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