1 /* UNIX Domain Sockets - uds.c - socket management */
5 static struct udssock uds_array
[NR_UDSSOCK
];
6 static TAILQ_HEAD(uds_freelist
, udssock
) uds_freelist
;
7 static unsigned int uds_in_use
;
8 static int uds_running
;
10 static const struct sockevent_ops uds_ops
;
12 static SLIST_HEAD(udshash
, udssock
) udshash
[UDSHASH_SLOTS
];
15 * Initialize file-to-socket hash table.
22 for (slot
= 0; slot
< __arraycount(udshash
); slot
++)
23 SLIST_INIT(&udshash
[slot
]);
27 * Return a hash table slot number for the given <dev,ino> pair.
30 udshash_slot(dev_t dev
, ino_t ino
)
33 assert(dev
!= NO_DEV
);
37 * Effectively combining two 64-bit numbers into a single 6-or-so-bit
38 * hash is not too easy. This hash function is probably among the
39 * worst options. Then again it is not all that critical as we are not
40 * expecting that many bound UDS sockets in the system anyway.
42 return (unsigned int)(dev
^ ino
) % UDSHASH_SLOTS
;
46 * Look for a socket that is bound to the given <dev,ino> pair. Return a
47 * pointer to the socket if found, or NULL otherwise.
49 static struct udssock
*
50 udshash_get(dev_t dev
, ino_t ino
)
55 slot
= udshash_slot(dev
, ino
);
57 SLIST_FOREACH(uds
, &udshash
[slot
], uds_hash
) {
58 if (uds
->uds_dev
== dev
&& uds
->uds_ino
== ino
)
66 * Add a socket to the file-to-socket hash table. The socket must have its
67 * device and inode fields set, and must not be in the hash table already.
70 udshash_add(struct udssock
* uds
)
74 slot
= udshash_slot(uds
->uds_dev
, uds
->uds_ino
);
76 SLIST_INSERT_HEAD(&udshash
[slot
], uds
, uds_hash
);
80 * Remove a socket from the file-to-socket hash table. The socket must be in
84 udshash_del(struct udssock
* uds
)
88 slot
= udshash_slot(uds
->uds_dev
, uds
->uds_ino
);
90 /* This macro is O(n). */
91 SLIST_REMOVE(&udshash
[slot
], uds
, udssock
, uds_hash
);
95 * Return the socket identifier for the given UDS socket object.
98 uds_get_id(struct udssock
* uds
)
101 return (sockid_t
)(uds
- uds_array
);
105 * Given either NULL or a previously returned socket, return the next in-use
106 * UDS socket of the given socket type, or NULL if there are no more matches.
107 * The sockets are returned in random order, but each matching socket is
108 * returned exactly once (until any socket is allocated or freed).
111 uds_enum(struct udssock
* prev
, int type
)
116 id
= uds_get_id(prev
) + 1;
120 for (; id
< NR_UDSSOCK
; id
++)
121 if ((uds_array
[id
].uds_flags
& UDSF_IN_USE
) &&
122 uds_get_type(&uds_array
[id
]) == type
)
123 return &uds_array
[id
];
129 * Invalidate credentials on the socket.
132 uds_clear_cred(struct udssock
* uds
)
135 uds
->uds_cred
.unp_pid
= -1;
136 uds
->uds_cred
.unp_euid
= -1;
137 uds
->uds_cred
.unp_egid
= -1;
141 * Obtain the credentials (process, user, and group ID) of the given user
142 * endpoint and associate them with the socket for later retrieval. It is
143 * important to note that this information is obtained once at connect time,
144 * and never updated later. The party receiving the credentials must take this
148 uds_get_cred(struct udssock
* uds
, endpoint_t user_endpt
)
152 if ((uds
->uds_cred
.unp_pid
= r
= getepinfo(user_endpt
,
153 &uds
->uds_cred
.unp_euid
, &uds
->uds_cred
.unp_egid
)) < 0) {
154 printf("UDS: failed obtaining credentials of %d (%d)\n",
162 * Allocate and initialize a UDS socket. On succes, return OK with a pointer
163 * to the new socket in 'udsp'. On failure, return a negative error code.
166 uds_alloc(struct udssock
** udsp
)
171 /* Allocate, initialize, and return a UNIX domain socket object. */
172 if (TAILQ_EMPTY(&uds_freelist
))
175 uds
= TAILQ_FIRST(&uds_freelist
);
177 uds
->uds_conn
= NULL
; /* not connected */
178 uds
->uds_link
= NULL
; /* not connecting or linked */
180 uds
->uds_flags
= UDSF_IN_USE
; /* may be found through enumeration */
181 uds
->uds_pathlen
= 0; /* not bound: no path */
182 uds
->uds_dev
= NO_DEV
; /* not hashed: no socket file device */
183 uds
->uds_ino
= 0; /* not hashed: no socket file inode */
184 uds_clear_cred(uds
); /* no bind/connect-time credentials */
185 TAILQ_INIT(&uds
->uds_queue
); /* an empty queue */
187 if ((r
= uds_io_setup(uds
)) != OK
)
190 TAILQ_REMOVE(&uds_freelist
, uds
, uds_next
);
192 assert(uds_in_use
< NR_UDSSOCK
);
200 * Free a previously allocated socket.
203 uds_free(struct sock
* sock
)
205 struct udssock
*uds
= (struct udssock
*)sock
;
209 uds
->uds_flags
= 0; /* no longer in use */
211 TAILQ_INSERT_HEAD(&uds_freelist
, uds
, uds_next
);
213 assert(uds_in_use
> 0);
214 if (--uds_in_use
== 0 && uds_running
== FALSE
)
219 * Create a new socket.
222 uds_socket(int domain
, int type
, int protocol
, endpoint_t user_endpt __unused
,
223 struct sock
** sockp
, const struct sockevent_ops
** ops
)
228 dprintf(("UDS: socket(%d,%d,%d)\n", domain
, type
, protocol
));
230 if (domain
!= PF_UNIX
) {
231 /* This means the service was configured incorrectly. */
232 printf("UDS: got request for domain %d\n", domain
);
237 /* We support the following three socket types. */
248 * The PF_UNIX domain does not support particular protocols, so the
249 * given protocol must be zero (= anything that matches).
251 if (protocol
!= UDSPROTO_UDS
)
252 return EPROTONOSUPPORT
;
254 if ((r
= uds_alloc(&uds
)) != OK
)
257 dprintf(("UDS: socket returns %d\n", uds_get_id(uds
)));
259 *sockp
= &uds
->uds_sock
;
261 return uds_get_id(uds
);
265 * Connect a pair of sockets.
268 uds_pair(struct sock
* sock1
, struct sock
* sock2
, endpoint_t user_endpt
)
270 struct udssock
*uds1
= (struct udssock
*)sock1
;
271 struct udssock
*uds2
= (struct udssock
*)sock2
;
273 dprintf(("UDS: pair(%d,%d)\n", uds_get_id(uds1
), uds_get_id(uds2
)));
275 /* Only connection-oriented types are acceptable. */
276 if (uds_get_type(uds1
) == SOCK_DGRAM
)
279 /* Connect the sockets. */
280 uds1
->uds_conn
= uds2
;
281 uds2
->uds_conn
= uds1
;
282 uds1
->uds_flags
|= UDSF_CONNECTED
;
283 uds2
->uds_flags
|= UDSF_CONNECTED
;
285 /* Obtain the (same) credentials for both sides of the connection. */
286 uds_get_cred(uds1
, user_endpt
);
287 memcpy(&uds2
->uds_cred
, &uds1
->uds_cred
, sizeof(uds2
->uds_cred
));
293 * Disconnect a UDS socket, notifying or freeing up the other end of the
294 * connection depending on whether the socket was linked, that is, on the
295 * accept queue of a listening socket.
298 uds_disconnect(struct udssock
* uds
, int was_linked
)
300 struct udssock
*conn
;
302 assert(uds_is_connected(uds
));
303 assert(uds_has_conn(uds
));
305 conn
= uds
->uds_conn
;
307 assert(uds_is_connected(conn
));
308 assert(uds_has_conn(conn
));
309 assert(!uds_has_link(conn
));
310 assert(conn
->uds_conn
== uds
);
312 /* Disconnect the sockets. */
313 uds
->uds_conn
= NULL
;
314 conn
->uds_conn
= NULL
;
317 * If the given socket is linked, then it is a connected socket for
318 * which the other end has been created but not yet accepted. In that
319 * case, the other end ('conn') will have to be freed up. Otherwise,
320 * it is a regular user-created socket and we must properly transition
321 * it into disconnected state.
324 sockevent_raise(&conn
->uds_sock
, SEV_SEND
| SEV_RECV
);
327 * Clear the peer credentials so that they will not be mistaken
328 * for having been obtained at bind time.
330 uds_clear_cred(conn
);
332 sockevent_raise(&conn
->uds_sock
, SEV_CLOSE
);
336 * Add the socket 'link' to the queue of the socket 'uds'. This also implies
337 * that 'link's link socket is set to 'uds'.
340 uds_add_queue(struct udssock
* uds
, struct udssock
* link
)
343 dprintf(("UDS: add_queue(%d,%d)\n",
344 uds_get_id(uds
), uds_get_id(link
)));
346 TAILQ_INSERT_TAIL(&uds
->uds_queue
, link
, uds_next
);
349 assert(uds
->uds_queued
!= 0);
351 link
->uds_link
= uds
;
355 * Remove the socket 'link' from the queue of the socket 'uds'. This also
356 * reset 'link's link to NULL.
359 uds_del_queue(struct udssock
* uds
, struct udssock
* link
)
362 dprintf(("UDS: del_queue(%d,%d)\n",
363 uds_get_id(uds
), uds_get_id(link
)));
365 assert(link
->uds_link
== uds
);
367 TAILQ_REMOVE(&uds
->uds_queue
, link
, uds_next
);
369 assert(uds
->uds_queued
> 0);
372 link
->uds_link
= NULL
;
376 * Remove all sockets from the queue of the socket 'uds', with the exception of
377 * 'except' if non-NULL. Raise an ECONNRESET error on all removed sockets that
378 * are not equal to 'uds'.
381 uds_clear_queue(struct udssock
* uds
, struct udssock
* except
)
383 struct udssock
*link
, *tmp
;
386 dprintf(("UDS: clear_queue(%d,%d)\n",
387 uds_get_id(uds
), (except
!= NULL
) ? uds_get_id(except
) : -1));
392 * Abort all connecting sockets queued on this socket, except for the
393 * given exception, which may be NULL.
395 TAILQ_FOREACH_SAFE(link
, &uds
->uds_queue
, uds_next
, tmp
) {
396 if (link
== except
) {
402 dprintf(("UDS: clear_queue removes %d\n", uds_get_id(link
)));
404 assert(uds_get_type(link
) == SOCK_DGRAM
||
405 uds_is_connecting(link
) || uds_is_connected(link
));
407 uds_del_queue(uds
, link
);
410 * Generate an error only if the socket was not linked to
411 * itself (only datagram sockets can be linked to themselves).
412 * The error is not helpful for applications in that case.
415 sockevent_set_error(&link
->uds_sock
, ECONNRESET
);
418 * If this is a listening socket, disconnect the connecting or
419 * connected end. If a connected peer was already created for
420 * the queued socket, dispose of that peer.
422 * Clear credentials obtained when starting to connect (in
423 * which case the socket is always a connection-oriented
424 * socket), so that they will not be mistaken for credentials
425 * obtained at bind time.
427 if (uds_get_type(link
) != SOCK_DGRAM
) {
428 if (uds_is_connected(link
))
429 uds_disconnect(link
, TRUE
/*was_linked*/);
431 uds_clear_cred(link
);
435 assert(uds
->uds_queued
== found
);
439 * Check whether the socket address given in 'addr', with length 'addr_len', is
440 * a valid UNIX domain socket address (including a path to a socket file). On
441 * success, return the (non-zero) length of the socket file's path, minus the
442 * null terminator which may in fact not be present. The caller is responsible
443 * for copying and terminating the path as needed. A pointer to the path as
444 * stored in 'addr' is returned in 'pathp'. On failure, return an error code.
447 uds_check_addr(const struct sockaddr
* addr
, socklen_t addr_len
,
454 * We could cast to a sockaddr_un structure pointer first, but that
455 * would not provide any benefits here. Instead, we use sa_data as the
456 * generic equivalent of sun_path.
458 if (addr_len
< offsetof(struct sockaddr
, sa_data
))
461 if (addr
->sa_family
!= AF_UNIX
)
464 len
= (size_t)addr_len
- offsetof(struct sockaddr
, sa_data
);
465 if (len
> 0 && (p
= memchr(addr
->sa_data
, '\0', len
)) != NULL
)
466 len
= (size_t)(p
- addr
->sa_data
);
468 /* The given path name must not be an empty string. */
472 /* This check should be redundant but better safe than sorry. */
473 if (len
>= UDS_PATH_MAX
)
476 *pathp
= (const char *)addr
->sa_data
;
481 * Given the socket file path given as 'path' with length 'path_len' (not
482 * necessarily null terminated), store a socket address with the path in
483 * 'addr', and return the socket address length in 'addr_len'. The calling
484 * libraries (libsockdriver, libsockevent) and the static assert in uds.h
485 * guarantee that 'addr' is sufficiently large to store any address we generate
486 * here. The libraries may subsequently copy out only a part of it to the user
487 * process. This function always succeeds.
490 uds_make_addr(const char * path
, size_t len
, struct sockaddr
* addr
,
491 socklen_t
* addr_len
)
495 * Generate the address. The stored length (sa_len/sun_len) does not
496 * include a null terminator. The entire structure does include a null
497 * terminator, but only if the socket is bound.
499 addr
->sa_len
= offsetof(struct sockaddr
, sa_data
) + len
;
500 addr
->sa_family
= AF_UNIX
;
502 /* This call may (intentionally) overrun the sa_data size. */
503 memcpy((char *)addr
->sa_data
, path
, len
);
504 ((char *)addr
->sa_data
)[len
] = '\0';
506 /* The socket is bound, so include the null terminator. */
508 assert(len
<= UDS_PATH_MAX
);
511 /* Note that this length may be different from sa_len/sun_len now. */
512 *addr_len
= offsetof(struct sockaddr
, sa_data
) + len
;
516 * Bind a socket to a local address.
519 uds_bind(struct sock
* sock
, const struct sockaddr
* addr
, socklen_t addr_len
,
520 endpoint_t user_endpt
)
522 struct udssock
*uds
= (struct udssock
*)sock
;
523 struct udssock
*uds2
;
530 dprintf(("UDS: bind(%d)\n", uds_get_id(uds
)));
532 /* A socket may be bound at any time, but only once. */
533 if (uds_is_bound(uds
))
536 /* Verify that the user gave us an acceptable address. */
537 if ((r
= uds_check_addr(addr
, addr_len
, &path
)) < 0)
541 /* Attempt to create the socket file on the file system. */
542 r
= socketpath(user_endpt
, path
, len
, SPATH_CREATE
, &dev
, &ino
);
545 assert(dev
!= NO_DEV
&& ino
!= 0);
548 * It is possible that a socket file of a previously bound socket was
549 * unlinked, and due to inode number reuse, a new socket file has now
550 * been created with the same <dev,ino> pair. In that case, we must
551 * unbind the old socket, because it must no longer be found. The old
552 * socket will still have a path (and behave as though it is bound) but
553 * no longer be found through hash lookups.
555 if ((uds2
= udshash_get(dev
, ino
)) != NULL
) {
558 uds2
->uds_dev
= NO_DEV
;
563 * Obtain credentials for the socket, unless the socket is already
564 * connecting or connected, in which case we must not replace the
565 * credentials we obtained already. We later clear those credentials
566 * upon a connection failure or disconnect, so that if the socket is
567 * then put in listening mode, we know there are no bind-time
568 * credentials. Not ideal, but we really need two separate sets of
569 * credentials if we want to get this right, which is a waste of memory
570 * as no sane application writer would ever rely on credential passing
571 * after recycling a socket..
573 if (uds_get_type(uds
) != SOCK_DGRAM
&& !uds_is_connecting(uds
) &&
574 !uds_is_connected(uds
))
575 uds_get_cred(uds
, user_endpt
);
577 /* Asssign the address to the socket. */
578 uds
->uds_pathlen
= len
;
579 memcpy(&uds
->uds_path
, path
, len
);
589 * Look up a UDS socket based on a user-given address. If a socket exists for
590 * the address, check if it is type-compatible with the given UDS socket.
591 * On succes, return OK, with 'peerp' set to the socket that was found. On
592 * failure, return a negative error code.
595 uds_lookup(struct udssock
* uds
, const struct sockaddr
* addr
,
596 socklen_t addr_len
, endpoint_t user_endpt
, struct udssock
** peerp
)
598 struct udssock
*peer
;
605 /* Verify that the user gave us an acceptable address. */
606 if ((r
= uds_check_addr(addr
, addr_len
, &path
)) < 0)
610 /* Attempt to look up the socket file on the file system. */
611 r
= socketpath(user_endpt
, path
, len
, SPATH_CHECK
, &dev
, &ino
);
614 assert(dev
!= NO_DEV
&& ino
!= 0);
616 if ((peer
= udshash_get(dev
, ino
)) == NULL
)
618 if (uds_get_type(peer
) != uds_get_type(uds
))
626 * Given the listening socket 'uds', and the socket 'link' that is calling or
627 * has called connect(2) and is or will be linked to the listening socket's
628 * queue, create a new socket and connect it to 'link', putting both sockets in
629 * the connected state. The given link socket may be in unconnected,
630 * connecting, or disconnected state prior to the call. Return OK or an error
631 * code. The link state of the link socket remains unchanged in any case.
634 uds_attach(struct udssock
* uds
, struct udssock
* link
)
636 struct udssock
*conn
;
640 * Allocate a new socket to use as peer socket for the connection that
641 * is about to be established. The new socket is not yet known by
644 if ((r
= uds_alloc(&conn
)) != OK
)
648 * Ask libsockevent to clone the sock object in the new UDS socket from
649 * the listening socket. This adds the sock object to libsockevent's
650 * data structures and ensures that we can safely use the socket
651 * despite the fact that it has not yet been accepted (and thus
652 * returned to libsockevent). From this moment on, we must either
653 * return the socket's ID (but not a pointer to it!) from uds_accept()
654 * or raise SEV_CLOSE on it.
656 sockevent_clone(&uds
->uds_sock
, &conn
->uds_sock
, uds_get_id(conn
));
658 /* Connect the link socket to the new socket. */
659 link
->uds_conn
= conn
;
660 link
->uds_flags
|= UDSF_CONNECTED
;
663 * Connect the new socket to the link socket as well. The child
664 * socket should also inherit pretty much all settings from the
665 * listening socket, including the bind path and the listening socket's
666 * bind-time credentials.
668 conn
->uds_conn
= link
;
669 conn
->uds_flags
= uds
->uds_flags
& (UDSF_PASSCRED
| UDSF_CONNWAIT
);
670 conn
->uds_flags
|= UDSF_CONNECTED
;
671 conn
->uds_pathlen
= uds
->uds_pathlen
;
672 memcpy(conn
->uds_path
, uds
->uds_path
, (size_t)uds
->uds_pathlen
);
673 memcpy(&conn
->uds_cred
, &uds
->uds_cred
, sizeof(conn
->uds_cred
));
679 * Connect a socket to a remote address.
682 uds_connect(struct sock
* sock
, const struct sockaddr
* addr
,
683 socklen_t addr_len
, endpoint_t user_endpt
)
685 struct udssock
*uds
= (struct udssock
*)sock
;
686 struct udssock
*link
;
689 dprintf(("UDS: connect(%d)\n", uds_get_id(uds
)));
691 /* For connection-oriented sockets, several state checks apply. */
692 if (uds_get_type(uds
) != SOCK_DGRAM
) {
693 if (uds_is_listening(uds
))
695 if (uds_is_connecting(uds
))
697 if (uds_is_connected(uds
))
699 /* Disconnected sockets may be reconnected, see below. */
702 * Connectionless sockets may be unconnected by providing an
703 * address with family AF_UNSPEC. Handle this case first here.
705 if (addr_len
>= offsetof(struct sockaddr
, sa_data
) &&
706 addr
->sa_family
== AF_UNSPEC
) {
708 * Reset this socket's previous connection to another
709 * socket, if any. Unconnecting has no effect on other
710 * sockets connected to this socket, though.
712 if (uds_has_link(uds
))
713 uds_del_queue(uds
->uds_link
, uds
);
720 * Find the socket identified by the given address. If it exists at
721 * all, see if it is a proper match.
723 if ((r
= uds_lookup(uds
, addr
, addr_len
, user_endpt
, &link
)) != OK
)
727 * Handle connectionless sockets first, in which case a connect links
728 * the socket to a send target and limits receipt to datagrams from
729 * that target. We actually point the socket to the peer socket,
730 * through uds_link. That also means that if the target socket
731 * disappears, we have to reset any sockets connected to it, in which
732 * case we return them to the unconnected state. In order to allow
733 * finding all sockets connected to a particular socket, we put all
734 * those sockets on their target's queue, hence why we use uds_link and
735 * not uds_conn. As mentioned before, we allow reconnecting without
737 * TODO: see if reconnecting should clear a pending ECONNRESET.
739 * An important note: 'uds' and 'link' may actually be the same socket,
740 * if the caller chooses to connect a socket with itself!
742 if (uds_get_type(uds
) == SOCK_DGRAM
) {
743 /* Reconnecting to the same socket has no effect. */
744 if (uds_has_link(uds
) && uds
->uds_link
== link
)
748 * If the intended target is linked to another socket, we
749 * refuse linking to it. Sending or receiving would never work
750 * anyway. Do allow a socket to link to itself after being
751 * linked to another socket. The error code is the same as in
752 * the sending code, borrowed from Linux.
754 if (uds
!= link
&& uds_has_link(link
) && link
->uds_link
!= uds
)
758 * Reset this socket's previous link to another socket, if any.
760 if (uds_has_link(uds
))
761 uds_del_queue(uds
->uds_link
, uds
);
764 * Reset any links to this socket, except for the one by
765 * the intended target. Sending or receiving would no longer
766 * work anyway. If the socket was linked to itself, clear its
767 * self-link without generating an ECONNRESET. If the socket
768 * is relinking to itself, reestablish the link after first
771 uds_clear_queue(uds
, (uds
!= link
) ? link
: NULL
);
773 uds_add_queue(link
, uds
);
779 * For connection-oriented sockets there is more to do. First, make
780 * sure that the peer is a listening socket, that it has not been shut
781 * down, and that its backlog is not already at the configured maximum.
783 if (!uds_is_listening(link
))
786 if (uds_is_shutdown(link
, SFL_SHUT_RD
| SFL_SHUT_WR
))
789 if (link
->uds_queued
>= link
->uds_backlog
)
793 * The behavior of connect(2) now depends on whether LOCAL_CONNWAIT is
794 * set on either the connecting or the listening socket. If it is not,
795 * the socket will be connected to a new as-yet invisible socket, which
796 * will be the one returned from accept(2) later. If it was, the
797 * socket will be put in the connecting state.
799 if (!((uds
->uds_flags
| link
->uds_flags
) & UDSF_CONNWAIT
)) {
800 if ((r
= uds_attach(link
, uds
)) != OK
)
803 assert(uds_is_connected(uds
));
806 * Disconnected sockets now stop being connected. Any pending
807 * data can still be received, though.
809 uds
->uds_flags
&= ~UDSF_CONNECTED
;
814 /* Obtain credentials for the socket. */
815 uds_get_cred(uds
, user_endpt
);
817 /* Add the socket at the end of the listening socket's queue. */
818 uds_add_queue(link
, uds
);
820 assert(r
!= SUSPEND
|| uds_is_connecting(uds
));
823 * Let an accept call handle the rest, which will in turn resume this
824 * connect call. The sockevent library ensures that this works even if
825 * the call is non-blocking.
827 sockevent_raise(&link
->uds_sock
, SEV_ACCEPT
);
833 * Put a socket in listening mode.
836 uds_listen(struct sock
* sock
, int backlog
)
838 struct udssock
*uds
= (struct udssock
*)sock
;
840 /* The maximum backlog value must not exceed its field size. */
841 assert(SOMAXCONN
<= USHRT_MAX
);
843 dprintf(("UDS: listen(%d)\n", uds_get_id(uds
)));
845 /* Only connection-oriented types may be put in listening mode. */
846 if (uds_get_type(uds
) == SOCK_DGRAM
)
849 /* A connecting or connected socket may not listen. */
850 if (uds_is_connecting(uds
) || uds_is_connected(uds
))
853 /* POSIX says that this is now the appropriate error code here. */
854 if (!uds_is_bound(uds
))
858 * The socket is now entering the listening state. If it was
859 * previously disconnected, clear the connection flag.
861 uds
->uds_flags
&= ~UDSF_CONNECTED
;
864 * We do not remove sockets from the backlog if it is now being dropped
865 * below the current number of queued sockets. We only refuse newly
866 * connecting sockets beyond the backlog size.
868 uds
->uds_backlog
= backlog
;
874 * Test whether an accept request would block. Return OK if a socket could be
875 * accepted, an appropriate error code if an accept call would fail instantly,
876 * or SUSPEND if the accept request would block waiting for a connection.
879 uds_test_accept(struct sock
* sock
)
881 struct udssock
*uds
= (struct udssock
*)sock
;
884 * Ensure that the socket is in listening mode. If not, we must return
885 * the error code that is appropriate for this socket type.
887 if (uds_get_type(uds
) == SOCK_DGRAM
)
889 if (!uds_is_listening(uds
))
893 * If the socket has been shut down, new connections are no longer
894 * accepted and accept calls no longer block. This is not a POSIX
895 * requirement, but rather an application convenience feature.
897 if (uds
->uds_queued
== 0) {
898 if (uds_is_shutdown(uds
, SFL_SHUT_RD
| SFL_SHUT_WR
))
908 * Accept a connection on a listening socket, creating a new socket. On
909 * success, return the new socket identifier, with the new socket stored in
910 * 'newsockp'. Otherwise, return an error code.
913 uds_accept(struct sock
* sock
, struct sockaddr
* addr
, socklen_t
* addr_len
,
914 endpoint_t user_endpt __unused
, struct sock
** newsockp
)
916 struct udssock
*uds
= (struct udssock
*)sock
;
917 struct udssock
*link
, *conn
;
920 dprintf(("UDS: accept(%d)\n", uds_get_id(uds
)));
922 if ((r
= uds_test_accept(sock
)) != OK
)
926 * Take the first connecting socket off the listening queue.
928 assert(!TAILQ_EMPTY(&uds
->uds_queue
));
930 link
= TAILQ_FIRST(&uds
->uds_queue
);
933 * Depending on the LOCAL_CONNWAIT setting at the time of connect(2),
934 * the socket may be connecting or connected. In the latter case, its
935 * attached socket is the socket we will return now. Otherwise we have
936 * to attach a socket first.
938 assert(uds_is_connecting(link
) || uds_is_connected(link
));
940 if (uds_is_connecting(link
)) {
942 * Attach a new socket. If this fails, return the error but
943 * leave the connecting socket on the listening queue.
945 if ((r
= uds_attach(uds
, link
)) != OK
)
948 assert(uds_is_connected(link
));
951 * Wake up blocked (connect, send, select) calls on the peer
954 sockevent_raise(&link
->uds_sock
, SEV_CONNECT
);
957 uds_del_queue(uds
, link
);
959 /* Return the peer socket's address to the caller. */
960 uds_make_addr(link
->uds_path
, link
->uds_pathlen
, addr
, addr_len
);
962 conn
= link
->uds_conn
;
964 dprintf(("UDS: accept returns %d\n", uds_get_id(conn
)));
967 * We already cloned the sock object, so return its ID but not a
968 * pointer to it. That tells libsockevent not to reinitialize it.
971 return uds_get_id(conn
);
975 * Set socket options.
978 uds_setsockopt(struct sock
* sock
, int level
, int name
,
979 const struct sockdriver_data
* data
, socklen_t len
)
981 struct udssock
*uds
= (struct udssock
*)sock
;
984 dprintf(("UDS: setsockopt(%d,%d,%d)\n", uds_get_id(uds
), level
, name
));
992 * The send buffer size may not be changed because the
993 * buffer is the same as the other side's receive
994 * buffer, and what the other side is may vary from
995 * send call to send call. Changing the receive buffer
996 * size would disallow us from even accurately guessing
997 * the send buffer size in getsockopt calls. Therefore
998 * both are hardcoded and cannot actually be changed.
999 * In order to support applications that want at least
1000 * a certain minimum, we do accept requests to shrink
1001 * either buffer, but we ignore the given size.
1003 if ((r
= sockdriver_copyin_opt(data
, &val
, sizeof(val
),
1007 if (val
<= 0 || (size_t)val
> uds_io_buflen())
1010 return OK
; /* ignore new value */
1018 if ((r
= sockdriver_copyin_opt(data
, &val
, sizeof(val
),
1023 uds
->uds_flags
|= UDSF_PASSCRED
;
1025 uds
->uds_flags
&= ~UDSF_PASSCRED
;
1028 * In incredibly rare cases, disabling this flag may
1029 * allow blocked sends to be resumed, because suddenly
1030 * no room for the credentials is needed in the receive
1034 sockevent_raise(&uds
->uds_sock
, SEV_SEND
);
1038 case LOCAL_CONNWAIT
:
1039 if ((r
= sockdriver_copyin_opt(data
, &val
, sizeof(val
),
1044 uds
->uds_flags
|= UDSF_CONNWAIT
;
1046 uds
->uds_flags
&= ~UDSF_CONNWAIT
;
1049 * Changing the setting does not affect sockets that
1050 * are currently pending to be accepted. Therefore,
1051 * uds_accept() may have to deal with either case on a
1052 * socket-by-socket basis.
1057 /* This option may be retrieved but not set. */
1068 * Retrieve socket options.
1071 uds_getsockopt(struct sock
* sock
, int level
, int name
,
1072 const struct sockdriver_data
* data
, socklen_t
* len
)
1074 struct udssock
*uds
= (struct udssock
*)sock
;
1077 dprintf(("UDS: getsockopt(%d,%d,%d)\n", uds_get_id(uds
), level
, name
));
1084 /* See uds_setsockopt() for why this is static. */
1085 val
= (int)uds_io_buflen();
1087 return sockdriver_copyout_opt(data
, &val
, sizeof(val
),
1096 val
= !!(uds
->uds_flags
& UDSF_PASSCRED
);
1098 return sockdriver_copyout_opt(data
, &val
, sizeof(val
),
1101 case LOCAL_CONNWAIT
:
1102 val
= !!(uds
->uds_flags
& UDSF_CONNWAIT
);
1104 return sockdriver_copyout_opt(data
, &val
, sizeof(val
),
1108 /* getpeereid(3) documents these error codes. */
1109 if (uds_get_type(uds
) == SOCK_DGRAM
)
1111 if (!uds_is_connected(uds
))
1115 * This is a custom MINIX3 error, indicating that there
1116 * are no credentials to return. This could be due to
1117 * a failure to obtain them (which *should* not happen)
1118 * but also if the socket was bound while connected,
1119 * disconnected, and then reused as listening socket.
1121 if (uds
->uds_conn
->uds_cred
.unp_pid
== -1)
1124 return sockdriver_copyout_opt(data
,
1125 &uds
->uds_conn
->uds_cred
,
1126 sizeof(uds
->uds_conn
->uds_cred
), len
);
1136 * Retrieve a socket's local address.
1139 uds_getsockname(struct sock
* sock
, struct sockaddr
* addr
,
1140 socklen_t
* addr_len
)
1142 struct udssock
*uds
= (struct udssock
*)sock
;
1144 dprintf(("UDS: getsockname(%d)\n", uds_get_id(uds
)));
1146 uds_make_addr(uds
->uds_path
, uds
->uds_pathlen
, addr
, addr_len
);
1152 * Retrieve a socket's remote address.
1155 uds_getpeername(struct sock
* sock
, struct sockaddr
* addr
,
1156 socklen_t
* addr_len
)
1158 struct udssock
*uds
= (struct udssock
*)sock
;
1159 struct udssock
*peer
;
1161 dprintf(("UDS: getpeername(%d)\n", uds_get_id(uds
)));
1164 * For disconnected sockets, we no longer have a peer socket and thus
1165 * also no peer address. Too bad, but NetBSD does the same.
1167 * For connecting sockets we could in fact return a peer address, but
1168 * POSIX says (and other platforms agree) that we should deny the call.
1170 peer
= uds_get_peer(uds
);
1172 if (peer
== NULL
|| uds_is_connecting(uds
))
1175 uds_make_addr(peer
->uds_path
, peer
->uds_pathlen
, addr
, addr_len
);
1181 * Shut down socket send and receive operations. Note that 'flags' is a
1182 * bitwise mask with libsockevent's SFL_SHUT_{RD,WR} flags rather than the set
1183 * of SHUT_{RD,WR,RDWR} values from userland.
1186 uds_shutdown(struct sock
* sock
, unsigned int flags
)
1188 struct udssock
*uds
= (struct udssock
*)sock
;
1189 struct udssock
*conn
;
1192 dprintf(("UDS: shutdown(%d,0x%x)\n", uds_get_id(uds
), flags
));
1195 * If we are shutting down the socket for reading, we can already close
1196 * any in-flight file descriptors associated with this socket.
1198 if (flags
& SFL_SHUT_RD
)
1202 * A shutdown on this side of a connection may have an effect on
1203 * ongoing operations on the other side. Fire appropriate events.
1205 if (uds_is_connected(uds
)) {
1206 assert(uds_get_type(uds
) != SOCK_DGRAM
);
1208 conn
= uds
->uds_conn
;
1211 if (flags
& SFL_SHUT_RD
)
1213 if (flags
& SFL_SHUT_WR
)
1216 sockevent_raise(&conn
->uds_sock
, mask
);
1225 * The 'force' flag is unused because we need never wait for data to be sent,
1226 * since we keep all in-flight data on the receiver side.
1229 uds_close(struct sock
* sock
, int force __unused
)
1231 struct udssock
*uds
= (struct udssock
*)sock
;
1233 dprintf(("UDS: close(%d)\n", uds_get_id(uds
)));
1235 if (uds_get_type(uds
) == SOCK_DGRAM
) {
1236 /* If this socket is linked to a target, disconnect it. */
1237 if (uds_has_link(uds
))
1238 uds_del_queue(uds
->uds_link
, uds
);
1240 /* Reset all sockets linked to this socket as a target. */
1241 uds_clear_queue(uds
, NULL
);
1242 } else if (uds_is_listening(uds
)) {
1244 * Abort all connecting sockets queued on this socket, and
1245 * break all connections for connected sockets queued on this
1246 * socket, freeing their peers.
1248 uds_clear_queue(uds
, NULL
);
1249 } else if (uds_has_link(uds
)) {
1251 * This socket is connecting or connected while the other side
1252 * has not been accepted yet. Remove the socket from the
1253 * listening socket's queue, and if it was connected, get rid
1254 * of its peer socket altogether.
1256 assert(uds_is_listening(uds
->uds_link
));
1258 uds_del_queue(uds
->uds_link
, uds
);
1260 if (uds_is_connected(uds
))
1261 uds_disconnect(uds
, TRUE
/*was_linked*/);
1262 } else if (uds_is_connected(uds
)) {
1264 * Decouple the peer socket from this socket, and possibly wake
1265 * up any pending operations on it. The socket remains marked
1266 * as connected, but will now be disconnected.
1268 uds_disconnect(uds
, FALSE
/*was_linked*/);
1271 if (uds_is_hashed(uds
))
1277 static const struct sockevent_ops uds_ops
= {
1278 .sop_pair
= uds_pair
,
1279 .sop_bind
= uds_bind
,
1280 .sop_connect
= uds_connect
,
1281 .sop_listen
= uds_listen
,
1282 .sop_accept
= uds_accept
,
1283 .sop_test_accept
= uds_test_accept
,
1284 .sop_pre_send
= uds_pre_send
,
1285 .sop_send
= uds_send
,
1286 .sop_test_send
= uds_test_send
,
1287 .sop_pre_recv
= uds_pre_recv
,
1288 .sop_recv
= uds_recv
,
1289 .sop_test_recv
= uds_test_recv
,
1290 .sop_setsockopt
= uds_setsockopt
,
1291 .sop_getsockopt
= uds_getsockopt
,
1292 .sop_getsockname
= uds_getsockname
,
1293 .sop_getpeername
= uds_getpeername
,
1294 .sop_shutdown
= uds_shutdown
,
1295 .sop_close
= uds_close
,
1296 .sop_free
= uds_free
1300 * Initialize the service.
1303 uds_init(int type __unused
, sef_init_info_t
* info __unused
)
1307 /* Initialize the list of free sockets. */
1308 TAILQ_INIT(&uds_freelist
);
1310 for (i
= 0; i
< __arraycount(uds_array
); i
++) {
1311 uds_array
[i
].uds_flags
= 0;
1313 TAILQ_INSERT_TAIL(&uds_freelist
, &uds_array
[i
], uds_next
);
1316 /* Initialize the file-to-socket hash table. */
1319 /* Initialize the input/output module. */
1322 /* Initialize the status module. */
1325 /* Initialize the sockevent library. */
1326 sockevent_init(uds_socket
);
1335 * Clean up before shutdown.
1341 /* Tell the status module to clean up. */
1346 * The service has received a signal.
1349 uds_signal(int signo
)
1352 /* Only check for the termination signal. Ignore anything else. */
1353 if (signo
!= SIGTERM
)
1356 /* Exit only once all sockets have been closed. */
1357 uds_running
= FALSE
;
1359 if (uds_in_use
== 0)
1364 * Perform initialization using the System Event Framework (SEF).
1370 /* Register initialization callbacks. */
1371 sef_setcb_init_fresh(uds_init
);
1373 /* Register signal callback. */
1374 sef_setcb_signal_handler(uds_signal
);
1376 /* Let SEF perform startup. */
1381 * The UNIX Domain Sockets driver.
1389 /* Initialize the service. */
1392 /* Loop receiving and processing messages until instructed to stop. */
1393 while (uds_running
|| uds_in_use
> 0) {
1394 if ((r
= sef_receive_status(ANY
, &m
, &ipc_status
)) != OK
) {
1396 continue; /* sef_cancel() was called */
1398 panic("UDS: sef_receive_status failed: %d", r
);
1402 * Messages from the MIB service are (ultimately) for the
1403 * status module. Everything else is assumed to be a socket
1404 * request and passed to libsockevent, which will ignore
1405 * anything it does not recognize.
1407 if (m
.m_source
== MIB_PROC_NR
)
1408 rmib_process(&m
, ipc_status
);
1410 sockevent_process(&m
, ipc_status
);
1413 /* Clean up before graceful shutdown. */
1416 return EXIT_SUCCESS
;