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 <ctype.h>
282c2c4183Svi #include <errno.h>
292c2c4183Svi #include <stdlib.h>
302c2c4183Svi #include <strings.h>
312c2c4183Svi #include <sip.h>
322c2c4183Svi
3340cb5e5dSvi #include "sip_msg.h"
3440cb5e5dSvi #include "sip_miscdefs.h"
3540cb5e5dSvi #include "sip_parse_generic.h"
362c2c4183Svi #include "sip_parse_uri.h"
372c2c4183Svi
3840cb5e5dSvi
3940cb5e5dSvi /*
4040cb5e5dSvi * Accept = "Accept" HCOLON [ accept-range *(COMMA accept-range) ]
4140cb5e5dSvi * accept-range = media-range *(SEMI accept-param)
4240cb5e5dSvi * media-range = ("* / *" | (m-type SLASH "*") | (m-type SLASH m-subtype))
4340cb5e5dSvi * *(SEMI m-param)
4440cb5e5dSvi * accept-param = ("q" EQUAL qvalue) | generic-param
4540cb5e5dSvi * qvalue = ("0" ["." 0*3DIGIT]) | ("1" ["." 0*3DIGIT])
4640cb5e5dSvi * generic-param = token [ EQUAL gen-value]
4740cb5e5dSvi * gen-value = token | host | quoted-str
4840cb5e5dSvi */
4940cb5e5dSvi int
sip_parse_acpt_header(_sip_header_t * sip_header,sip_parsed_header_t ** header)5040cb5e5dSvi sip_parse_acpt_header(_sip_header_t *sip_header, sip_parsed_header_t **header)
5140cb5e5dSvi {
5240cb5e5dSvi if (sip_is_empty_hdr(sip_header))
5340cb5e5dSvi return (sip_parse_hdr_empty(sip_header, header));
5440cb5e5dSvi return (sip_parse_hdr_parser1(sip_header, header, SIP_SLASH));
5540cb5e5dSvi }
5640cb5e5dSvi
5740cb5e5dSvi /*
5840cb5e5dSvi * Accept-Encoding = "Accept-Encoding" ":" 1#(codings [ ";" "q" "=" qval])
5940cb5e5dSvi * codings = (content-coding | "*")
6040cb5e5dSvi * content-coding = token
6140cb5e5dSvi */
6240cb5e5dSvi int
sip_parse_acpt_encode_header(_sip_header_t * sip_header,sip_parsed_header_t ** header)6340cb5e5dSvi sip_parse_acpt_encode_header(_sip_header_t *sip_header,
64*559f8b54SToomas Soome sip_parsed_header_t **header)
6540cb5e5dSvi {
66*559f8b54SToomas Soome return (sip_parse_hdr_parser1(sip_header, header, 0));
6740cb5e5dSvi }
6840cb5e5dSvi
6940cb5e5dSvi /*
7040cb5e5dSvi * Accept-Language = "Accept-Language" ":" [ lang * (COMMA lang) ]
7140cb5e5dSvi * lang = lang-range *(SEMI accept-param)
7240cb5e5dSvi * lang-range = ((1*8ALPHA * ("-" 1*8ALPHA)) | "*"
7340cb5e5dSvi */
7440cb5e5dSvi int
sip_parse_acpt_lang_header(_sip_header_t * sip_header,sip_parsed_header_t ** header)7540cb5e5dSvi sip_parse_acpt_lang_header(_sip_header_t *sip_header,
76*559f8b54SToomas Soome sip_parsed_header_t **header)
7740cb5e5dSvi {
7840cb5e5dSvi if (sip_is_empty_hdr(sip_header))
7940cb5e5dSvi return (sip_parse_hdr_empty(sip_header, header));
80*559f8b54SToomas Soome return (sip_parse_hdr_parser1(sip_header, header, 0));
8140cb5e5dSvi }
8240cb5e5dSvi
8340cb5e5dSvi /*
8440cb5e5dSvi * Alert-Info = "Alert-Info" ":" alert-param *(COMMA alert-param)
8540cb5e5dSvi * alert-param = LAQUOT absoluteURI RAQUOT * (SEMI generic-param)
8640cb5e5dSvi */
8740cb5e5dSvi int
sip_parse_alert_header(_sip_header_t * sip_header,sip_parsed_header_t ** header)8840cb5e5dSvi sip_parse_alert_header(_sip_header_t *sip_header, sip_parsed_header_t **header)
8940cb5e5dSvi {
9040cb5e5dSvi return (sip_parse_hdr_parser3(sip_header, header, SIP_STR_VAL, B_TRUE));
9140cb5e5dSvi }
9240cb5e5dSvi
9340cb5e5dSvi /*
9440cb5e5dSvi * Allow = "Allow" ":" method-name1[, method-name2..]
9540cb5e5dSvi */
9640cb5e5dSvi int
sip_parse_allow_header(_sip_header_t * hdr,sip_parsed_header_t ** phdr)9740cb5e5dSvi sip_parse_allow_header(_sip_header_t *hdr, sip_parsed_header_t **phdr)
9840cb5e5dSvi {
9940cb5e5dSvi sip_parsed_header_t *parsed_header;
10040cb5e5dSvi sip_hdr_value_t *value = NULL;
10140cb5e5dSvi sip_hdr_value_t *last_value = NULL;
10240cb5e5dSvi int len;
10340cb5e5dSvi int i;
10440cb5e5dSvi int ret;
10540cb5e5dSvi boolean_t multi_value = B_FALSE;
10640cb5e5dSvi
10740cb5e5dSvi if ((ret = sip_prim_parsers(hdr, phdr)) != 0)
10840cb5e5dSvi return (ret);
10940cb5e5dSvi
11040cb5e5dSvi if (*phdr != NULL)
11140cb5e5dSvi return (0);
11240cb5e5dSvi
11340cb5e5dSvi parsed_header = calloc(1, sizeof (sip_parsed_header_t));
11440cb5e5dSvi if (parsed_header == NULL)
11540cb5e5dSvi return (ENOMEM);
11640cb5e5dSvi parsed_header->sip_parsed_header_version = SIP_PARSED_HEADER_VERSION_1;
11740cb5e5dSvi parsed_header->sip_header = hdr;
11840cb5e5dSvi
11940cb5e5dSvi while (hdr->sip_hdr_current < hdr->sip_hdr_end) {
12040cb5e5dSvi value = calloc(1, sizeof (sip_hdr_value_t));
12140cb5e5dSvi if (value == NULL) {
12240cb5e5dSvi sip_free_phdr(parsed_header);
12340cb5e5dSvi return (ENOMEM);
12440cb5e5dSvi }
12540cb5e5dSvi if (last_value != NULL)
12640cb5e5dSvi last_value->sip_next_value = value;
12740cb5e5dSvi else
12840cb5e5dSvi parsed_header->value = (sip_value_t *)value;
12940cb5e5dSvi
13040cb5e5dSvi value->sip_value_start = hdr->sip_hdr_current;
13140cb5e5dSvi value->sip_value_header = parsed_header;
13240cb5e5dSvi
133*559f8b54SToomas Soome if (sip_find_separator(hdr, SIP_COMMA, 0, 0, B_FALSE) == 0) {
13440cb5e5dSvi multi_value = B_TRUE;
13540cb5e5dSvi }
13640cb5e5dSvi
13740cb5e5dSvi len = hdr->sip_hdr_current - value->sip_value_start;
13840cb5e5dSvi for (i = 1; i < MAX_SIP_METHODS; i++) {
13940cb5e5dSvi if (strncmp(sip_methods[i].name, value->sip_value_start,
14040cb5e5dSvi len) == 0) {
14140cb5e5dSvi break;
14240cb5e5dSvi }
14340cb5e5dSvi }
14440cb5e5dSvi if (i >= MAX_SIP_METHODS) {
14540cb5e5dSvi value->int_val = 0;
14640cb5e5dSvi value->sip_value_state = SIP_VALUE_BAD;
14740cb5e5dSvi if (multi_value)
14840cb5e5dSvi goto next_val;
14940cb5e5dSvi else
15040cb5e5dSvi goto end;
15140cb5e5dSvi }
15240cb5e5dSvi value->int_val = i;
15340cb5e5dSvi if (!multi_value)
15440cb5e5dSvi goto end;
15540cb5e5dSvi next_val:
15640cb5e5dSvi if (sip_find_token(hdr, SIP_COMMA) != 0)
15740cb5e5dSvi break;
15840cb5e5dSvi value->sip_value_end = hdr->sip_hdr_current - 1;
15940cb5e5dSvi last_value = value;
16040cb5e5dSvi (void) sip_skip_white_space(hdr);
16140cb5e5dSvi }
16240cb5e5dSvi
16340cb5e5dSvi end:
16440cb5e5dSvi *phdr = parsed_header;
16540cb5e5dSvi return (0);
16640cb5e5dSvi }
16740cb5e5dSvi
16840cb5e5dSvi
16940cb5e5dSvi /*
17040cb5e5dSvi * Call-Info = "Call-Info" HCOLON info * (COMMA info)
17140cb5e5dSvi * info = LAQUOT absoluteURI RAQUOT * (SEMI info-param)
17240cb5e5dSvi * info-param = ("purpose" EQUAL ("icon" | "info" | "card" | token)) |
17340cb5e5dSvi * generic-param
17440cb5e5dSvi */
17540cb5e5dSvi int
sip_parse_callinfo_header(_sip_header_t * sip_header,sip_parsed_header_t ** header)17640cb5e5dSvi sip_parse_callinfo_header(_sip_header_t *sip_header,
17740cb5e5dSvi sip_parsed_header_t **header)
17840cb5e5dSvi {
17940cb5e5dSvi return (sip_parse_hdr_parser3(sip_header, header, SIP_STR_VAL, B_TRUE));
18040cb5e5dSvi }
18140cb5e5dSvi
18240cb5e5dSvi /*
18340cb5e5dSvi * Content-Disposition = "Content-Disposition" HCOLON disp-type *
18440cb5e5dSvi * (SEMI disp-param)
18540cb5e5dSvi * disp-type = "render" | "session" | "icon" | "alert" | disp-ext-token
18640cb5e5dSvi * disp-param = handling-param | generic-param
18740cb5e5dSvi * handling-param = "handling" EQUAL("optional" | "required" | other-handling)
18840cb5e5dSvi * other-handling = token
18940cb5e5dSvi * disp-ext-token = token
19040cb5e5dSvi *
19140cb5e5dSvi */
19240cb5e5dSvi int
sip_parse_contentdis_header(_sip_header_t * sip_header,sip_parsed_header_t ** header)19340cb5e5dSvi sip_parse_contentdis_header(_sip_header_t *sip_header,
19440cb5e5dSvi sip_parsed_header_t **header)
19540cb5e5dSvi {
196*559f8b54SToomas Soome return (sip_parse_hdr_parser1(sip_header, header, 0));
19740cb5e5dSvi }
19840cb5e5dSvi
19940cb5e5dSvi /*
20040cb5e5dSvi * Content-Encoding = ("Content-Encoding" | "e") HCOLON content-coding *
20140cb5e5dSvi * (COMMA content-coding)
20240cb5e5dSvi */
20340cb5e5dSvi int
sip_parse_contentencode_header(_sip_header_t * sip_header,sip_parsed_header_t ** header)20440cb5e5dSvi sip_parse_contentencode_header(_sip_header_t *sip_header,
20540cb5e5dSvi sip_parsed_header_t **header)
20640cb5e5dSvi {
207*559f8b54SToomas Soome return (sip_parse_hdr_parser1(sip_header, header, 0));
20840cb5e5dSvi }
20940cb5e5dSvi
21040cb5e5dSvi /*
21140cb5e5dSvi * Content-Language = ("Content-Language" | "l") HCOLON lang-tag *
21240cb5e5dSvi * (COMMA lang-tag)
21340cb5e5dSvi * lang-tag = primary-tag *("-" subtag)
21440cb5e5dSvi * prmary-tag = 1*8ALPHA
21540cb5e5dSvi * subtag = 1*8ALPHA
21640cb5e5dSvi */
21740cb5e5dSvi int
sip_parse_contentlang_header(_sip_header_t * sip_header,sip_parsed_header_t ** header)21840cb5e5dSvi sip_parse_contentlang_header(_sip_header_t *sip_header,
21940cb5e5dSvi sip_parsed_header_t **header)
22040cb5e5dSvi {
221*559f8b54SToomas Soome return (sip_parse_hdr_parser1(sip_header, header, 0));
22240cb5e5dSvi }
22340cb5e5dSvi
22440cb5e5dSvi /*
22540cb5e5dSvi * Date = "Date" HCOLON SIPdate
22640cb5e5dSvi * SIPdate = wkday "," SP date1 SP time SP "GMT"
22740cb5e5dSvi * date1 = 2DIGIT SP mnth SP 4DIGIT; day month year
22840cb5e5dSvi * time = 2DIGIT ":" 2DIGIT ":" 2DIGIT
22940cb5e5dSvi * wkday = "Mon" | "Tue" | "Wed" | "Thu" | "Fri" | "Sat" | "Sun"
23040cb5e5dSvi * month = "Jan" | "Feb" etc
23140cb5e5dSvi */
23240cb5e5dSvi int
sip_parse_date_header(_sip_header_t * sip_header,sip_parsed_header_t ** header)23340cb5e5dSvi sip_parse_date_header(_sip_header_t *sip_header, sip_parsed_header_t **header)
23440cb5e5dSvi {
23540cb5e5dSvi sip_parsed_header_t *parsed_header;
23640cb5e5dSvi int r;
23740cb5e5dSvi sip_hdr_value_t *value = NULL;
23840cb5e5dSvi
23940cb5e5dSvi if ((r = sip_prim_parsers(sip_header, header)) != 0)
24040cb5e5dSvi return (r);
24140cb5e5dSvi
24240cb5e5dSvi if (*header != NULL)
24340cb5e5dSvi return (0);
24440cb5e5dSvi
24540cb5e5dSvi parsed_header = calloc(1, sizeof (sip_parsed_header_t));
24640cb5e5dSvi if (parsed_header == NULL)
24740cb5e5dSvi return (ENOMEM);
24840cb5e5dSvi parsed_header->sip_parsed_header_version = SIP_PARSED_HEADER_VERSION_1;
24940cb5e5dSvi parsed_header->sip_header = sip_header;
25040cb5e5dSvi
25140cb5e5dSvi value = calloc(1, sizeof (sip_hdr_value_t));
25240cb5e5dSvi if (value == NULL) {
25340cb5e5dSvi sip_free_phdr(parsed_header);
25440cb5e5dSvi return (ENOMEM);
25540cb5e5dSvi }
25640cb5e5dSvi parsed_header->value = (sip_value_t *)value;
25740cb5e5dSvi
25840cb5e5dSvi value->sip_value_start = sip_header->sip_hdr_current;
25940cb5e5dSvi value->sip_value_header = parsed_header;
26040cb5e5dSvi value->date_wd_ptr = sip_header->sip_hdr_current;
26140cb5e5dSvi if (sip_find_token(sip_header, SIP_COMMA) == 0) {
26240cb5e5dSvi value->date_wd_len = sip_header->sip_hdr_current -
26340cb5e5dSvi value->date_wd_ptr - 1;
26440cb5e5dSvi sip_header->sip_hdr_current++;
26540cb5e5dSvi if (sip_skip_white_space(sip_header) != 0) {
26640cb5e5dSvi value->sip_value_state = SIP_VALUE_BAD;
26740cb5e5dSvi return (EPROTO);
26840cb5e5dSvi }
26940cb5e5dSvi } else {
27040cb5e5dSvi value->sip_value_state = SIP_VALUE_BAD;
27140cb5e5dSvi return (EPROTO);
27240cb5e5dSvi }
27340cb5e5dSvi
27440cb5e5dSvi if (sip_skip_white_space(sip_header) != 0) {
27540cb5e5dSvi value->sip_value_state = SIP_VALUE_BAD;
27640cb5e5dSvi return (EPROTO);
27740cb5e5dSvi }
27840cb5e5dSvi r = sip_atoi(sip_header, &value->date_d);
27940cb5e5dSvi if (r != 0 || value->date_d < 0 || value->date_d > 31) {
28040cb5e5dSvi value->sip_value_state = SIP_VALUE_BAD;
28140cb5e5dSvi return (EPROTO);
28240cb5e5dSvi }
28340cb5e5dSvi if (sip_skip_white_space(sip_header) != 0) {
28440cb5e5dSvi value->sip_value_state = SIP_VALUE_BAD;
28540cb5e5dSvi return (EPROTO);
28640cb5e5dSvi }
28740cb5e5dSvi value->date_m_ptr = sip_header->sip_hdr_current;
28840cb5e5dSvi if (sip_find_token(sip_header, SIP_SP) == 0) {
28940cb5e5dSvi value->date_m_len = sip_header->sip_hdr_current -
29040cb5e5dSvi value->date_m_ptr - 1;
29140cb5e5dSvi } else {
29240cb5e5dSvi value->sip_value_state = SIP_VALUE_BAD;
29340cb5e5dSvi return (EPROTO);
29440cb5e5dSvi }
29540cb5e5dSvi
29640cb5e5dSvi r = sip_atoi(sip_header, &value->date_y);
29740cb5e5dSvi if (r != 0 || value->date_y < 0) {
29840cb5e5dSvi value->sip_value_state = SIP_VALUE_BAD;
29940cb5e5dSvi return (EPROTO);
30040cb5e5dSvi }
30140cb5e5dSvi if (sip_skip_white_space(sip_header) != 0) {
30240cb5e5dSvi value->sip_value_state = SIP_VALUE_BAD;
30340cb5e5dSvi return (EPROTO);
30440cb5e5dSvi }
30540cb5e5dSvi value->date_t_ptr = sip_header->sip_hdr_current;
30640cb5e5dSvi if (sip_find_token(sip_header, SIP_SP) == 0) {
30740cb5e5dSvi value->date_t_len = sip_header->sip_hdr_current -
30840cb5e5dSvi value->date_t_ptr - 1;
30940cb5e5dSvi } else {
31040cb5e5dSvi value->sip_value_state = SIP_VALUE_BAD;
31140cb5e5dSvi return (EPROTO);
31240cb5e5dSvi }
31340cb5e5dSvi
31440cb5e5dSvi value->date_tz_ptr = sip_header->sip_hdr_current;
31540cb5e5dSvi /*
31640cb5e5dSvi * minus 2 to get rid of the CRLF
31740cb5e5dSvi */
31840cb5e5dSvi value->date_tz_len = sip_header->sip_hdr_end -
31940cb5e5dSvi sip_header->sip_hdr_current - 2;
32040cb5e5dSvi
32140cb5e5dSvi *header = parsed_header;
32240cb5e5dSvi
32340cb5e5dSvi sip_header->sip_hdr_parsed = *header;
32440cb5e5dSvi return (0);
32540cb5e5dSvi }
32640cb5e5dSvi
32740cb5e5dSvi /*
32840cb5e5dSvi * Error-Info = "Error-Info" HCOLON error-uri *(COMMA error-uri)
32940cb5e5dSvi * error-uri = LAQUOT absoluteURI RAQUOT *(SEMI generic-param)
33040cb5e5dSvi */
33140cb5e5dSvi int
sip_parse_errorinfo_header(_sip_header_t * sip_header,sip_parsed_header_t ** header)33240cb5e5dSvi sip_parse_errorinfo_header(_sip_header_t *sip_header,
33340cb5e5dSvi sip_parsed_header_t **header)
33440cb5e5dSvi {
33540cb5e5dSvi return (sip_parse_hdr_parser3(sip_header, header, SIP_STR_VAL, B_TRUE));
33640cb5e5dSvi }
33740cb5e5dSvi
33840cb5e5dSvi /*
33940cb5e5dSvi * Expires = "Expires" HCOLON delta-seconds
34040cb5e5dSvi */
34140cb5e5dSvi int
sip_parse_expire_header(_sip_header_t * sip_header,sip_parsed_header_t ** header)34240cb5e5dSvi sip_parse_expire_header(_sip_header_t *sip_header,
34340cb5e5dSvi sip_parsed_header_t **header)
34440cb5e5dSvi {
34540cb5e5dSvi return (sip_parse_hdr_parser2(sip_header, header, SIP_INT_VAL));
34640cb5e5dSvi }
34740cb5e5dSvi
34840cb5e5dSvi /*
34940cb5e5dSvi * In-Reply-To = "In-Reply-To" HCOLON callid *(COMMA callid)
35040cb5e5dSvi */
35140cb5e5dSvi int
sip_parse_inreplyto_header(_sip_header_t * sip_header,sip_parsed_header_t ** header)35240cb5e5dSvi sip_parse_inreplyto_header(_sip_header_t *sip_header,
35340cb5e5dSvi sip_parsed_header_t **header)
35440cb5e5dSvi {
355*559f8b54SToomas Soome return (sip_parse_hdr_parser1(sip_header, header, 0));
35640cb5e5dSvi }
35740cb5e5dSvi
35840cb5e5dSvi /*
35940cb5e5dSvi * RSeq = "RSeq" HCOLON response-num
36040cb5e5dSvi */
36140cb5e5dSvi int
sip_parse_rseq(_sip_header_t * sip_header,sip_parsed_header_t ** header)36240cb5e5dSvi sip_parse_rseq(_sip_header_t *sip_header, sip_parsed_header_t **header)
36340cb5e5dSvi {
36440cb5e5dSvi int r;
36540cb5e5dSvi sip_hdr_value_t *rseq_value;
36640cb5e5dSvi
36740cb5e5dSvi r = sip_parse_hdr_parser2(sip_header, header, SIP_INT_VAL);
36840cb5e5dSvi /*
36940cb5e5dSvi * Additionally, a value of 0 is bad_value
37040cb5e5dSvi */
37140cb5e5dSvi if (sip_header->sip_hdr_parsed != NULL &&
37240cb5e5dSvi sip_header->sip_hdr_parsed->value != NULL) {
37340cb5e5dSvi rseq_value = (sip_hdr_value_t *)
37440cb5e5dSvi sip_header->sip_hdr_parsed->value;
37540cb5e5dSvi if (rseq_value->int_val == 0)
37640cb5e5dSvi rseq_value->sip_value_state = SIP_VALUE_BAD;
37740cb5e5dSvi }
37840cb5e5dSvi return (r);
37940cb5e5dSvi }
38040cb5e5dSvi
38140cb5e5dSvi /*
38240cb5e5dSvi * Min-Expires = "Min-Expires" HCOLON delta-seconds
38340cb5e5dSvi */
38440cb5e5dSvi int
sip_parse_minexpire_header(_sip_header_t * sip_header,sip_parsed_header_t ** header)38540cb5e5dSvi sip_parse_minexpire_header(_sip_header_t *sip_header,
38640cb5e5dSvi sip_parsed_header_t **header)
38740cb5e5dSvi {
38840cb5e5dSvi return (sip_parse_hdr_parser2(sip_header, header, SIP_INT_VAL));
38940cb5e5dSvi }
39040cb5e5dSvi
39140cb5e5dSvi /*
39240cb5e5dSvi * MIME-Version = "MIME-Version" HCOLON 1*DIGIT "." 1*DIGIT
39340cb5e5dSvi */
39440cb5e5dSvi int
sip_parse_mimeversion_header(_sip_header_t * sip_header,sip_parsed_header_t ** header)39540cb5e5dSvi sip_parse_mimeversion_header(_sip_header_t *sip_header,
39640cb5e5dSvi sip_parsed_header_t **header)
39740cb5e5dSvi {
39840cb5e5dSvi return (sip_parse_hdr_parser4(sip_header, header));
39940cb5e5dSvi }
40040cb5e5dSvi
40140cb5e5dSvi /*
40240cb5e5dSvi * Organization = "Organization" HCOLON [TEXT-UTF8-TRIM]
40340cb5e5dSvi */
40440cb5e5dSvi int
sip_parse_org_header(_sip_header_t * sip_header,sip_parsed_header_t ** header)40540cb5e5dSvi sip_parse_org_header(_sip_header_t *sip_header,
40640cb5e5dSvi sip_parsed_header_t **header)
40740cb5e5dSvi {
40840cb5e5dSvi if (sip_is_empty_hdr(sip_header))
40940cb5e5dSvi return (sip_parse_hdr_empty(sip_header, header));
41040cb5e5dSvi return (sip_parse_hdr_parser4(sip_header, header));
41140cb5e5dSvi }
41240cb5e5dSvi
41340cb5e5dSvi /*
41440cb5e5dSvi * Priority = "Priority" HCOLON priority-val
41540cb5e5dSvi * priority-val = "emergency" | "urgent" | "normal" | "non-urgent" | other
41640cb5e5dSvi * other = token
41740cb5e5dSvi */
41840cb5e5dSvi int
sip_parse_priority_header(_sip_header_t * sip_header,sip_parsed_header_t ** header)41940cb5e5dSvi sip_parse_priority_header(_sip_header_t *sip_header,
42040cb5e5dSvi sip_parsed_header_t **header)
42140cb5e5dSvi {
42240cb5e5dSvi return (sip_parse_hdr_parser4(sip_header, header));
42340cb5e5dSvi }
42440cb5e5dSvi
42540cb5e5dSvi /*
42640cb5e5dSvi * Reply-To = "Reply-To" HCOLON rplyto-spec
42740cb5e5dSvi * rplyto-spec = (name-addr | addr-spec) *(SEMI rplyto-param)
42840cb5e5dSvi * rplyto-param = generic-param
42940cb5e5dSvi * name-addr = [ display-name ] LAQUOT addr-spec RAQUOT
43040cb5e5dSvi * addr-spec = SIP-URI | SIPS-URI | absolute URI
43140cb5e5dSvi */
43240cb5e5dSvi int
sip_parse_replyto_header(_sip_header_t * sip_header,sip_parsed_header_t ** header)43340cb5e5dSvi sip_parse_replyto_header(_sip_header_t *sip_header,
43440cb5e5dSvi sip_parsed_header_t **header)
43540cb5e5dSvi {
43640cb5e5dSvi return (sip_parse_hdr_parser3(sip_header, header, SIP_STRS_VAL,
43740cb5e5dSvi B_TRUE));
43840cb5e5dSvi }
43940cb5e5dSvi
44040cb5e5dSvi /*
44140cb5e5dSvi * PRIVACY = "Privacy" HCOLON priv-value *(COMMA priv-value)
44240cb5e5dSvi * priv-value = "header" / "session" / "user" / "none" / "critical"
44340cb5e5dSvi * / token / id
44440cb5e5dSvi */
44540cb5e5dSvi int
sip_parse_privacy_header(_sip_header_t * sip_header,sip_parsed_header_t ** header)44640cb5e5dSvi sip_parse_privacy_header(_sip_header_t *sip_header,
44740cb5e5dSvi sip_parsed_header_t **header)
44840cb5e5dSvi {
449*559f8b54SToomas Soome return (sip_parse_hdr_parser1(sip_header, header, 0));
45040cb5e5dSvi }
45140cb5e5dSvi
45240cb5e5dSvi
45340cb5e5dSvi /*
45440cb5e5dSvi * Require = "Require" HCOLON option-tag * (COMMA option-tag)
45540cb5e5dSvi */
45640cb5e5dSvi int
sip_parse_require_header(_sip_header_t * sip_header,sip_parsed_header_t ** header)45740cb5e5dSvi sip_parse_require_header(_sip_header_t *sip_header,
45840cb5e5dSvi sip_parsed_header_t **header)
45940cb5e5dSvi {
460*559f8b54SToomas Soome return (sip_parse_hdr_parser1(sip_header, header, 0));
46140cb5e5dSvi }
46240cb5e5dSvi
46340cb5e5dSvi /*
46440cb5e5dSvi * Retry-After = "Retry-After" HCOLON delta-seconds [ comment ] *
46540cb5e5dSvi * (SEMI retry-param)
46640cb5e5dSvi * retry-param = "duration" EQUAL delta-seconds
46740cb5e5dSvi */
46840cb5e5dSvi int
sip_parse_retryaft_header(_sip_header_t * sip_header,sip_parsed_header_t ** header)46940cb5e5dSvi sip_parse_retryaft_header(_sip_header_t *sip_header,
47040cb5e5dSvi sip_parsed_header_t **header)
47140cb5e5dSvi {
47240cb5e5dSvi sip_parsed_header_t *parsed_header;
47340cb5e5dSvi sip_hdr_value_t *value = NULL;
47440cb5e5dSvi int ret;
47540cb5e5dSvi
47640cb5e5dSvi if ((ret = sip_prim_parsers(sip_header, header)) != 0)
47740cb5e5dSvi return (ret);
47840cb5e5dSvi
47940cb5e5dSvi if (*header != NULL)
48040cb5e5dSvi return (0);
48140cb5e5dSvi
48240cb5e5dSvi parsed_header = calloc(1, sizeof (sip_parsed_header_t));
48340cb5e5dSvi if (parsed_header == NULL)
48440cb5e5dSvi return (ENOMEM);
48540cb5e5dSvi parsed_header->sip_parsed_header_version = SIP_PARSED_HEADER_VERSION_1;
48640cb5e5dSvi parsed_header->sip_header = sip_header;
48740cb5e5dSvi
48840cb5e5dSvi value = calloc(1, sizeof (sip_hdr_value_t));
48940cb5e5dSvi if (value == NULL) {
49040cb5e5dSvi sip_free_phdr(parsed_header);
49140cb5e5dSvi return (ENOMEM);
49240cb5e5dSvi }
49340cb5e5dSvi
49440cb5e5dSvi parsed_header->value = (sip_value_t *)value;
49540cb5e5dSvi value->sip_value_start = sip_header->sip_hdr_current;
49640cb5e5dSvi value->sip_value_header = parsed_header;
49740cb5e5dSvi
49840cb5e5dSvi ret = sip_atoi(sip_header, &(value->intstr_int));
49940cb5e5dSvi if (ret != 0)
50040cb5e5dSvi value->sip_value_state = SIP_VALUE_BAD;
50140cb5e5dSvi if (sip_find_token(sip_header, SIP_LPAR) == 0) {
50240cb5e5dSvi value->intstr_str_ptr = sip_header->sip_hdr_current;
50340cb5e5dSvi if (sip_find_token(sip_header, SIP_RPAR) == 0) {
50440cb5e5dSvi value->intstr_str_len =
50540cb5e5dSvi sip_header->sip_hdr_current -
506df4705eaSgm value->intstr_str_ptr - 1;
50740cb5e5dSvi if (sip_find_token(sip_header, SIP_SEMI) == 0) {
50840cb5e5dSvi sip_header->sip_hdr_current--;
50940cb5e5dSvi (void) sip_parse_params(sip_header,
51040cb5e5dSvi &(value->sip_param_list));
51140cb5e5dSvi }
51240cb5e5dSvi } else {
51340cb5e5dSvi value->sip_value_state = SIP_VALUE_BAD;
51440cb5e5dSvi return (EPROTO);
51540cb5e5dSvi }
51640cb5e5dSvi } else {
51740cb5e5dSvi value->intstr_str_ptr = NULL;
51840cb5e5dSvi value->intstr_str_len = 0;
51940cb5e5dSvi
52040cb5e5dSvi /*
52140cb5e5dSvi * from value start, search if parameter list
52240cb5e5dSvi */
52340cb5e5dSvi sip_header->sip_hdr_current = value->sip_value_start;
52440cb5e5dSvi if (sip_find_token(sip_header, SIP_SEMI) == 0) {
52540cb5e5dSvi sip_header->sip_hdr_current--;
52640cb5e5dSvi (void) sip_parse_params(sip_header,
52740cb5e5dSvi &(value->sip_param_list));
52840cb5e5dSvi }
52940cb5e5dSvi }
53040cb5e5dSvi
53140cb5e5dSvi *header = parsed_header;
53240cb5e5dSvi sip_header->sip_hdr_parsed = *header;
53340cb5e5dSvi return (0);
53440cb5e5dSvi }
53540cb5e5dSvi
53640cb5e5dSvi /*
53740cb5e5dSvi * Server = "Server" HCOLON servel-val *(LWS server-val)
53840cb5e5dSvi * servel-val = product|comment
53940cb5e5dSvi * product = token [SLASH version]
54040cb5e5dSvi * version = token
54140cb5e5dSvi * Treated as one single string
54240cb5e5dSvi */
54340cb5e5dSvi int
sip_parse_server_header(_sip_header_t * sip_header,sip_parsed_header_t ** header)54440cb5e5dSvi sip_parse_server_header(_sip_header_t *sip_header, sip_parsed_header_t **header)
54540cb5e5dSvi {
54640cb5e5dSvi return (sip_parse_hdr_parser4(sip_header, header));
54740cb5e5dSvi }
54840cb5e5dSvi
54940cb5e5dSvi /*
55040cb5e5dSvi * Subject = ("Subject" | "s")HCOLON [TEXT-UTF8-TRIM]
55140cb5e5dSvi */
55240cb5e5dSvi int
sip_parse_subject_header(_sip_header_t * sip_header,sip_parsed_header_t ** header)55340cb5e5dSvi sip_parse_subject_header(_sip_header_t *sip_header,
55440cb5e5dSvi sip_parsed_header_t **header)
55540cb5e5dSvi {
55640cb5e5dSvi if (sip_is_empty_hdr(sip_header))
55740cb5e5dSvi return (sip_parse_hdr_empty(sip_header, header));
55840cb5e5dSvi return (sip_parse_hdr_parser4(sip_header, header));
55940cb5e5dSvi }
56040cb5e5dSvi
56140cb5e5dSvi /*
56240cb5e5dSvi * Supported = ("Supported" | "k") HCOLON [option-tag * (COMMA option-tag) ]
56340cb5e5dSvi */
56440cb5e5dSvi int
sip_parse_support_header(_sip_header_t * sip_header,sip_parsed_header_t ** header)56540cb5e5dSvi sip_parse_support_header(_sip_header_t *sip_header,
56640cb5e5dSvi sip_parsed_header_t **header)
56740cb5e5dSvi {
56840cb5e5dSvi if (sip_is_empty_hdr(sip_header))
56940cb5e5dSvi return (sip_parse_hdr_empty(sip_header, header));
570*559f8b54SToomas Soome return (sip_parse_hdr_parser1(sip_header, header, 0));
57140cb5e5dSvi }
57240cb5e5dSvi
57340cb5e5dSvi /*
57440cb5e5dSvi * Timestamp = "Timestamp" HCOLON 1*DIGIT ["." *(DIGIT)] [LWS delay]
57540cb5e5dSvi */
57640cb5e5dSvi int
sip_parse_timestamp_header(_sip_header_t * sip_header,sip_parsed_header_t ** header)57740cb5e5dSvi sip_parse_timestamp_header(_sip_header_t *sip_header,
57840cb5e5dSvi sip_parsed_header_t **header)
57940cb5e5dSvi {
58040cb5e5dSvi sip_parsed_header_t *parsed_header;
58140cb5e5dSvi sip_hdr_value_t *value = NULL;
58240cb5e5dSvi int ret;
58340cb5e5dSvi
58440cb5e5dSvi if ((ret = sip_prim_parsers(sip_header, header)) != 0)
58540cb5e5dSvi return (ret);
58640cb5e5dSvi
58740cb5e5dSvi if (*header != NULL)
58840cb5e5dSvi return (0);
58940cb5e5dSvi
59040cb5e5dSvi parsed_header = calloc(1, sizeof (sip_parsed_header_t));
59140cb5e5dSvi if (parsed_header == NULL)
59240cb5e5dSvi return (ENOMEM);
59340cb5e5dSvi parsed_header->sip_parsed_header_version = SIP_PARSED_HEADER_VERSION_1;
59440cb5e5dSvi parsed_header->sip_header = sip_header;
59540cb5e5dSvi
59640cb5e5dSvi value = calloc(1, sizeof (sip_hdr_value_t));
59740cb5e5dSvi if (value == NULL) {
59840cb5e5dSvi sip_free_phdr(parsed_header);
59940cb5e5dSvi return (ENOMEM);
60040cb5e5dSvi }
60140cb5e5dSvi parsed_header->value = (sip_value_t *)value;
60240cb5e5dSvi
60340cb5e5dSvi value->sip_value_start = sip_header->sip_hdr_current;
60440cb5e5dSvi value->sip_value_header = parsed_header;
60540cb5e5dSvi
60640cb5e5dSvi if (sip_skip_white_space(sip_header) != 0) {
60740cb5e5dSvi value->sip_value_state = SIP_VALUE_BAD;
60840cb5e5dSvi return (EPROTO);
60940cb5e5dSvi }
61040cb5e5dSvi value->strs1_val_ptr = sip_header->sip_hdr_current;
61140cb5e5dSvi
61240cb5e5dSvi if (sip_find_white_space(sip_header) == 0) {
61340cb5e5dSvi /*
61440cb5e5dSvi * timestamp and delay, timestamp in str1, delay in str2
61540cb5e5dSvi */
61640cb5e5dSvi value->strs1_val_len = sip_header->sip_hdr_current -
61740cb5e5dSvi value->strs1_val_ptr;
61840cb5e5dSvi (void) sip_skip_white_space(sip_header);
61940cb5e5dSvi
62040cb5e5dSvi value->strs2_val_ptr = sip_header->sip_hdr_current;
62140cb5e5dSvi if (sip_find_cr(sip_header) != 0) {
62240cb5e5dSvi value->sip_value_state = SIP_VALUE_BAD;
62340cb5e5dSvi return (EPROTO);
62440cb5e5dSvi }
62540cb5e5dSvi if (sip_header->sip_hdr_current < value->strs2_val_ptr) {
62640cb5e5dSvi value->strs2_val_ptr = NULL;
62740cb5e5dSvi value->strs2_val_len = 0;
62840cb5e5dSvi } else {
62940cb5e5dSvi value->strs2_val_len = sip_header->sip_hdr_current -
63040cb5e5dSvi value->strs2_val_ptr;
63140cb5e5dSvi }
63240cb5e5dSvi } else {
63340cb5e5dSvi /*
63440cb5e5dSvi * no delay information
63540cb5e5dSvi */
63640cb5e5dSvi value->strs1_val_len = sip_header->sip_hdr_current
63740cb5e5dSvi - value->strs1_val_ptr;
63840cb5e5dSvi value->strs2_val_ptr = NULL;
63940cb5e5dSvi value->strs2_val_len = 0;
64040cb5e5dSvi }
64140cb5e5dSvi
64240cb5e5dSvi *header = parsed_header;
64340cb5e5dSvi sip_header->sip_hdr_parsed = *header;
64440cb5e5dSvi
64540cb5e5dSvi return (0);
64640cb5e5dSvi }
64740cb5e5dSvi /*
64840cb5e5dSvi * Unsupported = "Unsupported" HCOLON option-tag * (COMMA option-tag)
64940cb5e5dSvi */
65040cb5e5dSvi int
sip_parse_usupport_header(_sip_header_t * sip_header,sip_parsed_header_t ** header)65140cb5e5dSvi sip_parse_usupport_header(_sip_header_t *sip_header,
65240cb5e5dSvi sip_parsed_header_t **header)
65340cb5e5dSvi {
654*559f8b54SToomas Soome return (sip_parse_hdr_parser1(sip_header, header, 0));
65540cb5e5dSvi }
65640cb5e5dSvi
65740cb5e5dSvi /*
65840cb5e5dSvi * User-Agent = "User-Agent" HCOLON server-val * (LWS server-val)
65940cb5e5dSvi * servel-val = product |comment
66040cb5e5dSvi * product = token [SLASH version]
66140cb5e5dSvi * version = token
66240cb5e5dSvi */
66340cb5e5dSvi int
sip_parse_useragt_header(_sip_header_t * sip_header,sip_parsed_header_t ** header)66440cb5e5dSvi sip_parse_useragt_header(_sip_header_t *sip_header,
66540cb5e5dSvi sip_parsed_header_t **header)
66640cb5e5dSvi {
66740cb5e5dSvi return (sip_parse_hdr_parser4(sip_header, header));
66840cb5e5dSvi }
66940cb5e5dSvi
67040cb5e5dSvi /*
67140cb5e5dSvi * Warning = "Warning" HCOLON warning-value *(COMMA warning-value)
67240cb5e5dSvi * warning-value = warn-code SP warn-agent SP warn-text
67340cb5e5dSvi * warn-code = 3DIGIT
67440cb5e5dSvi * warn-agent = hostport | pseudonym ;
67540cb5e5dSvi * the name or pseudonym of the server adding;
67640cb5e5dSvi * the Warning header, for use in debugging
67740cb5e5dSvi * warn-text = quoted-string
67840cb5e5dSvi * pseudonym = token
67940cb5e5dSvi */
68040cb5e5dSvi int
sip_parse_warn_header(_sip_header_t * sip_header,sip_parsed_header_t ** header)68140cb5e5dSvi sip_parse_warn_header(_sip_header_t *sip_header, sip_parsed_header_t **header)
68240cb5e5dSvi {
68340cb5e5dSvi sip_parsed_header_t *parsed_header;
68440cb5e5dSvi int ret;
68540cb5e5dSvi sip_hdr_value_t *value = NULL;
68640cb5e5dSvi sip_hdr_value_t *last_value = NULL;
68740cb5e5dSvi
68840cb5e5dSvi if ((ret = sip_prim_parsers(sip_header, header)) != 0)
68940cb5e5dSvi return (ret);
69040cb5e5dSvi
69140cb5e5dSvi if (*header != NULL)
69240cb5e5dSvi return (0);
69340cb5e5dSvi
69440cb5e5dSvi parsed_header = calloc(1, sizeof (sip_parsed_header_t));
69540cb5e5dSvi if (parsed_header == NULL)
69640cb5e5dSvi return (ENOMEM);
69740cb5e5dSvi parsed_header->sip_parsed_header_version = SIP_PARSED_HEADER_VERSION_1;
69840cb5e5dSvi parsed_header->sip_header = sip_header;
69940cb5e5dSvi
70040cb5e5dSvi while (sip_header->sip_hdr_current < sip_header->sip_hdr_end) {
70140cb5e5dSvi value = calloc(1, sizeof (sip_hdr_value_t));
70240cb5e5dSvi if (value == NULL) {
70340cb5e5dSvi sip_free_phdr(parsed_header);
70440cb5e5dSvi return (ENOMEM);
70540cb5e5dSvi }
70640cb5e5dSvi
70740cb5e5dSvi if (last_value != NULL)
70840cb5e5dSvi last_value->sip_next_value = value;
70940cb5e5dSvi else
71040cb5e5dSvi parsed_header->value = (sip_value_t *)value;
71140cb5e5dSvi
71240cb5e5dSvi value->sip_value_start = sip_header->sip_hdr_current;
71340cb5e5dSvi value->sip_value_header = parsed_header;
71440cb5e5dSvi
71540cb5e5dSvi ret = sip_atoi(sip_header, &value->warn_code);
71640cb5e5dSvi if (ret != 0 || value->warn_code < 100 ||
71740cb5e5dSvi value->warn_code > 999) {
71840cb5e5dSvi value->sip_value_state = SIP_VALUE_BAD;
71940cb5e5dSvi goto get_next_val;
72040cb5e5dSvi }
72140cb5e5dSvi if (sip_skip_white_space(sip_header) != 0) {
72240cb5e5dSvi value->sip_value_state = SIP_VALUE_BAD;
72340cb5e5dSvi goto get_next_val;
72440cb5e5dSvi }
72540cb5e5dSvi value->warn_agt_ptr = sip_header->sip_hdr_current;
72640cb5e5dSvi
72740cb5e5dSvi if (sip_find_token(sip_header, SIP_QUOTE) == 0) {
72840cb5e5dSvi /*
72940cb5e5dSvi * get warning agent
73040cb5e5dSvi */
73140cb5e5dSvi sip_header->sip_hdr_current--;
73240cb5e5dSvi (void) sip_reverse_skip_white_space(sip_header);
73340cb5e5dSvi value->warn_agt_len = sip_header->sip_hdr_current -
73440cb5e5dSvi value->warn_agt_ptr - 1;
73540cb5e5dSvi if (value->warn_agt_len <= 0) {
73640cb5e5dSvi value->warn_agt_ptr = NULL;
73740cb5e5dSvi value->sip_value_state = SIP_VALUE_BAD;
73840cb5e5dSvi }
73940cb5e5dSvi
74040cb5e5dSvi /*
74140cb5e5dSvi * We will have a SIP_QUOTE here
74240cb5e5dSvi */
74340cb5e5dSvi (void) sip_find_token(sip_header, SIP_QUOTE);
74440cb5e5dSvi
74540cb5e5dSvi value->warn_text_ptr = sip_header->sip_hdr_current;
74640cb5e5dSvi if (sip_find_token(sip_header, SIP_QUOTE) == 0) {
74740cb5e5dSvi value->warn_text_len =
74840cb5e5dSvi sip_header->sip_hdr_current -
749df4705eaSgm value->warn_text_ptr - 1;
75040cb5e5dSvi } else {
75140cb5e5dSvi value->sip_value_state = SIP_VALUE_BAD;
75240cb5e5dSvi goto get_next_val;
75340cb5e5dSvi }
75440cb5e5dSvi } else
75540cb5e5dSvi /*
75640cb5e5dSvi * warning text must present
75740cb5e5dSvi */
75840cb5e5dSvi value->sip_value_state = SIP_VALUE_BAD;
75940cb5e5dSvi
76040cb5e5dSvi get_next_val:
76140cb5e5dSvi if (sip_find_token(sip_header, SIP_COMMA) != 0)
76240cb5e5dSvi break;
76340cb5e5dSvi value->sip_value_end = sip_header->sip_hdr_current - 1;
76440cb5e5dSvi last_value = value;
76540cb5e5dSvi (void) sip_skip_white_space(sip_header);
76640cb5e5dSvi }
76740cb5e5dSvi
76840cb5e5dSvi *header = parsed_header;
76940cb5e5dSvi
77040cb5e5dSvi sip_header->sip_hdr_parsed = *header;
77140cb5e5dSvi return (0);
77240cb5e5dSvi }
77340cb5e5dSvi
77440cb5e5dSvi /*
77540cb5e5dSvi * Parse RAck header
77640cb5e5dSvi * "RAck" HCOLON response-num LWS CSeq-num LWS Method
77740cb5e5dSvi * response-num = 1*DIGIT
77840cb5e5dSvi * CSeq-num = 1*DIGIT
77940cb5e5dSvi */
78040cb5e5dSvi int
sip_parse_rack(_sip_header_t * sip_header,sip_parsed_header_t ** header)78140cb5e5dSvi sip_parse_rack(_sip_header_t *sip_header, sip_parsed_header_t **header)
78240cb5e5dSvi {
78340cb5e5dSvi sip_parsed_header_t *parsed_header;
78440cb5e5dSvi sip_hdr_value_t *rack_value;
78540cb5e5dSvi int len;
78640cb5e5dSvi char *tmp_ptr;
78740cb5e5dSvi int i;
78840cb5e5dSvi int ret;
78940cb5e5dSvi
79040cb5e5dSvi if ((ret = sip_prim_parsers(sip_header, header)) != 0)
79140cb5e5dSvi return (ret);
79240cb5e5dSvi
79340cb5e5dSvi if (*header != NULL)
79440cb5e5dSvi return (0);
79540cb5e5dSvi
79640cb5e5dSvi parsed_header = calloc(1, sizeof (sip_parsed_header_t));
79740cb5e5dSvi if (parsed_header == NULL)
79840cb5e5dSvi return (ENOMEM);
79940cb5e5dSvi parsed_header->sip_parsed_header_version = SIP_PARSED_HEADER_VERSION_1;
80040cb5e5dSvi parsed_header->sip_header = sip_header;
80140cb5e5dSvi
80240cb5e5dSvi parsed_header->value = calloc(1, sizeof (sip_hdr_value_t));
80340cb5e5dSvi if (parsed_header->value == NULL) {
80440cb5e5dSvi free(parsed_header);
80540cb5e5dSvi return (ENOMEM);
80640cb5e5dSvi }
80740cb5e5dSvi rack_value = (sip_hdr_value_t *)parsed_header->value;
80840cb5e5dSvi rack_value->sip_value_version = SIP_VALUE_VERSION_1;
80940cb5e5dSvi rack_value->sip_value_start = sip_header->sip_hdr_current;
81040cb5e5dSvi rack_value->sip_value_header = parsed_header;
81140cb5e5dSvi if (sip_atoi(sip_header, &rack_value->rack_resp) ||
81240cb5e5dSvi rack_value->rack_resp == 0) {
81340cb5e5dSvi rack_value->sip_value_state = SIP_VALUE_BAD;
81440cb5e5dSvi rack_value->sip_value_end = sip_header->sip_hdr_end - 2;
81540cb5e5dSvi goto rack_parse_done;
81640cb5e5dSvi }
81740cb5e5dSvi rack_value->sip_value_header = parsed_header;
81840cb5e5dSvi /*
81940cb5e5dSvi * Get cseq.
82040cb5e5dSvi */
82140cb5e5dSvi if (sip_skip_white_space(sip_header) != 0) {
82240cb5e5dSvi rack_value->sip_value_state = SIP_VALUE_BAD;
82340cb5e5dSvi rack_value->sip_value_end = sip_header->sip_hdr_end - 2;
82440cb5e5dSvi goto rack_parse_done;
82540cb5e5dSvi }
82640cb5e5dSvi if (sip_atoi(sip_header, &rack_value->rack_cseq)) {
82740cb5e5dSvi rack_value->sip_value_state = SIP_VALUE_BAD;
82840cb5e5dSvi rack_value->sip_value_end = sip_header->sip_hdr_end - 2;
82940cb5e5dSvi goto rack_parse_done;
83040cb5e5dSvi }
83140cb5e5dSvi /*
83240cb5e5dSvi * Get method.
83340cb5e5dSvi */
83440cb5e5dSvi if (sip_skip_white_space(sip_header) != 0) {
83540cb5e5dSvi rack_value->sip_value_state = SIP_VALUE_BAD;
83640cb5e5dSvi rack_value->sip_value_end = sip_header->sip_hdr_end - 2;
83740cb5e5dSvi goto rack_parse_done;
83840cb5e5dSvi }
83940cb5e5dSvi
84040cb5e5dSvi tmp_ptr = sip_header->sip_hdr_current;
84140cb5e5dSvi if (sip_find_white_space(sip_header)) {
84240cb5e5dSvi rack_value->sip_value_state = SIP_VALUE_BAD;
84340cb5e5dSvi rack_value->sip_value_end = sip_header->sip_hdr_end - 2;
84440cb5e5dSvi goto rack_parse_done;
84540cb5e5dSvi }
84640cb5e5dSvi
84740cb5e5dSvi len = sip_header->sip_hdr_current - tmp_ptr;
84840cb5e5dSvi
84940cb5e5dSvi for (i = 1; i < MAX_SIP_METHODS; i++) {
85040cb5e5dSvi if (strncmp(sip_methods[i].name, tmp_ptr, len) == 0)
85140cb5e5dSvi break;
85240cb5e5dSvi }
85340cb5e5dSvi
85440cb5e5dSvi if (i >= MAX_SIP_METHODS) {
85540cb5e5dSvi rack_value->sip_value_state = SIP_VALUE_BAD;
85640cb5e5dSvi rack_value->sip_value_end = sip_header->sip_hdr_end - 2;
85740cb5e5dSvi goto rack_parse_done;
85840cb5e5dSvi }
85940cb5e5dSvi
86040cb5e5dSvi rack_value->rack_method = i;
86140cb5e5dSvi rack_value->sip_value_end = sip_header->sip_hdr_current;
86240cb5e5dSvi
86340cb5e5dSvi rack_parse_done:
86440cb5e5dSvi sip_header->sip_hdr_parsed = parsed_header;
86540cb5e5dSvi
86640cb5e5dSvi *header = parsed_header;
86740cb5e5dSvi return (0);
86840cb5e5dSvi }
86940cb5e5dSvi
87040cb5e5dSvi /*
87140cb5e5dSvi * Allow = "Allow" HCOLON [Method *(COMMA Method)]
87240cb5e5dSvi */
87340cb5e5dSvi int
sip_parse_allow_events_header(_sip_header_t * sip_header,sip_parsed_header_t ** header)87440cb5e5dSvi sip_parse_allow_events_header(_sip_header_t *sip_header,
87540cb5e5dSvi sip_parsed_header_t **header)
87640cb5e5dSvi {
877*559f8b54SToomas Soome return (sip_parse_hdr_parser1(sip_header, header, 0));
87840cb5e5dSvi }
87940cb5e5dSvi
88040cb5e5dSvi /*
88140cb5e5dSvi * Event = ( "Event" / "o" ) HCOLON event-type
88240cb5e5dSvi * *( SEMI event-param )
88340cb5e5dSvi * event-type = event-package *( "." event-template )
88440cb5e5dSvi * event-package = token-nodot
88540cb5e5dSvi * event-template = token-nodot
88640cb5e5dSvi * token-nodot = 1*( alphanum / "-" / "!" / "%" / "*"
88740cb5e5dSvi * / "_" / "+" / "`" / "'" / "~" )
88840cb5e5dSvi * event-param = generic-param / ( "id" EQUAL token )
88940cb5e5dSvi */
89040cb5e5dSvi int
sip_parse_event_header(_sip_header_t * sip_header,sip_parsed_header_t ** header)89140cb5e5dSvi sip_parse_event_header(_sip_header_t *sip_header, sip_parsed_header_t **header)
89240cb5e5dSvi {
893*559f8b54SToomas Soome return (sip_parse_hdr_parser1(sip_header, header, 0));
89440cb5e5dSvi }
89540cb5e5dSvi
89640cb5e5dSvi /*
89740cb5e5dSvi * Subscription-State = "Subscription-State" HCOLON substate-value
898*559f8b54SToomas Soome * *( SEMI subexp-params )
89940cb5e5dSvi * substate-value = "active" / "pending" / "terminated"
90040cb5e5dSvi * / extension-substate
90140cb5e5dSvi * extension-substate = token
90240cb5e5dSvi * subexp-params = ("reason" EQUAL event-reason-value)
90340cb5e5dSvi * / ("expires" EQUAL delta-seconds)*
904*559f8b54SToomas Soome * / ("retry-after" EQUAL delta-seconds)
90540cb5e5dSvi * / generic-param
90640cb5e5dSvi * event-reason-value = "deactivated"
90740cb5e5dSvi * / "probation"
90840cb5e5dSvi * / "rejected"
90940cb5e5dSvi * / "timeout"
91040cb5e5dSvi * / "giveup"
91140cb5e5dSvi * / "noresource"
91240cb5e5dSvi * / event-reason-extension
91340cb5e5dSvi * event-reason-extension = token
91440cb5e5dSvi */
91540cb5e5dSvi int
sip_parse_substate_header(_sip_header_t * sip_header,sip_parsed_header_t ** header)91640cb5e5dSvi sip_parse_substate_header(_sip_header_t *sip_header,
91740cb5e5dSvi sip_parsed_header_t **header)
91840cb5e5dSvi {
919*559f8b54SToomas Soome return (sip_parse_hdr_parser1(sip_header, header, 0));
92040cb5e5dSvi }
92140cb5e5dSvi
92240cb5e5dSvi /*
92340cb5e5dSvi * Authorization = "Authorization" HCOLON credentials
92440cb5e5dSvi * credentials = ("Digest" LWS digest-response)
92540cb5e5dSvi * / other-response
92640cb5e5dSvi * digest-response = dig-resp *(COMMA dig-resp)
92740cb5e5dSvi * dig-resp = username / realm / nonce / digest-uri
92840cb5e5dSvi * / dresponse / algorithm / cnonce
92940cb5e5dSvi * / opaque / message-qop
93040cb5e5dSvi * / nonce-count / auth-param
93140cb5e5dSvi * username = "username" EQUAL username-value
93240cb5e5dSvi * username-value = quoted-string
93340cb5e5dSvi * digest-uri = "uri" EQUAL LDQUOT digest-uri-value RDQUOT
93440cb5e5dSvi * digest-uri-value = rquest-uri ; Equal to request-uri as specified
93540cb5e5dSvi * by HTTP/1.1
93640cb5e5dSvi * message-qop = "qop" EQUAL qop-value
93740cb5e5dSvi * cnonce = "cnonce" EQUAL cnonce-value
93840cb5e5dSvi * cnonce-value = nonce-value
93940cb5e5dSvi * nonce-count = "nc" EQUAL nc-value
94040cb5e5dSvi * nc-value = 8LHEX
94140cb5e5dSvi * dresponse = "response" EQUAL request-digest
94240cb5e5dSvi * request-digest = LDQUOT 32LHEX RDQUOT
94340cb5e5dSvi * auth-param = auth-param-name EQUAL
944*559f8b54SToomas Soome * ( token / quoted-string )
94540cb5e5dSvi * auth-param-name = token
94640cb5e5dSvi * other-response = auth-scheme LWS auth-param
94740cb5e5dSvi * *(COMMA auth-param)
94840cb5e5dSvi * auth-scheme = token
94940cb5e5dSvi */
95040cb5e5dSvi int
sip_parse_author_header(_sip_header_t * sip_header,sip_parsed_header_t ** header)95140cb5e5dSvi sip_parse_author_header(_sip_header_t *sip_header,
95240cb5e5dSvi sip_parsed_header_t **header)
95340cb5e5dSvi {
95440cb5e5dSvi return (sip_parse_hdr_parser5(sip_header, header, B_TRUE));
95540cb5e5dSvi }
95640cb5e5dSvi
95740cb5e5dSvi /*
95840cb5e5dSvi * Authentication-Info = "Authentication-Info" HCOLON ainfo
95940cb5e5dSvi * *(COMMA ainfo)
96040cb5e5dSvi * ainfo = nextnonce / message-qop
96140cb5e5dSvi * / response-auth / cnonce
96240cb5e5dSvi * / nonce-count
96340cb5e5dSvi * nextnonce = "nextnonce" EQUAL nonce-value
96440cb5e5dSvi * response-auth = "rspauth" EQUAL response-digest
96540cb5e5dSvi * response-digest = LDQUOT *LHEX RDQUOT
96640cb5e5dSvi *
96740cb5e5dSvi */
96840cb5e5dSvi int
sip_parse_ainfo_header(_sip_header_t * sip_header,sip_parsed_header_t ** header)96940cb5e5dSvi sip_parse_ainfo_header(_sip_header_t *sip_header,
97040cb5e5dSvi sip_parsed_header_t **header)
97140cb5e5dSvi {
972*559f8b54SToomas Soome return (sip_parse_hdr_parser1(sip_header, header, 0));
97340cb5e5dSvi }
97440cb5e5dSvi
97540cb5e5dSvi /*
97640cb5e5dSvi * Proxy-Authenticate = "Proxy-Authenticate" HCOLON challenge
97740cb5e5dSvi * challenge = ("Digest" LWS digest-cln *(COMMA digest-cln))
97840cb5e5dSvi * / other-challenge
97940cb5e5dSvi * other-challenge = auth-scheme LWS auth-param
980*559f8b54SToomas Soome * *(COMMA auth-param)
98140cb5e5dSvi * digest-cln = realm / domain / nonce
98240cb5e5dSvi * / opaque / stale / algorithm
98340cb5e5dSvi * / qop-options / auth-param
98440cb5e5dSvi * realm = "realm" EQUAL realm-value
98540cb5e5dSvi * realm-value = quoted-string
98640cb5e5dSvi * domain = "domain" EQUAL LDQUOT URI
98740cb5e5dSvi * *( 1*SP URI ) RDQUOT
98840cb5e5dSvi * URI = absoluteURI / abs-path
98940cb5e5dSvi * nonce = "nonce" EQUAL nonce-value
99040cb5e5dSvi * nonce-value = quoted-string
99140cb5e5dSvi * opaque = "opaque" EQUAL quoted-string
99240cb5e5dSvi * stale = "stale" EQUAL ( "true" / "false" )
99340cb5e5dSvi * algorithm = "algorithm" EQUAL ( "MD5" / "MD5-sess"
99440cb5e5dSvi * / token )
99540cb5e5dSvi * qop-options = "qop" EQUAL LDQUOT qop-value
99640cb5e5dSvi * *("," qop-value) RDQUOT
99740cb5e5dSvi * qop-value = "auth" / "auth-int" / token
99840cb5e5dSvi *
99940cb5e5dSvi */
100040cb5e5dSvi int
sip_parse_pauthen_header(_sip_header_t * sip_header,sip_parsed_header_t ** header)100140cb5e5dSvi sip_parse_pauthen_header(_sip_header_t *sip_header,
100240cb5e5dSvi sip_parsed_header_t **header)
100340cb5e5dSvi {
100440cb5e5dSvi return (sip_parse_hdr_parser5(sip_header, header, B_TRUE));
100540cb5e5dSvi }
100640cb5e5dSvi
100740cb5e5dSvi /*
100840cb5e5dSvi * Proxy-Authorization = "Proxy-Authorization" HCOLON credentials
100940cb5e5dSvi */
101040cb5e5dSvi int
sip_parse_pauthor_header(_sip_header_t * sip_header,sip_parsed_header_t ** header)101140cb5e5dSvi sip_parse_pauthor_header(_sip_header_t *sip_header,
101240cb5e5dSvi sip_parsed_header_t **header)
101340cb5e5dSvi {
101440cb5e5dSvi return (sip_parse_hdr_parser5(sip_header, header, B_TRUE));
101540cb5e5dSvi }
101640cb5e5dSvi
101740cb5e5dSvi /*
101840cb5e5dSvi * Proxy-Require = "Proxy-Require" HCOLON option-tag
101940cb5e5dSvi * *(COMMA option-tag)
102040cb5e5dSvi * option-tag = token
102140cb5e5dSvi */
102240cb5e5dSvi int
sip_parse_preq_header(_sip_header_t * sip_header,sip_parsed_header_t ** header)102340cb5e5dSvi sip_parse_preq_header(_sip_header_t *sip_header,
102440cb5e5dSvi sip_parsed_header_t **header)
102540cb5e5dSvi {
1026*559f8b54SToomas Soome return (sip_parse_hdr_parser1(sip_header, header, 0));
102740cb5e5dSvi }
102840cb5e5dSvi
102940cb5e5dSvi /*
103040cb5e5dSvi * WWW-Authenticate = "WWW-Authenticate" HCOLON challenge
103140cb5e5dSvi * extension-header = header-name HCOLON header-value
103240cb5e5dSvi * header-name = token
103340cb5e5dSvi * header-value = *(TEXT-UTF8char / UTF8-CONT / LWS)
103440cb5e5dSvi * message-body = *OCTET
103540cb5e5dSvi *
103640cb5e5dSvi */
103740cb5e5dSvi int
sip_parse_wauthen_header(_sip_header_t * sip_header,sip_parsed_header_t ** header)103840cb5e5dSvi sip_parse_wauthen_header(_sip_header_t *sip_header,
103940cb5e5dSvi sip_parsed_header_t **header)
104040cb5e5dSvi {
104140cb5e5dSvi return (sip_parse_hdr_parser5(sip_header, header, B_TRUE));
104240cb5e5dSvi }
104340cb5e5dSvi
104440cb5e5dSvi /*
104540cb5e5dSvi * Call-ID = ( "Call-ID" / "i" ) HCOLON callid
104640cb5e5dSvi */
104740cb5e5dSvi int
sip_parse_cid_header(_sip_header_t * sip_header,sip_parsed_header_t ** header)104840cb5e5dSvi sip_parse_cid_header(_sip_header_t *sip_header, sip_parsed_header_t **header)
104940cb5e5dSvi {
105040cb5e5dSvi return (sip_parse_hdr_parser4(sip_header, header));
105140cb5e5dSvi }
105240cb5e5dSvi
105340cb5e5dSvi /*
105440cb5e5dSvi * CSeq = "CSeq" HCOLON 1*DIGIT LWS Method
105540cb5e5dSvi */
105640cb5e5dSvi int
sip_parse_cseq_header(_sip_header_t * sip_header,sip_parsed_header_t ** header)105740cb5e5dSvi sip_parse_cseq_header(_sip_header_t *sip_header, sip_parsed_header_t **header)
105840cb5e5dSvi {
105940cb5e5dSvi sip_parsed_header_t *parsed_header;
106040cb5e5dSvi sip_hdr_value_t *cseq_value;
106140cb5e5dSvi int len;
106240cb5e5dSvi char *tmp_ptr;
106340cb5e5dSvi int i;
106440cb5e5dSvi int ret;
106540cb5e5dSvi
106640cb5e5dSvi if ((ret = sip_prim_parsers(sip_header, header)) != 0)
106740cb5e5dSvi return (ret);
106840cb5e5dSvi
106940cb5e5dSvi if (*header != NULL)
107040cb5e5dSvi return (0);
107140cb5e5dSvi
107240cb5e5dSvi parsed_header = calloc(1, sizeof (sip_parsed_header_t));
107340cb5e5dSvi if (parsed_header == NULL)
107440cb5e5dSvi return (ENOMEM);
107540cb5e5dSvi parsed_header->sip_parsed_header_version = SIP_PARSED_HEADER_VERSION_1;
107640cb5e5dSvi parsed_header->sip_header = sip_header;
107740cb5e5dSvi
107840cb5e5dSvi parsed_header->value = calloc(1, sizeof (sip_hdr_value_t));
107940cb5e5dSvi if (parsed_header->value == NULL) {
108040cb5e5dSvi free(parsed_header);
108140cb5e5dSvi return (ENOMEM);
108240cb5e5dSvi }
108340cb5e5dSvi cseq_value = (sip_hdr_value_t *)parsed_header->value;
108440cb5e5dSvi cseq_value->sip_value_version = SIP_VALUE_VERSION_1;
108540cb5e5dSvi cseq_value->sip_value_start = sip_header->sip_hdr_current;
108640cb5e5dSvi if (sip_atoi(sip_header, &cseq_value->cseq_num)) {
108740cb5e5dSvi cseq_value->sip_value_state = SIP_VALUE_BAD;
108840cb5e5dSvi cseq_value->sip_value_end = sip_header->sip_hdr_end - 2;
108940cb5e5dSvi goto cseq_parse_done;
109040cb5e5dSvi }
109140cb5e5dSvi cseq_value->sip_value_header = parsed_header;
109240cb5e5dSvi /*
109340cb5e5dSvi * Get method.
109440cb5e5dSvi */
109540cb5e5dSvi if (sip_skip_white_space(sip_header) != 0) {
109640cb5e5dSvi cseq_value->sip_value_state = SIP_VALUE_BAD;
109740cb5e5dSvi cseq_value->sip_value_end = sip_header->sip_hdr_end - 2;
109840cb5e5dSvi goto cseq_parse_done;
109940cb5e5dSvi }
110040cb5e5dSvi
110140cb5e5dSvi tmp_ptr = sip_header->sip_hdr_current;
110240cb5e5dSvi
110340cb5e5dSvi if (sip_find_white_space(sip_header)) {
110440cb5e5dSvi cseq_value->sip_value_state = SIP_VALUE_BAD;
110540cb5e5dSvi cseq_value->sip_value_end = sip_header->sip_hdr_current;
110640cb5e5dSvi goto cseq_parse_done;
110740cb5e5dSvi }
110840cb5e5dSvi
110940cb5e5dSvi len = sip_header->sip_hdr_current - tmp_ptr;
111040cb5e5dSvi
111140cb5e5dSvi for (i = 1; i < MAX_SIP_METHODS; i++) {
111240cb5e5dSvi if (strncmp(sip_methods[i].name, tmp_ptr, len) == 0)
111340cb5e5dSvi break;
111440cb5e5dSvi }
111540cb5e5dSvi
111640cb5e5dSvi if (i >= MAX_SIP_METHODS) {
111740cb5e5dSvi cseq_value->sip_value_state = SIP_VALUE_BAD;
111840cb5e5dSvi cseq_value->sip_value_end = sip_header->sip_hdr_current;
111940cb5e5dSvi goto cseq_parse_done;
112040cb5e5dSvi }
112140cb5e5dSvi
112240cb5e5dSvi cseq_value->cseq_method = i;
112340cb5e5dSvi cseq_value->sip_value_end = sip_header->sip_hdr_current;
112440cb5e5dSvi cseq_parse_done:
112540cb5e5dSvi
112640cb5e5dSvi sip_header->sip_hdr_parsed = parsed_header;
112740cb5e5dSvi
112840cb5e5dSvi *header = parsed_header;
112940cb5e5dSvi return (0);
113040cb5e5dSvi }
113140cb5e5dSvi
113240cb5e5dSvi
113340cb5e5dSvi /*
113440cb5e5dSvi * Via = ( "Via" / "v" ) HCOLON via-parm *(COMMA via-parm)
113540cb5e5dSvi * via-parm = sent-protocol LWS sent-by *( SEMI via-params )
113640cb5e5dSvi * via-params = via-ttl / via-maddr
113740cb5e5dSvi * / via-received / via-branch
113840cb5e5dSvi * / via-extension
113940cb5e5dSvi * via-ttl = "ttl" EQUAL ttl
114040cb5e5dSvi * via-maddr = "maddr" EQUAL host
114140cb5e5dSvi * via-received = "received" EQUAL (IPv4address / IPv6address)
114240cb5e5dSvi * via-branch = "branch" EQUAL token
114340cb5e5dSvi * via-extension = generic-param
114440cb5e5dSvi * sent-protocol = protocol-name SLASH protocol-version
114540cb5e5dSvi * SLASH transport
114640cb5e5dSvi * protocol-name = "SIP" / token
114740cb5e5dSvi * protocol-version = token
114840cb5e5dSvi * transport = "UDP" / "TCP" / "TLS" / "SCTP"
114940cb5e5dSvi * / other-transport
115040cb5e5dSvi * sent-by = host [ COLON port ]
115140cb5e5dSvi * ttl = 1*3DIGIT ; 0 to 255
115240cb5e5dSvi *
115340cb5e5dSvi * There can be multiple via headers we always append the header.
115440cb5e5dSvi */
115540cb5e5dSvi int
sip_parse_via_header(_sip_header_t * sip_header,sip_parsed_header_t ** header)115640cb5e5dSvi sip_parse_via_header(_sip_header_t *sip_header, sip_parsed_header_t **header)
115740cb5e5dSvi {
115840cb5e5dSvi sip_parsed_header_t *parsed_header;
115940cb5e5dSvi int ret;
116040cb5e5dSvi sip_hdr_value_t *value = NULL;
116140cb5e5dSvi sip_hdr_value_t *last_value = NULL;
116240cb5e5dSvi
116340cb5e5dSvi if ((ret = sip_prim_parsers(sip_header, header)) != 0)
116440cb5e5dSvi return (ret);
116540cb5e5dSvi
116640cb5e5dSvi if (*header != NULL)
116740cb5e5dSvi return (0);
116840cb5e5dSvi
116940cb5e5dSvi parsed_header = calloc(1, sizeof (sip_parsed_header_t));
117040cb5e5dSvi if (parsed_header == NULL)
117140cb5e5dSvi return (ENOMEM);
117240cb5e5dSvi parsed_header->sip_parsed_header_version = SIP_PARSED_HEADER_VERSION_1;
117340cb5e5dSvi parsed_header->sip_header = sip_header;
117440cb5e5dSvi
117540cb5e5dSvi while (sip_header->sip_hdr_current < sip_header->sip_hdr_end) {
117640cb5e5dSvi
117740cb5e5dSvi value = calloc(1, sizeof (sip_hdr_value_t));
117840cb5e5dSvi if (value == NULL) {
117940cb5e5dSvi sip_free_phdr(parsed_header);
118040cb5e5dSvi return (ENOMEM);
118140cb5e5dSvi }
118240cb5e5dSvi if (last_value != NULL)
118340cb5e5dSvi last_value->sip_next_value = value;
118440cb5e5dSvi else
118540cb5e5dSvi parsed_header->value = (sip_value_t *)value;
118640cb5e5dSvi
118740cb5e5dSvi value->sip_value_version = SIP_VALUE_VERSION_1;
118840cb5e5dSvi value->sip_value_start = sip_header->sip_hdr_current;
118940cb5e5dSvi value->sip_value_header = parsed_header;
119040cb5e5dSvi value->via_protocol_name.sip_str_ptr =
119140cb5e5dSvi sip_header->sip_hdr_current;
119240cb5e5dSvi
119340cb5e5dSvi /*
119440cb5e5dSvi * Check to see if there is a version number
119540cb5e5dSvi */
119640cb5e5dSvi if (sip_get_protocol_version(sip_header,
119740cb5e5dSvi &value->via_protocol) != 0) {
119840cb5e5dSvi if (sip_goto_next_value(sip_header) != 0) {
119940cb5e5dSvi sip_free_phdr(parsed_header);
120040cb5e5dSvi return (EPROTO);
120140cb5e5dSvi }
120240cb5e5dSvi value->sip_value_state = SIP_VALUE_BAD;
120340cb5e5dSvi goto get_next_via_value;
120440cb5e5dSvi }
120540cb5e5dSvi
120640cb5e5dSvi if (sip_find_token(sip_header, SIP_SLASH) != 0) {
120740cb5e5dSvi if (sip_goto_next_value(sip_header) != 0) {
120840cb5e5dSvi sip_free_phdr(parsed_header);
120940cb5e5dSvi return (EPROTO);
121040cb5e5dSvi }
121140cb5e5dSvi value->sip_value_state = SIP_VALUE_BAD;
121240cb5e5dSvi goto get_next_via_value;
121340cb5e5dSvi }
121440cb5e5dSvi
121540cb5e5dSvi if (sip_skip_white_space(sip_header) != 0) {
121640cb5e5dSvi if (sip_goto_next_value(sip_header) != 0) {
121740cb5e5dSvi sip_free_phdr(parsed_header);
121840cb5e5dSvi return (EPROTO);
121940cb5e5dSvi }
122040cb5e5dSvi value->sip_value_state = SIP_VALUE_BAD;
122140cb5e5dSvi goto get_next_via_value;
122240cb5e5dSvi }
122340cb5e5dSvi
122440cb5e5dSvi value->via_protocol_transport.sip_str_ptr =
122540cb5e5dSvi sip_header->sip_hdr_current;
122640cb5e5dSvi if (sip_find_white_space(sip_header) != 0) {
122740cb5e5dSvi if (sip_goto_next_value(sip_header) != 0) {
122840cb5e5dSvi sip_free_phdr(parsed_header);
122940cb5e5dSvi return (EPROTO);
123040cb5e5dSvi }
123140cb5e5dSvi value->sip_value_state = SIP_VALUE_BAD;
123240cb5e5dSvi goto get_next_via_value;
123340cb5e5dSvi }
123440cb5e5dSvi
123540cb5e5dSvi value->via_protocol_transport.sip_str_len =
123640cb5e5dSvi sip_header->sip_hdr_current -
123740cb5e5dSvi value->via_protocol_transport.sip_str_ptr;
123840cb5e5dSvi
123940cb5e5dSvi if (sip_skip_white_space(sip_header) != 0) {
124040cb5e5dSvi if (sip_goto_next_value(sip_header) != 0) {
124140cb5e5dSvi sip_free_phdr(parsed_header);
124240cb5e5dSvi return (EPROTO);
124340cb5e5dSvi }
124440cb5e5dSvi value->sip_value_state = SIP_VALUE_BAD;
124540cb5e5dSvi goto get_next_via_value;
124640cb5e5dSvi }
124740cb5e5dSvi
124840cb5e5dSvi value->via_sent_by_host.sip_str_ptr =
124940cb5e5dSvi sip_header->sip_hdr_current;
125040cb5e5dSvi if (*sip_header->sip_hdr_current == '[') {
125140cb5e5dSvi if (sip_find_token(sip_header, ']')) {
125240cb5e5dSvi if (sip_goto_next_value(sip_header) != 0) {
125340cb5e5dSvi sip_free_phdr(parsed_header);
125440cb5e5dSvi return (EPROTO);
125540cb5e5dSvi }
125640cb5e5dSvi value->sip_value_state = SIP_VALUE_BAD;
125740cb5e5dSvi goto get_next_via_value;
125840cb5e5dSvi }
125940cb5e5dSvi } else if (sip_find_separator(sip_header, SIP_SEMI, SIP_COMMA,
1260df4705eaSgm SIP_HCOLON, B_FALSE)) {
126140cb5e5dSvi if (sip_goto_next_value(sip_header) != 0) {
126240cb5e5dSvi sip_free_phdr(parsed_header);
126340cb5e5dSvi return (EPROTO);
126440cb5e5dSvi }
126540cb5e5dSvi value->sip_value_state = SIP_VALUE_BAD;
126640cb5e5dSvi goto get_next_via_value;
126740cb5e5dSvi }
126840cb5e5dSvi value->via_sent_by_host.sip_str_len =
126940cb5e5dSvi sip_header->sip_hdr_current -
127040cb5e5dSvi value->via_sent_by_host.sip_str_ptr;
127140cb5e5dSvi
127240cb5e5dSvi if (sip_skip_white_space(sip_header) != 0) {
127340cb5e5dSvi if (sip_goto_next_value(sip_header) != 0) {
127440cb5e5dSvi sip_free_phdr(parsed_header);
127540cb5e5dSvi return (EPROTO);
127640cb5e5dSvi }
127740cb5e5dSvi value->sip_value_state = SIP_VALUE_BAD;
127840cb5e5dSvi goto get_next_via_value;
127940cb5e5dSvi }
128040cb5e5dSvi
128140cb5e5dSvi if (*sip_header->sip_hdr_current == SIP_HCOLON) {
128240cb5e5dSvi sip_header->sip_hdr_current++;
128340cb5e5dSvi /*
128440cb5e5dSvi * We have a port number
128540cb5e5dSvi */
128640cb5e5dSvi if (sip_atoi(sip_header, &value->via_sent_by_port) !=
128740cb5e5dSvi 0) {
128840cb5e5dSvi if (sip_goto_next_value(sip_header) != 0) {
128940cb5e5dSvi sip_free_phdr(parsed_header);
129040cb5e5dSvi return (EPROTO);
129140cb5e5dSvi }
129240cb5e5dSvi value->sip_value_state = SIP_VALUE_BAD;
129340cb5e5dSvi goto get_next_via_value;
129440cb5e5dSvi }
129540cb5e5dSvi
129640cb5e5dSvi }
129740cb5e5dSvi
129840cb5e5dSvi /*
129940cb5e5dSvi * Do some sanity checking.
130040cb5e5dSvi * This should be replaced by a v4/v6 address check.
130140cb5e5dSvi */
130240cb5e5dSvi if (value->via_sent_by_host.sip_str_len == 0 ||
130340cb5e5dSvi (!isalnum(*value->via_sent_by_host.sip_str_ptr) &&
130440cb5e5dSvi *value->via_sent_by_host.sip_str_ptr != '[')) {
130540cb5e5dSvi if (sip_goto_next_value(sip_header) != 0) {
130640cb5e5dSvi sip_free_phdr(parsed_header);
130740cb5e5dSvi return (EPROTO);
130840cb5e5dSvi }
130940cb5e5dSvi value->sip_value_state = SIP_VALUE_BAD;
131040cb5e5dSvi goto get_next_via_value;
131140cb5e5dSvi }
131240cb5e5dSvi
131340cb5e5dSvi ret = sip_parse_params(sip_header, &value->sip_param_list);
131440cb5e5dSvi if (ret == EPROTO) {
131540cb5e5dSvi value->sip_value_state = SIP_VALUE_BAD;
131640cb5e5dSvi } else if (ret != 0) {
131740cb5e5dSvi sip_free_phdr(parsed_header);
131840cb5e5dSvi return (ret);
131940cb5e5dSvi }
132040cb5e5dSvi get_next_via_value:
132140cb5e5dSvi value->sip_value_end = sip_header->sip_hdr_current;
132240cb5e5dSvi
132340cb5e5dSvi if (sip_find_token(sip_header, SIP_COMMA) != 0)
132440cb5e5dSvi break;
132540cb5e5dSvi last_value = value;
132640cb5e5dSvi (void) sip_skip_white_space(sip_header);
132740cb5e5dSvi }
132840cb5e5dSvi
132940cb5e5dSvi sip_header->sip_hdr_parsed = parsed_header;
133040cb5e5dSvi
133140cb5e5dSvi *header = parsed_header;
133240cb5e5dSvi return (0);
133340cb5e5dSvi }
133440cb5e5dSvi
133540cb5e5dSvi /*
133640cb5e5dSvi * Max-Forwards = "Max-Forwards" HCOLON 1*DIGIT
133740cb5e5dSvi */
133840cb5e5dSvi int
sip_parse_maxf_header(_sip_header_t * sip_header,sip_parsed_header_t ** header)133940cb5e5dSvi sip_parse_maxf_header(_sip_header_t *sip_header, sip_parsed_header_t **header)
134040cb5e5dSvi {
134140cb5e5dSvi return (sip_parse_hdr_parser2(sip_header, header, SIP_INT_VAL));
134240cb5e5dSvi }
134340cb5e5dSvi
134440cb5e5dSvi /*
134540cb5e5dSvi * Content-Type = ( "Content-Type" / "c" ) HCOLON media-type
134640cb5e5dSvi * media-type = m-type SLASH m-subtype *(SEMI m-parameter)
134740cb5e5dSvi * m-type = discrete-type / composite-type
134840cb5e5dSvi * discrete-type = "text" / "image" / "audio" / "video"
134940cb5e5dSvi * / "application" / extension-token
135040cb5e5dSvi * composite-type = "message" / "multipart" / extension-token
135140cb5e5dSvi * extension-token = ietf-token / x-token
135240cb5e5dSvi * ietf-token = token
135340cb5e5dSvi * x-token = "x-" token
135440cb5e5dSvi * m-subtype = extension-token / iana-token
135540cb5e5dSvi * iana-token = token
135640cb5e5dSvi * m-parameter = m-attribute EQUAL m-value
135740cb5e5dSvi * m-attribute = token
135840cb5e5dSvi * m-value = token / quoted-string
135940cb5e5dSvi */
136040cb5e5dSvi int
sip_parse_ctype_header(_sip_header_t * sip_header,sip_parsed_header_t ** header)136140cb5e5dSvi sip_parse_ctype_header(_sip_header_t *sip_header, sip_parsed_header_t **header)
136240cb5e5dSvi {
136340cb5e5dSvi return (sip_parse_hdr_parser1(sip_header, header, SIP_SLASH));
136440cb5e5dSvi }
136540cb5e5dSvi
136640cb5e5dSvi /*
136740cb5e5dSvi * Content-Length = ( "Content-Length" / "l" ) HCOLON 1*DIGIT
136840cb5e5dSvi */
136940cb5e5dSvi int
sip_parse_clen_header(_sip_header_t * sip_header,sip_parsed_header_t ** header)137040cb5e5dSvi sip_parse_clen_header(_sip_header_t *sip_header, sip_parsed_header_t **header)
137140cb5e5dSvi {
137240cb5e5dSvi return (sip_parse_hdr_parser2(sip_header, header, SIP_INT_VAL));
137340cb5e5dSvi }
137440cb5e5dSvi
137540cb5e5dSvi /*
137640cb5e5dSvi * Generic parser for Contact, From, To, Route and Record-Route headers
137740cb5e5dSvi *
137840cb5e5dSvi * Contact = ("Contact" / "m" ) HCOLON
137940cb5e5dSvi * ( STAR / (contact-param *(COMMA contact-param)))
138040cb5e5dSvi * contact-param = (name-addr / addr-spec) *(SEMI contact-params)
138140cb5e5dSvi * name-addr = [ display-name ] LAQUOT addr-spec RAQUOT
138240cb5e5dSvi * addr-spec = SIP-URI / SIPS-URI / absoluteURI
138340cb5e5dSvi * display-name = *(token LWS)/ quoted-string
138440cb5e5dSvi * contact-params = c-p-q / c-p-expires
138540cb5e5dSvi * / contact-extension
138640cb5e5dSvi *
138740cb5e5dSvi * From = ( "From" / "f" ) HCOLON from-spec
138840cb5e5dSvi * from-spec = ( name-addr / addr-spec )
138940cb5e5dSvi * *( SEMI from-param )
139040cb5e5dSvi * from-param = tag-param / generic-param
139140cb5e5dSvi * tag-param = "tag" EQUAL token
139240cb5e5dSvi *
139340cb5e5dSvi * To = ( "To" / "t" ) HCOLON ( name-addr
139440cb5e5dSvi * / addr-spec ) *( SEMI to-param )
139540cb5e5dSvi * to-param = tag-param / generic-param
139640cb5e5dSvi *
139740cb5e5dSvi * Route = "Route" HCOLON route-param *(COMMA route-param)
139840cb5e5dSvi * route-param = name-addr *( SEMI rr-param )
139940cb5e5dSvi *
140040cb5e5dSvi * Record-Route = "Record-Route" HCOLON rec-route *(COMMA rec-route)
140140cb5e5dSvi * rec-route = name-addr *( SEMI rr-param )
140240cb5e5dSvi * rr-param = generic-param
140340cb5e5dSvi *
140440cb5e5dSvi * We could have multiple values for these headers. For the ones that have
140540cb5e5dSvi * a display name we will have a LAQUOT/RAQUOT. If we encounter an error
140640cb5e5dSvi * when parsing a value, we mark the value as bad and start paring the
140740cb5e5dSvi * next value, if present. Before we start parsing the next value, we
140840cb5e5dSvi * check for any parameters, if present.
140940cb5e5dSvi */
141040cb5e5dSvi int
sip_parse_cftr_header(_sip_header_t * sip_header,sip_parsed_header_t ** header)141140cb5e5dSvi sip_parse_cftr_header(_sip_header_t *sip_header, sip_parsed_header_t **header)
141240cb5e5dSvi {
141340cb5e5dSvi sip_parsed_header_t *parsed_header;
141440cb5e5dSvi char *tmp_ptr;
141540cb5e5dSvi char *tmp_ptr_2;
141640cb5e5dSvi int ret;
141740cb5e5dSvi sip_hdr_value_t *value = NULL;
141840cb5e5dSvi sip_hdr_value_t *last_value = NULL;
141940cb5e5dSvi
142040cb5e5dSvi if ((ret = sip_prim_parsers(sip_header, header)) != 0)
142140cb5e5dSvi return (ret);
142240cb5e5dSvi
142340cb5e5dSvi if (*header != NULL)
142440cb5e5dSvi return (0);
142540cb5e5dSvi
142640cb5e5dSvi parsed_header = calloc(1, sizeof (sip_parsed_header_t));
142740cb5e5dSvi if (parsed_header == NULL)
142840cb5e5dSvi return (ENOMEM);
142940cb5e5dSvi parsed_header->sip_parsed_header_version = SIP_PARSED_HEADER_VERSION_1;
143040cb5e5dSvi parsed_header->sip_header = sip_header;
143140cb5e5dSvi while (sip_header->sip_hdr_current < sip_header->sip_hdr_end) {
143240cb5e5dSvi boolean_t quoted_name = B_FALSE;
143340cb5e5dSvi
143440cb5e5dSvi value = calloc(1, sizeof (sip_hdr_value_t));
143540cb5e5dSvi if (value == NULL) {
143640cb5e5dSvi sip_free_cftr_header(parsed_header);
143740cb5e5dSvi return (ENOMEM);
143840cb5e5dSvi }
143940cb5e5dSvi if (last_value != NULL)
144040cb5e5dSvi last_value->sip_next_value = value;
144140cb5e5dSvi else
144240cb5e5dSvi parsed_header->value = (sip_value_t *)value;
144340cb5e5dSvi if (*sip_header->sip_hdr_current == SIP_QUOTE) {
144440cb5e5dSvi sip_header->sip_hdr_current++;
144540cb5e5dSvi quoted_name = B_TRUE;
144640cb5e5dSvi }
144740cb5e5dSvi value->sip_value_version = SIP_VALUE_VERSION_1;
144840cb5e5dSvi value->sip_value_start = sip_header->sip_hdr_current;
144940cb5e5dSvi value->sip_value_header = parsed_header;
145040cb5e5dSvi /*
145140cb5e5dSvi * let's see if there is a display name
145240cb5e5dSvi */
145340cb5e5dSvi if (*sip_header->sip_hdr_current != SIP_LAQUOT) {
145440cb5e5dSvi
145540cb5e5dSvi tmp_ptr = sip_header->sip_hdr_current;
145640cb5e5dSvi /*
145740cb5e5dSvi * According to 20.10 '<' may not have a leading
145840cb5e5dSvi * space.
145940cb5e5dSvi */
146040cb5e5dSvi if (quoted_name &&
146140cb5e5dSvi sip_find_token(sip_header, SIP_QUOTE) != 0) {
146240cb5e5dSvi if (sip_goto_next_value(sip_header) != 0) {
146340cb5e5dSvi sip_free_cftr_header(parsed_header);
146440cb5e5dSvi return (EPROTO);
146540cb5e5dSvi }
146640cb5e5dSvi value->sip_value_state = SIP_VALUE_BAD;
146740cb5e5dSvi goto get_next_cftr_value;
146840cb5e5dSvi } else if (sip_find_separator(sip_header, SIP_SEMI,
1469df4705eaSgm SIP_LAQUOT, SIP_COMMA, B_TRUE) != 0) {
147040cb5e5dSvi /*
147140cb5e5dSvi * only a uri.
147240cb5e5dSvi */
147340cb5e5dSvi value->cftr_uri.sip_str_ptr = tmp_ptr;
147440cb5e5dSvi value->cftr_uri.sip_str_len =
147540cb5e5dSvi sip_header->sip_hdr_current - tmp_ptr;
147640cb5e5dSvi /*
147740cb5e5dSvi * It's an error not to have a uri.
147840cb5e5dSvi */
147940cb5e5dSvi if (value->cftr_uri.sip_str_len == 0) {
148040cb5e5dSvi if (sip_goto_next_value(sip_header) !=
148140cb5e5dSvi 0) {
148240cb5e5dSvi sip_free_cftr_header(
148340cb5e5dSvi parsed_header);
148440cb5e5dSvi return (EPROTO);
148540cb5e5dSvi }
148640cb5e5dSvi value->sip_value_state = SIP_VALUE_BAD;
148740cb5e5dSvi goto get_next_cftr_value;
148840cb5e5dSvi }
1489df4705eaSgm goto get_next_cftr_value;
149040cb5e5dSvi }
1491df4705eaSgm /*
1492df4705eaSgm * This is needed to get rid of leading white spaces of
1493df4705eaSgm * display name or uri
1494df4705eaSgm */
1495df4705eaSgm --sip_header->sip_hdr_current;
1496df4705eaSgm (void) sip_reverse_skip_white_space(sip_header);
1497df4705eaSgm ++sip_header->sip_hdr_current;
149840cb5e5dSvi tmp_ptr_2 = sip_header->sip_hdr_current;
149940cb5e5dSvi if (*sip_header->sip_hdr_current == SIP_SP) {
150040cb5e5dSvi if (sip_skip_white_space(sip_header) != 0) {
150140cb5e5dSvi /*
150240cb5e5dSvi * only a uri.
150340cb5e5dSvi */
150440cb5e5dSvi value->cftr_uri.sip_str_ptr = tmp_ptr;
150540cb5e5dSvi value->cftr_uri.sip_str_len =
150640cb5e5dSvi tmp_ptr_2 - tmp_ptr;
150740cb5e5dSvi /*
150840cb5e5dSvi * It's an error not to have a uri.
150940cb5e5dSvi */
151040cb5e5dSvi if (value->cftr_uri.sip_str_len == 0) {
151140cb5e5dSvi if (sip_goto_next_value(
151240cb5e5dSvi sip_header) != 0) {
151340cb5e5dSvi sip_free_cftr_header(
151440cb5e5dSvi parsed_header);
151540cb5e5dSvi return (EPROTO);
151640cb5e5dSvi }
151740cb5e5dSvi value->sip_value_state =
151840cb5e5dSvi SIP_VALUE_BAD;
151940cb5e5dSvi goto get_next_cftr_value;
152040cb5e5dSvi }
1521df4705eaSgm goto get_next_cftr_value;
152240cb5e5dSvi }
152340cb5e5dSvi }
152440cb5e5dSvi
152540cb5e5dSvi if (*sip_header->sip_hdr_current != SIP_LAQUOT) {
152640cb5e5dSvi /*
152740cb5e5dSvi * No display name here.
152840cb5e5dSvi */
152940cb5e5dSvi value->cftr_uri.sip_str_ptr = tmp_ptr;
153040cb5e5dSvi value->cftr_uri.sip_str_len = tmp_ptr_2 -
153140cb5e5dSvi tmp_ptr;
153240cb5e5dSvi /*
153340cb5e5dSvi * It's an error not to have a uri.
153440cb5e5dSvi */
153540cb5e5dSvi if (value->cftr_uri.sip_str_len == 0) {
153640cb5e5dSvi if (sip_goto_next_value(sip_header) !=
153740cb5e5dSvi 0) {
153840cb5e5dSvi sip_free_cftr_header(
153940cb5e5dSvi parsed_header);
154040cb5e5dSvi return (EPROTO);
154140cb5e5dSvi }
154240cb5e5dSvi value->sip_value_state = SIP_VALUE_BAD;
154340cb5e5dSvi goto get_next_cftr_value;
154440cb5e5dSvi }
154540cb5e5dSvi goto get_params;
154640cb5e5dSvi }
154740cb5e5dSvi
154840cb5e5dSvi value->cftr_name = malloc(sizeof (sip_str_t));
154940cb5e5dSvi if (value->cftr_name == NULL) {
155040cb5e5dSvi sip_free_cftr_header(parsed_header);
155140cb5e5dSvi return (ENOMEM);
155240cb5e5dSvi }
155340cb5e5dSvi value->cftr_name->sip_str_ptr = tmp_ptr;
155440cb5e5dSvi value->cftr_name->sip_str_len = tmp_ptr_2 - tmp_ptr;
155540cb5e5dSvi if (quoted_name)
155640cb5e5dSvi value->cftr_name->sip_str_len--;
155740cb5e5dSvi }
155840cb5e5dSvi
155940cb5e5dSvi if (sip_find_token(sip_header, SIP_LAQUOT) != 0) {
156040cb5e5dSvi if (sip_goto_next_value(sip_header) != 0) {
156140cb5e5dSvi sip_free_cftr_header(parsed_header);
156240cb5e5dSvi return (EPROTO);
156340cb5e5dSvi }
156440cb5e5dSvi value->sip_value_state = SIP_VALUE_BAD;
156540cb5e5dSvi goto get_next_cftr_value;
156640cb5e5dSvi }
156740cb5e5dSvi
156840cb5e5dSvi if (*sip_header->sip_hdr_current == SIP_SP) {
156940cb5e5dSvi if (sip_skip_white_space(sip_header) != 0) {
157040cb5e5dSvi if (sip_goto_next_value(sip_header) != 0) {
157140cb5e5dSvi sip_free_cftr_header(parsed_header);
157240cb5e5dSvi return (EPROTO);
157340cb5e5dSvi }
157440cb5e5dSvi value->sip_value_state = SIP_VALUE_BAD;
157540cb5e5dSvi goto get_next_cftr_value;
157640cb5e5dSvi }
157740cb5e5dSvi }
157840cb5e5dSvi
157940cb5e5dSvi tmp_ptr = sip_header->sip_hdr_current;
158040cb5e5dSvi
1581*559f8b54SToomas Soome if (sip_find_separator(sip_header, SIP_RAQUOT, 0, 0, B_FALSE)) {
158240cb5e5dSvi if (sip_goto_next_value(sip_header) != 0) {
158340cb5e5dSvi sip_free_cftr_header(parsed_header);
158440cb5e5dSvi return (EPROTO);
158540cb5e5dSvi }
158640cb5e5dSvi value->sip_value_state = SIP_VALUE_BAD;
158740cb5e5dSvi goto get_next_cftr_value;
158840cb5e5dSvi }
158940cb5e5dSvi
159040cb5e5dSvi value->cftr_uri.sip_str_ptr = tmp_ptr;
159140cb5e5dSvi value->cftr_uri.sip_str_len =
159240cb5e5dSvi sip_header->sip_hdr_current - tmp_ptr;
159340cb5e5dSvi
159440cb5e5dSvi if (sip_find_token(sip_header, SIP_RAQUOT) != 0) {
159540cb5e5dSvi if (sip_goto_next_value(sip_header) != 0) {
159640cb5e5dSvi sip_free_cftr_header(parsed_header);
159740cb5e5dSvi return (EINVAL);
159840cb5e5dSvi }
159940cb5e5dSvi value->sip_value_state = SIP_VALUE_BAD;
160040cb5e5dSvi goto get_next_cftr_value;
160140cb5e5dSvi }
160240cb5e5dSvi
160340cb5e5dSvi if (value->cftr_uri.sip_str_len <= strlen("<>")) {
160440cb5e5dSvi if (sip_goto_next_value(sip_header) != 0) {
160540cb5e5dSvi sip_free_cftr_header(parsed_header);
160640cb5e5dSvi return (EPROTO);
160740cb5e5dSvi }
160840cb5e5dSvi value->sip_value_state = SIP_VALUE_BAD;
160940cb5e5dSvi goto get_next_cftr_value;
161040cb5e5dSvi }
161140cb5e5dSvi
161240cb5e5dSvi get_params:
161340cb5e5dSvi ret = sip_parse_params(sip_header, &value->sip_param_list);
161440cb5e5dSvi if (ret == EPROTO) {
161540cb5e5dSvi value->sip_value_state = SIP_VALUE_BAD;
161640cb5e5dSvi } else if (ret != 0) {
161740cb5e5dSvi sip_free_cftr_header(parsed_header);
161840cb5e5dSvi return (ret);
161940cb5e5dSvi }
162040cb5e5dSvi get_next_cftr_value:
162140cb5e5dSvi value->sip_value_end = sip_header->sip_hdr_current;
162240cb5e5dSvi
162340cb5e5dSvi /*
162440cb5e5dSvi * Parse uri
162540cb5e5dSvi */
162640cb5e5dSvi if (value->cftr_uri.sip_str_len > 0) {
1627df4705eaSgm int error;
1628df4705eaSgm uint_t uri_errflags;
1629df4705eaSgm char *uri = "*";
1630df4705eaSgm _sip_msg_t *sip_msg;
1631df4705eaSgm sip_message_type_t *msg_type;
163240cb5e5dSvi
163340cb5e5dSvi value->sip_value_parsed_uri = sip_parse_uri(
163440cb5e5dSvi &value->cftr_uri, &error);
163540cb5e5dSvi if (value->sip_value_parsed_uri == NULL) {
163640cb5e5dSvi sip_free_cftr_header(parsed_header);
163740cb5e5dSvi return (ENOMEM);
163840cb5e5dSvi }
1639df4705eaSgm uri_errflags = ((_sip_uri_t *)value->
1640df4705eaSgm sip_value_parsed_uri)->sip_uri_errflags;
1641df4705eaSgm if (error != 0 || uri_errflags != 0) {
1642df4705eaSgm if ((strcmp(SIP_CONTACT, sip_header->
1643df4705eaSgm sip_header_functions->header_name) == 0) &&
1644df4705eaSgm (strncmp(value->cftr_uri.sip_str_ptr, uri,
1645df4705eaSgm strlen(uri)) == 0) && (strlen(uri) ==
1646df4705eaSgm value->cftr_uri.sip_str_len)) {
1647df4705eaSgm sip_msg = sip_header->sip_hdr_sipmsg;
1648df4705eaSgm msg_type = sip_msg->sip_msg_req_res;
1649df4705eaSgm if (msg_type->is_request && msg_type->
1650df4705eaSgm sip_req_method == REGISTER) {
1651df4705eaSgm error = 0;
1652df4705eaSgm ((_sip_uri_t *)value->
1653df4705eaSgm sip_value_parsed_uri)->
1654df4705eaSgm sip_uri_errflags = 0;
1655df4705eaSgm } else {
1656df4705eaSgm value->sip_value_state =
1657df4705eaSgm SIP_VALUE_BAD;
1658df4705eaSgm }
1659df4705eaSgm } else {
1660df4705eaSgm value->sip_value_state = SIP_VALUE_BAD;
1661df4705eaSgm }
166240cb5e5dSvi }
166340cb5e5dSvi }
166440cb5e5dSvi
166540cb5e5dSvi (void) sip_find_token(sip_header, SIP_COMMA);
166640cb5e5dSvi last_value = value;
166740cb5e5dSvi (void) sip_skip_white_space(sip_header);
166840cb5e5dSvi }
166940cb5e5dSvi
167040cb5e5dSvi sip_header->sip_hdr_parsed = parsed_header;
167140cb5e5dSvi
167240cb5e5dSvi *header = parsed_header;
167340cb5e5dSvi return (0);
167440cb5e5dSvi }
167540cb5e5dSvi
167640cb5e5dSvi /*
167740cb5e5dSvi * PAssertedID = "P-Asserted-Identity" HCOLON PAssertedID-value
167840cb5e5dSvi * *(COMMA PAssertedID-value)
167940cb5e5dSvi * PAssertedID-value = name-addr / addr-spec
168040cb5e5dSvi */
168140cb5e5dSvi int
sip_parse_passertedid(_sip_header_t * sip_header,sip_parsed_header_t ** header)168240cb5e5dSvi sip_parse_passertedid(_sip_header_t *sip_header, sip_parsed_header_t **header)
168340cb5e5dSvi {
168440cb5e5dSvi return (sip_parse_hdr_parser3(sip_header, header, SIP_STRS_VAL,
168540cb5e5dSvi B_TRUE));
168640cb5e5dSvi }
168740cb5e5dSvi
168840cb5e5dSvi /*
168940cb5e5dSvi * PPreferredID = "P-Preferred-Identity" HCOLON PPreferredID-value
169040cb5e5dSvi * *(COMMA PAssertedID-value)
169140cb5e5dSvi * PPreferredID-value = name-addr / addr-spec
169240cb5e5dSvi */
169340cb5e5dSvi int
sip_parse_ppreferredid(_sip_header_t * sip_header,sip_parsed_header_t ** header)169440cb5e5dSvi sip_parse_ppreferredid(_sip_header_t *sip_header, sip_parsed_header_t **header)
169540cb5e5dSvi {
169640cb5e5dSvi return (sip_parse_hdr_parser3(sip_header, header, SIP_STRS_VAL,
169740cb5e5dSvi B_TRUE));
169840cb5e5dSvi }
169940cb5e5dSvi
170040cb5e5dSvi
170140cb5e5dSvi /*
170240cb5e5dSvi * We don't do anything for a header we don't understand
170340cb5e5dSvi */
170440cb5e5dSvi /* ARGSUSED */
170540cb5e5dSvi int
sip_parse_unknown_header(_sip_header_t * sip_header,sip_parsed_header_t ** header)170640cb5e5dSvi sip_parse_unknown_header(_sip_header_t *sip_header,
170740cb5e5dSvi sip_parsed_header_t **header)
170840cb5e5dSvi {
170940cb5e5dSvi return (EINVAL);
171040cb5e5dSvi }
1711