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