xref: /illumos-gate/usr/src/lib/libsip/common/sip_dialog.c (revision 4c87aefe8930bd07275b8dd2e96ea5f24d93a52e)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <assert.h>
32 #include <errno.h>
33 #include <pthread.h>
34 #include <strings.h>
35 #include <sip.h>
36 
37 #include "sip_msg.h"
38 #include "sip_miscdefs.h"
39 #include "sip_hash.h"
40 #include "sip_dialog.h"
41 #include "sip_parse_generic.h"
42 
43 #define	SIP_DLG_XCHG_FROM	0
44 #define	SIP_DLG_XCHG_TO		1
45 
46 /*
47  * Dialog state change callback function
48  */
49 void (*sip_dlg_ulp_state_cb)(sip_dialog_t, sip_msg_t, int, int) = NULL;
50 void (*sip_ulp_dlg_del_cb)(sip_dialog_t, sip_msg_t, void *) = NULL;
51 
52 boolean_t	sip_incomplete_dialog(sip_dialog_t);
53 
54 /*
55  * Exchange From/To header
56  */
57 _sip_header_t *sip_dlg_xchg_from_to(sip_msg_t, int);
58 
59 /*
60  * Complete dialog hash table
61  */
62 sip_hash_t sip_dialog_hash[SIP_HASH_SZ];
63 
64 /*
65  * Partial dialog hash table
66  */
67 sip_hash_t sip_dialog_phash[SIP_HASH_SZ];
68 
69 /*
70  * Route set structure
71  */
72 typedef struct sip_dlg_route_set_s  {
73 	char		*sip_dlg_route;
74 	sip_str_t	sip_dlg_ruri;
75 	boolean_t	sip_dlg_route_lr;
76 	struct sip_dlg_route_set_s *sip_dlg_route_next;
77 }sip_dlg_route_set_t;
78 
79 sip_dialog_t		sip_seed_dialog(sip_conn_object_t, _sip_msg_t *,
80 			    boolean_t, int);
81 sip_dialog_t		sip_complete_dialog(_sip_msg_t *, _sip_dialog_t *);
82 int			sip_dialog_process(_sip_msg_t *, sip_dialog_t *);
83 void			sip_dialog_delete(_sip_dialog_t *);
84 void			sip_dialog_init();
85 sip_dialog_t		sip_dialog_find(_sip_msg_t *);
86 boolean_t		sip_dialog_match(void *, void *);
87 boolean_t		sip_dialog_free(void *, void *, int *);
88 sip_dialog_t		sip_update_dialog(sip_dialog_t, _sip_msg_t *);
89 char			*sip_dialog_req_uri(sip_dialog_t);
90 
91 static void		sip_release_dialog_res(_sip_dialog_t *);
92 void			sip_dlg_self_destruct(void *);
93 static int		sip_dialog_get_route_set(_sip_dialog_t *, _sip_msg_t *,
94 			    int);
95 static void		sip_dialog_free_rset(sip_dlg_route_set_t *);
96 
97 /*
98  * Timer object for partial dialogs
99  */
100 typedef struct sip_dialog_timer_obj_s {
101 	_sip_dialog_t	*dialog;
102 	void		(*func)(sip_dialog_t, sip_msg_t, void *);
103 } sip_dialog_timer_obj_t;
104 
105 /*
106  * To avoid duplication all over the place
107  */
108 static void
109 sip_release_dialog_res(_sip_dialog_t *dialog)
110 {
111 	int			count = 0;
112 	sip_msg_chain_t		*msg_chain;
113 	sip_msg_chain_t		*nmsg_chain;
114 
115 	if (dialog->sip_dlg_ref_cnt != 0) {
116 		sip_write_to_log((void *)dialog, SIP_DIALOG_LOG |
117 		    SIP_ASSERT_ERROR, __FILE__,  __LINE__);
118 	}
119 	assert(dialog->sip_dlg_ref_cnt == 0);
120 	if (SIP_IS_TIMER_RUNNING(dialog->sip_dlg_timer))
121 		SIP_CANCEL_TIMER(dialog->sip_dlg_timer);
122 	if (dialog->sip_dlg_call_id != NULL)
123 		sip_free_header(dialog->sip_dlg_call_id);
124 	if (dialog->sip_dlg_local_uri_tag != NULL)
125 		sip_free_header(dialog->sip_dlg_local_uri_tag);
126 	if (dialog->sip_dlg_remote_uri_tag != NULL)
127 		sip_free_header(dialog->sip_dlg_remote_uri_tag);
128 	if (dialog->sip_dlg_remote_target != NULL)
129 		sip_free_header(dialog->sip_dlg_remote_target);
130 	if (dialog->sip_dlg_local_contact != NULL)
131 		sip_free_header(dialog->sip_dlg_local_contact);
132 	if (dialog->sip_dlg_new_local_contact != NULL)
133 		sip_free_header(dialog->sip_dlg_new_local_contact);
134 	if (dialog->sip_dlg_route_set != NULL)
135 		sip_free_header(dialog->sip_dlg_route_set);
136 	if (dialog->sip_dlg_event != NULL)
137 		sip_free_header(dialog->sip_dlg_event);
138 	if (dialog->sip_dlg_req_uri.sip_str_ptr != NULL) {
139 		free(dialog->sip_dlg_req_uri.sip_str_ptr);
140 		dialog->sip_dlg_req_uri.sip_str_ptr = NULL;
141 		dialog->sip_dlg_req_uri.sip_str_len = 0;
142 	}
143 	if (dialog->sip_dlg_rset.sip_str_ptr != NULL) {
144 		free(dialog->sip_dlg_rset.sip_str_ptr);
145 		dialog->sip_dlg_rset.sip_str_len = 0;
146 		dialog->sip_dlg_rset.sip_str_ptr = NULL;
147 	}
148 	for (count = 0; count <= SIP_DLG_DESTROYED; count++) {
149 		msg_chain = dialog->sip_dlg_log[count].sip_msgs;
150 		while (msg_chain != NULL) {
151 			nmsg_chain = msg_chain->next;
152 			if (msg_chain->sip_msg != NULL)
153 				free(msg_chain->sip_msg);
154 			free(msg_chain);
155 			msg_chain = nmsg_chain;
156 		}
157 	}
158 	(void) pthread_mutex_destroy(&dialog->sip_dlg_mutex);
159 	free(dialog);
160 }
161 
162 /*
163  * Get the route information from the 'value' and add it to the route
164  * set.
165  */
166 static sip_dlg_route_set_t *
167 sip_add_route_to_set(sip_hdr_value_t *value)
168 {
169 	int			vlen = 0;
170 	sip_dlg_route_set_t	*rset;
171 	char			*crlf;
172 	const sip_param_t	*uri_param;
173 	int			error;
174 
175 	rset = calloc(1, sizeof (*rset));
176 	if (rset == NULL)
177 		return (NULL);
178 	rset->sip_dlg_route_next = NULL;
179 	vlen = value->sip_value_end - value->sip_value_start;
180 
181 	/*
182 	 * check for CRLF
183 	 */
184 	crlf = value->sip_value_end - strlen(SIP_CRLF);
185 	while (crlf != NULL && strncmp(crlf, SIP_CRLF, strlen(SIP_CRLF)) == 0) {
186 		vlen -= strlen(SIP_CRLF);
187 		crlf -= strlen(SIP_CRLF);
188 	}
189 	rset->sip_dlg_route = calloc(1, vlen + 1);
190 	if (rset->sip_dlg_route == NULL) {
191 		free(rset);
192 		return (NULL);
193 	}
194 	/*
195 	 * loose routing
196 	 */
197 	rset->sip_dlg_route_lr = B_FALSE;
198 	(void) strncpy(rset->sip_dlg_route, value->sip_value_start, vlen);
199 	rset->sip_dlg_ruri.sip_str_ptr = rset->sip_dlg_route +
200 	    (value->cftr_uri.sip_str_ptr - value->sip_value_start);
201 	rset->sip_dlg_ruri.sip_str_len = value->cftr_uri.sip_str_len;
202 	rset->sip_dlg_route[vlen] = '\0';
203 
204 	assert(value->sip_value_parsed_uri != NULL);
205 	/*
206 	 * Check if the 'lr' param is present for this route.
207 	 */
208 	uri_param = sip_get_uri_params(value->sip_value_parsed_uri, &error);
209 	if (error != 0) {
210 		free(rset->sip_dlg_route);
211 		free(rset);
212 		return (NULL);
213 	}
214 	if (uri_param != NULL) {
215 		rset->sip_dlg_route_lr = sip_is_param_present(uri_param, "lr",
216 		    strlen("lr"));
217 	}
218 	return (rset);
219 }
220 
221 /*
222  * Depending on the route-set, determine the request URI.
223  */
224 char *
225 sip_dialog_req_uri(sip_dialog_t dialog)
226 {
227 	const sip_str_t		*req_uri;
228 	char			*uri;
229 	_sip_dialog_t		*_dialog;
230 
231 	_dialog = (_sip_dialog_t *)dialog;
232 	if (_dialog->sip_dlg_route_set == NULL ||
233 	    _dialog->sip_dlg_req_uri.sip_str_ptr == NULL) {
234 		const struct sip_value	*val;
235 
236 		val = sip_get_header_value(_dialog->sip_dlg_remote_target,
237 		    NULL);
238 		if (val == NULL)
239 			return (NULL);
240 		req_uri = &((sip_hdr_value_t *)val)->cftr_uri;
241 	} else {
242 		req_uri = &_dialog->sip_dlg_req_uri;
243 	}
244 	uri = (char *)malloc(req_uri->sip_str_len + 1);
245 	if (uri == NULL)
246 		return (NULL);
247 	(void) strncpy(uri, req_uri->sip_str_ptr, req_uri->sip_str_len);
248 	uri[req_uri->sip_str_len] = '\0';
249 
250 	return (uri);
251 }
252 
253 /*
254  * Free the route set.
255  */
256 void
257 sip_dialog_free_rset(sip_dlg_route_set_t *rset)
258 {
259 	sip_dlg_route_set_t	*next;
260 
261 	while (rset != NULL) {
262 		next = rset->sip_dlg_route_next;
263 		rset->sip_dlg_route_next = NULL;
264 		free(rset->sip_dlg_route);
265 		free(rset);
266 		rset = next;
267 	}
268 }
269 
270 /*
271  * Recompute route-set
272  */
273 static int
274 sip_dlg_recompute_rset(_sip_dialog_t *dialog, _sip_msg_t *sip_msg, int what)
275 {
276 	int ret;
277 
278 	if (dialog->sip_dlg_route_set != NULL) {
279 		sip_free_header(dialog->sip_dlg_route_set);
280 		dialog->sip_dlg_route_set = NULL;
281 	}
282 	if (dialog->sip_dlg_req_uri.sip_str_ptr != NULL) {
283 		free(dialog->sip_dlg_req_uri.sip_str_ptr);
284 		dialog->sip_dlg_req_uri.sip_str_ptr = NULL;
285 		dialog->sip_dlg_req_uri.sip_str_len = 0;
286 	}
287 	if (dialog->sip_dlg_rset.sip_str_ptr != NULL) {
288 		free(dialog->sip_dlg_rset.sip_str_ptr);
289 		dialog->sip_dlg_rset.sip_str_ptr = NULL;
290 		dialog->sip_dlg_rset.sip_str_len = 0;
291 	}
292 	ret = sip_dialog_get_route_set(dialog, sip_msg, what);
293 	return (ret);
294 }
295 
296 /*
297  * If the route set is empty, the UAC MUST place the remote target URI
298  * into the Request-URI.  The UAC MUST NOT add a Route header field to
299  * the request.
300  *
301  * If the route set is not empty, and the first URI in the route set
302  * contains the lr parameter (see Section 19.1.1), the UAC MUST place
303  * the remote target URI into the Request-URI and MUST include a Route
304  * header field containing the route set values in order, including all
305  * parameters.
306  *
307  * If the route set is not empty, and its first URI does not contain the
308  * lr parameter, the UAC MUST place the first URI from the route set
309  * into the Request-URI, stripping any parameters that are not allowed
310  * in a Request-URI.  The UAC MUST add a Route header field containing
311  * the remainder of the route set values in order, including all
312  * parameters.  The UAC MUST then place the remote target URI into the
313  * Route header field as the last value.
314  */
315 int
316 sip_dialog_set_route_hdr(_sip_dialog_t *dialog, sip_dlg_route_set_t *rset_head,
317     int rcnt, int rlen)
318 {
319 	size_t			rset_len;
320 	_sip_header_t		*rhdr;
321 	char			*rset;
322 	char			*rp;
323 	char			*rsp;
324 	int			count;
325 	sip_dlg_route_set_t	*route;
326 	boolean_t		first = B_TRUE;
327 	const sip_str_t		*to_uri;
328 	char			*uri = NULL;
329 	int			rspl;
330 	int			rpl;
331 
332 	if (rcnt <= 0) {
333 		sip_write_to_log((void *)dialog, SIP_DIALOG_LOG |
334 		    SIP_ASSERT_ERROR, __FILE__, __LINE__);
335 	}
336 	assert(rcnt > 0);
337 
338 	dialog->sip_dlg_rset.sip_str_len = rlen + rcnt - 1;
339 	dialog->sip_dlg_rset.sip_str_ptr = malloc(rlen + rcnt);
340 	if (dialog->sip_dlg_rset.sip_str_ptr == NULL)
341 		return (ENOMEM);
342 	rsp = dialog->sip_dlg_rset.sip_str_ptr;
343 	rspl = rlen + rcnt;
344 	route = rset_head;
345 	rset_len = rlen;
346 	if (!route->sip_dlg_route_lr) {
347 		const struct sip_value	*val;
348 
349 		val = sip_get_header_value(dialog->sip_dlg_remote_target, NULL);
350 		to_uri = &((sip_hdr_value_t *)val)->cftr_uri;
351 		uri = (char *)malloc(to_uri->sip_str_len + 1);
352 		if (uri == NULL) {
353 			free(dialog->sip_dlg_rset.sip_str_ptr);
354 			dialog->sip_dlg_rset.sip_str_len = 0;
355 			dialog->sip_dlg_rset.sip_str_ptr = NULL;
356 			return (ENOMEM);
357 		}
358 		(void) strncpy(uri, to_uri->sip_str_ptr, to_uri->sip_str_len);
359 		uri[to_uri->sip_str_len] = '\0';
360 		rset_len = rlen - strlen(route->sip_dlg_route) + strlen(uri) +
361 		    SIP_SPACE_LEN + sizeof (char) + SIP_SPACE_LEN +
362 		    sizeof (char);
363 		count = snprintf(rsp, rspl, "%s", route->sip_dlg_route);
364 		dialog->sip_dlg_req_uri.sip_str_ptr = malloc(
365 		    route->sip_dlg_ruri.sip_str_len + 1);
366 		if (dialog->sip_dlg_req_uri.sip_str_ptr == NULL) {
367 			free(uri);
368 			free(dialog->sip_dlg_rset.sip_str_ptr);
369 			dialog->sip_dlg_rset.sip_str_len = 0;
370 			dialog->sip_dlg_rset.sip_str_ptr = NULL;
371 			return (ENOMEM);
372 		}
373 		(void) strncpy(dialog->sip_dlg_req_uri.sip_str_ptr, rsp +
374 		    (route->sip_dlg_ruri.sip_str_ptr - route->sip_dlg_route),
375 		    route->sip_dlg_ruri.sip_str_len);
376 		dialog->sip_dlg_req_uri.sip_str_ptr[
377 		    route->sip_dlg_ruri.sip_str_len] = '\0';
378 		dialog->sip_dlg_req_uri.sip_str_len =
379 		    route->sip_dlg_ruri.sip_str_len;
380 
381 		rsp += count;
382 		rspl -= count;
383 		route = route->sip_dlg_route_next;
384 	}
385 
386 	/*
387 	 * rcnt - 1 is for the number of COMMAs
388 	 */
389 	rset_len += strlen(SIP_ROUTE) + SIP_SPACE_LEN + sizeof (char) +
390 	    SIP_SPACE_LEN + rcnt - 1;
391 	rset = malloc(rset_len + 1);
392 	if (rset == NULL) {
393 		free(dialog->sip_dlg_rset.sip_str_ptr);
394 		dialog->sip_dlg_rset.sip_str_len = 0;
395 		dialog->sip_dlg_rset.sip_str_ptr = NULL;
396 		return (ENOMEM);
397 	}
398 	rhdr = sip_new_header(rset_len + strlen(SIP_CRLF));
399 	if (rhdr == NULL) {
400 		free(rset);
401 		free(dialog->sip_dlg_rset.sip_str_ptr);
402 		dialog->sip_dlg_rset.sip_str_len = 0;
403 		dialog->sip_dlg_rset.sip_str_ptr = NULL;
404 		return (ENOMEM);
405 	}
406 
407 	rp = rset;
408 	rpl = rset_len + 1;
409 	count = snprintf(rp, rpl, "%s %c ", SIP_ROUTE, SIP_HCOLON);
410 	rp += count;
411 	rpl -= count;
412 
413 	while (route != NULL) {
414 		if (first) {
415 			count = snprintf(rp, rpl, "%s", route->sip_dlg_route);
416 			rp += count;
417 			rpl -= count;
418 			first = B_FALSE;
419 			if (uri != NULL) {
420 				count = snprintf(rsp, rspl, "%c%s",
421 				    SIP_COMMA, route->sip_dlg_route);
422 			} else {
423 				count = snprintf(rsp, rspl, "%s",
424 				    route->sip_dlg_route);
425 			}
426 			rsp += count;
427 			rspl -= count;
428 		} else {
429 			count = snprintf(rp, rpl, "%c%s", SIP_COMMA,
430 			    route->sip_dlg_route);
431 			rp += count;
432 			rpl -= count;
433 			count = snprintf(rsp, rspl, "%c%s", SIP_COMMA,
434 			    route->sip_dlg_route);
435 			rsp += count;
436 			rspl -= count;
437 		}
438 		route = route->sip_dlg_route_next;
439 	}
440 	if (rsp > dialog->sip_dlg_rset.sip_str_ptr +
441 	    dialog->sip_dlg_rset.sip_str_len) {
442 		sip_write_to_log((void *)dialog, SIP_DIALOG_LOG |
443 		    SIP_ASSERT_ERROR, __FILE__, __LINE__);
444 	}
445 	assert(rsp <= dialog->sip_dlg_rset.sip_str_ptr +
446 	    dialog->sip_dlg_rset.sip_str_len);
447 	dialog->sip_dlg_rset.sip_str_ptr[dialog->sip_dlg_rset.sip_str_len] =
448 	    '\0';
449 	if (uri != NULL) {
450 		if (first) {
451 			count = snprintf(rp, rpl, "%c %s %c", SIP_LAQUOT,
452 			    uri, SIP_RAQUOT);
453 		} else {
454 			count = snprintf(rp, rpl, "%c%c %s %c", SIP_COMMA,
455 			    SIP_LAQUOT, uri, SIP_RAQUOT);
456 		}
457 		rp += count;
458 		rpl -= count;
459 		free(uri);
460 	}
461 	if (rp > rset + rset_len) {
462 		sip_write_to_log((void *)dialog, SIP_DIALOG_LOG |
463 		    SIP_ASSERT_ERROR, __FILE__, __LINE__);
464 	}
465 	assert(rp <= rset + rset_len);
466 	(void) snprintf(rhdr->sip_hdr_start, rset_len + strlen(SIP_CRLF) + 1,
467 	    "%s%s", rset, SIP_CRLF);
468 	free(rset);
469 	dialog->sip_dlg_route_set = (sip_header_t)rhdr;
470 	sip_dialog_free_rset(rset_head);
471 	return (0);
472 }
473 
474 /*
475  * UAC Behavior
476  * The route set MUST be set to the list of URIs in the Record-Route
477  * header field from the response, taken in reverse order and preserving
478  * all URI parameters.
479  *
480  * UAS behavior
481  * The route set MUST be set to the list of URIs in the Record-Route
482  * header field from the request, taken in order and preserving all URI
483  * parameters.
484  */
485 static int
486 sip_dialog_get_route_set(_sip_dialog_t *dialog, _sip_msg_t *sip_msg, int what)
487 {
488 	sip_header_t		rrhdr;
489 	sip_hdr_value_t		*value;
490 	int			error;
491 	sip_dlg_route_set_t	*rset_head = NULL;
492 	sip_dlg_route_set_t	*rset_tail = NULL;
493 	sip_dlg_route_set_t	*rset;
494 	int			rset_cnt = 0;
495 	int			rset_len = 0;
496 
497 	(void) pthread_mutex_lock(&sip_msg->sip_msg_mutex);
498 	rrhdr = sip_search_for_header(sip_msg, SIP_RECORD_ROUTE, NULL);
499 	while (rrhdr != NULL) {
500 		(void) pthread_mutex_unlock(&sip_msg->sip_msg_mutex);
501 		value = (sip_hdr_value_t *)sip_get_header_value(rrhdr, &error);
502 		while (value != NULL && error == 0) {
503 			char	*crlf;
504 
505 			if (value->sip_value_state == SIP_VALUE_BAD) {
506 				value = (sip_hdr_value_t *)sip_get_next_value(
507 				    (sip_header_value_t)value, &error);
508 				continue;
509 			}
510 			rset = sip_add_route_to_set(value);
511 			if (rset == NULL)
512 				goto r_error;
513 			/*
514 			 * Add one for COMMA
515 			 */
516 			rset_cnt++;
517 			rset_len += (value->sip_value_end -
518 			    value->sip_value_start);
519 			/*
520 			 * Check for CRLF
521 			 */
522 			crlf = value->sip_value_end - strlen(SIP_CRLF);
523 			while (crlf != NULL &&
524 			    strncmp(crlf, SIP_CRLF, strlen(SIP_CRLF)) == 0) {
525 				rset_len -= strlen(SIP_CRLF);
526 				crlf -= strlen(SIP_CRLF);
527 			}
528 			if (rset_head == NULL) {
529 				if (rset_tail != NULL) {
530 					sip_write_to_log((void *)dialog,
531 					    SIP_DIALOG_LOG | SIP_ASSERT_ERROR,
532 					    __FILE__, __LINE__);
533 				}
534 				assert(rset_tail == NULL);
535 				rset_head = rset_tail = rset;
536 			} else if (what == SIP_UAS_DIALOG) {
537 				rset_tail->sip_dlg_route_next = rset;
538 				rset_tail = rset;
539 			} else if (what == SIP_UAC_DIALOG) {
540 				rset->sip_dlg_route_next = rset_head;
541 				rset_head = rset;
542 			} else {
543 				sip_write_to_log((void *)dialog,
544 				    SIP_DIALOG_LOG | SIP_ASSERT_ERROR,
545 				    __FILE__, __LINE__);
546 				assert(0);
547 			}
548 			value = (sip_hdr_value_t *)sip_get_next_value(
549 			    (sip_header_value_t)value, &error);
550 		}
551 		(void) pthread_mutex_lock(&sip_msg->sip_msg_mutex);
552 		rrhdr = sip_search_for_header(sip_msg, SIP_RECORD_ROUTE, rrhdr);
553 	}
554 	(void) pthread_mutex_unlock(&sip_msg->sip_msg_mutex);
555 	if (rset_cnt == 0)
556 		return (0);
557 	if (sip_dialog_set_route_hdr(dialog, rset_head, rset_cnt,
558 	    rset_len) != 0) {
559 		goto r_error;
560 	}
561 	return (0);
562 r_error:
563 	sip_dialog_free_rset(rset_head);
564 	return (ENOMEM);
565 }
566 
567 /*
568  * UAS behavior:
569  * The remote sequence number MUST be set to the value of the sequence
570  * number in the CSeq header field of the request.  The local sequence
571  * number MUST be empty.  The call identifier component of the dialog ID
572  * MUST be set to the value of the Call-ID in the request.  The local
573  * tag component of the dialog ID MUST be set to the tag in the To field
574  * in the response to the request (which always includes a tag), and the
575  * remote tag component of the dialog ID MUST be set to the tag from the
576  * From field in the request.  A UAS MUST be prepared to receive a
577  * request without a tag in the From field, in which case the tag is
578  * considered to have a value of null.
579  * The remote URI MUST be set to the URI in the From field, and the
580  * local URI MUST be set to the URI in the To field.
581  * The remote target MUST be set to the URI from the Contact header field
582  * of the request.
583  *
584  * UAC behavior:
585  * The local sequence number MUST be set to the value of the sequence
586  * number in the CSeq header field of the request.  The remote sequence
587  * number MUST be empty (it is established when the remote UA sends a
588  * request within the dialog).  The call identifier component of the
589  * dialog ID MUST be set to the value of the Call-ID in the request.
590  * The local tag component of the dialog ID MUST be set to the tag in
591  * the From field in the request, and the remote tag component of the
592  * dialog ID MUST be set to the tag in the To field of the response.  A
593  * UAC MUST be prepared to receive a response without a tag in the To
594  * field, in which case the tag is considered to have a value of null.
595  * The remote URI MUST be set to the URI in the To field, and the local
596  * URI MUST be set to the URI in the From field.
597  * The remote target MUST be set to the URI from the Contact header field
598  * of the response.
599  */
600 
601 
602 /*
603  * This is the routine that seeds a dialog.
604  */
605 sip_dialog_t
606 sip_seed_dialog(sip_conn_object_t obj, _sip_msg_t *sip_msg,
607     boolean_t dlg_on_fork, int dlg_type)
608 {
609 	_sip_dialog_t		*dialog;
610 	int			cseq;
611 	sip_header_t		fhdr = NULL;
612 	sip_header_t		thdr = NULL;
613 	sip_header_t		chdr;
614 	sip_header_t		cihdr;
615 	sip_header_t		evhdr = NULL;
616 	const struct sip_value	*value;
617 	sip_dialog_timer_obj_t	*tim_obj = NULL;
618 	const sip_str_t		*callid;
619 	sip_method_t		method;
620 	int			timer1 = sip_timer_T1;
621 	int			error;
622 
623 	if (!sip_msg_is_request((sip_msg_t)sip_msg, &error))
624 		return (NULL);
625 
626 	method = sip_get_request_method((sip_msg_t)sip_msg, &error);
627 	/*
628 	 * Only INVITE and SUBSCRIBE supported
629 	 */
630 	if (error != 0 || (method != INVITE && method != SUBSCRIBE))
631 		return (NULL);
632 
633 	/*
634 	 * A request outside of a dialog MUST NOT contain a To tag
635 	 */
636 	if (sip_get_to_tag((sip_msg_t)sip_msg, NULL) != NULL)
637 		return (NULL);
638 
639 	if (dlg_type == SIP_UAS_DIALOG) {
640 		thdr = sip_dlg_xchg_from_to((sip_msg_t)sip_msg,
641 		    SIP_DLG_XCHG_FROM);
642 		(void) pthread_mutex_lock(&sip_msg->sip_msg_mutex);
643 	} else {
644 		(void) pthread_mutex_lock(&sip_msg->sip_msg_mutex);
645 		fhdr = sip_search_for_header(sip_msg, SIP_FROM, NULL);
646 	}
647 	cihdr = sip_search_for_header(sip_msg, SIP_CALL_ID, NULL);
648 	chdr = sip_search_for_header(sip_msg, SIP_CONTACT, NULL);
649 	if (method == SUBSCRIBE)
650 		evhdr = sip_search_for_header(sip_msg, SIP_EVENT, NULL);
651 	(void) pthread_mutex_unlock(&sip_msg->sip_msg_mutex);
652 	if ((fhdr == NULL && thdr == NULL) || cihdr == NULL || chdr == NULL ||
653 	    (method == SUBSCRIBE && evhdr == NULL)) {
654 		if (thdr != NULL)
655 			sip_free_header(thdr);
656 		return (NULL);
657 	}
658 
659 	/*
660 	 * Sanity check since we just store the headers in the dialog
661 	 */
662 	if (sip_get_from_tag((sip_msg_t)sip_msg, NULL) == NULL ||
663 	    sip_get_from_uri_str((sip_msg_t)sip_msg, NULL) == NULL ||
664 	    ((cseq = sip_get_callseq_num((sip_msg_t)sip_msg, NULL)) == -1) ||
665 	    (callid = sip_get_callid((sip_msg_t)sip_msg, NULL)) == NULL ||
666 	    sip_get_to_uri_str((sip_msg_t)sip_msg, NULL) == NULL ||
667 	    ((value = sip_get_header_value(chdr, NULL)) == NULL) ||
668 	    sip_get_contact_uri_str((sip_header_value_t)value, NULL) == NULL) {
669 		if (thdr != NULL)
670 			sip_free_header(thdr);
671 		return (NULL);
672 	}
673 
674 	tim_obj = calloc(1, sizeof (sip_dialog_timer_obj_t));
675 	if (tim_obj == NULL) {
676 		if (thdr != NULL)
677 			sip_free_header(thdr);
678 		return (NULL);
679 	}
680 	dialog = calloc(1, sizeof (_sip_dialog_t));
681 	if (dialog == NULL) {
682 		if (thdr != NULL)
683 			sip_free_header(thdr);
684 		return (NULL);
685 	}
686 	/*
687 	 * We will take the TO header with the tag when we complete this
688 	 * dialog
689 	 */
690 	if (dlg_type == SIP_UAS_DIALOG) {
691 		dialog->sip_dlg_remote_uri_tag = thdr;
692 		/*
693 		 * We take the remote target from the incoming request on the
694 		 * UAS. For the UAC, we will take it from the response.
695 		 */
696 		if ((dialog->sip_dlg_remote_target = sip_dup_header(chdr)) ==
697 		    NULL) {
698 			goto dia_err;
699 		}
700 	} else {
701 		if ((dialog->sip_dlg_local_uri_tag = sip_dup_header(fhdr)) ==
702 		    NULL) {
703 			goto dia_err;
704 		}
705 		/*
706 		 * We take the local contact from the originating request on
707 		 * UAC. For the UAS, we will take it from the response.
708 		 */
709 		if ((dialog->sip_dlg_local_contact = sip_dup_header(chdr)) ==
710 		    NULL) {
711 			goto dia_err;
712 		} else {
713 			dialog->sip_dlg_new_local_contact = NULL;
714 		}
715 	}
716 	if ((dialog->sip_dlg_call_id = sip_dup_header(cihdr)) == NULL)
717 		goto dia_err;
718 	if (method == SUBSCRIBE) {
719 		dialog->sip_dlg_event = sip_dup_header(evhdr);
720 		if (dialog->sip_dlg_event == NULL) {
721 			goto dia_err;
722 		}
723 	}
724 	dialog->sip_dlg_rset.sip_str_ptr = NULL;
725 	dialog->sip_dlg_rset.sip_str_len = 0;
726 	dialog->sip_dlg_req_uri.sip_str_ptr = NULL;
727 	dialog->sip_dlg_req_uri.sip_str_len = 0;
728 	/*
729 	 * Get the route set from the request, if present
730 	 */
731 	if (dlg_type == SIP_UAS_DIALOG &&
732 	    sip_dialog_get_route_set(dialog, sip_msg, dlg_type) != 0) {
733 		goto dia_err;
734 	}
735 	if (dlg_type == SIP_UAC_DIALOG)
736 		dialog->sip_dlg_local_cseq = cseq;
737 	else
738 		dialog->sip_dlg_remote_cseq = cseq;
739 	dialog->sip_dlg_type = dlg_type;
740 	dialog->sip_dlg_on_fork = dlg_on_fork;
741 	dialog->sip_dlg_method = method;
742 	/*
743 	 * Set the partial dialog timer with the INVITE timeout val
744 	 */
745 	if (sip_conn_timer1 != NULL)
746 		timer1 = sip_conn_timer1(obj);
747 	SIP_INIT_TIMER(dialog->sip_dlg_timer, 64 * timer1);
748 	tim_obj->dialog = dialog;
749 	/*
750 	 * Since at the client we never pass the partial dialog, we need not
751 	 * invoke the callback when the partial dialog self-destructs.
752 	 */
753 	if (dlg_type == SIP_UAS_DIALOG)
754 		tim_obj->func = sip_ulp_dlg_del_cb;
755 	SIP_SCHED_TIMER(dialog->sip_dlg_timer, (void *)tim_obj,
756 	    sip_dlg_self_destruct);
757 	if (!SIP_IS_TIMER_RUNNING(dialog->sip_dlg_timer))
758 		goto dia_err;
759 	(void) pthread_mutex_init(&dialog->sip_dlg_mutex, NULL);
760 
761 	if (dlg_type == SIP_UAC_DIALOG) {
762 		const sip_str_t	*local_tag;
763 
764 		local_tag = sip_get_from_tag((sip_msg_t)sip_msg, NULL);
765 		if (local_tag == NULL) {
766 			sip_write_to_log((void *)dialog, SIP_DIALOG_LOG |
767 			    SIP_ASSERT_ERROR, __FILE__, __LINE__);
768 		}
769 		assert(local_tag != NULL);
770 		sip_md5_hash(local_tag->sip_str_ptr, local_tag->sip_str_len,
771 		    callid->sip_str_ptr, callid->sip_str_len,
772 		    NULL, 0, NULL, 0, NULL, 0, NULL, 0,
773 		    (uchar_t *)dialog->sip_dlg_id);
774 
775 
776 		/*
777 		 * Add it to the partial hash table
778 		 */
779 		if (sip_hash_add(sip_dialog_phash, (void *)dialog,
780 		    SIP_DIGEST_TO_HASH(dialog->sip_dlg_id)) != 0) {
781 			goto dia_err;
782 		}
783 	}
784 
785 	dialog->sip_dlg_msgcnt = 1;
786 	sip_add_log(&dialog->sip_dlg_log[dialog->sip_dlg_state],
787 	    (sip_msg_t)sip_msg, dialog->sip_dlg_msgcnt, SIP_DIALOG_LOG);
788 
789 	SIP_DLG_REFCNT_INCR(dialog);
790 	return ((sip_dialog_t)dialog);
791 dia_err:
792 	sip_release_dialog_res(dialog);
793 	if (SIP_IS_TIMER_RUNNING(dialog->sip_dlg_timer))
794 		SIP_CANCEL_TIMER(dialog->sip_dlg_timer);
795 	if (tim_obj != NULL)
796 		free(tim_obj);
797 	return (NULL);
798 }
799 
800 /*
801  * When creating a dialog from a NOTIFY request, we need to get the FROM
802  * header for the dialog from the TO header of the NOTIFY.
803  */
804 _sip_header_t *
805 sip_dlg_xchg_from_to(sip_msg_t sip_msg, int what)
806 {
807 	int			len;
808 	_sip_header_t		*newhdr;
809 	int			cnt;
810 	const struct sip_header	*hdr;
811 	int			hdrsize;
812 	int			error;
813 
814 	hdr = sip_get_header(sip_msg, what == SIP_DLG_XCHG_FROM ? SIP_FROM :
815 	    SIP_TO, NULL, &error);
816 	if (error != 0 || hdr == NULL)
817 		return (NULL);
818 	if (sip_parse_goto_values((_sip_header_t *)hdr) != 0)
819 		return (NULL);
820 	len = hdr->sip_hdr_end - hdr->sip_hdr_current;
821 	if (what == SIP_DLG_XCHG_FROM) {
822 		hdrsize = len + strlen(SIP_TO) + SIP_SPACE_LEN + sizeof (char) +
823 		    SIP_SPACE_LEN;
824 	} else {
825 		hdrsize = len + strlen(SIP_FROM) + SIP_SPACE_LEN +
826 		    sizeof (char) + SIP_SPACE_LEN;
827 	}
828 	newhdr = sip_new_header(hdrsize);
829 	if (newhdr == NULL)
830 		return (NULL);
831 	if (what == SIP_DLG_XCHG_FROM) {
832 		cnt = snprintf(newhdr->sip_hdr_current, hdrsize + 1,
833 		    "%s %c ", SIP_TO, SIP_HCOLON);
834 	} else {
835 		cnt = snprintf(newhdr->sip_hdr_current, hdrsize + 1,
836 		    "%s %c ", SIP_FROM, SIP_HCOLON);
837 	}
838 	newhdr->sip_hdr_current += cnt;
839 	(void) strncpy(newhdr->sip_hdr_current, hdr->sip_hdr_current, len);
840 	newhdr->sip_hdr_current += len;
841 	assert(newhdr->sip_hdr_current == newhdr->sip_hdr_end);
842 	assert(hdr->sip_header_functions != NULL);
843 
844 	/*
845 	 * FROM and TO have common parsing functions
846 	 */
847 	newhdr->sip_header_functions = hdr->sip_header_functions;
848 	newhdr->sip_hdr_current = newhdr->sip_hdr_start;
849 
850 	return (newhdr);
851 }
852 
853 /*
854  * This is the response that completes the dialog that was created
855  * in sip_seed_dialog().
856  */
857 sip_dialog_t
858 sip_complete_dialog(_sip_msg_t *sip_msg, _sip_dialog_t *dialog)
859 {
860 	_sip_header_t		*thdr;
861 	_sip_header_t		*evhdr = NULL;
862 	_sip_header_t		*substate = NULL;
863 	sip_header_t		chdr = NULL;
864 	int			resp_code;
865 	const sip_str_t		*ttag;
866 	const sip_str_t		*remtag;
867 	const sip_str_t		*callid;
868 	const struct sip_value 	*val;
869 	sip_method_t		method;
870 	int			error = 0;
871 	int			prev_state;
872 	boolean_t		alloc_thdr = B_FALSE;
873 
874 	if (sip_msg_is_request((sip_msg_t)sip_msg, &error) && error == 0)
875 		method = sip_get_request_method((sip_msg_t)sip_msg, &error);
876 	else
877 		method = sip_get_callseq_method((sip_msg_t)sip_msg, &error);
878 	if (error != 0 || dialog == NULL ||
879 	    (sip_msg_is_request((sip_msg_t)sip_msg, &error) &&
880 	    (dialog->sip_dlg_method == INVITE || method != NOTIFY))) {
881 		return (NULL);
882 	}
883 	if ((dialog->sip_dlg_type == SIP_UAC_DIALOG && method != NOTIFY &&
884 	    sip_get_callseq_num((sip_msg_t)sip_msg, NULL) !=
885 	    dialog->sip_dlg_local_cseq) ||
886 	    (dialog->sip_dlg_type == SIP_UAS_DIALOG && method != NOTIFY &&
887 	    sip_get_callseq_num((sip_msg_t)sip_msg, NULL) !=
888 	    dialog->sip_dlg_remote_cseq)) {
889 		return (NULL);
890 	}
891 	if (method == NOTIFY) {
892 		const sip_str_t	*sstate;
893 
894 		thdr = sip_dlg_xchg_from_to((sip_msg_t)sip_msg,
895 		    SIP_DLG_XCHG_FROM);
896 		if (thdr == NULL)
897 			return (NULL);
898 		alloc_thdr = B_TRUE;
899 		(void) pthread_mutex_lock(&sip_msg->sip_msg_mutex);
900 		chdr = sip_search_for_header(sip_msg, SIP_CONTACT, NULL);
901 		if (chdr == NULL) {
902 			(void) pthread_mutex_unlock(&sip_msg->sip_msg_mutex);
903 			sip_free_header(thdr);
904 			return (NULL);
905 		}
906 		evhdr = sip_search_for_header(sip_msg, SIP_EVENT, NULL);
907 		if (evhdr == NULL) {
908 			(void) pthread_mutex_unlock(&sip_msg->sip_msg_mutex);
909 			sip_free_header(thdr);
910 			return (NULL);
911 		}
912 		substate = sip_search_for_header(sip_msg,
913 		    SIP_SUBSCRIPTION_STATE, NULL);
914 		if (substate == NULL) {
915 			(void) pthread_mutex_unlock(&sip_msg->sip_msg_mutex);
916 			sip_free_header(thdr);
917 			return (NULL);
918 		}
919 		(void) pthread_mutex_unlock(&sip_msg->sip_msg_mutex);
920 		sstate = sip_get_substate((sip_msg_t)sip_msg, &error);
921 		if (sstate == NULL || error != 0) {
922 			sip_free_header(thdr);
923 			return (NULL);
924 		}
925 		if ((sstate->sip_str_len != strlen("pending") &&
926 		    sstate->sip_str_len != strlen("active")) ||
927 		    ((sstate->sip_str_len == strlen("pending") &&
928 		    strncasecmp(sstate->sip_str_ptr, "pending",
929 		    strlen("pending")) != 0) ||
930 		    (sstate->sip_str_len == strlen("active") &&
931 		    strncasecmp(sstate->sip_str_ptr, "active",
932 		    strlen("active")) != 0))) {
933 			sip_free_header(thdr);
934 			return (NULL);
935 		}
936 		ttag = sip_get_from_tag((sip_msg_t)sip_msg, NULL);
937 	} else {
938 		if (dialog->sip_dlg_type == SIP_UAS_DIALOG) {
939 			thdr = sip_dlg_xchg_from_to((sip_msg_t)sip_msg,
940 			    SIP_DLG_XCHG_TO);
941 			alloc_thdr = B_TRUE;
942 		} else {
943 			(void) pthread_mutex_lock(&sip_msg->sip_msg_mutex);
944 			thdr = sip_search_for_header(sip_msg, SIP_TO, NULL);
945 			if (dialog->sip_dlg_remote_target == NULL) {
946 				chdr = sip_search_for_header(sip_msg,
947 				    SIP_CONTACT, NULL);
948 			}
949 			(void) pthread_mutex_unlock(&sip_msg->sip_msg_mutex);
950 		}
951 		if (thdr == NULL) {
952 			(void) pthread_mutex_unlock(&sip_msg->sip_msg_mutex);
953 			return (NULL);
954 		}
955 		ttag = sip_get_to_tag((sip_msg_t)sip_msg, NULL);
956 	}
957 	if (ttag == NULL) {
958 		if (alloc_thdr)
959 			sip_free_header(thdr);
960 		return (NULL);
961 	}
962 	prev_state = dialog->sip_dlg_state;
963 
964 	if (method == NOTIFY) {
965 		int			error;
966 		const sip_str_t		*dlg_id_val = NULL;
967 		const sip_str_t		*event;
968 		const sip_str_t		*id_val = NULL;
969 		sip_header_value_t	ev_val;
970 		sip_hdr_value_t		*dlg_ev_val = NULL;
971 
972 		event = sip_get_event((sip_msg_t)sip_msg, &error);
973 		if (event == NULL || error != 0) {
974 			sip_free_header(thdr);
975 			return (NULL);
976 		}
977 		ev_val = (sip_header_value_t)sip_get_header_value(evhdr,
978 		    &error);
979 		if (ev_val != NULL)
980 			id_val = sip_get_param_value(ev_val, "id", &error);
981 		if (error == 0) {
982 			dlg_ev_val = (sip_hdr_value_t *)sip_get_header_value(
983 			    dialog->sip_dlg_event, &error);
984 		}
985 		if (dlg_ev_val == NULL || error != 0) {
986 			sip_free_header(thdr);
987 			return (NULL);
988 		}
989 		dlg_id_val = sip_get_param_value((sip_header_value_t)dlg_ev_val,
990 		    "id", &error);
991 		if (error != 0 ||
992 		    dlg_ev_val->str_val_len != event->sip_str_len ||
993 		    strncmp(dlg_ev_val->str_val_ptr, event->sip_str_ptr,
994 		    event->sip_str_len != 0)) {
995 			sip_free_header(thdr);
996 			return (NULL);
997 		}
998 		if ((dlg_id_val == NULL && id_val != NULL) ||
999 		    (dlg_id_val != NULL && id_val == NULL)) {
1000 			sip_free_header(thdr);
1001 			return (NULL);
1002 		} else if (dlg_id_val != NULL && id_val != NULL) {
1003 			if (dlg_id_val->sip_str_len != id_val->sip_str_len ||
1004 			    strncasecmp(dlg_id_val->sip_str_ptr,
1005 			    id_val->sip_str_ptr, dlg_id_val->sip_str_len) !=
1006 			    0) {
1007 				sip_free_header(thdr);
1008 				return (NULL);
1009 			}
1010 		}
1011 		if (dialog->sip_dlg_type == SIP_UAC_DIALOG) {
1012 			dialog->sip_dlg_remote_uri_tag = thdr;
1013 			if ((dialog->sip_dlg_remote_target =
1014 			    sip_dup_header(chdr)) == NULL) {
1015 				sip_free_header(thdr);
1016 				return (NULL);
1017 			}
1018 		} else {
1019 			dialog->sip_dlg_local_uri_tag = thdr;
1020 		}
1021 		dialog->sip_dlg_state = SIP_DLG_CONFIRMED;
1022 	} else {
1023 		resp_code = sip_get_response_code((sip_msg_t)sip_msg, &error);
1024 		(void) pthread_mutex_lock(&dialog->sip_dlg_mutex);
1025 		if (dialog->sip_dlg_state != SIP_DLG_NEW) {
1026 			sip_write_to_log((void *)dialog, SIP_DIALOG_LOG |
1027 			    SIP_ASSERT_ERROR, __FILE__, __LINE__);
1028 		}
1029 		assert(dialog->sip_dlg_state == SIP_DLG_NEW);
1030 		if (dialog->sip_dlg_remote_target == NULL && chdr != NULL) {
1031 			if (dialog->sip_dlg_type != SIP_UAC_DIALOG) {
1032 				sip_write_to_log((void *)dialog,
1033 				    SIP_DIALOG_LOG | SIP_ASSERT_ERROR,
1034 				    __FILE__, __LINE__);
1035 			}
1036 			assert(dialog->sip_dlg_type == SIP_UAC_DIALOG);
1037 			if ((dialog->sip_dlg_remote_target =
1038 			    sip_dup_header(chdr)) == NULL) {
1039 				(void) pthread_mutex_unlock(
1040 				    &dialog->sip_dlg_mutex);
1041 				if (alloc_thdr)
1042 					sip_free_header(thdr);
1043 				goto terminate_new_dlg;
1044 			}
1045 			if (sip_dialog_get_route_set(dialog, sip_msg,
1046 			    dialog->sip_dlg_type) != 0) {
1047 				(void) pthread_mutex_unlock(
1048 				    &dialog->sip_dlg_mutex);
1049 				if (alloc_thdr)
1050 					sip_free_header(thdr);
1051 				goto terminate_new_dlg;
1052 			}
1053 		}
1054 		if (SIP_PROVISIONAL_RESP(resp_code)) {
1055 			dialog->sip_dlg_state = SIP_DLG_EARLY;
1056 		} else if (SIP_OK_RESP(resp_code)) {
1057 			/*
1058 			 * Per 12.1 the UAS must include the contact header
1059 			 * for a dialog establishing response, so if we
1060 			 * don't find one, we terminate it.
1061 			 */
1062 			if (dialog->sip_dlg_remote_target == NULL) {
1063 				(void) pthread_mutex_unlock(
1064 				    &dialog->sip_dlg_mutex);
1065 				if (sip_ulp_dlg_del_cb != NULL) {
1066 					sip_ulp_dlg_del_cb(dialog,
1067 					    (sip_msg_t)sip_msg, NULL);
1068 				}
1069 				if (alloc_thdr)
1070 					sip_free_header(thdr);
1071 				goto terminate_new_dlg;
1072 			}
1073 			dialog->sip_dlg_state = SIP_DLG_CONFIRMED;
1074 		} else {
1075 			(void) pthread_mutex_unlock(&dialog->sip_dlg_mutex);
1076 			if (sip_ulp_dlg_del_cb != NULL) {
1077 				sip_ulp_dlg_del_cb(dialog, (sip_msg_t)sip_msg,
1078 				    NULL);
1079 			}
1080 			if (alloc_thdr)
1081 				sip_free_header(thdr);
1082 			goto terminate_new_dlg;
1083 		}
1084 		if (dialog->sip_dlg_type == SIP_UAS_DIALOG) {
1085 			dialog->sip_dlg_local_uri_tag = thdr;
1086 		} else {
1087 			if ((dialog->sip_dlg_remote_uri_tag =
1088 			    sip_dup_header(thdr)) == NULL) {
1089 				(void) pthread_mutex_unlock(
1090 				    &dialog->sip_dlg_mutex);
1091 				goto terminate_new_dlg;
1092 			}
1093 		}
1094 	}
1095 
1096 	/*
1097 	 * We take the local contact for UAS Dialog from the response (either
1098 	 * NOTIFY for SUBSCRIBE request or from final response 2xx to INVITE
1099 	 * request)
1100 	 */
1101 	if ((dialog->sip_dlg_type == SIP_UAS_DIALOG) && (dialog->sip_dlg_state
1102 	    == SIP_DLG_CONFIRMED)) {
1103 		if (chdr == NULL) {
1104 			(void) pthread_mutex_lock(&sip_msg->sip_msg_mutex);
1105 			chdr = sip_search_for_header(sip_msg, SIP_CONTACT,
1106 			    NULL);
1107 			(void) pthread_mutex_unlock(&sip_msg->sip_msg_mutex);
1108 		}
1109 		if ((chdr == NULL) || ((dialog->sip_dlg_local_contact =
1110 		    sip_dup_header(chdr)) == NULL)) {
1111 			(void) pthread_mutex_unlock(&dialog->sip_dlg_mutex);
1112 			if (alloc_thdr)
1113 				sip_free_header(thdr);
1114 			goto terminate_new_dlg;
1115 		}
1116 	}
1117 
1118 	/*
1119 	 * Cancel the partial dialog timer
1120 	 */
1121 	if (SIP_IS_TIMER_RUNNING(dialog->sip_dlg_timer))
1122 		SIP_CANCEL_TIMER(dialog->sip_dlg_timer);
1123 
1124 	if (dialog->sip_dlg_type == SIP_UAC_DIALOG) {
1125 		val =  sip_get_header_value(dialog->sip_dlg_local_uri_tag,
1126 		    &error);
1127 	} else {
1128 		val =  sip_get_header_value(dialog->sip_dlg_remote_uri_tag,
1129 		    &error);
1130 	}
1131 	if (val == NULL || error != 0) {
1132 		sip_write_to_log((void *)dialog, SIP_DIALOG_LOG |
1133 		    SIP_ASSERT_ERROR, __FILE__, __LINE__);
1134 	}
1135 	assert(val != NULL && error == 0);
1136 	remtag = sip_get_param_value((sip_header_value_t)val, "tag", &error);
1137 
1138 	val = sip_get_header_value(dialog->sip_dlg_call_id, &error);
1139 	callid = &((sip_hdr_value_t *)val)->str_val;
1140 
1141 	/*
1142 	 * Get an ID for this dialog
1143 	 */
1144 	if (dialog->sip_dlg_type == SIP_UAC_DIALOG) {
1145 		sip_md5_hash(remtag->sip_str_ptr, remtag->sip_str_len,
1146 		    ttag->sip_str_ptr, ttag->sip_str_len,
1147 		    callid->sip_str_ptr, callid->sip_str_len,
1148 		    NULL, 0, NULL, 0, NULL, 0, (uchar_t *)dialog->sip_dlg_id);
1149 	} else {
1150 		sip_md5_hash(ttag->sip_str_ptr, ttag->sip_str_len,
1151 		    remtag->sip_str_ptr, remtag->sip_str_len,
1152 		    callid->sip_str_ptr, callid->sip_str_len,
1153 		    NULL, 0, NULL, 0, NULL, 0, (uchar_t *)dialog->sip_dlg_id);
1154 	}
1155 
1156 	SIP_DLG_REFCNT_INCR(dialog);
1157 	(void) pthread_mutex_unlock(&dialog->sip_dlg_mutex);
1158 
1159 	/*
1160 	 * Add it to the hash table
1161 	 */
1162 	if (sip_hash_add(sip_dialog_hash, (void *)dialog,
1163 	    SIP_DIGEST_TO_HASH(dialog->sip_dlg_id)) != 0) {
1164 	terminate_new_dlg:
1165 		/*
1166 		 * So that sip_dialog_delete() does not try to remove
1167 		 * this from the hash table.
1168 		 */
1169 		(void) pthread_mutex_lock(&dialog->sip_dlg_mutex);
1170 		if (dialog->sip_dlg_type == SIP_UAS_DIALOG) {
1171 			if (dialog->sip_dlg_local_uri_tag != NULL) {
1172 				sip_free_header(dialog->sip_dlg_local_uri_tag);
1173 				dialog->sip_dlg_local_uri_tag = NULL;
1174 			}
1175 		} else {
1176 			if (dialog->sip_dlg_remote_uri_tag != NULL) {
1177 				sip_free_header(dialog->sip_dlg_remote_uri_tag);
1178 				dialog->sip_dlg_remote_uri_tag = NULL;
1179 			}
1180 		}
1181 		(void) pthread_mutex_unlock(&dialog->sip_dlg_mutex);
1182 		sip_dialog_terminate(dialog, (sip_msg_t)sip_msg);
1183 		return (NULL);
1184 	}
1185 	if (sip_dlg_ulp_state_cb != NULL) {
1186 		sip_dlg_ulp_state_cb((sip_dialog_t)dialog,
1187 		    (sip_msg_t)sip_msg, prev_state, dialog->sip_dlg_state);
1188 	}
1189 	return ((sip_dialog_t)dialog);
1190 }
1191 
1192 /*
1193  * Check if this dialog is a match.
1194  */
1195 boolean_t
1196 sip_dialog_match(void *obj, void *hindex)
1197 {
1198 	_sip_dialog_t	*dialog = (_sip_dialog_t *)obj;
1199 
1200 	(void) pthread_mutex_lock(&dialog->sip_dlg_mutex);
1201 	if (dialog->sip_dlg_state == SIP_DLG_DESTROYED) {
1202 		(void) pthread_mutex_unlock(&dialog->sip_dlg_mutex);
1203 		return (B_FALSE);
1204 	}
1205 	if (bcmp(dialog->sip_dlg_id, hindex,
1206 	    sizeof (dialog->sip_dlg_id)) == 0) {
1207 		SIP_DLG_REFCNT_INCR(dialog);
1208 		(void) pthread_mutex_unlock(&dialog->sip_dlg_mutex);
1209 		return (B_TRUE);
1210 	}
1211 	(void) pthread_mutex_unlock(&dialog->sip_dlg_mutex);
1212 	return (B_FALSE);
1213 }
1214 
1215 /*
1216  * Don't delete, just take it out of the hash
1217  */
1218 boolean_t
1219 sip_dialog_dontfree(void *obj, void *hindex, int *found)
1220 {
1221 	_sip_dialog_t	*dialog = (_sip_dialog_t *)obj;
1222 
1223 	*found = 0;
1224 	(void) pthread_mutex_lock(&dialog->sip_dlg_mutex);
1225 	if (bcmp(dialog->sip_dlg_id, hindex, sizeof (dialog->sip_dlg_id))
1226 	    == 0) {
1227 		*found = 1;
1228 		(void) pthread_mutex_unlock(&dialog->sip_dlg_mutex);
1229 		return (B_TRUE);
1230 	}
1231 	(void) pthread_mutex_unlock(&dialog->sip_dlg_mutex);
1232 	return (B_FALSE);
1233 }
1234 
1235 /*
1236  * Free resources associated with the dialog, the object will be removed
1237  * from the hash list by sip_hash_delete.
1238  */
1239 boolean_t
1240 sip_dialog_free(void *obj, void *hindex, int *found)
1241 {
1242 	_sip_dialog_t	*dialog = (_sip_dialog_t *)obj;
1243 
1244 	*found = 0;
1245 	(void) pthread_mutex_lock(&dialog->sip_dlg_mutex);
1246 	if (bcmp(dialog->sip_dlg_id, hindex, sizeof (dialog->sip_dlg_id))
1247 	    == 0) {
1248 		*found = 1;
1249 		if (dialog->sip_dlg_state != SIP_DLG_DESTROYED) {
1250 			sip_write_to_log((void *)dialog, SIP_DIALOG_LOG |
1251 			    SIP_ASSERT_ERROR, __FILE__, __LINE__);
1252 		}
1253 		assert(dialog->sip_dlg_state == SIP_DLG_DESTROYED);
1254 		if (dialog->sip_dlg_ref_cnt != 0) {
1255 			(void) pthread_mutex_unlock(&dialog->sip_dlg_mutex);
1256 			return (B_FALSE);
1257 		}
1258 		sip_write_to_log((void *)dialog, SIP_DIALOG_LOG, NULL, 0);
1259 		sip_release_dialog_res(dialog);
1260 		return (B_TRUE);
1261 	}
1262 	(void) pthread_mutex_unlock(&dialog->sip_dlg_mutex);
1263 	return (B_FALSE);
1264 }
1265 
1266 /*
1267  * The UAS will receive the request from the transaction layer.  If the
1268  * request has a tag in the To header field, the UAS core computes the
1269  * dialog identifier corresponding to the request and compares it with
1270  * existing dialogs.  If there is a match, this is a mid-dialog request.
1271  */
1272 sip_dialog_t
1273 sip_dialog_find(_sip_msg_t *sip_msg)
1274 {
1275 	const sip_str_t	*localtag;
1276 	const sip_str_t	*remtag;
1277 	const sip_str_t	*callid;
1278 	uint16_t	digest[8];
1279 	_sip_dialog_t	*dialog;
1280 	boolean_t	is_request;
1281 	int		error;
1282 
1283 	is_request = sip_msg_is_request((sip_msg_t)sip_msg, &error);
1284 	if (error != 0)
1285 		return (NULL);
1286 	if (is_request) {
1287 		localtag = sip_get_to_tag((sip_msg_t)sip_msg, &error);
1288 		if (error == 0)
1289 			remtag = sip_get_from_tag((sip_msg_t)sip_msg, &error);
1290 	} else {
1291 		remtag = sip_get_to_tag((sip_msg_t)sip_msg, &error);
1292 		if (error == 0)
1293 			localtag = sip_get_from_tag((sip_msg_t)sip_msg, &error);
1294 	}
1295 	if (error != 0)
1296 		return (NULL);
1297 	callid = sip_get_callid((sip_msg_t)sip_msg, &error);
1298 	if (error != 0 || remtag == NULL || localtag == NULL ||
1299 	    callid == NULL) {
1300 		return (NULL);
1301 	}
1302 	sip_md5_hash(localtag->sip_str_ptr, localtag->sip_str_len,
1303 	    remtag->sip_str_ptr, remtag->sip_str_len,
1304 	    callid->sip_str_ptr, callid->sip_str_len,
1305 	    NULL, 0, NULL, 0, NULL, 0, (uchar_t *)digest);
1306 
1307 	dialog = (_sip_dialog_t *)sip_hash_find(sip_dialog_hash,
1308 	    (void *)digest, SIP_DIGEST_TO_HASH(digest), sip_dialog_match);
1309 	if (dialog == NULL) {
1310 		sip_md5_hash(localtag->sip_str_ptr, localtag->sip_str_len,
1311 		    NULL, 0, callid->sip_str_ptr, callid->sip_str_len,
1312 		    NULL, 0, NULL, 0, NULL, 0, (uchar_t *)digest);
1313 		dialog = (_sip_dialog_t *)sip_hash_find(sip_dialog_phash,
1314 		    (void *)digest, SIP_DIGEST_TO_HASH(digest),
1315 		    sip_dialog_match);
1316 	}
1317 	return ((sip_dialog_t)dialog);
1318 }
1319 
1320 /*
1321  * We keep this partial dialog for the duration of the INVITE
1322  * transaction timeout duration, i.e. Timer B.
1323  */
1324 void
1325 sip_dlg_self_destruct(void *args)
1326 {
1327 	sip_dialog_timer_obj_t	*tim_obj = (sip_dialog_timer_obj_t *)args;
1328 	_sip_dialog_t		*dialog = (_sip_dialog_t *)tim_obj->dialog;
1329 	int			index;
1330 
1331 	(void) pthread_mutex_lock(&dialog->sip_dlg_mutex);
1332 	if (dialog->sip_dlg_state != SIP_DLG_NEW) {
1333 		sip_write_to_log((void *)dialog, SIP_DIALOG_LOG |
1334 		    SIP_ASSERT_ERROR, __FILE__, __LINE__);
1335 	}
1336 	assert(dialog->sip_dlg_state == SIP_DLG_NEW);
1337 	dialog->sip_dlg_state = SIP_DLG_DESTROYED;
1338 	if (dialog->sip_dlg_type == SIP_UAC_DIALOG) {
1339 		index = SIP_DIGEST_TO_HASH(dialog->sip_dlg_id);
1340 		(void) pthread_mutex_unlock(&dialog->sip_dlg_mutex);
1341 		sip_hash_delete(sip_dialog_phash, (void *)dialog->sip_dlg_id,
1342 		    index, sip_dialog_dontfree);
1343 	} else {
1344 		(void) pthread_mutex_unlock(&dialog->sip_dlg_mutex);
1345 	}
1346 	if (tim_obj->func != NULL)
1347 		tim_obj->func(dialog, NULL, NULL);
1348 	free(tim_obj);
1349 	SIP_DLG_REFCNT_DECR(dialog);
1350 }
1351 
1352 /*
1353  * Terminate a dialog
1354  */
1355 void
1356 sip_dialog_terminate(_sip_dialog_t *dialog, sip_msg_t sip_msg)
1357 {
1358 	int	prev_state;
1359 
1360 	(void) pthread_mutex_lock(&dialog->sip_dlg_mutex);
1361 	prev_state = dialog->sip_dlg_state;
1362 	dialog->sip_dlg_state = SIP_DLG_DESTROYED;
1363 	(void) pthread_mutex_unlock(&dialog->sip_dlg_mutex);
1364 	if (sip_dlg_ulp_state_cb != NULL) {
1365 		sip_dlg_ulp_state_cb((sip_dialog_t)dialog, sip_msg, prev_state,
1366 		    dialog->sip_dlg_state);
1367 	}
1368 	SIP_DLG_REFCNT_DECR(dialog);
1369 }
1370 
1371 /*
1372  * Delete a dialog
1373  */
1374 void
1375 sip_dialog_delete(_sip_dialog_t *dialog)
1376 {
1377 	int	index;
1378 
1379 	/*
1380 	 * partial dialog, not in the hash table
1381 	 */
1382 	if (dialog->sip_dlg_local_uri_tag == NULL ||
1383 	    dialog->sip_dlg_remote_uri_tag == NULL) {
1384 		/*
1385 		 * Cancel the partial dialog timer
1386 		 */
1387 		if (SIP_IS_TIMER_RUNNING(dialog->sip_dlg_timer))
1388 			SIP_CANCEL_TIMER(dialog->sip_dlg_timer);
1389 		sip_write_to_log((void *)dialog, SIP_DIALOG_LOG, NULL, 0);
1390 		sip_release_dialog_res(dialog);
1391 		return;
1392 	}
1393 	index = SIP_DIGEST_TO_HASH(dialog->sip_dlg_id);
1394 	sip_hash_delete(sip_dialog_hash, (void *)dialog->sip_dlg_id, index,
1395 	    sip_dialog_free);
1396 }
1397 
1398 /*
1399  * Get the remote target from the CONTACT header from the 200 OK response
1400  */
1401 static boolean_t
1402 sip_get_rtarg(_sip_dialog_t *dialog, _sip_msg_t *sip_msg)
1403 {
1404 	sip_header_t	chdr;
1405 
1406 	if (dialog->sip_dlg_remote_target != NULL)
1407 		return (B_TRUE);
1408 
1409 	(void) pthread_mutex_lock(&sip_msg->sip_msg_mutex);
1410 	chdr = sip_search_for_header(sip_msg, SIP_CONTACT, NULL);
1411 	(void) pthread_mutex_unlock(&sip_msg->sip_msg_mutex);
1412 	if (chdr == NULL)
1413 		return (B_FALSE);
1414 	if ((dialog->sip_dlg_remote_target = sip_dup_header(chdr)) == NULL)
1415 		return (B_FALSE);
1416 
1417 	return (B_TRUE);
1418 }
1419 
1420 /*
1421  * Process an incoming request/response
1422  */
1423 /* ARGSUSED */
1424 int
1425 sip_dialog_process(_sip_msg_t *sip_msg, sip_dialog_t *sip_dialog)
1426 {
1427 	boolean_t	request;
1428 	_sip_dialog_t	*_dialog;
1429 	int		error;
1430 
1431 	_dialog = (_sip_dialog_t *)*sip_dialog;
1432 
1433 	(void) pthread_mutex_lock(&_dialog->sip_dlg_mutex);
1434 	_dialog->sip_dlg_msgcnt++;
1435 	sip_add_log(&_dialog->sip_dlg_log[_dialog->sip_dlg_state],
1436 	    (sip_msg_t)sip_msg, _dialog->sip_dlg_msgcnt, SIP_DIALOG_LOG);
1437 	(void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
1438 
1439 	request = sip_msg_is_request((sip_msg_t)sip_msg, &error);
1440 	if (error != 0)
1441 		return (EINVAL);
1442 	if (request) {
1443 		uint32_t	cseq;
1444 		sip_method_t	method;
1445 
1446 		cseq = sip_get_callseq_num((sip_msg_t)sip_msg, &error);
1447 		if (error != 0)
1448 			return (EINVAL);
1449 		method = sip_get_callseq_method((sip_msg_t)sip_msg, &error);
1450 		if (error != 0)
1451 			return (EINVAL);
1452 		if (sip_get_request_method((sip_msg_t)sip_msg, &error) !=
1453 		    method) {
1454 			return (EINVAL);
1455 		}
1456 		(void) pthread_mutex_lock(&_dialog->sip_dlg_mutex);
1457 		/*
1458 		 * Requests that do not change in any way the state
1459 		 * of a dialog may be received within a dialog.
1460 		 * They are processed as if they had been received
1461 		 * outside the dialog.
1462 		 * For dialogs that have been established with an
1463 		 * INVITE, the only target refresh request defined is
1464 		 * re-INVITE.
1465 		 */
1466 		if (_dialog->sip_dlg_method == INVITE &&
1467 		    method == INVITE && _dialog->sip_dlg_remote_cseq != 0 &&
1468 		    SIP_CSEQ_LT(cseq, _dialog->sip_dlg_remote_cseq)) {
1469 			(void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
1470 			return (EPROTO);
1471 		}
1472 		/*
1473 		 * Target-Refresh request
1474 		 */
1475 		if (_dialog->sip_dlg_method == INVITE && method == INVITE) {
1476 			sip_header_t	chdr;
1477 			sip_header_t	nchdr;
1478 
1479 			(void) pthread_mutex_lock(&sip_msg->sip_msg_mutex);
1480 			chdr = sip_search_for_header(sip_msg, SIP_CONTACT,
1481 			    NULL);
1482 			(void) pthread_mutex_unlock(&sip_msg->sip_msg_mutex);
1483 			if (chdr != NULL &&
1484 			    (nchdr = sip_dup_header(chdr)) != NULL) {
1485 				if (_dialog->sip_dlg_remote_target != NULL) {
1486 					sip_free_header(
1487 					    _dialog->sip_dlg_remote_target);
1488 				}
1489 				_dialog->sip_dlg_remote_target = nchdr;
1490 			}
1491 		}
1492 		_dialog->sip_dlg_remote_cseq = cseq;
1493 		(void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
1494 	} else {
1495 		int		resp_code;
1496 		sip_method_t	method;
1497 		int		error;
1498 
1499 		resp_code = sip_get_response_code((sip_msg_t)sip_msg, &error);
1500 		if (error == 0) {
1501 			method = sip_get_callseq_method((sip_msg_t)sip_msg,
1502 			    &error);
1503 		}
1504 		if (error != 0)
1505 			return (error);
1506 
1507 		(void) pthread_mutex_lock(&_dialog->sip_dlg_mutex);
1508 		if (_dialog->sip_dlg_state == SIP_DLG_DESTROYED) {
1509 			(void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
1510 			return (0);
1511 		}
1512 		if (_dialog->sip_dlg_state != SIP_DLG_EARLY &&
1513 		    _dialog->sip_dlg_state != SIP_DLG_CONFIRMED) {
1514 			sip_write_to_log((void *)_dialog, SIP_DIALOG_LOG |
1515 			    SIP_ASSERT_ERROR, __FILE__, __LINE__);
1516 		}
1517 		assert(_dialog->sip_dlg_state == SIP_DLG_EARLY ||
1518 		    _dialog->sip_dlg_state == SIP_DLG_CONFIRMED);
1519 		/*
1520 		 * Let the user delete the dialog if it is not a 1XX/2XX resp
1521 		 * for an early INVITE dialog.
1522 		 */
1523 		if (SIP_OK_RESP(resp_code)) {
1524 			if (method == INVITE) {
1525 				if (!sip_get_rtarg(_dialog, sip_msg)) {
1526 					(void) pthread_mutex_unlock(
1527 					    &_dialog->sip_dlg_mutex);
1528 					if (sip_ulp_dlg_del_cb != NULL) {
1529 						sip_ulp_dlg_del_cb(
1530 						    (sip_dialog_t)_dialog,
1531 						    (sip_msg_t)sip_msg, NULL);
1532 					}
1533 					sip_dialog_terminate(_dialog,
1534 					    (sip_msg_t)sip_msg);
1535 					return (0);
1536 				}
1537 				if (_dialog->sip_dlg_state == SIP_DLG_EARLY) {
1538 					_dialog->sip_dlg_state =
1539 					    SIP_DLG_CONFIRMED;
1540 					(void) sip_dlg_recompute_rset(_dialog,
1541 					    sip_msg, SIP_UAC_DIALOG);
1542 					(void) pthread_mutex_unlock(
1543 					    &_dialog->sip_dlg_mutex);
1544 					if (sip_dlg_ulp_state_cb != NULL) {
1545 						sip_dlg_ulp_state_cb(
1546 						    (sip_dialog_t)_dialog,
1547 						    sip_msg, SIP_DLG_EARLY,
1548 						    _dialog->sip_dlg_state);
1549 					}
1550 					return (0);
1551 				} else if (_dialog->sip_dlg_new_local_contact
1552 				    != NULL) {
1553 					if (_dialog->sip_dlg_local_contact ==
1554 					    NULL) {
1555 						(void) sip_write_to_log((void *)
1556 						    _dialog, SIP_DIALOG_LOG |
1557 						    SIP_ASSERT_ERROR,  __FILE__,
1558 						    __LINE__);
1559 					}
1560 					assert(_dialog->sip_dlg_local_contact
1561 					    != NULL);
1562 					sip_free_header(_dialog->
1563 					    sip_dlg_local_contact);
1564 					_dialog->sip_dlg_local_contact =
1565 					    _dialog->sip_dlg_new_local_contact;
1566 					_dialog->sip_dlg_new_local_contact =
1567 					    NULL;
1568 				}
1569 			}
1570 		}
1571 		(void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
1572 	}
1573 	return (0);
1574 }
1575 
1576 /*
1577  * Copy partial dialog to create a complete dialog
1578  */
1579 _sip_dialog_t *
1580 sip_copy_partial_dialog(_sip_dialog_t *dialog)
1581 {
1582 	_sip_dialog_t	*new_dlg;
1583 
1584 	new_dlg =  calloc(1, sizeof (_sip_dialog_t));
1585 	if (new_dlg == NULL)
1586 		return (NULL);
1587 	if (dialog->sip_dlg_req_uri.sip_str_ptr != NULL) {
1588 		new_dlg->sip_dlg_req_uri.sip_str_ptr =
1589 		    malloc(dialog->sip_dlg_req_uri.sip_str_len + 1);
1590 		if (new_dlg->sip_dlg_req_uri.sip_str_ptr == NULL) {
1591 			free(new_dlg);
1592 			return (NULL);
1593 		}
1594 		(void) strncpy(new_dlg->sip_dlg_req_uri.sip_str_ptr,
1595 		    dialog->sip_dlg_req_uri.sip_str_ptr,
1596 		    dialog->sip_dlg_req_uri.sip_str_len);
1597 		new_dlg->sip_dlg_req_uri.sip_str_ptr[
1598 		    dialog->sip_dlg_req_uri.sip_str_len] = '\0';
1599 		new_dlg->sip_dlg_req_uri.sip_str_len =
1600 		    dialog->sip_dlg_req_uri.sip_str_len;
1601 	}
1602 	if (dialog->sip_dlg_route_set != NULL) {
1603 		if (dialog->sip_dlg_rset.sip_str_ptr == NULL) {
1604 			sip_write_to_log((void *)dialog, SIP_DIALOG_LOG |
1605 			    SIP_ASSERT_ERROR, __FILE__, __LINE__);
1606 		}
1607 		assert(dialog->sip_dlg_rset.sip_str_ptr != NULL);
1608 		new_dlg->sip_dlg_rset.sip_str_ptr =
1609 		    malloc(dialog->sip_dlg_rset.sip_str_len + 1);
1610 		if (new_dlg->sip_dlg_rset.sip_str_ptr == NULL) {
1611 			if (new_dlg->sip_dlg_req_uri.sip_str_ptr != NULL)
1612 				free(new_dlg->sip_dlg_req_uri.sip_str_ptr);
1613 			free(new_dlg);
1614 			return (NULL);
1615 		}
1616 		(void) strncpy(new_dlg->sip_dlg_rset.sip_str_ptr,
1617 		    dialog->sip_dlg_rset.sip_str_ptr,
1618 		    dialog->sip_dlg_rset.sip_str_len);
1619 		new_dlg->sip_dlg_rset.sip_str_ptr[
1620 		    dialog->sip_dlg_rset.sip_str_len] = '\0';
1621 		new_dlg->sip_dlg_rset.sip_str_len =
1622 		    dialog->sip_dlg_rset.sip_str_len;
1623 
1624 		new_dlg->sip_dlg_route_set =
1625 		    sip_dup_header(dialog->sip_dlg_route_set);
1626 		if (new_dlg->sip_dlg_route_set == NULL) {
1627 			free(new_dlg->sip_dlg_rset.sip_str_ptr);
1628 			if (new_dlg->sip_dlg_req_uri.sip_str_ptr != NULL)
1629 				free(new_dlg->sip_dlg_req_uri.sip_str_ptr);
1630 			free(new_dlg);
1631 			return (NULL);
1632 		}
1633 	}
1634 	if ((new_dlg->sip_dlg_local_uri_tag =
1635 	    sip_dup_header(dialog->sip_dlg_local_uri_tag)) == NULL ||
1636 	    (new_dlg->sip_dlg_remote_target =
1637 	    sip_dup_header(dialog->sip_dlg_remote_target)) == NULL ||
1638 	    (new_dlg->sip_dlg_local_contact =
1639 	    sip_dup_header(dialog->sip_dlg_local_contact)) == NULL ||
1640 	    (new_dlg->sip_dlg_call_id =
1641 	    sip_dup_header(dialog->sip_dlg_call_id)) == NULL) {
1642 		sip_release_dialog_res(new_dlg);
1643 		return (NULL);
1644 	}
1645 	if (dialog->sip_dlg_event != NULL) {
1646 		new_dlg->sip_dlg_event = sip_dup_header(dialog->sip_dlg_event);
1647 		if (new_dlg->sip_dlg_event == NULL) {
1648 			sip_release_dialog_res(new_dlg);
1649 			return (NULL);
1650 		}
1651 	}
1652 	new_dlg->sip_dlg_local_cseq = dialog->sip_dlg_local_cseq;
1653 	new_dlg->sip_dlg_type = dialog->sip_dlg_type;
1654 	new_dlg->sip_dlg_on_fork = B_FALSE;
1655 	(void) pthread_mutex_init(&new_dlg->sip_dlg_mutex, NULL);
1656 
1657 	return (new_dlg);
1658 }
1659 
1660 /*
1661  * Update the dialog using the response
1662  */
1663 sip_dialog_t
1664 sip_update_dialog(sip_dialog_t dialog, _sip_msg_t *sip_msg)
1665 {
1666 	_sip_dialog_t	*_dialog;
1667 	boolean_t	isreq;
1668 	sip_method_t	method;
1669 	int		resp_code = 0;
1670 	int		prev_state;
1671 	boolean_t	decr_ref = B_FALSE;
1672 	int		error;
1673 
1674 	_dialog = (_sip_dialog_t *)dialog;
1675 	(void) pthread_mutex_lock(&_dialog->sip_dlg_mutex);
1676 	_dialog->sip_dlg_msgcnt++;
1677 	sip_add_log(&_dialog->sip_dlg_log[_dialog->sip_dlg_state],
1678 	    (sip_msg_t)sip_msg, _dialog->sip_dlg_msgcnt, SIP_DIALOG_LOG);
1679 	(void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
1680 
1681 	isreq = sip_msg_is_request((sip_msg_t)sip_msg, &error);
1682 	if (error != 0)
1683 		return (dialog);
1684 	(void) pthread_mutex_lock(&_dialog->sip_dlg_mutex);
1685 	if (isreq) {
1686 		method = sip_get_request_method((sip_msg_t)sip_msg, &error);
1687 		if (error != 0 || _dialog->sip_dlg_method != SUBSCRIBE ||
1688 		    method != NOTIFY) {
1689 			(void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
1690 			return (dialog);
1691 		}
1692 	} else {
1693 		resp_code = sip_get_response_code((sip_msg_t)sip_msg, &error);
1694 		if (error != 0) {
1695 			(void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
1696 			return (dialog);
1697 		}
1698 		method = sip_get_callseq_method((sip_msg_t)sip_msg, &error);
1699 		if (error != 0) {
1700 			(void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
1701 			return (dialog);
1702 		}
1703 	}
1704 	prev_state = _dialog->sip_dlg_state;
1705 	if (_dialog->sip_dlg_state == SIP_DLG_CONFIRMED) {
1706 		(void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
1707 	} else if (_dialog->sip_dlg_state == SIP_DLG_EARLY) {
1708 		/*
1709 		 * Let the user delete the dialog if it is not a 1XX/2XX resp
1710 		 * for an early dialog.
1711 		 */
1712 		if (isreq) {
1713 			sip_write_to_log((void *)_dialog, SIP_DIALOG_LOG |
1714 			    SIP_ASSERT_ERROR, __FILE__, __LINE__);
1715 		}
1716 		assert(!isreq);
1717 		if (SIP_OK_RESP(resp_code)) {
1718 			_dialog->sip_dlg_state = SIP_DLG_CONFIRMED;
1719 			/*
1720 			 * If we recieved provisional response before we would
1721 			 * not have captured local contact. So store it now.
1722 			 */
1723 			if (_dialog->sip_dlg_type == SIP_UAS_DIALOG && _dialog->
1724 			    sip_dlg_method == INVITE && method == INVITE) {
1725 				sip_header_t chdr;
1726 				(void) pthread_mutex_lock(&sip_msg->
1727 				    sip_msg_mutex);
1728 				chdr = sip_search_for_header(sip_msg,
1729 				    SIP_CONTACT, NULL);
1730 				(void) pthread_mutex_unlock(&sip_msg->
1731 				    sip_msg_mutex);
1732 				if (chdr != NULL) {
1733 					_dialog->sip_dlg_local_contact
1734 					    = sip_dup_header(chdr);
1735 					_dialog->sip_dlg_new_local_contact =
1736 					    NULL;
1737 				}
1738 			}
1739 			(void) sip_dlg_recompute_rset(_dialog, sip_msg,
1740 			    SIP_UAS_DIALOG);
1741 			(void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
1742 			if (sip_dlg_ulp_state_cb != NULL) {
1743 				sip_dlg_ulp_state_cb(dialog, (sip_msg_t)sip_msg,
1744 				    prev_state, dialog->sip_dlg_state);
1745 			}
1746 		} else {
1747 			(void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
1748 		}
1749 	} else if (_dialog->sip_dlg_state == SIP_DLG_NEW) {
1750 		if (!isreq && _dialog->sip_dlg_method == SUBSCRIBE &&
1751 		    SIP_PROVISIONAL_RESP(resp_code)) {
1752 			(void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
1753 			return (dialog);
1754 		}
1755 		if (_dialog->sip_dlg_type == SIP_UAC_DIALOG) {
1756 			_sip_dialog_t	*new_dlg;
1757 
1758 			if (_dialog->sip_dlg_on_fork) {
1759 				new_dlg = sip_copy_partial_dialog(_dialog);
1760 				if (new_dlg == NULL) {
1761 					(void) pthread_mutex_unlock(
1762 					    &_dialog->sip_dlg_mutex);
1763 					return (dialog);
1764 				}
1765 				/*
1766 				 * This decr/incr dance is because the caller
1767 				 * has incremented the ref on the partial
1768 				 * dialog, we release it here and incr the
1769 				 * ref on the new dialog which will be
1770 				 * released by the caller.
1771 				 */
1772 				(void) pthread_mutex_unlock(
1773 				    &_dialog->sip_dlg_mutex);
1774 				SIP_DLG_REFCNT_DECR(_dialog);
1775 				_dialog = new_dlg;
1776 				(void) pthread_mutex_lock(
1777 				    &_dialog->sip_dlg_mutex);
1778 				SIP_DLG_REFCNT_INCR(_dialog);
1779 			} else {
1780 				int	index;
1781 
1782 				/*
1783 				 * take it out of the list so that further
1784 				 * responses will not result in a dialog.
1785 				 * We will have an extra refcount when we
1786 				 * come back from sip_complete_dialog(), i.e.
1787 				 * one when the partial dialog was created -
1788 				 * in sip_seed_dialog(), one held by the caller
1789 				 * and one that will be added by
1790 				 * sip_complete_dialog(). We need to release
1791 				 * the one added by the sip_seed_dialog(),
1792 				 * since the one in sip_complete_dialog()
1793 				 * is for the same purpose.
1794 				 */
1795 				if (SIP_IS_TIMER_RUNNING(
1796 				    _dialog->sip_dlg_timer)) {
1797 					SIP_CANCEL_TIMER(
1798 					    _dialog->sip_dlg_timer);
1799 				}
1800 				index = SIP_DIGEST_TO_HASH(dialog->sip_dlg_id);
1801 				(void) pthread_mutex_unlock(
1802 				    &_dialog->sip_dlg_mutex);
1803 				sip_hash_delete(sip_dialog_phash,
1804 				    (void *)_dialog->sip_dlg_id,
1805 				    index, sip_dialog_dontfree);
1806 				(void) pthread_mutex_lock(
1807 				    &_dialog->sip_dlg_mutex);
1808 				decr_ref = B_TRUE;
1809 			}
1810 		} else {
1811 			decr_ref = B_TRUE;
1812 		}
1813 		(void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
1814 		if ((dialog = sip_complete_dialog(sip_msg, _dialog)) ==
1815 		    NULL) {
1816 			if (_dialog->sip_dlg_type == SIP_UAC_DIALOG && decr_ref)
1817 				SIP_DLG_REFCNT_DECR(_dialog);
1818 			return (NULL);
1819 		}
1820 		if (decr_ref)
1821 			SIP_DLG_REFCNT_DECR(_dialog);
1822 	} else {
1823 		(void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
1824 	}
1825 	return (dialog);
1826 }
1827 
1828 /*
1829  * Initialize the hash table
1830  */
1831 void
1832 sip_dialog_init(void (*ulp_dlg_del) (sip_dialog_t, sip_msg_t, void *),
1833     void (*ulp_state_cb)(sip_dialog_t, sip_msg_t, int, int))
1834 {
1835 	int	cnt;
1836 
1837 	for (cnt = 0; cnt < SIP_HASH_SZ; cnt++) {
1838 		sip_dialog_hash[cnt].hash_count = 0;
1839 		sip_dialog_hash[cnt].hash_head = NULL;
1840 		sip_dialog_hash[cnt].hash_tail = NULL;
1841 		(void) pthread_mutex_init(
1842 		    &sip_dialog_hash[cnt].sip_hash_mutex, NULL);
1843 		sip_dialog_phash[cnt].hash_count = 0;
1844 		sip_dialog_phash[cnt].hash_head = NULL;
1845 		sip_dialog_phash[cnt].hash_tail = NULL;
1846 		(void) pthread_mutex_init(
1847 		    &sip_dialog_phash[cnt].sip_hash_mutex, NULL);
1848 	}
1849 	if (ulp_dlg_del != NULL)
1850 		sip_ulp_dlg_del_cb = ulp_dlg_del;
1851 
1852 	if (ulp_state_cb != NULL)
1853 		sip_dlg_ulp_state_cb = ulp_state_cb;
1854 }
1855 
1856 /*
1857  * Copy the new contact header of re-INVITE
1858  */
1859 void
1860 sip_dialog_add_new_contact(sip_dialog_t dialog, _sip_msg_t *sip_msg)
1861 {
1862 	sip_header_t chdr = NULL;
1863 	sip_header_t nhdr = NULL;
1864 
1865 	(void) pthread_mutex_lock(&sip_msg->sip_msg_mutex);
1866 	chdr = sip_search_for_header(sip_msg, SIP_CONTACT, NULL);
1867 	(void) pthread_mutex_unlock(&sip_msg->sip_msg_mutex);
1868 
1869 	if (chdr == NULL)
1870 		return;
1871 
1872 	(void) pthread_mutex_lock(&dialog->sip_dlg_mutex);
1873 	if (dialog->sip_dlg_method != INVITE || dialog->sip_dlg_state
1874 	    != SIP_DLG_CONFIRMED) {
1875 		(void) pthread_mutex_unlock(&dialog->sip_dlg_mutex);
1876 		return;
1877 	}
1878 
1879 	if (((nhdr = sip_dup_header(chdr)) != NULL)) {
1880 		if (dialog->sip_dlg_new_local_contact != NULL)
1881 			sip_free_header(dialog->sip_dlg_new_local_contact);
1882 		dialog->sip_dlg_new_local_contact = nhdr;
1883 	}
1884 	(void) pthread_mutex_unlock(&dialog->sip_dlg_mutex);
1885 }
1886 
1887 /*
1888  * Given a state, return the  string - This is mostly for debug purposes
1889  */
1890 char *
1891 sip_get_dialog_state_str(int state)
1892 {
1893 	switch (state) {
1894 		case SIP_DLG_NEW:
1895 			return ("SIP_DLG_NEW");
1896 		case SIP_DLG_EARLY:
1897 			return ("SIP_DLG_EARLY");
1898 		case SIP_DLG_CONFIRMED:
1899 			return ("SIP_DLG_CONFIRMED");
1900 		case SIP_DLG_DESTROYED:
1901 			return ("SIP_DLG_DESTROYED");
1902 		default:
1903 			return ("UNKNOWN");
1904 	}
1905 }
1906