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