xref: /illumos-gate/usr/src/lib/libsip/common/sip_ui.c (revision 1da57d55)
140cb5e5dSvi /*
240cb5e5dSvi  * CDDL HEADER START
340cb5e5dSvi  *
440cb5e5dSvi  * The contents of this file are subject to the terms of the
540cb5e5dSvi  * Common Development and Distribution License (the "License").
640cb5e5dSvi  * You may not use this file except in compliance with the License.
740cb5e5dSvi  *
840cb5e5dSvi  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
940cb5e5dSvi  * or http://www.opensolaris.org/os/licensing.
1040cb5e5dSvi  * See the License for the specific language governing permissions
1140cb5e5dSvi  * and limitations under the License.
1240cb5e5dSvi  *
1340cb5e5dSvi  * When distributing Covered Code, include this CDDL HEADER in each
1440cb5e5dSvi  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1540cb5e5dSvi  * If applicable, add the following below this CDDL HEADER, with the
1640cb5e5dSvi  * fields enclosed by brackets "[]" replaced with your own identifying
1740cb5e5dSvi  * information: Portions Copyright [yyyy] [name of copyright owner]
1840cb5e5dSvi  *
1940cb5e5dSvi  * CDDL HEADER END
2040cb5e5dSvi  */
2140cb5e5dSvi 
2240cb5e5dSvi /*
23*2c2c4183Svi  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
2440cb5e5dSvi  * Use is subject to license terms.
2540cb5e5dSvi  */
2640cb5e5dSvi 
27*2c2c4183Svi #include <stdio.h>
28*2c2c4183Svi #include <stdlib.h>
29*2c2c4183Svi #include <assert.h>
30*2c2c4183Svi #include <ctype.h>
31*2c2c4183Svi #include <errno.h>
32*2c2c4183Svi #include <strings.h>
33*2c2c4183Svi #include <pthread.h>
34*2c2c4183Svi #include <sip.h>
35*2c2c4183Svi 
3640cb5e5dSvi #include "sip_msg.h"
3740cb5e5dSvi #include "sip_miscdefs.h"
38*2c2c4183Svi #include "sip_parse_uri.h"
3940cb5e5dSvi #include "sip_xaction.h"
4040cb5e5dSvi 
4140cb5e5dSvi #define	SIP_BUF_SIZE	128
4240cb5e5dSvi 
4340cb5e5dSvi /*
4440cb5e5dSvi  * Find the header named header, consecutive calls with old_header
4540cb5e5dSvi  * passed in will return next header of the same type.
4640cb5e5dSvi  * If no name is passed the first header is returned. consectutive calls
4740cb5e5dSvi  * with no name but an old header will return the next header.
4840cb5e5dSvi  */
4940cb5e5dSvi const struct sip_header *
sip_get_header(sip_msg_t sip_msg,char * header_name,sip_header_t old_header,int * error)5040cb5e5dSvi sip_get_header(sip_msg_t sip_msg, char *header_name, sip_header_t old_header,
5140cb5e5dSvi     int *error)
5240cb5e5dSvi {
5340cb5e5dSvi 	_sip_msg_t		*_sip_msg;
5440cb5e5dSvi 	const struct sip_header	*sip_hdr;
5540cb5e5dSvi 
5640cb5e5dSvi 	if (error != NULL)
5740cb5e5dSvi 		*error = 0;
5840cb5e5dSvi 	if (sip_msg == NULL) {
5940cb5e5dSvi 		if (error != NULL)
6040cb5e5dSvi 			*error = EINVAL;
6140cb5e5dSvi 		return (NULL);
6240cb5e5dSvi 	}
6340cb5e5dSvi 	_sip_msg = (_sip_msg_t *)sip_msg;
6440cb5e5dSvi 	(void) pthread_mutex_lock(&_sip_msg->sip_msg_mutex);
6540cb5e5dSvi 	sip_hdr = (sip_header_t)sip_search_for_header((_sip_msg_t *)sip_msg,
6640cb5e5dSvi 	    header_name, (_sip_header_t *)old_header);
6740cb5e5dSvi 	(void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
6840cb5e5dSvi 	if (sip_hdr == NULL && error != NULL)
6940cb5e5dSvi 		*error = EINVAL;
7040cb5e5dSvi 	return (sip_hdr);
7140cb5e5dSvi }
7240cb5e5dSvi 
7340cb5e5dSvi /*
7440cb5e5dSvi  * Return the request line as a string. Caller releases the returned string.
7540cb5e5dSvi  */
7640cb5e5dSvi char *
sip_reqline_to_str(sip_msg_t sip_msg,int * error)7740cb5e5dSvi sip_reqline_to_str(sip_msg_t sip_msg, int *error)
7840cb5e5dSvi {
7940cb5e5dSvi 	char	*reqstr;
8040cb5e5dSvi 
8140cb5e5dSvi 	if (error != NULL)
8240cb5e5dSvi 		*error = 0;
8340cb5e5dSvi 	if (sip_msg == NULL || !sip_msg_is_request(sip_msg, error)) {
8440cb5e5dSvi 		if (error != NULL)
8540cb5e5dSvi 			*error = EINVAL;
8640cb5e5dSvi 		return (NULL);
8740cb5e5dSvi 	}
8840cb5e5dSvi 	reqstr = _sip_startline_to_str((_sip_msg_t *)sip_msg, error);
8940cb5e5dSvi 	return (reqstr);
9040cb5e5dSvi }
9140cb5e5dSvi 
9240cb5e5dSvi /*
9340cb5e5dSvi  * Return the response line as a string. Caller releases the returned string.
9440cb5e5dSvi  */
9540cb5e5dSvi char *
sip_respline_to_str(sip_msg_t sip_msg,int * error)9640cb5e5dSvi sip_respline_to_str(sip_msg_t sip_msg, int *error)
9740cb5e5dSvi {
9840cb5e5dSvi 	char	*respstr;
9940cb5e5dSvi 
10040cb5e5dSvi 	if (error != NULL)
10140cb5e5dSvi 		*error = 0;
10240cb5e5dSvi 	if (sip_msg == NULL || sip_msg_is_request(sip_msg, error)) {
10340cb5e5dSvi 		if (error != NULL)
10440cb5e5dSvi 			*error = EINVAL;
10540cb5e5dSvi 		return (NULL);
10640cb5e5dSvi 	}
10740cb5e5dSvi 	respstr = _sip_startline_to_str((_sip_msg_t *)sip_msg, error);
10840cb5e5dSvi 	return (respstr);
10940cb5e5dSvi }
11040cb5e5dSvi 
11140cb5e5dSvi /*
11240cb5e5dSvi  * return the first value of the header
11340cb5e5dSvi  */
11440cb5e5dSvi const struct sip_value *
sip_get_header_value(const struct sip_header * sip_header,int * error)11540cb5e5dSvi sip_get_header_value(const struct sip_header *sip_header, int *error)
11640cb5e5dSvi {
11740cb5e5dSvi 	_sip_header_t		*_sip_header;
11840cb5e5dSvi 	sip_parsed_header_t	*sip_parsed_header;
11940cb5e5dSvi 	int			ret = 0;
12040cb5e5dSvi 	const struct sip_value	*value;
12140cb5e5dSvi 
12240cb5e5dSvi 	if (error != NULL)
12340cb5e5dSvi 		*error = 0;
12440cb5e5dSvi 	if (sip_header == NULL) {
12540cb5e5dSvi 		if (error != NULL)
12640cb5e5dSvi 			*error = EINVAL;
12740cb5e5dSvi 		return (NULL);
12840cb5e5dSvi 	}
12940cb5e5dSvi 	_sip_header = (_sip_header_t *)sip_header;
13040cb5e5dSvi 	if (_sip_header->sip_hdr_sipmsg != NULL) {
13140cb5e5dSvi 		(void) pthread_mutex_lock(
13240cb5e5dSvi 		    &_sip_header->sip_hdr_sipmsg->sip_msg_mutex);
13340cb5e5dSvi 	}
13440cb5e5dSvi 	if (_sip_header->sip_header_state == SIP_HEADER_DELETED) {
13540cb5e5dSvi 		if (_sip_header->sip_hdr_sipmsg != NULL) {
13640cb5e5dSvi 			(void) pthread_mutex_unlock(
13740cb5e5dSvi 			    &_sip_header->sip_hdr_sipmsg->sip_msg_mutex);
13840cb5e5dSvi 		}
13940cb5e5dSvi 		if (error != NULL)
14040cb5e5dSvi 			*error = EINVAL;
14140cb5e5dSvi 		return (NULL);
14240cb5e5dSvi 	}
14340cb5e5dSvi 	ret = _sip_header->sip_header_functions->header_parse_func(
14440cb5e5dSvi 	    _sip_header, &sip_parsed_header);
14540cb5e5dSvi 	if (_sip_header->sip_hdr_sipmsg != NULL) {
14640cb5e5dSvi 		(void) pthread_mutex_unlock
14740cb5e5dSvi 		    (&_sip_header->sip_hdr_sipmsg->sip_msg_mutex);
14840cb5e5dSvi 	}
14940cb5e5dSvi 	if (error != NULL)
15040cb5e5dSvi 		*error = ret;
15140cb5e5dSvi 
15240cb5e5dSvi 	if (ret != 0)
15340cb5e5dSvi 		return (NULL);
15440cb5e5dSvi 	value = (sip_header_value_t)sip_parsed_header->value;
15540cb5e5dSvi 	while (value != NULL && value->value_state == SIP_VALUE_DELETED)
15640cb5e5dSvi 		value = value->next;
15740cb5e5dSvi 	if (value != NULL && value->value_state == SIP_VALUE_BAD &&
15840cb5e5dSvi 	    error != NULL) {
15940cb5e5dSvi 		*error = EPROTO;
16040cb5e5dSvi 	}
16140cb5e5dSvi 	return ((sip_header_value_t)value);
16240cb5e5dSvi }
16340cb5e5dSvi 
16440cb5e5dSvi /*
16540cb5e5dSvi  * Return the next value of the header.
16640cb5e5dSvi  */
16740cb5e5dSvi const struct sip_value *
sip_get_next_value(sip_header_value_t old_value,int * error)16840cb5e5dSvi sip_get_next_value(sip_header_value_t old_value, int *error)
16940cb5e5dSvi {
17040cb5e5dSvi 	const struct sip_value *value;
17140cb5e5dSvi 
17240cb5e5dSvi 	if (error != NULL)
17340cb5e5dSvi 		*error = 0;
17440cb5e5dSvi 	if (old_value == NULL || old_value->next == NULL) {
17540cb5e5dSvi 		if (error != NULL)
17640cb5e5dSvi 			*error = EINVAL;
17740cb5e5dSvi 		return (NULL);
17840cb5e5dSvi 	}
17940cb5e5dSvi 	/*
18040cb5e5dSvi 	 * We never free the deleted values so no need to hold a lock.
18140cb5e5dSvi 	 */
18240cb5e5dSvi 	value = (sip_header_value_t)old_value->next;
18340cb5e5dSvi 	while (value != NULL && value->value_state == SIP_VALUE_DELETED)
18440cb5e5dSvi 		value = value->next;
18540cb5e5dSvi 	if (value != NULL && value->value_state == SIP_VALUE_BAD &&
18640cb5e5dSvi 	    error != NULL) {
18740cb5e5dSvi 		*error = EPROTO;
18840cb5e5dSvi 	}
18940cb5e5dSvi 	return ((sip_header_value_t)value);
19040cb5e5dSvi }
19140cb5e5dSvi 
19240cb5e5dSvi /*
19340cb5e5dSvi  * Given a SIP message, delete the header "header_name".
19440cb5e5dSvi  */
19540cb5e5dSvi int
sip_delete_header_by_name(sip_msg_t msg,char * header_name)19640cb5e5dSvi sip_delete_header_by_name(sip_msg_t msg, char *header_name)
19740cb5e5dSvi {
19840cb5e5dSvi 	_sip_msg_t	*_msg = (_sip_msg_t *)msg;
19940cb5e5dSvi 	sip_header_t	sip_hdr;
20040cb5e5dSvi 	_sip_header_t	*_sip_hdr;
20140cb5e5dSvi 
20240cb5e5dSvi 	if (_msg == NULL || header_name == NULL)
20340cb5e5dSvi 		return (EINVAL);
20440cb5e5dSvi 	(void) pthread_mutex_lock(&_msg->sip_msg_mutex);
20540cb5e5dSvi 	if (_msg->sip_msg_cannot_be_modified) {
20640cb5e5dSvi 		(void) pthread_mutex_unlock(&_msg->sip_msg_mutex);
20740cb5e5dSvi 		return (EPERM);
20840cb5e5dSvi 	}
20940cb5e5dSvi 	sip_hdr = (sip_header_t)sip_search_for_header(_msg, header_name, NULL);
21040cb5e5dSvi 	if (sip_hdr == NULL) {
21140cb5e5dSvi 		(void) pthread_mutex_unlock(&_msg->sip_msg_mutex);
21240cb5e5dSvi 		return (EINVAL);
21340cb5e5dSvi 	}
21440cb5e5dSvi 	_sip_hdr = (_sip_header_t *)sip_hdr;
21540cb5e5dSvi 	_sip_hdr->sip_header_state = SIP_HEADER_DELETED;
21640cb5e5dSvi 	_sip_hdr->sip_hdr_sipmsg->sip_msg_len -= _sip_hdr->sip_hdr_end -
21740cb5e5dSvi 	    _sip_hdr->sip_hdr_start;
21840cb5e5dSvi 	assert(_sip_hdr->sip_hdr_sipmsg->sip_msg_len >= 0);
21940cb5e5dSvi 	if (_msg->sip_msg_buf != NULL)
22040cb5e5dSvi 		_msg->sip_msg_modified = B_TRUE;
22140cb5e5dSvi 	(void) pthread_mutex_unlock(&_msg->sip_msg_mutex);
22240cb5e5dSvi 
22340cb5e5dSvi 	return (0);
22440cb5e5dSvi }
22540cb5e5dSvi 
22640cb5e5dSvi /*
22740cb5e5dSvi  * Mark the header as deleted.
22840cb5e5dSvi  */
22940cb5e5dSvi int
sip_delete_header(sip_header_t sip_header)23040cb5e5dSvi sip_delete_header(sip_header_t sip_header)
23140cb5e5dSvi {
23240cb5e5dSvi 	_sip_header_t	*_sip_header;
23340cb5e5dSvi 
23440cb5e5dSvi 	if (sip_header == NULL)
23540cb5e5dSvi 		return (EINVAL);
23640cb5e5dSvi 	_sip_header = (_sip_header_t *)sip_header;
23740cb5e5dSvi 	(void) pthread_mutex_lock(&_sip_header->sip_hdr_sipmsg->sip_msg_mutex);
23840cb5e5dSvi 	if (_sip_header->sip_hdr_sipmsg->sip_msg_cannot_be_modified) {
23940cb5e5dSvi 		(void) pthread_mutex_unlock
24040cb5e5dSvi 		    (&_sip_header->sip_hdr_sipmsg->sip_msg_mutex);
24140cb5e5dSvi 		return (EPERM);
24240cb5e5dSvi 	}
24340cb5e5dSvi 	if (_sip_header->sip_header_state == SIP_HEADER_DELETED) {
24440cb5e5dSvi 		(void) pthread_mutex_unlock(
24540cb5e5dSvi 		    &_sip_header->sip_hdr_sipmsg->sip_msg_mutex);
24640cb5e5dSvi 		return (EINVAL);
24740cb5e5dSvi 	}
24840cb5e5dSvi 	_sip_header->sip_header_state = SIP_HEADER_DELETED;
24940cb5e5dSvi 	_sip_header->sip_hdr_sipmsg->sip_msg_len -= _sip_header->sip_hdr_end -
25040cb5e5dSvi 	    _sip_header->sip_hdr_start;
25140cb5e5dSvi 	assert(_sip_header->sip_hdr_sipmsg->sip_msg_len >= 0);
25240cb5e5dSvi 	if (_sip_header->sip_hdr_sipmsg->sip_msg_buf != NULL)
25340cb5e5dSvi 		_sip_header->sip_hdr_sipmsg->sip_msg_modified = B_TRUE;
25440cb5e5dSvi 	(void) pthread_mutex_unlock
25540cb5e5dSvi 	    (&_sip_header->sip_hdr_sipmsg->sip_msg_mutex);
25640cb5e5dSvi 	return (0);
25740cb5e5dSvi }
25840cb5e5dSvi 
25940cb5e5dSvi /*
26040cb5e5dSvi  * Mark the value as deleted.
26140cb5e5dSvi  */
26240cb5e5dSvi int
sip_delete_value(sip_header_t sip_header,sip_header_value_t sip_header_value)26340cb5e5dSvi sip_delete_value(sip_header_t sip_header, sip_header_value_t sip_header_value)
26440cb5e5dSvi {
26540cb5e5dSvi 	_sip_header_t	*_sip_header;
26640cb5e5dSvi 	sip_value_t	*_sip_header_value;
26740cb5e5dSvi 	int		vlen;
26840cb5e5dSvi 	char		*c;
26940cb5e5dSvi 
27040cb5e5dSvi 	if (sip_header == NULL || sip_header_value == NULL)
27140cb5e5dSvi 		return (EINVAL);
27240cb5e5dSvi 	_sip_header = (_sip_header_t *)sip_header;
27340cb5e5dSvi 	(void) pthread_mutex_lock(&_sip_header->sip_hdr_sipmsg->sip_msg_mutex);
27440cb5e5dSvi 	if (_sip_header->sip_hdr_sipmsg->sip_msg_cannot_be_modified) {
27540cb5e5dSvi 		(void) pthread_mutex_unlock(&_sip_header->
27640cb5e5dSvi 		    sip_hdr_sipmsg->sip_msg_mutex);
27740cb5e5dSvi 		return (EPERM);
27840cb5e5dSvi 	}
27940cb5e5dSvi 	if (_sip_header->sip_header_state == SIP_HEADER_DELETED) {
28040cb5e5dSvi 		(void) pthread_mutex_unlock(
28140cb5e5dSvi 		    &_sip_header->sip_hdr_sipmsg->sip_msg_mutex);
28240cb5e5dSvi 		return (EINVAL);
28340cb5e5dSvi 	}
28440cb5e5dSvi 	_sip_header_value = (sip_value_t *)sip_header_value;
28540cb5e5dSvi 	if (_sip_header_value->value_state == SIP_VALUE_DELETED) {
28640cb5e5dSvi 		(void) pthread_mutex_unlock(
28740cb5e5dSvi 		    &_sip_header->sip_hdr_sipmsg->sip_msg_mutex);
28840cb5e5dSvi 		return (EINVAL);
28940cb5e5dSvi 	}
29040cb5e5dSvi 	_sip_header->sip_header_state = SIP_HEADER_DELETED_VAL;
29140cb5e5dSvi 	_sip_header_value->value_state = SIP_VALUE_DELETED;
29240cb5e5dSvi 	vlen = _sip_header_value->value_end - _sip_header_value->value_start;
29340cb5e5dSvi 	if (_sip_header->sip_hdr_parsed->value == _sip_header_value) {
29440cb5e5dSvi 		c = _sip_header_value->value_start;
29540cb5e5dSvi 		while (*c-- != SIP_HCOLON)
29640cb5e5dSvi 			vlen++;
29740cb5e5dSvi 	} else {
29840cb5e5dSvi 		c = _sip_header_value->value_start;
29940cb5e5dSvi 		while (*c-- != SIP_COMMA)
30040cb5e5dSvi 			vlen++;
30140cb5e5dSvi 	}
30240cb5e5dSvi 	if (_sip_header_value->next == NULL) {
30340cb5e5dSvi 		sip_value_t	*value = _sip_header->sip_hdr_parsed->value;
30440cb5e5dSvi 		boolean_t	crlf_present =  B_FALSE;
30540cb5e5dSvi 		char		*s;
30640cb5e5dSvi 
30740cb5e5dSvi 		while (value != NULL && value != _sip_header_value) {
30840cb5e5dSvi 			crlf_present = B_FALSE;
30940cb5e5dSvi 
31040cb5e5dSvi 			if (value->value_state == SIP_VALUE_DELETED) {
31140cb5e5dSvi 				value = value->next;
31240cb5e5dSvi 				continue;
31340cb5e5dSvi 			}
31440cb5e5dSvi 			s = value->value_end;
31540cb5e5dSvi 			while (s != value->value_start) {
31640cb5e5dSvi 				if (*s == '\r' && strncmp(s, SIP_CRLF,
31740cb5e5dSvi 				    strlen(SIP_CRLF)) == 0) {
31840cb5e5dSvi 					crlf_present = B_TRUE;
31940cb5e5dSvi 					break;
32040cb5e5dSvi 				}
32140cb5e5dSvi 				s--;
32240cb5e5dSvi 			}
32340cb5e5dSvi 			value = value->next;
32440cb5e5dSvi 		}
32540cb5e5dSvi 		if (!crlf_present) {
32640cb5e5dSvi 			c = _sip_header_value->value_end;
32740cb5e5dSvi 			while (*c-- != '\r')
32840cb5e5dSvi 				vlen--;
32940cb5e5dSvi 			assert(vlen > 0);
33040cb5e5dSvi 		}
33140cb5e5dSvi 	}
33240cb5e5dSvi 	_sip_header->sip_hdr_sipmsg->sip_msg_len -= vlen;
33340cb5e5dSvi 	if (_sip_header->sip_hdr_sipmsg->sip_msg_buf != NULL)
33440cb5e5dSvi 		_sip_header->sip_hdr_sipmsg->sip_msg_modified = B_TRUE;
33540cb5e5dSvi 	(void) pthread_mutex_unlock
33640cb5e5dSvi 	    (&_sip_header->sip_hdr_sipmsg->sip_msg_mutex);
33740cb5e5dSvi 	return (0);
33840cb5e5dSvi }
33940cb5e5dSvi 
34040cb5e5dSvi /*
34140cb5e5dSvi  * Given a param list, check if a param name exists.
34240cb5e5dSvi  */
34340cb5e5dSvi boolean_t
sip_is_param_present(const sip_param_t * param_list,char * param_name,int param_len)34440cb5e5dSvi sip_is_param_present(const sip_param_t *param_list, char *param_name,
34540cb5e5dSvi     int param_len)
34640cb5e5dSvi {
34740cb5e5dSvi 	const sip_param_t	*param = param_list;
34840cb5e5dSvi 
34940cb5e5dSvi 	while (param != NULL) {
35040cb5e5dSvi 		if (param->param_name.sip_str_len == param_len &&
35140cb5e5dSvi 		    strncasecmp(param->param_name.sip_str_ptr, param_name,
35240cb5e5dSvi 			param_len) == 0) {
35340cb5e5dSvi 			return (B_TRUE);
35440cb5e5dSvi 		}
35540cb5e5dSvi 		param = param->param_next;
35640cb5e5dSvi 	}
35740cb5e5dSvi 	return (B_FALSE);
35840cb5e5dSvi }
35940cb5e5dSvi 
36040cb5e5dSvi 
36140cb5e5dSvi /*
36240cb5e5dSvi  * Given a value header return the value of the named param.
36340cb5e5dSvi  */
36440cb5e5dSvi const sip_str_t *
sip_get_param_value(sip_header_value_t header_value,char * param_name,int * error)36540cb5e5dSvi sip_get_param_value(sip_header_value_t header_value, char *param_name,
36640cb5e5dSvi     int *error)
36740cb5e5dSvi {
36840cb5e5dSvi 	sip_value_t	*_sip_header_value;
36940cb5e5dSvi 	sip_param_t	*sip_param;
37040cb5e5dSvi 
37140cb5e5dSvi 	if (error != NULL)
37240cb5e5dSvi 		*error = 0;
37340cb5e5dSvi 	if (header_value == NULL || param_name == NULL) {
37440cb5e5dSvi 		if (error != NULL)
37540cb5e5dSvi 			*error = EINVAL;
37640cb5e5dSvi 		return (NULL);
37740cb5e5dSvi 	}
37840cb5e5dSvi 	_sip_header_value = (sip_value_t *)header_value;
37940cb5e5dSvi 	if (_sip_header_value->value_state == SIP_VALUE_DELETED) {
38040cb5e5dSvi 		if (error != NULL)
38140cb5e5dSvi 			*error = EINVAL;
38240cb5e5dSvi 		return (NULL);
38340cb5e5dSvi 	}
38440cb5e5dSvi 	if (_sip_header_value->param_list == NULL) {
38540cb5e5dSvi 		if (error != NULL)
38640cb5e5dSvi 			*error = EINVAL;
38740cb5e5dSvi 		return (NULL);
38840cb5e5dSvi 	}
38940cb5e5dSvi 	sip_param = sip_get_param_from_list(_sip_header_value->param_list,
39040cb5e5dSvi 	    param_name);
39140cb5e5dSvi 	if (sip_param != NULL)
39240cb5e5dSvi 		return (&sip_param->param_value);
39340cb5e5dSvi 	return (NULL);
39440cb5e5dSvi }
39540cb5e5dSvi 
39640cb5e5dSvi /*
39740cb5e5dSvi  * Return the list of params in the header
39840cb5e5dSvi  */
39940cb5e5dSvi const sip_param_t *
sip_get_params(sip_header_value_t header_value,int * error)40040cb5e5dSvi sip_get_params(sip_header_value_t header_value, int *error)
40140cb5e5dSvi {
40240cb5e5dSvi 	sip_value_t	*sip_header_value;
40340cb5e5dSvi 
40440cb5e5dSvi 	if (error != NULL)
40540cb5e5dSvi 		*error = 0;
40640cb5e5dSvi 	if (header_value == NULL) {
40740cb5e5dSvi 		if (error != NULL)
40840cb5e5dSvi 			*error = EINVAL;
40940cb5e5dSvi 		return (NULL);
41040cb5e5dSvi 	}
41140cb5e5dSvi 	sip_header_value = (sip_value_t *)header_value;
41240cb5e5dSvi 	if (sip_header_value->value_state == SIP_VALUE_DELETED) {
41340cb5e5dSvi 		if (error != NULL)
41440cb5e5dSvi 			*error = EINVAL;
41540cb5e5dSvi 		return (NULL);
41640cb5e5dSvi 	}
41740cb5e5dSvi 	return (sip_header_value->param_list);
41840cb5e5dSvi }
41940cb5e5dSvi 
42040cb5e5dSvi /*
42140cb5e5dSvi  * Return true if this is a SIP request
42240cb5e5dSvi  */
42340cb5e5dSvi boolean_t
sip_msg_is_request(sip_msg_t sip_msg,int * error)42440cb5e5dSvi sip_msg_is_request(sip_msg_t sip_msg, int *error)
42540cb5e5dSvi {
42640cb5e5dSvi 	_sip_msg_t		*_sip_msg;
42740cb5e5dSvi 	sip_message_type_t	*sip_msg_info;
42840cb5e5dSvi 	boolean_t		ret;
42940cb5e5dSvi 
43040cb5e5dSvi 	if (error != NULL)
43140cb5e5dSvi 		*error = 0;
43240cb5e5dSvi 	if (sip_msg == NULL) {
43340cb5e5dSvi 		if (error != NULL)
43440cb5e5dSvi 			*error = EINVAL;
43540cb5e5dSvi 		return (B_FALSE);
43640cb5e5dSvi 	}
43740cb5e5dSvi 	_sip_msg = (_sip_msg_t *)sip_msg;
43840cb5e5dSvi 	(void) pthread_mutex_lock(&_sip_msg->sip_msg_mutex);
43940cb5e5dSvi 	if (_sip_msg->sip_msg_req_res == NULL) {
44040cb5e5dSvi 		(void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
44140cb5e5dSvi 		if (error != NULL)
44240cb5e5dSvi 			*error = EINVAL;
44340cb5e5dSvi 		return (B_FALSE);
44440cb5e5dSvi 	}
44540cb5e5dSvi 	sip_msg_info = _sip_msg->sip_msg_req_res;
44640cb5e5dSvi 	ret = sip_msg_info->is_request;
44740cb5e5dSvi 	(void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
44840cb5e5dSvi 	return (ret);
44940cb5e5dSvi }
45040cb5e5dSvi 
45140cb5e5dSvi /*
45240cb5e5dSvi  * Return true if this is a SIP response
45340cb5e5dSvi  */
45440cb5e5dSvi boolean_t
sip_msg_is_response(sip_msg_t sip_msg,int * error)45540cb5e5dSvi sip_msg_is_response(sip_msg_t sip_msg, int *error)
45640cb5e5dSvi {
45740cb5e5dSvi 	boolean_t		is_resp;
45840cb5e5dSvi 	_sip_msg_t		*_sip_msg;
45940cb5e5dSvi 	sip_message_type_t	*sip_msg_info;
46040cb5e5dSvi 
46140cb5e5dSvi 	if (error != NULL)
46240cb5e5dSvi 		*error = 0;
46340cb5e5dSvi 	if (sip_msg == NULL) {
46440cb5e5dSvi 		if (error != NULL)
46540cb5e5dSvi 			*error = EINVAL;
46640cb5e5dSvi 		return (B_FALSE);
46740cb5e5dSvi 	}
46840cb5e5dSvi 	_sip_msg = (_sip_msg_t *)sip_msg;
46940cb5e5dSvi 	(void) pthread_mutex_lock(&_sip_msg->sip_msg_mutex);
47040cb5e5dSvi 	if (_sip_msg->sip_msg_req_res == NULL) {
47140cb5e5dSvi 		(void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
47240cb5e5dSvi 		if (error != NULL)
47340cb5e5dSvi 			*error = EINVAL;
47440cb5e5dSvi 		return (B_FALSE);
47540cb5e5dSvi 	}
47640cb5e5dSvi 	sip_msg_info = _sip_msg->sip_msg_req_res;
47740cb5e5dSvi 	is_resp = !sip_msg_info->is_request;
47840cb5e5dSvi 	(void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
47940cb5e5dSvi 	return (is_resp);
48040cb5e5dSvi }
48140cb5e5dSvi 
48240cb5e5dSvi /*
48340cb5e5dSvi  * Return the method in the request line
48440cb5e5dSvi  */
48540cb5e5dSvi sip_method_t
sip_get_request_method(sip_msg_t sip_msg,int * error)48640cb5e5dSvi sip_get_request_method(sip_msg_t sip_msg, int *error)
48740cb5e5dSvi {
48840cb5e5dSvi 	_sip_msg_t		*_sip_msg;
48940cb5e5dSvi 	sip_message_type_t	*sip_msg_info;
49040cb5e5dSvi 	sip_method_t 		ret = -1;
49140cb5e5dSvi 
49240cb5e5dSvi 	if (error != NULL)
49340cb5e5dSvi 		*error = 0;
49440cb5e5dSvi 	if (sip_msg == NULL) {
49540cb5e5dSvi 		if (error != NULL)
49640cb5e5dSvi 			*error = EINVAL;
49740cb5e5dSvi 		return (ret);
49840cb5e5dSvi 	}
49940cb5e5dSvi 	_sip_msg = (_sip_msg_t *)sip_msg;
50040cb5e5dSvi 	(void) pthread_mutex_lock(&_sip_msg->sip_msg_mutex);
50140cb5e5dSvi 	sip_msg_info = _sip_msg->sip_msg_req_res;
50240cb5e5dSvi 	if (_sip_msg->sip_msg_req_res == NULL) {
50340cb5e5dSvi 		(void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
50440cb5e5dSvi 		if (error != NULL)
50540cb5e5dSvi 			*error = EINVAL;
50640cb5e5dSvi 		return (ret);
50740cb5e5dSvi 	}
50840cb5e5dSvi 	if (sip_msg_info->is_request)
50940cb5e5dSvi 		ret = sip_msg_info->sip_req_method;
51040cb5e5dSvi 	else if (error != NULL)
51140cb5e5dSvi 		*error = EINVAL;
51240cb5e5dSvi 	(void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
51340cb5e5dSvi 	return (ret);
51440cb5e5dSvi }
51540cb5e5dSvi 
51640cb5e5dSvi /*
51740cb5e5dSvi  * Return the URI from the request line
51840cb5e5dSvi  */
51940cb5e5dSvi const sip_str_t *
sip_get_request_uri_str(sip_msg_t sip_msg,int * error)52040cb5e5dSvi sip_get_request_uri_str(sip_msg_t sip_msg, int *error)
52140cb5e5dSvi {
52240cb5e5dSvi 	_sip_msg_t		*_sip_msg;
52340cb5e5dSvi 	sip_message_type_t	*sip_msg_info;
52440cb5e5dSvi 	sip_str_t 		*ret = NULL;
52540cb5e5dSvi 	struct sip_uri		*parsed_uri;
52640cb5e5dSvi 
52740cb5e5dSvi 	if (error != NULL)
52840cb5e5dSvi 		*error = 0;
52940cb5e5dSvi 	if (sip_msg == NULL) {
53040cb5e5dSvi 		if (error != NULL)
53140cb5e5dSvi 			*error = EINVAL;
53240cb5e5dSvi 		return (NULL);
53340cb5e5dSvi 	}
53440cb5e5dSvi 	_sip_msg = (_sip_msg_t *)sip_msg;
53540cb5e5dSvi 	(void) pthread_mutex_lock(&_sip_msg->sip_msg_mutex);
53640cb5e5dSvi 	if (_sip_msg->sip_msg_req_res == NULL) {
53740cb5e5dSvi 		(void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
53840cb5e5dSvi 		if (error != NULL)
53940cb5e5dSvi 			*error = EINVAL;
54040cb5e5dSvi 		return (NULL);
54140cb5e5dSvi 	}
54240cb5e5dSvi 	sip_msg_info = _sip_msg->sip_msg_req_res;
54340cb5e5dSvi 	if (sip_msg_info->is_request)
54440cb5e5dSvi 		ret = &sip_msg_info->sip_req_uri;
54540cb5e5dSvi 	(void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
54640cb5e5dSvi 
54740cb5e5dSvi 	/*
54840cb5e5dSvi 	 * If the error is required, check the validity of the URI via
54940cb5e5dSvi 	 * sip_uri_parse().
55040cb5e5dSvi 	 */
55140cb5e5dSvi 	if (error != NULL) {
55240cb5e5dSvi 		parsed_uri = sip_parse_uri(ret, error);
55340cb5e5dSvi 		if (parsed_uri != NULL)
55440cb5e5dSvi 			sip_free_parsed_uri((sip_uri_t)parsed_uri);
55540cb5e5dSvi 	}
55640cb5e5dSvi 	return (ret);
55740cb5e5dSvi }
55840cb5e5dSvi 
55940cb5e5dSvi /*
56040cb5e5dSvi  * Return the response code
56140cb5e5dSvi  */
56240cb5e5dSvi int
sip_get_response_code(sip_msg_t sip_msg,int * error)56340cb5e5dSvi sip_get_response_code(sip_msg_t sip_msg, int *error)
56440cb5e5dSvi {
56540cb5e5dSvi 	_sip_msg_t		*_sip_msg;
56640cb5e5dSvi 	sip_message_type_t	*sip_msg_info;
56740cb5e5dSvi 	int 			ret = -1;
56840cb5e5dSvi 
56940cb5e5dSvi 	if (error != NULL)
57040cb5e5dSvi 		*error = 0;
57140cb5e5dSvi 	if (sip_msg == NULL) {
57240cb5e5dSvi 		if (error != NULL)
57340cb5e5dSvi 			*error = EINVAL;
57440cb5e5dSvi 		return (ret);
57540cb5e5dSvi 	}
57640cb5e5dSvi 	_sip_msg = (_sip_msg_t *)sip_msg;
57740cb5e5dSvi 	(void) pthread_mutex_lock(&_sip_msg->sip_msg_mutex);
57840cb5e5dSvi 	if (_sip_msg->sip_msg_req_res == NULL) {
57940cb5e5dSvi 		(void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
58040cb5e5dSvi 		if (error != NULL)
58140cb5e5dSvi 			*error = EINVAL;
58240cb5e5dSvi 		return (ret);
58340cb5e5dSvi 	}
58440cb5e5dSvi 	sip_msg_info = _sip_msg->sip_msg_req_res;
58540cb5e5dSvi 	if (!sip_msg_info->is_request)
58640cb5e5dSvi 		ret = sip_msg_info->sip_resp_code;
58740cb5e5dSvi 	else if (error != NULL)
58840cb5e5dSvi 		*error = EINVAL;
58940cb5e5dSvi 	(void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
59040cb5e5dSvi 	return (ret);
59140cb5e5dSvi }
59240cb5e5dSvi 
59340cb5e5dSvi /*
59440cb5e5dSvi  * Get the response phrase
59540cb5e5dSvi  */
59640cb5e5dSvi const sip_str_t *
sip_get_response_phrase(sip_msg_t sip_msg,int * error)59740cb5e5dSvi sip_get_response_phrase(sip_msg_t sip_msg, int *error)
59840cb5e5dSvi {
59940cb5e5dSvi 	_sip_msg_t		*_sip_msg;
60040cb5e5dSvi 	sip_message_type_t	*sip_msg_info;
60140cb5e5dSvi 	sip_str_t 		*ret = NULL;
60240cb5e5dSvi 
60340cb5e5dSvi 	if (error != NULL)
60440cb5e5dSvi 		*error = 0;
60540cb5e5dSvi 	if (sip_msg == NULL) {
60640cb5e5dSvi 		if (error != NULL)
60740cb5e5dSvi 			*error = EINVAL;
60840cb5e5dSvi 		return (ret);
60940cb5e5dSvi 	}
61040cb5e5dSvi 	_sip_msg = (_sip_msg_t *)sip_msg;
61140cb5e5dSvi 	(void) pthread_mutex_lock(&_sip_msg->sip_msg_mutex);
61240cb5e5dSvi 	if (_sip_msg->sip_msg_req_res == NULL) {
61340cb5e5dSvi 		(void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
61440cb5e5dSvi 		if (error != NULL)
61540cb5e5dSvi 			*error = EINVAL;
61640cb5e5dSvi 		return (ret);
61740cb5e5dSvi 	}
61840cb5e5dSvi 	sip_msg_info = _sip_msg->sip_msg_req_res;
61940cb5e5dSvi 	(void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
62040cb5e5dSvi 	if (!sip_msg_info->is_request) {
62140cb5e5dSvi 		if (sip_msg_info->sip_resp_phrase_len == 0)
62240cb5e5dSvi 			ret = NULL;
62340cb5e5dSvi 		else
62440cb5e5dSvi 			ret = &sip_msg_info->sip_resp_phrase;
62540cb5e5dSvi 	} else if (error != NULL) {
62640cb5e5dSvi 		*error = EINVAL;
62740cb5e5dSvi 	}
62840cb5e5dSvi 	return (ret);
62940cb5e5dSvi }
63040cb5e5dSvi 
63140cb5e5dSvi /*
63240cb5e5dSvi  * Get the SIP version string
63340cb5e5dSvi  */
63440cb5e5dSvi const sip_str_t *
sip_get_sip_version(sip_msg_t sip_msg,int * error)63540cb5e5dSvi sip_get_sip_version(sip_msg_t sip_msg, int *error)
63640cb5e5dSvi {
63740cb5e5dSvi 	_sip_msg_t		*_sip_msg;
63840cb5e5dSvi 	sip_message_type_t	*sip_msg_info;
63940cb5e5dSvi 	sip_str_t		*ret = NULL;
64040cb5e5dSvi 
64140cb5e5dSvi 	if (error != NULL)
64240cb5e5dSvi 		*error = 0;
64340cb5e5dSvi 	if (sip_msg == NULL) {
64440cb5e5dSvi 		if (error != NULL)
64540cb5e5dSvi 			*error = EINVAL;
64640cb5e5dSvi 		return (ret);
64740cb5e5dSvi 	}
64840cb5e5dSvi 	_sip_msg = (_sip_msg_t *)sip_msg;
64940cb5e5dSvi 	(void) pthread_mutex_lock(&_sip_msg->sip_msg_mutex);
65040cb5e5dSvi 	if (_sip_msg->sip_msg_req_res == NULL) {
65140cb5e5dSvi 		(void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
65240cb5e5dSvi 		if (error != NULL)
65340cb5e5dSvi 			*error = EINVAL;
65440cb5e5dSvi 		return (ret);
65540cb5e5dSvi 	}
65640cb5e5dSvi 	sip_msg_info = _sip_msg->sip_msg_req_res;
65740cb5e5dSvi 	(void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
65840cb5e5dSvi 	ret = &sip_msg_info->sip_proto_version.version;
65940cb5e5dSvi 	return (ret);
66040cb5e5dSvi }
66140cb5e5dSvi 
66240cb5e5dSvi /*
66340cb5e5dSvi  * Return the length of the SIP message
66440cb5e5dSvi  */
66540cb5e5dSvi int
sip_get_msg_len(sip_msg_t sip_msg,int * error)66640cb5e5dSvi sip_get_msg_len(sip_msg_t sip_msg, int *error)
66740cb5e5dSvi {
66840cb5e5dSvi 	_sip_msg_t	*_sip_msg;
66940cb5e5dSvi 
67040cb5e5dSvi 	if (error != NULL)
67140cb5e5dSvi 		*error = 0;
67240cb5e5dSvi 	if (sip_msg == NULL) {
67340cb5e5dSvi 		if (error != NULL)
67440cb5e5dSvi 			*error = EINVAL;
67540cb5e5dSvi 		return (-1);
67640cb5e5dSvi 	}
67740cb5e5dSvi 	_sip_msg = (_sip_msg_t *)sip_msg;
67840cb5e5dSvi 
67940cb5e5dSvi 	return (_sip_msg->sip_msg_len);
68040cb5e5dSvi }
68140cb5e5dSvi 
68240cb5e5dSvi /*
68340cb5e5dSvi  * Get content as a string. Caller frees the string
68440cb5e5dSvi  */
68540cb5e5dSvi char *
sip_get_content(sip_msg_t sip_msg,int * error)68640cb5e5dSvi sip_get_content(sip_msg_t sip_msg, int *error)
68740cb5e5dSvi {
68840cb5e5dSvi 	_sip_msg_t	*_sip_msg;
68940cb5e5dSvi 	sip_content_t	*sip_content;
69040cb5e5dSvi 	char		*content;
69140cb5e5dSvi 	int		len;
69240cb5e5dSvi 	char		*p;
69340cb5e5dSvi 
69440cb5e5dSvi 	if (error != NULL)
69540cb5e5dSvi 		*error = 0;
69640cb5e5dSvi 
69740cb5e5dSvi 	if (sip_msg == NULL) {
69840cb5e5dSvi 		if (error != NULL)
69940cb5e5dSvi 			*error = EINVAL;
70040cb5e5dSvi 		return (NULL);
70140cb5e5dSvi 	}
70240cb5e5dSvi 	_sip_msg = (_sip_msg_t *)sip_msg;
70340cb5e5dSvi 	(void) pthread_mutex_lock(&_sip_msg->sip_msg_mutex);
70440cb5e5dSvi 	if (_sip_msg->sip_msg_content == NULL) {
70540cb5e5dSvi 		(void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
70640cb5e5dSvi 		if (error != NULL)
70740cb5e5dSvi 			*error = EINVAL;
70840cb5e5dSvi 		return (NULL);
70940cb5e5dSvi 	}
71040cb5e5dSvi 	content = malloc(_sip_msg->sip_msg_content_len + 1);
71140cb5e5dSvi 	if (content == NULL) {
71240cb5e5dSvi 		(void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
71340cb5e5dSvi 		if (error != NULL)
71440cb5e5dSvi 			*error = ENOMEM;
71540cb5e5dSvi 		return (NULL);
71640cb5e5dSvi 	}
71740cb5e5dSvi 	p = content;
71840cb5e5dSvi 	sip_content = _sip_msg->sip_msg_content;
71940cb5e5dSvi 	while (sip_content != NULL) {
72040cb5e5dSvi 		len =  sip_content->sip_content_end -
72140cb5e5dSvi 		    sip_content->sip_content_start;
72240cb5e5dSvi 		(void) strncpy(p, sip_content->sip_content_start, len);
72340cb5e5dSvi 		p += len;
72440cb5e5dSvi 		sip_content = sip_content->sip_content_next;
72540cb5e5dSvi 	}
72640cb5e5dSvi 	content[_sip_msg->sip_msg_content_len] = '\0';
72740cb5e5dSvi 	(void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
72840cb5e5dSvi 	return (content);
72940cb5e5dSvi }
73040cb5e5dSvi 
73140cb5e5dSvi /*
73240cb5e5dSvi  * copy sip_header with param, if any, to sip_msg
73340cb5e5dSvi  */
73440cb5e5dSvi int
sip_copy_header(sip_msg_t sip_msg,sip_header_t sip_header,char * param)73540cb5e5dSvi sip_copy_header(sip_msg_t sip_msg, sip_header_t sip_header, char *param)
73640cb5e5dSvi {
73740cb5e5dSvi 	_sip_msg_t	*_sip_msg;
73840cb5e5dSvi 	_sip_header_t	*_sip_header;
73940cb5e5dSvi 	int		ret;
74040cb5e5dSvi 
74140cb5e5dSvi 	if (sip_msg == NULL || sip_header == NULL)
74240cb5e5dSvi 		return (EINVAL);
74340cb5e5dSvi 	_sip_msg = (_sip_msg_t *)sip_msg;
74440cb5e5dSvi 	_sip_header = (_sip_header_t *)sip_header;
74540cb5e5dSvi 	(void) pthread_mutex_lock(&_sip_msg->sip_msg_mutex);
74640cb5e5dSvi 	if (_sip_msg->sip_msg_cannot_be_modified) {
74740cb5e5dSvi 		(void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
74840cb5e5dSvi 		return (EPERM);
74940cb5e5dSvi 	}
75040cb5e5dSvi 	if (_sip_header->sip_header_state == SIP_HEADER_DELETED) {
75140cb5e5dSvi 		(void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
75240cb5e5dSvi 		return (EINVAL);
75340cb5e5dSvi 	}
75440cb5e5dSvi 
75540cb5e5dSvi 	ret = _sip_copy_header(_sip_msg, _sip_header, param, B_TRUE);
75640cb5e5dSvi 	if (_sip_msg->sip_msg_buf != NULL)
75740cb5e5dSvi 		_sip_msg->sip_msg_modified = B_TRUE;
75840cb5e5dSvi 	(void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
75940cb5e5dSvi 	return (ret);
76040cb5e5dSvi }
76140cb5e5dSvi 
76240cb5e5dSvi /*
76340cb5e5dSvi  * copy the header specified by header_name, with param, if any
76440cb5e5dSvi  */
76540cb5e5dSvi int
sip_copy_header_by_name(sip_msg_t old_msg,sip_msg_t new_msg,char * header_name,char * param)76640cb5e5dSvi sip_copy_header_by_name(sip_msg_t old_msg, sip_msg_t new_msg,
76740cb5e5dSvi     char *header_name, char *param)
76840cb5e5dSvi {
76940cb5e5dSvi 	int		ret;
77040cb5e5dSvi 	_sip_msg_t	*_old_msg = (_sip_msg_t *)old_msg;
77140cb5e5dSvi 	_sip_msg_t	*_new_msg = (_sip_msg_t *)new_msg;
77240cb5e5dSvi 
77340cb5e5dSvi 	if (_old_msg == NULL || _new_msg == NULL || header_name == NULL ||
77440cb5e5dSvi 	    _old_msg == _new_msg) {
77540cb5e5dSvi 		return (EINVAL);
77640cb5e5dSvi 	}
77740cb5e5dSvi 	(void) pthread_mutex_lock(&_new_msg->sip_msg_mutex);
77840cb5e5dSvi 	if (_new_msg->sip_msg_cannot_be_modified) {
77940cb5e5dSvi 		(void) pthread_mutex_unlock(&_new_msg->sip_msg_mutex);
78040cb5e5dSvi 		return (EPERM);
78140cb5e5dSvi 	}
78240cb5e5dSvi 
78340cb5e5dSvi 	(void) pthread_mutex_lock(&_old_msg->sip_msg_mutex);
78440cb5e5dSvi 	ret = _sip_find_and_copy_header(_old_msg, _new_msg, header_name, param,
78540cb5e5dSvi 	    B_FALSE);
78640cb5e5dSvi 	(void) pthread_mutex_unlock(&_old_msg->sip_msg_mutex);
78740cb5e5dSvi 	if (_new_msg->sip_msg_buf != NULL)
78840cb5e5dSvi 		_new_msg->sip_msg_modified = B_TRUE;
78940cb5e5dSvi 	(void) pthread_mutex_unlock(&_new_msg->sip_msg_mutex);
79040cb5e5dSvi 	return (ret);
79140cb5e5dSvi }
79240cb5e5dSvi 
79340cb5e5dSvi /*
79440cb5e5dSvi  * add the given header to sip_message
79540cb5e5dSvi  */
79640cb5e5dSvi int
sip_add_header(sip_msg_t sip_msg,char * header_string)79740cb5e5dSvi sip_add_header(sip_msg_t sip_msg, char *header_string)
79840cb5e5dSvi {
79940cb5e5dSvi 	int		header_size;
80040cb5e5dSvi 	_sip_header_t	*new_header;
80140cb5e5dSvi 	_sip_msg_t	*_sip_msg;
80240cb5e5dSvi 
80340cb5e5dSvi 	if (sip_msg == NULL || header_string == NULL)
80440cb5e5dSvi 		return (EINVAL);
80540cb5e5dSvi 	_sip_msg = (_sip_msg_t *)sip_msg;
80640cb5e5dSvi 	(void) pthread_mutex_lock(&_sip_msg->sip_msg_mutex);
80740cb5e5dSvi 	if (_sip_msg->sip_msg_cannot_be_modified) {
80840cb5e5dSvi 		(void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
80940cb5e5dSvi 		return (EPERM);
81040cb5e5dSvi 	}
81140cb5e5dSvi 	header_size = strlen(header_string) + strlen(SIP_CRLF);
81240cb5e5dSvi 	new_header = sip_new_header(header_size);
81340cb5e5dSvi 	if (new_header == NULL) {
81440cb5e5dSvi 		(void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
81540cb5e5dSvi 		return (ENOMEM);
81640cb5e5dSvi 	}
81740cb5e5dSvi 
81840cb5e5dSvi 	(void) snprintf(new_header->sip_hdr_start, header_size + 1, "%s%s",
81940cb5e5dSvi 	    header_string, SIP_CRLF);
82040cb5e5dSvi 	_sip_add_header(_sip_msg, new_header, B_TRUE, B_FALSE, NULL);
82140cb5e5dSvi 	if (_sip_msg->sip_msg_buf != NULL)
82240cb5e5dSvi 		_sip_msg->sip_msg_modified = B_TRUE;
82340cb5e5dSvi 	(void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
82440cb5e5dSvi 	return (0);
82540cb5e5dSvi }
82640cb5e5dSvi 
82740cb5e5dSvi /*
82840cb5e5dSvi  * add the given param to the sip_header. create a new header with the param
82940cb5e5dSvi  * and mark the old header as deleted.
83040cb5e5dSvi  */
83140cb5e5dSvi sip_header_t
sip_add_param(sip_header_t sip_header,char * param,int * error)83240cb5e5dSvi sip_add_param(sip_header_t sip_header, char *param, int *error)
83340cb5e5dSvi {
83440cb5e5dSvi 	_sip_header_t	*_sip_header;
83540cb5e5dSvi 	_sip_header_t	*new_header;
83640cb5e5dSvi 	int		hdrlen;
83740cb5e5dSvi 	_sip_msg_t	*_sip_msg;
83840cb5e5dSvi 	int		param_len;
83940cb5e5dSvi 	char		*tmp_ptr;
84040cb5e5dSvi 
84140cb5e5dSvi 	if (error != NULL)
84240cb5e5dSvi 		*error = 0;
84340cb5e5dSvi 
84440cb5e5dSvi 	if (param == NULL || sip_header == NULL) {
84540cb5e5dSvi 		if (error != NULL)
84640cb5e5dSvi 			*error = EINVAL;
84740cb5e5dSvi 		return (NULL);
84840cb5e5dSvi 	}
84940cb5e5dSvi 
85040cb5e5dSvi 	_sip_header = (_sip_header_t *)sip_header;
85140cb5e5dSvi 
85240cb5e5dSvi 	(void) pthread_mutex_lock(&_sip_header->sip_hdr_sipmsg->sip_msg_mutex);
85340cb5e5dSvi 	if (_sip_header->sip_hdr_sipmsg->sip_msg_cannot_be_modified) {
85440cb5e5dSvi 		if (error != NULL)
85540cb5e5dSvi 			*error = EPERM;
85640cb5e5dSvi 		(void) pthread_mutex_unlock(
85740cb5e5dSvi 		    &_sip_header->sip_hdr_sipmsg->sip_msg_mutex);
85840cb5e5dSvi 		return (NULL);
85940cb5e5dSvi 	}
86040cb5e5dSvi 	if (_sip_header->sip_header_state == SIP_HEADER_DELETED) {
86140cb5e5dSvi 		if (error != NULL)
86240cb5e5dSvi 			*error = EINVAL;
86340cb5e5dSvi 		(void) pthread_mutex_unlock(
86440cb5e5dSvi 		    &_sip_header->sip_hdr_sipmsg->sip_msg_mutex);
86540cb5e5dSvi 		return (NULL);
86640cb5e5dSvi 	}
86740cb5e5dSvi 
86840cb5e5dSvi 	param_len = SIP_SPACE_LEN + sizeof (char) + SIP_SPACE_LEN +
86940cb5e5dSvi 	    strlen(param);
87040cb5e5dSvi 	hdrlen = _sip_header->sip_hdr_end - _sip_header->sip_hdr_start;
87140cb5e5dSvi 	new_header = sip_new_header(hdrlen + param_len);
87240cb5e5dSvi 	if (new_header == NULL) {
87340cb5e5dSvi 		if (error != NULL)
87440cb5e5dSvi 			*error = ENOMEM;
87540cb5e5dSvi 		(void) pthread_mutex_unlock(
87640cb5e5dSvi 		    &_sip_header->sip_hdr_sipmsg->sip_msg_mutex);
87740cb5e5dSvi 		return (NULL);
87840cb5e5dSvi 	}
87940cb5e5dSvi 	(void) memcpy(new_header->sip_hdr_start, _sip_header->sip_hdr_start,
88040cb5e5dSvi 	    hdrlen);
88140cb5e5dSvi 	new_header->sip_hdr_end = new_header->sip_hdr_start + hdrlen;
88240cb5e5dSvi 	hdrlen = param_len + 1;
88340cb5e5dSvi 	/*
88440cb5e5dSvi 	 * Find CRLF
88540cb5e5dSvi 	 */
88640cb5e5dSvi 	tmp_ptr = new_header->sip_hdr_end;
88740cb5e5dSvi 	while (*tmp_ptr-- != '\n') {
88840cb5e5dSvi 		hdrlen++;
88940cb5e5dSvi 		if (tmp_ptr == new_header->sip_hdr_start) {
89040cb5e5dSvi 			sip_free_header(new_header);
89140cb5e5dSvi 			if (error != NULL)
89240cb5e5dSvi 				*error = EINVAL;
89340cb5e5dSvi 			(void) pthread_mutex_unlock(
89440cb5e5dSvi 			    &_sip_header->sip_hdr_sipmsg->sip_msg_mutex);
89540cb5e5dSvi 			return (NULL);
89640cb5e5dSvi 		}
89740cb5e5dSvi 	}
89840cb5e5dSvi 	(void) snprintf(tmp_ptr, hdrlen + 1,
89940cb5e5dSvi 	    " %c %s%s", SIP_SEMI, param, SIP_CRLF);
90040cb5e5dSvi 	new_header->sip_hdr_end += param_len;
90140cb5e5dSvi 	new_header->sip_header_functions = _sip_header->sip_header_functions;
90240cb5e5dSvi 	_sip_msg = _sip_header->sip_hdr_sipmsg;
90340cb5e5dSvi 	_sip_add_header(_sip_msg, new_header, B_TRUE, B_FALSE, NULL);
90440cb5e5dSvi 	if (_sip_header->sip_hdr_sipmsg->sip_msg_buf != NULL)
90540cb5e5dSvi 		_sip_header->sip_hdr_sipmsg->sip_msg_modified = B_TRUE;
90640cb5e5dSvi 	(void) pthread_mutex_unlock(&new_header->sip_hdr_sipmsg->sip_msg_mutex);
90740cb5e5dSvi 	(void) sip_delete_header(sip_header);
90840cb5e5dSvi 	return ((sip_header_t)new_header);
90940cb5e5dSvi }
91040cb5e5dSvi 
91140cb5e5dSvi /*
91240cb5e5dSvi  * Get Request URI
91340cb5e5dSvi  */
91440cb5e5dSvi const struct sip_uri *
sip_get_request_uri(sip_msg_t sip_msg,int * error)91540cb5e5dSvi sip_get_request_uri(sip_msg_t sip_msg, int *error)
91640cb5e5dSvi {
91740cb5e5dSvi 	_sip_msg_t		*_sip_msg;
91840cb5e5dSvi 	sip_message_type_t	*sip_msg_info;
91940cb5e5dSvi 	const struct sip_uri	*ret = NULL;
92040cb5e5dSvi 
92140cb5e5dSvi 	if (error != NULL)
92240cb5e5dSvi 		*error = 0;
92340cb5e5dSvi 
92440cb5e5dSvi 	if (sip_msg == NULL) {
92540cb5e5dSvi 		if (error != NULL)
92640cb5e5dSvi 			*error = EINVAL;
92740cb5e5dSvi 		return (NULL);
92840cb5e5dSvi 	}
92940cb5e5dSvi 	_sip_msg = (_sip_msg_t *)sip_msg;
93040cb5e5dSvi 	(void) pthread_mutex_lock(&_sip_msg->sip_msg_mutex);
93140cb5e5dSvi 	sip_msg_info = _sip_msg->sip_msg_req_res;
93240cb5e5dSvi 	if (sip_msg_info != NULL && sip_msg_info->is_request) {
93340cb5e5dSvi 		ret = sip_msg_info->sip_req_parse_uri;
93440cb5e5dSvi 	} else {
93540cb5e5dSvi 		if (error != NULL)
93640cb5e5dSvi 			*error = EINVAL;
93740cb5e5dSvi 	}
93840cb5e5dSvi 	(void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
93940cb5e5dSvi 
94040cb5e5dSvi 	if (ret != NULL) {
94140cb5e5dSvi 		if (ret->sip_uri_scheme.sip_str_len == 0 ||
94240cb5e5dSvi 		    ret->sip_uri_scheme.sip_str_ptr == NULL) {
94340cb5e5dSvi 			ret = NULL;
94440cb5e5dSvi 			if (error != NULL)
94540cb5e5dSvi 				*error = EINVAL;
94640cb5e5dSvi 		} else if (ret->sip_uri_errflags != 0 && error != NULL) {
94740cb5e5dSvi 			*error = EINVAL;
94840cb5e5dSvi 		}
94940cb5e5dSvi 	}
95040cb5e5dSvi 	return ((sip_uri_t)ret);
95140cb5e5dSvi }
95240cb5e5dSvi 
95340cb5e5dSvi /*
95440cb5e5dSvi  * returns a comma separated string of all the sent-by values registered by
95540cb5e5dSvi  * the UA.
95640cb5e5dSvi  */
95740cb5e5dSvi char *
sip_sent_by_to_str(int * error)95840cb5e5dSvi sip_sent_by_to_str(int *error)
95940cb5e5dSvi {
96040cb5e5dSvi 	sent_by_list_t	*sb;
96140cb5e5dSvi 	int		sb_len = 0;
96240cb5e5dSvi 	int		slen;
96340cb5e5dSvi 	char		*sb_str;
96440cb5e5dSvi 	char		*p;
96540cb5e5dSvi 	int		count = 0;
96640cb5e5dSvi 	int		cnt = 0;
96740cb5e5dSvi 
96840cb5e5dSvi 	if (error != NULL)
96940cb5e5dSvi 		*error = 0;
97040cb5e5dSvi 
97140cb5e5dSvi 	(void) pthread_mutex_lock(&sip_sent_by_lock);
97240cb5e5dSvi 	if (sip_sent_by == NULL) {
97340cb5e5dSvi 		(void) pthread_mutex_unlock(&sip_sent_by_lock);
97440cb5e5dSvi 		return (NULL);
97540cb5e5dSvi 	}
97640cb5e5dSvi 	sb = sip_sent_by;
97740cb5e5dSvi 	for (cnt = 0; cnt < sip_sent_by_count; cnt++) {
97840cb5e5dSvi 		sb_len += strlen(sb->sb_val);
97940cb5e5dSvi 		sb = sb->sb_next;
98040cb5e5dSvi 	}
98140cb5e5dSvi 	/*
98240cb5e5dSvi 	 * for the commas
98340cb5e5dSvi 	 */
98440cb5e5dSvi 	sb_len += sip_sent_by_count - 1;
98540cb5e5dSvi 	sb_str = malloc(sb_len + 1);
98640cb5e5dSvi 	if (sb_str == NULL) {
98740cb5e5dSvi 		if (error != NULL)
98840cb5e5dSvi 			*error = ENOMEM;
98940cb5e5dSvi 		(void) pthread_mutex_unlock(&sip_sent_by_lock);
99040cb5e5dSvi 		return (NULL);
99140cb5e5dSvi 	}
99240cb5e5dSvi 	sb = sip_sent_by;
99340cb5e5dSvi 	p = sb_str;
99440cb5e5dSvi 	slen = sb_len + 1;
99540cb5e5dSvi 	for (cnt = 0; cnt < sip_sent_by_count; cnt++) {
99640cb5e5dSvi 		if (cnt == 0) {
99740cb5e5dSvi 			count = snprintf(p, slen, "%s", sb->sb_val);
99840cb5e5dSvi 		} else {
99940cb5e5dSvi 			count = snprintf(p, slen, "%c%s", SIP_COMMA,
100040cb5e5dSvi 			    sb->sb_val);
100140cb5e5dSvi 		}
100240cb5e5dSvi 		p += count;
100340cb5e5dSvi 		slen -= count;
100440cb5e5dSvi 		sb = sb->sb_next;
100540cb5e5dSvi 	}
100640cb5e5dSvi 	sb_str[sb_len] = '\0';
100740cb5e5dSvi 	(void) pthread_mutex_unlock(&sip_sent_by_lock);
100840cb5e5dSvi 	return (sb_str);
100940cb5e5dSvi }
101040cb5e5dSvi 
101140cb5e5dSvi /*
101240cb5e5dSvi  * A comma separated list of sent-by values.
101340cb5e5dSvi  */
101440cb5e5dSvi int
sip_register_sent_by(char * val)101540cb5e5dSvi sip_register_sent_by(char *val)
101640cb5e5dSvi {
101740cb5e5dSvi 	sent_by_list_t	*sb = NULL;
101840cb5e5dSvi 	sent_by_list_t	*sb_tail = NULL;
101940cb5e5dSvi 	char		*str;
102040cb5e5dSvi 	int		count = 0;
102140cb5e5dSvi 
102240cb5e5dSvi 	if (val == NULL)
102340cb5e5dSvi 		return (EINVAL);
102440cb5e5dSvi 	str = strtok(val, ",");
102540cb5e5dSvi 	while (str != NULL) {
102640cb5e5dSvi 		int	slen;
102740cb5e5dSvi 		char	*start = str;
102840cb5e5dSvi 		char	*end = str + strlen(str) - 1;
102940cb5e5dSvi 
103040cb5e5dSvi 		while (isspace(*start))
103140cb5e5dSvi 			start++;
103240cb5e5dSvi 		while (isspace(*end))
103340cb5e5dSvi 			end--;
103440cb5e5dSvi 		if (end <= start)
103540cb5e5dSvi 			goto err_ret;
103640cb5e5dSvi 		slen = end - start + 1;
103740cb5e5dSvi 		sb_tail = (sent_by_list_t *)malloc(sizeof (*sb_tail));
103840cb5e5dSvi 		if (sb_tail == NULL)
103940cb5e5dSvi 			goto err_ret;
104040cb5e5dSvi 		sb_tail->sb_next = sb_tail->sb_prev = NULL;
104140cb5e5dSvi 		if ((sb_tail->sb_val = (char *)malloc(slen + 1)) == NULL) {
104240cb5e5dSvi 			free(sb_tail);
104340cb5e5dSvi 			goto err_ret;
104440cb5e5dSvi 		}
104540cb5e5dSvi 		(void) strncpy(sb_tail->sb_val, start, slen);
104640cb5e5dSvi 		sb_tail->sb_val[slen] = '\0';
104740cb5e5dSvi 		if (sb == NULL) {
104840cb5e5dSvi 			sb = sb_tail;
104940cb5e5dSvi 		} else {
105040cb5e5dSvi 			sb_tail->sb_next = sb;
105140cb5e5dSvi 			sb->sb_prev = sb_tail;
105240cb5e5dSvi 			sb = sb_tail;
105340cb5e5dSvi 		}
105440cb5e5dSvi 		count++;
105540cb5e5dSvi 		str = strtok(NULL, ",");
105640cb5e5dSvi 	}
105740cb5e5dSvi 	sb_tail = sb;
105840cb5e5dSvi 	while (sb_tail->sb_next != NULL)
105940cb5e5dSvi 		sb_tail = sb_tail->sb_next;
106040cb5e5dSvi 	(void) pthread_mutex_lock(&sip_sent_by_lock);
106140cb5e5dSvi 	if (sip_sent_by != NULL) {
106240cb5e5dSvi 		sb_tail->sb_next = sip_sent_by;
106340cb5e5dSvi 		sip_sent_by->sb_prev = sb_tail;
106440cb5e5dSvi 	}
106540cb5e5dSvi 	sip_sent_by = sb;
106640cb5e5dSvi 	sip_sent_by_count += count;
106740cb5e5dSvi 	(void) pthread_mutex_unlock(&sip_sent_by_lock);
106840cb5e5dSvi 	return (0);
106940cb5e5dSvi err_ret:
107040cb5e5dSvi 	sb_tail = sb;
107140cb5e5dSvi 	for (; count > 0; count--) {
107240cb5e5dSvi 		sb = sb_tail->sb_next;
107340cb5e5dSvi 		free(sb_tail->sb_val);
107440cb5e5dSvi 		sb_tail->sb_next = NULL;
107540cb5e5dSvi 		sb_tail->sb_prev = NULL;
107640cb5e5dSvi 		free(sb_tail);
107740cb5e5dSvi 		sb_tail = sb;
107840cb5e5dSvi 	}
107940cb5e5dSvi 	return (EINVAL);
108040cb5e5dSvi }
108140cb5e5dSvi 
108240cb5e5dSvi /*
108340cb5e5dSvi  * Un-register sent-by values; 'val' contains a comma separated list
108440cb5e5dSvi  */
108540cb5e5dSvi void
sip_unregister_sent_by(char * val)108640cb5e5dSvi sip_unregister_sent_by(char *val)
108740cb5e5dSvi {
108840cb5e5dSvi 	sent_by_list_t	*sb;
108940cb5e5dSvi 	char		*str;
109040cb5e5dSvi 	int		count = 0;
109140cb5e5dSvi 
109240cb5e5dSvi 	(void) pthread_mutex_lock(&sip_sent_by_lock);
109340cb5e5dSvi 	str = strtok(val, ",");
109440cb5e5dSvi 	while (str != NULL) {
109540cb5e5dSvi 		sb = sip_sent_by;
109640cb5e5dSvi 		for (count = 0; count < sip_sent_by_count; count++) {
109740cb5e5dSvi 			if (strncmp(sb->sb_val, str, strlen(str)) == 0) {
109840cb5e5dSvi 				if (sb == sip_sent_by) {
109940cb5e5dSvi 					if (sb->sb_next != NULL)
110040cb5e5dSvi 						sip_sent_by = sb->sb_next;
110140cb5e5dSvi 					else
110240cb5e5dSvi 						sip_sent_by = NULL;
110340cb5e5dSvi 				} else if (sb->sb_next == NULL) {
110440cb5e5dSvi 					sb->sb_prev->sb_next = NULL;
110540cb5e5dSvi 				} else {
110640cb5e5dSvi 					sb->sb_prev->sb_next = sb->sb_next;
110740cb5e5dSvi 					sb->sb_next->sb_prev = sb->sb_prev;
110840cb5e5dSvi 				}
110940cb5e5dSvi 				sip_sent_by_count--;
111040cb5e5dSvi 				sb->sb_next = NULL;
111140cb5e5dSvi 				sb->sb_prev = NULL;
111240cb5e5dSvi 				free(sb->sb_val);
111340cb5e5dSvi 				free(sb);
111440cb5e5dSvi 				break;
111540cb5e5dSvi 			}
111640cb5e5dSvi 			sb = sb->sb_next;
111740cb5e5dSvi 		}
111840cb5e5dSvi 		str = strtok(NULL, ",");
111940cb5e5dSvi 	}
112040cb5e5dSvi 	(void) pthread_mutex_unlock(&sip_sent_by_lock);
112140cb5e5dSvi }
112240cb5e5dSvi 
112340cb5e5dSvi /*
112440cb5e5dSvi  * Un-register all the sent-by values
112540cb5e5dSvi  */
112640cb5e5dSvi void
sip_unregister_all_sent_by()112740cb5e5dSvi sip_unregister_all_sent_by()
112840cb5e5dSvi {
112940cb5e5dSvi 	sent_by_list_t	*sb;
113040cb5e5dSvi 	int		count;
113140cb5e5dSvi 
113240cb5e5dSvi 	(void) pthread_mutex_lock(&sip_sent_by_lock);
113340cb5e5dSvi 	sb = sip_sent_by;
113440cb5e5dSvi 	for (count = 0; count < sip_sent_by_count; count++) {
113540cb5e5dSvi 		sip_sent_by = sb->sb_next;
113640cb5e5dSvi 		free(sb->sb_val);
113740cb5e5dSvi 		sb->sb_next = NULL;
113840cb5e5dSvi 		sb->sb_prev = NULL;
113940cb5e5dSvi 		free(sb);
114040cb5e5dSvi 		sb = sip_sent_by;
114140cb5e5dSvi 	}
114240cb5e5dSvi 	sip_sent_by = NULL;
114340cb5e5dSvi 	sip_sent_by_count = 0;
114440cb5e5dSvi 	(void) pthread_mutex_unlock(&sip_sent_by_lock);
114540cb5e5dSvi }
114640cb5e5dSvi 
114740cb5e5dSvi /*
114840cb5e5dSvi  * Given a response code, return the corresponding phrase
114940cb5e5dSvi  */
115040cb5e5dSvi char *
sip_get_resp_desc(int resp_code)115140cb5e5dSvi sip_get_resp_desc(int resp_code)
115240cb5e5dSvi {
115340cb5e5dSvi 	switch (resp_code) {
115440cb5e5dSvi 	case SIP_TRYING:
115540cb5e5dSvi 		return ("TRYING");
115640cb5e5dSvi 	case SIP_RINGING:
115740cb5e5dSvi 		return ("RINGING");
115840cb5e5dSvi 	case SIP_CALL_IS_BEING_FORWARDED:
115940cb5e5dSvi 		return ("CALL_IS_BEING_FORWARDED");
116040cb5e5dSvi 	case SIP_QUEUED:
116140cb5e5dSvi 		return ("QUEUED");
116240cb5e5dSvi 	case SIP_SESSION_PROGRESS:
116340cb5e5dSvi 		return ("SESSION_PROGRESS");
116440cb5e5dSvi 	case SIP_OK:
116540cb5e5dSvi 		return ("OK");
116640cb5e5dSvi 	case SIP_ACCEPTED:
116740cb5e5dSvi 		return ("ACCEPTED");
116840cb5e5dSvi 	case SIP_MULTIPLE_CHOICES:
116940cb5e5dSvi 		return ("MULTIPLE_CHOICES");
117040cb5e5dSvi 	case SIP_MOVED_PERMANENTLY:
117140cb5e5dSvi 		return ("MOVED_PERMANENTLY");
117240cb5e5dSvi 	case SIP_MOVED_TEMPORARILY:
117340cb5e5dSvi 		return ("MOVED_TEMPORARILY");
117440cb5e5dSvi 	case SIP_USE_PROXY:
117540cb5e5dSvi 		return ("USE_PROXY");
117640cb5e5dSvi 	case SIP_ALTERNATIVE_SERVICE:
117740cb5e5dSvi 		return ("ALTERNATIVE_SERVICE");
117840cb5e5dSvi 	case SIP_BAD_REQUEST:
117940cb5e5dSvi 		return ("BAD_REQUEST");
118040cb5e5dSvi 	case SIP_UNAUTHORIZED:
118140cb5e5dSvi 		return ("UNAUTHORIZED");
118240cb5e5dSvi 	case SIP_PAYMENT_REQUIRED:
118340cb5e5dSvi 		return ("PAYMENT_REQUIRED");
118440cb5e5dSvi 	case SIP_FORBIDDEN:
118540cb5e5dSvi 		return ("FORBIDDEN");
118640cb5e5dSvi 	case SIP_NOT_FOUND:
118740cb5e5dSvi 		return ("NOT_FOUND");
118840cb5e5dSvi 	case SIP_METHOD_NOT_ALLOWED:
118940cb5e5dSvi 		return ("METHOD_NOT_ALLOWED");
119040cb5e5dSvi 	case SIP_NOT_ACCEPTABLE:
119140cb5e5dSvi 		return ("NOT_ACCEPTABLE");
119240cb5e5dSvi 	case SIP_PROXY_AUTH_REQUIRED:
119340cb5e5dSvi 		return ("PROXY_AUTH_REQUIRED");
119440cb5e5dSvi 	case SIP_REQUEST_TIMEOUT:
119540cb5e5dSvi 		return ("REQUEST_TIMEOUT");
119640cb5e5dSvi 	case SIP_GONE:
119740cb5e5dSvi 		return ("GONE");
119840cb5e5dSvi 	case SIP_REQUEST_ENTITY_2_LARGE:
119940cb5e5dSvi 		return ("REQUEST_ENTITY_2_LARGE");
120040cb5e5dSvi 	case SIP_REQUEST_URI_2_LONG:
120140cb5e5dSvi 		return ("REQUEST_URI_2_LONG");
120240cb5e5dSvi 	case SIP_UNSUPPORTED_MEDIA_TYPE:
120340cb5e5dSvi 		return ("UNSUPPORTED_MEDIA_TYPE");
120440cb5e5dSvi 	case SIP_UNSUPPORTED_URI_SCHEME:
120540cb5e5dSvi 		return ("UNSUPPORTED_URI_SCHEME");
120640cb5e5dSvi 	case SIP_BAD_EXTENSION:
120740cb5e5dSvi 		return ("BAD_EXTENSION");
120840cb5e5dSvi 	case SIP_EXTENSION_REQUIRED:
120940cb5e5dSvi 		return ("EXTENSION_REQUIRED");
121040cb5e5dSvi 	case SIP_INTERVAL_2_BRIEF:
121140cb5e5dSvi 		return ("INTERVAL_2_BRIEF");
121240cb5e5dSvi 	case SIP_TEMPORARILY_UNAVAIL:
121340cb5e5dSvi 		return ("TEMPORARILY_UNAVAIL");
121440cb5e5dSvi 	case SIP_CALL_NON_EXISTANT:
121540cb5e5dSvi 		return ("CALL_NON_EXISTANT");
121640cb5e5dSvi 	case SIP_LOOP_DETECTED:
121740cb5e5dSvi 		return ("LOOP_DETECTED");
121840cb5e5dSvi 	case SIP_TOO_MANY_HOOPS:
121940cb5e5dSvi 		return ("TOO_MANY_HOOPS");
122040cb5e5dSvi 	case SIP_ADDRESS_INCOMPLETE:
122140cb5e5dSvi 		return ("ADDRESS_INCOMPLETE");
122240cb5e5dSvi 	case SIP_AMBIGUOUS:
122340cb5e5dSvi 		return ("AMBIGUOUS");
122440cb5e5dSvi 	case SIP_BUSY_HERE:
122540cb5e5dSvi 		return ("BUSY_HERE");
122640cb5e5dSvi 	case SIP_REQUEST_TERMINATED:
122740cb5e5dSvi 		return ("REQUEST_TERMINATED");
122840cb5e5dSvi 	case SIP_NOT_ACCEPTABLE_HERE:
122940cb5e5dSvi 		return ("NOT_ACCEPTABLE_HERE");
123040cb5e5dSvi 	case SIP_BAD_EVENT:
123140cb5e5dSvi 		return ("BAD_EVENT");
123240cb5e5dSvi 	case SIP_REQUEST_PENDING:
123340cb5e5dSvi 		return ("REQUEST_PENDING");
123440cb5e5dSvi 	case SIP_UNDECIPHERABLE:
123540cb5e5dSvi 		return ("UNDECIPHERABLE");
123640cb5e5dSvi 	case SIP_SERVER_INTERNAL_ERROR:
123740cb5e5dSvi 		return ("SERVER_INTERNAL_ERROR");
123840cb5e5dSvi 	case SIP_NOT_IMPLEMENTED:
123940cb5e5dSvi 		return ("NOT_IMPLEMENTED");
124040cb5e5dSvi 	case SIP_BAD_GATEWAY:
124140cb5e5dSvi 		return ("BAD_GATEWAY");
124240cb5e5dSvi 	case SIP_SERVICE_UNAVAILABLE:
124340cb5e5dSvi 		return ("SERVICE_UNAVAILABLE");
124440cb5e5dSvi 	case SIP_SERVER_TIMEOUT:
124540cb5e5dSvi 		return ("SERVER_TIMEOUT");
124640cb5e5dSvi 	case SIP_VERSION_NOT_SUPPORTED:
124740cb5e5dSvi 		return ("VERSION_NOT_SUPPORTED");
124840cb5e5dSvi 	case SIP_MESSAGE_2_LARGE:
124940cb5e5dSvi 		return ("MESSAGE_2_LARGE");
125040cb5e5dSvi 	case SIP_BUSY_EVERYWHERE:
125140cb5e5dSvi 		return ("BUSY_EVERYWHERE");
125240cb5e5dSvi 	case SIP_DECLINE:
125340cb5e5dSvi 		return ("DECLINE");
125440cb5e5dSvi 	case SIP_DOES_NOT_EXIST_ANYWHERE:
125540cb5e5dSvi 		return ("DOES_NOT_EXIST_ANYWHERE");
125640cb5e5dSvi 	case SIP_NOT_ACCEPTABLE_ANYWHERE:
125740cb5e5dSvi 		return ("NOT_ACCEPTABLE_ANYWHERE");
125840cb5e5dSvi 	default:
125940cb5e5dSvi 		return ("UNKNOWN");
126040cb5e5dSvi 	}
126140cb5e5dSvi }
126240cb5e5dSvi 
126340cb5e5dSvi /*
126440cb5e5dSvi  * The following three fns initialize and destroy the private library
126540cb5e5dSvi  * data in sip_conn_object_t. The assumption is that the 1st member
126640cb5e5dSvi  * of sip_conn_object_t is reserved for library use. The private data
126740cb5e5dSvi  * is used only for byte-stream protocols such as TCP to accumulate
126840cb5e5dSvi  * a complete SIP message, based on the CONTENT-LENGTH value, before
126940cb5e5dSvi  * processing it.
127040cb5e5dSvi  */
127140cb5e5dSvi int
sip_init_conn_object(sip_conn_object_t obj)127240cb5e5dSvi sip_init_conn_object(sip_conn_object_t obj)
127340cb5e5dSvi {
127440cb5e5dSvi 	void			**obj_val;
127540cb5e5dSvi 	sip_conn_obj_pvt_t	*pvt_data;
127640cb5e5dSvi 
127740cb5e5dSvi 	if (obj == NULL)
127840cb5e5dSvi 		return (EINVAL);
127940cb5e5dSvi 	pvt_data =  malloc(sizeof (sip_conn_obj_pvt_t));
128040cb5e5dSvi 	if (pvt_data == NULL)
128140cb5e5dSvi 		return (ENOMEM);
128240cb5e5dSvi 	pvt_data->sip_conn_obj_cache = NULL;
128340cb5e5dSvi 	pvt_data->sip_conn_obj_reass = malloc(sizeof (sip_reass_entry_t));
128440cb5e5dSvi 	if (pvt_data->sip_conn_obj_reass == NULL) {
128540cb5e5dSvi 		free(pvt_data);
128640cb5e5dSvi 		return (ENOMEM);
128740cb5e5dSvi 	}
128840cb5e5dSvi 	bzero(pvt_data->sip_conn_obj_reass, sizeof (sip_reass_entry_t));
128940cb5e5dSvi 	(void) pthread_mutex_init(&pvt_data->sip_conn_obj_reass_lock, NULL);
129040cb5e5dSvi 	(void) pthread_mutex_init(&pvt_data->sip_conn_obj_cache_lock, NULL);
129140cb5e5dSvi 	sip_refhold_conn(obj);
129240cb5e5dSvi 	obj_val = (void *)obj;
129340cb5e5dSvi 	*obj_val = (void *)pvt_data;
129440cb5e5dSvi 
129540cb5e5dSvi 	return (0);
129640cb5e5dSvi }
129740cb5e5dSvi 
129840cb5e5dSvi /*
129940cb5e5dSvi  * Clear private date, if any
130040cb5e5dSvi  */
130140cb5e5dSvi void
sip_clear_stale_data(sip_conn_object_t obj)130240cb5e5dSvi sip_clear_stale_data(sip_conn_object_t obj)
130340cb5e5dSvi {
130440cb5e5dSvi 	void			**obj_val;
130540cb5e5dSvi 	sip_conn_obj_pvt_t	*pvt_data;
130640cb5e5dSvi 	sip_reass_entry_t	*reass;
130740cb5e5dSvi 
130840cb5e5dSvi 	if (obj == NULL)
130940cb5e5dSvi 		return;
131040cb5e5dSvi 	obj_val = (void *)obj;
131140cb5e5dSvi 	pvt_data = (sip_conn_obj_pvt_t *)*obj_val;
131240cb5e5dSvi 	(void) pthread_mutex_lock(&pvt_data->sip_conn_obj_reass_lock);
131340cb5e5dSvi 	reass = pvt_data->sip_conn_obj_reass;
131440cb5e5dSvi 	if (reass->sip_reass_msg != NULL) {
131540cb5e5dSvi 		assert(reass->sip_reass_msglen > 0);
131640cb5e5dSvi 		free(reass->sip_reass_msg);
131740cb5e5dSvi 		reass->sip_reass_msglen = 0;
131840cb5e5dSvi 	}
131940cb5e5dSvi 	assert(reass->sip_reass_msglen == 0);
132040cb5e5dSvi 	(void) pthread_mutex_unlock(&pvt_data->sip_conn_obj_reass_lock);
132140cb5e5dSvi }
132240cb5e5dSvi 
132340cb5e5dSvi /*
132440cb5e5dSvi  * Walk through all the transactions, remove if this obj has been cached
132540cb5e5dSvi  * by any.
132640cb5e5dSvi  */
132740cb5e5dSvi void
sip_conn_destroyed(sip_conn_object_t obj)132840cb5e5dSvi sip_conn_destroyed(sip_conn_object_t obj)
132940cb5e5dSvi {
133040cb5e5dSvi 	void			**obj_val;
133140cb5e5dSvi 	sip_conn_obj_pvt_t	*pvt_data;
133240cb5e5dSvi 
133340cb5e5dSvi 	if (obj == NULL)
133440cb5e5dSvi 		return;
133540cb5e5dSvi 	obj_val = (void *)obj;
133640cb5e5dSvi 	pvt_data = (sip_conn_obj_pvt_t *)*obj_val;
133740cb5e5dSvi 
133840cb5e5dSvi 	sip_clear_stale_data(obj);
133940cb5e5dSvi 	free(pvt_data->sip_conn_obj_reass);
134040cb5e5dSvi 	pvt_data->sip_conn_obj_reass = NULL;
134140cb5e5dSvi 	(void) pthread_mutex_destroy(&pvt_data->sip_conn_obj_reass_lock);
134240cb5e5dSvi 
134340cb5e5dSvi 	sip_del_conn_obj_cache(obj, NULL);
134440cb5e5dSvi 	(void) pthread_mutex_destroy(&pvt_data->sip_conn_obj_cache_lock);
134540cb5e5dSvi 
134640cb5e5dSvi 	free(pvt_data);
134740cb5e5dSvi 	*obj_val = NULL;
134840cb5e5dSvi 	sip_refrele_conn(obj);
134940cb5e5dSvi }
1350