summaryrefslogtreecommitdiff
path: root/usr/src/uts/common/fs/sockfs/socktpi.h
blob: 15d128afb5631654d7e79b4ac5e34b4bb33c4d30 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License (the "License").
 * You may not use this file except in compliance with the License.
 *
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 * or http://www.opensolaris.org/os/licensing.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information: Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 */

/*
 * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
 * Copyright 2022 Garrett D'Amore
 */

#ifndef _SOCKFS_SOCKTPI_H
#define	_SOCKFS_SOCKTPI_H

#ifdef	__cplusplus
extern "C" {
#endif

/*
 * Internal representation used for addresses.
 */
struct soaddr {
	struct sockaddr	*soa_sa;	/* Actual address */
	t_uscalar_t	soa_len;	/* Length in bytes for kmem_free */
	t_uscalar_t	soa_maxlen;	/* Allocated length */
};
/* Maximum size address for transports that have ADDR_size == 1 */
#define	SOA_DEFSIZE	128

struct sonode;

/*
 * TPI Sockets
 * ======================
 *
 * A TPI socket can be created by the TPI socket module, or as a
 * result of fallback. In either case, the TPI related information is
 * stored in a sotpi_info_t. Sockets that are TPI based from the
 * beginning will use a sotpi_sonode_t, but fallback case the
 * sotpi_info_t will be allocated when needed. However, the so_priv
 * field in the sonode will always point to the sotpi_info_t, and the
 * structure should only be accessed via so_priv. Use SOTOTPI().
 *
 * A TPI socket always corresponds to a VCHR stream representing the
 * transport provider (e.g. /dev/tcp). This information is retrieved
 * from the kernel socket configuration table and accessible via
 * so_sockparams->sp_sdev_info.  sockfs uses this to perform
 * VOP_ACCESS checks before allowing an open of the transport
 * provider.
 *
 * AF_UNIX Sockets
 * -------------------------
 *
 * When an AF_UNIX socket is bound to a pathname the sockfs creates a
 * VSOCK vnode in the underlying file system. However, the vnodeops
 * etc in this VNODE remain those of the underlying file system.
 * Sockfs uses the v_stream pointer in the underlying file system
 * VSOCK node to find the sonode bound to the pathname. The bound
 * pathname vnode is accessed through sti_ux_vp.
 *
 * Out of Band Data Handling
 * -------------------------
 *
 * The counts (sti_oobcnt and sti_oobsigcnt) track the number of
 * urgent indicates that are (logically) queued on the stream head
 * read queue. The urgent data is queued on the stream head
 * as follows.
 *
 * In the normal case the SIGURG is not generated until
 * the T_EXDATA_IND arrives at the stream head. However, transports
 * that have an early indication that urgent data is pending
 * (e.g. TCP receiving a "new" urgent pointer value) can send up
 * an M_PCPROTO/SIGURG message to generate the signal early.
 *
 * The mark is indicated by either:
 *  - a T_EXDATA_IND (with no M_DATA b_cont) with MSGMARK set.
 *    When this message is consumed by sorecvmsg the socket layer
 *    sets SS_RCVATMARK until data has been consumed past the mark.
 *  - a message with MSGMARKNEXT set (indicating that the
 *    first byte of the next message constitutes the mark). When
 *    the last byte of the MSGMARKNEXT message is consumed in
 *    the stream head the stream head sets STRATMARK. This flag
 *    is cleared when at least one byte is read. (Note that
 *    the MSGMARKNEXT messages can be of zero length when there
 *    is no previous data to which the marknext can be attached.)
 *
 * While the T_EXDATA_IND method is the common case which is used
 * with all TPI transports, the MSGMARKNEXT method is needed to
 * indicate the mark when e.g. the TCP urgent byte has not been
 * received yet but the TCP urgent pointer has made TCP generate
 * the M_PCSIG/SIGURG.
 *
 * The signal (the M_PCSIG carrying the SIGURG) and the mark
 * indication can not be delivered as a single message, since
 * the signal should be delivered as high priority and any mark
 * indication must flow with the data. This implies that immediately
 * when the SIGURG has been delivered if the stream head queue is
 * empty it is impossible to determine if this will be the position
 * of the mark. This race condition is resolved by using MSGNOTMARKNEXT
 * messages and the STRNOTATMARK flag in the stream head. The
 * SIOCATMARK code calls the stream head to wait for either a
 * non-empty queue or one of the STR*ATMARK flags being set.
 * This implies that any transport that is sending M_PCSIG(SIGURG)
 * should send the appropriate MSGNOTMARKNEXT message (which can be
 * zero length) after sending an M_PCSIG to prevent SIOCATMARK
 * from sleeping unnecessarily.
 */

#define	SOTPI_INFO_MAGIC	0x12345678

/*
 * Information used by TPI/STREAMS sockets
 */
typedef struct sotpi_info {
	/*
	 * These fields are initialized once.
	 */
	uint32_t	sti_magic;	/* always set to SOTPI_INFO_MAGIC */
	dev_t		sti_dev;	/* device the sonode represents */

	struct sockparams *sti_orig_sp;	/* in case of fallback; the orig sp */

	kmutex_t	sti_plumb_lock;	/* serializes plumbs, and the related */
					/* so_pushcnt */
	short		sti_pushcnt;	/* Number of modules above "sockmod" */

	kcondvar_t	sti_ack_cv;	/* wait for TPI acks */

	uint8_t
		sti_laddr_valid : 1,	/* sti_laddr valid for user */
		sti_faddr_valid : 1,	/* sti_faddr valid for user */
		sti_faddr_noxlate : 1,	/* No xlation of faddr for AF_UNIX */

		sti_direct : 1,		/* transport is directly below */

		sti_pad_to_bit7 : 4;

	mblk_t	*sti_ack_mp;		/* TPI ack received from below */
	mblk_t	*sti_unbind_mp;		/* Preallocated T_UNBIND_REQ message */

	time_t  sti_atime;		/* time of last access */
	time_t  sti_mtime;		/* time of last modification */
	time_t  sti_ctime;		/* time of last attributes change */

	ushort_t sti_delayed_error;	/* From T_uderror_ind */
	mblk_t	*sti_eaddr_mp;		/* for so_delayed_error */
					/* put here for delayed processing  */

	mblk_t	*sti_conn_ind_head;	/* b_next list of T_CONN_IND */
	mblk_t	*sti_conn_ind_tail;

	uint_t	sti_oobsigcnt;		/* Number of SIGURG generated */
	uint_t	sti_oobcnt;		/* Number of T_EXDATA_IND queued */

	/* From T_info_ack */
	t_uscalar_t	sti_tsdu_size;
	t_uscalar_t	sti_etsdu_size;
	t_scalar_t	sti_addr_size;
	t_uscalar_t	sti_opt_size;
	t_uscalar_t	sti_tidu_size;
	t_scalar_t	sti_serv_type;

	/* From T_capability_ack */
	t_uscalar_t	sti_acceptor_id;

	/* Internal provider information */
	struct tpi_provinfo	*sti_provinfo;

	/*
	 * The local and remote addresses have multiple purposes
	 * but one of the key reasons for their existence and careful
	 * tracking in sockfs is to support getsockname and getpeername
	 * when the transport does not handle the TI_GET*NAME ioctls
	 * and caching when it does (signalled by valid bits in so_state).
	 * When all transports support the new TPI (with T_ADDR_REQ)
	 * we can revisit this code.
	 *
	 * The other usage of sti_faddr is to keep the "connected to"
	 * address for datagram sockets.
	 *
	 * Finally, for AF_UNIX both local and remote addresses are used
	 * to record the sockaddr_un since we use a separate namespace
	 * in the loopback transport.
	 */
	struct soaddr sti_laddr;	/* Local address */
	struct soaddr sti_faddr;	/* Peer address */
#define	sti_laddr_sa		sti_laddr.soa_sa
#define	sti_faddr_sa		sti_faddr.soa_sa
#define	sti_laddr_len		sti_laddr.soa_len
#define	sti_faddr_len		sti_faddr.soa_len
#define	sti_laddr_maxlen	sti_laddr.soa_maxlen
#define	sti_faddr_maxlen	sti_faddr.soa_maxlen

	/*
	 * For AF_UNIX sockets:
	 *
	 * sti_ux_laddr/faddr records the internal addresses used with the
	 * transport. sti_ux_vp and v_stream->sd_vnode form the
	 * cross-linkage between the underlying fs vnode corresponding
	 * to the bound sockaddr_un and the socket node.
	 *
	 * sti_ux_taddr holds the result of translations done in
	 * so_ux_addr_xlate(), which may or may not be the same as
	 * sti_ux_faddr (which is our connected peer address).
	 */
	struct so_ux_addr sti_ux_laddr; /* laddr bound with the transport */
	struct so_ux_addr sti_ux_faddr; /* connected peer address */
	struct so_ux_addr sti_ux_taddr; /* temporary address for sendmsg */
	struct vnode	*sti_ux_bound_vp; /* bound AF_UNIX file system vnode */
	struct sonode	*sti_next_so;	/* next sonode on socklist	*/
	struct sonode	*sti_prev_so;	/* previous sonode on socklist	*/
	mblk_t	*sti_discon_ind_mp;	/* T_DISCON_IND received from below */
} sotpi_info_t;

struct T_capability_ack;

extern sonodeops_t sotpi_sonodeops;

extern int	socktpi_init(void);
extern int	sotpi_convert_sonode(struct sonode *, struct sockparams *,
		    boolean_t *, queue_t **, struct cred *);
extern void	sotpi_revert_sonode(struct sonode *, struct cred *);
extern void	sotpi_update_state(struct sonode *, struct T_capability_ack *,
		    struct sockaddr *, socklen_t, struct sockaddr *, socklen_t,
		    short);

extern sotpi_info_t	*sotpi_sototpi(struct sonode *);
#ifdef DEBUG
#define	SOTOTPI(so)	(sotpi_sototpi(so))
#else
#define	SOTOTPI(so)	((sotpi_info_t *)(so)->so_priv)
#endif

/* for consumers outside sockfs */
#define	_SOTOTPI(so)	((sotpi_info_t *)(so)->so_priv)

#ifdef	__cplusplus
}
#endif

#endif /* _SOCKFS_SOCKTPI_H */