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