Drop main() prototype. Syncs with NetBSD-8
[minix.git] / minix / net / uds / uds.h
blob4ccbaf425f4ebfdc546606670772026a46d56435
1 #ifndef MINIX_NET_UDS_UDS_H
2 #define MINIX_NET_UDS_UDS_H
4 #include <minix/drivers.h>
5 #include <minix/sockevent.h>
6 #include <minix/rmib.h>
7 #include <sys/un.h>
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.
15 #define NR_UDSSOCK 256
17 /* Number of slots in the <dev,ino>-to-udssock hash table. */
18 #define UDSHASH_SLOTS 64
20 /* UDS has no protocols, so we accept only an "any protocol" value. */
21 #define UDSPROTO_UDS 0
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.
33 #define UDS_BUF 32768
35 /* Maximum size of control data that can be sent or received at once. */
36 #define UDS_CTL_MAX 4096
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.
45 #define UDS_PATH_MAX (UINT8_MAX - sizeof(uint8_t) - sizeof(sa_family_t) + 1)
47 /* Output debugging information? */
48 #define DEBUG 0
50 #if DEBUG
51 #define dprintf(x) printf x
52 #else
53 #define dprintf(x)
54 #endif
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.
61 struct sockaddr_unx {
62 uint8_t sunx_len;
63 sa_family_t sunx_family;
64 char sunx_path[UDS_PATH_MAX];
66 STATIC_SOCKADDR_MAX_ASSERT(sockaddr_unx);
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.
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 */
83 * Connection-type sockets (SOCK_STREAM, SOCK_SEQPACKET) are always in one of
84 * the following five states, each with unique characteristics:
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.
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!
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.
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.
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.
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.
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 */
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 */
183 /* Macros. */
184 #define uds_get_type(uds) sockevent_get_type(&(uds)->uds_sock)
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().
194 #define uds_is_bound(uds) ((uds)->uds_pathlen != 0)
195 #define uds_is_hashed(uds) ((uds)->uds_dev != NO_DEV)
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.
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))
215 #define uds_is_shutdown(uds, mask) \
216 sockevent_is_shutdown(&(uds)->uds_sock, (mask))
218 /* Function prototypes. */
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);
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);
250 /* stat.c */
251 void uds_stat_init(void);
252 void uds_stat_cleanup(void);
254 #endif /* !MINIX_NET_UDS_UDS_H */