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/6] inany: Better helpers for using inany and specific family addrs together
Date: Tue, 21 May 2024 15:57:04 +1000	[thread overview]
Message-ID: <20240521055708.1150050-3-david@gibson.dropbear.id.au> (raw)
In-Reply-To: <20240521055708.1150050-1-david@gibson.dropbear.id.au>

This adds some extra inany helpers for comparing an inany address to
addresses of a specific family (including special addresses), and building
an inany from an IPv4 address (either statically or at runtime).

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
---
 inany.c | 17 ++--------
 inany.h | 97 ++++++++++++++++++++++++++++++++++++++++++++++++++++++---
 tcp.c   | 29 +++++++----------
 3 files changed, 106 insertions(+), 37 deletions(-)

diff --git a/inany.c b/inany.c
index c8479a75..5e391dc7 100644
--- a/inany.c
+++ b/inany.c
@@ -17,21 +17,8 @@
 #include "siphash.h"
 #include "inany.h"
 
-const union inany_addr inany_loopback4 = {
-	.v4mapped = {
-		.zero = { 0 },
-		.one = { 0xff, 0xff, },
-		.a4 = IN4ADDR_LOOPBACK_INIT,
-	},
-};
-
-const union inany_addr inany_any4 = {
-	.v4mapped = {
-		.zero = { 0 },
-		.one = { 0xff, 0xff, },
-		.a4 = IN4ADDR_ANY_INIT,
-	},
-};
+const union inany_addr inany_loopback4 = INANY_INIT4(IN4ADDR_LOOPBACK_INIT);
+const union inany_addr inany_any4 = INANY_INIT4(IN4ADDR_ANY_INIT);
 
 /** inany_ntop - Convert an IPv[46] address to text format
  * @src:	IPv[46] address
diff --git a/inany.h b/inany.h
index 407690e2..47b66fa9 100644
--- a/inany.h
+++ b/inany.h
@@ -43,6 +43,17 @@ extern const union inany_addr inany_any4;
 #define in4addr_loopback	(inany_loopback4.v4mapped.a4)
 #define in4addr_any		(inany_any4.v4mapped.a4)
 
+#define INANY_INIT4(a4init)	{					\
+					.v4mapped = {			\
+						.zero = { 0 },		\
+						.one = { 0xff, 0xff },	\
+						.a4 = a4init,		\
+					},				\
+				}
+
+#define inany_from_v4(a4)	\
+	((union inany_addr)INANY_INIT4((a4)))
+
 /** union sockaddr_inany - Either a sockaddr_in or a sockaddr_in6
  * @sa_family:	Address family, AF_INET or AF_INET6
  * @sa:		Plain struct sockaddr (useful to avoid casts)
@@ -79,16 +90,84 @@ static inline bool inany_equals(const union inany_addr *a,
 	return IN6_ARE_ADDR_EQUAL(&a->a6, &b->a6);
 }
 
+/** inany_equals4 - Compare an IPv[46] address to an IPv4 address
+ * @a:		IPv[46] addresses
+ * @b:		IPv4 address
+ *
+ * Return: true if @a and @b are the same address
+ */
+static inline bool inany_equals4(const union inany_addr *a,
+				 const struct in_addr *b)
+{
+	const struct in_addr *a4 = inany_v4(a);
+
+	return a4 && IN4_ARE_ADDR_EQUAL(a4, b);
+}
+
+/** inany_equals6 - Compare an IPv[46] address to an IPv6 address
+ * @a:		IPv[46] addresses
+ * @b:		IPv6 address
+ *
+ * Return: true if @a and @b are the same address
+ */
+static inline bool inany_equals6(const union inany_addr *a,
+				 const struct in6_addr *b)
+{
+	return IN6_ARE_ADDR_EQUAL(&a->a6, b);
+}
+
+/** inany_is_loopback4() - Check if address is IPv4 loopback
+ * @a:		IPv[46] address
+ *
+ * Return: true if @a is in 127.0.0.1/8
+ */
+static inline bool inany_is_loopback4(const union inany_addr *a)
+{
+	const struct in_addr *v4 = inany_v4(a);
+
+	return v4 && IN4_IS_ADDR_LOOPBACK(v4);
+}
+
+/** inany_is_loopback6() - Check if address is IPv6 loopback
+ * @a:		IPv[46] address
+ *
+ * Return: true if @a is in ::1
+ */
+static inline bool inany_is_loopback6(const union inany_addr *a)
+{
+	return IN6_IS_ADDR_LOOPBACK(&a->a6);
+}
+
 /** inany_is_loopback() - Check if address is loopback
  * @a:		IPv[46] address
  *
  * Return: true if @a is either ::1 or in 127.0.0.1/8
  */
 static inline bool inany_is_loopback(const union inany_addr *a)
+{
+	return inany_is_loopback4(a) || inany_is_loopback6(a);
+}
+
+/** inany_is_unspecified4() - Check if address is unspecified IPv4
+ * @a:		IPv[46] address
+ *
+ * Return: true if @a is 0.0.0.0
+ */
+static inline bool inany_is_unspecified4(const union inany_addr *a)
 {
 	const struct in_addr *v4 = inany_v4(a);
 
-	return IN6_IS_ADDR_LOOPBACK(&a->a6) || (v4 && IN4_IS_ADDR_LOOPBACK(v4));
+	return v4 && IN4_IS_ADDR_UNSPECIFIED(v4);
+}
+
+/** inany_is_unspecified6() - Check if address is unspecified IPv6
+ * @a:		IPv[46] address
+ *
+ * Return: true if @a is ::
+ */
+static inline bool inany_is_unspecified6(const union inany_addr *a)
+{
+	return IN6_IS_ADDR_UNSPECIFIED(&a->a6);
 }
 
 /** inany_is_unspecified() - Check if address is unspecified
@@ -98,10 +177,20 @@ static inline bool inany_is_loopback(const union inany_addr *a)
  */
 static inline bool inany_is_unspecified(const union inany_addr *a)
 {
-	const struct in_addr *v4 = inany_v4(a);
+	return inany_is_unspecified4(a) || inany_is_unspecified6(a);
+}
 
-	return IN6_IS_ADDR_UNSPECIFIED(&a->a6) ||
-		(v4 && IN4_IS_ADDR_UNSPECIFIED(v4));
+/* FIXME: consider handling of IPv4 link-local addresses */
+
+/** inany_is_linklocal6() - Check if address is link-local IPv6
+ * @a:		IPv[46] address
+ *
+ * Return: true if @a is in fe80::/10 (IPv6 link local unicast)
+ */
+/* cppcheck-suppress unusedFunction */
+static inline bool inany_is_linklocal6(const union inany_addr *a)
+{
+	return IN6_IS_ADDR_LINKLOCAL(&a->a6);
 }
 
 /** inany_is_multicast() - Check if address is multicast or broadcast
diff --git a/tcp.c b/tcp.c
index a8ba5858..4512af0b 100644
--- a/tcp.c
+++ b/tcp.c
@@ -2687,24 +2687,17 @@ static void tcp_connect_finish(struct ctx *c, struct tcp_tap_conn *conn)
  */
 static void tcp_snat_inbound(const struct ctx *c, union inany_addr *addr)
 {
-	struct in_addr *addr4 = inany_v4(addr);
-
-	if (addr4) {
-		if (IN4_IS_ADDR_LOOPBACK(addr4) ||
-		    IN4_IS_ADDR_UNSPECIFIED(addr4) ||
-		    IN4_ARE_ADDR_EQUAL(addr4, &c->ip4.addr_seen))
-			*addr4 = c->ip4.gw;
-	} else {
-		struct in6_addr *addr6 = &addr->a6;
-
-		if (IN6_IS_ADDR_LOOPBACK(addr6) ||
-		    IN6_ARE_ADDR_EQUAL(addr6, &c->ip6.addr_seen) ||
-		    IN6_ARE_ADDR_EQUAL(addr6, &c->ip6.addr)) {
-			if (IN6_IS_ADDR_LINKLOCAL(&c->ip6.gw))
-				*addr6 = c->ip6.gw;
-			else
-				*addr6 = c->ip6.addr_ll;
-		}
+	if (inany_is_loopback4(addr) ||
+	    inany_is_unspecified4(addr) ||
+	    inany_equals4(addr, &c->ip4.addr_seen)) {
+		*addr = inany_from_v4(c->ip4.gw);
+	} else if (inany_is_loopback6(addr) ||
+		   inany_equals6(addr, &c->ip6.addr_seen) ||
+		   inany_equals6(addr, &c->ip6.addr)) {
+		if (IN6_IS_ADDR_LINKLOCAL(&c->ip6.gw))
+			addr->a6 = c->ip6.gw;
+		else
+			addr->a6 = c->ip6.addr_ll;
 	}
 }
 
-- 
@@ -2687,24 +2687,17 @@ static void tcp_connect_finish(struct ctx *c, struct tcp_tap_conn *conn)
  */
 static void tcp_snat_inbound(const struct ctx *c, union inany_addr *addr)
 {
-	struct in_addr *addr4 = inany_v4(addr);
-
-	if (addr4) {
-		if (IN4_IS_ADDR_LOOPBACK(addr4) ||
-		    IN4_IS_ADDR_UNSPECIFIED(addr4) ||
-		    IN4_ARE_ADDR_EQUAL(addr4, &c->ip4.addr_seen))
-			*addr4 = c->ip4.gw;
-	} else {
-		struct in6_addr *addr6 = &addr->a6;
-
-		if (IN6_IS_ADDR_LOOPBACK(addr6) ||
-		    IN6_ARE_ADDR_EQUAL(addr6, &c->ip6.addr_seen) ||
-		    IN6_ARE_ADDR_EQUAL(addr6, &c->ip6.addr)) {
-			if (IN6_IS_ADDR_LINKLOCAL(&c->ip6.gw))
-				*addr6 = c->ip6.gw;
-			else
-				*addr6 = c->ip6.addr_ll;
-		}
+	if (inany_is_loopback4(addr) ||
+	    inany_is_unspecified4(addr) ||
+	    inany_equals4(addr, &c->ip4.addr_seen)) {
+		*addr = inany_from_v4(c->ip4.gw);
+	} else if (inany_is_loopback6(addr) ||
+		   inany_equals6(addr, &c->ip6.addr_seen) ||
+		   inany_equals6(addr, &c->ip6.addr)) {
+		if (IN6_IS_ADDR_LINKLOCAL(&c->ip6.gw))
+			addr->a6 = c->ip6.gw;
+		else
+			addr->a6 = c->ip6.addr_ll;
 	}
 }
 
-- 
2.45.1



  parent reply	other threads:[~2024-05-21  5:57 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-05-21  5:57 [PATCH 0/6] Final flow table preliminaries David Gibson
2024-05-21  5:57 ` [PATCH 1/6] flow: Properly type callbacks to protocol specific handlers David Gibson
2024-05-21  5:57 ` David Gibson [this message]
2024-05-21  5:57 ` [PATCH 3/6] flow: Clarify and enforce flow state transitions David Gibson
2024-05-21  5:57 ` [PATCH 4/6] flow: Make side 0 always be the initiating side David Gibson
2024-05-21  5:57 ` [PATCH 5/6] flow: Record the pifs for each side of each flow David Gibson
2024-05-21  5:57 ` [PATCH 6/6] tcp: Remove interim 'tapside' field from connection David Gibson

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=20240521055708.1150050-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).