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