1 /*
2  * Copyright (C) 2001-2003 FhG Fokus
3  *
4  * This file is part of Kamailio, a free SIP server.
5  *
6  * Kamailio is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version
10  *
11  * Kamailio is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
19  *
20  */
21 
22 /*!
23  * \file
24  * \brief TM ::
25  * \ingroup tm
26  */
27 
28 
29 #include <string.h>
30 #include "../../core/mem/shm_mem.h"
31 #include "../../core/dprint.h"
32 #include "../../core/parser/contact/parse_contact.h"
33 #include "../../core/parser/parse_to.h"
34 #include "../../core/parser/parse_from.h"
35 #include "../../core/parser/parse_uri.h"
36 #include "../../core/trim.h"
37 #include "../../core/ut.h"
38 #include "../../core/config.h"
39 #include "dlg.h"
40 #include "t_reply.h"
41 #include "../../core/parser/parser_f.h"
42 
43 /* next added to allow automatical tag generation */
44 #include "callid.h"
45 #include "uac.h"
46 
47 #define NORMAL_ORDER 0  /* Create route set in normal order - UAS */
48 #define REVERSE_ORDER 1 /* Create route set in reverse order - UAC */
49 
50 
51 #ifdef DIALOG_CALLBACKS
52 
53 struct new_dlg_cb
54 {
55 	int types;
56 	struct new_dlg_cb *next;
57 	dialog_cb *callback;
58 	void *param;
59 };
60 
61 static struct new_dlg_cb *new_dlg_cb_list = 0;
62 /* callbacks for new dialogs (called each time a new dialog (uas or uac) is
63  * created)
64  * params: type - DLG_CB_UAC or DLG_CB_UAS
65  *            f - callback function
66  *        param - parameter passed to the callback; if allocated it must
67  *                  be allocated in shared mem.
68  * returns < 0 on error
69  * WARNING: this callbacks can be registered only before forking (in mod_init)
70  */
register_new_dlg_cb(int type,dialog_cb f,void * param)71 int register_new_dlg_cb(int type, dialog_cb f, void *param)
72 {
73 	struct new_dlg_cb *dlg_cb;
74 
75 	dlg_cb = shm_malloc(sizeof(struct new_dlg_cb));
76 	if(dlg_cb == 0) {
77 		SHM_MEM_ERROR;
78 		return E_OUT_OF_MEM;
79 	}
80 	dlg_cb->types = type;
81 	dlg_cb->callback = f;
82 	dlg_cb->param = param;
83 	dlg_cb->next = new_dlg_cb_list;
84 	new_dlg_cb_list = dlg_cb;
85 	return 0;
86 }
87 
88 
destroy_new_dlg_cbs()89 void destroy_new_dlg_cbs()
90 {
91 	struct new_dlg_cb *c;
92 	struct new_dlg_cb *n;
93 
94 	c = new_dlg_cb_list;
95 	while(c) {
96 		n = c->next;
97 		shm_free(c);
98 		c = n;
99 	}
100 	new_dlg_cb_list = 0;
101 }
102 
103 
run_new_dlg_callbacks(int type,dlg_t * dlg,struct sip_msg * msg)104 static void run_new_dlg_callbacks(int type, dlg_t *dlg, struct sip_msg *msg)
105 {
106 	struct new_dlg_cb *c;
107 	for(c = new_dlg_cb_list; c; c = c->next) {
108 		if(c->types & type)
109 			c->callback(type, dlg, msg);
110 	}
111 }
112 
113 
register_dlg_tmcb(int types,dlg_t * dlg,transaction_cb f,void * param)114 int register_dlg_tmcb(int types, dlg_t *dlg, transaction_cb f, void *param)
115 {
116 	/* only TMCB_DLG bad TMCB_DESTROY allowed */
117 	if((types & (TMCB_DLG | TMCB_DESTROY)) != types) {
118 		LM_CRIT("bad types %d\n", types);
119 		return E_BUG;
120 	}
121 	if(f == 0) {
122 		LM_CRIT("null callback function\n");
123 		return E_BUG;
124 	}
125 	return insert_tmcb(&dlg->dlg_callbacks, types, f, param, NULL);
126 }
127 
128 
129 /* per dialog callbacks receive only the transaction, send buffer, destination
130  * and the retr. buff */
run_trans_dlg_callbacks(dlg_t * dlg,struct cell * trans,struct retr_buf * rbuf)131 void run_trans_dlg_callbacks(
132 		dlg_t *dlg, struct cell *trans, struct retr_buf *rbuf)
133 {
134 	struct tmcb_params params;
135 
136 	if(dlg->dlg_callbacks.first == 0)
137 		return;
138 	memset(&params, 0, sizeof(params));
139 	if(rbuf) {
140 		params.t_rbuf = rbuf;
141 		params.dst = &rbuf->dst;
142 		params.send_buf.s = rbuf->buffer;
143 		params.send_buf.len = rbuf->buffer_len;
144 	}
145 
146 	run_trans_callbacks_internal(&dlg->dlg_callbacks, TMCB_DLG, trans, &params);
147 }
148 
149 /* TMCB_DESTROY per dialog callbacks */
destroy_trans_dlg_callbacks(dlg_t * dlg)150 static void destroy_trans_dlg_callbacks(dlg_t *dlg)
151 {
152 	struct tmcb_params params;
153 	struct tm_callback *cbp;
154 
155 	if((dlg->dlg_callbacks.first == 0)
156 			|| ((dlg->dlg_callbacks.reg_types & TMCB_DESTROY) == 0))
157 		return;
158 	memset(&params, 0, sizeof(params));
159 	for(cbp = (struct tm_callback *)dlg->dlg_callbacks.first; cbp;
160 			cbp = cbp->next) {
161 		if(cbp->types & TMCB_DESTROY) {
162 			params.param = &(cbp->param);
163 			cbp->callback(0, 0, &params);
164 		}
165 	}
166 }
167 #endif /* DIALOG_CALLBACKS */
168 
169 /*** Temporary hack ! */
170 /*
171  * This function skips name part
172  * uri parsed by parse_contact must be used
173  * (the uri must not contain any leading or
174  *  trailing part and if angle bracket were
175  *  used, right angle bracket must be the
176  *  last character in the string)
177  *
178  * _s will be modified so it should be a tmp
179  * copy
180  */
get_raw_uri(str * _s)181 void get_raw_uri(str *_s)
182 {
183 	char *aq;
184 
185 	if(_s->s[_s->len - 1] == '>') {
186 		aq = find_not_quoted(_s, '<');
187 		_s->len -= aq - _s->s + 2;
188 		_s->s = aq + 1;
189 	}
190 }
191 
192 
193 /*
194  * Make a copy of a str structure using shm_malloc
195  */
str_duplicate(str * _d,str * _s)196 static inline int str_duplicate(str *_d, str *_s)
197 {
198 	_d->s = shm_malloc(_s->len);
199 	if(!_d->s) {
200 		SHM_MEM_ERROR;
201 		return -1;
202 	}
203 
204 	memcpy(_d->s, _s->s, _s->len);
205 	_d->len = _s->len;
206 	return 0;
207 }
208 
209 
210 /*
211  * Calculate dialog hooks
212  * @return:
213  *  negative : error
214  *  0 : no routes present
215  *  F_RB_NH_LOOSE : routes present, next hop is loose router
216  *  F_RB_NH_STRICT: next hop is strict.
217  */
calculate_hooks(dlg_t * _d)218 static inline int calculate_hooks(dlg_t *_d)
219 {
220 	str *uri;
221 	struct sip_uri puri;
222 	int nhop;
223 
224 	/* we might re-calc. some existing hooks =>
225 	 * reset all the hooks to 0 */
226 	memset(&_d->hooks, 0, sizeof(_d->hooks));
227 	if(_d->route_set) {
228 		uri = &_d->route_set->nameaddr.uri;
229 		if(parse_uri(uri->s, uri->len, &puri) < 0) {
230 			LM_ERR("error while parsing URI\n");
231 			return -1;
232 		}
233 
234 		if(puri.lr.s) {
235 			if(_d->rem_target.s)
236 				_d->hooks.request_uri = &_d->rem_target;
237 			else
238 				_d->hooks.request_uri = &_d->rem_uri;
239 			_d->hooks.next_hop = &_d->route_set->nameaddr.uri;
240 			_d->hooks.first_route = _d->route_set;
241 			nhop = F_RB_NH_LOOSE;
242 		} else {
243 			_d->hooks.request_uri = &_d->route_set->nameaddr.uri;
244 			_d->hooks.next_hop = _d->hooks.request_uri;
245 			_d->hooks.first_route = _d->route_set->next;
246 			if(_d->rem_target.len > 0)
247 				_d->hooks.last_route = &_d->rem_target;
248 			else
249 				_d->hooks.last_route = NULL; /* ? */
250 			nhop = F_RB_NH_STRICT;
251 		}
252 	} else {
253 		if(_d->rem_target.s)
254 			_d->hooks.request_uri = &_d->rem_target;
255 		else
256 			_d->hooks.request_uri = &_d->rem_uri;
257 
258 		if(_d->dst_uri.s)
259 			_d->hooks.next_hop = &_d->dst_uri;
260 		else
261 			_d->hooks.next_hop = _d->hooks.request_uri;
262 
263 		nhop = 0;
264 		/*
265 		 * the routes in the hooks need to be reset because if the route_set
266 		 * was dropped somewhere else then these will remain set without the
267 		 * actual routes existing any more
268 		 */
269 		_d->hooks.first_route = 0;
270 		_d->hooks.last_route = 0;
271 	}
272 
273 	if((_d->hooks.request_uri) && (_d->hooks.request_uri->s)
274 			&& (_d->hooks.request_uri->len)) {
275 		_d->hooks.ru.s = _d->hooks.request_uri->s;
276 		_d->hooks.ru.len = _d->hooks.request_uri->len;
277 		_d->hooks.request_uri = &_d->hooks.ru;
278 		get_raw_uri(_d->hooks.request_uri);
279 	}
280 	if((_d->hooks.next_hop) && (_d->hooks.next_hop->s)
281 			&& (_d->hooks.next_hop->len)) {
282 		_d->hooks.nh.s = _d->hooks.next_hop->s;
283 		_d->hooks.nh.len = _d->hooks.next_hop->len;
284 		_d->hooks.next_hop = &_d->hooks.nh;
285 		get_raw_uri(_d->hooks.next_hop);
286 	}
287 
288 	return nhop;
289 }
290 
291 /*
292  * wrapper to calculate_hooks
293  * added by dcm
294  */
w_calculate_hooks(dlg_t * _d)295 int w_calculate_hooks(dlg_t *_d)
296 {
297 	return calculate_hooks(_d);
298 }
299 
300 /*
301  * Create a new dialog
302  */
new_dlg_uac(str * _cid,str * _ltag,unsigned int _lseq,str * _luri,str * _ruri,dlg_t ** _d)303 int new_dlg_uac(str *_cid, str *_ltag, unsigned int _lseq, str *_luri,
304 		str *_ruri, dlg_t **_d)
305 {
306 	dlg_t *res;
307 	str generated_cid;
308 	str generated_ltag;
309 
310 	if(!_cid) { /* if not given, compute new one */
311 		generate_callid(&generated_cid);
312 		_cid = &generated_cid;
313 	}
314 	if(_cid && (!_ltag)) { /* if not given, compute new one */
315 		generate_fromtag(&generated_ltag, _cid, _ruri);
316 		_ltag = &generated_ltag;
317 	}
318 	if(_lseq == 0)
319 		_lseq = DEFAULT_CSEQ;
320 
321 	if(!_cid || !_ltag || !_luri || !_ruri || !_d) {
322 		LM_ERR("invalid parameter value\n");
323 		return -1;
324 	}
325 
326 	res = (dlg_t *)shm_malloc(sizeof(dlg_t));
327 	if(res == 0) {
328 		SHM_MEM_ERROR;
329 		return -2;
330 	}
331 
332 	/* Clear everything */
333 	memset(res, 0, sizeof(dlg_t));
334 
335 	/* Make a copy of Call-ID */
336 	if(str_duplicate(&res->id.call_id, _cid) < 0)
337 		return -3;
338 	/* Make a copy of local tag (usually From tag) */
339 	if(str_duplicate(&res->id.loc_tag, _ltag) < 0)
340 		return -4;
341 	/* Make a copy of local URI (usually From) */
342 	if(str_duplicate(&res->loc_uri, _luri) < 0)
343 		return -5;
344 	/* Make a copy of remote URI (usually To) */
345 	if(str_duplicate(&res->rem_uri, _ruri) < 0)
346 		return -6;
347 	/* Make a copy of local sequence (usually CSeq) */
348 	res->loc_seq.value = _lseq;
349 	/* And mark it as set */
350 	res->loc_seq.is_set = 1;
351 
352 	*_d = res;
353 
354 	if(calculate_hooks(*_d) < 0) {
355 		LM_ERR("error while calculating hooks\n");
356 		/* FIXME: free everything here */
357 		shm_free(res);
358 		return -2;
359 	}
360 #ifdef DIALOG_CALLBACKS
361 	run_new_dlg_callbacks(DLG_CB_UAC, res, 0);
362 #endif
363 
364 	return 0;
365 }
366 
367 /**
368  * @brief Store display names into a dialog
369  * @param _d - dialog structure
370  * @param _ldname - local party display name
371  * @param _rdname - remote party dispaly name
372  * @return 0 on success; negative on error
373  */
374 
dlg_add_extra(dlg_t * _d,str * _ldname,str * _rdname)375 int dlg_add_extra(dlg_t *_d, str *_ldname, str *_rdname)
376 {
377 	if(!_d || !_ldname || !_rdname) {
378 		LM_ERR("Invalid parameters\n");
379 		return -1;
380 	}
381 
382 	/* Make a copy of local Display Name */
383 	if(shm_str_dup(&_d->loc_dname, _ldname) < 0)
384 		return -2;
385 	/* Make a copy of remote Display Name */
386 	if(shm_str_dup(&_d->rem_dname, _rdname) < 0)
387 		return -3;
388 
389 	return 0;
390 }
391 
392 /*
393  * Parse Contact header field body and extract URI
394  * Does not parse headers !!
395  */
get_contact_uri(struct sip_msg * _m,str * _uri)396 static inline int get_contact_uri(struct sip_msg *_m, str *_uri)
397 {
398 	contact_t *c;
399 
400 	_uri->len = 0;
401 	_uri->s = 0;
402 
403 	if(!_m->contact)
404 		return 1;
405 
406 	if(parse_contact(_m->contact) < 0) {
407 		LM_ERR("error while parsing Contact body\n");
408 		return -2;
409 	}
410 
411 	c = ((contact_body_t *)_m->contact->parsed)->contacts;
412 
413 	if(!c) {
414 		LM_ERR("empty body or * contact\n");
415 		return -3;
416 	}
417 
418 	_uri->s = c->uri.s;
419 	_uri->len = c->uri.len;
420 	return 0;
421 }
422 
423 
424 /*
425  * Extract tag from To header field of a response
426  * Doesn't parse message headers !!
427  */
get_to_tag(struct sip_msg * _m,str * _tag)428 static inline int get_to_tag(struct sip_msg *_m, str *_tag)
429 {
430 	if(!_m->to) {
431 		LM_ERR("To header field missing\n");
432 		return -1;
433 	}
434 
435 	if(get_to(_m)->tag_value.len) {
436 		_tag->s = get_to(_m)->tag_value.s;
437 		_tag->len = get_to(_m)->tag_value.len;
438 	} else {
439 		_tag->len = 0;
440 	}
441 
442 	return 0;
443 }
444 
445 
446 /*
447  * Extract tag from From header field of a request
448  */
get_from_tag(struct sip_msg * _m,str * _tag)449 static inline int get_from_tag(struct sip_msg *_m, str *_tag)
450 {
451 	if(parse_from_header(_m) == -1) {
452 		LM_ERR("error while parsing From header\n");
453 		return -1;
454 	}
455 
456 	if(get_from(_m)->tag_value.len) {
457 		_tag->s = get_from(_m)->tag_value.s;
458 		_tag->len = get_from(_m)->tag_value.len;
459 	} else {
460 		_tag->len = 0;
461 	}
462 
463 	return 0;
464 }
465 
466 
467 /*
468  * Extract Call-ID value
469  * Doesn't parse headers !!
470  */
get_callid(struct sip_msg * _m,str * _cid)471 static inline int get_callid(struct sip_msg *_m, str *_cid)
472 {
473 	if(_m->callid == 0) {
474 		LM_ERR("Call-ID not found\n");
475 		return -1;
476 	}
477 
478 	_cid->s = _m->callid->body.s;
479 	_cid->len = _m->callid->body.len;
480 	trim(_cid);
481 	return 0;
482 }
483 
revert_route(rr_t * r)484 static rr_t *revert_route(rr_t *r)
485 {
486 	rr_t *a, *b;
487 
488 	a = NULL;
489 
490 	while(r) {
491 		b = r->next;
492 		r->next = a;
493 		a = r;
494 		r = b;
495 	}
496 
497 	return a;
498 }
499 
500 /*
501  * Create a copy of route set either in normal or reverse order
502  */
get_route_set(struct sip_msg * _m,rr_t ** _rs,unsigned char _order)503 static inline int get_route_set(
504 		struct sip_msg *_m, rr_t **_rs, unsigned char _order)
505 {
506 	struct hdr_field *ptr;
507 	rr_t *last, *p, *t;
508 
509 	last = 0;
510 
511 	ptr = _m->record_route;
512 	while(ptr) {
513 		if(ptr->type == HDR_RECORDROUTE_T) {
514 			if(parse_rr(ptr) < 0) {
515 				LM_ERR("error while parsing Record-Route body\n");
516 				goto error;
517 			}
518 
519 			p = (rr_t *)ptr->parsed;
520 			if(shm_duplicate_rr(&t, p) < 0) {
521 				LM_ERR("error while duplicating rr_t\n");
522 				goto error;
523 			}
524 			if(!*_rs)
525 				*_rs = t;
526 			if(last)
527 				last->next = t;
528 			last = t;
529 			while(last->next)
530 				last = last->next; /* !!! there may be more routes in one hdr field !!! */
531 		}
532 		ptr = ptr->next;
533 	}
534 	if((*_rs) && (_order != NORMAL_ORDER)) {
535 		/* better to revert the route outside of cycle above */
536 		*_rs = revert_route(*_rs);
537 	}
538 
539 	return 0;
540 
541 error:
542 	shm_free_rr(_rs);
543 	return -1;
544 }
545 
546 /*
547  * Extract method from CSeq header field
548  */
get_cseq_method(struct sip_msg * _m,str * _method)549 static inline int get_cseq_method(struct sip_msg *_m, str *_method)
550 {
551 	if(!_m->cseq && ((parse_headers(_m, HDR_CSEQ_F, 0) == -1) || !_m->cseq)) {
552 		LM_ERR("error while parsing CSeq\n");
553 		return -1;
554 	}
555 
556 	_method->s = get_cseq(_m)->method.s;
557 	_method->len = get_cseq(_m)->method.len;
558 	return 0;
559 }
560 
561 
refresh_dialog_resp(struct sip_msg * _m,target_refresh_t is_target_refresh)562 static inline int refresh_dialog_resp(
563 		struct sip_msg *_m, target_refresh_t is_target_refresh)
564 {
565 	str method;
566 
567 	switch(is_target_refresh) {
568 		case IS_NOT_TARGET_REFRESH:
569 			return 0;
570 		case IS_TARGET_REFRESH:
571 			return 1;
572 		case TARGET_REFRESH_UNKNOWN:
573 			if(get_cseq_method(_m, &method) < 0)
574 				return 0; /* error */
575 			if((method.len == 6) && !memcmp("INVITE", method.s, 6))
576 				return 1;
577 			else
578 				return 0;
579 	}
580 	return 0;
581 }
582 
refresh_dialog_req(struct sip_msg * _m,target_refresh_t is_target_refresh)583 static inline int refresh_dialog_req(
584 		struct sip_msg *_m, target_refresh_t is_target_refresh)
585 {
586 	switch(is_target_refresh) {
587 		case IS_NOT_TARGET_REFRESH:
588 			return 0;
589 		case IS_TARGET_REFRESH:
590 			return 1;
591 		case TARGET_REFRESH_UNKNOWN:
592 			return (_m->first_line.u.request.method_value == METHOD_INVITE);
593 			break;
594 	}
595 	return 0;
596 }
597 
598 /*
599  * Extract all necessary information from a response and put it
600  * in a dialog structure
601  */
response2dlg(struct sip_msg * _m,dlg_t * _d)602 static inline int response2dlg(struct sip_msg *_m, dlg_t *_d)
603 {
604 	str contact, rtag;
605 
606 	/* Parse the whole message, we will need all Record-Route headers */
607 	if(parse_headers(_m, HDR_EOH_F, 0) == -1) {
608 		LM_ERR("error while parsing headers\n");
609 		return -1;
610 	}
611 
612 	if(get_contact_uri(_m, &contact) < 0)
613 		return -2;
614 	if(_d->rem_target.s) {
615 		shm_free(_d->rem_target.s);
616 		_d->rem_target.s = 0;
617 		_d->rem_target.len = 0;
618 	}
619 	if(_d->dst_uri.s) {
620 		shm_free(_d->dst_uri.s);
621 		_d->dst_uri.s = 0;
622 		_d->dst_uri.len = 0;
623 	}
624 	if(contact.len && str_duplicate(&_d->rem_target, &contact) < 0)
625 		return -3;
626 
627 	if(get_to_tag(_m, &rtag) < 0)
628 		goto err1;
629 	if(rtag.len && str_duplicate(&_d->id.rem_tag, &rtag) < 0)
630 		goto err1;
631 
632 	if(get_route_set(_m, &_d->route_set, REVERSE_ORDER) < 0)
633 		goto err2;
634 
635 	return 0;
636 err2:
637 	if(_d->id.rem_tag.s)
638 		shm_free(_d->id.rem_tag.s);
639 	_d->id.rem_tag.s = 0;
640 	_d->id.rem_tag.len = 0;
641 
642 err1:
643 	if(_d->rem_target.s)
644 		shm_free(_d->rem_target.s);
645 	_d->rem_target.s = 0;
646 	_d->rem_target.len = 0;
647 	return -4;
648 }
649 
650 
651 /*
652  * Handle dialog in DLG_NEW state, we will be processing the
653  * first response
654  */
dlg_new_resp_uac(dlg_t * _d,struct sip_msg * _m)655 static inline int dlg_new_resp_uac(dlg_t *_d, struct sip_msg *_m)
656 {
657 	int code;
658 	/*
659 	 * Dialog is in DLG_NEW state, we will copy remote
660 	 * target URI, remote tag if present, and route-set
661 	 * if present. And we will transit into DLG_CONFIRMED
662 	 * if the response was 2xx and to DLG_DESTROYED if the
663 	 * request was a negative final response.
664 	 */
665 
666 	code = _m->first_line.u.reply.statuscode;
667 
668 	if(code < 200) {
669 		/* A provisional response, do nothing, we could
670 		 * update remote tag and route set but we will do that
671 		 * for a positive final response anyway and I don't want
672 		 * bet on presence of these fields in provisional responses
673 		 *
674 		 * Send a request to jan@iptel.org if you need to update
675 		 * the structures here
676 		 */
677 	} else if((code >= 200) && (code < 299)) {
678 		/* A final response, update the structures and transit
679 		 * into DLG_CONFIRMED
680 		 */
681 		if(response2dlg(_m, _d) < 0)
682 			return -1;
683 		_d->state = DLG_CONFIRMED;
684 
685 		if(calculate_hooks(_d) < 0) {
686 			LM_ERR("error while calculating hooks\n");
687 			return -2;
688 		}
689 	} else {
690 		/* A negative final response, mark the dialog as destroyed
691 		 * Again, I do not update the structures here because it
692 		 * makes no sense to me, a dialog shouldn't be used after
693 		 * it is destroyed
694 		 */
695 		_d->state = DLG_DESTROYED;
696 		/* Signalize the termination with positive return value */
697 		return 1;
698 	}
699 
700 	return 0;
701 }
702 
703 
704 /*
705  * Handle dialog in DLG_EARLY state, we will be processing either
706  * next provisional response or a final response
707  */
dlg_early_resp_uac(dlg_t * _d,struct sip_msg * _m)708 static inline int dlg_early_resp_uac(dlg_t *_d, struct sip_msg *_m)
709 {
710 	int code;
711 	code = _m->first_line.u.reply.statuscode;
712 
713 	if(code < 200) {
714 		/* We are in early state already, do nothing */
715 	} else if((code >= 200) && (code <= 299)) {
716 		/* Warning - we can handle here response for non-initial request (for
717 		 * example UPDATE within early INVITE/BYE dialog) and move into
718 		 * confirmed state may be error! But this depends on dialog type... */
719 
720 		/* Same as in dlg_new_resp_uac */
721 		/* A final response, update the structures and transit
722 		 * into DLG_CONFIRMED
723 		 */
724 		if(response2dlg(_m, _d) < 0)
725 			return -1;
726 		_d->state = DLG_CONFIRMED;
727 
728 		if(calculate_hooks(_d) < 0) {
729 			LM_ERR("error while calculating hooks\n");
730 			return -2;
731 		}
732 	} else {
733 		/* Else terminate the dialog */
734 		_d->state = DLG_DESTROYED;
735 		/* Signalize the termination with positive return value */
736 		return 1;
737 	}
738 
739 	return 0;
740 }
741 
742 
743 /*
744  * Handle dialog in DLG_CONFIRMED state, we will be processing
745  * a response to a request sent within a dialog
746  */
dlg_confirmed_resp_uac(dlg_t * _d,struct sip_msg * _m,target_refresh_t is_target_refresh)747 static inline int dlg_confirmed_resp_uac(
748 		dlg_t *_d, struct sip_msg *_m, target_refresh_t is_target_refresh)
749 {
750 	int code;
751 	str contact;
752 
753 	code = _m->first_line.u.reply.statuscode;
754 
755 	/* Dialog has been already confirmed, that means we received
756 	 * a response to a request sent within the dialog. We will
757 	 * update remote target URI if and only if the message sent was
758 	 * a target refresher.
759 	 */
760 
761 	/* IF we receive a 481 response, terminate the dialog because
762 	 * the remote peer indicated that it didn't have the dialog
763 	 * state anymore, signal this termination with a positive return
764 	 * value
765 	 */
766 	if(code == 481) {
767 		_d->state = DLG_DESTROYED;
768 		return 1;
769 	}
770 
771 	/* Do nothing if not 2xx */
772 	if((code < 200) || (code >= 300))
773 		return 0;
774 
775 	if(refresh_dialog_resp(_m, is_target_refresh)) {
776 		/* Get contact if any and update remote target */
777 		if(parse_headers(_m, HDR_CONTACT_F, 0) == -1) {
778 			LM_ERR("error while parsing headers\n");
779 			return -2;
780 		}
781 
782 		/* Try to extract contact URI */
783 		if(get_contact_uri(_m, &contact) < 0)
784 			return -3;
785 		/* If there is a contact URI */
786 		if(contact.len) {
787 			/* Free old remote target and destination uri if any */
788 			if(_d->rem_target.s)
789 				shm_free(_d->rem_target.s);
790 			if(_d->dst_uri.s) {
791 				shm_free(_d->dst_uri.s);
792 				_d->dst_uri.s = 0;
793 				_d->dst_uri.len = 0;
794 			}
795 
796 			/* Duplicate new remote target */
797 			if(str_duplicate(&_d->rem_target, &contact) < 0)
798 				return -4;
799 		}
800 
801 		if(calculate_hooks(_d) < 0)
802 			return -1;
803 	}
804 
805 	return 0;
806 }
807 
808 
809 /*
810  * A response arrived, update dialog
811  */
dlg_response_uac(dlg_t * _d,struct sip_msg * _m,target_refresh_t is_target_refresh)812 int dlg_response_uac(
813 		dlg_t *_d, struct sip_msg *_m, target_refresh_t is_target_refresh)
814 {
815 	if(!_d || !_m) {
816 		LM_ERR("invalid parameter value\n");
817 		return -1;
818 	}
819 
820 	/* The main dispatcher */
821 	switch(_d->state) {
822 		case DLG_NEW:
823 			return dlg_new_resp_uac(_d, _m);
824 
825 		case DLG_EARLY:
826 			return dlg_early_resp_uac(_d, _m);
827 
828 		case DLG_CONFIRMED:
829 			return dlg_confirmed_resp_uac(_d, _m, is_target_refresh);
830 
831 		case DLG_DESTROYED:
832 			LM_DBG("cannot handle destroyed dialog\n");
833 			return -2;
834 	}
835 
836 	LM_ERR("Error in switch statement\n");
837 	return -3;
838 }
839 
840 
841 /*
842  * Get CSeq number
843  * Does not parse headers !!
844  */
get_cseq_value(struct sip_msg * _m,unsigned int * _cs)845 static inline int get_cseq_value(struct sip_msg *_m, unsigned int *_cs)
846 {
847 	str num;
848 
849 	if(_m->cseq == 0) {
850 		LM_ERR("CSeq header not found\n");
851 		return -1;
852 	}
853 
854 	num.s = get_cseq(_m)->number.s;
855 	num.len = get_cseq(_m)->number.len;
856 
857 	trim_leading(&num);
858 	if(str2int(&num, _cs) < 0) {
859 		LM_ERR("error while converting cseq number\n");
860 		return -2;
861 	}
862 	return 0;
863 }
864 
865 
866 /*
867  * Copy To or From URI without tag parameter
868  */
get_dlg_uri(struct hdr_field * _h,str * _s)869 static inline int get_dlg_uri(struct hdr_field *_h, str *_s)
870 {
871 	struct to_param *ptr, *prev;
872 	struct to_body *body;
873 	char *tag = 0; /* Makes gcc happy */
874 	int tag_len = 0, len;
875 
876 	if(!_h) {
877 		LM_ERR("header field not found\n");
878 		return -1;
879 	}
880 
881 	/* From was already parsed when extracting tag
882 	 * and To is parsed by default
883 	 */
884 
885 	body = (struct to_body *)_h->parsed;
886 
887 	ptr = body->param_lst;
888 	prev = 0;
889 	while(ptr) {
890 		if(ptr->type == TAG_PARAM)
891 			break;
892 		prev = ptr;
893 		ptr = ptr->next;
894 	}
895 
896 	if(ptr) {
897 		/* Tag param found */
898 		if(prev) {
899 			tag = prev->value.s + prev->value.len;
900 		} else {
901 			tag = body->body.s + body->body.len;
902 		}
903 
904 		if(ptr->next) {
905 			tag_len = ptr->value.s + ptr->value.len - tag;
906 		} else {
907 			tag_len = _h->body.s + _h->body.len - tag;
908 		}
909 	}
910 
911 	_s->s = shm_malloc(_h->body.len - tag_len);
912 	if(!_s->s) {
913 		SHM_MEM_ERROR;
914 		return -1;
915 	}
916 
917 	if(tag_len) {
918 		len = tag - _h->body.s;
919 		memcpy(_s->s, _h->body.s, len);
920 		memcpy(_s->s + len, tag + tag_len, _h->body.len - len - tag_len);
921 		_s->len = _h->body.len - tag_len;
922 	} else {
923 		memcpy(_s->s, _h->body.s, _h->body.len);
924 		_s->len = _h->body.len;
925 	}
926 
927 	return 0;
928 }
929 
930 
931 /*
932  * Extract all information from a request
933  * and update a dialog structure
934  */
request2dlg(struct sip_msg * _m,dlg_t * _d)935 static inline int request2dlg(struct sip_msg *_m, dlg_t *_d)
936 {
937 	str contact, rtag, callid;
938 
939 	if(parse_headers(_m, HDR_EOH_F, 0) == -1) {
940 		LM_ERR("error while parsing headers\n");
941 		return -1;
942 	}
943 
944 	if(get_contact_uri(_m, &contact) < 0)
945 		return -2;
946 	if(contact.len) {
947 		if(_d->rem_target.s)
948 			shm_free(_d->rem_target.s);
949 		if(_d->dst_uri.s) {
950 			shm_free(_d->dst_uri.s);
951 			_d->dst_uri.s = 0;
952 			_d->dst_uri.len = 0;
953 		}
954 		if(str_duplicate(&_d->rem_target, &contact) < 0)
955 			return -3;
956 	}
957 
958 	if(get_from_tag(_m, &rtag) < 0)
959 		goto err1;
960 	if(rtag.len && str_duplicate(&_d->id.rem_tag, &rtag) < 0)
961 		goto err1;
962 
963 	if(get_callid(_m, &callid) < 0)
964 		goto err2;
965 	if(callid.len && str_duplicate(&_d->id.call_id, &callid) < 0)
966 		goto err2;
967 
968 	if(get_cseq_value(_m, &_d->rem_seq.value) < 0)
969 		goto err3;
970 	_d->rem_seq.is_set = 1;
971 
972 	if(get_dlg_uri(_m->from, &_d->rem_uri) < 0)
973 		goto err3;
974 	if(get_dlg_uri(_m->to, &_d->loc_uri) < 0)
975 		goto err4;
976 
977 	if(get_route_set(_m, &_d->route_set, NORMAL_ORDER) < 0)
978 		goto err5;
979 
980 	return 0;
981 err5:
982 	if(_d->loc_uri.s)
983 		shm_free(_d->loc_uri.s);
984 	_d->loc_uri.s = 0;
985 	_d->loc_uri.len = 0;
986 err4:
987 	if(_d->rem_uri.s)
988 		shm_free(_d->rem_uri.s);
989 	_d->rem_uri.s = 0;
990 	_d->rem_uri.len = 0;
991 err3:
992 	if(_d->id.call_id.s)
993 		shm_free(_d->id.call_id.s);
994 	_d->id.call_id.s = 0;
995 	_d->id.call_id.len = 0;
996 err2:
997 	if(_d->id.rem_tag.s)
998 		shm_free(_d->id.rem_tag.s);
999 	_d->id.rem_tag.s = 0;
1000 	_d->id.rem_tag.len = 0;
1001 err1:
1002 	if(_d->rem_target.s)
1003 		shm_free(_d->rem_target.s);
1004 	_d->rem_target.s = 0;
1005 	_d->rem_target.len = 0;
1006 	return -4;
1007 }
1008 
1009 
1010 /*
1011  * Establishing a new dialog, UAS side
1012  */
new_dlg_uas(struct sip_msg * _req,int _code,dlg_t ** _d)1013 int new_dlg_uas(struct sip_msg *_req, int _code, /*str* _tag,*/ dlg_t **_d)
1014 {
1015 	dlg_t *res;
1016 	str tag;
1017 
1018 	if(!_req || /*!_tag ||*/ !_d) {
1019 		LM_ERR("invalid parameter value\n");
1020 		return -1;
1021 	}
1022 
1023 	if(_code > 299) {
1024 		LM_DBG("status code >= 300, no dialog created\n");
1025 	}
1026 
1027 	res = (dlg_t *)shm_malloc(sizeof(dlg_t));
1028 	if(res == 0) {
1029 		SHM_MEM_ERROR;
1030 		return -3;
1031 	}
1032 	/* Clear everything */
1033 	memset(res, 0, sizeof(dlg_t));
1034 
1035 	if(request2dlg(_req, res) < 0) {
1036 		LM_ERR("error while converting request to dialog\n");
1037 		free_dlg(res);
1038 		return -4;
1039 	}
1040 
1041 	if(_code > 100) {
1042 		tag.s = tm_tags;
1043 		tag.len = TOTAG_VALUE_LEN;
1044 		calc_crc_suffix(_req, tm_tag_suffix);
1045 		if(str_duplicate(&res->id.loc_tag, &tag) < 0) {
1046 			free_dlg(res);
1047 			return -5;
1048 		}
1049 	}
1050 
1051 	*_d = res;
1052 
1053 	if(_code < 100)
1054 		(*_d)->state = DLG_NEW;
1055 	else if(_code < 200)
1056 		(*_d)->state = DLG_EARLY;
1057 	else
1058 		(*_d)->state = DLG_CONFIRMED;
1059 
1060 	if(calculate_hooks(*_d) < 0) {
1061 		LM_ERR("error while calculating hooks\n");
1062 		free_dlg(res);
1063 		return -6;
1064 	}
1065 #ifdef DIALOG_CALLBACKS
1066 	run_new_dlg_callbacks(DLG_CB_UAS, res, _req);
1067 #endif
1068 
1069 	return 0;
1070 }
1071 
1072 /*
1073  * UAS side - update dialog state and to tag
1074  */
update_dlg_uas(dlg_t * _d,int _code,str * _tag)1075 int update_dlg_uas(dlg_t *_d, int _code, str *_tag)
1076 {
1077 	if(_d->state == DLG_CONFIRMED) {
1078 		LM_ERR("dialog is already confirmed\n");
1079 		return -1;
1080 	} else if(_d->state == DLG_DESTROYED) {
1081 		LM_ERR("dialog is already destroyed\n");
1082 		return -2;
1083 	}
1084 
1085 	if(_tag && _tag->s) {
1086 		if(_d->id.loc_tag.s) {
1087 			if((_tag->len == _d->id.loc_tag.len)
1088 					&& (!memcmp(_tag->s, _d->id.loc_tag.s, _tag->len))) {
1089 				LM_DBG("local tag is already set\n");
1090 			} else {
1091 				LM_ERR("error trying to rewrite local tag\n");
1092 				return -3;
1093 			}
1094 		} else {
1095 			if(str_duplicate(&_d->id.loc_tag, _tag) < 0) {
1096 				LM_ERR("not enough memory\n");
1097 				return -4;
1098 			}
1099 		}
1100 	}
1101 
1102 	if((100 < _code) && (_code < 200))
1103 		_d->state = DLG_EARLY;
1104 	else if(_code < 300)
1105 		_d->state = DLG_CONFIRMED;
1106 	else
1107 		_d->state = DLG_DESTROYED;
1108 
1109 	return 0;
1110 }
1111 
1112 /*
1113  * UAS side - update a dialog from a request
1114  */
dlg_request_uas(dlg_t * _d,struct sip_msg * _m,target_refresh_t is_target_refresh)1115 int dlg_request_uas(
1116 		dlg_t *_d, struct sip_msg *_m, target_refresh_t is_target_refresh)
1117 {
1118 	str contact;
1119 	int cseq;
1120 
1121 	if(!_d || !_m) {
1122 		LM_ERR("invalid parameter value\n");
1123 		return -1;
1124 	}
1125 
1126 	/* We must check if the request is not out of order or retransmission
1127 	 * first, if so then we will not update anything
1128 	 */
1129 	if(parse_headers(_m, HDR_CSEQ_F, 0) == -1) {
1130 		LM_ERR("error while parsing headers\n");
1131 		return -2;
1132 	}
1133 	if(get_cseq_value(_m, (unsigned int *)&cseq) < 0)
1134 		return -3;
1135 	if(_d->rem_seq.is_set && (cseq <= _d->rem_seq.value))
1136 		return 0;
1137 
1138 	/* Neither out of order nor retransmission -> update */
1139 	_d->rem_seq.value = cseq;
1140 	_d->rem_seq.is_set = 1;
1141 
1142 	/* We will als update remote target URI if the message
1143 	 * is target refresher
1144 	 */
1145 	if(refresh_dialog_req(_m, is_target_refresh)) { /* target refresher */
1146 		if(parse_headers(_m, HDR_CONTACT_F, 0) == -1) {
1147 			LM_ERR("error while parsing headers\n");
1148 			return -4;
1149 		}
1150 
1151 		if(get_contact_uri(_m, &contact) < 0)
1152 			return -5;
1153 		if(contact.len) {
1154 			if(_d->rem_target.s)
1155 				shm_free(_d->rem_target.s);
1156 			if(_d->dst_uri.s) {
1157 				shm_free(_d->dst_uri.s);
1158 				_d->dst_uri.s = 0;
1159 				_d->dst_uri.len = 0;
1160 			}
1161 			if(str_duplicate(&_d->rem_target, &contact) < 0)
1162 				return -6;
1163 		}
1164 
1165 		if(calculate_hooks(_d) < 0)
1166 			return -1;
1167 	}
1168 
1169 	return 0;
1170 }
1171 
1172 
1173 /*
1174  * Calculate length of the route set
1175  */
calculate_routeset_length(dlg_t * _d)1176 int calculate_routeset_length(dlg_t *_d)
1177 {
1178 	int len;
1179 	rr_t *ptr;
1180 
1181 	if(!_d->route_set)
1182 		return 0;
1183 
1184 	len = ROUTE_PREFIX_LEN;
1185 
1186 	for(ptr = _d->hooks.first_route; ptr; ptr = ptr->next) {
1187 		len += ptr->len;
1188 		len += ROUTE_SEPARATOR_LEN;
1189 	}
1190 	if(_d->hooks.last_route) {
1191 		if(_d->hooks.first_route)
1192 			len += ROUTE_SEPARATOR_LEN;
1193 		len += _d->hooks.last_route->len + 2; /* < > */
1194 	} else {
1195 		len -= ROUTE_SEPARATOR_LEN;
1196 	}
1197 
1198 	len += CRLF_LEN;
1199 
1200 	return len;
1201 }
1202 
1203 /*
1204  *
1205  * Print the route set
1206  */
print_routeset(char * buf,dlg_t * _d)1207 char *print_routeset(char *buf, dlg_t *_d)
1208 {
1209 	rr_t *ptr;
1210 
1211 	ptr = _d->hooks.first_route;
1212 
1213 	if(ptr || _d->hooks.last_route) {
1214 		memcpy(buf, ROUTE_PREFIX, ROUTE_PREFIX_LEN);
1215 		buf += ROUTE_PREFIX_LEN;
1216 	}
1217 
1218 	while(ptr) {
1219 		memcpy(buf, ptr->nameaddr.name.s, ptr->len);
1220 		buf += ptr->len;
1221 
1222 		ptr = ptr->next;
1223 		if(ptr) {
1224 			memcpy(buf, ROUTE_SEPARATOR, ROUTE_SEPARATOR_LEN);
1225 			buf += ROUTE_SEPARATOR_LEN;
1226 		}
1227 	}
1228 
1229 	if(_d->hooks.last_route) {
1230 		if(_d->hooks.first_route) {
1231 			memcpy(buf, ROUTE_SEPARATOR, ROUTE_SEPARATOR_LEN);
1232 			buf += ROUTE_SEPARATOR_LEN;
1233 		}
1234 		memcpy(buf, "<", 1);
1235 		buf++;
1236 		memcpy(buf, _d->hooks.last_route->s, _d->hooks.last_route->len);
1237 		buf += _d->hooks.last_route->len;
1238 		*buf = '>';
1239 		buf++;
1240 	}
1241 
1242 	if(_d->hooks.first_route || _d->hooks.last_route) {
1243 		memcpy(buf, CRLF, CRLF_LEN);
1244 		buf += CRLF_LEN;
1245 	}
1246 
1247 	return buf;
1248 }
1249 
1250 
1251 /*
1252  * Destroy a dialog state
1253  */
free_dlg(dlg_t * _d)1254 void free_dlg(dlg_t *_d)
1255 {
1256 	if(!_d)
1257 		return;
1258 #ifdef DIALOG_CALLBACKS
1259 	destroy_trans_dlg_callbacks(_d);
1260 #endif
1261 	if(_d->id.call_id.s)
1262 		shm_free(_d->id.call_id.s);
1263 	if(_d->id.rem_tag.s)
1264 		shm_free(_d->id.rem_tag.s);
1265 	if(_d->id.loc_tag.s)
1266 		shm_free(_d->id.loc_tag.s);
1267 
1268 	if(_d->loc_uri.s)
1269 		shm_free(_d->loc_uri.s);
1270 	if(_d->rem_uri.s)
1271 		shm_free(_d->rem_uri.s);
1272 	if(_d->rem_target.s)
1273 		shm_free(_d->rem_target.s);
1274 	if(_d->dst_uri.s)
1275 		shm_free(_d->dst_uri.s);
1276 
1277 	if(_d->loc_dname.s)
1278 		shm_free(_d->loc_dname.s);
1279 	if(_d->rem_dname.s)
1280 		shm_free(_d->rem_dname.s);
1281 
1282 	/* Free all routes in the route set */
1283 	shm_free_rr(&_d->route_set);
1284 	shm_free(_d);
1285 }
1286 
1287 
1288 /*
1289  * Print a dialog structure, just for debugging
1290  */
print_dlg(FILE * out,dlg_t * _d)1291 void print_dlg(FILE *out, dlg_t *_d)
1292 {
1293 	fprintf(out, "====dlg_t===\n");
1294 	fprintf(out, "id.call_id    : '%.*s'\n", _d->id.call_id.len,
1295 			_d->id.call_id.s);
1296 	fprintf(out, "id.rem_tag    : '%.*s'\n", _d->id.rem_tag.len,
1297 			_d->id.rem_tag.s);
1298 	fprintf(out, "id.loc_tag    : '%.*s'\n", _d->id.loc_tag.len,
1299 			_d->id.loc_tag.s);
1300 	fprintf(out, "loc_seq.value : %d\n", _d->loc_seq.value);
1301 	fprintf(out, "loc_seq.is_set: %s\n", _d->loc_seq.is_set ? "YES" : "NO");
1302 	fprintf(out, "rem_seq.value : %d\n", _d->rem_seq.value);
1303 	fprintf(out, "rem_seq.is_set: %s\n", _d->rem_seq.is_set ? "YES" : "NO");
1304 	fprintf(out, "loc_uri       : '%.*s'\n", _d->loc_uri.len, _d->loc_uri.s);
1305 	fprintf(out, "rem_uri       : '%.*s'\n", _d->rem_uri.len, _d->rem_uri.s);
1306 	fprintf(out, "rem_target    : '%.*s'\n", _d->rem_target.len,
1307 			_d->rem_target.s);
1308 	fprintf(out, "dst_uri       : '%.*s'\n", _d->dst_uri.len, _d->dst_uri.s);
1309 	fprintf(out, "secure:       : %d\n", _d->secure);
1310 	fprintf(out, "state         : ");
1311 	switch(_d->state) {
1312 		case DLG_NEW:
1313 			fprintf(out, "DLG_NEW\n");
1314 			break;
1315 		case DLG_EARLY:
1316 			fprintf(out, "DLG_EARLY\n");
1317 			break;
1318 		case DLG_CONFIRMED:
1319 			fprintf(out, "DLG_CONFIRMED\n");
1320 			break;
1321 		case DLG_DESTROYED:
1322 			fprintf(out, "DLG_DESTROYED\n");
1323 			break;
1324 	}
1325 	print_rr(out, _d->route_set);
1326 	if(_d->hooks.request_uri)
1327 		fprintf(out, "hooks.request_uri: '%.*s'\n", _d->hooks.request_uri->len,
1328 				_d->hooks.request_uri->s);
1329 	if(_d->hooks.next_hop)
1330 		fprintf(out, "hooks.next_hop   : '%.*s'\n", _d->hooks.next_hop->len,
1331 				_d->hooks.next_hop->s);
1332 	if(_d->hooks.first_route)
1333 		fprintf(out, "hooks.first_route: '%.*s'\n", _d->hooks.first_route->len,
1334 				_d->hooks.first_route->nameaddr.name.s);
1335 	if(_d->hooks.last_route)
1336 		fprintf(out, "hooks.last_route : '%.*s'\n", _d->hooks.last_route->len,
1337 				_d->hooks.last_route->s);
1338 
1339 	fprintf(out, "====dlg_t====\n");
1340 }
1341 
1342 /*
1343  * set dialog's request uri and destination uri (optional)
1344  */
set_dlg_target(dlg_t * _d,str * _ruri,str * _duri)1345 int set_dlg_target(dlg_t *_d, str *_ruri, str *_duri)
1346 {
1347 
1348 	if(!_d || !_ruri) {
1349 		LM_ERR("invalid parameter value\n");
1350 		return -1;
1351 	}
1352 
1353 	if(_d->rem_target.s)
1354 		shm_free(_d->rem_target.s);
1355 	if(_d->dst_uri.s) {
1356 		shm_free(_d->dst_uri.s);
1357 		_d->dst_uri.s = 0;
1358 		_d->dst_uri.len = 0;
1359 	}
1360 
1361 	if(str_duplicate(&_d->rem_target, _ruri))
1362 		return -1;
1363 	if(_duri && _duri->len) {
1364 		if(str_duplicate(&_d->dst_uri, _duri))
1365 			return -1;
1366 	}
1367 
1368 	if(calculate_hooks(_d) < 0) {
1369 		LM_ERR("error while calculating hooks\n");
1370 		return -1;
1371 	}
1372 
1373 	return 0;
1374 }
1375