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
00037 #include "domainpolicy_mod.h"
00038 #include "domainpolicy.h"
00039 #include "../../lib/srdb1/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 "../../lib/kcore/regexp.h"
00050
00051 #define IS_D2PNAPTR(naptr) ((naptr->services_len >= 7) && (!strncasecmp("D2P+SIP", naptr->services, 7)))
00052
00053 static db1_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
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
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
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
00260 int domainpolicy_db_ver(const str* db_url, const str* name)
00261 {
00262 int ver;
00263 db1_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 db1_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]) = DB1_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]) = DB1_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) != DB1_STRING) ||
00494 (VAL_TYPE(val+1) != DB1_STRING) ||
00495 (VAL_TYPE(val+2) != DB1_STRING) ||
00496 (VAL_TYPE(val+3) != DB1_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, RES_ONLY_TYPE);
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
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 (!is_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
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 (!is_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
00846
00847 if (parse_phostport(val.s.s, &(host.s), &(host.len), &port, &proto)) {
00848 LM_ERR("could not parse send_socket, return with error ...\n");
00849 return -1;
00850 }
00851 si = grep_sock_info( &host, (unsigned short) port, (unsigned short) proto);
00852 if (si) {
00853 set_force_socket(_msg, si);
00854 } else {
00855 LM_WARN("could not find socket for"
00856 "send_socket '%.*s'\n", val.s.len, ZSW(val.s.s));
00857 }
00858 } else {
00859 LM_DBG("send_socket_avp not found\n");
00860 }
00861
00862
00863
00864
00865
00866 didsomething = 0;
00867
00868 if (parse_sip_msg_uri(_msg) < 0) {
00869 LM_ERR("failed to parse R-URI\n");
00870 return -1;
00871 }
00872
00873 at = (char *)&(duri[0]);
00874 len = 0;
00875 if ( (len + 4) > MAX_URI_SIZE) {
00876 LM_ERR("duri buffer to small to add uri schema\n");
00877 return -1;
00878 }
00879 memcpy(at, "sip:", 4); at = at + 4; len = len + 4;
00880
00881 domain = &(_msg->parsed_uri.host);
00882 LM_DBG("domain is %.*s.\n", domain->len, ZSW(domain->s));
00883
00884
00885 avp = search_first_avp(domain_prefix_avp_name_str, domain_prefix_name, &val, 0);
00886 if (avp) {
00887 if ( !(avp->flags&AVP_VAL_STR) || !val.s.s || !val.s.len) {
00888 LM_ERR("empty or non-string domain_prefix_avp, return with error ...\n");
00889 return -1;
00890 }
00891 LM_DBG("domain_prefix_avp found = '%.*s'\n", val.s.len, ZSW(val.s.s));
00892 if ( (len + val.s.len +1) > MAX_URI_SIZE) {
00893 LM_ERR("duri buffer to small to add domain prefix\n");
00894 return -1;
00895 }
00896 memcpy(at, val.s.s, val.s.len); at = at + val.s.len;
00897 *at = '.'; at = at + 1;
00898 didsomething = 1;
00899 } else {
00900 LM_DBG("domain_prefix_avp not found\n");
00901 }
00902
00903
00904
00905 avp = search_first_avp(domain_replacement_avp_name_str, domain_replacement_name, &val, 0);
00906 if (avp) {
00907 if ( !(avp->flags&AVP_VAL_STR) || !val.s.s || !val.s.len) {
00908 LM_ERR("empty or non-string domain_replacement_avp, return with"
00909 "error ...\n");
00910 return -1;
00911 }
00912 LM_DBG("domain_replacement_avp found='%.*s'\n",val.s.len, ZSW(val.s.s));
00913 if ( (len + val.s.len +1) > MAX_URI_SIZE) {
00914 LM_ERR("duri buffer to small to add domain replacement\n");
00915 return -1;
00916 }
00917 memcpy(at, val.s.s, val.s.len); at = at + val.s.len;
00918 didsomething = 1;
00919 } else {
00920 LM_DBG("domain_replacement_avp not found, using original domain '"
00921 "%.*s'\n",domain->len, domain->s);
00922 if ( (len + domain->len) > MAX_URI_SIZE) {
00923 LM_ERR("duri buffer to small to add domain\n");
00924 return -1;
00925 }
00926 memcpy(at, domain->s, domain->len); at = at + domain->len;
00927 }
00928
00929
00930 avp = search_first_avp(domain_suffix_avp_name_str, domain_suffix_name, &val, 0);
00931 if (avp) {
00932 if ( !(avp->flags&AVP_VAL_STR) || !val.s.s || !val.s.len) {
00933 LM_ERR("empty or non-string domain_suffix_avp,return with error .."
00934 "\n");
00935 return -1;
00936 }
00937 LM_DBG("domain_suffix_avp found = '%.*s'\n", val.s.len, ZSW(val.s.s));
00938 if ( (len + val.s.len + 1) > MAX_URI_SIZE) {
00939 LM_ERR("duri buffer to small to add domain suffix\n");
00940 return -1;
00941 }
00942 *at = '.'; at = at + 1;
00943 memcpy(at, val.s.s, val.s.len); at = at + val.s.len;
00944 didsomething = 1;
00945 } else {
00946 LM_DBG("domain_suffix_avp not found\n");
00947 }
00948
00949
00950 avp = search_first_avp(port_override_avp_name_str, port_override_name, &val, 0);
00951 if (avp) {
00952 if ( !(avp->flags&AVP_VAL_STR) || !val.s.s || !val.s.len) {
00953 LM_ERR("empty or non-string port_override_avp, return with error ...\n");
00954 return -1;
00955 }
00956 LM_DBG("port_override_avp found = '%.*s'\n", val.s.len, ZSW(val.s.s));
00957
00958 if ( (len + val.s.len + 1) > MAX_URI_SIZE) {
00959 LM_ERR("duri buffer to small to add domain suffix\n");
00960 return -1;
00961 }
00962 *at = ':'; at = at + 1;
00963 memcpy(at, val.s.s, val.s.len); at = at + val.s.len;
00964 didsomething = 1;
00965 } else {
00966 LM_DBG("port_override_avp not found, using original port\n");
00967 if (_msg->parsed_uri.port.len) {
00968 LM_DBG("port found in RURI, reusing it for DURI\n");
00969 if ( (len + _msg->parsed_uri.port.len + 1) > MAX_URI_SIZE) {
00970 LM_ERR("duri buffer to small to copy port\n");
00971 return -1;
00972 }
00973 *at = ':'; at = at + 1;
00974
00975 memcpy(at, _msg->parsed_uri.port.s, _msg->parsed_uri.port.len);
00976 at = at + _msg->parsed_uri.port.len;
00977 } else {
00978 LM_DBG("port not found in RURI, no need to copy it to DURI\n");
00979 }
00980 }
00981
00982
00983 avp = search_first_avp(transport_override_avp_name_str, transport_override_name, &val, 0);
00984 if (avp) {
00985 if ( !(avp->flags&AVP_VAL_STR) || !val.s.s || !val.s.len) {
00986 LM_ERR("empty or non-string transport_override_avp, "
00987 "return with error ...\n");
00988 return -1;
00989 }
00990 LM_DBG("transport_override_avp found='%.*s'\n",val.s.len, ZSW(val.s.s));
00991
00992 if ( (len + val.s.len + 11) > MAX_URI_SIZE) {
00993 LM_ERR("duri buffer to small to add transport override\n");
00994 return -1;
00995 }
00996
00997 memcpy(at, ";transport=", 11); at = at + 11;
00998 memcpy(at, val.s.s, val.s.len); at = at + val.s.len;
00999 didsomething = 1;
01000 } else {
01001 LM_DBG("transport_override_avp not found, using original transport\n");
01002 if (_msg->parsed_uri.transport.len) {
01003 LM_DBG("transport found in RURI, reusing it for DURI\n");
01004 if ( (len + _msg->parsed_uri.transport.len + 1) > MAX_URI_SIZE) {
01005 LM_ERR("duri buffer to small to copy transport\n");
01006 return -1;
01007 }
01008 *at = ';'; at = at + 1;
01009 memcpy(at, _msg->parsed_uri.transport.s, _msg->parsed_uri.transport.len); at = at + _msg->parsed_uri.transport.len;
01010 } else {
01011 LM_DBG("transport not found in RURI, no need to copy it to DURI\n");
01012 }
01013 }
01014
01015
01016 if (didsomething == 0) {
01017 LM_DBG("no domainpolicy AVP set, no need to push new DURI\n");
01018 return 2;
01019 }
01020 duri_str.s = (char *)&(duri[0]);
01021 duri_str.len = at - duri_str.s;
01022 LM_DBG("new DURI is '%.*s'\n",duri_str.len, ZSW(duri_str.s));
01023 set_dst_uri(_msg, &duri_str);
01024
01025
01026 ruri_mark_new();
01027
01028 return 1;
01029 }
01030