Changeset 1338:f1b65381c1e7 in freeDiameter
- Timestamp:
- Apr 9, 2019, 10:48:45 PM (5 years ago)
- Branch:
- default
- Phase:
- public
- histedit_source:
- a96776a293770a9223f9cf06945dfdcf3844398a
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
doc/rt_ereg.conf.sample
r525 r1338 4 4 # The rt_ereg extension allows creation of routing rules based on AVP value matching regular expressions. 5 5 6 # This extension supports configuration reload at runtime. Send 7 # signal SIGUSR1 to the process to cause the process to reload its 8 # config. 9 6 10 # First, one must indicate which AVP should be used for matching. 7 11 # At the moment, only AVP with OCTETSTRING types are valid. 8 12 # AVP = "User-Name"; 13 # It is possible to specify AVPs below GROUPED AVPs with the by separating AVPs with a colon (':'): 14 # AVP = "Grouped-AVP1" : "Grouped-AVP2" : "Octetstring-AVP"; 9 15 # This parameter is mandatory. There is no default value. 10 16 … … 20 26 # (reminder: the server with the peer with the highest score gets the message) 21 27 # Note that all rules are tested for each message that contain the AVP, not only the first match. 28 29 # There can be multiple blocks of AVPs and rules; just start the next one with another AVP line: 30 # AVP = "Other-AVP"; 31 # and continue with rules as above. -
extensions/rt_ereg/rtereg.c
r1216 r1338 34 34 *********************************************************************************************************/ 35 35 36 /* 36 /* 37 37 * This extension allows to perform some pattern-matching on an AVP 38 38 * and send the message to a server accordingly. … … 40 40 */ 41 41 42 #include <pthread.h> 43 #include <signal.h> 44 42 45 #include "rtereg.h" 43 46 47 static pthread_rwlock_t rte_lock; 48 49 #define MODULE_NAME "rt_ereg" 50 51 static char *rt_ereg_config_file; 52 44 53 /* The configuration structure */ 45 struct rtereg_conf rtereg_conf; 54 struct rtereg_conf *rtereg_conf; 55 int rtereg_conf_size; 46 56 47 57 #ifndef HAVE_REG_STARTEND … … 51 61 #endif /* HAVE_REG_STARTEND */ 52 62 53 static int proceed(char * value, size_t len, struct fd_list * candidates) 63 static int rtereg_init(void); 64 static int rtereg_init_config(void); 65 static void rtereg_fini(void); 66 67 void rtereg_conf_free(struct rtereg_conf *config_struct, int config_size) 68 { 69 int i, j; 70 71 /* Destroy the data */ 72 for (j=0; j<config_size; j++) { 73 if (config_struct[j].rules) { 74 for (i = 0; i < config_struct[j].rules_nb; i++) { 75 free(config_struct[j].rules[i].pattern); 76 free(config_struct[j].rules[i].server); 77 regfree(&config_struct[j].rules[i].preg); 78 } 79 } 80 free(config_struct[j].avps); 81 free(config_struct[j].rules); 82 } 83 free(config_struct); 84 } 85 86 static int proceed(char * value, size_t len, struct fd_list * candidates, int conf) 54 87 { 55 88 int i; 56 57 for (i = 0; i < rtereg_conf .rules_nb; i++) {89 90 for (i = 0; i < rtereg_conf[conf].rules_nb; i++) { 58 91 /* Does this pattern match the value? */ 59 struct rtereg_rule * r = &rtereg_conf .rules[i];92 struct rtereg_rule * r = &rtereg_conf[conf].rules[i]; 60 93 int err = 0; 61 94 struct fd_list * c; 62 95 63 96 TRACE_DEBUG(ANNOYING, "Attempt pattern matching of '%.*s' with rule '%s'", (int)len, value, r->pattern); 64 97 65 98 #ifdef HAVE_REG_STARTEND 66 99 { … … 77 110 } 78 111 #endif /* HAVE_REG_STARTEND */ 79 112 80 113 if (err == REG_NOMATCH) 81 114 continue; 82 115 83 116 if (err != 0) { 84 117 char * errstr; … … 100 133 /* Free the buffer, return the error */ 101 134 free(errstr); 102 135 103 136 return (err == REG_ESPACE) ? ENOMEM : EINVAL; 104 137 } 105 138 106 139 /* From this point, the expression matched the AVP value */ 107 140 TRACE_DEBUG(FULL, "[rt_ereg] Match: '%s' to value '%.*s' => '%s' += %d", … … 111 144 r->server, 112 145 r->score); 113 146 114 147 for (c = candidates->next; c != candidates; c = c->next) { 115 148 struct rtd_candidate * cand = (struct rtd_candidate *)c; … … 121 154 } 122 155 }; 123 156 157 return 0; 158 } 159 160 static int find_avp(msg_or_avp *where, int conf_index, int level, struct fd_list * candidates) 161 { 162 struct dict_object *what; 163 struct dict_avp_data dictdata; 164 struct avp *nextavp = NULL; 165 struct avp_hdr *avp_hdr = NULL; 166 167 /* iterate over all AVPs and try to find a match */ 168 // for (i = 0; i<rtereg_conf[j].level; i++) { 169 if (level > rtereg_conf[conf_index].level) { 170 TRACE_DEBUG(INFO, "internal error, dug too deep"); 171 return 1; 172 } 173 what = rtereg_conf[conf_index].avps[level]; 174 175 CHECK_FCT(fd_dict_getval(what, &dictdata)); 176 CHECK_FCT(fd_msg_browse(where, MSG_BRW_FIRST_CHILD, (void *)&nextavp, NULL)); 177 while (nextavp) { 178 CHECK_FCT(fd_msg_avp_hdr(nextavp, &avp_hdr)); 179 if ((avp_hdr->avp_code == dictdata.avp_code) && (avp_hdr->avp_vendor == dictdata.avp_vendor)) { 180 if (level != rtereg_conf[conf_index].level - 1) { 181 TRACE_DEBUG(INFO, "[rt_ereg] found grouped AVP %d (vendor %d), digging deeper", avp_hdr->avp_code, avp_hdr->avp_vendor); 182 CHECK_FCT(find_avp(nextavp, conf_index, level+1, candidates)); 183 } else { 184 TRACE_DEBUG(INFO, "[rt_ereg] found AVP %d (vendor %d)", avp_hdr->avp_code, avp_hdr->avp_vendor); 185 if (avp_hdr->avp_value != NULL) { 186 #ifndef HAVE_REG_STARTEND 187 int ret; 188 189 /* Lock the buffer */ 190 CHECK_POSIX( pthread_mutex_lock(&mtx) ); 191 192 /* Augment the buffer if needed */ 193 if (avp_hdr->avp_value->os.len >= bufsz) { 194 CHECK_MALLOC_DO( buf = realloc(buf, avp_hdr->avp_value->os.len + 1), 195 { pthread_mutex_unlock(&mtx); return ENOMEM; } ); 196 } 197 198 /* Copy the AVP value */ 199 memcpy(buf, avp_hdr->avp_value->os.data, avp_hdr->avp_value->os.len); 200 buf[avp_hdr->avp_value->os.len] = '\0'; 201 202 /* Now apply the rules */ 203 ret = proceed(buf, avp_hdr->avp_value->os.len, candidates, conf_index); 204 205 CHECK_POSIX(pthread_mutex_unlock(&mtx)); 206 207 CHECK_FCT(ret); 208 #else /* HAVE_REG_STARTEND */ 209 CHECK_FCT( proceed((char *) avp_hdr->avp_value->os.data, avp_hdr->avp_value->os.len, candidates, conf_index) ); 210 #endif /* HAVE_REG_STARTEND */ 211 } 212 } 213 } 214 CHECK_FCT(fd_msg_browse(nextavp, MSG_BRW_NEXT, (void *)&nextavp, NULL)); 215 } 216 124 217 return 0; 125 218 } … … 128 221 static int rtereg_out(void * cbdata, struct msg ** pmsg, struct fd_list * candidates) 129 222 { 130 struct msg * msg = *pmsg; 131 struct avp * avp = NULL; 132 133 TRACE_ENTRY("%p %p %p", cbdata, msg, candidates); 134 135 CHECK_PARAMS(msg && candidates); 136 223 msg_or_avp *where; 224 int j, ret; 225 226 TRACE_ENTRY("%p %p %p", cbdata, *pmsg, candidates); 227 228 CHECK_PARAMS(pmsg && *pmsg && candidates); 229 230 if (pthread_rwlock_rdlock(&rte_lock) != 0) { 231 fd_log_notice("%s: read-lock failed, skipping handler", MODULE_NAME); 232 return 0; 233 } 234 ret = 0; 137 235 /* Check if it is worth processing the message */ 138 if (FD_IS_LIST_EMPTY(candidates)) { 139 return 0; 140 } 141 142 /* Now search the AVP in the message */ 143 CHECK_FCT( fd_msg_search_avp ( msg, rtereg_conf.avp, &avp ) ); 144 if (avp != NULL) { 145 struct avp_hdr * ahdr = NULL; 146 CHECK_FCT( fd_msg_avp_hdr ( avp, &ahdr ) ); 147 if (ahdr->avp_value != NULL) { 148 #ifndef HAVE_REG_STARTEND 149 int ret; 150 151 /* Lock the buffer */ 152 CHECK_POSIX( pthread_mutex_lock(&mtx) ); 153 154 /* Augment the buffer if needed */ 155 if (ahdr->avp_value->os.len >= bufsz) { 156 CHECK_MALLOC_DO( buf = realloc(buf, ahdr->avp_value->os.len + 1), 157 { pthread_mutex_unlock(&mtx); return ENOMEM; } ); 236 if (!FD_IS_LIST_EMPTY(candidates)) { 237 /* Now search the AVPs in the message */ 238 239 for (j=0; j<rtereg_conf_size; j++) { 240 where = *pmsg; 241 TRACE_DEBUG(INFO, "[rt_ereg] iterating over AVP group %d", j); 242 if ((ret=find_avp(where, j, 0, candidates)) != 0) { 243 break; 158 244 } 159 160 /* Copy the AVP value */ 161 memcpy(buf, ahdr->avp_value->os.data, ahdr->avp_value->os.len); 162 buf[ahdr->avp_value->os.len] = '\0'; 163 164 /* Now apply the rules */ 165 ret = proceed(buf, ahdr->avp_value->os.len, candidates); 166 167 CHECK_POSIX(pthread_mutex_unlock(&mtx)); 168 169 CHECK_FCT(ret); 170 #else /* HAVE_REG_STARTEND */ 171 CHECK_FCT( proceed((char *) ahdr->avp_value->os.data, ahdr->avp_value->os.len, candidates) ); 172 #endif /* HAVE_REG_STARTEND */ 173 } 174 } 175 176 return 0; 245 } 246 } 247 if (pthread_rwlock_unlock(&rte_lock) != 0) { 248 fd_log_notice("%s: read-unlock failed after rtereg_out, exiting", MODULE_NAME); 249 exit(1); 250 } 251 252 return ret; 177 253 } 178 254 … … 180 256 static struct fd_rt_out_hdl * rtereg_hdl = NULL; 181 257 258 static volatile int in_signal_handler = 0; 259 260 /* signal handler */ 261 static void sig_hdlr(void) 262 { 263 struct rtereg_conf *old_config; 264 int old_config_size; 265 266 if (in_signal_handler) { 267 fd_log_error("%s: already handling a signal, ignoring new one", MODULE_NAME); 268 return; 269 } 270 in_signal_handler = 1; 271 272 if (pthread_rwlock_wrlock(&rte_lock) != 0) { 273 fd_log_error("%s: locking failed, aborting config reload", MODULE_NAME); 274 return; 275 } 276 277 /* save old config in case reload goes wrong */ 278 old_config = rtereg_conf; 279 old_config_size = rtereg_conf_size; 280 rtereg_conf = NULL; 281 rtereg_conf_size = 0; 282 283 if (rtereg_init_config() != 0) { 284 fd_log_notice("%s: error reloading configuration, restoring previous configuration", MODULE_NAME); 285 rtereg_conf = old_config; 286 rtereg_conf_size = old_config_size; 287 } else { 288 rtereg_conf_free(old_config, old_config_size); 289 } 290 291 if (pthread_rwlock_unlock(&rte_lock) != 0) { 292 fd_log_error("%s: unlocking failed after config reload, exiting", MODULE_NAME); 293 exit(1); 294 } 295 296 fd_log_notice("%s: reloaded configuration, %d AVP group%s defined", MODULE_NAME, rtereg_conf_size, rtereg_conf_size != 1 ? "s" : ""); 297 298 in_signal_handler = 0; 299 } 300 182 301 /* entry point */ 183 302 static int rtereg_entry(char * conffile) 184 303 { 185 304 TRACE_ENTRY("%p", conffile); 186 305 306 rt_ereg_config_file = conffile; 307 308 if (rtereg_init() != 0) { 309 return 1; 310 } 311 312 /* Register reload callback */ 313 CHECK_FCT(fd_event_trig_regcb(SIGUSR1, MODULE_NAME, sig_hdlr)); 314 315 fd_log_notice("%s: configured, %d AVP group%s defined", MODULE_NAME, rtereg_conf_size, rtereg_conf_size != 1 ? "s" : ""); 316 317 return 0; 318 } 319 320 static int rtereg_init_config(void) 321 { 187 322 /* Initialize the configuration */ 188 memset(&rtereg_conf, 0, sizeof(rtereg_conf)); 189 323 if ((rtereg_conf=malloc(sizeof(*rtereg_conf))) == NULL) { 324 TRACE_DEBUG(INFO, "malloc failured"); 325 return 1; 326 } 327 rtereg_conf_size = 1; 328 memset(rtereg_conf, 0, sizeof(*rtereg_conf)); 329 190 330 /* Parse the configuration file */ 191 CHECK_FCT( rtereg_conf_handle(conffile) ); 192 331 CHECK_FCT( rtereg_conf_handle(rt_ereg_config_file) ); 332 333 return 0; 334 } 335 336 337 /* Load */ 338 static int rtereg_init(void) 339 { 340 int ret; 341 342 pthread_rwlock_init(&rte_lock, NULL); 343 344 if (pthread_rwlock_wrlock(&rte_lock) != 0) { 345 fd_log_notice("%s: write-lock failed, aborting", MODULE_NAME); 346 return EDEADLK; 347 } 348 349 if ((ret=rtereg_init_config()) != 0) { 350 pthread_rwlock_unlock(&rte_lock); 351 return ret; 352 } 353 354 if (pthread_rwlock_unlock(&rte_lock) != 0) { 355 fd_log_notice("%s: write-unlock failed, aborting", MODULE_NAME); 356 return EDEADLK; 357 } 358 193 359 /* Register the callback */ 194 360 CHECK_FCT( fd_rt_out_register( rtereg_out, NULL, 1, &rtereg_hdl ) ); 195 361 196 362 /* We're done */ 197 363 return 0; … … 199 365 200 366 /* Unload */ 201 void fd_ext_fini(void) 202 { 203 int i; 367 static void rtereg_fini(void) 368 { 204 369 TRACE_ENTRY(); 205 370 206 371 /* Unregister the cb */ 207 372 CHECK_FCT_DO( fd_rt_out_unregister ( rtereg_hdl, NULL ), /* continue */ ); 208 373 209 374 /* Destroy the data */ 210 if (rtereg_conf.rules) 211 for (i = 0; i < rtereg_conf.rules_nb; i++) { 212 free(rtereg_conf.rules[i].pattern); 213 free(rtereg_conf.rules[i].server); 214 regfree(&rtereg_conf.rules[i].preg); 215 } 216 free(rtereg_conf.rules); 375 rtereg_conf_free(rtereg_conf, rtereg_conf_size); 376 rtereg_conf = NULL; 377 rtereg_conf_size = 0; 217 378 #ifndef HAVE_REG_STARTEND 218 379 free(buf); 380 buf = NULL; 219 381 #endif /* HAVE_REG_STARTEND */ 220 382 221 383 /* Done */ 222 384 return ; 223 385 } 224 386 225 EXTENSION_ENTRY("rt_ereg", rtereg_entry); 387 void fd_ext_fini(void) 388 { 389 rtereg_fini(); 390 } 391 392 EXTENSION_ENTRY(MODULE_NAME, rtereg_entry); -
extensions/rt_ereg/rtereg.h
r741 r1338 58 58 int rules_nb; /* Number of rules in the configuration */ 59 59 struct rtereg_rule *rules; /* The array of rules */ 60 61 int level; /* how many levels of AVPs we have to dig down into */ 62 int finished; /* AVP fully configured, for configuration file reading */ 63 struct dict_object **avps; /* cache the dictionary objects that we are searching */ 60 64 61 struct dict_object * avp; /* cache the dictionary object that we are searching */ 62 63 } rtereg_conf; 65 } *rtereg_conf; 64 66 67 extern int rtereg_conf_size; -
extensions/rt_ereg/rtereg_conf.y
r1127 r1338 38 38 39 39 /* For development only : */ 40 %debug 40 %debug 41 41 %error-verbose 42 42 … … 45 45 46 46 /* Keep track of location */ 47 %locations 47 %locations 48 48 %pure-parser 49 49 … … 54 54 /* Forward declaration */ 55 55 int yyparse(char * conffile); 56 void rtereg_confrestart(FILE *input_file); 56 57 57 58 /* Parse the configuration file */ … … 60 61 extern FILE * rtereg_confin; 61 62 int ret; 62 63 63 64 TRACE_ENTRY("%p", conffile); 64 65 65 66 TRACE_DEBUG (FULL, "Parsing configuration file: %s...", conffile); 66 67 67 68 rtereg_confin = fopen(conffile, "r"); 68 69 if (rtereg_confin == NULL) { 69 70 ret = errno; 70 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 73 return ret; 73 74 } 74 75 76 rtereg_confrestart(rtereg_confin); 75 77 ret = yyparse(conffile); 76 78 77 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 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 88 return EINVAL; 82 89 } else { 83 TRACE_DEBUG(FULL, "[rt-ereg] Added %d rules successfully.", rtereg_conf.rules_nb); 84 } 85 90 int i, sum = 0; 91 for (i=0; i<rtereg_conf_size; i++) { 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 141 return 0; 87 142 } … … 93 148 void yyerror (YYLTYPE *ploc, char * conffile, char const *s) 94 149 { 95 TRACE_DEBUG(INFO, " Error in configuration parsing");96 150 TRACE_DEBUG(INFO, "rt_ereg: error in configuration parsing"); 151 97 152 if (ploc->first_line != ploc->last_line) 98 153 fd_log_debug("%s:%d.%d-%d.%d : %s", conffile, ploc->first_line, ploc->first_column, ploc->last_line, ploc->last_column, s); … … 126 181 127 182 /* The grammar definition */ 128 conffile: rules avp rules 129 ; 130 183 conffile: avp rules 184 | conffile avp rules 185 ; 186 131 187 /* a server entry */ 132 avp: AVP '=' QSTRING ';' 133 { 134 if (rtereg_conf.avp != NULL) { 135 yyerror(&yylloc, conffile, "Only one AVP can be specified"); 136 YYERROR; 137 } 138 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 188 avp: AVP '=' avp_part ';' 189 ; 190 191 avp_part: avp_part ':' QSTRING { if (avp_add($3) < 0) { YYERROR; } } 192 | QSTRING { if (avp_add($1) < 0) { YYERROR; } } 193 ; 194 160 195 rules: /* empty OK */ 161 196 | rules rule 162 197 ; 163 198 164 199 rule: QSTRING ':' QSTRING '+' '=' INTEGER ';' 165 200 { 166 201 struct rtereg_rule * new; 167 202 int err; 168 203 169 204 /* Add new rule in the array */ 170 rtereg_conf .rules_nb += 1;171 CHECK_MALLOC_DO(rtereg_conf .rules = realloc(rtereg_conf.rules, rtereg_conf.rules_nb * sizeof(struct rtereg_rule)),205 rtereg_conf[rtereg_conf_size-1].rules_nb += 1; 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 208 yyerror (&yylloc, conffile, "Not enough memory to store the configuration..."); 174 209 YYERROR; 175 210 } ); 176 177 new = &rtereg_conf .rules[rtereg_conf.rules_nb - 1];178 211 212 new = &rtereg_conf[rtereg_conf_size-1].rules[rtereg_conf[rtereg_conf_size-1].rules_nb - 1]; 213 179 214 new->pattern = $1; 180 215 new->server = $3; 181 216 new->score = $6; 182 217 183 218 /* Attempt to compile the regex */ 184 219 CHECK_FCT_DO( err=regcomp(&new->preg, new->pattern, REG_EXTENDED | REG_NOSUB), … … 188 223 189 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 227 /* Get the error message size */ … … 199 234 regerror(err, &new->preg, buf, bl); 200 235 TRACE_DEBUG(INFO, "\t%s", buf); 201 236 202 237 /* Free the buffer, return the error */ 203 238 free(buf); 204 239 205 240 yyerror (&yylloc, conffile, "Invalid regular expression."); 206 241 YYERROR;
Note: See TracChangeset
for help on using the changeset viewer.