xref: /onnv-gate/usr/src/lib/libsip/common/sip_headers.c (revision 5092:0cbd682a52d4)
12882Svi117747 /*
22882Svi117747  * CDDL HEADER START
32882Svi117747  *
42882Svi117747  * The contents of this file are subject to the terms of the
52882Svi117747  * Common Development and Distribution License (the "License").
62882Svi117747  * You may not use this file except in compliance with the License.
72882Svi117747  *
82882Svi117747  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
92882Svi117747  * or http://www.opensolaris.org/os/licensing.
102882Svi117747  * See the License for the specific language governing permissions
112882Svi117747  * and limitations under the License.
122882Svi117747  *
132882Svi117747  * When distributing Covered Code, include this CDDL HEADER in each
142882Svi117747  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
152882Svi117747  * If applicable, add the following below this CDDL HEADER, with the
162882Svi117747  * fields enclosed by brackets "[]" replaced with your own identifying
172882Svi117747  * information: Portions Copyright [yyyy] [name of copyright owner]
182882Svi117747  *
192882Svi117747  * CDDL HEADER END
202882Svi117747  */
212882Svi117747 
222882Svi117747 /*
233439Svi117747  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
242882Svi117747  * Use is subject to license terms.
252882Svi117747  */
262882Svi117747 
272882Svi117747 #pragma ident	"%Z%%M%	%I%	%E% SMI"
282882Svi117747 
293439Svi117747 #include <stdio.h>
303439Svi117747 #include <assert.h>
313439Svi117747 #include <errno.h>
323439Svi117747 #include <pthread.h>
333439Svi117747 #include <stdlib.h>
343439Svi117747 #include <string.h>
353439Svi117747 #include <sip.h>
363439Svi117747 
372882Svi117747 #include "sip_msg.h"
382882Svi117747 #include "sip_miscdefs.h"
392882Svi117747 #include "sip_parse_generic.h"
402882Svi117747 
412882Svi117747 sip_methods_t sip_methods[MAX_SIP_METHODS] = {
422882Svi117747 	{"UNKNOWN", 7},
432882Svi117747 	{"INVITE", 6},
442882Svi117747 	{"ACK", 3},
452882Svi117747 	{"OPTIONS", 7},
462882Svi117747 	{"BYE", 3},
472882Svi117747 	{"CANCEL", 6},
482882Svi117747 	{"REGISTER", 8},
492882Svi117747 	{"REFER", 5},
502882Svi117747 	{"INFO", 4},
512882Svi117747 	{"SUBSCRIBE", 9},
522882Svi117747 	{"NOTIFY", 6},
532882Svi117747 	{"PRACK", 5}
542882Svi117747 };
552882Svi117747 
562882Svi117747 /*
572882Svi117747  * Built-In Header function table
582882Svi117747  */
592882Svi117747 sip_header_function_t sip_header_function_table[] = {
602882Svi117747 	{"Unknown", NULL, sip_parse_unknown_header, NULL, NULL, NULL},
612882Svi117747 	{"CONTACT", "m", sip_parse_cftr_header, NULL, NULL,
622882Svi117747 	sip_free_cftr_header},
632882Svi117747 	{"FROM", "F", sip_parse_cftr_header, NULL, NULL, sip_free_cftr_header},
642882Svi117747 	{"TO", "T", sip_parse_cftr_header, NULL, NULL, sip_free_cftr_header},
652882Svi117747 	{"CONTENT-LENGTH", "l", sip_parse_clen_header, NULL, NULL,
662882Svi117747 	sip_free_phdr},
672882Svi117747 	{"CONTENT-TYPE", "c", sip_parse_ctype_header, NULL, NULL,
682882Svi117747 	sip_free_phdr},
692882Svi117747 	{"CALL-ID", "i", sip_parse_cid_header, NULL, NULL, sip_free_phdr},
702882Svi117747 	{"CSEQ", NULL, sip_parse_cseq_header, NULL, NULL, sip_free_phdr},
712882Svi117747 	{"VIA", "v", sip_parse_via_header, NULL, NULL, sip_free_phdr},
722882Svi117747 	{"Max-Forwards", NULL, sip_parse_maxf_header, NULL, NULL,
732882Svi117747 	sip_free_phdr},
742882Svi117747 	{"RECORD-ROUTE", NULL, sip_parse_cftr_header, NULL, NULL,
752882Svi117747 	sip_free_cftr_header},
762882Svi117747 	{"ROUTE", NULL, sip_parse_cftr_header, NULL, NULL,
772882Svi117747 	sip_free_cftr_header},
782882Svi117747 	{"ACCEPT", NULL, sip_parse_acpt_header, NULL, NULL, sip_free_phdr},
792882Svi117747 	{"ACCEPT-ENCODING", NULL, sip_parse_acpt_encode_header, NULL, NULL,
802882Svi117747 	sip_free_phdr},
812882Svi117747 	{"ACCEPT-LANGUAGE", NULL, sip_parse_acpt_lang_header, NULL, NULL,
822882Svi117747 	sip_free_phdr},
832882Svi117747 	{"ALERT-INFO", NULL, sip_parse_alert_header, NULL, NULL, sip_free_phdr},
842882Svi117747 	{"ALLOW", NULL, sip_parse_allow_header, NULL, NULL, sip_free_phdr},
852882Svi117747 	{"CALL-INFO", NULL, sip_parse_callinfo_header, NULL, NULL,
862882Svi117747 	sip_free_phdr},
872882Svi117747 	{"CONTENT-DISPOSITION", NULL, sip_parse_contentdis_header, NULL, NULL,
882882Svi117747 	sip_free_phdr},
892882Svi117747 	{"CONTENT-ENCODING", "e", sip_parse_contentencode_header, NULL, NULL,
902882Svi117747 	sip_free_phdr},
912882Svi117747 	{"CONTENT-LANGUAGE", NULL, sip_parse_contentlang_header, NULL, NULL,
922882Svi117747 	sip_free_phdr},
932882Svi117747 	{"DATE", NULL, sip_parse_date_header, NULL, NULL, sip_free_phdr},
942882Svi117747 	{"ERROR-INFO", NULL, sip_parse_errorinfo_header, NULL, NULL,
952882Svi117747 	sip_free_phdr},
962882Svi117747 	{"EXPIRES", NULL, sip_parse_expire_header, NULL, NULL, sip_free_phdr},
972882Svi117747 	{"IN-REPLY-TO", NULL, sip_parse_inreplyto_header, NULL, NULL,
982882Svi117747 	sip_free_phdr},
992882Svi117747 	{"MIN-EXPIRES", NULL, sip_parse_minexpire_header, NULL, NULL,
1002882Svi117747 	sip_free_phdr},
1012882Svi117747 	{"MIME-VERSION", NULL, sip_parse_mimeversion_header, NULL, NULL,
1022882Svi117747 	sip_free_phdr},
1032882Svi117747 	{"ORGANIZATION", NULL, sip_parse_org_header, NULL, NULL, sip_free_phdr},
1042882Svi117747 	{"PRIORITY", NULL, sip_parse_priority_header, NULL, NULL,
1052882Svi117747 	sip_free_phdr},
1062882Svi117747 	{"REQUIRE", NULL, sip_parse_require_header, NULL, NULL, sip_free_phdr},
1072882Svi117747 	{"REPLY-TO", NULL, sip_parse_replyto_header, NULL, NULL, sip_free_phdr},
1082882Svi117747 	{"RETRY-AFTER", NULL, sip_parse_retryaft_header, NULL, NULL,
1092882Svi117747 	sip_free_phdr},
1102882Svi117747 	{"SERVER", NULL, sip_parse_server_header, NULL, NULL, sip_free_phdr},
1112882Svi117747 	{"SUBJECT", "s", sip_parse_subject_header, NULL, NULL, sip_free_phdr},
1122882Svi117747 	{"TIMESTAMP", NULL, sip_parse_timestamp_header, NULL, NULL,
1132882Svi117747 	sip_free_phdr},
1142882Svi117747 	{"UNSUPPORTED", NULL, sip_parse_usupport_header, NULL, NULL,
1152882Svi117747 	sip_free_phdr},
1162882Svi117747 	{"SUPPORTED", "k", sip_parse_support_header, NULL, NULL, sip_free_phdr},
1172882Svi117747 	{"USER-AGENT", NULL, sip_parse_useragt_header, NULL, NULL,
1182882Svi117747 	sip_free_phdr},
1192882Svi117747 	{"WARNING", NULL, sip_parse_warn_header, NULL, NULL, sip_free_phdr},
1202882Svi117747 	{"ALLOW-EVENTS", "u", sip_parse_allow_events_header, NULL, NULL,
1212882Svi117747 	sip_free_phdr},
1222882Svi117747 	{"EVENT", "o", sip_parse_event_header, NULL, NULL, sip_free_phdr},
1232882Svi117747 	{"SUBSCRIPTION-STATE", NULL, sip_parse_substate_header, NULL, NULL,
1242882Svi117747 	sip_free_phdr},
1252882Svi117747 	{"AUTHORIZATION", NULL, sip_parse_author_header, NULL, NULL,
1262882Svi117747 	sip_free_phdr},
1272882Svi117747 	{"AUTHENTICATION-INFO", NULL, sip_parse_ainfo_header, NULL, NULL,
1282882Svi117747 	sip_free_phdr},
1292882Svi117747 	{"PROXY-AUTHORIZATION", NULL, sip_parse_pauthor_header, NULL, NULL,
1302882Svi117747 	sip_free_phdr},
1312882Svi117747 	{"PROXY-AUTHENTICATE", NULL, sip_parse_pauthen_header, NULL, NULL,
1322882Svi117747 	sip_free_phdr},
1332882Svi117747 	{"PROXY-REQUIRE", NULL, sip_parse_preq_header, NULL, NULL,
1342882Svi117747 	sip_free_phdr},
1352882Svi117747 	{"WWW-AUTHENTICATE", NULL, sip_parse_wauthen_header, NULL, NULL,
1362882Svi117747 	sip_free_phdr},
1372882Svi117747 	{"RSEQ", NULL, sip_parse_rseq, NULL, NULL, sip_free_phdr},
1382882Svi117747 	{"RACK", NULL, sip_parse_rack, NULL, NULL, sip_free_phdr},
1392882Svi117747 	{"P-ASSERTED-IDENTITY", NULL, sip_parse_passertedid, NULL, NULL,
1402882Svi117747 	sip_free_phdr},
1412882Svi117747 	{"P-PREFERRED-IDENTITY", NULL, sip_parse_ppreferredid, NULL, NULL,
1422882Svi117747 	sip_free_phdr},
1432882Svi117747 	{"PRIVACY", NULL, sip_parse_privacy_header, NULL, NULL, sip_free_phdr},
1442882Svi117747 	{NULL, NULL, NULL, NULL, NULL, NULL},
1452882Svi117747 };
1462882Svi117747 
1472882Svi117747 #define	MAX_SIP_HEADERS	\
1482882Svi117747 	sizeof (sip_header_function_table) / sizeof (sip_header_function_t)
1492882Svi117747 
1502882Svi117747 /*
1512882Svi117747  * External/application provided function table
1522882Svi117747  */
1532882Svi117747 sip_header_function_t *sip_header_function_table_external = NULL;
1542882Svi117747 
1552882Svi117747 /*
1562882Svi117747  * Free parameter list
1572882Svi117747  */
1582882Svi117747 static void
sip_free_params(sip_param_t * param_list)1592882Svi117747 sip_free_params(sip_param_t *param_list)
1602882Svi117747 {
1612882Svi117747 	sip_param_t *param, *next_param;
1622882Svi117747 
1632882Svi117747 	param = param_list;
1642882Svi117747 
1652882Svi117747 	while (param != NULL) {
1662882Svi117747 		next_param = param->param_next;
1672882Svi117747 		free(param);
1682882Svi117747 		param = next_param;
1692882Svi117747 	}
1702882Svi117747 }
1712882Svi117747 
1722882Svi117747 /*
1732882Svi117747  * Common header free routine
1742882Svi117747  */
1752882Svi117747 void
sip_free_phdr(sip_parsed_header_t * header)1762882Svi117747 sip_free_phdr(sip_parsed_header_t *header)
1772882Svi117747 {
1782882Svi117747 	sip_hdr_value_t	*value;
1792882Svi117747 	sip_hdr_value_t	*next_value;
1802882Svi117747 
1812882Svi117747 	if (header == NULL)
1822882Svi117747 		return;
1832882Svi117747 	value = (sip_hdr_value_t *)header->value;
1842882Svi117747 	while (value != NULL) {
1852882Svi117747 		sip_free_params(value->sip_param_list);
1862882Svi117747 		next_value = value->sip_next_value;
1872882Svi117747 		free(value);
1882882Svi117747 		value = next_value;
1892882Svi117747 	}
1902882Svi117747 	free(header);
1912882Svi117747 }
1922882Svi117747 
1932882Svi117747 /*
1942882Svi117747  * Free Contact/From/To header
1952882Svi117747  */
1962882Svi117747 void
sip_free_cftr_header(sip_parsed_header_t * header)1972882Svi117747 sip_free_cftr_header(sip_parsed_header_t *header)
1982882Svi117747 {
1992882Svi117747 	sip_hdr_value_t	*value;
2002882Svi117747 	sip_hdr_value_t	*next_value;
2012882Svi117747 
2022882Svi117747 	if (header == NULL)
2032882Svi117747 		return;
2042882Svi117747 	value = (sip_hdr_value_t *)header->value;
2052882Svi117747 	while (value != NULL) {
2062882Svi117747 		next_value = value->sip_next_value;
2072882Svi117747 		sip_free_params(value->sip_param_list);
2082882Svi117747 		if (value->cftr_name != NULL)
2092882Svi117747 			free(value->cftr_name);
2102882Svi117747 		if (value->sip_value_parsed_uri != NULL) {
2112882Svi117747 			sip_free_parsed_uri(value->sip_value_parsed_uri);
2122882Svi117747 			value->sip_value_parsed_uri = NULL;
2132882Svi117747 		}
2142882Svi117747 		free(value);
2152882Svi117747 		value = next_value;
2162882Svi117747 	}
2172882Svi117747 	free(header);
2182882Svi117747 }
2192882Svi117747 
2202882Svi117747 /*
2212882Svi117747  * Return new header
2222882Svi117747  */
2232882Svi117747 _sip_header_t *
sip_new_header(int header_size)2242882Svi117747 sip_new_header(int header_size)
2252882Svi117747 {
2262882Svi117747 	_sip_header_t *new_header;
2272882Svi117747 
2282882Svi117747 	new_header = calloc(1, sizeof (_sip_header_t));
2292882Svi117747 	if (new_header == NULL)
2302882Svi117747 		return (NULL);
2312882Svi117747 
2322882Svi117747 	/*
2332882Svi117747 	 * We are using snprintf which adds a null character
2342882Svi117747 	 * so allocate an extra byte which is not part of
2352882Svi117747 	 * the message header
2362882Svi117747 	 */
2372882Svi117747 	new_header->sip_hdr_start = calloc(1, header_size + 1);
2382882Svi117747 	if (new_header->sip_hdr_start == NULL) {
2392882Svi117747 		free(new_header);
2402882Svi117747 		return (NULL);
2412882Svi117747 	}
2422882Svi117747 	new_header->sip_hdr_end = new_header->sip_hdr_start + header_size;
2432882Svi117747 	new_header->sip_hdr_current = new_header->sip_hdr_start;
2442882Svi117747 	new_header->sip_hdr_allocated = B_TRUE;
2452882Svi117747 	return (new_header);
2462882Svi117747 }
2472882Svi117747 
2482882Svi117747 /*
2492882Svi117747  * Free the given header
2502882Svi117747  */
2512882Svi117747 void
sip_free_header(_sip_header_t * sip_header)2522882Svi117747 sip_free_header(_sip_header_t *sip_header)
2532882Svi117747 {
2542882Svi117747 	if (sip_header->sip_hdr_allocated) {
2552882Svi117747 		assert(sip_header->sip_hdr_start != NULL);
2562882Svi117747 		free(sip_header->sip_hdr_start);
2572882Svi117747 	}
2582882Svi117747 	if (sip_header->sip_hdr_parsed != NULL) {
2592882Svi117747 		assert(sip_header->sip_header_functions != NULL);
2602882Svi117747 		if (sip_header->sip_header_functions->header_free != NULL) {
2612882Svi117747 			sip_header->sip_header_functions->header_free(
2622882Svi117747 			    sip_header->sip_hdr_parsed);
2632882Svi117747 		}
2642882Svi117747 	}
2652882Svi117747 	free(sip_header);
2662882Svi117747 }
2672882Svi117747 
2682882Svi117747 /*
2692882Svi117747  * Return a copy of the header passed in.
2702882Svi117747  */
2712882Svi117747 _sip_header_t *
sip_dup_header(_sip_header_t * from)2722882Svi117747 sip_dup_header(_sip_header_t *from)
2732882Svi117747 {
2742882Svi117747 	size_t		hdr_size;
2752882Svi117747 	_sip_header_t	*to;
2762882Svi117747 
2772882Svi117747 	hdr_size = from->sip_hdr_end - from->sip_hdr_start;
2782882Svi117747 	to = sip_new_header(hdr_size);
2792882Svi117747 	if (to == NULL)
2802882Svi117747 		return (NULL);
2812882Svi117747 	if (from->sip_header_state == SIP_HEADER_DELETED_VAL) {
2822882Svi117747 		to->sip_hdr_end = to->sip_hdr_start +
2832882Svi117747 		    sip_copy_values(to->sip_hdr_start, from);
2842882Svi117747 	} else {
2852882Svi117747 		(void) memcpy(to->sip_hdr_start, from->sip_hdr_start, hdr_size);
2862882Svi117747 		to->sip_hdr_end = to->sip_hdr_start + hdr_size;
2872882Svi117747 	}
2882882Svi117747 	to->sip_header_functions = from->sip_header_functions;
2892882Svi117747 	return (to);
2902882Svi117747 }
2912882Svi117747 
2922882Svi117747 /*
2932882Svi117747  * Copy header with extra_param, if any, to sip_msg
2942882Svi117747  */
2952882Svi117747 int
_sip_copy_header(_sip_msg_t * sip_msg,_sip_header_t * header,char * extra_param,boolean_t skip_crlf)2962882Svi117747 _sip_copy_header(_sip_msg_t *sip_msg, _sip_header_t *header, char *extra_param,
2972882Svi117747     boolean_t skip_crlf)
2982882Svi117747 {
2992882Svi117747 	_sip_header_t	*new_header;
3002882Svi117747 	int		hdrlen;
3012882Svi117747 	int		extra_len = 0;
3022882Svi117747 	int		ncrlf = 0;
3032882Svi117747 	char		*p;
3042882Svi117747 
3052882Svi117747 #ifdef	__solaris__
3062882Svi117747 	assert(mutex_held(&sip_msg->sip_msg_mutex));
3072882Svi117747 #endif
3082882Svi117747 	if (extra_param != NULL) {
3092882Svi117747 		extra_len = SIP_SPACE_LEN + sizeof (char) + SIP_SPACE_LEN +
3102882Svi117747 		    strlen(extra_param);
3112882Svi117747 	}
3122882Svi117747 	/*
3132882Svi117747 	 * Just take one if there are more, i.e. if this is the last header
3142882Svi117747 	 * before the content.
3152882Svi117747 	 */
3162882Svi117747 	if (skip_crlf) {
3172882Svi117747 		if (header->sip_hdr_end - strlen(SIP_CRLF) <=
3182882Svi117747 		    header->sip_hdr_start) {
3192882Svi117747 			goto proceed;
3202882Svi117747 		}
3212882Svi117747 		p = header->sip_hdr_end - strlen(SIP_CRLF);
3222882Svi117747 		while (strncmp(SIP_CRLF, p, strlen(SIP_CRLF)) == 0) {
3232882Svi117747 			ncrlf++;
3242882Svi117747 			if (p - strlen(SIP_CRLF) < header->sip_hdr_start)
3252882Svi117747 				break;
3262882Svi117747 			p -= strlen(SIP_CRLF);
3272882Svi117747 		}
3282882Svi117747 		/*
3292882Svi117747 		 * Take one CRLF.
3302882Svi117747 		 */
3312882Svi117747 		ncrlf = (ncrlf - 1) * strlen(SIP_CRLF);
3322882Svi117747 	}
3332882Svi117747 proceed:
3342882Svi117747 	hdrlen = header->sip_hdr_end - header->sip_hdr_start - ncrlf;
3352882Svi117747 	new_header = sip_new_header(hdrlen + extra_len);
3362882Svi117747 	if (new_header == NULL)
3372882Svi117747 		return (ENOMEM);
3382882Svi117747 	if (header->sip_header_state == SIP_HEADER_DELETED_VAL) {
3392882Svi117747 		int	len;
3402882Svi117747 
3412882Svi117747 		len = sip_copy_values(new_header->sip_hdr_start, header);
3422882Svi117747 		new_header->sip_hdr_end = new_header->sip_hdr_start + len;
3432882Svi117747 		hdrlen = hdrlen - len + extra_len;
3442882Svi117747 	} else {
3452882Svi117747 		(void) memcpy(new_header->sip_hdr_start, header->sip_hdr_start,
3462882Svi117747 		    hdrlen);
3472882Svi117747 		new_header->sip_hdr_end = new_header->sip_hdr_start + hdrlen;
3482882Svi117747 		hdrlen = extra_len;
3492882Svi117747 	}
3502882Svi117747 	if (extra_param != NULL) {
3512882Svi117747 		/*
3522882Svi117747 		 * Find CR
3532882Svi117747 		 */
3542882Svi117747 		if (sip_find_cr(new_header) != 0) {
3552882Svi117747 			sip_free_header(new_header);
3562882Svi117747 			return (EINVAL);
3572882Svi117747 		}
3582882Svi117747 		hdrlen += new_header->sip_hdr_end - new_header->sip_hdr_current;
3592882Svi117747 		(void) snprintf(new_header->sip_hdr_current, hdrlen + 1,
3602882Svi117747 		    " %c %s%s", SIP_SEMI, extra_param, SIP_CRLF);
3612882Svi117747 	}
3622882Svi117747 
3632882Svi117747 	new_header->sip_hdr_end += extra_len;
3642882Svi117747 	new_header->sip_header_functions = header->sip_header_functions;
3652882Svi117747 	_sip_add_header(sip_msg, new_header, B_TRUE, B_FALSE, NULL);
3662882Svi117747 	return (0);
3672882Svi117747 }
3682882Svi117747 
3692882Svi117747 /*
3702882Svi117747  * Copy all "header_name" headers from _old_msg to _new_msg
3712882Svi117747  */
3722882Svi117747 int
_sip_find_and_copy_all_header(_sip_msg_t * _old_msg,_sip_msg_t * _new_msg,char * header_name)3732882Svi117747 _sip_find_and_copy_all_header(_sip_msg_t *_old_msg, _sip_msg_t *_new_msg,
3742882Svi117747     char *header_name)
3752882Svi117747 {
3762882Svi117747 	_sip_header_t	*header;
3772882Svi117747 	int		ret = 0;
3782882Svi117747 
3792882Svi117747 	if (_old_msg == NULL || _new_msg == NULL)
3802882Svi117747 		return (EINVAL);
3812882Svi117747 #ifdef	__solaris__
3822882Svi117747 	assert(mutex_held(&_old_msg->sip_msg_mutex));
3832882Svi117747 #endif
3842882Svi117747 	if (_old_msg != _new_msg)
3852882Svi117747 		(void) pthread_mutex_lock(&_new_msg->sip_msg_mutex);
3862882Svi117747 	header = sip_search_for_header(_old_msg, header_name, NULL);
3872882Svi117747 	while (header != NULL) {
3882882Svi117747 		ret = _sip_copy_header(_new_msg, header, NULL, B_TRUE);
3892882Svi117747 		if (ret != 0)
3902882Svi117747 			break;
3912882Svi117747 		header = sip_search_for_header(_old_msg, header_name, header);
3922882Svi117747 	}
3932882Svi117747 	if (_old_msg != _new_msg)
3942882Svi117747 		(void) pthread_mutex_unlock(&_new_msg->sip_msg_mutex);
3952882Svi117747 	return (ret);
3962882Svi117747 }
3972882Svi117747 
3982882Svi117747 /*
3992882Svi117747  * Copy header_name from _old_msg to _new_msg with extra_parm.
4002882Svi117747  */
4012882Svi117747 int
_sip_find_and_copy_header(sip_msg_t _old_msg,sip_msg_t _new_msg,char * header_name,char * extra_param,boolean_t lock_newmsg)4022882Svi117747 _sip_find_and_copy_header(sip_msg_t _old_msg, sip_msg_t _new_msg,
4032882Svi117747     char *header_name, char *extra_param, boolean_t lock_newmsg)
4042882Svi117747 {
4052882Svi117747 	_sip_header_t	*header;
4062882Svi117747 	int		ret;
4072882Svi117747 
4082882Svi117747 	if (_old_msg == NULL || _new_msg == NULL)
4092882Svi117747 		return (EINVAL);
4102882Svi117747 #ifdef	__solaris__
4112882Svi117747 	assert(mutex_held(&_old_msg->sip_msg_mutex));
4122882Svi117747 #endif
4132882Svi117747 	header = sip_search_for_header(_old_msg, header_name, NULL);
4142882Svi117747 	if (header == NULL)
4152882Svi117747 		return (EINVAL);
4162882Svi117747 	if (lock_newmsg)
4172882Svi117747 		(void) pthread_mutex_lock(&_new_msg->sip_msg_mutex);
4182882Svi117747 	ret = _sip_copy_header(_new_msg, header, extra_param, B_TRUE);
4192882Svi117747 	if (lock_newmsg)
4202882Svi117747 		(void) pthread_mutex_unlock(&_new_msg->sip_msg_mutex);
4212882Svi117747 	return (ret);
4222882Svi117747 }
4232882Svi117747 
4242882Svi117747 /*
4252882Svi117747  * Copy all headers from old_msg to new_msg
4262882Svi117747  */
4272882Svi117747 int
sip_copy_all_headers(sip_msg_t old_msg,sip_msg_t new_msg)4282882Svi117747 sip_copy_all_headers(sip_msg_t old_msg, sip_msg_t new_msg)
4292882Svi117747 {
4302882Svi117747 	_sip_header_t	*header;
4312882Svi117747 	_sip_msg_t	*_old_msg;
4322882Svi117747 	_sip_msg_t	*_new_msg;
4332882Svi117747 	int		ret = 0;
4342882Svi117747 
4352882Svi117747 	if (old_msg == NULL || new_msg == NULL)
4362882Svi117747 		return (EINVAL);
4372882Svi117747 	_old_msg = (_sip_msg_t *)old_msg;
4382882Svi117747 	_new_msg = (_sip_msg_t *)new_msg;
4392882Svi117747 
4402882Svi117747 	(void) pthread_mutex_lock(&_old_msg->sip_msg_mutex);
4412882Svi117747 	(void) pthread_mutex_lock(&_new_msg->sip_msg_mutex);
4422882Svi117747 	header = sip_search_for_header(_old_msg, NULL, NULL);
4432882Svi117747 	while (header != NULL) {
4442882Svi117747 		ret = _sip_copy_header(_new_msg, header, NULL, B_FALSE);
4452882Svi117747 		if (ret != 0)
4462882Svi117747 			goto done;
4472882Svi117747 		header = sip_search_for_header(_old_msg, NULL, header);
4482882Svi117747 	}
4492882Svi117747 done:
4502882Svi117747 	(void) pthread_mutex_unlock(&_new_msg->sip_msg_mutex);
4512882Svi117747 	(void) pthread_mutex_unlock(&_old_msg->sip_msg_mutex);
4522882Svi117747 	return (ret);
4532882Svi117747 }
4542882Svi117747 
4552882Svi117747 /*
4562882Svi117747  * Copy start line from msg to sip_msg
4572882Svi117747  */
4582882Svi117747 int
sip_copy_start_line(sip_msg_t msg,sip_msg_t sip_msg)4592882Svi117747 sip_copy_start_line(sip_msg_t msg, sip_msg_t sip_msg)
4602882Svi117747 {
4612882Svi117747 	int		len;
4622882Svi117747 	_sip_header_t	*new_header;
4632882Svi117747 	_sip_msg_t	*_old_msg;
4642882Svi117747 	_sip_msg_t	*_sip_msg;
4652882Svi117747 
4662882Svi117747 	if (msg == NULL || sip_msg == NULL)
4672882Svi117747 		return (EINVAL);
4682882Svi117747 	_old_msg = (_sip_msg_t *)msg;
4692882Svi117747 	_sip_msg = (_sip_msg_t *)sip_msg;
4702882Svi117747 
4712882Svi117747 	(void) pthread_mutex_lock(&_old_msg->sip_msg_mutex);
4722882Svi117747 	if (_old_msg->sip_msg_start_line == NULL) {
4732882Svi117747 		(void) pthread_mutex_unlock(&_old_msg->sip_msg_mutex);
4742882Svi117747 		return (EINVAL);
4752882Svi117747 	}
4762882Svi117747 	len = _old_msg->sip_msg_start_line->sip_hdr_end -
4772882Svi117747 	    _old_msg->sip_msg_start_line->sip_hdr_start;
4782882Svi117747 	new_header = sip_new_header(len);
4792882Svi117747 	if (new_header == NULL) {
4802882Svi117747 		(void) pthread_mutex_unlock(&_old_msg->sip_msg_mutex);
4812882Svi117747 		return (ENOMEM);
4822882Svi117747 	}
4832882Svi117747 	new_header->sip_hdr_sipmsg = _sip_msg;
4842882Svi117747 	(void) pthread_mutex_lock(&sip_msg->sip_msg_mutex);
4852882Svi117747 	_sip_msg->sip_msg_start_line = new_header;
4862882Svi117747 	_sip_msg->sip_msg_len = len;
4872882Svi117747 	(void) strncpy(_sip_msg->sip_msg_start_line->sip_hdr_start,
4882882Svi117747 	    _old_msg->sip_msg_start_line->sip_hdr_start, len);
4892882Svi117747 	(void) sip_parse_first_line(_sip_msg->sip_msg_start_line,
4902882Svi117747 	    &_sip_msg->sip_msg_req_res);
4912882Svi117747 	(void) pthread_mutex_unlock(&_old_msg->sip_msg_mutex);
4922882Svi117747 	(void) pthread_mutex_unlock(&sip_msg->sip_msg_mutex);
4932882Svi117747 	return (0);
4942882Svi117747 }
4952882Svi117747 
4962882Svi117747 /*
4972882Svi117747  * Delete start line from sip_msg
4982882Svi117747  */
4992882Svi117747 int
sip_delete_start_line_locked(_sip_msg_t * _sip_msg)5002882Svi117747 sip_delete_start_line_locked(_sip_msg_t *_sip_msg)
5012882Svi117747 {
5022882Svi117747 	_sip_header_t	*header;
5032882Svi117747 	_sip_header_t	*next_header;
5042882Svi117747 
5052882Svi117747 	if (_sip_msg->sip_msg_start_line == NULL)
5062882Svi117747 		return (EINVAL);
5072882Svi117747 
5082882Svi117747 	header = _sip_msg->sip_msg_start_line;
5092882Svi117747 	while (header != NULL) {
5102882Svi117747 		next_header = header->sip_hdr_next;
5112882Svi117747 		_sip_msg->sip_msg_len -= (header->sip_hdr_end -
5122882Svi117747 		    header->sip_hdr_start);
5132882Svi117747 		sip_free_header(header);
5142882Svi117747 		header = next_header;
5152882Svi117747 	}
5162882Svi117747 	_sip_msg->sip_msg_start_line = NULL;
5172882Svi117747 
5182882Svi117747 	/*
5192882Svi117747 	 * Also delete the sip_msg_req_res info since we don't have a start
5202882Svi117747 	 * line.
5212882Svi117747 	 */
5222882Svi117747 	while (_sip_msg->sip_msg_req_res != NULL) {
5232882Svi117747 		sip_message_type_t	*sip_msg_type_ptr;
5242882Svi117747 
5252882Svi117747 		sip_msg_type_ptr = _sip_msg->sip_msg_req_res->sip_next;
5262882Svi117747 		if (_sip_msg->sip_msg_req_res->is_request) {
5272882Svi117747 			sip_request_t	*reqline;
5282882Svi117747 
5292882Svi117747 			reqline = &_sip_msg->sip_msg_req_res->U.sip_request;
5302882Svi117747 			if (reqline->sip_parse_uri != NULL) {
5312882Svi117747 				sip_free_parsed_uri(reqline->sip_parse_uri);
5322882Svi117747 				reqline->sip_parse_uri = NULL;
5332882Svi117747 			}
5342882Svi117747 		}
5352882Svi117747 		free(_sip_msg->sip_msg_req_res);
5362882Svi117747 		_sip_msg->sip_msg_req_res = sip_msg_type_ptr;
5372882Svi117747 	}
5382882Svi117747 	return (0);
5392882Svi117747 }
5402882Svi117747 
5412882Svi117747 
5422882Svi117747 /*
5432882Svi117747  * Delete start line from sip_msg
5442882Svi117747  */
5452882Svi117747 int
sip_delete_start_line(sip_msg_t sip_msg)5462882Svi117747 sip_delete_start_line(sip_msg_t sip_msg)
5472882Svi117747 {
5482882Svi117747 	_sip_msg_t	*_sip_msg;
5492882Svi117747 	int		ret;
5502882Svi117747 
5512882Svi117747 	if (sip_msg == NULL)
5522882Svi117747 		return (EINVAL);
5532882Svi117747 
5542882Svi117747 	_sip_msg = (_sip_msg_t *)sip_msg;
5552882Svi117747 	(void) pthread_mutex_lock(&_sip_msg->sip_msg_mutex);
5562882Svi117747 	ret = sip_delete_start_line_locked(_sip_msg);
5572882Svi117747 	(void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
5582882Svi117747 
5592882Svi117747 	return (ret);
5602882Svi117747 }
5612882Svi117747 
5622882Svi117747 /*
5632882Svi117747  * Delete all headers from _sip_msg
5642882Svi117747  */
5652882Svi117747 void
sip_delete_all_headers(_sip_msg_t * _sip_msg)5662882Svi117747 sip_delete_all_headers(_sip_msg_t *_sip_msg)
5672882Svi117747 {
5682882Svi117747 	_sip_header_t *header;
5692882Svi117747 
5702882Svi117747 #ifdef	__solaris__
5712882Svi117747 	assert(mutex_held(&_sip_msg->sip_msg_mutex));
5722882Svi117747 #endif
5732882Svi117747 
5742882Svi117747 	header = _sip_msg->sip_msg_headers_start;
5752882Svi117747 	while (header != NULL) {
5762882Svi117747 		_sip_header_t *next_header;
5772882Svi117747 		next_header = header->sip_hdr_next;
5782882Svi117747 		sip_free_header(header);
5792882Svi117747 		header = next_header;
5802882Svi117747 	}
5812882Svi117747 	_sip_msg->sip_msg_headers_start = NULL;
5822882Svi117747 	_sip_msg->sip_msg_headers_end = NULL;
5832882Svi117747 }
5842882Svi117747 
5852882Svi117747 /*
5862882Svi117747  * Delete and free the named header. If header_name is null
5872882Svi117747  * free all headers.
5882882Svi117747  */
5892882Svi117747 void
sip_delete_headers(sip_msg_t sip_msg,char * header_name)5902882Svi117747 sip_delete_headers(sip_msg_t sip_msg, char *header_name)
5912882Svi117747 {
5922882Svi117747 	_sip_header_t *header;
5932882Svi117747 	_sip_msg_t *_sip_msg;
5942882Svi117747 
5952882Svi117747 	_sip_msg = (_sip_msg_t *)sip_msg;
5962882Svi117747 #ifdef	__solaris__
5972882Svi117747 	assert(mutex_held(&_sip_msg->sip_msg_mutex));
5982882Svi117747 #endif
5992882Svi117747 	header = sip_search_for_header(_sip_msg, header_name, NULL);
6002882Svi117747 	if (header == NULL)
6012882Svi117747 		return;
6022882Svi117747 	while (header != NULL) {
6032882Svi117747 		if (_sip_msg->sip_msg_headers_start == header) {
6042882Svi117747 			_sip_msg->sip_msg_headers_start = header->sip_hdr_next;
6052882Svi117747 		} else {
6062882Svi117747 			header->sip_hdr_prev->sip_hdr_next =
6072882Svi117747 			    header->sip_hdr_next;
6082882Svi117747 		}
6092882Svi117747 		if (_sip_msg->sip_msg_headers_end == header) {
6102882Svi117747 			_sip_msg->sip_msg_headers_end = header->sip_hdr_prev;
6112882Svi117747 		} else {
6122882Svi117747 			header->sip_hdr_next->sip_hdr_prev =
6132882Svi117747 			    header->sip_hdr_prev;
6142882Svi117747 		}
6152882Svi117747 		sip_free_header(header);
6162882Svi117747 		if (header_name != NULL)
6172882Svi117747 			return;
6182882Svi117747 		else
6192882Svi117747 			header = sip_search_for_header(_sip_msg, NULL, NULL);
6202882Svi117747 	}
6212882Svi117747 }
6222882Svi117747 
6232882Svi117747 /*
6242882Svi117747  * Add a header to sip_msg. If header_name is provided then the new header
6252882Svi117747  * is added before that header, if first is set, or after. If append is
6262882Svi117747  * set, then the header is added to the end of the header list.
6272882Svi117747  */
6282882Svi117747 void
_sip_add_header(_sip_msg_t * sip_msg,_sip_header_t * new_header,boolean_t append,boolean_t first,char * header_name)6292882Svi117747 _sip_add_header(_sip_msg_t *sip_msg, _sip_header_t *new_header,
6302882Svi117747     boolean_t append, boolean_t first, char *header_name)
6312882Svi117747 {
6322882Svi117747 	_sip_header_t	*header = NULL;
6332882Svi117747 
6342882Svi117747 	if (sip_msg == NULL || new_header == NULL)
6352882Svi117747 		return;
6362882Svi117747 #ifdef	__solaris__
6372882Svi117747 	assert(mutex_held(&sip_msg->sip_msg_mutex));
6382882Svi117747 #endif
6392882Svi117747 	new_header->sip_hdr_sipmsg = sip_msg;
6402882Svi117747 	if (header_name != NULL) {
6412882Svi117747 		_sip_header_t	*header_tmp;
6422882Svi117747 
6432882Svi117747 		header = sip_search_for_header(sip_msg, header_name, NULL);
6442882Svi117747 		header_tmp = header;
6452882Svi117747 		if (!first) {
6462882Svi117747 			while (header != NULL) {
6472882Svi117747 				header_tmp = header;
6482882Svi117747 				header = sip_search_for_header(sip_msg,
6492882Svi117747 				    header_name, header);
6502882Svi117747 			}
6512882Svi117747 		}
6522882Svi117747 		header = header_tmp;
6532882Svi117747 		if (header == NULL)
6542882Svi117747 			append =  B_TRUE;
6552882Svi117747 	}
6562882Svi117747 
6572882Svi117747 	if (header != NULL) {
6582882Svi117747 		if (append) {
6592882Svi117747 			new_header->sip_hdr_prev = header;
6602882Svi117747 			if (sip_msg->sip_msg_headers_end == header) {
6612882Svi117747 				sip_msg->sip_msg_headers_end = new_header;
6622882Svi117747 				new_header->sip_hdr_next = NULL;
6632882Svi117747 			} else {
6642882Svi117747 				header->sip_hdr_next->sip_hdr_prev = new_header;
6652882Svi117747 				new_header->sip_hdr_next = header->sip_hdr_next;
6662882Svi117747 			}
6672882Svi117747 			header->sip_hdr_next = new_header;
6682882Svi117747 		} else {
6692882Svi117747 			new_header->sip_hdr_next = header;
6702882Svi117747 			if (sip_msg->sip_msg_headers_start == header) {
6712882Svi117747 				sip_msg->sip_msg_headers_start = new_header;
6722882Svi117747 				new_header->sip_hdr_prev = NULL;
6732882Svi117747 			} else {
6742882Svi117747 				header->sip_hdr_prev->sip_hdr_next = new_header;
6752882Svi117747 				new_header->sip_hdr_prev = header->sip_hdr_prev;
6762882Svi117747 			}
6772882Svi117747 			header->sip_hdr_prev = new_header;
6782882Svi117747 		}
6792882Svi117747 	} else {
6802882Svi117747 		if (append) {
6812882Svi117747 			if (sip_msg->sip_msg_headers_end != NULL) {
6822882Svi117747 				sip_msg->sip_msg_headers_end->sip_hdr_next =
6832882Svi117747 				    new_header;
6842882Svi117747 			} else {
6852882Svi117747 				sip_msg->sip_msg_headers_start = new_header;
6862882Svi117747 			}
6872882Svi117747 			new_header->sip_hdr_prev =
6882882Svi117747 			    sip_msg->sip_msg_headers_end;
6892882Svi117747 			new_header->sip_hdr_next = NULL;
6902882Svi117747 			sip_msg->sip_msg_headers_end = new_header;
6912882Svi117747 		} else {
6922882Svi117747 			if (sip_msg->sip_msg_headers_start != NULL) {
6932882Svi117747 				sip_msg->sip_msg_headers_start->sip_hdr_prev =
6942882Svi117747 				    new_header;
6952882Svi117747 			} else {
6962882Svi117747 				sip_msg->sip_msg_headers_end = new_header;
6972882Svi117747 			}
6982882Svi117747 			new_header->sip_hdr_next =
6992882Svi117747 			    sip_msg->sip_msg_headers_start;
7002882Svi117747 			new_header->sip_hdr_prev = NULL;
7012882Svi117747 			sip_msg->sip_msg_headers_start = new_header;
7022882Svi117747 		}
7032882Svi117747 	}
7042882Svi117747 	sip_msg->sip_msg_len += new_header->sip_hdr_end -
7052882Svi117747 	    new_header->sip_hdr_start;
7062882Svi117747 }
7072882Svi117747 
7082882Svi117747 /*
7092882Svi117747  * Scan through the function table and return the entry for the given header
7102882Svi117747  * type.
7112882Svi117747  */
7122882Svi117747 sip_header_function_t *
_sip_get_header_functions(sip_header_function_t * sip_header_function_table,_sip_header_t * sip_header,char * header_name)7132882Svi117747 _sip_get_header_functions(sip_header_function_t *sip_header_function_table,
7142882Svi117747     _sip_header_t *sip_header, char *header_name)
7152882Svi117747 {
7162882Svi117747 	int	len;
7172882Svi117747 	int	i = 0;
7182882Svi117747 
7192882Svi117747 	if (sip_header == NULL && header_name == NULL)
7202882Svi117747 		return (NULL);
7212882Svi117747 
7222882Svi117747 	/*
7232882Svi117747 	 * If header_name is NULL we first have to locate the name
7242882Svi117747 	 */
7252882Svi117747 	if (header_name == NULL) {
7262882Svi117747 		if (sip_skip_white_space(sip_header) != 0) {
7272882Svi117747 			return (NULL);
7282882Svi117747 		}
7292882Svi117747 		header_name = sip_header->sip_hdr_current;
7302882Svi117747 		if (sip_find_separator(sip_header, SIP_HCOLON, (char)NULL,
731*5092Sgm209912 		    (char)NULL, B_FALSE) != 0) {
7322882Svi117747 			return (NULL);
7332882Svi117747 		}
7342882Svi117747 		len = sip_header->sip_hdr_current - header_name;
7352882Svi117747 	} else {
7362882Svi117747 		len = strlen(header_name);
7372882Svi117747 	}
7382882Svi117747 
7392882Svi117747 	if (len > 0) {
7402882Svi117747 		while (sip_header_function_table[i].header_name != NULL ||
7412882Svi117747 		    sip_header_function_table[i].header_short_name != NULL) {
7422882Svi117747 			if (sip_header_function_table[i].header_name != NULL &&
7432882Svi117747 			    len ==
7442882Svi117747 			    strlen(sip_header_function_table[i].header_name)) {
7452882Svi117747 				if (strncasecmp(header_name,
7462882Svi117747 				    sip_header_function_table[i].
7472882Svi117747 				    header_name, len) == 0) {
7482882Svi117747 					break;
7492882Svi117747 				}
7502882Svi117747 			} else if (sip_header_function_table[i].
7512882Svi117747 			    header_short_name != NULL && len ==
7522882Svi117747 			    strlen(sip_header_function_table[i].
7532882Svi117747 			    header_short_name)) {
7542882Svi117747 				if (strncasecmp(header_name,
7552882Svi117747 				    sip_header_function_table[i].
7562882Svi117747 				    header_short_name, len) == 0) {
7572882Svi117747 					break;
7582882Svi117747 				}
7592882Svi117747 			}
7602882Svi117747 			i++;
7612882Svi117747 		}
7622882Svi117747 	}
7632882Svi117747 
7642882Svi117747 	if (sip_header != NULL)
7652882Svi117747 		sip_header->sip_hdr_current = sip_header->sip_hdr_start;
7662882Svi117747 	if (sip_header_function_table[i].header_name == NULL)
7672882Svi117747 		return (NULL);
7682882Svi117747 	return (&sip_header_function_table[i]);
7692882Svi117747 }
7702882Svi117747 
7712882Svi117747 /*
7722882Svi117747  * Return the entry from the function table for the given header
7732882Svi117747  */
7742882Svi117747 sip_header_function_t *
sip_get_header_functions(_sip_header_t * sip_header,char * header_name)7752882Svi117747 sip_get_header_functions(_sip_header_t *sip_header, char *header_name)
7762882Svi117747 {
7772882Svi117747 	sip_header_function_t	*func;
7782882Svi117747 	sip_header_function_t	*header_f_table = NULL;
7792882Svi117747 
7802882Svi117747 	if (sip_header_function_table_external != NULL) {
7812882Svi117747 		header_f_table = _sip_get_header_functions(
7822882Svi117747 		    sip_header_function_table_external,
7832882Svi117747 		    sip_header, header_name);
7842882Svi117747 		if (header_f_table != NULL)
7852882Svi117747 			return (header_f_table);
7862882Svi117747 	}
7872882Svi117747 	func = _sip_get_header_functions(sip_header_function_table, sip_header,
7882882Svi117747 	    header_name);
7892882Svi117747 	return (func);
7902882Svi117747 }
7912882Svi117747 
7922882Svi117747 /*
7932882Svi117747  * Search for the header name passed in.
7942882Svi117747  */
7952882Svi117747 _sip_header_t *
sip_search_for_header(_sip_msg_t * sip_msg,char * header_name,_sip_header_t * old_header)7962882Svi117747 sip_search_for_header(_sip_msg_t *sip_msg, char *header_name,
7972882Svi117747     _sip_header_t *old_header)
7982882Svi117747 {
7992882Svi117747 	int			len = 0;
8002882Svi117747 	int			full_len = 0;
8012882Svi117747 	int			compact_len = 0;
8022882Svi117747 	_sip_header_t		*header = NULL;
8032882Svi117747 	char			*compact_name = NULL;
8042882Svi117747 	char			*full_name = NULL;
8052882Svi117747 	sip_header_function_t	*header_f_table = NULL;
8062882Svi117747 
8072882Svi117747 	if (sip_msg == NULL)
8082882Svi117747 		return (NULL);
8092882Svi117747 #ifdef	__solaris__
8102882Svi117747 	assert(mutex_held(&sip_msg->sip_msg_mutex));
8112882Svi117747 #endif
8122882Svi117747 
8132882Svi117747 	if (header_name != NULL) {
8142882Svi117747 		header_f_table = sip_get_header_functions(NULL, header_name);
8152882Svi117747 		if (header_f_table != NULL) {
8162882Svi117747 			full_name = header_f_table->header_name;
8172882Svi117747 			compact_name = header_f_table->header_short_name;
8182882Svi117747 			if (full_name != NULL)
8192882Svi117747 				full_len = strlen(full_name);
8202882Svi117747 			if (compact_name != NULL)
8212882Svi117747 				compact_len = strlen(compact_name);
8222882Svi117747 		} else {
8232882Svi117747 			header_f_table = &sip_header_function_table[0];
8242882Svi117747 			full_name = header_name;
8252882Svi117747 			full_len  = strlen(full_name);
8262882Svi117747 		}
8272882Svi117747 	}
8282882Svi117747 
8292882Svi117747 	if (old_header != NULL)
8302882Svi117747 		header = old_header->sip_hdr_next;
8312882Svi117747 	else
8322882Svi117747 		header = sip_msg->sip_msg_headers_start;
8332882Svi117747 
8342882Svi117747 	while (header != NULL) {
8352882Svi117747 
8362882Svi117747 		if (header->sip_header_state == SIP_HEADER_DELETED) {
8372882Svi117747 			header = header->sip_hdr_next;
8382882Svi117747 			continue;
8392882Svi117747 		}
8402882Svi117747 
8412882Svi117747 		if (compact_len == 0 && full_len == 0)
8422882Svi117747 			break;
8432882Svi117747 
8442882Svi117747 		header->sip_hdr_current = header->sip_hdr_start;
8452882Svi117747 
8462882Svi117747 		if (sip_skip_white_space(header)) {
8472882Svi117747 			header = header->sip_hdr_next;
8482882Svi117747 			continue;
8492882Svi117747 		}
8502882Svi117747 
8512882Svi117747 		len = header->sip_hdr_end - header->sip_hdr_current;
8522882Svi117747 
8532882Svi117747 		if (full_name != NULL && (full_len <= len) &&
8542882Svi117747 		    strncasecmp(header->sip_hdr_current, full_name,
8552882Svi117747 		    full_len) == 0) {
8562882Svi117747 			header->sip_hdr_current += full_len;
8572882Svi117747 			if (sip_skip_white_space(header)) {
8582882Svi117747 				header = header->sip_hdr_next;
8592882Svi117747 				continue;
8602882Svi117747 			}
8612882Svi117747 
8622882Svi117747 			if (*header->sip_hdr_current == SIP_HCOLON) {
8632882Svi117747 				header_name = full_name;
8642882Svi117747 				break;
8652882Svi117747 			}
8662882Svi117747 		}
8672882Svi117747 
8682882Svi117747 		if (compact_name != NULL && (compact_len <= len) &&
8692882Svi117747 		    strncasecmp(header->sip_hdr_current, compact_name,
8702882Svi117747 		    compact_len) == 0) {
8712882Svi117747 			header->sip_hdr_current += compact_len;
8722882Svi117747 			if (sip_skip_white_space(header)) {
8732882Svi117747 				header = header->sip_hdr_next;
8742882Svi117747 				continue;
8752882Svi117747 			}
8762882Svi117747 			if (*header->sip_hdr_current == SIP_HCOLON) {
8772882Svi117747 				header_name = compact_name;
8782882Svi117747 				break;
8792882Svi117747 			}
8802882Svi117747 		}
8812882Svi117747 		header = header->sip_hdr_next;
8822882Svi117747 	}
8832882Svi117747 
8842882Svi117747 	if (header != NULL) {
8852882Svi117747 		header->sip_hdr_current = header->sip_hdr_start;
8862882Svi117747 		if (header_f_table == NULL) {
8872882Svi117747 			header_f_table =
8882882Svi117747 			    sip_get_header_functions(header, header_name);
8892882Svi117747 			if (header_f_table == NULL)
8902882Svi117747 				header_f_table = &sip_header_function_table[0];
8912882Svi117747 		}
8922882Svi117747 
8932882Svi117747 		header->sip_header_functions = header_f_table;
8942882Svi117747 	}
8952882Svi117747 	return (header);
8962882Svi117747 }
8972882Svi117747 
8982882Svi117747 /*
8992882Svi117747  * Return the start line as a string. Caller frees string
9002882Svi117747  */
9012882Svi117747 char *
_sip_startline_to_str(_sip_msg_t * sip_msg,int * error)9022882Svi117747 _sip_startline_to_str(_sip_msg_t *sip_msg, int *error)
9032882Svi117747 {
9042882Svi117747 	char		*slstr;
9052882Svi117747 	int		len;
9062882Svi117747 
9072882Svi117747 	if (error != NULL)
9082882Svi117747 		*error = 0;
9092882Svi117747 
9102882Svi117747 	if (sip_msg == NULL || sip_msg->sip_msg_start_line == NULL) {
9112882Svi117747 		if (error != NULL)
9122882Svi117747 			*error = EINVAL;
9132882Svi117747 		return (NULL);
9142882Svi117747 	}
9152882Svi117747 	(void) pthread_mutex_lock(&sip_msg->sip_msg_mutex);
9162882Svi117747 	len = sip_msg->sip_msg_start_line->sip_hdr_end -
9172882Svi117747 	    sip_msg->sip_msg_start_line->sip_hdr_start - 2;
9182882Svi117747 	if ((slstr = malloc(len + 1)) == NULL) {
9192882Svi117747 		(void) pthread_mutex_unlock(&sip_msg->sip_msg_mutex);
9202882Svi117747 		if (error != NULL)
9212882Svi117747 			*error = ENOMEM;
9222882Svi117747 		return (NULL);
9232882Svi117747 	}
9242882Svi117747 	(void) strncpy(slstr, sip_msg->sip_msg_start_line->sip_hdr_start, len);
9252882Svi117747 	(void) pthread_mutex_unlock(&sip_msg->sip_msg_mutex);
9262882Svi117747 	slstr[len] = '\0';
9272882Svi117747 	return (slstr);
9282882Svi117747 }
9292882Svi117747 
9302882Svi117747 /*
9312882Svi117747  * Return the given header as a string. Caller frees string
9322882Svi117747  */
9332882Svi117747 char *
sip_hdr_to_str(sip_header_t sip_header,int * error)9342882Svi117747 sip_hdr_to_str(sip_header_t sip_header, int *error)
9352882Svi117747 {
9362882Svi117747 	char		*hdrstr;
9372882Svi117747 	char		*tmpptr;
9382882Svi117747 	_sip_header_t	*_sip_header;
9392882Svi117747 	int		len;
9402882Svi117747 
9412882Svi117747 	if (error != NULL)
9422882Svi117747 		*error = 0;
9432882Svi117747 
9442882Svi117747 	if (sip_header == NULL) {
9452882Svi117747 		if (error != NULL)
9462882Svi117747 			*error = EINVAL;
9472882Svi117747 		return (NULL);
9482882Svi117747 	}
9492882Svi117747 	_sip_header = (_sip_header_t *)sip_header;
9502882Svi117747 	if (_sip_header->sip_header_state == SIP_HEADER_DELETED) {
9512882Svi117747 		if (_sip_header->sip_hdr_sipmsg != NULL) {
9522882Svi117747 			(void) pthread_mutex_unlock(
9532882Svi117747 			    &_sip_header->sip_hdr_sipmsg->sip_msg_mutex);
9542882Svi117747 		}
9552882Svi117747 		if (error != NULL)
9562882Svi117747 			*error = EINVAL;
9572882Svi117747 		return (NULL);
9582882Svi117747 	}
9592882Svi117747 	if (_sip_header->sip_hdr_sipmsg != NULL) {
9602882Svi117747 		(void) pthread_mutex_lock(
9612882Svi117747 		    &_sip_header->sip_hdr_sipmsg->sip_msg_mutex);
9622882Svi117747 	}
9632882Svi117747 	len = _sip_header->sip_hdr_end - _sip_header->sip_hdr_start;
9642882Svi117747 	hdrstr = malloc(len);
9652882Svi117747 	if (hdrstr == NULL) {
9662882Svi117747 		if (_sip_header->sip_hdr_sipmsg != NULL) {
9672882Svi117747 			(void) pthread_mutex_unlock(
9682882Svi117747 			    &_sip_header->sip_hdr_sipmsg->sip_msg_mutex);
9692882Svi117747 		}
9702882Svi117747 		if (error != NULL)
9712882Svi117747 			*error = ENOMEM;
9722882Svi117747 		return (NULL);
9732882Svi117747 	}
9742882Svi117747 	if (_sip_header->sip_header_state == SIP_HEADER_DELETED_VAL) {
9752882Svi117747 		len = sip_copy_values(hdrstr, _sip_header);
9762882Svi117747 	} else {
9772882Svi117747 		(void) strncpy(hdrstr, _sip_header->sip_hdr_start, len);
9782882Svi117747 	}
9792882Svi117747 	if (_sip_header->sip_hdr_sipmsg != NULL) {
9802882Svi117747 		(void) pthread_mutex_unlock(
9812882Svi117747 		    &_sip_header->sip_hdr_sipmsg->sip_msg_mutex);
9822882Svi117747 	}
9832882Svi117747 	tmpptr = hdrstr + len;
9842882Svi117747 	while (*tmpptr-- != '\n') {
9852882Svi117747 		if (tmpptr == _sip_header->sip_hdr_start) {
9862882Svi117747 			free(hdrstr);
9872882Svi117747 			if (error != NULL)
9882882Svi117747 				*error = EINVAL;
9892882Svi117747 			return (NULL);
9902882Svi117747 		}
9912882Svi117747 	}
9922882Svi117747 	*tmpptr = '\0';
9932882Svi117747 	return (hdrstr);
9942882Svi117747 }
9952882Svi117747 
9962882Svi117747 /*
9972882Svi117747  * Given a param list find the named parameter.
9982882Svi117747  * Returns a pointer to the value or NULL.
9992882Svi117747  */
10002882Svi117747 sip_param_t *
sip_get_param_from_list(sip_param_t * param_list,char * param_name)10012882Svi117747 sip_get_param_from_list(sip_param_t *param_list, char *param_name)
10022882Svi117747 {
10032882Svi117747 	while (param_list != NULL) {
10042882Svi117747 		if (param_list->param_name.sip_str_len == strlen(param_name) &&
10052882Svi117747 		    strncasecmp(param_list->param_name.sip_str_ptr, param_name,
10062882Svi117747 		    strlen(param_name)) == 0) {
10072882Svi117747 			return (param_list);
10082882Svi117747 		}
10092882Svi117747 		param_list = param_list->param_next;
10102882Svi117747 	}
10112882Svi117747 	return (NULL);
10122882Svi117747 }
1013