xref: /titanic_51/usr/src/lib/libsip/common/sip_parse_generic.c (revision df4705eab9c873eae60bada4f2138e6f22a76e11)
140cb5e5dSvi117747 /*
240cb5e5dSvi117747  * CDDL HEADER START
340cb5e5dSvi117747  *
440cb5e5dSvi117747  * The contents of this file are subject to the terms of the
540cb5e5dSvi117747  * Common Development and Distribution License (the "License").
640cb5e5dSvi117747  * You may not use this file except in compliance with the License.
740cb5e5dSvi117747  *
840cb5e5dSvi117747  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
940cb5e5dSvi117747  * or http://www.opensolaris.org/os/licensing.
1040cb5e5dSvi117747  * See the License for the specific language governing permissions
1140cb5e5dSvi117747  * and limitations under the License.
1240cb5e5dSvi117747  *
1340cb5e5dSvi117747  * When distributing Covered Code, include this CDDL HEADER in each
1440cb5e5dSvi117747  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1540cb5e5dSvi117747  * If applicable, add the following below this CDDL HEADER, with the
1640cb5e5dSvi117747  * fields enclosed by brackets "[]" replaced with your own identifying
1740cb5e5dSvi117747  * information: Portions Copyright [yyyy] [name of copyright owner]
1840cb5e5dSvi117747  *
1940cb5e5dSvi117747  * CDDL HEADER END
2040cb5e5dSvi117747  */
2140cb5e5dSvi117747 
2240cb5e5dSvi117747 /*
232c2c4183Svi117747  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
2440cb5e5dSvi117747  * Use is subject to license terms.
2540cb5e5dSvi117747  */
2640cb5e5dSvi117747 
2740cb5e5dSvi117747 #pragma ident	"%Z%%M%	%I%	%E% SMI"
2840cb5e5dSvi117747 
292c2c4183Svi117747 #include <stdlib.h>
302c2c4183Svi117747 #include <assert.h>
312c2c4183Svi117747 #include <errno.h>
322c2c4183Svi117747 #include <strings.h>
332c2c4183Svi117747 #include <ctype.h>
342c2c4183Svi117747 #include <sip.h>
352c2c4183Svi117747 
3640cb5e5dSvi117747 #include "sip_miscdefs.h"
372c2c4183Svi117747 #include "sip_msg.h"
382c2c4183Svi117747 #include "sip_parse_uri.h"
3940cb5e5dSvi117747 
4040cb5e5dSvi117747 /*
4140cb5e5dSvi117747  * atoi function from a header
4240cb5e5dSvi117747  */
4340cb5e5dSvi117747 int
4440cb5e5dSvi117747 sip_atoi(_sip_header_t *sip_header, int *num)
4540cb5e5dSvi117747 {
4640cb5e5dSvi117747 	boolean_t	num_found = B_FALSE;
4740cb5e5dSvi117747 
4840cb5e5dSvi117747 	*num = 0;
4940cb5e5dSvi117747 	while (sip_header->sip_hdr_current < sip_header->sip_hdr_end) {
5040cb5e5dSvi117747 		if (isspace(*sip_header->sip_hdr_current)) {
5140cb5e5dSvi117747 			sip_header->sip_hdr_current++;
5240cb5e5dSvi117747 			if (num_found)
5340cb5e5dSvi117747 				break;
5440cb5e5dSvi117747 		} else if (isdigit(*sip_header->sip_hdr_current)) {
5540cb5e5dSvi117747 			*num = (*num * 10) +
5640cb5e5dSvi117747 			    (*sip_header->sip_hdr_current - '0');
5740cb5e5dSvi117747 			num_found = B_TRUE;
5840cb5e5dSvi117747 			sip_header->sip_hdr_current++;
5940cb5e5dSvi117747 		} else {
6040cb5e5dSvi117747 			break;
6140cb5e5dSvi117747 		}
6240cb5e5dSvi117747 	}
6340cb5e5dSvi117747 	if (!num_found)
6440cb5e5dSvi117747 		return (EINVAL);
6540cb5e5dSvi117747 	return (0);
6640cb5e5dSvi117747 }
6740cb5e5dSvi117747 
6840cb5e5dSvi117747 /*
6940cb5e5dSvi117747  * Find the 'token'
7040cb5e5dSvi117747  */
7140cb5e5dSvi117747 int
7240cb5e5dSvi117747 sip_find_token(_sip_header_t *sip_header, char token)
7340cb5e5dSvi117747 {
7440cb5e5dSvi117747 	while (sip_header->sip_hdr_current < sip_header->sip_hdr_end) {
7540cb5e5dSvi117747 		if (token != SIP_COMMA &&
7640cb5e5dSvi117747 		    *sip_header->sip_hdr_current == SIP_COMMA) {
7740cb5e5dSvi117747 			sip_header->sip_hdr_current--;
7840cb5e5dSvi117747 			return (1);
7940cb5e5dSvi117747 		}
8040cb5e5dSvi117747 		if (*sip_header->sip_hdr_current++ == token) {
8140cb5e5dSvi117747 			/*
8240cb5e5dSvi117747 			 * sip_hdr_current points to the char
8340cb5e5dSvi117747 			 * after the token
8440cb5e5dSvi117747 			 */
8540cb5e5dSvi117747 			return (0);
8640cb5e5dSvi117747 		}
8740cb5e5dSvi117747 	}
8840cb5e5dSvi117747 	return (1);
8940cb5e5dSvi117747 }
9040cb5e5dSvi117747 
9140cb5e5dSvi117747 /*
9240cb5e5dSvi117747  * Find a carriage-return
9340cb5e5dSvi117747  */
9440cb5e5dSvi117747 int
9540cb5e5dSvi117747 sip_find_cr(_sip_header_t *sip_header)
9640cb5e5dSvi117747 {
9740cb5e5dSvi117747 	sip_header->sip_hdr_current = sip_header->sip_hdr_end;
9840cb5e5dSvi117747 	while (*sip_header->sip_hdr_current-- != '\n') {
9940cb5e5dSvi117747 		if (sip_header->sip_hdr_current == sip_header->sip_hdr_start)
10040cb5e5dSvi117747 			return (1);
10140cb5e5dSvi117747 	}
10240cb5e5dSvi117747 	return (0);
10340cb5e5dSvi117747 }
10440cb5e5dSvi117747 
10540cb5e5dSvi117747 /*
10640cb5e5dSvi117747  * Find one of the separator provided, i.e. separator_1st or separator_2nd or
10740cb5e5dSvi117747  * separator_3rd.
10840cb5e5dSvi117747  */
10940cb5e5dSvi117747 int
11040cb5e5dSvi117747 sip_find_separator(_sip_header_t *sip_header, char separator_1st,
111*df4705eaSgm209912     char separator_2nd, char separator_3rd, boolean_t ignore_space)
11240cb5e5dSvi117747 {
11340cb5e5dSvi117747 	assert(separator_1st != (char)NULL || separator_2nd != (char)NULL);
11440cb5e5dSvi117747 	while (sip_header->sip_hdr_current < sip_header->sip_hdr_end) {
115*df4705eaSgm209912 		if (ignore_space && (*sip_header->sip_hdr_current == SIP_SP)) {
116*df4705eaSgm209912 			sip_header->sip_hdr_current++;
117*df4705eaSgm209912 			continue;
118*df4705eaSgm209912 		}
11940cb5e5dSvi117747 		if (isspace(*sip_header->sip_hdr_current) ||
12040cb5e5dSvi117747 		    (separator_1st != (char)NULL &&
12140cb5e5dSvi117747 		    (*sip_header->sip_hdr_current == separator_1st)) ||
12240cb5e5dSvi117747 		    (separator_2nd != (char)NULL &&
12340cb5e5dSvi117747 		    (*sip_header->sip_hdr_current == separator_2nd)) ||
12440cb5e5dSvi117747 		    (separator_3rd != (char)NULL &&
12540cb5e5dSvi117747 		    (*sip_header->sip_hdr_current == separator_3rd))) {
12640cb5e5dSvi117747 			return (0);
12740cb5e5dSvi117747 		}
12840cb5e5dSvi117747 		/*
12940cb5e5dSvi117747 		 * If we have escape character, go to the next char
13040cb5e5dSvi117747 		 */
13140cb5e5dSvi117747 		if (*sip_header->sip_hdr_current == '\\')
13240cb5e5dSvi117747 			sip_header->sip_hdr_current++;
13340cb5e5dSvi117747 		sip_header->sip_hdr_current++;
13440cb5e5dSvi117747 	}
13540cb5e5dSvi117747 	return (1);
13640cb5e5dSvi117747 }
13740cb5e5dSvi117747 
13840cb5e5dSvi117747 /*
13940cb5e5dSvi117747  * Return when we hit a white space
14040cb5e5dSvi117747  */
14140cb5e5dSvi117747 int
14240cb5e5dSvi117747 sip_find_white_space(_sip_header_t *sip_header)
14340cb5e5dSvi117747 {
14440cb5e5dSvi117747 	while (sip_header->sip_hdr_current < sip_header->sip_hdr_end) {
14540cb5e5dSvi117747 		if (isspace(*sip_header->sip_hdr_current))
14640cb5e5dSvi117747 			return (0);
14740cb5e5dSvi117747 		sip_header->sip_hdr_current++;
14840cb5e5dSvi117747 	}
14940cb5e5dSvi117747 	return (1);
15040cb5e5dSvi117747 }
15140cb5e5dSvi117747 
15240cb5e5dSvi117747 /*
15340cb5e5dSvi117747  * Skip to the next non-whitespace
15440cb5e5dSvi117747  */
15540cb5e5dSvi117747 int
15640cb5e5dSvi117747 sip_skip_white_space(_sip_header_t *sip_header)
15740cb5e5dSvi117747 {
15840cb5e5dSvi117747 	while (sip_header->sip_hdr_current < sip_header->sip_hdr_end) {
15940cb5e5dSvi117747 		if (!isspace(*sip_header->sip_hdr_current))
16040cb5e5dSvi117747 			return (0);
16140cb5e5dSvi117747 		sip_header->sip_hdr_current++;
16240cb5e5dSvi117747 	}
16340cb5e5dSvi117747 	return (1);
16440cb5e5dSvi117747 }
16540cb5e5dSvi117747 
16640cb5e5dSvi117747 
16740cb5e5dSvi117747 /*
16840cb5e5dSvi117747  * Skip to the non-white space in the reverse direction
16940cb5e5dSvi117747  */
17040cb5e5dSvi117747 int
17140cb5e5dSvi117747 sip_reverse_skip_white_space(_sip_header_t *sip_header)
17240cb5e5dSvi117747 {
17340cb5e5dSvi117747 	while (sip_header->sip_hdr_current >= sip_header->sip_hdr_start) {
17440cb5e5dSvi117747 		if (!isspace(*sip_header->sip_hdr_current))
17540cb5e5dSvi117747 			return (0);
17640cb5e5dSvi117747 		sip_header->sip_hdr_current--;
17740cb5e5dSvi117747 	}
17840cb5e5dSvi117747 	return (1);
17940cb5e5dSvi117747 }
18040cb5e5dSvi117747 
18140cb5e5dSvi117747 /*
18240cb5e5dSvi117747  * get to the first non space after ':'
18340cb5e5dSvi117747  */
18440cb5e5dSvi117747 int
18540cb5e5dSvi117747 sip_parse_goto_values(_sip_header_t *sip_header)
18640cb5e5dSvi117747 {
18740cb5e5dSvi117747 	if (sip_find_token(sip_header, SIP_HCOLON) !=  0)
18840cb5e5dSvi117747 		return (1);
18940cb5e5dSvi117747 	if (sip_skip_white_space(sip_header) != 0)
19040cb5e5dSvi117747 		return (1);
19140cb5e5dSvi117747 
19240cb5e5dSvi117747 	return (0);
19340cb5e5dSvi117747 }
19440cb5e5dSvi117747 
19540cb5e5dSvi117747 /*
19640cb5e5dSvi117747  * Skip the current value.
19740cb5e5dSvi117747  */
19840cb5e5dSvi117747 int
19940cb5e5dSvi117747 sip_goto_next_value(_sip_header_t *sip_header)
20040cb5e5dSvi117747 {
20140cb5e5dSvi117747 	boolean_t	quoted = B_FALSE;
20240cb5e5dSvi117747 
20340cb5e5dSvi117747 	while (sip_header->sip_hdr_current < sip_header->sip_hdr_end) {
20440cb5e5dSvi117747 		if (*sip_header->sip_hdr_current == SIP_QUOTE) {
20540cb5e5dSvi117747 			if (quoted)
20640cb5e5dSvi117747 				quoted = B_FALSE;
20740cb5e5dSvi117747 			else
20840cb5e5dSvi117747 				quoted = B_TRUE;
20940cb5e5dSvi117747 		} else if (!quoted &&
21040cb5e5dSvi117747 		    *sip_header->sip_hdr_current == SIP_COMMA) {
21140cb5e5dSvi117747 			/*
21240cb5e5dSvi117747 			 * value ends before the COMMA
21340cb5e5dSvi117747 			 */
21440cb5e5dSvi117747 			sip_header->sip_hdr_current--;
21540cb5e5dSvi117747 			return (0);
21640cb5e5dSvi117747 		}
21740cb5e5dSvi117747 		sip_header->sip_hdr_current++;
21840cb5e5dSvi117747 	}
21940cb5e5dSvi117747 	if (quoted)
22040cb5e5dSvi117747 		return (1);
22140cb5e5dSvi117747 	return (0);
22240cb5e5dSvi117747 }
22340cb5e5dSvi117747 
22440cb5e5dSvi117747 /*
22540cb5e5dSvi117747  * Parse the header into parameter list. Parameters start with a ';'
22640cb5e5dSvi117747  */
22740cb5e5dSvi117747 int
22840cb5e5dSvi117747 sip_parse_params(_sip_header_t *sip_header, sip_param_t **parsed_list)
22940cb5e5dSvi117747 {
23040cb5e5dSvi117747 	sip_param_t	*param = NULL;
23140cb5e5dSvi117747 	sip_param_t	*new_param;
23240cb5e5dSvi117747 	char		*tmp_ptr;
23340cb5e5dSvi117747 
23440cb5e5dSvi117747 	if (parsed_list == NULL)
23540cb5e5dSvi117747 		return (0);
23640cb5e5dSvi117747 
23740cb5e5dSvi117747 	*parsed_list = NULL;
23840cb5e5dSvi117747 	for (;;) {
23940cb5e5dSvi117747 		boolean_t	quoted_name = B_FALSE;
24040cb5e5dSvi117747 
24140cb5e5dSvi117747 		/*
24240cb5e5dSvi117747 		 * First check if there are any params
24340cb5e5dSvi117747 		 */
24440cb5e5dSvi117747 		if (sip_skip_white_space(sip_header) != 0)
24540cb5e5dSvi117747 			return (0);
24640cb5e5dSvi117747 		if (*sip_header->sip_hdr_current != SIP_SEMI)
24740cb5e5dSvi117747 			return (0);
24840cb5e5dSvi117747 
24940cb5e5dSvi117747 		sip_header->sip_hdr_current++;
25040cb5e5dSvi117747 
25140cb5e5dSvi117747 		new_param = calloc(1, sizeof (sip_param_t));
25240cb5e5dSvi117747 		if (new_param == NULL)
25340cb5e5dSvi117747 			return (ENOMEM);
25440cb5e5dSvi117747 
25540cb5e5dSvi117747 		if (param != NULL)
25640cb5e5dSvi117747 			param->param_next = new_param;
25740cb5e5dSvi117747 		else
25840cb5e5dSvi117747 			*parsed_list = new_param;
25940cb5e5dSvi117747 
26040cb5e5dSvi117747 		param = new_param;
26140cb5e5dSvi117747 
26240cb5e5dSvi117747 		/*
26340cb5e5dSvi117747 		 * Let's get to the start of the param name
26440cb5e5dSvi117747 		 */
26540cb5e5dSvi117747 		if (sip_skip_white_space(sip_header) != 0)
26640cb5e5dSvi117747 			return (EPROTO);
26740cb5e5dSvi117747 		/*
26840cb5e5dSvi117747 		 * start of param name
26940cb5e5dSvi117747 		 */
27040cb5e5dSvi117747 		tmp_ptr = sip_header->sip_hdr_current;
27140cb5e5dSvi117747 		param->param_name.sip_str_ptr = tmp_ptr;
27240cb5e5dSvi117747 
27340cb5e5dSvi117747 		if (sip_find_separator(sip_header, SIP_EQUAL, SIP_SEMI,
274*df4705eaSgm209912 		    SIP_COMMA, B_FALSE) != 0) {
27540cb5e5dSvi117747 			param->param_name.sip_str_len =
27640cb5e5dSvi117747 			    sip_header->sip_hdr_current - tmp_ptr;
27740cb5e5dSvi117747 			param->param_value.sip_str_ptr = NULL;
27840cb5e5dSvi117747 			param->param_value.sip_str_len = 0;
27940cb5e5dSvi117747 			return (0);
28040cb5e5dSvi117747 		}
28140cb5e5dSvi117747 
28240cb5e5dSvi117747 		/*
28340cb5e5dSvi117747 		 * End of param name
28440cb5e5dSvi117747 		 */
28540cb5e5dSvi117747 		param->param_name.sip_str_len =
28640cb5e5dSvi117747 		    sip_header->sip_hdr_current - tmp_ptr;
28740cb5e5dSvi117747 
28840cb5e5dSvi117747 		if (sip_skip_white_space(sip_header) != 0 ||
28940cb5e5dSvi117747 		    *sip_header->sip_hdr_current == SIP_COMMA) {
29040cb5e5dSvi117747 			param->param_value.sip_str_ptr = NULL;
29140cb5e5dSvi117747 			param->param_value.sip_str_len = 0;
29240cb5e5dSvi117747 			return (0);
29340cb5e5dSvi117747 		}
29440cb5e5dSvi117747 		if (*sip_header->sip_hdr_current == SIP_SEMI) {
29540cb5e5dSvi117747 			param->param_value.sip_str_ptr = NULL;
29640cb5e5dSvi117747 			param->param_value.sip_str_len = 0;
29740cb5e5dSvi117747 			continue;
29840cb5e5dSvi117747 		}
29940cb5e5dSvi117747 		assert(*sip_header->sip_hdr_current == SIP_EQUAL);
30040cb5e5dSvi117747 
30140cb5e5dSvi117747 		/*
30240cb5e5dSvi117747 		 * We are at EQUAL, lets go beyond that
30340cb5e5dSvi117747 		 */
30440cb5e5dSvi117747 		sip_header->sip_hdr_current++;
30540cb5e5dSvi117747 
30640cb5e5dSvi117747 		if (sip_skip_white_space(sip_header) != 0)
30740cb5e5dSvi117747 			return (EPROTO);
30840cb5e5dSvi117747 
30940cb5e5dSvi117747 		if (*sip_header->sip_hdr_current == SIP_QUOTE) {
31040cb5e5dSvi117747 			sip_header->sip_hdr_current++;
31140cb5e5dSvi117747 			quoted_name = B_TRUE;
31240cb5e5dSvi117747 		}
31340cb5e5dSvi117747 
31440cb5e5dSvi117747 		/*
31540cb5e5dSvi117747 		 * start of param value
31640cb5e5dSvi117747 		 */
31740cb5e5dSvi117747 		param->param_value.sip_str_ptr = sip_header->sip_hdr_current;
31840cb5e5dSvi117747 		tmp_ptr = sip_header->sip_hdr_current;
31940cb5e5dSvi117747 
32040cb5e5dSvi117747 		if (quoted_name && sip_find_token(sip_header, SIP_QUOTE) != 0) {
32140cb5e5dSvi117747 			return (EPROTO);
32240cb5e5dSvi117747 		} else if (sip_find_separator(sip_header, SIP_SEMI, SIP_COMMA,
323*df4705eaSgm209912 		    (char)NULL, B_FALSE) != 0) {
32440cb5e5dSvi117747 			return (EPROTO);
32540cb5e5dSvi117747 		}
32640cb5e5dSvi117747 		param->param_value.sip_str_len = sip_header->sip_hdr_current -
32740cb5e5dSvi117747 		    tmp_ptr;
32840cb5e5dSvi117747 		if (quoted_name)
32940cb5e5dSvi117747 			param->param_value.sip_str_len--;
33040cb5e5dSvi117747 	}
33140cb5e5dSvi117747 }
33240cb5e5dSvi117747 
33340cb5e5dSvi117747 /*
33440cb5e5dSvi117747  * a header that only has "header_name : " is an empty header
33540cb5e5dSvi117747  * ":" must exist
33640cb5e5dSvi117747  * sip_hdr_current resets to sip_hdr_start before exit
33740cb5e5dSvi117747  */
33840cb5e5dSvi117747 boolean_t
33940cb5e5dSvi117747 sip_is_empty_hdr(_sip_header_t *sip_header)
34040cb5e5dSvi117747 {
34140cb5e5dSvi117747 	if (sip_find_token(sip_header, SIP_HCOLON) != 0) {
34240cb5e5dSvi117747 		sip_header->sip_hdr_current = sip_header->sip_hdr_start;
34340cb5e5dSvi117747 		return (B_FALSE);
34440cb5e5dSvi117747 	}
34540cb5e5dSvi117747 
34640cb5e5dSvi117747 	if (sip_skip_white_space(sip_header) == 0) {
34740cb5e5dSvi117747 		sip_header->sip_hdr_current = sip_header->sip_hdr_start;
34840cb5e5dSvi117747 		return (B_FALSE);
34940cb5e5dSvi117747 	}
35040cb5e5dSvi117747 
35140cb5e5dSvi117747 	sip_header->sip_hdr_current = sip_header->sip_hdr_start;
35240cb5e5dSvi117747 	return (B_TRUE);
35340cb5e5dSvi117747 }
35440cb5e5dSvi117747 
35540cb5e5dSvi117747 /*
35640cb5e5dSvi117747  * Parsing an empty header, i.e. only has a ":"
35740cb5e5dSvi117747  */
35840cb5e5dSvi117747 int
35940cb5e5dSvi117747 sip_parse_hdr_empty(_sip_header_t *hdr, sip_parsed_header_t **phdr)
36040cb5e5dSvi117747 {
36140cb5e5dSvi117747 	sip_parsed_header_t	*parsed_header;
36240cb5e5dSvi117747 
36340cb5e5dSvi117747 	if (hdr == NULL || phdr == NULL)
36440cb5e5dSvi117747 		return (EINVAL);
36540cb5e5dSvi117747 
36640cb5e5dSvi117747 	/*
36740cb5e5dSvi117747 	 * check if already parsed
36840cb5e5dSvi117747 	 */
36940cb5e5dSvi117747 	if (hdr->sip_hdr_parsed != NULL) {
37040cb5e5dSvi117747 		*phdr = hdr->sip_hdr_parsed;
37140cb5e5dSvi117747 		return (0);
37240cb5e5dSvi117747 	}
37340cb5e5dSvi117747 
37440cb5e5dSvi117747 	*phdr = NULL;
37540cb5e5dSvi117747 
37640cb5e5dSvi117747 	parsed_header = calloc(1, sizeof (sip_parsed_header_t));
37740cb5e5dSvi117747 	if (parsed_header == NULL)
37840cb5e5dSvi117747 		return (ENOMEM);
37940cb5e5dSvi117747 	parsed_header->sip_header = hdr;
38040cb5e5dSvi117747 
38140cb5e5dSvi117747 	parsed_header->value = NULL;
38240cb5e5dSvi117747 
38340cb5e5dSvi117747 	*phdr = parsed_header;
38440cb5e5dSvi117747 	return (0);
38540cb5e5dSvi117747 }
38640cb5e5dSvi117747 
38740cb5e5dSvi117747 /*
38840cb5e5dSvi117747  * validate uri str and parse uri using uri_parse()
38940cb5e5dSvi117747  */
39040cb5e5dSvi117747 static void
39140cb5e5dSvi117747 sip_parse_uri_str(sip_str_t *sip_str, sip_hdr_value_t *value)
39240cb5e5dSvi117747 {
39340cb5e5dSvi117747 	int		error;
39440cb5e5dSvi117747 
39540cb5e5dSvi117747 	/*
39640cb5e5dSvi117747 	 * Parse uri
39740cb5e5dSvi117747 	 */
39840cb5e5dSvi117747 	if (sip_str->sip_str_len > 0) {
39940cb5e5dSvi117747 		value->sip_value_parsed_uri = sip_parse_uri(sip_str, &error);
40040cb5e5dSvi117747 		if (value->sip_value_parsed_uri == NULL)
40140cb5e5dSvi117747 			return;
40240cb5e5dSvi117747 		if (error != 0 ||
40340cb5e5dSvi117747 		    value->sip_value_parsed_uri->sip_uri_errflags != 0) {
40440cb5e5dSvi117747 			value->sip_value_state = SIP_VALUE_BAD;
40540cb5e5dSvi117747 		}
40640cb5e5dSvi117747 	}
40740cb5e5dSvi117747 }
40840cb5e5dSvi117747 
40940cb5e5dSvi117747 /*
41040cb5e5dSvi117747  * Some basic common checks before parsing the headers
41140cb5e5dSvi117747  */
41240cb5e5dSvi117747 int
41340cb5e5dSvi117747 sip_prim_parsers(_sip_header_t *sip_header, sip_parsed_header_t **header)
41440cb5e5dSvi117747 {
41540cb5e5dSvi117747 	if (sip_header == NULL || header == NULL)
41640cb5e5dSvi117747 		return (EINVAL);
41740cb5e5dSvi117747 
41840cb5e5dSvi117747 	/*
41940cb5e5dSvi117747 	 * check if already parsed
42040cb5e5dSvi117747 	 */
42140cb5e5dSvi117747 	if (sip_header->sip_hdr_parsed != NULL) {
42240cb5e5dSvi117747 		*header = sip_header->sip_hdr_parsed;
42340cb5e5dSvi117747 		return (0);
42440cb5e5dSvi117747 	}
42540cb5e5dSvi117747 	*header = NULL;
42640cb5e5dSvi117747 
42740cb5e5dSvi117747 	assert(sip_header->sip_hdr_start == sip_header->sip_hdr_current);
42840cb5e5dSvi117747 
42940cb5e5dSvi117747 	if (sip_parse_goto_values(sip_header) != 0)
43040cb5e5dSvi117747 		return (EPROTO);
43140cb5e5dSvi117747 
43240cb5e5dSvi117747 	return (0);
43340cb5e5dSvi117747 }
43440cb5e5dSvi117747 
43540cb5e5dSvi117747 /*
43640cb5e5dSvi117747  * Parse SIP/2.0 string
43740cb5e5dSvi117747  */
43840cb5e5dSvi117747 int
43940cb5e5dSvi117747 sip_get_protocol_version(_sip_header_t *sip_header,
44040cb5e5dSvi117747     sip_proto_version_t *sip_proto_version)
44140cb5e5dSvi117747 {
44240cb5e5dSvi117747 	if (sip_skip_white_space(sip_header) != 0)
44340cb5e5dSvi117747 		return (1);
44440cb5e5dSvi117747 
44540cb5e5dSvi117747 	if (strncasecmp(sip_header->sip_hdr_current, SIP, strlen(SIP)) == 0) {
44640cb5e5dSvi117747 		sip_proto_version->name.sip_str_ptr =
44740cb5e5dSvi117747 		    sip_header->sip_hdr_current;
44840cb5e5dSvi117747 		sip_proto_version->name.sip_str_len = strlen(SIP);
44940cb5e5dSvi117747 
45040cb5e5dSvi117747 		if (sip_find_token(sip_header, SIP_SLASH) != 0)
45140cb5e5dSvi117747 			return (1);
45240cb5e5dSvi117747 		if (sip_skip_white_space(sip_header) != 0)
45340cb5e5dSvi117747 			return (1);
45440cb5e5dSvi117747 
45540cb5e5dSvi117747 		sip_proto_version->version.sip_str_ptr =
45640cb5e5dSvi117747 		    sip_header->sip_hdr_current;
45740cb5e5dSvi117747 		while (isdigit(*sip_header->sip_hdr_current)) {
45840cb5e5dSvi117747 			sip_header->sip_hdr_current++;
45940cb5e5dSvi117747 			if (sip_header->sip_hdr_current >=
46040cb5e5dSvi117747 			    sip_header->sip_hdr_end) {
46140cb5e5dSvi117747 				return (1);
46240cb5e5dSvi117747 			}
46340cb5e5dSvi117747 		}
46440cb5e5dSvi117747 		if (*sip_header->sip_hdr_current != SIP_PERIOD)
46540cb5e5dSvi117747 			return (1);
46640cb5e5dSvi117747 		sip_header->sip_hdr_current++;
46740cb5e5dSvi117747 
46840cb5e5dSvi117747 		if (!isdigit(*sip_header->sip_hdr_current))
46940cb5e5dSvi117747 			return (1);
47040cb5e5dSvi117747 		while (isdigit(*sip_header->sip_hdr_current)) {
47140cb5e5dSvi117747 			sip_header->sip_hdr_current++;
47240cb5e5dSvi117747 			if (sip_header->sip_hdr_current >=
47340cb5e5dSvi117747 			    sip_header->sip_hdr_end) {
47440cb5e5dSvi117747 				return (1);
47540cb5e5dSvi117747 			}
47640cb5e5dSvi117747 		}
47740cb5e5dSvi117747 
47840cb5e5dSvi117747 		sip_proto_version->version.sip_str_len =
47940cb5e5dSvi117747 		    sip_header->sip_hdr_current -
48040cb5e5dSvi117747 		    sip_proto_version->version.sip_str_ptr;
48140cb5e5dSvi117747 		return (0);
48240cb5e5dSvi117747 	}
48340cb5e5dSvi117747 	return (1);
48440cb5e5dSvi117747 }
48540cb5e5dSvi117747 
48640cb5e5dSvi117747 /*
48740cb5e5dSvi117747  * parser1 parses hdr format
48840cb5e5dSvi117747  *	header_name: val1[; par1=pval1;par2=pval2 ..][, val2[;parlist..] ]
48940cb5e5dSvi117747  *	val can be str1/str2 or str
49040cb5e5dSvi117747  * headers: Accept, Accept-Encode, Accept-lang, Allow, Content-disp,
49140cb5e5dSvi117747  *	    Content-Encode, Content-Lang, In-reply-to,
49240cb5e5dSvi117747  *	    Priority, Require, Supported, Unsupported
49340cb5e5dSvi117747  *	    Allow-Events, Event, Subscription-State
49440cb5e5dSvi117747  */
49540cb5e5dSvi117747 int
49640cb5e5dSvi117747 sip_parse_hdr_parser1(_sip_header_t *hdr, sip_parsed_header_t **phdr, char sep)
49740cb5e5dSvi117747 {
49840cb5e5dSvi117747 	sip_parsed_header_t	*parsed_header;
49940cb5e5dSvi117747 	int			ret;
50040cb5e5dSvi117747 	sip_hdr_value_t		*value = NULL;
50140cb5e5dSvi117747 	sip_hdr_value_t		*last_value = NULL;
50240cb5e5dSvi117747 
50340cb5e5dSvi117747 	if ((ret = sip_prim_parsers(hdr, phdr)) != 0)
50440cb5e5dSvi117747 		return (ret);
50540cb5e5dSvi117747 
50640cb5e5dSvi117747 	/*
50740cb5e5dSvi117747 	 * check if previously parsed
50840cb5e5dSvi117747 	 */
50940cb5e5dSvi117747 	if (*phdr != NULL) {
51040cb5e5dSvi117747 		hdr->sip_hdr_parsed = *phdr;
51140cb5e5dSvi117747 		return (0);
51240cb5e5dSvi117747 	}
51340cb5e5dSvi117747 
51440cb5e5dSvi117747 	parsed_header = calloc(1, sizeof (sip_parsed_header_t));
51540cb5e5dSvi117747 	if (parsed_header == NULL)
51640cb5e5dSvi117747 		return (ENOMEM);
51740cb5e5dSvi117747 	parsed_header->sip_parsed_header_version = SIP_PARSED_HEADER_VERSION_1;
51840cb5e5dSvi117747 	parsed_header->sip_header = hdr;
51940cb5e5dSvi117747 
52040cb5e5dSvi117747 	while (hdr->sip_hdr_current < hdr->sip_hdr_end) {
52140cb5e5dSvi117747 		value = calloc(1, sizeof (sip_hdr_value_t));
52240cb5e5dSvi117747 		if (value == NULL) {
52340cb5e5dSvi117747 			sip_free_phdr(parsed_header);
52440cb5e5dSvi117747 			return (ENOMEM);
52540cb5e5dSvi117747 		}
52640cb5e5dSvi117747 		if (last_value != NULL)
52740cb5e5dSvi117747 			last_value->sip_next_value = value;
52840cb5e5dSvi117747 		else
52940cb5e5dSvi117747 			parsed_header->value = (sip_value_t *)value;
53040cb5e5dSvi117747 
53140cb5e5dSvi117747 		value->sip_value_start = hdr->sip_hdr_current;
53240cb5e5dSvi117747 		value->sip_value_header = parsed_header;
53340cb5e5dSvi117747 
534*df4705eaSgm209912 		if (sip_find_separator(hdr, sep, SIP_COMMA, SIP_SEMI,
535*df4705eaSgm209912 		    B_FALSE) == 0) {
53640cb5e5dSvi117747 			char	c = *hdr->sip_hdr_current;
53740cb5e5dSvi117747 
53840cb5e5dSvi117747 			if (isspace(c) && sep == (char)NULL) {
53940cb5e5dSvi117747 				value->str_val_ptr = value->sip_value_start;
54040cb5e5dSvi117747 				value->str_val_len = hdr->sip_hdr_current -
54140cb5e5dSvi117747 				    value->sip_value_start;
54240cb5e5dSvi117747 				/*
54340cb5e5dSvi117747 				 * nothing at the end except space
54440cb5e5dSvi117747 				 */
54540cb5e5dSvi117747 				if (sip_skip_white_space(hdr) != 0) {
54640cb5e5dSvi117747 					value->sip_value_end =
54740cb5e5dSvi117747 					    hdr->sip_hdr_current;
54840cb5e5dSvi117747 					goto end;
54940cb5e5dSvi117747 				}
55040cb5e5dSvi117747 				/*
55140cb5e5dSvi117747 				 * white space skipped
55240cb5e5dSvi117747 				 */
55340cb5e5dSvi117747 				c = *(hdr->sip_hdr_current);
55440cb5e5dSvi117747 			}
55540cb5e5dSvi117747 
55640cb5e5dSvi117747 			/*
55740cb5e5dSvi117747 			 * only one string until COMMA, use sip_str_t
55840cb5e5dSvi117747 			 */
55940cb5e5dSvi117747 			if (c == SIP_COMMA) {
56040cb5e5dSvi117747 				char	*t = hdr->sip_hdr_current;
56140cb5e5dSvi117747 
56240cb5e5dSvi117747 				hdr->sip_hdr_current--;
56340cb5e5dSvi117747 				(void) sip_reverse_skip_white_space(hdr);
56440cb5e5dSvi117747 				value->str_val_ptr = value->sip_value_start;
56540cb5e5dSvi117747 				value->str_val_len = hdr->sip_hdr_current -
56640cb5e5dSvi117747 				    value->sip_value_start + 1;
56740cb5e5dSvi117747 				hdr->sip_hdr_current = t;
56840cb5e5dSvi117747 				goto get_next_val;
56940cb5e5dSvi117747 			}
57040cb5e5dSvi117747 
57140cb5e5dSvi117747 			/*
57240cb5e5dSvi117747 			 * two strings, use sip_2strs_t
57340cb5e5dSvi117747 			 */
57440cb5e5dSvi117747 			if ((sep != (char)NULL) && (c == sep)) {
57540cb5e5dSvi117747 				value->strs1_val_ptr = value->sip_value_start;
57640cb5e5dSvi117747 				value->strs1_val_len = hdr->sip_hdr_current -
57740cb5e5dSvi117747 				    value->sip_value_start;
57840cb5e5dSvi117747 
57940cb5e5dSvi117747 				value->strs2_val_ptr =
58040cb5e5dSvi117747 				    (++hdr->sip_hdr_current);
58140cb5e5dSvi117747 				if (sip_find_separator(hdr, SIP_SEMI, SIP_COMMA,
582*df4705eaSgm209912 				    (char)NULL, B_FALSE) == 0) {
58340cb5e5dSvi117747 					char t = *(hdr->sip_hdr_current);
58440cb5e5dSvi117747 					value->strs2_val_len =
58540cb5e5dSvi117747 					    hdr->sip_hdr_current -
58640cb5e5dSvi117747 					    value->strs2_val_ptr;
58740cb5e5dSvi117747 					/*
58840cb5e5dSvi117747 					 * if COMMA, no param list, get next val
58940cb5e5dSvi117747 					 * if SEMI, need to set params list
59040cb5e5dSvi117747 					 */
59140cb5e5dSvi117747 					if (t == SIP_COMMA)
59240cb5e5dSvi117747 						goto get_next_val;
59340cb5e5dSvi117747 				} else { /* the last part */
59440cb5e5dSvi117747 					value->strs2_val_len =
59540cb5e5dSvi117747 					    hdr->sip_hdr_current -
59640cb5e5dSvi117747 					    value->strs2_val_ptr;
59740cb5e5dSvi117747 					value->sip_value_end =
59840cb5e5dSvi117747 					    hdr->sip_hdr_current;
59940cb5e5dSvi117747 					goto end;
60040cb5e5dSvi117747 				}
60140cb5e5dSvi117747 			} else if (sep != (char)NULL) {
60240cb5e5dSvi117747 				value->sip_value_state = SIP_VALUE_BAD;
60340cb5e5dSvi117747 				goto get_next_val;
60440cb5e5dSvi117747 			}
60540cb5e5dSvi117747 
60640cb5e5dSvi117747 			/*
60740cb5e5dSvi117747 			 * c == SEMI, value contains single string
60840cb5e5dSvi117747 			 * only one string until SEMI, use sip_str_t
60940cb5e5dSvi117747 			 */
61040cb5e5dSvi117747 			if (c == SIP_SEMI) {
61140cb5e5dSvi117747 				char	*t = hdr->sip_hdr_current;
61240cb5e5dSvi117747 
61340cb5e5dSvi117747 				hdr->sip_hdr_current--;
61440cb5e5dSvi117747 				/*
61540cb5e5dSvi117747 				 * get rid of SP at end of value field
61640cb5e5dSvi117747 				 */
61740cb5e5dSvi117747 				(void) sip_reverse_skip_white_space(hdr);
61840cb5e5dSvi117747 				value->str_val_ptr = value->sip_value_start;
61940cb5e5dSvi117747 				value->str_val_len = hdr->sip_hdr_current -
62040cb5e5dSvi117747 				    value->str_val_ptr + 1;
62140cb5e5dSvi117747 				hdr->sip_hdr_current = t;
62240cb5e5dSvi117747 			}
62340cb5e5dSvi117747 
62440cb5e5dSvi117747 			/*
62540cb5e5dSvi117747 			 * if SEMI exists in the value, set params list
62640cb5e5dSvi117747 			 * two situations, there is or not SLASH before SEMI
62740cb5e5dSvi117747 			 */
62840cb5e5dSvi117747 			ret = sip_parse_params(hdr, &value->sip_param_list);
62940cb5e5dSvi117747 			if (ret == EPROTO) {
63040cb5e5dSvi117747 				value->sip_value_state = SIP_VALUE_BAD;
63140cb5e5dSvi117747 			} else if (ret != 0) {
63240cb5e5dSvi117747 				sip_free_phdr(parsed_header);
63340cb5e5dSvi117747 				return (ret);
63440cb5e5dSvi117747 			}
63540cb5e5dSvi117747 			goto get_next_val;
63640cb5e5dSvi117747 		} else {
63740cb5e5dSvi117747 			value->str_val_ptr = value->sip_value_start;
63840cb5e5dSvi117747 			value->str_val_len = hdr->sip_hdr_current -
63940cb5e5dSvi117747 			    value->sip_value_start;
64040cb5e5dSvi117747 			value->sip_value_end = hdr->sip_hdr_current;
64140cb5e5dSvi117747 			goto end;
64240cb5e5dSvi117747 		}
64340cb5e5dSvi117747 get_next_val:
64440cb5e5dSvi117747 		if (sip_find_token(hdr, SIP_COMMA) != 0) {
64540cb5e5dSvi117747 			value->sip_value_end = hdr->sip_hdr_current;
64640cb5e5dSvi117747 			break;
64740cb5e5dSvi117747 		}
64840cb5e5dSvi117747 		value->sip_value_end = hdr->sip_hdr_current - 1;
64940cb5e5dSvi117747 		last_value = value;
65040cb5e5dSvi117747 		(void) sip_skip_white_space(hdr);
65140cb5e5dSvi117747 	}
65240cb5e5dSvi117747 
65340cb5e5dSvi117747 end:
65440cb5e5dSvi117747 	*phdr = parsed_header;
65540cb5e5dSvi117747 	hdr->sip_hdr_parsed = *phdr;
65640cb5e5dSvi117747 	return (0);
65740cb5e5dSvi117747 }
65840cb5e5dSvi117747 
65940cb5e5dSvi117747 /*
66040cb5e5dSvi117747  * header_name: int
66140cb5e5dSvi117747  * headers: Expires, Min-Expires
66240cb5e5dSvi117747  */
66340cb5e5dSvi117747 /* ARGSUSED */
66440cb5e5dSvi117747 int
66540cb5e5dSvi117747 sip_parse_hdr_parser2(_sip_header_t *hdr, sip_parsed_header_t **phdr,
66640cb5e5dSvi117747     int val_type)
66740cb5e5dSvi117747 {
66840cb5e5dSvi117747 	sip_parsed_header_t	*parsed_header;
66940cb5e5dSvi117747 	int			ret = 0;
67040cb5e5dSvi117747 	sip_hdr_value_t		*value = NULL;
67140cb5e5dSvi117747 
67240cb5e5dSvi117747 	if ((ret = sip_prim_parsers(hdr, phdr)) != 0)
67340cb5e5dSvi117747 		return (ret);
67440cb5e5dSvi117747 
67540cb5e5dSvi117747 	/*
67640cb5e5dSvi117747 	 * check if previously parsed
67740cb5e5dSvi117747 	 */
67840cb5e5dSvi117747 	if (*phdr != NULL) {
67940cb5e5dSvi117747 		hdr->sip_hdr_parsed = *phdr;
68040cb5e5dSvi117747 		return (0);
68140cb5e5dSvi117747 	}
68240cb5e5dSvi117747 	parsed_header = calloc(1, sizeof (sip_parsed_header_t));
68340cb5e5dSvi117747 	if (parsed_header == NULL)
68440cb5e5dSvi117747 		return (ENOMEM);
68540cb5e5dSvi117747 	parsed_header->sip_parsed_header_version = SIP_PARSED_HEADER_VERSION_1;
68640cb5e5dSvi117747 	parsed_header->sip_header = hdr;
68740cb5e5dSvi117747 
68840cb5e5dSvi117747 	value = calloc(1, sizeof (sip_hdr_value_t));
68940cb5e5dSvi117747 	if (value == NULL) {
69040cb5e5dSvi117747 		sip_free_phdr(parsed_header);
69140cb5e5dSvi117747 		return (ENOMEM);
69240cb5e5dSvi117747 	}
69340cb5e5dSvi117747 
69440cb5e5dSvi117747 	parsed_header->value = (sip_value_t *)value;
69540cb5e5dSvi117747 
69640cb5e5dSvi117747 	value->sip_value_start = hdr->sip_hdr_current;
69740cb5e5dSvi117747 	value->sip_value_header = parsed_header;
69840cb5e5dSvi117747 
69940cb5e5dSvi117747 	ret = sip_atoi(hdr, &value->int_val);
70040cb5e5dSvi117747 	if (ret != 0) {
70140cb5e5dSvi117747 		value->int_val = 0;
70240cb5e5dSvi117747 		value->sip_value_state = SIP_VALUE_BAD;
70340cb5e5dSvi117747 	}
70440cb5e5dSvi117747 
70540cb5e5dSvi117747 	value->sip_value_end = hdr->sip_hdr_current - 1;
70640cb5e5dSvi117747 
70740cb5e5dSvi117747 	*phdr = parsed_header;
70840cb5e5dSvi117747 	hdr->sip_hdr_parsed = *phdr;
70940cb5e5dSvi117747 	return (0);
71040cb5e5dSvi117747 }
71140cb5e5dSvi117747 
71240cb5e5dSvi117747 /*
71340cb5e5dSvi117747  * parser3 parses hdr format
71440cb5e5dSvi117747  * header_name: <val1>[, <val2>]
71540cb5e5dSvi117747  * Alert-Info, Call-Info, Error-Info, reply-to
71640cb5e5dSvi117747  */
71740cb5e5dSvi117747 int
71840cb5e5dSvi117747 sip_parse_hdr_parser3(_sip_header_t *hdr, sip_parsed_header_t **phdr, int type,
71940cb5e5dSvi117747     boolean_t parse_uri)
72040cb5e5dSvi117747 {
72140cb5e5dSvi117747 	sip_parsed_header_t	*parsed_header;
72240cb5e5dSvi117747 	sip_hdr_value_t		*value = NULL;
72340cb5e5dSvi117747 	sip_hdr_value_t		*last_value = NULL;
72440cb5e5dSvi117747 	int			ret;
72540cb5e5dSvi117747 
72640cb5e5dSvi117747 	if ((ret = sip_prim_parsers(hdr, phdr)) != 0)
72740cb5e5dSvi117747 		return (ret);
72840cb5e5dSvi117747 
72940cb5e5dSvi117747 	/*
73040cb5e5dSvi117747 	 * check if previously parsed
73140cb5e5dSvi117747 	 */
73240cb5e5dSvi117747 	if (*phdr != NULL) {
73340cb5e5dSvi117747 		hdr->sip_hdr_parsed = *phdr;
73440cb5e5dSvi117747 		return (0);
73540cb5e5dSvi117747 	}
73640cb5e5dSvi117747 	parsed_header = calloc(1, sizeof (sip_parsed_header_t));
73740cb5e5dSvi117747 	if (parsed_header == NULL)
73840cb5e5dSvi117747 		return (ENOMEM);
73940cb5e5dSvi117747 	parsed_header->sip_parsed_header_version = SIP_PARSED_HEADER_VERSION_1;
74040cb5e5dSvi117747 	parsed_header->sip_header = hdr;
74140cb5e5dSvi117747 	while (hdr->sip_hdr_current < hdr->sip_hdr_end) {
74240cb5e5dSvi117747 		int		r;
74340cb5e5dSvi117747 
74440cb5e5dSvi117747 		value = calloc(1, sizeof (sip_hdr_value_t));
74540cb5e5dSvi117747 		if (value == NULL) {
74640cb5e5dSvi117747 			sip_free_phdr(parsed_header);
74740cb5e5dSvi117747 			return (ENOMEM);
74840cb5e5dSvi117747 		}
74940cb5e5dSvi117747 
75040cb5e5dSvi117747 		if (last_value != NULL)
75140cb5e5dSvi117747 			last_value->sip_next_value = value;
75240cb5e5dSvi117747 		else
75340cb5e5dSvi117747 			parsed_header->value = (sip_value_t *)value;
75440cb5e5dSvi117747 
75540cb5e5dSvi117747 		value->sip_value_start = hdr->sip_hdr_current;
75640cb5e5dSvi117747 		value->sip_value_header = parsed_header;
75740cb5e5dSvi117747 
75840cb5e5dSvi117747 		if (type == SIP_STRS_VAL) {
75940cb5e5dSvi117747 			if (sip_find_token(hdr, SIP_LAQUOT) == 0) {
76040cb5e5dSvi117747 				char	*cur;
76140cb5e5dSvi117747 
76240cb5e5dSvi117747 				/*
76340cb5e5dSvi117747 				 * record the position after LAQUOT
76440cb5e5dSvi117747 				 */
76540cb5e5dSvi117747 				cur = hdr->sip_hdr_current;
76640cb5e5dSvi117747 				/*
76740cb5e5dSvi117747 				 * get display name and store in str1
76840cb5e5dSvi117747 				 */
76940cb5e5dSvi117747 				hdr->sip_hdr_current = value->sip_value_start;
77040cb5e5dSvi117747 				if (*(hdr->sip_hdr_current) != SIP_LAQUOT) {
77140cb5e5dSvi117747 					/*
77240cb5e5dSvi117747 					 * record start pos of display name
77340cb5e5dSvi117747 					 */
77440cb5e5dSvi117747 					char	*tmp = hdr->sip_hdr_current;
77540cb5e5dSvi117747 
77640cb5e5dSvi117747 					if (*hdr->sip_hdr_current ==
77740cb5e5dSvi117747 					    SIP_QUOTE) {
77840cb5e5dSvi117747 						hdr->sip_hdr_current++;
77940cb5e5dSvi117747 						tmp++;
78040cb5e5dSvi117747 						if (sip_find_token(hdr,
78140cb5e5dSvi117747 						    SIP_QUOTE) != 0) {
78240cb5e5dSvi117747 							value->sip_value_state =
78340cb5e5dSvi117747 							    SIP_VALUE_BAD;
78440cb5e5dSvi117747 							goto get_next_val;
78540cb5e5dSvi117747 						}
78640cb5e5dSvi117747 						hdr->sip_hdr_current -= 2;
78740cb5e5dSvi117747 					} else {
78840cb5e5dSvi117747 						hdr->sip_hdr_current = cur - 2;
78940cb5e5dSvi117747 						(void)
79040cb5e5dSvi117747 						    sip_reverse_skip_white_space
79140cb5e5dSvi117747 						    (hdr);
79240cb5e5dSvi117747 					}
79340cb5e5dSvi117747 					value->strs1_val_ptr = tmp;
79440cb5e5dSvi117747 					value->strs1_val_len =
79540cb5e5dSvi117747 					    hdr->sip_hdr_current - tmp + 1;
79640cb5e5dSvi117747 				} else {
79740cb5e5dSvi117747 					value->strs1_val_ptr = NULL;
79840cb5e5dSvi117747 					value->strs1_val_len = 0;
79940cb5e5dSvi117747 				}
80040cb5e5dSvi117747 
80140cb5e5dSvi117747 				/*
80240cb5e5dSvi117747 				 * set current to the char after LAQUOT
80340cb5e5dSvi117747 				 */
80440cb5e5dSvi117747 				hdr->sip_hdr_current = cur;
80540cb5e5dSvi117747 				value->strs2_val_ptr = hdr->sip_hdr_current;
80640cb5e5dSvi117747 				if (sip_find_token(hdr, SIP_RAQUOT)) {
80740cb5e5dSvi117747 					/*
80840cb5e5dSvi117747 					 * no RAQUOT
80940cb5e5dSvi117747 					 */
81040cb5e5dSvi117747 					value->strs1_val_ptr = NULL;
81140cb5e5dSvi117747 					value->strs1_val_len = 0;
81240cb5e5dSvi117747 					value->strs2_val_ptr = NULL;
81340cb5e5dSvi117747 					value->strs2_val_len = 0;
81440cb5e5dSvi117747 					value->sip_value_state = SIP_VALUE_BAD;
81540cb5e5dSvi117747 					goto get_next_val;
81640cb5e5dSvi117747 				}
81740cb5e5dSvi117747 				value->strs2_val_len = hdr->sip_hdr_current -
81840cb5e5dSvi117747 				    value->strs2_val_ptr - 1;
81940cb5e5dSvi117747 			} else {
82040cb5e5dSvi117747 				char	*cur;
82140cb5e5dSvi117747 
82240cb5e5dSvi117747 				/*
82340cb5e5dSvi117747 				 * No display name - Only URI.
82440cb5e5dSvi117747 				 */
82540cb5e5dSvi117747 				value->strs1_val_ptr = NULL;
82640cb5e5dSvi117747 				value->strs1_val_len = 0;
82740cb5e5dSvi117747 				cur = value->sip_value_start;
82840cb5e5dSvi117747 				hdr->sip_hdr_current = cur;
82940cb5e5dSvi117747 				if (sip_find_separator(hdr, SIP_COMMA,
830*df4705eaSgm209912 				    (char)NULL, (char)NULL, B_FALSE) != 0) {
83140cb5e5dSvi117747 					value->strs2_val_ptr = cur;
83240cb5e5dSvi117747 					value->strs2_val_len =
83340cb5e5dSvi117747 					    hdr->sip_hdr_current -
83440cb5e5dSvi117747 					    value->strs2_val_ptr - 1;
83540cb5e5dSvi117747 				} else if (*hdr->sip_hdr_current == SIP_SP) {
83640cb5e5dSvi117747 					value->strs2_val_ptr = cur;
83740cb5e5dSvi117747 					cur = hdr->sip_hdr_current - 1;
83840cb5e5dSvi117747 					if (sip_skip_white_space(hdr) != 0) {
83940cb5e5dSvi117747 						value->strs2_val_len = cur -
84040cb5e5dSvi117747 						    value->strs2_val_ptr - 1;
84140cb5e5dSvi117747 					} else if (*hdr->sip_hdr_current ==
84240cb5e5dSvi117747 					    SIP_COMMA) {
84340cb5e5dSvi117747 						value->strs2_val_len = cur -
84440cb5e5dSvi117747 						    value->strs2_val_ptr - 1;
84540cb5e5dSvi117747 					} else {
84640cb5e5dSvi117747 						value->sip_value_state =
84740cb5e5dSvi117747 						    SIP_VALUE_BAD;
84840cb5e5dSvi117747 						goto get_next_val;
84940cb5e5dSvi117747 					}
85040cb5e5dSvi117747 				} else {
85140cb5e5dSvi117747 					value->strs2_val_ptr = cur;
85240cb5e5dSvi117747 					value->strs2_val_len =
85340cb5e5dSvi117747 					    hdr->sip_hdr_current -
85440cb5e5dSvi117747 					    value->strs2_val_ptr;
85540cb5e5dSvi117747 				}
85640cb5e5dSvi117747 			}
85740cb5e5dSvi117747 			if (parse_uri)
85840cb5e5dSvi117747 				sip_parse_uri_str(&value->strs_s2, value);
85940cb5e5dSvi117747 		}
86040cb5e5dSvi117747 
86140cb5e5dSvi117747 		if (type == SIP_STR_VAL) {
86240cb5e5dSvi117747 			/*
86340cb5e5dSvi117747 			 * alert-info, error-info, call-info
86440cb5e5dSvi117747 			 */
86540cb5e5dSvi117747 			if (sip_find_token(hdr, SIP_LAQUOT) == 0) {
86640cb5e5dSvi117747 				value->str_val_ptr = hdr->sip_hdr_current;
86740cb5e5dSvi117747 				if (sip_find_token(hdr, SIP_RAQUOT) == 0) {
86840cb5e5dSvi117747 					value->str_val_len =
86940cb5e5dSvi117747 					    hdr->sip_hdr_current -
87040cb5e5dSvi117747 					    value->str_val_ptr - 1;
87140cb5e5dSvi117747 				} else {
87240cb5e5dSvi117747 					value->str_val_ptr = NULL;
87340cb5e5dSvi117747 					value->str_val_len = 0;
87440cb5e5dSvi117747 					value->sip_value_state = SIP_VALUE_BAD;
87540cb5e5dSvi117747 					goto get_next_val;
87640cb5e5dSvi117747 				}
87740cb5e5dSvi117747 				hdr->sip_hdr_current--;
87840cb5e5dSvi117747 			} else {
87940cb5e5dSvi117747 				value->str_val_ptr = NULL;
88040cb5e5dSvi117747 				value->str_val_len = 0;
88140cb5e5dSvi117747 				value->sip_value_state = SIP_VALUE_BAD;
88240cb5e5dSvi117747 				goto get_next_val;
88340cb5e5dSvi117747 			}
88440cb5e5dSvi117747 			if (parse_uri)
88540cb5e5dSvi117747 				sip_parse_uri_str(&value->str_val, value);
88640cb5e5dSvi117747 		}
88740cb5e5dSvi117747 
888*df4705eaSgm209912 		r = sip_find_separator(hdr, SIP_COMMA, SIP_SEMI, (char)NULL,
889*df4705eaSgm209912 		    B_FALSE);
89040cb5e5dSvi117747 		if (r != 0) {
89140cb5e5dSvi117747 			value->sip_value_end = hdr->sip_hdr_current;
89240cb5e5dSvi117747 			goto end;
89340cb5e5dSvi117747 		}
89440cb5e5dSvi117747 		if (*hdr->sip_hdr_current == SIP_SEMI) {
89540cb5e5dSvi117747 			(void) sip_parse_params(hdr,
89640cb5e5dSvi117747 			    &(value->sip_param_list));
89740cb5e5dSvi117747 			goto get_next_val;
89840cb5e5dSvi117747 		}
89940cb5e5dSvi117747 
90040cb5e5dSvi117747 		if (*hdr->sip_hdr_current == SIP_COMMA) {
90140cb5e5dSvi117747 			hdr->sip_hdr_current--;
90240cb5e5dSvi117747 			goto get_next_val;
90340cb5e5dSvi117747 		}
90440cb5e5dSvi117747 get_next_val:
90540cb5e5dSvi117747 		if (sip_find_token(hdr, SIP_COMMA) != 0) {
90640cb5e5dSvi117747 			value->sip_value_end = hdr->sip_hdr_current;
90740cb5e5dSvi117747 			break;
90840cb5e5dSvi117747 		}
90940cb5e5dSvi117747 		value->sip_value_end = hdr->sip_hdr_current - 1;
91040cb5e5dSvi117747 		last_value = value;
91140cb5e5dSvi117747 		(void) sip_skip_white_space(hdr);
91240cb5e5dSvi117747 	}
91340cb5e5dSvi117747 
91440cb5e5dSvi117747 end:
91540cb5e5dSvi117747 	*phdr = parsed_header;
91640cb5e5dSvi117747 	hdr->sip_hdr_parsed = *phdr;
91740cb5e5dSvi117747 	return (0);
91840cb5e5dSvi117747 }
91940cb5e5dSvi117747 
92040cb5e5dSvi117747 /*
92140cb5e5dSvi117747  * parser4 parses hdr format, the whole field is one single str
92240cb5e5dSvi117747  * header: Subject, MIME-Version, Organization, Server, User-Agent
92340cb5e5dSvi117747  */
92440cb5e5dSvi117747 int
92540cb5e5dSvi117747 sip_parse_hdr_parser4(_sip_header_t *hdr, sip_parsed_header_t **phdr)
92640cb5e5dSvi117747 {
92740cb5e5dSvi117747 	sip_parsed_header_t	*parsed_header;
92840cb5e5dSvi117747 	sip_hdr_value_t		*value = NULL;
92940cb5e5dSvi117747 	int			ret;
93040cb5e5dSvi117747 
93140cb5e5dSvi117747 	if ((ret = sip_prim_parsers(hdr, phdr)) != 0)
93240cb5e5dSvi117747 		return (ret);
93340cb5e5dSvi117747 
93440cb5e5dSvi117747 	/*
93540cb5e5dSvi117747 	 * check if previously parsed
93640cb5e5dSvi117747 	 */
93740cb5e5dSvi117747 	if (*phdr != NULL) {
93840cb5e5dSvi117747 		hdr->sip_hdr_parsed = *phdr;
93940cb5e5dSvi117747 		return (0);
94040cb5e5dSvi117747 	}
94140cb5e5dSvi117747 	parsed_header = calloc(1, sizeof (sip_parsed_header_t));
94240cb5e5dSvi117747 	if (parsed_header == NULL)
94340cb5e5dSvi117747 		return (ENOMEM);
94440cb5e5dSvi117747 	parsed_header->sip_parsed_header_version = SIP_PARSED_HEADER_VERSION_1;
94540cb5e5dSvi117747 	parsed_header->sip_header = hdr;
94640cb5e5dSvi117747 
94740cb5e5dSvi117747 	value = calloc(1, sizeof (sip_hdr_value_t));
94840cb5e5dSvi117747 	if (value == NULL) {
94940cb5e5dSvi117747 		sip_free_phdr(parsed_header);
95040cb5e5dSvi117747 		return (ENOMEM);
95140cb5e5dSvi117747 	}
95240cb5e5dSvi117747 
95340cb5e5dSvi117747 	parsed_header->value = (sip_value_t *)value;
95440cb5e5dSvi117747 
95540cb5e5dSvi117747 	value->sip_value_start = hdr->sip_hdr_current;
95640cb5e5dSvi117747 	value->sip_value_header = parsed_header;
95740cb5e5dSvi117747 
95840cb5e5dSvi117747 	value->str_val_ptr = hdr->sip_hdr_current;
95940cb5e5dSvi117747 	/*
96040cb5e5dSvi117747 	 * get rid of CRLF at end
96140cb5e5dSvi117747 	 */
96240cb5e5dSvi117747 	value->str_val_len = hdr->sip_hdr_end - value->str_val_ptr - 2;
96340cb5e5dSvi117747 	value->sip_value_end = hdr->sip_hdr_end;
96440cb5e5dSvi117747 
96540cb5e5dSvi117747 	*phdr = parsed_header;
96640cb5e5dSvi117747 	hdr->sip_hdr_parsed = *phdr;
96740cb5e5dSvi117747 	return (0);
96840cb5e5dSvi117747 }
96940cb5e5dSvi117747 
97040cb5e5dSvi117747 int
97140cb5e5dSvi117747 sip_parse_hdr_parser5(_sip_header_t *hdr, sip_parsed_header_t **phdr,
97240cb5e5dSvi117747     boolean_t parse_uri)
97340cb5e5dSvi117747 {
97440cb5e5dSvi117747 	sip_parsed_header_t	*parsed_header;
97540cb5e5dSvi117747 	sip_hdr_value_t		*value = NULL;
97640cb5e5dSvi117747 	sip_param_t		*tmp_param;
97740cb5e5dSvi117747 	boolean_t		first_param = B_TRUE;
97840cb5e5dSvi117747 	int			ret;
97940cb5e5dSvi117747 
98040cb5e5dSvi117747 	if ((ret = sip_prim_parsers(hdr, phdr)) != 0)
98140cb5e5dSvi117747 		return (ret);
98240cb5e5dSvi117747 
98340cb5e5dSvi117747 	/*
98440cb5e5dSvi117747 	 * check if previously parsed
98540cb5e5dSvi117747 	 */
98640cb5e5dSvi117747 	if (*phdr != NULL) {
98740cb5e5dSvi117747 		hdr->sip_hdr_parsed = *phdr;
98840cb5e5dSvi117747 		return (0);
98940cb5e5dSvi117747 	}
99040cb5e5dSvi117747 	parsed_header = calloc(1, sizeof (sip_parsed_header_t));
99140cb5e5dSvi117747 	if (parsed_header == NULL)
99240cb5e5dSvi117747 		return (ENOMEM);
99340cb5e5dSvi117747 	parsed_header->sip_parsed_header_version = SIP_PARSED_HEADER_VERSION_1;
99440cb5e5dSvi117747 	parsed_header->sip_header = hdr;
99540cb5e5dSvi117747 
99640cb5e5dSvi117747 	value = calloc(1, sizeof (sip_hdr_value_t));
99740cb5e5dSvi117747 	if (value == NULL) {
99840cb5e5dSvi117747 		sip_free_phdr(parsed_header);
99940cb5e5dSvi117747 		return (ENOMEM);
100040cb5e5dSvi117747 	}
100140cb5e5dSvi117747 
100240cb5e5dSvi117747 	parsed_header->value = (sip_value_t *)value;
100340cb5e5dSvi117747 
100440cb5e5dSvi117747 	value->sip_value_start = hdr->sip_hdr_current;
100540cb5e5dSvi117747 	value->auth_scheme_ptr = value->sip_value_start;
100640cb5e5dSvi117747 	value->sip_value_header = parsed_header;
100740cb5e5dSvi117747 	/*
100840cb5e5dSvi117747 	 * get auth_scheme
100940cb5e5dSvi117747 	 */
101040cb5e5dSvi117747 	if (sip_find_white_space(hdr)) {
101140cb5e5dSvi117747 		value->sip_value_state = SIP_VALUE_BAD;
101240cb5e5dSvi117747 		return (EINVAL);
101340cb5e5dSvi117747 	}
101440cb5e5dSvi117747 	value->auth_scheme_len = hdr->sip_hdr_current - value->auth_scheme_ptr;
101540cb5e5dSvi117747 
101640cb5e5dSvi117747 	tmp_param = value->auth_param;
101740cb5e5dSvi117747 
101840cb5e5dSvi117747 	/*
101940cb5e5dSvi117747 	 * parse auth_param
102040cb5e5dSvi117747 	 */
102140cb5e5dSvi117747 	for (;;) {
102240cb5e5dSvi117747 		char		*tmp_cur;
102340cb5e5dSvi117747 		boolean_t	quoted_name = B_FALSE;
102440cb5e5dSvi117747 		char		quoted_char = (char)0;
102540cb5e5dSvi117747 		sip_param_t	*new_param;
102640cb5e5dSvi117747 		boolean_t	pval_is_uri = B_FALSE;
102740cb5e5dSvi117747 
102840cb5e5dSvi117747 		if (sip_skip_white_space(hdr) != 0) {
102940cb5e5dSvi117747 			value->sip_value_state = SIP_VALUE_BAD;
103040cb5e5dSvi117747 			return (EPROTO);
103140cb5e5dSvi117747 		}
103240cb5e5dSvi117747 		tmp_cur = hdr->sip_hdr_current;
103340cb5e5dSvi117747 
103440cb5e5dSvi117747 		new_param = calloc(1, sizeof (sip_param_t));
103540cb5e5dSvi117747 		if (new_param == NULL)
103640cb5e5dSvi117747 			return (ENOMEM);
103740cb5e5dSvi117747 
103840cb5e5dSvi117747 		if (first_param == B_FALSE)
103940cb5e5dSvi117747 			tmp_param->param_next = new_param;
104040cb5e5dSvi117747 		else
104140cb5e5dSvi117747 			value->auth_param = new_param;
104240cb5e5dSvi117747 
104340cb5e5dSvi117747 		tmp_param = new_param;
104440cb5e5dSvi117747 		tmp_param->param_name.sip_str_ptr = tmp_cur;
104540cb5e5dSvi117747 
1046*df4705eaSgm209912 		if (sip_find_separator(hdr, SIP_EQUAL, SIP_COMMA, (char)NULL,
1047*df4705eaSgm209912 		    B_FALSE) != 0) {
104840cb5e5dSvi117747 			tmp_param->param_name.sip_str_len =
104940cb5e5dSvi117747 			    hdr->sip_hdr_current - tmp_cur;
105040cb5e5dSvi117747 			tmp_param->param_value.sip_str_ptr = NULL;
105140cb5e5dSvi117747 			tmp_param->param_value.sip_str_len = 0;
105240cb5e5dSvi117747 			value->sip_value_end = hdr->sip_hdr_current;
105340cb5e5dSvi117747 			goto end;
105440cb5e5dSvi117747 		}
105540cb5e5dSvi117747 
105640cb5e5dSvi117747 		/*
105740cb5e5dSvi117747 		 * End of param name
105840cb5e5dSvi117747 		 */
105940cb5e5dSvi117747 		tmp_param->param_name.sip_str_len = hdr->sip_hdr_current -
106040cb5e5dSvi117747 		    tmp_cur;
106140cb5e5dSvi117747 
106240cb5e5dSvi117747 		if (sip_skip_white_space(hdr) != 0 ||
106340cb5e5dSvi117747 		    *hdr->sip_hdr_current == SIP_COMMA) {
106440cb5e5dSvi117747 			tmp_param->param_value.sip_str_ptr = NULL;
106540cb5e5dSvi117747 			tmp_param->param_value.sip_str_len = 0;
106640cb5e5dSvi117747 			continue;
106740cb5e5dSvi117747 		}
106840cb5e5dSvi117747 
106940cb5e5dSvi117747 		/*
107040cb5e5dSvi117747 		 * We are at EQUAL
107140cb5e5dSvi117747 		 */
107240cb5e5dSvi117747 		hdr->sip_hdr_current++;
107340cb5e5dSvi117747 
107440cb5e5dSvi117747 		if (sip_skip_white_space(hdr) != 0) {
107540cb5e5dSvi117747 			value->sip_value_state = SIP_VALUE_BAD;
107640cb5e5dSvi117747 			free(tmp_param);
107740cb5e5dSvi117747 			return (EPROTO);
107840cb5e5dSvi117747 		}
107940cb5e5dSvi117747 
108040cb5e5dSvi117747 		if (*hdr->sip_hdr_current == SIP_QUOTE ||
108140cb5e5dSvi117747 		    *hdr->sip_hdr_current == SIP_LAQUOT) {
108240cb5e5dSvi117747 			if (*hdr->sip_hdr_current == SIP_QUOTE)
108340cb5e5dSvi117747 				quoted_char = SIP_QUOTE;
108440cb5e5dSvi117747 			else {
108540cb5e5dSvi117747 				quoted_char = SIP_RAQUOT;
108640cb5e5dSvi117747 				pval_is_uri = B_TRUE;
108740cb5e5dSvi117747 			}
108840cb5e5dSvi117747 			hdr->sip_hdr_current++;
108940cb5e5dSvi117747 			quoted_name = B_TRUE;
109040cb5e5dSvi117747 		}
109140cb5e5dSvi117747 
109240cb5e5dSvi117747 		/*
109340cb5e5dSvi117747 		 * start of param value
109440cb5e5dSvi117747 		 */
109540cb5e5dSvi117747 		tmp_cur = hdr->sip_hdr_current;
109640cb5e5dSvi117747 		tmp_param->param_value.sip_str_ptr = tmp_cur;
109740cb5e5dSvi117747 		if (quoted_name) {
109840cb5e5dSvi117747 			if (sip_find_token(hdr, quoted_char) != 0) {
109940cb5e5dSvi117747 				value->sip_value_state = SIP_VALUE_BAD;
110040cb5e5dSvi117747 				free(tmp_param);
110140cb5e5dSvi117747 				return (EPROTO);
110240cb5e5dSvi117747 			}
110340cb5e5dSvi117747 			tmp_param->param_value.sip_str_len =
110440cb5e5dSvi117747 			    hdr->sip_hdr_current - tmp_cur - 1;
110540cb5e5dSvi117747 		}
110640cb5e5dSvi117747 
110740cb5e5dSvi117747 		if (sip_find_token(hdr, SIP_COMMA) != 0) {
110840cb5e5dSvi117747 			value->sip_value_end = hdr->sip_hdr_current;
110940cb5e5dSvi117747 			goto end;
111040cb5e5dSvi117747 		} else {
111140cb5e5dSvi117747 			if (!quoted_name) {
111240cb5e5dSvi117747 				char *t = hdr->sip_hdr_current;
111340cb5e5dSvi117747 				hdr->sip_hdr_current--;
111440cb5e5dSvi117747 				(void) sip_reverse_skip_white_space(hdr);
111540cb5e5dSvi117747 				tmp_param->param_value.sip_str_len =
111640cb5e5dSvi117747 				    hdr->sip_hdr_current - tmp_cur;
111740cb5e5dSvi117747 				hdr->sip_hdr_current = t;
111840cb5e5dSvi117747 			}
111940cb5e5dSvi117747 		}
112040cb5e5dSvi117747 
112140cb5e5dSvi117747 		if (first_param == B_TRUE)
112240cb5e5dSvi117747 			first_param = B_FALSE;
112340cb5e5dSvi117747 
112440cb5e5dSvi117747 		/*
112540cb5e5dSvi117747 		 * Parse uri
112640cb5e5dSvi117747 		 */
112740cb5e5dSvi117747 		if (pval_is_uri && parse_uri)
112840cb5e5dSvi117747 			sip_parse_uri_str(&tmp_param->param_value, value);
112940cb5e5dSvi117747 
113040cb5e5dSvi117747 	}
113140cb5e5dSvi117747 
113240cb5e5dSvi117747 end:
113340cb5e5dSvi117747 	*phdr = parsed_header;
113440cb5e5dSvi117747 	hdr->sip_hdr_parsed = *phdr;
113540cb5e5dSvi117747 	return (0);
113640cb5e5dSvi117747 }
113740cb5e5dSvi117747 
113840cb5e5dSvi117747 /*
113940cb5e5dSvi117747  * Return the URI in the request startline
114040cb5e5dSvi117747  */
114140cb5e5dSvi117747 static int
114240cb5e5dSvi117747 _sip_get_request_uri(_sip_header_t *sip_header, sip_message_type_t *msg_info)
114340cb5e5dSvi117747 {
114440cb5e5dSvi117747 	int	size = 0;
114540cb5e5dSvi117747 	char	*start_ptr;
114640cb5e5dSvi117747 
114740cb5e5dSvi117747 	if (sip_skip_white_space(sip_header) != 0)
114840cb5e5dSvi117747 		return (EINVAL);
114940cb5e5dSvi117747 	start_ptr = sip_header->sip_hdr_current;
115040cb5e5dSvi117747 
115140cb5e5dSvi117747 	while (!isspace(*sip_header->sip_hdr_current)) {
115240cb5e5dSvi117747 		if (sip_header->sip_hdr_current >= sip_header->sip_hdr_end)
115340cb5e5dSvi117747 			return (EINVAL);
115440cb5e5dSvi117747 		sip_header->sip_hdr_current++;
115540cb5e5dSvi117747 	}
115640cb5e5dSvi117747 
115740cb5e5dSvi117747 	size = sip_header->sip_hdr_current - start_ptr;
115840cb5e5dSvi117747 
115940cb5e5dSvi117747 	msg_info->U.sip_request.sip_request_uri.sip_str_ptr = start_ptr;
116040cb5e5dSvi117747 	msg_info->U.sip_request.sip_request_uri.sip_str_len = size;
116140cb5e5dSvi117747 	if (size > 0) {	/* Parse uri */
116240cb5e5dSvi117747 		int		error;
116340cb5e5dSvi117747 
116440cb5e5dSvi117747 		msg_info->U.sip_request.sip_parse_uri = sip_parse_uri(
116540cb5e5dSvi117747 		    &msg_info->U.sip_request.sip_request_uri, &error);
116640cb5e5dSvi117747 		if (msg_info->U.sip_request.sip_parse_uri == NULL)
116740cb5e5dSvi117747 			return (error);
116840cb5e5dSvi117747 	}
116940cb5e5dSvi117747 	return (0);
117040cb5e5dSvi117747 }
117140cb5e5dSvi117747 
117240cb5e5dSvi117747 /*
117340cb5e5dSvi117747  * Parse the start line into request/response
117440cb5e5dSvi117747  */
117540cb5e5dSvi117747 int
117640cb5e5dSvi117747 sip_parse_first_line(_sip_header_t *sip_header, sip_message_type_t **msg_info)
117740cb5e5dSvi117747 {
117840cb5e5dSvi117747 	sip_message_type_t	*sip_msg_info;
117940cb5e5dSvi117747 	boolean_t		sip_is_request = B_TRUE;
118040cb5e5dSvi117747 	int			ret;
118140cb5e5dSvi117747 
118240cb5e5dSvi117747 	if (sip_header == NULL || msg_info == NULL)
118340cb5e5dSvi117747 		return (EINVAL);
118440cb5e5dSvi117747 
118540cb5e5dSvi117747 	if (sip_skip_white_space(sip_header) != 0)
118640cb5e5dSvi117747 		return (EPROTO);
118740cb5e5dSvi117747 
118840cb5e5dSvi117747 	/*
118940cb5e5dSvi117747 	 * There is nothing, return
119040cb5e5dSvi117747 	 */
119140cb5e5dSvi117747 	if (sip_header->sip_hdr_current + strlen(SIP_VERSION) >=
119240cb5e5dSvi117747 	    sip_header->sip_hdr_end) {
119340cb5e5dSvi117747 		return (EPROTO);
119440cb5e5dSvi117747 	}
119540cb5e5dSvi117747 #ifdef	__solaris__
119640cb5e5dSvi117747 	assert(mutex_held(&sip_header->sip_hdr_sipmsg->sip_msg_mutex));
119740cb5e5dSvi117747 #endif
119840cb5e5dSvi117747 	sip_msg_info = malloc(sizeof (sip_message_type_t));
119940cb5e5dSvi117747 	if (sip_msg_info == NULL)
120040cb5e5dSvi117747 		return (ENOMEM);
120140cb5e5dSvi117747 
120240cb5e5dSvi117747 	/*
120340cb5e5dSvi117747 	 * let's see if it's a request or a response
120440cb5e5dSvi117747 	 */
120540cb5e5dSvi117747 	ret = sip_get_protocol_version(sip_header,
120640cb5e5dSvi117747 	    &sip_msg_info->sip_proto_version);
120740cb5e5dSvi117747 	if (ret == 0) {
120840cb5e5dSvi117747 		sip_is_request = B_FALSE;
120940cb5e5dSvi117747 	} else if (ret == 2) {
121040cb5e5dSvi117747 		free(sip_msg_info);
121140cb5e5dSvi117747 		return (EPROTO);
121240cb5e5dSvi117747 	}
121340cb5e5dSvi117747 
121440cb5e5dSvi117747 	if (sip_skip_white_space(sip_header) != 0) {
121540cb5e5dSvi117747 		free(sip_msg_info);
121640cb5e5dSvi117747 		return (EPROTO);
121740cb5e5dSvi117747 	}
121840cb5e5dSvi117747 
121940cb5e5dSvi117747 	if (!sip_is_request) {
122040cb5e5dSvi117747 		/*
122140cb5e5dSvi117747 		 * check for status code.
122240cb5e5dSvi117747 		 */
122340cb5e5dSvi117747 		if (sip_skip_white_space(sip_header) != 0) {
122440cb5e5dSvi117747 			free(sip_msg_info);
122540cb5e5dSvi117747 			return (EPROTO);
122640cb5e5dSvi117747 		}
122740cb5e5dSvi117747 		if (sip_header->sip_hdr_current + SIP_SIZE_OF_STATUS_CODE >=
122840cb5e5dSvi117747 		    sip_header->sip_hdr_end) {
122940cb5e5dSvi117747 			free(sip_msg_info);
123040cb5e5dSvi117747 			return (EPROTO);
123140cb5e5dSvi117747 		}
123240cb5e5dSvi117747 
123340cb5e5dSvi117747 		if (sip_atoi(sip_header,
123440cb5e5dSvi117747 		    &sip_msg_info->U.sip_response.sip_response_code)) {
123540cb5e5dSvi117747 			free(sip_msg_info);
123640cb5e5dSvi117747 			return (EPROTO);
123740cb5e5dSvi117747 		}
123840cb5e5dSvi117747 
123940cb5e5dSvi117747 		if (sip_msg_info->U.sip_response.sip_response_code < 100 ||
124040cb5e5dSvi117747 		    sip_msg_info->U.sip_response.sip_response_code > 700) {
124140cb5e5dSvi117747 			free(sip_msg_info);
124240cb5e5dSvi117747 			return (EPROTO);
124340cb5e5dSvi117747 		}
124440cb5e5dSvi117747 
124540cb5e5dSvi117747 		/*
124640cb5e5dSvi117747 		 * get reason phrase.
124740cb5e5dSvi117747 		 */
124840cb5e5dSvi117747 		if (sip_skip_white_space(sip_header) != 0) {
124940cb5e5dSvi117747 			sip_msg_info->sip_resp_phrase_len = 0;
125040cb5e5dSvi117747 			sip_msg_info->sip_resp_phrase_ptr = NULL;
125140cb5e5dSvi117747 		} else {
125240cb5e5dSvi117747 			sip_msg_info->sip_resp_phrase_ptr =
125340cb5e5dSvi117747 			    sip_header->sip_hdr_current;
125440cb5e5dSvi117747 			if (sip_find_cr(sip_header) != 0) {
125540cb5e5dSvi117747 				free(sip_msg_info);
125640cb5e5dSvi117747 				return (EPROTO);
125740cb5e5dSvi117747 			}
125840cb5e5dSvi117747 			sip_msg_info->sip_resp_phrase_len =
125940cb5e5dSvi117747 			    sip_header->sip_hdr_current -
126040cb5e5dSvi117747 			    sip_msg_info->sip_resp_phrase_ptr;
126140cb5e5dSvi117747 		}
126240cb5e5dSvi117747 		sip_msg_info->is_request = B_FALSE;
126340cb5e5dSvi117747 	} else {
126440cb5e5dSvi117747 		int i;
126540cb5e5dSvi117747 		/*
126640cb5e5dSvi117747 		 * It's a request.
126740cb5e5dSvi117747 		 */
126840cb5e5dSvi117747 		sip_msg_info->is_request = B_TRUE;
126940cb5e5dSvi117747 		for (i = 1; i < MAX_SIP_METHODS; i++) {
127040cb5e5dSvi117747 			if (strncmp(sip_methods[i].name,
127140cb5e5dSvi117747 			    sip_header->sip_hdr_current,
127240cb5e5dSvi117747 			    sip_methods[i].len) == 0) {
127340cb5e5dSvi117747 				sip_msg_info->sip_req_method = i;
127440cb5e5dSvi117747 				sip_header->sip_hdr_current +=
127540cb5e5dSvi117747 				    sip_methods[i].len;
127640cb5e5dSvi117747 				if (!isspace(*sip_header->sip_hdr_current++) ||
127740cb5e5dSvi117747 				    !isalpha(*sip_header->sip_hdr_current)) {
127840cb5e5dSvi117747 					free(sip_msg_info);
127940cb5e5dSvi117747 					return (EPROTO);
128040cb5e5dSvi117747 				}
128140cb5e5dSvi117747 
128240cb5e5dSvi117747 				if ((ret = _sip_get_request_uri(sip_header,
128340cb5e5dSvi117747 				    sip_msg_info)) != 0) {
128440cb5e5dSvi117747 					free(sip_msg_info);
128540cb5e5dSvi117747 					return (ret);
128640cb5e5dSvi117747 				}
128740cb5e5dSvi117747 
128840cb5e5dSvi117747 				/*
128940cb5e5dSvi117747 				 * Get SIP version
129040cb5e5dSvi117747 				 */
129140cb5e5dSvi117747 				ret = sip_get_protocol_version(sip_header,
129240cb5e5dSvi117747 				    &sip_msg_info->sip_proto_version);
129340cb5e5dSvi117747 				if (ret != 0) {
129440cb5e5dSvi117747 					free(sip_msg_info);
129540cb5e5dSvi117747 					return (EPROTO);
129640cb5e5dSvi117747 				}
129740cb5e5dSvi117747 				goto done;
129840cb5e5dSvi117747 			}
129940cb5e5dSvi117747 		}
130040cb5e5dSvi117747 		free(sip_msg_info);
130140cb5e5dSvi117747 		return (EPROTO);
130240cb5e5dSvi117747 	}
130340cb5e5dSvi117747 done:
130440cb5e5dSvi117747 	sip_msg_info->sip_next = *msg_info;
130540cb5e5dSvi117747 	*msg_info = sip_msg_info;
130640cb5e5dSvi117747 	return (0);
130740cb5e5dSvi117747 }
1308