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