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 #include "sip_parse_generic.h" 33*2882Svi117747 34*2882Svi117747 /* 35*2882Svi117747 * Accept = "Accept" HCOLON [ accept-range *(COMMA accept-range) ] 36*2882Svi117747 * accept-range = media-range *(SEMI accept-param) 37*2882Svi117747 * media-range = ("* / *" | (m-type SLASH "*") | (m-type SLASH m-subtype)) 38*2882Svi117747 * *(SEMI m-param) 39*2882Svi117747 * accept-param = ("q" EQUAL qvalue) | generic-param 40*2882Svi117747 * qvalue = ("0" ["." 0*3DIGIT]) | ("1" ["." 0*3DIGIT]) 41*2882Svi117747 * generic-param = token [ EQUAL gen-value] 42*2882Svi117747 * gen-value = token | host | quoted-str 43*2882Svi117747 */ 44*2882Svi117747 int 45*2882Svi117747 sip_parse_acpt_header(_sip_header_t *sip_header, sip_parsed_header_t **header) 46*2882Svi117747 { 47*2882Svi117747 if (sip_is_empty_hdr(sip_header)) 48*2882Svi117747 return (sip_parse_hdr_empty(sip_header, header)); 49*2882Svi117747 return (sip_parse_hdr_parser1(sip_header, header, SIP_SLASH)); 50*2882Svi117747 } 51*2882Svi117747 52*2882Svi117747 /* 53*2882Svi117747 * Accept-Encoding = "Accept-Encoding" ":" 1#(codings [ ";" "q" "=" qval]) 54*2882Svi117747 * codings = (content-coding | "*") 55*2882Svi117747 * content-coding = token 56*2882Svi117747 */ 57*2882Svi117747 int 58*2882Svi117747 sip_parse_acpt_encode_header(_sip_header_t *sip_header, 59*2882Svi117747 sip_parsed_header_t **header) 60*2882Svi117747 { 61*2882Svi117747 return (sip_parse_hdr_parser1(sip_header, header, (char)NULL)); 62*2882Svi117747 } 63*2882Svi117747 64*2882Svi117747 /* 65*2882Svi117747 * Accept-Language = "Accept-Language" ":" [ lang * (COMMA lang) ] 66*2882Svi117747 * lang = lang-range *(SEMI accept-param) 67*2882Svi117747 * lang-range = ((1*8ALPHA * ("-" 1*8ALPHA)) | "*" 68*2882Svi117747 */ 69*2882Svi117747 int 70*2882Svi117747 sip_parse_acpt_lang_header(_sip_header_t *sip_header, 71*2882Svi117747 sip_parsed_header_t **header) 72*2882Svi117747 { 73*2882Svi117747 if (sip_is_empty_hdr(sip_header)) 74*2882Svi117747 return (sip_parse_hdr_empty(sip_header, header)); 75*2882Svi117747 return (sip_parse_hdr_parser1(sip_header, header, (char)NULL)); 76*2882Svi117747 } 77*2882Svi117747 78*2882Svi117747 /* 79*2882Svi117747 * Alert-Info = "Alert-Info" ":" alert-param *(COMMA alert-param) 80*2882Svi117747 * alert-param = LAQUOT absoluteURI RAQUOT * (SEMI generic-param) 81*2882Svi117747 */ 82*2882Svi117747 int 83*2882Svi117747 sip_parse_alert_header(_sip_header_t *sip_header, sip_parsed_header_t **header) 84*2882Svi117747 { 85*2882Svi117747 return (sip_parse_hdr_parser3(sip_header, header, SIP_STR_VAL, B_TRUE)); 86*2882Svi117747 } 87*2882Svi117747 88*2882Svi117747 /* 89*2882Svi117747 * Allow = "Allow" ":" method-name1[, method-name2..] 90*2882Svi117747 */ 91*2882Svi117747 int 92*2882Svi117747 sip_parse_allow_header(_sip_header_t *hdr, sip_parsed_header_t **phdr) 93*2882Svi117747 { 94*2882Svi117747 sip_parsed_header_t *parsed_header; 95*2882Svi117747 sip_hdr_value_t *value = NULL; 96*2882Svi117747 sip_hdr_value_t *last_value = NULL; 97*2882Svi117747 int len; 98*2882Svi117747 int i; 99*2882Svi117747 int ret; 100*2882Svi117747 boolean_t multi_value = B_FALSE; 101*2882Svi117747 102*2882Svi117747 if ((ret = sip_prim_parsers(hdr, phdr)) != 0) 103*2882Svi117747 return (ret); 104*2882Svi117747 105*2882Svi117747 if (*phdr != NULL) 106*2882Svi117747 return (0); 107*2882Svi117747 108*2882Svi117747 parsed_header = calloc(1, sizeof (sip_parsed_header_t)); 109*2882Svi117747 if (parsed_header == NULL) 110*2882Svi117747 return (ENOMEM); 111*2882Svi117747 parsed_header->sip_parsed_header_version = SIP_PARSED_HEADER_VERSION_1; 112*2882Svi117747 parsed_header->sip_header = hdr; 113*2882Svi117747 114*2882Svi117747 while (hdr->sip_hdr_current < hdr->sip_hdr_end) { 115*2882Svi117747 value = calloc(1, sizeof (sip_hdr_value_t)); 116*2882Svi117747 if (value == NULL) { 117*2882Svi117747 sip_free_phdr(parsed_header); 118*2882Svi117747 return (ENOMEM); 119*2882Svi117747 } 120*2882Svi117747 if (last_value != NULL) 121*2882Svi117747 last_value->sip_next_value = value; 122*2882Svi117747 else 123*2882Svi117747 parsed_header->value = (sip_value_t *)value; 124*2882Svi117747 125*2882Svi117747 value->sip_value_start = hdr->sip_hdr_current; 126*2882Svi117747 value->sip_value_header = parsed_header; 127*2882Svi117747 128*2882Svi117747 if (sip_find_separator(hdr, SIP_COMMA, (char)NULL, 129*2882Svi117747 (char)NULL) == 0) { 130*2882Svi117747 multi_value = B_TRUE; 131*2882Svi117747 } 132*2882Svi117747 133*2882Svi117747 len = hdr->sip_hdr_current - value->sip_value_start; 134*2882Svi117747 for (i = 1; i < MAX_SIP_METHODS; i++) { 135*2882Svi117747 if (strncmp(sip_methods[i].name, value->sip_value_start, 136*2882Svi117747 len) == 0) { 137*2882Svi117747 break; 138*2882Svi117747 } 139*2882Svi117747 } 140*2882Svi117747 if (i >= MAX_SIP_METHODS) { 141*2882Svi117747 value->int_val = 0; 142*2882Svi117747 value->sip_value_state = SIP_VALUE_BAD; 143*2882Svi117747 if (multi_value) 144*2882Svi117747 goto next_val; 145*2882Svi117747 else 146*2882Svi117747 goto end; 147*2882Svi117747 } 148*2882Svi117747 value->int_val = i; 149*2882Svi117747 if (!multi_value) 150*2882Svi117747 goto end; 151*2882Svi117747 next_val: 152*2882Svi117747 if (sip_find_token(hdr, SIP_COMMA) != 0) 153*2882Svi117747 break; 154*2882Svi117747 value->sip_value_end = hdr->sip_hdr_current - 1; 155*2882Svi117747 last_value = value; 156*2882Svi117747 (void) sip_skip_white_space(hdr); 157*2882Svi117747 } 158*2882Svi117747 159*2882Svi117747 end: 160*2882Svi117747 *phdr = parsed_header; 161*2882Svi117747 return (0); 162*2882Svi117747 } 163*2882Svi117747 164*2882Svi117747 165*2882Svi117747 /* 166*2882Svi117747 * Call-Info = "Call-Info" HCOLON info * (COMMA info) 167*2882Svi117747 * info = LAQUOT absoluteURI RAQUOT * (SEMI info-param) 168*2882Svi117747 * info-param = ("purpose" EQUAL ("icon" | "info" | "card" | token)) | 169*2882Svi117747 * generic-param 170*2882Svi117747 */ 171*2882Svi117747 int 172*2882Svi117747 sip_parse_callinfo_header(_sip_header_t *sip_header, 173*2882Svi117747 sip_parsed_header_t **header) 174*2882Svi117747 { 175*2882Svi117747 return (sip_parse_hdr_parser3(sip_header, header, SIP_STR_VAL, B_TRUE)); 176*2882Svi117747 } 177*2882Svi117747 178*2882Svi117747 /* 179*2882Svi117747 * Content-Disposition = "Content-Disposition" HCOLON disp-type * 180*2882Svi117747 * (SEMI disp-param) 181*2882Svi117747 * disp-type = "render" | "session" | "icon" | "alert" | disp-ext-token 182*2882Svi117747 * disp-param = handling-param | generic-param 183*2882Svi117747 * handling-param = "handling" EQUAL("optional" | "required" | other-handling) 184*2882Svi117747 * other-handling = token 185*2882Svi117747 * disp-ext-token = token 186*2882Svi117747 * 187*2882Svi117747 */ 188*2882Svi117747 int 189*2882Svi117747 sip_parse_contentdis_header(_sip_header_t *sip_header, 190*2882Svi117747 sip_parsed_header_t **header) 191*2882Svi117747 { 192*2882Svi117747 return (sip_parse_hdr_parser1(sip_header, header, (char)NULL)); 193*2882Svi117747 } 194*2882Svi117747 195*2882Svi117747 /* 196*2882Svi117747 * Content-Encoding = ("Content-Encoding" | "e") HCOLON content-coding * 197*2882Svi117747 * (COMMA content-coding) 198*2882Svi117747 */ 199*2882Svi117747 int 200*2882Svi117747 sip_parse_contentencode_header(_sip_header_t *sip_header, 201*2882Svi117747 sip_parsed_header_t **header) 202*2882Svi117747 { 203*2882Svi117747 return (sip_parse_hdr_parser1(sip_header, header, (char)NULL)); 204*2882Svi117747 } 205*2882Svi117747 206*2882Svi117747 /* 207*2882Svi117747 * Content-Language = ("Content-Language" | "l") HCOLON lang-tag * 208*2882Svi117747 * (COMMA lang-tag) 209*2882Svi117747 * lang-tag = primary-tag *("-" subtag) 210*2882Svi117747 * prmary-tag = 1*8ALPHA 211*2882Svi117747 * subtag = 1*8ALPHA 212*2882Svi117747 */ 213*2882Svi117747 int 214*2882Svi117747 sip_parse_contentlang_header(_sip_header_t *sip_header, 215*2882Svi117747 sip_parsed_header_t **header) 216*2882Svi117747 { 217*2882Svi117747 return (sip_parse_hdr_parser1(sip_header, header, (char)NULL)); 218*2882Svi117747 } 219*2882Svi117747 220*2882Svi117747 /* 221*2882Svi117747 * Date = "Date" HCOLON SIPdate 222*2882Svi117747 * SIPdate = wkday "," SP date1 SP time SP "GMT" 223*2882Svi117747 * date1 = 2DIGIT SP mnth SP 4DIGIT; day month year 224*2882Svi117747 * time = 2DIGIT ":" 2DIGIT ":" 2DIGIT 225*2882Svi117747 * wkday = "Mon" | "Tue" | "Wed" | "Thu" | "Fri" | "Sat" | "Sun" 226*2882Svi117747 * month = "Jan" | "Feb" etc 227*2882Svi117747 */ 228*2882Svi117747 int 229*2882Svi117747 sip_parse_date_header(_sip_header_t *sip_header, sip_parsed_header_t **header) 230*2882Svi117747 { 231*2882Svi117747 sip_parsed_header_t *parsed_header; 232*2882Svi117747 int r; 233*2882Svi117747 sip_hdr_value_t *value = NULL; 234*2882Svi117747 235*2882Svi117747 if ((r = sip_prim_parsers(sip_header, header)) != 0) 236*2882Svi117747 return (r); 237*2882Svi117747 238*2882Svi117747 if (*header != NULL) 239*2882Svi117747 return (0); 240*2882Svi117747 241*2882Svi117747 parsed_header = calloc(1, sizeof (sip_parsed_header_t)); 242*2882Svi117747 if (parsed_header == NULL) 243*2882Svi117747 return (ENOMEM); 244*2882Svi117747 parsed_header->sip_parsed_header_version = SIP_PARSED_HEADER_VERSION_1; 245*2882Svi117747 parsed_header->sip_header = sip_header; 246*2882Svi117747 247*2882Svi117747 value = calloc(1, sizeof (sip_hdr_value_t)); 248*2882Svi117747 if (value == NULL) { 249*2882Svi117747 sip_free_phdr(parsed_header); 250*2882Svi117747 return (ENOMEM); 251*2882Svi117747 } 252*2882Svi117747 parsed_header->value = (sip_value_t *)value; 253*2882Svi117747 254*2882Svi117747 value->sip_value_start = sip_header->sip_hdr_current; 255*2882Svi117747 value->sip_value_header = parsed_header; 256*2882Svi117747 value->date_wd_ptr = sip_header->sip_hdr_current; 257*2882Svi117747 if (sip_find_token(sip_header, SIP_COMMA) == 0) { 258*2882Svi117747 value->date_wd_len = sip_header->sip_hdr_current - 259*2882Svi117747 value->date_wd_ptr - 1; 260*2882Svi117747 sip_header->sip_hdr_current++; 261*2882Svi117747 if (sip_skip_white_space(sip_header) != 0) { 262*2882Svi117747 value->sip_value_state = SIP_VALUE_BAD; 263*2882Svi117747 return (EPROTO); 264*2882Svi117747 } 265*2882Svi117747 } else { 266*2882Svi117747 value->sip_value_state = SIP_VALUE_BAD; 267*2882Svi117747 return (EPROTO); 268*2882Svi117747 } 269*2882Svi117747 270*2882Svi117747 if (sip_skip_white_space(sip_header) != 0) { 271*2882Svi117747 value->sip_value_state = SIP_VALUE_BAD; 272*2882Svi117747 return (EPROTO); 273*2882Svi117747 } 274*2882Svi117747 r = sip_atoi(sip_header, &value->date_d); 275*2882Svi117747 if (r != 0 || value->date_d < 0 || value->date_d > 31) { 276*2882Svi117747 value->sip_value_state = SIP_VALUE_BAD; 277*2882Svi117747 return (EPROTO); 278*2882Svi117747 } 279*2882Svi117747 if (sip_skip_white_space(sip_header) != 0) { 280*2882Svi117747 value->sip_value_state = SIP_VALUE_BAD; 281*2882Svi117747 return (EPROTO); 282*2882Svi117747 } 283*2882Svi117747 value->date_m_ptr = sip_header->sip_hdr_current; 284*2882Svi117747 if (sip_find_token(sip_header, SIP_SP) == 0) { 285*2882Svi117747 value->date_m_len = sip_header->sip_hdr_current - 286*2882Svi117747 value->date_m_ptr - 1; 287*2882Svi117747 } else { 288*2882Svi117747 value->sip_value_state = SIP_VALUE_BAD; 289*2882Svi117747 return (EPROTO); 290*2882Svi117747 } 291*2882Svi117747 292*2882Svi117747 r = sip_atoi(sip_header, &value->date_y); 293*2882Svi117747 if (r != 0 || value->date_y < 0) { 294*2882Svi117747 value->sip_value_state = SIP_VALUE_BAD; 295*2882Svi117747 return (EPROTO); 296*2882Svi117747 } 297*2882Svi117747 if (sip_skip_white_space(sip_header) != 0) { 298*2882Svi117747 value->sip_value_state = SIP_VALUE_BAD; 299*2882Svi117747 return (EPROTO); 300*2882Svi117747 } 301*2882Svi117747 value->date_t_ptr = sip_header->sip_hdr_current; 302*2882Svi117747 if (sip_find_token(sip_header, SIP_SP) == 0) { 303*2882Svi117747 value->date_t_len = sip_header->sip_hdr_current - 304*2882Svi117747 value->date_t_ptr - 1; 305*2882Svi117747 } else { 306*2882Svi117747 value->sip_value_state = SIP_VALUE_BAD; 307*2882Svi117747 return (EPROTO); 308*2882Svi117747 } 309*2882Svi117747 310*2882Svi117747 value->date_tz_ptr = sip_header->sip_hdr_current; 311*2882Svi117747 /* 312*2882Svi117747 * minus 2 to get rid of the CRLF 313*2882Svi117747 */ 314*2882Svi117747 value->date_tz_len = sip_header->sip_hdr_end - 315*2882Svi117747 sip_header->sip_hdr_current - 2; 316*2882Svi117747 317*2882Svi117747 *header = parsed_header; 318*2882Svi117747 319*2882Svi117747 sip_header->sip_hdr_parsed = *header; 320*2882Svi117747 return (0); 321*2882Svi117747 } 322*2882Svi117747 323*2882Svi117747 /* 324*2882Svi117747 * Error-Info = "Error-Info" HCOLON error-uri *(COMMA error-uri) 325*2882Svi117747 * error-uri = LAQUOT absoluteURI RAQUOT *(SEMI generic-param) 326*2882Svi117747 */ 327*2882Svi117747 int 328*2882Svi117747 sip_parse_errorinfo_header(_sip_header_t *sip_header, 329*2882Svi117747 sip_parsed_header_t **header) 330*2882Svi117747 { 331*2882Svi117747 return (sip_parse_hdr_parser3(sip_header, header, SIP_STR_VAL, B_TRUE)); 332*2882Svi117747 } 333*2882Svi117747 334*2882Svi117747 /* 335*2882Svi117747 * Expires = "Expires" HCOLON delta-seconds 336*2882Svi117747 */ 337*2882Svi117747 int 338*2882Svi117747 sip_parse_expire_header(_sip_header_t *sip_header, 339*2882Svi117747 sip_parsed_header_t **header) 340*2882Svi117747 { 341*2882Svi117747 return (sip_parse_hdr_parser2(sip_header, header, SIP_INT_VAL)); 342*2882Svi117747 } 343*2882Svi117747 344*2882Svi117747 /* 345*2882Svi117747 * In-Reply-To = "In-Reply-To" HCOLON callid *(COMMA callid) 346*2882Svi117747 */ 347*2882Svi117747 int 348*2882Svi117747 sip_parse_inreplyto_header(_sip_header_t *sip_header, 349*2882Svi117747 sip_parsed_header_t **header) 350*2882Svi117747 { 351*2882Svi117747 return (sip_parse_hdr_parser1(sip_header, header, (char)NULL)); 352*2882Svi117747 } 353*2882Svi117747 354*2882Svi117747 /* 355*2882Svi117747 * RSeq = "RSeq" HCOLON response-num 356*2882Svi117747 */ 357*2882Svi117747 int 358*2882Svi117747 sip_parse_rseq(_sip_header_t *sip_header, sip_parsed_header_t **header) 359*2882Svi117747 { 360*2882Svi117747 int r; 361*2882Svi117747 sip_hdr_value_t *rseq_value; 362*2882Svi117747 363*2882Svi117747 r = sip_parse_hdr_parser2(sip_header, header, SIP_INT_VAL); 364*2882Svi117747 /* 365*2882Svi117747 * Additionally, a value of 0 is bad_value 366*2882Svi117747 */ 367*2882Svi117747 if (sip_header->sip_hdr_parsed != NULL && 368*2882Svi117747 sip_header->sip_hdr_parsed->value != NULL) { 369*2882Svi117747 rseq_value = (sip_hdr_value_t *) 370*2882Svi117747 sip_header->sip_hdr_parsed->value; 371*2882Svi117747 if (rseq_value->int_val == 0) 372*2882Svi117747 rseq_value->sip_value_state = SIP_VALUE_BAD; 373*2882Svi117747 } 374*2882Svi117747 return (r); 375*2882Svi117747 } 376*2882Svi117747 377*2882Svi117747 /* 378*2882Svi117747 * Min-Expires = "Min-Expires" HCOLON delta-seconds 379*2882Svi117747 */ 380*2882Svi117747 int 381*2882Svi117747 sip_parse_minexpire_header(_sip_header_t *sip_header, 382*2882Svi117747 sip_parsed_header_t **header) 383*2882Svi117747 { 384*2882Svi117747 return (sip_parse_hdr_parser2(sip_header, header, SIP_INT_VAL)); 385*2882Svi117747 } 386*2882Svi117747 387*2882Svi117747 /* 388*2882Svi117747 * MIME-Version = "MIME-Version" HCOLON 1*DIGIT "." 1*DIGIT 389*2882Svi117747 */ 390*2882Svi117747 int 391*2882Svi117747 sip_parse_mimeversion_header(_sip_header_t *sip_header, 392*2882Svi117747 sip_parsed_header_t **header) 393*2882Svi117747 { 394*2882Svi117747 return (sip_parse_hdr_parser4(sip_header, header)); 395*2882Svi117747 } 396*2882Svi117747 397*2882Svi117747 /* 398*2882Svi117747 * Organization = "Organization" HCOLON [TEXT-UTF8-TRIM] 399*2882Svi117747 */ 400*2882Svi117747 int 401*2882Svi117747 sip_parse_org_header(_sip_header_t *sip_header, 402*2882Svi117747 sip_parsed_header_t **header) 403*2882Svi117747 { 404*2882Svi117747 if (sip_is_empty_hdr(sip_header)) 405*2882Svi117747 return (sip_parse_hdr_empty(sip_header, header)); 406*2882Svi117747 return (sip_parse_hdr_parser4(sip_header, header)); 407*2882Svi117747 } 408*2882Svi117747 409*2882Svi117747 /* 410*2882Svi117747 * Priority = "Priority" HCOLON priority-val 411*2882Svi117747 * priority-val = "emergency" | "urgent" | "normal" | "non-urgent" | other 412*2882Svi117747 * other = token 413*2882Svi117747 */ 414*2882Svi117747 int 415*2882Svi117747 sip_parse_priority_header(_sip_header_t *sip_header, 416*2882Svi117747 sip_parsed_header_t **header) 417*2882Svi117747 { 418*2882Svi117747 return (sip_parse_hdr_parser4(sip_header, header)); 419*2882Svi117747 } 420*2882Svi117747 421*2882Svi117747 /* 422*2882Svi117747 * Reply-To = "Reply-To" HCOLON rplyto-spec 423*2882Svi117747 * rplyto-spec = (name-addr | addr-spec) *(SEMI rplyto-param) 424*2882Svi117747 * rplyto-param = generic-param 425*2882Svi117747 * name-addr = [ display-name ] LAQUOT addr-spec RAQUOT 426*2882Svi117747 * addr-spec = SIP-URI | SIPS-URI | absolute URI 427*2882Svi117747 */ 428*2882Svi117747 int 429*2882Svi117747 sip_parse_replyto_header(_sip_header_t *sip_header, 430*2882Svi117747 sip_parsed_header_t **header) 431*2882Svi117747 { 432*2882Svi117747 return (sip_parse_hdr_parser3(sip_header, header, SIP_STRS_VAL, 433*2882Svi117747 B_TRUE)); 434*2882Svi117747 } 435*2882Svi117747 436*2882Svi117747 /* 437*2882Svi117747 * PRIVACY = "Privacy" HCOLON priv-value *(COMMA priv-value) 438*2882Svi117747 * priv-value = "header" / "session" / "user" / "none" / "critical" 439*2882Svi117747 * / token / id 440*2882Svi117747 */ 441*2882Svi117747 int 442*2882Svi117747 sip_parse_privacy_header(_sip_header_t *sip_header, 443*2882Svi117747 sip_parsed_header_t **header) 444*2882Svi117747 { 445*2882Svi117747 return (sip_parse_hdr_parser1(sip_header, header, (char)NULL)); 446*2882Svi117747 } 447*2882Svi117747 448*2882Svi117747 449*2882Svi117747 /* 450*2882Svi117747 * Require = "Require" HCOLON option-tag * (COMMA option-tag) 451*2882Svi117747 */ 452*2882Svi117747 int 453*2882Svi117747 sip_parse_require_header(_sip_header_t *sip_header, 454*2882Svi117747 sip_parsed_header_t **header) 455*2882Svi117747 { 456*2882Svi117747 return (sip_parse_hdr_parser1(sip_header, header, (char)NULL)); 457*2882Svi117747 } 458*2882Svi117747 459*2882Svi117747 /* 460*2882Svi117747 * Retry-After = "Retry-After" HCOLON delta-seconds [ comment ] * 461*2882Svi117747 * (SEMI retry-param) 462*2882Svi117747 * retry-param = "duration" EQUAL delta-seconds 463*2882Svi117747 */ 464*2882Svi117747 int 465*2882Svi117747 sip_parse_retryaft_header(_sip_header_t *sip_header, 466*2882Svi117747 sip_parsed_header_t **header) 467*2882Svi117747 { 468*2882Svi117747 sip_parsed_header_t *parsed_header; 469*2882Svi117747 sip_hdr_value_t *value = NULL; 470*2882Svi117747 int ret; 471*2882Svi117747 472*2882Svi117747 if ((ret = sip_prim_parsers(sip_header, header)) != 0) 473*2882Svi117747 return (ret); 474*2882Svi117747 475*2882Svi117747 if (*header != NULL) 476*2882Svi117747 return (0); 477*2882Svi117747 478*2882Svi117747 parsed_header = calloc(1, sizeof (sip_parsed_header_t)); 479*2882Svi117747 if (parsed_header == NULL) 480*2882Svi117747 return (ENOMEM); 481*2882Svi117747 parsed_header->sip_parsed_header_version = SIP_PARSED_HEADER_VERSION_1; 482*2882Svi117747 parsed_header->sip_header = sip_header; 483*2882Svi117747 484*2882Svi117747 value = calloc(1, sizeof (sip_hdr_value_t)); 485*2882Svi117747 if (value == NULL) { 486*2882Svi117747 sip_free_phdr(parsed_header); 487*2882Svi117747 return (ENOMEM); 488*2882Svi117747 } 489*2882Svi117747 490*2882Svi117747 parsed_header->value = (sip_value_t *)value; 491*2882Svi117747 value->sip_value_start = sip_header->sip_hdr_current; 492*2882Svi117747 value->sip_value_header = parsed_header; 493*2882Svi117747 494*2882Svi117747 ret = sip_atoi(sip_header, &(value->intstr_int)); 495*2882Svi117747 if (ret != 0) 496*2882Svi117747 value->sip_value_state = SIP_VALUE_BAD; 497*2882Svi117747 if (sip_find_token(sip_header, SIP_LPAR) == 0) { 498*2882Svi117747 value->intstr_str_ptr = sip_header->sip_hdr_current; 499*2882Svi117747 if (sip_find_token(sip_header, SIP_RPAR) == 0) { 500*2882Svi117747 value->intstr_str_len = 501*2882Svi117747 sip_header->sip_hdr_current - 502*2882Svi117747 value->intstr_str_ptr - 1; 503*2882Svi117747 if (sip_find_token(sip_header, SIP_SEMI) == 0) { 504*2882Svi117747 sip_header->sip_hdr_current--; 505*2882Svi117747 (void) sip_parse_params(sip_header, 506*2882Svi117747 &(value->sip_param_list)); 507*2882Svi117747 } 508*2882Svi117747 } else { 509*2882Svi117747 value->sip_value_state = SIP_VALUE_BAD; 510*2882Svi117747 return (EPROTO); 511*2882Svi117747 } 512*2882Svi117747 } else { 513*2882Svi117747 value->intstr_str_ptr = NULL; 514*2882Svi117747 value->intstr_str_len = 0; 515*2882Svi117747 516*2882Svi117747 /* 517*2882Svi117747 * from value start, search if parameter list 518*2882Svi117747 */ 519*2882Svi117747 sip_header->sip_hdr_current = value->sip_value_start; 520*2882Svi117747 if (sip_find_token(sip_header, SIP_SEMI) == 0) { 521*2882Svi117747 sip_header->sip_hdr_current--; 522*2882Svi117747 (void) sip_parse_params(sip_header, 523*2882Svi117747 &(value->sip_param_list)); 524*2882Svi117747 } 525*2882Svi117747 } 526*2882Svi117747 527*2882Svi117747 *header = parsed_header; 528*2882Svi117747 sip_header->sip_hdr_parsed = *header; 529*2882Svi117747 return (0); 530*2882Svi117747 } 531*2882Svi117747 532*2882Svi117747 /* 533*2882Svi117747 * Server = "Server" HCOLON servel-val *(LWS server-val) 534*2882Svi117747 * servel-val = product|comment 535*2882Svi117747 * product = token [SLASH version] 536*2882Svi117747 * version = token 537*2882Svi117747 * Treated as one single string 538*2882Svi117747 */ 539*2882Svi117747 int 540*2882Svi117747 sip_parse_server_header(_sip_header_t *sip_header, sip_parsed_header_t **header) 541*2882Svi117747 { 542*2882Svi117747 return (sip_parse_hdr_parser4(sip_header, header)); 543*2882Svi117747 } 544*2882Svi117747 545*2882Svi117747 /* 546*2882Svi117747 * Subject = ("Subject" | "s")HCOLON [TEXT-UTF8-TRIM] 547*2882Svi117747 */ 548*2882Svi117747 int 549*2882Svi117747 sip_parse_subject_header(_sip_header_t *sip_header, 550*2882Svi117747 sip_parsed_header_t **header) 551*2882Svi117747 { 552*2882Svi117747 if (sip_is_empty_hdr(sip_header)) 553*2882Svi117747 return (sip_parse_hdr_empty(sip_header, header)); 554*2882Svi117747 return (sip_parse_hdr_parser4(sip_header, header)); 555*2882Svi117747 } 556*2882Svi117747 557*2882Svi117747 /* 558*2882Svi117747 * Supported = ("Supported" | "k") HCOLON [option-tag * (COMMA option-tag) ] 559*2882Svi117747 */ 560*2882Svi117747 int 561*2882Svi117747 sip_parse_support_header(_sip_header_t *sip_header, 562*2882Svi117747 sip_parsed_header_t **header) 563*2882Svi117747 { 564*2882Svi117747 if (sip_is_empty_hdr(sip_header)) 565*2882Svi117747 return (sip_parse_hdr_empty(sip_header, header)); 566*2882Svi117747 return (sip_parse_hdr_parser1(sip_header, header, (char)NULL)); 567*2882Svi117747 } 568*2882Svi117747 569*2882Svi117747 /* 570*2882Svi117747 * Timestamp = "Timestamp" HCOLON 1*DIGIT ["." *(DIGIT)] [LWS delay] 571*2882Svi117747 */ 572*2882Svi117747 int 573*2882Svi117747 sip_parse_timestamp_header(_sip_header_t *sip_header, 574*2882Svi117747 sip_parsed_header_t **header) 575*2882Svi117747 { 576*2882Svi117747 sip_parsed_header_t *parsed_header; 577*2882Svi117747 sip_hdr_value_t *value = NULL; 578*2882Svi117747 int ret; 579*2882Svi117747 580*2882Svi117747 if ((ret = sip_prim_parsers(sip_header, header)) != 0) 581*2882Svi117747 return (ret); 582*2882Svi117747 583*2882Svi117747 if (*header != NULL) 584*2882Svi117747 return (0); 585*2882Svi117747 586*2882Svi117747 parsed_header = calloc(1, sizeof (sip_parsed_header_t)); 587*2882Svi117747 if (parsed_header == NULL) 588*2882Svi117747 return (ENOMEM); 589*2882Svi117747 parsed_header->sip_parsed_header_version = SIP_PARSED_HEADER_VERSION_1; 590*2882Svi117747 parsed_header->sip_header = sip_header; 591*2882Svi117747 592*2882Svi117747 value = calloc(1, sizeof (sip_hdr_value_t)); 593*2882Svi117747 if (value == NULL) { 594*2882Svi117747 sip_free_phdr(parsed_header); 595*2882Svi117747 return (ENOMEM); 596*2882Svi117747 } 597*2882Svi117747 parsed_header->value = (sip_value_t *)value; 598*2882Svi117747 599*2882Svi117747 value->sip_value_start = sip_header->sip_hdr_current; 600*2882Svi117747 value->sip_value_header = parsed_header; 601*2882Svi117747 602*2882Svi117747 if (sip_skip_white_space(sip_header) != 0) { 603*2882Svi117747 value->sip_value_state = SIP_VALUE_BAD; 604*2882Svi117747 return (EPROTO); 605*2882Svi117747 } 606*2882Svi117747 value->strs1_val_ptr = sip_header->sip_hdr_current; 607*2882Svi117747 608*2882Svi117747 if (sip_find_white_space(sip_header) == 0) { 609*2882Svi117747 /* 610*2882Svi117747 * timestamp and delay, timestamp in str1, delay in str2 611*2882Svi117747 */ 612*2882Svi117747 value->strs1_val_len = sip_header->sip_hdr_current - 613*2882Svi117747 value->strs1_val_ptr; 614*2882Svi117747 (void) sip_skip_white_space(sip_header); 615*2882Svi117747 616*2882Svi117747 value->strs2_val_ptr = sip_header->sip_hdr_current; 617*2882Svi117747 if (sip_find_cr(sip_header) != 0) { 618*2882Svi117747 value->sip_value_state = SIP_VALUE_BAD; 619*2882Svi117747 return (EPROTO); 620*2882Svi117747 } 621*2882Svi117747 if (sip_header->sip_hdr_current < value->strs2_val_ptr) { 622*2882Svi117747 value->strs2_val_ptr = NULL; 623*2882Svi117747 value->strs2_val_len = 0; 624*2882Svi117747 } else { 625*2882Svi117747 value->strs2_val_len = sip_header->sip_hdr_current - 626*2882Svi117747 value->strs2_val_ptr; 627*2882Svi117747 } 628*2882Svi117747 } else { 629*2882Svi117747 /* 630*2882Svi117747 * no delay information 631*2882Svi117747 */ 632*2882Svi117747 value->strs1_val_len = sip_header->sip_hdr_current 633*2882Svi117747 - value->strs1_val_ptr; 634*2882Svi117747 value->strs2_val_ptr = NULL; 635*2882Svi117747 value->strs2_val_len = 0; 636*2882Svi117747 } 637*2882Svi117747 638*2882Svi117747 *header = parsed_header; 639*2882Svi117747 sip_header->sip_hdr_parsed = *header; 640*2882Svi117747 641*2882Svi117747 return (0); 642*2882Svi117747 } 643*2882Svi117747 /* 644*2882Svi117747 * Unsupported = "Unsupported" HCOLON option-tag * (COMMA option-tag) 645*2882Svi117747 */ 646*2882Svi117747 int 647*2882Svi117747 sip_parse_usupport_header(_sip_header_t *sip_header, 648*2882Svi117747 sip_parsed_header_t **header) 649*2882Svi117747 { 650*2882Svi117747 return (sip_parse_hdr_parser1(sip_header, header, (char)NULL)); 651*2882Svi117747 } 652*2882Svi117747 653*2882Svi117747 /* 654*2882Svi117747 * User-Agent = "User-Agent" HCOLON server-val * (LWS server-val) 655*2882Svi117747 * servel-val = product |comment 656*2882Svi117747 * product = token [SLASH version] 657*2882Svi117747 * version = token 658*2882Svi117747 */ 659*2882Svi117747 int 660*2882Svi117747 sip_parse_useragt_header(_sip_header_t *sip_header, 661*2882Svi117747 sip_parsed_header_t **header) 662*2882Svi117747 { 663*2882Svi117747 return (sip_parse_hdr_parser4(sip_header, header)); 664*2882Svi117747 } 665*2882Svi117747 666*2882Svi117747 /* 667*2882Svi117747 * Warning = "Warning" HCOLON warning-value *(COMMA warning-value) 668*2882Svi117747 * warning-value = warn-code SP warn-agent SP warn-text 669*2882Svi117747 * warn-code = 3DIGIT 670*2882Svi117747 * warn-agent = hostport | pseudonym ; 671*2882Svi117747 * the name or pseudonym of the server adding; 672*2882Svi117747 * the Warning header, for use in debugging 673*2882Svi117747 * warn-text = quoted-string 674*2882Svi117747 * pseudonym = token 675*2882Svi117747 */ 676*2882Svi117747 int 677*2882Svi117747 sip_parse_warn_header(_sip_header_t *sip_header, sip_parsed_header_t **header) 678*2882Svi117747 { 679*2882Svi117747 sip_parsed_header_t *parsed_header; 680*2882Svi117747 int ret; 681*2882Svi117747 sip_hdr_value_t *value = NULL; 682*2882Svi117747 sip_hdr_value_t *last_value = NULL; 683*2882Svi117747 684*2882Svi117747 if ((ret = sip_prim_parsers(sip_header, header)) != 0) 685*2882Svi117747 return (ret); 686*2882Svi117747 687*2882Svi117747 if (*header != NULL) 688*2882Svi117747 return (0); 689*2882Svi117747 690*2882Svi117747 parsed_header = calloc(1, sizeof (sip_parsed_header_t)); 691*2882Svi117747 if (parsed_header == NULL) 692*2882Svi117747 return (ENOMEM); 693*2882Svi117747 parsed_header->sip_parsed_header_version = SIP_PARSED_HEADER_VERSION_1; 694*2882Svi117747 parsed_header->sip_header = sip_header; 695*2882Svi117747 696*2882Svi117747 while (sip_header->sip_hdr_current < sip_header->sip_hdr_end) { 697*2882Svi117747 value = calloc(1, sizeof (sip_hdr_value_t)); 698*2882Svi117747 if (value == NULL) { 699*2882Svi117747 sip_free_phdr(parsed_header); 700*2882Svi117747 return (ENOMEM); 701*2882Svi117747 } 702*2882Svi117747 703*2882Svi117747 if (last_value != NULL) 704*2882Svi117747 last_value->sip_next_value = value; 705*2882Svi117747 else 706*2882Svi117747 parsed_header->value = (sip_value_t *)value; 707*2882Svi117747 708*2882Svi117747 value->sip_value_start = sip_header->sip_hdr_current; 709*2882Svi117747 value->sip_value_header = parsed_header; 710*2882Svi117747 711*2882Svi117747 ret = sip_atoi(sip_header, &value->warn_code); 712*2882Svi117747 if (ret != 0 || value->warn_code < 100 || 713*2882Svi117747 value->warn_code > 999) { 714*2882Svi117747 value->sip_value_state = SIP_VALUE_BAD; 715*2882Svi117747 goto get_next_val; 716*2882Svi117747 } 717*2882Svi117747 if (sip_skip_white_space(sip_header) != 0) { 718*2882Svi117747 value->sip_value_state = SIP_VALUE_BAD; 719*2882Svi117747 goto get_next_val; 720*2882Svi117747 } 721*2882Svi117747 value->warn_agt_ptr = sip_header->sip_hdr_current; 722*2882Svi117747 723*2882Svi117747 if (sip_find_token(sip_header, SIP_QUOTE) == 0) { 724*2882Svi117747 /* 725*2882Svi117747 * get warning agent 726*2882Svi117747 */ 727*2882Svi117747 sip_header->sip_hdr_current--; 728*2882Svi117747 (void) sip_reverse_skip_white_space(sip_header); 729*2882Svi117747 value->warn_agt_len = sip_header->sip_hdr_current - 730*2882Svi117747 value->warn_agt_ptr - 1; 731*2882Svi117747 if (value->warn_agt_len <= 0) { 732*2882Svi117747 value->warn_agt_ptr = NULL; 733*2882Svi117747 value->sip_value_state = SIP_VALUE_BAD; 734*2882Svi117747 } 735*2882Svi117747 736*2882Svi117747 /* 737*2882Svi117747 * We will have a SIP_QUOTE here 738*2882Svi117747 */ 739*2882Svi117747 (void) sip_find_token(sip_header, SIP_QUOTE); 740*2882Svi117747 741*2882Svi117747 value->warn_text_ptr = sip_header->sip_hdr_current; 742*2882Svi117747 if (sip_find_token(sip_header, SIP_QUOTE) == 0) { 743*2882Svi117747 value->warn_text_len = 744*2882Svi117747 sip_header->sip_hdr_current - 745*2882Svi117747 value->warn_text_ptr - 1; 746*2882Svi117747 } else { 747*2882Svi117747 value->sip_value_state = SIP_VALUE_BAD; 748*2882Svi117747 goto get_next_val; 749*2882Svi117747 } 750*2882Svi117747 } else 751*2882Svi117747 /* 752*2882Svi117747 * warning text must present 753*2882Svi117747 */ 754*2882Svi117747 value->sip_value_state = SIP_VALUE_BAD; 755*2882Svi117747 756*2882Svi117747 get_next_val: 757*2882Svi117747 if (sip_find_token(sip_header, SIP_COMMA) != 0) 758*2882Svi117747 break; 759*2882Svi117747 value->sip_value_end = sip_header->sip_hdr_current - 1; 760*2882Svi117747 last_value = value; 761*2882Svi117747 (void) sip_skip_white_space(sip_header); 762*2882Svi117747 } 763*2882Svi117747 764*2882Svi117747 *header = parsed_header; 765*2882Svi117747 766*2882Svi117747 sip_header->sip_hdr_parsed = *header; 767*2882Svi117747 return (0); 768*2882Svi117747 } 769*2882Svi117747 770*2882Svi117747 /* 771*2882Svi117747 * Parse RAck header 772*2882Svi117747 * "RAck" HCOLON response-num LWS CSeq-num LWS Method 773*2882Svi117747 * response-num = 1*DIGIT 774*2882Svi117747 * CSeq-num = 1*DIGIT 775*2882Svi117747 */ 776*2882Svi117747 int 777*2882Svi117747 sip_parse_rack(_sip_header_t *sip_header, sip_parsed_header_t **header) 778*2882Svi117747 { 779*2882Svi117747 sip_parsed_header_t *parsed_header; 780*2882Svi117747 sip_hdr_value_t *rack_value; 781*2882Svi117747 int len; 782*2882Svi117747 char *tmp_ptr; 783*2882Svi117747 int i; 784*2882Svi117747 int ret; 785*2882Svi117747 786*2882Svi117747 if ((ret = sip_prim_parsers(sip_header, header)) != 0) 787*2882Svi117747 return (ret); 788*2882Svi117747 789*2882Svi117747 if (*header != NULL) 790*2882Svi117747 return (0); 791*2882Svi117747 792*2882Svi117747 parsed_header = calloc(1, sizeof (sip_parsed_header_t)); 793*2882Svi117747 if (parsed_header == NULL) 794*2882Svi117747 return (ENOMEM); 795*2882Svi117747 parsed_header->sip_parsed_header_version = SIP_PARSED_HEADER_VERSION_1; 796*2882Svi117747 parsed_header->sip_header = sip_header; 797*2882Svi117747 798*2882Svi117747 parsed_header->value = calloc(1, sizeof (sip_hdr_value_t)); 799*2882Svi117747 if (parsed_header->value == NULL) { 800*2882Svi117747 free(parsed_header); 801*2882Svi117747 return (ENOMEM); 802*2882Svi117747 } 803*2882Svi117747 rack_value = (sip_hdr_value_t *)parsed_header->value; 804*2882Svi117747 rack_value->sip_value_version = SIP_VALUE_VERSION_1; 805*2882Svi117747 rack_value->sip_value_start = sip_header->sip_hdr_current; 806*2882Svi117747 rack_value->sip_value_header = parsed_header; 807*2882Svi117747 if (sip_atoi(sip_header, &rack_value->rack_resp) || 808*2882Svi117747 rack_value->rack_resp == 0) { 809*2882Svi117747 rack_value->sip_value_state = SIP_VALUE_BAD; 810*2882Svi117747 rack_value->sip_value_end = sip_header->sip_hdr_end - 2; 811*2882Svi117747 goto rack_parse_done; 812*2882Svi117747 } 813*2882Svi117747 rack_value->sip_value_header = parsed_header; 814*2882Svi117747 /* 815*2882Svi117747 * Get cseq. 816*2882Svi117747 */ 817*2882Svi117747 if (sip_skip_white_space(sip_header) != 0) { 818*2882Svi117747 rack_value->sip_value_state = SIP_VALUE_BAD; 819*2882Svi117747 rack_value->sip_value_end = sip_header->sip_hdr_end - 2; 820*2882Svi117747 goto rack_parse_done; 821*2882Svi117747 } 822*2882Svi117747 if (sip_atoi(sip_header, &rack_value->rack_cseq)) { 823*2882Svi117747 rack_value->sip_value_state = SIP_VALUE_BAD; 824*2882Svi117747 rack_value->sip_value_end = sip_header->sip_hdr_end - 2; 825*2882Svi117747 goto rack_parse_done; 826*2882Svi117747 } 827*2882Svi117747 /* 828*2882Svi117747 * Get method. 829*2882Svi117747 */ 830*2882Svi117747 if (sip_skip_white_space(sip_header) != 0) { 831*2882Svi117747 rack_value->sip_value_state = SIP_VALUE_BAD; 832*2882Svi117747 rack_value->sip_value_end = sip_header->sip_hdr_end - 2; 833*2882Svi117747 goto rack_parse_done; 834*2882Svi117747 } 835*2882Svi117747 836*2882Svi117747 tmp_ptr = sip_header->sip_hdr_current; 837*2882Svi117747 if (sip_find_white_space(sip_header)) { 838*2882Svi117747 rack_value->sip_value_state = SIP_VALUE_BAD; 839*2882Svi117747 rack_value->sip_value_end = sip_header->sip_hdr_end - 2; 840*2882Svi117747 goto rack_parse_done; 841*2882Svi117747 } 842*2882Svi117747 843*2882Svi117747 len = sip_header->sip_hdr_current - tmp_ptr; 844*2882Svi117747 845*2882Svi117747 for (i = 1; i < MAX_SIP_METHODS; i++) { 846*2882Svi117747 if (strncmp(sip_methods[i].name, tmp_ptr, len) == 0) 847*2882Svi117747 break; 848*2882Svi117747 } 849*2882Svi117747 850*2882Svi117747 if (i >= MAX_SIP_METHODS) { 851*2882Svi117747 rack_value->sip_value_state = SIP_VALUE_BAD; 852*2882Svi117747 rack_value->sip_value_end = sip_header->sip_hdr_end - 2; 853*2882Svi117747 goto rack_parse_done; 854*2882Svi117747 } 855*2882Svi117747 856*2882Svi117747 rack_value->rack_method = i; 857*2882Svi117747 rack_value->sip_value_end = sip_header->sip_hdr_current; 858*2882Svi117747 859*2882Svi117747 rack_parse_done: 860*2882Svi117747 sip_header->sip_hdr_parsed = parsed_header; 861*2882Svi117747 862*2882Svi117747 *header = parsed_header; 863*2882Svi117747 return (0); 864*2882Svi117747 } 865*2882Svi117747 866*2882Svi117747 /* 867*2882Svi117747 * Allow = "Allow" HCOLON [Method *(COMMA Method)] 868*2882Svi117747 */ 869*2882Svi117747 int 870*2882Svi117747 sip_parse_allow_events_header(_sip_header_t *sip_header, 871*2882Svi117747 sip_parsed_header_t **header) 872*2882Svi117747 { 873*2882Svi117747 return (sip_parse_hdr_parser1(sip_header, header, (char)NULL)); 874*2882Svi117747 } 875*2882Svi117747 876*2882Svi117747 /* 877*2882Svi117747 * Event = ( "Event" / "o" ) HCOLON event-type 878*2882Svi117747 * *( SEMI event-param ) 879*2882Svi117747 * event-type = event-package *( "." event-template ) 880*2882Svi117747 * event-package = token-nodot 881*2882Svi117747 * event-template = token-nodot 882*2882Svi117747 * token-nodot = 1*( alphanum / "-" / "!" / "%" / "*" 883*2882Svi117747 * / "_" / "+" / "`" / "'" / "~" ) 884*2882Svi117747 * event-param = generic-param / ( "id" EQUAL token ) 885*2882Svi117747 */ 886*2882Svi117747 int 887*2882Svi117747 sip_parse_event_header(_sip_header_t *sip_header, sip_parsed_header_t **header) 888*2882Svi117747 { 889*2882Svi117747 return (sip_parse_hdr_parser1(sip_header, header, (char)NULL)); 890*2882Svi117747 } 891*2882Svi117747 892*2882Svi117747 /* 893*2882Svi117747 * Subscription-State = "Subscription-State" HCOLON substate-value 894*2882Svi117747 * *( SEMI subexp-params ) 895*2882Svi117747 * substate-value = "active" / "pending" / "terminated" 896*2882Svi117747 * / extension-substate 897*2882Svi117747 * extension-substate = token 898*2882Svi117747 * subexp-params = ("reason" EQUAL event-reason-value) 899*2882Svi117747 * / ("expires" EQUAL delta-seconds)* 900*2882Svi117747 * / ("retry-after" EQUAL delta-seconds) 901*2882Svi117747 * / generic-param 902*2882Svi117747 * event-reason-value = "deactivated" 903*2882Svi117747 * / "probation" 904*2882Svi117747 * / "rejected" 905*2882Svi117747 * / "timeout" 906*2882Svi117747 * / "giveup" 907*2882Svi117747 * / "noresource" 908*2882Svi117747 * / event-reason-extension 909*2882Svi117747 * event-reason-extension = token 910*2882Svi117747 */ 911*2882Svi117747 int 912*2882Svi117747 sip_parse_substate_header(_sip_header_t *sip_header, 913*2882Svi117747 sip_parsed_header_t **header) 914*2882Svi117747 { 915*2882Svi117747 return (sip_parse_hdr_parser1(sip_header, header, (char)NULL)); 916*2882Svi117747 } 917*2882Svi117747 918*2882Svi117747 /* 919*2882Svi117747 * Authorization = "Authorization" HCOLON credentials 920*2882Svi117747 * credentials = ("Digest" LWS digest-response) 921*2882Svi117747 * / other-response 922*2882Svi117747 * digest-response = dig-resp *(COMMA dig-resp) 923*2882Svi117747 * dig-resp = username / realm / nonce / digest-uri 924*2882Svi117747 * / dresponse / algorithm / cnonce 925*2882Svi117747 * / opaque / message-qop 926*2882Svi117747 * / nonce-count / auth-param 927*2882Svi117747 * username = "username" EQUAL username-value 928*2882Svi117747 * username-value = quoted-string 929*2882Svi117747 * digest-uri = "uri" EQUAL LDQUOT digest-uri-value RDQUOT 930*2882Svi117747 * digest-uri-value = rquest-uri ; Equal to request-uri as specified 931*2882Svi117747 * by HTTP/1.1 932*2882Svi117747 * message-qop = "qop" EQUAL qop-value 933*2882Svi117747 * cnonce = "cnonce" EQUAL cnonce-value 934*2882Svi117747 * cnonce-value = nonce-value 935*2882Svi117747 * nonce-count = "nc" EQUAL nc-value 936*2882Svi117747 * nc-value = 8LHEX 937*2882Svi117747 * dresponse = "response" EQUAL request-digest 938*2882Svi117747 * request-digest = LDQUOT 32LHEX RDQUOT 939*2882Svi117747 * auth-param = auth-param-name EQUAL 940*2882Svi117747 * ( token / quoted-string ) 941*2882Svi117747 * auth-param-name = token 942*2882Svi117747 * other-response = auth-scheme LWS auth-param 943*2882Svi117747 * *(COMMA auth-param) 944*2882Svi117747 * auth-scheme = token 945*2882Svi117747 */ 946*2882Svi117747 int 947*2882Svi117747 sip_parse_author_header(_sip_header_t *sip_header, 948*2882Svi117747 sip_parsed_header_t **header) 949*2882Svi117747 { 950*2882Svi117747 return (sip_parse_hdr_parser5(sip_header, header, B_TRUE)); 951*2882Svi117747 } 952*2882Svi117747 953*2882Svi117747 /* 954*2882Svi117747 * Authentication-Info = "Authentication-Info" HCOLON ainfo 955*2882Svi117747 * *(COMMA ainfo) 956*2882Svi117747 * ainfo = nextnonce / message-qop 957*2882Svi117747 * / response-auth / cnonce 958*2882Svi117747 * / nonce-count 959*2882Svi117747 * nextnonce = "nextnonce" EQUAL nonce-value 960*2882Svi117747 * response-auth = "rspauth" EQUAL response-digest 961*2882Svi117747 * response-digest = LDQUOT *LHEX RDQUOT 962*2882Svi117747 * 963*2882Svi117747 */ 964*2882Svi117747 int 965*2882Svi117747 sip_parse_ainfo_header(_sip_header_t *sip_header, 966*2882Svi117747 sip_parsed_header_t **header) 967*2882Svi117747 { 968*2882Svi117747 return (sip_parse_hdr_parser1(sip_header, header, (char)NULL)); 969*2882Svi117747 } 970*2882Svi117747 971*2882Svi117747 /* 972*2882Svi117747 * Proxy-Authenticate = "Proxy-Authenticate" HCOLON challenge 973*2882Svi117747 * challenge = ("Digest" LWS digest-cln *(COMMA digest-cln)) 974*2882Svi117747 * / other-challenge 975*2882Svi117747 * other-challenge = auth-scheme LWS auth-param 976*2882Svi117747 * *(COMMA auth-param) 977*2882Svi117747 * digest-cln = realm / domain / nonce 978*2882Svi117747 * / opaque / stale / algorithm 979*2882Svi117747 * / qop-options / auth-param 980*2882Svi117747 * realm = "realm" EQUAL realm-value 981*2882Svi117747 * realm-value = quoted-string 982*2882Svi117747 * domain = "domain" EQUAL LDQUOT URI 983*2882Svi117747 * *( 1*SP URI ) RDQUOT 984*2882Svi117747 * URI = absoluteURI / abs-path 985*2882Svi117747 * nonce = "nonce" EQUAL nonce-value 986*2882Svi117747 * nonce-value = quoted-string 987*2882Svi117747 * opaque = "opaque" EQUAL quoted-string 988*2882Svi117747 * stale = "stale" EQUAL ( "true" / "false" ) 989*2882Svi117747 * algorithm = "algorithm" EQUAL ( "MD5" / "MD5-sess" 990*2882Svi117747 * / token ) 991*2882Svi117747 * qop-options = "qop" EQUAL LDQUOT qop-value 992*2882Svi117747 * *("," qop-value) RDQUOT 993*2882Svi117747 * qop-value = "auth" / "auth-int" / token 994*2882Svi117747 * 995*2882Svi117747 */ 996*2882Svi117747 int 997*2882Svi117747 sip_parse_pauthen_header(_sip_header_t *sip_header, 998*2882Svi117747 sip_parsed_header_t **header) 999*2882Svi117747 { 1000*2882Svi117747 return (sip_parse_hdr_parser5(sip_header, header, B_TRUE)); 1001*2882Svi117747 } 1002*2882Svi117747 1003*2882Svi117747 /* 1004*2882Svi117747 * Proxy-Authorization = "Proxy-Authorization" HCOLON credentials 1005*2882Svi117747 */ 1006*2882Svi117747 int 1007*2882Svi117747 sip_parse_pauthor_header(_sip_header_t *sip_header, 1008*2882Svi117747 sip_parsed_header_t **header) 1009*2882Svi117747 { 1010*2882Svi117747 return (sip_parse_hdr_parser5(sip_header, header, B_TRUE)); 1011*2882Svi117747 } 1012*2882Svi117747 1013*2882Svi117747 /* 1014*2882Svi117747 * Proxy-Require = "Proxy-Require" HCOLON option-tag 1015*2882Svi117747 * *(COMMA option-tag) 1016*2882Svi117747 * option-tag = token 1017*2882Svi117747 */ 1018*2882Svi117747 int 1019*2882Svi117747 sip_parse_preq_header(_sip_header_t *sip_header, 1020*2882Svi117747 sip_parsed_header_t **header) 1021*2882Svi117747 { 1022*2882Svi117747 return (sip_parse_hdr_parser1(sip_header, header, (char)NULL)); 1023*2882Svi117747 } 1024*2882Svi117747 1025*2882Svi117747 /* 1026*2882Svi117747 * WWW-Authenticate = "WWW-Authenticate" HCOLON challenge 1027*2882Svi117747 * extension-header = header-name HCOLON header-value 1028*2882Svi117747 * header-name = token 1029*2882Svi117747 * header-value = *(TEXT-UTF8char / UTF8-CONT / LWS) 1030*2882Svi117747 * message-body = *OCTET 1031*2882Svi117747 * 1032*2882Svi117747 */ 1033*2882Svi117747 int 1034*2882Svi117747 sip_parse_wauthen_header(_sip_header_t *sip_header, 1035*2882Svi117747 sip_parsed_header_t **header) 1036*2882Svi117747 { 1037*2882Svi117747 return (sip_parse_hdr_parser5(sip_header, header, B_TRUE)); 1038*2882Svi117747 } 1039*2882Svi117747 1040*2882Svi117747 /* 1041*2882Svi117747 * Call-ID = ( "Call-ID" / "i" ) HCOLON callid 1042*2882Svi117747 */ 1043*2882Svi117747 int 1044*2882Svi117747 sip_parse_cid_header(_sip_header_t *sip_header, sip_parsed_header_t **header) 1045*2882Svi117747 { 1046*2882Svi117747 return (sip_parse_hdr_parser4(sip_header, header)); 1047*2882Svi117747 } 1048*2882Svi117747 1049*2882Svi117747 /* 1050*2882Svi117747 * CSeq = "CSeq" HCOLON 1*DIGIT LWS Method 1051*2882Svi117747 */ 1052*2882Svi117747 int 1053*2882Svi117747 sip_parse_cseq_header(_sip_header_t *sip_header, sip_parsed_header_t **header) 1054*2882Svi117747 { 1055*2882Svi117747 sip_parsed_header_t *parsed_header; 1056*2882Svi117747 sip_hdr_value_t *cseq_value; 1057*2882Svi117747 int len; 1058*2882Svi117747 char *tmp_ptr; 1059*2882Svi117747 int i; 1060*2882Svi117747 int ret; 1061*2882Svi117747 1062*2882Svi117747 if ((ret = sip_prim_parsers(sip_header, header)) != 0) 1063*2882Svi117747 return (ret); 1064*2882Svi117747 1065*2882Svi117747 if (*header != NULL) 1066*2882Svi117747 return (0); 1067*2882Svi117747 1068*2882Svi117747 parsed_header = calloc(1, sizeof (sip_parsed_header_t)); 1069*2882Svi117747 if (parsed_header == NULL) 1070*2882Svi117747 return (ENOMEM); 1071*2882Svi117747 parsed_header->sip_parsed_header_version = SIP_PARSED_HEADER_VERSION_1; 1072*2882Svi117747 parsed_header->sip_header = sip_header; 1073*2882Svi117747 1074*2882Svi117747 parsed_header->value = calloc(1, sizeof (sip_hdr_value_t)); 1075*2882Svi117747 if (parsed_header->value == NULL) { 1076*2882Svi117747 free(parsed_header); 1077*2882Svi117747 return (ENOMEM); 1078*2882Svi117747 } 1079*2882Svi117747 cseq_value = (sip_hdr_value_t *)parsed_header->value; 1080*2882Svi117747 cseq_value->sip_value_version = SIP_VALUE_VERSION_1; 1081*2882Svi117747 cseq_value->sip_value_start = sip_header->sip_hdr_current; 1082*2882Svi117747 if (sip_atoi(sip_header, &cseq_value->cseq_num)) { 1083*2882Svi117747 cseq_value->sip_value_state = SIP_VALUE_BAD; 1084*2882Svi117747 cseq_value->sip_value_end = sip_header->sip_hdr_end - 2; 1085*2882Svi117747 goto cseq_parse_done; 1086*2882Svi117747 } 1087*2882Svi117747 cseq_value->sip_value_header = parsed_header; 1088*2882Svi117747 /* 1089*2882Svi117747 * Get method. 1090*2882Svi117747 */ 1091*2882Svi117747 if (sip_skip_white_space(sip_header) != 0) { 1092*2882Svi117747 cseq_value->sip_value_state = SIP_VALUE_BAD; 1093*2882Svi117747 cseq_value->sip_value_end = sip_header->sip_hdr_end - 2; 1094*2882Svi117747 goto cseq_parse_done; 1095*2882Svi117747 } 1096*2882Svi117747 1097*2882Svi117747 tmp_ptr = sip_header->sip_hdr_current; 1098*2882Svi117747 1099*2882Svi117747 if (sip_find_white_space(sip_header)) { 1100*2882Svi117747 cseq_value->sip_value_state = SIP_VALUE_BAD; 1101*2882Svi117747 cseq_value->sip_value_end = sip_header->sip_hdr_current; 1102*2882Svi117747 goto cseq_parse_done; 1103*2882Svi117747 } 1104*2882Svi117747 1105*2882Svi117747 len = sip_header->sip_hdr_current - tmp_ptr; 1106*2882Svi117747 1107*2882Svi117747 for (i = 1; i < MAX_SIP_METHODS; i++) { 1108*2882Svi117747 if (strncmp(sip_methods[i].name, tmp_ptr, len) == 0) 1109*2882Svi117747 break; 1110*2882Svi117747 } 1111*2882Svi117747 1112*2882Svi117747 if (i >= MAX_SIP_METHODS) { 1113*2882Svi117747 cseq_value->sip_value_state = SIP_VALUE_BAD; 1114*2882Svi117747 cseq_value->sip_value_end = sip_header->sip_hdr_current; 1115*2882Svi117747 goto cseq_parse_done; 1116*2882Svi117747 } 1117*2882Svi117747 1118*2882Svi117747 cseq_value->cseq_method = i; 1119*2882Svi117747 cseq_value->sip_value_end = sip_header->sip_hdr_current; 1120*2882Svi117747 cseq_parse_done: 1121*2882Svi117747 1122*2882Svi117747 sip_header->sip_hdr_parsed = parsed_header; 1123*2882Svi117747 1124*2882Svi117747 *header = parsed_header; 1125*2882Svi117747 return (0); 1126*2882Svi117747 } 1127*2882Svi117747 1128*2882Svi117747 1129*2882Svi117747 /* 1130*2882Svi117747 * Via = ( "Via" / "v" ) HCOLON via-parm *(COMMA via-parm) 1131*2882Svi117747 * via-parm = sent-protocol LWS sent-by *( SEMI via-params ) 1132*2882Svi117747 * via-params = via-ttl / via-maddr 1133*2882Svi117747 * / via-received / via-branch 1134*2882Svi117747 * / via-extension 1135*2882Svi117747 * via-ttl = "ttl" EQUAL ttl 1136*2882Svi117747 * via-maddr = "maddr" EQUAL host 1137*2882Svi117747 * via-received = "received" EQUAL (IPv4address / IPv6address) 1138*2882Svi117747 * via-branch = "branch" EQUAL token 1139*2882Svi117747 * via-extension = generic-param 1140*2882Svi117747 * sent-protocol = protocol-name SLASH protocol-version 1141*2882Svi117747 * SLASH transport 1142*2882Svi117747 * protocol-name = "SIP" / token 1143*2882Svi117747 * protocol-version = token 1144*2882Svi117747 * transport = "UDP" / "TCP" / "TLS" / "SCTP" 1145*2882Svi117747 * / other-transport 1146*2882Svi117747 * sent-by = host [ COLON port ] 1147*2882Svi117747 * ttl = 1*3DIGIT ; 0 to 255 1148*2882Svi117747 * 1149*2882Svi117747 * There can be multiple via headers we always append the header. 1150*2882Svi117747 */ 1151*2882Svi117747 int 1152*2882Svi117747 sip_parse_via_header(_sip_header_t *sip_header, sip_parsed_header_t **header) 1153*2882Svi117747 { 1154*2882Svi117747 sip_parsed_header_t *parsed_header; 1155*2882Svi117747 int ret; 1156*2882Svi117747 sip_hdr_value_t *value = NULL; 1157*2882Svi117747 sip_hdr_value_t *last_value = NULL; 1158*2882Svi117747 1159*2882Svi117747 if ((ret = sip_prim_parsers(sip_header, header)) != 0) 1160*2882Svi117747 return (ret); 1161*2882Svi117747 1162*2882Svi117747 if (*header != NULL) 1163*2882Svi117747 return (0); 1164*2882Svi117747 1165*2882Svi117747 parsed_header = calloc(1, sizeof (sip_parsed_header_t)); 1166*2882Svi117747 if (parsed_header == NULL) 1167*2882Svi117747 return (ENOMEM); 1168*2882Svi117747 parsed_header->sip_parsed_header_version = SIP_PARSED_HEADER_VERSION_1; 1169*2882Svi117747 parsed_header->sip_header = sip_header; 1170*2882Svi117747 1171*2882Svi117747 while (sip_header->sip_hdr_current < sip_header->sip_hdr_end) { 1172*2882Svi117747 1173*2882Svi117747 value = calloc(1, sizeof (sip_hdr_value_t)); 1174*2882Svi117747 if (value == NULL) { 1175*2882Svi117747 sip_free_phdr(parsed_header); 1176*2882Svi117747 return (ENOMEM); 1177*2882Svi117747 } 1178*2882Svi117747 if (last_value != NULL) 1179*2882Svi117747 last_value->sip_next_value = value; 1180*2882Svi117747 else 1181*2882Svi117747 parsed_header->value = (sip_value_t *)value; 1182*2882Svi117747 1183*2882Svi117747 value->sip_value_version = SIP_VALUE_VERSION_1; 1184*2882Svi117747 value->sip_value_start = sip_header->sip_hdr_current; 1185*2882Svi117747 value->sip_value_header = parsed_header; 1186*2882Svi117747 value->via_protocol_name.sip_str_ptr = 1187*2882Svi117747 sip_header->sip_hdr_current; 1188*2882Svi117747 1189*2882Svi117747 /* 1190*2882Svi117747 * Check to see if there is a version number 1191*2882Svi117747 */ 1192*2882Svi117747 if (sip_get_protocol_version(sip_header, 1193*2882Svi117747 &value->via_protocol) != 0) { 1194*2882Svi117747 if (sip_goto_next_value(sip_header) != 0) { 1195*2882Svi117747 sip_free_phdr(parsed_header); 1196*2882Svi117747 return (EPROTO); 1197*2882Svi117747 } 1198*2882Svi117747 value->sip_value_state = SIP_VALUE_BAD; 1199*2882Svi117747 goto get_next_via_value; 1200*2882Svi117747 } 1201*2882Svi117747 1202*2882Svi117747 if (sip_find_token(sip_header, SIP_SLASH) != 0) { 1203*2882Svi117747 if (sip_goto_next_value(sip_header) != 0) { 1204*2882Svi117747 sip_free_phdr(parsed_header); 1205*2882Svi117747 return (EPROTO); 1206*2882Svi117747 } 1207*2882Svi117747 value->sip_value_state = SIP_VALUE_BAD; 1208*2882Svi117747 goto get_next_via_value; 1209*2882Svi117747 } 1210*2882Svi117747 1211*2882Svi117747 if (sip_skip_white_space(sip_header) != 0) { 1212*2882Svi117747 if (sip_goto_next_value(sip_header) != 0) { 1213*2882Svi117747 sip_free_phdr(parsed_header); 1214*2882Svi117747 return (EPROTO); 1215*2882Svi117747 } 1216*2882Svi117747 value->sip_value_state = SIP_VALUE_BAD; 1217*2882Svi117747 goto get_next_via_value; 1218*2882Svi117747 } 1219*2882Svi117747 1220*2882Svi117747 value->via_protocol_transport.sip_str_ptr = 1221*2882Svi117747 sip_header->sip_hdr_current; 1222*2882Svi117747 if (sip_find_white_space(sip_header) != 0) { 1223*2882Svi117747 if (sip_goto_next_value(sip_header) != 0) { 1224*2882Svi117747 sip_free_phdr(parsed_header); 1225*2882Svi117747 return (EPROTO); 1226*2882Svi117747 } 1227*2882Svi117747 value->sip_value_state = SIP_VALUE_BAD; 1228*2882Svi117747 goto get_next_via_value; 1229*2882Svi117747 } 1230*2882Svi117747 1231*2882Svi117747 value->via_protocol_transport.sip_str_len = 1232*2882Svi117747 sip_header->sip_hdr_current - 1233*2882Svi117747 value->via_protocol_transport.sip_str_ptr; 1234*2882Svi117747 1235*2882Svi117747 if (sip_skip_white_space(sip_header) != 0) { 1236*2882Svi117747 if (sip_goto_next_value(sip_header) != 0) { 1237*2882Svi117747 sip_free_phdr(parsed_header); 1238*2882Svi117747 return (EPROTO); 1239*2882Svi117747 } 1240*2882Svi117747 value->sip_value_state = SIP_VALUE_BAD; 1241*2882Svi117747 goto get_next_via_value; 1242*2882Svi117747 } 1243*2882Svi117747 1244*2882Svi117747 value->via_sent_by_host.sip_str_ptr = 1245*2882Svi117747 sip_header->sip_hdr_current; 1246*2882Svi117747 if (*sip_header->sip_hdr_current == '[') { 1247*2882Svi117747 if (sip_find_token(sip_header, ']')) { 1248*2882Svi117747 if (sip_goto_next_value(sip_header) != 0) { 1249*2882Svi117747 sip_free_phdr(parsed_header); 1250*2882Svi117747 return (EPROTO); 1251*2882Svi117747 } 1252*2882Svi117747 value->sip_value_state = SIP_VALUE_BAD; 1253*2882Svi117747 goto get_next_via_value; 1254*2882Svi117747 } 1255*2882Svi117747 } else if (sip_find_separator(sip_header, SIP_SEMI, SIP_COMMA, 1256*2882Svi117747 SIP_HCOLON)) { 1257*2882Svi117747 if (sip_goto_next_value(sip_header) != 0) { 1258*2882Svi117747 sip_free_phdr(parsed_header); 1259*2882Svi117747 return (EPROTO); 1260*2882Svi117747 } 1261*2882Svi117747 value->sip_value_state = SIP_VALUE_BAD; 1262*2882Svi117747 goto get_next_via_value; 1263*2882Svi117747 } 1264*2882Svi117747 value->via_sent_by_host.sip_str_len = 1265*2882Svi117747 sip_header->sip_hdr_current - 1266*2882Svi117747 value->via_sent_by_host.sip_str_ptr; 1267*2882Svi117747 1268*2882Svi117747 if (sip_skip_white_space(sip_header) != 0) { 1269*2882Svi117747 if (sip_goto_next_value(sip_header) != 0) { 1270*2882Svi117747 sip_free_phdr(parsed_header); 1271*2882Svi117747 return (EPROTO); 1272*2882Svi117747 } 1273*2882Svi117747 value->sip_value_state = SIP_VALUE_BAD; 1274*2882Svi117747 goto get_next_via_value; 1275*2882Svi117747 } 1276*2882Svi117747 1277*2882Svi117747 if (*sip_header->sip_hdr_current == SIP_HCOLON) { 1278*2882Svi117747 sip_header->sip_hdr_current++; 1279*2882Svi117747 /* 1280*2882Svi117747 * We have a port number 1281*2882Svi117747 */ 1282*2882Svi117747 if (sip_atoi(sip_header, &value->via_sent_by_port) != 1283*2882Svi117747 0) { 1284*2882Svi117747 if (sip_goto_next_value(sip_header) != 0) { 1285*2882Svi117747 sip_free_phdr(parsed_header); 1286*2882Svi117747 return (EPROTO); 1287*2882Svi117747 } 1288*2882Svi117747 value->sip_value_state = SIP_VALUE_BAD; 1289*2882Svi117747 goto get_next_via_value; 1290*2882Svi117747 } 1291*2882Svi117747 1292*2882Svi117747 } 1293*2882Svi117747 1294*2882Svi117747 /* 1295*2882Svi117747 * Do some sanity checking. 1296*2882Svi117747 * This should be replaced by a v4/v6 address check. 1297*2882Svi117747 */ 1298*2882Svi117747 if (value->via_sent_by_host.sip_str_len == 0 || 1299*2882Svi117747 (!isalnum(*value->via_sent_by_host.sip_str_ptr) && 1300*2882Svi117747 *value->via_sent_by_host.sip_str_ptr != '[')) { 1301*2882Svi117747 if (sip_goto_next_value(sip_header) != 0) { 1302*2882Svi117747 sip_free_phdr(parsed_header); 1303*2882Svi117747 return (EPROTO); 1304*2882Svi117747 } 1305*2882Svi117747 value->sip_value_state = SIP_VALUE_BAD; 1306*2882Svi117747 goto get_next_via_value; 1307*2882Svi117747 } 1308*2882Svi117747 1309*2882Svi117747 ret = sip_parse_params(sip_header, &value->sip_param_list); 1310*2882Svi117747 if (ret == EPROTO) { 1311*2882Svi117747 value->sip_value_state = SIP_VALUE_BAD; 1312*2882Svi117747 } else if (ret != 0) { 1313*2882Svi117747 sip_free_phdr(parsed_header); 1314*2882Svi117747 return (ret); 1315*2882Svi117747 } 1316*2882Svi117747 get_next_via_value: 1317*2882Svi117747 value->sip_value_end = sip_header->sip_hdr_current; 1318*2882Svi117747 1319*2882Svi117747 if (sip_find_token(sip_header, SIP_COMMA) != 0) 1320*2882Svi117747 break; 1321*2882Svi117747 last_value = value; 1322*2882Svi117747 (void) sip_skip_white_space(sip_header); 1323*2882Svi117747 } 1324*2882Svi117747 1325*2882Svi117747 sip_header->sip_hdr_parsed = parsed_header; 1326*2882Svi117747 1327*2882Svi117747 *header = parsed_header; 1328*2882Svi117747 return (0); 1329*2882Svi117747 } 1330*2882Svi117747 1331*2882Svi117747 /* 1332*2882Svi117747 * Max-Forwards = "Max-Forwards" HCOLON 1*DIGIT 1333*2882Svi117747 */ 1334*2882Svi117747 int 1335*2882Svi117747 sip_parse_maxf_header(_sip_header_t *sip_header, sip_parsed_header_t **header) 1336*2882Svi117747 { 1337*2882Svi117747 return (sip_parse_hdr_parser2(sip_header, header, SIP_INT_VAL)); 1338*2882Svi117747 } 1339*2882Svi117747 1340*2882Svi117747 /* 1341*2882Svi117747 * Content-Type = ( "Content-Type" / "c" ) HCOLON media-type 1342*2882Svi117747 * media-type = m-type SLASH m-subtype *(SEMI m-parameter) 1343*2882Svi117747 * m-type = discrete-type / composite-type 1344*2882Svi117747 * discrete-type = "text" / "image" / "audio" / "video" 1345*2882Svi117747 * / "application" / extension-token 1346*2882Svi117747 * composite-type = "message" / "multipart" / extension-token 1347*2882Svi117747 * extension-token = ietf-token / x-token 1348*2882Svi117747 * ietf-token = token 1349*2882Svi117747 * x-token = "x-" token 1350*2882Svi117747 * m-subtype = extension-token / iana-token 1351*2882Svi117747 * iana-token = token 1352*2882Svi117747 * m-parameter = m-attribute EQUAL m-value 1353*2882Svi117747 * m-attribute = token 1354*2882Svi117747 * m-value = token / quoted-string 1355*2882Svi117747 */ 1356*2882Svi117747 int 1357*2882Svi117747 sip_parse_ctype_header(_sip_header_t *sip_header, sip_parsed_header_t **header) 1358*2882Svi117747 { 1359*2882Svi117747 return (sip_parse_hdr_parser1(sip_header, header, SIP_SLASH)); 1360*2882Svi117747 } 1361*2882Svi117747 1362*2882Svi117747 /* 1363*2882Svi117747 * Content-Length = ( "Content-Length" / "l" ) HCOLON 1*DIGIT 1364*2882Svi117747 */ 1365*2882Svi117747 int 1366*2882Svi117747 sip_parse_clen_header(_sip_header_t *sip_header, sip_parsed_header_t **header) 1367*2882Svi117747 { 1368*2882Svi117747 return (sip_parse_hdr_parser2(sip_header, header, SIP_INT_VAL)); 1369*2882Svi117747 } 1370*2882Svi117747 1371*2882Svi117747 /* 1372*2882Svi117747 * Generic parser for Contact, From, To, Route and Record-Route headers 1373*2882Svi117747 * 1374*2882Svi117747 * Contact = ("Contact" / "m" ) HCOLON 1375*2882Svi117747 * ( STAR / (contact-param *(COMMA contact-param))) 1376*2882Svi117747 * contact-param = (name-addr / addr-spec) *(SEMI contact-params) 1377*2882Svi117747 * name-addr = [ display-name ] LAQUOT addr-spec RAQUOT 1378*2882Svi117747 * addr-spec = SIP-URI / SIPS-URI / absoluteURI 1379*2882Svi117747 * display-name = *(token LWS)/ quoted-string 1380*2882Svi117747 * contact-params = c-p-q / c-p-expires 1381*2882Svi117747 * / contact-extension 1382*2882Svi117747 * 1383*2882Svi117747 * From = ( "From" / "f" ) HCOLON from-spec 1384*2882Svi117747 * from-spec = ( name-addr / addr-spec ) 1385*2882Svi117747 * *( SEMI from-param ) 1386*2882Svi117747 * from-param = tag-param / generic-param 1387*2882Svi117747 * tag-param = "tag" EQUAL token 1388*2882Svi117747 * 1389*2882Svi117747 * To = ( "To" / "t" ) HCOLON ( name-addr 1390*2882Svi117747 * / addr-spec ) *( SEMI to-param ) 1391*2882Svi117747 * to-param = tag-param / generic-param 1392*2882Svi117747 * 1393*2882Svi117747 * Route = "Route" HCOLON route-param *(COMMA route-param) 1394*2882Svi117747 * route-param = name-addr *( SEMI rr-param ) 1395*2882Svi117747 * 1396*2882Svi117747 * Record-Route = "Record-Route" HCOLON rec-route *(COMMA rec-route) 1397*2882Svi117747 * rec-route = name-addr *( SEMI rr-param ) 1398*2882Svi117747 * rr-param = generic-param 1399*2882Svi117747 * 1400*2882Svi117747 * We could have multiple values for these headers. For the ones that have 1401*2882Svi117747 * a display name we will have a LAQUOT/RAQUOT. If we encounter an error 1402*2882Svi117747 * when parsing a value, we mark the value as bad and start paring the 1403*2882Svi117747 * next value, if present. Before we start parsing the next value, we 1404*2882Svi117747 * check for any parameters, if present. 1405*2882Svi117747 */ 1406*2882Svi117747 int 1407*2882Svi117747 sip_parse_cftr_header(_sip_header_t *sip_header, sip_parsed_header_t **header) 1408*2882Svi117747 { 1409*2882Svi117747 sip_parsed_header_t *parsed_header; 1410*2882Svi117747 char *tmp_ptr; 1411*2882Svi117747 char *tmp_ptr_2; 1412*2882Svi117747 int ret; 1413*2882Svi117747 sip_hdr_value_t *value = NULL; 1414*2882Svi117747 sip_hdr_value_t *last_value = NULL; 1415*2882Svi117747 1416*2882Svi117747 if ((ret = sip_prim_parsers(sip_header, header)) != 0) 1417*2882Svi117747 return (ret); 1418*2882Svi117747 1419*2882Svi117747 if (*header != NULL) 1420*2882Svi117747 return (0); 1421*2882Svi117747 1422*2882Svi117747 parsed_header = calloc(1, sizeof (sip_parsed_header_t)); 1423*2882Svi117747 if (parsed_header == NULL) 1424*2882Svi117747 return (ENOMEM); 1425*2882Svi117747 parsed_header->sip_parsed_header_version = SIP_PARSED_HEADER_VERSION_1; 1426*2882Svi117747 parsed_header->sip_header = sip_header; 1427*2882Svi117747 while (sip_header->sip_hdr_current < sip_header->sip_hdr_end) { 1428*2882Svi117747 boolean_t quoted_name = B_FALSE; 1429*2882Svi117747 1430*2882Svi117747 value = calloc(1, sizeof (sip_hdr_value_t)); 1431*2882Svi117747 if (value == NULL) { 1432*2882Svi117747 sip_free_cftr_header(parsed_header); 1433*2882Svi117747 return (ENOMEM); 1434*2882Svi117747 } 1435*2882Svi117747 if (last_value != NULL) 1436*2882Svi117747 last_value->sip_next_value = value; 1437*2882Svi117747 else 1438*2882Svi117747 parsed_header->value = (sip_value_t *)value; 1439*2882Svi117747 if (*sip_header->sip_hdr_current == SIP_QUOTE) { 1440*2882Svi117747 sip_header->sip_hdr_current++; 1441*2882Svi117747 quoted_name = B_TRUE; 1442*2882Svi117747 } 1443*2882Svi117747 value->sip_value_version = SIP_VALUE_VERSION_1; 1444*2882Svi117747 value->sip_value_start = sip_header->sip_hdr_current; 1445*2882Svi117747 value->sip_value_header = parsed_header; 1446*2882Svi117747 /* 1447*2882Svi117747 * let's see if there is a display name 1448*2882Svi117747 */ 1449*2882Svi117747 if (*sip_header->sip_hdr_current != SIP_LAQUOT) { 1450*2882Svi117747 1451*2882Svi117747 tmp_ptr = sip_header->sip_hdr_current; 1452*2882Svi117747 /* 1453*2882Svi117747 * According to 20.10 '<' may not have a leading 1454*2882Svi117747 * space. 1455*2882Svi117747 */ 1456*2882Svi117747 if (quoted_name && 1457*2882Svi117747 sip_find_token(sip_header, SIP_QUOTE) != 0) { 1458*2882Svi117747 if (sip_goto_next_value(sip_header) != 0) { 1459*2882Svi117747 sip_free_cftr_header(parsed_header); 1460*2882Svi117747 return (EPROTO); 1461*2882Svi117747 } 1462*2882Svi117747 value->sip_value_state = SIP_VALUE_BAD; 1463*2882Svi117747 goto get_next_cftr_value; 1464*2882Svi117747 } else if (sip_find_separator(sip_header, SIP_SEMI, 1465*2882Svi117747 SIP_LAQUOT, SIP_COMMA) != 0) { 1466*2882Svi117747 /* 1467*2882Svi117747 * only a uri. 1468*2882Svi117747 */ 1469*2882Svi117747 value->cftr_uri.sip_str_ptr = tmp_ptr; 1470*2882Svi117747 value->cftr_uri.sip_str_len = 1471*2882Svi117747 sip_header->sip_hdr_current - tmp_ptr; 1472*2882Svi117747 /* 1473*2882Svi117747 * It's an error not to have a uri. 1474*2882Svi117747 */ 1475*2882Svi117747 if (value->cftr_uri.sip_str_len == 0) { 1476*2882Svi117747 if (sip_goto_next_value(sip_header) != 1477*2882Svi117747 0) { 1478*2882Svi117747 sip_free_cftr_header( 1479*2882Svi117747 parsed_header); 1480*2882Svi117747 return (EPROTO); 1481*2882Svi117747 } 1482*2882Svi117747 value->sip_value_state = SIP_VALUE_BAD; 1483*2882Svi117747 goto get_next_cftr_value; 1484*2882Svi117747 } 1485*2882Svi117747 continue; 1486*2882Svi117747 } 1487*2882Svi117747 1488*2882Svi117747 tmp_ptr_2 = sip_header->sip_hdr_current; 1489*2882Svi117747 if (*sip_header->sip_hdr_current == SIP_SP) { 1490*2882Svi117747 if (sip_skip_white_space(sip_header) != 0) { 1491*2882Svi117747 /* 1492*2882Svi117747 * only a uri. 1493*2882Svi117747 */ 1494*2882Svi117747 value->cftr_uri.sip_str_ptr = tmp_ptr; 1495*2882Svi117747 value->cftr_uri.sip_str_len = 1496*2882Svi117747 tmp_ptr_2 - tmp_ptr; 1497*2882Svi117747 /* 1498*2882Svi117747 * It's an error not to have a uri. 1499*2882Svi117747 */ 1500*2882Svi117747 if (value->cftr_uri.sip_str_len == 0) { 1501*2882Svi117747 if (sip_goto_next_value( 1502*2882Svi117747 sip_header) != 0) { 1503*2882Svi117747 sip_free_cftr_header( 1504*2882Svi117747 parsed_header); 1505*2882Svi117747 return (EPROTO); 1506*2882Svi117747 } 1507*2882Svi117747 value->sip_value_state = 1508*2882Svi117747 SIP_VALUE_BAD; 1509*2882Svi117747 goto get_next_cftr_value; 1510*2882Svi117747 } 1511*2882Svi117747 continue; 1512*2882Svi117747 } 1513*2882Svi117747 } 1514*2882Svi117747 1515*2882Svi117747 if (*sip_header->sip_hdr_current != SIP_LAQUOT) { 1516*2882Svi117747 /* 1517*2882Svi117747 * No display name here. 1518*2882Svi117747 */ 1519*2882Svi117747 value->cftr_uri.sip_str_ptr = tmp_ptr; 1520*2882Svi117747 value->cftr_uri.sip_str_len = tmp_ptr_2 - 1521*2882Svi117747 tmp_ptr; 1522*2882Svi117747 /* 1523*2882Svi117747 * It's an error not to have a uri. 1524*2882Svi117747 */ 1525*2882Svi117747 if (value->cftr_uri.sip_str_len == 0) { 1526*2882Svi117747 if (sip_goto_next_value(sip_header) != 1527*2882Svi117747 0) { 1528*2882Svi117747 sip_free_cftr_header( 1529*2882Svi117747 parsed_header); 1530*2882Svi117747 return (EPROTO); 1531*2882Svi117747 } 1532*2882Svi117747 value->sip_value_state = SIP_VALUE_BAD; 1533*2882Svi117747 goto get_next_cftr_value; 1534*2882Svi117747 } 1535*2882Svi117747 goto get_params; 1536*2882Svi117747 } 1537*2882Svi117747 1538*2882Svi117747 value->cftr_name = malloc(sizeof (sip_str_t)); 1539*2882Svi117747 if (value->cftr_name == NULL) { 1540*2882Svi117747 sip_free_cftr_header(parsed_header); 1541*2882Svi117747 return (ENOMEM); 1542*2882Svi117747 } 1543*2882Svi117747 value->cftr_name->sip_str_ptr = tmp_ptr; 1544*2882Svi117747 value->cftr_name->sip_str_len = tmp_ptr_2 - tmp_ptr; 1545*2882Svi117747 if (quoted_name) 1546*2882Svi117747 value->cftr_name->sip_str_len--; 1547*2882Svi117747 } 1548*2882Svi117747 1549*2882Svi117747 if (sip_find_token(sip_header, SIP_LAQUOT) != 0) { 1550*2882Svi117747 if (sip_goto_next_value(sip_header) != 0) { 1551*2882Svi117747 sip_free_cftr_header(parsed_header); 1552*2882Svi117747 return (EPROTO); 1553*2882Svi117747 } 1554*2882Svi117747 value->sip_value_state = SIP_VALUE_BAD; 1555*2882Svi117747 goto get_next_cftr_value; 1556*2882Svi117747 } 1557*2882Svi117747 1558*2882Svi117747 if (*sip_header->sip_hdr_current == SIP_SP) { 1559*2882Svi117747 if (sip_skip_white_space(sip_header) != 0) { 1560*2882Svi117747 if (sip_goto_next_value(sip_header) != 0) { 1561*2882Svi117747 sip_free_cftr_header(parsed_header); 1562*2882Svi117747 return (EPROTO); 1563*2882Svi117747 } 1564*2882Svi117747 value->sip_value_state = SIP_VALUE_BAD; 1565*2882Svi117747 goto get_next_cftr_value; 1566*2882Svi117747 } 1567*2882Svi117747 } 1568*2882Svi117747 1569*2882Svi117747 tmp_ptr = sip_header->sip_hdr_current; 1570*2882Svi117747 1571*2882Svi117747 if (sip_find_separator(sip_header, SIP_RAQUOT, (char)NULL, 1572*2882Svi117747 (char)NULL)) { 1573*2882Svi117747 if (sip_goto_next_value(sip_header) != 0) { 1574*2882Svi117747 sip_free_cftr_header(parsed_header); 1575*2882Svi117747 return (EPROTO); 1576*2882Svi117747 } 1577*2882Svi117747 value->sip_value_state = SIP_VALUE_BAD; 1578*2882Svi117747 goto get_next_cftr_value; 1579*2882Svi117747 } 1580*2882Svi117747 1581*2882Svi117747 value->cftr_uri.sip_str_ptr = tmp_ptr; 1582*2882Svi117747 value->cftr_uri.sip_str_len = 1583*2882Svi117747 sip_header->sip_hdr_current - tmp_ptr; 1584*2882Svi117747 1585*2882Svi117747 if (sip_find_token(sip_header, SIP_RAQUOT) != 0) { 1586*2882Svi117747 if (sip_goto_next_value(sip_header) != 0) { 1587*2882Svi117747 sip_free_cftr_header(parsed_header); 1588*2882Svi117747 return (EINVAL); 1589*2882Svi117747 } 1590*2882Svi117747 value->sip_value_state = SIP_VALUE_BAD; 1591*2882Svi117747 goto get_next_cftr_value; 1592*2882Svi117747 } 1593*2882Svi117747 1594*2882Svi117747 if (value->cftr_uri.sip_str_len <= strlen("<>")) { 1595*2882Svi117747 if (sip_goto_next_value(sip_header) != 0) { 1596*2882Svi117747 sip_free_cftr_header(parsed_header); 1597*2882Svi117747 return (EPROTO); 1598*2882Svi117747 } 1599*2882Svi117747 value->sip_value_state = SIP_VALUE_BAD; 1600*2882Svi117747 goto get_next_cftr_value; 1601*2882Svi117747 } 1602*2882Svi117747 1603*2882Svi117747 get_params: 1604*2882Svi117747 ret = sip_parse_params(sip_header, &value->sip_param_list); 1605*2882Svi117747 if (ret == EPROTO) { 1606*2882Svi117747 value->sip_value_state = SIP_VALUE_BAD; 1607*2882Svi117747 } else if (ret != 0) { 1608*2882Svi117747 sip_free_cftr_header(parsed_header); 1609*2882Svi117747 return (ret); 1610*2882Svi117747 } 1611*2882Svi117747 get_next_cftr_value: 1612*2882Svi117747 value->sip_value_end = sip_header->sip_hdr_current; 1613*2882Svi117747 1614*2882Svi117747 /* 1615*2882Svi117747 * Parse uri 1616*2882Svi117747 */ 1617*2882Svi117747 if (value->cftr_uri.sip_str_len > 0) { 1618*2882Svi117747 int error; 1619*2882Svi117747 1620*2882Svi117747 value->sip_value_parsed_uri = sip_parse_uri( 1621*2882Svi117747 &value->cftr_uri, &error); 1622*2882Svi117747 if (value->sip_value_parsed_uri == NULL) { 1623*2882Svi117747 sip_free_cftr_header(parsed_header); 1624*2882Svi117747 return (ENOMEM); 1625*2882Svi117747 } 1626*2882Svi117747 if (error != 0 || 1627*2882Svi117747 ((_sip_uri_t *)value->sip_value_parsed_uri)-> 1628*2882Svi117747 sip_uri_errflags != 0) { 1629*2882Svi117747 value->sip_value_state = SIP_VALUE_BAD; 1630*2882Svi117747 } 1631*2882Svi117747 } 1632*2882Svi117747 1633*2882Svi117747 (void) sip_find_token(sip_header, SIP_COMMA); 1634*2882Svi117747 last_value = value; 1635*2882Svi117747 (void) sip_skip_white_space(sip_header); 1636*2882Svi117747 } 1637*2882Svi117747 1638*2882Svi117747 sip_header->sip_hdr_parsed = parsed_header; 1639*2882Svi117747 1640*2882Svi117747 *header = parsed_header; 1641*2882Svi117747 return (0); 1642*2882Svi117747 } 1643*2882Svi117747 1644*2882Svi117747 /* 1645*2882Svi117747 * PAssertedID = "P-Asserted-Identity" HCOLON PAssertedID-value 1646*2882Svi117747 * *(COMMA PAssertedID-value) 1647*2882Svi117747 * PAssertedID-value = name-addr / addr-spec 1648*2882Svi117747 */ 1649*2882Svi117747 int 1650*2882Svi117747 sip_parse_passertedid(_sip_header_t *sip_header, sip_parsed_header_t **header) 1651*2882Svi117747 { 1652*2882Svi117747 return (sip_parse_hdr_parser3(sip_header, header, SIP_STRS_VAL, 1653*2882Svi117747 B_TRUE)); 1654*2882Svi117747 } 1655*2882Svi117747 1656*2882Svi117747 /* 1657*2882Svi117747 * PPreferredID = "P-Preferred-Identity" HCOLON PPreferredID-value 1658*2882Svi117747 * *(COMMA PAssertedID-value) 1659*2882Svi117747 * PPreferredID-value = name-addr / addr-spec 1660*2882Svi117747 */ 1661*2882Svi117747 int 1662*2882Svi117747 sip_parse_ppreferredid(_sip_header_t *sip_header, sip_parsed_header_t **header) 1663*2882Svi117747 { 1664*2882Svi117747 return (sip_parse_hdr_parser3(sip_header, header, SIP_STRS_VAL, 1665*2882Svi117747 B_TRUE)); 1666*2882Svi117747 } 1667*2882Svi117747 1668*2882Svi117747 1669*2882Svi117747 /* 1670*2882Svi117747 * We don't do anything for a header we don't understand 1671*2882Svi117747 */ 1672*2882Svi117747 /* ARGSUSED */ 1673*2882Svi117747 int 1674*2882Svi117747 sip_parse_unknown_header(_sip_header_t *sip_header, 1675*2882Svi117747 sip_parsed_header_t **header) 1676*2882Svi117747 { 1677*2882Svi117747 return (EINVAL); 1678*2882Svi117747 } 1679