12882Svi117747 /* 22882Svi117747 * CDDL HEADER START 32882Svi117747 * 42882Svi117747 * The contents of this file are subject to the terms of the 52882Svi117747 * Common Development and Distribution License (the "License"). 62882Svi117747 * You may not use this file except in compliance with the License. 72882Svi117747 * 82882Svi117747 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 92882Svi117747 * or http://www.opensolaris.org/os/licensing. 102882Svi117747 * See the License for the specific language governing permissions 112882Svi117747 * and limitations under the License. 122882Svi117747 * 132882Svi117747 * When distributing Covered Code, include this CDDL HEADER in each 142882Svi117747 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 152882Svi117747 * If applicable, add the following below this CDDL HEADER, with the 162882Svi117747 * fields enclosed by brackets "[]" replaced with your own identifying 172882Svi117747 * information: Portions Copyright [yyyy] [name of copyright owner] 182882Svi117747 * 192882Svi117747 * CDDL HEADER END 202882Svi117747 */ 212882Svi117747 222882Svi117747 /* 23*3439Svi117747 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 242882Svi117747 * Use is subject to license terms. 252882Svi117747 */ 262882Svi117747 272882Svi117747 #pragma ident "%Z%%M% %I% %E% SMI" 282882Svi117747 29*3439Svi117747 #include <stdio.h> 30*3439Svi117747 #include <string.h> 31*3439Svi117747 #include <stdlib.h> 32*3439Svi117747 #include <assert.h> 33*3439Svi117747 #include <ctype.h> 34*3439Svi117747 #include <errno.h> 35*3439Svi117747 #include <pthread.h> 36*3439Svi117747 #include <sip.h> 37*3439Svi117747 382882Svi117747 #include "sip_msg.h" 392882Svi117747 #include "sip_miscdefs.h" 402882Svi117747 #include "sip_xaction.h" 412882Svi117747 #include "sip_dialog.h" 422882Svi117747 #include "sip_parse_generic.h" 432882Svi117747 442882Svi117747 #define SIP_MSG_BUF_SZ 100 452882Svi117747 462882Svi117747 472882Svi117747 void (*sip_ulp_recv)(const sip_conn_object_t, sip_msg_t, 482882Svi117747 const sip_dialog_t) = NULL; 492882Svi117747 uint_t (*sip_stack_timeout)(void *, void (*func)(void *), 502882Svi117747 struct timeval *) = NULL; 512882Svi117747 boolean_t (*sip_stack_untimeout)(uint_t) = NULL; 522882Svi117747 int (*sip_stack_send)(sip_conn_object_t xonn_object, char *, int) = 532882Svi117747 NULL; 542882Svi117747 void (*sip_refhold_conn)(sip_conn_object_t) = NULL; 552882Svi117747 void (*sip_refrele_conn)(sip_conn_object_t) = NULL; 562882Svi117747 boolean_t (*sip_is_conn_stream)(sip_conn_object_t) = NULL; 572882Svi117747 boolean_t (*sip_is_conn_reliable)(sip_conn_object_t) = NULL; 582882Svi117747 int (*sip_conn_rem_addr)(sip_conn_object_t, struct sockaddr *, 592882Svi117747 socklen_t *) = NULL; 602882Svi117747 int (*sip_conn_local_addr)(sip_conn_object_t, struct sockaddr *, 612882Svi117747 socklen_t *) = NULL; 622882Svi117747 int (*sip_conn_transport)(sip_conn_object_t) = NULL; 632882Svi117747 int (*sip_conn_timer1)(sip_conn_object_t) = NULL; 642882Svi117747 int (*sip_conn_timer2)(sip_conn_object_t) = NULL; 652882Svi117747 int (*sip_conn_timer4)(sip_conn_object_t) = NULL; 662882Svi117747 int (*sip_conn_timerd)(sip_conn_object_t) = NULL; 672882Svi117747 682882Svi117747 boolean_t sip_manage_dialog = B_FALSE; 692882Svi117747 702882Svi117747 uint64_t sip_hash_salt = 0; 712882Svi117747 722882Svi117747 /* 732882Svi117747 * Defaults, overridden by configured values, if any 742882Svi117747 */ 752882Svi117747 int sip_timer_T1 = SIP_TIMER_T1; 762882Svi117747 int sip_timer_T2 = SIP_TIMER_T2; 772882Svi117747 int sip_timer_T4 = SIP_TIMER_T4; 782882Svi117747 int sip_timer_TD = 32 * SIP_SECONDS; 792882Svi117747 802882Svi117747 /* 812882Svi117747 * list of sent-by values registered by the UA 822882Svi117747 */ 832882Svi117747 sent_by_list_t *sip_sent_by = NULL; 842882Svi117747 int sip_sent_by_count = 0; 852882Svi117747 pthread_mutex_t sip_sent_by_lock; 862882Svi117747 872882Svi117747 /* 882882Svi117747 * Create and send an error response 892882Svi117747 */ 902882Svi117747 static void 912882Svi117747 sip_send_resp(sip_conn_object_t conn_obj, _sip_msg_t *sip_msg, int resp) 922882Svi117747 { 932882Svi117747 _sip_msg_t *sip_msg_resp; 942882Svi117747 952882Svi117747 sip_msg_resp = (_sip_msg_t *)sip_create_response((sip_msg_t)sip_msg, 962882Svi117747 resp, sip_get_resp_desc(resp), NULL, NULL); 972882Svi117747 if (sip_msg_resp == NULL) { 982882Svi117747 /* 992882Svi117747 * Message was too bad to even create a 1002882Svi117747 * response. Just drop the messge. 1012882Svi117747 */ 1022882Svi117747 return; 1032882Svi117747 } 1042882Svi117747 /* 1052882Svi117747 * We directly send it to the transport here. 1062882Svi117747 */ 1072882Svi117747 if (sip_adjust_msgbuf(sip_msg_resp) != 0) { 1082882Svi117747 sip_free_msg((sip_msg_t)sip_msg_resp); 1092882Svi117747 return; 1102882Svi117747 } 1112882Svi117747 (void) sip_stack_send(conn_obj, sip_msg_resp->sip_msg_buf, 1122882Svi117747 sip_msg_resp->sip_msg_len); 1132882Svi117747 sip_free_msg((sip_msg_t)sip_msg_resp); 1142882Svi117747 } 1152882Svi117747 1162882Svi117747 /* 1172882Svi117747 * Validate some of the common headers 1182882Svi117747 */ 1192882Svi117747 boolean_t 1202882Svi117747 sip_check_common_headers(sip_conn_object_t conn_obj, _sip_msg_t *sip_msg) 1212882Svi117747 { 1222882Svi117747 int err; 1232882Svi117747 1242882Svi117747 if (sip_get_to_uri_str((sip_msg_t)sip_msg, &err) == NULL) 1252882Svi117747 goto error; 1262882Svi117747 if (sip_get_from_uri_str((sip_msg_t)sip_msg, &err) == NULL) 1272882Svi117747 goto error; 1282882Svi117747 if (sip_get_callseq_num((sip_msg_t)sip_msg, &err) < 0) 1292882Svi117747 goto error; 1302882Svi117747 if (sip_get_callid((sip_msg_t)sip_msg, &err) == NULL) 1312882Svi117747 goto error; 1322882Svi117747 return (B_FALSE); 1332882Svi117747 error: 1342882Svi117747 sip_send_resp(conn_obj, sip_msg, SIP_BAD_REQUEST); 1352882Svi117747 return (B_TRUE); 1362882Svi117747 } 1372882Svi117747 1382882Svi117747 /* 1392882Svi117747 * setup pointers to where the headers are. 1402882Svi117747 */ 1412882Svi117747 static int 1422882Svi117747 sip_setup_header_pointers(_sip_msg_t *sip_msg) 1432882Svi117747 { 1442882Svi117747 char *msg; 1452882Svi117747 _sip_header_t *sip_msg_header; 1462882Svi117747 char *end; 1472882Svi117747 1482882Svi117747 msg = sip_msg->sip_msg_buf; 1492882Svi117747 end = sip_msg->sip_msg_buf + sip_msg->sip_msg_len; 1502882Svi117747 /* 1512882Svi117747 * Skip while space. 1522882Svi117747 */ 1532882Svi117747 while (isspace(*msg)) { 1542882Svi117747 if (msg < end) 1552882Svi117747 msg++; 1562882Svi117747 else 1572882Svi117747 return (EINVAL); 1582882Svi117747 } 1592882Svi117747 1602882Svi117747 /* 1612882Svi117747 * We consider Request and Response line as a header 1622882Svi117747 */ 1632882Svi117747 for (;;) { 1642882Svi117747 /* 1652882Svi117747 * Skip CRLF 1662882Svi117747 */ 1672882Svi117747 if (strncmp(SIP_CRLF, msg, strlen(SIP_CRLF)) == 0) { 1682882Svi117747 if (sip_msg->sip_msg_headers_end != NULL) { 1692882Svi117747 SKIP_CRLF(msg); 1702882Svi117747 sip_msg->sip_msg_headers_end->sip_hdr_end = msg; 1712882Svi117747 } 1722882Svi117747 /* 1732882Svi117747 * Start of a header. 1742882Svi117747 * Check for empty line. 1752882Svi117747 */ 1762882Svi117747 if (strncmp(SIP_CRLF, msg, strlen(SIP_CRLF)) == 0) { 1772882Svi117747 /* 1782882Svi117747 * empty line, start of content. 1792882Svi117747 */ 1802882Svi117747 SKIP_CRLF(msg); 1812882Svi117747 sip_msg->sip_msg_headers_end->sip_hdr_end = msg; 1822882Svi117747 break; 1832882Svi117747 } 1842882Svi117747 /* 1852882Svi117747 * store start of header. 1862882Svi117747 */ 1872882Svi117747 sip_msg_header = calloc(1, sizeof (_sip_header_t)); 1882882Svi117747 if (sip_msg_header == NULL) 1892882Svi117747 return (EINVAL); 1902882Svi117747 sip_msg_header->sip_hdr_start = msg; 1912882Svi117747 sip_msg_header->sip_hdr_current = msg; 1922882Svi117747 sip_msg_header->sip_hdr_allocated = B_FALSE; 1932882Svi117747 sip_msg_header->sip_hdr_prev = 1942882Svi117747 sip_msg->sip_msg_headers_end; 1952882Svi117747 sip_msg_header->sip_hdr_next = NULL; 1962882Svi117747 sip_msg_header->sip_hdr_sipmsg = sip_msg; 1972882Svi117747 sip_msg->sip_msg_headers_end->sip_hdr_next = 1982882Svi117747 sip_msg_header; 1992882Svi117747 sip_msg->sip_msg_headers_end = sip_msg_header; 2002882Svi117747 } else { 2012882Svi117747 if (sip_msg->sip_msg_headers_start == NULL) { 2022882Svi117747 /* 2032882Svi117747 * Allocate first header structure. 2042882Svi117747 */ 2052882Svi117747 sip_msg_header = calloc(1, 2062882Svi117747 sizeof (_sip_header_t)); 2072882Svi117747 if (sip_msg_header == NULL) 2082882Svi117747 return (EINVAL); 2092882Svi117747 sip_msg_header->sip_hdr_allocated = B_FALSE; 2102882Svi117747 sip_msg_header->sip_hdr_start = msg; 2112882Svi117747 sip_msg_header->sip_hdr_current = msg; 2122882Svi117747 sip_msg_header->sip_hdr_sipmsg = sip_msg; 2132882Svi117747 sip_msg->sip_msg_headers_start = sip_msg_header; 2142882Svi117747 sip_msg->sip_msg_headers_end = sip_msg_header; 2152882Svi117747 } 2162882Svi117747 msg++; 2172882Svi117747 } 2182882Svi117747 /* 2192882Svi117747 * We have reached the end without hitting the empty line. 2202882Svi117747 */ 2212882Svi117747 if (msg - sip_msg->sip_msg_buf >= sip_msg->sip_msg_len) 2222882Svi117747 return (EINVAL); 2232882Svi117747 } 2242882Svi117747 2252882Svi117747 if (sip_msg->sip_msg_headers_start == NULL) 2262882Svi117747 return (EPROTO); 2272882Svi117747 2282882Svi117747 /* 2292882Svi117747 * Move start line to be a separate line. 2302882Svi117747 */ 2312882Svi117747 sip_msg->sip_msg_start_line = sip_msg->sip_msg_headers_start; 2322882Svi117747 sip_msg->sip_msg_headers_start = 2332882Svi117747 sip_msg->sip_msg_headers_start->sip_hdr_next; 2342882Svi117747 sip_msg->sip_msg_start_line->sip_hdr_prev = NULL; 2352882Svi117747 sip_msg->sip_msg_start_line->sip_hdr_next = NULL; 2362882Svi117747 2372882Svi117747 if (sip_msg->sip_msg_headers_start == NULL) 2382882Svi117747 return (EINVAL); 2392882Svi117747 sip_msg->sip_msg_headers_start->sip_hdr_prev = NULL; 2402882Svi117747 2412882Svi117747 2422882Svi117747 /* 2432882Svi117747 * Deal with content. 2442882Svi117747 */ 2452882Svi117747 sip_msg->sip_msg_content = calloc(1, sizeof (sip_content_t)); 2462882Svi117747 sip_msg->sip_msg_content->sip_content_start = msg; 2472882Svi117747 sip_msg->sip_msg_content->sip_content_end = sip_msg->sip_msg_buf + 2482882Svi117747 sip_msg->sip_msg_len; 2492882Svi117747 sip_msg->sip_msg_content->sip_content_allocated = B_FALSE; 2502882Svi117747 sip_msg->sip_msg_content_len = 2512882Svi117747 sip_msg->sip_msg_content->sip_content_end - 2522882Svi117747 sip_msg->sip_msg_content->sip_content_start; 2532882Svi117747 return (0); 2542882Svi117747 } 2552882Svi117747 2562882Svi117747 /* 2572882Svi117747 * The send interface to the sip stack. Used by upper layers. 2582882Svi117747 */ 2592882Svi117747 int 2602882Svi117747 sip_sendmsg(sip_conn_object_t obj, sip_msg_t sip_msg, sip_dialog_t dialog, 2612882Svi117747 uint32_t flags) 2622882Svi117747 { 2632882Svi117747 sip_xaction_t *sip_trans = NULL; 2642882Svi117747 int ret = 0; 2652882Svi117747 sip_message_type_t *sip_msg_info; 2662882Svi117747 _sip_msg_t *_sip_msg; 2672882Svi117747 boolean_t stateful = flags & SIP_SEND_STATEFUL; 2682882Svi117747 boolean_t dlg_on_fork = flags & SIP_DIALOG_ON_FORK; 2692882Svi117747 2702882Svi117747 sip_refhold_conn(obj); 2712882Svi117747 2722882Svi117747 _sip_msg = (_sip_msg_t *)sip_msg; 2732882Svi117747 if ((ret = sip_adjust_msgbuf(_sip_msg)) != 0) { 2742882Svi117747 sip_refrele_conn(obj); 2752882Svi117747 return (ret); 2762882Svi117747 } 2772882Svi117747 2782882Svi117747 assert(_sip_msg->sip_msg_req_res != NULL); 2792882Svi117747 sip_msg_info = _sip_msg->sip_msg_req_res; 2802882Svi117747 /* 2812882Svi117747 * Send it statefully if: 2822882Svi117747 * if stateful is set in 'flags' AND 2832882Svi117747 * this is not an ACK request, if it is a request (should the upper 2842882Svi117747 * layer set stateful in the latter case?, i.e is the check 2852882Svi117747 * necessary here?) 2862882Svi117747 */ 2872882Svi117747 if (stateful && (!sip_msg_info->is_request || 2882882Svi117747 sip_msg_info->sip_req_method != ACK)) { 2892882Svi117747 sip_trans = (sip_xaction_t *)sip_xaction_get(obj, sip_msg, 2902882Svi117747 B_TRUE, sip_msg_info->is_request ? SIP_CLIENT_TRANSACTION : 2912882Svi117747 SIP_SERVER_TRANSACTION, &ret); 2922882Svi117747 if (sip_trans == NULL) { 2932882Svi117747 sip_refrele_conn(obj); 2942882Svi117747 return (ret); 2952882Svi117747 } 2962882Svi117747 ret = sip_xaction_output(obj, sip_trans, _sip_msg); 2972882Svi117747 SIP_XACTION_REFCNT_DECR(sip_trans); 2982882Svi117747 if (ret != 0) { 2992882Svi117747 sip_refrele_conn(obj); 3002882Svi117747 return (ret); 3012882Svi117747 } 3022882Svi117747 } 3032882Svi117747 /* 3042882Svi117747 * If the appln wants us to create the dialog, create a partial 3052882Svi117747 * dialog at this stage, when we get the response, we will 3062882Svi117747 * complete it. 3072882Svi117747 */ 3082882Svi117747 if (sip_manage_dialog) { 3092882Svi117747 if (sip_msg_info->is_request && dialog == NULL) { 3102882Svi117747 dialog = (sip_dialog_t)sip_seed_dialog(obj, sip_msg, 3112882Svi117747 dlg_on_fork, SIP_UAC_DIALOG); 3122882Svi117747 } else if (dialog != NULL && (!sip_msg_info->is_request || 3132882Svi117747 sip_msg_info->sip_req_method == NOTIFY)) { 3142882Svi117747 (void) sip_update_dialog(dialog, _sip_msg); 3152882Svi117747 } 3162882Svi117747 } 3172882Svi117747 3182882Svi117747 if ((ret = sip_stack_send(obj, _sip_msg->sip_msg_buf, 3192882Svi117747 _sip_msg->sip_msg_len)) != 0) { 3202882Svi117747 if (sip_trans != NULL) { 3212882Svi117747 sip_xaction_terminate(sip_trans, _sip_msg, 3222882Svi117747 sip_conn_transport(obj)); 3232882Svi117747 } 3242882Svi117747 sip_refrele_conn(obj); 3252882Svi117747 return (ret); 3262882Svi117747 } 3272882Svi117747 sip_refrele_conn(obj); 3282882Svi117747 return (ret); 3292882Svi117747 } 3302882Svi117747 3312882Svi117747 /* 3322882Svi117747 * Given a sent-by value check if it is in the registered list. If no values 3332882Svi117747 * have been registered, the check passes. 3342882Svi117747 */ 3352882Svi117747 static boolean_t 3362882Svi117747 sip_sent_by_registered(const sip_str_t *sb_val) 3372882Svi117747 { 3382882Svi117747 sent_by_list_t *sb; 3392882Svi117747 int count = 0; 3402882Svi117747 3412882Svi117747 (void) pthread_mutex_lock(&sip_sent_by_lock); 3422882Svi117747 if (sip_sent_by == NULL) { 3432882Svi117747 (void) pthread_mutex_unlock(&sip_sent_by_lock); 3442882Svi117747 return (B_TRUE); 3452882Svi117747 } 3462882Svi117747 sb = sip_sent_by; 3472882Svi117747 for (count = 0; count < sip_sent_by_count; count++) { 3482882Svi117747 if (strncasecmp(sb->sb_val, sb_val->sip_str_ptr, 3492882Svi117747 sb_val->sip_str_len) == 0) { 3502882Svi117747 (void) pthread_mutex_unlock(&sip_sent_by_lock); 3512882Svi117747 return (B_TRUE); 3522882Svi117747 } 3532882Svi117747 sb = sb->sb_next; 3542882Svi117747 } 3552882Svi117747 (void) pthread_mutex_unlock(&sip_sent_by_lock); 3562882Svi117747 return (B_FALSE); 3572882Svi117747 } 3582882Svi117747 3592882Svi117747 /* 3602882Svi117747 * Given a response, check if the sent-by in the VIA header is valid. 3612882Svi117747 */ 3622882Svi117747 boolean_t 3632882Svi117747 sip_valid_sent_by(sip_msg_t sip_msg) 3642882Svi117747 { 3652882Svi117747 sip_header_t via; 3662882Svi117747 sip_header_value_t value = NULL; 3672882Svi117747 int error; 3682882Svi117747 const sip_str_t *sent_by = NULL; 3692882Svi117747 3702882Svi117747 via = (sip_header_t)sip_get_header(sip_msg, SIP_VIA, NULL, &error); 3712882Svi117747 if (via == NULL || error != 0) 3722882Svi117747 return (B_TRUE); 3732882Svi117747 value = (sip_header_value_t)sip_get_header_value(via, &error); 3742882Svi117747 if (value == NULL || error != 0) 3752882Svi117747 return (B_TRUE); 3762882Svi117747 sent_by = sip_get_via_sent_by_host(value, &error); 3772882Svi117747 if (sent_by == NULL || error != 0) 3782882Svi117747 return (B_TRUE); 3792882Svi117747 if (sip_sent_by_registered(sent_by)) 3802882Svi117747 return (B_TRUE); 3812882Svi117747 return (B_FALSE); 3822882Svi117747 } 3832882Svi117747 3842882Svi117747 3852882Svi117747 /* 3862882Svi117747 * The receive interface to the transport layer. 3872882Svi117747 */ 3882882Svi117747 void 3892882Svi117747 sip_process_new_packet(sip_conn_object_t conn_object, void *msgstr, 3902882Svi117747 size_t msglen) 3912882Svi117747 { 3922882Svi117747 _sip_msg_t *sip_msg; 3932882Svi117747 sip_message_type_t *sip_msg_info; 3942882Svi117747 sip_xaction_t *sip_trans; 3952882Svi117747 sip_dialog_t dialog = NULL; 3962882Svi117747 boolean_t dialog_created = B_FALSE; 3972882Svi117747 int transport; 3982882Svi117747 char *msgbuf = NULL; 3992882Svi117747 4002882Svi117747 sip_refhold_conn(conn_object); 4012882Svi117747 transport = sip_conn_transport(conn_object); 4022882Svi117747 if (transport == IPPROTO_TCP) { 4032882Svi117747 next_msg: 4042882Svi117747 msgstr = (char *)sip_get_tcp_msg(conn_object, (char *)msgstr, 4052882Svi117747 &msglen); 4062882Svi117747 if (msgstr == NULL) { 4072882Svi117747 sip_refrele_conn(conn_object); 4082882Svi117747 return; 4092882Svi117747 } 4102882Svi117747 } else { 4112882Svi117747 msgbuf = (char *)malloc(msglen + 1); 4122882Svi117747 if (msgbuf == NULL) { 4132882Svi117747 sip_refrele_conn(conn_object); 4142882Svi117747 return; 4152882Svi117747 } 4162882Svi117747 (void) strncpy(msgbuf, msgstr, msglen); 4172882Svi117747 msgbuf[msglen] = '\0'; 4182882Svi117747 msgstr = msgbuf; 4192882Svi117747 } 4202882Svi117747 sip_msg = (_sip_msg_t *)sip_new_msg(); 4212882Svi117747 if (sip_msg == NULL) { 4222882Svi117747 if (msgbuf != NULL) 4232882Svi117747 free(msgbuf); 4242882Svi117747 sip_refrele_conn(conn_object); 4252882Svi117747 return; 4262882Svi117747 } 4272882Svi117747 sip_msg->sip_msg_buf = (char *)msgstr; 4282882Svi117747 sip_msg->sip_msg_len = msglen; 4292882Svi117747 (void) pthread_mutex_lock(&sip_msg->sip_msg_mutex); 4302882Svi117747 if (sip_setup_header_pointers(sip_msg) != 0) { 4312882Svi117747 (void) pthread_mutex_unlock(&sip_msg->sip_msg_mutex); 4322882Svi117747 sip_refrele_conn(conn_object); 4332882Svi117747 sip_free_msg((sip_msg_t)sip_msg); 4342882Svi117747 return; 4352882Svi117747 } 4362882Svi117747 if (sip_parse_first_line(sip_msg->sip_msg_start_line, 4372882Svi117747 &sip_msg->sip_msg_req_res)) { 4382882Svi117747 (void) pthread_mutex_unlock(&sip_msg->sip_msg_mutex); 4392882Svi117747 sip_refrele_conn(conn_object); 4402882Svi117747 sip_free_msg((sip_msg_t)sip_msg); 4412882Svi117747 return; 4422882Svi117747 } 4432882Svi117747 sip_msg_info = sip_msg->sip_msg_req_res; 4442882Svi117747 (void) pthread_mutex_unlock(&sip_msg->sip_msg_mutex); 4452882Svi117747 4462882Svi117747 if (sip_check_common_headers(conn_object, sip_msg)) { 4472882Svi117747 sip_refrele_conn(conn_object); 4482882Svi117747 sip_free_msg((sip_msg_t)sip_msg); 4492882Svi117747 return; 4502882Svi117747 } 4512882Svi117747 4522882Svi117747 /* 4532882Svi117747 * Silently discard the response if the top VIA has a sent-by value AND 4542882Svi117747 * the UA has registered sent-by values AND the one in the VIA is 4552882Svi117747 * not part of the registerd sent-by values. 4562882Svi117747 */ 4572882Svi117747 if (!sip_msg_info->is_request && !sip_valid_sent_by(sip_msg)) { 4582882Svi117747 sip_refrele_conn(conn_object); 4592882Svi117747 sip_free_msg((sip_msg_t)sip_msg); 4602882Svi117747 return; 4612882Svi117747 4622882Svi117747 } 4632882Svi117747 sip_trans = (sip_xaction_t *)sip_xaction_get(conn_object, 4642882Svi117747 (sip_msg_t)sip_msg, 4652882Svi117747 B_FALSE, sip_msg_info->is_request ? SIP_SERVER_TRANSACTION : 4662882Svi117747 SIP_CLIENT_TRANSACTION, NULL); 4672882Svi117747 if (sip_trans != NULL) { 4682882Svi117747 if (sip_xaction_input(conn_object, sip_trans, &sip_msg) != 0) { 4692882Svi117747 SIP_XACTION_REFCNT_DECR(sip_trans); 4702882Svi117747 sip_refrele_conn(conn_object); 4712882Svi117747 sip_free_msg((sip_msg_t)sip_msg); 4722882Svi117747 return; 4732882Svi117747 } 4742882Svi117747 SIP_XACTION_REFCNT_DECR(sip_trans); 4752882Svi117747 4762882Svi117747 /* 4772882Svi117747 * msg was retransmission - handled by the transaction 4782882Svi117747 */ 4792882Svi117747 if (sip_msg == NULL) 4802882Svi117747 goto check_next; 4812882Svi117747 } else { 4822882Svi117747 /* 4832882Svi117747 * If we are getting an INVITE request, let us send a 4842882Svi117747 * 100 TRYING response here, as in 17.2.1: 4852882Svi117747 * "The server transaction MUST generate a 100 (Trying) 4862882Svi117747 * response unless it knows that the TU will generate a 4872882Svi117747 * provisional or final response within 200 ms". 4882882Svi117747 */ 4892882Svi117747 if (sip_msg_info->is_request && 4902882Svi117747 sip_msg_info->sip_req_method == INVITE) { 4912882Svi117747 sip_send_resp(conn_object, sip_msg, SIP_TRYING); 4922882Svi117747 } 4932882Svi117747 } 4942882Svi117747 if (sip_manage_dialog) { 4952882Svi117747 dialog = sip_dialog_find(sip_msg); 4962882Svi117747 if (dialog == NULL) { 4972882Svi117747 if (sip_msg_info->is_request) { 4982882Svi117747 /* 4992882Svi117747 * sip_seed_dialog will check for the 5002882Svi117747 * method in the request 5012882Svi117747 */ 5022882Svi117747 dialog = (sip_dialog_t)sip_seed_dialog( 5032882Svi117747 conn_object, sip_msg, 5042882Svi117747 B_FALSE, SIP_UAS_DIALOG); 5052882Svi117747 dialog_created = B_TRUE; 5062882Svi117747 } 5072882Svi117747 } else if (sip_incomplete_dialog(dialog)) { 5082882Svi117747 if (!sip_msg_info->is_request || 5092882Svi117747 sip_msg_info->sip_req_method == NOTIFY) { 5102882Svi117747 dialog = sip_update_dialog(dialog, sip_msg); 5112882Svi117747 } 5122882Svi117747 } else if (sip_dialog_process(sip_msg, &dialog) != 0) { 5132882Svi117747 if (dialog != NULL) 5142882Svi117747 sip_release_dialog(dialog); 5152882Svi117747 /* 5162882Svi117747 * cseq number in error, send a 5172882Svi117747 * SIP_SERVER_INTERNAL_ERROR response. 5182882Svi117747 */ 5192882Svi117747 if (sip_msg_info->is_request) { 5202882Svi117747 sip_send_resp(conn_object, sip_msg, 5212882Svi117747 SIP_SERVER_INTERNAL_ERROR); 5222882Svi117747 } 5232882Svi117747 sip_refrele_conn(conn_object); 5242882Svi117747 sip_free_msg((sip_msg_t)sip_msg); 5252882Svi117747 return; 5262882Svi117747 } 5272882Svi117747 } 5282882Svi117747 sip_ulp_recv(conn_object, (sip_msg_t)sip_msg, dialog); 5292882Svi117747 sip_free_msg((sip_msg_t)sip_msg); 5302882Svi117747 if (dialog != NULL && !dialog_created) 5312882Svi117747 sip_release_dialog(dialog); 5322882Svi117747 check_next: 5332882Svi117747 /* 5342882Svi117747 * Check if there are more complete messages in the TCP fragment list 5352882Svi117747 * to be consumed 5362882Svi117747 */ 5372882Svi117747 if (transport == IPPROTO_TCP) { 5382882Svi117747 msgstr = NULL; 5392882Svi117747 msglen = 0; 5402882Svi117747 goto next_msg; 5412882Svi117747 } 5422882Svi117747 sip_refrele_conn(conn_object); 5432882Svi117747 } 5442882Svi117747 5452882Svi117747 /* 5462882Svi117747 * Initialize the stack. The connection manager functions, upper layer 5472882Svi117747 * receive functions are mandatory. 5482882Svi117747 */ 5492882Svi117747 int 5502882Svi117747 sip_stack_init(sip_stack_init_t *stack_val) 5512882Svi117747 { 5522882Svi117747 #ifdef __linux__ 5532882Svi117747 struct timespec tspec; 5542882Svi117747 #endif 5552882Svi117747 5562882Svi117747 /* 5572882Svi117747 * If the stack has already been configured, return error 5582882Svi117747 */ 5592882Svi117747 if (sip_stack_send != NULL || 5602882Svi117747 stack_val->sip_version != SIP_STACK_VERSION) { 5612882Svi117747 return (EINVAL); 5622882Svi117747 } 5632882Svi117747 if (stack_val->sip_io_pointers == NULL || 5642882Svi117747 stack_val->sip_ulp_pointers == NULL) { 5652882Svi117747 return (EINVAL); 5662882Svi117747 } 5672882Svi117747 sip_ulp_recv = stack_val->sip_ulp_pointers->sip_ulp_recv; 5682882Svi117747 sip_manage_dialog = stack_val->sip_stack_flags & SIP_STACK_DIALOGS; 5692882Svi117747 5702882Svi117747 sip_stack_send = stack_val->sip_io_pointers->sip_conn_send; 5712882Svi117747 sip_refhold_conn = stack_val->sip_io_pointers->sip_hold_conn_object; 5722882Svi117747 sip_refrele_conn = stack_val->sip_io_pointers->sip_rel_conn_object; 5732882Svi117747 sip_is_conn_stream = stack_val->sip_io_pointers->sip_conn_is_stream; 5742882Svi117747 sip_is_conn_reliable = stack_val->sip_io_pointers->sip_conn_is_reliable; 5752882Svi117747 sip_conn_rem_addr = stack_val->sip_io_pointers->sip_conn_remote_address; 5762882Svi117747 sip_conn_local_addr = 5772882Svi117747 stack_val->sip_io_pointers->sip_conn_local_address; 5782882Svi117747 sip_conn_transport = stack_val->sip_io_pointers->sip_conn_transport; 5792882Svi117747 sip_header_function_table_external = stack_val->sip_function_table; 5802882Svi117747 5812882Svi117747 if (sip_ulp_recv == NULL || sip_stack_send == NULL || 5822882Svi117747 sip_refhold_conn == NULL || sip_refrele_conn == NULL || 5832882Svi117747 sip_is_conn_stream == NULL || sip_is_conn_reliable == NULL || 5842882Svi117747 sip_conn_rem_addr == NULL || sip_conn_local_addr == NULL || 5852882Svi117747 sip_conn_transport == NULL) { 5862882Svi117747 err_ret: 5872882Svi117747 sip_ulp_recv = NULL; 5882882Svi117747 sip_stack_send = NULL; 5892882Svi117747 sip_refhold_conn = NULL; 5902882Svi117747 sip_refrele_conn = NULL; 5912882Svi117747 sip_is_conn_stream = NULL; 5922882Svi117747 sip_is_conn_reliable = NULL; 5932882Svi117747 sip_conn_rem_addr = NULL; 5942882Svi117747 sip_conn_local_addr = NULL; 5952882Svi117747 sip_conn_transport = NULL; 5962882Svi117747 sip_header_function_table_external = NULL; 5972882Svi117747 sip_stack_timeout = NULL; 5982882Svi117747 sip_stack_untimeout = NULL; 5992882Svi117747 return (EINVAL); 6002882Svi117747 } 6012882Svi117747 6022882Svi117747 sip_conn_timer1 = stack_val->sip_io_pointers->sip_conn_timer1; 6032882Svi117747 sip_conn_timer2 = stack_val->sip_io_pointers->sip_conn_timer2; 6042882Svi117747 sip_conn_timer4 = stack_val->sip_io_pointers->sip_conn_timer4; 6052882Svi117747 sip_conn_timerd = stack_val->sip_io_pointers->sip_conn_timerd; 6062882Svi117747 6072882Svi117747 /* 6082882Svi117747 * Use Appln timeout routines, if provided 6092882Svi117747 */ 6102882Svi117747 if (stack_val->sip_ulp_pointers->sip_ulp_timeout != NULL) { 6112882Svi117747 if (stack_val->sip_ulp_pointers->sip_ulp_untimeout == NULL) 6122882Svi117747 goto err_ret; 6132882Svi117747 sip_stack_timeout = 6142882Svi117747 stack_val->sip_ulp_pointers->sip_ulp_timeout; 6152882Svi117747 sip_stack_untimeout = 6162882Svi117747 stack_val->sip_ulp_pointers->sip_ulp_untimeout; 6172882Svi117747 } else { 6182882Svi117747 if (stack_val->sip_ulp_pointers->sip_ulp_untimeout != NULL) 6192882Svi117747 goto err_ret; 6202882Svi117747 sip_timeout_init(); 6212882Svi117747 sip_stack_timeout = sip_timeout; 6222882Svi117747 sip_stack_untimeout = sip_untimeout; 6232882Svi117747 } 6242882Svi117747 6252882Svi117747 /* 6262882Svi117747 * Manage Dialogs? 6272882Svi117747 */ 6282882Svi117747 if (sip_manage_dialog) { 6292882Svi117747 sip_dialog_init(stack_val->sip_ulp_pointers->sip_ulp_dlg_del, 6302882Svi117747 stack_val->sip_ulp_pointers->sip_ulp_dlg_state_cb); 6312882Svi117747 } 6322882Svi117747 sip_xaction_init(stack_val->sip_ulp_pointers->sip_ulp_trans_error, 6332882Svi117747 stack_val->sip_ulp_pointers->sip_ulp_trans_state_cb); 6342882Svi117747 6352882Svi117747 #ifdef __linux__ 6362882Svi117747 if (clock_gettime(CLOCK_REALTIME, &tspec) != 0) 6372882Svi117747 goto err_ret; 6382882Svi117747 sip_hash_salt = tspec.tv_nsec; 6392882Svi117747 #else 6402882Svi117747 sip_hash_salt = gethrtime(); 6412882Svi117747 #endif 6422882Svi117747 (void) pthread_mutex_init(&sip_sent_by_lock, NULL); 6432882Svi117747 return (0); 6442882Svi117747 } 645