summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWilly Tarreau <w@1wt.eu>2020-09-01 15:12:08 +0200
committerWilly Tarreau <w@1wt.eu>2020-09-01 15:43:09 +0200
commit4aa835d24c7120f89a9ad7956fa0a69e22fb92c2 (patch)
tree41d6cb39c6ffddc98d0d8cfdf3d58cd0646d6bf8
parentac3cb36455607c594d3127b0a8fc745aa00c50c3 (diff)
downloadhaproxy-4aa835d24c7120f89a9ad7956fa0a69e22fb92c2.tar.gz
MINOR: receiver: add the foreign and v6only flags
The new RX_O_FOREIGN and RX_O_V6ONLY flags are now derived from the listener at the moment the ->bind() call is made. It's difficult to do it earlier because the keyword parsers are called one at a time without context so it's not possible to know whether v6only and v4v6 conflict for example, nor is it easy to know when all keywords were parsed. But fixing the receiver before starting it is fine.
-rw-r--r--include/haproxy/receiver-t.h2
-rw-r--r--src/proto_tcp.c13
-rw-r--r--src/sock.c13
3 files changed, 18 insertions, 10 deletions
diff --git a/include/haproxy/receiver-t.h b/include/haproxy/receiver-t.h
index 36841ac11..c56a27473 100644
--- a/include/haproxy/receiver-t.h
+++ b/include/haproxy/receiver-t.h
@@ -32,6 +32,8 @@
/* Bit values for receiver->options */
#define RX_O_BOUND 0x00000001 /* receiver already bound */
#define RX_O_INHERITED 0x00000002 /* inherited FD from the parent process (fd@) */
+#define RX_O_FOREIGN 0x00000004 /* receives on foreign addresses */
+#define RX_O_V6ONLY 0x00000008 /* binds to IPv6 addresses only */
/* This describes a receiver with all its characteristics (address, options, etc) */
struct receiver {
diff --git a/src/proto_tcp.c b/src/proto_tcp.c
index db997fda2..4431a6f15 100644
--- a/src/proto_tcp.c
+++ b/src/proto_tcp.c
@@ -577,6 +577,19 @@ int tcp_bind_listener(struct listener *listener, char *errmsg, int errlen)
if (listener->rx.options & RX_O_BOUND)
goto bound;
+ if (listener->options & LI_O_FOREIGN)
+ listener->rx.options |= RX_O_FOREIGN;
+
+ if (listener->rx.addr.ss_family == AF_INET6) {
+ /* Prepare to match the v6only option against what we really want. Note
+ * that sadly the two options are not exclusive to each other and that
+ * v6only is stronger than v4v6.
+ */
+ if ((listener->options & LI_O_V6ONLY) ||
+ (sock_inet6_v6only_default && !(listener->options & LI_O_V4V6)))
+ listener->rx.options |= RX_O_V6ONLY;
+ }
+
if (listener->rx.fd == -1)
listener->rx.fd = sock_find_compatible_fd(listener);
diff --git a/src/sock.c b/src/sock.c
index 6e078c0ff..3aa72832e 100644
--- a/src/sock.c
+++ b/src/sock.c
@@ -372,18 +372,11 @@ int sock_find_compatible_fd(const struct listener *l)
if (l->rx.addr.ss_family == AF_CUST_UDP4 || l->rx.addr.ss_family == AF_CUST_UDP6)
options |= SOCK_XFER_OPT_DGRAM;
- if (l->options & LI_O_FOREIGN)
+ if (l->rx.options & RX_O_FOREIGN)
options |= SOCK_XFER_OPT_FOREIGN;
- if (l->rx.addr.ss_family == AF_INET6) {
- /* Prepare to match the v6only option against what we really want. Note
- * that sadly the two options are not exclusive to each other and that
- * v6only is stronger than v4v6.
- */
- if ((l->options & LI_O_V6ONLY) ||
- (sock_inet6_v6only_default && !(l->options & LI_O_V4V6)))
- options |= SOCK_XFER_OPT_V6ONLY;
- }
+ if (l->rx.options & RX_O_V6ONLY)
+ options |= SOCK_XFER_OPT_V6ONLY;
if (l->rx.interface)
if_namelen = strlen(l->rx.interface);