public inbox for passt-dev@passt.top
 help / color / mirror / code / Atom feed
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


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