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