00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037 #include "domainpolicy_mod.h"
00038 #include "domainpolicy.h"
00039 #include "../../db/db.h"
00040 #include "../../parser/parse_uri.h"
00041 #include "../../parser/parse_from.h"
00042 #include "../../ut.h"
00043 #include "../../dset.h"
00044 #include "../../route.h"
00045 #include "../../ip_addr.h"
00046 #include "../../socket_info.h"
00047
00048 #include "../../resolve.h"
00049 #include "../../regexp.h"
00050
00051 #define IS_D2PNAPTR(naptr) ((naptr->services_len >= 7) && (!strncasecmp("D2P+SIP", naptr->services, 7)))
00052
00053 static db_con_t* db_handle=0;
00054 static db_func_t domainpolicy_dbf;
00055
00056
00057
00058
00059
00060
00061
00062
00063 #define AVPMAXSIZE 120
00064 #define AVPSTACKSIZE 32
00065
00066 struct avp {
00067 char att[AVPMAXSIZE];
00068 char val[AVPMAXSIZE];
00069 };
00070
00071 struct avp_stack {
00072 int succeeded;
00073 int i;
00074 struct avp avp[AVPSTACKSIZE];
00075 };
00076
00077
00078
00079
00080
00081
00082 static int stack_push(struct avp_stack *stack, char *att, char *val) {
00083 int i;
00084 if (stack->i >= (AVPSTACKSIZE-1)) {
00085 LM_ERR("exceeded stack size.!\n");
00086 return(0);
00087 }
00088
00089 i = (stack->i)++;
00090 strncpy(stack->avp[i].att, att, AVPMAXSIZE - 1);
00091 strncpy(stack->avp[i].val, val, AVPMAXSIZE - 1);
00092
00093 stack->succeeded = 1;
00094
00095 return(1);
00096 }
00097
00098
00099 static void stack_reset(struct avp_stack *stack) {
00100 stack->i = 0;
00101 stack->succeeded = 0;
00102 }
00103
00104 static int stack_succeeded(struct avp_stack *stack) {
00105 return(stack->succeeded);
00106 }
00107
00108 static void stack_to_avp(struct avp_stack *stack) {
00109 int j;
00110 int_str avp_att;
00111 int_str avp_val;
00112 unsigned int intval;
00113
00114 intval=2;
00115
00116 for(j=0; j< stack->i; j++) {
00117
00118 LM_DBG("process AVP: name='%s' value='%s'\n",
00119 stack->avp[j].att, stack->avp[j].val);
00120
00121
00122
00123
00124
00125 if ( stack->avp[j].att[0] && stack->avp[j].att[1]==':' ) {
00126
00127 switch (stack->avp[j].att[0]) {
00128 case 'i':
00129 case 'I':
00130 intval = 1;
00131 break;
00132 case 's':
00133 case 'S':
00134 intval = 0;
00135 break;
00136 default:
00137 LM_ERR("invalid type '%c'\n",stack->avp[j].att[0]);
00138 continue;
00139 }
00140 avp_att.s.s = (char *) &(stack->avp[j].att[2]);
00141 } else {
00142 avp_att.s.s = stack->avp[j].att;
00143 }
00144 avp_att.s.len = strlen(avp_att.s.s);
00145 if (!avp_att.s.len) {
00146 LM_ERR("empty AVP name string!\n");
00147 continue;
00148 }
00149
00150 avp_val.s.s = stack->avp[j].val;
00151 avp_val.s.len = strlen(avp_val.s.s);
00152
00153 if (intval==1) {
00154
00155 if (str2int(&(avp_att.s), &intval) == 0) {
00156
00157 if (!intval) {
00158 LM_ERR("nameless integer AVP!\n");
00159 continue;
00160 }
00161 avp_att.n = intval;
00162 LM_DBG("create integer named AVP <i:%d>\n", avp_att.n);
00163 add_avp(AVP_VAL_STR, avp_att, avp_val);
00164 continue;
00165 } else {
00166 LM_ERR("integer AVP is not an integer!\n");
00167 continue;
00168 }
00169 }
00170
00171 if (intval==2) {
00172
00173
00174
00175
00176
00177 if (str2int(&(avp_att.s), &intval) == 0) {
00178
00179 if (!intval) {
00180 LM_ERR("nameless integer AVP!\n");
00181 continue;
00182 }
00183 avp_att.n = intval;
00184 LM_DBG("create integer named AVP <i:%d>\n", avp_att.n);
00185 add_avp(AVP_VAL_STR, avp_att, avp_val);
00186 continue;
00187 } else {
00188 LM_DBG("create string named AVP <s:%.*s>\n",
00189 avp_att.s.len, ZSW(avp_att.s.s));
00190 add_avp(AVP_NAME_STR | AVP_VAL_STR, avp_att, avp_val);
00191 continue;
00192 }
00193 }
00194
00195
00196 LM_DBG("create string named AVP <s:%.*s>\n",
00197 avp_att.s.len, ZSW(avp_att.s.s));
00198 add_avp(AVP_NAME_STR | AVP_VAL_STR, avp_att, avp_val);
00199 }
00200 }
00201
00202
00203
00204
00205
00206
00207
00208
00209 int domainpolicy_db_bind(const str* db_url)
00210 {
00211 if (db_bind_mod(db_url, &domainpolicy_dbf )) {
00212 LM_CRIT("cannot bind to database module! "
00213 "Did you forget to load a database module ?\n");
00214 return -1;
00215 }
00216 return 0;
00217 }
00218
00219
00220
00221
00222
00223
00224
00225 int domainpolicy_db_init(const str* db_url)
00226 {
00227 if (domainpolicy_dbf.init==0){
00228 LM_CRIT("unbound database module\n");
00229 goto error;
00230 }
00231 db_handle=domainpolicy_dbf.init(db_url);
00232 if (db_handle==0){
00233 LM_CRIT("cannot initialize database connection\n");
00234 goto error;
00235 }
00236 return 0;
00237 error:
00238 return -1;
00239 }
00240
00241
00242
00243
00244
00245 void domainpolicy_db_close(void)
00246 {
00247 if (db_handle && domainpolicy_dbf.close){
00248 domainpolicy_dbf.close(db_handle);
00249 db_handle=0;
00250 }
00251 }
00252
00253
00254
00255
00256
00257
00258
00259
00260 int domainpolicy_db_ver(const str* db_url, const str* name)
00261 {
00262 int ver;
00263 db_con_t* dbh;
00264
00265 if (domainpolicy_dbf.init==0){
00266 LM_CRIT("unbound database\n");
00267 return -1;
00268 }
00269 dbh=domainpolicy_dbf.init(db_url);
00270 if (dbh==0){
00271 LM_CRIT("null database handler\n");
00272 return -1;
00273 }
00274 ver=db_table_version(&domainpolicy_dbf, dbh, name);
00275 domainpolicy_dbf.close(dbh);
00276 return ver;
00277 }
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293 static inline int parse_naptr_regexp(char* first, int len, str* pattern,
00294 str* replacement)
00295 {
00296 char *second, *third;
00297
00298 if (len > 0) {
00299 if (*first == '!') {
00300 second = (char *)memchr((void *)(first + 1), '!', len - 1);
00301 if (second) {
00302 len = len - (second - first + 1);
00303 if (len > 0) {
00304 third = memchr(second + 1, '!', len);
00305 if (third) {
00306 pattern->len = second - first - 1;
00307 pattern->s = first + 1;
00308 replacement->len = third - second - 1;
00309 replacement->s = second + 1;
00310 return 1;
00311 } else {
00312 LM_ERR("third ! missing from regexp\n");
00313 return -1;
00314 }
00315 } else {
00316 LM_ERR("third ! missing from regexp\n");
00317 return -2;
00318 }
00319 } else {
00320 LM_ERR("second ! missing from regexp\n");
00321 return -3;
00322 }
00323 } else {
00324 LM_ERR("first ! missing from regexp\n");
00325 return -4;
00326 }
00327 } else {
00328 LM_ERR("regexp missing\n");
00329 return -5;
00330 }
00331 }
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343 static inline int naptr_greater(struct rdata* a, struct rdata* b)
00344 {
00345 struct naptr_rdata *na, *nb;
00346
00347 if (a->type != T_NAPTR) return 1;
00348 if (b->type != T_NAPTR) return 0;
00349
00350 na = (struct naptr_rdata*)a->rdata;
00351 if (na == 0) return 1;
00352
00353 nb = (struct naptr_rdata*)b->rdata;
00354 if (nb == 0) return 0;
00355
00356 if (!IS_D2PNAPTR(na))
00357 return 1;
00358
00359 if (!IS_D2PNAPTR(nb))
00360 return 0;
00361
00362
00363 return (((na->order) << 16) + na->pref) >
00364 (((nb->order) << 16) + nb->pref);
00365 }
00366
00367
00368
00369
00370
00371 static inline void naptr_sort(struct rdata** head)
00372 {
00373 struct rdata *p, *q, *r, *s, *temp, *start;
00374
00375
00376
00377
00378 s = NULL;
00379 start = *head;
00380 while ( s != start -> next ) {
00381 r = p = start ;
00382 q = p -> next ;
00383 while ( p != s ) {
00384 if ( naptr_greater(p, q) ) {
00385 if ( p == start ) {
00386 temp = q -> next ;
00387 q -> next = p ;
00388 p -> next = temp ;
00389 start = q ;
00390 r = q ;
00391 } else {
00392 temp = q -> next ;
00393 q -> next = p ;
00394 p -> next = temp ;
00395 r -> next = q ;
00396 r = q ;
00397 }
00398 } else {
00399 r = p ;
00400 p = p -> next ;
00401 }
00402 q = p -> next ;
00403 if ( q == s ) s = p ;
00404 }
00405 }
00406 *head = start;
00407 }
00408
00409
00410
00411
00412
00413
00414
00415
00416 static int check_rule(str *rule, char *service, int service_len, struct avp_stack *stack) {
00417
00418
00419 db_key_t keys[2];
00420 db_val_t vals[2];
00421 db_key_t cols[4];
00422 db_res_t* res;
00423 db_row_t* row;
00424 db_val_t* val;
00425 int i;
00426 char *type;
00427 int type_len;
00428
00429 LM_INFO("checking for '%.*s'.\n", rule->len, ZSW(rule->s));
00430
00431 if ((service_len != 11) || (strncasecmp("d2p+sip:fed", service, 11) &&
00432 strncasecmp("d2p+sip:std", service, 11) && strncasecmp("d2p+sip:dom", service, 11))) {
00433 LM_ERR("can only cope with d2p+sip:fed, d2p+sip:std,and d2p+sip:dom "
00434 "for now (and not %.*s).\n", service_len, service);
00435 return(0);
00436 }
00437
00438 type = service + 8;
00439 type_len = service_len - 8;
00440
00441 if (domainpolicy_dbf.use_table(db_handle, &domainpolicy_table) < 0) {
00442 LM_ERR("failed to domainpolicy table\n");
00443 return -1;
00444 }
00445
00446 keys[0]=&domainpolicy_col_rule;
00447 keys[1]=&domainpolicy_col_type;
00448 cols[0]=&domainpolicy_col_rule;
00449 cols[1]=&domainpolicy_col_type;
00450 cols[2]=&domainpolicy_col_att;
00451 cols[3]=&domainpolicy_col_val;
00452
00453 VAL_TYPE(&vals[0]) = DB_STR;
00454 VAL_NULL(&vals[0]) = 0;
00455 VAL_STR(&vals[0]).s = rule->s;
00456 VAL_STR(&vals[0]).len = rule->len;
00457
00458 VAL_TYPE(&vals[1]) = DB_STR;
00459 VAL_NULL(&vals[1]) = 0;
00460 VAL_STR(&vals[1]).s = type;
00461 VAL_STR(&vals[1]).len = type_len;
00462
00463
00464
00465
00466
00467 if (domainpolicy_dbf.query(db_handle, keys, 0, vals, cols, 2, 4, 0, &res) < 0
00468 ) {
00469 LM_ERR("querying database\n");
00470 return -1;
00471 }
00472
00473 LM_INFO("querying database OK\n");
00474
00475 if (RES_ROW_N(res) == 0) {
00476 LM_DBG("rule '%.*s' is not know.\n",
00477 rule->len, ZSW(rule->s));
00478 domainpolicy_dbf.free_result(db_handle, res);
00479 return 0;
00480 } else {
00481 LM_DBG("rule '%.*s' is known\n", rule->len, ZSW(rule->s));
00482
00483 row = RES_ROWS(res);
00484
00485 for(i = 0; i < RES_ROW_N(res); i++) {
00486 if (ROW_N(row + i) != 4) {
00487 LM_ERR("unexpected cell count\n");
00488 return(-1);
00489 }
00490
00491 val = ROW_VALUES(row + i);
00492
00493 if ((VAL_TYPE(val) != DB_STRING) ||
00494 (VAL_TYPE(val+1) != DB_STRING) ||
00495 (VAL_TYPE(val+2) != DB_STRING) ||
00496 (VAL_TYPE(val+3) != DB_STRING)) {
00497 LM_ERR("unexpected cell types\n");
00498 return(-1);
00499 }
00500
00501 if (VAL_NULL(val+2) || VAL_NULL(val+3)) {
00502 LM_INFO("db returned NULL values. Fine with us.\n");
00503 continue;
00504 }
00505
00506 LM_INFO("DB returned %s/%s \n",VAL_STRING(val+2),VAL_STRING(val+3));
00507
00508
00509 if (!stack_push(stack, (char *) VAL_STRING(val+2),
00510 (char *) VAL_STRING(val+3))) {
00511 return(-1);
00512 }
00513 }
00514 domainpolicy_dbf.free_result(db_handle, res);
00515 return 1;
00516 }
00517 }
00518
00519 int dp_can_connect_str(str *domain, int rec_level) {
00520 struct rdata* head;
00521 struct rdata* l;
00522 struct naptr_rdata* naptr;
00523 struct naptr_rdata* next_naptr;
00524 int ret;
00525 str newdomain;
00526 char uri[MAX_URI_SIZE];
00527 struct avp_stack stack;
00528 int last_order = -1;
00529 int failed = 0;
00530 int found_anything = 0;
00531
00532 str pattern, replacement, result;
00533
00534 stack_reset(&stack);
00535
00536 if ( rec_level > 0 ) {
00537 stack_push(&stack, domain_replacement_name.s.s, domain->s);
00538 stack.succeeded = 0;
00539 }
00540
00541 if (rec_level > MAX_DDDS_RECURSIONS) {
00542 LM_ERR("too many indirect NAPTRs. Aborting at %.*s.\n", domain->len,
00543 ZSW(domain->s));
00544 return(DP_DDDS_RET_DNSERROR);
00545 }
00546
00547 LM_INFO("looking up Domain itself: %.*s\n",domain->len, ZSW(domain->s));
00548 ret = check_rule(domain,"D2P+sip:dom", 11, &stack);
00549
00550 if (ret == 1) {
00551 LM_INFO("found a match on domain itself\n");
00552 stack_to_avp(&stack);
00553 return(DP_DDDS_RET_POSITIVE);
00554 } else if (ret == 0) {
00555 LM_INFO("no match on domain itself.\n");
00556 stack_reset(&stack);
00557
00558 if ( rec_level > 0 ) {
00559 stack_push(&stack, domain_replacement_name.s.s, (char *) domain->s);
00560 stack.succeeded = 0;
00561 }
00562 } else {
00563 return(DP_DDDS_RET_DNSERROR);
00564 }
00565
00566 LM_INFO("doing DDDS with %.*s\n",domain->len, ZSW(domain->s));
00567 head = get_record(domain->s, T_NAPTR);
00568 if (head == 0) {
00569 LM_NOTICE("no NAPTR record found for %.*s.\n",
00570 domain->len, ZSW(domain->s));
00571 return(DP_DDDS_RET_NOTFOUND);
00572 }
00573
00574 LM_DBG("found the following NAPTRs: \n");
00575 for (l = head; l; l = l->next) {
00576 if (l->type != T_NAPTR) {
00577 LM_DBG("found non-NAPTR record.\n");
00578 continue;
00579 }
00580 naptr = (struct naptr_rdata*)l->rdata;
00581 if (naptr == 0) {
00582 LM_CRIT("null rdata\n");
00583 continue;
00584 }
00585 LM_DBG("order %u, pref %u, flen %u, flags '%.*s', slen %u, "
00586 "services '%.*s', rlen %u, regexp '%.*s', repl '%s'\n",
00587 naptr->order, naptr->pref,
00588 naptr->flags_len, (int)(naptr->flags_len), ZSW(naptr->flags),
00589 naptr->services_len,
00590 (int)(naptr->services_len), ZSW(naptr->services), naptr->regexp_len,
00591 (int)(naptr->regexp_len), ZSW(naptr->regexp),
00592 ZSW(naptr->repl)
00593 );
00594 }
00595
00596
00597 LM_DBG("sorting...\n");
00598 naptr_sort(&head);
00599
00600 for (l = head; l; l = l->next) {
00601
00602 if (l->type != T_NAPTR) continue;
00603 naptr = (struct naptr_rdata*)l->rdata;
00604 if (naptr == 0) {
00605 LM_CRIT("null rdata\n");
00606 continue;
00607 }
00608
00609 LM_DBG("considering order %u, pref %u, flen %u, flags '%.*s', slen %u, "
00610 "services '%.*s', rlen %u, regexp '%.*s', repl '%s'\n",
00611 naptr->order, naptr->pref,
00612 naptr->flags_len, (int)(naptr->flags_len), ZSW(naptr->flags),
00613 naptr->services_len,
00614 (int)(naptr->services_len), ZSW(naptr->services), naptr->regexp_len,
00615 (int)(naptr->regexp_len), ZSW(naptr->regexp),
00616 ZSW(naptr->repl)
00617 );
00618
00619
00620
00621
00622
00623 if (last_order != naptr->order) {
00624 last_order = naptr->order;
00625 failed = 0;
00626
00627 if (stack_succeeded(&stack)) {
00628 LM_INFO("we don't need to consider further orders "
00629 "(starting with %d).\n",last_order);
00630 break;
00631 }
00632 } else if (failed) {
00633 LM_INFO("order %d has already failed.\n",last_order);
00634 continue;
00635 }
00636
00637
00638
00639
00640
00641 if (!IS_D2PNAPTR(naptr))
00642 continue;
00643
00644
00645
00646
00647 found_anything = 1;
00648
00649 next_naptr = NULL;
00650 if (l->next && (l->next->type == T_NAPTR)) {
00651 next_naptr = (struct naptr_rdata*)l->next->rdata;
00652 }
00653
00654
00655
00656
00657 if ((naptr->services_len == 7) && !strncasecmp("D2P+SIP", naptr->services,7) && (naptr->flags_len == 0)){
00658 LM_INFO("found non-terminal NAPTR\n");
00659
00660
00661
00662
00663 if (next_naptr && (next_naptr->order == naptr->order) && IS_D2PNAPTR(next_naptr)) {
00664 LM_ERR("non-terminal NAPTR needs to be the only one "
00665 "with this order %.*s.\n", domain->len, ZSW(domain->s));
00666
00667 return(DP_DDDS_RET_DNSERROR);
00668 }
00669
00670 newdomain.s = naptr->repl;
00671 newdomain.len = strlen(naptr->repl);
00672
00673 ret = dp_can_connect_str(&newdomain, rec_level + 1);
00674
00675 if (ret == DP_DDDS_RET_POSITIVE)
00676 return(ret);
00677
00678 if (ret == DP_DDDS_RET_NEGATIVE)
00679 continue;
00680
00681 if (ret == DP_DDDS_RET_DNSERROR)
00682 return(ret);
00683
00684 if (ret == DP_DDDS_RET_NOTFOUND)
00685 return(ret);
00686
00687 continue;
00688 }
00689
00690
00691
00692
00693 if ((naptr->flags_len != 1) || (tolower(naptr->flags[0]) != 'u')) {
00694 LM_ERR("terminal NAPTR needs flag = 'u' and not '%.*s'.\n",
00695 (int)naptr->flags_len, ZSW(naptr->flags));
00696
00697
00698
00699
00700 continue;
00701 }
00702
00703 if (parse_naptr_regexp(&(naptr->regexp[0]), naptr->regexp_len,
00704 &pattern, &replacement) < 0) {
00705 LM_ERR("parsing of NAPTR regexp failed\n");
00706 continue;
00707 }
00708 result.s = &(uri[0]);
00709 result.len = MAX_URI_SIZE;
00710
00711
00712 pattern.s[pattern.len] = (char)0;
00713 replacement.s[replacement.len] = (char)0;
00714 if (reg_replace(pattern.s, replacement.s, domain->s,
00715 &result) < 0) {
00716 pattern.s[pattern.len] = '!';
00717 replacement.s[replacement.len] = '!';
00718 LM_ERR("regexp replace failed\n");
00719 continue;
00720 }
00721 LM_INFO("resulted in replacement: '%.*s'\n", result.len, ZSW(result.s));
00722 pattern.s[pattern.len] = '!';
00723 replacement.s[replacement.len] = '!';
00724
00725 ret = check_rule(&result,naptr->services,naptr->services_len, &stack);
00726
00727 if (ret == 1) {
00728 LM_INFO("positive return\n");
00729 } else if (ret == 0) {
00730 LM_INFO("check_rule failed.\n");
00731 stack_reset(&stack);
00732
00733 if ( rec_level > 0 ) {
00734 stack_push(&stack, domain_replacement_name.s.s, (char *) domain->s);
00735 stack.succeeded = 0;
00736 }
00737 failed = 1;
00738 } else {
00739 return(DP_DDDS_RET_DNSERROR);
00740 }
00741 }
00742
00743 if (stack_succeeded(&stack)) {
00744 LM_INFO("calling stack_to_avp.\n");
00745 stack_to_avp(&stack);
00746 return(DP_DDDS_RET_POSITIVE);
00747 }
00748
00749 LM_INFO("returning %d.\n",
00750 (found_anything ? DP_DDDS_RET_NEGATIVE : DP_DDDS_RET_NOTFOUND));
00751 return( found_anything ? DP_DDDS_RET_NEGATIVE : DP_DDDS_RET_NOTFOUND );
00752 }
00753
00754
00755
00756
00757
00758
00759
00760
00761
00762 int dp_can_connect(struct sip_msg* _msg, char* _s1, char* _s2) {
00763
00764 static char domainname[MAX_DOMAIN_SIZE];
00765 str domain;
00766 int ret;
00767
00768 if (route_type != REQUEST_ROUTE) {
00769 LM_ERR("unsupported route type\n");
00770 return -1;
00771 }
00772
00773 if (parse_sip_msg_uri(_msg) < 0) {
00774 LM_ERR("failed to parse R-URI\n");
00775 return -1;
00776 }
00777
00778 if (_msg->parsed_uri.host.len >= MAX_DOMAIN_SIZE) {
00779 LM_ERR("domain buffer to small\n");
00780 return -1;
00781 }
00782
00783
00784
00785
00786 domain.s = (char *) &(domainname[0]);
00787 domain.len = _msg->parsed_uri.host.len;
00788 memcpy(domain.s, _msg->parsed_uri.host.s, domain.len);
00789 domainname[domain.len] = '\0';
00790
00791 LM_DBG("domain is %.*s.\n", domain.len, ZSW(domain.s));
00792
00793 ret = dp_can_connect_str(&domain,0);
00794 LM_DBG("returning %d.\n", ret);
00795 return(ret);
00796 }
00797
00798
00799
00800
00801
00802
00803
00804
00805
00806
00807
00808
00809
00810
00811 int dp_apply_policy(struct sip_msg* _msg, char* _s1, char* _s2) {
00812
00813 str *domain;
00814 int_str val;
00815 struct usr_avp *avp;
00816
00817 char duri[MAX_URI_SIZE];
00818 str duri_str;
00819 int len, didsomething;
00820 char *at;
00821
00822 str host;
00823 int port, proto;
00824 struct socket_info* si;
00825
00826 if (route_type != REQUEST_ROUTE) {
00827 LM_ERR("unsupported route type\n");
00828 return -1;
00829 }
00830
00831
00832
00833
00834
00835
00836 avp = search_first_avp(send_socket_avp_name_str, send_socket_name, &val, 0);
00837 if (avp) {
00838 if ( !(avp->flags&AVP_VAL_STR) || !val.s.s || !val.s.len) {
00839 LM_ERR("empty or non-string send_socket_avp, "
00840 "return with error ...\n");
00841 return -1;
00842 }
00843 LM_DBG("send_socket_avp found = '%.*s'\n", val.s.len, ZSW(val.s.s));
00844
00845 if (parse_phostport(val.s.s, val.s.len, &(host.s), &(host.len), &port, &proto)) {
00846 LM_ERR("could not parse send_socket, return with error ...\n");
00847 return -1;
00848 }
00849 si = grep_sock_info( &host, (unsigned short) port, (unsigned short) proto);
00850 if (si) {
00851 _msg->force_send_socket = si;
00852 } else {
00853 LM_WARN("could not find socket for"
00854 "send_socket '%.*s'\n", val.s.len, ZSW(val.s.s));
00855 }
00856 } else {
00857 LM_DBG("send_socket_avp not found\n");
00858 }
00859
00860
00861
00862
00863
00864 didsomething = 0;
00865
00866 if (parse_sip_msg_uri(_msg) < 0) {
00867 LM_ERR("failed to parse R-URI\n");
00868 return -1;
00869 }
00870
00871 at = (char *)&(duri[0]);
00872 len = 0;
00873 if ( (len + 4) > MAX_URI_SIZE) {
00874 LM_ERR("duri buffer to small to add uri schema\n");
00875 return -1;
00876 }
00877 memcpy(at, "sip:", 4); at = at + 4; len = len + 4;
00878
00879 domain = &(_msg->parsed_uri.host);
00880 LM_DBG("domain is %.*s.\n", domain->len, ZSW(domain->s));
00881
00882
00883 avp = search_first_avp(domain_prefix_avp_name_str, domain_prefix_name, &val, 0);
00884 if (avp) {
00885 if ( !(avp->flags&AVP_VAL_STR) || !val.s.s || !val.s.len) {
00886 LM_ERR("empty or non-string domain_prefix_avp, return with error ...\n");
00887 return -1;
00888 }
00889 LM_DBG("domain_prefix_avp found = '%.*s'\n", val.s.len, ZSW(val.s.s));
00890 if ( (len + val.s.len +1) > MAX_URI_SIZE) {
00891 LM_ERR("duri buffer to small to add domain prefix\n");
00892 return -1;
00893 }
00894 memcpy(at, val.s.s, val.s.len); at = at + val.s.len;
00895 *at = '.'; at = at + 1;
00896 didsomething = 1;
00897 } else {
00898 LM_DBG("domain_prefix_avp not found\n");
00899 }
00900
00901
00902
00903 avp = search_first_avp(domain_replacement_avp_name_str, domain_replacement_name, &val, 0);
00904 if (avp) {
00905 if ( !(avp->flags&AVP_VAL_STR) || !val.s.s || !val.s.len) {
00906 LM_ERR("empty or non-string domain_replacement_avp, return with"
00907 "error ...\n");
00908 return -1;
00909 }
00910 LM_DBG("domain_replacement_avp found='%.*s'\n",val.s.len, ZSW(val.s.s));
00911 if ( (len + val.s.len +1) > MAX_URI_SIZE) {
00912 LM_ERR("duri buffer to small to add domain replacement\n");
00913 return -1;
00914 }
00915 memcpy(at, val.s.s, val.s.len); at = at + val.s.len;
00916 didsomething = 1;
00917 } else {
00918 LM_DBG("domain_replacement_avp not found, using original domain '"
00919 "%.*s'\n",domain->len, domain->s);
00920 if ( (len + domain->len) > MAX_URI_SIZE) {
00921 LM_ERR("duri buffer to small to add domain\n");
00922 return -1;
00923 }
00924 memcpy(at, domain->s, domain->len); at = at + domain->len;
00925 }
00926
00927
00928 avp = search_first_avp(domain_suffix_avp_name_str, domain_suffix_name, &val, 0);
00929 if (avp) {
00930 if ( !(avp->flags&AVP_VAL_STR) || !val.s.s || !val.s.len) {
00931 LM_ERR("empty or non-string domain_suffix_avp,return with error .."
00932 "\n");
00933 return -1;
00934 }
00935 LM_DBG("domain_suffix_avp found = '%.*s'\n", val.s.len, ZSW(val.s.s));
00936 if ( (len + val.s.len + 1) > MAX_URI_SIZE) {
00937 LM_ERR("duri buffer to small to add domain suffix\n");
00938 return -1;
00939 }
00940 *at = '.'; at = at + 1;
00941 memcpy(at, val.s.s, val.s.len); at = at + val.s.len;
00942 didsomething = 1;
00943 } else {
00944 LM_DBG("domain_suffix_avp not found\n");
00945 }
00946
00947
00948 avp = search_first_avp(port_override_avp_name_str, port_override_name, &val, 0);
00949 if (avp) {
00950 if ( !(avp->flags&AVP_VAL_STR) || !val.s.s || !val.s.len) {
00951 LM_ERR("empty or non-string port_override_avp, return with error ...\n");
00952 return -1;
00953 }
00954 LM_DBG("port_override_avp found = '%.*s'\n", val.s.len, ZSW(val.s.s));
00955
00956 if ( (len + val.s.len + 1) > MAX_URI_SIZE) {
00957 LM_ERR("duri buffer to small to add domain suffix\n");
00958 return -1;
00959 }
00960 *at = ':'; at = at + 1;
00961 memcpy(at, val.s.s, val.s.len); at = at + val.s.len;
00962 didsomething = 1;
00963 } else {
00964 LM_DBG("port_override_avp not found, using original port\n");
00965 if (_msg->parsed_uri.port.len) {
00966 LM_DBG("port found in RURI, reusing it for DURI\n");
00967 if ( (len + _msg->parsed_uri.port.len + 1) > MAX_URI_SIZE) {
00968 LM_ERR("duri buffer to small to copy port\n");
00969 return -1;
00970 }
00971 *at = ':'; at = at + 1;
00972
00973 memcpy(at, _msg->parsed_uri.port.s, _msg->parsed_uri.port.len);
00974 at = at + _msg->parsed_uri.port.len;
00975 } else {
00976 LM_DBG("port not found in RURI, no need to copy it to DURI\n");
00977 }
00978 }
00979
00980
00981 avp = search_first_avp(transport_override_avp_name_str, transport_override_name, &val, 0);
00982 if (avp) {
00983 if ( !(avp->flags&AVP_VAL_STR) || !val.s.s || !val.s.len) {
00984 LM_ERR("empty or non-string transport_override_avp, "
00985 "return with error ...\n");
00986 return -1;
00987 }
00988 LM_DBG("transport_override_avp found='%.*s'\n",val.s.len, ZSW(val.s.s));
00989
00990 if ( (len + val.s.len + 11) > MAX_URI_SIZE) {
00991 LM_ERR("duri buffer to small to add transport override\n");
00992 return -1;
00993 }
00994
00995 memcpy(at, ";transport=", 11); at = at + 11;
00996 memcpy(at, val.s.s, val.s.len); at = at + val.s.len;
00997 didsomething = 1;
00998 } else {
00999 LM_DBG("transport_override_avp not found, using original transport\n");
01000 if (_msg->parsed_uri.transport.len) {
01001 LM_DBG("transport found in RURI, reusing it for DURI\n");
01002 if ( (len + _msg->parsed_uri.transport.len + 1) > MAX_URI_SIZE) {
01003 LM_ERR("duri buffer to small to copy transport\n");
01004 return -1;
01005 }
01006 *at = ';'; at = at + 1;
01007 memcpy(at, _msg->parsed_uri.transport.s, _msg->parsed_uri.transport.len); at = at + _msg->parsed_uri.transport.len;
01008 } else {
01009 LM_DBG("transport not found in RURI, no need to copy it to DURI\n");
01010 }
01011 }
01012
01013
01014 if (didsomething == 0) {
01015 LM_DBG("no domainpolicy AVP set, no need to push new DURI\n");
01016 return 2;
01017 }
01018 duri_str.s = (char *)&(duri[0]);
01019 duri_str.len = at - duri_str.s;
01020 LM_DBG("new DURI is '%.*s'\n",duri_str.len, ZSW(duri_str.s));
01021 set_dst_uri(_msg, &duri_str);
01022
01023 return 1;
01024 }
01025