12882Svi117747 /* 22882Svi117747 * CDDL HEADER START 32882Svi117747 * 42882Svi117747 * The contents of this file are subject to the terms of the 52882Svi117747 * Common Development and Distribution License (the "License"). 62882Svi117747 * You may not use this file except in compliance with the License. 72882Svi117747 * 82882Svi117747 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 92882Svi117747 * or http://www.opensolaris.org/os/licensing. 102882Svi117747 * See the License for the specific language governing permissions 112882Svi117747 * and limitations under the License. 122882Svi117747 * 132882Svi117747 * When distributing Covered Code, include this CDDL HEADER in each 142882Svi117747 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 152882Svi117747 * If applicable, add the following below this CDDL HEADER, with the 162882Svi117747 * fields enclosed by brackets "[]" replaced with your own identifying 172882Svi117747 * information: Portions Copyright [yyyy] [name of copyright owner] 182882Svi117747 * 192882Svi117747 * CDDL HEADER END 202882Svi117747 */ 212882Svi117747 222882Svi117747 /* 233439Svi117747 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 242882Svi117747 * Use is subject to license terms. 252882Svi117747 */ 262882Svi117747 272882Svi117747 #pragma ident "%Z%%M% %I% %E% SMI" 282882Svi117747 293439Svi117747 #include <stdlib.h> 303439Svi117747 #include <assert.h> 313439Svi117747 #include <errno.h> 323439Svi117747 #include <strings.h> 333439Svi117747 #include <ctype.h> 343439Svi117747 #include <sip.h> 353439Svi117747 363439Svi117747 #include "sip_miscdefs.h" 372882Svi117747 #include "sip_msg.h" 383439Svi117747 #include "sip_parse_uri.h" 392882Svi117747 402882Svi117747 /* 412882Svi117747 * atoi function from a header 422882Svi117747 */ 432882Svi117747 int 442882Svi117747 sip_atoi(_sip_header_t *sip_header, int *num) 452882Svi117747 { 462882Svi117747 boolean_t num_found = B_FALSE; 472882Svi117747 482882Svi117747 *num = 0; 492882Svi117747 while (sip_header->sip_hdr_current < sip_header->sip_hdr_end) { 502882Svi117747 if (isspace(*sip_header->sip_hdr_current)) { 512882Svi117747 sip_header->sip_hdr_current++; 522882Svi117747 if (num_found) 532882Svi117747 break; 542882Svi117747 } else if (isdigit(*sip_header->sip_hdr_current)) { 552882Svi117747 *num = (*num * 10) + 562882Svi117747 (*sip_header->sip_hdr_current - '0'); 572882Svi117747 num_found = B_TRUE; 582882Svi117747 sip_header->sip_hdr_current++; 592882Svi117747 } else { 602882Svi117747 break; 612882Svi117747 } 622882Svi117747 } 632882Svi117747 if (!num_found) 642882Svi117747 return (EINVAL); 652882Svi117747 return (0); 662882Svi117747 } 672882Svi117747 682882Svi117747 /* 692882Svi117747 * Find the 'token' 702882Svi117747 */ 712882Svi117747 int 722882Svi117747 sip_find_token(_sip_header_t *sip_header, char token) 732882Svi117747 { 742882Svi117747 while (sip_header->sip_hdr_current < sip_header->sip_hdr_end) { 752882Svi117747 if (token != SIP_COMMA && 762882Svi117747 *sip_header->sip_hdr_current == SIP_COMMA) { 772882Svi117747 sip_header->sip_hdr_current--; 782882Svi117747 return (1); 792882Svi117747 } 802882Svi117747 if (*sip_header->sip_hdr_current++ == token) { 812882Svi117747 /* 822882Svi117747 * sip_hdr_current points to the char 832882Svi117747 * after the token 842882Svi117747 */ 852882Svi117747 return (0); 862882Svi117747 } 872882Svi117747 } 882882Svi117747 return (1); 892882Svi117747 } 902882Svi117747 912882Svi117747 /* 922882Svi117747 * Find a carriage-return 932882Svi117747 */ 942882Svi117747 int 952882Svi117747 sip_find_cr(_sip_header_t *sip_header) 962882Svi117747 { 972882Svi117747 sip_header->sip_hdr_current = sip_header->sip_hdr_end; 982882Svi117747 while (*sip_header->sip_hdr_current-- != '\n') { 992882Svi117747 if (sip_header->sip_hdr_current == sip_header->sip_hdr_start) 1002882Svi117747 return (1); 1012882Svi117747 } 1022882Svi117747 return (0); 1032882Svi117747 } 1042882Svi117747 1052882Svi117747 /* 1062882Svi117747 * Find one of the separator provided, i.e. separator_1st or separator_2nd or 1072882Svi117747 * separator_3rd. 1082882Svi117747 */ 1092882Svi117747 int 1102882Svi117747 sip_find_separator(_sip_header_t *sip_header, char separator_1st, 111*5092Sgm209912 char separator_2nd, char separator_3rd, boolean_t ignore_space) 1122882Svi117747 { 1132882Svi117747 assert(separator_1st != (char)NULL || separator_2nd != (char)NULL); 1142882Svi117747 while (sip_header->sip_hdr_current < sip_header->sip_hdr_end) { 115*5092Sgm209912 if (ignore_space && (*sip_header->sip_hdr_current == SIP_SP)) { 116*5092Sgm209912 sip_header->sip_hdr_current++; 117*5092Sgm209912 continue; 118*5092Sgm209912 } 1192882Svi117747 if (isspace(*sip_header->sip_hdr_current) || 1202882Svi117747 (separator_1st != (char)NULL && 1212882Svi117747 (*sip_header->sip_hdr_current == separator_1st)) || 1222882Svi117747 (separator_2nd != (char)NULL && 1232882Svi117747 (*sip_header->sip_hdr_current == separator_2nd)) || 1242882Svi117747 (separator_3rd != (char)NULL && 1252882Svi117747 (*sip_header->sip_hdr_current == separator_3rd))) { 1262882Svi117747 return (0); 1272882Svi117747 } 1282882Svi117747 /* 1292882Svi117747 * If we have escape character, go to the next char 1302882Svi117747 */ 1312882Svi117747 if (*sip_header->sip_hdr_current == '\\') 1322882Svi117747 sip_header->sip_hdr_current++; 1332882Svi117747 sip_header->sip_hdr_current++; 1342882Svi117747 } 1352882Svi117747 return (1); 1362882Svi117747 } 1372882Svi117747 1382882Svi117747 /* 1392882Svi117747 * Return when we hit a white space 1402882Svi117747 */ 1412882Svi117747 int 1422882Svi117747 sip_find_white_space(_sip_header_t *sip_header) 1432882Svi117747 { 1442882Svi117747 while (sip_header->sip_hdr_current < sip_header->sip_hdr_end) { 1452882Svi117747 if (isspace(*sip_header->sip_hdr_current)) 1462882Svi117747 return (0); 1472882Svi117747 sip_header->sip_hdr_current++; 1482882Svi117747 } 1492882Svi117747 return (1); 1502882Svi117747 } 1512882Svi117747 1522882Svi117747 /* 1532882Svi117747 * Skip to the next non-whitespace 1542882Svi117747 */ 1552882Svi117747 int 1562882Svi117747 sip_skip_white_space(_sip_header_t *sip_header) 1572882Svi117747 { 1582882Svi117747 while (sip_header->sip_hdr_current < sip_header->sip_hdr_end) { 1592882Svi117747 if (!isspace(*sip_header->sip_hdr_current)) 1602882Svi117747 return (0); 1612882Svi117747 sip_header->sip_hdr_current++; 1622882Svi117747 } 1632882Svi117747 return (1); 1642882Svi117747 } 1652882Svi117747 1662882Svi117747 1672882Svi117747 /* 1682882Svi117747 * Skip to the non-white space in the reverse direction 1692882Svi117747 */ 1702882Svi117747 int 1712882Svi117747 sip_reverse_skip_white_space(_sip_header_t *sip_header) 1722882Svi117747 { 1732882Svi117747 while (sip_header->sip_hdr_current >= sip_header->sip_hdr_start) { 1742882Svi117747 if (!isspace(*sip_header->sip_hdr_current)) 1752882Svi117747 return (0); 1762882Svi117747 sip_header->sip_hdr_current--; 1772882Svi117747 } 1782882Svi117747 return (1); 1792882Svi117747 } 1802882Svi117747 1812882Svi117747 /* 1822882Svi117747 * get to the first non space after ':' 1832882Svi117747 */ 1842882Svi117747 int 1852882Svi117747 sip_parse_goto_values(_sip_header_t *sip_header) 1862882Svi117747 { 1872882Svi117747 if (sip_find_token(sip_header, SIP_HCOLON) != 0) 1882882Svi117747 return (1); 1892882Svi117747 if (sip_skip_white_space(sip_header) != 0) 1902882Svi117747 return (1); 1912882Svi117747 1922882Svi117747 return (0); 1932882Svi117747 } 1942882Svi117747 1952882Svi117747 /* 1962882Svi117747 * Skip the current value. 1972882Svi117747 */ 1982882Svi117747 int 1992882Svi117747 sip_goto_next_value(_sip_header_t *sip_header) 2002882Svi117747 { 2012882Svi117747 boolean_t quoted = B_FALSE; 2022882Svi117747 2032882Svi117747 while (sip_header->sip_hdr_current < sip_header->sip_hdr_end) { 2042882Svi117747 if (*sip_header->sip_hdr_current == SIP_QUOTE) { 2052882Svi117747 if (quoted) 2062882Svi117747 quoted = B_FALSE; 2072882Svi117747 else 2082882Svi117747 quoted = B_TRUE; 2092882Svi117747 } else if (!quoted && 2102882Svi117747 *sip_header->sip_hdr_current == SIP_COMMA) { 2112882Svi117747 /* 2122882Svi117747 * value ends before the COMMA 2132882Svi117747 */ 2142882Svi117747 sip_header->sip_hdr_current--; 2152882Svi117747 return (0); 2162882Svi117747 } 2172882Svi117747 sip_header->sip_hdr_current++; 2182882Svi117747 } 2192882Svi117747 if (quoted) 2202882Svi117747 return (1); 2212882Svi117747 return (0); 2222882Svi117747 } 2232882Svi117747 2242882Svi117747 /* 2252882Svi117747 * Parse the header into parameter list. Parameters start with a ';' 2262882Svi117747 */ 2272882Svi117747 int 2282882Svi117747 sip_parse_params(_sip_header_t *sip_header, sip_param_t **parsed_list) 2292882Svi117747 { 2302882Svi117747 sip_param_t *param = NULL; 2312882Svi117747 sip_param_t *new_param; 2322882Svi117747 char *tmp_ptr; 2332882Svi117747 2342882Svi117747 if (parsed_list == NULL) 2352882Svi117747 return (0); 2362882Svi117747 2372882Svi117747 *parsed_list = NULL; 2382882Svi117747 for (;;) { 2392882Svi117747 boolean_t quoted_name = B_FALSE; 2402882Svi117747 2412882Svi117747 /* 2422882Svi117747 * First check if there are any params 2432882Svi117747 */ 2442882Svi117747 if (sip_skip_white_space(sip_header) != 0) 2452882Svi117747 return (0); 2462882Svi117747 if (*sip_header->sip_hdr_current != SIP_SEMI) 2472882Svi117747 return (0); 2482882Svi117747 2492882Svi117747 sip_header->sip_hdr_current++; 2502882Svi117747 2512882Svi117747 new_param = calloc(1, sizeof (sip_param_t)); 2522882Svi117747 if (new_param == NULL) 2532882Svi117747 return (ENOMEM); 2542882Svi117747 2552882Svi117747 if (param != NULL) 2562882Svi117747 param->param_next = new_param; 2572882Svi117747 else 2582882Svi117747 *parsed_list = new_param; 2592882Svi117747 2602882Svi117747 param = new_param; 2612882Svi117747 2622882Svi117747 /* 2632882Svi117747 * Let's get to the start of the param name 2642882Svi117747 */ 2652882Svi117747 if (sip_skip_white_space(sip_header) != 0) 2662882Svi117747 return (EPROTO); 2672882Svi117747 /* 2682882Svi117747 * start of param name 2692882Svi117747 */ 2702882Svi117747 tmp_ptr = sip_header->sip_hdr_current; 2712882Svi117747 param->param_name.sip_str_ptr = tmp_ptr; 2722882Svi117747 2732882Svi117747 if (sip_find_separator(sip_header, SIP_EQUAL, SIP_SEMI, 274*5092Sgm209912 SIP_COMMA, B_FALSE) != 0) { 2752882Svi117747 param->param_name.sip_str_len = 2762882Svi117747 sip_header->sip_hdr_current - tmp_ptr; 2772882Svi117747 param->param_value.sip_str_ptr = NULL; 2782882Svi117747 param->param_value.sip_str_len = 0; 2792882Svi117747 return (0); 2802882Svi117747 } 2812882Svi117747 2822882Svi117747 /* 2832882Svi117747 * End of param name 2842882Svi117747 */ 2852882Svi117747 param->param_name.sip_str_len = 2862882Svi117747 sip_header->sip_hdr_current - tmp_ptr; 2872882Svi117747 2882882Svi117747 if (sip_skip_white_space(sip_header) != 0 || 2892882Svi117747 *sip_header->sip_hdr_current == SIP_COMMA) { 2902882Svi117747 param->param_value.sip_str_ptr = NULL; 2912882Svi117747 param->param_value.sip_str_len = 0; 2922882Svi117747 return (0); 2932882Svi117747 } 2942882Svi117747 if (*sip_header->sip_hdr_current == SIP_SEMI) { 2952882Svi117747 param->param_value.sip_str_ptr = NULL; 2962882Svi117747 param->param_value.sip_str_len = 0; 2972882Svi117747 continue; 2982882Svi117747 } 2992882Svi117747 assert(*sip_header->sip_hdr_current == SIP_EQUAL); 3002882Svi117747 3012882Svi117747 /* 3022882Svi117747 * We are at EQUAL, lets go beyond that 3032882Svi117747 */ 3042882Svi117747 sip_header->sip_hdr_current++; 3052882Svi117747 3062882Svi117747 if (sip_skip_white_space(sip_header) != 0) 3072882Svi117747 return (EPROTO); 3082882Svi117747 3092882Svi117747 if (*sip_header->sip_hdr_current == SIP_QUOTE) { 3102882Svi117747 sip_header->sip_hdr_current++; 3112882Svi117747 quoted_name = B_TRUE; 3122882Svi117747 } 3132882Svi117747 3142882Svi117747 /* 3152882Svi117747 * start of param value 3162882Svi117747 */ 3172882Svi117747 param->param_value.sip_str_ptr = sip_header->sip_hdr_current; 3182882Svi117747 tmp_ptr = sip_header->sip_hdr_current; 3192882Svi117747 3202882Svi117747 if (quoted_name && sip_find_token(sip_header, SIP_QUOTE) != 0) { 3212882Svi117747 return (EPROTO); 3222882Svi117747 } else if (sip_find_separator(sip_header, SIP_SEMI, SIP_COMMA, 323*5092Sgm209912 (char)NULL, B_FALSE) != 0) { 3242882Svi117747 return (EPROTO); 3252882Svi117747 } 3262882Svi117747 param->param_value.sip_str_len = sip_header->sip_hdr_current - 3272882Svi117747 tmp_ptr; 3282882Svi117747 if (quoted_name) 3292882Svi117747 param->param_value.sip_str_len--; 3302882Svi117747 } 3312882Svi117747 } 3322882Svi117747 3332882Svi117747 /* 3342882Svi117747 * a header that only has "header_name : " is an empty header 3352882Svi117747 * ":" must exist 3362882Svi117747 * sip_hdr_current resets to sip_hdr_start before exit 3372882Svi117747 */ 3382882Svi117747 boolean_t 3392882Svi117747 sip_is_empty_hdr(_sip_header_t *sip_header) 3402882Svi117747 { 3412882Svi117747 if (sip_find_token(sip_header, SIP_HCOLON) != 0) { 3422882Svi117747 sip_header->sip_hdr_current = sip_header->sip_hdr_start; 3432882Svi117747 return (B_FALSE); 3442882Svi117747 } 3452882Svi117747 3462882Svi117747 if (sip_skip_white_space(sip_header) == 0) { 3472882Svi117747 sip_header->sip_hdr_current = sip_header->sip_hdr_start; 3482882Svi117747 return (B_FALSE); 3492882Svi117747 } 3502882Svi117747 3512882Svi117747 sip_header->sip_hdr_current = sip_header->sip_hdr_start; 3522882Svi117747 return (B_TRUE); 3532882Svi117747 } 3542882Svi117747 3552882Svi117747 /* 3562882Svi117747 * Parsing an empty header, i.e. only has a ":" 3572882Svi117747 */ 3582882Svi117747 int 3592882Svi117747 sip_parse_hdr_empty(_sip_header_t *hdr, sip_parsed_header_t **phdr) 3602882Svi117747 { 3612882Svi117747 sip_parsed_header_t *parsed_header; 3622882Svi117747 3632882Svi117747 if (hdr == NULL || phdr == NULL) 3642882Svi117747 return (EINVAL); 3652882Svi117747 3662882Svi117747 /* 3672882Svi117747 * check if already parsed 3682882Svi117747 */ 3692882Svi117747 if (hdr->sip_hdr_parsed != NULL) { 3702882Svi117747 *phdr = hdr->sip_hdr_parsed; 3712882Svi117747 return (0); 3722882Svi117747 } 3732882Svi117747 3742882Svi117747 *phdr = NULL; 3752882Svi117747 3762882Svi117747 parsed_header = calloc(1, sizeof (sip_parsed_header_t)); 3772882Svi117747 if (parsed_header == NULL) 3782882Svi117747 return (ENOMEM); 3792882Svi117747 parsed_header->sip_header = hdr; 3802882Svi117747 3812882Svi117747 parsed_header->value = NULL; 3822882Svi117747 3832882Svi117747 *phdr = parsed_header; 3842882Svi117747 return (0); 3852882Svi117747 } 3862882Svi117747 3872882Svi117747 /* 3882882Svi117747 * validate uri str and parse uri using uri_parse() 3892882Svi117747 */ 3902882Svi117747 static void 3912882Svi117747 sip_parse_uri_str(sip_str_t *sip_str, sip_hdr_value_t *value) 3922882Svi117747 { 3932882Svi117747 int error; 3942882Svi117747 3952882Svi117747 /* 3962882Svi117747 * Parse uri 3972882Svi117747 */ 3982882Svi117747 if (sip_str->sip_str_len > 0) { 3992882Svi117747 value->sip_value_parsed_uri = sip_parse_uri(sip_str, &error); 4002882Svi117747 if (value->sip_value_parsed_uri == NULL) 4012882Svi117747 return; 4022882Svi117747 if (error != 0 || 4032882Svi117747 value->sip_value_parsed_uri->sip_uri_errflags != 0) { 4042882Svi117747 value->sip_value_state = SIP_VALUE_BAD; 4052882Svi117747 } 4062882Svi117747 } 4072882Svi117747 } 4082882Svi117747 4092882Svi117747 /* 4102882Svi117747 * Some basic common checks before parsing the headers 4112882Svi117747 */ 4122882Svi117747 int 4132882Svi117747 sip_prim_parsers(_sip_header_t *sip_header, sip_parsed_header_t **header) 4142882Svi117747 { 4152882Svi117747 if (sip_header == NULL || header == NULL) 4162882Svi117747 return (EINVAL); 4172882Svi117747 4182882Svi117747 /* 4192882Svi117747 * check if already parsed 4202882Svi117747 */ 4212882Svi117747 if (sip_header->sip_hdr_parsed != NULL) { 4222882Svi117747 *header = sip_header->sip_hdr_parsed; 4232882Svi117747 return (0); 4242882Svi117747 } 4252882Svi117747 *header = NULL; 4262882Svi117747 4272882Svi117747 assert(sip_header->sip_hdr_start == sip_header->sip_hdr_current); 4282882Svi117747 4292882Svi117747 if (sip_parse_goto_values(sip_header) != 0) 4302882Svi117747 return (EPROTO); 4312882Svi117747 4322882Svi117747 return (0); 4332882Svi117747 } 4342882Svi117747 4352882Svi117747 /* 4362882Svi117747 * Parse SIP/2.0 string 4372882Svi117747 */ 4382882Svi117747 int 4392882Svi117747 sip_get_protocol_version(_sip_header_t *sip_header, 4402882Svi117747 sip_proto_version_t *sip_proto_version) 4412882Svi117747 { 4422882Svi117747 if (sip_skip_white_space(sip_header) != 0) 4432882Svi117747 return (1); 4442882Svi117747 4452882Svi117747 if (strncasecmp(sip_header->sip_hdr_current, SIP, strlen(SIP)) == 0) { 4462882Svi117747 sip_proto_version->name.sip_str_ptr = 4472882Svi117747 sip_header->sip_hdr_current; 4482882Svi117747 sip_proto_version->name.sip_str_len = strlen(SIP); 4492882Svi117747 4502882Svi117747 if (sip_find_token(sip_header, SIP_SLASH) != 0) 4512882Svi117747 return (1); 4522882Svi117747 if (sip_skip_white_space(sip_header) != 0) 4532882Svi117747 return (1); 4542882Svi117747 4552882Svi117747 sip_proto_version->version.sip_str_ptr = 4562882Svi117747 sip_header->sip_hdr_current; 4572882Svi117747 while (isdigit(*sip_header->sip_hdr_current)) { 4582882Svi117747 sip_header->sip_hdr_current++; 4592882Svi117747 if (sip_header->sip_hdr_current >= 4602882Svi117747 sip_header->sip_hdr_end) { 4612882Svi117747 return (1); 4622882Svi117747 } 4632882Svi117747 } 4642882Svi117747 if (*sip_header->sip_hdr_current != SIP_PERIOD) 4652882Svi117747 return (1); 4662882Svi117747 sip_header->sip_hdr_current++; 4672882Svi117747 4682882Svi117747 if (!isdigit(*sip_header->sip_hdr_current)) 4692882Svi117747 return (1); 4702882Svi117747 while (isdigit(*sip_header->sip_hdr_current)) { 4712882Svi117747 sip_header->sip_hdr_current++; 4722882Svi117747 if (sip_header->sip_hdr_current >= 4732882Svi117747 sip_header->sip_hdr_end) { 4742882Svi117747 return (1); 4752882Svi117747 } 4762882Svi117747 } 4772882Svi117747 4782882Svi117747 sip_proto_version->version.sip_str_len = 4792882Svi117747 sip_header->sip_hdr_current - 4802882Svi117747 sip_proto_version->version.sip_str_ptr; 4812882Svi117747 return (0); 4822882Svi117747 } 4832882Svi117747 return (1); 4842882Svi117747 } 4852882Svi117747 4862882Svi117747 /* 4872882Svi117747 * parser1 parses hdr format 4882882Svi117747 * header_name: val1[; par1=pval1;par2=pval2 ..][, val2[;parlist..] ] 4892882Svi117747 * val can be str1/str2 or str 4902882Svi117747 * headers: Accept, Accept-Encode, Accept-lang, Allow, Content-disp, 4912882Svi117747 * Content-Encode, Content-Lang, In-reply-to, 4922882Svi117747 * Priority, Require, Supported, Unsupported 4932882Svi117747 * Allow-Events, Event, Subscription-State 4942882Svi117747 */ 4952882Svi117747 int 4962882Svi117747 sip_parse_hdr_parser1(_sip_header_t *hdr, sip_parsed_header_t **phdr, char sep) 4972882Svi117747 { 4982882Svi117747 sip_parsed_header_t *parsed_header; 4992882Svi117747 int ret; 5002882Svi117747 sip_hdr_value_t *value = NULL; 5012882Svi117747 sip_hdr_value_t *last_value = NULL; 5022882Svi117747 5032882Svi117747 if ((ret = sip_prim_parsers(hdr, phdr)) != 0) 5042882Svi117747 return (ret); 5052882Svi117747 5062882Svi117747 /* 5072882Svi117747 * check if previously parsed 5082882Svi117747 */ 5092882Svi117747 if (*phdr != NULL) { 5102882Svi117747 hdr->sip_hdr_parsed = *phdr; 5112882Svi117747 return (0); 5122882Svi117747 } 5132882Svi117747 5142882Svi117747 parsed_header = calloc(1, sizeof (sip_parsed_header_t)); 5152882Svi117747 if (parsed_header == NULL) 5162882Svi117747 return (ENOMEM); 5172882Svi117747 parsed_header->sip_parsed_header_version = SIP_PARSED_HEADER_VERSION_1; 5182882Svi117747 parsed_header->sip_header = hdr; 5192882Svi117747 5202882Svi117747 while (hdr->sip_hdr_current < hdr->sip_hdr_end) { 5212882Svi117747 value = calloc(1, sizeof (sip_hdr_value_t)); 5222882Svi117747 if (value == NULL) { 5232882Svi117747 sip_free_phdr(parsed_header); 5242882Svi117747 return (ENOMEM); 5252882Svi117747 } 5262882Svi117747 if (last_value != NULL) 5272882Svi117747 last_value->sip_next_value = value; 5282882Svi117747 else 5292882Svi117747 parsed_header->value = (sip_value_t *)value; 5302882Svi117747 5312882Svi117747 value->sip_value_start = hdr->sip_hdr_current; 5322882Svi117747 value->sip_value_header = parsed_header; 5332882Svi117747 534*5092Sgm209912 if (sip_find_separator(hdr, sep, SIP_COMMA, SIP_SEMI, 535*5092Sgm209912 B_FALSE) == 0) { 5362882Svi117747 char c = *hdr->sip_hdr_current; 5372882Svi117747 5382882Svi117747 if (isspace(c) && sep == (char)NULL) { 5392882Svi117747 value->str_val_ptr = value->sip_value_start; 5402882Svi117747 value->str_val_len = hdr->sip_hdr_current - 5412882Svi117747 value->sip_value_start; 5422882Svi117747 /* 5432882Svi117747 * nothing at the end except space 5442882Svi117747 */ 5452882Svi117747 if (sip_skip_white_space(hdr) != 0) { 5462882Svi117747 value->sip_value_end = 5472882Svi117747 hdr->sip_hdr_current; 5482882Svi117747 goto end; 5492882Svi117747 } 5502882Svi117747 /* 5512882Svi117747 * white space skipped 5522882Svi117747 */ 5532882Svi117747 c = *(hdr->sip_hdr_current); 5542882Svi117747 } 5552882Svi117747 5562882Svi117747 /* 5572882Svi117747 * only one string until COMMA, use sip_str_t 5582882Svi117747 */ 5592882Svi117747 if (c == SIP_COMMA) { 5602882Svi117747 char *t = hdr->sip_hdr_current; 5612882Svi117747 5622882Svi117747 hdr->sip_hdr_current--; 5632882Svi117747 (void) sip_reverse_skip_white_space(hdr); 5642882Svi117747 value->str_val_ptr = value->sip_value_start; 5652882Svi117747 value->str_val_len = hdr->sip_hdr_current - 5662882Svi117747 value->sip_value_start + 1; 5672882Svi117747 hdr->sip_hdr_current = t; 5682882Svi117747 goto get_next_val; 5692882Svi117747 } 5702882Svi117747 5712882Svi117747 /* 5722882Svi117747 * two strings, use sip_2strs_t 5732882Svi117747 */ 5742882Svi117747 if ((sep != (char)NULL) && (c == sep)) { 5752882Svi117747 value->strs1_val_ptr = value->sip_value_start; 5762882Svi117747 value->strs1_val_len = hdr->sip_hdr_current - 5772882Svi117747 value->sip_value_start; 5782882Svi117747 5792882Svi117747 value->strs2_val_ptr = 5802882Svi117747 (++hdr->sip_hdr_current); 5812882Svi117747 if (sip_find_separator(hdr, SIP_SEMI, SIP_COMMA, 582*5092Sgm209912 (char)NULL, B_FALSE) == 0) { 5832882Svi117747 char t = *(hdr->sip_hdr_current); 5842882Svi117747 value->strs2_val_len = 5852882Svi117747 hdr->sip_hdr_current - 586*5092Sgm209912 value->strs2_val_ptr; 5872882Svi117747 /* 5882882Svi117747 * if COMMA, no param list, get next val 5892882Svi117747 * if SEMI, need to set params list 5902882Svi117747 */ 5912882Svi117747 if (t == SIP_COMMA) 5922882Svi117747 goto get_next_val; 5932882Svi117747 } else { /* the last part */ 5942882Svi117747 value->strs2_val_len = 5952882Svi117747 hdr->sip_hdr_current - 596*5092Sgm209912 value->strs2_val_ptr; 5972882Svi117747 value->sip_value_end = 5982882Svi117747 hdr->sip_hdr_current; 5992882Svi117747 goto end; 6002882Svi117747 } 6012882Svi117747 } else if (sep != (char)NULL) { 6022882Svi117747 value->sip_value_state = SIP_VALUE_BAD; 6032882Svi117747 goto get_next_val; 6042882Svi117747 } 6052882Svi117747 6062882Svi117747 /* 6072882Svi117747 * c == SEMI, value contains single string 6082882Svi117747 * only one string until SEMI, use sip_str_t 6092882Svi117747 */ 6102882Svi117747 if (c == SIP_SEMI) { 6112882Svi117747 char *t = hdr->sip_hdr_current; 6122882Svi117747 6132882Svi117747 hdr->sip_hdr_current--; 6142882Svi117747 /* 6152882Svi117747 * get rid of SP at end of value field 6162882Svi117747 */ 6172882Svi117747 (void) sip_reverse_skip_white_space(hdr); 6182882Svi117747 value->str_val_ptr = value->sip_value_start; 6192882Svi117747 value->str_val_len = hdr->sip_hdr_current - 6202882Svi117747 value->str_val_ptr + 1; 6212882Svi117747 hdr->sip_hdr_current = t; 6222882Svi117747 } 6232882Svi117747 6242882Svi117747 /* 6252882Svi117747 * if SEMI exists in the value, set params list 6262882Svi117747 * two situations, there is or not SLASH before SEMI 6272882Svi117747 */ 6282882Svi117747 ret = sip_parse_params(hdr, &value->sip_param_list); 6292882Svi117747 if (ret == EPROTO) { 6302882Svi117747 value->sip_value_state = SIP_VALUE_BAD; 6312882Svi117747 } else if (ret != 0) { 6322882Svi117747 sip_free_phdr(parsed_header); 6332882Svi117747 return (ret); 6342882Svi117747 } 6352882Svi117747 goto get_next_val; 6362882Svi117747 } else { 6372882Svi117747 value->str_val_ptr = value->sip_value_start; 6382882Svi117747 value->str_val_len = hdr->sip_hdr_current - 6392882Svi117747 value->sip_value_start; 6402882Svi117747 value->sip_value_end = hdr->sip_hdr_current; 6412882Svi117747 goto end; 6422882Svi117747 } 6432882Svi117747 get_next_val: 6442882Svi117747 if (sip_find_token(hdr, SIP_COMMA) != 0) { 6452882Svi117747 value->sip_value_end = hdr->sip_hdr_current; 6462882Svi117747 break; 6472882Svi117747 } 6482882Svi117747 value->sip_value_end = hdr->sip_hdr_current - 1; 6492882Svi117747 last_value = value; 6502882Svi117747 (void) sip_skip_white_space(hdr); 6512882Svi117747 } 6522882Svi117747 6532882Svi117747 end: 6542882Svi117747 *phdr = parsed_header; 6552882Svi117747 hdr->sip_hdr_parsed = *phdr; 6562882Svi117747 return (0); 6572882Svi117747 } 6582882Svi117747 6592882Svi117747 /* 6602882Svi117747 * header_name: int 6612882Svi117747 * headers: Expires, Min-Expires 6622882Svi117747 */ 6632882Svi117747 /* ARGSUSED */ 6642882Svi117747 int 6652882Svi117747 sip_parse_hdr_parser2(_sip_header_t *hdr, sip_parsed_header_t **phdr, 6662882Svi117747 int val_type) 6672882Svi117747 { 6682882Svi117747 sip_parsed_header_t *parsed_header; 6692882Svi117747 int ret = 0; 6702882Svi117747 sip_hdr_value_t *value = NULL; 6712882Svi117747 6722882Svi117747 if ((ret = sip_prim_parsers(hdr, phdr)) != 0) 6732882Svi117747 return (ret); 6742882Svi117747 6752882Svi117747 /* 6762882Svi117747 * check if previously parsed 6772882Svi117747 */ 6782882Svi117747 if (*phdr != NULL) { 6792882Svi117747 hdr->sip_hdr_parsed = *phdr; 6802882Svi117747 return (0); 6812882Svi117747 } 6822882Svi117747 parsed_header = calloc(1, sizeof (sip_parsed_header_t)); 6832882Svi117747 if (parsed_header == NULL) 6842882Svi117747 return (ENOMEM); 6852882Svi117747 parsed_header->sip_parsed_header_version = SIP_PARSED_HEADER_VERSION_1; 6862882Svi117747 parsed_header->sip_header = hdr; 6872882Svi117747 6882882Svi117747 value = calloc(1, sizeof (sip_hdr_value_t)); 6892882Svi117747 if (value == NULL) { 6902882Svi117747 sip_free_phdr(parsed_header); 6912882Svi117747 return (ENOMEM); 6922882Svi117747 } 6932882Svi117747 6942882Svi117747 parsed_header->value = (sip_value_t *)value; 6952882Svi117747 6962882Svi117747 value->sip_value_start = hdr->sip_hdr_current; 6972882Svi117747 value->sip_value_header = parsed_header; 6982882Svi117747 6992882Svi117747 ret = sip_atoi(hdr, &value->int_val); 7002882Svi117747 if (ret != 0) { 7012882Svi117747 value->int_val = 0; 7022882Svi117747 value->sip_value_state = SIP_VALUE_BAD; 7032882Svi117747 } 7042882Svi117747 7052882Svi117747 value->sip_value_end = hdr->sip_hdr_current - 1; 7062882Svi117747 7072882Svi117747 *phdr = parsed_header; 7082882Svi117747 hdr->sip_hdr_parsed = *phdr; 7092882Svi117747 return (0); 7102882Svi117747 } 7112882Svi117747 7122882Svi117747 /* 7132882Svi117747 * parser3 parses hdr format 7142882Svi117747 * header_name: <val1>[, <val2>] 7152882Svi117747 * Alert-Info, Call-Info, Error-Info, reply-to 7162882Svi117747 */ 7172882Svi117747 int 7182882Svi117747 sip_parse_hdr_parser3(_sip_header_t *hdr, sip_parsed_header_t **phdr, int type, 7192882Svi117747 boolean_t parse_uri) 7202882Svi117747 { 7212882Svi117747 sip_parsed_header_t *parsed_header; 7222882Svi117747 sip_hdr_value_t *value = NULL; 7232882Svi117747 sip_hdr_value_t *last_value = NULL; 7242882Svi117747 int ret; 7252882Svi117747 7262882Svi117747 if ((ret = sip_prim_parsers(hdr, phdr)) != 0) 7272882Svi117747 return (ret); 7282882Svi117747 7292882Svi117747 /* 7302882Svi117747 * check if previously parsed 7312882Svi117747 */ 7322882Svi117747 if (*phdr != NULL) { 7332882Svi117747 hdr->sip_hdr_parsed = *phdr; 7342882Svi117747 return (0); 7352882Svi117747 } 7362882Svi117747 parsed_header = calloc(1, sizeof (sip_parsed_header_t)); 7372882Svi117747 if (parsed_header == NULL) 7382882Svi117747 return (ENOMEM); 7392882Svi117747 parsed_header->sip_parsed_header_version = SIP_PARSED_HEADER_VERSION_1; 7402882Svi117747 parsed_header->sip_header = hdr; 7412882Svi117747 while (hdr->sip_hdr_current < hdr->sip_hdr_end) { 7422882Svi117747 int r; 7432882Svi117747 7442882Svi117747 value = calloc(1, sizeof (sip_hdr_value_t)); 7452882Svi117747 if (value == NULL) { 7462882Svi117747 sip_free_phdr(parsed_header); 7472882Svi117747 return (ENOMEM); 7482882Svi117747 } 7492882Svi117747 7502882Svi117747 if (last_value != NULL) 7512882Svi117747 last_value->sip_next_value = value; 7522882Svi117747 else 7532882Svi117747 parsed_header->value = (sip_value_t *)value; 7542882Svi117747 7552882Svi117747 value->sip_value_start = hdr->sip_hdr_current; 7562882Svi117747 value->sip_value_header = parsed_header; 7572882Svi117747 7582882Svi117747 if (type == SIP_STRS_VAL) { 7592882Svi117747 if (sip_find_token(hdr, SIP_LAQUOT) == 0) { 7602882Svi117747 char *cur; 7612882Svi117747 7622882Svi117747 /* 7632882Svi117747 * record the position after LAQUOT 7642882Svi117747 */ 7652882Svi117747 cur = hdr->sip_hdr_current; 7662882Svi117747 /* 7672882Svi117747 * get display name and store in str1 7682882Svi117747 */ 7692882Svi117747 hdr->sip_hdr_current = value->sip_value_start; 7702882Svi117747 if (*(hdr->sip_hdr_current) != SIP_LAQUOT) { 7712882Svi117747 /* 7722882Svi117747 * record start pos of display name 7732882Svi117747 */ 7742882Svi117747 char *tmp = hdr->sip_hdr_current; 7752882Svi117747 7762882Svi117747 if (*hdr->sip_hdr_current == 7772882Svi117747 SIP_QUOTE) { 7782882Svi117747 hdr->sip_hdr_current++; 7792882Svi117747 tmp++; 7802882Svi117747 if (sip_find_token(hdr, 7812882Svi117747 SIP_QUOTE) != 0) { 7822882Svi117747 value->sip_value_state = 7832882Svi117747 SIP_VALUE_BAD; 7842882Svi117747 goto get_next_val; 7852882Svi117747 } 7862882Svi117747 hdr->sip_hdr_current -= 2; 7872882Svi117747 } else { 7882882Svi117747 hdr->sip_hdr_current = cur - 2; 7892882Svi117747 (void) 7902882Svi117747 sip_reverse_skip_white_space 7912882Svi117747 (hdr); 7922882Svi117747 } 7932882Svi117747 value->strs1_val_ptr = tmp; 7942882Svi117747 value->strs1_val_len = 7952882Svi117747 hdr->sip_hdr_current - tmp + 1; 7962882Svi117747 } else { 7972882Svi117747 value->strs1_val_ptr = NULL; 7982882Svi117747 value->strs1_val_len = 0; 7992882Svi117747 } 8002882Svi117747 8012882Svi117747 /* 8022882Svi117747 * set current to the char after LAQUOT 8032882Svi117747 */ 8042882Svi117747 hdr->sip_hdr_current = cur; 8052882Svi117747 value->strs2_val_ptr = hdr->sip_hdr_current; 8062882Svi117747 if (sip_find_token(hdr, SIP_RAQUOT)) { 8072882Svi117747 /* 8082882Svi117747 * no RAQUOT 8092882Svi117747 */ 8102882Svi117747 value->strs1_val_ptr = NULL; 8112882Svi117747 value->strs1_val_len = 0; 8122882Svi117747 value->strs2_val_ptr = NULL; 8132882Svi117747 value->strs2_val_len = 0; 8142882Svi117747 value->sip_value_state = SIP_VALUE_BAD; 8152882Svi117747 goto get_next_val; 8162882Svi117747 } 8172882Svi117747 value->strs2_val_len = hdr->sip_hdr_current - 8182882Svi117747 value->strs2_val_ptr - 1; 8192882Svi117747 } else { 8202882Svi117747 char *cur; 8212882Svi117747 8222882Svi117747 /* 8232882Svi117747 * No display name - Only URI. 8242882Svi117747 */ 8252882Svi117747 value->strs1_val_ptr = NULL; 8262882Svi117747 value->strs1_val_len = 0; 8272882Svi117747 cur = value->sip_value_start; 8282882Svi117747 hdr->sip_hdr_current = cur; 8292882Svi117747 if (sip_find_separator(hdr, SIP_COMMA, 830*5092Sgm209912 (char)NULL, (char)NULL, B_FALSE) != 0) { 8312882Svi117747 value->strs2_val_ptr = cur; 8322882Svi117747 value->strs2_val_len = 8332882Svi117747 hdr->sip_hdr_current - 8342882Svi117747 value->strs2_val_ptr - 1; 8352882Svi117747 } else if (*hdr->sip_hdr_current == SIP_SP) { 8362882Svi117747 value->strs2_val_ptr = cur; 8372882Svi117747 cur = hdr->sip_hdr_current - 1; 8382882Svi117747 if (sip_skip_white_space(hdr) != 0) { 8392882Svi117747 value->strs2_val_len = cur - 8402882Svi117747 value->strs2_val_ptr - 1; 8412882Svi117747 } else if (*hdr->sip_hdr_current == 8422882Svi117747 SIP_COMMA) { 8432882Svi117747 value->strs2_val_len = cur - 8442882Svi117747 value->strs2_val_ptr - 1; 8452882Svi117747 } else { 8462882Svi117747 value->sip_value_state = 8472882Svi117747 SIP_VALUE_BAD; 8482882Svi117747 goto get_next_val; 8492882Svi117747 } 8502882Svi117747 } else { 8512882Svi117747 value->strs2_val_ptr = cur; 8522882Svi117747 value->strs2_val_len = 8532882Svi117747 hdr->sip_hdr_current - 8542882Svi117747 value->strs2_val_ptr; 8552882Svi117747 } 8562882Svi117747 } 8572882Svi117747 if (parse_uri) 8582882Svi117747 sip_parse_uri_str(&value->strs_s2, value); 8592882Svi117747 } 8602882Svi117747 8612882Svi117747 if (type == SIP_STR_VAL) { 8622882Svi117747 /* 8632882Svi117747 * alert-info, error-info, call-info 8642882Svi117747 */ 8652882Svi117747 if (sip_find_token(hdr, SIP_LAQUOT) == 0) { 8662882Svi117747 value->str_val_ptr = hdr->sip_hdr_current; 8672882Svi117747 if (sip_find_token(hdr, SIP_RAQUOT) == 0) { 8682882Svi117747 value->str_val_len = 8692882Svi117747 hdr->sip_hdr_current - 870*5092Sgm209912 value->str_val_ptr - 1; 8712882Svi117747 } else { 8722882Svi117747 value->str_val_ptr = NULL; 8732882Svi117747 value->str_val_len = 0; 8742882Svi117747 value->sip_value_state = SIP_VALUE_BAD; 8752882Svi117747 goto get_next_val; 8762882Svi117747 } 8772882Svi117747 hdr->sip_hdr_current--; 8782882Svi117747 } else { 8792882Svi117747 value->str_val_ptr = NULL; 8802882Svi117747 value->str_val_len = 0; 8812882Svi117747 value->sip_value_state = SIP_VALUE_BAD; 8822882Svi117747 goto get_next_val; 8832882Svi117747 } 8842882Svi117747 if (parse_uri) 8852882Svi117747 sip_parse_uri_str(&value->str_val, value); 8862882Svi117747 } 8872882Svi117747 888*5092Sgm209912 r = sip_find_separator(hdr, SIP_COMMA, SIP_SEMI, (char)NULL, 889*5092Sgm209912 B_FALSE); 8902882Svi117747 if (r != 0) { 8912882Svi117747 value->sip_value_end = hdr->sip_hdr_current; 8922882Svi117747 goto end; 8932882Svi117747 } 8942882Svi117747 if (*hdr->sip_hdr_current == SIP_SEMI) { 8952882Svi117747 (void) sip_parse_params(hdr, 8962882Svi117747 &(value->sip_param_list)); 8972882Svi117747 goto get_next_val; 8982882Svi117747 } 8992882Svi117747 9002882Svi117747 if (*hdr->sip_hdr_current == SIP_COMMA) { 9012882Svi117747 hdr->sip_hdr_current--; 9022882Svi117747 goto get_next_val; 9032882Svi117747 } 9042882Svi117747 get_next_val: 9052882Svi117747 if (sip_find_token(hdr, SIP_COMMA) != 0) { 9062882Svi117747 value->sip_value_end = hdr->sip_hdr_current; 9072882Svi117747 break; 9082882Svi117747 } 9092882Svi117747 value->sip_value_end = hdr->sip_hdr_current - 1; 9102882Svi117747 last_value = value; 9112882Svi117747 (void) sip_skip_white_space(hdr); 9122882Svi117747 } 9132882Svi117747 9142882Svi117747 end: 9152882Svi117747 *phdr = parsed_header; 9162882Svi117747 hdr->sip_hdr_parsed = *phdr; 9172882Svi117747 return (0); 9182882Svi117747 } 9192882Svi117747 9202882Svi117747 /* 9212882Svi117747 * parser4 parses hdr format, the whole field is one single str 9222882Svi117747 * header: Subject, MIME-Version, Organization, Server, User-Agent 9232882Svi117747 */ 9242882Svi117747 int 9252882Svi117747 sip_parse_hdr_parser4(_sip_header_t *hdr, sip_parsed_header_t **phdr) 9262882Svi117747 { 9272882Svi117747 sip_parsed_header_t *parsed_header; 9282882Svi117747 sip_hdr_value_t *value = NULL; 9292882Svi117747 int ret; 9302882Svi117747 9312882Svi117747 if ((ret = sip_prim_parsers(hdr, phdr)) != 0) 9322882Svi117747 return (ret); 9332882Svi117747 9342882Svi117747 /* 9352882Svi117747 * check if previously parsed 9362882Svi117747 */ 9372882Svi117747 if (*phdr != NULL) { 9382882Svi117747 hdr->sip_hdr_parsed = *phdr; 9392882Svi117747 return (0); 9402882Svi117747 } 9412882Svi117747 parsed_header = calloc(1, sizeof (sip_parsed_header_t)); 9422882Svi117747 if (parsed_header == NULL) 9432882Svi117747 return (ENOMEM); 9442882Svi117747 parsed_header->sip_parsed_header_version = SIP_PARSED_HEADER_VERSION_1; 9452882Svi117747 parsed_header->sip_header = hdr; 9462882Svi117747 9472882Svi117747 value = calloc(1, sizeof (sip_hdr_value_t)); 9482882Svi117747 if (value == NULL) { 9492882Svi117747 sip_free_phdr(parsed_header); 9502882Svi117747 return (ENOMEM); 9512882Svi117747 } 9522882Svi117747 9532882Svi117747 parsed_header->value = (sip_value_t *)value; 9542882Svi117747 9552882Svi117747 value->sip_value_start = hdr->sip_hdr_current; 9562882Svi117747 value->sip_value_header = parsed_header; 9572882Svi117747 9582882Svi117747 value->str_val_ptr = hdr->sip_hdr_current; 9592882Svi117747 /* 9602882Svi117747 * get rid of CRLF at end 9612882Svi117747 */ 9622882Svi117747 value->str_val_len = hdr->sip_hdr_end - value->str_val_ptr - 2; 9632882Svi117747 value->sip_value_end = hdr->sip_hdr_end; 9642882Svi117747 9652882Svi117747 *phdr = parsed_header; 9662882Svi117747 hdr->sip_hdr_parsed = *phdr; 9672882Svi117747 return (0); 9682882Svi117747 } 9692882Svi117747 9702882Svi117747 int 9712882Svi117747 sip_parse_hdr_parser5(_sip_header_t *hdr, sip_parsed_header_t **phdr, 9722882Svi117747 boolean_t parse_uri) 9732882Svi117747 { 9742882Svi117747 sip_parsed_header_t *parsed_header; 9752882Svi117747 sip_hdr_value_t *value = NULL; 9762882Svi117747 sip_param_t *tmp_param; 9772882Svi117747 boolean_t first_param = B_TRUE; 9782882Svi117747 int ret; 9792882Svi117747 9802882Svi117747 if ((ret = sip_prim_parsers(hdr, phdr)) != 0) 9812882Svi117747 return (ret); 9822882Svi117747 9832882Svi117747 /* 9842882Svi117747 * check if previously parsed 9852882Svi117747 */ 9862882Svi117747 if (*phdr != NULL) { 9872882Svi117747 hdr->sip_hdr_parsed = *phdr; 9882882Svi117747 return (0); 9892882Svi117747 } 9902882Svi117747 parsed_header = calloc(1, sizeof (sip_parsed_header_t)); 9912882Svi117747 if (parsed_header == NULL) 9922882Svi117747 return (ENOMEM); 9932882Svi117747 parsed_header->sip_parsed_header_version = SIP_PARSED_HEADER_VERSION_1; 9942882Svi117747 parsed_header->sip_header = hdr; 9952882Svi117747 9962882Svi117747 value = calloc(1, sizeof (sip_hdr_value_t)); 9972882Svi117747 if (value == NULL) { 9982882Svi117747 sip_free_phdr(parsed_header); 9992882Svi117747 return (ENOMEM); 10002882Svi117747 } 10012882Svi117747 10022882Svi117747 parsed_header->value = (sip_value_t *)value; 10032882Svi117747 10042882Svi117747 value->sip_value_start = hdr->sip_hdr_current; 10052882Svi117747 value->auth_scheme_ptr = value->sip_value_start; 10062882Svi117747 value->sip_value_header = parsed_header; 10072882Svi117747 /* 10082882Svi117747 * get auth_scheme 10092882Svi117747 */ 10102882Svi117747 if (sip_find_white_space(hdr)) { 10112882Svi117747 value->sip_value_state = SIP_VALUE_BAD; 10122882Svi117747 return (EINVAL); 10132882Svi117747 } 10142882Svi117747 value->auth_scheme_len = hdr->sip_hdr_current - value->auth_scheme_ptr; 10152882Svi117747 10162882Svi117747 tmp_param = value->auth_param; 10172882Svi117747 10182882Svi117747 /* 10192882Svi117747 * parse auth_param 10202882Svi117747 */ 10212882Svi117747 for (;;) { 10222882Svi117747 char *tmp_cur; 10232882Svi117747 boolean_t quoted_name = B_FALSE; 10242882Svi117747 char quoted_char = (char)0; 10252882Svi117747 sip_param_t *new_param; 10262882Svi117747 boolean_t pval_is_uri = B_FALSE; 10272882Svi117747 10282882Svi117747 if (sip_skip_white_space(hdr) != 0) { 10292882Svi117747 value->sip_value_state = SIP_VALUE_BAD; 10302882Svi117747 return (EPROTO); 10312882Svi117747 } 10322882Svi117747 tmp_cur = hdr->sip_hdr_current; 10332882Svi117747 10342882Svi117747 new_param = calloc(1, sizeof (sip_param_t)); 10352882Svi117747 if (new_param == NULL) 10362882Svi117747 return (ENOMEM); 10372882Svi117747 10382882Svi117747 if (first_param == B_FALSE) 10392882Svi117747 tmp_param->param_next = new_param; 10402882Svi117747 else 10412882Svi117747 value->auth_param = new_param; 10422882Svi117747 10432882Svi117747 tmp_param = new_param; 10442882Svi117747 tmp_param->param_name.sip_str_ptr = tmp_cur; 10452882Svi117747 1046*5092Sgm209912 if (sip_find_separator(hdr, SIP_EQUAL, SIP_COMMA, (char)NULL, 1047*5092Sgm209912 B_FALSE) != 0) { 10482882Svi117747 tmp_param->param_name.sip_str_len = 10492882Svi117747 hdr->sip_hdr_current - tmp_cur; 10502882Svi117747 tmp_param->param_value.sip_str_ptr = NULL; 10512882Svi117747 tmp_param->param_value.sip_str_len = 0; 10522882Svi117747 value->sip_value_end = hdr->sip_hdr_current; 10532882Svi117747 goto end; 10542882Svi117747 } 10552882Svi117747 10562882Svi117747 /* 10572882Svi117747 * End of param name 10582882Svi117747 */ 10592882Svi117747 tmp_param->param_name.sip_str_len = hdr->sip_hdr_current - 10602882Svi117747 tmp_cur; 10612882Svi117747 10622882Svi117747 if (sip_skip_white_space(hdr) != 0 || 10632882Svi117747 *hdr->sip_hdr_current == SIP_COMMA) { 10642882Svi117747 tmp_param->param_value.sip_str_ptr = NULL; 10652882Svi117747 tmp_param->param_value.sip_str_len = 0; 10662882Svi117747 continue; 10672882Svi117747 } 10682882Svi117747 10692882Svi117747 /* 10702882Svi117747 * We are at EQUAL 10712882Svi117747 */ 10722882Svi117747 hdr->sip_hdr_current++; 10732882Svi117747 10742882Svi117747 if (sip_skip_white_space(hdr) != 0) { 10752882Svi117747 value->sip_value_state = SIP_VALUE_BAD; 10762882Svi117747 free(tmp_param); 10772882Svi117747 return (EPROTO); 10782882Svi117747 } 10792882Svi117747 10802882Svi117747 if (*hdr->sip_hdr_current == SIP_QUOTE || 10812882Svi117747 *hdr->sip_hdr_current == SIP_LAQUOT) { 10822882Svi117747 if (*hdr->sip_hdr_current == SIP_QUOTE) 10832882Svi117747 quoted_char = SIP_QUOTE; 10842882Svi117747 else { 10852882Svi117747 quoted_char = SIP_RAQUOT; 10862882Svi117747 pval_is_uri = B_TRUE; 10872882Svi117747 } 10882882Svi117747 hdr->sip_hdr_current++; 10892882Svi117747 quoted_name = B_TRUE; 10902882Svi117747 } 10912882Svi117747 10922882Svi117747 /* 10932882Svi117747 * start of param value 10942882Svi117747 */ 10952882Svi117747 tmp_cur = hdr->sip_hdr_current; 10962882Svi117747 tmp_param->param_value.sip_str_ptr = tmp_cur; 10972882Svi117747 if (quoted_name) { 10982882Svi117747 if (sip_find_token(hdr, quoted_char) != 0) { 10992882Svi117747 value->sip_value_state = SIP_VALUE_BAD; 11002882Svi117747 free(tmp_param); 11012882Svi117747 return (EPROTO); 11022882Svi117747 } 11032882Svi117747 tmp_param->param_value.sip_str_len = 11042882Svi117747 hdr->sip_hdr_current - tmp_cur - 1; 11052882Svi117747 } 11062882Svi117747 11072882Svi117747 if (sip_find_token(hdr, SIP_COMMA) != 0) { 11082882Svi117747 value->sip_value_end = hdr->sip_hdr_current; 11092882Svi117747 goto end; 11102882Svi117747 } else { 11112882Svi117747 if (!quoted_name) { 11122882Svi117747 char *t = hdr->sip_hdr_current; 11132882Svi117747 hdr->sip_hdr_current--; 11142882Svi117747 (void) sip_reverse_skip_white_space(hdr); 11152882Svi117747 tmp_param->param_value.sip_str_len = 11162882Svi117747 hdr->sip_hdr_current - tmp_cur; 11172882Svi117747 hdr->sip_hdr_current = t; 11182882Svi117747 } 11192882Svi117747 } 11202882Svi117747 11212882Svi117747 if (first_param == B_TRUE) 11222882Svi117747 first_param = B_FALSE; 11232882Svi117747 11242882Svi117747 /* 11252882Svi117747 * Parse uri 11262882Svi117747 */ 11272882Svi117747 if (pval_is_uri && parse_uri) 11282882Svi117747 sip_parse_uri_str(&tmp_param->param_value, value); 11292882Svi117747 11302882Svi117747 } 11312882Svi117747 11322882Svi117747 end: 11332882Svi117747 *phdr = parsed_header; 11342882Svi117747 hdr->sip_hdr_parsed = *phdr; 11352882Svi117747 return (0); 11362882Svi117747 } 11372882Svi117747 11382882Svi117747 /* 11392882Svi117747 * Return the URI in the request startline 11402882Svi117747 */ 11412882Svi117747 static int 11422882Svi117747 _sip_get_request_uri(_sip_header_t *sip_header, sip_message_type_t *msg_info) 11432882Svi117747 { 11442882Svi117747 int size = 0; 11452882Svi117747 char *start_ptr; 11462882Svi117747 11472882Svi117747 if (sip_skip_white_space(sip_header) != 0) 11482882Svi117747 return (EINVAL); 11492882Svi117747 start_ptr = sip_header->sip_hdr_current; 11502882Svi117747 11512882Svi117747 while (!isspace(*sip_header->sip_hdr_current)) { 11522882Svi117747 if (sip_header->sip_hdr_current >= sip_header->sip_hdr_end) 11532882Svi117747 return (EINVAL); 11542882Svi117747 sip_header->sip_hdr_current++; 11552882Svi117747 } 11562882Svi117747 11572882Svi117747 size = sip_header->sip_hdr_current - start_ptr; 11582882Svi117747 11592882Svi117747 msg_info->U.sip_request.sip_request_uri.sip_str_ptr = start_ptr; 11602882Svi117747 msg_info->U.sip_request.sip_request_uri.sip_str_len = size; 11612882Svi117747 if (size > 0) { /* Parse uri */ 11622882Svi117747 int error; 11632882Svi117747 11642882Svi117747 msg_info->U.sip_request.sip_parse_uri = sip_parse_uri( 11652882Svi117747 &msg_info->U.sip_request.sip_request_uri, &error); 11662882Svi117747 if (msg_info->U.sip_request.sip_parse_uri == NULL) 11672882Svi117747 return (error); 11682882Svi117747 } 11692882Svi117747 return (0); 11702882Svi117747 } 11712882Svi117747 11722882Svi117747 /* 11732882Svi117747 * Parse the start line into request/response 11742882Svi117747 */ 11752882Svi117747 int 11762882Svi117747 sip_parse_first_line(_sip_header_t *sip_header, sip_message_type_t **msg_info) 11772882Svi117747 { 11782882Svi117747 sip_message_type_t *sip_msg_info; 11792882Svi117747 boolean_t sip_is_request = B_TRUE; 11802882Svi117747 int ret; 11812882Svi117747 11822882Svi117747 if (sip_header == NULL || msg_info == NULL) 11832882Svi117747 return (EINVAL); 11842882Svi117747 11852882Svi117747 if (sip_skip_white_space(sip_header) != 0) 11862882Svi117747 return (EPROTO); 11872882Svi117747 11882882Svi117747 /* 11892882Svi117747 * There is nothing, return 11902882Svi117747 */ 11912882Svi117747 if (sip_header->sip_hdr_current + strlen(SIP_VERSION) >= 11922882Svi117747 sip_header->sip_hdr_end) { 11932882Svi117747 return (EPROTO); 11942882Svi117747 } 11952882Svi117747 #ifdef __solaris__ 11962882Svi117747 assert(mutex_held(&sip_header->sip_hdr_sipmsg->sip_msg_mutex)); 11972882Svi117747 #endif 11982882Svi117747 sip_msg_info = malloc(sizeof (sip_message_type_t)); 11992882Svi117747 if (sip_msg_info == NULL) 12002882Svi117747 return (ENOMEM); 12012882Svi117747 12022882Svi117747 /* 12032882Svi117747 * let's see if it's a request or a response 12042882Svi117747 */ 12052882Svi117747 ret = sip_get_protocol_version(sip_header, 12062882Svi117747 &sip_msg_info->sip_proto_version); 12072882Svi117747 if (ret == 0) { 12082882Svi117747 sip_is_request = B_FALSE; 12092882Svi117747 } else if (ret == 2) { 12102882Svi117747 free(sip_msg_info); 12112882Svi117747 return (EPROTO); 12122882Svi117747 } 12132882Svi117747 12142882Svi117747 if (sip_skip_white_space(sip_header) != 0) { 12152882Svi117747 free(sip_msg_info); 12162882Svi117747 return (EPROTO); 12172882Svi117747 } 12182882Svi117747 12192882Svi117747 if (!sip_is_request) { 12202882Svi117747 /* 12212882Svi117747 * check for status code. 12222882Svi117747 */ 12232882Svi117747 if (sip_skip_white_space(sip_header) != 0) { 12242882Svi117747 free(sip_msg_info); 12252882Svi117747 return (EPROTO); 12262882Svi117747 } 12272882Svi117747 if (sip_header->sip_hdr_current + SIP_SIZE_OF_STATUS_CODE >= 12282882Svi117747 sip_header->sip_hdr_end) { 12292882Svi117747 free(sip_msg_info); 12302882Svi117747 return (EPROTO); 12312882Svi117747 } 12322882Svi117747 12332882Svi117747 if (sip_atoi(sip_header, 12342882Svi117747 &sip_msg_info->U.sip_response.sip_response_code)) { 12352882Svi117747 free(sip_msg_info); 12362882Svi117747 return (EPROTO); 12372882Svi117747 } 12382882Svi117747 12392882Svi117747 if (sip_msg_info->U.sip_response.sip_response_code < 100 || 12402882Svi117747 sip_msg_info->U.sip_response.sip_response_code > 700) { 12412882Svi117747 free(sip_msg_info); 12422882Svi117747 return (EPROTO); 12432882Svi117747 } 12442882Svi117747 12452882Svi117747 /* 12462882Svi117747 * get reason phrase. 12472882Svi117747 */ 12482882Svi117747 if (sip_skip_white_space(sip_header) != 0) { 12492882Svi117747 sip_msg_info->sip_resp_phrase_len = 0; 12502882Svi117747 sip_msg_info->sip_resp_phrase_ptr = NULL; 12512882Svi117747 } else { 12522882Svi117747 sip_msg_info->sip_resp_phrase_ptr = 12532882Svi117747 sip_header->sip_hdr_current; 12542882Svi117747 if (sip_find_cr(sip_header) != 0) { 12552882Svi117747 free(sip_msg_info); 12562882Svi117747 return (EPROTO); 12572882Svi117747 } 12582882Svi117747 sip_msg_info->sip_resp_phrase_len = 12592882Svi117747 sip_header->sip_hdr_current - 12602882Svi117747 sip_msg_info->sip_resp_phrase_ptr; 12612882Svi117747 } 12622882Svi117747 sip_msg_info->is_request = B_FALSE; 12632882Svi117747 } else { 12642882Svi117747 int i; 12652882Svi117747 /* 12662882Svi117747 * It's a request. 12672882Svi117747 */ 12682882Svi117747 sip_msg_info->is_request = B_TRUE; 12692882Svi117747 for (i = 1; i < MAX_SIP_METHODS; i++) { 12702882Svi117747 if (strncmp(sip_methods[i].name, 12712882Svi117747 sip_header->sip_hdr_current, 12722882Svi117747 sip_methods[i].len) == 0) { 12732882Svi117747 sip_msg_info->sip_req_method = i; 12742882Svi117747 sip_header->sip_hdr_current += 12752882Svi117747 sip_methods[i].len; 12762882Svi117747 if (!isspace(*sip_header->sip_hdr_current++) || 12772882Svi117747 !isalpha(*sip_header->sip_hdr_current)) { 12782882Svi117747 free(sip_msg_info); 12792882Svi117747 return (EPROTO); 12802882Svi117747 } 12812882Svi117747 12822882Svi117747 if ((ret = _sip_get_request_uri(sip_header, 12832882Svi117747 sip_msg_info)) != 0) { 12842882Svi117747 free(sip_msg_info); 12852882Svi117747 return (ret); 12862882Svi117747 } 12872882Svi117747 12882882Svi117747 /* 12892882Svi117747 * Get SIP version 12902882Svi117747 */ 12912882Svi117747 ret = sip_get_protocol_version(sip_header, 12922882Svi117747 &sip_msg_info->sip_proto_version); 12932882Svi117747 if (ret != 0) { 12942882Svi117747 free(sip_msg_info); 12952882Svi117747 return (EPROTO); 12962882Svi117747 } 12972882Svi117747 goto done; 12982882Svi117747 } 12992882Svi117747 } 13002882Svi117747 free(sip_msg_info); 13012882Svi117747 return (EPROTO); 13022882Svi117747 } 13032882Svi117747 done: 13042882Svi117747 sip_msg_info->sip_next = *msg_info; 13052882Svi117747 *msg_info = sip_msg_info; 13062882Svi117747 return (0); 13072882Svi117747 } 1308