]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MEDIUM: sockpair: implement sockpair_bind_receiver()
authorWilly Tarreau <w@1wt.eu>
Wed, 2 Sep 2020 15:52:23 +0000 (17:52 +0200)
committerWilly Tarreau <w@1wt.eu>
Wed, 16 Sep 2020 20:08:07 +0000 (22:08 +0200)
Note that for now we don't have a sockpair.c file to host that unusual
family, so the new function was placed directly into proto_sockpair.c.
It's no big deal given that this family is currently not shared with
multiple protocols.

The function does almost nothing but setting up the receiver. This is
normal as the socket the FDs are passed onto are supposed to have been
already created somewhere else, and the only usable identifier for such
a socket pair is the receiving FD itself.

The function was assigned to sockpair's ->bind() and is not used yet.

include/haproxy/proto_sockpair.h
src/proto_sockpair.c

index ff1482e20967cd75e61b62fc34307c1cf076b15c..b04ebea38ee9648a3a723b557fcf1ac7d27a0d68 100644 (file)
@@ -23,6 +23,7 @@
 
 int recv_fd_uxst(int sock);
 int send_fd_uxst(int fd, int send_fd);
+int sockpair_bind_receiver(struct receiver *rx, void (*handler)(int fd), char **errmsg);
 
 #endif /* _HAPROXY_PROTO_SOCKPAIR_H  */
 
index c5361c67832978ad559c4a792774eaadc906394d..de28faf7acdecfcbd68c1dcd051b5d80f4bb9f46 100644 (file)
@@ -35,6 +35,7 @@
 #include <haproxy/list.h>
 #include <haproxy/listener.h>
 #include <haproxy/protocol.h>
+#include <haproxy/proto_sockpair.h>
 #include <haproxy/time.h>
 #include <haproxy/tools.h>
 #include <haproxy/version.h>
@@ -55,6 +56,7 @@ static struct protocol proto_sockpair = {
        .l3_addrlen = sizeof(((struct sockaddr_un*)0)->sun_path),/* path len */
        .accept = &listener_accept,
        .connect = &sockpair_connect_server,
+       .bind = sockpair_bind_receiver,
        .listen = sockpair_bind_listener,
        .enable_all = enable_all_listeners,
        .disable_all = disable_all_listeners,
@@ -85,6 +87,61 @@ static void sockpair_add_listener(struct listener *listener, int port)
        proto_sockpair.nb_listeners++;
 }
 
+/* Binds receiver <rx>, and assigns <handler> and rx->owner as the callback and
+ * context, respectively, with <tm> as the thread mask. Returns and error code
+ * made of ERR_* bits on failure or ERR_NONE on success. On failure, an error
+ * message may be passed into <errmsg>. Note that the binding address is only
+ * an FD to receive the incoming FDs on. Thus by definition there is no real
+ * "bind" operation, this only completes the receiver. Such FDs are not
+ * inherited upon reload.
+ */
+int sockpair_bind_receiver(struct receiver *rx, void (*handler)(int fd), char **errmsg)
+{
+       int err;
+
+       /* ensure we never return garbage */
+       if (errmsg)
+               *errmsg = 0;
+
+       err = ERR_NONE;
+
+       if (rx->flags & RX_F_BOUND)
+               return ERR_NONE;
+
+       if (rx->fd == -1) {
+               err |= ERR_FATAL | ERR_ALERT;
+               memprintf(errmsg, "sockpair may be only used with inherited FDs");
+               goto bind_return;
+       }
+
+       if (rx->fd >= global.maxsock) {
+               err |= ERR_FATAL | ERR_ABORT | ERR_ALERT;
+               memprintf(errmsg, "not enough free sockets (raise '-n' parameter)");
+               goto bind_close_return;
+       }
+
+       if (fcntl(rx->fd, F_SETFL, O_NONBLOCK) == -1) {
+               err |= ERR_FATAL | ERR_ALERT;
+               memprintf(errmsg, "cannot make socket non-blocking");
+               goto bind_close_return;
+       }
+
+       rx->flags |= RX_F_BOUND;
+
+       fd_insert(rx->fd, rx->owner, handler, thread_mask(rx->settings->bind_thread) & all_threads_mask);
+       return err;
+
+ bind_return:
+       if (errmsg && *errmsg)
+               memprintf(errmsg, "%s [fd %d]", *errmsg, rx->fd);
+
+       return err;
+
+ bind_close_return:
+       close(rx->fd);
+       goto bind_return;
+}
+
 /* This function changes the state from ASSIGNED to LISTEN. The socket is NOT
  * enabled for polling.  The return value is composed from ERR_NONE,
  * ERR_RETRYABLE and ERR_FATAL. It may return a warning or an error message in