From: David Gibson <david@gibson.dropbear.id.au>
To: Stefano Brivio <sbrivio@redhat.com>
Cc: passt-dev@passt.top, Paul Holzinger <pholzing@redhat.com>
Subject: Re: [PATCH 2/3] conf: Split the notions of read DNS addresses and offered ones
Date: Thu, 3 Nov 2022 14:37:18 +1100 [thread overview]
Message-ID: <Y2M3bi2X5rhknGvT@yekko> (raw)
In-Reply-To: <20221102230443.377446-3-sbrivio@redhat.com>
[-- Attachment #1: Type: text/plain, Size: 8878 bytes --]
On Thu, Nov 03, 2022 at 12:04:42AM +0100, Stefano Brivio wrote:
> With --dns-forward, if the host has a loopback address configured as
> DNS server, we should actually use it to forward queries, but, if
> --no-map-gw is passed, we shouldn't offer the same address via DHCP,
> NDP and DHCPv6, because it's not going to be reachable.
>
> Problematic configuration: systemd-resolved configuring the usual
> 127.0.0.53 on the host, and --dns-forward specified with an unrelated
> address. We still want to forward queries to 127.0.0.53, so we can't
> drop it from the addresses in IPv4 and IPv6 context,
I'm not entirely sure what you mean by that.
> but we shouldn't
> offer that address either.
>
> With this change, I'm only covering the case of automatically
> configured DNS servers from /etc/resolv.conf. We could extend this to
> addresses configured with command-line options, but I don't really
> see a likely use case at this point.
>
> Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
> ---
> conf.c | 50 ++++++++++++++++++++++++++++++++++----------------
> dhcp.c | 5 +++--
> dhcpv6.c | 5 +++--
> ndp.c | 6 +++---
> passt.h | 8 ++++++--
> 5 files changed, 49 insertions(+), 25 deletions(-)
>
> diff --git a/conf.c b/conf.c
> index 5b88547..c4e1030 100644
> --- a/conf.c
> +++ b/conf.c
> @@ -355,10 +355,11 @@ overlap:
> */
> static void get_dns(struct ctx *c)
> {
> + uint32_t *dns4 = &c->ip4.dns[0], *dns4_send = &c->ip4.dns_send[0];
> + struct in6_addr *dns6_send = &c->ip6.dns_send[0];
> int dns4_set, dns6_set, dnss_set, dns_set, fd;
> struct in6_addr *dns6 = &c->ip6.dns[0];
> struct fqdn *s = c->dns_search;
> - uint32_t *dns4 = &c->ip4.dns[0];
> struct lineread resolvconf;
> int line_len;
> char *line, *p, *end;
> @@ -388,30 +389,45 @@ static void get_dns(struct ctx *c)
> if (!dns4_set &&
> dns4 - &c->ip4.dns[0] < ARRAY_SIZE(c->ip4.dns) - 1 &&
> inet_pton(AF_INET, p + 1, dns4)) {
> - /* We can only access local addresses via the gw redirect */
> - if (ntohl(*dns4) >> IN_CLASSA_NSHIFT == IN_LOOPBACKNET) {
> - if (c->no_map_gw) {
> - *dns4 = 0;
> + /* Guest or container can only access local
> + * addresses via local redirect
> + */
> + if (IPV4_IS_LOOPBACK(ntohl(*dns4))) {
> + if (c->no_map_gw)
> continue;
In this case shouldn't you still be recording the local address in the
dns[] array (but not dns_send[]) since it's a valid nameserver for the
host. In which case you'd need to advance the dns4 pointer.
If I'm mistaken and you don't want to record it in the dns[] array,
then shouldn't you clear it (because otherwise you will record it if
this is the last "nameserver" line).
> - }
> - *dns4 = c->ip4.gw;
> +
> + *dns4_send = c->ip4.gw;
> + } else {
> + *dns4_send = *dns4;
> }
I think it would be clearer to update *dns4 if necessary, then
set *dns4_send = *dns4 outside the if statement.
> +
> + dns4_send++;
> dns4++;
> - *dns4 = 0;
> +
> + *dns4 = *dns4_send = 0;
> }
>
> if (!dns6_set &&
> dns6 - &c->ip6.dns[0] < ARRAY_SIZE(c->ip6.dns) - 1 &&
> inet_pton(AF_INET6, p + 1, dns6)) {
> - /* We can only access local addresses via the gw redirect */
> + /* Guest or container can only access local
> + * addresses via local redirect
> + */
> if (IN6_IS_ADDR_LOOPBACK(dns6)) {
> - if (c->no_map_gw) {
> - memset(dns6, 0, sizeof(*dns6));
> + if (c->no_map_gw)
> continue;
> - }
> - memcpy(dns6, &c->ip6.gw, sizeof(*dns6));
> +
> + memcpy(dns6_send, &c->ip6.gw,
> + sizeof(*dns6_send));
> + } else {
> + memcpy(dns6_send, &c->ip6.gw,
> + sizeof(*dns6_send));
> }
> +
> + dns6_send++;
> dns6++;
> +
> + memset(dns6_send, 0, sizeof(*dns6_send));
> memset(dns6, 0, sizeof(*dns6));
> }
> } else if (!dnss_set && strstr(line, "search ") == line &&
> @@ -832,10 +848,11 @@ static void conf_print(const struct ctx *c)
> inet_ntop(AF_INET, &c->ip4.gw, buf4, sizeof(buf4)));
> }
>
> - for (i = 0; c->ip4.dns[i]; i++) {
> + for (i = 0; c->ip4.dns_send[i]; i++) {
> if (!i)
> info("DNS:");
> - inet_ntop(AF_INET, &c->ip4.dns[i], buf4, sizeof(buf4));
> + inet_ntop(AF_INET, &c->ip4.dns_send[i], buf4,
> + sizeof(buf4));
> info(" %s", buf4);
> }
>
> @@ -866,7 +883,8 @@ static void conf_print(const struct ctx *c)
> inet_ntop(AF_INET6, &c->ip6.addr_ll, buf6, sizeof(buf6)));
>
> dns6:
> - for (i = 0; !IN6_IS_ADDR_UNSPECIFIED(&c->ip6.dns[i]); i++) {
> + for (i = 0; !IN6_IS_ADDR_UNSPECIFIED(&c->ip6.dns_send[i]);
> + i++) {
> if (!i)
> info("DNS:");
> inet_ntop(AF_INET6, &c->ip6.dns[i], buf6, sizeof(buf6));
> diff --git a/dhcp.c b/dhcp.c
> index d22698a..e816eb6 100644
> --- a/dhcp.c
> +++ b/dhcp.c
> @@ -355,8 +355,9 @@ int dhcp(const struct ctx *c, const struct pool *p)
> opts[26].s[1] = c->mtu % 256;
> }
>
> - for (i = 0, opts[6].slen = 0; !c->no_dhcp_dns && c->ip4.dns[i]; i++) {
> - ((uint32_t *)opts[6].s)[i] = c->ip4.dns[i];
> + opts[6].slen = 0;
> + for (i = 0; !c->no_dhcp_dns && c->ip4.dns_send[i]; i++) {
> + ((uint32_t *)opts[6].s)[i] = c->ip4.dns_send[i];
> opts[6].slen += sizeof(uint32_t);
> }
>
> diff --git a/dhcpv6.c b/dhcpv6.c
> index e763aed..67262e6 100644
> --- a/dhcpv6.c
> +++ b/dhcpv6.c
> @@ -379,7 +379,7 @@ static size_t dhcpv6_dns_fill(const struct ctx *c, char *buf, int offset)
> if (c->no_dhcp_dns)
> goto search;
>
> - for (i = 0; !IN6_IS_ADDR_UNSPECIFIED(&c->ip6.dns[i]); i++) {
> + for (i = 0; !IN6_IS_ADDR_UNSPECIFIED(&c->ip6.dns_send[i]); i++) {
> if (!i) {
> srv = (struct opt_dns_servers *)(buf + offset);
> offset += sizeof(struct opt_hdr);
> @@ -387,7 +387,8 @@ static size_t dhcpv6_dns_fill(const struct ctx *c, char *buf, int offset)
> srv->hdr.l = 0;
> }
>
> - memcpy(&srv->addr[i], &c->ip6.dns[i], sizeof(srv->addr[i]));
> + memcpy(&srv->addr[i], &c->ip6.dns_send[i],
> + sizeof(srv->addr[i]));
> srv->hdr.l += sizeof(srv->addr[i]);
> offset += sizeof(srv->addr[i]);
> }
> diff --git a/ndp.c b/ndp.c
> index 80e1f19..6d79477 100644
> --- a/ndp.c
> +++ b/ndp.c
> @@ -121,7 +121,7 @@ int ndp(struct ctx *c, const struct icmp6hdr *ih, const struct in6_addr *saddr)
> if (c->no_dhcp_dns)
> goto dns_done;
>
> - for (n = 0; !IN6_IS_ADDR_UNSPECIFIED(&c->ip6.dns[n]); n++);
> + for (n = 0; !IN6_IS_ADDR_UNSPECIFIED(&c->ip6.dns_send[n]); n++);
> if (n) {
> *p++ = 25; /* RDNSS */
> *p++ = 1 + 2 * n; /* length */
> @@ -130,8 +130,8 @@ int ndp(struct ctx *c, const struct icmp6hdr *ih, const struct in6_addr *saddr)
> p += 4;
>
> for (i = 0; i < n; i++) {
> - memcpy(p, &c->ip6.dns[i], 16); /* address */
> - p += 16;
> + memcpy(p, &c->ip6.dns_send[i], 16);
> + p += 16; /* address */
> }
>
> for (n = 0; *c->dns_search[n].n; n++)
> diff --git a/passt.h b/passt.h
> index 67281db..9f9bf3b 100644
> --- a/passt.h
> +++ b/passt.h
> @@ -101,7 +101,8 @@ enum passt_modes {
> * @addr_seen: Latest IPv4 address seen as source from tap
> * @mask: IPv4 netmask, network order
> * @gw: Default IPv4 gateway, network order
> - * @dns: IPv4 DNS addresses, zero-terminated, network order
> + * @dns: Host IPv4 DNS addresses, zero-terminated, network order
> + * @dns_send: Offered IPv4 DNS, zero-terminated, network order
> * @dns_fwd: Address forwarded (UDP) to first IPv4 DNS, network order
> */
> struct ip4_ctx {
> @@ -110,6 +111,7 @@ struct ip4_ctx {
> uint32_t mask;
> uint32_t gw;
> uint32_t dns[MAXNS + 1];
> + uint32_t dns_send[MAXNS + 1];
> uint32_t dns_fwd;
> };
>
> @@ -120,7 +122,8 @@ struct ip4_ctx {
> * @addr_seen: Latest IPv6 global/site address seen as source from tap
> * @addr_ll_seen: Latest IPv6 link-local address seen as source from tap
> * @gw: Default IPv6 gateway
> - * @dns: IPv6 DNS addresses, zero-terminated
> + * @dns: Host IPv6 DNS addresses, zero-terminated
> + * @dns_send: Offered IPv6 DNS addresses, zero-terminated
> * @dns_fwd: Address forwarded (UDP) to first IPv6 DNS, network order
> */
> struct ip6_ctx {
> @@ -130,6 +133,7 @@ struct ip6_ctx {
> struct in6_addr addr_ll_seen;
> struct in6_addr gw;
> struct in6_addr dns[MAXNS + 1];
> + struct in6_addr dns_send[MAXNS + 1];
> struct in6_addr dns_fwd;
> };
>
--
David Gibson | I'll have my music baroque, and my code
david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_
| _way_ _around_!
http://www.ozlabs.org/~dgibson
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
next prev parent reply other threads:[~2022-11-03 3:42 UTC|newest]
Thread overview: 19+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-11-02 23:04 [PATCH 0/3] Fixes and workarounds for pasta with Podman in Google Cloud Stefano Brivio
2022-11-02 23:04 ` [PATCH 1/3] conf: Consistency check between configured IPv4 netmask and gateway Stefano Brivio
2022-11-03 3:17 ` David Gibson
2022-11-03 6:39 ` Stefano Brivio
2022-11-02 23:04 ` [PATCH 2/3] conf: Split the notions of read DNS addresses and offered ones Stefano Brivio
2022-11-03 3:37 ` David Gibson [this message]
2022-11-03 6:42 ` Stefano Brivio
2022-11-02 23:04 ` [PATCH 3/3] udp: Check for answers to forwarded DNS queries before handling local redirects Stefano Brivio
2022-11-03 3:42 ` David Gibson
2022-11-03 6:42 ` Stefano Brivio
2022-11-05 1:19 ` David Gibson
2022-11-06 22:22 ` Stefano Brivio
2022-11-07 1:08 ` David Gibson
2022-11-07 9:51 ` Stefano Brivio
2022-11-08 5:51 ` David Gibson
2022-11-08 6:22 ` Stefano Brivio
2022-11-10 4:30 ` David Gibson
2022-11-03 3:13 ` [PATCH 0/3] Fixes and workarounds for pasta with Podman in Google Cloud David Gibson
2022-11-03 6:36 ` Stefano Brivio
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=Y2M3bi2X5rhknGvT@yekko \
--to=david@gibson.dropbear.id.au \
--cc=passt-dev@passt.top \
--cc=pholzing@redhat.com \
--cc=sbrivio@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
Code repositories for project(s) associated with this public inbox
https://passt.top/passt
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for IMAP folder(s).