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