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 2007 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 <stdio.h> 30 #include <string.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 #define SIP_MSG_BUF_SZ 100 45 46 47 void (*sip_ulp_recv)(const sip_conn_object_t, sip_msg_t, 48 const sip_dialog_t) = NULL; 49 uint_t (*sip_stack_timeout)(void *, void (*func)(void *), 50 struct timeval *) = NULL; 51 boolean_t (*sip_stack_untimeout)(uint_t) = NULL; 52 int (*sip_stack_send)(sip_conn_object_t xonn_object, char *, int) = 53 NULL; 54 void (*sip_refhold_conn)(sip_conn_object_t) = NULL; 55 void (*sip_refrele_conn)(sip_conn_object_t) = NULL; 56 boolean_t (*sip_is_conn_stream)(sip_conn_object_t) = NULL; 57 boolean_t (*sip_is_conn_reliable)(sip_conn_object_t) = NULL; 58 int (*sip_conn_rem_addr)(sip_conn_object_t, struct sockaddr *, 59 socklen_t *) = NULL; 60 int (*sip_conn_local_addr)(sip_conn_object_t, struct sockaddr *, 61 socklen_t *) = NULL; 62 int (*sip_conn_transport)(sip_conn_object_t) = NULL; 63 int (*sip_conn_timer1)(sip_conn_object_t) = NULL; 64 int (*sip_conn_timer2)(sip_conn_object_t) = NULL; 65 int (*sip_conn_timer4)(sip_conn_object_t) = NULL; 66 int (*sip_conn_timerd)(sip_conn_object_t) = NULL; 67 68 boolean_t sip_manage_dialog = B_FALSE; 69 70 uint64_t sip_hash_salt = 0; 71 72 /* 73 * Defaults, overridden by configured values, if any 74 */ 75 int sip_timer_T1 = SIP_TIMER_T1; 76 int sip_timer_T2 = SIP_TIMER_T2; 77 int sip_timer_T4 = SIP_TIMER_T4; 78 int sip_timer_TD = 32 * SIP_SECONDS; 79 80 /* 81 * list of sent-by values registered by the UA 82 */ 83 sent_by_list_t *sip_sent_by = NULL; 84 int sip_sent_by_count = 0; 85 pthread_mutex_t sip_sent_by_lock; 86 87 /* 88 * Create and send an error response 89 */ 90 static void 91 sip_send_resp(sip_conn_object_t conn_obj, _sip_msg_t *sip_msg, int resp) 92 { 93 _sip_msg_t *sip_msg_resp; 94 95 sip_msg_resp = (_sip_msg_t *)sip_create_response((sip_msg_t)sip_msg, 96 resp, sip_get_resp_desc(resp), NULL, NULL); 97 if (sip_msg_resp == NULL) { 98 /* 99 * Message was too bad to even create a 100 * response. Just drop the messge. 101 */ 102 return; 103 } 104 /* 105 * We directly send it to the transport here. 106 */ 107 if (sip_adjust_msgbuf(sip_msg_resp) != 0) { 108 sip_free_msg((sip_msg_t)sip_msg_resp); 109 return; 110 } 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 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 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 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 && sip_msg_info->is_request && 316 sip_msg_info->sip_req_method == INVITE) { 317 (void) sip_dialog_add_new_contact(dialog, _sip_msg); 318 } 319 } 320 321 if ((ret = sip_stack_send(obj, _sip_msg->sip_msg_buf, 322 _sip_msg->sip_msg_len)) != 0) { 323 if (sip_trans != NULL) { 324 sip_xaction_terminate(sip_trans, _sip_msg, 325 sip_conn_transport(obj)); 326 } 327 sip_refrele_conn(obj); 328 return (ret); 329 } 330 sip_refrele_conn(obj); 331 return (ret); 332 } 333 334 /* 335 * Given a sent-by value check if it is in the registered list. If no values 336 * have been registered, the check passes. 337 */ 338 static boolean_t 339 sip_sent_by_registered(const sip_str_t *sb_val) 340 { 341 sent_by_list_t *sb; 342 int count = 0; 343 344 (void) pthread_mutex_lock(&sip_sent_by_lock); 345 if (sip_sent_by == NULL) { 346 (void) pthread_mutex_unlock(&sip_sent_by_lock); 347 return (B_TRUE); 348 } 349 sb = sip_sent_by; 350 for (count = 0; count < sip_sent_by_count; count++) { 351 if (strncasecmp(sb->sb_val, sb_val->sip_str_ptr, 352 sb_val->sip_str_len) == 0) { 353 (void) pthread_mutex_unlock(&sip_sent_by_lock); 354 return (B_TRUE); 355 } 356 sb = sb->sb_next; 357 } 358 (void) pthread_mutex_unlock(&sip_sent_by_lock); 359 return (B_FALSE); 360 } 361 362 /* 363 * Given a response, check if the sent-by in the VIA header is valid. 364 */ 365 boolean_t 366 sip_valid_sent_by(sip_msg_t sip_msg) 367 { 368 sip_header_t via; 369 sip_header_value_t value = NULL; 370 int error; 371 const sip_str_t *sent_by = NULL; 372 373 via = (sip_header_t)sip_get_header(sip_msg, SIP_VIA, NULL, &error); 374 if (via == NULL || error != 0) 375 return (B_TRUE); 376 value = (sip_header_value_t)sip_get_header_value(via, &error); 377 if (value == NULL || error != 0) 378 return (B_TRUE); 379 sent_by = sip_get_via_sent_by_host(value, &error); 380 if (sent_by == NULL || error != 0) 381 return (B_TRUE); 382 if (sip_sent_by_registered(sent_by)) 383 return (B_TRUE); 384 return (B_FALSE); 385 } 386 387 388 /* 389 * The receive interface to the transport layer. 390 */ 391 void 392 sip_process_new_packet(sip_conn_object_t conn_object, void *msgstr, 393 size_t msglen) 394 { 395 _sip_msg_t *sip_msg; 396 sip_message_type_t *sip_msg_info; 397 sip_xaction_t *sip_trans; 398 sip_dialog_t dialog = NULL; 399 boolean_t dialog_created = B_FALSE; 400 int transport; 401 char *msgbuf = NULL; 402 403 sip_refhold_conn(conn_object); 404 transport = sip_conn_transport(conn_object); 405 if (transport == IPPROTO_TCP) { 406 next_msg: 407 msgstr = (char *)sip_get_tcp_msg(conn_object, (char *)msgstr, 408 &msglen); 409 if (msgstr == NULL) { 410 sip_refrele_conn(conn_object); 411 return; 412 } 413 } else { 414 msgbuf = (char *)malloc(msglen + 1); 415 if (msgbuf == NULL) { 416 sip_refrele_conn(conn_object); 417 return; 418 } 419 (void) strncpy(msgbuf, msgstr, msglen); 420 msgbuf[msglen] = '\0'; 421 msgstr = msgbuf; 422 } 423 sip_msg = (_sip_msg_t *)sip_new_msg(); 424 if (sip_msg == NULL) { 425 if (msgbuf != NULL) 426 free(msgbuf); 427 sip_refrele_conn(conn_object); 428 return; 429 } 430 sip_msg->sip_msg_buf = (char *)msgstr; 431 sip_msg->sip_msg_len = msglen; 432 (void) pthread_mutex_lock(&sip_msg->sip_msg_mutex); 433 if (sip_setup_header_pointers(sip_msg) != 0) { 434 (void) pthread_mutex_unlock(&sip_msg->sip_msg_mutex); 435 sip_refrele_conn(conn_object); 436 sip_free_msg((sip_msg_t)sip_msg); 437 return; 438 } 439 if (sip_parse_first_line(sip_msg->sip_msg_start_line, 440 &sip_msg->sip_msg_req_res)) { 441 (void) pthread_mutex_unlock(&sip_msg->sip_msg_mutex); 442 sip_refrele_conn(conn_object); 443 sip_free_msg((sip_msg_t)sip_msg); 444 return; 445 } 446 sip_msg_info = sip_msg->sip_msg_req_res; 447 (void) pthread_mutex_unlock(&sip_msg->sip_msg_mutex); 448 449 if (sip_check_common_headers(conn_object, sip_msg)) { 450 sip_refrele_conn(conn_object); 451 sip_free_msg((sip_msg_t)sip_msg); 452 return; 453 } 454 455 /* 456 * Silently discard the response if the top VIA has a sent-by value AND 457 * the UA has registered sent-by values AND the one in the VIA is 458 * not part of the registerd sent-by values. 459 */ 460 if (!sip_msg_info->is_request && !sip_valid_sent_by(sip_msg)) { 461 sip_refrele_conn(conn_object); 462 sip_free_msg((sip_msg_t)sip_msg); 463 return; 464 465 } 466 sip_trans = (sip_xaction_t *)sip_xaction_get(conn_object, 467 (sip_msg_t)sip_msg, 468 B_FALSE, sip_msg_info->is_request ? SIP_SERVER_TRANSACTION : 469 SIP_CLIENT_TRANSACTION, NULL); 470 if (sip_trans != NULL) { 471 if (sip_xaction_input(conn_object, sip_trans, &sip_msg) != 0) { 472 SIP_XACTION_REFCNT_DECR(sip_trans); 473 sip_refrele_conn(conn_object); 474 sip_free_msg((sip_msg_t)sip_msg); 475 return; 476 } 477 SIP_XACTION_REFCNT_DECR(sip_trans); 478 479 /* 480 * msg was retransmission - handled by the transaction 481 */ 482 if (sip_msg == NULL) 483 goto check_next; 484 } else { 485 /* 486 * If we are getting an INVITE request, let us send a 487 * 100 TRYING response here, as in 17.2.1: 488 * "The server transaction MUST generate a 100 (Trying) 489 * response unless it knows that the TU will generate a 490 * provisional or final response within 200 ms". 491 */ 492 if (sip_msg_info->is_request && 493 sip_msg_info->sip_req_method == INVITE) { 494 sip_send_resp(conn_object, sip_msg, SIP_TRYING); 495 } 496 } 497 if (sip_manage_dialog) { 498 dialog = sip_dialog_find(sip_msg); 499 if (dialog == NULL) { 500 if (sip_msg_info->is_request) { 501 /* 502 * sip_seed_dialog will check for the 503 * method in the request 504 */ 505 dialog = (sip_dialog_t)sip_seed_dialog( 506 conn_object, sip_msg, 507 B_FALSE, SIP_UAS_DIALOG); 508 dialog_created = B_TRUE; 509 } 510 } else if (sip_incomplete_dialog(dialog)) { 511 if (!sip_msg_info->is_request || 512 sip_msg_info->sip_req_method == NOTIFY) { 513 dialog = sip_update_dialog(dialog, sip_msg); 514 } 515 } else if (sip_dialog_process(sip_msg, &dialog) != 0) { 516 if (dialog != NULL) 517 sip_release_dialog(dialog); 518 /* 519 * cseq number in error, send a 520 * SIP_SERVER_INTERNAL_ERROR response. 521 */ 522 if (sip_msg_info->is_request) { 523 sip_send_resp(conn_object, sip_msg, 524 SIP_SERVER_INTERNAL_ERROR); 525 } 526 sip_refrele_conn(conn_object); 527 sip_free_msg((sip_msg_t)sip_msg); 528 return; 529 } 530 } 531 sip_ulp_recv(conn_object, (sip_msg_t)sip_msg, dialog); 532 sip_free_msg((sip_msg_t)sip_msg); 533 if (dialog != NULL && !dialog_created) 534 sip_release_dialog(dialog); 535 check_next: 536 /* 537 * Check if there are more complete messages in the TCP fragment list 538 * to be consumed 539 */ 540 if (transport == IPPROTO_TCP) { 541 msgstr = NULL; 542 msglen = 0; 543 goto next_msg; 544 } 545 sip_refrele_conn(conn_object); 546 } 547 548 /* 549 * Initialize the stack. The connection manager functions, upper layer 550 * receive functions are mandatory. 551 */ 552 int 553 sip_stack_init(sip_stack_init_t *stack_val) 554 { 555 #ifdef __linux__ 556 struct timespec tspec; 557 #endif 558 559 /* 560 * If the stack has already been configured, return error 561 */ 562 if (sip_stack_send != NULL || 563 stack_val->sip_version != SIP_STACK_VERSION) { 564 return (EINVAL); 565 } 566 if (stack_val->sip_io_pointers == NULL || 567 stack_val->sip_ulp_pointers == NULL) { 568 return (EINVAL); 569 } 570 sip_ulp_recv = stack_val->sip_ulp_pointers->sip_ulp_recv; 571 sip_manage_dialog = stack_val->sip_stack_flags & SIP_STACK_DIALOGS; 572 573 sip_stack_send = stack_val->sip_io_pointers->sip_conn_send; 574 sip_refhold_conn = stack_val->sip_io_pointers->sip_hold_conn_object; 575 sip_refrele_conn = stack_val->sip_io_pointers->sip_rel_conn_object; 576 sip_is_conn_stream = stack_val->sip_io_pointers->sip_conn_is_stream; 577 sip_is_conn_reliable = stack_val->sip_io_pointers->sip_conn_is_reliable; 578 sip_conn_rem_addr = stack_val->sip_io_pointers->sip_conn_remote_address; 579 sip_conn_local_addr = 580 stack_val->sip_io_pointers->sip_conn_local_address; 581 sip_conn_transport = stack_val->sip_io_pointers->sip_conn_transport; 582 sip_header_function_table_external = stack_val->sip_function_table; 583 584 if (sip_ulp_recv == NULL || sip_stack_send == NULL || 585 sip_refhold_conn == NULL || sip_refrele_conn == NULL || 586 sip_is_conn_stream == NULL || sip_is_conn_reliable == NULL || 587 sip_conn_rem_addr == NULL || sip_conn_local_addr == NULL || 588 sip_conn_transport == NULL) { 589 err_ret: 590 sip_ulp_recv = NULL; 591 sip_stack_send = NULL; 592 sip_refhold_conn = NULL; 593 sip_refrele_conn = NULL; 594 sip_is_conn_stream = NULL; 595 sip_is_conn_reliable = NULL; 596 sip_conn_rem_addr = NULL; 597 sip_conn_local_addr = NULL; 598 sip_conn_transport = NULL; 599 sip_header_function_table_external = NULL; 600 sip_stack_timeout = NULL; 601 sip_stack_untimeout = NULL; 602 return (EINVAL); 603 } 604 605 sip_conn_timer1 = stack_val->sip_io_pointers->sip_conn_timer1; 606 sip_conn_timer2 = stack_val->sip_io_pointers->sip_conn_timer2; 607 sip_conn_timer4 = stack_val->sip_io_pointers->sip_conn_timer4; 608 sip_conn_timerd = stack_val->sip_io_pointers->sip_conn_timerd; 609 610 /* 611 * Use Appln timeout routines, if provided 612 */ 613 if (stack_val->sip_ulp_pointers->sip_ulp_timeout != NULL) { 614 if (stack_val->sip_ulp_pointers->sip_ulp_untimeout == NULL) 615 goto err_ret; 616 sip_stack_timeout = 617 stack_val->sip_ulp_pointers->sip_ulp_timeout; 618 sip_stack_untimeout = 619 stack_val->sip_ulp_pointers->sip_ulp_untimeout; 620 } else { 621 if (stack_val->sip_ulp_pointers->sip_ulp_untimeout != NULL) 622 goto err_ret; 623 sip_timeout_init(); 624 sip_stack_timeout = sip_timeout; 625 sip_stack_untimeout = sip_untimeout; 626 } 627 628 /* 629 * Manage Dialogs? 630 */ 631 if (sip_manage_dialog) { 632 sip_dialog_init(stack_val->sip_ulp_pointers->sip_ulp_dlg_del, 633 stack_val->sip_ulp_pointers->sip_ulp_dlg_state_cb); 634 } 635 sip_xaction_init(stack_val->sip_ulp_pointers->sip_ulp_trans_error, 636 stack_val->sip_ulp_pointers->sip_ulp_trans_state_cb); 637 638 #ifdef __linux__ 639 if (clock_gettime(CLOCK_REALTIME, &tspec) != 0) 640 goto err_ret; 641 sip_hash_salt = tspec.tv_nsec; 642 #else 643 sip_hash_salt = gethrtime(); 644 #endif 645 (void) pthread_mutex_init(&sip_sent_by_lock, NULL); 646 return (0); 647 } 648