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(&reg_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(&reg_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(&reg_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(&reg_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(&reg_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(&reg_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