1/*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22/*
23 * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
24 * Use is subject to license terms.
25 */
26
27#pragma ident	"%Z%%M%	%I%	%E% SMI"
28
29#include <string.h>
30#include <strings.h>
31#include <stdlib.h>
32#include <assert.h>
33#include <ctype.h>
34#include <errno.h>
35#include <pthread.h>
36#include <sip.h>
37
38#include "sip_msg.h"
39#include "sip_miscdefs.h"
40#include "sip_xaction.h"
41#include "sip_dialog.h"
42#include "sip_parse_generic.h"
43
44void		(*sip_ulp_recv)(const sip_conn_object_t, sip_msg_t,
45		    const sip_dialog_t) = NULL;
46uint_t		(*sip_stack_timeout)(void *, void (*func)(void *),
47		    struct timeval *) = NULL;
48boolean_t	(*sip_stack_untimeout)(uint_t) = NULL;
49int		(*sip_stack_send)(sip_conn_object_t xonn_object, char *, int) =
50		    NULL;
51void		(*sip_refhold_conn)(sip_conn_object_t) = NULL;
52void		(*sip_refrele_conn)(sip_conn_object_t) = NULL;
53boolean_t	(*sip_is_conn_stream)(sip_conn_object_t) = NULL;
54boolean_t	(*sip_is_conn_reliable)(sip_conn_object_t) = NULL;
55int 		(*sip_conn_rem_addr)(sip_conn_object_t, struct sockaddr *,
56		    socklen_t *) = NULL;
57int		(*sip_conn_local_addr)(sip_conn_object_t, struct sockaddr *,
58		    socklen_t *) = NULL;
59int		(*sip_conn_transport)(sip_conn_object_t) = NULL;
60int		(*sip_conn_timer1)(sip_conn_object_t) = NULL;
61int		(*sip_conn_timer2)(sip_conn_object_t) = NULL;
62int		(*sip_conn_timer4)(sip_conn_object_t) = NULL;
63int		(*sip_conn_timerd)(sip_conn_object_t) = NULL;
64
65boolean_t	sip_manage_dialog = B_FALSE;
66
67uint64_t	sip_hash_salt = 0;
68
69/*
70 * Defaults, overridden by configured values, if any
71 */
72int		sip_timer_T1 = SIP_TIMER_T1;
73int		sip_timer_T2 = SIP_TIMER_T2;
74int		sip_timer_T4 = SIP_TIMER_T4;
75int		sip_timer_TD = 32 * SIP_SECONDS;
76
77/*
78 * list of sent-by values registered by the UA
79 */
80sent_by_list_t	*sip_sent_by = NULL;
81int		sip_sent_by_count = 0;
82pthread_mutex_t	sip_sent_by_lock;
83
84/*
85 * Create and send an error response
86 */
87static void
88sip_send_resp(sip_conn_object_t conn_obj, _sip_msg_t *sip_msg, int resp)
89{
90	_sip_msg_t		*sip_msg_resp;
91
92	sip_msg_resp = (_sip_msg_t *)sip_create_response((sip_msg_t)sip_msg,
93	    resp, sip_get_resp_desc(resp), NULL, NULL);
94	if (sip_msg_resp == NULL) {
95		/*
96		 * Message was too bad to even create a
97		 * response. Just drop the messge.
98		 */
99		return;
100	}
101	/*
102	 * We directly send it to the transport here.
103	 */
104	if (sip_adjust_msgbuf(sip_msg_resp) != 0) {
105		sip_free_msg((sip_msg_t)sip_msg_resp);
106		return;
107	}
108
109	SIP_UPDATE_COUNTERS(B_FALSE, 0, resp, B_TRUE, sip_msg_resp->
110	    sip_msg_len);
111	(void) sip_stack_send(conn_obj, sip_msg_resp->sip_msg_buf,
112	    sip_msg_resp->sip_msg_len);
113	sip_free_msg((sip_msg_t)sip_msg_resp);
114}
115
116/*
117 * Validate some of the common headers
118 */
119boolean_t
120sip_check_common_headers(sip_conn_object_t conn_obj, _sip_msg_t *sip_msg)
121{
122	int	err;
123
124	if (sip_get_to_uri_str((sip_msg_t)sip_msg, &err) == NULL)
125		goto error;
126	if (sip_get_from_uri_str((sip_msg_t)sip_msg, &err) == NULL)
127		goto error;
128	if (sip_get_callseq_num((sip_msg_t)sip_msg, &err) < 0)
129		goto error;
130	if (sip_get_callid((sip_msg_t)sip_msg, &err) == NULL)
131		goto error;
132	return (B_FALSE);
133error:
134	sip_send_resp(conn_obj, sip_msg, SIP_BAD_REQUEST);
135	return (B_TRUE);
136}
137
138/*
139 * setup pointers to where the headers are.
140 */
141static int
142sip_setup_header_pointers(_sip_msg_t *sip_msg)
143{
144	char		*msg;
145	_sip_header_t	*sip_msg_header;
146	char		*end;
147
148	msg = sip_msg->sip_msg_buf;
149	end = sip_msg->sip_msg_buf + sip_msg->sip_msg_len;
150	/*
151	 * Skip while space.
152	 */
153	while (isspace(*msg)) {
154		if (msg < end)
155			msg++;
156		else
157			return (EINVAL);
158	}
159
160	/*
161	 * We consider Request and Response line as a header
162	 */
163	for (;;) {
164		/*
165		 * Skip CRLF
166		 */
167		if (strncmp(SIP_CRLF, msg, strlen(SIP_CRLF)) == 0) {
168			if (sip_msg->sip_msg_headers_end != NULL) {
169				SKIP_CRLF(msg);
170				sip_msg->sip_msg_headers_end->sip_hdr_end = msg;
171			}
172			/*
173			 * Start of a header.
174			 * Check for empty line.
175			 */
176			if (strncmp(SIP_CRLF, msg, strlen(SIP_CRLF)) == 0) {
177				/*
178				 * empty line, start of content.
179				 */
180				SKIP_CRLF(msg);
181				sip_msg->sip_msg_headers_end->sip_hdr_end = msg;
182				break;
183			}
184			/*
185			 * store start of header.
186			 */
187			sip_msg_header = calloc(1, sizeof (_sip_header_t));
188			if (sip_msg_header == NULL)
189				return (EINVAL);
190			sip_msg_header->sip_hdr_start = msg;
191			sip_msg_header->sip_hdr_current = msg;
192			sip_msg_header->sip_hdr_allocated = B_FALSE;
193			sip_msg_header->sip_hdr_prev =
194			    sip_msg->sip_msg_headers_end;
195			sip_msg_header->sip_hdr_next = NULL;
196			sip_msg_header->sip_hdr_sipmsg = sip_msg;
197			sip_msg->sip_msg_headers_end->sip_hdr_next =
198			    sip_msg_header;
199			sip_msg->sip_msg_headers_end = sip_msg_header;
200		} else {
201			if (sip_msg->sip_msg_headers_start == NULL) {
202				/*
203				 * Allocate first header structure.
204				 */
205				sip_msg_header = calloc(1,
206				    sizeof (_sip_header_t));
207				if (sip_msg_header == NULL)
208					return (EINVAL);
209				sip_msg_header->sip_hdr_allocated = B_FALSE;
210				sip_msg_header->sip_hdr_start = msg;
211				sip_msg_header->sip_hdr_current = msg;
212				sip_msg_header->sip_hdr_sipmsg = sip_msg;
213				sip_msg->sip_msg_headers_start = sip_msg_header;
214				sip_msg->sip_msg_headers_end = sip_msg_header;
215			}
216			msg++;
217		}
218		/*
219		 * We have reached the end without hitting the empty line.
220		 */
221		if (msg - sip_msg->sip_msg_buf >= sip_msg->sip_msg_len)
222			return (EINVAL);
223	}
224
225	if (sip_msg->sip_msg_headers_start == NULL)
226		return (EPROTO);
227
228	/*
229	 * Move start line to be a separate line.
230	 */
231	sip_msg->sip_msg_start_line = sip_msg->sip_msg_headers_start;
232	sip_msg->sip_msg_headers_start =
233	    sip_msg->sip_msg_headers_start->sip_hdr_next;
234	sip_msg->sip_msg_start_line->sip_hdr_prev = NULL;
235	sip_msg->sip_msg_start_line->sip_hdr_next = NULL;
236
237	if (sip_msg->sip_msg_headers_start == NULL)
238		return (EINVAL);
239	sip_msg->sip_msg_headers_start->sip_hdr_prev = NULL;
240
241
242	/*
243	 * Deal with content.
244	 */
245	sip_msg->sip_msg_content = calloc(1, sizeof (sip_content_t));
246	sip_msg->sip_msg_content->sip_content_start = msg;
247	sip_msg->sip_msg_content->sip_content_end = sip_msg->sip_msg_buf +
248	    sip_msg->sip_msg_len;
249	sip_msg->sip_msg_content->sip_content_allocated = B_FALSE;
250	sip_msg->sip_msg_content_len =
251	    sip_msg->sip_msg_content->sip_content_end -
252	    sip_msg->sip_msg_content->sip_content_start;
253	return (0);
254}
255
256/*
257 * The send interface to the sip stack. Used by upper layers.
258 */
259int
260sip_sendmsg(sip_conn_object_t obj, sip_msg_t sip_msg, sip_dialog_t dialog,
261    uint32_t flags)
262{
263	sip_xaction_t		*sip_trans = NULL;
264	int			ret = 0;
265	sip_message_type_t	*sip_msg_info;
266	_sip_msg_t 		*_sip_msg;
267	boolean_t		stateful = flags & SIP_SEND_STATEFUL;
268	boolean_t		dlg_on_fork = flags & SIP_DIALOG_ON_FORK;
269
270	sip_refhold_conn(obj);
271
272	_sip_msg = (_sip_msg_t *)sip_msg;
273	if ((ret = sip_adjust_msgbuf(_sip_msg)) != 0) {
274		sip_refrele_conn(obj);
275		return (ret);
276	}
277
278	assert(_sip_msg->sip_msg_req_res != NULL);
279	sip_msg_info = _sip_msg->sip_msg_req_res;
280	/*
281	 * Send it statefully if:
282	 * if stateful is set in 'flags' AND
283	 * this is not an ACK request, if it is a request (should the upper
284	 * layer set stateful in the latter case?, i.e is the check
285	 * necessary here?)
286	 */
287	if (stateful && (!sip_msg_info->is_request ||
288	    sip_msg_info->sip_req_method != ACK)) {
289		sip_trans = (sip_xaction_t *)sip_xaction_get(obj, sip_msg,
290		    B_TRUE, sip_msg_info->is_request ? SIP_CLIENT_TRANSACTION :
291		    SIP_SERVER_TRANSACTION, &ret);
292		if (sip_trans == NULL) {
293			sip_refrele_conn(obj);
294			return (ret);
295		}
296		ret = sip_xaction_output(obj, sip_trans, _sip_msg);
297		SIP_XACTION_REFCNT_DECR(sip_trans);
298		if (ret != 0) {
299			sip_refrele_conn(obj);
300			return (ret);
301		}
302	}
303	/*
304	 * If the appln wants us to create the dialog, create a partial
305	 * dialog at this stage, when we get the response, we will
306	 * complete it.
307	 */
308	if (sip_manage_dialog) {
309		if (sip_msg_info->is_request && dialog == NULL) {
310			dialog = (sip_dialog_t)sip_seed_dialog(obj, sip_msg,
311			    dlg_on_fork, SIP_UAC_DIALOG);
312		} else if (dialog != NULL && (!sip_msg_info->is_request ||
313		    sip_msg_info->sip_req_method == NOTIFY)) {
314			(void) sip_update_dialog(dialog, _sip_msg);
315		} else if (dialog != NULL) {
316			/*
317			 * Dialog is in CONFIRMED state. If logging is enabled
318			 * track the SIP message sent within a dialog.
319			 */
320			(void) pthread_mutex_lock(&dialog->sip_dlg_mutex);
321			dialog->sip_dlg_msgcnt++;
322			sip_add_log(&dialog->sip_dlg_log[dialog->sip_dlg_state],
323			    (sip_msg_t)sip_msg, dialog->sip_dlg_msgcnt,
324			    SIP_DIALOG_LOG);
325			(void) pthread_mutex_unlock(&dialog->sip_dlg_mutex);
326
327			if (sip_msg_info->is_request && sip_msg_info->
328			    sip_req_method == INVITE) {
329				(void) sip_dialog_add_new_contact(dialog,
330				    _sip_msg);
331			}
332		}
333	}
334	/*
335	 * if measure sip traffic is enabled, capture the measurements
336	 * Is this the right place to measure or should I put this after
337	 * the call to sip_stack_send()
338	 */
339	if (sip_msg_info->is_request) {
340		SIP_UPDATE_COUNTERS(B_TRUE, sip_msg_info->sip_req_method, 0,
341		    B_TRUE, _sip_msg->sip_msg_len);
342	} else {
343		SIP_UPDATE_COUNTERS(B_FALSE, 0, sip_msg_info->sip_resp_code,
344		    B_TRUE, _sip_msg->sip_msg_len);
345	}
346	if ((ret = sip_stack_send(obj, _sip_msg->sip_msg_buf,
347	    _sip_msg->sip_msg_len)) != 0) {
348		if (sip_trans != NULL) {
349			sip_xaction_terminate(sip_trans, _sip_msg,
350			    sip_conn_transport(obj));
351		}
352		sip_refrele_conn(obj);
353		return (ret);
354	}
355	sip_refrele_conn(obj);
356	return (ret);
357}
358
359/*
360 * Given a sent-by value check if it is in the registered list. If no values
361 * have been registered, the check passes.
362 */
363static boolean_t
364sip_sent_by_registered(const sip_str_t *sb_val)
365{
366	sent_by_list_t	*sb;
367	int		count = 0;
368
369	(void) pthread_mutex_lock(&sip_sent_by_lock);
370	if (sip_sent_by == NULL) {
371		(void) pthread_mutex_unlock(&sip_sent_by_lock);
372		return (B_TRUE);
373	}
374	sb = sip_sent_by;
375	for (count = 0; count < sip_sent_by_count; count++) {
376		if (strncasecmp(sb->sb_val, sb_val->sip_str_ptr,
377		    sb_val->sip_str_len) == 0) {
378			(void) pthread_mutex_unlock(&sip_sent_by_lock);
379			return (B_TRUE);
380		}
381		sb = sb->sb_next;
382	}
383	(void) pthread_mutex_unlock(&sip_sent_by_lock);
384	return (B_FALSE);
385}
386
387/*
388 * Given a response, check if the sent-by in the VIA header is valid.
389 */
390boolean_t
391sip_valid_sent_by(sip_msg_t sip_msg)
392{
393	sip_header_t		via;
394	sip_header_value_t	value = NULL;
395	int			error;
396	const sip_str_t		*sent_by = NULL;
397
398	via = (sip_header_t)sip_get_header(sip_msg, SIP_VIA,  NULL, &error);
399	if (via == NULL || error != 0)
400		return (B_TRUE);
401	value = (sip_header_value_t)sip_get_header_value(via, &error);
402	if (value == NULL || error != 0)
403		return (B_TRUE);
404	sent_by = sip_get_via_sent_by_host(value, &error);
405	if (sent_by == NULL || error != 0)
406		return (B_TRUE);
407	if (sip_sent_by_registered(sent_by))
408		return (B_TRUE);
409	return (B_FALSE);
410}
411
412
413/*
414 * The receive interface to the transport layer.
415 */
416void
417sip_process_new_packet(sip_conn_object_t conn_object, void *msgstr,
418    size_t msglen)
419{
420	_sip_msg_t		*sip_msg;
421	sip_message_type_t	*sip_msg_info;
422	sip_xaction_t		*sip_trans;
423	sip_dialog_t		dialog = NULL;
424	boolean_t		dialog_created = B_FALSE;
425	int			transport;
426	char			*msgbuf = NULL;
427
428	sip_refhold_conn(conn_object);
429	transport = sip_conn_transport(conn_object);
430	if (transport == IPPROTO_TCP) {
431next_msg:
432		msgstr = (char *)sip_get_tcp_msg(conn_object, (char *)msgstr,
433		    &msglen);
434		if (msgstr == NULL) {
435			sip_refrele_conn(conn_object);
436			return;
437		}
438	} else {
439		msgbuf = (char *)malloc(msglen + 1);
440		if (msgbuf == NULL) {
441			sip_refrele_conn(conn_object);
442			return;
443		}
444		(void) strncpy(msgbuf, msgstr, msglen);
445		msgbuf[msglen] = '\0';
446		msgstr = msgbuf;
447	}
448	sip_msg = (_sip_msg_t *)sip_new_msg();
449	if (sip_msg == NULL) {
450		if (msgbuf != NULL)
451			free(msgbuf);
452		sip_refrele_conn(conn_object);
453		return;
454	}
455	sip_msg->sip_msg_buf = (char *)msgstr;
456	sip_msg->sip_msg_len = msglen;
457	(void) pthread_mutex_lock(&sip_msg->sip_msg_mutex);
458	if (sip_setup_header_pointers(sip_msg) != 0) {
459		(void) pthread_mutex_unlock(&sip_msg->sip_msg_mutex);
460		sip_refrele_conn(conn_object);
461		sip_free_msg((sip_msg_t)sip_msg);
462		return;
463	}
464	if (sip_parse_first_line(sip_msg->sip_msg_start_line,
465	    &sip_msg->sip_msg_req_res)) {
466		(void) pthread_mutex_unlock(&sip_msg->sip_msg_mutex);
467		sip_refrele_conn(conn_object);
468		sip_free_msg((sip_msg_t)sip_msg);
469		return;
470	}
471	sip_msg_info = sip_msg->sip_msg_req_res;
472	(void) pthread_mutex_unlock(&sip_msg->sip_msg_mutex);
473
474	if (sip_check_common_headers(conn_object, sip_msg)) {
475		sip_refrele_conn(conn_object);
476		sip_free_msg((sip_msg_t)sip_msg);
477		return;
478	}
479
480	/*
481	 * Silently discard the response if the top VIA has a sent-by value AND
482	 * the UA has registered sent-by values AND the one in the VIA is
483	 * not part of the registerd sent-by values.
484	 */
485	if (!sip_msg_info->is_request && !sip_valid_sent_by(sip_msg)) {
486		sip_refrele_conn(conn_object);
487		sip_free_msg((sip_msg_t)sip_msg);
488		return;
489
490	}
491	sip_trans = (sip_xaction_t *)sip_xaction_get(conn_object,
492	    (sip_msg_t)sip_msg,
493	    B_FALSE, sip_msg_info->is_request ? SIP_SERVER_TRANSACTION :
494	    SIP_CLIENT_TRANSACTION, NULL);
495	if (sip_trans != NULL) {
496		if (sip_xaction_input(conn_object, sip_trans, &sip_msg) != 0) {
497			SIP_XACTION_REFCNT_DECR(sip_trans);
498			sip_refrele_conn(conn_object);
499			sip_free_msg((sip_msg_t)sip_msg);
500			return;
501		}
502		SIP_XACTION_REFCNT_DECR(sip_trans);
503
504		/*
505		 * msg was retransmission - handled by the transaction
506		 */
507		if (sip_msg == NULL)
508			goto check_next;
509	} else {
510		/*
511		 * If we are getting an INVITE request, let us send a
512		 * 100 TRYING response here, as in 17.2.1:
513		 * "The server transaction MUST generate a 100 (Trying)
514		 * response unless it knows that the TU will generate a
515		 * provisional or final response within 200 ms".
516		 */
517		if (sip_msg_info->is_request &&
518		    sip_msg_info->sip_req_method == INVITE) {
519			sip_send_resp(conn_object, sip_msg, SIP_TRYING);
520		}
521	}
522	if (sip_manage_dialog) {
523		dialog = sip_dialog_find(sip_msg);
524		if (dialog == NULL) {
525			if (sip_msg_info->is_request) {
526				/*
527				 * sip_seed_dialog will check for the
528				 * method in the request
529				 */
530				dialog = (sip_dialog_t)sip_seed_dialog(
531				    conn_object, sip_msg,
532				    B_FALSE, SIP_UAS_DIALOG);
533				dialog_created = B_TRUE;
534			}
535		} else if (sip_incomplete_dialog(dialog)) {
536			if (!sip_msg_info->is_request ||
537			    sip_msg_info->sip_req_method == NOTIFY) {
538				dialog = sip_update_dialog(dialog, sip_msg);
539			}
540		} else if (sip_dialog_process(sip_msg, &dialog) != 0) {
541			if (dialog != NULL)
542				sip_release_dialog(dialog);
543			/*
544			 * cseq number in error, send a
545			 * SIP_SERVER_INTERNAL_ERROR response.
546			 */
547			if (sip_msg_info->is_request) {
548				sip_send_resp(conn_object, sip_msg,
549				    SIP_SERVER_INTERNAL_ERROR);
550			}
551			sip_refrele_conn(conn_object);
552			sip_free_msg((sip_msg_t)sip_msg);
553			return;
554		}
555	}
556	if (sip_msg_info->is_request) {
557		SIP_UPDATE_COUNTERS(B_TRUE, sip_msg_info->sip_req_method, 0,
558		    B_FALSE, sip_msg->sip_msg_len);
559	} else {
560		SIP_UPDATE_COUNTERS(B_FALSE, 0, sip_msg_info->sip_resp_code,
561		    B_FALSE, sip_msg->sip_msg_len);
562	}
563	sip_ulp_recv(conn_object, (sip_msg_t)sip_msg, dialog);
564	sip_free_msg((sip_msg_t)sip_msg);
565	if (dialog != NULL && !dialog_created)
566		sip_release_dialog(dialog);
567check_next:
568	/*
569	 * Check if there are more complete messages in the TCP fragment list
570	 * to be consumed
571	 */
572	if (transport == IPPROTO_TCP) {
573		msgstr = NULL;
574		msglen = 0;
575		goto next_msg;
576	}
577	sip_refrele_conn(conn_object);
578}
579
580/*
581 * Initialize the stack. The connection manager functions, upper layer
582 * receive functions are mandatory.
583 */
584int
585sip_stack_init(sip_stack_init_t *stack_val)
586{
587#ifdef	__linux__
588	struct timespec	tspec;
589#endif
590
591	/*
592	 * If the stack has already been configured, return error
593	 */
594	if (sip_stack_send != NULL ||
595	    stack_val->sip_version != SIP_STACK_VERSION) {
596		return (EINVAL);
597	}
598	if (stack_val->sip_io_pointers == NULL ||
599	    stack_val->sip_ulp_pointers == NULL) {
600		return (EINVAL);
601	}
602	sip_ulp_recv = stack_val->sip_ulp_pointers->sip_ulp_recv;
603	sip_manage_dialog = stack_val->sip_stack_flags & SIP_STACK_DIALOGS;
604
605	sip_stack_send = stack_val->sip_io_pointers->sip_conn_send;
606	sip_refhold_conn = stack_val->sip_io_pointers->sip_hold_conn_object;
607	sip_refrele_conn = stack_val->sip_io_pointers->sip_rel_conn_object;
608	sip_is_conn_stream = stack_val->sip_io_pointers->sip_conn_is_stream;
609	sip_is_conn_reliable = stack_val->sip_io_pointers->sip_conn_is_reliable;
610	sip_conn_rem_addr = stack_val->sip_io_pointers->sip_conn_remote_address;
611	sip_conn_local_addr =
612	    stack_val->sip_io_pointers->sip_conn_local_address;
613	sip_conn_transport = stack_val->sip_io_pointers->sip_conn_transport;
614	sip_header_function_table_external = stack_val->sip_function_table;
615
616	if (sip_ulp_recv == NULL || sip_stack_send == NULL ||
617	    sip_refhold_conn == NULL || sip_refrele_conn == NULL ||
618	    sip_is_conn_stream == NULL || sip_is_conn_reliable == NULL ||
619	    sip_conn_rem_addr == NULL || sip_conn_local_addr == NULL ||
620	    sip_conn_transport == NULL) {
621	err_ret:
622		sip_ulp_recv = NULL;
623		sip_stack_send = NULL;
624		sip_refhold_conn = NULL;
625		sip_refrele_conn = NULL;
626		sip_is_conn_stream = NULL;
627		sip_is_conn_reliable = NULL;
628		sip_conn_rem_addr = NULL;
629		sip_conn_local_addr = NULL;
630		sip_conn_transport = NULL;
631		sip_header_function_table_external = NULL;
632		sip_stack_timeout = NULL;
633		sip_stack_untimeout = NULL;
634		return (EINVAL);
635	}
636
637	sip_conn_timer1 = stack_val->sip_io_pointers->sip_conn_timer1;
638	sip_conn_timer2 = stack_val->sip_io_pointers->sip_conn_timer2;
639	sip_conn_timer4 = stack_val->sip_io_pointers->sip_conn_timer4;
640	sip_conn_timerd = stack_val->sip_io_pointers->sip_conn_timerd;
641
642	/*
643	 * Use Appln timeout routines, if provided
644	 */
645	if (stack_val->sip_ulp_pointers->sip_ulp_timeout != NULL) {
646		if (stack_val->sip_ulp_pointers->sip_ulp_untimeout == NULL)
647			goto err_ret;
648		sip_stack_timeout =
649		    stack_val->sip_ulp_pointers->sip_ulp_timeout;
650		sip_stack_untimeout =
651		    stack_val->sip_ulp_pointers->sip_ulp_untimeout;
652	} else {
653		if (stack_val->sip_ulp_pointers->sip_ulp_untimeout != NULL)
654			goto err_ret;
655		sip_timeout_init();
656		sip_stack_timeout = sip_timeout;
657		sip_stack_untimeout = sip_untimeout;
658	}
659
660	/*
661	 * Manage Dialogs?
662	 */
663	if (sip_manage_dialog) {
664		sip_dialog_init(stack_val->sip_ulp_pointers->sip_ulp_dlg_del,
665		    stack_val->sip_ulp_pointers->sip_ulp_dlg_state_cb);
666	}
667	sip_xaction_init(stack_val->sip_ulp_pointers->sip_ulp_trans_error,
668	    stack_val->sip_ulp_pointers->sip_ulp_trans_state_cb);
669
670	/*
671	 * Initialize SIP traffic counter mutex
672	 */
673	(void) pthread_mutex_init(&sip_counters.sip_counter_mutex, NULL);
674
675	/*
676	 * Initialize SIP logfile structures mutex
677	 */
678	(void) pthread_mutex_init(&trans_log.sip_logfile_mutex, NULL);
679	(void) pthread_mutex_init(&dialog_log.sip_logfile_mutex, NULL);
680
681#ifdef	__linux__
682	if (clock_gettime(CLOCK_REALTIME, &tspec) != 0)
683		goto err_ret;
684	sip_hash_salt = tspec.tv_nsec;
685#else
686	sip_hash_salt = gethrtime();
687#endif
688	(void) pthread_mutex_init(&sip_sent_by_lock, NULL);
689	return (0);
690}
691