* [PATCH HACK] fwd, fwd_rule: Implement configurable destination address mapping
@ 2026-05-07 5:50 Stefano Brivio
0 siblings, 0 replies; only message in thread
From: Stefano Brivio @ 2026-05-07 5:50 UTC (permalink / raw)
To: Paul Holzinger; +Cc: passt-dev
This isn't complete, it's rather a quick hack to enable early
integration testing.
Add a 'daddr' field to forwarding rules, and some rudimentary parsing.
Format (for either command line or pesto):
-t 2222:192.0.2.1/2222
This should work along with all the other bits, that is, say:
-t 192.0.2.1%eth0/2222-2225:192.0.2.2/22-25
Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
---
fwd.c | 4 +++-
fwd_rule.c | 46 +++++++++++++++++++++++++++++++++++-----------
fwd_rule.h | 2 ++
3 files changed, 40 insertions(+), 12 deletions(-)
diff --git a/fwd.c b/fwd.c
index d224c0a..75db350 100644
--- a/fwd.c
+++ b/fwd.c
@@ -1095,7 +1095,9 @@ uint8_t fwd_nat_from_host(const struct ctx *c,
}
tgt->oport = ini->eport;
- if (inany_v4(&tgt->oaddr)) {
+ if (!inany_is_unspecified(&rule->daddr)) {
+ tgt->eaddr = rule->daddr;
+ } else if (inany_v4(&tgt->oaddr)) {
tgt->eaddr = inany_from_v4(c->ip4.addr_seen);
} else {
if (inany_is_linklocal6(&tgt->oaddr))
diff --git a/fwd_rule.c b/fwd_rule.c
index 5fc04d7..5bce2fb 100644
--- a/fwd_rule.c
+++ b/fwd_rule.c
@@ -465,6 +465,7 @@ static int parse_keyword(const char *s, const char **endptr, const char *kw)
*/
static void fwd_rule_range_except(struct fwd_table *fwd, bool del,
uint8_t proto, const union inany_addr *addr,
+ const union inany_addr *daddr,
const char *ifname,
uint16_t first, uint16_t last,
const uint8_t *exclude, uint16_t to,
@@ -472,6 +473,7 @@ static void fwd_rule_range_except(struct fwd_table *fwd, bool del,
{
struct fwd_rule rule = {
.addr = addr ? *addr : inany_any6,
+ .daddr = daddr ? *daddr : inany_any6,
.ifname = { 0 },
.proto = proto,
.flags = flags,
@@ -544,13 +546,13 @@ fail:
*/
static void fwd_rule_parse_ports(struct fwd_table *fwd, bool del, uint8_t proto,
const union inany_addr *addr,
- const char *ifname,
- const char *spec)
+ const char *ifname, char *spec)
{
+ union inany_addr daddr_buf = inany_any6, *daddr = &daddr_buf;
uint8_t exclude[PORT_BITMAP_SIZE] = { 0 };
bool exclude_only = true;
- const char *p, *ep;
uint8_t flags = 0;
+ char *p, *ep;
unsigned i;
if (!strcmp(spec, "all")) {
@@ -568,7 +570,7 @@ static void fwd_rule_parse_ports(struct fwd_table *fwd, bool del, uint8_t proto,
continue;
}
- if (parse_keyword(p, &p, "auto") == 0) {
+ if (parse_keyword(p, (const char **)&p, "auto") == 0) {
if (p != ep) /* Garbage after the keyword */
goto bad;
@@ -586,7 +588,7 @@ static void fwd_rule_parse_ports(struct fwd_table *fwd, bool del, uint8_t proto,
goto bad;
p++;
- if (parse_port_range(p, &p, &xrange))
+ if (parse_port_range(p, (const char **)&p, &xrange))
goto bad;
if (p != ep) /* Garbage after the range */
goto bad;
@@ -599,7 +601,7 @@ static void fwd_rule_parse_ports(struct fwd_table *fwd, bool del, uint8_t proto,
/* Exclude ephemeral ports */
fwd_port_map_ephemeral(exclude);
- fwd_rule_range_except(fwd, del, proto, addr, ifname,
+ fwd_rule_range_except(fwd, del, proto, addr, NULL, ifname,
1, NUM_PORTS - 1, exclude,
1, flags | FWD_WEAK);
return;
@@ -613,11 +615,32 @@ static void fwd_rule_parse_ports(struct fwd_table *fwd, bool del, uint8_t proto,
/* Already parsed */
continue;
- if (parse_port_range(p, &p, &orig_range))
+ if (parse_port_range(p, (const char **)&p, &orig_range))
goto bad;
- if (*p == ':') { /* There's a range to map to as well */
- if (parse_port_range(p + 1, &p, &mapped_range))
+ if (*p == ':') {
+ /* There's a range or address to map to as well */
+ char *addr_end = strchr(p, '/');
+
+ if (addr_end) {
+ *addr_end = '\0';
+
+ if (*p == '[' && p[strlen(p) - 1] == ']') {
+ p[strlen(p) - 1] = '\0';
+ p++;
+ }
+
+ if (!inany_pton(p + 1, daddr))
+ die("Bad forwarding address '%s'", p);
+
+ p = addr_end;
+ } else {
+ daddr = NULL;
+ }
+
+
+ if (parse_port_range(p + 1, (const char **)&p,
+ &mapped_range))
goto bad;
if ((mapped_range.last - mapped_range.first) !=
(orig_range.last - orig_range.first))
@@ -629,7 +652,7 @@ static void fwd_rule_parse_ports(struct fwd_table *fwd, bool del, uint8_t proto,
if (p != ep) /* Garbage after the ranges */
goto bad;
- fwd_rule_range_except(fwd, del, proto, addr, ifname,
+ fwd_rule_range_except(fwd, del, proto, addr, daddr, ifname,
orig_range.first, orig_range.last,
exclude,
mapped_range.first, flags);
@@ -675,7 +698,8 @@ void fwd_rule_parse(char optname, bool del, const char *optarg,
strncpy(buf, optarg, sizeof(buf) - 1);
- if ((spec = strchr(buf, '/'))) {
+ if ((spec = strchr(buf, '/')) &&
+ strchr(spec, ':') == strchr(buf, ':')) {
*spec = 0;
spec++;
diff --git a/fwd_rule.h b/fwd_rule.h
index ae9a3cb..3a2a809 100644
--- a/fwd_rule.h
+++ b/fwd_rule.h
@@ -35,6 +35,7 @@
/**
* struct fwd_rule - Forwarding rule governing a range of ports
* @addr: Address to forward from
+ * @daddr: Optional address to set as destination when forwarding
* @ifname: Interface to forward from
* @first: First port number to forward
* @last: Last port number to forward
@@ -47,6 +48,7 @@
*/
struct fwd_rule {
union inany_addr addr;
+ union inany_addr daddr;
char ifname[IFNAMSIZ];
in_port_t first;
in_port_t last;
--
2.43.0
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2026-05-07 5:50 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-05-07 5:50 [PATCH HACK] fwd, fwd_rule: Implement configurable destination address mapping Stefano Brivio
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).