usr/src/uts/common/fs/sockfs/socktpi.c
author kais
Sat, 12 Nov 2005 18:58:05 -0800
changeset 898 64b2a371a6bd
parent 741 40027a3621ac
child 1092 11ac87ff53c2
permissions -rw-r--r--
PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy 4931229 Kernel-level SSL proxy
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
     1
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
     2
 * CDDL HEADER START
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
     3
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
     4
 * The contents of this file are subject to the terms of the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
     5
 * Common Development and Distribution License, Version 1.0 only
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
     6
 * (the "License").  You may not use this file except in compliance
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
     7
 * with the License.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
     8
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
     9
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    10
 * or http://www.opensolaris.org/os/licensing.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    11
 * See the License for the specific language governing permissions
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    12
 * and limitations under the License.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    13
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    14
 * When distributing Covered Code, include this CDDL HEADER in each
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    15
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    16
 * If applicable, add the following below this CDDL HEADER, with the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    17
 * fields enclosed by brackets "[]" replaced with your own identifying
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    18
 * information: Portions Copyright [yyyy] [name of copyright owner]
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    19
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    20
 * CDDL HEADER END
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    21
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    22
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    23
 * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    24
 * Use is subject to license terms.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    25
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    26
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    27
#pragma ident	"%Z%%M%	%I%	%E% SMI"
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    28
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    29
#include <sys/types.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    30
#include <sys/t_lock.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    31
#include <sys/param.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    32
#include <sys/systm.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    33
#include <sys/buf.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    34
#include <sys/conf.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    35
#include <sys/cred.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    36
#include <sys/kmem.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    37
#include <sys/sysmacros.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    38
#include <sys/vfs.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    39
#include <sys/vnode.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    40
#include <sys/debug.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    41
#include <sys/errno.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    42
#include <sys/time.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    43
#include <sys/file.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    44
#include <sys/open.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    45
#include <sys/user.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    46
#include <sys/termios.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    47
#include <sys/stream.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    48
#include <sys/strsubr.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    49
#include <sys/strsun.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    50
#include <sys/ddi.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    51
#include <sys/esunddi.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    52
#include <sys/flock.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    53
#include <sys/modctl.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    54
#include <sys/vtrace.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    55
#include <sys/cmn_err.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    56
#include <sys/pathname.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    57
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    58
#include <sys/socket.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    59
#include <sys/socketvar.h>
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
    60
#include <sys/sockio.h>
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    61
#include <netinet/in.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    62
#include <sys/un.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    63
#include <sys/strsun.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    64
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    65
#include <sys/tiuser.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    66
#define	_SUN_TPI_VERSION	2
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    67
#include <sys/tihdr.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    68
#include <sys/timod.h>		/* TI_GETMYNAME, TI_GETPEERNAME */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    69
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    70
#include <c2/audit.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    71
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    72
#include <inet/common.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    73
#include <inet/ip.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    74
#include <inet/ip6.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    75
#include <inet/tcp.h>
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
    76
#include <inet/udp_impl.h>
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    77
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    78
#include <fs/sockfs/nl7c.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    79
#include <sys/zone.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    80
898
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 741
diff changeset
    81
#include <inet/kssl/ksslapi.h>
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 741
diff changeset
    82
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    83
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    84
 * Possible failures when memory can't be allocated. The documented behavior:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    85
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    86
 * 		5.5:			4.X:		XNET:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    87
 * accept:	ENOMEM/ENOSR/EINTR	- (EINTR)	ENOMEM/ENOBUFS/ENOSR/
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    88
 *							EINTR
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    89
 *	(4.X does not document EINTR but returns it)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    90
 * bind:	ENOSR			-		ENOBUFS/ENOSR
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    91
 * connect: 	EINTR			EINTR		ENOBUFS/ENOSR/EINTR
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    92
 * getpeername:	ENOMEM/ENOSR		ENOBUFS (-)	ENOBUFS/ENOSR
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    93
 * getsockname:	ENOMEM/ENOSR		ENOBUFS (-)	ENOBUFS/ENOSR
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    94
 *	(4.X getpeername and getsockname do not fail in practice)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    95
 * getsockopt:	ENOMEM/ENOSR		-		ENOBUFS/ENOSR
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    96
 * listen:	-			-		ENOBUFS
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    97
 * recv:	ENOMEM/ENOSR/EINTR	EINTR		ENOBUFS/ENOMEM/ENOSR/
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    98
 *							EINTR
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    99
 * send:	ENOMEM/ENOSR/EINTR	ENOBUFS/EINTR	ENOBUFS/ENOMEM/ENOSR/
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   100
 *							EINTR
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   101
 * setsockopt:	ENOMEM/ENOSR		-		ENOBUFS/ENOMEM/ENOSR
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   102
 * shutdown:	ENOMEM/ENOSR		-		ENOBUFS/ENOSR
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   103
 * socket:	ENOMEM/ENOSR		ENOBUFS		ENOBUFS/ENOMEM/ENOSR
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   104
 * socketpair:	ENOMEM/ENOSR		-		ENOBUFS/ENOMEM/ENOSR
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   105
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   106
 * Resolution. When allocation fails:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   107
 *	recv: return EINTR
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   108
 *	send: return EINTR
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   109
 *	connect, accept: EINTR
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   110
 *	bind, listen, shutdown (unbind, unix_close, disconnect): sleep
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   111
 *	socket, socketpair: ENOBUFS
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   112
 *	getpeername, getsockname: sleep
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   113
 *	getsockopt, setsockopt: sleep
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   114
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   115
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   116
#ifdef SOCK_TEST
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   117
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   118
 * Variables that make sockfs do something other than the standard TPI
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   119
 * for the AF_INET transports.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   120
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   121
 * solisten_tpi_tcp:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   122
 *	TCP can handle a O_T_BIND_REQ with an increased backlog even though
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   123
 *	the transport is already bound. This is needed to avoid loosing the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   124
 *	port number should listen() do a T_UNBIND_REQ followed by a
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   125
 *	O_T_BIND_REQ.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   126
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   127
 * soconnect_tpi_udp:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   128
 *	UDP and ICMP can handle a T_CONN_REQ.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   129
 *	This is needed to make the sequence of connect(), getsockname()
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   130
 *	return the local IP address used to send packets to the connected to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   131
 *	destination.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   132
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   133
 * soconnect_tpi_tcp:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   134
 *	TCP can handle a T_CONN_REQ without seeing a O_T_BIND_REQ.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   135
 *	Set this to non-zero to send TPI conformant messages to TCP in this
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   136
 *	respect. This is a performance optimization.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   137
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   138
 * soaccept_tpi_tcp:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   139
 *	TCP can handle a T_CONN_REQ without the acceptor being bound.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   140
 *	This is a performance optimization that has been picked up in XTI.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   141
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   142
 * soaccept_tpi_multioptions:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   143
 *	When inheriting SOL_SOCKET options from the listener to the accepting
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   144
 *	socket send them as a single message for AF_INET{,6}.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   145
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   146
int solisten_tpi_tcp = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   147
int soconnect_tpi_udp = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   148
int soconnect_tpi_tcp = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   149
int soaccept_tpi_tcp = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   150
int soaccept_tpi_multioptions = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   151
#else /* SOCK_TEST */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   152
#define	soconnect_tpi_tcp	0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   153
#define	soconnect_tpi_udp	0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   154
#define	solisten_tpi_tcp	0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   155
#define	soaccept_tpi_tcp	0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   156
#define	soaccept_tpi_multioptions	1
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   157
#endif /* SOCK_TEST */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   158
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   159
#ifdef SOCK_TEST
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   160
extern int do_useracc;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   161
extern clock_t sock_test_timelimit;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   162
#endif /* SOCK_TEST */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   163
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   164
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   165
 * Some X/Open added checks might have to be backed out to keep SunOS 4.X
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   166
 * applications working. Turn on this flag to disable these checks.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   167
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   168
int xnet_skip_checks = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   169
int xnet_check_print = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   170
int xnet_truncate_print = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   171
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   172
extern	void sigintr(k_sigset_t *, int);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   173
extern	void sigunintr(k_sigset_t *);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   174
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   175
extern	void *nl7c_lookup_addr(void *, t_uscalar_t);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   176
extern	void *nl7c_add_addr(void *, t_uscalar_t);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   177
extern	void nl7c_listener_addr(void *, queue_t *);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   178
898
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 741
diff changeset
   179
/* Sockets acting as an in-kernel SSL proxy */
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 741
diff changeset
   180
extern mblk_t	*strsock_kssl_input(vnode_t *, mblk_t *, strwakeup_t *,
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 741
diff changeset
   181
		    strsigset_t *, strsigset_t *, strpollset_t *);
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 741
diff changeset
   182
extern mblk_t	*strsock_kssl_output(vnode_t *, mblk_t *, strwakeup_t *,
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 741
diff changeset
   183
		    strsigset_t *, strsigset_t *, strpollset_t *);
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 741
diff changeset
   184
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   185
static int	sotpi_unbind(struct sonode *, int);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   186
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   187
/* TPI sockfs sonode operations */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   188
static int	sotpi_accept(struct sonode *, int, struct sonode **);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   189
static int	sotpi_bind(struct sonode *, struct sockaddr *, socklen_t,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   190
		    int);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   191
static int	sotpi_connect(struct sonode *, const struct sockaddr *,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   192
		    socklen_t, int, int);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   193
static int	sotpi_listen(struct sonode *, int);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   194
static int	sotpi_sendmsg(struct sonode *, struct nmsghdr *,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   195
		    struct uio *);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   196
static int	sotpi_shutdown(struct sonode *, int);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   197
static int	sotpi_getsockname(struct sonode *);
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
   198
static int	sosend_dgramcmsg(struct sonode *, struct sockaddr *, socklen_t,
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
   199
		    struct uio *, void *, t_uscalar_t, int);
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
   200
static int	sodgram_direct(struct sonode *, struct sockaddr *,
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
   201
		    socklen_t, struct uio *, int);
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   202
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   203
sonodeops_t sotpi_sonodeops = {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   204
	sotpi_accept,		/* sop_accept		*/
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   205
	sotpi_bind,		/* sop_bind		*/
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   206
	sotpi_listen,		/* sop_listen		*/
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   207
	sotpi_connect,		/* sop_connect		*/
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   208
	sotpi_recvmsg,		/* sop_recvmsg		*/
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   209
	sotpi_sendmsg,		/* sop_sendmsg		*/
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   210
	sotpi_getpeername,	/* sop_getpeername	*/
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   211
	sotpi_getsockname,	/* sop_getsockname	*/
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   212
	sotpi_shutdown,		/* sop_shutdown		*/
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   213
	sotpi_getsockopt,	/* sop_getsockopt	*/
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   214
	sotpi_setsockopt	/* sop_setsockopt	*/
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   215
};
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   216
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   217
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   218
 * Common create code for socket and accept. If tso is set the values
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   219
 * from that node is used instead of issuing a T_INFO_REQ.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   220
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   221
 * Assumes that the caller has a VN_HOLD on accessvp.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   222
 * The VN_RELE will occur either when sotpi_create() fails or when
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   223
 * the returned sonode is freed.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   224
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   225
struct sonode *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   226
sotpi_create(vnode_t *accessvp, int domain, int type, int protocol, int version,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   227
    struct sonode *tso, int *errorp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   228
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   229
	struct sonode	*so;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   230
	vnode_t		*vp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   231
	int		flags, error;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   232
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   233
	ASSERT(accessvp != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   234
	vp = makesockvp(accessvp, domain, type, protocol);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   235
	ASSERT(vp != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   236
	so = VTOSO(vp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   237
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   238
	flags = FREAD|FWRITE;
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
   239
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
   240
	if ((type == SOCK_STREAM || type == SOCK_DGRAM) &&
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
   241
	    (domain == AF_INET || domain == AF_INET6) &&
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
   242
	    (protocol == IPPROTO_TCP || protocol == IPPROTO_UDP ||
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
   243
	    protocol == IPPROTO_IP)) {
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
   244
		/* Tell tcp or udp that it's talking to sockets */
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
   245
		flags |= SO_SOCKSTR;
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
   246
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
   247
		/*
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
   248
		 * Here we indicate to socktpi_open() our attempt to
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
   249
		 * make direct calls between sockfs and transport.
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
   250
		 * The final decision is left to socktpi_open().
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
   251
		 */
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
   252
		so->so_state |= SS_DIRECT;
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
   253
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
   254
		ASSERT(so->so_type != SOCK_DGRAM || tso == NULL);
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
   255
		if (so->so_type == SOCK_STREAM && tso != NULL) {
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
   256
			if (tso->so_state & SS_DIRECT) {
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
   257
				/*
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
   258
				 * Inherit SS_DIRECT from listener and pass
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
   259
				 * SO_ACCEPTOR open flag to tcp, indicating
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
   260
				 * that this is an accept fast-path instance.
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
   261
				 */
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
   262
				flags |= SO_ACCEPTOR;
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
   263
			} else {
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
   264
				/*
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
   265
				 * SS_DIRECT is not set on listener, meaning
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
   266
				 * that the listener has been converted from
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
   267
				 * a socket to a stream.  Ensure that the
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
   268
				 * acceptor inherits these settings.
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
   269
				 */
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
   270
				so->so_state &= ~SS_DIRECT;
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
   271
				flags &= ~SO_SOCKSTR;
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
   272
			}
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   273
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   274
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   275
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   276
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   277
	 * Tell local transport that it is talking to sockets.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   278
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   279
	if (so->so_family == AF_UNIX) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   280
		flags |= SO_SOCKSTR;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   281
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   282
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   283
	if (error = socktpi_open(&vp, flags, CRED())) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   284
		VN_RELE(vp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   285
		*errorp = error;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   286
		return (NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   287
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   288
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   289
	if (error = so_strinit(so, tso)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   290
		(void) VOP_CLOSE(vp, 0, 1, 0, CRED());
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   291
		VN_RELE(vp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   292
		*errorp = error;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   293
		return (NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   294
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   295
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   296
	if (version == SOV_DEFAULT)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   297
		version = so_default_version;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   298
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   299
	so->so_version = (short)version;
898
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 741
diff changeset
   300
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 741
diff changeset
   301
	/* Initialize the kernel SSL proxy fields */
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 741
diff changeset
   302
	so->so_kssl_type = KSSL_NO_PROXY;
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 741
diff changeset
   303
	so->so_kssl_ent = NULL;
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 741
diff changeset
   304
	so->so_kssl_ctx = NULL;
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 741
diff changeset
   305
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   306
	return (so);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   307
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   308
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   309
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   310
 * Bind the socket to an unspecified address in sockfs only.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   311
 * Used for TCP/UDP transports where we know that the O_T_BIND_REQ isn't
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   312
 * required in all cases.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   313
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   314
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   315
so_automatic_bind(struct sonode *so)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   316
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   317
	ASSERT(so->so_family == AF_INET || so->so_family == AF_INET6);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   318
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   319
	ASSERT(MUTEX_HELD(&so->so_lock));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   320
	ASSERT(!(so->so_state & SS_ISBOUND));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   321
	ASSERT(so->so_unbind_mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   322
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   323
	ASSERT(so->so_laddr_len <= so->so_laddr_maxlen);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   324
	bzero(so->so_laddr_sa, so->so_laddr_len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   325
	so->so_laddr_sa->sa_family = so->so_family;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   326
	so->so_state |= SS_ISBOUND;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   327
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   328
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   329
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   330
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   331
 * bind the socket.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   332
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   333
 * If the socket is already bound and none of _SOBIND_SOCKBSD or _SOBIND_XPG4_2
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   334
 * are passed in we allow rebinding. Note that for backwards compatibility
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   335
 * even "svr4" sockets pass in _SOBIND_SOCKBSD/SOV_SOCKBSD to sobind/bind.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   336
 * Thus the rebinding code is currently not executed.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   337
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   338
 * The constraints for rebinding are:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   339
 * - it is a SOCK_DGRAM, or
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   340
 * - it is a SOCK_STREAM/SOCK_SEQPACKET that has not been connected
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   341
 *   and no listen() has been done.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   342
 * This rebinding code was added based on some language in the XNET book
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   343
 * about not returning EINVAL it the protocol allows rebinding. However,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   344
 * this language is not present in the Posix socket draft. Thus maybe the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   345
 * rebinding logic should be deleted from the source.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   346
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   347
 * A null "name" can be used to unbind the socket if:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   348
 * - it is a SOCK_DGRAM, or
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   349
 * - it is a SOCK_STREAM/SOCK_SEQPACKET that has not been connected
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   350
 *   and no listen() has been done.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   351
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   352
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   353
sotpi_bindlisten(struct sonode *so, struct sockaddr *name,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   354
    socklen_t namelen, int backlog, int flags)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   355
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   356
	struct T_bind_req	bind_req;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   357
	struct T_bind_ack	*bind_ack;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   358
	int			error = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   359
	mblk_t			*mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   360
	void			*addr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   361
	t_uscalar_t		addrlen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   362
	int			unbind_on_err = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   363
	boolean_t		clear_acceptconn_on_err = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   364
	boolean_t		restore_backlog_on_err = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   365
	int			save_so_backlog;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   366
	t_scalar_t		PRIM_type = O_T_BIND_REQ;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   367
	boolean_t		tcp_udp_xport;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   368
	void			*nl7c = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   369
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   370
	dprintso(so, 1, ("sotpi_bindlisten(%p, %p, %d, %d, 0x%x) %s\n",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   371
		so, name, namelen, backlog, flags,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   372
		pr_state(so->so_state, so->so_mode)));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   373
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   374
	tcp_udp_xport = so->so_type == SOCK_STREAM || so->so_type == SOCK_DGRAM;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   375
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   376
	if (!(flags & _SOBIND_LOCK_HELD)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   377
		mutex_enter(&so->so_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   378
		so_lock_single(so);	/* Set SOLOCKED */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   379
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   380
		ASSERT(MUTEX_HELD(&so->so_lock));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   381
		ASSERT(so->so_flag & SOLOCKED);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   382
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   383
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   384
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   385
	 * Make sure that there is a preallocated unbind_req message
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   386
	 * before binding. This message allocated when the socket is
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   387
	 * created  but it might be have been consumed.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   388
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   389
	if (so->so_unbind_mp == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   390
		dprintso(so, 1, ("sobind: allocating unbind_req\n"));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   391
		/* NOTE: holding so_lock while sleeping */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   392
		so->so_unbind_mp =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   393
		    soallocproto(sizeof (struct T_unbind_req), _ALLOC_SLEEP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   394
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   395
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   396
	if (flags & _SOBIND_REBIND) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   397
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   398
		 * Called from solisten after doing an sotpi_unbind() or
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   399
		 * potentially without the unbind (latter for AF_INET{,6}).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   400
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   401
		ASSERT(name == NULL && namelen == 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   402
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   403
		if (so->so_family == AF_UNIX) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   404
			ASSERT(so->so_ux_bound_vp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   405
			addr = &so->so_ux_laddr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   406
			addrlen = (t_uscalar_t)sizeof (so->so_ux_laddr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   407
			dprintso(so, 1,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   408
			("sobind rebind UNIX: addrlen %d, addr 0x%p, vp %p\n",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   409
			    addrlen,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   410
			    ((struct so_ux_addr *)addr)->soua_vp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   411
			    so->so_ux_bound_vp));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   412
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   413
			addr = so->so_laddr_sa;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   414
			addrlen = (t_uscalar_t)so->so_laddr_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   415
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   416
	} else if (flags & _SOBIND_UNSPEC) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   417
		ASSERT(name == NULL && namelen == 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   418
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   419
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   420
		 * The caller checked SS_ISBOUND but not necessarily
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   421
		 * under so_lock
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   422
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   423
		if (so->so_state & SS_ISBOUND) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   424
			/* No error */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   425
			goto done;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   426
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   427
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   428
		/* Set an initial local address */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   429
		switch (so->so_family) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   430
		case AF_UNIX:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   431
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   432
			 * Use an address with same size as struct sockaddr
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   433
			 * just like BSD.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   434
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   435
			so->so_laddr_len =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   436
				(socklen_t)sizeof (struct sockaddr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   437
			ASSERT(so->so_laddr_len <= so->so_laddr_maxlen);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   438
			bzero(so->so_laddr_sa, so->so_laddr_len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   439
			so->so_laddr_sa->sa_family = so->so_family;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   440
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   441
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   442
			 * Pass down an address with the implicit bind
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   443
			 * magic number and the rest all zeros.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   444
			 * The transport will return a unique address.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   445
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   446
			so->so_ux_laddr.soua_vp = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   447
			so->so_ux_laddr.soua_magic = SOU_MAGIC_IMPLICIT;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   448
			addr = &so->so_ux_laddr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   449
			addrlen = (t_uscalar_t)sizeof (so->so_ux_laddr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   450
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   451
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   452
		case AF_INET:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   453
		case AF_INET6:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   454
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   455
			 * An unspecified bind in TPI has a NULL address.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   456
			 * Set the address in sockfs to have the sa_family.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   457
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   458
			so->so_laddr_len = (so->so_family == AF_INET) ?
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   459
			    (socklen_t)sizeof (sin_t) :
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   460
			    (socklen_t)sizeof (sin6_t);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   461
			ASSERT(so->so_laddr_len <= so->so_laddr_maxlen);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   462
			bzero(so->so_laddr_sa, so->so_laddr_len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   463
			so->so_laddr_sa->sa_family = so->so_family;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   464
			addr = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   465
			addrlen = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   466
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   467
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   468
		default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   469
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   470
			 * An unspecified bind in TPI has a NULL address.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   471
			 * Set the address in sockfs to be zero length.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   472
			 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   473
			 * Can not assume there is a sa_family for all
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   474
			 * protocol families. For example, AF_X25 does not
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   475
			 * have a family field.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   476
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   477
			so->so_laddr_len = 0;	/* XXX correct? */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   478
			bzero(so->so_laddr_sa, so->so_laddr_len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   479
			addr = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   480
			addrlen = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   481
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   482
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   483
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   484
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   485
		if (so->so_state & SS_ISBOUND) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   486
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   487
			 * If it is ok to rebind the socket, first unbind
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   488
			 * with the transport. A rebind to the NULL address
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   489
			 * is interpreted as an unbind.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   490
			 * Note that a bind to NULL in BSD does unbind the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   491
			 * socket but it fails with EINVAL.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   492
			 * Note that regular sockets set SOV_SOCKBSD i.e.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   493
			 * _SOBIND_SOCKBSD gets set here hence no type of
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   494
			 * socket does currently allow rebinding.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   495
			 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   496
			 * If the name is NULL just do an unbind.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   497
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   498
			if (flags & (_SOBIND_SOCKBSD|_SOBIND_XPG4_2) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   499
			    name != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   500
				error = EINVAL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   501
				unbind_on_err = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   502
				eprintsoline(so, error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   503
				goto done;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   504
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   505
			if ((so->so_mode & SM_CONNREQUIRED) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   506
			    (so->so_state & SS_CANTREBIND)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   507
				error = EINVAL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   508
				unbind_on_err = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   509
				eprintsoline(so, error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   510
				goto done;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   511
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   512
			error = sotpi_unbind(so, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   513
			if (error) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   514
				eprintsoline(so, error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   515
				goto done;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   516
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   517
			ASSERT(!(so->so_state & SS_ISBOUND));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   518
			if (name == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   519
				so->so_state &=
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   520
					~(SS_ISCONNECTED|SS_ISCONNECTING);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   521
				goto done;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   522
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   523
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   524
		/* X/Open requires this check */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   525
		if ((so->so_state & SS_CANTSENDMORE) && !xnet_skip_checks) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   526
			if (xnet_check_print) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   527
				printf("sockfs: X/Open bind state check "
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   528
				    "caused EINVAL\n");
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   529
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   530
			error = EINVAL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   531
			goto done;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   532
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   533
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   534
		switch (so->so_family) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   535
		case AF_UNIX:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   536
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   537
			 * All AF_UNIX addresses are nul terminated
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   538
			 * when copied (copyin_name) in so the minimum
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   539
			 * length is 3 bytes.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   540
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   541
			if (name == NULL ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   542
			    (ssize_t)namelen <= sizeof (short) + 1) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   543
				error = EISDIR;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   544
				eprintsoline(so, error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   545
				goto done;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   546
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   547
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   548
			 * Verify so_family matches the bound family.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   549
			 * BSD does not check this for AF_UNIX resulting
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   550
			 * in funny mknods.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   551
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   552
			if (name->sa_family != so->so_family) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   553
				error = EAFNOSUPPORT;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   554
				goto done;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   555
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   556
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   557
		case AF_INET:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   558
			if (name == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   559
				error = EINVAL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   560
				eprintsoline(so, error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   561
				goto done;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   562
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   563
			if ((size_t)namelen != sizeof (sin_t)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   564
				error = name->sa_family != so->so_family ?
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   565
				    EAFNOSUPPORT : EINVAL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   566
				eprintsoline(so, error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   567
				goto done;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   568
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   569
			if ((flags & _SOBIND_XPG4_2) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   570
			    (name->sa_family != so->so_family)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   571
				/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   572
				 * This check has to be made for X/Open
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   573
				 * sockets however application failures have
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   574
				 * been observed when it is applied to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   575
				 * all sockets.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   576
				 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   577
				error = EAFNOSUPPORT;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   578
				eprintsoline(so, error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   579
				goto done;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   580
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   581
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   582
			 * Force a zero sa_family to match so_family.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   583
			 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   584
			 * Some programs like inetd(1M) don't set the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   585
			 * family field. Other programs leave
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   586
			 * sin_family set to garbage - SunOS 4.X does
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   587
			 * not check the family field on a bind.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   588
			 * We use the family field that
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   589
			 * was passed in to the socket() call.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   590
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   591
			name->sa_family = so->so_family;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   592
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   593
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   594
		case AF_INET6: {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   595
#ifdef DEBUG
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   596
			sin6_t *sin6 = (sin6_t *)name;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   597
#endif /* DEBUG */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   598
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   599
			if (name == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   600
				error = EINVAL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   601
				eprintsoline(so, error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   602
				goto done;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   603
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   604
			if ((size_t)namelen != sizeof (sin6_t)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   605
				error = name->sa_family != so->so_family ?
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   606
				    EAFNOSUPPORT : EINVAL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   607
				eprintsoline(so, error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   608
				goto done;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   609
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   610
			if (name->sa_family != so->so_family) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   611
				/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   612
				 * With IPv6 we require the family to match
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   613
				 * unlike in IPv4.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   614
				 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   615
				error = EAFNOSUPPORT;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   616
				eprintsoline(so, error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   617
				goto done;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   618
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   619
#ifdef DEBUG
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   620
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   621
			 * Verify that apps don't forget to clear
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   622
			 * sin6_scope_id etc
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   623
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   624
			if (sin6->sin6_scope_id != 0 &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   625
			    !IN6_IS_ADDR_LINKSCOPE(&sin6->sin6_addr)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   626
				cmn_err(CE_WARN,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   627
				    "bind with uninitialized sin6_scope_id "
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   628
				    "(%d) on socket. Pid = %d\n",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   629
				    (int)sin6->sin6_scope_id,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   630
				    (int)curproc->p_pid);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   631
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   632
			if (sin6->__sin6_src_id != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   633
				cmn_err(CE_WARN,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   634
				    "bind with uninitialized __sin6_src_id "
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   635
				    "(%d) on socket. Pid = %d\n",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   636
				    (int)sin6->__sin6_src_id,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   637
				    (int)curproc->p_pid);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   638
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   639
#endif /* DEBUG */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   640
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   641
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   642
		default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   643
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   644
			 * Don't do any length or sa_family check to allow
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   645
			 * non-sockaddr style addresses.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   646
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   647
			if (name == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   648
				error = EINVAL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   649
				eprintsoline(so, error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   650
				goto done;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   651
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   652
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   653
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   654
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   655
		if (namelen > (t_uscalar_t)so->so_laddr_maxlen) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   656
			error = ENAMETOOLONG;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   657
			eprintsoline(so, error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   658
			goto done;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   659
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   660
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   661
		 * Save local address.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   662
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   663
		so->so_laddr_len = (socklen_t)namelen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   664
		ASSERT(so->so_laddr_len <= so->so_laddr_maxlen);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   665
		bcopy(name, so->so_laddr_sa, namelen);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   666
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   667
		addr = so->so_laddr_sa;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   668
		addrlen = (t_uscalar_t)so->so_laddr_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   669
		switch (so->so_family) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   670
		case AF_INET6:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   671
		case AF_INET:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   672
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   673
		case AF_UNIX: {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   674
			struct sockaddr_un *soun =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   675
				(struct sockaddr_un *)so->so_laddr_sa;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   676
			struct vnode *vp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   677
			struct vattr vattr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   678
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   679
			ASSERT(so->so_ux_bound_vp == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   680
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   681
			 * Create vnode for the specified path name.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   682
			 * Keep vnode held with a reference in so_ux_bound_vp.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   683
			 * Use the vnode pointer as the address used in the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   684
			 * bind with the transport.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   685
			 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   686
			 * Use the same mode as in BSD. In particular this does
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   687
			 * not observe the umask.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   688
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   689
			/* MAXPATHLEN + soun_family + nul termination */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   690
			if (so->so_laddr_len >
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   691
			    (socklen_t)(MAXPATHLEN + sizeof (short) + 1)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   692
				error = ENAMETOOLONG;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   693
				eprintsoline(so, error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   694
				goto done;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   695
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   696
			vattr.va_type = VSOCK;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   697
			vattr.va_mode = 0777 & ~u.u_cmask;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   698
			vattr.va_mask = AT_TYPE|AT_MODE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   699
			/* NOTE: holding so_lock */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   700
			error = vn_create(soun->sun_path, UIO_SYSSPACE, &vattr,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   701
						EXCL, 0, &vp, CRMKNOD, 0, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   702
			if (error) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   703
				if (error == EEXIST)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   704
					error = EADDRINUSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   705
				eprintsoline(so, error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   706
				goto done;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   707
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   708
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   709
			 * Establish pointer from the underlying filesystem
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   710
			 * vnode to the socket node.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   711
			 * so_ux_bound_vp and v_stream->sd_vnode form the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   712
			 * cross-linkage between the underlying filesystem
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   713
			 * node and the socket node.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   714
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   715
			ASSERT(SOTOV(so)->v_stream);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   716
			mutex_enter(&vp->v_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   717
			vp->v_stream = SOTOV(so)->v_stream;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   718
			so->so_ux_bound_vp = vp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   719
			mutex_exit(&vp->v_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   720
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   721
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   722
			 * Use the vnode pointer value as a unique address
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   723
			 * (together with the magic number to avoid conflicts
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   724
			 * with implicit binds) in the transport provider.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   725
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   726
			so->so_ux_laddr.soua_vp = (void *)so->so_ux_bound_vp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   727
			so->so_ux_laddr.soua_magic = SOU_MAGIC_EXPLICIT;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   728
			addr = &so->so_ux_laddr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   729
			addrlen = (t_uscalar_t)sizeof (so->so_ux_laddr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   730
			dprintso(so, 1, ("sobind UNIX: addrlen %d, addr %p\n",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   731
			    addrlen,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   732
			    ((struct so_ux_addr *)addr)->soua_vp));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   733
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   734
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   735
		} /* end switch (so->so_family) */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   736
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   737
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   738
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   739
	 * set SS_ACCEPTCONN before sending down O_T_BIND_REQ since
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   740
	 * the transport can start passing up T_CONN_IND messages
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   741
	 * as soon as it receives the bind req and strsock_proto()
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   742
	 * insists that SS_ACCEPTCONN is set when processing T_CONN_INDs.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   743
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   744
	if (flags & _SOBIND_LISTEN) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   745
		if ((so->so_state & SS_ACCEPTCONN) == 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   746
			clear_acceptconn_on_err = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   747
		save_so_backlog = so->so_backlog;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   748
		restore_backlog_on_err = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   749
		so->so_state |= SS_ACCEPTCONN;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   750
		so->so_backlog = backlog;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   751
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   752
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   753
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   754
	 * If NL7C addr(s) have been configured check for addr/port match,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   755
	 * or if an implicit NL7C socket via AF_NCA mark socket as NL7C.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   756
	 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   757
	 * NL7C supports the TCP transport only so check AF_INET and AF_INET6
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   758
	 * family sockets only. If match mark as such.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   759
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   760
	if ((nl7c_enabled && addr != NULL &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   761
	    (so->so_family == AF_INET || so->so_family == AF_INET6) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   762
	    (nl7c = nl7c_lookup_addr(addr, addrlen))) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   763
	    so->so_nl7c_flags == NL7C_AF_NCA) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   764
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   765
		 * NL7C is not supported in non-global zones,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   766
		 * we enforce this restriction here.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   767
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   768
		if (so->so_zoneid == GLOBAL_ZONEID) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   769
			/* An NL7C socket, mark it */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   770
			so->so_nl7c_flags |= NL7C_ENABLED;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   771
		} else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   772
			nl7c = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   773
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   774
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   775
	 * We send a T_BIND_REQ for TCP/UDP since we know it supports it,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   776
	 * for other transports we will send in a O_T_BIND_REQ.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   777
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   778
	if (tcp_udp_xport &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   779
	    (so->so_family == AF_INET || so->so_family == AF_INET6))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   780
		PRIM_type = T_BIND_REQ;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   781
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   782
	bind_req.PRIM_type = PRIM_type;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   783
	bind_req.ADDR_length = addrlen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   784
	bind_req.ADDR_offset = (t_scalar_t)sizeof (bind_req);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   785
	bind_req.CONIND_number = backlog;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   786
	/* NOTE: holding so_lock while sleeping */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   787
	mp = soallocproto2(&bind_req, sizeof (bind_req),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   788
				addr, addrlen, 0, _ALLOC_SLEEP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   789
	so->so_state &= ~SS_LADDR_VALID;
898
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 741
diff changeset
   790
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   791
	/* Done using so_laddr_sa - can drop the lock */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   792
	mutex_exit(&so->so_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   793
898
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 741
diff changeset
   794
	/*
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 741
diff changeset
   795
	 * Intercept the bind_req message here to check if this <address/port>
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 741
diff changeset
   796
	 * was configured as an SSL proxy server, or if another endpoint was
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 741
diff changeset
   797
	 * already configured to act as a proxy for us.
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 741
diff changeset
   798
	 */
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 741
diff changeset
   799
	if ((so->so_family == AF_INET || so->so_family == AF_INET6) &&
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 741
diff changeset
   800
	    so->so_type == SOCK_STREAM) {
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 741
diff changeset
   801
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 741
diff changeset
   802
		if (so->so_kssl_ent != NULL) {
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 741
diff changeset
   803
			kssl_release_ent(so->so_kssl_ent, so, so->so_kssl_type);
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 741
diff changeset
   804
			so->so_kssl_ent = NULL;
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 741
diff changeset
   805
		}
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 741
diff changeset
   806
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 741
diff changeset
   807
		so->so_kssl_type = kssl_check_proxy(mp, so, &so->so_kssl_ent);
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 741
diff changeset
   808
		switch (so->so_kssl_type) {
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 741
diff changeset
   809
		case KSSL_NO_PROXY:
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 741
diff changeset
   810
			break;
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 741
diff changeset
   811
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 741
diff changeset
   812
		case KSSL_HAS_PROXY:
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 741
diff changeset
   813
			mutex_enter(&so->so_lock);
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 741
diff changeset
   814
			goto skip_transport;
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 741
diff changeset
   815
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 741
diff changeset
   816
		case KSSL_IS_PROXY:
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 741
diff changeset
   817
			break;
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 741
diff changeset
   818
		}
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 741
diff changeset
   819
	}
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 741
diff changeset
   820
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   821
	error = kstrputmsg(SOTOV(so), mp, NULL, 0, 0,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   822
			MSG_BAND|MSG_HOLDSIG|MSG_IGNERROR, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   823
	if (error) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   824
		eprintsoline(so, error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   825
		mutex_enter(&so->so_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   826
		goto done;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   827
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   828
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   829
	mutex_enter(&so->so_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   830
	error = sowaitprim(so, PRIM_type, T_BIND_ACK,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   831
	    (t_uscalar_t)sizeof (*bind_ack), &mp, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   832
	if (error) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   833
		eprintsoline(so, error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   834
		goto done;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   835
	}
898
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 741
diff changeset
   836
skip_transport:
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   837
	ASSERT(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   838
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   839
	 * Even if some TPI message (e.g. T_DISCON_IND) was received in
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   840
	 * strsock_proto while the lock was dropped above, the bind
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   841
	 * is allowed to complete.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   842
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   843
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   844
	/* Mark as bound. This will be undone if we detect errors below. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   845
	if (flags & _SOBIND_NOXLATE) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   846
		ASSERT(so->so_family == AF_UNIX);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   847
		so->so_state |= SS_FADDR_NOXLATE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   848
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   849
	ASSERT(!(so->so_state & SS_ISBOUND) || (flags & _SOBIND_REBIND));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   850
	so->so_state |= SS_ISBOUND;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   851
	ASSERT(so->so_unbind_mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   852
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   853
	/* note that we've already set SS_ACCEPTCONN above */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   854
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   855
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   856
	 * Recompute addrlen - an unspecied bind sent down an
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   857
	 * address of length zero but we expect the appropriate length
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   858
	 * in return.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   859
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   860
	addrlen = (t_uscalar_t)(so->so_family == AF_UNIX ?
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   861
	    sizeof (so->so_ux_laddr) : so->so_laddr_len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   862
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   863
	bind_ack = (struct T_bind_ack *)mp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   864
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   865
	 * The alignment restriction is really too strict but
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   866
	 * we want enough alignment to inspect the fields of
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   867
	 * a sockaddr_in.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   868
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   869
	addr = sogetoff(mp, bind_ack->ADDR_offset,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   870
			bind_ack->ADDR_length,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   871
			__TPI_ALIGN_SIZE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   872
	if (addr == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   873
		freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   874
		error = EPROTO;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   875
		eprintsoline(so, error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   876
		goto done;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   877
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   878
	if (!(flags & _SOBIND_UNSPEC)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   879
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   880
		 * Verify that the transport didn't return something we
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   881
		 * did not want e.g. an address other than what we asked for.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   882
		 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   883
		 * NOTE: These checks would go away if/when we switch to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   884
		 * using the new TPI (in which the transport would fail
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   885
		 * the request instead of assigning a different address).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   886
		 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   887
		 * NOTE2: For protocols that we don't know (i.e. any
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   888
		 * other than AF_INET6, AF_INET and AF_UNIX), we
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   889
		 * cannot know if the transport should be expected to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   890
		 * return the same address as that requested.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   891
		 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   892
		 * NOTE3: For AF_INET and AF_INET6, TCP/UDP, we send
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   893
		 * down a T_BIND_REQ. We use O_T_BIND_REQ for others.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   894
		 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   895
		 * For example, in the case of netatalk it may be
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   896
		 * inappropriate for the transport to return the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   897
		 * requested address (as it may have allocated a local
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   898
		 * port number in behaviour similar to that of an
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   899
		 * AF_INET bind request with a port number of zero).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   900
		 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   901
		 * Given the definition of O_T_BIND_REQ, where the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   902
		 * transport may bind to an address other than the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   903
		 * requested address, it's not possible to determine
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   904
		 * whether a returned address that differs from the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   905
		 * requested address is a reason to fail (because the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   906
		 * requested address was not available) or succeed
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   907
		 * (because the transport allocated an appropriate
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   908
		 * address and/or port).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   909
		 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   910
		 * sockfs currently requires that the transport return
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   911
		 * the requested address in the T_BIND_ACK, unless
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   912
		 * there is code here to allow for any discrepancy.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   913
		 * Such code exists for AF_INET and AF_INET6.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   914
		 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   915
		 * Netatalk chooses to return the requested address
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   916
		 * rather than the (correct) allocated address.  This
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   917
		 * means that netatalk violates the TPI specification
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   918
		 * (and would not function correctly if used from a
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   919
		 * TLI application), but it does mean that it works
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   920
		 * with sockfs.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   921
		 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   922
		 * As noted above, using the newer XTI bind primitive
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   923
		 * (T_BIND_REQ) in preference to O_T_BIND_REQ would
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   924
		 * allow sockfs to be more sure about whether or not
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   925
		 * the bind request had succeeded (as transports are
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   926
		 * not permitted to bind to a different address than
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   927
		 * that requested - they must return failure).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   928
		 * Unfortunately, support for T_BIND_REQ may not be
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   929
		 * present in all transport implementations (netatalk,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   930
		 * for example, doesn't have it), making the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   931
		 * transition difficult.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   932
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   933
		if (bind_ack->ADDR_length != addrlen) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   934
			/* Assumes that the requested address was in use */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   935
			freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   936
			error = EADDRINUSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   937
			eprintsoline(so, error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   938
			goto done;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   939
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   940
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   941
		switch (so->so_family) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   942
		case AF_INET6:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   943
		case AF_INET: {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   944
			sin_t *rname, *aname;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   945
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   946
			rname = (sin_t *)addr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   947
			aname = (sin_t *)so->so_laddr_sa;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   948
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   949
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   950
			 * Take advantage of the alignment
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   951
			 * of sin_port and sin6_port which fall
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   952
			 * in the same place in their data structures.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   953
			 * Just use sin_port for either address family.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   954
			 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   955
			 * This may become a problem if (heaven forbid)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   956
			 * there's a separate ipv6port_reserved... :-P
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   957
			 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   958
			 * Binding to port 0 has the semantics of letting
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   959
			 * the transport bind to any port.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   960
			 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   961
			 * If the transport is TCP or UDP since we had sent
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   962
			 * a T_BIND_REQ we would not get a port other than
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   963
			 * what we asked for.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   964
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   965
			if (tcp_udp_xport) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   966
				/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   967
				 * Pick up the new port number if we bound to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   968
				 * port 0.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   969
				 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   970
				if (aname->sin_port == 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   971
					aname->sin_port = rname->sin_port;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   972
				so->so_state |= SS_LADDR_VALID;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   973
				break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   974
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   975
			if (aname->sin_port != 0 &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   976
			    aname->sin_port != rname->sin_port) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   977
				freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   978
				error = EADDRINUSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   979
				eprintsoline(so, error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   980
				goto done;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   981
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   982
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   983
			 * Pick up the new port number if we bound to port 0.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   984
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   985
			aname->sin_port = rname->sin_port;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   986
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   987
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   988
			 * Unfortunately, addresses aren't _quite_ the same.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   989
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   990
			if (so->so_family == AF_INET) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   991
				if (aname->sin_addr.s_addr !=
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   992
				    rname->sin_addr.s_addr) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   993
					freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   994
					error = EADDRNOTAVAIL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   995
					eprintsoline(so, error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   996
					goto done;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   997
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   998
			} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   999
				sin6_t *rname6 = (sin6_t *)rname;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1000
				sin6_t *aname6 = (sin6_t *)aname;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1001
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1002
				if (!IN6_ARE_ADDR_EQUAL(&aname6->sin6_addr,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1003
				    &rname6->sin6_addr)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1004
					freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1005
					error = EADDRNOTAVAIL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1006
					eprintsoline(so, error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1007
					goto done;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1008
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1009
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1010
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1011
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1012
		case AF_UNIX:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1013
			if (bcmp(addr, &so->so_ux_laddr, addrlen) != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1014
				freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1015
				error = EADDRINUSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1016
				eprintsoline(so, error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1017
				eprintso(so,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1018
					("addrlen %d, addr 0x%x, vp %p\n",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1019
					addrlen, *((int *)addr),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1020
					so->so_ux_bound_vp));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1021
				goto done;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1022
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1023
			so->so_state |= SS_LADDR_VALID;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1024
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1025
		default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1026
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1027
			 * NOTE: This assumes that addresses can be
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1028
			 * byte-compared for equivalence.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1029
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1030
			if (bcmp(addr, so->so_laddr_sa, addrlen) != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1031
				freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1032
				error = EADDRINUSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1033
				eprintsoline(so, error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1034
				goto done;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1035
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1036
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1037
			 * Don't mark SS_LADDR_VALID, as we cannot be
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1038
			 * sure that the returned address is the real
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1039
			 * bound address when talking to an unknown
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1040
			 * transport.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1041
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1042
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1043
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1044
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1045
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1046
		 * Save for returned address for getsockname.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1047
		 * Needed for unspecific bind unless transport supports
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1048
		 * the TI_GETMYNAME ioctl.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1049
		 * Do this for AF_INET{,6} even though they do, as
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1050
		 * caching info here is much better performance than
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1051
		 * a TPI/STREAMS trip to the transport for getsockname.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1052
		 * Any which can't for some reason _must_ _not_ set
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1053
		 * LADDR_VALID here for the caching version of getsockname
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1054
		 * to not break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1055
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1056
		switch (so->so_family) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1057
		case AF_UNIX:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1058
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1059
			 * Record the address bound with the transport
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1060
			 * for use by socketpair.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1061
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1062
			bcopy(addr, &so->so_ux_laddr, addrlen);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1063
			so->so_state |= SS_LADDR_VALID;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1064
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1065
		case AF_INET:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1066
		case AF_INET6:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1067
			ASSERT(so->so_laddr_len <= so->so_laddr_maxlen);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1068
			bcopy(addr, so->so_laddr_sa, so->so_laddr_len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1069
			so->so_state |= SS_LADDR_VALID;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1070
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1071
		default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1072
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1073
			 * Don't mark SS_LADDR_VALID, as we cannot be
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1074
			 * sure that the returned address is the real
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1075
			 * bound address when talking to an unknown
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1076
			 * transport.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1077
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1078
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1079
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1080
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1081
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1082
	if (nl7c == NULL && (so->so_nl7c_flags & NL7C_AF_NCA) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1083
	    (so->so_nl7c_flags & NL7C_ENABLED)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1084
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1085
		 * Was an AF_NCA bind() so add it to the addr list for
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1086
		 * reporting purposes.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1087
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1088
		nl7c = nl7c_add_addr(addr, addrlen);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1089
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1090
	if (nl7c != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1091
		nl7c_listener_addr(nl7c, strvp2wq(SOTOV(so)));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1092
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1093
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1094
	freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1095
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1096
done:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1097
	if (error) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1098
		/* reset state & backlog to values held on entry */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1099
		if (clear_acceptconn_on_err == B_TRUE)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1100
			so->so_state &= ~SS_ACCEPTCONN;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1101
		if (restore_backlog_on_err == B_TRUE)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1102
			so->so_backlog = save_so_backlog;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1103
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1104
		if (unbind_on_err && so->so_state & SS_ISBOUND) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1105
			int err;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1106
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1107
			err = sotpi_unbind(so, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1108
			/* LINTED - statement has no consequent: if */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1109
			if (err) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1110
				eprintsoline(so, error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1111
			} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1112
				ASSERT(!(so->so_state & SS_ISBOUND));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1113
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1114
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1115
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1116
	if (!(flags & _SOBIND_LOCK_HELD)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1117
		so_unlock_single(so, SOLOCKED);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1118
		mutex_exit(&so->so_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1119
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1120
		/* If the caller held the lock don't release it here */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1121
		ASSERT(MUTEX_HELD(&so->so_lock));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1122
		ASSERT(so->so_flag & SOLOCKED);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1123
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1124
	return (error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1125
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1126
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1127
/* bind the socket */
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  1128
static int
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1129
sotpi_bind(struct sonode *so, struct sockaddr *name, socklen_t namelen,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1130
    int flags)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1131
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1132
	if ((flags & _SOBIND_SOCKETPAIR) == 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1133
		return (sotpi_bindlisten(so, name, namelen, 0, flags));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1134
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1135
	flags &= ~_SOBIND_SOCKETPAIR;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1136
	return (sotpi_bindlisten(so, name, namelen, 1, flags));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1137
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1138
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1139
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1140
 * Unbind a socket - used when bind() fails, when bind() specifies a NULL
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1141
 * address, or when listen needs to unbind and bind.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1142
 * If the _SOUNBIND_REBIND flag is specified the addresses are retained
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1143
 * so that a sobind can pick them up.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1144
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1145
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1146
sotpi_unbind(struct sonode *so, int flags)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1147
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1148
	struct T_unbind_req	unbind_req;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1149
	int			error = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1150
	mblk_t			*mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1151
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1152
	dprintso(so, 1, ("sotpi_unbind(%p, 0x%x) %s\n",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1153
			so, flags, pr_state(so->so_state, so->so_mode)));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1154
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1155
	ASSERT(MUTEX_HELD(&so->so_lock));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1156
	ASSERT(so->so_flag & SOLOCKED);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1157
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1158
	if (!(so->so_state & SS_ISBOUND)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1159
		error = EINVAL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1160
		eprintsoline(so, error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1161
		goto done;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1162
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1163
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1164
	mutex_exit(&so->so_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1165
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1166
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1167
	 * Flush the read and write side (except stream head read queue)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1168
	 * and send down T_UNBIND_REQ.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1169
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1170
	(void) putnextctl1(strvp2wq(SOTOV(so)), M_FLUSH, FLUSHRW);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1171
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1172
	unbind_req.PRIM_type = T_UNBIND_REQ;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1173
	mp = soallocproto1(&unbind_req, sizeof (unbind_req),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1174
	    0, _ALLOC_SLEEP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1175
	error = kstrputmsg(SOTOV(so), mp, NULL, 0, 0,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1176
			MSG_BAND|MSG_HOLDSIG|MSG_IGNERROR, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1177
	mutex_enter(&so->so_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1178
	if (error) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1179
		eprintsoline(so, error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1180
		goto done;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1181
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1182
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1183
	error = sowaitokack(so, T_UNBIND_REQ);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1184
	if (error) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1185
		eprintsoline(so, error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1186
		goto done;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1187
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1188
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1189
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1190
	 * Even if some TPI message (e.g. T_DISCON_IND) was received in
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1191
	 * strsock_proto while the lock was dropped above, the unbind
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1192
	 * is allowed to complete.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1193
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1194
	if (!(flags & _SOUNBIND_REBIND)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1195
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1196
		 * Clear out bound address.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1197
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1198
		vnode_t *vp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1199
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1200
		if ((vp = so->so_ux_bound_vp) != NULL) {
898
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 741
diff changeset
  1201
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 741
diff changeset
  1202
			/* Undo any SSL proxy setup */
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 741
diff changeset
  1203
			if ((so->so_family == AF_INET ||
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 741
diff changeset
  1204
			    so->so_family == AF_INET6) &&
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 741
diff changeset
  1205
			    (so->so_type == SOCK_STREAM) &&
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 741
diff changeset
  1206
			    (so->so_kssl_ent != NULL)) {
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 741
diff changeset
  1207
				kssl_release_ent(so->so_kssl_ent, so,
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 741
diff changeset
  1208
				    so->so_kssl_type);
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 741
diff changeset
  1209
				so->so_kssl_ent = NULL;
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 741
diff changeset
  1210
				so->so_kssl_type = KSSL_NO_PROXY;
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 741
diff changeset
  1211
			}
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 741
diff changeset
  1212
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1213
			so->so_ux_bound_vp = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1214
			vn_rele_stream(vp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1215
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1216
		/* Clear out address */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1217
		so->so_laddr_len = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1218
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1219
	so->so_state &= ~(SS_ISBOUND|SS_ACCEPTCONN|SS_LADDR_VALID);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1220
done:
898
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 741
diff changeset
  1221
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1222
	/* If the caller held the lock don't release it here */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1223
	ASSERT(MUTEX_HELD(&so->so_lock));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1224
	ASSERT(so->so_flag & SOLOCKED);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1225
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1226
	return (error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1227
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1228
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1229
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1230
 * listen on the socket.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1231
 * For TPI conforming transports this has to first unbind with the transport
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1232
 * and then bind again using the new backlog.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1233
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1234
int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1235
sotpi_listen(struct sonode *so, int backlog)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1236
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1237
	int		error = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1238
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1239
	dprintso(so, 1, ("sotpi_listen(%p, %d) %s\n",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1240
		so, backlog, pr_state(so->so_state, so->so_mode)));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1241
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1242
	if (so->so_serv_type == T_CLTS)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1243
		return (EOPNOTSUPP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1244
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1245
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1246
	 * If the socket is ready to accept connections already, then
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1247
	 * return without doing anything.  This avoids a problem where
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1248
	 * a second listen() call fails if a connection is pending and
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1249
	 * leaves the socket unbound. Only when we are not unbinding
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1250
	 * with the transport can we safely increase the backlog.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1251
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1252
	if (so->so_state & SS_ACCEPTCONN &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1253
	    !((so->so_family == AF_INET || so->so_family == AF_INET6) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1254
		/*CONSTCOND*/
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1255
		!solisten_tpi_tcp))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1256
		return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1257
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1258
	if (so->so_state & SS_ISCONNECTED)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1259
		return (EINVAL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1260
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1261
	mutex_enter(&so->so_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1262
	so_lock_single(so);	/* Set SOLOCKED */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1263
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1264
	if (backlog < 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1265
		backlog = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1266
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1267
	 * Use the same qlimit as in BSD. BSD checks the qlimit
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1268
	 * before queuing the next connection implying that a
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1269
	 * listen(sock, 0) allows one connection to be queued.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1270
	 * BSD also uses 1.5 times the requested backlog.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1271
	 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1272
	 * XNS Issue 4 required a strict interpretation of the backlog.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1273
	 * This has been waived subsequently for Issue 4 and the change
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1274
	 * incorporated in XNS Issue 5. So we aren't required to do
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1275
	 * anything special for XPG apps.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1276
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1277
	if (backlog >= (INT_MAX - 1) / 3)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1278
		backlog = INT_MAX;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1279
	else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1280
		backlog = backlog * 3 / 2 + 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1281
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1282
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1283
	 * If the listen doesn't change the backlog we do nothing.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1284
	 * This avoids an EPROTO error from the transport.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1285
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1286
	if ((so->so_state & SS_ACCEPTCONN) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1287
	    so->so_backlog == backlog)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1288
		goto done;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1289
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1290
	if (!(so->so_state & SS_ISBOUND)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1291
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1292
		 * Must have been explicitly bound in the UNIX domain.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1293
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1294
		if (so->so_family == AF_UNIX) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1295
			error = EINVAL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1296
			goto done;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1297
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1298
		error = sotpi_bindlisten(so, NULL, 0, backlog,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1299
			    _SOBIND_UNSPEC|_SOBIND_LOCK_HELD|_SOBIND_LISTEN);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1300
	} else if (backlog > 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1301
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1302
		 * AF_INET{,6} hack to avoid losing the port.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1303
		 * Assumes that all AF_INET{,6} transports can handle a
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1304
		 * O_T_BIND_REQ with a non-zero CONIND_number when the TPI
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1305
		 * has already bound thus it is possible to avoid the unbind.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1306
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1307
		if (!((so->so_family == AF_INET || so->so_family == AF_INET6) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1308
		    /*CONSTCOND*/
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1309
		    !solisten_tpi_tcp)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1310
			error = sotpi_unbind(so, _SOUNBIND_REBIND);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1311
			if (error)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1312
				goto done;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1313
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1314
		error = sotpi_bindlisten(so, NULL, 0, backlog,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1315
			    _SOBIND_REBIND|_SOBIND_LOCK_HELD|_SOBIND_LISTEN);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1316
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1317
		so->so_state |= SS_ACCEPTCONN;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1318
		so->so_backlog = backlog;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1319
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1320
	if (error)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1321
		goto done;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1322
	ASSERT(so->so_state & SS_ACCEPTCONN);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1323
done:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1324
	so_unlock_single(so, SOLOCKED);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1325
	mutex_exit(&so->so_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1326
	return (error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1327
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1328
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1329
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1330
 * Disconnect either a specified seqno or all (-1).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1331
 * The former is used on listening sockets only.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1332
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1333
 * When seqno == -1 sodisconnect could call sotpi_unbind. However,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1334
 * the current use of sodisconnect(seqno == -1) is only for shutdown
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1335
 * so there is no point (and potentially incorrect) to unbind.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1336
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1337
int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1338
sodisconnect(struct sonode *so, t_scalar_t seqno, int flags)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1339
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1340
	struct T_discon_req	discon_req;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1341
	int			error = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1342
	mblk_t			*mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1343
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1344
	dprintso(so, 1, ("sodisconnect(%p, %d, 0x%x) %s\n",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1345
			so, seqno, flags, pr_state(so->so_state, so->so_mode)));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1346
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1347
	if (!(flags & _SODISCONNECT_LOCK_HELD)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1348
		mutex_enter(&so->so_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1349
		so_lock_single(so);	/* Set SOLOCKED */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1350
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1351
		ASSERT(MUTEX_HELD(&so->so_lock));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1352
		ASSERT(so->so_flag & SOLOCKED);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1353
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1354
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1355
	if (!(so->so_state & (SS_ISCONNECTED|SS_ISCONNECTING|SS_ACCEPTCONN))) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1356
		error = EINVAL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1357
		eprintsoline(so, error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1358
		goto done;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1359
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1360
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1361
	mutex_exit(&so->so_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1362
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1363
	 * Flush the write side (unless this is a listener)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1364
	 * and then send down a T_DISCON_REQ.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1365
	 * (Don't flush on listener since it could flush {O_}T_CONN_RES
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1366
	 * and other messages.)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1367
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1368
	if (!(so->so_state & SS_ACCEPTCONN))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1369
		(void) putnextctl1(strvp2wq(SOTOV(so)), M_FLUSH, FLUSHW);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1370
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1371
	discon_req.PRIM_type = T_DISCON_REQ;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1372
	discon_req.SEQ_number = seqno;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1373
	mp = soallocproto1(&discon_req, sizeof (discon_req),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1374
	    0, _ALLOC_SLEEP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1375
	error = kstrputmsg(SOTOV(so), mp, NULL, 0, 0,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1376
			MSG_BAND|MSG_HOLDSIG|MSG_IGNERROR, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1377
	mutex_enter(&so->so_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1378
	if (error) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1379
		eprintsoline(so, error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1380
		goto done;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1381
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1382
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1383
	error = sowaitokack(so, T_DISCON_REQ);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1384
	if (error) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1385
		eprintsoline(so, error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1386
		goto done;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1387
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1388
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1389
	 * Even if some TPI message (e.g. T_DISCON_IND) was received in
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1390
	 * strsock_proto while the lock was dropped above, the disconnect
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1391
	 * is allowed to complete. However, it is not possible to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1392
	 * assert that SS_ISCONNECTED|SS_ISCONNECTING are set.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1393
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1394
	so->so_state &=
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1395
	    ~(SS_ISCONNECTED|SS_ISCONNECTING|SS_LADDR_VALID|SS_FADDR_VALID);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1396
done:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1397
	if (!(flags & _SODISCONNECT_LOCK_HELD)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1398
		so_unlock_single(so, SOLOCKED);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1399
		mutex_exit(&so->so_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1400
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1401
		/* If the caller held the lock don't release it here */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1402
		ASSERT(MUTEX_HELD(&so->so_lock));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1403
		ASSERT(so->so_flag & SOLOCKED);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1404
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1405
	return (error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1406
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1407
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1408
int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1409
sotpi_accept(struct sonode *so, int fflag, struct sonode **nsop)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1410
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1411
	struct T_conn_ind	*conn_ind;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1412
	struct T_conn_res	*conn_res;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1413
	int			error = 0;
898
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 741
diff changeset
  1414
	mblk_t			*mp, *ctxmp;
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1415
	struct sonode		*nso;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1416
	vnode_t			*nvp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1417
	void			*src;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1418
	t_uscalar_t		srclen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1419
	void			*opt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1420
	t_uscalar_t		optlen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1421
	t_scalar_t		PRIM_type;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1422
	t_scalar_t		SEQ_number;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1423
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1424
	dprintso(so, 1, ("sotpi_accept(%p, 0x%x, %p) %s\n",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1425
		so, fflag, nsop, pr_state(so->so_state, so->so_mode)));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1426
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1427
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1428
	 * Defer single-threading the accepting socket until
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1429
	 * the T_CONN_IND has been received and parsed and the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1430
	 * new sonode has been opened.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1431
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1432
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1433
	/* Check that we are not already connected */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1434
	if ((so->so_state & SS_ACCEPTCONN) == 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1435
		goto conn_bad;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1436
again:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1437
	if ((error = sowaitconnind(so, fflag, &mp)) != 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1438
		goto e_bad;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1439
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1440
	ASSERT(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1441
	conn_ind = (struct T_conn_ind *)mp->b_rptr;
898
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 741
diff changeset
  1442
	ctxmp = mp->b_cont;
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 741
diff changeset
  1443
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1444
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1445
	 * Save SEQ_number for error paths.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1446
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1447
	SEQ_number = conn_ind->SEQ_number;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1448
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1449
	srclen = conn_ind->SRC_length;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1450
	src = sogetoff(mp, conn_ind->SRC_offset, srclen, 1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1451
	if (src == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1452
		error = EPROTO;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1453
		freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1454
		eprintsoline(so, error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1455
		goto disconnect_unlocked;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1456
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1457
	optlen = conn_ind->OPT_length;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1458
	switch (so->so_family) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1459
	case AF_INET:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1460
	case AF_INET6:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1461
		if ((optlen == sizeof (intptr_t)) &&
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  1462
		    ((so->so_state & SS_DIRECT) != 0)) {
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1463
			bcopy(mp->b_rptr + conn_ind->OPT_offset,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1464
			    &opt, conn_ind->OPT_length);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1465
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1466
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1467
			 * The transport (in this case TCP) hasn't sent up
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1468
			 * a pointer to an instance for the accept fast-path.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1469
			 * Disable fast-path completely because the call to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1470
			 * sotpi_create() below would otherwise create an
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1471
			 * incomplete TCP instance, which would lead to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1472
			 * problems when sockfs sends a normal T_CONN_RES
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1473
			 * message down the new stream.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1474
			 */
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  1475
			if (so->so_state & SS_DIRECT) {
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  1476
				int rval;
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  1477
				/*
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  1478
				 * For consistency we inform tcp to disable
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  1479
				 * direct interface on the listener, though
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  1480
				 * we can certainly live without doing this
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  1481
				 * because no data will ever travel upstream
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  1482
				 * on the listening socket.
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  1483
				 */
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  1484
				so->so_state &= ~SS_DIRECT;
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  1485
				(void) strioctl(SOTOV(so), _SIOCSOCKFALLBACK,
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  1486
				    0, 0, K_TO_K, CRED(), &rval);
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  1487
			}
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1488
			opt = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1489
			optlen = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1490
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1491
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1492
	case AF_UNIX:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1493
	default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1494
		if (optlen != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1495
			opt = sogetoff(mp, conn_ind->OPT_offset, optlen,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1496
			    __TPI_ALIGN_SIZE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1497
			if (opt == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1498
				error = EPROTO;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1499
				freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1500
				eprintsoline(so, error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1501
				goto disconnect_unlocked;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1502
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1503
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1504
		if (so->so_family == AF_UNIX) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1505
			if (!(so->so_state & SS_FADDR_NOXLATE)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1506
				src = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1507
				srclen = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1508
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1509
			/* Extract src address from options */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1510
			if (optlen != 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1511
				so_getopt_srcaddr(opt, optlen, &src, &srclen);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1512
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1513
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1514
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1515
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1516
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1517
	 * Create the new socket.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1518
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1519
	VN_HOLD(so->so_accessvp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1520
	nso = sotpi_create(so->so_accessvp, so->so_family, so->so_type,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1521
			so->so_protocol, so->so_version, so, &error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1522
	if (nso == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1523
		ASSERT(error != 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1524
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1525
		 * Accept can not fail with ENOBUFS. sotpi_create
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1526
		 * sleeps waiting for memory until a signal is caught
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1527
		 * so return EINTR.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1528
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1529
		freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1530
		if (error == ENOBUFS)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1531
			error = EINTR;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1532
		goto e_disc_unl;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1533
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1534
	nvp = SOTOV(nso);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1535
898
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 741
diff changeset
  1536
	/*
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 741
diff changeset
  1537
	 * If the transport sent up an SSL connection context, then attach
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 741
diff changeset
  1538
	 * it the new socket, and set the (sd_wputdatafunc)() and
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 741
diff changeset
  1539
	 * (sd_rputdatafunc)() stream head hooks to intercept and process
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 741
diff changeset
  1540
	 * SSL records.
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 741
diff changeset
  1541
	 */
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 741
diff changeset
  1542
	if (ctxmp != NULL) {
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 741
diff changeset
  1543
		/*
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 741
diff changeset
  1544
		 * This kssl_ctx_t is already held for us by the transport.
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 741
diff changeset
  1545
		 * So, we don't need to do a kssl_hold_ctx() here.
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 741
diff changeset
  1546
		 */
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 741
diff changeset
  1547
		nso->so_kssl_ctx = *((kssl_ctx_t *)ctxmp->b_rptr);
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 741
diff changeset
  1548
		freemsg(ctxmp);
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 741
diff changeset
  1549
		mp->b_cont = NULL;
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 741
diff changeset
  1550
		strsetrwputdatahooks(nvp, strsock_kssl_input,
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 741
diff changeset
  1551
		    strsock_kssl_output);
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 741
diff changeset
  1552
	}
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1553
#ifdef DEBUG
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1554
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1555
	 * SO_DEBUG is used to trigger the dprint* and eprint* macros thus
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1556
	 * it's inherited early to allow debugging of the accept code itself.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1557
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1558
	nso->so_options |= so->so_options & SO_DEBUG;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1559
#endif /* DEBUG */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1560
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1561
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1562
	 * Save the SRC address from the T_CONN_IND
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1563
	 * for getpeername to work on AF_UNIX and on transports that do not
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1564
	 * support TI_GETPEERNAME.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1565
	 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1566
	 * NOTE: AF_UNIX NUL termination is ensured by the sender's
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1567
	 * copyin_name().
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1568
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1569
	if (srclen > (t_uscalar_t)nso->so_faddr_maxlen) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1570
		error = EINVAL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1571
		freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1572
		eprintsoline(so, error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1573
		goto disconnect_vp_unlocked;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1574
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1575
	nso->so_faddr_len = (socklen_t)srclen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1576
	ASSERT(so->so_faddr_len <= so->so_faddr_maxlen);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1577
	bcopy(src, nso->so_faddr_sa, srclen);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1578
	nso->so_state |= SS_FADDR_VALID;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1579
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1580
	if ((DB_REF(mp) > 1) || MBLKSIZE(mp) <
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1581
	    (sizeof (struct T_conn_res) + sizeof (intptr_t))) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1582
		cred_t *cr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1583
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1584
		if ((cr = DB_CRED(mp)) != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1585
			crhold(cr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1586
			nso->so_peercred = cr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1587
			nso->so_cpid = DB_CPID(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1588
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1589
		freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1590
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1591
		mp = soallocproto1(NULL, sizeof (struct T_conn_res) +
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1592
		    sizeof (intptr_t), 0, _ALLOC_INTR);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1593
		if (mp == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1594
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1595
			 * Accept can not fail with ENOBUFS.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1596
			 * A signal was caught so return EINTR.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1597
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1598
			error = EINTR;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1599
			eprintsoline(so, error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1600
			goto disconnect_vp_unlocked;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1601
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1602
		conn_res = (struct T_conn_res *)mp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1603
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1604
		nso->so_peercred = DB_CRED(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1605
		nso->so_cpid = DB_CPID(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1606
		DB_CRED(mp) = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1607
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1608
		mp->b_rptr = DB_BASE(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1609
		conn_res = (struct T_conn_res *)mp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1610
		mp->b_wptr = mp->b_rptr + sizeof (struct T_conn_res);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1611
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1612
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1613
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1614
	 * New socket must be bound at least in sockfs and, except for AF_INET,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1615
	 * (or AF_INET6) it also has to be bound in the transport provider.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1616
	 * After accepting the connection on nso so_laddr_sa will be set to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1617
	 * contain the same address as the listener's local address
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1618
	 * so the address we bind to isn't important.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1619
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1620
	if ((nso->so_family == AF_INET || nso->so_family == AF_INET6) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1621
	    /*CONSTCOND*/
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1622
	    nso->so_type == SOCK_STREAM && !soaccept_tpi_tcp) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1623
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1624
		 * Optimization for AF_INET{,6} transports
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1625
		 * that can handle a T_CONN_RES without being bound.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1626
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1627
		mutex_enter(&nso->so_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1628
		so_automatic_bind(nso);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1629
		mutex_exit(&nso->so_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1630
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1631
		/* Perform NULL bind with the transport provider. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1632
		if ((error = sotpi_bind(nso, NULL, 0, _SOBIND_UNSPEC)) != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1633
			ASSERT(error != ENOBUFS);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1634
			freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1635
			eprintsoline(nso, error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1636
			goto disconnect_vp_unlocked;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1637
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1638
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1639
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1640
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1641
	 * Inherit SIOCSPGRP, SS_ASYNC before we send the {O_}T_CONN_RES
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1642
	 * so that any data arriving on the new socket will cause the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1643
	 * appropriate signals to be delivered for the new socket.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1644
	 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1645
	 * No other thread (except strsock_proto and strsock_misc)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1646
	 * can access the new socket thus we relax the locking.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1647
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1648
	nso->so_pgrp = so->so_pgrp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1649
	nso->so_state |= so->so_state & (SS_ASYNC|SS_FADDR_NOXLATE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1650
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1651
	if (nso->so_pgrp != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1652
		if ((error = so_set_events(nso, nvp, CRED())) != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1653
			eprintsoline(nso, error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1654
			error = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1655
			nso->so_pgrp = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1656
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1657
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1658
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1659
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1660
	 * Make note of the socket level options. TCP and IP level options
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1661
	 * are already inherited. We could do all this after accept is
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1662
	 * successful but doing it here simplifies code and no harm done
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1663
	 * for error case.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1664
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1665
	nso->so_options = so->so_options & (SO_DEBUG|SO_REUSEADDR|SO_KEEPALIVE|
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1666
	    SO_DONTROUTE|SO_BROADCAST|SO_USELOOPBACK|
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1667
	    SO_OOBINLINE|SO_DGRAM_ERRIND|SO_LINGER);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1668
	nso->so_sndbuf = so->so_sndbuf;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1669
	nso->so_rcvbuf = so->so_rcvbuf;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1670
	if (nso->so_options & SO_LINGER)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1671
		nso->so_linger = so->so_linger;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1672
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  1673
	if ((so->so_state & SS_DIRECT) != 0) {
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1674
		mblk_t *ack_mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1675
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  1676
		ASSERT(nso->so_state & SS_DIRECT);
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1677
		ASSERT(opt != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1678
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1679
		conn_res->OPT_length = optlen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1680
		conn_res->OPT_offset = MBLKL(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1681
		bcopy(&opt, mp->b_wptr, optlen);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1682
		mp->b_wptr += optlen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1683
		conn_res->PRIM_type = T_CONN_RES;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1684
		conn_res->ACCEPTOR_id = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1685
		PRIM_type = T_CONN_RES;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1686
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1687
		/* Send down the T_CONN_RES on acceptor STREAM */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1688
		error = kstrputmsg(SOTOV(nso), mp, NULL,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1689
		    0, 0, MSG_BAND|MSG_HOLDSIG|MSG_IGNERROR, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1690
		if (error) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1691
			mutex_enter(&so->so_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1692
			so_lock_single(so);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1693
			eprintsoline(so, error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1694
			goto disconnect_vp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1695
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1696
		mutex_enter(&nso->so_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1697
		error = sowaitprim(nso, T_CONN_RES, T_OK_ACK,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1698
		    (t_uscalar_t)sizeof (struct T_ok_ack), &ack_mp, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1699
		if (error) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1700
			mutex_exit(&nso->so_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1701
			mutex_enter(&so->so_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1702
			so_lock_single(so);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1703
			eprintsoline(so, error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1704
			goto disconnect_vp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1705
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1706
		if (nso->so_family == AF_INET) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1707
			sin_t *sin;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1708
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1709
			sin = (sin_t *)(ack_mp->b_rptr +
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1710
			    sizeof (struct T_ok_ack));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1711
			bcopy(sin, nso->so_laddr_sa, sizeof (sin_t));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1712
			nso->so_laddr_len = sizeof (sin_t);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1713
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1714
			sin6_t *sin6;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1715
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1716
			sin6 = (sin6_t *)(ack_mp->b_rptr +
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1717
			    sizeof (struct T_ok_ack));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1718
			bcopy(sin6, nso->so_laddr_sa, sizeof (sin6_t));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1719
			nso->so_laddr_len = sizeof (sin6_t);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1720
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1721
		freemsg(ack_mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1722
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1723
		nso->so_state |= SS_ISCONNECTED | SS_LADDR_VALID;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1724
		nso->so_priv = opt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1725
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1726
		if (so->so_nl7c_flags & NL7C_ENABLED) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1727
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1728
			 * An NL7C marked listen()er so the new socket
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1729
			 * inherits the listen()er's NL7C state.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1730
			 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1731
			 * When calling NL7C to process the new socket
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1732
			 * pass the nonblocking i/o state of the listen
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1733
			 * socket as this is the context we are in.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1734
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1735
			nso->so_nl7c_flags = so->so_nl7c_flags;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1736
			if (nl7c_process(nso,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1737
			    (nso->so_state & (SS_NONBLOCK|SS_NDELAY)),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1738
			    (int)((tcp_t *)nso->so_priv)->tcp_mss)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1739
				/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1740
				 * NL7C has completed processing on the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1741
				 * socket, close the socket and back to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1742
				 * the top to await the next T_CONN_IND.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1743
				 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1744
				mutex_exit(&nso->so_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1745
				(void) VOP_CLOSE(nvp, 0, 1, (offset_t)0,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1746
						CRED());
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1747
				VN_RELE(nvp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1748
				goto again;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1749
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1750
			/* Pass the new socket out */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1751
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1752
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1753
		mutex_exit(&nso->so_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1754
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1755
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1756
		 * Pass out new socket.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1757
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1758
		if (nsop != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1759
			*nsop = nso;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1760
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1761
		return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1762
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1763
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1764
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1765
	 * Copy local address from listener.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1766
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1767
	nso->so_laddr_len = so->so_laddr_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1768
	ASSERT(nso->so_laddr_len <= nso->so_laddr_maxlen);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1769
	bcopy(so->so_laddr_sa, nso->so_laddr_sa, nso->so_laddr_len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1770
	nso->so_state |= SS_LADDR_VALID;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1771
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1772
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1773
	 * This is the non-performance case for sockets (e.g. AF_UNIX sockets)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1774
	 * which don't support the FireEngine accept fast-path. It is also
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1775
	 * used when the virtual "sockmod" has been I_POP'd and I_PUSH'd
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1776
	 * again. Neither sockfs nor TCP attempt to find out if some other
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1777
	 * random module has been inserted in between (in which case we
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1778
	 * should follow TLI accept behaviour). We blindly assume the worst
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1779
	 * case and revert back to old behaviour i.e. TCP will not send us
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1780
	 * any option (eager) and the accept should happen on the listener
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1781
	 * queue. Any queued T_conn_ind have already got their options removed
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1782
	 * by so_sock2_stream() when "sockmod" was I_POP'd.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1783
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1784
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1785
	 * Fill in the {O_}T_CONN_RES before getting SOLOCKED.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1786
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1787
	if ((nso->so_mode & SM_ACCEPTOR_ID) == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1788
#ifdef	_ILP32
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1789
		queue_t	*q;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1790
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1791
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1792
		 * Find read queue in driver
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1793
		 * Can safely do this since we "own" nso/nvp.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1794
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1795
		q = strvp2wq(nvp)->q_next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1796
		while (SAMESTR(q))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1797
			q = q->q_next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1798
		q = RD(q);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1799
		conn_res->ACCEPTOR_id = (t_uscalar_t)q;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1800
#else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1801
		conn_res->ACCEPTOR_id = (t_uscalar_t)getminor(nvp->v_rdev);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1802
#endif	/* _ILP32 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1803
		conn_res->PRIM_type = O_T_CONN_RES;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1804
		PRIM_type = O_T_CONN_RES;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1805
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1806
		conn_res->ACCEPTOR_id = nso->so_acceptor_id;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1807
		conn_res->PRIM_type = T_CONN_RES;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1808
		PRIM_type = T_CONN_RES;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1809
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1810
	conn_res->SEQ_number = SEQ_number;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1811
	conn_res->OPT_length = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1812
	conn_res->OPT_offset = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1813
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1814
	mutex_enter(&so->so_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1815
	so_lock_single(so);	/* Set SOLOCKED */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1816
	mutex_exit(&so->so_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1817
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1818
	error = kstrputmsg(SOTOV(so), mp, NULL,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1819
	    0, 0, MSG_BAND|MSG_HOLDSIG|MSG_IGNERROR, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1820
	mutex_enter(&so->so_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1821
	if (error) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1822
		eprintsoline(so, error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1823
		goto disconnect_vp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1824
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1825
	error = sowaitokack(so, PRIM_type);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1826
	if (error) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1827
		eprintsoline(so, error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1828
		goto disconnect_vp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1829
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1830
	so_unlock_single(so, SOLOCKED);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1831
	mutex_exit(&so->so_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1832
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1833
	nso->so_state |= SS_ISCONNECTED;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1834
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1835
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1836
	 * Pass out new socket.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1837
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1838
	if (nsop != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1839
		*nsop = nso;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1840
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1841
	return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1842
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1843
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1844
eproto_disc_unl:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1845
	error = EPROTO;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1846
e_disc_unl:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1847
	eprintsoline(so, error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1848
	goto disconnect_unlocked;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1849
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1850
pr_disc_vp_unl:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1851
	eprintsoline(so, error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1852
disconnect_vp_unlocked:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1853
	(void) VOP_CLOSE(nvp, 0, 1, 0, CRED());
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1854
	VN_RELE(nvp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1855
disconnect_unlocked:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1856
	(void) sodisconnect(so, SEQ_number, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1857
	return (error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1858
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1859
pr_disc_vp:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1860
	eprintsoline(so, error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1861
disconnect_vp:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1862
	(void) sodisconnect(so, SEQ_number, _SODISCONNECT_LOCK_HELD);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1863
	so_unlock_single(so, SOLOCKED);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1864
	mutex_exit(&so->so_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1865
	(void) VOP_CLOSE(nvp, 0, 1, 0, CRED());
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1866
	VN_RELE(nvp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1867
	return (error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1868
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1869
conn_bad:	/* Note: SunOS 4/BSD unconditionally returns EINVAL here */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1870
	error = (so->so_type == SOCK_DGRAM || so->so_type == SOCK_RAW)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1871
	    ? EOPNOTSUPP : EINVAL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1872
e_bad:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1873
	eprintsoline(so, error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1874
	return (error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1875
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1876
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1877
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1878
 * connect a socket.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1879
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1880
 * Allow SOCK_DGRAM sockets to reconnect (by specifying a new address) and to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1881
 * unconnect (by specifying a null address).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1882
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1883
int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1884
sotpi_connect(struct sonode *so,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1885
	const struct sockaddr *name,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1886
	socklen_t namelen,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1887
	int fflag,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1888
	int flags)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1889
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1890
	struct T_conn_req	conn_req;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1891
	int			error = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1892
	mblk_t			*mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1893
	void			*src;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1894
	socklen_t		srclen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1895
	void			*addr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1896
	socklen_t		addrlen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1897
	boolean_t		need_unlock;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1898
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1899
	dprintso(so, 1, ("sotpi_connect(%p, %p, %d, 0x%x, 0x%x) %s\n",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1900
		so, name, namelen, fflag, flags,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1901
		pr_state(so->so_state, so->so_mode)));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1902
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1903
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1904
	 * Preallocate the T_CONN_REQ mblk before grabbing SOLOCKED to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1905
	 * avoid sleeping for memory with SOLOCKED held.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1906
	 * We know that the T_CONN_REQ can't be larger than 2 * so_faddr_maxlen
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1907
	 * + sizeof (struct T_opthdr).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1908
	 * (the AF_UNIX so_ux_addr_xlate() does not make the address
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1909
	 * exceed so_faddr_maxlen).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1910
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1911
	mp = soallocproto(sizeof (struct T_conn_req) +
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1912
	    2 * so->so_faddr_maxlen + sizeof (struct T_opthdr), _ALLOC_INTR);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1913
	if (mp == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1914
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1915
		 * Connect can not fail with ENOBUFS. A signal was
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1916
		 * caught so return EINTR.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1917
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1918
		error = EINTR;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1919
		eprintsoline(so, error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1920
		return (error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1921
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1922
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1923
	mutex_enter(&so->so_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1924
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1925
	 * Make sure that there is a preallocated unbind_req
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1926
	 * message before any binding. This message allocated when
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1927
	 * the socket is created  but it might be have been
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1928
	 * consumed.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1929
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1930
	if (so->so_unbind_mp == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1931
		dprintso(so, 1, ("sotpi_connect: allocating unbind_req\n"));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1932
		/* NOTE: holding so_lock while sleeping */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1933
		so->so_unbind_mp =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1934
		    soallocproto(sizeof (struct T_unbind_req), _ALLOC_INTR);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1935
		if (so->so_unbind_mp == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1936
			error = EINTR;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1937
			need_unlock = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1938
			goto done;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1939
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1940
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1941
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1942
	so_lock_single(so);	/* Set SOLOCKED */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1943
	need_unlock = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1944
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1945
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1946
	 * Can't have done a listen before connecting.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1947
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1948
	if (so->so_state & SS_ACCEPTCONN) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1949
		error = EOPNOTSUPP;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1950
		goto done;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1951
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1952
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1953
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1954
	 * Must be bound with the transport
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1955
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1956
	if (!(so->so_state & SS_ISBOUND)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1957
		if ((so->so_family == AF_INET || so->so_family == AF_INET6) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1958
		    /*CONSTCOND*/
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1959
		    so->so_type == SOCK_STREAM && !soconnect_tpi_tcp) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1960
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1961
			 * Optimization for AF_INET{,6} transports
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1962
			 * that can handle a T_CONN_REQ without being bound.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1963
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1964
			so_automatic_bind(so);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1965
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1966
			error = sotpi_bind(so, NULL, 0,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1967
			    _SOBIND_UNSPEC|_SOBIND_LOCK_HELD);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1968
			if (error)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1969
				goto done;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1970
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1971
		ASSERT(so->so_state & SS_ISBOUND);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1972
		flags |= _SOCONNECT_DID_BIND;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1973
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1974
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1975
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1976
	 * Handle a connect to a name parameter of type AF_UNSPEC like a
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1977
	 * connect to a null address. This is the portable method to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1978
	 * unconnect a socket.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1979
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1980
	if ((namelen >= sizeof (sa_family_t)) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1981
	    (name->sa_family == AF_UNSPEC)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1982
		name = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1983
		namelen = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1984
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1985
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1986
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1987
	 * Check that we are not already connected.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1988
	 * A connection-oriented socket cannot be reconnected.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1989
	 * A connected connection-less socket can be
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1990
	 * - connected to a different address by a subsequent connect
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1991
	 * - "unconnected" by a connect to the NULL address
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1992
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1993
	if (so->so_state & (SS_ISCONNECTED|SS_ISCONNECTING)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1994
		ASSERT(!(flags & _SOCONNECT_DID_BIND));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1995
		if (so->so_mode & SM_CONNREQUIRED) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1996
			/* Connection-oriented socket */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1997
			error = so->so_state & SS_ISCONNECTED ?
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1998
			    EISCONN : EALREADY;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1999
			goto done;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2000
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2001
		/* Connection-less socket */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2002
		if (name == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2003
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2004
			 * Remove the connected state and clear SO_DGRAM_ERRIND
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2005
			 * since it was set when the socket was connected.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2006
			 * If this is UDP also send down a T_DISCON_REQ.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2007
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2008
			int val;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2009
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2010
			if ((so->so_family == AF_INET ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2011
				so->so_family == AF_INET6) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2012
			    (so->so_type == SOCK_DGRAM ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2013
				so->so_type == SOCK_RAW) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2014
			    /*CONSTCOND*/
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2015
			    !soconnect_tpi_udp) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2016
				/* XXX What about implicitly unbinding here? */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2017
				error = sodisconnect(so, -1,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2018
						_SODISCONNECT_LOCK_HELD);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2019
			} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2020
				so->so_state &=
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2021
				    ~(SS_ISCONNECTED | SS_ISCONNECTING |
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2022
				    SS_FADDR_VALID);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2023
				so->so_faddr_len = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2024
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2025
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2026
			so_unlock_single(so, SOLOCKED);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2027
			mutex_exit(&so->so_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2028
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2029
			val = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2030
			(void) sotpi_setsockopt(so, SOL_SOCKET, SO_DGRAM_ERRIND,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2031
					&val, (t_uscalar_t)sizeof (val));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2032
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2033
			mutex_enter(&so->so_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2034
			so_lock_single(so);	/* Set SOLOCKED */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2035
			goto done;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2036
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2037
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2038
	ASSERT(so->so_state & SS_ISBOUND);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2039
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2040
	if (name == NULL || namelen == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2041
		error = EINVAL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2042
		goto done;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2043
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2044
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2045
	 * Mark the socket if so_faddr_sa represents the transport level
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2046
	 * address.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2047
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2048
	if (flags & _SOCONNECT_NOXLATE) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2049
		struct sockaddr_ux	*soaddr_ux;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2050
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2051
		ASSERT(so->so_family == AF_UNIX);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2052
		if (namelen != sizeof (struct sockaddr_ux)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2053
			error = EINVAL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2054
			goto done;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2055
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2056
		soaddr_ux = (struct sockaddr_ux *)name;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2057
		name = (struct sockaddr *)&soaddr_ux->sou_addr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2058
		namelen = sizeof (soaddr_ux->sou_addr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2059
		so->so_state |= SS_FADDR_NOXLATE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2060
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2061
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2062
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2063
	 * Length and family checks.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2064
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2065
	error = so_addr_verify(so, name, namelen);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2066
	if (error)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2067
		goto bad;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2068
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2069
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2070
	 * Save foreign address. Needed for AF_UNIX as well as
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2071
	 * transport providers that do not support TI_GETPEERNAME.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2072
	 * Also used for cached foreign address for TCP and UDP.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2073
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2074
	if (namelen > (t_uscalar_t)so->so_faddr_maxlen) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2075
		error = EINVAL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2076
		goto done;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2077
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2078
	so->so_faddr_len = (socklen_t)namelen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2079
	ASSERT(so->so_faddr_len <= so->so_faddr_maxlen);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2080
	bcopy(name, so->so_faddr_sa, namelen);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2081
	so->so_state |= SS_FADDR_VALID;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2082
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2083
	if (so->so_family == AF_UNIX) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2084
		if (so->so_state & SS_FADDR_NOXLATE) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2085
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2086
			 * Already have a transport internal address. Do not
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2087
			 * pass any (transport internal) source address.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2088
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2089
			addr = so->so_faddr_sa;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2090
			addrlen = (t_uscalar_t)so->so_faddr_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2091
			src = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2092
			srclen = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2093
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2094
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2095
			 * Pass the sockaddr_un source address as an option
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2096
			 * and translate the remote address.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2097
			 * Holding so_lock thus so_laddr_sa can not change.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2098
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2099
			src = so->so_laddr_sa;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2100
			srclen = (t_uscalar_t)so->so_laddr_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2101
			dprintso(so, 1,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2102
				("sotpi_connect UNIX: srclen %d, src %p\n",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2103
				srclen, src));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2104
			error = so_ux_addr_xlate(so,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2105
				so->so_faddr_sa, (socklen_t)so->so_faddr_len,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2106
				(flags & _SOCONNECT_XPG4_2),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2107
				&addr, &addrlen);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2108
			if (error)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2109
				goto bad;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2110
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2111
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2112
		addr = so->so_faddr_sa;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2113
		addrlen = (t_uscalar_t)so->so_faddr_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2114
		src = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2115
		srclen = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2116
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2117
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2118
	 * When connecting a datagram socket we issue the SO_DGRAM_ERRIND
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2119
	 * option which asks the transport provider to send T_UDERR_IND
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2120
	 * messages. These T_UDERR_IND messages are used to return connected
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2121
	 * style errors (e.g. ECONNRESET) for connected datagram sockets.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2122
	 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2123
	 * In addition, for UDP (and SOCK_RAW AF_INET{,6} sockets)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2124
	 * we send down a T_CONN_REQ. This is needed to let the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2125
	 * transport assign a local address that is consistent with
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2126
	 * the remote address. Applications depend on a getsockname()
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2127
	 * after a connect() to retrieve the "source" IP address for
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2128
	 * the connected socket.  Invalidate the cached local address
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2129
	 * to force getsockname() to enquire of the transport.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2130
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2131
	if (!(so->so_mode & SM_CONNREQUIRED)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2132
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2133
		 * Datagram socket.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2134
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2135
		int32_t val;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2136
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2137
		so_unlock_single(so, SOLOCKED);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2138
		mutex_exit(&so->so_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2139
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2140
		val = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2141
		(void) sotpi_setsockopt(so, SOL_SOCKET, SO_DGRAM_ERRIND,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2142
					&val, (t_uscalar_t)sizeof (val));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2143
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2144
		mutex_enter(&so->so_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2145
		so_lock_single(so);	/* Set SOLOCKED */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2146
		if ((so->so_family != AF_INET && so->so_family != AF_INET6) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2147
		    (so->so_type != SOCK_DGRAM && so->so_type != SOCK_RAW) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2148
		    soconnect_tpi_udp) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2149
			soisconnected(so);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2150
			goto done;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2151
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2152
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2153
		 * Send down T_CONN_REQ etc.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2154
		 * Clear fflag to avoid returning EWOULDBLOCK.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2155
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2156
		fflag = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2157
		ASSERT(so->so_family != AF_UNIX);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2158
		so->so_state &= ~SS_LADDR_VALID;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2159
	} else if (so->so_laddr_len != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2160
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2161
		 * If the local address or port was "any" then it may be
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2162
		 * changed by the transport as a result of the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2163
		 * connect.  Invalidate the cached version if we have one.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2164
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2165
		switch (so->so_family) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2166
		case AF_INET:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2167
			ASSERT(so->so_laddr_len == (socklen_t)sizeof (sin_t));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2168
			if (((sin_t *)so->so_laddr_sa)->sin_addr.s_addr ==
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2169
			    INADDR_ANY ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2170
			    ((sin_t *)so->so_laddr_sa)->sin_port == 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2171
				so->so_state &= ~SS_LADDR_VALID;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2172
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2173
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2174
		case AF_INET6:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2175
			ASSERT(so->so_laddr_len == (socklen_t)sizeof (sin6_t));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2176
			if (IN6_IS_ADDR_UNSPECIFIED(
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2177
			    &((sin6_t *)so->so_laddr_sa) ->sin6_addr) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2178
			    IN6_IS_ADDR_V4MAPPED_ANY(
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2179
			    &((sin6_t *)so->so_laddr_sa)->sin6_addr) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2180
			    ((sin6_t *)so->so_laddr_sa)->sin6_port == 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2181
				    so->so_state &= ~SS_LADDR_VALID;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2182
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2183
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2184
		default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2185
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2186
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2187
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2188
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2189
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2190
	 * Check for failure of an earlier call
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2191
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2192
	if (so->so_error != 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2193
		goto so_bad;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2194
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2195
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2196
	 * Send down T_CONN_REQ. Message was allocated above.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2197
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2198
	conn_req.PRIM_type = T_CONN_REQ;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2199
	conn_req.DEST_length = addrlen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2200
	conn_req.DEST_offset = (t_scalar_t)sizeof (conn_req);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2201
	if (srclen == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2202
		conn_req.OPT_length = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2203
		conn_req.OPT_offset = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2204
		soappendmsg(mp, &conn_req, sizeof (conn_req));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2205
		soappendmsg(mp, addr, addrlen);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2206
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2207
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2208
		 * There is a AF_UNIX sockaddr_un to include as a source
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2209
		 * address option.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2210
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2211
		struct T_opthdr toh;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2212
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2213
		toh.level = SOL_SOCKET;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2214
		toh.name = SO_SRCADDR;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2215
		toh.len = (t_uscalar_t)(srclen + sizeof (struct T_opthdr));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2216
		toh.status = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2217
		conn_req.OPT_length =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2218
			(t_scalar_t)(sizeof (toh) + _TPI_ALIGN_TOPT(srclen));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2219
		conn_req.OPT_offset = (t_scalar_t)(sizeof (conn_req) +
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2220
			_TPI_ALIGN_TOPT(addrlen));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2221
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2222
		soappendmsg(mp, &conn_req, sizeof (conn_req));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2223
		soappendmsg(mp, addr, addrlen);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2224
		mp->b_wptr += _TPI_ALIGN_TOPT(addrlen) - addrlen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2225
		soappendmsg(mp, &toh, sizeof (toh));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2226
		soappendmsg(mp, src, srclen);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2227
		mp->b_wptr += _TPI_ALIGN_TOPT(srclen) - srclen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2228
		ASSERT(mp->b_wptr <= mp->b_datap->db_lim);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2229
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2230
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2231
	 * Set SS_ISCONNECTING before sending down the T_CONN_REQ
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2232
	 * in order to have the right state when the T_CONN_CON shows up.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2233
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2234
	soisconnecting(so);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2235
	mutex_exit(&so->so_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2236
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2237
#ifdef C2_AUDIT
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2238
	if (audit_active)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2239
		audit_sock(T_CONN_REQ, strvp2wq(SOTOV(so)), mp, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2240
#endif /* C2_AUDIT */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2241
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2242
	error = kstrputmsg(SOTOV(so), mp, NULL, 0, 0,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2243
			MSG_BAND|MSG_HOLDSIG|MSG_IGNERROR, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2244
	mp = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2245
	mutex_enter(&so->so_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2246
	if (error != 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2247
		goto bad;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2248
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2249
	if ((error = sowaitokack(so, T_CONN_REQ)) != 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2250
		goto bad;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2251
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2252
	/* Allow other threads to access the socket */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2253
	so_unlock_single(so, SOLOCKED);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2254
	need_unlock = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2255
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2256
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2257
	 * Wait until we get a T_CONN_CON or an error
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2258
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2259
	if ((error = sowaitconnected(so, fflag, 0)) != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2260
		so_lock_single(so);	/* Set SOLOCKED */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2261
		need_unlock = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2262
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2263
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2264
done:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2265
	freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2266
	switch (error) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2267
	case EINPROGRESS:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2268
	case EALREADY:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2269
	case EISCONN:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2270
	case EINTR:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2271
		/* Non-fatal errors */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2272
		so->so_state &= ~SS_LADDR_VALID;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2273
		/* FALLTHRU */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2274
	case 0:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2275
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2276
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2277
	case EHOSTUNREACH:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2278
		if (flags & _SOCONNECT_XPG4_2) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2279
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2280
			 * X/Open specification contains a requirement that
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2281
			 * ENETUNREACH be returned but does not require
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2282
			 * EHOSTUNREACH. In order to keep the test suite
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2283
			 * happy we mess with the errno here.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2284
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2285
			error = ENETUNREACH;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2286
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2287
		/* FALLTHRU */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2288
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2289
	default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2290
		ASSERT(need_unlock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2291
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2292
		 * Fatal errors: clear SS_ISCONNECTING in case it was set,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2293
		 * and invalidate local-address cache
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2294
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2295
		so->so_state &= ~(SS_ISCONNECTING | SS_LADDR_VALID);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2296
		/* A discon_ind might have already unbound us */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2297
		if ((flags & _SOCONNECT_DID_BIND) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2298
		    (so->so_state & SS_ISBOUND)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2299
			int err;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2300
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2301
			err = sotpi_unbind(so, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2302
			/* LINTED - statement has no conseq */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2303
			if (err) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2304
				eprintsoline(so, err);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2305
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2306
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2307
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2308
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2309
	if (need_unlock)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2310
		so_unlock_single(so, SOLOCKED);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2311
	mutex_exit(&so->so_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2312
	return (error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2313
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2314
so_bad:	error = sogeterr(so);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2315
bad:	eprintsoline(so, error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2316
	goto done;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2317
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2318
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2319
int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2320
sotpi_shutdown(struct sonode *so, int how)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2321
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2322
	struct T_ordrel_req	ordrel_req;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2323
	mblk_t			*mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2324
	uint_t			old_state, state_change;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2325
	int			error = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2326
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2327
	dprintso(so, 1, ("sotpi_shutdown(%p, %d) %s\n",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2328
		so, how, pr_state(so->so_state, so->so_mode)));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2329
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2330
	mutex_enter(&so->so_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2331
	so_lock_single(so);	/* Set SOLOCKED */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2332
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2333
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2334
	 * SunOS 4.X has no check for datagram sockets.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2335
	 * 5.X checks that it is connected (ENOTCONN)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2336
	 * X/Open requires that we check the connected state.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2337
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2338
	if (!(so->so_state & SS_ISCONNECTED)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2339
		if (!xnet_skip_checks) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2340
			error = ENOTCONN;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2341
			if (xnet_check_print) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2342
				printf("sockfs: X/Open shutdown check "
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2343
					"caused ENOTCONN\n");
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2344
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2345
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2346
		goto done;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2347
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2348
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2349
	 * Record the current state and then perform any state changes.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2350
	 * Then use the difference between the old and new states to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2351
	 * determine which messages need to be sent.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2352
	 * This prevents e.g. duplicate T_ORDREL_REQ when there are
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2353
	 * duplicate calls to shutdown().
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2354
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2355
	old_state = so->so_state;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2356
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2357
	switch (how) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2358
	case 0:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2359
		socantrcvmore(so);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2360
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2361
	case 1:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2362
		socantsendmore(so);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2363
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2364
	case 2:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2365
		socantsendmore(so);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2366
		socantrcvmore(so);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2367
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2368
	default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2369
		error = EINVAL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2370
		goto done;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2371
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2372
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2373
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2374
	 * Assumes that the SS_CANT* flags are never cleared in the above code.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2375
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2376
	state_change = (so->so_state & (SS_CANTRCVMORE|SS_CANTSENDMORE)) -
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2377
		(old_state & (SS_CANTRCVMORE|SS_CANTSENDMORE));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2378
	ASSERT((state_change & ~(SS_CANTRCVMORE|SS_CANTSENDMORE)) == 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2379
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2380
	switch (state_change) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2381
	case 0:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2382
		dprintso(so, 1,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2383
		    ("sotpi_shutdown: nothing to send in state 0x%x\n",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2384
		    so->so_state));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2385
		goto done;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2386
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2387
	case SS_CANTRCVMORE:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2388
		mutex_exit(&so->so_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2389
		strseteof(SOTOV(so), 1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2390
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2391
		 * strseteof takes care of read side wakeups,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2392
		 * pollwakeups, and signals.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2393
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2394
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2395
		 * Get the read lock before flushing data to avoid problems
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2396
		 * with the T_EXDATA_IND MSG_PEEK code in sotpi_recvmsg.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2397
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2398
		mutex_enter(&so->so_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2399
		(void) so_lock_read(so, 0);	/* Set SOREADLOCKED */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2400
		mutex_exit(&so->so_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2401
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2402
		/* Flush read side queue */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2403
		strflushrq(SOTOV(so), FLUSHALL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2404
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2405
		mutex_enter(&so->so_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2406
		so_unlock_read(so);		/* Clear SOREADLOCKED */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2407
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2408
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2409
	case SS_CANTSENDMORE:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2410
		mutex_exit(&so->so_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2411
		strsetwerror(SOTOV(so), 0, 0, sogetwrerr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2412
		mutex_enter(&so->so_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2413
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2414
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2415
	case SS_CANTSENDMORE|SS_CANTRCVMORE:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2416
		mutex_exit(&so->so_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2417
		strsetwerror(SOTOV(so), 0, 0, sogetwrerr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2418
		strseteof(SOTOV(so), 1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2419
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2420
		 * strseteof takes care of read side wakeups,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2421
		 * pollwakeups, and signals.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2422
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2423
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2424
		 * Get the read lock before flushing data to avoid problems
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2425
		 * with the T_EXDATA_IND MSG_PEEK code in sotpi_recvmsg.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2426
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2427
		mutex_enter(&so->so_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2428
		(void) so_lock_read(so, 0);	/* Set SOREADLOCKED */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2429
		mutex_exit(&so->so_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2430
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2431
		/* Flush read side queue */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2432
		strflushrq(SOTOV(so), FLUSHALL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2433
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2434
		mutex_enter(&so->so_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2435
		so_unlock_read(so);		/* Clear SOREADLOCKED */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2436
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2437
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2438
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2439
	ASSERT(MUTEX_HELD(&so->so_lock));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2440
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2441
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2442
	 * If either SS_CANTSENDMORE or SS_CANTRCVMORE or both of them
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2443
	 * was set due to this call and the new state has both of them set:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2444
	 *	Send the AF_UNIX close indication
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2445
	 *	For T_COTS send a discon_ind
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2446
	 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2447
	 * If cantsend was set due to this call:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2448
	 *	For T_COTSORD send an ordrel_ind
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2449
	 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2450
	 * Note that for T_CLTS there is no message sent here.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2451
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2452
	if ((so->so_state & (SS_CANTRCVMORE|SS_CANTSENDMORE)) ==
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2453
	    (SS_CANTRCVMORE|SS_CANTSENDMORE)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2454
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2455
		 * For SunOS 4.X compatibility we tell the other end
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2456
		 * that we are unable to receive at this point.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2457
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2458
		if (so->so_family == AF_UNIX && so->so_serv_type != T_CLTS)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2459
			so_unix_close(so);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2460
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2461
		if (so->so_serv_type == T_COTS)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2462
			error = sodisconnect(so, -1, _SODISCONNECT_LOCK_HELD);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2463
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2464
	if ((state_change & SS_CANTSENDMORE) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2465
	    (so->so_serv_type == T_COTS_ORD)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2466
		/* Send an orderly release */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2467
		ordrel_req.PRIM_type = T_ORDREL_REQ;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2468
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2469
		mutex_exit(&so->so_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2470
		mp = soallocproto1(&ordrel_req, sizeof (ordrel_req),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2471
		    0, _ALLOC_SLEEP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2472
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2473
		 * Send down the T_ORDREL_REQ even if there is flow control.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2474
		 * This prevents shutdown from blocking.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2475
		 * Note that there is no T_OK_ACK for ordrel_req.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2476
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2477
		error = kstrputmsg(SOTOV(so), mp, NULL, 0, 0,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2478
			MSG_BAND|MSG_HOLDSIG|MSG_IGNERROR|MSG_IGNFLOW, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2479
		mutex_enter(&so->so_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2480
		if (error) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2481
			eprintsoline(so, error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2482
			goto done;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2483
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2484
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2485
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2486
done:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2487
	so_unlock_single(so, SOLOCKED);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2488
	mutex_exit(&so->so_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2489
	return (error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2490
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2491
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2492
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2493
 * For any connected SOCK_STREAM/SOCK_SEQPACKET AF_UNIX socket we send
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2494
 * a zero-length T_OPTDATA_REQ with the SO_UNIX_CLOSE option to inform the peer
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2495
 * that we have closed.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2496
 * Also, for connected AF_UNIX SOCK_DGRAM sockets we send a zero-length
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2497
 * T_UNITDATA_REQ containing the same option.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2498
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2499
 * For SOCK_DGRAM half-connections (somebody connected to this end
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2500
 * but this end is not connect) we don't know where to send any
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2501
 * SO_UNIX_CLOSE.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2502
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2503
 * We have to ignore stream head errors just in case there has been
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2504
 * a shutdown(output).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2505
 * Ignore any flow control to try to get the message more quickly to the peer.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2506
 * While locally ignoring flow control solves the problem when there
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2507
 * is only the loopback transport on the stream it would not provide
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2508
 * the correct AF_UNIX socket semantics when one or more modules have
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2509
 * been pushed.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2510
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2511
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2512
so_unix_close(struct sonode *so)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2513
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2514
	int		error;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2515
	struct T_opthdr	toh;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2516
	mblk_t		*mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2517
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2518
	ASSERT(MUTEX_HELD(&so->so_lock));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2519
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2520
	ASSERT(so->so_family == AF_UNIX);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2521
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2522
	if ((so->so_state & (SS_ISCONNECTED|SS_ISBOUND)) !=
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2523
	    (SS_ISCONNECTED|SS_ISBOUND))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2524
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2525
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2526
	dprintso(so, 1, ("so_unix_close(%p) %s\n",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2527
		so, pr_state(so->so_state, so->so_mode)));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2528
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2529
	toh.level = SOL_SOCKET;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2530
	toh.name = SO_UNIX_CLOSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2531
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2532
	/* zero length + header */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2533
	toh.len = (t_uscalar_t)sizeof (struct T_opthdr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2534
	toh.status = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2535
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2536
	if (so->so_type == SOCK_STREAM || so->so_type == SOCK_SEQPACKET) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2537
		struct T_optdata_req tdr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2538
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2539
		tdr.PRIM_type = T_OPTDATA_REQ;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2540
		tdr.DATA_flag = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2541
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2542
		tdr.OPT_length = (t_scalar_t)sizeof (toh);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2543
		tdr.OPT_offset = (t_scalar_t)sizeof (tdr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2544
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2545
		/* NOTE: holding so_lock while sleeping */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2546
		mp = soallocproto2(&tdr, sizeof (tdr),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2547
		    &toh, sizeof (toh), 0, _ALLOC_SLEEP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2548
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2549
		struct T_unitdata_req	tudr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2550
		void			*addr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2551
		socklen_t		addrlen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2552
		void			*src;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2553
		socklen_t		srclen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2554
		struct T_opthdr		toh2;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2555
		t_scalar_t		size;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2556
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2557
		/* Connecteded DGRAM socket */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2558
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2559
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2560
		 * For AF_UNIX the destination address is translated to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2561
		 * an internal name and the source address is passed as
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2562
		 * an option.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2563
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2564
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2565
		 * Length and family checks.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2566
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2567
		error = so_addr_verify(so, so->so_faddr_sa,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2568
					(t_uscalar_t)so->so_faddr_len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2569
		if (error) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2570
			eprintsoline(so, error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2571
			return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2572
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2573
		if (so->so_state & SS_FADDR_NOXLATE) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2574
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2575
			 * Already have a transport internal address. Do not
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2576
			 * pass any (transport internal) source address.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2577
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2578
			addr = so->so_faddr_sa;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2579
			addrlen = (t_uscalar_t)so->so_faddr_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2580
			src = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2581
			srclen = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2582
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2583
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2584
			 * Pass the sockaddr_un source address as an option
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2585
			 * and translate the remote address.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2586
			 * Holding so_lock thus so_laddr_sa can not change.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2587
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2588
			src = so->so_laddr_sa;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2589
			srclen = (socklen_t)so->so_laddr_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2590
			dprintso(so, 1,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2591
				("so_ux_close: srclen %d, src %p\n",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2592
				srclen, src));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2593
			error = so_ux_addr_xlate(so,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2594
				so->so_faddr_sa,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2595
				(socklen_t)so->so_faddr_len, 0,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2596
				&addr, &addrlen);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2597
			if (error) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2598
				eprintsoline(so, error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2599
				return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2600
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2601
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2602
		tudr.PRIM_type = T_UNITDATA_REQ;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2603
		tudr.DEST_length = addrlen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2604
		tudr.DEST_offset = (t_scalar_t)sizeof (tudr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2605
		if (srclen == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2606
			tudr.OPT_length = (t_scalar_t)sizeof (toh);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2607
			tudr.OPT_offset = (t_scalar_t)(sizeof (tudr) +
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2608
				_TPI_ALIGN_TOPT(addrlen));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2609
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2610
			size = tudr.OPT_offset + tudr.OPT_length;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2611
			/* NOTE: holding so_lock while sleeping */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2612
			mp = soallocproto2(&tudr, sizeof (tudr),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2613
			    addr, addrlen, size, _ALLOC_SLEEP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2614
			mp->b_wptr += (_TPI_ALIGN_TOPT(addrlen) - addrlen);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2615
			soappendmsg(mp, &toh, sizeof (toh));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2616
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2617
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2618
			 * There is a AF_UNIX sockaddr_un to include as a
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2619
			 * source address option.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2620
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2621
			tudr.OPT_length = (t_scalar_t)(2 * sizeof (toh) +
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2622
			    _TPI_ALIGN_TOPT(srclen));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2623
			tudr.OPT_offset = (t_scalar_t)(sizeof (tudr) +
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2624
			    _TPI_ALIGN_TOPT(addrlen));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2625
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2626
			toh2.level = SOL_SOCKET;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2627
			toh2.name = SO_SRCADDR;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2628
			toh2.len = (t_uscalar_t)(srclen +
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2629
					sizeof (struct T_opthdr));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2630
			toh2.status = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2631
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2632
			size = tudr.OPT_offset + tudr.OPT_length;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2633
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2634
			/* NOTE: holding so_lock while sleeping */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2635
			mp = soallocproto2(&tudr, sizeof (tudr),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2636
			    addr, addrlen, size, _ALLOC_SLEEP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2637
			mp->b_wptr += _TPI_ALIGN_TOPT(addrlen) - addrlen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2638
			soappendmsg(mp, &toh, sizeof (toh));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2639
			soappendmsg(mp, &toh2, sizeof (toh2));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2640
			soappendmsg(mp, src, srclen);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2641
			mp->b_wptr += _TPI_ALIGN_TOPT(srclen) - srclen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2642
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2643
		ASSERT(mp->b_wptr <= mp->b_datap->db_lim);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2644
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2645
	mutex_exit(&so->so_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2646
	error = kstrputmsg(SOTOV(so), mp, NULL, 0, 0,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2647
			MSG_BAND|MSG_HOLDSIG|MSG_IGNERROR|MSG_IGNFLOW, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2648
	mutex_enter(&so->so_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2649
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2650
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2651
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2652
 * Handle recv* calls that set MSG_OOB or MSG_OOB together with MSG_PEEK.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2653
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2654
int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2655
sorecvoob(struct sonode *so, struct nmsghdr *msg, struct uio *uiop, int flags)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2656
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2657
	mblk_t		*mp, *nmp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2658
	int		error;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2659
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2660
	dprintso(so, 1, ("sorecvoob(%p, %p, 0x%x)\n", so, msg, flags));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2661
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2662
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2663
	 * There is never any oob data with addresses or control since
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2664
	 * the T_EXDATA_IND does not carry any options.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2665
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2666
	msg->msg_controllen = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2667
	msg->msg_namelen = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2668
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2669
	mutex_enter(&so->so_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2670
	ASSERT(so_verify_oobstate(so));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2671
	if ((so->so_options & SO_OOBINLINE) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2672
	    (so->so_state & (SS_OOBPEND|SS_HADOOBDATA)) != SS_OOBPEND) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2673
		dprintso(so, 1, ("sorecvoob: inline or data consumed\n"));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2674
		mutex_exit(&so->so_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2675
		return (EINVAL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2676
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2677
	if (!(so->so_state & SS_HAVEOOBDATA)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2678
		dprintso(so, 1, ("sorecvoob: no data yet\n"));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2679
		mutex_exit(&so->so_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2680
		return (EWOULDBLOCK);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2681
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2682
	ASSERT(so->so_oobmsg != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2683
	mp = so->so_oobmsg;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2684
	if (flags & MSG_PEEK) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2685
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2686
		 * Since recv* can not return ENOBUFS we can not use dupmsg.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2687
		 * Instead we revert to the consolidation private
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2688
		 * allocb_wait plus bcopy.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2689
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2690
		mblk_t *mp1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2691
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2692
		mp1 = allocb_wait(msgdsize(mp), BPRI_MED, STR_NOSIG, NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2693
		ASSERT(mp1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2694
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2695
		while (mp != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2696
			ssize_t size;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2697
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2698
			size = MBLKL(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2699
			bcopy(mp->b_rptr, mp1->b_wptr, size);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2700
			mp1->b_wptr += size;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2701
			ASSERT(mp1->b_wptr <= mp1->b_datap->db_lim);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2702
			mp = mp->b_cont;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2703
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2704
		mp = mp1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2705
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2706
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2707
		 * Update the state indicating that the data has been consumed.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2708
		 * Keep SS_OOBPEND set until data is consumed past the mark.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2709
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2710
		so->so_oobmsg = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2711
		so->so_state ^= SS_HAVEOOBDATA|SS_HADOOBDATA;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2712
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2713
	dprintso(so, 1,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2714
		("after recvoob(%p): counts %d/%d state %s\n",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2715
		so, so->so_oobsigcnt,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2716
		so->so_oobcnt, pr_state(so->so_state, so->so_mode)));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2717
	ASSERT(so_verify_oobstate(so));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2718
	mutex_exit(&so->so_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2719
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2720
	error = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2721
	nmp = mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2722
	while (nmp != NULL && uiop->uio_resid > 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2723
		ssize_t n = MBLKL(nmp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2724
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2725
		n = MIN(n, uiop->uio_resid);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2726
		if (n > 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2727
			error = uiomove(nmp->b_rptr, n,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2728
					UIO_READ, uiop);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2729
		if (error)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2730
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2731
		nmp = nmp->b_cont;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2732
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2733
	freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2734
	return (error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2735
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2736
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2737
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2738
 * Called by sotpi_recvmsg when reading a non-zero amount of data.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2739
 * In addition, the caller typically verifies that there is some
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2740
 * potential state to clear by checking
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2741
 *	if (so->so_state & (SS_OOBPEND|SS_HAVEOOBDATA|SS_RCVATMARK))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2742
 * before calling this routine.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2743
 * Note that such a check can be made without holding so_lock since
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2744
 * sotpi_recvmsg is single-threaded (using SOREADLOCKED) and only sotpi_recvmsg
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2745
 * decrements so_oobsigcnt.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2746
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2747
 * When data is read *after* the point that all pending
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2748
 * oob data has been consumed the oob indication is cleared.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2749
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2750
 * This logic keeps select/poll returning POLLRDBAND and
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2751
 * SIOCATMARK returning true until we have read past
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2752
 * the mark.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2753
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2754
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2755
sorecv_update_oobstate(struct sonode *so)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2756
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2757
	mutex_enter(&so->so_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2758
	ASSERT(so_verify_oobstate(so));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2759
	dprintso(so, 1,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2760
		("sorecv_update_oobstate: counts %d/%d state %s\n",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2761
		so->so_oobsigcnt,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2762
		so->so_oobcnt, pr_state(so->so_state, so->so_mode)));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2763
	if (so->so_oobsigcnt == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2764
		/* No more pending oob indications */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2765
		so->so_state &= ~(SS_OOBPEND|SS_HAVEOOBDATA|SS_RCVATMARK);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2766
		freemsg(so->so_oobmsg);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2767
		so->so_oobmsg = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2768
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2769
	ASSERT(so_verify_oobstate(so));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2770
	mutex_exit(&so->so_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2771
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2772
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2773
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2774
 * Handle recv* calls for an so which has NL7C saved recv mblk_t(s).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2775
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2776
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2777
nl7c_sorecv(struct sonode *so, mblk_t **rmp, uio_t *uiop, rval_t *rp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2778
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2779
	int	error = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2780
	mblk_t *tmp = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2781
	mblk_t *pmp = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2782
	mblk_t *nmp = so->so_nl7c_rcv_mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2783
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2784
	ASSERT(nmp != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2785
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2786
	while (nmp != NULL && uiop->uio_resid > 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2787
		ssize_t n;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2788
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2789
		if (DB_TYPE(nmp) == M_DATA) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2790
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2791
			 * We have some data, uiomove up to resid bytes.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2792
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2793
			n = MIN(MBLKL(nmp), uiop->uio_resid);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2794
			if (n > 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2795
				error = uiomove(nmp->b_rptr, n, UIO_READ, uiop);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2796
			if (error)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2797
				break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2798
			nmp->b_rptr += n;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2799
			if (nmp->b_rptr == nmp->b_wptr) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2800
				pmp = nmp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2801
				nmp = nmp->b_cont;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2802
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2803
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2804
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2805
			 * We only handle data, save for caller to handle.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2806
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2807
			if (pmp != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2808
				pmp->b_cont = nmp->b_cont;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2809
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2810
			nmp->b_cont = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2811
			if (*rmp == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2812
				*rmp = nmp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2813
			} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2814
				tmp->b_next = nmp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2815
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2816
			nmp = nmp->b_cont;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2817
			tmp = nmp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2818
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2819
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2820
	if (pmp != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2821
		/* Free any mblk_t(s) which we have consumed */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2822
		pmp->b_cont = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2823
		freemsg(so->so_nl7c_rcv_mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2824
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2825
	if ((so->so_nl7c_rcv_mp = nmp) == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2826
		/* Last mblk_t so return the saved rval from kstrgetmsg() */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2827
		rp->r_vals = so->so_nl7c_rcv_rval;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2828
		so->so_nl7c_rcv_rval = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2829
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2830
		/* More mblk_t(s) to process so no rval to return */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2831
		rp->r_vals = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2832
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2833
	return (error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2834
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2835
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2836
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2837
 * Receive the next message on the queue.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2838
 * If msg_controllen is non-zero when called the caller is interested in
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2839
 * any received control info (options).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2840
 * If msg_namelen is non-zero when called the caller is interested in
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2841
 * any received source address.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2842
 * The routine returns with msg_control and msg_name pointing to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2843
 * kmem_alloc'ed memory which the caller has to free.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2844
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2845
int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2846
sotpi_recvmsg(struct sonode *so, struct nmsghdr *msg, struct uio *uiop)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2847
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2848
	union T_primitives	*tpr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2849
	mblk_t			*mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2850
	uchar_t			pri;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2851
	int			pflag, opflag;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2852
	void			*control;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2853
	t_uscalar_t		controllen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2854
	t_uscalar_t		namelen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2855
	int			so_state = so->so_state; /* Snapshot */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2856
	ssize_t			saved_resid;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2857
	int			error;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2858
	rval_t			rval;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2859
	int			flags;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2860
	clock_t			timout;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2861
	int			first;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2862
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2863
	flags = msg->msg_flags;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2864
	msg->msg_flags = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2865
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2866
	dprintso(so, 1, ("sotpi_recvmsg(%p, %p, 0x%x) state %s err %d\n",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2867
		so, msg, flags,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2868
		pr_state(so->so_state, so->so_mode), so->so_error));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2869
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2870
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2871
	 * If we are not connected because we have never been connected
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2872
	 * we return ENOTCONN. If we have been connected (but are no longer
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2873
	 * connected) then SS_CANTRCVMORE is set and we let kstrgetmsg return
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2874
	 * the EOF.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2875
	 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2876
	 * An alternative would be to post an ENOTCONN error in stream head
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2877
	 * (read+write) and clear it when we're connected. However, that error
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2878
	 * would cause incorrect poll/select behavior!
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2879
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2880
	if ((so_state & (SS_ISCONNECTED|SS_CANTRCVMORE)) == 0 &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2881
	    (so->so_mode & SM_CONNREQUIRED)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2882
		return (ENOTCONN);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2883
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2884
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2885
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2886
	 * Note: SunOS 4.X checks uio_resid == 0 before going to sleep (but
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2887
	 * after checking that the read queue is empty) and returns zero.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2888
	 * This implementation will sleep (in kstrgetmsg) even if uio_resid
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2889
	 * is zero.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2890
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2891
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2892
	if (flags & MSG_OOB) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2893
		/* Check that the transport supports OOB */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2894
		if (!(so->so_mode & SM_EXDATA))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2895
			return (EOPNOTSUPP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2896
		return (sorecvoob(so, msg, uiop, flags));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2897
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2898
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2899
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2900
	 * Set msg_controllen and msg_namelen to zero here to make it
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2901
	 * simpler in the cases that no control or name is returned.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2902
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2903
	controllen = msg->msg_controllen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2904
	namelen = msg->msg_namelen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2905
	msg->msg_controllen = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2906
	msg->msg_namelen = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2907
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2908
	dprintso(so, 1, ("sotpi_recvmsg: namelen %d controllen %d\n",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2909
		namelen, controllen));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2910
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2911
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2912
	 * If an NL7C enabled socket and not waiting for write data.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2913
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2914
	mutex_enter(&so->so_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2915
	if ((so->so_nl7c_flags & (NL7C_ENABLED|NL7C_WAITWRITE)) ==
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2916
	    NL7C_ENABLED) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2917
		if (so->so_nl7c_uri) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2918
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2919
			 * Close uri processing for a previous request.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2920
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2921
			nl7c_close(so);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2922
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2923
		if (nl7c_process(so,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2924
		    (so->so_state & (SS_NONBLOCK|SS_NDELAY)),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2925
		    (int)((tcp_t *)so->so_priv)->tcp_mss)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2926
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2927
			 * NL7C has completed processing on the socket,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2928
			 * clear the enabled bit as no further NL7C
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2929
			 * processing will be needed.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2930
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2931
			so->so_nl7c_flags = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2932
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2933
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2934
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2935
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2936
	 * Only one reader is allowed at any given time. This is needed
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2937
	 * for T_EXDATA handling and, in the future, MSG_WAITALL.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2938
	 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2939
	 * This is slightly different that BSD behavior in that it fails with
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2940
	 * EWOULDBLOCK when using nonblocking io. In BSD the read queue access
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2941
	 * is single-threaded using sblock(), which is dropped while waiting
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2942
	 * for data to appear. The difference shows up e.g. if one
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2943
	 * file descriptor does not have O_NONBLOCK but a dup'ed file descriptor
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2944
	 * does use nonblocking io and different threads are reading each
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2945
	 * file descriptor. In BSD there would never be an EWOULDBLOCK error
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2946
	 * in this case as long as the read queue doesn't get empty.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2947
	 * In this implementation the thread using nonblocking io can
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2948
	 * get an EWOULDBLOCK error due to the blocking thread executing
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2949
	 * e.g. in the uiomove in kstrgetmsg.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2950
	 * This difference is not believed to be significant.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2951
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2952
	error = so_lock_read_intr(so, uiop->uio_fmode);	/* Set SOREADLOCKED */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2953
	mutex_exit(&so->so_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2954
	if (error)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2955
		return (error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2956
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2957
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2958
	 * Tell kstrgetmsg to not inspect the stream head errors until all
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2959
	 * queued data has been consumed.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2960
	 * Use a timeout=-1 to wait forever unless MSG_DONTWAIT is set.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2961
	 * Also, If uio_fmode indicates nonblocking kstrgetmsg will not block.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2962
	 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2963
	 * MSG_WAITALL only applies to M_DATA and T_DATA_IND messages and
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2964
	 * to T_OPTDATA_IND that do not contain any user-visible control msg.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2965
	 * Note that MSG_WAITALL set with MSG_PEEK is a noop.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2966
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2967
	pflag = MSG_ANY | MSG_DELAYERROR;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2968
	if (flags & MSG_PEEK) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2969
		pflag |= MSG_IPEEK;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2970
		flags &= ~MSG_WAITALL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2971
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2972
	if (so->so_mode & SM_ATOMIC)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2973
		pflag |= MSG_DISCARDTAIL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2974
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2975
	if (flags & MSG_DONTWAIT)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2976
		timout = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2977
	else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2978
		timout = -1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2979
	opflag = pflag;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2980
	first = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2981
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2982
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2983
	 * If so saved NL7C rcv mblk_t(s) uiomove them first
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2984
	 * else get'm from the streamhead.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2985
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2986
retry:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2987
	saved_resid = uiop->uio_resid;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2988
	pri = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2989
	mp = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2990
	if (so->so_nl7c_rcv_mp != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2991
		error = nl7c_sorecv(so, &mp, uiop, &rval);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2992
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2993
		error = kstrgetmsg(SOTOV(so), &mp, uiop, &pri, &pflag,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2994
		    timout, &rval);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2995
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2996
	if (error) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2997
		switch (error) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2998
		case EINTR:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2999
		case EWOULDBLOCK:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3000
			if (!first)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3001
				error = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3002
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3003
		case ETIME:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3004
			/* Returned from kstrgetmsg when timeout expires */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3005
			if (!first)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3006
				error = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3007
			else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3008
				error = EWOULDBLOCK;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3009
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3010
		default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3011
			eprintsoline(so, error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3012
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3013
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3014
		mutex_enter(&so->so_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3015
		so_unlock_read(so);	/* Clear SOREADLOCKED */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3016
		mutex_exit(&so->so_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3017
		return (error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3018
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3019
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3020
	 * For datagrams the MOREDATA flag is used to set MSG_TRUNC.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3021
	 * For non-datagrams MOREDATA is used to set MSG_EOR.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3022
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3023
	ASSERT(!(rval.r_val1 & MORECTL));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3024
	if ((rval.r_val1 & MOREDATA) && (so->so_mode & SM_ATOMIC))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3025
		msg->msg_flags |= MSG_TRUNC;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3026
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3027
	if (mp == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3028
		dprintso(so, 1, ("sotpi_recvmsg: got M_DATA\n"));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3029
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3030
		 * 4.3BSD and 4.4BSD clears the mark when peeking across it.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3031
		 * The draft Posix socket spec states that the mark should
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3032
		 * not be cleared when peeking. We follow the latter.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3033
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3034
		if ((so->so_state &
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3035
		    (SS_OOBPEND|SS_HAVEOOBDATA|SS_RCVATMARK)) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3036
		    (uiop->uio_resid != saved_resid) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3037
		    !(flags & MSG_PEEK)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3038
			sorecv_update_oobstate(so);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3039
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3040
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3041
		mutex_enter(&so->so_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3042
		/* Set MSG_EOR based on MOREDATA */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3043
		if (!(rval.r_val1 & MOREDATA)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3044
			if (so->so_state & SS_SAVEDEOR) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3045
				msg->msg_flags |= MSG_EOR;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3046
				so->so_state &= ~SS_SAVEDEOR;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3047
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3048
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3049
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3050
		 * If some data was received (i.e. not EOF) and the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3051
		 * read/recv* has not been satisfied wait for some more.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3052
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3053
		if ((flags & MSG_WAITALL) && !(msg->msg_flags & MSG_EOR) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3054
		    uiop->uio_resid != saved_resid && uiop->uio_resid > 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3055
			mutex_exit(&so->so_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3056
			first = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3057
			pflag = opflag | MSG_NOMARK;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3058
			goto retry;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3059
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3060
		so_unlock_read(so);	/* Clear SOREADLOCKED */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3061
		mutex_exit(&so->so_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3062
		return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3063
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3064
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3065
	/* strsock_proto has already verified length and alignment */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3066
	tpr = (union T_primitives *)mp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3067
	dprintso(so, 1, ("sotpi_recvmsg: type %d\n", tpr->type));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3068
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3069
	switch (tpr->type) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3070
	case T_DATA_IND: {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3071
		if ((so->so_state &
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3072
		    (SS_OOBPEND|SS_HAVEOOBDATA|SS_RCVATMARK)) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3073
		    (uiop->uio_resid != saved_resid) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3074
		    !(flags & MSG_PEEK)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3075
			sorecv_update_oobstate(so);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3076
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3077
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3078
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3079
		 * Set msg_flags to MSG_EOR based on
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3080
		 * MORE_flag and MOREDATA.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3081
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3082
		mutex_enter(&so->so_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3083
		so->so_state &= ~SS_SAVEDEOR;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3084
		if (!(tpr->data_ind.MORE_flag & 1)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3085
			if (!(rval.r_val1 & MOREDATA))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3086
				msg->msg_flags |= MSG_EOR;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3087
			else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3088
				so->so_state |= SS_SAVEDEOR;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3089
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3090
		freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3091
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3092
		 * If some data was received (i.e. not EOF) and the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3093
		 * read/recv* has not been satisfied wait for some more.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3094
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3095
		if ((flags & MSG_WAITALL) && !(msg->msg_flags & MSG_EOR) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3096
		    uiop->uio_resid != saved_resid && uiop->uio_resid > 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3097
			mutex_exit(&so->so_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3098
			first = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3099
			pflag = opflag | MSG_NOMARK;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3100
			goto retry;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3101
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3102
		so_unlock_read(so);	/* Clear SOREADLOCKED */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3103
		mutex_exit(&so->so_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3104
		return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3105
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3106
	case T_UNITDATA_IND: {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3107
		void *addr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3108
		t_uscalar_t addrlen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3109
		void *abuf;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3110
		t_uscalar_t optlen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3111
		void *opt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3112
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3113
		if ((so->so_state &
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3114
		    (SS_OOBPEND|SS_HAVEOOBDATA|SS_RCVATMARK)) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3115
		    (uiop->uio_resid != saved_resid) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3116
		    !(flags & MSG_PEEK)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3117
			sorecv_update_oobstate(so);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3118
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3119
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3120
		if (namelen != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3121
			/* Caller wants source address */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3122
			addrlen = tpr->unitdata_ind.SRC_length;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3123
			addr = sogetoff(mp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3124
				tpr->unitdata_ind.SRC_offset,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3125
				addrlen, 1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3126
			if (addr == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3127
				freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3128
				error = EPROTO;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3129
				eprintsoline(so, error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3130
				goto err;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3131
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3132
			if (so->so_family == AF_UNIX) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3133
				/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3134
				 * Can not use the transport level address.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3135
				 * If there is a SO_SRCADDR option carrying
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3136
				 * the socket level address it will be
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3137
				 * extracted below.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3138
				 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3139
				addr = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3140
				addrlen = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3141
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3142
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3143
		optlen = tpr->unitdata_ind.OPT_length;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3144
		if (optlen != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3145
			t_uscalar_t ncontrollen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3146
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3147
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3148
			 * Extract any source address option.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3149
			 * Determine how large cmsg buffer is needed.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3150
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3151
			opt = sogetoff(mp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3152
				tpr->unitdata_ind.OPT_offset,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3153
				optlen, __TPI_ALIGN_SIZE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3154
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3155
			if (opt == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3156
				freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3157
				error = EPROTO;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3158
				eprintsoline(so, error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3159
				goto err;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3160
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3161
			if (so->so_family == AF_UNIX)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3162
				so_getopt_srcaddr(opt, optlen, &addr, &addrlen);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3163
			ncontrollen = so_cmsglen(mp, opt, optlen,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3164
						!(flags & MSG_XPG4_2));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3165
			if (controllen != 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3166
				controllen = ncontrollen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3167
			else if (ncontrollen != 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3168
				msg->msg_flags |= MSG_CTRUNC;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3169
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3170
			controllen = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3171
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3172
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3173
		if (namelen != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3174
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3175
			 * Return address to caller.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3176
			 * Caller handles truncation if length
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3177
			 * exceeds msg_namelen.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3178
			 * NOTE: AF_UNIX NUL termination is ensured by
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3179
			 * the sender's copyin_name().
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3180
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3181
			abuf = kmem_alloc(addrlen, KM_SLEEP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3182
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3183
			bcopy(addr, abuf, addrlen);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3184
			msg->msg_name = abuf;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3185
			msg->msg_namelen = addrlen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3186
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3187
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3188
		if (controllen != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3189
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3190
			 * Return control msg to caller.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3191
			 * Caller handles truncation if length
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3192
			 * exceeds msg_controllen.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3193
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3194
			control = kmem_alloc(controllen, KM_SLEEP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3195
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3196
			error = so_opt2cmsg(mp, opt, optlen,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3197
					!(flags & MSG_XPG4_2),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3198
					control, controllen);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3199
			if (error) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3200
				freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3201
				if (msg->msg_namelen != 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3202
					kmem_free(msg->msg_name,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3203
						msg->msg_namelen);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3204
				kmem_free(control, controllen);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3205
				eprintsoline(so, error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3206
				goto err;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3207
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3208
			msg->msg_control = control;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3209
			msg->msg_controllen = controllen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3210
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3211
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3212
		freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3213
		mutex_enter(&so->so_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3214
		so_unlock_read(so);	/* Clear SOREADLOCKED */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3215
		mutex_exit(&so->so_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3216
		return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3217
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3218
	case T_OPTDATA_IND: {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3219
		struct T_optdata_req *tdr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3220
		void *opt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3221
		t_uscalar_t optlen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3222
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3223
		if ((so->so_state &
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3224
		    (SS_OOBPEND|SS_HAVEOOBDATA|SS_RCVATMARK)) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3225
		    (uiop->uio_resid != saved_resid) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3226
		    !(flags & MSG_PEEK)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3227
			sorecv_update_oobstate(so);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3228
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3229
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3230
		tdr = (struct T_optdata_req *)mp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3231
		optlen = tdr->OPT_length;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3232
		if (optlen != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3233
			t_uscalar_t ncontrollen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3234
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3235
			 * Determine how large cmsg buffer is needed.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3236
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3237
			opt = sogetoff(mp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3238
					tpr->optdata_ind.OPT_offset,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3239
					optlen, __TPI_ALIGN_SIZE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3240
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3241
			if (opt == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3242
				freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3243
				error = EPROTO;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3244
				eprintsoline(so, error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3245
				goto err;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3246
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3247
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3248
			ncontrollen = so_cmsglen(mp, opt, optlen,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3249
						!(flags & MSG_XPG4_2));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3250
			if (controllen != 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3251
				controllen = ncontrollen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3252
			else if (ncontrollen != 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3253
				msg->msg_flags |= MSG_CTRUNC;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3254
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3255
			controllen = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3256
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3257
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3258
		if (controllen != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3259
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3260
			 * Return control msg to caller.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3261
			 * Caller handles truncation if length
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3262
			 * exceeds msg_controllen.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3263
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3264
			control = kmem_alloc(controllen, KM_SLEEP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3265
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3266
			error = so_opt2cmsg(mp, opt, optlen,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3267
					!(flags & MSG_XPG4_2),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3268
					control, controllen);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3269
			if (error) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3270
				freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3271
				kmem_free(control, controllen);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3272
				eprintsoline(so, error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3273
				goto err;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3274
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3275
			msg->msg_control = control;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3276
			msg->msg_controllen = controllen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3277
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3278
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3279
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3280
		 * Set msg_flags to MSG_EOR based on
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3281
		 * DATA_flag and MOREDATA.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3282
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3283
		mutex_enter(&so->so_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3284
		so->so_state &= ~SS_SAVEDEOR;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3285
		if (!(tpr->data_ind.MORE_flag & 1)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3286
			if (!(rval.r_val1 & MOREDATA))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3287
				msg->msg_flags |= MSG_EOR;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3288
			else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3289
				so->so_state |= SS_SAVEDEOR;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3290
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3291
		freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3292
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3293
		 * If some data was received (i.e. not EOF) and the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3294
		 * read/recv* has not been satisfied wait for some more.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3295
		 * Not possible to wait if control info was received.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3296
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3297
		if ((flags & MSG_WAITALL) && !(msg->msg_flags & MSG_EOR) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3298
		    controllen == 0 &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3299
		    uiop->uio_resid != saved_resid && uiop->uio_resid > 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3300
			mutex_exit(&so->so_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3301
			first = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3302
			pflag = opflag | MSG_NOMARK;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3303
			goto retry;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3304
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3305
		so_unlock_read(so);	/* Clear SOREADLOCKED */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3306
		mutex_exit(&so->so_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3307
		return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3308
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3309
	case T_EXDATA_IND: {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3310
		dprintso(so, 1,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3311
			("sotpi_recvmsg: EXDATA_IND counts %d/%d consumed %ld "
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3312
			"state %s\n",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3313
			so->so_oobsigcnt, so->so_oobcnt,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3314
			saved_resid - uiop->uio_resid,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3315
			pr_state(so->so_state, so->so_mode)));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3316
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3317
		 * kstrgetmsg handles MSGMARK so there is nothing to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3318
		 * inspect in the T_EXDATA_IND.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3319
		 * strsock_proto makes the stream head queue the T_EXDATA_IND
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3320
		 * as a separate message with no M_DATA component. Furthermore,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3321
		 * the stream head does not consolidate M_DATA messages onto
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3322
		 * an MSGMARK'ed message ensuring that the T_EXDATA_IND
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3323
		 * remains a message by itself. This is needed since MSGMARK
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3324
		 * marks both the whole message as well as the last byte
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3325
		 * of the message.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3326
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3327
		freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3328
		ASSERT(uiop->uio_resid == saved_resid);	/* No data */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3329
		if (flags & MSG_PEEK) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3330
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3331
			 * Even though we are peeking we consume the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3332
			 * T_EXDATA_IND thereby moving the mark information
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3333
			 * to SS_RCVATMARK. Then the oob code below will
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3334
			 * retry the peeking kstrgetmsg.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3335
			 * Note that the stream head read queue is
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3336
			 * never flushed without holding SOREADLOCKED
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3337
			 * thus the T_EXDATA_IND can not disappear
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3338
			 * underneath us.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3339
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3340
			dprintso(so, 1,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3341
				("sotpi_recvmsg: consume EXDATA_IND "
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3342
				"counts %d/%d state %s\n",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3343
				so->so_oobsigcnt,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3344
				so->so_oobcnt,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3345
				pr_state(so->so_state, so->so_mode)));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3346
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3347
			pflag = MSG_ANY | MSG_DELAYERROR;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3348
			if (so->so_mode & SM_ATOMIC)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3349
				pflag |= MSG_DISCARDTAIL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3350
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3351
			pri = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3352
			mp = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3353
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3354
			error = kstrgetmsg(SOTOV(so), &mp, uiop,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3355
				&pri, &pflag, (clock_t)-1, &rval);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3356
			ASSERT(uiop->uio_resid == saved_resid);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3357
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3358
			if (error) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3359
#ifdef SOCK_DEBUG
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3360
				if (error != EWOULDBLOCK && error != EINTR) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3361
					eprintsoline(so, error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3362
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3363
#endif /* SOCK_DEBUG */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3364
				mutex_enter(&so->so_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3365
				so_unlock_read(so);	/* Clear SOREADLOCKED */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3366
				mutex_exit(&so->so_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3367
				return (error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3368
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3369
			ASSERT(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3370
			tpr = (union T_primitives *)mp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3371
			ASSERT(tpr->type == T_EXDATA_IND);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3372
			freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3373
		} /* end "if (flags & MSG_PEEK)" */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3374
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3375
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3376
		 * Decrement the number of queued and pending oob.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3377
		 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3378
		 * SS_RCVATMARK is cleared when we read past a mark.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3379
		 * SS_HAVEOOBDATA is cleared when we've read past the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3380
		 * last mark.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3381
		 * SS_OOBPEND is cleared if we've read past the last
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3382
		 * mark and no (new) SIGURG has been posted.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3383
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3384
		mutex_enter(&so->so_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3385
		ASSERT(so_verify_oobstate(so));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3386
		ASSERT(so->so_oobsigcnt >= so->so_oobcnt);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3387
		ASSERT(so->so_oobsigcnt > 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3388
		so->so_oobsigcnt--;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3389
		ASSERT(so->so_oobcnt > 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3390
		so->so_oobcnt--;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3391
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3392
		 * Since the T_EXDATA_IND has been removed from the stream
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3393
		 * head, but we have not read data past the mark,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3394
		 * sockfs needs to track that the socket is still at the mark.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3395
		 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3396
		 * Since no data was received call kstrgetmsg again to wait
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3397
		 * for data.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3398
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3399
		so->so_state |= SS_RCVATMARK;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3400
		mutex_exit(&so->so_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3401
		dprintso(so, 1,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3402
		    ("sotpi_recvmsg: retry EXDATA_IND counts %d/%d state %s\n",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3403
		    so->so_oobsigcnt, so->so_oobcnt,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3404
		    pr_state(so->so_state, so->so_mode)));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3405
		pflag = opflag;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3406
		goto retry;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3407
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3408
	default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3409
		ASSERT(0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3410
		freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3411
		error = EPROTO;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3412
		eprintsoline(so, error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3413
		goto err;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3414
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3415
	/* NOTREACHED */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3416
err:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3417
	mutex_enter(&so->so_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3418
	so_unlock_read(so);	/* Clear SOREADLOCKED */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3419
	mutex_exit(&so->so_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3420
	return (error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3421
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3422
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3423
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3424
 * Sending data with options on a datagram socket.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3425
 * Assumes caller has verified that SS_ISBOUND etc. are set.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3426
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3427
static int
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  3428
sosend_dgramcmsg(struct sonode *so, struct sockaddr *name, socklen_t namelen,
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  3429
    struct uio *uiop, void *control, t_uscalar_t controllen, int flags)
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3430
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3431
	struct T_unitdata_req	tudr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3432
	mblk_t			*mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3433
	int			error;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3434
	void			*addr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3435
	socklen_t		addrlen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3436
	void			*src;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3437
	socklen_t		srclen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3438
	ssize_t			len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3439
	int			size;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3440
	struct T_opthdr		toh;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3441
	struct fdbuf		*fdbuf;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3442
	t_uscalar_t		optlen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3443
	void			*fds;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3444
	int			fdlen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3445
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3446
	ASSERT(name && namelen);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3447
	ASSERT(control && controllen);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3448
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3449
	len = uiop->uio_resid;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3450
	if (len > (ssize_t)so->so_tidu_size) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3451
		return (EMSGSIZE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3452
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3453
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3454
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3455
	 * For AF_UNIX the destination address is translated to an internal
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3456
	 * name and the source address is passed as an option.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3457
	 * Also, file descriptors are passed as file pointers in an
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3458
	 * option.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3459
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3460
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3461
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3462
	 * Length and family checks.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3463
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3464
	error = so_addr_verify(so, name, namelen);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3465
	if (error) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3466
		eprintsoline(so, error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3467
		return (error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3468
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3469
	if (so->so_family == AF_UNIX) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3470
		if (so->so_state & SS_FADDR_NOXLATE) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3471
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3472
			 * Already have a transport internal address. Do not
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3473
			 * pass any (transport internal) source address.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3474
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3475
			addr = name;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3476
			addrlen = namelen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3477
			src = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3478
			srclen = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3479
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3480
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3481
			 * Pass the sockaddr_un source address as an option
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3482
			 * and translate the remote address.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3483
			 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3484
			 * Note that this code does not prevent so_laddr_sa
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3485
			 * from changing while it is being used. Thus
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3486
			 * if an unbind+bind occurs concurrently with this
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3487
			 * send the peer might see a partially new and a
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3488
			 * partially old "from" address.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3489
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3490
			src = so->so_laddr_sa;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3491
			srclen = (t_uscalar_t)so->so_laddr_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3492
			dprintso(so, 1,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3493
			    ("sosend_dgramcmsg UNIX: srclen %d, src %p\n",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3494
			    srclen, src));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3495
			error = so_ux_addr_xlate(so, name, namelen,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3496
				(flags & MSG_XPG4_2),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3497
				&addr, &addrlen);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3498
			if (error) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3499
				eprintsoline(so, error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3500
				return (error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3501
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3502
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3503
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3504
		addr = name;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3505
		addrlen = namelen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3506
		src = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3507
		srclen = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3508
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3509
	optlen = so_optlen(control, controllen,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3510
					!(flags & MSG_XPG4_2));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3511
	tudr.PRIM_type = T_UNITDATA_REQ;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3512
	tudr.DEST_length = addrlen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3513
	tudr.DEST_offset = (t_scalar_t)sizeof (tudr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3514
	if (srclen != 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3515
		tudr.OPT_length = (t_scalar_t)(optlen + sizeof (toh) +
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3516
		    _TPI_ALIGN_TOPT(srclen));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3517
	else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3518
		tudr.OPT_length = optlen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3519
	tudr.OPT_offset = (t_scalar_t)(sizeof (tudr) +
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3520
				_TPI_ALIGN_TOPT(addrlen));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3521
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3522
	size = tudr.OPT_offset + tudr.OPT_length;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3523
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3524
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3525
	 * File descriptors only when SM_FDPASSING set.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3526
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3527
	error = so_getfdopt(control, controllen,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3528
			!(flags & MSG_XPG4_2), &fds, &fdlen);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3529
	if (error)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3530
		return (error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3531
	if (fdlen != -1) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3532
		if (!(so->so_mode & SM_FDPASSING))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3533
			return (EOPNOTSUPP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3534
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3535
		error = fdbuf_create(fds, fdlen, &fdbuf);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3536
		if (error)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3537
			return (error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3538
		mp = fdbuf_allocmsg(size, fdbuf);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3539
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3540
		mp = soallocproto(size, _ALLOC_INTR);
455
d7392d9146c7 PSARC/2005/478 Add desballoc() to the DDI
meem
parents: 0
diff changeset
  3541
		if (mp == NULL) {
d7392d9146c7 PSARC/2005/478 Add desballoc() to the DDI
meem
parents: 0
diff changeset
  3542
			/*
d7392d9146c7 PSARC/2005/478 Add desballoc() to the DDI
meem
parents: 0
diff changeset
  3543
			 * Caught a signal waiting for memory.
d7392d9146c7 PSARC/2005/478 Add desballoc() to the DDI
meem
parents: 0
diff changeset
  3544
			 * Let send* return EINTR.
d7392d9146c7 PSARC/2005/478 Add desballoc() to the DDI
meem
parents: 0
diff changeset
  3545
			 */
d7392d9146c7 PSARC/2005/478 Add desballoc() to the DDI
meem
parents: 0
diff changeset
  3546
			return (EINTR);
d7392d9146c7 PSARC/2005/478 Add desballoc() to the DDI
meem
parents: 0
diff changeset
  3547
		}
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3548
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3549
	soappendmsg(mp, &tudr, sizeof (tudr));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3550
	soappendmsg(mp, addr, addrlen);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3551
	mp->b_wptr += _TPI_ALIGN_TOPT(addrlen) - addrlen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3552
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3553
	if (fdlen != -1) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3554
		ASSERT(fdbuf != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3555
		toh.level = SOL_SOCKET;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3556
		toh.name = SO_FILEP;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3557
		toh.len = fdbuf->fd_size +
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3558
				(t_uscalar_t)sizeof (struct T_opthdr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3559
		toh.status = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3560
		soappendmsg(mp, &toh, sizeof (toh));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3561
		soappendmsg(mp, fdbuf, fdbuf->fd_size);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3562
		ASSERT(__TPI_TOPT_ISALIGNED(mp->b_wptr));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3563
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3564
	if (srclen != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3565
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3566
		 * There is a AF_UNIX sockaddr_un to include as a source
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3567
		 * address option.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3568
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3569
		toh.level = SOL_SOCKET;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3570
		toh.name = SO_SRCADDR;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3571
		toh.len = (t_uscalar_t)(srclen + sizeof (struct T_opthdr));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3572
		toh.status = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3573
		soappendmsg(mp, &toh, sizeof (toh));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3574
		soappendmsg(mp, src, srclen);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3575
		mp->b_wptr += _TPI_ALIGN_TOPT(srclen) - srclen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3576
		ASSERT(__TPI_TOPT_ISALIGNED(mp->b_wptr));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3577
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3578
	ASSERT(mp->b_wptr <= mp->b_datap->db_lim);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3579
	so_cmsg2opt(control, controllen, !(flags & MSG_XPG4_2), mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3580
	/* At most 3 bytes left in the message */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3581
	ASSERT(MBLKL(mp) > (ssize_t)(size - __TPI_ALIGN_SIZE));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3582
	ASSERT(MBLKL(mp) <= (ssize_t)size);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3583
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3584
	ASSERT(mp->b_wptr <= mp->b_datap->db_lim);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3585
#ifdef C2_AUDIT
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3586
	if (audit_active)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3587
		audit_sock(T_UNITDATA_REQ, strvp2wq(SOTOV(so)), mp, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3588
#endif /* C2_AUDIT */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3589
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3590
	error = kstrputmsg(SOTOV(so), mp, uiop, len, 0, MSG_BAND, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3591
#ifdef SOCK_DEBUG
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3592
	if (error) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3593
		eprintsoline(so, error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3594
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3595
#endif /* SOCK_DEBUG */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3596
	return (error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3597
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3598
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3599
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3600
 * Sending data with options on a connected stream socket.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3601
 * Assumes caller has verified that SS_ISCONNECTED is set.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3602
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3603
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3604
sosend_svccmsg(struct sonode *so,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3605
		struct uio *uiop,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3606
		int more,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3607
		void *control,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3608
		t_uscalar_t controllen,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3609
		int flags)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3610
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3611
	struct T_optdata_req	tdr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3612
	mblk_t			*mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3613
	int			error;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3614
	ssize_t			iosize;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3615
	int			first = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3616
	int			size;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3617
	struct fdbuf		*fdbuf;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3618
	t_uscalar_t		optlen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3619
	void			*fds;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3620
	int			fdlen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3621
	struct T_opthdr		toh;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3622
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3623
	dprintso(so, 1,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3624
		("sosend_svccmsg: resid %ld bytes\n", uiop->uio_resid));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3625
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3626
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3627
	 * Has to be bound and connected. However, since no locks are
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3628
	 * held the state could have changed after sotpi_sendmsg checked it
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3629
	 * thus it is not possible to ASSERT on the state.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3630
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3631
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3632
	/* Options on connection-oriented only when SM_OPTDATA set. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3633
	if (!(so->so_mode & SM_OPTDATA))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3634
		return (EOPNOTSUPP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3635
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3636
	do {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3637
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3638
		 * Set the MORE flag if uio_resid does not fit in this
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3639
		 * message or if the caller passed in "more".
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3640
		 * Error for transports with zero tidu_size.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3641
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3642
		tdr.PRIM_type = T_OPTDATA_REQ;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3643
		iosize = so->so_tidu_size;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3644
		if (iosize <= 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3645
			return (EMSGSIZE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3646
		if (uiop->uio_resid > iosize) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3647
			tdr.DATA_flag = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3648
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3649
			if (more)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3650
				tdr.DATA_flag = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3651
			else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3652
				tdr.DATA_flag = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3653
			iosize = uiop->uio_resid;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3654
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3655
		dprintso(so, 1, ("sosend_svccmsg: sending %d, %ld bytes\n",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3656
			tdr.DATA_flag, iosize));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3657
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3658
		optlen = so_optlen(control, controllen, !(flags & MSG_XPG4_2));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3659
		tdr.OPT_length = optlen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3660
		tdr.OPT_offset = (t_scalar_t)sizeof (tdr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3661
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3662
		size = (int)sizeof (tdr) + optlen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3663
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3664
		 * File descriptors only when SM_FDPASSING set.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3665
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3666
		error = so_getfdopt(control, controllen,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3667
				!(flags & MSG_XPG4_2), &fds, &fdlen);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3668
		if (error)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3669
			return (error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3670
		if (fdlen != -1) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3671
			if (!(so->so_mode & SM_FDPASSING))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3672
				return (EOPNOTSUPP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3673
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3674
			error = fdbuf_create(fds, fdlen, &fdbuf);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3675
			if (error)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3676
				return (error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3677
			mp = fdbuf_allocmsg(size, fdbuf);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3678
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3679
			mp = soallocproto(size, _ALLOC_INTR);
455
d7392d9146c7 PSARC/2005/478 Add desballoc() to the DDI
meem
parents: 0
diff changeset
  3680
			if (mp == NULL) {
d7392d9146c7 PSARC/2005/478 Add desballoc() to the DDI
meem
parents: 0
diff changeset
  3681
				/*
d7392d9146c7 PSARC/2005/478 Add desballoc() to the DDI
meem
parents: 0
diff changeset
  3682
				 * Caught a signal waiting for memory.
d7392d9146c7 PSARC/2005/478 Add desballoc() to the DDI
meem
parents: 0
diff changeset
  3683
				 * Let send* return EINTR.
d7392d9146c7 PSARC/2005/478 Add desballoc() to the DDI
meem
parents: 0
diff changeset
  3684
				 */
d7392d9146c7 PSARC/2005/478 Add desballoc() to the DDI
meem
parents: 0
diff changeset
  3685
				return (first ? EINTR : 0);
d7392d9146c7 PSARC/2005/478 Add desballoc() to the DDI
meem
parents: 0
diff changeset
  3686
			}
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3687
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3688
		soappendmsg(mp, &tdr, sizeof (tdr));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3689
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3690
		if (fdlen != -1) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3691
			ASSERT(fdbuf != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3692
			toh.level = SOL_SOCKET;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3693
			toh.name = SO_FILEP;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3694
			toh.len = fdbuf->fd_size +
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3695
				(t_uscalar_t)sizeof (struct T_opthdr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3696
			toh.status = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3697
			soappendmsg(mp, &toh, sizeof (toh));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3698
			soappendmsg(mp, fdbuf, fdbuf->fd_size);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3699
			ASSERT(__TPI_TOPT_ISALIGNED(mp->b_wptr));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3700
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3701
		so_cmsg2opt(control, controllen, !(flags & MSG_XPG4_2), mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3702
		/* At most 3 bytes left in the message */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3703
		ASSERT(MBLKL(mp) > (ssize_t)(size - __TPI_ALIGN_SIZE));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3704
		ASSERT(MBLKL(mp) <= (ssize_t)size);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3705
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3706
		ASSERT(mp->b_wptr <= mp->b_datap->db_lim);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3707
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3708
		error = kstrputmsg(SOTOV(so), mp, uiop, iosize,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3709
					0, MSG_BAND, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3710
		if (error) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3711
			if (!first && error == EWOULDBLOCK)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3712
				return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3713
			eprintsoline(so, error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3714
			return (error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3715
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3716
		control = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3717
		first = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3718
		if (uiop->uio_resid > 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3719
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3720
			 * Recheck for fatal errors. Fail write even though
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3721
			 * some data have been written. This is consistent
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3722
			 * with strwrite semantics and BSD sockets semantics.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3723
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3724
			if (so->so_state & SS_CANTSENDMORE) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3725
				tsignal(curthread, SIGPIPE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3726
				eprintsoline(so, error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3727
				return (EPIPE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3728
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3729
			if (so->so_error != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3730
				mutex_enter(&so->so_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3731
				error = sogeterr(so);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3732
				mutex_exit(&so->so_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3733
				if (error != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3734
					eprintsoline(so, error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3735
					return (error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3736
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3737
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3738
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3739
	} while (uiop->uio_resid > 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3740
	return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3741
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3742
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3743
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3744
 * Sending data on a datagram socket.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3745
 * Assumes caller has verified that SS_ISBOUND etc. are set.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3746
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3747
 * For AF_UNIX the destination address is translated to an internal
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3748
 * name and the source address is passed as an option.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3749
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3750
int
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  3751
sosend_dgram(struct sonode *so, struct sockaddr	*name, socklen_t namelen,
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  3752
    struct uio *uiop, int flags)
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3753
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3754
	struct T_unitdata_req	tudr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3755
	mblk_t			*mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3756
	int			error;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3757
	void			*addr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3758
	socklen_t		addrlen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3759
	void			*src;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3760
	socklen_t		srclen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3761
	ssize_t			len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3762
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  3763
	ASSERT(name != NULL && namelen != 0);
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3764
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3765
	len = uiop->uio_resid;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3766
	if (len > so->so_tidu_size) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3767
		error = EMSGSIZE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3768
		goto done;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3769
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3770
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  3771
	/* Length and family checks */
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3772
	error = so_addr_verify(so, name, namelen);
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  3773
	if (error != 0)
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3774
		goto done;
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  3775
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  3776
	if (so->so_state & SS_DIRECT)
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  3777
		return (sodgram_direct(so, name, namelen, uiop, flags));
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  3778
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3779
	if (so->so_family == AF_UNIX) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3780
		if (so->so_state & SS_FADDR_NOXLATE) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3781
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3782
			 * Already have a transport internal address. Do not
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3783
			 * pass any (transport internal) source address.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3784
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3785
			addr = name;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3786
			addrlen = namelen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3787
			src = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3788
			srclen = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3789
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3790
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3791
			 * Pass the sockaddr_un source address as an option
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3792
			 * and translate the remote address.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3793
			 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3794
			 * Note that this code does not prevent so_laddr_sa
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3795
			 * from changing while it is being used. Thus
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3796
			 * if an unbind+bind occurs concurrently with this
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3797
			 * send the peer might see a partially new and a
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3798
			 * partially old "from" address.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3799
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3800
			src = so->so_laddr_sa;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3801
			srclen = (socklen_t)so->so_laddr_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3802
			dprintso(so, 1,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3803
				("sosend_dgram UNIX: srclen %d, src %p\n",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3804
				srclen, src));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3805
			error = so_ux_addr_xlate(so, name, namelen,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3806
				(flags & MSG_XPG4_2),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3807
				&addr, &addrlen);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3808
			if (error) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3809
				eprintsoline(so, error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3810
				goto done;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3811
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3812
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3813
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3814
		addr = name;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3815
		addrlen = namelen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3816
		src = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3817
		srclen = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3818
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3819
	tudr.PRIM_type = T_UNITDATA_REQ;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3820
	tudr.DEST_length = addrlen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3821
	tudr.DEST_offset = (t_scalar_t)sizeof (tudr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3822
	if (srclen == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3823
		tudr.OPT_length = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3824
		tudr.OPT_offset = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3825
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3826
		mp = soallocproto2(&tudr, sizeof (tudr),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3827
		    addr, addrlen, 0, _ALLOC_INTR);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3828
		if (mp == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3829
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3830
			 * Caught a signal waiting for memory.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3831
			 * Let send* return EINTR.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3832
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3833
			error = EINTR;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3834
			goto done;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3835
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3836
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3837
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3838
		 * There is a AF_UNIX sockaddr_un to include as a source
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3839
		 * address option.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3840
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3841
		struct T_opthdr toh;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3842
		ssize_t size;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3843
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3844
		tudr.OPT_length = (t_scalar_t)(sizeof (toh) +
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3845
					_TPI_ALIGN_TOPT(srclen));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3846
		tudr.OPT_offset = (t_scalar_t)(sizeof (tudr) +
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3847
					_TPI_ALIGN_TOPT(addrlen));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3848
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3849
		toh.level = SOL_SOCKET;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3850
		toh.name = SO_SRCADDR;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3851
		toh.len = (t_uscalar_t)(srclen + sizeof (struct T_opthdr));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3852
		toh.status = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3853
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3854
		size = tudr.OPT_offset + tudr.OPT_length;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3855
		mp = soallocproto2(&tudr, sizeof (tudr),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3856
		    addr, addrlen, size, _ALLOC_INTR);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3857
		if (mp == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3858
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3859
			 * Caught a signal waiting for memory.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3860
			 * Let send* return EINTR.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3861
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3862
			error = EINTR;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3863
			goto done;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3864
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3865
		mp->b_wptr += _TPI_ALIGN_TOPT(addrlen) - addrlen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3866
		soappendmsg(mp, &toh, sizeof (toh));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3867
		soappendmsg(mp, src, srclen);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3868
		mp->b_wptr += _TPI_ALIGN_TOPT(srclen) - srclen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3869
		ASSERT(mp->b_wptr <= mp->b_datap->db_lim);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3870
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3871
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3872
#ifdef C2_AUDIT
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3873
	if (audit_active)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3874
		audit_sock(T_UNITDATA_REQ, strvp2wq(SOTOV(so)), mp, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3875
#endif /* C2_AUDIT */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3876
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3877
	error = kstrputmsg(SOTOV(so), mp, uiop, len, 0, MSG_BAND, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3878
done:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3879
#ifdef SOCK_DEBUG
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3880
	if (error) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3881
		eprintsoline(so, error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3882
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3883
#endif /* SOCK_DEBUG */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3884
	return (error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3885
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3886
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3887
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3888
 * Sending data on a connected stream socket.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3889
 * Assumes caller has verified that SS_ISCONNECTED is set.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3890
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3891
int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3892
sosend_svc(struct sonode *so,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3893
	struct uio *uiop,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3894
	t_scalar_t prim,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3895
	int more,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3896
	int sflag)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3897
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3898
	struct T_data_req	tdr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3899
	mblk_t			*mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3900
	int			error;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3901
	ssize_t			iosize;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3902
	int			first = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3903
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3904
	dprintso(so, 1,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3905
		("sosend_svc: %p, resid %ld bytes, prim %d, sflag 0x%x\n",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3906
		so, uiop->uio_resid, prim, sflag));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3907
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3908
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3909
	 * Has to be bound and connected. However, since no locks are
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3910
	 * held the state could have changed after sotpi_sendmsg checked it
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3911
	 * thus it is not possible to ASSERT on the state.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3912
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3913
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3914
	do {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3915
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3916
		 * Set the MORE flag if uio_resid does not fit in this
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3917
		 * message or if the caller passed in "more".
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3918
		 * Error for transports with zero tidu_size.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3919
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3920
		tdr.PRIM_type = prim;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3921
		iosize = so->so_tidu_size;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3922
		if (iosize <= 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3923
			return (EMSGSIZE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3924
		if (uiop->uio_resid > iosize) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3925
			tdr.MORE_flag = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3926
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3927
			if (more)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3928
				tdr.MORE_flag = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3929
			else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3930
				tdr.MORE_flag = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3931
			iosize = uiop->uio_resid;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3932
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3933
		dprintso(so, 1, ("sosend_svc: sending 0x%x %d, %ld bytes\n",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3934
			prim, tdr.MORE_flag, iosize));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3935
		mp = soallocproto1(&tdr, sizeof (tdr), 0, _ALLOC_INTR);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3936
		if (mp == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3937
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3938
			 * Caught a signal waiting for memory.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3939
			 * Let send* return EINTR.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3940
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3941
			if (first)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3942
				return (EINTR);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3943
			else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3944
				return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3945
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3946
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3947
		error = kstrputmsg(SOTOV(so), mp, uiop, iosize,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3948
					0, sflag | MSG_BAND, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3949
		if (error) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3950
			if (!first && error == EWOULDBLOCK)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3951
				return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3952
			eprintsoline(so, error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3953
			return (error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3954
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3955
		first = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3956
		if (uiop->uio_resid > 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3957
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3958
			 * Recheck for fatal errors. Fail write even though
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3959
			 * some data have been written. This is consistent
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3960
			 * with strwrite semantics and BSD sockets semantics.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3961
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3962
			if (so->so_state & SS_CANTSENDMORE) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3963
				tsignal(curthread, SIGPIPE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3964
				eprintsoline(so, error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3965
				return (EPIPE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3966
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3967
			if (so->so_error != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3968
				mutex_enter(&so->so_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3969
				error = sogeterr(so);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3970
				mutex_exit(&so->so_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3971
				if (error != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3972
					eprintsoline(so, error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3973
					return (error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3974
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3975
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3976
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3977
	} while (uiop->uio_resid > 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3978
	return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3979
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3980
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3981
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3982
 * Check the state for errors and call the appropriate send function.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3983
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3984
 * If MSG_DONTROUTE is set (and SO_DONTROUTE isn't already set)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3985
 * this function issues a setsockopt to toggle SO_DONTROUTE before and
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3986
 * after sending the message.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3987
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3988
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3989
sotpi_sendmsg(struct sonode *so, struct nmsghdr *msg, struct uio *uiop)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3990
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3991
	int		so_state;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3992
	int		so_mode;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3993
	int		error;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3994
	struct sockaddr *name;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3995
	t_uscalar_t	namelen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3996
	int		dontroute;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3997
	int		flags;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3998
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3999
	dprintso(so, 1, ("sotpi_sendmsg(%p, %p, 0x%x) state %s, error %d\n",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4000
		so, msg, msg->msg_flags,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4001
		pr_state(so->so_state, so->so_mode), so->so_error));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4002
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4003
	mutex_enter(&so->so_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4004
	so_state = so->so_state;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4005
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4006
	if (so_state & SS_CANTSENDMORE) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4007
		mutex_exit(&so->so_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4008
		tsignal(curthread, SIGPIPE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4009
		return (EPIPE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4010
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4011
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4012
	if (so->so_error != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4013
		error = sogeterr(so);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4014
		if (error != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4015
			mutex_exit(&so->so_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4016
			return (error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4017
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4018
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4019
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4020
	name = (struct sockaddr *)msg->msg_name;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4021
	namelen = msg->msg_namelen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4022
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4023
	so_mode = so->so_mode;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4024
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4025
	if (name == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4026
		if (!(so_state & SS_ISCONNECTED)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4027
			mutex_exit(&so->so_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4028
			if (so_mode & SM_CONNREQUIRED)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4029
				return (ENOTCONN);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4030
			else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4031
				return (EDESTADDRREQ);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4032
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4033
		if (so_mode & SM_CONNREQUIRED) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4034
			name = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4035
			namelen = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4036
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4037
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4038
			 * Note that this code does not prevent so_faddr_sa
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4039
			 * from changing while it is being used. Thus
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4040
			 * if an "unconnect"+connect occurs concurrently with
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4041
			 * this send the datagram might be delivered to a
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4042
			 * garbaled address.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4043
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4044
			ASSERT(so->so_faddr_sa);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4045
			name = so->so_faddr_sa;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4046
			namelen = (t_uscalar_t)so->so_faddr_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4047
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4048
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4049
		if (!(so_state & SS_ISCONNECTED) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4050
		    (so_mode & SM_CONNREQUIRED)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4051
			/* Required but not connected */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4052
			mutex_exit(&so->so_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4053
			return (ENOTCONN);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4054
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4055
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4056
		 * Ignore the address on connection-oriented sockets.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4057
		 * Just like BSD this code does not generate an error for
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4058
		 * TCP (a CONNREQUIRED socket) when sending to an address
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4059
		 * passed in with sendto/sendmsg. Instead the data is
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4060
		 * delivered on the connection as if no address had been
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4061
		 * supplied.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4062
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4063
		if ((so_state & SS_ISCONNECTED) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4064
		    !(so_mode & SM_CONNREQUIRED)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4065
			mutex_exit(&so->so_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4066
			return (EISCONN);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4067
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4068
		if (!(so_state & SS_ISBOUND)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4069
			so_lock_single(so);	/* Set SOLOCKED */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4070
			error = sotpi_bind(so, NULL, 0,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4071
			    _SOBIND_UNSPEC|_SOBIND_LOCK_HELD);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4072
			so_unlock_single(so, SOLOCKED);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4073
			if (error) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4074
				mutex_exit(&so->so_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4075
				eprintsoline(so, error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4076
				return (error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4077
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4078
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4079
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4080
		 * Handle delayed datagram errors. These are only queued
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4081
		 * when the application sets SO_DGRAM_ERRIND.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4082
		 * Return the error if we are sending to the address
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4083
		 * that was returned in the last T_UDERROR_IND.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4084
		 * If sending to some other address discard the delayed
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4085
		 * error indication.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4086
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4087
		if (so->so_delayed_error) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4088
			struct T_uderror_ind	*tudi;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4089
			void			*addr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4090
			t_uscalar_t		addrlen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4091
			boolean_t		match = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4092
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4093
			ASSERT(so->so_eaddr_mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4094
			error = so->so_delayed_error;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4095
			so->so_delayed_error = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4096
			tudi = (struct T_uderror_ind *)so->so_eaddr_mp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4097
			addrlen = tudi->DEST_length;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4098
			addr = sogetoff(so->so_eaddr_mp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4099
					tudi->DEST_offset,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4100
					addrlen, 1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4101
			ASSERT(addr);	/* Checked by strsock_proto */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4102
			switch (so->so_family) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4103
			case AF_INET: {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4104
				/* Compare just IP address and port */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4105
				sin_t *sin1 = (sin_t *)name;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4106
				sin_t *sin2 = (sin_t *)addr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4107
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4108
				if (addrlen == sizeof (sin_t) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4109
				    namelen == addrlen &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4110
				    sin1->sin_port == sin2->sin_port &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4111
				    sin1->sin_addr.s_addr ==
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4112
				    sin2->sin_addr.s_addr)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4113
					match = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4114
				break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4115
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4116
			case AF_INET6: {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4117
				/* Compare just IP address and port. Not flow */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4118
				sin6_t *sin1 = (sin6_t *)name;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4119
				sin6_t *sin2 = (sin6_t *)addr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4120
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4121
				if (addrlen == sizeof (sin6_t) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4122
				    namelen == addrlen &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4123
				    sin1->sin6_port == sin2->sin6_port &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4124
				    IN6_ARE_ADDR_EQUAL(&sin1->sin6_addr,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4125
					&sin2->sin6_addr))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4126
					match = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4127
				break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4128
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4129
			case AF_UNIX:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4130
			default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4131
				if (namelen == addrlen &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4132
				    bcmp(name, addr, namelen) == 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4133
					match = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4134
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4135
			if (match) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4136
				freemsg(so->so_eaddr_mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4137
				so->so_eaddr_mp = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4138
				mutex_exit(&so->so_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4139
#ifdef DEBUG
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4140
				dprintso(so, 0,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4141
					("sockfs delayed error %d for %s\n",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4142
					error,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4143
					pr_addr(so->so_family, name, namelen)));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4144
#endif /* DEBUG */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4145
				return (error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4146
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4147
			freemsg(so->so_eaddr_mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4148
			so->so_eaddr_mp = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4149
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4150
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4151
	mutex_exit(&so->so_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4152
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4153
	flags = msg->msg_flags;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4154
	dontroute = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4155
	if ((flags & MSG_DONTROUTE) && !(so->so_options & SO_DONTROUTE)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4156
		uint32_t	val;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4157
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4158
		val = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4159
		error = sotpi_setsockopt(so, SOL_SOCKET, SO_DONTROUTE,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4160
					&val, (t_uscalar_t)sizeof (val));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4161
		if (error)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4162
			return (error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4163
		dontroute = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4164
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4165
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4166
	if ((flags & MSG_OOB) && !(so_mode & SM_EXDATA)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4167
		error = EOPNOTSUPP;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4168
		goto done;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4169
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4170
	if (msg->msg_controllen != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4171
		if (!(so_mode & SM_CONNREQUIRED)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4172
			error = sosend_dgramcmsg(so, name, namelen, uiop,
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4173
			    msg->msg_control, msg->msg_controllen, flags);
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4174
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4175
			if (flags & MSG_OOB) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4176
				/* Can't generate T_EXDATA_REQ with options */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4177
				error = EOPNOTSUPP;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4178
				goto done;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4179
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4180
			error = sosend_svccmsg(so, uiop,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4181
				!(flags & MSG_EOR),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4182
				msg->msg_control, msg->msg_controllen,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4183
				flags);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4184
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4185
		goto done;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4186
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4187
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4188
	if (!(so_mode & SM_CONNREQUIRED)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4189
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4190
		 * If there is no SO_DONTROUTE to turn off return immediately
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4191
		 * from send_dgram. This can allow tail-call optimizations.
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4192
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4193
		if (!dontroute) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4194
			return (sosend_dgram(so, name, namelen, uiop, flags));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4195
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4196
		error = sosend_dgram(so, name, namelen, uiop, flags);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4197
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4198
		t_scalar_t prim;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4199
		int sflag;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4200
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4201
		/* Ignore msg_name in the connected state */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4202
		if (flags & MSG_OOB) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4203
			prim = T_EXDATA_REQ;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4204
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4205
			 * Send down T_EXDATA_REQ even if there is flow
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4206
			 * control for data.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4207
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4208
			sflag = MSG_IGNFLOW;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4209
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4210
			if (so_mode & SM_BYTESTREAM) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4211
				/* Byte stream transport - use write */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4212
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4213
				dprintso(so, 1, ("sotpi_sendmsg: write\n"));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4214
				/*
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4215
				 * If there is no SO_DONTROUTE to turn off,
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4216
				 * SS_DIRECT is on, and there is no flow
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4217
				 * control, we can take the fast path.
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4218
				 */
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4219
				if (!dontroute &&
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4220
				    (so_state & SS_DIRECT) &&
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4221
				    canputnext(SOTOV(so)->v_stream->sd_wrq)) {
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4222
					return (sostream_direct(so, uiop,
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4223
					    NULL, CRED()));
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4224
				}
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4225
				error = strwrite(SOTOV(so), uiop, CRED());
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4226
				goto done;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4227
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4228
			prim = T_DATA_REQ;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4229
			sflag = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4230
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4231
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4232
		 * If there is no SO_DONTROUTE to turn off return immediately
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4233
		 * from sosend_svc. This can allow tail-call optimizations.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4234
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4235
		if (!dontroute)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4236
			return (sosend_svc(so, uiop, prim,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4237
				!(flags & MSG_EOR), sflag));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4238
		error = sosend_svc(so, uiop, prim,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4239
				!(flags & MSG_EOR), sflag);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4240
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4241
	ASSERT(dontroute);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4242
done:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4243
	if (dontroute) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4244
		uint32_t	val;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4245
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4246
		val = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4247
		(void) sotpi_setsockopt(so, SOL_SOCKET, SO_DONTROUTE,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4248
				&val, (t_uscalar_t)sizeof (val));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4249
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4250
	return (error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4251
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4252
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4253
/*
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4254
 * Sending data on a datagram socket.
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4255
 * Assumes caller has verified that SS_ISBOUND etc. are set.
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4256
 */
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4257
/* ARGSUSED */
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4258
static int
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4259
sodgram_direct(struct sonode *so, struct sockaddr *name,
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4260
    socklen_t namelen, struct uio *uiop, int flags)
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4261
{
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4262
	struct T_unitdata_req	tudr;
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4263
	mblk_t			*mp;
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4264
	int			error = 0;
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4265
	void			*addr;
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4266
	socklen_t		addrlen;
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4267
	ssize_t			len;
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4268
	struct stdata		*stp = SOTOV(so)->v_stream;
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4269
	int			so_state;
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4270
	queue_t			*udp_wq;
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4271
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4272
	ASSERT(name != NULL && namelen != 0);
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4273
	ASSERT(!(so->so_mode & SM_CONNREQUIRED));
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4274
	ASSERT(!(so->so_mode & SM_EXDATA));
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4275
	ASSERT(so->so_family == AF_INET || so->so_family == AF_INET6);
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4276
	ASSERT(SOTOV(so)->v_type == VSOCK);
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4277
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4278
	/* Caller checked for proper length */
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4279
	len = uiop->uio_resid;
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4280
	ASSERT(len <= so->so_tidu_size);
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4281
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4282
	/* Length and family checks have been done by caller */
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4283
	ASSERT(name->sa_family == so->so_family);
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4284
	ASSERT(so->so_family == AF_INET ||
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4285
	    (namelen == (socklen_t)sizeof (struct sockaddr_in6)));
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4286
	ASSERT(so->so_family == AF_INET6 ||
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4287
	    (namelen == (socklen_t)sizeof (struct sockaddr_in)));
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4288
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4289
	addr = name;
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4290
	addrlen = namelen;
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4291
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4292
	if (stp->sd_sidp != NULL &&
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4293
	    (error = straccess(stp, JCWRITE)) != 0)
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4294
		goto done;
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4295
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4296
	so_state = so->so_state;
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4297
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4298
	/*
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4299
	 * For UDP we don't break up the copyin into smaller pieces
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4300
	 * as in the TCP case.  That means if ENOMEM is returned by
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4301
	 * mcopyinuio() then the uio vector has not been modified at
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4302
	 * all and we fallback to either strwrite() or kstrputmsg()
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4303
	 * below.  Note also that we never generate priority messages
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4304
	 * from here.
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4305
	 */
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4306
	udp_wq = stp->sd_wrq->q_next;
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4307
	if (canput(udp_wq) &&
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4308
	    (mp = mcopyinuio(stp, uiop, -1, -1, &error)) != NULL) {
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4309
		ASSERT(DB_TYPE(mp) == M_DATA);
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4310
		ASSERT(uiop->uio_resid == 0);
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4311
#ifdef C2_AUDIT
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4312
		if (audit_active)
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4313
			audit_sock(T_UNITDATA_REQ, strvp2wq(SOTOV(so)), mp, 0);
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4314
#endif /* C2_AUDIT */
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4315
		udp_wput_data(udp_wq, mp, addr, addrlen);
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4316
		return (0);
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4317
	}
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4318
	if (error != 0 && error != ENOMEM)
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4319
		return (error);
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4320
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4321
	/*
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4322
	 * For connected, let strwrite() handle the blocking case.
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4323
	 * Otherwise we fall thru and use kstrputmsg().
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4324
	 */
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4325
	if (so_state & SS_ISCONNECTED)
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4326
		return (strwrite(SOTOV(so), uiop, CRED()));
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4327
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4328
	tudr.PRIM_type = T_UNITDATA_REQ;
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4329
	tudr.DEST_length = addrlen;
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4330
	tudr.DEST_offset = (t_scalar_t)sizeof (tudr);
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4331
	tudr.OPT_length = 0;
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4332
	tudr.OPT_offset = 0;
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4333
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4334
	mp = soallocproto2(&tudr, sizeof (tudr), addr, addrlen, 0, _ALLOC_INTR);
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4335
	if (mp == NULL) {
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4336
		/*
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4337
		 * Caught a signal waiting for memory.
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4338
		 * Let send* return EINTR.
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4339
		 */
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4340
		error = EINTR;
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4341
		goto done;
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4342
	}
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4343
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4344
#ifdef C2_AUDIT
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4345
	if (audit_active)
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4346
		audit_sock(T_UNITDATA_REQ, strvp2wq(SOTOV(so)), mp, 0);
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4347
#endif /* C2_AUDIT */
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4348
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4349
	error = kstrputmsg(SOTOV(so), mp, uiop, len, 0, MSG_BAND, 0);
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4350
done:
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4351
#ifdef SOCK_DEBUG
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4352
	if (error != 0) {
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4353
		eprintsoline(so, error);
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4354
	}
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4355
#endif /* SOCK_DEBUG */
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4356
	return (error);
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4357
}
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4358
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4359
int
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4360
sostream_direct(struct sonode *so, struct uio *uiop, mblk_t *mp, cred_t *cr)
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4361
{
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4362
	struct stdata *stp = SOTOV(so)->v_stream;
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4363
	ssize_t iosize, rmax, maxblk;
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4364
	queue_t *tcp_wq = stp->sd_wrq->q_next;
898
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 741
diff changeset
  4365
	mblk_t *newmp;
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4366
	int error = 0, wflag = 0;
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4367
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4368
	ASSERT(so->so_mode & SM_BYTESTREAM);
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4369
	ASSERT(SOTOV(so)->v_type == VSOCK);
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4370
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4371
	if (stp->sd_sidp != NULL &&
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4372
	    (error = straccess(stp, JCWRITE)) != 0)
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4373
		return (error);
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4374
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4375
	if (uiop == NULL) {
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4376
		/*
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4377
		 * kstrwritemp() should have checked sd_flag and
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4378
		 * flow-control before coming here.  If we end up
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4379
		 * here it means that we can simply pass down the
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4380
		 * data to tcp.
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4381
		 */
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4382
		ASSERT(mp != NULL);
898
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 741
diff changeset
  4383
		if (stp->sd_wputdatafunc != NULL) {
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 741
diff changeset
  4384
			newmp = (stp->sd_wputdatafunc)(SOTOV(so), mp, NULL,
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 741
diff changeset
  4385
			    NULL, NULL, NULL);
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 741
diff changeset
  4386
			if (newmp == NULL) {
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 741
diff changeset
  4387
				/* The caller will free mp */
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 741
diff changeset
  4388
				return (ECOMM);
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 741
diff changeset
  4389
			}
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 741
diff changeset
  4390
			mp = newmp;
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 741
diff changeset
  4391
		}
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4392
		tcp_wput(tcp_wq, mp);
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4393
		return (0);
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4394
	}
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4395
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4396
	/* Fallback to strwrite() to do proper error handling */
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4397
	if (stp->sd_flag & (STWRERR|STRHUP|STPLEX|STRDELIM|OLDNDELAY))
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4398
		return (strwrite(SOTOV(so), uiop, cr));
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4399
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4400
	rmax = stp->sd_qn_maxpsz;
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4401
	ASSERT(rmax >= 0 || rmax == INFPSZ);
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4402
	if (rmax == 0 || uiop->uio_resid <= 0)
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4403
		return (0);
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4404
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4405
	if (rmax == INFPSZ)
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4406
		rmax = uiop->uio_resid;
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4407
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4408
	maxblk = stp->sd_maxblk;
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4409
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4410
	for (;;) {
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4411
		iosize = MIN(uiop->uio_resid, rmax);
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4412
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4413
		mp = mcopyinuio(stp, uiop, iosize, maxblk, &error);
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4414
		if (mp == NULL) {
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4415
			/*
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4416
			 * Fallback to strwrite() for ENOMEM; if this
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4417
			 * is our first time in this routine and the uio
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4418
			 * vector has not been modified, we will end up
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4419
			 * calling strwrite() without any flag set.
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4420
			 */
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4421
			if (error == ENOMEM)
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4422
				goto slow_send;
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4423
			else
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4424
				return (error);
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4425
		}
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4426
		ASSERT(uiop->uio_resid >= 0);
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4427
		/*
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4428
		 * If mp is non-NULL and ENOMEM is set, it means that
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4429
		 * mcopyinuio() was able to break down some of the user
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4430
		 * data into one or more mblks.  Send the partial data
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4431
		 * to tcp and let the rest be handled in strwrite().
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4432
		 */
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4433
		ASSERT(error == 0 || error == ENOMEM);
898
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 741
diff changeset
  4434
		if (stp->sd_wputdatafunc != NULL) {
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 741
diff changeset
  4435
			newmp = (stp->sd_wputdatafunc)(SOTOV(so), mp, NULL,
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 741
diff changeset
  4436
			    NULL, NULL, NULL);
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 741
diff changeset
  4437
			if (newmp == NULL) {
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 741
diff changeset
  4438
				/* The caller will free mp */
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 741
diff changeset
  4439
				return (ECOMM);
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 741
diff changeset
  4440
			}
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 741
diff changeset
  4441
			mp = newmp;
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 741
diff changeset
  4442
		}
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4443
		tcp_wput(tcp_wq, mp);
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4444
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4445
		wflag |= NOINTR;
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4446
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4447
		if (uiop->uio_resid == 0) {	/* No more data; we're done */
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4448
			ASSERT(error == 0);
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4449
			break;
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4450
		} else if (error == ENOMEM || !canput(tcp_wq) || (stp->sd_flag &
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4451
		    (STWRERR|STRHUP|STPLEX|STRDELIM|OLDNDELAY))) {
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4452
slow_send:
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4453
			/*
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4454
			 * We were able to send down partial data using
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4455
			 * the direct call interface, but are now relying
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4456
			 * on strwrite() to handle the non-fastpath cases.
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4457
			 * If the socket is blocking we will sleep in
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4458
			 * strwaitq() until write is permitted, otherwise,
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4459
			 * we will need to return the amount of bytes
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4460
			 * written so far back to the app.  This is the
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4461
			 * reason why we pass NOINTR flag to strwrite()
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4462
			 * for non-blocking socket, because we don't want
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4463
			 * to return EAGAIN when portion of the user data
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4464
			 * has actually been sent down.
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4465
			 */
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4466
			return (strwrite_common(SOTOV(so), uiop, cr, wflag));
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4467
		}
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4468
	}
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4469
	return (0);
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4470
}
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4471
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 455
diff changeset
  4472
/*
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4473
 * Update so_faddr by asking the transport (unless AF_UNIX).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4474
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4475
int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4476
sotpi_getpeername(struct sonode *so)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4477
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4478
	struct strbuf	strbuf;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4479
	int		error = 0, res;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4480
	void		*addr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4481
	t_uscalar_t	addrlen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4482
	k_sigset_t	smask;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4483
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4484
	dprintso(so, 1, ("sotpi_getpeername(%p) %s\n",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4485
		so, pr_state(so->so_state, so->so_mode)));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4486
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4487
	mutex_enter(&so->so_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4488
	so_lock_single(so);	/* Set SOLOCKED */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4489
	if (!(so->so_state & SS_ISCONNECTED)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4490
		error = ENOTCONN;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4491
		goto done;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4492
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4493
	/* Added this check for X/Open */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4494
	if ((so->so_state & SS_CANTSENDMORE) && !xnet_skip_checks) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4495
		error = EINVAL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4496
		if (xnet_check_print) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4497
			printf("sockfs: X/Open getpeername check => EINVAL\n");
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4498
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4499
		goto done;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4500
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4501
#ifdef DEBUG
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4502
	dprintso(so, 1, ("sotpi_getpeername (local): %s\n",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4503
		pr_addr(so->so_family, so->so_faddr_sa,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4504
			(t_uscalar_t)so->so_faddr_len)));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4505
#endif /* DEBUG */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4506
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4507
	if (so->so_family == AF_UNIX || so->so_family == AF_NCA) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4508
		/* Transport has different name space - return local info */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4509
		error = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4510
		goto done;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4511
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4512
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4513
	ASSERT(so->so_faddr_sa);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4514
	/* Allocate local buffer to use with ioctl */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4515
	addrlen = (t_uscalar_t)so->so_faddr_maxlen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4516
	mutex_exit(&so->so_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4517
	addr = kmem_alloc(addrlen, KM_SLEEP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4518
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4519
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4520
	 * Issue TI_GETPEERNAME with signals masked.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4521
	 * Put the result in so_faddr_sa so that getpeername works after
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4522
	 * a shutdown(output).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4523
	 * If the ioctl fails (e.g. due to a ECONNRESET) the error is reposted
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4524
	 * back to the socket.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4525
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4526
	strbuf.buf = addr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4527
	strbuf.maxlen = addrlen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4528
	strbuf.len = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4529
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4530
	sigintr(&smask, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4531
	res = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4532
	ASSERT(CRED());
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4533
	error = strioctl(SOTOV(so), TI_GETPEERNAME, (intptr_t)&strbuf,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4534
			0, K_TO_K, CRED(), &res);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4535
	sigunintr(&smask);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4536
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4537
	mutex_enter(&so->so_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4538
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4539
	 * If there is an error record the error in so_error put don't fail
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4540
	 * the getpeername. Instead fallback on the recorded
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4541
	 * so->so_faddr_sa.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4542
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4543
	if (error) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4544
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4545
		 * Various stream head errors can be returned to the ioctl.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4546
		 * However, it is impossible to determine which ones of
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4547
		 * these are really socket level errors that were incorrectly
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4548
		 * consumed by the ioctl. Thus this code silently ignores the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4549
		 * error - to code explicitly does not reinstate the error
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4550
		 * using soseterror().
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4551
		 * Experiments have shows that at least this set of
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4552
		 * errors are reported and should not be reinstated on the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4553
		 * socket:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4554
		 *	EINVAL	E.g. if an I_LINK was in effect when
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4555
		 *		getpeername was called.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4556
		 *	EPIPE	The ioctl error semantics prefer the write
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4557
		 *		side error over the read side error.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4558
		 *	ENOTCONN The transport just got disconnected but
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4559
		 *		sockfs had not yet seen the T_DISCON_IND
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4560
		 *		when issuing the ioctl.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4561
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4562
		error = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4563
	} else if (res == 0 && strbuf.len > 0 &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4564
	    (so->so_state & SS_ISCONNECTED)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4565
		ASSERT(strbuf.len <= (int)so->so_faddr_maxlen);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4566
		so->so_faddr_len = (socklen_t)strbuf.len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4567
		bcopy(addr, so->so_faddr_sa, so->so_faddr_len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4568
		so->so_state |= SS_FADDR_VALID;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4569
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4570
	kmem_free(addr, addrlen);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4571
#ifdef DEBUG
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4572
	dprintso(so, 1, ("sotpi_getpeername (tp): %s\n",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4573
			pr_addr(so->so_family, so->so_faddr_sa,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4574
				(t_uscalar_t)so->so_faddr_len)));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4575
#endif /* DEBUG */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4576
done:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4577
	so_unlock_single(so, SOLOCKED);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4578
	mutex_exit(&so->so_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4579
	return (error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4580
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4581
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4582
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4583
 * Update so_laddr by asking the transport (unless AF_UNIX).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4584
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4585
int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4586
sotpi_getsockname(struct sonode *so)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4587
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4588
	struct strbuf	strbuf;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4589
	int		error = 0, res;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4590
	void		*addr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4591
	t_uscalar_t	addrlen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4592
	k_sigset_t	smask;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4593
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4594
	dprintso(so, 1, ("sotpi_getsockname(%p) %s\n",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4595
		so, pr_state(so->so_state, so->so_mode)));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4596
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4597
	mutex_enter(&so->so_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4598
	so_lock_single(so);	/* Set SOLOCKED */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4599
	if (!(so->so_state & SS_ISBOUND) && so->so_family != AF_UNIX) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4600
		/* Return an all zero address except for the family */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4601
		if (so->so_family == AF_INET)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4602
			so->so_laddr_len = (socklen_t)sizeof (sin_t);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4603
		else if (so->so_family == AF_INET6)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4604
			so->so_laddr_len = (socklen_t)sizeof (sin6_t);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4605
		ASSERT(so->so_laddr_len <= so->so_laddr_maxlen);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4606
		bzero(so->so_laddr_sa, so->so_laddr_len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4607
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4608
		 * Can not assume there is a sa_family for all
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4609
		 * protocol families.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4610
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4611
		if (so->so_family == AF_INET || so->so_family == AF_INET6)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4612
			so->so_laddr_sa->sa_family = so->so_family;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4613
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4614
#ifdef DEBUG
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4615
	dprintso(so, 1, ("sotpi_getsockname (local): %s\n",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4616
		pr_addr(so->so_family, so->so_laddr_sa,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4617
			(t_uscalar_t)so->so_laddr_len)));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4618
#endif /* DEBUG */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4619
	if (so->so_family == AF_UNIX) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4620
		/* Transport has different name space - return local info */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4621
		error = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4622
		goto done;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4623
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4624
	/* Allocate local buffer to use with ioctl */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4625
	addrlen = (t_uscalar_t)so->so_laddr_maxlen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4626
	mutex_exit(&so->so_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4627
	addr = kmem_alloc(addrlen, KM_SLEEP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4628
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4629
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4630
	 * Issue TI_GETMYNAME with signals masked.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4631
	 * Put the result in so_laddr_sa so that getsockname works after
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4632
	 * a shutdown(output).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4633
	 * If the ioctl fails (e.g. due to a ECONNRESET) the error is reposted
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4634
	 * back to the socket.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4635
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4636
	strbuf.buf = addr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4637
	strbuf.maxlen = addrlen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4638
	strbuf.len = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4639
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4640
	sigintr(&smask, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4641
	res = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4642
	ASSERT(CRED());
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4643
	error = strioctl(SOTOV(so), TI_GETMYNAME, (intptr_t)&strbuf,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4644
			0, K_TO_K, CRED(), &res);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4645
	sigunintr(&smask);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4646
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4647
	mutex_enter(&so->so_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4648
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4649
	 * If there is an error record the error in so_error put don't fail
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4650
	 * the getsockname. Instead fallback on the recorded
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4651
	 * so->so_laddr_sa.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4652
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4653
	if (error) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4654
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4655
		 * Various stream head errors can be returned to the ioctl.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4656
		 * However, it is impossible to determine which ones of
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4657
		 * these are really socket level errors that were incorrectly
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4658
		 * consumed by the ioctl. Thus this code silently ignores the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4659
		 * error - to code explicitly does not reinstate the error
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4660
		 * using soseterror().
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4661
		 * Experiments have shows that at least this set of
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4662
		 * errors are reported and should not be reinstated on the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4663
		 * socket:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4664
		 *	EINVAL	E.g. if an I_LINK was in effect when
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4665
		 *		getsockname was called.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4666
		 *	EPIPE	The ioctl error semantics prefer the write
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4667
		 *		side error over the read side error.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4668
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4669
		error = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4670
	} else if (res == 0 && strbuf.len > 0 &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4671
	    (so->so_state & SS_ISBOUND)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4672
		ASSERT(strbuf.len <= (int)so->so_laddr_maxlen);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4673
		so->so_laddr_len = (socklen_t)strbuf.len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4674
		bcopy(addr, so->so_laddr_sa, so->so_laddr_len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4675
		so->so_state |= SS_LADDR_VALID;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4676
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4677
	kmem_free(addr, addrlen);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4678
#ifdef DEBUG
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4679
	dprintso(so, 1, ("sotpi_getsockname (tp): %s\n",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4680
			pr_addr(so->so_family, so->so_laddr_sa,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4681
				(t_uscalar_t)so->so_laddr_len)));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4682
#endif /* DEBUG */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4683
done:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4684
	so_unlock_single(so, SOLOCKED);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4685
	mutex_exit(&so->so_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4686
	return (error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4687
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4688
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4689
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4690
 * Get socket options. For SOL_SOCKET options some options are handled
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4691
 * by the sockfs while others use the value recorded in the sonode as a
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4692
 * fallback should the T_SVR4_OPTMGMT_REQ fail.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4693
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4694
 * On the return most *optlenp bytes are copied to optval.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4695
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4696
int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4697
sotpi_getsockopt(struct sonode *so, int level, int option_name,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4698
		void *optval, socklen_t *optlenp, int flags)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4699
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4700
	struct T_optmgmt_req	optmgmt_req;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4701
	struct T_optmgmt_ack	*optmgmt_ack;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4702
	struct opthdr		oh;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4703
	struct opthdr		*opt_res;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4704
	mblk_t			*mp = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4705
	int			error = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4706
	void			*option = NULL;	/* Set if fallback value */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4707
	t_uscalar_t		maxlen = *optlenp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4708
	t_uscalar_t		len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4709
	uint32_t		value;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4710
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4711
	dprintso(so, 1, ("sotpi_getsockopt(%p, 0x%x, 0x%x, %p, %p) %s\n",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4712
			so, level, option_name, optval, optlenp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4713
			pr_state(so->so_state, so->so_mode)));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4714
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4715
	mutex_enter(&so->so_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4716
	so_lock_single(so);	/* Set SOLOCKED */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4717
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4718
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4719
	 * Check for SOL_SOCKET options.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4720
	 * Certain SOL_SOCKET options are returned directly whereas
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4721
	 * others only provide a default (fallback) value should
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4722
	 * the T_SVR4_OPTMGMT_REQ fail.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4723
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4724
	if (level == SOL_SOCKET) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4725
		/* Check parameters */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4726
		switch (option_name) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4727
		case SO_TYPE:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4728
		case SO_ERROR:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4729
		case SO_DEBUG:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4730
		case SO_ACCEPTCONN:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4731
		case SO_REUSEADDR:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4732
		case SO_KEEPALIVE:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4733
		case SO_DONTROUTE:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4734
		case SO_BROADCAST:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4735
		case SO_USELOOPBACK:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4736
		case SO_OOBINLINE:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4737
		case SO_SNDBUF:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4738
		case SO_RCVBUF:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4739
#ifdef notyet
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4740
		case SO_SNDLOWAT:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4741
		case SO_RCVLOWAT:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4742
		case SO_SNDTIMEO:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4743
		case SO_RCVTIMEO:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4744
#endif /* notyet */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4745
		case SO_DGRAM_ERRIND:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4746
			if (maxlen < (t_uscalar_t)sizeof (int32_t)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4747
				error = EINVAL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4748
				eprintsoline(so, error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4749
				goto done2;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4750
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4751
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4752
		case SO_LINGER:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4753
			if (maxlen < (t_uscalar_t)sizeof (struct linger)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4754
				error = EINVAL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4755
				eprintsoline(so, error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4756
				goto done2;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4757
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4758
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4759
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4760
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4761
		len = (t_uscalar_t)sizeof (uint32_t);	/* Default */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4762
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4763
		switch (option_name) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4764
		case SO_TYPE:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4765
			value = so->so_type;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4766
			option = &value;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4767
			goto copyout; /* No need to issue T_SVR4_OPTMGMT_REQ */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4768
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4769
		case SO_ERROR:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4770
			value = sogeterr(so);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4771
			option = &value;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4772
			goto copyout; /* No need to issue T_SVR4_OPTMGMT_REQ */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4773
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4774
		case SO_ACCEPTCONN:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4775
			if (so->so_state & SS_ACCEPTCONN)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4776
				value = SO_ACCEPTCONN;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4777
			else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4778
				value = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4779
#ifdef DEBUG
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4780
			if (value) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4781
				dprintso(so, 1,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4782
				    ("sotpi_getsockopt: 0x%x is set\n",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4783
				    option_name));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4784
			} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4785
				dprintso(so, 1,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4786
				    ("sotpi_getsockopt: 0x%x not set\n",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4787
				    option_name));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4788
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4789
#endif /* DEBUG */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4790
			option = &value;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4791
			goto copyout; /* No need to issue T_SVR4_OPTMGMT_REQ */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4792
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4793
		case SO_DEBUG:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4794
		case SO_REUSEADDR:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4795
		case SO_KEEPALIVE:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4796
		case SO_DONTROUTE:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4797
		case SO_BROADCAST:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4798
		case SO_USELOOPBACK:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4799
		case SO_OOBINLINE:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4800
		case SO_DGRAM_ERRIND:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4801
			value = (so->so_options & option_name);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4802
#ifdef DEBUG
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4803
			if (value) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4804
				dprintso(so, 1,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4805
				    ("sotpi_getsockopt: 0x%x is set\n",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4806
				    option_name));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4807
			} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4808
				dprintso(so, 1,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4809
				    ("sotpi_getsockopt: 0x%x not set\n",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4810
				    option_name));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4811
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4812
#endif /* DEBUG */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4813
			option = &value;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4814
			goto copyout; /* No need to issue T_SVR4_OPTMGMT_REQ */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4815
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4816
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4817
		 * The following options are only returned by sockfs when the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4818
		 * T_SVR4_OPTMGMT_REQ fails.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4819
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4820
		case SO_LINGER:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4821
			option = &so->so_linger;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4822
			len = (t_uscalar_t)sizeof (struct linger);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4823
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4824
		case SO_SNDBUF: {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4825
			ssize_t lvalue;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4826
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4827
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4828
			 * If the option has not been set then get a default
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4829
			 * value from the read queue. This value is
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4830
			 * returned if the transport fails
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4831
			 * the T_SVR4_OPTMGMT_REQ.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4832
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4833
			lvalue = so->so_sndbuf;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4834
			if (lvalue == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4835
				mutex_exit(&so->so_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4836
				(void) strqget(strvp2wq(SOTOV(so))->q_next,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4837
						QHIWAT, 0, &lvalue);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4838
				mutex_enter(&so->so_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4839
				dprintso(so, 1,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4840
				    ("got SO_SNDBUF %ld from q\n", lvalue));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4841
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4842
			value = (int)lvalue;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4843
			option = &value;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4844
			len = (t_uscalar_t)sizeof (so->so_sndbuf);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4845
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4846
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4847
		case SO_RCVBUF: {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4848
			ssize_t lvalue;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4849
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4850
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4851
			 * If the option has not been set then get a default
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4852
			 * value from the read queue. This value is
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4853
			 * returned if the transport fails
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4854
			 * the T_SVR4_OPTMGMT_REQ.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4855
			 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4856
			 * XXX If SO_RCVBUF has been set and this is an
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4857
			 * XPG 4.2 application then do not ask the transport
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4858
			 * since the transport might adjust the value and not
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4859
			 * return exactly what was set by the application.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4860
			 * For non-XPG 4.2 application we return the value
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4861
			 * that the transport is actually using.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4862
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4863
			lvalue = so->so_rcvbuf;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4864
			if (lvalue == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4865
				mutex_exit(&so->so_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4866
				(void) strqget(RD(strvp2wq(SOTOV(so))),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4867
						QHIWAT, 0, &lvalue);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4868
				mutex_enter(&so->so_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4869
				dprintso(so, 1,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4870
				    ("got SO_RCVBUF %ld from q\n", lvalue));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4871
			} else if (flags & _SOGETSOCKOPT_XPG4_2) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4872
				value = (int)lvalue;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4873
				option = &value;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4874
				goto copyout;	/* skip asking transport */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4875
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4876
			value = (int)lvalue;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4877
			option = &value;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4878
			len = (t_uscalar_t)sizeof (so->so_rcvbuf);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4879
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4880
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4881
#ifdef notyet
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4882
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4883
		 * We do not implement the semantics of these options
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4884
		 * thus we shouldn't implement the options either.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4885
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4886
		case SO_SNDLOWAT:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4887
			value = so->so_sndlowat;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4888
			option = &value;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4889
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4890
		case SO_RCVLOWAT:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4891
			value = so->so_rcvlowat;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4892
			option = &value;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4893
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4894
		case SO_SNDTIMEO:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4895
			value = so->so_sndtimeo;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4896
			option = &value;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4897
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4898
		case SO_RCVTIMEO:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4899
			value = so->so_rcvtimeo;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4900
			option = &value;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4901
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4902
#endif /* notyet */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4903
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4904
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4905
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4906
	if (so->so_family == AF_NCA) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4907
		goto done2;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4908
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4909
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4910
	mutex_exit(&so->so_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4911
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4912
	/* Send request */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4913
	optmgmt_req.PRIM_type = T_SVR4_OPTMGMT_REQ;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4914
	optmgmt_req.MGMT_flags = T_CHECK;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4915
	optmgmt_req.OPT_length = (t_scalar_t)(sizeof (oh) + maxlen);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4916
	optmgmt_req.OPT_offset = (t_scalar_t)sizeof (optmgmt_req);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4917
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4918
	oh.level = level;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4919
	oh.name = option_name;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4920
	oh.len = maxlen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4921
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4922
	mp = soallocproto3(&optmgmt_req, sizeof (optmgmt_req),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4923
	    &oh, sizeof (oh), NULL, maxlen, 0, _ALLOC_SLEEP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4924
	/* Let option management work in the presence of data flow control */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4925
	error = kstrputmsg(SOTOV(so), mp, NULL, 0, 0,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4926
			MSG_BAND|MSG_HOLDSIG|MSG_IGNERROR|MSG_IGNFLOW, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4927
	mp = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4928
	mutex_enter(&so->so_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4929
	if (error) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4930
		eprintsoline(so, error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4931
		goto done2;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4932
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4933
	error = sowaitprim(so, T_SVR4_OPTMGMT_REQ, T_OPTMGMT_ACK,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4934
	    (t_uscalar_t)(sizeof (*optmgmt_ack) + sizeof (*opt_res)), &mp, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4935
	if (error) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4936
		if (option != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4937
			/* We have a fallback value */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4938
			error = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4939
			goto copyout;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4940
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4941
		eprintsoline(so, error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4942
		goto done2;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4943
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4944
	ASSERT(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4945
	optmgmt_ack = (struct T_optmgmt_ack *)mp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4946
	opt_res = (struct opthdr *)sogetoff(mp, optmgmt_ack->OPT_offset,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4947
			optmgmt_ack->OPT_length, __TPI_ALIGN_SIZE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4948
	if (opt_res == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4949
		if (option != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4950
			/* We have a fallback value */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4951
			error = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4952
			goto copyout;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4953
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4954
		error = EPROTO;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4955
		eprintsoline(so, error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4956
		goto done;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4957
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4958
	option = &opt_res[1];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4959
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4960
	/* check to ensure that the option is within bounds */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4961
	if (((uintptr_t)option + opt_res->len < (uintptr_t)option) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4962
		(uintptr_t)option + opt_res->len > (uintptr_t)mp->b_wptr) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4963
		if (option != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4964
			/* We have a fallback value */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4965
			error = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4966
			goto copyout;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4967
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4968
		error = EPROTO;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4969
		eprintsoline(so, error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4970
		goto done;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4971
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4972
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4973
	len = opt_res->len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4974
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4975
copyout: {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4976
		t_uscalar_t size = MIN(len, maxlen);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4977
		bcopy(option, optval, size);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4978
		bcopy(&size, optlenp, sizeof (size));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4979
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4980
done:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4981
	freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4982
done2:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4983
	so_unlock_single(so, SOLOCKED);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4984
	mutex_exit(&so->so_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4985
	return (error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4986
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4987
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4988
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4989
 * Set socket options. All options are passed down in a T_SVR4_OPTMGMT_REQ.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4990
 * SOL_SOCKET options are also recorded in the sonode. A setsockopt for
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4991
 * SOL_SOCKET options will not fail just because the T_SVR4_OPTMGMT_REQ fails -
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4992
 * setsockopt has to work even if the transport does not support the option.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4993
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4994
int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4995
sotpi_setsockopt(struct sonode *so, int level, int option_name,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4996
	const void *optval, t_uscalar_t optlen)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4997
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4998
	struct T_optmgmt_req	optmgmt_req;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4999
	struct opthdr		oh;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5000
	mblk_t			*mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5001
	int			error = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5002
	boolean_t		handled = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5003
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5004
	dprintso(so, 1, ("sotpi_setsockopt(%p, 0x%x, 0x%x, %p, %d) %s\n",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5005
			so, level, option_name, optval, optlen,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5006
			pr_state(so->so_state, so->so_mode)));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5007
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5008
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5009
	/* X/Open requires this check */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5010
	if ((so->so_state & SS_CANTSENDMORE) && !xnet_skip_checks) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5011
		if (xnet_check_print)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5012
			printf("sockfs: X/Open setsockopt check => EINVAL\n");
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5013
		return (EINVAL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5014
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5015
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5016
	/* Caller allocates aligned optval, or passes null */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5017
	ASSERT(((uintptr_t)optval & (sizeof (t_scalar_t) - 1)) == 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5018
	/* If optval is null optlen is 0, and vice-versa */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5019
	ASSERT(optval != NULL || optlen == 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5020
	ASSERT(optlen != 0 || optval == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5021
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5022
	mutex_enter(&so->so_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5023
	so_lock_single(so);	/* Set SOLOCKED */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5024
	mutex_exit(&so->so_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5025
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5026
	if (so->so_family == AF_NCA) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5027
		/* Ignore any flow control problems with the transport. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5028
		mutex_enter(&so->so_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5029
		goto done;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5030
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5031
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5032
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5033
	 * For SOCKET or TCP level options, try to set it here itself
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5034
	 * provided socket has not been popped and we know the tcp
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5035
	 * structure (stored in so_priv).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5036
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5037
	if ((level == SOL_SOCKET || level == IPPROTO_TCP) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5038
	    (so->so_family == AF_INET || so->so_family == AF_INET6) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5039
	    (so->so_version == SOV_SOCKSTREAM) && (so->so_priv != NULL)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5040
		tcp_t		*tcp = so->so_priv;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5041
		boolean_t	onoff;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5042
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5043
#define	intvalue	(*(int32_t *)optval)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5044
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5045
		switch (level) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5046
		case SOL_SOCKET:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5047
			switch (option_name) {		/* Check length param */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5048
			case SO_DEBUG:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5049
			case SO_REUSEADDR:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5050
			case SO_DONTROUTE:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5051
			case SO_BROADCAST:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5052
			case SO_USELOOPBACK:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5053
			case SO_OOBINLINE:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5054
			case SO_DGRAM_ERRIND:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5055
				if (optlen != (t_uscalar_t)sizeof (int32_t)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5056
					error = EINVAL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5057
					eprintsoline(so, error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5058
					mutex_enter(&so->so_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5059
					goto done2;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5060
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5061
				ASSERT(optval);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5062
				onoff = intvalue != 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5063
				handled = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5064
				break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5065
			case SO_LINGER:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5066
				if (optlen !=
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5067
				    (t_uscalar_t)sizeof (struct linger)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5068
					error = EINVAL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5069
					eprintsoline(so, error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5070
					mutex_enter(&so->so_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5071
					goto done2;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5072
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5073
				ASSERT(optval);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5074
				handled = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5075
				break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5076
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5077
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5078
			switch (option_name) {			/* Do actions */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5079
			case SO_LINGER: {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5080
				struct linger *lgr = (struct linger *)optval;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5081
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5082
				if (lgr->l_onoff) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5083
					tcp->tcp_linger = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5084
					tcp->tcp_lingertime = lgr->l_linger;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5085
					so->so_linger.l_onoff = SO_LINGER;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5086
					so->so_options |= SO_LINGER;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5087
				} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5088
					tcp->tcp_linger = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5089
					tcp->tcp_lingertime = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5090
					so->so_linger.l_onoff = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5091
					so->so_options &= ~SO_LINGER;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5092
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5093
				so->so_linger.l_linger = lgr->l_linger;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5094
				handled = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5095
				break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5096
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5097
			case SO_DEBUG:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5098
				tcp->tcp_debug = onoff;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5099
#ifdef SOCK_TEST
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5100
				if (intvalue & 2)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5101
					sock_test_timelimit = 10 * hz;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5102
				else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5103
					sock_test_timelimit = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5104
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5105
				if (intvalue & 4)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5106
					do_useracc = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5107
				else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5108
					do_useracc = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5109
#endif /* SOCK_TEST */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5110
				break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5111
			case SO_DONTROUTE:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5112
				/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5113
				 * SO_DONTROUTE, SO_USELOOPBACK and
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5114
				 * SO_BROADCAST are only of interest to IP.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5115
				 * We track them here only so
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5116
				 * that we can report their current value.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5117
				 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5118
				tcp->tcp_dontroute = onoff;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5119
				if (onoff)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5120
					so->so_options |= option_name;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5121
				else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5122
					so->so_options &= ~option_name;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5123
				break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5124
			case SO_USELOOPBACK:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5125
				tcp->tcp_useloopback = onoff;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5126
				if (onoff)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5127
					so->so_options |= option_name;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5128
				else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5129
					so->so_options &= ~option_name;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5130
				break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5131
			case SO_BROADCAST:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5132
				tcp->tcp_broadcast = onoff;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5133
				if (onoff)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5134
					so->so_options |= option_name;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5135
				else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5136
					so->so_options &= ~option_name;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5137
				break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5138
			case SO_REUSEADDR:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5139
				tcp->tcp_reuseaddr = onoff;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5140
				if (onoff)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5141
					so->so_options |= option_name;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5142
				else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5143
					so->so_options &= ~option_name;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5144
				break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5145
			case SO_OOBINLINE:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5146
				tcp->tcp_oobinline = onoff;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5147
				if (onoff)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5148
					so->so_options |= option_name;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5149
				else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5150
					so->so_options &= ~option_name;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5151
				break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5152
			case SO_DGRAM_ERRIND:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5153
				tcp->tcp_dgram_errind = onoff;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5154
				if (onoff)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5155
					so->so_options |= option_name;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5156
				else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5157
					so->so_options &= ~option_name;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5158
				break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5159
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5160
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5161
		case IPPROTO_TCP:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5162
			switch (option_name) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5163
			case TCP_NODELAY:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5164
				if (optlen != (t_uscalar_t)sizeof (int32_t)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5165
					error = EINVAL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5166
					eprintsoline(so, error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5167
					mutex_enter(&so->so_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5168
					goto done2;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5169
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5170
				ASSERT(optval);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5171
				tcp->tcp_naglim = intvalue ? 1 : tcp->tcp_mss;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5172
				handled = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5173
				break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5174
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5175
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5176
		default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5177
			handled = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5178
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5179
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5180
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5181
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5182
	if (handled) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5183
		mutex_enter(&so->so_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5184
		goto done2;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5185
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5186
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5187
	optmgmt_req.PRIM_type = T_SVR4_OPTMGMT_REQ;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5188
	optmgmt_req.MGMT_flags = T_NEGOTIATE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5189
	optmgmt_req.OPT_length = (t_scalar_t)sizeof (oh) + optlen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5190
	optmgmt_req.OPT_offset = (t_scalar_t)sizeof (optmgmt_req);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5191
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5192
	oh.level = level;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5193
	oh.name = option_name;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5194
	oh.len = optlen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5195
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5196
	mp = soallocproto3(&optmgmt_req, sizeof (optmgmt_req),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5197
	    &oh, sizeof (oh), optval, optlen, 0, _ALLOC_SLEEP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5198
	/* Let option management work in the presence of data flow control */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5199
	error = kstrputmsg(SOTOV(so), mp, NULL, 0, 0,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5200
			MSG_BAND|MSG_HOLDSIG|MSG_IGNERROR|MSG_IGNFLOW, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5201
	mp = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5202
	mutex_enter(&so->so_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5203
	if (error) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5204
		eprintsoline(so, error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5205
		goto done;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5206
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5207
	error = sowaitprim(so, T_SVR4_OPTMGMT_REQ, T_OPTMGMT_ACK,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5208
	    (t_uscalar_t)sizeof (struct T_optmgmt_ack), &mp, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5209
	if (error) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5210
		eprintsoline(so, error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5211
		goto done;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5212
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5213
	ASSERT(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5214
	/* No need to verify T_optmgmt_ack */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5215
	freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5216
done:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5217
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5218
	 * Check for SOL_SOCKET options and record their values.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5219
	 * If we know about a SOL_SOCKET parameter and the transport
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5220
	 * failed it with TBADOPT or TOUTSTATE (i.e. ENOPROTOOPT or
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5221
	 * EPROTO) we let the setsockopt succeed.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5222
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5223
	if (level == SOL_SOCKET) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5224
		/* Check parameters */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5225
		switch (option_name) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5226
		case SO_DEBUG:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5227
		case SO_REUSEADDR:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5228
		case SO_KEEPALIVE:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5229
		case SO_DONTROUTE:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5230
		case SO_BROADCAST:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5231
		case SO_USELOOPBACK:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5232
		case SO_OOBINLINE:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5233
		case SO_SNDBUF:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5234
		case SO_RCVBUF:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5235
#ifdef notyet
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5236
		case SO_SNDLOWAT:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5237
		case SO_RCVLOWAT:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5238
		case SO_SNDTIMEO:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5239
		case SO_RCVTIMEO:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5240
#endif /* notyet */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5241
		case SO_DGRAM_ERRIND:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5242
			if (optlen != (t_uscalar_t)sizeof (int32_t)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5243
				error = EINVAL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5244
				eprintsoline(so, error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5245
				goto done2;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5246
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5247
			ASSERT(optval);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5248
			handled = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5249
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5250
		case SO_LINGER:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5251
			if (optlen != (t_uscalar_t)sizeof (struct linger)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5252
				error = EINVAL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5253
				eprintsoline(so, error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5254
				goto done2;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5255
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5256
			ASSERT(optval);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5257
			handled = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5258
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5259
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5260
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5261
#define	intvalue	(*(int32_t *)optval)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5262
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5263
		switch (option_name) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5264
		case SO_TYPE:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5265
		case SO_ERROR:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5266
		case SO_ACCEPTCONN:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5267
			/* Can't be set */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5268
			error = ENOPROTOOPT;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5269
			goto done2;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5270
		case SO_LINGER: {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5271
			struct linger *l = (struct linger *)optval;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5272
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5273
			so->so_linger.l_linger = l->l_linger;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5274
			if (l->l_onoff) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5275
				so->so_linger.l_onoff = SO_LINGER;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5276
				so->so_options |= SO_LINGER;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5277
			} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5278
				so->so_linger.l_onoff = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5279
				so->so_options &= ~SO_LINGER;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5280
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5281
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5282
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5283
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5284
		case SO_DEBUG:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5285
#ifdef SOCK_TEST
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5286
			if (intvalue & 2)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5287
				sock_test_timelimit = 10 * hz;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5288
			else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5289
				sock_test_timelimit = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5290
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5291
			if (intvalue & 4)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5292
				do_useracc = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5293
			else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5294
				do_useracc = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5295
#endif /* SOCK_TEST */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5296
			/* FALLTHRU */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5297
		case SO_REUSEADDR:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5298
		case SO_KEEPALIVE:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5299
		case SO_DONTROUTE:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5300
		case SO_BROADCAST:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5301
		case SO_USELOOPBACK:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5302
		case SO_OOBINLINE:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5303
		case SO_DGRAM_ERRIND:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5304
			if (intvalue != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5305
				dprintso(so, 1,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5306
					("sotpi_setsockopt: setting 0x%x\n",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5307
					option_name));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5308
				so->so_options |= option_name;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5309
			} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5310
				dprintso(so, 1,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5311
					("sotpi_setsockopt: clearing 0x%x\n",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5312
					option_name));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5313
				so->so_options &= ~option_name;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5314
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5315
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5316
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5317
		 * The following options are only returned by us when the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5318
		 * T_SVR4_OPTMGMT_REQ fails.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5319
		 * XXX XPG 4.2 applications retrieve SO_RCVBUF from sockfs
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5320
		 * since the transport might adjust the value and not
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5321
		 * return exactly what was set by the application.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5322
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5323
		case SO_SNDBUF:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5324
			so->so_sndbuf = intvalue;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5325
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5326
		case SO_RCVBUF:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5327
			so->so_rcvbuf = intvalue;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5328
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5329
#ifdef notyet
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5330
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5331
		 * We do not implement the semantics of these options
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5332
		 * thus we shouldn't implement the options either.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5333
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5334
		case SO_SNDLOWAT:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5335
			so->so_sndlowat = intvalue;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5336
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5337
		case SO_RCVLOWAT:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5338
			so->so_rcvlowat = intvalue;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5339
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5340
		case SO_SNDTIMEO:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5341
			so->so_sndtimeo = intvalue;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5342
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5343
		case SO_RCVTIMEO:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5344
			so->so_rcvtimeo = intvalue;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5345
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5346
#endif /* notyet */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5347
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5348
#undef	intvalue
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5349
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5350
		if (error) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5351
			if ((error == ENOPROTOOPT || error == EPROTO ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5352
			    error == EINVAL) && handled) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5353
				dprintso(so, 1,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5354
				    ("setsockopt: ignoring error %d for 0x%x\n",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5355
				    error, option_name));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5356
				error = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5357
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5358
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5359
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5360
done2:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5361
ret:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5362
	so_unlock_single(so, SOLOCKED);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5363
	mutex_exit(&so->so_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5364
	return (error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5365
}