Changeset 1338:f1b65381c1e7 in freeDiameter for extensions/rt_ereg/rtereg.c
- Timestamp:
- Apr 9, 2019, 10:48:45 PM (5 years ago)
- Branch:
- default
- Phase:
- public
- histedit_source:
- a96776a293770a9223f9cf06945dfdcf3844398a
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
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);
Note: See TracChangeset
for help on using the changeset viewer.