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=bsVlDp0z; dkim-atps=neutral Received: from mail.ozlabs.org (mail.ozlabs.org [IPv6:2404:9400:2221:ea00::3]) by passt.top (Postfix) with ESMTPS id BC46C5A0262 for ; Tue, 10 Mar 2026 05:16:11 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gibson.dropbear.id.au; s=202602; t=1773116167; bh=uZSbMuFmaSu4v1v5yHZv1LQPQR162izhp+FLWyCitCI=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=bsVlDp0zYLDb5sdGD+v+75Zq4F0EnausBZaT78Zpsn7/8SYoVvSFXblhERUI704bd djp9mhpOttKWBP1vV5GpCBXBYPRz0gQc1FV4QU90u+sMK6AHuEX0NlZXoj+j8beYtm t1+Fe43kh5h/iBL+uoBWZVAC6Tgt6kbOUvZC9OENtui3VSOzzmMLVhxPebO8c73iXl N8ti8sP5ufyiMq4t7Hz+WJCfHB+GSxykVRUQJE5cfg31XVs3cHFL1XtKis7+ijpuhG 7ozYmXHOwDkINb/R1RLBKBTAx+Lct4wMQFUDIkMTNLq+Nsp5mptnHnfGk9j0cTp07C lsxw4WRSw3gyg== Received: by gandalf.ozlabs.org (Postfix, from userid 1007) id 4fVLCq5BZgz4wD3; Tue, 10 Mar 2026 15:16:07 +1100 (AEDT) From: David Gibson To: Stefano Brivio , passt-dev@passt.top Subject: [PATCH 1/6] conf, fwd: Make overall forwarding mode local to conf path Date: Tue, 10 Mar 2026 15:16:00 +1100 Message-ID: <20260310041605.1322552-2-david@gibson.dropbear.id.au> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260310041605.1322552-1-david@gibson.dropbear.id.au> References: <20260310041605.1322552-1-david@gibson.dropbear.id.au> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Message-ID-Hash: FXJEA5Y6TREDMLDJR4F2QV7F6WSG6SIS X-Message-ID-Hash: FXJEA5Y6TREDMLDJR4F2QV7F6WSG6SIS 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: The 'mode' field of struct fwd_ports records the overall forwarding mode. Now that runtime forwarding decisions are made based on the forwarding table, this is almost unused outside conf(). The only exception is the auto-port scanning code, which uses it to determine if a port scan is necessary. We can instead derive that from the forwarding table itself by checking if there are any entries with the FWD_SCAN flag. Once that's done, make the mode purely local to conf(). While we're there rename the constants to FWD_MODE_* to avoid confusion with the forwarding rule flag bits, which are also prefixed with FWD_. Signed-off-by: David Gibson --- conf.c | 82 ++++++++++++++++++++++++++++++++++++---------------------- fwd.c | 27 ++++++++++++++----- fwd.h | 10 ------- 3 files changed, 72 insertions(+), 47 deletions(-) diff --git a/conf.c b/conf.c index 11d84536..c436b88e 100644 --- a/conf.c +++ b/conf.c @@ -199,15 +199,27 @@ static void conf_ports_range_except(const struct ctx *c, char optname, } } +/** + * enum fwd_mode - Overall forwarding mode for a direction and protocol + */ +enum fwd_mode { + FWD_MODE_UNSET = 0, + FWD_MODE_SPEC, + FWD_MODE_NONE, + FWD_MODE_AUTO, + FWD_MODE_ALL, +}; + /** * conf_ports() - Parse port configuration options, initialise UDP/TCP sockets * @c: Execution context * @optname: Short option name, t, T, u, or U * @optarg: Option argument (port specification) * @fwd: Pointer to @fwd_ports to be updated + * @mode: Overall port forwarding mode (updated) */ static void conf_ports(const struct ctx *c, char optname, const char *optarg, - struct fwd_ports *fwd) + struct fwd_ports *fwd, enum fwd_mode *mode) { union inany_addr addr_buf = inany_any6, *addr = &addr_buf; char buf[BUFSIZ], *spec, *ifname = NULL, *p; @@ -216,10 +228,10 @@ static void conf_ports(const struct ctx *c, char optname, const char *optarg, unsigned i; if (!strcmp(optarg, "none")) { - if (fwd->mode) + if (*mode) goto mode_conflict; - fwd->mode = FWD_NONE; + *mode = FWD_MODE_NONE; return; } @@ -229,7 +241,7 @@ static void conf_ports(const struct ctx *c, char optname, const char *optarg, die("UDP port forwarding requested but UDP is disabled"); if (!strcmp(optarg, "auto")) { - if (fwd->mode) + if (*mode) goto mode_conflict; if (c->mode != MODE_PASTA) @@ -241,18 +253,18 @@ static void conf_ports(const struct ctx *c, char optname, const char *optarg, warn( "Forwarding from addresses other than 127.0.0.1 will not work"); } - fwd->mode = FWD_AUTO; + *mode = FWD_MODE_AUTO; return; } if (!strcmp(optarg, "all")) { - if (fwd->mode) + if (*mode) goto mode_conflict; if (c->mode == MODE_PASTA) die("'all' port forwarding is only allowed for passt"); - fwd->mode = FWD_ALL; + *mode = FWD_MODE_ALL; /* Exclude ephemeral ports */ for (i = 0; i < NUM_PORTS; i++) @@ -266,10 +278,10 @@ static void conf_ports(const struct ctx *c, char optname, const char *optarg, return; } - if (fwd->mode > FWD_SPEC) + if (*mode > FWD_MODE_SPEC) die("Specific ports cannot be specified together with all/none/auto"); - fwd->mode = FWD_SPEC; + *mode = FWD_MODE_SPEC; strncpy(buf, optarg, sizeof(buf) - 1); @@ -1525,7 +1537,11 @@ void conf(struct ctx *c, int argc, char **argv) const char *logname = (c->mode == MODE_PASTA) ? "pasta" : "passt"; char userns[PATH_MAX] = { 0 }, netns[PATH_MAX] = { 0 }; bool copy_addrs_opt = false, copy_routes_opt = false; - enum fwd_ports_mode fwd_default = FWD_NONE; + enum fwd_mode tcp_out_mode = FWD_MODE_UNSET; + enum fwd_mode udp_out_mode = FWD_MODE_UNSET; + enum fwd_mode tcp_in_mode = FWD_MODE_UNSET; + enum fwd_mode udp_in_mode = FWD_MODE_UNSET; + enum fwd_mode fwd_default = FWD_MODE_NONE; bool v4_only = false, v6_only = false; unsigned dns4_idx = 0, dns6_idx = 0; unsigned long max_mtu = IP_MAX_MTU; @@ -1540,17 +1556,16 @@ void conf(struct ctx *c, int argc, char **argv) int name, ret; uid_t uid; gid_t gid; + if (c->mode == MODE_PASTA) { c->no_dhcp_dns = c->no_dhcp_dns_search = 1; - fwd_default = FWD_AUTO; + fwd_default = FWD_MODE_AUTO; } if (tap_l2_max_len(c) - ETH_HLEN < max_mtu) max_mtu = tap_l2_max_len(c) - ETH_HLEN; c->mtu = ROUND_DOWN(max_mtu, sizeof(uint32_t)); - c->tcp.fwd_in.mode = c->tcp.fwd_out.mode = FWD_UNSET; - c->udp.fwd_in.mode = c->udp.fwd_out.mode = FWD_UNSET; memcpy(c->our_tap_mac, MAC_OUR_LAA, ETH_ALEN); optind = 0; @@ -2100,9 +2115,11 @@ void conf(struct ctx *c, int argc, char **argv) name = getopt_long(argc, argv, optstring, options, NULL); if (name == 't') { - conf_ports(c, name, optarg, &c->tcp.fwd_in); + conf_ports(c, name, optarg, + &c->tcp.fwd_in, &tcp_in_mode); } else if (name == 'u') { - conf_ports(c, name, optarg, &c->udp.fwd_in); + conf_ports(c, name, optarg, + &c->udp.fwd_in, &udp_in_mode); } else if (name == 'D') { struct in6_addr dns6_tmp; struct in_addr dns4_tmp; @@ -2172,10 +2189,13 @@ void conf(struct ctx *c, int argc, char **argv) do { name = getopt_long(argc, argv, optstring, options, NULL); - if (name == 'T') - conf_ports(c, name, optarg, &c->tcp.fwd_out); - else if (name == 'U') - conf_ports(c, name, optarg, &c->udp.fwd_out); + if (name == 'T') { + conf_ports(c, name, optarg, + &c->tcp.fwd_out, &tcp_out_mode); + } else if (name == 'U') { + conf_ports(c, name, optarg, + &c->udp.fwd_out, &udp_out_mode); + } } while (name != -1); if (!c->ifi4) @@ -2197,31 +2217,31 @@ void conf(struct ctx *c, int argc, char **argv) if_indextoname(c->ifi6, c->pasta_ifn); } - if (!c->tcp.fwd_in.mode) - c->tcp.fwd_in.mode = fwd_default; - if (!c->tcp.fwd_out.mode) - c->tcp.fwd_out.mode = fwd_default; - if (!c->udp.fwd_in.mode) - c->udp.fwd_in.mode = fwd_default; - if (!c->udp.fwd_out.mode) - c->udp.fwd_out.mode = fwd_default; + if (!tcp_in_mode) + tcp_in_mode = fwd_default; + if (!tcp_out_mode) + tcp_out_mode = fwd_default; + if (!udp_in_mode) + udp_in_mode = fwd_default; + if (!udp_out_mode) + udp_out_mode = fwd_default; - if (c->tcp.fwd_in.mode == FWD_AUTO) { + if (tcp_in_mode == FWD_MODE_AUTO) { conf_ports_range_except(c, 't', "auto", &c->tcp.fwd_in, NULL, NULL, 1, NUM_PORTS - 1, NULL, 1, FWD_SCAN); } - if (c->tcp.fwd_out.mode == FWD_AUTO) { + if (tcp_out_mode == FWD_MODE_AUTO) { conf_ports_range_except(c, 'T', "auto", &c->tcp.fwd_out, NULL, "lo", 1, NUM_PORTS - 1, NULL, 1, FWD_SCAN); } - if (c->udp.fwd_in.mode == FWD_AUTO) { + if (udp_in_mode == FWD_MODE_AUTO) { conf_ports_range_except(c, 'u', "auto", &c->udp.fwd_in, NULL, NULL, 1, NUM_PORTS - 1, NULL, 1, FWD_SCAN); } - if (c->udp.fwd_out.mode == FWD_AUTO) { + if (udp_out_mode == FWD_MODE_AUTO) { conf_ports_range_except(c, 'U', "auto", &c->udp.fwd_out, NULL, "lo", 1, NUM_PORTS - 1, NULL, 1, FWD_SCAN); diff --git a/fwd.c b/fwd.c index 4052b797..c5090fb1 100644 --- a/fwd.c +++ b/fwd.c @@ -717,6 +717,21 @@ static void procfs_scan_listen(int fd, unsigned int lstate, uint8_t *map) } } +/** + * has_scan_rules() - Does the given table have any FWD_SCAN rules? + * @fwd: Forwarding table + */ +static bool has_scan_rules(const struct fwd_ports *fwd) +{ + unsigned i; + + for (i = 0; i < fwd->count; i++) { + if (fwd->rules[i].flags & FWD_SCAN) + return true; + } + return false; +} + /** * fwd_scan_ports_tcp() - Scan /proc to update TCP forwarding map * @fwd: Forwarding information to update @@ -724,7 +739,7 @@ static void procfs_scan_listen(int fd, unsigned int lstate, uint8_t *map) */ static void fwd_scan_ports_tcp(struct fwd_ports *fwd, const uint8_t *exclude) { - if (fwd->mode != FWD_AUTO) + if (!has_scan_rules(fwd)) return; memset(fwd->map, 0, PORT_BITMAP_SIZE); @@ -743,7 +758,7 @@ static void fwd_scan_ports_udp(struct fwd_ports *fwd, const struct fwd_ports *tcp_fwd, const uint8_t *exclude) { - if (fwd->mode != FWD_AUTO) + if (!has_scan_rules(fwd)) return; memset(fwd->map, 0, PORT_BITMAP_SIZE); @@ -816,19 +831,19 @@ void fwd_scan_ports_init(struct ctx *c) c->udp.fwd_in.scan4 = c->udp.fwd_in.scan6 = -1; c->udp.fwd_out.scan4 = c->udp.fwd_out.scan6 = -1; - if (c->tcp.fwd_in.mode == FWD_AUTO) { + if (has_scan_rules(&c->tcp.fwd_in)) { c->tcp.fwd_in.scan4 = open_in_ns(c, "/proc/net/tcp", flags); c->tcp.fwd_in.scan6 = open_in_ns(c, "/proc/net/tcp6", flags); } - if (c->udp.fwd_in.mode == FWD_AUTO) { + if (has_scan_rules(&c->udp.fwd_in)) { c->udp.fwd_in.scan4 = open_in_ns(c, "/proc/net/udp", flags); c->udp.fwd_in.scan6 = open_in_ns(c, "/proc/net/udp6", flags); } - if (c->tcp.fwd_out.mode == FWD_AUTO) { + if (has_scan_rules(&c->tcp.fwd_out)) { c->tcp.fwd_out.scan4 = open("/proc/net/tcp", flags); c->tcp.fwd_out.scan6 = open("/proc/net/tcp6", flags); } - if (c->udp.fwd_out.mode == FWD_AUTO) { + if (has_scan_rules(&c->udp.fwd_out)) { c->udp.fwd_out.scan4 = open("/proc/net/udp", flags); c->udp.fwd_out.scan6 = open("/proc/net/udp6", flags); } diff --git a/fwd.h b/fwd.h index 7f52f76e..6d657ddc 100644 --- a/fwd.h +++ b/fwd.h @@ -68,14 +68,6 @@ struct fwd_listen_ref { unsigned rule :FWD_RULE_BITS; }; -enum fwd_ports_mode { - FWD_UNSET = 0, - FWD_SPEC = 1, - FWD_NONE, - FWD_AUTO, - FWD_ALL, -}; - #define PORT_BITMAP_SIZE DIV_ROUND_UP(NUM_PORTS, 8) /* Maximum number of listening sockets (per pif & protocol) @@ -87,7 +79,6 @@ enum fwd_ports_mode { /** * fwd_ports() - Describes port forwarding for one protocol and direction - * @mode: Overall mode (all, none, auto, specific ports) * @scan4: /proc/net fd to scan for IPv4 ports when in AUTO mode * @scan6: /proc/net fd to scan for IPv6 ports when in AUTO mode * @count: Number of forwarding rules @@ -97,7 +88,6 @@ enum fwd_ports_mode { * @socks: Listening sockets for forwarding */ struct fwd_ports { - enum fwd_ports_mode mode; int scan4; int scan6; unsigned count; -- 2.53.0