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
sip_send_resp(sip_conn_object_t conn_obj,_sip_msg_t * sip_msg,int resp)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
sip_check_common_headers(sip_conn_object_t conn_obj,_sip_msg_t * sip_msg)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
sip_setup_header_pointers(_sip_msg_t * sip_msg)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
sip_sendmsg(sip_conn_object_t obj,sip_msg_t sip_msg,sip_dialog_t dialog,uint32_t flags)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
sip_sent_by_registered(const sip_str_t * sb_val)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
sip_valid_sent_by(sip_msg_t sip_msg)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
sip_process_new_packet(sip_conn_object_t conn_object,void * msgstr,size_t msglen)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
sip_stack_init(sip_stack_init_t * stack_val)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