1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 #include "sip_parse_uri.h" 30 #include "sip_msg.h" 31 #include "sip_miscdefs.h" 32 #include "sip_parse_generic.h" 33 34 sip_methods_t sip_methods[MAX_SIP_METHODS] = { 35 {"UNKNOWN", 7}, 36 {"INVITE", 6}, 37 {"ACK", 3}, 38 {"OPTIONS", 7}, 39 {"BYE", 3}, 40 {"CANCEL", 6}, 41 {"REGISTER", 8}, 42 {"REFER", 5}, 43 {"INFO", 4}, 44 {"SUBSCRIBE", 9}, 45 {"NOTIFY", 6}, 46 {"PRACK", 5} 47 }; 48 49 /* 50 * Built-In Header function table 51 */ 52 sip_header_function_t sip_header_function_table[] = { 53 {"Unknown", NULL, sip_parse_unknown_header, NULL, NULL, NULL}, 54 {"CONTACT", "m", sip_parse_cftr_header, NULL, NULL, 55 sip_free_cftr_header}, 56 {"FROM", "F", sip_parse_cftr_header, NULL, NULL, sip_free_cftr_header}, 57 {"TO", "T", sip_parse_cftr_header, NULL, NULL, sip_free_cftr_header}, 58 {"CONTENT-LENGTH", "l", sip_parse_clen_header, NULL, NULL, 59 sip_free_phdr}, 60 {"CONTENT-TYPE", "c", sip_parse_ctype_header, NULL, NULL, 61 sip_free_phdr}, 62 {"CALL-ID", "i", sip_parse_cid_header, NULL, NULL, sip_free_phdr}, 63 {"CSEQ", NULL, sip_parse_cseq_header, NULL, NULL, sip_free_phdr}, 64 {"VIA", "v", sip_parse_via_header, NULL, NULL, sip_free_phdr}, 65 {"Max-Forwards", NULL, sip_parse_maxf_header, NULL, NULL, 66 sip_free_phdr}, 67 {"RECORD-ROUTE", NULL, sip_parse_cftr_header, NULL, NULL, 68 sip_free_cftr_header}, 69 {"ROUTE", NULL, sip_parse_cftr_header, NULL, NULL, 70 sip_free_cftr_header}, 71 {"ACCEPT", NULL, sip_parse_acpt_header, NULL, NULL, sip_free_phdr}, 72 {"ACCEPT-ENCODING", NULL, sip_parse_acpt_encode_header, NULL, NULL, 73 sip_free_phdr}, 74 {"ACCEPT-LANGUAGE", NULL, sip_parse_acpt_lang_header, NULL, NULL, 75 sip_free_phdr}, 76 {"ALERT-INFO", NULL, sip_parse_alert_header, NULL, NULL, sip_free_phdr}, 77 {"ALLOW", NULL, sip_parse_allow_header, NULL, NULL, sip_free_phdr}, 78 {"CALL-INFO", NULL, sip_parse_callinfo_header, NULL, NULL, 79 sip_free_phdr}, 80 {"CONTENT-DISPOSITION", NULL, sip_parse_contentdis_header, NULL, NULL, 81 sip_free_phdr}, 82 {"CONTENT-ENCODING", "e", sip_parse_contentencode_header, NULL, NULL, 83 sip_free_phdr}, 84 {"CONTENT-LANGUAGE", NULL, sip_parse_contentlang_header, NULL, NULL, 85 sip_free_phdr}, 86 {"DATE", NULL, sip_parse_date_header, NULL, NULL, sip_free_phdr}, 87 {"ERROR-INFO", NULL, sip_parse_errorinfo_header, NULL, NULL, 88 sip_free_phdr}, 89 {"EXPIRES", NULL, sip_parse_expire_header, NULL, NULL, sip_free_phdr}, 90 {"IN-REPLY-TO", NULL, sip_parse_inreplyto_header, NULL, NULL, 91 sip_free_phdr}, 92 {"MIN-EXPIRES", NULL, sip_parse_minexpire_header, NULL, NULL, 93 sip_free_phdr}, 94 {"MIME-VERSION", NULL, sip_parse_mimeversion_header, NULL, NULL, 95 sip_free_phdr}, 96 {"ORGANIZATION", NULL, sip_parse_org_header, NULL, NULL, sip_free_phdr}, 97 {"PRIORITY", NULL, sip_parse_priority_header, NULL, NULL, 98 sip_free_phdr}, 99 {"REQUIRE", NULL, sip_parse_require_header, NULL, NULL, sip_free_phdr}, 100 {"REPLY-TO", NULL, sip_parse_replyto_header, NULL, NULL, sip_free_phdr}, 101 {"RETRY-AFTER", NULL, sip_parse_retryaft_header, NULL, NULL, 102 sip_free_phdr}, 103 {"SERVER", NULL, sip_parse_server_header, NULL, NULL, sip_free_phdr}, 104 {"SUBJECT", "s", sip_parse_subject_header, NULL, NULL, sip_free_phdr}, 105 {"TIMESTAMP", NULL, sip_parse_timestamp_header, NULL, NULL, 106 sip_free_phdr}, 107 {"UNSUPPORTED", NULL, sip_parse_usupport_header, NULL, NULL, 108 sip_free_phdr}, 109 {"SUPPORTED", "k", sip_parse_support_header, NULL, NULL, sip_free_phdr}, 110 {"USER-AGENT", NULL, sip_parse_useragt_header, NULL, NULL, 111 sip_free_phdr}, 112 {"WARNING", NULL, sip_parse_warn_header, NULL, NULL, sip_free_phdr}, 113 {"ALLOW-EVENTS", "u", sip_parse_allow_events_header, NULL, NULL, 114 sip_free_phdr}, 115 {"EVENT", "o", sip_parse_event_header, NULL, NULL, sip_free_phdr}, 116 {"SUBSCRIPTION-STATE", NULL, sip_parse_substate_header, NULL, NULL, 117 sip_free_phdr}, 118 {"AUTHORIZATION", NULL, sip_parse_author_header, NULL, NULL, 119 sip_free_phdr}, 120 {"AUTHENTICATION-INFO", NULL, sip_parse_ainfo_header, NULL, NULL, 121 sip_free_phdr}, 122 {"PROXY-AUTHORIZATION", NULL, sip_parse_pauthor_header, NULL, NULL, 123 sip_free_phdr}, 124 {"PROXY-AUTHENTICATE", NULL, sip_parse_pauthen_header, NULL, NULL, 125 sip_free_phdr}, 126 {"PROXY-REQUIRE", NULL, sip_parse_preq_header, NULL, NULL, 127 sip_free_phdr}, 128 {"WWW-AUTHENTICATE", NULL, sip_parse_wauthen_header, NULL, NULL, 129 sip_free_phdr}, 130 {"RSEQ", NULL, sip_parse_rseq, NULL, NULL, sip_free_phdr}, 131 {"RACK", NULL, sip_parse_rack, NULL, NULL, sip_free_phdr}, 132 {"P-ASSERTED-IDENTITY", NULL, sip_parse_passertedid, NULL, NULL, 133 sip_free_phdr}, 134 {"P-PREFERRED-IDENTITY", NULL, sip_parse_ppreferredid, NULL, NULL, 135 sip_free_phdr}, 136 {"PRIVACY", NULL, sip_parse_privacy_header, NULL, NULL, sip_free_phdr}, 137 {NULL, NULL, NULL, NULL, NULL, NULL}, 138 }; 139 140 #define MAX_SIP_HEADERS \ 141 sizeof (sip_header_function_table) / sizeof (sip_header_function_t) 142 143 /* 144 * External/application provided function table 145 */ 146 sip_header_function_t *sip_header_function_table_external = NULL; 147 148 /* 149 * Free parameter list 150 */ 151 static void 152 sip_free_params(sip_param_t *param_list) 153 { 154 sip_param_t *param, *next_param; 155 156 param = param_list; 157 158 while (param != NULL) { 159 next_param = param->param_next; 160 free(param); 161 param = next_param; 162 } 163 } 164 165 /* 166 * Common header free routine 167 */ 168 void 169 sip_free_phdr(sip_parsed_header_t *header) 170 { 171 sip_hdr_value_t *value; 172 sip_hdr_value_t *next_value; 173 174 if (header == NULL) 175 return; 176 value = (sip_hdr_value_t *)header->value; 177 while (value != NULL) { 178 sip_free_params(value->sip_param_list); 179 next_value = value->sip_next_value; 180 free(value); 181 value = next_value; 182 } 183 free(header); 184 } 185 186 /* 187 * Free Contact/From/To header 188 */ 189 void 190 sip_free_cftr_header(sip_parsed_header_t *header) 191 { 192 sip_hdr_value_t *value; 193 sip_hdr_value_t *next_value; 194 195 if (header == NULL) 196 return; 197 value = (sip_hdr_value_t *)header->value; 198 while (value != NULL) { 199 next_value = value->sip_next_value; 200 sip_free_params(value->sip_param_list); 201 if (value->cftr_name != NULL) 202 free(value->cftr_name); 203 if (value->sip_value_parsed_uri != NULL) { 204 sip_free_parsed_uri(value->sip_value_parsed_uri); 205 value->sip_value_parsed_uri = NULL; 206 } 207 free(value); 208 value = next_value; 209 } 210 free(header); 211 } 212 213 /* 214 * Return new header 215 */ 216 _sip_header_t * 217 sip_new_header(int header_size) 218 { 219 _sip_header_t *new_header; 220 221 new_header = calloc(1, sizeof (_sip_header_t)); 222 if (new_header == NULL) 223 return (NULL); 224 225 /* 226 * We are using snprintf which adds a null character 227 * so allocate an extra byte which is not part of 228 * the message header 229 */ 230 new_header->sip_hdr_start = calloc(1, header_size + 1); 231 if (new_header->sip_hdr_start == NULL) { 232 free(new_header); 233 return (NULL); 234 } 235 new_header->sip_hdr_end = new_header->sip_hdr_start + header_size; 236 new_header->sip_hdr_current = new_header->sip_hdr_start; 237 new_header->sip_hdr_allocated = B_TRUE; 238 return (new_header); 239 } 240 241 /* 242 * Free the given header 243 */ 244 void 245 sip_free_header(_sip_header_t *sip_header) 246 { 247 if (sip_header->sip_hdr_allocated) { 248 assert(sip_header->sip_hdr_start != NULL); 249 free(sip_header->sip_hdr_start); 250 } 251 if (sip_header->sip_hdr_parsed != NULL) { 252 assert(sip_header->sip_header_functions != NULL); 253 if (sip_header->sip_header_functions->header_free != NULL) { 254 sip_header->sip_header_functions->header_free( 255 sip_header->sip_hdr_parsed); 256 } 257 } 258 free(sip_header); 259 } 260 261 /* 262 * Return a copy of the header passed in. 263 */ 264 _sip_header_t * 265 sip_dup_header(_sip_header_t *from) 266 { 267 size_t hdr_size; 268 _sip_header_t *to; 269 270 hdr_size = from->sip_hdr_end - from->sip_hdr_start; 271 to = sip_new_header(hdr_size); 272 if (to == NULL) 273 return (NULL); 274 if (from->sip_header_state == SIP_HEADER_DELETED_VAL) { 275 to->sip_hdr_end = to->sip_hdr_start + 276 sip_copy_values(to->sip_hdr_start, from); 277 } else { 278 (void) memcpy(to->sip_hdr_start, from->sip_hdr_start, hdr_size); 279 to->sip_hdr_end = to->sip_hdr_start + hdr_size; 280 } 281 to->sip_header_functions = from->sip_header_functions; 282 return (to); 283 } 284 285 /* 286 * Copy header with extra_param, if any, to sip_msg 287 */ 288 int 289 _sip_copy_header(_sip_msg_t *sip_msg, _sip_header_t *header, char *extra_param, 290 boolean_t skip_crlf) 291 { 292 _sip_header_t *new_header; 293 int hdrlen; 294 int extra_len = 0; 295 int ncrlf = 0; 296 char *p; 297 298 #ifdef __solaris__ 299 assert(mutex_held(&sip_msg->sip_msg_mutex)); 300 #endif 301 if (extra_param != NULL) { 302 extra_len = SIP_SPACE_LEN + sizeof (char) + SIP_SPACE_LEN + 303 strlen(extra_param); 304 } 305 /* 306 * Just take one if there are more, i.e. if this is the last header 307 * before the content. 308 */ 309 if (skip_crlf) { 310 if (header->sip_hdr_end - strlen(SIP_CRLF) <= 311 header->sip_hdr_start) { 312 goto proceed; 313 } 314 p = header->sip_hdr_end - strlen(SIP_CRLF); 315 while (strncmp(SIP_CRLF, p, strlen(SIP_CRLF)) == 0) { 316 ncrlf++; 317 if (p - strlen(SIP_CRLF) < header->sip_hdr_start) 318 break; 319 p -= strlen(SIP_CRLF); 320 } 321 /* 322 * Take one CRLF. 323 */ 324 ncrlf = (ncrlf - 1) * strlen(SIP_CRLF); 325 } 326 proceed: 327 hdrlen = header->sip_hdr_end - header->sip_hdr_start - ncrlf; 328 new_header = sip_new_header(hdrlen + extra_len); 329 if (new_header == NULL) 330 return (ENOMEM); 331 if (header->sip_header_state == SIP_HEADER_DELETED_VAL) { 332 int len; 333 334 len = sip_copy_values(new_header->sip_hdr_start, header); 335 new_header->sip_hdr_end = new_header->sip_hdr_start + len; 336 hdrlen = hdrlen - len + extra_len; 337 } else { 338 (void) memcpy(new_header->sip_hdr_start, header->sip_hdr_start, 339 hdrlen); 340 new_header->sip_hdr_end = new_header->sip_hdr_start + hdrlen; 341 hdrlen = extra_len; 342 } 343 if (extra_param != NULL) { 344 /* 345 * Find CR 346 */ 347 if (sip_find_cr(new_header) != 0) { 348 sip_free_header(new_header); 349 return (EINVAL); 350 } 351 hdrlen += new_header->sip_hdr_end - new_header->sip_hdr_current; 352 (void) snprintf(new_header->sip_hdr_current, hdrlen + 1, 353 " %c %s%s", SIP_SEMI, extra_param, SIP_CRLF); 354 } 355 356 new_header->sip_hdr_end += extra_len; 357 new_header->sip_header_functions = header->sip_header_functions; 358 _sip_add_header(sip_msg, new_header, B_TRUE, B_FALSE, NULL); 359 return (0); 360 } 361 362 /* 363 * Copy all "header_name" headers from _old_msg to _new_msg 364 */ 365 int 366 _sip_find_and_copy_all_header(_sip_msg_t *_old_msg, _sip_msg_t *_new_msg, 367 char *header_name) 368 { 369 _sip_header_t *header; 370 int ret = 0; 371 372 if (_old_msg == NULL || _new_msg == NULL) 373 return (EINVAL); 374 #ifdef __solaris__ 375 assert(mutex_held(&_old_msg->sip_msg_mutex)); 376 #endif 377 if (_old_msg != _new_msg) 378 (void) pthread_mutex_lock(&_new_msg->sip_msg_mutex); 379 header = sip_search_for_header(_old_msg, header_name, NULL); 380 while (header != NULL) { 381 ret = _sip_copy_header(_new_msg, header, NULL, B_TRUE); 382 if (ret != 0) 383 break; 384 header = sip_search_for_header(_old_msg, header_name, header); 385 } 386 if (_old_msg != _new_msg) 387 (void) pthread_mutex_unlock(&_new_msg->sip_msg_mutex); 388 return (ret); 389 } 390 391 /* 392 * Copy header_name from _old_msg to _new_msg with extra_parm. 393 */ 394 int 395 _sip_find_and_copy_header(sip_msg_t _old_msg, sip_msg_t _new_msg, 396 char *header_name, char *extra_param, boolean_t lock_newmsg) 397 { 398 _sip_header_t *header; 399 int ret; 400 401 if (_old_msg == NULL || _new_msg == NULL) 402 return (EINVAL); 403 #ifdef __solaris__ 404 assert(mutex_held(&_old_msg->sip_msg_mutex)); 405 #endif 406 header = sip_search_for_header(_old_msg, header_name, NULL); 407 if (header == NULL) 408 return (EINVAL); 409 if (lock_newmsg) 410 (void) pthread_mutex_lock(&_new_msg->sip_msg_mutex); 411 ret = _sip_copy_header(_new_msg, header, extra_param, B_TRUE); 412 if (lock_newmsg) 413 (void) pthread_mutex_unlock(&_new_msg->sip_msg_mutex); 414 return (ret); 415 } 416 417 /* 418 * Copy all headers from old_msg to new_msg 419 */ 420 int 421 sip_copy_all_headers(sip_msg_t old_msg, sip_msg_t new_msg) 422 { 423 _sip_header_t *header; 424 _sip_msg_t *_old_msg; 425 _sip_msg_t *_new_msg; 426 int ret = 0; 427 428 if (old_msg == NULL || new_msg == NULL) 429 return (EINVAL); 430 _old_msg = (_sip_msg_t *)old_msg; 431 _new_msg = (_sip_msg_t *)new_msg; 432 433 (void) pthread_mutex_lock(&_old_msg->sip_msg_mutex); 434 (void) pthread_mutex_lock(&_new_msg->sip_msg_mutex); 435 header = sip_search_for_header(_old_msg, NULL, NULL); 436 while (header != NULL) { 437 ret = _sip_copy_header(_new_msg, header, NULL, B_FALSE); 438 if (ret != 0) 439 goto done; 440 header = sip_search_for_header(_old_msg, NULL, header); 441 } 442 done: 443 (void) pthread_mutex_unlock(&_new_msg->sip_msg_mutex); 444 (void) pthread_mutex_unlock(&_old_msg->sip_msg_mutex); 445 return (ret); 446 } 447 448 /* 449 * Copy start line from msg to sip_msg 450 */ 451 int 452 sip_copy_start_line(sip_msg_t msg, sip_msg_t sip_msg) 453 { 454 int len; 455 _sip_header_t *new_header; 456 _sip_msg_t *_old_msg; 457 _sip_msg_t *_sip_msg; 458 459 if (msg == NULL || sip_msg == NULL) 460 return (EINVAL); 461 _old_msg = (_sip_msg_t *)msg; 462 _sip_msg = (_sip_msg_t *)sip_msg; 463 464 (void) pthread_mutex_lock(&_old_msg->sip_msg_mutex); 465 if (_old_msg->sip_msg_start_line == NULL) { 466 (void) pthread_mutex_unlock(&_old_msg->sip_msg_mutex); 467 return (EINVAL); 468 } 469 len = _old_msg->sip_msg_start_line->sip_hdr_end - 470 _old_msg->sip_msg_start_line->sip_hdr_start; 471 new_header = sip_new_header(len); 472 if (new_header == NULL) { 473 (void) pthread_mutex_unlock(&_old_msg->sip_msg_mutex); 474 return (ENOMEM); 475 } 476 new_header->sip_hdr_sipmsg = _sip_msg; 477 (void) pthread_mutex_lock(&sip_msg->sip_msg_mutex); 478 _sip_msg->sip_msg_start_line = new_header; 479 _sip_msg->sip_msg_len = len; 480 (void) strncpy(_sip_msg->sip_msg_start_line->sip_hdr_start, 481 _old_msg->sip_msg_start_line->sip_hdr_start, len); 482 (void) sip_parse_first_line(_sip_msg->sip_msg_start_line, 483 &_sip_msg->sip_msg_req_res); 484 (void) pthread_mutex_unlock(&_old_msg->sip_msg_mutex); 485 (void) pthread_mutex_unlock(&sip_msg->sip_msg_mutex); 486 return (0); 487 } 488 489 /* 490 * Delete start line from sip_msg 491 */ 492 int 493 sip_delete_start_line_locked(_sip_msg_t *_sip_msg) 494 { 495 _sip_header_t *header; 496 _sip_header_t *next_header; 497 498 if (_sip_msg->sip_msg_start_line == NULL) 499 return (EINVAL); 500 501 header = _sip_msg->sip_msg_start_line; 502 while (header != NULL) { 503 next_header = header->sip_hdr_next; 504 _sip_msg->sip_msg_len -= (header->sip_hdr_end - 505 header->sip_hdr_start); 506 sip_free_header(header); 507 header = next_header; 508 } 509 _sip_msg->sip_msg_start_line = NULL; 510 511 /* 512 * Also delete the sip_msg_req_res info since we don't have a start 513 * line. 514 */ 515 while (_sip_msg->sip_msg_req_res != NULL) { 516 sip_message_type_t *sip_msg_type_ptr; 517 518 sip_msg_type_ptr = _sip_msg->sip_msg_req_res->sip_next; 519 if (_sip_msg->sip_msg_req_res->is_request) { 520 sip_request_t *reqline; 521 522 reqline = &_sip_msg->sip_msg_req_res->U.sip_request; 523 if (reqline->sip_parse_uri != NULL) { 524 sip_free_parsed_uri(reqline->sip_parse_uri); 525 reqline->sip_parse_uri = NULL; 526 } 527 } 528 free(_sip_msg->sip_msg_req_res); 529 _sip_msg->sip_msg_req_res = sip_msg_type_ptr; 530 } 531 return (0); 532 } 533 534 535 /* 536 * Delete start line from sip_msg 537 */ 538 int 539 sip_delete_start_line(sip_msg_t sip_msg) 540 { 541 _sip_msg_t *_sip_msg; 542 int ret; 543 544 if (sip_msg == NULL) 545 return (EINVAL); 546 547 _sip_msg = (_sip_msg_t *)sip_msg; 548 (void) pthread_mutex_lock(&_sip_msg->sip_msg_mutex); 549 ret = sip_delete_start_line_locked(_sip_msg); 550 (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex); 551 552 return (ret); 553 } 554 555 /* 556 * Delete all headers from _sip_msg 557 */ 558 void 559 sip_delete_all_headers(_sip_msg_t *_sip_msg) 560 { 561 _sip_header_t *header; 562 563 #ifdef __solaris__ 564 assert(mutex_held(&_sip_msg->sip_msg_mutex)); 565 #endif 566 567 header = _sip_msg->sip_msg_headers_start; 568 while (header != NULL) { 569 _sip_header_t *next_header; 570 next_header = header->sip_hdr_next; 571 sip_free_header(header); 572 header = next_header; 573 } 574 _sip_msg->sip_msg_headers_start = NULL; 575 _sip_msg->sip_msg_headers_end = NULL; 576 } 577 578 /* 579 * Delete and free the named header. If header_name is null 580 * free all headers. 581 */ 582 void 583 sip_delete_headers(sip_msg_t sip_msg, char *header_name) 584 { 585 _sip_header_t *header; 586 _sip_msg_t *_sip_msg; 587 588 _sip_msg = (_sip_msg_t *)sip_msg; 589 #ifdef __solaris__ 590 assert(mutex_held(&_sip_msg->sip_msg_mutex)); 591 #endif 592 header = sip_search_for_header(_sip_msg, header_name, NULL); 593 if (header == NULL) 594 return; 595 while (header != NULL) { 596 if (_sip_msg->sip_msg_headers_start == header) { 597 _sip_msg->sip_msg_headers_start = header->sip_hdr_next; 598 } else { 599 header->sip_hdr_prev->sip_hdr_next = 600 header->sip_hdr_next; 601 } 602 if (_sip_msg->sip_msg_headers_end == header) { 603 _sip_msg->sip_msg_headers_end = header->sip_hdr_prev; 604 } else { 605 header->sip_hdr_next->sip_hdr_prev = 606 header->sip_hdr_prev; 607 } 608 sip_free_header(header); 609 if (header_name != NULL) 610 return; 611 else 612 header = sip_search_for_header(_sip_msg, NULL, NULL); 613 } 614 } 615 616 /* 617 * Add a header to sip_msg. If header_name is provided then the new header 618 * is added before that header, if first is set, or after. If append is 619 * set, then the header is added to the end of the header list. 620 */ 621 void 622 _sip_add_header(_sip_msg_t *sip_msg, _sip_header_t *new_header, 623 boolean_t append, boolean_t first, char *header_name) 624 { 625 _sip_header_t *header = NULL; 626 627 if (sip_msg == NULL || new_header == NULL) 628 return; 629 #ifdef __solaris__ 630 assert(mutex_held(&sip_msg->sip_msg_mutex)); 631 #endif 632 new_header->sip_hdr_sipmsg = sip_msg; 633 if (header_name != NULL) { 634 _sip_header_t *header_tmp; 635 636 header = sip_search_for_header(sip_msg, header_name, NULL); 637 header_tmp = header; 638 if (!first) { 639 while (header != NULL) { 640 header_tmp = header; 641 header = sip_search_for_header(sip_msg, 642 header_name, header); 643 } 644 } 645 header = header_tmp; 646 if (header == NULL) 647 append = B_TRUE; 648 } 649 650 if (header != NULL) { 651 if (append) { 652 new_header->sip_hdr_prev = header; 653 if (sip_msg->sip_msg_headers_end == header) { 654 sip_msg->sip_msg_headers_end = new_header; 655 new_header->sip_hdr_next = NULL; 656 } else { 657 header->sip_hdr_next->sip_hdr_prev = new_header; 658 new_header->sip_hdr_next = header->sip_hdr_next; 659 } 660 header->sip_hdr_next = new_header; 661 } else { 662 new_header->sip_hdr_next = header; 663 if (sip_msg->sip_msg_headers_start == header) { 664 sip_msg->sip_msg_headers_start = new_header; 665 new_header->sip_hdr_prev = NULL; 666 } else { 667 header->sip_hdr_prev->sip_hdr_next = new_header; 668 new_header->sip_hdr_prev = header->sip_hdr_prev; 669 } 670 header->sip_hdr_prev = new_header; 671 } 672 } else { 673 if (append) { 674 if (sip_msg->sip_msg_headers_end != NULL) { 675 sip_msg->sip_msg_headers_end->sip_hdr_next = 676 new_header; 677 } else { 678 sip_msg->sip_msg_headers_start = new_header; 679 } 680 new_header->sip_hdr_prev = 681 sip_msg->sip_msg_headers_end; 682 new_header->sip_hdr_next = NULL; 683 sip_msg->sip_msg_headers_end = new_header; 684 } else { 685 if (sip_msg->sip_msg_headers_start != NULL) { 686 sip_msg->sip_msg_headers_start->sip_hdr_prev = 687 new_header; 688 } else { 689 sip_msg->sip_msg_headers_end = new_header; 690 } 691 new_header->sip_hdr_next = 692 sip_msg->sip_msg_headers_start; 693 new_header->sip_hdr_prev = NULL; 694 sip_msg->sip_msg_headers_start = new_header; 695 } 696 } 697 sip_msg->sip_msg_len += new_header->sip_hdr_end - 698 new_header->sip_hdr_start; 699 } 700 701 /* 702 * Scan through the function table and return the entry for the given header 703 * type. 704 */ 705 sip_header_function_t * 706 _sip_get_header_functions(sip_header_function_t *sip_header_function_table, 707 _sip_header_t *sip_header, char *header_name) 708 { 709 int len; 710 int i = 0; 711 712 if (sip_header == NULL && header_name == NULL) 713 return (NULL); 714 715 /* 716 * If header_name is NULL we first have to locate the name 717 */ 718 if (header_name == NULL) { 719 if (sip_skip_white_space(sip_header) != 0) { 720 return (NULL); 721 } 722 header_name = sip_header->sip_hdr_current; 723 if (sip_find_separator(sip_header, SIP_HCOLON, (char)NULL, 724 (char)NULL) != 0) { 725 return (NULL); 726 } 727 len = sip_header->sip_hdr_current - header_name; 728 } else { 729 len = strlen(header_name); 730 } 731 732 if (len > 0) { 733 while (sip_header_function_table[i].header_name != NULL || 734 sip_header_function_table[i].header_short_name != NULL) { 735 if (sip_header_function_table[i].header_name != NULL && 736 len == 737 strlen(sip_header_function_table[i].header_name)) { 738 if (strncasecmp(header_name, 739 sip_header_function_table[i]. 740 header_name, len) == 0) { 741 break; 742 } 743 } else if (sip_header_function_table[i]. 744 header_short_name != NULL && len == 745 strlen(sip_header_function_table[i]. 746 header_short_name)) { 747 if (strncasecmp(header_name, 748 sip_header_function_table[i]. 749 header_short_name, len) == 0) { 750 break; 751 } 752 } 753 i++; 754 } 755 } 756 757 if (sip_header != NULL) 758 sip_header->sip_hdr_current = sip_header->sip_hdr_start; 759 if (sip_header_function_table[i].header_name == NULL) 760 return (NULL); 761 return (&sip_header_function_table[i]); 762 } 763 764 /* 765 * Return the entry from the function table for the given header 766 */ 767 sip_header_function_t * 768 sip_get_header_functions(_sip_header_t *sip_header, char *header_name) 769 { 770 sip_header_function_t *func; 771 sip_header_function_t *header_f_table = NULL; 772 773 if (sip_header_function_table_external != NULL) { 774 header_f_table = _sip_get_header_functions( 775 sip_header_function_table_external, 776 sip_header, header_name); 777 if (header_f_table != NULL) 778 return (header_f_table); 779 } 780 func = _sip_get_header_functions(sip_header_function_table, sip_header, 781 header_name); 782 return (func); 783 } 784 785 /* 786 * Search for the header name passed in. 787 */ 788 _sip_header_t * 789 sip_search_for_header(_sip_msg_t *sip_msg, char *header_name, 790 _sip_header_t *old_header) 791 { 792 int len = 0; 793 int full_len = 0; 794 int compact_len = 0; 795 _sip_header_t *header = NULL; 796 char *compact_name = NULL; 797 char *full_name = NULL; 798 sip_header_function_t *header_f_table = NULL; 799 800 if (sip_msg == NULL) 801 return (NULL); 802 #ifdef __solaris__ 803 assert(mutex_held(&sip_msg->sip_msg_mutex)); 804 #endif 805 806 if (header_name != NULL) { 807 header_f_table = sip_get_header_functions(NULL, header_name); 808 if (header_f_table != NULL) { 809 full_name = header_f_table->header_name; 810 compact_name = header_f_table->header_short_name; 811 if (full_name != NULL) 812 full_len = strlen(full_name); 813 if (compact_name != NULL) 814 compact_len = strlen(compact_name); 815 } else { 816 header_f_table = &sip_header_function_table[0]; 817 full_name = header_name; 818 full_len = strlen(full_name); 819 } 820 } 821 822 if (old_header != NULL) 823 header = old_header->sip_hdr_next; 824 else 825 header = sip_msg->sip_msg_headers_start; 826 827 while (header != NULL) { 828 829 if (header->sip_header_state == SIP_HEADER_DELETED) { 830 header = header->sip_hdr_next; 831 continue; 832 } 833 834 if (compact_len == 0 && full_len == 0) 835 break; 836 837 header->sip_hdr_current = header->sip_hdr_start; 838 839 if (sip_skip_white_space(header)) { 840 header = header->sip_hdr_next; 841 continue; 842 } 843 844 len = header->sip_hdr_end - header->sip_hdr_current; 845 846 if (full_name != NULL && (full_len <= len) && 847 strncasecmp(header->sip_hdr_current, full_name, 848 full_len) == 0) { 849 header->sip_hdr_current += full_len; 850 if (sip_skip_white_space(header)) { 851 header = header->sip_hdr_next; 852 continue; 853 } 854 855 if (*header->sip_hdr_current == SIP_HCOLON) { 856 header_name = full_name; 857 break; 858 } 859 } 860 861 if (compact_name != NULL && (compact_len <= len) && 862 strncasecmp(header->sip_hdr_current, compact_name, 863 compact_len) == 0) { 864 header->sip_hdr_current += compact_len; 865 if (sip_skip_white_space(header)) { 866 header = header->sip_hdr_next; 867 continue; 868 } 869 if (*header->sip_hdr_current == SIP_HCOLON) { 870 header_name = compact_name; 871 break; 872 } 873 } 874 header = header->sip_hdr_next; 875 } 876 877 if (header != NULL) { 878 header->sip_hdr_current = header->sip_hdr_start; 879 if (header_f_table == NULL) { 880 header_f_table = 881 sip_get_header_functions(header, header_name); 882 if (header_f_table == NULL) 883 header_f_table = &sip_header_function_table[0]; 884 } 885 886 header->sip_header_functions = header_f_table; 887 } 888 return (header); 889 } 890 891 /* 892 * Return the start line as a string. Caller frees string 893 */ 894 char * 895 _sip_startline_to_str(_sip_msg_t *sip_msg, int *error) 896 { 897 char *slstr; 898 int len; 899 900 if (error != NULL) 901 *error = 0; 902 903 if (sip_msg == NULL || sip_msg->sip_msg_start_line == NULL) { 904 if (error != NULL) 905 *error = EINVAL; 906 return (NULL); 907 } 908 (void) pthread_mutex_lock(&sip_msg->sip_msg_mutex); 909 len = sip_msg->sip_msg_start_line->sip_hdr_end - 910 sip_msg->sip_msg_start_line->sip_hdr_start - 2; 911 if ((slstr = malloc(len + 1)) == NULL) { 912 (void) pthread_mutex_unlock(&sip_msg->sip_msg_mutex); 913 if (error != NULL) 914 *error = ENOMEM; 915 return (NULL); 916 } 917 (void) strncpy(slstr, sip_msg->sip_msg_start_line->sip_hdr_start, len); 918 (void) pthread_mutex_unlock(&sip_msg->sip_msg_mutex); 919 slstr[len] = '\0'; 920 return (slstr); 921 } 922 923 /* 924 * Return the given header as a string. Caller frees string 925 */ 926 char * 927 sip_hdr_to_str(sip_header_t sip_header, int *error) 928 { 929 char *hdrstr; 930 char *tmpptr; 931 _sip_header_t *_sip_header; 932 int len; 933 934 if (error != NULL) 935 *error = 0; 936 937 if (sip_header == NULL) { 938 if (error != NULL) 939 *error = EINVAL; 940 return (NULL); 941 } 942 _sip_header = (_sip_header_t *)sip_header; 943 if (_sip_header->sip_header_state == SIP_HEADER_DELETED) { 944 if (_sip_header->sip_hdr_sipmsg != NULL) { 945 (void) pthread_mutex_unlock( 946 &_sip_header->sip_hdr_sipmsg->sip_msg_mutex); 947 } 948 if (error != NULL) 949 *error = EINVAL; 950 return (NULL); 951 } 952 if (_sip_header->sip_hdr_sipmsg != NULL) { 953 (void) pthread_mutex_lock( 954 &_sip_header->sip_hdr_sipmsg->sip_msg_mutex); 955 } 956 len = _sip_header->sip_hdr_end - _sip_header->sip_hdr_start; 957 hdrstr = malloc(len); 958 if (hdrstr == NULL) { 959 if (_sip_header->sip_hdr_sipmsg != NULL) { 960 (void) pthread_mutex_unlock( 961 &_sip_header->sip_hdr_sipmsg->sip_msg_mutex); 962 } 963 if (error != NULL) 964 *error = ENOMEM; 965 return (NULL); 966 } 967 if (_sip_header->sip_header_state == SIP_HEADER_DELETED_VAL) { 968 len = sip_copy_values(hdrstr, _sip_header); 969 } else { 970 (void) strncpy(hdrstr, _sip_header->sip_hdr_start, len); 971 } 972 if (_sip_header->sip_hdr_sipmsg != NULL) { 973 (void) pthread_mutex_unlock( 974 &_sip_header->sip_hdr_sipmsg->sip_msg_mutex); 975 } 976 tmpptr = hdrstr + len; 977 while (*tmpptr-- != '\n') { 978 if (tmpptr == _sip_header->sip_hdr_start) { 979 free(hdrstr); 980 if (error != NULL) 981 *error = EINVAL; 982 return (NULL); 983 } 984 } 985 *tmpptr = '\0'; 986 return (hdrstr); 987 } 988 989 /* 990 * Given a param list find the named parameter. 991 * Returns a pointer to the value or NULL. 992 */ 993 sip_param_t * 994 sip_get_param_from_list(sip_param_t *param_list, char *param_name) 995 { 996 while (param_list != NULL) { 997 if (param_list->param_name.sip_str_len == strlen(param_name) && 998 strncasecmp(param_list->param_name.sip_str_ptr, param_name, 999 strlen(param_name)) == 0) { 1000 return (param_list); 1001 } 1002 param_list = param_list->param_next; 1003 } 1004 return (NULL); 1005 } 1006