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