public inbox for passt-dev@passt.top
 help / color / mirror / code / Atom feed
From: David Gibson <david@gibson.dropbear.id.au>
To: Stefano Brivio <sbrivio@redhat.com>, passt-dev@passt.top
Cc: David Gibson <david@gibson.dropbear.id.au>
Subject: [PATCH 2/7] udp: Simplify setting od destination IPv6 address for inbound packets
Date: Mon,  1 May 2023 21:06:57 +1000	[thread overview]
Message-ID: <20230501110702.3915529-3-david@gibson.dropbear.id.au> (raw)
In-Reply-To: <20230501110702.3915529-1-david@gibson.dropbear.id.au>

Depending on several possible NAT situations, udp_update_hdr6() has a few
different paths for setting the destination IPv6 address.  However, this
isn't really separate from the selection of the IPv6 source address:
if the adjusted source address is link-local then we need to use a link
local destination, otherwise we need the global destination address.

This fixes a small bug: it's theoretically possible, although unlikely, for
the dns_match address to be link-local, in which case the previous code
would have used the wrong destination.

This does do slightly more work in the case of NATting packets originating
on the host.  Currently we always NAT those to a link-local address so we
could statically set a link-local destination address, but we now recheck.
However, as well as being simpler, the new approach is more robust if we
want to allow non-link-local NAT-to-host addresses, which we do plan to in
future.

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
---
 udp.c | 13 +++++--------
 1 file changed, 5 insertions(+), 8 deletions(-)

diff --git a/udp.c b/udp.c
index 361f24c..9c96c0f 100644
--- a/udp.c
+++ b/udp.c
@@ -640,18 +640,13 @@ static size_t udp_update_hdr6(const struct ctx *c, int n, in_port_t dstport,
 
 	b->ip6h.payload_len = htons(udp6_l2_mh_sock[n].msg_len + sizeof(b->uh));
 
-	if (IN6_IS_ADDR_LINKLOCAL(src)) {
-		b->ip6h.daddr = c->ip6.addr_ll_seen;
-	} else if (!IN6_IS_ADDR_UNSPECIFIED(&c->ip6.dns_match) &&
+	if (!IN6_IS_ADDR_UNSPECIFIED(&c->ip6.dns_match) &&
 		   IN6_ARE_ADDR_EQUAL(src, &c->ip6.dns_host) &&
 		   src_port == 53) {
-		b->ip6h.daddr = c->ip6.addr_seen;
 		src = &c->ip6.dns_match;
 	} else if (IN6_IS_ADDR_LOOPBACK(src)			||
 		   IN6_ARE_ADDR_EQUAL(src, &c->ip6.addr_seen)	||
 		   IN6_ARE_ADDR_EQUAL(src, &c->ip6.addr)) {
-		b->ip6h.daddr = c->ip6.addr_ll_seen;
-
 		udp_tap_map[V6][src_port].ts = now->tv_sec;
 		udp_tap_map[V6][src_port].flags |= PORT_LOCAL;
 
@@ -671,11 +666,13 @@ static size_t udp_update_hdr6(const struct ctx *c, int n, in_port_t dstport,
 			src = &c->ip6.gw;
 		else
 			src = &c->ip6.addr_ll;
-	} else {
-		b->ip6h.daddr = c->ip6.addr_seen;
 	}
 
 	b->ip6h.saddr = *src;
+	if (IN6_IS_ADDR_LINKLOCAL(src))
+		b->ip6h.daddr = c->ip6.addr_ll_seen;
+	else
+		b->ip6h.daddr = c->ip6.addr_seen;
 
 	b->uh.source = b->s_in6.sin6_port;
 	b->uh.dest = htons(dstport);
-- 
@@ -640,18 +640,13 @@ static size_t udp_update_hdr6(const struct ctx *c, int n, in_port_t dstport,
 
 	b->ip6h.payload_len = htons(udp6_l2_mh_sock[n].msg_len + sizeof(b->uh));
 
-	if (IN6_IS_ADDR_LINKLOCAL(src)) {
-		b->ip6h.daddr = c->ip6.addr_ll_seen;
-	} else if (!IN6_IS_ADDR_UNSPECIFIED(&c->ip6.dns_match) &&
+	if (!IN6_IS_ADDR_UNSPECIFIED(&c->ip6.dns_match) &&
 		   IN6_ARE_ADDR_EQUAL(src, &c->ip6.dns_host) &&
 		   src_port == 53) {
-		b->ip6h.daddr = c->ip6.addr_seen;
 		src = &c->ip6.dns_match;
 	} else if (IN6_IS_ADDR_LOOPBACK(src)			||
 		   IN6_ARE_ADDR_EQUAL(src, &c->ip6.addr_seen)	||
 		   IN6_ARE_ADDR_EQUAL(src, &c->ip6.addr)) {
-		b->ip6h.daddr = c->ip6.addr_ll_seen;
-
 		udp_tap_map[V6][src_port].ts = now->tv_sec;
 		udp_tap_map[V6][src_port].flags |= PORT_LOCAL;
 
@@ -671,11 +666,13 @@ static size_t udp_update_hdr6(const struct ctx *c, int n, in_port_t dstport,
 			src = &c->ip6.gw;
 		else
 			src = &c->ip6.addr_ll;
-	} else {
-		b->ip6h.daddr = c->ip6.addr_seen;
 	}
 
 	b->ip6h.saddr = *src;
+	if (IN6_IS_ADDR_LINKLOCAL(src))
+		b->ip6h.daddr = c->ip6.addr_ll_seen;
+	else
+		b->ip6h.daddr = c->ip6.addr_seen;
 
 	b->uh.source = b->s_in6.sin6_port;
 	b->uh.dest = htons(dstport);
-- 
2.40.1


  parent reply	other threads:[~2023-05-01 11:08 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-05-01 11:06 [PATCH 0/7] RFC: Allow NAT-to-host address to be configured explicitly David Gibson
2023-05-01 11:06 ` [PATCH 1/7] udp: Simplify setting of source IPv6 address for inbound packets David Gibson
2023-05-01 11:06 ` David Gibson [this message]
2023-05-04 21:53   ` [PATCH 2/7] udp: Simplify setting od destination " Stefano Brivio
2023-05-01 11:06 ` [PATCH 3/7] nat: Split notion of gateway/router from from guest-visible host address David Gibson
2023-05-01 11:06 ` [PATCH 4/7] nat: Simplify --no-map-gw handling David Gibson
2023-05-01 11:07 ` [PATCH 5/7] nat: Centralise handling of gateway versus link-local address for host NAT David Gibson
2023-05-01 11:07 ` [PATCH 6/7] Allow nat-to-host addresses to be overridden David Gibson
2023-05-01 11:07 ` [PATCH 7/7] nat, test: Test --nat-to-host option David Gibson
2023-05-02 21:52 ` [PATCH 0/7] RFC: Allow NAT-to-host address to be configured explicitly 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=20230501110702.3915529-3-david@gibson.dropbear.id.au \
    --to=david@gibson.dropbear.id.au \
    --cc=passt-dev@passt.top \
    --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).