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