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