From mboxrd@z Thu Jan 1 00:00:00 1970 Authentication-Results: passt.top; dmarc=none (p=none dis=none) header.from=gibson.dropbear.id.au Authentication-Results: passt.top; dkim=fail reason="key not found in DNS" header.d=gibson.dropbear.id.au header.i=@gibson.dropbear.id.au header.a=rsa-sha256 header.s=202312 header.b=lW8nP1qx; dkim-atps=neutral Received: from mail.ozlabs.org (mail.ozlabs.org [IPv6:2404:9400:2221:ea00::3]) by passt.top (Postfix) with ESMTPS id C01B35A027F for ; Fri, 16 Aug 2024 07:40:23 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gibson.dropbear.id.au; s=202312; t=1723786807; bh=NdRmXImxOxdpVwC8gRaVrtc+kocoRBjRnOmDdBmS0A8=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=lW8nP1qx7Dbb8Bc0p9WqPH/bJjARkEmcud1lHy3jlpvovi3UBkexkK7I5iLHwrvnW PYahBVj8uHTa5twZFgZid8Ov1VyNMdaVROrSDQixu1/9SkDdzvhylVFUCu+4savHRl AuwPfdsvtvOTGS/9mhkhMMaUEBJEZ/iIeEGrNCldwkUwyf+tdcvoCIrg5CM0WTeZqj XchrU8xRdNwK3rHYeacA9dDPgbL7IO3PXzkJOdfGeIfdlnzxTTVBwrbGj+wdxsQcty xZ/yDbeK+ULyhoBUGqhZTUhMM87RhVCd9uAHMzkYbsX6vlcTEQMJhTHSfXkTEdEuWM ectw5IXLOGVRA== Received: by gandalf.ozlabs.org (Postfix, from userid 1007) id 4WlW6H0Zxpz4x4c; Fri, 16 Aug 2024 15:40:07 +1000 (AEST) From: David Gibson To: Stefano Brivio , passt-dev@passt.top Subject: [PATCH 10/22] conf: Treat --dns addresses as guest visible addresses Date: Fri, 16 Aug 2024 15:39:51 +1000 Message-ID: <20240816054004.1335006-11-david@gibson.dropbear.id.au> X-Mailer: git-send-email 2.46.0 In-Reply-To: <20240816054004.1335006-1-david@gibson.dropbear.id.au> References: <20240816054004.1335006-1-david@gibson.dropbear.id.au> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Message-ID-Hash: FJOSG43EGSWI3VIOE5PDULNR2RJNMVAM X-Message-ID-Hash: FJOSG43EGSWI3VIOE5PDULNR2RJNMVAM X-MailFrom: dgibson@gandalf.ozlabs.org X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; emergency; loop; banned-address; member-moderation; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; digests; suspicious-header CC: Paul Holzinger , David Gibson X-Mailman-Version: 3.3.8 Precedence: list List-Id: Development discussion and patches for passt Archived-At: Archived-At: List-Archive: List-Archive: List-Help: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: Although it's not 100% explicit in the man page, addresses given to the --dns option are intended to be addresses as seen by the guest. This differs from addresses taken from the host's /etc/resolv.conf, which must be translated to to guest accessible versions in some cases. Our implementation is currently inconsistent on this: when using --dns-forward, you must usually also give --dns with the matching address, which is meaningful only in the guest's address view. However if you give --dns with a loopback addres, it will be translated like a host view address. Move the remapping logic for DNS addresses out of add_dns4() and add_dns6() into add_dns_resolv() so that it is only applied for host nameserver addresses, not for nameservers given explicitly with --dns. Signed-off-by: David Gibson --- conf.c | 88 ++++++++++++++++++++++++++++----------------------------- passt.1 | 14 +++++---- 2 files changed, 52 insertions(+), 50 deletions(-) diff --git a/conf.c b/conf.c index bf61c143..3c102bcf 100644 --- a/conf.c +++ b/conf.c @@ -353,7 +353,7 @@ bind_all_fail: /** * add_dns4() - Possibly add the IPv4 address of a DNS resolver to configuration * @c: Execution context - * @addr: Address found in /etc/resolv.conf + * @addr: Guest nameserver IPv4 address * @idx: Index of free entry in array of IPv4 resolvers * * Return: Number of entries added (0 or 1) @@ -361,64 +361,29 @@ bind_all_fail: static unsigned add_dns4(struct ctx *c, const struct in_addr *addr, unsigned idx) { - unsigned added = 0; - if (idx >= ARRAY_SIZE(c->ip4.dns)) return 0; - /* Guest or container can only access local addresses via redirect */ - if (IN4_IS_ADDR_LOOPBACK(addr)) { - if (!c->no_map_gw) { - c->ip4.dns[idx] = c->ip4.gw; - added++; - - if (IN4_IS_ADDR_UNSPECIFIED(&c->ip4.dns_match)) - c->ip4.dns_match = c->ip4.gw; - } - } else { - c->ip4.dns[idx] = *addr; - added++; - } - - if (IN4_IS_ADDR_UNSPECIFIED(&c->ip4.dns_host)) - c->ip4.dns_host = *addr; - - return added; + c->ip4.dns[idx] = *addr; + return 1; } /** * add_dns6() - Possibly add the IPv6 address of a DNS resolver to configuration * @c: Execution context - * @addr: Address found in /etc/resolv.conf + * @addr: Guest nameserver IPv6 address * @idx: Index of free entry in array of IPv6 resolvers * * Return: Number of entries added (0 or 1) */ -static unsigned add_dns6(struct ctx *c, struct in6_addr *addr, unsigned idx) +static unsigned add_dns6(struct ctx *c, const struct in6_addr *addr, + unsigned idx) { - unsigned added = 0; - if (idx >= ARRAY_SIZE(c->ip6.dns)) return 0; - /* Guest or container can only access local addresses via redirect */ - if (IN6_IS_ADDR_LOOPBACK(addr)) { - if (!c->no_map_gw) { - c->ip6.dns[idx] = c->ip6.gw; - added++; - - if (IN6_IS_ADDR_UNSPECIFIED(&c->ip6.dns_match)) - c->ip6.dns_match = c->ip6.gw; - } - } else { - c->ip6.dns[idx] = *addr; - added++; - } - - if (IN6_IS_ADDR_UNSPECIFIED(&c->ip6.dns_host)) - c->ip6.dns_host = *addr; - - return added; + c->ip6.dns[idx] = *addr; + return 1; } /** @@ -437,11 +402,44 @@ static void add_dns_resolv(struct ctx *c, const char *nameserver, struct in6_addr ns6; struct in_addr ns4; - if (idx4 && inet_pton(AF_INET, nameserver, &ns4)) + if (idx4 && inet_pton(AF_INET, nameserver, &ns4)) { + if (IN4_IS_ADDR_UNSPECIFIED(&c->ip4.dns_host)) + c->ip4.dns_host = ns4; + + /* Guest or container can only access local addresses via + * redirect + */ + if (IN4_IS_ADDR_LOOPBACK(&ns4)) { + if (c->no_map_gw) + return; + + ns4 = c->ip4.gw; + if (IN4_IS_ADDR_UNSPECIFIED(&c->ip4.dns_match)) + c->ip4.dns_match = c->ip4.gw; + } + *idx4 += add_dns4(c, &ns4, *idx4); + } + + if (idx6 && inet_pton(AF_INET6, nameserver, &ns6)) { + if (IN6_IS_ADDR_UNSPECIFIED(&c->ip6.dns_host)) + c->ip6.dns_host = ns6; + + /* Guest or container can only access local addresses via + * redirect + */ + if (IN6_IS_ADDR_LOOPBACK(&ns6)) { + if (c->no_map_gw) + return; + + ns6 = c->ip6.gw; + + if (IN6_IS_ADDR_UNSPECIFIED(&c->ip6.dns_match)) + c->ip6.dns_match = c->ip6.gw; + } - if (idx6 && inet_pton(AF_INET6, nameserver, &ns6)) *idx6 += add_dns6(c, &ns6, *idx6); + } } /** diff --git a/passt.1 b/passt.1 index 3062b719..dca433b6 100644 --- a/passt.1 +++ b/passt.1 @@ -236,11 +236,15 @@ interface will be chosen instead. .TP .BR \-D ", " \-\-dns " " \fIaddr -Use \fIaddr\fR (IPv4 or IPv6) for DHCP, DHCPv6, NDP or DNS forwarding, as -configured (see options \fB--no-dhcp-dns\fR, \fB--dhcp-dns\fR, -\fB--dns-forward\fR) instead of reading addresses from \fI/etc/resolv.conf\fR. -This option can be specified multiple times. Specifying \fB-D none\fR disables -usage of DNS addresses altogether. +Instruct the guest (via DHCP, DHVPv6 or NDP) to use \fIaddr\fR (IPv4 +or IPv6) as a nameserver, as configured (see options +\fB--no-dhcp-dns\fR, \fB--dhcp-dns\fR) instead of reading addresses +from \fI/etc/resolv.conf\fR. This option can be specified multiple +times. Specifying \fB-D none\fR disables usage of DNS addresses +altogether. Unlike addresses from \fI/etc/resolv.conf\fR, \fIaddr\fR +is given to the guest without remapping. For example \fB--dns +127.0.0.1\fR will instruct the guest to use itself as nameserver, not +the host. .TP .BR \-\-dns-forward " " \fIaddr -- 2.46.0