From cc8b6534834b88c3ed9868f65625d8d7936a3a2a Mon Sep 17 00:00:00 2001 From: Willy Tarreau Date: Tue, 13 Oct 2020 17:27:34 +0200 Subject: [PATCH] MINOR: sockpair: implement the .rx_listening function For socket pairs we don't rely on a real listening socket but we need to have a properly connected UNIX stream socket. This is what the new sockpair_accept_conn() tries to report. Some corner cases like half shutdown will still not be detected but that should be sufficient for most cases we really care about. --- src/proto_sockpair.c | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/src/proto_sockpair.c b/src/proto_sockpair.c index 4ac5b7642..48b598bbf 100644 --- a/src/proto_sockpair.c +++ b/src/proto_sockpair.c @@ -47,6 +47,7 @@ static int sockpair_bind_listener(struct listener *listener, char *errmsg, int e static void sockpair_enable_listener(struct listener *listener); static void sockpair_disable_listener(struct listener *listener); static int sockpair_connect_server(struct connection *conn, int flags); +static int sockpair_accept_conn(const struct receiver *rx); struct proto_fam proto_fam_sockpair = { .name = "sockpair", @@ -76,6 +77,7 @@ static struct protocol proto_sockpair = { .rx_unbind = sock_unbind, .rx_enable = sock_enable, .rx_disable = sock_disable, + .rx_listening = sockpair_accept_conn, .accept = &listener_accept, .connect = &sockpair_connect_server, .receivers = LIST_HEAD_INIT(proto_sockpair.receivers), @@ -432,6 +434,43 @@ int recv_fd_uxst(int sock) return recv_fd; } +/* Tests if the receiver supports accepting connections. Returns positive on + * success, 0 if not possible, negative if the socket is non-recoverable. In + * practice zero is never returned since we don't support suspending sockets. + * The real test consists in verifying we have a connected SOCK_STREAM of + * family AF_UNIX. + */ +static int sockpair_accept_conn(const struct receiver *rx) +{ + struct sockaddr sa; + socklen_t len; + int val; + + len = sizeof(val); + if (getsockopt(rx->fd, SOL_SOCKET, SO_TYPE, &val, &len) == -1) + return -1; + + if (val != SOCK_STREAM) + return -1; + + len = sizeof(sa); + if (getsockname(rx->fd, &sa, &len) != 0) + return -1; + + if (sa.sa_family != AF_UNIX) + return -1; + + len = sizeof(val); + if (getsockopt(rx->fd, SOL_SOCKET, SO_ACCEPTCONN, &val, &len) == -1) + return -1; + + /* Note: cannot be a listening socket, must be established */ + if (val) + return -1; + + return 1; +} + /* * Local variables: * c-indent-level: 8