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