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