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