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.
This commit is contained in:
Willy Tarreau 2020-09-02 17:52:23 +02:00
parent cd5e5eaf50
commit 62292b28a3
2 changed files with 58 additions and 0 deletions

View 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 */

View 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