1*2882Svi117747 /* 2*2882Svi117747 * CDDL HEADER START 3*2882Svi117747 * 4*2882Svi117747 * The contents of this file are subject to the terms of the 5*2882Svi117747 * Common Development and Distribution License (the "License"). 6*2882Svi117747 * You may not use this file except in compliance with the License. 7*2882Svi117747 * 8*2882Svi117747 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*2882Svi117747 * or http://www.opensolaris.org/os/licensing. 10*2882Svi117747 * See the License for the specific language governing permissions 11*2882Svi117747 * and limitations under the License. 12*2882Svi117747 * 13*2882Svi117747 * When distributing Covered Code, include this CDDL HEADER in each 14*2882Svi117747 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*2882Svi117747 * If applicable, add the following below this CDDL HEADER, with the 16*2882Svi117747 * fields enclosed by brackets "[]" replaced with your own identifying 17*2882Svi117747 * information: Portions Copyright [yyyy] [name of copyright owner] 18*2882Svi117747 * 19*2882Svi117747 * CDDL HEADER END 20*2882Svi117747 */ 21*2882Svi117747 22*2882Svi117747 /* 23*2882Svi117747 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 24*2882Svi117747 * Use is subject to license terms. 25*2882Svi117747 */ 26*2882Svi117747 27*2882Svi117747 #pragma ident "%Z%%M% %I% %E% SMI" 28*2882Svi117747 29*2882Svi117747 #include "sip_parse_uri.h" 30*2882Svi117747 #include "sip_msg.h" 31*2882Svi117747 #include "sip_miscdefs.h" 32*2882Svi117747 33*2882Svi117747 /* 34*2882Svi117747 * atoi function from a header 35*2882Svi117747 */ 36*2882Svi117747 int 37*2882Svi117747 sip_atoi(_sip_header_t *sip_header, int *num) 38*2882Svi117747 { 39*2882Svi117747 boolean_t num_found = B_FALSE; 40*2882Svi117747 41*2882Svi117747 *num = 0; 42*2882Svi117747 while (sip_header->sip_hdr_current < sip_header->sip_hdr_end) { 43*2882Svi117747 if (isspace(*sip_header->sip_hdr_current)) { 44*2882Svi117747 sip_header->sip_hdr_current++; 45*2882Svi117747 if (num_found) 46*2882Svi117747 break; 47*2882Svi117747 } else if (isdigit(*sip_header->sip_hdr_current)) { 48*2882Svi117747 *num = (*num * 10) + 49*2882Svi117747 (*sip_header->sip_hdr_current - '0'); 50*2882Svi117747 num_found = B_TRUE; 51*2882Svi117747 sip_header->sip_hdr_current++; 52*2882Svi117747 } else { 53*2882Svi117747 break; 54*2882Svi117747 } 55*2882Svi117747 } 56*2882Svi117747 if (!num_found) 57*2882Svi117747 return (EINVAL); 58*2882Svi117747 return (0); 59*2882Svi117747 } 60*2882Svi117747 61*2882Svi117747 /* 62*2882Svi117747 * Find the 'token' 63*2882Svi117747 */ 64*2882Svi117747 int 65*2882Svi117747 sip_find_token(_sip_header_t *sip_header, char token) 66*2882Svi117747 { 67*2882Svi117747 while (sip_header->sip_hdr_current < sip_header->sip_hdr_end) { 68*2882Svi117747 if (token != SIP_COMMA && 69*2882Svi117747 *sip_header->sip_hdr_current == SIP_COMMA) { 70*2882Svi117747 sip_header->sip_hdr_current--; 71*2882Svi117747 return (1); 72*2882Svi117747 } 73*2882Svi117747 if (*sip_header->sip_hdr_current++ == token) { 74*2882Svi117747 /* 75*2882Svi117747 * sip_hdr_current points to the char 76*2882Svi117747 * after the token 77*2882Svi117747 */ 78*2882Svi117747 return (0); 79*2882Svi117747 } 80*2882Svi117747 } 81*2882Svi117747 return (1); 82*2882Svi117747 } 83*2882Svi117747 84*2882Svi117747 /* 85*2882Svi117747 * Find a carriage-return 86*2882Svi117747 */ 87*2882Svi117747 int 88*2882Svi117747 sip_find_cr(_sip_header_t *sip_header) 89*2882Svi117747 { 90*2882Svi117747 sip_header->sip_hdr_current = sip_header->sip_hdr_end; 91*2882Svi117747 while (*sip_header->sip_hdr_current-- != '\n') { 92*2882Svi117747 if (sip_header->sip_hdr_current == sip_header->sip_hdr_start) 93*2882Svi117747 return (1); 94*2882Svi117747 } 95*2882Svi117747 return (0); 96*2882Svi117747 } 97*2882Svi117747 98*2882Svi117747 /* 99*2882Svi117747 * Find one of the separator provided, i.e. separator_1st or separator_2nd or 100*2882Svi117747 * separator_3rd. 101*2882Svi117747 */ 102*2882Svi117747 int 103*2882Svi117747 sip_find_separator(_sip_header_t *sip_header, char separator_1st, 104*2882Svi117747 char separator_2nd, char separator_3rd) 105*2882Svi117747 { 106*2882Svi117747 assert(separator_1st != (char)NULL || separator_2nd != (char)NULL); 107*2882Svi117747 while (sip_header->sip_hdr_current < sip_header->sip_hdr_end) { 108*2882Svi117747 if (isspace(*sip_header->sip_hdr_current) || 109*2882Svi117747 (separator_1st != (char)NULL && 110*2882Svi117747 (*sip_header->sip_hdr_current == separator_1st)) || 111*2882Svi117747 (separator_2nd != (char)NULL && 112*2882Svi117747 (*sip_header->sip_hdr_current == separator_2nd)) || 113*2882Svi117747 (separator_3rd != (char)NULL && 114*2882Svi117747 (*sip_header->sip_hdr_current == separator_3rd))) { 115*2882Svi117747 return (0); 116*2882Svi117747 } 117*2882Svi117747 /* 118*2882Svi117747 * If we have escape character, go to the next char 119*2882Svi117747 */ 120*2882Svi117747 if (*sip_header->sip_hdr_current == '\\') 121*2882Svi117747 sip_header->sip_hdr_current++; 122*2882Svi117747 sip_header->sip_hdr_current++; 123*2882Svi117747 } 124*2882Svi117747 return (1); 125*2882Svi117747 } 126*2882Svi117747 127*2882Svi117747 /* 128*2882Svi117747 * Return when we hit a white space 129*2882Svi117747 */ 130*2882Svi117747 int 131*2882Svi117747 sip_find_white_space(_sip_header_t *sip_header) 132*2882Svi117747 { 133*2882Svi117747 while (sip_header->sip_hdr_current < sip_header->sip_hdr_end) { 134*2882Svi117747 if (isspace(*sip_header->sip_hdr_current)) 135*2882Svi117747 return (0); 136*2882Svi117747 sip_header->sip_hdr_current++; 137*2882Svi117747 } 138*2882Svi117747 return (1); 139*2882Svi117747 } 140*2882Svi117747 141*2882Svi117747 /* 142*2882Svi117747 * Skip to the next non-whitespace 143*2882Svi117747 */ 144*2882Svi117747 int 145*2882Svi117747 sip_skip_white_space(_sip_header_t *sip_header) 146*2882Svi117747 { 147*2882Svi117747 while (sip_header->sip_hdr_current < sip_header->sip_hdr_end) { 148*2882Svi117747 if (!isspace(*sip_header->sip_hdr_current)) 149*2882Svi117747 return (0); 150*2882Svi117747 sip_header->sip_hdr_current++; 151*2882Svi117747 } 152*2882Svi117747 return (1); 153*2882Svi117747 } 154*2882Svi117747 155*2882Svi117747 156*2882Svi117747 /* 157*2882Svi117747 * Skip to the non-white space in the reverse direction 158*2882Svi117747 */ 159*2882Svi117747 int 160*2882Svi117747 sip_reverse_skip_white_space(_sip_header_t *sip_header) 161*2882Svi117747 { 162*2882Svi117747 while (sip_header->sip_hdr_current >= sip_header->sip_hdr_start) { 163*2882Svi117747 if (!isspace(*sip_header->sip_hdr_current)) 164*2882Svi117747 return (0); 165*2882Svi117747 sip_header->sip_hdr_current--; 166*2882Svi117747 } 167*2882Svi117747 return (1); 168*2882Svi117747 } 169*2882Svi117747 170*2882Svi117747 /* 171*2882Svi117747 * get to the first non space after ':' 172*2882Svi117747 */ 173*2882Svi117747 int 174*2882Svi117747 sip_parse_goto_values(_sip_header_t *sip_header) 175*2882Svi117747 { 176*2882Svi117747 if (sip_find_token(sip_header, SIP_HCOLON) != 0) 177*2882Svi117747 return (1); 178*2882Svi117747 if (sip_skip_white_space(sip_header) != 0) 179*2882Svi117747 return (1); 180*2882Svi117747 181*2882Svi117747 return (0); 182*2882Svi117747 } 183*2882Svi117747 184*2882Svi117747 /* 185*2882Svi117747 * Skip the current value. 186*2882Svi117747 */ 187*2882Svi117747 int 188*2882Svi117747 sip_goto_next_value(_sip_header_t *sip_header) 189*2882Svi117747 { 190*2882Svi117747 boolean_t quoted = B_FALSE; 191*2882Svi117747 192*2882Svi117747 while (sip_header->sip_hdr_current < sip_header->sip_hdr_end) { 193*2882Svi117747 if (*sip_header->sip_hdr_current == SIP_QUOTE) { 194*2882Svi117747 if (quoted) 195*2882Svi117747 quoted = B_FALSE; 196*2882Svi117747 else 197*2882Svi117747 quoted = B_TRUE; 198*2882Svi117747 } else if (!quoted && 199*2882Svi117747 *sip_header->sip_hdr_current == SIP_COMMA) { 200*2882Svi117747 /* 201*2882Svi117747 * value ends before the COMMA 202*2882Svi117747 */ 203*2882Svi117747 sip_header->sip_hdr_current--; 204*2882Svi117747 return (0); 205*2882Svi117747 } 206*2882Svi117747 sip_header->sip_hdr_current++; 207*2882Svi117747 } 208*2882Svi117747 if (quoted) 209*2882Svi117747 return (1); 210*2882Svi117747 return (0); 211*2882Svi117747 } 212*2882Svi117747 213*2882Svi117747 /* 214*2882Svi117747 * Parse the header into parameter list. Parameters start with a ';' 215*2882Svi117747 */ 216*2882Svi117747 int 217*2882Svi117747 sip_parse_params(_sip_header_t *sip_header, sip_param_t **parsed_list) 218*2882Svi117747 { 219*2882Svi117747 sip_param_t *param = NULL; 220*2882Svi117747 sip_param_t *new_param; 221*2882Svi117747 char *tmp_ptr; 222*2882Svi117747 223*2882Svi117747 if (parsed_list == NULL) 224*2882Svi117747 return (0); 225*2882Svi117747 226*2882Svi117747 *parsed_list = NULL; 227*2882Svi117747 for (;;) { 228*2882Svi117747 boolean_t quoted_name = B_FALSE; 229*2882Svi117747 230*2882Svi117747 /* 231*2882Svi117747 * First check if there are any params 232*2882Svi117747 */ 233*2882Svi117747 if (sip_skip_white_space(sip_header) != 0) 234*2882Svi117747 return (0); 235*2882Svi117747 if (*sip_header->sip_hdr_current != SIP_SEMI) 236*2882Svi117747 return (0); 237*2882Svi117747 238*2882Svi117747 sip_header->sip_hdr_current++; 239*2882Svi117747 240*2882Svi117747 new_param = calloc(1, sizeof (sip_param_t)); 241*2882Svi117747 if (new_param == NULL) 242*2882Svi117747 return (ENOMEM); 243*2882Svi117747 244*2882Svi117747 if (param != NULL) 245*2882Svi117747 param->param_next = new_param; 246*2882Svi117747 else 247*2882Svi117747 *parsed_list = new_param; 248*2882Svi117747 249*2882Svi117747 param = new_param; 250*2882Svi117747 251*2882Svi117747 /* 252*2882Svi117747 * Let's get to the start of the param name 253*2882Svi117747 */ 254*2882Svi117747 if (sip_skip_white_space(sip_header) != 0) 255*2882Svi117747 return (EPROTO); 256*2882Svi117747 /* 257*2882Svi117747 * start of param name 258*2882Svi117747 */ 259*2882Svi117747 tmp_ptr = sip_header->sip_hdr_current; 260*2882Svi117747 param->param_name.sip_str_ptr = tmp_ptr; 261*2882Svi117747 262*2882Svi117747 if (sip_find_separator(sip_header, SIP_EQUAL, SIP_SEMI, 263*2882Svi117747 SIP_COMMA) != 0) { 264*2882Svi117747 param->param_name.sip_str_len = 265*2882Svi117747 sip_header->sip_hdr_current - tmp_ptr; 266*2882Svi117747 param->param_value.sip_str_ptr = NULL; 267*2882Svi117747 param->param_value.sip_str_len = 0; 268*2882Svi117747 return (0); 269*2882Svi117747 } 270*2882Svi117747 271*2882Svi117747 /* 272*2882Svi117747 * End of param name 273*2882Svi117747 */ 274*2882Svi117747 param->param_name.sip_str_len = 275*2882Svi117747 sip_header->sip_hdr_current - tmp_ptr; 276*2882Svi117747 277*2882Svi117747 if (sip_skip_white_space(sip_header) != 0 || 278*2882Svi117747 *sip_header->sip_hdr_current == SIP_COMMA) { 279*2882Svi117747 param->param_value.sip_str_ptr = NULL; 280*2882Svi117747 param->param_value.sip_str_len = 0; 281*2882Svi117747 return (0); 282*2882Svi117747 } 283*2882Svi117747 if (*sip_header->sip_hdr_current == SIP_SEMI) { 284*2882Svi117747 param->param_value.sip_str_ptr = NULL; 285*2882Svi117747 param->param_value.sip_str_len = 0; 286*2882Svi117747 continue; 287*2882Svi117747 } 288*2882Svi117747 assert(*sip_header->sip_hdr_current == SIP_EQUAL); 289*2882Svi117747 290*2882Svi117747 /* 291*2882Svi117747 * We are at EQUAL, lets go beyond that 292*2882Svi117747 */ 293*2882Svi117747 sip_header->sip_hdr_current++; 294*2882Svi117747 295*2882Svi117747 if (sip_skip_white_space(sip_header) != 0) 296*2882Svi117747 return (EPROTO); 297*2882Svi117747 298*2882Svi117747 if (*sip_header->sip_hdr_current == SIP_QUOTE) { 299*2882Svi117747 sip_header->sip_hdr_current++; 300*2882Svi117747 quoted_name = B_TRUE; 301*2882Svi117747 } 302*2882Svi117747 303*2882Svi117747 /* 304*2882Svi117747 * start of param value 305*2882Svi117747 */ 306*2882Svi117747 param->param_value.sip_str_ptr = sip_header->sip_hdr_current; 307*2882Svi117747 tmp_ptr = sip_header->sip_hdr_current; 308*2882Svi117747 309*2882Svi117747 if (quoted_name && sip_find_token(sip_header, SIP_QUOTE) != 0) { 310*2882Svi117747 return (EPROTO); 311*2882Svi117747 } else if (sip_find_separator(sip_header, SIP_SEMI, SIP_COMMA, 312*2882Svi117747 (char)NULL) != 0) { 313*2882Svi117747 return (EPROTO); 314*2882Svi117747 } 315*2882Svi117747 param->param_value.sip_str_len = sip_header->sip_hdr_current - 316*2882Svi117747 tmp_ptr; 317*2882Svi117747 if (quoted_name) 318*2882Svi117747 param->param_value.sip_str_len--; 319*2882Svi117747 } 320*2882Svi117747 } 321*2882Svi117747 322*2882Svi117747 /* 323*2882Svi117747 * a header that only has "header_name : " is an empty header 324*2882Svi117747 * ":" must exist 325*2882Svi117747 * sip_hdr_current resets to sip_hdr_start before exit 326*2882Svi117747 */ 327*2882Svi117747 boolean_t 328*2882Svi117747 sip_is_empty_hdr(_sip_header_t *sip_header) 329*2882Svi117747 { 330*2882Svi117747 if (sip_find_token(sip_header, SIP_HCOLON) != 0) { 331*2882Svi117747 sip_header->sip_hdr_current = sip_header->sip_hdr_start; 332*2882Svi117747 return (B_FALSE); 333*2882Svi117747 } 334*2882Svi117747 335*2882Svi117747 if (sip_skip_white_space(sip_header) == 0) { 336*2882Svi117747 sip_header->sip_hdr_current = sip_header->sip_hdr_start; 337*2882Svi117747 return (B_FALSE); 338*2882Svi117747 } 339*2882Svi117747 340*2882Svi117747 sip_header->sip_hdr_current = sip_header->sip_hdr_start; 341*2882Svi117747 return (B_TRUE); 342*2882Svi117747 } 343*2882Svi117747 344*2882Svi117747 /* 345*2882Svi117747 * Parsing an empty header, i.e. only has a ":" 346*2882Svi117747 */ 347*2882Svi117747 int 348*2882Svi117747 sip_parse_hdr_empty(_sip_header_t *hdr, sip_parsed_header_t **phdr) 349*2882Svi117747 { 350*2882Svi117747 sip_parsed_header_t *parsed_header; 351*2882Svi117747 352*2882Svi117747 if (hdr == NULL || phdr == NULL) 353*2882Svi117747 return (EINVAL); 354*2882Svi117747 355*2882Svi117747 /* 356*2882Svi117747 * check if already parsed 357*2882Svi117747 */ 358*2882Svi117747 if (hdr->sip_hdr_parsed != NULL) { 359*2882Svi117747 *phdr = hdr->sip_hdr_parsed; 360*2882Svi117747 return (0); 361*2882Svi117747 } 362*2882Svi117747 363*2882Svi117747 *phdr = NULL; 364*2882Svi117747 365*2882Svi117747 parsed_header = calloc(1, sizeof (sip_parsed_header_t)); 366*2882Svi117747 if (parsed_header == NULL) 367*2882Svi117747 return (ENOMEM); 368*2882Svi117747 parsed_header->sip_header = hdr; 369*2882Svi117747 370*2882Svi117747 parsed_header->value = NULL; 371*2882Svi117747 372*2882Svi117747 *phdr = parsed_header; 373*2882Svi117747 return (0); 374*2882Svi117747 } 375*2882Svi117747 376*2882Svi117747 /* 377*2882Svi117747 * validate uri str and parse uri using uri_parse() 378*2882Svi117747 */ 379*2882Svi117747 static void 380*2882Svi117747 sip_parse_uri_str(sip_str_t *sip_str, sip_hdr_value_t *value) 381*2882Svi117747 { 382*2882Svi117747 int error; 383*2882Svi117747 384*2882Svi117747 /* 385*2882Svi117747 * Parse uri 386*2882Svi117747 */ 387*2882Svi117747 if (sip_str->sip_str_len > 0) { 388*2882Svi117747 value->sip_value_parsed_uri = sip_parse_uri(sip_str, &error); 389*2882Svi117747 if (value->sip_value_parsed_uri == NULL) 390*2882Svi117747 return; 391*2882Svi117747 if (error != 0 || 392*2882Svi117747 value->sip_value_parsed_uri->sip_uri_errflags != 0) { 393*2882Svi117747 value->sip_value_state = SIP_VALUE_BAD; 394*2882Svi117747 } 395*2882Svi117747 } 396*2882Svi117747 } 397*2882Svi117747 398*2882Svi117747 /* 399*2882Svi117747 * Some basic common checks before parsing the headers 400*2882Svi117747 */ 401*2882Svi117747 int 402*2882Svi117747 sip_prim_parsers(_sip_header_t *sip_header, sip_parsed_header_t **header) 403*2882Svi117747 { 404*2882Svi117747 if (sip_header == NULL || header == NULL) 405*2882Svi117747 return (EINVAL); 406*2882Svi117747 407*2882Svi117747 /* 408*2882Svi117747 * check if already parsed 409*2882Svi117747 */ 410*2882Svi117747 if (sip_header->sip_hdr_parsed != NULL) { 411*2882Svi117747 *header = sip_header->sip_hdr_parsed; 412*2882Svi117747 return (0); 413*2882Svi117747 } 414*2882Svi117747 *header = NULL; 415*2882Svi117747 416*2882Svi117747 assert(sip_header->sip_hdr_start == sip_header->sip_hdr_current); 417*2882Svi117747 418*2882Svi117747 if (sip_parse_goto_values(sip_header) != 0) 419*2882Svi117747 return (EPROTO); 420*2882Svi117747 421*2882Svi117747 return (0); 422*2882Svi117747 } 423*2882Svi117747 424*2882Svi117747 /* 425*2882Svi117747 * Parse SIP/2.0 string 426*2882Svi117747 */ 427*2882Svi117747 int 428*2882Svi117747 sip_get_protocol_version(_sip_header_t *sip_header, 429*2882Svi117747 sip_proto_version_t *sip_proto_version) 430*2882Svi117747 { 431*2882Svi117747 if (sip_skip_white_space(sip_header) != 0) 432*2882Svi117747 return (1); 433*2882Svi117747 434*2882Svi117747 if (strncasecmp(sip_header->sip_hdr_current, SIP, strlen(SIP)) == 0) { 435*2882Svi117747 sip_proto_version->name.sip_str_ptr = 436*2882Svi117747 sip_header->sip_hdr_current; 437*2882Svi117747 sip_proto_version->name.sip_str_len = strlen(SIP); 438*2882Svi117747 439*2882Svi117747 if (sip_find_token(sip_header, SIP_SLASH) != 0) 440*2882Svi117747 return (1); 441*2882Svi117747 if (sip_skip_white_space(sip_header) != 0) 442*2882Svi117747 return (1); 443*2882Svi117747 444*2882Svi117747 sip_proto_version->version.sip_str_ptr = 445*2882Svi117747 sip_header->sip_hdr_current; 446*2882Svi117747 while (isdigit(*sip_header->sip_hdr_current)) { 447*2882Svi117747 sip_header->sip_hdr_current++; 448*2882Svi117747 if (sip_header->sip_hdr_current >= 449*2882Svi117747 sip_header->sip_hdr_end) { 450*2882Svi117747 return (1); 451*2882Svi117747 } 452*2882Svi117747 } 453*2882Svi117747 if (*sip_header->sip_hdr_current != SIP_PERIOD) 454*2882Svi117747 return (1); 455*2882Svi117747 sip_header->sip_hdr_current++; 456*2882Svi117747 457*2882Svi117747 if (!isdigit(*sip_header->sip_hdr_current)) 458*2882Svi117747 return (1); 459*2882Svi117747 while (isdigit(*sip_header->sip_hdr_current)) { 460*2882Svi117747 sip_header->sip_hdr_current++; 461*2882Svi117747 if (sip_header->sip_hdr_current >= 462*2882Svi117747 sip_header->sip_hdr_end) { 463*2882Svi117747 return (1); 464*2882Svi117747 } 465*2882Svi117747 } 466*2882Svi117747 467*2882Svi117747 sip_proto_version->version.sip_str_len = 468*2882Svi117747 sip_header->sip_hdr_current - 469*2882Svi117747 sip_proto_version->version.sip_str_ptr; 470*2882Svi117747 return (0); 471*2882Svi117747 } 472*2882Svi117747 return (1); 473*2882Svi117747 } 474*2882Svi117747 475*2882Svi117747 /* 476*2882Svi117747 * parser1 parses hdr format 477*2882Svi117747 * header_name: val1[; par1=pval1;par2=pval2 ..][, val2[;parlist..] ] 478*2882Svi117747 * val can be str1/str2 or str 479*2882Svi117747 * headers: Accept, Accept-Encode, Accept-lang, Allow, Content-disp, 480*2882Svi117747 * Content-Encode, Content-Lang, In-reply-to, 481*2882Svi117747 * Priority, Require, Supported, Unsupported 482*2882Svi117747 * Allow-Events, Event, Subscription-State 483*2882Svi117747 */ 484*2882Svi117747 int 485*2882Svi117747 sip_parse_hdr_parser1(_sip_header_t *hdr, sip_parsed_header_t **phdr, char sep) 486*2882Svi117747 { 487*2882Svi117747 sip_parsed_header_t *parsed_header; 488*2882Svi117747 int ret; 489*2882Svi117747 sip_hdr_value_t *value = NULL; 490*2882Svi117747 sip_hdr_value_t *last_value = NULL; 491*2882Svi117747 492*2882Svi117747 if ((ret = sip_prim_parsers(hdr, phdr)) != 0) 493*2882Svi117747 return (ret); 494*2882Svi117747 495*2882Svi117747 /* 496*2882Svi117747 * check if previously parsed 497*2882Svi117747 */ 498*2882Svi117747 if (*phdr != NULL) { 499*2882Svi117747 hdr->sip_hdr_parsed = *phdr; 500*2882Svi117747 return (0); 501*2882Svi117747 } 502*2882Svi117747 503*2882Svi117747 parsed_header = calloc(1, sizeof (sip_parsed_header_t)); 504*2882Svi117747 if (parsed_header == NULL) 505*2882Svi117747 return (ENOMEM); 506*2882Svi117747 parsed_header->sip_parsed_header_version = SIP_PARSED_HEADER_VERSION_1; 507*2882Svi117747 parsed_header->sip_header = hdr; 508*2882Svi117747 509*2882Svi117747 while (hdr->sip_hdr_current < hdr->sip_hdr_end) { 510*2882Svi117747 value = calloc(1, sizeof (sip_hdr_value_t)); 511*2882Svi117747 if (value == NULL) { 512*2882Svi117747 sip_free_phdr(parsed_header); 513*2882Svi117747 return (ENOMEM); 514*2882Svi117747 } 515*2882Svi117747 if (last_value != NULL) 516*2882Svi117747 last_value->sip_next_value = value; 517*2882Svi117747 else 518*2882Svi117747 parsed_header->value = (sip_value_t *)value; 519*2882Svi117747 520*2882Svi117747 value->sip_value_start = hdr->sip_hdr_current; 521*2882Svi117747 value->sip_value_header = parsed_header; 522*2882Svi117747 523*2882Svi117747 if (sip_find_separator(hdr, sep, SIP_COMMA, SIP_SEMI) == 0) { 524*2882Svi117747 char c = *hdr->sip_hdr_current; 525*2882Svi117747 526*2882Svi117747 if (isspace(c) && sep == (char)NULL) { 527*2882Svi117747 value->str_val_ptr = value->sip_value_start; 528*2882Svi117747 value->str_val_len = hdr->sip_hdr_current - 529*2882Svi117747 value->sip_value_start; 530*2882Svi117747 /* 531*2882Svi117747 * nothing at the end except space 532*2882Svi117747 */ 533*2882Svi117747 if (sip_skip_white_space(hdr) != 0) { 534*2882Svi117747 value->sip_value_end = 535*2882Svi117747 hdr->sip_hdr_current; 536*2882Svi117747 goto end; 537*2882Svi117747 } 538*2882Svi117747 /* 539*2882Svi117747 * white space skipped 540*2882Svi117747 */ 541*2882Svi117747 c = *(hdr->sip_hdr_current); 542*2882Svi117747 } 543*2882Svi117747 544*2882Svi117747 /* 545*2882Svi117747 * only one string until COMMA, use sip_str_t 546*2882Svi117747 */ 547*2882Svi117747 if (c == SIP_COMMA) { 548*2882Svi117747 char *t = hdr->sip_hdr_current; 549*2882Svi117747 550*2882Svi117747 hdr->sip_hdr_current--; 551*2882Svi117747 (void) sip_reverse_skip_white_space(hdr); 552*2882Svi117747 value->str_val_ptr = value->sip_value_start; 553*2882Svi117747 value->str_val_len = hdr->sip_hdr_current - 554*2882Svi117747 value->sip_value_start + 1; 555*2882Svi117747 hdr->sip_hdr_current = t; 556*2882Svi117747 goto get_next_val; 557*2882Svi117747 } 558*2882Svi117747 559*2882Svi117747 /* 560*2882Svi117747 * two strings, use sip_2strs_t 561*2882Svi117747 */ 562*2882Svi117747 if ((sep != (char)NULL) && (c == sep)) { 563*2882Svi117747 value->strs1_val_ptr = value->sip_value_start; 564*2882Svi117747 value->strs1_val_len = hdr->sip_hdr_current - 565*2882Svi117747 value->sip_value_start; 566*2882Svi117747 567*2882Svi117747 value->strs2_val_ptr = 568*2882Svi117747 (++hdr->sip_hdr_current); 569*2882Svi117747 if (sip_find_separator(hdr, SIP_SEMI, SIP_COMMA, 570*2882Svi117747 (char)NULL) == 0) { 571*2882Svi117747 char t = *(hdr->sip_hdr_current); 572*2882Svi117747 value->strs2_val_len = 573*2882Svi117747 hdr->sip_hdr_current - 574*2882Svi117747 value->strs2_val_ptr; 575*2882Svi117747 /* 576*2882Svi117747 * if COMMA, no param list, get next val 577*2882Svi117747 * if SEMI, need to set params list 578*2882Svi117747 */ 579*2882Svi117747 if (t == SIP_COMMA) 580*2882Svi117747 goto get_next_val; 581*2882Svi117747 } else { /* the last part */ 582*2882Svi117747 value->strs2_val_len = 583*2882Svi117747 hdr->sip_hdr_current - 584*2882Svi117747 value->strs2_val_ptr; 585*2882Svi117747 value->sip_value_end = 586*2882Svi117747 hdr->sip_hdr_current; 587*2882Svi117747 goto end; 588*2882Svi117747 } 589*2882Svi117747 } else if (sep != (char)NULL) { 590*2882Svi117747 value->sip_value_state = SIP_VALUE_BAD; 591*2882Svi117747 goto get_next_val; 592*2882Svi117747 } 593*2882Svi117747 594*2882Svi117747 /* 595*2882Svi117747 * c == SEMI, value contains single string 596*2882Svi117747 * only one string until SEMI, use sip_str_t 597*2882Svi117747 */ 598*2882Svi117747 if (c == SIP_SEMI) { 599*2882Svi117747 char *t = hdr->sip_hdr_current; 600*2882Svi117747 601*2882Svi117747 hdr->sip_hdr_current--; 602*2882Svi117747 /* 603*2882Svi117747 * get rid of SP at end of value field 604*2882Svi117747 */ 605*2882Svi117747 (void) sip_reverse_skip_white_space(hdr); 606*2882Svi117747 value->str_val_ptr = value->sip_value_start; 607*2882Svi117747 value->str_val_len = hdr->sip_hdr_current - 608*2882Svi117747 value->str_val_ptr + 1; 609*2882Svi117747 hdr->sip_hdr_current = t; 610*2882Svi117747 } 611*2882Svi117747 612*2882Svi117747 /* 613*2882Svi117747 * if SEMI exists in the value, set params list 614*2882Svi117747 * two situations, there is or not SLASH before SEMI 615*2882Svi117747 */ 616*2882Svi117747 ret = sip_parse_params(hdr, &value->sip_param_list); 617*2882Svi117747 if (ret == EPROTO) { 618*2882Svi117747 value->sip_value_state = SIP_VALUE_BAD; 619*2882Svi117747 } else if (ret != 0) { 620*2882Svi117747 sip_free_phdr(parsed_header); 621*2882Svi117747 return (ret); 622*2882Svi117747 } 623*2882Svi117747 goto get_next_val; 624*2882Svi117747 } else { 625*2882Svi117747 value->str_val_ptr = value->sip_value_start; 626*2882Svi117747 value->str_val_len = hdr->sip_hdr_current - 627*2882Svi117747 value->sip_value_start; 628*2882Svi117747 value->sip_value_end = hdr->sip_hdr_current; 629*2882Svi117747 goto end; 630*2882Svi117747 } 631*2882Svi117747 get_next_val: 632*2882Svi117747 if (sip_find_token(hdr, SIP_COMMA) != 0) { 633*2882Svi117747 value->sip_value_end = hdr->sip_hdr_current; 634*2882Svi117747 break; 635*2882Svi117747 } 636*2882Svi117747 value->sip_value_end = hdr->sip_hdr_current - 1; 637*2882Svi117747 last_value = value; 638*2882Svi117747 (void) sip_skip_white_space(hdr); 639*2882Svi117747 } 640*2882Svi117747 641*2882Svi117747 end: 642*2882Svi117747 *phdr = parsed_header; 643*2882Svi117747 hdr->sip_hdr_parsed = *phdr; 644*2882Svi117747 return (0); 645*2882Svi117747 } 646*2882Svi117747 647*2882Svi117747 /* 648*2882Svi117747 * header_name: int 649*2882Svi117747 * headers: Expires, Min-Expires 650*2882Svi117747 */ 651*2882Svi117747 /* ARGSUSED */ 652*2882Svi117747 int 653*2882Svi117747 sip_parse_hdr_parser2(_sip_header_t *hdr, sip_parsed_header_t **phdr, 654*2882Svi117747 int val_type) 655*2882Svi117747 { 656*2882Svi117747 sip_parsed_header_t *parsed_header; 657*2882Svi117747 int ret = 0; 658*2882Svi117747 sip_hdr_value_t *value = NULL; 659*2882Svi117747 660*2882Svi117747 if ((ret = sip_prim_parsers(hdr, phdr)) != 0) 661*2882Svi117747 return (ret); 662*2882Svi117747 663*2882Svi117747 /* 664*2882Svi117747 * check if previously parsed 665*2882Svi117747 */ 666*2882Svi117747 if (*phdr != NULL) { 667*2882Svi117747 hdr->sip_hdr_parsed = *phdr; 668*2882Svi117747 return (0); 669*2882Svi117747 } 670*2882Svi117747 parsed_header = calloc(1, sizeof (sip_parsed_header_t)); 671*2882Svi117747 if (parsed_header == NULL) 672*2882Svi117747 return (ENOMEM); 673*2882Svi117747 parsed_header->sip_parsed_header_version = SIP_PARSED_HEADER_VERSION_1; 674*2882Svi117747 parsed_header->sip_header = hdr; 675*2882Svi117747 676*2882Svi117747 value = calloc(1, sizeof (sip_hdr_value_t)); 677*2882Svi117747 if (value == NULL) { 678*2882Svi117747 sip_free_phdr(parsed_header); 679*2882Svi117747 return (ENOMEM); 680*2882Svi117747 } 681*2882Svi117747 682*2882Svi117747 parsed_header->value = (sip_value_t *)value; 683*2882Svi117747 684*2882Svi117747 value->sip_value_start = hdr->sip_hdr_current; 685*2882Svi117747 value->sip_value_header = parsed_header; 686*2882Svi117747 687*2882Svi117747 ret = sip_atoi(hdr, &value->int_val); 688*2882Svi117747 if (ret != 0) { 689*2882Svi117747 value->int_val = 0; 690*2882Svi117747 value->sip_value_state = SIP_VALUE_BAD; 691*2882Svi117747 } 692*2882Svi117747 693*2882Svi117747 value->sip_value_end = hdr->sip_hdr_current - 1; 694*2882Svi117747 695*2882Svi117747 *phdr = parsed_header; 696*2882Svi117747 hdr->sip_hdr_parsed = *phdr; 697*2882Svi117747 return (0); 698*2882Svi117747 } 699*2882Svi117747 700*2882Svi117747 /* 701*2882Svi117747 * parser3 parses hdr format 702*2882Svi117747 * header_name: <val1>[, <val2>] 703*2882Svi117747 * Alert-Info, Call-Info, Error-Info, reply-to 704*2882Svi117747 */ 705*2882Svi117747 int 706*2882Svi117747 sip_parse_hdr_parser3(_sip_header_t *hdr, sip_parsed_header_t **phdr, int type, 707*2882Svi117747 boolean_t parse_uri) 708*2882Svi117747 { 709*2882Svi117747 sip_parsed_header_t *parsed_header; 710*2882Svi117747 sip_hdr_value_t *value = NULL; 711*2882Svi117747 sip_hdr_value_t *last_value = NULL; 712*2882Svi117747 int ret; 713*2882Svi117747 714*2882Svi117747 if ((ret = sip_prim_parsers(hdr, phdr)) != 0) 715*2882Svi117747 return (ret); 716*2882Svi117747 717*2882Svi117747 /* 718*2882Svi117747 * check if previously parsed 719*2882Svi117747 */ 720*2882Svi117747 if (*phdr != NULL) { 721*2882Svi117747 hdr->sip_hdr_parsed = *phdr; 722*2882Svi117747 return (0); 723*2882Svi117747 } 724*2882Svi117747 parsed_header = calloc(1, sizeof (sip_parsed_header_t)); 725*2882Svi117747 if (parsed_header == NULL) 726*2882Svi117747 return (ENOMEM); 727*2882Svi117747 parsed_header->sip_parsed_header_version = SIP_PARSED_HEADER_VERSION_1; 728*2882Svi117747 parsed_header->sip_header = hdr; 729*2882Svi117747 while (hdr->sip_hdr_current < hdr->sip_hdr_end) { 730*2882Svi117747 int r; 731*2882Svi117747 732*2882Svi117747 value = calloc(1, sizeof (sip_hdr_value_t)); 733*2882Svi117747 if (value == NULL) { 734*2882Svi117747 sip_free_phdr(parsed_header); 735*2882Svi117747 return (ENOMEM); 736*2882Svi117747 } 737*2882Svi117747 738*2882Svi117747 if (last_value != NULL) 739*2882Svi117747 last_value->sip_next_value = value; 740*2882Svi117747 else 741*2882Svi117747 parsed_header->value = (sip_value_t *)value; 742*2882Svi117747 743*2882Svi117747 value->sip_value_start = hdr->sip_hdr_current; 744*2882Svi117747 value->sip_value_header = parsed_header; 745*2882Svi117747 746*2882Svi117747 if (type == SIP_STRS_VAL) { 747*2882Svi117747 if (sip_find_token(hdr, SIP_LAQUOT) == 0) { 748*2882Svi117747 char *cur; 749*2882Svi117747 750*2882Svi117747 /* 751*2882Svi117747 * record the position after LAQUOT 752*2882Svi117747 */ 753*2882Svi117747 cur = hdr->sip_hdr_current; 754*2882Svi117747 /* 755*2882Svi117747 * get display name and store in str1 756*2882Svi117747 */ 757*2882Svi117747 hdr->sip_hdr_current = value->sip_value_start; 758*2882Svi117747 if (*(hdr->sip_hdr_current) != SIP_LAQUOT) { 759*2882Svi117747 /* 760*2882Svi117747 * record start pos of display name 761*2882Svi117747 */ 762*2882Svi117747 char *tmp = hdr->sip_hdr_current; 763*2882Svi117747 764*2882Svi117747 if (*hdr->sip_hdr_current == 765*2882Svi117747 SIP_QUOTE) { 766*2882Svi117747 hdr->sip_hdr_current++; 767*2882Svi117747 tmp++; 768*2882Svi117747 if (sip_find_token(hdr, 769*2882Svi117747 SIP_QUOTE) != 0) { 770*2882Svi117747 value->sip_value_state = 771*2882Svi117747 SIP_VALUE_BAD; 772*2882Svi117747 goto get_next_val; 773*2882Svi117747 } 774*2882Svi117747 hdr->sip_hdr_current -= 2; 775*2882Svi117747 } else { 776*2882Svi117747 hdr->sip_hdr_current = cur - 2; 777*2882Svi117747 (void) 778*2882Svi117747 sip_reverse_skip_white_space 779*2882Svi117747 (hdr); 780*2882Svi117747 } 781*2882Svi117747 value->strs1_val_ptr = tmp; 782*2882Svi117747 value->strs1_val_len = 783*2882Svi117747 hdr->sip_hdr_current - tmp + 1; 784*2882Svi117747 } else { 785*2882Svi117747 value->strs1_val_ptr = NULL; 786*2882Svi117747 value->strs1_val_len = 0; 787*2882Svi117747 } 788*2882Svi117747 789*2882Svi117747 /* 790*2882Svi117747 * set current to the char after LAQUOT 791*2882Svi117747 */ 792*2882Svi117747 hdr->sip_hdr_current = cur; 793*2882Svi117747 value->strs2_val_ptr = hdr->sip_hdr_current; 794*2882Svi117747 if (sip_find_token(hdr, SIP_RAQUOT)) { 795*2882Svi117747 /* 796*2882Svi117747 * no RAQUOT 797*2882Svi117747 */ 798*2882Svi117747 value->strs1_val_ptr = NULL; 799*2882Svi117747 value->strs1_val_len = 0; 800*2882Svi117747 value->strs2_val_ptr = NULL; 801*2882Svi117747 value->strs2_val_len = 0; 802*2882Svi117747 value->sip_value_state = SIP_VALUE_BAD; 803*2882Svi117747 goto get_next_val; 804*2882Svi117747 } 805*2882Svi117747 value->strs2_val_len = hdr->sip_hdr_current - 806*2882Svi117747 value->strs2_val_ptr - 1; 807*2882Svi117747 } else { 808*2882Svi117747 char *cur; 809*2882Svi117747 810*2882Svi117747 /* 811*2882Svi117747 * No display name - Only URI. 812*2882Svi117747 */ 813*2882Svi117747 value->strs1_val_ptr = NULL; 814*2882Svi117747 value->strs1_val_len = 0; 815*2882Svi117747 cur = value->sip_value_start; 816*2882Svi117747 hdr->sip_hdr_current = cur; 817*2882Svi117747 if (sip_find_separator(hdr, SIP_COMMA, 818*2882Svi117747 (char)NULL, (char)NULL) != 0) { 819*2882Svi117747 value->strs2_val_ptr = cur; 820*2882Svi117747 value->strs2_val_len = 821*2882Svi117747 hdr->sip_hdr_current - 822*2882Svi117747 value->strs2_val_ptr - 1; 823*2882Svi117747 } else if (*hdr->sip_hdr_current == SIP_SP) { 824*2882Svi117747 value->strs2_val_ptr = cur; 825*2882Svi117747 cur = hdr->sip_hdr_current - 1; 826*2882Svi117747 if (sip_skip_white_space(hdr) != 0) { 827*2882Svi117747 value->strs2_val_len = cur - 828*2882Svi117747 value->strs2_val_ptr - 1; 829*2882Svi117747 } else if (*hdr->sip_hdr_current == 830*2882Svi117747 SIP_COMMA) { 831*2882Svi117747 value->strs2_val_len = cur - 832*2882Svi117747 value->strs2_val_ptr - 1; 833*2882Svi117747 } else { 834*2882Svi117747 value->sip_value_state = 835*2882Svi117747 SIP_VALUE_BAD; 836*2882Svi117747 goto get_next_val; 837*2882Svi117747 } 838*2882Svi117747 } else { 839*2882Svi117747 value->strs2_val_ptr = cur; 840*2882Svi117747 value->strs2_val_len = 841*2882Svi117747 hdr->sip_hdr_current - 842*2882Svi117747 value->strs2_val_ptr; 843*2882Svi117747 } 844*2882Svi117747 } 845*2882Svi117747 if (parse_uri) 846*2882Svi117747 sip_parse_uri_str(&value->strs_s2, value); 847*2882Svi117747 } 848*2882Svi117747 849*2882Svi117747 if (type == SIP_STR_VAL) { 850*2882Svi117747 /* 851*2882Svi117747 * alert-info, error-info, call-info 852*2882Svi117747 */ 853*2882Svi117747 if (sip_find_token(hdr, SIP_LAQUOT) == 0) { 854*2882Svi117747 value->str_val_ptr = hdr->sip_hdr_current; 855*2882Svi117747 if (sip_find_token(hdr, SIP_RAQUOT) == 0) { 856*2882Svi117747 value->str_val_len = 857*2882Svi117747 hdr->sip_hdr_current - 858*2882Svi117747 value->str_val_ptr - 1; 859*2882Svi117747 } else { 860*2882Svi117747 value->str_val_ptr = NULL; 861*2882Svi117747 value->str_val_len = 0; 862*2882Svi117747 value->sip_value_state = SIP_VALUE_BAD; 863*2882Svi117747 goto get_next_val; 864*2882Svi117747 } 865*2882Svi117747 hdr->sip_hdr_current--; 866*2882Svi117747 } else { 867*2882Svi117747 value->str_val_ptr = NULL; 868*2882Svi117747 value->str_val_len = 0; 869*2882Svi117747 value->sip_value_state = SIP_VALUE_BAD; 870*2882Svi117747 goto get_next_val; 871*2882Svi117747 } 872*2882Svi117747 if (parse_uri) 873*2882Svi117747 sip_parse_uri_str(&value->str_val, value); 874*2882Svi117747 } 875*2882Svi117747 876*2882Svi117747 r = sip_find_separator(hdr, SIP_COMMA, SIP_SEMI, (char)NULL); 877*2882Svi117747 if (r != 0) { 878*2882Svi117747 value->sip_value_end = hdr->sip_hdr_current; 879*2882Svi117747 goto end; 880*2882Svi117747 } 881*2882Svi117747 if (*hdr->sip_hdr_current == SIP_SEMI) { 882*2882Svi117747 (void) sip_parse_params(hdr, 883*2882Svi117747 &(value->sip_param_list)); 884*2882Svi117747 goto get_next_val; 885*2882Svi117747 } 886*2882Svi117747 887*2882Svi117747 if (*hdr->sip_hdr_current == SIP_COMMA) { 888*2882Svi117747 hdr->sip_hdr_current--; 889*2882Svi117747 goto get_next_val; 890*2882Svi117747 } 891*2882Svi117747 get_next_val: 892*2882Svi117747 if (sip_find_token(hdr, SIP_COMMA) != 0) { 893*2882Svi117747 value->sip_value_end = hdr->sip_hdr_current; 894*2882Svi117747 break; 895*2882Svi117747 } 896*2882Svi117747 value->sip_value_end = hdr->sip_hdr_current - 1; 897*2882Svi117747 last_value = value; 898*2882Svi117747 (void) sip_skip_white_space(hdr); 899*2882Svi117747 } 900*2882Svi117747 901*2882Svi117747 end: 902*2882Svi117747 *phdr = parsed_header; 903*2882Svi117747 hdr->sip_hdr_parsed = *phdr; 904*2882Svi117747 return (0); 905*2882Svi117747 } 906*2882Svi117747 907*2882Svi117747 /* 908*2882Svi117747 * parser4 parses hdr format, the whole field is one single str 909*2882Svi117747 * header: Subject, MIME-Version, Organization, Server, User-Agent 910*2882Svi117747 */ 911*2882Svi117747 int 912*2882Svi117747 sip_parse_hdr_parser4(_sip_header_t *hdr, sip_parsed_header_t **phdr) 913*2882Svi117747 { 914*2882Svi117747 sip_parsed_header_t *parsed_header; 915*2882Svi117747 sip_hdr_value_t *value = NULL; 916*2882Svi117747 int ret; 917*2882Svi117747 918*2882Svi117747 if ((ret = sip_prim_parsers(hdr, phdr)) != 0) 919*2882Svi117747 return (ret); 920*2882Svi117747 921*2882Svi117747 /* 922*2882Svi117747 * check if previously parsed 923*2882Svi117747 */ 924*2882Svi117747 if (*phdr != NULL) { 925*2882Svi117747 hdr->sip_hdr_parsed = *phdr; 926*2882Svi117747 return (0); 927*2882Svi117747 } 928*2882Svi117747 parsed_header = calloc(1, sizeof (sip_parsed_header_t)); 929*2882Svi117747 if (parsed_header == NULL) 930*2882Svi117747 return (ENOMEM); 931*2882Svi117747 parsed_header->sip_parsed_header_version = SIP_PARSED_HEADER_VERSION_1; 932*2882Svi117747 parsed_header->sip_header = hdr; 933*2882Svi117747 934*2882Svi117747 value = calloc(1, sizeof (sip_hdr_value_t)); 935*2882Svi117747 if (value == NULL) { 936*2882Svi117747 sip_free_phdr(parsed_header); 937*2882Svi117747 return (ENOMEM); 938*2882Svi117747 } 939*2882Svi117747 940*2882Svi117747 parsed_header->value = (sip_value_t *)value; 941*2882Svi117747 942*2882Svi117747 value->sip_value_start = hdr->sip_hdr_current; 943*2882Svi117747 value->sip_value_header = parsed_header; 944*2882Svi117747 945*2882Svi117747 value->str_val_ptr = hdr->sip_hdr_current; 946*2882Svi117747 /* 947*2882Svi117747 * get rid of CRLF at end 948*2882Svi117747 */ 949*2882Svi117747 value->str_val_len = hdr->sip_hdr_end - value->str_val_ptr - 2; 950*2882Svi117747 value->sip_value_end = hdr->sip_hdr_end; 951*2882Svi117747 952*2882Svi117747 *phdr = parsed_header; 953*2882Svi117747 hdr->sip_hdr_parsed = *phdr; 954*2882Svi117747 return (0); 955*2882Svi117747 } 956*2882Svi117747 957*2882Svi117747 int 958*2882Svi117747 sip_parse_hdr_parser5(_sip_header_t *hdr, sip_parsed_header_t **phdr, 959*2882Svi117747 boolean_t parse_uri) 960*2882Svi117747 { 961*2882Svi117747 sip_parsed_header_t *parsed_header; 962*2882Svi117747 sip_hdr_value_t *value = NULL; 963*2882Svi117747 sip_param_t *tmp_param; 964*2882Svi117747 boolean_t first_param = B_TRUE; 965*2882Svi117747 int ret; 966*2882Svi117747 967*2882Svi117747 if ((ret = sip_prim_parsers(hdr, phdr)) != 0) 968*2882Svi117747 return (ret); 969*2882Svi117747 970*2882Svi117747 /* 971*2882Svi117747 * check if previously parsed 972*2882Svi117747 */ 973*2882Svi117747 if (*phdr != NULL) { 974*2882Svi117747 hdr->sip_hdr_parsed = *phdr; 975*2882Svi117747 return (0); 976*2882Svi117747 } 977*2882Svi117747 parsed_header = calloc(1, sizeof (sip_parsed_header_t)); 978*2882Svi117747 if (parsed_header == NULL) 979*2882Svi117747 return (ENOMEM); 980*2882Svi117747 parsed_header->sip_parsed_header_version = SIP_PARSED_HEADER_VERSION_1; 981*2882Svi117747 parsed_header->sip_header = hdr; 982*2882Svi117747 983*2882Svi117747 value = calloc(1, sizeof (sip_hdr_value_t)); 984*2882Svi117747 if (value == NULL) { 985*2882Svi117747 sip_free_phdr(parsed_header); 986*2882Svi117747 return (ENOMEM); 987*2882Svi117747 } 988*2882Svi117747 989*2882Svi117747 parsed_header->value = (sip_value_t *)value; 990*2882Svi117747 991*2882Svi117747 value->sip_value_start = hdr->sip_hdr_current; 992*2882Svi117747 value->auth_scheme_ptr = value->sip_value_start; 993*2882Svi117747 value->sip_value_header = parsed_header; 994*2882Svi117747 /* 995*2882Svi117747 * get auth_scheme 996*2882Svi117747 */ 997*2882Svi117747 if (sip_find_white_space(hdr)) { 998*2882Svi117747 value->sip_value_state = SIP_VALUE_BAD; 999*2882Svi117747 return (EINVAL); 1000*2882Svi117747 } 1001*2882Svi117747 value->auth_scheme_len = hdr->sip_hdr_current - value->auth_scheme_ptr; 1002*2882Svi117747 1003*2882Svi117747 tmp_param = value->auth_param; 1004*2882Svi117747 1005*2882Svi117747 /* 1006*2882Svi117747 * parse auth_param 1007*2882Svi117747 */ 1008*2882Svi117747 for (;;) { 1009*2882Svi117747 char *tmp_cur; 1010*2882Svi117747 boolean_t quoted_name = B_FALSE; 1011*2882Svi117747 char quoted_char = (char)0; 1012*2882Svi117747 sip_param_t *new_param; 1013*2882Svi117747 boolean_t pval_is_uri = B_FALSE; 1014*2882Svi117747 1015*2882Svi117747 if (sip_skip_white_space(hdr) != 0) { 1016*2882Svi117747 value->sip_value_state = SIP_VALUE_BAD; 1017*2882Svi117747 return (EPROTO); 1018*2882Svi117747 } 1019*2882Svi117747 tmp_cur = hdr->sip_hdr_current; 1020*2882Svi117747 1021*2882Svi117747 new_param = calloc(1, sizeof (sip_param_t)); 1022*2882Svi117747 if (new_param == NULL) 1023*2882Svi117747 return (ENOMEM); 1024*2882Svi117747 1025*2882Svi117747 if (first_param == B_FALSE) 1026*2882Svi117747 tmp_param->param_next = new_param; 1027*2882Svi117747 else 1028*2882Svi117747 value->auth_param = new_param; 1029*2882Svi117747 1030*2882Svi117747 tmp_param = new_param; 1031*2882Svi117747 tmp_param->param_name.sip_str_ptr = tmp_cur; 1032*2882Svi117747 1033*2882Svi117747 if (sip_find_separator(hdr, SIP_EQUAL, SIP_COMMA, (char)NULL) != 1034*2882Svi117747 0) { 1035*2882Svi117747 tmp_param->param_name.sip_str_len = 1036*2882Svi117747 hdr->sip_hdr_current - tmp_cur; 1037*2882Svi117747 tmp_param->param_value.sip_str_ptr = NULL; 1038*2882Svi117747 tmp_param->param_value.sip_str_len = 0; 1039*2882Svi117747 value->sip_value_end = hdr->sip_hdr_current; 1040*2882Svi117747 goto end; 1041*2882Svi117747 } 1042*2882Svi117747 1043*2882Svi117747 /* 1044*2882Svi117747 * End of param name 1045*2882Svi117747 */ 1046*2882Svi117747 tmp_param->param_name.sip_str_len = hdr->sip_hdr_current - 1047*2882Svi117747 tmp_cur; 1048*2882Svi117747 1049*2882Svi117747 if (sip_skip_white_space(hdr) != 0 || 1050*2882Svi117747 *hdr->sip_hdr_current == SIP_COMMA) { 1051*2882Svi117747 tmp_param->param_value.sip_str_ptr = NULL; 1052*2882Svi117747 tmp_param->param_value.sip_str_len = 0; 1053*2882Svi117747 continue; 1054*2882Svi117747 } 1055*2882Svi117747 1056*2882Svi117747 /* 1057*2882Svi117747 * We are at EQUAL 1058*2882Svi117747 */ 1059*2882Svi117747 hdr->sip_hdr_current++; 1060*2882Svi117747 1061*2882Svi117747 if (sip_skip_white_space(hdr) != 0) { 1062*2882Svi117747 value->sip_value_state = SIP_VALUE_BAD; 1063*2882Svi117747 free(tmp_param); 1064*2882Svi117747 return (EPROTO); 1065*2882Svi117747 } 1066*2882Svi117747 1067*2882Svi117747 if (*hdr->sip_hdr_current == SIP_QUOTE || 1068*2882Svi117747 *hdr->sip_hdr_current == SIP_LAQUOT) { 1069*2882Svi117747 if (*hdr->sip_hdr_current == SIP_QUOTE) 1070*2882Svi117747 quoted_char = SIP_QUOTE; 1071*2882Svi117747 else { 1072*2882Svi117747 quoted_char = SIP_RAQUOT; 1073*2882Svi117747 pval_is_uri = B_TRUE; 1074*2882Svi117747 } 1075*2882Svi117747 hdr->sip_hdr_current++; 1076*2882Svi117747 quoted_name = B_TRUE; 1077*2882Svi117747 } 1078*2882Svi117747 1079*2882Svi117747 /* 1080*2882Svi117747 * start of param value 1081*2882Svi117747 */ 1082*2882Svi117747 tmp_cur = hdr->sip_hdr_current; 1083*2882Svi117747 tmp_param->param_value.sip_str_ptr = tmp_cur; 1084*2882Svi117747 if (quoted_name) { 1085*2882Svi117747 if (sip_find_token(hdr, quoted_char) != 0) { 1086*2882Svi117747 value->sip_value_state = SIP_VALUE_BAD; 1087*2882Svi117747 free(tmp_param); 1088*2882Svi117747 return (EPROTO); 1089*2882Svi117747 } 1090*2882Svi117747 tmp_param->param_value.sip_str_len = 1091*2882Svi117747 hdr->sip_hdr_current - tmp_cur - 1; 1092*2882Svi117747 } 1093*2882Svi117747 1094*2882Svi117747 if (sip_find_token(hdr, SIP_COMMA) != 0) { 1095*2882Svi117747 value->sip_value_end = hdr->sip_hdr_current; 1096*2882Svi117747 goto end; 1097*2882Svi117747 } else { 1098*2882Svi117747 if (!quoted_name) { 1099*2882Svi117747 char *t = hdr->sip_hdr_current; 1100*2882Svi117747 hdr->sip_hdr_current--; 1101*2882Svi117747 (void) sip_reverse_skip_white_space(hdr); 1102*2882Svi117747 tmp_param->param_value.sip_str_len = 1103*2882Svi117747 hdr->sip_hdr_current - tmp_cur; 1104*2882Svi117747 hdr->sip_hdr_current = t; 1105*2882Svi117747 } 1106*2882Svi117747 } 1107*2882Svi117747 1108*2882Svi117747 if (first_param == B_TRUE) 1109*2882Svi117747 first_param = B_FALSE; 1110*2882Svi117747 1111*2882Svi117747 /* 1112*2882Svi117747 * Parse uri 1113*2882Svi117747 */ 1114*2882Svi117747 if (pval_is_uri && parse_uri) 1115*2882Svi117747 sip_parse_uri_str(&tmp_param->param_value, value); 1116*2882Svi117747 1117*2882Svi117747 } 1118*2882Svi117747 1119*2882Svi117747 end: 1120*2882Svi117747 *phdr = parsed_header; 1121*2882Svi117747 hdr->sip_hdr_parsed = *phdr; 1122*2882Svi117747 return (0); 1123*2882Svi117747 } 1124*2882Svi117747 1125*2882Svi117747 /* 1126*2882Svi117747 * Return the URI in the request startline 1127*2882Svi117747 */ 1128*2882Svi117747 static int 1129*2882Svi117747 _sip_get_request_uri(_sip_header_t *sip_header, sip_message_type_t *msg_info) 1130*2882Svi117747 { 1131*2882Svi117747 int size = 0; 1132*2882Svi117747 char *start_ptr; 1133*2882Svi117747 1134*2882Svi117747 if (sip_skip_white_space(sip_header) != 0) 1135*2882Svi117747 return (EINVAL); 1136*2882Svi117747 start_ptr = sip_header->sip_hdr_current; 1137*2882Svi117747 1138*2882Svi117747 while (!isspace(*sip_header->sip_hdr_current)) { 1139*2882Svi117747 if (sip_header->sip_hdr_current >= sip_header->sip_hdr_end) 1140*2882Svi117747 return (EINVAL); 1141*2882Svi117747 sip_header->sip_hdr_current++; 1142*2882Svi117747 } 1143*2882Svi117747 1144*2882Svi117747 size = sip_header->sip_hdr_current - start_ptr; 1145*2882Svi117747 1146*2882Svi117747 msg_info->U.sip_request.sip_request_uri.sip_str_ptr = start_ptr; 1147*2882Svi117747 msg_info->U.sip_request.sip_request_uri.sip_str_len = size; 1148*2882Svi117747 if (size > 0) { /* Parse uri */ 1149*2882Svi117747 int error; 1150*2882Svi117747 1151*2882Svi117747 msg_info->U.sip_request.sip_parse_uri = sip_parse_uri( 1152*2882Svi117747 &msg_info->U.sip_request.sip_request_uri, &error); 1153*2882Svi117747 if (msg_info->U.sip_request.sip_parse_uri == NULL) 1154*2882Svi117747 return (error); 1155*2882Svi117747 } 1156*2882Svi117747 return (0); 1157*2882Svi117747 } 1158*2882Svi117747 1159*2882Svi117747 /* 1160*2882Svi117747 * Parse the start line into request/response 1161*2882Svi117747 */ 1162*2882Svi117747 int 1163*2882Svi117747 sip_parse_first_line(_sip_header_t *sip_header, sip_message_type_t **msg_info) 1164*2882Svi117747 { 1165*2882Svi117747 sip_message_type_t *sip_msg_info; 1166*2882Svi117747 boolean_t sip_is_request = B_TRUE; 1167*2882Svi117747 int ret; 1168*2882Svi117747 1169*2882Svi117747 if (sip_header == NULL || msg_info == NULL) 1170*2882Svi117747 return (EINVAL); 1171*2882Svi117747 1172*2882Svi117747 if (sip_skip_white_space(sip_header) != 0) 1173*2882Svi117747 return (EPROTO); 1174*2882Svi117747 1175*2882Svi117747 /* 1176*2882Svi117747 * There is nothing, return 1177*2882Svi117747 */ 1178*2882Svi117747 if (sip_header->sip_hdr_current + strlen(SIP_VERSION) >= 1179*2882Svi117747 sip_header->sip_hdr_end) { 1180*2882Svi117747 return (EPROTO); 1181*2882Svi117747 } 1182*2882Svi117747 #ifdef __solaris__ 1183*2882Svi117747 assert(mutex_held(&sip_header->sip_hdr_sipmsg->sip_msg_mutex)); 1184*2882Svi117747 #endif 1185*2882Svi117747 sip_msg_info = malloc(sizeof (sip_message_type_t)); 1186*2882Svi117747 if (sip_msg_info == NULL) 1187*2882Svi117747 return (ENOMEM); 1188*2882Svi117747 1189*2882Svi117747 /* 1190*2882Svi117747 * let's see if it's a request or a response 1191*2882Svi117747 */ 1192*2882Svi117747 ret = sip_get_protocol_version(sip_header, 1193*2882Svi117747 &sip_msg_info->sip_proto_version); 1194*2882Svi117747 if (ret == 0) { 1195*2882Svi117747 sip_is_request = B_FALSE; 1196*2882Svi117747 } else if (ret == 2) { 1197*2882Svi117747 free(sip_msg_info); 1198*2882Svi117747 return (EPROTO); 1199*2882Svi117747 } 1200*2882Svi117747 1201*2882Svi117747 if (sip_skip_white_space(sip_header) != 0) { 1202*2882Svi117747 free(sip_msg_info); 1203*2882Svi117747 return (EPROTO); 1204*2882Svi117747 } 1205*2882Svi117747 1206*2882Svi117747 if (!sip_is_request) { 1207*2882Svi117747 /* 1208*2882Svi117747 * check for status code. 1209*2882Svi117747 */ 1210*2882Svi117747 if (sip_skip_white_space(sip_header) != 0) { 1211*2882Svi117747 free(sip_msg_info); 1212*2882Svi117747 return (EPROTO); 1213*2882Svi117747 } 1214*2882Svi117747 if (sip_header->sip_hdr_current + SIP_SIZE_OF_STATUS_CODE >= 1215*2882Svi117747 sip_header->sip_hdr_end) { 1216*2882Svi117747 free(sip_msg_info); 1217*2882Svi117747 return (EPROTO); 1218*2882Svi117747 } 1219*2882Svi117747 1220*2882Svi117747 if (sip_atoi(sip_header, 1221*2882Svi117747 &sip_msg_info->U.sip_response.sip_response_code)) { 1222*2882Svi117747 free(sip_msg_info); 1223*2882Svi117747 return (EPROTO); 1224*2882Svi117747 } 1225*2882Svi117747 1226*2882Svi117747 if (sip_msg_info->U.sip_response.sip_response_code < 100 || 1227*2882Svi117747 sip_msg_info->U.sip_response.sip_response_code > 700) { 1228*2882Svi117747 free(sip_msg_info); 1229*2882Svi117747 return (EPROTO); 1230*2882Svi117747 } 1231*2882Svi117747 1232*2882Svi117747 /* 1233*2882Svi117747 * get reason phrase. 1234*2882Svi117747 */ 1235*2882Svi117747 if (sip_skip_white_space(sip_header) != 0) { 1236*2882Svi117747 sip_msg_info->sip_resp_phrase_len = 0; 1237*2882Svi117747 sip_msg_info->sip_resp_phrase_ptr = NULL; 1238*2882Svi117747 } else { 1239*2882Svi117747 sip_msg_info->sip_resp_phrase_ptr = 1240*2882Svi117747 sip_header->sip_hdr_current; 1241*2882Svi117747 if (sip_find_cr(sip_header) != 0) { 1242*2882Svi117747 free(sip_msg_info); 1243*2882Svi117747 return (EPROTO); 1244*2882Svi117747 } 1245*2882Svi117747 sip_msg_info->sip_resp_phrase_len = 1246*2882Svi117747 sip_header->sip_hdr_current - 1247*2882Svi117747 sip_msg_info->sip_resp_phrase_ptr; 1248*2882Svi117747 } 1249*2882Svi117747 sip_msg_info->is_request = B_FALSE; 1250*2882Svi117747 } else { 1251*2882Svi117747 int i; 1252*2882Svi117747 /* 1253*2882Svi117747 * It's a request. 1254*2882Svi117747 */ 1255*2882Svi117747 sip_msg_info->is_request = B_TRUE; 1256*2882Svi117747 for (i = 1; i < MAX_SIP_METHODS; i++) { 1257*2882Svi117747 if (strncmp(sip_methods[i].name, 1258*2882Svi117747 sip_header->sip_hdr_current, 1259*2882Svi117747 sip_methods[i].len) == 0) { 1260*2882Svi117747 sip_msg_info->sip_req_method = i; 1261*2882Svi117747 sip_header->sip_hdr_current += 1262*2882Svi117747 sip_methods[i].len; 1263*2882Svi117747 if (!isspace(*sip_header->sip_hdr_current++) || 1264*2882Svi117747 !isalpha(*sip_header->sip_hdr_current)) { 1265*2882Svi117747 free(sip_msg_info); 1266*2882Svi117747 return (EPROTO); 1267*2882Svi117747 } 1268*2882Svi117747 1269*2882Svi117747 if ((ret = _sip_get_request_uri(sip_header, 1270*2882Svi117747 sip_msg_info)) != 0) { 1271*2882Svi117747 free(sip_msg_info); 1272*2882Svi117747 return (ret); 1273*2882Svi117747 } 1274*2882Svi117747 1275*2882Svi117747 /* 1276*2882Svi117747 * Get SIP version 1277*2882Svi117747 */ 1278*2882Svi117747 ret = sip_get_protocol_version(sip_header, 1279*2882Svi117747 &sip_msg_info->sip_proto_version); 1280*2882Svi117747 if (ret != 0) { 1281*2882Svi117747 free(sip_msg_info); 1282*2882Svi117747 return (EPROTO); 1283*2882Svi117747 } 1284*2882Svi117747 goto done; 1285*2882Svi117747 } 1286*2882Svi117747 } 1287*2882Svi117747 free(sip_msg_info); 1288*2882Svi117747 return (EPROTO); 1289*2882Svi117747 } 1290*2882Svi117747 done: 1291*2882Svi117747 sip_msg_info->sip_next = *msg_info; 1292*2882Svi117747 *msg_info = sip_msg_info; 1293*2882Svi117747 return (0); 1294*2882Svi117747 } 1295