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