Changes in / [1257:55d0867dd8b8:1263:285287f22041] in freeDiameter
- Files:
-
- 1 added
- 10 edited
Legend:
- Unmodified
- Added
- Removed
-
extensions/dict_dcca_3gpp/dict_dcca_3gpp.c
r1231 r1262 10387 10387 struct dict_avp_request vpa; 10388 10388 vpa.avp_vendor = 10415; 10389 vpa.avp_name = "Address-Domain"; 10390 CHECK_dict_search(DICT_AVP, AVP_BY_NAME_AND_VENDOR, &vpa, &rule_avp); 10391 struct local_rules_definition rules[] = 10392 { 10393 { { .avp_vendor = 10415, .avp_name = "Domain-Name" }, RULE_OPTIONAL, -1, 1 }, 10394 { { .avp_vendor = 10415, .avp_name = "3GPP-IMSI-MCC-MNC" }, RULE_OPTIONAL, -1, 1 }, 10395 }; 10396 PARSE_loc_rules(rules, rule_avp); 10397 } 10398 10399 { 10400 struct dict_object *rule_avp; 10401 struct dict_avp_request vpa; 10402 vpa.avp_vendor = 10415; 10389 10403 vpa.avp_name = "Application-Server-Information"; 10390 10404 CHECK_dict_search(DICT_AVP, AVP_BY_NAME_AND_VENDOR, &vpa, &rule_avp); … … 10393 10407 { { .avp_vendor = 10415, .avp_name = "Application-Server" }, RULE_REQUIRED, -1, 1 }, 10394 10408 { { .avp_vendor = 10415, .avp_name = "Application-Provided-Called-Party-Address" }, RULE_OPTIONAL, -1, -1 }, 10409 }; 10410 PARSE_loc_rules(rules, rule_avp); 10411 } 10412 10413 { 10414 struct dict_object *rule_avp; 10415 struct dict_avp_request vpa; 10416 vpa.avp_vendor = 10415; 10417 vpa.avp_name = "Destination-Interface"; 10418 CHECK_dict_search(DICT_AVP, AVP_BY_NAME_AND_VENDOR, &vpa, &rule_avp); 10419 struct local_rules_definition rules[] = 10420 { 10421 { { .avp_vendor = 10415, .avp_name = "Interface-Id" }, RULE_OPTIONAL, -1, 1 }, 10422 { { .avp_vendor = 10415, .avp_name = "Interface-Text" }, RULE_OPTIONAL, -1, 1 }, 10423 { { .avp_vendor = 10415, .avp_name = "Interface-Port" }, RULE_OPTIONAL, -1, 1 }, 10424 { { .avp_vendor = 10415, .avp_name = "Interface-Type" }, RULE_OPTIONAL, -1, 1 }, 10395 10425 }; 10396 10426 PARSE_loc_rules(rules, rule_avp); … … 10487 10517 struct dict_avp_request vpa; 10488 10518 vpa.avp_vendor = 10415; 10519 vpa.avp_name = "Message-Class"; 10520 CHECK_dict_search(DICT_AVP, AVP_BY_NAME_AND_VENDOR, &vpa, &rule_avp); 10521 struct local_rules_definition rules[] = 10522 { 10523 { { .avp_vendor = 10415, .avp_name = "Class-Identifier" }, RULE_OPTIONAL, -1, 1 }, 10524 { { .avp_vendor = 10415, .avp_name = "Token-Text" }, RULE_OPTIONAL, -1, 1 }, 10525 }; 10526 PARSE_loc_rules(rules, rule_avp); 10527 } 10528 10529 { 10530 struct dict_object *rule_avp; 10531 struct dict_avp_request vpa; 10532 vpa.avp_vendor = 10415; 10489 10533 vpa.avp_name = "MMS-Information"; 10490 10534 CHECK_dict_search(DICT_AVP, AVP_BY_NAME_AND_VENDOR, &vpa, &rule_avp); … … 10545 10589 10546 10590 { 10547 /* Used-Service-Unit */10548 /* additional allowed AVPs */10549 struct dict_object *rule_avp;10550 struct dict_avp_request vpa;10551 vpa.avp_vendor = 0;10552 vpa.avp_name = "Used-Service-Unit";10553 CHECK_dict_search(DICT_AVP, AVP_BY_NAME_AND_VENDOR, &vpa, &rule_avp);10554 struct local_rules_definition rules[] =10555 {10556 { { .avp_vendor = 10415, .avp_name = "Reporting-Reason" }, RULE_OPTIONAL, -1, 1 },10557 { { .avp_vendor = 10415, .avp_name = "Event-Charging-TimeStamp" }, RULE_OPTIONAL, -1, -1 },10558 };10559 PARSE_loc_rules(rules, rule_avp);10560 }10561 10562 {10563 10591 struct dict_object *rule_avp; 10564 10592 struct dict_avp_request vpa; … … 10587 10615 { { .avp_vendor = 10415, .avp_name = "Address-Data" }, RULE_OPTIONAL, -1, 1 }, 10588 10616 { { .avp_vendor = 10415, .avp_name = "Address-Domain" }, RULE_OPTIONAL, -1, 1 }, 10617 }; 10618 PARSE_loc_rules(rules, rule_avp); 10619 } 10620 10621 { 10622 struct dict_object *rule_avp; 10623 struct dict_avp_request vpa; 10624 vpa.avp_vendor = 10415; 10625 vpa.avp_name = "Originator-Interface"; 10626 CHECK_dict_search(DICT_AVP, AVP_BY_NAME_AND_VENDOR, &vpa, &rule_avp); 10627 struct local_rules_definition rules[] = 10628 { 10629 { { .avp_vendor = 10415, .avp_name = "Interface-Id" }, RULE_OPTIONAL, -1, 1 }, 10630 { { .avp_vendor = 10415, .avp_name = "Interface-Text" }, RULE_OPTIONAL, -1, 1 }, 10631 { { .avp_vendor = 10415, .avp_name = "Interface-Port" }, RULE_OPTIONAL, -1, 1 }, 10632 { { .avp_vendor = 10415, .avp_name = "Interface-Type" }, RULE_OPTIONAL, -1, 1 }, 10589 10633 }; 10590 10634 PARSE_loc_rules(rules, rule_avp); … … 10684 10728 struct dict_avp_request vpa; 10685 10729 vpa.avp_vendor = 10415; 10730 vpa.avp_name = "Recipient-Info"; 10731 CHECK_dict_search(DICT_AVP, AVP_BY_NAME_AND_VENDOR, &vpa, &rule_avp); 10732 struct local_rules_definition rules[] = 10733 { 10734 { { .avp_vendor = 10415, .avp_name = "Destination-Interface" }, RULE_OPTIONAL, -1, 1 }, 10735 { { .avp_vendor = 10415, .avp_name = "Recipient-Address" }, RULE_OPTIONAL, -1, -1 }, 10736 { { .avp_vendor = 10415, .avp_name = "Recipient-Received-Address" }, RULE_OPTIONAL, -1, -1 }, 10737 { { .avp_vendor = 10415, .avp_name = "Recipient-SCCP-Address" }, RULE_OPTIONAL, -1, 1 }, 10738 { { .avp_vendor = 10415, .avp_name = "SM-Protocol-ID" }, RULE_OPTIONAL, -1, 1 }, 10739 }; 10740 PARSE_loc_rules(rules, rule_avp); 10741 } 10742 10743 { 10744 struct dict_object *rule_avp; 10745 struct dict_avp_request vpa; 10746 vpa.avp_vendor = 10415; 10747 vpa.avp_name = "Recipient-Received-Address"; 10748 CHECK_dict_search(DICT_AVP, AVP_BY_NAME_AND_VENDOR, &vpa, &rule_avp); 10749 struct local_rules_definition rules[] = 10750 { 10751 { { .avp_vendor = 10415, .avp_name = "Address-Type" }, RULE_OPTIONAL, -1, 1 }, 10752 { { .avp_vendor = 10415, .avp_name = "Address-Data" }, RULE_OPTIONAL, -1, 1 }, 10753 { { .avp_vendor = 10415, .avp_name = "Address-Domain" }, RULE_OPTIONAL, -1, 1 }, 10754 }; 10755 PARSE_loc_rules(rules, rule_avp); 10756 } 10757 10758 { 10759 struct dict_object *rule_avp; 10760 struct dict_avp_request vpa; 10761 vpa.avp_vendor = 10415; 10686 10762 vpa.avp_name = "SDP-Media-Component"; 10687 10763 CHECK_dict_search(DICT_AVP, AVP_BY_NAME_AND_VENDOR, &vpa, &rule_avp); … … 10786 10862 } 10787 10863 10864 { 10865 /* Used-Service-Unit */ 10866 /* additional allowed AVPs */ 10867 struct dict_object *rule_avp; 10868 struct dict_avp_request vpa; 10869 vpa.avp_vendor = 0; 10870 vpa.avp_name = "Used-Service-Unit"; 10871 CHECK_dict_search(DICT_AVP, AVP_BY_NAME_AND_VENDOR, &vpa, &rule_avp); 10872 struct local_rules_definition rules[] = 10873 { 10874 { { .avp_vendor = 10415, .avp_name = "Reporting-Reason" }, RULE_OPTIONAL, -1, 1 }, 10875 { { .avp_vendor = 10415, .avp_name = "Event-Charging-TimeStamp" }, RULE_OPTIONAL, -1, -1 }, 10876 }; 10877 PARSE_loc_rules(rules, rule_avp); 10878 } 10879 10788 10880 /* OMA */ 10789 10881 { -
extensions/rt_redirect/CMakeLists.txt
r717 r1260 9 9 redir_fwd.c 10 10 redir_out.c 11 uthash.h 11 12 ) 12 13 -
extensions/rt_redirect/redir_entries.c
r740 r1260 1 1 /********************************************************************************************************* 2 2 * Software License Agreement (BSD License) * 3 * Author: Sebastien Decugis <sdecugis@freediameter.net> * 3 * Authors: Sebastien Decugis <sdecugis@freediameter.net> * 4 * and Thomas Klausner <tk@giga.or.at> * 4 5 * * 5 * Copyright (c) 2011, WIDE Project and NICT*6 * Copyright (c) 2011, 2014, WIDE Project and NICT * 6 7 * All rights reserved. * 7 8 * * … … 35 36 36 37 #include "rt_redir.h" 38 #include "uthash.h" 37 39 38 40 /* The array with all entries ordered by their data */ 39 41 struct redir_line redirects_usages[H_U_MAX + 1]; 42 43 /* for symmetry reasons, hash tables for all types exist, but only ALL_SESSION and ALL_USER will be used */ 44 struct redir_entry *redirect_hash_table[H_U_MAX+1]; 40 45 41 46 /* Initialize the array */ … … 43 48 { 44 49 int i; 45 50 46 51 TRACE_ENTRY(""); 47 52 48 53 /* redirects_usages */ 49 54 memset(&redirects_usages, 0, sizeof(redirects_usages)); 50 55 51 56 for (i = 0; i <= H_U_MAX; i++) { 57 /* only one of the two will be used for each type, but initialize both to be on the safe side */ 58 59 /* initialize list */ 52 60 CHECK_POSIX( pthread_rwlock_init( &redirects_usages[i].lock, NULL) ); 53 61 fd_list_init( &redirects_usages[i].sentinel, &redirects_usages[i] ); 54 } 55 62 63 /* initialize hash table */ 64 redirect_hash_table[i] = NULL; 65 } 66 56 67 /* initialize the scores */ 57 68 redirects_usages[ DONT_CACHE ].score = FD_SCORE_REDIR_ONCE; … … 66 77 } 67 78 79 int redir_entry_fini() 80 { 81 int i; 82 struct redir_entry *current_entry, *tmp; 83 84 /* Empty all entries */ 85 CHECK_POSIX_DO( pthread_mutex_lock(&redir_exp_peer_lock), ); 86 for (i = 0; i <= H_U_MAX; i++) { 87 CHECK_POSIX_DO( pthread_rwlock_wrlock( &redirects_usages[i].lock), ); 88 switch(i) { 89 case ALL_SESSION: 90 case ALL_USER: 91 HASH_ITER(hh, redirect_hash_table[i], current_entry, tmp) { 92 HASH_DEL(redirect_hash_table[i], current_entry); 93 CHECK_FCT_DO( redir_entry_destroy(current_entry), ); 94 } 95 break; 96 default: 97 while (!FD_IS_LIST_EMPTY(&redirects_usages[i].sentinel)) { 98 struct redir_entry * e = redirects_usages[i].sentinel.next->o; 99 fd_list_unlink(&e->redir_list); 100 CHECK_FCT_DO( redir_entry_destroy(e), ); 101 } 102 } 103 CHECK_POSIX_DO( pthread_rwlock_unlock( &redirects_usages[i].lock), ); 104 CHECK_POSIX_DO( pthread_rwlock_destroy( &redirects_usages[i].lock), ); 105 } 106 CHECK_POSIX_DO( pthread_mutex_unlock(&redir_exp_peer_lock), ); 107 108 return 0; 109 } 68 110 69 111 /* Create a new redir_entry and add the correct data */ … … 73 115 os0_t s; 74 116 size_t l; 75 117 76 118 TRACE_ENTRY("%p %p %d %p %p %zd %p %zd", e, targets, rhu, qry, nh, nhlen, oh, ohlen) 77 119 ASSERT(e && targets && (rhu <= H_U_MAX) && qry && nh && nhlen && oh && ohlen); 78 120 79 121 CHECK_MALLOC( entry = malloc(sizeof(struct redir_entry)) ); 80 122 memset(entry, 0, sizeof(struct redir_entry)); 81 123 82 124 entry->eyec = REDIR_ENTRY_EYEC; 83 125 84 126 CHECK_MALLOC( entry->from.s = os0dup(nh, nhlen) ); 85 127 entry->from.l = nhlen; 86 128 87 129 fd_list_init(&entry->target_peers_list, entry); 88 130 fd_list_move_end(&entry->target_peers_list, targets); 89 131 90 132 fd_list_init(&entry->exp_list, entry); 91 133 92 134 entry->type = rhu; 135 /* list entry for putting into redirects_usage; also doubles as pointer into that list so it can be removed easily */ 93 136 fd_list_init(&entry->redir_list, entry); 94 137 /* finally initialize the data */ … … 97 140 entry->data.message.msg = qry; 98 141 break; 99 142 100 143 case ALL_SESSION: 101 144 { … … 114 157 } 115 158 break; 116 159 117 160 case ALL_REALM: 118 161 { … … 132 175 } 133 176 break; 134 177 135 178 case REALM_AND_APPLICATION: 136 179 { … … 156 199 } 157 200 break; 158 201 159 202 case ALL_APPLICATION: 160 203 { … … 164 207 } 165 208 break; 166 209 167 210 case ALL_HOST: 168 211 CHECK_MALLOC( entry->data.host.s = os0dup(oh, ohlen) ); 169 212 entry->data.host.l = ohlen; 170 213 break; 171 214 172 215 case ALL_USER: 173 216 { … … 187 230 } 188 231 break; 189 232 190 233 default: 191 234 ASSERT(0); 192 235 return EINVAL; 193 236 } 194 237 195 238 /* We're done */ 196 239 *e = entry; … … 203 246 unsigned long v1 = (unsigned long) d1->message.msg; 204 247 unsigned long v2 = (unsigned long) d2->message.msg; 205 if (v1 > v2) 248 if (v1 > v2) 206 249 return 1; 207 250 if (v1 < v2) … … 211 254 /* Compare two applications (REALM_AND_APPLICATION and ALL_APPLICATION) */ 212 255 static int compare_entries_appl(union matchdata * d1, union matchdata * d2) { 213 if (d1->app.a > d2->app.a) 256 if (d1->app.a > d2->app.a) 214 257 return 1; 215 if (d1->app.a < d2->app.a) 258 if (d1->app.a < d2->app.a) 216 259 return -1; 217 260 return 0; … … 238 281 { 239 282 struct fd_list * li; 240 283 struct redir_entry * r = NULL; 284 241 285 TRACE_ENTRY("%p", e); 242 286 CHECK_PARAMS(e && (e->eyec == REDIR_ENTRY_EYEC)); 243 287 244 288 /* Write-Lock the line */ 245 289 CHECK_POSIX( pthread_rwlock_wrlock( RWLOCK_REDIR(e) ) ); 246 247 for (li = redirects_usages[e->type].sentinel.next; li != &redirects_usages[e->type].sentinel; li = li->next) { 248 struct redir_entry * n = li->o; 249 int cmp = redir_entry_cmp_key[e->type](&e->data, &n->data); 250 if (cmp <= 0) 251 break; 252 } 253 254 fd_list_insert_before(li, &e->redir_list); 255 290 291 switch (e->type) { 292 case ALL_SESSION: 293 HASH_FIND(hh, redirect_hash_table[e->type], e->data.session.s, e->data.session.l, r); 294 if (r) { 295 /* previously existing entry, delete it from hash and free it */ 296 HASH_DELETE(hh, redirect_hash_table[e->type], r); 297 CHECK_FCT_DO( redir_entry_destroy(r), ); 298 } 299 HASH_ADD_KEYPTR(hh, redirect_hash_table[e->type], e->data.session.s, e->data.session.l, e); 300 break; 301 case ALL_USER: 302 HASH_FIND(hh, redirect_hash_table[e->type], e->data.user.s, e->data.user.l, r); 303 if (r) { 304 /* previously existing entry, delete it from hash and free it */ 305 HASH_DELETE(hh, redirect_hash_table[e->type], r); 306 CHECK_FCT_DO( redir_entry_destroy(r), ); 307 } 308 HASH_ADD_KEYPTR(hh, redirect_hash_table[e->type], e->data.user.s, e->data.user.l, e); 309 break; 310 default: 311 for (li = redirects_usages[e->type].sentinel.next; li != &redirects_usages[e->type].sentinel; li = li->next) { 312 struct redir_entry * n = li->o; 313 int cmp = redir_entry_cmp_key[e->type](&e->data, &n->data); 314 if (cmp <= 0) 315 break; 316 } 317 318 fd_list_insert_before(li, &e->redir_list); 319 break; 320 } 321 256 322 /* unLock the line */ 257 323 CHECK_POSIX( pthread_rwlock_unlock( RWLOCK_REDIR(e) ) ); … … 263 329 int redir_entry_destroy(struct redir_entry * e) 264 330 { 331 struct redir_entry *match; 265 332 TRACE_ENTRY("%p", e); 266 333 CHECK_PARAMS(e && (e->eyec == REDIR_ENTRY_EYEC)); 267 268 /* If the entry is linked, lock the rwlock also */ 269 if (!FD_IS_LIST_EMPTY(&e->redir_list)) { 270 CHECK_POSIX( pthread_rwlock_wrlock( RWLOCK_REDIR(e) ) ); 271 fd_list_unlink(&e->redir_list); 272 CHECK_POSIX( pthread_rwlock_unlock( RWLOCK_REDIR(e) ) ); 273 } 274 334 335 switch (e->type) { 336 case ALL_SESSION: 337 /* If the entry is in the hash table, lock the rwlock also */ 338 HASH_FIND(hh, redirect_hash_table[e->type], e->data.session.s, e->data.session.l, match); 339 if (match) { 340 /* TODO: check if e == match? */ 341 CHECK_POSIX( pthread_rwlock_wrlock( RWLOCK_REDIR(e) ) ); 342 HASH_DELETE(hh, redirect_hash_table[e->type], match); 343 CHECK_POSIX( pthread_rwlock_unlock( RWLOCK_REDIR(e) ) ); 344 } 345 break; 346 case ALL_USER: 347 /* If the entry is in the hash table, lock the rwlock also */ 348 HASH_FIND(hh, redirect_hash_table[e->type], e->data.user.s, e->data.user.l, match); 349 if (match) { 350 /* TODO: check if e == match? */ 351 CHECK_POSIX( pthread_rwlock_wrlock( RWLOCK_REDIR(e) ) ); 352 HASH_DELETE(hh, redirect_hash_table[e->type], match); 353 CHECK_POSIX( pthread_rwlock_unlock( RWLOCK_REDIR(e) ) ); 354 } 355 break; 356 default: 357 /* If the entry is linked, lock the rwlock also */ 358 if (!FD_IS_LIST_EMPTY(&e->redir_list)) { 359 CHECK_POSIX( pthread_rwlock_wrlock( RWLOCK_REDIR(e) ) ); 360 fd_list_unlink(&e->redir_list); 361 CHECK_POSIX( pthread_rwlock_unlock( RWLOCK_REDIR(e) ) ); 362 } 363 break; 364 } 365 275 366 /* Now unlink from other list */ 276 367 fd_list_unlink(&e->exp_list); 277 368 278 369 /* Empty the targets list */ 279 370 while (!FD_IS_LIST_EMPTY(&e->target_peers_list)) { 280 371 struct redir_host * h = (struct redir_host *)e->target_peers_list.next->o; 281 372 282 373 fd_list_unlink(&h->chain); 283 374 free(h->id); 284 375 free(h); 285 376 } 286 377 287 378 /* Now we can destroy the data safely */ 288 379 switch (e->type) { … … 312 403 return EINVAL; 313 404 } 314 405 315 406 free(e->from.s); 316 407 317 408 free(e); 318 409 return 0; -
extensions/rt_redirect/redir_expiry.c
r740 r1259 41 41 /* Entries by their ascending expiration date, to accelerate the work of the expire thread */ 42 42 static struct fd_list expire_list = FD_LIST_INITIALIZER(expire_list); 43 static pthread_cond_t exp_cnd = PTHREAD_COND_INITIALIZER; 43 static pthread_cond_t exp_cnd = PTHREAD_COND_INITIALIZER; 44 44 45 45 pthread_mutex_t redir_exp_peer_lock = PTHREAD_MUTEX_INITIALIZER; 46 46 47 47 /* The thread that handles expired entries cleanup. */ 48 void * redir_exp_thr_fct(void * arg) 48 void * redir_exp_thr_fct(void * arg) 49 49 { 50 50 fd_log_threadname ( "Redirects/expire" ); … … 53 53 CHECK_POSIX_DO( pthread_mutex_lock(&redir_exp_peer_lock), goto fatal_error ); 54 54 pthread_cleanup_push( fd_cleanup_mutex, &redir_exp_peer_lock ); 55 55 56 56 do { 57 57 struct timespec now; 58 58 struct redir_entry * first; 59 again: 59 again: 60 60 /* Check if there are expiring entries available */ 61 61 if (FD_IS_LIST_EMPTY(&expire_list)) { … … 65 65 goto again; 66 66 } 67 67 68 68 /* Get the pointer to the entry that expires first */ 69 69 first = (struct redir_entry *)(expire_list.next->o); 70 70 71 71 /* Get the current time */ 72 72 CHECK_SYS_DO( clock_gettime(CLOCK_REALTIME, &now), break ); … … 74 74 /* If first session is not expired, we just wait until it happens */ 75 75 if ( TS_IS_INFERIOR( &now, &first->timeout ) ) { 76 77 CHECK_POSIX_DO2( pthread_cond_timedwait( &exp_cnd, &redir_exp_peer_lock, &first->timeout ), 76 77 CHECK_POSIX_DO2( pthread_cond_timedwait( &exp_cnd, &redir_exp_peer_lock, &first->timeout ), 78 78 ETIMEDOUT, /* ETIMEDOUT is a normal error, continue */, 79 79 /* on other error, */ break ); 80 80 81 81 /* on wakeup, loop */ 82 82 goto again; 83 83 } 84 84 85 85 /* Now, the first entry in the list is expired; destroy it */ 86 86 87 87 CHECK_FCT_DO( redir_entry_destroy( first ), break ); 88 88 89 89 } while (1); 90 90 91 91 pthread_cleanup_pop( 0 ); 92 92 CHECK_POSIX_DO( pthread_mutex_unlock(&redir_exp_peer_lock), ); 93 93 94 94 fatal_error: 95 95 TRACE_DEBUG(INFO, "A system error occurred in redirect module! Expiry thread is terminating..."); … … 104 104 TRACE_ENTRY("%p %d", e, duration); 105 105 CHECK_PARAMS(e && (e->eyec == REDIR_ENTRY_EYEC) && duration ); 106 106 107 107 /* Unlink in case it was already set before */ 108 108 fd_list_unlink(&e->exp_list); 109 109 110 110 /* Get current time */ 111 111 CHECK_SYS( clock_gettime(CLOCK_REALTIME, &e->timeout) ); 112 112 113 113 /* Add the duration */ 114 114 e->timeout.tv_sec += duration; 115 115 116 116 /* now search the next element in the list */ 117 117 for (li = expire_list.next; li != &expire_list; li = li->next) { 118 118 struct redir_entry * n = li->o; 119 119 120 120 if ( TS_IS_INFERIOR( &e->timeout, &n->timeout ) ) 121 121 break; 122 122 123 123 } 124 124 125 125 /* Insert before this element */ 126 126 fd_list_insert_before(li, &e->exp_list); 127 127 128 128 /* Signal the expiry thread if needed */ 129 129 if (e->exp_list.prev == &expire_list) { /* it is the first element */ 130 130 CHECK_POSIX( pthread_cond_signal(&exp_cnd) ); 131 131 } 132 132 133 133 /* Done */ 134 134 return 0; -
extensions/rt_redirect/redir_fwd.c
r1127 r1259 59 59 int nbrh = 0; 60 60 struct redir_entry * entry; 61 61 62 62 TRACE_ENTRY("%p %p", cbdata, msg); 63 63 64 64 CHECK_PARAMS(msg && *msg); 65 65 66 66 m = *msg; 67 67 68 68 /* First get the header */ 69 69 CHECK_FCT( fd_msg_hdr(m, &hdr) ); 70 70 71 71 /* Check if we have an error */ 72 72 ASSERT(!(hdr->msg_flags & CMD_FLAG_REQUEST)); … … 75 75 return 0; 76 76 } 77 77 78 78 /* Now get the AVPs we are interested in */ 79 79 CHECK_FCT( fd_msg_browse(m, MSG_BRW_FIRST_CHILD, &avp, NULL) ); 80 80 while (avp) { 81 81 struct avp_hdr * ahdr; 82 82 83 83 CHECK_FCT( fd_msg_avp_hdr( avp, &ahdr ) ); 84 84 if (! (ahdr->avp_flags & AVP_FLAG_VENDOR)) { … … 90 90 a_oh = ahdr->avp_value; 91 91 break; 92 92 93 93 case AC_RESULT_CODE: 94 94 /* Parse this AVP */ … … 96 96 ASSERT( ahdr->avp_value ); 97 97 a_rc = ahdr->avp_value; 98 98 99 99 if (a_rc->u32 != ER_DIAMETER_REDIRECT_INDICATION) { 100 100 /* It is not a REDIRECT error, we don't do anything */ … … 102 102 } 103 103 break; 104 104 105 105 case AC_REDIRECT_HOST: 106 106 { … … 112 112 int l4 = 0; 113 113 char proto = 0; 114 114 115 115 /* Parse this AVP */ 116 116 CHECK_FCT( fd_msg_parse_dict ( avp, fd_g_config->cnf_dict, NULL ) ); 117 117 ASSERT( ahdr->avp_value ); 118 118 119 119 nbrh++; 120 121 CHECK_FCT_DO( fd_os_parse_DiameterURI(ahdr->avp_value->os.data, ahdr->avp_value->os.len, 120 121 CHECK_FCT_DO( fd_os_parse_DiameterURI(ahdr->avp_value->os.data, ahdr->avp_value->os.len, 122 122 &id, &len, &secure, &port, &l4, &proto), 123 123 { … … 125 125 break; 126 126 } ); 127 127 128 128 /* Now check if the transport & protocol are supported */ 129 129 if (proto && (proto != 'd')) { … … 137 137 break; 138 138 } 139 139 140 140 /* It looks OK, save this entry. */ 141 141 142 142 CHECK_MALLOC( h = malloc(sizeof(struct redir_host)) ); 143 143 memset(h, 0, sizeof(struct redir_host)); … … 146 146 h->len = len; 147 147 /* later: secure, port */ 148 148 149 149 /* The list is kept ordered by id so that it is faster to compare to candidates later */ 150 150 for (li = task.rh.next; li != &task.rh; li = li->next) { … … 183 183 CHECK_FCT( fd_msg_browse(avp, MSG_BRW_NEXT, &avp, NULL) ); 184 184 } 185 185 186 186 /* Check we have received the necessary information */ 187 187 if (!a_rc) { … … 189 189 goto out; 190 190 } 191 191 192 192 if (!a_oh) { 193 193 TRACE_DEBUG(FULL, "Invalid Diameter answer without an Origin-Host AVP, Redirect module gave up"); 194 194 goto out; 195 195 } 196 196 197 197 if (FD_IS_LIST_EMPTY(&task.rh)) { 198 198 TRACE_DEBUG(FULL, "Diameter answer with a DIAMETER_REDIRECT_INDICATION Result-Code AVP but no valid/supported Redirect-Host AVP, Redirect module gave up"); … … 204 204 goto out; 205 205 } 206 206 207 207 /* It looks like we can process the Redirect indication */ 208 208 209 209 /* Search for the peers we already know */ 210 210 for (li = task.rh.next; li != &task.rh; li = li->next) { 211 211 struct redir_host * h = li->o; 212 212 struct peer_hdr * peer; 213 213 214 214 CHECK_FCT( fd_peer_getbyid( h->id, h->len, 1, &peer ) ); 215 215 if (peer) { … … 221 221 } 222 222 } 223 223 224 224 TRACE_DEBUG(FULL, "Redirect module: received %d Redirect-Hosts, %d are known peers, %d have an OPEN connection", nbrh, known, actives); 225 225 226 226 /* in this version, we only redirect when there are known active peers. TODO: add new peers via fd_peer_add when no active peer is available */ 227 227 228 228 if (!actives) { 229 229 TRACE_DEBUG(INFO, "Unable to comply to Redirect indication: none of the peers included is in OPEN state"); 230 230 goto out; 231 231 } 232 232 233 233 /* From this point, we will re-send the query to a different peer, so stop forwarding the answer here */ 234 234 *msg = NULL; 235 235 236 236 /* Get the query's routing data & add the new error */ 237 237 CHECK_FCT( fd_msg_answ_getq(m, &q) ); … … 239 239 CHECK_FCT( fd_msg_source_get( m, &nh, &nhlen ) ); 240 240 CHECK_FCT( fd_rtd_error_add(rtd, nh, nhlen, a_oh->os.data, a_oh->os.len, a_rc->u32, NULL, NULL) ); 241 241 242 242 /* Create a redir_rule */ 243 243 CHECK_FCT( redir_entry_new(&entry, &task.rh, task.rhu, q, nh, nhlen, a_oh->os.data, a_oh->os.len) ); 244 244 245 245 CHECK_POSIX( pthread_mutex_lock(&redir_exp_peer_lock) ); 246 246 /* Insert in the split list */ … … 253 253 CHECK_FCT( fd_msg_answ_detach(m) ); 254 254 CHECK_FCT( fd_msg_free(m) ); 255 255 256 256 /* Send it */ 257 257 CHECK_FCT( fd_msg_send(&q, NULL, NULL) ); 258 258 259 259 /* Done! */ 260 260 261 261 out: 262 262 while (!FD_IS_LIST_EMPTY(&task.rh)) { … … 266 266 free(h); 267 267 } 268 268 269 269 return 0; 270 270 -
extensions/rt_redirect/redir_out.c
r1216 r1260 1 1 /********************************************************************************************************* 2 2 * Software License Agreement (BSD License) * 3 * Author: Sebastien Decugis <sdecugis@freediameter.net> * 3 * Authors: Sebastien Decugis <sdecugis@freediameter.net> * 4 * and Thomas Klausner <tk@giga.or.at> * 4 5 * * 5 * Copyright (c) 2013, WIDE Project and NICT*6 * Copyright (c) 2013, 2014, WIDE Project and NICT * 6 7 * All rights reserved. * 7 8 * * … … 41 42 { 42 43 TRACE_ENTRY("%d %p %p %p", type, msg, data, nodata); 43 44 44 45 /* Initialize the data area */ 45 46 memset(data, 0, sizeof(union matchdata)); 46 47 *nodata = 0; 47 48 48 49 /* Now, find the appropriate information, depending on type */ 49 50 switch (type) { … … 51 52 data->message.msg = msg; 52 53 break; 53 54 54 55 case ALL_SESSION: 55 56 { … … 65 66 } 66 67 break; 67 68 68 69 case ALL_REALM: 69 70 { … … 82 83 } 83 84 break; 84 85 85 86 case REALM_AND_APPLICATION: 86 87 { … … 96 97 data->realm_app.s = ahdr->avp_value->os.data; 97 98 data->realm_app.l = ahdr->avp_value->os.len; 98 99 99 100 /* and then the application */ 100 101 { … … 107 108 } 108 109 break; 109 110 110 111 case ALL_APPLICATION: 111 112 { … … 116 117 } 117 118 break; 118 119 119 120 case ALL_HOST: 120 121 /* This is more complex, we need to match with all candidates in each rule, it'll be done later */ 121 122 break; 122 123 123 124 case ALL_USER: 124 125 { … … 137 138 } 138 139 break; 139 140 140 141 default: 141 142 ASSERT(0); … … 153 154 struct rtd_candidate * c_oh = NULL; 154 155 int cmp; 155 156 156 157 TRACE_ENTRY("%p %p %p", e, msg, candidates); 157 158 ASSERT( e && msg && candidates ); 158 159 159 160 if (FD_IS_LIST_EMPTY(candidates)) { 160 161 TRACE_DEBUG(ANNOYING, "Skip Redirect rule since candidates list is empty"); 161 162 return 0; 162 163 } 163 164 164 165 /* Now search common peers between e->target_peers_list and candidates */ 165 166 TRACE_DEBUG(ANNOYING, "Message %p matches a Redirect rule (t:%d, @%p), processing candidates list", msg, e->type, e); 166 167 167 168 /* First, decrease the score of the host that we received the previous Redirect from, in case it is in the list */ 168 169 for (lic = candidates->next; lic != candidates; lic = lic->next) { 169 170 struct rtd_candidate * cand = (struct rtd_candidate *) lic; 170 171 171 172 /* Special case: ALL_HOST rules: we decrease the score of the Origin-Host if present */ 172 173 if (e->type == ALL_HOST) { … … 179 180 } 180 181 } 181 182 182 183 cmp = fd_os_cmp(cand->diamid, cand->diamidlen, e->from.s, e->from.l); 183 184 if (!cmp) { … … 185 186 cand->score += FD_SCORE_SENT_REDIRECT; 186 187 } 187 188 } 189 188 189 } 190 190 191 if ((e->type == ALL_HOST) && (c_oh == NULL)) { 191 192 /* The rule does not apply, we're done */ 192 193 return 0; 193 194 } 194 195 195 196 /* for each candidate, if it is found in the target_peers list, we add the rule's score to this candidate */ 196 197 for (lic = candidates->next; lic != candidates; lic = lic->next) { 197 198 /* the candidates list is not guaranteed to be ordered at this time, so we cannot avoid the two imbricated loops */ 198 199 struct rtd_candidate * cand = (struct rtd_candidate *) lic; 199 200 200 201 /* Is this candidate in the "Redirect-Host" list ? We must search caseinsentive here. */ 201 202 for (lirh = e->target_peers_list.next; lirh != &e->target_peers_list; lirh = lirh->next) { 202 203 struct redir_host * host = lirh->o; 203 204 int cont; 204 205 205 206 cmp = fd_os_almostcasesrch( cand->diamid, cand->diamidlen, host->id, host->len, &cont ); 206 207 207 208 if (cmp == 0) { 208 209 TRACE_DEBUG(FULL, "Redirect msg %p: peer '%.*s' += %d (rule t:%d @%p)", msg, (int)cand->diamidlen, cand->diamid, redirects_usages[e->type].score, e->type, e); … … 214 215 } 215 216 } 216 217 217 218 return 0; 218 219 } 219 220 221 static int redir_exist_for_type(int rule_type) 222 { 223 int ret; 224 225 switch(rule_type) { 226 case ALL_SESSION: 227 case ALL_USER: 228 ret = redirect_hash_table[rule_type] != NULL; 229 break; 230 default: 231 ret = !FD_IS_LIST_EMPTY(&redirects_usages[rule_type].sentinel); 232 break; 233 } 234 return ret; 235 } 236 237 static int match_message(int rule_type, struct msg *msg, union matchdata *data, struct fd_list * candidates) 238 { 239 struct fd_list * li; 240 struct redir_entry * e = NULL; 241 int ret = 0; 242 243 switch(rule_type) { 244 case ALL_SESSION: 245 HASH_FIND(hh, redirect_hash_table[rule_type], data->session.s, data->session.l, e); 246 if (e) { 247 /* This message matches a rule, apply */ 248 CHECK_FCT_DO( ret = apply_rule(e, msg, candidates), break ); 249 } 250 break; 251 case ALL_USER: 252 HASH_FIND(hh, redirect_hash_table[rule_type], data->user.s, data->user.l, e); 253 if (e) { 254 /* This message matches a rule, apply */ 255 CHECK_FCT_DO( ret = apply_rule(e, msg, candidates), break ); 256 } 257 break; 258 default: 259 /* Attempt each rule we have stored */ 260 for (li = redirects_usages[rule_type].sentinel.next; li != &redirects_usages[rule_type].sentinel; li = li->next) { 261 e = li->o; 262 263 /* Does it match ? */ 264 if (rule_type != ALL_HOST) { /* this one is an exception, we handle it separately */ 265 int cmp = redir_entry_cmp_key[rule_type](data, &e->data); 266 if (cmp > 0) 267 continue; 268 if (cmp < 0) 269 break; 270 } 271 272 /* This rule matches (or we are in ALL_HOST), apply */ 273 CHECK_FCT_DO( ret = apply_rule(e, msg, candidates), break ); 274 275 /* If this was a DONT_CACHE rule, we unlink it, so that it will not be used again */ 276 if (rule_type == DONT_CACHE) { 277 li = li->prev; 278 fd_list_unlink( li->next ); 279 /* We cannot delete here without taking the mutex, which would mean we have first to release the lock... 280 just let expiry garbage collect the rule */ 281 } 282 } 283 } 284 285 return ret; 286 } 220 287 221 288 /* OUT callback */ … … 224 291 int i, ret = 0; 225 292 struct msg * msg = *pmsg; 226 293 227 294 TRACE_ENTRY("%p %p %p", cbdata, msg, candidates); 228 295 229 296 for (i = 0; i <= H_U_MAX; i++) { 230 297 /* Lock the line. We write lock in case of DONT_CACHE so we can directly unlink the entry. read in other cases is sufficient */ … … 234 301 CHECK_POSIX( pthread_rwlock_rdlock( &redirects_usages[i].lock ) ); 235 302 } 236 237 if ( !FD_IS_LIST_EMPTY(&redirects_usages[i].sentinel)) {303 304 if (redir_exist_for_type(i)) { 238 305 union matchdata data; 239 306 int nodata; /* The message does not allow to apply this rule, skip */ 240 307 241 308 /* Retrieve the data that may match in the message */ 242 309 CHECK_FCT_DO( ret = get_data_to_match(i, msg, &data, &nodata), goto out ); 243 244 /* If this message may match some of our rules */ 245 if (!nodata) { 246 struct fd_list * li; 247 /* Attempt each rule we have stored */ 248 for (li = redirects_usages[i].sentinel.next; li != &redirects_usages[i].sentinel; li = li->next) { 249 struct redir_entry * e = li->o; 250 251 /* Does it match ? */ 252 if (i != ALL_HOST) { /* this one is an exception, we handle it separately */ 253 int cmp = redir_entry_cmp_key[i](&data, &e->data); 254 if (cmp > 0) 255 continue; 256 if (cmp < 0) 257 break; 258 } 259 260 /* This rule matches (or we are in ALL_HOST), apply */ 261 CHECK_FCT_DO( ret = apply_rule(e, msg, candidates), goto out ); 262 263 /* If this was a DONT_CACHE rule, we unlink it, so that it will not be used again */ 264 if (i == DONT_CACHE) { 265 li=li->prev; 266 fd_list_unlink( li->next ); 267 /* We cannot delete here without taking the mutex, which would mean we have first to release the lock... 268 just let expiry garbage collet the rule */ 269 } 270 } 271 } 272 273 } 274 out: 310 311 /* If data found for this type of rule, then try matching it */ 312 if (!nodata) 313 ret = match_message(i, msg, &data, candidates); 314 } 315 out: 275 316 CHECK_POSIX( pthread_rwlock_unlock( &redirects_usages[i].lock ) ); 276 317 if (ret) 277 318 return ret; 278 319 } 279 320 280 321 return 0; 281 322 } -
extensions/rt_redirect/rt_redir.c
r740 r1260 1 1 /********************************************************************************************************* 2 2 * Software License Agreement (BSD License) * 3 * Author: Sebastien Decugis <sdecugis@freediameter.net> * 3 * Authors: Sebastien Decugis <sdecugis@freediameter.net> * 4 * and Thomas Klausner <tk@giga.or.at> * 4 5 * * 5 * Copyright (c) 2011, WIDE Project and NICT*6 * Copyright (c) 2011, 2014, WIDE Project and NICT * 6 7 * All rights reserved. * 7 8 * * … … 47 48 { 48 49 TRACE_ENTRY(""); 49 50 50 51 /* Dictionary objects */ 51 52 CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Destination-Realm", &redir_dict_dr, ENOENT) ); … … 54 55 /* Initialize the entries array */ 55 56 CHECK_FCT( redir_entry_init() ); 56 57 57 58 /* Start the expire thread */ 58 59 CHECK_POSIX( pthread_create( &exp_thr, NULL, redir_exp_thr_fct, NULL ) ); 59 60 60 61 /* Register the callback that receives the answers and processes when it contains a Redirect indication. */ 61 62 CHECK_FCT( fd_rt_fwd_register ( redir_fwd_cb, NULL, RT_FWD_ANS, &fwd_hdl ) ); … … 72 73 void fd_ext_fini(void) 73 74 { 74 int i;75 76 75 /* Unregister the callbacks */ 77 76 if (fwd_hdl) { … … 81 80 CHECK_FCT_DO( fd_rt_out_unregister(out_hdl, NULL), ); 82 81 } 83 82 84 83 /* Stop the expiry thread */ 85 84 CHECK_FCT_DO( fd_thr_term(&exp_thr), ); 86 85 87 86 /* Empty all entries */ 88 CHECK_POSIX_DO( pthread_mutex_lock(&redir_exp_peer_lock), ); 89 for (i = 0; i <= H_U_MAX; i++) { 90 CHECK_POSIX_DO( pthread_rwlock_wrlock( &redirects_usages[i].lock), ); 91 while (!FD_IS_LIST_EMPTY(&redirects_usages[i].sentinel)) { 92 struct redir_entry * e = redirects_usages[i].sentinel.next->o; 93 fd_list_unlink(&e->redir_list); 94 CHECK_FCT_DO( redir_entry_destroy(e), ); 95 } 96 CHECK_POSIX_DO( pthread_rwlock_unlock( &redirects_usages[i].lock), ); 97 CHECK_POSIX_DO( pthread_rwlock_destroy( &redirects_usages[i].lock), ); 98 } 99 CHECK_POSIX_DO( pthread_mutex_unlock(&redir_exp_peer_lock), ); 100 87 redir_entry_fini(); 88 101 89 return; 102 90 } -
extensions/rt_redirect/rt_redir.h
r1235 r1260 1 1 /********************************************************************************************************* 2 2 * Software License Agreement (BSD License) * 3 * Author: Sebastien Decugis <sdecugis@freediameter.net> * 4 * * 5 * Copyright (c) 2013, WIDE Project and NICT * 3 * Author: Sebastien Decugis <sdecugis@freediameter.net> and * 4 * Thomas Klausner <tk@giga.or.at> * 5 * * 6 * Copyright (c) 2013, 2014, WIDE Project and NICT * 6 7 * All rights reserved. * 7 8 * * … … 37 38 #include <freeDiameter/extension.h> 38 39 40 #include "uthash.h" 41 39 42 /* There are 2 locks in this module. The priority is established as follow to avoid deadlocks: 40 43 exp_peer mutex > usages rwlock. 41 (e.g., the rwlock can be taken while holding the mutex, but not the other way) 44 (e.g., the rwlock can be taken while holding the mutex, but not the other way) 42 45 */ 43 46 … … 59 62 /* Expiration time set for DONT_CACHE tasks, so that the entry is found when the code is called back */ 60 63 #define DEFAULT_EXPIRE_TIME 10 /* seconds */ 61 64 62 65 /* Structure to store a parsed Redirect-Host */ 63 66 struct redir_host { 64 struct fd_list chain; 65 67 struct fd_list chain; 68 66 69 DiamId_t id; /* malloc'd */ 67 70 size_t len; 68 /* We don't use the following yet because we don't support dynamic new connections 71 /* We don't use the following yet because we don't support dynamic new connections 69 72 int secure; 70 73 uint16_t port; … … 117 120 } user; 118 121 }; 119 122 120 123 121 124 /* Structure to store a Redirect indication */ 122 125 struct redir_entry { 123 126 uint32_t eyec; /* must be REDIR_ENTRY_EYEC, used for debug only */ 124 127 125 128 struct { 126 129 os0_t s; /* alloc'd, must be freed */ … … 130 133 struct fd_list target_peers_list; /* The list of Redirect-Hosts for this entry */ 131 134 132 struct timespec timeout; /* When does this entry expire s? */135 struct timespec timeout; /* When does this entry expire? */ 133 136 struct fd_list exp_list; /* chain in the expire_list list, ordered by expiration date, protected by exp_peer_lock */ 134 135 enum redir_h_u type; /* Type of this entry */137 138 enum redir_h_u type; /* Type of this entry */ 136 139 struct fd_list redir_list; /* link in redirects_usages lists. Lists are ordered by the data value. Protected by rw locks */ 137 union matchdata data; /* The strings are duplicated & must be freed in this structure */ 140 union matchdata data; /* The strings are duplicated & must be freed in this structure */ 141 UT_hash_handle hh; /* magic entry for hash table */ 138 142 }; 139 143 … … 145 149 }; 146 150 extern struct redir_line redirects_usages[]; 151 /* the hash table where entries are stored for ALL_SESSION and ALL_USER */ 152 extern struct redir_entry *redirect_hash_table[]; 147 153 148 154 /* Accelerator to the line lock */ … … 158 164 /* Functions on redir_entry */ 159 165 int redir_entry_init(); 166 int redir_entry_fini(); 160 167 int redir_entry_new(struct redir_entry ** e, struct fd_list * targets, uint32_t rhu, struct msg * qry, DiamId_t nh, size_t nhlen, os0_t oh, size_t ohlen); 161 168 extern int (*redir_entry_cmp_key[])(union matchdata * , union matchdata *); /* compare functions */ -
include/freeDiameter/libfdproto.h
r1248 r1258 484 484 || (fd_debug_one_file && !strcmp(fd_debug_one_file, file) )) 485 485 return 2; /* Level override */ 486 if ( level <= fd_g_debug_lvl)486 if ((int)level <= fd_g_debug_lvl) 487 487 return 1; /* Normal level */ 488 488 return 0; /* No trace */ -
libfdproto/dictionary_functions.c
r1225 r1261 201 201 memcpy(&s.sin6.sin6_port, avp_value->os.data + 18, 2); 202 202 break; 203 case 8: 204 /* E.164 */ 205 CHECK_MALLOC_DO( fd_dump_extend(FD_DUMP_STD_PARAMS, "%.*s", avp_value->os.len-2, avp_value->os.data+2), return NULL); 206 return *buf; 203 207 default: 204 208 CHECK_MALLOC_DO( fd_dump_extend(FD_DUMP_STD_PARAMS, "[unsupported family: 0x%hx]", fam), return NULL);
Note: See TracChangeset
for help on using the changeset viewer.