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