1*2882Svi117747 /*
2*2882Svi117747  * CDDL HEADER START
3*2882Svi117747  *
4*2882Svi117747  * The contents of this file are subject to the terms of the
5*2882Svi117747  * Common Development and Distribution License (the "License").
6*2882Svi117747  * You may not use this file except in compliance with the License.
7*2882Svi117747  *
8*2882Svi117747  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*2882Svi117747  * or http://www.opensolaris.org/os/licensing.
10*2882Svi117747  * See the License for the specific language governing permissions
11*2882Svi117747  * and limitations under the License.
12*2882Svi117747  *
13*2882Svi117747  * When distributing Covered Code, include this CDDL HEADER in each
14*2882Svi117747  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*2882Svi117747  * If applicable, add the following below this CDDL HEADER, with the
16*2882Svi117747  * fields enclosed by brackets "[]" replaced with your own identifying
17*2882Svi117747  * information: Portions Copyright [yyyy] [name of copyright owner]
18*2882Svi117747  *
19*2882Svi117747  * CDDL HEADER END
20*2882Svi117747  */
21*2882Svi117747 
22*2882Svi117747 /*
23*2882Svi117747  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
24*2882Svi117747  * Use is subject to license terms.
25*2882Svi117747  */
26*2882Svi117747 
27*2882Svi117747 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*2882Svi117747 
29*2882Svi117747 #include "sip_parse_uri.h"
30*2882Svi117747 #include "sip_msg.h"
31*2882Svi117747 #include "sip_miscdefs.h"
32*2882Svi117747 #include "sip_xaction.h"
33*2882Svi117747 
34*2882Svi117747 #define	SIP_BUF_SIZE	128
35*2882Svi117747 
36*2882Svi117747 /*
37*2882Svi117747  * Find the header named header, consecutive calls with old_header
38*2882Svi117747  * passed in will return next header of the same type.
39*2882Svi117747  * If no name is passed the first header is returned. consectutive calls
40*2882Svi117747  * with no name but an old header will return the next header.
41*2882Svi117747  */
42*2882Svi117747 const struct sip_header *
43*2882Svi117747 sip_get_header(sip_msg_t sip_msg, char *header_name, sip_header_t old_header,
44*2882Svi117747     int *error)
45*2882Svi117747 {
46*2882Svi117747 	_sip_msg_t		*_sip_msg;
47*2882Svi117747 	const struct sip_header	*sip_hdr;
48*2882Svi117747 
49*2882Svi117747 	if (error != NULL)
50*2882Svi117747 		*error = 0;
51*2882Svi117747 	if (sip_msg == NULL) {
52*2882Svi117747 		if (error != NULL)
53*2882Svi117747 			*error = EINVAL;
54*2882Svi117747 		return (NULL);
55*2882Svi117747 	}
56*2882Svi117747 	_sip_msg = (_sip_msg_t *)sip_msg;
57*2882Svi117747 	(void) pthread_mutex_lock(&_sip_msg->sip_msg_mutex);
58*2882Svi117747 	sip_hdr = (sip_header_t)sip_search_for_header((_sip_msg_t *)sip_msg,
59*2882Svi117747 	    header_name, (_sip_header_t *)old_header);
60*2882Svi117747 	(void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
61*2882Svi117747 	if (sip_hdr == NULL && error != NULL)
62*2882Svi117747 		*error = EINVAL;
63*2882Svi117747 	return (sip_hdr);
64*2882Svi117747 }
65*2882Svi117747 
66*2882Svi117747 /*
67*2882Svi117747  * Return the request line as a string. Caller releases the returned string.
68*2882Svi117747  */
69*2882Svi117747 char *
70*2882Svi117747 sip_reqline_to_str(sip_msg_t sip_msg, int *error)
71*2882Svi117747 {
72*2882Svi117747 	char	*reqstr;
73*2882Svi117747 
74*2882Svi117747 	if (error != NULL)
75*2882Svi117747 		*error = 0;
76*2882Svi117747 	if (sip_msg == NULL || !sip_msg_is_request(sip_msg, error)) {
77*2882Svi117747 		if (error != NULL)
78*2882Svi117747 			*error = EINVAL;
79*2882Svi117747 		return (NULL);
80*2882Svi117747 	}
81*2882Svi117747 	reqstr = _sip_startline_to_str((_sip_msg_t *)sip_msg, error);
82*2882Svi117747 	return (reqstr);
83*2882Svi117747 }
84*2882Svi117747 
85*2882Svi117747 /*
86*2882Svi117747  * Return the response line as a string. Caller releases the returned string.
87*2882Svi117747  */
88*2882Svi117747 char *
89*2882Svi117747 sip_respline_to_str(sip_msg_t sip_msg, int *error)
90*2882Svi117747 {
91*2882Svi117747 	char	*respstr;
92*2882Svi117747 
93*2882Svi117747 	if (error != NULL)
94*2882Svi117747 		*error = 0;
95*2882Svi117747 	if (sip_msg == NULL || sip_msg_is_request(sip_msg, error)) {
96*2882Svi117747 		if (error != NULL)
97*2882Svi117747 			*error = EINVAL;
98*2882Svi117747 		return (NULL);
99*2882Svi117747 	}
100*2882Svi117747 	respstr = _sip_startline_to_str((_sip_msg_t *)sip_msg, error);
101*2882Svi117747 	return (respstr);
102*2882Svi117747 }
103*2882Svi117747 
104*2882Svi117747 /*
105*2882Svi117747  * return the first value of the header
106*2882Svi117747  */
107*2882Svi117747 const struct sip_value *
108*2882Svi117747 sip_get_header_value(const struct sip_header *sip_header, int *error)
109*2882Svi117747 {
110*2882Svi117747 	_sip_header_t		*_sip_header;
111*2882Svi117747 	sip_parsed_header_t	*sip_parsed_header;
112*2882Svi117747 	int			ret = 0;
113*2882Svi117747 	const struct sip_value	*value;
114*2882Svi117747 
115*2882Svi117747 	if (error != NULL)
116*2882Svi117747 		*error = 0;
117*2882Svi117747 	if (sip_header == NULL) {
118*2882Svi117747 		if (error != NULL)
119*2882Svi117747 			*error = EINVAL;
120*2882Svi117747 		return (NULL);
121*2882Svi117747 	}
122*2882Svi117747 	_sip_header = (_sip_header_t *)sip_header;
123*2882Svi117747 	if (_sip_header->sip_hdr_sipmsg != NULL) {
124*2882Svi117747 		(void) pthread_mutex_lock(
125*2882Svi117747 		    &_sip_header->sip_hdr_sipmsg->sip_msg_mutex);
126*2882Svi117747 	}
127*2882Svi117747 	if (_sip_header->sip_header_state == SIP_HEADER_DELETED) {
128*2882Svi117747 		if (_sip_header->sip_hdr_sipmsg != NULL) {
129*2882Svi117747 			(void) pthread_mutex_unlock(
130*2882Svi117747 			    &_sip_header->sip_hdr_sipmsg->sip_msg_mutex);
131*2882Svi117747 		}
132*2882Svi117747 		if (error != NULL)
133*2882Svi117747 			*error = EINVAL;
134*2882Svi117747 		return (NULL);
135*2882Svi117747 	}
136*2882Svi117747 	ret = _sip_header->sip_header_functions->header_parse_func(
137*2882Svi117747 	    _sip_header, &sip_parsed_header);
138*2882Svi117747 	if (_sip_header->sip_hdr_sipmsg != NULL) {
139*2882Svi117747 		(void) pthread_mutex_unlock
140*2882Svi117747 		    (&_sip_header->sip_hdr_sipmsg->sip_msg_mutex);
141*2882Svi117747 	}
142*2882Svi117747 	if (error != NULL)
143*2882Svi117747 		*error = ret;
144*2882Svi117747 
145*2882Svi117747 	if (ret != 0)
146*2882Svi117747 		return (NULL);
147*2882Svi117747 	value = (sip_header_value_t)sip_parsed_header->value;
148*2882Svi117747 	while (value != NULL && value->value_state == SIP_VALUE_DELETED)
149*2882Svi117747 		value = value->next;
150*2882Svi117747 	if (value != NULL && value->value_state == SIP_VALUE_BAD &&
151*2882Svi117747 	    error != NULL) {
152*2882Svi117747 		*error = EPROTO;
153*2882Svi117747 	}
154*2882Svi117747 	return ((sip_header_value_t)value);
155*2882Svi117747 }
156*2882Svi117747 
157*2882Svi117747 /*
158*2882Svi117747  * Return the next value of the header.
159*2882Svi117747  */
160*2882Svi117747 const struct sip_value *
161*2882Svi117747 sip_get_next_value(sip_header_value_t old_value, int *error)
162*2882Svi117747 {
163*2882Svi117747 	const struct sip_value *value;
164*2882Svi117747 
165*2882Svi117747 	if (error != NULL)
166*2882Svi117747 		*error = 0;
167*2882Svi117747 	if (old_value == NULL || old_value->next == NULL) {
168*2882Svi117747 		if (error != NULL)
169*2882Svi117747 			*error = EINVAL;
170*2882Svi117747 		return (NULL);
171*2882Svi117747 	}
172*2882Svi117747 	/*
173*2882Svi117747 	 * We never free the deleted values so no need to hold a lock.
174*2882Svi117747 	 */
175*2882Svi117747 	value = (sip_header_value_t)old_value->next;
176*2882Svi117747 	while (value != NULL && value->value_state == SIP_VALUE_DELETED)
177*2882Svi117747 		value = value->next;
178*2882Svi117747 	if (value != NULL && value->value_state == SIP_VALUE_BAD &&
179*2882Svi117747 	    error != NULL) {
180*2882Svi117747 		*error = EPROTO;
181*2882Svi117747 	}
182*2882Svi117747 	return ((sip_header_value_t)value);
183*2882Svi117747 }
184*2882Svi117747 
185*2882Svi117747 /*
186*2882Svi117747  * Given a SIP message, delete the header "header_name".
187*2882Svi117747  */
188*2882Svi117747 int
189*2882Svi117747 sip_delete_header_by_name(sip_msg_t msg, char *header_name)
190*2882Svi117747 {
191*2882Svi117747 	_sip_msg_t	*_msg = (_sip_msg_t *)msg;
192*2882Svi117747 	sip_header_t	sip_hdr;
193*2882Svi117747 	_sip_header_t	*_sip_hdr;
194*2882Svi117747 
195*2882Svi117747 	if (_msg == NULL || header_name == NULL)
196*2882Svi117747 		return (EINVAL);
197*2882Svi117747 	(void) pthread_mutex_lock(&_msg->sip_msg_mutex);
198*2882Svi117747 	if (_msg->sip_msg_cannot_be_modified) {
199*2882Svi117747 		(void) pthread_mutex_unlock(&_msg->sip_msg_mutex);
200*2882Svi117747 		return (EPERM);
201*2882Svi117747 	}
202*2882Svi117747 	sip_hdr = (sip_header_t)sip_search_for_header(_msg, header_name, NULL);
203*2882Svi117747 	if (sip_hdr == NULL) {
204*2882Svi117747 		(void) pthread_mutex_unlock(&_msg->sip_msg_mutex);
205*2882Svi117747 		return (EINVAL);
206*2882Svi117747 	}
207*2882Svi117747 	_sip_hdr = (_sip_header_t *)sip_hdr;
208*2882Svi117747 	_sip_hdr->sip_header_state = SIP_HEADER_DELETED;
209*2882Svi117747 	_sip_hdr->sip_hdr_sipmsg->sip_msg_len -= _sip_hdr->sip_hdr_end -
210*2882Svi117747 	    _sip_hdr->sip_hdr_start;
211*2882Svi117747 	assert(_sip_hdr->sip_hdr_sipmsg->sip_msg_len >= 0);
212*2882Svi117747 	if (_msg->sip_msg_buf != NULL)
213*2882Svi117747 		_msg->sip_msg_modified = B_TRUE;
214*2882Svi117747 	(void) pthread_mutex_unlock(&_msg->sip_msg_mutex);
215*2882Svi117747 
216*2882Svi117747 	return (0);
217*2882Svi117747 }
218*2882Svi117747 
219*2882Svi117747 /*
220*2882Svi117747  * Mark the header as deleted.
221*2882Svi117747  */
222*2882Svi117747 int
223*2882Svi117747 sip_delete_header(sip_header_t sip_header)
224*2882Svi117747 {
225*2882Svi117747 	_sip_header_t	*_sip_header;
226*2882Svi117747 
227*2882Svi117747 	if (sip_header == NULL)
228*2882Svi117747 		return (EINVAL);
229*2882Svi117747 	_sip_header = (_sip_header_t *)sip_header;
230*2882Svi117747 	(void) pthread_mutex_lock(&_sip_header->sip_hdr_sipmsg->sip_msg_mutex);
231*2882Svi117747 	if (_sip_header->sip_hdr_sipmsg->sip_msg_cannot_be_modified) {
232*2882Svi117747 		(void) pthread_mutex_unlock
233*2882Svi117747 		    (&_sip_header->sip_hdr_sipmsg->sip_msg_mutex);
234*2882Svi117747 		return (EPERM);
235*2882Svi117747 	}
236*2882Svi117747 	if (_sip_header->sip_header_state == SIP_HEADER_DELETED) {
237*2882Svi117747 		(void) pthread_mutex_unlock(
238*2882Svi117747 		    &_sip_header->sip_hdr_sipmsg->sip_msg_mutex);
239*2882Svi117747 		return (EINVAL);
240*2882Svi117747 	}
241*2882Svi117747 	_sip_header->sip_header_state = SIP_HEADER_DELETED;
242*2882Svi117747 	_sip_header->sip_hdr_sipmsg->sip_msg_len -= _sip_header->sip_hdr_end -
243*2882Svi117747 	    _sip_header->sip_hdr_start;
244*2882Svi117747 	assert(_sip_header->sip_hdr_sipmsg->sip_msg_len >= 0);
245*2882Svi117747 	if (_sip_header->sip_hdr_sipmsg->sip_msg_buf != NULL)
246*2882Svi117747 		_sip_header->sip_hdr_sipmsg->sip_msg_modified = B_TRUE;
247*2882Svi117747 	(void) pthread_mutex_unlock
248*2882Svi117747 	    (&_sip_header->sip_hdr_sipmsg->sip_msg_mutex);
249*2882Svi117747 	return (0);
250*2882Svi117747 }
251*2882Svi117747 
252*2882Svi117747 /*
253*2882Svi117747  * Mark the value as deleted.
254*2882Svi117747  */
255*2882Svi117747 int
256*2882Svi117747 sip_delete_value(sip_header_t sip_header, sip_header_value_t sip_header_value)
257*2882Svi117747 {
258*2882Svi117747 	_sip_header_t	*_sip_header;
259*2882Svi117747 	sip_value_t	*_sip_header_value;
260*2882Svi117747 	int		vlen;
261*2882Svi117747 	char		*c;
262*2882Svi117747 
263*2882Svi117747 	if (sip_header == NULL || sip_header_value == NULL)
264*2882Svi117747 		return (EINVAL);
265*2882Svi117747 	_sip_header = (_sip_header_t *)sip_header;
266*2882Svi117747 	(void) pthread_mutex_lock(&_sip_header->sip_hdr_sipmsg->sip_msg_mutex);
267*2882Svi117747 	if (_sip_header->sip_hdr_sipmsg->sip_msg_cannot_be_modified) {
268*2882Svi117747 		(void) pthread_mutex_unlock(&_sip_header->
269*2882Svi117747 		    sip_hdr_sipmsg->sip_msg_mutex);
270*2882Svi117747 		return (EPERM);
271*2882Svi117747 	}
272*2882Svi117747 	if (_sip_header->sip_header_state == SIP_HEADER_DELETED) {
273*2882Svi117747 		(void) pthread_mutex_unlock(
274*2882Svi117747 		    &_sip_header->sip_hdr_sipmsg->sip_msg_mutex);
275*2882Svi117747 		return (EINVAL);
276*2882Svi117747 	}
277*2882Svi117747 	_sip_header_value = (sip_value_t *)sip_header_value;
278*2882Svi117747 	if (_sip_header_value->value_state == SIP_VALUE_DELETED) {
279*2882Svi117747 		(void) pthread_mutex_unlock(
280*2882Svi117747 		    &_sip_header->sip_hdr_sipmsg->sip_msg_mutex);
281*2882Svi117747 		return (EINVAL);
282*2882Svi117747 	}
283*2882Svi117747 	_sip_header->sip_header_state = SIP_HEADER_DELETED_VAL;
284*2882Svi117747 	_sip_header_value->value_state = SIP_VALUE_DELETED;
285*2882Svi117747 	vlen = _sip_header_value->value_end - _sip_header_value->value_start;
286*2882Svi117747 	if (_sip_header->sip_hdr_parsed->value == _sip_header_value) {
287*2882Svi117747 		c = _sip_header_value->value_start;
288*2882Svi117747 		while (*c-- != SIP_HCOLON)
289*2882Svi117747 			vlen++;
290*2882Svi117747 	} else {
291*2882Svi117747 		c = _sip_header_value->value_start;
292*2882Svi117747 		while (*c-- != SIP_COMMA)
293*2882Svi117747 			vlen++;
294*2882Svi117747 	}
295*2882Svi117747 	if (_sip_header_value->next == NULL) {
296*2882Svi117747 		sip_value_t	*value = _sip_header->sip_hdr_parsed->value;
297*2882Svi117747 		boolean_t	crlf_present =  B_FALSE;
298*2882Svi117747 		char		*s;
299*2882Svi117747 
300*2882Svi117747 		while (value != NULL && value != _sip_header_value) {
301*2882Svi117747 			crlf_present = B_FALSE;
302*2882Svi117747 
303*2882Svi117747 			if (value->value_state == SIP_VALUE_DELETED) {
304*2882Svi117747 				value = value->next;
305*2882Svi117747 				continue;
306*2882Svi117747 			}
307*2882Svi117747 			s = value->value_end;
308*2882Svi117747 			while (s != value->value_start) {
309*2882Svi117747 				if (*s == '\r' && strncmp(s, SIP_CRLF,
310*2882Svi117747 				    strlen(SIP_CRLF)) == 0) {
311*2882Svi117747 					crlf_present = B_TRUE;
312*2882Svi117747 					break;
313*2882Svi117747 				}
314*2882Svi117747 				s--;
315*2882Svi117747 			}
316*2882Svi117747 			value = value->next;
317*2882Svi117747 		}
318*2882Svi117747 		if (!crlf_present) {
319*2882Svi117747 			c = _sip_header_value->value_end;
320*2882Svi117747 			while (*c-- != '\r')
321*2882Svi117747 				vlen--;
322*2882Svi117747 			assert(vlen > 0);
323*2882Svi117747 		}
324*2882Svi117747 	}
325*2882Svi117747 	_sip_header->sip_hdr_sipmsg->sip_msg_len -= vlen;
326*2882Svi117747 	if (_sip_header->sip_hdr_sipmsg->sip_msg_buf != NULL)
327*2882Svi117747 		_sip_header->sip_hdr_sipmsg->sip_msg_modified = B_TRUE;
328*2882Svi117747 	(void) pthread_mutex_unlock
329*2882Svi117747 	    (&_sip_header->sip_hdr_sipmsg->sip_msg_mutex);
330*2882Svi117747 	return (0);
331*2882Svi117747 }
332*2882Svi117747 
333*2882Svi117747 /*
334*2882Svi117747  * Given a param list, check if a param name exists.
335*2882Svi117747  */
336*2882Svi117747 boolean_t
337*2882Svi117747 sip_is_param_present(const sip_param_t *param_list, char *param_name,
338*2882Svi117747     int param_len)
339*2882Svi117747 {
340*2882Svi117747 	const sip_param_t	*param = param_list;
341*2882Svi117747 
342*2882Svi117747 	while (param != NULL) {
343*2882Svi117747 		if (param->param_name.sip_str_len == param_len &&
344*2882Svi117747 		    strncasecmp(param->param_name.sip_str_ptr, param_name,
345*2882Svi117747 			param_len) == 0) {
346*2882Svi117747 			return (B_TRUE);
347*2882Svi117747 		}
348*2882Svi117747 		param = param->param_next;
349*2882Svi117747 	}
350*2882Svi117747 	return (B_FALSE);
351*2882Svi117747 }
352*2882Svi117747 
353*2882Svi117747 
354*2882Svi117747 /*
355*2882Svi117747  * Given a value header return the value of the named param.
356*2882Svi117747  */
357*2882Svi117747 const sip_str_t *
358*2882Svi117747 sip_get_param_value(sip_header_value_t header_value, char *param_name,
359*2882Svi117747     int *error)
360*2882Svi117747 {
361*2882Svi117747 	sip_value_t	*_sip_header_value;
362*2882Svi117747 	sip_param_t	*sip_param;
363*2882Svi117747 
364*2882Svi117747 	if (error != NULL)
365*2882Svi117747 		*error = 0;
366*2882Svi117747 	if (header_value == NULL || param_name == NULL) {
367*2882Svi117747 		if (error != NULL)
368*2882Svi117747 			*error = EINVAL;
369*2882Svi117747 		return (NULL);
370*2882Svi117747 	}
371*2882Svi117747 	_sip_header_value = (sip_value_t *)header_value;
372*2882Svi117747 	if (_sip_header_value->value_state == SIP_VALUE_DELETED) {
373*2882Svi117747 		if (error != NULL)
374*2882Svi117747 			*error = EINVAL;
375*2882Svi117747 		return (NULL);
376*2882Svi117747 	}
377*2882Svi117747 	if (_sip_header_value->param_list == NULL) {
378*2882Svi117747 		if (error != NULL)
379*2882Svi117747 			*error = EINVAL;
380*2882Svi117747 		return (NULL);
381*2882Svi117747 	}
382*2882Svi117747 	sip_param = sip_get_param_from_list(_sip_header_value->param_list,
383*2882Svi117747 	    param_name);
384*2882Svi117747 	if (sip_param != NULL)
385*2882Svi117747 		return (&sip_param->param_value);
386*2882Svi117747 	return (NULL);
387*2882Svi117747 }
388*2882Svi117747 
389*2882Svi117747 /*
390*2882Svi117747  * Return the list of params in the header
391*2882Svi117747  */
392*2882Svi117747 const sip_param_t *
393*2882Svi117747 sip_get_params(sip_header_value_t header_value, int *error)
394*2882Svi117747 {
395*2882Svi117747 	sip_value_t	*sip_header_value;
396*2882Svi117747 
397*2882Svi117747 	if (error != NULL)
398*2882Svi117747 		*error = 0;
399*2882Svi117747 	if (header_value == NULL) {
400*2882Svi117747 		if (error != NULL)
401*2882Svi117747 			*error = EINVAL;
402*2882Svi117747 		return (NULL);
403*2882Svi117747 	}
404*2882Svi117747 	sip_header_value = (sip_value_t *)header_value;
405*2882Svi117747 	if (sip_header_value->value_state == SIP_VALUE_DELETED) {
406*2882Svi117747 		if (error != NULL)
407*2882Svi117747 			*error = EINVAL;
408*2882Svi117747 		return (NULL);
409*2882Svi117747 	}
410*2882Svi117747 	return (sip_header_value->param_list);
411*2882Svi117747 }
412*2882Svi117747 
413*2882Svi117747 /*
414*2882Svi117747  * Return true if this is a SIP request
415*2882Svi117747  */
416*2882Svi117747 boolean_t
417*2882Svi117747 sip_msg_is_request(sip_msg_t sip_msg, int *error)
418*2882Svi117747 {
419*2882Svi117747 	_sip_msg_t		*_sip_msg;
420*2882Svi117747 	sip_message_type_t	*sip_msg_info;
421*2882Svi117747 	boolean_t		ret;
422*2882Svi117747 
423*2882Svi117747 	if (error != NULL)
424*2882Svi117747 		*error = 0;
425*2882Svi117747 	if (sip_msg == NULL) {
426*2882Svi117747 		if (error != NULL)
427*2882Svi117747 			*error = EINVAL;
428*2882Svi117747 		return (B_FALSE);
429*2882Svi117747 	}
430*2882Svi117747 	_sip_msg = (_sip_msg_t *)sip_msg;
431*2882Svi117747 	(void) pthread_mutex_lock(&_sip_msg->sip_msg_mutex);
432*2882Svi117747 	if (_sip_msg->sip_msg_req_res == NULL) {
433*2882Svi117747 		(void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
434*2882Svi117747 		if (error != NULL)
435*2882Svi117747 			*error = EINVAL;
436*2882Svi117747 		return (B_FALSE);
437*2882Svi117747 	}
438*2882Svi117747 	sip_msg_info = _sip_msg->sip_msg_req_res;
439*2882Svi117747 	ret = sip_msg_info->is_request;
440*2882Svi117747 	(void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
441*2882Svi117747 	return (ret);
442*2882Svi117747 }
443*2882Svi117747 
444*2882Svi117747 /*
445*2882Svi117747  * Return true if this is a SIP response
446*2882Svi117747  */
447*2882Svi117747 boolean_t
448*2882Svi117747 sip_msg_is_response(sip_msg_t sip_msg, int *error)
449*2882Svi117747 {
450*2882Svi117747 	boolean_t		is_resp;
451*2882Svi117747 	_sip_msg_t		*_sip_msg;
452*2882Svi117747 	sip_message_type_t	*sip_msg_info;
453*2882Svi117747 
454*2882Svi117747 	if (error != NULL)
455*2882Svi117747 		*error = 0;
456*2882Svi117747 	if (sip_msg == NULL) {
457*2882Svi117747 		if (error != NULL)
458*2882Svi117747 			*error = EINVAL;
459*2882Svi117747 		return (B_FALSE);
460*2882Svi117747 	}
461*2882Svi117747 	_sip_msg = (_sip_msg_t *)sip_msg;
462*2882Svi117747 	(void) pthread_mutex_lock(&_sip_msg->sip_msg_mutex);
463*2882Svi117747 	if (_sip_msg->sip_msg_req_res == NULL) {
464*2882Svi117747 		(void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
465*2882Svi117747 		if (error != NULL)
466*2882Svi117747 			*error = EINVAL;
467*2882Svi117747 		return (B_FALSE);
468*2882Svi117747 	}
469*2882Svi117747 	sip_msg_info = _sip_msg->sip_msg_req_res;
470*2882Svi117747 	is_resp = !sip_msg_info->is_request;
471*2882Svi117747 	(void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
472*2882Svi117747 	return (is_resp);
473*2882Svi117747 }
474*2882Svi117747 
475*2882Svi117747 /*
476*2882Svi117747  * Return the method in the request line
477*2882Svi117747  */
478*2882Svi117747 sip_method_t
479*2882Svi117747 sip_get_request_method(sip_msg_t sip_msg, int *error)
480*2882Svi117747 {
481*2882Svi117747 	_sip_msg_t		*_sip_msg;
482*2882Svi117747 	sip_message_type_t	*sip_msg_info;
483*2882Svi117747 	sip_method_t 		ret = -1;
484*2882Svi117747 
485*2882Svi117747 	if (error != NULL)
486*2882Svi117747 		*error = 0;
487*2882Svi117747 	if (sip_msg == NULL) {
488*2882Svi117747 		if (error != NULL)
489*2882Svi117747 			*error = EINVAL;
490*2882Svi117747 		return (ret);
491*2882Svi117747 	}
492*2882Svi117747 	_sip_msg = (_sip_msg_t *)sip_msg;
493*2882Svi117747 	(void) pthread_mutex_lock(&_sip_msg->sip_msg_mutex);
494*2882Svi117747 	sip_msg_info = _sip_msg->sip_msg_req_res;
495*2882Svi117747 	if (_sip_msg->sip_msg_req_res == NULL) {
496*2882Svi117747 		(void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
497*2882Svi117747 		if (error != NULL)
498*2882Svi117747 			*error = EINVAL;
499*2882Svi117747 		return (ret);
500*2882Svi117747 	}
501*2882Svi117747 	if (sip_msg_info->is_request)
502*2882Svi117747 		ret = sip_msg_info->sip_req_method;
503*2882Svi117747 	else if (error != NULL)
504*2882Svi117747 		*error = EINVAL;
505*2882Svi117747 	(void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
506*2882Svi117747 	return (ret);
507*2882Svi117747 }
508*2882Svi117747 
509*2882Svi117747 /*
510*2882Svi117747  * Return the URI from the request line
511*2882Svi117747  */
512*2882Svi117747 const sip_str_t *
513*2882Svi117747 sip_get_request_uri_str(sip_msg_t sip_msg, int *error)
514*2882Svi117747 {
515*2882Svi117747 	_sip_msg_t		*_sip_msg;
516*2882Svi117747 	sip_message_type_t	*sip_msg_info;
517*2882Svi117747 	sip_str_t 		*ret = NULL;
518*2882Svi117747 	struct sip_uri		*parsed_uri;
519*2882Svi117747 
520*2882Svi117747 	if (error != NULL)
521*2882Svi117747 		*error = 0;
522*2882Svi117747 	if (sip_msg == NULL) {
523*2882Svi117747 		if (error != NULL)
524*2882Svi117747 			*error = EINVAL;
525*2882Svi117747 		return (NULL);
526*2882Svi117747 	}
527*2882Svi117747 	_sip_msg = (_sip_msg_t *)sip_msg;
528*2882Svi117747 	(void) pthread_mutex_lock(&_sip_msg->sip_msg_mutex);
529*2882Svi117747 	if (_sip_msg->sip_msg_req_res == NULL) {
530*2882Svi117747 		(void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
531*2882Svi117747 		if (error != NULL)
532*2882Svi117747 			*error = EINVAL;
533*2882Svi117747 		return (NULL);
534*2882Svi117747 	}
535*2882Svi117747 	sip_msg_info = _sip_msg->sip_msg_req_res;
536*2882Svi117747 	if (sip_msg_info->is_request)
537*2882Svi117747 		ret = &sip_msg_info->sip_req_uri;
538*2882Svi117747 	(void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
539*2882Svi117747 
540*2882Svi117747 	/*
541*2882Svi117747 	 * If the error is required, check the validity of the URI via
542*2882Svi117747 	 * sip_uri_parse().
543*2882Svi117747 	 */
544*2882Svi117747 	if (error != NULL) {
545*2882Svi117747 		parsed_uri = sip_parse_uri(ret, error);
546*2882Svi117747 		if (parsed_uri != NULL)
547*2882Svi117747 			sip_free_parsed_uri((sip_uri_t)parsed_uri);
548*2882Svi117747 	}
549*2882Svi117747 	return (ret);
550*2882Svi117747 }
551*2882Svi117747 
552*2882Svi117747 /*
553*2882Svi117747  * Return the response code
554*2882Svi117747  */
555*2882Svi117747 int
556*2882Svi117747 sip_get_response_code(sip_msg_t sip_msg, int *error)
557*2882Svi117747 {
558*2882Svi117747 	_sip_msg_t		*_sip_msg;
559*2882Svi117747 	sip_message_type_t	*sip_msg_info;
560*2882Svi117747 	int 			ret = -1;
561*2882Svi117747 
562*2882Svi117747 	if (error != NULL)
563*2882Svi117747 		*error = 0;
564*2882Svi117747 	if (sip_msg == NULL) {
565*2882Svi117747 		if (error != NULL)
566*2882Svi117747 			*error = EINVAL;
567*2882Svi117747 		return (ret);
568*2882Svi117747 	}
569*2882Svi117747 	_sip_msg = (_sip_msg_t *)sip_msg;
570*2882Svi117747 	(void) pthread_mutex_lock(&_sip_msg->sip_msg_mutex);
571*2882Svi117747 	if (_sip_msg->sip_msg_req_res == NULL) {
572*2882Svi117747 		(void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
573*2882Svi117747 		if (error != NULL)
574*2882Svi117747 			*error = EINVAL;
575*2882Svi117747 		return (ret);
576*2882Svi117747 	}
577*2882Svi117747 	sip_msg_info = _sip_msg->sip_msg_req_res;
578*2882Svi117747 	if (!sip_msg_info->is_request)
579*2882Svi117747 		ret = sip_msg_info->sip_resp_code;
580*2882Svi117747 	else if (error != NULL)
581*2882Svi117747 		*error = EINVAL;
582*2882Svi117747 	(void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
583*2882Svi117747 	return (ret);
584*2882Svi117747 }
585*2882Svi117747 
586*2882Svi117747 /*
587*2882Svi117747  * Get the response phrase
588*2882Svi117747  */
589*2882Svi117747 const sip_str_t *
590*2882Svi117747 sip_get_response_phrase(sip_msg_t sip_msg, int *error)
591*2882Svi117747 {
592*2882Svi117747 	_sip_msg_t		*_sip_msg;
593*2882Svi117747 	sip_message_type_t	*sip_msg_info;
594*2882Svi117747 	sip_str_t 		*ret = NULL;
595*2882Svi117747 
596*2882Svi117747 	if (error != NULL)
597*2882Svi117747 		*error = 0;
598*2882Svi117747 	if (sip_msg == NULL) {
599*2882Svi117747 		if (error != NULL)
600*2882Svi117747 			*error = EINVAL;
601*2882Svi117747 		return (ret);
602*2882Svi117747 	}
603*2882Svi117747 	_sip_msg = (_sip_msg_t *)sip_msg;
604*2882Svi117747 	(void) pthread_mutex_lock(&_sip_msg->sip_msg_mutex);
605*2882Svi117747 	if (_sip_msg->sip_msg_req_res == NULL) {
606*2882Svi117747 		(void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
607*2882Svi117747 		if (error != NULL)
608*2882Svi117747 			*error = EINVAL;
609*2882Svi117747 		return (ret);
610*2882Svi117747 	}
611*2882Svi117747 	sip_msg_info = _sip_msg->sip_msg_req_res;
612*2882Svi117747 	(void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
613*2882Svi117747 	if (!sip_msg_info->is_request) {
614*2882Svi117747 		if (sip_msg_info->sip_resp_phrase_len == 0)
615*2882Svi117747 			ret = NULL;
616*2882Svi117747 		else
617*2882Svi117747 			ret = &sip_msg_info->sip_resp_phrase;
618*2882Svi117747 	} else if (error != NULL) {
619*2882Svi117747 		*error = EINVAL;
620*2882Svi117747 	}
621*2882Svi117747 	return (ret);
622*2882Svi117747 }
623*2882Svi117747 
624*2882Svi117747 /*
625*2882Svi117747  * Get the SIP version string
626*2882Svi117747  */
627*2882Svi117747 const sip_str_t *
628*2882Svi117747 sip_get_sip_version(sip_msg_t sip_msg, int *error)
629*2882Svi117747 {
630*2882Svi117747 	_sip_msg_t		*_sip_msg;
631*2882Svi117747 	sip_message_type_t	*sip_msg_info;
632*2882Svi117747 	sip_str_t		*ret = NULL;
633*2882Svi117747 
634*2882Svi117747 	if (error != NULL)
635*2882Svi117747 		*error = 0;
636*2882Svi117747 	if (sip_msg == NULL) {
637*2882Svi117747 		if (error != NULL)
638*2882Svi117747 			*error = EINVAL;
639*2882Svi117747 		return (ret);
640*2882Svi117747 	}
641*2882Svi117747 	_sip_msg = (_sip_msg_t *)sip_msg;
642*2882Svi117747 	(void) pthread_mutex_lock(&_sip_msg->sip_msg_mutex);
643*2882Svi117747 	if (_sip_msg->sip_msg_req_res == NULL) {
644*2882Svi117747 		(void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
645*2882Svi117747 		if (error != NULL)
646*2882Svi117747 			*error = EINVAL;
647*2882Svi117747 		return (ret);
648*2882Svi117747 	}
649*2882Svi117747 	sip_msg_info = _sip_msg->sip_msg_req_res;
650*2882Svi117747 	(void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
651*2882Svi117747 	ret = &sip_msg_info->sip_proto_version.version;
652*2882Svi117747 	return (ret);
653*2882Svi117747 }
654*2882Svi117747 
655*2882Svi117747 /*
656*2882Svi117747  * Return the length of the SIP message
657*2882Svi117747  */
658*2882Svi117747 int
659*2882Svi117747 sip_get_msg_len(sip_msg_t sip_msg, int *error)
660*2882Svi117747 {
661*2882Svi117747 	_sip_msg_t	*_sip_msg;
662*2882Svi117747 
663*2882Svi117747 	if (error != NULL)
664*2882Svi117747 		*error = 0;
665*2882Svi117747 	if (sip_msg == NULL) {
666*2882Svi117747 		if (error != NULL)
667*2882Svi117747 			*error = EINVAL;
668*2882Svi117747 		return (-1);
669*2882Svi117747 	}
670*2882Svi117747 	_sip_msg = (_sip_msg_t *)sip_msg;
671*2882Svi117747 
672*2882Svi117747 	return (_sip_msg->sip_msg_len);
673*2882Svi117747 }
674*2882Svi117747 
675*2882Svi117747 /*
676*2882Svi117747  * Get content as a string. Caller frees the string
677*2882Svi117747  */
678*2882Svi117747 char *
679*2882Svi117747 sip_get_content(sip_msg_t sip_msg, int *error)
680*2882Svi117747 {
681*2882Svi117747 	_sip_msg_t	*_sip_msg;
682*2882Svi117747 	sip_content_t	*sip_content;
683*2882Svi117747 	char		*content;
684*2882Svi117747 	int		len;
685*2882Svi117747 	char		*p;
686*2882Svi117747 
687*2882Svi117747 	if (error != NULL)
688*2882Svi117747 		*error = 0;
689*2882Svi117747 
690*2882Svi117747 	if (sip_msg == NULL) {
691*2882Svi117747 		if (error != NULL)
692*2882Svi117747 			*error = EINVAL;
693*2882Svi117747 		return (NULL);
694*2882Svi117747 	}
695*2882Svi117747 	_sip_msg = (_sip_msg_t *)sip_msg;
696*2882Svi117747 	(void) pthread_mutex_lock(&_sip_msg->sip_msg_mutex);
697*2882Svi117747 	if (_sip_msg->sip_msg_content == NULL) {
698*2882Svi117747 		(void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
699*2882Svi117747 		if (error != NULL)
700*2882Svi117747 			*error = EINVAL;
701*2882Svi117747 		return (NULL);
702*2882Svi117747 	}
703*2882Svi117747 	content = malloc(_sip_msg->sip_msg_content_len + 1);
704*2882Svi117747 	if (content == NULL) {
705*2882Svi117747 		(void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
706*2882Svi117747 		if (error != NULL)
707*2882Svi117747 			*error = ENOMEM;
708*2882Svi117747 		return (NULL);
709*2882Svi117747 	}
710*2882Svi117747 	p = content;
711*2882Svi117747 	sip_content = _sip_msg->sip_msg_content;
712*2882Svi117747 	while (sip_content != NULL) {
713*2882Svi117747 		len =  sip_content->sip_content_end -
714*2882Svi117747 		    sip_content->sip_content_start;
715*2882Svi117747 		(void) strncpy(p, sip_content->sip_content_start, len);
716*2882Svi117747 		p += len;
717*2882Svi117747 		sip_content = sip_content->sip_content_next;
718*2882Svi117747 	}
719*2882Svi117747 	content[_sip_msg->sip_msg_content_len] = '\0';
720*2882Svi117747 	(void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
721*2882Svi117747 	return (content);
722*2882Svi117747 }
723*2882Svi117747 
724*2882Svi117747 /*
725*2882Svi117747  * copy sip_header with param, if any, to sip_msg
726*2882Svi117747  */
727*2882Svi117747 int
728*2882Svi117747 sip_copy_header(sip_msg_t sip_msg, sip_header_t sip_header, char *param)
729*2882Svi117747 {
730*2882Svi117747 	_sip_msg_t	*_sip_msg;
731*2882Svi117747 	_sip_header_t	*_sip_header;
732*2882Svi117747 	int		ret;
733*2882Svi117747 
734*2882Svi117747 	if (sip_msg == NULL || sip_header == NULL)
735*2882Svi117747 		return (EINVAL);
736*2882Svi117747 	_sip_msg = (_sip_msg_t *)sip_msg;
737*2882Svi117747 	_sip_header = (_sip_header_t *)sip_header;
738*2882Svi117747 	(void) pthread_mutex_lock(&_sip_msg->sip_msg_mutex);
739*2882Svi117747 	if (_sip_msg->sip_msg_cannot_be_modified) {
740*2882Svi117747 		(void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
741*2882Svi117747 		return (EPERM);
742*2882Svi117747 	}
743*2882Svi117747 	if (_sip_header->sip_header_state == SIP_HEADER_DELETED) {
744*2882Svi117747 		(void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
745*2882Svi117747 		return (EINVAL);
746*2882Svi117747 	}
747*2882Svi117747 
748*2882Svi117747 	ret = _sip_copy_header(_sip_msg, _sip_header, param, B_TRUE);
749*2882Svi117747 	if (_sip_msg->sip_msg_buf != NULL)
750*2882Svi117747 		_sip_msg->sip_msg_modified = B_TRUE;
751*2882Svi117747 	(void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
752*2882Svi117747 	return (ret);
753*2882Svi117747 }
754*2882Svi117747 
755*2882Svi117747 /*
756*2882Svi117747  * copy the header specified by header_name, with param, if any
757*2882Svi117747  */
758*2882Svi117747 int
759*2882Svi117747 sip_copy_header_by_name(sip_msg_t old_msg, sip_msg_t new_msg,
760*2882Svi117747     char *header_name, char *param)
761*2882Svi117747 {
762*2882Svi117747 	int		ret;
763*2882Svi117747 	_sip_msg_t	*_old_msg = (_sip_msg_t *)old_msg;
764*2882Svi117747 	_sip_msg_t	*_new_msg = (_sip_msg_t *)new_msg;
765*2882Svi117747 
766*2882Svi117747 	if (_old_msg == NULL || _new_msg == NULL || header_name == NULL ||
767*2882Svi117747 	    _old_msg == _new_msg) {
768*2882Svi117747 		return (EINVAL);
769*2882Svi117747 	}
770*2882Svi117747 	(void) pthread_mutex_lock(&_new_msg->sip_msg_mutex);
771*2882Svi117747 	if (_new_msg->sip_msg_cannot_be_modified) {
772*2882Svi117747 		(void) pthread_mutex_unlock(&_new_msg->sip_msg_mutex);
773*2882Svi117747 		return (EPERM);
774*2882Svi117747 	}
775*2882Svi117747 
776*2882Svi117747 	(void) pthread_mutex_lock(&_old_msg->sip_msg_mutex);
777*2882Svi117747 	ret = _sip_find_and_copy_header(_old_msg, _new_msg, header_name, param,
778*2882Svi117747 	    B_FALSE);
779*2882Svi117747 	(void) pthread_mutex_unlock(&_old_msg->sip_msg_mutex);
780*2882Svi117747 	if (_new_msg->sip_msg_buf != NULL)
781*2882Svi117747 		_new_msg->sip_msg_modified = B_TRUE;
782*2882Svi117747 	(void) pthread_mutex_unlock(&_new_msg->sip_msg_mutex);
783*2882Svi117747 	return (ret);
784*2882Svi117747 }
785*2882Svi117747 
786*2882Svi117747 /*
787*2882Svi117747  * add the given header to sip_message
788*2882Svi117747  */
789*2882Svi117747 int
790*2882Svi117747 sip_add_header(sip_msg_t sip_msg, char *header_string)
791*2882Svi117747 {
792*2882Svi117747 	int		header_size;
793*2882Svi117747 	_sip_header_t	*new_header;
794*2882Svi117747 	_sip_msg_t	*_sip_msg;
795*2882Svi117747 
796*2882Svi117747 	if (sip_msg == NULL || header_string == NULL)
797*2882Svi117747 		return (EINVAL);
798*2882Svi117747 	_sip_msg = (_sip_msg_t *)sip_msg;
799*2882Svi117747 	(void) pthread_mutex_lock(&_sip_msg->sip_msg_mutex);
800*2882Svi117747 	if (_sip_msg->sip_msg_cannot_be_modified) {
801*2882Svi117747 		(void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
802*2882Svi117747 		return (EPERM);
803*2882Svi117747 	}
804*2882Svi117747 	header_size = strlen(header_string) + strlen(SIP_CRLF);
805*2882Svi117747 	new_header = sip_new_header(header_size);
806*2882Svi117747 	if (new_header == NULL) {
807*2882Svi117747 		(void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
808*2882Svi117747 		return (ENOMEM);
809*2882Svi117747 	}
810*2882Svi117747 
811*2882Svi117747 	(void) snprintf(new_header->sip_hdr_start, header_size + 1, "%s%s",
812*2882Svi117747 	    header_string, SIP_CRLF);
813*2882Svi117747 	_sip_add_header(_sip_msg, new_header, B_TRUE, B_FALSE, NULL);
814*2882Svi117747 	if (_sip_msg->sip_msg_buf != NULL)
815*2882Svi117747 		_sip_msg->sip_msg_modified = B_TRUE;
816*2882Svi117747 	(void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
817*2882Svi117747 	return (0);
818*2882Svi117747 }
819*2882Svi117747 
820*2882Svi117747 /*
821*2882Svi117747  * add the given param to the sip_header. create a new header with the param
822*2882Svi117747  * and mark the old header as deleted.
823*2882Svi117747  */
824*2882Svi117747 sip_header_t
825*2882Svi117747 sip_add_param(sip_header_t sip_header, char *param, int *error)
826*2882Svi117747 {
827*2882Svi117747 	_sip_header_t	*_sip_header;
828*2882Svi117747 	_sip_header_t	*new_header;
829*2882Svi117747 	int		hdrlen;
830*2882Svi117747 	_sip_msg_t	*_sip_msg;
831*2882Svi117747 	int		param_len;
832*2882Svi117747 	char		*tmp_ptr;
833*2882Svi117747 
834*2882Svi117747 	if (error != NULL)
835*2882Svi117747 		*error = 0;
836*2882Svi117747 
837*2882Svi117747 	if (param == NULL || sip_header == NULL) {
838*2882Svi117747 		if (error != NULL)
839*2882Svi117747 			*error = EINVAL;
840*2882Svi117747 		return (NULL);
841*2882Svi117747 	}
842*2882Svi117747 
843*2882Svi117747 	_sip_header = (_sip_header_t *)sip_header;
844*2882Svi117747 
845*2882Svi117747 	(void) pthread_mutex_lock(&_sip_header->sip_hdr_sipmsg->sip_msg_mutex);
846*2882Svi117747 	if (_sip_header->sip_hdr_sipmsg->sip_msg_cannot_be_modified) {
847*2882Svi117747 		if (error != NULL)
848*2882Svi117747 			*error = EPERM;
849*2882Svi117747 		(void) pthread_mutex_unlock(
850*2882Svi117747 		    &_sip_header->sip_hdr_sipmsg->sip_msg_mutex);
851*2882Svi117747 		return (NULL);
852*2882Svi117747 	}
853*2882Svi117747 	if (_sip_header->sip_header_state == SIP_HEADER_DELETED) {
854*2882Svi117747 		if (error != NULL)
855*2882Svi117747 			*error = EINVAL;
856*2882Svi117747 		(void) pthread_mutex_unlock(
857*2882Svi117747 		    &_sip_header->sip_hdr_sipmsg->sip_msg_mutex);
858*2882Svi117747 		return (NULL);
859*2882Svi117747 	}
860*2882Svi117747 
861*2882Svi117747 	param_len = SIP_SPACE_LEN + sizeof (char) + SIP_SPACE_LEN +
862*2882Svi117747 	    strlen(param);
863*2882Svi117747 	hdrlen = _sip_header->sip_hdr_end - _sip_header->sip_hdr_start;
864*2882Svi117747 	new_header = sip_new_header(hdrlen + param_len);
865*2882Svi117747 	if (new_header == NULL) {
866*2882Svi117747 		if (error != NULL)
867*2882Svi117747 			*error = ENOMEM;
868*2882Svi117747 		(void) pthread_mutex_unlock(
869*2882Svi117747 		    &_sip_header->sip_hdr_sipmsg->sip_msg_mutex);
870*2882Svi117747 		return (NULL);
871*2882Svi117747 	}
872*2882Svi117747 	(void) memcpy(new_header->sip_hdr_start, _sip_header->sip_hdr_start,
873*2882Svi117747 	    hdrlen);
874*2882Svi117747 	new_header->sip_hdr_end = new_header->sip_hdr_start + hdrlen;
875*2882Svi117747 	hdrlen = param_len + 1;
876*2882Svi117747 	/*
877*2882Svi117747 	 * Find CRLF
878*2882Svi117747 	 */
879*2882Svi117747 	tmp_ptr = new_header->sip_hdr_end;
880*2882Svi117747 	while (*tmp_ptr-- != '\n') {
881*2882Svi117747 		hdrlen++;
882*2882Svi117747 		if (tmp_ptr == new_header->sip_hdr_start) {
883*2882Svi117747 			sip_free_header(new_header);
884*2882Svi117747 			if (error != NULL)
885*2882Svi117747 				*error = EINVAL;
886*2882Svi117747 			(void) pthread_mutex_unlock(
887*2882Svi117747 			    &_sip_header->sip_hdr_sipmsg->sip_msg_mutex);
888*2882Svi117747 			return (NULL);
889*2882Svi117747 		}
890*2882Svi117747 	}
891*2882Svi117747 	(void) snprintf(tmp_ptr, hdrlen + 1,
892*2882Svi117747 	    " %c %s%s", SIP_SEMI, param, SIP_CRLF);
893*2882Svi117747 	new_header->sip_hdr_end += param_len;
894*2882Svi117747 	new_header->sip_header_functions = _sip_header->sip_header_functions;
895*2882Svi117747 	_sip_msg = _sip_header->sip_hdr_sipmsg;
896*2882Svi117747 	_sip_add_header(_sip_msg, new_header, B_TRUE, B_FALSE, NULL);
897*2882Svi117747 	if (_sip_header->sip_hdr_sipmsg->sip_msg_buf != NULL)
898*2882Svi117747 		_sip_header->sip_hdr_sipmsg->sip_msg_modified = B_TRUE;
899*2882Svi117747 	(void) pthread_mutex_unlock(&new_header->sip_hdr_sipmsg->sip_msg_mutex);
900*2882Svi117747 	(void) sip_delete_header(sip_header);
901*2882Svi117747 	return ((sip_header_t)new_header);
902*2882Svi117747 }
903*2882Svi117747 
904*2882Svi117747 /*
905*2882Svi117747  * Get Request URI
906*2882Svi117747  */
907*2882Svi117747 const struct sip_uri *
908*2882Svi117747 sip_get_request_uri(sip_msg_t sip_msg, int *error)
909*2882Svi117747 {
910*2882Svi117747 	_sip_msg_t		*_sip_msg;
911*2882Svi117747 	sip_message_type_t	*sip_msg_info;
912*2882Svi117747 	const struct sip_uri	*ret = NULL;
913*2882Svi117747 
914*2882Svi117747 	if (error != NULL)
915*2882Svi117747 		*error = 0;
916*2882Svi117747 
917*2882Svi117747 	if (sip_msg == NULL) {
918*2882Svi117747 		if (error != NULL)
919*2882Svi117747 			*error = EINVAL;
920*2882Svi117747 		return (NULL);
921*2882Svi117747 	}
922*2882Svi117747 	_sip_msg = (_sip_msg_t *)sip_msg;
923*2882Svi117747 	(void) pthread_mutex_lock(&_sip_msg->sip_msg_mutex);
924*2882Svi117747 	sip_msg_info = _sip_msg->sip_msg_req_res;
925*2882Svi117747 	if (sip_msg_info != NULL && sip_msg_info->is_request) {
926*2882Svi117747 		ret = sip_msg_info->sip_req_parse_uri;
927*2882Svi117747 	} else {
928*2882Svi117747 		if (error != NULL)
929*2882Svi117747 			*error = EINVAL;
930*2882Svi117747 	}
931*2882Svi117747 	(void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
932*2882Svi117747 
933*2882Svi117747 	if (ret != NULL) {
934*2882Svi117747 		if (ret->sip_uri_scheme.sip_str_len == 0 ||
935*2882Svi117747 		    ret->sip_uri_scheme.sip_str_ptr == NULL) {
936*2882Svi117747 			ret = NULL;
937*2882Svi117747 			if (error != NULL)
938*2882Svi117747 				*error = EINVAL;
939*2882Svi117747 		} else if (ret->sip_uri_errflags != 0 && error != NULL) {
940*2882Svi117747 			*error = EINVAL;
941*2882Svi117747 		}
942*2882Svi117747 	}
943*2882Svi117747 	return ((sip_uri_t)ret);
944*2882Svi117747 }
945*2882Svi117747 
946*2882Svi117747 /*
947*2882Svi117747  * returns a comma separated string of all the sent-by values registered by
948*2882Svi117747  * the UA.
949*2882Svi117747  */
950*2882Svi117747 char *
951*2882Svi117747 sip_sent_by_to_str(int *error)
952*2882Svi117747 {
953*2882Svi117747 	sent_by_list_t	*sb;
954*2882Svi117747 	int		sb_len = 0;
955*2882Svi117747 	int		slen;
956*2882Svi117747 	char		*sb_str;
957*2882Svi117747 	char		*p;
958*2882Svi117747 	int		count = 0;
959*2882Svi117747 	int		cnt = 0;
960*2882Svi117747 
961*2882Svi117747 	if (error != NULL)
962*2882Svi117747 		*error = 0;
963*2882Svi117747 
964*2882Svi117747 	(void) pthread_mutex_lock(&sip_sent_by_lock);
965*2882Svi117747 	if (sip_sent_by == NULL) {
966*2882Svi117747 		(void) pthread_mutex_unlock(&sip_sent_by_lock);
967*2882Svi117747 		return (NULL);
968*2882Svi117747 	}
969*2882Svi117747 	sb = sip_sent_by;
970*2882Svi117747 	for (cnt = 0; cnt < sip_sent_by_count; cnt++) {
971*2882Svi117747 		sb_len += strlen(sb->sb_val);
972*2882Svi117747 		sb = sb->sb_next;
973*2882Svi117747 	}
974*2882Svi117747 	/*
975*2882Svi117747 	 * for the commas
976*2882Svi117747 	 */
977*2882Svi117747 	sb_len += sip_sent_by_count - 1;
978*2882Svi117747 	sb_str = malloc(sb_len + 1);
979*2882Svi117747 	if (sb_str == NULL) {
980*2882Svi117747 		if (error != NULL)
981*2882Svi117747 			*error = ENOMEM;
982*2882Svi117747 		(void) pthread_mutex_unlock(&sip_sent_by_lock);
983*2882Svi117747 		return (NULL);
984*2882Svi117747 	}
985*2882Svi117747 	sb = sip_sent_by;
986*2882Svi117747 	p = sb_str;
987*2882Svi117747 	slen = sb_len + 1;
988*2882Svi117747 	for (cnt = 0; cnt < sip_sent_by_count; cnt++) {
989*2882Svi117747 		if (cnt == 0) {
990*2882Svi117747 			count = snprintf(p, slen, "%s", sb->sb_val);
991*2882Svi117747 		} else {
992*2882Svi117747 			count = snprintf(p, slen, "%c%s", SIP_COMMA,
993*2882Svi117747 			    sb->sb_val);
994*2882Svi117747 		}
995*2882Svi117747 		p += count;
996*2882Svi117747 		slen -= count;
997*2882Svi117747 		sb = sb->sb_next;
998*2882Svi117747 	}
999*2882Svi117747 	sb_str[sb_len] = '\0';
1000*2882Svi117747 	(void) pthread_mutex_unlock(&sip_sent_by_lock);
1001*2882Svi117747 	return (sb_str);
1002*2882Svi117747 }
1003*2882Svi117747 
1004*2882Svi117747 /*
1005*2882Svi117747  * A comma separated list of sent-by values.
1006*2882Svi117747  */
1007*2882Svi117747 int
1008*2882Svi117747 sip_register_sent_by(char *val)
1009*2882Svi117747 {
1010*2882Svi117747 	sent_by_list_t	*sb = NULL;
1011*2882Svi117747 	sent_by_list_t	*sb_tail = NULL;
1012*2882Svi117747 	char		*str;
1013*2882Svi117747 	int		count = 0;
1014*2882Svi117747 
1015*2882Svi117747 	if (val == NULL)
1016*2882Svi117747 		return (EINVAL);
1017*2882Svi117747 	str = strtok(val, ",");
1018*2882Svi117747 	while (str != NULL) {
1019*2882Svi117747 		int	slen;
1020*2882Svi117747 		char	*start = str;
1021*2882Svi117747 		char	*end = str + strlen(str) - 1;
1022*2882Svi117747 
1023*2882Svi117747 		while (isspace(*start))
1024*2882Svi117747 			start++;
1025*2882Svi117747 		while (isspace(*end))
1026*2882Svi117747 			end--;
1027*2882Svi117747 		if (end <= start)
1028*2882Svi117747 			goto err_ret;
1029*2882Svi117747 		slen = end - start + 1;
1030*2882Svi117747 		sb_tail = (sent_by_list_t *)malloc(sizeof (*sb_tail));
1031*2882Svi117747 		if (sb_tail == NULL)
1032*2882Svi117747 			goto err_ret;
1033*2882Svi117747 		sb_tail->sb_next = sb_tail->sb_prev = NULL;
1034*2882Svi117747 		if ((sb_tail->sb_val = (char *)malloc(slen + 1)) == NULL) {
1035*2882Svi117747 			free(sb_tail);
1036*2882Svi117747 			goto err_ret;
1037*2882Svi117747 		}
1038*2882Svi117747 		(void) strncpy(sb_tail->sb_val, start, slen);
1039*2882Svi117747 		sb_tail->sb_val[slen] = '\0';
1040*2882Svi117747 		if (sb == NULL) {
1041*2882Svi117747 			sb = sb_tail;
1042*2882Svi117747 		} else {
1043*2882Svi117747 			sb_tail->sb_next = sb;
1044*2882Svi117747 			sb->sb_prev = sb_tail;
1045*2882Svi117747 			sb = sb_tail;
1046*2882Svi117747 		}
1047*2882Svi117747 		count++;
1048*2882Svi117747 		str = strtok(NULL, ",");
1049*2882Svi117747 	}
1050*2882Svi117747 	sb_tail = sb;
1051*2882Svi117747 	while (sb_tail->sb_next != NULL)
1052*2882Svi117747 		sb_tail = sb_tail->sb_next;
1053*2882Svi117747 	(void) pthread_mutex_lock(&sip_sent_by_lock);
1054*2882Svi117747 	if (sip_sent_by != NULL) {
1055*2882Svi117747 		sb_tail->sb_next = sip_sent_by;
1056*2882Svi117747 		sip_sent_by->sb_prev = sb_tail;
1057*2882Svi117747 	}
1058*2882Svi117747 	sip_sent_by = sb;
1059*2882Svi117747 	sip_sent_by_count += count;
1060*2882Svi117747 	(void) pthread_mutex_unlock(&sip_sent_by_lock);
1061*2882Svi117747 	return (0);
1062*2882Svi117747 err_ret:
1063*2882Svi117747 	sb_tail = sb;
1064*2882Svi117747 	for (; count > 0; count--) {
1065*2882Svi117747 		sb = sb_tail->sb_next;
1066*2882Svi117747 		free(sb_tail->sb_val);
1067*2882Svi117747 		sb_tail->sb_next = NULL;
1068*2882Svi117747 		sb_tail->sb_prev = NULL;
1069*2882Svi117747 		free(sb_tail);
1070*2882Svi117747 		sb_tail = sb;
1071*2882Svi117747 	}
1072*2882Svi117747 	return (EINVAL);
1073*2882Svi117747 }
1074*2882Svi117747 
1075*2882Svi117747 /*
1076*2882Svi117747  * Un-register sent-by values; 'val' contains a comma separated list
1077*2882Svi117747  */
1078*2882Svi117747 void
1079*2882Svi117747 sip_unregister_sent_by(char *val)
1080*2882Svi117747 {
1081*2882Svi117747 	sent_by_list_t	*sb;
1082*2882Svi117747 	char		*str;
1083*2882Svi117747 	int		count = 0;
1084*2882Svi117747 
1085*2882Svi117747 	(void) pthread_mutex_lock(&sip_sent_by_lock);
1086*2882Svi117747 	str = strtok(val, ",");
1087*2882Svi117747 	while (str != NULL) {
1088*2882Svi117747 		sb = sip_sent_by;
1089*2882Svi117747 		for (count = 0; count < sip_sent_by_count; count++) {
1090*2882Svi117747 			if (strncmp(sb->sb_val, str, strlen(str)) == 0) {
1091*2882Svi117747 				if (sb == sip_sent_by) {
1092*2882Svi117747 					if (sb->sb_next != NULL)
1093*2882Svi117747 						sip_sent_by = sb->sb_next;
1094*2882Svi117747 					else
1095*2882Svi117747 						sip_sent_by = NULL;
1096*2882Svi117747 				} else if (sb->sb_next == NULL) {
1097*2882Svi117747 					sb->sb_prev->sb_next = NULL;
1098*2882Svi117747 				} else {
1099*2882Svi117747 					sb->sb_prev->sb_next = sb->sb_next;
1100*2882Svi117747 					sb->sb_next->sb_prev = sb->sb_prev;
1101*2882Svi117747 				}
1102*2882Svi117747 				sip_sent_by_count--;
1103*2882Svi117747 				sb->sb_next = NULL;
1104*2882Svi117747 				sb->sb_prev = NULL;
1105*2882Svi117747 				free(sb->sb_val);
1106*2882Svi117747 				free(sb);
1107*2882Svi117747 				break;
1108*2882Svi117747 			}
1109*2882Svi117747 			sb = sb->sb_next;
1110*2882Svi117747 		}
1111*2882Svi117747 		str = strtok(NULL, ",");
1112*2882Svi117747 	}
1113*2882Svi117747 	(void) pthread_mutex_unlock(&sip_sent_by_lock);
1114*2882Svi117747 }
1115*2882Svi117747 
1116*2882Svi117747 /*
1117*2882Svi117747  * Un-register all the sent-by values
1118*2882Svi117747  */
1119*2882Svi117747 void
1120*2882Svi117747 sip_unregister_all_sent_by()
1121*2882Svi117747 {
1122*2882Svi117747 	sent_by_list_t	*sb;
1123*2882Svi117747 	int		count;
1124*2882Svi117747 
1125*2882Svi117747 	(void) pthread_mutex_lock(&sip_sent_by_lock);
1126*2882Svi117747 	sb = sip_sent_by;
1127*2882Svi117747 	for (count = 0; count < sip_sent_by_count; count++) {
1128*2882Svi117747 		sip_sent_by = sb->sb_next;
1129*2882Svi117747 		free(sb->sb_val);
1130*2882Svi117747 		sb->sb_next = NULL;
1131*2882Svi117747 		sb->sb_prev = NULL;
1132*2882Svi117747 		free(sb);
1133*2882Svi117747 		sb = sip_sent_by;
1134*2882Svi117747 	}
1135*2882Svi117747 	sip_sent_by = NULL;
1136*2882Svi117747 	sip_sent_by_count = 0;
1137*2882Svi117747 	(void) pthread_mutex_unlock(&sip_sent_by_lock);
1138*2882Svi117747 }
1139*2882Svi117747 
1140*2882Svi117747 /*
1141*2882Svi117747  * Given a response code, return the corresponding phrase
1142*2882Svi117747  */
1143*2882Svi117747 char *
1144*2882Svi117747 sip_get_resp_desc(int resp_code)
1145*2882Svi117747 {
1146*2882Svi117747 	switch (resp_code) {
1147*2882Svi117747 	case SIP_TRYING:
1148*2882Svi117747 		return ("TRYING");
1149*2882Svi117747 	case SIP_RINGING:
1150*2882Svi117747 		return ("RINGING");
1151*2882Svi117747 	case SIP_CALL_IS_BEING_FORWARDED:
1152*2882Svi117747 		return ("CALL_IS_BEING_FORWARDED");
1153*2882Svi117747 	case SIP_QUEUED:
1154*2882Svi117747 		return ("QUEUED");
1155*2882Svi117747 	case SIP_SESSION_PROGRESS:
1156*2882Svi117747 		return ("SESSION_PROGRESS");
1157*2882Svi117747 	case SIP_OK:
1158*2882Svi117747 		return ("OK");
1159*2882Svi117747 	case SIP_ACCEPTED:
1160*2882Svi117747 		return ("ACCEPTED");
1161*2882Svi117747 	case SIP_MULTIPLE_CHOICES:
1162*2882Svi117747 		return ("MULTIPLE_CHOICES");
1163*2882Svi117747 	case SIP_MOVED_PERMANENTLY:
1164*2882Svi117747 		return ("MOVED_PERMANENTLY");
1165*2882Svi117747 	case SIP_MOVED_TEMPORARILY:
1166*2882Svi117747 		return ("MOVED_TEMPORARILY");
1167*2882Svi117747 	case SIP_USE_PROXY:
1168*2882Svi117747 		return ("USE_PROXY");
1169*2882Svi117747 	case SIP_ALTERNATIVE_SERVICE:
1170*2882Svi117747 		return ("ALTERNATIVE_SERVICE");
1171*2882Svi117747 	case SIP_BAD_REQUEST:
1172*2882Svi117747 		return ("BAD_REQUEST");
1173*2882Svi117747 	case SIP_UNAUTHORIZED:
1174*2882Svi117747 		return ("UNAUTHORIZED");
1175*2882Svi117747 	case SIP_PAYMENT_REQUIRED:
1176*2882Svi117747 		return ("PAYMENT_REQUIRED");
1177*2882Svi117747 	case SIP_FORBIDDEN:
1178*2882Svi117747 		return ("FORBIDDEN");
1179*2882Svi117747 	case SIP_NOT_FOUND:
1180*2882Svi117747 		return ("NOT_FOUND");
1181*2882Svi117747 	case SIP_METHOD_NOT_ALLOWED:
1182*2882Svi117747 		return ("METHOD_NOT_ALLOWED");
1183*2882Svi117747 	case SIP_NOT_ACCEPTABLE:
1184*2882Svi117747 		return ("NOT_ACCEPTABLE");
1185*2882Svi117747 	case SIP_PROXY_AUTH_REQUIRED:
1186*2882Svi117747 		return ("PROXY_AUTH_REQUIRED");
1187*2882Svi117747 	case SIP_REQUEST_TIMEOUT:
1188*2882Svi117747 		return ("REQUEST_TIMEOUT");
1189*2882Svi117747 	case SIP_GONE:
1190*2882Svi117747 		return ("GONE");
1191*2882Svi117747 	case SIP_REQUEST_ENTITY_2_LARGE:
1192*2882Svi117747 		return ("REQUEST_ENTITY_2_LARGE");
1193*2882Svi117747 	case SIP_REQUEST_URI_2_LONG:
1194*2882Svi117747 		return ("REQUEST_URI_2_LONG");
1195*2882Svi117747 	case SIP_UNSUPPORTED_MEDIA_TYPE:
1196*2882Svi117747 		return ("UNSUPPORTED_MEDIA_TYPE");
1197*2882Svi117747 	case SIP_UNSUPPORTED_URI_SCHEME:
1198*2882Svi117747 		return ("UNSUPPORTED_URI_SCHEME");
1199*2882Svi117747 	case SIP_BAD_EXTENSION:
1200*2882Svi117747 		return ("BAD_EXTENSION");
1201*2882Svi117747 	case SIP_EXTENSION_REQUIRED:
1202*2882Svi117747 		return ("EXTENSION_REQUIRED");
1203*2882Svi117747 	case SIP_INTERVAL_2_BRIEF:
1204*2882Svi117747 		return ("INTERVAL_2_BRIEF");
1205*2882Svi117747 	case SIP_TEMPORARILY_UNAVAIL:
1206*2882Svi117747 		return ("TEMPORARILY_UNAVAIL");
1207*2882Svi117747 	case SIP_CALL_NON_EXISTANT:
1208*2882Svi117747 		return ("CALL_NON_EXISTANT");
1209*2882Svi117747 	case SIP_LOOP_DETECTED:
1210*2882Svi117747 		return ("LOOP_DETECTED");
1211*2882Svi117747 	case SIP_TOO_MANY_HOOPS:
1212*2882Svi117747 		return ("TOO_MANY_HOOPS");
1213*2882Svi117747 	case SIP_ADDRESS_INCOMPLETE:
1214*2882Svi117747 		return ("ADDRESS_INCOMPLETE");
1215*2882Svi117747 	case SIP_AMBIGUOUS:
1216*2882Svi117747 		return ("AMBIGUOUS");
1217*2882Svi117747 	case SIP_BUSY_HERE:
1218*2882Svi117747 		return ("BUSY_HERE");
1219*2882Svi117747 	case SIP_REQUEST_TERMINATED:
1220*2882Svi117747 		return ("REQUEST_TERMINATED");
1221*2882Svi117747 	case SIP_NOT_ACCEPTABLE_HERE:
1222*2882Svi117747 		return ("NOT_ACCEPTABLE_HERE");
1223*2882Svi117747 	case SIP_BAD_EVENT:
1224*2882Svi117747 		return ("BAD_EVENT");
1225*2882Svi117747 	case SIP_REQUEST_PENDING:
1226*2882Svi117747 		return ("REQUEST_PENDING");
1227*2882Svi117747 	case SIP_UNDECIPHERABLE:
1228*2882Svi117747 		return ("UNDECIPHERABLE");
1229*2882Svi117747 	case SIP_SERVER_INTERNAL_ERROR:
1230*2882Svi117747 		return ("SERVER_INTERNAL_ERROR");
1231*2882Svi117747 	case SIP_NOT_IMPLEMENTED:
1232*2882Svi117747 		return ("NOT_IMPLEMENTED");
1233*2882Svi117747 	case SIP_BAD_GATEWAY:
1234*2882Svi117747 		return ("BAD_GATEWAY");
1235*2882Svi117747 	case SIP_SERVICE_UNAVAILABLE:
1236*2882Svi117747 		return ("SERVICE_UNAVAILABLE");
1237*2882Svi117747 	case SIP_SERVER_TIMEOUT:
1238*2882Svi117747 		return ("SERVER_TIMEOUT");
1239*2882Svi117747 	case SIP_VERSION_NOT_SUPPORTED:
1240*2882Svi117747 		return ("VERSION_NOT_SUPPORTED");
1241*2882Svi117747 	case SIP_MESSAGE_2_LARGE:
1242*2882Svi117747 		return ("MESSAGE_2_LARGE");
1243*2882Svi117747 	case SIP_BUSY_EVERYWHERE:
1244*2882Svi117747 		return ("BUSY_EVERYWHERE");
1245*2882Svi117747 	case SIP_DECLINE:
1246*2882Svi117747 		return ("DECLINE");
1247*2882Svi117747 	case SIP_DOES_NOT_EXIST_ANYWHERE:
1248*2882Svi117747 		return ("DOES_NOT_EXIST_ANYWHERE");
1249*2882Svi117747 	case SIP_NOT_ACCEPTABLE_ANYWHERE:
1250*2882Svi117747 		return ("NOT_ACCEPTABLE_ANYWHERE");
1251*2882Svi117747 	default:
1252*2882Svi117747 		return ("UNKNOWN");
1253*2882Svi117747 	}
1254*2882Svi117747 }
1255*2882Svi117747 
1256*2882Svi117747 /*
1257*2882Svi117747  * The following three fns initialize and destroy the private library
1258*2882Svi117747  * data in sip_conn_object_t. The assumption is that the 1st member
1259*2882Svi117747  * of sip_conn_object_t is reserved for library use. The private data
1260*2882Svi117747  * is used only for byte-stream protocols such as TCP to accumulate
1261*2882Svi117747  * a complete SIP message, based on the CONTENT-LENGTH value, before
1262*2882Svi117747  * processing it.
1263*2882Svi117747  */
1264*2882Svi117747 int
1265*2882Svi117747 sip_init_conn_object(sip_conn_object_t obj)
1266*2882Svi117747 {
1267*2882Svi117747 	void			**obj_val;
1268*2882Svi117747 	sip_conn_obj_pvt_t	*pvt_data;
1269*2882Svi117747 
1270*2882Svi117747 	if (obj == NULL)
1271*2882Svi117747 		return (EINVAL);
1272*2882Svi117747 	pvt_data =  malloc(sizeof (sip_conn_obj_pvt_t));
1273*2882Svi117747 	if (pvt_data == NULL)
1274*2882Svi117747 		return (ENOMEM);
1275*2882Svi117747 	pvt_data->sip_conn_obj_cache = NULL;
1276*2882Svi117747 	pvt_data->sip_conn_obj_reass = malloc(sizeof (sip_reass_entry_t));
1277*2882Svi117747 	if (pvt_data->sip_conn_obj_reass == NULL) {
1278*2882Svi117747 		free(pvt_data);
1279*2882Svi117747 		return (ENOMEM);
1280*2882Svi117747 	}
1281*2882Svi117747 	bzero(pvt_data->sip_conn_obj_reass, sizeof (sip_reass_entry_t));
1282*2882Svi117747 	(void) pthread_mutex_init(&pvt_data->sip_conn_obj_reass_lock, NULL);
1283*2882Svi117747 	(void) pthread_mutex_init(&pvt_data->sip_conn_obj_cache_lock, NULL);
1284*2882Svi117747 	sip_refhold_conn(obj);
1285*2882Svi117747 	obj_val = (void *)obj;
1286*2882Svi117747 	*obj_val = (void *)pvt_data;
1287*2882Svi117747 
1288*2882Svi117747 	return (0);
1289*2882Svi117747 }
1290*2882Svi117747 
1291*2882Svi117747 /*
1292*2882Svi117747  * Clear private date, if any
1293*2882Svi117747  */
1294*2882Svi117747 void
1295*2882Svi117747 sip_clear_stale_data(sip_conn_object_t obj)
1296*2882Svi117747 {
1297*2882Svi117747 	void			**obj_val;
1298*2882Svi117747 	sip_conn_obj_pvt_t	*pvt_data;
1299*2882Svi117747 	sip_reass_entry_t	*reass;
1300*2882Svi117747 
1301*2882Svi117747 	if (obj == NULL)
1302*2882Svi117747 		return;
1303*2882Svi117747 	obj_val = (void *)obj;
1304*2882Svi117747 	pvt_data = (sip_conn_obj_pvt_t *)*obj_val;
1305*2882Svi117747 	(void) pthread_mutex_lock(&pvt_data->sip_conn_obj_reass_lock);
1306*2882Svi117747 	reass = pvt_data->sip_conn_obj_reass;
1307*2882Svi117747 	if (reass->sip_reass_msg != NULL) {
1308*2882Svi117747 		assert(reass->sip_reass_msglen > 0);
1309*2882Svi117747 		free(reass->sip_reass_msg);
1310*2882Svi117747 		reass->sip_reass_msglen = 0;
1311*2882Svi117747 	}
1312*2882Svi117747 	assert(reass->sip_reass_msglen == 0);
1313*2882Svi117747 	(void) pthread_mutex_unlock(&pvt_data->sip_conn_obj_reass_lock);
1314*2882Svi117747 }
1315*2882Svi117747 
1316*2882Svi117747 /*
1317*2882Svi117747  * Walk through all the transactions, remove if this obj has been cached
1318*2882Svi117747  * by any.
1319*2882Svi117747  */
1320*2882Svi117747 void
1321*2882Svi117747 sip_conn_destroyed(sip_conn_object_t obj)
1322*2882Svi117747 {
1323*2882Svi117747 	void			**obj_val;
1324*2882Svi117747 	sip_conn_obj_pvt_t	*pvt_data;
1325*2882Svi117747 
1326*2882Svi117747 	if (obj == NULL)
1327*2882Svi117747 		return;
1328*2882Svi117747 	obj_val = (void *)obj;
1329*2882Svi117747 	pvt_data = (sip_conn_obj_pvt_t *)*obj_val;
1330*2882Svi117747 
1331*2882Svi117747 	sip_clear_stale_data(obj);
1332*2882Svi117747 	free(pvt_data->sip_conn_obj_reass);
1333*2882Svi117747 	pvt_data->sip_conn_obj_reass = NULL;
1334*2882Svi117747 	(void) pthread_mutex_destroy(&pvt_data->sip_conn_obj_reass_lock);
1335*2882Svi117747 
1336*2882Svi117747 	sip_del_conn_obj_cache(obj, NULL);
1337*2882Svi117747 	(void) pthread_mutex_destroy(&pvt_data->sip_conn_obj_cache_lock);
1338*2882Svi117747 
1339*2882Svi117747 	free(pvt_data);
1340*2882Svi117747 	*obj_val = NULL;
1341*2882Svi117747 	sip_refrele_conn(obj);
1342*2882Svi117747 }
1343