140cb5e5dSvi117747 /* 240cb5e5dSvi117747 * CDDL HEADER START 340cb5e5dSvi117747 * 440cb5e5dSvi117747 * The contents of this file are subject to the terms of the 540cb5e5dSvi117747 * Common Development and Distribution License (the "License"). 640cb5e5dSvi117747 * You may not use this file except in compliance with the License. 740cb5e5dSvi117747 * 840cb5e5dSvi117747 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 940cb5e5dSvi117747 * or http://www.opensolaris.org/os/licensing. 1040cb5e5dSvi117747 * See the License for the specific language governing permissions 1140cb5e5dSvi117747 * and limitations under the License. 1240cb5e5dSvi117747 * 1340cb5e5dSvi117747 * When distributing Covered Code, include this CDDL HEADER in each 1440cb5e5dSvi117747 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 1540cb5e5dSvi117747 * If applicable, add the following below this CDDL HEADER, with the 1640cb5e5dSvi117747 * fields enclosed by brackets "[]" replaced with your own identifying 1740cb5e5dSvi117747 * information: Portions Copyright [yyyy] [name of copyright owner] 1840cb5e5dSvi117747 * 1940cb5e5dSvi117747 * CDDL HEADER END 2040cb5e5dSvi117747 */ 2140cb5e5dSvi117747 2240cb5e5dSvi117747 /* 23*943efbc3Sgm209912 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 2440cb5e5dSvi117747 * Use is subject to license terms. 2540cb5e5dSvi117747 */ 2640cb5e5dSvi117747 2740cb5e5dSvi117747 #pragma ident "%Z%%M% %I% %E% SMI" 2840cb5e5dSvi117747 292c2c4183Svi117747 #include <stdio.h> 302c2c4183Svi117747 #include <stdlib.h> 312c2c4183Svi117747 #include <assert.h> 322c2c4183Svi117747 #include <errno.h> 332c2c4183Svi117747 #include <pthread.h> 342c2c4183Svi117747 #include <strings.h> 352c2c4183Svi117747 #include <sip.h> 362c2c4183Svi117747 3740cb5e5dSvi117747 #include "sip_msg.h" 3840cb5e5dSvi117747 #include "sip_miscdefs.h" 392c2c4183Svi117747 #include "sip_hash.h" 4040cb5e5dSvi117747 #include "sip_dialog.h" 4140cb5e5dSvi117747 #include "sip_parse_generic.h" 4240cb5e5dSvi117747 4340cb5e5dSvi117747 #define SIP_DLG_XCHG_FROM 0 4440cb5e5dSvi117747 #define SIP_DLG_XCHG_TO 1 4540cb5e5dSvi117747 4640cb5e5dSvi117747 /* 4740cb5e5dSvi117747 * Dialog state change callback function 4840cb5e5dSvi117747 */ 4940cb5e5dSvi117747 void (*sip_dlg_ulp_state_cb)(sip_dialog_t, sip_msg_t, int, int) = NULL; 5040cb5e5dSvi117747 void (*sip_ulp_dlg_del_cb)(sip_dialog_t, sip_msg_t, void *) = NULL; 5140cb5e5dSvi117747 5240cb5e5dSvi117747 boolean_t sip_incomplete_dialog(sip_dialog_t); 5340cb5e5dSvi117747 5440cb5e5dSvi117747 /* 5540cb5e5dSvi117747 * Exchange From/To header 5640cb5e5dSvi117747 */ 5740cb5e5dSvi117747 _sip_header_t *sip_dlg_xchg_from_to(sip_msg_t, int); 5840cb5e5dSvi117747 5940cb5e5dSvi117747 /* 6040cb5e5dSvi117747 * Complete dialog hash table 6140cb5e5dSvi117747 */ 6240cb5e5dSvi117747 sip_hash_t sip_dialog_hash[SIP_HASH_SZ]; 6340cb5e5dSvi117747 6440cb5e5dSvi117747 /* 6540cb5e5dSvi117747 * Partial dialog hash table 6640cb5e5dSvi117747 */ 6740cb5e5dSvi117747 sip_hash_t sip_dialog_phash[SIP_HASH_SZ]; 6840cb5e5dSvi117747 6940cb5e5dSvi117747 /* 7040cb5e5dSvi117747 * Route set structure 7140cb5e5dSvi117747 */ 7240cb5e5dSvi117747 typedef struct sip_dlg_route_set_s { 7340cb5e5dSvi117747 char *sip_dlg_route; 7440cb5e5dSvi117747 sip_str_t sip_dlg_ruri; 7540cb5e5dSvi117747 boolean_t sip_dlg_route_lr; 7640cb5e5dSvi117747 struct sip_dlg_route_set_s *sip_dlg_route_next; 7740cb5e5dSvi117747 }sip_dlg_route_set_t; 7840cb5e5dSvi117747 7940cb5e5dSvi117747 sip_dialog_t sip_seed_dialog(sip_conn_object_t, _sip_msg_t *, 8040cb5e5dSvi117747 boolean_t, int); 8140cb5e5dSvi117747 sip_dialog_t sip_complete_dialog(_sip_msg_t *, _sip_dialog_t *); 8240cb5e5dSvi117747 int sip_dialog_process(_sip_msg_t *, sip_dialog_t *); 8340cb5e5dSvi117747 void sip_dialog_delete(_sip_dialog_t *); 8440cb5e5dSvi117747 void sip_dialog_init(); 8540cb5e5dSvi117747 sip_dialog_t sip_dialog_find(_sip_msg_t *); 8640cb5e5dSvi117747 boolean_t sip_dialog_match(void *, void *); 8740cb5e5dSvi117747 boolean_t sip_dialog_free(void *, void *, int *); 8840cb5e5dSvi117747 sip_dialog_t sip_update_dialog(sip_dialog_t, _sip_msg_t *); 8940cb5e5dSvi117747 char *sip_dialog_req_uri(sip_dialog_t); 9040cb5e5dSvi117747 9140cb5e5dSvi117747 static void sip_release_dialog_res(_sip_dialog_t *); 9240cb5e5dSvi117747 void sip_dlg_self_destruct(void *); 9340cb5e5dSvi117747 static int sip_dialog_get_route_set(_sip_dialog_t *, _sip_msg_t *, 9440cb5e5dSvi117747 int); 9540cb5e5dSvi117747 static void sip_dialog_free_rset(sip_dlg_route_set_t *); 9640cb5e5dSvi117747 9740cb5e5dSvi117747 /* 9840cb5e5dSvi117747 * Timer object for partial dialogs 9940cb5e5dSvi117747 */ 10040cb5e5dSvi117747 typedef struct sip_dialog_timer_obj_s { 10140cb5e5dSvi117747 _sip_dialog_t *dialog; 10240cb5e5dSvi117747 void (*func)(sip_dialog_t, sip_msg_t, void *); 10340cb5e5dSvi117747 } sip_dialog_timer_obj_t; 10440cb5e5dSvi117747 10540cb5e5dSvi117747 /* 10640cb5e5dSvi117747 * To avoid duplication all over the place 10740cb5e5dSvi117747 */ 10840cb5e5dSvi117747 static void 10940cb5e5dSvi117747 sip_release_dialog_res(_sip_dialog_t *dialog) 11040cb5e5dSvi117747 { 111*943efbc3Sgm209912 int count = 0; 112*943efbc3Sgm209912 sip_msg_chain_t *msg_chain; 113*943efbc3Sgm209912 sip_msg_chain_t *nmsg_chain; 11440cb5e5dSvi117747 115*943efbc3Sgm209912 if (dialog->sip_dlg_ref_cnt != 0) { 116*943efbc3Sgm209912 sip_write_to_log((void *)dialog, SIP_DIALOG_LOG | 117*943efbc3Sgm209912 SIP_ASSERT_ERROR, __FILE__, __LINE__); 118*943efbc3Sgm209912 } 11940cb5e5dSvi117747 assert(dialog->sip_dlg_ref_cnt == 0); 12040cb5e5dSvi117747 if (SIP_IS_TIMER_RUNNING(dialog->sip_dlg_timer)) 12140cb5e5dSvi117747 SIP_CANCEL_TIMER(dialog->sip_dlg_timer); 12240cb5e5dSvi117747 if (dialog->sip_dlg_call_id != NULL) 12340cb5e5dSvi117747 sip_free_header(dialog->sip_dlg_call_id); 12440cb5e5dSvi117747 if (dialog->sip_dlg_local_uri_tag != NULL) 12540cb5e5dSvi117747 sip_free_header(dialog->sip_dlg_local_uri_tag); 12640cb5e5dSvi117747 if (dialog->sip_dlg_remote_uri_tag != NULL) 12740cb5e5dSvi117747 sip_free_header(dialog->sip_dlg_remote_uri_tag); 12840cb5e5dSvi117747 if (dialog->sip_dlg_remote_target != NULL) 12940cb5e5dSvi117747 sip_free_header(dialog->sip_dlg_remote_target); 130d8a40387Sgm209912 if (dialog->sip_dlg_local_contact != NULL) 131d8a40387Sgm209912 sip_free_header(dialog->sip_dlg_local_contact); 132d8a40387Sgm209912 if (dialog->sip_dlg_new_local_contact != NULL) 133d8a40387Sgm209912 sip_free_header(dialog->sip_dlg_new_local_contact); 13440cb5e5dSvi117747 if (dialog->sip_dlg_route_set != NULL) 13540cb5e5dSvi117747 sip_free_header(dialog->sip_dlg_route_set); 13640cb5e5dSvi117747 if (dialog->sip_dlg_event != NULL) 13740cb5e5dSvi117747 sip_free_header(dialog->sip_dlg_event); 13840cb5e5dSvi117747 if (dialog->sip_dlg_req_uri.sip_str_ptr != NULL) { 13940cb5e5dSvi117747 free(dialog->sip_dlg_req_uri.sip_str_ptr); 14040cb5e5dSvi117747 dialog->sip_dlg_req_uri.sip_str_ptr = NULL; 14140cb5e5dSvi117747 dialog->sip_dlg_req_uri.sip_str_len = 0; 14240cb5e5dSvi117747 } 14340cb5e5dSvi117747 if (dialog->sip_dlg_rset.sip_str_ptr != NULL) { 14440cb5e5dSvi117747 free(dialog->sip_dlg_rset.sip_str_ptr); 14540cb5e5dSvi117747 dialog->sip_dlg_rset.sip_str_len = 0; 14640cb5e5dSvi117747 dialog->sip_dlg_rset.sip_str_ptr = NULL; 14740cb5e5dSvi117747 } 148*943efbc3Sgm209912 for (count = 0; count <= SIP_DLG_DESTROYED; count++) { 149*943efbc3Sgm209912 msg_chain = dialog->sip_dlg_log[count].sip_msgs; 150*943efbc3Sgm209912 while (msg_chain != NULL) { 151*943efbc3Sgm209912 nmsg_chain = msg_chain->next; 152*943efbc3Sgm209912 if (msg_chain->sip_msg != NULL) 153*943efbc3Sgm209912 free(msg_chain->sip_msg); 154*943efbc3Sgm209912 free(msg_chain); 155*943efbc3Sgm209912 msg_chain = nmsg_chain; 156*943efbc3Sgm209912 } 157*943efbc3Sgm209912 } 15840cb5e5dSvi117747 (void) pthread_mutex_destroy(&dialog->sip_dlg_mutex); 15940cb5e5dSvi117747 free(dialog); 16040cb5e5dSvi117747 } 16140cb5e5dSvi117747 16240cb5e5dSvi117747 /* 16340cb5e5dSvi117747 * Get the route information from the 'value' and add it to the route 16440cb5e5dSvi117747 * set. 16540cb5e5dSvi117747 */ 16640cb5e5dSvi117747 static sip_dlg_route_set_t * 16740cb5e5dSvi117747 sip_add_route_to_set(sip_hdr_value_t *value) 16840cb5e5dSvi117747 { 16940cb5e5dSvi117747 int vlen = 0; 17040cb5e5dSvi117747 sip_dlg_route_set_t *rset; 17140cb5e5dSvi117747 char *crlf; 17240cb5e5dSvi117747 const sip_param_t *uri_param; 17340cb5e5dSvi117747 int error; 17440cb5e5dSvi117747 17540cb5e5dSvi117747 rset = calloc(1, sizeof (*rset)); 17640cb5e5dSvi117747 if (rset == NULL) 17740cb5e5dSvi117747 return (NULL); 17840cb5e5dSvi117747 rset->sip_dlg_route_next = NULL; 17940cb5e5dSvi117747 vlen = value->sip_value_end - value->sip_value_start; 18040cb5e5dSvi117747 18140cb5e5dSvi117747 /* 18240cb5e5dSvi117747 * check for CRLF 18340cb5e5dSvi117747 */ 18440cb5e5dSvi117747 crlf = value->sip_value_end - strlen(SIP_CRLF); 18540cb5e5dSvi117747 while (crlf != NULL && strncmp(crlf, SIP_CRLF, strlen(SIP_CRLF)) == 0) { 18640cb5e5dSvi117747 vlen -= strlen(SIP_CRLF); 18740cb5e5dSvi117747 crlf -= strlen(SIP_CRLF); 18840cb5e5dSvi117747 } 18940cb5e5dSvi117747 rset->sip_dlg_route = calloc(1, vlen + 1); 19040cb5e5dSvi117747 if (rset->sip_dlg_route == NULL) { 19140cb5e5dSvi117747 free(rset); 19240cb5e5dSvi117747 return (NULL); 19340cb5e5dSvi117747 } 19440cb5e5dSvi117747 /* 19540cb5e5dSvi117747 * loose routing 19640cb5e5dSvi117747 */ 19740cb5e5dSvi117747 rset->sip_dlg_route_lr = B_FALSE; 19840cb5e5dSvi117747 (void) strncpy(rset->sip_dlg_route, value->sip_value_start, vlen); 19940cb5e5dSvi117747 rset->sip_dlg_ruri.sip_str_ptr = rset->sip_dlg_route + 20040cb5e5dSvi117747 (value->cftr_uri.sip_str_ptr - value->sip_value_start); 20140cb5e5dSvi117747 rset->sip_dlg_ruri.sip_str_len = value->cftr_uri.sip_str_len; 20240cb5e5dSvi117747 rset->sip_dlg_route[vlen] = '\0'; 20340cb5e5dSvi117747 20440cb5e5dSvi117747 assert(value->sip_value_parsed_uri != NULL); 20540cb5e5dSvi117747 /* 20640cb5e5dSvi117747 * Check if the 'lr' param is present for this route. 20740cb5e5dSvi117747 */ 20840cb5e5dSvi117747 uri_param = sip_get_uri_params(value->sip_value_parsed_uri, &error); 20940cb5e5dSvi117747 if (error != 0) { 21040cb5e5dSvi117747 free(rset->sip_dlg_route); 21140cb5e5dSvi117747 free(rset); 21240cb5e5dSvi117747 return (NULL); 21340cb5e5dSvi117747 } 21440cb5e5dSvi117747 if (uri_param != NULL) { 21540cb5e5dSvi117747 rset->sip_dlg_route_lr = sip_is_param_present(uri_param, "lr", 21640cb5e5dSvi117747 strlen("lr")); 21740cb5e5dSvi117747 } 21840cb5e5dSvi117747 return (rset); 21940cb5e5dSvi117747 } 22040cb5e5dSvi117747 22140cb5e5dSvi117747 /* 22240cb5e5dSvi117747 * Depending on the route-set, determine the request URI. 22340cb5e5dSvi117747 */ 22440cb5e5dSvi117747 char * 22540cb5e5dSvi117747 sip_dialog_req_uri(sip_dialog_t dialog) 22640cb5e5dSvi117747 { 22740cb5e5dSvi117747 const sip_str_t *req_uri; 22840cb5e5dSvi117747 char *uri; 22940cb5e5dSvi117747 _sip_dialog_t *_dialog; 23040cb5e5dSvi117747 23140cb5e5dSvi117747 _dialog = (_sip_dialog_t *)dialog; 23240cb5e5dSvi117747 if (_dialog->sip_dlg_route_set == NULL || 23340cb5e5dSvi117747 _dialog->sip_dlg_req_uri.sip_str_ptr == NULL) { 23440cb5e5dSvi117747 const struct sip_value *val; 23540cb5e5dSvi117747 23640cb5e5dSvi117747 val = sip_get_header_value(_dialog->sip_dlg_remote_target, 23740cb5e5dSvi117747 NULL); 23840cb5e5dSvi117747 if (val == NULL) 23940cb5e5dSvi117747 return (NULL); 24040cb5e5dSvi117747 req_uri = &((sip_hdr_value_t *)val)->cftr_uri; 24140cb5e5dSvi117747 } else { 24240cb5e5dSvi117747 req_uri = &_dialog->sip_dlg_req_uri; 24340cb5e5dSvi117747 } 24440cb5e5dSvi117747 uri = (char *)malloc(req_uri->sip_str_len + 1); 24540cb5e5dSvi117747 if (uri == NULL) 24640cb5e5dSvi117747 return (NULL); 24740cb5e5dSvi117747 (void) strncpy(uri, req_uri->sip_str_ptr, req_uri->sip_str_len); 24840cb5e5dSvi117747 uri[req_uri->sip_str_len] = '\0'; 24940cb5e5dSvi117747 25040cb5e5dSvi117747 return (uri); 25140cb5e5dSvi117747 } 25240cb5e5dSvi117747 25340cb5e5dSvi117747 /* 25440cb5e5dSvi117747 * Free the route set. 25540cb5e5dSvi117747 */ 25640cb5e5dSvi117747 void 25740cb5e5dSvi117747 sip_dialog_free_rset(sip_dlg_route_set_t *rset) 25840cb5e5dSvi117747 { 25940cb5e5dSvi117747 sip_dlg_route_set_t *next; 26040cb5e5dSvi117747 26140cb5e5dSvi117747 while (rset != NULL) { 26240cb5e5dSvi117747 next = rset->sip_dlg_route_next; 26340cb5e5dSvi117747 rset->sip_dlg_route_next = NULL; 26440cb5e5dSvi117747 free(rset->sip_dlg_route); 26540cb5e5dSvi117747 free(rset); 26640cb5e5dSvi117747 rset = next; 26740cb5e5dSvi117747 } 26840cb5e5dSvi117747 } 26940cb5e5dSvi117747 27040cb5e5dSvi117747 /* 27140cb5e5dSvi117747 * Recompute route-set 27240cb5e5dSvi117747 */ 27340cb5e5dSvi117747 static int 27440cb5e5dSvi117747 sip_dlg_recompute_rset(_sip_dialog_t *dialog, _sip_msg_t *sip_msg, int what) 27540cb5e5dSvi117747 { 27640cb5e5dSvi117747 int ret; 27740cb5e5dSvi117747 27840cb5e5dSvi117747 if (dialog->sip_dlg_route_set != NULL) { 27940cb5e5dSvi117747 sip_free_header(dialog->sip_dlg_route_set); 28040cb5e5dSvi117747 dialog->sip_dlg_route_set = NULL; 28140cb5e5dSvi117747 } 28240cb5e5dSvi117747 if (dialog->sip_dlg_req_uri.sip_str_ptr != NULL) { 28340cb5e5dSvi117747 free(dialog->sip_dlg_req_uri.sip_str_ptr); 28440cb5e5dSvi117747 dialog->sip_dlg_req_uri.sip_str_ptr = NULL; 28540cb5e5dSvi117747 dialog->sip_dlg_req_uri.sip_str_len = 0; 28640cb5e5dSvi117747 } 28740cb5e5dSvi117747 if (dialog->sip_dlg_rset.sip_str_ptr != NULL) { 28840cb5e5dSvi117747 free(dialog->sip_dlg_rset.sip_str_ptr); 28940cb5e5dSvi117747 dialog->sip_dlg_rset.sip_str_ptr = NULL; 29040cb5e5dSvi117747 dialog->sip_dlg_rset.sip_str_len = 0; 29140cb5e5dSvi117747 } 29240cb5e5dSvi117747 ret = sip_dialog_get_route_set(dialog, sip_msg, what); 29340cb5e5dSvi117747 return (ret); 29440cb5e5dSvi117747 } 29540cb5e5dSvi117747 29640cb5e5dSvi117747 /* 29740cb5e5dSvi117747 * If the route set is empty, the UAC MUST place the remote target URI 29840cb5e5dSvi117747 * into the Request-URI. The UAC MUST NOT add a Route header field to 29940cb5e5dSvi117747 * the request. 30040cb5e5dSvi117747 * 30140cb5e5dSvi117747 * If the route set is not empty, and the first URI in the route set 30240cb5e5dSvi117747 * contains the lr parameter (see Section 19.1.1), the UAC MUST place 30340cb5e5dSvi117747 * the remote target URI into the Request-URI and MUST include a Route 30440cb5e5dSvi117747 * header field containing the route set values in order, including all 30540cb5e5dSvi117747 * parameters. 30640cb5e5dSvi117747 * 30740cb5e5dSvi117747 * If the route set is not empty, and its first URI does not contain the 30840cb5e5dSvi117747 * lr parameter, the UAC MUST place the first URI from the route set 30940cb5e5dSvi117747 * into the Request-URI, stripping any parameters that are not allowed 31040cb5e5dSvi117747 * in a Request-URI. The UAC MUST add a Route header field containing 31140cb5e5dSvi117747 * the remainder of the route set values in order, including all 31240cb5e5dSvi117747 * parameters. The UAC MUST then place the remote target URI into the 31340cb5e5dSvi117747 * Route header field as the last value. 31440cb5e5dSvi117747 */ 31540cb5e5dSvi117747 int 31640cb5e5dSvi117747 sip_dialog_set_route_hdr(_sip_dialog_t *dialog, sip_dlg_route_set_t *rset_head, 31740cb5e5dSvi117747 int rcnt, int rlen) 31840cb5e5dSvi117747 { 31940cb5e5dSvi117747 size_t rset_len; 32040cb5e5dSvi117747 _sip_header_t *rhdr; 32140cb5e5dSvi117747 char *rset; 32240cb5e5dSvi117747 char *rp; 32340cb5e5dSvi117747 char *rsp; 32440cb5e5dSvi117747 int count; 32540cb5e5dSvi117747 sip_dlg_route_set_t *route; 32640cb5e5dSvi117747 boolean_t first = B_TRUE; 32740cb5e5dSvi117747 const sip_str_t *to_uri; 32840cb5e5dSvi117747 char *uri = NULL; 32940cb5e5dSvi117747 int rspl; 33040cb5e5dSvi117747 int rpl; 33140cb5e5dSvi117747 332*943efbc3Sgm209912 if (rcnt <= 0) { 333*943efbc3Sgm209912 sip_write_to_log((void *)dialog, SIP_DIALOG_LOG | 334*943efbc3Sgm209912 SIP_ASSERT_ERROR, __FILE__, __LINE__); 335*943efbc3Sgm209912 } 33640cb5e5dSvi117747 assert(rcnt > 0); 33740cb5e5dSvi117747 33840cb5e5dSvi117747 dialog->sip_dlg_rset.sip_str_len = rlen + rcnt - 1; 33940cb5e5dSvi117747 dialog->sip_dlg_rset.sip_str_ptr = malloc(rlen + rcnt); 34040cb5e5dSvi117747 if (dialog->sip_dlg_rset.sip_str_ptr == NULL) 34140cb5e5dSvi117747 return (ENOMEM); 34240cb5e5dSvi117747 rsp = dialog->sip_dlg_rset.sip_str_ptr; 34340cb5e5dSvi117747 rspl = rlen + rcnt; 34440cb5e5dSvi117747 route = rset_head; 34540cb5e5dSvi117747 rset_len = rlen; 34640cb5e5dSvi117747 if (!route->sip_dlg_route_lr) { 34740cb5e5dSvi117747 const struct sip_value *val; 34840cb5e5dSvi117747 34940cb5e5dSvi117747 val = sip_get_header_value(dialog->sip_dlg_remote_target, NULL); 35040cb5e5dSvi117747 to_uri = &((sip_hdr_value_t *)val)->cftr_uri; 35140cb5e5dSvi117747 uri = (char *)malloc(to_uri->sip_str_len + 1); 35240cb5e5dSvi117747 if (uri == NULL) { 35340cb5e5dSvi117747 free(dialog->sip_dlg_rset.sip_str_ptr); 35440cb5e5dSvi117747 dialog->sip_dlg_rset.sip_str_len = 0; 35540cb5e5dSvi117747 dialog->sip_dlg_rset.sip_str_ptr = NULL; 35640cb5e5dSvi117747 return (ENOMEM); 35740cb5e5dSvi117747 } 35840cb5e5dSvi117747 (void) strncpy(uri, to_uri->sip_str_ptr, to_uri->sip_str_len); 35940cb5e5dSvi117747 uri[to_uri->sip_str_len] = '\0'; 36040cb5e5dSvi117747 rset_len = rlen - strlen(route->sip_dlg_route) + strlen(uri) + 36140cb5e5dSvi117747 SIP_SPACE_LEN + sizeof (char) + SIP_SPACE_LEN + 36240cb5e5dSvi117747 sizeof (char); 36340cb5e5dSvi117747 count = snprintf(rsp, rspl, "%s", route->sip_dlg_route); 36440cb5e5dSvi117747 dialog->sip_dlg_req_uri.sip_str_ptr = malloc( 36540cb5e5dSvi117747 route->sip_dlg_ruri.sip_str_len + 1); 36640cb5e5dSvi117747 if (dialog->sip_dlg_req_uri.sip_str_ptr == NULL) { 36740cb5e5dSvi117747 free(uri); 36840cb5e5dSvi117747 free(dialog->sip_dlg_rset.sip_str_ptr); 36940cb5e5dSvi117747 dialog->sip_dlg_rset.sip_str_len = 0; 37040cb5e5dSvi117747 dialog->sip_dlg_rset.sip_str_ptr = NULL; 37140cb5e5dSvi117747 return (ENOMEM); 37240cb5e5dSvi117747 } 37340cb5e5dSvi117747 (void) strncpy(dialog->sip_dlg_req_uri.sip_str_ptr, rsp + 37440cb5e5dSvi117747 (route->sip_dlg_ruri.sip_str_ptr - route->sip_dlg_route), 37540cb5e5dSvi117747 route->sip_dlg_ruri.sip_str_len); 37640cb5e5dSvi117747 dialog->sip_dlg_req_uri.sip_str_ptr[ 37740cb5e5dSvi117747 route->sip_dlg_ruri.sip_str_len] = '\0'; 37840cb5e5dSvi117747 dialog->sip_dlg_req_uri.sip_str_len = 37940cb5e5dSvi117747 route->sip_dlg_ruri.sip_str_len; 38040cb5e5dSvi117747 38140cb5e5dSvi117747 rsp += count; 38240cb5e5dSvi117747 rspl -= count; 38340cb5e5dSvi117747 route = route->sip_dlg_route_next; 38440cb5e5dSvi117747 } 38540cb5e5dSvi117747 38640cb5e5dSvi117747 /* 38740cb5e5dSvi117747 * rcnt - 1 is for the number of COMMAs 38840cb5e5dSvi117747 */ 38940cb5e5dSvi117747 rset_len += strlen(SIP_ROUTE) + SIP_SPACE_LEN + sizeof (char) + 39040cb5e5dSvi117747 SIP_SPACE_LEN + rcnt - 1; 39140cb5e5dSvi117747 rset = malloc(rset_len + 1); 39240cb5e5dSvi117747 if (rset == NULL) { 39340cb5e5dSvi117747 free(dialog->sip_dlg_rset.sip_str_ptr); 39440cb5e5dSvi117747 dialog->sip_dlg_rset.sip_str_len = 0; 39540cb5e5dSvi117747 dialog->sip_dlg_rset.sip_str_ptr = NULL; 39640cb5e5dSvi117747 return (ENOMEM); 39740cb5e5dSvi117747 } 39840cb5e5dSvi117747 rhdr = sip_new_header(rset_len + strlen(SIP_CRLF)); 39940cb5e5dSvi117747 if (rhdr == NULL) { 40040cb5e5dSvi117747 free(rset); 40140cb5e5dSvi117747 free(dialog->sip_dlg_rset.sip_str_ptr); 40240cb5e5dSvi117747 dialog->sip_dlg_rset.sip_str_len = 0; 40340cb5e5dSvi117747 dialog->sip_dlg_rset.sip_str_ptr = NULL; 40440cb5e5dSvi117747 return (ENOMEM); 40540cb5e5dSvi117747 } 40640cb5e5dSvi117747 40740cb5e5dSvi117747 rp = rset; 40840cb5e5dSvi117747 rpl = rset_len + 1; 40940cb5e5dSvi117747 count = snprintf(rp, rpl, "%s %c ", SIP_ROUTE, SIP_HCOLON); 41040cb5e5dSvi117747 rp += count; 41140cb5e5dSvi117747 rpl -= count; 41240cb5e5dSvi117747 41340cb5e5dSvi117747 while (route != NULL) { 41440cb5e5dSvi117747 if (first) { 41540cb5e5dSvi117747 count = snprintf(rp, rpl, "%s", route->sip_dlg_route); 41640cb5e5dSvi117747 rp += count; 41740cb5e5dSvi117747 rpl -= count; 41840cb5e5dSvi117747 first = B_FALSE; 41940cb5e5dSvi117747 if (uri != NULL) { 42040cb5e5dSvi117747 count = snprintf(rsp, rspl, "%c%s", 42140cb5e5dSvi117747 SIP_COMMA, route->sip_dlg_route); 42240cb5e5dSvi117747 } else { 42340cb5e5dSvi117747 count = snprintf(rsp, rspl, "%s", 42440cb5e5dSvi117747 route->sip_dlg_route); 42540cb5e5dSvi117747 } 42640cb5e5dSvi117747 rsp += count; 42740cb5e5dSvi117747 rspl -= count; 42840cb5e5dSvi117747 } else { 42940cb5e5dSvi117747 count = snprintf(rp, rpl, "%c%s", SIP_COMMA, 43040cb5e5dSvi117747 route->sip_dlg_route); 43140cb5e5dSvi117747 rp += count; 43240cb5e5dSvi117747 rpl -= count; 43340cb5e5dSvi117747 count = snprintf(rsp, rspl, "%c%s", SIP_COMMA, 43440cb5e5dSvi117747 route->sip_dlg_route); 43540cb5e5dSvi117747 rsp += count; 43640cb5e5dSvi117747 rspl -= count; 43740cb5e5dSvi117747 } 43840cb5e5dSvi117747 route = route->sip_dlg_route_next; 43940cb5e5dSvi117747 } 440*943efbc3Sgm209912 if (rsp > dialog->sip_dlg_rset.sip_str_ptr + 441*943efbc3Sgm209912 dialog->sip_dlg_rset.sip_str_len) { 442*943efbc3Sgm209912 sip_write_to_log((void *)dialog, SIP_DIALOG_LOG | 443*943efbc3Sgm209912 SIP_ASSERT_ERROR, __FILE__, __LINE__); 444*943efbc3Sgm209912 } 44540cb5e5dSvi117747 assert(rsp <= dialog->sip_dlg_rset.sip_str_ptr + 44640cb5e5dSvi117747 dialog->sip_dlg_rset.sip_str_len); 44740cb5e5dSvi117747 dialog->sip_dlg_rset.sip_str_ptr[dialog->sip_dlg_rset.sip_str_len] = 44840cb5e5dSvi117747 '\0'; 44940cb5e5dSvi117747 if (uri != NULL) { 45040cb5e5dSvi117747 if (first) { 45140cb5e5dSvi117747 count = snprintf(rp, rpl, "%c %s %c", SIP_LAQUOT, 45240cb5e5dSvi117747 uri, SIP_RAQUOT); 45340cb5e5dSvi117747 } else { 45440cb5e5dSvi117747 count = snprintf(rp, rpl, "%c%c %s %c", SIP_COMMA, 45540cb5e5dSvi117747 SIP_LAQUOT, uri, SIP_RAQUOT); 45640cb5e5dSvi117747 } 45740cb5e5dSvi117747 rp += count; 45840cb5e5dSvi117747 rpl -= count; 45940cb5e5dSvi117747 free(uri); 46040cb5e5dSvi117747 } 461*943efbc3Sgm209912 if (rp > rset + rset_len) { 462*943efbc3Sgm209912 sip_write_to_log((void *)dialog, SIP_DIALOG_LOG | 463*943efbc3Sgm209912 SIP_ASSERT_ERROR, __FILE__, __LINE__); 464*943efbc3Sgm209912 } 46540cb5e5dSvi117747 assert(rp <= rset + rset_len); 46640cb5e5dSvi117747 (void) snprintf(rhdr->sip_hdr_start, rset_len + strlen(SIP_CRLF) + 1, 46740cb5e5dSvi117747 "%s%s", rset, SIP_CRLF); 46840cb5e5dSvi117747 free(rset); 46940cb5e5dSvi117747 dialog->sip_dlg_route_set = (sip_header_t)rhdr; 47040cb5e5dSvi117747 sip_dialog_free_rset(rset_head); 47140cb5e5dSvi117747 return (0); 47240cb5e5dSvi117747 } 47340cb5e5dSvi117747 47440cb5e5dSvi117747 /* 47540cb5e5dSvi117747 * UAC Behavior 47640cb5e5dSvi117747 * The route set MUST be set to the list of URIs in the Record-Route 47740cb5e5dSvi117747 * header field from the response, taken in reverse order and preserving 47840cb5e5dSvi117747 * all URI parameters. 47940cb5e5dSvi117747 * 48040cb5e5dSvi117747 * UAS behavior 48140cb5e5dSvi117747 * The route set MUST be set to the list of URIs in the Record-Route 48240cb5e5dSvi117747 * header field from the request, taken in order and preserving all URI 48340cb5e5dSvi117747 * parameters. 48440cb5e5dSvi117747 */ 48540cb5e5dSvi117747 static int 48640cb5e5dSvi117747 sip_dialog_get_route_set(_sip_dialog_t *dialog, _sip_msg_t *sip_msg, int what) 48740cb5e5dSvi117747 { 48840cb5e5dSvi117747 sip_header_t rrhdr; 48940cb5e5dSvi117747 sip_hdr_value_t *value; 49040cb5e5dSvi117747 int error; 49140cb5e5dSvi117747 sip_dlg_route_set_t *rset_head = NULL; 49240cb5e5dSvi117747 sip_dlg_route_set_t *rset_tail = NULL; 49340cb5e5dSvi117747 sip_dlg_route_set_t *rset; 49440cb5e5dSvi117747 int rset_cnt = 0; 49540cb5e5dSvi117747 int rset_len = 0; 49640cb5e5dSvi117747 49740cb5e5dSvi117747 (void) pthread_mutex_lock(&sip_msg->sip_msg_mutex); 49840cb5e5dSvi117747 rrhdr = sip_search_for_header(sip_msg, SIP_RECORD_ROUTE, NULL); 49940cb5e5dSvi117747 while (rrhdr != NULL) { 50040cb5e5dSvi117747 (void) pthread_mutex_unlock(&sip_msg->sip_msg_mutex); 50140cb5e5dSvi117747 value = (sip_hdr_value_t *)sip_get_header_value(rrhdr, &error); 50240cb5e5dSvi117747 while (value != NULL && error == 0) { 50340cb5e5dSvi117747 char *crlf; 50440cb5e5dSvi117747 50540cb5e5dSvi117747 if (value->sip_value_state == SIP_VALUE_BAD) { 50640cb5e5dSvi117747 value = (sip_hdr_value_t *)sip_get_next_value( 50740cb5e5dSvi117747 (sip_header_value_t)value, &error); 50840cb5e5dSvi117747 continue; 50940cb5e5dSvi117747 } 51040cb5e5dSvi117747 rset = sip_add_route_to_set(value); 51140cb5e5dSvi117747 if (rset == NULL) 51240cb5e5dSvi117747 goto r_error; 51340cb5e5dSvi117747 /* 51440cb5e5dSvi117747 * Add one for COMMA 51540cb5e5dSvi117747 */ 51640cb5e5dSvi117747 rset_cnt++; 51740cb5e5dSvi117747 rset_len += (value->sip_value_end - 51840cb5e5dSvi117747 value->sip_value_start); 51940cb5e5dSvi117747 /* 52040cb5e5dSvi117747 * Check for CRLF 52140cb5e5dSvi117747 */ 52240cb5e5dSvi117747 crlf = value->sip_value_end - strlen(SIP_CRLF); 52340cb5e5dSvi117747 while (crlf != NULL && 52440cb5e5dSvi117747 strncmp(crlf, SIP_CRLF, strlen(SIP_CRLF)) == 0) { 52540cb5e5dSvi117747 rset_len -= strlen(SIP_CRLF); 52640cb5e5dSvi117747 crlf -= strlen(SIP_CRLF); 52740cb5e5dSvi117747 } 52840cb5e5dSvi117747 if (rset_head == NULL) { 529*943efbc3Sgm209912 if (rset_tail != NULL) { 530*943efbc3Sgm209912 sip_write_to_log((void *)dialog, 531*943efbc3Sgm209912 SIP_DIALOG_LOG | SIP_ASSERT_ERROR, 532*943efbc3Sgm209912 __FILE__, __LINE__); 533*943efbc3Sgm209912 } 53440cb5e5dSvi117747 assert(rset_tail == NULL); 53540cb5e5dSvi117747 rset_head = rset_tail = rset; 53640cb5e5dSvi117747 } else if (what == SIP_UAS_DIALOG) { 53740cb5e5dSvi117747 rset_tail->sip_dlg_route_next = rset; 53840cb5e5dSvi117747 rset_tail = rset; 53940cb5e5dSvi117747 } else if (what == SIP_UAC_DIALOG) { 54040cb5e5dSvi117747 rset->sip_dlg_route_next = rset_head; 54140cb5e5dSvi117747 rset_head = rset; 54240cb5e5dSvi117747 } else { 543*943efbc3Sgm209912 sip_write_to_log((void *)dialog, 544*943efbc3Sgm209912 SIP_DIALOG_LOG | SIP_ASSERT_ERROR, 545*943efbc3Sgm209912 __FILE__, __LINE__); 54640cb5e5dSvi117747 assert(0); 54740cb5e5dSvi117747 } 54840cb5e5dSvi117747 value = (sip_hdr_value_t *)sip_get_next_value( 54940cb5e5dSvi117747 (sip_header_value_t)value, &error); 55040cb5e5dSvi117747 } 55140cb5e5dSvi117747 (void) pthread_mutex_lock(&sip_msg->sip_msg_mutex); 55240cb5e5dSvi117747 rrhdr = sip_search_for_header(sip_msg, SIP_RECORD_ROUTE, rrhdr); 55340cb5e5dSvi117747 } 55440cb5e5dSvi117747 (void) pthread_mutex_unlock(&sip_msg->sip_msg_mutex); 55540cb5e5dSvi117747 if (rset_cnt == 0) 55640cb5e5dSvi117747 return (0); 55740cb5e5dSvi117747 if (sip_dialog_set_route_hdr(dialog, rset_head, rset_cnt, 55840cb5e5dSvi117747 rset_len) != 0) { 55940cb5e5dSvi117747 goto r_error; 56040cb5e5dSvi117747 } 56140cb5e5dSvi117747 return (0); 56240cb5e5dSvi117747 r_error: 56340cb5e5dSvi117747 sip_dialog_free_rset(rset_head); 56440cb5e5dSvi117747 return (ENOMEM); 56540cb5e5dSvi117747 } 56640cb5e5dSvi117747 56740cb5e5dSvi117747 /* 56840cb5e5dSvi117747 * UAS behavior: 56940cb5e5dSvi117747 * The remote sequence number MUST be set to the value of the sequence 57040cb5e5dSvi117747 * number in the CSeq header field of the request. The local sequence 57140cb5e5dSvi117747 * number MUST be empty. The call identifier component of the dialog ID 57240cb5e5dSvi117747 * MUST be set to the value of the Call-ID in the request. The local 57340cb5e5dSvi117747 * tag component of the dialog ID MUST be set to the tag in the To field 57440cb5e5dSvi117747 * in the response to the request (which always includes a tag), and the 57540cb5e5dSvi117747 * remote tag component of the dialog ID MUST be set to the tag from the 57640cb5e5dSvi117747 * From field in the request. A UAS MUST be prepared to receive a 57740cb5e5dSvi117747 * request without a tag in the From field, in which case the tag is 57840cb5e5dSvi117747 * considered to have a value of null. 57940cb5e5dSvi117747 * The remote URI MUST be set to the URI in the From field, and the 58040cb5e5dSvi117747 * local URI MUST be set to the URI in the To field. 58140cb5e5dSvi117747 * The remote target MUST be set to the URI from the Contact header field 58240cb5e5dSvi117747 * of the request. 58340cb5e5dSvi117747 * 58440cb5e5dSvi117747 * UAC behavior: 58540cb5e5dSvi117747 * The local sequence number MUST be set to the value of the sequence 58640cb5e5dSvi117747 * number in the CSeq header field of the request. The remote sequence 58740cb5e5dSvi117747 * number MUST be empty (it is established when the remote UA sends a 58840cb5e5dSvi117747 * request within the dialog). The call identifier component of the 58940cb5e5dSvi117747 * dialog ID MUST be set to the value of the Call-ID in the request. 59040cb5e5dSvi117747 * The local tag component of the dialog ID MUST be set to the tag in 59140cb5e5dSvi117747 * the From field in the request, and the remote tag component of the 59240cb5e5dSvi117747 * dialog ID MUST be set to the tag in the To field of the response. A 59340cb5e5dSvi117747 * UAC MUST be prepared to receive a response without a tag in the To 59440cb5e5dSvi117747 * field, in which case the tag is considered to have a value of null. 59540cb5e5dSvi117747 * The remote URI MUST be set to the URI in the To field, and the local 59640cb5e5dSvi117747 * URI MUST be set to the URI in the From field. 59740cb5e5dSvi117747 * The remote target MUST be set to the URI from the Contact header field 59840cb5e5dSvi117747 * of the response. 59940cb5e5dSvi117747 */ 60040cb5e5dSvi117747 60140cb5e5dSvi117747 60240cb5e5dSvi117747 /* 60340cb5e5dSvi117747 * This is the routine that seeds a dialog. 60440cb5e5dSvi117747 */ 60540cb5e5dSvi117747 sip_dialog_t 60640cb5e5dSvi117747 sip_seed_dialog(sip_conn_object_t obj, _sip_msg_t *sip_msg, 60740cb5e5dSvi117747 boolean_t dlg_on_fork, int dlg_type) 60840cb5e5dSvi117747 { 60940cb5e5dSvi117747 _sip_dialog_t *dialog; 61040cb5e5dSvi117747 int cseq; 61140cb5e5dSvi117747 sip_header_t fhdr = NULL; 61240cb5e5dSvi117747 sip_header_t thdr = NULL; 61340cb5e5dSvi117747 sip_header_t chdr; 61440cb5e5dSvi117747 sip_header_t cihdr; 61540cb5e5dSvi117747 sip_header_t evhdr = NULL; 61640cb5e5dSvi117747 const struct sip_value *value; 61740cb5e5dSvi117747 sip_dialog_timer_obj_t *tim_obj = NULL; 61840cb5e5dSvi117747 const sip_str_t *callid; 61940cb5e5dSvi117747 sip_method_t method; 62040cb5e5dSvi117747 int timer1 = sip_timer_T1; 62140cb5e5dSvi117747 int error; 62240cb5e5dSvi117747 62340cb5e5dSvi117747 if (!sip_msg_is_request((sip_msg_t)sip_msg, &error)) 62440cb5e5dSvi117747 return (NULL); 62540cb5e5dSvi117747 62640cb5e5dSvi117747 method = sip_get_request_method((sip_msg_t)sip_msg, &error); 62740cb5e5dSvi117747 /* 62840cb5e5dSvi117747 * Only INVITE and SUBSCRIBE supported 62940cb5e5dSvi117747 */ 63040cb5e5dSvi117747 if (error != 0 || (method != INVITE && method != SUBSCRIBE)) 63140cb5e5dSvi117747 return (NULL); 63240cb5e5dSvi117747 63340cb5e5dSvi117747 /* 63440cb5e5dSvi117747 * A request outside of a dialog MUST NOT contain a To tag 63540cb5e5dSvi117747 */ 63640cb5e5dSvi117747 if (sip_get_to_tag((sip_msg_t)sip_msg, NULL) != NULL) 63740cb5e5dSvi117747 return (NULL); 63840cb5e5dSvi117747 63940cb5e5dSvi117747 if (dlg_type == SIP_UAS_DIALOG) { 64040cb5e5dSvi117747 thdr = sip_dlg_xchg_from_to((sip_msg_t)sip_msg, 64140cb5e5dSvi117747 SIP_DLG_XCHG_FROM); 64240cb5e5dSvi117747 (void) pthread_mutex_lock(&sip_msg->sip_msg_mutex); 64340cb5e5dSvi117747 } else { 64440cb5e5dSvi117747 (void) pthread_mutex_lock(&sip_msg->sip_msg_mutex); 64540cb5e5dSvi117747 fhdr = sip_search_for_header(sip_msg, SIP_FROM, NULL); 64640cb5e5dSvi117747 } 64740cb5e5dSvi117747 cihdr = sip_search_for_header(sip_msg, SIP_CALL_ID, NULL); 64840cb5e5dSvi117747 chdr = sip_search_for_header(sip_msg, SIP_CONTACT, NULL); 64940cb5e5dSvi117747 if (method == SUBSCRIBE) 65040cb5e5dSvi117747 evhdr = sip_search_for_header(sip_msg, SIP_EVENT, NULL); 65140cb5e5dSvi117747 (void) pthread_mutex_unlock(&sip_msg->sip_msg_mutex); 65240cb5e5dSvi117747 if ((fhdr == NULL && thdr == NULL) || cihdr == NULL || chdr == NULL || 65340cb5e5dSvi117747 (method == SUBSCRIBE && evhdr == NULL)) { 65440cb5e5dSvi117747 if (thdr != NULL) 65540cb5e5dSvi117747 sip_free_header(thdr); 65640cb5e5dSvi117747 return (NULL); 65740cb5e5dSvi117747 } 65840cb5e5dSvi117747 65940cb5e5dSvi117747 /* 66040cb5e5dSvi117747 * Sanity check since we just store the headers in the dialog 66140cb5e5dSvi117747 */ 66240cb5e5dSvi117747 if (sip_get_from_tag((sip_msg_t)sip_msg, NULL) == NULL || 66340cb5e5dSvi117747 sip_get_from_uri_str((sip_msg_t)sip_msg, NULL) == NULL || 66440cb5e5dSvi117747 ((cseq = sip_get_callseq_num((sip_msg_t)sip_msg, NULL)) == -1) || 66540cb5e5dSvi117747 (callid = sip_get_callid((sip_msg_t)sip_msg, NULL)) == NULL || 66640cb5e5dSvi117747 sip_get_to_uri_str((sip_msg_t)sip_msg, NULL) == NULL || 66740cb5e5dSvi117747 ((value = sip_get_header_value(chdr, NULL)) == NULL) || 66840cb5e5dSvi117747 sip_get_contact_uri_str((sip_header_value_t)value, NULL) == NULL) { 66940cb5e5dSvi117747 if (thdr != NULL) 67040cb5e5dSvi117747 sip_free_header(thdr); 67140cb5e5dSvi117747 return (NULL); 67240cb5e5dSvi117747 } 67340cb5e5dSvi117747 67440cb5e5dSvi117747 tim_obj = calloc(1, sizeof (sip_dialog_timer_obj_t)); 67540cb5e5dSvi117747 if (tim_obj == NULL) { 67640cb5e5dSvi117747 if (thdr != NULL) 67740cb5e5dSvi117747 sip_free_header(thdr); 67840cb5e5dSvi117747 return (NULL); 67940cb5e5dSvi117747 } 68040cb5e5dSvi117747 dialog = calloc(1, sizeof (_sip_dialog_t)); 68140cb5e5dSvi117747 if (dialog == NULL) { 68240cb5e5dSvi117747 if (thdr != NULL) 68340cb5e5dSvi117747 sip_free_header(thdr); 68440cb5e5dSvi117747 return (NULL); 68540cb5e5dSvi117747 } 68640cb5e5dSvi117747 /* 68740cb5e5dSvi117747 * We will take the TO header with the tag when we complete this 68840cb5e5dSvi117747 * dialog 68940cb5e5dSvi117747 */ 69040cb5e5dSvi117747 if (dlg_type == SIP_UAS_DIALOG) { 69140cb5e5dSvi117747 dialog->sip_dlg_remote_uri_tag = thdr; 69240cb5e5dSvi117747 /* 69340cb5e5dSvi117747 * We take the remote target from the incoming request on the 69440cb5e5dSvi117747 * UAS. For the UAC, we will take it from the response. 69540cb5e5dSvi117747 */ 69640cb5e5dSvi117747 if ((dialog->sip_dlg_remote_target = sip_dup_header(chdr)) == 69740cb5e5dSvi117747 NULL) { 69840cb5e5dSvi117747 goto dia_err; 69940cb5e5dSvi117747 } 70040cb5e5dSvi117747 } else { 70140cb5e5dSvi117747 if ((dialog->sip_dlg_local_uri_tag = sip_dup_header(fhdr)) == 70240cb5e5dSvi117747 NULL) { 70340cb5e5dSvi117747 goto dia_err; 70440cb5e5dSvi117747 } 705d8a40387Sgm209912 /* 706d8a40387Sgm209912 * We take the local contact from the originating request on 707d8a40387Sgm209912 * UAC. For the UAS, we will take it from the response. 708d8a40387Sgm209912 */ 709d8a40387Sgm209912 if ((dialog->sip_dlg_local_contact = sip_dup_header(chdr)) == 710d8a40387Sgm209912 NULL) { 711d8a40387Sgm209912 goto dia_err; 712d8a40387Sgm209912 } else { 713d8a40387Sgm209912 dialog->sip_dlg_new_local_contact = NULL; 714d8a40387Sgm209912 } 71540cb5e5dSvi117747 } 71640cb5e5dSvi117747 if ((dialog->sip_dlg_call_id = sip_dup_header(cihdr)) == NULL) 71740cb5e5dSvi117747 goto dia_err; 71840cb5e5dSvi117747 if (method == SUBSCRIBE) { 71940cb5e5dSvi117747 dialog->sip_dlg_event = sip_dup_header(evhdr); 72040cb5e5dSvi117747 if (dialog->sip_dlg_event == NULL) { 72140cb5e5dSvi117747 goto dia_err; 72240cb5e5dSvi117747 } 72340cb5e5dSvi117747 } 72440cb5e5dSvi117747 dialog->sip_dlg_rset.sip_str_ptr = NULL; 72540cb5e5dSvi117747 dialog->sip_dlg_rset.sip_str_len = 0; 72640cb5e5dSvi117747 dialog->sip_dlg_req_uri.sip_str_ptr = NULL; 72740cb5e5dSvi117747 dialog->sip_dlg_req_uri.sip_str_len = 0; 72840cb5e5dSvi117747 /* 72940cb5e5dSvi117747 * Get the route set from the request, if present 73040cb5e5dSvi117747 */ 73140cb5e5dSvi117747 if (dlg_type == SIP_UAS_DIALOG && 73240cb5e5dSvi117747 sip_dialog_get_route_set(dialog, sip_msg, dlg_type) != 0) { 73340cb5e5dSvi117747 goto dia_err; 73440cb5e5dSvi117747 } 73540cb5e5dSvi117747 if (dlg_type == SIP_UAC_DIALOG) 73640cb5e5dSvi117747 dialog->sip_dlg_local_cseq = cseq; 73740cb5e5dSvi117747 else 73840cb5e5dSvi117747 dialog->sip_dlg_remote_cseq = cseq; 73940cb5e5dSvi117747 dialog->sip_dlg_type = dlg_type; 74040cb5e5dSvi117747 dialog->sip_dlg_on_fork = dlg_on_fork; 74140cb5e5dSvi117747 dialog->sip_dlg_method = method; 74240cb5e5dSvi117747 /* 74340cb5e5dSvi117747 * Set the partial dialog timer with the INVITE timeout val 74440cb5e5dSvi117747 */ 74540cb5e5dSvi117747 if (sip_conn_timer1 != NULL) 74640cb5e5dSvi117747 timer1 = sip_conn_timer1(obj); 74740cb5e5dSvi117747 SIP_INIT_TIMER(dialog->sip_dlg_timer, 64 * timer1); 74840cb5e5dSvi117747 tim_obj->dialog = dialog; 74940cb5e5dSvi117747 /* 75040cb5e5dSvi117747 * Since at the client we never pass the partial dialog, we need not 75140cb5e5dSvi117747 * invoke the callback when the partial dialog self-destructs. 75240cb5e5dSvi117747 */ 75340cb5e5dSvi117747 if (dlg_type == SIP_UAS_DIALOG) 75440cb5e5dSvi117747 tim_obj->func = sip_ulp_dlg_del_cb; 75540cb5e5dSvi117747 SIP_SCHED_TIMER(dialog->sip_dlg_timer, (void *)tim_obj, 75640cb5e5dSvi117747 sip_dlg_self_destruct); 75740cb5e5dSvi117747 if (!SIP_IS_TIMER_RUNNING(dialog->sip_dlg_timer)) 75840cb5e5dSvi117747 goto dia_err; 75940cb5e5dSvi117747 (void) pthread_mutex_init(&dialog->sip_dlg_mutex, NULL); 76040cb5e5dSvi117747 76140cb5e5dSvi117747 if (dlg_type == SIP_UAC_DIALOG) { 76240cb5e5dSvi117747 const sip_str_t *local_tag; 76340cb5e5dSvi117747 76440cb5e5dSvi117747 local_tag = sip_get_from_tag((sip_msg_t)sip_msg, NULL); 765*943efbc3Sgm209912 if (local_tag == NULL) { 766*943efbc3Sgm209912 sip_write_to_log((void *)dialog, SIP_DIALOG_LOG | 767*943efbc3Sgm209912 SIP_ASSERT_ERROR, __FILE__, __LINE__); 768*943efbc3Sgm209912 } 76940cb5e5dSvi117747 assert(local_tag != NULL); 77040cb5e5dSvi117747 sip_md5_hash(local_tag->sip_str_ptr, local_tag->sip_str_len, 77140cb5e5dSvi117747 callid->sip_str_ptr, callid->sip_str_len, 77240cb5e5dSvi117747 NULL, 0, NULL, 0, NULL, 0, NULL, 0, 77340cb5e5dSvi117747 (uchar_t *)dialog->sip_dlg_id); 77440cb5e5dSvi117747 77540cb5e5dSvi117747 77640cb5e5dSvi117747 /* 77740cb5e5dSvi117747 * Add it to the partial hash table 77840cb5e5dSvi117747 */ 77940cb5e5dSvi117747 if (sip_hash_add(sip_dialog_phash, (void *)dialog, 78040cb5e5dSvi117747 SIP_DIGEST_TO_HASH(dialog->sip_dlg_id)) != 0) { 78140cb5e5dSvi117747 goto dia_err; 78240cb5e5dSvi117747 } 78340cb5e5dSvi117747 } 784*943efbc3Sgm209912 785*943efbc3Sgm209912 dialog->sip_dlg_msgcnt = 1; 786*943efbc3Sgm209912 sip_add_log(&dialog->sip_dlg_log[dialog->sip_dlg_state], 787*943efbc3Sgm209912 (sip_msg_t)sip_msg, dialog->sip_dlg_msgcnt, SIP_DIALOG_LOG); 788*943efbc3Sgm209912 78940cb5e5dSvi117747 SIP_DLG_REFCNT_INCR(dialog); 79040cb5e5dSvi117747 return ((sip_dialog_t)dialog); 79140cb5e5dSvi117747 dia_err: 79240cb5e5dSvi117747 sip_release_dialog_res(dialog); 79340cb5e5dSvi117747 if (SIP_IS_TIMER_RUNNING(dialog->sip_dlg_timer)) 79440cb5e5dSvi117747 SIP_CANCEL_TIMER(dialog->sip_dlg_timer); 79540cb5e5dSvi117747 if (tim_obj != NULL) 79640cb5e5dSvi117747 free(tim_obj); 79740cb5e5dSvi117747 return (NULL); 79840cb5e5dSvi117747 } 79940cb5e5dSvi117747 80040cb5e5dSvi117747 /* 80140cb5e5dSvi117747 * When creating a dialog from a NOTIFY request, we need to get the FROM 80240cb5e5dSvi117747 * header for the dialog from the TO header of the NOTIFY. 80340cb5e5dSvi117747 */ 80440cb5e5dSvi117747 _sip_header_t * 80540cb5e5dSvi117747 sip_dlg_xchg_from_to(sip_msg_t sip_msg, int what) 80640cb5e5dSvi117747 { 80740cb5e5dSvi117747 int len; 80840cb5e5dSvi117747 _sip_header_t *newhdr; 80940cb5e5dSvi117747 int cnt; 81040cb5e5dSvi117747 const struct sip_header *hdr; 81140cb5e5dSvi117747 int hdrsize; 81240cb5e5dSvi117747 int error; 81340cb5e5dSvi117747 81440cb5e5dSvi117747 hdr = sip_get_header(sip_msg, what == SIP_DLG_XCHG_FROM ? SIP_FROM : 81540cb5e5dSvi117747 SIP_TO, NULL, &error); 81640cb5e5dSvi117747 if (error != 0 || hdr == NULL) 81740cb5e5dSvi117747 return (NULL); 81840cb5e5dSvi117747 if (sip_parse_goto_values((_sip_header_t *)hdr) != 0) 81940cb5e5dSvi117747 return (NULL); 82040cb5e5dSvi117747 len = hdr->sip_hdr_end - hdr->sip_hdr_current; 82140cb5e5dSvi117747 if (what == SIP_DLG_XCHG_FROM) { 82240cb5e5dSvi117747 hdrsize = len + strlen(SIP_TO) + SIP_SPACE_LEN + sizeof (char) + 82340cb5e5dSvi117747 SIP_SPACE_LEN; 82440cb5e5dSvi117747 } else { 82540cb5e5dSvi117747 hdrsize = len + strlen(SIP_FROM) + SIP_SPACE_LEN + 82640cb5e5dSvi117747 sizeof (char) + SIP_SPACE_LEN; 82740cb5e5dSvi117747 } 82840cb5e5dSvi117747 newhdr = sip_new_header(hdrsize); 82940cb5e5dSvi117747 if (newhdr == NULL) 83040cb5e5dSvi117747 return (NULL); 83140cb5e5dSvi117747 if (what == SIP_DLG_XCHG_FROM) { 83240cb5e5dSvi117747 cnt = snprintf(newhdr->sip_hdr_current, hdrsize + 1, 83340cb5e5dSvi117747 "%s %c ", SIP_TO, SIP_HCOLON); 83440cb5e5dSvi117747 } else { 83540cb5e5dSvi117747 cnt = snprintf(newhdr->sip_hdr_current, hdrsize + 1, 83640cb5e5dSvi117747 "%s %c ", SIP_FROM, SIP_HCOLON); 83740cb5e5dSvi117747 } 83840cb5e5dSvi117747 newhdr->sip_hdr_current += cnt; 83940cb5e5dSvi117747 (void) strncpy(newhdr->sip_hdr_current, hdr->sip_hdr_current, len); 84040cb5e5dSvi117747 newhdr->sip_hdr_current += len; 84140cb5e5dSvi117747 assert(newhdr->sip_hdr_current == newhdr->sip_hdr_end); 84240cb5e5dSvi117747 assert(hdr->sip_header_functions != NULL); 84340cb5e5dSvi117747 84440cb5e5dSvi117747 /* 84540cb5e5dSvi117747 * FROM and TO have common parsing functions 84640cb5e5dSvi117747 */ 84740cb5e5dSvi117747 newhdr->sip_header_functions = hdr->sip_header_functions; 84840cb5e5dSvi117747 newhdr->sip_hdr_current = newhdr->sip_hdr_start; 84940cb5e5dSvi117747 85040cb5e5dSvi117747 return (newhdr); 85140cb5e5dSvi117747 } 85240cb5e5dSvi117747 85340cb5e5dSvi117747 /* 85440cb5e5dSvi117747 * This is the response that completes the dialog that was created 85540cb5e5dSvi117747 * in sip_seed_dialog(). 85640cb5e5dSvi117747 */ 85740cb5e5dSvi117747 sip_dialog_t 85840cb5e5dSvi117747 sip_complete_dialog(_sip_msg_t *sip_msg, _sip_dialog_t *dialog) 85940cb5e5dSvi117747 { 86040cb5e5dSvi117747 _sip_header_t *thdr; 86140cb5e5dSvi117747 _sip_header_t *evhdr = NULL; 86240cb5e5dSvi117747 _sip_header_t *substate = NULL; 86340cb5e5dSvi117747 sip_header_t chdr = NULL; 86440cb5e5dSvi117747 int resp_code; 86540cb5e5dSvi117747 const sip_str_t *ttag; 86640cb5e5dSvi117747 const sip_str_t *remtag; 86740cb5e5dSvi117747 const sip_str_t *callid; 86840cb5e5dSvi117747 const struct sip_value *val; 86940cb5e5dSvi117747 sip_method_t method; 87040cb5e5dSvi117747 int error = 0; 87140cb5e5dSvi117747 int prev_state; 87240cb5e5dSvi117747 boolean_t alloc_thdr = B_FALSE; 87340cb5e5dSvi117747 87440cb5e5dSvi117747 if (sip_msg_is_request((sip_msg_t)sip_msg, &error) && error == 0) 87540cb5e5dSvi117747 method = sip_get_request_method((sip_msg_t)sip_msg, &error); 87640cb5e5dSvi117747 else 87740cb5e5dSvi117747 method = sip_get_callseq_method((sip_msg_t)sip_msg, &error); 87840cb5e5dSvi117747 if (error != 0 || dialog == NULL || 87940cb5e5dSvi117747 (sip_msg_is_request((sip_msg_t)sip_msg, &error) && 88040cb5e5dSvi117747 (dialog->sip_dlg_method == INVITE || method != NOTIFY))) { 88140cb5e5dSvi117747 return (NULL); 88240cb5e5dSvi117747 } 88340cb5e5dSvi117747 if ((dialog->sip_dlg_type == SIP_UAC_DIALOG && method != NOTIFY && 88440cb5e5dSvi117747 sip_get_callseq_num((sip_msg_t)sip_msg, NULL) != 88540cb5e5dSvi117747 dialog->sip_dlg_local_cseq) || 88640cb5e5dSvi117747 (dialog->sip_dlg_type == SIP_UAS_DIALOG && method != NOTIFY && 88740cb5e5dSvi117747 sip_get_callseq_num((sip_msg_t)sip_msg, NULL) != 88840cb5e5dSvi117747 dialog->sip_dlg_remote_cseq)) { 88940cb5e5dSvi117747 return (NULL); 89040cb5e5dSvi117747 } 89140cb5e5dSvi117747 if (method == NOTIFY) { 89240cb5e5dSvi117747 const sip_str_t *sstate; 89340cb5e5dSvi117747 89440cb5e5dSvi117747 thdr = sip_dlg_xchg_from_to((sip_msg_t)sip_msg, 89540cb5e5dSvi117747 SIP_DLG_XCHG_FROM); 89640cb5e5dSvi117747 if (thdr == NULL) 89740cb5e5dSvi117747 return (NULL); 89840cb5e5dSvi117747 alloc_thdr = B_TRUE; 89940cb5e5dSvi117747 (void) pthread_mutex_lock(&sip_msg->sip_msg_mutex); 90040cb5e5dSvi117747 chdr = sip_search_for_header(sip_msg, SIP_CONTACT, NULL); 90140cb5e5dSvi117747 if (chdr == NULL) { 90240cb5e5dSvi117747 (void) pthread_mutex_unlock(&sip_msg->sip_msg_mutex); 90340cb5e5dSvi117747 sip_free_header(thdr); 90440cb5e5dSvi117747 return (NULL); 90540cb5e5dSvi117747 } 90640cb5e5dSvi117747 evhdr = sip_search_for_header(sip_msg, SIP_EVENT, NULL); 90740cb5e5dSvi117747 if (evhdr == NULL) { 90840cb5e5dSvi117747 (void) pthread_mutex_unlock(&sip_msg->sip_msg_mutex); 90940cb5e5dSvi117747 sip_free_header(thdr); 91040cb5e5dSvi117747 return (NULL); 91140cb5e5dSvi117747 } 91240cb5e5dSvi117747 substate = sip_search_for_header(sip_msg, 91340cb5e5dSvi117747 SIP_SUBSCRIPTION_STATE, NULL); 91440cb5e5dSvi117747 if (substate == NULL) { 91540cb5e5dSvi117747 (void) pthread_mutex_unlock(&sip_msg->sip_msg_mutex); 91640cb5e5dSvi117747 sip_free_header(thdr); 91740cb5e5dSvi117747 return (NULL); 91840cb5e5dSvi117747 } 91940cb5e5dSvi117747 (void) pthread_mutex_unlock(&sip_msg->sip_msg_mutex); 92040cb5e5dSvi117747 sstate = sip_get_substate((sip_msg_t)sip_msg, &error); 92140cb5e5dSvi117747 if (sstate == NULL || error != 0) { 92240cb5e5dSvi117747 sip_free_header(thdr); 92340cb5e5dSvi117747 return (NULL); 92440cb5e5dSvi117747 } 92540cb5e5dSvi117747 if ((sstate->sip_str_len != strlen("pending") && 92640cb5e5dSvi117747 sstate->sip_str_len != strlen("active")) || 92740cb5e5dSvi117747 ((sstate->sip_str_len == strlen("pending") && 92840cb5e5dSvi117747 strncasecmp(sstate->sip_str_ptr, "pending", 92940cb5e5dSvi117747 strlen("pending")) != 0) || 93040cb5e5dSvi117747 (sstate->sip_str_len == strlen("active") && 93140cb5e5dSvi117747 strncasecmp(sstate->sip_str_ptr, "active", 93240cb5e5dSvi117747 strlen("active")) != 0))) { 93340cb5e5dSvi117747 sip_free_header(thdr); 93440cb5e5dSvi117747 return (NULL); 93540cb5e5dSvi117747 } 93640cb5e5dSvi117747 ttag = sip_get_from_tag((sip_msg_t)sip_msg, NULL); 93740cb5e5dSvi117747 } else { 93840cb5e5dSvi117747 if (dialog->sip_dlg_type == SIP_UAS_DIALOG) { 93940cb5e5dSvi117747 thdr = sip_dlg_xchg_from_to((sip_msg_t)sip_msg, 94040cb5e5dSvi117747 SIP_DLG_XCHG_TO); 94140cb5e5dSvi117747 alloc_thdr = B_TRUE; 94240cb5e5dSvi117747 } else { 94340cb5e5dSvi117747 (void) pthread_mutex_lock(&sip_msg->sip_msg_mutex); 94440cb5e5dSvi117747 thdr = sip_search_for_header(sip_msg, SIP_TO, NULL); 94540cb5e5dSvi117747 if (dialog->sip_dlg_remote_target == NULL) { 94640cb5e5dSvi117747 chdr = sip_search_for_header(sip_msg, 94740cb5e5dSvi117747 SIP_CONTACT, NULL); 94840cb5e5dSvi117747 } 94940cb5e5dSvi117747 (void) pthread_mutex_unlock(&sip_msg->sip_msg_mutex); 95040cb5e5dSvi117747 } 95140cb5e5dSvi117747 if (thdr == NULL) { 95240cb5e5dSvi117747 (void) pthread_mutex_unlock(&sip_msg->sip_msg_mutex); 95340cb5e5dSvi117747 return (NULL); 95440cb5e5dSvi117747 } 95540cb5e5dSvi117747 ttag = sip_get_to_tag((sip_msg_t)sip_msg, NULL); 95640cb5e5dSvi117747 } 95740cb5e5dSvi117747 if (ttag == NULL) { 95840cb5e5dSvi117747 if (alloc_thdr) 95940cb5e5dSvi117747 sip_free_header(thdr); 96040cb5e5dSvi117747 return (NULL); 96140cb5e5dSvi117747 } 96240cb5e5dSvi117747 prev_state = dialog->sip_dlg_state; 96340cb5e5dSvi117747 96440cb5e5dSvi117747 if (method == NOTIFY) { 96540cb5e5dSvi117747 int error; 96640cb5e5dSvi117747 const sip_str_t *dlg_id_val = NULL; 96740cb5e5dSvi117747 const sip_str_t *event; 96840cb5e5dSvi117747 const sip_str_t *id_val = NULL; 96940cb5e5dSvi117747 sip_header_value_t ev_val; 97040cb5e5dSvi117747 sip_hdr_value_t *dlg_ev_val = NULL; 97140cb5e5dSvi117747 97240cb5e5dSvi117747 event = sip_get_event((sip_msg_t)sip_msg, &error); 97340cb5e5dSvi117747 if (event == NULL || error != 0) { 97440cb5e5dSvi117747 sip_free_header(thdr); 97540cb5e5dSvi117747 return (NULL); 97640cb5e5dSvi117747 } 97740cb5e5dSvi117747 ev_val = (sip_header_value_t)sip_get_header_value(evhdr, 97840cb5e5dSvi117747 &error); 97940cb5e5dSvi117747 if (ev_val != NULL) 98040cb5e5dSvi117747 id_val = sip_get_param_value(ev_val, "id", &error); 98140cb5e5dSvi117747 if (error == 0) { 98240cb5e5dSvi117747 dlg_ev_val = (sip_hdr_value_t *)sip_get_header_value( 98340cb5e5dSvi117747 dialog->sip_dlg_event, &error); 98440cb5e5dSvi117747 } 98540cb5e5dSvi117747 if (dlg_ev_val == NULL || error != 0) { 98640cb5e5dSvi117747 sip_free_header(thdr); 98740cb5e5dSvi117747 return (NULL); 98840cb5e5dSvi117747 } 98940cb5e5dSvi117747 dlg_id_val = sip_get_param_value((sip_header_value_t)dlg_ev_val, 99040cb5e5dSvi117747 "id", &error); 99140cb5e5dSvi117747 if (error != 0 || 99240cb5e5dSvi117747 dlg_ev_val->str_val_len != event->sip_str_len || 99340cb5e5dSvi117747 strncmp(dlg_ev_val->str_val_ptr, event->sip_str_ptr, 99440cb5e5dSvi117747 event->sip_str_len != 0)) { 99540cb5e5dSvi117747 sip_free_header(thdr); 99640cb5e5dSvi117747 return (NULL); 99740cb5e5dSvi117747 } 99840cb5e5dSvi117747 if ((dlg_id_val == NULL && id_val != NULL) || 99940cb5e5dSvi117747 (dlg_id_val != NULL && id_val == NULL)) { 100040cb5e5dSvi117747 sip_free_header(thdr); 100140cb5e5dSvi117747 return (NULL); 100240cb5e5dSvi117747 } else if (dlg_id_val != NULL && id_val != NULL) { 100340cb5e5dSvi117747 if (dlg_id_val->sip_str_len != id_val->sip_str_len || 100440cb5e5dSvi117747 strncasecmp(dlg_id_val->sip_str_ptr, 100540cb5e5dSvi117747 id_val->sip_str_ptr, dlg_id_val->sip_str_len) != 100640cb5e5dSvi117747 0) { 100740cb5e5dSvi117747 sip_free_header(thdr); 100840cb5e5dSvi117747 return (NULL); 100940cb5e5dSvi117747 } 101040cb5e5dSvi117747 } 101140cb5e5dSvi117747 if (dialog->sip_dlg_type == SIP_UAC_DIALOG) { 101240cb5e5dSvi117747 dialog->sip_dlg_remote_uri_tag = thdr; 101340cb5e5dSvi117747 if ((dialog->sip_dlg_remote_target = 101440cb5e5dSvi117747 sip_dup_header(chdr)) == NULL) { 101540cb5e5dSvi117747 sip_free_header(thdr); 101640cb5e5dSvi117747 return (NULL); 101740cb5e5dSvi117747 } 101840cb5e5dSvi117747 } else { 101940cb5e5dSvi117747 dialog->sip_dlg_local_uri_tag = thdr; 102040cb5e5dSvi117747 } 102140cb5e5dSvi117747 dialog->sip_dlg_state = SIP_DLG_CONFIRMED; 102240cb5e5dSvi117747 } else { 102340cb5e5dSvi117747 resp_code = sip_get_response_code((sip_msg_t)sip_msg, &error); 102440cb5e5dSvi117747 (void) pthread_mutex_lock(&dialog->sip_dlg_mutex); 1025*943efbc3Sgm209912 if (dialog->sip_dlg_state != SIP_DLG_NEW) { 1026*943efbc3Sgm209912 sip_write_to_log((void *)dialog, SIP_DIALOG_LOG | 1027*943efbc3Sgm209912 SIP_ASSERT_ERROR, __FILE__, __LINE__); 1028*943efbc3Sgm209912 } 102940cb5e5dSvi117747 assert(dialog->sip_dlg_state == SIP_DLG_NEW); 103040cb5e5dSvi117747 if (dialog->sip_dlg_remote_target == NULL && chdr != NULL) { 1031*943efbc3Sgm209912 if (dialog->sip_dlg_type != SIP_UAC_DIALOG) { 1032*943efbc3Sgm209912 sip_write_to_log((void *)dialog, 1033*943efbc3Sgm209912 SIP_DIALOG_LOG | SIP_ASSERT_ERROR, 1034*943efbc3Sgm209912 __FILE__, __LINE__); 1035*943efbc3Sgm209912 } 103640cb5e5dSvi117747 assert(dialog->sip_dlg_type == SIP_UAC_DIALOG); 103740cb5e5dSvi117747 if ((dialog->sip_dlg_remote_target = 103840cb5e5dSvi117747 sip_dup_header(chdr)) == NULL) { 103940cb5e5dSvi117747 (void) pthread_mutex_unlock( 104040cb5e5dSvi117747 &dialog->sip_dlg_mutex); 104140cb5e5dSvi117747 if (alloc_thdr) 104240cb5e5dSvi117747 sip_free_header(thdr); 10432c2c4183Svi117747 goto terminate_new_dlg; 104440cb5e5dSvi117747 } 104540cb5e5dSvi117747 if (sip_dialog_get_route_set(dialog, sip_msg, 104640cb5e5dSvi117747 dialog->sip_dlg_type) != 0) { 104740cb5e5dSvi117747 (void) pthread_mutex_unlock( 104840cb5e5dSvi117747 &dialog->sip_dlg_mutex); 104940cb5e5dSvi117747 if (alloc_thdr) 105040cb5e5dSvi117747 sip_free_header(thdr); 10512c2c4183Svi117747 goto terminate_new_dlg; 105240cb5e5dSvi117747 } 105340cb5e5dSvi117747 } 105440cb5e5dSvi117747 if (SIP_PROVISIONAL_RESP(resp_code)) { 105540cb5e5dSvi117747 dialog->sip_dlg_state = SIP_DLG_EARLY; 105640cb5e5dSvi117747 } else if (SIP_OK_RESP(resp_code)) { 105740cb5e5dSvi117747 /* 105840cb5e5dSvi117747 * Per 12.1 the UAS must include the contact header 105940cb5e5dSvi117747 * for a dialog establishing response, so if we 106040cb5e5dSvi117747 * don't find one, we terminate it. 106140cb5e5dSvi117747 */ 106240cb5e5dSvi117747 if (dialog->sip_dlg_remote_target == NULL) { 106340cb5e5dSvi117747 (void) pthread_mutex_unlock( 106440cb5e5dSvi117747 &dialog->sip_dlg_mutex); 106540cb5e5dSvi117747 if (sip_ulp_dlg_del_cb != NULL) { 106640cb5e5dSvi117747 sip_ulp_dlg_del_cb(dialog, 106740cb5e5dSvi117747 (sip_msg_t)sip_msg, NULL); 106840cb5e5dSvi117747 } 106940cb5e5dSvi117747 if (alloc_thdr) 107040cb5e5dSvi117747 sip_free_header(thdr); 10712c2c4183Svi117747 goto terminate_new_dlg; 107240cb5e5dSvi117747 } 107340cb5e5dSvi117747 dialog->sip_dlg_state = SIP_DLG_CONFIRMED; 107440cb5e5dSvi117747 } else { 107540cb5e5dSvi117747 (void) pthread_mutex_unlock(&dialog->sip_dlg_mutex); 107640cb5e5dSvi117747 if (sip_ulp_dlg_del_cb != NULL) { 107740cb5e5dSvi117747 sip_ulp_dlg_del_cb(dialog, (sip_msg_t)sip_msg, 107840cb5e5dSvi117747 NULL); 107940cb5e5dSvi117747 } 108040cb5e5dSvi117747 if (alloc_thdr) 108140cb5e5dSvi117747 sip_free_header(thdr); 10822c2c4183Svi117747 goto terminate_new_dlg; 108340cb5e5dSvi117747 } 108440cb5e5dSvi117747 if (dialog->sip_dlg_type == SIP_UAS_DIALOG) { 108540cb5e5dSvi117747 dialog->sip_dlg_local_uri_tag = thdr; 108640cb5e5dSvi117747 } else { 108740cb5e5dSvi117747 if ((dialog->sip_dlg_remote_uri_tag = 108840cb5e5dSvi117747 sip_dup_header(thdr)) == NULL) { 108940cb5e5dSvi117747 (void) pthread_mutex_unlock( 109040cb5e5dSvi117747 &dialog->sip_dlg_mutex); 10912c2c4183Svi117747 goto terminate_new_dlg; 109240cb5e5dSvi117747 } 109340cb5e5dSvi117747 } 109440cb5e5dSvi117747 } 109540cb5e5dSvi117747 109640cb5e5dSvi117747 /* 1097d8a40387Sgm209912 * We take the local contact for UAS Dialog from the response (either 1098d8a40387Sgm209912 * NOTIFY for SUBSCRIBE request or from final response 2xx to INVITE 1099d8a40387Sgm209912 * request) 1100d8a40387Sgm209912 */ 1101d8a40387Sgm209912 if ((dialog->sip_dlg_type == SIP_UAS_DIALOG) && (dialog->sip_dlg_state 1102d8a40387Sgm209912 == SIP_DLG_CONFIRMED)) { 1103d8a40387Sgm209912 if (chdr == NULL) { 1104d8a40387Sgm209912 (void) pthread_mutex_lock(&sip_msg->sip_msg_mutex); 1105d8a40387Sgm209912 chdr = sip_search_for_header(sip_msg, SIP_CONTACT, 1106d8a40387Sgm209912 NULL); 1107d8a40387Sgm209912 (void) pthread_mutex_unlock(&sip_msg->sip_msg_mutex); 1108d8a40387Sgm209912 } 1109d8a40387Sgm209912 if ((chdr == NULL) || ((dialog->sip_dlg_local_contact = 1110d8a40387Sgm209912 sip_dup_header(chdr)) == NULL)) { 1111d8a40387Sgm209912 (void) pthread_mutex_unlock(&dialog->sip_dlg_mutex); 1112d8a40387Sgm209912 if (alloc_thdr) 1113d8a40387Sgm209912 sip_free_header(thdr); 1114d8a40387Sgm209912 goto terminate_new_dlg; 1115d8a40387Sgm209912 } 1116d8a40387Sgm209912 } 1117d8a40387Sgm209912 1118d8a40387Sgm209912 /* 111940cb5e5dSvi117747 * Cancel the partial dialog timer 112040cb5e5dSvi117747 */ 112140cb5e5dSvi117747 if (SIP_IS_TIMER_RUNNING(dialog->sip_dlg_timer)) 112240cb5e5dSvi117747 SIP_CANCEL_TIMER(dialog->sip_dlg_timer); 112340cb5e5dSvi117747 112440cb5e5dSvi117747 if (dialog->sip_dlg_type == SIP_UAC_DIALOG) { 112540cb5e5dSvi117747 val = sip_get_header_value(dialog->sip_dlg_local_uri_tag, 112640cb5e5dSvi117747 &error); 112740cb5e5dSvi117747 } else { 112840cb5e5dSvi117747 val = sip_get_header_value(dialog->sip_dlg_remote_uri_tag, 112940cb5e5dSvi117747 &error); 113040cb5e5dSvi117747 } 1131*943efbc3Sgm209912 if (val == NULL || error != 0) { 1132*943efbc3Sgm209912 sip_write_to_log((void *)dialog, SIP_DIALOG_LOG | 1133*943efbc3Sgm209912 SIP_ASSERT_ERROR, __FILE__, __LINE__); 1134*943efbc3Sgm209912 } 113540cb5e5dSvi117747 assert(val != NULL && error == 0); 113640cb5e5dSvi117747 remtag = sip_get_param_value((sip_header_value_t)val, "tag", &error); 113740cb5e5dSvi117747 113840cb5e5dSvi117747 val = sip_get_header_value(dialog->sip_dlg_call_id, &error); 113940cb5e5dSvi117747 callid = &((sip_hdr_value_t *)val)->str_val; 114040cb5e5dSvi117747 114140cb5e5dSvi117747 /* 114240cb5e5dSvi117747 * Get an ID for this dialog 114340cb5e5dSvi117747 */ 114440cb5e5dSvi117747 if (dialog->sip_dlg_type == SIP_UAC_DIALOG) { 114540cb5e5dSvi117747 sip_md5_hash(remtag->sip_str_ptr, remtag->sip_str_len, 114640cb5e5dSvi117747 ttag->sip_str_ptr, ttag->sip_str_len, 114740cb5e5dSvi117747 callid->sip_str_ptr, callid->sip_str_len, 114840cb5e5dSvi117747 NULL, 0, NULL, 0, NULL, 0, (uchar_t *)dialog->sip_dlg_id); 114940cb5e5dSvi117747 } else { 115040cb5e5dSvi117747 sip_md5_hash(ttag->sip_str_ptr, ttag->sip_str_len, 115140cb5e5dSvi117747 remtag->sip_str_ptr, remtag->sip_str_len, 115240cb5e5dSvi117747 callid->sip_str_ptr, callid->sip_str_len, 115340cb5e5dSvi117747 NULL, 0, NULL, 0, NULL, 0, (uchar_t *)dialog->sip_dlg_id); 115440cb5e5dSvi117747 } 115540cb5e5dSvi117747 115640cb5e5dSvi117747 SIP_DLG_REFCNT_INCR(dialog); 115740cb5e5dSvi117747 (void) pthread_mutex_unlock(&dialog->sip_dlg_mutex); 115840cb5e5dSvi117747 115940cb5e5dSvi117747 /* 116040cb5e5dSvi117747 * Add it to the hash table 116140cb5e5dSvi117747 */ 116240cb5e5dSvi117747 if (sip_hash_add(sip_dialog_hash, (void *)dialog, 116340cb5e5dSvi117747 SIP_DIGEST_TO_HASH(dialog->sip_dlg_id)) != 0) { 11642c2c4183Svi117747 terminate_new_dlg: 116540cb5e5dSvi117747 /* 116640cb5e5dSvi117747 * So that sip_dialog_delete() does not try to remove 116740cb5e5dSvi117747 * this from the hash table. 116840cb5e5dSvi117747 */ 116940cb5e5dSvi117747 (void) pthread_mutex_lock(&dialog->sip_dlg_mutex); 117040cb5e5dSvi117747 if (dialog->sip_dlg_type == SIP_UAS_DIALOG) { 11712c2c4183Svi117747 if (dialog->sip_dlg_local_uri_tag != NULL) { 117240cb5e5dSvi117747 sip_free_header(dialog->sip_dlg_local_uri_tag); 117340cb5e5dSvi117747 dialog->sip_dlg_local_uri_tag = NULL; 11742c2c4183Svi117747 } 117540cb5e5dSvi117747 } else { 11762c2c4183Svi117747 if (dialog->sip_dlg_remote_uri_tag != NULL) { 117740cb5e5dSvi117747 sip_free_header(dialog->sip_dlg_remote_uri_tag); 117840cb5e5dSvi117747 dialog->sip_dlg_remote_uri_tag = NULL; 117940cb5e5dSvi117747 } 11802c2c4183Svi117747 } 118140cb5e5dSvi117747 (void) pthread_mutex_unlock(&dialog->sip_dlg_mutex); 118240cb5e5dSvi117747 sip_dialog_terminate(dialog, (sip_msg_t)sip_msg); 118340cb5e5dSvi117747 return (NULL); 118440cb5e5dSvi117747 } 118540cb5e5dSvi117747 if (sip_dlg_ulp_state_cb != NULL) { 118640cb5e5dSvi117747 sip_dlg_ulp_state_cb((sip_dialog_t)dialog, 118740cb5e5dSvi117747 (sip_msg_t)sip_msg, prev_state, dialog->sip_dlg_state); 118840cb5e5dSvi117747 } 118940cb5e5dSvi117747 return ((sip_dialog_t)dialog); 119040cb5e5dSvi117747 } 119140cb5e5dSvi117747 119240cb5e5dSvi117747 /* 119340cb5e5dSvi117747 * Check if this dialog is a match. 119440cb5e5dSvi117747 */ 119540cb5e5dSvi117747 boolean_t 119640cb5e5dSvi117747 sip_dialog_match(void *obj, void *hindex) 119740cb5e5dSvi117747 { 119840cb5e5dSvi117747 _sip_dialog_t *dialog = (_sip_dialog_t *)obj; 119940cb5e5dSvi117747 120040cb5e5dSvi117747 (void) pthread_mutex_lock(&dialog->sip_dlg_mutex); 120140cb5e5dSvi117747 if (dialog->sip_dlg_state == SIP_DLG_DESTROYED) { 120240cb5e5dSvi117747 (void) pthread_mutex_unlock(&dialog->sip_dlg_mutex); 120340cb5e5dSvi117747 return (B_FALSE); 120440cb5e5dSvi117747 } 120540cb5e5dSvi117747 if (bcmp(dialog->sip_dlg_id, hindex, 120640cb5e5dSvi117747 sizeof (dialog->sip_dlg_id)) == 0) { 120740cb5e5dSvi117747 SIP_DLG_REFCNT_INCR(dialog); 120840cb5e5dSvi117747 (void) pthread_mutex_unlock(&dialog->sip_dlg_mutex); 120940cb5e5dSvi117747 return (B_TRUE); 121040cb5e5dSvi117747 } 121140cb5e5dSvi117747 (void) pthread_mutex_unlock(&dialog->sip_dlg_mutex); 121240cb5e5dSvi117747 return (B_FALSE); 121340cb5e5dSvi117747 } 121440cb5e5dSvi117747 121540cb5e5dSvi117747 /* 121640cb5e5dSvi117747 * Don't delete, just take it out of the hash 121740cb5e5dSvi117747 */ 121840cb5e5dSvi117747 boolean_t 121940cb5e5dSvi117747 sip_dialog_dontfree(void *obj, void *hindex, int *found) 122040cb5e5dSvi117747 { 122140cb5e5dSvi117747 _sip_dialog_t *dialog = (_sip_dialog_t *)obj; 122240cb5e5dSvi117747 122340cb5e5dSvi117747 *found = 0; 122440cb5e5dSvi117747 (void) pthread_mutex_lock(&dialog->sip_dlg_mutex); 122540cb5e5dSvi117747 if (bcmp(dialog->sip_dlg_id, hindex, sizeof (dialog->sip_dlg_id)) 122640cb5e5dSvi117747 == 0) { 122740cb5e5dSvi117747 *found = 1; 122840cb5e5dSvi117747 (void) pthread_mutex_unlock(&dialog->sip_dlg_mutex); 122940cb5e5dSvi117747 return (B_TRUE); 123040cb5e5dSvi117747 } 123140cb5e5dSvi117747 (void) pthread_mutex_unlock(&dialog->sip_dlg_mutex); 123240cb5e5dSvi117747 return (B_FALSE); 123340cb5e5dSvi117747 } 123440cb5e5dSvi117747 123540cb5e5dSvi117747 /* 123640cb5e5dSvi117747 * Free resources associated with the dialog, the object will be removed 123740cb5e5dSvi117747 * from the hash list by sip_hash_delete. 123840cb5e5dSvi117747 */ 123940cb5e5dSvi117747 boolean_t 124040cb5e5dSvi117747 sip_dialog_free(void *obj, void *hindex, int *found) 124140cb5e5dSvi117747 { 124240cb5e5dSvi117747 _sip_dialog_t *dialog = (_sip_dialog_t *)obj; 124340cb5e5dSvi117747 124440cb5e5dSvi117747 *found = 0; 124540cb5e5dSvi117747 (void) pthread_mutex_lock(&dialog->sip_dlg_mutex); 124640cb5e5dSvi117747 if (bcmp(dialog->sip_dlg_id, hindex, sizeof (dialog->sip_dlg_id)) 124740cb5e5dSvi117747 == 0) { 124840cb5e5dSvi117747 *found = 1; 1249*943efbc3Sgm209912 if (dialog->sip_dlg_state != SIP_DLG_DESTROYED) { 1250*943efbc3Sgm209912 sip_write_to_log((void *)dialog, SIP_DIALOG_LOG | 1251*943efbc3Sgm209912 SIP_ASSERT_ERROR, __FILE__, __LINE__); 1252*943efbc3Sgm209912 } 125340cb5e5dSvi117747 assert(dialog->sip_dlg_state == SIP_DLG_DESTROYED); 125440cb5e5dSvi117747 if (dialog->sip_dlg_ref_cnt != 0) { 125540cb5e5dSvi117747 (void) pthread_mutex_unlock(&dialog->sip_dlg_mutex); 125640cb5e5dSvi117747 return (B_FALSE); 125740cb5e5dSvi117747 } 1258*943efbc3Sgm209912 sip_write_to_log((void *)dialog, SIP_DIALOG_LOG, NULL, 0); 125940cb5e5dSvi117747 sip_release_dialog_res(dialog); 126040cb5e5dSvi117747 return (B_TRUE); 126140cb5e5dSvi117747 } 126240cb5e5dSvi117747 (void) pthread_mutex_unlock(&dialog->sip_dlg_mutex); 126340cb5e5dSvi117747 return (B_FALSE); 126440cb5e5dSvi117747 } 126540cb5e5dSvi117747 126640cb5e5dSvi117747 /* 126740cb5e5dSvi117747 * The UAS will receive the request from the transaction layer. If the 126840cb5e5dSvi117747 * request has a tag in the To header field, the UAS core computes the 126940cb5e5dSvi117747 * dialog identifier corresponding to the request and compares it with 127040cb5e5dSvi117747 * existing dialogs. If there is a match, this is a mid-dialog request. 127140cb5e5dSvi117747 */ 127240cb5e5dSvi117747 sip_dialog_t 127340cb5e5dSvi117747 sip_dialog_find(_sip_msg_t *sip_msg) 127440cb5e5dSvi117747 { 127540cb5e5dSvi117747 const sip_str_t *localtag; 127640cb5e5dSvi117747 const sip_str_t *remtag; 127740cb5e5dSvi117747 const sip_str_t *callid; 127840cb5e5dSvi117747 uint16_t digest[8]; 127940cb5e5dSvi117747 _sip_dialog_t *dialog; 128040cb5e5dSvi117747 boolean_t is_request; 128140cb5e5dSvi117747 int error; 128240cb5e5dSvi117747 128340cb5e5dSvi117747 is_request = sip_msg_is_request((sip_msg_t)sip_msg, &error); 128440cb5e5dSvi117747 if (error != 0) 128540cb5e5dSvi117747 return (NULL); 128640cb5e5dSvi117747 if (is_request) { 128740cb5e5dSvi117747 localtag = sip_get_to_tag((sip_msg_t)sip_msg, &error); 128840cb5e5dSvi117747 if (error == 0) 128940cb5e5dSvi117747 remtag = sip_get_from_tag((sip_msg_t)sip_msg, &error); 129040cb5e5dSvi117747 } else { 129140cb5e5dSvi117747 remtag = sip_get_to_tag((sip_msg_t)sip_msg, &error); 129240cb5e5dSvi117747 if (error == 0) 129340cb5e5dSvi117747 localtag = sip_get_from_tag((sip_msg_t)sip_msg, &error); 129440cb5e5dSvi117747 } 129540cb5e5dSvi117747 if (error != 0) 129640cb5e5dSvi117747 return (NULL); 129740cb5e5dSvi117747 callid = sip_get_callid((sip_msg_t)sip_msg, &error); 129840cb5e5dSvi117747 if (error != 0 || remtag == NULL || localtag == NULL || 129940cb5e5dSvi117747 callid == NULL) { 130040cb5e5dSvi117747 return (NULL); 130140cb5e5dSvi117747 } 130240cb5e5dSvi117747 sip_md5_hash(localtag->sip_str_ptr, localtag->sip_str_len, 130340cb5e5dSvi117747 remtag->sip_str_ptr, remtag->sip_str_len, 130440cb5e5dSvi117747 callid->sip_str_ptr, callid->sip_str_len, 130540cb5e5dSvi117747 NULL, 0, NULL, 0, NULL, 0, (uchar_t *)digest); 130640cb5e5dSvi117747 130740cb5e5dSvi117747 dialog = (_sip_dialog_t *)sip_hash_find(sip_dialog_hash, 130840cb5e5dSvi117747 (void *)digest, SIP_DIGEST_TO_HASH(digest), sip_dialog_match); 130940cb5e5dSvi117747 if (dialog == NULL) { 131040cb5e5dSvi117747 sip_md5_hash(localtag->sip_str_ptr, localtag->sip_str_len, 131140cb5e5dSvi117747 NULL, 0, callid->sip_str_ptr, callid->sip_str_len, 131240cb5e5dSvi117747 NULL, 0, NULL, 0, NULL, 0, (uchar_t *)digest); 131340cb5e5dSvi117747 dialog = (_sip_dialog_t *)sip_hash_find(sip_dialog_phash, 131440cb5e5dSvi117747 (void *)digest, SIP_DIGEST_TO_HASH(digest), 131540cb5e5dSvi117747 sip_dialog_match); 131640cb5e5dSvi117747 } 131740cb5e5dSvi117747 return ((sip_dialog_t)dialog); 131840cb5e5dSvi117747 } 131940cb5e5dSvi117747 132040cb5e5dSvi117747 /* 132140cb5e5dSvi117747 * We keep this partial dialog for the duration of the INVITE 132240cb5e5dSvi117747 * transaction timeout duration, i.e. Timer B. 132340cb5e5dSvi117747 */ 132440cb5e5dSvi117747 void 132540cb5e5dSvi117747 sip_dlg_self_destruct(void *args) 132640cb5e5dSvi117747 { 132740cb5e5dSvi117747 sip_dialog_timer_obj_t *tim_obj = (sip_dialog_timer_obj_t *)args; 132840cb5e5dSvi117747 _sip_dialog_t *dialog = (_sip_dialog_t *)tim_obj->dialog; 132940cb5e5dSvi117747 int index; 133040cb5e5dSvi117747 133140cb5e5dSvi117747 (void) pthread_mutex_lock(&dialog->sip_dlg_mutex); 1332*943efbc3Sgm209912 if (dialog->sip_dlg_state != SIP_DLG_NEW) { 1333*943efbc3Sgm209912 sip_write_to_log((void *)dialog, SIP_DIALOG_LOG | 1334*943efbc3Sgm209912 SIP_ASSERT_ERROR, __FILE__, __LINE__); 1335*943efbc3Sgm209912 } 133640cb5e5dSvi117747 assert(dialog->sip_dlg_state == SIP_DLG_NEW); 133740cb5e5dSvi117747 dialog->sip_dlg_state = SIP_DLG_DESTROYED; 133840cb5e5dSvi117747 if (dialog->sip_dlg_type == SIP_UAC_DIALOG) { 133940cb5e5dSvi117747 index = SIP_DIGEST_TO_HASH(dialog->sip_dlg_id); 134040cb5e5dSvi117747 (void) pthread_mutex_unlock(&dialog->sip_dlg_mutex); 134140cb5e5dSvi117747 sip_hash_delete(sip_dialog_phash, (void *)dialog->sip_dlg_id, 134240cb5e5dSvi117747 index, sip_dialog_dontfree); 134340cb5e5dSvi117747 } else { 134440cb5e5dSvi117747 (void) pthread_mutex_unlock(&dialog->sip_dlg_mutex); 134540cb5e5dSvi117747 } 134640cb5e5dSvi117747 if (tim_obj->func != NULL) 134740cb5e5dSvi117747 tim_obj->func(dialog, NULL, NULL); 134840cb5e5dSvi117747 free(tim_obj); 134940cb5e5dSvi117747 SIP_DLG_REFCNT_DECR(dialog); 135040cb5e5dSvi117747 } 135140cb5e5dSvi117747 135240cb5e5dSvi117747 /* 135340cb5e5dSvi117747 * Terminate a dialog 135440cb5e5dSvi117747 */ 135540cb5e5dSvi117747 void 135640cb5e5dSvi117747 sip_dialog_terminate(_sip_dialog_t *dialog, sip_msg_t sip_msg) 135740cb5e5dSvi117747 { 135840cb5e5dSvi117747 int prev_state; 135940cb5e5dSvi117747 136040cb5e5dSvi117747 (void) pthread_mutex_lock(&dialog->sip_dlg_mutex); 136140cb5e5dSvi117747 prev_state = dialog->sip_dlg_state; 136240cb5e5dSvi117747 dialog->sip_dlg_state = SIP_DLG_DESTROYED; 136340cb5e5dSvi117747 (void) pthread_mutex_unlock(&dialog->sip_dlg_mutex); 136440cb5e5dSvi117747 if (sip_dlg_ulp_state_cb != NULL) { 136540cb5e5dSvi117747 sip_dlg_ulp_state_cb((sip_dialog_t)dialog, sip_msg, prev_state, 136640cb5e5dSvi117747 dialog->sip_dlg_state); 136740cb5e5dSvi117747 } 136840cb5e5dSvi117747 SIP_DLG_REFCNT_DECR(dialog); 136940cb5e5dSvi117747 } 137040cb5e5dSvi117747 137140cb5e5dSvi117747 /* 137240cb5e5dSvi117747 * Delete a dialog 137340cb5e5dSvi117747 */ 137440cb5e5dSvi117747 void 137540cb5e5dSvi117747 sip_dialog_delete(_sip_dialog_t *dialog) 137640cb5e5dSvi117747 { 137740cb5e5dSvi117747 int index; 137840cb5e5dSvi117747 137940cb5e5dSvi117747 /* 138040cb5e5dSvi117747 * partial dialog, not in the hash table 138140cb5e5dSvi117747 */ 138240cb5e5dSvi117747 if (dialog->sip_dlg_local_uri_tag == NULL || 138340cb5e5dSvi117747 dialog->sip_dlg_remote_uri_tag == NULL) { 138440cb5e5dSvi117747 /* 138540cb5e5dSvi117747 * Cancel the partial dialog timer 138640cb5e5dSvi117747 */ 138740cb5e5dSvi117747 if (SIP_IS_TIMER_RUNNING(dialog->sip_dlg_timer)) 138840cb5e5dSvi117747 SIP_CANCEL_TIMER(dialog->sip_dlg_timer); 1389*943efbc3Sgm209912 sip_write_to_log((void *)dialog, SIP_DIALOG_LOG, NULL, 0); 139040cb5e5dSvi117747 sip_release_dialog_res(dialog); 139140cb5e5dSvi117747 return; 139240cb5e5dSvi117747 } 139340cb5e5dSvi117747 index = SIP_DIGEST_TO_HASH(dialog->sip_dlg_id); 139440cb5e5dSvi117747 sip_hash_delete(sip_dialog_hash, (void *)dialog->sip_dlg_id, index, 139540cb5e5dSvi117747 sip_dialog_free); 139640cb5e5dSvi117747 } 139740cb5e5dSvi117747 139840cb5e5dSvi117747 /* 139940cb5e5dSvi117747 * Get the remote target from the CONTACT header from the 200 OK response 140040cb5e5dSvi117747 */ 140140cb5e5dSvi117747 static boolean_t 140240cb5e5dSvi117747 sip_get_rtarg(_sip_dialog_t *dialog, _sip_msg_t *sip_msg) 140340cb5e5dSvi117747 { 140440cb5e5dSvi117747 sip_header_t chdr; 140540cb5e5dSvi117747 140640cb5e5dSvi117747 if (dialog->sip_dlg_remote_target != NULL) 140740cb5e5dSvi117747 return (B_TRUE); 140840cb5e5dSvi117747 140940cb5e5dSvi117747 (void) pthread_mutex_lock(&sip_msg->sip_msg_mutex); 141040cb5e5dSvi117747 chdr = sip_search_for_header(sip_msg, SIP_CONTACT, NULL); 141140cb5e5dSvi117747 (void) pthread_mutex_unlock(&sip_msg->sip_msg_mutex); 141240cb5e5dSvi117747 if (chdr == NULL) 141340cb5e5dSvi117747 return (B_FALSE); 141440cb5e5dSvi117747 if ((dialog->sip_dlg_remote_target = sip_dup_header(chdr)) == NULL) 141540cb5e5dSvi117747 return (B_FALSE); 141640cb5e5dSvi117747 141740cb5e5dSvi117747 return (B_TRUE); 141840cb5e5dSvi117747 } 141940cb5e5dSvi117747 142040cb5e5dSvi117747 /* 142140cb5e5dSvi117747 * Process an incoming request/response 142240cb5e5dSvi117747 */ 142340cb5e5dSvi117747 /* ARGSUSED */ 142440cb5e5dSvi117747 int 142540cb5e5dSvi117747 sip_dialog_process(_sip_msg_t *sip_msg, sip_dialog_t *sip_dialog) 142640cb5e5dSvi117747 { 142740cb5e5dSvi117747 boolean_t request; 142840cb5e5dSvi117747 _sip_dialog_t *_dialog; 142940cb5e5dSvi117747 int error; 143040cb5e5dSvi117747 1431*943efbc3Sgm209912 _dialog = (_sip_dialog_t *)*sip_dialog; 1432*943efbc3Sgm209912 1433*943efbc3Sgm209912 (void) pthread_mutex_lock(&_dialog->sip_dlg_mutex); 1434*943efbc3Sgm209912 _dialog->sip_dlg_msgcnt++; 1435*943efbc3Sgm209912 sip_add_log(&_dialog->sip_dlg_log[_dialog->sip_dlg_state], 1436*943efbc3Sgm209912 (sip_msg_t)sip_msg, _dialog->sip_dlg_msgcnt, SIP_DIALOG_LOG); 1437*943efbc3Sgm209912 (void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex); 1438*943efbc3Sgm209912 143940cb5e5dSvi117747 request = sip_msg_is_request((sip_msg_t)sip_msg, &error); 144040cb5e5dSvi117747 if (error != 0) 144140cb5e5dSvi117747 return (EINVAL); 144240cb5e5dSvi117747 if (request) { 144340cb5e5dSvi117747 uint32_t cseq; 144440cb5e5dSvi117747 sip_method_t method; 144540cb5e5dSvi117747 144640cb5e5dSvi117747 cseq = sip_get_callseq_num((sip_msg_t)sip_msg, &error); 144740cb5e5dSvi117747 if (error != 0) 144840cb5e5dSvi117747 return (EINVAL); 144940cb5e5dSvi117747 method = sip_get_callseq_method((sip_msg_t)sip_msg, &error); 145040cb5e5dSvi117747 if (error != 0) 145140cb5e5dSvi117747 return (EINVAL); 145240cb5e5dSvi117747 if (sip_get_request_method((sip_msg_t)sip_msg, &error) != 145340cb5e5dSvi117747 method) { 145440cb5e5dSvi117747 return (EINVAL); 145540cb5e5dSvi117747 } 145640cb5e5dSvi117747 (void) pthread_mutex_lock(&_dialog->sip_dlg_mutex); 145740cb5e5dSvi117747 /* 145840cb5e5dSvi117747 * Requests that do not change in any way the state 145940cb5e5dSvi117747 * of a dialog may be received within a dialog. 146040cb5e5dSvi117747 * They are processed as if they had been received 146140cb5e5dSvi117747 * outside the dialog. 146240cb5e5dSvi117747 * For dialogs that have been established with an 146340cb5e5dSvi117747 * INVITE, the only target refresh request defined is 146440cb5e5dSvi117747 * re-INVITE. 146540cb5e5dSvi117747 */ 146640cb5e5dSvi117747 if (_dialog->sip_dlg_method == INVITE && 146740cb5e5dSvi117747 method == INVITE && _dialog->sip_dlg_remote_cseq != 0 && 146840cb5e5dSvi117747 SIP_CSEQ_LT(cseq, _dialog->sip_dlg_remote_cseq)) { 146940cb5e5dSvi117747 (void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex); 147040cb5e5dSvi117747 return (EPROTO); 147140cb5e5dSvi117747 } 147240cb5e5dSvi117747 /* 147340cb5e5dSvi117747 * Target-Refresh request 147440cb5e5dSvi117747 */ 147540cb5e5dSvi117747 if (_dialog->sip_dlg_method == INVITE && method == INVITE) { 147640cb5e5dSvi117747 sip_header_t chdr; 147740cb5e5dSvi117747 sip_header_t nchdr; 147840cb5e5dSvi117747 147940cb5e5dSvi117747 (void) pthread_mutex_lock(&sip_msg->sip_msg_mutex); 148040cb5e5dSvi117747 chdr = sip_search_for_header(sip_msg, SIP_CONTACT, 148140cb5e5dSvi117747 NULL); 148240cb5e5dSvi117747 (void) pthread_mutex_unlock(&sip_msg->sip_msg_mutex); 148340cb5e5dSvi117747 if (chdr != NULL && 148440cb5e5dSvi117747 (nchdr = sip_dup_header(chdr)) != NULL) { 148540cb5e5dSvi117747 if (_dialog->sip_dlg_remote_target != NULL) { 148640cb5e5dSvi117747 sip_free_header( 148740cb5e5dSvi117747 _dialog->sip_dlg_remote_target); 148840cb5e5dSvi117747 } 148940cb5e5dSvi117747 _dialog->sip_dlg_remote_target = nchdr; 149040cb5e5dSvi117747 } 149140cb5e5dSvi117747 } 149240cb5e5dSvi117747 _dialog->sip_dlg_remote_cseq = cseq; 149340cb5e5dSvi117747 (void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex); 149440cb5e5dSvi117747 } else { 149540cb5e5dSvi117747 int resp_code; 149640cb5e5dSvi117747 sip_method_t method; 149740cb5e5dSvi117747 int error; 149840cb5e5dSvi117747 149940cb5e5dSvi117747 resp_code = sip_get_response_code((sip_msg_t)sip_msg, &error); 150040cb5e5dSvi117747 if (error == 0) { 150140cb5e5dSvi117747 method = sip_get_callseq_method((sip_msg_t)sip_msg, 150240cb5e5dSvi117747 &error); 150340cb5e5dSvi117747 } 150440cb5e5dSvi117747 if (error != 0) 150540cb5e5dSvi117747 return (error); 150640cb5e5dSvi117747 150740cb5e5dSvi117747 (void) pthread_mutex_lock(&_dialog->sip_dlg_mutex); 15085878c602Sgm209912 if (_dialog->sip_dlg_state == SIP_DLG_DESTROYED) { 15095878c602Sgm209912 (void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex); 15105878c602Sgm209912 return (0); 15115878c602Sgm209912 } 1512*943efbc3Sgm209912 if (_dialog->sip_dlg_state != SIP_DLG_EARLY && 1513*943efbc3Sgm209912 _dialog->sip_dlg_state != SIP_DLG_CONFIRMED) { 1514*943efbc3Sgm209912 sip_write_to_log((void *)_dialog, SIP_DIALOG_LOG | 1515*943efbc3Sgm209912 SIP_ASSERT_ERROR, __FILE__, __LINE__); 1516*943efbc3Sgm209912 } 151740cb5e5dSvi117747 assert(_dialog->sip_dlg_state == SIP_DLG_EARLY || 151840cb5e5dSvi117747 _dialog->sip_dlg_state == SIP_DLG_CONFIRMED); 151940cb5e5dSvi117747 /* 152040cb5e5dSvi117747 * Let the user delete the dialog if it is not a 1XX/2XX resp 152140cb5e5dSvi117747 * for an early INVITE dialog. 152240cb5e5dSvi117747 */ 152340cb5e5dSvi117747 if (SIP_OK_RESP(resp_code)) { 152440cb5e5dSvi117747 if (method == INVITE) { 152540cb5e5dSvi117747 if (!sip_get_rtarg(_dialog, sip_msg)) { 152640cb5e5dSvi117747 (void) pthread_mutex_unlock( 152740cb5e5dSvi117747 &_dialog->sip_dlg_mutex); 152840cb5e5dSvi117747 if (sip_ulp_dlg_del_cb != NULL) { 152940cb5e5dSvi117747 sip_ulp_dlg_del_cb( 153040cb5e5dSvi117747 (sip_dialog_t)_dialog, 153140cb5e5dSvi117747 (sip_msg_t)sip_msg, NULL); 153240cb5e5dSvi117747 } 153340cb5e5dSvi117747 sip_dialog_terminate(_dialog, 153440cb5e5dSvi117747 (sip_msg_t)sip_msg); 153540cb5e5dSvi117747 return (0); 153640cb5e5dSvi117747 } 153740cb5e5dSvi117747 if (_dialog->sip_dlg_state == SIP_DLG_EARLY) { 153840cb5e5dSvi117747 _dialog->sip_dlg_state = 153940cb5e5dSvi117747 SIP_DLG_CONFIRMED; 154040cb5e5dSvi117747 (void) sip_dlg_recompute_rset(_dialog, 154140cb5e5dSvi117747 sip_msg, SIP_UAC_DIALOG); 1542*943efbc3Sgm209912 (void) pthread_mutex_unlock( 1543*943efbc3Sgm209912 &_dialog->sip_dlg_mutex); 154440cb5e5dSvi117747 if (sip_dlg_ulp_state_cb != NULL) { 154540cb5e5dSvi117747 sip_dlg_ulp_state_cb( 154640cb5e5dSvi117747 (sip_dialog_t)_dialog, 154740cb5e5dSvi117747 sip_msg, SIP_DLG_EARLY, 154840cb5e5dSvi117747 _dialog->sip_dlg_state); 154940cb5e5dSvi117747 } 155040cb5e5dSvi117747 return (0); 1551d8a40387Sgm209912 } else if (_dialog->sip_dlg_new_local_contact 1552d8a40387Sgm209912 != NULL) { 1553*943efbc3Sgm209912 if (_dialog->sip_dlg_local_contact == 1554*943efbc3Sgm209912 NULL) { 1555*943efbc3Sgm209912 (void) sip_write_to_log((void *) 1556*943efbc3Sgm209912 _dialog, SIP_DIALOG_LOG | 1557*943efbc3Sgm209912 SIP_ASSERT_ERROR, __FILE__, 1558*943efbc3Sgm209912 __LINE__); 1559*943efbc3Sgm209912 } 1560d8a40387Sgm209912 assert(_dialog->sip_dlg_local_contact 1561d8a40387Sgm209912 != NULL); 1562d8a40387Sgm209912 sip_free_header(_dialog-> 1563d8a40387Sgm209912 sip_dlg_local_contact); 1564d8a40387Sgm209912 _dialog->sip_dlg_local_contact = 1565d8a40387Sgm209912 _dialog->sip_dlg_new_local_contact; 1566d8a40387Sgm209912 _dialog->sip_dlg_new_local_contact = 1567d8a40387Sgm209912 NULL; 156840cb5e5dSvi117747 } 156940cb5e5dSvi117747 } 157040cb5e5dSvi117747 } 157140cb5e5dSvi117747 (void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex); 157240cb5e5dSvi117747 } 157340cb5e5dSvi117747 return (0); 157440cb5e5dSvi117747 } 157540cb5e5dSvi117747 157640cb5e5dSvi117747 /* 157740cb5e5dSvi117747 * Copy partial dialog to create a complete dialog 157840cb5e5dSvi117747 */ 157940cb5e5dSvi117747 _sip_dialog_t * 158040cb5e5dSvi117747 sip_copy_partial_dialog(_sip_dialog_t *dialog) 158140cb5e5dSvi117747 { 158240cb5e5dSvi117747 _sip_dialog_t *new_dlg; 158340cb5e5dSvi117747 158440cb5e5dSvi117747 new_dlg = calloc(1, sizeof (_sip_dialog_t)); 158540cb5e5dSvi117747 if (new_dlg == NULL) 158640cb5e5dSvi117747 return (NULL); 158740cb5e5dSvi117747 if (dialog->sip_dlg_req_uri.sip_str_ptr != NULL) { 158840cb5e5dSvi117747 new_dlg->sip_dlg_req_uri.sip_str_ptr = 158940cb5e5dSvi117747 malloc(dialog->sip_dlg_req_uri.sip_str_len + 1); 159040cb5e5dSvi117747 if (new_dlg->sip_dlg_req_uri.sip_str_ptr == NULL) { 159140cb5e5dSvi117747 free(new_dlg); 159240cb5e5dSvi117747 return (NULL); 159340cb5e5dSvi117747 } 159440cb5e5dSvi117747 (void) strncpy(new_dlg->sip_dlg_req_uri.sip_str_ptr, 159540cb5e5dSvi117747 dialog->sip_dlg_req_uri.sip_str_ptr, 159640cb5e5dSvi117747 dialog->sip_dlg_req_uri.sip_str_len); 159740cb5e5dSvi117747 new_dlg->sip_dlg_req_uri.sip_str_ptr[ 159840cb5e5dSvi117747 dialog->sip_dlg_req_uri.sip_str_len] = '\0'; 159940cb5e5dSvi117747 new_dlg->sip_dlg_req_uri.sip_str_len = 160040cb5e5dSvi117747 dialog->sip_dlg_req_uri.sip_str_len; 160140cb5e5dSvi117747 } 160240cb5e5dSvi117747 if (dialog->sip_dlg_route_set != NULL) { 1603*943efbc3Sgm209912 if (dialog->sip_dlg_rset.sip_str_ptr == NULL) { 1604*943efbc3Sgm209912 sip_write_to_log((void *)dialog, SIP_DIALOG_LOG | 1605*943efbc3Sgm209912 SIP_ASSERT_ERROR, __FILE__, __LINE__); 1606*943efbc3Sgm209912 } 160740cb5e5dSvi117747 assert(dialog->sip_dlg_rset.sip_str_ptr != NULL); 160840cb5e5dSvi117747 new_dlg->sip_dlg_rset.sip_str_ptr = 160940cb5e5dSvi117747 malloc(dialog->sip_dlg_rset.sip_str_len + 1); 161040cb5e5dSvi117747 if (new_dlg->sip_dlg_rset.sip_str_ptr == NULL) { 161140cb5e5dSvi117747 if (new_dlg->sip_dlg_req_uri.sip_str_ptr != NULL) 161240cb5e5dSvi117747 free(new_dlg->sip_dlg_req_uri.sip_str_ptr); 161340cb5e5dSvi117747 free(new_dlg); 161440cb5e5dSvi117747 return (NULL); 161540cb5e5dSvi117747 } 161640cb5e5dSvi117747 (void) strncpy(new_dlg->sip_dlg_rset.sip_str_ptr, 161740cb5e5dSvi117747 dialog->sip_dlg_rset.sip_str_ptr, 161840cb5e5dSvi117747 dialog->sip_dlg_rset.sip_str_len); 161940cb5e5dSvi117747 new_dlg->sip_dlg_rset.sip_str_ptr[ 162040cb5e5dSvi117747 dialog->sip_dlg_rset.sip_str_len] = '\0'; 162140cb5e5dSvi117747 new_dlg->sip_dlg_rset.sip_str_len = 162240cb5e5dSvi117747 dialog->sip_dlg_rset.sip_str_len; 162340cb5e5dSvi117747 162440cb5e5dSvi117747 new_dlg->sip_dlg_route_set = 162540cb5e5dSvi117747 sip_dup_header(dialog->sip_dlg_route_set); 162640cb5e5dSvi117747 if (new_dlg->sip_dlg_route_set == NULL) { 162740cb5e5dSvi117747 free(new_dlg->sip_dlg_rset.sip_str_ptr); 162840cb5e5dSvi117747 if (new_dlg->sip_dlg_req_uri.sip_str_ptr != NULL) 162940cb5e5dSvi117747 free(new_dlg->sip_dlg_req_uri.sip_str_ptr); 163040cb5e5dSvi117747 free(new_dlg); 163140cb5e5dSvi117747 return (NULL); 163240cb5e5dSvi117747 } 163340cb5e5dSvi117747 } 163440cb5e5dSvi117747 if ((new_dlg->sip_dlg_local_uri_tag = 163540cb5e5dSvi117747 sip_dup_header(dialog->sip_dlg_local_uri_tag)) == NULL || 163640cb5e5dSvi117747 (new_dlg->sip_dlg_remote_target = 163740cb5e5dSvi117747 sip_dup_header(dialog->sip_dlg_remote_target)) == NULL || 1638d8a40387Sgm209912 (new_dlg->sip_dlg_local_contact = 1639d8a40387Sgm209912 sip_dup_header(dialog->sip_dlg_local_contact)) == NULL || 164040cb5e5dSvi117747 (new_dlg->sip_dlg_call_id = 164140cb5e5dSvi117747 sip_dup_header(dialog->sip_dlg_call_id)) == NULL) { 164240cb5e5dSvi117747 sip_release_dialog_res(new_dlg); 164340cb5e5dSvi117747 return (NULL); 164440cb5e5dSvi117747 } 164540cb5e5dSvi117747 if (dialog->sip_dlg_event != NULL) { 164640cb5e5dSvi117747 new_dlg->sip_dlg_event = sip_dup_header(dialog->sip_dlg_event); 164740cb5e5dSvi117747 if (new_dlg->sip_dlg_event == NULL) { 164840cb5e5dSvi117747 sip_release_dialog_res(new_dlg); 164940cb5e5dSvi117747 return (NULL); 165040cb5e5dSvi117747 } 165140cb5e5dSvi117747 } 165240cb5e5dSvi117747 new_dlg->sip_dlg_local_cseq = dialog->sip_dlg_local_cseq; 165340cb5e5dSvi117747 new_dlg->sip_dlg_type = dialog->sip_dlg_type; 165440cb5e5dSvi117747 new_dlg->sip_dlg_on_fork = B_FALSE; 165540cb5e5dSvi117747 (void) pthread_mutex_init(&new_dlg->sip_dlg_mutex, NULL); 165640cb5e5dSvi117747 165740cb5e5dSvi117747 return (new_dlg); 165840cb5e5dSvi117747 } 165940cb5e5dSvi117747 166040cb5e5dSvi117747 /* 166140cb5e5dSvi117747 * Update the dialog using the response 166240cb5e5dSvi117747 */ 166340cb5e5dSvi117747 sip_dialog_t 166440cb5e5dSvi117747 sip_update_dialog(sip_dialog_t dialog, _sip_msg_t *sip_msg) 166540cb5e5dSvi117747 { 166640cb5e5dSvi117747 _sip_dialog_t *_dialog; 166740cb5e5dSvi117747 boolean_t isreq; 166840cb5e5dSvi117747 sip_method_t method; 166940cb5e5dSvi117747 int resp_code = 0; 167040cb5e5dSvi117747 int prev_state; 167140cb5e5dSvi117747 boolean_t decr_ref = B_FALSE; 167240cb5e5dSvi117747 int error; 167340cb5e5dSvi117747 1674*943efbc3Sgm209912 _dialog = (_sip_dialog_t *)dialog; 1675*943efbc3Sgm209912 (void) pthread_mutex_lock(&_dialog->sip_dlg_mutex); 1676*943efbc3Sgm209912 _dialog->sip_dlg_msgcnt++; 1677*943efbc3Sgm209912 sip_add_log(&_dialog->sip_dlg_log[_dialog->sip_dlg_state], 1678*943efbc3Sgm209912 (sip_msg_t)sip_msg, _dialog->sip_dlg_msgcnt, SIP_DIALOG_LOG); 1679*943efbc3Sgm209912 (void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex); 1680*943efbc3Sgm209912 168140cb5e5dSvi117747 isreq = sip_msg_is_request((sip_msg_t)sip_msg, &error); 168240cb5e5dSvi117747 if (error != 0) 168340cb5e5dSvi117747 return (dialog); 168440cb5e5dSvi117747 (void) pthread_mutex_lock(&_dialog->sip_dlg_mutex); 168540cb5e5dSvi117747 if (isreq) { 168640cb5e5dSvi117747 method = sip_get_request_method((sip_msg_t)sip_msg, &error); 168740cb5e5dSvi117747 if (error != 0 || _dialog->sip_dlg_method != SUBSCRIBE || 168840cb5e5dSvi117747 method != NOTIFY) { 168940cb5e5dSvi117747 (void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex); 169040cb5e5dSvi117747 return (dialog); 169140cb5e5dSvi117747 } 169240cb5e5dSvi117747 } else { 169340cb5e5dSvi117747 resp_code = sip_get_response_code((sip_msg_t)sip_msg, &error); 169440cb5e5dSvi117747 if (error != 0) { 169540cb5e5dSvi117747 (void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex); 169640cb5e5dSvi117747 return (dialog); 169740cb5e5dSvi117747 } 1698d8a40387Sgm209912 method = sip_get_callseq_method((sip_msg_t)sip_msg, &error); 1699d8a40387Sgm209912 if (error != 0) { 1700d8a40387Sgm209912 (void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex); 1701d8a40387Sgm209912 return (dialog); 1702d8a40387Sgm209912 } 170340cb5e5dSvi117747 } 170440cb5e5dSvi117747 prev_state = _dialog->sip_dlg_state; 170540cb5e5dSvi117747 if (_dialog->sip_dlg_state == SIP_DLG_CONFIRMED) { 170640cb5e5dSvi117747 (void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex); 170740cb5e5dSvi117747 } else if (_dialog->sip_dlg_state == SIP_DLG_EARLY) { 170840cb5e5dSvi117747 /* 170940cb5e5dSvi117747 * Let the user delete the dialog if it is not a 1XX/2XX resp 171040cb5e5dSvi117747 * for an early dialog. 171140cb5e5dSvi117747 */ 1712*943efbc3Sgm209912 if (isreq) { 1713*943efbc3Sgm209912 sip_write_to_log((void *)_dialog, SIP_DIALOG_LOG | 1714*943efbc3Sgm209912 SIP_ASSERT_ERROR, __FILE__, __LINE__); 1715*943efbc3Sgm209912 } 171640cb5e5dSvi117747 assert(!isreq); 171740cb5e5dSvi117747 if (SIP_OK_RESP(resp_code)) { 171840cb5e5dSvi117747 _dialog->sip_dlg_state = SIP_DLG_CONFIRMED; 1719d8a40387Sgm209912 /* 1720d8a40387Sgm209912 * If we recieved provisional response before we would 1721d8a40387Sgm209912 * not have captured local contact. So store it now. 1722d8a40387Sgm209912 */ 1723d8a40387Sgm209912 if (_dialog->sip_dlg_type == SIP_UAS_DIALOG && _dialog-> 1724d8a40387Sgm209912 sip_dlg_method == INVITE && method == INVITE) { 1725d8a40387Sgm209912 sip_header_t chdr; 1726d8a40387Sgm209912 (void) pthread_mutex_lock(&sip_msg-> 1727d8a40387Sgm209912 sip_msg_mutex); 1728d8a40387Sgm209912 chdr = sip_search_for_header(sip_msg, 1729d8a40387Sgm209912 SIP_CONTACT, NULL); 1730d8a40387Sgm209912 (void) pthread_mutex_unlock(&sip_msg-> 1731d8a40387Sgm209912 sip_msg_mutex); 1732d8a40387Sgm209912 if (chdr != NULL) { 1733d8a40387Sgm209912 _dialog->sip_dlg_local_contact 1734d8a40387Sgm209912 = sip_dup_header(chdr); 1735d8a40387Sgm209912 _dialog->sip_dlg_new_local_contact = 1736d8a40387Sgm209912 NULL; 1737d8a40387Sgm209912 } 1738d8a40387Sgm209912 } 173940cb5e5dSvi117747 (void) sip_dlg_recompute_rset(_dialog, sip_msg, 174040cb5e5dSvi117747 SIP_UAS_DIALOG); 1741*943efbc3Sgm209912 (void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex); 174240cb5e5dSvi117747 if (sip_dlg_ulp_state_cb != NULL) { 174340cb5e5dSvi117747 sip_dlg_ulp_state_cb(dialog, (sip_msg_t)sip_msg, 174440cb5e5dSvi117747 prev_state, dialog->sip_dlg_state); 174540cb5e5dSvi117747 } 174640cb5e5dSvi117747 } else { 174740cb5e5dSvi117747 (void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex); 174840cb5e5dSvi117747 } 174940cb5e5dSvi117747 } else if (_dialog->sip_dlg_state == SIP_DLG_NEW) { 175040cb5e5dSvi117747 if (!isreq && _dialog->sip_dlg_method == SUBSCRIBE && 175140cb5e5dSvi117747 SIP_PROVISIONAL_RESP(resp_code)) { 175240cb5e5dSvi117747 (void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex); 175340cb5e5dSvi117747 return (dialog); 175440cb5e5dSvi117747 } 175540cb5e5dSvi117747 if (_dialog->sip_dlg_type == SIP_UAC_DIALOG) { 175640cb5e5dSvi117747 _sip_dialog_t *new_dlg; 175740cb5e5dSvi117747 175840cb5e5dSvi117747 if (_dialog->sip_dlg_on_fork) { 175940cb5e5dSvi117747 new_dlg = sip_copy_partial_dialog(_dialog); 176040cb5e5dSvi117747 if (new_dlg == NULL) { 176140cb5e5dSvi117747 (void) pthread_mutex_unlock( 176240cb5e5dSvi117747 &_dialog->sip_dlg_mutex); 176340cb5e5dSvi117747 return (dialog); 176440cb5e5dSvi117747 } 176540cb5e5dSvi117747 /* 176640cb5e5dSvi117747 * This decr/incr dance is because the caller 176740cb5e5dSvi117747 * has incremented the ref on the partial 176840cb5e5dSvi117747 * dialog, we release it here and incr the 176940cb5e5dSvi117747 * ref on the new dialog which will be 177040cb5e5dSvi117747 * released by the caller. 177140cb5e5dSvi117747 */ 177240cb5e5dSvi117747 (void) pthread_mutex_unlock( 177340cb5e5dSvi117747 &_dialog->sip_dlg_mutex); 177440cb5e5dSvi117747 SIP_DLG_REFCNT_DECR(_dialog); 177540cb5e5dSvi117747 _dialog = new_dlg; 177640cb5e5dSvi117747 (void) pthread_mutex_lock( 177740cb5e5dSvi117747 &_dialog->sip_dlg_mutex); 177840cb5e5dSvi117747 SIP_DLG_REFCNT_INCR(_dialog); 177940cb5e5dSvi117747 } else { 178040cb5e5dSvi117747 int index; 178140cb5e5dSvi117747 178240cb5e5dSvi117747 /* 178340cb5e5dSvi117747 * take it out of the list so that further 178440cb5e5dSvi117747 * responses will not result in a dialog. 178540cb5e5dSvi117747 * We will have an extra refcount when we 178640cb5e5dSvi117747 * come back from sip_complete_dialog(), i.e. 178740cb5e5dSvi117747 * one when the partial dialog was created - 178840cb5e5dSvi117747 * in sip_seed_dialog(), one held by the caller 178940cb5e5dSvi117747 * and one that will be added by 179040cb5e5dSvi117747 * sip_complete_dialog(). We need to release 179140cb5e5dSvi117747 * the one added by the sip_seed_dialog(), 179240cb5e5dSvi117747 * since the one in sip_complete_dialog() 179340cb5e5dSvi117747 * is for the same purpose. 179440cb5e5dSvi117747 */ 179540cb5e5dSvi117747 if (SIP_IS_TIMER_RUNNING( 179640cb5e5dSvi117747 _dialog->sip_dlg_timer)) { 179740cb5e5dSvi117747 SIP_CANCEL_TIMER( 179840cb5e5dSvi117747 _dialog->sip_dlg_timer); 179940cb5e5dSvi117747 } 180040cb5e5dSvi117747 index = SIP_DIGEST_TO_HASH(dialog->sip_dlg_id); 180140cb5e5dSvi117747 (void) pthread_mutex_unlock( 180240cb5e5dSvi117747 &_dialog->sip_dlg_mutex); 180340cb5e5dSvi117747 sip_hash_delete(sip_dialog_phash, 180440cb5e5dSvi117747 (void *)_dialog->sip_dlg_id, 180540cb5e5dSvi117747 index, sip_dialog_dontfree); 180640cb5e5dSvi117747 (void) pthread_mutex_lock( 180740cb5e5dSvi117747 &_dialog->sip_dlg_mutex); 180840cb5e5dSvi117747 decr_ref = B_TRUE; 180940cb5e5dSvi117747 } 181040cb5e5dSvi117747 } else { 181140cb5e5dSvi117747 decr_ref = B_TRUE; 181240cb5e5dSvi117747 } 181340cb5e5dSvi117747 (void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex); 181440cb5e5dSvi117747 if ((dialog = sip_complete_dialog(sip_msg, _dialog)) == 181540cb5e5dSvi117747 NULL) { 18162c2c4183Svi117747 if (_dialog->sip_dlg_type == SIP_UAC_DIALOG && decr_ref) 18172c2c4183Svi117747 SIP_DLG_REFCNT_DECR(_dialog); 181840cb5e5dSvi117747 return (NULL); 181940cb5e5dSvi117747 } 182040cb5e5dSvi117747 if (decr_ref) 182140cb5e5dSvi117747 SIP_DLG_REFCNT_DECR(_dialog); 182240cb5e5dSvi117747 } else { 182340cb5e5dSvi117747 (void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex); 182440cb5e5dSvi117747 } 182540cb5e5dSvi117747 return (dialog); 182640cb5e5dSvi117747 } 182740cb5e5dSvi117747 182840cb5e5dSvi117747 /* 182940cb5e5dSvi117747 * Initialize the hash table 183040cb5e5dSvi117747 */ 183140cb5e5dSvi117747 void 183240cb5e5dSvi117747 sip_dialog_init(void (*ulp_dlg_del) (sip_dialog_t, sip_msg_t, void *), 183340cb5e5dSvi117747 void (*ulp_state_cb)(sip_dialog_t, sip_msg_t, int, int)) 183440cb5e5dSvi117747 { 183540cb5e5dSvi117747 int cnt; 183640cb5e5dSvi117747 183740cb5e5dSvi117747 for (cnt = 0; cnt < SIP_HASH_SZ; cnt++) { 183840cb5e5dSvi117747 sip_dialog_hash[cnt].hash_count = 0; 183940cb5e5dSvi117747 sip_dialog_hash[cnt].hash_head = NULL; 184040cb5e5dSvi117747 sip_dialog_hash[cnt].hash_tail = NULL; 184140cb5e5dSvi117747 (void) pthread_mutex_init( 184240cb5e5dSvi117747 &sip_dialog_hash[cnt].sip_hash_mutex, NULL); 184340cb5e5dSvi117747 sip_dialog_phash[cnt].hash_count = 0; 184440cb5e5dSvi117747 sip_dialog_phash[cnt].hash_head = NULL; 184540cb5e5dSvi117747 sip_dialog_phash[cnt].hash_tail = NULL; 184640cb5e5dSvi117747 (void) pthread_mutex_init( 184740cb5e5dSvi117747 &sip_dialog_phash[cnt].sip_hash_mutex, NULL); 184840cb5e5dSvi117747 } 184940cb5e5dSvi117747 if (ulp_dlg_del != NULL) 185040cb5e5dSvi117747 sip_ulp_dlg_del_cb = ulp_dlg_del; 185140cb5e5dSvi117747 185240cb5e5dSvi117747 if (ulp_state_cb != NULL) 185340cb5e5dSvi117747 sip_dlg_ulp_state_cb = ulp_state_cb; 185440cb5e5dSvi117747 } 1855d8a40387Sgm209912 1856d8a40387Sgm209912 /* 1857d8a40387Sgm209912 * Copy the new contact header of re-INVITE 1858d8a40387Sgm209912 */ 1859d8a40387Sgm209912 void 1860d8a40387Sgm209912 sip_dialog_add_new_contact(sip_dialog_t dialog, _sip_msg_t *sip_msg) 1861d8a40387Sgm209912 { 1862d8a40387Sgm209912 sip_header_t chdr = NULL; 1863d8a40387Sgm209912 sip_header_t nhdr = NULL; 1864d8a40387Sgm209912 1865d8a40387Sgm209912 (void) pthread_mutex_lock(&sip_msg->sip_msg_mutex); 1866d8a40387Sgm209912 chdr = sip_search_for_header(sip_msg, SIP_CONTACT, NULL); 1867d8a40387Sgm209912 (void) pthread_mutex_unlock(&sip_msg->sip_msg_mutex); 1868d8a40387Sgm209912 1869d8a40387Sgm209912 if (chdr == NULL) 1870d8a40387Sgm209912 return; 1871d8a40387Sgm209912 1872d8a40387Sgm209912 (void) pthread_mutex_lock(&dialog->sip_dlg_mutex); 1873d8a40387Sgm209912 if (dialog->sip_dlg_method != INVITE || dialog->sip_dlg_state 1874d8a40387Sgm209912 != SIP_DLG_CONFIRMED) { 1875d8a40387Sgm209912 (void) pthread_mutex_unlock(&dialog->sip_dlg_mutex); 1876d8a40387Sgm209912 return; 1877d8a40387Sgm209912 } 1878d8a40387Sgm209912 1879d8a40387Sgm209912 if (((nhdr = sip_dup_header(chdr)) != NULL)) { 1880d8a40387Sgm209912 if (dialog->sip_dlg_new_local_contact != NULL) 1881d8a40387Sgm209912 sip_free_header(dialog->sip_dlg_new_local_contact); 1882d8a40387Sgm209912 dialog->sip_dlg_new_local_contact = nhdr; 1883d8a40387Sgm209912 } 1884d8a40387Sgm209912 (void) pthread_mutex_unlock(&dialog->sip_dlg_mutex); 1885d8a40387Sgm209912 } 1886*943efbc3Sgm209912 1887*943efbc3Sgm209912 /* 1888*943efbc3Sgm209912 * Given a state, return the string - This is mostly for debug purposes 1889*943efbc3Sgm209912 */ 1890*943efbc3Sgm209912 char * 1891*943efbc3Sgm209912 sip_get_dialog_state_str(int state) 1892*943efbc3Sgm209912 { 1893*943efbc3Sgm209912 switch (state) { 1894*943efbc3Sgm209912 case SIP_DLG_NEW: 1895*943efbc3Sgm209912 return ("SIP_DLG_NEW"); 1896*943efbc3Sgm209912 case SIP_DLG_EARLY: 1897*943efbc3Sgm209912 return ("SIP_DLG_EARLY"); 1898*943efbc3Sgm209912 case SIP_DLG_CONFIRMED: 1899*943efbc3Sgm209912 return ("SIP_DLG_CONFIRMED"); 1900*943efbc3Sgm209912 case SIP_DLG_DESTROYED: 1901*943efbc3Sgm209912 return ("SIP_DLG_DESTROYED"); 1902*943efbc3Sgm209912 default: 1903*943efbc3Sgm209912 return ("UNKNOWN"); 1904*943efbc3Sgm209912 } 1905*943efbc3Sgm209912 } 1906