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