From mboxrd@z Thu Jan 1 00:00:00 1970 Authentication-Results: passt.top; dmarc=none (p=none dis=none) header.from=gibson.dropbear.id.au Authentication-Results: passt.top; dkim=pass (2048-bit key; secure) header.d=gibson.dropbear.id.au header.i=@gibson.dropbear.id.au header.a=rsa-sha256 header.s=202602 header.b=d1XeuHTa; dkim-atps=neutral Received: from mail.ozlabs.org (gandalf.ozlabs.org [150.107.74.76]) by passt.top (Postfix) with ESMTPS id 678105A0275 for ; Tue, 07 Apr 2026 05:16:42 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gibson.dropbear.id.au; s=202602; t=1775531792; bh=yzCKBprZv/adQacrfHAmMTjJ4sgxEFv56KXaxSUFZZE=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=d1XeuHTas5Fo8oDIMbBNzFvusgeIMZ/APV0gc6Z/DSKDQr7EMMPeZCf2pRJs6cbpD yU+99Eg9ZH8BL4Ol2I/pyCRvlgNIGejvC933OIEZZWWXp/TsgqjI3Vv12XDOYlgKCu ITrctbbOMLrgmvEPo7Q4S0mIYqO9PeEKpIPD6wpU29afzD4wWyXKhd7yB37YjhIoBL ipgQzjfHeeNjF9SPeslt/3vrv8ajSB8KF/P68GLch93wVBX4IiisA39Ifl1GZ4knGI E622IejUWDzwq4zFAfUTty7/7xC46eOU/VKKIjXzHOJnAK74oozwoYemZMiiSdJ00k DDJcon8LnHpuA== Received: by gandalf.ozlabs.org (Postfix, from userid 1007) id 4fqWZ85hcZz4wLB; Tue, 07 Apr 2026 13:16:32 +1000 (AEST) From: David Gibson To: passt-dev@passt.top, Stefano Brivio Subject: [PATCH 09/18] fwd: Split rule building from rule adding Date: Tue, 7 Apr 2026 13:16:21 +1000 Message-ID: <20260407031630.2457081-10-david@gibson.dropbear.id.au> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260407031630.2457081-1-david@gibson.dropbear.id.au> References: <20260407031630.2457081-1-david@gibson.dropbear.id.au> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Message-ID-Hash: UN7NH4762RW55YTCSEI7E723EMGAHH5I X-Message-ID-Hash: UN7NH4762RW55YTCSEI7E723EMGAHH5I X-MailFrom: dgibson@gandalf.ozlabs.org X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; emergency; loop; banned-address; member-moderation; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; digests; suspicious-header CC: David Gibson X-Mailman-Version: 3.3.8 Precedence: list List-Id: Development discussion and patches for passt Archived-At: Archived-At: List-Archive: List-Archive: List-Help: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: 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 --- 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