From: David Gibson <david@gibson.dropbear.id.au>
To: passt-dev@passt.top, Stefano Brivio <sbrivio@redhat.com>
Cc: David Gibson <david@gibson.dropbear.id.au>
Subject: [PATCH 09/18] fwd: Split rule building from rule adding
Date: Tue, 7 Apr 2026 13:16:21 +1000 [thread overview]
Message-ID: <20260407031630.2457081-10-david@gibson.dropbear.id.au> (raw)
In-Reply-To: <20260407031630.2457081-1-david@gibson.dropbear.id.au>
Currently fwd_rule_add() both builds the struct fwd_rule and inserts it
into the table. This will be inconvenient when we want to dynamically add
rules from a configuration client. Alter fwd_rule_add() to take a
pre-constructed struct fwd_rule, which we build in the caller.
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
---
conf.c | 42 ++++++++++++++++++++++++++++++++--------
fwd.c | 61 ++++++++++++++--------------------------------------------
fwd.h | 4 +---
3 files changed, 49 insertions(+), 58 deletions(-)
diff --git a/conf.c b/conf.c
index 23125d2c..c9ee8c59 100644
--- a/conf.c
+++ b/conf.c
@@ -151,9 +151,26 @@ static void conf_ports_range_except(const struct ctx *c, char optname,
const uint8_t *exclude, uint16_t to,
uint8_t flags)
{
+ struct fwd_rule rule = {
+ .addr = addr ? *addr : inany_any6,
+ .ifname = { 0 },
+ .proto = proto,
+ .flags = flags,
+ };
unsigned delta = to - first;
unsigned base, i;
+ if (!addr)
+ rule.flags |= FWD_DUAL_STACK_ANY;
+ if (ifname) {
+ int ret;
+
+ ret = snprintf(rule.ifname, sizeof(rule.ifname),
+ "%s", ifname);
+ if (ret <= 0 || (size_t)ret >= sizeof(rule.ifname))
+ die("Invalid interface name: %s", ifname);
+ }
+
assert(first != 0);
for (base = first; base <= last; base++) {
@@ -165,28 +182,37 @@ static void conf_ports_range_except(const struct ctx *c, char optname,
break;
}
+ rule.first = base;
+ rule.last = i - 1;
+ rule.to = base + delta;
+
if ((optname == 'T' || optname == 'U') && c->no_bindtodevice) {
/* FIXME: Once the fwd bitmaps are removed, move this
* workaround to the caller
*/
+ struct fwd_rule rulev = {
+ .ifname = { 0 },
+ .flags = flags,
+ .first = base,
+ .last = i - 1,
+ .to = base + delta,
+ };
+
assert(!addr && ifname && !strcmp(ifname, "lo"));
warn(
"SO_BINDTODEVICE unavailable, forwarding only 127.0.0.1 and ::1 for '-%c %s'",
optname, optarg);
if (c->ifi4) {
- fwd_rule_add(fwd, proto, flags,
- &inany_loopback4, NULL,
- base, i - 1, base + delta);
+ rulev.addr = inany_loopback4;
+ fwd_rule_add(fwd, &rulev);
}
if (c->ifi6) {
- fwd_rule_add(fwd, proto, flags,
- &inany_loopback6, NULL,
- base, i - 1, base + delta);
+ rulev.addr = inany_loopback6;
+ fwd_rule_add(fwd, &rulev);
}
} else {
- fwd_rule_add(fwd, proto, flags, addr, ifname,
- base, i - 1, base + delta);
+ fwd_rule_add(fwd, &rule);
}
base = i - 1;
}
diff --git a/fwd.c b/fwd.c
index 39a14c40..c05107d1 100644
--- a/fwd.c
+++ b/fwd.c
@@ -332,30 +332,22 @@ void fwd_rule_init(struct ctx *c)
}
/**
- * fwd_rule_add() - Add a rule to a forwarding table
+ * fwd_rule_add() - Validate and add a rule to a forwarding table
* @fwd: Table to add to
- * @proto: Protocol to forward
- * @flags: Flags for this entry
- * @addr: Our address to forward (NULL for both 0.0.0.0 and ::)
- * @ifname: Only forward from this interface name, if non-empty
- * @first: First port number to forward
- * @last: Last port number to forward
- * @to: First port of target port range to map to
+ * @new: Rule to add
*/
-void fwd_rule_add(struct fwd_table *fwd, uint8_t proto, uint8_t flags,
- const union inany_addr *addr, const char *ifname,
- in_port_t first, in_port_t last, in_port_t to)
+void fwd_rule_add(struct fwd_table *fwd, const struct fwd_rule *new)
{
/* Flags which can be set from the caller */
const uint8_t allowed_flags = FWD_WEAK | FWD_SCAN | FWD_DUAL_STACK_ANY;
- unsigned num = (unsigned)last - first + 1;
- struct fwd_rule *new;
+ unsigned num = (unsigned)new->last - new->first + 1;
unsigned i, port;
- assert(!(flags & ~allowed_flags));
+ assert(!(new->flags & ~allowed_flags));
/* Passing a non-wildcard address with DUAL_STACK_ANY is a bug */
- assert(!(flags & FWD_DUAL_STACK_ANY) || !addr ||
- inany_equals(addr, &inany_any6));
+ assert(!(new->flags & FWD_DUAL_STACK_ANY) ||
+ inany_equals(&new->addr, &inany_any6));
+ assert(new->first <= new->last);
if (fwd->count >= ARRAY_SIZE(fwd->rules))
die("Too many port forwarding ranges");
@@ -367,55 +359,30 @@ void fwd_rule_add(struct fwd_table *fwd, uint8_t proto, uint8_t flags,
char newstr[INANY_ADDRSTRLEN], rulestr[INANY_ADDRSTRLEN];
const struct fwd_rule *rule = &fwd->rules[i];
- if (proto != rule->proto)
+ if (new->proto != rule->proto)
/* Non-conflicting protocols */
continue;
- if (!inany_matches(addr, fwd_rule_addr(rule)))
+ if (!inany_matches(fwd_rule_addr(new), fwd_rule_addr(rule)))
/* Non-conflicting addresses */
continue;
- if (last < rule->first || rule->last < first)
+ if (new->last < rule->first || rule->last < new->first)
/* Port ranges don't overlap */
continue;
die("Forwarding configuration conflict: %s/%u-%u versus %s/%u-%u",
- inany_ntop(addr, newstr, sizeof(newstr)), first, last,
+ inany_ntop(fwd_rule_addr(new), newstr, sizeof(newstr)),
+ new->first, new->last,
inany_ntop(fwd_rule_addr(rule), rulestr, sizeof(rulestr)),
rule->first, rule->last);
}
- new = &fwd->rules[fwd->count];
- new->proto = proto;
- new->flags = flags;
-
- if (addr) {
- new->addr = *addr;
- } else {
- new->addr = inany_any6;
- new->flags |= FWD_DUAL_STACK_ANY;
- }
-
- memset(new->ifname, 0, sizeof(new->ifname));
- if (ifname) {
- int ret;
-
- ret = snprintf(new->ifname, sizeof(new->ifname),
- "%s", ifname);
- if (ret <= 0 || (size_t)ret >= sizeof(new->ifname))
- die("Invalid interface name: %s", ifname);
- }
-
- assert(first <= last);
- new->first = first;
- new->last = last;
- new->to = to;
-
fwd->rulesocks[fwd->count] = &fwd->socks[fwd->sock_count];
for (port = new->first; port <= new->last; port++)
fwd->rulesocks[fwd->count][port - new->first] = -1;
- fwd->count++;
+ fwd->rules[fwd->count++] = *new;
fwd->sock_count += num;
}
diff --git a/fwd.h b/fwd.h
index c5f6d554..1d74cbd2 100644
--- a/fwd.h
+++ b/fwd.h
@@ -83,9 +83,7 @@ struct fwd_scan {
#define FWD_PORT_SCAN_INTERVAL 1000 /* ms */
void fwd_rule_init(struct ctx *c);
-void fwd_rule_add(struct fwd_table *fwd, uint8_t proto, uint8_t flags,
- const union inany_addr *addr, const char *ifname,
- in_port_t first, in_port_t last, in_port_t to);
+void fwd_rule_add(struct fwd_table *fwd, const struct fwd_rule *new);
const struct fwd_rule *fwd_rule_search(const struct fwd_table *fwd,
const struct flowside *ini,
uint8_t proto, int hint);
--
2.53.0
next prev parent reply other threads:[~2026-04-07 3:16 UTC|newest]
Thread overview: 40+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-04-07 3:16 [PATCH 00/18] Rework forwarding option parsing David Gibson
2026-04-07 3:16 ` [PATCH 01/18] conf: Split parsing of port specifiers from the rest of -[tuTU] parsing David Gibson
2026-04-07 3:16 ` [PATCH 02/18] conf: Simplify handling of default forwarding mode David Gibson
2026-04-07 23:14 ` Stefano Brivio
2026-04-08 1:10 ` David Gibson
2026-04-07 3:16 ` [PATCH 03/18] conf: Move first pass handling of -[TU] next to handling of -[tu] David Gibson
2026-04-07 3:16 ` [PATCH 04/18] doc: Consolidate -[tu] option descriptions for passt and pasta David Gibson
2026-04-07 23:14 ` Stefano Brivio
2026-04-08 1:23 ` David Gibson
2026-04-07 3:16 ` [PATCH 05/18] conf: Permit -[tTuU] all in pasta mode David Gibson
2026-04-07 3:16 ` [PATCH 06/18] fwd: Better split forwarding rule specification from associated sockets David Gibson
2026-04-07 23:14 ` Stefano Brivio
2026-04-08 1:30 ` David Gibson
2026-04-08 21:39 ` Stefano Brivio
2026-04-09 0:47 ` David Gibson
2026-04-07 3:16 ` [PATCH 07/18] fwd_rule: Move forwarding rule formatting David Gibson
2026-04-07 3:16 ` [PATCH 08/18] conf: Pass protocol explicitly to conf_ports_range_except() David Gibson
2026-04-07 3:16 ` David Gibson [this message]
2026-04-07 3:16 ` [PATCH 10/18] fwd_rule: Move rule conflict checking from fwd_rule_add() to caller David Gibson
2026-04-07 23:14 ` Stefano Brivio
2026-04-08 1:37 ` David Gibson
2026-04-08 4:42 ` David Gibson
2026-04-07 3:16 ` [PATCH 11/18] fwd: Improve error handling in fwd_rule_add() David Gibson
2026-04-08 21:40 ` Stefano Brivio
2026-04-09 0:10 ` David Gibson
2026-04-07 3:16 ` [PATCH 12/18] conf: Don't be strict about exclusivity of forwarding mode David Gibson
2026-04-08 21:40 ` Stefano Brivio
2026-04-09 0:12 ` David Gibson
2026-04-07 3:16 ` [PATCH 13/18] conf: Rework stepping through chunks of port specifiers David Gibson
2026-04-08 21:40 ` Stefano Brivio
2026-04-09 0:13 ` David Gibson
2026-04-07 3:16 ` [PATCH 14/18] conf: Rework checking for garbage after a range David Gibson
2026-04-08 21:40 ` Stefano Brivio
2026-04-09 0:15 ` David Gibson
2026-04-07 3:16 ` [PATCH 15/18] conf: Move "all" handling to port specifier David Gibson
2026-04-08 21:40 ` Stefano Brivio
2026-04-07 3:16 ` [PATCH 16/18] conf: Allow user-specified auto-scanned port forwarding ranges David Gibson
2026-04-08 21:40 ` Stefano Brivio
2026-04-07 3:16 ` [PATCH 17/18] conf: Move SO_BINDTODEVICE workaround to conf_ports() David Gibson
2026-04-07 3:16 ` [PATCH 18/18] conf: Don't pass raw commandline argument to conf_ports_spec() 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=20260407031630.2457081-10-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).