xref: /titanic_51/usr/src/lib/libsip/common/sip_itf.c (revision 943efbc33954e332318b6365bf27037c05bff72c)
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