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 
33*2882Svi117747 /*
34*2882Svi117747  * atoi function from a header
35*2882Svi117747  */
36*2882Svi117747 int
37*2882Svi117747 sip_atoi(_sip_header_t *sip_header, int *num)
38*2882Svi117747 {
39*2882Svi117747 	boolean_t	num_found = B_FALSE;
40*2882Svi117747 
41*2882Svi117747 	*num = 0;
42*2882Svi117747 	while (sip_header->sip_hdr_current < sip_header->sip_hdr_end) {
43*2882Svi117747 		if (isspace(*sip_header->sip_hdr_current)) {
44*2882Svi117747 			sip_header->sip_hdr_current++;
45*2882Svi117747 			if (num_found)
46*2882Svi117747 				break;
47*2882Svi117747 		} else if (isdigit(*sip_header->sip_hdr_current)) {
48*2882Svi117747 			*num = (*num * 10) +
49*2882Svi117747 			    (*sip_header->sip_hdr_current - '0');
50*2882Svi117747 			num_found = B_TRUE;
51*2882Svi117747 			sip_header->sip_hdr_current++;
52*2882Svi117747 		} else {
53*2882Svi117747 			break;
54*2882Svi117747 		}
55*2882Svi117747 	}
56*2882Svi117747 	if (!num_found)
57*2882Svi117747 		return (EINVAL);
58*2882Svi117747 	return (0);
59*2882Svi117747 }
60*2882Svi117747 
61*2882Svi117747 /*
62*2882Svi117747  * Find the 'token'
63*2882Svi117747  */
64*2882Svi117747 int
65*2882Svi117747 sip_find_token(_sip_header_t *sip_header, char token)
66*2882Svi117747 {
67*2882Svi117747 	while (sip_header->sip_hdr_current < sip_header->sip_hdr_end) {
68*2882Svi117747 		if (token != SIP_COMMA &&
69*2882Svi117747 		    *sip_header->sip_hdr_current == SIP_COMMA) {
70*2882Svi117747 			sip_header->sip_hdr_current--;
71*2882Svi117747 			return (1);
72*2882Svi117747 		}
73*2882Svi117747 		if (*sip_header->sip_hdr_current++ == token) {
74*2882Svi117747 			/*
75*2882Svi117747 			 * sip_hdr_current points to the char
76*2882Svi117747 			 * after the token
77*2882Svi117747 			 */
78*2882Svi117747 			return (0);
79*2882Svi117747 		}
80*2882Svi117747 	}
81*2882Svi117747 	return (1);
82*2882Svi117747 }
83*2882Svi117747 
84*2882Svi117747 /*
85*2882Svi117747  * Find a carriage-return
86*2882Svi117747  */
87*2882Svi117747 int
88*2882Svi117747 sip_find_cr(_sip_header_t *sip_header)
89*2882Svi117747 {
90*2882Svi117747 	sip_header->sip_hdr_current = sip_header->sip_hdr_end;
91*2882Svi117747 	while (*sip_header->sip_hdr_current-- != '\n') {
92*2882Svi117747 		if (sip_header->sip_hdr_current == sip_header->sip_hdr_start)
93*2882Svi117747 			return (1);
94*2882Svi117747 	}
95*2882Svi117747 	return (0);
96*2882Svi117747 }
97*2882Svi117747 
98*2882Svi117747 /*
99*2882Svi117747  * Find one of the separator provided, i.e. separator_1st or separator_2nd or
100*2882Svi117747  * separator_3rd.
101*2882Svi117747  */
102*2882Svi117747 int
103*2882Svi117747 sip_find_separator(_sip_header_t *sip_header, char separator_1st,
104*2882Svi117747     char separator_2nd, char separator_3rd)
105*2882Svi117747 {
106*2882Svi117747 	assert(separator_1st != (char)NULL || separator_2nd != (char)NULL);
107*2882Svi117747 	while (sip_header->sip_hdr_current < sip_header->sip_hdr_end) {
108*2882Svi117747 		if (isspace(*sip_header->sip_hdr_current) ||
109*2882Svi117747 		    (separator_1st != (char)NULL &&
110*2882Svi117747 		    (*sip_header->sip_hdr_current == separator_1st)) ||
111*2882Svi117747 		    (separator_2nd != (char)NULL &&
112*2882Svi117747 		    (*sip_header->sip_hdr_current == separator_2nd)) ||
113*2882Svi117747 		    (separator_3rd != (char)NULL &&
114*2882Svi117747 		    (*sip_header->sip_hdr_current == separator_3rd))) {
115*2882Svi117747 			return (0);
116*2882Svi117747 		}
117*2882Svi117747 		/*
118*2882Svi117747 		 * If we have escape character, go to the next char
119*2882Svi117747 		 */
120*2882Svi117747 		if (*sip_header->sip_hdr_current == '\\')
121*2882Svi117747 			sip_header->sip_hdr_current++;
122*2882Svi117747 		sip_header->sip_hdr_current++;
123*2882Svi117747 	}
124*2882Svi117747 	return (1);
125*2882Svi117747 }
126*2882Svi117747 
127*2882Svi117747 /*
128*2882Svi117747  * Return when we hit a white space
129*2882Svi117747  */
130*2882Svi117747 int
131*2882Svi117747 sip_find_white_space(_sip_header_t *sip_header)
132*2882Svi117747 {
133*2882Svi117747 	while (sip_header->sip_hdr_current < sip_header->sip_hdr_end) {
134*2882Svi117747 		if (isspace(*sip_header->sip_hdr_current))
135*2882Svi117747 			return (0);
136*2882Svi117747 		sip_header->sip_hdr_current++;
137*2882Svi117747 	}
138*2882Svi117747 	return (1);
139*2882Svi117747 }
140*2882Svi117747 
141*2882Svi117747 /*
142*2882Svi117747  * Skip to the next non-whitespace
143*2882Svi117747  */
144*2882Svi117747 int
145*2882Svi117747 sip_skip_white_space(_sip_header_t *sip_header)
146*2882Svi117747 {
147*2882Svi117747 	while (sip_header->sip_hdr_current < sip_header->sip_hdr_end) {
148*2882Svi117747 		if (!isspace(*sip_header->sip_hdr_current))
149*2882Svi117747 			return (0);
150*2882Svi117747 		sip_header->sip_hdr_current++;
151*2882Svi117747 	}
152*2882Svi117747 	return (1);
153*2882Svi117747 }
154*2882Svi117747 
155*2882Svi117747 
156*2882Svi117747 /*
157*2882Svi117747  * Skip to the non-white space in the reverse direction
158*2882Svi117747  */
159*2882Svi117747 int
160*2882Svi117747 sip_reverse_skip_white_space(_sip_header_t *sip_header)
161*2882Svi117747 {
162*2882Svi117747 	while (sip_header->sip_hdr_current >= sip_header->sip_hdr_start) {
163*2882Svi117747 		if (!isspace(*sip_header->sip_hdr_current))
164*2882Svi117747 			return (0);
165*2882Svi117747 		sip_header->sip_hdr_current--;
166*2882Svi117747 	}
167*2882Svi117747 	return (1);
168*2882Svi117747 }
169*2882Svi117747 
170*2882Svi117747 /*
171*2882Svi117747  * get to the first non space after ':'
172*2882Svi117747  */
173*2882Svi117747 int
174*2882Svi117747 sip_parse_goto_values(_sip_header_t *sip_header)
175*2882Svi117747 {
176*2882Svi117747 	if (sip_find_token(sip_header, SIP_HCOLON) !=  0)
177*2882Svi117747 		return (1);
178*2882Svi117747 	if (sip_skip_white_space(sip_header) != 0)
179*2882Svi117747 		return (1);
180*2882Svi117747 
181*2882Svi117747 	return (0);
182*2882Svi117747 }
183*2882Svi117747 
184*2882Svi117747 /*
185*2882Svi117747  * Skip the current value.
186*2882Svi117747  */
187*2882Svi117747 int
188*2882Svi117747 sip_goto_next_value(_sip_header_t *sip_header)
189*2882Svi117747 {
190*2882Svi117747 	boolean_t	quoted = B_FALSE;
191*2882Svi117747 
192*2882Svi117747 	while (sip_header->sip_hdr_current < sip_header->sip_hdr_end) {
193*2882Svi117747 		if (*sip_header->sip_hdr_current == SIP_QUOTE) {
194*2882Svi117747 			if (quoted)
195*2882Svi117747 				quoted = B_FALSE;
196*2882Svi117747 			else
197*2882Svi117747 				quoted = B_TRUE;
198*2882Svi117747 		} else if (!quoted &&
199*2882Svi117747 		    *sip_header->sip_hdr_current == SIP_COMMA) {
200*2882Svi117747 			/*
201*2882Svi117747 			 * value ends before the COMMA
202*2882Svi117747 			 */
203*2882Svi117747 			sip_header->sip_hdr_current--;
204*2882Svi117747 			return (0);
205*2882Svi117747 		}
206*2882Svi117747 		sip_header->sip_hdr_current++;
207*2882Svi117747 	}
208*2882Svi117747 	if (quoted)
209*2882Svi117747 		return (1);
210*2882Svi117747 	return (0);
211*2882Svi117747 }
212*2882Svi117747 
213*2882Svi117747 /*
214*2882Svi117747  * Parse the header into parameter list. Parameters start with a ';'
215*2882Svi117747  */
216*2882Svi117747 int
217*2882Svi117747 sip_parse_params(_sip_header_t *sip_header, sip_param_t **parsed_list)
218*2882Svi117747 {
219*2882Svi117747 	sip_param_t	*param = NULL;
220*2882Svi117747 	sip_param_t	*new_param;
221*2882Svi117747 	char		*tmp_ptr;
222*2882Svi117747 
223*2882Svi117747 	if (parsed_list == NULL)
224*2882Svi117747 		return (0);
225*2882Svi117747 
226*2882Svi117747 	*parsed_list = NULL;
227*2882Svi117747 	for (;;) {
228*2882Svi117747 		boolean_t	quoted_name = B_FALSE;
229*2882Svi117747 
230*2882Svi117747 		/*
231*2882Svi117747 		 * First check if there are any params
232*2882Svi117747 		 */
233*2882Svi117747 		if (sip_skip_white_space(sip_header) != 0)
234*2882Svi117747 			return (0);
235*2882Svi117747 		if (*sip_header->sip_hdr_current != SIP_SEMI)
236*2882Svi117747 			return (0);
237*2882Svi117747 
238*2882Svi117747 		sip_header->sip_hdr_current++;
239*2882Svi117747 
240*2882Svi117747 		new_param = calloc(1, sizeof (sip_param_t));
241*2882Svi117747 		if (new_param == NULL)
242*2882Svi117747 			return (ENOMEM);
243*2882Svi117747 
244*2882Svi117747 		if (param != NULL)
245*2882Svi117747 			param->param_next = new_param;
246*2882Svi117747 		else
247*2882Svi117747 			*parsed_list = new_param;
248*2882Svi117747 
249*2882Svi117747 		param = new_param;
250*2882Svi117747 
251*2882Svi117747 		/*
252*2882Svi117747 		 * Let's get to the start of the param name
253*2882Svi117747 		 */
254*2882Svi117747 		if (sip_skip_white_space(sip_header) != 0)
255*2882Svi117747 			return (EPROTO);
256*2882Svi117747 		/*
257*2882Svi117747 		 * start of param name
258*2882Svi117747 		 */
259*2882Svi117747 		tmp_ptr = sip_header->sip_hdr_current;
260*2882Svi117747 		param->param_name.sip_str_ptr = tmp_ptr;
261*2882Svi117747 
262*2882Svi117747 		if (sip_find_separator(sip_header, SIP_EQUAL, SIP_SEMI,
263*2882Svi117747 		    SIP_COMMA) != 0) {
264*2882Svi117747 			param->param_name.sip_str_len =
265*2882Svi117747 			    sip_header->sip_hdr_current - tmp_ptr;
266*2882Svi117747 			param->param_value.sip_str_ptr = NULL;
267*2882Svi117747 			param->param_value.sip_str_len = 0;
268*2882Svi117747 			return (0);
269*2882Svi117747 		}
270*2882Svi117747 
271*2882Svi117747 		/*
272*2882Svi117747 		 * End of param name
273*2882Svi117747 		 */
274*2882Svi117747 		param->param_name.sip_str_len =
275*2882Svi117747 		    sip_header->sip_hdr_current - tmp_ptr;
276*2882Svi117747 
277*2882Svi117747 		if (sip_skip_white_space(sip_header) != 0 ||
278*2882Svi117747 		    *sip_header->sip_hdr_current == SIP_COMMA) {
279*2882Svi117747 			param->param_value.sip_str_ptr = NULL;
280*2882Svi117747 			param->param_value.sip_str_len = 0;
281*2882Svi117747 			return (0);
282*2882Svi117747 		}
283*2882Svi117747 		if (*sip_header->sip_hdr_current == SIP_SEMI) {
284*2882Svi117747 			param->param_value.sip_str_ptr = NULL;
285*2882Svi117747 			param->param_value.sip_str_len = 0;
286*2882Svi117747 			continue;
287*2882Svi117747 		}
288*2882Svi117747 		assert(*sip_header->sip_hdr_current == SIP_EQUAL);
289*2882Svi117747 
290*2882Svi117747 		/*
291*2882Svi117747 		 * We are at EQUAL, lets go beyond that
292*2882Svi117747 		 */
293*2882Svi117747 		sip_header->sip_hdr_current++;
294*2882Svi117747 
295*2882Svi117747 		if (sip_skip_white_space(sip_header) != 0)
296*2882Svi117747 			return (EPROTO);
297*2882Svi117747 
298*2882Svi117747 		if (*sip_header->sip_hdr_current == SIP_QUOTE) {
299*2882Svi117747 			sip_header->sip_hdr_current++;
300*2882Svi117747 			quoted_name = B_TRUE;
301*2882Svi117747 		}
302*2882Svi117747 
303*2882Svi117747 		/*
304*2882Svi117747 		 * start of param value
305*2882Svi117747 		 */
306*2882Svi117747 		param->param_value.sip_str_ptr = sip_header->sip_hdr_current;
307*2882Svi117747 		tmp_ptr = sip_header->sip_hdr_current;
308*2882Svi117747 
309*2882Svi117747 		if (quoted_name && sip_find_token(sip_header, SIP_QUOTE) != 0) {
310*2882Svi117747 			return (EPROTO);
311*2882Svi117747 		} else if (sip_find_separator(sip_header, SIP_SEMI, SIP_COMMA,
312*2882Svi117747 		    (char)NULL) != 0) {
313*2882Svi117747 			return (EPROTO);
314*2882Svi117747 		}
315*2882Svi117747 		param->param_value.sip_str_len = sip_header->sip_hdr_current -
316*2882Svi117747 		    tmp_ptr;
317*2882Svi117747 		if (quoted_name)
318*2882Svi117747 			param->param_value.sip_str_len--;
319*2882Svi117747 	}
320*2882Svi117747 }
321*2882Svi117747 
322*2882Svi117747 /*
323*2882Svi117747  * a header that only has "header_name : " is an empty header
324*2882Svi117747  * ":" must exist
325*2882Svi117747  * sip_hdr_current resets to sip_hdr_start before exit
326*2882Svi117747  */
327*2882Svi117747 boolean_t
328*2882Svi117747 sip_is_empty_hdr(_sip_header_t *sip_header)
329*2882Svi117747 {
330*2882Svi117747 	if (sip_find_token(sip_header, SIP_HCOLON) != 0) {
331*2882Svi117747 		sip_header->sip_hdr_current = sip_header->sip_hdr_start;
332*2882Svi117747 		return (B_FALSE);
333*2882Svi117747 	}
334*2882Svi117747 
335*2882Svi117747 	if (sip_skip_white_space(sip_header) == 0) {
336*2882Svi117747 		sip_header->sip_hdr_current = sip_header->sip_hdr_start;
337*2882Svi117747 		return (B_FALSE);
338*2882Svi117747 	}
339*2882Svi117747 
340*2882Svi117747 	sip_header->sip_hdr_current = sip_header->sip_hdr_start;
341*2882Svi117747 	return (B_TRUE);
342*2882Svi117747 }
343*2882Svi117747 
344*2882Svi117747 /*
345*2882Svi117747  * Parsing an empty header, i.e. only has a ":"
346*2882Svi117747  */
347*2882Svi117747 int
348*2882Svi117747 sip_parse_hdr_empty(_sip_header_t *hdr, sip_parsed_header_t **phdr)
349*2882Svi117747 {
350*2882Svi117747 	sip_parsed_header_t	*parsed_header;
351*2882Svi117747 
352*2882Svi117747 	if (hdr == NULL || phdr == NULL)
353*2882Svi117747 		return (EINVAL);
354*2882Svi117747 
355*2882Svi117747 	/*
356*2882Svi117747 	 * check if already parsed
357*2882Svi117747 	 */
358*2882Svi117747 	if (hdr->sip_hdr_parsed != NULL) {
359*2882Svi117747 		*phdr = hdr->sip_hdr_parsed;
360*2882Svi117747 		return (0);
361*2882Svi117747 	}
362*2882Svi117747 
363*2882Svi117747 	*phdr = NULL;
364*2882Svi117747 
365*2882Svi117747 	parsed_header = calloc(1, sizeof (sip_parsed_header_t));
366*2882Svi117747 	if (parsed_header == NULL)
367*2882Svi117747 		return (ENOMEM);
368*2882Svi117747 	parsed_header->sip_header = hdr;
369*2882Svi117747 
370*2882Svi117747 	parsed_header->value = NULL;
371*2882Svi117747 
372*2882Svi117747 	*phdr = parsed_header;
373*2882Svi117747 	return (0);
374*2882Svi117747 }
375*2882Svi117747 
376*2882Svi117747 /*
377*2882Svi117747  * validate uri str and parse uri using uri_parse()
378*2882Svi117747  */
379*2882Svi117747 static void
380*2882Svi117747 sip_parse_uri_str(sip_str_t *sip_str, sip_hdr_value_t *value)
381*2882Svi117747 {
382*2882Svi117747 	int		error;
383*2882Svi117747 
384*2882Svi117747 	/*
385*2882Svi117747 	 * Parse uri
386*2882Svi117747 	 */
387*2882Svi117747 	if (sip_str->sip_str_len > 0) {
388*2882Svi117747 		value->sip_value_parsed_uri = sip_parse_uri(sip_str, &error);
389*2882Svi117747 		if (value->sip_value_parsed_uri == NULL)
390*2882Svi117747 			return;
391*2882Svi117747 		if (error != 0 ||
392*2882Svi117747 		    value->sip_value_parsed_uri->sip_uri_errflags != 0) {
393*2882Svi117747 			value->sip_value_state = SIP_VALUE_BAD;
394*2882Svi117747 		}
395*2882Svi117747 	}
396*2882Svi117747 }
397*2882Svi117747 
398*2882Svi117747 /*
399*2882Svi117747  * Some basic common checks before parsing the headers
400*2882Svi117747  */
401*2882Svi117747 int
402*2882Svi117747 sip_prim_parsers(_sip_header_t *sip_header, sip_parsed_header_t **header)
403*2882Svi117747 {
404*2882Svi117747 	if (sip_header == NULL || header == NULL)
405*2882Svi117747 		return (EINVAL);
406*2882Svi117747 
407*2882Svi117747 	/*
408*2882Svi117747 	 * check if already parsed
409*2882Svi117747 	 */
410*2882Svi117747 	if (sip_header->sip_hdr_parsed != NULL) {
411*2882Svi117747 		*header = sip_header->sip_hdr_parsed;
412*2882Svi117747 		return (0);
413*2882Svi117747 	}
414*2882Svi117747 	*header = NULL;
415*2882Svi117747 
416*2882Svi117747 	assert(sip_header->sip_hdr_start == sip_header->sip_hdr_current);
417*2882Svi117747 
418*2882Svi117747 	if (sip_parse_goto_values(sip_header) != 0)
419*2882Svi117747 		return (EPROTO);
420*2882Svi117747 
421*2882Svi117747 	return (0);
422*2882Svi117747 }
423*2882Svi117747 
424*2882Svi117747 /*
425*2882Svi117747  * Parse SIP/2.0 string
426*2882Svi117747  */
427*2882Svi117747 int
428*2882Svi117747 sip_get_protocol_version(_sip_header_t *sip_header,
429*2882Svi117747     sip_proto_version_t *sip_proto_version)
430*2882Svi117747 {
431*2882Svi117747 	if (sip_skip_white_space(sip_header) != 0)
432*2882Svi117747 		return (1);
433*2882Svi117747 
434*2882Svi117747 	if (strncasecmp(sip_header->sip_hdr_current, SIP, strlen(SIP)) == 0) {
435*2882Svi117747 		sip_proto_version->name.sip_str_ptr =
436*2882Svi117747 		    sip_header->sip_hdr_current;
437*2882Svi117747 		sip_proto_version->name.sip_str_len = strlen(SIP);
438*2882Svi117747 
439*2882Svi117747 		if (sip_find_token(sip_header, SIP_SLASH) != 0)
440*2882Svi117747 			return (1);
441*2882Svi117747 		if (sip_skip_white_space(sip_header) != 0)
442*2882Svi117747 			return (1);
443*2882Svi117747 
444*2882Svi117747 		sip_proto_version->version.sip_str_ptr =
445*2882Svi117747 		    sip_header->sip_hdr_current;
446*2882Svi117747 		while (isdigit(*sip_header->sip_hdr_current)) {
447*2882Svi117747 			sip_header->sip_hdr_current++;
448*2882Svi117747 			if (sip_header->sip_hdr_current >=
449*2882Svi117747 			    sip_header->sip_hdr_end) {
450*2882Svi117747 				return (1);
451*2882Svi117747 			}
452*2882Svi117747 		}
453*2882Svi117747 		if (*sip_header->sip_hdr_current != SIP_PERIOD)
454*2882Svi117747 			return (1);
455*2882Svi117747 		sip_header->sip_hdr_current++;
456*2882Svi117747 
457*2882Svi117747 		if (!isdigit(*sip_header->sip_hdr_current))
458*2882Svi117747 			return (1);
459*2882Svi117747 		while (isdigit(*sip_header->sip_hdr_current)) {
460*2882Svi117747 			sip_header->sip_hdr_current++;
461*2882Svi117747 			if (sip_header->sip_hdr_current >=
462*2882Svi117747 			    sip_header->sip_hdr_end) {
463*2882Svi117747 				return (1);
464*2882Svi117747 			}
465*2882Svi117747 		}
466*2882Svi117747 
467*2882Svi117747 		sip_proto_version->version.sip_str_len =
468*2882Svi117747 		    sip_header->sip_hdr_current -
469*2882Svi117747 		    sip_proto_version->version.sip_str_ptr;
470*2882Svi117747 		return (0);
471*2882Svi117747 	}
472*2882Svi117747 	return (1);
473*2882Svi117747 }
474*2882Svi117747 
475*2882Svi117747 /*
476*2882Svi117747  * parser1 parses hdr format
477*2882Svi117747  *	header_name: val1[; par1=pval1;par2=pval2 ..][, val2[;parlist..] ]
478*2882Svi117747  *	val can be str1/str2 or str
479*2882Svi117747  * headers: Accept, Accept-Encode, Accept-lang, Allow, Content-disp,
480*2882Svi117747  *	    Content-Encode, Content-Lang, In-reply-to,
481*2882Svi117747  *	    Priority, Require, Supported, Unsupported
482*2882Svi117747  *	    Allow-Events, Event, Subscription-State
483*2882Svi117747  */
484*2882Svi117747 int
485*2882Svi117747 sip_parse_hdr_parser1(_sip_header_t *hdr, sip_parsed_header_t **phdr, char sep)
486*2882Svi117747 {
487*2882Svi117747 	sip_parsed_header_t	*parsed_header;
488*2882Svi117747 	int			ret;
489*2882Svi117747 	sip_hdr_value_t		*value = NULL;
490*2882Svi117747 	sip_hdr_value_t		*last_value = NULL;
491*2882Svi117747 
492*2882Svi117747 	if ((ret = sip_prim_parsers(hdr, phdr)) != 0)
493*2882Svi117747 		return (ret);
494*2882Svi117747 
495*2882Svi117747 	/*
496*2882Svi117747 	 * check if previously parsed
497*2882Svi117747 	 */
498*2882Svi117747 	if (*phdr != NULL) {
499*2882Svi117747 		hdr->sip_hdr_parsed = *phdr;
500*2882Svi117747 		return (0);
501*2882Svi117747 	}
502*2882Svi117747 
503*2882Svi117747 	parsed_header = calloc(1, sizeof (sip_parsed_header_t));
504*2882Svi117747 	if (parsed_header == NULL)
505*2882Svi117747 		return (ENOMEM);
506*2882Svi117747 	parsed_header->sip_parsed_header_version = SIP_PARSED_HEADER_VERSION_1;
507*2882Svi117747 	parsed_header->sip_header = hdr;
508*2882Svi117747 
509*2882Svi117747 	while (hdr->sip_hdr_current < hdr->sip_hdr_end) {
510*2882Svi117747 		value = calloc(1, sizeof (sip_hdr_value_t));
511*2882Svi117747 		if (value == NULL) {
512*2882Svi117747 			sip_free_phdr(parsed_header);
513*2882Svi117747 			return (ENOMEM);
514*2882Svi117747 		}
515*2882Svi117747 		if (last_value != NULL)
516*2882Svi117747 			last_value->sip_next_value = value;
517*2882Svi117747 		else
518*2882Svi117747 			parsed_header->value = (sip_value_t *)value;
519*2882Svi117747 
520*2882Svi117747 		value->sip_value_start = hdr->sip_hdr_current;
521*2882Svi117747 		value->sip_value_header = parsed_header;
522*2882Svi117747 
523*2882Svi117747 		if (sip_find_separator(hdr, sep, SIP_COMMA, SIP_SEMI) == 0) {
524*2882Svi117747 			char	c = *hdr->sip_hdr_current;
525*2882Svi117747 
526*2882Svi117747 			if (isspace(c) && sep == (char)NULL) {
527*2882Svi117747 				value->str_val_ptr = value->sip_value_start;
528*2882Svi117747 				value->str_val_len = hdr->sip_hdr_current -
529*2882Svi117747 				    value->sip_value_start;
530*2882Svi117747 				/*
531*2882Svi117747 				 * nothing at the end except space
532*2882Svi117747 				 */
533*2882Svi117747 				if (sip_skip_white_space(hdr) != 0) {
534*2882Svi117747 					value->sip_value_end =
535*2882Svi117747 					    hdr->sip_hdr_current;
536*2882Svi117747 					goto end;
537*2882Svi117747 				}
538*2882Svi117747 				/*
539*2882Svi117747 				 * white space skipped
540*2882Svi117747 				 */
541*2882Svi117747 				c = *(hdr->sip_hdr_current);
542*2882Svi117747 			}
543*2882Svi117747 
544*2882Svi117747 			/*
545*2882Svi117747 			 * only one string until COMMA, use sip_str_t
546*2882Svi117747 			 */
547*2882Svi117747 			if (c == SIP_COMMA) {
548*2882Svi117747 				char	*t = hdr->sip_hdr_current;
549*2882Svi117747 
550*2882Svi117747 				hdr->sip_hdr_current--;
551*2882Svi117747 				(void) sip_reverse_skip_white_space(hdr);
552*2882Svi117747 				value->str_val_ptr = value->sip_value_start;
553*2882Svi117747 				value->str_val_len = hdr->sip_hdr_current -
554*2882Svi117747 				    value->sip_value_start + 1;
555*2882Svi117747 				hdr->sip_hdr_current = t;
556*2882Svi117747 				goto get_next_val;
557*2882Svi117747 			}
558*2882Svi117747 
559*2882Svi117747 			/*
560*2882Svi117747 			 * two strings, use sip_2strs_t
561*2882Svi117747 			 */
562*2882Svi117747 			if ((sep != (char)NULL) && (c == sep)) {
563*2882Svi117747 				value->strs1_val_ptr = value->sip_value_start;
564*2882Svi117747 				value->strs1_val_len = hdr->sip_hdr_current -
565*2882Svi117747 				    value->sip_value_start;
566*2882Svi117747 
567*2882Svi117747 				value->strs2_val_ptr =
568*2882Svi117747 				    (++hdr->sip_hdr_current);
569*2882Svi117747 				if (sip_find_separator(hdr, SIP_SEMI, SIP_COMMA,
570*2882Svi117747 				    (char)NULL) == 0) {
571*2882Svi117747 					char t = *(hdr->sip_hdr_current);
572*2882Svi117747 					value->strs2_val_len =
573*2882Svi117747 					    hdr->sip_hdr_current -
574*2882Svi117747 						value->strs2_val_ptr;
575*2882Svi117747 					/*
576*2882Svi117747 					 * if COMMA, no param list, get next val
577*2882Svi117747 					 * if SEMI, need to set params list
578*2882Svi117747 					 */
579*2882Svi117747 					if (t == SIP_COMMA)
580*2882Svi117747 						goto get_next_val;
581*2882Svi117747 				} else { /* the last part */
582*2882Svi117747 					value->strs2_val_len =
583*2882Svi117747 					    hdr->sip_hdr_current -
584*2882Svi117747 						value->strs2_val_ptr;
585*2882Svi117747 					value->sip_value_end =
586*2882Svi117747 					    hdr->sip_hdr_current;
587*2882Svi117747 					goto end;
588*2882Svi117747 				}
589*2882Svi117747 			} else if (sep != (char)NULL) {
590*2882Svi117747 				value->sip_value_state = SIP_VALUE_BAD;
591*2882Svi117747 				goto get_next_val;
592*2882Svi117747 			}
593*2882Svi117747 
594*2882Svi117747 			/*
595*2882Svi117747 			 * c == SEMI, value contains single string
596*2882Svi117747 			 * only one string until SEMI, use sip_str_t
597*2882Svi117747 			 */
598*2882Svi117747 			if (c == SIP_SEMI) {
599*2882Svi117747 				char	*t = hdr->sip_hdr_current;
600*2882Svi117747 
601*2882Svi117747 				hdr->sip_hdr_current--;
602*2882Svi117747 				/*
603*2882Svi117747 				 * get rid of SP at end of value field
604*2882Svi117747 				 */
605*2882Svi117747 				(void) sip_reverse_skip_white_space(hdr);
606*2882Svi117747 				value->str_val_ptr = value->sip_value_start;
607*2882Svi117747 				value->str_val_len = hdr->sip_hdr_current -
608*2882Svi117747 				    value->str_val_ptr + 1;
609*2882Svi117747 				hdr->sip_hdr_current = t;
610*2882Svi117747 			}
611*2882Svi117747 
612*2882Svi117747 			/*
613*2882Svi117747 			 * if SEMI exists in the value, set params list
614*2882Svi117747 			 * two situations, there is or not SLASH before SEMI
615*2882Svi117747 			 */
616*2882Svi117747 			ret = sip_parse_params(hdr, &value->sip_param_list);
617*2882Svi117747 			if (ret == EPROTO) {
618*2882Svi117747 				value->sip_value_state = SIP_VALUE_BAD;
619*2882Svi117747 			} else if (ret != 0) {
620*2882Svi117747 				sip_free_phdr(parsed_header);
621*2882Svi117747 				return (ret);
622*2882Svi117747 			}
623*2882Svi117747 			goto get_next_val;
624*2882Svi117747 		} else {
625*2882Svi117747 			value->str_val_ptr = value->sip_value_start;
626*2882Svi117747 			value->str_val_len = hdr->sip_hdr_current -
627*2882Svi117747 			    value->sip_value_start;
628*2882Svi117747 			value->sip_value_end = hdr->sip_hdr_current;
629*2882Svi117747 			goto end;
630*2882Svi117747 		}
631*2882Svi117747 get_next_val:
632*2882Svi117747 		if (sip_find_token(hdr, SIP_COMMA) != 0) {
633*2882Svi117747 			value->sip_value_end = hdr->sip_hdr_current;
634*2882Svi117747 			break;
635*2882Svi117747 		}
636*2882Svi117747 		value->sip_value_end = hdr->sip_hdr_current - 1;
637*2882Svi117747 		last_value = value;
638*2882Svi117747 		(void) sip_skip_white_space(hdr);
639*2882Svi117747 	}
640*2882Svi117747 
641*2882Svi117747 end:
642*2882Svi117747 	*phdr = parsed_header;
643*2882Svi117747 	hdr->sip_hdr_parsed = *phdr;
644*2882Svi117747 	return (0);
645*2882Svi117747 }
646*2882Svi117747 
647*2882Svi117747 /*
648*2882Svi117747  * header_name: int
649*2882Svi117747  * headers: Expires, Min-Expires
650*2882Svi117747  */
651*2882Svi117747 /* ARGSUSED */
652*2882Svi117747 int
653*2882Svi117747 sip_parse_hdr_parser2(_sip_header_t *hdr, sip_parsed_header_t **phdr,
654*2882Svi117747     int val_type)
655*2882Svi117747 {
656*2882Svi117747 	sip_parsed_header_t	*parsed_header;
657*2882Svi117747 	int			ret = 0;
658*2882Svi117747 	sip_hdr_value_t		*value = NULL;
659*2882Svi117747 
660*2882Svi117747 	if ((ret = sip_prim_parsers(hdr, phdr)) != 0)
661*2882Svi117747 		return (ret);
662*2882Svi117747 
663*2882Svi117747 	/*
664*2882Svi117747 	 * check if previously parsed
665*2882Svi117747 	 */
666*2882Svi117747 	if (*phdr != NULL) {
667*2882Svi117747 		hdr->sip_hdr_parsed = *phdr;
668*2882Svi117747 		return (0);
669*2882Svi117747 	}
670*2882Svi117747 	parsed_header = calloc(1, sizeof (sip_parsed_header_t));
671*2882Svi117747 	if (parsed_header == NULL)
672*2882Svi117747 		return (ENOMEM);
673*2882Svi117747 	parsed_header->sip_parsed_header_version = SIP_PARSED_HEADER_VERSION_1;
674*2882Svi117747 	parsed_header->sip_header = hdr;
675*2882Svi117747 
676*2882Svi117747 	value = calloc(1, sizeof (sip_hdr_value_t));
677*2882Svi117747 	if (value == NULL) {
678*2882Svi117747 		sip_free_phdr(parsed_header);
679*2882Svi117747 		return (ENOMEM);
680*2882Svi117747 	}
681*2882Svi117747 
682*2882Svi117747 	parsed_header->value = (sip_value_t *)value;
683*2882Svi117747 
684*2882Svi117747 	value->sip_value_start = hdr->sip_hdr_current;
685*2882Svi117747 	value->sip_value_header = parsed_header;
686*2882Svi117747 
687*2882Svi117747 	ret = sip_atoi(hdr, &value->int_val);
688*2882Svi117747 	if (ret != 0) {
689*2882Svi117747 		value->int_val = 0;
690*2882Svi117747 		value->sip_value_state = SIP_VALUE_BAD;
691*2882Svi117747 	}
692*2882Svi117747 
693*2882Svi117747 	value->sip_value_end = hdr->sip_hdr_current - 1;
694*2882Svi117747 
695*2882Svi117747 	*phdr = parsed_header;
696*2882Svi117747 	hdr->sip_hdr_parsed = *phdr;
697*2882Svi117747 	return (0);
698*2882Svi117747 }
699*2882Svi117747 
700*2882Svi117747 /*
701*2882Svi117747  * parser3 parses hdr format
702*2882Svi117747  * header_name: <val1>[, <val2>]
703*2882Svi117747  * Alert-Info, Call-Info, Error-Info, reply-to
704*2882Svi117747  */
705*2882Svi117747 int
706*2882Svi117747 sip_parse_hdr_parser3(_sip_header_t *hdr, sip_parsed_header_t **phdr, int type,
707*2882Svi117747     boolean_t parse_uri)
708*2882Svi117747 {
709*2882Svi117747 	sip_parsed_header_t	*parsed_header;
710*2882Svi117747 	sip_hdr_value_t		*value = NULL;
711*2882Svi117747 	sip_hdr_value_t		*last_value = NULL;
712*2882Svi117747 	int			ret;
713*2882Svi117747 
714*2882Svi117747 	if ((ret = sip_prim_parsers(hdr, phdr)) != 0)
715*2882Svi117747 		return (ret);
716*2882Svi117747 
717*2882Svi117747 	/*
718*2882Svi117747 	 * check if previously parsed
719*2882Svi117747 	 */
720*2882Svi117747 	if (*phdr != NULL) {
721*2882Svi117747 		hdr->sip_hdr_parsed = *phdr;
722*2882Svi117747 		return (0);
723*2882Svi117747 	}
724*2882Svi117747 	parsed_header = calloc(1, sizeof (sip_parsed_header_t));
725*2882Svi117747 	if (parsed_header == NULL)
726*2882Svi117747 		return (ENOMEM);
727*2882Svi117747 	parsed_header->sip_parsed_header_version = SIP_PARSED_HEADER_VERSION_1;
728*2882Svi117747 	parsed_header->sip_header = hdr;
729*2882Svi117747 	while (hdr->sip_hdr_current < hdr->sip_hdr_end) {
730*2882Svi117747 		int		r;
731*2882Svi117747 
732*2882Svi117747 		value = calloc(1, sizeof (sip_hdr_value_t));
733*2882Svi117747 		if (value == NULL) {
734*2882Svi117747 			sip_free_phdr(parsed_header);
735*2882Svi117747 			return (ENOMEM);
736*2882Svi117747 		}
737*2882Svi117747 
738*2882Svi117747 		if (last_value != NULL)
739*2882Svi117747 			last_value->sip_next_value = value;
740*2882Svi117747 		else
741*2882Svi117747 			parsed_header->value = (sip_value_t *)value;
742*2882Svi117747 
743*2882Svi117747 		value->sip_value_start = hdr->sip_hdr_current;
744*2882Svi117747 		value->sip_value_header = parsed_header;
745*2882Svi117747 
746*2882Svi117747 		if (type == SIP_STRS_VAL) {
747*2882Svi117747 			if (sip_find_token(hdr, SIP_LAQUOT) == 0) {
748*2882Svi117747 				char	*cur;
749*2882Svi117747 
750*2882Svi117747 				/*
751*2882Svi117747 				 * record the position after LAQUOT
752*2882Svi117747 				 */
753*2882Svi117747 				cur = hdr->sip_hdr_current;
754*2882Svi117747 				/*
755*2882Svi117747 				 * get display name and store in str1
756*2882Svi117747 				 */
757*2882Svi117747 				hdr->sip_hdr_current = value->sip_value_start;
758*2882Svi117747 				if (*(hdr->sip_hdr_current) != SIP_LAQUOT) {
759*2882Svi117747 					/*
760*2882Svi117747 					 * record start pos of display name
761*2882Svi117747 					 */
762*2882Svi117747 					char	*tmp = hdr->sip_hdr_current;
763*2882Svi117747 
764*2882Svi117747 					if (*hdr->sip_hdr_current ==
765*2882Svi117747 					    SIP_QUOTE) {
766*2882Svi117747 						hdr->sip_hdr_current++;
767*2882Svi117747 						tmp++;
768*2882Svi117747 						if (sip_find_token(hdr,
769*2882Svi117747 						    SIP_QUOTE) != 0) {
770*2882Svi117747 							value->sip_value_state =
771*2882Svi117747 							    SIP_VALUE_BAD;
772*2882Svi117747 							goto get_next_val;
773*2882Svi117747 						}
774*2882Svi117747 						hdr->sip_hdr_current -= 2;
775*2882Svi117747 					} else {
776*2882Svi117747 						hdr->sip_hdr_current = cur - 2;
777*2882Svi117747 						(void)
778*2882Svi117747 						    sip_reverse_skip_white_space
779*2882Svi117747 						    (hdr);
780*2882Svi117747 					}
781*2882Svi117747 					value->strs1_val_ptr = tmp;
782*2882Svi117747 					value->strs1_val_len =
783*2882Svi117747 					    hdr->sip_hdr_current - tmp + 1;
784*2882Svi117747 				} else {
785*2882Svi117747 					value->strs1_val_ptr = NULL;
786*2882Svi117747 					value->strs1_val_len = 0;
787*2882Svi117747 				}
788*2882Svi117747 
789*2882Svi117747 				/*
790*2882Svi117747 				 * set current to the char after LAQUOT
791*2882Svi117747 				 */
792*2882Svi117747 				hdr->sip_hdr_current = cur;
793*2882Svi117747 				value->strs2_val_ptr = hdr->sip_hdr_current;
794*2882Svi117747 				if (sip_find_token(hdr, SIP_RAQUOT)) {
795*2882Svi117747 					/*
796*2882Svi117747 					 * no RAQUOT
797*2882Svi117747 					 */
798*2882Svi117747 					value->strs1_val_ptr = NULL;
799*2882Svi117747 					value->strs1_val_len = 0;
800*2882Svi117747 					value->strs2_val_ptr = NULL;
801*2882Svi117747 					value->strs2_val_len = 0;
802*2882Svi117747 					value->sip_value_state = SIP_VALUE_BAD;
803*2882Svi117747 					goto get_next_val;
804*2882Svi117747 				}
805*2882Svi117747 				value->strs2_val_len = hdr->sip_hdr_current -
806*2882Svi117747 				    value->strs2_val_ptr - 1;
807*2882Svi117747 			} else {
808*2882Svi117747 				char	*cur;
809*2882Svi117747 
810*2882Svi117747 				/*
811*2882Svi117747 				 * No display name - Only URI.
812*2882Svi117747 				 */
813*2882Svi117747 				value->strs1_val_ptr = NULL;
814*2882Svi117747 				value->strs1_val_len = 0;
815*2882Svi117747 				cur = value->sip_value_start;
816*2882Svi117747 				hdr->sip_hdr_current = cur;
817*2882Svi117747 				if (sip_find_separator(hdr, SIP_COMMA,
818*2882Svi117747 				    (char)NULL, (char)NULL) != 0) {
819*2882Svi117747 					value->strs2_val_ptr = cur;
820*2882Svi117747 					value->strs2_val_len =
821*2882Svi117747 					    hdr->sip_hdr_current -
822*2882Svi117747 					    value->strs2_val_ptr - 1;
823*2882Svi117747 				} else if (*hdr->sip_hdr_current == SIP_SP) {
824*2882Svi117747 					value->strs2_val_ptr = cur;
825*2882Svi117747 					cur = hdr->sip_hdr_current - 1;
826*2882Svi117747 					if (sip_skip_white_space(hdr) != 0) {
827*2882Svi117747 						value->strs2_val_len = cur -
828*2882Svi117747 						    value->strs2_val_ptr - 1;
829*2882Svi117747 					} else if (*hdr->sip_hdr_current ==
830*2882Svi117747 					    SIP_COMMA) {
831*2882Svi117747 						value->strs2_val_len = cur -
832*2882Svi117747 						    value->strs2_val_ptr - 1;
833*2882Svi117747 					} else {
834*2882Svi117747 						value->sip_value_state =
835*2882Svi117747 						    SIP_VALUE_BAD;
836*2882Svi117747 						goto get_next_val;
837*2882Svi117747 					}
838*2882Svi117747 				} else {
839*2882Svi117747 					value->strs2_val_ptr = cur;
840*2882Svi117747 					value->strs2_val_len =
841*2882Svi117747 					    hdr->sip_hdr_current -
842*2882Svi117747 					    value->strs2_val_ptr;
843*2882Svi117747 				}
844*2882Svi117747 			}
845*2882Svi117747 			if (parse_uri)
846*2882Svi117747 				sip_parse_uri_str(&value->strs_s2, value);
847*2882Svi117747 		}
848*2882Svi117747 
849*2882Svi117747 		if (type == SIP_STR_VAL) {
850*2882Svi117747 			/*
851*2882Svi117747 			 * alert-info, error-info, call-info
852*2882Svi117747 			 */
853*2882Svi117747 			if (sip_find_token(hdr, SIP_LAQUOT) == 0) {
854*2882Svi117747 				value->str_val_ptr = hdr->sip_hdr_current;
855*2882Svi117747 				if (sip_find_token(hdr, SIP_RAQUOT) == 0) {
856*2882Svi117747 					value->str_val_len =
857*2882Svi117747 					    hdr->sip_hdr_current -
858*2882Svi117747 						value->str_val_ptr - 1;
859*2882Svi117747 				} else {
860*2882Svi117747 					value->str_val_ptr = NULL;
861*2882Svi117747 					value->str_val_len = 0;
862*2882Svi117747 					value->sip_value_state = SIP_VALUE_BAD;
863*2882Svi117747 					goto get_next_val;
864*2882Svi117747 				}
865*2882Svi117747 				hdr->sip_hdr_current--;
866*2882Svi117747 			} else {
867*2882Svi117747 				value->str_val_ptr = NULL;
868*2882Svi117747 				value->str_val_len = 0;
869*2882Svi117747 				value->sip_value_state = SIP_VALUE_BAD;
870*2882Svi117747 				goto get_next_val;
871*2882Svi117747 			}
872*2882Svi117747 			if (parse_uri)
873*2882Svi117747 				sip_parse_uri_str(&value->str_val, value);
874*2882Svi117747 		}
875*2882Svi117747 
876*2882Svi117747 		r = sip_find_separator(hdr, SIP_COMMA, SIP_SEMI, (char)NULL);
877*2882Svi117747 		if (r != 0) {
878*2882Svi117747 			value->sip_value_end = hdr->sip_hdr_current;
879*2882Svi117747 			goto end;
880*2882Svi117747 		}
881*2882Svi117747 		if (*hdr->sip_hdr_current == SIP_SEMI) {
882*2882Svi117747 			(void) sip_parse_params(hdr,
883*2882Svi117747 			    &(value->sip_param_list));
884*2882Svi117747 			goto get_next_val;
885*2882Svi117747 		}
886*2882Svi117747 
887*2882Svi117747 		if (*hdr->sip_hdr_current == SIP_COMMA) {
888*2882Svi117747 			hdr->sip_hdr_current--;
889*2882Svi117747 			goto get_next_val;
890*2882Svi117747 		}
891*2882Svi117747 get_next_val:
892*2882Svi117747 		if (sip_find_token(hdr, SIP_COMMA) != 0) {
893*2882Svi117747 			value->sip_value_end = hdr->sip_hdr_current;
894*2882Svi117747 			break;
895*2882Svi117747 		}
896*2882Svi117747 		value->sip_value_end = hdr->sip_hdr_current - 1;
897*2882Svi117747 		last_value = value;
898*2882Svi117747 		(void) sip_skip_white_space(hdr);
899*2882Svi117747 	}
900*2882Svi117747 
901*2882Svi117747 end:
902*2882Svi117747 	*phdr = parsed_header;
903*2882Svi117747 	hdr->sip_hdr_parsed = *phdr;
904*2882Svi117747 	return (0);
905*2882Svi117747 }
906*2882Svi117747 
907*2882Svi117747 /*
908*2882Svi117747  * parser4 parses hdr format, the whole field is one single str
909*2882Svi117747  * header: Subject, MIME-Version, Organization, Server, User-Agent
910*2882Svi117747  */
911*2882Svi117747 int
912*2882Svi117747 sip_parse_hdr_parser4(_sip_header_t *hdr, sip_parsed_header_t **phdr)
913*2882Svi117747 {
914*2882Svi117747 	sip_parsed_header_t	*parsed_header;
915*2882Svi117747 	sip_hdr_value_t		*value = NULL;
916*2882Svi117747 	int			ret;
917*2882Svi117747 
918*2882Svi117747 	if ((ret = sip_prim_parsers(hdr, phdr)) != 0)
919*2882Svi117747 		return (ret);
920*2882Svi117747 
921*2882Svi117747 	/*
922*2882Svi117747 	 * check if previously parsed
923*2882Svi117747 	 */
924*2882Svi117747 	if (*phdr != NULL) {
925*2882Svi117747 		hdr->sip_hdr_parsed = *phdr;
926*2882Svi117747 		return (0);
927*2882Svi117747 	}
928*2882Svi117747 	parsed_header = calloc(1, sizeof (sip_parsed_header_t));
929*2882Svi117747 	if (parsed_header == NULL)
930*2882Svi117747 		return (ENOMEM);
931*2882Svi117747 	parsed_header->sip_parsed_header_version = SIP_PARSED_HEADER_VERSION_1;
932*2882Svi117747 	parsed_header->sip_header = hdr;
933*2882Svi117747 
934*2882Svi117747 	value = calloc(1, sizeof (sip_hdr_value_t));
935*2882Svi117747 	if (value == NULL) {
936*2882Svi117747 		sip_free_phdr(parsed_header);
937*2882Svi117747 		return (ENOMEM);
938*2882Svi117747 	}
939*2882Svi117747 
940*2882Svi117747 	parsed_header->value = (sip_value_t *)value;
941*2882Svi117747 
942*2882Svi117747 	value->sip_value_start = hdr->sip_hdr_current;
943*2882Svi117747 	value->sip_value_header = parsed_header;
944*2882Svi117747 
945*2882Svi117747 	value->str_val_ptr = hdr->sip_hdr_current;
946*2882Svi117747 	/*
947*2882Svi117747 	 * get rid of CRLF at end
948*2882Svi117747 	 */
949*2882Svi117747 	value->str_val_len = hdr->sip_hdr_end - value->str_val_ptr - 2;
950*2882Svi117747 	value->sip_value_end = hdr->sip_hdr_end;
951*2882Svi117747 
952*2882Svi117747 	*phdr = parsed_header;
953*2882Svi117747 	hdr->sip_hdr_parsed = *phdr;
954*2882Svi117747 	return (0);
955*2882Svi117747 }
956*2882Svi117747 
957*2882Svi117747 int
958*2882Svi117747 sip_parse_hdr_parser5(_sip_header_t *hdr, sip_parsed_header_t **phdr,
959*2882Svi117747     boolean_t parse_uri)
960*2882Svi117747 {
961*2882Svi117747 	sip_parsed_header_t	*parsed_header;
962*2882Svi117747 	sip_hdr_value_t		*value = NULL;
963*2882Svi117747 	sip_param_t		*tmp_param;
964*2882Svi117747 	boolean_t		first_param = B_TRUE;
965*2882Svi117747 	int			ret;
966*2882Svi117747 
967*2882Svi117747 	if ((ret = sip_prim_parsers(hdr, phdr)) != 0)
968*2882Svi117747 		return (ret);
969*2882Svi117747 
970*2882Svi117747 	/*
971*2882Svi117747 	 * check if previously parsed
972*2882Svi117747 	 */
973*2882Svi117747 	if (*phdr != NULL) {
974*2882Svi117747 		hdr->sip_hdr_parsed = *phdr;
975*2882Svi117747 		return (0);
976*2882Svi117747 	}
977*2882Svi117747 	parsed_header = calloc(1, sizeof (sip_parsed_header_t));
978*2882Svi117747 	if (parsed_header == NULL)
979*2882Svi117747 		return (ENOMEM);
980*2882Svi117747 	parsed_header->sip_parsed_header_version = SIP_PARSED_HEADER_VERSION_1;
981*2882Svi117747 	parsed_header->sip_header = hdr;
982*2882Svi117747 
983*2882Svi117747 	value = calloc(1, sizeof (sip_hdr_value_t));
984*2882Svi117747 	if (value == NULL) {
985*2882Svi117747 		sip_free_phdr(parsed_header);
986*2882Svi117747 		return (ENOMEM);
987*2882Svi117747 	}
988*2882Svi117747 
989*2882Svi117747 	parsed_header->value = (sip_value_t *)value;
990*2882Svi117747 
991*2882Svi117747 	value->sip_value_start = hdr->sip_hdr_current;
992*2882Svi117747 	value->auth_scheme_ptr = value->sip_value_start;
993*2882Svi117747 	value->sip_value_header = parsed_header;
994*2882Svi117747 	/*
995*2882Svi117747 	 * get auth_scheme
996*2882Svi117747 	 */
997*2882Svi117747 	if (sip_find_white_space(hdr)) {
998*2882Svi117747 		value->sip_value_state = SIP_VALUE_BAD;
999*2882Svi117747 		return (EINVAL);
1000*2882Svi117747 	}
1001*2882Svi117747 	value->auth_scheme_len = hdr->sip_hdr_current - value->auth_scheme_ptr;
1002*2882Svi117747 
1003*2882Svi117747 	tmp_param = value->auth_param;
1004*2882Svi117747 
1005*2882Svi117747 	/*
1006*2882Svi117747 	 * parse auth_param
1007*2882Svi117747 	 */
1008*2882Svi117747 	for (;;) {
1009*2882Svi117747 		char		*tmp_cur;
1010*2882Svi117747 		boolean_t	quoted_name = B_FALSE;
1011*2882Svi117747 		char		quoted_char = (char)0;
1012*2882Svi117747 		sip_param_t	*new_param;
1013*2882Svi117747 		boolean_t	pval_is_uri = B_FALSE;
1014*2882Svi117747 
1015*2882Svi117747 		if (sip_skip_white_space(hdr) != 0) {
1016*2882Svi117747 			value->sip_value_state = SIP_VALUE_BAD;
1017*2882Svi117747 			return (EPROTO);
1018*2882Svi117747 		}
1019*2882Svi117747 		tmp_cur = hdr->sip_hdr_current;
1020*2882Svi117747 
1021*2882Svi117747 		new_param = calloc(1, sizeof (sip_param_t));
1022*2882Svi117747 		if (new_param == NULL)
1023*2882Svi117747 			return (ENOMEM);
1024*2882Svi117747 
1025*2882Svi117747 		if (first_param == B_FALSE)
1026*2882Svi117747 			tmp_param->param_next = new_param;
1027*2882Svi117747 		else
1028*2882Svi117747 			value->auth_param = new_param;
1029*2882Svi117747 
1030*2882Svi117747 		tmp_param = new_param;
1031*2882Svi117747 		tmp_param->param_name.sip_str_ptr = tmp_cur;
1032*2882Svi117747 
1033*2882Svi117747 		if (sip_find_separator(hdr, SIP_EQUAL, SIP_COMMA, (char)NULL) !=
1034*2882Svi117747 		    0) {
1035*2882Svi117747 			tmp_param->param_name.sip_str_len =
1036*2882Svi117747 			    hdr->sip_hdr_current - tmp_cur;
1037*2882Svi117747 			tmp_param->param_value.sip_str_ptr = NULL;
1038*2882Svi117747 			tmp_param->param_value.sip_str_len = 0;
1039*2882Svi117747 			value->sip_value_end = hdr->sip_hdr_current;
1040*2882Svi117747 			goto end;
1041*2882Svi117747 		}
1042*2882Svi117747 
1043*2882Svi117747 		/*
1044*2882Svi117747 		 * End of param name
1045*2882Svi117747 		 */
1046*2882Svi117747 		tmp_param->param_name.sip_str_len = hdr->sip_hdr_current -
1047*2882Svi117747 		    tmp_cur;
1048*2882Svi117747 
1049*2882Svi117747 		if (sip_skip_white_space(hdr) != 0 ||
1050*2882Svi117747 		    *hdr->sip_hdr_current == SIP_COMMA) {
1051*2882Svi117747 			tmp_param->param_value.sip_str_ptr = NULL;
1052*2882Svi117747 			tmp_param->param_value.sip_str_len = 0;
1053*2882Svi117747 			continue;
1054*2882Svi117747 		}
1055*2882Svi117747 
1056*2882Svi117747 		/*
1057*2882Svi117747 		 * We are at EQUAL
1058*2882Svi117747 		 */
1059*2882Svi117747 		hdr->sip_hdr_current++;
1060*2882Svi117747 
1061*2882Svi117747 		if (sip_skip_white_space(hdr) != 0) {
1062*2882Svi117747 			value->sip_value_state = SIP_VALUE_BAD;
1063*2882Svi117747 			free(tmp_param);
1064*2882Svi117747 			return (EPROTO);
1065*2882Svi117747 		}
1066*2882Svi117747 
1067*2882Svi117747 		if (*hdr->sip_hdr_current == SIP_QUOTE ||
1068*2882Svi117747 		    *hdr->sip_hdr_current == SIP_LAQUOT) {
1069*2882Svi117747 			if (*hdr->sip_hdr_current == SIP_QUOTE)
1070*2882Svi117747 				quoted_char = SIP_QUOTE;
1071*2882Svi117747 			else {
1072*2882Svi117747 				quoted_char = SIP_RAQUOT;
1073*2882Svi117747 				pval_is_uri = B_TRUE;
1074*2882Svi117747 			}
1075*2882Svi117747 			hdr->sip_hdr_current++;
1076*2882Svi117747 			quoted_name = B_TRUE;
1077*2882Svi117747 		}
1078*2882Svi117747 
1079*2882Svi117747 		/*
1080*2882Svi117747 		 * start of param value
1081*2882Svi117747 		 */
1082*2882Svi117747 		tmp_cur = hdr->sip_hdr_current;
1083*2882Svi117747 		tmp_param->param_value.sip_str_ptr = tmp_cur;
1084*2882Svi117747 		if (quoted_name) {
1085*2882Svi117747 			if (sip_find_token(hdr, quoted_char) != 0) {
1086*2882Svi117747 				value->sip_value_state = SIP_VALUE_BAD;
1087*2882Svi117747 				free(tmp_param);
1088*2882Svi117747 				return (EPROTO);
1089*2882Svi117747 			}
1090*2882Svi117747 			tmp_param->param_value.sip_str_len =
1091*2882Svi117747 			    hdr->sip_hdr_current - tmp_cur - 1;
1092*2882Svi117747 		}
1093*2882Svi117747 
1094*2882Svi117747 		if (sip_find_token(hdr, SIP_COMMA) != 0) {
1095*2882Svi117747 			value->sip_value_end = hdr->sip_hdr_current;
1096*2882Svi117747 			goto end;
1097*2882Svi117747 		} else {
1098*2882Svi117747 			if (!quoted_name) {
1099*2882Svi117747 				char *t = hdr->sip_hdr_current;
1100*2882Svi117747 				hdr->sip_hdr_current--;
1101*2882Svi117747 				(void) sip_reverse_skip_white_space(hdr);
1102*2882Svi117747 				tmp_param->param_value.sip_str_len =
1103*2882Svi117747 				    hdr->sip_hdr_current - tmp_cur;
1104*2882Svi117747 				hdr->sip_hdr_current = t;
1105*2882Svi117747 			}
1106*2882Svi117747 		}
1107*2882Svi117747 
1108*2882Svi117747 		if (first_param == B_TRUE)
1109*2882Svi117747 			first_param = B_FALSE;
1110*2882Svi117747 
1111*2882Svi117747 		/*
1112*2882Svi117747 		 * Parse uri
1113*2882Svi117747 		 */
1114*2882Svi117747 		if (pval_is_uri && parse_uri)
1115*2882Svi117747 			sip_parse_uri_str(&tmp_param->param_value, value);
1116*2882Svi117747 
1117*2882Svi117747 	}
1118*2882Svi117747 
1119*2882Svi117747 end:
1120*2882Svi117747 	*phdr = parsed_header;
1121*2882Svi117747 	hdr->sip_hdr_parsed = *phdr;
1122*2882Svi117747 	return (0);
1123*2882Svi117747 }
1124*2882Svi117747 
1125*2882Svi117747 /*
1126*2882Svi117747  * Return the URI in the request startline
1127*2882Svi117747  */
1128*2882Svi117747 static int
1129*2882Svi117747 _sip_get_request_uri(_sip_header_t *sip_header, sip_message_type_t *msg_info)
1130*2882Svi117747 {
1131*2882Svi117747 	int	size = 0;
1132*2882Svi117747 	char	*start_ptr;
1133*2882Svi117747 
1134*2882Svi117747 	if (sip_skip_white_space(sip_header) != 0)
1135*2882Svi117747 		return (EINVAL);
1136*2882Svi117747 	start_ptr = sip_header->sip_hdr_current;
1137*2882Svi117747 
1138*2882Svi117747 	while (!isspace(*sip_header->sip_hdr_current)) {
1139*2882Svi117747 		if (sip_header->sip_hdr_current >= sip_header->sip_hdr_end)
1140*2882Svi117747 			return (EINVAL);
1141*2882Svi117747 		sip_header->sip_hdr_current++;
1142*2882Svi117747 	}
1143*2882Svi117747 
1144*2882Svi117747 	size = sip_header->sip_hdr_current - start_ptr;
1145*2882Svi117747 
1146*2882Svi117747 	msg_info->U.sip_request.sip_request_uri.sip_str_ptr = start_ptr;
1147*2882Svi117747 	msg_info->U.sip_request.sip_request_uri.sip_str_len = size;
1148*2882Svi117747 	if (size > 0) {	/* Parse uri */
1149*2882Svi117747 		int		error;
1150*2882Svi117747 
1151*2882Svi117747 		msg_info->U.sip_request.sip_parse_uri = sip_parse_uri(
1152*2882Svi117747 		    &msg_info->U.sip_request.sip_request_uri, &error);
1153*2882Svi117747 		if (msg_info->U.sip_request.sip_parse_uri == NULL)
1154*2882Svi117747 			return (error);
1155*2882Svi117747 	}
1156*2882Svi117747 	return (0);
1157*2882Svi117747 }
1158*2882Svi117747 
1159*2882Svi117747 /*
1160*2882Svi117747  * Parse the start line into request/response
1161*2882Svi117747  */
1162*2882Svi117747 int
1163*2882Svi117747 sip_parse_first_line(_sip_header_t *sip_header, sip_message_type_t **msg_info)
1164*2882Svi117747 {
1165*2882Svi117747 	sip_message_type_t	*sip_msg_info;
1166*2882Svi117747 	boolean_t		sip_is_request = B_TRUE;
1167*2882Svi117747 	int			ret;
1168*2882Svi117747 
1169*2882Svi117747 	if (sip_header == NULL || msg_info == NULL)
1170*2882Svi117747 		return (EINVAL);
1171*2882Svi117747 
1172*2882Svi117747 	if (sip_skip_white_space(sip_header) != 0)
1173*2882Svi117747 		return (EPROTO);
1174*2882Svi117747 
1175*2882Svi117747 	/*
1176*2882Svi117747 	 * There is nothing, return
1177*2882Svi117747 	 */
1178*2882Svi117747 	if (sip_header->sip_hdr_current + strlen(SIP_VERSION) >=
1179*2882Svi117747 	    sip_header->sip_hdr_end) {
1180*2882Svi117747 		return (EPROTO);
1181*2882Svi117747 	}
1182*2882Svi117747 #ifdef	__solaris__
1183*2882Svi117747 	assert(mutex_held(&sip_header->sip_hdr_sipmsg->sip_msg_mutex));
1184*2882Svi117747 #endif
1185*2882Svi117747 	sip_msg_info = malloc(sizeof (sip_message_type_t));
1186*2882Svi117747 	if (sip_msg_info == NULL)
1187*2882Svi117747 		return (ENOMEM);
1188*2882Svi117747 
1189*2882Svi117747 	/*
1190*2882Svi117747 	 * let's see if it's a request or a response
1191*2882Svi117747 	 */
1192*2882Svi117747 	ret = sip_get_protocol_version(sip_header,
1193*2882Svi117747 	    &sip_msg_info->sip_proto_version);
1194*2882Svi117747 	if (ret == 0) {
1195*2882Svi117747 		sip_is_request = B_FALSE;
1196*2882Svi117747 	} else if (ret == 2) {
1197*2882Svi117747 		free(sip_msg_info);
1198*2882Svi117747 		return (EPROTO);
1199*2882Svi117747 	}
1200*2882Svi117747 
1201*2882Svi117747 	if (sip_skip_white_space(sip_header) != 0) {
1202*2882Svi117747 		free(sip_msg_info);
1203*2882Svi117747 		return (EPROTO);
1204*2882Svi117747 	}
1205*2882Svi117747 
1206*2882Svi117747 	if (!sip_is_request) {
1207*2882Svi117747 		/*
1208*2882Svi117747 		 * check for status code.
1209*2882Svi117747 		 */
1210*2882Svi117747 		if (sip_skip_white_space(sip_header) != 0) {
1211*2882Svi117747 			free(sip_msg_info);
1212*2882Svi117747 			return (EPROTO);
1213*2882Svi117747 		}
1214*2882Svi117747 		if (sip_header->sip_hdr_current + SIP_SIZE_OF_STATUS_CODE >=
1215*2882Svi117747 		    sip_header->sip_hdr_end) {
1216*2882Svi117747 			free(sip_msg_info);
1217*2882Svi117747 			return (EPROTO);
1218*2882Svi117747 		}
1219*2882Svi117747 
1220*2882Svi117747 		if (sip_atoi(sip_header,
1221*2882Svi117747 		    &sip_msg_info->U.sip_response.sip_response_code)) {
1222*2882Svi117747 			free(sip_msg_info);
1223*2882Svi117747 			return (EPROTO);
1224*2882Svi117747 		}
1225*2882Svi117747 
1226*2882Svi117747 		if (sip_msg_info->U.sip_response.sip_response_code < 100 ||
1227*2882Svi117747 		    sip_msg_info->U.sip_response.sip_response_code > 700) {
1228*2882Svi117747 			free(sip_msg_info);
1229*2882Svi117747 			return (EPROTO);
1230*2882Svi117747 		}
1231*2882Svi117747 
1232*2882Svi117747 		/*
1233*2882Svi117747 		 * get reason phrase.
1234*2882Svi117747 		 */
1235*2882Svi117747 		if (sip_skip_white_space(sip_header) != 0) {
1236*2882Svi117747 			sip_msg_info->sip_resp_phrase_len = 0;
1237*2882Svi117747 			sip_msg_info->sip_resp_phrase_ptr = NULL;
1238*2882Svi117747 		} else {
1239*2882Svi117747 			sip_msg_info->sip_resp_phrase_ptr =
1240*2882Svi117747 			    sip_header->sip_hdr_current;
1241*2882Svi117747 			if (sip_find_cr(sip_header) != 0) {
1242*2882Svi117747 				free(sip_msg_info);
1243*2882Svi117747 				return (EPROTO);
1244*2882Svi117747 			}
1245*2882Svi117747 			sip_msg_info->sip_resp_phrase_len =
1246*2882Svi117747 			    sip_header->sip_hdr_current -
1247*2882Svi117747 			    sip_msg_info->sip_resp_phrase_ptr;
1248*2882Svi117747 		}
1249*2882Svi117747 		sip_msg_info->is_request = B_FALSE;
1250*2882Svi117747 	} else {
1251*2882Svi117747 		int i;
1252*2882Svi117747 		/*
1253*2882Svi117747 		 * It's a request.
1254*2882Svi117747 		 */
1255*2882Svi117747 		sip_msg_info->is_request = B_TRUE;
1256*2882Svi117747 		for (i = 1; i < MAX_SIP_METHODS; i++) {
1257*2882Svi117747 			if (strncmp(sip_methods[i].name,
1258*2882Svi117747 			    sip_header->sip_hdr_current,
1259*2882Svi117747 			    sip_methods[i].len) == 0) {
1260*2882Svi117747 				sip_msg_info->sip_req_method = i;
1261*2882Svi117747 				sip_header->sip_hdr_current +=
1262*2882Svi117747 				    sip_methods[i].len;
1263*2882Svi117747 				if (!isspace(*sip_header->sip_hdr_current++) ||
1264*2882Svi117747 				    !isalpha(*sip_header->sip_hdr_current)) {
1265*2882Svi117747 					free(sip_msg_info);
1266*2882Svi117747 					return (EPROTO);
1267*2882Svi117747 				}
1268*2882Svi117747 
1269*2882Svi117747 				if ((ret = _sip_get_request_uri(sip_header,
1270*2882Svi117747 				    sip_msg_info)) != 0) {
1271*2882Svi117747 					free(sip_msg_info);
1272*2882Svi117747 					return (ret);
1273*2882Svi117747 				}
1274*2882Svi117747 
1275*2882Svi117747 				/*
1276*2882Svi117747 				 * Get SIP version
1277*2882Svi117747 				 */
1278*2882Svi117747 				ret = sip_get_protocol_version(sip_header,
1279*2882Svi117747 				    &sip_msg_info->sip_proto_version);
1280*2882Svi117747 				if (ret != 0) {
1281*2882Svi117747 					free(sip_msg_info);
1282*2882Svi117747 					return (EPROTO);
1283*2882Svi117747 				}
1284*2882Svi117747 				goto done;
1285*2882Svi117747 			}
1286*2882Svi117747 		}
1287*2882Svi117747 		free(sip_msg_info);
1288*2882Svi117747 		return (EPROTO);
1289*2882Svi117747 	}
1290*2882Svi117747 done:
1291*2882Svi117747 	sip_msg_info->sip_next = *msg_info;
1292*2882Svi117747 	*msg_info = sip_msg_info;
1293*2882Svi117747 	return (0);
1294*2882Svi117747 }
1295