xref: /titanic_52/usr/src/lib/libsip/common/sip_dialog_ui.c (revision 943efbc33954e332318b6365bf27037c05bff72c)
140cb5e5dSvi117747 /*
240cb5e5dSvi117747  * CDDL HEADER START
340cb5e5dSvi117747  *
440cb5e5dSvi117747  * The contents of this file are subject to the terms of the
540cb5e5dSvi117747  * Common Development and Distribution License (the "License").
640cb5e5dSvi117747  * You may not use this file except in compliance with the License.
740cb5e5dSvi117747  *
840cb5e5dSvi117747  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
940cb5e5dSvi117747  * or http://www.opensolaris.org/os/licensing.
1040cb5e5dSvi117747  * See the License for the specific language governing permissions
1140cb5e5dSvi117747  * and limitations under the License.
1240cb5e5dSvi117747  *
1340cb5e5dSvi117747  * When distributing Covered Code, include this CDDL HEADER in each
1440cb5e5dSvi117747  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1540cb5e5dSvi117747  * If applicable, add the following below this CDDL HEADER, with the
1640cb5e5dSvi117747  * fields enclosed by brackets "[]" replaced with your own identifying
1740cb5e5dSvi117747  * information: Portions Copyright [yyyy] [name of copyright owner]
1840cb5e5dSvi117747  *
1940cb5e5dSvi117747  * CDDL HEADER END
2040cb5e5dSvi117747  */
2140cb5e5dSvi117747 
2240cb5e5dSvi117747 /*
23*943efbc3Sgm209912  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
2440cb5e5dSvi117747  * Use is subject to license terms.
2540cb5e5dSvi117747  */
2640cb5e5dSvi117747 
2740cb5e5dSvi117747 #pragma ident	"%Z%%M%	%I%	%E% SMI"
2840cb5e5dSvi117747 
292c2c4183Svi117747 #include <stdlib.h>
302c2c4183Svi117747 #include <assert.h>
312c2c4183Svi117747 #include <errno.h>
322c2c4183Svi117747 #include <pthread.h>
332c2c4183Svi117747 #include <sip.h>
342c2c4183Svi117747 
3540cb5e5dSvi117747 #include "sip_msg.h"
3640cb5e5dSvi117747 #include "sip_miscdefs.h"
372c2c4183Svi117747 #include "sip_parse_uri.h"
3840cb5e5dSvi117747 #include "sip_dialog.h"
3940cb5e5dSvi117747 
4040cb5e5dSvi117747 /*
4140cb5e5dSvi117747  * Create a request using the state maintained in the dialog.
4240cb5e5dSvi117747  */
4340cb5e5dSvi117747 sip_msg_t
4440cb5e5dSvi117747 sip_create_dialog_req(sip_method_t method, sip_dialog_t dialog,
4540cb5e5dSvi117747     char *transport, char *sent_by, int sent_by_port, char *via_param,
4640cb5e5dSvi117747     uint32_t maxforward, int cseq)
4740cb5e5dSvi117747 {
4840cb5e5dSvi117747 	_sip_dialog_t	*_dialog;
4940cb5e5dSvi117747 	sip_msg_t	sip_msg;
5040cb5e5dSvi117747 	char		*uri;
5140cb5e5dSvi117747 	int		oldseq = 0;
5240cb5e5dSvi117747 
5340cb5e5dSvi117747 	if (!sip_manage_dialog || dialog == NULL || transport == NULL ||
5440cb5e5dSvi117747 	    sent_by == NULL) {
5540cb5e5dSvi117747 		return (NULL);
5640cb5e5dSvi117747 	}
5740cb5e5dSvi117747 	if ((sip_msg = sip_new_msg()) == NULL)
5840cb5e5dSvi117747 		return (NULL);
5940cb5e5dSvi117747 	_dialog = (_sip_dialog_t *)dialog;
6040cb5e5dSvi117747 	(void) pthread_mutex_lock(&_dialog->sip_dlg_mutex);
6140cb5e5dSvi117747 	/*
6240cb5e5dSvi117747 	 * Depending on the route set, if any, the request URI could either
6340cb5e5dSvi117747 	 * be the contact URI or the 1st URI from the route set.
6440cb5e5dSvi117747 	 */
6540cb5e5dSvi117747 	uri = (char *)sip_dialog_req_uri(_dialog);
6640cb5e5dSvi117747 	if (uri == NULL)
6740cb5e5dSvi117747 		goto err_ret;
6840cb5e5dSvi117747 	if (sip_add_request_line(sip_msg, method, uri) != 0) {
6940cb5e5dSvi117747 		free(uri);
7040cb5e5dSvi117747 		goto err_ret;
7140cb5e5dSvi117747 	}
7240cb5e5dSvi117747 	free(uri);
7340cb5e5dSvi117747 	if (sip_copy_header(sip_msg, _dialog->sip_dlg_local_uri_tag, NULL) != 0)
7440cb5e5dSvi117747 		goto err_ret;
7540cb5e5dSvi117747 	if (sip_copy_header(sip_msg, _dialog->sip_dlg_remote_uri_tag, NULL) !=
7640cb5e5dSvi117747 	    0) {
7740cb5e5dSvi117747 		goto err_ret;
7840cb5e5dSvi117747 	}
79d8a40387Sgm209912 	if (sip_copy_header(sip_msg, _dialog->sip_dlg_local_contact, NULL) != 0)
80d8a40387Sgm209912 		goto err_ret;
8140cb5e5dSvi117747 	if (sip_add_via(sip_msg, transport, sent_by, sent_by_port, via_param) !=
8240cb5e5dSvi117747 	    0) {
8340cb5e5dSvi117747 		goto err_ret;
8440cb5e5dSvi117747 	}
8540cb5e5dSvi117747 	if (sip_add_maxforward(sip_msg, maxforward) != 0)
8640cb5e5dSvi117747 		goto err_ret;
8740cb5e5dSvi117747 	if (sip_copy_header(sip_msg, _dialog->sip_dlg_call_id, NULL) != 0)
8840cb5e5dSvi117747 		goto err_ret;
8940cb5e5dSvi117747 	if (cseq < 0) {
9040cb5e5dSvi117747 		if (_dialog->sip_dlg_local_cseq == 0)
9140cb5e5dSvi117747 			_dialog->sip_dlg_local_cseq = 1;
9240cb5e5dSvi117747 		oldseq = _dialog->sip_dlg_local_cseq;
9340cb5e5dSvi117747 		cseq = ++_dialog->sip_dlg_local_cseq;
9440cb5e5dSvi117747 	}
9540cb5e5dSvi117747 	if (sip_add_cseq(sip_msg, method, cseq) != 0) {
9640cb5e5dSvi117747 		_dialog->sip_dlg_local_cseq = oldseq;
9740cb5e5dSvi117747 		goto err_ret;
9840cb5e5dSvi117747 	}
9940cb5e5dSvi117747 	/*
10040cb5e5dSvi117747 	 * The route set, even if empty, overrides any pre-existing route set.
10140cb5e5dSvi117747 	 * If the route set is empty, the UAC MUST NOT add a Route header
10240cb5e5dSvi117747 	 * field to the request.
10340cb5e5dSvi117747 	 */
10440cb5e5dSvi117747 	(void) sip_delete_header_by_name(sip_msg, SIP_ROUTE);
10540cb5e5dSvi117747 
10640cb5e5dSvi117747 	if (_dialog->sip_dlg_route_set != NULL) {
10740cb5e5dSvi117747 		if (sip_copy_header(sip_msg, _dialog->sip_dlg_route_set,
10840cb5e5dSvi117747 		    NULL) != 0) {
10940cb5e5dSvi117747 			_dialog->sip_dlg_local_cseq = oldseq;
11040cb5e5dSvi117747 			goto err_ret;
11140cb5e5dSvi117747 		}
11240cb5e5dSvi117747 	}
11340cb5e5dSvi117747 	(void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
11440cb5e5dSvi117747 	return (sip_msg);
11540cb5e5dSvi117747 err_ret:
11640cb5e5dSvi117747 	(void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
11740cb5e5dSvi117747 	sip_free_msg(sip_msg);
11840cb5e5dSvi117747 	return (NULL);
11940cb5e5dSvi117747 }
12040cb5e5dSvi117747 
12140cb5e5dSvi117747 /*
122df4705eaSgm209912  * Create a request using the state maintained in the dialog. The request will
123df4705eaSgm209912  * not have Contact header.
124df4705eaSgm209912  */
125df4705eaSgm209912 sip_msg_t
126df4705eaSgm209912 sip_create_dialog_req_nocontact(sip_method_t method, sip_dialog_t dialog,
127df4705eaSgm209912     char *transport, char *sent_by, int sent_by_port, char *via_param,
128df4705eaSgm209912     uint32_t maxforward, int cseq)
129df4705eaSgm209912 {
130df4705eaSgm209912 	sip_msg_t	sip_msg;
131df4705eaSgm209912 
132df4705eaSgm209912 	sip_msg = sip_create_dialog_req(method, dialog, transport, sent_by,
133df4705eaSgm209912 	    sent_by_port, via_param, maxforward, cseq);
134df4705eaSgm209912 	if (sip_msg != NULL) {
135df4705eaSgm209912 		if (sip_delete_header_by_name(sip_msg, SIP_CONTACT) != 0) {
136df4705eaSgm209912 			sip_free_msg(sip_msg);
137df4705eaSgm209912 			return (NULL);
138df4705eaSgm209912 		}
139df4705eaSgm209912 	}
140df4705eaSgm209912 
141df4705eaSgm209912 	return (sip_msg);
142df4705eaSgm209912 }
143df4705eaSgm209912 
144df4705eaSgm209912 /*
14540cb5e5dSvi117747  * Get the Dialog method
14640cb5e5dSvi117747  */
14740cb5e5dSvi117747 int
14840cb5e5dSvi117747 sip_get_dialog_method(sip_dialog_t dialog, int *error)
14940cb5e5dSvi117747 {
15040cb5e5dSvi117747 	_sip_dialog_t	*_dialog;
15140cb5e5dSvi117747 
15240cb5e5dSvi117747 	if (error != NULL)
15340cb5e5dSvi117747 		*error = 0;
15440cb5e5dSvi117747 	if (!sip_manage_dialog) {
15540cb5e5dSvi117747 		if (error != NULL)
15640cb5e5dSvi117747 			*error = EINVAL;
15740cb5e5dSvi117747 		return (0);
15840cb5e5dSvi117747 	}
15940cb5e5dSvi117747 	if (dialog == NULL) {
16040cb5e5dSvi117747 		if (error != NULL)
16140cb5e5dSvi117747 			*error = EINVAL;
16240cb5e5dSvi117747 		return (0);
16340cb5e5dSvi117747 	}
16440cb5e5dSvi117747 	_dialog = (_sip_dialog_t *)dialog;
16540cb5e5dSvi117747 	return (_dialog->sip_dlg_method);
16640cb5e5dSvi117747 }
16740cb5e5dSvi117747 
16840cb5e5dSvi117747 /*
16940cb5e5dSvi117747  * Get the Dialog state
17040cb5e5dSvi117747  */
17140cb5e5dSvi117747 int
17240cb5e5dSvi117747 sip_get_dialog_state(sip_dialog_t dialog, int *error)
17340cb5e5dSvi117747 {
17440cb5e5dSvi117747 	_sip_dialog_t	*_dialog;
17540cb5e5dSvi117747 
17640cb5e5dSvi117747 	if (error != NULL)
17740cb5e5dSvi117747 		*error = 0;
17840cb5e5dSvi117747 	if (!sip_manage_dialog) {
17940cb5e5dSvi117747 		if (error != NULL)
18040cb5e5dSvi117747 			*error = EINVAL;
18140cb5e5dSvi117747 		return (0);
18240cb5e5dSvi117747 	}
18340cb5e5dSvi117747 	if (dialog == NULL) {
18440cb5e5dSvi117747 		if (error != NULL)
18540cb5e5dSvi117747 			*error = EINVAL;
18640cb5e5dSvi117747 		return (0);
18740cb5e5dSvi117747 	}
18840cb5e5dSvi117747 	_dialog = (_sip_dialog_t *)dialog;
18940cb5e5dSvi117747 	return (_dialog->sip_dlg_state);
19040cb5e5dSvi117747 }
19140cb5e5dSvi117747 
19240cb5e5dSvi117747 /*
19340cb5e5dSvi117747  * Return the dialog callid
19440cb5e5dSvi117747  */
19540cb5e5dSvi117747 const sip_str_t *
19640cb5e5dSvi117747 sip_get_dialog_callid(sip_dialog_t dialog, int *error)
19740cb5e5dSvi117747 {
19840cb5e5dSvi117747 	_sip_dialog_t		*_dialog;
19940cb5e5dSvi117747 	const struct sip_value	*val;
20040cb5e5dSvi117747 	const sip_str_t		*callid = NULL;
20140cb5e5dSvi117747 
20240cb5e5dSvi117747 	if (error != NULL)
20340cb5e5dSvi117747 		*error = 0;
20440cb5e5dSvi117747 	if (!sip_manage_dialog || dialog == NULL) {
20540cb5e5dSvi117747 		if (error != NULL)
20640cb5e5dSvi117747 			*error = EINVAL;
20740cb5e5dSvi117747 		return (NULL);
20840cb5e5dSvi117747 	}
20940cb5e5dSvi117747 	_dialog = (_sip_dialog_t *)dialog;
21040cb5e5dSvi117747 	(void) pthread_mutex_lock(&_dialog->sip_dlg_mutex);
21140cb5e5dSvi117747 	if (dialog->sip_dlg_call_id != NULL) {
21240cb5e5dSvi117747 		val = sip_get_header_value(_dialog->sip_dlg_call_id, error);
21340cb5e5dSvi117747 		if (val == NULL) {
21440cb5e5dSvi117747 			(void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
21540cb5e5dSvi117747 			return (NULL);
21640cb5e5dSvi117747 		}
21740cb5e5dSvi117747 		callid = &((sip_hdr_value_t *)val)->str_val;
21840cb5e5dSvi117747 	}
21940cb5e5dSvi117747 	(void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
22040cb5e5dSvi117747 	return (callid);
22140cb5e5dSvi117747 }
22240cb5e5dSvi117747 
22340cb5e5dSvi117747 /*
22440cb5e5dSvi117747  * Return the dialog localtag.
22540cb5e5dSvi117747  */
22640cb5e5dSvi117747 const sip_str_t *
22740cb5e5dSvi117747 sip_get_dialog_local_tag(sip_dialog_t dialog, int *error)
22840cb5e5dSvi117747 {
22940cb5e5dSvi117747 	_sip_dialog_t		*_dialog;
23040cb5e5dSvi117747 	const sip_str_t		*ltag = NULL;
23140cb5e5dSvi117747 	const struct sip_value	*val;
23240cb5e5dSvi117747 
23340cb5e5dSvi117747 	if (error != NULL)
23440cb5e5dSvi117747 		*error = 0;
23540cb5e5dSvi117747 	if (!sip_manage_dialog || dialog == NULL) {
23640cb5e5dSvi117747 		if (error != NULL)
23740cb5e5dSvi117747 			*error = EINVAL;
23840cb5e5dSvi117747 		return (NULL);
23940cb5e5dSvi117747 	}
24040cb5e5dSvi117747 	_dialog = (_sip_dialog_t *)dialog;
24140cb5e5dSvi117747 	(void) pthread_mutex_lock(&_dialog->sip_dlg_mutex);
24240cb5e5dSvi117747 	if (dialog->sip_dlg_local_uri_tag != NULL) {
24340cb5e5dSvi117747 		val = sip_get_header_value(_dialog->sip_dlg_local_uri_tag,
24440cb5e5dSvi117747 		    error);
24540cb5e5dSvi117747 		if (val == NULL) {
24640cb5e5dSvi117747 			(void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
24740cb5e5dSvi117747 			return (NULL);
24840cb5e5dSvi117747 		}
24940cb5e5dSvi117747 		ltag = sip_get_param_value((sip_header_value_t)val, "tag",
25040cb5e5dSvi117747 		    error);
25140cb5e5dSvi117747 	}
25240cb5e5dSvi117747 	(void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
25340cb5e5dSvi117747 	return (ltag);
25440cb5e5dSvi117747 }
25540cb5e5dSvi117747 
25640cb5e5dSvi117747 /*
25740cb5e5dSvi117747  * Return the dialog remotetag
25840cb5e5dSvi117747  */
25940cb5e5dSvi117747 const sip_str_t *
26040cb5e5dSvi117747 sip_get_dialog_remote_tag(sip_dialog_t dialog, int *error)
26140cb5e5dSvi117747 {
26240cb5e5dSvi117747 	_sip_dialog_t		*_dialog;
26340cb5e5dSvi117747 	const sip_str_t		*ttag = NULL;
26440cb5e5dSvi117747 	const struct sip_value	*val;
26540cb5e5dSvi117747 
26640cb5e5dSvi117747 	if (error != NULL)
26740cb5e5dSvi117747 		*error = 0;
26840cb5e5dSvi117747 	if (!sip_manage_dialog || dialog == NULL) {
26940cb5e5dSvi117747 		if (error != NULL)
27040cb5e5dSvi117747 			*error = EINVAL;
27140cb5e5dSvi117747 		return (NULL);
27240cb5e5dSvi117747 	}
27340cb5e5dSvi117747 	_dialog = (_sip_dialog_t *)dialog;
27440cb5e5dSvi117747 	(void) pthread_mutex_lock(&_dialog->sip_dlg_mutex);
27540cb5e5dSvi117747 	if (dialog->sip_dlg_remote_uri_tag != NULL) {
27640cb5e5dSvi117747 		val = sip_get_header_value(_dialog->sip_dlg_remote_uri_tag,
27740cb5e5dSvi117747 		    error);
27840cb5e5dSvi117747 		if (val == NULL) {
27940cb5e5dSvi117747 			(void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
28040cb5e5dSvi117747 			return (NULL);
28140cb5e5dSvi117747 		}
28240cb5e5dSvi117747 		ttag = sip_get_param_value((sip_header_value_t)val, "tag",
28340cb5e5dSvi117747 		    error);
28440cb5e5dSvi117747 	}
28540cb5e5dSvi117747 	(void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
28640cb5e5dSvi117747 
28740cb5e5dSvi117747 	return (ttag);
28840cb5e5dSvi117747 }
28940cb5e5dSvi117747 
29040cb5e5dSvi117747 /*
29140cb5e5dSvi117747  * Return the dialog localuri.
29240cb5e5dSvi117747  */
29340cb5e5dSvi117747 const struct sip_uri *
29440cb5e5dSvi117747 sip_get_dialog_local_uri(sip_dialog_t dialog, int *error)
29540cb5e5dSvi117747 {
29640cb5e5dSvi117747 	_sip_dialog_t		*_dialog;
29740cb5e5dSvi117747 	const _sip_uri_t	*luri = NULL;
29840cb5e5dSvi117747 	const struct sip_value	*val;
29940cb5e5dSvi117747 
30040cb5e5dSvi117747 	if (error != NULL)
30140cb5e5dSvi117747 		*error = 0;
30240cb5e5dSvi117747 	if (!sip_manage_dialog || dialog == NULL) {
30340cb5e5dSvi117747 		if (error != NULL)
30440cb5e5dSvi117747 			*error = EINVAL;
30540cb5e5dSvi117747 		return (NULL);
30640cb5e5dSvi117747 	}
30740cb5e5dSvi117747 	_dialog = (_sip_dialog_t *)dialog;
30840cb5e5dSvi117747 	(void) pthread_mutex_lock(&_dialog->sip_dlg_mutex);
30940cb5e5dSvi117747 	if (dialog->sip_dlg_local_uri_tag != NULL) {
31040cb5e5dSvi117747 		val = sip_get_header_value(_dialog->sip_dlg_local_uri_tag,
31140cb5e5dSvi117747 		    error);
31240cb5e5dSvi117747 		if (val == NULL) {
31340cb5e5dSvi117747 			(void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
31440cb5e5dSvi117747 			return (NULL);
31540cb5e5dSvi117747 		}
31640cb5e5dSvi117747 		luri = val->sip_value_parse_uri;
31740cb5e5dSvi117747 	}
31840cb5e5dSvi117747 	(void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
31940cb5e5dSvi117747 
32040cb5e5dSvi117747 	return ((sip_uri_t)luri);
32140cb5e5dSvi117747 }
32240cb5e5dSvi117747 
32340cb5e5dSvi117747 /*
32440cb5e5dSvi117747  * Return the dialog remoteuri.
32540cb5e5dSvi117747  */
32640cb5e5dSvi117747 const struct sip_uri *
32740cb5e5dSvi117747 sip_get_dialog_remote_uri(sip_dialog_t dialog, int *error)
32840cb5e5dSvi117747 {
32940cb5e5dSvi117747 	_sip_dialog_t		*_dialog;
33040cb5e5dSvi117747 	const _sip_uri_t	*ruri = NULL;
33140cb5e5dSvi117747 	const struct sip_value	*val;
33240cb5e5dSvi117747 
33340cb5e5dSvi117747 	if (error != NULL)
33440cb5e5dSvi117747 		*error = 0;
33540cb5e5dSvi117747 	if (!sip_manage_dialog || dialog == NULL) {
33640cb5e5dSvi117747 		if (error != NULL)
33740cb5e5dSvi117747 			*error = EINVAL;
33840cb5e5dSvi117747 		return (NULL);
33940cb5e5dSvi117747 	}
34040cb5e5dSvi117747 	_dialog = (_sip_dialog_t *)dialog;
34140cb5e5dSvi117747 	(void) pthread_mutex_lock(&_dialog->sip_dlg_mutex);
34240cb5e5dSvi117747 	if (dialog->sip_dlg_remote_uri_tag != NULL) {
34340cb5e5dSvi117747 		val = sip_get_header_value(dialog->sip_dlg_remote_uri_tag,
34440cb5e5dSvi117747 		    error);
34540cb5e5dSvi117747 		if (val == NULL) {
34640cb5e5dSvi117747 			(void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
34740cb5e5dSvi117747 			return (NULL);
34840cb5e5dSvi117747 		}
34940cb5e5dSvi117747 		ruri = val->sip_value_parse_uri;
35040cb5e5dSvi117747 	}
35140cb5e5dSvi117747 	(void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
35240cb5e5dSvi117747 	return ((sip_uri_t)ruri);
35340cb5e5dSvi117747 }
35440cb5e5dSvi117747 
35540cb5e5dSvi117747 /*
35640cb5e5dSvi117747  * Return the dialog remotetarg.
35740cb5e5dSvi117747  */
35840cb5e5dSvi117747 const struct sip_uri *
35940cb5e5dSvi117747 sip_get_dialog_remote_target_uri(sip_dialog_t dialog, int *error)
36040cb5e5dSvi117747 {
36140cb5e5dSvi117747 	_sip_dialog_t		*_dialog;
36240cb5e5dSvi117747 	const struct sip_uri	*rtarg = NULL;
36340cb5e5dSvi117747 	const struct sip_value	*val;
36440cb5e5dSvi117747 
36540cb5e5dSvi117747 	if (error != NULL)
36640cb5e5dSvi117747 		*error = 0;
36740cb5e5dSvi117747 	if (!sip_manage_dialog || dialog == NULL) {
36840cb5e5dSvi117747 		if (error != NULL)
36940cb5e5dSvi117747 			*error = EINVAL;
37040cb5e5dSvi117747 		return (NULL);
37140cb5e5dSvi117747 	}
37240cb5e5dSvi117747 	_dialog = (_sip_dialog_t *)dialog;
37340cb5e5dSvi117747 	(void) pthread_mutex_lock(&_dialog->sip_dlg_mutex);
37440cb5e5dSvi117747 	if (dialog->sip_dlg_remote_target != NULL) {
37540cb5e5dSvi117747 		val = sip_get_header_value(_dialog->sip_dlg_remote_target,
37640cb5e5dSvi117747 		    error);
37740cb5e5dSvi117747 		if (val == NULL) {
37840cb5e5dSvi117747 			(void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
37940cb5e5dSvi117747 			return (NULL);
38040cb5e5dSvi117747 		}
38140cb5e5dSvi117747 		rtarg = val->sip_value_parse_uri;
38240cb5e5dSvi117747 	}
38340cb5e5dSvi117747 	(void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
38440cb5e5dSvi117747 
38540cb5e5dSvi117747 	return ((sip_uri_t)rtarg);
38640cb5e5dSvi117747 }
38740cb5e5dSvi117747 
38840cb5e5dSvi117747 /*
389df4705eaSgm209912  * Return the dialog local contact uri.
390df4705eaSgm209912  */
391df4705eaSgm209912 const struct sip_uri *
392df4705eaSgm209912 sip_get_dialog_local_contact_uri(sip_dialog_t dialog, int *error)
393df4705eaSgm209912 {
394df4705eaSgm209912 	_sip_dialog_t		*_dialog;
395df4705eaSgm209912 	const struct sip_uri	*lcuri = NULL;
396df4705eaSgm209912 	const struct sip_value	*val;
397df4705eaSgm209912 
398df4705eaSgm209912 	if (error != NULL)
399df4705eaSgm209912 		*error = 0;
400df4705eaSgm209912 	if (!sip_manage_dialog || dialog == NULL) {
401df4705eaSgm209912 		if (error != NULL)
402df4705eaSgm209912 			*error = EINVAL;
403df4705eaSgm209912 		return (NULL);
404df4705eaSgm209912 	}
405df4705eaSgm209912 	_dialog = (_sip_dialog_t *)dialog;
406df4705eaSgm209912 	(void) pthread_mutex_lock(&_dialog->sip_dlg_mutex);
407df4705eaSgm209912 	if (dialog->sip_dlg_local_contact != NULL) {
408df4705eaSgm209912 		val = sip_get_header_value(_dialog->sip_dlg_local_contact,
409df4705eaSgm209912 		    error);
410df4705eaSgm209912 		if (val == NULL) {
411df4705eaSgm209912 			(void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
412df4705eaSgm209912 			return (NULL);
413df4705eaSgm209912 		}
414df4705eaSgm209912 		lcuri = val->sip_value_parse_uri;
415df4705eaSgm209912 	}
416df4705eaSgm209912 	(void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
417df4705eaSgm209912 
418df4705eaSgm209912 	return ((sip_uri_t)lcuri);
419df4705eaSgm209912 }
420df4705eaSgm209912 
421df4705eaSgm209912 /*
42240cb5e5dSvi117747  * Return the dialog route set
42340cb5e5dSvi117747  */
42440cb5e5dSvi117747 const sip_str_t *
42540cb5e5dSvi117747 sip_get_dialog_route_set(sip_dialog_t dialog, int *error)
42640cb5e5dSvi117747 {
42740cb5e5dSvi117747 	_sip_dialog_t		*_dialog;
42840cb5e5dSvi117747 
42940cb5e5dSvi117747 	if (error != NULL)
43040cb5e5dSvi117747 		*error = 0;
43140cb5e5dSvi117747 	if (!sip_manage_dialog || dialog == NULL) {
43240cb5e5dSvi117747 		if (error != NULL)
43340cb5e5dSvi117747 			*error = EINVAL;
43440cb5e5dSvi117747 		return (NULL);
43540cb5e5dSvi117747 	}
43640cb5e5dSvi117747 	_dialog = (_sip_dialog_t *)dialog;
43740cb5e5dSvi117747 	if (_dialog->sip_dlg_rset.sip_str_len > 0)
43840cb5e5dSvi117747 		return (&_dialog->sip_dlg_rset);
43940cb5e5dSvi117747 	return (NULL);
44040cb5e5dSvi117747 }
44140cb5e5dSvi117747 
44240cb5e5dSvi117747 /*
44340cb5e5dSvi117747  * Return the dialog secure
44440cb5e5dSvi117747  */
44540cb5e5dSvi117747 boolean_t
44640cb5e5dSvi117747 sip_is_dialog_secure(sip_dialog_t dialog, int *error)
44740cb5e5dSvi117747 {
44840cb5e5dSvi117747 	_sip_dialog_t	*_dialog;
44940cb5e5dSvi117747 	boolean_t	issecure;
45040cb5e5dSvi117747 
45140cb5e5dSvi117747 	if (error != NULL)
45240cb5e5dSvi117747 		*error = 0;
45340cb5e5dSvi117747 	if (!sip_manage_dialog || dialog == NULL) {
45440cb5e5dSvi117747 		if (error != NULL)
45540cb5e5dSvi117747 			*error = EINVAL;
45640cb5e5dSvi117747 		return (B_FALSE);
45740cb5e5dSvi117747 	}
45840cb5e5dSvi117747 	_dialog = (_sip_dialog_t *)dialog;
45940cb5e5dSvi117747 	(void) pthread_mutex_lock(&_dialog->sip_dlg_mutex);
46040cb5e5dSvi117747 	issecure = _dialog->sip_dlg_secure;
46140cb5e5dSvi117747 	(void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
46240cb5e5dSvi117747 	return (issecure);
46340cb5e5dSvi117747 }
46440cb5e5dSvi117747 
46540cb5e5dSvi117747 /*
46640cb5e5dSvi117747  * Return the dialog local cseq
46740cb5e5dSvi117747  */
46840cb5e5dSvi117747 uint32_t
46940cb5e5dSvi117747 sip_get_dialog_local_cseq(sip_dialog_t dialog, int *error)
47040cb5e5dSvi117747 {
47140cb5e5dSvi117747 	_sip_dialog_t	*_dialog;
47240cb5e5dSvi117747 	uint32_t	cseq;
47340cb5e5dSvi117747 
47440cb5e5dSvi117747 	if (error != NULL)
47540cb5e5dSvi117747 		*error = 0;
47640cb5e5dSvi117747 	if (!sip_manage_dialog || dialog == NULL) {
47740cb5e5dSvi117747 		if (error != NULL)
47840cb5e5dSvi117747 			*error = EINVAL;
47940cb5e5dSvi117747 		return (0);
48040cb5e5dSvi117747 	}
48140cb5e5dSvi117747 	_dialog = (_sip_dialog_t *)dialog;
48240cb5e5dSvi117747 	(void) pthread_mutex_lock(&_dialog->sip_dlg_mutex);
48340cb5e5dSvi117747 	cseq = _dialog->sip_dlg_local_cseq;
48440cb5e5dSvi117747 	(void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
48540cb5e5dSvi117747 	return (cseq);
48640cb5e5dSvi117747 }
48740cb5e5dSvi117747 
48840cb5e5dSvi117747 /*
48940cb5e5dSvi117747  * Return the dialog remote cseq
49040cb5e5dSvi117747  */
49140cb5e5dSvi117747 uint32_t
49240cb5e5dSvi117747 sip_get_dialog_remote_cseq(sip_dialog_t dialog, int *error)
49340cb5e5dSvi117747 {
49440cb5e5dSvi117747 	_sip_dialog_t	*_dialog;
49540cb5e5dSvi117747 	uint32_t	cseq;
49640cb5e5dSvi117747 
49740cb5e5dSvi117747 	if (error != NULL)
49840cb5e5dSvi117747 		*error = 0;
49940cb5e5dSvi117747 	if (!sip_manage_dialog || dialog == NULL) {
50040cb5e5dSvi117747 		if (error != NULL)
50140cb5e5dSvi117747 			*error = EINVAL;
50240cb5e5dSvi117747 		return (0);
50340cb5e5dSvi117747 	}
50440cb5e5dSvi117747 	_dialog = (_sip_dialog_t *)dialog;
50540cb5e5dSvi117747 	(void) pthread_mutex_lock(&_dialog->sip_dlg_mutex);
50640cb5e5dSvi117747 	cseq = _dialog->sip_dlg_remote_cseq;
50740cb5e5dSvi117747 	(void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
50840cb5e5dSvi117747 	return (cseq);
50940cb5e5dSvi117747 }
51040cb5e5dSvi117747 
51140cb5e5dSvi117747 /*
51240cb5e5dSvi117747  * Return the dialog type
51340cb5e5dSvi117747  */
51440cb5e5dSvi117747 int
51540cb5e5dSvi117747 sip_get_dialog_type(sip_dialog_t dialog, int *error)
51640cb5e5dSvi117747 {
51740cb5e5dSvi117747 	_sip_dialog_t	*_dialog;
51840cb5e5dSvi117747 	int		type;
51940cb5e5dSvi117747 
52040cb5e5dSvi117747 	if (error != NULL)
52140cb5e5dSvi117747 		*error = 0;
52240cb5e5dSvi117747 	if (!sip_manage_dialog || dialog == NULL) {
52340cb5e5dSvi117747 		if (error != NULL)
52440cb5e5dSvi117747 			*error = EINVAL;
52540cb5e5dSvi117747 		return (-1);
52640cb5e5dSvi117747 	}
52740cb5e5dSvi117747 	_dialog = (_sip_dialog_t *)dialog;
52840cb5e5dSvi117747 	(void) pthread_mutex_lock(&_dialog->sip_dlg_mutex);
52940cb5e5dSvi117747 	type = _dialog->sip_dlg_type;
53040cb5e5dSvi117747 	(void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
53140cb5e5dSvi117747 	return (type);
53240cb5e5dSvi117747 }
53340cb5e5dSvi117747 
534*943efbc3Sgm209912 /*
535*943efbc3Sgm209912  * Return the number of messages exchanged within a dialog.
536*943efbc3Sgm209912  */
537*943efbc3Sgm209912 int
538*943efbc3Sgm209912 sip_get_dialog_msgcnt(sip_dialog_t dialog, int *error)
539*943efbc3Sgm209912 {
540*943efbc3Sgm209912 	_sip_dialog_t	*_dialog;
541*943efbc3Sgm209912 	int		nmsgs;
542*943efbc3Sgm209912 
543*943efbc3Sgm209912 	if (error != NULL)
544*943efbc3Sgm209912 		*error = 0;
545*943efbc3Sgm209912 	if (!sip_manage_dialog || dialog == NULL) {
546*943efbc3Sgm209912 		if (error != NULL)
547*943efbc3Sgm209912 			*error = EINVAL;
548*943efbc3Sgm209912 		return (-1);
549*943efbc3Sgm209912 	}
550*943efbc3Sgm209912 	_dialog = (_sip_dialog_t *)dialog;
551*943efbc3Sgm209912 	(void) pthread_mutex_lock(&_dialog->sip_dlg_mutex);
552*943efbc3Sgm209912 	nmsgs = _dialog->sip_dlg_msgcnt;
553*943efbc3Sgm209912 	(void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
554*943efbc3Sgm209912 	return (nmsgs);
555*943efbc3Sgm209912 }
55640cb5e5dSvi117747 
55740cb5e5dSvi117747 /*
55840cb5e5dSvi117747  * Partial dialog ?
55940cb5e5dSvi117747  */
56040cb5e5dSvi117747 boolean_t
56140cb5e5dSvi117747 sip_incomplete_dialog(sip_dialog_t dialog)
56240cb5e5dSvi117747 {
56340cb5e5dSvi117747 	_sip_dialog_t	*_dialog;
56440cb5e5dSvi117747 	boolean_t	isnew;
56540cb5e5dSvi117747 
56640cb5e5dSvi117747 	if (!sip_manage_dialog || dialog == NULL)
56740cb5e5dSvi117747 		return (B_FALSE);
56840cb5e5dSvi117747 	_dialog = (_sip_dialog_t *)dialog;
56940cb5e5dSvi117747 	(void) pthread_mutex_lock(&_dialog->sip_dlg_mutex);
57040cb5e5dSvi117747 	isnew = _dialog->sip_dlg_state == SIP_DLG_NEW;
57140cb5e5dSvi117747 	(void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
57240cb5e5dSvi117747 	return (isnew);
57340cb5e5dSvi117747 }
57440cb5e5dSvi117747 
57540cb5e5dSvi117747 /*
57640cb5e5dSvi117747  * Hold dialog
57740cb5e5dSvi117747  */
57840cb5e5dSvi117747 void
57940cb5e5dSvi117747 sip_hold_dialog(sip_dialog_t dialog)
58040cb5e5dSvi117747 {
58140cb5e5dSvi117747 	_sip_dialog_t	*_dialog;
58240cb5e5dSvi117747 
58340cb5e5dSvi117747 	if (!sip_manage_dialog || dialog == NULL)
58440cb5e5dSvi117747 		return;
58540cb5e5dSvi117747 	_dialog = (_sip_dialog_t *)dialog;
58640cb5e5dSvi117747 	(void) pthread_mutex_lock(&_dialog->sip_dlg_mutex);
58740cb5e5dSvi117747 	SIP_DLG_REFCNT_INCR(_dialog);
58840cb5e5dSvi117747 	(void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
58940cb5e5dSvi117747 }
59040cb5e5dSvi117747 
59140cb5e5dSvi117747 /*
59240cb5e5dSvi117747  * Release dialog
59340cb5e5dSvi117747  */
59440cb5e5dSvi117747 void
59540cb5e5dSvi117747 sip_release_dialog(sip_dialog_t dialog)
59640cb5e5dSvi117747 {
59740cb5e5dSvi117747 	_sip_dialog_t	*_dialog;
59840cb5e5dSvi117747 
59940cb5e5dSvi117747 	if (!sip_manage_dialog || dialog == NULL)
60040cb5e5dSvi117747 		return;
60140cb5e5dSvi117747 	_dialog = (_sip_dialog_t *)dialog;
60240cb5e5dSvi117747 	SIP_DLG_REFCNT_DECR(_dialog);
60340cb5e5dSvi117747 }
60440cb5e5dSvi117747 
60540cb5e5dSvi117747 /*
60640cb5e5dSvi117747  * Delete a dialog
60740cb5e5dSvi117747  */
60840cb5e5dSvi117747 void
60940cb5e5dSvi117747 sip_delete_dialog(sip_dialog_t dialog)
61040cb5e5dSvi117747 {
61140cb5e5dSvi117747 	if (!sip_manage_dialog || dialog == NULL)
61240cb5e5dSvi117747 		return;
61340cb5e5dSvi117747 	sip_dialog_terminate(dialog, NULL);
61440cb5e5dSvi117747 }
615