1*2882Svi117747 /*
2*2882Svi117747  * CDDL HEADER START
3*2882Svi117747  *
4*2882Svi117747  * The contents of this file are subject to the terms of the
5*2882Svi117747  * Common Development and Distribution License (the "License").
6*2882Svi117747  * You may not use this file except in compliance with the License.
7*2882Svi117747  *
8*2882Svi117747  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*2882Svi117747  * or http://www.opensolaris.org/os/licensing.
10*2882Svi117747  * See the License for the specific language governing permissions
11*2882Svi117747  * and limitations under the License.
12*2882Svi117747  *
13*2882Svi117747  * When distributing Covered Code, include this CDDL HEADER in each
14*2882Svi117747  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*2882Svi117747  * If applicable, add the following below this CDDL HEADER, with the
16*2882Svi117747  * fields enclosed by brackets "[]" replaced with your own identifying
17*2882Svi117747  * information: Portions Copyright [yyyy] [name of copyright owner]
18*2882Svi117747  *
19*2882Svi117747  * CDDL HEADER END
20*2882Svi117747  */
21*2882Svi117747 
22*2882Svi117747 /*
23*2882Svi117747  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
24*2882Svi117747  * Use is subject to license terms.
25*2882Svi117747  */
26*2882Svi117747 
27*2882Svi117747 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*2882Svi117747 
29*2882Svi117747 #include "sip_parse_uri.h"
30*2882Svi117747 #include "sip_msg.h"
31*2882Svi117747 #include "sip_miscdefs.h"
32*2882Svi117747 #include "sip_parse_generic.h"
33*2882Svi117747 
34*2882Svi117747 sip_methods_t sip_methods[MAX_SIP_METHODS] = {
35*2882Svi117747 	{"UNKNOWN", 7},
36*2882Svi117747 	{"INVITE", 6},
37*2882Svi117747 	{"ACK", 3},
38*2882Svi117747 	{"OPTIONS", 7},
39*2882Svi117747 	{"BYE", 3},
40*2882Svi117747 	{"CANCEL", 6},
41*2882Svi117747 	{"REGISTER", 8},
42*2882Svi117747 	{"REFER", 5},
43*2882Svi117747 	{"INFO", 4},
44*2882Svi117747 	{"SUBSCRIBE", 9},
45*2882Svi117747 	{"NOTIFY", 6},
46*2882Svi117747 	{"PRACK", 5}
47*2882Svi117747 };
48*2882Svi117747 
49*2882Svi117747 /*
50*2882Svi117747  * Built-In Header function table
51*2882Svi117747  */
52*2882Svi117747 sip_header_function_t sip_header_function_table[] = {
53*2882Svi117747 	{"Unknown", NULL, sip_parse_unknown_header, NULL, NULL, NULL},
54*2882Svi117747 	{"CONTACT", "m", sip_parse_cftr_header, NULL, NULL,
55*2882Svi117747 	sip_free_cftr_header},
56*2882Svi117747 	{"FROM", "F", sip_parse_cftr_header, NULL, NULL, sip_free_cftr_header},
57*2882Svi117747 	{"TO", "T", sip_parse_cftr_header, NULL, NULL, sip_free_cftr_header},
58*2882Svi117747 	{"CONTENT-LENGTH", "l", sip_parse_clen_header, NULL, NULL,
59*2882Svi117747 	sip_free_phdr},
60*2882Svi117747 	{"CONTENT-TYPE", "c", sip_parse_ctype_header, NULL, NULL,
61*2882Svi117747 	sip_free_phdr},
62*2882Svi117747 	{"CALL-ID", "i", sip_parse_cid_header, NULL, NULL, sip_free_phdr},
63*2882Svi117747 	{"CSEQ", NULL, sip_parse_cseq_header, NULL, NULL, sip_free_phdr},
64*2882Svi117747 	{"VIA", "v", sip_parse_via_header, NULL, NULL, sip_free_phdr},
65*2882Svi117747 	{"Max-Forwards", NULL, sip_parse_maxf_header, NULL, NULL,
66*2882Svi117747 	sip_free_phdr},
67*2882Svi117747 	{"RECORD-ROUTE", NULL, sip_parse_cftr_header, NULL, NULL,
68*2882Svi117747 	sip_free_cftr_header},
69*2882Svi117747 	{"ROUTE", NULL, sip_parse_cftr_header, NULL, NULL,
70*2882Svi117747 	sip_free_cftr_header},
71*2882Svi117747 	{"ACCEPT", NULL, sip_parse_acpt_header, NULL, NULL, sip_free_phdr},
72*2882Svi117747 	{"ACCEPT-ENCODING", NULL, sip_parse_acpt_encode_header, NULL, NULL,
73*2882Svi117747 	sip_free_phdr},
74*2882Svi117747 	{"ACCEPT-LANGUAGE", NULL, sip_parse_acpt_lang_header, NULL, NULL,
75*2882Svi117747 	sip_free_phdr},
76*2882Svi117747 	{"ALERT-INFO", NULL, sip_parse_alert_header, NULL, NULL, sip_free_phdr},
77*2882Svi117747 	{"ALLOW", NULL, sip_parse_allow_header, NULL, NULL, sip_free_phdr},
78*2882Svi117747 	{"CALL-INFO", NULL, sip_parse_callinfo_header, NULL, NULL,
79*2882Svi117747 	sip_free_phdr},
80*2882Svi117747 	{"CONTENT-DISPOSITION", NULL, sip_parse_contentdis_header, NULL, NULL,
81*2882Svi117747 	sip_free_phdr},
82*2882Svi117747 	{"CONTENT-ENCODING", "e", sip_parse_contentencode_header, NULL, NULL,
83*2882Svi117747 	sip_free_phdr},
84*2882Svi117747 	{"CONTENT-LANGUAGE", NULL, sip_parse_contentlang_header, NULL, NULL,
85*2882Svi117747 	sip_free_phdr},
86*2882Svi117747 	{"DATE", NULL, sip_parse_date_header, NULL, NULL, sip_free_phdr},
87*2882Svi117747 	{"ERROR-INFO", NULL, sip_parse_errorinfo_header, NULL, NULL,
88*2882Svi117747 	sip_free_phdr},
89*2882Svi117747 	{"EXPIRES", NULL, sip_parse_expire_header, NULL, NULL, sip_free_phdr},
90*2882Svi117747 	{"IN-REPLY-TO", NULL, sip_parse_inreplyto_header, NULL, NULL,
91*2882Svi117747 	sip_free_phdr},
92*2882Svi117747 	{"MIN-EXPIRES", NULL, sip_parse_minexpire_header, NULL, NULL,
93*2882Svi117747 	sip_free_phdr},
94*2882Svi117747 	{"MIME-VERSION", NULL, sip_parse_mimeversion_header, NULL, NULL,
95*2882Svi117747 	sip_free_phdr},
96*2882Svi117747 	{"ORGANIZATION", NULL, sip_parse_org_header, NULL, NULL, sip_free_phdr},
97*2882Svi117747 	{"PRIORITY", NULL, sip_parse_priority_header, NULL, NULL,
98*2882Svi117747 	sip_free_phdr},
99*2882Svi117747 	{"REQUIRE", NULL, sip_parse_require_header, NULL, NULL, sip_free_phdr},
100*2882Svi117747 	{"REPLY-TO", NULL, sip_parse_replyto_header, NULL, NULL, sip_free_phdr},
101*2882Svi117747 	{"RETRY-AFTER", NULL, sip_parse_retryaft_header, NULL, NULL,
102*2882Svi117747 	sip_free_phdr},
103*2882Svi117747 	{"SERVER", NULL, sip_parse_server_header, NULL, NULL, sip_free_phdr},
104*2882Svi117747 	{"SUBJECT", "s", sip_parse_subject_header, NULL, NULL, sip_free_phdr},
105*2882Svi117747 	{"TIMESTAMP", NULL, sip_parse_timestamp_header, NULL, NULL,
106*2882Svi117747 	sip_free_phdr},
107*2882Svi117747 	{"UNSUPPORTED", NULL, sip_parse_usupport_header, NULL, NULL,
108*2882Svi117747 	sip_free_phdr},
109*2882Svi117747 	{"SUPPORTED", "k", sip_parse_support_header, NULL, NULL, sip_free_phdr},
110*2882Svi117747 	{"USER-AGENT", NULL, sip_parse_useragt_header, NULL, NULL,
111*2882Svi117747 	sip_free_phdr},
112*2882Svi117747 	{"WARNING", NULL, sip_parse_warn_header, NULL, NULL, sip_free_phdr},
113*2882Svi117747 	{"ALLOW-EVENTS", "u", sip_parse_allow_events_header, NULL, NULL,
114*2882Svi117747 	sip_free_phdr},
115*2882Svi117747 	{"EVENT", "o", sip_parse_event_header, NULL, NULL, sip_free_phdr},
116*2882Svi117747 	{"SUBSCRIPTION-STATE", NULL, sip_parse_substate_header, NULL, NULL,
117*2882Svi117747 	sip_free_phdr},
118*2882Svi117747 	{"AUTHORIZATION", NULL, sip_parse_author_header, NULL, NULL,
119*2882Svi117747 	sip_free_phdr},
120*2882Svi117747 	{"AUTHENTICATION-INFO", NULL, sip_parse_ainfo_header, NULL, NULL,
121*2882Svi117747 	sip_free_phdr},
122*2882Svi117747 	{"PROXY-AUTHORIZATION", NULL, sip_parse_pauthor_header, NULL, NULL,
123*2882Svi117747 	sip_free_phdr},
124*2882Svi117747 	{"PROXY-AUTHENTICATE", NULL, sip_parse_pauthen_header, NULL, NULL,
125*2882Svi117747 	sip_free_phdr},
126*2882Svi117747 	{"PROXY-REQUIRE", NULL, sip_parse_preq_header, NULL, NULL,
127*2882Svi117747 	sip_free_phdr},
128*2882Svi117747 	{"WWW-AUTHENTICATE", NULL, sip_parse_wauthen_header, NULL, NULL,
129*2882Svi117747 	sip_free_phdr},
130*2882Svi117747 	{"RSEQ", NULL, sip_parse_rseq, NULL, NULL, sip_free_phdr},
131*2882Svi117747 	{"RACK", NULL, sip_parse_rack, NULL, NULL, sip_free_phdr},
132*2882Svi117747 	{"P-ASSERTED-IDENTITY", NULL, sip_parse_passertedid, NULL, NULL,
133*2882Svi117747 	sip_free_phdr},
134*2882Svi117747 	{"P-PREFERRED-IDENTITY", NULL, sip_parse_ppreferredid, NULL, NULL,
135*2882Svi117747 	sip_free_phdr},
136*2882Svi117747 	{"PRIVACY", NULL, sip_parse_privacy_header, NULL, NULL, sip_free_phdr},
137*2882Svi117747 	{NULL, NULL, NULL, NULL, NULL, NULL},
138*2882Svi117747 };
139*2882Svi117747 
140*2882Svi117747 #define	MAX_SIP_HEADERS	\
141*2882Svi117747 	sizeof (sip_header_function_table) / sizeof (sip_header_function_t)
142*2882Svi117747 
143*2882Svi117747 /*
144*2882Svi117747  * External/application provided function table
145*2882Svi117747  */
146*2882Svi117747 sip_header_function_t *sip_header_function_table_external = NULL;
147*2882Svi117747 
148*2882Svi117747 /*
149*2882Svi117747  * Free parameter list
150*2882Svi117747  */
151*2882Svi117747 static void
152*2882Svi117747 sip_free_params(sip_param_t *param_list)
153*2882Svi117747 {
154*2882Svi117747 	sip_param_t *param, *next_param;
155*2882Svi117747 
156*2882Svi117747 	param = param_list;
157*2882Svi117747 
158*2882Svi117747 	while (param != NULL) {
159*2882Svi117747 		next_param = param->param_next;
160*2882Svi117747 		free(param);
161*2882Svi117747 		param = next_param;
162*2882Svi117747 	}
163*2882Svi117747 }
164*2882Svi117747 
165*2882Svi117747 /*
166*2882Svi117747  * Common header free routine
167*2882Svi117747  */
168*2882Svi117747 void
169*2882Svi117747 sip_free_phdr(sip_parsed_header_t *header)
170*2882Svi117747 {
171*2882Svi117747 	sip_hdr_value_t	*value;
172*2882Svi117747 	sip_hdr_value_t	*next_value;
173*2882Svi117747 
174*2882Svi117747 	if (header == NULL)
175*2882Svi117747 		return;
176*2882Svi117747 	value = (sip_hdr_value_t *)header->value;
177*2882Svi117747 	while (value != NULL) {
178*2882Svi117747 		sip_free_params(value->sip_param_list);
179*2882Svi117747 		next_value = value->sip_next_value;
180*2882Svi117747 		free(value);
181*2882Svi117747 		value = next_value;
182*2882Svi117747 	}
183*2882Svi117747 	free(header);
184*2882Svi117747 }
185*2882Svi117747 
186*2882Svi117747 /*
187*2882Svi117747  * Free Contact/From/To header
188*2882Svi117747  */
189*2882Svi117747 void
190*2882Svi117747 sip_free_cftr_header(sip_parsed_header_t *header)
191*2882Svi117747 {
192*2882Svi117747 	sip_hdr_value_t	*value;
193*2882Svi117747 	sip_hdr_value_t	*next_value;
194*2882Svi117747 
195*2882Svi117747 	if (header == NULL)
196*2882Svi117747 		return;
197*2882Svi117747 	value = (sip_hdr_value_t *)header->value;
198*2882Svi117747 	while (value != NULL) {
199*2882Svi117747 		next_value = value->sip_next_value;
200*2882Svi117747 		sip_free_params(value->sip_param_list);
201*2882Svi117747 		if (value->cftr_name != NULL)
202*2882Svi117747 			free(value->cftr_name);
203*2882Svi117747 		if (value->sip_value_parsed_uri != NULL) {
204*2882Svi117747 			sip_free_parsed_uri(value->sip_value_parsed_uri);
205*2882Svi117747 			value->sip_value_parsed_uri = NULL;
206*2882Svi117747 		}
207*2882Svi117747 		free(value);
208*2882Svi117747 		value = next_value;
209*2882Svi117747 	}
210*2882Svi117747 	free(header);
211*2882Svi117747 }
212*2882Svi117747 
213*2882Svi117747 /*
214*2882Svi117747  * Return new header
215*2882Svi117747  */
216*2882Svi117747 _sip_header_t *
217*2882Svi117747 sip_new_header(int header_size)
218*2882Svi117747 {
219*2882Svi117747 	_sip_header_t *new_header;
220*2882Svi117747 
221*2882Svi117747 	new_header = calloc(1, sizeof (_sip_header_t));
222*2882Svi117747 	if (new_header == NULL)
223*2882Svi117747 		return (NULL);
224*2882Svi117747 
225*2882Svi117747 	/*
226*2882Svi117747 	 * We are using snprintf which adds a null character
227*2882Svi117747 	 * so allocate an extra byte which is not part of
228*2882Svi117747 	 * the message header
229*2882Svi117747 	 */
230*2882Svi117747 	new_header->sip_hdr_start = calloc(1, header_size + 1);
231*2882Svi117747 	if (new_header->sip_hdr_start == NULL) {
232*2882Svi117747 		free(new_header);
233*2882Svi117747 		return (NULL);
234*2882Svi117747 	}
235*2882Svi117747 	new_header->sip_hdr_end = new_header->sip_hdr_start + header_size;
236*2882Svi117747 	new_header->sip_hdr_current = new_header->sip_hdr_start;
237*2882Svi117747 	new_header->sip_hdr_allocated = B_TRUE;
238*2882Svi117747 	return (new_header);
239*2882Svi117747 }
240*2882Svi117747 
241*2882Svi117747 /*
242*2882Svi117747  * Free the given header
243*2882Svi117747  */
244*2882Svi117747 void
245*2882Svi117747 sip_free_header(_sip_header_t *sip_header)
246*2882Svi117747 {
247*2882Svi117747 	if (sip_header->sip_hdr_allocated) {
248*2882Svi117747 		assert(sip_header->sip_hdr_start != NULL);
249*2882Svi117747 		free(sip_header->sip_hdr_start);
250*2882Svi117747 	}
251*2882Svi117747 	if (sip_header->sip_hdr_parsed != NULL) {
252*2882Svi117747 		assert(sip_header->sip_header_functions != NULL);
253*2882Svi117747 		if (sip_header->sip_header_functions->header_free != NULL) {
254*2882Svi117747 			sip_header->sip_header_functions->header_free(
255*2882Svi117747 			    sip_header->sip_hdr_parsed);
256*2882Svi117747 		}
257*2882Svi117747 	}
258*2882Svi117747 	free(sip_header);
259*2882Svi117747 }
260*2882Svi117747 
261*2882Svi117747 /*
262*2882Svi117747  * Return a copy of the header passed in.
263*2882Svi117747  */
264*2882Svi117747 _sip_header_t *
265*2882Svi117747 sip_dup_header(_sip_header_t *from)
266*2882Svi117747 {
267*2882Svi117747 	size_t		hdr_size;
268*2882Svi117747 	_sip_header_t	*to;
269*2882Svi117747 
270*2882Svi117747 	hdr_size = from->sip_hdr_end - from->sip_hdr_start;
271*2882Svi117747 	to = sip_new_header(hdr_size);
272*2882Svi117747 	if (to == NULL)
273*2882Svi117747 		return (NULL);
274*2882Svi117747 	if (from->sip_header_state == SIP_HEADER_DELETED_VAL) {
275*2882Svi117747 		to->sip_hdr_end = to->sip_hdr_start +
276*2882Svi117747 		    sip_copy_values(to->sip_hdr_start, from);
277*2882Svi117747 	} else {
278*2882Svi117747 		(void) memcpy(to->sip_hdr_start, from->sip_hdr_start, hdr_size);
279*2882Svi117747 		to->sip_hdr_end = to->sip_hdr_start + hdr_size;
280*2882Svi117747 	}
281*2882Svi117747 	to->sip_header_functions = from->sip_header_functions;
282*2882Svi117747 	return (to);
283*2882Svi117747 }
284*2882Svi117747 
285*2882Svi117747 /*
286*2882Svi117747  * Copy header with extra_param, if any, to sip_msg
287*2882Svi117747  */
288*2882Svi117747 int
289*2882Svi117747 _sip_copy_header(_sip_msg_t *sip_msg, _sip_header_t *header, char *extra_param,
290*2882Svi117747     boolean_t skip_crlf)
291*2882Svi117747 {
292*2882Svi117747 	_sip_header_t	*new_header;
293*2882Svi117747 	int		hdrlen;
294*2882Svi117747 	int		extra_len = 0;
295*2882Svi117747 	int		ncrlf = 0;
296*2882Svi117747 	char		*p;
297*2882Svi117747 
298*2882Svi117747 #ifdef	__solaris__
299*2882Svi117747 	assert(mutex_held(&sip_msg->sip_msg_mutex));
300*2882Svi117747 #endif
301*2882Svi117747 	if (extra_param != NULL) {
302*2882Svi117747 		extra_len = SIP_SPACE_LEN + sizeof (char) + SIP_SPACE_LEN +
303*2882Svi117747 		    strlen(extra_param);
304*2882Svi117747 	}
305*2882Svi117747 	/*
306*2882Svi117747 	 * Just take one if there are more, i.e. if this is the last header
307*2882Svi117747 	 * before the content.
308*2882Svi117747 	 */
309*2882Svi117747 	if (skip_crlf) {
310*2882Svi117747 		if (header->sip_hdr_end - strlen(SIP_CRLF) <=
311*2882Svi117747 		    header->sip_hdr_start) {
312*2882Svi117747 			goto proceed;
313*2882Svi117747 		}
314*2882Svi117747 		p = header->sip_hdr_end - strlen(SIP_CRLF);
315*2882Svi117747 		while (strncmp(SIP_CRLF, p, strlen(SIP_CRLF)) == 0) {
316*2882Svi117747 			ncrlf++;
317*2882Svi117747 			if (p - strlen(SIP_CRLF) < header->sip_hdr_start)
318*2882Svi117747 				break;
319*2882Svi117747 			p -= strlen(SIP_CRLF);
320*2882Svi117747 		}
321*2882Svi117747 		/*
322*2882Svi117747 		 * Take one CRLF.
323*2882Svi117747 		 */
324*2882Svi117747 		ncrlf = (ncrlf - 1) * strlen(SIP_CRLF);
325*2882Svi117747 	}
326*2882Svi117747 proceed:
327*2882Svi117747 	hdrlen = header->sip_hdr_end - header->sip_hdr_start - ncrlf;
328*2882Svi117747 	new_header = sip_new_header(hdrlen + extra_len);
329*2882Svi117747 	if (new_header == NULL)
330*2882Svi117747 		return (ENOMEM);
331*2882Svi117747 	if (header->sip_header_state == SIP_HEADER_DELETED_VAL) {
332*2882Svi117747 		int	len;
333*2882Svi117747 
334*2882Svi117747 		len = sip_copy_values(new_header->sip_hdr_start, header);
335*2882Svi117747 		new_header->sip_hdr_end = new_header->sip_hdr_start + len;
336*2882Svi117747 		hdrlen = hdrlen - len + extra_len;
337*2882Svi117747 	} else {
338*2882Svi117747 		(void) memcpy(new_header->sip_hdr_start, header->sip_hdr_start,
339*2882Svi117747 		    hdrlen);
340*2882Svi117747 		new_header->sip_hdr_end = new_header->sip_hdr_start + hdrlen;
341*2882Svi117747 		hdrlen = extra_len;
342*2882Svi117747 	}
343*2882Svi117747 	if (extra_param != NULL) {
344*2882Svi117747 		/*
345*2882Svi117747 		 * Find CR
346*2882Svi117747 		 */
347*2882Svi117747 		if (sip_find_cr(new_header) != 0) {
348*2882Svi117747 			sip_free_header(new_header);
349*2882Svi117747 			return (EINVAL);
350*2882Svi117747 		}
351*2882Svi117747 		hdrlen += new_header->sip_hdr_end - new_header->sip_hdr_current;
352*2882Svi117747 		(void) snprintf(new_header->sip_hdr_current, hdrlen + 1,
353*2882Svi117747 		    " %c %s%s", SIP_SEMI, extra_param, SIP_CRLF);
354*2882Svi117747 	}
355*2882Svi117747 
356*2882Svi117747 	new_header->sip_hdr_end += extra_len;
357*2882Svi117747 	new_header->sip_header_functions = header->sip_header_functions;
358*2882Svi117747 	_sip_add_header(sip_msg, new_header, B_TRUE, B_FALSE, NULL);
359*2882Svi117747 	return (0);
360*2882Svi117747 }
361*2882Svi117747 
362*2882Svi117747 /*
363*2882Svi117747  * Copy all "header_name" headers from _old_msg to _new_msg
364*2882Svi117747  */
365*2882Svi117747 int
366*2882Svi117747 _sip_find_and_copy_all_header(_sip_msg_t *_old_msg, _sip_msg_t *_new_msg,
367*2882Svi117747     char *header_name)
368*2882Svi117747 {
369*2882Svi117747 	_sip_header_t	*header;
370*2882Svi117747 	int		ret = 0;
371*2882Svi117747 
372*2882Svi117747 	if (_old_msg == NULL || _new_msg == NULL)
373*2882Svi117747 		return (EINVAL);
374*2882Svi117747 #ifdef	__solaris__
375*2882Svi117747 	assert(mutex_held(&_old_msg->sip_msg_mutex));
376*2882Svi117747 #endif
377*2882Svi117747 	if (_old_msg != _new_msg)
378*2882Svi117747 		(void) pthread_mutex_lock(&_new_msg->sip_msg_mutex);
379*2882Svi117747 	header = sip_search_for_header(_old_msg, header_name, NULL);
380*2882Svi117747 	while (header != NULL) {
381*2882Svi117747 		ret = _sip_copy_header(_new_msg, header, NULL, B_TRUE);
382*2882Svi117747 		if (ret != 0)
383*2882Svi117747 			break;
384*2882Svi117747 		header = sip_search_for_header(_old_msg, header_name, header);
385*2882Svi117747 	}
386*2882Svi117747 	if (_old_msg != _new_msg)
387*2882Svi117747 		(void) pthread_mutex_unlock(&_new_msg->sip_msg_mutex);
388*2882Svi117747 	return (ret);
389*2882Svi117747 }
390*2882Svi117747 
391*2882Svi117747 /*
392*2882Svi117747  * Copy header_name from _old_msg to _new_msg with extra_parm.
393*2882Svi117747  */
394*2882Svi117747 int
395*2882Svi117747 _sip_find_and_copy_header(sip_msg_t _old_msg, sip_msg_t _new_msg,
396*2882Svi117747     char *header_name, char *extra_param, boolean_t lock_newmsg)
397*2882Svi117747 {
398*2882Svi117747 	_sip_header_t	*header;
399*2882Svi117747 	int		ret;
400*2882Svi117747 
401*2882Svi117747 	if (_old_msg == NULL || _new_msg == NULL)
402*2882Svi117747 		return (EINVAL);
403*2882Svi117747 #ifdef	__solaris__
404*2882Svi117747 	assert(mutex_held(&_old_msg->sip_msg_mutex));
405*2882Svi117747 #endif
406*2882Svi117747 	header = sip_search_for_header(_old_msg, header_name, NULL);
407*2882Svi117747 	if (header == NULL)
408*2882Svi117747 		return (EINVAL);
409*2882Svi117747 	if (lock_newmsg)
410*2882Svi117747 		(void) pthread_mutex_lock(&_new_msg->sip_msg_mutex);
411*2882Svi117747 	ret = _sip_copy_header(_new_msg, header, extra_param, B_TRUE);
412*2882Svi117747 	if (lock_newmsg)
413*2882Svi117747 		(void) pthread_mutex_unlock(&_new_msg->sip_msg_mutex);
414*2882Svi117747 	return (ret);
415*2882Svi117747 }
416*2882Svi117747 
417*2882Svi117747 /*
418*2882Svi117747  * Copy all headers from old_msg to new_msg
419*2882Svi117747  */
420*2882Svi117747 int
421*2882Svi117747 sip_copy_all_headers(sip_msg_t old_msg, sip_msg_t new_msg)
422*2882Svi117747 {
423*2882Svi117747 	_sip_header_t	*header;
424*2882Svi117747 	_sip_msg_t	*_old_msg;
425*2882Svi117747 	_sip_msg_t	*_new_msg;
426*2882Svi117747 	int		ret = 0;
427*2882Svi117747 
428*2882Svi117747 	if (old_msg == NULL || new_msg == NULL)
429*2882Svi117747 		return (EINVAL);
430*2882Svi117747 	_old_msg = (_sip_msg_t *)old_msg;
431*2882Svi117747 	_new_msg = (_sip_msg_t *)new_msg;
432*2882Svi117747 
433*2882Svi117747 	(void) pthread_mutex_lock(&_old_msg->sip_msg_mutex);
434*2882Svi117747 	(void) pthread_mutex_lock(&_new_msg->sip_msg_mutex);
435*2882Svi117747 	header = sip_search_for_header(_old_msg, NULL, NULL);
436*2882Svi117747 	while (header != NULL) {
437*2882Svi117747 		ret = _sip_copy_header(_new_msg, header, NULL, B_FALSE);
438*2882Svi117747 		if (ret != 0)
439*2882Svi117747 			goto done;
440*2882Svi117747 		header = sip_search_for_header(_old_msg, NULL, header);
441*2882Svi117747 	}
442*2882Svi117747 done:
443*2882Svi117747 	(void) pthread_mutex_unlock(&_new_msg->sip_msg_mutex);
444*2882Svi117747 	(void) pthread_mutex_unlock(&_old_msg->sip_msg_mutex);
445*2882Svi117747 	return (ret);
446*2882Svi117747 }
447*2882Svi117747 
448*2882Svi117747 /*
449*2882Svi117747  * Copy start line from msg to sip_msg
450*2882Svi117747  */
451*2882Svi117747 int
452*2882Svi117747 sip_copy_start_line(sip_msg_t msg, sip_msg_t sip_msg)
453*2882Svi117747 {
454*2882Svi117747 	int		len;
455*2882Svi117747 	_sip_header_t	*new_header;
456*2882Svi117747 	_sip_msg_t	*_old_msg;
457*2882Svi117747 	_sip_msg_t	*_sip_msg;
458*2882Svi117747 
459*2882Svi117747 	if (msg == NULL || sip_msg == NULL)
460*2882Svi117747 		return (EINVAL);
461*2882Svi117747 	_old_msg = (_sip_msg_t *)msg;
462*2882Svi117747 	_sip_msg = (_sip_msg_t *)sip_msg;
463*2882Svi117747 
464*2882Svi117747 	(void) pthread_mutex_lock(&_old_msg->sip_msg_mutex);
465*2882Svi117747 	if (_old_msg->sip_msg_start_line == NULL) {
466*2882Svi117747 		(void) pthread_mutex_unlock(&_old_msg->sip_msg_mutex);
467*2882Svi117747 		return (EINVAL);
468*2882Svi117747 	}
469*2882Svi117747 	len = _old_msg->sip_msg_start_line->sip_hdr_end -
470*2882Svi117747 	    _old_msg->sip_msg_start_line->sip_hdr_start;
471*2882Svi117747 	new_header = sip_new_header(len);
472*2882Svi117747 	if (new_header == NULL) {
473*2882Svi117747 		(void) pthread_mutex_unlock(&_old_msg->sip_msg_mutex);
474*2882Svi117747 		return (ENOMEM);
475*2882Svi117747 	}
476*2882Svi117747 	new_header->sip_hdr_sipmsg = _sip_msg;
477*2882Svi117747 	(void) pthread_mutex_lock(&sip_msg->sip_msg_mutex);
478*2882Svi117747 	_sip_msg->sip_msg_start_line = new_header;
479*2882Svi117747 	_sip_msg->sip_msg_len = len;
480*2882Svi117747 	(void) strncpy(_sip_msg->sip_msg_start_line->sip_hdr_start,
481*2882Svi117747 	    _old_msg->sip_msg_start_line->sip_hdr_start, len);
482*2882Svi117747 	(void) sip_parse_first_line(_sip_msg->sip_msg_start_line,
483*2882Svi117747 	    &_sip_msg->sip_msg_req_res);
484*2882Svi117747 	(void) pthread_mutex_unlock(&_old_msg->sip_msg_mutex);
485*2882Svi117747 	(void) pthread_mutex_unlock(&sip_msg->sip_msg_mutex);
486*2882Svi117747 	return (0);
487*2882Svi117747 }
488*2882Svi117747 
489*2882Svi117747 /*
490*2882Svi117747  * Delete start line from sip_msg
491*2882Svi117747  */
492*2882Svi117747 int
493*2882Svi117747 sip_delete_start_line_locked(_sip_msg_t *_sip_msg)
494*2882Svi117747 {
495*2882Svi117747 	_sip_header_t	*header;
496*2882Svi117747 	_sip_header_t	*next_header;
497*2882Svi117747 
498*2882Svi117747 	if (_sip_msg->sip_msg_start_line == NULL)
499*2882Svi117747 		return (EINVAL);
500*2882Svi117747 
501*2882Svi117747 	header = _sip_msg->sip_msg_start_line;
502*2882Svi117747 	while (header != NULL) {
503*2882Svi117747 		next_header = header->sip_hdr_next;
504*2882Svi117747 		_sip_msg->sip_msg_len -= (header->sip_hdr_end -
505*2882Svi117747 		    header->sip_hdr_start);
506*2882Svi117747 		sip_free_header(header);
507*2882Svi117747 		header = next_header;
508*2882Svi117747 	}
509*2882Svi117747 	_sip_msg->sip_msg_start_line = NULL;
510*2882Svi117747 
511*2882Svi117747 	/*
512*2882Svi117747 	 * Also delete the sip_msg_req_res info since we don't have a start
513*2882Svi117747 	 * line.
514*2882Svi117747 	 */
515*2882Svi117747 	while (_sip_msg->sip_msg_req_res != NULL) {
516*2882Svi117747 		sip_message_type_t	*sip_msg_type_ptr;
517*2882Svi117747 
518*2882Svi117747 		sip_msg_type_ptr = _sip_msg->sip_msg_req_res->sip_next;
519*2882Svi117747 		if (_sip_msg->sip_msg_req_res->is_request) {
520*2882Svi117747 			sip_request_t	*reqline;
521*2882Svi117747 
522*2882Svi117747 			reqline = &_sip_msg->sip_msg_req_res->U.sip_request;
523*2882Svi117747 			if (reqline->sip_parse_uri != NULL) {
524*2882Svi117747 				sip_free_parsed_uri(reqline->sip_parse_uri);
525*2882Svi117747 				reqline->sip_parse_uri = NULL;
526*2882Svi117747 			}
527*2882Svi117747 		}
528*2882Svi117747 		free(_sip_msg->sip_msg_req_res);
529*2882Svi117747 		_sip_msg->sip_msg_req_res = sip_msg_type_ptr;
530*2882Svi117747 	}
531*2882Svi117747 	return (0);
532*2882Svi117747 }
533*2882Svi117747 
534*2882Svi117747 
535*2882Svi117747 /*
536*2882Svi117747  * Delete start line from sip_msg
537*2882Svi117747  */
538*2882Svi117747 int
539*2882Svi117747 sip_delete_start_line(sip_msg_t sip_msg)
540*2882Svi117747 {
541*2882Svi117747 	_sip_msg_t	*_sip_msg;
542*2882Svi117747 	int		ret;
543*2882Svi117747 
544*2882Svi117747 	if (sip_msg == NULL)
545*2882Svi117747 		return (EINVAL);
546*2882Svi117747 
547*2882Svi117747 	_sip_msg = (_sip_msg_t *)sip_msg;
548*2882Svi117747 	(void) pthread_mutex_lock(&_sip_msg->sip_msg_mutex);
549*2882Svi117747 	ret = sip_delete_start_line_locked(_sip_msg);
550*2882Svi117747 	(void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
551*2882Svi117747 
552*2882Svi117747 	return (ret);
553*2882Svi117747 }
554*2882Svi117747 
555*2882Svi117747 /*
556*2882Svi117747  * Delete all headers from _sip_msg
557*2882Svi117747  */
558*2882Svi117747 void
559*2882Svi117747 sip_delete_all_headers(_sip_msg_t *_sip_msg)
560*2882Svi117747 {
561*2882Svi117747 	_sip_header_t *header;
562*2882Svi117747 
563*2882Svi117747 #ifdef	__solaris__
564*2882Svi117747 	assert(mutex_held(&_sip_msg->sip_msg_mutex));
565*2882Svi117747 #endif
566*2882Svi117747 
567*2882Svi117747 	header = _sip_msg->sip_msg_headers_start;
568*2882Svi117747 	while (header != NULL) {
569*2882Svi117747 		_sip_header_t *next_header;
570*2882Svi117747 		next_header = header->sip_hdr_next;
571*2882Svi117747 		sip_free_header(header);
572*2882Svi117747 		header = next_header;
573*2882Svi117747 	}
574*2882Svi117747 	_sip_msg->sip_msg_headers_start = NULL;
575*2882Svi117747 	_sip_msg->sip_msg_headers_end = NULL;
576*2882Svi117747 }
577*2882Svi117747 
578*2882Svi117747 /*
579*2882Svi117747  * Delete and free the named header. If header_name is null
580*2882Svi117747  * free all headers.
581*2882Svi117747  */
582*2882Svi117747 void
583*2882Svi117747 sip_delete_headers(sip_msg_t sip_msg, char *header_name)
584*2882Svi117747 {
585*2882Svi117747 	_sip_header_t *header;
586*2882Svi117747 	_sip_msg_t *_sip_msg;
587*2882Svi117747 
588*2882Svi117747 	_sip_msg = (_sip_msg_t *)sip_msg;
589*2882Svi117747 #ifdef	__solaris__
590*2882Svi117747 	assert(mutex_held(&_sip_msg->sip_msg_mutex));
591*2882Svi117747 #endif
592*2882Svi117747 	header = sip_search_for_header(_sip_msg, header_name, NULL);
593*2882Svi117747 	if (header == NULL)
594*2882Svi117747 		return;
595*2882Svi117747 	while (header != NULL) {
596*2882Svi117747 		if (_sip_msg->sip_msg_headers_start == header) {
597*2882Svi117747 			_sip_msg->sip_msg_headers_start = header->sip_hdr_next;
598*2882Svi117747 		} else {
599*2882Svi117747 			header->sip_hdr_prev->sip_hdr_next =
600*2882Svi117747 			    header->sip_hdr_next;
601*2882Svi117747 		}
602*2882Svi117747 		if (_sip_msg->sip_msg_headers_end == header) {
603*2882Svi117747 			_sip_msg->sip_msg_headers_end = header->sip_hdr_prev;
604*2882Svi117747 		} else {
605*2882Svi117747 			header->sip_hdr_next->sip_hdr_prev =
606*2882Svi117747 			    header->sip_hdr_prev;
607*2882Svi117747 		}
608*2882Svi117747 		sip_free_header(header);
609*2882Svi117747 		if (header_name != NULL)
610*2882Svi117747 			return;
611*2882Svi117747 		else
612*2882Svi117747 			header = sip_search_for_header(_sip_msg, NULL, NULL);
613*2882Svi117747 	}
614*2882Svi117747 }
615*2882Svi117747 
616*2882Svi117747 /*
617*2882Svi117747  * Add a header to sip_msg. If header_name is provided then the new header
618*2882Svi117747  * is added before that header, if first is set, or after. If append is
619*2882Svi117747  * set, then the header is added to the end of the header list.
620*2882Svi117747  */
621*2882Svi117747 void
622*2882Svi117747 _sip_add_header(_sip_msg_t *sip_msg, _sip_header_t *new_header,
623*2882Svi117747     boolean_t append, boolean_t first, char *header_name)
624*2882Svi117747 {
625*2882Svi117747 	_sip_header_t	*header = NULL;
626*2882Svi117747 
627*2882Svi117747 	if (sip_msg == NULL || new_header == NULL)
628*2882Svi117747 		return;
629*2882Svi117747 #ifdef	__solaris__
630*2882Svi117747 	assert(mutex_held(&sip_msg->sip_msg_mutex));
631*2882Svi117747 #endif
632*2882Svi117747 	new_header->sip_hdr_sipmsg = sip_msg;
633*2882Svi117747 	if (header_name != NULL) {
634*2882Svi117747 		_sip_header_t	*header_tmp;
635*2882Svi117747 
636*2882Svi117747 		header = sip_search_for_header(sip_msg, header_name, NULL);
637*2882Svi117747 		header_tmp = header;
638*2882Svi117747 		if (!first) {
639*2882Svi117747 			while (header != NULL) {
640*2882Svi117747 				header_tmp = header;
641*2882Svi117747 				header = sip_search_for_header(sip_msg,
642*2882Svi117747 				    header_name, header);
643*2882Svi117747 			}
644*2882Svi117747 		}
645*2882Svi117747 		header = header_tmp;
646*2882Svi117747 		if (header == NULL)
647*2882Svi117747 			append =  B_TRUE;
648*2882Svi117747 	}
649*2882Svi117747 
650*2882Svi117747 	if (header != NULL) {
651*2882Svi117747 		if (append) {
652*2882Svi117747 			new_header->sip_hdr_prev = header;
653*2882Svi117747 			if (sip_msg->sip_msg_headers_end == header) {
654*2882Svi117747 				sip_msg->sip_msg_headers_end = new_header;
655*2882Svi117747 				new_header->sip_hdr_next = NULL;
656*2882Svi117747 			} else {
657*2882Svi117747 				header->sip_hdr_next->sip_hdr_prev = new_header;
658*2882Svi117747 				new_header->sip_hdr_next = header->sip_hdr_next;
659*2882Svi117747 			}
660*2882Svi117747 			header->sip_hdr_next = new_header;
661*2882Svi117747 		} else {
662*2882Svi117747 			new_header->sip_hdr_next = header;
663*2882Svi117747 			if (sip_msg->sip_msg_headers_start == header) {
664*2882Svi117747 				sip_msg->sip_msg_headers_start = new_header;
665*2882Svi117747 				new_header->sip_hdr_prev = NULL;
666*2882Svi117747 			} else {
667*2882Svi117747 				header->sip_hdr_prev->sip_hdr_next = new_header;
668*2882Svi117747 				new_header->sip_hdr_prev = header->sip_hdr_prev;
669*2882Svi117747 			}
670*2882Svi117747 			header->sip_hdr_prev = new_header;
671*2882Svi117747 		}
672*2882Svi117747 	} else {
673*2882Svi117747 		if (append) {
674*2882Svi117747 			if (sip_msg->sip_msg_headers_end != NULL) {
675*2882Svi117747 				sip_msg->sip_msg_headers_end->sip_hdr_next =
676*2882Svi117747 				    new_header;
677*2882Svi117747 			} else {
678*2882Svi117747 				sip_msg->sip_msg_headers_start = new_header;
679*2882Svi117747 			}
680*2882Svi117747 			new_header->sip_hdr_prev =
681*2882Svi117747 			    sip_msg->sip_msg_headers_end;
682*2882Svi117747 			new_header->sip_hdr_next = NULL;
683*2882Svi117747 			sip_msg->sip_msg_headers_end = new_header;
684*2882Svi117747 		} else {
685*2882Svi117747 			if (sip_msg->sip_msg_headers_start != NULL) {
686*2882Svi117747 				sip_msg->sip_msg_headers_start->sip_hdr_prev =
687*2882Svi117747 				    new_header;
688*2882Svi117747 			} else {
689*2882Svi117747 				sip_msg->sip_msg_headers_end = new_header;
690*2882Svi117747 			}
691*2882Svi117747 			new_header->sip_hdr_next =
692*2882Svi117747 			    sip_msg->sip_msg_headers_start;
693*2882Svi117747 			new_header->sip_hdr_prev = NULL;
694*2882Svi117747 			sip_msg->sip_msg_headers_start = new_header;
695*2882Svi117747 		}
696*2882Svi117747 	}
697*2882Svi117747 	sip_msg->sip_msg_len += new_header->sip_hdr_end -
698*2882Svi117747 	    new_header->sip_hdr_start;
699*2882Svi117747 }
700*2882Svi117747 
701*2882Svi117747 /*
702*2882Svi117747  * Scan through the function table and return the entry for the given header
703*2882Svi117747  * type.
704*2882Svi117747  */
705*2882Svi117747 sip_header_function_t *
706*2882Svi117747 _sip_get_header_functions(sip_header_function_t *sip_header_function_table,
707*2882Svi117747     _sip_header_t *sip_header, char *header_name)
708*2882Svi117747 {
709*2882Svi117747 	int	len;
710*2882Svi117747 	int	i = 0;
711*2882Svi117747 
712*2882Svi117747 	if (sip_header == NULL && header_name == NULL)
713*2882Svi117747 		return (NULL);
714*2882Svi117747 
715*2882Svi117747 	/*
716*2882Svi117747 	 * If header_name is NULL we first have to locate the name
717*2882Svi117747 	 */
718*2882Svi117747 	if (header_name == NULL) {
719*2882Svi117747 		if (sip_skip_white_space(sip_header) != 0) {
720*2882Svi117747 			return (NULL);
721*2882Svi117747 		}
722*2882Svi117747 		header_name = sip_header->sip_hdr_current;
723*2882Svi117747 		if (sip_find_separator(sip_header, SIP_HCOLON, (char)NULL,
724*2882Svi117747 		    (char)NULL) != 0) {
725*2882Svi117747 			return (NULL);
726*2882Svi117747 		}
727*2882Svi117747 		len = sip_header->sip_hdr_current - header_name;
728*2882Svi117747 	} else {
729*2882Svi117747 		len = strlen(header_name);
730*2882Svi117747 	}
731*2882Svi117747 
732*2882Svi117747 	if (len > 0) {
733*2882Svi117747 		while (sip_header_function_table[i].header_name != NULL ||
734*2882Svi117747 		    sip_header_function_table[i].header_short_name != NULL) {
735*2882Svi117747 			if (sip_header_function_table[i].header_name != NULL &&
736*2882Svi117747 			    len ==
737*2882Svi117747 			    strlen(sip_header_function_table[i].header_name)) {
738*2882Svi117747 				if (strncasecmp(header_name,
739*2882Svi117747 				    sip_header_function_table[i].
740*2882Svi117747 				    header_name, len) == 0) {
741*2882Svi117747 					break;
742*2882Svi117747 				}
743*2882Svi117747 			} else if (sip_header_function_table[i].
744*2882Svi117747 			    header_short_name != NULL && len ==
745*2882Svi117747 			    strlen(sip_header_function_table[i].
746*2882Svi117747 			    header_short_name)) {
747*2882Svi117747 				if (strncasecmp(header_name,
748*2882Svi117747 				    sip_header_function_table[i].
749*2882Svi117747 				    header_short_name, len) == 0) {
750*2882Svi117747 					break;
751*2882Svi117747 				}
752*2882Svi117747 			}
753*2882Svi117747 			i++;
754*2882Svi117747 		}
755*2882Svi117747 	}
756*2882Svi117747 
757*2882Svi117747 	if (sip_header != NULL)
758*2882Svi117747 		sip_header->sip_hdr_current = sip_header->sip_hdr_start;
759*2882Svi117747 	if (sip_header_function_table[i].header_name == NULL)
760*2882Svi117747 		return (NULL);
761*2882Svi117747 	return (&sip_header_function_table[i]);
762*2882Svi117747 }
763*2882Svi117747 
764*2882Svi117747 /*
765*2882Svi117747  * Return the entry from the function table for the given header
766*2882Svi117747  */
767*2882Svi117747 sip_header_function_t *
768*2882Svi117747 sip_get_header_functions(_sip_header_t *sip_header, char *header_name)
769*2882Svi117747 {
770*2882Svi117747 	sip_header_function_t	*func;
771*2882Svi117747 	sip_header_function_t	*header_f_table = NULL;
772*2882Svi117747 
773*2882Svi117747 	if (sip_header_function_table_external != NULL) {
774*2882Svi117747 		header_f_table = _sip_get_header_functions(
775*2882Svi117747 		    sip_header_function_table_external,
776*2882Svi117747 		    sip_header, header_name);
777*2882Svi117747 		if (header_f_table != NULL)
778*2882Svi117747 			return (header_f_table);
779*2882Svi117747 	}
780*2882Svi117747 	func = _sip_get_header_functions(sip_header_function_table, sip_header,
781*2882Svi117747 	    header_name);
782*2882Svi117747 	return (func);
783*2882Svi117747 }
784*2882Svi117747 
785*2882Svi117747 /*
786*2882Svi117747  * Search for the header name passed in.
787*2882Svi117747  */
788*2882Svi117747 _sip_header_t *
789*2882Svi117747 sip_search_for_header(_sip_msg_t *sip_msg, char *header_name,
790*2882Svi117747     _sip_header_t *old_header)
791*2882Svi117747 {
792*2882Svi117747 	int			len = 0;
793*2882Svi117747 	int			full_len = 0;
794*2882Svi117747 	int			compact_len = 0;
795*2882Svi117747 	_sip_header_t		*header = NULL;
796*2882Svi117747 	char			*compact_name = NULL;
797*2882Svi117747 	char			*full_name = NULL;
798*2882Svi117747 	sip_header_function_t	*header_f_table = NULL;
799*2882Svi117747 
800*2882Svi117747 	if (sip_msg == NULL)
801*2882Svi117747 		return (NULL);
802*2882Svi117747 #ifdef	__solaris__
803*2882Svi117747 	assert(mutex_held(&sip_msg->sip_msg_mutex));
804*2882Svi117747 #endif
805*2882Svi117747 
806*2882Svi117747 	if (header_name != NULL) {
807*2882Svi117747 		header_f_table = sip_get_header_functions(NULL, header_name);
808*2882Svi117747 		if (header_f_table != NULL) {
809*2882Svi117747 			full_name = header_f_table->header_name;
810*2882Svi117747 			compact_name = header_f_table->header_short_name;
811*2882Svi117747 			if (full_name != NULL)
812*2882Svi117747 				full_len = strlen(full_name);
813*2882Svi117747 			if (compact_name != NULL)
814*2882Svi117747 				compact_len = strlen(compact_name);
815*2882Svi117747 		} else {
816*2882Svi117747 			header_f_table = &sip_header_function_table[0];
817*2882Svi117747 			full_name = header_name;
818*2882Svi117747 			full_len  = strlen(full_name);
819*2882Svi117747 		}
820*2882Svi117747 	}
821*2882Svi117747 
822*2882Svi117747 	if (old_header != NULL)
823*2882Svi117747 		header = old_header->sip_hdr_next;
824*2882Svi117747 	else
825*2882Svi117747 		header = sip_msg->sip_msg_headers_start;
826*2882Svi117747 
827*2882Svi117747 	while (header != NULL) {
828*2882Svi117747 
829*2882Svi117747 		if (header->sip_header_state == SIP_HEADER_DELETED) {
830*2882Svi117747 			header = header->sip_hdr_next;
831*2882Svi117747 			continue;
832*2882Svi117747 		}
833*2882Svi117747 
834*2882Svi117747 		if (compact_len == 0 && full_len == 0)
835*2882Svi117747 			break;
836*2882Svi117747 
837*2882Svi117747 		header->sip_hdr_current = header->sip_hdr_start;
838*2882Svi117747 
839*2882Svi117747 		if (sip_skip_white_space(header)) {
840*2882Svi117747 			header = header->sip_hdr_next;
841*2882Svi117747 			continue;
842*2882Svi117747 		}
843*2882Svi117747 
844*2882Svi117747 		len = header->sip_hdr_end - header->sip_hdr_current;
845*2882Svi117747 
846*2882Svi117747 		if (full_name != NULL && (full_len <= len) &&
847*2882Svi117747 		    strncasecmp(header->sip_hdr_current, full_name,
848*2882Svi117747 		    full_len) == 0) {
849*2882Svi117747 			header->sip_hdr_current += full_len;
850*2882Svi117747 			if (sip_skip_white_space(header)) {
851*2882Svi117747 				header = header->sip_hdr_next;
852*2882Svi117747 				continue;
853*2882Svi117747 			}
854*2882Svi117747 
855*2882Svi117747 			if (*header->sip_hdr_current == SIP_HCOLON) {
856*2882Svi117747 				header_name = full_name;
857*2882Svi117747 				break;
858*2882Svi117747 			}
859*2882Svi117747 		}
860*2882Svi117747 
861*2882Svi117747 		if (compact_name != NULL && (compact_len <= len) &&
862*2882Svi117747 		    strncasecmp(header->sip_hdr_current, compact_name,
863*2882Svi117747 		    compact_len) == 0) {
864*2882Svi117747 			header->sip_hdr_current += compact_len;
865*2882Svi117747 			if (sip_skip_white_space(header)) {
866*2882Svi117747 				header = header->sip_hdr_next;
867*2882Svi117747 				continue;
868*2882Svi117747 			}
869*2882Svi117747 			if (*header->sip_hdr_current == SIP_HCOLON) {
870*2882Svi117747 				header_name = compact_name;
871*2882Svi117747 				break;
872*2882Svi117747 			}
873*2882Svi117747 		}
874*2882Svi117747 		header = header->sip_hdr_next;
875*2882Svi117747 	}
876*2882Svi117747 
877*2882Svi117747 	if (header != NULL) {
878*2882Svi117747 		header->sip_hdr_current = header->sip_hdr_start;
879*2882Svi117747 		if (header_f_table == NULL) {
880*2882Svi117747 			header_f_table =
881*2882Svi117747 			    sip_get_header_functions(header, header_name);
882*2882Svi117747 			if (header_f_table == NULL)
883*2882Svi117747 				header_f_table = &sip_header_function_table[0];
884*2882Svi117747 		}
885*2882Svi117747 
886*2882Svi117747 		header->sip_header_functions = header_f_table;
887*2882Svi117747 	}
888*2882Svi117747 	return (header);
889*2882Svi117747 }
890*2882Svi117747 
891*2882Svi117747 /*
892*2882Svi117747  * Return the start line as a string. Caller frees string
893*2882Svi117747  */
894*2882Svi117747 char *
895*2882Svi117747 _sip_startline_to_str(_sip_msg_t *sip_msg, int *error)
896*2882Svi117747 {
897*2882Svi117747 	char		*slstr;
898*2882Svi117747 	int		len;
899*2882Svi117747 
900*2882Svi117747 	if (error != NULL)
901*2882Svi117747 		*error = 0;
902*2882Svi117747 
903*2882Svi117747 	if (sip_msg == NULL || sip_msg->sip_msg_start_line == NULL) {
904*2882Svi117747 		if (error != NULL)
905*2882Svi117747 			*error = EINVAL;
906*2882Svi117747 		return (NULL);
907*2882Svi117747 	}
908*2882Svi117747 	(void) pthread_mutex_lock(&sip_msg->sip_msg_mutex);
909*2882Svi117747 	len = sip_msg->sip_msg_start_line->sip_hdr_end -
910*2882Svi117747 	    sip_msg->sip_msg_start_line->sip_hdr_start - 2;
911*2882Svi117747 	if ((slstr = malloc(len + 1)) == NULL) {
912*2882Svi117747 		(void) pthread_mutex_unlock(&sip_msg->sip_msg_mutex);
913*2882Svi117747 		if (error != NULL)
914*2882Svi117747 			*error = ENOMEM;
915*2882Svi117747 		return (NULL);
916*2882Svi117747 	}
917*2882Svi117747 	(void) strncpy(slstr, sip_msg->sip_msg_start_line->sip_hdr_start, len);
918*2882Svi117747 	(void) pthread_mutex_unlock(&sip_msg->sip_msg_mutex);
919*2882Svi117747 	slstr[len] = '\0';
920*2882Svi117747 	return (slstr);
921*2882Svi117747 }
922*2882Svi117747 
923*2882Svi117747 /*
924*2882Svi117747  * Return the given header as a string. Caller frees string
925*2882Svi117747  */
926*2882Svi117747 char *
927*2882Svi117747 sip_hdr_to_str(sip_header_t sip_header, int *error)
928*2882Svi117747 {
929*2882Svi117747 	char		*hdrstr;
930*2882Svi117747 	char		*tmpptr;
931*2882Svi117747 	_sip_header_t	*_sip_header;
932*2882Svi117747 	int		len;
933*2882Svi117747 
934*2882Svi117747 	if (error != NULL)
935*2882Svi117747 		*error = 0;
936*2882Svi117747 
937*2882Svi117747 	if (sip_header == NULL) {
938*2882Svi117747 		if (error != NULL)
939*2882Svi117747 			*error = EINVAL;
940*2882Svi117747 		return (NULL);
941*2882Svi117747 	}
942*2882Svi117747 	_sip_header = (_sip_header_t *)sip_header;
943*2882Svi117747 	if (_sip_header->sip_header_state == SIP_HEADER_DELETED) {
944*2882Svi117747 		if (_sip_header->sip_hdr_sipmsg != NULL) {
945*2882Svi117747 			(void) pthread_mutex_unlock(
946*2882Svi117747 			    &_sip_header->sip_hdr_sipmsg->sip_msg_mutex);
947*2882Svi117747 		}
948*2882Svi117747 		if (error != NULL)
949*2882Svi117747 			*error = EINVAL;
950*2882Svi117747 		return (NULL);
951*2882Svi117747 	}
952*2882Svi117747 	if (_sip_header->sip_hdr_sipmsg != NULL) {
953*2882Svi117747 		(void) pthread_mutex_lock(
954*2882Svi117747 		    &_sip_header->sip_hdr_sipmsg->sip_msg_mutex);
955*2882Svi117747 	}
956*2882Svi117747 	len = _sip_header->sip_hdr_end - _sip_header->sip_hdr_start;
957*2882Svi117747 	hdrstr = malloc(len);
958*2882Svi117747 	if (hdrstr == NULL) {
959*2882Svi117747 		if (_sip_header->sip_hdr_sipmsg != NULL) {
960*2882Svi117747 			(void) pthread_mutex_unlock(
961*2882Svi117747 			    &_sip_header->sip_hdr_sipmsg->sip_msg_mutex);
962*2882Svi117747 		}
963*2882Svi117747 		if (error != NULL)
964*2882Svi117747 			*error = ENOMEM;
965*2882Svi117747 		return (NULL);
966*2882Svi117747 	}
967*2882Svi117747 	if (_sip_header->sip_header_state == SIP_HEADER_DELETED_VAL) {
968*2882Svi117747 		len = sip_copy_values(hdrstr, _sip_header);
969*2882Svi117747 	} else {
970*2882Svi117747 		(void) strncpy(hdrstr, _sip_header->sip_hdr_start, len);
971*2882Svi117747 	}
972*2882Svi117747 	if (_sip_header->sip_hdr_sipmsg != NULL) {
973*2882Svi117747 		(void) pthread_mutex_unlock(
974*2882Svi117747 		    &_sip_header->sip_hdr_sipmsg->sip_msg_mutex);
975*2882Svi117747 	}
976*2882Svi117747 	tmpptr = hdrstr + len;
977*2882Svi117747 	while (*tmpptr-- != '\n') {
978*2882Svi117747 		if (tmpptr == _sip_header->sip_hdr_start) {
979*2882Svi117747 			free(hdrstr);
980*2882Svi117747 			if (error != NULL)
981*2882Svi117747 				*error = EINVAL;
982*2882Svi117747 			return (NULL);
983*2882Svi117747 		}
984*2882Svi117747 	}
985*2882Svi117747 	*tmpptr = '\0';
986*2882Svi117747 	return (hdrstr);
987*2882Svi117747 }
988*2882Svi117747 
989*2882Svi117747 /*
990*2882Svi117747  * Given a param list find the named parameter.
991*2882Svi117747  * Returns a pointer to the value or NULL.
992*2882Svi117747  */
993*2882Svi117747 sip_param_t *
994*2882Svi117747 sip_get_param_from_list(sip_param_t *param_list, char *param_name)
995*2882Svi117747 {
996*2882Svi117747 	while (param_list != NULL) {
997*2882Svi117747 		if (param_list->param_name.sip_str_len == strlen(param_name) &&
998*2882Svi117747 		    strncasecmp(param_list->param_name.sip_str_ptr, param_name,
999*2882Svi117747 		    strlen(param_name)) == 0) {
1000*2882Svi117747 			return (param_list);
1001*2882Svi117747 		}
1002*2882Svi117747 		param_list = param_list->param_next;
1003*2882Svi117747 	}
1004*2882Svi117747 	return (NULL);
1005*2882Svi117747 }
1006