xref: /minix/minix/net/uds/uds.h (revision fb9c64b2)
1 #ifndef MINIX_NET_UDS_UDS_H
2 #define MINIX_NET_UDS_UDS_H
3 
4 #include <minix/drivers.h>
5 #include <minix/sockevent.h>
6 #include <minix/rmib.h>
7 #include <sys/un.h>
8 
9 /*
10  * Maximum number of UNIX domain sockets.  The control structures for all of
11  * these are allocated statically, although each socket's receive buffer is
12  * allocated only when the socket is in use.  If this constant is increased
13  * beyond 65535, a few field sizes need to be changed.
14  */
15 #define NR_UDSSOCK	256
16 
17 /* Number of slots in the <dev,ino>-to-udssock hash table. */
18 #define UDSHASH_SLOTS	64
19 
20 /* UDS has no protocols, so we accept only an "any protocol" value. */
21 #define UDSPROTO_UDS	0
22 
23 /*
24  * The size of each socket's receive buffer.  This size is currently a global
25  * setting which cannot be changed per socket at run time, and it would be
26  * rather tricky to change that.  In order not to waste resources, this size
27  * should be a multiple of the page size.  Due to the fact that data and
28  * metadata (such as lengths, source addresses and sender credentials) are
29  * intermixed in the same buffer, the actual amount of data that can be in
30  * transit at once is typically less than this value.  If this constant is
31  * increased beyond 65535, several fields and field sizes need to be changed.
32  */
33 #define UDS_BUF		32768
34 
35 /* Maximum size of control data that can be sent or received at once. */
36 #define UDS_CTL_MAX	4096
37 
38 /*
39  * We allow longer path names than the size of struct sockaddr_un's sun_path
40  * field.  The actual limit is determined by the maximum value of the sun_len
41  * field, which is 255 and includes the first two fields of the structure (one
42  * byte each) but not the null terminator of the path.  Thus, the maximum
43  * length of the path minus null terminator is 253; with terminator it is 254.
44  */
45 #define UDS_PATH_MAX	(UINT8_MAX - sizeof(uint8_t) - sizeof(sa_family_t) + 1)
46 
47 /* Output debugging information? */
48 #define DEBUG		0
49 
50 #if DEBUG
51 #define dprintf(x)	printf x
52 #else
53 #define dprintf(x)
54 #endif
55 
56 /*
57  * We declare this structure only for the static assert right below it.  We
58  * have no need for the structure otherwise, as we use "struct sockaddr"
59  * directly instead.
60  */
61 struct sockaddr_unx {
62 	uint8_t sunx_len;
63 	sa_family_t sunx_family;
64 	char sunx_path[UDS_PATH_MAX];
65 };
66 STATIC_SOCKADDR_MAX_ASSERT(sockaddr_unx);
67 
68 /*
69  * In-flight file descriptor object.  Each in-use object is part of a socket's
70  * file descriptor queue, and the file descriptor is for a file open by this
71  * service.  For each set of in-flight file descriptors associated with a
72  * particular segment, the first object's count field contains the number of
73  * file descriptors in that set.  For all other objects in that set, the count
74  * field is zero.  TODO: the count should be stored in the segment itself.
75  */
76 struct uds_fd {
77 	SIMPLEQ_ENTRY(uds_fd) ufd_next;	/* next FD object for this socket */
78 	int ufd_fd;			/* local file descriptor number */
79 	unsigned int ufd_count;		/* number of FDs for this segment */
80 };
81 
82 /*
83  * Connection-type sockets (SOCK_STREAM, SOCK_SEQPACKET) are always in one of
84  * the following five states, each with unique characteristics:
85  *
86  * - Unconnected: this socket is not in any of the other states, usually
87  *   because it either has just been created, or because it has failed a
88  *   connection attempt.  This socket has no connected peer and does not have
89  *   the SO_ACCEPTCONN socket option set.
90  * - Listening: this socket is in listening mode.  It has a queue with sockets
91  *   that are connecting or connected to it but have not yet been accepted on
92  *   it.  This socket has no connected peer.  It has the SO_ACCEPTCONN socket
93  *   option set.
94  * - Connecting: this socket is on a listening socket's queue.  While in this
95  *   state, the socket has the listening socket as its linked peer, and it has
96  *   no connected peer.
97  * - Connected: this socket is connected to another socket, which is its
98  *   connected peer socket.  It has the UDSF_CONNECTED flag set.  A socket may
99  *   be connected and still be involved with a listening socket; see below.
100  * - Disconnected: this socket was connected to another socket, but that other
101  *   socket has been closed.  As a result, this socket has no peer.  It does
102  *   have the UDSF_CONNECTED flag set.
103  *
104  * The UDS service supports two different type of connect behaviors, depending
105  * on what the LOCAL_CONNWAIT option is set to on either the connecting or the
106  * listening socket.  If LOCAL_CONNWAIT is not set on either (the default), the
107  * connecting socket socket (let's call it "A") enters the connected state
108  * right away, even if the connection is not immediately accepted through
109  * accept(2).  In that case, a new limbo socket "B" is allocated as its
110  * connection peer.  Limbo socket B is also in connected state, and either
111  * returned from accept(2) later, or freed when socket A leaves the connected
112  * state.  Socket A can leave the connected state either by being closed or
113  * when the listening socket is closed.  If LOCAL_CONNWAIT is set, socket A
114  * stays in the connecting state until it is accepted through accept(2).
115  * Importantly, in both cases, it is socket A, and (in the first case) *not*
116  * socket B, that is on the queue of the listening socket!
117  *
118  * Connected peers (uds_conn) are always symmetric: if one socket is connected
119  * to another socket, that other socket is connected to it.  Any socket that is
120  * on the queue of another socket, is said to be "linked" to that other socket
121  * (uds_link). This is an asymmetric, one-to-many relationship: many sockets
122  * may be linked to one other socket, which keeps all those sockets on its
123  * queue. From the above story it should now be clear that for connection-type
124  * sockets, only listening sockets may have sockets on its queue, and while
125  * connecting sockets are always on a listening socket's queue, connected
126  * sockets may or may not be.  Sockets in other states never are.
127  *
128  * UNIX domain sockets are generally reusable.  This means that the listening
129  * state is the only final state; all other socket states allow the socket to
130  * enter another state, although not necessarily every other state.  For
131  * example, a disconnected socket may be reconnected to another target; if that
132  * connection fails, the socket will enter the unconnected state.  As a result,
133  * a socket in any state (even the listening state) may still have incoming
134  * data pending from a previous connection.  However, EOF is currently produced
135  * only for disconnected sockets.  To be sure: connecting and connected sockets
136  * must first enter the unconnected or disconnected state, respectively, before
137  * possibly being reconnected.
138  *
139  * For connectionless (i.e., SOCK_DGRAM) sockets, there are no separate states.
140  * However, a connectionless socket may have been connected to another socket.
141  * We maintain these links not with uds_conn but with uds_link, because such
142  * connections are not symmetric, and there is an interest in keeping track of
143  * which datagram sockets are connected to a particular socket (namely, to
144  * break the connection on close without doing an exhaustive search).  For that
145  * reason, when a datagram socket connects to another socket, it is linked to
146  * that other socket, and the other socket has this socket on its queue.  As a
147  * strange corner case, a connectionless socket may be connected to itself, in
148  * which case it is its own linked peer and it is also on its own queue.  For
149  * datagram sockets, uds_conn is always NULL and UDSF_CONNECTED is never set.
150  *
151  * For the purposes of sending and receiving, we generally refer to the
152  * communication partner of a socket as its "peer".  As should now be clear,
153  * for connection-type sockets, the socket's peer is identified with uds_conn;
154  * for connectionless sockets, the socket's peer is identified with uds_link.
155  */
156 struct udssock {
157 	struct sock uds_sock;		/* sock object */
158 	struct udssock *uds_conn;	/* connected socket, or NULL if none */
159 	struct udssock *uds_link;	/* linked socket, or NULL if none */
160 	unsigned char *uds_buf;		/* receive buffer (memory-mapped) */
161 	unsigned short uds_tail;	/* tail of data in receive buffer */
162 	unsigned short uds_len;		/* length of data in receive buffer */
163 	unsigned short uds_last;	/* offset to last header in buffer */
164 	unsigned short uds_queued;	/* current nr of sockets on queue */
165 	unsigned short uds_backlog;	/* maximum nr of connecting sockets */
166 	unsigned char uds_flags;	/* UDS-specific flags (UDSF_) */
167 	unsigned char uds_pathlen;	/* socket file path length (w/o nul) */
168 	char uds_path[UDS_PATH_MAX - 1];/* socket file path (not terminated) */
169 	dev_t uds_dev;			/* socket file device number */
170 	ino_t uds_ino;			/* socket file inode number */
171 	struct unpcbid uds_cred;	/* bind/connect-time credentials */
172 	SLIST_ENTRY(udssock) uds_hash;	/* next in hash chain */
173 	TAILQ_ENTRY(udssock) uds_next;	/* next in free list or queue */
174 	SIMPLEQ_HEAD(, uds_fd) uds_fds;	/* in-flight file descriptors */
175 	TAILQ_HEAD(, udssock) uds_queue;/* queue of linked sockets */
176 };
177 
178 #define UDSF_IN_USE		0x01	/* in use (for enumeration only) */
179 #define UDSF_CONNECTED		0x02	/* connected or disconnected */
180 #define UDSF_CONNWAIT		0x04	/* leave connecting until accept */
181 #define UDSF_PASSCRED		0x08	/* pass credentials when receiving */
182 
183 /* Macros. */
184 #define uds_get_type(uds)	sockevent_get_type(&(uds)->uds_sock)
185 
186 /*
187  * A socket that can be found through hash table lookups always has a non-empty
188  * path as well as a valid <dev,ino> pair identifying the socket file that is,
189  * or once was, identified by that path.  However, a socket that is bound, even
190  * though it will still have an associated path, is not necessarily hashed.
191  * The reason for the difference is <dev,ino> pair reuse.  This case is
192  * elaborated on in uds_bind().
193  */
194 #define uds_is_bound(uds)	((uds)->uds_pathlen != 0)
195 #define uds_is_hashed(uds)	((uds)->uds_dev != NO_DEV)
196 
197 /*
198  * These macros may be used on all socket types.  However, the uds_is_connected
199  * macro returns TRUE only for connection-oriented sockets.  To see if a
200  * datagram socket is connected to a target, use uds_has_link instead.
201  */
202 #define uds_has_conn(uds)	((uds)->uds_conn != NULL)
203 #define uds_has_link(uds)	((uds)->uds_link != NULL)
204 #define uds_get_peer(uds)	\
205 	((uds_get_type(uds) != SOCK_DGRAM) ? (uds)->uds_conn : (uds)->uds_link)
206 #define uds_is_listening(uds)	sockevent_is_listening(&(uds)->uds_sock)
207 #define uds_is_connecting(uds)						\
208 	(uds_has_link(uds) && !((uds)->uds_flags & UDSF_CONNECTED) &&	\
209 	uds_get_type(uds) != SOCK_DGRAM)
210 #define uds_is_connected(uds)	\
211 	(((uds)->uds_flags & UDSF_CONNECTED) && uds_has_conn(uds))
212 #define uds_is_disconnected(uds)	\
213 	(((uds)->uds_flags & UDSF_CONNECTED) && !uds_has_conn(uds))
214 
215 #define uds_is_shutdown(uds, mask)	\
216 	sockevent_is_shutdown(&(uds)->uds_sock, (mask))
217 
218 /* Function prototypes. */
219 
220 /* uds.c */
221 sockid_t uds_get_id(struct udssock * uds);
222 struct udssock *uds_enum(struct udssock * prev, int type);
223 void uds_make_addr(const char * path, size_t len, struct sockaddr * addr,
224 	socklen_t * addr_len);
225 int uds_lookup(struct udssock * uds, const struct sockaddr * addr,
226 	socklen_t addr_len, endpoint_t user_endpt, struct udssock ** peerp);
227 
228 /* io.c */
229 void uds_io_init(void);
230 int uds_io_setup(struct udssock * uds);
231 void uds_io_cleanup(struct udssock * uds);
232 void uds_io_reset(struct udssock * uds);
233 size_t uds_io_buflen(void);
234 int uds_pre_send(struct sock * sock, size_t len, socklen_t ctl_len,
235 	const struct sockaddr * addr, socklen_t addr_len,
236 	endpoint_t user_endpt, int flags);
237 int uds_send(struct sock * sock, const struct sockdriver_data * data,
238 	size_t len, size_t * off, const struct sockdriver_data * ctl,
239 	socklen_t ctl_len, socklen_t * ctl_off, const struct sockaddr * addr,
240 	socklen_t addr_len, endpoint_t user_endpt, int flags, size_t min);
241 int uds_test_send(struct sock * sock, size_t min);
242 int uds_pre_recv(struct sock * sock, endpoint_t user_endpt, int flags);
243 int uds_recv(struct sock * sock, const struct sockdriver_data * data,
244 	size_t len, size_t * off, const struct sockdriver_data * ctl,
245 	socklen_t ctl_len, socklen_t * ctl_off, struct sockaddr * addr,
246 	socklen_t * addr_len, endpoint_t user_endpt, int flags, size_t min,
247 	int * rflags);
248 int uds_test_recv(struct sock * sock, size_t min, size_t * size);
249 
250 /* stat.c */
251 void uds_stat_init(void);
252 void uds_stat_cleanup(void);
253 
254 #endif /* !MINIX_NET_UDS_UDS_H */
255