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 */
49void (*sip_dlg_ulp_state_cb)(sip_dialog_t, sip_msg_t, int, int) = NULL;
50void (*sip_ulp_dlg_del_cb)(sip_dialog_t, sip_msg_t, void *) = NULL;
51
52boolean_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 */
62sip_hash_t sip_dialog_hash[SIP_HASH_SZ];
63
64/*
65 * Partial dialog hash table
66 */
67sip_hash_t sip_dialog_phash[SIP_HASH_SZ];
68
69/*
70 * Route set structure
71 */
72typedef 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
79sip_dialog_t		sip_seed_dialog(sip_conn_object_t, _sip_msg_t *,
80			    boolean_t, int);
81sip_dialog_t		sip_complete_dialog(_sip_msg_t *, _sip_dialog_t *);
82int			sip_dialog_process(_sip_msg_t *, sip_dialog_t *);
83void			sip_dialog_delete(_sip_dialog_t *);
84void			sip_dialog_init();
85sip_dialog_t		sip_dialog_find(_sip_msg_t *);
86boolean_t		sip_dialog_match(void *, void *);
87boolean_t		sip_dialog_free(void *, void *, int *);
88sip_dialog_t		sip_update_dialog(sip_dialog_t, _sip_msg_t *);
89char			*sip_dialog_req_uri(sip_dialog_t);
90
91static void		sip_release_dialog_res(_sip_dialog_t *);
92void			sip_dlg_self_destruct(void *);
93static int		sip_dialog_get_route_set(_sip_dialog_t *, _sip_msg_t *,
94			    int);
95static void		sip_dialog_free_rset(sip_dlg_route_set_t *);
96
97/*
98 * Timer object for partial dialogs
99 */
100typedef 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 */
108static void
109sip_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 */
166static sip_dlg_route_set_t *
167sip_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 */
224char *
225sip_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 */
256void
257sip_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 */
273static int
274sip_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 */
315int
316sip_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 */
485static int
486sip_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);
562r_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 */
605sip_dialog_t
606sip_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);
791dia_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 *
805sip_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 */
857sip_dialog_t
858sip_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 */
1195boolean_t
1196sip_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 */
1218boolean_t
1219sip_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 */
1239boolean_t
1240sip_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 */
1272sip_dialog_t
1273sip_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 */
1324void
1325sip_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 */
1355void
1356sip_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 */
1374void
1375sip_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 */
1401static boolean_t
1402sip_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 */
1424int
1425sip_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 *
1580sip_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 */
1663sip_dialog_t
1664sip_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 */
1831void
1832sip_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 */
1859void
1860sip_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 */
1890char *
1891sip_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