From: Willy Tarreau Date: Tue, 1 Sep 2020 08:47:07 +0000 (+0200) Subject: MINOR: receiver: add a receiver-specific flag to indicate the socket is bound X-Git-Tag: v2.3-dev5~61 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=0b9150155e499a781ea76c24b9b9a70703b87186;p=thirdparty%2Fhaproxy.git MINOR: receiver: add a receiver-specific flag to indicate the socket is bound In order to split the receiver from the listener, we'll need to know that a socket is already bound and ready to receive. We used to do that via tha LI_O_ASSIGNED state but that's not sufficient anymore since the receiver might not belong to a listener anymore. The new RX_F_BOUND flag is used for this. --- diff --git a/include/haproxy/receiver-t.h b/include/haproxy/receiver-t.h index 5b45dc2692..5537d5ab55 100644 --- a/include/haproxy/receiver-t.h +++ b/include/haproxy/receiver-t.h @@ -29,6 +29,9 @@ #include #include +/* Bit values for receiver->options */ +#define RX_F_BOUND 0x00000001 /* receiver already bound */ + /* All the settings that are used to configure a receiver */ struct rx_settings { unsigned long bind_proc; /* bitmask of processes allowed to use these listeners */ diff --git a/src/listener.c b/src/listener.c index 4026ea2333..27476cd7ac 100644 --- a/src/listener.c +++ b/src/listener.c @@ -505,6 +505,7 @@ void do_unbind_listener(struct listener *listener, int do_close) fd_stop_both(listener->rx.fd); if (do_close) { fd_delete(listener->rx.fd); + listener->rx.flags &= ~RX_F_BOUND; listener->rx.fd = -1; } } diff --git a/src/proto_sockpair.c b/src/proto_sockpair.c index 90300cc22c..d25ab5a424 100644 --- a/src/proto_sockpair.c +++ b/src/proto_sockpair.c @@ -106,6 +106,9 @@ static int sockpair_bind_listener(struct listener *listener, char *errmsg, int e if (listener->state != LI_ASSIGNED) return ERR_NONE; /* already bound */ + if (listener->rx.flags & RX_F_BOUND) + goto bound; + if (listener->rx.fd == -1) { err |= ERR_FATAL | ERR_ALERT; msg = "sockpair can be only used with inherited FDs"; @@ -122,7 +125,9 @@ static int sockpair_bind_listener(struct listener *listener, char *errmsg, int e msg = "cannot make sockpair non-blocking"; goto err_return; } + listener->rx.flags |= RX_F_BOUND; + bound: listener->state = LI_LISTEN; fd_insert(fd, listener, listener->rx.proto->accept, diff --git a/src/proto_tcp.c b/src/proto_tcp.c index 62f86117dc..84b3635f95 100644 --- a/src/proto_tcp.c +++ b/src/proto_tcp.c @@ -569,6 +569,9 @@ int tcp_bind_listener(struct listener *listener, char *errmsg, int errlen) err = ERR_NONE; + if (listener->rx.flags & RX_F_BOUND) + goto bound; + if (listener->rx.fd == -1) listener->rx.fd = sock_find_compatible_fd(listener); @@ -744,7 +747,9 @@ int tcp_bind_listener(struct listener *listener, char *errmsg, int errlen) msg = "cannot bind socket"; goto tcp_close_return; } + listener->rx.flags |= RX_F_BOUND; + bound: ready = 0; ready_len = sizeof(ready); if (getsockopt(fd, SOL_SOCKET, SO_ACCEPTCONN, &ready, &ready_len) == -1) diff --git a/src/proto_udp.c b/src/proto_udp.c index 9325ba8f46..64ea639318 100644 --- a/src/proto_udp.c +++ b/src/proto_udp.c @@ -195,6 +195,9 @@ int udp_bind_listener(struct listener *listener, char *errmsg, int errlen) err = ERR_NONE; + if (listener->rx.flags & RX_F_BOUND) + goto bound; + /* TODO: Implement reuse fd. Take care that to identify fd to reuse * listeners uses a special AF_CUST_ family and we MUST consider * IPPROTO (sockaddr is not enough) @@ -276,7 +279,9 @@ int udp_bind_listener(struct listener *listener, char *errmsg, int errlen) msg = "cannot bind socket"; goto udp_close_return; } + listener->rx.flags |= RX_F_BOUND; + bound: /* the socket is ready */ listener->rx.fd = fd; listener->state = LI_LISTEN; diff --git a/src/proto_uxst.c b/src/proto_uxst.c index 55d02be8d0..4378db3ad9 100644 --- a/src/proto_uxst.c +++ b/src/proto_uxst.c @@ -109,6 +109,9 @@ static int uxst_bind_listener(struct listener *listener, char *errmsg, int errle if (listener->state != LI_ASSIGNED) return ERR_NONE; /* already bound */ + if (listener->rx.flags & RX_F_BOUND) + goto bound; + if (listener->rx.fd == -1) listener->rx.fd = sock_find_compatible_fd(listener); path = ((struct sockaddr_un *)&listener->rx.addr)->sun_path; @@ -230,7 +233,9 @@ static int uxst_bind_listener(struct listener *listener, char *errmsg, int errle msg = "cannot change UNIX socket ownership"; goto err_unlink_temp; } + listener->rx.flags |= RX_F_BOUND; + bound: ready = 0; ready_len = sizeof(ready); if (getsockopt(fd, SOL_SOCKET, SO_ACCEPTCONN, &ready, &ready_len) == -1)