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
44 void (*sip_ulp_recv)(const sip_conn_object_t, sip_msg_t,
45 const sip_dialog_t) = NULL;
46 uint_t (*sip_stack_timeout)(void *, void (*func)(void *),
47 struct timeval *) = NULL;
48 boolean_t (*sip_stack_untimeout)(uint_t) = NULL;
49 int (*sip_stack_send)(sip_conn_object_t xonn_object, char *, int) =
50 NULL;
51 void (*sip_refhold_conn)(sip_conn_object_t) = NULL;
52 void (*sip_refrele_conn)(sip_conn_object_t) = NULL;
53 boolean_t (*sip_is_conn_stream)(sip_conn_object_t) = NULL;
54 boolean_t (*sip_is_conn_reliable)(sip_conn_object_t) = NULL;
55 int (*sip_conn_rem_addr)(sip_conn_object_t, struct sockaddr *,
56 socklen_t *) = NULL;
57 int (*sip_conn_local_addr)(sip_conn_object_t, struct sockaddr *,
58 socklen_t *) = NULL;
59 int (*sip_conn_transport)(sip_conn_object_t) = NULL;
60 int (*sip_conn_timer1)(sip_conn_object_t) = NULL;
61 int (*sip_conn_timer2)(sip_conn_object_t) = NULL;
62 int (*sip_conn_timer4)(sip_conn_object_t) = NULL;
63 int (*sip_conn_timerd)(sip_conn_object_t) = NULL;
64
65 boolean_t sip_manage_dialog = B_FALSE;
66
67 uint64_t sip_hash_salt = 0;
68
69 /*
70 * Defaults, overridden by configured values, if any
71 */
72 int sip_timer_T1 = SIP_TIMER_T1;
73 int sip_timer_T2 = SIP_TIMER_T2;
74 int sip_timer_T4 = SIP_TIMER_T4;
75 int sip_timer_TD = 32 * SIP_SECONDS;
76
77 /*
78 * list of sent-by values registered by the UA
79 */
80 sent_by_list_t *sip_sent_by = NULL;
81 int sip_sent_by_count = 0;
82 pthread_mutex_t sip_sent_by_lock;
83
84 /*
85 * Create and send an error response
86 */
87 static void
sip_send_resp(sip_conn_object_t conn_obj,_sip_msg_t * sip_msg,int resp)88 sip_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 */
119 boolean_t
sip_check_common_headers(sip_conn_object_t conn_obj,_sip_msg_t * sip_msg)120 sip_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);
133 error:
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 */
141 static int
sip_setup_header_pointers(_sip_msg_t * sip_msg)142 sip_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 */
259 int
sip_sendmsg(sip_conn_object_t obj,sip_msg_t sip_msg,sip_dialog_t dialog,uint32_t flags)260 sip_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 */
363 static boolean_t
sip_sent_by_registered(const sip_str_t * sb_val)364 sip_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 */
390 boolean_t
sip_valid_sent_by(sip_msg_t sip_msg)391 sip_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 */
416 void
sip_process_new_packet(sip_conn_object_t conn_object,void * msgstr,size_t msglen)417 sip_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) {
431 next_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);
567 check_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 */
584 int
sip_stack_init(sip_stack_init_t * stack_val)585 sip_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