From: Willy Tarreau Date: Wed, 2 Sep 2020 15:52:23 +0000 (+0200) Subject: MEDIUM: sockpair: implement sockpair_bind_receiver() X-Git-Tag: v2.3-dev5~50 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=62292b28a372b4e875c015e49edfb94a8ef4773e;p=thirdparty%2Fhaproxy.git MEDIUM: sockpair: implement sockpair_bind_receiver() 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. --- diff --git a/include/haproxy/proto_sockpair.h b/include/haproxy/proto_sockpair.h index ff1482e209..b04ebea38e 100644 --- a/include/haproxy/proto_sockpair.h +++ b/include/haproxy/proto_sockpair.h @@ -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 */ diff --git a/src/proto_sockpair.c b/src/proto_sockpair.c index c5361c6783..de28faf7ac 100644 --- a/src/proto_sockpair.c +++ b/src/proto_sockpair.c @@ -35,6 +35,7 @@ #include #include #include +#include #include #include #include @@ -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 , and assigns and rx->owner as the callback and + * context, respectively, with 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 . 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