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