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