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