sip_dialog.c revision 5878c602b2d040000355d54d766aac95446139a9
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi/*
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * CDDL HEADER START
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi *
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * The contents of this file are subject to the terms of the
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * Common Development and Distribution License (the "License").
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * You may not use this file except in compliance with the License.
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi *
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * or http://www.opensolaris.org/os/licensing.
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * See the License for the specific language governing permissions
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * and limitations under the License.
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi *
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * When distributing Covered Code, include this CDDL HEADER in each
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * If applicable, add the following below this CDDL HEADER, with the
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * fields enclosed by brackets "[]" replaced with your own identifying
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * information: Portions Copyright [yyyy] [name of copyright owner]
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi *
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * CDDL HEADER END
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi */
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi/*
2c2c41837e330b002c4220a39638150db504fe0evi * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * Use is subject to license terms.
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi */
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi#pragma ident "%Z%%M% %I% %E% SMI"
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
2c2c41837e330b002c4220a39638150db504fe0evi#include <stdio.h>
2c2c41837e330b002c4220a39638150db504fe0evi#include <stdlib.h>
2c2c41837e330b002c4220a39638150db504fe0evi#include <assert.h>
2c2c41837e330b002c4220a39638150db504fe0evi#include <errno.h>
2c2c41837e330b002c4220a39638150db504fe0evi#include <pthread.h>
2c2c41837e330b002c4220a39638150db504fe0evi#include <strings.h>
2c2c41837e330b002c4220a39638150db504fe0evi#include <sip.h>
2c2c41837e330b002c4220a39638150db504fe0evi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi#include "sip_msg.h"
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi#include "sip_miscdefs.h"
2c2c41837e330b002c4220a39638150db504fe0evi#include "sip_hash.h"
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi#include "sip_dialog.h"
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi#include "sip_parse_generic.h"
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi#define SIP_DLG_XCHG_FROM 0
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi#define SIP_DLG_XCHG_TO 1
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi/*
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * Dialog state change callback function
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi */
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vivoid (*sip_dlg_ulp_state_cb)(sip_dialog_t, sip_msg_t, int, int) = NULL;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vivoid (*sip_ulp_dlg_del_cb)(sip_dialog_t, sip_msg_t, void *) = NULL;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331viboolean_t sip_incomplete_dialog(sip_dialog_t);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi/*
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * Exchange From/To header
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi */
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi_sip_header_t *sip_dlg_xchg_from_to(sip_msg_t, int);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi/*
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * Complete dialog hash table
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi */
40cb5e5daa7b80bb70fcf8dadfb20f9281566331visip_hash_t sip_dialog_hash[SIP_HASH_SZ];
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi/*
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * Partial dialog hash table
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi */
40cb5e5daa7b80bb70fcf8dadfb20f9281566331visip_hash_t sip_dialog_phash[SIP_HASH_SZ];
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi/*
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * Route set structure
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi */
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vitypedef struct sip_dlg_route_set_s {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi char *sip_dlg_route;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_str_t sip_dlg_ruri;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi boolean_t sip_dlg_route_lr;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi struct sip_dlg_route_set_s *sip_dlg_route_next;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi}sip_dlg_route_set_t;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331visip_dialog_t sip_seed_dialog(sip_conn_object_t, _sip_msg_t *,
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi boolean_t, int);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331visip_dialog_t sip_complete_dialog(_sip_msg_t *, _sip_dialog_t *);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331viint sip_dialog_process(_sip_msg_t *, sip_dialog_t *);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vivoid sip_dialog_delete(_sip_dialog_t *);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vivoid sip_dialog_init();
40cb5e5daa7b80bb70fcf8dadfb20f9281566331visip_dialog_t sip_dialog_find(_sip_msg_t *);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331viboolean_t sip_dialog_match(void *, void *);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331viboolean_t sip_dialog_free(void *, void *, int *);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331visip_dialog_t sip_update_dialog(sip_dialog_t, _sip_msg_t *);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vichar *sip_dialog_req_uri(sip_dialog_t);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vistatic void sip_release_dialog_res(_sip_dialog_t *);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vivoid sip_dlg_self_destruct(void *);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vistatic int sip_dialog_get_route_set(_sip_dialog_t *, _sip_msg_t *,
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi int);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vistatic void sip_dialog_free_rset(sip_dlg_route_set_t *);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi/*
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * Timer object for partial dialogs
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi */
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vitypedef struct sip_dialog_timer_obj_s {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi _sip_dialog_t *dialog;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi void (*func)(sip_dialog_t, sip_msg_t, void *);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi} sip_dialog_timer_obj_t;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi/*
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * To avoid duplication all over the place
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi */
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vistatic void
40cb5e5daa7b80bb70fcf8dadfb20f9281566331visip_release_dialog_res(_sip_dialog_t *dialog)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi{
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi assert(dialog->sip_dlg_ref_cnt == 0);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (SIP_IS_TIMER_RUNNING(dialog->sip_dlg_timer))
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi SIP_CANCEL_TIMER(dialog->sip_dlg_timer);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (dialog->sip_dlg_call_id != NULL)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_free_header(dialog->sip_dlg_call_id);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (dialog->sip_dlg_local_uri_tag != NULL)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_free_header(dialog->sip_dlg_local_uri_tag);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (dialog->sip_dlg_remote_uri_tag != NULL)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_free_header(dialog->sip_dlg_remote_uri_tag);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (dialog->sip_dlg_remote_target != NULL)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_free_header(dialog->sip_dlg_remote_target);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (dialog->sip_dlg_route_set != NULL)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_free_header(dialog->sip_dlg_route_set);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (dialog->sip_dlg_event != NULL)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_free_header(dialog->sip_dlg_event);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (dialog->sip_dlg_req_uri.sip_str_ptr != NULL) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi free(dialog->sip_dlg_req_uri.sip_str_ptr);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi dialog->sip_dlg_req_uri.sip_str_ptr = NULL;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi dialog->sip_dlg_req_uri.sip_str_len = 0;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (dialog->sip_dlg_rset.sip_str_ptr != NULL) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi free(dialog->sip_dlg_rset.sip_str_ptr);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi dialog->sip_dlg_rset.sip_str_len = 0;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi dialog->sip_dlg_rset.sip_str_ptr = NULL;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) pthread_mutex_destroy(&dialog->sip_dlg_mutex);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi free(dialog);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi}
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi/*
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * Get the route information from the 'value' and add it to the route
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * set.
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi */
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vistatic sip_dlg_route_set_t *
40cb5e5daa7b80bb70fcf8dadfb20f9281566331visip_add_route_to_set(sip_hdr_value_t *value)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi{
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi int vlen = 0;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_dlg_route_set_t *rset;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi char *crlf;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi const sip_param_t *uri_param;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi int error;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi rset = calloc(1, sizeof (*rset));
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (rset == NULL)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (NULL);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi rset->sip_dlg_route_next = NULL;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi vlen = value->sip_value_end - value->sip_value_start;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi /*
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * check for CRLF
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi */
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi crlf = value->sip_value_end - strlen(SIP_CRLF);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi while (crlf != NULL && strncmp(crlf, SIP_CRLF, strlen(SIP_CRLF)) == 0) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi vlen -= strlen(SIP_CRLF);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi crlf -= strlen(SIP_CRLF);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi rset->sip_dlg_route = calloc(1, vlen + 1);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (rset->sip_dlg_route == NULL) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi free(rset);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (NULL);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi /*
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * loose routing
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi */
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi rset->sip_dlg_route_lr = B_FALSE;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) strncpy(rset->sip_dlg_route, value->sip_value_start, vlen);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi rset->sip_dlg_ruri.sip_str_ptr = rset->sip_dlg_route +
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (value->cftr_uri.sip_str_ptr - value->sip_value_start);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi rset->sip_dlg_ruri.sip_str_len = value->cftr_uri.sip_str_len;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi rset->sip_dlg_route[vlen] = '\0';
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi assert(value->sip_value_parsed_uri != NULL);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi /*
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * Check if the 'lr' param is present for this route.
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi */
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi uri_param = sip_get_uri_params(value->sip_value_parsed_uri, &error);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (error != 0) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi free(rset->sip_dlg_route);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi free(rset);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (NULL);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (uri_param != NULL) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi rset->sip_dlg_route_lr = sip_is_param_present(uri_param, "lr",
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi strlen("lr"));
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (rset);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi}
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi/*
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * Depending on the route-set, determine the request URI.
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi */
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vichar *
40cb5e5daa7b80bb70fcf8dadfb20f9281566331visip_dialog_req_uri(sip_dialog_t dialog)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi{
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi const sip_str_t *req_uri;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi char *uri;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi _sip_dialog_t *_dialog;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi _dialog = (_sip_dialog_t *)dialog;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (_dialog->sip_dlg_route_set == NULL ||
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi _dialog->sip_dlg_req_uri.sip_str_ptr == NULL) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi const struct sip_value *val;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi val = sip_get_header_value(_dialog->sip_dlg_remote_target,
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi NULL);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (val == NULL)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (NULL);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi req_uri = &((sip_hdr_value_t *)val)->cftr_uri;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi } else {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi req_uri = &_dialog->sip_dlg_req_uri;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi uri = (char *)malloc(req_uri->sip_str_len + 1);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (uri == NULL)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (NULL);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) strncpy(uri, req_uri->sip_str_ptr, req_uri->sip_str_len);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi uri[req_uri->sip_str_len] = '\0';
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (uri);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi}
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi/*
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * Free the route set.
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi */
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vivoid
40cb5e5daa7b80bb70fcf8dadfb20f9281566331visip_dialog_free_rset(sip_dlg_route_set_t *rset)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi{
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_dlg_route_set_t *next;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi while (rset != NULL) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi next = rset->sip_dlg_route_next;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi rset->sip_dlg_route_next = NULL;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi free(rset->sip_dlg_route);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi free(rset);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi rset = next;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi}
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi/*
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * Recompute route-set
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi */
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vistatic int
40cb5e5daa7b80bb70fcf8dadfb20f9281566331visip_dlg_recompute_rset(_sip_dialog_t *dialog, _sip_msg_t *sip_msg, int what)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi{
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi int ret;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (dialog->sip_dlg_route_set != NULL) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_free_header(dialog->sip_dlg_route_set);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi dialog->sip_dlg_route_set = NULL;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (dialog->sip_dlg_req_uri.sip_str_ptr != NULL) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi free(dialog->sip_dlg_req_uri.sip_str_ptr);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi dialog->sip_dlg_req_uri.sip_str_ptr = NULL;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi dialog->sip_dlg_req_uri.sip_str_len = 0;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (dialog->sip_dlg_rset.sip_str_ptr != NULL) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi free(dialog->sip_dlg_rset.sip_str_ptr);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi dialog->sip_dlg_rset.sip_str_ptr = NULL;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi dialog->sip_dlg_rset.sip_str_len = 0;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi ret = sip_dialog_get_route_set(dialog, sip_msg, what);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (ret);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi}
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi/*
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * If the route set is empty, the UAC MUST place the remote target URI
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * into the Request-URI. The UAC MUST NOT add a Route header field to
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * the request.
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi *
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * If the route set is not empty, and the first URI in the route set
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * contains the lr parameter (see Section 19.1.1), the UAC MUST place
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * the remote target URI into the Request-URI and MUST include a Route
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * header field containing the route set values in order, including all
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * parameters.
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi *
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * If the route set is not empty, and its first URI does not contain the
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * lr parameter, the UAC MUST place the first URI from the route set
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * into the Request-URI, stripping any parameters that are not allowed
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * in a Request-URI. The UAC MUST add a Route header field containing
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * the remainder of the route set values in order, including all
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * parameters. The UAC MUST then place the remote target URI into the
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * Route header field as the last value.
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi */
40cb5e5daa7b80bb70fcf8dadfb20f9281566331viint
40cb5e5daa7b80bb70fcf8dadfb20f9281566331visip_dialog_set_route_hdr(_sip_dialog_t *dialog, sip_dlg_route_set_t *rset_head,
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi int rcnt, int rlen)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi{
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi size_t rset_len;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi _sip_header_t *rhdr;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi char *rset;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi char *rp;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi char *rsp;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi int count;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_dlg_route_set_t *route;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi boolean_t first = B_TRUE;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi const sip_str_t *to_uri;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi char *uri = NULL;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi int rspl;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi int rpl;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi assert(rcnt > 0);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi dialog->sip_dlg_rset.sip_str_len = rlen + rcnt - 1;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi dialog->sip_dlg_rset.sip_str_ptr = malloc(rlen + rcnt);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (dialog->sip_dlg_rset.sip_str_ptr == NULL)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (ENOMEM);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi rsp = dialog->sip_dlg_rset.sip_str_ptr;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi rspl = rlen + rcnt;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi route = rset_head;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi rset_len = rlen;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (!route->sip_dlg_route_lr) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi const struct sip_value *val;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi val = sip_get_header_value(dialog->sip_dlg_remote_target, NULL);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi to_uri = &((sip_hdr_value_t *)val)->cftr_uri;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi uri = (char *)malloc(to_uri->sip_str_len + 1);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (uri == NULL) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi free(dialog->sip_dlg_rset.sip_str_ptr);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi dialog->sip_dlg_rset.sip_str_len = 0;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi dialog->sip_dlg_rset.sip_str_ptr = NULL;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (ENOMEM);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) strncpy(uri, to_uri->sip_str_ptr, to_uri->sip_str_len);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi uri[to_uri->sip_str_len] = '\0';
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi rset_len = rlen - strlen(route->sip_dlg_route) + strlen(uri) +
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi SIP_SPACE_LEN + sizeof (char) + SIP_SPACE_LEN +
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sizeof (char);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi count = snprintf(rsp, rspl, "%s", route->sip_dlg_route);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi dialog->sip_dlg_req_uri.sip_str_ptr = malloc(
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi route->sip_dlg_ruri.sip_str_len + 1);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (dialog->sip_dlg_req_uri.sip_str_ptr == NULL) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi free(uri);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi free(dialog->sip_dlg_rset.sip_str_ptr);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi dialog->sip_dlg_rset.sip_str_len = 0;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi dialog->sip_dlg_rset.sip_str_ptr = NULL;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (ENOMEM);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) strncpy(dialog->sip_dlg_req_uri.sip_str_ptr, rsp +
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (route->sip_dlg_ruri.sip_str_ptr - route->sip_dlg_route),
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi route->sip_dlg_ruri.sip_str_len);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi dialog->sip_dlg_req_uri.sip_str_ptr[
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi route->sip_dlg_ruri.sip_str_len] = '\0';
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi dialog->sip_dlg_req_uri.sip_str_len =
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi route->sip_dlg_ruri.sip_str_len;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi rsp += count;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi rspl -= count;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi route = route->sip_dlg_route_next;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi /*
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * rcnt - 1 is for the number of COMMAs
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi */
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi rset_len += strlen(SIP_ROUTE) + SIP_SPACE_LEN + sizeof (char) +
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi SIP_SPACE_LEN + rcnt - 1;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi rset = malloc(rset_len + 1);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (rset == NULL) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi free(dialog->sip_dlg_rset.sip_str_ptr);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi dialog->sip_dlg_rset.sip_str_len = 0;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi dialog->sip_dlg_rset.sip_str_ptr = NULL;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (ENOMEM);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi rhdr = sip_new_header(rset_len + strlen(SIP_CRLF));
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (rhdr == NULL) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi free(rset);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi free(dialog->sip_dlg_rset.sip_str_ptr);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi dialog->sip_dlg_rset.sip_str_len = 0;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi dialog->sip_dlg_rset.sip_str_ptr = NULL;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (ENOMEM);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi rp = rset;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi rpl = rset_len + 1;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi count = snprintf(rp, rpl, "%s %c ", SIP_ROUTE, SIP_HCOLON);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi rp += count;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi rpl -= count;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi while (route != NULL) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (first) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi count = snprintf(rp, rpl, "%s", route->sip_dlg_route);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi rp += count;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi rpl -= count;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi first = B_FALSE;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (uri != NULL) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi count = snprintf(rsp, rspl, "%c%s",
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi SIP_COMMA, route->sip_dlg_route);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi } else {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi count = snprintf(rsp, rspl, "%s",
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi route->sip_dlg_route);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi rsp += count;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi rspl -= count;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi } else {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi count = snprintf(rp, rpl, "%c%s", SIP_COMMA,
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi route->sip_dlg_route);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi rp += count;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi rpl -= count;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi count = snprintf(rsp, rspl, "%c%s", SIP_COMMA,
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi route->sip_dlg_route);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi rsp += count;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi rspl -= count;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi route = route->sip_dlg_route_next;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi assert(rsp <= dialog->sip_dlg_rset.sip_str_ptr +
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi dialog->sip_dlg_rset.sip_str_len);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi dialog->sip_dlg_rset.sip_str_ptr[dialog->sip_dlg_rset.sip_str_len] =
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi '\0';
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (uri != NULL) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (first) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi count = snprintf(rp, rpl, "%c %s %c", SIP_LAQUOT,
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi uri, SIP_RAQUOT);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi } else {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi count = snprintf(rp, rpl, "%c%c %s %c", SIP_COMMA,
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi SIP_LAQUOT, uri, SIP_RAQUOT);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi rp += count;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi rpl -= count;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi free(uri);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi assert(rp <= rset + rset_len);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) snprintf(rhdr->sip_hdr_start, rset_len + strlen(SIP_CRLF) + 1,
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi "%s%s", rset, SIP_CRLF);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi free(rset);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi dialog->sip_dlg_route_set = (sip_header_t)rhdr;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_dialog_free_rset(rset_head);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (0);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi}
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi/*
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * UAC Behavior
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * The route set MUST be set to the list of URIs in the Record-Route
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * header field from the response, taken in reverse order and preserving
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * all URI parameters.
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi *
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * UAS behavior
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * The route set MUST be set to the list of URIs in the Record-Route
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * header field from the request, taken in order and preserving all URI
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * parameters.
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi */
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vistatic int
40cb5e5daa7b80bb70fcf8dadfb20f9281566331visip_dialog_get_route_set(_sip_dialog_t *dialog, _sip_msg_t *sip_msg, int what)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi{
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_header_t rrhdr;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_hdr_value_t *value;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi int error;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_dlg_route_set_t *rset_head = NULL;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_dlg_route_set_t *rset_tail = NULL;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_dlg_route_set_t *rset;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi int rset_cnt = 0;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi int rset_len = 0;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) pthread_mutex_lock(&sip_msg->sip_msg_mutex);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi rrhdr = sip_search_for_header(sip_msg, SIP_RECORD_ROUTE, NULL);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi while (rrhdr != NULL) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) pthread_mutex_unlock(&sip_msg->sip_msg_mutex);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi value = (sip_hdr_value_t *)sip_get_header_value(rrhdr, &error);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi while (value != NULL && error == 0) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi char *crlf;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (value->sip_value_state == SIP_VALUE_BAD) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi value = (sip_hdr_value_t *)sip_get_next_value(
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (sip_header_value_t)value, &error);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi continue;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi rset = sip_add_route_to_set(value);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (rset == NULL)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi goto r_error;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi /*
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * Add one for COMMA
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi */
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi rset_cnt++;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi rset_len += (value->sip_value_end -
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi value->sip_value_start);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi /*
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * Check for CRLF
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi */
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi crlf = value->sip_value_end - strlen(SIP_CRLF);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi while (crlf != NULL &&
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi strncmp(crlf, SIP_CRLF, strlen(SIP_CRLF)) == 0) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi rset_len -= strlen(SIP_CRLF);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi crlf -= strlen(SIP_CRLF);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (rset_head == NULL) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi assert(rset_tail == NULL);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi rset_head = rset_tail = rset;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi } else if (what == SIP_UAS_DIALOG) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi rset_tail->sip_dlg_route_next = rset;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi rset_tail = rset;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi } else if (what == SIP_UAC_DIALOG) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi rset->sip_dlg_route_next = rset_head;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi rset_head = rset;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi } else {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi assert(0);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi value = (sip_hdr_value_t *)sip_get_next_value(
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (sip_header_value_t)value, &error);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) pthread_mutex_lock(&sip_msg->sip_msg_mutex);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi rrhdr = sip_search_for_header(sip_msg, SIP_RECORD_ROUTE, rrhdr);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) pthread_mutex_unlock(&sip_msg->sip_msg_mutex);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (rset_cnt == 0)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (0);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (sip_dialog_set_route_hdr(dialog, rset_head, rset_cnt,
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi rset_len) != 0) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi goto r_error;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (0);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vir_error:
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_dialog_free_rset(rset_head);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (ENOMEM);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi}
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi/*
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * UAS behavior:
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * The remote sequence number MUST be set to the value of the sequence
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * number in the CSeq header field of the request. The local sequence
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * number MUST be empty. The call identifier component of the dialog ID
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * MUST be set to the value of the Call-ID in the request. The local
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * tag component of the dialog ID MUST be set to the tag in the To field
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * in the response to the request (which always includes a tag), and the
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * remote tag component of the dialog ID MUST be set to the tag from the
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * From field in the request. A UAS MUST be prepared to receive a
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * request without a tag in the From field, in which case the tag is
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * considered to have a value of null.
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * The remote URI MUST be set to the URI in the From field, and the
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * local URI MUST be set to the URI in the To field.
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * The remote target MUST be set to the URI from the Contact header field
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * of the request.
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi *
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * UAC behavior:
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * The local sequence number MUST be set to the value of the sequence
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * number in the CSeq header field of the request. The remote sequence
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * number MUST be empty (it is established when the remote UA sends a
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * request within the dialog). The call identifier component of the
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * dialog ID MUST be set to the value of the Call-ID in the request.
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * The local tag component of the dialog ID MUST be set to the tag in
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * the From field in the request, and the remote tag component of the
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * dialog ID MUST be set to the tag in the To field of the response. A
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * UAC MUST be prepared to receive a response without a tag in the To
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * field, in which case the tag is considered to have a value of null.
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * The remote URI MUST be set to the URI in the To field, and the local
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * URI MUST be set to the URI in the From field.
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * The remote target MUST be set to the URI from the Contact header field
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * of the response.
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi */
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi/*
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * This is the routine that seeds a dialog.
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi */
40cb5e5daa7b80bb70fcf8dadfb20f9281566331visip_dialog_t
40cb5e5daa7b80bb70fcf8dadfb20f9281566331visip_seed_dialog(sip_conn_object_t obj, _sip_msg_t *sip_msg,
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi boolean_t dlg_on_fork, int dlg_type)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi{
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi _sip_dialog_t *dialog;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi int cseq;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_header_t fhdr = NULL;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_header_t thdr = NULL;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_header_t chdr;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_header_t cihdr;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_header_t evhdr = NULL;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi const struct sip_value *value;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_dialog_timer_obj_t *tim_obj = NULL;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi const sip_str_t *callid;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_method_t method;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi int timer1 = sip_timer_T1;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi int error;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (!sip_msg_is_request((sip_msg_t)sip_msg, &error))
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (NULL);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi method = sip_get_request_method((sip_msg_t)sip_msg, &error);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi /*
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * Only INVITE and SUBSCRIBE supported
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi */
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (error != 0 || (method != INVITE && method != SUBSCRIBE))
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (NULL);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi /*
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * A request outside of a dialog MUST NOT contain a To tag
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi */
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (sip_get_to_tag((sip_msg_t)sip_msg, NULL) != NULL)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (NULL);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (dlg_type == SIP_UAS_DIALOG) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi thdr = sip_dlg_xchg_from_to((sip_msg_t)sip_msg,
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi SIP_DLG_XCHG_FROM);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) pthread_mutex_lock(&sip_msg->sip_msg_mutex);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi } else {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) pthread_mutex_lock(&sip_msg->sip_msg_mutex);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi fhdr = sip_search_for_header(sip_msg, SIP_FROM, NULL);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi cihdr = sip_search_for_header(sip_msg, SIP_CALL_ID, NULL);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi chdr = sip_search_for_header(sip_msg, SIP_CONTACT, NULL);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (method == SUBSCRIBE)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi evhdr = sip_search_for_header(sip_msg, SIP_EVENT, NULL);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) pthread_mutex_unlock(&sip_msg->sip_msg_mutex);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if ((fhdr == NULL && thdr == NULL) || cihdr == NULL || chdr == NULL ||
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (method == SUBSCRIBE && evhdr == NULL)) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (thdr != NULL)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_free_header(thdr);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (NULL);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi /*
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * Sanity check since we just store the headers in the dialog
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi */
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (sip_get_from_tag((sip_msg_t)sip_msg, NULL) == NULL ||
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_get_from_uri_str((sip_msg_t)sip_msg, NULL) == NULL ||
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi ((cseq = sip_get_callseq_num((sip_msg_t)sip_msg, NULL)) == -1) ||
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (callid = sip_get_callid((sip_msg_t)sip_msg, NULL)) == NULL ||
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_get_to_uri_str((sip_msg_t)sip_msg, NULL) == NULL ||
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi ((value = sip_get_header_value(chdr, NULL)) == NULL) ||
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_get_contact_uri_str((sip_header_value_t)value, NULL) == NULL) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (thdr != NULL)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_free_header(thdr);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (NULL);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi tim_obj = calloc(1, sizeof (sip_dialog_timer_obj_t));
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (tim_obj == NULL) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (thdr != NULL)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_free_header(thdr);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (NULL);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi dialog = calloc(1, sizeof (_sip_dialog_t));
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (dialog == NULL) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (thdr != NULL)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_free_header(thdr);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (NULL);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi /*
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * We will take the TO header with the tag when we complete this
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * dialog
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi */
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (dlg_type == SIP_UAS_DIALOG) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi dialog->sip_dlg_remote_uri_tag = thdr;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi /*
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * We take the remote target from the incoming request on the
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * UAS. For the UAC, we will take it from the response.
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi */
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if ((dialog->sip_dlg_remote_target = sip_dup_header(chdr)) ==
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi NULL) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi goto dia_err;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi } else {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if ((dialog->sip_dlg_local_uri_tag = sip_dup_header(fhdr)) ==
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi NULL) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi goto dia_err;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if ((dialog->sip_dlg_call_id = sip_dup_header(cihdr)) == NULL)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi goto dia_err;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (method == SUBSCRIBE) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi dialog->sip_dlg_event = sip_dup_header(evhdr);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (dialog->sip_dlg_event == NULL) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi goto dia_err;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi dialog->sip_dlg_rset.sip_str_ptr = NULL;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi dialog->sip_dlg_rset.sip_str_len = 0;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi dialog->sip_dlg_req_uri.sip_str_ptr = NULL;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi dialog->sip_dlg_req_uri.sip_str_len = 0;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi /*
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * Get the route set from the request, if present
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi */
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (dlg_type == SIP_UAS_DIALOG &&
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_dialog_get_route_set(dialog, sip_msg, dlg_type) != 0) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi goto dia_err;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (dlg_type == SIP_UAC_DIALOG)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi dialog->sip_dlg_local_cseq = cseq;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi else
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi dialog->sip_dlg_remote_cseq = cseq;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi dialog->sip_dlg_type = dlg_type;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi dialog->sip_dlg_on_fork = dlg_on_fork;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi dialog->sip_dlg_method = method;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi /*
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * Set the partial dialog timer with the INVITE timeout val
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi */
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (sip_conn_timer1 != NULL)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi timer1 = sip_conn_timer1(obj);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi SIP_INIT_TIMER(dialog->sip_dlg_timer, 64 * timer1);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi tim_obj->dialog = dialog;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi /*
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * Since at the client we never pass the partial dialog, we need not
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * invoke the callback when the partial dialog self-destructs.
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi */
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (dlg_type == SIP_UAS_DIALOG)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi tim_obj->func = sip_ulp_dlg_del_cb;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi SIP_SCHED_TIMER(dialog->sip_dlg_timer, (void *)tim_obj,
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_dlg_self_destruct);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (!SIP_IS_TIMER_RUNNING(dialog->sip_dlg_timer))
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi goto dia_err;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) pthread_mutex_init(&dialog->sip_dlg_mutex, NULL);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (dlg_type == SIP_UAC_DIALOG) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi const sip_str_t *local_tag;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi local_tag = sip_get_from_tag((sip_msg_t)sip_msg, NULL);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi assert(local_tag != NULL);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_md5_hash(local_tag->sip_str_ptr, local_tag->sip_str_len,
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi callid->sip_str_ptr, callid->sip_str_len,
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi NULL, 0, NULL, 0, NULL, 0, NULL, 0,
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (uchar_t *)dialog->sip_dlg_id);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi /*
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * Add it to the partial hash table
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi */
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (sip_hash_add(sip_dialog_phash, (void *)dialog,
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi SIP_DIGEST_TO_HASH(dialog->sip_dlg_id)) != 0) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi goto dia_err;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi SIP_DLG_REFCNT_INCR(dialog);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return ((sip_dialog_t)dialog);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vidia_err:
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_release_dialog_res(dialog);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (SIP_IS_TIMER_RUNNING(dialog->sip_dlg_timer))
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi SIP_CANCEL_TIMER(dialog->sip_dlg_timer);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (tim_obj != NULL)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi free(tim_obj);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (NULL);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi}
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi/*
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * When creating a dialog from a NOTIFY request, we need to get the FROM
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * header for the dialog from the TO header of the NOTIFY.
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi */
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi_sip_header_t *
40cb5e5daa7b80bb70fcf8dadfb20f9281566331visip_dlg_xchg_from_to(sip_msg_t sip_msg, int what)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi{
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi int len;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi _sip_header_t *newhdr;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi int cnt;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi const struct sip_header *hdr;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi int hdrsize;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi int error;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi hdr = sip_get_header(sip_msg, what == SIP_DLG_XCHG_FROM ? SIP_FROM :
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi SIP_TO, NULL, &error);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (error != 0 || hdr == NULL)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (NULL);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (sip_parse_goto_values((_sip_header_t *)hdr) != 0)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (NULL);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi len = hdr->sip_hdr_end - hdr->sip_hdr_current;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (what == SIP_DLG_XCHG_FROM) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi hdrsize = len + strlen(SIP_TO) + SIP_SPACE_LEN + sizeof (char) +
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi SIP_SPACE_LEN;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi } else {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi hdrsize = len + strlen(SIP_FROM) + SIP_SPACE_LEN +
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sizeof (char) + SIP_SPACE_LEN;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi newhdr = sip_new_header(hdrsize);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (newhdr == NULL)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (NULL);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (what == SIP_DLG_XCHG_FROM) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi cnt = snprintf(newhdr->sip_hdr_current, hdrsize + 1,
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi "%s %c ", SIP_TO, SIP_HCOLON);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi } else {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi cnt = snprintf(newhdr->sip_hdr_current, hdrsize + 1,
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi "%s %c ", SIP_FROM, SIP_HCOLON);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi newhdr->sip_hdr_current += cnt;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) strncpy(newhdr->sip_hdr_current, hdr->sip_hdr_current, len);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi newhdr->sip_hdr_current += len;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi assert(newhdr->sip_hdr_current == newhdr->sip_hdr_end);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi assert(hdr->sip_header_functions != NULL);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi /*
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * FROM and TO have common parsing functions
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi */
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi newhdr->sip_header_functions = hdr->sip_header_functions;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi newhdr->sip_hdr_current = newhdr->sip_hdr_start;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (newhdr);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi}
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi/*
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * This is the response that completes the dialog that was created
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * in sip_seed_dialog().
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi */
40cb5e5daa7b80bb70fcf8dadfb20f9281566331visip_dialog_t
40cb5e5daa7b80bb70fcf8dadfb20f9281566331visip_complete_dialog(_sip_msg_t *sip_msg, _sip_dialog_t *dialog)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi{
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi _sip_header_t *thdr;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi _sip_header_t *evhdr = NULL;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi _sip_header_t *substate = NULL;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_header_t chdr = NULL;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi int resp_code;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi const sip_str_t *ttag;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi const sip_str_t *remtag;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi const sip_str_t *callid;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi const struct sip_value *val;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_method_t method;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi int error = 0;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi int prev_state;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi boolean_t alloc_thdr = B_FALSE;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (sip_msg_is_request((sip_msg_t)sip_msg, &error) && error == 0)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi method = sip_get_request_method((sip_msg_t)sip_msg, &error);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi else
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi method = sip_get_callseq_method((sip_msg_t)sip_msg, &error);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (error != 0 || dialog == NULL ||
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (sip_msg_is_request((sip_msg_t)sip_msg, &error) &&
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (dialog->sip_dlg_method == INVITE || method != NOTIFY))) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (NULL);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if ((dialog->sip_dlg_type == SIP_UAC_DIALOG && method != NOTIFY &&
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_get_callseq_num((sip_msg_t)sip_msg, NULL) !=
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi dialog->sip_dlg_local_cseq) ||
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (dialog->sip_dlg_type == SIP_UAS_DIALOG && method != NOTIFY &&
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_get_callseq_num((sip_msg_t)sip_msg, NULL) !=
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi dialog->sip_dlg_remote_cseq)) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (NULL);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (method == NOTIFY) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi const sip_str_t *sstate;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi thdr = sip_dlg_xchg_from_to((sip_msg_t)sip_msg,
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi SIP_DLG_XCHG_FROM);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (thdr == NULL)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (NULL);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi alloc_thdr = B_TRUE;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) pthread_mutex_lock(&sip_msg->sip_msg_mutex);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi chdr = sip_search_for_header(sip_msg, SIP_CONTACT, NULL);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (chdr == NULL) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) pthread_mutex_unlock(&sip_msg->sip_msg_mutex);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_free_header(thdr);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (NULL);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi evhdr = sip_search_for_header(sip_msg, SIP_EVENT, NULL);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (evhdr == NULL) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) pthread_mutex_unlock(&sip_msg->sip_msg_mutex);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_free_header(thdr);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (NULL);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi substate = sip_search_for_header(sip_msg,
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi SIP_SUBSCRIPTION_STATE, NULL);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (substate == NULL) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) pthread_mutex_unlock(&sip_msg->sip_msg_mutex);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_free_header(thdr);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (NULL);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) pthread_mutex_unlock(&sip_msg->sip_msg_mutex);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sstate = sip_get_substate((sip_msg_t)sip_msg, &error);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (sstate == NULL || error != 0) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_free_header(thdr);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (NULL);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if ((sstate->sip_str_len != strlen("pending") &&
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sstate->sip_str_len != strlen("active")) ||
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi ((sstate->sip_str_len == strlen("pending") &&
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi strncasecmp(sstate->sip_str_ptr, "pending",
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi strlen("pending")) != 0) ||
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (sstate->sip_str_len == strlen("active") &&
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi strncasecmp(sstate->sip_str_ptr, "active",
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi strlen("active")) != 0))) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_free_header(thdr);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (NULL);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi ttag = sip_get_from_tag((sip_msg_t)sip_msg, NULL);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi } else {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (dialog->sip_dlg_type == SIP_UAS_DIALOG) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi thdr = sip_dlg_xchg_from_to((sip_msg_t)sip_msg,
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi SIP_DLG_XCHG_TO);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi alloc_thdr = B_TRUE;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi } else {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) pthread_mutex_lock(&sip_msg->sip_msg_mutex);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi thdr = sip_search_for_header(sip_msg, SIP_TO, NULL);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (dialog->sip_dlg_remote_target == NULL) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi chdr = sip_search_for_header(sip_msg,
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi SIP_CONTACT, NULL);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) pthread_mutex_unlock(&sip_msg->sip_msg_mutex);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (thdr == NULL) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) pthread_mutex_unlock(&sip_msg->sip_msg_mutex);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (NULL);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi ttag = sip_get_to_tag((sip_msg_t)sip_msg, NULL);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (ttag == NULL) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (alloc_thdr)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_free_header(thdr);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (NULL);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi prev_state = dialog->sip_dlg_state;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (method == NOTIFY) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi int error;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi const sip_str_t *dlg_id_val = NULL;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi const sip_str_t *event;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi const sip_str_t *id_val = NULL;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_header_value_t ev_val;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_hdr_value_t *dlg_ev_val = NULL;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi event = sip_get_event((sip_msg_t)sip_msg, &error);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (event == NULL || error != 0) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_free_header(thdr);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (NULL);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi ev_val = (sip_header_value_t)sip_get_header_value(evhdr,
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi &error);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (ev_val != NULL)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi id_val = sip_get_param_value(ev_val, "id", &error);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (error == 0) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi dlg_ev_val = (sip_hdr_value_t *)sip_get_header_value(
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi dialog->sip_dlg_event, &error);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (dlg_ev_val == NULL || error != 0) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_free_header(thdr);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (NULL);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi dlg_id_val = sip_get_param_value((sip_header_value_t)dlg_ev_val,
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi "id", &error);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (error != 0 ||
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi dlg_ev_val->str_val_len != event->sip_str_len ||
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi strncmp(dlg_ev_val->str_val_ptr, event->sip_str_ptr,
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi event->sip_str_len != 0)) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_free_header(thdr);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (NULL);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if ((dlg_id_val == NULL && id_val != NULL) ||
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (dlg_id_val != NULL && id_val == NULL)) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_free_header(thdr);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (NULL);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi } else if (dlg_id_val != NULL && id_val != NULL) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (dlg_id_val->sip_str_len != id_val->sip_str_len ||
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi strncasecmp(dlg_id_val->sip_str_ptr,
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi id_val->sip_str_ptr, dlg_id_val->sip_str_len) !=
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi 0) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_free_header(thdr);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (NULL);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (dialog->sip_dlg_type == SIP_UAC_DIALOG) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi dialog->sip_dlg_remote_uri_tag = thdr;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if ((dialog->sip_dlg_remote_target =
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_dup_header(chdr)) == NULL) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_free_header(thdr);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (NULL);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi } else {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi dialog->sip_dlg_local_uri_tag = thdr;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi dialog->sip_dlg_state = SIP_DLG_CONFIRMED;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi } else {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi resp_code = sip_get_response_code((sip_msg_t)sip_msg, &error);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) pthread_mutex_lock(&dialog->sip_dlg_mutex);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi assert(dialog->sip_dlg_state == SIP_DLG_NEW);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (dialog->sip_dlg_remote_target == NULL && chdr != NULL) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi assert(dialog->sip_dlg_type == SIP_UAC_DIALOG);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if ((dialog->sip_dlg_remote_target =
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_dup_header(chdr)) == NULL) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) pthread_mutex_unlock(
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi &dialog->sip_dlg_mutex);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (alloc_thdr)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_free_header(thdr);
2c2c41837e330b002c4220a39638150db504fe0evi goto terminate_new_dlg;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (sip_dialog_get_route_set(dialog, sip_msg,
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi dialog->sip_dlg_type) != 0) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) pthread_mutex_unlock(
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi &dialog->sip_dlg_mutex);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (alloc_thdr)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_free_header(thdr);
2c2c41837e330b002c4220a39638150db504fe0evi goto terminate_new_dlg;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (SIP_PROVISIONAL_RESP(resp_code)) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi dialog->sip_dlg_state = SIP_DLG_EARLY;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi } else if (SIP_OK_RESP(resp_code)) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi /*
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * Per 12.1 the UAS must include the contact header
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * for a dialog establishing response, so if we
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * don't find one, we terminate it.
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi */
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (dialog->sip_dlg_remote_target == NULL) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) pthread_mutex_unlock(
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi &dialog->sip_dlg_mutex);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (sip_ulp_dlg_del_cb != NULL) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_ulp_dlg_del_cb(dialog,
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (sip_msg_t)sip_msg, NULL);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (alloc_thdr)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_free_header(thdr);
2c2c41837e330b002c4220a39638150db504fe0evi goto terminate_new_dlg;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi dialog->sip_dlg_state = SIP_DLG_CONFIRMED;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi } else {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) pthread_mutex_unlock(&dialog->sip_dlg_mutex);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (sip_ulp_dlg_del_cb != NULL) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_ulp_dlg_del_cb(dialog, (sip_msg_t)sip_msg,
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi NULL);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (alloc_thdr)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_free_header(thdr);
2c2c41837e330b002c4220a39638150db504fe0evi goto terminate_new_dlg;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (dialog->sip_dlg_type == SIP_UAS_DIALOG) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi dialog->sip_dlg_local_uri_tag = thdr;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi } else {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if ((dialog->sip_dlg_remote_uri_tag =
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_dup_header(thdr)) == NULL) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) pthread_mutex_unlock(
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi &dialog->sip_dlg_mutex);
2c2c41837e330b002c4220a39638150db504fe0evi goto terminate_new_dlg;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi /*
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * Cancel the partial dialog timer
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi */
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (SIP_IS_TIMER_RUNNING(dialog->sip_dlg_timer))
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi SIP_CANCEL_TIMER(dialog->sip_dlg_timer);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (dialog->sip_dlg_type == SIP_UAC_DIALOG) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi val = sip_get_header_value(dialog->sip_dlg_local_uri_tag,
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi &error);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi } else {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi val = sip_get_header_value(dialog->sip_dlg_remote_uri_tag,
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi &error);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi assert(val != NULL && error == 0);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi remtag = sip_get_param_value((sip_header_value_t)val, "tag", &error);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi val = sip_get_header_value(dialog->sip_dlg_call_id, &error);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi callid = &((sip_hdr_value_t *)val)->str_val;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi /*
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * Get an ID for this dialog
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi */
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (dialog->sip_dlg_type == SIP_UAC_DIALOG) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_md5_hash(remtag->sip_str_ptr, remtag->sip_str_len,
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi ttag->sip_str_ptr, ttag->sip_str_len,
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi callid->sip_str_ptr, callid->sip_str_len,
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi NULL, 0, NULL, 0, NULL, 0, (uchar_t *)dialog->sip_dlg_id);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi } else {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_md5_hash(ttag->sip_str_ptr, ttag->sip_str_len,
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi remtag->sip_str_ptr, remtag->sip_str_len,
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi callid->sip_str_ptr, callid->sip_str_len,
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi NULL, 0, NULL, 0, NULL, 0, (uchar_t *)dialog->sip_dlg_id);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi SIP_DLG_REFCNT_INCR(dialog);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) pthread_mutex_unlock(&dialog->sip_dlg_mutex);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi /*
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * Add it to the hash table
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi */
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (sip_hash_add(sip_dialog_hash, (void *)dialog,
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi SIP_DIGEST_TO_HASH(dialog->sip_dlg_id)) != 0) {
2c2c41837e330b002c4220a39638150db504fe0evi terminate_new_dlg:
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi /*
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * So that sip_dialog_delete() does not try to remove
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * this from the hash table.
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi */
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) pthread_mutex_lock(&dialog->sip_dlg_mutex);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (dialog->sip_dlg_type == SIP_UAS_DIALOG) {
2c2c41837e330b002c4220a39638150db504fe0evi if (dialog->sip_dlg_local_uri_tag != NULL) {
2c2c41837e330b002c4220a39638150db504fe0evi sip_free_header(dialog->sip_dlg_local_uri_tag);
2c2c41837e330b002c4220a39638150db504fe0evi dialog->sip_dlg_local_uri_tag = NULL;
2c2c41837e330b002c4220a39638150db504fe0evi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi } else {
2c2c41837e330b002c4220a39638150db504fe0evi if (dialog->sip_dlg_remote_uri_tag != NULL) {
2c2c41837e330b002c4220a39638150db504fe0evi sip_free_header(dialog->sip_dlg_remote_uri_tag);
2c2c41837e330b002c4220a39638150db504fe0evi dialog->sip_dlg_remote_uri_tag = NULL;
2c2c41837e330b002c4220a39638150db504fe0evi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) pthread_mutex_unlock(&dialog->sip_dlg_mutex);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_dialog_terminate(dialog, (sip_msg_t)sip_msg);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (NULL);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (sip_dlg_ulp_state_cb != NULL) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_dlg_ulp_state_cb((sip_dialog_t)dialog,
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (sip_msg_t)sip_msg, prev_state, dialog->sip_dlg_state);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return ((sip_dialog_t)dialog);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi}
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi/*
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * Check if this dialog is a match.
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi */
40cb5e5daa7b80bb70fcf8dadfb20f9281566331viboolean_t
40cb5e5daa7b80bb70fcf8dadfb20f9281566331visip_dialog_match(void *obj, void *hindex)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi{
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi _sip_dialog_t *dialog = (_sip_dialog_t *)obj;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) pthread_mutex_lock(&dialog->sip_dlg_mutex);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (dialog->sip_dlg_state == SIP_DLG_DESTROYED) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) pthread_mutex_unlock(&dialog->sip_dlg_mutex);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (B_FALSE);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (bcmp(dialog->sip_dlg_id, hindex,
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sizeof (dialog->sip_dlg_id)) == 0) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi SIP_DLG_REFCNT_INCR(dialog);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) pthread_mutex_unlock(&dialog->sip_dlg_mutex);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (B_TRUE);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) pthread_mutex_unlock(&dialog->sip_dlg_mutex);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (B_FALSE);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi}
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi/*
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * Don't delete, just take it out of the hash
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi */
40cb5e5daa7b80bb70fcf8dadfb20f9281566331viboolean_t
40cb5e5daa7b80bb70fcf8dadfb20f9281566331visip_dialog_dontfree(void *obj, void *hindex, int *found)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi{
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi _sip_dialog_t *dialog = (_sip_dialog_t *)obj;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi *found = 0;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) pthread_mutex_lock(&dialog->sip_dlg_mutex);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (bcmp(dialog->sip_dlg_id, hindex, sizeof (dialog->sip_dlg_id))
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi == 0) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi *found = 1;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) pthread_mutex_unlock(&dialog->sip_dlg_mutex);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (B_TRUE);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) pthread_mutex_unlock(&dialog->sip_dlg_mutex);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (B_FALSE);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi}
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi/*
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * Free resources associated with the dialog, the object will be removed
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * from the hash list by sip_hash_delete.
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi */
40cb5e5daa7b80bb70fcf8dadfb20f9281566331viboolean_t
40cb5e5daa7b80bb70fcf8dadfb20f9281566331visip_dialog_free(void *obj, void *hindex, int *found)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi{
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi _sip_dialog_t *dialog = (_sip_dialog_t *)obj;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi *found = 0;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) pthread_mutex_lock(&dialog->sip_dlg_mutex);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (bcmp(dialog->sip_dlg_id, hindex, sizeof (dialog->sip_dlg_id))
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi == 0) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi *found = 1;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi assert(dialog->sip_dlg_state == SIP_DLG_DESTROYED);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (dialog->sip_dlg_ref_cnt != 0) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) pthread_mutex_unlock(&dialog->sip_dlg_mutex);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (B_FALSE);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_release_dialog_res(dialog);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (B_TRUE);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) pthread_mutex_unlock(&dialog->sip_dlg_mutex);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (B_FALSE);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi}
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi/*
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * The UAS will receive the request from the transaction layer. If the
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * request has a tag in the To header field, the UAS core computes the
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * dialog identifier corresponding to the request and compares it with
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * existing dialogs. If there is a match, this is a mid-dialog request.
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi */
40cb5e5daa7b80bb70fcf8dadfb20f9281566331visip_dialog_t
40cb5e5daa7b80bb70fcf8dadfb20f9281566331visip_dialog_find(_sip_msg_t *sip_msg)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi{
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi const sip_str_t *localtag;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi const sip_str_t *remtag;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi const sip_str_t *callid;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi uint16_t digest[8];
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi _sip_dialog_t *dialog;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi boolean_t is_request;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi int error;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi is_request = sip_msg_is_request((sip_msg_t)sip_msg, &error);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (error != 0)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (NULL);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (is_request) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi localtag = sip_get_to_tag((sip_msg_t)sip_msg, &error);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (error == 0)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi remtag = sip_get_from_tag((sip_msg_t)sip_msg, &error);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi } else {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi remtag = sip_get_to_tag((sip_msg_t)sip_msg, &error);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (error == 0)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi localtag = sip_get_from_tag((sip_msg_t)sip_msg, &error);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (error != 0)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (NULL);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi callid = sip_get_callid((sip_msg_t)sip_msg, &error);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (error != 0 || remtag == NULL || localtag == NULL ||
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi callid == NULL) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (NULL);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_md5_hash(localtag->sip_str_ptr, localtag->sip_str_len,
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi remtag->sip_str_ptr, remtag->sip_str_len,
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi callid->sip_str_ptr, callid->sip_str_len,
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi NULL, 0, NULL, 0, NULL, 0, (uchar_t *)digest);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi dialog = (_sip_dialog_t *)sip_hash_find(sip_dialog_hash,
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void *)digest, SIP_DIGEST_TO_HASH(digest), sip_dialog_match);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (dialog == NULL) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_md5_hash(localtag->sip_str_ptr, localtag->sip_str_len,
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi NULL, 0, callid->sip_str_ptr, callid->sip_str_len,
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi NULL, 0, NULL, 0, NULL, 0, (uchar_t *)digest);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi dialog = (_sip_dialog_t *)sip_hash_find(sip_dialog_phash,
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void *)digest, SIP_DIGEST_TO_HASH(digest),
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_dialog_match);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return ((sip_dialog_t)dialog);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi}
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi/*
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * We keep this partial dialog for the duration of the INVITE
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * transaction timeout duration, i.e. Timer B.
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi */
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vivoid
40cb5e5daa7b80bb70fcf8dadfb20f9281566331visip_dlg_self_destruct(void *args)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi{
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_dialog_timer_obj_t *tim_obj = (sip_dialog_timer_obj_t *)args;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi _sip_dialog_t *dialog = (_sip_dialog_t *)tim_obj->dialog;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi int index;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) pthread_mutex_lock(&dialog->sip_dlg_mutex);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi assert(dialog->sip_dlg_state == SIP_DLG_NEW);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi dialog->sip_dlg_state = SIP_DLG_DESTROYED;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (dialog->sip_dlg_type == SIP_UAC_DIALOG) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi index = SIP_DIGEST_TO_HASH(dialog->sip_dlg_id);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) pthread_mutex_unlock(&dialog->sip_dlg_mutex);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_hash_delete(sip_dialog_phash, (void *)dialog->sip_dlg_id,
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi index, sip_dialog_dontfree);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi } else {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) pthread_mutex_unlock(&dialog->sip_dlg_mutex);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (tim_obj->func != NULL)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi tim_obj->func(dialog, NULL, NULL);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi free(tim_obj);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi SIP_DLG_REFCNT_DECR(dialog);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi}
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi/*
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * Terminate a dialog
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi */
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vivoid
40cb5e5daa7b80bb70fcf8dadfb20f9281566331visip_dialog_terminate(_sip_dialog_t *dialog, sip_msg_t sip_msg)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi{
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi int prev_state;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) pthread_mutex_lock(&dialog->sip_dlg_mutex);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi prev_state = dialog->sip_dlg_state;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi dialog->sip_dlg_state = SIP_DLG_DESTROYED;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) pthread_mutex_unlock(&dialog->sip_dlg_mutex);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (sip_dlg_ulp_state_cb != NULL) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_dlg_ulp_state_cb((sip_dialog_t)dialog, sip_msg, prev_state,
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi dialog->sip_dlg_state);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi SIP_DLG_REFCNT_DECR(dialog);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi}
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi/*
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * Delete a dialog
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi */
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vivoid
40cb5e5daa7b80bb70fcf8dadfb20f9281566331visip_dialog_delete(_sip_dialog_t *dialog)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi{
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi int index;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi /*
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * partial dialog, not in the hash table
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi */
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (dialog->sip_dlg_local_uri_tag == NULL ||
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi dialog->sip_dlg_remote_uri_tag == NULL) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi /*
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * Cancel the partial dialog timer
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi */
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (SIP_IS_TIMER_RUNNING(dialog->sip_dlg_timer))
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi SIP_CANCEL_TIMER(dialog->sip_dlg_timer);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_release_dialog_res(dialog);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi index = SIP_DIGEST_TO_HASH(dialog->sip_dlg_id);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_hash_delete(sip_dialog_hash, (void *)dialog->sip_dlg_id, index,
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_dialog_free);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi}
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi/*
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * Get the remote target from the CONTACT header from the 200 OK response
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi */
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vistatic boolean_t
40cb5e5daa7b80bb70fcf8dadfb20f9281566331visip_get_rtarg(_sip_dialog_t *dialog, _sip_msg_t *sip_msg)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi{
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_header_t chdr;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (dialog->sip_dlg_remote_target != NULL)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (B_TRUE);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) pthread_mutex_lock(&sip_msg->sip_msg_mutex);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi chdr = sip_search_for_header(sip_msg, SIP_CONTACT, NULL);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) pthread_mutex_unlock(&sip_msg->sip_msg_mutex);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (chdr == NULL)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (B_FALSE);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if ((dialog->sip_dlg_remote_target = sip_dup_header(chdr)) == NULL)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (B_FALSE);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (B_TRUE);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi}
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi/*
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * Process an incoming request/response
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi */
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi/* ARGSUSED */
40cb5e5daa7b80bb70fcf8dadfb20f9281566331viint
40cb5e5daa7b80bb70fcf8dadfb20f9281566331visip_dialog_process(_sip_msg_t *sip_msg, sip_dialog_t *sip_dialog)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi{
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi boolean_t request;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi _sip_dialog_t *_dialog;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi int error;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi request = sip_msg_is_request((sip_msg_t)sip_msg, &error);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (error != 0)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (EINVAL);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi _dialog = (_sip_dialog_t *)*sip_dialog;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (request) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi uint32_t cseq;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_method_t method;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi cseq = sip_get_callseq_num((sip_msg_t)sip_msg, &error);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (error != 0)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (EINVAL);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi method = sip_get_callseq_method((sip_msg_t)sip_msg, &error);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (error != 0)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (EINVAL);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (sip_get_request_method((sip_msg_t)sip_msg, &error) !=
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi method) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (EINVAL);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) pthread_mutex_lock(&_dialog->sip_dlg_mutex);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi /*
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * Requests that do not change in any way the state
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * of a dialog may be received within a dialog.
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * They are processed as if they had been received
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * outside the dialog.
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * For dialogs that have been established with an
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * INVITE, the only target refresh request defined is
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * re-INVITE.
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi */
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (_dialog->sip_dlg_method == INVITE &&
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi method == INVITE && _dialog->sip_dlg_remote_cseq != 0 &&
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi SIP_CSEQ_LT(cseq, _dialog->sip_dlg_remote_cseq)) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (EPROTO);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi /*
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * Target-Refresh request
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi */
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (_dialog->sip_dlg_method == INVITE && method == INVITE) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_header_t chdr;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_header_t nchdr;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) pthread_mutex_lock(&sip_msg->sip_msg_mutex);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi chdr = sip_search_for_header(sip_msg, SIP_CONTACT,
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi NULL);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) pthread_mutex_unlock(&sip_msg->sip_msg_mutex);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (chdr != NULL &&
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (nchdr = sip_dup_header(chdr)) != NULL) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (_dialog->sip_dlg_remote_target != NULL) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_free_header(
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi _dialog->sip_dlg_remote_target);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi _dialog->sip_dlg_remote_target = nchdr;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi _dialog->sip_dlg_remote_cseq = cseq;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi } else {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi int resp_code;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_method_t method;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi int error;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi resp_code = sip_get_response_code((sip_msg_t)sip_msg, &error);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (error == 0) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi method = sip_get_callseq_method((sip_msg_t)sip_msg,
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi &error);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (error != 0)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (error);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) pthread_mutex_lock(&_dialog->sip_dlg_mutex);
5878c602b2d040000355d54d766aac95446139a9gm if (_dialog->sip_dlg_state == SIP_DLG_DESTROYED) {
5878c602b2d040000355d54d766aac95446139a9gm (void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
5878c602b2d040000355d54d766aac95446139a9gm return (0);
5878c602b2d040000355d54d766aac95446139a9gm }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi assert(_dialog->sip_dlg_state == SIP_DLG_EARLY ||
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi _dialog->sip_dlg_state == SIP_DLG_CONFIRMED);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi /*
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * Let the user delete the dialog if it is not a 1XX/2XX resp
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * for an early INVITE dialog.
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi */
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (SIP_OK_RESP(resp_code)) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (method == INVITE) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (!sip_get_rtarg(_dialog, sip_msg)) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) pthread_mutex_unlock(
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi &_dialog->sip_dlg_mutex);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (sip_ulp_dlg_del_cb != NULL) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_ulp_dlg_del_cb(
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (sip_dialog_t)_dialog,
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (sip_msg_t)sip_msg, NULL);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_dialog_terminate(_dialog,
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (sip_msg_t)sip_msg);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (0);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (_dialog->sip_dlg_state == SIP_DLG_EARLY) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi _dialog->sip_dlg_state =
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi SIP_DLG_CONFIRMED;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) pthread_mutex_unlock(
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi &_dialog->sip_dlg_mutex);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) sip_dlg_recompute_rset(_dialog,
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_msg, SIP_UAC_DIALOG);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (sip_dlg_ulp_state_cb != NULL) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_dlg_ulp_state_cb(
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (sip_dialog_t)_dialog,
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_msg, SIP_DLG_EARLY,
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi _dialog->sip_dlg_state);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (0);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (0);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi}
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi/*
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * Copy partial dialog to create a complete dialog
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi */
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi_sip_dialog_t *
40cb5e5daa7b80bb70fcf8dadfb20f9281566331visip_copy_partial_dialog(_sip_dialog_t *dialog)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi{
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi _sip_dialog_t *new_dlg;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi new_dlg = calloc(1, sizeof (_sip_dialog_t));
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (new_dlg == NULL)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (NULL);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (dialog->sip_dlg_req_uri.sip_str_ptr != NULL) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi new_dlg->sip_dlg_req_uri.sip_str_ptr =
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi malloc(dialog->sip_dlg_req_uri.sip_str_len + 1);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (new_dlg->sip_dlg_req_uri.sip_str_ptr == NULL) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi free(new_dlg);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (NULL);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) strncpy(new_dlg->sip_dlg_req_uri.sip_str_ptr,
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi dialog->sip_dlg_req_uri.sip_str_ptr,
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi dialog->sip_dlg_req_uri.sip_str_len);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi new_dlg->sip_dlg_req_uri.sip_str_ptr[
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi dialog->sip_dlg_req_uri.sip_str_len] = '\0';
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi new_dlg->sip_dlg_req_uri.sip_str_len =
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi dialog->sip_dlg_req_uri.sip_str_len;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (dialog->sip_dlg_route_set != NULL) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi assert(dialog->sip_dlg_rset.sip_str_ptr != NULL);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi new_dlg->sip_dlg_rset.sip_str_ptr =
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi malloc(dialog->sip_dlg_rset.sip_str_len + 1);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (new_dlg->sip_dlg_rset.sip_str_ptr == NULL) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (new_dlg->sip_dlg_req_uri.sip_str_ptr != NULL)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi free(new_dlg->sip_dlg_req_uri.sip_str_ptr);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi free(new_dlg);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (NULL);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) strncpy(new_dlg->sip_dlg_rset.sip_str_ptr,
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi dialog->sip_dlg_rset.sip_str_ptr,
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi dialog->sip_dlg_rset.sip_str_len);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi new_dlg->sip_dlg_rset.sip_str_ptr[
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi dialog->sip_dlg_rset.sip_str_len] = '\0';
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi new_dlg->sip_dlg_rset.sip_str_len =
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi dialog->sip_dlg_rset.sip_str_len;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi new_dlg->sip_dlg_route_set =
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_dup_header(dialog->sip_dlg_route_set);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (new_dlg->sip_dlg_route_set == NULL) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi free(new_dlg->sip_dlg_rset.sip_str_ptr);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (new_dlg->sip_dlg_req_uri.sip_str_ptr != NULL)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi free(new_dlg->sip_dlg_req_uri.sip_str_ptr);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi free(new_dlg);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (NULL);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if ((new_dlg->sip_dlg_local_uri_tag =
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_dup_header(dialog->sip_dlg_local_uri_tag)) == NULL ||
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (new_dlg->sip_dlg_remote_target =
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_dup_header(dialog->sip_dlg_remote_target)) == NULL ||
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (new_dlg->sip_dlg_call_id =
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_dup_header(dialog->sip_dlg_call_id)) == NULL) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_release_dialog_res(new_dlg);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (NULL);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (dialog->sip_dlg_event != NULL) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi new_dlg->sip_dlg_event = sip_dup_header(dialog->sip_dlg_event);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (new_dlg->sip_dlg_event == NULL) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_release_dialog_res(new_dlg);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (NULL);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi new_dlg->sip_dlg_local_cseq = dialog->sip_dlg_local_cseq;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi new_dlg->sip_dlg_type = dialog->sip_dlg_type;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi new_dlg->sip_dlg_on_fork = B_FALSE;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) pthread_mutex_init(&new_dlg->sip_dlg_mutex, NULL);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (new_dlg);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi}
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi/*
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * Update the dialog using the response
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi */
40cb5e5daa7b80bb70fcf8dadfb20f9281566331visip_dialog_t
40cb5e5daa7b80bb70fcf8dadfb20f9281566331visip_update_dialog(sip_dialog_t dialog, _sip_msg_t *sip_msg)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi{
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi _sip_dialog_t *_dialog;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi boolean_t isreq;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_method_t method;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi int resp_code = 0;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi int prev_state;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi boolean_t decr_ref = B_FALSE;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi int error;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi isreq = sip_msg_is_request((sip_msg_t)sip_msg, &error);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (error != 0)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (dialog);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi _dialog = (_sip_dialog_t *)dialog;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) pthread_mutex_lock(&_dialog->sip_dlg_mutex);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (isreq) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi method = sip_get_request_method((sip_msg_t)sip_msg, &error);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (error != 0 || _dialog->sip_dlg_method != SUBSCRIBE ||
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi method != NOTIFY) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (dialog);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi } else {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi resp_code = sip_get_response_code((sip_msg_t)sip_msg, &error);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (error != 0) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (dialog);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi prev_state = _dialog->sip_dlg_state;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (_dialog->sip_dlg_state == SIP_DLG_CONFIRMED) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi } else if (_dialog->sip_dlg_state == SIP_DLG_EARLY) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi /*
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * Let the user delete the dialog if it is not a 1XX/2XX resp
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * for an early dialog.
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi */
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi assert(!isreq);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (SIP_OK_RESP(resp_code)) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi _dialog->sip_dlg_state = SIP_DLG_CONFIRMED;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) sip_dlg_recompute_rset(_dialog, sip_msg,
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi SIP_UAS_DIALOG);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (sip_dlg_ulp_state_cb != NULL) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_dlg_ulp_state_cb(dialog, (sip_msg_t)sip_msg,
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi prev_state, dialog->sip_dlg_state);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi } else {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi } else if (_dialog->sip_dlg_state == SIP_DLG_NEW) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (!isreq && _dialog->sip_dlg_method == SUBSCRIBE &&
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi SIP_PROVISIONAL_RESP(resp_code)) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (dialog);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (_dialog->sip_dlg_type == SIP_UAC_DIALOG) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi _sip_dialog_t *new_dlg;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (_dialog->sip_dlg_on_fork) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi new_dlg = sip_copy_partial_dialog(_dialog);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (new_dlg == NULL) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) pthread_mutex_unlock(
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi &_dialog->sip_dlg_mutex);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (dialog);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi /*
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * This decr/incr dance is because the caller
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * has incremented the ref on the partial
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * dialog, we release it here and incr the
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * ref on the new dialog which will be
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * released by the caller.
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi */
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) pthread_mutex_unlock(
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi &_dialog->sip_dlg_mutex);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi SIP_DLG_REFCNT_DECR(_dialog);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi _dialog = new_dlg;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) pthread_mutex_lock(
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi &_dialog->sip_dlg_mutex);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi SIP_DLG_REFCNT_INCR(_dialog);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi } else {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi int index;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi /*
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * take it out of the list so that further
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * responses will not result in a dialog.
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * We will have an extra refcount when we
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * come back from sip_complete_dialog(), i.e.
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * one when the partial dialog was created -
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * in sip_seed_dialog(), one held by the caller
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * and one that will be added by
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * sip_complete_dialog(). We need to release
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * the one added by the sip_seed_dialog(),
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * since the one in sip_complete_dialog()
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * is for the same purpose.
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi */
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (SIP_IS_TIMER_RUNNING(
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi _dialog->sip_dlg_timer)) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi SIP_CANCEL_TIMER(
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi _dialog->sip_dlg_timer);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi index = SIP_DIGEST_TO_HASH(dialog->sip_dlg_id);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) pthread_mutex_unlock(
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi &_dialog->sip_dlg_mutex);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_hash_delete(sip_dialog_phash,
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void *)_dialog->sip_dlg_id,
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi index, sip_dialog_dontfree);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) pthread_mutex_lock(
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi &_dialog->sip_dlg_mutex);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi decr_ref = B_TRUE;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi } else {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi decr_ref = B_TRUE;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if ((dialog = sip_complete_dialog(sip_msg, _dialog)) ==
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi NULL) {
2c2c41837e330b002c4220a39638150db504fe0evi if (_dialog->sip_dlg_type == SIP_UAC_DIALOG && decr_ref)
2c2c41837e330b002c4220a39638150db504fe0evi SIP_DLG_REFCNT_DECR(_dialog);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (NULL);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (decr_ref)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi SIP_DLG_REFCNT_DECR(_dialog);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi } else {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (dialog);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi}
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi/*
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * Initialize the hash table
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi */
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vivoid
40cb5e5daa7b80bb70fcf8dadfb20f9281566331visip_dialog_init(void (*ulp_dlg_del) (sip_dialog_t, sip_msg_t, void *),
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi void (*ulp_state_cb)(sip_dialog_t, sip_msg_t, int, int))
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi{
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi int cnt;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi for (cnt = 0; cnt < SIP_HASH_SZ; cnt++) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_dialog_hash[cnt].hash_count = 0;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_dialog_hash[cnt].hash_head = NULL;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_dialog_hash[cnt].hash_tail = NULL;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) pthread_mutex_init(
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi &sip_dialog_hash[cnt].sip_hash_mutex, NULL);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_dialog_phash[cnt].hash_count = 0;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_dialog_phash[cnt].hash_head = NULL;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_dialog_phash[cnt].hash_tail = NULL;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) pthread_mutex_init(
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi &sip_dialog_phash[cnt].sip_hash_mutex, NULL);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (ulp_dlg_del != NULL)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_ulp_dlg_del_cb = ulp_dlg_del;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (ulp_state_cb != NULL)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_dlg_ulp_state_cb = ulp_state_cb;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi}