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