1*0Sstevel@tonic-gate /* 2*0Sstevel@tonic-gate * CDDL HEADER START 3*0Sstevel@tonic-gate * 4*0Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*0Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*0Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*0Sstevel@tonic-gate * with the License. 8*0Sstevel@tonic-gate * 9*0Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*0Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*0Sstevel@tonic-gate * See the License for the specific language governing permissions 12*0Sstevel@tonic-gate * and limitations under the License. 13*0Sstevel@tonic-gate * 14*0Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*0Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*0Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*0Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*0Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*0Sstevel@tonic-gate * 20*0Sstevel@tonic-gate * CDDL HEADER END 21*0Sstevel@tonic-gate */ 22*0Sstevel@tonic-gate /* 23*0Sstevel@tonic-gate * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24*0Sstevel@tonic-gate * Use is subject to license terms. 25*0Sstevel@tonic-gate */ 26*0Sstevel@tonic-gate 27*0Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*0Sstevel@tonic-gate 29*0Sstevel@tonic-gate #include <sys/types.h> 30*0Sstevel@tonic-gate #include <sys/inttypes.h> 31*0Sstevel@tonic-gate #include <sys/t_lock.h> 32*0Sstevel@tonic-gate #include <sys/param.h> 33*0Sstevel@tonic-gate #include <sys/systm.h> 34*0Sstevel@tonic-gate #include <sys/buf.h> 35*0Sstevel@tonic-gate #include <sys/conf.h> 36*0Sstevel@tonic-gate #include <sys/cred.h> 37*0Sstevel@tonic-gate #include <sys/kmem.h> 38*0Sstevel@tonic-gate #include <sys/sysmacros.h> 39*0Sstevel@tonic-gate #include <sys/vfs.h> 40*0Sstevel@tonic-gate #include <sys/vnode.h> 41*0Sstevel@tonic-gate #include <sys/debug.h> 42*0Sstevel@tonic-gate #include <sys/errno.h> 43*0Sstevel@tonic-gate #include <sys/time.h> 44*0Sstevel@tonic-gate #include <sys/file.h> 45*0Sstevel@tonic-gate #include <sys/user.h> 46*0Sstevel@tonic-gate #include <sys/stream.h> 47*0Sstevel@tonic-gate #include <sys/strsubr.h> 48*0Sstevel@tonic-gate #include <sys/esunddi.h> 49*0Sstevel@tonic-gate #include <sys/flock.h> 50*0Sstevel@tonic-gate #include <sys/modctl.h> 51*0Sstevel@tonic-gate #include <sys/vtrace.h> 52*0Sstevel@tonic-gate #include <sys/strsun.h> 53*0Sstevel@tonic-gate #include <sys/cmn_err.h> 54*0Sstevel@tonic-gate #include <sys/proc.h> 55*0Sstevel@tonic-gate #include <sys/ddi.h> 56*0Sstevel@tonic-gate #include <sys/kmem_impl.h> 57*0Sstevel@tonic-gate 58*0Sstevel@tonic-gate #include <sys/suntpi.h> 59*0Sstevel@tonic-gate #include <sys/socket.h> 60*0Sstevel@tonic-gate #include <sys/sockio.h> 61*0Sstevel@tonic-gate #include <sys/socketvar.h> 62*0Sstevel@tonic-gate #include <netinet/in.h> 63*0Sstevel@tonic-gate 64*0Sstevel@tonic-gate #include <sys/tiuser.h> 65*0Sstevel@tonic-gate #define _SUN_TPI_VERSION 2 66*0Sstevel@tonic-gate #include <sys/tihdr.h> 67*0Sstevel@tonic-gate 68*0Sstevel@tonic-gate #include <c2/audit.h> 69*0Sstevel@tonic-gate 70*0Sstevel@tonic-gate int so_default_version = SOV_SOCKSTREAM; 71*0Sstevel@tonic-gate 72*0Sstevel@tonic-gate #ifdef DEBUG 73*0Sstevel@tonic-gate /* Set sockdebug to print debug messages when SO_DEBUG is set */ 74*0Sstevel@tonic-gate int sockdebug = 0; 75*0Sstevel@tonic-gate 76*0Sstevel@tonic-gate /* Set sockprinterr to print error messages when SO_DEBUG is set */ 77*0Sstevel@tonic-gate int sockprinterr = 0; 78*0Sstevel@tonic-gate 79*0Sstevel@tonic-gate /* 80*0Sstevel@tonic-gate * Set so_default_options to SO_DEBUG is all sockets should be created 81*0Sstevel@tonic-gate * with SO_DEBUG set. This is needed to get debug printouts from the 82*0Sstevel@tonic-gate * socket() call itself. 83*0Sstevel@tonic-gate */ 84*0Sstevel@tonic-gate int so_default_options = 0; 85*0Sstevel@tonic-gate #endif /* DEBUG */ 86*0Sstevel@tonic-gate 87*0Sstevel@tonic-gate #ifdef SOCK_TEST 88*0Sstevel@tonic-gate /* 89*0Sstevel@tonic-gate * Set to number of ticks to limit cv_waits for code coverage testing. 90*0Sstevel@tonic-gate * Set to 1000 when SO_DEBUG is set to 2. 91*0Sstevel@tonic-gate */ 92*0Sstevel@tonic-gate clock_t sock_test_timelimit = 0; 93*0Sstevel@tonic-gate #endif /* SOCK_TEST */ 94*0Sstevel@tonic-gate 95*0Sstevel@tonic-gate /* 96*0Sstevel@tonic-gate * For concurrency testing of e.g. opening /dev/ip which does not 97*0Sstevel@tonic-gate * handle T_INFO_REQ messages. 98*0Sstevel@tonic-gate */ 99*0Sstevel@tonic-gate int so_no_tinfo = 0; 100*0Sstevel@tonic-gate 101*0Sstevel@tonic-gate /* 102*0Sstevel@tonic-gate * Timeout for getting a T_CAPABILITY_ACK - it is possible for a provider 103*0Sstevel@tonic-gate * to simply ignore the T_CAPABILITY_REQ. 104*0Sstevel@tonic-gate */ 105*0Sstevel@tonic-gate clock_t sock_capability_timeout = 2; /* seconds */ 106*0Sstevel@tonic-gate 107*0Sstevel@tonic-gate static int do_tcapability(struct sonode *so, t_uscalar_t cap_bits1); 108*0Sstevel@tonic-gate static void so_removehooks(struct sonode *so); 109*0Sstevel@tonic-gate 110*0Sstevel@tonic-gate static mblk_t *strsock_proto(vnode_t *vp, mblk_t *mp, 111*0Sstevel@tonic-gate strwakeup_t *wakeups, strsigset_t *firstmsgsigs, 112*0Sstevel@tonic-gate strsigset_t *allmsgsigs, strpollset_t *pollwakeups); 113*0Sstevel@tonic-gate static mblk_t *strsock_misc(vnode_t *vp, mblk_t *mp, 114*0Sstevel@tonic-gate strwakeup_t *wakeups, strsigset_t *firstmsgsigs, 115*0Sstevel@tonic-gate strsigset_t *allmsgsigs, strpollset_t *pollwakeups); 116*0Sstevel@tonic-gate 117*0Sstevel@tonic-gate static int tlitosyserr(int terr); 118*0Sstevel@tonic-gate 119*0Sstevel@tonic-gate /* 120*0Sstevel@tonic-gate * Convert a socket to a stream. Invoked when the illusory sockmod 121*0Sstevel@tonic-gate * is popped from the stream. 122*0Sstevel@tonic-gate * Change the stream head back to default operation without losing 123*0Sstevel@tonic-gate * any messages (T_conn_ind's are moved to the stream head queue). 124*0Sstevel@tonic-gate */ 125*0Sstevel@tonic-gate int 126*0Sstevel@tonic-gate so_sock2stream(struct sonode *so) 127*0Sstevel@tonic-gate { 128*0Sstevel@tonic-gate struct vnode *vp = SOTOV(so); 129*0Sstevel@tonic-gate queue_t *rq; 130*0Sstevel@tonic-gate mblk_t *mp; 131*0Sstevel@tonic-gate int error = 0; 132*0Sstevel@tonic-gate 133*0Sstevel@tonic-gate ASSERT(MUTEX_HELD(&so->so_plumb_lock)); 134*0Sstevel@tonic-gate 135*0Sstevel@tonic-gate mutex_enter(&so->so_lock); 136*0Sstevel@tonic-gate so_lock_single(so); 137*0Sstevel@tonic-gate 138*0Sstevel@tonic-gate ASSERT(so->so_version != SOV_STREAM); 139*0Sstevel@tonic-gate 140*0Sstevel@tonic-gate /* tell the transport below that sockmod is being popped */ 141*0Sstevel@tonic-gate if ((so->so_state & SS_TCP_FAST_ACCEPT) != 0) { 142*0Sstevel@tonic-gate int rval; 143*0Sstevel@tonic-gate mblk_t **mpp; 144*0Sstevel@tonic-gate 145*0Sstevel@tonic-gate mutex_exit(&so->so_lock); 146*0Sstevel@tonic-gate error = strioctl(vp, SIOCPOPSOCKFS, NULL, 0, K_TO_K, CRED(), 147*0Sstevel@tonic-gate &rval); 148*0Sstevel@tonic-gate mutex_enter(&so->so_lock); 149*0Sstevel@tonic-gate if (error != 0) { 150*0Sstevel@tonic-gate dprintso(so, 0, 151*0Sstevel@tonic-gate ("so_sock2stream(%p): SIOCPOPSOCKFS failed\n", so)); 152*0Sstevel@tonic-gate goto exit; 153*0Sstevel@tonic-gate } 154*0Sstevel@tonic-gate so->so_state &= ~SS_TCP_FAST_ACCEPT; 155*0Sstevel@tonic-gate 156*0Sstevel@tonic-gate for (mpp = &so->so_conn_ind_head; (mp = *mpp) != NULL; 157*0Sstevel@tonic-gate mpp = &mp->b_next) { 158*0Sstevel@tonic-gate struct T_conn_ind *conn_ind; 159*0Sstevel@tonic-gate 160*0Sstevel@tonic-gate /* 161*0Sstevel@tonic-gate * strsock_proto() has already verified the length of 162*0Sstevel@tonic-gate * this message block. 163*0Sstevel@tonic-gate */ 164*0Sstevel@tonic-gate ASSERT(MBLKL(mp) >= sizeof (struct T_conn_ind)); 165*0Sstevel@tonic-gate 166*0Sstevel@tonic-gate conn_ind = (struct T_conn_ind *)mp->b_rptr; 167*0Sstevel@tonic-gate if (conn_ind->OPT_length == 0 && 168*0Sstevel@tonic-gate conn_ind->OPT_offset == 0) 169*0Sstevel@tonic-gate continue; 170*0Sstevel@tonic-gate 171*0Sstevel@tonic-gate if (DB_REF(mp) > 1) { 172*0Sstevel@tonic-gate mblk_t *newmp; 173*0Sstevel@tonic-gate size_t length; 174*0Sstevel@tonic-gate cred_t *cr; 175*0Sstevel@tonic-gate 176*0Sstevel@tonic-gate /* 177*0Sstevel@tonic-gate * Copy the message block because it is used 178*0Sstevel@tonic-gate * elsewhere, too. 179*0Sstevel@tonic-gate */ 180*0Sstevel@tonic-gate length = MBLKL(mp); 181*0Sstevel@tonic-gate newmp = soallocproto(length, _ALLOC_INTR); 182*0Sstevel@tonic-gate if (newmp == NULL) { 183*0Sstevel@tonic-gate error = EINTR; 184*0Sstevel@tonic-gate goto exit; 185*0Sstevel@tonic-gate } 186*0Sstevel@tonic-gate bcopy(mp->b_rptr, newmp->b_wptr, length); 187*0Sstevel@tonic-gate newmp->b_wptr += length; 188*0Sstevel@tonic-gate newmp->b_next = mp->b_next; 189*0Sstevel@tonic-gate cr = DB_CRED(mp); 190*0Sstevel@tonic-gate if (cr != NULL) 191*0Sstevel@tonic-gate mblk_setcred(newmp, cr); 192*0Sstevel@tonic-gate DB_CPID(newmp) = DB_CPID(mp); 193*0Sstevel@tonic-gate 194*0Sstevel@tonic-gate /* 195*0Sstevel@tonic-gate * Link the new message block into the queue 196*0Sstevel@tonic-gate * and free the old one. 197*0Sstevel@tonic-gate */ 198*0Sstevel@tonic-gate *mpp = newmp; 199*0Sstevel@tonic-gate mp->b_next = NULL; 200*0Sstevel@tonic-gate freemsg(mp); 201*0Sstevel@tonic-gate 202*0Sstevel@tonic-gate mp = newmp; 203*0Sstevel@tonic-gate conn_ind = (struct T_conn_ind *)mp->b_rptr; 204*0Sstevel@tonic-gate } 205*0Sstevel@tonic-gate 206*0Sstevel@tonic-gate /* 207*0Sstevel@tonic-gate * Remove options added by TCP for accept fast-path. 208*0Sstevel@tonic-gate */ 209*0Sstevel@tonic-gate conn_ind->OPT_length = 0; 210*0Sstevel@tonic-gate conn_ind->OPT_offset = 0; 211*0Sstevel@tonic-gate } 212*0Sstevel@tonic-gate } 213*0Sstevel@tonic-gate 214*0Sstevel@tonic-gate so->so_version = SOV_STREAM; 215*0Sstevel@tonic-gate so->so_priv = NULL; 216*0Sstevel@tonic-gate 217*0Sstevel@tonic-gate /* 218*0Sstevel@tonic-gate * Remove the hooks in the stream head to avoid queuing more 219*0Sstevel@tonic-gate * packets in sockfs. 220*0Sstevel@tonic-gate */ 221*0Sstevel@tonic-gate mutex_exit(&so->so_lock); 222*0Sstevel@tonic-gate so_removehooks(so); 223*0Sstevel@tonic-gate mutex_enter(&so->so_lock); 224*0Sstevel@tonic-gate 225*0Sstevel@tonic-gate /* 226*0Sstevel@tonic-gate * Clear any state related to urgent data. Leave any T_EXDATA_IND 227*0Sstevel@tonic-gate * on the queue - the behavior of urgent data after a switch is 228*0Sstevel@tonic-gate * left undefined. 229*0Sstevel@tonic-gate */ 230*0Sstevel@tonic-gate so->so_error = so->so_delayed_error = 0; 231*0Sstevel@tonic-gate freemsg(so->so_oobmsg); 232*0Sstevel@tonic-gate so->so_oobmsg = NULL; 233*0Sstevel@tonic-gate so->so_oobsigcnt = so->so_oobcnt = 0; 234*0Sstevel@tonic-gate 235*0Sstevel@tonic-gate so->so_state &= ~(SS_RCVATMARK|SS_OOBPEND|SS_HAVEOOBDATA|SS_HADOOBDATA| 236*0Sstevel@tonic-gate SS_HASCONNIND|SS_SAVEDEOR); 237*0Sstevel@tonic-gate ASSERT(so_verify_oobstate(so)); 238*0Sstevel@tonic-gate 239*0Sstevel@tonic-gate freemsg(so->so_ack_mp); 240*0Sstevel@tonic-gate so->so_ack_mp = NULL; 241*0Sstevel@tonic-gate 242*0Sstevel@tonic-gate /* 243*0Sstevel@tonic-gate * Flush the T_DISCON_IND on so_discon_ind_mp. 244*0Sstevel@tonic-gate */ 245*0Sstevel@tonic-gate so_flush_discon_ind(so); 246*0Sstevel@tonic-gate 247*0Sstevel@tonic-gate /* 248*0Sstevel@tonic-gate * Move any queued T_CONN_IND messages to stream head queue. 249*0Sstevel@tonic-gate */ 250*0Sstevel@tonic-gate rq = RD(strvp2wq(vp)); 251*0Sstevel@tonic-gate while ((mp = so->so_conn_ind_head) != NULL) { 252*0Sstevel@tonic-gate so->so_conn_ind_head = mp->b_next; 253*0Sstevel@tonic-gate mp->b_next = NULL; 254*0Sstevel@tonic-gate if (so->so_conn_ind_head == NULL) { 255*0Sstevel@tonic-gate ASSERT(so->so_conn_ind_tail == mp); 256*0Sstevel@tonic-gate so->so_conn_ind_tail = NULL; 257*0Sstevel@tonic-gate } 258*0Sstevel@tonic-gate dprintso(so, 0, 259*0Sstevel@tonic-gate ("so_sock2stream(%p): moving T_CONN_IND\n", 260*0Sstevel@tonic-gate so)); 261*0Sstevel@tonic-gate 262*0Sstevel@tonic-gate /* Drop lock across put() */ 263*0Sstevel@tonic-gate mutex_exit(&so->so_lock); 264*0Sstevel@tonic-gate put(rq, mp); 265*0Sstevel@tonic-gate mutex_enter(&so->so_lock); 266*0Sstevel@tonic-gate } 267*0Sstevel@tonic-gate 268*0Sstevel@tonic-gate exit: 269*0Sstevel@tonic-gate ASSERT(MUTEX_HELD(&so->so_lock)); 270*0Sstevel@tonic-gate so_unlock_single(so, SOLOCKED); 271*0Sstevel@tonic-gate mutex_exit(&so->so_lock); 272*0Sstevel@tonic-gate return (error); 273*0Sstevel@tonic-gate } 274*0Sstevel@tonic-gate 275*0Sstevel@tonic-gate /* 276*0Sstevel@tonic-gate * Covert a stream back to a socket. This is invoked when the illusory 277*0Sstevel@tonic-gate * sockmod is pushed on a stream (where the stream was "created" by 278*0Sstevel@tonic-gate * popping the illusory sockmod). 279*0Sstevel@tonic-gate * This routine can not recreate the socket state (certain aspects of 280*0Sstevel@tonic-gate * it like urgent data state and the bound/connected addresses for AF_UNIX 281*0Sstevel@tonic-gate * sockets can not be recreated by asking the transport for information). 282*0Sstevel@tonic-gate * Thus this routine implicitly assumes that the socket is in an initial 283*0Sstevel@tonic-gate * state (as if it was just created). It flushes any messages queued on the 284*0Sstevel@tonic-gate * read queue to avoid dealing with e.g. TPI acks or T_exdata_ind messages. 285*0Sstevel@tonic-gate */ 286*0Sstevel@tonic-gate void 287*0Sstevel@tonic-gate so_stream2sock(struct sonode *so) 288*0Sstevel@tonic-gate { 289*0Sstevel@tonic-gate struct vnode *vp = SOTOV(so); 290*0Sstevel@tonic-gate 291*0Sstevel@tonic-gate ASSERT(MUTEX_HELD(&so->so_plumb_lock)); 292*0Sstevel@tonic-gate 293*0Sstevel@tonic-gate mutex_enter(&so->so_lock); 294*0Sstevel@tonic-gate so_lock_single(so); 295*0Sstevel@tonic-gate ASSERT(so->so_version == SOV_STREAM); 296*0Sstevel@tonic-gate so->so_version = SOV_SOCKSTREAM; 297*0Sstevel@tonic-gate so->so_pushcnt = 0; 298*0Sstevel@tonic-gate mutex_exit(&so->so_lock); 299*0Sstevel@tonic-gate 300*0Sstevel@tonic-gate /* 301*0Sstevel@tonic-gate * Set a permenent error to force any thread in sorecvmsg to 302*0Sstevel@tonic-gate * return (and drop SOREADLOCKED). Clear the error once 303*0Sstevel@tonic-gate * we have SOREADLOCKED. 304*0Sstevel@tonic-gate * This makes a read sleeping during the I_PUSH of sockmod return 305*0Sstevel@tonic-gate * EIO. 306*0Sstevel@tonic-gate */ 307*0Sstevel@tonic-gate strsetrerror(SOTOV(so), EIO, 1, NULL); 308*0Sstevel@tonic-gate 309*0Sstevel@tonic-gate /* 310*0Sstevel@tonic-gate * Get the read lock before flushing data to avoid 311*0Sstevel@tonic-gate * problems with the T_EXDATA_IND MSG_PEEK code in sorecvmsg. 312*0Sstevel@tonic-gate */ 313*0Sstevel@tonic-gate mutex_enter(&so->so_lock); 314*0Sstevel@tonic-gate (void) so_lock_read(so, 0); /* Set SOREADLOCKED */ 315*0Sstevel@tonic-gate mutex_exit(&so->so_lock); 316*0Sstevel@tonic-gate 317*0Sstevel@tonic-gate strsetrerror(SOTOV(so), 0, 0, NULL); 318*0Sstevel@tonic-gate so_installhooks(so); 319*0Sstevel@tonic-gate 320*0Sstevel@tonic-gate /* 321*0Sstevel@tonic-gate * Flush everything on the read queue. 322*0Sstevel@tonic-gate * This ensures that no T_CONN_IND remain and that no T_EXDATA_IND 323*0Sstevel@tonic-gate * remain; those types of messages would confuse sockfs. 324*0Sstevel@tonic-gate */ 325*0Sstevel@tonic-gate strflushrq(vp, FLUSHALL); 326*0Sstevel@tonic-gate mutex_enter(&so->so_lock); 327*0Sstevel@tonic-gate 328*0Sstevel@tonic-gate /* 329*0Sstevel@tonic-gate * Flush the T_DISCON_IND on so_discon_ind_mp. 330*0Sstevel@tonic-gate */ 331*0Sstevel@tonic-gate so_flush_discon_ind(so); 332*0Sstevel@tonic-gate so_unlock_read(so); /* Clear SOREADLOCKED */ 333*0Sstevel@tonic-gate 334*0Sstevel@tonic-gate so_unlock_single(so, SOLOCKED); 335*0Sstevel@tonic-gate mutex_exit(&so->so_lock); 336*0Sstevel@tonic-gate } 337*0Sstevel@tonic-gate 338*0Sstevel@tonic-gate /* 339*0Sstevel@tonic-gate * Install the hooks in the stream head. 340*0Sstevel@tonic-gate */ 341*0Sstevel@tonic-gate void 342*0Sstevel@tonic-gate so_installhooks(struct sonode *so) 343*0Sstevel@tonic-gate { 344*0Sstevel@tonic-gate struct vnode *vp = SOTOV(so); 345*0Sstevel@tonic-gate 346*0Sstevel@tonic-gate strsetrputhooks(vp, SH_SIGALLDATA | SH_IGN_ZEROLEN | SH_CONSOL_DATA, 347*0Sstevel@tonic-gate strsock_proto, strsock_misc); 348*0Sstevel@tonic-gate strsetwputhooks(vp, SH_SIGPIPE | SH_RECHECK_ERR, 0); 349*0Sstevel@tonic-gate } 350*0Sstevel@tonic-gate 351*0Sstevel@tonic-gate /* 352*0Sstevel@tonic-gate * Remove the hooks in the stream head. 353*0Sstevel@tonic-gate */ 354*0Sstevel@tonic-gate static void 355*0Sstevel@tonic-gate so_removehooks(struct sonode *so) 356*0Sstevel@tonic-gate { 357*0Sstevel@tonic-gate struct vnode *vp = SOTOV(so); 358*0Sstevel@tonic-gate 359*0Sstevel@tonic-gate strsetrputhooks(vp, 0, NULL, NULL); 360*0Sstevel@tonic-gate strsetwputhooks(vp, 0, STRTIMOUT); 361*0Sstevel@tonic-gate /* 362*0Sstevel@tonic-gate * Leave read behavior as it would have been for a normal 363*0Sstevel@tonic-gate * stream i.e. a read of an M_PROTO will fail. 364*0Sstevel@tonic-gate */ 365*0Sstevel@tonic-gate } 366*0Sstevel@tonic-gate 367*0Sstevel@tonic-gate /* 368*0Sstevel@tonic-gate * Initialize the streams side of a socket including 369*0Sstevel@tonic-gate * T_info_req/ack processing. If tso is not NULL its values are used thereby 370*0Sstevel@tonic-gate * avoiding the T_INFO_REQ. 371*0Sstevel@tonic-gate */ 372*0Sstevel@tonic-gate int 373*0Sstevel@tonic-gate so_strinit(struct sonode *so, struct sonode *tso) 374*0Sstevel@tonic-gate { 375*0Sstevel@tonic-gate struct vnode *vp = SOTOV(so); 376*0Sstevel@tonic-gate struct stdata *stp; 377*0Sstevel@tonic-gate mblk_t *mp; 378*0Sstevel@tonic-gate int error; 379*0Sstevel@tonic-gate 380*0Sstevel@tonic-gate dprintso(so, 1, ("so_strinit(%p)\n", so)); 381*0Sstevel@tonic-gate 382*0Sstevel@tonic-gate /* Preallocate an unbind_req message */ 383*0Sstevel@tonic-gate mp = soallocproto(sizeof (struct T_unbind_req), _ALLOC_SLEEP); 384*0Sstevel@tonic-gate mutex_enter(&so->so_lock); 385*0Sstevel@tonic-gate so->so_unbind_mp = mp; 386*0Sstevel@tonic-gate #ifdef DEBUG 387*0Sstevel@tonic-gate so->so_options = so_default_options; 388*0Sstevel@tonic-gate #endif /* DEBUG */ 389*0Sstevel@tonic-gate mutex_exit(&so->so_lock); 390*0Sstevel@tonic-gate 391*0Sstevel@tonic-gate so_installhooks(so); 392*0Sstevel@tonic-gate 393*0Sstevel@tonic-gate /* 394*0Sstevel@tonic-gate * The T_CAPABILITY_REQ should be the first message sent down because 395*0Sstevel@tonic-gate * at least TCP has a fast-path for this which avoids timeouts while 396*0Sstevel@tonic-gate * waiting for the T_CAPABILITY_ACK under high system load. 397*0Sstevel@tonic-gate */ 398*0Sstevel@tonic-gate if (tso == NULL) { 399*0Sstevel@tonic-gate error = do_tcapability(so, TC1_ACCEPTOR_ID | TC1_INFO); 400*0Sstevel@tonic-gate if (error) 401*0Sstevel@tonic-gate return (error); 402*0Sstevel@tonic-gate } else { 403*0Sstevel@tonic-gate mutex_enter(&so->so_lock); 404*0Sstevel@tonic-gate so->so_tsdu_size = tso->so_tsdu_size; 405*0Sstevel@tonic-gate so->so_etsdu_size = tso->so_etsdu_size; 406*0Sstevel@tonic-gate so->so_addr_size = tso->so_addr_size; 407*0Sstevel@tonic-gate so->so_opt_size = tso->so_opt_size; 408*0Sstevel@tonic-gate so->so_tidu_size = tso->so_tidu_size; 409*0Sstevel@tonic-gate so->so_serv_type = tso->so_serv_type; 410*0Sstevel@tonic-gate so->so_mode = tso->so_mode & ~SM_ACCEPTOR_ID; 411*0Sstevel@tonic-gate mutex_exit(&so->so_lock); 412*0Sstevel@tonic-gate 413*0Sstevel@tonic-gate /* the following do_tcapability may update so->so_mode */ 414*0Sstevel@tonic-gate if ((tso->so_serv_type != T_CLTS) && 415*0Sstevel@tonic-gate ((so->so_state & SS_TCP_FAST_ACCEPT) == 0)) { 416*0Sstevel@tonic-gate error = do_tcapability(so, TC1_ACCEPTOR_ID); 417*0Sstevel@tonic-gate if (error) 418*0Sstevel@tonic-gate return (error); 419*0Sstevel@tonic-gate } 420*0Sstevel@tonic-gate } 421*0Sstevel@tonic-gate /* 422*0Sstevel@tonic-gate * If the addr_size is 0 we treat it as already bound 423*0Sstevel@tonic-gate * and connected. This is used by the routing socket. 424*0Sstevel@tonic-gate * We set the addr_size to something to allocate a the address 425*0Sstevel@tonic-gate * structures. 426*0Sstevel@tonic-gate */ 427*0Sstevel@tonic-gate if (so->so_addr_size == 0) { 428*0Sstevel@tonic-gate so->so_state |= SS_ISBOUND | SS_ISCONNECTED; 429*0Sstevel@tonic-gate /* Address size can vary with address families. */ 430*0Sstevel@tonic-gate if (so->so_family == AF_INET6) 431*0Sstevel@tonic-gate so->so_addr_size = 432*0Sstevel@tonic-gate (t_scalar_t)sizeof (struct sockaddr_in6); 433*0Sstevel@tonic-gate else 434*0Sstevel@tonic-gate so->so_addr_size = 435*0Sstevel@tonic-gate (t_scalar_t)sizeof (struct sockaddr_in); 436*0Sstevel@tonic-gate ASSERT(so->so_unbind_mp); 437*0Sstevel@tonic-gate } 438*0Sstevel@tonic-gate /* 439*0Sstevel@tonic-gate * Allocate the addresses. 440*0Sstevel@tonic-gate */ 441*0Sstevel@tonic-gate ASSERT(so->so_laddr_sa == NULL && so->so_faddr_sa == NULL); 442*0Sstevel@tonic-gate ASSERT(so->so_laddr_len == 0 && so->so_faddr_len == 0); 443*0Sstevel@tonic-gate so->so_laddr_maxlen = so->so_faddr_maxlen = 444*0Sstevel@tonic-gate P2ROUNDUP(so->so_addr_size, KMEM_ALIGN); 445*0Sstevel@tonic-gate so->so_laddr_sa = kmem_alloc(so->so_laddr_maxlen * 2, KM_SLEEP); 446*0Sstevel@tonic-gate so->so_faddr_sa = (struct sockaddr *)((caddr_t)so->so_laddr_sa 447*0Sstevel@tonic-gate + so->so_laddr_maxlen); 448*0Sstevel@tonic-gate 449*0Sstevel@tonic-gate if (so->so_family == AF_UNIX) { 450*0Sstevel@tonic-gate /* 451*0Sstevel@tonic-gate * Initialize AF_UNIX related fields. 452*0Sstevel@tonic-gate */ 453*0Sstevel@tonic-gate bzero(&so->so_ux_laddr, sizeof (so->so_ux_laddr)); 454*0Sstevel@tonic-gate bzero(&so->so_ux_faddr, sizeof (so->so_ux_faddr)); 455*0Sstevel@tonic-gate } 456*0Sstevel@tonic-gate 457*0Sstevel@tonic-gate stp = vp->v_stream; 458*0Sstevel@tonic-gate /* 459*0Sstevel@tonic-gate * Have to keep minpsz at zero in order to allow write/send of zero 460*0Sstevel@tonic-gate * bytes. 461*0Sstevel@tonic-gate */ 462*0Sstevel@tonic-gate mutex_enter(&stp->sd_lock); 463*0Sstevel@tonic-gate if (stp->sd_qn_minpsz == 1) 464*0Sstevel@tonic-gate stp->sd_qn_minpsz = 0; 465*0Sstevel@tonic-gate mutex_exit(&stp->sd_lock); 466*0Sstevel@tonic-gate 467*0Sstevel@tonic-gate return (0); 468*0Sstevel@tonic-gate } 469*0Sstevel@tonic-gate 470*0Sstevel@tonic-gate static void 471*0Sstevel@tonic-gate copy_tinfo(struct sonode *so, struct T_info_ack *tia) 472*0Sstevel@tonic-gate { 473*0Sstevel@tonic-gate so->so_tsdu_size = tia->TSDU_size; 474*0Sstevel@tonic-gate so->so_etsdu_size = tia->ETSDU_size; 475*0Sstevel@tonic-gate so->so_addr_size = tia->ADDR_size; 476*0Sstevel@tonic-gate so->so_opt_size = tia->OPT_size; 477*0Sstevel@tonic-gate so->so_tidu_size = tia->TIDU_size; 478*0Sstevel@tonic-gate so->so_serv_type = tia->SERV_type; 479*0Sstevel@tonic-gate switch (tia->CURRENT_state) { 480*0Sstevel@tonic-gate case TS_UNBND: 481*0Sstevel@tonic-gate break; 482*0Sstevel@tonic-gate case TS_IDLE: 483*0Sstevel@tonic-gate so->so_state |= SS_ISBOUND; 484*0Sstevel@tonic-gate so->so_laddr_len = 0; 485*0Sstevel@tonic-gate so->so_state &= ~SS_LADDR_VALID; 486*0Sstevel@tonic-gate break; 487*0Sstevel@tonic-gate case TS_DATA_XFER: 488*0Sstevel@tonic-gate so->so_state |= SS_ISBOUND|SS_ISCONNECTED; 489*0Sstevel@tonic-gate so->so_laddr_len = 0; 490*0Sstevel@tonic-gate so->so_faddr_len = 0; 491*0Sstevel@tonic-gate so->so_state &= ~(SS_LADDR_VALID | SS_FADDR_VALID); 492*0Sstevel@tonic-gate break; 493*0Sstevel@tonic-gate } 494*0Sstevel@tonic-gate 495*0Sstevel@tonic-gate /* 496*0Sstevel@tonic-gate * Heuristics for determining the socket mode flags 497*0Sstevel@tonic-gate * (SM_ATOMIC, SM_CONNREQUIRED, SM_ADDR, SM_FDPASSING, 498*0Sstevel@tonic-gate * and SM_EXDATA, SM_OPTDATA, and SM_BYTESTREAM) 499*0Sstevel@tonic-gate * from the info ack. 500*0Sstevel@tonic-gate */ 501*0Sstevel@tonic-gate if (so->so_serv_type == T_CLTS) { 502*0Sstevel@tonic-gate so->so_mode |= SM_ATOMIC | SM_ADDR; 503*0Sstevel@tonic-gate } else { 504*0Sstevel@tonic-gate so->so_mode |= SM_CONNREQUIRED; 505*0Sstevel@tonic-gate if (so->so_etsdu_size != 0 && so->so_etsdu_size != -2) 506*0Sstevel@tonic-gate so->so_mode |= SM_EXDATA; 507*0Sstevel@tonic-gate } 508*0Sstevel@tonic-gate if (so->so_type == SOCK_SEQPACKET || so->so_type == SOCK_RAW) { 509*0Sstevel@tonic-gate /* Semantics are to discard tail end of messages */ 510*0Sstevel@tonic-gate so->so_mode |= SM_ATOMIC; 511*0Sstevel@tonic-gate } 512*0Sstevel@tonic-gate if (so->so_family == AF_UNIX) { 513*0Sstevel@tonic-gate so->so_mode |= SM_FDPASSING | SM_OPTDATA; 514*0Sstevel@tonic-gate if (so->so_addr_size == -1) { 515*0Sstevel@tonic-gate /* MAXPATHLEN + soun_family + nul termination */ 516*0Sstevel@tonic-gate so->so_addr_size = (t_scalar_t)(MAXPATHLEN + 517*0Sstevel@tonic-gate sizeof (short) + 1); 518*0Sstevel@tonic-gate } 519*0Sstevel@tonic-gate if (so->so_type == SOCK_STREAM) { 520*0Sstevel@tonic-gate /* 521*0Sstevel@tonic-gate * Make it into a byte-stream transport. 522*0Sstevel@tonic-gate * SOCK_SEQPACKET sockets are unchanged. 523*0Sstevel@tonic-gate */ 524*0Sstevel@tonic-gate so->so_tsdu_size = 0; 525*0Sstevel@tonic-gate } 526*0Sstevel@tonic-gate } else if (so->so_addr_size == -1) { 527*0Sstevel@tonic-gate /* 528*0Sstevel@tonic-gate * Logic extracted from sockmod - have to pick some max address 529*0Sstevel@tonic-gate * length in order to preallocate the addresses. 530*0Sstevel@tonic-gate */ 531*0Sstevel@tonic-gate so->so_addr_size = SOA_DEFSIZE; 532*0Sstevel@tonic-gate } 533*0Sstevel@tonic-gate if (so->so_tsdu_size == 0) 534*0Sstevel@tonic-gate so->so_mode |= SM_BYTESTREAM; 535*0Sstevel@tonic-gate } 536*0Sstevel@tonic-gate 537*0Sstevel@tonic-gate static int 538*0Sstevel@tonic-gate check_tinfo(struct sonode *so) 539*0Sstevel@tonic-gate { 540*0Sstevel@tonic-gate /* Consistency checks */ 541*0Sstevel@tonic-gate if (so->so_type == SOCK_DGRAM && so->so_serv_type != T_CLTS) { 542*0Sstevel@tonic-gate eprintso(so, ("service type and socket type mismatch\n")); 543*0Sstevel@tonic-gate eprintsoline(so, EPROTO); 544*0Sstevel@tonic-gate return (EPROTO); 545*0Sstevel@tonic-gate } 546*0Sstevel@tonic-gate if (so->so_type == SOCK_STREAM && so->so_serv_type == T_CLTS) { 547*0Sstevel@tonic-gate eprintso(so, ("service type and socket type mismatch\n")); 548*0Sstevel@tonic-gate eprintsoline(so, EPROTO); 549*0Sstevel@tonic-gate return (EPROTO); 550*0Sstevel@tonic-gate } 551*0Sstevel@tonic-gate if (so->so_type == SOCK_SEQPACKET && so->so_serv_type == T_CLTS) { 552*0Sstevel@tonic-gate eprintso(so, ("service type and socket type mismatch\n")); 553*0Sstevel@tonic-gate eprintsoline(so, EPROTO); 554*0Sstevel@tonic-gate return (EPROTO); 555*0Sstevel@tonic-gate } 556*0Sstevel@tonic-gate if (so->so_family == AF_INET && 557*0Sstevel@tonic-gate so->so_addr_size != (t_scalar_t)sizeof (struct sockaddr_in)) { 558*0Sstevel@tonic-gate eprintso(so, 559*0Sstevel@tonic-gate ("AF_INET must have sockaddr_in address length. Got %d\n", 560*0Sstevel@tonic-gate so->so_addr_size)); 561*0Sstevel@tonic-gate eprintsoline(so, EMSGSIZE); 562*0Sstevel@tonic-gate return (EMSGSIZE); 563*0Sstevel@tonic-gate } 564*0Sstevel@tonic-gate if (so->so_family == AF_INET6 && 565*0Sstevel@tonic-gate so->so_addr_size != (t_scalar_t)sizeof (struct sockaddr_in6)) { 566*0Sstevel@tonic-gate eprintso(so, 567*0Sstevel@tonic-gate ("AF_INET6 must have sockaddr_in6 address length. Got %d\n", 568*0Sstevel@tonic-gate so->so_addr_size)); 569*0Sstevel@tonic-gate eprintsoline(so, EMSGSIZE); 570*0Sstevel@tonic-gate return (EMSGSIZE); 571*0Sstevel@tonic-gate } 572*0Sstevel@tonic-gate 573*0Sstevel@tonic-gate dprintso(so, 1, ( 574*0Sstevel@tonic-gate "tinfo: serv %d tsdu %d, etsdu %d, addr %d, opt %d, tidu %d\n", 575*0Sstevel@tonic-gate so->so_serv_type, so->so_tsdu_size, so->so_etsdu_size, 576*0Sstevel@tonic-gate so->so_addr_size, so->so_opt_size, 577*0Sstevel@tonic-gate so->so_tidu_size)); 578*0Sstevel@tonic-gate dprintso(so, 1, ("tinfo: so_state %s\n", 579*0Sstevel@tonic-gate pr_state(so->so_state, so->so_mode))); 580*0Sstevel@tonic-gate return (0); 581*0Sstevel@tonic-gate } 582*0Sstevel@tonic-gate 583*0Sstevel@tonic-gate /* 584*0Sstevel@tonic-gate * Send down T_info_req and wait for the ack. 585*0Sstevel@tonic-gate * Record interesting T_info_ack values in the sonode. 586*0Sstevel@tonic-gate */ 587*0Sstevel@tonic-gate static int 588*0Sstevel@tonic-gate do_tinfo(struct sonode *so) 589*0Sstevel@tonic-gate { 590*0Sstevel@tonic-gate struct T_info_req tir; 591*0Sstevel@tonic-gate mblk_t *mp; 592*0Sstevel@tonic-gate int error; 593*0Sstevel@tonic-gate 594*0Sstevel@tonic-gate ASSERT(MUTEX_NOT_HELD(&so->so_lock)); 595*0Sstevel@tonic-gate 596*0Sstevel@tonic-gate if (so_no_tinfo) { 597*0Sstevel@tonic-gate so->so_addr_size = 0; 598*0Sstevel@tonic-gate return (0); 599*0Sstevel@tonic-gate } 600*0Sstevel@tonic-gate 601*0Sstevel@tonic-gate dprintso(so, 1, ("do_tinfo(%p)\n", so)); 602*0Sstevel@tonic-gate 603*0Sstevel@tonic-gate /* Send T_INFO_REQ */ 604*0Sstevel@tonic-gate tir.PRIM_type = T_INFO_REQ; 605*0Sstevel@tonic-gate mp = soallocproto1(&tir, sizeof (tir), 606*0Sstevel@tonic-gate sizeof (struct T_info_req) + sizeof (struct T_info_ack), 607*0Sstevel@tonic-gate _ALLOC_INTR); 608*0Sstevel@tonic-gate if (mp == NULL) { 609*0Sstevel@tonic-gate eprintsoline(so, ENOBUFS); 610*0Sstevel@tonic-gate return (ENOBUFS); 611*0Sstevel@tonic-gate } 612*0Sstevel@tonic-gate /* T_INFO_REQ has to be M_PCPROTO */ 613*0Sstevel@tonic-gate DB_TYPE(mp) = M_PCPROTO; 614*0Sstevel@tonic-gate 615*0Sstevel@tonic-gate error = kstrputmsg(SOTOV(so), mp, NULL, 0, 0, 616*0Sstevel@tonic-gate MSG_BAND|MSG_HOLDSIG|MSG_IGNERROR, 0); 617*0Sstevel@tonic-gate if (error) { 618*0Sstevel@tonic-gate eprintsoline(so, error); 619*0Sstevel@tonic-gate return (error); 620*0Sstevel@tonic-gate } 621*0Sstevel@tonic-gate mutex_enter(&so->so_lock); 622*0Sstevel@tonic-gate /* Wait for T_INFO_ACK */ 623*0Sstevel@tonic-gate if ((error = sowaitprim(so, T_INFO_REQ, T_INFO_ACK, 624*0Sstevel@tonic-gate (t_uscalar_t)sizeof (struct T_info_ack), &mp, 0))) { 625*0Sstevel@tonic-gate mutex_exit(&so->so_lock); 626*0Sstevel@tonic-gate eprintsoline(so, error); 627*0Sstevel@tonic-gate return (error); 628*0Sstevel@tonic-gate } 629*0Sstevel@tonic-gate 630*0Sstevel@tonic-gate ASSERT(mp); 631*0Sstevel@tonic-gate copy_tinfo(so, (struct T_info_ack *)mp->b_rptr); 632*0Sstevel@tonic-gate mutex_exit(&so->so_lock); 633*0Sstevel@tonic-gate freemsg(mp); 634*0Sstevel@tonic-gate return (check_tinfo(so)); 635*0Sstevel@tonic-gate } 636*0Sstevel@tonic-gate 637*0Sstevel@tonic-gate /* 638*0Sstevel@tonic-gate * Send down T_capability_req and wait for the ack. 639*0Sstevel@tonic-gate * Record interesting T_capability_ack values in the sonode. 640*0Sstevel@tonic-gate */ 641*0Sstevel@tonic-gate static int 642*0Sstevel@tonic-gate do_tcapability(struct sonode *so, t_uscalar_t cap_bits1) 643*0Sstevel@tonic-gate { 644*0Sstevel@tonic-gate struct T_capability_req tcr; 645*0Sstevel@tonic-gate struct T_capability_ack *tca; 646*0Sstevel@tonic-gate mblk_t *mp; 647*0Sstevel@tonic-gate int error; 648*0Sstevel@tonic-gate 649*0Sstevel@tonic-gate ASSERT(cap_bits1 != 0); 650*0Sstevel@tonic-gate ASSERT((cap_bits1 & ~(TC1_ACCEPTOR_ID | TC1_INFO)) == 0); 651*0Sstevel@tonic-gate ASSERT(MUTEX_NOT_HELD(&so->so_lock)); 652*0Sstevel@tonic-gate 653*0Sstevel@tonic-gate if (so->so_provinfo->tpi_capability == PI_NO) 654*0Sstevel@tonic-gate return (do_tinfo(so)); 655*0Sstevel@tonic-gate 656*0Sstevel@tonic-gate if (so_no_tinfo) { 657*0Sstevel@tonic-gate so->so_addr_size = 0; 658*0Sstevel@tonic-gate if ((cap_bits1 &= ~TC1_INFO) == 0) 659*0Sstevel@tonic-gate return (0); 660*0Sstevel@tonic-gate } 661*0Sstevel@tonic-gate 662*0Sstevel@tonic-gate dprintso(so, 1, ("do_tcapability(%p)\n", so)); 663*0Sstevel@tonic-gate 664*0Sstevel@tonic-gate /* Send T_CAPABILITY_REQ */ 665*0Sstevel@tonic-gate tcr.PRIM_type = T_CAPABILITY_REQ; 666*0Sstevel@tonic-gate tcr.CAP_bits1 = cap_bits1; 667*0Sstevel@tonic-gate mp = soallocproto1(&tcr, sizeof (tcr), 668*0Sstevel@tonic-gate sizeof (struct T_capability_req) + sizeof (struct T_capability_ack), 669*0Sstevel@tonic-gate _ALLOC_INTR); 670*0Sstevel@tonic-gate if (mp == NULL) { 671*0Sstevel@tonic-gate eprintsoline(so, ENOBUFS); 672*0Sstevel@tonic-gate return (ENOBUFS); 673*0Sstevel@tonic-gate } 674*0Sstevel@tonic-gate /* T_CAPABILITY_REQ should be M_PCPROTO here */ 675*0Sstevel@tonic-gate DB_TYPE(mp) = M_PCPROTO; 676*0Sstevel@tonic-gate 677*0Sstevel@tonic-gate error = kstrputmsg(SOTOV(so), mp, NULL, 0, 0, 678*0Sstevel@tonic-gate MSG_BAND|MSG_HOLDSIG|MSG_IGNERROR, 0); 679*0Sstevel@tonic-gate if (error) { 680*0Sstevel@tonic-gate eprintsoline(so, error); 681*0Sstevel@tonic-gate return (error); 682*0Sstevel@tonic-gate } 683*0Sstevel@tonic-gate mutex_enter(&so->so_lock); 684*0Sstevel@tonic-gate /* Wait for T_CAPABILITY_ACK */ 685*0Sstevel@tonic-gate if ((error = sowaitprim(so, T_CAPABILITY_REQ, T_CAPABILITY_ACK, 686*0Sstevel@tonic-gate (t_uscalar_t)sizeof (*tca), &mp, sock_capability_timeout * hz))) { 687*0Sstevel@tonic-gate mutex_exit(&so->so_lock); 688*0Sstevel@tonic-gate PI_PROVLOCK(so->so_provinfo); 689*0Sstevel@tonic-gate if (so->so_provinfo->tpi_capability == PI_DONTKNOW) 690*0Sstevel@tonic-gate so->so_provinfo->tpi_capability = PI_NO; 691*0Sstevel@tonic-gate PI_PROVUNLOCK(so->so_provinfo); 692*0Sstevel@tonic-gate ASSERT((so->so_mode & SM_ACCEPTOR_ID) == 0); 693*0Sstevel@tonic-gate if (cap_bits1 & TC1_INFO) { 694*0Sstevel@tonic-gate /* 695*0Sstevel@tonic-gate * If the T_CAPABILITY_REQ timed out and then a 696*0Sstevel@tonic-gate * T_INFO_REQ gets a protocol error, most likely 697*0Sstevel@tonic-gate * the capability was slow (vs. unsupported). Return 698*0Sstevel@tonic-gate * ENOSR for this case as a best guess. 699*0Sstevel@tonic-gate */ 700*0Sstevel@tonic-gate if (error == ETIME) { 701*0Sstevel@tonic-gate return ((error = do_tinfo(so)) == EPROTO ? 702*0Sstevel@tonic-gate ENOSR : error); 703*0Sstevel@tonic-gate } 704*0Sstevel@tonic-gate return (do_tinfo(so)); 705*0Sstevel@tonic-gate } 706*0Sstevel@tonic-gate return (0); 707*0Sstevel@tonic-gate } 708*0Sstevel@tonic-gate 709*0Sstevel@tonic-gate if (so->so_provinfo->tpi_capability == PI_DONTKNOW) { 710*0Sstevel@tonic-gate PI_PROVLOCK(so->so_provinfo); 711*0Sstevel@tonic-gate so->so_provinfo->tpi_capability = PI_YES; 712*0Sstevel@tonic-gate PI_PROVUNLOCK(so->so_provinfo); 713*0Sstevel@tonic-gate } 714*0Sstevel@tonic-gate 715*0Sstevel@tonic-gate ASSERT(mp); 716*0Sstevel@tonic-gate tca = (struct T_capability_ack *)mp->b_rptr; 717*0Sstevel@tonic-gate 718*0Sstevel@tonic-gate ASSERT((cap_bits1 & TC1_INFO) == (tca->CAP_bits1 & TC1_INFO)); 719*0Sstevel@tonic-gate 720*0Sstevel@tonic-gate cap_bits1 = tca->CAP_bits1; 721*0Sstevel@tonic-gate 722*0Sstevel@tonic-gate if (cap_bits1 & TC1_ACCEPTOR_ID) { 723*0Sstevel@tonic-gate so->so_acceptor_id = tca->ACCEPTOR_id; 724*0Sstevel@tonic-gate so->so_mode |= SM_ACCEPTOR_ID; 725*0Sstevel@tonic-gate } 726*0Sstevel@tonic-gate 727*0Sstevel@tonic-gate if (cap_bits1 & TC1_INFO) 728*0Sstevel@tonic-gate copy_tinfo(so, &tca->INFO_ack); 729*0Sstevel@tonic-gate 730*0Sstevel@tonic-gate mutex_exit(&so->so_lock); 731*0Sstevel@tonic-gate freemsg(mp); 732*0Sstevel@tonic-gate 733*0Sstevel@tonic-gate if (cap_bits1 & TC1_INFO) 734*0Sstevel@tonic-gate return (check_tinfo(so)); 735*0Sstevel@tonic-gate 736*0Sstevel@tonic-gate return (0); 737*0Sstevel@tonic-gate } 738*0Sstevel@tonic-gate 739*0Sstevel@tonic-gate /* 740*0Sstevel@tonic-gate * Retrieve and clear the socket error. 741*0Sstevel@tonic-gate */ 742*0Sstevel@tonic-gate int 743*0Sstevel@tonic-gate sogeterr(struct sonode *so) 744*0Sstevel@tonic-gate { 745*0Sstevel@tonic-gate int error; 746*0Sstevel@tonic-gate 747*0Sstevel@tonic-gate ASSERT(MUTEX_HELD(&so->so_lock)); 748*0Sstevel@tonic-gate 749*0Sstevel@tonic-gate error = so->so_error; 750*0Sstevel@tonic-gate so->so_error = 0; 751*0Sstevel@tonic-gate 752*0Sstevel@tonic-gate return (error); 753*0Sstevel@tonic-gate } 754*0Sstevel@tonic-gate 755*0Sstevel@tonic-gate /* 756*0Sstevel@tonic-gate * This routine is registered with the stream head to retrieve read 757*0Sstevel@tonic-gate * side errors. 758*0Sstevel@tonic-gate * It does not clear the socket error for a peeking read side operation. 759*0Sstevel@tonic-gate * It the error is to be cleared it sets *clearerr. 760*0Sstevel@tonic-gate */ 761*0Sstevel@tonic-gate int 762*0Sstevel@tonic-gate sogetrderr(vnode_t *vp, int ispeek, int *clearerr) 763*0Sstevel@tonic-gate { 764*0Sstevel@tonic-gate struct sonode *so = VTOSO(vp); 765*0Sstevel@tonic-gate int error; 766*0Sstevel@tonic-gate 767*0Sstevel@tonic-gate mutex_enter(&so->so_lock); 768*0Sstevel@tonic-gate if (ispeek) { 769*0Sstevel@tonic-gate error = so->so_error; 770*0Sstevel@tonic-gate *clearerr = 0; 771*0Sstevel@tonic-gate } else { 772*0Sstevel@tonic-gate error = so->so_error; 773*0Sstevel@tonic-gate so->so_error = 0; 774*0Sstevel@tonic-gate *clearerr = 1; 775*0Sstevel@tonic-gate } 776*0Sstevel@tonic-gate mutex_exit(&so->so_lock); 777*0Sstevel@tonic-gate return (error); 778*0Sstevel@tonic-gate } 779*0Sstevel@tonic-gate 780*0Sstevel@tonic-gate /* 781*0Sstevel@tonic-gate * This routine is registered with the stream head to retrieve write 782*0Sstevel@tonic-gate * side errors. 783*0Sstevel@tonic-gate * It does not clear the socket error for a peeking read side operation. 784*0Sstevel@tonic-gate * It the error is to be cleared it sets *clearerr. 785*0Sstevel@tonic-gate */ 786*0Sstevel@tonic-gate int 787*0Sstevel@tonic-gate sogetwrerr(vnode_t *vp, int ispeek, int *clearerr) 788*0Sstevel@tonic-gate { 789*0Sstevel@tonic-gate struct sonode *so = VTOSO(vp); 790*0Sstevel@tonic-gate int error; 791*0Sstevel@tonic-gate 792*0Sstevel@tonic-gate mutex_enter(&so->so_lock); 793*0Sstevel@tonic-gate if (so->so_state & SS_CANTSENDMORE) { 794*0Sstevel@tonic-gate error = EPIPE; 795*0Sstevel@tonic-gate *clearerr = 0; 796*0Sstevel@tonic-gate } else { 797*0Sstevel@tonic-gate error = so->so_error; 798*0Sstevel@tonic-gate if (ispeek) { 799*0Sstevel@tonic-gate *clearerr = 0; 800*0Sstevel@tonic-gate } else { 801*0Sstevel@tonic-gate so->so_error = 0; 802*0Sstevel@tonic-gate *clearerr = 1; 803*0Sstevel@tonic-gate } 804*0Sstevel@tonic-gate } 805*0Sstevel@tonic-gate mutex_exit(&so->so_lock); 806*0Sstevel@tonic-gate return (error); 807*0Sstevel@tonic-gate } 808*0Sstevel@tonic-gate 809*0Sstevel@tonic-gate /* 810*0Sstevel@tonic-gate * Set a nonpersistent read and write error on the socket. 811*0Sstevel@tonic-gate * Used when there is a T_uderror_ind for a connected socket. 812*0Sstevel@tonic-gate * The caller also needs to call strsetrerror and strsetwerror 813*0Sstevel@tonic-gate * after dropping the lock. 814*0Sstevel@tonic-gate */ 815*0Sstevel@tonic-gate void 816*0Sstevel@tonic-gate soseterror(struct sonode *so, int error) 817*0Sstevel@tonic-gate { 818*0Sstevel@tonic-gate ASSERT(error != 0); 819*0Sstevel@tonic-gate 820*0Sstevel@tonic-gate ASSERT(MUTEX_HELD(&so->so_lock)); 821*0Sstevel@tonic-gate so->so_error = (ushort_t)error; 822*0Sstevel@tonic-gate } 823*0Sstevel@tonic-gate 824*0Sstevel@tonic-gate void 825*0Sstevel@tonic-gate soisconnecting(struct sonode *so) 826*0Sstevel@tonic-gate { 827*0Sstevel@tonic-gate ASSERT(MUTEX_HELD(&so->so_lock)); 828*0Sstevel@tonic-gate so->so_state &= ~(SS_ISCONNECTED|SS_ISDISCONNECTING); 829*0Sstevel@tonic-gate so->so_state |= SS_ISCONNECTING; 830*0Sstevel@tonic-gate cv_broadcast(&so->so_state_cv); 831*0Sstevel@tonic-gate } 832*0Sstevel@tonic-gate 833*0Sstevel@tonic-gate void 834*0Sstevel@tonic-gate soisconnected(struct sonode *so) 835*0Sstevel@tonic-gate { 836*0Sstevel@tonic-gate ASSERT(MUTEX_HELD(&so->so_lock)); 837*0Sstevel@tonic-gate so->so_state &= ~(SS_ISCONNECTING|SS_ISDISCONNECTING); 838*0Sstevel@tonic-gate so->so_state |= SS_ISCONNECTED; 839*0Sstevel@tonic-gate cv_broadcast(&so->so_state_cv); 840*0Sstevel@tonic-gate } 841*0Sstevel@tonic-gate 842*0Sstevel@tonic-gate /* 843*0Sstevel@tonic-gate * The caller also needs to call strsetrerror, strsetwerror and strseteof. 844*0Sstevel@tonic-gate */ 845*0Sstevel@tonic-gate void 846*0Sstevel@tonic-gate soisdisconnected(struct sonode *so, int error) 847*0Sstevel@tonic-gate { 848*0Sstevel@tonic-gate ASSERT(MUTEX_HELD(&so->so_lock)); 849*0Sstevel@tonic-gate so->so_state &= ~(SS_ISCONNECTING|SS_ISCONNECTED|SS_ISDISCONNECTING| 850*0Sstevel@tonic-gate SS_LADDR_VALID|SS_FADDR_VALID); 851*0Sstevel@tonic-gate so->so_state |= (SS_CANTRCVMORE|SS_CANTSENDMORE); 852*0Sstevel@tonic-gate so->so_error = (ushort_t)error; 853*0Sstevel@tonic-gate if (so->so_peercred != NULL) { 854*0Sstevel@tonic-gate crfree(so->so_peercred); 855*0Sstevel@tonic-gate so->so_peercred = NULL; 856*0Sstevel@tonic-gate } 857*0Sstevel@tonic-gate cv_broadcast(&so->so_state_cv); 858*0Sstevel@tonic-gate } 859*0Sstevel@tonic-gate 860*0Sstevel@tonic-gate /* 861*0Sstevel@tonic-gate * For connected AF_UNIX SOCK_DGRAM sockets when the peer closes. 862*0Sstevel@tonic-gate * Does not affect write side. 863*0Sstevel@tonic-gate * The caller also has to call strsetrerror. 864*0Sstevel@tonic-gate */ 865*0Sstevel@tonic-gate static void 866*0Sstevel@tonic-gate sobreakconn(struct sonode *so, int error) 867*0Sstevel@tonic-gate { 868*0Sstevel@tonic-gate ASSERT(MUTEX_HELD(&so->so_lock)); 869*0Sstevel@tonic-gate so->so_state &= ~(SS_ISCONNECTING|SS_ISCONNECTED|SS_ISDISCONNECTING); 870*0Sstevel@tonic-gate so->so_error = (ushort_t)error; 871*0Sstevel@tonic-gate cv_broadcast(&so->so_state_cv); 872*0Sstevel@tonic-gate } 873*0Sstevel@tonic-gate 874*0Sstevel@tonic-gate /* 875*0Sstevel@tonic-gate * Can no longer send. 876*0Sstevel@tonic-gate * Caller must also call strsetwerror. 877*0Sstevel@tonic-gate * 878*0Sstevel@tonic-gate * We mark the peer address as no longer valid for getpeername, but 879*0Sstevel@tonic-gate * leave it around for so_unix_close to notify the peer (that 880*0Sstevel@tonic-gate * transport has no addressing held at that layer). 881*0Sstevel@tonic-gate */ 882*0Sstevel@tonic-gate void 883*0Sstevel@tonic-gate socantsendmore(struct sonode *so) 884*0Sstevel@tonic-gate { 885*0Sstevel@tonic-gate ASSERT(MUTEX_HELD(&so->so_lock)); 886*0Sstevel@tonic-gate so->so_state = so->so_state & ~SS_FADDR_VALID | SS_CANTSENDMORE; 887*0Sstevel@tonic-gate cv_broadcast(&so->so_state_cv); 888*0Sstevel@tonic-gate } 889*0Sstevel@tonic-gate 890*0Sstevel@tonic-gate /* 891*0Sstevel@tonic-gate * The caller must call strseteof(,1) as well as this routine 892*0Sstevel@tonic-gate * to change the socket state. 893*0Sstevel@tonic-gate */ 894*0Sstevel@tonic-gate void 895*0Sstevel@tonic-gate socantrcvmore(struct sonode *so) 896*0Sstevel@tonic-gate { 897*0Sstevel@tonic-gate ASSERT(MUTEX_HELD(&so->so_lock)); 898*0Sstevel@tonic-gate so->so_state |= SS_CANTRCVMORE; 899*0Sstevel@tonic-gate cv_broadcast(&so->so_state_cv); 900*0Sstevel@tonic-gate } 901*0Sstevel@tonic-gate 902*0Sstevel@tonic-gate /* 903*0Sstevel@tonic-gate * The caller has sent down a "request_prim" primitive and wants to wait for 904*0Sstevel@tonic-gate * an ack ("ack_prim") or an T_ERROR_ACK for it. 905*0Sstevel@tonic-gate * The specified "ack_prim" can be a T_OK_ACK. 906*0Sstevel@tonic-gate * 907*0Sstevel@tonic-gate * Assumes that all the TPI acks are M_PCPROTO messages. 908*0Sstevel@tonic-gate * 909*0Sstevel@tonic-gate * Note that the socket is single-threaded (using so_lock_single) 910*0Sstevel@tonic-gate * for all operations that generate TPI ack messages. Since 911*0Sstevel@tonic-gate * only TPI ack messages are M_PCPROTO we should never receive 912*0Sstevel@tonic-gate * anything except either the ack we are expecting or a T_ERROR_ACK 913*0Sstevel@tonic-gate * for the same primitive. 914*0Sstevel@tonic-gate */ 915*0Sstevel@tonic-gate int 916*0Sstevel@tonic-gate sowaitprim(struct sonode *so, t_scalar_t request_prim, t_scalar_t ack_prim, 917*0Sstevel@tonic-gate t_uscalar_t min_size, mblk_t **mpp, clock_t wait) 918*0Sstevel@tonic-gate { 919*0Sstevel@tonic-gate mblk_t *mp; 920*0Sstevel@tonic-gate union T_primitives *tpr; 921*0Sstevel@tonic-gate int error; 922*0Sstevel@tonic-gate 923*0Sstevel@tonic-gate dprintso(so, 1, ("sowaitprim(%p, %d, %d, %d, %p, %lu)\n", 924*0Sstevel@tonic-gate so, request_prim, ack_prim, min_size, mpp, wait)); 925*0Sstevel@tonic-gate 926*0Sstevel@tonic-gate ASSERT(MUTEX_HELD(&so->so_lock)); 927*0Sstevel@tonic-gate 928*0Sstevel@tonic-gate error = sowaitack(so, &mp, wait); 929*0Sstevel@tonic-gate if (error) 930*0Sstevel@tonic-gate return (error); 931*0Sstevel@tonic-gate 932*0Sstevel@tonic-gate dprintso(so, 1, ("got msg %p\n", mp)); 933*0Sstevel@tonic-gate if (DB_TYPE(mp) != M_PCPROTO || 934*0Sstevel@tonic-gate MBLKL(mp) < sizeof (tpr->type)) { 935*0Sstevel@tonic-gate freemsg(mp); 936*0Sstevel@tonic-gate eprintsoline(so, EPROTO); 937*0Sstevel@tonic-gate return (EPROTO); 938*0Sstevel@tonic-gate } 939*0Sstevel@tonic-gate tpr = (union T_primitives *)mp->b_rptr; 940*0Sstevel@tonic-gate /* 941*0Sstevel@tonic-gate * Did we get the primitive that we were asking for? 942*0Sstevel@tonic-gate * For T_OK_ACK we also check that it matches the request primitive. 943*0Sstevel@tonic-gate */ 944*0Sstevel@tonic-gate if (tpr->type == ack_prim && 945*0Sstevel@tonic-gate (ack_prim != T_OK_ACK || 946*0Sstevel@tonic-gate tpr->ok_ack.CORRECT_prim == request_prim)) { 947*0Sstevel@tonic-gate if (MBLKL(mp) >= (ssize_t)min_size) { 948*0Sstevel@tonic-gate /* Found what we are looking for */ 949*0Sstevel@tonic-gate *mpp = mp; 950*0Sstevel@tonic-gate return (0); 951*0Sstevel@tonic-gate } 952*0Sstevel@tonic-gate /* Too short */ 953*0Sstevel@tonic-gate freemsg(mp); 954*0Sstevel@tonic-gate eprintsoline(so, EPROTO); 955*0Sstevel@tonic-gate return (EPROTO); 956*0Sstevel@tonic-gate } 957*0Sstevel@tonic-gate 958*0Sstevel@tonic-gate if (tpr->type == T_ERROR_ACK && 959*0Sstevel@tonic-gate tpr->error_ack.ERROR_prim == request_prim) { 960*0Sstevel@tonic-gate /* Error to the primitive we were looking for */ 961*0Sstevel@tonic-gate if (tpr->error_ack.TLI_error == TSYSERR) { 962*0Sstevel@tonic-gate error = tpr->error_ack.UNIX_error; 963*0Sstevel@tonic-gate } else { 964*0Sstevel@tonic-gate error = tlitosyserr(tpr->error_ack.TLI_error); 965*0Sstevel@tonic-gate } 966*0Sstevel@tonic-gate dprintso(so, 0, ("error_ack for %d: %d/%d ->%d\n", 967*0Sstevel@tonic-gate tpr->error_ack.ERROR_prim, 968*0Sstevel@tonic-gate tpr->error_ack.TLI_error, 969*0Sstevel@tonic-gate tpr->error_ack.UNIX_error, 970*0Sstevel@tonic-gate error)); 971*0Sstevel@tonic-gate freemsg(mp); 972*0Sstevel@tonic-gate return (error); 973*0Sstevel@tonic-gate } 974*0Sstevel@tonic-gate /* 975*0Sstevel@tonic-gate * Wrong primitive or T_ERROR_ACK for the wrong primitive 976*0Sstevel@tonic-gate */ 977*0Sstevel@tonic-gate #ifdef DEBUG 978*0Sstevel@tonic-gate if (tpr->type == T_ERROR_ACK) { 979*0Sstevel@tonic-gate dprintso(so, 0, ("error_ack for %d: %d/%d\n", 980*0Sstevel@tonic-gate tpr->error_ack.ERROR_prim, 981*0Sstevel@tonic-gate tpr->error_ack.TLI_error, 982*0Sstevel@tonic-gate tpr->error_ack.UNIX_error)); 983*0Sstevel@tonic-gate } else if (tpr->type == T_OK_ACK) { 984*0Sstevel@tonic-gate dprintso(so, 0, ("ok_ack for %d, expected %d for %d\n", 985*0Sstevel@tonic-gate tpr->ok_ack.CORRECT_prim, 986*0Sstevel@tonic-gate ack_prim, request_prim)); 987*0Sstevel@tonic-gate } else { 988*0Sstevel@tonic-gate dprintso(so, 0, 989*0Sstevel@tonic-gate ("unexpected primitive %d, expected %d for %d\n", 990*0Sstevel@tonic-gate tpr->type, ack_prim, request_prim)); 991*0Sstevel@tonic-gate } 992*0Sstevel@tonic-gate #endif /* DEBUG */ 993*0Sstevel@tonic-gate 994*0Sstevel@tonic-gate freemsg(mp); 995*0Sstevel@tonic-gate eprintsoline(so, EPROTO); 996*0Sstevel@tonic-gate return (EPROTO); 997*0Sstevel@tonic-gate } 998*0Sstevel@tonic-gate 999*0Sstevel@tonic-gate /* 1000*0Sstevel@tonic-gate * Wait for a T_OK_ACK for the specified primitive. 1001*0Sstevel@tonic-gate */ 1002*0Sstevel@tonic-gate int 1003*0Sstevel@tonic-gate sowaitokack(struct sonode *so, t_scalar_t request_prim) 1004*0Sstevel@tonic-gate { 1005*0Sstevel@tonic-gate mblk_t *mp; 1006*0Sstevel@tonic-gate int error; 1007*0Sstevel@tonic-gate 1008*0Sstevel@tonic-gate error = sowaitprim(so, request_prim, T_OK_ACK, 1009*0Sstevel@tonic-gate (t_uscalar_t)sizeof (struct T_ok_ack), &mp, 0); 1010*0Sstevel@tonic-gate if (error) 1011*0Sstevel@tonic-gate return (error); 1012*0Sstevel@tonic-gate freemsg(mp); 1013*0Sstevel@tonic-gate return (0); 1014*0Sstevel@tonic-gate } 1015*0Sstevel@tonic-gate 1016*0Sstevel@tonic-gate /* 1017*0Sstevel@tonic-gate * Queue a received TPI ack message on so_ack_mp. 1018*0Sstevel@tonic-gate */ 1019*0Sstevel@tonic-gate void 1020*0Sstevel@tonic-gate soqueueack(struct sonode *so, mblk_t *mp) 1021*0Sstevel@tonic-gate { 1022*0Sstevel@tonic-gate if (DB_TYPE(mp) != M_PCPROTO) { 1023*0Sstevel@tonic-gate cmn_err(CE_WARN, 1024*0Sstevel@tonic-gate "sockfs: received unexpected M_PROTO TPI ack. Prim %d\n", 1025*0Sstevel@tonic-gate *(t_scalar_t *)mp->b_rptr); 1026*0Sstevel@tonic-gate freemsg(mp); 1027*0Sstevel@tonic-gate return; 1028*0Sstevel@tonic-gate } 1029*0Sstevel@tonic-gate 1030*0Sstevel@tonic-gate mutex_enter(&so->so_lock); 1031*0Sstevel@tonic-gate if (so->so_ack_mp != NULL) { 1032*0Sstevel@tonic-gate dprintso(so, 1, ("so_ack_mp already set\n")); 1033*0Sstevel@tonic-gate freemsg(so->so_ack_mp); 1034*0Sstevel@tonic-gate so->so_ack_mp = NULL; 1035*0Sstevel@tonic-gate } 1036*0Sstevel@tonic-gate so->so_ack_mp = mp; 1037*0Sstevel@tonic-gate cv_broadcast(&so->so_ack_cv); 1038*0Sstevel@tonic-gate mutex_exit(&so->so_lock); 1039*0Sstevel@tonic-gate } 1040*0Sstevel@tonic-gate 1041*0Sstevel@tonic-gate /* 1042*0Sstevel@tonic-gate * Wait for a TPI ack ignoring signals and errors. 1043*0Sstevel@tonic-gate */ 1044*0Sstevel@tonic-gate int 1045*0Sstevel@tonic-gate sowaitack(struct sonode *so, mblk_t **mpp, clock_t wait) 1046*0Sstevel@tonic-gate { 1047*0Sstevel@tonic-gate ASSERT(MUTEX_HELD(&so->so_lock)); 1048*0Sstevel@tonic-gate 1049*0Sstevel@tonic-gate while (so->so_ack_mp == NULL) { 1050*0Sstevel@tonic-gate #ifdef SOCK_TEST 1051*0Sstevel@tonic-gate if (wait == 0 && sock_test_timelimit != 0) 1052*0Sstevel@tonic-gate wait = sock_test_timelimit; 1053*0Sstevel@tonic-gate #endif 1054*0Sstevel@tonic-gate if (wait != 0) { 1055*0Sstevel@tonic-gate /* 1056*0Sstevel@tonic-gate * Only wait for the time limit. 1057*0Sstevel@tonic-gate */ 1058*0Sstevel@tonic-gate clock_t now; 1059*0Sstevel@tonic-gate 1060*0Sstevel@tonic-gate time_to_wait(&now, wait); 1061*0Sstevel@tonic-gate if (cv_timedwait(&so->so_ack_cv, &so->so_lock, 1062*0Sstevel@tonic-gate now) == -1) { 1063*0Sstevel@tonic-gate eprintsoline(so, ETIME); 1064*0Sstevel@tonic-gate return (ETIME); 1065*0Sstevel@tonic-gate } 1066*0Sstevel@tonic-gate } 1067*0Sstevel@tonic-gate else 1068*0Sstevel@tonic-gate cv_wait(&so->so_ack_cv, &so->so_lock); 1069*0Sstevel@tonic-gate } 1070*0Sstevel@tonic-gate *mpp = so->so_ack_mp; 1071*0Sstevel@tonic-gate #ifdef DEBUG 1072*0Sstevel@tonic-gate { 1073*0Sstevel@tonic-gate union T_primitives *tpr; 1074*0Sstevel@tonic-gate mblk_t *mp = *mpp; 1075*0Sstevel@tonic-gate 1076*0Sstevel@tonic-gate tpr = (union T_primitives *)mp->b_rptr; 1077*0Sstevel@tonic-gate ASSERT(DB_TYPE(mp) == M_PCPROTO); 1078*0Sstevel@tonic-gate ASSERT(tpr->type == T_OK_ACK || 1079*0Sstevel@tonic-gate tpr->type == T_ERROR_ACK || 1080*0Sstevel@tonic-gate tpr->type == T_BIND_ACK || 1081*0Sstevel@tonic-gate tpr->type == T_CAPABILITY_ACK || 1082*0Sstevel@tonic-gate tpr->type == T_INFO_ACK || 1083*0Sstevel@tonic-gate tpr->type == T_OPTMGMT_ACK); 1084*0Sstevel@tonic-gate } 1085*0Sstevel@tonic-gate #endif /* DEBUG */ 1086*0Sstevel@tonic-gate so->so_ack_mp = NULL; 1087*0Sstevel@tonic-gate return (0); 1088*0Sstevel@tonic-gate } 1089*0Sstevel@tonic-gate 1090*0Sstevel@tonic-gate /* 1091*0Sstevel@tonic-gate * Queue a received T_CONN_IND message on so_conn_ind_head/tail. 1092*0Sstevel@tonic-gate */ 1093*0Sstevel@tonic-gate void 1094*0Sstevel@tonic-gate soqueueconnind(struct sonode *so, mblk_t *mp) 1095*0Sstevel@tonic-gate { 1096*0Sstevel@tonic-gate if (DB_TYPE(mp) != M_PROTO) { 1097*0Sstevel@tonic-gate cmn_err(CE_WARN, 1098*0Sstevel@tonic-gate "sockfs: received unexpected M_PCPROTO T_CONN_IND\n"); 1099*0Sstevel@tonic-gate freemsg(mp); 1100*0Sstevel@tonic-gate return; 1101*0Sstevel@tonic-gate } 1102*0Sstevel@tonic-gate 1103*0Sstevel@tonic-gate mutex_enter(&so->so_lock); 1104*0Sstevel@tonic-gate ASSERT(mp->b_next == NULL); 1105*0Sstevel@tonic-gate if (so->so_conn_ind_head == NULL) { 1106*0Sstevel@tonic-gate so->so_conn_ind_head = mp; 1107*0Sstevel@tonic-gate so->so_state |= SS_HASCONNIND; 1108*0Sstevel@tonic-gate } else { 1109*0Sstevel@tonic-gate ASSERT(so->so_state & SS_HASCONNIND); 1110*0Sstevel@tonic-gate ASSERT(so->so_conn_ind_tail->b_next == NULL); 1111*0Sstevel@tonic-gate so->so_conn_ind_tail->b_next = mp; 1112*0Sstevel@tonic-gate } 1113*0Sstevel@tonic-gate so->so_conn_ind_tail = mp; 1114*0Sstevel@tonic-gate /* Wakeup a single consumer of the T_CONN_IND */ 1115*0Sstevel@tonic-gate cv_signal(&so->so_connind_cv); 1116*0Sstevel@tonic-gate mutex_exit(&so->so_lock); 1117*0Sstevel@tonic-gate } 1118*0Sstevel@tonic-gate 1119*0Sstevel@tonic-gate /* 1120*0Sstevel@tonic-gate * Wait for a T_CONN_IND. 1121*0Sstevel@tonic-gate * Don't wait if nonblocking. 1122*0Sstevel@tonic-gate * Accept signals and socket errors. 1123*0Sstevel@tonic-gate */ 1124*0Sstevel@tonic-gate int 1125*0Sstevel@tonic-gate sowaitconnind(struct sonode *so, int fmode, mblk_t **mpp) 1126*0Sstevel@tonic-gate { 1127*0Sstevel@tonic-gate mblk_t *mp; 1128*0Sstevel@tonic-gate int error = 0; 1129*0Sstevel@tonic-gate 1130*0Sstevel@tonic-gate ASSERT(MUTEX_NOT_HELD(&so->so_lock)); 1131*0Sstevel@tonic-gate mutex_enter(&so->so_lock); 1132*0Sstevel@tonic-gate check_error: 1133*0Sstevel@tonic-gate if (so->so_error) { 1134*0Sstevel@tonic-gate error = sogeterr(so); 1135*0Sstevel@tonic-gate if (error) { 1136*0Sstevel@tonic-gate mutex_exit(&so->so_lock); 1137*0Sstevel@tonic-gate return (error); 1138*0Sstevel@tonic-gate } 1139*0Sstevel@tonic-gate } 1140*0Sstevel@tonic-gate 1141*0Sstevel@tonic-gate if (so->so_conn_ind_head == NULL) { 1142*0Sstevel@tonic-gate if (fmode & (FNDELAY|FNONBLOCK)) { 1143*0Sstevel@tonic-gate error = EWOULDBLOCK; 1144*0Sstevel@tonic-gate goto done; 1145*0Sstevel@tonic-gate } 1146*0Sstevel@tonic-gate if (!cv_wait_sig_swap(&so->so_connind_cv, &so->so_lock)) { 1147*0Sstevel@tonic-gate error = EINTR; 1148*0Sstevel@tonic-gate goto done; 1149*0Sstevel@tonic-gate } 1150*0Sstevel@tonic-gate goto check_error; 1151*0Sstevel@tonic-gate } 1152*0Sstevel@tonic-gate mp = so->so_conn_ind_head; 1153*0Sstevel@tonic-gate so->so_conn_ind_head = mp->b_next; 1154*0Sstevel@tonic-gate mp->b_next = NULL; 1155*0Sstevel@tonic-gate if (so->so_conn_ind_head == NULL) { 1156*0Sstevel@tonic-gate ASSERT(so->so_conn_ind_tail == mp); 1157*0Sstevel@tonic-gate so->so_conn_ind_tail = NULL; 1158*0Sstevel@tonic-gate so->so_state &= ~SS_HASCONNIND; 1159*0Sstevel@tonic-gate } 1160*0Sstevel@tonic-gate *mpp = mp; 1161*0Sstevel@tonic-gate done: 1162*0Sstevel@tonic-gate mutex_exit(&so->so_lock); 1163*0Sstevel@tonic-gate return (error); 1164*0Sstevel@tonic-gate } 1165*0Sstevel@tonic-gate 1166*0Sstevel@tonic-gate /* 1167*0Sstevel@tonic-gate * Flush a T_CONN_IND matching the sequence number from the list. 1168*0Sstevel@tonic-gate * Return zero if found; non-zero otherwise. 1169*0Sstevel@tonic-gate * This is called very infrequently thus it is ok to do a linear search. 1170*0Sstevel@tonic-gate */ 1171*0Sstevel@tonic-gate int 1172*0Sstevel@tonic-gate soflushconnind(struct sonode *so, t_scalar_t seqno) 1173*0Sstevel@tonic-gate { 1174*0Sstevel@tonic-gate mblk_t *prevmp, *mp; 1175*0Sstevel@tonic-gate struct T_conn_ind *tci; 1176*0Sstevel@tonic-gate 1177*0Sstevel@tonic-gate mutex_enter(&so->so_lock); 1178*0Sstevel@tonic-gate for (prevmp = NULL, mp = so->so_conn_ind_head; mp != NULL; 1179*0Sstevel@tonic-gate prevmp = mp, mp = mp->b_next) { 1180*0Sstevel@tonic-gate tci = (struct T_conn_ind *)mp->b_rptr; 1181*0Sstevel@tonic-gate if (tci->SEQ_number == seqno) { 1182*0Sstevel@tonic-gate dprintso(so, 1, 1183*0Sstevel@tonic-gate ("t_discon_ind: found T_CONN_IND %d\n", seqno)); 1184*0Sstevel@tonic-gate /* Deleting last? */ 1185*0Sstevel@tonic-gate if (so->so_conn_ind_tail == mp) { 1186*0Sstevel@tonic-gate so->so_conn_ind_tail = prevmp; 1187*0Sstevel@tonic-gate } 1188*0Sstevel@tonic-gate if (prevmp == NULL) { 1189*0Sstevel@tonic-gate /* Deleting first */ 1190*0Sstevel@tonic-gate so->so_conn_ind_head = mp->b_next; 1191*0Sstevel@tonic-gate } else { 1192*0Sstevel@tonic-gate prevmp->b_next = mp->b_next; 1193*0Sstevel@tonic-gate } 1194*0Sstevel@tonic-gate mp->b_next = NULL; 1195*0Sstevel@tonic-gate if (so->so_conn_ind_head == NULL) { 1196*0Sstevel@tonic-gate ASSERT(so->so_conn_ind_tail == NULL); 1197*0Sstevel@tonic-gate so->so_state &= ~SS_HASCONNIND; 1198*0Sstevel@tonic-gate } else { 1199*0Sstevel@tonic-gate ASSERT(so->so_conn_ind_tail != NULL); 1200*0Sstevel@tonic-gate } 1201*0Sstevel@tonic-gate so->so_error = ECONNABORTED; 1202*0Sstevel@tonic-gate mutex_exit(&so->so_lock); 1203*0Sstevel@tonic-gate freemsg(mp); 1204*0Sstevel@tonic-gate return (0); 1205*0Sstevel@tonic-gate } 1206*0Sstevel@tonic-gate } 1207*0Sstevel@tonic-gate mutex_exit(&so->so_lock); 1208*0Sstevel@tonic-gate dprintso(so, 1, ("t_discon_ind: NOT found T_CONN_IND %d\n", seqno)); 1209*0Sstevel@tonic-gate return (-1); 1210*0Sstevel@tonic-gate } 1211*0Sstevel@tonic-gate 1212*0Sstevel@tonic-gate /* 1213*0Sstevel@tonic-gate * Wait until the socket is connected or there is an error. 1214*0Sstevel@tonic-gate * fmode should contain any nonblocking flags. nosig should be 1215*0Sstevel@tonic-gate * set if the caller does not want the wait to be interrupted by a signal. 1216*0Sstevel@tonic-gate */ 1217*0Sstevel@tonic-gate int 1218*0Sstevel@tonic-gate sowaitconnected(struct sonode *so, int fmode, int nosig) 1219*0Sstevel@tonic-gate { 1220*0Sstevel@tonic-gate int error; 1221*0Sstevel@tonic-gate 1222*0Sstevel@tonic-gate ASSERT(MUTEX_HELD(&so->so_lock)); 1223*0Sstevel@tonic-gate 1224*0Sstevel@tonic-gate while ((so->so_state & (SS_ISCONNECTED|SS_ISCONNECTING)) == 1225*0Sstevel@tonic-gate SS_ISCONNECTING && so->so_error == 0) { 1226*0Sstevel@tonic-gate 1227*0Sstevel@tonic-gate dprintso(so, 1, ("waiting for SS_ISCONNECTED on %p\n", so)); 1228*0Sstevel@tonic-gate if (fmode & (FNDELAY|FNONBLOCK)) 1229*0Sstevel@tonic-gate return (EINPROGRESS); 1230*0Sstevel@tonic-gate 1231*0Sstevel@tonic-gate if (nosig) 1232*0Sstevel@tonic-gate cv_wait(&so->so_state_cv, &so->so_lock); 1233*0Sstevel@tonic-gate else if (!cv_wait_sig_swap(&so->so_state_cv, &so->so_lock)) { 1234*0Sstevel@tonic-gate /* 1235*0Sstevel@tonic-gate * Return EINTR and let the application use 1236*0Sstevel@tonic-gate * nonblocking techniques for detecting when 1237*0Sstevel@tonic-gate * the connection has been established. 1238*0Sstevel@tonic-gate */ 1239*0Sstevel@tonic-gate return (EINTR); 1240*0Sstevel@tonic-gate } 1241*0Sstevel@tonic-gate dprintso(so, 1, ("awoken on %p\n", so)); 1242*0Sstevel@tonic-gate } 1243*0Sstevel@tonic-gate 1244*0Sstevel@tonic-gate if (so->so_error != 0) { 1245*0Sstevel@tonic-gate error = sogeterr(so); 1246*0Sstevel@tonic-gate ASSERT(error != 0); 1247*0Sstevel@tonic-gate dprintso(so, 1, ("sowaitconnected: error %d\n", error)); 1248*0Sstevel@tonic-gate return (error); 1249*0Sstevel@tonic-gate } 1250*0Sstevel@tonic-gate if (!(so->so_state & SS_ISCONNECTED)) { 1251*0Sstevel@tonic-gate /* 1252*0Sstevel@tonic-gate * Could have received a T_ORDREL_IND or a T_DISCON_IND with 1253*0Sstevel@tonic-gate * zero errno. Or another thread could have consumed so_error 1254*0Sstevel@tonic-gate * e.g. by calling read. 1255*0Sstevel@tonic-gate */ 1256*0Sstevel@tonic-gate error = ECONNREFUSED; 1257*0Sstevel@tonic-gate dprintso(so, 1, ("sowaitconnected: error %d\n", error)); 1258*0Sstevel@tonic-gate return (error); 1259*0Sstevel@tonic-gate } 1260*0Sstevel@tonic-gate return (0); 1261*0Sstevel@tonic-gate } 1262*0Sstevel@tonic-gate 1263*0Sstevel@tonic-gate 1264*0Sstevel@tonic-gate /* 1265*0Sstevel@tonic-gate * Handle the signal generation aspect of urgent data. 1266*0Sstevel@tonic-gate */ 1267*0Sstevel@tonic-gate static void 1268*0Sstevel@tonic-gate so_oob_sig(struct sonode *so, int extrasig, 1269*0Sstevel@tonic-gate strsigset_t *signals, strpollset_t *pollwakeups) 1270*0Sstevel@tonic-gate { 1271*0Sstevel@tonic-gate ASSERT(MUTEX_HELD(&so->so_lock)); 1272*0Sstevel@tonic-gate 1273*0Sstevel@tonic-gate ASSERT(so_verify_oobstate(so)); 1274*0Sstevel@tonic-gate ASSERT(so->so_oobsigcnt >= so->so_oobcnt); 1275*0Sstevel@tonic-gate if (so->so_oobsigcnt > so->so_oobcnt) { 1276*0Sstevel@tonic-gate /* 1277*0Sstevel@tonic-gate * Signal has already been generated once for this 1278*0Sstevel@tonic-gate * urgent "event". However, since TCP can receive updated 1279*0Sstevel@tonic-gate * urgent pointers we still generate a signal. 1280*0Sstevel@tonic-gate */ 1281*0Sstevel@tonic-gate ASSERT(so->so_state & SS_OOBPEND); 1282*0Sstevel@tonic-gate if (extrasig) { 1283*0Sstevel@tonic-gate *signals |= S_RDBAND; 1284*0Sstevel@tonic-gate *pollwakeups |= POLLRDBAND; 1285*0Sstevel@tonic-gate } 1286*0Sstevel@tonic-gate return; 1287*0Sstevel@tonic-gate } 1288*0Sstevel@tonic-gate 1289*0Sstevel@tonic-gate so->so_oobsigcnt++; 1290*0Sstevel@tonic-gate ASSERT(so->so_oobsigcnt > 0); /* Wraparound */ 1291*0Sstevel@tonic-gate ASSERT(so->so_oobsigcnt > so->so_oobcnt); 1292*0Sstevel@tonic-gate 1293*0Sstevel@tonic-gate /* 1294*0Sstevel@tonic-gate * Record (for select/poll) that urgent data is pending. 1295*0Sstevel@tonic-gate */ 1296*0Sstevel@tonic-gate so->so_state |= SS_OOBPEND; 1297*0Sstevel@tonic-gate /* 1298*0Sstevel@tonic-gate * New urgent data on the way so forget about any old 1299*0Sstevel@tonic-gate * urgent data. 1300*0Sstevel@tonic-gate */ 1301*0Sstevel@tonic-gate so->so_state &= ~(SS_HAVEOOBDATA|SS_HADOOBDATA); 1302*0Sstevel@tonic-gate if (so->so_oobmsg != NULL) { 1303*0Sstevel@tonic-gate dprintso(so, 1, ("sock: discarding old oob\n")); 1304*0Sstevel@tonic-gate freemsg(so->so_oobmsg); 1305*0Sstevel@tonic-gate so->so_oobmsg = NULL; 1306*0Sstevel@tonic-gate } 1307*0Sstevel@tonic-gate *signals |= S_RDBAND; 1308*0Sstevel@tonic-gate *pollwakeups |= POLLRDBAND; 1309*0Sstevel@tonic-gate ASSERT(so_verify_oobstate(so)); 1310*0Sstevel@tonic-gate } 1311*0Sstevel@tonic-gate 1312*0Sstevel@tonic-gate /* 1313*0Sstevel@tonic-gate * Handle the processing of the T_EXDATA_IND with urgent data. 1314*0Sstevel@tonic-gate * Returns the T_EXDATA_IND if it should be queued on the read queue. 1315*0Sstevel@tonic-gate */ 1316*0Sstevel@tonic-gate /* ARGSUSED2 */ 1317*0Sstevel@tonic-gate static mblk_t * 1318*0Sstevel@tonic-gate so_oob_exdata(struct sonode *so, mblk_t *mp, 1319*0Sstevel@tonic-gate strsigset_t *signals, strpollset_t *pollwakeups) 1320*0Sstevel@tonic-gate { 1321*0Sstevel@tonic-gate ASSERT(MUTEX_HELD(&so->so_lock)); 1322*0Sstevel@tonic-gate 1323*0Sstevel@tonic-gate ASSERT(so_verify_oobstate(so)); 1324*0Sstevel@tonic-gate 1325*0Sstevel@tonic-gate ASSERT(so->so_oobsigcnt > so->so_oobcnt); 1326*0Sstevel@tonic-gate 1327*0Sstevel@tonic-gate so->so_oobcnt++; 1328*0Sstevel@tonic-gate ASSERT(so->so_oobcnt > 0); /* wraparound? */ 1329*0Sstevel@tonic-gate ASSERT(so->so_oobsigcnt >= so->so_oobcnt); 1330*0Sstevel@tonic-gate 1331*0Sstevel@tonic-gate /* 1332*0Sstevel@tonic-gate * Set MSGMARK for SIOCATMARK. 1333*0Sstevel@tonic-gate */ 1334*0Sstevel@tonic-gate mp->b_flag |= MSGMARK; 1335*0Sstevel@tonic-gate 1336*0Sstevel@tonic-gate ASSERT(so_verify_oobstate(so)); 1337*0Sstevel@tonic-gate return (mp); 1338*0Sstevel@tonic-gate } 1339*0Sstevel@tonic-gate 1340*0Sstevel@tonic-gate /* 1341*0Sstevel@tonic-gate * Handle the processing of the actual urgent data. 1342*0Sstevel@tonic-gate * Returns the data mblk if it should be queued on the read queue. 1343*0Sstevel@tonic-gate */ 1344*0Sstevel@tonic-gate static mblk_t * 1345*0Sstevel@tonic-gate so_oob_data(struct sonode *so, mblk_t *mp, 1346*0Sstevel@tonic-gate strsigset_t *signals, strpollset_t *pollwakeups) 1347*0Sstevel@tonic-gate { 1348*0Sstevel@tonic-gate ASSERT(MUTEX_HELD(&so->so_lock)); 1349*0Sstevel@tonic-gate 1350*0Sstevel@tonic-gate ASSERT(so_verify_oobstate(so)); 1351*0Sstevel@tonic-gate 1352*0Sstevel@tonic-gate ASSERT(so->so_oobsigcnt >= so->so_oobcnt); 1353*0Sstevel@tonic-gate ASSERT(mp != NULL); 1354*0Sstevel@tonic-gate /* 1355*0Sstevel@tonic-gate * For OOBINLINE we keep the data in the T_EXDATA_IND. 1356*0Sstevel@tonic-gate * Otherwise we store it in so_oobmsg. 1357*0Sstevel@tonic-gate */ 1358*0Sstevel@tonic-gate ASSERT(so->so_oobmsg == NULL); 1359*0Sstevel@tonic-gate if (so->so_options & SO_OOBINLINE) { 1360*0Sstevel@tonic-gate *pollwakeups |= POLLIN | POLLRDNORM | POLLRDBAND; 1361*0Sstevel@tonic-gate *signals |= S_INPUT | S_RDNORM; 1362*0Sstevel@tonic-gate } else { 1363*0Sstevel@tonic-gate *pollwakeups |= POLLRDBAND; 1364*0Sstevel@tonic-gate so->so_state |= SS_HAVEOOBDATA; 1365*0Sstevel@tonic-gate so->so_oobmsg = mp; 1366*0Sstevel@tonic-gate mp = NULL; 1367*0Sstevel@tonic-gate } 1368*0Sstevel@tonic-gate ASSERT(so_verify_oobstate(so)); 1369*0Sstevel@tonic-gate return (mp); 1370*0Sstevel@tonic-gate } 1371*0Sstevel@tonic-gate 1372*0Sstevel@tonic-gate /* 1373*0Sstevel@tonic-gate * Caller must hold the mutex. 1374*0Sstevel@tonic-gate * For delayed processing, save the T_DISCON_IND received 1375*0Sstevel@tonic-gate * from below on so_discon_ind_mp. 1376*0Sstevel@tonic-gate * When the message is processed the framework will call: 1377*0Sstevel@tonic-gate * (*func)(so, mp); 1378*0Sstevel@tonic-gate */ 1379*0Sstevel@tonic-gate static void 1380*0Sstevel@tonic-gate so_save_discon_ind(struct sonode *so, 1381*0Sstevel@tonic-gate mblk_t *mp, 1382*0Sstevel@tonic-gate void (*func)(struct sonode *so, mblk_t *)) 1383*0Sstevel@tonic-gate { 1384*0Sstevel@tonic-gate ASSERT(MUTEX_HELD(&so->so_lock)); 1385*0Sstevel@tonic-gate 1386*0Sstevel@tonic-gate /* 1387*0Sstevel@tonic-gate * Discard new T_DISCON_IND if we have already received another. 1388*0Sstevel@tonic-gate * Currently the earlier message can either be on so_discon_ind_mp 1389*0Sstevel@tonic-gate * or being processed. 1390*0Sstevel@tonic-gate */ 1391*0Sstevel@tonic-gate if (so->so_discon_ind_mp != NULL || (so->so_flag & SOASYNC_UNBIND)) { 1392*0Sstevel@tonic-gate cmn_err(CE_WARN, 1393*0Sstevel@tonic-gate "sockfs: received unexpected additional T_DISCON_IND\n"); 1394*0Sstevel@tonic-gate freemsg(mp); 1395*0Sstevel@tonic-gate return; 1396*0Sstevel@tonic-gate } 1397*0Sstevel@tonic-gate mp->b_prev = (mblk_t *)func; 1398*0Sstevel@tonic-gate mp->b_next = NULL; 1399*0Sstevel@tonic-gate so->so_discon_ind_mp = mp; 1400*0Sstevel@tonic-gate } 1401*0Sstevel@tonic-gate 1402*0Sstevel@tonic-gate /* 1403*0Sstevel@tonic-gate * Caller must hold the mutex and make sure that either SOLOCKED 1404*0Sstevel@tonic-gate * or SOASYNC_UNBIND is set. Called from so_unlock_single(). 1405*0Sstevel@tonic-gate * Perform delayed processing of T_DISCON_IND message on so_discon_ind_mp. 1406*0Sstevel@tonic-gate * Need to ensure that strsock_proto() will not end up sleeping for 1407*0Sstevel@tonic-gate * SOASYNC_UNBIND, while executing this function. 1408*0Sstevel@tonic-gate */ 1409*0Sstevel@tonic-gate void 1410*0Sstevel@tonic-gate so_drain_discon_ind(struct sonode *so) 1411*0Sstevel@tonic-gate { 1412*0Sstevel@tonic-gate mblk_t *bp; 1413*0Sstevel@tonic-gate void (*func)(struct sonode *so, mblk_t *); 1414*0Sstevel@tonic-gate 1415*0Sstevel@tonic-gate ASSERT(MUTEX_HELD(&so->so_lock)); 1416*0Sstevel@tonic-gate ASSERT(so->so_flag & (SOLOCKED|SOASYNC_UNBIND)); 1417*0Sstevel@tonic-gate 1418*0Sstevel@tonic-gate /* Process T_DISCON_IND on so_discon_ind_mp */ 1419*0Sstevel@tonic-gate if ((bp = so->so_discon_ind_mp) != NULL) { 1420*0Sstevel@tonic-gate so->so_discon_ind_mp = NULL; 1421*0Sstevel@tonic-gate func = (void (*)())bp->b_prev; 1422*0Sstevel@tonic-gate bp->b_prev = NULL; 1423*0Sstevel@tonic-gate 1424*0Sstevel@tonic-gate /* 1425*0Sstevel@tonic-gate * This (*func) is supposed to generate a message downstream 1426*0Sstevel@tonic-gate * and we need to have a flag set until the corresponding 1427*0Sstevel@tonic-gate * upstream message reaches stream head. 1428*0Sstevel@tonic-gate * When processing T_DISCON_IND in strsock_discon_ind 1429*0Sstevel@tonic-gate * we hold SOASYN_UNBIND when sending T_UNBIND_REQ down and 1430*0Sstevel@tonic-gate * drop the flag after we get the ACK in strsock_proto. 1431*0Sstevel@tonic-gate */ 1432*0Sstevel@tonic-gate (void) (*func)(so, bp); 1433*0Sstevel@tonic-gate } 1434*0Sstevel@tonic-gate } 1435*0Sstevel@tonic-gate 1436*0Sstevel@tonic-gate /* 1437*0Sstevel@tonic-gate * Caller must hold the mutex. 1438*0Sstevel@tonic-gate * Remove the T_DISCON_IND on so_discon_ind_mp. 1439*0Sstevel@tonic-gate */ 1440*0Sstevel@tonic-gate void 1441*0Sstevel@tonic-gate so_flush_discon_ind(struct sonode *so) 1442*0Sstevel@tonic-gate { 1443*0Sstevel@tonic-gate mblk_t *bp; 1444*0Sstevel@tonic-gate 1445*0Sstevel@tonic-gate ASSERT(MUTEX_HELD(&so->so_lock)); 1446*0Sstevel@tonic-gate 1447*0Sstevel@tonic-gate /* 1448*0Sstevel@tonic-gate * Remove T_DISCON_IND mblk at so_discon_ind_mp. 1449*0Sstevel@tonic-gate */ 1450*0Sstevel@tonic-gate if ((bp = so->so_discon_ind_mp) != NULL) { 1451*0Sstevel@tonic-gate so->so_discon_ind_mp = NULL; 1452*0Sstevel@tonic-gate bp->b_prev = NULL; 1453*0Sstevel@tonic-gate freemsg(bp); 1454*0Sstevel@tonic-gate } 1455*0Sstevel@tonic-gate } 1456*0Sstevel@tonic-gate 1457*0Sstevel@tonic-gate /* 1458*0Sstevel@tonic-gate * Caller must hold the mutex. 1459*0Sstevel@tonic-gate * 1460*0Sstevel@tonic-gate * This function is used to process the T_DISCON_IND message. It does 1461*0Sstevel@tonic-gate * immediate processing when called from strsock_proto and delayed 1462*0Sstevel@tonic-gate * processing of discon_ind saved on so_discon_ind_mp when called from 1463*0Sstevel@tonic-gate * so_drain_discon_ind. When a T_DISCON_IND message is saved in 1464*0Sstevel@tonic-gate * so_discon_ind_mp for delayed processing, this function is registered 1465*0Sstevel@tonic-gate * as the callback function to process the message. 1466*0Sstevel@tonic-gate * 1467*0Sstevel@tonic-gate * SOASYNC_UNBIND should be held in this function, during the non-blocking 1468*0Sstevel@tonic-gate * unbind operation, and should be released only after we receive the ACK 1469*0Sstevel@tonic-gate * in strsock_proto, for the T_UNBIND_REQ sent here. Since SOLOCKED is not set, 1470*0Sstevel@tonic-gate * no TPI messages would be sent down at this time. This is to prevent M_FLUSH 1471*0Sstevel@tonic-gate * sent from either this function or tcp_unbind(), flushing away any TPI 1472*0Sstevel@tonic-gate * message that is being sent down and stays in a lower module's queue. 1473*0Sstevel@tonic-gate * 1474*0Sstevel@tonic-gate * This function drops so_lock and grabs it again. 1475*0Sstevel@tonic-gate */ 1476*0Sstevel@tonic-gate static void 1477*0Sstevel@tonic-gate strsock_discon_ind(struct sonode *so, mblk_t *discon_mp) 1478*0Sstevel@tonic-gate { 1479*0Sstevel@tonic-gate struct vnode *vp; 1480*0Sstevel@tonic-gate struct stdata *stp; 1481*0Sstevel@tonic-gate union T_primitives *tpr; 1482*0Sstevel@tonic-gate struct T_unbind_req *ubr; 1483*0Sstevel@tonic-gate mblk_t *mp; 1484*0Sstevel@tonic-gate int error; 1485*0Sstevel@tonic-gate 1486*0Sstevel@tonic-gate ASSERT(MUTEX_HELD(&so->so_lock)); 1487*0Sstevel@tonic-gate ASSERT(discon_mp); 1488*0Sstevel@tonic-gate ASSERT(discon_mp->b_rptr); 1489*0Sstevel@tonic-gate 1490*0Sstevel@tonic-gate tpr = (union T_primitives *)discon_mp->b_rptr; 1491*0Sstevel@tonic-gate ASSERT(tpr->type == T_DISCON_IND); 1492*0Sstevel@tonic-gate 1493*0Sstevel@tonic-gate vp = SOTOV(so); 1494*0Sstevel@tonic-gate stp = vp->v_stream; 1495*0Sstevel@tonic-gate ASSERT(stp); 1496*0Sstevel@tonic-gate 1497*0Sstevel@tonic-gate /* 1498*0Sstevel@tonic-gate * Not a listener 1499*0Sstevel@tonic-gate */ 1500*0Sstevel@tonic-gate ASSERT((so->so_state & SS_ACCEPTCONN) == 0); 1501*0Sstevel@tonic-gate 1502*0Sstevel@tonic-gate /* 1503*0Sstevel@tonic-gate * This assumes that the name space for DISCON_reason 1504*0Sstevel@tonic-gate * is the errno name space. 1505*0Sstevel@tonic-gate */ 1506*0Sstevel@tonic-gate soisdisconnected(so, tpr->discon_ind.DISCON_reason); 1507*0Sstevel@tonic-gate 1508*0Sstevel@tonic-gate /* 1509*0Sstevel@tonic-gate * Unbind with the transport without blocking. 1510*0Sstevel@tonic-gate * If we've already received a T_DISCON_IND do not unbind. 1511*0Sstevel@tonic-gate * 1512*0Sstevel@tonic-gate * If there is no preallocated unbind message, we have already 1513*0Sstevel@tonic-gate * unbound with the transport 1514*0Sstevel@tonic-gate * 1515*0Sstevel@tonic-gate * If the socket is not bound, no need to unbind. 1516*0Sstevel@tonic-gate */ 1517*0Sstevel@tonic-gate mp = so->so_unbind_mp; 1518*0Sstevel@tonic-gate if (mp == NULL) { 1519*0Sstevel@tonic-gate ASSERT(!(so->so_state & SS_ISBOUND)); 1520*0Sstevel@tonic-gate mutex_exit(&so->so_lock); 1521*0Sstevel@tonic-gate } else if (!(so->so_state & SS_ISBOUND)) { 1522*0Sstevel@tonic-gate mutex_exit(&so->so_lock); 1523*0Sstevel@tonic-gate } else { 1524*0Sstevel@tonic-gate so->so_unbind_mp = NULL; 1525*0Sstevel@tonic-gate 1526*0Sstevel@tonic-gate /* 1527*0Sstevel@tonic-gate * Is another T_DISCON_IND being processed. 1528*0Sstevel@tonic-gate */ 1529*0Sstevel@tonic-gate ASSERT((so->so_flag & SOASYNC_UNBIND) == 0); 1530*0Sstevel@tonic-gate 1531*0Sstevel@tonic-gate /* 1532*0Sstevel@tonic-gate * Make strsock_proto ignore T_OK_ACK and T_ERROR_ACK for 1533*0Sstevel@tonic-gate * this unbind. Set SOASYNC_UNBIND. This should be cleared 1534*0Sstevel@tonic-gate * only after we receive the ACK in strsock_proto. 1535*0Sstevel@tonic-gate */ 1536*0Sstevel@tonic-gate so->so_flag |= SOASYNC_UNBIND; 1537*0Sstevel@tonic-gate ASSERT(!(so->so_state & (SS_ISCONNECTED|SS_ISCONNECTING))); 1538*0Sstevel@tonic-gate so->so_state &= ~(SS_ISBOUND|SS_ACCEPTCONN|SS_LADDR_VALID); 1539*0Sstevel@tonic-gate mutex_exit(&so->so_lock); 1540*0Sstevel@tonic-gate 1541*0Sstevel@tonic-gate /* 1542*0Sstevel@tonic-gate * Send down T_UNBIND_REQ ignoring flow control. 1543*0Sstevel@tonic-gate * XXX Assumes that MSG_IGNFLOW implies that this thread 1544*0Sstevel@tonic-gate * does not run service procedures. 1545*0Sstevel@tonic-gate */ 1546*0Sstevel@tonic-gate ASSERT(DB_TYPE(mp) == M_PROTO); 1547*0Sstevel@tonic-gate ubr = (struct T_unbind_req *)mp->b_rptr; 1548*0Sstevel@tonic-gate mp->b_wptr += sizeof (*ubr); 1549*0Sstevel@tonic-gate ubr->PRIM_type = T_UNBIND_REQ; 1550*0Sstevel@tonic-gate 1551*0Sstevel@tonic-gate /* 1552*0Sstevel@tonic-gate * Flush the read and write side (except stream head read queue) 1553*0Sstevel@tonic-gate * and send down T_UNBIND_REQ. 1554*0Sstevel@tonic-gate */ 1555*0Sstevel@tonic-gate (void) putnextctl1(strvp2wq(SOTOV(so)), M_FLUSH, FLUSHRW); 1556*0Sstevel@tonic-gate error = kstrputmsg(SOTOV(so), mp, NULL, 0, 0, 1557*0Sstevel@tonic-gate MSG_BAND|MSG_HOLDSIG|MSG_IGNERROR|MSG_IGNFLOW, 0); 1558*0Sstevel@tonic-gate /* LINTED - warning: statement has no consequent: if */ 1559*0Sstevel@tonic-gate if (error) { 1560*0Sstevel@tonic-gate eprintsoline(so, error); 1561*0Sstevel@tonic-gate } 1562*0Sstevel@tonic-gate } 1563*0Sstevel@tonic-gate 1564*0Sstevel@tonic-gate if (tpr->discon_ind.DISCON_reason != 0) 1565*0Sstevel@tonic-gate strsetrerror(SOTOV(so), 0, 0, sogetrderr); 1566*0Sstevel@tonic-gate strsetwerror(SOTOV(so), 0, 0, sogetwrerr); 1567*0Sstevel@tonic-gate strseteof(SOTOV(so), 1); 1568*0Sstevel@tonic-gate /* 1569*0Sstevel@tonic-gate * strseteof takes care of read side wakeups, 1570*0Sstevel@tonic-gate * pollwakeups, and signals. 1571*0Sstevel@tonic-gate */ 1572*0Sstevel@tonic-gate dprintso(so, 1, ("T_DISCON_IND: error %d\n", so->so_error)); 1573*0Sstevel@tonic-gate freemsg(discon_mp); 1574*0Sstevel@tonic-gate 1575*0Sstevel@tonic-gate 1576*0Sstevel@tonic-gate pollwakeup(&stp->sd_pollist, POLLOUT); 1577*0Sstevel@tonic-gate mutex_enter(&stp->sd_lock); 1578*0Sstevel@tonic-gate 1579*0Sstevel@tonic-gate /* 1580*0Sstevel@tonic-gate * Wake sleeping write 1581*0Sstevel@tonic-gate */ 1582*0Sstevel@tonic-gate if (stp->sd_flag & WSLEEP) { 1583*0Sstevel@tonic-gate stp->sd_flag &= ~WSLEEP; 1584*0Sstevel@tonic-gate cv_broadcast(&stp->sd_wrq->q_wait); 1585*0Sstevel@tonic-gate } 1586*0Sstevel@tonic-gate 1587*0Sstevel@tonic-gate /* 1588*0Sstevel@tonic-gate * strsendsig can handle multiple signals with a 1589*0Sstevel@tonic-gate * single call. Send SIGPOLL for S_OUTPUT event. 1590*0Sstevel@tonic-gate */ 1591*0Sstevel@tonic-gate if (stp->sd_sigflags & S_OUTPUT) 1592*0Sstevel@tonic-gate strsendsig(stp->sd_siglist, S_OUTPUT, 0, 0); 1593*0Sstevel@tonic-gate 1594*0Sstevel@tonic-gate mutex_exit(&stp->sd_lock); 1595*0Sstevel@tonic-gate mutex_enter(&so->so_lock); 1596*0Sstevel@tonic-gate } 1597*0Sstevel@tonic-gate 1598*0Sstevel@tonic-gate /* 1599*0Sstevel@tonic-gate * This routine is registered with the stream head to receive M_PROTO 1600*0Sstevel@tonic-gate * and M_PCPROTO messages. 1601*0Sstevel@tonic-gate * 1602*0Sstevel@tonic-gate * Returns NULL if the message was consumed. 1603*0Sstevel@tonic-gate * Returns an mblk to make that mblk be processed (and queued) by the stream 1604*0Sstevel@tonic-gate * head. 1605*0Sstevel@tonic-gate * 1606*0Sstevel@tonic-gate * Sets the return parameters (*wakeups, *firstmsgsigs, *allmsgsigs, and 1607*0Sstevel@tonic-gate * *pollwakeups) for the stream head to take action on. Note that since 1608*0Sstevel@tonic-gate * sockets always deliver SIGIO for every new piece of data this routine 1609*0Sstevel@tonic-gate * never sets *firstmsgsigs; any signals are returned in *allmsgsigs. 1610*0Sstevel@tonic-gate * 1611*0Sstevel@tonic-gate * This routine handles all data related TPI messages independent of 1612*0Sstevel@tonic-gate * the type of the socket i.e. it doesn't care if T_UNITDATA_IND message 1613*0Sstevel@tonic-gate * arrive on a SOCK_STREAM. 1614*0Sstevel@tonic-gate */ 1615*0Sstevel@tonic-gate static mblk_t * 1616*0Sstevel@tonic-gate strsock_proto(vnode_t *vp, mblk_t *mp, 1617*0Sstevel@tonic-gate strwakeup_t *wakeups, strsigset_t *firstmsgsigs, 1618*0Sstevel@tonic-gate strsigset_t *allmsgsigs, strpollset_t *pollwakeups) 1619*0Sstevel@tonic-gate { 1620*0Sstevel@tonic-gate union T_primitives *tpr; 1621*0Sstevel@tonic-gate struct sonode *so; 1622*0Sstevel@tonic-gate 1623*0Sstevel@tonic-gate so = VTOSO(vp); 1624*0Sstevel@tonic-gate 1625*0Sstevel@tonic-gate dprintso(so, 1, ("strsock_proto(%p, %p)\n", vp, mp)); 1626*0Sstevel@tonic-gate 1627*0Sstevel@tonic-gate /* Set default return values */ 1628*0Sstevel@tonic-gate *firstmsgsigs = *wakeups = *allmsgsigs = *pollwakeups = 0; 1629*0Sstevel@tonic-gate 1630*0Sstevel@tonic-gate ASSERT(DB_TYPE(mp) == M_PROTO || 1631*0Sstevel@tonic-gate DB_TYPE(mp) == M_PCPROTO); 1632*0Sstevel@tonic-gate 1633*0Sstevel@tonic-gate if (MBLKL(mp) < sizeof (tpr->type)) { 1634*0Sstevel@tonic-gate /* The message is too short to even contain the primitive */ 1635*0Sstevel@tonic-gate cmn_err(CE_WARN, 1636*0Sstevel@tonic-gate "sockfs: Too short TPI message received. Len = %ld\n", 1637*0Sstevel@tonic-gate (ptrdiff_t)(MBLKL(mp))); 1638*0Sstevel@tonic-gate freemsg(mp); 1639*0Sstevel@tonic-gate return (NULL); 1640*0Sstevel@tonic-gate } 1641*0Sstevel@tonic-gate if (!__TPI_PRIM_ISALIGNED(mp->b_rptr)) { 1642*0Sstevel@tonic-gate /* The read pointer is not aligned correctly for TPI */ 1643*0Sstevel@tonic-gate cmn_err(CE_WARN, 1644*0Sstevel@tonic-gate "sockfs: Unaligned TPI message received. rptr = %p\n", 1645*0Sstevel@tonic-gate (void *)mp->b_rptr); 1646*0Sstevel@tonic-gate freemsg(mp); 1647*0Sstevel@tonic-gate return (NULL); 1648*0Sstevel@tonic-gate } 1649*0Sstevel@tonic-gate tpr = (union T_primitives *)mp->b_rptr; 1650*0Sstevel@tonic-gate dprintso(so, 1, ("strsock_proto: primitive %d\n", tpr->type)); 1651*0Sstevel@tonic-gate 1652*0Sstevel@tonic-gate switch (tpr->type) { 1653*0Sstevel@tonic-gate 1654*0Sstevel@tonic-gate case T_DATA_IND: 1655*0Sstevel@tonic-gate if (MBLKL(mp) < sizeof (struct T_data_ind)) { 1656*0Sstevel@tonic-gate cmn_err(CE_WARN, 1657*0Sstevel@tonic-gate "sockfs: Too short T_DATA_IND. Len = %ld\n", 1658*0Sstevel@tonic-gate (ptrdiff_t)(MBLKL(mp))); 1659*0Sstevel@tonic-gate freemsg(mp); 1660*0Sstevel@tonic-gate return (NULL); 1661*0Sstevel@tonic-gate } 1662*0Sstevel@tonic-gate /* 1663*0Sstevel@tonic-gate * Ignore zero-length T_DATA_IND messages. These might be 1664*0Sstevel@tonic-gate * generated by some transports. 1665*0Sstevel@tonic-gate * This is needed to prevent read (which skips the M_PROTO 1666*0Sstevel@tonic-gate * part) to unexpectedly return 0 (or return EWOULDBLOCK 1667*0Sstevel@tonic-gate * on a non-blocking socket after select/poll has indicated 1668*0Sstevel@tonic-gate * that data is available). 1669*0Sstevel@tonic-gate */ 1670*0Sstevel@tonic-gate if (msgdsize(mp->b_cont) == 0) { 1671*0Sstevel@tonic-gate dprintso(so, 0, 1672*0Sstevel@tonic-gate ("strsock_proto: zero length T_DATA_IND\n")); 1673*0Sstevel@tonic-gate freemsg(mp); 1674*0Sstevel@tonic-gate return (NULL); 1675*0Sstevel@tonic-gate } 1676*0Sstevel@tonic-gate *allmsgsigs = S_INPUT | S_RDNORM; 1677*0Sstevel@tonic-gate *pollwakeups = POLLIN | POLLRDNORM; 1678*0Sstevel@tonic-gate *wakeups = RSLEEP; 1679*0Sstevel@tonic-gate return (mp); 1680*0Sstevel@tonic-gate 1681*0Sstevel@tonic-gate case T_UNITDATA_IND: { 1682*0Sstevel@tonic-gate struct T_unitdata_ind *tudi = &tpr->unitdata_ind; 1683*0Sstevel@tonic-gate void *addr; 1684*0Sstevel@tonic-gate t_uscalar_t addrlen; 1685*0Sstevel@tonic-gate 1686*0Sstevel@tonic-gate if (MBLKL(mp) < sizeof (struct T_unitdata_ind)) { 1687*0Sstevel@tonic-gate cmn_err(CE_WARN, 1688*0Sstevel@tonic-gate "sockfs: Too short T_UNITDATA_IND. Len = %ld\n", 1689*0Sstevel@tonic-gate (ptrdiff_t)(MBLKL(mp))); 1690*0Sstevel@tonic-gate freemsg(mp); 1691*0Sstevel@tonic-gate return (NULL); 1692*0Sstevel@tonic-gate } 1693*0Sstevel@tonic-gate 1694*0Sstevel@tonic-gate /* Is this is not a connected datagram socket? */ 1695*0Sstevel@tonic-gate if ((so->so_mode & SM_CONNREQUIRED) || 1696*0Sstevel@tonic-gate !(so->so_state & SS_ISCONNECTED)) { 1697*0Sstevel@tonic-gate /* 1698*0Sstevel@tonic-gate * Not a connected datagram socket. Look for 1699*0Sstevel@tonic-gate * the SO_UNIX_CLOSE option. If such an option is found 1700*0Sstevel@tonic-gate * discard the message (since it has no meaning 1701*0Sstevel@tonic-gate * unless connected). 1702*0Sstevel@tonic-gate */ 1703*0Sstevel@tonic-gate if (so->so_family == AF_UNIX && msgdsize(mp) == 0 && 1704*0Sstevel@tonic-gate tudi->OPT_length != 0) { 1705*0Sstevel@tonic-gate void *opt; 1706*0Sstevel@tonic-gate t_uscalar_t optlen = tudi->OPT_length; 1707*0Sstevel@tonic-gate 1708*0Sstevel@tonic-gate opt = sogetoff(mp, tudi->OPT_offset, 1709*0Sstevel@tonic-gate optlen, __TPI_ALIGN_SIZE); 1710*0Sstevel@tonic-gate if (opt == NULL) { 1711*0Sstevel@tonic-gate /* The len/off falls outside mp */ 1712*0Sstevel@tonic-gate freemsg(mp); 1713*0Sstevel@tonic-gate mutex_enter(&so->so_lock); 1714*0Sstevel@tonic-gate soseterror(so, EPROTO); 1715*0Sstevel@tonic-gate mutex_exit(&so->so_lock); 1716*0Sstevel@tonic-gate cmn_err(CE_WARN, 1717*0Sstevel@tonic-gate "sockfs: T_unidata_ind with " 1718*0Sstevel@tonic-gate "invalid optlen/offset %u/%d\n", 1719*0Sstevel@tonic-gate optlen, tudi->OPT_offset); 1720*0Sstevel@tonic-gate return (NULL); 1721*0Sstevel@tonic-gate } 1722*0Sstevel@tonic-gate if (so_getopt_unix_close(opt, optlen)) { 1723*0Sstevel@tonic-gate freemsg(mp); 1724*0Sstevel@tonic-gate return (NULL); 1725*0Sstevel@tonic-gate } 1726*0Sstevel@tonic-gate } 1727*0Sstevel@tonic-gate *allmsgsigs = S_INPUT | S_RDNORM; 1728*0Sstevel@tonic-gate *pollwakeups = POLLIN | POLLRDNORM; 1729*0Sstevel@tonic-gate *wakeups = RSLEEP; 1730*0Sstevel@tonic-gate #ifdef C2_AUDIT 1731*0Sstevel@tonic-gate if (audit_active) 1732*0Sstevel@tonic-gate audit_sock(T_UNITDATA_IND, strvp2wq(vp), 1733*0Sstevel@tonic-gate mp, 0); 1734*0Sstevel@tonic-gate #endif /* C2_AUDIT */ 1735*0Sstevel@tonic-gate return (mp); 1736*0Sstevel@tonic-gate } 1737*0Sstevel@tonic-gate 1738*0Sstevel@tonic-gate /* 1739*0Sstevel@tonic-gate * A connect datagram socket. For AF_INET{,6} we verify that 1740*0Sstevel@tonic-gate * the source address matches the "connected to" address. 1741*0Sstevel@tonic-gate * The semantics of AF_UNIX sockets is to not verify 1742*0Sstevel@tonic-gate * the source address. 1743*0Sstevel@tonic-gate * Note that this source address verification is transport 1744*0Sstevel@tonic-gate * specific. Thus the real fix would be to extent TPI 1745*0Sstevel@tonic-gate * to allow T_CONN_REQ messages to be send to connectionless 1746*0Sstevel@tonic-gate * transport providers and always let the transport provider 1747*0Sstevel@tonic-gate * do whatever filtering is needed. 1748*0Sstevel@tonic-gate * 1749*0Sstevel@tonic-gate * The verification/filtering semantics for transports 1750*0Sstevel@tonic-gate * other than AF_INET and AF_UNIX are unknown. The choice 1751*0Sstevel@tonic-gate * would be to either filter using bcmp or let all messages 1752*0Sstevel@tonic-gate * get through. This code does not filter other address 1753*0Sstevel@tonic-gate * families since this at least allows the application to 1754*0Sstevel@tonic-gate * work around any missing filtering. 1755*0Sstevel@tonic-gate * 1756*0Sstevel@tonic-gate * XXX Should we move filtering to UDP/ICMP??? 1757*0Sstevel@tonic-gate * That would require passing e.g. a T_DISCON_REQ to UDP 1758*0Sstevel@tonic-gate * when the socket becomes unconnected. 1759*0Sstevel@tonic-gate */ 1760*0Sstevel@tonic-gate addrlen = tudi->SRC_length; 1761*0Sstevel@tonic-gate /* 1762*0Sstevel@tonic-gate * The alignment restriction is really to strict but 1763*0Sstevel@tonic-gate * we want enough alignment to inspect the fields of 1764*0Sstevel@tonic-gate * a sockaddr_in. 1765*0Sstevel@tonic-gate */ 1766*0Sstevel@tonic-gate addr = sogetoff(mp, tudi->SRC_offset, addrlen, 1767*0Sstevel@tonic-gate __TPI_ALIGN_SIZE); 1768*0Sstevel@tonic-gate if (addr == NULL) { 1769*0Sstevel@tonic-gate freemsg(mp); 1770*0Sstevel@tonic-gate mutex_enter(&so->so_lock); 1771*0Sstevel@tonic-gate soseterror(so, EPROTO); 1772*0Sstevel@tonic-gate mutex_exit(&so->so_lock); 1773*0Sstevel@tonic-gate cmn_err(CE_WARN, 1774*0Sstevel@tonic-gate "sockfs: T_unidata_ind with invalid " 1775*0Sstevel@tonic-gate "addrlen/offset %u/%d\n", 1776*0Sstevel@tonic-gate addrlen, tudi->SRC_offset); 1777*0Sstevel@tonic-gate return (NULL); 1778*0Sstevel@tonic-gate } 1779*0Sstevel@tonic-gate 1780*0Sstevel@tonic-gate if (so->so_family == AF_INET) { 1781*0Sstevel@tonic-gate /* 1782*0Sstevel@tonic-gate * For AF_INET we allow wildcarding both sin_addr 1783*0Sstevel@tonic-gate * and sin_port. 1784*0Sstevel@tonic-gate */ 1785*0Sstevel@tonic-gate struct sockaddr_in *faddr, *sin; 1786*0Sstevel@tonic-gate 1787*0Sstevel@tonic-gate /* Prevent so_faddr_sa from changing while accessed */ 1788*0Sstevel@tonic-gate mutex_enter(&so->so_lock); 1789*0Sstevel@tonic-gate ASSERT(so->so_faddr_len == 1790*0Sstevel@tonic-gate (socklen_t)sizeof (struct sockaddr_in)); 1791*0Sstevel@tonic-gate faddr = (struct sockaddr_in *)so->so_faddr_sa; 1792*0Sstevel@tonic-gate sin = (struct sockaddr_in *)addr; 1793*0Sstevel@tonic-gate if (addrlen != 1794*0Sstevel@tonic-gate (t_uscalar_t)sizeof (struct sockaddr_in) || 1795*0Sstevel@tonic-gate (sin->sin_addr.s_addr != faddr->sin_addr.s_addr && 1796*0Sstevel@tonic-gate faddr->sin_addr.s_addr != INADDR_ANY) || 1797*0Sstevel@tonic-gate (so->so_type != SOCK_RAW && 1798*0Sstevel@tonic-gate sin->sin_port != faddr->sin_port && 1799*0Sstevel@tonic-gate faddr->sin_port != 0)) { 1800*0Sstevel@tonic-gate #ifdef DEBUG 1801*0Sstevel@tonic-gate dprintso(so, 0, 1802*0Sstevel@tonic-gate ("sockfs: T_UNITDATA_IND mismatch: %s", 1803*0Sstevel@tonic-gate pr_addr(so->so_family, 1804*0Sstevel@tonic-gate (struct sockaddr *)addr, 1805*0Sstevel@tonic-gate addrlen))); 1806*0Sstevel@tonic-gate dprintso(so, 0, (" - %s\n", 1807*0Sstevel@tonic-gate pr_addr(so->so_family, so->so_faddr_sa, 1808*0Sstevel@tonic-gate (t_uscalar_t)so->so_faddr_len))); 1809*0Sstevel@tonic-gate #endif /* DEBUG */ 1810*0Sstevel@tonic-gate mutex_exit(&so->so_lock); 1811*0Sstevel@tonic-gate freemsg(mp); 1812*0Sstevel@tonic-gate return (NULL); 1813*0Sstevel@tonic-gate } 1814*0Sstevel@tonic-gate mutex_exit(&so->so_lock); 1815*0Sstevel@tonic-gate } else if (so->so_family == AF_INET6) { 1816*0Sstevel@tonic-gate /* 1817*0Sstevel@tonic-gate * For AF_INET6 we allow wildcarding both sin6_addr 1818*0Sstevel@tonic-gate * and sin6_port. 1819*0Sstevel@tonic-gate */ 1820*0Sstevel@tonic-gate struct sockaddr_in6 *faddr6, *sin6; 1821*0Sstevel@tonic-gate static struct in6_addr zeroes; /* inits to all zeros */ 1822*0Sstevel@tonic-gate 1823*0Sstevel@tonic-gate /* Prevent so_faddr_sa from changing while accessed */ 1824*0Sstevel@tonic-gate mutex_enter(&so->so_lock); 1825*0Sstevel@tonic-gate ASSERT(so->so_faddr_len == 1826*0Sstevel@tonic-gate (socklen_t)sizeof (struct sockaddr_in6)); 1827*0Sstevel@tonic-gate faddr6 = (struct sockaddr_in6 *)so->so_faddr_sa; 1828*0Sstevel@tonic-gate sin6 = (struct sockaddr_in6 *)addr; 1829*0Sstevel@tonic-gate /* XXX could we get a mapped address ::ffff:0.0.0.0 ? */ 1830*0Sstevel@tonic-gate if (addrlen != 1831*0Sstevel@tonic-gate (t_uscalar_t)sizeof (struct sockaddr_in6) || 1832*0Sstevel@tonic-gate (!IN6_ARE_ADDR_EQUAL(&sin6->sin6_addr, 1833*0Sstevel@tonic-gate &faddr6->sin6_addr) && 1834*0Sstevel@tonic-gate !IN6_ARE_ADDR_EQUAL(&faddr6->sin6_addr, &zeroes)) || 1835*0Sstevel@tonic-gate (so->so_type != SOCK_RAW && 1836*0Sstevel@tonic-gate sin6->sin6_port != faddr6->sin6_port && 1837*0Sstevel@tonic-gate faddr6->sin6_port != 0)) { 1838*0Sstevel@tonic-gate #ifdef DEBUG 1839*0Sstevel@tonic-gate dprintso(so, 0, 1840*0Sstevel@tonic-gate ("sockfs: T_UNITDATA_IND mismatch: %s", 1841*0Sstevel@tonic-gate pr_addr(so->so_family, 1842*0Sstevel@tonic-gate (struct sockaddr *)addr, 1843*0Sstevel@tonic-gate addrlen))); 1844*0Sstevel@tonic-gate dprintso(so, 0, (" - %s\n", 1845*0Sstevel@tonic-gate pr_addr(so->so_family, so->so_faddr_sa, 1846*0Sstevel@tonic-gate (t_uscalar_t)so->so_faddr_len))); 1847*0Sstevel@tonic-gate #endif /* DEBUG */ 1848*0Sstevel@tonic-gate mutex_exit(&so->so_lock); 1849*0Sstevel@tonic-gate freemsg(mp); 1850*0Sstevel@tonic-gate return (NULL); 1851*0Sstevel@tonic-gate } 1852*0Sstevel@tonic-gate mutex_exit(&so->so_lock); 1853*0Sstevel@tonic-gate } else if (so->so_family == AF_UNIX && 1854*0Sstevel@tonic-gate msgdsize(mp->b_cont) == 0 && 1855*0Sstevel@tonic-gate tudi->OPT_length != 0) { 1856*0Sstevel@tonic-gate /* 1857*0Sstevel@tonic-gate * Attempt to extract AF_UNIX 1858*0Sstevel@tonic-gate * SO_UNIX_CLOSE indication from options. 1859*0Sstevel@tonic-gate */ 1860*0Sstevel@tonic-gate void *opt; 1861*0Sstevel@tonic-gate t_uscalar_t optlen = tudi->OPT_length; 1862*0Sstevel@tonic-gate 1863*0Sstevel@tonic-gate opt = sogetoff(mp, tudi->OPT_offset, 1864*0Sstevel@tonic-gate optlen, __TPI_ALIGN_SIZE); 1865*0Sstevel@tonic-gate if (opt == NULL) { 1866*0Sstevel@tonic-gate /* The len/off falls outside mp */ 1867*0Sstevel@tonic-gate freemsg(mp); 1868*0Sstevel@tonic-gate mutex_enter(&so->so_lock); 1869*0Sstevel@tonic-gate soseterror(so, EPROTO); 1870*0Sstevel@tonic-gate mutex_exit(&so->so_lock); 1871*0Sstevel@tonic-gate cmn_err(CE_WARN, 1872*0Sstevel@tonic-gate "sockfs: T_unidata_ind with invalid " 1873*0Sstevel@tonic-gate "optlen/offset %u/%d\n", 1874*0Sstevel@tonic-gate optlen, tudi->OPT_offset); 1875*0Sstevel@tonic-gate return (NULL); 1876*0Sstevel@tonic-gate } 1877*0Sstevel@tonic-gate /* 1878*0Sstevel@tonic-gate * If we received a unix close indication mark the 1879*0Sstevel@tonic-gate * socket and discard this message. 1880*0Sstevel@tonic-gate */ 1881*0Sstevel@tonic-gate if (so_getopt_unix_close(opt, optlen)) { 1882*0Sstevel@tonic-gate mutex_enter(&so->so_lock); 1883*0Sstevel@tonic-gate sobreakconn(so, ECONNRESET); 1884*0Sstevel@tonic-gate mutex_exit(&so->so_lock); 1885*0Sstevel@tonic-gate strsetrerror(SOTOV(so), 0, 0, sogetrderr); 1886*0Sstevel@tonic-gate freemsg(mp); 1887*0Sstevel@tonic-gate *pollwakeups = POLLIN | POLLRDNORM; 1888*0Sstevel@tonic-gate *allmsgsigs = S_INPUT | S_RDNORM; 1889*0Sstevel@tonic-gate *wakeups = RSLEEP; 1890*0Sstevel@tonic-gate return (NULL); 1891*0Sstevel@tonic-gate } 1892*0Sstevel@tonic-gate } 1893*0Sstevel@tonic-gate *allmsgsigs = S_INPUT | S_RDNORM; 1894*0Sstevel@tonic-gate *pollwakeups = POLLIN | POLLRDNORM; 1895*0Sstevel@tonic-gate *wakeups = RSLEEP; 1896*0Sstevel@tonic-gate return (mp); 1897*0Sstevel@tonic-gate } 1898*0Sstevel@tonic-gate 1899*0Sstevel@tonic-gate case T_OPTDATA_IND: { 1900*0Sstevel@tonic-gate struct T_optdata_ind *tdi = &tpr->optdata_ind; 1901*0Sstevel@tonic-gate 1902*0Sstevel@tonic-gate if (MBLKL(mp) < sizeof (struct T_optdata_ind)) { 1903*0Sstevel@tonic-gate cmn_err(CE_WARN, 1904*0Sstevel@tonic-gate "sockfs: Too short T_OPTDATA_IND. Len = %ld\n", 1905*0Sstevel@tonic-gate (ptrdiff_t)(MBLKL(mp))); 1906*0Sstevel@tonic-gate freemsg(mp); 1907*0Sstevel@tonic-gate return (NULL); 1908*0Sstevel@tonic-gate } 1909*0Sstevel@tonic-gate /* 1910*0Sstevel@tonic-gate * Allow zero-length messages carrying options. 1911*0Sstevel@tonic-gate * This is used when carrying the SO_UNIX_CLOSE option. 1912*0Sstevel@tonic-gate */ 1913*0Sstevel@tonic-gate if (so->so_family == AF_UNIX && msgdsize(mp->b_cont) == 0 && 1914*0Sstevel@tonic-gate tdi->OPT_length != 0) { 1915*0Sstevel@tonic-gate /* 1916*0Sstevel@tonic-gate * Attempt to extract AF_UNIX close indication 1917*0Sstevel@tonic-gate * from the options. Ignore any other options - 1918*0Sstevel@tonic-gate * those are handled once the message is removed 1919*0Sstevel@tonic-gate * from the queue. 1920*0Sstevel@tonic-gate * The close indication message should not carry data. 1921*0Sstevel@tonic-gate */ 1922*0Sstevel@tonic-gate void *opt; 1923*0Sstevel@tonic-gate t_uscalar_t optlen = tdi->OPT_length; 1924*0Sstevel@tonic-gate 1925*0Sstevel@tonic-gate opt = sogetoff(mp, tdi->OPT_offset, 1926*0Sstevel@tonic-gate optlen, __TPI_ALIGN_SIZE); 1927*0Sstevel@tonic-gate if (opt == NULL) { 1928*0Sstevel@tonic-gate /* The len/off falls outside mp */ 1929*0Sstevel@tonic-gate freemsg(mp); 1930*0Sstevel@tonic-gate mutex_enter(&so->so_lock); 1931*0Sstevel@tonic-gate soseterror(so, EPROTO); 1932*0Sstevel@tonic-gate mutex_exit(&so->so_lock); 1933*0Sstevel@tonic-gate cmn_err(CE_WARN, 1934*0Sstevel@tonic-gate "sockfs: T_optdata_ind with invalid " 1935*0Sstevel@tonic-gate "optlen/offset %u/%d\n", 1936*0Sstevel@tonic-gate optlen, tdi->OPT_offset); 1937*0Sstevel@tonic-gate return (NULL); 1938*0Sstevel@tonic-gate } 1939*0Sstevel@tonic-gate /* 1940*0Sstevel@tonic-gate * If we received a close indication mark the 1941*0Sstevel@tonic-gate * socket and discard this message. 1942*0Sstevel@tonic-gate */ 1943*0Sstevel@tonic-gate if (so_getopt_unix_close(opt, optlen)) { 1944*0Sstevel@tonic-gate mutex_enter(&so->so_lock); 1945*0Sstevel@tonic-gate socantsendmore(so); 1946*0Sstevel@tonic-gate mutex_exit(&so->so_lock); 1947*0Sstevel@tonic-gate strsetwerror(SOTOV(so), 0, 0, sogetwrerr); 1948*0Sstevel@tonic-gate freemsg(mp); 1949*0Sstevel@tonic-gate return (NULL); 1950*0Sstevel@tonic-gate } 1951*0Sstevel@tonic-gate } 1952*0Sstevel@tonic-gate *allmsgsigs = S_INPUT | S_RDNORM; 1953*0Sstevel@tonic-gate *pollwakeups = POLLIN | POLLRDNORM; 1954*0Sstevel@tonic-gate *wakeups = RSLEEP; 1955*0Sstevel@tonic-gate return (mp); 1956*0Sstevel@tonic-gate } 1957*0Sstevel@tonic-gate 1958*0Sstevel@tonic-gate case T_EXDATA_IND: { 1959*0Sstevel@tonic-gate mblk_t *mctl, *mdata; 1960*0Sstevel@tonic-gate 1961*0Sstevel@tonic-gate if (MBLKL(mp) < sizeof (struct T_exdata_ind)) { 1962*0Sstevel@tonic-gate cmn_err(CE_WARN, 1963*0Sstevel@tonic-gate "sockfs: Too short T_EXDATA_IND. Len = %ld\n", 1964*0Sstevel@tonic-gate (ptrdiff_t)(MBLKL(mp))); 1965*0Sstevel@tonic-gate freemsg(mp); 1966*0Sstevel@tonic-gate return (NULL); 1967*0Sstevel@tonic-gate } 1968*0Sstevel@tonic-gate /* 1969*0Sstevel@tonic-gate * Ignore zero-length T_EXDATA_IND messages. These might be 1970*0Sstevel@tonic-gate * generated by some transports. 1971*0Sstevel@tonic-gate * 1972*0Sstevel@tonic-gate * This is needed to prevent read (which skips the M_PROTO 1973*0Sstevel@tonic-gate * part) to unexpectedly return 0 (or return EWOULDBLOCK 1974*0Sstevel@tonic-gate * on a non-blocking socket after select/poll has indicated 1975*0Sstevel@tonic-gate * that data is available). 1976*0Sstevel@tonic-gate */ 1977*0Sstevel@tonic-gate dprintso(so, 1, 1978*0Sstevel@tonic-gate ("T_EXDATA_IND(%p): counts %d/%d state %s\n", 1979*0Sstevel@tonic-gate vp, so->so_oobsigcnt, so->so_oobcnt, 1980*0Sstevel@tonic-gate pr_state(so->so_state, so->so_mode))); 1981*0Sstevel@tonic-gate 1982*0Sstevel@tonic-gate if (msgdsize(mp->b_cont) == 0) { 1983*0Sstevel@tonic-gate dprintso(so, 0, 1984*0Sstevel@tonic-gate ("strsock_proto: zero length T_EXDATA_IND\n")); 1985*0Sstevel@tonic-gate freemsg(mp); 1986*0Sstevel@tonic-gate return (NULL); 1987*0Sstevel@tonic-gate } 1988*0Sstevel@tonic-gate 1989*0Sstevel@tonic-gate /* 1990*0Sstevel@tonic-gate * Split into the T_EXDATA_IND and the M_DATA part. 1991*0Sstevel@tonic-gate * We process these three pieces separately: 1992*0Sstevel@tonic-gate * signal generation 1993*0Sstevel@tonic-gate * handling T_EXDATA_IND 1994*0Sstevel@tonic-gate * handling M_DATA component 1995*0Sstevel@tonic-gate */ 1996*0Sstevel@tonic-gate mctl = mp; 1997*0Sstevel@tonic-gate mdata = mctl->b_cont; 1998*0Sstevel@tonic-gate mctl->b_cont = NULL; 1999*0Sstevel@tonic-gate mutex_enter(&so->so_lock); 2000*0Sstevel@tonic-gate so_oob_sig(so, 0, allmsgsigs, pollwakeups); 2001*0Sstevel@tonic-gate mctl = so_oob_exdata(so, mctl, allmsgsigs, pollwakeups); 2002*0Sstevel@tonic-gate mdata = so_oob_data(so, mdata, allmsgsigs, pollwakeups); 2003*0Sstevel@tonic-gate 2004*0Sstevel@tonic-gate /* 2005*0Sstevel@tonic-gate * Pass the T_EXDATA_IND and the M_DATA back separately 2006*0Sstevel@tonic-gate * by using b_next linkage. (The stream head will queue any 2007*0Sstevel@tonic-gate * b_next linked messages separately.) This is needed 2008*0Sstevel@tonic-gate * since MSGMARK applies to the last by of the message 2009*0Sstevel@tonic-gate * hence we can not have any M_DATA component attached 2010*0Sstevel@tonic-gate * to the marked T_EXDATA_IND. Note that the stream head 2011*0Sstevel@tonic-gate * will not consolidate M_DATA messages onto an MSGMARK'ed 2012*0Sstevel@tonic-gate * message in order to preserve the constraint that 2013*0Sstevel@tonic-gate * the T_EXDATA_IND always is a separate message. 2014*0Sstevel@tonic-gate */ 2015*0Sstevel@tonic-gate ASSERT(mctl != NULL); 2016*0Sstevel@tonic-gate mctl->b_next = mdata; 2017*0Sstevel@tonic-gate mp = mctl; 2018*0Sstevel@tonic-gate #ifdef DEBUG 2019*0Sstevel@tonic-gate if (mdata == NULL) { 2020*0Sstevel@tonic-gate dprintso(so, 1, 2021*0Sstevel@tonic-gate ("after outofline T_EXDATA_IND(%p): " 2022*0Sstevel@tonic-gate "counts %d/%d poll 0x%x sig 0x%x state %s\n", 2023*0Sstevel@tonic-gate vp, so->so_oobsigcnt, 2024*0Sstevel@tonic-gate so->so_oobcnt, *pollwakeups, *allmsgsigs, 2025*0Sstevel@tonic-gate pr_state(so->so_state, so->so_mode))); 2026*0Sstevel@tonic-gate } else { 2027*0Sstevel@tonic-gate dprintso(so, 1, 2028*0Sstevel@tonic-gate ("after inline T_EXDATA_IND(%p): " 2029*0Sstevel@tonic-gate "counts %d/%d poll 0x%x sig 0x%x state %s\n", 2030*0Sstevel@tonic-gate vp, so->so_oobsigcnt, 2031*0Sstevel@tonic-gate so->so_oobcnt, *pollwakeups, *allmsgsigs, 2032*0Sstevel@tonic-gate pr_state(so->so_state, so->so_mode))); 2033*0Sstevel@tonic-gate } 2034*0Sstevel@tonic-gate #endif /* DEBUG */ 2035*0Sstevel@tonic-gate mutex_exit(&so->so_lock); 2036*0Sstevel@tonic-gate *wakeups = RSLEEP; 2037*0Sstevel@tonic-gate return (mp); 2038*0Sstevel@tonic-gate } 2039*0Sstevel@tonic-gate 2040*0Sstevel@tonic-gate case T_CONN_CON: { 2041*0Sstevel@tonic-gate struct T_conn_con *conn_con; 2042*0Sstevel@tonic-gate void *addr; 2043*0Sstevel@tonic-gate t_uscalar_t addrlen; 2044*0Sstevel@tonic-gate 2045*0Sstevel@tonic-gate /* 2046*0Sstevel@tonic-gate * Verify the state, update the state to ISCONNECTED, 2047*0Sstevel@tonic-gate * record the potentially new address in the message, 2048*0Sstevel@tonic-gate * and drop the message. 2049*0Sstevel@tonic-gate */ 2050*0Sstevel@tonic-gate if (MBLKL(mp) < sizeof (struct T_conn_con)) { 2051*0Sstevel@tonic-gate cmn_err(CE_WARN, 2052*0Sstevel@tonic-gate "sockfs: Too short T_CONN_CON. Len = %ld\n", 2053*0Sstevel@tonic-gate (ptrdiff_t)(MBLKL(mp))); 2054*0Sstevel@tonic-gate freemsg(mp); 2055*0Sstevel@tonic-gate return (NULL); 2056*0Sstevel@tonic-gate } 2057*0Sstevel@tonic-gate 2058*0Sstevel@tonic-gate mutex_enter(&so->so_lock); 2059*0Sstevel@tonic-gate if ((so->so_state & (SS_ISCONNECTED|SS_ISCONNECTING)) != 2060*0Sstevel@tonic-gate SS_ISCONNECTING) { 2061*0Sstevel@tonic-gate mutex_exit(&so->so_lock); 2062*0Sstevel@tonic-gate dprintso(so, 1, 2063*0Sstevel@tonic-gate ("T_CONN_CON: state %x\n", so->so_state)); 2064*0Sstevel@tonic-gate freemsg(mp); 2065*0Sstevel@tonic-gate return (NULL); 2066*0Sstevel@tonic-gate } 2067*0Sstevel@tonic-gate 2068*0Sstevel@tonic-gate conn_con = &tpr->conn_con; 2069*0Sstevel@tonic-gate addrlen = conn_con->RES_length; 2070*0Sstevel@tonic-gate /* 2071*0Sstevel@tonic-gate * Allow the address to be of different size than sent down 2072*0Sstevel@tonic-gate * in the T_CONN_REQ as long as it doesn't exceed the maxlen. 2073*0Sstevel@tonic-gate * For AF_UNIX require the identical length. 2074*0Sstevel@tonic-gate */ 2075*0Sstevel@tonic-gate if (so->so_family == AF_UNIX ? 2076*0Sstevel@tonic-gate addrlen != (t_uscalar_t)sizeof (so->so_ux_laddr) : 2077*0Sstevel@tonic-gate addrlen > (t_uscalar_t)so->so_faddr_maxlen) { 2078*0Sstevel@tonic-gate cmn_err(CE_WARN, 2079*0Sstevel@tonic-gate "sockfs: T_conn_con with different " 2080*0Sstevel@tonic-gate "length %u/%d\n", 2081*0Sstevel@tonic-gate addrlen, conn_con->RES_length); 2082*0Sstevel@tonic-gate soisdisconnected(so, EPROTO); 2083*0Sstevel@tonic-gate mutex_exit(&so->so_lock); 2084*0Sstevel@tonic-gate strsetrerror(SOTOV(so), 0, 0, sogetrderr); 2085*0Sstevel@tonic-gate strsetwerror(SOTOV(so), 0, 0, sogetwrerr); 2086*0Sstevel@tonic-gate strseteof(SOTOV(so), 1); 2087*0Sstevel@tonic-gate freemsg(mp); 2088*0Sstevel@tonic-gate /* 2089*0Sstevel@tonic-gate * strseteof takes care of read side wakeups, 2090*0Sstevel@tonic-gate * pollwakeups, and signals. 2091*0Sstevel@tonic-gate */ 2092*0Sstevel@tonic-gate *wakeups = WSLEEP; 2093*0Sstevel@tonic-gate *allmsgsigs = S_OUTPUT; 2094*0Sstevel@tonic-gate *pollwakeups = POLLOUT; 2095*0Sstevel@tonic-gate return (NULL); 2096*0Sstevel@tonic-gate } 2097*0Sstevel@tonic-gate addr = sogetoff(mp, conn_con->RES_offset, addrlen, 1); 2098*0Sstevel@tonic-gate if (addr == NULL) { 2099*0Sstevel@tonic-gate cmn_err(CE_WARN, 2100*0Sstevel@tonic-gate "sockfs: T_conn_con with invalid " 2101*0Sstevel@tonic-gate "addrlen/offset %u/%d\n", 2102*0Sstevel@tonic-gate addrlen, conn_con->RES_offset); 2103*0Sstevel@tonic-gate mutex_exit(&so->so_lock); 2104*0Sstevel@tonic-gate strsetrerror(SOTOV(so), 0, 0, sogetrderr); 2105*0Sstevel@tonic-gate strsetwerror(SOTOV(so), 0, 0, sogetwrerr); 2106*0Sstevel@tonic-gate strseteof(SOTOV(so), 1); 2107*0Sstevel@tonic-gate freemsg(mp); 2108*0Sstevel@tonic-gate /* 2109*0Sstevel@tonic-gate * strseteof takes care of read side wakeups, 2110*0Sstevel@tonic-gate * pollwakeups, and signals. 2111*0Sstevel@tonic-gate */ 2112*0Sstevel@tonic-gate *wakeups = WSLEEP; 2113*0Sstevel@tonic-gate *allmsgsigs = S_OUTPUT; 2114*0Sstevel@tonic-gate *pollwakeups = POLLOUT; 2115*0Sstevel@tonic-gate return (NULL); 2116*0Sstevel@tonic-gate } 2117*0Sstevel@tonic-gate 2118*0Sstevel@tonic-gate /* 2119*0Sstevel@tonic-gate * Save for getpeername. 2120*0Sstevel@tonic-gate */ 2121*0Sstevel@tonic-gate if (so->so_family != AF_UNIX) { 2122*0Sstevel@tonic-gate so->so_faddr_len = (socklen_t)addrlen; 2123*0Sstevel@tonic-gate ASSERT(so->so_faddr_len <= so->so_faddr_maxlen); 2124*0Sstevel@tonic-gate bcopy(addr, so->so_faddr_sa, addrlen); 2125*0Sstevel@tonic-gate so->so_state |= SS_FADDR_VALID; 2126*0Sstevel@tonic-gate } 2127*0Sstevel@tonic-gate 2128*0Sstevel@tonic-gate if (so->so_peercred != NULL) 2129*0Sstevel@tonic-gate crfree(so->so_peercred); 2130*0Sstevel@tonic-gate so->so_peercred = DB_CRED(mp); 2131*0Sstevel@tonic-gate so->so_cpid = DB_CPID(mp); 2132*0Sstevel@tonic-gate if (so->so_peercred != NULL) 2133*0Sstevel@tonic-gate crhold(so->so_peercred); 2134*0Sstevel@tonic-gate 2135*0Sstevel@tonic-gate /* Wakeup anybody sleeping in sowaitconnected */ 2136*0Sstevel@tonic-gate soisconnected(so); 2137*0Sstevel@tonic-gate mutex_exit(&so->so_lock); 2138*0Sstevel@tonic-gate 2139*0Sstevel@tonic-gate /* 2140*0Sstevel@tonic-gate * The socket is now available for sending data. 2141*0Sstevel@tonic-gate */ 2142*0Sstevel@tonic-gate *wakeups = WSLEEP; 2143*0Sstevel@tonic-gate *allmsgsigs = S_OUTPUT; 2144*0Sstevel@tonic-gate *pollwakeups = POLLOUT; 2145*0Sstevel@tonic-gate freemsg(mp); 2146*0Sstevel@tonic-gate return (NULL); 2147*0Sstevel@tonic-gate } 2148*0Sstevel@tonic-gate 2149*0Sstevel@tonic-gate case T_CONN_IND: 2150*0Sstevel@tonic-gate /* 2151*0Sstevel@tonic-gate * Verify the min size and queue the message on 2152*0Sstevel@tonic-gate * the so_conn_ind_head/tail list. 2153*0Sstevel@tonic-gate */ 2154*0Sstevel@tonic-gate if (MBLKL(mp) < sizeof (struct T_conn_ind)) { 2155*0Sstevel@tonic-gate cmn_err(CE_WARN, 2156*0Sstevel@tonic-gate "sockfs: Too short T_CONN_IND. Len = %ld\n", 2157*0Sstevel@tonic-gate (ptrdiff_t)(MBLKL(mp))); 2158*0Sstevel@tonic-gate freemsg(mp); 2159*0Sstevel@tonic-gate return (NULL); 2160*0Sstevel@tonic-gate } 2161*0Sstevel@tonic-gate 2162*0Sstevel@tonic-gate #ifdef C2_AUDIT 2163*0Sstevel@tonic-gate if (audit_active) 2164*0Sstevel@tonic-gate audit_sock(T_CONN_IND, strvp2wq(vp), mp, 0); 2165*0Sstevel@tonic-gate #endif /* C2_AUDIT */ 2166*0Sstevel@tonic-gate if (!(so->so_state & SS_ACCEPTCONN)) { 2167*0Sstevel@tonic-gate cmn_err(CE_WARN, 2168*0Sstevel@tonic-gate "sockfs: T_conn_ind on non-listening socket\n"); 2169*0Sstevel@tonic-gate freemsg(mp); 2170*0Sstevel@tonic-gate return (NULL); 2171*0Sstevel@tonic-gate } 2172*0Sstevel@tonic-gate soqueueconnind(so, mp); 2173*0Sstevel@tonic-gate *allmsgsigs = S_INPUT | S_RDNORM; 2174*0Sstevel@tonic-gate *pollwakeups = POLLIN | POLLRDNORM; 2175*0Sstevel@tonic-gate *wakeups = RSLEEP; 2176*0Sstevel@tonic-gate return (NULL); 2177*0Sstevel@tonic-gate 2178*0Sstevel@tonic-gate case T_ORDREL_IND: 2179*0Sstevel@tonic-gate if (MBLKL(mp) < sizeof (struct T_ordrel_ind)) { 2180*0Sstevel@tonic-gate cmn_err(CE_WARN, 2181*0Sstevel@tonic-gate "sockfs: Too short T_ORDREL_IND. Len = %ld\n", 2182*0Sstevel@tonic-gate (ptrdiff_t)(MBLKL(mp))); 2183*0Sstevel@tonic-gate freemsg(mp); 2184*0Sstevel@tonic-gate return (NULL); 2185*0Sstevel@tonic-gate } 2186*0Sstevel@tonic-gate 2187*0Sstevel@tonic-gate /* 2188*0Sstevel@tonic-gate * Some providers send this when not fully connected. 2189*0Sstevel@tonic-gate * SunLink X.25 needs to retrieve disconnect reason after 2190*0Sstevel@tonic-gate * disconnect for compatibility. It uses T_ORDREL_IND 2191*0Sstevel@tonic-gate * instead of T_DISCON_IND so that it may use the 2192*0Sstevel@tonic-gate * endpoint after a connect failure to retrieve the 2193*0Sstevel@tonic-gate * reason using an ioctl. Thus we explicitly clear 2194*0Sstevel@tonic-gate * SS_ISCONNECTING here for SunLink X.25. 2195*0Sstevel@tonic-gate * This is a needed TPI violation. 2196*0Sstevel@tonic-gate */ 2197*0Sstevel@tonic-gate mutex_enter(&so->so_lock); 2198*0Sstevel@tonic-gate so->so_state &= ~SS_ISCONNECTING; 2199*0Sstevel@tonic-gate socantrcvmore(so); 2200*0Sstevel@tonic-gate mutex_exit(&so->so_lock); 2201*0Sstevel@tonic-gate strseteof(SOTOV(so), 1); 2202*0Sstevel@tonic-gate /* 2203*0Sstevel@tonic-gate * strseteof takes care of read side wakeups, 2204*0Sstevel@tonic-gate * pollwakeups, and signals. 2205*0Sstevel@tonic-gate */ 2206*0Sstevel@tonic-gate freemsg(mp); 2207*0Sstevel@tonic-gate return (NULL); 2208*0Sstevel@tonic-gate 2209*0Sstevel@tonic-gate case T_DISCON_IND: 2210*0Sstevel@tonic-gate if (MBLKL(mp) < sizeof (struct T_discon_ind)) { 2211*0Sstevel@tonic-gate cmn_err(CE_WARN, 2212*0Sstevel@tonic-gate "sockfs: Too short T_DISCON_IND. Len = %ld\n", 2213*0Sstevel@tonic-gate (ptrdiff_t)(MBLKL(mp))); 2214*0Sstevel@tonic-gate freemsg(mp); 2215*0Sstevel@tonic-gate return (NULL); 2216*0Sstevel@tonic-gate } 2217*0Sstevel@tonic-gate if (so->so_state & SS_ACCEPTCONN) { 2218*0Sstevel@tonic-gate /* 2219*0Sstevel@tonic-gate * This is a listener. Look for a queued T_CONN_IND 2220*0Sstevel@tonic-gate * with a matching sequence number and remove it 2221*0Sstevel@tonic-gate * from the list. 2222*0Sstevel@tonic-gate * It is normal to not find the sequence number since 2223*0Sstevel@tonic-gate * the soaccept might have already dequeued it 2224*0Sstevel@tonic-gate * (in which case the T_CONN_RES will fail with 2225*0Sstevel@tonic-gate * TBADSEQ). 2226*0Sstevel@tonic-gate */ 2227*0Sstevel@tonic-gate (void) soflushconnind(so, tpr->discon_ind.SEQ_number); 2228*0Sstevel@tonic-gate freemsg(mp); 2229*0Sstevel@tonic-gate return (0); 2230*0Sstevel@tonic-gate } 2231*0Sstevel@tonic-gate 2232*0Sstevel@tonic-gate /* 2233*0Sstevel@tonic-gate * Not a listener 2234*0Sstevel@tonic-gate * 2235*0Sstevel@tonic-gate * If SS_CANTRCVMORE for AF_UNIX ignore the discon_reason. 2236*0Sstevel@tonic-gate * Such a discon_ind appears when the peer has first done 2237*0Sstevel@tonic-gate * a shutdown() followed by a close() in which case we just 2238*0Sstevel@tonic-gate * want to record socantsendmore. 2239*0Sstevel@tonic-gate * In this case sockfs first receives a T_ORDREL_IND followed 2240*0Sstevel@tonic-gate * by a T_DISCON_IND. 2241*0Sstevel@tonic-gate * Note that for other transports (e.g. TCP) we need to handle 2242*0Sstevel@tonic-gate * the discon_ind in this case since it signals an error. 2243*0Sstevel@tonic-gate */ 2244*0Sstevel@tonic-gate mutex_enter(&so->so_lock); 2245*0Sstevel@tonic-gate if ((so->so_state & SS_CANTRCVMORE) && 2246*0Sstevel@tonic-gate (so->so_family == AF_UNIX)) { 2247*0Sstevel@tonic-gate socantsendmore(so); 2248*0Sstevel@tonic-gate mutex_exit(&so->so_lock); 2249*0Sstevel@tonic-gate strsetwerror(SOTOV(so), 0, 0, sogetwrerr); 2250*0Sstevel@tonic-gate dprintso(so, 1, 2251*0Sstevel@tonic-gate ("T_DISCON_IND: error %d\n", so->so_error)); 2252*0Sstevel@tonic-gate freemsg(mp); 2253*0Sstevel@tonic-gate /* 2254*0Sstevel@tonic-gate * Set these variables for caller to process them. 2255*0Sstevel@tonic-gate * For the else part where T_DISCON_IND is processed, 2256*0Sstevel@tonic-gate * this will be done in the function being called 2257*0Sstevel@tonic-gate * (strsock_discon_ind()) 2258*0Sstevel@tonic-gate */ 2259*0Sstevel@tonic-gate *wakeups = WSLEEP; 2260*0Sstevel@tonic-gate *allmsgsigs = S_OUTPUT; 2261*0Sstevel@tonic-gate *pollwakeups = POLLOUT; 2262*0Sstevel@tonic-gate } else if (so->so_flag & (SOASYNC_UNBIND | SOLOCKED)) { 2263*0Sstevel@tonic-gate /* 2264*0Sstevel@tonic-gate * Deferred processing of T_DISCON_IND 2265*0Sstevel@tonic-gate */ 2266*0Sstevel@tonic-gate so_save_discon_ind(so, mp, strsock_discon_ind); 2267*0Sstevel@tonic-gate mutex_exit(&so->so_lock); 2268*0Sstevel@tonic-gate } else { 2269*0Sstevel@tonic-gate /* 2270*0Sstevel@tonic-gate * Process T_DISCON_IND now 2271*0Sstevel@tonic-gate */ 2272*0Sstevel@tonic-gate (void) strsock_discon_ind(so, mp); 2273*0Sstevel@tonic-gate mutex_exit(&so->so_lock); 2274*0Sstevel@tonic-gate } 2275*0Sstevel@tonic-gate return (NULL); 2276*0Sstevel@tonic-gate 2277*0Sstevel@tonic-gate case T_UDERROR_IND: { 2278*0Sstevel@tonic-gate struct T_uderror_ind *tudi = &tpr->uderror_ind; 2279*0Sstevel@tonic-gate void *addr; 2280*0Sstevel@tonic-gate t_uscalar_t addrlen; 2281*0Sstevel@tonic-gate int error; 2282*0Sstevel@tonic-gate 2283*0Sstevel@tonic-gate dprintso(so, 0, 2284*0Sstevel@tonic-gate ("T_UDERROR_IND: error %d\n", tudi->ERROR_type)); 2285*0Sstevel@tonic-gate 2286*0Sstevel@tonic-gate if (MBLKL(mp) < sizeof (struct T_uderror_ind)) { 2287*0Sstevel@tonic-gate cmn_err(CE_WARN, 2288*0Sstevel@tonic-gate "sockfs: Too short T_UDERROR_IND. Len = %ld\n", 2289*0Sstevel@tonic-gate (ptrdiff_t)(MBLKL(mp))); 2290*0Sstevel@tonic-gate freemsg(mp); 2291*0Sstevel@tonic-gate return (NULL); 2292*0Sstevel@tonic-gate } 2293*0Sstevel@tonic-gate /* Ignore on connection-oriented transports */ 2294*0Sstevel@tonic-gate if (so->so_mode & SM_CONNREQUIRED) { 2295*0Sstevel@tonic-gate freemsg(mp); 2296*0Sstevel@tonic-gate eprintsoline(so, 0); 2297*0Sstevel@tonic-gate cmn_err(CE_WARN, 2298*0Sstevel@tonic-gate "sockfs: T_uderror_ind on connection-oriented " 2299*0Sstevel@tonic-gate "transport\n"); 2300*0Sstevel@tonic-gate return (NULL); 2301*0Sstevel@tonic-gate } 2302*0Sstevel@tonic-gate addrlen = tudi->DEST_length; 2303*0Sstevel@tonic-gate addr = sogetoff(mp, tudi->DEST_offset, addrlen, 1); 2304*0Sstevel@tonic-gate if (addr == NULL) { 2305*0Sstevel@tonic-gate cmn_err(CE_WARN, 2306*0Sstevel@tonic-gate "sockfs: T_uderror_ind with invalid " 2307*0Sstevel@tonic-gate "addrlen/offset %u/%d\n", 2308*0Sstevel@tonic-gate addrlen, tudi->DEST_offset); 2309*0Sstevel@tonic-gate freemsg(mp); 2310*0Sstevel@tonic-gate return (NULL); 2311*0Sstevel@tonic-gate } 2312*0Sstevel@tonic-gate 2313*0Sstevel@tonic-gate /* Verify source address for connected socket. */ 2314*0Sstevel@tonic-gate mutex_enter(&so->so_lock); 2315*0Sstevel@tonic-gate if (so->so_state & SS_ISCONNECTED) { 2316*0Sstevel@tonic-gate void *faddr; 2317*0Sstevel@tonic-gate t_uscalar_t faddr_len; 2318*0Sstevel@tonic-gate boolean_t match = B_FALSE; 2319*0Sstevel@tonic-gate 2320*0Sstevel@tonic-gate switch (so->so_family) { 2321*0Sstevel@tonic-gate case AF_INET: { 2322*0Sstevel@tonic-gate /* Compare just IP address and port */ 2323*0Sstevel@tonic-gate struct sockaddr_in *sin1, *sin2; 2324*0Sstevel@tonic-gate 2325*0Sstevel@tonic-gate sin1 = (struct sockaddr_in *)so->so_faddr_sa; 2326*0Sstevel@tonic-gate sin2 = (struct sockaddr_in *)addr; 2327*0Sstevel@tonic-gate if (addrlen == sizeof (struct sockaddr_in) && 2328*0Sstevel@tonic-gate sin1->sin_port == sin2->sin_port && 2329*0Sstevel@tonic-gate sin1->sin_addr.s_addr == 2330*0Sstevel@tonic-gate sin2->sin_addr.s_addr) 2331*0Sstevel@tonic-gate match = B_TRUE; 2332*0Sstevel@tonic-gate break; 2333*0Sstevel@tonic-gate } 2334*0Sstevel@tonic-gate case AF_INET6: { 2335*0Sstevel@tonic-gate /* Compare just IP address and port. Not flow */ 2336*0Sstevel@tonic-gate struct sockaddr_in6 *sin1, *sin2; 2337*0Sstevel@tonic-gate 2338*0Sstevel@tonic-gate sin1 = (struct sockaddr_in6 *)so->so_faddr_sa; 2339*0Sstevel@tonic-gate sin2 = (struct sockaddr_in6 *)addr; 2340*0Sstevel@tonic-gate if (addrlen == sizeof (struct sockaddr_in6) && 2341*0Sstevel@tonic-gate sin1->sin6_port == sin2->sin6_port && 2342*0Sstevel@tonic-gate IN6_ARE_ADDR_EQUAL(&sin1->sin6_addr, 2343*0Sstevel@tonic-gate &sin2->sin6_addr)) 2344*0Sstevel@tonic-gate match = B_TRUE; 2345*0Sstevel@tonic-gate break; 2346*0Sstevel@tonic-gate } 2347*0Sstevel@tonic-gate case AF_UNIX: 2348*0Sstevel@tonic-gate faddr = &so->so_ux_faddr; 2349*0Sstevel@tonic-gate faddr_len = 2350*0Sstevel@tonic-gate (t_uscalar_t)sizeof (so->so_ux_faddr); 2351*0Sstevel@tonic-gate if (faddr_len == addrlen && 2352*0Sstevel@tonic-gate bcmp(addr, faddr, addrlen) == 0) 2353*0Sstevel@tonic-gate match = B_TRUE; 2354*0Sstevel@tonic-gate break; 2355*0Sstevel@tonic-gate default: 2356*0Sstevel@tonic-gate faddr = so->so_faddr_sa; 2357*0Sstevel@tonic-gate faddr_len = (t_uscalar_t)so->so_faddr_len; 2358*0Sstevel@tonic-gate if (faddr_len == addrlen && 2359*0Sstevel@tonic-gate bcmp(addr, faddr, addrlen) == 0) 2360*0Sstevel@tonic-gate match = B_TRUE; 2361*0Sstevel@tonic-gate break; 2362*0Sstevel@tonic-gate } 2363*0Sstevel@tonic-gate 2364*0Sstevel@tonic-gate if (!match) { 2365*0Sstevel@tonic-gate #ifdef DEBUG 2366*0Sstevel@tonic-gate dprintso(so, 0, 2367*0Sstevel@tonic-gate ("sockfs: T_UDERR_IND mismatch: %s - ", 2368*0Sstevel@tonic-gate pr_addr(so->so_family, 2369*0Sstevel@tonic-gate (struct sockaddr *)addr, 2370*0Sstevel@tonic-gate addrlen))); 2371*0Sstevel@tonic-gate dprintso(so, 0, ("%s\n", 2372*0Sstevel@tonic-gate pr_addr(so->so_family, so->so_faddr_sa, 2373*0Sstevel@tonic-gate so->so_faddr_len))); 2374*0Sstevel@tonic-gate #endif /* DEBUG */ 2375*0Sstevel@tonic-gate mutex_exit(&so->so_lock); 2376*0Sstevel@tonic-gate freemsg(mp); 2377*0Sstevel@tonic-gate return (NULL); 2378*0Sstevel@tonic-gate } 2379*0Sstevel@tonic-gate /* 2380*0Sstevel@tonic-gate * Make the write error nonpersistent. If the error 2381*0Sstevel@tonic-gate * is zero we use ECONNRESET. 2382*0Sstevel@tonic-gate * This assumes that the name space for ERROR_type 2383*0Sstevel@tonic-gate * is the errno name space. 2384*0Sstevel@tonic-gate */ 2385*0Sstevel@tonic-gate if (tudi->ERROR_type != 0) 2386*0Sstevel@tonic-gate error = tudi->ERROR_type; 2387*0Sstevel@tonic-gate else 2388*0Sstevel@tonic-gate error = ECONNRESET; 2389*0Sstevel@tonic-gate 2390*0Sstevel@tonic-gate soseterror(so, error); 2391*0Sstevel@tonic-gate mutex_exit(&so->so_lock); 2392*0Sstevel@tonic-gate strsetrerror(SOTOV(so), 0, 0, sogetrderr); 2393*0Sstevel@tonic-gate strsetwerror(SOTOV(so), 0, 0, sogetwrerr); 2394*0Sstevel@tonic-gate *wakeups = RSLEEP | WSLEEP; 2395*0Sstevel@tonic-gate *allmsgsigs = S_INPUT | S_RDNORM | S_OUTPUT; 2396*0Sstevel@tonic-gate *pollwakeups = POLLIN | POLLRDNORM | POLLOUT; 2397*0Sstevel@tonic-gate freemsg(mp); 2398*0Sstevel@tonic-gate return (NULL); 2399*0Sstevel@tonic-gate } 2400*0Sstevel@tonic-gate /* 2401*0Sstevel@tonic-gate * If the application asked for delayed errors 2402*0Sstevel@tonic-gate * record the T_UDERROR_IND so_eaddr_mp and the reason in 2403*0Sstevel@tonic-gate * so_delayed_error for delayed error posting. If the reason 2404*0Sstevel@tonic-gate * is zero use ECONNRESET. 2405*0Sstevel@tonic-gate * Note that delayed error indications do not make sense for 2406*0Sstevel@tonic-gate * AF_UNIX sockets since sendto checks that the destination 2407*0Sstevel@tonic-gate * address is valid at the time of the sendto. 2408*0Sstevel@tonic-gate */ 2409*0Sstevel@tonic-gate if (!(so->so_options & SO_DGRAM_ERRIND)) { 2410*0Sstevel@tonic-gate mutex_exit(&so->so_lock); 2411*0Sstevel@tonic-gate freemsg(mp); 2412*0Sstevel@tonic-gate return (NULL); 2413*0Sstevel@tonic-gate } 2414*0Sstevel@tonic-gate if (so->so_eaddr_mp != NULL) 2415*0Sstevel@tonic-gate freemsg(so->so_eaddr_mp); 2416*0Sstevel@tonic-gate 2417*0Sstevel@tonic-gate so->so_eaddr_mp = mp; 2418*0Sstevel@tonic-gate if (tudi->ERROR_type != 0) 2419*0Sstevel@tonic-gate error = tudi->ERROR_type; 2420*0Sstevel@tonic-gate else 2421*0Sstevel@tonic-gate error = ECONNRESET; 2422*0Sstevel@tonic-gate so->so_delayed_error = (ushort_t)error; 2423*0Sstevel@tonic-gate mutex_exit(&so->so_lock); 2424*0Sstevel@tonic-gate return (NULL); 2425*0Sstevel@tonic-gate } 2426*0Sstevel@tonic-gate 2427*0Sstevel@tonic-gate case T_ERROR_ACK: 2428*0Sstevel@tonic-gate dprintso(so, 0, 2429*0Sstevel@tonic-gate ("strsock_proto: T_ERROR_ACK for %d, error %d/%d\n", 2430*0Sstevel@tonic-gate tpr->error_ack.ERROR_prim, 2431*0Sstevel@tonic-gate tpr->error_ack.TLI_error, 2432*0Sstevel@tonic-gate tpr->error_ack.UNIX_error)); 2433*0Sstevel@tonic-gate 2434*0Sstevel@tonic-gate if (MBLKL(mp) < sizeof (struct T_error_ack)) { 2435*0Sstevel@tonic-gate cmn_err(CE_WARN, 2436*0Sstevel@tonic-gate "sockfs: Too short T_ERROR_ACK. Len = %ld\n", 2437*0Sstevel@tonic-gate (ptrdiff_t)(MBLKL(mp))); 2438*0Sstevel@tonic-gate freemsg(mp); 2439*0Sstevel@tonic-gate return (NULL); 2440*0Sstevel@tonic-gate } 2441*0Sstevel@tonic-gate /* 2442*0Sstevel@tonic-gate * Check if we were waiting for the async message 2443*0Sstevel@tonic-gate */ 2444*0Sstevel@tonic-gate mutex_enter(&so->so_lock); 2445*0Sstevel@tonic-gate if ((so->so_flag & SOASYNC_UNBIND) && 2446*0Sstevel@tonic-gate tpr->error_ack.ERROR_prim == T_UNBIND_REQ) { 2447*0Sstevel@tonic-gate so_unlock_single(so, SOASYNC_UNBIND); 2448*0Sstevel@tonic-gate mutex_exit(&so->so_lock); 2449*0Sstevel@tonic-gate freemsg(mp); 2450*0Sstevel@tonic-gate return (NULL); 2451*0Sstevel@tonic-gate } 2452*0Sstevel@tonic-gate mutex_exit(&so->so_lock); 2453*0Sstevel@tonic-gate soqueueack(so, mp); 2454*0Sstevel@tonic-gate return (NULL); 2455*0Sstevel@tonic-gate 2456*0Sstevel@tonic-gate case T_OK_ACK: 2457*0Sstevel@tonic-gate if (MBLKL(mp) < sizeof (struct T_ok_ack)) { 2458*0Sstevel@tonic-gate cmn_err(CE_WARN, 2459*0Sstevel@tonic-gate "sockfs: Too short T_OK_ACK. Len = %ld\n", 2460*0Sstevel@tonic-gate (ptrdiff_t)(MBLKL(mp))); 2461*0Sstevel@tonic-gate freemsg(mp); 2462*0Sstevel@tonic-gate return (NULL); 2463*0Sstevel@tonic-gate } 2464*0Sstevel@tonic-gate /* 2465*0Sstevel@tonic-gate * Check if we were waiting for the async message 2466*0Sstevel@tonic-gate */ 2467*0Sstevel@tonic-gate mutex_enter(&so->so_lock); 2468*0Sstevel@tonic-gate if ((so->so_flag & SOASYNC_UNBIND) && 2469*0Sstevel@tonic-gate tpr->ok_ack.CORRECT_prim == T_UNBIND_REQ) { 2470*0Sstevel@tonic-gate dprintso(so, 1, 2471*0Sstevel@tonic-gate ("strsock_proto: T_OK_ACK async unbind\n")); 2472*0Sstevel@tonic-gate so_unlock_single(so, SOASYNC_UNBIND); 2473*0Sstevel@tonic-gate mutex_exit(&so->so_lock); 2474*0Sstevel@tonic-gate freemsg(mp); 2475*0Sstevel@tonic-gate return (NULL); 2476*0Sstevel@tonic-gate } 2477*0Sstevel@tonic-gate mutex_exit(&so->so_lock); 2478*0Sstevel@tonic-gate soqueueack(so, mp); 2479*0Sstevel@tonic-gate return (NULL); 2480*0Sstevel@tonic-gate 2481*0Sstevel@tonic-gate case T_INFO_ACK: 2482*0Sstevel@tonic-gate if (MBLKL(mp) < sizeof (struct T_info_ack)) { 2483*0Sstevel@tonic-gate cmn_err(CE_WARN, 2484*0Sstevel@tonic-gate "sockfs: Too short T_INFO_ACK. Len = %ld\n", 2485*0Sstevel@tonic-gate (ptrdiff_t)(MBLKL(mp))); 2486*0Sstevel@tonic-gate freemsg(mp); 2487*0Sstevel@tonic-gate return (NULL); 2488*0Sstevel@tonic-gate } 2489*0Sstevel@tonic-gate soqueueack(so, mp); 2490*0Sstevel@tonic-gate return (NULL); 2491*0Sstevel@tonic-gate 2492*0Sstevel@tonic-gate case T_CAPABILITY_ACK: 2493*0Sstevel@tonic-gate /* 2494*0Sstevel@tonic-gate * A T_capability_ack need only be large enough to hold 2495*0Sstevel@tonic-gate * the PRIM_type and CAP_bits1 fields; checking for anything 2496*0Sstevel@tonic-gate * larger might reject a correct response from an older 2497*0Sstevel@tonic-gate * provider. 2498*0Sstevel@tonic-gate */ 2499*0Sstevel@tonic-gate if (MBLKL(mp) < 2 * sizeof (t_uscalar_t)) { 2500*0Sstevel@tonic-gate cmn_err(CE_WARN, 2501*0Sstevel@tonic-gate "sockfs: Too short T_CAPABILITY_ACK. Len = %ld\n", 2502*0Sstevel@tonic-gate (ptrdiff_t)(MBLKL(mp))); 2503*0Sstevel@tonic-gate freemsg(mp); 2504*0Sstevel@tonic-gate return (NULL); 2505*0Sstevel@tonic-gate } 2506*0Sstevel@tonic-gate soqueueack(so, mp); 2507*0Sstevel@tonic-gate return (NULL); 2508*0Sstevel@tonic-gate 2509*0Sstevel@tonic-gate case T_BIND_ACK: 2510*0Sstevel@tonic-gate if (MBLKL(mp) < sizeof (struct T_bind_ack)) { 2511*0Sstevel@tonic-gate cmn_err(CE_WARN, 2512*0Sstevel@tonic-gate "sockfs: Too short T_BIND_ACK. Len = %ld\n", 2513*0Sstevel@tonic-gate (ptrdiff_t)(MBLKL(mp))); 2514*0Sstevel@tonic-gate freemsg(mp); 2515*0Sstevel@tonic-gate return (NULL); 2516*0Sstevel@tonic-gate } 2517*0Sstevel@tonic-gate soqueueack(so, mp); 2518*0Sstevel@tonic-gate return (NULL); 2519*0Sstevel@tonic-gate 2520*0Sstevel@tonic-gate case T_OPTMGMT_ACK: 2521*0Sstevel@tonic-gate if (MBLKL(mp) < sizeof (struct T_optmgmt_ack)) { 2522*0Sstevel@tonic-gate cmn_err(CE_WARN, 2523*0Sstevel@tonic-gate "sockfs: Too short T_OPTMGMT_ACK. Len = %ld\n", 2524*0Sstevel@tonic-gate (ptrdiff_t)(MBLKL(mp))); 2525*0Sstevel@tonic-gate freemsg(mp); 2526*0Sstevel@tonic-gate return (NULL); 2527*0Sstevel@tonic-gate } 2528*0Sstevel@tonic-gate soqueueack(so, mp); 2529*0Sstevel@tonic-gate return (NULL); 2530*0Sstevel@tonic-gate default: 2531*0Sstevel@tonic-gate #ifdef DEBUG 2532*0Sstevel@tonic-gate cmn_err(CE_WARN, 2533*0Sstevel@tonic-gate "sockfs: unknown TPI primitive %d received\n", 2534*0Sstevel@tonic-gate tpr->type); 2535*0Sstevel@tonic-gate #endif /* DEBUG */ 2536*0Sstevel@tonic-gate freemsg(mp); 2537*0Sstevel@tonic-gate return (NULL); 2538*0Sstevel@tonic-gate } 2539*0Sstevel@tonic-gate } 2540*0Sstevel@tonic-gate 2541*0Sstevel@tonic-gate /* 2542*0Sstevel@tonic-gate * This routine is registered with the stream head to receive other 2543*0Sstevel@tonic-gate * (non-data, and non-proto) messages. 2544*0Sstevel@tonic-gate * 2545*0Sstevel@tonic-gate * Returns NULL if the message was consumed. 2546*0Sstevel@tonic-gate * Returns an mblk to make that mblk be processed by the stream head. 2547*0Sstevel@tonic-gate * 2548*0Sstevel@tonic-gate * Sets the return parameters (*wakeups, *firstmsgsigs, *allmsgsigs, and 2549*0Sstevel@tonic-gate * *pollwakeups) for the stream head to take action on. 2550*0Sstevel@tonic-gate */ 2551*0Sstevel@tonic-gate static mblk_t * 2552*0Sstevel@tonic-gate strsock_misc(vnode_t *vp, mblk_t *mp, 2553*0Sstevel@tonic-gate strwakeup_t *wakeups, strsigset_t *firstmsgsigs, 2554*0Sstevel@tonic-gate strsigset_t *allmsgsigs, strpollset_t *pollwakeups) 2555*0Sstevel@tonic-gate { 2556*0Sstevel@tonic-gate struct sonode *so; 2557*0Sstevel@tonic-gate 2558*0Sstevel@tonic-gate so = VTOSO(vp); 2559*0Sstevel@tonic-gate 2560*0Sstevel@tonic-gate dprintso(so, 1, ("strsock_misc(%p, %p, 0x%x)\n", 2561*0Sstevel@tonic-gate vp, mp, DB_TYPE(mp))); 2562*0Sstevel@tonic-gate 2563*0Sstevel@tonic-gate /* Set default return values */ 2564*0Sstevel@tonic-gate *wakeups = *allmsgsigs = *firstmsgsigs = *pollwakeups = 0; 2565*0Sstevel@tonic-gate 2566*0Sstevel@tonic-gate switch (DB_TYPE(mp)) { 2567*0Sstevel@tonic-gate case M_PCSIG: 2568*0Sstevel@tonic-gate /* 2569*0Sstevel@tonic-gate * This assumes that an M_PCSIG for the urgent data arrives 2570*0Sstevel@tonic-gate * before the corresponding T_EXDATA_IND. 2571*0Sstevel@tonic-gate * 2572*0Sstevel@tonic-gate * Note: Just like in SunOS 4.X and 4.4BSD a poll will be 2573*0Sstevel@tonic-gate * awoken before the urgent data shows up. 2574*0Sstevel@tonic-gate * For OOBINLINE this can result in select returning 2575*0Sstevel@tonic-gate * only exceptions as opposed to except|read. 2576*0Sstevel@tonic-gate */ 2577*0Sstevel@tonic-gate if (*mp->b_rptr == SIGURG) { 2578*0Sstevel@tonic-gate mutex_enter(&so->so_lock); 2579*0Sstevel@tonic-gate dprintso(so, 1, 2580*0Sstevel@tonic-gate ("SIGURG(%p): counts %d/%d state %s\n", 2581*0Sstevel@tonic-gate vp, so->so_oobsigcnt, 2582*0Sstevel@tonic-gate so->so_oobcnt, 2583*0Sstevel@tonic-gate pr_state(so->so_state, so->so_mode))); 2584*0Sstevel@tonic-gate so_oob_sig(so, 1, allmsgsigs, pollwakeups); 2585*0Sstevel@tonic-gate dprintso(so, 1, 2586*0Sstevel@tonic-gate ("after SIGURG(%p): counts %d/%d " 2587*0Sstevel@tonic-gate " poll 0x%x sig 0x%x state %s\n", 2588*0Sstevel@tonic-gate vp, so->so_oobsigcnt, 2589*0Sstevel@tonic-gate so->so_oobcnt, *pollwakeups, *allmsgsigs, 2590*0Sstevel@tonic-gate pr_state(so->so_state, so->so_mode))); 2591*0Sstevel@tonic-gate mutex_exit(&so->so_lock); 2592*0Sstevel@tonic-gate } 2593*0Sstevel@tonic-gate freemsg(mp); 2594*0Sstevel@tonic-gate return (NULL); 2595*0Sstevel@tonic-gate 2596*0Sstevel@tonic-gate case M_SIG: 2597*0Sstevel@tonic-gate case M_HANGUP: 2598*0Sstevel@tonic-gate case M_UNHANGUP: 2599*0Sstevel@tonic-gate case M_ERROR: 2600*0Sstevel@tonic-gate /* M_ERRORs etc are ignored */ 2601*0Sstevel@tonic-gate freemsg(mp); 2602*0Sstevel@tonic-gate return (NULL); 2603*0Sstevel@tonic-gate 2604*0Sstevel@tonic-gate case M_FLUSH: 2605*0Sstevel@tonic-gate /* 2606*0Sstevel@tonic-gate * Do not flush read queue. If the M_FLUSH 2607*0Sstevel@tonic-gate * arrives because of an impending T_discon_ind 2608*0Sstevel@tonic-gate * we still have to keep any queued data - this is part of 2609*0Sstevel@tonic-gate * socket semantics. 2610*0Sstevel@tonic-gate */ 2611*0Sstevel@tonic-gate if (*mp->b_rptr & FLUSHW) { 2612*0Sstevel@tonic-gate *mp->b_rptr &= ~FLUSHR; 2613*0Sstevel@tonic-gate return (mp); 2614*0Sstevel@tonic-gate } 2615*0Sstevel@tonic-gate freemsg(mp); 2616*0Sstevel@tonic-gate return (NULL); 2617*0Sstevel@tonic-gate 2618*0Sstevel@tonic-gate default: 2619*0Sstevel@tonic-gate return (mp); 2620*0Sstevel@tonic-gate } 2621*0Sstevel@tonic-gate } 2622*0Sstevel@tonic-gate 2623*0Sstevel@tonic-gate 2624*0Sstevel@tonic-gate /* Register to receive signals for certain events */ 2625*0Sstevel@tonic-gate int 2626*0Sstevel@tonic-gate so_set_asyncsigs(vnode_t *vp, pid_t pgrp, int events, int mode, cred_t *cr) 2627*0Sstevel@tonic-gate { 2628*0Sstevel@tonic-gate struct strsigset ss; 2629*0Sstevel@tonic-gate int32_t rval; 2630*0Sstevel@tonic-gate 2631*0Sstevel@tonic-gate /* 2632*0Sstevel@tonic-gate * Note that SOLOCKED will be set except for the call from soaccept(). 2633*0Sstevel@tonic-gate */ 2634*0Sstevel@tonic-gate ASSERT(!mutex_owned(&VTOSO(vp)->so_lock)); 2635*0Sstevel@tonic-gate ss.ss_pid = pgrp; 2636*0Sstevel@tonic-gate ss.ss_events = events; 2637*0Sstevel@tonic-gate return (strioctl(vp, I_ESETSIG, (intptr_t)&ss, mode, K_TO_K, cr, 2638*0Sstevel@tonic-gate &rval)); 2639*0Sstevel@tonic-gate } 2640*0Sstevel@tonic-gate 2641*0Sstevel@tonic-gate 2642*0Sstevel@tonic-gate /* Register for events matching the SS_ASYNC flag */ 2643*0Sstevel@tonic-gate int 2644*0Sstevel@tonic-gate so_set_events(struct sonode *so, vnode_t *vp, cred_t *cr) 2645*0Sstevel@tonic-gate { 2646*0Sstevel@tonic-gate int events = so->so_state & SS_ASYNC ? 2647*0Sstevel@tonic-gate S_RDBAND | S_BANDURG | S_RDNORM | S_OUTPUT : 2648*0Sstevel@tonic-gate S_RDBAND | S_BANDURG; 2649*0Sstevel@tonic-gate 2650*0Sstevel@tonic-gate return (so_set_asyncsigs(vp, so->so_pgrp, events, 0, cr)); 2651*0Sstevel@tonic-gate } 2652*0Sstevel@tonic-gate 2653*0Sstevel@tonic-gate 2654*0Sstevel@tonic-gate /* Change the SS_ASYNC flag, and update signal delivery if needed */ 2655*0Sstevel@tonic-gate int 2656*0Sstevel@tonic-gate so_flip_async(struct sonode *so, vnode_t *vp, int mode, cred_t *cr) 2657*0Sstevel@tonic-gate { 2658*0Sstevel@tonic-gate ASSERT(mutex_owned(&so->so_lock)); 2659*0Sstevel@tonic-gate if (so->so_pgrp != 0) { 2660*0Sstevel@tonic-gate int error; 2661*0Sstevel@tonic-gate int events = so->so_state & SS_ASYNC ? /* Old flag */ 2662*0Sstevel@tonic-gate S_RDBAND | S_BANDURG : /* New sigs */ 2663*0Sstevel@tonic-gate S_RDBAND | S_BANDURG | S_RDNORM | S_OUTPUT; 2664*0Sstevel@tonic-gate 2665*0Sstevel@tonic-gate so_lock_single(so); 2666*0Sstevel@tonic-gate mutex_exit(&so->so_lock); 2667*0Sstevel@tonic-gate 2668*0Sstevel@tonic-gate error = so_set_asyncsigs(vp, so->so_pgrp, events, mode, cr); 2669*0Sstevel@tonic-gate 2670*0Sstevel@tonic-gate mutex_enter(&so->so_lock); 2671*0Sstevel@tonic-gate so_unlock_single(so, SOLOCKED); 2672*0Sstevel@tonic-gate if (error) 2673*0Sstevel@tonic-gate return (error); 2674*0Sstevel@tonic-gate } 2675*0Sstevel@tonic-gate so->so_state ^= SS_ASYNC; 2676*0Sstevel@tonic-gate return (0); 2677*0Sstevel@tonic-gate } 2678*0Sstevel@tonic-gate 2679*0Sstevel@tonic-gate /* 2680*0Sstevel@tonic-gate * Set new pid/pgrp for SIGPOLL (or SIGIO for FIOASYNC mode), replacing 2681*0Sstevel@tonic-gate * any existing one. If passed zero, just clear the existing one. 2682*0Sstevel@tonic-gate */ 2683*0Sstevel@tonic-gate int 2684*0Sstevel@tonic-gate so_set_siggrp(struct sonode *so, vnode_t *vp, pid_t pgrp, int mode, cred_t *cr) 2685*0Sstevel@tonic-gate { 2686*0Sstevel@tonic-gate int events = so->so_state & SS_ASYNC ? 2687*0Sstevel@tonic-gate S_RDBAND | S_BANDURG | S_RDNORM | S_OUTPUT : 2688*0Sstevel@tonic-gate S_RDBAND | S_BANDURG; 2689*0Sstevel@tonic-gate int error; 2690*0Sstevel@tonic-gate 2691*0Sstevel@tonic-gate ASSERT(mutex_owned(&so->so_lock)); 2692*0Sstevel@tonic-gate 2693*0Sstevel@tonic-gate /* 2694*0Sstevel@tonic-gate * Change socket process (group). 2695*0Sstevel@tonic-gate * 2696*0Sstevel@tonic-gate * strioctl (via so_set_asyncsigs) will perform permission check and 2697*0Sstevel@tonic-gate * also keep a PID_HOLD to prevent the pid from being reused. 2698*0Sstevel@tonic-gate */ 2699*0Sstevel@tonic-gate so_lock_single(so); 2700*0Sstevel@tonic-gate mutex_exit(&so->so_lock); 2701*0Sstevel@tonic-gate 2702*0Sstevel@tonic-gate if (pgrp != 0) { 2703*0Sstevel@tonic-gate dprintso(so, 1, ("setown: adding pgrp %d ev 0x%x\n", 2704*0Sstevel@tonic-gate pgrp, events)); 2705*0Sstevel@tonic-gate error = so_set_asyncsigs(vp, pgrp, events, mode, cr); 2706*0Sstevel@tonic-gate if (error != 0) { 2707*0Sstevel@tonic-gate eprintsoline(so, error); 2708*0Sstevel@tonic-gate goto bad; 2709*0Sstevel@tonic-gate } 2710*0Sstevel@tonic-gate } 2711*0Sstevel@tonic-gate /* Remove the previously registered process/group */ 2712*0Sstevel@tonic-gate if (so->so_pgrp != 0) { 2713*0Sstevel@tonic-gate dprintso(so, 1, ("setown: removing pgrp %d\n", so->so_pgrp)); 2714*0Sstevel@tonic-gate error = so_set_asyncsigs(vp, so->so_pgrp, 0, mode, cr); 2715*0Sstevel@tonic-gate if (error != 0) { 2716*0Sstevel@tonic-gate eprintsoline(so, error); 2717*0Sstevel@tonic-gate error = 0; 2718*0Sstevel@tonic-gate } 2719*0Sstevel@tonic-gate } 2720*0Sstevel@tonic-gate mutex_enter(&so->so_lock); 2721*0Sstevel@tonic-gate so_unlock_single(so, SOLOCKED); 2722*0Sstevel@tonic-gate so->so_pgrp = pgrp; 2723*0Sstevel@tonic-gate return (0); 2724*0Sstevel@tonic-gate bad: 2725*0Sstevel@tonic-gate mutex_enter(&so->so_lock); 2726*0Sstevel@tonic-gate so_unlock_single(so, SOLOCKED); 2727*0Sstevel@tonic-gate return (error); 2728*0Sstevel@tonic-gate } 2729*0Sstevel@tonic-gate 2730*0Sstevel@tonic-gate 2731*0Sstevel@tonic-gate 2732*0Sstevel@tonic-gate /* 2733*0Sstevel@tonic-gate * Translate a TLI(/XTI) error into a system error as best we can. 2734*0Sstevel@tonic-gate */ 2735*0Sstevel@tonic-gate static const int tli_errs[] = { 2736*0Sstevel@tonic-gate 0, /* no error */ 2737*0Sstevel@tonic-gate EADDRNOTAVAIL, /* TBADADDR */ 2738*0Sstevel@tonic-gate ENOPROTOOPT, /* TBADOPT */ 2739*0Sstevel@tonic-gate EACCES, /* TACCES */ 2740*0Sstevel@tonic-gate EBADF, /* TBADF */ 2741*0Sstevel@tonic-gate EADDRNOTAVAIL, /* TNOADDR */ 2742*0Sstevel@tonic-gate EPROTO, /* TOUTSTATE */ 2743*0Sstevel@tonic-gate ECONNABORTED, /* TBADSEQ */ 2744*0Sstevel@tonic-gate 0, /* TSYSERR - will never get */ 2745*0Sstevel@tonic-gate EPROTO, /* TLOOK - should never be sent by transport */ 2746*0Sstevel@tonic-gate EMSGSIZE, /* TBADDATA */ 2747*0Sstevel@tonic-gate EMSGSIZE, /* TBUFOVFLW */ 2748*0Sstevel@tonic-gate EPROTO, /* TFLOW */ 2749*0Sstevel@tonic-gate EWOULDBLOCK, /* TNODATA */ 2750*0Sstevel@tonic-gate EPROTO, /* TNODIS */ 2751*0Sstevel@tonic-gate EPROTO, /* TNOUDERR */ 2752*0Sstevel@tonic-gate EINVAL, /* TBADFLAG */ 2753*0Sstevel@tonic-gate EPROTO, /* TNOREL */ 2754*0Sstevel@tonic-gate EOPNOTSUPP, /* TNOTSUPPORT */ 2755*0Sstevel@tonic-gate EPROTO, /* TSTATECHNG */ 2756*0Sstevel@tonic-gate /* following represent error namespace expansion with XTI */ 2757*0Sstevel@tonic-gate EPROTO, /* TNOSTRUCTYPE - never sent by transport */ 2758*0Sstevel@tonic-gate EPROTO, /* TBADNAME - never sent by transport */ 2759*0Sstevel@tonic-gate EPROTO, /* TBADQLEN - never sent by transport */ 2760*0Sstevel@tonic-gate EADDRINUSE, /* TADDRBUSY */ 2761*0Sstevel@tonic-gate EBADF, /* TINDOUT */ 2762*0Sstevel@tonic-gate EBADF, /* TPROVMISMATCH */ 2763*0Sstevel@tonic-gate EBADF, /* TRESQLEN */ 2764*0Sstevel@tonic-gate EBADF, /* TRESADDR */ 2765*0Sstevel@tonic-gate EPROTO, /* TQFULL - never sent by transport */ 2766*0Sstevel@tonic-gate EPROTO, /* TPROTO */ 2767*0Sstevel@tonic-gate }; 2768*0Sstevel@tonic-gate 2769*0Sstevel@tonic-gate static int 2770*0Sstevel@tonic-gate tlitosyserr(int terr) 2771*0Sstevel@tonic-gate { 2772*0Sstevel@tonic-gate ASSERT(terr != TSYSERR); 2773*0Sstevel@tonic-gate if (terr >= (sizeof (tli_errs) / sizeof (tli_errs[0]))) 2774*0Sstevel@tonic-gate return (EPROTO); 2775*0Sstevel@tonic-gate else 2776*0Sstevel@tonic-gate return (tli_errs[terr]); 2777*0Sstevel@tonic-gate } 2778