Blame SOURCES/0003-conf-udp-Allow-any-loopback-address-to-be-used-as-re.patch

f07426
From ae0004f591d816f1b6e78c57c3d9530098f123b0 Mon Sep 17 00:00:00 2001
f07426
From: Stefano Brivio <sbrivio@redhat.com>
f07426
Date: Thu, 23 Feb 2023 16:41:47 +0000
f07426
Subject: [PATCH 03/20] conf, udp: Allow any loopback address to be used as
f07426
 resolver
f07426
f07426
Andrea reports that with a Fedora 37 guest running on a Fedora 37
f07426
host, both using systemd-resolved, with passt connecting them,
f07426
running with default options, DNS queries don't work.
f07426
f07426
systemd-resolved on the host is reachable only at the loopback
f07426
address 127.0.0.53.
f07426
f07426
We advertise the default gateway address to the guest as resolver,
f07426
because our local address is of course unreachable from there, which
f07426
means we see DNS queries directed to the default gateway, and we
f07426
redirect them to 127.0.0.1. However, systemd-resolved doesn't answer
f07426
on 127.0.0.1.
f07426
f07426
To fix this, set @dns_match to the address of the default gateway,
f07426
unless a different resolver address is explicitly configured, so that
f07426
we know we explicitly have to map DNS queries, in this case, to the
f07426
address of the local resolver.
f07426
f07426
This means that in udp_tap_handler() we need to check, first, if
f07426
the destination address of packets matches @dns_match: even if it's
f07426
the address of the local gateway, we want to map that to a specific
f07426
address, which isn't necessarily 127.0.0.1.
f07426
f07426
Do the same for IPv6 for consistency, even though IPv6 defines a
f07426
single loopback address.
f07426
f07426
Reported-by: Andrea Bolognani <abologna@redhat.com>
f07426
Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
f07426
Tested-by: Andrea Bolognani <abologna@redhat.com>
f07426
Reviewed-by: David Gibson <david@gibson.dropbear.id.au>
f07426
(cherry picked from commit bad252687271c0255f6a077f19cbc19aa0427f8d)
f07426
---
f07426
 conf.c |  6 ++++++
f07426
 udp.c  | 20 ++++++++++----------
f07426
 2 files changed, 16 insertions(+), 10 deletions(-)
f07426
f07426
diff --git a/conf.c b/conf.c
f07426
index ed25e35..37f25d6 100644
f07426
--- a/conf.c
f07426
+++ b/conf.c
f07426
@@ -395,6 +395,9 @@ static void add_dns4(struct ctx *c, struct in_addr *addr, struct in_addr **conf)
f07426
 		if (!c->no_map_gw) {
f07426
 			**conf = c->ip4.gw;
f07426
 			(*conf)++;
f07426
+
f07426
+			if (IN4_IS_ADDR_UNSPECIFIED(&c->ip4.dns_match))
f07426
+				c->ip4.dns_match = c->ip4.gw;
f07426
 		}
f07426
 	} else {
f07426
 		**conf = *addr;
f07426
@@ -419,6 +422,9 @@ static void add_dns6(struct ctx *c,
f07426
 		if (!c->no_map_gw) {
f07426
 			memcpy(*conf, &c->ip6.gw, sizeof(**conf));
f07426
 			(*conf)++;
f07426
+
f07426
+			if (IN6_IS_ADDR_UNSPECIFIED(&c->ip6.dns_match))
f07426
+				memcpy(&c->ip6.dns_match, addr, sizeof(*addr));
f07426
 		}
f07426
 	} else {
f07426
 		memcpy(*conf, addr, sizeof(**conf));
f07426
diff --git a/udp.c b/udp.c
f07426
index 1d65559..20a9ea0 100644
f07426
--- a/udp.c
f07426
+++ b/udp.c
f07426
@@ -857,17 +857,16 @@ int udp_tap_handler(struct ctx *c, int af, const void *addr,
f07426
 
f07426
 		udp_tap_map[V4][src].ts = now->tv_sec;
f07426
 
f07426
-		if (IN4_ARE_ADDR_EQUAL(&s_in.sin_addr, &c->ip4.gw) &&
f07426
-		    !c->no_map_gw) {
f07426
+		if (IN4_ARE_ADDR_EQUAL(&s_in.sin_addr, &c->ip4.dns_match) &&
f07426
+		    ntohs(s_in.sin_port) == 53) {
f07426
+			s_in.sin_addr = c->ip4.dns_host;
f07426
+		} else if (IN4_ARE_ADDR_EQUAL(&s_in.sin_addr, &c->ip4.gw) &&
f07426
+			   !c->no_map_gw) {
f07426
 			if (!(udp_tap_map[V4][dst].flags & PORT_LOCAL) ||
f07426
 			    (udp_tap_map[V4][dst].flags & PORT_LOOPBACK))
f07426
 				s_in.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
f07426
 			else
f07426
 				s_in.sin_addr = c->ip4.addr_seen;
f07426
-		} else if (IN4_ARE_ADDR_EQUAL(&s_in.sin_addr,
f07426
-					      &c->ip4.dns_match) &&
f07426
-			   ntohs(s_in.sin_port) == 53) {
f07426
-			s_in.sin_addr = c->ip4.dns_host;
f07426
 		}
f07426
 	} else {
f07426
 		s_in6 = (struct sockaddr_in6) {
f07426
@@ -880,7 +879,11 @@ int udp_tap_handler(struct ctx *c, int af, const void *addr,
f07426
 		sa = (struct sockaddr *)&s_in6;
f07426
 		sl = sizeof(s_in6);
f07426
 
f07426
-		if (IN6_ARE_ADDR_EQUAL(addr, &c->ip6.gw) && !c->no_map_gw) {
f07426
+		if (IN6_ARE_ADDR_EQUAL(addr, &c->ip6.dns_match) &&
f07426
+		    ntohs(s_in6.sin6_port) == 53) {
f07426
+			s_in6.sin6_addr = c->ip6.dns_host;
f07426
+		} else if (IN6_ARE_ADDR_EQUAL(addr, &c->ip6.gw) &&
f07426
+			   !c->no_map_gw) {
f07426
 			if (!(udp_tap_map[V6][dst].flags & PORT_LOCAL) ||
f07426
 			    (udp_tap_map[V6][dst].flags & PORT_LOOPBACK))
f07426
 				s_in6.sin6_addr = in6addr_loopback;
f07426
@@ -888,9 +891,6 @@ int udp_tap_handler(struct ctx *c, int af, const void *addr,
f07426
 				s_in6.sin6_addr = c->ip6.addr;
f07426
 			else
f07426
 				s_in6.sin6_addr = c->ip6.addr_seen;
f07426
-		} else if (IN6_ARE_ADDR_EQUAL(addr, &c->ip6.dns_match) &&
f07426
-			   ntohs(s_in6.sin6_port) == 53) {
f07426
-			s_in6.sin6_addr = c->ip6.dns_host;
f07426
 		} else if (IN6_IS_ADDR_LINKLOCAL(&s_in6.sin6_addr)) {
f07426
 			bind_addr = &c->ip6.addr_ll;
f07426
 		}
f07426
-- 
f07426
2.39.2
f07426