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  1548   rshoaib /*
     23  8477       Rao  * 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/t_lock.h>
     29     0    stevel #include <sys/param.h>
     30     0    stevel #include <sys/systm.h>
     31     0    stevel #include <sys/buf.h>
     32     0    stevel #include <sys/conf.h>
     33     0    stevel #include <sys/cred.h>
     34     0    stevel #include <sys/kmem.h>
     35  8348      Eric #include <sys/kmem_impl.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/open.h>
     44     0    stevel #include <sys/user.h>
     45     0    stevel #include <sys/termios.h>
     46     0    stevel #include <sys/stream.h>
     47     0    stevel #include <sys/strsubr.h>
     48     0    stevel #include <sys/strsun.h>
     49  8348      Eric #include <sys/suntpi.h>
     50     0    stevel #include <sys/ddi.h>
     51     0    stevel #include <sys/esunddi.h>
     52     0    stevel #include <sys/flock.h>
     53     0    stevel #include <sys/modctl.h>
     54     0    stevel #include <sys/vtrace.h>
     55     0    stevel #include <sys/cmn_err.h>
     56     0    stevel #include <sys/pathname.h>
     57     0    stevel 
     58     0    stevel #include <sys/socket.h>
     59     0    stevel #include <sys/socketvar.h>
     60   741  masputra #include <sys/sockio.h>
     61     0    stevel #include <netinet/in.h>
     62     0    stevel #include <sys/un.h>
     63     0    stevel #include <sys/strsun.h>
     64     0    stevel 
     65     0    stevel #include <sys/tiuser.h>
     66     0    stevel #define	_SUN_TPI_VERSION	2
     67     0    stevel #include <sys/tihdr.h>
     68     0    stevel #include <sys/timod.h>		/* TI_GETMYNAME, TI_GETPEERNAME */
     69     0    stevel 
     70     0    stevel #include <c2/audit.h>
     71     0    stevel 
     72     0    stevel #include <inet/common.h>
     73     0    stevel #include <inet/ip.h>
     74     0    stevel #include <inet/ip6.h>
     75     0    stevel #include <inet/tcp.h>
     76   741  masputra #include <inet/udp_impl.h>
     77     0    stevel 
     78  1974    brutus #include <sys/zone.h>
     79  1974    brutus 
     80     0    stevel #include <fs/sockfs/nl7c.h>
     81  1974    brutus #include <fs/sockfs/nl7curi.h>
     82     0    stevel 
     83   898      kais #include <inet/kssl/ksslapi.h>
     84  8348      Eric 
     85  8348      Eric #include <fs/sockfs/sockcommon.h>
     86  8348      Eric #include <fs/sockfs/socktpi.h>
     87  8348      Eric #include <fs/sockfs/socktpi_impl.h>
     88   898      kais 
     89     0    stevel /*
     90     0    stevel  * Possible failures when memory can't be allocated. The documented behavior:
     91     0    stevel  *
     92     0    stevel  * 		5.5:			4.X:		XNET:
     93     0    stevel  * accept:	ENOMEM/ENOSR/EINTR	- (EINTR)	ENOMEM/ENOBUFS/ENOSR/
     94     0    stevel  *							EINTR
     95     0    stevel  *	(4.X does not document EINTR but returns it)
     96     0    stevel  * bind:	ENOSR			-		ENOBUFS/ENOSR
     97     0    stevel  * connect: 	EINTR			EINTR		ENOBUFS/ENOSR/EINTR
     98     0    stevel  * getpeername:	ENOMEM/ENOSR		ENOBUFS (-)	ENOBUFS/ENOSR
     99     0    stevel  * getsockname:	ENOMEM/ENOSR		ENOBUFS (-)	ENOBUFS/ENOSR
    100     0    stevel  *	(4.X getpeername and getsockname do not fail in practice)
    101     0    stevel  * getsockopt:	ENOMEM/ENOSR		-		ENOBUFS/ENOSR
    102     0    stevel  * listen:	-			-		ENOBUFS
    103     0    stevel  * recv:	ENOMEM/ENOSR/EINTR	EINTR		ENOBUFS/ENOMEM/ENOSR/
    104     0    stevel  *							EINTR
    105     0    stevel  * send:	ENOMEM/ENOSR/EINTR	ENOBUFS/EINTR	ENOBUFS/ENOMEM/ENOSR/
    106     0    stevel  *							EINTR
    107     0    stevel  * setsockopt:	ENOMEM/ENOSR		-		ENOBUFS/ENOMEM/ENOSR
    108     0    stevel  * shutdown:	ENOMEM/ENOSR		-		ENOBUFS/ENOSR
    109     0    stevel  * socket:	ENOMEM/ENOSR		ENOBUFS		ENOBUFS/ENOMEM/ENOSR
    110     0    stevel  * socketpair:	ENOMEM/ENOSR		-		ENOBUFS/ENOMEM/ENOSR
    111     0    stevel  *
    112     0    stevel  * Resolution. When allocation fails:
    113     0    stevel  *	recv: return EINTR
    114     0    stevel  *	send: return EINTR
    115     0    stevel  *	connect, accept: EINTR
    116     0    stevel  *	bind, listen, shutdown (unbind, unix_close, disconnect): sleep
    117     0    stevel  *	socket, socketpair: ENOBUFS
    118     0    stevel  *	getpeername, getsockname: sleep
    119     0    stevel  *	getsockopt, setsockopt: sleep
    120     0    stevel  */
    121     0    stevel 
    122     0    stevel #ifdef SOCK_TEST
    123     0    stevel /*
    124     0    stevel  * Variables that make sockfs do something other than the standard TPI
    125     0    stevel  * for the AF_INET transports.
    126     0    stevel  *
    127     0    stevel  * solisten_tpi_tcp:
    128     0    stevel  *	TCP can handle a O_T_BIND_REQ with an increased backlog even though
    129     0    stevel  *	the transport is already bound. This is needed to avoid loosing the
    130     0    stevel  *	port number should listen() do a T_UNBIND_REQ followed by a
    131     0    stevel  *	O_T_BIND_REQ.
    132     0    stevel  *
    133     0    stevel  * soconnect_tpi_udp:
    134     0    stevel  *	UDP and ICMP can handle a T_CONN_REQ.
    135     0    stevel  *	This is needed to make the sequence of connect(), getsockname()
    136     0    stevel  *	return the local IP address used to send packets to the connected to
    137     0    stevel  *	destination.
    138     0    stevel  *
    139     0    stevel  * soconnect_tpi_tcp:
    140     0    stevel  *	TCP can handle a T_CONN_REQ without seeing a O_T_BIND_REQ.
    141     0    stevel  *	Set this to non-zero to send TPI conformant messages to TCP in this
    142     0    stevel  *	respect. This is a performance optimization.
    143     0    stevel  *
    144     0    stevel  * soaccept_tpi_tcp:
    145     0    stevel  *	TCP can handle a T_CONN_REQ without the acceptor being bound.
    146     0    stevel  *	This is a performance optimization that has been picked up in XTI.
    147     0    stevel  *
    148     0    stevel  * soaccept_tpi_multioptions:
    149     0    stevel  *	When inheriting SOL_SOCKET options from the listener to the accepting
    150     0    stevel  *	socket send them as a single message for AF_INET{,6}.
    151     0    stevel  */
    152     0    stevel int solisten_tpi_tcp = 0;
    153     0    stevel int soconnect_tpi_udp = 0;
    154     0    stevel int soconnect_tpi_tcp = 0;
    155     0    stevel int soaccept_tpi_tcp = 0;
    156     0    stevel int soaccept_tpi_multioptions = 1;
    157     0    stevel #else /* SOCK_TEST */
    158     0    stevel #define	soconnect_tpi_tcp	0
    159     0    stevel #define	soconnect_tpi_udp	0
    160     0    stevel #define	solisten_tpi_tcp	0
    161     0    stevel #define	soaccept_tpi_tcp	0
    162     0    stevel #define	soaccept_tpi_multioptions	1
    163     0    stevel #endif /* SOCK_TEST */
    164     0    stevel 
    165     0    stevel #ifdef SOCK_TEST
    166     0    stevel extern int do_useracc;
    167     0    stevel extern clock_t sock_test_timelimit;
    168     0    stevel #endif /* SOCK_TEST */
    169     0    stevel 
    170     0    stevel /*
    171     0    stevel  * Some X/Open added checks might have to be backed out to keep SunOS 4.X
    172     0    stevel  * applications working. Turn on this flag to disable these checks.
    173     0    stevel  */
    174     0    stevel int xnet_skip_checks = 0;
    175     0    stevel int xnet_check_print = 0;
    176     0    stevel int xnet_truncate_print = 0;
    177     0    stevel 
    178  8348      Eric static void sotpi_destroy(struct sonode *);
    179  8348      Eric static struct sonode *sotpi_create(struct sockparams *, int, int, int, int,
    180  8348      Eric     int, int *, cred_t *cr);
    181  8348      Eric 
    182  8348      Eric static boolean_t	sotpi_info_create(struct sonode *, int);
    183  8348      Eric static void		sotpi_info_init(struct sonode *);
    184  8348      Eric static void 		sotpi_info_fini(struct sonode *);
    185  8348      Eric static void 		sotpi_info_destroy(struct sonode *);
    186  8348      Eric 
    187  8348      Eric /*
    188  8348      Eric  * Do direct function call to the transport layer below; this would
    189  8348      Eric  * also allow the transport to utilize read-side synchronous stream
    190  8348      Eric  * interface if necessary.  This is a /etc/system tunable that must
    191  8348      Eric  * not be modified on a running system.  By default this is enabled
    192  8348      Eric  * for performance reasons and may be disabled for debugging purposes.
    193  8348      Eric  */
    194  8348      Eric boolean_t socktpi_direct = B_TRUE;
    195  8348      Eric 
    196  8348      Eric static struct kmem_cache *socktpi_cache, *socktpi_unix_cache;
    197  8348      Eric 
    198     0    stevel extern	void sigintr(k_sigset_t *, int);
    199     0    stevel extern	void sigunintr(k_sigset_t *);
    200     0    stevel 
    201   898      kais /* Sockets acting as an in-kernel SSL proxy */
    202   898      kais extern mblk_t	*strsock_kssl_input(vnode_t *, mblk_t *, strwakeup_t *,
    203   898      kais 		    strsigset_t *, strsigset_t *, strpollset_t *);
    204   898      kais extern mblk_t	*strsock_kssl_output(vnode_t *, mblk_t *, strwakeup_t *,
    205   898      kais 		    strsigset_t *, strsigset_t *, strpollset_t *);
    206   898      kais 
    207     0    stevel static int	sotpi_unbind(struct sonode *, int);
    208  6707    brutus 
    209     0    stevel /* TPI sockfs sonode operations */
    210  8348      Eric int 		sotpi_init(struct sonode *, struct sonode *, struct cred *,
    211  8348      Eric 		    int);
    212  8348      Eric static int	sotpi_accept(struct sonode *, int, struct cred *,
    213  8348      Eric 		    struct sonode **);
    214     0    stevel static int	sotpi_bind(struct sonode *, struct sockaddr *, socklen_t,
    215  8348      Eric 		    int, struct cred *);
    216  8348      Eric static int	sotpi_listen(struct sonode *, int, struct cred *);
    217     0    stevel static int	sotpi_connect(struct sonode *, const struct sockaddr *,
    218  8348      Eric 		    socklen_t, int, int, struct cred *);
    219  8348      Eric extern int	sotpi_recvmsg(struct sonode *, struct nmsghdr *,
    220  8348      Eric 		    struct uio *, struct cred *);
    221     0    stevel static int	sotpi_sendmsg(struct sonode *, struct nmsghdr *,
    222  8348      Eric 		    struct uio *, struct cred *);
    223  8348      Eric static int	sotpi_sendmblk(struct sonode *, struct nmsghdr *, int,
    224  8348      Eric 		    struct cred *, mblk_t **);
    225   741  masputra static int	sosend_dgramcmsg(struct sonode *, struct sockaddr *, socklen_t,
    226   741  masputra 		    struct uio *, void *, t_uscalar_t, int);
    227   741  masputra static int	sodgram_direct(struct sonode *, struct sockaddr *,
    228   741  masputra 		    socklen_t, struct uio *, int);
    229  8348      Eric extern int	sotpi_getpeername(struct sonode *, struct sockaddr *,
    230  8348      Eric 		    socklen_t *, boolean_t, struct cred *);
    231  8348      Eric static int	sotpi_getsockname(struct sonode *, struct sockaddr *,
    232  8348      Eric 		    socklen_t *, struct cred *);
    233  8348      Eric static int	sotpi_shutdown(struct sonode *, int, struct cred *);
    234  8348      Eric extern int	sotpi_getsockopt(struct sonode *, int, int, void *,
    235  8348      Eric 		    socklen_t *, int, struct cred *);
    236  8348      Eric extern int	sotpi_setsockopt(struct sonode *, int, int, const void *,
    237  8348      Eric 		    socklen_t, struct cred *);
    238  8348      Eric static int 	sotpi_ioctl(struct sonode *, int, intptr_t, int, struct cred *,
    239  8348      Eric 		    int32_t *);
    240  8348      Eric static int 	socktpi_plumbioctl(struct vnode *, int, intptr_t, int,
    241  8348      Eric 		    struct cred *, int32_t *);
    242  8348      Eric static int 	sotpi_poll(struct sonode *, short, int, short *,
    243  8348      Eric 		    struct pollhead **);
    244  8348      Eric static int 	sotpi_close(struct sonode *, int, struct cred *);
    245  8348      Eric 
    246  8348      Eric static int	i_sotpi_info_constructor(sotpi_info_t *);
    247  8348      Eric static void 	i_sotpi_info_destructor(sotpi_info_t *);
    248     0    stevel 
    249     0    stevel sonodeops_t sotpi_sonodeops = {
    250  8348      Eric 	sotpi_init,		/* sop_init		*/
    251     0    stevel 	sotpi_accept,		/* sop_accept		*/
    252     0    stevel 	sotpi_bind,		/* sop_bind		*/
    253     0    stevel 	sotpi_listen,		/* sop_listen		*/
    254     0    stevel 	sotpi_connect,		/* sop_connect		*/
    255     0    stevel 	sotpi_recvmsg,		/* sop_recvmsg		*/
    256     0    stevel 	sotpi_sendmsg,		/* sop_sendmsg		*/
    257  8348      Eric 	sotpi_sendmblk,		/* sop_sendmblk		*/
    258     0    stevel 	sotpi_getpeername,	/* sop_getpeername	*/
    259     0    stevel 	sotpi_getsockname,	/* sop_getsockname	*/
    260     0    stevel 	sotpi_shutdown,		/* sop_shutdown		*/
    261     0    stevel 	sotpi_getsockopt,	/* sop_getsockopt	*/
    262  8348      Eric 	sotpi_setsockopt,	/* sop_setsockopt	*/
    263  8348      Eric 	sotpi_ioctl,		/* sop_ioctl		*/
    264  8348      Eric 	sotpi_poll,		/* sop_poll		*/
    265  8348      Eric 	sotpi_close,		/* sop_close		*/
    266     0    stevel };
    267  8348      Eric 
    268  8348      Eric /*
    269  8348      Eric  * Return a TPI socket vnode.
    270  8348      Eric  *
    271  8348      Eric  * Note that sockets assume that the driver will clone (either itself
    272  8348      Eric  * or by using the clone driver) i.e. a socket() call will always
    273  8348      Eric  * result in a new vnode being created.
    274  8348      Eric  */
    275     0    stevel 
    276     0    stevel /*
    277     0    stevel  * Common create code for socket and accept. If tso is set the values
    278     0    stevel  * from that node is used instead of issuing a T_INFO_REQ.
    279  8348      Eric  */
    280  8348      Eric 
    281  8348      Eric /* ARGSUSED */
    282  8348      Eric static struct sonode *
    283  8348      Eric sotpi_create(struct sockparams *sp, int family, int type, int protocol,
    284  8348      Eric     int version, int sflags, int *errorp, cred_t *cr)
    285     0    stevel {
    286     0    stevel 	struct sonode	*so;
    287  8348      Eric 	kmem_cache_t 	*cp;
    288  8348      Eric 	int		sfamily = family;
    289  8348      Eric 
    290  8348      Eric 	ASSERT(sp->sp_sdev_info.sd_vnode != NULL);
    291  8348      Eric 
    292  8348      Eric 	if (family == AF_NCA) {
    293  8348      Eric 		/*
    294  8348      Eric 		 * The request is for an NCA socket so for NL7C use the
    295  8348      Eric 		 * INET domain instead and mark NL7C_AF_NCA below.
    296  8348      Eric 		 */
    297  8348      Eric 		family = AF_INET;
    298  8348      Eric 		/*
    299  8348      Eric 		 * NL7C is not supported in the non-global zone,
    300  8348      Eric 		 * we enforce this restriction here.
    301  8348      Eric 		 */
    302  8348      Eric 		if (getzoneid() != GLOBAL_ZONEID) {
    303  8348      Eric 			*errorp = ENOTSUP;
    304  8348      Eric 			return (NULL);
    305  8348      Eric 		}
    306  8348      Eric 	}
    307  8348      Eric 
    308  8348      Eric 	/*
    309  8348      Eric 	 * to be compatible with old tpi socket implementation ignore
    310  8348      Eric 	 * sleep flag (sflags) passed in
    311  8348      Eric 	 */
    312  8348      Eric 	cp = (family == AF_UNIX) ? socktpi_unix_cache : socktpi_cache;
    313  8348      Eric 	so = kmem_cache_alloc(cp, KM_SLEEP);
    314  8348      Eric 	if (so == NULL) {
    315  8348      Eric 		*errorp = ENOMEM;
    316  8348      Eric 		return (NULL);
    317  8348      Eric 	}
    318  8348      Eric 
    319  8348      Eric 	sonode_init(so, sp, family, type, protocol, &sotpi_sonodeops);
    320  8348      Eric 	sotpi_info_init(so);
    321  8348      Eric 
    322  8348      Eric 	if (sfamily == AF_NCA) {
    323  8348      Eric 		SOTOTPI(so)->sti_nl7c_flags = NL7C_AF_NCA;
    324  8348      Eric 	}
    325  8348      Eric 
    326  8348      Eric 	if (version == SOV_DEFAULT)
    327  8348      Eric 		version = so_default_version;
    328  8348      Eric 
    329  8348      Eric 	so->so_version = (short)version;
    330  8348      Eric 	*errorp = 0;
    331  8348      Eric 
    332  8348      Eric 	return (so);
    333  8348      Eric }
    334  8348      Eric 
    335  8348      Eric static void
    336  8348      Eric sotpi_destroy(struct sonode *so)
    337  8348      Eric {
    338  8348      Eric 	kmem_cache_t *cp;
    339  8348      Eric 	struct sockparams *origsp;
    340  8348      Eric 
    341  8348      Eric 	/*
    342  8348      Eric 	 * If there is a new dealloc function (ie. smod_destroy_func),
    343  8348      Eric 	 * then it should check the correctness of the ops.
    344  8348      Eric 	 */
    345  8348      Eric 
    346  8348      Eric 	ASSERT(so->so_ops == &sotpi_sonodeops);
    347  8348      Eric 
    348  8348      Eric 	origsp = SOTOTPI(so)->sti_orig_sp;
    349  8348      Eric 
    350  8348      Eric 	sotpi_info_fini(so);
    351  8348      Eric 
    352  8348      Eric 	if (so->so_state & SS_FALLBACK_COMP) {
    353  8348      Eric 		/*
    354  8348      Eric 		 * A fallback happend, which means that a sotpi_info_t struct
    355  8348      Eric 		 * was allocated (as opposed to being allocated from the TPI
    356  8348      Eric 		 * sonode cache. Therefore we explicitly free the struct
    357  8348      Eric 		 * here.
    358  8348      Eric 		 */
    359  8348      Eric 		sotpi_info_destroy(so);
    360  8348      Eric 		ASSERT(origsp != NULL);
    361  8348      Eric 
    362  8348      Eric 		origsp->sp_smod_info->smod_sock_destroy_func(so);
    363  8348      Eric 		SOCKPARAMS_DEC_REF(origsp);
    364  8348      Eric 	} else {
    365  8348      Eric 		sonode_fini(so);
    366  8348      Eric 		cp = (so->so_family == AF_UNIX) ? socktpi_unix_cache :
    367  8348      Eric 		    socktpi_cache;
    368  8348      Eric 		kmem_cache_free(cp, so);
    369  8348      Eric 	}
    370  8348      Eric }
    371  8348      Eric 
    372  8348      Eric /* ARGSUSED1 */
    373  8348      Eric int
    374  8348      Eric sotpi_init(struct sonode *so, struct sonode *tso, struct cred *cr, int flags)
    375  8348      Eric {
    376  8348      Eric 	major_t maj;
    377  8348      Eric 	dev_t newdev;
    378  8348      Eric 	struct vnode *vp;
    379  8348      Eric 	int error = 0;
    380  8348      Eric 	struct stdata *stp;
    381  8348      Eric 
    382  8348      Eric 	sotpi_info_t *sti = SOTOTPI(so);
    383  8348      Eric 
    384  8348      Eric 	dprint(1, ("sotpi_init()\n"));
    385  8348      Eric 
    386  8348      Eric 	/*
    387  8348      Eric 	 * over write the sleep flag passed in but that is ok
    388  8348      Eric 	 * as tpi socket does not honor sleep flag.
    389  8348      Eric 	 */
    390  8348      Eric 	flags |= FREAD|FWRITE;
    391  8348      Eric 
    392  8348      Eric 	/*
    393  8348      Eric 	 * Record in so_flag that it is a clone.
    394  8348      Eric 	 */
    395  8348      Eric 	if (getmajor(sti->sti_dev) == clone_major)
    396  8348      Eric 		so->so_flag |= SOCLONE;
    397  8348      Eric 
    398  8348      Eric 	if ((so->so_type == SOCK_STREAM || so->so_type == SOCK_DGRAM) &&
    399  8348      Eric 	    (so->so_family == AF_INET || so->so_family == AF_INET6) &&
    400  8348      Eric 	    (so->so_protocol == IPPROTO_TCP || so->so_protocol == IPPROTO_UDP ||
    401  8348      Eric 	    so->so_protocol == IPPROTO_IP)) {
    402   741  masputra 		/* Tell tcp or udp that it's talking to sockets */
    403   741  masputra 		flags |= SO_SOCKSTR;
    404   741  masputra 
    405   741  masputra 		/*
    406   741  masputra 		 * Here we indicate to socktpi_open() our attempt to
    407   741  masputra 		 * make direct calls between sockfs and transport.
    408   741  masputra 		 * The final decision is left to socktpi_open().
    409   741  masputra 		 */
    410  8348      Eric 		sti->sti_direct = 1;
    411   741  masputra 
    412   741  masputra 		ASSERT(so->so_type != SOCK_DGRAM || tso == NULL);
    413   741  masputra 		if (so->so_type == SOCK_STREAM && tso != NULL) {
    414  8348      Eric 			if (SOTOTPI(tso)->sti_direct) {
    415  8348      Eric 				/*
    416  8348      Eric 				 * Inherit sti_direct from listener and pass
    417   741  masputra 				 * SO_ACCEPTOR open flag to tcp, indicating
    418   741  masputra 				 * that this is an accept fast-path instance.
    419   741  masputra 				 */
    420   741  masputra 				flags |= SO_ACCEPTOR;
    421   741  masputra 			} else {
    422   741  masputra 				/*
    423  8348      Eric 				 * sti_direct is not set on listener, meaning
    424   741  masputra 				 * that the listener has been converted from
    425   741  masputra 				 * a socket to a stream.  Ensure that the
    426   741  masputra 				 * acceptor inherits these settings.
    427   741  masputra 				 */
    428  8348      Eric 				sti->sti_direct = 0;
    429   741  masputra 				flags &= ~SO_SOCKSTR;
    430   741  masputra 			}
    431     0    stevel 		}
    432     0    stevel 	}
    433     0    stevel 
    434     0    stevel 	/*
    435     0    stevel 	 * Tell local transport that it is talking to sockets.
    436     0    stevel 	 */
    437     0    stevel 	if (so->so_family == AF_UNIX) {
    438     0    stevel 		flags |= SO_SOCKSTR;
    439     0    stevel 	}
    440     0    stevel 
    441  8348      Eric 	vp = SOTOV(so);
    442  8348      Eric 	newdev = vp->v_rdev;
    443  8348      Eric 	maj = getmajor(newdev);
    444  8348      Eric 	ASSERT(STREAMSTAB(maj));
    445  8348      Eric 
    446  8348      Eric 	error = stropen(vp, &newdev, flags, cr);
    447  8348      Eric 
    448  8348      Eric 	stp = vp->v_stream;
    449  8348      Eric 	if (error == 0) {
    450  8348      Eric 		if (so->so_flag & SOCLONE)
    451  8348      Eric 			ASSERT(newdev != vp->v_rdev);
    452  8348      Eric 		mutex_enter(&so->so_lock);
    453  8348      Eric 		sti->sti_dev = newdev;
    454  8348      Eric 		vp->v_rdev = newdev;
    455  8348      Eric 		mutex_exit(&so->so_lock);
    456  8348      Eric 
    457  8348      Eric 		if (stp->sd_flag & STRISTTY) {
    458  8348      Eric 			/*
    459  8348      Eric 			 * this is a post SVR4 tty driver - a socket can not
    460  8348      Eric 			 * be a controlling terminal. Fail the open.
    461  8348      Eric 			 */
    462  8348      Eric 			(void) sotpi_close(so, flags, cr);
    463  8348      Eric 			return (ENOTTY);	/* XXX */
    464  8348      Eric 		}
    465  8348      Eric 
    466  8348      Eric 		ASSERT(stp->sd_wrq != NULL);
    467  8348      Eric 		sti->sti_provinfo = tpi_findprov(stp->sd_wrq);
    468  8348      Eric 
    469  8348      Eric 		/*
    470  8348      Eric 		 * If caller is interested in doing direct function call
    471  8348      Eric 		 * interface to/from transport module, probe the module
    472  8348      Eric 		 * directly beneath the streamhead to see if it qualifies.
    473  8348      Eric 		 *
    474  8348      Eric 		 * We turn off the direct interface when qualifications fail.
    475  8348      Eric 		 * In the acceptor case, we simply turn off the sti_direct
    476  8348      Eric 		 * flag on the socket. We do the fallback after the accept
    477  8348      Eric 		 * has completed, before the new socket is returned to the
    478  8348      Eric 		 * application.
    479  8348      Eric 		 */
    480  8348      Eric 		if (sti->sti_direct) {
    481  8348      Eric 			queue_t *tq = stp->sd_wrq->q_next;
    482  8348      Eric 
    483  8348      Eric 			/*
    484  8348      Eric 			 * sti_direct is currently supported and tested
    485  8348      Eric 			 * only for tcp/udp; this is the main reason to
    486  8348      Eric 			 * have the following assertions.
    487  8348      Eric 			 */
    488  8348      Eric 			ASSERT(so->so_family == AF_INET ||
    489  8348      Eric 			    so->so_family == AF_INET6);
    490  8348      Eric 			ASSERT(so->so_protocol == IPPROTO_UDP ||
    491  8348      Eric 			    so->so_protocol == IPPROTO_TCP ||
    492  8348      Eric 			    so->so_protocol == IPPROTO_IP);
    493  8348      Eric 			ASSERT(so->so_type == SOCK_DGRAM ||
    494  8348      Eric 			    so->so_type == SOCK_STREAM);
    495  8348      Eric 
    496  8348      Eric 			/*
    497  8348      Eric 			 * Abort direct call interface if the module directly
    498  8348      Eric 			 * underneath the stream head is not defined with the
    499  8348      Eric 			 * _D_DIRECT flag.  This could happen in the tcp or
    500  8348      Eric 			 * udp case, when some other module is autopushed
    501  8348      Eric 			 * above it, or for some reasons the expected module
    502  8348      Eric 			 * isn't purely D_MP (which is the main requirement).
    503  8348      Eric 			 */
    504  8348      Eric 			if (!socktpi_direct || !(tq->q_flag & _QDIRECT) ||
    505  8348      Eric 			    !(_OTHERQ(tq)->q_flag & _QDIRECT)) {
    506  8348      Eric 				int rval;
    507  8348      Eric 
    508  8348      Eric 				/* Continue on without direct calls */
    509  8348      Eric 				sti->sti_direct = 0;
    510  8348      Eric 
    511  8348      Eric 				/*
    512  8348      Eric 				 * Cannot issue ioctl on fallback socket since
    513  8348      Eric 				 * there is no conn associated with the queue.
    514  8348      Eric 				 * The fallback downcall will notify the proto
    515  8348      Eric 				 * of the change.
    516  8348      Eric 				 */
    517  8348      Eric 				if (!(flags & SO_ACCEPTOR) &&
    518  8348      Eric 				    !(flags & SO_FALLBACK)) {
    519  8348      Eric 					if ((error = strioctl(vp,
    520  8348      Eric 					    _SIOCSOCKFALLBACK, 0, 0, K_TO_K,
    521  8348      Eric 					    cr, &rval)) != 0) {
    522  8348      Eric 						(void) sotpi_close(so, flags,
    523  8348      Eric 						    cr);
    524  8348      Eric 						return (error);
    525  8348      Eric 					}
    526  8348      Eric 				}
    527  8348      Eric 			}
    528  8348      Eric 		}
    529  8348      Eric 
    530  8348      Eric 		if (flags & SO_FALLBACK) {
    531  8348      Eric 			/*
    532  8348      Eric 			 * The stream created does not have a conn.
    533  8348      Eric 			 * do stream set up after conn has been assigned
    534  8348      Eric 			 */
    535  8348      Eric 			return (error);
    536  8348      Eric 		}
    537  8348      Eric 		if (error = so_strinit(so, tso)) {
    538  8348      Eric 			(void) sotpi_close(so, flags, cr);
    539  8348      Eric 			return (error);
    540  8348      Eric 		}
    541  8348      Eric 
    542  8348      Eric 		/* Wildcard */
    543  8348      Eric 		if (so->so_protocol != so->so_sockparams->sp_protocol) {
    544  8348      Eric 			int protocol = so->so_protocol;
    545  8348      Eric 			/*
    546  8348      Eric 			 * Issue SO_PROTOTYPE setsockopt.
    547  8348      Eric 			 */
    548  8348      Eric 			error = sotpi_setsockopt(so, SOL_SOCKET, SO_PROTOTYPE,
    549  8348      Eric 			    &protocol, (t_uscalar_t)sizeof (protocol), cr);
    550  8348      Eric 			if (error != 0) {
    551  8348      Eric 				(void) sotpi_close(so, flags, cr);
    552  8348      Eric 				/*
    553  8348      Eric 				 * Setsockopt often fails with ENOPROTOOPT but
    554  8348      Eric 				 * socket() should fail with
    555  8348      Eric 				 * EPROTONOSUPPORT/EPROTOTYPE.
    556  8348      Eric 				 */
    557  8348      Eric 				return (EPROTONOSUPPORT);
    558  8348      Eric 			}
    559  8348      Eric 		}
    560  8348      Eric 
    561  8348      Eric 	} else {
    562  8348      Eric 		/*
    563  8348      Eric 		 * While the same socket can not be reopened (unlike specfs)
    564  8348      Eric 		 * the stream head sets STREOPENFAIL when the autopush fails.
    565  8348      Eric 		 */
    566  8348      Eric 		if ((stp != NULL) &&
    567  8348      Eric 		    (stp->sd_flag & STREOPENFAIL)) {
    568  8348      Eric 			/*
    569  8348      Eric 			 * Open failed part way through.
    570  8348      Eric 			 */
    571  8348      Eric 			mutex_enter(&stp->sd_lock);
    572  8348      Eric 			stp->sd_flag &= ~STREOPENFAIL;
    573  8348      Eric 			mutex_exit(&stp->sd_lock);
    574  8348      Eric 			(void) sotpi_close(so, flags, cr);
    575  8348      Eric 			return (error);
    576  8348      Eric 			/*NOTREACHED*/
    577  8348      Eric 		}
    578  8348      Eric 		ASSERT(stp == NULL);
    579  8348      Eric 	}
    580  8348      Eric 	TRACE_4(TR_FAC_SOCKFS, TR_SOCKFS_OPEN,
    581  8348      Eric 	    "sockfs open:maj %d vp %p so %p error %d",
    582  8348      Eric 	    maj, vp, so, error);
    583  8348      Eric 	return (error);
    584     0    stevel }
    585     0    stevel 
    586     0    stevel /*
    587     0    stevel  * Bind the socket to an unspecified address in sockfs only.
    588     0    stevel  * Used for TCP/UDP transports where we know that the O_T_BIND_REQ isn't
    589     0    stevel  * required in all cases.
    590     0    stevel  */
    591     0    stevel static void
    592     0    stevel so_automatic_bind(struct sonode *so)
    593     0    stevel {
    594  8348      Eric 	sotpi_info_t *sti = SOTOTPI(so);
    595     0    stevel 	ASSERT(so->so_family == AF_INET || so->so_family == AF_INET6);
    596     0    stevel 
    597     0    stevel 	ASSERT(MUTEX_HELD(&so->so_lock));
    598     0    stevel 	ASSERT(!(so->so_state & SS_ISBOUND));
    599  8348      Eric 	ASSERT(sti->sti_unbind_mp);
    600  8348      Eric 
    601  8348      Eric 	ASSERT(sti->sti_laddr_len <= sti->sti_laddr_maxlen);
    602  8348      Eric 	bzero(sti->sti_laddr_sa, sti->sti_laddr_len);
    603  8348      Eric 	sti->sti_laddr_sa->sa_family = so->so_family;
    604     0    stevel 	so->so_state |= SS_ISBOUND;
    605     0    stevel }
    606     0    stevel 
    607     0    stevel 
    608     0    stevel /*
    609     0    stevel  * bind the socket.
    610     0    stevel  *
    611     0    stevel  * If the socket is already bound and none of _SOBIND_SOCKBSD or _SOBIND_XPG4_2
    612     0    stevel  * are passed in we allow rebinding. Note that for backwards compatibility
    613     0    stevel  * even "svr4" sockets pass in _SOBIND_SOCKBSD/SOV_SOCKBSD to sobind/bind.
    614     0    stevel  * Thus the rebinding code is currently not executed.
    615     0    stevel  *
    616     0    stevel  * The constraints for rebinding are:
    617     0    stevel  * - it is a SOCK_DGRAM, or
    618     0    stevel  * - it is a SOCK_STREAM/SOCK_SEQPACKET that has not been connected
    619     0    stevel  *   and no listen() has been done.
    620     0    stevel  * This rebinding code was added based on some language in the XNET book
    621     0    stevel  * about not returning EINVAL it the protocol allows rebinding. However,
    622     0    stevel  * this language is not present in the Posix socket draft. Thus maybe the
    623     0    stevel  * rebinding logic should be deleted from the source.
    624     0    stevel  *
    625     0    stevel  * A null "name" can be used to unbind the socket if:
    626     0    stevel  * - it is a SOCK_DGRAM, or
    627     0    stevel  * - it is a SOCK_STREAM/SOCK_SEQPACKET that has not been connected
    628     0    stevel  *   and no listen() has been done.
    629     0    stevel  */
    630  8348      Eric /* ARGSUSED */
    631     0    stevel static int
    632     0    stevel sotpi_bindlisten(struct sonode *so, struct sockaddr *name,
    633  8348      Eric     socklen_t namelen, int backlog, int flags, struct cred *cr)
    634     0    stevel {
    635     0    stevel 	struct T_bind_req	bind_req;
    636     0    stevel 	struct T_bind_ack	*bind_ack;
    637     0    stevel 	int			error = 0;
    638     0    stevel 	mblk_t			*mp;
    639     0    stevel 	void			*addr;
    640     0    stevel 	t_uscalar_t		addrlen;
    641     0    stevel 	int			unbind_on_err = 1;
    642     0    stevel 	boolean_t		clear_acceptconn_on_err = B_FALSE;
    643     0    stevel 	boolean_t		restore_backlog_on_err = B_FALSE;
    644     0    stevel 	int			save_so_backlog;
    645     0    stevel 	t_scalar_t		PRIM_type = O_T_BIND_REQ;
    646     0    stevel 	boolean_t		tcp_udp_xport;
    647     0    stevel 	void			*nl7c = NULL;
    648  8348      Eric 	sotpi_info_t		*sti = SOTOTPI(so);
    649     0    stevel 
    650     0    stevel 	dprintso(so, 1, ("sotpi_bindlisten(%p, %p, %d, %d, 0x%x) %s\n",
    651  7240   rh87107 	    (void *)so, (void *)name, namelen, backlog, flags,
    652  5240  nordmark 	    pr_state(so->so_state, so->so_mode)));
    653     0    stevel 
    654     0    stevel 	tcp_udp_xport = so->so_type == SOCK_STREAM || so->so_type == SOCK_DGRAM;
    655     0    stevel 
    656     0    stevel 	if (!(flags & _SOBIND_LOCK_HELD)) {
    657     0    stevel 		mutex_enter(&so->so_lock);
    658     0    stevel 		so_lock_single(so);	/* Set SOLOCKED */
    659     0    stevel 	} else {
    660     0    stevel 		ASSERT(MUTEX_HELD(&so->so_lock));
    661     0    stevel 		ASSERT(so->so_flag & SOLOCKED);
    662     0    stevel 	}
    663     0    stevel 
    664     0    stevel 	/*
    665     0    stevel 	 * Make sure that there is a preallocated unbind_req message
    666     0    stevel 	 * before binding. This message allocated when the socket is
    667     0    stevel 	 * created  but it might be have been consumed.
    668     0    stevel 	 */
    669  8348      Eric 	if (sti->sti_unbind_mp == NULL) {
    670     0    stevel 		dprintso(so, 1, ("sobind: allocating unbind_req\n"));
    671     0    stevel 		/* NOTE: holding so_lock while sleeping */
    672  8348      Eric 		sti->sti_unbind_mp =
    673  8778      Erik 		    soallocproto(sizeof (struct T_unbind_req), _ALLOC_SLEEP,
    674  8778      Erik 		    cr);
    675     0    stevel 	}
    676     0    stevel 
    677     0    stevel 	if (flags & _SOBIND_REBIND) {
    678     0    stevel 		/*
    679     0    stevel 		 * Called from solisten after doing an sotpi_unbind() or
    680     0    stevel 		 * potentially without the unbind (latter for AF_INET{,6}).
    681     0    stevel 		 */
    682     0    stevel 		ASSERT(name == NULL && namelen == 0);
    683     0    stevel 
    684     0    stevel 		if (so->so_family == AF_UNIX) {
    685  8348      Eric 			ASSERT(sti->sti_ux_bound_vp);
    686  8348      Eric 			addr = &sti->sti_ux_laddr;
    687  8348      Eric 			addrlen = (t_uscalar_t)sizeof (sti->sti_ux_laddr);
    688  5240  nordmark 			dprintso(so, 1, ("sobind rebind UNIX: addrlen %d, "
    689  5240  nordmark 			    "addr 0x%p, vp %p\n",
    690     0    stevel 			    addrlen,
    691  7240   rh87107 			    (void *)((struct so_ux_addr *)addr)->soua_vp,
    692  8348      Eric 			    (void *)sti->sti_ux_bound_vp));
    693  8348      Eric 		} else {
    694  8348      Eric 			addr = sti->sti_laddr_sa;
    695  8348      Eric 			addrlen = (t_uscalar_t)sti->sti_laddr_len;
    696     0    stevel 		}
    697     0    stevel 	} else if (flags & _SOBIND_UNSPEC) {
    698     0    stevel 		ASSERT(name == NULL && namelen == 0);
    699     0    stevel 
    700     0    stevel 		/*
    701     0    stevel 		 * The caller checked SS_ISBOUND but not necessarily
    702     0    stevel 		 * under so_lock
    703     0    stevel 		 */
    704     0    stevel 		if (so->so_state & SS_ISBOUND) {
    705     0    stevel 			/* No error */
    706     0    stevel 			goto done;
    707     0    stevel 		}
    708     0    stevel 
    709     0    stevel 		/* Set an initial local address */
    710     0    stevel 		switch (so->so_family) {
    711     0    stevel 		case AF_UNIX:
    712     0    stevel 			/*
    713     0    stevel 			 * Use an address with same size as struct sockaddr
    714     0    stevel 			 * just like BSD.
    715     0    stevel 			 */
    716  8348      Eric 			sti->sti_laddr_len =
    717  5240  nordmark 			    (socklen_t)sizeof (struct sockaddr);
    718  8348      Eric 			ASSERT(sti->sti_laddr_len <= sti->sti_laddr_maxlen);
    719  8348      Eric 			bzero(sti->sti_laddr_sa, sti->sti_laddr_len);
    720  8348      Eric 			sti->sti_laddr_sa->sa_family = so->so_family;
    721     0    stevel 
    722     0    stevel 			/*
    723     0    stevel 			 * Pass down an address with the implicit bind
    724     0    stevel 			 * magic number and the rest all zeros.
    725     0    stevel 			 * The transport will return a unique address.
    726     0    stevel 			 */
    727  8348      Eric 			sti->sti_ux_laddr.soua_vp = NULL;
    728  8348      Eric 			sti->sti_ux_laddr.soua_magic = SOU_MAGIC_IMPLICIT;
    729  8348      Eric 			addr = &sti->sti_ux_laddr;
    730  8348      Eric 			addrlen = (t_uscalar_t)sizeof (sti->sti_ux_laddr);
    731     0    stevel 			break;
    732     0    stevel 
    733     0    stevel 		case AF_INET:
    734     0    stevel 		case AF_INET6:
    735     0    stevel 			/*
    736     0    stevel 			 * An unspecified bind in TPI has a NULL address.
    737     0    stevel 			 * Set the address in sockfs to have the sa_family.
    738     0    stevel 			 */
    739  8348      Eric 			sti->sti_laddr_len = (so->so_family == AF_INET) ?
    740     0    stevel 			    (socklen_t)sizeof (sin_t) :
    741     0    stevel 			    (socklen_t)sizeof (sin6_t);
    742  8348      Eric 			ASSERT(sti->sti_laddr_len <= sti->sti_laddr_maxlen);
    743  8348      Eric 			bzero(sti->sti_laddr_sa, sti->sti_laddr_len);
    744  8348      Eric 			sti->sti_laddr_sa->sa_family = so->so_family;
    745     0    stevel 			addr = NULL;
    746     0    stevel 			addrlen = 0;
    747     0    stevel 			break;
    748     0    stevel 
    749     0    stevel 		default:
    750     0    stevel 			/*
    751     0    stevel 			 * An unspecified bind in TPI has a NULL address.
    752     0    stevel 			 * Set the address in sockfs to be zero length.
    753     0    stevel 			 *
    754     0    stevel 			 * Can not assume there is a sa_family for all
    755     0    stevel 			 * protocol families. For example, AF_X25 does not
    756     0    stevel 			 * have a family field.
    757     0    stevel 			 */
    758  8348      Eric 			bzero(sti->sti_laddr_sa, sti->sti_laddr_len);
    759  8348      Eric 			sti->sti_laddr_len = 0;	/* XXX correct? */
    760     0    stevel 			addr = NULL;
    761     0    stevel 			addrlen = 0;
    762     0    stevel 			break;
    763     0    stevel 		}
    764     0    stevel 
    765     0    stevel 	} else {
    766     0    stevel 		if (so->so_state & SS_ISBOUND) {
    767     0    stevel 			/*
    768     0    stevel 			 * If it is ok to rebind the socket, first unbind
    769     0    stevel 			 * with the transport. A rebind to the NULL address
    770     0    stevel 			 * is interpreted as an unbind.
    771     0    stevel 			 * Note that a bind to NULL in BSD does unbind the
    772     0    stevel 			 * socket but it fails with EINVAL.
    773     0    stevel 			 * Note that regular sockets set SOV_SOCKBSD i.e.
    774     0    stevel 			 * _SOBIND_SOCKBSD gets set here hence no type of
    775     0    stevel 			 * socket does currently allow rebinding.
    776     0    stevel 			 *
    777     0    stevel 			 * If the name is NULL just do an unbind.
    778     0    stevel 			 */
    779     0    stevel 			if (flags & (_SOBIND_SOCKBSD|_SOBIND_XPG4_2) &&
    780     0    stevel 			    name != NULL) {
    781     0    stevel 				error = EINVAL;
    782     0    stevel 				unbind_on_err = 0;
    783     0    stevel 				eprintsoline(so, error);
    784     0    stevel 				goto done;
    785     0    stevel 			}
    786     0    stevel 			if ((so->so_mode & SM_CONNREQUIRED) &&
    787     0    stevel 			    (so->so_state & SS_CANTREBIND)) {
    788     0    stevel 				error = EINVAL;
    789     0    stevel 				unbind_on_err = 0;
    790     0    stevel 				eprintsoline(so, error);
    791     0    stevel 				goto done;
    792     0    stevel 			}
    793     0    stevel 			error = sotpi_unbind(so, 0);
    794     0    stevel 			if (error) {
    795     0    stevel 				eprintsoline(so, error);
    796     0    stevel 				goto done;
    797     0    stevel 			}
    798     0    stevel 			ASSERT(!(so->so_state & SS_ISBOUND));
    799     0    stevel 			if (name == NULL) {
    800     0    stevel 				so->so_state &=
    801  5240  nordmark 				    ~(SS_ISCONNECTED|SS_ISCONNECTING);
    802     0    stevel 				goto done;
    803     0    stevel 			}
    804     0    stevel 		}
    805  8348      Eric 
    806     0    stevel 		/* X/Open requires this check */
    807     0    stevel 		if ((so->so_state & SS_CANTSENDMORE) && !xnet_skip_checks) {
    808     0    stevel 			if (xnet_check_print) {
    809     0    stevel 				printf("sockfs: X/Open bind state check "
    810     0    stevel 				    "caused EINVAL\n");
    811     0    stevel 			}
    812     0    stevel 			error = EINVAL;
    813     0    stevel 			goto done;
    814     0    stevel 		}
    815     0    stevel 
    816     0    stevel 		switch (so->so_family) {
    817     0    stevel 		case AF_UNIX:
    818     0    stevel 			/*
    819     0    stevel 			 * All AF_UNIX addresses are nul terminated
    820     0    stevel 			 * when copied (copyin_name) in so the minimum
    821     0    stevel 			 * length is 3 bytes.
    822     0    stevel 			 */
    823     0    stevel 			if (name == NULL ||
    824     0    stevel 			    (ssize_t)namelen <= sizeof (short) + 1) {
    825     0    stevel 				error = EISDIR;
    826     0    stevel 				eprintsoline(so, error);
    827     0    stevel 				goto done;
    828     0    stevel 			}
    829     0    stevel 			/*
    830     0    stevel 			 * Verify so_family matches the bound family.
    831     0    stevel 			 * BSD does not check this for AF_UNIX resulting
    832     0    stevel 			 * in funny mknods.
    833     0    stevel 			 */
    834     0    stevel 			if (name->sa_family != so->so_family) {
    835     0    stevel 				error = EAFNOSUPPORT;
    836     0    stevel 				goto done;
    837     0    stevel 			}
    838     0    stevel 			break;
    839     0    stevel 		case AF_INET:
    840     0    stevel 			if (name == NULL) {
    841     0    stevel 				error = EINVAL;
    842     0    stevel 				eprintsoline(so, error);
    843     0    stevel 				goto done;
    844     0    stevel 			}
    845     0    stevel 			if ((size_t)namelen != sizeof (sin_t)) {
    846     0    stevel 				error = name->sa_family != so->so_family ?
    847     0    stevel 				    EAFNOSUPPORT : EINVAL;
    848     0    stevel 				eprintsoline(so, error);
    849     0    stevel 				goto done;
    850     0    stevel 			}
    851     0    stevel 			if ((flags & _SOBIND_XPG4_2) &&
    852     0    stevel 			    (name->sa_family != so->so_family)) {
    853     0    stevel 				/*
    854     0    stevel 				 * This check has to be made for X/Open
    855     0    stevel 				 * sockets however application failures have
    856     0    stevel 				 * been observed when it is applied to
    857     0    stevel 				 * all sockets.
    858     0    stevel 				 */
    859     0    stevel 				error = EAFNOSUPPORT;
    860     0    stevel 				eprintsoline(so, error);
    861     0    stevel 				goto done;
    862     0    stevel 			}
    863     0    stevel 			/*
    864     0    stevel 			 * Force a zero sa_family to match so_family.
    865     0    stevel 			 *
    866     0    stevel 			 * Some programs like inetd(1M) don't set the
    867     0    stevel 			 * family field. Other programs leave
    868     0    stevel 			 * sin_family set to garbage - SunOS 4.X does
    869     0    stevel 			 * not check the family field on a bind.
    870     0    stevel 			 * We use the family field that
    871     0    stevel 			 * was passed in to the socket() call.
    872     0    stevel 			 */
    873     0    stevel 			name->sa_family = so->so_family;
    874     0    stevel 			break;
    875     0    stevel 
    876     0    stevel 		case AF_INET6: {
    877     0    stevel #ifdef DEBUG
    878     0    stevel 			sin6_t *sin6 = (sin6_t *)name;
    879     0    stevel #endif /* DEBUG */
    880     0    stevel 
    881     0    stevel 			if (name == NULL) {
    882     0    stevel 				error = EINVAL;
    883     0    stevel 				eprintsoline(so, error);
    884     0    stevel 				goto done;
    885     0    stevel 			}
    886     0    stevel 			if ((size_t)namelen != sizeof (sin6_t)) {
    887     0    stevel 				error = name->sa_family != so->so_family ?
    888     0    stevel 				    EAFNOSUPPORT : EINVAL;
    889     0    stevel 				eprintsoline(so, error);
    890     0    stevel 				goto done;
    891     0    stevel 			}
    892     0    stevel 			if (name->sa_family != so->so_family) {
    893     0    stevel 				/*
    894     0    stevel 				 * With IPv6 we require the family to match
    895     0    stevel 				 * unlike in IPv4.
    896     0    stevel 				 */
    897     0    stevel 				error = EAFNOSUPPORT;
    898     0    stevel 				eprintsoline(so, error);
    899     0    stevel 				goto done;
    900     0    stevel 			}
    901     0    stevel #ifdef DEBUG
    902     0    stevel 			/*
    903     0    stevel 			 * Verify that apps don't forget to clear
    904     0    stevel 			 * sin6_scope_id etc
    905     0    stevel 			 */
    906     0    stevel 			if (sin6->sin6_scope_id != 0 &&
    907     0    stevel 			    !IN6_IS_ADDR_LINKSCOPE(&sin6->sin6_addr)) {
    908  1548   rshoaib 				zcmn_err(getzoneid(), CE_WARN,
    909     0    stevel 				    "bind with uninitialized sin6_scope_id "
    910     0    stevel 				    "(%d) on socket. Pid = %d\n",
    911     0    stevel 				    (int)sin6->sin6_scope_id,
    912     0    stevel 				    (int)curproc->p_pid);
    913     0    stevel 			}
    914     0    stevel 			if (sin6->__sin6_src_id != 0) {
    915  1548   rshoaib 				zcmn_err(getzoneid(), CE_WARN,
    916     0    stevel 				    "bind with uninitialized __sin6_src_id "
    917     0    stevel 				    "(%d) on socket. Pid = %d\n",
    918     0    stevel 				    (int)sin6->__sin6_src_id,
    919     0    stevel 				    (int)curproc->p_pid);
    920     0    stevel 			}
    921     0    stevel #endif /* DEBUG */
    922     0    stevel 			break;
    923     0    stevel 		}
    924     0    stevel 		default:
    925     0    stevel 			/*
    926     0    stevel 			 * Don't do any length or sa_family check to allow
    927     0    stevel 			 * non-sockaddr style addresses.
    928     0    stevel 			 */
    929     0    stevel 			if (name == NULL) {
    930     0    stevel 				error = EINVAL;
    931     0    stevel 				eprintsoline(so, error);
    932     0    stevel 				goto done;
    933     0    stevel 			}
    934     0    stevel 			break;
    935     0    stevel 		}
    936     0    stevel 
    937  8348      Eric 		if (namelen > (t_uscalar_t)sti->sti_laddr_maxlen) {
    938     0    stevel 			error = ENAMETOOLONG;
    939     0    stevel 			eprintsoline(so, error);
    940     0    stevel 			goto done;
    941     0    stevel 		}
    942     0    stevel 		/*
    943     0    stevel 		 * Save local address.
    944     0    stevel 		 */
    945  8348      Eric 		sti->sti_laddr_len = (socklen_t)namelen;
    946  8348      Eric 		ASSERT(sti->sti_laddr_len <= sti->sti_laddr_maxlen);
    947  8348      Eric 		bcopy(name, sti->sti_laddr_sa, namelen);
    948  8348      Eric 
    949  8348      Eric 		addr = sti->sti_laddr_sa;
    950  8348      Eric 		addrlen = (t_uscalar_t)sti->sti_laddr_len;
    951     0    stevel 		switch (so->so_family) {
    952     0    stevel 		case AF_INET6:
    953     0    stevel 		case AF_INET:
    954     0    stevel 			break;
    955     0    stevel 		case AF_UNIX: {
    956     0    stevel 			struct sockaddr_un *soun =
    957  8348      Eric 			    (struct sockaddr_un *)sti->sti_laddr_sa;
    958  8032       Ric 			struct vnode *vp, *rvp;
    959     0    stevel 			struct vattr vattr;
    960     0    stevel 
    961  8348      Eric 			ASSERT(sti->sti_ux_bound_vp == NULL);
    962     0    stevel 			/*
    963     0    stevel 			 * Create vnode for the specified path name.
    964  8348      Eric 			 * Keep vnode held with a reference in sti_ux_bound_vp.
    965     0    stevel 			 * Use the vnode pointer as the address used in the
    966     0    stevel 			 * bind with the transport.
    967     0    stevel 			 *
    968     0    stevel 			 * Use the same mode as in BSD. In particular this does
    969     0    stevel 			 * not observe the umask.
    970     0    stevel 			 */
    971     0    stevel 			/* MAXPATHLEN + soun_family + nul termination */
    972  8348      Eric 			if (sti->sti_laddr_len >
    973     0    stevel 			    (socklen_t)(MAXPATHLEN + sizeof (short) + 1)) {
    974     0    stevel 				error = ENAMETOOLONG;
    975     0    stevel 				eprintsoline(so, error);
    976     0    stevel 				goto done;
    977     0    stevel 			}
    978     0    stevel 			vattr.va_type = VSOCK;
    979  3446       mrj 			vattr.va_mode = 0777 & ~PTOU(curproc)->u_cmask;
    980     0    stevel 			vattr.va_mask = AT_TYPE|AT_MODE;
    981     0    stevel 			/* NOTE: holding so_lock */
    982     0    stevel 			error = vn_create(soun->sun_path, UIO_SYSSPACE, &vattr,
    983  5240  nordmark 			    EXCL, 0, &vp, CRMKNOD, 0, 0);
    984     0    stevel 			if (error) {
    985     0    stevel 				if (error == EEXIST)
    986     0    stevel 					error = EADDRINUSE;
    987     0    stevel 				eprintsoline(so, error);
    988     0    stevel 				goto done;
    989     0    stevel 			}
    990     0    stevel 			/*
    991     0    stevel 			 * Establish pointer from the underlying filesystem
    992     0    stevel 			 * vnode to the socket node.
    993  8348      Eric 			 * sti_ux_bound_vp and v_stream->sd_vnode form the
    994     0    stevel 			 * cross-linkage between the underlying filesystem
    995     0    stevel 			 * node and the socket node.
    996     0    stevel 			 */
    997  8032       Ric 
    998  8032       Ric 			if ((VOP_REALVP(vp, &rvp, NULL) == 0) && (vp != rvp)) {
    999  8032       Ric 				VN_HOLD(rvp);
   1000  8032       Ric 				VN_RELE(vp);
   1001  8032       Ric 				vp = rvp;
   1002  8032       Ric 			}
   1003  8032       Ric 
   1004     0    stevel 			ASSERT(SOTOV(so)->v_stream);
   1005     0    stevel 			mutex_enter(&vp->v_lock);
   1006     0    stevel 			vp->v_stream = SOTOV(so)->v_stream;
   1007  8348      Eric 			sti->sti_ux_bound_vp = vp;
   1008     0    stevel 			mutex_exit(&vp->v_lock);
   1009     0    stevel 
   1010     0    stevel 			/*
   1011     0    stevel 			 * Use the vnode pointer value as a unique address
   1012     0    stevel 			 * (together with the magic number to avoid conflicts
   1013     0    stevel 			 * with implicit binds) in the transport provider.
   1014     0    stevel 			 */
   1015  8348      Eric 			sti->sti_ux_laddr.soua_vp =
   1016  8348      Eric 			    (void *)sti->sti_ux_bound_vp;
   1017  8348      Eric 			sti->sti_ux_laddr.soua_magic = SOU_MAGIC_EXPLICIT;
   1018  8348      Eric 			addr = &sti->sti_ux_laddr;
   1019  8348      Eric 			addrlen = (t_uscalar_t)sizeof (sti->sti_ux_laddr);
   1020     0    stevel 			dprintso(so, 1, ("sobind UNIX: addrlen %d, addr %p\n",
   1021     0    stevel 			    addrlen,
   1022  8348      Eric 			    (void *)((struct so_ux_addr *)addr)->soua_vp));
   1023     0    stevel 			break;
   1024     0    stevel 		}
   1025     0    stevel 		} /* end switch (so->so_family) */
   1026     0    stevel 	}
   1027     0    stevel 
   1028     0    stevel 	/*
   1029     0    stevel 	 * set SS_ACCEPTCONN before sending down O_T_BIND_REQ since
   1030     0    stevel 	 * the transport can start passing up T_CONN_IND messages
   1031     0    stevel 	 * as soon as it receives the bind req and strsock_proto()
   1032     0    stevel 	 * insists that SS_ACCEPTCONN is set when processing T_CONN_INDs.
   1033     0    stevel 	 */
   1034     0    stevel 	if (flags & _SOBIND_LISTEN) {
   1035     0    stevel 		if ((so->so_state & SS_ACCEPTCONN) == 0)
   1036     0    stevel 			clear_acceptconn_on_err = B_TRUE;
   1037     0    stevel 		save_so_backlog = so->so_backlog;
   1038     0    stevel 		restore_backlog_on_err = B_TRUE;
   1039     0    stevel 		so->so_state |= SS_ACCEPTCONN;
   1040     0    stevel 		so->so_backlog = backlog;
   1041     0    stevel 	}
   1042     0    stevel 
   1043     0    stevel 	/*
   1044     0    stevel 	 * If NL7C addr(s) have been configured check for addr/port match,
   1045     0    stevel 	 * or if an implicit NL7C socket via AF_NCA mark socket as NL7C.
   1046     0    stevel 	 *
   1047     0    stevel 	 * NL7C supports the TCP transport only so check AF_INET and AF_INET6
   1048     0    stevel 	 * family sockets only. If match mark as such.
   1049     0    stevel 	 */
   1050  1974    brutus 	if (nl7c_enabled && ((addr != NULL &&
   1051     0    stevel 	    (so->so_family == AF_INET || so->so_family == AF_INET6) &&
   1052     0    stevel 	    (nl7c = nl7c_lookup_addr(addr, addrlen))) ||
   1053  8348      Eric 	    sti->sti_nl7c_flags == NL7C_AF_NCA)) {
   1054     0    stevel 		/*
   1055     0    stevel 		 * NL7C is not supported in non-global zones,
   1056     0    stevel 		 * we enforce this restriction here.
   1057     0    stevel 		 */
   1058     0    stevel 		if (so->so_zoneid == GLOBAL_ZONEID) {
   1059     0    stevel 			/* An NL7C socket, mark it */
   1060  8348      Eric 			sti->sti_nl7c_flags |= NL7C_ENABLED;
   1061  1974    brutus 			if (nl7c == NULL) {
   1062  1974    brutus 				/*
   1063  1974    brutus 				 * Was an AF_NCA bind() so add it to the
   1064  1974    brutus 				 * addr list for reporting purposes.
   1065  1974    brutus 				 */
   1066  1974    brutus 				nl7c = nl7c_add_addr(addr, addrlen);
   1067  1974    brutus 			}
   1068     0    stevel 		} else
   1069     0    stevel 			nl7c = NULL;
   1070     0    stevel 	}
   1071  8348      Eric 
   1072     0    stevel 	/*
   1073     0    stevel 	 * We send a T_BIND_REQ for TCP/UDP since we know it supports it,
   1074     0    stevel 	 * for other transports we will send in a O_T_BIND_REQ.
   1075     0    stevel 	 */
   1076     0    stevel 	if (tcp_udp_xport &&
   1077     0    stevel 	    (so->so_family == AF_INET || so->so_family == AF_INET6))
   1078     0    stevel 		PRIM_type = T_BIND_REQ;
   1079     0    stevel 
   1080     0    stevel 	bind_req.PRIM_type = PRIM_type;
   1081     0    stevel 	bind_req.ADDR_length = addrlen;
   1082     0    stevel 	bind_req.ADDR_offset = (t_scalar_t)sizeof (bind_req);
   1083     0    stevel 	bind_req.CONIND_number = backlog;
   1084     0    stevel 	/* NOTE: holding so_lock while sleeping */
   1085     0    stevel 	mp = soallocproto2(&bind_req, sizeof (bind_req),
   1086  8778      Erik 	    addr, addrlen, 0, _ALLOC_SLEEP, cr);
   1087  8348      Eric 	sti->sti_laddr_valid = 0;
   1088  8348      Eric 
   1089  8348      Eric 	/* Done using sti_laddr_sa - can drop the lock */
   1090     0    stevel 	mutex_exit(&so->so_lock);
   1091   898      kais 
   1092   898      kais 	/*
   1093   898      kais 	 * Intercept the bind_req message here to check if this <address/port>
   1094   898      kais 	 * was configured as an SSL proxy server, or if another endpoint was
   1095   898      kais 	 * already configured to act as a proxy for us.
   1096  1974    brutus 	 *
   1097  1974    brutus 	 * Note, only if NL7C not enabled for this socket.
   1098  1974    brutus 	 */
   1099  1974    brutus 	if (nl7c == NULL &&
   1100  1974    brutus 	    (so->so_family == AF_INET || so->so_family == AF_INET6) &&
   1101   898      kais 	    so->so_type == SOCK_STREAM) {
   1102   898      kais 
   1103  8348      Eric 		if (sti->sti_kssl_ent != NULL) {
   1104  8348      Eric 			kssl_release_ent(sti->sti_kssl_ent, so,
   1105  8348      Eric 			    sti->sti_kssl_type);
   1106  8348      Eric 			sti->sti_kssl_ent = NULL;
   1107  8348      Eric 		}
   1108  8348      Eric 
   1109  8348      Eric 		sti->sti_kssl_type = kssl_check_proxy(mp, so,
   1110  8348      Eric 		    &sti->sti_kssl_ent);
   1111  8348      Eric 		switch (sti->sti_kssl_type) {
   1112   898      kais 		case KSSL_NO_PROXY:
   1113   898      kais 			break;
   1114   898      kais 
   1115   898      kais 		case KSSL_HAS_PROXY:
   1116   898      kais 			mutex_enter(&so->so_lock);
   1117   898      kais 			goto skip_transport;
   1118   898      kais 
   1119   898      kais 		case KSSL_IS_PROXY:
   1120   898      kais 			break;
   1121   898      kais 		}
   1122   898      kais 	}
   1123     0    stevel 
   1124     0    stevel 	error = kstrputmsg(SOTOV(so), mp, NULL, 0, 0,
   1125  5240  nordmark 	    MSG_BAND|MSG_HOLDSIG|MSG_IGNERROR, 0);
   1126     0    stevel 	if (error) {
   1127     0    stevel 		eprintsoline(so, error);
   1128     0    stevel 		mutex_enter(&so->so_lock);
   1129     0    stevel 		goto done;
   1130     0    stevel 	}
   1131     0    stevel 
   1132     0    stevel 	mutex_enter(&so->so_lock);
   1133     0    stevel 	error = sowaitprim(so, PRIM_type, T_BIND_ACK,
   1134     0    stevel 	    (t_uscalar_t)sizeof (*bind_ack), &mp, 0);
   1135     0    stevel 	if (error) {
   1136     0    stevel 		eprintsoline(so, error);
   1137     0    stevel 		goto done;
   1138     0    stevel 	}
   1139   898      kais skip_transport:
   1140     0    stevel 	ASSERT(mp);
   1141     0    stevel 	/*
   1142     0    stevel 	 * Even if some TPI message (e.g. T_DISCON_IND) was received in
   1143     0    stevel 	 * strsock_proto while the lock was dropped above, the bind
   1144     0    stevel 	 * is allowed to complete.
   1145     0    stevel 	 */
   1146     0    stevel 
   1147     0    stevel 	/* Mark as bound. This will be undone if we detect errors below. */
   1148     0    stevel 	if (flags & _SOBIND_NOXLATE) {
   1149     0    stevel 		ASSERT(so->so_family == AF_UNIX);
   1150  8348      Eric 		sti->sti_faddr_noxlate = 1;
   1151     0    stevel 	}
   1152     0    stevel 	ASSERT(!(so->so_state & SS_ISBOUND) || (flags & _SOBIND_REBIND));
   1153     0    stevel 	so->so_state |= SS_ISBOUND;
   1154  8348      Eric 	ASSERT(sti->sti_unbind_mp);
   1155     0    stevel 
   1156     0    stevel 	/* note that we've already set SS_ACCEPTCONN above */
   1157     0    stevel 
   1158     0    stevel 	/*
   1159     0    stevel 	 * Recompute addrlen - an unspecied bind sent down an
   1160     0    stevel 	 * address of length zero but we expect the appropriate length
   1161     0    stevel 	 * in return.
   1162     0    stevel 	 */
   1163     0    stevel 	addrlen = (t_uscalar_t)(so->so_family == AF_UNIX ?
   1164  8348      Eric 	    sizeof (sti->sti_ux_laddr) : sti->sti_laddr_len);
   1165     0    stevel 
   1166     0    stevel 	bind_ack = (struct T_bind_ack *)mp->b_rptr;
   1167     0    stevel 	/*
   1168     0    stevel 	 * The alignment restriction is really too strict but
   1169     0    stevel 	 * we want enough alignment to inspect the fields of
   1170     0    stevel 	 * a sockaddr_in.
   1171     0    stevel 	 */
   1172     0    stevel 	addr = sogetoff(mp, bind_ack->ADDR_offset,
   1173  5240  nordmark 	    bind_ack->ADDR_length,
   1174  5240  nordmark 	    __TPI_ALIGN_SIZE);
   1175     0    stevel 	if (addr == NULL) {
   1176     0    stevel 		freemsg(mp);
   1177     0    stevel 		error = EPROTO;
   1178     0    stevel 		eprintsoline(so, error);
   1179     0    stevel 		goto done;
   1180     0    stevel 	}
   1181     0    stevel 	if (!(flags & _SOBIND_UNSPEC)) {
   1182     0    stevel 		/*
   1183     0    stevel 		 * Verify that the transport didn't return something we
   1184     0    stevel 		 * did not want e.g. an address other than what we asked for.
   1185     0    stevel 		 *
   1186     0    stevel 		 * NOTE: These checks would go away if/when we switch to
   1187     0    stevel 		 * using the new TPI (in which the transport would fail
   1188     0    stevel 		 * the request instead of assigning a different address).
   1189     0    stevel 		 *
   1190     0    stevel 		 * NOTE2: For protocols that we don't know (i.e. any
   1191     0    stevel 		 * other than AF_INET6, AF_INET and AF_UNIX), we
   1192     0    stevel 		 * cannot know if the transport should be expected to
   1193     0    stevel 		 * return the same address as that requested.
   1194     0    stevel 		 *
   1195     0    stevel 		 * NOTE3: For AF_INET and AF_INET6, TCP/UDP, we send
   1196     0    stevel 		 * down a T_BIND_REQ. We use O_T_BIND_REQ for others.
   1197     0    stevel 		 *
   1198     0    stevel 		 * For example, in the case of netatalk it may be
   1199     0    stevel 		 * inappropriate for the transport to return the
   1200     0    stevel 		 * requested address (as it may have allocated a local
   1201     0    stevel 		 * port number in behaviour similar to that of an
   1202     0    stevel 		 * AF_INET bind request with a port number of zero).
   1203     0    stevel 		 *
   1204     0    stevel 		 * Given the definition of O_T_BIND_REQ, where the
   1205     0    stevel 		 * transport may bind to an address other than the
   1206     0    stevel 		 * requested address, it's not possible to determine
   1207     0    stevel 		 * whether a returned address that differs from the
   1208     0    stevel 		 * requested address is a reason to fail (because the
   1209     0    stevel 		 * requested address was not available) or succeed
   1210     0    stevel 		 * (because the transport allocated an appropriate
   1211     0    stevel 		 * address and/or port).
   1212     0    stevel 		 *
   1213     0    stevel 		 * sockfs currently requires that the transport return
   1214     0    stevel 		 * the requested address in the T_BIND_ACK, unless
   1215     0    stevel 		 * there is code here to allow for any discrepancy.
   1216     0    stevel 		 * Such code exists for AF_INET and AF_INET6.
   1217     0    stevel 		 *
   1218     0    stevel 		 * Netatalk chooses to return the requested address
   1219     0    stevel 		 * rather than the (correct) allocated address.  This
   1220     0    stevel 		 * means that netatalk violates the TPI specification
   1221     0    stevel 		 * (and would not function correctly if used from a
   1222     0    stevel 		 * TLI application), but it does mean that it works
   1223     0    stevel 		 * with sockfs.
   1224     0    stevel 		 *
   1225     0    stevel 		 * As noted above, using the newer XTI bind primitive
   1226     0    stevel 		 * (T_BIND_REQ) in preference to O_T_BIND_REQ would
   1227     0    stevel 		 * allow sockfs to be more sure about whether or not
   1228     0    stevel 		 * the bind request had succeeded (as transports are
   1229     0    stevel 		 * not permitted to bind to a different address than
   1230     0    stevel 		 * that requested - they must return failure).
   1231     0    stevel 		 * Unfortunately, support for T_BIND_REQ may not be
   1232     0    stevel 		 * present in all transport implementations (netatalk,
   1233     0    stevel 		 * for example, doesn't have it), making the
   1234     0    stevel 		 * transition difficult.
   1235     0    stevel 		 */
   1236     0    stevel 		if (bind_ack->ADDR_length != addrlen) {
   1237     0    stevel 			/* Assumes that the requested address was in use */
   1238     0    stevel 			freemsg(mp);
   1239     0    stevel 			error = EADDRINUSE;
   1240     0    stevel 			eprintsoline(so, error);
   1241     0    stevel 			goto done;
   1242     0    stevel 		}
   1243     0    stevel 
   1244     0    stevel 		switch (so->so_family) {
   1245     0    stevel 		case AF_INET6:
   1246     0    stevel 		case AF_INET: {
   1247     0    stevel 			sin_t *rname, *aname;
   1248     0    stevel 
   1249     0    stevel 			rname = (sin_t *)addr;
   1250  8348      Eric 			aname = (sin_t *)sti->sti_laddr_sa;
   1251     0    stevel 
   1252     0    stevel 			/*
   1253     0    stevel 			 * Take advantage of the alignment
   1254     0    stevel 			 * of sin_port and sin6_port which fall
   1255     0    stevel 			 * in the same place in their data structures.
   1256     0    stevel 			 * Just use sin_port for either address family.
   1257     0    stevel 			 *
   1258     0    stevel 			 * This may become a problem if (heaven forbid)
   1259     0    stevel 			 * there's a separate ipv6port_reserved... :-P
   1260     0    stevel 			 *
   1261     0    stevel 			 * Binding to port 0 has the semantics of letting
   1262     0    stevel 			 * the transport bind to any port.
   1263     0    stevel 			 *
   1264     0    stevel 			 * If the transport is TCP or UDP since we had sent
   1265     0    stevel 			 * a T_BIND_REQ we would not get a port other than
   1266     0    stevel 			 * what we asked for.
   1267     0    stevel 			 */
   1268     0    stevel 			if (tcp_udp_xport) {
   1269     0    stevel 				/*
   1270     0    stevel 				 * Pick up the new port number if we bound to
   1271     0    stevel 				 * port 0.
   1272     0    stevel 				 */
   1273     0    stevel 				if (aname->sin_port == 0)
   1274     0    stevel 					aname->sin_port = rname->sin_port;
   1275  8348      Eric 				sti->sti_laddr_valid = 1;
   1276     0    stevel 				break;
   1277     0    stevel 			}
   1278     0    stevel 			if (aname->sin_port != 0 &&
   1279     0    stevel 			    aname->sin_port != rname->sin_port) {
   1280     0    stevel 				freemsg(mp);
   1281     0    stevel 				error = EADDRINUSE;
   1282     0    stevel 				eprintsoline(so, error);
   1283     0    stevel 				goto done;
   1284     0    stevel 			}
   1285     0    stevel 			/*
   1286     0    stevel 			 * Pick up the new port number if we bound to port 0.
   1287     0    stevel 			 */
   1288     0    stevel 			aname->sin_port = rname->sin_port;
   1289     0    stevel 
   1290     0    stevel 			/*
   1291     0    stevel 			 * Unfortunately, addresses aren't _quite_ the same.
   1292     0    stevel 			 */
   1293     0    stevel 			if (so->so_family == AF_INET) {
   1294     0    stevel 				if (aname->sin_addr.s_addr !=
   1295     0    stevel 				    rname->sin_addr.s_addr) {
   1296     0    stevel 					freemsg(mp);
   1297     0    stevel 					error = EADDRNOTAVAIL;
   1298     0    stevel 					eprintsoline(so, error);
   1299     0    stevel 					goto done;
   1300     0    stevel 				}
   1301     0    stevel 			} else {
   1302     0    stevel 				sin6_t *rname6 = (sin6_t *)rname;
   1303     0    stevel 				sin6_t *aname6 = (sin6_t *)aname;
   1304     0    stevel 
   1305     0    stevel 				if (!IN6_ARE_ADDR_EQUAL(&aname6->sin6_addr,
   1306     0    stevel 				    &rname6->sin6_addr)) {
   1307     0    stevel 					freemsg(mp);
   1308     0    stevel 					error = EADDRNOTAVAIL;
   1309     0    stevel 					eprintsoline(so, error);
   1310     0    stevel 					goto done;
   1311     0    stevel 				}
   1312     0    stevel 			}
   1313     0    stevel 			break;
   1314     0    stevel 		}
   1315     0    stevel 		case AF_UNIX:
   1316  8348      Eric 			if (bcmp(addr, &sti->sti_ux_laddr, addrlen) != 0) {
   1317     0    stevel 				freemsg(mp);
   1318     0    stevel 				error = EADDRINUSE;
   1319     0    stevel 				eprintsoline(so, error);
   1320     0    stevel 				eprintso(so,
   1321  5240  nordmark 				    ("addrlen %d, addr 0x%x, vp %p\n",
   1322  5240  nordmark 				    addrlen, *((int *)addr),
   1323  8348      Eric 				    (void *)sti->sti_ux_bound_vp));
   1324  8348      Eric 				goto done;
   1325  8348      Eric 			}
   1326  8348      Eric 			sti->sti_laddr_valid = 1;
   1327     0    stevel 			break;
   1328     0    stevel 		default:
   1329     0    stevel 			/*
   1330     0    stevel 			 * NOTE: This assumes that addresses can be
   1331     0    stevel 			 * byte-compared for equivalence.
   1332     0    stevel 			 */
   1333  8348      Eric 			if (bcmp(addr, sti->sti_laddr_sa, addrlen) != 0) {
   1334     0    stevel 				freemsg(mp);
   1335     0    stevel 				error = EADDRINUSE;
   1336     0    stevel 				eprintsoline(so, error);
   1337     0    stevel 				goto done;
   1338     0    stevel 			}
   1339     0    stevel 			/*
   1340  8348      Eric 			 * Don't mark sti_laddr_valid, as we cannot be
   1341     0    stevel 			 * sure that the returned address is the real
   1342     0    stevel 			 * bound address when talking to an unknown
   1343     0    stevel 			 * transport.
   1344     0    stevel 			 */
   1345     0    stevel 			break;
   1346     0    stevel 		}
   1347     0    stevel 	} else {
   1348     0    stevel 		/*
   1349     0    stevel 		 * Save for returned address for getsockname.
   1350     0    stevel 		 * Needed for unspecific bind unless transport supports
   1351     0    stevel 		 * the TI_GETMYNAME ioctl.
   1352     0    stevel 		 * Do this for AF_INET{,6} even though they do, as
   1353     0    stevel 		 * caching info here is much better performance than
   1354     0    stevel 		 * a TPI/STREAMS trip to the transport for getsockname.
   1355     0    stevel 		 * Any which can't for some reason _must_ _not_ set
   1356  8348      Eric 		 * sti_laddr_valid here for the caching version of
   1357  8348      Eric 		 * getsockname to not break;
   1358     0    stevel 		 */
   1359     0    stevel 		switch (so->so_family) {
   1360     0    stevel 		case AF_UNIX:
   1361     0    stevel 			/*
   1362     0    stevel 			 * Record the address bound with the transport
   1363     0    stevel 			 * for use by socketpair.
   1364     0    stevel 			 */
   1365  8348      Eric 			bcopy(addr, &sti->sti_ux_laddr, addrlen);
   1366  8348      Eric 			sti->sti_laddr_valid = 1;
   1367     0    stevel 			break;
   1368     0    stevel 		case AF_INET:
   1369     0    stevel 		case AF_INET6:
   1370  8348      Eric 			ASSERT(sti->sti_laddr_len <= sti->sti_laddr_maxlen);
   1371  8348      Eric 			bcopy(addr, sti->sti_laddr_sa, sti->sti_laddr_len);
   1372  8348      Eric 			sti->sti_laddr_valid = 1;
   1373     0    stevel 			break;
   1374     0    stevel 		default:
   1375     0    stevel 			/*
   1376  8348      Eric 			 * Don't mark sti_laddr_valid, as we cannot be
   1377     0    stevel 			 * sure that the returned address is the real
   1378     0    stevel 			 * bound address when talking to an unknown
   1379     0    stevel 			 * transport.
   1380     0    stevel 			 */
   1381     0    stevel 			break;
   1382     0    stevel 		}
   1383     0    stevel 	}
   1384     0    stevel 
   1385     0    stevel 	if (nl7c != NULL) {
   1386  1974    brutus 		/* Register listen()er sonode pointer with NL7C */
   1387  1974    brutus 		nl7c_listener_addr(nl7c, so);
   1388     0    stevel 	}
   1389     0    stevel 
   1390     0    stevel 	freemsg(mp);
   1391     0    stevel 
   1392     0    stevel done:
   1393     0    stevel 	if (error) {
   1394     0    stevel 		/* reset state & backlog to values held on entry */
   1395     0    stevel 		if (clear_acceptconn_on_err == B_TRUE)
   1396     0    stevel 			so->so_state &= ~SS_ACCEPTCONN;
   1397     0    stevel 		if (restore_backlog_on_err == B_TRUE)
   1398     0    stevel 			so->so_backlog = save_so_backlog;
   1399     0    stevel 
   1400     0    stevel 		if (unbind_on_err && so->so_state & SS_ISBOUND) {
   1401     0    stevel 			int err;
   1402     0    stevel 
   1403     0    stevel 			err = sotpi_unbind(so, 0);
   1404     0    stevel 			/* LINTED - statement has no consequent: if */
   1405     0    stevel 			if (err) {
   1406     0    stevel 				eprintsoline(so, error);
   1407     0    stevel 			} else {
   1408     0    stevel 				ASSERT(!(so->so_state & SS_ISBOUND));
   1409     0    stevel 			}
   1410     0    stevel 		}
   1411     0    stevel 	}
   1412     0    stevel 	if (!(flags & _SOBIND_LOCK_HELD)) {
   1413     0    stevel 		so_unlock_single(so, SOLOCKED);
   1414     0    stevel 		mutex_exit(&so->so_lock);
   1415     0    stevel 	} else {
   1416     0    stevel 		ASSERT(MUTEX_HELD(&so->so_lock));
   1417     0    stevel 		ASSERT(so->so_flag & SOLOCKED);
   1418     0    stevel 	}
   1419     0    stevel 	return (error);
   1420     0    stevel }
   1421     0    stevel 
   1422     0    stevel /* bind the socket */
   1423   741  masputra static int
   1424     0    stevel sotpi_bind(struct sonode *so, struct sockaddr *name, socklen_t namelen,
   1425  8348      Eric     int flags, struct cred *cr)
   1426     0    stevel {
   1427     0    stevel 	if ((flags & _SOBIND_SOCKETPAIR) == 0)
   1428  8348      Eric 		return (sotpi_bindlisten(so, name, namelen, 0, flags, cr));
   1429     0    stevel 
   1430     0    stevel 	flags &= ~_SOBIND_SOCKETPAIR;
   1431  8348      Eric 	return (sotpi_bindlisten(so, name, namelen, 1, flags, cr));
   1432     0    stevel }
   1433     0    stevel 
   1434     0    stevel /*
   1435     0    stevel  * Unbind a socket - used when bind() fails, when bind() specifies a NULL
   1436     0    stevel  * address, or when listen needs to unbind and bind.
   1437     0    stevel  * If the _SOUNBIND_REBIND flag is specified the addresses are retained
   1438     0    stevel  * so that a sobind can pick them up.
   1439     0    stevel  */
   1440     0    stevel static int
   1441     0    stevel sotpi_unbind(struct sonode *so, int flags)
   1442     0    stevel {
   1443     0    stevel 	struct T_unbind_req	unbind_req;
   1444     0    stevel 	int			error = 0;
   1445     0    stevel 	mblk_t			*mp;
   1446  8348      Eric 	sotpi_info_t		*sti = SOTOTPI(so);
   1447     0    stevel 
   1448     0    stevel 	dprintso(so, 1, ("sotpi_unbind(%p, 0x%x) %s\n",
   1449  7240   rh87107 	    (void *)so, flags, pr_state(so->so_state, so->so_mode)));
   1450     0    stevel 
   1451     0    stevel 	ASSERT(MUTEX_HELD(&so->so_lock));
   1452     0    stevel 	ASSERT(so->so_flag & SOLOCKED);
   1453     0    stevel 
   1454     0    stevel 	if (!(so->so_state & SS_ISBOUND)) {
   1455     0    stevel 		error = EINVAL;
   1456     0    stevel 		eprintsoline(so, error);
   1457     0    stevel 		goto done;
   1458     0    stevel 	}
   1459     0    stevel 
   1460     0    stevel 	mutex_exit(&so->so_lock);
   1461     0    stevel 
   1462     0    stevel 	/*
   1463     0    stevel 	 * Flush the read and write side (except stream head read queue)
   1464     0    stevel 	 * and send down T_UNBIND_REQ.
   1465     0    stevel 	 */
   1466     0    stevel 	(void) putnextctl1(strvp2wq(SOTOV(so)), M_FLUSH, FLUSHRW);
   1467     0    stevel 
   1468     0    stevel 	unbind_req.PRIM_type = T_UNBIND_REQ;
   1469     0    stevel 	mp = soallocproto1(&unbind_req, sizeof (unbind_req),
   1470  8778      Erik 	    0, _ALLOC_SLEEP, CRED());
   1471     0    stevel 	error = kstrputmsg(SOTOV(so), mp, NULL, 0, 0,
   1472  5240  nordmark 	    MSG_BAND|MSG_HOLDSIG|MSG_IGNERROR, 0);
   1473     0    stevel 	mutex_enter(&so->so_lock);
   1474     0    stevel 	if (error) {
   1475     0    stevel 		eprintsoline(so, error);
   1476     0    stevel 		goto done;
   1477     0    stevel 	}
   1478     0    stevel 
   1479     0    stevel 	error = sowaitokack(so, T_UNBIND_REQ);
   1480     0    stevel 	if (error) {
   1481     0    stevel 		eprintsoline(so, error);
   1482     0    stevel 		goto done;
   1483     0    stevel 	}
   1484     0    stevel 
   1485     0    stevel 	/*
   1486     0    stevel 	 * Even if some TPI message (e.g. T_DISCON_IND) was received in
   1487     0    stevel 	 * strsock_proto while the lock was dropped above, the unbind
   1488     0    stevel 	 * is allowed to complete.
   1489     0    stevel 	 */
   1490     0    stevel 	if (!(flags & _SOUNBIND_REBIND)) {
   1491     0    stevel 		/*
   1492     0    stevel 		 * Clear out bound address.
   1493     0    stevel 		 */
   1494     0    stevel 		vnode_t *vp;
   1495     0    stevel 
   1496  8348      Eric 		if ((vp = sti->sti_ux_bound_vp) != NULL) {
   1497   898      kais 
   1498   898      kais 			/* Undo any SSL proxy setup */
   1499   898      kais 			if ((so->so_family == AF_INET ||
   1500   898      kais 			    so->so_family == AF_INET6) &&
   1501   898      kais 			    (so->so_type == SOCK_STREAM) &&
   1502  8348      Eric 			    (sti->sti_kssl_ent != NULL)) {
   1503  8348      Eric 				kssl_release_ent(sti->sti_kssl_ent, so,
   1504  8348      Eric 				    sti->sti_kssl_type);
   1505  8348      Eric 				sti->sti_kssl_ent = NULL;
   1506  8348      Eric 				sti->sti_kssl_type = KSSL_NO_PROXY;
   1507  8348      Eric 			}
   1508  8348      Eric 			sti->sti_ux_bound_vp = NULL;
   1509     0    stevel 			vn_rele_stream(vp);
   1510     0    stevel 		}
   1511     0    stevel 		/* Clear out address */
   1512  8348      Eric 		sti->sti_laddr_len = 0;
   1513  8348      Eric 	}
   1514  8348      Eric 	so->so_state &= ~(SS_ISBOUND|SS_ACCEPTCONN);
   1515  8348      Eric 	sti->sti_laddr_valid = 0;
   1516  1974    brutus 
   1517     0    stevel done:
   1518   898      kais 
   1519     0    stevel 	/* If the caller held the lock don't release it here */
   1520     0    stevel 	ASSERT(MUTEX_HELD(&so->so_lock));
   1521     0    stevel 	ASSERT(so->so_flag & SOLOCKED);
   1522     0    stevel 
   1523     0    stevel 	return (error);
   1524     0    stevel }
   1525     0    stevel 
   1526     0    stevel /*
   1527     0    stevel  * listen on the socket.
   1528     0    stevel  * For TPI conforming transports this has to first unbind with the transport
   1529     0    stevel  * and then bind again using the new backlog.
   1530     0    stevel  */
   1531  8348      Eric /* ARGSUSED */
   1532  8348      Eric int
   1533  8348      Eric sotpi_listen(struct sonode *so, int backlog, struct cred *cr)
   1534     0    stevel {
   1535     0    stevel 	int		error = 0;
   1536  8348      Eric 	sotpi_info_t	*sti = SOTOTPI(so);
   1537     0    stevel 
   1538     0    stevel 	dprintso(so, 1, ("sotpi_listen(%p, %d) %s\n",
   1539  7240   rh87107 	    (void *)so, backlog, pr_state(so->so_state, so->so_mode)));
   1540     0    stevel 
   1541  8348      Eric 	if (sti->sti_serv_type == T_CLTS)
   1542     0    stevel 		return (EOPNOTSUPP);
   1543     0    stevel 
   1544     0    stevel 	/*
   1545     0    stevel 	 * If the socket is ready to accept connections already, then
   1546     0    stevel 	 * return without doing anything.  This avoids a problem where
   1547     0    stevel 	 * a second listen() call fails if a connection is pending and
   1548     0    stevel 	 * leaves the socket unbound. Only when we are not unbinding
   1549     0    stevel 	 * with the transport can we safely increase the backlog.
   1550     0    stevel 	 */
   1551     0    stevel 	if (so->so_state & SS_ACCEPTCONN &&
   1552     0    stevel 	    !((so->so_family == AF_INET || so->so_family == AF_INET6) &&
   1553  5240  nordmark 	    /*CONSTCOND*/
   1554  5240  nordmark 	    !solisten_tpi_tcp))
   1555     0    stevel 		return (0);
   1556     0    stevel 
   1557     0    stevel 	if (so->so_state & SS_ISCONNECTED)
   1558     0    stevel 		return (EINVAL);
   1559     0    stevel 
   1560     0    stevel 	mutex_enter(&so->so_lock);
   1561     0    stevel 	so_lock_single(so);	/* Set SOLOCKED */
   1562     0    stevel 
   1563     0    stevel 	/*
   1564     0    stevel 	 * If the listen doesn't change the backlog we do nothing.
   1565     0    stevel 	 * This avoids an EPROTO error from the transport.
   1566     0    stevel 	 */
   1567     0    stevel 	if ((so->so_state & SS_ACCEPTCONN) &&
   1568     0    stevel 	    so->so_backlog == backlog)
   1569     0    stevel 		goto done;
   1570     0    stevel 
   1571     0    stevel 	if (!(so->so_state & SS_ISBOUND)) {
   1572     0    stevel 		/*
   1573     0    stevel 		 * Must have been explicitly bound in the UNIX domain.
   1574     0    stevel 		 */
   1575     0    stevel 		if (so->so_family == AF_UNIX) {
   1576     0    stevel 			error = EINVAL;
   1577     0    stevel 			goto done;
   1578     0    stevel 		}
   1579     0    stevel 		error = sotpi_bindlisten(so, NULL, 0, backlog,
   1580  8348      Eric 		    _SOBIND_UNSPEC|_SOBIND_LOCK_HELD|_SOBIND_LISTEN, cr);
   1581     0    stevel 	} else if (backlog > 0) {
   1582     0    stevel 		/*
   1583     0    stevel 		 * AF_INET{,6} hack to avoid losing the port.
   1584     0    stevel 		 * Assumes that all AF_INET{,6} transports can handle a
   1585     0    stevel 		 * O_T_BIND_REQ with a non-zero CONIND_number when the TPI
   1586     0    stevel 		 * has already bound thus it is possible to avoid the unbind.
   1587     0    stevel 		 */
   1588     0    stevel 		if (!((so->so_family == AF_INET || so->so_family == AF_INET6) &&
   1589     0    stevel 		    /*CONSTCOND*/
   1590     0    stevel 		    !solisten_tpi_tcp)) {
   1591     0    stevel 			error = sotpi_unbind(so, _SOUNBIND_REBIND);
   1592     0    stevel 			if (error)
   1593     0    stevel 				goto done;
   1594     0    stevel 		}
   1595     0    stevel 		error = sotpi_bindlisten(so, NULL, 0, backlog,
   1596  8348      Eric 		    _SOBIND_REBIND|_SOBIND_LOCK_HELD|_SOBIND_LISTEN, cr);
   1597     0    stevel 	} else {
   1598     0    stevel 		so->so_state |= SS_ACCEPTCONN;
   1599     0    stevel 		so->so_backlog = backlog;
   1600     0    stevel 	}
   1601     0    stevel 	if (error)
   1602     0    stevel 		goto done;
   1603     0    stevel 	ASSERT(so->so_state & SS_ACCEPTCONN);
   1604     0    stevel done:
   1605     0    stevel 	so_unlock_single(so, SOLOCKED);
   1606     0    stevel 	mutex_exit(&so->so_lock);
   1607     0    stevel 	return (error);
   1608     0    stevel }
   1609     0    stevel 
   1610     0    stevel /*
   1611     0    stevel  * Disconnect either a specified seqno or all (-1).
   1612     0    stevel  * The former is used on listening sockets only.
   1613     0    stevel  *
   1614     0    stevel  * When seqno == -1 sodisconnect could call sotpi_unbind. However,
   1615     0    stevel  * the current use of sodisconnect(seqno == -1) is only for shutdown
   1616     0    stevel  * so there is no point (and potentially incorrect) to unbind.
   1617     0    stevel  */
   1618  8348      Eric static int
   1619     0    stevel sodisconnect(struct sonode *so, t_scalar_t seqno, int flags)
   1620     0    stevel {
   1621     0    stevel 	struct T_discon_req	discon_req;
   1622     0    stevel 	int			error = 0;
   1623     0    stevel 	mblk_t			*mp;
   1624     0    stevel 
   1625     0    stevel 	dprintso(so, 1, ("sodisconnect(%p, %d, 0x%x) %s\n",
   1626  7240   rh87107 	    (void *)so, seqno, flags, pr_state(so->so_state, so->so_mode)));
   1627     0    stevel 
   1628     0    stevel 	if (!(flags & _SODISCONNECT_LOCK_HELD)) {
   1629     0    stevel 		mutex_enter(&so->so_lock);
   1630     0    stevel 		so_lock_single(so);	/* Set SOLOCKED */
   1631     0    stevel 	} else {
   1632     0    stevel 		ASSERT(MUTEX_HELD(&so->so_lock));
   1633     0    stevel 		ASSERT(so->so_flag & SOLOCKED);
   1634     0    stevel 	}
   1635     0    stevel 
   1636     0    stevel 	if (!(so->so_state & (SS_ISCONNECTED|SS_ISCONNECTING|SS_ACCEPTCONN))) {
   1637     0    stevel 		error = EINVAL;
   1638     0    stevel 		eprintsoline(so, error);
   1639     0    stevel 		goto done;
   1640     0    stevel 	}
   1641     0    stevel 
   1642     0    stevel 	mutex_exit(&so->so_lock);
   1643     0    stevel 	/*
   1644     0    stevel 	 * Flush the write side (unless this is a listener)
   1645     0    stevel 	 * and then send down a T_DISCON_REQ.
   1646     0    stevel 	 * (Don't flush on listener since it could flush {O_}T_CONN_RES
   1647     0    stevel 	 * and other messages.)
   1648     0    stevel 	 */
   1649     0    stevel 	if (!(so->so_state & SS_ACCEPTCONN))
   1650     0    stevel 		(void) putnextctl1(strvp2wq(SOTOV(so)), M_FLUSH, FLUSHW);
   1651     0    stevel 
   1652     0    stevel 	discon_req.PRIM_type = T_DISCON_REQ;
   1653     0    stevel 	discon_req.SEQ_number = seqno;
   1654     0    stevel 	mp = soallocproto1(&discon_req, sizeof (discon_req),
   1655  8778      Erik 	    0, _ALLOC_SLEEP, CRED());
   1656     0    stevel 	error = kstrputmsg(SOTOV(so), mp, NULL, 0, 0,
   1657  5240  nordmark 	    MSG_BAND|MSG_HOLDSIG|MSG_IGNERROR, 0);
   1658     0    stevel 	mutex_enter(&so->so_lock);
   1659     0    stevel 	if (error) {
   1660     0    stevel 		eprintsoline(so, error);
   1661     0    stevel 		goto done;
   1662     0    stevel 	}
   1663     0    stevel 
   1664     0    stevel 	error = sowaitokack(so, T_DISCON_REQ);
   1665     0    stevel 	if (error) {
   1666     0    stevel 		eprintsoline(so, error);
   1667     0    stevel 		goto done;
   1668     0    stevel 	}
   1669     0    stevel 	/*
   1670     0    stevel 	 * Even if some TPI message (e.g. T_DISCON_IND) was received in
   1671     0    stevel 	 * strsock_proto while the lock was dropped above, the disconnect
   1672     0    stevel 	 * is allowed to complete. However, it is not possible to
   1673     0    stevel 	 * assert that SS_ISCONNECTED|SS_ISCONNECTING are set.
   1674     0    stevel 	 */
   1675  8348      Eric 	so->so_state &= ~(SS_ISCONNECTED|SS_ISCONNECTING);
   1676  8348      Eric 	SOTOTPI(so)->sti_laddr_valid = 0;
   1677  8348      Eric 	SOTOTPI(so)->sti_faddr_valid = 0;
   1678     0    stevel done:
   1679     0    stevel 	if (!(flags & _SODISCONNECT_LOCK_HELD)) {
   1680     0    stevel 		so_unlock_single(so, SOLOCKED);
   1681     0    stevel 		mutex_exit(&so->so_lock);
   1682     0    stevel 	} else {
   1683     0    stevel 		/* If the caller held the lock don't release it here */
   1684     0    stevel 		ASSERT(MUTEX_HELD(&so->so_lock));
   1685     0    stevel 		ASSERT(so->so_flag & SOLOCKED);
   1686     0    stevel 	}
   1687     0    stevel 	return (error);
   1688     0    stevel }
   1689     0    stevel 
   1690  8348      Eric /* ARGSUSED */
   1691  8348      Eric int
   1692  8348      Eric sotpi_accept(struct sonode *so, int fflag, struct cred *cr,
   1693  8348      Eric     struct sonode **nsop)
   1694     0    stevel {
   1695     0    stevel 	struct T_conn_ind	*conn_ind;
   1696     0    stevel 	struct T_conn_res	*conn_res;
   1697     0    stevel 	int			error = 0;
   1698  4379   ja97890 	mblk_t			*mp, *ctxmp, *ack_mp;
   1699     0    stevel 	struct sonode		*nso;
   1700     0    stevel 	vnode_t			*nvp;
   1701     0    stevel 	void			*src;
   1702     0    stevel 	t_uscalar_t		srclen;
   1703     0    stevel 	void			*opt;
   1704     0    stevel 	t_uscalar_t		optlen;
   1705     0    stevel 	t_scalar_t		PRIM_type;
   1706     0    stevel 	t_scalar_t		SEQ_number;
   1707  4379   ja97890 	size_t			sinlen;
   1708  8348      Eric 	sotpi_info_t		*sti = SOTOTPI(so);
   1709  8348      Eric 	sotpi_info_t		*nsti;
   1710     0    stevel 
   1711     0    stevel 	dprintso(so, 1, ("sotpi_accept(%p, 0x%x, %p) %s\n",
   1712  7240   rh87107 	    (void *)so, fflag, (void *)nsop,
   1713  7240   rh87107 	    pr_state(so->so_state, so->so_mode)));
   1714     0    stevel 
   1715     0    stevel 	/*
   1716     0    stevel 	 * Defer single-threading the accepting socket until
   1717     0    stevel 	 * the T_CONN_IND has been received and parsed and the
   1718     0    stevel 	 * new sonode has been opened.
   1719     0    stevel 	 */
   1720     0    stevel 
   1721     0    stevel 	/* Check that we are not already connected */
   1722     0    stevel 	if ((so->so_state & SS_ACCEPTCONN) == 0)
   1723     0    stevel 		goto conn_bad;
   1724     0    stevel again:
   1725     0    stevel 	if ((error = sowaitconnind(so, fflag, &mp)) != 0)
   1726     0    stevel 		goto e_bad;
   1727     0    stevel 
   1728  8348      Eric 	ASSERT(mp != NULL);
   1729     0    stevel 	conn_ind = (struct T_conn_ind *)mp->b_rptr;
   1730   898      kais 	ctxmp = mp->b_cont;
   1731   898      kais 
   1732     0    stevel 	/*
   1733     0    stevel 	 * Save SEQ_number for error paths.
   1734     0    stevel 	 */
   1735     0    stevel 	SEQ_number = conn_ind->SEQ_number;
   1736     0    stevel 
   1737     0    stevel 	srclen = conn_ind->SRC_length;
   1738     0    stevel 	src = sogetoff(mp, conn_ind->SRC_offset, srclen, 1);
   1739     0    stevel 	if (src == NULL) {
   1740     0    stevel 		error = EPROTO;
   1741     0    stevel 		freemsg(mp);
   1742     0    stevel 		eprintsoline(so, error);
   1743     0    stevel 		goto disconnect_unlocked;
   1744     0    stevel 	}
   1745     0    stevel 	optlen = conn_ind->OPT_length;
   1746     0    stevel 	switch (so->so_family) {
   1747     0    stevel 	case AF_INET:
   1748     0    stevel 	case AF_INET6:
   1749  8348      Eric 		if ((optlen == sizeof (intptr_t)) && (sti->sti_direct != 0)) {
   1750     0    stevel 			bcopy(mp->b_rptr + conn_ind->OPT_offset,
   1751     0    stevel 			    &opt, conn_ind->OPT_length);
   1752     0    stevel 		} else {
   1753     0    stevel 			/*
   1754     0    stevel 			 * The transport (in this case TCP) hasn't sent up
   1755     0    stevel 			 * a pointer to an instance for the accept fast-path.
   1756     0    stevel 			 * Disable fast-path completely because the call to
   1757     0    stevel 			 * sotpi_create() below would otherwise create an
   1758     0    stevel 			 * incomplete TCP instance, which would lead to
   1759     0    stevel 			 * problems when sockfs sends a normal T_CONN_RES
   1760     0    stevel 			 * message down the new stream.
   1761     0    stevel 			 */
   1762  8348      Eric 			if (sti->sti_direct) {
   1763   741  masputra 				int rval;
   1764   741  masputra 				/*
   1765   741  masputra 				 * For consistency we inform tcp to disable
   1766   741  masputra 				 * direct interface on the listener, though
   1767   741  masputra 				 * we can certainly live without doing this
   1768   741  masputra 				 * because no data will ever travel upstream
   1769   741  masputra 				 * on the listening socket.
   1770   741  masputra 				 */
   1771  8348      Eric 				sti->sti_direct = 0;
   1772   741  masputra 				(void) strioctl(SOTOV(so), _SIOCSOCKFALLBACK,
   1773  8778      Erik 				    0, 0, K_TO_K, cr, &rval);
   1774   741  masputra 			}
   1775     0    stevel 			opt = NULL;
   1776     0    stevel 			optlen = 0;
   1777     0    stevel 		}
   1778     0    stevel 		break;
   1779     0    stevel 	case AF_UNIX:
   1780     0    stevel 	default:
   1781     0    stevel 		if (optlen != 0) {
   1782     0    stevel 			opt = sogetoff(mp, conn_ind->OPT_offset, optlen,
   1783     0    stevel 			    __TPI_ALIGN_SIZE);
   1784     0    stevel 			if (opt == NULL) {
   1785     0    stevel 				error = EPROTO;
   1786     0    stevel 				freemsg(mp);
   1787     0    stevel 				eprintsoline(so, error);
   1788     0    stevel 				goto disconnect_unlocked;
   1789     0    stevel 			}
   1790     0    stevel 		}
   1791     0    stevel 		if (so->so_family == AF_UNIX) {
   1792  8348      Eric 			if (!sti->sti_faddr_noxlate) {
   1793     0    stevel 				src = NULL;
   1794     0    stevel 				srclen = 0;
   1795     0    stevel 			}
   1796     0    stevel 			/* Extract src address from options */
   1797     0    stevel 			if (optlen != 0)
   1798     0    stevel 				so_getopt_srcaddr(opt, optlen, &src, &srclen);
   1799     0    stevel 		}
   1800     0    stevel 		break;
   1801     0    stevel 	}
   1802     0    stevel 
   1803     0    stevel 	/*
   1804     0    stevel 	 * Create the new socket.
   1805     0    stevel 	 */
   1806  8348      Eric 	nso = socket_newconn(so, NULL, NULL, SOCKET_SLEEP, &error);
   1807     0    stevel 	if (nso == NULL) {
   1808     0    stevel 		ASSERT(error != 0);
   1809     0    stevel 		/*
   1810     0    stevel 		 * Accept can not fail with ENOBUFS. sotpi_create
   1811     0    stevel 		 * sleeps waiting for memory until a signal is caught
   1812     0    stevel 		 * so return EINTR.
   1813     0    stevel 		 */
   1814     0    stevel 		freemsg(mp);
   1815     0    stevel 		if (error == ENOBUFS)
   1816     0    stevel 			error = EINTR;
   1817     0    stevel 		goto e_disc_unl;
   1818     0    stevel 	}
   1819     0    stevel 	nvp = SOTOV(nso);
   1820  8348      Eric 	nsti = SOTOTPI(nso);
   1821     0    stevel 
   1822   898      kais 	/*
   1823   898      kais 	 * If the transport sent up an SSL connection context, then attach
   1824   898      kais 	 * it the new socket, and set the (sd_wputdatafunc)() and
   1825   898      kais 	 * (sd_rputdatafunc)() stream head hooks to intercept and process
   1826   898      kais 	 * SSL records.
   1827   898      kais 	 */
   1828   898      kais 	if (ctxmp != NULL) {
   1829   898      kais 		/*
   1830   898      kais 		 * This kssl_ctx_t is already held for us by the transport.
   1831   898      kais 		 * So, we don't need to do a kssl_hold_ctx() here.
   1832   898      kais 		 */
   1833  8348      Eric 		nsti->sti_kssl_ctx = *((kssl_ctx_t *)ctxmp->b_rptr);
   1834   898      kais 		freemsg(ctxmp);
   1835   898      kais 		mp->b_cont = NULL;
   1836   898      kais 		strsetrwputdatahooks(nvp, strsock_kssl_input,
   1837   898      kais 		    strsock_kssl_output);
   1838   898      kais 	}
   1839     0    stevel #ifdef DEBUG
   1840     0    stevel 	/*
   1841     0    stevel 	 * SO_DEBUG is used to trigger the dprint* and eprint* macros thus
   1842     0    stevel 	 * it's inherited early to allow debugging of the accept code itself.
   1843     0    stevel 	 */
   1844     0    stevel 	nso->so_options |= so->so_options & SO_DEBUG;
   1845     0    stevel #endif /* DEBUG */
   1846     0    stevel 
   1847     0    stevel 	/*
   1848     0    stevel 	 * Save the SRC address from the T_CONN_IND
   1849     0    stevel 	 * for getpeername to work on AF_UNIX and on transports that do not
   1850     0    stevel 	 * support TI_GETPEERNAME.
   1851     0    stevel 	 *
   1852     0    stevel 	 * NOTE: AF_UNIX NUL termination is ensured by the sender's
   1853     0    stevel 	 * copyin_name().
   1854     0    stevel 	 */
   1855  8348      Eric 	if (srclen > (t_uscalar_t)nsti->sti_faddr_maxlen) {
   1856     0    stevel 		error = EINVAL;
   1857     0    stevel 		freemsg(mp);
   1858     0    stevel 		eprintsoline(so, error);
   1859     0    stevel 		goto disconnect_vp_unlocked;
   1860     0    stevel 	}
   1861  8348      Eric 	nsti->sti_faddr_len = (socklen_t)srclen;
   1862  8348      Eric 	ASSERT(sti->sti_faddr_len <= sti->sti_faddr_maxlen);
   1863  8348      Eric 	bcopy(src, nsti->sti_faddr_sa, srclen);
   1864  8348      Eric 	nsti->sti_faddr_valid = 1;
   1865     0    stevel 
   1866  8778      Erik 	/*
   1867  8778      Erik 	 * Record so_peercred and so_cpid from a cred in the T_CONN_IND.
   1868  8778      Erik 	 */
   1869     0    stevel 	if ((DB_REF(mp) > 1) || MBLKSIZE(mp) <
   1870     0    stevel 	    (sizeof (struct T_conn_res) + sizeof (intptr_t))) {
   1871  8778      Erik 		cred_t	*cr;
   1872  8778      Erik 		pid_t	cpid;
   1873  8778      Erik 
   1874  8778      Erik 		cr = msg_getcred(mp, &cpid);
   1875  8778      Erik 		if (cr != NULL) {
   1876     0    stevel 			crhold(cr);
   1877     0    stevel 			nso->so_peercred = cr;
   1878  8778      Erik 			nso->so_cpid = cpid;
   1879     0    stevel 		}
   1880     0    stevel 		freemsg(mp);
   1881     0    stevel 
   1882     0    stevel 		mp = soallocproto1(NULL, sizeof (struct T_conn_res) +
   1883  8965    Anders 		    sizeof (intptr_t), 0, _ALLOC_INTR, cr);
   1884     0    stevel 		if (mp == NULL) {
   1885     0    stevel 			/*
   1886     0    stevel 			 * Accept can not fail with ENOBUFS.
   1887     0    stevel 			 * A signal was caught so return EINTR.
   1888     0    stevel 			 */
   1889     0    stevel 			error = EINTR;
   1890     0    stevel 			eprintsoline(so, error);
   1891     0    stevel 			goto disconnect_vp_unlocked;
   1892     0    stevel 		}
   1893     0    stevel 		conn_res = (struct T_conn_res *)mp->b_rptr;
   1894     0    stevel 	} else {
   1895  8778      Erik 		/*
   1896  8778      Erik 		 * For efficency reasons we use msg_extractcred; no crhold
   1897  8778      Erik 		 * needed since db_credp is cleared (i.e., we move the cred
   1898  8778      Erik 		 * from the message to so_peercred.
   1899  8778      Erik 		 */
   1900  8778      Erik 		nso->so_peercred = msg_extractcred(mp, &nso->so_cpid);
   1901     0    stevel 
   1902     0    stevel 		mp->b_rptr = DB_BASE(mp);
   1903     0    stevel 		conn_res = (struct T_conn_res *)mp->b_rptr;
   1904     0    stevel 		mp->b_wptr = mp->b_rptr + sizeof (struct T_conn_res);
   1905  8965    Anders 
   1906  8965    Anders 		mblk_setcred(mp, cr, curproc->p_pid);
   1907     0    stevel 	}
   1908     0    stevel 
   1909     0    stevel 	/*
   1910     0    stevel 	 * New socket must be bound at least in sockfs and, except for AF_INET,
   1911     0    stevel 	 * (or AF_INET6) it also has to be bound in the transport provider.
   1912  4379   ja97890 	 * We set the local address in the sonode from the T_OK_ACK of the
   1913  4379   ja97890 	 * T_CONN_RES. For this reason the address we bind to here isn't
   1914  4379   ja97890 	 * important.
   1915     0    stevel 	 */
   1916     0    stevel 	if ((nso->so_family == AF_INET || nso->so_family == AF_INET6) &&
   1917     0    stevel 	    /*CONSTCOND*/
   1918     0    stevel 	    nso->so_type == SOCK_STREAM && !soaccept_tpi_tcp) {
   1919     0    stevel 		/*
   1920     0    stevel 		 * Optimization for AF_INET{,6} transports
   1921     0    stevel 		 * that can handle a T_CONN_RES without being bound.
   1922     0    stevel 		 */
   1923     0    stevel 		mutex_enter(&nso->so_lock);
   1924     0    stevel 		so_automatic_bind(nso);
   1925     0    stevel 		mutex_exit(&nso->so_lock);
   1926     0    stevel 	} else {
   1927     0    stevel 		/* Perform NULL bind with the transport provider. */
   1928  8348      Eric 		if ((error = sotpi_bind(nso, NULL, 0, _SOBIND_UNSPEC,
   1929  8348      Eric 		    cr)) != 0) {
   1930     0    stevel 			ASSERT(error != ENOBUFS);
   1931     0    stevel 			freemsg(mp);
   1932     0    stevel 			eprintsoline(nso, error);
   1933     0    stevel 			goto disconnect_vp_unlocked;
   1934     0    stevel 		}
   1935     0    stevel 	}
   1936     0    stevel 
   1937     0    stevel 	/*
   1938     0    stevel 	 * Inherit SIOCSPGRP, SS_ASYNC before we send the {O_}T_CONN_RES
   1939     0    stevel 	 * so that any data arriving on the new socket will cause the
   1940     0    stevel 	 * appropriate signals to be delivered for the new socket.
   1941     0    stevel 	 *
   1942     0    stevel 	 * No other thread (except strsock_proto and strsock_misc)
   1943     0    stevel 	 * can access the new socket thus we relax the locking.
   1944     0    stevel 	 */
   1945     0    stevel 	nso->so_pgrp = so->so_pgrp;
   1946  8348      Eric 	nso->so_state |= so->so_state & SS_ASYNC;
   1947  8348      Eric 	nsti->sti_faddr_noxlate = sti->sti_faddr_noxlate;
   1948     0    stevel 
   1949     0    stevel 	if (nso->so_pgrp != 0) {
   1950  8778      Erik 		if ((error = so_set_events(nso, nvp, cr)) != 0) {
   1951     0    stevel 			eprintsoline(nso, error);
   1952     0    stevel 			error = 0;
   1953     0    stevel 			nso->so_pgrp = 0;
   1954     0    stevel 		}
   1955     0    stevel 	}
   1956     0    stevel 
   1957     0    stevel 	/*
   1958     0    stevel 	 * Make note of the socket level options. TCP and IP level options
   1959     0    stevel 	 * are already inherited. We could do all this after accept is
   1960     0    stevel 	 * successful but doing it here simplifies code and no harm done
   1961     0    stevel 	 * for error case.
   1962     0    stevel 	 */
   1963     0    stevel 	nso->so_options = so->so_options & (SO_DEBUG|SO_REUSEADDR|SO_KEEPALIVE|
   1964     0    stevel 	    SO_DONTROUTE|SO_BROADCAST|SO_USELOOPBACK|
   1965     0    stevel 	    SO_OOBINLINE|SO_DGRAM_ERRIND|SO_LINGER);
   1966     0    stevel 	nso->so_sndbuf = so->so_sndbuf;
   1967     0    stevel 	nso->so_rcvbuf = so->so_rcvbuf;
   1968     0    stevel 	if (nso->so_options & SO_LINGER)
   1969     0    stevel 		nso->so_linger = so->so_linger;
   1970     0    stevel 
   1971  8348      Eric 	/*
   1972  8348      Eric 	 * Note that the following sti_direct code path should be
   1973  8348      Eric 	 * removed once we are confident that the direct sockets
   1974  8348      Eric 	 * do not result in any degradation.
   1975  8348      Eric 	 */
   1976  8348      Eric 	if (sti->sti_direct) {
   1977     0    stevel 
   1978     0    stevel 		ASSERT(opt != NULL);
   1979     0    stevel 
   1980     0    stevel 		conn_res->OPT_length = optlen;
   1981     0    stevel 		conn_res->OPT_offset = MBLKL(mp);
   1982     0    stevel 		bcopy(&opt, mp->b_wptr, optlen);
   1983     0    stevel 		mp->b_wptr += optlen;
   1984     0    stevel 		conn_res->PRIM_type = T_CONN_RES;
   1985     0    stevel 		conn_res->ACCEPTOR_id = 0;
   1986     0    stevel 		PRIM_type = T_CONN_RES;
   1987     0    stevel 
   1988     0    stevel 		/* Send down the T_CONN_RES on acceptor STREAM */
   1989     0    stevel 		error = kstrputmsg(SOTOV(nso), mp, NULL,
   1990     0    stevel 		    0, 0, MSG_BAND|MSG_HOLDSIG|MSG_IGNERROR, 0);
   1991     0    stevel 		if (error) {
   1992     0    stevel 			mutex_enter(&so->so_lock);
   1993     0    stevel 			so_lock_single(so);
   1994     0    stevel 			eprintsoline(so, error);
   1995     0    stevel 			goto disconnect_vp;
   1996     0    stevel 		}
   1997     0    stevel 		mutex_enter(&nso->so_lock);
   1998     0    stevel 		error = sowaitprim(nso, T_CONN_RES, T_OK_ACK,
   1999     0    stevel 		    (t_uscalar_t)sizeof (struct T_ok_ack), &ack_mp, 0);
   2000     0    stevel 		if (error) {
   2001     0    stevel 			mutex_exit(&nso->so_lock);
   2002     0    stevel 			mutex_enter(&so->so_lock);
   2003     0    stevel 			so_lock_single(so);
   2004     0    stevel 			eprintsoline(so, error);
   2005     0    stevel 			goto disconnect_vp;
   2006     0    stevel 		}
   2007     0    stevel 		if (nso->so_family == AF_INET) {
   2008     0    stevel 			sin_t *sin;
   2009     0    stevel 
   2010     0    stevel 			sin = (sin_t *)(ack_mp->b_rptr +
   2011     0    stevel 			    sizeof (struct T_ok_ack));
   2012  8348      Eric 			bcopy(sin, nsti->sti_laddr_sa, sizeof (sin_t));
   2013  8348      Eric 			nsti->sti_laddr_len = sizeof (sin_t);
   2014     0    stevel 		} else {
   2015     0    stevel 			sin6_t *sin6;
   2016     0    stevel 
   2017     0    stevel 			sin6 = (sin6_t *)(ack_mp->b_rptr +
   2018     0    stevel 			    sizeof (struct T_ok_ack));
   2019  8348      Eric 			bcopy(sin6, nsti->sti_laddr_sa, sizeof (sin6_t));
   2020  8348      Eric 			nsti->sti_laddr_len = sizeof (sin6_t);
   2021     0    stevel 		}
   2022     0    stevel 		freemsg(ack_mp);
   2023     0    stevel 
   2024  8348      Eric 		nso->so_state |= SS_ISCONNECTED;
   2025  8348      Eric 		nso->so_proto_handle = (sock_lower_handle_t)opt;
   2026  8348      Eric 		nsti->sti_laddr_valid = 1;
   2027  8348      Eric 
   2028  8348      Eric 		if (sti->sti_nl7c_flags & NL7C_ENABLED) {
   2029     0    stevel 			/*
   2030  1974    brutus 			 * A NL7C marked listen()er so the new socket
   2031  1974    brutus 			 * inherits the listen()er's NL7C state, except
   2032  1974    brutus 			 * for NL7C_POLLIN.
   2033  1974    brutus 			 *
   2034  1974    brutus 			 * Only call NL7C to process the new socket if
   2035  1974    brutus 			 * the listen socket allows blocking i/o.
   2036  1974    brutus 			 */
   2037  8348      Eric 			nsti->sti_nl7c_flags =
   2038  8348      Eric 			    sti->sti_nl7c_flags & (~NL7C_POLLIN);
   2039  1974    brutus 			if (so->so_state & (SS_NONBLOCK|SS_NDELAY)) {
   2040  1974    brutus 				/*
   2041  1974    brutus 				 * Nonblocking accept() just make it
   2042  1974    brutus 				 * persist to defer processing to the
   2043  1974    brutus 				 * read-side syscall (e.g. read).
   2044  1974    brutus 				 */
   2045  8348      Eric 				nsti->sti_nl7c_flags |= NL7C_SOPERSIST;
   2046  1974    brutus 			} else if (nl7c_process(nso, B_FALSE)) {
   2047     0    stevel 				/*
   2048     0    stevel 				 * NL7C has completed processing on the
   2049     0    stevel 				 * socket, close the socket and back to
   2050     0    stevel 				 * the top to await the next T_CONN_IND.
   2051     0    stevel 				 */
   2052     0    stevel 				mutex_exit(&nso->so_lock);
   2053     0    stevel 				(void) VOP_CLOSE(nvp, 0, 1, (offset_t)0,
   2054  8778      Erik 				    cr, NULL);
   2055     0    stevel 				VN_RELE(nvp);
   2056     0    stevel 				goto again;
   2057     0    stevel 			}
   2058     0    stevel 			/* Pass the new socket out */
   2059     0    stevel 		}
   2060     0    stevel 
   2061     0    stevel 		mutex_exit(&nso->so_lock);
   2062  2811   ja97890 
   2063  2811   ja97890 		/*
   2064  2811   ja97890 		 * It's possible, through the use of autopush for example,
   2065  8348      Eric 		 * that the acceptor stream may not support sti_direct
   2066  8348      Eric 		 * semantics. If the new socket does not support sti_direct
   2067  2811   ja97890 		 * we issue a _SIOCSOCKFALLBACK to inform the transport
   2068  2811   ja97890 		 * as we would in the I_PUSH case.
   2069  2811   ja97890 		 */
   2070  8348      Eric 		if (nsti->sti_direct == 0) {
   2071  2811   ja97890 			int	rval;
   2072  2811   ja97890 
   2073  2811   ja97890 			if ((error = strioctl(SOTOV(nso), _SIOCSOCKFALLBACK,
   2074  8778      Erik 			    0, 0, K_TO_K, cr, &rval)) != 0) {
   2075  2811   ja97890 				mutex_enter(&so->so_lock);
   2076  2811   ja97890 				so_lock_single(so);
   2077  2811   ja97890 				eprintsoline(so, error);
   2078  2811   ja97890 				goto disconnect_vp;
   2079  2811   ja97890 			}
   2080  2811   ja97890 		}
   2081     0    stevel 
   2082     0    stevel 		/*
   2083     0    stevel 		 * Pass out new socket.
   2084     0    stevel 		 */
   2085     0    stevel 		if (nsop != NULL)
   2086     0    stevel 			*nsop = nso;
   2087     0    stevel 
   2088     0    stevel 		return (0);
   2089     0    stevel 	}
   2090     0    stevel 
   2091     0    stevel 	/*
   2092     0    stevel 	 * This is the non-performance case for sockets (e.g. AF_UNIX sockets)
   2093     0    stevel 	 * which don't support the FireEngine accept fast-path. It is also
   2094     0    stevel 	 * used when the virtual "sockmod" has been I_POP'd and I_PUSH'd
   2095     0    stevel 	 * again. Neither sockfs nor TCP attempt to find out if some other
   2096     0    stevel 	 * random module has been inserted in between (in which case we
   2097     0    stevel 	 * should follow TLI accept behaviour). We blindly assume the worst
   2098     0    stevel 	 * case and revert back to old behaviour i.e. TCP will not send us
   2099     0    stevel 	 * any option (eager) and the accept should happen on the listener
   2100     0    stevel 	 * queue. Any queued T_conn_ind have already got their options removed
   2101     0    stevel 	 * by so_sock2_stream() when "sockmod" was I_POP'd.
   2102     0    stevel 	 */
   2103     0    stevel 	/*
   2104     0    stevel 	 * Fill in the {O_}T_CONN_RES before getting SOLOCKED.
   2105     0    stevel 	 */
   2106     0    stevel 	if ((nso->so_mode & SM_ACCEPTOR_ID) == 0) {
   2107     0    stevel #ifdef	_ILP32
   2108     0    stevel 		queue_t	*q;
   2109     0    stevel 
   2110     0    stevel 		/*
   2111     0    stevel 		 * Find read queue in driver
   2112     0    stevel 		 * Can safely do this since we "own" nso/nvp.
   2113     0    stevel 		 */
   2114     0    stevel 		q = strvp2wq(nvp)->q_next;
   2115     0    stevel 		while (SAMESTR(q))
   2116     0    stevel 			q = q->q_next;
   2117     0    stevel 		q = RD(q);
   2118     0    stevel 		conn_res->ACCEPTOR_id = (t_uscalar_t)q;
   2119     0    stevel #else
   2120     0    stevel 		conn_res->ACCEPTOR_id = (t_uscalar_t)getminor(nvp->v_rdev);
   2121     0    stevel #endif	/* _ILP32 */
   2122     0    stevel 		conn_res->PRIM_type = O_T_CONN_RES;
   2123     0    stevel 		PRIM_type = O_T_CONN_RES;
   2124     0    stevel 	} else {
   2125  8348      Eric 		conn_res->ACCEPTOR_id = nsti->sti_acceptor_id;
   2126     0    stevel 		conn_res->PRIM_type = T_CONN_RES;
   2127     0    stevel 		PRIM_type = T_CONN_RES;
   2128     0    stevel 	}
   2129     0    stevel 	conn_res->SEQ_number = SEQ_number;
   2130     0    stevel 	conn_res->OPT_length = 0;
   2131     0    stevel 	conn_res->OPT_offset = 0;
   2132     0    stevel 
   2133     0    stevel 	mutex_enter(&so->so_lock);
   2134     0    stevel 	so_lock_single(so);	/* Set SOLOCKED */
   2135     0    stevel 	mutex_exit(&so->so_lock);
   2136     0    stevel 
   2137     0    stevel 	error = kstrputmsg(SOTOV(so), mp, NULL,
   2138     0    stevel 	    0, 0, MSG_BAND|MSG_HOLDSIG|MSG_IGNERROR, 0);
   2139     0    stevel 	mutex_enter(&so->so_lock);
   2140     0    stevel 	if (error) {
   2141     0    stevel 		eprintsoline(so, error);
   2142     0    stevel 		goto disconnect_vp;
   2143     0    stevel 	}
   2144  4379   ja97890 	error = sowaitprim(so, PRIM_type, T_OK_ACK,
   2145  4379   ja97890 	    (t_uscalar_t)sizeof (struct T_ok_ack), &ack_mp, 0);
   2146     0    stevel 	if (error) {
   2147     0    stevel 		eprintsoline(so, error);
   2148     0    stevel 		goto disconnect_vp;
   2149     0    stevel 	}
   2150  4379   ja97890 	/*
   2151  4379   ja97890 	 * If there is a sin/sin6 appended onto the T_OK_ACK use
   2152  4379   ja97890 	 * that to set the local address. If this is not present
   2153  4379   ja97890 	 * then we zero out the address and don't set the
   2154  8348      Eric 	 * sti_laddr_valid bit. For AF_UNIX endpoints we copy over
   2155  4678   ja97890 	 * the pathname from the listening socket.
   2156  4379   ja97890 	 */
   2157  4379   ja97890 	sinlen = (nso->so_family == AF_INET) ? sizeof (sin_t) : sizeof (sin6_t);
   2158  4379   ja97890 	if ((nso->so_family == AF_INET) || (nso->so_family == AF_INET6) &&
   2159  4379   ja97890 	    MBLKL(ack_mp) == (sizeof (struct T_ok_ack) + sinlen)) {
   2160  4379   ja97890 		ack_mp->b_rptr += sizeof (struct T_ok_ack);
   2161  8348      Eric 		bcopy(ack_mp->b_rptr, nsti->sti_laddr_sa, sinlen);
   2162  8348      Eric 		nsti->sti_laddr_len = sinlen;
   2163  8348      Eric 		nsti->sti_laddr_valid = 1;
   2164  4678   ja97890 	} else if (nso->so_family == AF_UNIX) {
   2165  4678   ja97890 		ASSERT(so->so_family == AF_UNIX);
   2166  8348      Eric 		nsti->sti_laddr_len = sti->sti_laddr_len;
   2167  8348      Eric 		ASSERT(nsti->sti_laddr_len <= nsti->sti_laddr_maxlen);
   2168  8348      Eric 		bcopy(sti->sti_laddr_sa, nsti->sti_laddr_sa,
   2169  8348      Eric 		    nsti->sti_laddr_len);
   2170  8348      Eric 		nsti->sti_laddr_valid = 1;
   2171  8348      Eric 	} else {
   2172  8348      Eric 		nsti->sti_laddr_len = sti->sti_laddr_len;
   2173  8348      Eric 		ASSERT(nsti->sti_laddr_len <= nsti->sti_laddr_maxlen);
   2174  8348      Eric 		bzero(nsti->sti_laddr_sa, nsti->sti_addr_size);
   2175  8348      Eric 		nsti->sti_laddr_sa->sa_family = nso->so_family;
   2176  4379   ja97890 	}
   2177  4379   ja97890 	freemsg(ack_mp);
   2178  4379   ja97890 
   2179     0    stevel 	so_unlock_single(so, SOLOCKED);
   2180     0    stevel 	mutex_exit(&so->so_lock);
   2181     0    stevel 
   2182     0    stevel 	nso->so_state |= SS_ISCONNECTED;
   2183     0    stevel 
   2184     0    stevel 	/*
   2185     0    stevel 	 * Pass out new socket.
   2186     0    stevel 	 */
   2187     0    stevel 	if (nsop != NULL)
   2188     0    stevel 		*nsop = nso;
   2189     0    stevel 
   2190     0    stevel 	return (0);
   2191     0    stevel 
   2192     0    stevel 
   2193     0    stevel eproto_disc_unl:
   2194     0    stevel 	error = EPROTO;
   2195     0    stevel e_disc_unl:
   2196     0    stevel 	eprintsoline(so, error);
   2197     0    stevel 	goto disconnect_unlocked;
   2198     0    stevel 
   2199     0    stevel pr_disc_vp_unl:
   2200     0    stevel 	eprintsoline(so, error);
   2201     0    stevel disconnect_vp_unlocked:
   2202  8778      Erik 	(void) VOP_CLOSE(nvp, 0, 1, 0, cr, NULL);
   2203     0    stevel 	VN_RELE(nvp);
   2204     0    stevel disconnect_unlocked:
   2205     0    stevel 	(void) sodisconnect(so, SEQ_number, 0);
   2206     0    stevel 	return (error);
   2207     0    stevel 
   2208     0    stevel pr_disc_vp:
   2209     0    stevel 	eprintsoline(so, error);
   2210     0    stevel disconnect_vp:
   2211     0    stevel 	(void) sodisconnect(so, SEQ_number, _SODISCONNECT_LOCK_HELD);
   2212     0    stevel 	so_unlock_single(so, SOLOCKED);
   2213     0    stevel 	mutex_exit(&so->so_lock);
   2214  8778      Erik 	(void) VOP_CLOSE(nvp, 0, 1, 0, cr, NULL);
   2215     0    stevel 	VN_RELE(nvp);
   2216     0    stevel 	return (error);
   2217     0    stevel 
   2218     0    stevel conn_bad:	/* Note: SunOS 4/BSD unconditionally returns EINVAL here */
   2219     0    stevel 	error = (so->so_type == SOCK_DGRAM || so->so_type == SOCK_RAW)
   2220     0    stevel 	    ? EOPNOTSUPP : EINVAL;
   2221     0    stevel e_bad:
   2222     0    stevel 	eprintsoline(so, error);
   2223     0    stevel 	return (error);
   2224     0    stevel }
   2225     0    stevel 
   2226     0    stevel /*
   2227     0    stevel  * connect a socket.
   2228     0    stevel  *
   2229     0    stevel  * Allow SOCK_DGRAM sockets to reconnect (by specifying a new address) and to
   2230     0    stevel  * unconnect (by specifying a null address).
   2231     0    stevel  */
   2232     0    stevel int
   2233     0    stevel sotpi_connect(struct sonode *so,
   2234     0    stevel 	const struct sockaddr *name,
   2235     0    stevel 	socklen_t namelen,
   2236     0    stevel 	int fflag,
   2237  8348      Eric 	int flags,
   2238  8348      Eric 	struct cred *cr)
   2239     0    stevel {
   2240     0    stevel 	struct T_conn_req	conn_req;
   2241     0    stevel 	int			error = 0;
   2242     0    stevel 	mblk_t			*mp;
   2243     0    stevel 	void			*src;
   2244     0    stevel 	socklen_t		srclen;
   2245     0    stevel 	void			*addr;
   2246     0    stevel 	socklen_t		addrlen;
   2247     0    stevel 	boolean_t		need_unlock;
   2248  8348      Eric 	sotpi_info_t		*sti = SOTOTPI(so);
   2249     0    stevel 
   2250     0    stevel 	dprintso(so, 1, ("sotpi_connect(%p, %p, %d, 0x%x, 0x%x) %s\n",
   2251  7240   rh87107 	    (void *)so, (void *)name, namelen, fflag, flags,
   2252  5240  nordmark 	    pr_state(so->so_state, so->so_mode)));
   2253     0    stevel 
   2254     0    stevel 	/*
   2255     0    stevel 	 * Preallocate the T_CONN_REQ mblk before grabbing SOLOCKED to
   2256     0    stevel 	 * avoid sleeping for memory with SOLOCKED held.
   2257  8348      Eric 	 * We know that the T_CONN_REQ can't be larger than 2 * sti_faddr_maxlen
   2258     0    stevel 	 * + sizeof (struct T_opthdr).
   2259     0    stevel 	 * (the AF_UNIX so_ux_addr_xlate() does not make the address
   2260  8348      Eric 	 * exceed sti_faddr_maxlen).
   2261     0    stevel 	 */
   2262     0    stevel 	mp = soallocproto(sizeof (struct T_conn_req) +
   2263  8778      Erik 	    2 * sti->sti_faddr_maxlen + sizeof (struct T_opthdr), _ALLOC_INTR,
   2264  8778      Erik 	    cr);
   2265     0    stevel 	if (mp == NULL) {
   2266     0    stevel 		/*
   2267     0    stevel 		 * Connect can not fail with ENOBUFS. A signal was
   2268     0    stevel 		 * caught so return EINTR.
   2269     0    stevel 		 */
   2270     0    stevel 		error = EINTR;
   2271     0    stevel 		eprintsoline(so, error);
   2272     0    stevel 		return (error);
   2273     0    stevel 	}
   2274     0    stevel 
   2275     0    stevel 	mutex_enter(&so->so_lock);
   2276     0    stevel 	/*
   2277  5694  jprakash 	 * Make sure there is a preallocated T_unbind_req message
   2278  5694  jprakash 	 * before any binding. This message is allocated when the
   2279  5694  jprakash 	 * socket is created. Since another thread can consume
   2280  5694  jprakash 	 * so_unbind_mp by the time we return from so_lock_single(),
   2281  5694  jprakash 	 * we should check the availability of so_unbind_mp after
   2282  5694  jprakash 	 * we return from so_lock_single().
   2283  5694  jprakash 	 */
   2284  5694  jprakash 
   2285  5694  jprakash 	so_lock_single(so);	/* Set SOLOCKED */
   2286  5694  jprakash 	need_unlock = B_TRUE;
   2287  5694  jprakash 
   2288  8348      Eric 	if (sti->sti_unbind_mp == NULL) {
   2289     0    stevel 		dprintso(so, 1, ("sotpi_connect: allocating unbind_req\n"));
   2290     0    stevel 		/* NOTE: holding so_lock while sleeping */
   2291  8348      Eric 		sti->sti_unbind_mp =
   2292  8778      Erik 		    soallocproto(sizeof (struct T_unbind_req), _ALLOC_INTR, cr);
   2293  8348      Eric 		if (sti->sti_unbind_mp == NULL) {
   2294     0    stevel 			error = EINTR;
   2295  5694  jprakash 			goto done;
   2296  5694  jprakash 		}
   2297  5694  jprakash 	}
   2298     0    stevel 
   2299     0    stevel 	/*
   2300     0    stevel 	 * Can't have done a listen before connecting.
   2301     0    stevel 	 */
   2302     0    stevel 	if (so->so_state & SS_ACCEPTCONN) {
   2303     0    stevel 		error = EOPNOTSUPP;
   2304     0    stevel 		goto done;
   2305     0    stevel 	}
   2306     0    stevel 
   2307     0    stevel 	/*
   2308     0    stevel 	 * Must be bound with the transport
   2309     0    stevel 	 */
   2310     0    stevel 	if (!(so->so_state & SS_ISBOUND)) {
   2311     0    stevel 		if ((so->so_family == AF_INET || so->so_family == AF_INET6) &&
   2312     0    stevel 		    /*CONSTCOND*/
   2313     0    stevel 		    so->so_type == SOCK_STREAM && !soconnect_tpi_tcp) {
   2314     0    stevel 			/*
   2315     0    stevel 			 * Optimization for AF_INET{,6} transports
   2316     0    stevel 			 * that can handle a T_CONN_REQ without being bound.
   2317     0    stevel 			 */
   2318     0    stevel 			so_automatic_bind(so);
   2319     0    stevel 		} else {
   2320     0    stevel 			error = sotpi_bind(so, NULL, 0,
   2321  8348      Eric 			    _SOBIND_UNSPEC|_SOBIND_LOCK_HELD, cr);
   2322     0    stevel 			if (error)
   2323     0    stevel 				goto done;
   2324     0    stevel 		}
   2325     0    stevel 		ASSERT(so->so_state & SS_ISBOUND);
   2326     0    stevel 		flags |= _SOCONNECT_DID_BIND;
   2327     0    stevel 	}
   2328     0    stevel 
   2329     0    stevel 	/*
   2330     0    stevel 	 * Handle a connect to a name parameter of type AF_UNSPEC like a
   2331     0    stevel 	 * connect to a null address. This is the portable method to
   2332     0    stevel 	 * unconnect a socket.
   2333     0    stevel 	 */
   2334     0    stevel 	if ((namelen >= sizeof (sa_family_t)) &&
   2335     0    stevel 	    (name->sa_family == AF_UNSPEC)) {
   2336     0    stevel 		name = NULL;
   2337     0    stevel 		namelen = 0;
   2338     0    stevel 	}
   2339     0    stevel 
   2340     0    stevel 	/*
   2341     0    stevel 	 * Check that we are not already connected.
   2342     0    stevel 	 * A connection-oriented socket cannot be reconnected.
   2343     0    stevel 	 * A connected connection-less socket can be
   2344     0    stevel 	 * - connected to a different address by a subsequent connect
   2345     0    stevel 	 * - "unconnected" by a connect to the NULL address
   2346     0    stevel 	 */
   2347     0    stevel 	if (so->so_state & (SS_ISCONNECTED|SS_ISCONNECTING)) {
   2348     0    stevel 		ASSERT(!(flags & _SOCONNECT_DID_BIND));
   2349     0    stevel 		if (so->so_mode & SM_CONNREQUIRED) {
   2350     0    stevel 			/* Connection-oriented socket */
   2351     0    stevel 			error = so->so_state & SS_ISCONNECTED ?
   2352     0    stevel 			    EISCONN : EALREADY;
   2353     0    stevel 			goto done;
   2354     0    stevel 		}
   2355     0    stevel 		/* Connection-less socket */
   2356     0    stevel 		if (name == NULL) {
   2357     0    stevel 			/*
   2358     0    stevel 			 * Remove the connected state and clear SO_DGRAM_ERRIND
   2359     0    stevel 			 * since it was set when the socket was connected.
   2360     0    stevel 			 * If this is UDP also send down a T_DISCON_REQ.
   2361     0    stevel 			 */
   2362     0    stevel 			int val;
   2363     0    stevel 
   2364     0    stevel 			if ((so->so_family == AF_INET ||
   2365  5240  nordmark 			    so->so_family == AF_INET6) &&
   2366     0    stevel 			    (so->so_type == SOCK_DGRAM ||
   2367  5240  nordmark 			    so->so_type == SOCK_RAW) &&
   2368     0    stevel 			    /*CONSTCOND*/
   2369     0    stevel 			    !soconnect_tpi_udp) {
   2370     0    stevel 				/* XXX What about implicitly unbinding here? */
   2371     0    stevel 				error = sodisconnect(so, -1,
   2372  5240  nordmark 				    _SODISCONNECT_LOCK_HELD);
   2373     0    stevel 			} else {
   2374     0    stevel 				so->so_state &=
   2375  8348      Eric 				    ~(SS_ISCONNECTED | SS_ISCONNECTING);
   2376  8348      Eric 				sti->sti_faddr_valid = 0;
   2377  8348      Eric 				sti->sti_faddr_len = 0;
   2378  8348      Eric 			}
   2379  8348      Eric 
   2380  8348      Eric 			/* Remove SOLOCKED since setsockopt will grab it */
   2381     0    stevel 			so_unlock_single(so, SOLOCKED);
   2382     0    stevel 			mutex_exit(&so->so_lock);
   2383     0    stevel 
   2384     0    stevel 			val = 0;
   2385  8348      Eric 			(void) sotpi_setsockopt(so, SOL_SOCKET,
   2386  8348      Eric 			    SO_DGRAM_ERRIND, &val, (t_uscalar_t)sizeof (val),
   2387  8348      Eric 			    cr);
   2388     0    stevel 
   2389     0    stevel 			mutex_enter(&so->so_lock);
   2390     0    stevel 			so_lock_single(so);	/* Set SOLOCKED */
   2391     0    stevel 			goto done;
   2392     0    stevel 		}
   2393     0    stevel 	}
   2394     0    stevel 	ASSERT(so->so_state & SS_ISBOUND);
   2395     0    stevel 
   2396     0    stevel 	if (name == NULL || namelen == 0) {
   2397     0    stevel 		error = EINVAL;
   2398     0    stevel 		goto done;
   2399     0    stevel 	}
   2400     0    stevel 	/*
   2401  8348      Eric 	 * Mark the socket if sti_faddr_sa represents the transport level
   2402     0    stevel 	 * address.
   2403     0    stevel 	 */
   2404     0    stevel 	if (flags & _SOCONNECT_NOXLATE) {
   2405     0    stevel 		struct sockaddr_ux	*soaddr_ux;
   2406     0    stevel 
   2407     0    stevel 		ASSERT(so->so_family == AF_UNIX);
   2408     0    stevel 		if (namelen != sizeof (struct sockaddr_ux)) {
   2409     0    stevel 			error = EINVAL;
   2410     0    stevel 			goto done;
   2411     0    stevel 		}
   2412     0    stevel 		soaddr_ux = (struct sockaddr_ux *)name;
   2413     0    stevel 		name = (struct sockaddr *)&soaddr_ux->sou_addr;
   2414     0    stevel 		namelen = sizeof (soaddr_ux->sou_addr);
   2415  8348      Eric 		sti->sti_faddr_noxlate = 1;
   2416     0    stevel 	}
   2417     0    stevel 
   2418     0    stevel 	/*
   2419     0    stevel 	 * Length and family checks.
   2420     0    stevel 	 */
   2421     0    stevel 	error = so_addr_verify(so, name, namelen);
   2422     0    stevel 	if (error)
   2423     0    stevel 		goto bad;
   2424     0    stevel 
   2425     0    stevel 	/*
   2426     0    stevel 	 * Save foreign address. Needed for AF_UNIX as well as
   2427     0    stevel 	 * transport providers that do not support TI_GETPEERNAME.
   2428     0    stevel 	 * Also used for cached foreign address for TCP and UDP.
   2429     0    stevel 	 */
   2430  8348      Eric 	if (namelen > (t_uscalar_t)sti->sti_faddr_maxlen) {
   2431  8348      Eric 		error = EINVAL;
   2432  8348      Eric 		goto done;
   2433  8348      Eric 	}
   2434  8348      Eric 	sti->sti_faddr_len = (socklen_t)namelen;
   2435  8348      Eric 	ASSERT(sti->sti_faddr_len <= sti->sti_faddr_maxlen);
   2436  8348      Eric 	bcopy(name, sti->sti_faddr_sa, namelen);
   2437  8348      Eric 	sti->sti_faddr_valid = 1;
   2438  8348      Eric 
   2439  8348      Eric 	if (so->so_family == AF_UNIX) {
   2440  8348      Eric 		if (sti->sti_faddr_noxlate) {
   2441     0    stevel 			/*
   2442     0    stevel 			 * Already have a transport internal address. Do not
   2443     0    stevel 			 * pass any (transport internal) source address.
   2444     0    stevel 			 */
   2445  8348      Eric 			addr = sti->sti_faddr_sa;
   2446  8348      Eric 			addrlen = (t_uscalar_t)sti->sti_faddr_len;
   2447     0    stevel 			src = NULL;
   2448     0    stevel 			srclen = 0;
   2449     0    stevel 		} else {
   2450     0    stevel 			/*
   2451     0    stevel 			 * Pass the sockaddr_un source address as an option
   2452     0    stevel 			 * and translate the remote address.
   2453  8348      Eric 			 * Holding so_lock thus sti_laddr_sa can not change.
   2454  8348      Eric 			 */
   2455  8348      Eric 			src = sti->sti_laddr_sa;
   2456  8348      Eric 			srclen = (t_uscalar_t)sti->sti_laddr_len;
   2457     0    stevel 			dprintso(so, 1,
   2458  5240  nordmark 			    ("sotpi_connect UNIX: srclen %d, src %p\n",
   2459  5240  nordmark 			    srclen, src));
   2460     0    stevel 			error = so_ux_addr_xlate(so,
   2461  8348      Eric 			    sti->sti_faddr_sa, (socklen_t)sti->sti_faddr_len,
   2462  5240  nordmark 			    (flags & _SOCONNECT_XPG4_2),
   2463  5240  nordmark 			    &addr, &addrlen);
   2464     0    stevel 			if (error)
   2465     0    stevel 				goto bad;
   2466     0    stevel 		}
   2467     0    stevel 	} else {
   2468  8348      Eric 		addr = sti->sti_faddr_sa;
   2469  8348      Eric 		addrlen = (t_uscalar_t)sti->sti_faddr_len;
   2470     0    stevel 		src = NULL;
   2471     0    stevel 		srclen = 0;
   2472     0    stevel 	}
   2473     0    stevel 	/*
   2474     0    stevel 	 * When connecting a datagram socket we issue the SO_DGRAM_ERRIND
   2475     0    stevel 	 * option which asks the transport provider to send T_UDERR_IND
   2476     0    stevel 	 * messages. These T_UDERR_IND messages are used to return connected
   2477     0    stevel 	 * style errors (e.g. ECONNRESET) for connected datagram sockets.
   2478     0    stevel 	 *
   2479     0    stevel 	 * In addition, for UDP (and SOCK_RAW AF_INET{,6} sockets)
   2480     0    stevel 	 * we send down a T_CONN_REQ. This is needed to let the
   2481     0    stevel 	 * transport assign a local address that is consistent with
   2482     0    stevel 	 * the remote address. Applications depend on a getsockname()
   2483     0    stevel 	 * after a connect() to retrieve the "source" IP address for
   2484     0    stevel 	 * the connected socket.  Invalidate the cached local address
   2485     0    stevel 	 * to force getsockname() to enquire of the transport.
   2486     0    stevel 	 */
   2487     0    stevel 	if (!(so->so_mode & SM_CONNREQUIRED)) {
   2488     0    stevel 		/*
   2489     0    stevel 		 * Datagram socket.
   2490     0    stevel 		 */
   2491     0    stevel 		int32_t val;
   2492     0    stevel 
   2493     0    stevel 		so_unlock_single(so, SOLOCKED);
   2494     0    stevel 		mutex_exit(&so->so_lock);
   2495     0    stevel 
   2496     0    stevel 		val = 1;
   2497     0    stevel 		(void) sotpi_setsockopt(so, SOL_SOCKET, SO_DGRAM_ERRIND,
   2498  8348      Eric 		    &val, (t_uscalar_t)sizeof (val), cr);
   2499     0    stevel 
   2500     0    stevel 		mutex_enter(&so->so_lock);
   2501     0    stevel 		so_lock_single(so);	/* Set SOLOCKED */
   2502     0    stevel 		if ((so->so_family != AF_INET && so->so_family != AF_INET6) ||
   2503     0    stevel 		    (so->so_type != SOCK_DGRAM && so->so_type != SOCK_RAW) ||
   2504     0    stevel 		    soconnect_tpi_udp) {
   2505     0    stevel 			soisconnected(so);
   2506     0    stevel 			goto done;
   2507     0    stevel 		}
   2508     0    stevel 		/*
   2509     0    stevel 		 * Send down T_CONN_REQ etc.
   2510     0    stevel 		 * Clear fflag to avoid returning EWOULDBLOCK.
   2511     0    stevel 		 */
   2512     0    stevel 		fflag = 0;
   2513     0    stevel 		ASSERT(so->so_family != AF_UNIX);
   2514  8348      Eric 		sti->sti_laddr_valid = 0;
   2515  8348      Eric 	} else if (sti->sti_laddr_len != 0) {
   2516     0    stevel 		/*
   2517     0    stevel 		 * If the local address or port was "any" then it may be
   2518     0    stevel 		 * changed by the transport as a result of the
   2519     0    stevel 		 * connect.  Invalidate the cached version if we have one.
   2520     0    stevel 		 */
   2521     0    stevel 		switch (so->so_family) {
   2522     0    stevel 		case AF_INET:
   2523  8348      Eric 			ASSERT(sti->sti_laddr_len == (socklen_t)sizeof (sin_t));
   2524  8348      Eric 			if (((sin_t *)sti->sti_laddr_sa)->sin_addr.s_addr ==
   2525     0    stevel 			    INADDR_ANY ||
   2526  8348      Eric 			    ((sin_t *)sti->sti_laddr_sa)->sin_port == 0)
   2527  8348      Eric 				sti->sti_laddr_valid = 0;
   2528     0    stevel 			break;
   2529     0    stevel 
   2530     0    stevel 		case AF_INET6:
   2531  8348      Eric 			ASSERT(sti->sti_laddr_len ==
   2532  8348      Eric 			    (socklen_t)sizeof (sin6_t));
   2533     0    stevel 			if (IN6_IS_ADDR_UNSPECIFIED(
   2534  8348      Eric 			    &((sin6_t *)sti->sti_laddr_sa) ->sin6_addr) ||
   2535     0    stevel 			    IN6_IS_ADDR_V4MAPPED_ANY(
   2536  8348      Eric 			    &((sin6_t *)sti->sti_laddr_sa)->sin6_addr) ||
   2537  8348      Eric 			    ((sin6_t *)sti->sti_laddr_sa)->sin6_port == 0)
   2538  8348      Eric 				sti->sti_laddr_valid = 0;
   2539     0    stevel 			break;
   2540     0    stevel 
   2541     0    stevel 		default:
   2542     0    stevel 			break;
   2543     0    stevel 		}
   2544     0    stevel 	}
   2545     0    stevel 
   2546     0    stevel 	/*
   2547     0    stevel 	 * Check for failure of an earlier call
   2548     0    stevel 	 */
   2549     0    stevel 	if (so->so_error != 0)
   2550     0    stevel 		goto so_bad;
   2551     0    stevel 
   2552     0    stevel 	/*
   2553     0    stevel 	 * Send down T_CONN_REQ. Message was allocated above.
   2554     0    stevel 	 */
   2555     0    stevel 	conn_req.PRIM_type = T_CONN_REQ;
   2556     0    stevel 	conn_req.DEST_length = addrlen;
   2557     0    stevel 	conn_req.DEST_offset = (t_scalar_t)sizeof (conn_req);
   2558     0    stevel 	if (srclen == 0) {
   2559     0    stevel 		conn_req.OPT_length = 0;
   2560     0    stevel 		conn_req.OPT_offset = 0;
   2561     0    stevel 		soappendmsg(mp, &conn_req, sizeof (conn_req));
   2562     0    stevel 		soappendmsg(mp, addr, addrlen);
   2563     0    stevel 	} else {
   2564     0    stevel 		/*
   2565     0    stevel 		 * There is a AF_UNIX sockaddr_un to include as a source
   2566     0    stevel 		 * address option.
   2567     0    stevel 		 */
   2568     0    stevel 		struct T_opthdr toh;
   2569     0    stevel 
   2570     0    stevel 		toh.level = SOL_SOCKET;
   2571     0    stevel 		toh.name = SO_SRCADDR;
   2572     0    stevel 		toh.len = (t_uscalar_t)(srclen + sizeof (struct T_opthdr));
   2573     0    stevel 		toh.status = 0;
   2574     0    stevel 		conn_req.OPT_length =
   2575  5240  nordmark 		    (t_scalar_t)(sizeof (toh) + _TPI_ALIGN_TOPT(srclen));
   2576     0    stevel 		conn_req.OPT_offset = (t_scalar_t)(sizeof (conn_req) +
   2577  5240  nordmark 		    _TPI_ALIGN_TOPT(addrlen));
   2578     0    stevel 
   2579     0    stevel 		soappendmsg(mp, &conn_req, sizeof (conn_req));
   2580     0    stevel 		soappendmsg(mp, addr, addrlen);
   2581     0    stevel 		mp->b_wptr += _TPI_ALIGN_TOPT(addrlen) - addrlen;
   2582     0    stevel 		soappendmsg(mp, &toh, sizeof (toh));
   2583     0    stevel 		soappendmsg(mp, src, srclen);
   2584     0    stevel 		mp->b_wptr += _TPI_ALIGN_TOPT(srclen) - srclen;
   2585     0    stevel 		ASSERT(mp->b_wptr <= mp->b_datap->db_lim);
   2586     0    stevel 	}
   2587     0    stevel 	/*
   2588     0    stevel 	 * Set SS_ISCONNECTING before sending down the T_CONN_REQ
   2589     0    stevel 	 * in order to have the right state when the T_CONN_CON shows up.
   2590     0    stevel 	 */
   2591     0    stevel 	soisconnecting(so);
   2592     0    stevel 	mutex_exit(&so->so_lock);
   2593     0    stevel 
   2594     0    stevel 	if (audit_active)
   2595     0    stevel 		audit_sock(T_CONN_REQ, strvp2wq(SOTOV(so)), mp, 0);
   2596     0    stevel 
   2597     0    stevel 	error = kstrputmsg(SOTOV(so), mp, NULL, 0, 0,
   2598  5240  nordmark 	    MSG_BAND|MSG_HOLDSIG|MSG_IGNERROR, 0);
   2599     0    stevel 	mp = NULL;
   2600     0    stevel 	mutex_enter(&so->so_lock);
   2601     0    stevel 	if (error != 0)
   2602     0    stevel 		goto bad;
   2603     0    stevel 
   2604     0    stevel 	if ((error = sowaitokack(so, T_CONN_REQ)) != 0)
   2605     0    stevel 		goto bad;
   2606     0    stevel 
   2607     0    stevel 	/* Allow other threads to access the socket */
   2608     0    stevel 	so_unlock_single(so, SOLOCKED);
   2609     0    stevel 	need_unlock = B_FALSE;
   2610     0    stevel 
   2611     0    stevel 	/*
   2612     0    stevel 	 * Wait until we get a T_CONN_CON or an error
   2613     0    stevel 	 */
   2614     0    stevel 	if ((error = sowaitconnected(so, fflag, 0)) != 0) {
   2615     0    stevel 		so_lock_single(so);	/* Set SOLOCKED */
   2616     0    stevel 		need_unlock = B_TRUE;
   2617     0    stevel 	}
   2618     0    stevel 
   2619     0    stevel done:
   2620     0    stevel 	freemsg(mp);
   2621     0    stevel 	switch (error) {
   2622     0    stevel 	case EINPROGRESS:
   2623     0    stevel 	case EALREADY:
   2624     0    stevel 	case EISCONN:
   2625     0    stevel 	case EINTR:
   2626     0    stevel 		/* Non-fatal errors */
   2627  8348      Eric 		sti->sti_laddr_valid = 0;
   2628     0    stevel 		/* FALLTHRU */
   2629     0    stevel 	case 0:
   2630     0    stevel 		break;
   2631     0    stevel 	default:
   2632     0    stevel 		ASSERT(need_unlock);
   2633     0    stevel 		/*
   2634     0    stevel 		 * Fatal errors: clear SS_ISCONNECTING in case it was set,
   2635     0    stevel 		 * and invalidate local-address cache
   2636     0    stevel 		 */
   2637  8348      Eric 		so->so_state &= ~SS_ISCONNECTING;
   2638  8348      Eric 		sti->sti_laddr_valid = 0;
   2639     0    stevel 		/* A discon_ind might have already unbound us */
   2640     0    stevel 		if ((flags & _SOCONNECT_DID_BIND) &&
   2641     0    stevel 		    (so->so_state & SS_ISBOUND)) {
   2642     0    stevel 			int err;
   2643     0    stevel 
   2644     0    stevel 			err = sotpi_unbind(so, 0);
   2645     0    stevel 			/* LINTED - statement has no conseq */
   2646     0    stevel 			if (err) {
   2647     0    stevel 				eprintsoline(so, err);
   2648     0    stevel 			}
   2649     0    stevel 		}
   2650     0    stevel 		break;
   2651     0    stevel 	}
   2652     0    stevel 	if (need_unlock)
   2653     0    stevel 		so_unlock_single(so, SOLOCKED);
   2654     0    stevel 	mutex_exit(&so->so_lock);
   2655     0    stevel 	return (error);
   2656     0    stevel 
   2657  8348      Eric so_bad:	error = sogeterr(so, B_TRUE);
   2658     0    stevel bad:	eprintsoline(so, error);
   2659     0    stevel 	goto done;
   2660     0    stevel }
   2661     0    stevel 
   2662  8348      Eric /* ARGSUSED */
   2663  8348      Eric int
   2664  8348      Eric sotpi_shutdown(struct sonode *so, int how, struct cred *cr)
   2665     0    stevel {
   2666     0    stevel 	struct T_ordrel_req	ordrel_req;
   2667     0    stevel 	mblk_t			*mp;
   2668     0    stevel 	uint_t			old_state, state_change;
   2669     0    stevel 	int			error = 0;
   2670  8348      Eric 	sotpi_info_t		*sti = SOTOTPI(so);
   2671     0    stevel 
   2672     0    stevel 	dprintso(so, 1, ("sotpi_shutdown(%p, %d) %s\n",
   2673  7240   rh87107 	    (void *)so, how, pr_state(so->so_state, so->so_mode)));
   2674     0    stevel 
   2675     0    stevel 	mutex_enter(&so->so_lock);
   2676     0    stevel 	so_lock_single(so);	/* Set SOLOCKED */
   2677     0    stevel 
   2678     0    stevel 	/*
   2679     0    stevel 	 * SunOS 4.X has no check for datagram sockets.
   2680     0    stevel 	 * 5.X checks that it is connected (ENOTCONN)
   2681     0    stevel 	 * X/Open requires that we check the connected state.
   2682     0    stevel 	 */
   2683     0    stevel 	if (!(so->so_state & SS_ISCONNECTED)) {
   2684     0    stevel 		if (!xnet_skip_checks) {
   2685     0    stevel 			error = ENOTCONN;
   2686     0    stevel 			if (xnet_check_print) {
   2687     0    stevel 				printf("sockfs: X/Open shutdown check "
   2688  5240  nordmark 				    "caused ENOTCONN\n");
   2689     0    stevel 			}
   2690     0    stevel 		}
   2691     0    stevel 		goto done;
   2692     0    stevel 	}
   2693     0    stevel 	/*
   2694     0    stevel 	 * Record the current state and then perform any state changes.
   2695     0    stevel 	 * Then use the difference between the old and new states to
   2696     0    stevel 	 * determine which messages need to be sent.
   2697     0    stevel 	 * This prevents e.g. duplicate T_ORDREL_REQ when there are
   2698     0    stevel 	 * duplicate calls to shutdown().
   2699     0    stevel 	 */
   2700     0    stevel 	old_state = so->so_state;
   2701     0    stevel 
   2702     0    stevel 	switch (how) {
   2703     0    stevel 	case 0:
   2704     0    stevel 		socantrcvmore(so);
   2705     0    stevel 		break;
   2706     0    stevel 	case 1:
   2707     0    stevel 		socantsendmore(so);
   2708     0    stevel 		break;
   2709     0    stevel 	case 2:
   2710     0    stevel 		socantsendmore(so);
   2711     0    stevel 		socantrcvmore(so);
   2712     0    stevel 		break;
   2713     0    stevel 	default:
   2714     0    stevel 		error = EINVAL;
   2715     0    stevel 		goto done;
   2716     0    stevel 	}
   2717     0    stevel 
   2718     0    stevel 	/*
   2719     0    stevel 	 * Assumes that the SS_CANT* flags are never cleared in the above code.
   2720     0    stevel 	 */
   2721     0    stevel 	state_change = (so->so_state & (SS_CANTRCVMORE|SS_CANTSENDMORE)) -
   2722  5240  nordmark 	    (old_state & (SS_CANTRCVMORE|SS_CANTSENDMORE));
   2723     0    stevel 	ASSERT((state_change & ~(SS_CANTRCVMORE|SS_CANTSENDMORE)) == 0);
   2724     0    stevel 
   2725     0    stevel 	switch (state_change) {
   2726     0    stevel 	case 0:
   2727     0    stevel 		dprintso(so, 1,
   2728     0    stevel 		    ("sotpi_shutdown: nothing to send in state 0x%x\n",
   2729     0    stevel 		    so->so_state));
   2730     0    stevel 		goto done;
   2731     0    stevel 
   2732     0    stevel 	case SS_CANTRCVMORE:
   2733     0    stevel 		mutex_exit(&so->so_lock);
   2734     0    stevel 		strseteof(SOTOV(so), 1);
   2735     0    stevel 		/*
   2736     0    stevel 		 * strseteof takes care of read side wakeups,
   2737     0    stevel 		 * pollwakeups, and signals.
   2738     0    stevel 		 */
   2739     0    stevel 		/*
   2740     0    stevel 		 * Get the read lock before flushing data to avoid problems
   2741     0    stevel 		 * with the T_EXDATA_IND MSG_PEEK code in sotpi_recvmsg.
   2742     0    stevel 		 */
   2743     0    stevel 		mutex_enter(&so->so_lock);
   2744     0    stevel 		(void) so_lock_read(so, 0);	/* Set SOREADLOCKED */
   2745     0    stevel 		mutex_exit(&so->so_lock);
   2746     0    stevel 
   2747     0    stevel 		/* Flush read side queue */
   2748     0    stevel 		strflushrq(SOTOV(so), FLUSHALL);
   2749     0    stevel 
   2750     0    stevel 		mutex_enter(&so->so_lock);
   2751     0    stevel 		so_unlock_read(so);		/* Clear SOREADLOCKED */
   2752     0    stevel 		break;
   2753     0    stevel 
   2754     0    stevel 	case SS_CANTSENDMORE:
   2755     0    stevel 		mutex_exit(&so->so_lock);
   2756     0    stevel 		strsetwerror(SOTOV(so), 0, 0, sogetwrerr);
   2757     0    stevel 		mutex_enter(&so->so_lock);
   2758     0    stevel 		break;
   2759     0    stevel 
   2760     0    stevel 	case SS_CANTSENDMORE|SS_CANTRCVMORE:
   2761     0    stevel 		mutex_exit(&so->so_lock);
   2762     0    stevel 		strsetwerror(SOTOV(so), 0, 0, sogetwrerr);
   2763     0    stevel 		strseteof(SOTOV(so), 1);
   2764     0    stevel 		/*
   2765     0    stevel 		 * strseteof takes care of read side wakeups,
   2766     0    stevel 		 * pollwakeups, and signals.
   2767     0    stevel 		 */
   2768     0    stevel 		/*
   2769     0    stevel 		 * Get the read lock before flushing data to avoid problems
   2770     0    stevel 		 * with the T_EXDATA_IND MSG_PEEK code in sotpi_recvmsg.
   2771     0    stevel 		 */
   2772     0    stevel 		mutex_enter(&so->so_lock);
   2773     0    stevel 		(void) so_lock_read(so, 0);	/* Set SOREADLOCKED */
   2774     0    stevel 		mutex_exit(&so->so_lock);
   2775     0    stevel 
   2776     0    stevel 		/* Flush read side queue */
   2777     0    stevel 		strflushrq(SOTOV(so), FLUSHALL);
   2778     0    stevel 
   2779     0    stevel 		mutex_enter(&so->so_lock);
   2780     0    stevel 		so_unlock_read(so);		/* Clear SOREADLOCKED */
   2781     0    stevel 		break;
   2782     0    stevel 	}
   2783     0    stevel 
   2784     0    stevel 	ASSERT(MUTEX_HELD(&so->so_lock));
   2785     0    stevel 
   2786     0    stevel 	/*
   2787     0    stevel 	 * If either SS_CANTSENDMORE or SS_CANTRCVMORE or both of them
   2788     0    stevel 	 * was set due to this call and the new state has both of them set:
   2789     0    stevel 	 *	Send the AF_UNIX close indication
   2790     0    stevel 	 *	For T_COTS send a discon_ind
   2791     0    stevel 	 *
   2792     0    stevel 	 * If cantsend was set due to this call:
   2793     0    stevel 	 *	For T_COTSORD send an ordrel_ind
   2794     0    stevel 	 *
   2795     0    stevel 	 * Note that for T_CLTS there is no message sent here.
   2796     0    stevel 	 */
   2797     0    stevel 	if ((so->so_state & (SS_CANTRCVMORE|SS_CANTSENDMORE)) ==
   2798     0    stevel 	    (SS_CANTRCVMORE|SS_CANTSENDMORE)) {
   2799     0    stevel 		/*
   2800     0    stevel 		 * For SunOS 4.X compatibility we tell the other end
   2801     0    stevel 		 * that we are unable to receive at this point.
   2802     0    stevel 		 */
   2803  8348      Eric 		if (so->so_family == AF_UNIX && sti->sti_serv_type != T_CLTS)
   2804     0    stevel 			so_unix_close(so);
   2805     0    stevel 
   2806  8348      Eric 		if (sti->sti_serv_type == T_COTS)
   2807     0    stevel 			error = sodisconnect(so, -1, _SODISCONNECT_LOCK_HELD);
   2808     0    stevel 	}
   2809     0    stevel 	if ((state_change & SS_CANTSENDMORE) &&
   2810  8348      Eric 	    (sti->sti_serv_type == T_COTS_ORD)) {
   2811     0    stevel 		/* Send an orderly release */
   2812     0    stevel 		ordrel_req.PRIM_type = T_ORDREL_REQ;
   2813     0    stevel 
   2814     0    stevel 		mutex_exit(&so->so_lock);
   2815     0    stevel 		mp = soallocproto1(&ordrel_req, sizeof (ordrel_req),
   2816  8778      Erik 		    0, _ALLOC_SLEEP, cr);
   2817     0    stevel 		/*
   2818     0    stevel 		 * Send down the T_ORDREL_REQ even if there is flow control.
   2819     0    stevel 		 * This prevents shutdown from blocking.
   2820     0    stevel 		 * Note that there is no T_OK_ACK for ordrel_req.
   2821     0    stevel 		 */
   2822     0    stevel 		error = kstrputmsg(SOTOV(so), mp, NULL, 0, 0,
   2823  5240  nordmark 		    MSG_BAND|MSG_HOLDSIG|MSG_IGNERROR|MSG_IGNFLOW, 0);
   2824     0    stevel 		mutex_enter(&so->so_lock);
   2825     0    stevel 		if (error) {
   2826     0    stevel 			eprintsoline(so, error);
   2827     0    stevel 			goto done;
   2828     0    stevel 		}
   2829     0    stevel 	}
   2830     0    stevel 
   2831     0    stevel done:
   2832     0    stevel 	so_unlock_single(so, SOLOCKED);
   2833     0    stevel 	mutex_exit(&so->so_lock);
   2834     0    stevel 	return (error);
   2835     0    stevel }
   2836     0    stevel 
   2837     0    stevel /*
   2838     0    stevel  * For any connected SOCK_STREAM/SOCK_SEQPACKET AF_UNIX socket we send
   2839     0    stevel  * a zero-length T_OPTDATA_REQ with the SO_UNIX_CLOSE option to inform the peer
   2840     0    stevel  * that we have closed.
   2841     0    stevel  * Also, for connected AF_UNIX SOCK_DGRAM sockets we send a zero-length
   2842     0    stevel  * T_UNITDATA_REQ containing the same option.
   2843     0    stevel  *
   2844     0    stevel  * For SOCK_DGRAM half-connections (somebody connected to this end
   2845     0    stevel  * but this end is not connect) we don't know where to send any
   2846     0    stevel  * SO_UNIX_CLOSE.
   2847     0    stevel  *
   2848     0    stevel  * We have to ignore stream head errors just in case there has been
   2849     0    stevel  * a shutdown(output).
   2850     0    stevel  * Ignore any flow control to try to get the message more quickly to the peer.
   2851     0    stevel  * While locally ignoring flow control solves the problem when there
   2852     0    stevel  * is only the loopback transport on the stream it would not provide
   2853     0    stevel  * the correct AF_UNIX socket semantics when one or more modules have
   2854     0    stevel  * been pushed.
   2855     0    stevel  */
   2856     0    stevel void
   2857     0    stevel so_unix_close(struct sonode *so)
   2858     0    stevel {
   2859     0    stevel 	int		error;
   2860     0    stevel 	struct T_opthdr	toh;
   2861     0    stevel 	mblk_t		*mp;
   2862  8348      Eric 	sotpi_info_t	*sti = SOTOTPI(so);
   2863     0    stevel 
   2864     0    stevel 	ASSERT(MUTEX_HELD(&so->so_lock));
   2865     0    stevel 
   2866     0    stevel 	ASSERT(so->so_family == AF_UNIX);
   2867     0    stevel 
   2868     0    stevel 	if ((so->so_state & (SS_ISCONNECTED|SS_ISBOUND)) !=
   2869     0    stevel 	    (SS_ISCONNECTED|SS_ISBOUND))
   2870     0    stevel 		return;
   2871     0    stevel 
   2872     0    stevel 	dprintso(so, 1, ("so_unix_close(%p) %s\n",
   2873  7240   rh87107 	    (void *)so, pr_state(so->so_state, so->so_mode)));
   2874     0    stevel 
   2875     0    stevel 	toh.level = SOL_SOCKET;
   2876     0    stevel 	toh.name = SO_UNIX_CLOSE;
   2877     0    stevel 
   2878     0    stevel 	/* zero length + header */
   2879     0    stevel 	toh.len = (t_uscalar_t)sizeof (struct T_opthdr);
   2880     0    stevel 	toh.status = 0;
   2881     0    stevel 
   2882     0    stevel 	if (so->so_type == SOCK_STREAM || so->so_type == SOCK_SEQPACKET) {
   2883     0    stevel 		struct T_optdata_req tdr;
   2884     0    stevel 
   2885     0    stevel 		tdr.PRIM_type = T_OPTDATA_REQ;
   2886     0    stevel 		tdr.DATA_flag = 0;
   2887     0    stevel 
   2888     0    stevel 		tdr.OPT_length = (t_scalar_t)sizeof (toh);
   2889     0    stevel 		tdr.OPT_offset = (t_scalar_t)sizeof (tdr);
   2890     0    stevel 
   2891     0    stevel 		/* NOTE: holding so_lock while sleeping */
   2892     0    stevel 		mp = soallocproto2(&tdr, sizeof (tdr),
   2893  8778      Erik 		    &toh, sizeof (toh), 0, _ALLOC_SLEEP, CRED());
   2894     0    stevel 	} else {
   2895     0    stevel 		struct T_unitdata_req	tudr;
   2896     0    stevel 		void			*addr;
   2897     0    stevel 		socklen_t		addrlen;
   2898     0    stevel 		void			*src;
   2899     0    stevel 		socklen_t		srclen;
   2900     0    stevel 		struct T_opthdr		toh2;
   2901     0    stevel 		t_scalar_t		size;
   2902     0    stevel 
   2903     0    stevel 		/* Connecteded DGRAM socket */
   2904     0    stevel 
   2905     0    stevel 		/*
   2906     0    stevel 		 * For AF_UNIX the destination address is translated to
   2907     0    stevel 		 * an internal name and the source address is passed as
   2908     0    stevel 		 * an option.
   2909     0    stevel 		 */
   2910     0    stevel 		/*
   2911     0    stevel 		 * Length and family checks.
   2912     0    stevel 		 */
   2913  8348      Eric 		error = so_addr_verify(so, sti->sti_faddr_sa,
   2914  8348      Eric 		    (t_uscalar_t)sti->sti_faddr_len);
   2915     0    stevel 		if (error) {
   2916     0    stevel 			eprintsoline(so, error);
   2917     0    stevel 			return;
   2918     0    stevel 		}
   2919  8348      Eric 		if (sti->sti_faddr_noxlate) {
   2920     0    stevel 			/*
   2921     0    stevel 			 * Already have a transport internal address. Do not
   2922     0    stevel 			 * pass any (transport internal) source address.
   2923     0    stevel 			 */
   2924  8348      Eric 			addr = sti->sti_faddr_sa;
   2925  8348      Eric 			addrlen = (t_uscalar_t)sti->sti_faddr_len;
   2926     0    stevel 			src = NULL;
   2927     0    stevel 			srclen = 0;
   2928     0    stevel 		} else {
   2929     0    stevel 			/*
   2930     0    stevel 			 * Pass the sockaddr_un source address as an option
   2931     0    stevel 			 * and translate the remote address.
   2932  8348      Eric 			 * Holding so_lock thus sti_laddr_sa can not change.
   2933  8348      Eric 			 */
   2934  8348      Eric 			src = sti->sti_laddr_sa;
   2935  8348      Eric 			srclen = (socklen_t)sti->sti_laddr_len;
   2936     0    stevel 			dprintso(so, 1,
   2937  5240  nordmark 			    ("so_ux_close: srclen %d, src %p\n",
   2938  5240  nordmark 			    srclen, src));
   2939     0    stevel 			error = so_ux_addr_xlate(so,
   2940  8348      Eric 			    sti->sti_faddr_sa,
   2941  8348      Eric 			    (socklen_t)sti->sti_faddr_len, 0,
   2942  5240  nordmark 			    &addr, &addrlen);
   2943     0    stevel 			if (error) {
   2944     0    stevel 				eprintsoline(so, error);
   2945     0    stevel 				return;
   2946     0    stevel 			}
   2947     0    stevel 		}
   2948     0    stevel 		tudr.PRIM_type = T_UNITDATA_REQ;
   2949     0    stevel 		tudr.DEST_length = addrlen;
   2950     0    stevel 		tudr.DEST_offset = (t_scalar_t)sizeof (tudr);
   2951     0    stevel 		if (srclen == 0) {
   2952     0    stevel 			tudr.OPT_length = (t_scalar_t)sizeof (toh);
   2953     0    stevel 			tudr.OPT_offset = (t_scalar_t)(sizeof (tudr) +
   2954  5240  nordmark 			    _TPI_ALIGN_TOPT(addrlen));
   2955     0    stevel 
   2956     0    stevel 			size = tudr.OPT_offset + tudr.OPT_length;
   2957     0    stevel 			/* NOTE: holding so_lock while sleeping */
   2958     0    stevel 			mp = soallocproto2(&tudr, sizeof (tudr),
   2959  8778      Erik 			    addr, addrlen, size, _ALLOC_SLEEP, CRED());
   2960     0    stevel 			mp->b_wptr += (_TPI_ALIGN_TOPT(addrlen) - addrlen);
   2961     0    stevel 			soappendmsg(mp, &toh, sizeof (toh));
   2962     0    stevel 		} else {
   2963     0    stevel 			/*
   2964     0    stevel 			 * There is a AF_UNIX sockaddr_un to include as a
   2965     0    stevel 			 * source address option.
   2966     0    stevel 			 */
   2967     0    stevel 			tudr.OPT_length = (t_scalar_t)(2 * sizeof (toh) +
   2968     0    stevel 			    _TPI_ALIGN_TOPT(srclen));
   2969     0    stevel 			tudr.OPT_offset = (t_scalar_t)(sizeof (tudr) +
   2970     0    stevel 			    _TPI_ALIGN_TOPT(addrlen));
   2971     0    stevel 
   2972     0    stevel 			toh2.level = SOL_SOCKET;
   2973     0    stevel 			toh2.name = SO_SRCADDR;
   2974     0    stevel 			toh2.len = (t_uscalar_t)(srclen +
   2975  5240  nordmark 			    sizeof (struct T_opthdr));
   2976     0    stevel 			toh2.status = 0;
   2977     0    stevel 
   2978     0    stevel 			size = tudr.OPT_offset + tudr.OPT_length;
   2979     0    stevel 
   2980     0    stevel 			/* NOTE: holding so_lock while sleeping */
   2981     0    stevel 			mp = soallocproto2(&tudr, sizeof (tudr),
   2982  8778      Erik 			    addr, addrlen, size, _ALLOC_SLEEP, CRED());
   2983     0    stevel 			mp->b_wptr += _TPI_ALIGN_TOPT(addrlen) - addrlen;
   2984     0    stevel 			soappendmsg(mp, &toh, sizeof (toh));
   2985     0    stevel 			soappendmsg(mp, &toh2, sizeof (toh2));
   2986     0    stevel 			soappendmsg(mp, src, srclen);
   2987     0    stevel 			mp->b_wptr += _TPI_ALIGN_TOPT(srclen) - srclen;
   2988     0    stevel 		}
   2989     0    stevel 		ASSERT(mp->b_wptr <= mp->b_datap->db_lim);
   2990     0    stevel 	}
   2991     0    stevel 	mutex_exit(&so->so_lock);
   2992     0    stevel 	error = kstrputmsg(SOTOV(so), mp, NULL, 0, 0,
   2993  5240  nordmark 	    MSG_BAND|MSG_HOLDSIG|MSG_IGNERROR|MSG_IGNFLOW, 0);
   2994     0    stevel 	mutex_enter(&so->so_lock);
   2995     0    stevel }
   2996     0    stevel 
   2997     0    stevel /*
   2998     0    stevel  * Called by sotpi_recvmsg when reading a non-zero amount of data.
   2999     0    stevel  * In addition, the caller typically verifies that there is some
   3000     0    stevel  * potential state to clear by checking
   3001     0    stevel  *	if (so->so_state & (SS_OOBPEND|SS_HAVEOOBDATA|SS_RCVATMARK))
   3002     0    stevel  * before calling this routine.
   3003     0    stevel  * Note that such a check can be made without holding so_lock since
   3004     0    stevel  * sotpi_recvmsg is single-threaded (using SOREADLOCKED) and only sotpi_recvmsg
   3005  8348      Eric  * decrements sti_oobsigcnt.
   3006     0    stevel  *
   3007     0    stevel  * When data is read *after* the point that all pending
   3008     0    stevel  * oob data has been consumed the oob indication is cleared.
   3009     0    stevel  *
   3010     0    stevel  * This logic keeps select/poll returning POLLRDBAND and
   3011     0    stevel  * SIOCATMARK returning true until we have read past
   3012     0    stevel  * the mark.
   3013     0    stevel  */
   3014     0    stevel static void
   3015     0    stevel sorecv_update_oobstate(struct sonode *so)
   3016     0    stevel {
   3017  8348      Eric 	sotpi_info_t *sti = SOTOTPI(so);
   3018  8348      Eric 
   3019     0    stevel 	mutex_enter(&so->so_lock);
   3020     0    stevel 	ASSERT(so_verify_oobstate(so));
   3021     0    stevel 	dprintso(so, 1,
   3022  5240  nordmark 	    ("sorecv_update_oobstate: counts %d/%d state %s\n",
   3023  8348      Eric 	    sti->sti_oobsigcnt,
   3024  8348      Eric 	    sti->sti_oobcnt, pr_state(so->so_state, so->so_mode)));
   3025  8348      Eric 	if (sti->sti_oobsigcnt == 0) {
   3026     0    stevel 		/* No more pending oob indications */
   3027     0    stevel 		so->so_state &= ~(SS_OOBPEND|SS_HAVEOOBDATA|SS_RCVATMARK);
   3028     0    stevel 		freemsg(so->so_oobmsg);
   3029     0    stevel 		so->so_oobmsg = NULL;
   3030     0    stevel 	}
   3031     0    stevel 	ASSERT(so_verify_oobstate(so));
   3032     0    stevel 	mutex_exit(&so->so_lock);
   3033     0    stevel }
   3034     0    stevel 
   3035     0    stevel /*
   3036     0    stevel  * Handle recv* calls for an so which has NL7C saved recv mblk_t(s).
   3037     0    stevel  */
   3038     0    stevel static int
   3039     0    stevel nl7c_sorecv(struct sonode *so, mblk_t **rmp, uio_t *uiop, rval_t *rp)
   3040     0    stevel {
   3041  8348      Eric 	sotpi_info_t *sti = SOTOTPI(so);
   3042     0    stevel 	int	error = 0;
   3043     0    stevel 	mblk_t *tmp = NULL;
   3044     0    stevel 	mblk_t *pmp = NULL;
   3045  8348      Eric 	mblk_t *nmp = sti->sti_nl7c_rcv_mp;
   3046     0    stevel 
   3047     0    stevel 	ASSERT(nmp != NULL);
   3048     0    stevel 
   3049     0    stevel 	while (nmp != NULL && uiop->uio_resid > 0) {
   3050     0    stevel 		ssize_t n;
   3051     0    stevel 
   3052     0    stevel 		if (DB_TYPE(nmp) == M_DATA) {
   3053     0    stevel 			/*
   3054     0    stevel 			 * We have some data, uiomove up to resid bytes.
   3055     0    stevel 			 */
   3056     0    stevel 			n = MIN(MBLKL(nmp), uiop->uio_resid);
   3057     0    stevel 			if (n > 0)
   3058     0    stevel 				error = uiomove(nmp->b_rptr, n, UIO_READ, uiop);
   3059     0    stevel 			nmp->b_rptr += n;
   3060     0    stevel 			if (nmp->b_rptr == nmp->b_wptr) {
   3061     0    stevel 				pmp = nmp;
   3062     0    stevel 				nmp = nmp->b_cont;
   3063     0    stevel 			}
   3064  1974    brutus 			if (error)
   3065  1974    brutus 				break;
   3066     0    stevel 		} else {
   3067     0    stevel 			/*
   3068     0    stevel 			 * We only handle data, save for caller to handle.
   3069     0    stevel 			 */
   3070     0    stevel 			if (pmp != NULL) {
   3071     0    stevel 				pmp->b_cont = nmp->b_cont;
   3072     0    stevel 			}
   3073     0    stevel 			nmp->b_cont = NULL;
   3074     0    stevel 			if (*rmp == NULL) {
   3075     0    stevel 				*rmp = nmp;
   3076     0    stevel 			} else {
   3077  1974    brutus 				tmp->b_cont = nmp;
   3078     0    stevel 			}
   3079     0    stevel 			nmp = nmp->b_cont;
   3080     0    stevel 			tmp = nmp;
   3081     0    stevel 		}
   3082     0    stevel 	}
   3083     0    stevel 	if (pmp != NULL) {
   3084     0    stevel 		/* Free any mblk_t(s) which we have consumed */
   3085     0    stevel 		pmp->b_cont = NULL;
   3086  8348      Eric 		freemsg(sti->sti_nl7c_rcv_mp);
   3087  8348      Eric 	}
   3088  8348      Eric 	if ((sti->sti_nl7c_rcv_mp = nmp) == NULL) {
   3089  1974    brutus 		/* Last mblk_t so return the saved kstrgetmsg() rval/error */
   3090  1974    brutus 		if (error == 0) {
   3091  8348      Eric 			rval_t	*p = (rval_t *)&sti->sti_nl7c_rcv_rval;
   3092  1974    brutus 
   3093  1974    brutus 			error = p->r_v.r_v2;
   3094  1974    brutus 			p->r_v.r_v2 = 0;
   3095  1974    brutus 		}
   3096  8348      Eric 		rp->r_vals = sti->sti_nl7c_rcv_rval;
   3097  8348      Eric 		sti->sti_nl7c_rcv_rval = 0;
   3098     0    stevel 	} else {
   3099     0    stevel 		/* More mblk_t(s) to process so no rval to return */
   3100     0    stevel 		rp->r_vals =