xref: /onnv-gate/usr/src/lib/libsip/common/sip_parse_generic.c (revision 5092:0cbd682a52d4)
12882Svi117747 /*
22882Svi117747  * CDDL HEADER START
32882Svi117747  *
42882Svi117747  * The contents of this file are subject to the terms of the
52882Svi117747  * Common Development and Distribution License (the "License").
62882Svi117747  * You may not use this file except in compliance with the License.
72882Svi117747  *
82882Svi117747  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
92882Svi117747  * or http://www.opensolaris.org/os/licensing.
102882Svi117747  * See the License for the specific language governing permissions
112882Svi117747  * and limitations under the License.
122882Svi117747  *
132882Svi117747  * When distributing Covered Code, include this CDDL HEADER in each
142882Svi117747  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
152882Svi117747  * If applicable, add the following below this CDDL HEADER, with the
162882Svi117747  * fields enclosed by brackets "[]" replaced with your own identifying
172882Svi117747  * information: Portions Copyright [yyyy] [name of copyright owner]
182882Svi117747  *
192882Svi117747  * CDDL HEADER END
202882Svi117747  */
212882Svi117747 
222882Svi117747 /*
233439Svi117747  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
242882Svi117747  * Use is subject to license terms.
252882Svi117747  */
262882Svi117747 
272882Svi117747 #pragma ident	"%Z%%M%	%I%	%E% SMI"
282882Svi117747 
293439Svi117747 #include <stdlib.h>
303439Svi117747 #include <assert.h>
313439Svi117747 #include <errno.h>
323439Svi117747 #include <strings.h>
333439Svi117747 #include <ctype.h>
343439Svi117747 #include <sip.h>
353439Svi117747 
363439Svi117747 #include "sip_miscdefs.h"
372882Svi117747 #include "sip_msg.h"
383439Svi117747 #include "sip_parse_uri.h"
392882Svi117747 
402882Svi117747 /*
412882Svi117747  * atoi function from a header
422882Svi117747  */
432882Svi117747 int
sip_atoi(_sip_header_t * sip_header,int * num)442882Svi117747 sip_atoi(_sip_header_t *sip_header, int *num)
452882Svi117747 {
462882Svi117747 	boolean_t	num_found = B_FALSE;
472882Svi117747 
482882Svi117747 	*num = 0;
492882Svi117747 	while (sip_header->sip_hdr_current < sip_header->sip_hdr_end) {
502882Svi117747 		if (isspace(*sip_header->sip_hdr_current)) {
512882Svi117747 			sip_header->sip_hdr_current++;
522882Svi117747 			if (num_found)
532882Svi117747 				break;
542882Svi117747 		} else if (isdigit(*sip_header->sip_hdr_current)) {
552882Svi117747 			*num = (*num * 10) +
562882Svi117747 			    (*sip_header->sip_hdr_current - '0');
572882Svi117747 			num_found = B_TRUE;
582882Svi117747 			sip_header->sip_hdr_current++;
592882Svi117747 		} else {
602882Svi117747 			break;
612882Svi117747 		}
622882Svi117747 	}
632882Svi117747 	if (!num_found)
642882Svi117747 		return (EINVAL);
652882Svi117747 	return (0);
662882Svi117747 }
672882Svi117747 
682882Svi117747 /*
692882Svi117747  * Find the 'token'
702882Svi117747  */
712882Svi117747 int
sip_find_token(_sip_header_t * sip_header,char token)722882Svi117747 sip_find_token(_sip_header_t *sip_header, char token)
732882Svi117747 {
742882Svi117747 	while (sip_header->sip_hdr_current < sip_header->sip_hdr_end) {
752882Svi117747 		if (token != SIP_COMMA &&
762882Svi117747 		    *sip_header->sip_hdr_current == SIP_COMMA) {
772882Svi117747 			sip_header->sip_hdr_current--;
782882Svi117747 			return (1);
792882Svi117747 		}
802882Svi117747 		if (*sip_header->sip_hdr_current++ == token) {
812882Svi117747 			/*
822882Svi117747 			 * sip_hdr_current points to the char
832882Svi117747 			 * after the token
842882Svi117747 			 */
852882Svi117747 			return (0);
862882Svi117747 		}
872882Svi117747 	}
882882Svi117747 	return (1);
892882Svi117747 }
902882Svi117747 
912882Svi117747 /*
922882Svi117747  * Find a carriage-return
932882Svi117747  */
942882Svi117747 int
sip_find_cr(_sip_header_t * sip_header)952882Svi117747 sip_find_cr(_sip_header_t *sip_header)
962882Svi117747 {
972882Svi117747 	sip_header->sip_hdr_current = sip_header->sip_hdr_end;
982882Svi117747 	while (*sip_header->sip_hdr_current-- != '\n') {
992882Svi117747 		if (sip_header->sip_hdr_current == sip_header->sip_hdr_start)
1002882Svi117747 			return (1);
1012882Svi117747 	}
1022882Svi117747 	return (0);
1032882Svi117747 }
1042882Svi117747 
1052882Svi117747 /*
1062882Svi117747  * Find one of the separator provided, i.e. separator_1st or separator_2nd or
1072882Svi117747  * separator_3rd.
1082882Svi117747  */
1092882Svi117747 int
sip_find_separator(_sip_header_t * sip_header,char separator_1st,char separator_2nd,char separator_3rd,boolean_t ignore_space)1102882Svi117747 sip_find_separator(_sip_header_t *sip_header, char separator_1st,
111*5092Sgm209912     char separator_2nd, char separator_3rd, boolean_t ignore_space)
1122882Svi117747 {
1132882Svi117747 	assert(separator_1st != (char)NULL || separator_2nd != (char)NULL);
1142882Svi117747 	while (sip_header->sip_hdr_current < sip_header->sip_hdr_end) {
115*5092Sgm209912 		if (ignore_space && (*sip_header->sip_hdr_current == SIP_SP)) {
116*5092Sgm209912 			sip_header->sip_hdr_current++;
117*5092Sgm209912 			continue;
118*5092Sgm209912 		}
1192882Svi117747 		if (isspace(*sip_header->sip_hdr_current) ||
1202882Svi117747 		    (separator_1st != (char)NULL &&
1212882Svi117747 		    (*sip_header->sip_hdr_current == separator_1st)) ||
1222882Svi117747 		    (separator_2nd != (char)NULL &&
1232882Svi117747 		    (*sip_header->sip_hdr_current == separator_2nd)) ||
1242882Svi117747 		    (separator_3rd != (char)NULL &&
1252882Svi117747 		    (*sip_header->sip_hdr_current == separator_3rd))) {
1262882Svi117747 			return (0);
1272882Svi117747 		}
1282882Svi117747 		/*
1292882Svi117747 		 * If we have escape character, go to the next char
1302882Svi117747 		 */
1312882Svi117747 		if (*sip_header->sip_hdr_current == '\\')
1322882Svi117747 			sip_header->sip_hdr_current++;
1332882Svi117747 		sip_header->sip_hdr_current++;
1342882Svi117747 	}
1352882Svi117747 	return (1);
1362882Svi117747 }
1372882Svi117747 
1382882Svi117747 /*
1392882Svi117747  * Return when we hit a white space
1402882Svi117747  */
1412882Svi117747 int
sip_find_white_space(_sip_header_t * sip_header)1422882Svi117747 sip_find_white_space(_sip_header_t *sip_header)
1432882Svi117747 {
1442882Svi117747 	while (sip_header->sip_hdr_current < sip_header->sip_hdr_end) {
1452882Svi117747 		if (isspace(*sip_header->sip_hdr_current))
1462882Svi117747 			return (0);
1472882Svi117747 		sip_header->sip_hdr_current++;
1482882Svi117747 	}
1492882Svi117747 	return (1);
1502882Svi117747 }
1512882Svi117747 
1522882Svi117747 /*
1532882Svi117747  * Skip to the next non-whitespace
1542882Svi117747  */
1552882Svi117747 int
sip_skip_white_space(_sip_header_t * sip_header)1562882Svi117747 sip_skip_white_space(_sip_header_t *sip_header)
1572882Svi117747 {
1582882Svi117747 	while (sip_header->sip_hdr_current < sip_header->sip_hdr_end) {
1592882Svi117747 		if (!isspace(*sip_header->sip_hdr_current))
1602882Svi117747 			return (0);
1612882Svi117747 		sip_header->sip_hdr_current++;
1622882Svi117747 	}
1632882Svi117747 	return (1);
1642882Svi117747 }
1652882Svi117747 
1662882Svi117747 
1672882Svi117747 /*
1682882Svi117747  * Skip to the non-white space in the reverse direction
1692882Svi117747  */
1702882Svi117747 int
sip_reverse_skip_white_space(_sip_header_t * sip_header)1712882Svi117747 sip_reverse_skip_white_space(_sip_header_t *sip_header)
1722882Svi117747 {
1732882Svi117747 	while (sip_header->sip_hdr_current >= sip_header->sip_hdr_start) {
1742882Svi117747 		if (!isspace(*sip_header->sip_hdr_current))
1752882Svi117747 			return (0);
1762882Svi117747 		sip_header->sip_hdr_current--;
1772882Svi117747 	}
1782882Svi117747 	return (1);
1792882Svi117747 }
1802882Svi117747 
1812882Svi117747 /*
1822882Svi117747  * get to the first non space after ':'
1832882Svi117747  */
1842882Svi117747 int
sip_parse_goto_values(_sip_header_t * sip_header)1852882Svi117747 sip_parse_goto_values(_sip_header_t *sip_header)
1862882Svi117747 {
1872882Svi117747 	if (sip_find_token(sip_header, SIP_HCOLON) !=  0)
1882882Svi117747 		return (1);
1892882Svi117747 	if (sip_skip_white_space(sip_header) != 0)
1902882Svi117747 		return (1);
1912882Svi117747 
1922882Svi117747 	return (0);
1932882Svi117747 }
1942882Svi117747 
1952882Svi117747 /*
1962882Svi117747  * Skip the current value.
1972882Svi117747  */
1982882Svi117747 int
sip_goto_next_value(_sip_header_t * sip_header)1992882Svi117747 sip_goto_next_value(_sip_header_t *sip_header)
2002882Svi117747 {
2012882Svi117747 	boolean_t	quoted = B_FALSE;
2022882Svi117747 
2032882Svi117747 	while (sip_header->sip_hdr_current < sip_header->sip_hdr_end) {
2042882Svi117747 		if (*sip_header->sip_hdr_current == SIP_QUOTE) {
2052882Svi117747 			if (quoted)
2062882Svi117747 				quoted = B_FALSE;
2072882Svi117747 			else
2082882Svi117747 				quoted = B_TRUE;
2092882Svi117747 		} else if (!quoted &&
2102882Svi117747 		    *sip_header->sip_hdr_current == SIP_COMMA) {
2112882Svi117747 			/*
2122882Svi117747 			 * value ends before the COMMA
2132882Svi117747 			 */
2142882Svi117747 			sip_header->sip_hdr_current--;
2152882Svi117747 			return (0);
2162882Svi117747 		}
2172882Svi117747 		sip_header->sip_hdr_current++;
2182882Svi117747 	}
2192882Svi117747 	if (quoted)
2202882Svi117747 		return (1);
2212882Svi117747 	return (0);
2222882Svi117747 }
2232882Svi117747 
2242882Svi117747 /*
2252882Svi117747  * Parse the header into parameter list. Parameters start with a ';'
2262882Svi117747  */
2272882Svi117747 int
sip_parse_params(_sip_header_t * sip_header,sip_param_t ** parsed_list)2282882Svi117747 sip_parse_params(_sip_header_t *sip_header, sip_param_t **parsed_list)
2292882Svi117747 {
2302882Svi117747 	sip_param_t	*param = NULL;
2312882Svi117747 	sip_param_t	*new_param;
2322882Svi117747 	char		*tmp_ptr;
2332882Svi117747 
2342882Svi117747 	if (parsed_list == NULL)
2352882Svi117747 		return (0);
2362882Svi117747 
2372882Svi117747 	*parsed_list = NULL;
2382882Svi117747 	for (;;) {
2392882Svi117747 		boolean_t	quoted_name = B_FALSE;
2402882Svi117747 
2412882Svi117747 		/*
2422882Svi117747 		 * First check if there are any params
2432882Svi117747 		 */
2442882Svi117747 		if (sip_skip_white_space(sip_header) != 0)
2452882Svi117747 			return (0);
2462882Svi117747 		if (*sip_header->sip_hdr_current != SIP_SEMI)
2472882Svi117747 			return (0);
2482882Svi117747 
2492882Svi117747 		sip_header->sip_hdr_current++;
2502882Svi117747 
2512882Svi117747 		new_param = calloc(1, sizeof (sip_param_t));
2522882Svi117747 		if (new_param == NULL)
2532882Svi117747 			return (ENOMEM);
2542882Svi117747 
2552882Svi117747 		if (param != NULL)
2562882Svi117747 			param->param_next = new_param;
2572882Svi117747 		else
2582882Svi117747 			*parsed_list = new_param;
2592882Svi117747 
2602882Svi117747 		param = new_param;
2612882Svi117747 
2622882Svi117747 		/*
2632882Svi117747 		 * Let's get to the start of the param name
2642882Svi117747 		 */
2652882Svi117747 		if (sip_skip_white_space(sip_header) != 0)
2662882Svi117747 			return (EPROTO);
2672882Svi117747 		/*
2682882Svi117747 		 * start of param name
2692882Svi117747 		 */
2702882Svi117747 		tmp_ptr = sip_header->sip_hdr_current;
2712882Svi117747 		param->param_name.sip_str_ptr = tmp_ptr;
2722882Svi117747 
2732882Svi117747 		if (sip_find_separator(sip_header, SIP_EQUAL, SIP_SEMI,
274*5092Sgm209912 		    SIP_COMMA, B_FALSE) != 0) {
2752882Svi117747 			param->param_name.sip_str_len =
2762882Svi117747 			    sip_header->sip_hdr_current - tmp_ptr;
2772882Svi117747 			param->param_value.sip_str_ptr = NULL;
2782882Svi117747 			param->param_value.sip_str_len = 0;
2792882Svi117747 			return (0);
2802882Svi117747 		}
2812882Svi117747 
2822882Svi117747 		/*
2832882Svi117747 		 * End of param name
2842882Svi117747 		 */
2852882Svi117747 		param->param_name.sip_str_len =
2862882Svi117747 		    sip_header->sip_hdr_current - tmp_ptr;
2872882Svi117747 
2882882Svi117747 		if (sip_skip_white_space(sip_header) != 0 ||
2892882Svi117747 		    *sip_header->sip_hdr_current == SIP_COMMA) {
2902882Svi117747 			param->param_value.sip_str_ptr = NULL;
2912882Svi117747 			param->param_value.sip_str_len = 0;
2922882Svi117747 			return (0);
2932882Svi117747 		}
2942882Svi117747 		if (*sip_header->sip_hdr_current == SIP_SEMI) {
2952882Svi117747 			param->param_value.sip_str_ptr = NULL;
2962882Svi117747 			param->param_value.sip_str_len = 0;
2972882Svi117747 			continue;
2982882Svi117747 		}
2992882Svi117747 		assert(*sip_header->sip_hdr_current == SIP_EQUAL);
3002882Svi117747 
3012882Svi117747 		/*
3022882Svi117747 		 * We are at EQUAL, lets go beyond that
3032882Svi117747 		 */
3042882Svi117747 		sip_header->sip_hdr_current++;
3052882Svi117747 
3062882Svi117747 		if (sip_skip_white_space(sip_header) != 0)
3072882Svi117747 			return (EPROTO);
3082882Svi117747 
3092882Svi117747 		if (*sip_header->sip_hdr_current == SIP_QUOTE) {
3102882Svi117747 			sip_header->sip_hdr_current++;
3112882Svi117747 			quoted_name = B_TRUE;
3122882Svi117747 		}
3132882Svi117747 
3142882Svi117747 		/*
3152882Svi117747 		 * start of param value
3162882Svi117747 		 */
3172882Svi117747 		param->param_value.sip_str_ptr = sip_header->sip_hdr_current;
3182882Svi117747 		tmp_ptr = sip_header->sip_hdr_current;
3192882Svi117747 
3202882Svi117747 		if (quoted_name && sip_find_token(sip_header, SIP_QUOTE) != 0) {
3212882Svi117747 			return (EPROTO);
3222882Svi117747 		} else if (sip_find_separator(sip_header, SIP_SEMI, SIP_COMMA,
323*5092Sgm209912 		    (char)NULL, B_FALSE) != 0) {
3242882Svi117747 			return (EPROTO);
3252882Svi117747 		}
3262882Svi117747 		param->param_value.sip_str_len = sip_header->sip_hdr_current -
3272882Svi117747 		    tmp_ptr;
3282882Svi117747 		if (quoted_name)
3292882Svi117747 			param->param_value.sip_str_len--;
3302882Svi117747 	}
3312882Svi117747 }
3322882Svi117747 
3332882Svi117747 /*
3342882Svi117747  * a header that only has "header_name : " is an empty header
3352882Svi117747  * ":" must exist
3362882Svi117747  * sip_hdr_current resets to sip_hdr_start before exit
3372882Svi117747  */
3382882Svi117747 boolean_t
sip_is_empty_hdr(_sip_header_t * sip_header)3392882Svi117747 sip_is_empty_hdr(_sip_header_t *sip_header)
3402882Svi117747 {
3412882Svi117747 	if (sip_find_token(sip_header, SIP_HCOLON) != 0) {
3422882Svi117747 		sip_header->sip_hdr_current = sip_header->sip_hdr_start;
3432882Svi117747 		return (B_FALSE);
3442882Svi117747 	}
3452882Svi117747 
3462882Svi117747 	if (sip_skip_white_space(sip_header) == 0) {
3472882Svi117747 		sip_header->sip_hdr_current = sip_header->sip_hdr_start;
3482882Svi117747 		return (B_FALSE);
3492882Svi117747 	}
3502882Svi117747 
3512882Svi117747 	sip_header->sip_hdr_current = sip_header->sip_hdr_start;
3522882Svi117747 	return (B_TRUE);
3532882Svi117747 }
3542882Svi117747 
3552882Svi117747 /*
3562882Svi117747  * Parsing an empty header, i.e. only has a ":"
3572882Svi117747  */
3582882Svi117747 int
sip_parse_hdr_empty(_sip_header_t * hdr,sip_parsed_header_t ** phdr)3592882Svi117747 sip_parse_hdr_empty(_sip_header_t *hdr, sip_parsed_header_t **phdr)
3602882Svi117747 {
3612882Svi117747 	sip_parsed_header_t	*parsed_header;
3622882Svi117747 
3632882Svi117747 	if (hdr == NULL || phdr == NULL)
3642882Svi117747 		return (EINVAL);
3652882Svi117747 
3662882Svi117747 	/*
3672882Svi117747 	 * check if already parsed
3682882Svi117747 	 */
3692882Svi117747 	if (hdr->sip_hdr_parsed != NULL) {
3702882Svi117747 		*phdr = hdr->sip_hdr_parsed;
3712882Svi117747 		return (0);
3722882Svi117747 	}
3732882Svi117747 
3742882Svi117747 	*phdr = NULL;
3752882Svi117747 
3762882Svi117747 	parsed_header = calloc(1, sizeof (sip_parsed_header_t));
3772882Svi117747 	if (parsed_header == NULL)
3782882Svi117747 		return (ENOMEM);
3792882Svi117747 	parsed_header->sip_header = hdr;
3802882Svi117747 
3812882Svi117747 	parsed_header->value = NULL;
3822882Svi117747 
3832882Svi117747 	*phdr = parsed_header;
3842882Svi117747 	return (0);
3852882Svi117747 }
3862882Svi117747 
3872882Svi117747 /*
3882882Svi117747  * validate uri str and parse uri using uri_parse()
3892882Svi117747  */
3902882Svi117747 static void
sip_parse_uri_str(sip_str_t * sip_str,sip_hdr_value_t * value)3912882Svi117747 sip_parse_uri_str(sip_str_t *sip_str, sip_hdr_value_t *value)
3922882Svi117747 {
3932882Svi117747 	int		error;
3942882Svi117747 
3952882Svi117747 	/*
3962882Svi117747 	 * Parse uri
3972882Svi117747 	 */
3982882Svi117747 	if (sip_str->sip_str_len > 0) {
3992882Svi117747 		value->sip_value_parsed_uri = sip_parse_uri(sip_str, &error);
4002882Svi117747 		if (value->sip_value_parsed_uri == NULL)
4012882Svi117747 			return;
4022882Svi117747 		if (error != 0 ||
4032882Svi117747 		    value->sip_value_parsed_uri->sip_uri_errflags != 0) {
4042882Svi117747 			value->sip_value_state = SIP_VALUE_BAD;
4052882Svi117747 		}
4062882Svi117747 	}
4072882Svi117747 }
4082882Svi117747 
4092882Svi117747 /*
4102882Svi117747  * Some basic common checks before parsing the headers
4112882Svi117747  */
4122882Svi117747 int
sip_prim_parsers(_sip_header_t * sip_header,sip_parsed_header_t ** header)4132882Svi117747 sip_prim_parsers(_sip_header_t *sip_header, sip_parsed_header_t **header)
4142882Svi117747 {
4152882Svi117747 	if (sip_header == NULL || header == NULL)
4162882Svi117747 		return (EINVAL);
4172882Svi117747 
4182882Svi117747 	/*
4192882Svi117747 	 * check if already parsed
4202882Svi117747 	 */
4212882Svi117747 	if (sip_header->sip_hdr_parsed != NULL) {
4222882Svi117747 		*header = sip_header->sip_hdr_parsed;
4232882Svi117747 		return (0);
4242882Svi117747 	}
4252882Svi117747 	*header = NULL;
4262882Svi117747 
4272882Svi117747 	assert(sip_header->sip_hdr_start == sip_header->sip_hdr_current);
4282882Svi117747 
4292882Svi117747 	if (sip_parse_goto_values(sip_header) != 0)
4302882Svi117747 		return (EPROTO);
4312882Svi117747 
4322882Svi117747 	return (0);
4332882Svi117747 }
4342882Svi117747 
4352882Svi117747 /*
4362882Svi117747  * Parse SIP/2.0 string
4372882Svi117747  */
4382882Svi117747 int
sip_get_protocol_version(_sip_header_t * sip_header,sip_proto_version_t * sip_proto_version)4392882Svi117747 sip_get_protocol_version(_sip_header_t *sip_header,
4402882Svi117747     sip_proto_version_t *sip_proto_version)
4412882Svi117747 {
4422882Svi117747 	if (sip_skip_white_space(sip_header) != 0)
4432882Svi117747 		return (1);
4442882Svi117747 
4452882Svi117747 	if (strncasecmp(sip_header->sip_hdr_current, SIP, strlen(SIP)) == 0) {
4462882Svi117747 		sip_proto_version->name.sip_str_ptr =
4472882Svi117747 		    sip_header->sip_hdr_current;
4482882Svi117747 		sip_proto_version->name.sip_str_len = strlen(SIP);
4492882Svi117747 
4502882Svi117747 		if (sip_find_token(sip_header, SIP_SLASH) != 0)
4512882Svi117747 			return (1);
4522882Svi117747 		if (sip_skip_white_space(sip_header) != 0)
4532882Svi117747 			return (1);
4542882Svi117747 
4552882Svi117747 		sip_proto_version->version.sip_str_ptr =
4562882Svi117747 		    sip_header->sip_hdr_current;
4572882Svi117747 		while (isdigit(*sip_header->sip_hdr_current)) {
4582882Svi117747 			sip_header->sip_hdr_current++;
4592882Svi117747 			if (sip_header->sip_hdr_current >=
4602882Svi117747 			    sip_header->sip_hdr_end) {
4612882Svi117747 				return (1);
4622882Svi117747 			}
4632882Svi117747 		}
4642882Svi117747 		if (*sip_header->sip_hdr_current != SIP_PERIOD)
4652882Svi117747 			return (1);
4662882Svi117747 		sip_header->sip_hdr_current++;
4672882Svi117747 
4682882Svi117747 		if (!isdigit(*sip_header->sip_hdr_current))
4692882Svi117747 			return (1);
4702882Svi117747 		while (isdigit(*sip_header->sip_hdr_current)) {
4712882Svi117747 			sip_header->sip_hdr_current++;
4722882Svi117747 			if (sip_header->sip_hdr_current >=
4732882Svi117747 			    sip_header->sip_hdr_end) {
4742882Svi117747 				return (1);
4752882Svi117747 			}
4762882Svi117747 		}
4772882Svi117747 
4782882Svi117747 		sip_proto_version->version.sip_str_len =
4792882Svi117747 		    sip_header->sip_hdr_current -
4802882Svi117747 		    sip_proto_version->version.sip_str_ptr;
4812882Svi117747 		return (0);
4822882Svi117747 	}
4832882Svi117747 	return (1);
4842882Svi117747 }
4852882Svi117747 
4862882Svi117747 /*
4872882Svi117747  * parser1 parses hdr format
4882882Svi117747  *	header_name: val1[; par1=pval1;par2=pval2 ..][, val2[;parlist..] ]
4892882Svi117747  *	val can be str1/str2 or str
4902882Svi117747  * headers: Accept, Accept-Encode, Accept-lang, Allow, Content-disp,
4912882Svi117747  *	    Content-Encode, Content-Lang, In-reply-to,
4922882Svi117747  *	    Priority, Require, Supported, Unsupported
4932882Svi117747  *	    Allow-Events, Event, Subscription-State
4942882Svi117747  */
4952882Svi117747 int
sip_parse_hdr_parser1(_sip_header_t * hdr,sip_parsed_header_t ** phdr,char sep)4962882Svi117747 sip_parse_hdr_parser1(_sip_header_t *hdr, sip_parsed_header_t **phdr, char sep)
4972882Svi117747 {
4982882Svi117747 	sip_parsed_header_t	*parsed_header;
4992882Svi117747 	int			ret;
5002882Svi117747 	sip_hdr_value_t		*value = NULL;
5012882Svi117747 	sip_hdr_value_t		*last_value = NULL;
5022882Svi117747 
5032882Svi117747 	if ((ret = sip_prim_parsers(hdr, phdr)) != 0)
5042882Svi117747 		return (ret);
5052882Svi117747 
5062882Svi117747 	/*
5072882Svi117747 	 * check if previously parsed
5082882Svi117747 	 */
5092882Svi117747 	if (*phdr != NULL) {
5102882Svi117747 		hdr->sip_hdr_parsed = *phdr;
5112882Svi117747 		return (0);
5122882Svi117747 	}
5132882Svi117747 
5142882Svi117747 	parsed_header = calloc(1, sizeof (sip_parsed_header_t));
5152882Svi117747 	if (parsed_header == NULL)
5162882Svi117747 		return (ENOMEM);
5172882Svi117747 	parsed_header->sip_parsed_header_version = SIP_PARSED_HEADER_VERSION_1;
5182882Svi117747 	parsed_header->sip_header = hdr;
5192882Svi117747 
5202882Svi117747 	while (hdr->sip_hdr_current < hdr->sip_hdr_end) {
5212882Svi117747 		value = calloc(1, sizeof (sip_hdr_value_t));
5222882Svi117747 		if (value == NULL) {
5232882Svi117747 			sip_free_phdr(parsed_header);
5242882Svi117747 			return (ENOMEM);
5252882Svi117747 		}
5262882Svi117747 		if (last_value != NULL)
5272882Svi117747 			last_value->sip_next_value = value;
5282882Svi117747 		else
5292882Svi117747 			parsed_header->value = (sip_value_t *)value;
5302882Svi117747 
5312882Svi117747 		value->sip_value_start = hdr->sip_hdr_current;
5322882Svi117747 		value->sip_value_header = parsed_header;
5332882Svi117747 
534*5092Sgm209912 		if (sip_find_separator(hdr, sep, SIP_COMMA, SIP_SEMI,
535*5092Sgm209912 		    B_FALSE) == 0) {
5362882Svi117747 			char	c = *hdr->sip_hdr_current;
5372882Svi117747 
5382882Svi117747 			if (isspace(c) && sep == (char)NULL) {
5392882Svi117747 				value->str_val_ptr = value->sip_value_start;
5402882Svi117747 				value->str_val_len = hdr->sip_hdr_current -
5412882Svi117747 				    value->sip_value_start;
5422882Svi117747 				/*
5432882Svi117747 				 * nothing at the end except space
5442882Svi117747 				 */
5452882Svi117747 				if (sip_skip_white_space(hdr) != 0) {
5462882Svi117747 					value->sip_value_end =
5472882Svi117747 					    hdr->sip_hdr_current;
5482882Svi117747 					goto end;
5492882Svi117747 				}
5502882Svi117747 				/*
5512882Svi117747 				 * white space skipped
5522882Svi117747 				 */
5532882Svi117747 				c = *(hdr->sip_hdr_current);
5542882Svi117747 			}
5552882Svi117747 
5562882Svi117747 			/*
5572882Svi117747 			 * only one string until COMMA, use sip_str_t
5582882Svi117747 			 */
5592882Svi117747 			if (c == SIP_COMMA) {
5602882Svi117747 				char	*t = hdr->sip_hdr_current;
5612882Svi117747 
5622882Svi117747 				hdr->sip_hdr_current--;
5632882Svi117747 				(void) sip_reverse_skip_white_space(hdr);
5642882Svi117747 				value->str_val_ptr = value->sip_value_start;
5652882Svi117747 				value->str_val_len = hdr->sip_hdr_current -
5662882Svi117747 				    value->sip_value_start + 1;
5672882Svi117747 				hdr->sip_hdr_current = t;
5682882Svi117747 				goto get_next_val;
5692882Svi117747 			}
5702882Svi117747 
5712882Svi117747 			/*
5722882Svi117747 			 * two strings, use sip_2strs_t
5732882Svi117747 			 */
5742882Svi117747 			if ((sep != (char)NULL) && (c == sep)) {
5752882Svi117747 				value->strs1_val_ptr = value->sip_value_start;
5762882Svi117747 				value->strs1_val_len = hdr->sip_hdr_current -
5772882Svi117747 				    value->sip_value_start;
5782882Svi117747 
5792882Svi117747 				value->strs2_val_ptr =
5802882Svi117747 				    (++hdr->sip_hdr_current);
5812882Svi117747 				if (sip_find_separator(hdr, SIP_SEMI, SIP_COMMA,
582*5092Sgm209912 				    (char)NULL, B_FALSE) == 0) {
5832882Svi117747 					char t = *(hdr->sip_hdr_current);
5842882Svi117747 					value->strs2_val_len =
5852882Svi117747 					    hdr->sip_hdr_current -
586*5092Sgm209912 					    value->strs2_val_ptr;
5872882Svi117747 					/*
5882882Svi117747 					 * if COMMA, no param list, get next val
5892882Svi117747 					 * if SEMI, need to set params list
5902882Svi117747 					 */
5912882Svi117747 					if (t == SIP_COMMA)
5922882Svi117747 						goto get_next_val;
5932882Svi117747 				} else { /* the last part */
5942882Svi117747 					value->strs2_val_len =
5952882Svi117747 					    hdr->sip_hdr_current -
596*5092Sgm209912 					    value->strs2_val_ptr;
5972882Svi117747 					value->sip_value_end =
5982882Svi117747 					    hdr->sip_hdr_current;
5992882Svi117747 					goto end;
6002882Svi117747 				}
6012882Svi117747 			} else if (sep != (char)NULL) {
6022882Svi117747 				value->sip_value_state = SIP_VALUE_BAD;
6032882Svi117747 				goto get_next_val;
6042882Svi117747 			}
6052882Svi117747 
6062882Svi117747 			/*
6072882Svi117747 			 * c == SEMI, value contains single string
6082882Svi117747 			 * only one string until SEMI, use sip_str_t
6092882Svi117747 			 */
6102882Svi117747 			if (c == SIP_SEMI) {
6112882Svi117747 				char	*t = hdr->sip_hdr_current;
6122882Svi117747 
6132882Svi117747 				hdr->sip_hdr_current--;
6142882Svi117747 				/*
6152882Svi117747 				 * get rid of SP at end of value field
6162882Svi117747 				 */
6172882Svi117747 				(void) sip_reverse_skip_white_space(hdr);
6182882Svi117747 				value->str_val_ptr = value->sip_value_start;
6192882Svi117747 				value->str_val_len = hdr->sip_hdr_current -
6202882Svi117747 				    value->str_val_ptr + 1;
6212882Svi117747 				hdr->sip_hdr_current = t;
6222882Svi117747 			}
6232882Svi117747 
6242882Svi117747 			/*
6252882Svi117747 			 * if SEMI exists in the value, set params list
6262882Svi117747 			 * two situations, there is or not SLASH before SEMI
6272882Svi117747 			 */
6282882Svi117747 			ret = sip_parse_params(hdr, &value->sip_param_list);
6292882Svi117747 			if (ret == EPROTO) {
6302882Svi117747 				value->sip_value_state = SIP_VALUE_BAD;
6312882Svi117747 			} else if (ret != 0) {
6322882Svi117747 				sip_free_phdr(parsed_header);
6332882Svi117747 				return (ret);
6342882Svi117747 			}
6352882Svi117747 			goto get_next_val;
6362882Svi117747 		} else {
6372882Svi117747 			value->str_val_ptr = value->sip_value_start;
6382882Svi117747 			value->str_val_len = hdr->sip_hdr_current -
6392882Svi117747 			    value->sip_value_start;
6402882Svi117747 			value->sip_value_end = hdr->sip_hdr_current;
6412882Svi117747 			goto end;
6422882Svi117747 		}
6432882Svi117747 get_next_val:
6442882Svi117747 		if (sip_find_token(hdr, SIP_COMMA) != 0) {
6452882Svi117747 			value->sip_value_end = hdr->sip_hdr_current;
6462882Svi117747 			break;
6472882Svi117747 		}
6482882Svi117747 		value->sip_value_end = hdr->sip_hdr_current - 1;
6492882Svi117747 		last_value = value;
6502882Svi117747 		(void) sip_skip_white_space(hdr);
6512882Svi117747 	}
6522882Svi117747 
6532882Svi117747 end:
6542882Svi117747 	*phdr = parsed_header;
6552882Svi117747 	hdr->sip_hdr_parsed = *phdr;
6562882Svi117747 	return (0);
6572882Svi117747 }
6582882Svi117747 
6592882Svi117747 /*
6602882Svi117747  * header_name: int
6612882Svi117747  * headers: Expires, Min-Expires
6622882Svi117747  */
6632882Svi117747 /* ARGSUSED */
6642882Svi117747 int
sip_parse_hdr_parser2(_sip_header_t * hdr,sip_parsed_header_t ** phdr,int val_type)6652882Svi117747 sip_parse_hdr_parser2(_sip_header_t *hdr, sip_parsed_header_t **phdr,
6662882Svi117747     int val_type)
6672882Svi117747 {
6682882Svi117747 	sip_parsed_header_t	*parsed_header;
6692882Svi117747 	int			ret = 0;
6702882Svi117747 	sip_hdr_value_t		*value = NULL;
6712882Svi117747 
6722882Svi117747 	if ((ret = sip_prim_parsers(hdr, phdr)) != 0)
6732882Svi117747 		return (ret);
6742882Svi117747 
6752882Svi117747 	/*
6762882Svi117747 	 * check if previously parsed
6772882Svi117747 	 */
6782882Svi117747 	if (*phdr != NULL) {
6792882Svi117747 		hdr->sip_hdr_parsed = *phdr;
6802882Svi117747 		return (0);
6812882Svi117747 	}
6822882Svi117747 	parsed_header = calloc(1, sizeof (sip_parsed_header_t));
6832882Svi117747 	if (parsed_header == NULL)
6842882Svi117747 		return (ENOMEM);
6852882Svi117747 	parsed_header->sip_parsed_header_version = SIP_PARSED_HEADER_VERSION_1;
6862882Svi117747 	parsed_header->sip_header = hdr;
6872882Svi117747 
6882882Svi117747 	value = calloc(1, sizeof (sip_hdr_value_t));
6892882Svi117747 	if (value == NULL) {
6902882Svi117747 		sip_free_phdr(parsed_header);
6912882Svi117747 		return (ENOMEM);
6922882Svi117747 	}
6932882Svi117747 
6942882Svi117747 	parsed_header->value = (sip_value_t *)value;
6952882Svi117747 
6962882Svi117747 	value->sip_value_start = hdr->sip_hdr_current;
6972882Svi117747 	value->sip_value_header = parsed_header;
6982882Svi117747 
6992882Svi117747 	ret = sip_atoi(hdr, &value->int_val);
7002882Svi117747 	if (ret != 0) {
7012882Svi117747 		value->int_val = 0;
7022882Svi117747 		value->sip_value_state = SIP_VALUE_BAD;
7032882Svi117747 	}
7042882Svi117747 
7052882Svi117747 	value->sip_value_end = hdr->sip_hdr_current - 1;
7062882Svi117747 
7072882Svi117747 	*phdr = parsed_header;
7082882Svi117747 	hdr->sip_hdr_parsed = *phdr;
7092882Svi117747 	return (0);
7102882Svi117747 }
7112882Svi117747 
7122882Svi117747 /*
7132882Svi117747  * parser3 parses hdr format
7142882Svi117747  * header_name: <val1>[, <val2>]
7152882Svi117747  * Alert-Info, Call-Info, Error-Info, reply-to
7162882Svi117747  */
7172882Svi117747 int
sip_parse_hdr_parser3(_sip_header_t * hdr,sip_parsed_header_t ** phdr,int type,boolean_t parse_uri)7182882Svi117747 sip_parse_hdr_parser3(_sip_header_t *hdr, sip_parsed_header_t **phdr, int type,
7192882Svi117747     boolean_t parse_uri)
7202882Svi117747 {
7212882Svi117747 	sip_parsed_header_t	*parsed_header;
7222882Svi117747 	sip_hdr_value_t		*value = NULL;
7232882Svi117747 	sip_hdr_value_t		*last_value = NULL;
7242882Svi117747 	int			ret;
7252882Svi117747 
7262882Svi117747 	if ((ret = sip_prim_parsers(hdr, phdr)) != 0)
7272882Svi117747 		return (ret);
7282882Svi117747 
7292882Svi117747 	/*
7302882Svi117747 	 * check if previously parsed
7312882Svi117747 	 */
7322882Svi117747 	if (*phdr != NULL) {
7332882Svi117747 		hdr->sip_hdr_parsed = *phdr;
7342882Svi117747 		return (0);
7352882Svi117747 	}
7362882Svi117747 	parsed_header = calloc(1, sizeof (sip_parsed_header_t));
7372882Svi117747 	if (parsed_header == NULL)
7382882Svi117747 		return (ENOMEM);
7392882Svi117747 	parsed_header->sip_parsed_header_version = SIP_PARSED_HEADER_VERSION_1;
7402882Svi117747 	parsed_header->sip_header = hdr;
7412882Svi117747 	while (hdr->sip_hdr_current < hdr->sip_hdr_end) {
7422882Svi117747 		int		r;
7432882Svi117747 
7442882Svi117747 		value = calloc(1, sizeof (sip_hdr_value_t));
7452882Svi117747 		if (value == NULL) {
7462882Svi117747 			sip_free_phdr(parsed_header);
7472882Svi117747 			return (ENOMEM);
7482882Svi117747 		}
7492882Svi117747 
7502882Svi117747 		if (last_value != NULL)
7512882Svi117747 			last_value->sip_next_value = value;
7522882Svi117747 		else
7532882Svi117747 			parsed_header->value = (sip_value_t *)value;
7542882Svi117747 
7552882Svi117747 		value->sip_value_start = hdr->sip_hdr_current;
7562882Svi117747 		value->sip_value_header = parsed_header;
7572882Svi117747 
7582882Svi117747 		if (type == SIP_STRS_VAL) {
7592882Svi117747 			if (sip_find_token(hdr, SIP_LAQUOT) == 0) {
7602882Svi117747 				char	*cur;
7612882Svi117747 
7622882Svi117747 				/*
7632882Svi117747 				 * record the position after LAQUOT
7642882Svi117747 				 */
7652882Svi117747 				cur = hdr->sip_hdr_current;
7662882Svi117747 				/*
7672882Svi117747 				 * get display name and store in str1
7682882Svi117747 				 */
7692882Svi117747 				hdr->sip_hdr_current = value->sip_value_start;
7702882Svi117747 				if (*(hdr->sip_hdr_current) != SIP_LAQUOT) {
7712882Svi117747 					/*
7722882Svi117747 					 * record start pos of display name
7732882Svi117747 					 */
7742882Svi117747 					char	*tmp = hdr->sip_hdr_current;
7752882Svi117747 
7762882Svi117747 					if (*hdr->sip_hdr_current ==
7772882Svi117747 					    SIP_QUOTE) {
7782882Svi117747 						hdr->sip_hdr_current++;
7792882Svi117747 						tmp++;
7802882Svi117747 						if (sip_find_token(hdr,
7812882Svi117747 						    SIP_QUOTE) != 0) {
7822882Svi117747 							value->sip_value_state =
7832882Svi117747 							    SIP_VALUE_BAD;
7842882Svi117747 							goto get_next_val;
7852882Svi117747 						}
7862882Svi117747 						hdr->sip_hdr_current -= 2;
7872882Svi117747 					} else {
7882882Svi117747 						hdr->sip_hdr_current = cur - 2;
7892882Svi117747 						(void)
7902882Svi117747 						    sip_reverse_skip_white_space
7912882Svi117747 						    (hdr);
7922882Svi117747 					}
7932882Svi117747 					value->strs1_val_ptr = tmp;
7942882Svi117747 					value->strs1_val_len =
7952882Svi117747 					    hdr->sip_hdr_current - tmp + 1;
7962882Svi117747 				} else {
7972882Svi117747 					value->strs1_val_ptr = NULL;
7982882Svi117747 					value->strs1_val_len = 0;
7992882Svi117747 				}
8002882Svi117747 
8012882Svi117747 				/*
8022882Svi117747 				 * set current to the char after LAQUOT
8032882Svi117747 				 */
8042882Svi117747 				hdr->sip_hdr_current = cur;
8052882Svi117747 				value->strs2_val_ptr = hdr->sip_hdr_current;
8062882Svi117747 				if (sip_find_token(hdr, SIP_RAQUOT)) {
8072882Svi117747 					/*
8082882Svi117747 					 * no RAQUOT
8092882Svi117747 					 */
8102882Svi117747 					value->strs1_val_ptr = NULL;
8112882Svi117747 					value->strs1_val_len = 0;
8122882Svi117747 					value->strs2_val_ptr = NULL;
8132882Svi117747 					value->strs2_val_len = 0;
8142882Svi117747 					value->sip_value_state = SIP_VALUE_BAD;
8152882Svi117747 					goto get_next_val;
8162882Svi117747 				}
8172882Svi117747 				value->strs2_val_len = hdr->sip_hdr_current -
8182882Svi117747 				    value->strs2_val_ptr - 1;
8192882Svi117747 			} else {
8202882Svi117747 				char	*cur;
8212882Svi117747 
8222882Svi117747 				/*
8232882Svi117747 				 * No display name - Only URI.
8242882Svi117747 				 */
8252882Svi117747 				value->strs1_val_ptr = NULL;
8262882Svi117747 				value->strs1_val_len = 0;
8272882Svi117747 				cur = value->sip_value_start;
8282882Svi117747 				hdr->sip_hdr_current = cur;
8292882Svi117747 				if (sip_find_separator(hdr, SIP_COMMA,
830*5092Sgm209912 				    (char)NULL, (char)NULL, B_FALSE) != 0) {
8312882Svi117747 					value->strs2_val_ptr = cur;
8322882Svi117747 					value->strs2_val_len =
8332882Svi117747 					    hdr->sip_hdr_current -
8342882Svi117747 					    value->strs2_val_ptr - 1;
8352882Svi117747 				} else if (*hdr->sip_hdr_current == SIP_SP) {
8362882Svi117747 					value->strs2_val_ptr = cur;
8372882Svi117747 					cur = hdr->sip_hdr_current - 1;
8382882Svi117747 					if (sip_skip_white_space(hdr) != 0) {
8392882Svi117747 						value->strs2_val_len = cur -
8402882Svi117747 						    value->strs2_val_ptr - 1;
8412882Svi117747 					} else if (*hdr->sip_hdr_current ==
8422882Svi117747 					    SIP_COMMA) {
8432882Svi117747 						value->strs2_val_len = cur -
8442882Svi117747 						    value->strs2_val_ptr - 1;
8452882Svi117747 					} else {
8462882Svi117747 						value->sip_value_state =
8472882Svi117747 						    SIP_VALUE_BAD;
8482882Svi117747 						goto get_next_val;
8492882Svi117747 					}
8502882Svi117747 				} else {
8512882Svi117747 					value->strs2_val_ptr = cur;
8522882Svi117747 					value->strs2_val_len =
8532882Svi117747 					    hdr->sip_hdr_current -
8542882Svi117747 					    value->strs2_val_ptr;
8552882Svi117747 				}
8562882Svi117747 			}
8572882Svi117747 			if (parse_uri)
8582882Svi117747 				sip_parse_uri_str(&value->strs_s2, value);
8592882Svi117747 		}
8602882Svi117747 
8612882Svi117747 		if (type == SIP_STR_VAL) {
8622882Svi117747 			/*
8632882Svi117747 			 * alert-info, error-info, call-info
8642882Svi117747 			 */
8652882Svi117747 			if (sip_find_token(hdr, SIP_LAQUOT) == 0) {
8662882Svi117747 				value->str_val_ptr = hdr->sip_hdr_current;
8672882Svi117747 				if (sip_find_token(hdr, SIP_RAQUOT) == 0) {
8682882Svi117747 					value->str_val_len =
8692882Svi117747 					    hdr->sip_hdr_current -
870*5092Sgm209912 					    value->str_val_ptr - 1;
8712882Svi117747 				} else {
8722882Svi117747 					value->str_val_ptr = NULL;
8732882Svi117747 					value->str_val_len = 0;
8742882Svi117747 					value->sip_value_state = SIP_VALUE_BAD;
8752882Svi117747 					goto get_next_val;
8762882Svi117747 				}
8772882Svi117747 				hdr->sip_hdr_current--;
8782882Svi117747 			} else {
8792882Svi117747 				value->str_val_ptr = NULL;
8802882Svi117747 				value->str_val_len = 0;
8812882Svi117747 				value->sip_value_state = SIP_VALUE_BAD;
8822882Svi117747 				goto get_next_val;
8832882Svi117747 			}
8842882Svi117747 			if (parse_uri)
8852882Svi117747 				sip_parse_uri_str(&value->str_val, value);
8862882Svi117747 		}
8872882Svi117747 
888*5092Sgm209912 		r = sip_find_separator(hdr, SIP_COMMA, SIP_SEMI, (char)NULL,
889*5092Sgm209912 		    B_FALSE);
8902882Svi117747 		if (r != 0) {
8912882Svi117747 			value->sip_value_end = hdr->sip_hdr_current;
8922882Svi117747 			goto end;
8932882Svi117747 		}
8942882Svi117747 		if (*hdr->sip_hdr_current == SIP_SEMI) {
8952882Svi117747 			(void) sip_parse_params(hdr,
8962882Svi117747 			    &(value->sip_param_list));
8972882Svi117747 			goto get_next_val;
8982882Svi117747 		}
8992882Svi117747 
9002882Svi117747 		if (*hdr->sip_hdr_current == SIP_COMMA) {
9012882Svi117747 			hdr->sip_hdr_current--;
9022882Svi117747 			goto get_next_val;
9032882Svi117747 		}
9042882Svi117747 get_next_val:
9052882Svi117747 		if (sip_find_token(hdr, SIP_COMMA) != 0) {
9062882Svi117747 			value->sip_value_end = hdr->sip_hdr_current;
9072882Svi117747 			break;
9082882Svi117747 		}
9092882Svi117747 		value->sip_value_end = hdr->sip_hdr_current - 1;
9102882Svi117747 		last_value = value;
9112882Svi117747 		(void) sip_skip_white_space(hdr);
9122882Svi117747 	}
9132882Svi117747 
9142882Svi117747 end:
9152882Svi117747 	*phdr = parsed_header;
9162882Svi117747 	hdr->sip_hdr_parsed = *phdr;
9172882Svi117747 	return (0);
9182882Svi117747 }
9192882Svi117747 
9202882Svi117747 /*
9212882Svi117747  * parser4 parses hdr format, the whole field is one single str
9222882Svi117747  * header: Subject, MIME-Version, Organization, Server, User-Agent
9232882Svi117747  */
9242882Svi117747 int
sip_parse_hdr_parser4(_sip_header_t * hdr,sip_parsed_header_t ** phdr)9252882Svi117747 sip_parse_hdr_parser4(_sip_header_t *hdr, sip_parsed_header_t **phdr)
9262882Svi117747 {
9272882Svi117747 	sip_parsed_header_t	*parsed_header;
9282882Svi117747 	sip_hdr_value_t		*value = NULL;
9292882Svi117747 	int			ret;
9302882Svi117747 
9312882Svi117747 	if ((ret = sip_prim_parsers(hdr, phdr)) != 0)
9322882Svi117747 		return (ret);
9332882Svi117747 
9342882Svi117747 	/*
9352882Svi117747 	 * check if previously parsed
9362882Svi117747 	 */
9372882Svi117747 	if (*phdr != NULL) {
9382882Svi117747 		hdr->sip_hdr_parsed = *phdr;
9392882Svi117747 		return (0);
9402882Svi117747 	}
9412882Svi117747 	parsed_header = calloc(1, sizeof (sip_parsed_header_t));
9422882Svi117747 	if (parsed_header == NULL)
9432882Svi117747 		return (ENOMEM);
9442882Svi117747 	parsed_header->sip_parsed_header_version = SIP_PARSED_HEADER_VERSION_1;
9452882Svi117747 	parsed_header->sip_header = hdr;
9462882Svi117747 
9472882Svi117747 	value = calloc(1, sizeof (sip_hdr_value_t));
9482882Svi117747 	if (value == NULL) {
9492882Svi117747 		sip_free_phdr(parsed_header);
9502882Svi117747 		return (ENOMEM);
9512882Svi117747 	}
9522882Svi117747 
9532882Svi117747 	parsed_header->value = (sip_value_t *)value;
9542882Svi117747 
9552882Svi117747 	value->sip_value_start = hdr->sip_hdr_current;
9562882Svi117747 	value->sip_value_header = parsed_header;
9572882Svi117747 
9582882Svi117747 	value->str_val_ptr = hdr->sip_hdr_current;
9592882Svi117747 	/*
9602882Svi117747 	 * get rid of CRLF at end
9612882Svi117747 	 */
9622882Svi117747 	value->str_val_len = hdr->sip_hdr_end - value->str_val_ptr - 2;
9632882Svi117747 	value->sip_value_end = hdr->sip_hdr_end;
9642882Svi117747 
9652882Svi117747 	*phdr = parsed_header;
9662882Svi117747 	hdr->sip_hdr_parsed = *phdr;
9672882Svi117747 	return (0);
9682882Svi117747 }
9692882Svi117747 
9702882Svi117747 int
sip_parse_hdr_parser5(_sip_header_t * hdr,sip_parsed_header_t ** phdr,boolean_t parse_uri)9712882Svi117747 sip_parse_hdr_parser5(_sip_header_t *hdr, sip_parsed_header_t **phdr,
9722882Svi117747     boolean_t parse_uri)
9732882Svi117747 {
9742882Svi117747 	sip_parsed_header_t	*parsed_header;
9752882Svi117747 	sip_hdr_value_t		*value = NULL;
9762882Svi117747 	sip_param_t		*tmp_param;
9772882Svi117747 	boolean_t		first_param = B_TRUE;
9782882Svi117747 	int			ret;
9792882Svi117747 
9802882Svi117747 	if ((ret = sip_prim_parsers(hdr, phdr)) != 0)
9812882Svi117747 		return (ret);
9822882Svi117747 
9832882Svi117747 	/*
9842882Svi117747 	 * check if previously parsed
9852882Svi117747 	 */
9862882Svi117747 	if (*phdr != NULL) {
9872882Svi117747 		hdr->sip_hdr_parsed = *phdr;
9882882Svi117747 		return (0);
9892882Svi117747 	}
9902882Svi117747 	parsed_header = calloc(1, sizeof (sip_parsed_header_t));
9912882Svi117747 	if (parsed_header == NULL)
9922882Svi117747 		return (ENOMEM);
9932882Svi117747 	parsed_header->sip_parsed_header_version = SIP_PARSED_HEADER_VERSION_1;
9942882Svi117747 	parsed_header->sip_header = hdr;
9952882Svi117747 
9962882Svi117747 	value = calloc(1, sizeof (sip_hdr_value_t));
9972882Svi117747 	if (value == NULL) {
9982882Svi117747 		sip_free_phdr(parsed_header);
9992882Svi117747 		return (ENOMEM);
10002882Svi117747 	}
10012882Svi117747 
10022882Svi117747 	parsed_header->value = (sip_value_t *)value;
10032882Svi117747 
10042882Svi117747 	value->sip_value_start = hdr->sip_hdr_current;
10052882Svi117747 	value->auth_scheme_ptr = value->sip_value_start;
10062882Svi117747 	value->sip_value_header = parsed_header;
10072882Svi117747 	/*
10082882Svi117747 	 * get auth_scheme
10092882Svi117747 	 */
10102882Svi117747 	if (sip_find_white_space(hdr)) {
10112882Svi117747 		value->sip_value_state = SIP_VALUE_BAD;
10122882Svi117747 		return (EINVAL);
10132882Svi117747 	}
10142882Svi117747 	value->auth_scheme_len = hdr->sip_hdr_current - value->auth_scheme_ptr;
10152882Svi117747 
10162882Svi117747 	tmp_param = value->auth_param;
10172882Svi117747 
10182882Svi117747 	/*
10192882Svi117747 	 * parse auth_param
10202882Svi117747 	 */
10212882Svi117747 	for (;;) {
10222882Svi117747 		char		*tmp_cur;
10232882Svi117747 		boolean_t	quoted_name = B_FALSE;
10242882Svi117747 		char		quoted_char = (char)0;
10252882Svi117747 		sip_param_t	*new_param;
10262882Svi117747 		boolean_t	pval_is_uri = B_FALSE;
10272882Svi117747 
10282882Svi117747 		if (sip_skip_white_space(hdr) != 0) {
10292882Svi117747 			value->sip_value_state = SIP_VALUE_BAD;
10302882Svi117747 			return (EPROTO);
10312882Svi117747 		}
10322882Svi117747 		tmp_cur = hdr->sip_hdr_current;
10332882Svi117747 
10342882Svi117747 		new_param = calloc(1, sizeof (sip_param_t));
10352882Svi117747 		if (new_param == NULL)
10362882Svi117747 			return (ENOMEM);
10372882Svi117747 
10382882Svi117747 		if (first_param == B_FALSE)
10392882Svi117747 			tmp_param->param_next = new_param;
10402882Svi117747 		else
10412882Svi117747 			value->auth_param = new_param;
10422882Svi117747 
10432882Svi117747 		tmp_param = new_param;
10442882Svi117747 		tmp_param->param_name.sip_str_ptr = tmp_cur;
10452882Svi117747 
1046*5092Sgm209912 		if (sip_find_separator(hdr, SIP_EQUAL, SIP_COMMA, (char)NULL,
1047*5092Sgm209912 		    B_FALSE) != 0) {
10482882Svi117747 			tmp_param->param_name.sip_str_len =
10492882Svi117747 			    hdr->sip_hdr_current - tmp_cur;
10502882Svi117747 			tmp_param->param_value.sip_str_ptr = NULL;
10512882Svi117747 			tmp_param->param_value.sip_str_len = 0;
10522882Svi117747 			value->sip_value_end = hdr->sip_hdr_current;
10532882Svi117747 			goto end;
10542882Svi117747 		}
10552882Svi117747 
10562882Svi117747 		/*
10572882Svi117747 		 * End of param name
10582882Svi117747 		 */
10592882Svi117747 		tmp_param->param_name.sip_str_len = hdr->sip_hdr_current -
10602882Svi117747 		    tmp_cur;
10612882Svi117747 
10622882Svi117747 		if (sip_skip_white_space(hdr) != 0 ||
10632882Svi117747 		    *hdr->sip_hdr_current == SIP_COMMA) {
10642882Svi117747 			tmp_param->param_value.sip_str_ptr = NULL;
10652882Svi117747 			tmp_param->param_value.sip_str_len = 0;
10662882Svi117747 			continue;
10672882Svi117747 		}
10682882Svi117747 
10692882Svi117747 		/*
10702882Svi117747 		 * We are at EQUAL
10712882Svi117747 		 */
10722882Svi117747 		hdr->sip_hdr_current++;
10732882Svi117747 
10742882Svi117747 		if (sip_skip_white_space(hdr) != 0) {
10752882Svi117747 			value->sip_value_state = SIP_VALUE_BAD;
10762882Svi117747 			free(tmp_param);
10772882Svi117747 			return (EPROTO);
10782882Svi117747 		}
10792882Svi117747 
10802882Svi117747 		if (*hdr->sip_hdr_current == SIP_QUOTE ||
10812882Svi117747 		    *hdr->sip_hdr_current == SIP_LAQUOT) {
10822882Svi117747 			if (*hdr->sip_hdr_current == SIP_QUOTE)
10832882Svi117747 				quoted_char = SIP_QUOTE;
10842882Svi117747 			else {
10852882Svi117747 				quoted_char = SIP_RAQUOT;
10862882Svi117747 				pval_is_uri = B_TRUE;
10872882Svi117747 			}
10882882Svi117747 			hdr->sip_hdr_current++;
10892882Svi117747 			quoted_name = B_TRUE;
10902882Svi117747 		}
10912882Svi117747 
10922882Svi117747 		/*
10932882Svi117747 		 * start of param value
10942882Svi117747 		 */
10952882Svi117747 		tmp_cur = hdr->sip_hdr_current;
10962882Svi117747 		tmp_param->param_value.sip_str_ptr = tmp_cur;
10972882Svi117747 		if (quoted_name) {
10982882Svi117747 			if (sip_find_token(hdr, quoted_char) != 0) {
10992882Svi117747 				value->sip_value_state = SIP_VALUE_BAD;
11002882Svi117747 				free(tmp_param);
11012882Svi117747 				return (EPROTO);
11022882Svi117747 			}
11032882Svi117747 			tmp_param->param_value.sip_str_len =
11042882Svi117747 			    hdr->sip_hdr_current - tmp_cur - 1;
11052882Svi117747 		}
11062882Svi117747 
11072882Svi117747 		if (sip_find_token(hdr, SIP_COMMA) != 0) {
11082882Svi117747 			value->sip_value_end = hdr->sip_hdr_current;
11092882Svi117747 			goto end;
11102882Svi117747 		} else {
11112882Svi117747 			if (!quoted_name) {
11122882Svi117747 				char *t = hdr->sip_hdr_current;
11132882Svi117747 				hdr->sip_hdr_current--;
11142882Svi117747 				(void) sip_reverse_skip_white_space(hdr);
11152882Svi117747 				tmp_param->param_value.sip_str_len =
11162882Svi117747 				    hdr->sip_hdr_current - tmp_cur;
11172882Svi117747 				hdr->sip_hdr_current = t;
11182882Svi117747 			}
11192882Svi117747 		}
11202882Svi117747 
11212882Svi117747 		if (first_param == B_TRUE)
11222882Svi117747 			first_param = B_FALSE;
11232882Svi117747 
11242882Svi117747 		/*
11252882Svi117747 		 * Parse uri
11262882Svi117747 		 */
11272882Svi117747 		if (pval_is_uri && parse_uri)
11282882Svi117747 			sip_parse_uri_str(&tmp_param->param_value, value);
11292882Svi117747 
11302882Svi117747 	}
11312882Svi117747 
11322882Svi117747 end:
11332882Svi117747 	*phdr = parsed_header;
11342882Svi117747 	hdr->sip_hdr_parsed = *phdr;
11352882Svi117747 	return (0);
11362882Svi117747 }
11372882Svi117747 
11382882Svi117747 /*
11392882Svi117747  * Return the URI in the request startline
11402882Svi117747  */
11412882Svi117747 static int
_sip_get_request_uri(_sip_header_t * sip_header,sip_message_type_t * msg_info)11422882Svi117747 _sip_get_request_uri(_sip_header_t *sip_header, sip_message_type_t *msg_info)
11432882Svi117747 {
11442882Svi117747 	int	size = 0;
11452882Svi117747 	char	*start_ptr;
11462882Svi117747 
11472882Svi117747 	if (sip_skip_white_space(sip_header) != 0)
11482882Svi117747 		return (EINVAL);
11492882Svi117747 	start_ptr = sip_header->sip_hdr_current;
11502882Svi117747 
11512882Svi117747 	while (!isspace(*sip_header->sip_hdr_current)) {
11522882Svi117747 		if (sip_header->sip_hdr_current >= sip_header->sip_hdr_end)
11532882Svi117747 			return (EINVAL);
11542882Svi117747 		sip_header->sip_hdr_current++;
11552882Svi117747 	}
11562882Svi117747 
11572882Svi117747 	size = sip_header->sip_hdr_current - start_ptr;
11582882Svi117747 
11592882Svi117747 	msg_info->U.sip_request.sip_request_uri.sip_str_ptr = start_ptr;
11602882Svi117747 	msg_info->U.sip_request.sip_request_uri.sip_str_len = size;
11612882Svi117747 	if (size > 0) {	/* Parse uri */
11622882Svi117747 		int		error;
11632882Svi117747 
11642882Svi117747 		msg_info->U.sip_request.sip_parse_uri = sip_parse_uri(
11652882Svi117747 		    &msg_info->U.sip_request.sip_request_uri, &error);
11662882Svi117747 		if (msg_info->U.sip_request.sip_parse_uri == NULL)
11672882Svi117747 			return (error);
11682882Svi117747 	}
11692882Svi117747 	return (0);
11702882Svi117747 }
11712882Svi117747 
11722882Svi117747 /*
11732882Svi117747  * Parse the start line into request/response
11742882Svi117747  */
11752882Svi117747 int
sip_parse_first_line(_sip_header_t * sip_header,sip_message_type_t ** msg_info)11762882Svi117747 sip_parse_first_line(_sip_header_t *sip_header, sip_message_type_t **msg_info)
11772882Svi117747 {
11782882Svi117747 	sip_message_type_t	*sip_msg_info;
11792882Svi117747 	boolean_t		sip_is_request = B_TRUE;
11802882Svi117747 	int			ret;
11812882Svi117747 
11822882Svi117747 	if (sip_header == NULL || msg_info == NULL)
11832882Svi117747 		return (EINVAL);
11842882Svi117747 
11852882Svi117747 	if (sip_skip_white_space(sip_header) != 0)
11862882Svi117747 		return (EPROTO);
11872882Svi117747 
11882882Svi117747 	/*
11892882Svi117747 	 * There is nothing, return
11902882Svi117747 	 */
11912882Svi117747 	if (sip_header->sip_hdr_current + strlen(SIP_VERSION) >=
11922882Svi117747 	    sip_header->sip_hdr_end) {
11932882Svi117747 		return (EPROTO);
11942882Svi117747 	}
11952882Svi117747 #ifdef	__solaris__
11962882Svi117747 	assert(mutex_held(&sip_header->sip_hdr_sipmsg->sip_msg_mutex));
11972882Svi117747 #endif
11982882Svi117747 	sip_msg_info = malloc(sizeof (sip_message_type_t));
11992882Svi117747 	if (sip_msg_info == NULL)
12002882Svi117747 		return (ENOMEM);
12012882Svi117747 
12022882Svi117747 	/*
12032882Svi117747 	 * let's see if it's a request or a response
12042882Svi117747 	 */
12052882Svi117747 	ret = sip_get_protocol_version(sip_header,
12062882Svi117747 	    &sip_msg_info->sip_proto_version);
12072882Svi117747 	if (ret == 0) {
12082882Svi117747 		sip_is_request = B_FALSE;
12092882Svi117747 	} else if (ret == 2) {
12102882Svi117747 		free(sip_msg_info);
12112882Svi117747 		return (EPROTO);
12122882Svi117747 	}
12132882Svi117747 
12142882Svi117747 	if (sip_skip_white_space(sip_header) != 0) {
12152882Svi117747 		free(sip_msg_info);
12162882Svi117747 		return (EPROTO);
12172882Svi117747 	}
12182882Svi117747 
12192882Svi117747 	if (!sip_is_request) {
12202882Svi117747 		/*
12212882Svi117747 		 * check for status code.
12222882Svi117747 		 */
12232882Svi117747 		if (sip_skip_white_space(sip_header) != 0) {
12242882Svi117747 			free(sip_msg_info);
12252882Svi117747 			return (EPROTO);
12262882Svi117747 		}
12272882Svi117747 		if (sip_header->sip_hdr_current + SIP_SIZE_OF_STATUS_CODE >=
12282882Svi117747 		    sip_header->sip_hdr_end) {
12292882Svi117747 			free(sip_msg_info);
12302882Svi117747 			return (EPROTO);
12312882Svi117747 		}
12322882Svi117747 
12332882Svi117747 		if (sip_atoi(sip_header,
12342882Svi117747 		    &sip_msg_info->U.sip_response.sip_response_code)) {
12352882Svi117747 			free(sip_msg_info);
12362882Svi117747 			return (EPROTO);
12372882Svi117747 		}
12382882Svi117747 
12392882Svi117747 		if (sip_msg_info->U.sip_response.sip_response_code < 100 ||
12402882Svi117747 		    sip_msg_info->U.sip_response.sip_response_code > 700) {
12412882Svi117747 			free(sip_msg_info);
12422882Svi117747 			return (EPROTO);
12432882Svi117747 		}
12442882Svi117747 
12452882Svi117747 		/*
12462882Svi117747 		 * get reason phrase.
12472882Svi117747 		 */
12482882Svi117747 		if (sip_skip_white_space(sip_header) != 0) {
12492882Svi117747 			sip_msg_info->sip_resp_phrase_len = 0;
12502882Svi117747 			sip_msg_info->sip_resp_phrase_ptr = NULL;
12512882Svi117747 		} else {
12522882Svi117747 			sip_msg_info->sip_resp_phrase_ptr =
12532882Svi117747 			    sip_header->sip_hdr_current;
12542882Svi117747 			if (sip_find_cr(sip_header) != 0) {
12552882Svi117747 				free(sip_msg_info);
12562882Svi117747 				return (EPROTO);
12572882Svi117747 			}
12582882Svi117747 			sip_msg_info->sip_resp_phrase_len =
12592882Svi117747 			    sip_header->sip_hdr_current -
12602882Svi117747 			    sip_msg_info->sip_resp_phrase_ptr;
12612882Svi117747 		}
12622882Svi117747 		sip_msg_info->is_request = B_FALSE;
12632882Svi117747 	} else {
12642882Svi117747 		int i;
12652882Svi117747 		/*
12662882Svi117747 		 * It's a request.
12672882Svi117747 		 */
12682882Svi117747 		sip_msg_info->is_request = B_TRUE;
12692882Svi117747 		for (i = 1; i < MAX_SIP_METHODS; i++) {
12702882Svi117747 			if (strncmp(sip_methods[i].name,
12712882Svi117747 			    sip_header->sip_hdr_current,
12722882Svi117747 			    sip_methods[i].len) == 0) {
12732882Svi117747 				sip_msg_info->sip_req_method = i;
12742882Svi117747 				sip_header->sip_hdr_current +=
12752882Svi117747 				    sip_methods[i].len;
12762882Svi117747 				if (!isspace(*sip_header->sip_hdr_current++) ||
12772882Svi117747 				    !isalpha(*sip_header->sip_hdr_current)) {
12782882Svi117747 					free(sip_msg_info);
12792882Svi117747 					return (EPROTO);
12802882Svi117747 				}
12812882Svi117747 
12822882Svi117747 				if ((ret = _sip_get_request_uri(sip_header,
12832882Svi117747 				    sip_msg_info)) != 0) {
12842882Svi117747 					free(sip_msg_info);
12852882Svi117747 					return (ret);
12862882Svi117747 				}
12872882Svi117747 
12882882Svi117747 				/*
12892882Svi117747 				 * Get SIP version
12902882Svi117747 				 */
12912882Svi117747 				ret = sip_get_protocol_version(sip_header,
12922882Svi117747 				    &sip_msg_info->sip_proto_version);
12932882Svi117747 				if (ret != 0) {
12942882Svi117747 					free(sip_msg_info);
12952882Svi117747 					return (EPROTO);
12962882Svi117747 				}
12972882Svi117747 				goto done;
12982882Svi117747 			}
12992882Svi117747 		}
13002882Svi117747 		free(sip_msg_info);
13012882Svi117747 		return (EPROTO);
13022882Svi117747 	}
13032882Svi117747 done:
13042882Svi117747 	sip_msg_info->sip_next = *msg_info;
13052882Svi117747 	*msg_info = sip_msg_info;
13062882Svi117747 	return (0);
13072882Svi117747 }
1308