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