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 <errno.h> 33 #include <pthread.h> 34 #include <strings.h> 35 #include <sip.h> 36 37 #include "sip_msg.h" 38 #include "sip_miscdefs.h" 39 #include "sip_hash.h" 40 #include "sip_dialog.h" 41 #include "sip_parse_generic.h" 42 43 #define SIP_DLG_XCHG_FROM 0 44 #define SIP_DLG_XCHG_TO 1 45 46 /* 47 * Dialog state change callback function 48 */ 49 void (*sip_dlg_ulp_state_cb)(sip_dialog_t, sip_msg_t, int, int) = NULL; 50 void (*sip_ulp_dlg_del_cb)(sip_dialog_t, sip_msg_t, void *) = NULL; 51 52 boolean_t sip_incomplete_dialog(sip_dialog_t); 53 54 /* 55 * Exchange From/To header 56 */ 57 _sip_header_t *sip_dlg_xchg_from_to(sip_msg_t, int); 58 59 /* 60 * Complete dialog hash table 61 */ 62 sip_hash_t sip_dialog_hash[SIP_HASH_SZ]; 63 64 /* 65 * Partial dialog hash table 66 */ 67 sip_hash_t sip_dialog_phash[SIP_HASH_SZ]; 68 69 /* 70 * Route set structure 71 */ 72 typedef struct sip_dlg_route_set_s { 73 char *sip_dlg_route; 74 sip_str_t sip_dlg_ruri; 75 boolean_t sip_dlg_route_lr; 76 struct sip_dlg_route_set_s *sip_dlg_route_next; 77 }sip_dlg_route_set_t; 78 79 sip_dialog_t sip_seed_dialog(sip_conn_object_t, _sip_msg_t *, 80 boolean_t, int); 81 sip_dialog_t sip_complete_dialog(_sip_msg_t *, _sip_dialog_t *); 82 int sip_dialog_process(_sip_msg_t *, sip_dialog_t *); 83 void sip_dialog_delete(_sip_dialog_t *); 84 void sip_dialog_init(); 85 sip_dialog_t sip_dialog_find(_sip_msg_t *); 86 boolean_t sip_dialog_match(void *, void *); 87 boolean_t sip_dialog_free(void *, void *, int *); 88 sip_dialog_t sip_update_dialog(sip_dialog_t, _sip_msg_t *); 89 char *sip_dialog_req_uri(sip_dialog_t); 90 91 static void sip_release_dialog_res(_sip_dialog_t *); 92 void sip_dlg_self_destruct(void *); 93 static int sip_dialog_get_route_set(_sip_dialog_t *, _sip_msg_t *, 94 int); 95 static void sip_dialog_free_rset(sip_dlg_route_set_t *); 96 97 /* 98 * Timer object for partial dialogs 99 */ 100 typedef struct sip_dialog_timer_obj_s { 101 _sip_dialog_t *dialog; 102 void (*func)(sip_dialog_t, sip_msg_t, void *); 103 } sip_dialog_timer_obj_t; 104 105 /* 106 * To avoid duplication all over the place 107 */ 108 static void 109 sip_release_dialog_res(_sip_dialog_t *dialog) 110 { 111 112 assert(dialog->sip_dlg_ref_cnt == 0); 113 if (SIP_IS_TIMER_RUNNING(dialog->sip_dlg_timer)) 114 SIP_CANCEL_TIMER(dialog->sip_dlg_timer); 115 if (dialog->sip_dlg_call_id != NULL) 116 sip_free_header(dialog->sip_dlg_call_id); 117 if (dialog->sip_dlg_local_uri_tag != NULL) 118 sip_free_header(dialog->sip_dlg_local_uri_tag); 119 if (dialog->sip_dlg_remote_uri_tag != NULL) 120 sip_free_header(dialog->sip_dlg_remote_uri_tag); 121 if (dialog->sip_dlg_remote_target != NULL) 122 sip_free_header(dialog->sip_dlg_remote_target); 123 if (dialog->sip_dlg_local_contact != NULL) 124 sip_free_header(dialog->sip_dlg_local_contact); 125 if (dialog->sip_dlg_new_local_contact != NULL) 126 sip_free_header(dialog->sip_dlg_new_local_contact); 127 if (dialog->sip_dlg_route_set != NULL) 128 sip_free_header(dialog->sip_dlg_route_set); 129 if (dialog->sip_dlg_event != NULL) 130 sip_free_header(dialog->sip_dlg_event); 131 if (dialog->sip_dlg_req_uri.sip_str_ptr != NULL) { 132 free(dialog->sip_dlg_req_uri.sip_str_ptr); 133 dialog->sip_dlg_req_uri.sip_str_ptr = NULL; 134 dialog->sip_dlg_req_uri.sip_str_len = 0; 135 } 136 if (dialog->sip_dlg_rset.sip_str_ptr != NULL) { 137 free(dialog->sip_dlg_rset.sip_str_ptr); 138 dialog->sip_dlg_rset.sip_str_len = 0; 139 dialog->sip_dlg_rset.sip_str_ptr = NULL; 140 } 141 (void) pthread_mutex_destroy(&dialog->sip_dlg_mutex); 142 free(dialog); 143 } 144 145 /* 146 * Get the route information from the 'value' and add it to the route 147 * set. 148 */ 149 static sip_dlg_route_set_t * 150 sip_add_route_to_set(sip_hdr_value_t *value) 151 { 152 int vlen = 0; 153 sip_dlg_route_set_t *rset; 154 char *crlf; 155 const sip_param_t *uri_param; 156 int error; 157 158 rset = calloc(1, sizeof (*rset)); 159 if (rset == NULL) 160 return (NULL); 161 rset->sip_dlg_route_next = NULL; 162 vlen = value->sip_value_end - value->sip_value_start; 163 164 /* 165 * check for CRLF 166 */ 167 crlf = value->sip_value_end - strlen(SIP_CRLF); 168 while (crlf != NULL && strncmp(crlf, SIP_CRLF, strlen(SIP_CRLF)) == 0) { 169 vlen -= strlen(SIP_CRLF); 170 crlf -= strlen(SIP_CRLF); 171 } 172 rset->sip_dlg_route = calloc(1, vlen + 1); 173 if (rset->sip_dlg_route == NULL) { 174 free(rset); 175 return (NULL); 176 } 177 /* 178 * loose routing 179 */ 180 rset->sip_dlg_route_lr = B_FALSE; 181 (void) strncpy(rset->sip_dlg_route, value->sip_value_start, vlen); 182 rset->sip_dlg_ruri.sip_str_ptr = rset->sip_dlg_route + 183 (value->cftr_uri.sip_str_ptr - value->sip_value_start); 184 rset->sip_dlg_ruri.sip_str_len = value->cftr_uri.sip_str_len; 185 rset->sip_dlg_route[vlen] = '\0'; 186 187 assert(value->sip_value_parsed_uri != NULL); 188 /* 189 * Check if the 'lr' param is present for this route. 190 */ 191 uri_param = sip_get_uri_params(value->sip_value_parsed_uri, &error); 192 if (error != 0) { 193 free(rset->sip_dlg_route); 194 free(rset); 195 return (NULL); 196 } 197 if (uri_param != NULL) { 198 rset->sip_dlg_route_lr = sip_is_param_present(uri_param, "lr", 199 strlen("lr")); 200 } 201 return (rset); 202 } 203 204 /* 205 * Depending on the route-set, determine the request URI. 206 */ 207 char * 208 sip_dialog_req_uri(sip_dialog_t dialog) 209 { 210 const sip_str_t *req_uri; 211 char *uri; 212 _sip_dialog_t *_dialog; 213 214 _dialog = (_sip_dialog_t *)dialog; 215 if (_dialog->sip_dlg_route_set == NULL || 216 _dialog->sip_dlg_req_uri.sip_str_ptr == NULL) { 217 const struct sip_value *val; 218 219 val = sip_get_header_value(_dialog->sip_dlg_remote_target, 220 NULL); 221 if (val == NULL) 222 return (NULL); 223 req_uri = &((sip_hdr_value_t *)val)->cftr_uri; 224 } else { 225 req_uri = &_dialog->sip_dlg_req_uri; 226 } 227 uri = (char *)malloc(req_uri->sip_str_len + 1); 228 if (uri == NULL) 229 return (NULL); 230 (void) strncpy(uri, req_uri->sip_str_ptr, req_uri->sip_str_len); 231 uri[req_uri->sip_str_len] = '\0'; 232 233 return (uri); 234 } 235 236 /* 237 * Free the route set. 238 */ 239 void 240 sip_dialog_free_rset(sip_dlg_route_set_t *rset) 241 { 242 sip_dlg_route_set_t *next; 243 244 while (rset != NULL) { 245 next = rset->sip_dlg_route_next; 246 rset->sip_dlg_route_next = NULL; 247 free(rset->sip_dlg_route); 248 free(rset); 249 rset = next; 250 } 251 } 252 253 /* 254 * Recompute route-set 255 */ 256 static int 257 sip_dlg_recompute_rset(_sip_dialog_t *dialog, _sip_msg_t *sip_msg, int what) 258 { 259 int ret; 260 261 if (dialog->sip_dlg_route_set != NULL) { 262 sip_free_header(dialog->sip_dlg_route_set); 263 dialog->sip_dlg_route_set = NULL; 264 } 265 if (dialog->sip_dlg_req_uri.sip_str_ptr != NULL) { 266 free(dialog->sip_dlg_req_uri.sip_str_ptr); 267 dialog->sip_dlg_req_uri.sip_str_ptr = NULL; 268 dialog->sip_dlg_req_uri.sip_str_len = 0; 269 } 270 if (dialog->sip_dlg_rset.sip_str_ptr != NULL) { 271 free(dialog->sip_dlg_rset.sip_str_ptr); 272 dialog->sip_dlg_rset.sip_str_ptr = NULL; 273 dialog->sip_dlg_rset.sip_str_len = 0; 274 } 275 ret = sip_dialog_get_route_set(dialog, sip_msg, what); 276 return (ret); 277 } 278 279 /* 280 * If the route set is empty, the UAC MUST place the remote target URI 281 * into the Request-URI. The UAC MUST NOT add a Route header field to 282 * the request. 283 * 284 * If the route set is not empty, and the first URI in the route set 285 * contains the lr parameter (see Section 19.1.1), the UAC MUST place 286 * the remote target URI into the Request-URI and MUST include a Route 287 * header field containing the route set values in order, including all 288 * parameters. 289 * 290 * If the route set is not empty, and its first URI does not contain the 291 * lr parameter, the UAC MUST place the first URI from the route set 292 * into the Request-URI, stripping any parameters that are not allowed 293 * in a Request-URI. The UAC MUST add a Route header field containing 294 * the remainder of the route set values in order, including all 295 * parameters. The UAC MUST then place the remote target URI into the 296 * Route header field as the last value. 297 */ 298 int 299 sip_dialog_set_route_hdr(_sip_dialog_t *dialog, sip_dlg_route_set_t *rset_head, 300 int rcnt, int rlen) 301 { 302 size_t rset_len; 303 _sip_header_t *rhdr; 304 char *rset; 305 char *rp; 306 char *rsp; 307 int count; 308 sip_dlg_route_set_t *route; 309 boolean_t first = B_TRUE; 310 const sip_str_t *to_uri; 311 char *uri = NULL; 312 int rspl; 313 int rpl; 314 315 assert(rcnt > 0); 316 317 dialog->sip_dlg_rset.sip_str_len = rlen + rcnt - 1; 318 dialog->sip_dlg_rset.sip_str_ptr = malloc(rlen + rcnt); 319 if (dialog->sip_dlg_rset.sip_str_ptr == NULL) 320 return (ENOMEM); 321 rsp = dialog->sip_dlg_rset.sip_str_ptr; 322 rspl = rlen + rcnt; 323 route = rset_head; 324 rset_len = rlen; 325 if (!route->sip_dlg_route_lr) { 326 const struct sip_value *val; 327 328 val = sip_get_header_value(dialog->sip_dlg_remote_target, NULL); 329 to_uri = &((sip_hdr_value_t *)val)->cftr_uri; 330 uri = (char *)malloc(to_uri->sip_str_len + 1); 331 if (uri == NULL) { 332 free(dialog->sip_dlg_rset.sip_str_ptr); 333 dialog->sip_dlg_rset.sip_str_len = 0; 334 dialog->sip_dlg_rset.sip_str_ptr = NULL; 335 return (ENOMEM); 336 } 337 (void) strncpy(uri, to_uri->sip_str_ptr, to_uri->sip_str_len); 338 uri[to_uri->sip_str_len] = '\0'; 339 rset_len = rlen - strlen(route->sip_dlg_route) + strlen(uri) + 340 SIP_SPACE_LEN + sizeof (char) + SIP_SPACE_LEN + 341 sizeof (char); 342 count = snprintf(rsp, rspl, "%s", route->sip_dlg_route); 343 dialog->sip_dlg_req_uri.sip_str_ptr = malloc( 344 route->sip_dlg_ruri.sip_str_len + 1); 345 if (dialog->sip_dlg_req_uri.sip_str_ptr == NULL) { 346 free(uri); 347 free(dialog->sip_dlg_rset.sip_str_ptr); 348 dialog->sip_dlg_rset.sip_str_len = 0; 349 dialog->sip_dlg_rset.sip_str_ptr = NULL; 350 return (ENOMEM); 351 } 352 (void) strncpy(dialog->sip_dlg_req_uri.sip_str_ptr, rsp + 353 (route->sip_dlg_ruri.sip_str_ptr - route->sip_dlg_route), 354 route->sip_dlg_ruri.sip_str_len); 355 dialog->sip_dlg_req_uri.sip_str_ptr[ 356 route->sip_dlg_ruri.sip_str_len] = '\0'; 357 dialog->sip_dlg_req_uri.sip_str_len = 358 route->sip_dlg_ruri.sip_str_len; 359 360 rsp += count; 361 rspl -= count; 362 route = route->sip_dlg_route_next; 363 } 364 365 /* 366 * rcnt - 1 is for the number of COMMAs 367 */ 368 rset_len += strlen(SIP_ROUTE) + SIP_SPACE_LEN + sizeof (char) + 369 SIP_SPACE_LEN + rcnt - 1; 370 rset = malloc(rset_len + 1); 371 if (rset == NULL) { 372 free(dialog->sip_dlg_rset.sip_str_ptr); 373 dialog->sip_dlg_rset.sip_str_len = 0; 374 dialog->sip_dlg_rset.sip_str_ptr = NULL; 375 return (ENOMEM); 376 } 377 rhdr = sip_new_header(rset_len + strlen(SIP_CRLF)); 378 if (rhdr == NULL) { 379 free(rset); 380 free(dialog->sip_dlg_rset.sip_str_ptr); 381 dialog->sip_dlg_rset.sip_str_len = 0; 382 dialog->sip_dlg_rset.sip_str_ptr = NULL; 383 return (ENOMEM); 384 } 385 386 rp = rset; 387 rpl = rset_len + 1; 388 count = snprintf(rp, rpl, "%s %c ", SIP_ROUTE, SIP_HCOLON); 389 rp += count; 390 rpl -= count; 391 392 while (route != NULL) { 393 if (first) { 394 count = snprintf(rp, rpl, "%s", route->sip_dlg_route); 395 rp += count; 396 rpl -= count; 397 first = B_FALSE; 398 if (uri != NULL) { 399 count = snprintf(rsp, rspl, "%c%s", 400 SIP_COMMA, route->sip_dlg_route); 401 } else { 402 count = snprintf(rsp, rspl, "%s", 403 route->sip_dlg_route); 404 } 405 rsp += count; 406 rspl -= count; 407 } else { 408 count = snprintf(rp, rpl, "%c%s", SIP_COMMA, 409 route->sip_dlg_route); 410 rp += count; 411 rpl -= count; 412 count = snprintf(rsp, rspl, "%c%s", SIP_COMMA, 413 route->sip_dlg_route); 414 rsp += count; 415 rspl -= count; 416 } 417 route = route->sip_dlg_route_next; 418 } 419 assert(rsp <= dialog->sip_dlg_rset.sip_str_ptr + 420 dialog->sip_dlg_rset.sip_str_len); 421 dialog->sip_dlg_rset.sip_str_ptr[dialog->sip_dlg_rset.sip_str_len] = 422 '\0'; 423 if (uri != NULL) { 424 if (first) { 425 count = snprintf(rp, rpl, "%c %s %c", SIP_LAQUOT, 426 uri, SIP_RAQUOT); 427 } else { 428 count = snprintf(rp, rpl, "%c%c %s %c", SIP_COMMA, 429 SIP_LAQUOT, uri, SIP_RAQUOT); 430 } 431 rp += count; 432 rpl -= count; 433 free(uri); 434 } 435 assert(rp <= rset + rset_len); 436 (void) snprintf(rhdr->sip_hdr_start, rset_len + strlen(SIP_CRLF) + 1, 437 "%s%s", rset, SIP_CRLF); 438 free(rset); 439 dialog->sip_dlg_route_set = (sip_header_t)rhdr; 440 sip_dialog_free_rset(rset_head); 441 return (0); 442 } 443 444 /* 445 * UAC Behavior 446 * The route set MUST be set to the list of URIs in the Record-Route 447 * header field from the response, taken in reverse order and preserving 448 * all URI parameters. 449 * 450 * UAS behavior 451 * The route set MUST be set to the list of URIs in the Record-Route 452 * header field from the request, taken in order and preserving all URI 453 * parameters. 454 */ 455 static int 456 sip_dialog_get_route_set(_sip_dialog_t *dialog, _sip_msg_t *sip_msg, int what) 457 { 458 sip_header_t rrhdr; 459 sip_hdr_value_t *value; 460 int error; 461 sip_dlg_route_set_t *rset_head = NULL; 462 sip_dlg_route_set_t *rset_tail = NULL; 463 sip_dlg_route_set_t *rset; 464 int rset_cnt = 0; 465 int rset_len = 0; 466 467 (void) pthread_mutex_lock(&sip_msg->sip_msg_mutex); 468 rrhdr = sip_search_for_header(sip_msg, SIP_RECORD_ROUTE, NULL); 469 while (rrhdr != NULL) { 470 (void) pthread_mutex_unlock(&sip_msg->sip_msg_mutex); 471 value = (sip_hdr_value_t *)sip_get_header_value(rrhdr, &error); 472 while (value != NULL && error == 0) { 473 char *crlf; 474 475 if (value->sip_value_state == SIP_VALUE_BAD) { 476 value = (sip_hdr_value_t *)sip_get_next_value( 477 (sip_header_value_t)value, &error); 478 continue; 479 } 480 rset = sip_add_route_to_set(value); 481 if (rset == NULL) 482 goto r_error; 483 /* 484 * Add one for COMMA 485 */ 486 rset_cnt++; 487 rset_len += (value->sip_value_end - 488 value->sip_value_start); 489 /* 490 * Check for CRLF 491 */ 492 crlf = value->sip_value_end - strlen(SIP_CRLF); 493 while (crlf != NULL && 494 strncmp(crlf, SIP_CRLF, strlen(SIP_CRLF)) == 0) { 495 rset_len -= strlen(SIP_CRLF); 496 crlf -= strlen(SIP_CRLF); 497 } 498 if (rset_head == NULL) { 499 assert(rset_tail == NULL); 500 rset_head = rset_tail = rset; 501 } else if (what == SIP_UAS_DIALOG) { 502 rset_tail->sip_dlg_route_next = rset; 503 rset_tail = rset; 504 } else if (what == SIP_UAC_DIALOG) { 505 rset->sip_dlg_route_next = rset_head; 506 rset_head = rset; 507 } else { 508 assert(0); 509 } 510 value = (sip_hdr_value_t *)sip_get_next_value( 511 (sip_header_value_t)value, &error); 512 } 513 (void) pthread_mutex_lock(&sip_msg->sip_msg_mutex); 514 rrhdr = sip_search_for_header(sip_msg, SIP_RECORD_ROUTE, rrhdr); 515 } 516 (void) pthread_mutex_unlock(&sip_msg->sip_msg_mutex); 517 if (rset_cnt == 0) 518 return (0); 519 if (sip_dialog_set_route_hdr(dialog, rset_head, rset_cnt, 520 rset_len) != 0) { 521 goto r_error; 522 } 523 return (0); 524 r_error: 525 sip_dialog_free_rset(rset_head); 526 return (ENOMEM); 527 } 528 529 /* 530 * UAS behavior: 531 * The remote sequence number MUST be set to the value of the sequence 532 * number in the CSeq header field of the request. The local sequence 533 * number MUST be empty. The call identifier component of the dialog ID 534 * MUST be set to the value of the Call-ID in the request. The local 535 * tag component of the dialog ID MUST be set to the tag in the To field 536 * in the response to the request (which always includes a tag), and the 537 * remote tag component of the dialog ID MUST be set to the tag from the 538 * From field in the request. A UAS MUST be prepared to receive a 539 * request without a tag in the From field, in which case the tag is 540 * considered to have a value of null. 541 * The remote URI MUST be set to the URI in the From field, and the 542 * local URI MUST be set to the URI in the To field. 543 * The remote target MUST be set to the URI from the Contact header field 544 * of the request. 545 * 546 * UAC behavior: 547 * The local sequence number MUST be set to the value of the sequence 548 * number in the CSeq header field of the request. The remote sequence 549 * number MUST be empty (it is established when the remote UA sends a 550 * request within the dialog). The call identifier component of the 551 * dialog ID MUST be set to the value of the Call-ID in the request. 552 * The local tag component of the dialog ID MUST be set to the tag in 553 * the From field in the request, and the remote tag component of the 554 * dialog ID MUST be set to the tag in the To field of the response. A 555 * UAC MUST be prepared to receive a response without a tag in the To 556 * field, in which case the tag is considered to have a value of null. 557 * The remote URI MUST be set to the URI in the To field, and the local 558 * URI MUST be set to the URI in the From field. 559 * The remote target MUST be set to the URI from the Contact header field 560 * of the response. 561 */ 562 563 564 /* 565 * This is the routine that seeds a dialog. 566 */ 567 sip_dialog_t 568 sip_seed_dialog(sip_conn_object_t obj, _sip_msg_t *sip_msg, 569 boolean_t dlg_on_fork, int dlg_type) 570 { 571 _sip_dialog_t *dialog; 572 int cseq; 573 sip_header_t fhdr = NULL; 574 sip_header_t thdr = NULL; 575 sip_header_t chdr; 576 sip_header_t cihdr; 577 sip_header_t evhdr = NULL; 578 const struct sip_value *value; 579 sip_dialog_timer_obj_t *tim_obj = NULL; 580 const sip_str_t *callid; 581 sip_method_t method; 582 int timer1 = sip_timer_T1; 583 int error; 584 585 if (!sip_msg_is_request((sip_msg_t)sip_msg, &error)) 586 return (NULL); 587 588 method = sip_get_request_method((sip_msg_t)sip_msg, &error); 589 /* 590 * Only INVITE and SUBSCRIBE supported 591 */ 592 if (error != 0 || (method != INVITE && method != SUBSCRIBE)) 593 return (NULL); 594 595 /* 596 * A request outside of a dialog MUST NOT contain a To tag 597 */ 598 if (sip_get_to_tag((sip_msg_t)sip_msg, NULL) != NULL) 599 return (NULL); 600 601 if (dlg_type == SIP_UAS_DIALOG) { 602 thdr = sip_dlg_xchg_from_to((sip_msg_t)sip_msg, 603 SIP_DLG_XCHG_FROM); 604 (void) pthread_mutex_lock(&sip_msg->sip_msg_mutex); 605 } else { 606 (void) pthread_mutex_lock(&sip_msg->sip_msg_mutex); 607 fhdr = sip_search_for_header(sip_msg, SIP_FROM, NULL); 608 } 609 cihdr = sip_search_for_header(sip_msg, SIP_CALL_ID, NULL); 610 chdr = sip_search_for_header(sip_msg, SIP_CONTACT, NULL); 611 if (method == SUBSCRIBE) 612 evhdr = sip_search_for_header(sip_msg, SIP_EVENT, NULL); 613 (void) pthread_mutex_unlock(&sip_msg->sip_msg_mutex); 614 if ((fhdr == NULL && thdr == NULL) || cihdr == NULL || chdr == NULL || 615 (method == SUBSCRIBE && evhdr == NULL)) { 616 if (thdr != NULL) 617 sip_free_header(thdr); 618 return (NULL); 619 } 620 621 /* 622 * Sanity check since we just store the headers in the dialog 623 */ 624 if (sip_get_from_tag((sip_msg_t)sip_msg, NULL) == NULL || 625 sip_get_from_uri_str((sip_msg_t)sip_msg, NULL) == NULL || 626 ((cseq = sip_get_callseq_num((sip_msg_t)sip_msg, NULL)) == -1) || 627 (callid = sip_get_callid((sip_msg_t)sip_msg, NULL)) == NULL || 628 sip_get_to_uri_str((sip_msg_t)sip_msg, NULL) == NULL || 629 ((value = sip_get_header_value(chdr, NULL)) == NULL) || 630 sip_get_contact_uri_str((sip_header_value_t)value, NULL) == NULL) { 631 if (thdr != NULL) 632 sip_free_header(thdr); 633 return (NULL); 634 } 635 636 tim_obj = calloc(1, sizeof (sip_dialog_timer_obj_t)); 637 if (tim_obj == NULL) { 638 if (thdr != NULL) 639 sip_free_header(thdr); 640 return (NULL); 641 } 642 dialog = calloc(1, sizeof (_sip_dialog_t)); 643 if (dialog == NULL) { 644 if (thdr != NULL) 645 sip_free_header(thdr); 646 return (NULL); 647 } 648 /* 649 * We will take the TO header with the tag when we complete this 650 * dialog 651 */ 652 if (dlg_type == SIP_UAS_DIALOG) { 653 dialog->sip_dlg_remote_uri_tag = thdr; 654 /* 655 * We take the remote target from the incoming request on the 656 * UAS. For the UAC, we will take it from the response. 657 */ 658 if ((dialog->sip_dlg_remote_target = sip_dup_header(chdr)) == 659 NULL) { 660 goto dia_err; 661 } 662 } else { 663 if ((dialog->sip_dlg_local_uri_tag = sip_dup_header(fhdr)) == 664 NULL) { 665 goto dia_err; 666 } 667 /* 668 * We take the local contact from the originating request on 669 * UAC. For the UAS, we will take it from the response. 670 */ 671 if ((dialog->sip_dlg_local_contact = sip_dup_header(chdr)) == 672 NULL) { 673 goto dia_err; 674 } else { 675 dialog->sip_dlg_new_local_contact = NULL; 676 } 677 } 678 if ((dialog->sip_dlg_call_id = sip_dup_header(cihdr)) == NULL) 679 goto dia_err; 680 if (method == SUBSCRIBE) { 681 dialog->sip_dlg_event = sip_dup_header(evhdr); 682 if (dialog->sip_dlg_event == NULL) { 683 goto dia_err; 684 } 685 } 686 dialog->sip_dlg_rset.sip_str_ptr = NULL; 687 dialog->sip_dlg_rset.sip_str_len = 0; 688 dialog->sip_dlg_req_uri.sip_str_ptr = NULL; 689 dialog->sip_dlg_req_uri.sip_str_len = 0; 690 /* 691 * Get the route set from the request, if present 692 */ 693 if (dlg_type == SIP_UAS_DIALOG && 694 sip_dialog_get_route_set(dialog, sip_msg, dlg_type) != 0) { 695 goto dia_err; 696 } 697 if (dlg_type == SIP_UAC_DIALOG) 698 dialog->sip_dlg_local_cseq = cseq; 699 else 700 dialog->sip_dlg_remote_cseq = cseq; 701 dialog->sip_dlg_type = dlg_type; 702 dialog->sip_dlg_on_fork = dlg_on_fork; 703 dialog->sip_dlg_method = method; 704 /* 705 * Set the partial dialog timer with the INVITE timeout val 706 */ 707 if (sip_conn_timer1 != NULL) 708 timer1 = sip_conn_timer1(obj); 709 SIP_INIT_TIMER(dialog->sip_dlg_timer, 64 * timer1); 710 tim_obj->dialog = dialog; 711 /* 712 * Since at the client we never pass the partial dialog, we need not 713 * invoke the callback when the partial dialog self-destructs. 714 */ 715 if (dlg_type == SIP_UAS_DIALOG) 716 tim_obj->func = sip_ulp_dlg_del_cb; 717 SIP_SCHED_TIMER(dialog->sip_dlg_timer, (void *)tim_obj, 718 sip_dlg_self_destruct); 719 if (!SIP_IS_TIMER_RUNNING(dialog->sip_dlg_timer)) 720 goto dia_err; 721 (void) pthread_mutex_init(&dialog->sip_dlg_mutex, NULL); 722 723 if (dlg_type == SIP_UAC_DIALOG) { 724 const sip_str_t *local_tag; 725 726 local_tag = sip_get_from_tag((sip_msg_t)sip_msg, NULL); 727 assert(local_tag != NULL); 728 sip_md5_hash(local_tag->sip_str_ptr, local_tag->sip_str_len, 729 callid->sip_str_ptr, callid->sip_str_len, 730 NULL, 0, NULL, 0, NULL, 0, NULL, 0, 731 (uchar_t *)dialog->sip_dlg_id); 732 733 734 /* 735 * Add it to the partial hash table 736 */ 737 if (sip_hash_add(sip_dialog_phash, (void *)dialog, 738 SIP_DIGEST_TO_HASH(dialog->sip_dlg_id)) != 0) { 739 goto dia_err; 740 } 741 } 742 SIP_DLG_REFCNT_INCR(dialog); 743 return ((sip_dialog_t)dialog); 744 dia_err: 745 sip_release_dialog_res(dialog); 746 if (SIP_IS_TIMER_RUNNING(dialog->sip_dlg_timer)) 747 SIP_CANCEL_TIMER(dialog->sip_dlg_timer); 748 if (tim_obj != NULL) 749 free(tim_obj); 750 return (NULL); 751 } 752 753 /* 754 * When creating a dialog from a NOTIFY request, we need to get the FROM 755 * header for the dialog from the TO header of the NOTIFY. 756 */ 757 _sip_header_t * 758 sip_dlg_xchg_from_to(sip_msg_t sip_msg, int what) 759 { 760 int len; 761 _sip_header_t *newhdr; 762 int cnt; 763 const struct sip_header *hdr; 764 int hdrsize; 765 int error; 766 767 hdr = sip_get_header(sip_msg, what == SIP_DLG_XCHG_FROM ? SIP_FROM : 768 SIP_TO, NULL, &error); 769 if (error != 0 || hdr == NULL) 770 return (NULL); 771 if (sip_parse_goto_values((_sip_header_t *)hdr) != 0) 772 return (NULL); 773 len = hdr->sip_hdr_end - hdr->sip_hdr_current; 774 if (what == SIP_DLG_XCHG_FROM) { 775 hdrsize = len + strlen(SIP_TO) + SIP_SPACE_LEN + sizeof (char) + 776 SIP_SPACE_LEN; 777 } else { 778 hdrsize = len + strlen(SIP_FROM) + SIP_SPACE_LEN + 779 sizeof (char) + SIP_SPACE_LEN; 780 } 781 newhdr = sip_new_header(hdrsize); 782 if (newhdr == NULL) 783 return (NULL); 784 if (what == SIP_DLG_XCHG_FROM) { 785 cnt = snprintf(newhdr->sip_hdr_current, hdrsize + 1, 786 "%s %c ", SIP_TO, SIP_HCOLON); 787 } else { 788 cnt = snprintf(newhdr->sip_hdr_current, hdrsize + 1, 789 "%s %c ", SIP_FROM, SIP_HCOLON); 790 } 791 newhdr->sip_hdr_current += cnt; 792 (void) strncpy(newhdr->sip_hdr_current, hdr->sip_hdr_current, len); 793 newhdr->sip_hdr_current += len; 794 assert(newhdr->sip_hdr_current == newhdr->sip_hdr_end); 795 assert(hdr->sip_header_functions != NULL); 796 797 /* 798 * FROM and TO have common parsing functions 799 */ 800 newhdr->sip_header_functions = hdr->sip_header_functions; 801 newhdr->sip_hdr_current = newhdr->sip_hdr_start; 802 803 return (newhdr); 804 } 805 806 /* 807 * This is the response that completes the dialog that was created 808 * in sip_seed_dialog(). 809 */ 810 sip_dialog_t 811 sip_complete_dialog(_sip_msg_t *sip_msg, _sip_dialog_t *dialog) 812 { 813 _sip_header_t *thdr; 814 _sip_header_t *evhdr = NULL; 815 _sip_header_t *substate = NULL; 816 sip_header_t chdr = NULL; 817 int resp_code; 818 const sip_str_t *ttag; 819 const sip_str_t *remtag; 820 const sip_str_t *callid; 821 const struct sip_value *val; 822 sip_method_t method; 823 int error = 0; 824 int prev_state; 825 boolean_t alloc_thdr = B_FALSE; 826 827 if (sip_msg_is_request((sip_msg_t)sip_msg, &error) && error == 0) 828 method = sip_get_request_method((sip_msg_t)sip_msg, &error); 829 else 830 method = sip_get_callseq_method((sip_msg_t)sip_msg, &error); 831 if (error != 0 || dialog == NULL || 832 (sip_msg_is_request((sip_msg_t)sip_msg, &error) && 833 (dialog->sip_dlg_method == INVITE || method != NOTIFY))) { 834 return (NULL); 835 } 836 if ((dialog->sip_dlg_type == SIP_UAC_DIALOG && method != NOTIFY && 837 sip_get_callseq_num((sip_msg_t)sip_msg, NULL) != 838 dialog->sip_dlg_local_cseq) || 839 (dialog->sip_dlg_type == SIP_UAS_DIALOG && method != NOTIFY && 840 sip_get_callseq_num((sip_msg_t)sip_msg, NULL) != 841 dialog->sip_dlg_remote_cseq)) { 842 return (NULL); 843 } 844 if (method == NOTIFY) { 845 const sip_str_t *sstate; 846 847 thdr = sip_dlg_xchg_from_to((sip_msg_t)sip_msg, 848 SIP_DLG_XCHG_FROM); 849 if (thdr == NULL) 850 return (NULL); 851 alloc_thdr = B_TRUE; 852 (void) pthread_mutex_lock(&sip_msg->sip_msg_mutex); 853 chdr = sip_search_for_header(sip_msg, SIP_CONTACT, NULL); 854 if (chdr == NULL) { 855 (void) pthread_mutex_unlock(&sip_msg->sip_msg_mutex); 856 sip_free_header(thdr); 857 return (NULL); 858 } 859 evhdr = sip_search_for_header(sip_msg, SIP_EVENT, NULL); 860 if (evhdr == NULL) { 861 (void) pthread_mutex_unlock(&sip_msg->sip_msg_mutex); 862 sip_free_header(thdr); 863 return (NULL); 864 } 865 substate = sip_search_for_header(sip_msg, 866 SIP_SUBSCRIPTION_STATE, NULL); 867 if (substate == NULL) { 868 (void) pthread_mutex_unlock(&sip_msg->sip_msg_mutex); 869 sip_free_header(thdr); 870 return (NULL); 871 } 872 (void) pthread_mutex_unlock(&sip_msg->sip_msg_mutex); 873 sstate = sip_get_substate((sip_msg_t)sip_msg, &error); 874 if (sstate == NULL || error != 0) { 875 sip_free_header(thdr); 876 return (NULL); 877 } 878 if ((sstate->sip_str_len != strlen("pending") && 879 sstate->sip_str_len != strlen("active")) || 880 ((sstate->sip_str_len == strlen("pending") && 881 strncasecmp(sstate->sip_str_ptr, "pending", 882 strlen("pending")) != 0) || 883 (sstate->sip_str_len == strlen("active") && 884 strncasecmp(sstate->sip_str_ptr, "active", 885 strlen("active")) != 0))) { 886 sip_free_header(thdr); 887 return (NULL); 888 } 889 ttag = sip_get_from_tag((sip_msg_t)sip_msg, NULL); 890 } else { 891 if (dialog->sip_dlg_type == SIP_UAS_DIALOG) { 892 thdr = sip_dlg_xchg_from_to((sip_msg_t)sip_msg, 893 SIP_DLG_XCHG_TO); 894 alloc_thdr = B_TRUE; 895 } else { 896 (void) pthread_mutex_lock(&sip_msg->sip_msg_mutex); 897 thdr = sip_search_for_header(sip_msg, SIP_TO, NULL); 898 if (dialog->sip_dlg_remote_target == NULL) { 899 chdr = sip_search_for_header(sip_msg, 900 SIP_CONTACT, NULL); 901 } 902 (void) pthread_mutex_unlock(&sip_msg->sip_msg_mutex); 903 } 904 if (thdr == NULL) { 905 (void) pthread_mutex_unlock(&sip_msg->sip_msg_mutex); 906 return (NULL); 907 } 908 ttag = sip_get_to_tag((sip_msg_t)sip_msg, NULL); 909 } 910 if (ttag == NULL) { 911 if (alloc_thdr) 912 sip_free_header(thdr); 913 return (NULL); 914 } 915 prev_state = dialog->sip_dlg_state; 916 917 if (method == NOTIFY) { 918 int error; 919 const sip_str_t *dlg_id_val = NULL; 920 const sip_str_t *event; 921 const sip_str_t *id_val = NULL; 922 sip_header_value_t ev_val; 923 sip_hdr_value_t *dlg_ev_val = NULL; 924 925 event = sip_get_event((sip_msg_t)sip_msg, &error); 926 if (event == NULL || error != 0) { 927 sip_free_header(thdr); 928 return (NULL); 929 } 930 ev_val = (sip_header_value_t)sip_get_header_value(evhdr, 931 &error); 932 if (ev_val != NULL) 933 id_val = sip_get_param_value(ev_val, "id", &error); 934 if (error == 0) { 935 dlg_ev_val = (sip_hdr_value_t *)sip_get_header_value( 936 dialog->sip_dlg_event, &error); 937 } 938 if (dlg_ev_val == NULL || error != 0) { 939 sip_free_header(thdr); 940 return (NULL); 941 } 942 dlg_id_val = sip_get_param_value((sip_header_value_t)dlg_ev_val, 943 "id", &error); 944 if (error != 0 || 945 dlg_ev_val->str_val_len != event->sip_str_len || 946 strncmp(dlg_ev_val->str_val_ptr, event->sip_str_ptr, 947 event->sip_str_len != 0)) { 948 sip_free_header(thdr); 949 return (NULL); 950 } 951 if ((dlg_id_val == NULL && id_val != NULL) || 952 (dlg_id_val != NULL && id_val == NULL)) { 953 sip_free_header(thdr); 954 return (NULL); 955 } else if (dlg_id_val != NULL && id_val != NULL) { 956 if (dlg_id_val->sip_str_len != id_val->sip_str_len || 957 strncasecmp(dlg_id_val->sip_str_ptr, 958 id_val->sip_str_ptr, dlg_id_val->sip_str_len) != 959 0) { 960 sip_free_header(thdr); 961 return (NULL); 962 } 963 } 964 if (dialog->sip_dlg_type == SIP_UAC_DIALOG) { 965 dialog->sip_dlg_remote_uri_tag = thdr; 966 if ((dialog->sip_dlg_remote_target = 967 sip_dup_header(chdr)) == NULL) { 968 sip_free_header(thdr); 969 return (NULL); 970 } 971 } else { 972 dialog->sip_dlg_local_uri_tag = thdr; 973 } 974 dialog->sip_dlg_state = SIP_DLG_CONFIRMED; 975 } else { 976 resp_code = sip_get_response_code((sip_msg_t)sip_msg, &error); 977 (void) pthread_mutex_lock(&dialog->sip_dlg_mutex); 978 assert(dialog->sip_dlg_state == SIP_DLG_NEW); 979 if (dialog->sip_dlg_remote_target == NULL && chdr != NULL) { 980 assert(dialog->sip_dlg_type == SIP_UAC_DIALOG); 981 if ((dialog->sip_dlg_remote_target = 982 sip_dup_header(chdr)) == NULL) { 983 (void) pthread_mutex_unlock( 984 &dialog->sip_dlg_mutex); 985 if (alloc_thdr) 986 sip_free_header(thdr); 987 goto terminate_new_dlg; 988 } 989 if (sip_dialog_get_route_set(dialog, sip_msg, 990 dialog->sip_dlg_type) != 0) { 991 (void) pthread_mutex_unlock( 992 &dialog->sip_dlg_mutex); 993 if (alloc_thdr) 994 sip_free_header(thdr); 995 goto terminate_new_dlg; 996 } 997 } 998 if (SIP_PROVISIONAL_RESP(resp_code)) { 999 dialog->sip_dlg_state = SIP_DLG_EARLY; 1000 } else if (SIP_OK_RESP(resp_code)) { 1001 /* 1002 * Per 12.1 the UAS must include the contact header 1003 * for a dialog establishing response, so if we 1004 * don't find one, we terminate it. 1005 */ 1006 if (dialog->sip_dlg_remote_target == NULL) { 1007 (void) pthread_mutex_unlock( 1008 &dialog->sip_dlg_mutex); 1009 if (sip_ulp_dlg_del_cb != NULL) { 1010 sip_ulp_dlg_del_cb(dialog, 1011 (sip_msg_t)sip_msg, NULL); 1012 } 1013 if (alloc_thdr) 1014 sip_free_header(thdr); 1015 goto terminate_new_dlg; 1016 } 1017 dialog->sip_dlg_state = SIP_DLG_CONFIRMED; 1018 } else { 1019 (void) pthread_mutex_unlock(&dialog->sip_dlg_mutex); 1020 if (sip_ulp_dlg_del_cb != NULL) { 1021 sip_ulp_dlg_del_cb(dialog, (sip_msg_t)sip_msg, 1022 NULL); 1023 } 1024 if (alloc_thdr) 1025 sip_free_header(thdr); 1026 goto terminate_new_dlg; 1027 } 1028 if (dialog->sip_dlg_type == SIP_UAS_DIALOG) { 1029 dialog->sip_dlg_local_uri_tag = thdr; 1030 } else { 1031 if ((dialog->sip_dlg_remote_uri_tag = 1032 sip_dup_header(thdr)) == NULL) { 1033 (void) pthread_mutex_unlock( 1034 &dialog->sip_dlg_mutex); 1035 goto terminate_new_dlg; 1036 } 1037 } 1038 } 1039 1040 /* 1041 * We take the local contact for UAS Dialog from the response (either 1042 * NOTIFY for SUBSCRIBE request or from final response 2xx to INVITE 1043 * request) 1044 */ 1045 if ((dialog->sip_dlg_type == SIP_UAS_DIALOG) && (dialog->sip_dlg_state 1046 == SIP_DLG_CONFIRMED)) { 1047 if (chdr == NULL) { 1048 (void) pthread_mutex_lock(&sip_msg->sip_msg_mutex); 1049 chdr = sip_search_for_header(sip_msg, SIP_CONTACT, 1050 NULL); 1051 (void) pthread_mutex_unlock(&sip_msg->sip_msg_mutex); 1052 } 1053 if ((chdr == NULL) || ((dialog->sip_dlg_local_contact = 1054 sip_dup_header(chdr)) == NULL)) { 1055 (void) pthread_mutex_unlock(&dialog->sip_dlg_mutex); 1056 if (alloc_thdr) 1057 sip_free_header(thdr); 1058 goto terminate_new_dlg; 1059 } 1060 } 1061 1062 /* 1063 * Cancel the partial dialog timer 1064 */ 1065 if (SIP_IS_TIMER_RUNNING(dialog->sip_dlg_timer)) 1066 SIP_CANCEL_TIMER(dialog->sip_dlg_timer); 1067 1068 if (dialog->sip_dlg_type == SIP_UAC_DIALOG) { 1069 val = sip_get_header_value(dialog->sip_dlg_local_uri_tag, 1070 &error); 1071 } else { 1072 val = sip_get_header_value(dialog->sip_dlg_remote_uri_tag, 1073 &error); 1074 } 1075 assert(val != NULL && error == 0); 1076 remtag = sip_get_param_value((sip_header_value_t)val, "tag", &error); 1077 1078 val = sip_get_header_value(dialog->sip_dlg_call_id, &error); 1079 callid = &((sip_hdr_value_t *)val)->str_val; 1080 1081 /* 1082 * Get an ID for this dialog 1083 */ 1084 if (dialog->sip_dlg_type == SIP_UAC_DIALOG) { 1085 sip_md5_hash(remtag->sip_str_ptr, remtag->sip_str_len, 1086 ttag->sip_str_ptr, ttag->sip_str_len, 1087 callid->sip_str_ptr, callid->sip_str_len, 1088 NULL, 0, NULL, 0, NULL, 0, (uchar_t *)dialog->sip_dlg_id); 1089 } else { 1090 sip_md5_hash(ttag->sip_str_ptr, ttag->sip_str_len, 1091 remtag->sip_str_ptr, remtag->sip_str_len, 1092 callid->sip_str_ptr, callid->sip_str_len, 1093 NULL, 0, NULL, 0, NULL, 0, (uchar_t *)dialog->sip_dlg_id); 1094 } 1095 1096 SIP_DLG_REFCNT_INCR(dialog); 1097 (void) pthread_mutex_unlock(&dialog->sip_dlg_mutex); 1098 1099 /* 1100 * Add it to the hash table 1101 */ 1102 if (sip_hash_add(sip_dialog_hash, (void *)dialog, 1103 SIP_DIGEST_TO_HASH(dialog->sip_dlg_id)) != 0) { 1104 terminate_new_dlg: 1105 /* 1106 * So that sip_dialog_delete() does not try to remove 1107 * this from the hash table. 1108 */ 1109 (void) pthread_mutex_lock(&dialog->sip_dlg_mutex); 1110 if (dialog->sip_dlg_type == SIP_UAS_DIALOG) { 1111 if (dialog->sip_dlg_local_uri_tag != NULL) { 1112 sip_free_header(dialog->sip_dlg_local_uri_tag); 1113 dialog->sip_dlg_local_uri_tag = NULL; 1114 } 1115 } else { 1116 if (dialog->sip_dlg_remote_uri_tag != NULL) { 1117 sip_free_header(dialog->sip_dlg_remote_uri_tag); 1118 dialog->sip_dlg_remote_uri_tag = NULL; 1119 } 1120 } 1121 (void) pthread_mutex_unlock(&dialog->sip_dlg_mutex); 1122 sip_dialog_terminate(dialog, (sip_msg_t)sip_msg); 1123 return (NULL); 1124 } 1125 if (sip_dlg_ulp_state_cb != NULL) { 1126 sip_dlg_ulp_state_cb((sip_dialog_t)dialog, 1127 (sip_msg_t)sip_msg, prev_state, dialog->sip_dlg_state); 1128 } 1129 return ((sip_dialog_t)dialog); 1130 } 1131 1132 /* 1133 * Check if this dialog is a match. 1134 */ 1135 boolean_t 1136 sip_dialog_match(void *obj, void *hindex) 1137 { 1138 _sip_dialog_t *dialog = (_sip_dialog_t *)obj; 1139 1140 (void) pthread_mutex_lock(&dialog->sip_dlg_mutex); 1141 if (dialog->sip_dlg_state == SIP_DLG_DESTROYED) { 1142 (void) pthread_mutex_unlock(&dialog->sip_dlg_mutex); 1143 return (B_FALSE); 1144 } 1145 if (bcmp(dialog->sip_dlg_id, hindex, 1146 sizeof (dialog->sip_dlg_id)) == 0) { 1147 SIP_DLG_REFCNT_INCR(dialog); 1148 (void) pthread_mutex_unlock(&dialog->sip_dlg_mutex); 1149 return (B_TRUE); 1150 } 1151 (void) pthread_mutex_unlock(&dialog->sip_dlg_mutex); 1152 return (B_FALSE); 1153 } 1154 1155 /* 1156 * Don't delete, just take it out of the hash 1157 */ 1158 boolean_t 1159 sip_dialog_dontfree(void *obj, void *hindex, int *found) 1160 { 1161 _sip_dialog_t *dialog = (_sip_dialog_t *)obj; 1162 1163 *found = 0; 1164 (void) pthread_mutex_lock(&dialog->sip_dlg_mutex); 1165 if (bcmp(dialog->sip_dlg_id, hindex, sizeof (dialog->sip_dlg_id)) 1166 == 0) { 1167 *found = 1; 1168 (void) pthread_mutex_unlock(&dialog->sip_dlg_mutex); 1169 return (B_TRUE); 1170 } 1171 (void) pthread_mutex_unlock(&dialog->sip_dlg_mutex); 1172 return (B_FALSE); 1173 } 1174 1175 /* 1176 * Free resources associated with the dialog, the object will be removed 1177 * from the hash list by sip_hash_delete. 1178 */ 1179 boolean_t 1180 sip_dialog_free(void *obj, void *hindex, int *found) 1181 { 1182 _sip_dialog_t *dialog = (_sip_dialog_t *)obj; 1183 1184 *found = 0; 1185 (void) pthread_mutex_lock(&dialog->sip_dlg_mutex); 1186 if (bcmp(dialog->sip_dlg_id, hindex, sizeof (dialog->sip_dlg_id)) 1187 == 0) { 1188 *found = 1; 1189 assert(dialog->sip_dlg_state == SIP_DLG_DESTROYED); 1190 if (dialog->sip_dlg_ref_cnt != 0) { 1191 (void) pthread_mutex_unlock(&dialog->sip_dlg_mutex); 1192 return (B_FALSE); 1193 } 1194 sip_release_dialog_res(dialog); 1195 return (B_TRUE); 1196 } 1197 (void) pthread_mutex_unlock(&dialog->sip_dlg_mutex); 1198 return (B_FALSE); 1199 } 1200 1201 /* 1202 * The UAS will receive the request from the transaction layer. If the 1203 * request has a tag in the To header field, the UAS core computes the 1204 * dialog identifier corresponding to the request and compares it with 1205 * existing dialogs. If there is a match, this is a mid-dialog request. 1206 */ 1207 sip_dialog_t 1208 sip_dialog_find(_sip_msg_t *sip_msg) 1209 { 1210 const sip_str_t *localtag; 1211 const sip_str_t *remtag; 1212 const sip_str_t *callid; 1213 uint16_t digest[8]; 1214 _sip_dialog_t *dialog; 1215 boolean_t is_request; 1216 int error; 1217 1218 is_request = sip_msg_is_request((sip_msg_t)sip_msg, &error); 1219 if (error != 0) 1220 return (NULL); 1221 if (is_request) { 1222 localtag = sip_get_to_tag((sip_msg_t)sip_msg, &error); 1223 if (error == 0) 1224 remtag = sip_get_from_tag((sip_msg_t)sip_msg, &error); 1225 } else { 1226 remtag = sip_get_to_tag((sip_msg_t)sip_msg, &error); 1227 if (error == 0) 1228 localtag = sip_get_from_tag((sip_msg_t)sip_msg, &error); 1229 } 1230 if (error != 0) 1231 return (NULL); 1232 callid = sip_get_callid((sip_msg_t)sip_msg, &error); 1233 if (error != 0 || remtag == NULL || localtag == NULL || 1234 callid == NULL) { 1235 return (NULL); 1236 } 1237 sip_md5_hash(localtag->sip_str_ptr, localtag->sip_str_len, 1238 remtag->sip_str_ptr, remtag->sip_str_len, 1239 callid->sip_str_ptr, callid->sip_str_len, 1240 NULL, 0, NULL, 0, NULL, 0, (uchar_t *)digest); 1241 1242 dialog = (_sip_dialog_t *)sip_hash_find(sip_dialog_hash, 1243 (void *)digest, SIP_DIGEST_TO_HASH(digest), sip_dialog_match); 1244 if (dialog == NULL) { 1245 sip_md5_hash(localtag->sip_str_ptr, localtag->sip_str_len, 1246 NULL, 0, callid->sip_str_ptr, callid->sip_str_len, 1247 NULL, 0, NULL, 0, NULL, 0, (uchar_t *)digest); 1248 dialog = (_sip_dialog_t *)sip_hash_find(sip_dialog_phash, 1249 (void *)digest, SIP_DIGEST_TO_HASH(digest), 1250 sip_dialog_match); 1251 } 1252 return ((sip_dialog_t)dialog); 1253 } 1254 1255 /* 1256 * We keep this partial dialog for the duration of the INVITE 1257 * transaction timeout duration, i.e. Timer B. 1258 */ 1259 void 1260 sip_dlg_self_destruct(void *args) 1261 { 1262 sip_dialog_timer_obj_t *tim_obj = (sip_dialog_timer_obj_t *)args; 1263 _sip_dialog_t *dialog = (_sip_dialog_t *)tim_obj->dialog; 1264 int index; 1265 1266 (void) pthread_mutex_lock(&dialog->sip_dlg_mutex); 1267 assert(dialog->sip_dlg_state == SIP_DLG_NEW); 1268 dialog->sip_dlg_state = SIP_DLG_DESTROYED; 1269 if (dialog->sip_dlg_type == SIP_UAC_DIALOG) { 1270 index = SIP_DIGEST_TO_HASH(dialog->sip_dlg_id); 1271 (void) pthread_mutex_unlock(&dialog->sip_dlg_mutex); 1272 sip_hash_delete(sip_dialog_phash, (void *)dialog->sip_dlg_id, 1273 index, sip_dialog_dontfree); 1274 } else { 1275 (void) pthread_mutex_unlock(&dialog->sip_dlg_mutex); 1276 } 1277 if (tim_obj->func != NULL) 1278 tim_obj->func(dialog, NULL, NULL); 1279 free(tim_obj); 1280 SIP_DLG_REFCNT_DECR(dialog); 1281 } 1282 1283 /* 1284 * Terminate a dialog 1285 */ 1286 void 1287 sip_dialog_terminate(_sip_dialog_t *dialog, sip_msg_t sip_msg) 1288 { 1289 int prev_state; 1290 1291 (void) pthread_mutex_lock(&dialog->sip_dlg_mutex); 1292 prev_state = dialog->sip_dlg_state; 1293 dialog->sip_dlg_state = SIP_DLG_DESTROYED; 1294 (void) pthread_mutex_unlock(&dialog->sip_dlg_mutex); 1295 if (sip_dlg_ulp_state_cb != NULL) { 1296 sip_dlg_ulp_state_cb((sip_dialog_t)dialog, sip_msg, prev_state, 1297 dialog->sip_dlg_state); 1298 } 1299 SIP_DLG_REFCNT_DECR(dialog); 1300 } 1301 1302 /* 1303 * Delete a dialog 1304 */ 1305 void 1306 sip_dialog_delete(_sip_dialog_t *dialog) 1307 { 1308 int index; 1309 1310 /* 1311 * partial dialog, not in the hash table 1312 */ 1313 if (dialog->sip_dlg_local_uri_tag == NULL || 1314 dialog->sip_dlg_remote_uri_tag == NULL) { 1315 /* 1316 * Cancel the partial dialog timer 1317 */ 1318 if (SIP_IS_TIMER_RUNNING(dialog->sip_dlg_timer)) 1319 SIP_CANCEL_TIMER(dialog->sip_dlg_timer); 1320 sip_release_dialog_res(dialog); 1321 return; 1322 } 1323 index = SIP_DIGEST_TO_HASH(dialog->sip_dlg_id); 1324 sip_hash_delete(sip_dialog_hash, (void *)dialog->sip_dlg_id, index, 1325 sip_dialog_free); 1326 } 1327 1328 /* 1329 * Get the remote target from the CONTACT header from the 200 OK response 1330 */ 1331 static boolean_t 1332 sip_get_rtarg(_sip_dialog_t *dialog, _sip_msg_t *sip_msg) 1333 { 1334 sip_header_t chdr; 1335 1336 if (dialog->sip_dlg_remote_target != NULL) 1337 return (B_TRUE); 1338 1339 (void) pthread_mutex_lock(&sip_msg->sip_msg_mutex); 1340 chdr = sip_search_for_header(sip_msg, SIP_CONTACT, NULL); 1341 (void) pthread_mutex_unlock(&sip_msg->sip_msg_mutex); 1342 if (chdr == NULL) 1343 return (B_FALSE); 1344 if ((dialog->sip_dlg_remote_target = sip_dup_header(chdr)) == NULL) 1345 return (B_FALSE); 1346 1347 return (B_TRUE); 1348 } 1349 1350 /* 1351 * Process an incoming request/response 1352 */ 1353 /* ARGSUSED */ 1354 int 1355 sip_dialog_process(_sip_msg_t *sip_msg, sip_dialog_t *sip_dialog) 1356 { 1357 boolean_t request; 1358 _sip_dialog_t *_dialog; 1359 int error; 1360 1361 request = sip_msg_is_request((sip_msg_t)sip_msg, &error); 1362 if (error != 0) 1363 return (EINVAL); 1364 _dialog = (_sip_dialog_t *)*sip_dialog; 1365 if (request) { 1366 uint32_t cseq; 1367 sip_method_t method; 1368 1369 cseq = sip_get_callseq_num((sip_msg_t)sip_msg, &error); 1370 if (error != 0) 1371 return (EINVAL); 1372 method = sip_get_callseq_method((sip_msg_t)sip_msg, &error); 1373 if (error != 0) 1374 return (EINVAL); 1375 if (sip_get_request_method((sip_msg_t)sip_msg, &error) != 1376 method) { 1377 return (EINVAL); 1378 } 1379 (void) pthread_mutex_lock(&_dialog->sip_dlg_mutex); 1380 /* 1381 * Requests that do not change in any way the state 1382 * of a dialog may be received within a dialog. 1383 * They are processed as if they had been received 1384 * outside the dialog. 1385 * For dialogs that have been established with an 1386 * INVITE, the only target refresh request defined is 1387 * re-INVITE. 1388 */ 1389 if (_dialog->sip_dlg_method == INVITE && 1390 method == INVITE && _dialog->sip_dlg_remote_cseq != 0 && 1391 SIP_CSEQ_LT(cseq, _dialog->sip_dlg_remote_cseq)) { 1392 (void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex); 1393 return (EPROTO); 1394 } 1395 /* 1396 * Target-Refresh request 1397 */ 1398 if (_dialog->sip_dlg_method == INVITE && method == INVITE) { 1399 sip_header_t chdr; 1400 sip_header_t nchdr; 1401 1402 (void) pthread_mutex_lock(&sip_msg->sip_msg_mutex); 1403 chdr = sip_search_for_header(sip_msg, SIP_CONTACT, 1404 NULL); 1405 (void) pthread_mutex_unlock(&sip_msg->sip_msg_mutex); 1406 if (chdr != NULL && 1407 (nchdr = sip_dup_header(chdr)) != NULL) { 1408 if (_dialog->sip_dlg_remote_target != NULL) { 1409 sip_free_header( 1410 _dialog->sip_dlg_remote_target); 1411 } 1412 _dialog->sip_dlg_remote_target = nchdr; 1413 } 1414 } 1415 _dialog->sip_dlg_remote_cseq = cseq; 1416 (void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex); 1417 } else { 1418 int resp_code; 1419 sip_method_t method; 1420 int error; 1421 1422 resp_code = sip_get_response_code((sip_msg_t)sip_msg, &error); 1423 if (error == 0) { 1424 method = sip_get_callseq_method((sip_msg_t)sip_msg, 1425 &error); 1426 } 1427 if (error != 0) 1428 return (error); 1429 1430 (void) pthread_mutex_lock(&_dialog->sip_dlg_mutex); 1431 if (_dialog->sip_dlg_state == SIP_DLG_DESTROYED) { 1432 (void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex); 1433 return (0); 1434 } 1435 assert(_dialog->sip_dlg_state == SIP_DLG_EARLY || 1436 _dialog->sip_dlg_state == SIP_DLG_CONFIRMED); 1437 /* 1438 * Let the user delete the dialog if it is not a 1XX/2XX resp 1439 * for an early INVITE dialog. 1440 */ 1441 if (SIP_OK_RESP(resp_code)) { 1442 if (method == INVITE) { 1443 if (!sip_get_rtarg(_dialog, sip_msg)) { 1444 (void) pthread_mutex_unlock( 1445 &_dialog->sip_dlg_mutex); 1446 if (sip_ulp_dlg_del_cb != NULL) { 1447 sip_ulp_dlg_del_cb( 1448 (sip_dialog_t)_dialog, 1449 (sip_msg_t)sip_msg, NULL); 1450 } 1451 sip_dialog_terminate(_dialog, 1452 (sip_msg_t)sip_msg); 1453 return (0); 1454 } 1455 if (_dialog->sip_dlg_state == SIP_DLG_EARLY) { 1456 _dialog->sip_dlg_state = 1457 SIP_DLG_CONFIRMED; 1458 (void) pthread_mutex_unlock( 1459 &_dialog->sip_dlg_mutex); 1460 (void) sip_dlg_recompute_rset(_dialog, 1461 sip_msg, SIP_UAC_DIALOG); 1462 if (sip_dlg_ulp_state_cb != NULL) { 1463 sip_dlg_ulp_state_cb( 1464 (sip_dialog_t)_dialog, 1465 sip_msg, SIP_DLG_EARLY, 1466 _dialog->sip_dlg_state); 1467 } 1468 return (0); 1469 } else if (_dialog->sip_dlg_new_local_contact 1470 != NULL) { 1471 assert(_dialog->sip_dlg_local_contact 1472 != NULL); 1473 sip_free_header(_dialog-> 1474 sip_dlg_local_contact); 1475 _dialog->sip_dlg_local_contact = 1476 _dialog->sip_dlg_new_local_contact; 1477 _dialog->sip_dlg_new_local_contact = 1478 NULL; 1479 } 1480 } 1481 } 1482 (void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex); 1483 } 1484 return (0); 1485 } 1486 1487 /* 1488 * Copy partial dialog to create a complete dialog 1489 */ 1490 _sip_dialog_t * 1491 sip_copy_partial_dialog(_sip_dialog_t *dialog) 1492 { 1493 _sip_dialog_t *new_dlg; 1494 1495 new_dlg = calloc(1, sizeof (_sip_dialog_t)); 1496 if (new_dlg == NULL) 1497 return (NULL); 1498 if (dialog->sip_dlg_req_uri.sip_str_ptr != NULL) { 1499 new_dlg->sip_dlg_req_uri.sip_str_ptr = 1500 malloc(dialog->sip_dlg_req_uri.sip_str_len + 1); 1501 if (new_dlg->sip_dlg_req_uri.sip_str_ptr == NULL) { 1502 free(new_dlg); 1503 return (NULL); 1504 } 1505 (void) strncpy(new_dlg->sip_dlg_req_uri.sip_str_ptr, 1506 dialog->sip_dlg_req_uri.sip_str_ptr, 1507 dialog->sip_dlg_req_uri.sip_str_len); 1508 new_dlg->sip_dlg_req_uri.sip_str_ptr[ 1509 dialog->sip_dlg_req_uri.sip_str_len] = '\0'; 1510 new_dlg->sip_dlg_req_uri.sip_str_len = 1511 dialog->sip_dlg_req_uri.sip_str_len; 1512 } 1513 if (dialog->sip_dlg_route_set != NULL) { 1514 assert(dialog->sip_dlg_rset.sip_str_ptr != NULL); 1515 new_dlg->sip_dlg_rset.sip_str_ptr = 1516 malloc(dialog->sip_dlg_rset.sip_str_len + 1); 1517 if (new_dlg->sip_dlg_rset.sip_str_ptr == NULL) { 1518 if (new_dlg->sip_dlg_req_uri.sip_str_ptr != NULL) 1519 free(new_dlg->sip_dlg_req_uri.sip_str_ptr); 1520 free(new_dlg); 1521 return (NULL); 1522 } 1523 (void) strncpy(new_dlg->sip_dlg_rset.sip_str_ptr, 1524 dialog->sip_dlg_rset.sip_str_ptr, 1525 dialog->sip_dlg_rset.sip_str_len); 1526 new_dlg->sip_dlg_rset.sip_str_ptr[ 1527 dialog->sip_dlg_rset.sip_str_len] = '\0'; 1528 new_dlg->sip_dlg_rset.sip_str_len = 1529 dialog->sip_dlg_rset.sip_str_len; 1530 1531 new_dlg->sip_dlg_route_set = 1532 sip_dup_header(dialog->sip_dlg_route_set); 1533 if (new_dlg->sip_dlg_route_set == NULL) { 1534 free(new_dlg->sip_dlg_rset.sip_str_ptr); 1535 if (new_dlg->sip_dlg_req_uri.sip_str_ptr != NULL) 1536 free(new_dlg->sip_dlg_req_uri.sip_str_ptr); 1537 free(new_dlg); 1538 return (NULL); 1539 } 1540 } 1541 if ((new_dlg->sip_dlg_local_uri_tag = 1542 sip_dup_header(dialog->sip_dlg_local_uri_tag)) == NULL || 1543 (new_dlg->sip_dlg_remote_target = 1544 sip_dup_header(dialog->sip_dlg_remote_target)) == NULL || 1545 (new_dlg->sip_dlg_local_contact = 1546 sip_dup_header(dialog->sip_dlg_local_contact)) == NULL || 1547 (new_dlg->sip_dlg_call_id = 1548 sip_dup_header(dialog->sip_dlg_call_id)) == NULL) { 1549 sip_release_dialog_res(new_dlg); 1550 return (NULL); 1551 } 1552 if (dialog->sip_dlg_event != NULL) { 1553 new_dlg->sip_dlg_event = sip_dup_header(dialog->sip_dlg_event); 1554 if (new_dlg->sip_dlg_event == NULL) { 1555 sip_release_dialog_res(new_dlg); 1556 return (NULL); 1557 } 1558 } 1559 new_dlg->sip_dlg_local_cseq = dialog->sip_dlg_local_cseq; 1560 new_dlg->sip_dlg_type = dialog->sip_dlg_type; 1561 new_dlg->sip_dlg_on_fork = B_FALSE; 1562 (void) pthread_mutex_init(&new_dlg->sip_dlg_mutex, NULL); 1563 1564 return (new_dlg); 1565 } 1566 1567 /* 1568 * Update the dialog using the response 1569 */ 1570 sip_dialog_t 1571 sip_update_dialog(sip_dialog_t dialog, _sip_msg_t *sip_msg) 1572 { 1573 _sip_dialog_t *_dialog; 1574 boolean_t isreq; 1575 sip_method_t method; 1576 int resp_code = 0; 1577 int prev_state; 1578 boolean_t decr_ref = B_FALSE; 1579 int error; 1580 1581 isreq = sip_msg_is_request((sip_msg_t)sip_msg, &error); 1582 if (error != 0) 1583 return (dialog); 1584 _dialog = (_sip_dialog_t *)dialog; 1585 (void) pthread_mutex_lock(&_dialog->sip_dlg_mutex); 1586 if (isreq) { 1587 method = sip_get_request_method((sip_msg_t)sip_msg, &error); 1588 if (error != 0 || _dialog->sip_dlg_method != SUBSCRIBE || 1589 method != NOTIFY) { 1590 (void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex); 1591 return (dialog); 1592 } 1593 } else { 1594 resp_code = sip_get_response_code((sip_msg_t)sip_msg, &error); 1595 if (error != 0) { 1596 (void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex); 1597 return (dialog); 1598 } 1599 method = sip_get_callseq_method((sip_msg_t)sip_msg, &error); 1600 if (error != 0) { 1601 (void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex); 1602 return (dialog); 1603 } 1604 } 1605 prev_state = _dialog->sip_dlg_state; 1606 if (_dialog->sip_dlg_state == SIP_DLG_CONFIRMED) { 1607 (void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex); 1608 } else if (_dialog->sip_dlg_state == SIP_DLG_EARLY) { 1609 /* 1610 * Let the user delete the dialog if it is not a 1XX/2XX resp 1611 * for an early dialog. 1612 */ 1613 assert(!isreq); 1614 if (SIP_OK_RESP(resp_code)) { 1615 _dialog->sip_dlg_state = SIP_DLG_CONFIRMED; 1616 /* 1617 * If we recieved provisional response before we would 1618 * not have captured local contact. So store it now. 1619 */ 1620 if (_dialog->sip_dlg_type == SIP_UAS_DIALOG && _dialog-> 1621 sip_dlg_method == INVITE && method == INVITE) { 1622 sip_header_t chdr; 1623 (void) pthread_mutex_lock(&sip_msg-> 1624 sip_msg_mutex); 1625 chdr = sip_search_for_header(sip_msg, 1626 SIP_CONTACT, NULL); 1627 (void) pthread_mutex_unlock(&sip_msg-> 1628 sip_msg_mutex); 1629 if (chdr != NULL) { 1630 _dialog->sip_dlg_local_contact 1631 = sip_dup_header(chdr); 1632 _dialog->sip_dlg_new_local_contact = 1633 NULL; 1634 } 1635 } 1636 (void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex); 1637 (void) sip_dlg_recompute_rset(_dialog, sip_msg, 1638 SIP_UAS_DIALOG); 1639 if (sip_dlg_ulp_state_cb != NULL) { 1640 sip_dlg_ulp_state_cb(dialog, (sip_msg_t)sip_msg, 1641 prev_state, dialog->sip_dlg_state); 1642 } 1643 } else { 1644 (void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex); 1645 } 1646 } else if (_dialog->sip_dlg_state == SIP_DLG_NEW) { 1647 if (!isreq && _dialog->sip_dlg_method == SUBSCRIBE && 1648 SIP_PROVISIONAL_RESP(resp_code)) { 1649 (void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex); 1650 return (dialog); 1651 } 1652 if (_dialog->sip_dlg_type == SIP_UAC_DIALOG) { 1653 _sip_dialog_t *new_dlg; 1654 1655 if (_dialog->sip_dlg_on_fork) { 1656 new_dlg = sip_copy_partial_dialog(_dialog); 1657 if (new_dlg == NULL) { 1658 (void) pthread_mutex_unlock( 1659 &_dialog->sip_dlg_mutex); 1660 return (dialog); 1661 } 1662 /* 1663 * This decr/incr dance is because the caller 1664 * has incremented the ref on the partial 1665 * dialog, we release it here and incr the 1666 * ref on the new dialog which will be 1667 * released by the caller. 1668 */ 1669 (void) pthread_mutex_unlock( 1670 &_dialog->sip_dlg_mutex); 1671 SIP_DLG_REFCNT_DECR(_dialog); 1672 _dialog = new_dlg; 1673 (void) pthread_mutex_lock( 1674 &_dialog->sip_dlg_mutex); 1675 SIP_DLG_REFCNT_INCR(_dialog); 1676 } else { 1677 int index; 1678 1679 /* 1680 * take it out of the list so that further 1681 * responses will not result in a dialog. 1682 * We will have an extra refcount when we 1683 * come back from sip_complete_dialog(), i.e. 1684 * one when the partial dialog was created - 1685 * in sip_seed_dialog(), one held by the caller 1686 * and one that will be added by 1687 * sip_complete_dialog(). We need to release 1688 * the one added by the sip_seed_dialog(), 1689 * since the one in sip_complete_dialog() 1690 * is for the same purpose. 1691 */ 1692 if (SIP_IS_TIMER_RUNNING( 1693 _dialog->sip_dlg_timer)) { 1694 SIP_CANCEL_TIMER( 1695 _dialog->sip_dlg_timer); 1696 } 1697 index = SIP_DIGEST_TO_HASH(dialog->sip_dlg_id); 1698 (void) pthread_mutex_unlock( 1699 &_dialog->sip_dlg_mutex); 1700 sip_hash_delete(sip_dialog_phash, 1701 (void *)_dialog->sip_dlg_id, 1702 index, sip_dialog_dontfree); 1703 (void) pthread_mutex_lock( 1704 &_dialog->sip_dlg_mutex); 1705 decr_ref = B_TRUE; 1706 } 1707 } else { 1708 decr_ref = B_TRUE; 1709 } 1710 (void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex); 1711 if ((dialog = sip_complete_dialog(sip_msg, _dialog)) == 1712 NULL) { 1713 if (_dialog->sip_dlg_type == SIP_UAC_DIALOG && decr_ref) 1714 SIP_DLG_REFCNT_DECR(_dialog); 1715 return (NULL); 1716 } 1717 if (decr_ref) 1718 SIP_DLG_REFCNT_DECR(_dialog); 1719 } else { 1720 (void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex); 1721 } 1722 return (dialog); 1723 } 1724 1725 /* 1726 * Initialize the hash table 1727 */ 1728 void 1729 sip_dialog_init(void (*ulp_dlg_del) (sip_dialog_t, sip_msg_t, void *), 1730 void (*ulp_state_cb)(sip_dialog_t, sip_msg_t, int, int)) 1731 { 1732 int cnt; 1733 1734 for (cnt = 0; cnt < SIP_HASH_SZ; cnt++) { 1735 sip_dialog_hash[cnt].hash_count = 0; 1736 sip_dialog_hash[cnt].hash_head = NULL; 1737 sip_dialog_hash[cnt].hash_tail = NULL; 1738 (void) pthread_mutex_init( 1739 &sip_dialog_hash[cnt].sip_hash_mutex, NULL); 1740 sip_dialog_phash[cnt].hash_count = 0; 1741 sip_dialog_phash[cnt].hash_head = NULL; 1742 sip_dialog_phash[cnt].hash_tail = NULL; 1743 (void) pthread_mutex_init( 1744 &sip_dialog_phash[cnt].sip_hash_mutex, NULL); 1745 } 1746 if (ulp_dlg_del != NULL) 1747 sip_ulp_dlg_del_cb = ulp_dlg_del; 1748 1749 if (ulp_state_cb != NULL) 1750 sip_dlg_ulp_state_cb = ulp_state_cb; 1751 } 1752 1753 /* 1754 * Copy the new contact header of re-INVITE 1755 */ 1756 void 1757 sip_dialog_add_new_contact(sip_dialog_t dialog, _sip_msg_t *sip_msg) 1758 { 1759 sip_header_t chdr = NULL; 1760 sip_header_t nhdr = NULL; 1761 1762 (void) pthread_mutex_lock(&sip_msg->sip_msg_mutex); 1763 chdr = sip_search_for_header(sip_msg, SIP_CONTACT, NULL); 1764 (void) pthread_mutex_unlock(&sip_msg->sip_msg_mutex); 1765 1766 if (chdr == NULL) 1767 return; 1768 1769 (void) pthread_mutex_lock(&dialog->sip_dlg_mutex); 1770 if (dialog->sip_dlg_method != INVITE || dialog->sip_dlg_state 1771 != SIP_DLG_CONFIRMED) { 1772 (void) pthread_mutex_unlock(&dialog->sip_dlg_mutex); 1773 return; 1774 } 1775 1776 if (((nhdr = sip_dup_header(chdr)) != NULL)) { 1777 if (dialog->sip_dlg_new_local_contact != NULL) 1778 sip_free_header(dialog->sip_dlg_new_local_contact); 1779 dialog->sip_dlg_new_local_contact = nhdr; 1780 } 1781 (void) pthread_mutex_unlock(&dialog->sip_dlg_mutex); 1782 } 1783