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_xaction.h" 33 34 #define SIP_BUF_SIZE 128 35 36 /* 37 * Find the header named header, consecutive calls with old_header 38 * passed in will return next header of the same type. 39 * If no name is passed the first header is returned. consectutive calls 40 * with no name but an old header will return the next header. 41 */ 42 const struct sip_header * 43 sip_get_header(sip_msg_t sip_msg, char *header_name, sip_header_t old_header, 44 int *error) 45 { 46 _sip_msg_t *_sip_msg; 47 const struct sip_header *sip_hdr; 48 49 if (error != NULL) 50 *error = 0; 51 if (sip_msg == NULL) { 52 if (error != NULL) 53 *error = EINVAL; 54 return (NULL); 55 } 56 _sip_msg = (_sip_msg_t *)sip_msg; 57 (void) pthread_mutex_lock(&_sip_msg->sip_msg_mutex); 58 sip_hdr = (sip_header_t)sip_search_for_header((_sip_msg_t *)sip_msg, 59 header_name, (_sip_header_t *)old_header); 60 (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex); 61 if (sip_hdr == NULL && error != NULL) 62 *error = EINVAL; 63 return (sip_hdr); 64 } 65 66 /* 67 * Return the request line as a string. Caller releases the returned string. 68 */ 69 char * 70 sip_reqline_to_str(sip_msg_t sip_msg, int *error) 71 { 72 char *reqstr; 73 74 if (error != NULL) 75 *error = 0; 76 if (sip_msg == NULL || !sip_msg_is_request(sip_msg, error)) { 77 if (error != NULL) 78 *error = EINVAL; 79 return (NULL); 80 } 81 reqstr = _sip_startline_to_str((_sip_msg_t *)sip_msg, error); 82 return (reqstr); 83 } 84 85 /* 86 * Return the response line as a string. Caller releases the returned string. 87 */ 88 char * 89 sip_respline_to_str(sip_msg_t sip_msg, int *error) 90 { 91 char *respstr; 92 93 if (error != NULL) 94 *error = 0; 95 if (sip_msg == NULL || sip_msg_is_request(sip_msg, error)) { 96 if (error != NULL) 97 *error = EINVAL; 98 return (NULL); 99 } 100 respstr = _sip_startline_to_str((_sip_msg_t *)sip_msg, error); 101 return (respstr); 102 } 103 104 /* 105 * return the first value of the header 106 */ 107 const struct sip_value * 108 sip_get_header_value(const struct sip_header *sip_header, int *error) 109 { 110 _sip_header_t *_sip_header; 111 sip_parsed_header_t *sip_parsed_header; 112 int ret = 0; 113 const struct sip_value *value; 114 115 if (error != NULL) 116 *error = 0; 117 if (sip_header == NULL) { 118 if (error != NULL) 119 *error = EINVAL; 120 return (NULL); 121 } 122 _sip_header = (_sip_header_t *)sip_header; 123 if (_sip_header->sip_hdr_sipmsg != NULL) { 124 (void) pthread_mutex_lock( 125 &_sip_header->sip_hdr_sipmsg->sip_msg_mutex); 126 } 127 if (_sip_header->sip_header_state == SIP_HEADER_DELETED) { 128 if (_sip_header->sip_hdr_sipmsg != NULL) { 129 (void) pthread_mutex_unlock( 130 &_sip_header->sip_hdr_sipmsg->sip_msg_mutex); 131 } 132 if (error != NULL) 133 *error = EINVAL; 134 return (NULL); 135 } 136 ret = _sip_header->sip_header_functions->header_parse_func( 137 _sip_header, &sip_parsed_header); 138 if (_sip_header->sip_hdr_sipmsg != NULL) { 139 (void) pthread_mutex_unlock 140 (&_sip_header->sip_hdr_sipmsg->sip_msg_mutex); 141 } 142 if (error != NULL) 143 *error = ret; 144 145 if (ret != 0) 146 return (NULL); 147 value = (sip_header_value_t)sip_parsed_header->value; 148 while (value != NULL && value->value_state == SIP_VALUE_DELETED) 149 value = value->next; 150 if (value != NULL && value->value_state == SIP_VALUE_BAD && 151 error != NULL) { 152 *error = EPROTO; 153 } 154 return ((sip_header_value_t)value); 155 } 156 157 /* 158 * Return the next value of the header. 159 */ 160 const struct sip_value * 161 sip_get_next_value(sip_header_value_t old_value, int *error) 162 { 163 const struct sip_value *value; 164 165 if (error != NULL) 166 *error = 0; 167 if (old_value == NULL || old_value->next == NULL) { 168 if (error != NULL) 169 *error = EINVAL; 170 return (NULL); 171 } 172 /* 173 * We never free the deleted values so no need to hold a lock. 174 */ 175 value = (sip_header_value_t)old_value->next; 176 while (value != NULL && value->value_state == SIP_VALUE_DELETED) 177 value = value->next; 178 if (value != NULL && value->value_state == SIP_VALUE_BAD && 179 error != NULL) { 180 *error = EPROTO; 181 } 182 return ((sip_header_value_t)value); 183 } 184 185 /* 186 * Given a SIP message, delete the header "header_name". 187 */ 188 int 189 sip_delete_header_by_name(sip_msg_t msg, char *header_name) 190 { 191 _sip_msg_t *_msg = (_sip_msg_t *)msg; 192 sip_header_t sip_hdr; 193 _sip_header_t *_sip_hdr; 194 195 if (_msg == NULL || header_name == NULL) 196 return (EINVAL); 197 (void) pthread_mutex_lock(&_msg->sip_msg_mutex); 198 if (_msg->sip_msg_cannot_be_modified) { 199 (void) pthread_mutex_unlock(&_msg->sip_msg_mutex); 200 return (EPERM); 201 } 202 sip_hdr = (sip_header_t)sip_search_for_header(_msg, header_name, NULL); 203 if (sip_hdr == NULL) { 204 (void) pthread_mutex_unlock(&_msg->sip_msg_mutex); 205 return (EINVAL); 206 } 207 _sip_hdr = (_sip_header_t *)sip_hdr; 208 _sip_hdr->sip_header_state = SIP_HEADER_DELETED; 209 _sip_hdr->sip_hdr_sipmsg->sip_msg_len -= _sip_hdr->sip_hdr_end - 210 _sip_hdr->sip_hdr_start; 211 assert(_sip_hdr->sip_hdr_sipmsg->sip_msg_len >= 0); 212 if (_msg->sip_msg_buf != NULL) 213 _msg->sip_msg_modified = B_TRUE; 214 (void) pthread_mutex_unlock(&_msg->sip_msg_mutex); 215 216 return (0); 217 } 218 219 /* 220 * Mark the header as deleted. 221 */ 222 int 223 sip_delete_header(sip_header_t sip_header) 224 { 225 _sip_header_t *_sip_header; 226 227 if (sip_header == NULL) 228 return (EINVAL); 229 _sip_header = (_sip_header_t *)sip_header; 230 (void) pthread_mutex_lock(&_sip_header->sip_hdr_sipmsg->sip_msg_mutex); 231 if (_sip_header->sip_hdr_sipmsg->sip_msg_cannot_be_modified) { 232 (void) pthread_mutex_unlock 233 (&_sip_header->sip_hdr_sipmsg->sip_msg_mutex); 234 return (EPERM); 235 } 236 if (_sip_header->sip_header_state == SIP_HEADER_DELETED) { 237 (void) pthread_mutex_unlock( 238 &_sip_header->sip_hdr_sipmsg->sip_msg_mutex); 239 return (EINVAL); 240 } 241 _sip_header->sip_header_state = SIP_HEADER_DELETED; 242 _sip_header->sip_hdr_sipmsg->sip_msg_len -= _sip_header->sip_hdr_end - 243 _sip_header->sip_hdr_start; 244 assert(_sip_header->sip_hdr_sipmsg->sip_msg_len >= 0); 245 if (_sip_header->sip_hdr_sipmsg->sip_msg_buf != NULL) 246 _sip_header->sip_hdr_sipmsg->sip_msg_modified = B_TRUE; 247 (void) pthread_mutex_unlock 248 (&_sip_header->sip_hdr_sipmsg->sip_msg_mutex); 249 return (0); 250 } 251 252 /* 253 * Mark the value as deleted. 254 */ 255 int 256 sip_delete_value(sip_header_t sip_header, sip_header_value_t sip_header_value) 257 { 258 _sip_header_t *_sip_header; 259 sip_value_t *_sip_header_value; 260 int vlen; 261 char *c; 262 263 if (sip_header == NULL || sip_header_value == NULL) 264 return (EINVAL); 265 _sip_header = (_sip_header_t *)sip_header; 266 (void) pthread_mutex_lock(&_sip_header->sip_hdr_sipmsg->sip_msg_mutex); 267 if (_sip_header->sip_hdr_sipmsg->sip_msg_cannot_be_modified) { 268 (void) pthread_mutex_unlock(&_sip_header-> 269 sip_hdr_sipmsg->sip_msg_mutex); 270 return (EPERM); 271 } 272 if (_sip_header->sip_header_state == SIP_HEADER_DELETED) { 273 (void) pthread_mutex_unlock( 274 &_sip_header->sip_hdr_sipmsg->sip_msg_mutex); 275 return (EINVAL); 276 } 277 _sip_header_value = (sip_value_t *)sip_header_value; 278 if (_sip_header_value->value_state == SIP_VALUE_DELETED) { 279 (void) pthread_mutex_unlock( 280 &_sip_header->sip_hdr_sipmsg->sip_msg_mutex); 281 return (EINVAL); 282 } 283 _sip_header->sip_header_state = SIP_HEADER_DELETED_VAL; 284 _sip_header_value->value_state = SIP_VALUE_DELETED; 285 vlen = _sip_header_value->value_end - _sip_header_value->value_start; 286 if (_sip_header->sip_hdr_parsed->value == _sip_header_value) { 287 c = _sip_header_value->value_start; 288 while (*c-- != SIP_HCOLON) 289 vlen++; 290 } else { 291 c = _sip_header_value->value_start; 292 while (*c-- != SIP_COMMA) 293 vlen++; 294 } 295 if (_sip_header_value->next == NULL) { 296 sip_value_t *value = _sip_header->sip_hdr_parsed->value; 297 boolean_t crlf_present = B_FALSE; 298 char *s; 299 300 while (value != NULL && value != _sip_header_value) { 301 crlf_present = B_FALSE; 302 303 if (value->value_state == SIP_VALUE_DELETED) { 304 value = value->next; 305 continue; 306 } 307 s = value->value_end; 308 while (s != value->value_start) { 309 if (*s == '\r' && strncmp(s, SIP_CRLF, 310 strlen(SIP_CRLF)) == 0) { 311 crlf_present = B_TRUE; 312 break; 313 } 314 s--; 315 } 316 value = value->next; 317 } 318 if (!crlf_present) { 319 c = _sip_header_value->value_end; 320 while (*c-- != '\r') 321 vlen--; 322 assert(vlen > 0); 323 } 324 } 325 _sip_header->sip_hdr_sipmsg->sip_msg_len -= vlen; 326 if (_sip_header->sip_hdr_sipmsg->sip_msg_buf != NULL) 327 _sip_header->sip_hdr_sipmsg->sip_msg_modified = B_TRUE; 328 (void) pthread_mutex_unlock 329 (&_sip_header->sip_hdr_sipmsg->sip_msg_mutex); 330 return (0); 331 } 332 333 /* 334 * Given a param list, check if a param name exists. 335 */ 336 boolean_t 337 sip_is_param_present(const sip_param_t *param_list, char *param_name, 338 int param_len) 339 { 340 const sip_param_t *param = param_list; 341 342 while (param != NULL) { 343 if (param->param_name.sip_str_len == param_len && 344 strncasecmp(param->param_name.sip_str_ptr, param_name, 345 param_len) == 0) { 346 return (B_TRUE); 347 } 348 param = param->param_next; 349 } 350 return (B_FALSE); 351 } 352 353 354 /* 355 * Given a value header return the value of the named param. 356 */ 357 const sip_str_t * 358 sip_get_param_value(sip_header_value_t header_value, char *param_name, 359 int *error) 360 { 361 sip_value_t *_sip_header_value; 362 sip_param_t *sip_param; 363 364 if (error != NULL) 365 *error = 0; 366 if (header_value == NULL || param_name == NULL) { 367 if (error != NULL) 368 *error = EINVAL; 369 return (NULL); 370 } 371 _sip_header_value = (sip_value_t *)header_value; 372 if (_sip_header_value->value_state == SIP_VALUE_DELETED) { 373 if (error != NULL) 374 *error = EINVAL; 375 return (NULL); 376 } 377 if (_sip_header_value->param_list == NULL) { 378 if (error != NULL) 379 *error = EINVAL; 380 return (NULL); 381 } 382 sip_param = sip_get_param_from_list(_sip_header_value->param_list, 383 param_name); 384 if (sip_param != NULL) 385 return (&sip_param->param_value); 386 return (NULL); 387 } 388 389 /* 390 * Return the list of params in the header 391 */ 392 const sip_param_t * 393 sip_get_params(sip_header_value_t header_value, int *error) 394 { 395 sip_value_t *sip_header_value; 396 397 if (error != NULL) 398 *error = 0; 399 if (header_value == NULL) { 400 if (error != NULL) 401 *error = EINVAL; 402 return (NULL); 403 } 404 sip_header_value = (sip_value_t *)header_value; 405 if (sip_header_value->value_state == SIP_VALUE_DELETED) { 406 if (error != NULL) 407 *error = EINVAL; 408 return (NULL); 409 } 410 return (sip_header_value->param_list); 411 } 412 413 /* 414 * Return true if this is a SIP request 415 */ 416 boolean_t 417 sip_msg_is_request(sip_msg_t sip_msg, int *error) 418 { 419 _sip_msg_t *_sip_msg; 420 sip_message_type_t *sip_msg_info; 421 boolean_t ret; 422 423 if (error != NULL) 424 *error = 0; 425 if (sip_msg == NULL) { 426 if (error != NULL) 427 *error = EINVAL; 428 return (B_FALSE); 429 } 430 _sip_msg = (_sip_msg_t *)sip_msg; 431 (void) pthread_mutex_lock(&_sip_msg->sip_msg_mutex); 432 if (_sip_msg->sip_msg_req_res == NULL) { 433 (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex); 434 if (error != NULL) 435 *error = EINVAL; 436 return (B_FALSE); 437 } 438 sip_msg_info = _sip_msg->sip_msg_req_res; 439 ret = sip_msg_info->is_request; 440 (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex); 441 return (ret); 442 } 443 444 /* 445 * Return true if this is a SIP response 446 */ 447 boolean_t 448 sip_msg_is_response(sip_msg_t sip_msg, int *error) 449 { 450 boolean_t is_resp; 451 _sip_msg_t *_sip_msg; 452 sip_message_type_t *sip_msg_info; 453 454 if (error != NULL) 455 *error = 0; 456 if (sip_msg == NULL) { 457 if (error != NULL) 458 *error = EINVAL; 459 return (B_FALSE); 460 } 461 _sip_msg = (_sip_msg_t *)sip_msg; 462 (void) pthread_mutex_lock(&_sip_msg->sip_msg_mutex); 463 if (_sip_msg->sip_msg_req_res == NULL) { 464 (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex); 465 if (error != NULL) 466 *error = EINVAL; 467 return (B_FALSE); 468 } 469 sip_msg_info = _sip_msg->sip_msg_req_res; 470 is_resp = !sip_msg_info->is_request; 471 (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex); 472 return (is_resp); 473 } 474 475 /* 476 * Return the method in the request line 477 */ 478 sip_method_t 479 sip_get_request_method(sip_msg_t sip_msg, int *error) 480 { 481 _sip_msg_t *_sip_msg; 482 sip_message_type_t *sip_msg_info; 483 sip_method_t ret = -1; 484 485 if (error != NULL) 486 *error = 0; 487 if (sip_msg == NULL) { 488 if (error != NULL) 489 *error = EINVAL; 490 return (ret); 491 } 492 _sip_msg = (_sip_msg_t *)sip_msg; 493 (void) pthread_mutex_lock(&_sip_msg->sip_msg_mutex); 494 sip_msg_info = _sip_msg->sip_msg_req_res; 495 if (_sip_msg->sip_msg_req_res == NULL) { 496 (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex); 497 if (error != NULL) 498 *error = EINVAL; 499 return (ret); 500 } 501 if (sip_msg_info->is_request) 502 ret = sip_msg_info->sip_req_method; 503 else if (error != NULL) 504 *error = EINVAL; 505 (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex); 506 return (ret); 507 } 508 509 /* 510 * Return the URI from the request line 511 */ 512 const sip_str_t * 513 sip_get_request_uri_str(sip_msg_t sip_msg, int *error) 514 { 515 _sip_msg_t *_sip_msg; 516 sip_message_type_t *sip_msg_info; 517 sip_str_t *ret = NULL; 518 struct sip_uri *parsed_uri; 519 520 if (error != NULL) 521 *error = 0; 522 if (sip_msg == NULL) { 523 if (error != NULL) 524 *error = EINVAL; 525 return (NULL); 526 } 527 _sip_msg = (_sip_msg_t *)sip_msg; 528 (void) pthread_mutex_lock(&_sip_msg->sip_msg_mutex); 529 if (_sip_msg->sip_msg_req_res == NULL) { 530 (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex); 531 if (error != NULL) 532 *error = EINVAL; 533 return (NULL); 534 } 535 sip_msg_info = _sip_msg->sip_msg_req_res; 536 if (sip_msg_info->is_request) 537 ret = &sip_msg_info->sip_req_uri; 538 (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex); 539 540 /* 541 * If the error is required, check the validity of the URI via 542 * sip_uri_parse(). 543 */ 544 if (error != NULL) { 545 parsed_uri = sip_parse_uri(ret, error); 546 if (parsed_uri != NULL) 547 sip_free_parsed_uri((sip_uri_t)parsed_uri); 548 } 549 return (ret); 550 } 551 552 /* 553 * Return the response code 554 */ 555 int 556 sip_get_response_code(sip_msg_t sip_msg, int *error) 557 { 558 _sip_msg_t *_sip_msg; 559 sip_message_type_t *sip_msg_info; 560 int ret = -1; 561 562 if (error != NULL) 563 *error = 0; 564 if (sip_msg == NULL) { 565 if (error != NULL) 566 *error = EINVAL; 567 return (ret); 568 } 569 _sip_msg = (_sip_msg_t *)sip_msg; 570 (void) pthread_mutex_lock(&_sip_msg->sip_msg_mutex); 571 if (_sip_msg->sip_msg_req_res == NULL) { 572 (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex); 573 if (error != NULL) 574 *error = EINVAL; 575 return (ret); 576 } 577 sip_msg_info = _sip_msg->sip_msg_req_res; 578 if (!sip_msg_info->is_request) 579 ret = sip_msg_info->sip_resp_code; 580 else if (error != NULL) 581 *error = EINVAL; 582 (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex); 583 return (ret); 584 } 585 586 /* 587 * Get the response phrase 588 */ 589 const sip_str_t * 590 sip_get_response_phrase(sip_msg_t sip_msg, int *error) 591 { 592 _sip_msg_t *_sip_msg; 593 sip_message_type_t *sip_msg_info; 594 sip_str_t *ret = NULL; 595 596 if (error != NULL) 597 *error = 0; 598 if (sip_msg == NULL) { 599 if (error != NULL) 600 *error = EINVAL; 601 return (ret); 602 } 603 _sip_msg = (_sip_msg_t *)sip_msg; 604 (void) pthread_mutex_lock(&_sip_msg->sip_msg_mutex); 605 if (_sip_msg->sip_msg_req_res == NULL) { 606 (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex); 607 if (error != NULL) 608 *error = EINVAL; 609 return (ret); 610 } 611 sip_msg_info = _sip_msg->sip_msg_req_res; 612 (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex); 613 if (!sip_msg_info->is_request) { 614 if (sip_msg_info->sip_resp_phrase_len == 0) 615 ret = NULL; 616 else 617 ret = &sip_msg_info->sip_resp_phrase; 618 } else if (error != NULL) { 619 *error = EINVAL; 620 } 621 return (ret); 622 } 623 624 /* 625 * Get the SIP version string 626 */ 627 const sip_str_t * 628 sip_get_sip_version(sip_msg_t sip_msg, int *error) 629 { 630 _sip_msg_t *_sip_msg; 631 sip_message_type_t *sip_msg_info; 632 sip_str_t *ret = NULL; 633 634 if (error != NULL) 635 *error = 0; 636 if (sip_msg == NULL) { 637 if (error != NULL) 638 *error = EINVAL; 639 return (ret); 640 } 641 _sip_msg = (_sip_msg_t *)sip_msg; 642 (void) pthread_mutex_lock(&_sip_msg->sip_msg_mutex); 643 if (_sip_msg->sip_msg_req_res == NULL) { 644 (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex); 645 if (error != NULL) 646 *error = EINVAL; 647 return (ret); 648 } 649 sip_msg_info = _sip_msg->sip_msg_req_res; 650 (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex); 651 ret = &sip_msg_info->sip_proto_version.version; 652 return (ret); 653 } 654 655 /* 656 * Return the length of the SIP message 657 */ 658 int 659 sip_get_msg_len(sip_msg_t sip_msg, int *error) 660 { 661 _sip_msg_t *_sip_msg; 662 663 if (error != NULL) 664 *error = 0; 665 if (sip_msg == NULL) { 666 if (error != NULL) 667 *error = EINVAL; 668 return (-1); 669 } 670 _sip_msg = (_sip_msg_t *)sip_msg; 671 672 return (_sip_msg->sip_msg_len); 673 } 674 675 /* 676 * Get content as a string. Caller frees the string 677 */ 678 char * 679 sip_get_content(sip_msg_t sip_msg, int *error) 680 { 681 _sip_msg_t *_sip_msg; 682 sip_content_t *sip_content; 683 char *content; 684 int len; 685 char *p; 686 687 if (error != NULL) 688 *error = 0; 689 690 if (sip_msg == NULL) { 691 if (error != NULL) 692 *error = EINVAL; 693 return (NULL); 694 } 695 _sip_msg = (_sip_msg_t *)sip_msg; 696 (void) pthread_mutex_lock(&_sip_msg->sip_msg_mutex); 697 if (_sip_msg->sip_msg_content == NULL) { 698 (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex); 699 if (error != NULL) 700 *error = EINVAL; 701 return (NULL); 702 } 703 content = malloc(_sip_msg->sip_msg_content_len + 1); 704 if (content == NULL) { 705 (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex); 706 if (error != NULL) 707 *error = ENOMEM; 708 return (NULL); 709 } 710 p = content; 711 sip_content = _sip_msg->sip_msg_content; 712 while (sip_content != NULL) { 713 len = sip_content->sip_content_end - 714 sip_content->sip_content_start; 715 (void) strncpy(p, sip_content->sip_content_start, len); 716 p += len; 717 sip_content = sip_content->sip_content_next; 718 } 719 content[_sip_msg->sip_msg_content_len] = '\0'; 720 (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex); 721 return (content); 722 } 723 724 /* 725 * copy sip_header with param, if any, to sip_msg 726 */ 727 int 728 sip_copy_header(sip_msg_t sip_msg, sip_header_t sip_header, char *param) 729 { 730 _sip_msg_t *_sip_msg; 731 _sip_header_t *_sip_header; 732 int ret; 733 734 if (sip_msg == NULL || sip_header == NULL) 735 return (EINVAL); 736 _sip_msg = (_sip_msg_t *)sip_msg; 737 _sip_header = (_sip_header_t *)sip_header; 738 (void) pthread_mutex_lock(&_sip_msg->sip_msg_mutex); 739 if (_sip_msg->sip_msg_cannot_be_modified) { 740 (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex); 741 return (EPERM); 742 } 743 if (_sip_header->sip_header_state == SIP_HEADER_DELETED) { 744 (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex); 745 return (EINVAL); 746 } 747 748 ret = _sip_copy_header(_sip_msg, _sip_header, param, B_TRUE); 749 if (_sip_msg->sip_msg_buf != NULL) 750 _sip_msg->sip_msg_modified = B_TRUE; 751 (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex); 752 return (ret); 753 } 754 755 /* 756 * copy the header specified by header_name, with param, if any 757 */ 758 int 759 sip_copy_header_by_name(sip_msg_t old_msg, sip_msg_t new_msg, 760 char *header_name, char *param) 761 { 762 int ret; 763 _sip_msg_t *_old_msg = (_sip_msg_t *)old_msg; 764 _sip_msg_t *_new_msg = (_sip_msg_t *)new_msg; 765 766 if (_old_msg == NULL || _new_msg == NULL || header_name == NULL || 767 _old_msg == _new_msg) { 768 return (EINVAL); 769 } 770 (void) pthread_mutex_lock(&_new_msg->sip_msg_mutex); 771 if (_new_msg->sip_msg_cannot_be_modified) { 772 (void) pthread_mutex_unlock(&_new_msg->sip_msg_mutex); 773 return (EPERM); 774 } 775 776 (void) pthread_mutex_lock(&_old_msg->sip_msg_mutex); 777 ret = _sip_find_and_copy_header(_old_msg, _new_msg, header_name, param, 778 B_FALSE); 779 (void) pthread_mutex_unlock(&_old_msg->sip_msg_mutex); 780 if (_new_msg->sip_msg_buf != NULL) 781 _new_msg->sip_msg_modified = B_TRUE; 782 (void) pthread_mutex_unlock(&_new_msg->sip_msg_mutex); 783 return (ret); 784 } 785 786 /* 787 * add the given header to sip_message 788 */ 789 int 790 sip_add_header(sip_msg_t sip_msg, char *header_string) 791 { 792 int header_size; 793 _sip_header_t *new_header; 794 _sip_msg_t *_sip_msg; 795 796 if (sip_msg == NULL || header_string == NULL) 797 return (EINVAL); 798 _sip_msg = (_sip_msg_t *)sip_msg; 799 (void) pthread_mutex_lock(&_sip_msg->sip_msg_mutex); 800 if (_sip_msg->sip_msg_cannot_be_modified) { 801 (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex); 802 return (EPERM); 803 } 804 header_size = strlen(header_string) + strlen(SIP_CRLF); 805 new_header = sip_new_header(header_size); 806 if (new_header == NULL) { 807 (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex); 808 return (ENOMEM); 809 } 810 811 (void) snprintf(new_header->sip_hdr_start, header_size + 1, "%s%s", 812 header_string, SIP_CRLF); 813 _sip_add_header(_sip_msg, new_header, B_TRUE, B_FALSE, NULL); 814 if (_sip_msg->sip_msg_buf != NULL) 815 _sip_msg->sip_msg_modified = B_TRUE; 816 (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex); 817 return (0); 818 } 819 820 /* 821 * add the given param to the sip_header. create a new header with the param 822 * and mark the old header as deleted. 823 */ 824 sip_header_t 825 sip_add_param(sip_header_t sip_header, char *param, int *error) 826 { 827 _sip_header_t *_sip_header; 828 _sip_header_t *new_header; 829 int hdrlen; 830 _sip_msg_t *_sip_msg; 831 int param_len; 832 char *tmp_ptr; 833 834 if (error != NULL) 835 *error = 0; 836 837 if (param == NULL || sip_header == NULL) { 838 if (error != NULL) 839 *error = EINVAL; 840 return (NULL); 841 } 842 843 _sip_header = (_sip_header_t *)sip_header; 844 845 (void) pthread_mutex_lock(&_sip_header->sip_hdr_sipmsg->sip_msg_mutex); 846 if (_sip_header->sip_hdr_sipmsg->sip_msg_cannot_be_modified) { 847 if (error != NULL) 848 *error = EPERM; 849 (void) pthread_mutex_unlock( 850 &_sip_header->sip_hdr_sipmsg->sip_msg_mutex); 851 return (NULL); 852 } 853 if (_sip_header->sip_header_state == SIP_HEADER_DELETED) { 854 if (error != NULL) 855 *error = EINVAL; 856 (void) pthread_mutex_unlock( 857 &_sip_header->sip_hdr_sipmsg->sip_msg_mutex); 858 return (NULL); 859 } 860 861 param_len = SIP_SPACE_LEN + sizeof (char) + SIP_SPACE_LEN + 862 strlen(param); 863 hdrlen = _sip_header->sip_hdr_end - _sip_header->sip_hdr_start; 864 new_header = sip_new_header(hdrlen + param_len); 865 if (new_header == NULL) { 866 if (error != NULL) 867 *error = ENOMEM; 868 (void) pthread_mutex_unlock( 869 &_sip_header->sip_hdr_sipmsg->sip_msg_mutex); 870 return (NULL); 871 } 872 (void) memcpy(new_header->sip_hdr_start, _sip_header->sip_hdr_start, 873 hdrlen); 874 new_header->sip_hdr_end = new_header->sip_hdr_start + hdrlen; 875 hdrlen = param_len + 1; 876 /* 877 * Find CRLF 878 */ 879 tmp_ptr = new_header->sip_hdr_end; 880 while (*tmp_ptr-- != '\n') { 881 hdrlen++; 882 if (tmp_ptr == new_header->sip_hdr_start) { 883 sip_free_header(new_header); 884 if (error != NULL) 885 *error = EINVAL; 886 (void) pthread_mutex_unlock( 887 &_sip_header->sip_hdr_sipmsg->sip_msg_mutex); 888 return (NULL); 889 } 890 } 891 (void) snprintf(tmp_ptr, hdrlen + 1, 892 " %c %s%s", SIP_SEMI, param, SIP_CRLF); 893 new_header->sip_hdr_end += param_len; 894 new_header->sip_header_functions = _sip_header->sip_header_functions; 895 _sip_msg = _sip_header->sip_hdr_sipmsg; 896 _sip_add_header(_sip_msg, new_header, B_TRUE, B_FALSE, NULL); 897 if (_sip_header->sip_hdr_sipmsg->sip_msg_buf != NULL) 898 _sip_header->sip_hdr_sipmsg->sip_msg_modified = B_TRUE; 899 (void) pthread_mutex_unlock(&new_header->sip_hdr_sipmsg->sip_msg_mutex); 900 (void) sip_delete_header(sip_header); 901 return ((sip_header_t)new_header); 902 } 903 904 /* 905 * Get Request URI 906 */ 907 const struct sip_uri * 908 sip_get_request_uri(sip_msg_t sip_msg, int *error) 909 { 910 _sip_msg_t *_sip_msg; 911 sip_message_type_t *sip_msg_info; 912 const struct sip_uri *ret = NULL; 913 914 if (error != NULL) 915 *error = 0; 916 917 if (sip_msg == NULL) { 918 if (error != NULL) 919 *error = EINVAL; 920 return (NULL); 921 } 922 _sip_msg = (_sip_msg_t *)sip_msg; 923 (void) pthread_mutex_lock(&_sip_msg->sip_msg_mutex); 924 sip_msg_info = _sip_msg->sip_msg_req_res; 925 if (sip_msg_info != NULL && sip_msg_info->is_request) { 926 ret = sip_msg_info->sip_req_parse_uri; 927 } else { 928 if (error != NULL) 929 *error = EINVAL; 930 } 931 (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex); 932 933 if (ret != NULL) { 934 if (ret->sip_uri_scheme.sip_str_len == 0 || 935 ret->sip_uri_scheme.sip_str_ptr == NULL) { 936 ret = NULL; 937 if (error != NULL) 938 *error = EINVAL; 939 } else if (ret->sip_uri_errflags != 0 && error != NULL) { 940 *error = EINVAL; 941 } 942 } 943 return ((sip_uri_t)ret); 944 } 945 946 /* 947 * returns a comma separated string of all the sent-by values registered by 948 * the UA. 949 */ 950 char * 951 sip_sent_by_to_str(int *error) 952 { 953 sent_by_list_t *sb; 954 int sb_len = 0; 955 int slen; 956 char *sb_str; 957 char *p; 958 int count = 0; 959 int cnt = 0; 960 961 if (error != NULL) 962 *error = 0; 963 964 (void) pthread_mutex_lock(&sip_sent_by_lock); 965 if (sip_sent_by == NULL) { 966 (void) pthread_mutex_unlock(&sip_sent_by_lock); 967 return (NULL); 968 } 969 sb = sip_sent_by; 970 for (cnt = 0; cnt < sip_sent_by_count; cnt++) { 971 sb_len += strlen(sb->sb_val); 972 sb = sb->sb_next; 973 } 974 /* 975 * for the commas 976 */ 977 sb_len += sip_sent_by_count - 1; 978 sb_str = malloc(sb_len + 1); 979 if (sb_str == NULL) { 980 if (error != NULL) 981 *error = ENOMEM; 982 (void) pthread_mutex_unlock(&sip_sent_by_lock); 983 return (NULL); 984 } 985 sb = sip_sent_by; 986 p = sb_str; 987 slen = sb_len + 1; 988 for (cnt = 0; cnt < sip_sent_by_count; cnt++) { 989 if (cnt == 0) { 990 count = snprintf(p, slen, "%s", sb->sb_val); 991 } else { 992 count = snprintf(p, slen, "%c%s", SIP_COMMA, 993 sb->sb_val); 994 } 995 p += count; 996 slen -= count; 997 sb = sb->sb_next; 998 } 999 sb_str[sb_len] = '\0'; 1000 (void) pthread_mutex_unlock(&sip_sent_by_lock); 1001 return (sb_str); 1002 } 1003 1004 /* 1005 * A comma separated list of sent-by values. 1006 */ 1007 int 1008 sip_register_sent_by(char *val) 1009 { 1010 sent_by_list_t *sb = NULL; 1011 sent_by_list_t *sb_tail = NULL; 1012 char *str; 1013 int count = 0; 1014 1015 if (val == NULL) 1016 return (EINVAL); 1017 str = strtok(val, ","); 1018 while (str != NULL) { 1019 int slen; 1020 char *start = str; 1021 char *end = str + strlen(str) - 1; 1022 1023 while (isspace(*start)) 1024 start++; 1025 while (isspace(*end)) 1026 end--; 1027 if (end <= start) 1028 goto err_ret; 1029 slen = end - start + 1; 1030 sb_tail = (sent_by_list_t *)malloc(sizeof (*sb_tail)); 1031 if (sb_tail == NULL) 1032 goto err_ret; 1033 sb_tail->sb_next = sb_tail->sb_prev = NULL; 1034 if ((sb_tail->sb_val = (char *)malloc(slen + 1)) == NULL) { 1035 free(sb_tail); 1036 goto err_ret; 1037 } 1038 (void) strncpy(sb_tail->sb_val, start, slen); 1039 sb_tail->sb_val[slen] = '\0'; 1040 if (sb == NULL) { 1041 sb = sb_tail; 1042 } else { 1043 sb_tail->sb_next = sb; 1044 sb->sb_prev = sb_tail; 1045 sb = sb_tail; 1046 } 1047 count++; 1048 str = strtok(NULL, ","); 1049 } 1050 sb_tail = sb; 1051 while (sb_tail->sb_next != NULL) 1052 sb_tail = sb_tail->sb_next; 1053 (void) pthread_mutex_lock(&sip_sent_by_lock); 1054 if (sip_sent_by != NULL) { 1055 sb_tail->sb_next = sip_sent_by; 1056 sip_sent_by->sb_prev = sb_tail; 1057 } 1058 sip_sent_by = sb; 1059 sip_sent_by_count += count; 1060 (void) pthread_mutex_unlock(&sip_sent_by_lock); 1061 return (0); 1062 err_ret: 1063 sb_tail = sb; 1064 for (; count > 0; count--) { 1065 sb = sb_tail->sb_next; 1066 free(sb_tail->sb_val); 1067 sb_tail->sb_next = NULL; 1068 sb_tail->sb_prev = NULL; 1069 free(sb_tail); 1070 sb_tail = sb; 1071 } 1072 return (EINVAL); 1073 } 1074 1075 /* 1076 * Un-register sent-by values; 'val' contains a comma separated list 1077 */ 1078 void 1079 sip_unregister_sent_by(char *val) 1080 { 1081 sent_by_list_t *sb; 1082 char *str; 1083 int count = 0; 1084 1085 (void) pthread_mutex_lock(&sip_sent_by_lock); 1086 str = strtok(val, ","); 1087 while (str != NULL) { 1088 sb = sip_sent_by; 1089 for (count = 0; count < sip_sent_by_count; count++) { 1090 if (strncmp(sb->sb_val, str, strlen(str)) == 0) { 1091 if (sb == sip_sent_by) { 1092 if (sb->sb_next != NULL) 1093 sip_sent_by = sb->sb_next; 1094 else 1095 sip_sent_by = NULL; 1096 } else if (sb->sb_next == NULL) { 1097 sb->sb_prev->sb_next = NULL; 1098 } else { 1099 sb->sb_prev->sb_next = sb->sb_next; 1100 sb->sb_next->sb_prev = sb->sb_prev; 1101 } 1102 sip_sent_by_count--; 1103 sb->sb_next = NULL; 1104 sb->sb_prev = NULL; 1105 free(sb->sb_val); 1106 free(sb); 1107 break; 1108 } 1109 sb = sb->sb_next; 1110 } 1111 str = strtok(NULL, ","); 1112 } 1113 (void) pthread_mutex_unlock(&sip_sent_by_lock); 1114 } 1115 1116 /* 1117 * Un-register all the sent-by values 1118 */ 1119 void 1120 sip_unregister_all_sent_by() 1121 { 1122 sent_by_list_t *sb; 1123 int count; 1124 1125 (void) pthread_mutex_lock(&sip_sent_by_lock); 1126 sb = sip_sent_by; 1127 for (count = 0; count < sip_sent_by_count; count++) { 1128 sip_sent_by = sb->sb_next; 1129 free(sb->sb_val); 1130 sb->sb_next = NULL; 1131 sb->sb_prev = NULL; 1132 free(sb); 1133 sb = sip_sent_by; 1134 } 1135 sip_sent_by = NULL; 1136 sip_sent_by_count = 0; 1137 (void) pthread_mutex_unlock(&sip_sent_by_lock); 1138 } 1139 1140 /* 1141 * Given a response code, return the corresponding phrase 1142 */ 1143 char * 1144 sip_get_resp_desc(int resp_code) 1145 { 1146 switch (resp_code) { 1147 case SIP_TRYING: 1148 return ("TRYING"); 1149 case SIP_RINGING: 1150 return ("RINGING"); 1151 case SIP_CALL_IS_BEING_FORWARDED: 1152 return ("CALL_IS_BEING_FORWARDED"); 1153 case SIP_QUEUED: 1154 return ("QUEUED"); 1155 case SIP_SESSION_PROGRESS: 1156 return ("SESSION_PROGRESS"); 1157 case SIP_OK: 1158 return ("OK"); 1159 case SIP_ACCEPTED: 1160 return ("ACCEPTED"); 1161 case SIP_MULTIPLE_CHOICES: 1162 return ("MULTIPLE_CHOICES"); 1163 case SIP_MOVED_PERMANENTLY: 1164 return ("MOVED_PERMANENTLY"); 1165 case SIP_MOVED_TEMPORARILY: 1166 return ("MOVED_TEMPORARILY"); 1167 case SIP_USE_PROXY: 1168 return ("USE_PROXY"); 1169 case SIP_ALTERNATIVE_SERVICE: 1170 return ("ALTERNATIVE_SERVICE"); 1171 case SIP_BAD_REQUEST: 1172 return ("BAD_REQUEST"); 1173 case SIP_UNAUTHORIZED: 1174 return ("UNAUTHORIZED"); 1175 case SIP_PAYMENT_REQUIRED: 1176 return ("PAYMENT_REQUIRED"); 1177 case SIP_FORBIDDEN: 1178 return ("FORBIDDEN"); 1179 case SIP_NOT_FOUND: 1180 return ("NOT_FOUND"); 1181 case SIP_METHOD_NOT_ALLOWED: 1182 return ("METHOD_NOT_ALLOWED"); 1183 case SIP_NOT_ACCEPTABLE: 1184 return ("NOT_ACCEPTABLE"); 1185 case SIP_PROXY_AUTH_REQUIRED: 1186 return ("PROXY_AUTH_REQUIRED"); 1187 case SIP_REQUEST_TIMEOUT: 1188 return ("REQUEST_TIMEOUT"); 1189 case SIP_GONE: 1190 return ("GONE"); 1191 case SIP_REQUEST_ENTITY_2_LARGE: 1192 return ("REQUEST_ENTITY_2_LARGE"); 1193 case SIP_REQUEST_URI_2_LONG: 1194 return ("REQUEST_URI_2_LONG"); 1195 case SIP_UNSUPPORTED_MEDIA_TYPE: 1196 return ("UNSUPPORTED_MEDIA_TYPE"); 1197 case SIP_UNSUPPORTED_URI_SCHEME: 1198 return ("UNSUPPORTED_URI_SCHEME"); 1199 case SIP_BAD_EXTENSION: 1200 return ("BAD_EXTENSION"); 1201 case SIP_EXTENSION_REQUIRED: 1202 return ("EXTENSION_REQUIRED"); 1203 case SIP_INTERVAL_2_BRIEF: 1204 return ("INTERVAL_2_BRIEF"); 1205 case SIP_TEMPORARILY_UNAVAIL: 1206 return ("TEMPORARILY_UNAVAIL"); 1207 case SIP_CALL_NON_EXISTANT: 1208 return ("CALL_NON_EXISTANT"); 1209 case SIP_LOOP_DETECTED: 1210 return ("LOOP_DETECTED"); 1211 case SIP_TOO_MANY_HOOPS: 1212 return ("TOO_MANY_HOOPS"); 1213 case SIP_ADDRESS_INCOMPLETE: 1214 return ("ADDRESS_INCOMPLETE"); 1215 case SIP_AMBIGUOUS: 1216 return ("AMBIGUOUS"); 1217 case SIP_BUSY_HERE: 1218 return ("BUSY_HERE"); 1219 case SIP_REQUEST_TERMINATED: 1220 return ("REQUEST_TERMINATED"); 1221 case SIP_NOT_ACCEPTABLE_HERE: 1222 return ("NOT_ACCEPTABLE_HERE"); 1223 case SIP_BAD_EVENT: 1224 return ("BAD_EVENT"); 1225 case SIP_REQUEST_PENDING: 1226 return ("REQUEST_PENDING"); 1227 case SIP_UNDECIPHERABLE: 1228 return ("UNDECIPHERABLE"); 1229 case SIP_SERVER_INTERNAL_ERROR: 1230 return ("SERVER_INTERNAL_ERROR"); 1231 case SIP_NOT_IMPLEMENTED: 1232 return ("NOT_IMPLEMENTED"); 1233 case SIP_BAD_GATEWAY: 1234 return ("BAD_GATEWAY"); 1235 case SIP_SERVICE_UNAVAILABLE: 1236 return ("SERVICE_UNAVAILABLE"); 1237 case SIP_SERVER_TIMEOUT: 1238 return ("SERVER_TIMEOUT"); 1239 case SIP_VERSION_NOT_SUPPORTED: 1240 return ("VERSION_NOT_SUPPORTED"); 1241 case SIP_MESSAGE_2_LARGE: 1242 return ("MESSAGE_2_LARGE"); 1243 case SIP_BUSY_EVERYWHERE: 1244 return ("BUSY_EVERYWHERE"); 1245 case SIP_DECLINE: 1246 return ("DECLINE"); 1247 case SIP_DOES_NOT_EXIST_ANYWHERE: 1248 return ("DOES_NOT_EXIST_ANYWHERE"); 1249 case SIP_NOT_ACCEPTABLE_ANYWHERE: 1250 return ("NOT_ACCEPTABLE_ANYWHERE"); 1251 default: 1252 return ("UNKNOWN"); 1253 } 1254 } 1255 1256 /* 1257 * The following three fns initialize and destroy the private library 1258 * data in sip_conn_object_t. The assumption is that the 1st member 1259 * of sip_conn_object_t is reserved for library use. The private data 1260 * is used only for byte-stream protocols such as TCP to accumulate 1261 * a complete SIP message, based on the CONTENT-LENGTH value, before 1262 * processing it. 1263 */ 1264 int 1265 sip_init_conn_object(sip_conn_object_t obj) 1266 { 1267 void **obj_val; 1268 sip_conn_obj_pvt_t *pvt_data; 1269 1270 if (obj == NULL) 1271 return (EINVAL); 1272 pvt_data = malloc(sizeof (sip_conn_obj_pvt_t)); 1273 if (pvt_data == NULL) 1274 return (ENOMEM); 1275 pvt_data->sip_conn_obj_cache = NULL; 1276 pvt_data->sip_conn_obj_reass = malloc(sizeof (sip_reass_entry_t)); 1277 if (pvt_data->sip_conn_obj_reass == NULL) { 1278 free(pvt_data); 1279 return (ENOMEM); 1280 } 1281 bzero(pvt_data->sip_conn_obj_reass, sizeof (sip_reass_entry_t)); 1282 (void) pthread_mutex_init(&pvt_data->sip_conn_obj_reass_lock, NULL); 1283 (void) pthread_mutex_init(&pvt_data->sip_conn_obj_cache_lock, NULL); 1284 sip_refhold_conn(obj); 1285 obj_val = (void *)obj; 1286 *obj_val = (void *)pvt_data; 1287 1288 return (0); 1289 } 1290 1291 /* 1292 * Clear private date, if any 1293 */ 1294 void 1295 sip_clear_stale_data(sip_conn_object_t obj) 1296 { 1297 void **obj_val; 1298 sip_conn_obj_pvt_t *pvt_data; 1299 sip_reass_entry_t *reass; 1300 1301 if (obj == NULL) 1302 return; 1303 obj_val = (void *)obj; 1304 pvt_data = (sip_conn_obj_pvt_t *)*obj_val; 1305 (void) pthread_mutex_lock(&pvt_data->sip_conn_obj_reass_lock); 1306 reass = pvt_data->sip_conn_obj_reass; 1307 if (reass->sip_reass_msg != NULL) { 1308 assert(reass->sip_reass_msglen > 0); 1309 free(reass->sip_reass_msg); 1310 reass->sip_reass_msglen = 0; 1311 } 1312 assert(reass->sip_reass_msglen == 0); 1313 (void) pthread_mutex_unlock(&pvt_data->sip_conn_obj_reass_lock); 1314 } 1315 1316 /* 1317 * Walk through all the transactions, remove if this obj has been cached 1318 * by any. 1319 */ 1320 void 1321 sip_conn_destroyed(sip_conn_object_t obj) 1322 { 1323 void **obj_val; 1324 sip_conn_obj_pvt_t *pvt_data; 1325 1326 if (obj == NULL) 1327 return; 1328 obj_val = (void *)obj; 1329 pvt_data = (sip_conn_obj_pvt_t *)*obj_val; 1330 1331 sip_clear_stale_data(obj); 1332 free(pvt_data->sip_conn_obj_reass); 1333 pvt_data->sip_conn_obj_reass = NULL; 1334 (void) pthread_mutex_destroy(&pvt_data->sip_conn_obj_reass_lock); 1335 1336 sip_del_conn_obj_cache(obj, NULL); 1337 (void) pthread_mutex_destroy(&pvt_data->sip_conn_obj_cache_lock); 1338 1339 free(pvt_data); 1340 *obj_val = NULL; 1341 sip_refrele_conn(obj); 1342 } 1343