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