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