1 /*
2 * Lookup contacts in usrloc
3 *
4 * Copyright (C) 2001-2003 FhG Fokus
5 *
6 * This file is part of Kamailio, a free SIP server.
7 *
8 * Kamailio is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version
12 *
13 * Kamailio is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 *
22 */
23 /*!
24 * \file
25 * \brief SIP registrar module - lookup contacts in usrloc
26 * \ingroup registrar
27 */
28
29
30 #include <string.h>
31 #include "../../core/ut.h"
32 #include "../../core/dset.h"
33 #include "../../core/str.h"
34 #include "../../core/xavp.h"
35 #include "../../core/config.h"
36 #include "../../core/action.h"
37 #include "../../core/mod_fix.h"
38 #include "../../core/parser/parse_rr.h"
39 #include "../../core/parser/parse_to.h"
40 #include "../../core/forward.h"
41 #include "../usrloc/usrloc.h"
42 #include "common.h"
43 #include "regtime.h"
44 #include "registrar.h"
45 #include "lookup.h"
46 #include "config.h"
47
48
49 extern int reg_lookup_filter_mode;
50
51 typedef struct reg_lookup_filter {
52 uint32_t factive;
53 uint32_t bflags;
54 } reg_lookup_filter_t;
55
56 static reg_lookup_filter_t _reg_lookup_filter;
57
reg_lookup_filter_init(void)58 static void reg_lookup_filter_init(void)
59 {
60 str filter_bflags = str_init("rlf_bflags");
61 sr_xavp_t *vavp = NULL;
62
63 if(reg_lookup_filter_mode==0 || reg_xavp_cfg.s==NULL) {
64 return;
65 }
66 memset(&_reg_lookup_filter, 0, sizeof(reg_lookup_filter_t));
67
68 if((reg_lookup_filter_mode & 1)
69 && (vavp = xavp_get_child_with_ival(®_xavp_cfg,
70 &filter_bflags)) != NULL) {
71 if(vavp->val.v.i != 0) {
72 _reg_lookup_filter.bflags = (uint32_t)vavp->val.v.i;
73 _reg_lookup_filter.factive = 1;
74 }
75 }
76 return;
77 }
78
reg_lookup_filter_match(ucontact_t * ptr)79 static int reg_lookup_filter_match(ucontact_t* ptr)
80 {
81 if(reg_lookup_filter_mode==0 || reg_xavp_cfg.s==NULL) {
82 return 1;
83 }
84 if(_reg_lookup_filter.factive==0) {
85 return 1;
86 }
87 if(_reg_lookup_filter.bflags!=0) {
88 if((_reg_lookup_filter.bflags & ptr->cflags)==0) {
89 return 0;
90 }
91 }
92 return 1;
93
94 }
95
has_to_tag(struct sip_msg * msg)96 static int has_to_tag(struct sip_msg* msg)
97 {
98 if (parse_to_header(msg) < 0) return 0;
99 return (get_to(msg)->tag_value.len > 0) ? 1 : 0;
100 }
101
102 #define allowed_method(_msg, _c) \
103 ( !method_filtering || ((_msg)->REQ_METHOD)&((_c)->methods) || \
104 has_to_tag(_msg) )
105
106 /**
107 * compare two instances, by skipping '<' & '>'
108 */
reg_cmp_instances(str * i1,str * i2)109 int reg_cmp_instances(str *i1, str *i2)
110 {
111 str inst1;
112 str inst2;
113
114 if(i1==NULL || i2==NULL || i1->len<=0 || i2->len<=0)
115 return -1;
116
117 inst1 = *i1;
118 inst2 = *i2;
119 if(inst1.len>2 && inst1.s[0]=='<' && inst1.s[inst1.len-1]=='>')
120 {
121 inst1.s++;
122 inst1.len -=2;
123 }
124 if(inst2.len>2 && inst2.s[0]=='<' && inst2.s[inst2.len-1]=='>')
125 {
126 inst2.s++;
127 inst2.len -=2;
128 }
129 if(inst1.len>0 && inst1.len==inst2.len
130 && memcmp(inst1.s, inst2.s, inst2.len)==0)
131 return 0;
132 return -1;
133 }
134
135 /*! \brief
136 * Lookup a contact in usrloc and rewrite R-URI if found
137 */
lookup(struct sip_msg * _m,udomain_t * _d,str * _uri)138 int lookup(struct sip_msg* _m, udomain_t* _d, str* _uri)
139 {
140 return lookup_helper(_m, _d, _uri, 0);
141 }
142
143 /*! \brief
144 * Lookup a contact in usrloc and add the records to the dset structure
145 */
lookup_to_dset(struct sip_msg * _m,udomain_t * _d,str * _uri)146 int lookup_to_dset(struct sip_msg* _m, udomain_t* _d, str* _uri)
147 {
148 return lookup_helper(_m, _d, _uri, 1);
149 }
150
151 /*! \brief
152 * add xavp with details of the record (ruid, ...)
153 */
xavp_rcd_helper(ucontact_t * ptr)154 int xavp_rcd_helper(ucontact_t* ptr)
155 {
156 sr_xavp_t **xavp=NULL;
157 sr_xavp_t *list=NULL;
158 sr_xavp_t *new_xavp=NULL;
159 str xname_ruid = {"ruid", 4};
160 str xname_received = { "received", 8};
161 str xname_contact = { "contact", 7};
162 str xname_expires = {"expires", 7};
163 str xname_path = {"path", 4};
164 sr_xval_t xval;
165
166 if(ptr==NULL) return -1;
167
168 if(reg_xavp_rcd.s==NULL || reg_xavp_rcd.len<=0) return 0;
169
170 list = xavp_get(®_xavp_rcd, NULL);
171 xavp = list ? &list->val.v.xavp : &new_xavp;
172
173 if(!(reg_xavp_rcd_mask & AVP_RCD_RUID)) {
174 memset(&xval, 0, sizeof(sr_xval_t));
175 xval.type = SR_XTYPE_STR;
176 xval.v.s = ptr->ruid;
177 xavp_add_value(&xname_ruid, &xval, xavp);
178 }
179
180 if(!(reg_xavp_rcd_mask & AVP_RCD_RCV) && (ptr->received.len > 0)) {
181 memset(&xval, 0, sizeof(sr_xval_t));
182 xval.type = SR_XTYPE_STR;
183 xval.v.s = ptr->received;
184 xavp_add_value(&xname_received, &xval, xavp);
185 }
186
187 if(!(reg_xavp_rcd_mask & AVP_RCD_CNT)) {
188 memset(&xval, 0, sizeof(sr_xval_t));
189 xval.type = SR_XTYPE_STR;
190 xval.v.s = ptr->c;
191 xavp_add_value(&xname_contact, &xval, xavp);
192 }
193
194 if(!(reg_xavp_rcd_mask & AVP_RCD_EXP)) {
195 memset(&xval, 0, sizeof(sr_xval_t));
196 xval.type = SR_XTYPE_INT;
197 xval.v.i = (int) (ptr->expires - time(0));
198 xavp_add_value(&xname_expires, &xval, xavp);
199 }
200
201 if(!(reg_xavp_rcd_mask & AVP_RCD_PATH) && (ptr->path.len > 0)) {
202 memset(&xval, 0, sizeof(sr_xval_t));
203 xval.type = SR_XTYPE_STR;
204 xval.v.s = ptr->path;
205 xavp_add_value(&xname_path, &xval, xavp);
206 }
207
208 if(list==NULL) {
209 /* no reg_xavp_rcd xavp in root list - add it */
210 xval.type = SR_XTYPE_XAVP;
211 xval.v.xavp = *xavp;
212 if(xavp_add_value(®_xavp_rcd, &xval, NULL)==NULL) {
213 LM_ERR("cannot add ruid xavp to root list\n");
214 xavp_destroy_list(xavp);
215 }
216 }
217 return 0;
218 }
219
220 /*! \brief
221 * Lookup contact in the database and rewrite Request-URI
222 * or not according to _mode value:
223 * 0: rewrite
224 * 1: don't rewrite
225 * \return: -1 : not found
226 * -2 : found but method not allowed
227 * -3 : error
228 */
lookup_helper(struct sip_msg * _m,udomain_t * _d,str * _uri,int _mode)229 int lookup_helper(struct sip_msg* _m, udomain_t* _d, str* _uri, int _mode)
230 {
231 urecord_t* r;
232 str aor, uri;
233 sip_uri_t puri;
234 ucontact_t* ptr = 0;
235 int res;
236 int ret;
237 str path_dst;
238 flag_t old_bflags;
239 int i;
240 str inst = {0};
241 unsigned int ahash = 0;
242 sr_xavp_t *xavp=NULL;
243 sip_uri_t path_uri;
244 str path_str;
245 branch_t *nbranch;
246
247 ret = -1;
248
249 if (_m->new_uri.s) uri = _m->new_uri;
250 else uri = _m->first_line.u.request.uri;
251
252 if (extract_aor((_uri)?_uri:&uri, &aor, &puri) < 0) {
253 LM_ERR("failed to extract address of record\n");
254 return -3;
255 }
256 /* check if gruu */
257 if(puri.gr.s!=NULL)
258 {
259 if(puri.gr_val.len>0) {
260 /* pub-gruu */
261 inst = puri.gr_val;
262 LM_DBG("looking up pub gruu [%.*s]\n", inst.len, inst.s);
263 } else {
264 /* temp-gruu */
265 ahash = 0;
266 inst = puri.user;
267 for(i=inst.len-1; i>=0; i--)
268 {
269 if(inst.s[i]==REG_GRUU_SEP)
270 break;
271 ahash <<= 4;
272 if(inst.s[i] >='0' && inst.s[i] <='9') ahash+=inst.s[i] -'0';
273 else if (inst.s[i] >='a' && inst.s[i] <='f') ahash+=inst.s[i] -'a'+10;
274 else if (inst.s[i] >='A' && inst.s[i] <='F') ahash+=inst.s[i] -'A'+10;
275 else {
276 LM_ERR("failed to extract temp gruu - invalid hash\n");
277 return -3;
278 }
279 }
280 if(i<0) {
281 LM_ERR("failed to extract temp gruu - invalid format\n");
282 return -3;
283 }
284 inst.len = i;
285 LM_DBG("looking up temp gruu [%u / %.*s]\n", ahash, inst.len, inst.s);
286 }
287 }
288
289 get_act_time();
290 reg_lookup_filter_init();
291
292 if(puri.gr.s==NULL || puri.gr_val.len>0)
293 {
294 /* aor or pub-gruu lookup */
295 ul.lock_udomain(_d, &aor);
296 res = ul.get_urecord(_d, &aor, &r);
297 if (res > 0) {
298 LM_DBG("'%.*s' Not found in usrloc\n", aor.len, ZSW(aor.s));
299 ul.unlock_udomain(_d, &aor);
300 return -1;
301 }
302
303 ptr = r->contacts;
304 ret = -1;
305 /* look first for an un-expired and suported contact */
306 while (ptr) {
307 if(VALID_CONTACT(ptr,act_time) || cfg_get(registrar,registrar_cfg,use_expired_contacts)) {
308 if(allowed_method(_m,ptr)) {
309 /* match on instance, if pub-gruu */
310 if(inst.len>0) {
311 if(reg_cmp_instances(&inst, &ptr->instance)==0)
312 {
313 /* pub-gruu - found by instance */
314 LM_DBG("contact for [%.*s] found by pub gruu [%.*s]\n",
315 aor.len, ZSW(aor.s), inst.len, inst.s);
316 break;
317 }
318 } else {
319 if(reg_lookup_filter_match(ptr)) {
320 /* no-gruu - found by address */
321 LM_DBG("contact for [%.*s] found by address\n",
322 aor.len, ZSW(aor.s));
323 break;
324 }
325 }
326 } else {
327 LM_DBG("contact for [%.*s] cannot handle the SIP method\n",
328 aor.len, ZSW(aor.s));
329 ret = -2;
330 }
331 }
332 ptr = ptr->next;
333 }
334 if (ptr==0) {
335 /* nothing found */
336 LM_DBG("'%.*s' has no valid contact in usrloc\n", aor.len, ZSW(aor.s));
337 goto done;
338 }
339 } else {
340 /* temp-gruu lookup */
341 res = ul.get_urecord_by_ruid(_d, ahash, &inst, &r, &ptr);
342 if(res<0) {
343 LM_DBG("temp gruu '%.*s' not found in usrloc\n", aor.len, ZSW(aor.s));
344 return -1;
345 }
346 aor = *ptr->aor;
347 /* test if not expired and contact with suported method */
348 if(ptr) {
349 if(!(VALID_CONTACT(ptr,act_time) || cfg_get(registrar,registrar_cfg,use_expired_contacts))) {
350 goto done;
351 } else if(!allowed_method(_m,ptr)) {
352 ret=-2;
353 goto done;
354 }
355 }
356 LM_DBG("contact for [%.*s] found by temp gruu [%.*s / %u]\n",
357 aor.len, ZSW(aor.s), inst.len, inst.s, ahash);
358 }
359
360 ret = 1;
361 /* don't rewrite r-uri if called by lookup_to_dset */
362 if (_mode == 0 && ptr) {
363 if (rewrite_uri(_m, &ptr->c) < 0) {
364 LM_ERR("unable to rewrite Request-URI\n");
365 ret = -3;
366 goto done;
367 }
368
369 /* reset next hop address */
370 reset_dst_uri(_m);
371
372 xavp_rcd_helper(ptr);
373
374 /* If a Path is present, use first path-uri in favour of
375 * received-uri because in that case the last hop towards the uac
376 * has to handle NAT. - agranig */
377 if (ptr->path.s && ptr->path.len) {
378 /* make a copy, so any change we need to make here does not mess up the structure in usrloc */
379 path_str = ptr->path;
380 if (get_path_dst_uri(&path_str, &path_dst) < 0) {
381 LM_ERR("failed to get dst_uri for Path\n");
382 ret = -3;
383 goto done;
384 }
385 if (path_check_local > 0) {
386 if (parse_uri(path_dst.s, path_dst.len, &path_uri) < 0){
387 LM_ERR("failed to parse the Path URI\n");
388 ret = -3;
389 goto done;
390 }
391 if (check_self(&(path_uri.host), 0, 0)) {
392 /* first hop in path vector is local - check for additional hops and if present, point to next one */
393 if (path_str.len > (path_dst.len + 3)) {
394 path_str.s = path_str.s + path_dst.len + 3;
395 path_str.len = path_str.len - path_dst.len - 3;
396 if (get_path_dst_uri(&path_str, &path_dst) < 0) {
397 LM_ERR("failed to get second dst_uri for Path\n");
398 ret = -3;
399 goto done;
400 }
401 } else {
402 /* no more hops */
403 path_dst.s = NULL;
404 path_dst.len = 0;
405 }
406 }
407 }
408 } else {
409 path_dst.s = NULL;
410 path_dst.len = 0;
411 }
412 if (path_dst.s && path_dst.len) {
413 if (set_path_vector(_m, &path_str) < 0) {
414 LM_ERR("failed to set path vector\n");
415 ret = -3;
416 goto done;
417 }
418 if (set_dst_uri(_m, &path_dst) < 0) {
419 LM_ERR("failed to set dst_uri of Path\n");
420 ret = -3;
421 goto done;
422 }
423 } else if (ptr->received.s && ptr->received.len) {
424 if (set_dst_uri(_m, &ptr->received) < 0) {
425 ret = -3;
426 goto done;
427 }
428 }
429
430 if (ptr->instance.len) {
431 if (set_instance(_m, &(ptr->instance)) < 0) {
432 ret = -3;
433 goto done;
434 }
435 }
436
437 _m->reg_id = ptr->reg_id;
438 _m->otcpid = ptr->tcpconn_id;
439
440 if (ptr->ruid.len) {
441 if (set_ruid(_m, &(ptr->ruid)) < 0) {
442 ret = -3;
443 goto done;
444 }
445 }
446
447 if (ptr->user_agent.len) {
448 if (set_ua(_m, &(ptr->user_agent)) < 0) {
449 ret = -3;
450 goto done;
451 }
452 }
453
454 set_ruri_q(ptr->q);
455
456 old_bflags = 0;
457 getbflagsval(0, &old_bflags);
458 setbflagsval(0, old_bflags|ptr->cflags);
459
460 if (ptr->sock)
461 set_force_socket(_m, ptr->sock);
462
463 if(ptr->xavp!=NULL) {
464 xavp = xavp_clone_level_nodata(ptr->xavp);
465 if(xavp != NULL) {
466 if(xavp_insert(xavp, 0, NULL)<0) {
467 LM_ERR("error inserting xavp after clone\n");
468 xavp_destroy_list(&xavp);
469 ret = -3;
470 goto done;
471 }
472 } else {
473 LM_ERR("error cloning xavp\n");
474 ret = -3;
475 goto done;
476 }
477 }
478 ptr = ptr->next;
479 }
480
481 /* if was gruu, no more branches */
482 if(inst.len>0) goto done;
483
484 /* Append branches if enabled */
485 if (!cfg_get(registrar, registrar_cfg, append_branches)) goto done;
486
487 for( ; ptr ; ptr = ptr->next ) {
488 if ((VALID_CONTACT(ptr, act_time) || cfg_get(registrar,registrar_cfg,use_expired_contacts)) && allowed_method(_m, ptr)
489 && reg_lookup_filter_match(ptr)) {
490 path_dst.len = 0;
491 if(ptr->path.s && ptr->path.len) {
492 path_str = ptr->path;
493 if (get_path_dst_uri(&path_str, &path_dst) < 0) {
494 LM_ERR("failed to get dst_uri for Path\n");
495 continue;
496 }
497 if (path_check_local > 0) {
498 if (parse_uri(path_dst.s, path_dst.len, &path_uri) < 0) {
499 LM_ERR("failed to parse the Path URI\n");
500 continue;
501 }
502 if (check_self(&(path_uri.host), 0, 0)) {
503 /* first hop in path vector is local - check for additional hops and if present, point to next one */
504 if (path_str.len > (path_dst.len + 3)) {
505 path_str.s = path_str.s + path_dst.len + 3;
506 path_str.len = path_str.len - path_dst.len - 3;
507 if (get_path_dst_uri(&path_str, &path_dst) < 0) {
508 LM_ERR("failed to get second dst_uri for Path\n");
509 continue;
510 }
511 } else {
512 /* no more hops */
513 path_dst.s = NULL;
514 path_dst.len = 0;
515 }
516 }
517 }
518 } else {
519 path_dst.s = NULL;
520 path_dst.len = 0;
521 }
522
523 /* The same as for the first contact applies for branches
524 * regarding path vs. received. */
525 LM_DBG("instance is %.*s\n",
526 ptr->instance.len, ptr->instance.s);
527 nbranch = ksr_push_branch(_m, &ptr->c,
528 path_dst.len?&path_dst:&ptr->received,
529 path_dst.len?&path_str:0, ptr->q, ptr->cflags,
530 ptr->sock,
531 ptr->instance.len?&(ptr->instance):0,
532 ptr->instance.len?ptr->reg_id:0,
533 &ptr->ruid, &ptr->user_agent);
534 if (nbranch==NULL) {
535 LM_ERR("failed to append a branch\n");
536 /* Also give a chance to the next branches*/
537 continue;
538 }
539 nbranch->otcpid = ptr->tcpconn_id;
540 if(ptr->xavp!=NULL) {
541 xavp = xavp_clone_level_nodata(ptr->xavp);
542 if(xavp != NULL) {
543 if(xavp_insert(xavp, nr_branches, NULL)<0) {
544 LM_ERR("error inserting xavp after clone\n");
545 xavp_destroy_list(&xavp);
546 ret = -3;
547 goto done;
548 }
549 } else {
550 LM_ERR("error cloning xavp\n");
551 ret = -3;
552 goto done;
553 }
554 }
555 }
556 }
557
558 done:
559 ul.release_urecord(r);
560 ul.unlock_udomain(_d, &aor);
561 return ret;
562 }
563
564
565 /**
566 * only reset the pointers after local backup in lookup_branches
567 */
clear_ruri_branch(sip_msg_t * msg)568 int clear_ruri_branch(sip_msg_t *msg)
569 {
570 if(msg==NULL)
571 return -1;
572
573 msg->dst_uri.s = 0;
574 msg->dst_uri.len = 0;
575 msg->path_vec.s = 0;
576 msg->path_vec.len = 0;
577 set_ruri_q(Q_UNSPECIFIED);
578 reset_force_socket(msg);
579 setbflagsval(0, 0);
580 msg->instance.len = 0;
581 msg->reg_id = 0;
582 msg->ruid.s = 0;
583 msg->ruid.len = 0;
584 msg->location_ua.s = 0;
585 msg->location_ua.len = 0;
586 return 0;
587 }
588
589 /**
590 * reset and free the pointers after cloning to a branch in lookup_branches
591 */
reset_ruri_branch(sip_msg_t * msg)592 int reset_ruri_branch(sip_msg_t *msg)
593 {
594 if(msg==NULL)
595 return -1;
596
597 reset_dst_uri(msg);
598 reset_path_vector(msg);
599 set_ruri_q(Q_UNSPECIFIED);
600 reset_force_socket(msg);
601 setbflagsval(0, 0);
602 reset_instance(msg);
603 msg->reg_id = 0;
604 reset_ruid(msg);
605 reset_ua(msg);
606 return 0;
607 }
608
609 /*! \brief
610 * Lookup contacts in the database for all branches, including R-URI
611 * \return: -1 : not found
612 * -2 : found but method not allowed (for r-uri)
613 * -3 : error
614 */
lookup_branches(sip_msg_t * msg,udomain_t * d)615 int lookup_branches(sip_msg_t *msg, udomain_t *d)
616 {
617 unsigned int nr_branches_start;
618 unsigned int i;
619 int ret;
620 int found;
621 str new_uri;
622 str ruri_b_uri = {0};
623 str ruri_b_dst_uri = {0};
624 str ruri_b_path = {0};
625 int ruri_b_q = Q_UNSPECIFIED;
626 struct socket_info *ruri_b_socket = 0;
627 flag_t ruri_b_flags = 0;
628 str ruri_b_instance = {0};
629 unsigned int ruri_b_reg_id = 0;
630 str ruri_b_ruid = {0};
631 str ruri_b_ua = {0};
632 branch_t *crt = NULL;
633
634 ret = 1;
635 found = 0;
636 nr_branches_start = nr_branches;
637 /* first lookup the r-uri */
638 ret = lookup(msg, d, NULL);
639
640 /* if no other branches -- all done */
641 if(nr_branches_start==0)
642 return ret;
643
644 if(ret>0)
645 found = 1;
646
647 /* backup r-uri branch */
648 ruri_b_uri = msg->new_uri;
649 ruri_b_dst_uri = msg->dst_uri;
650 ruri_b_path = msg->path_vec;
651 ruri_b_q = get_ruri_q();
652 ruri_b_socket = msg->force_send_socket;
653 getbflagsval(0, &ruri_b_flags);
654 ruri_b_instance = msg->instance;
655 ruri_b_reg_id = msg->reg_id;
656 ruri_b_ruid = msg->ruid;
657 ruri_b_ua = msg->location_ua;
658 clear_ruri_branch(msg);
659 /* set new uri buf to null, otherwise is freed or overwritten by
660 * rewrite_uri() during branch lookup */
661 msg->new_uri.len=0;
662 msg->new_uri.s=0;
663 msg->parsed_uri_ok=0;
664
665 for(i=0; i<nr_branches_start; i++) {
666 crt = get_sip_branch(i);
667 /* it has to be a clean branch to do lookup for it */
668 if(crt->len <= 0 || crt->dst_uri_len > 0
669 || crt->path_len > 0 || crt->force_send_socket!=NULL
670 || crt->flags !=0)
671 continue;
672 /* set the new uri from branch and lookup */
673 new_uri.s = crt->uri;
674 new_uri.len = crt->len;
675 if (rewrite_uri(msg, &new_uri) < 0) {
676 LM_ERR("unable to rewrite Request-URI for branch %u\n", i);
677 ret = -3;
678 goto done;
679 }
680 ret = lookup(msg, d, NULL);
681 if(ret>0) {
682 /* move r-uri branch attributes to crt branch */
683 found = 1;
684
685 if (unlikely(msg->new_uri.len > MAX_URI_SIZE - 1)) {
686 LM_ERR("too long uri: %.*s\n", msg->new_uri.len,
687 msg->new_uri.s);
688 ret = -3;
689 goto done;
690 }
691
692 /* copy the dst_uri */
693 if (msg->dst_uri.len>0 && msg->dst_uri.s!=NULL) {
694 if (unlikely(msg->dst_uri.len > MAX_URI_SIZE - 1)) {
695 LM_ERR("too long dst_uri: %.*s\n", msg->dst_uri.len,
696 msg->dst_uri.s);
697 ret = -3;
698 goto done;
699 }
700
701 memcpy(crt->dst_uri, msg->dst_uri.s, msg->dst_uri.len);
702 crt->dst_uri[msg->dst_uri.len] = 0;
703 crt->dst_uri_len = msg->dst_uri.len;
704 }
705
706 /* copy the path string */
707 if (unlikely(msg->path_vec.len>0 && msg->path_vec.s!=NULL)) {
708 if (unlikely(msg->path_vec.len > MAX_PATH_SIZE - 1)) {
709 LM_ERR("too long path: %.*s\n", msg->path_vec.len,
710 msg->path_vec.s);
711 ret = -3;
712 goto done;
713 }
714 memcpy(crt->path, msg->path_vec.s, msg->path_vec.len);
715 crt->path[msg->path_vec.len] = 0;
716 crt->path_len = msg->path_vec.len;
717 }
718
719 /* copy the ruri */
720 memcpy(crt->uri, msg->new_uri.s, msg->new_uri.len);
721 crt->uri[msg->new_uri.len] = 0;
722 crt->len = msg->new_uri.len;
723 crt->q = get_ruri_q();
724
725 crt->force_send_socket = msg->force_send_socket;
726 getbflagsval(0, &crt->flags);
727 }
728 reset_ruri_branch(msg);
729 }
730
731 done:
732 reset_ruri_branch(msg);
733 /* new uri could be set to allocated buffer by branch lookup */
734 if(msg->new_uri.s!=NULL)
735 pkg_free(msg->new_uri.s);
736 msg->new_uri = ruri_b_uri;
737 ruri_mark_new();
738 msg->parsed_uri_ok = 0;
739 msg->dst_uri = ruri_b_dst_uri;
740 msg->path_vec = ruri_b_path;
741 set_ruri_q(ruri_b_q);
742 set_force_socket(msg, ruri_b_socket);
743 setbflagsval(0, ruri_b_flags);
744 msg->instance = ruri_b_instance;
745 msg->reg_id = ruri_b_reg_id;
746 msg->ruid = ruri_b_ruid;
747 msg->location_ua = ruri_b_ua;
748
749 return (found)?1:ret;
750 }
751
752 /*! \brief the is_registered() function
753 * Return true if the AOR in the Request-URI is registered,
754 * it is similar to lookup but registered neither rewrites
755 * the Request-URI nor appends branches
756 */
registered(struct sip_msg * _m,udomain_t * _d,str * _uri)757 int registered(struct sip_msg* _m, udomain_t* _d, str* _uri)
758 {
759 return registered4(_m, _d, _uri, 0, 0);
760 }
761
762 /**
763 *
764 */
registered3(struct sip_msg * _m,udomain_t * _d,str * _uri,int match_flag)765 int registered3(struct sip_msg* _m, udomain_t* _d, str* _uri, int match_flag)
766 {
767 return registered4(_m, _d, _uri, match_flag, 0);
768 }
769
770 /**
771 *
772 */
registered4(struct sip_msg * _m,udomain_t * _d,str * _uri,int match_flag,int match_action_flag)773 int registered4(struct sip_msg* _m, udomain_t* _d, str* _uri, int match_flag,
774 int match_action_flag)
775 {
776 str uri, aor;
777 urecord_t* r;
778 ucontact_t* ptr;
779 int res;
780 str match_callid = {0,0};
781 str match_received = {0,0};
782 str match_contact = {0,0};
783 sr_xavp_t *vavp = NULL;
784
785 if(_uri!=NULL)
786 {
787 uri = *_uri;
788 } else {
789 if(IS_SIP_REPLY(_m)) {
790 if (parse_to_header(_m) < 0) {
791 LM_ERR("failed to prepare the message\n");
792 return -1;
793 }
794 uri = get_to(_m)->uri;
795 } else {
796 if (_m->new_uri.s) uri = _m->new_uri;
797 else uri = _m->first_line.u.request.uri;
798 }
799 }
800
801 if (extract_aor(&uri, &aor, NULL) < 0) {
802 LM_ERR("failed to extract address of record\n");
803 return -1;
804 }
805
806 ul.lock_udomain(_d, &aor);
807 res = ul.get_urecord(_d, &aor, &r);
808
809 if (res < 0) {
810 ul.unlock_udomain(_d, &aor);
811 LM_ERR("failed to query usrloc\n");
812 return -1;
813 }
814
815 if (res == 0) {
816 LM_DBG("searching with match flags (%d,%d)\n", match_flag,
817 match_action_flag);
818 if(reg_xavp_cfg.s!=NULL) {
819
820 if((match_flag & 1)
821 && (vavp = xavp_get_child_with_sval(®_xavp_cfg,
822 &match_callid_name)) != NULL
823 && vavp->val.v.s.len > 0) {
824 match_callid = vavp->val.v.s;
825 LM_DBG("matching with callid %.*s\n", match_callid.len,
826 match_callid.s);
827 }
828
829 if((match_flag & 2)
830 && (vavp = xavp_get_child_with_sval(®_xavp_cfg,
831 &match_received_name)) != NULL
832 && vavp->val.v.s.len > 0) {
833 match_received = vavp->val.v.s;
834 LM_DBG("matching with received %.*s\n", match_received.len,
835 match_received.s);
836 }
837
838 if((match_flag & 4)
839 && (vavp = xavp_get_child_with_sval(®_xavp_cfg,
840 &match_contact_name)) != NULL
841 && vavp->val.v.s.len > 0) {
842 match_contact = vavp->val.v.s;
843 LM_DBG("matching with contact %.*s\n", match_contact.len,
844 match_contact.s);
845 }
846 }
847
848 get_act_time();
849 for (ptr = r->contacts; ptr; ptr = ptr->next) {
850 if(!(VALID_CONTACT(ptr, act_time) || cfg_get(registrar,registrar_cfg,use_expired_contacts))) continue;
851 if (match_callid.s && /* optionally enforce tighter matching w/ Call-ID */
852 match_callid.len > 0 &&
853 (match_callid.len != ptr->callid.len ||
854 memcmp(match_callid.s, ptr->callid.s, match_callid.len)))
855 continue;
856 if (match_received.s && /* optionally enforce tighter matching w/ ip:port */
857 match_received.len > 0 &&
858 (match_received.len != ptr->received.len ||
859 memcmp(match_received.s, ptr->received.s, match_received.len)))
860 continue;
861 if (match_contact.s && /* optionally enforce tighter matching w/ Contact */
862 match_contact.len > 0 &&
863 (match_contact.len != ptr->c.len ||
864 memcmp(match_contact.s, ptr->c.s, match_contact.len)))
865 continue;
866
867 if(!(match_action_flag & 2)) {
868 xavp_rcd_helper(ptr);
869 }
870
871 if((ptr->xavp!=NULL) && (match_action_flag & 1)) {
872 sr_xavp_t *xavp = xavp_clone_level_nodata(ptr->xavp);
873 if(xavp != NULL) {
874 if(xavp_add(xavp, NULL)<0) {
875 LM_ERR("error adding xavp for %.*s after successful match\n",
876 aor.len, ZSW(aor.s));
877 xavp_destroy_list(&xavp);
878 }
879 } else {
880 LM_ERR("error cloning xavp for %.*s after successful match\n",
881 aor.len, ZSW(aor.s));
882 }
883 }
884
885 ul.release_urecord(r);
886 ul.unlock_udomain(_d, &aor);
887 LM_DBG("'%.*s' found in usrloc\n", aor.len, ZSW(aor.s));
888
889 return 1;
890 }
891 }
892
893 ul.unlock_udomain(_d, &aor);
894 LM_DBG("'%.*s' not found in usrloc\n", aor.len, ZSW(aor.s));
895 return -1;
896 }
897