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