]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: sockpair: implement the .rx_listening function
authorWilly Tarreau <w@1wt.eu>
Tue, 13 Oct 2020 15:27:34 +0000 (17:27 +0200)
committerWilly Tarreau <w@1wt.eu>
Tue, 13 Oct 2020 16:15:33 +0000 (18:15 +0200)
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

index 4ac5b7642a900583a2d0089cd1ab736deb17c7c2..48b598bbfc72ca05bbbcd3e89fecf1e7b55ffd82 100644 (file)
@@ -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