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