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
next prev 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).