1 /*
2  * $Id$
3  *
4  * Copyright (C) 2012 Smile Communications, jason.penton@smilecoms.com
5  * Copyright (C) 2012 Smile Communications, richard.good@smilecoms.com
6  *
7  * The initial version of this code was written by Dragos Vingarzan
8  * (dragos(dot)vingarzan(at)fokus(dot)fraunhofer(dot)de and the
9  * Fruanhofer Institute. It was and still is maintained in a separate
10  * branch of the original SER. We are therefore migrating it to
11  * Kamailio/SR and look forward to maintaining it from here on out.
12  * 2011/2012 Smile Communications, Pty. Ltd.
13  * ported/maintained/improved by
14  * Jason Penton (jason(dot)penton(at)smilecoms.com and
15  * Richard Good (richard(dot)good(at)smilecoms.com) as part of an
16  * effort to add full IMS support to Kamailio/SR using a new and
17  * improved architecture
18  *
19  * NB: Alot of this code was originally part of OpenIMSCore,
20  * FhG Fokus.
21  * Copyright (C) 2004-2006 FhG Fokus
22  * Thanks for great work! This is an effort to
23  * break apart the various CSCF functions into logically separate
24  * components. We hope this will drive wider use. We also feel
25  * that in this way the architecture is more complete and thereby easier
26  * to manage in the Kamailio/SR environment
27  *
28  * This file is part of Kamailio, a free SIP server.
29  *
30  * Kamailio is free software; you can redistribute it and/or modify
31  * it under the terms of the GNU General Public License as published by
32  * the Free Software Foundation; either version 2 of the License, or
33  * (at your option) any later version
34  *
35  * Kamailio is distributed in the hope that it will be useful,
36  * but WITHOUT ANY WARRANTY; without even the implied warranty of
37  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
38  * GNU General Public License for more details.
39  *
40  * You should have received a copy of the GNU General Public License
41  * along with this program; if not, write to the Free Software
42  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
43  *
44  */
45 
46 #include "checker.h"
47 
48 /**
49  *	Check if a Service Point Trigger for Header matches the SDP body
50  *	@param spt - the service point trigger
51  *	@param headers - the headers of the message
52  *	@returns - 1 on success, 0 on failure
53  */
isc_check_headers(ims_spt * spt,struct hdr_field * headers)54 static int isc_check_headers(ims_spt *spt, struct hdr_field *headers) {
55 	struct hdr_field *i;
56 	char c, ch;
57 	char buf[256];
58 	regex_t header_comp, content_comp;
59 	i = headers;
60 
61     if (spt->sip_header.header.len >= sizeof(buf)) {
62         LM_ERR("Header name \"%.*s\" is to long to be processed (max %d bytes)\n", spt->sip_header.header.len, spt->sip_header.header.s, (int) (sizeof(buf) - 1));
63         return FALSE;
64     }
65     if (spt->sip_header.content.len >= sizeof(buf)) {
66         LM_ERR("Header content \"%.*s\" is to long to be processed (max %d bytes)\n", spt->sip_header.content.len, spt->sip_header.content.s, (int) (sizeof(buf) - 1));
67         return FALSE;
68     }
69 
70 	/* compile the regex for header name */
71 	memcpy(buf, spt->sip_header.header.s, spt->sip_header.header.len);
72 	buf[spt->sip_header.header.len] = 0;
73 	if (regcomp(&(header_comp), buf, REG_ICASE | REG_EXTENDED) != 0) {
74 	    LM_ERR("Error compiling the following regexp for header name: %.*s\n", spt->sip_header.header.len, spt->sip_header.header.s);
75 	    return FALSE;
76 	}
77 
78 	/* compile the regex for content */
79 	memcpy(buf, spt->sip_header.content.s, spt->sip_header.content.len);
80 	buf[spt->sip_header.content.len] = 0;
81 	if(regcomp(&(content_comp), buf, REG_ICASE | REG_EXTENDED) != 0) {
82 	    LM_ERR("Error compiling the following regexp for header content: %.*s\n", spt->sip_header.content.len, spt->sip_header.content.s);
83 	    regfree(&(header_comp));
84 	    return FALSE;
85 	}
86 
87 	LM_DBG("isc_check_headers: Looking for Header[%.*s(%d)] %.*s \n",
88 			spt->sip_header.header.len, spt->sip_header.header.s, spt->sip_header.type, spt->sip_header.content.len, spt->sip_header.content.s);
89 	while (i != NULL) {
90 		ch = i->name.s[i->name.len];
91 		i->name.s[i->name.len] = 0;
92 
93 		if ((spt->sip_header.type > 0 && spt->sip_header.type == i->type) || //matches known type
94 				(regexec(&(header_comp), i->name.s, 0, NULL, 0) == 0) //or matches the name
95 				) {
96 
97 			i->name.s[i->name.len] = ch;
98 			LM_DBG("isc_check_headers: Found Header[%.*s(%d)] %.*s \n",
99 					i->name.len, i->name.s, i->type, i->body.len, i->body.s);
100 			//if the header should be absent but found it
101 
102 			if (spt->sip_header.content.s == NULL)
103 				if (spt->condition_negated) {
104 					regfree(&(header_comp));
105 					regfree(&(content_comp));
106 					return FALSE;
107 				}
108 
109 			//check regex
110 			c = i->body.s[i->body.len];
111 			i->body.s[i->body.len] = 0;
112 
113 			if (regexec(&(content_comp), i->body.s, 0, NULL, 0) == 0) //regex match
114 			{
115 				regfree(&(header_comp));
116 				regfree(&(content_comp));
117 				i->body.s[i->body.len] = c;
118 				return TRUE;
119 			}
120 
121 			i->body.s[i->body.len] = c;
122 		} else
123 			i->name.s[i->name.len] = ch;
124 		i = i->next;
125 	}
126 
127 	regfree(&(header_comp));
128 	regfree(&(content_comp));
129 	return FALSE;
130 }
131 
132 static str sdp = { "application/sdp", 15 };
133 
134 /**
135  *	Check if a Service Point Trigger for Session Description matches the SDP body
136  *	@param spt - the service point trigger
137  *	@param msg - the message
138  *	@returns - 1 on success, 0 on failure
139  */
isc_check_session_desc(ims_spt * spt,struct sip_msg * msg)140 static int isc_check_session_desc(ims_spt *spt, struct sip_msg *msg) {
141 	int len;
142 	char *body, c;
143 	char *x;
144 	regex_t comp;
145 
146 	if (msg->content_type == NULL)
147 		return FALSE;
148 	if (strncasecmp(msg->content_type->body.s, sdp.s,
149 			msg->content_type->body.len) != 0)
150 		return FALSE;
151 	LM_DBG("ifc_check_session_desc:      Found Content-Type == appliction/sdp\n");
152 	//check for sdp line
153 	body = get_body(msg);
154 	if (body == 0)
155 		return FALSE;
156 	if (msg->content_length->parsed == NULL) {
157 		parse_content_length(msg->content_length->body.s,
158 				msg->content_length->body.s + msg->content_length->body.len,
159 				&len);
160 		msg->content_length->parsed = (void*) (long) len;
161 	} else
162 		len = (long) msg->content_length->parsed;
163 
164 	c = body[len];
165 	body[len] = 0;
166 	x =	pkg_malloc(spt->session_desc.line.len + 2 + spt->session_desc.content.len);
167 	sprintf(x, "%.*s=%.*s", spt->session_desc.line.len,
168 			spt->session_desc.line.s, spt->session_desc.content.len,
169 			spt->session_desc.content.s);
170 	/* compile the whole  regexp */
171 	regcomp(&(comp), x, REG_ICASE | REG_EXTENDED);
172 	if (regexec(&(comp), body, 0, NULL, 0) == 0) //regex match
173 	{
174 		body[len] = c;
175 		LM_DBG("ifc_check_session_desc:      Found Session Desc. > %s\n", body);
176 		pkg_free(x);
177 		return TRUE;
178 	}
179 	body[len] = c;
180 	pkg_free(x);
181 	return FALSE;
182 }
183 
184 /**
185  *	Check if a Service Point Trigger for RURI matches the RURI of a message
186  *	@param spt - the service point trigger
187  *	@param msg - the message
188  *	@returns - 1 on success, 0 on failure
189  */
isc_check_ruri(ims_spt * spt,struct sip_msg * msg)190 static int isc_check_ruri(ims_spt *spt, struct sip_msg *msg) {
191 	char buf[256];
192 	char buf2[256];
193 	regex_t comp;
194 
195 	if (spt->request_uri.len >= sizeof(buf)) {
196 	    LM_ERR("RURI regexp \"%.*s\" is too long to be compiled (max %d bytes)\n", spt->request_uri.len, spt->request_uri.s, (int) (sizeof(buf) - 1));
197 	    return FALSE;
198 	}
199 
200 	if (msg->first_line.u.request.uri.len >= sizeof(buf2)) {
201 	    LM_ERR("RURI \"%.*s\" is too long to be processed (max %d bytes)\n", msg->first_line.u.request.uri.len, msg->first_line.u.request.uri.s, (int) (sizeof(buf2) - 1));
202 	    return FALSE;
203 	}
204 
205 	/* compile the regex for content */
206 	memcpy(buf, spt->request_uri.s, spt->request_uri.len);
207 	buf[spt->request_uri.len] = 0;
208 	if (regcomp(&(comp), buf, REG_ICASE | REG_EXTENDED) != 0) {
209 	    LM_ERR("Error compiling the following regexp for RURI content: %.*s\n", spt->request_uri.len, spt->request_uri.s);
210 	    return FALSE;
211 	}
212 
213 	memcpy(buf2, msg->first_line.u.request.uri.s, msg->first_line.u.request.uri.len);
214 	buf2[msg->first_line.u.request.uri.len] = 0;
215 	if (regexec(&(comp), buf2, 0, NULL, 0) == 0) //regex match
216 	{
217 		regfree(&(comp));
218 		return TRUE;
219 	}
220 	regfree(&(comp));
221 	return FALSE;
222 }
223 
224 
225 
226 /**
227  *	Check if a Service Point Trigger matches a message
228  *	@param spt - the service point trigger
229  *	@param msg - the message
230  *	@param direction - if filter criteria is for originating/terminating/terminating_unregistered
231  *	@param registration_type - if the message is initial/re/de registration
232  *	@returns - 1 on success, 0 on failure
233  */
isc_check_spt(ims_spt * spt,struct sip_msg * msg,char direction,char registration_type)234 static int isc_check_spt(ims_spt *spt, struct sip_msg *msg, char direction,
235 		char registration_type) {
236 	int r = FALSE;
237 	switch (spt->type) {
238 	case IFC_REQUEST_URI:
239 		LM_DBG("ifc_check_spt:             SPT type %d -> RequestURI == %.*s ?\n",
240 				spt->type, spt->request_uri.len, spt->request_uri.s);
241 		LM_DBG("ifc_check_spt:               Found Request URI %.*s \n",
242 				msg->first_line.u.request.uri.len, msg->first_line.u.request.uri.s);
243 		r = isc_check_ruri(spt, msg);
244 		break;
245 	case IFC_METHOD:
246 		LM_DBG("ifc_check_spt:             SPT type %d -> Method == %.*s ?\n",
247 				spt->type, spt->method.len, spt->method.s);
248 		LM_DBG("ifc_check_spt:               Found method %.*s \n",
249 				msg->first_line.u.request.method.len, msg->first_line.u.request.method.s);
250 		r = (strncasecmp(spt->method.s, msg->first_line.u.request.method.s,
251 				spt->method.len) == 0);
252 		if (r && spt->method.len == 8
253 				&& strncasecmp(spt->method.s, "REGISTER", 8) == 0
254 				&& !(spt->registration_type == 0
255 						|| (registration_type & spt->registration_type)))
256 			r = 0;
257 		break;
258 	case IFC_SIP_HEADER:
259 		LM_DBG("ifc_check_spt:             SPT type %d -> Header[%.*s]  %%= %.*s ?\n",
260 				spt->type, spt->sip_header.header.len, spt->sip_header.header.s, spt->sip_header.content.len, spt->sip_header.content.s);
261 		if (parse_headers(msg, HDR_EOH_F, 0) != 0) {
262 			LM_ERR("ifc_checker: can't parse all headers\n");
263 			r = FALSE;
264 		} else
265 			r = isc_check_headers(spt, msg->headers);
266 		break;
267 	case IFC_SESSION_CASE:
268 		LM_DBG("ifc_check_spt:             SPT type %d -> Session Case  == %d ?\n",
269 				spt->type, spt->session_case);
270 		LM_DBG("ifc_check_spt:               Found session_case %d \n",
271 				direction);
272 		r = (direction == spt->session_case);
273 		break;
274 	case IFC_SESSION_DESC:
275 		LM_DBG("ifc_check_spt:             SPT type %d -> Session Desc.[%.*s]  %%= %.*s ?\n",
276 				spt->type, spt->session_desc.line.len, spt->session_desc.line.s, spt->session_desc.content.len, spt->session_desc.content.s);
277 
278 		if (parse_headers(msg, HDR_CONTENTTYPE_F | HDR_CONTENTLENGTH_F, 0) != 0) {
279 			LM_ERR("ifc_checker: can't parse all headers \n");
280 			r = FALSE;
281 		}
282 		r = isc_check_session_desc(spt, msg);
283 		break;
284 	default:
285 		LM_ERR("ifc_checker: unknown spt type %d \n", spt->type);
286 		return FALSE;
287 	}
288 	if (spt->condition_negated)
289 		return !r;
290 	else
291 		return r;
292 }
293 
294 /**
295  *	Check if an entire filter criteria matches a message
296  *	@param fc - the filter criteria
297  *	@param msg - the message
298  *	@param direction - if filter criteria is for originating/terminating/terminating_unregistered
299  *	@param registration_type - if the message is initial/re/de registration
300  *	@returns - 1 on success, 0 on failure
301  */
isc_check_filter_criteria(ims_filter_criteria * fc,struct sip_msg * msg,char direction,char registration_type)302 static int isc_check_filter_criteria(ims_filter_criteria *fc,
303 		struct sip_msg *msg, char direction, char registration_type) {
304 
305 	int i, partial, total, inside, outside, group;
306 	ims_trigger_point *t;
307 	t = fc->trigger_point;
308 
309 	/* If the trigger is missing -> always fwd */
310 	if (t == NULL)
311 		return TRUE;
312 	/* This shouldn't happen */
313 	if (msg == NULL)
314 		return FALSE;
315 
316 	if (t->condition_type_cnf == IFC_CNF) { //CNF
317 		inside = TRUE;
318 		outside = FALSE;
319 		partial = FALSE;
320 		total = TRUE;
321 	} else { //DNF
322 		inside = FALSE;
323 		outside = TRUE;
324 		partial = TRUE;
325 		total = FALSE;
326 	}
327 	LM_DBG("ifc_checker_trigger: Starting expression check: \n");
328 	group = t->spt[0].group;
329 	for (i = 0; i < t->spt_cnt; i++) {
330 		if (group != t->spt[i].group) { //jump to other group
331 			total = t->condition_type_cnf == IFC_CNF ?
332 					total && partial : total || partial;
333 			if (total == outside) {
334 				LM_DBG("ifc_checker_trigger: Total compromised, aborting...\n");
335 				return outside; // will never match from now on, so get out
336 			}
337 
338 			group = t->spt[i].group;
339 			partial = isc_check_spt(t->spt + i, msg, direction,
340 					registration_type);
341 			LM_DBG("ifc_checker_trigger:  - group %d => %d. \n", group, partial);
342 		} else { //in same group
343 			partial = t->condition_type_cnf == IFC_CNF ? partial || isc_check_spt(t->spt + i, msg, direction, registration_type) : partial
344 									&& isc_check_spt(t->spt + i, msg, direction, registration_type);
345 		}
346 
347 		if (partial == inside) { // can't change partial from now, so next group
348 			LM_DBG("ifc_checker_trigger:       - group compromised, skipping to next group\n");
349 			while (i + 1 < t->spt_cnt && t->spt[i + 1].group == group)
350 				i++;
351 			continue;
352 		}
353 	}
354 	total = t->condition_type_cnf == IFC_CNF ?
355 			total && partial : total || partial;
356 	LM_DBG("ifc_checker_trigger: Check finished => %d\n", total);
357 	return total;
358 }
359 
360 /**
361  * Create a new matching instance
362  * @param fc - filter criteria that match
363  * @param index - index of the filter that matches
364  * @returns the new isc_match* structure or NULL on error
365  */
isc_new_match(ims_filter_criteria * fc,int index)366 static inline isc_match* isc_new_match(ims_filter_criteria *fc, int index) {
367 	isc_match *r = 0;
368 
369 	r = pkg_malloc(sizeof (isc_match));
370 	if (!r) {
371 		LM_ERR("isc_new_match(): error allocating %lx bytes\n", sizeof (isc_match));
372 		return 0;
373 	}
374 	memset(r, 0, sizeof(isc_match));
375 	if (fc->application_server.server_name.len) {
376 		r->server_name.s = pkg_malloc(fc->application_server.server_name.len);
377 		if (!r->server_name.s) {
378 			LM_ERR("isc_new_match(): error allocating %d bytes\n",
379 					fc->application_server.server_name.len);
380 			pkg_free(r);
381 			return 0;
382 		}
383 		r->server_name.len = fc->application_server.server_name.len;
384 		memcpy(r->server_name.s, fc->application_server.server_name.s,
385 				fc->application_server.server_name.len);
386 	}
387 	r->default_handling = fc->application_server.default_handling;
388 	if (fc->application_server.service_info.len) {
389 		r->service_info.s = pkg_malloc(fc->application_server.service_info.len);
390 		if (!r->service_info.s) {
391 			LM_ERR("isc_new_match(): error allocating %d bytes\n",
392 					fc->application_server.service_info.len);
393 			if (r->server_name.s) {
394 				pkg_free(r->server_name.s);
395 			}
396 			pkg_free(r);
397 			return 0;
398 		}
399 		r->service_info.len = fc->application_server.service_info.len;
400 		memcpy(r->service_info.s, fc->application_server.service_info.s,
401 				fc->application_server.service_info.len);
402 	}
403 	r->index = index;
404 	r->include_register_request = fc->application_server.include_register_request;
405 	r->include_register_response = fc->application_server.include_register_response;
406 	return r;
407 }
408 
409 /**
410  * Find the next match and fill up the ifc_match structure with the position of the match
411  * @param uri - URI of the user for which to apply the IFC
412  * @param direction - direction of the session
413  * @param skip - how many IFCs to skip because already matched
414  * @param msg - the SIP initial request to check on
415  * @return - TRUE if found, FALSE if none found, end of search space
416  */
isc_checker_find(str uri,char direction,int skip,struct sip_msg * msg,int registered,udomain_t * d)417 isc_match* isc_checker_find(str uri, char direction, int skip,
418 		struct sip_msg *msg, int registered, udomain_t *d) {
419 	int expires;
420 	char registration_type;
421 	int i, j, k, cnt, si, sj, next;
422 
423 	impurecord_t *p;
424 	int ret;
425 
426 	ims_service_profile *sp;
427 	ims_filter_criteria *fc;
428 	isc_match *r;
429 
430 	if (skip == 0)
431 		LM_DBG("isc_checker_find: starting search\n");
432 	else
433 		LM_DBG("isc_checker_find: resuming search from %d\n", skip);
434 
435 	expires = cscf_get_expires(msg);
436 	if (!registered)
437 		registration_type = IFC_INITIAL_REGISTRATION;
438 	else if (expires > 0)
439 		registration_type = IFC_RE_REGISTRATION;
440 	else
441 		registration_type = IFC_DE_REGISTRATION;
442 
443 	isc_ulb.lock_udomain(d, &uri);
444 
445 	//need to get the urecord
446 	if ((ret = isc_ulb.get_impurecord(d, &uri, &p)) != 0) {
447 		isc_ulb.unlock_udomain(d, &uri);
448 		LM_ERR("Failure getting IMPU record for [%.*s] - ISC checker find METHOD: [%.*s]\n", uri.len, uri.s, msg->first_line.u.request.method.len, msg->first_line.u.request.method.s);
449 		return 0;
450 	};
451 
452 	LM_DBG("isc_checker_find(): got a r_public for the user %.*s\n",
453 			uri.len, uri.s);
454 	if (!p->s) {
455 		LM_DBG("isc_checker_find() : got an user without a subscription\n");
456 		//need to free the record somewhere
457 		//isc_ulb.release_impurecord(p);
458 		//need to do an unlock on the domain somewhere
459 		isc_ulb.unlock_udomain(d, &uri);
460 		return 0;
461 	}
462 
463 	/* find the starting fc as the skip-th one*/
464 	cnt = 0;
465 	si = 0;
466 	sj = 0;
467 
468 	LM_DBG("About to try p->s->service_profiles_cnt!! #profiles is %d\n",
469 			p->s->service_profiles_cnt);
470 	while (si < p->s->service_profiles_cnt) {
471 		LM_DBG("About to try p->s->service_profiles[a].filter_criterai_cnt\n");
472 		next = cnt + p->s->service_profiles[si].filter_criteria_cnt;
473 		if (cnt <= skip && skip < next) {
474 			sj = skip - cnt;
475 			cnt += sj;
476 			break;
477 		}
478 		cnt = next;
479 		si++;
480 	}
481 
482 	LM_DBG("DEBUG ISC: SECOND TIME About to try p->s->service_profiles_cnt!!\n");
483 	/* iterate through the rest and check for matches */
484 	i = si;
485 	while (i < p->s->service_profiles_cnt) {
486 		LM_DBG("DEBUG ISC : About to try p->s->service_profiles\n");
487 		sp = p->s->service_profiles + i;
488 		k = 0;
489 		LM_DBG("DEBUG ISC : About to try public identities\n");
490 		for (j = 0; j < sp->public_identities_cnt; j++) {
491 
492 			LM_DBG("DEBUG ISC : About to try WPSI\n");
493 			if (p->s->wpsi) {
494 				// here i should regexec again!
495 				// to check this , but anyway if i already got p
496 				// from the get_r_public , that is already checked...
497 				// or not if there is no wildcardPSI but ... then ...
498 				//isc_check_wpsi_match();
499 				k = 1;
500 				break;
501 
502 			} else {
503 				if (sp->public_identities[j].public_identity.len == uri.len
504 						&& strncasecmp(
505 								sp->public_identities[j].public_identity.s,
506 								uri.s, uri.len) == 0) {
507 					k = 1;
508 					break;
509 				}
510 			}
511 		}
512 
513 		if (!k) {/* this sp is not for this id */
514 
515 			cnt += sp->filter_criteria_cnt;
516 		} else {
517 
518 			for (j = sj; j < sp->filter_criteria_cnt; j++) {
519 				fc = sp->filter_criteria + j;
520 				if (fc->profile_part_indicator) {
521 					if (((registered == IMS_USER_REGISTERED)
522 							&& (*fc->profile_part_indicator))
523 							|| ((registered == IMS_USER_UNREGISTERED)
524 									&& !(*fc->profile_part_indicator))) {
525 						LM_DBG("isc_checker_find: this one is not good... ppindicator wrong \n");
526 						cnt++;
527 						continue;
528 					}
529 				}
530 
531 				if (isc_check_filter_criteria(fc, msg, direction, registration_type)) {
532 					LM_DBG("isc_checker_find: MATCH -> %.*s (%.*s) handling %d \n",
533 							fc->application_server.server_name.len, fc->application_server.server_name.s, fc->application_server.service_info.len, fc->application_server.service_info.s, fc->application_server.default_handling);
534 					r = isc_new_match(fc, cnt);
535 
536 					//need to free the record somewhere
537 					//isc_ulb.release_urecord(p);
538 					//need to do an unlock on the domain somewhere
539 					isc_ulb.unlock_udomain(d, &uri);
540 
541 					return r;
542 				} else {
543 					cnt++;
544 					continue;
545 				}
546 			}
547 		}
548 		i++;
549 		sj = 0;
550 	}
551 	//need to free the record somewhere
552 //	isc_ulb.release_urecord(p);
553 	//need to do an unlock on the domain somewhere
554 	isc_ulb.unlock_udomain(d, &uri);
555 
556 	return 0;
557 }
558 
559 /**
560  *	Free up all memory taken by a isc_match.
561  * @param m - match to deallocate
562  */
isc_free_match(isc_match * m)563 void isc_free_match(isc_match *m) {
564 	if (m) {
565 		if (m->server_name.s)
566 			pkg_free(m->server_name.s);
567 		if (m->service_info.s)
568 			pkg_free(m->service_info.s);
569 		pkg_free(m);
570 	}
571 	LM_DBG("isc_match_free: match position freed\n");
572 }
573 /**
574  *	Find if user is registered or not => TRUE/FALSE.
575  * This uses the S-CSCF registrar to get the state.
576  * @param uri - uri of the user to check
577  * @returns the reg_state
578  */
isc_is_registered(str * uri,udomain_t * d)579 int isc_is_registered(str *uri, udomain_t *d) {
580     int result = 0;
581     int ret = 0;
582     impurecord_t *p;
583 
584     isc_ulb.lock_udomain(d, uri);
585 
586     LM_DBG("Searching in usrloc\n");
587     //need to get the urecord
588     if ((ret = isc_ulb.get_impurecord(d, uri, &p)) != 0) {
589         LM_DBG("no record exists for [%.*s]\n", uri->len, uri->s);
590         isc_ulb.unlock_udomain(d, uri);
591         return result;
592     }
593 
594     LM_DBG("Finished searching usrloc\n");
595     result = p->reg_state;
596     isc_ulb.unlock_udomain(d, uri);
597 
598     return result;
599 }
600 
601