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 #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
00066
00067 #define RR_PARAM_BUF_SIZE 512
00068
00069
00070
00071
00072
00073
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
00079
00080
00081
00082
00083
00084
00085
00086
00087
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
00116
00117
00118
00119
00120
00121
00122
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
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159 static inline int build_rr(struct lump* _l, struct lump* _l2, str* user,
00160 str *tag, str *params, int _inbound)
00161 {
00162 char* prefix, *suffix, *term, *r2;
00163 int suffix_len, prefix_len;
00164 char *p;
00165
00166 prefix_len = RR_PREFIX_LEN + (user->len ? (user->len + 1) : 0);
00167 if (enable_full_lr) {
00168 suffix_len = RR_LR_FULL_LEN + (params?params->len:0) +
00169 ((tag && tag->len) ? (RR_FROMTAG_LEN + tag->len) : 0);
00170 } else {
00171 suffix_len = RR_LR_LEN + (params?params->len:0) +
00172 ((tag && tag->len) ? (RR_FROMTAG_LEN + tag->len) : 0);
00173 }
00174
00175 prefix = pkg_malloc(prefix_len);
00176 suffix = pkg_malloc(suffix_len);
00177 term = pkg_malloc(RR_TERM_LEN);
00178 r2 = pkg_malloc(RR_R2_LEN);
00179
00180 if (!prefix || !suffix || !term || !r2) {
00181 LM_ERR("No more pkg memory\n");
00182 if (suffix) pkg_free(suffix);
00183 if (prefix) pkg_free(prefix);
00184 if (term) pkg_free(term);
00185 if (r2) pkg_free(r2);
00186 return -3;
00187 }
00188
00189 memcpy(prefix, RR_PREFIX, RR_PREFIX_LEN);
00190 if (user->len) {
00191 memcpy(prefix + RR_PREFIX_LEN, user->s, user->len);
00192 #ifdef ENABLE_USER_CHECK
00193
00194 if(i_user.len && i_user.len == user->len &&
00195 !strncmp(i_user.s, user->s, i_user.len))
00196 {
00197 if(prefix[RR_PREFIX_LEN]=='x')
00198 prefix[RR_PREFIX_LEN]='y';
00199 else
00200 prefix[RR_PREFIX_LEN]='x';
00201 }
00202 #endif
00203 prefix[RR_PREFIX_LEN + user->len] = '@';
00204 }
00205
00206 p = suffix;
00207 if (enable_full_lr) {
00208 memcpy( p, RR_LR_FULL, RR_LR_FULL_LEN);
00209 p += RR_LR_FULL_LEN;
00210 } else {
00211 memcpy( p, RR_LR, RR_LR_LEN);
00212 p += RR_LR_LEN;
00213 }
00214 if (tag && tag->len) {
00215 memcpy(p, RR_FROMTAG, RR_FROMTAG_LEN);
00216 p += RR_FROMTAG_LEN;
00217 memcpy(p, tag->s, tag->len);
00218 p += tag->len;
00219 }
00220 if (params && params->len) {
00221 memcpy(p, params->s, params->len);
00222 p += params->len;
00223 }
00224
00225 memcpy(term, RR_TERM, RR_TERM_LEN);
00226 memcpy(r2, RR_R2, RR_R2_LEN);
00227
00228 if (!(_l = insert_new_lump_after(_l, prefix, prefix_len, 0)))
00229 goto lump_err;
00230 prefix = 0;
00231 _l = insert_subst_lump_after(_l, _inbound?SUBST_RCV_ALL:SUBST_SND_ALL, 0);
00232 if (_l ==0 )
00233 goto lump_err;
00234 if (enable_double_rr) {
00235 if (!(_l = insert_cond_lump_after(_l, COND_IF_DIFF_REALMS, 0)))
00236 goto lump_err;
00237 if (!(_l = insert_new_lump_after(_l, r2, RR_R2_LEN, 0)))
00238 goto lump_err;
00239 r2 = 0;
00240 } else {
00241 pkg_free(r2);
00242 r2 = 0;
00243 }
00244 _l2 = insert_new_lump_before(_l2, suffix, suffix_len, HDR_RECORDROUTE_T);
00245 if (_l2 == 0)
00246 goto lump_err;
00247 if (rr_param_buf.len) {
00248 _l2 = insert_rr_param_lump(_l2, rr_param_buf.s, rr_param_buf.len);
00249 if (_l2 == 0)
00250 goto lump_err;
00251 }
00252 suffix = 0;
00253 if (!(_l2 = insert_new_lump_before(_l2, term, RR_TERM_LEN, 0)))
00254 goto lump_err;
00255 term = 0;
00256 return 0;
00257
00258 lump_err:
00259 LM_ERR("failed to insert lumps\n");
00260 if (prefix) pkg_free(prefix);
00261 if (suffix) pkg_free(suffix);
00262 if (r2) pkg_free(r2);
00263 if (term) pkg_free(term);
00264 return -4;
00265 }
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277 int record_route(struct sip_msg* _m, str *params)
00278 {
00279 struct lump* l, *l2;
00280 str user;
00281 struct to_body* from = NULL;
00282 str* tag;
00283
00284 user.len = 0;
00285
00286 if (add_username) {
00287 if (get_username(_m, &user) < 0) {
00288 LM_ERR("failed to extract username\n");
00289 return -1;
00290 }
00291 }
00292
00293 if (append_fromtag) {
00294 if (parse_from_header(_m) < 0) {
00295 LM_ERR("From parsing failed\n");
00296 return -2;
00297 }
00298 from = (struct to_body*)_m->from->parsed;
00299 tag = &from->tag_value;
00300 } else {
00301 tag = 0;
00302 }
00303
00304 if (rr_param_buf.len && rr_param_msg!=_m->id) {
00305
00306 rr_param_buf.len = 0;
00307 }
00308
00309 if (enable_double_rr) {
00310 l = anchor_lump(_m, _m->headers->name.s - _m->buf,0,HDR_RECORDROUTE_T);
00311 l2 = anchor_lump(_m, _m->headers->name.s - _m->buf, 0, 0);
00312 if (!l || !l2) {
00313 LM_ERR("failed to create an anchor\n");
00314 return -5;
00315 }
00316 l = insert_cond_lump_after(l, COND_IF_DIFF_REALMS, 0);
00317 l2 = insert_cond_lump_before(l2, COND_IF_DIFF_REALMS, 0);
00318 if (!l || !l2) {
00319 LM_ERR("failed to insert conditional lump\n");
00320 return -6;
00321 }
00322 if (build_rr(l, l2, &user, tag, params, OUTBOUND) < 0) {
00323 LM_ERR("failed to insert outbound Record-Route\n");
00324 return -7;
00325 }
00326 }
00327
00328 l = anchor_lump(_m, _m->headers->name.s - _m->buf, 0, HDR_RECORDROUTE_T);
00329 l2 = anchor_lump(_m, _m->headers->name.s - _m->buf, 0, 0);
00330 if (!l || !l2) {
00331 LM_ERR("failed to create an anchor\n");
00332 return -3;
00333 }
00334
00335 if (build_rr(l, l2, &user, tag, params, INBOUND) < 0) {
00336 LM_ERR("failed to insert inbound Record-Route\n");
00337 return -4;
00338 }
00339
00340
00341 rr_param_buf.len = 0;
00342 return 0;
00343 }
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356 int record_route_preset(struct sip_msg* _m, str* _data)
00357 {
00358 str user;
00359 struct to_body* from;
00360 struct lump* l;
00361 char* hdr, *p;
00362 int hdr_len;
00363
00364 from = 0;
00365 user.len = 0;
00366 user.s = 0;
00367
00368 if (add_username) {
00369 if (get_username(_m, &user) < 0) {
00370 LM_ERR("failed to extract username\n");
00371 return -1;
00372 }
00373 }
00374
00375 if (append_fromtag) {
00376 if (parse_from_header(_m) < 0) {
00377 LM_ERR("From parsing failed\n");
00378 return -2;
00379 }
00380 from = (struct to_body*)_m->from->parsed;
00381 }
00382
00383 l = anchor_lump(_m, _m->headers->name.s - _m->buf, 0, HDR_RECORDROUTE_T);
00384 if (!l) {
00385 LM_ERR("failed to create lump anchor\n");
00386 return -3;
00387 }
00388
00389 hdr_len = RR_PREFIX_LEN;
00390 if (user.len)
00391 hdr_len += user.len + 1;
00392 hdr_len += _data->len;
00393
00394 if (append_fromtag && from->tag_value.len) {
00395 hdr_len += RR_FROMTAG_LEN + from->tag_value.len;
00396 }
00397
00398 if (enable_full_lr) {
00399 hdr_len += RR_LR_FULL_LEN;
00400 } else {
00401 hdr_len += RR_LR_LEN;
00402 }
00403
00404 hdr_len += RR_TERM_LEN;
00405
00406 hdr = pkg_malloc(hdr_len);
00407 if (!hdr) {
00408 LM_ERR("no pkg memory left\n");
00409 return -4;
00410 }
00411
00412 p = hdr;
00413 memcpy(p, RR_PREFIX, RR_PREFIX_LEN);
00414 p += RR_PREFIX_LEN;
00415
00416 if (user.len) {
00417 memcpy(p, user.s, user.len);
00418 p += user.len;
00419 *p = '@';
00420 p++;
00421 }
00422
00423 memcpy(p, _data->s, _data->len);
00424 p += _data->len;
00425
00426 if (append_fromtag && from->tag_value.len) {
00427 memcpy(p, RR_FROMTAG, RR_FROMTAG_LEN);
00428 p += RR_FROMTAG_LEN;
00429 memcpy(p, from->tag_value.s, from->tag_value.len);
00430 p += from->tag_value.len;
00431 }
00432
00433 if (enable_full_lr) {
00434 memcpy(p, RR_LR_FULL, RR_LR_FULL_LEN);
00435 p += RR_LR_FULL_LEN;
00436 } else {
00437 memcpy(p, RR_LR, RR_LR_LEN);
00438 p += RR_LR_LEN;
00439 }
00440
00441 memcpy(p, RR_TERM, RR_TERM_LEN);
00442
00443 if (!insert_new_lump_after(l, hdr, hdr_len, 0)) {
00444 LM_ERR("failed to insert new lump\n");
00445 pkg_free(hdr);
00446 return -5;
00447 }
00448 return 1;
00449 }
00450
00451
00452
00453
00454
00455
00456
00457 static struct lump *get_rr_param_lump( struct lump** root)
00458 {
00459 struct lump *r, *crt, *last;
00460
00461
00462 last = 0;
00463 for( crt=*root ; crt && !last ; crt=crt->next,(*root)=crt ) {
00464
00465 for( r=crt->before ; r ; r=r->before ) {
00466
00467
00468 if ( r->type==HDR_RECORDROUTE_T && r->op==LUMP_ADD)
00469 last = r;
00470 }
00471 }
00472 return last;
00473 }
00474
00475
00476
00477
00478
00479
00480
00481
00482 int add_rr_param(struct sip_msg* msg, str* rr_param)
00483 {
00484 struct lump *last_param;
00485 struct lump *root;
00486
00487 root = msg->add_rm;
00488 last_param = get_rr_param_lump( &root );
00489 if (last_param) {
00490
00491 if (insert_rr_param_lump( last_param, rr_param->s, rr_param->len)==0) {
00492 LM_ERR("failed to add lump\n");
00493 goto error;
00494 }
00495
00496 if (enable_double_rr) {
00497 if (root==0 || (last_param=get_rr_param_lump(&root))==0) {
00498 LM_CRIT("failed to locate double RR lump\n");
00499 goto error;
00500 }
00501 if (insert_rr_param_lump(last_param,rr_param->s,rr_param->len)==0){
00502 LM_ERR("failed to add 2nd lump\n");
00503 goto error;
00504 }
00505 }
00506 } else {
00507
00508 if (rr_param_msg!=msg->id) {
00509
00510 rr_param_buf.len = 0;
00511 rr_param_msg = msg->id;
00512 }
00513 if (rr_param_buf.len+rr_param->len>RR_PARAM_BUF_SIZE) {
00514 LM_ERR("maximum size of rr_param_buf exceeded\n");
00515 goto error;
00516 }
00517 memcpy( rr_param_buf.s+rr_param_buf.len, rr_param->s, rr_param->len);
00518 rr_param_buf.len += rr_param->len;
00519 LM_DBG("rr_param_buf=<%.*s>\n",rr_param_buf.len, rr_param_buf.s);
00520 }
00521 return 0;
00522
00523 error:
00524 return -1;
00525 }