-T and -U options don't allow specifying a listening address. Usually this
will listen on *%lo in the guest. However on kernels without unprivileged
SO_BINDTODEVICE that's not possible so we instead listen separately on
127.0.0.1 and ::1.
Currently that's handled at the point we actually set up the listens, we
record both address and ifname as NULL in the forwarding table entry. That
will cause trouble for future extensions we want, so update this to
accurately create the forwarding table: either a single entry with ifname
== "lo" or two entries with address of 127.0.0.1 and ::1.
As a bonus, this gives the user a warning if they specify an explicit
outbound forwarding on a kernel without SO_BINDTODEVICE. The existing
warning for missing SO_BINDTODEVICE (incorrectly) only covers the case of
-T auto or -U auto.
Signed-off-by: David Gibson
---
conf.c | 38 ++++++++++++++++++++++++++++++--------
1 file changed, 30 insertions(+), 8 deletions(-)
diff --git a/conf.c b/conf.c
index 88971d04..b24ab407 100644
--- a/conf.c
+++ b/conf.c
@@ -157,12 +157,6 @@ static void conf_ports_range_except(const struct ctx *c, char optname,
optname, optarg);
}
- if (ifname && c->no_bindtodevice) {
- die(
-"Device binding for '-%c %s' unsupported (requires kernel 5.7+)",
- optname, optarg);
- }
-
for (base = first; base <= last; base++) {
if (bitmap_isset(exclude, base))
continue;
@@ -204,8 +198,27 @@ static void conf_ports_range_except(const struct ctx *c, char optname,
}
}
- fwd_table_add(fwd, flags, addr, ifname,
- base, i - 1, base + delta);
+ if ((optname == 'T' || optname == 'U') && c->no_bindtodevice) {
+ /* FIXME: Once the fwd bitmaps are removed, move this
+ * workaround to the caller
+ */
+ ASSERT(!addr && ifname && !strcmp(ifname, "lo"));
+ warn(
+"SO_BINDTODEVICE unavailable, forwarding only 127.0.0.1 and ::1 for '-%c %s'",
+ optname, optarg);
+
+ if (c->ifi4) {
+ fwd_table_add(fwd, flags, &inany_loopback4, NULL,
+ base, i - 1, base + delta);
+ }
+ if (c->ifi6) {
+ fwd_table_add(fwd, flags, &inany_loopback6, NULL,
+ base, i - 1, base + delta);
+ }
+ } else {
+ fwd_table_add(fwd, flags, addr, ifname,
+ base, i - 1, base + delta);
+ }
base = i - 1;
}
@@ -352,6 +365,15 @@ static void conf_ports(const struct ctx *c, char optname, const char *optarg,
}
} while ((p = next_chunk(p, ',')));
+ if (ifname && c->no_bindtodevice) {
+ die(
+"Device binding for '-%c %s' unsupported (requires kernel 5.7+)",
+ optname, optarg);
+ }
+ /* Outbound forwards come from guest loopback */
+ if ((optname == 'T' || optname == 'U') && !ifname)
+ ifname = "lo";
+
if (exclude_only) {
/* Exclude ephemeral ports */
for (i = 0; i < NUM_PORTS; i++)
--
2.52.0