import less(1)
[unleashed/tickless.git] / usr / src / lib / libsip / common / sip_itf.c
blob4a24aa5fab831957b153eb008187482762035e78
1 /*
2 * CDDL HEADER START
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.
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.
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]
19 * CDDL HEADER END
23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
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>
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"
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;
63 boolean_t sip_manage_dialog = B_FALSE;
65 uint64_t sip_hash_salt = 0;
68 * Defaults, overridden by configured values, if any
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;
76 * list of sent-by values registered by the UA
78 sent_by_list_t *sip_sent_by = NULL;
79 int sip_sent_by_count = 0;
80 pthread_mutex_t sip_sent_by_lock;
83 * Create and send an error response
85 static void
86 sip_send_resp(sip_conn_object_t conn_obj, _sip_msg_t *sip_msg, int resp)
88 _sip_msg_t *sip_msg_resp;
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) {
94 * Message was too bad to even create a
95 * response. Just drop the messge.
97 return;
100 * We directly send it to the transport here.
102 if (sip_adjust_msgbuf(sip_msg_resp) != 0) {
103 sip_free_msg((sip_msg_t)sip_msg_resp);
104 return;
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);
115 * Validate some of the common headers
117 boolean_t
118 sip_check_common_headers(sip_conn_object_t conn_obj, _sip_msg_t *sip_msg)
120 int err;
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);
137 * setup pointers to where the headers are.
139 static int
140 sip_setup_header_pointers(_sip_msg_t *sip_msg)
142 char *msg;
143 _sip_header_t *sip_msg_header;
144 char *end;
146 msg = sip_msg->sip_msg_buf;
147 end = sip_msg->sip_msg_buf + sip_msg->sip_msg_len;
149 * Skip while space.
151 while (isspace(*msg)) {
152 if (msg < end)
153 msg++;
154 else
155 return (EINVAL);
159 * We consider Request and Response line as a header
161 for (;;) {
163 * Skip CRLF
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;
171 * Start of a header.
172 * Check for empty line.
174 if (strncmp(SIP_CRLF, msg, strlen(SIP_CRLF)) == 0) {
176 * empty line, start of content.
178 SKIP_CRLF(msg);
179 sip_msg->sip_msg_headers_end->sip_hdr_end = msg;
180 break;
183 * store start of header.
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) {
201 * Allocate first header structure.
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;
214 msg++;
217 * We have reached the end without hitting the empty line.
219 if (msg - sip_msg->sip_msg_buf >= sip_msg->sip_msg_len)
220 return (EINVAL);
223 if (sip_msg->sip_msg_headers_start == NULL)
224 return (EPROTO);
227 * Move start line to be a separate line.
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;
235 if (sip_msg->sip_msg_headers_start == NULL)
236 return (EINVAL);
237 sip_msg->sip_msg_headers_start->sip_hdr_prev = NULL;
241 * Deal with content.
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);
255 * The send interface to the sip stack. Used by upper layers.
258 sip_sendmsg(sip_conn_object_t obj, sip_msg_t sip_msg, sip_dialog_t dialog,
259 uint32_t flags)
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;
268 sip_refhold_conn(obj);
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);
276 assert(_sip_msg->sip_msg_req_res != NULL);
277 sip_msg_info = _sip_msg->sip_msg_req_res;
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?)
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);
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);
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.
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) {
315 * Dialog is in CONFIRMED state. If logging is enabled
316 * track the SIP message sent within a dialog.
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);
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);
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()
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);
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));
350 sip_refrele_conn(obj);
351 return (ret);
353 sip_refrele_conn(obj);
354 return (ret);
358 * Given a sent-by value check if it is in the registered list. If no values
359 * have been registered, the check passes.
361 static boolean_t
362 sip_sent_by_registered(const sip_str_t *sb_val)
364 sent_by_list_t *sb;
365 int count = 0;
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);
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);
379 sb = sb->sb_next;
381 (void) pthread_mutex_unlock(&sip_sent_by_lock);
382 return (B_FALSE);
386 * Given a response, check if the sent-by in the VIA header is valid.
388 boolean_t
389 sip_valid_sent_by(sip_msg_t sip_msg)
391 sip_header_t via;
392 sip_header_value_t value = NULL;
393 int error;
394 const sip_str_t *sent_by = NULL;
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);
412 * The receive interface to the transport layer.
414 void
415 sip_process_new_packet(sip_conn_object_t conn_object, void *msgstr,
416 size_t msglen)
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;
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;
436 } else {
437 msgbuf = (char *)malloc(msglen + 1);
438 if (msgbuf == NULL) {
439 sip_refrele_conn(conn_object);
440 return;
442 (void) strncpy(msgbuf, msgstr, msglen);
443 msgbuf[msglen] = '\0';
444 msgstr = msgbuf;
446 sip_msg = (_sip_msg_t *)sip_new_msg();
447 if (sip_msg == NULL) {
448 free(msgbuf);
449 sip_refrele_conn(conn_object);
450 return;
452 sip_msg->sip_msg_buf = (char *)msgstr;
453 sip_msg->sip_msg_len = msglen;
454 (void) pthread_mutex_lock(&sip_msg->sip_msg_mutex);
455 if (sip_setup_header_pointers(sip_msg) != 0) {
456 (void) pthread_mutex_unlock(&sip_msg->sip_msg_mutex);
457 sip_refrele_conn(conn_object);
458 sip_free_msg((sip_msg_t)sip_msg);
459 return;
461 if (sip_parse_first_line(sip_msg->sip_msg_start_line,
462 &sip_msg->sip_msg_req_res)) {
463 (void) pthread_mutex_unlock(&sip_msg->sip_msg_mutex);
464 sip_refrele_conn(conn_object);
465 sip_free_msg((sip_msg_t)sip_msg);
466 return;
468 sip_msg_info = sip_msg->sip_msg_req_res;
469 (void) pthread_mutex_unlock(&sip_msg->sip_msg_mutex);
471 if (sip_check_common_headers(conn_object, sip_msg)) {
472 sip_refrele_conn(conn_object);
473 sip_free_msg((sip_msg_t)sip_msg);
474 return;
478 * Silently discard the response if the top VIA has a sent-by value AND
479 * the UA has registered sent-by values AND the one in the VIA is
480 * not part of the registerd sent-by values.
482 if (!sip_msg_info->is_request && !sip_valid_sent_by(sip_msg)) {
483 sip_refrele_conn(conn_object);
484 sip_free_msg((sip_msg_t)sip_msg);
485 return;
488 sip_trans = (sip_xaction_t *)sip_xaction_get(conn_object,
489 (sip_msg_t)sip_msg,
490 B_FALSE, sip_msg_info->is_request ? SIP_SERVER_TRANSACTION :
491 SIP_CLIENT_TRANSACTION, NULL);
492 if (sip_trans != NULL) {
493 if (sip_xaction_input(conn_object, sip_trans, &sip_msg) != 0) {
494 SIP_XACTION_REFCNT_DECR(sip_trans);
495 sip_refrele_conn(conn_object);
496 sip_free_msg((sip_msg_t)sip_msg);
497 return;
499 SIP_XACTION_REFCNT_DECR(sip_trans);
502 * msg was retransmission - handled by the transaction
504 if (sip_msg == NULL)
505 goto check_next;
506 } else {
508 * If we are getting an INVITE request, let us send a
509 * 100 TRYING response here, as in 17.2.1:
510 * "The server transaction MUST generate a 100 (Trying)
511 * response unless it knows that the TU will generate a
512 * provisional or final response within 200 ms".
514 if (sip_msg_info->is_request &&
515 sip_msg_info->sip_req_method == INVITE) {
516 sip_send_resp(conn_object, sip_msg, SIP_TRYING);
519 if (sip_manage_dialog) {
520 dialog = sip_dialog_find(sip_msg);
521 if (dialog == NULL) {
522 if (sip_msg_info->is_request) {
524 * sip_seed_dialog will check for the
525 * method in the request
527 dialog = (sip_dialog_t)sip_seed_dialog(
528 conn_object, sip_msg,
529 B_FALSE, SIP_UAS_DIALOG);
530 dialog_created = B_TRUE;
532 } else if (sip_incomplete_dialog(dialog)) {
533 if (!sip_msg_info->is_request ||
534 sip_msg_info->sip_req_method == NOTIFY) {
535 dialog = sip_update_dialog(dialog, sip_msg);
537 } else if (sip_dialog_process(sip_msg, &dialog) != 0) {
538 if (dialog != NULL)
539 sip_release_dialog(dialog);
541 * cseq number in error, send a
542 * SIP_SERVER_INTERNAL_ERROR response.
544 if (sip_msg_info->is_request) {
545 sip_send_resp(conn_object, sip_msg,
546 SIP_SERVER_INTERNAL_ERROR);
548 sip_refrele_conn(conn_object);
549 sip_free_msg((sip_msg_t)sip_msg);
550 return;
553 if (sip_msg_info->is_request) {
554 SIP_UPDATE_COUNTERS(B_TRUE, sip_msg_info->sip_req_method, 0,
555 B_FALSE, sip_msg->sip_msg_len);
556 } else {
557 SIP_UPDATE_COUNTERS(B_FALSE, 0, sip_msg_info->sip_resp_code,
558 B_FALSE, sip_msg->sip_msg_len);
560 sip_ulp_recv(conn_object, (sip_msg_t)sip_msg, dialog);
561 sip_free_msg((sip_msg_t)sip_msg);
562 if (dialog != NULL && !dialog_created)
563 sip_release_dialog(dialog);
564 check_next:
566 * Check if there are more complete messages in the TCP fragment list
567 * to be consumed
569 if (transport == IPPROTO_TCP) {
570 msgstr = NULL;
571 msglen = 0;
572 goto next_msg;
574 sip_refrele_conn(conn_object);
578 * Initialize the stack. The connection manager functions, upper layer
579 * receive functions are mandatory.
582 sip_stack_init(sip_stack_init_t *stack_val)
584 #ifdef __linux__
585 struct timespec tspec;
586 #endif
589 * If the stack has already been configured, return error
591 if (sip_stack_send != NULL ||
592 stack_val->sip_version != SIP_STACK_VERSION) {
593 return (EINVAL);
595 if (stack_val->sip_io_pointers == NULL ||
596 stack_val->sip_ulp_pointers == NULL) {
597 return (EINVAL);
599 sip_ulp_recv = stack_val->sip_ulp_pointers->sip_ulp_recv;
600 sip_manage_dialog = stack_val->sip_stack_flags & SIP_STACK_DIALOGS;
602 sip_stack_send = stack_val->sip_io_pointers->sip_conn_send;
603 sip_refhold_conn = stack_val->sip_io_pointers->sip_hold_conn_object;
604 sip_refrele_conn = stack_val->sip_io_pointers->sip_rel_conn_object;
605 sip_is_conn_stream = stack_val->sip_io_pointers->sip_conn_is_stream;
606 sip_is_conn_reliable = stack_val->sip_io_pointers->sip_conn_is_reliable;
607 sip_conn_rem_addr = stack_val->sip_io_pointers->sip_conn_remote_address;
608 sip_conn_local_addr =
609 stack_val->sip_io_pointers->sip_conn_local_address;
610 sip_conn_transport = stack_val->sip_io_pointers->sip_conn_transport;
611 sip_header_function_table_external = stack_val->sip_function_table;
613 if (sip_ulp_recv == NULL || sip_stack_send == NULL ||
614 sip_refhold_conn == NULL || sip_refrele_conn == NULL ||
615 sip_is_conn_stream == NULL || sip_is_conn_reliable == NULL ||
616 sip_conn_rem_addr == NULL || sip_conn_local_addr == NULL ||
617 sip_conn_transport == NULL) {
618 err_ret:
619 sip_ulp_recv = NULL;
620 sip_stack_send = NULL;
621 sip_refhold_conn = NULL;
622 sip_refrele_conn = NULL;
623 sip_is_conn_stream = NULL;
624 sip_is_conn_reliable = NULL;
625 sip_conn_rem_addr = NULL;
626 sip_conn_local_addr = NULL;
627 sip_conn_transport = NULL;
628 sip_header_function_table_external = NULL;
629 sip_stack_timeout = NULL;
630 sip_stack_untimeout = NULL;
631 return (EINVAL);
634 sip_conn_timer1 = stack_val->sip_io_pointers->sip_conn_timer1;
635 sip_conn_timer2 = stack_val->sip_io_pointers->sip_conn_timer2;
636 sip_conn_timer4 = stack_val->sip_io_pointers->sip_conn_timer4;
637 sip_conn_timerd = stack_val->sip_io_pointers->sip_conn_timerd;
640 * Use Appln timeout routines, if provided
642 if (stack_val->sip_ulp_pointers->sip_ulp_timeout != NULL) {
643 if (stack_val->sip_ulp_pointers->sip_ulp_untimeout == NULL)
644 goto err_ret;
645 sip_stack_timeout =
646 stack_val->sip_ulp_pointers->sip_ulp_timeout;
647 sip_stack_untimeout =
648 stack_val->sip_ulp_pointers->sip_ulp_untimeout;
649 } else {
650 if (stack_val->sip_ulp_pointers->sip_ulp_untimeout != NULL)
651 goto err_ret;
652 sip_timeout_init();
653 sip_stack_timeout = sip_timeout;
654 sip_stack_untimeout = sip_untimeout;
658 * Manage Dialogs?
660 if (sip_manage_dialog) {
661 sip_dialog_init(stack_val->sip_ulp_pointers->sip_ulp_dlg_del,
662 stack_val->sip_ulp_pointers->sip_ulp_dlg_state_cb);
664 sip_xaction_init(stack_val->sip_ulp_pointers->sip_ulp_trans_error,
665 stack_val->sip_ulp_pointers->sip_ulp_trans_state_cb);
668 * Initialize SIP traffic counter mutex
670 (void) pthread_mutex_init(&sip_counters.sip_counter_mutex, NULL);
673 * Initialize SIP logfile structures mutex
675 (void) pthread_mutex_init(&trans_log.sip_logfile_mutex, NULL);
676 (void) pthread_mutex_init(&dialog_log.sip_logfile_mutex, NULL);
678 #ifdef __linux__
679 if (clock_gettime(CLOCK_REALTIME, &tspec) != 0)
680 goto err_ret;
681 sip_hash_salt = tspec.tv_nsec;
682 #else
683 sip_hash_salt = gethrtime();
684 #endif
685 (void) pthread_mutex_init(&sip_sent_by_lock, NULL);
686 return (0);