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