1*0Sstevel@tonic-gate /* 2*0Sstevel@tonic-gate * CDDL HEADER START 3*0Sstevel@tonic-gate * 4*0Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*0Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*0Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*0Sstevel@tonic-gate * with the License. 8*0Sstevel@tonic-gate * 9*0Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*0Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*0Sstevel@tonic-gate * See the License for the specific language governing permissions 12*0Sstevel@tonic-gate * and limitations under the License. 13*0Sstevel@tonic-gate * 14*0Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*0Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*0Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*0Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*0Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*0Sstevel@tonic-gate * 20*0Sstevel@tonic-gate * CDDL HEADER END 21*0Sstevel@tonic-gate */ 22*0Sstevel@tonic-gate /* 23*0Sstevel@tonic-gate * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24*0Sstevel@tonic-gate * Use is subject to license terms. 25*0Sstevel@tonic-gate */ 26*0Sstevel@tonic-gate 27*0Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*0Sstevel@tonic-gate 29*0Sstevel@tonic-gate #include <sys/types.h> 30*0Sstevel@tonic-gate #include <sys/stream.h> 31*0Sstevel@tonic-gate #include <sys/strsubr.h> 32*0Sstevel@tonic-gate #include <sys/stropts.h> 33*0Sstevel@tonic-gate #include <sys/strsun.h> 34*0Sstevel@tonic-gate #define _SUN_TPI_VERSION 2 35*0Sstevel@tonic-gate #include <sys/tihdr.h> 36*0Sstevel@tonic-gate #include <sys/ddi.h> 37*0Sstevel@tonic-gate #include <sys/sunddi.h> 38*0Sstevel@tonic-gate #include <sys/xti_inet.h> 39*0Sstevel@tonic-gate #include <sys/cmn_err.h> 40*0Sstevel@tonic-gate #include <sys/debug.h> 41*0Sstevel@tonic-gate #include <sys/vtrace.h> 42*0Sstevel@tonic-gate #include <sys/kmem.h> 43*0Sstevel@tonic-gate #include <sys/cpuvar.h> 44*0Sstevel@tonic-gate #include <sys/random.h> 45*0Sstevel@tonic-gate 46*0Sstevel@tonic-gate #include <sys/errno.h> 47*0Sstevel@tonic-gate #include <sys/signal.h> 48*0Sstevel@tonic-gate #include <sys/socket.h> 49*0Sstevel@tonic-gate #include <sys/isa_defs.h> 50*0Sstevel@tonic-gate #include <netinet/in.h> 51*0Sstevel@tonic-gate #include <netinet/tcp.h> 52*0Sstevel@tonic-gate #include <netinet/ip6.h> 53*0Sstevel@tonic-gate #include <netinet/icmp6.h> 54*0Sstevel@tonic-gate #include <netinet/sctp.h> 55*0Sstevel@tonic-gate #include <net/if.h> 56*0Sstevel@tonic-gate 57*0Sstevel@tonic-gate #include <inet/common.h> 58*0Sstevel@tonic-gate #include <inet/ip.h> 59*0Sstevel@tonic-gate #include <inet/ip6.h> 60*0Sstevel@tonic-gate #include <inet/mi.h> 61*0Sstevel@tonic-gate #include <inet/mib2.h> 62*0Sstevel@tonic-gate #include <inet/nd.h> 63*0Sstevel@tonic-gate #include <inet/optcom.h> 64*0Sstevel@tonic-gate #include <inet/ipclassifier.h> 65*0Sstevel@tonic-gate #include <inet/ipsec_impl.h> 66*0Sstevel@tonic-gate #include <inet/sctp_ip.h> 67*0Sstevel@tonic-gate #include <inet/sctp_crc32.h> 68*0Sstevel@tonic-gate 69*0Sstevel@tonic-gate #include "sctp_impl.h" 70*0Sstevel@tonic-gate #include "sctp_addr.h" 71*0Sstevel@tonic-gate 72*0Sstevel@tonic-gate extern major_t SCTP6_MAJ; 73*0Sstevel@tonic-gate extern major_t SCTP_MAJ; 74*0Sstevel@tonic-gate 75*0Sstevel@tonic-gate int sctpdebug; 76*0Sstevel@tonic-gate sin6_t sctp_sin6_null; /* Zero address for quick clears */ 77*0Sstevel@tonic-gate 78*0Sstevel@tonic-gate extern mblk_t *sctp_pad_mp; /* pad unaligned data chunks */ 79*0Sstevel@tonic-gate 80*0Sstevel@tonic-gate static void sctp_closei_local(sctp_t *sctp); 81*0Sstevel@tonic-gate static int sctp_init_values(sctp_t *, sctp_t *, int); 82*0Sstevel@tonic-gate void sctp_display_all(); 83*0Sstevel@tonic-gate static void sctp_icmp_error_ipv6(sctp_t *sctp, mblk_t *mp); 84*0Sstevel@tonic-gate static void sctp_process_recvq(void *); 85*0Sstevel@tonic-gate static void sctp_rq_tq_init(void); 86*0Sstevel@tonic-gate static void sctp_rq_tq_fini(void); 87*0Sstevel@tonic-gate static void sctp_conn_cache_init(); 88*0Sstevel@tonic-gate static void sctp_conn_cache_fini(); 89*0Sstevel@tonic-gate static int sctp_conn_cache_constructor(); 90*0Sstevel@tonic-gate static void sctp_conn_cache_destructor(); 91*0Sstevel@tonic-gate void sctp_inc_taskq(void); 92*0Sstevel@tonic-gate 93*0Sstevel@tonic-gate /* 94*0Sstevel@tonic-gate * SCTP receive queue taskq 95*0Sstevel@tonic-gate * 96*0Sstevel@tonic-gate * At SCTP initialization time, a default taskq is created for 97*0Sstevel@tonic-gate * servicing packets received when the interrupt thread cannot 98*0Sstevel@tonic-gate * get a hold on the sctp_t. The number of taskq can be increased in 99*0Sstevel@tonic-gate * sctp_find_next_tq() when an existing taskq cannot be dispatched. 100*0Sstevel@tonic-gate * The taskqs are never removed. But the max number of taskq which 101*0Sstevel@tonic-gate * can be created is controlled by sctp_recvq_tq_list_max_sz. Note 102*0Sstevel@tonic-gate * that SCTP recvq taskq is not tied to any specific CPU or ill. 103*0Sstevel@tonic-gate * 104*0Sstevel@tonic-gate * Those taskqs are stored in an array recvq_tq_list. And they are 105*0Sstevel@tonic-gate * used in a round robin fashion. The current taskq being used is 106*0Sstevel@tonic-gate * determined by recvq_tq_list_cur. 107*0Sstevel@tonic-gate */ 108*0Sstevel@tonic-gate 109*0Sstevel@tonic-gate /* This lock protects the SCTP recvq_tq_list array and recvq_tq_list_cur_sz. */ 110*0Sstevel@tonic-gate static kmutex_t sctp_rq_tq_lock; 111*0Sstevel@tonic-gate int sctp_recvq_tq_list_max_sz = 16; 112*0Sstevel@tonic-gate static taskq_t **recvq_tq_list; 113*0Sstevel@tonic-gate 114*0Sstevel@tonic-gate /* Current number of recvq taskq. At least 1 for the default taskq. */ 115*0Sstevel@tonic-gate static uint32_t recvq_tq_list_cur_sz = 1; 116*0Sstevel@tonic-gate static uint32_t recvq_tq_list_cur = 0; 117*0Sstevel@tonic-gate 118*0Sstevel@tonic-gate /* The minimum number of threads for each taskq. */ 119*0Sstevel@tonic-gate int sctp_recvq_tq_thr_min = 4; 120*0Sstevel@tonic-gate /* The maximum number of threads for each taskq. */ 121*0Sstevel@tonic-gate int sctp_recvq_tq_thr_max = 16; 122*0Sstevel@tonic-gate /* The minimum number of tasks for each taskq. */ 123*0Sstevel@tonic-gate int sctp_recvq_tq_task_min = 5; 124*0Sstevel@tonic-gate /* The maxiimum number of tasks for each taskq. */ 125*0Sstevel@tonic-gate int sctp_recvq_tq_task_max = 50; 126*0Sstevel@tonic-gate 127*0Sstevel@tonic-gate /* 128*0Sstevel@tonic-gate * Default queue used for sending packets. No need to have lock for it 129*0Sstevel@tonic-gate * as it should never be changed. 130*0Sstevel@tonic-gate */ 131*0Sstevel@tonic-gate queue_t *sctp_g_q; 132*0Sstevel@tonic-gate int sctp_g_q_fd; 133*0Sstevel@tonic-gate /* The default sctp_t for responding out of the blue packets. */ 134*0Sstevel@tonic-gate sctp_t *gsctp; 135*0Sstevel@tonic-gate 136*0Sstevel@tonic-gate /* Protected by sctp_g_lock */ 137*0Sstevel@tonic-gate list_t sctp_g_list; /* SCTP instance data chain */ 138*0Sstevel@tonic-gate kmutex_t sctp_g_lock; 139*0Sstevel@tonic-gate 140*0Sstevel@tonic-gate /* sctp_t/conn_t kmem cache */ 141*0Sstevel@tonic-gate struct kmem_cache *sctp_conn_cache; 142*0Sstevel@tonic-gate 143*0Sstevel@tonic-gate #define SCTP_CONDEMNED(sctp) \ 144*0Sstevel@tonic-gate mutex_enter(&(sctp)->sctp_reflock); \ 145*0Sstevel@tonic-gate ((sctp)->sctp_condemned = B_TRUE); \ 146*0Sstevel@tonic-gate mutex_exit(&(sctp)->sctp_reflock); \ 147*0Sstevel@tonic-gate 148*0Sstevel@tonic-gate /* Link/unlink a sctp_t to/from the global list. */ 149*0Sstevel@tonic-gate #define SCTP_LINK(sctp) \ 150*0Sstevel@tonic-gate mutex_enter(&sctp_g_lock); \ 151*0Sstevel@tonic-gate list_insert_tail(&sctp_g_list, (sctp)); \ 152*0Sstevel@tonic-gate mutex_exit(&sctp_g_lock); 153*0Sstevel@tonic-gate 154*0Sstevel@tonic-gate #define SCTP_UNLINK(sctp) \ 155*0Sstevel@tonic-gate mutex_enter(&sctp_g_lock); \ 156*0Sstevel@tonic-gate ASSERT((sctp)->sctp_condemned); \ 157*0Sstevel@tonic-gate list_remove(&sctp_g_list, (sctp)); \ 158*0Sstevel@tonic-gate mutex_exit(&sctp_g_lock); 159*0Sstevel@tonic-gate 160*0Sstevel@tonic-gate /* 161*0Sstevel@tonic-gate * Return the version number of the SCTP kernel interface. 162*0Sstevel@tonic-gate */ 163*0Sstevel@tonic-gate int 164*0Sstevel@tonic-gate sctp_itf_ver(int cl_ver) 165*0Sstevel@tonic-gate { 166*0Sstevel@tonic-gate if (cl_ver != SCTP_ITF_VER) 167*0Sstevel@tonic-gate return (-1); 168*0Sstevel@tonic-gate return (SCTP_ITF_VER); 169*0Sstevel@tonic-gate } 170*0Sstevel@tonic-gate 171*0Sstevel@tonic-gate /* 172*0Sstevel@tonic-gate * Called when we need a new sctp instantiation but don't really have a 173*0Sstevel@tonic-gate * new q to hang it off of. Copy the priv flag from the passed in structure. 174*0Sstevel@tonic-gate */ 175*0Sstevel@tonic-gate sctp_t * 176*0Sstevel@tonic-gate sctp_create_eager(sctp_t *psctp) 177*0Sstevel@tonic-gate { 178*0Sstevel@tonic-gate sctp_t *sctp; 179*0Sstevel@tonic-gate mblk_t *ack_mp, *hb_mp; 180*0Sstevel@tonic-gate conn_t *connp, *pconnp; 181*0Sstevel@tonic-gate 182*0Sstevel@tonic-gate if ((connp = ipcl_conn_create(IPCL_SCTPCONN, KM_NOSLEEP)) == NULL) 183*0Sstevel@tonic-gate return (NULL); 184*0Sstevel@tonic-gate sctp = CONN2SCTP(connp); 185*0Sstevel@tonic-gate 186*0Sstevel@tonic-gate if ((ack_mp = sctp_timer_alloc(sctp, sctp_ack_timer)) == NULL || 187*0Sstevel@tonic-gate (hb_mp = sctp_timer_alloc(sctp, sctp_heartbeat_timer)) == NULL) { 188*0Sstevel@tonic-gate if (ack_mp != NULL) 189*0Sstevel@tonic-gate freeb(ack_mp); 190*0Sstevel@tonic-gate kmem_cache_free(sctp_conn_cache, connp); 191*0Sstevel@tonic-gate return (NULL); 192*0Sstevel@tonic-gate } 193*0Sstevel@tonic-gate 194*0Sstevel@tonic-gate sctp->sctp_ack_mp = ack_mp; 195*0Sstevel@tonic-gate sctp->sctp_heartbeat_mp = hb_mp; 196*0Sstevel@tonic-gate 197*0Sstevel@tonic-gate /* Inherit information from the "parent" */ 198*0Sstevel@tonic-gate sctp->sctp_ipversion = psctp->sctp_ipversion; 199*0Sstevel@tonic-gate sctp->sctp_family = psctp->sctp_family; 200*0Sstevel@tonic-gate pconnp = psctp->sctp_connp; 201*0Sstevel@tonic-gate connp->conn_af_isv6 = pconnp->conn_af_isv6; 202*0Sstevel@tonic-gate connp->conn_pkt_isv6 = pconnp->conn_pkt_isv6; 203*0Sstevel@tonic-gate connp->conn_ipv6_v6only = pconnp->conn_ipv6_v6only; 204*0Sstevel@tonic-gate if (sctp_init_values(sctp, psctp, KM_NOSLEEP) != 0) { 205*0Sstevel@tonic-gate freeb(ack_mp); 206*0Sstevel@tonic-gate freeb(hb_mp); 207*0Sstevel@tonic-gate kmem_cache_free(sctp_conn_cache, connp); 208*0Sstevel@tonic-gate return (NULL); 209*0Sstevel@tonic-gate } 210*0Sstevel@tonic-gate if (pconnp->conn_cred != NULL) { 211*0Sstevel@tonic-gate connp->conn_cred = pconnp->conn_cred; 212*0Sstevel@tonic-gate crhold(connp->conn_cred); 213*0Sstevel@tonic-gate } 214*0Sstevel@tonic-gate connp->conn_zoneid = psctp->sctp_zoneid; 215*0Sstevel@tonic-gate sctp->sctp_mss = psctp->sctp_mss; 216*0Sstevel@tonic-gate sctp->sctp_detached = B_TRUE; 217*0Sstevel@tonic-gate /* 218*0Sstevel@tonic-gate * Link to the global as soon as possible so that this sctp_t 219*0Sstevel@tonic-gate * can be found. 220*0Sstevel@tonic-gate */ 221*0Sstevel@tonic-gate SCTP_LINK(sctp); 222*0Sstevel@tonic-gate 223*0Sstevel@tonic-gate return (sctp); 224*0Sstevel@tonic-gate } 225*0Sstevel@tonic-gate 226*0Sstevel@tonic-gate /* 227*0Sstevel@tonic-gate * We are dying for some reason. Try to do it gracefully. 228*0Sstevel@tonic-gate */ 229*0Sstevel@tonic-gate void 230*0Sstevel@tonic-gate sctp_clean_death(sctp_t *sctp, int err) 231*0Sstevel@tonic-gate { 232*0Sstevel@tonic-gate ASSERT(sctp != NULL); 233*0Sstevel@tonic-gate ASSERT((sctp->sctp_family == AF_INET && 234*0Sstevel@tonic-gate sctp->sctp_ipversion == IPV4_VERSION) || 235*0Sstevel@tonic-gate (sctp->sctp_family == AF_INET6 && 236*0Sstevel@tonic-gate (sctp->sctp_ipversion == IPV4_VERSION || 237*0Sstevel@tonic-gate sctp->sctp_ipversion == IPV6_VERSION))); 238*0Sstevel@tonic-gate 239*0Sstevel@tonic-gate dprint(3, ("sctp_clean_death %p, state %d\n", sctp, sctp->sctp_state)); 240*0Sstevel@tonic-gate 241*0Sstevel@tonic-gate sctp->sctp_client_errno = err; 242*0Sstevel@tonic-gate /* 243*0Sstevel@tonic-gate * Check to see if we need to notify upper layer. 244*0Sstevel@tonic-gate */ 245*0Sstevel@tonic-gate if ((sctp->sctp_state >= SCTPS_COOKIE_WAIT) && 246*0Sstevel@tonic-gate !SCTP_IS_DETACHED(sctp)) { 247*0Sstevel@tonic-gate if (sctp->sctp_xmit_head || sctp->sctp_xmit_unsent) { 248*0Sstevel@tonic-gate sctp_regift_xmitlist(sctp); 249*0Sstevel@tonic-gate } 250*0Sstevel@tonic-gate if (sctp->sctp_ulp_disconnected(sctp->sctp_ulpd, err)) { 251*0Sstevel@tonic-gate /* 252*0Sstevel@tonic-gate * Socket is gone, detach. 253*0Sstevel@tonic-gate */ 254*0Sstevel@tonic-gate sctp->sctp_detached = B_TRUE; 255*0Sstevel@tonic-gate sctp->sctp_ulpd = NULL; 256*0Sstevel@tonic-gate bzero(&sctp->sctp_upcalls, sizeof (sctp_upcalls_t)); 257*0Sstevel@tonic-gate } 258*0Sstevel@tonic-gate } 259*0Sstevel@tonic-gate 260*0Sstevel@tonic-gate /* Remove this sctp from all hashes. */ 261*0Sstevel@tonic-gate sctp_closei_local(sctp); 262*0Sstevel@tonic-gate 263*0Sstevel@tonic-gate /* 264*0Sstevel@tonic-gate * If the sctp_t is detached, we need to finish freeing up 265*0Sstevel@tonic-gate * the resources. At this point, ip_fanout_sctp() should have 266*0Sstevel@tonic-gate * a hold on this sctp_t. Some thread doing snmp stuff can 267*0Sstevel@tonic-gate * have a hold. And a taskq can also have a hold waiting to 268*0Sstevel@tonic-gate * work. sctp_unlink() the sctp_t from the global list so 269*0Sstevel@tonic-gate * that no new thread can find it. Then do a SCTP_REFRELE(). 270*0Sstevel@tonic-gate * The sctp_t will be freed after all those threads are done. 271*0Sstevel@tonic-gate */ 272*0Sstevel@tonic-gate if (SCTP_IS_DETACHED(sctp)) { 273*0Sstevel@tonic-gate SCTP_CONDEMNED(sctp); 274*0Sstevel@tonic-gate SCTP_REFRELE(sctp); 275*0Sstevel@tonic-gate } 276*0Sstevel@tonic-gate } 277*0Sstevel@tonic-gate 278*0Sstevel@tonic-gate /* 279*0Sstevel@tonic-gate * Called by upper layer when it wants to close this association. 280*0Sstevel@tonic-gate * Depending on the state of this assoication, we need to do 281*0Sstevel@tonic-gate * different things. 282*0Sstevel@tonic-gate * 283*0Sstevel@tonic-gate * If the state is below COOKIE_ECHOED or it is COOKIE_ECHOED but with 284*0Sstevel@tonic-gate * no sent data, just remove this sctp from all the hashes. This 285*0Sstevel@tonic-gate * makes sure that all packets from the other end will go to the default 286*0Sstevel@tonic-gate * sctp handling. The upper layer will then do a sctp_close() to clean 287*0Sstevel@tonic-gate * up. 288*0Sstevel@tonic-gate * 289*0Sstevel@tonic-gate * Otherwise, check and see if SO_LINGER is set. If it is set, check 290*0Sstevel@tonic-gate * the value. If the value is 0, consider this an abortive close. Send 291*0Sstevel@tonic-gate * an ABORT message and kill the associatiion. 292*0Sstevel@tonic-gate * 293*0Sstevel@tonic-gate */ 294*0Sstevel@tonic-gate int 295*0Sstevel@tonic-gate sctp_disconnect(sctp_t *sctp) 296*0Sstevel@tonic-gate { 297*0Sstevel@tonic-gate int error = 0; 298*0Sstevel@tonic-gate sctp_faddr_t *fp; 299*0Sstevel@tonic-gate 300*0Sstevel@tonic-gate dprint(3, ("sctp_disconnect %p, state %d\n", sctp, sctp->sctp_state)); 301*0Sstevel@tonic-gate 302*0Sstevel@tonic-gate RUN_SCTP(sctp); 303*0Sstevel@tonic-gate 304*0Sstevel@tonic-gate switch (sctp->sctp_state) { 305*0Sstevel@tonic-gate case SCTPS_IDLE: 306*0Sstevel@tonic-gate case SCTPS_BOUND: 307*0Sstevel@tonic-gate case SCTPS_LISTEN: 308*0Sstevel@tonic-gate break; 309*0Sstevel@tonic-gate case SCTPS_COOKIE_WAIT: 310*0Sstevel@tonic-gate case SCTPS_COOKIE_ECHOED: 311*0Sstevel@tonic-gate /* 312*0Sstevel@tonic-gate * Close during the connect 3-way handshake 313*0Sstevel@tonic-gate * but here there may or may not be pending data 314*0Sstevel@tonic-gate * already on queue. Process almost same as in 315*0Sstevel@tonic-gate * the ESTABLISHED state. 316*0Sstevel@tonic-gate */ 317*0Sstevel@tonic-gate if (sctp->sctp_xmit_head == NULL && 318*0Sstevel@tonic-gate sctp->sctp_xmit_unsent == NULL) { 319*0Sstevel@tonic-gate break; 320*0Sstevel@tonic-gate } 321*0Sstevel@tonic-gate /* FALLTHRU */ 322*0Sstevel@tonic-gate default: 323*0Sstevel@tonic-gate /* 324*0Sstevel@tonic-gate * If SO_LINGER has set a zero linger time, abort the 325*0Sstevel@tonic-gate * connection with a reset. 326*0Sstevel@tonic-gate */ 327*0Sstevel@tonic-gate if (sctp->sctp_linger && sctp->sctp_lingertime == 0) { 328*0Sstevel@tonic-gate sctp_user_abort(sctp, NULL, B_FALSE); 329*0Sstevel@tonic-gate break; 330*0Sstevel@tonic-gate } 331*0Sstevel@tonic-gate 332*0Sstevel@tonic-gate /* 333*0Sstevel@tonic-gate * Transmit the shutdown before detaching the sctp_t. 334*0Sstevel@tonic-gate * After sctp_detach returns this queue/perimeter 335*0Sstevel@tonic-gate * no longer owns the sctp_t thus others can modify it. 336*0Sstevel@tonic-gate */ 337*0Sstevel@tonic-gate sctp_send_shutdown(sctp, 0); 338*0Sstevel@tonic-gate 339*0Sstevel@tonic-gate /* Pass gathered wisdom to IP for keeping */ 340*0Sstevel@tonic-gate for (fp = sctp->sctp_faddrs; fp != NULL; fp = fp->next) 341*0Sstevel@tonic-gate sctp_faddr2ire(sctp, fp); 342*0Sstevel@tonic-gate 343*0Sstevel@tonic-gate /* 344*0Sstevel@tonic-gate * If lingering on close then wait until the shutdown 345*0Sstevel@tonic-gate * is complete, or the SO_LINGER time passes, or an 346*0Sstevel@tonic-gate * ABORT is sent/received. Note that sctp_disconnect() 347*0Sstevel@tonic-gate * can be called more than once. Make sure that only 348*0Sstevel@tonic-gate * one thread waits. 349*0Sstevel@tonic-gate */ 350*0Sstevel@tonic-gate if (sctp->sctp_linger && sctp->sctp_lingertime > 0 && 351*0Sstevel@tonic-gate sctp->sctp_state >= SCTPS_ESTABLISHED && 352*0Sstevel@tonic-gate !sctp->sctp_lingering) { 353*0Sstevel@tonic-gate clock_t stoptime; /* in ticks */ 354*0Sstevel@tonic-gate clock_t ret; 355*0Sstevel@tonic-gate 356*0Sstevel@tonic-gate /* 357*0Sstevel@tonic-gate * Process the sendq to send the SHUTDOWN out 358*0Sstevel@tonic-gate * before waiting. 359*0Sstevel@tonic-gate */ 360*0Sstevel@tonic-gate sctp_process_sendq(sctp); 361*0Sstevel@tonic-gate 362*0Sstevel@tonic-gate sctp->sctp_lingering = 1; 363*0Sstevel@tonic-gate sctp->sctp_client_errno = 0; 364*0Sstevel@tonic-gate stoptime = lbolt + sctp->sctp_lingertime; 365*0Sstevel@tonic-gate 366*0Sstevel@tonic-gate mutex_enter(&sctp->sctp_lock); 367*0Sstevel@tonic-gate sctp->sctp_running = B_FALSE; 368*0Sstevel@tonic-gate while (sctp->sctp_state >= SCTPS_ESTABLISHED && 369*0Sstevel@tonic-gate sctp->sctp_client_errno == 0) { 370*0Sstevel@tonic-gate cv_broadcast(&sctp->sctp_cv); 371*0Sstevel@tonic-gate ret = cv_timedwait_sig(&sctp->sctp_cv, 372*0Sstevel@tonic-gate &sctp->sctp_lock, stoptime); 373*0Sstevel@tonic-gate if (ret < 0) { 374*0Sstevel@tonic-gate /* Stoptime has reached. */ 375*0Sstevel@tonic-gate sctp->sctp_client_errno = EWOULDBLOCK; 376*0Sstevel@tonic-gate break; 377*0Sstevel@tonic-gate } else if (ret == 0) { 378*0Sstevel@tonic-gate /* Got a signal. */ 379*0Sstevel@tonic-gate break; 380*0Sstevel@tonic-gate } 381*0Sstevel@tonic-gate } 382*0Sstevel@tonic-gate error = sctp->sctp_client_errno; 383*0Sstevel@tonic-gate sctp->sctp_client_errno = 0; 384*0Sstevel@tonic-gate mutex_exit(&sctp->sctp_lock); 385*0Sstevel@tonic-gate } 386*0Sstevel@tonic-gate 387*0Sstevel@tonic-gate WAKE_SCTP(sctp); 388*0Sstevel@tonic-gate sctp_process_sendq(sctp); 389*0Sstevel@tonic-gate return (error); 390*0Sstevel@tonic-gate } 391*0Sstevel@tonic-gate 392*0Sstevel@tonic-gate 393*0Sstevel@tonic-gate /* Remove this sctp from all hashes so nobody can find it. */ 394*0Sstevel@tonic-gate sctp_closei_local(sctp); 395*0Sstevel@tonic-gate WAKE_SCTP(sctp); 396*0Sstevel@tonic-gate return (error); 397*0Sstevel@tonic-gate } 398*0Sstevel@tonic-gate 399*0Sstevel@tonic-gate void 400*0Sstevel@tonic-gate sctp_close(sctp_t *sctp) 401*0Sstevel@tonic-gate { 402*0Sstevel@tonic-gate dprint(3, ("sctp_close %p, state %d\n", sctp, sctp->sctp_state)); 403*0Sstevel@tonic-gate 404*0Sstevel@tonic-gate RUN_SCTP(sctp); 405*0Sstevel@tonic-gate sctp->sctp_detached = 1; 406*0Sstevel@tonic-gate sctp->sctp_ulpd = NULL; 407*0Sstevel@tonic-gate bzero(&sctp->sctp_upcalls, sizeof (sctp_upcalls_t)); 408*0Sstevel@tonic-gate bzero(&sctp->sctp_events, sizeof (sctp->sctp_events)); 409*0Sstevel@tonic-gate 410*0Sstevel@tonic-gate /* If the graceful shutdown has not been completed, just return. */ 411*0Sstevel@tonic-gate if (sctp->sctp_state != SCTPS_IDLE) { 412*0Sstevel@tonic-gate WAKE_SCTP(sctp); 413*0Sstevel@tonic-gate return; 414*0Sstevel@tonic-gate } 415*0Sstevel@tonic-gate 416*0Sstevel@tonic-gate /* 417*0Sstevel@tonic-gate * Since sctp_t is in SCTPS_IDLE state, so the only thread which 418*0Sstevel@tonic-gate * can have a hold on the sctp_t is doing snmp stuff. Just do 419*0Sstevel@tonic-gate * a SCTP_REFRELE() here after the SCTP_UNLINK(). It will 420*0Sstevel@tonic-gate * be freed when the other thread is done. 421*0Sstevel@tonic-gate */ 422*0Sstevel@tonic-gate SCTP_CONDEMNED(sctp); 423*0Sstevel@tonic-gate WAKE_SCTP(sctp); 424*0Sstevel@tonic-gate SCTP_REFRELE(sctp); 425*0Sstevel@tonic-gate } 426*0Sstevel@tonic-gate 427*0Sstevel@tonic-gate /* 428*0Sstevel@tonic-gate * Unlink from global list and do the eager close. 429*0Sstevel@tonic-gate * Remove the refhold implicit in being on the global list. 430*0Sstevel@tonic-gate */ 431*0Sstevel@tonic-gate void 432*0Sstevel@tonic-gate sctp_close_eager(sctp_t *sctp) 433*0Sstevel@tonic-gate { 434*0Sstevel@tonic-gate SCTP_CONDEMNED(sctp); 435*0Sstevel@tonic-gate sctp_closei_local(sctp); 436*0Sstevel@tonic-gate SCTP_REFRELE(sctp); 437*0Sstevel@tonic-gate } 438*0Sstevel@tonic-gate 439*0Sstevel@tonic-gate /* 440*0Sstevel@tonic-gate * The sctp_t is going away. Remove it from all lists and set it 441*0Sstevel@tonic-gate * to SCTPS_IDLE. The caller has to remove it from the 442*0Sstevel@tonic-gate * global list. The freeing up of memory is deferred until 443*0Sstevel@tonic-gate * sctp_free(). This is needed since a thread in sctp_input() might have 444*0Sstevel@tonic-gate * done a SCTP_REFHOLD on this structure before it was removed from the 445*0Sstevel@tonic-gate * hashes. 446*0Sstevel@tonic-gate */ 447*0Sstevel@tonic-gate static void 448*0Sstevel@tonic-gate sctp_closei_local(sctp_t *sctp) 449*0Sstevel@tonic-gate { 450*0Sstevel@tonic-gate mblk_t *mp; 451*0Sstevel@tonic-gate ire_t *ire = NULL; 452*0Sstevel@tonic-gate conn_t *connp = sctp->sctp_connp; 453*0Sstevel@tonic-gate 454*0Sstevel@tonic-gate /* Stop and free the timers */ 455*0Sstevel@tonic-gate sctp_free_faddr_timers(sctp); 456*0Sstevel@tonic-gate if ((mp = sctp->sctp_heartbeat_mp) != NULL) { 457*0Sstevel@tonic-gate sctp_timer_free(mp); 458*0Sstevel@tonic-gate sctp->sctp_heartbeat_mp = NULL; 459*0Sstevel@tonic-gate } 460*0Sstevel@tonic-gate if ((mp = sctp->sctp_ack_mp) != NULL) { 461*0Sstevel@tonic-gate sctp_timer_free(mp); 462*0Sstevel@tonic-gate sctp->sctp_ack_mp = NULL; 463*0Sstevel@tonic-gate } 464*0Sstevel@tonic-gate 465*0Sstevel@tonic-gate /* Set the CONN_CLOSING flag so that IP will not cache IRE again. */ 466*0Sstevel@tonic-gate mutex_enter(&connp->conn_lock); 467*0Sstevel@tonic-gate connp->conn_state_flags |= CONN_CLOSING; 468*0Sstevel@tonic-gate ire = connp->conn_ire_cache; 469*0Sstevel@tonic-gate connp->conn_ire_cache = NULL; 470*0Sstevel@tonic-gate mutex_exit(&connp->conn_lock); 471*0Sstevel@tonic-gate if (ire != NULL) 472*0Sstevel@tonic-gate IRE_REFRELE_NOTR(ire); 473*0Sstevel@tonic-gate 474*0Sstevel@tonic-gate /* Remove from all hashes. */ 475*0Sstevel@tonic-gate sctp_bind_hash_remove(sctp); 476*0Sstevel@tonic-gate sctp_conn_hash_remove(sctp); 477*0Sstevel@tonic-gate sctp_listen_hash_remove(sctp); 478*0Sstevel@tonic-gate sctp->sctp_state = SCTPS_IDLE; 479*0Sstevel@tonic-gate 480*0Sstevel@tonic-gate /* 481*0Sstevel@tonic-gate * Clean up the recvq as much as possible. All those packets 482*0Sstevel@tonic-gate * will be silently dropped as this sctp_t is now in idle state. 483*0Sstevel@tonic-gate */ 484*0Sstevel@tonic-gate mutex_enter(&sctp->sctp_recvq_lock); 485*0Sstevel@tonic-gate while ((mp = sctp->sctp_recvq) != NULL) { 486*0Sstevel@tonic-gate mblk_t *ipsec_mp; 487*0Sstevel@tonic-gate 488*0Sstevel@tonic-gate sctp->sctp_recvq = mp->b_next; 489*0Sstevel@tonic-gate mp->b_next = NULL; 490*0Sstevel@tonic-gate if ((ipsec_mp = mp->b_prev) != NULL) { 491*0Sstevel@tonic-gate freeb(ipsec_mp); 492*0Sstevel@tonic-gate mp->b_prev = NULL; 493*0Sstevel@tonic-gate } 494*0Sstevel@tonic-gate freemsg(mp); 495*0Sstevel@tonic-gate } 496*0Sstevel@tonic-gate mutex_exit(&sctp->sctp_recvq_lock); 497*0Sstevel@tonic-gate } 498*0Sstevel@tonic-gate 499*0Sstevel@tonic-gate /* 500*0Sstevel@tonic-gate * Free memory associated with the sctp/ip header template. 501*0Sstevel@tonic-gate */ 502*0Sstevel@tonic-gate static void 503*0Sstevel@tonic-gate sctp_headers_free(sctp_t *sctp) 504*0Sstevel@tonic-gate { 505*0Sstevel@tonic-gate if (sctp->sctp_iphc != NULL) { 506*0Sstevel@tonic-gate kmem_free(sctp->sctp_iphc, sctp->sctp_iphc_len); 507*0Sstevel@tonic-gate sctp->sctp_iphc = NULL; 508*0Sstevel@tonic-gate sctp->sctp_ipha = NULL; 509*0Sstevel@tonic-gate sctp->sctp_hdr_len = 0; 510*0Sstevel@tonic-gate sctp->sctp_ip_hdr_len = 0; 511*0Sstevel@tonic-gate sctp->sctp_iphc_len = 0; 512*0Sstevel@tonic-gate sctp->sctp_sctph = NULL; 513*0Sstevel@tonic-gate sctp->sctp_hdr_len = 0; 514*0Sstevel@tonic-gate } 515*0Sstevel@tonic-gate if (sctp->sctp_iphc6 != NULL) { 516*0Sstevel@tonic-gate kmem_free(sctp->sctp_iphc6, sctp->sctp_iphc6_len); 517*0Sstevel@tonic-gate sctp->sctp_iphc6 = NULL; 518*0Sstevel@tonic-gate sctp->sctp_ip6h = NULL; 519*0Sstevel@tonic-gate sctp->sctp_hdr6_len = 0; 520*0Sstevel@tonic-gate sctp->sctp_ip_hdr6_len = 0; 521*0Sstevel@tonic-gate sctp->sctp_iphc6_len = 0; 522*0Sstevel@tonic-gate sctp->sctp_sctph6 = NULL; 523*0Sstevel@tonic-gate sctp->sctp_hdr6_len = 0; 524*0Sstevel@tonic-gate } 525*0Sstevel@tonic-gate } 526*0Sstevel@tonic-gate 527*0Sstevel@tonic-gate static void 528*0Sstevel@tonic-gate sctp_free_xmit_data(sctp_t *sctp) 529*0Sstevel@tonic-gate { 530*0Sstevel@tonic-gate mblk_t *ump = NULL; 531*0Sstevel@tonic-gate mblk_t *nump; 532*0Sstevel@tonic-gate mblk_t *mp; 533*0Sstevel@tonic-gate mblk_t *nmp; 534*0Sstevel@tonic-gate 535*0Sstevel@tonic-gate sctp->sctp_xmit_unacked = NULL; 536*0Sstevel@tonic-gate ump = sctp->sctp_xmit_head; 537*0Sstevel@tonic-gate sctp->sctp_xmit_tail = sctp->sctp_xmit_head = NULL; 538*0Sstevel@tonic-gate free_unsent: 539*0Sstevel@tonic-gate for (; ump != NULL; ump = nump) { 540*0Sstevel@tonic-gate for (mp = ump->b_cont; mp != NULL; mp = nmp) { 541*0Sstevel@tonic-gate nmp = mp->b_next; 542*0Sstevel@tonic-gate mp->b_next = NULL; 543*0Sstevel@tonic-gate mp->b_prev = NULL; 544*0Sstevel@tonic-gate freemsg(mp); 545*0Sstevel@tonic-gate } 546*0Sstevel@tonic-gate ASSERT(DB_REF(ump) == 1); 547*0Sstevel@tonic-gate nump = ump->b_next; 548*0Sstevel@tonic-gate ump->b_next = NULL; 549*0Sstevel@tonic-gate ump->b_prev = NULL; 550*0Sstevel@tonic-gate ump->b_cont = NULL; 551*0Sstevel@tonic-gate freeb(ump); 552*0Sstevel@tonic-gate } 553*0Sstevel@tonic-gate if ((ump = sctp->sctp_xmit_unsent) == NULL) { 554*0Sstevel@tonic-gate ASSERT(sctp->sctp_xmit_unsent_tail == NULL); 555*0Sstevel@tonic-gate return; 556*0Sstevel@tonic-gate } 557*0Sstevel@tonic-gate sctp->sctp_xmit_unsent = sctp->sctp_xmit_unsent_tail = NULL; 558*0Sstevel@tonic-gate goto free_unsent; 559*0Sstevel@tonic-gate } 560*0Sstevel@tonic-gate 561*0Sstevel@tonic-gate /* 562*0Sstevel@tonic-gate * Cleanup all the messages in the stream queue and the reassembly lists. 563*0Sstevel@tonic-gate * If 'free' is true, then delete the streams as well. 564*0Sstevel@tonic-gate */ 565*0Sstevel@tonic-gate void 566*0Sstevel@tonic-gate sctp_instream_cleanup(sctp_t *sctp, boolean_t free) 567*0Sstevel@tonic-gate { 568*0Sstevel@tonic-gate int i; 569*0Sstevel@tonic-gate mblk_t *mp; 570*0Sstevel@tonic-gate mblk_t *mp1; 571*0Sstevel@tonic-gate 572*0Sstevel@tonic-gate if (sctp->sctp_instr != NULL) { 573*0Sstevel@tonic-gate /* walk thru and flush out anything remaining in the Q */ 574*0Sstevel@tonic-gate for (i = 0; i < sctp->sctp_num_istr; i++) { 575*0Sstevel@tonic-gate mp = sctp->sctp_instr[i].istr_msgs; 576*0Sstevel@tonic-gate while (mp != NULL) { 577*0Sstevel@tonic-gate mp1 = mp->b_next; 578*0Sstevel@tonic-gate mp->b_next = mp->b_prev = NULL; 579*0Sstevel@tonic-gate freemsg(mp); 580*0Sstevel@tonic-gate mp = mp1; 581*0Sstevel@tonic-gate } 582*0Sstevel@tonic-gate sctp->sctp_instr[i].istr_msgs = NULL; 583*0Sstevel@tonic-gate sctp_free_reass((sctp->sctp_instr) + i); 584*0Sstevel@tonic-gate sctp->sctp_instr[i].nextseq = 0; 585*0Sstevel@tonic-gate } 586*0Sstevel@tonic-gate if (free) { 587*0Sstevel@tonic-gate kmem_free(sctp->sctp_instr, 588*0Sstevel@tonic-gate sizeof (*sctp->sctp_instr) * sctp->sctp_num_istr); 589*0Sstevel@tonic-gate sctp->sctp_instr = NULL; 590*0Sstevel@tonic-gate sctp->sctp_num_istr = 0; 591*0Sstevel@tonic-gate } 592*0Sstevel@tonic-gate } 593*0Sstevel@tonic-gate /* un-ordered fragments */ 594*0Sstevel@tonic-gate if (sctp->sctp_uo_frags != NULL) { 595*0Sstevel@tonic-gate for (mp = sctp->sctp_uo_frags; mp != NULL; mp = mp1) { 596*0Sstevel@tonic-gate mp1 = mp->b_next; 597*0Sstevel@tonic-gate mp->b_next = mp->b_prev = NULL; 598*0Sstevel@tonic-gate freemsg(mp); 599*0Sstevel@tonic-gate } 600*0Sstevel@tonic-gate } 601*0Sstevel@tonic-gate } 602*0Sstevel@tonic-gate 603*0Sstevel@tonic-gate /* 604*0Sstevel@tonic-gate * Last reference to the sctp_t is gone. Free all memory associated with it. 605*0Sstevel@tonic-gate * Called from SCTP_REFRELE. Called inline in sctp_close() 606*0Sstevel@tonic-gate */ 607*0Sstevel@tonic-gate void 608*0Sstevel@tonic-gate sctp_free(conn_t *connp) 609*0Sstevel@tonic-gate { 610*0Sstevel@tonic-gate sctp_t *sctp = CONN2SCTP(connp); 611*0Sstevel@tonic-gate ip6_pkt_t *ipp; 612*0Sstevel@tonic-gate int cnt; 613*0Sstevel@tonic-gate 614*0Sstevel@tonic-gate /* Unlink it from the global list */ 615*0Sstevel@tonic-gate SCTP_UNLINK(sctp); 616*0Sstevel@tonic-gate 617*0Sstevel@tonic-gate ASSERT(connp->conn_ref == 0); 618*0Sstevel@tonic-gate ASSERT(connp->conn_ulp == IPPROTO_SCTP); 619*0Sstevel@tonic-gate ASSERT(!MUTEX_HELD(&sctp->sctp_reflock)); 620*0Sstevel@tonic-gate ASSERT(sctp->sctp_refcnt == 0); 621*0Sstevel@tonic-gate 622*0Sstevel@tonic-gate ASSERT(sctp->sctp_ptpbhn == NULL && sctp->sctp_bind_hash == NULL); 623*0Sstevel@tonic-gate ASSERT(sctp->sctp_conn_hash_next == NULL && 624*0Sstevel@tonic-gate sctp->sctp_conn_hash_prev == NULL); 625*0Sstevel@tonic-gate 626*0Sstevel@tonic-gate 627*0Sstevel@tonic-gate /* Free up all the resources. */ 628*0Sstevel@tonic-gate 629*0Sstevel@tonic-gate /* blow away sctp stream management */ 630*0Sstevel@tonic-gate if (sctp->sctp_ostrcntrs != NULL) { 631*0Sstevel@tonic-gate kmem_free(sctp->sctp_ostrcntrs, 632*0Sstevel@tonic-gate sizeof (uint16_t) * sctp->sctp_num_ostr); 633*0Sstevel@tonic-gate sctp->sctp_ostrcntrs = NULL; 634*0Sstevel@tonic-gate } 635*0Sstevel@tonic-gate sctp_instream_cleanup(sctp, B_TRUE); 636*0Sstevel@tonic-gate 637*0Sstevel@tonic-gate /* Remove all data transfer resources. */ 638*0Sstevel@tonic-gate sctp->sctp_istr_nmsgs = 0; 639*0Sstevel@tonic-gate sctp->sctp_rxqueued = 0; 640*0Sstevel@tonic-gate sctp_free_xmit_data(sctp); 641*0Sstevel@tonic-gate sctp->sctp_unacked = 0; 642*0Sstevel@tonic-gate sctp->sctp_unsent = 0; 643*0Sstevel@tonic-gate if (sctp->sctp_cxmit_list != NULL) { 644*0Sstevel@tonic-gate freemsg(sctp->sctp_cxmit_list); 645*0Sstevel@tonic-gate sctp->sctp_cxmit_list = NULL; 646*0Sstevel@tonic-gate } 647*0Sstevel@tonic-gate sctp->sctp_lastdata = NULL; 648*0Sstevel@tonic-gate 649*0Sstevel@tonic-gate /* Clear out default xmit settings */ 650*0Sstevel@tonic-gate sctp->sctp_def_stream = 0; 651*0Sstevel@tonic-gate sctp->sctp_def_flags = 0; 652*0Sstevel@tonic-gate sctp->sctp_def_ppid = 0; 653*0Sstevel@tonic-gate sctp->sctp_def_context = 0; 654*0Sstevel@tonic-gate sctp->sctp_def_timetolive = 0; 655*0Sstevel@tonic-gate 656*0Sstevel@tonic-gate if (sctp->sctp_sack_info != NULL) { 657*0Sstevel@tonic-gate sctp_free_set(sctp->sctp_sack_info); 658*0Sstevel@tonic-gate sctp->sctp_sack_info = NULL; 659*0Sstevel@tonic-gate } 660*0Sstevel@tonic-gate sctp->sctp_sack_gaps = 0; 661*0Sstevel@tonic-gate 662*0Sstevel@tonic-gate if (sctp->sctp_cookie_mp != NULL) { 663*0Sstevel@tonic-gate freemsg(sctp->sctp_cookie_mp); 664*0Sstevel@tonic-gate sctp->sctp_cookie_mp = NULL; 665*0Sstevel@tonic-gate } 666*0Sstevel@tonic-gate 667*0Sstevel@tonic-gate /* Remove all the address resources. */ 668*0Sstevel@tonic-gate sctp_zap_addrs(sctp); 669*0Sstevel@tonic-gate for (cnt = 0; cnt < SCTP_IPIF_HASH; cnt++) { 670*0Sstevel@tonic-gate ASSERT(sctp->sctp_saddrs[cnt].ipif_count == 0); 671*0Sstevel@tonic-gate list_destroy(&sctp->sctp_saddrs[cnt].sctp_ipif_list); 672*0Sstevel@tonic-gate } 673*0Sstevel@tonic-gate 674*0Sstevel@tonic-gate ipp = &sctp->sctp_sticky_ipp; 675*0Sstevel@tonic-gate if (ipp->ipp_rthdrlen != 0) { 676*0Sstevel@tonic-gate kmem_free(ipp->ipp_rthdr, ipp->ipp_rthdrlen); 677*0Sstevel@tonic-gate ipp->ipp_rthdrlen = 0; 678*0Sstevel@tonic-gate } 679*0Sstevel@tonic-gate 680*0Sstevel@tonic-gate if (ipp->ipp_dstoptslen != 0) { 681*0Sstevel@tonic-gate kmem_free(ipp->ipp_dstopts, ipp->ipp_dstoptslen); 682*0Sstevel@tonic-gate ipp->ipp_dstoptslen = 0; 683*0Sstevel@tonic-gate } 684*0Sstevel@tonic-gate 685*0Sstevel@tonic-gate if (ipp->ipp_rtdstoptslen != 0) { 686*0Sstevel@tonic-gate kmem_free(ipp->ipp_rtdstopts, ipp->ipp_rtdstoptslen); 687*0Sstevel@tonic-gate ipp->ipp_rtdstoptslen = 0; 688*0Sstevel@tonic-gate } 689*0Sstevel@tonic-gate 690*0Sstevel@tonic-gate if (ipp->ipp_hopoptslen != 0) { 691*0Sstevel@tonic-gate kmem_free(ipp->ipp_hopopts, ipp->ipp_hopoptslen); 692*0Sstevel@tonic-gate ipp->ipp_hopoptslen = 0; 693*0Sstevel@tonic-gate } 694*0Sstevel@tonic-gate 695*0Sstevel@tonic-gate if (sctp->sctp_hopopts != NULL) { 696*0Sstevel@tonic-gate mi_free(sctp->sctp_hopopts); 697*0Sstevel@tonic-gate sctp->sctp_hopopts = NULL; 698*0Sstevel@tonic-gate sctp->sctp_hopoptslen = 0; 699*0Sstevel@tonic-gate } 700*0Sstevel@tonic-gate ASSERT(sctp->sctp_hopoptslen == 0); 701*0Sstevel@tonic-gate if (sctp->sctp_dstopts != NULL) { 702*0Sstevel@tonic-gate mi_free(sctp->sctp_dstopts); 703*0Sstevel@tonic-gate sctp->sctp_dstopts = NULL; 704*0Sstevel@tonic-gate sctp->sctp_dstoptslen = 0; 705*0Sstevel@tonic-gate } 706*0Sstevel@tonic-gate ASSERT(sctp->sctp_dstoptslen == 0); 707*0Sstevel@tonic-gate if (sctp->sctp_rtdstopts != NULL) { 708*0Sstevel@tonic-gate mi_free(sctp->sctp_rtdstopts); 709*0Sstevel@tonic-gate sctp->sctp_rtdstopts = NULL; 710*0Sstevel@tonic-gate sctp->sctp_rtdstoptslen = 0; 711*0Sstevel@tonic-gate } 712*0Sstevel@tonic-gate ASSERT(sctp->sctp_rtdstoptslen == 0); 713*0Sstevel@tonic-gate if (sctp->sctp_rthdr != NULL) { 714*0Sstevel@tonic-gate mi_free(sctp->sctp_rthdr); 715*0Sstevel@tonic-gate sctp->sctp_rthdr = NULL; 716*0Sstevel@tonic-gate sctp->sctp_rthdrlen = 0; 717*0Sstevel@tonic-gate } 718*0Sstevel@tonic-gate ASSERT(sctp->sctp_rthdrlen == 0); 719*0Sstevel@tonic-gate sctp_headers_free(sctp); 720*0Sstevel@tonic-gate 721*0Sstevel@tonic-gate sctp->sctp_shutdown_faddr = NULL; 722*0Sstevel@tonic-gate 723*0Sstevel@tonic-gate /* Clear all the bitfields. */ 724*0Sstevel@tonic-gate bzero(&sctp->sctp_bits, sizeof (sctp->sctp_bits)); 725*0Sstevel@tonic-gate 726*0Sstevel@tonic-gate /* It is time to update the global statistics. */ 727*0Sstevel@tonic-gate UPDATE_MIB(&sctp_mib, sctpOutSCTPPkts, sctp->sctp_opkts); 728*0Sstevel@tonic-gate UPDATE_MIB(&sctp_mib, sctpOutCtrlChunks, sctp->sctp_obchunks); 729*0Sstevel@tonic-gate UPDATE_MIB(&sctp_mib, sctpOutOrderChunks, sctp->sctp_odchunks); 730*0Sstevel@tonic-gate UPDATE_MIB(&sctp_mib, sctpOutUnorderChunks, sctp->sctp_oudchunks); 731*0Sstevel@tonic-gate UPDATE_MIB(&sctp_mib, sctpRetransChunks, sctp->sctp_rxtchunks); 732*0Sstevel@tonic-gate UPDATE_MIB(&sctp_mib, sctpInSCTPPkts, sctp->sctp_ipkts); 733*0Sstevel@tonic-gate UPDATE_MIB(&sctp_mib, sctpInCtrlChunks, sctp->sctp_ibchunks); 734*0Sstevel@tonic-gate UPDATE_MIB(&sctp_mib, sctpInOrderChunks, sctp->sctp_idchunks); 735*0Sstevel@tonic-gate UPDATE_MIB(&sctp_mib, sctpInUnorderChunks, sctp->sctp_iudchunks); 736*0Sstevel@tonic-gate UPDATE_MIB(&sctp_mib, sctpFragUsrMsgs, sctp->sctp_fragdmsgs); 737*0Sstevel@tonic-gate UPDATE_MIB(&sctp_mib, sctpReasmUsrMsgs, sctp->sctp_reassmsgs); 738*0Sstevel@tonic-gate sctp->sctp_opkts = 0; 739*0Sstevel@tonic-gate sctp->sctp_obchunks = 0; 740*0Sstevel@tonic-gate sctp->sctp_odchunks = 0; 741*0Sstevel@tonic-gate sctp->sctp_oudchunks = 0; 742*0Sstevel@tonic-gate sctp->sctp_rxtchunks = 0; 743*0Sstevel@tonic-gate sctp->sctp_ipkts = 0; 744*0Sstevel@tonic-gate sctp->sctp_ibchunks = 0; 745*0Sstevel@tonic-gate sctp->sctp_idchunks = 0; 746*0Sstevel@tonic-gate sctp->sctp_iudchunks = 0; 747*0Sstevel@tonic-gate sctp->sctp_fragdmsgs = 0; 748*0Sstevel@tonic-gate sctp->sctp_reassmsgs = 0; 749*0Sstevel@tonic-gate 750*0Sstevel@tonic-gate sctp->sctp_autoclose = 0; 751*0Sstevel@tonic-gate sctp->sctp_tx_adaption_code = 0; 752*0Sstevel@tonic-gate 753*0Sstevel@tonic-gate /* Clean up conn_t stuff */ 754*0Sstevel@tonic-gate connp->conn_policy_cached = B_FALSE; 755*0Sstevel@tonic-gate if (connp->conn_latch != NULL) { 756*0Sstevel@tonic-gate IPLATCH_REFRELE(connp->conn_latch); 757*0Sstevel@tonic-gate connp->conn_latch = NULL; 758*0Sstevel@tonic-gate } 759*0Sstevel@tonic-gate if (connp->conn_policy != NULL) { 760*0Sstevel@tonic-gate IPPH_REFRELE(connp->conn_policy); 761*0Sstevel@tonic-gate connp->conn_policy = NULL; 762*0Sstevel@tonic-gate } 763*0Sstevel@tonic-gate if (connp->conn_ipsec_opt_mp != NULL) { 764*0Sstevel@tonic-gate freemsg(connp->conn_ipsec_opt_mp); 765*0Sstevel@tonic-gate connp->conn_ipsec_opt_mp = NULL; 766*0Sstevel@tonic-gate } 767*0Sstevel@tonic-gate if (connp->conn_cred != NULL) { 768*0Sstevel@tonic-gate crfree(connp->conn_cred); 769*0Sstevel@tonic-gate connp->conn_cred = NULL; 770*0Sstevel@tonic-gate } 771*0Sstevel@tonic-gate 772*0Sstevel@tonic-gate kmem_cache_free(sctp_conn_cache, connp); 773*0Sstevel@tonic-gate } 774*0Sstevel@tonic-gate 775*0Sstevel@tonic-gate /* Diagnostic routine used to return a string associated with the sctp state. */ 776*0Sstevel@tonic-gate char * 777*0Sstevel@tonic-gate sctp_display(sctp_t *sctp, char *sup_buf) 778*0Sstevel@tonic-gate { 779*0Sstevel@tonic-gate char *buf; 780*0Sstevel@tonic-gate char buf1[30]; 781*0Sstevel@tonic-gate static char priv_buf[INET6_ADDRSTRLEN * 2 + 80]; 782*0Sstevel@tonic-gate char *cp; 783*0Sstevel@tonic-gate 784*0Sstevel@tonic-gate if (sctp == NULL) 785*0Sstevel@tonic-gate return ("NULL_SCTP"); 786*0Sstevel@tonic-gate 787*0Sstevel@tonic-gate buf = (sup_buf != NULL) ? sup_buf : priv_buf; 788*0Sstevel@tonic-gate 789*0Sstevel@tonic-gate switch (sctp->sctp_state) { 790*0Sstevel@tonic-gate case SCTPS_IDLE: 791*0Sstevel@tonic-gate cp = "SCTP_IDLE"; 792*0Sstevel@tonic-gate break; 793*0Sstevel@tonic-gate case SCTPS_BOUND: 794*0Sstevel@tonic-gate cp = "SCTP_BOUND"; 795*0Sstevel@tonic-gate break; 796*0Sstevel@tonic-gate case SCTPS_LISTEN: 797*0Sstevel@tonic-gate cp = "SCTP_LISTEN"; 798*0Sstevel@tonic-gate break; 799*0Sstevel@tonic-gate case SCTPS_COOKIE_WAIT: 800*0Sstevel@tonic-gate cp = "SCTP_COOKIE_WAIT"; 801*0Sstevel@tonic-gate break; 802*0Sstevel@tonic-gate case SCTPS_COOKIE_ECHOED: 803*0Sstevel@tonic-gate cp = "SCTP_COOKIE_ECHOED"; 804*0Sstevel@tonic-gate break; 805*0Sstevel@tonic-gate case SCTPS_ESTABLISHED: 806*0Sstevel@tonic-gate cp = "SCTP_ESTABLISHED"; 807*0Sstevel@tonic-gate break; 808*0Sstevel@tonic-gate case SCTPS_SHUTDOWN_PENDING: 809*0Sstevel@tonic-gate cp = "SCTP_SHUTDOWN_PENDING"; 810*0Sstevel@tonic-gate break; 811*0Sstevel@tonic-gate case SCTPS_SHUTDOWN_SENT: 812*0Sstevel@tonic-gate cp = "SCTPS_SHUTDOWN_SENT"; 813*0Sstevel@tonic-gate break; 814*0Sstevel@tonic-gate case SCTPS_SHUTDOWN_RECEIVED: 815*0Sstevel@tonic-gate cp = "SCTPS_SHUTDOWN_RECEIVED"; 816*0Sstevel@tonic-gate break; 817*0Sstevel@tonic-gate case SCTPS_SHUTDOWN_ACK_SENT: 818*0Sstevel@tonic-gate cp = "SCTPS_SHUTDOWN_ACK_SENT"; 819*0Sstevel@tonic-gate break; 820*0Sstevel@tonic-gate default: 821*0Sstevel@tonic-gate (void) mi_sprintf(buf1, "SCTPUnkState(%d)", sctp->sctp_state); 822*0Sstevel@tonic-gate cp = buf1; 823*0Sstevel@tonic-gate break; 824*0Sstevel@tonic-gate } 825*0Sstevel@tonic-gate (void) mi_sprintf(buf, "[%u, %u] %s", 826*0Sstevel@tonic-gate ntohs(sctp->sctp_lport), ntohs(sctp->sctp_fport), cp); 827*0Sstevel@tonic-gate 828*0Sstevel@tonic-gate return (buf); 829*0Sstevel@tonic-gate } 830*0Sstevel@tonic-gate 831*0Sstevel@tonic-gate /* 832*0Sstevel@tonic-gate * Initialize protocol control block. If a parent exists, inherit 833*0Sstevel@tonic-gate * all values set through setsockopt(). 834*0Sstevel@tonic-gate */ 835*0Sstevel@tonic-gate static int 836*0Sstevel@tonic-gate sctp_init_values(sctp_t *sctp, sctp_t *psctp, int sleep) 837*0Sstevel@tonic-gate { 838*0Sstevel@tonic-gate int err; 839*0Sstevel@tonic-gate int cnt; 840*0Sstevel@tonic-gate 841*0Sstevel@tonic-gate ASSERT((sctp->sctp_family == AF_INET && 842*0Sstevel@tonic-gate sctp->sctp_ipversion == IPV4_VERSION) || 843*0Sstevel@tonic-gate (sctp->sctp_family == AF_INET6 && 844*0Sstevel@tonic-gate (sctp->sctp_ipversion == IPV4_VERSION || 845*0Sstevel@tonic-gate sctp->sctp_ipversion == IPV6_VERSION))); 846*0Sstevel@tonic-gate 847*0Sstevel@tonic-gate sctp->sctp_nsaddrs = 0; 848*0Sstevel@tonic-gate for (cnt = 0; cnt < SCTP_IPIF_HASH; cnt++) { 849*0Sstevel@tonic-gate sctp->sctp_saddrs[cnt].ipif_count = 0; 850*0Sstevel@tonic-gate list_create(&sctp->sctp_saddrs[cnt].sctp_ipif_list, 851*0Sstevel@tonic-gate sizeof (sctp_saddr_ipif_t), offsetof(sctp_saddr_ipif_t, 852*0Sstevel@tonic-gate saddr_ipif)); 853*0Sstevel@tonic-gate } 854*0Sstevel@tonic-gate sctp->sctp_ports = 0; 855*0Sstevel@tonic-gate sctp->sctp_running = B_FALSE; 856*0Sstevel@tonic-gate sctp->sctp_state = SCTPS_IDLE; 857*0Sstevel@tonic-gate 858*0Sstevel@tonic-gate sctp->sctp_refcnt = 1; 859*0Sstevel@tonic-gate 860*0Sstevel@tonic-gate sctp->sctp_strikes = 0; 861*0Sstevel@tonic-gate 862*0Sstevel@tonic-gate sctp->sctp_last_mtu_probe = lbolt64; 863*0Sstevel@tonic-gate sctp->sctp_mtu_probe_intvl = sctp_mtu_probe_interval; 864*0Sstevel@tonic-gate 865*0Sstevel@tonic-gate sctp->sctp_sack_gaps = 0; 866*0Sstevel@tonic-gate sctp->sctp_sack_toggle = 2; 867*0Sstevel@tonic-gate 868*0Sstevel@tonic-gate if (psctp != NULL) { 869*0Sstevel@tonic-gate /* 870*0Sstevel@tonic-gate * Inherit from parent 871*0Sstevel@tonic-gate */ 872*0Sstevel@tonic-gate sctp->sctp_iphc = kmem_zalloc(psctp->sctp_iphc_len, 873*0Sstevel@tonic-gate KM_NOSLEEP); 874*0Sstevel@tonic-gate if (sctp->sctp_iphc == NULL) 875*0Sstevel@tonic-gate return (ENOMEM); 876*0Sstevel@tonic-gate sctp->sctp_iphc_len = psctp->sctp_iphc_len; 877*0Sstevel@tonic-gate sctp->sctp_hdr_len = psctp->sctp_hdr_len; 878*0Sstevel@tonic-gate 879*0Sstevel@tonic-gate sctp->sctp_iphc6 = kmem_zalloc(psctp->sctp_iphc6_len, 880*0Sstevel@tonic-gate KM_NOSLEEP); 881*0Sstevel@tonic-gate if (sctp->sctp_iphc6 == NULL) { 882*0Sstevel@tonic-gate sctp->sctp_iphc6_len = 0; 883*0Sstevel@tonic-gate return (ENOMEM); 884*0Sstevel@tonic-gate } 885*0Sstevel@tonic-gate sctp->sctp_iphc6_len = psctp->sctp_iphc6_len; 886*0Sstevel@tonic-gate sctp->sctp_hdr6_len = psctp->sctp_hdr6_len; 887*0Sstevel@tonic-gate 888*0Sstevel@tonic-gate sctp->sctp_ip_hdr_len = psctp->sctp_ip_hdr_len; 889*0Sstevel@tonic-gate sctp->sctp_ip_hdr6_len = psctp->sctp_ip_hdr6_len; 890*0Sstevel@tonic-gate 891*0Sstevel@tonic-gate /* 892*0Sstevel@tonic-gate * Copy the IP+SCTP header templates from listener 893*0Sstevel@tonic-gate */ 894*0Sstevel@tonic-gate bcopy(psctp->sctp_iphc, sctp->sctp_iphc, 895*0Sstevel@tonic-gate psctp->sctp_hdr_len); 896*0Sstevel@tonic-gate sctp->sctp_ipha = (ipha_t *)sctp->sctp_iphc; 897*0Sstevel@tonic-gate sctp->sctp_sctph = (sctp_hdr_t *)(sctp->sctp_iphc + 898*0Sstevel@tonic-gate sctp->sctp_ip_hdr_len); 899*0Sstevel@tonic-gate 900*0Sstevel@tonic-gate bcopy(psctp->sctp_iphc6, sctp->sctp_iphc6, 901*0Sstevel@tonic-gate psctp->sctp_hdr6_len); 902*0Sstevel@tonic-gate if (((ip6i_t *)(sctp->sctp_iphc6))->ip6i_nxt == IPPROTO_RAW) { 903*0Sstevel@tonic-gate sctp->sctp_ip6h = (ip6_t *)(sctp->sctp_iphc6 + 904*0Sstevel@tonic-gate sizeof (ip6i_t)); 905*0Sstevel@tonic-gate } else { 906*0Sstevel@tonic-gate sctp->sctp_ip6h = (ip6_t *)sctp->sctp_iphc6; 907*0Sstevel@tonic-gate } 908*0Sstevel@tonic-gate sctp->sctp_sctph6 = (sctp_hdr_t *)(sctp->sctp_iphc6 + 909*0Sstevel@tonic-gate sctp->sctp_ip_hdr6_len); 910*0Sstevel@tonic-gate 911*0Sstevel@tonic-gate sctp->sctp_cookie_lifetime = psctp->sctp_cookie_lifetime; 912*0Sstevel@tonic-gate sctp->sctp_xmit_lowater = psctp->sctp_xmit_lowater; 913*0Sstevel@tonic-gate sctp->sctp_xmit_hiwater = psctp->sctp_xmit_hiwater; 914*0Sstevel@tonic-gate sctp->sctp_cwnd_max = psctp->sctp_cwnd_max; 915*0Sstevel@tonic-gate sctp->sctp_rwnd = psctp->sctp_rwnd; 916*0Sstevel@tonic-gate 917*0Sstevel@tonic-gate sctp->sctp_rto_max = psctp->sctp_rto_max; 918*0Sstevel@tonic-gate sctp->sctp_init_rto_max = psctp->sctp_init_rto_max; 919*0Sstevel@tonic-gate sctp->sctp_rto_min = psctp->sctp_rto_min; 920*0Sstevel@tonic-gate sctp->sctp_rto_initial = psctp->sctp_rto_initial; 921*0Sstevel@tonic-gate sctp->sctp_pa_max_rxt = psctp->sctp_pa_max_rxt; 922*0Sstevel@tonic-gate sctp->sctp_pp_max_rxt = psctp->sctp_pp_max_rxt; 923*0Sstevel@tonic-gate sctp->sctp_max_init_rxt = psctp->sctp_max_init_rxt; 924*0Sstevel@tonic-gate 925*0Sstevel@tonic-gate sctp->sctp_def_stream = psctp->sctp_def_stream; 926*0Sstevel@tonic-gate sctp->sctp_def_flags = psctp->sctp_def_flags; 927*0Sstevel@tonic-gate sctp->sctp_def_ppid = psctp->sctp_def_ppid; 928*0Sstevel@tonic-gate sctp->sctp_def_context = psctp->sctp_def_context; 929*0Sstevel@tonic-gate sctp->sctp_def_timetolive = psctp->sctp_def_timetolive; 930*0Sstevel@tonic-gate 931*0Sstevel@tonic-gate sctp->sctp_num_istr = psctp->sctp_num_istr; 932*0Sstevel@tonic-gate sctp->sctp_num_ostr = psctp->sctp_num_ostr; 933*0Sstevel@tonic-gate 934*0Sstevel@tonic-gate sctp->sctp_hb_interval = psctp->sctp_hb_interval; 935*0Sstevel@tonic-gate sctp->sctp_autoclose = psctp->sctp_autoclose; 936*0Sstevel@tonic-gate sctp->sctp_tx_adaption_code = psctp->sctp_tx_adaption_code; 937*0Sstevel@tonic-gate 938*0Sstevel@tonic-gate /* xxx should be a better way to copy these flags xxx */ 939*0Sstevel@tonic-gate sctp->sctp_debug = psctp->sctp_debug; 940*0Sstevel@tonic-gate sctp->sctp_dontroute = psctp->sctp_dontroute; 941*0Sstevel@tonic-gate sctp->sctp_useloopback = psctp->sctp_useloopback; 942*0Sstevel@tonic-gate sctp->sctp_broadcast = psctp->sctp_broadcast; 943*0Sstevel@tonic-gate sctp->sctp_reuseaddr = psctp->sctp_reuseaddr; 944*0Sstevel@tonic-gate sctp->sctp_bound_to_all = psctp->sctp_bound_to_all; 945*0Sstevel@tonic-gate sctp->sctp_cansleep = psctp->sctp_cansleep; 946*0Sstevel@tonic-gate sctp->sctp_send_adaption = psctp->sctp_send_adaption; 947*0Sstevel@tonic-gate sctp->sctp_ndelay = psctp->sctp_ndelay; 948*0Sstevel@tonic-gate sctp->sctp_events = psctp->sctp_events; 949*0Sstevel@tonic-gate sctp->sctp_ipv6_recvancillary = psctp->sctp_ipv6_recvancillary; 950*0Sstevel@tonic-gate } else { 951*0Sstevel@tonic-gate /* 952*0Sstevel@tonic-gate * Initialize the header template 953*0Sstevel@tonic-gate */ 954*0Sstevel@tonic-gate if ((err = sctp_header_init_ipv4(sctp, sleep)) != 0) { 955*0Sstevel@tonic-gate return (err); 956*0Sstevel@tonic-gate } 957*0Sstevel@tonic-gate if ((err = sctp_header_init_ipv6(sctp, sleep)) != 0) { 958*0Sstevel@tonic-gate return (err); 959*0Sstevel@tonic-gate } 960*0Sstevel@tonic-gate 961*0Sstevel@tonic-gate /* 962*0Sstevel@tonic-gate * Set to system defaults 963*0Sstevel@tonic-gate */ 964*0Sstevel@tonic-gate sctp->sctp_cookie_lifetime = MSEC_TO_TICK(sctp_cookie_life); 965*0Sstevel@tonic-gate sctp->sctp_xmit_lowater = sctp_xmit_lowat; 966*0Sstevel@tonic-gate sctp->sctp_xmit_hiwater = sctp_xmit_hiwat; 967*0Sstevel@tonic-gate sctp->sctp_cwnd_max = sctp_cwnd_max_; 968*0Sstevel@tonic-gate sctp->sctp_rwnd = sctp_recv_hiwat; 969*0Sstevel@tonic-gate 970*0Sstevel@tonic-gate sctp->sctp_rto_max = MSEC_TO_TICK(sctp_rto_maxg); 971*0Sstevel@tonic-gate sctp->sctp_init_rto_max = sctp->sctp_rto_max; 972*0Sstevel@tonic-gate sctp->sctp_rto_min = MSEC_TO_TICK(sctp_rto_ming); 973*0Sstevel@tonic-gate sctp->sctp_rto_initial = MSEC_TO_TICK(sctp_rto_initialg); 974*0Sstevel@tonic-gate sctp->sctp_pa_max_rxt = sctp_pa_max_retr; 975*0Sstevel@tonic-gate sctp->sctp_pp_max_rxt = sctp_pp_max_retr; 976*0Sstevel@tonic-gate sctp->sctp_max_init_rxt = sctp_max_init_retr; 977*0Sstevel@tonic-gate 978*0Sstevel@tonic-gate sctp->sctp_num_istr = sctp_max_in_streams; 979*0Sstevel@tonic-gate sctp->sctp_num_ostr = sctp_initial_out_streams; 980*0Sstevel@tonic-gate 981*0Sstevel@tonic-gate sctp->sctp_hb_interval = MSEC_TO_TICK(sctp_heartbeat_interval); 982*0Sstevel@tonic-gate } 983*0Sstevel@tonic-gate sctp->sctp_understands_asconf = B_TRUE; 984*0Sstevel@tonic-gate sctp->sctp_understands_addip = B_TRUE; 985*0Sstevel@tonic-gate sctp->sctp_prsctp_aware = B_FALSE; 986*0Sstevel@tonic-gate 987*0Sstevel@tonic-gate sctp->sctp_connp->conn_ref = 1; 988*0Sstevel@tonic-gate sctp->sctp_connp->conn_fully_bound = B_FALSE; 989*0Sstevel@tonic-gate 990*0Sstevel@tonic-gate sctp->sctp_prsctpdrop = 0; 991*0Sstevel@tonic-gate sctp->sctp_msgcount = 0; 992*0Sstevel@tonic-gate 993*0Sstevel@tonic-gate return (0); 994*0Sstevel@tonic-gate } 995*0Sstevel@tonic-gate 996*0Sstevel@tonic-gate /* 997*0Sstevel@tonic-gate * Extracts the init tag from an INIT chunk and checks if it matches 998*0Sstevel@tonic-gate * the sctp's verification tag. Returns 0 if it doesn't match, 1 if 999*0Sstevel@tonic-gate * it does. 1000*0Sstevel@tonic-gate */ 1001*0Sstevel@tonic-gate static boolean_t 1002*0Sstevel@tonic-gate sctp_icmp_verf(sctp_t *sctp, sctp_hdr_t *sh, mblk_t *mp) 1003*0Sstevel@tonic-gate { 1004*0Sstevel@tonic-gate sctp_chunk_hdr_t *sch; 1005*0Sstevel@tonic-gate uint32_t verf, *vp; 1006*0Sstevel@tonic-gate 1007*0Sstevel@tonic-gate sch = (sctp_chunk_hdr_t *)(sh + 1); 1008*0Sstevel@tonic-gate vp = (uint32_t *)(sch + 1); 1009*0Sstevel@tonic-gate 1010*0Sstevel@tonic-gate /* Need at least the data chunk hdr and the first 4 bytes of INIT */ 1011*0Sstevel@tonic-gate if ((unsigned char *)(vp + 1) > mp->b_wptr) { 1012*0Sstevel@tonic-gate return (B_FALSE); 1013*0Sstevel@tonic-gate } 1014*0Sstevel@tonic-gate 1015*0Sstevel@tonic-gate bcopy(vp, &verf, sizeof (verf)); 1016*0Sstevel@tonic-gate 1017*0Sstevel@tonic-gate if (verf == sctp->sctp_lvtag) { 1018*0Sstevel@tonic-gate return (B_TRUE); 1019*0Sstevel@tonic-gate } 1020*0Sstevel@tonic-gate return (B_FALSE); 1021*0Sstevel@tonic-gate } 1022*0Sstevel@tonic-gate 1023*0Sstevel@tonic-gate /* 1024*0Sstevel@tonic-gate * sctp_icmp_error is called by sctp_input() to process ICMP error messages 1025*0Sstevel@tonic-gate * passed up by IP. The queue is the default queue. We need to find a sctp_t 1026*0Sstevel@tonic-gate * that corresponds to the returned datagram. Passes the message back in on 1027*0Sstevel@tonic-gate * the correct queue once it has located the connection. 1028*0Sstevel@tonic-gate * Assumes that IP has pulled up everything up to and including 1029*0Sstevel@tonic-gate * the ICMP header. 1030*0Sstevel@tonic-gate */ 1031*0Sstevel@tonic-gate void 1032*0Sstevel@tonic-gate sctp_icmp_error(sctp_t *sctp, mblk_t *mp) 1033*0Sstevel@tonic-gate { 1034*0Sstevel@tonic-gate icmph_t *icmph; 1035*0Sstevel@tonic-gate ipha_t *ipha; 1036*0Sstevel@tonic-gate int iph_hdr_length; 1037*0Sstevel@tonic-gate sctp_hdr_t *sctph; 1038*0Sstevel@tonic-gate mblk_t *first_mp; 1039*0Sstevel@tonic-gate uint32_t new_mtu; 1040*0Sstevel@tonic-gate in6_addr_t dst; 1041*0Sstevel@tonic-gate sctp_faddr_t *fp; 1042*0Sstevel@tonic-gate 1043*0Sstevel@tonic-gate dprint(1, ("sctp_icmp_error: sctp=%p, mp=%p\n", sctp, mp)); 1044*0Sstevel@tonic-gate 1045*0Sstevel@tonic-gate first_mp = mp; 1046*0Sstevel@tonic-gate 1047*0Sstevel@tonic-gate ipha = (ipha_t *)mp->b_rptr; 1048*0Sstevel@tonic-gate if (IPH_HDR_VERSION(ipha) != IPV4_VERSION) { 1049*0Sstevel@tonic-gate ASSERT(IPH_HDR_VERSION(ipha) == IPV6_VERSION); 1050*0Sstevel@tonic-gate sctp_icmp_error_ipv6(sctp, first_mp); 1051*0Sstevel@tonic-gate return; 1052*0Sstevel@tonic-gate } 1053*0Sstevel@tonic-gate 1054*0Sstevel@tonic-gate iph_hdr_length = IPH_HDR_LENGTH(ipha); 1055*0Sstevel@tonic-gate icmph = (icmph_t *)&mp->b_rptr[iph_hdr_length]; 1056*0Sstevel@tonic-gate ipha = (ipha_t *)&icmph[1]; 1057*0Sstevel@tonic-gate iph_hdr_length = IPH_HDR_LENGTH(ipha); 1058*0Sstevel@tonic-gate sctph = (sctp_hdr_t *)((char *)ipha + iph_hdr_length); 1059*0Sstevel@tonic-gate if ((uchar_t *)(sctph + 1) >= mp->b_wptr) { 1060*0Sstevel@tonic-gate /* not enough data for SCTP header */ 1061*0Sstevel@tonic-gate freemsg(first_mp); 1062*0Sstevel@tonic-gate return; 1063*0Sstevel@tonic-gate } 1064*0Sstevel@tonic-gate 1065*0Sstevel@tonic-gate switch (icmph->icmph_type) { 1066*0Sstevel@tonic-gate case ICMP_DEST_UNREACHABLE: 1067*0Sstevel@tonic-gate switch (icmph->icmph_code) { 1068*0Sstevel@tonic-gate case ICMP_FRAGMENTATION_NEEDED: 1069*0Sstevel@tonic-gate /* 1070*0Sstevel@tonic-gate * Reduce the MSS based on the new MTU. This will 1071*0Sstevel@tonic-gate * eliminate any fragmentation locally. 1072*0Sstevel@tonic-gate * N.B. There may well be some funny side-effects on 1073*0Sstevel@tonic-gate * the local send policy and the remote receive policy. 1074*0Sstevel@tonic-gate * Pending further research, we provide 1075*0Sstevel@tonic-gate * sctp_ignore_path_mtu just in case this proves 1076*0Sstevel@tonic-gate * disastrous somewhere. 1077*0Sstevel@tonic-gate * 1078*0Sstevel@tonic-gate * After updating the MSS, retransmit part of the 1079*0Sstevel@tonic-gate * dropped segment using the new mss by calling 1080*0Sstevel@tonic-gate * sctp_wput_slow(). Need to adjust all those 1081*0Sstevel@tonic-gate * params to make sure sctp_wput_slow() work properly. 1082*0Sstevel@tonic-gate */ 1083*0Sstevel@tonic-gate if (sctp_ignore_path_mtu) 1084*0Sstevel@tonic-gate break; 1085*0Sstevel@tonic-gate 1086*0Sstevel@tonic-gate /* find the offending faddr */ 1087*0Sstevel@tonic-gate IN6_IPADDR_TO_V4MAPPED(ipha->ipha_dst, &dst); 1088*0Sstevel@tonic-gate fp = sctp_lookup_faddr(sctp, &dst); 1089*0Sstevel@tonic-gate if (fp == NULL) { 1090*0Sstevel@tonic-gate break; 1091*0Sstevel@tonic-gate } 1092*0Sstevel@tonic-gate 1093*0Sstevel@tonic-gate new_mtu = ntohs(icmph->icmph_du_mtu); 1094*0Sstevel@tonic-gate 1095*0Sstevel@tonic-gate if (new_mtu - sctp->sctp_hdr_len >= fp->sfa_pmss) 1096*0Sstevel@tonic-gate break; 1097*0Sstevel@tonic-gate 1098*0Sstevel@tonic-gate /* 1099*0Sstevel@tonic-gate * Make sure that sfa_pmss is a multiple of 1100*0Sstevel@tonic-gate * SCTP_ALIGN. 1101*0Sstevel@tonic-gate */ 1102*0Sstevel@tonic-gate fp->sfa_pmss = (new_mtu - sctp->sctp_hdr_len) & 1103*0Sstevel@tonic-gate ~(SCTP_ALIGN - 1); 1104*0Sstevel@tonic-gate fp->pmtu_discovered = 1; 1105*0Sstevel@tonic-gate 1106*0Sstevel@tonic-gate break; 1107*0Sstevel@tonic-gate case ICMP_PORT_UNREACHABLE: 1108*0Sstevel@tonic-gate case ICMP_PROTOCOL_UNREACHABLE: 1109*0Sstevel@tonic-gate switch (sctp->sctp_state) { 1110*0Sstevel@tonic-gate case SCTPS_COOKIE_WAIT: 1111*0Sstevel@tonic-gate case SCTPS_COOKIE_ECHOED: 1112*0Sstevel@tonic-gate /* make sure the verification tag matches */ 1113*0Sstevel@tonic-gate if (!sctp_icmp_verf(sctp, sctph, mp)) { 1114*0Sstevel@tonic-gate break; 1115*0Sstevel@tonic-gate } 1116*0Sstevel@tonic-gate BUMP_MIB(&sctp_mib, sctpAborted); 1117*0Sstevel@tonic-gate sctp_clean_death(sctp, ECONNREFUSED); 1118*0Sstevel@tonic-gate break; 1119*0Sstevel@tonic-gate } 1120*0Sstevel@tonic-gate break; 1121*0Sstevel@tonic-gate case ICMP_HOST_UNREACHABLE: 1122*0Sstevel@tonic-gate case ICMP_NET_UNREACHABLE: 1123*0Sstevel@tonic-gate /* Record the error in case we finally time out. */ 1124*0Sstevel@tonic-gate sctp->sctp_client_errno = (icmph->icmph_code == 1125*0Sstevel@tonic-gate ICMP_HOST_UNREACHABLE) ? EHOSTUNREACH : ENETUNREACH; 1126*0Sstevel@tonic-gate break; 1127*0Sstevel@tonic-gate default: 1128*0Sstevel@tonic-gate break; 1129*0Sstevel@tonic-gate } 1130*0Sstevel@tonic-gate break; 1131*0Sstevel@tonic-gate case ICMP_SOURCE_QUENCH: { 1132*0Sstevel@tonic-gate /* Reduce the sending rate as if we got a retransmit timeout */ 1133*0Sstevel@tonic-gate break; 1134*0Sstevel@tonic-gate } 1135*0Sstevel@tonic-gate } 1136*0Sstevel@tonic-gate freemsg(first_mp); 1137*0Sstevel@tonic-gate } 1138*0Sstevel@tonic-gate 1139*0Sstevel@tonic-gate /* 1140*0Sstevel@tonic-gate * sctp_icmp_error_ipv6() is called by sctp_icmp_error() to process ICMPv6 1141*0Sstevel@tonic-gate * error messages passed up by IP. 1142*0Sstevel@tonic-gate * Assumes that IP has pulled up all the extension headers as well 1143*0Sstevel@tonic-gate * as the ICMPv6 header. 1144*0Sstevel@tonic-gate */ 1145*0Sstevel@tonic-gate static void 1146*0Sstevel@tonic-gate sctp_icmp_error_ipv6(sctp_t *sctp, mblk_t *mp) 1147*0Sstevel@tonic-gate { 1148*0Sstevel@tonic-gate icmp6_t *icmp6; 1149*0Sstevel@tonic-gate ip6_t *ip6h; 1150*0Sstevel@tonic-gate uint16_t iph_hdr_length; 1151*0Sstevel@tonic-gate sctp_hdr_t *sctpha; 1152*0Sstevel@tonic-gate uint8_t *nexthdrp; 1153*0Sstevel@tonic-gate uint32_t new_mtu; 1154*0Sstevel@tonic-gate sctp_faddr_t *fp; 1155*0Sstevel@tonic-gate 1156*0Sstevel@tonic-gate ip6h = (ip6_t *)mp->b_rptr; 1157*0Sstevel@tonic-gate iph_hdr_length = (ip6h->ip6_nxt != IPPROTO_SCTP) ? 1158*0Sstevel@tonic-gate ip_hdr_length_v6(mp, ip6h) : IPV6_HDR_LEN; 1159*0Sstevel@tonic-gate 1160*0Sstevel@tonic-gate icmp6 = (icmp6_t *)&mp->b_rptr[iph_hdr_length]; 1161*0Sstevel@tonic-gate ip6h = (ip6_t *)&icmp6[1]; 1162*0Sstevel@tonic-gate if (!ip_hdr_length_nexthdr_v6(mp, ip6h, &iph_hdr_length, &nexthdrp)) { 1163*0Sstevel@tonic-gate freemsg(mp); 1164*0Sstevel@tonic-gate return; 1165*0Sstevel@tonic-gate } 1166*0Sstevel@tonic-gate ASSERT(*nexthdrp == IPPROTO_SCTP); 1167*0Sstevel@tonic-gate 1168*0Sstevel@tonic-gate /* XXX need ifindex to find connection */ 1169*0Sstevel@tonic-gate sctpha = (sctp_hdr_t *)((char *)ip6h + iph_hdr_length); 1170*0Sstevel@tonic-gate if ((uchar_t *)sctpha >= mp->b_wptr) { 1171*0Sstevel@tonic-gate /* not enough data for SCTP header */ 1172*0Sstevel@tonic-gate freemsg(mp); 1173*0Sstevel@tonic-gate return; 1174*0Sstevel@tonic-gate } 1175*0Sstevel@tonic-gate switch (icmp6->icmp6_type) { 1176*0Sstevel@tonic-gate case ICMP6_PACKET_TOO_BIG: 1177*0Sstevel@tonic-gate /* 1178*0Sstevel@tonic-gate * Reduce the MSS based on the new MTU. This will 1179*0Sstevel@tonic-gate * eliminate any fragmentation locally. 1180*0Sstevel@tonic-gate * N.B. There may well be some funny side-effects on 1181*0Sstevel@tonic-gate * the local send policy and the remote receive policy. 1182*0Sstevel@tonic-gate * Pending further research, we provide 1183*0Sstevel@tonic-gate * sctp_ignore_path_mtu just in case this proves 1184*0Sstevel@tonic-gate * disastrous somewhere. 1185*0Sstevel@tonic-gate * 1186*0Sstevel@tonic-gate * After updating the MSS, retransmit part of the 1187*0Sstevel@tonic-gate * dropped segment using the new mss by calling 1188*0Sstevel@tonic-gate * sctp_wput_slow(). Need to adjust all those 1189*0Sstevel@tonic-gate * params to make sure sctp_wput_slow() work properly. 1190*0Sstevel@tonic-gate */ 1191*0Sstevel@tonic-gate if (sctp_ignore_path_mtu) 1192*0Sstevel@tonic-gate break; 1193*0Sstevel@tonic-gate 1194*0Sstevel@tonic-gate /* find the offending faddr */ 1195*0Sstevel@tonic-gate fp = sctp_lookup_faddr(sctp, &ip6h->ip6_dst); 1196*0Sstevel@tonic-gate if (fp == NULL) { 1197*0Sstevel@tonic-gate break; 1198*0Sstevel@tonic-gate } 1199*0Sstevel@tonic-gate 1200*0Sstevel@tonic-gate new_mtu = ntohs(icmp6->icmp6_mtu); 1201*0Sstevel@tonic-gate 1202*0Sstevel@tonic-gate if (new_mtu - sctp->sctp_hdr6_len >= fp->sfa_pmss) 1203*0Sstevel@tonic-gate break; 1204*0Sstevel@tonic-gate 1205*0Sstevel@tonic-gate /* Make sure that sfa_pmss is a multiple of SCTP_ALIGN. */ 1206*0Sstevel@tonic-gate fp->sfa_pmss = (new_mtu - sctp->sctp_hdr6_len) & 1207*0Sstevel@tonic-gate ~(SCTP_ALIGN - 1); 1208*0Sstevel@tonic-gate fp->pmtu_discovered = 1; 1209*0Sstevel@tonic-gate 1210*0Sstevel@tonic-gate break; 1211*0Sstevel@tonic-gate 1212*0Sstevel@tonic-gate case ICMP6_DST_UNREACH: 1213*0Sstevel@tonic-gate switch (icmp6->icmp6_code) { 1214*0Sstevel@tonic-gate case ICMP6_DST_UNREACH_NOPORT: 1215*0Sstevel@tonic-gate /* make sure the verification tag matches */ 1216*0Sstevel@tonic-gate if (!sctp_icmp_verf(sctp, sctpha, mp)) { 1217*0Sstevel@tonic-gate break; 1218*0Sstevel@tonic-gate } 1219*0Sstevel@tonic-gate if (sctp->sctp_state == SCTPS_COOKIE_WAIT || 1220*0Sstevel@tonic-gate sctp->sctp_state == SCTPS_COOKIE_ECHOED) { 1221*0Sstevel@tonic-gate BUMP_MIB(&sctp_mib, sctpAborted); 1222*0Sstevel@tonic-gate sctp_clean_death(sctp, ECONNREFUSED); 1223*0Sstevel@tonic-gate } 1224*0Sstevel@tonic-gate break; 1225*0Sstevel@tonic-gate 1226*0Sstevel@tonic-gate case ICMP6_DST_UNREACH_ADMIN: 1227*0Sstevel@tonic-gate case ICMP6_DST_UNREACH_NOROUTE: 1228*0Sstevel@tonic-gate case ICMP6_DST_UNREACH_NOTNEIGHBOR: 1229*0Sstevel@tonic-gate case ICMP6_DST_UNREACH_ADDR: 1230*0Sstevel@tonic-gate /* Record the error in case we finally time out. */ 1231*0Sstevel@tonic-gate sctp->sctp_client_errno = EHOSTUNREACH; 1232*0Sstevel@tonic-gate break; 1233*0Sstevel@tonic-gate default: 1234*0Sstevel@tonic-gate break; 1235*0Sstevel@tonic-gate } 1236*0Sstevel@tonic-gate break; 1237*0Sstevel@tonic-gate 1238*0Sstevel@tonic-gate case ICMP6_PARAM_PROB: 1239*0Sstevel@tonic-gate /* If this corresponds to an ICMP_PROTOCOL_UNREACHABLE */ 1240*0Sstevel@tonic-gate if (icmp6->icmp6_code == ICMP6_PARAMPROB_NEXTHEADER && 1241*0Sstevel@tonic-gate (uchar_t *)ip6h + icmp6->icmp6_pptr == 1242*0Sstevel@tonic-gate (uchar_t *)nexthdrp) { 1243*0Sstevel@tonic-gate /* make sure the verification tag matches */ 1244*0Sstevel@tonic-gate if (!sctp_icmp_verf(sctp, sctpha, mp)) { 1245*0Sstevel@tonic-gate break; 1246*0Sstevel@tonic-gate } 1247*0Sstevel@tonic-gate if (sctp->sctp_state == SCTPS_COOKIE_WAIT) { 1248*0Sstevel@tonic-gate BUMP_MIB(&sctp_mib, sctpAborted); 1249*0Sstevel@tonic-gate sctp_clean_death(sctp, ECONNREFUSED); 1250*0Sstevel@tonic-gate } 1251*0Sstevel@tonic-gate break; 1252*0Sstevel@tonic-gate } 1253*0Sstevel@tonic-gate break; 1254*0Sstevel@tonic-gate 1255*0Sstevel@tonic-gate case ICMP6_TIME_EXCEEDED: 1256*0Sstevel@tonic-gate default: 1257*0Sstevel@tonic-gate break; 1258*0Sstevel@tonic-gate } 1259*0Sstevel@tonic-gate freemsg(mp); 1260*0Sstevel@tonic-gate } 1261*0Sstevel@tonic-gate 1262*0Sstevel@tonic-gate /* 1263*0Sstevel@tonic-gate * Called by sockfs to create a new sctp instance. 1264*0Sstevel@tonic-gate * 1265*0Sstevel@tonic-gate * If parent pointer is passed in, inherit settings from it. 1266*0Sstevel@tonic-gate */ 1267*0Sstevel@tonic-gate sctp_t * 1268*0Sstevel@tonic-gate sctp_create(void *sctp_ulpd, sctp_t *parent, int family, int flags, 1269*0Sstevel@tonic-gate const sctp_upcalls_t *sctp_upcalls, sctp_sockbuf_limits_t *sbl, 1270*0Sstevel@tonic-gate cred_t *credp) 1271*0Sstevel@tonic-gate { 1272*0Sstevel@tonic-gate sctp_t *sctp, *psctp; 1273*0Sstevel@tonic-gate conn_t *sctp_connp; 1274*0Sstevel@tonic-gate mblk_t *ack_mp, *hb_mp; 1275*0Sstevel@tonic-gate int sleep = flags & SCTP_CAN_BLOCK ? KM_SLEEP : KM_NOSLEEP; 1276*0Sstevel@tonic-gate 1277*0Sstevel@tonic-gate /* User must supply a credential. */ 1278*0Sstevel@tonic-gate if (credp == NULL) 1279*0Sstevel@tonic-gate return (NULL); 1280*0Sstevel@tonic-gate 1281*0Sstevel@tonic-gate if ((sctp_connp = ipcl_conn_create(IPCL_SCTPCONN, sleep)) == NULL) 1282*0Sstevel@tonic-gate return (NULL); 1283*0Sstevel@tonic-gate psctp = (sctp_t *)parent; 1284*0Sstevel@tonic-gate 1285*0Sstevel@tonic-gate sctp = CONN2SCTP(sctp_connp); 1286*0Sstevel@tonic-gate 1287*0Sstevel@tonic-gate if ((ack_mp = sctp_timer_alloc(sctp, sctp_ack_timer)) == NULL || 1288*0Sstevel@tonic-gate (hb_mp = sctp_timer_alloc(sctp, sctp_heartbeat_timer)) == NULL) { 1289*0Sstevel@tonic-gate if (ack_mp != NULL) 1290*0Sstevel@tonic-gate freeb(ack_mp); 1291*0Sstevel@tonic-gate kmem_cache_free(sctp_conn_cache, sctp_connp); 1292*0Sstevel@tonic-gate return (NULL); 1293*0Sstevel@tonic-gate } 1294*0Sstevel@tonic-gate 1295*0Sstevel@tonic-gate sctp->sctp_ack_mp = ack_mp; 1296*0Sstevel@tonic-gate sctp->sctp_heartbeat_mp = hb_mp; 1297*0Sstevel@tonic-gate 1298*0Sstevel@tonic-gate switch (family) { 1299*0Sstevel@tonic-gate case AF_INET6: 1300*0Sstevel@tonic-gate sctp_connp->conn_af_isv6 = B_TRUE; 1301*0Sstevel@tonic-gate sctp->sctp_ipversion = IPV6_VERSION; 1302*0Sstevel@tonic-gate sctp->sctp_family = AF_INET6; 1303*0Sstevel@tonic-gate break; 1304*0Sstevel@tonic-gate 1305*0Sstevel@tonic-gate case AF_INET: 1306*0Sstevel@tonic-gate sctp_connp->conn_af_isv6 = B_FALSE; 1307*0Sstevel@tonic-gate sctp_connp->conn_pkt_isv6 = B_FALSE; 1308*0Sstevel@tonic-gate sctp->sctp_ipversion = IPV4_VERSION; 1309*0Sstevel@tonic-gate sctp->sctp_family = AF_INET; 1310*0Sstevel@tonic-gate break; 1311*0Sstevel@tonic-gate default: 1312*0Sstevel@tonic-gate ASSERT(0); 1313*0Sstevel@tonic-gate break; 1314*0Sstevel@tonic-gate } 1315*0Sstevel@tonic-gate if (sctp_init_values(sctp, psctp, sleep) != 0) { 1316*0Sstevel@tonic-gate freeb(ack_mp); 1317*0Sstevel@tonic-gate freeb(hb_mp); 1318*0Sstevel@tonic-gate kmem_cache_free(sctp_conn_cache, sctp_connp); 1319*0Sstevel@tonic-gate return (NULL); 1320*0Sstevel@tonic-gate } 1321*0Sstevel@tonic-gate sctp->sctp_cansleep = ((flags & SCTP_CAN_BLOCK) == SCTP_CAN_BLOCK); 1322*0Sstevel@tonic-gate 1323*0Sstevel@tonic-gate sctp->sctp_mss = sctp_initial_mtu - ((family == AF_INET6) ? 1324*0Sstevel@tonic-gate sctp->sctp_hdr6_len : sctp->sctp_hdr_len); 1325*0Sstevel@tonic-gate 1326*0Sstevel@tonic-gate if (psctp != NULL) { 1327*0Sstevel@tonic-gate RUN_SCTP(psctp); 1328*0Sstevel@tonic-gate /* 1329*0Sstevel@tonic-gate * Inherit local address list, local port. Parent is either 1330*0Sstevel@tonic-gate * in SCTPS_BOUND, or SCTPS_LISTEN state. 1331*0Sstevel@tonic-gate */ 1332*0Sstevel@tonic-gate ASSERT((psctp->sctp_state == SCTPS_BOUND) || 1333*0Sstevel@tonic-gate (psctp->sctp_state == SCTPS_LISTEN)); 1334*0Sstevel@tonic-gate if (sctp_dup_saddrs(psctp, sctp, sleep)) { 1335*0Sstevel@tonic-gate WAKE_SCTP(psctp); 1336*0Sstevel@tonic-gate freeb(ack_mp); 1337*0Sstevel@tonic-gate freeb(hb_mp); 1338*0Sstevel@tonic-gate sctp_headers_free(sctp); 1339*0Sstevel@tonic-gate kmem_cache_free(sctp_conn_cache, sctp_connp); 1340*0Sstevel@tonic-gate return (NULL); 1341*0Sstevel@tonic-gate } 1342*0Sstevel@tonic-gate 1343*0Sstevel@tonic-gate /* 1344*0Sstevel@tonic-gate * If the parent is specified, it'll be immediatelly 1345*0Sstevel@tonic-gate * followed by sctp_connect(). So don't add this guy to 1346*0Sstevel@tonic-gate * bind hash. 1347*0Sstevel@tonic-gate */ 1348*0Sstevel@tonic-gate sctp->sctp_lport = psctp->sctp_lport; 1349*0Sstevel@tonic-gate sctp->sctp_state = SCTPS_BOUND; 1350*0Sstevel@tonic-gate sctp->sctp_zoneid = psctp->sctp_zoneid; 1351*0Sstevel@tonic-gate WAKE_SCTP(psctp); 1352*0Sstevel@tonic-gate } else { 1353*0Sstevel@tonic-gate sctp->sctp_zoneid = getzoneid(); 1354*0Sstevel@tonic-gate } 1355*0Sstevel@tonic-gate 1356*0Sstevel@tonic-gate sctp_connp->conn_cred = credp; 1357*0Sstevel@tonic-gate crhold(credp); 1358*0Sstevel@tonic-gate 1359*0Sstevel@tonic-gate /* Initialize SCTP instance values, our verf tag must never be 0 */ 1360*0Sstevel@tonic-gate (void) random_get_pseudo_bytes((uint8_t *)&sctp->sctp_lvtag, 1361*0Sstevel@tonic-gate sizeof (sctp->sctp_lvtag)); 1362*0Sstevel@tonic-gate if (sctp->sctp_lvtag == 0) 1363*0Sstevel@tonic-gate sctp->sctp_lvtag = (uint32_t)gethrtime(); 1364*0Sstevel@tonic-gate ASSERT(sctp->sctp_lvtag != 0); 1365*0Sstevel@tonic-gate 1366*0Sstevel@tonic-gate sctp->sctp_ltsn = sctp->sctp_lvtag + 1; 1367*0Sstevel@tonic-gate sctp->sctp_lcsn = sctp->sctp_ltsn; 1368*0Sstevel@tonic-gate sctp->sctp_recovery_tsn = sctp->sctp_lastack_rxd = sctp->sctp_ltsn - 1; 1369*0Sstevel@tonic-gate sctp->sctp_adv_pap = sctp->sctp_lastack_rxd; 1370*0Sstevel@tonic-gate 1371*0Sstevel@tonic-gate /* Information required by upper layer */ 1372*0Sstevel@tonic-gate if (sctp_ulpd != NULL) { 1373*0Sstevel@tonic-gate sctp->sctp_ulpd = sctp_ulpd; 1374*0Sstevel@tonic-gate 1375*0Sstevel@tonic-gate ASSERT(sctp_upcalls != NULL); 1376*0Sstevel@tonic-gate bcopy(sctp_upcalls, &sctp->sctp_upcalls, 1377*0Sstevel@tonic-gate sizeof (sctp_upcalls_t)); 1378*0Sstevel@tonic-gate ASSERT(sbl != NULL); 1379*0Sstevel@tonic-gate /* Fill in the socket buffer limits for sctpsockfs */ 1380*0Sstevel@tonic-gate sbl->sbl_txlowat = sctp->sctp_xmit_lowater; 1381*0Sstevel@tonic-gate sbl->sbl_txbuf = sctp->sctp_xmit_hiwater; 1382*0Sstevel@tonic-gate sbl->sbl_rxbuf = sctp->sctp_rwnd; 1383*0Sstevel@tonic-gate sbl->sbl_rxlowat = SCTP_RECV_LOWATER; 1384*0Sstevel@tonic-gate } 1385*0Sstevel@tonic-gate /* If no sctp_ulpd, must be creating the default sctp */ 1386*0Sstevel@tonic-gate ASSERT(sctp_ulpd != NULL || gsctp == NULL); 1387*0Sstevel@tonic-gate 1388*0Sstevel@tonic-gate /* Insert this in the global list. */ 1389*0Sstevel@tonic-gate SCTP_LINK(sctp); 1390*0Sstevel@tonic-gate 1391*0Sstevel@tonic-gate return (sctp); 1392*0Sstevel@tonic-gate } 1393*0Sstevel@tonic-gate 1394*0Sstevel@tonic-gate void 1395*0Sstevel@tonic-gate sctp_ddi_init(void) 1396*0Sstevel@tonic-gate { 1397*0Sstevel@tonic-gate /* Initialize locks */ 1398*0Sstevel@tonic-gate mutex_init(&sctp_g_lock, NULL, MUTEX_DEFAULT, NULL); 1399*0Sstevel@tonic-gate mutex_init(&sctp_epriv_port_lock, NULL, MUTEX_DEFAULT, NULL); 1400*0Sstevel@tonic-gate 1401*0Sstevel@tonic-gate /* Initialize SCTP hash arrays. */ 1402*0Sstevel@tonic-gate sctp_hash_init(); 1403*0Sstevel@tonic-gate 1404*0Sstevel@tonic-gate sctp_pad_mp = allocb(SCTP_ALIGN, BPRI_MED); 1405*0Sstevel@tonic-gate bzero(sctp_pad_mp->b_rptr, SCTP_ALIGN); 1406*0Sstevel@tonic-gate ASSERT(sctp_pad_mp); 1407*0Sstevel@tonic-gate 1408*0Sstevel@tonic-gate if (!sctp_nd_init()) { 1409*0Sstevel@tonic-gate sctp_nd_free(); 1410*0Sstevel@tonic-gate } 1411*0Sstevel@tonic-gate 1412*0Sstevel@tonic-gate /* Create sctp_t/conn_t cache */ 1413*0Sstevel@tonic-gate sctp_conn_cache_init(); 1414*0Sstevel@tonic-gate 1415*0Sstevel@tonic-gate /* Create the faddr cache */ 1416*0Sstevel@tonic-gate sctp_faddr_init(); 1417*0Sstevel@tonic-gate 1418*0Sstevel@tonic-gate /* Create the sets cache */ 1419*0Sstevel@tonic-gate sctp_sets_init(); 1420*0Sstevel@tonic-gate 1421*0Sstevel@tonic-gate /* Create the PR-SCTP sets cache */ 1422*0Sstevel@tonic-gate sctp_ftsn_sets_init(); 1423*0Sstevel@tonic-gate 1424*0Sstevel@tonic-gate /* Initialize the recvq taskq. */ 1425*0Sstevel@tonic-gate sctp_rq_tq_init(); 1426*0Sstevel@tonic-gate 1427*0Sstevel@tonic-gate /* saddr init */ 1428*0Sstevel@tonic-gate sctp_saddr_init(); 1429*0Sstevel@tonic-gate 1430*0Sstevel@tonic-gate /* Global SCTP PCB list. */ 1431*0Sstevel@tonic-gate list_create(&sctp_g_list, sizeof (sctp_t), 1432*0Sstevel@tonic-gate offsetof(sctp_t, sctp_list)); 1433*0Sstevel@tonic-gate 1434*0Sstevel@tonic-gate /* Initialize tables used for CRC calculation */ 1435*0Sstevel@tonic-gate sctp_crc32_init(); 1436*0Sstevel@tonic-gate 1437*0Sstevel@tonic-gate /* Initialize sctp kernel stats. */ 1438*0Sstevel@tonic-gate sctp_kstat_init(); 1439*0Sstevel@tonic-gate } 1440*0Sstevel@tonic-gate 1441*0Sstevel@tonic-gate void 1442*0Sstevel@tonic-gate sctp_ddi_destroy(void) 1443*0Sstevel@tonic-gate { 1444*0Sstevel@tonic-gate sctp_nd_free(); 1445*0Sstevel@tonic-gate 1446*0Sstevel@tonic-gate /* Destroy sctp_t/conn_t caches */ 1447*0Sstevel@tonic-gate sctp_conn_cache_fini(); 1448*0Sstevel@tonic-gate 1449*0Sstevel@tonic-gate /* Destroy the faddr cache */ 1450*0Sstevel@tonic-gate sctp_faddr_fini(); 1451*0Sstevel@tonic-gate 1452*0Sstevel@tonic-gate /* Destroy the sets cache */ 1453*0Sstevel@tonic-gate sctp_sets_fini(); 1454*0Sstevel@tonic-gate 1455*0Sstevel@tonic-gate /* Destroy the PR-SCTP sets cache */ 1456*0Sstevel@tonic-gate sctp_ftsn_sets_fini(); 1457*0Sstevel@tonic-gate 1458*0Sstevel@tonic-gate /* Destroy the recvq taskqs. */ 1459*0Sstevel@tonic-gate sctp_rq_tq_fini(); 1460*0Sstevel@tonic-gate 1461*0Sstevel@tonic-gate /* Destroy saddr */ 1462*0Sstevel@tonic-gate sctp_saddr_fini(); 1463*0Sstevel@tonic-gate 1464*0Sstevel@tonic-gate /* Global SCTP PCB list. */ 1465*0Sstevel@tonic-gate list_destroy(&sctp_g_list); 1466*0Sstevel@tonic-gate 1467*0Sstevel@tonic-gate /* Destroy SCTP hash arrays. */ 1468*0Sstevel@tonic-gate sctp_hash_destroy(); 1469*0Sstevel@tonic-gate 1470*0Sstevel@tonic-gate /* Destroy SCTP kenrel stats. */ 1471*0Sstevel@tonic-gate sctp_kstat_fini(); 1472*0Sstevel@tonic-gate 1473*0Sstevel@tonic-gate mutex_destroy(&sctp_g_lock); 1474*0Sstevel@tonic-gate mutex_destroy(&sctp_epriv_port_lock); 1475*0Sstevel@tonic-gate } 1476*0Sstevel@tonic-gate 1477*0Sstevel@tonic-gate void 1478*0Sstevel@tonic-gate sctp_display_all() 1479*0Sstevel@tonic-gate { 1480*0Sstevel@tonic-gate sctp_t *sctp_walker; 1481*0Sstevel@tonic-gate 1482*0Sstevel@tonic-gate mutex_enter(&sctp_g_lock); 1483*0Sstevel@tonic-gate for (sctp_walker = gsctp; sctp_walker != NULL; 1484*0Sstevel@tonic-gate sctp_walker = (sctp_t *)list_next(&sctp_g_list, sctp_walker)) { 1485*0Sstevel@tonic-gate (void) sctp_display(sctp_walker, NULL); 1486*0Sstevel@tonic-gate } 1487*0Sstevel@tonic-gate mutex_exit(&sctp_g_lock); 1488*0Sstevel@tonic-gate } 1489*0Sstevel@tonic-gate 1490*0Sstevel@tonic-gate static void 1491*0Sstevel@tonic-gate sctp_rq_tq_init(void) 1492*0Sstevel@tonic-gate { 1493*0Sstevel@tonic-gate /* 1494*0Sstevel@tonic-gate * Initialize the recvq_tq_list and create the first recvq taskq. 1495*0Sstevel@tonic-gate * What to do if it fails? 1496*0Sstevel@tonic-gate */ 1497*0Sstevel@tonic-gate recvq_tq_list = kmem_zalloc(sctp_recvq_tq_list_max_sz * 1498*0Sstevel@tonic-gate sizeof (taskq_t *), KM_SLEEP); 1499*0Sstevel@tonic-gate recvq_tq_list[0] = taskq_create("sctp_def_recvq_taskq", 1500*0Sstevel@tonic-gate MIN(sctp_recvq_tq_thr_max, MAX(sctp_recvq_tq_thr_min, ncpus)), 1501*0Sstevel@tonic-gate minclsyspri, sctp_recvq_tq_task_min, sctp_recvq_tq_task_max, 1502*0Sstevel@tonic-gate TASKQ_PREPOPULATE); 1503*0Sstevel@tonic-gate mutex_init(&sctp_rq_tq_lock, NULL, MUTEX_DEFAULT, NULL); 1504*0Sstevel@tonic-gate } 1505*0Sstevel@tonic-gate 1506*0Sstevel@tonic-gate static void 1507*0Sstevel@tonic-gate sctp_rq_tq_fini(void) 1508*0Sstevel@tonic-gate { 1509*0Sstevel@tonic-gate int i; 1510*0Sstevel@tonic-gate 1511*0Sstevel@tonic-gate for (i = 0; i < recvq_tq_list_cur_sz; i++) { 1512*0Sstevel@tonic-gate ASSERT(recvq_tq_list[i] != NULL); 1513*0Sstevel@tonic-gate taskq_destroy(recvq_tq_list[i]); 1514*0Sstevel@tonic-gate } 1515*0Sstevel@tonic-gate kmem_free(recvq_tq_list, sctp_recvq_tq_list_max_sz * 1516*0Sstevel@tonic-gate sizeof (taskq_t *)); 1517*0Sstevel@tonic-gate } 1518*0Sstevel@tonic-gate 1519*0Sstevel@tonic-gate /* Add another taskq for a new ill. */ 1520*0Sstevel@tonic-gate void 1521*0Sstevel@tonic-gate sctp_inc_taskq(void) 1522*0Sstevel@tonic-gate { 1523*0Sstevel@tonic-gate taskq_t *tq; 1524*0Sstevel@tonic-gate char tq_name[TASKQ_NAMELEN]; 1525*0Sstevel@tonic-gate 1526*0Sstevel@tonic-gate mutex_enter(&sctp_rq_tq_lock); 1527*0Sstevel@tonic-gate if (recvq_tq_list_cur_sz + 1 > sctp_recvq_tq_list_max_sz) { 1528*0Sstevel@tonic-gate mutex_exit(&sctp_rq_tq_lock); 1529*0Sstevel@tonic-gate cmn_err(CE_NOTE, "Cannot create more SCTP recvq taskq"); 1530*0Sstevel@tonic-gate return; 1531*0Sstevel@tonic-gate } 1532*0Sstevel@tonic-gate 1533*0Sstevel@tonic-gate (void) snprintf(tq_name, sizeof (tq_name), "sctp_recvq_taskq_%u", 1534*0Sstevel@tonic-gate recvq_tq_list_cur_sz); 1535*0Sstevel@tonic-gate tq = taskq_create(tq_name, 1536*0Sstevel@tonic-gate MIN(sctp_recvq_tq_thr_max, MAX(sctp_recvq_tq_thr_min, ncpus)), 1537*0Sstevel@tonic-gate minclsyspri, sctp_recvq_tq_task_min, sctp_recvq_tq_task_max, 1538*0Sstevel@tonic-gate TASKQ_PREPOPULATE); 1539*0Sstevel@tonic-gate if (tq == NULL) { 1540*0Sstevel@tonic-gate mutex_exit(&sctp_rq_tq_lock); 1541*0Sstevel@tonic-gate cmn_err(CE_NOTE, "SCTP recvq taskq creation failed"); 1542*0Sstevel@tonic-gate return; 1543*0Sstevel@tonic-gate } 1544*0Sstevel@tonic-gate ASSERT(recvq_tq_list[recvq_tq_list_cur_sz] == NULL); 1545*0Sstevel@tonic-gate recvq_tq_list[recvq_tq_list_cur_sz] = tq; 1546*0Sstevel@tonic-gate atomic_add_32(&recvq_tq_list_cur_sz, 1); 1547*0Sstevel@tonic-gate mutex_exit(&sctp_rq_tq_lock); 1548*0Sstevel@tonic-gate } 1549*0Sstevel@tonic-gate 1550*0Sstevel@tonic-gate #ifdef DEBUG 1551*0Sstevel@tonic-gate uint32_t sendq_loop_cnt = 0; 1552*0Sstevel@tonic-gate uint32_t sendq_collision = 0; 1553*0Sstevel@tonic-gate uint32_t sendq_empty = 0; 1554*0Sstevel@tonic-gate #endif 1555*0Sstevel@tonic-gate 1556*0Sstevel@tonic-gate void 1557*0Sstevel@tonic-gate sctp_add_sendq(sctp_t *sctp, mblk_t *mp) 1558*0Sstevel@tonic-gate { 1559*0Sstevel@tonic-gate mutex_enter(&sctp->sctp_sendq_lock); 1560*0Sstevel@tonic-gate if (sctp->sctp_sendq == NULL) { 1561*0Sstevel@tonic-gate sctp->sctp_sendq = mp; 1562*0Sstevel@tonic-gate sctp->sctp_sendq_tail = mp; 1563*0Sstevel@tonic-gate } else { 1564*0Sstevel@tonic-gate sctp->sctp_sendq_tail->b_next = mp; 1565*0Sstevel@tonic-gate sctp->sctp_sendq_tail = mp; 1566*0Sstevel@tonic-gate } 1567*0Sstevel@tonic-gate mutex_exit(&sctp->sctp_sendq_lock); 1568*0Sstevel@tonic-gate } 1569*0Sstevel@tonic-gate 1570*0Sstevel@tonic-gate void 1571*0Sstevel@tonic-gate sctp_process_sendq(sctp_t *sctp) 1572*0Sstevel@tonic-gate { 1573*0Sstevel@tonic-gate mblk_t *mp; 1574*0Sstevel@tonic-gate #ifdef DEBUG 1575*0Sstevel@tonic-gate uint32_t loop_cnt = 0; 1576*0Sstevel@tonic-gate #endif 1577*0Sstevel@tonic-gate 1578*0Sstevel@tonic-gate mutex_enter(&sctp->sctp_sendq_lock); 1579*0Sstevel@tonic-gate if (sctp->sctp_sendq == NULL || sctp->sctp_sendq_sending) { 1580*0Sstevel@tonic-gate #ifdef DEBUG 1581*0Sstevel@tonic-gate if (sctp->sctp_sendq == NULL) 1582*0Sstevel@tonic-gate sendq_empty++; 1583*0Sstevel@tonic-gate else 1584*0Sstevel@tonic-gate sendq_collision++; 1585*0Sstevel@tonic-gate #endif 1586*0Sstevel@tonic-gate mutex_exit(&sctp->sctp_sendq_lock); 1587*0Sstevel@tonic-gate return; 1588*0Sstevel@tonic-gate } 1589*0Sstevel@tonic-gate sctp->sctp_sendq_sending = B_TRUE; 1590*0Sstevel@tonic-gate 1591*0Sstevel@tonic-gate /* 1592*0Sstevel@tonic-gate * Note that while we are in this loop, other thread can put 1593*0Sstevel@tonic-gate * new packets in the receive queue. We may be looping for 1594*0Sstevel@tonic-gate * quite a while. This is OK even for an interrupt thread. 1595*0Sstevel@tonic-gate * The reason is that SCTP should only able to send a limited 1596*0Sstevel@tonic-gate * number of packets out in a burst. So the number of times 1597*0Sstevel@tonic-gate * we go through this loop should not be many. 1598*0Sstevel@tonic-gate */ 1599*0Sstevel@tonic-gate while ((mp = sctp->sctp_sendq) != NULL) { 1600*0Sstevel@tonic-gate sctp->sctp_sendq = mp->b_next; 1601*0Sstevel@tonic-gate ASSERT(sctp->sctp_connp->conn_ref > 0); 1602*0Sstevel@tonic-gate mutex_exit(&sctp->sctp_sendq_lock); 1603*0Sstevel@tonic-gate mp->b_next = NULL; 1604*0Sstevel@tonic-gate CONN_INC_REF(sctp->sctp_connp); 1605*0Sstevel@tonic-gate mp->b_flag |= MSGHASREF; 1606*0Sstevel@tonic-gate /* If we don't have sctp_current, default to IPv4 */ 1607*0Sstevel@tonic-gate IP_PUT(mp, sctp->sctp_connp, sctp->sctp_current == NULL ? 1608*0Sstevel@tonic-gate B_TRUE : sctp->sctp_current->isv4); 1609*0Sstevel@tonic-gate BUMP_LOCAL(sctp->sctp_opkts); 1610*0Sstevel@tonic-gate #ifdef DEBUG 1611*0Sstevel@tonic-gate loop_cnt++; 1612*0Sstevel@tonic-gate #endif 1613*0Sstevel@tonic-gate mutex_enter(&sctp->sctp_sendq_lock); 1614*0Sstevel@tonic-gate } 1615*0Sstevel@tonic-gate 1616*0Sstevel@tonic-gate sctp->sctp_sendq_tail = NULL; 1617*0Sstevel@tonic-gate sctp->sctp_sendq_sending = B_FALSE; 1618*0Sstevel@tonic-gate #ifdef DEBUG 1619*0Sstevel@tonic-gate if (loop_cnt > sendq_loop_cnt) 1620*0Sstevel@tonic-gate sendq_loop_cnt = loop_cnt; 1621*0Sstevel@tonic-gate #endif 1622*0Sstevel@tonic-gate mutex_exit(&sctp->sctp_sendq_lock); 1623*0Sstevel@tonic-gate } 1624*0Sstevel@tonic-gate 1625*0Sstevel@tonic-gate #ifdef DEBUG 1626*0Sstevel@tonic-gate uint32_t recvq_loop_cnt = 0; 1627*0Sstevel@tonic-gate uint32_t recvq_call = 0; 1628*0Sstevel@tonic-gate #endif 1629*0Sstevel@tonic-gate 1630*0Sstevel@tonic-gate /* 1631*0Sstevel@tonic-gate * Find the next recvq_tq to use. This routine will go thru all the 1632*0Sstevel@tonic-gate * taskqs until it can dispatch a job for the sctp. If this fails, 1633*0Sstevel@tonic-gate * it will create a new taskq and try it. 1634*0Sstevel@tonic-gate */ 1635*0Sstevel@tonic-gate static boolean_t 1636*0Sstevel@tonic-gate sctp_find_next_tq(sctp_t *sctp) 1637*0Sstevel@tonic-gate { 1638*0Sstevel@tonic-gate int next_tq, try; 1639*0Sstevel@tonic-gate taskq_t *tq; 1640*0Sstevel@tonic-gate 1641*0Sstevel@tonic-gate /* 1642*0Sstevel@tonic-gate * Note that since we don't hold a lock on sctp_rq_tq_lock for 1643*0Sstevel@tonic-gate * performance reason, recvq_ta_list_cur_sz can be changed during 1644*0Sstevel@tonic-gate * this loop. The problem this will create is that the loop may 1645*0Sstevel@tonic-gate * not have tried all the recvq_tq. This should be OK. 1646*0Sstevel@tonic-gate */ 1647*0Sstevel@tonic-gate next_tq = atomic_add_32_nv(&recvq_tq_list_cur, 1) % 1648*0Sstevel@tonic-gate recvq_tq_list_cur_sz; 1649*0Sstevel@tonic-gate for (try = 0; try < recvq_tq_list_cur_sz; 1650*0Sstevel@tonic-gate try++, next_tq = (next_tq + 1) % recvq_tq_list_cur_sz) { 1651*0Sstevel@tonic-gate tq = recvq_tq_list[next_tq]; 1652*0Sstevel@tonic-gate if (taskq_dispatch(tq, sctp_process_recvq, sctp, 1653*0Sstevel@tonic-gate TQ_NOSLEEP) != NULL) { 1654*0Sstevel@tonic-gate sctp->sctp_recvq_tq = tq; 1655*0Sstevel@tonic-gate return (B_TRUE); 1656*0Sstevel@tonic-gate } 1657*0Sstevel@tonic-gate } 1658*0Sstevel@tonic-gate 1659*0Sstevel@tonic-gate /* 1660*0Sstevel@tonic-gate * Create one more taskq and try it. Note that sctp_inc_taskq() 1661*0Sstevel@tonic-gate * may not have created another taskq if the number of recvq 1662*0Sstevel@tonic-gate * taskqs is at the maximum. We are probably in a pretty bad 1663*0Sstevel@tonic-gate * shape if this actually happens... 1664*0Sstevel@tonic-gate */ 1665*0Sstevel@tonic-gate sctp_inc_taskq(); 1666*0Sstevel@tonic-gate tq = recvq_tq_list[recvq_tq_list_cur_sz - 1]; 1667*0Sstevel@tonic-gate if (taskq_dispatch(tq, sctp_process_recvq, sctp, TQ_NOSLEEP) != NULL) { 1668*0Sstevel@tonic-gate sctp->sctp_recvq_tq = tq; 1669*0Sstevel@tonic-gate return (B_TRUE); 1670*0Sstevel@tonic-gate } 1671*0Sstevel@tonic-gate return (B_FALSE); 1672*0Sstevel@tonic-gate } 1673*0Sstevel@tonic-gate 1674*0Sstevel@tonic-gate /* 1675*0Sstevel@tonic-gate * To add a message to the recvq. Note that the sctp_timer_fire() 1676*0Sstevel@tonic-gate * routine also uses this function to add the timer message to the 1677*0Sstevel@tonic-gate * receive queue for later processing. And it should be the only 1678*0Sstevel@tonic-gate * caller of sctp_add_recvq() which sets the try_harder argument 1679*0Sstevel@tonic-gate * to B_TRUE. 1680*0Sstevel@tonic-gate * 1681*0Sstevel@tonic-gate * If the try_harder argument is B_TRUE, this routine sctp_find_next_tq() 1682*0Sstevel@tonic-gate * will try very hard to dispatch the task. Refer to the comment 1683*0Sstevel@tonic-gate * for that routine on how it does that. 1684*0Sstevel@tonic-gate */ 1685*0Sstevel@tonic-gate boolean_t 1686*0Sstevel@tonic-gate sctp_add_recvq(sctp_t *sctp, mblk_t *mp, boolean_t caller_hold_lock) 1687*0Sstevel@tonic-gate { 1688*0Sstevel@tonic-gate if (!caller_hold_lock) 1689*0Sstevel@tonic-gate mutex_enter(&sctp->sctp_recvq_lock); 1690*0Sstevel@tonic-gate 1691*0Sstevel@tonic-gate /* If the taskq dispatch has not been scheduled, do it now. */ 1692*0Sstevel@tonic-gate if (sctp->sctp_recvq_tq == NULL) { 1693*0Sstevel@tonic-gate ASSERT(sctp->sctp_recvq == NULL); 1694*0Sstevel@tonic-gate if (!sctp_find_next_tq(sctp)) { 1695*0Sstevel@tonic-gate if (!caller_hold_lock) 1696*0Sstevel@tonic-gate mutex_exit(&sctp->sctp_recvq_lock); 1697*0Sstevel@tonic-gate return (B_FALSE); 1698*0Sstevel@tonic-gate } 1699*0Sstevel@tonic-gate /* Make sure the sctp_t will not go away. */ 1700*0Sstevel@tonic-gate SCTP_REFHOLD(sctp); 1701*0Sstevel@tonic-gate } 1702*0Sstevel@tonic-gate 1703*0Sstevel@tonic-gate if (sctp->sctp_recvq == NULL) { 1704*0Sstevel@tonic-gate sctp->sctp_recvq = mp; 1705*0Sstevel@tonic-gate sctp->sctp_recvq_tail = mp; 1706*0Sstevel@tonic-gate } else { 1707*0Sstevel@tonic-gate sctp->sctp_recvq_tail->b_next = mp; 1708*0Sstevel@tonic-gate sctp->sctp_recvq_tail = mp; 1709*0Sstevel@tonic-gate } 1710*0Sstevel@tonic-gate 1711*0Sstevel@tonic-gate if (!caller_hold_lock) 1712*0Sstevel@tonic-gate mutex_exit(&sctp->sctp_recvq_lock); 1713*0Sstevel@tonic-gate return (B_TRUE); 1714*0Sstevel@tonic-gate } 1715*0Sstevel@tonic-gate 1716*0Sstevel@tonic-gate static void 1717*0Sstevel@tonic-gate sctp_process_recvq(void *arg) 1718*0Sstevel@tonic-gate { 1719*0Sstevel@tonic-gate sctp_t *sctp = (sctp_t *)arg; 1720*0Sstevel@tonic-gate mblk_t *mp; 1721*0Sstevel@tonic-gate mblk_t *ipsec_mp; 1722*0Sstevel@tonic-gate #ifdef DEBUG 1723*0Sstevel@tonic-gate uint32_t loop_cnt = 0; 1724*0Sstevel@tonic-gate #endif 1725*0Sstevel@tonic-gate 1726*0Sstevel@tonic-gate #ifdef _BIG_ENDIAN 1727*0Sstevel@tonic-gate #define IPVER(ip6h) ((((uint32_t *)ip6h)[0] >> 28) & 0x7) 1728*0Sstevel@tonic-gate #else 1729*0Sstevel@tonic-gate #define IPVER(ip6h) ((((uint32_t *)ip6h)[0] >> 4) & 0x7) 1730*0Sstevel@tonic-gate #endif 1731*0Sstevel@tonic-gate 1732*0Sstevel@tonic-gate RUN_SCTP(sctp); 1733*0Sstevel@tonic-gate mutex_enter(&sctp->sctp_recvq_lock); 1734*0Sstevel@tonic-gate 1735*0Sstevel@tonic-gate #ifdef DEBUG 1736*0Sstevel@tonic-gate recvq_call++; 1737*0Sstevel@tonic-gate #endif 1738*0Sstevel@tonic-gate /* 1739*0Sstevel@tonic-gate * Note that while we are in this loop, other thread can put 1740*0Sstevel@tonic-gate * new packets in the receive queue. We may be looping for 1741*0Sstevel@tonic-gate * quite a while. 1742*0Sstevel@tonic-gate */ 1743*0Sstevel@tonic-gate while ((mp = sctp->sctp_recvq) != NULL) { 1744*0Sstevel@tonic-gate sctp->sctp_recvq = mp->b_next; 1745*0Sstevel@tonic-gate mutex_exit(&sctp->sctp_recvq_lock); 1746*0Sstevel@tonic-gate mp->b_next = NULL; 1747*0Sstevel@tonic-gate #ifdef DEBUG 1748*0Sstevel@tonic-gate loop_cnt++; 1749*0Sstevel@tonic-gate #endif 1750*0Sstevel@tonic-gate ipsec_mp = mp->b_prev; 1751*0Sstevel@tonic-gate mp->b_prev = NULL; 1752*0Sstevel@tonic-gate sctp_input_data(sctp, mp, ipsec_mp); 1753*0Sstevel@tonic-gate 1754*0Sstevel@tonic-gate mutex_enter(&sctp->sctp_recvq_lock); 1755*0Sstevel@tonic-gate } 1756*0Sstevel@tonic-gate 1757*0Sstevel@tonic-gate sctp->sctp_recvq_tail = NULL; 1758*0Sstevel@tonic-gate sctp->sctp_recvq_tq = NULL; 1759*0Sstevel@tonic-gate 1760*0Sstevel@tonic-gate mutex_exit(&sctp->sctp_recvq_lock); 1761*0Sstevel@tonic-gate 1762*0Sstevel@tonic-gate WAKE_SCTP(sctp); 1763*0Sstevel@tonic-gate 1764*0Sstevel@tonic-gate /* We may have sent something when processing the receive queue. */ 1765*0Sstevel@tonic-gate sctp_process_sendq(sctp); 1766*0Sstevel@tonic-gate #ifdef DEBUG 1767*0Sstevel@tonic-gate if (loop_cnt > recvq_loop_cnt) 1768*0Sstevel@tonic-gate recvq_loop_cnt = loop_cnt; 1769*0Sstevel@tonic-gate #endif 1770*0Sstevel@tonic-gate /* Now it can go away. */ 1771*0Sstevel@tonic-gate SCTP_REFRELE(sctp); 1772*0Sstevel@tonic-gate } 1773*0Sstevel@tonic-gate 1774*0Sstevel@tonic-gate /* ARGSUSED */ 1775*0Sstevel@tonic-gate static int 1776*0Sstevel@tonic-gate sctp_conn_cache_constructor(void *buf, void *cdrarg, int kmflags) 1777*0Sstevel@tonic-gate { 1778*0Sstevel@tonic-gate conn_t *sctp_connp = (conn_t *)buf; 1779*0Sstevel@tonic-gate sctp_t *sctp = (sctp_t *)&sctp_connp[1]; 1780*0Sstevel@tonic-gate 1781*0Sstevel@tonic-gate bzero(buf, (char *)&sctp[1] - (char *)buf); 1782*0Sstevel@tonic-gate 1783*0Sstevel@tonic-gate ASSERT(sctp_g_q != NULL); 1784*0Sstevel@tonic-gate sctp->sctp_connp = sctp_connp; 1785*0Sstevel@tonic-gate mutex_init(&sctp->sctp_reflock, NULL, MUTEX_DEFAULT, NULL); 1786*0Sstevel@tonic-gate mutex_init(&sctp->sctp_lock, NULL, MUTEX_DEFAULT, NULL); 1787*0Sstevel@tonic-gate mutex_init(&sctp->sctp_recvq_lock, NULL, MUTEX_DEFAULT, NULL); 1788*0Sstevel@tonic-gate cv_init(&sctp->sctp_cv, NULL, CV_DEFAULT, NULL); 1789*0Sstevel@tonic-gate mutex_init(&sctp->sctp_sendq_lock, NULL, MUTEX_DEFAULT, NULL); 1790*0Sstevel@tonic-gate 1791*0Sstevel@tonic-gate sctp_connp->conn_rq = sctp_connp->conn_wq = NULL; 1792*0Sstevel@tonic-gate sctp_connp->conn_multicast_loop = IP_DEFAULT_MULTICAST_LOOP; 1793*0Sstevel@tonic-gate sctp_connp->conn_ulp = IPPROTO_SCTP; 1794*0Sstevel@tonic-gate mutex_init(&sctp_connp->conn_lock, NULL, MUTEX_DEFAULT, NULL); 1795*0Sstevel@tonic-gate cv_init(&sctp_connp->conn_cv, NULL, CV_DEFAULT, NULL); 1796*0Sstevel@tonic-gate 1797*0Sstevel@tonic-gate return (0); 1798*0Sstevel@tonic-gate } 1799*0Sstevel@tonic-gate 1800*0Sstevel@tonic-gate /* ARGSUSED */ 1801*0Sstevel@tonic-gate static void 1802*0Sstevel@tonic-gate sctp_conn_cache_destructor(void *buf, void *cdrarg) 1803*0Sstevel@tonic-gate { 1804*0Sstevel@tonic-gate conn_t *sctp_connp = (conn_t *)buf; 1805*0Sstevel@tonic-gate sctp_t *sctp = (sctp_t *)&sctp_connp[1]; 1806*0Sstevel@tonic-gate 1807*0Sstevel@tonic-gate ASSERT(!MUTEX_HELD(&sctp->sctp_lock)); 1808*0Sstevel@tonic-gate ASSERT(!MUTEX_HELD(&sctp->sctp_reflock)); 1809*0Sstevel@tonic-gate ASSERT(!MUTEX_HELD(&sctp->sctp_recvq_lock)); 1810*0Sstevel@tonic-gate ASSERT(!MUTEX_HELD(&sctp->sctp_sendq_lock)); 1811*0Sstevel@tonic-gate ASSERT(!MUTEX_HELD(&sctp->sctp_connp->conn_lock)); 1812*0Sstevel@tonic-gate 1813*0Sstevel@tonic-gate ASSERT(sctp->sctp_conn_hash_next == NULL); 1814*0Sstevel@tonic-gate ASSERT(sctp->sctp_conn_hash_prev == NULL); 1815*0Sstevel@tonic-gate ASSERT(sctp->sctp_listen_hash_next == NULL); 1816*0Sstevel@tonic-gate ASSERT(sctp->sctp_listen_hash_prev == NULL); 1817*0Sstevel@tonic-gate ASSERT(sctp->sctp_listen_tfp == NULL); 1818*0Sstevel@tonic-gate ASSERT(sctp->sctp_conn_tfp == NULL); 1819*0Sstevel@tonic-gate 1820*0Sstevel@tonic-gate ASSERT(sctp->sctp_faddrs == NULL); 1821*0Sstevel@tonic-gate ASSERT(sctp->sctp_nsaddrs == 0); 1822*0Sstevel@tonic-gate 1823*0Sstevel@tonic-gate ASSERT(sctp->sctp_ulpd == NULL); 1824*0Sstevel@tonic-gate 1825*0Sstevel@tonic-gate ASSERT(sctp->sctp_lastfaddr == NULL); 1826*0Sstevel@tonic-gate ASSERT(sctp->sctp_primary == NULL); 1827*0Sstevel@tonic-gate ASSERT(sctp->sctp_current == NULL); 1828*0Sstevel@tonic-gate ASSERT(sctp->sctp_lastdata == NULL); 1829*0Sstevel@tonic-gate 1830*0Sstevel@tonic-gate ASSERT(sctp->sctp_xmit_head == NULL); 1831*0Sstevel@tonic-gate ASSERT(sctp->sctp_xmit_tail == NULL); 1832*0Sstevel@tonic-gate ASSERT(sctp->sctp_xmit_unsent == NULL); 1833*0Sstevel@tonic-gate ASSERT(sctp->sctp_xmit_unsent_tail == NULL); 1834*0Sstevel@tonic-gate 1835*0Sstevel@tonic-gate ASSERT(sctp->sctp_ostrcntrs == NULL); 1836*0Sstevel@tonic-gate 1837*0Sstevel@tonic-gate ASSERT(sctp->sctp_sack_info == NULL); 1838*0Sstevel@tonic-gate ASSERT(sctp->sctp_ack_mp == NULL); 1839*0Sstevel@tonic-gate ASSERT(sctp->sctp_instr == NULL); 1840*0Sstevel@tonic-gate 1841*0Sstevel@tonic-gate ASSERT(sctp->sctp_iphc == NULL); 1842*0Sstevel@tonic-gate ASSERT(sctp->sctp_iphc6 == NULL); 1843*0Sstevel@tonic-gate ASSERT(sctp->sctp_ipha == NULL); 1844*0Sstevel@tonic-gate ASSERT(sctp->sctp_ip6h == NULL); 1845*0Sstevel@tonic-gate ASSERT(sctp->sctp_sctph == NULL); 1846*0Sstevel@tonic-gate ASSERT(sctp->sctp_sctph6 == NULL); 1847*0Sstevel@tonic-gate 1848*0Sstevel@tonic-gate ASSERT(sctp->sctp_cookie_mp == NULL); 1849*0Sstevel@tonic-gate 1850*0Sstevel@tonic-gate ASSERT(sctp->sctp_refcnt == 0); 1851*0Sstevel@tonic-gate ASSERT(sctp->sctp_timer_mp == NULL); 1852*0Sstevel@tonic-gate ASSERT(sctp->sctp_connp->conn_ref == 0); 1853*0Sstevel@tonic-gate ASSERT(sctp->sctp_heartbeat_mp == NULL); 1854*0Sstevel@tonic-gate ASSERT(sctp->sctp_ptpbhn == NULL && sctp->sctp_bind_hash == NULL); 1855*0Sstevel@tonic-gate 1856*0Sstevel@tonic-gate ASSERT(sctp->sctp_shutdown_faddr == NULL); 1857*0Sstevel@tonic-gate 1858*0Sstevel@tonic-gate ASSERT(sctp->sctp_cxmit_list == NULL); 1859*0Sstevel@tonic-gate 1860*0Sstevel@tonic-gate ASSERT(sctp->sctp_recvq == NULL); 1861*0Sstevel@tonic-gate ASSERT(sctp->sctp_recvq_tail == NULL); 1862*0Sstevel@tonic-gate ASSERT(sctp->sctp_recvq_tq == NULL); 1863*0Sstevel@tonic-gate 1864*0Sstevel@tonic-gate ASSERT(sctp->sctp_sendq == NULL); 1865*0Sstevel@tonic-gate ASSERT(sctp->sctp_sendq_tail == NULL); 1866*0Sstevel@tonic-gate ASSERT(sctp->sctp_sendq_sending == B_FALSE); 1867*0Sstevel@tonic-gate 1868*0Sstevel@tonic-gate mutex_destroy(&sctp->sctp_reflock); 1869*0Sstevel@tonic-gate mutex_destroy(&sctp->sctp_lock); 1870*0Sstevel@tonic-gate mutex_destroy(&sctp->sctp_recvq_lock); 1871*0Sstevel@tonic-gate cv_destroy(&sctp->sctp_cv); 1872*0Sstevel@tonic-gate mutex_destroy(&sctp->sctp_sendq_lock); 1873*0Sstevel@tonic-gate 1874*0Sstevel@tonic-gate mutex_destroy(&sctp_connp->conn_lock); 1875*0Sstevel@tonic-gate cv_destroy(&sctp_connp->conn_cv); 1876*0Sstevel@tonic-gate } 1877*0Sstevel@tonic-gate 1878*0Sstevel@tonic-gate static void 1879*0Sstevel@tonic-gate sctp_conn_cache_init() 1880*0Sstevel@tonic-gate { 1881*0Sstevel@tonic-gate sctp_conn_cache = kmem_cache_create("sctp_conn_cache", 1882*0Sstevel@tonic-gate sizeof (sctp_t) + sizeof (conn_t), 0, sctp_conn_cache_constructor, 1883*0Sstevel@tonic-gate sctp_conn_cache_destructor, NULL, NULL, NULL, 0); 1884*0Sstevel@tonic-gate } 1885*0Sstevel@tonic-gate 1886*0Sstevel@tonic-gate static void 1887*0Sstevel@tonic-gate sctp_conn_cache_fini() 1888*0Sstevel@tonic-gate { 1889*0Sstevel@tonic-gate kmem_cache_destroy(sctp_conn_cache); 1890*0Sstevel@tonic-gate } 1891