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