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