140cb5e5dSvi117747 /* 240cb5e5dSvi117747 * CDDL HEADER START 340cb5e5dSvi117747 * 440cb5e5dSvi117747 * The contents of this file are subject to the terms of the 540cb5e5dSvi117747 * Common Development and Distribution License (the "License"). 640cb5e5dSvi117747 * You may not use this file except in compliance with the License. 740cb5e5dSvi117747 * 840cb5e5dSvi117747 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 940cb5e5dSvi117747 * or http://www.opensolaris.org/os/licensing. 1040cb5e5dSvi117747 * See the License for the specific language governing permissions 1140cb5e5dSvi117747 * and limitations under the License. 1240cb5e5dSvi117747 * 1340cb5e5dSvi117747 * When distributing Covered Code, include this CDDL HEADER in each 1440cb5e5dSvi117747 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 1540cb5e5dSvi117747 * If applicable, add the following below this CDDL HEADER, with the 1640cb5e5dSvi117747 * fields enclosed by brackets "[]" replaced with your own identifying 1740cb5e5dSvi117747 * information: Portions Copyright [yyyy] [name of copyright owner] 1840cb5e5dSvi117747 * 1940cb5e5dSvi117747 * CDDL HEADER END 2040cb5e5dSvi117747 */ 2140cb5e5dSvi117747 2240cb5e5dSvi117747 /* 23*943efbc3Sgm209912 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 2440cb5e5dSvi117747 * Use is subject to license terms. 2540cb5e5dSvi117747 */ 2640cb5e5dSvi117747 2740cb5e5dSvi117747 #pragma ident "%Z%%M% %I% %E% SMI" 2840cb5e5dSvi117747 292c2c4183Svi117747 #include <string.h> 30*943efbc3Sgm209912 #include <strings.h> 312c2c4183Svi117747 #include <stdlib.h> 322c2c4183Svi117747 #include <assert.h> 332c2c4183Svi117747 #include <ctype.h> 342c2c4183Svi117747 #include <errno.h> 352c2c4183Svi117747 #include <pthread.h> 362c2c4183Svi117747 #include <sip.h> 372c2c4183Svi117747 3840cb5e5dSvi117747 #include "sip_msg.h" 3940cb5e5dSvi117747 #include "sip_miscdefs.h" 4040cb5e5dSvi117747 #include "sip_xaction.h" 4140cb5e5dSvi117747 #include "sip_dialog.h" 4240cb5e5dSvi117747 #include "sip_parse_generic.h" 4340cb5e5dSvi117747 4440cb5e5dSvi117747 void (*sip_ulp_recv)(const sip_conn_object_t, sip_msg_t, 4540cb5e5dSvi117747 const sip_dialog_t) = NULL; 4640cb5e5dSvi117747 uint_t (*sip_stack_timeout)(void *, void (*func)(void *), 4740cb5e5dSvi117747 struct timeval *) = NULL; 4840cb5e5dSvi117747 boolean_t (*sip_stack_untimeout)(uint_t) = NULL; 4940cb5e5dSvi117747 int (*sip_stack_send)(sip_conn_object_t xonn_object, char *, int) = 5040cb5e5dSvi117747 NULL; 5140cb5e5dSvi117747 void (*sip_refhold_conn)(sip_conn_object_t) = NULL; 5240cb5e5dSvi117747 void (*sip_refrele_conn)(sip_conn_object_t) = NULL; 5340cb5e5dSvi117747 boolean_t (*sip_is_conn_stream)(sip_conn_object_t) = NULL; 5440cb5e5dSvi117747 boolean_t (*sip_is_conn_reliable)(sip_conn_object_t) = NULL; 5540cb5e5dSvi117747 int (*sip_conn_rem_addr)(sip_conn_object_t, struct sockaddr *, 5640cb5e5dSvi117747 socklen_t *) = NULL; 5740cb5e5dSvi117747 int (*sip_conn_local_addr)(sip_conn_object_t, struct sockaddr *, 5840cb5e5dSvi117747 socklen_t *) = NULL; 5940cb5e5dSvi117747 int (*sip_conn_transport)(sip_conn_object_t) = NULL; 6040cb5e5dSvi117747 int (*sip_conn_timer1)(sip_conn_object_t) = NULL; 6140cb5e5dSvi117747 int (*sip_conn_timer2)(sip_conn_object_t) = NULL; 6240cb5e5dSvi117747 int (*sip_conn_timer4)(sip_conn_object_t) = NULL; 6340cb5e5dSvi117747 int (*sip_conn_timerd)(sip_conn_object_t) = NULL; 6440cb5e5dSvi117747 6540cb5e5dSvi117747 boolean_t sip_manage_dialog = B_FALSE; 6640cb5e5dSvi117747 6740cb5e5dSvi117747 uint64_t sip_hash_salt = 0; 6840cb5e5dSvi117747 6940cb5e5dSvi117747 /* 7040cb5e5dSvi117747 * Defaults, overridden by configured values, if any 7140cb5e5dSvi117747 */ 7240cb5e5dSvi117747 int sip_timer_T1 = SIP_TIMER_T1; 7340cb5e5dSvi117747 int sip_timer_T2 = SIP_TIMER_T2; 7440cb5e5dSvi117747 int sip_timer_T4 = SIP_TIMER_T4; 7540cb5e5dSvi117747 int sip_timer_TD = 32 * SIP_SECONDS; 7640cb5e5dSvi117747 7740cb5e5dSvi117747 /* 7840cb5e5dSvi117747 * list of sent-by values registered by the UA 7940cb5e5dSvi117747 */ 8040cb5e5dSvi117747 sent_by_list_t *sip_sent_by = NULL; 8140cb5e5dSvi117747 int sip_sent_by_count = 0; 8240cb5e5dSvi117747 pthread_mutex_t sip_sent_by_lock; 8340cb5e5dSvi117747 8440cb5e5dSvi117747 /* 8540cb5e5dSvi117747 * Create and send an error response 8640cb5e5dSvi117747 */ 8740cb5e5dSvi117747 static void 8840cb5e5dSvi117747 sip_send_resp(sip_conn_object_t conn_obj, _sip_msg_t *sip_msg, int resp) 8940cb5e5dSvi117747 { 9040cb5e5dSvi117747 _sip_msg_t *sip_msg_resp; 9140cb5e5dSvi117747 9240cb5e5dSvi117747 sip_msg_resp = (_sip_msg_t *)sip_create_response((sip_msg_t)sip_msg, 9340cb5e5dSvi117747 resp, sip_get_resp_desc(resp), NULL, NULL); 9440cb5e5dSvi117747 if (sip_msg_resp == NULL) { 9540cb5e5dSvi117747 /* 9640cb5e5dSvi117747 * Message was too bad to even create a 9740cb5e5dSvi117747 * response. Just drop the messge. 9840cb5e5dSvi117747 */ 9940cb5e5dSvi117747 return; 10040cb5e5dSvi117747 } 10140cb5e5dSvi117747 /* 10240cb5e5dSvi117747 * We directly send it to the transport here. 10340cb5e5dSvi117747 */ 10440cb5e5dSvi117747 if (sip_adjust_msgbuf(sip_msg_resp) != 0) { 10540cb5e5dSvi117747 sip_free_msg((sip_msg_t)sip_msg_resp); 10640cb5e5dSvi117747 return; 10740cb5e5dSvi117747 } 108*943efbc3Sgm209912 109*943efbc3Sgm209912 SIP_UPDATE_COUNTERS(B_FALSE, 0, resp, B_TRUE, sip_msg_resp-> 110*943efbc3Sgm209912 sip_msg_len); 11140cb5e5dSvi117747 (void) sip_stack_send(conn_obj, sip_msg_resp->sip_msg_buf, 11240cb5e5dSvi117747 sip_msg_resp->sip_msg_len); 11340cb5e5dSvi117747 sip_free_msg((sip_msg_t)sip_msg_resp); 11440cb5e5dSvi117747 } 11540cb5e5dSvi117747 11640cb5e5dSvi117747 /* 11740cb5e5dSvi117747 * Validate some of the common headers 11840cb5e5dSvi117747 */ 11940cb5e5dSvi117747 boolean_t 12040cb5e5dSvi117747 sip_check_common_headers(sip_conn_object_t conn_obj, _sip_msg_t *sip_msg) 12140cb5e5dSvi117747 { 12240cb5e5dSvi117747 int err; 12340cb5e5dSvi117747 12440cb5e5dSvi117747 if (sip_get_to_uri_str((sip_msg_t)sip_msg, &err) == NULL) 12540cb5e5dSvi117747 goto error; 12640cb5e5dSvi117747 if (sip_get_from_uri_str((sip_msg_t)sip_msg, &err) == NULL) 12740cb5e5dSvi117747 goto error; 12840cb5e5dSvi117747 if (sip_get_callseq_num((sip_msg_t)sip_msg, &err) < 0) 12940cb5e5dSvi117747 goto error; 13040cb5e5dSvi117747 if (sip_get_callid((sip_msg_t)sip_msg, &err) == NULL) 13140cb5e5dSvi117747 goto error; 13240cb5e5dSvi117747 return (B_FALSE); 13340cb5e5dSvi117747 error: 13440cb5e5dSvi117747 sip_send_resp(conn_obj, sip_msg, SIP_BAD_REQUEST); 13540cb5e5dSvi117747 return (B_TRUE); 13640cb5e5dSvi117747 } 13740cb5e5dSvi117747 13840cb5e5dSvi117747 /* 13940cb5e5dSvi117747 * setup pointers to where the headers are. 14040cb5e5dSvi117747 */ 14140cb5e5dSvi117747 static int 14240cb5e5dSvi117747 sip_setup_header_pointers(_sip_msg_t *sip_msg) 14340cb5e5dSvi117747 { 14440cb5e5dSvi117747 char *msg; 14540cb5e5dSvi117747 _sip_header_t *sip_msg_header; 14640cb5e5dSvi117747 char *end; 14740cb5e5dSvi117747 14840cb5e5dSvi117747 msg = sip_msg->sip_msg_buf; 14940cb5e5dSvi117747 end = sip_msg->sip_msg_buf + sip_msg->sip_msg_len; 15040cb5e5dSvi117747 /* 15140cb5e5dSvi117747 * Skip while space. 15240cb5e5dSvi117747 */ 15340cb5e5dSvi117747 while (isspace(*msg)) { 15440cb5e5dSvi117747 if (msg < end) 15540cb5e5dSvi117747 msg++; 15640cb5e5dSvi117747 else 15740cb5e5dSvi117747 return (EINVAL); 15840cb5e5dSvi117747 } 15940cb5e5dSvi117747 16040cb5e5dSvi117747 /* 16140cb5e5dSvi117747 * We consider Request and Response line as a header 16240cb5e5dSvi117747 */ 16340cb5e5dSvi117747 for (;;) { 16440cb5e5dSvi117747 /* 16540cb5e5dSvi117747 * Skip CRLF 16640cb5e5dSvi117747 */ 16740cb5e5dSvi117747 if (strncmp(SIP_CRLF, msg, strlen(SIP_CRLF)) == 0) { 16840cb5e5dSvi117747 if (sip_msg->sip_msg_headers_end != NULL) { 16940cb5e5dSvi117747 SKIP_CRLF(msg); 17040cb5e5dSvi117747 sip_msg->sip_msg_headers_end->sip_hdr_end = msg; 17140cb5e5dSvi117747 } 17240cb5e5dSvi117747 /* 17340cb5e5dSvi117747 * Start of a header. 17440cb5e5dSvi117747 * Check for empty line. 17540cb5e5dSvi117747 */ 17640cb5e5dSvi117747 if (strncmp(SIP_CRLF, msg, strlen(SIP_CRLF)) == 0) { 17740cb5e5dSvi117747 /* 17840cb5e5dSvi117747 * empty line, start of content. 17940cb5e5dSvi117747 */ 18040cb5e5dSvi117747 SKIP_CRLF(msg); 18140cb5e5dSvi117747 sip_msg->sip_msg_headers_end->sip_hdr_end = msg; 18240cb5e5dSvi117747 break; 18340cb5e5dSvi117747 } 18440cb5e5dSvi117747 /* 18540cb5e5dSvi117747 * store start of header. 18640cb5e5dSvi117747 */ 18740cb5e5dSvi117747 sip_msg_header = calloc(1, sizeof (_sip_header_t)); 18840cb5e5dSvi117747 if (sip_msg_header == NULL) 18940cb5e5dSvi117747 return (EINVAL); 19040cb5e5dSvi117747 sip_msg_header->sip_hdr_start = msg; 19140cb5e5dSvi117747 sip_msg_header->sip_hdr_current = msg; 19240cb5e5dSvi117747 sip_msg_header->sip_hdr_allocated = B_FALSE; 19340cb5e5dSvi117747 sip_msg_header->sip_hdr_prev = 19440cb5e5dSvi117747 sip_msg->sip_msg_headers_end; 19540cb5e5dSvi117747 sip_msg_header->sip_hdr_next = NULL; 19640cb5e5dSvi117747 sip_msg_header->sip_hdr_sipmsg = sip_msg; 19740cb5e5dSvi117747 sip_msg->sip_msg_headers_end->sip_hdr_next = 19840cb5e5dSvi117747 sip_msg_header; 19940cb5e5dSvi117747 sip_msg->sip_msg_headers_end = sip_msg_header; 20040cb5e5dSvi117747 } else { 20140cb5e5dSvi117747 if (sip_msg->sip_msg_headers_start == NULL) { 20240cb5e5dSvi117747 /* 20340cb5e5dSvi117747 * Allocate first header structure. 20440cb5e5dSvi117747 */ 20540cb5e5dSvi117747 sip_msg_header = calloc(1, 20640cb5e5dSvi117747 sizeof (_sip_header_t)); 20740cb5e5dSvi117747 if (sip_msg_header == NULL) 20840cb5e5dSvi117747 return (EINVAL); 20940cb5e5dSvi117747 sip_msg_header->sip_hdr_allocated = B_FALSE; 21040cb5e5dSvi117747 sip_msg_header->sip_hdr_start = msg; 21140cb5e5dSvi117747 sip_msg_header->sip_hdr_current = msg; 21240cb5e5dSvi117747 sip_msg_header->sip_hdr_sipmsg = sip_msg; 21340cb5e5dSvi117747 sip_msg->sip_msg_headers_start = sip_msg_header; 21440cb5e5dSvi117747 sip_msg->sip_msg_headers_end = sip_msg_header; 21540cb5e5dSvi117747 } 21640cb5e5dSvi117747 msg++; 21740cb5e5dSvi117747 } 21840cb5e5dSvi117747 /* 21940cb5e5dSvi117747 * We have reached the end without hitting the empty line. 22040cb5e5dSvi117747 */ 22140cb5e5dSvi117747 if (msg - sip_msg->sip_msg_buf >= sip_msg->sip_msg_len) 22240cb5e5dSvi117747 return (EINVAL); 22340cb5e5dSvi117747 } 22440cb5e5dSvi117747 22540cb5e5dSvi117747 if (sip_msg->sip_msg_headers_start == NULL) 22640cb5e5dSvi117747 return (EPROTO); 22740cb5e5dSvi117747 22840cb5e5dSvi117747 /* 22940cb5e5dSvi117747 * Move start line to be a separate line. 23040cb5e5dSvi117747 */ 23140cb5e5dSvi117747 sip_msg->sip_msg_start_line = sip_msg->sip_msg_headers_start; 23240cb5e5dSvi117747 sip_msg->sip_msg_headers_start = 23340cb5e5dSvi117747 sip_msg->sip_msg_headers_start->sip_hdr_next; 23440cb5e5dSvi117747 sip_msg->sip_msg_start_line->sip_hdr_prev = NULL; 23540cb5e5dSvi117747 sip_msg->sip_msg_start_line->sip_hdr_next = NULL; 23640cb5e5dSvi117747 23740cb5e5dSvi117747 if (sip_msg->sip_msg_headers_start == NULL) 23840cb5e5dSvi117747 return (EINVAL); 23940cb5e5dSvi117747 sip_msg->sip_msg_headers_start->sip_hdr_prev = NULL; 24040cb5e5dSvi117747 24140cb5e5dSvi117747 24240cb5e5dSvi117747 /* 24340cb5e5dSvi117747 * Deal with content. 24440cb5e5dSvi117747 */ 24540cb5e5dSvi117747 sip_msg->sip_msg_content = calloc(1, sizeof (sip_content_t)); 24640cb5e5dSvi117747 sip_msg->sip_msg_content->sip_content_start = msg; 24740cb5e5dSvi117747 sip_msg->sip_msg_content->sip_content_end = sip_msg->sip_msg_buf + 24840cb5e5dSvi117747 sip_msg->sip_msg_len; 24940cb5e5dSvi117747 sip_msg->sip_msg_content->sip_content_allocated = B_FALSE; 25040cb5e5dSvi117747 sip_msg->sip_msg_content_len = 25140cb5e5dSvi117747 sip_msg->sip_msg_content->sip_content_end - 25240cb5e5dSvi117747 sip_msg->sip_msg_content->sip_content_start; 25340cb5e5dSvi117747 return (0); 25440cb5e5dSvi117747 } 25540cb5e5dSvi117747 25640cb5e5dSvi117747 /* 25740cb5e5dSvi117747 * The send interface to the sip stack. Used by upper layers. 25840cb5e5dSvi117747 */ 25940cb5e5dSvi117747 int 26040cb5e5dSvi117747 sip_sendmsg(sip_conn_object_t obj, sip_msg_t sip_msg, sip_dialog_t dialog, 26140cb5e5dSvi117747 uint32_t flags) 26240cb5e5dSvi117747 { 26340cb5e5dSvi117747 sip_xaction_t *sip_trans = NULL; 26440cb5e5dSvi117747 int ret = 0; 26540cb5e5dSvi117747 sip_message_type_t *sip_msg_info; 26640cb5e5dSvi117747 _sip_msg_t *_sip_msg; 26740cb5e5dSvi117747 boolean_t stateful = flags & SIP_SEND_STATEFUL; 26840cb5e5dSvi117747 boolean_t dlg_on_fork = flags & SIP_DIALOG_ON_FORK; 26940cb5e5dSvi117747 27040cb5e5dSvi117747 sip_refhold_conn(obj); 27140cb5e5dSvi117747 27240cb5e5dSvi117747 _sip_msg = (_sip_msg_t *)sip_msg; 27340cb5e5dSvi117747 if ((ret = sip_adjust_msgbuf(_sip_msg)) != 0) { 27440cb5e5dSvi117747 sip_refrele_conn(obj); 27540cb5e5dSvi117747 return (ret); 27640cb5e5dSvi117747 } 27740cb5e5dSvi117747 27840cb5e5dSvi117747 assert(_sip_msg->sip_msg_req_res != NULL); 27940cb5e5dSvi117747 sip_msg_info = _sip_msg->sip_msg_req_res; 28040cb5e5dSvi117747 /* 28140cb5e5dSvi117747 * Send it statefully if: 28240cb5e5dSvi117747 * if stateful is set in 'flags' AND 28340cb5e5dSvi117747 * this is not an ACK request, if it is a request (should the upper 28440cb5e5dSvi117747 * layer set stateful in the latter case?, i.e is the check 28540cb5e5dSvi117747 * necessary here?) 28640cb5e5dSvi117747 */ 28740cb5e5dSvi117747 if (stateful && (!sip_msg_info->is_request || 28840cb5e5dSvi117747 sip_msg_info->sip_req_method != ACK)) { 28940cb5e5dSvi117747 sip_trans = (sip_xaction_t *)sip_xaction_get(obj, sip_msg, 29040cb5e5dSvi117747 B_TRUE, sip_msg_info->is_request ? SIP_CLIENT_TRANSACTION : 29140cb5e5dSvi117747 SIP_SERVER_TRANSACTION, &ret); 29240cb5e5dSvi117747 if (sip_trans == NULL) { 29340cb5e5dSvi117747 sip_refrele_conn(obj); 29440cb5e5dSvi117747 return (ret); 29540cb5e5dSvi117747 } 29640cb5e5dSvi117747 ret = sip_xaction_output(obj, sip_trans, _sip_msg); 29740cb5e5dSvi117747 SIP_XACTION_REFCNT_DECR(sip_trans); 29840cb5e5dSvi117747 if (ret != 0) { 29940cb5e5dSvi117747 sip_refrele_conn(obj); 30040cb5e5dSvi117747 return (ret); 30140cb5e5dSvi117747 } 30240cb5e5dSvi117747 } 30340cb5e5dSvi117747 /* 30440cb5e5dSvi117747 * If the appln wants us to create the dialog, create a partial 30540cb5e5dSvi117747 * dialog at this stage, when we get the response, we will 30640cb5e5dSvi117747 * complete it. 30740cb5e5dSvi117747 */ 30840cb5e5dSvi117747 if (sip_manage_dialog) { 30940cb5e5dSvi117747 if (sip_msg_info->is_request && dialog == NULL) { 31040cb5e5dSvi117747 dialog = (sip_dialog_t)sip_seed_dialog(obj, sip_msg, 31140cb5e5dSvi117747 dlg_on_fork, SIP_UAC_DIALOG); 31240cb5e5dSvi117747 } else if (dialog != NULL && (!sip_msg_info->is_request || 31340cb5e5dSvi117747 sip_msg_info->sip_req_method == NOTIFY)) { 31440cb5e5dSvi117747 (void) sip_update_dialog(dialog, _sip_msg); 315*943efbc3Sgm209912 } else if (dialog != NULL) { 316*943efbc3Sgm209912 /* 317*943efbc3Sgm209912 * Dialog is in CONFIRMED state. If logging is enabled 318*943efbc3Sgm209912 * track the SIP message sent within a dialog. 319*943efbc3Sgm209912 */ 320*943efbc3Sgm209912 (void) pthread_mutex_lock(&dialog->sip_dlg_mutex); 321*943efbc3Sgm209912 dialog->sip_dlg_msgcnt++; 322*943efbc3Sgm209912 sip_add_log(&dialog->sip_dlg_log[dialog->sip_dlg_state], 323*943efbc3Sgm209912 (sip_msg_t)sip_msg, dialog->sip_dlg_msgcnt, 324*943efbc3Sgm209912 SIP_DIALOG_LOG); 325*943efbc3Sgm209912 (void) pthread_mutex_unlock(&dialog->sip_dlg_mutex); 32640cb5e5dSvi117747 327*943efbc3Sgm209912 if (sip_msg_info->is_request && sip_msg_info-> 328*943efbc3Sgm209912 sip_req_method == INVITE) { 329*943efbc3Sgm209912 (void) sip_dialog_add_new_contact(dialog, 330*943efbc3Sgm209912 _sip_msg); 331*943efbc3Sgm209912 } 332*943efbc3Sgm209912 } 333*943efbc3Sgm209912 } 334*943efbc3Sgm209912 /* 335*943efbc3Sgm209912 * if measure sip traffic is enabled, capture the measurements 336*943efbc3Sgm209912 * Is this the right place to measure or should I put this after 337*943efbc3Sgm209912 * the call to sip_stack_send() 338*943efbc3Sgm209912 */ 339*943efbc3Sgm209912 if (sip_msg_info->is_request) { 340*943efbc3Sgm209912 SIP_UPDATE_COUNTERS(B_TRUE, sip_msg_info->sip_req_method, 0, 341*943efbc3Sgm209912 B_TRUE, _sip_msg->sip_msg_len); 342*943efbc3Sgm209912 } else { 343*943efbc3Sgm209912 SIP_UPDATE_COUNTERS(B_FALSE, 0, sip_msg_info->sip_resp_code, 344*943efbc3Sgm209912 B_TRUE, _sip_msg->sip_msg_len); 345*943efbc3Sgm209912 } 34640cb5e5dSvi117747 if ((ret = sip_stack_send(obj, _sip_msg->sip_msg_buf, 34740cb5e5dSvi117747 _sip_msg->sip_msg_len)) != 0) { 34840cb5e5dSvi117747 if (sip_trans != NULL) { 34940cb5e5dSvi117747 sip_xaction_terminate(sip_trans, _sip_msg, 35040cb5e5dSvi117747 sip_conn_transport(obj)); 35140cb5e5dSvi117747 } 35240cb5e5dSvi117747 sip_refrele_conn(obj); 35340cb5e5dSvi117747 return (ret); 35440cb5e5dSvi117747 } 35540cb5e5dSvi117747 sip_refrele_conn(obj); 35640cb5e5dSvi117747 return (ret); 35740cb5e5dSvi117747 } 35840cb5e5dSvi117747 35940cb5e5dSvi117747 /* 36040cb5e5dSvi117747 * Given a sent-by value check if it is in the registered list. If no values 36140cb5e5dSvi117747 * have been registered, the check passes. 36240cb5e5dSvi117747 */ 36340cb5e5dSvi117747 static boolean_t 36440cb5e5dSvi117747 sip_sent_by_registered(const sip_str_t *sb_val) 36540cb5e5dSvi117747 { 36640cb5e5dSvi117747 sent_by_list_t *sb; 36740cb5e5dSvi117747 int count = 0; 36840cb5e5dSvi117747 36940cb5e5dSvi117747 (void) pthread_mutex_lock(&sip_sent_by_lock); 37040cb5e5dSvi117747 if (sip_sent_by == NULL) { 37140cb5e5dSvi117747 (void) pthread_mutex_unlock(&sip_sent_by_lock); 37240cb5e5dSvi117747 return (B_TRUE); 37340cb5e5dSvi117747 } 37440cb5e5dSvi117747 sb = sip_sent_by; 37540cb5e5dSvi117747 for (count = 0; count < sip_sent_by_count; count++) { 37640cb5e5dSvi117747 if (strncasecmp(sb->sb_val, sb_val->sip_str_ptr, 37740cb5e5dSvi117747 sb_val->sip_str_len) == 0) { 37840cb5e5dSvi117747 (void) pthread_mutex_unlock(&sip_sent_by_lock); 37940cb5e5dSvi117747 return (B_TRUE); 38040cb5e5dSvi117747 } 38140cb5e5dSvi117747 sb = sb->sb_next; 38240cb5e5dSvi117747 } 38340cb5e5dSvi117747 (void) pthread_mutex_unlock(&sip_sent_by_lock); 38440cb5e5dSvi117747 return (B_FALSE); 38540cb5e5dSvi117747 } 38640cb5e5dSvi117747 38740cb5e5dSvi117747 /* 38840cb5e5dSvi117747 * Given a response, check if the sent-by in the VIA header is valid. 38940cb5e5dSvi117747 */ 39040cb5e5dSvi117747 boolean_t 39140cb5e5dSvi117747 sip_valid_sent_by(sip_msg_t sip_msg) 39240cb5e5dSvi117747 { 39340cb5e5dSvi117747 sip_header_t via; 39440cb5e5dSvi117747 sip_header_value_t value = NULL; 39540cb5e5dSvi117747 int error; 39640cb5e5dSvi117747 const sip_str_t *sent_by = NULL; 39740cb5e5dSvi117747 39840cb5e5dSvi117747 via = (sip_header_t)sip_get_header(sip_msg, SIP_VIA, NULL, &error); 39940cb5e5dSvi117747 if (via == NULL || error != 0) 40040cb5e5dSvi117747 return (B_TRUE); 40140cb5e5dSvi117747 value = (sip_header_value_t)sip_get_header_value(via, &error); 40240cb5e5dSvi117747 if (value == NULL || error != 0) 40340cb5e5dSvi117747 return (B_TRUE); 40440cb5e5dSvi117747 sent_by = sip_get_via_sent_by_host(value, &error); 40540cb5e5dSvi117747 if (sent_by == NULL || error != 0) 40640cb5e5dSvi117747 return (B_TRUE); 40740cb5e5dSvi117747 if (sip_sent_by_registered(sent_by)) 40840cb5e5dSvi117747 return (B_TRUE); 40940cb5e5dSvi117747 return (B_FALSE); 41040cb5e5dSvi117747 } 41140cb5e5dSvi117747 41240cb5e5dSvi117747 41340cb5e5dSvi117747 /* 41440cb5e5dSvi117747 * The receive interface to the transport layer. 41540cb5e5dSvi117747 */ 41640cb5e5dSvi117747 void 41740cb5e5dSvi117747 sip_process_new_packet(sip_conn_object_t conn_object, void *msgstr, 41840cb5e5dSvi117747 size_t msglen) 41940cb5e5dSvi117747 { 42040cb5e5dSvi117747 _sip_msg_t *sip_msg; 42140cb5e5dSvi117747 sip_message_type_t *sip_msg_info; 42240cb5e5dSvi117747 sip_xaction_t *sip_trans; 42340cb5e5dSvi117747 sip_dialog_t dialog = NULL; 42440cb5e5dSvi117747 boolean_t dialog_created = B_FALSE; 42540cb5e5dSvi117747 int transport; 42640cb5e5dSvi117747 char *msgbuf = NULL; 42740cb5e5dSvi117747 42840cb5e5dSvi117747 sip_refhold_conn(conn_object); 42940cb5e5dSvi117747 transport = sip_conn_transport(conn_object); 43040cb5e5dSvi117747 if (transport == IPPROTO_TCP) { 43140cb5e5dSvi117747 next_msg: 43240cb5e5dSvi117747 msgstr = (char *)sip_get_tcp_msg(conn_object, (char *)msgstr, 43340cb5e5dSvi117747 &msglen); 43440cb5e5dSvi117747 if (msgstr == NULL) { 43540cb5e5dSvi117747 sip_refrele_conn(conn_object); 43640cb5e5dSvi117747 return; 43740cb5e5dSvi117747 } 43840cb5e5dSvi117747 } else { 43940cb5e5dSvi117747 msgbuf = (char *)malloc(msglen + 1); 44040cb5e5dSvi117747 if (msgbuf == NULL) { 44140cb5e5dSvi117747 sip_refrele_conn(conn_object); 44240cb5e5dSvi117747 return; 44340cb5e5dSvi117747 } 44440cb5e5dSvi117747 (void) strncpy(msgbuf, msgstr, msglen); 44540cb5e5dSvi117747 msgbuf[msglen] = '\0'; 44640cb5e5dSvi117747 msgstr = msgbuf; 44740cb5e5dSvi117747 } 44840cb5e5dSvi117747 sip_msg = (_sip_msg_t *)sip_new_msg(); 44940cb5e5dSvi117747 if (sip_msg == NULL) { 45040cb5e5dSvi117747 if (msgbuf != NULL) 45140cb5e5dSvi117747 free(msgbuf); 45240cb5e5dSvi117747 sip_refrele_conn(conn_object); 45340cb5e5dSvi117747 return; 45440cb5e5dSvi117747 } 45540cb5e5dSvi117747 sip_msg->sip_msg_buf = (char *)msgstr; 45640cb5e5dSvi117747 sip_msg->sip_msg_len = msglen; 45740cb5e5dSvi117747 (void) pthread_mutex_lock(&sip_msg->sip_msg_mutex); 45840cb5e5dSvi117747 if (sip_setup_header_pointers(sip_msg) != 0) { 45940cb5e5dSvi117747 (void) pthread_mutex_unlock(&sip_msg->sip_msg_mutex); 46040cb5e5dSvi117747 sip_refrele_conn(conn_object); 46140cb5e5dSvi117747 sip_free_msg((sip_msg_t)sip_msg); 46240cb5e5dSvi117747 return; 46340cb5e5dSvi117747 } 46440cb5e5dSvi117747 if (sip_parse_first_line(sip_msg->sip_msg_start_line, 46540cb5e5dSvi117747 &sip_msg->sip_msg_req_res)) { 46640cb5e5dSvi117747 (void) pthread_mutex_unlock(&sip_msg->sip_msg_mutex); 46740cb5e5dSvi117747 sip_refrele_conn(conn_object); 46840cb5e5dSvi117747 sip_free_msg((sip_msg_t)sip_msg); 46940cb5e5dSvi117747 return; 47040cb5e5dSvi117747 } 47140cb5e5dSvi117747 sip_msg_info = sip_msg->sip_msg_req_res; 47240cb5e5dSvi117747 (void) pthread_mutex_unlock(&sip_msg->sip_msg_mutex); 47340cb5e5dSvi117747 47440cb5e5dSvi117747 if (sip_check_common_headers(conn_object, sip_msg)) { 47540cb5e5dSvi117747 sip_refrele_conn(conn_object); 47640cb5e5dSvi117747 sip_free_msg((sip_msg_t)sip_msg); 47740cb5e5dSvi117747 return; 47840cb5e5dSvi117747 } 47940cb5e5dSvi117747 48040cb5e5dSvi117747 /* 48140cb5e5dSvi117747 * Silently discard the response if the top VIA has a sent-by value AND 48240cb5e5dSvi117747 * the UA has registered sent-by values AND the one in the VIA is 48340cb5e5dSvi117747 * not part of the registerd sent-by values. 48440cb5e5dSvi117747 */ 48540cb5e5dSvi117747 if (!sip_msg_info->is_request && !sip_valid_sent_by(sip_msg)) { 48640cb5e5dSvi117747 sip_refrele_conn(conn_object); 48740cb5e5dSvi117747 sip_free_msg((sip_msg_t)sip_msg); 48840cb5e5dSvi117747 return; 48940cb5e5dSvi117747 49040cb5e5dSvi117747 } 49140cb5e5dSvi117747 sip_trans = (sip_xaction_t *)sip_xaction_get(conn_object, 49240cb5e5dSvi117747 (sip_msg_t)sip_msg, 49340cb5e5dSvi117747 B_FALSE, sip_msg_info->is_request ? SIP_SERVER_TRANSACTION : 49440cb5e5dSvi117747 SIP_CLIENT_TRANSACTION, NULL); 49540cb5e5dSvi117747 if (sip_trans != NULL) { 49640cb5e5dSvi117747 if (sip_xaction_input(conn_object, sip_trans, &sip_msg) != 0) { 49740cb5e5dSvi117747 SIP_XACTION_REFCNT_DECR(sip_trans); 49840cb5e5dSvi117747 sip_refrele_conn(conn_object); 49940cb5e5dSvi117747 sip_free_msg((sip_msg_t)sip_msg); 50040cb5e5dSvi117747 return; 50140cb5e5dSvi117747 } 50240cb5e5dSvi117747 SIP_XACTION_REFCNT_DECR(sip_trans); 50340cb5e5dSvi117747 50440cb5e5dSvi117747 /* 50540cb5e5dSvi117747 * msg was retransmission - handled by the transaction 50640cb5e5dSvi117747 */ 50740cb5e5dSvi117747 if (sip_msg == NULL) 50840cb5e5dSvi117747 goto check_next; 50940cb5e5dSvi117747 } else { 51040cb5e5dSvi117747 /* 51140cb5e5dSvi117747 * If we are getting an INVITE request, let us send a 51240cb5e5dSvi117747 * 100 TRYING response here, as in 17.2.1: 51340cb5e5dSvi117747 * "The server transaction MUST generate a 100 (Trying) 51440cb5e5dSvi117747 * response unless it knows that the TU will generate a 51540cb5e5dSvi117747 * provisional or final response within 200 ms". 51640cb5e5dSvi117747 */ 51740cb5e5dSvi117747 if (sip_msg_info->is_request && 51840cb5e5dSvi117747 sip_msg_info->sip_req_method == INVITE) { 51940cb5e5dSvi117747 sip_send_resp(conn_object, sip_msg, SIP_TRYING); 52040cb5e5dSvi117747 } 52140cb5e5dSvi117747 } 52240cb5e5dSvi117747 if (sip_manage_dialog) { 52340cb5e5dSvi117747 dialog = sip_dialog_find(sip_msg); 52440cb5e5dSvi117747 if (dialog == NULL) { 52540cb5e5dSvi117747 if (sip_msg_info->is_request) { 52640cb5e5dSvi117747 /* 52740cb5e5dSvi117747 * sip_seed_dialog will check for the 52840cb5e5dSvi117747 * method in the request 52940cb5e5dSvi117747 */ 53040cb5e5dSvi117747 dialog = (sip_dialog_t)sip_seed_dialog( 53140cb5e5dSvi117747 conn_object, sip_msg, 53240cb5e5dSvi117747 B_FALSE, SIP_UAS_DIALOG); 53340cb5e5dSvi117747 dialog_created = B_TRUE; 53440cb5e5dSvi117747 } 53540cb5e5dSvi117747 } else if (sip_incomplete_dialog(dialog)) { 53640cb5e5dSvi117747 if (!sip_msg_info->is_request || 53740cb5e5dSvi117747 sip_msg_info->sip_req_method == NOTIFY) { 53840cb5e5dSvi117747 dialog = sip_update_dialog(dialog, sip_msg); 53940cb5e5dSvi117747 } 54040cb5e5dSvi117747 } else if (sip_dialog_process(sip_msg, &dialog) != 0) { 54140cb5e5dSvi117747 if (dialog != NULL) 54240cb5e5dSvi117747 sip_release_dialog(dialog); 54340cb5e5dSvi117747 /* 54440cb5e5dSvi117747 * cseq number in error, send a 54540cb5e5dSvi117747 * SIP_SERVER_INTERNAL_ERROR response. 54640cb5e5dSvi117747 */ 54740cb5e5dSvi117747 if (sip_msg_info->is_request) { 54840cb5e5dSvi117747 sip_send_resp(conn_object, sip_msg, 54940cb5e5dSvi117747 SIP_SERVER_INTERNAL_ERROR); 55040cb5e5dSvi117747 } 55140cb5e5dSvi117747 sip_refrele_conn(conn_object); 55240cb5e5dSvi117747 sip_free_msg((sip_msg_t)sip_msg); 55340cb5e5dSvi117747 return; 55440cb5e5dSvi117747 } 55540cb5e5dSvi117747 } 556*943efbc3Sgm209912 if (sip_msg_info->is_request) { 557*943efbc3Sgm209912 SIP_UPDATE_COUNTERS(B_TRUE, sip_msg_info->sip_req_method, 0, 558*943efbc3Sgm209912 B_FALSE, sip_msg->sip_msg_len); 559*943efbc3Sgm209912 } else { 560*943efbc3Sgm209912 SIP_UPDATE_COUNTERS(B_FALSE, 0, sip_msg_info->sip_resp_code, 561*943efbc3Sgm209912 B_FALSE, sip_msg->sip_msg_len); 562*943efbc3Sgm209912 } 56340cb5e5dSvi117747 sip_ulp_recv(conn_object, (sip_msg_t)sip_msg, dialog); 56440cb5e5dSvi117747 sip_free_msg((sip_msg_t)sip_msg); 56540cb5e5dSvi117747 if (dialog != NULL && !dialog_created) 56640cb5e5dSvi117747 sip_release_dialog(dialog); 56740cb5e5dSvi117747 check_next: 56840cb5e5dSvi117747 /* 56940cb5e5dSvi117747 * Check if there are more complete messages in the TCP fragment list 57040cb5e5dSvi117747 * to be consumed 57140cb5e5dSvi117747 */ 57240cb5e5dSvi117747 if (transport == IPPROTO_TCP) { 57340cb5e5dSvi117747 msgstr = NULL; 57440cb5e5dSvi117747 msglen = 0; 57540cb5e5dSvi117747 goto next_msg; 57640cb5e5dSvi117747 } 57740cb5e5dSvi117747 sip_refrele_conn(conn_object); 57840cb5e5dSvi117747 } 57940cb5e5dSvi117747 58040cb5e5dSvi117747 /* 58140cb5e5dSvi117747 * Initialize the stack. The connection manager functions, upper layer 58240cb5e5dSvi117747 * receive functions are mandatory. 58340cb5e5dSvi117747 */ 58440cb5e5dSvi117747 int 58540cb5e5dSvi117747 sip_stack_init(sip_stack_init_t *stack_val) 58640cb5e5dSvi117747 { 58740cb5e5dSvi117747 #ifdef __linux__ 58840cb5e5dSvi117747 struct timespec tspec; 58940cb5e5dSvi117747 #endif 59040cb5e5dSvi117747 59140cb5e5dSvi117747 /* 59240cb5e5dSvi117747 * If the stack has already been configured, return error 59340cb5e5dSvi117747 */ 59440cb5e5dSvi117747 if (sip_stack_send != NULL || 59540cb5e5dSvi117747 stack_val->sip_version != SIP_STACK_VERSION) { 59640cb5e5dSvi117747 return (EINVAL); 59740cb5e5dSvi117747 } 59840cb5e5dSvi117747 if (stack_val->sip_io_pointers == NULL || 59940cb5e5dSvi117747 stack_val->sip_ulp_pointers == NULL) { 60040cb5e5dSvi117747 return (EINVAL); 60140cb5e5dSvi117747 } 60240cb5e5dSvi117747 sip_ulp_recv = stack_val->sip_ulp_pointers->sip_ulp_recv; 60340cb5e5dSvi117747 sip_manage_dialog = stack_val->sip_stack_flags & SIP_STACK_DIALOGS; 60440cb5e5dSvi117747 60540cb5e5dSvi117747 sip_stack_send = stack_val->sip_io_pointers->sip_conn_send; 60640cb5e5dSvi117747 sip_refhold_conn = stack_val->sip_io_pointers->sip_hold_conn_object; 60740cb5e5dSvi117747 sip_refrele_conn = stack_val->sip_io_pointers->sip_rel_conn_object; 60840cb5e5dSvi117747 sip_is_conn_stream = stack_val->sip_io_pointers->sip_conn_is_stream; 60940cb5e5dSvi117747 sip_is_conn_reliable = stack_val->sip_io_pointers->sip_conn_is_reliable; 61040cb5e5dSvi117747 sip_conn_rem_addr = stack_val->sip_io_pointers->sip_conn_remote_address; 61140cb5e5dSvi117747 sip_conn_local_addr = 61240cb5e5dSvi117747 stack_val->sip_io_pointers->sip_conn_local_address; 61340cb5e5dSvi117747 sip_conn_transport = stack_val->sip_io_pointers->sip_conn_transport; 61440cb5e5dSvi117747 sip_header_function_table_external = stack_val->sip_function_table; 61540cb5e5dSvi117747 61640cb5e5dSvi117747 if (sip_ulp_recv == NULL || sip_stack_send == NULL || 61740cb5e5dSvi117747 sip_refhold_conn == NULL || sip_refrele_conn == NULL || 61840cb5e5dSvi117747 sip_is_conn_stream == NULL || sip_is_conn_reliable == NULL || 61940cb5e5dSvi117747 sip_conn_rem_addr == NULL || sip_conn_local_addr == NULL || 62040cb5e5dSvi117747 sip_conn_transport == NULL) { 62140cb5e5dSvi117747 err_ret: 62240cb5e5dSvi117747 sip_ulp_recv = NULL; 62340cb5e5dSvi117747 sip_stack_send = NULL; 62440cb5e5dSvi117747 sip_refhold_conn = NULL; 62540cb5e5dSvi117747 sip_refrele_conn = NULL; 62640cb5e5dSvi117747 sip_is_conn_stream = NULL; 62740cb5e5dSvi117747 sip_is_conn_reliable = NULL; 62840cb5e5dSvi117747 sip_conn_rem_addr = NULL; 62940cb5e5dSvi117747 sip_conn_local_addr = NULL; 63040cb5e5dSvi117747 sip_conn_transport = NULL; 63140cb5e5dSvi117747 sip_header_function_table_external = NULL; 63240cb5e5dSvi117747 sip_stack_timeout = NULL; 63340cb5e5dSvi117747 sip_stack_untimeout = NULL; 63440cb5e5dSvi117747 return (EINVAL); 63540cb5e5dSvi117747 } 63640cb5e5dSvi117747 63740cb5e5dSvi117747 sip_conn_timer1 = stack_val->sip_io_pointers->sip_conn_timer1; 63840cb5e5dSvi117747 sip_conn_timer2 = stack_val->sip_io_pointers->sip_conn_timer2; 63940cb5e5dSvi117747 sip_conn_timer4 = stack_val->sip_io_pointers->sip_conn_timer4; 64040cb5e5dSvi117747 sip_conn_timerd = stack_val->sip_io_pointers->sip_conn_timerd; 64140cb5e5dSvi117747 64240cb5e5dSvi117747 /* 64340cb5e5dSvi117747 * Use Appln timeout routines, if provided 64440cb5e5dSvi117747 */ 64540cb5e5dSvi117747 if (stack_val->sip_ulp_pointers->sip_ulp_timeout != NULL) { 64640cb5e5dSvi117747 if (stack_val->sip_ulp_pointers->sip_ulp_untimeout == NULL) 64740cb5e5dSvi117747 goto err_ret; 64840cb5e5dSvi117747 sip_stack_timeout = 64940cb5e5dSvi117747 stack_val->sip_ulp_pointers->sip_ulp_timeout; 65040cb5e5dSvi117747 sip_stack_untimeout = 65140cb5e5dSvi117747 stack_val->sip_ulp_pointers->sip_ulp_untimeout; 65240cb5e5dSvi117747 } else { 65340cb5e5dSvi117747 if (stack_val->sip_ulp_pointers->sip_ulp_untimeout != NULL) 65440cb5e5dSvi117747 goto err_ret; 65540cb5e5dSvi117747 sip_timeout_init(); 65640cb5e5dSvi117747 sip_stack_timeout = sip_timeout; 65740cb5e5dSvi117747 sip_stack_untimeout = sip_untimeout; 65840cb5e5dSvi117747 } 65940cb5e5dSvi117747 66040cb5e5dSvi117747 /* 66140cb5e5dSvi117747 * Manage Dialogs? 66240cb5e5dSvi117747 */ 66340cb5e5dSvi117747 if (sip_manage_dialog) { 66440cb5e5dSvi117747 sip_dialog_init(stack_val->sip_ulp_pointers->sip_ulp_dlg_del, 66540cb5e5dSvi117747 stack_val->sip_ulp_pointers->sip_ulp_dlg_state_cb); 66640cb5e5dSvi117747 } 66740cb5e5dSvi117747 sip_xaction_init(stack_val->sip_ulp_pointers->sip_ulp_trans_error, 66840cb5e5dSvi117747 stack_val->sip_ulp_pointers->sip_ulp_trans_state_cb); 66940cb5e5dSvi117747 670*943efbc3Sgm209912 /* 671*943efbc3Sgm209912 * Initialize SIP traffic counter mutex 672*943efbc3Sgm209912 */ 673*943efbc3Sgm209912 (void) pthread_mutex_init(&sip_counters.sip_counter_mutex, NULL); 674*943efbc3Sgm209912 675*943efbc3Sgm209912 /* 676*943efbc3Sgm209912 * Initialize SIP logfile structures mutex 677*943efbc3Sgm209912 */ 678*943efbc3Sgm209912 (void) pthread_mutex_init(&trans_log.sip_logfile_mutex, NULL); 679*943efbc3Sgm209912 (void) pthread_mutex_init(&dialog_log.sip_logfile_mutex, NULL); 680*943efbc3Sgm209912 68140cb5e5dSvi117747 #ifdef __linux__ 68240cb5e5dSvi117747 if (clock_gettime(CLOCK_REALTIME, &tspec) != 0) 68340cb5e5dSvi117747 goto err_ret; 68440cb5e5dSvi117747 sip_hash_salt = tspec.tv_nsec; 68540cb5e5dSvi117747 #else 68640cb5e5dSvi117747 sip_hash_salt = gethrtime(); 68740cb5e5dSvi117747 #endif 68840cb5e5dSvi117747 (void) pthread_mutex_init(&sip_sent_by_lock, NULL); 68940cb5e5dSvi117747 return (0); 69040cb5e5dSvi117747 } 691