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