00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00035 #include <string.h>
00036 #include "../../mem/mem.h"
00037 #include "../../dprint.h"
00038 #include "../../parser/parse_uri.h"
00039 #include "../../parser/parse_from.h"
00040 #include "../../str.h"
00041 #include "../../data_lump.h"
00042 #include "record.h"
00043 #include "rr_mod.h"
00044
00045
00046 #define RR_PREFIX "Record-Route: <sip:"
00047 #define RR_PREFIX_LEN (sizeof(RR_PREFIX)-1)
00048
00049 #define RR_LR ";lr"
00050 #define RR_LR_LEN (sizeof(RR_LR)-1)
00051
00052 #define RR_LR_FULL ";lr=on"
00053 #define RR_LR_FULL_LEN (sizeof(RR_LR_FULL)-1)
00054
00055 #define RR_FROMTAG ";ftag="
00056 #define RR_FROMTAG_LEN (sizeof(RR_FROMTAG)-1)
00057
00058 #define RR_R2 ";r2=on"
00059 #define RR_R2_LEN (sizeof(RR_R2)-1)
00060
00061 #define RR_TERM ">"CRLF
00062 #define RR_TERM_LEN (sizeof(RR_TERM)-1)
00063
00064 #define INBOUND 1
00065 #define OUTBOUND 0
00067 #define RR_PARAM_BUF_SIZE 512
00074 static char rr_param_buf_ptr[RR_PARAM_BUF_SIZE];
00075 static str rr_param_buf = {rr_param_buf_ptr,0};
00076 static unsigned int rr_param_msg;
00077
00078
00088 static inline int get_username(struct sip_msg* _m, str* _user)
00089 {
00090 struct sip_uri puri;
00091
00092
00093 if (parse_uri(_m->first_line.u.request.uri.s, _m->first_line.u.request.uri.len, &puri) < 0) {
00094 LM_ERR("failed to parse R-URI\n");
00095 return -1;
00096 }
00097
00098
00099
00100
00101
00102
00103 if (!puri.user.len && _m->new_uri.s) {
00104 if (parse_uri(_m->new_uri.s, _m->new_uri.len, &puri) < 0) {
00105 LM_ERR("failed to parse new_uri\n");
00106 return -2;
00107 }
00108 }
00109
00110 _user->s = puri.user.s;
00111 _user->len = puri.user.len;
00112 return 0;
00113 }
00114
00115
00123 static inline struct lump *insert_rr_param_lump(struct lump *before,
00124 char *s, int l)
00125 {
00126 struct lump *rrp_l;
00127 char *s1;
00128
00129
00130 s1 = (char*)pkg_malloc(l);
00131 if (s1==0) {
00132 LM_ERR("no more pkg mem (%d)\n",l);
00133 return 0;
00134 }
00135 memcpy( s1, s, l);
00136
00137
00138 rrp_l = insert_new_lump_before( before, s1, l, HDR_RECORDROUTE_T);
00139 if (rrp_l==0) {
00140 LM_ERR("failed to add before lump\n");
00141 pkg_free(s1);
00142 return 0;
00143 }
00144 return rrp_l;
00145 }
00146
00147
00160 static inline int build_rr(struct lump* _l, struct lump* _l2, str* user,
00161 str *tag, str *params, int _inbound)
00162 {
00163 char* prefix, *suffix, *term, *r2;
00164 int suffix_len, prefix_len;
00165 char *p;
00166
00167 prefix_len = RR_PREFIX_LEN + (user->len ? (user->len + 1) : 0);
00168 if (enable_full_lr) {
00169 suffix_len = RR_LR_FULL_LEN + (params?params->len:0) +
00170 ((tag && tag->len) ? (RR_FROMTAG_LEN + tag->len) : 0);
00171 } else {
00172 suffix_len = RR_LR_LEN + (params?params->len:0) +
00173 ((tag && tag->len) ? (RR_FROMTAG_LEN + tag->len) : 0);
00174 }
00175
00176 prefix = pkg_malloc(prefix_len);
00177 suffix = pkg_malloc(suffix_len);
00178 term = pkg_malloc(RR_TERM_LEN);
00179 r2 = pkg_malloc(RR_R2_LEN);
00180
00181 if (!prefix || !suffix || !term || !r2) {
00182 LM_ERR("No more pkg memory\n");
00183 if (suffix) pkg_free(suffix);
00184 if (prefix) pkg_free(prefix);
00185 if (term) pkg_free(term);
00186 if (r2) pkg_free(r2);
00187 return -3;
00188 }
00189
00190 memcpy(prefix, RR_PREFIX, RR_PREFIX_LEN);
00191 if (user->len) {
00192 memcpy(prefix + RR_PREFIX_LEN, user->s, user->len);
00193 #ifdef ENABLE_USER_CHECK
00194
00195 if(i_user.len && i_user.len == user->len &&
00196 !strncmp(i_user.s, user->s, i_user.len))
00197 {
00198 if(prefix[RR_PREFIX_LEN]=='x')
00199 prefix[RR_PREFIX_LEN]='y';
00200 else
00201 prefix[RR_PREFIX_LEN]='x';
00202 }
00203 #endif
00204 prefix[RR_PREFIX_LEN + user->len] = '@';
00205 }
00206
00207 p = suffix;
00208 if (enable_full_lr) {
00209 memcpy( p, RR_LR_FULL, RR_LR_FULL_LEN);
00210 p += RR_LR_FULL_LEN;
00211 } else {
00212 memcpy( p, RR_LR, RR_LR_LEN);
00213 p += RR_LR_LEN;
00214 }
00215 if (tag && tag->len) {
00216 memcpy(p, RR_FROMTAG, RR_FROMTAG_LEN);
00217 p += RR_FROMTAG_LEN;
00218 memcpy(p, tag->s, tag->len);
00219 p += tag->len;
00220 }
00221 if (params && params->len) {
00222 memcpy(p, params->s, params->len);
00223 p += params->len;
00224 }
00225
00226 memcpy(term, RR_TERM, RR_TERM_LEN);
00227 memcpy(r2, RR_R2, RR_R2_LEN);
00228
00229 if (!(_l = insert_new_lump_after(_l, prefix, prefix_len, 0)))
00230 goto lump_err;
00231 prefix = 0;
00232 _l = insert_subst_lump_after(_l, _inbound?SUBST_RCV_ALL:SUBST_SND_ALL, 0);
00233 if (_l ==0 )
00234 goto lump_err;
00235 if (enable_double_rr) {
00236 if (!(_l = insert_cond_lump_after(_l, COND_IF_DIFF_REALMS, 0)))
00237 goto lump_err;
00238 if (!(_l = insert_new_lump_after(_l, r2, RR_R2_LEN, 0)))
00239 goto lump_err;
00240 r2 = 0;
00241 } else {
00242 pkg_free(r2);
00243 r2 = 0;
00244 }
00245 _l2 = insert_new_lump_before(_l2, suffix, suffix_len, HDR_RECORDROUTE_T);
00246 if (_l2 == 0)
00247 goto lump_err;
00248 if (rr_param_buf.len) {
00249 _l2 = insert_rr_param_lump(_l2, rr_param_buf.s, rr_param_buf.len);
00250 if (_l2 == 0)
00251 goto lump_err;
00252 }
00253 suffix = 0;
00254 if (!(_l2 = insert_new_lump_before(_l2, term, RR_TERM_LEN, 0)))
00255 goto lump_err;
00256 term = 0;
00257 return 0;
00258
00259 lump_err:
00260 LM_ERR("failed to insert lumps\n");
00261 if (prefix) pkg_free(prefix);
00262 if (suffix) pkg_free(suffix);
00263 if (r2) pkg_free(r2);
00264 if (term) pkg_free(term);
00265 return -4;
00266 }
00267
00268
00278 int record_route(struct sip_msg* _m, str *params)
00279 {
00280 struct lump* l, *l2;
00281 str user;
00282 struct to_body* from = NULL;
00283 str* tag;
00284
00285 user.len = 0;
00286
00287 if (add_username) {
00288 if (get_username(_m, &user) < 0) {
00289 LM_ERR("failed to extract username\n");
00290 return -1;
00291 }
00292 }
00293
00294 if (append_fromtag) {
00295 if (parse_from_header(_m) < 0) {
00296 LM_ERR("From parsing failed\n");
00297 return -2;
00298 }
00299 from = (struct to_body*)_m->from->parsed;
00300 tag = &from->tag_value;
00301 } else {
00302 tag = 0;
00303 }
00304
00305 if (rr_param_buf.len && rr_param_msg!=_m->id) {
00306
00307 rr_param_buf.len = 0;
00308 }
00309
00310 if (enable_double_rr) {
00311 l = anchor_lump(_m, _m->headers->name.s - _m->buf,0,HDR_RECORDROUTE_T);
00312 l2 = anchor_lump(_m, _m->headers->name.s - _m->buf, 0, 0);
00313 if (!l || !l2) {
00314 LM_ERR("failed to create an anchor\n");
00315 return -5;
00316 }
00317 l = insert_cond_lump_after(l, COND_IF_DIFF_REALMS, 0);
00318 l2 = insert_cond_lump_before(l2, COND_IF_DIFF_REALMS, 0);
00319 if (!l || !l2) {
00320 LM_ERR("failed to insert conditional lump\n");
00321 return -6;
00322 }
00323 if (build_rr(l, l2, &user, tag, params, OUTBOUND) < 0) {
00324 LM_ERR("failed to insert outbound Record-Route\n");
00325 return -7;
00326 }
00327 }
00328
00329 l = anchor_lump(_m, _m->headers->name.s - _m->buf, 0, HDR_RECORDROUTE_T);
00330 l2 = anchor_lump(_m, _m->headers->name.s - _m->buf, 0, 0);
00331 if (!l || !l2) {
00332 LM_ERR("failed to create an anchor\n");
00333 return -3;
00334 }
00335
00336 if (build_rr(l, l2, &user, tag, params, INBOUND) < 0) {
00337 LM_ERR("failed to insert inbound Record-Route\n");
00338 return -4;
00339 }
00340
00341
00342 rr_param_buf.len = 0;
00343 return 0;
00344 }
00345
00346
00357 int record_route_preset(struct sip_msg* _m, str* _data)
00358 {
00359 str user;
00360 struct to_body* from;
00361 struct lump* l;
00362 char* hdr, *p;
00363 int hdr_len;
00364
00365 from = 0;
00366 user.len = 0;
00367 user.s = 0;
00368
00369 if (add_username) {
00370 if (get_username(_m, &user) < 0) {
00371 LM_ERR("failed to extract username\n");
00372 return -1;
00373 }
00374 }
00375
00376 if (append_fromtag) {
00377 if (parse_from_header(_m) < 0) {
00378 LM_ERR("From parsing failed\n");
00379 return -2;
00380 }
00381 from = (struct to_body*)_m->from->parsed;
00382 }
00383
00384 l = anchor_lump(_m, _m->headers->name.s - _m->buf, 0, HDR_RECORDROUTE_T);
00385 if (!l) {
00386 LM_ERR("failed to create lump anchor\n");
00387 return -3;
00388 }
00389
00390 hdr_len = RR_PREFIX_LEN;
00391 if (user.len)
00392 hdr_len += user.len + 1;
00393 hdr_len += _data->len;
00394
00395 if (append_fromtag && from->tag_value.len) {
00396 hdr_len += RR_FROMTAG_LEN + from->tag_value.len;
00397 }
00398
00399 if (enable_full_lr) {
00400 hdr_len += RR_LR_FULL_LEN;
00401 } else {
00402 hdr_len += RR_LR_LEN;
00403 }
00404
00405 hdr_len += RR_TERM_LEN;
00406
00407 hdr = pkg_malloc(hdr_len);
00408 if (!hdr) {
00409 LM_ERR("no pkg memory left\n");
00410 return -4;
00411 }
00412
00413 p = hdr;
00414 memcpy(p, RR_PREFIX, RR_PREFIX_LEN);
00415 p += RR_PREFIX_LEN;
00416
00417 if (user.len) {
00418 memcpy(p, user.s, user.len);
00419 p += user.len;
00420 *p = '@';
00421 p++;
00422 }
00423
00424 memcpy(p, _data->s, _data->len);
00425 p += _data->len;
00426
00427 if (append_fromtag && from->tag_value.len) {
00428 memcpy(p, RR_FROMTAG, RR_FROMTAG_LEN);
00429 p += RR_FROMTAG_LEN;
00430 memcpy(p, from->tag_value.s, from->tag_value.len);
00431 p += from->tag_value.len;
00432 }
00433
00434 if (enable_full_lr) {
00435 memcpy(p, RR_LR_FULL, RR_LR_FULL_LEN);
00436 p += RR_LR_FULL_LEN;
00437 } else {
00438 memcpy(p, RR_LR, RR_LR_LEN);
00439 p += RR_LR_LEN;
00440 }
00441
00442 memcpy(p, RR_TERM, RR_TERM_LEN);
00443
00444 if (!insert_new_lump_after(l, hdr, hdr_len, 0)) {
00445 LM_ERR("failed to insert new lump\n");
00446 pkg_free(hdr);
00447 return -5;
00448 }
00449 return 1;
00450 }
00451
00463 #define RR_TRANS_LEN 11
00464 #define RR_TRANS ";transport="
00465 static inline int build_advertised_rr(struct lump* _l, struct lump* _l2, str *_data,
00466 str* user, str *tag, int _inbound)
00467 {
00468 char *p;
00469 char *hdr, *trans, *r2, *suffix, *term;
00470 int hdr_len, suffix_len;
00471
00472 hdr_len = RR_PREFIX_LEN;
00473 if (user && user->len)
00474 hdr_len += user->len + 1;
00475 hdr_len += _data->len;
00476
00477 suffix_len = 0;
00478 if (tag && tag->len) {
00479 suffix_len += RR_FROMTAG_LEN + tag->len;
00480 }
00481
00482 if (enable_full_lr) {
00483 suffix_len += RR_LR_FULL_LEN;
00484 } else {
00485 suffix_len += RR_LR_LEN;
00486 }
00487
00488 hdr = pkg_malloc(hdr_len);
00489 trans = pkg_malloc(RR_TRANS_LEN);
00490 suffix = pkg_malloc(suffix_len);
00491 r2 = pkg_malloc(RR_R2_LEN);
00492 term = pkg_malloc(RR_TERM_LEN);
00493 if (!hdr || !trans || !suffix || !term || !r2) {
00494 LM_ERR("no pkg memory left\n");
00495 if (hdr) pkg_free(hdr);
00496 if (trans) pkg_free(trans);
00497 if (suffix) pkg_free(suffix);
00498 if (r2) pkg_free(r2);
00499 if (term) pkg_free(term);
00500 return -1;
00501 }
00502
00503 p = hdr;
00504 memcpy(p, RR_PREFIX, RR_PREFIX_LEN);
00505 p += RR_PREFIX_LEN;
00506
00507 if (user->len) {
00508 memcpy(p, user->s, user->len);
00509 p += user->len;
00510 *p = '@';
00511 p++;
00512 }
00513
00514 memcpy(p, _data->s, _data->len);
00515 p += _data->len;
00516
00517 p = suffix;
00518 if (tag && tag->len) {
00519 memcpy(p, RR_FROMTAG, RR_FROMTAG_LEN);
00520 p += RR_FROMTAG_LEN;
00521 memcpy(p, tag->s, tag->len);
00522 p += tag->len;
00523 }
00524
00525 if (enable_full_lr) {
00526 memcpy(p, RR_LR_FULL, RR_LR_FULL_LEN);
00527 p += RR_LR_FULL_LEN;
00528 } else {
00529 memcpy(p, RR_LR, RR_LR_LEN);
00530 p += RR_LR_LEN;
00531 }
00532
00533 memcpy(trans, RR_TRANS, RR_TRANS_LEN);
00534 memcpy(term, RR_TERM, RR_TERM_LEN);
00535 memcpy(r2, RR_R2, RR_R2_LEN);
00536
00537 if (!(_l = insert_new_lump_after(_l, hdr, hdr_len, 0))) {
00538 LM_ERR("failed to insert new lump\n");
00539 goto lump_err;
00540 }
00541 hdr = NULL;
00542 if (!(_l = insert_cond_lump_after(_l, COND_IF_DIFF_PROTO, 0)))
00543 goto lump_err;
00544 if (!(_l = insert_new_lump_after(_l, trans, RR_TRANS_LEN, 0)))
00545 goto lump_err;
00546 if (!(_l = insert_subst_lump_after(_l, _inbound?SUBST_RCV_PROTO:SUBST_SND_PROTO, 0)))
00547 goto lump_err;
00548 if (enable_double_rr) {
00549 if (!(_l = insert_cond_lump_after(_l, COND_IF_DIFF_REALMS, 0)))
00550 goto lump_err;
00551 if (!(_l = insert_new_lump_after(_l, r2, RR_R2_LEN, 0)))
00552 goto lump_err;
00553 r2 = 0;
00554 } else {
00555 pkg_free(r2);
00556 r2 = 0;
00557 }
00558 if (!(_l2 = insert_new_lump_before(_l2, suffix, suffix_len, HDR_RECORDROUTE_T)))
00559 goto lump_err;
00560 suffix = NULL;
00561 if (rr_param_buf.len) {
00562 if (!(_l2 = insert_rr_param_lump(_l2, rr_param_buf.s, rr_param_buf.len)))
00563 goto lump_err;
00564 }
00565 if (!(_l2 = insert_new_lump_before(_l2, term, RR_TERM_LEN, 0)))
00566 goto lump_err;
00567 return 1;
00568 lump_err:
00569 if (hdr) pkg_free(hdr);
00570 if (suffix) pkg_free(suffix);
00571 if (term) pkg_free(term);
00572 if (r2) pkg_free(r2);
00573 return -7;
00574 }
00575
00576 int record_route_advertised_address(struct sip_msg* _m, str* _data)
00577 {
00578 str user;
00579 str *tag = NULL;
00580 struct lump* l;
00581 struct lump* l2;
00582
00583 user.len = 0;
00584 user.s = 0;
00585
00586 if (add_username) {
00587 if (get_username(_m, &user) < 0) {
00588 LM_ERR("failed to extract username\n");
00589 return -1;
00590 }
00591 }
00592
00593 if (append_fromtag) {
00594 if (parse_from_header(_m) < 0) {
00595 LM_ERR("From parsing failed\n");
00596 return -2;
00597 }
00598 tag = &((struct to_body*)_m->from->parsed)->tag_value;
00599 }
00600
00601 if (enable_double_rr) {
00602 l = anchor_lump(_m, _m->headers->name.s - _m->buf,0,HDR_RECORDROUTE_T);
00603 l2 = anchor_lump(_m, _m->headers->name.s - _m->buf, 0, 0);
00604 if (!l || !l2) {
00605 LM_ERR("failed to create an anchor\n");
00606 return -3;
00607 }
00608 l = insert_cond_lump_after(l, COND_IF_DIFF_PROTO, 0);
00609 l2 = insert_cond_lump_before(l2, COND_IF_DIFF_PROTO, 0);
00610 if (!l || !l2) {
00611 LM_ERR("failed to insert conditional lump\n");
00612 return -4;
00613 }
00614 if (build_advertised_rr(l, l2, _data, &user, tag, OUTBOUND) < 0) {
00615 LM_ERR("failed to insert outbound Record-Route\n");
00616 return -5;
00617 }
00618 }
00619
00620 l = anchor_lump(_m, _m->headers->name.s - _m->buf, 0, HDR_RECORDROUTE_T);
00621 l2 = anchor_lump(_m, _m->headers->name.s - _m->buf, 0, 0);
00622 if (!l || !l2) {
00623 LM_ERR("failed to create an anchor\n");
00624 return -6;
00625 }
00626
00627 if (build_advertised_rr(l, l2, _data, &user, tag, INBOUND) < 0) {
00628 LM_ERR("failed to insert outbound Record-Route\n");
00629 return -7;
00630 }
00631 return 1;
00632 }
00633
00634
00640 static struct lump *get_rr_param_lump( struct lump** root)
00641 {
00642 struct lump *r, *crt, *last;
00643
00644
00645 last = 0;
00646 for( crt=*root ; crt && !last ; crt=crt->next,(*root)=crt ) {
00647
00648 for( r=crt->before ; r ; r=r->before ) {
00649
00650
00651 if ( r->type==HDR_RECORDROUTE_T && r->op==LUMP_ADD)
00652 last = r;
00653 }
00654 }
00655 return last;
00656 }
00657
00658
00665 int add_rr_param(struct sip_msg* msg, str* rr_param)
00666 {
00667 struct lump *last_param;
00668 struct lump *root;
00669
00670 root = msg->add_rm;
00671 last_param = get_rr_param_lump( &root );
00672 if (last_param) {
00673
00674 if (insert_rr_param_lump( last_param, rr_param->s, rr_param->len)==0) {
00675 LM_ERR("failed to add lump\n");
00676 goto error;
00677 }
00678
00679 if (enable_double_rr) {
00680 if (root==0 || (last_param=get_rr_param_lump(&root))==0) {
00681 LM_CRIT("failed to locate double RR lump\n");
00682 goto error;
00683 }
00684 if (insert_rr_param_lump(last_param,rr_param->s,rr_param->len)==0){
00685 LM_ERR("failed to add 2nd lump\n");
00686 goto error;
00687 }
00688 }
00689 } else {
00690
00691 if (rr_param_msg!=msg->id) {
00692
00693 rr_param_buf.len = 0;
00694 rr_param_msg = msg->id;
00695 }
00696 if (rr_param_buf.len+rr_param->len>RR_PARAM_BUF_SIZE) {
00697 LM_ERR("maximum size of rr_param_buf exceeded\n");
00698 goto error;
00699 }
00700 memcpy( rr_param_buf.s+rr_param_buf.len, rr_param->s, rr_param->len);
00701 rr_param_buf.len += rr_param->len;
00702 LM_DBG("rr_param_buf=<%.*s>\n",rr_param_buf.len, rr_param_buf.s);
00703 }
00704 return 0;
00705
00706 error:
00707 return -1;
00708 }