1 /*
2  * Copyright (C) 2012 Smile Communications, jason.penton@smilecoms.com
3  * Copyright (C) 2012 Smile Communications, richard.good@smilecoms.com
4  *
5  * The initial version of this code was written by Dragos Vingarzan
6  * (dragos(dot)vingarzan(at)fokus(dot)fraunhofer(dot)de and the
7  * Fruanhofer Institute. It was and still is maintained in a separate
8  * branch of the original SER. We are therefore migrating it to
9  * Kamailio/SR and look forward to maintaining it from here on out.
10  * 2011/2012 Smile Communications, Pty. Ltd.
11  * ported/maintained/improved by
12  * Jason Penton (jason(dot)penton(at)smilecoms.com and
13  * Richard Good (richard(dot)good(at)smilecoms.com) as part of an
14  * effort to add full IMS support to Kamailio/SR using a new and
15  * improved architecture
16  *
17  * NB: Alot of this code was originally part of OpenIMSCore,
18  * FhG Fokus.
19  * Copyright (C) 2004-2006 FhG Fokus
20  * Thanks for great work! This is an effort to
21  * break apart the various CSCF functions into logically separate
22  * components. We hope this will drive wider use. We also feel
23  * that in this way the architecture is more complete and thereby easier
24  * to manage in the Kamailio/SR environment
25  *
26  * This file is part of Kamailio, a free SIP server.
27  *
28  * Kamailio is free software; you can redistribute it and/or modify
29  * it under the terms of the GNU General Public License as published by
30  * the Free Software Foundation; either version 2 of the License, or
31  * (at your option) any later version
32  *
33  * Kamailio is distributed in the hope that it will be useful,
34  * but WITHOUT ANY WARRANTY; without even the implied warranty of
35  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
36  * GNU General Public License for more details.
37  *
38  * You should have received a copy of the GNU General Public License
39  * along with this program; if not, write to the Free Software
40  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
41  *
42  */
43 
44 #include "../../core/parser/msg_parser.h"
45 #include "../../core/parser/digest/digest.h"
46 #include "../../core/parser/parse_to.h"
47 #include "../../core/parser/parse_expires.h"
48 #include "../../core/parser/contact/parse_contact.h"
49 #include "../../core/parser/parse_uri.h"
50 #include "../../core/parser/parse_rr.h"
51 #include "../../core/parser/parse_nameaddr.h"
52 #include "../../core/data_lump.h"
53 #include "../../core/data_lump_rpl.h"
54 #include "../../core/parser/parse_from.h"
55 #include "../../core/parser/parse_content.h"
56 #include "ims_getters.h"
57 #include "../../core/parser/parse_ppi_pai.h"
58 
59 
60 /**
61  *	Delete parameters and stuff from uri.
62  * @param uri - the string to operate on
63  */
cscf_strip_uri(str * uri)64 static inline void cscf_strip_uri(str *uri)
65 {
66 	int i;
67 	/* Strip the ending */
68 	i = 0;
69 	while(i < uri->len && uri->s[i] != '@')
70 		i++;
71 	while(i < uri->len && uri->s[i] != ':' && uri->s[i] != '/'
72 			&& uri->s[i] != '&')
73 		i++;
74 	uri->len = i;
75 }
76 
77 /**
78  * Parses all the contact headers.
79  * @param msg - the SIP message
80  * @returns the first contact_body
81  */
cscf_parse_contacts(struct sip_msg * msg)82 contact_body_t *cscf_parse_contacts(struct sip_msg *msg)
83 {
84 	struct hdr_field *ptr;
85 	if(!msg)
86 		return 0;
87 
88 	if(parse_headers(msg, HDR_EOH_F, 0) < 0) {
89 		LM_ERR("Error parsing headers \n");
90 		return 0;
91 	}
92 	if(msg->contact) {
93 		ptr = msg->contact;
94 		while(ptr) {
95 			if(ptr->type == HDR_CONTACT_T) {
96 				if(ptr->parsed == 0) {
97 					if(parse_contact(ptr) < 0) {
98 						LM_DBG("error parsing contacts [%.*s]\n", ptr->body.len,
99 								ptr->body.s);
100 					}
101 				}
102 			}
103 			ptr = ptr->next;
104 		}
105 	}
106 	if(!msg->contact)
107 		return 0;
108 	return msg->contact->parsed;
109 }
110 
111 /**
112  * Returns the Private Identity extracted from the Authorization header.
113  * If none found there takes the SIP URI in To without the "sip:" prefix
114  * \todo - remove the fallback case to the To header
115  * @param msg - the SIP message
116  * @param realm - the realm to match in an Authorization header
117  * @returns the str containing the private id, no mem dup
118  */
cscf_get_private_identity(struct sip_msg * msg,str realm)119 str cscf_get_private_identity(struct sip_msg *msg, str realm)
120 {
121 	str pi = {0, 0};
122 	struct hdr_field *h = 0;
123 	int ret, i, res;
124 
125 	if((parse_headers(msg, HDR_AUTHORIZATION_F, 0) != 0)
126 			&& (parse_headers(msg, HDR_PROXYAUTH_F, 0) != 0)) {
127 		return pi;
128 	}
129 
130 	if(!msg->authorization) {
131 		goto fallback;
132 	}
133 	h = msg->authorization;
134 
135 	if(realm.len && realm.s) {
136 		ret = find_credentials(msg, &realm, HDR_AUTHORIZATION_T, &h);
137 		if(ret < 0) {
138 			ret = find_credentials(msg, &realm, HDR_PROXYAUTH_T, &h);
139 			if(ret < 0) {
140 				goto fallback;
141 			} else {
142 				if(ret > 0) {
143 					goto fallback;
144 				}
145 				h = msg->proxy_auth;
146 			}
147 		} else {
148 			if(ret > 0) {
149 				goto fallback;
150 			}
151 		}
152 	}
153 
154 	if(!h)
155 		goto fallback;
156 
157 	res = parse_credentials(h);
158 	if(res != 0) {
159 		LOG(L_ERR, "Error while parsing credentials\n");
160 		return pi;
161 	}
162 
163 	pi = ((auth_body_t *)h->parsed)->digest.username.whole;
164 	if(memchr(pi.s, '@', pi.len) == 0) {
165 		LM_DBG("no domain in username - required for IMPI - falling back "
166 			   "to IMPU\n");
167 		goto fallback;
168 	}
169 
170 	goto done;
171 
172 fallback:
173 	pi = cscf_get_public_identity(msg);
174 	if(pi.len > 4 && strncasecmp(pi.s, "sip:", 4) == 0) {
175 		pi.s += 4;
176 		pi.len -= 4;
177 	}
178 	for(i = 0; i < pi.len; i++)
179 		if(pi.s[i] == ';') {
180 			pi.len = i;
181 			break;
182 		}
183 done:
184 	return pi;
185 }
186 
187 /**
188  * Returns the Private Identity extracted from the Authorization header.
189  * If none found there takes the SIP URI in To without the "sip:" prefix
190  * \todo - remove the fallback case to the To header
191  * @param msg - the SIP message
192  * @param realm - the realm to match in an Authorization header
193  * @returns the str containing the private id, no mem dup
194  */
cscf_get_private_identity_from(struct sip_msg * msg,str realm)195 str cscf_get_private_identity_from(struct sip_msg *msg, str realm)
196 {
197 	str pi = {0, 0};
198 	struct hdr_field *h = 0;
199 	int ret, i, res;
200 
201 	if(parse_headers(msg, HDR_AUTHORIZATION_F, 0) != 0) {
202 		return pi;
203 	}
204 
205 	if(!msg->authorization) {
206 		goto fallback;
207 	}
208 	h = msg->authorization;
209 
210 	if(realm.len && realm.s) {
211 		ret = find_credentials(msg, &realm, HDR_AUTHORIZATION_T, &h);
212 		if(ret < 0) {
213 			goto fallback;
214 		} else if(ret > 0) {
215 			goto fallback;
216 		}
217 	}
218 
219 	res = parse_credentials(h);
220 	if(res != 0) {
221 		LOG(L_ERR, "Error while parsing credentials\n");
222 		return pi;
223 	}
224 
225 	pi = ((auth_body_t *)h->parsed)->digest.username.whole;
226 
227 	goto done;
228 
229 fallback:
230 	pi = cscf_get_public_identity_from(msg);
231 	if(pi.len > 4 && strncasecmp(pi.s, "sip:", 4) == 0) {
232 		pi.s += 4;
233 		pi.len -= 4;
234 	}
235 	for(i = 0; i < pi.len; i++)
236 		if(pi.s[i] == ';') {
237 			pi.len = i;
238 			break;
239 		}
240 done:
241 	return pi;
242 }
243 
244 /**
245  * Returns the Private Identity extracted from the Authorization header.
246  * If none found there takes the SIP URI in To without the "sip:" prefix
247  * \todo - remove the fallback case to the To header
248  * @param msg - the SIP message
249  * @param realm - the realm to match in an Authorization header
250  * @returns the str containing the private id, no mem dup
251  */
cscf_get_private_identity_no_realm(struct sip_msg * msg,str realm)252 str cscf_get_private_identity_no_realm(struct sip_msg *msg, str realm)
253 {
254 	str pi = {0, 0};
255 	struct hdr_field *h = 0;
256 	int i;
257 
258 	if(parse_headers(msg, HDR_AUTHORIZATION_F, 0) != 0) {
259 		return pi;
260 	}
261 
262 	if(!msg->authorization) {
263 		goto fallback;
264 	}
265 
266 	h = msg->authorization;
267 	if(h)
268 		pi = ((auth_body_t *)h->parsed)->digest.username.whole;
269 
270 	goto done;
271 
272 fallback:
273 	pi = cscf_get_public_identity(msg);
274 	if(pi.len > 4 && strncasecmp(pi.s, "sip:", 4) == 0) {
275 		pi.s += 4;
276 		pi.len -= 4;
277 	}
278 	for(i = 0; i < pi.len; i++)
279 		if(pi.s[i] == ';') {
280 			pi.len = i;
281 			break;
282 		}
283 done:
284 	return pi;
285 }
286 
287 /**
288  * Returns the Public Identity extracted from the To header
289  * @param msg - the SIP message
290  * @returns the str containing the public id, no mem dup
291  */
cscf_get_public_identity(struct sip_msg * msg)292 str cscf_get_public_identity(struct sip_msg *msg)
293 {
294 	str pu = {0, 0};
295 	struct to_body *to;
296 	int i;
297 
298 	if(parse_headers(msg, HDR_TO_F, 0) != 0) {
299 		return pu;
300 	}
301 
302 	if(get_to(msg) == NULL) {
303 		to = (struct to_body *)pkg_malloc(sizeof(struct to_body));
304 		if (to == NULL) {
305 			PKG_MEM_ERROR;
306 			return pu;
307 		}
308 		parse_to(msg->to->body.s, msg->to->body.s + msg->to->body.len, to);
309 		msg->to->parsed = to;
310 	} else
311 		to = (struct to_body *)msg->to->parsed;
312 
313 	pu = to->uri;
314 
315 	/* truncate to sip:username@host or tel:number */
316 	for(i = 4; i < pu.len; i++)
317 		if(pu.s[i] == ';' || pu.s[i] == '?' || pu.s[i] == ':') {
318 			pu.len = i;
319 		}
320 
321 	return pu;
322 }
323 
324 /**
325  * Returns the Public Identity extracted from the From header
326  * @param msg - the SIP message
327  * @returns the str containing the public id, no mem dup
328  */
cscf_get_public_identity_from(struct sip_msg * msg)329 str cscf_get_public_identity_from(struct sip_msg *msg)
330 {
331 	str pu = {0, 0};
332 	struct to_body *from;
333 	int i;
334 
335 	if(parse_headers(msg, HDR_FROM_F, 0) != 0) {
336 		return pu;
337 	}
338 
339 	if(get_from(msg) == NULL) {
340 		from = (struct to_body *)pkg_malloc(sizeof(struct to_body));
341 		if (from == NULL) {
342 			PKG_MEM_ERROR;
343 			return pu;
344 		}
345 		parse_to(msg->from->body.s, msg->from->body.s + msg->from->body.len,
346 				from);
347 		msg->from->parsed = from;
348 	} else
349 		from = (struct to_body *)msg->from->parsed;
350 
351 	pu = from->uri;
352 
353 	/* truncate to sip:username@host or tel:number */
354 	for(i = 4; i < pu.len; i++)
355 		if(pu.s[i] == ';' || pu.s[i] == '?' || pu.s[i] == ':') {
356 			pu.len = i;
357 		}
358 
359 	return pu;
360 }
361 
362 
363 /**
364  * Returns the expires value from the Expires header in the message.
365  * It searches into the Expires header and if not found returns -1
366  * @param msg - the SIP message, if available
367  * @is_shm - msg from from shared memory
368  * @returns the value of the expire or -1 if not found
369  */
cscf_get_expires_hdr(struct sip_msg * msg,int is_shm)370 int cscf_get_expires_hdr(struct sip_msg *msg, int is_shm)
371 {
372 	exp_body_t *exp;
373 	int expires;
374 	if(!msg)
375 		return -1;
376 	/*first search in Expires header */
377 	if(parse_headers(msg, HDR_EXPIRES_F, 0) != 0) {
378 		return -1;
379 	}
380 	if(msg->expires) {
381 		if(!msg->expires->parsed) {
382 			if(parse_expires(msg->expires) < 0) {
383 				LM_ERR("failed to parse expires header\n");
384 			}
385 		}
386 		if(msg->expires->parsed) {
387 			exp = (exp_body_t *)msg->expires->parsed;
388 			if(exp->valid) {
389 				expires = exp->val;
390 				if(is_shm) {
391 					free_expires((exp_body_t **)&exp);
392 					msg->expires->parsed = 0;
393 				}
394 				return expires;
395 			}
396 		}
397 	}
398 
399 	return -1;
400 }
401 
402 /**
403  * Returns the expires value from the message.
404  * First it searches into the Expires header and if not found it also looks
405  * into the expires parameter in the contact header
406  * @param msg - the SIP message
407  * @param is_shm - msg from shared memory
408  * @returns the value of the expire or the default 3600 if none found
409  */
cscf_get_max_expires(struct sip_msg * msg,int is_shm)410 int cscf_get_max_expires(struct sip_msg *msg, int is_shm)
411 {
412 	unsigned int exp;
413 	int max_expires = -1;
414 	struct hdr_field *h;
415 	contact_t *c;
416 	/*first search in Expires header */
417 	max_expires = cscf_get_expires_hdr(msg, is_shm);
418 
419 	cscf_parse_contacts(msg);
420 	for(h = msg->contact; h; h = h->next) {
421 		if(h->type == HDR_CONTACT_T && h->parsed) {
422 			for(c = ((contact_body_t *)h->parsed)->contacts; c; c = c->next) {
423 				if(c->expires) {
424 					if(!str2int(&(c->expires->body), (unsigned int *)&exp)
425 							&& (int)exp > max_expires)
426 						max_expires = exp;
427 				}
428 			}
429 		}
430 	}
431 
432 	if(is_shm) {
433 		for(h = msg->contact; h; h = h->next) {
434 			if(h->type == HDR_CONTACT_T && h->parsed) {
435 				free_contact((contact_body_t **)&(h->parsed));
436 				h->parsed = 0;
437 			}
438 		}
439 	}
440 
441 	return max_expires;
442 }
443 
444 /**
445  * Get the Public Identity from the Request URI of the message
446  * NB: free returned result str when done from shm
447  * @param msg - the SIP message
448  * @returns the public identity (don't forget to free from shm)
449  */
cscf_get_public_identity_from_requri(struct sip_msg * msg)450 str cscf_get_public_identity_from_requri(struct sip_msg *msg)
451 {
452 	str pu = {0, 0};
453 
454 	if(msg->first_line.type != SIP_REQUEST) {
455 		return pu;
456 	}
457 	if(parse_sip_msg_uri(msg) < 0) {
458 		return pu;
459 	}
460 
461 	if(msg->parsed_uri.type == TEL_URI_T) {
462 		pu.len = 4 + msg->parsed_uri.user.len;
463 		pu.s = shm_malloc(pu.len + 1);
464 		if(!pu.s) {
465 			SHM_MEM_ERROR;
466 			pu.len = 0;
467 			goto done;
468 		}
469 		sprintf(pu.s, "tel:%.*s", msg->parsed_uri.user.len,
470 				msg->parsed_uri.user.s);
471 	} else {
472 		pu.len = 4 + msg->parsed_uri.user.len + 1 + msg->parsed_uri.host.len;
473 		pu.s = shm_malloc(pu.len + 1);
474 		if(!pu.s) {
475 			SHM_MEM_ERROR;
476 			pu.len = 0;
477 			goto done;
478 		}
479 		sprintf(pu.s, "sip:%.*s@%.*s", msg->parsed_uri.user.len,
480 				msg->parsed_uri.user.s, msg->parsed_uri.host.len,
481 				msg->parsed_uri.host.s);
482 	}
483 
484 done:
485 	return pu;
486 }
487 
488 /**
489  * Get the contact from the Request URI of the message
490  * NB: free returned result str when done from shm
491  * @param msg - the SIP message
492  * @returns the contact (don't forget to free from shm)
493  *
494  * NOTE: should only be called when REQ URI has been converted sip:user@IP_ADDRESS:PORT or tel:IP_ADDRESS:PORT
495  */
cscf_get_contact_from_requri(struct sip_msg * msg)496 str cscf_get_contact_from_requri(struct sip_msg *msg)
497 {
498 	str pu = {0, 0};
499 
500 	if(msg->first_line.type != SIP_REQUEST) {
501 		return pu;
502 	}
503 	if(parse_sip_msg_uri(msg) < 0) {
504 		return pu;
505 	}
506 	if(!msg->parsed_uri.port.len) {
507 		return pu;
508 	}
509 
510 	if(msg->parsed_uri.type == TEL_URI_T) {
511 		pu.len = 4 + msg->parsed_uri.user.len + msg->parsed_uri.port.len
512 				 + 1 /*for colon before port*/;
513 		pu.s = shm_malloc(pu.len + 1);
514 		if(!pu.s) {
515 			SHM_MEM_ERROR;
516 			pu.len = 0;
517 			goto done;
518 		}
519 		sprintf(pu.s, "tel:%.*s:%.*s", msg->parsed_uri.user.len,
520 				msg->parsed_uri.user.s, msg->parsed_uri.port.len,
521 				msg->parsed_uri.port.s);
522 	} else {
523 		pu.len = 4 + msg->parsed_uri.user.len
524 				 + 1 /*for @*/ + msg->parsed_uri.host.len
525 				 + msg->parsed_uri.port.len + 1 /*for colon before port*/;
526 		pu.s = shm_malloc(pu.len + 1);
527 		if(!pu.s) {
528 			SHM_MEM_ERROR;
529 			pu.len = 0;
530 			goto done;
531 		}
532 		sprintf(pu.s, "sip:%.*s@%.*s:%.*s", msg->parsed_uri.user.len,
533 				msg->parsed_uri.user.s, msg->parsed_uri.host.len,
534 				msg->parsed_uri.host.s, msg->parsed_uri.port.len,
535 				msg->parsed_uri.port.s);
536 	}
537 
538 done:
539 	return pu;
540 }
541 
542 /**
543  * Finds if the message contains the orig parameter in the first Route header
544  * @param msg - the SIP message
545  * @param str1 - not used
546  * @param str2 - not used
547  * @returns #CSCF_RETURN_TRUE if yes, else #CSCF_RETURN_FALSE
548  */
cscf_has_originating(struct sip_msg * msg,char * str1,char * str2)549 int cscf_has_originating(struct sip_msg *msg, char *str1, char *str2)
550 {
551 	//int ret=CSCF_RETURN_FALSE;
552 	struct hdr_field *h;
553 	str *uri;
554 	rr_t *r;
555 
556 	if(parse_headers(msg, HDR_ROUTE_F, 0) < 0) {
557 		LM_DBG("I_originating: error parsing headers\n");
558 		return CSCF_RETURN_FALSE;
559 	}
560 	h = msg->route;
561 	if(!h) {
562 		LM_DBG("I_originating: Header Route not found\n");
563 		return CSCF_RETURN_FALSE;
564 	}
565 	if(parse_rr(h) < 0) {
566 		LM_DBG("I_originating: Error parsing as Route header\n");
567 		return CSCF_RETURN_FALSE;
568 	}
569 	r = (rr_t *)h->parsed;
570 
571 	uri = &r->nameaddr.uri;
572 	struct sip_uri puri;
573 	if(parse_uri(uri->s, uri->len, &puri) < 0) {
574 		LM_DBG("I_originating: Error while parsing the first route URI\n");
575 		return -1;
576 	}
577 	if(puri.params.len < 4)
578 		return CSCF_RETURN_FALSE;
579 	int c = 0;
580 	int state = 0;
581 	while(c < puri.params.len) {
582 		switch(puri.params.s[c]) {
583 			case 'o':
584 				if(state == 0)
585 					state = 1;
586 				break;
587 			case 'r':
588 				if(state == 1)
589 					state = 2;
590 				break;
591 			case 'i':
592 				if(state == 2)
593 					state = 3;
594 				break;
595 			case 'g':
596 				if(state == 3)
597 					state = 4;
598 				break;
599 			case ' ':
600 			case '\t':
601 			case '\r':
602 			case '\n':
603 			case ',':
604 			case ';':
605 				if(state == 4)
606 					return CSCF_RETURN_TRUE;
607 				state = 0;
608 				break;
609 			case '=':
610 				if(state == 4)
611 					return CSCF_RETURN_TRUE;
612 				state = -1;
613 				break;
614 			default:
615 				state = -1;
616 		}
617 		c++;
618 	}
619 
620 	return state == 4 ? CSCF_RETURN_TRUE : CSCF_RETURN_FALSE;
621 }
622 
623 str s_asserted_identity={"P-Asserted-Identity",19};
624 /**
625  * Looks for the P-Asserted-Identity header and extracts its content
626  * @param msg - the sip message
627  * @returns the asserted identity
628  */
cscf_get_asserted_identity(struct sip_msg * msg,int is_shm)629 str cscf_get_asserted_identity(struct sip_msg *msg, int is_shm) {
630 	int len;
631 	str uri = { 0, 0 };
632 
633 	if (!msg || !msg->pai)
634 		return uri;
635 
636 	if ((parse_pai_header(msg) == 0) && (msg->pai) && (msg->pai->parsed)) {
637 		to_body_t *pai = get_pai(msg)->id;
638 		if (!is_shm)
639 			return pai->uri;
640 
641 		//make a pkg malloc str to return to consuming function
642 		len = pai->uri.len + 1;
643 		uri.s = (char*) pkg_malloc(pai->uri.len + 1);
644 		if (!uri.s) {
645 			PKG_MEM_ERROR;
646 			return uri;
647 		}
648 		memset(uri.s, 0, len);
649 		memcpy(uri.s, pai->uri.s, pai->uri.len);
650 		uri.len = pai->uri.len;
651 
652 		p_id_body_t* ptr = (p_id_body_t*) msg->pai->parsed;
653 		msg->pai->parsed = 0;
654 		free_pai_ppi_body(ptr);
655 	}
656 	return uri;
657 }
658 
659 static str phone_context_s={";phone-context=",15};
660 /**
661  * Extracts the realm from a SIP/TEL URI.
662  * - SIP - the hostname
663  * - TEL - the phone-context parameter
664  * @param msg - the SIP message
665  * @returns the realm
666  */
cscf_get_realm_from_uri(str uri)667 str cscf_get_realm_from_uri(str uri)
668 {
669 	str realm={0,0};
670 	int i;
671 
672 	if (uri.len<5) {
673 		LM_DBG( "cscf_get_realm_from_uri: Error trying to extra realm from too short URI <%.*s>.\n",uri.len,uri.s);
674 		return realm;
675 	}
676 	if (strncasecmp(uri.s,"sip:",4)==0||
677 			strncasecmp(uri.s,"sips:",5)==0) {
678 		/* SIP URI */
679 		realm = uri;
680 		for(i=0;i<realm.len;i++)
681 			if (realm.s[i]=='@'){
682 				realm.s = realm.s + i + 1;
683 				realm.len = realm.len - i - 1;
684 				break;
685 			}
686 		if (!realm.len) realm = uri;
687 		for(i=0;i<realm.len;i++)
688 			if (realm.s[i]==';'||realm.s[i]=='&'||realm.s[i]==':') {
689 				realm.len = i;
690 				break;
691 			}
692 	}else
693 		if (strncasecmp(uri.s,"tel:",4)==0) {
694 			/* TEL URI */
695 			realm = uri;
696 			while(realm.s[0]!=';' && realm.len>0){
697 				realm.s++;
698 				realm.len--;
699 			}
700 			if (realm.len<1) {realm.len=0;return realm;}
701 			else{
702 				while(realm.len>phone_context_s.len){
703 					if (strncasecmp(realm.s,phone_context_s.s,phone_context_s.len)==0){
704 						realm.s+=phone_context_s.len;
705 						realm.len-=phone_context_s.len;
706 						for(i=0;i<realm.len;i++)
707 							if (realm.s[i]==';' || realm.s[i]=='&'){
708 								realm.len = i;
709 								break;
710 							}
711 						break;
712 					}
713 					realm.s++;
714 					realm.len--;
715 				}
716 			}
717 		}else{
718 			/* unknown... just extract between @ and ;? */
719 			realm = uri;
720 			for(i=0;i<realm.len;i++)
721 				if (realm.s[i]=='@'){
722 					realm.s = realm.s + i + 1;
723 					realm.len = realm.len - i - 1;
724 					break;
725 				}
726 			if (!realm.len) realm = uri;
727 			for(i=0;i<realm.len;i++)
728 				if (realm.s[i]==';'||realm.s[i]=='&'||realm.s[i]==':') {
729 					realm.len = i;
730 					break;
731 				}
732 		}
733 
734 	LM_DBG( "cscf_get_realm_from_uri: realm <%.*s>.\n",realm.len,realm.s);
735 	return realm;
736 }
737 
738 /**
739  * Delivers the Realm from request URI
740  * @param msg sip message
741  * @returns realm as String on success 0 on fail
742  */
cscf_get_realm_from_ruri(struct sip_msg * msg)743 str cscf_get_realm_from_ruri(struct sip_msg *msg)
744 {
745 	str realm={0,0};
746 	if (!msg || msg->first_line.type!=SIP_REQUEST){
747 		LM_DBG("cscf_get_realm_from_ruri: This is not a request!!!\n");
748 		return realm;
749 	}
750 	if (!msg->parsed_orig_ruri_ok)
751 		if (parse_orig_ruri(msg) < 0)
752 			return realm;
753 
754 	realm = msg->parsed_orig_ruri.host;
755 	return realm;
756 }
757 
758 /**
759  * Looks for the Call-ID header
760  * @param msg - the sip message
761  * @param hr - ptr to return the found hdr_field
762  * @returns the callid value
763  */
cscf_get_call_id(struct sip_msg * msg,struct hdr_field ** hr)764 str cscf_get_call_id(struct sip_msg *msg,struct hdr_field **hr)
765 {
766 	struct hdr_field *h;
767 	str call_id={0,0};
768 	if (hr) *hr = 0;
769 	if (!msg) return call_id;
770 	if (parse_headers(msg, HDR_CALLID_F, 0)<0){
771 		LM_DBG("cscf_get_call_id: error parsing headers\n");
772 		return call_id;
773 	}
774 	h = msg->callid;
775 	if (!h){
776 		LM_DBG("cscf_get_call_id: Header Call-ID not found\n");
777 		return call_id;
778 	}
779 	if (hr) *hr = h;
780 	call_id = h->body;
781 	return call_id;
782 }
783 
784 static str sos_uri_par={"sos", 3};
785 /**
786  * Check if the contact has an URI parameter with the value "sos",
787  * used for detecting an Emergency Registration
788  * http://tools.ietf.org/html/draft-patel-ecrit-sos-parameter-0x
789  * @param uri - contact uri to be checked
790  * @return 1 if found, 0 if not, -1 on error
791  */
cscf_get_sos_uri_param(str uri)792 int cscf_get_sos_uri_param(str uri)
793 {
794 	struct sip_uri puri;
795 	param_hooks_t h;
796 	param_t *p=0, *crt;
797 	enum pclass p_class = CLASS_URI;
798 	int ret;
799 
800 	ret = 0;
801 	p = NULL;
802 
803 	if(parse_uri(uri.s, uri.len, &puri)<0){
804 		LM_DBG("cscf_get_sos_uri_param: failed to parse %.*s\n",
805 				uri.len, uri.s);
806 		return -1;
807 	}
808 	if(puri.params.len <= 0)
809 		return 0;
810 
811 	LM_DBG( "cscf_get_sos_uri_param: searching through the uri parameters:%.*s\n",
812 			puri.params.len, puri.params.s);
813 
814 	if(parse_params(&(puri.params), p_class, &h, &p)){
815 		LM_DBG( "cscf_get_sos_uri_param:error while parsing uri parameters\n");
816 		ret = -1;
817 		goto end;
818 	}
819 
820 	for(crt = p ; crt ; crt=crt->next){
821 		LM_DBG( "cscf_get_sos_uri_param:name: %.*s body: %.*s\n",
822 				crt->name.len, crt->name.s,
823 				crt->body.len, crt->body.s);
824 		if((crt->name.len == sos_uri_par.len) &&
825 				(strncmp(crt->name.s, sos_uri_par.s, sos_uri_par.len) == 0)){
826 			ret =1;
827 			goto end;
828 		}
829 	}
830 
831 	end:
832 	if(p) free_params(p);
833 	return ret;
834 }
835 
836 str cscf_p_visited_network_id={"P-Visited-Network-ID",20};
837 /**
838  * Return the P-Visited-Network-ID header
839  * @param msg - the SIP message
840  * @returns the str with the header's body
841  */
cscf_get_visited_network_id(struct sip_msg * msg,struct hdr_field ** h)842 str cscf_get_visited_network_id(struct sip_msg *msg, struct hdr_field **h)
843 {
844 	str vnid={0,0};
845 	struct hdr_field *hdr;
846 
847 	if (h) *h=0;
848 	if (parse_headers(msg,HDR_EOH_F,0)!=0) {
849 		LM_DBG("cscf_get_visited_network_id: Error parsing until header EOH: \n");
850 		return vnid;
851 	}
852 	hdr = msg->headers;
853 	while(hdr){
854 		if (hdr->name.len==cscf_p_visited_network_id.len &&
855 				strncasecmp(hdr->name.s,cscf_p_visited_network_id.s,hdr->name.len)==0)
856 		{
857 			if (h) *h = hdr;
858 			vnid = hdr->body;
859 			goto done;
860 		}
861 		hdr = hdr->next;
862 	}
863 	LM_DBG("cscf_get_visited_network_id: P-Visited-Network-ID header not found \n");
864 
865 	done:
866 	LM_DBG("cscf_get_visited_network_id: <%.*s> \n",
867 			vnid.len,vnid.s);
868 	return vnid;
869 }
870 
871 /**
872  * Adds a header to the message as the first one in the message
873  * @param msg - the message to add a header to
874  * @param content - the str containing the new header
875  * @returns 1 on succes, 0 on failure
876  */
cscf_add_header_first(struct sip_msg * msg,str * hdr,int type)877 int cscf_add_header_first(struct sip_msg *msg, str *hdr,int type)
878 {
879 	struct hdr_field *first;
880 	struct lump* anchor,*l;
881 
882 	first = msg->headers;
883 	anchor = anchor_lump(msg, first->name.s - msg->buf, 0 , 0 );
884 
885 	if (anchor == NULL) {
886 		LM_DBG( "cscf_add_header_first: anchor_lump failed\n");
887 		return 0;
888 	}
889 
890 	if (!(l=insert_new_lump_before(anchor, hdr->s,hdr->len,type))){
891 		LM_ERR( "cscf_add_header_first: error creating lump for header\n" );
892 		return 0;
893 	}
894 	return 1;
895 }
896 
897 /**
898  * Returns the next header structure for a given header name.
899  * @param msg - the SIP message to look into
900  * @param header_name - the name of the header to search for
901  * @param last_header - last header to ignore in the search, or NULL if to start from the first one
902  * @returns the hdr_field on success or NULL if not found
903  */
cscf_get_next_header(struct sip_msg * msg,str header_name,struct hdr_field * last_header)904 struct hdr_field* cscf_get_next_header(struct sip_msg * msg ,
905 		str header_name,struct hdr_field* last_header)
906 {
907 	struct hdr_field *h;
908 	if (parse_headers(msg, HDR_EOH_F, 0)<0){
909 		LM_ERR("cscf_get_next_header_field: error parsing headers\n");
910 		return NULL;
911 	}
912 	if (last_header) h = last_header->next;
913 	else h = msg->headers;
914 	while(h){
915 		if (h->name.len==header_name.len &&strncasecmp(h->name.s,header_name.s,header_name.len)==0)
916 			break;
917 		h = h->next;
918 	}
919 	return h;
920 }
921 
922 /**
923  * Looks for the First Via header and returns its body.
924  * @param msg - the SIP message
925  * @param h - the hdr_field to fill with the result
926  * @returns the first via_body
927  */
cscf_get_first_via(struct sip_msg * msg,struct hdr_field ** h)928 struct via_body* cscf_get_first_via(struct sip_msg *msg,struct hdr_field **h)
929 {
930 	if (h) *h = 0;
931 
932 	if (!msg->h_via1 && parse_headers(msg,HDR_VIA_F,0)!=0) {
933 		LM_ERR("cscf_get_first_via: Error parsing until header Via: \n");
934 		return msg->h_via1->parsed;
935 	}
936 
937 	if (!msg->via1){
938 		LM_ERR( "cscf_get_first_via: Message does not contain Via header.\n");
939 		return msg->h_via1->parsed;
940 	}
941 
942 	return msg->h_via1->parsed;
943 }
944 
945 /**
946  * Looks for the UE Via in First Via header if its a request
947  * or in the last if its a response and returns its body
948  * @param msg - the SIP message
949  * @returns the via of the UE
950  */
cscf_get_ue_via(struct sip_msg * msg)951 struct via_body* cscf_get_ue_via(struct sip_msg *msg)
952 {
953 	struct via_body *vb=0;
954 
955 	if (msg->first_line.type==SIP_REQUEST) vb = cscf_get_first_via(msg,0);
956 	else vb = cscf_get_last_via(msg);
957 
958 	if (!vb) return 0;
959 
960 	if (vb->port == 0) vb->port=5060;
961 	return vb;
962 }
963 
964 /**
965  * Looks for the Last Via header and returns it.
966  * @param msg - the SIP message
967  * @returns the last via body body
968  */
cscf_get_last_via(struct sip_msg * msg)969 struct via_body* cscf_get_last_via(struct sip_msg *msg)
970 {
971 	struct hdr_field *h=0,*i;
972 	struct via_body *vb;
973 	if (parse_headers(msg,HDR_EOH_F,0)!=0) {
974 		LM_ERR("cscf_get_last_via: Error parsing until last header\n");
975 		return 0;
976 	}
977 
978 	i = msg->headers;
979 	while(i){
980 		if (i->type == HDR_VIA_T){
981 			h = i;
982 		}
983 		i = i->next;
984 	}
985 	if (!h) return 0;
986 	if (!h->parsed){
987 		vb = pkg_malloc(sizeof(struct via_body));
988 		if (!vb){
989 			PKG_MEM_ERROR;
990 			return 0;
991 		}
992 		parse_via(h->body.s,h->body.s+h->body.len,vb);
993 		h->parsed = vb;
994 	}
995 	vb = h->parsed;
996 	while(vb->next)
997 		vb = vb->next;
998 	return vb;
999 }
1000 
1001 /**
1002  * Looks for the WWW-Authenticate header and returns its body.
1003  * @param msg - the SIP message
1004  * @param h - the hdr_field to fill with the result
1005  * @returns the www-authenticate body
1006  */
cscf_get_authenticate(struct sip_msg * msg,struct hdr_field ** h)1007 str cscf_get_authenticate(struct sip_msg *msg,struct hdr_field **h)
1008 {
1009 	str auth={0,0};
1010 	struct hdr_field *hdr;
1011 	*h = 0;
1012 	if (parse_headers(msg,HDR_EOH_F,0)!=0) {
1013 		LM_ERR("cscf_get_authorization: Error parsing until header WWW-Authenticate: \n");
1014 		return auth;
1015 	}
1016 	hdr = msg->headers;
1017 	while(hdr){
1018 		if (hdr->name.len ==16  &&
1019 				strncasecmp(hdr->name.s,"WWW-Authenticate",16)==0)
1020 		{
1021 			*h = hdr;
1022 			auth = hdr->body;
1023 			break;
1024 		}
1025 		hdr = hdr->next;
1026 	}
1027 	if (!hdr){
1028 		LM_DBG( "cscf_get_authorization: Message does not contain WWW-Authenticate header.\n");
1029 		return auth;
1030 	}
1031 
1032 	return auth;
1033 }
1034 
1035 /**
1036  * Adds a header to the message
1037  * @param msg - the message to add a header to
1038  * @param content - the str containing the new header
1039  * @returns 1 on succes, 0 on failure
1040  */
cscf_add_header(struct sip_msg * msg,str * hdr,int type)1041 int cscf_add_header(struct sip_msg *msg, str *hdr,int type)
1042 {
1043 	struct hdr_field *last;
1044 	struct lump* anchor;
1045 	if (parse_headers(msg,HDR_EOH_F,0)!=0) {
1046 		LM_ERR("cscf_add_header: Error parsing until end of headers: \n");
1047 		return 0;
1048 	}
1049 	last = msg->headers;
1050 	while(last->next)
1051 		last = last->next;
1052 	anchor = anchor_lump(msg, last->name.s + last->len - msg->buf, 0 , 0);
1053 	if (anchor == NULL) {
1054 		LM_ERR( "cscf_add_header_first: anchor_lump failed\n");
1055 		return 0;
1056 	}
1057 
1058 	if (!insert_new_lump_after(anchor, hdr->s,hdr->len,type)){
1059 		LM_ERR( "cscf_add_header_first: error creating lump for header\n" );
1060 		return 0;
1061 	}
1062 	return 1;
1063 }
1064 
1065 /**
1066  *	Get the expires header value from a message.
1067  * @param msg - the SIP message
1068  * @returns the expires value or -1 if not found
1069  */
cscf_get_expires(struct sip_msg * msg)1070 int cscf_get_expires(struct sip_msg *msg)
1071 {
1072 	if (msg->expires) {
1073 		if (parse_expires(msg->expires) < 0) {
1074 			LM_INFO("ifc_get_expires:Error while parsing Expires header\n");
1075 			return -1;
1076 		}
1077 		return ((exp_body_t*) msg->expires->parsed)->val;
1078 	} else {
1079 		return -1;
1080 	}
1081 }
1082 
1083 
1084 static str bye_s={"BYE",3};
1085 static str ack_s={"ACK",3};
1086 static str prack_s={"PRACK",5};
1087 static str update_s={"UPDATE",6};
1088 static str notify_s={"NOTIFY",6};
1089 /**
1090  * Check if the message is an initial request for a dialog.
1091  *		- BYE, PRACK, UPDATE, NOTIFY belong to an already existing dialog
1092  * @param msg - the message to check
1093  * @returns 1 if initial, 0 if not
1094  */
cscf_is_initial_request(struct sip_msg * msg)1095 int cscf_is_initial_request(struct sip_msg *msg)
1096 {
1097 	if (msg->first_line.type != SIP_REQUEST ) return 0;
1098 	if (strncasecmp(msg->first_line.u.request.method.s,bye_s.s,bye_s.len)==0) return 0;
1099 	if (strncasecmp(msg->first_line.u.request.method.s,ack_s.s,ack_s.len)==0) return 0;
1100 	if (strncasecmp(msg->first_line.u.request.method.s,prack_s.s,prack_s.len)==0) return 0;
1101 	if (strncasecmp(msg->first_line.u.request.method.s,update_s.s,update_s.len)==0) return 0;
1102 	if (strncasecmp(msg->first_line.u.request.method.s,notify_s.s,notify_s.len)==0) return 0;
1103 	return 1;
1104 }
1105 
1106 /**
1107  *	Get the public identity from P-Asserted-Identity, or From if asserted not found.
1108  * @param msg - the SIP message
1109  * @param uri - uri to fill into
1110  * @returns 1 if found, 0 if not
1111  */
cscf_get_originating_user(struct sip_msg * msg,str * uri)1112 int cscf_get_originating_user( struct sip_msg * msg, str *uri )
1113 {
1114 	struct to_body * from;
1115 	*uri = cscf_get_asserted_identity(msg, 0);
1116 	if (!uri->len) {
1117 		/* Fallback to From header */
1118 		if ( parse_from_header( msg ) == -1 ) {
1119 			LM_ERR("ERROR:cscf_get_originating_user: unable to extract URI from FROM header\n" );
1120 			return 0;
1121 		}
1122 		if (!msg->from) return 0;
1123 		from = (struct to_body*) msg->from->parsed;
1124 		*uri = from->uri;
1125 		cscf_strip_uri(uri);
1126 	}
1127 	DBG("DEBUG:cscf_get_originating_user: From %.*s\n", uri->len,uri->s );
1128 	return 1;
1129 }
1130 
1131 /**
1132  *	Get public identity from Request-URI for terminating.
1133  * returns in uri the freshly pkg allocated uri - don't forget to free
1134  * @param msg - the SIP message
1135  * @param uri - uri to fill into
1136  * @returns 1 if found, else 0
1137  */
cscf_get_terminating_user(struct sip_msg * msg,str * uri)1138 int cscf_get_terminating_user( struct sip_msg * msg, str *uri )
1139 {
1140 	*uri = cscf_get_public_identity_from_requri(msg);
1141 	if (!uri->len) return 0;
1142 	return 1;
1143 }
1144 
1145 str cscf_p_access_network_info={"P-Access-Network-Info",21};
1146 
1147 /**
1148  * Return the P-Access-Network-Info header
1149  * @param msg - the SIP message
1150  * @returns the str with the header's body
1151  */
1152 
cscf_get_access_network_info(struct sip_msg * msg,struct hdr_field ** h)1153 str cscf_get_access_network_info(struct sip_msg *msg, struct hdr_field **h)
1154 {
1155 	str ani={0,0};
1156 	struct hdr_field *hdr;
1157 
1158 	*h=0;
1159 	if (parse_headers(msg,HDR_EOH_F,0)!=0) {
1160 		LM_DBG("cscf_get_access_network_info: Error parsing until header EOH: \n");
1161 		return ani;
1162 	}
1163 	hdr = msg->headers;
1164 	while(hdr){
1165 		if (hdr->name.len==cscf_p_access_network_info.len &&
1166 				strncasecmp(hdr->name.s,cscf_p_access_network_info.s,hdr->name.len)==0)
1167 		{
1168 			*h = hdr;
1169 			ani = hdr->body;
1170 			goto done;
1171 		}
1172 		hdr = hdr->next;
1173 	}
1174 	LM_DBG("cscf_get_access_network_info: P-Access-Network-Info header not found \n");
1175 
1176 	done:
1177 	LM_DBG("cscf_get_access_network_info: <%.*s> \n",
1178 			ani.len,ani.s);
1179 	return ani;
1180 }
1181 
1182 str cscf_p_charging_vector={"P-Charging-Vector",17};
1183 
1184 /**
1185  * Return the P-Charging-Vector header
1186  * @param msg - the SIP message
1187  * @returns the str with the header's body
1188  */
1189 
cscf_get_charging_vector(struct sip_msg * msg,struct hdr_field ** h)1190 str cscf_get_charging_vector(struct sip_msg *msg, struct hdr_field **h)
1191 {
1192 	str cv={0,0};
1193 	struct hdr_field *hdr;
1194 
1195 	*h=0;
1196 	if (parse_headers(msg,HDR_EOH_F,0)!=0) {
1197 		LM_DBG("cscf_get_charging_vector: Error parsing until header EOH: \n");
1198 		return cv;
1199 	}
1200 	hdr = msg->headers;
1201 	while(hdr){
1202 		if (hdr->name.len==cscf_p_charging_vector.len &&
1203 				strncasecmp(hdr->name.s,cscf_p_charging_vector.s,hdr->name.len)==0)
1204 		{
1205 			*h = hdr;
1206 			cv = hdr->body;
1207 			goto done;
1208 		}
1209 		hdr = hdr->next;
1210 	}
1211 	LM_DBG("cscf_get_charging_vector: P-Charging-Vector header not found \n");
1212 
1213 	done:
1214 	LM_DBG("cscf_get_charging_vector: <%.*s> \n",
1215 			cv.len,cv.s);
1216 	return cv;
1217 }
1218 
cscf_get_p_charging_vector(struct sip_msg * msg,str * icid,str * orig_ioi,str * term_ioi)1219 int cscf_get_p_charging_vector(struct sip_msg *msg, str * icid, str * orig_ioi,
1220 		str * term_ioi) {
1221 	struct hdr_field* header = 0;
1222 	str header_body = { 0, 0 };
1223 	char * p;
1224 	int index;
1225 	str temp = { 0, 0 };
1226 
1227 	if (parse_headers(msg, HDR_EOH_F, 0) < 0) {
1228 		LM_ERR("cscf_get_p_charging_vector: error parsing headers\n");
1229 		return 0;
1230 	}
1231 	header = msg->headers;
1232 	while (header) {
1233 		if (header->name.len == cscf_p_charging_vector.len
1234 				&& strncasecmp(header->name.s, cscf_p_charging_vector.s, cscf_p_charging_vector.len) == 0)
1235 			break;
1236 		header = header->next;
1237 	}
1238 	if (!header) {
1239 		LM_DBG("no header %.*s was found\n", cscf_p_charging_vector.len, cscf_p_charging_vector.s);
1240 		return 0;
1241 	}
1242 	if (!header->body.s || !header->body.len)
1243 		return 0;
1244 
1245 	str_dup(header_body, header->body, pkg);
1246 
1247 	LM_DBG("p_charging_vector body is %.*s\n", header_body.len, header_body.s);
1248 
1249 	p = strtok(header_body.s, " ;:\r\t\n\"=");
1250 	loop: if (p > (header_body.s + header_body.len))
1251 		return 1;
1252 
1253 	if (strncmp(p, "icid-value", 10) == 0) {
1254 		p = strtok(NULL, " ;:\r\t\n\"=");
1255 		if (p > (header_body.s + header_body.len)) {
1256 			LM_ERR("cscf_get_p_charging_vector: no value for icid\n");
1257 			return 0;
1258 		}
1259 		temp.s = p;
1260 		temp.len = 0;
1261 		while (*p != '\"') {
1262 			temp.len = temp.len + 1;
1263 			p++;
1264 		}
1265 		icid->len = temp.len;
1266 		index = temp.s - header_body.s;
1267 		LM_DBG("icid len %i, index %i\n", temp.len, index);
1268 		icid->s = header->body.s + index;
1269 		LM_DBG("icid is %.*s\n", icid->len, icid->s);
1270 		p = strtok(NULL, " ;:\r\t\n\"=");
1271 		goto loop;
1272 	} else if (strncmp(p, "orig-ioi", 8) == 0) {
1273 
1274 		p = strtok(NULL, " ;:\r\t\n\"=");
1275 		if (p > (header_body.s + header_body.len)) {
1276 			LM_ERR("cscf_get_p_charging_vector: no value for icid\n");
1277 			return 0;
1278 		}
1279 		temp.s = p;
1280 		temp.len = 0;
1281 		while (*p != '\"') {
1282 			temp.len = temp.len + 1;
1283 			p++;
1284 		}
1285 		orig_ioi->len = temp.len;
1286 		index = temp.s - header_body.s;
1287 		LM_DBG("orig ioi len %i, index %i\n", temp.len, index);
1288 		orig_ioi->s = header->body.s + index;
1289 		LM_DBG("orig_ioi is %.*s\n", orig_ioi->len, orig_ioi->s);
1290 		p = strtok(NULL, " ;:\r\t\n\"=");
1291 		goto loop;
1292 	} else if (strncmp(p, "term-ioi", 8) == 0) {
1293 
1294 		p = strtok(NULL, " ;:\r\t\n\"=");
1295 		if (p > (header_body.s + header_body.len)) {
1296 			LM_ERR("cscf_get_p_charging_vector: no value for icid\n");
1297 			return 0;
1298 		}
1299 		temp.s = p;
1300 		temp.len = 0;
1301 		while (*p != '\"') {
1302 			temp.len = temp.len + 1;
1303 			p++;
1304 		}
1305 		term_ioi->len = temp.len;
1306 		term_ioi->s = header->body.s + (temp.s - header_body.s);
1307 		p = strtok(NULL, " ;:\r\t\n\"=");
1308 		goto loop;
1309 	} else {
1310 		p = strtok(NULL, " ;:\r\t\n\"=");
1311 		goto loop;
1312 	}
1313 
1314 	LM_DBG("end\n");
1315 	str_free(header_body, pkg);
1316 	return 1;
1317 	out_of_memory:
1318 	PKG_MEM_ERROR;
1319 	return 0;
1320 }
1321 
1322 /**
1323  * Get the from tag
1324  * @param msg - the SIP message to look into
1325  * @param tag - the pointer to the tag to write to
1326  * @returns 0 on error or 1 on success
1327  */
cscf_get_from_tag(struct sip_msg * msg,str * tag)1328 int cscf_get_from_tag(struct sip_msg* msg, str* tag)
1329 {
1330 	struct to_body* from;
1331 
1332 	if (!msg || parse_from_header(msg)<0||!msg->from||!msg->from->parsed){
1333 		LM_DBG("cscf_get_from_tag: error parsing From header\n");
1334 		if (tag) {tag->s = 0;tag->len = 0;}
1335 		return 0;
1336 	}
1337 	from = msg->from->parsed;
1338 	if (tag) *tag = from->tag_value;
1339 	return 1;
1340 }
1341 
1342 /**
1343  * Get the to tag
1344  * @param msg  - the SIP Message to look into
1345  * @param tag - the pointer to the tag to write to
1346  * @returns 0 on error or 1 on success
1347  */
cscf_get_to_tag(struct sip_msg * msg,str * tag)1348 int cscf_get_to_tag(struct sip_msg* msg, str* tag)
1349 {
1350 	if (!msg || !msg->to) {
1351 		LM_DBG("cscf_get_to_tag(): To header field missing\n");
1352 		if (tag) {tag->s = 0;tag->len = 0;}
1353 		return 0;
1354 	}
1355 
1356 	if (tag) *tag = get_to(msg)->tag_value;
1357 	return 1;
1358 }
1359 
1360 /**
1361  * Get the local uri from the From header.
1362  * @param msg - the message to look into
1363  * @param local_uri - ptr to fill with the value
1364  * @returns 1 on success or 0 on error
1365  */
cscf_get_from_uri(struct sip_msg * msg,str * local_uri)1366 int cscf_get_from_uri(struct sip_msg* msg,str *local_uri)
1367 {
1368 	struct to_body* from;
1369 
1370 	if (!msg || parse_from_header(msg)<0 || !msg->from || !msg->from->parsed){
1371 		LM_DBG("cscf_get_from_uri: error parsing From header\n");
1372 		if (local_uri) {local_uri->s = 0;local_uri->len = 0;}
1373 		return 0;
1374 	}
1375 	from = msg->from->parsed;
1376 	if (local_uri) *local_uri = from->uri;
1377 	return 1;
1378 
1379 }
1380 
1381 /**
1382  * Get the local uri from the To header.
1383  * @param msg - the message to look into
1384  * @param local_uri - ptr to fill with the value
1385  * @returns 1 on success or 0 on error
1386  */
cscf_get_to_uri(struct sip_msg * msg,str * local_uri)1387 int cscf_get_to_uri(struct sip_msg* msg,str *local_uri)
1388 {
1389 	struct to_body* to=	NULL;
1390 
1391 	if (!msg || !msg->to || !msg->to->parsed || parse_headers(msg,HDR_TO_F,0)==-1 ){
1392 		LM_DBG("cscf_get_to_uri: error parsing TO header\n");
1393 		if (local_uri) {local_uri->s = 0;local_uri->len = 0;}
1394 		return 0;
1395 	}
1396 	to = msg->to->parsed;
1397 	if (local_uri) *local_uri = to->uri;
1398 	return 1;
1399 
1400 }
1401 
1402 /**
1403  * Looks for the Event header and extracts its content.
1404  * @param msg - the sip message
1405  * @returns the string event value or an empty string if none found
1406  */
cscf_get_event(struct sip_msg * msg)1407 str cscf_get_event(struct sip_msg *msg)
1408 {
1409 	str e={0,0};
1410 	if (!msg) return e;
1411 	if (parse_headers(msg, HDR_EVENT_F, 0) != -1 && msg->event &&
1412 			msg->event->body.len > 0)
1413 	{
1414 		e.len = msg->event->body.len;
1415 		e.s = msg->event->body.s;
1416 	}
1417 	return e;
1418 }
1419 
1420 /**
1421  * Returns the content of the P-Associated-URI header
1422  * Public_id is pkg_alloced and should be later freed.
1423  * Inside values are not duplicated.
1424  * @param msg - the SIP message to look into
1425  * @param public_id - array to be allocated and filled with the result
1426  * @param public_id_cnt - the size of the public_id array
1427  * @param is_shm - msg from shared memory
1428  * @returns 1 on success or 0 on error
1429  */
cscf_get_p_associated_uri(struct sip_msg * msg,str ** public_id,int * public_id_cnt,int is_shm)1430 int cscf_get_p_associated_uri(struct sip_msg *msg, str **public_id,
1431 		int *public_id_cnt, int is_shm) {
1432 	struct hdr_field *h;
1433 	rr_t *r, *r2;
1434 	*public_id = 0;
1435 	*public_id_cnt = 0;
1436 
1437 	if (!msg)
1438 		return 0;
1439 	if (parse_headers(msg, HDR_EOH_F, 0) < 0) {
1440 		LM_ERR("error parsing headers\n");
1441 		return 0;
1442 	}
1443 	h = msg->headers;
1444 	while (h) {
1445 		if (h->name.len == 16
1446 				&& strncasecmp(h->name.s, "P-Associated-URI", 16) == 0) {
1447 			break;
1448 		}
1449 		h = h->next;
1450 	}
1451 	if (!h) {
1452 		LM_DBG("Header P-Associated-URI not found\n");
1453 		return 0;
1454 	}
1455 	if (parse_rr(h) < 0) {
1456 		LM_DBG("Error parsing as Route header\n");
1457 		return 0;
1458 	}
1459 	r = (rr_t*) h->parsed;
1460 	h->type = HDR_ROUTE_T;
1461 	*public_id_cnt = 0;
1462 	r2 = r;
1463 	while (r2) {
1464 		(*public_id_cnt) = (*public_id_cnt) + 1;
1465 		r2 = r2->next;
1466 	}
1467 	*public_id = pkg_malloc(sizeof(str)*(*public_id_cnt));
1468 	if (*public_id==NULL) {
1469 		PKG_MEM_ERROR;
1470 		return 0;
1471 	}
1472 	r2 = r;
1473 	*public_id_cnt = 0;
1474 	while (r2) {
1475 		(*public_id)[(*public_id_cnt)] = r2->nameaddr.uri;
1476 		(*public_id_cnt) = (*public_id_cnt) + 1;
1477 		r2 = r2->next;
1478 	}
1479 
1480 	if (is_shm) {
1481 		r = (rr_t*) h->parsed;
1482 		h->parsed = 0;
1483 		free_rr(&r);
1484 	}
1485 
1486 	return 1;
1487 }
1488 
1489 static str realm_p={"realm=\"",7};
1490 /**
1491  * Looks for the realm parameter in the Authorization header and returns its value.
1492  * @param msg - the SIP message
1493  * @returns the realm
1494  */
cscf_get_realm(struct sip_msg * msg)1495 str cscf_get_realm(struct sip_msg *msg)
1496 {
1497         str realm={0,0};
1498         int i,k;
1499 
1500         if (parse_headers(msg,HDR_AUTHORIZATION_F,0)!=0) {
1501                 LM_DBG("Error parsing until header Authorization: \n");
1502                 return realm;
1503         }
1504 
1505         if (!msg->authorization){
1506                 LM_DBG("Message does not contain Authorization header.\n");
1507                 return realm;
1508         }
1509 
1510         k = msg->authorization->body.len - realm_p.len;
1511         for(i=0;i<k;i++)
1512          if (strncasecmp(msg->authorization->body.s+i,realm_p.s,realm_p.len)==0){
1513                 realm.s = msg->authorization->body.s+ i + realm_p.len;
1514                 i+=realm_p.len;
1515                 while(i<msg->authorization->body.len && msg->authorization->body.s[i]!='\"'){
1516                         i++;
1517                         realm.len++;
1518                 }
1519                 break;
1520          }
1521 
1522         if (!realm.len){
1523                 LM_DBG("Realm parameter not found.\n");
1524                 return realm;
1525         }
1526         LM_DBG("realm <%.*s>.\n",realm.len,realm.s);
1527         return realm;
1528 }
1529 
1530 /**
1531  * Returns the content of the Service-Route header.
1532  * data vector is pkg_alloced and should be later freed
1533  * inside values are not duplicated
1534  * @param msg - the SIP message
1535  * @param size - size of the returned vector, filled with the result
1536  * @param is_shm - msg from shared memory
1537  * @returns - the str vector of uris
1538  */
cscf_get_service_route(struct sip_msg * msg,int * size,int is_shm)1539 str* cscf_get_service_route(struct sip_msg *msg, int *size, int is_shm) {
1540 	struct hdr_field *h;
1541 	rr_t *r, *r2;
1542 	str *x = 0;
1543 	int k;
1544 	if (!size)
1545 		return 0;
1546 
1547 	*size = 0;
1548 
1549 	if (!msg)
1550 		return 0;
1551 	if (parse_headers(msg, HDR_EOH_F, 0) < 0) {
1552 		LM_ERR("error parsing headers\n");
1553 		return 0;
1554 	}
1555 	h = msg->headers;
1556 	while (h) {
1557 		if (h->name.len == 13
1558 				&& strncasecmp(h->name.s, "Service-Route", 13) == 0) {
1559 			if (parse_rr(h) < 0) {
1560 				LM_ERR("Error parsing as Route header\n");
1561 				continue;
1562 			}
1563 			r = (rr_t*) h->parsed;
1564 			h->type = HDR_ROUTE_T;
1565 			r2 = r;
1566 			k = 0;
1567 			while (r2) {
1568 				k++;
1569 				r2 = r2->next;
1570 			}
1571 			if (!k) {
1572 				LM_DBG("No items in this Service-Route\n");
1573 				continue;
1574 			}
1575 			x = pkg_reallocxf(x,(*size+k)*sizeof(str));
1576 			if (!x) {
1577 				LM_ERR("Error our of pkg memory");
1578 				return 0;
1579 			}
1580 			r2 = r;
1581 			while (r2) {
1582 				x[*size] = r2->nameaddr.uri;
1583 				(*size) = (*size) + 1;
1584 				r2 = r2->next;
1585 			}
1586 		}
1587 		h = h->next;
1588 	}
1589 	if (is_shm) {
1590 		h = msg->headers;
1591 		while (h) {
1592 			if (h->name.len == 13
1593 					&& strncasecmp(h->name.s, "Service-Route", 13) == 0) {
1594 				r = (rr_t*) h->parsed;
1595 				h->parsed = 0;
1596 				free_rr(&r);
1597 			}
1598 			h = h->next;
1599 		}
1600 	}
1601 
1602 	return x;
1603 }
1604 
1605 /**
1606  * Returns the s_dialog_direction from the direction string.
1607  * @param direction - "orig" or "term"
1608  * @returns the s_dialog_direction if ok or #DLG_MOBILE_UNKNOWN if not found
1609  */
cscf_get_dialog_direction(char * direction)1610 enum cscf_dialog_direction cscf_get_dialog_direction(char *direction)
1611 {
1612 	switch(direction[0]){
1613 		case 'o':
1614 		case 'O':
1615 		case '0':
1616 			return CSCF_MOBILE_ORIGINATING;
1617 		case 't':
1618 		case 'T':
1619 		case '1':
1620 			return CSCF_MOBILE_TERMINATING;
1621 		default:
1622 			LM_WARN("Unknown direction %s",direction);
1623 			return CSCF_MOBILE_UNKNOWN;
1624 	}
1625 }
1626 
cscf_get_content_length(struct sip_msg * msg)1627 long cscf_get_content_length (struct sip_msg* msg)
1628 {
1629 	int cl = 0;
1630 	if (!msg)
1631 		return 0;
1632 	if (parse_headers(msg, HDR_CONTENTLENGTH_F, 0) != -1 && msg->content_length
1633 			&& msg->content_length->parsed)
1634 		cl = get_content_length(msg);
1635 	return cl;
1636 
1637 }
1638 
1639 /**
1640  * Looks for the Contact header and extracts its content
1641  * @param msg - the sip message
1642  * @returns the first contact in the message
1643  */
cscf_get_contact(struct sip_msg * msg)1644 str cscf_get_contact(struct sip_msg *msg)
1645 {
1646 	str id={0,0};
1647 	struct hdr_field *h;
1648 	struct contact_body *cb;
1649 
1650 	if (!msg) return id;
1651 	if (parse_headers(msg, HDR_CONTACT_F, 0)<0) {
1652 		LM_ERR("ERR:cscf_get_contact: Error parsing headers until Contact.\n");
1653 		return id;
1654 	}
1655 
1656 	h = msg->contact;
1657 	if (!h) {
1658 		LM_ERR("ERR:cscf_get_contact: Contact header not found.\n");
1659 		return id;
1660 	}
1661 	if (h->parsed==0 &&
1662 		parse_contact(h)<0){
1663 		LM_ERR("ERR:cscf_get_contact: Error parsing contacts.\n");
1664 		return id;
1665 	}
1666 
1667 	cb = (struct contact_body *)h->parsed;
1668 	if (!cb || !cb->contacts){
1669 		LM_ERR("ERR:cscf_get_contact: No contacts in header.\n");
1670 		return id;
1671 	}
1672 	id = cb->contacts->uri;
1673 
1674 	return id;
1675 }
1676 
1677 /**
1678  * Adds a header to the reply message
1679  * @param msg - the request to add a header to its reply
1680  * @param content - the str containing the new header
1681  * @returns 1 on succes, 0 on failure
1682  */
cscf_add_header_rpl(struct sip_msg * msg,str * hdr)1683 int cscf_add_header_rpl(struct sip_msg *msg, str *hdr)
1684 {
1685 	if (add_lump_rpl( msg, hdr->s, hdr->len, LUMP_RPL_HDR)==0) {
1686 		LM_ERR("ERR:cscf_add_header_rpl: Can't add header <%.*s>\n",
1687 			hdr->len,hdr->s);
1688  		return 0;
1689  	}
1690  	return 1;
1691 }
1692 
1693 
1694 /**
1695  * Looks for the Call-ID header
1696  * @param msg - the sip message
1697  * @param hr - ptr to return the found hdr_field
1698  * @returns the callid value
1699  */
cscf_get_cseq(struct sip_msg * msg,struct hdr_field ** hr)1700 int cscf_get_cseq(struct sip_msg *msg,struct hdr_field **hr)
1701 {
1702 	struct hdr_field *h;
1703 	struct cseq_body *cseq;
1704 	int nr = 0,i;
1705 
1706 	if (hr) *hr = 0;
1707 	if (!msg) return 0;
1708 	if (parse_headers(msg, HDR_CSEQ_F, 0)<0){
1709 		LM_ERR("ERR:cscf_get_cseq: error parsing headers\n");
1710 		return 0;
1711 	}
1712 	h = msg->cseq;
1713 	if (!h){
1714 		LM_ERR("ERR:cscf_get_cseq: Header CSeq not found\n");
1715 		return 0;
1716 	}
1717 	if (hr) *hr = h;
1718 	if (!h->parsed){
1719 		cseq = pkg_malloc(sizeof(struct cseq_body));
1720 		if (!cseq){
1721 			PKG_MEM_ERROR;
1722 			return 0;
1723 		}
1724 		parse_cseq(h->body.s,h->body.s+h->body.len,cseq);
1725 		h->parsed = cseq;
1726 	}else
1727 		cseq = (struct cseq_body*) h->parsed;
1728 	for(i=0;i<cseq->number.len;i++)
1729 		nr = (nr*10)+(cseq->number.s[i]-'0');
1730 	return nr;
1731 }
1732 
1733 static str s_called_party_id={"P-Called-Party-ID",17};
1734 /**
1735  * Looks for the P-Called-Party-ID header and extracts the public identity from it
1736  * @param msg - the sip message
1737  * @param hr - ptr to return the found hdr_field
1738  * @returns the P-Called_Party-ID
1739  */
cscf_get_public_identity_from_called_party_id(struct sip_msg * msg,struct hdr_field ** hr)1740 str cscf_get_public_identity_from_called_party_id(struct sip_msg *msg,struct hdr_field **hr)
1741 {
1742 	str id={0,0};
1743 	struct hdr_field *h;
1744 	int after_semi_colon=0;
1745 	int len=0;
1746 	int i=0;
1747 
1748 	if (hr) *hr=0;
1749 	if (!msg) return id;
1750 	if (parse_headers(msg, HDR_EOH_F, 0)<0) {
1751 		return id;
1752 	}
1753 	h = msg->headers;
1754 	while(h)
1755 	{
1756 		if (h->name.len == s_called_party_id.len  &&
1757 			strncasecmp(h->name.s,s_called_party_id.s,s_called_party_id.len)==0)
1758 		{
1759 			id = h->body;
1760 			while(id.len && (id.s[0]==' ' || id.s[0]=='\t' || id.s[0]=='<')){
1761 				id.s = id.s+1;
1762 				id.len --;
1763 			}
1764 			while(id.len && (id.s[id.len-1]==' ' || id.s[id.len-1]=='\t' || id.s[id.len-1]=='>')){
1765 				id.len--;
1766 			}
1767 			//get only text in front of ';' there might not even be a semi-colon
1768 			//this caters for extra information after the public identity - e.g. phone-context
1769 			len= id.len;
1770 			for(i=0; i<len;i++) {
1771 			    if(id.s[i]==';'){
1772 				//found semi-colon
1773 				after_semi_colon = 1;
1774 			    }
1775 			    if(after_semi_colon){
1776 				id.len--;
1777 			    }
1778 			}
1779 			if (hr) *hr = h;
1780 			return id;
1781 		}
1782 		h = h->next;
1783 	}
1784 	return id;
1785 }
1786 
1787