comparison extensions/rt_ereg/rtereg_conf.y @ 1338:f1b65381c1e7

rt_ereg: Support config reload. Support grouped AVPs. Support multiple separate AVPs. Written for Effortel Technologies SA, published with their consent.
author Thomas Klausner <tk@giga.or.at>
date Tue, 09 Apr 2019 15:48:45 +0200
parents 1af09cc156d6
children fedc9eea70bc
comparison
equal deleted inserted replaced
1337:d66f60e29b22 1338:f1b65381c1e7
35 35
36 /* Yacc extension's configuration parser. 36 /* Yacc extension's configuration parser.
37 */ 37 */
38 38
39 /* For development only : */ 39 /* For development only : */
40 %debug 40 %debug
41 %error-verbose 41 %error-verbose
42 42
43 /* The parser receives the configuration file filename as parameter */ 43 /* The parser receives the configuration file filename as parameter */
44 %parse-param {char * conffile} 44 %parse-param {char * conffile}
45 45
46 /* Keep track of location */ 46 /* Keep track of location */
47 %locations 47 %locations
48 %pure-parser 48 %pure-parser
49 49
50 %{ 50 %{
51 #include "rtereg.h" 51 #include "rtereg.h"
52 #include "rtereg_conf.tab.h" /* bison is not smart enough to define the YYLTYPE before including this code, so... */ 52 #include "rtereg_conf.tab.h" /* bison is not smart enough to define the YYLTYPE before including this code, so... */
53 53
54 /* Forward declaration */ 54 /* Forward declaration */
55 int yyparse(char * conffile); 55 int yyparse(char * conffile);
56 void rtereg_confrestart(FILE *input_file);
56 57
57 /* Parse the configuration file */ 58 /* Parse the configuration file */
58 int rtereg_conf_handle(char * conffile) 59 int rtereg_conf_handle(char * conffile)
59 { 60 {
60 extern FILE * rtereg_confin; 61 extern FILE * rtereg_confin;
61 int ret; 62 int ret;
62 63
63 TRACE_ENTRY("%p", conffile); 64 TRACE_ENTRY("%p", conffile);
64 65
65 TRACE_DEBUG (FULL, "Parsing configuration file: %s...", conffile); 66 TRACE_DEBUG (FULL, "Parsing configuration file: %s...", conffile);
66 67
67 rtereg_confin = fopen(conffile, "r"); 68 rtereg_confin = fopen(conffile, "r");
68 if (rtereg_confin == NULL) { 69 if (rtereg_confin == NULL) {
69 ret = errno; 70 ret = errno;
70 fd_log_debug("Unable to open extension configuration file %s for reading: %s", conffile, strerror(ret)); 71 fd_log_debug("Unable to open extension configuration file %s for reading: %s", conffile, strerror(ret));
71 TRACE_DEBUG (INFO, "Error occurred, message logged -- configuration file."); 72 TRACE_DEBUG (INFO, "rt_ereg: error occurred, message logged -- configuration file.");
72 return ret; 73 return ret;
73 } 74 }
74 75
76 rtereg_confrestart(rtereg_confin);
75 ret = yyparse(conffile); 77 ret = yyparse(conffile);
76 78
77 fclose(rtereg_confin); 79 fclose(rtereg_confin);
78 80
81 if (rtereg_conf[rtereg_conf_size-1].finished == 0) {
82 TRACE_DEBUG(INFO, "rt_ereg: configuration invalid, AVP ended without OCTETSTRING AVP");
83 return EINVAL;
84 }
85
79 if (ret != 0) { 86 if (ret != 0) {
80 TRACE_DEBUG (INFO, "Unable to parse the configuration file."); 87 TRACE_DEBUG(INFO, "rt_ereg: unable to parse the configuration file.");
81 return EINVAL; 88 return EINVAL;
82 } else { 89 } else {
83 TRACE_DEBUG(FULL, "[rt-ereg] Added %d rules successfully.", rtereg_conf.rules_nb); 90 int i, sum = 0;
84 } 91 for (i=0; i<rtereg_conf_size; i++) {
85 92 sum += rtereg_conf[i].rules_nb;
93 }
94 TRACE_DEBUG(FULL, "[rt-ereg] Added %d rules successfully.", sum);
95 }
96
97 return 0;
98 }
99
100 int avp_add(const char *name)
101 {
102 void *ret;
103 int level;
104
105 if (rtereg_conf[rtereg_conf_size-1].finished) {
106 if ((ret = realloc(rtereg_conf, sizeof(*rtereg_conf)*(rtereg_conf_size+1))) == NULL) {
107 TRACE_DEBUG(INFO, "rt_ereg: realloc failed");
108 return -1;
109 }
110 rtereg_conf_size++;
111 rtereg_conf = ret;
112 memset(&rtereg_conf[rtereg_conf_size-1], 0, sizeof(*rtereg_conf));
113 TRACE_DEBUG(INFO, "rt_ereg: New AVP group found starting with %s", name);
114 }
115 level = rtereg_conf[rtereg_conf_size-1].level + 1;
116
117 if ((ret = realloc(rtereg_conf[rtereg_conf_size-1].avps, sizeof(*rtereg_conf[rtereg_conf_size-1].avps)*level)) == NULL) {
118 TRACE_DEBUG(INFO, "rt_ereg: realloc failed");
119 return -1;
120 }
121 rtereg_conf[rtereg_conf_size-1].avps = ret;
122
123 CHECK_FCT_DO( fd_dict_search ( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, name, &rtereg_conf[rtereg_conf_size-1].avps[level-1], ENOENT ),
124 {
125 TRACE_DEBUG(INFO, "rt_ereg: Unable to find '%s' AVP in the loaded dictionaries.", name);
126 return -1;
127 } );
128
129 /* Now check the type */
130 {
131 struct dict_avp_data data;
132 CHECK_FCT( fd_dict_getval( rtereg_conf[rtereg_conf_size-1].avps[level-1], &data) );
133 if (data.avp_basetype == AVP_TYPE_OCTETSTRING) {
134 rtereg_conf[rtereg_conf_size-1].finished = 1;
135 } else if (data.avp_basetype != AVP_TYPE_GROUPED) {
136 TRACE_DEBUG(INFO, "rt_ereg: '%s' AVP is not an OCTETSTRING nor GROUPED AVP (%d).", name, data.avp_basetype);
137 return -1;
138 }
139 }
140 rtereg_conf[rtereg_conf_size-1].level = level;
86 return 0; 141 return 0;
87 } 142 }
88 143
89 /* The Lex parser prototype */ 144 /* The Lex parser prototype */
90 int rtereg_conflex(YYSTYPE *lvalp, YYLTYPE *llocp); 145 int rtereg_conflex(YYSTYPE *lvalp, YYLTYPE *llocp);
91 146
92 /* Function to report the errors */ 147 /* Function to report the errors */
93 void yyerror (YYLTYPE *ploc, char * conffile, char const *s) 148 void yyerror (YYLTYPE *ploc, char * conffile, char const *s)
94 { 149 {
95 TRACE_DEBUG(INFO, "Error in configuration parsing"); 150 TRACE_DEBUG(INFO, "rt_ereg: error in configuration parsing");
96 151
97 if (ploc->first_line != ploc->last_line) 152 if (ploc->first_line != ploc->last_line)
98 fd_log_debug("%s:%d.%d-%d.%d : %s", conffile, ploc->first_line, ploc->first_column, ploc->last_line, ploc->last_column, s); 153 fd_log_debug("%s:%d.%d-%d.%d : %s", conffile, ploc->first_line, ploc->first_column, ploc->last_line, ploc->last_column, s);
99 else if (ploc->first_column != ploc->last_column) 154 else if (ploc->first_column != ploc->last_column)
100 fd_log_debug("%s:%d.%d-%d : %s", conffile, ploc->first_line, ploc->first_column, ploc->last_column, s); 155 fd_log_debug("%s:%d.%d-%d : %s", conffile, ploc->first_line, ploc->first_column, ploc->last_column, s);
101 else 156 else
123 178
124 /* -------------------------------------- */ 179 /* -------------------------------------- */
125 %% 180 %%
126 181
127 /* The grammar definition */ 182 /* The grammar definition */
128 conffile: rules avp rules 183 conffile: avp rules
129 ; 184 | conffile avp rules
130 185 ;
186
131 /* a server entry */ 187 /* a server entry */
132 avp: AVP '=' QSTRING ';' 188 avp: AVP '=' avp_part ';'
133 { 189 ;
134 if (rtereg_conf.avp != NULL) { 190
135 yyerror(&yylloc, conffile, "Only one AVP can be specified"); 191 avp_part: avp_part ':' QSTRING { if (avp_add($3) < 0) { YYERROR; } }
136 YYERROR; 192 | QSTRING { if (avp_add($1) < 0) { YYERROR; } }
137 } 193 ;
138 194
139 CHECK_FCT_DO( fd_dict_search ( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, $3, &rtereg_conf.avp, ENOENT ),
140 {
141 TRACE_DEBUG(INFO, "Unable to find '%s' AVP in the loaded dictionaries.", $3);
142 yyerror (&yylloc, conffile, "Invalid AVP value.");
143 YYERROR;
144 } );
145
146 /* Now check the type */
147 {
148 struct dict_avp_data data;
149 CHECK_FCT( fd_dict_getval( rtereg_conf.avp, &data) );
150 CHECK_PARAMS_DO (data.avp_basetype == AVP_TYPE_OCTETSTRING,
151 {
152 TRACE_DEBUG(INFO, "'%s' AVP in not an OCTETSTRING AVP (%d).", $3, data.avp_basetype);
153 yyerror (&yylloc, conffile, "AVP in not an OCTETSTRING type.");
154 YYERROR;
155 } );
156 }
157 }
158 ;
159
160 rules: /* empty OK */ 195 rules: /* empty OK */
161 | rules rule 196 | rules rule
162 ; 197 ;
163 198
164 rule: QSTRING ':' QSTRING '+' '=' INTEGER ';' 199 rule: QSTRING ':' QSTRING '+' '=' INTEGER ';'
165 { 200 {
166 struct rtereg_rule * new; 201 struct rtereg_rule * new;
167 int err; 202 int err;
168 203
169 /* Add new rule in the array */ 204 /* Add new rule in the array */
170 rtereg_conf.rules_nb += 1; 205 rtereg_conf[rtereg_conf_size-1].rules_nb += 1;
171 CHECK_MALLOC_DO(rtereg_conf.rules = realloc(rtereg_conf.rules, rtereg_conf.rules_nb * sizeof(struct rtereg_rule)), 206 CHECK_MALLOC_DO(rtereg_conf[rtereg_conf_size-1].rules = realloc(rtereg_conf[rtereg_conf_size-1].rules, rtereg_conf[rtereg_conf_size-1].rules_nb * sizeof(struct rtereg_rule)),
172 { 207 {
173 yyerror (&yylloc, conffile, "Not enough memory to store the configuration..."); 208 yyerror (&yylloc, conffile, "Not enough memory to store the configuration...");
174 YYERROR; 209 YYERROR;
175 } ); 210 } );
176 211
177 new = &rtereg_conf.rules[rtereg_conf.rules_nb - 1]; 212 new = &rtereg_conf[rtereg_conf_size-1].rules[rtereg_conf[rtereg_conf_size-1].rules_nb - 1];
178 213
179 new->pattern = $1; 214 new->pattern = $1;
180 new->server = $3; 215 new->server = $3;
181 new->score = $6; 216 new->score = $6;
182 217
183 /* Attempt to compile the regex */ 218 /* Attempt to compile the regex */
184 CHECK_FCT_DO( err=regcomp(&new->preg, new->pattern, REG_EXTENDED | REG_NOSUB), 219 CHECK_FCT_DO( err=regcomp(&new->preg, new->pattern, REG_EXTENDED | REG_NOSUB),
185 { 220 {
186 char * buf; 221 char * buf;
187 size_t bl; 222 size_t bl;
188 223
189 /* Error while compiling the regex */ 224 /* Error while compiling the regex */
190 TRACE_DEBUG(INFO, "Error while compiling the regular expression '%s':", new->pattern); 225 TRACE_DEBUG(INFO, "rt_ereg: error while compiling the regular expression '%s':", new->pattern);
191 226
192 /* Get the error message size */ 227 /* Get the error message size */
193 bl = regerror(err, &new->preg, NULL, 0); 228 bl = regerror(err, &new->preg, NULL, 0);
194 229
195 /* Alloc the buffer for error message */ 230 /* Alloc the buffer for error message */
196 CHECK_MALLOC( buf = malloc(bl) ); 231 CHECK_MALLOC( buf = malloc(bl) );
197 232
198 /* Get the error message content */ 233 /* Get the error message content */
199 regerror(err, &new->preg, buf, bl); 234 regerror(err, &new->preg, buf, bl);
200 TRACE_DEBUG(INFO, "\t%s", buf); 235 TRACE_DEBUG(INFO, "\t%s", buf);
201 236
202 /* Free the buffer, return the error */ 237 /* Free the buffer, return the error */
203 free(buf); 238 free(buf);
204 239
205 yyerror (&yylloc, conffile, "Invalid regular expression."); 240 yyerror (&yylloc, conffile, "Invalid regular expression.");
206 YYERROR; 241 YYERROR;
207 } ); 242 } );
208 } 243 }
209 ; 244 ;
"Welcome to our mercurial repository"