summaryrefslogtreecommitdiffstats
path: root/iptables
diff options
context:
space:
mode:
authorPhil Sutter <phil@nwl.cc>2024-03-05 16:28:29 +0100
committerPhil Sutter <phil@nwl.cc>2024-04-09 23:20:36 +0200
commitd45fb0a4077304a7e3f2c44bbac1bde3a9b49a77 (patch)
tree7f8643ab3f4d692dbbcbf224e58b82de73893ddb /iptables
parent681935f6cb5734e120b5efe5aa8512508e2793f4 (diff)
xlate: Improve redundant l4proto match avoidance
xtables-translate tries to avoid 'ip protocol'/'meta l4proto' matches if following expressions add this as dependency anyway. E.g.: | # iptables-translate -A FOO -p tcp -m tcp --dport 22 -j ACCEPT | nft 'add rule ip filter FOO tcp dport 22 counter accept' This worked by searching protocol name in loaded matches, but that approach is flawed as the protocol name and corresponding extension may differ ("mobility-header" vs. "mh"). Improve this by searching for all names (cached or resolved) for a given protocol number. Signed-off-by: Phil Sutter <phil@nwl.cc>
Diffstat (limited to 'iptables')
-rw-r--r--iptables/nft-ipv4.c23
-rw-r--r--iptables/nft-ipv6.c23
-rw-r--r--iptables/nft.h1
-rw-r--r--iptables/xtables-translate.c17
4 files changed, 39 insertions, 25 deletions
diff --git a/iptables/nft-ipv4.c b/iptables/nft-ipv4.c
index 0ce8477f..74092875 100644
--- a/iptables/nft-ipv4.c
+++ b/iptables/nft-ipv4.c
@@ -200,6 +200,7 @@ static void xlate_ipv4_addr(const char *selector, const struct in_addr *addr,
static int nft_ipv4_xlate(const struct iptables_command_state *cs,
struct xt_xlate *xl)
{
+ uint16_t proto = cs->fw.ip.proto;
const char *comment;
int ret;
@@ -213,18 +214,16 @@ static int nft_ipv4_xlate(const struct iptables_command_state *cs,
cs->fw.ip.invflags & IPT_INV_FRAG? "" : "!= ", 0);
}
- if (cs->fw.ip.proto != 0) {
- const char *pname = proto_to_name(cs->fw.ip.proto, 0);
-
- if (!pname || !xlate_find_match(cs, pname)) {
- xt_xlate_add(xl, "ip protocol");
- if (cs->fw.ip.invflags & IPT_INV_PROTO)
- xt_xlate_add(xl, " !=");
- if (pname)
- xt_xlate_add(xl, "%s", pname);
- else
- xt_xlate_add(xl, "%hu", cs->fw.ip.proto);
- }
+ if (proto != 0 && !xlate_find_protomatch(cs, proto)) {
+ const char *pname = proto_to_name(proto, 0);
+
+ xt_xlate_add(xl, "ip protocol");
+ if (cs->fw.ip.invflags & IPT_INV_PROTO)
+ xt_xlate_add(xl, " !=");
+ if (pname)
+ xt_xlate_add(xl, "%s", pname);
+ else
+ xt_xlate_add(xl, "%hu", proto);
}
xlate_ipv4_addr("ip saddr", &cs->fw.ip.src, &cs->fw.ip.smsk,
diff --git a/iptables/nft-ipv6.c b/iptables/nft-ipv6.c
index c371ba8c..b184f8af 100644
--- a/iptables/nft-ipv6.c
+++ b/iptables/nft-ipv6.c
@@ -184,6 +184,7 @@ static void xlate_ipv6_addr(const char *selector, const struct in6_addr *addr,
static int nft_ipv6_xlate(const struct iptables_command_state *cs,
struct xt_xlate *xl)
{
+ uint16_t proto = cs->fw6.ipv6.proto;
const char *comment;
int ret;
@@ -192,18 +193,16 @@ static int nft_ipv6_xlate(const struct iptables_command_state *cs,
xlate_ifname(xl, "oifname", cs->fw6.ipv6.outiface,
cs->fw6.ipv6.invflags & IP6T_INV_VIA_OUT);
- if (cs->fw6.ipv6.proto != 0) {
- const char *pname = proto_to_name(cs->fw6.ipv6.proto, 0);
-
- if (!pname || !xlate_find_match(cs, pname)) {
- xt_xlate_add(xl, "meta l4proto");
- if (cs->fw6.ipv6.invflags & IP6T_INV_PROTO)
- xt_xlate_add(xl, " !=");
- if (pname)
- xt_xlate_add(xl, "%s", pname);
- else
- xt_xlate_add(xl, "%hu", cs->fw6.ipv6.proto);
- }
+ if (proto != 0 && !xlate_find_protomatch(cs, proto)) {
+ const char *pname = proto_to_name(proto, 0);
+
+ xt_xlate_add(xl, "meta l4proto");
+ if (cs->fw6.ipv6.invflags & IP6T_INV_PROTO)
+ xt_xlate_add(xl, " !=");
+ if (pname)
+ xt_xlate_add(xl, "%s", pname);
+ else
+ xt_xlate_add(xl, "%hu", proto);
}
xlate_ipv6_addr("ip6 saddr", &cs->fw6.ipv6.src, &cs->fw6.ipv6.smsk,
diff --git a/iptables/nft.h b/iptables/nft.h
index 57533b65..b2a8484f 100644
--- a/iptables/nft.h
+++ b/iptables/nft.h
@@ -242,6 +242,7 @@ int do_commandeb(struct nft_handle *h, int argc, char *argv[], char **table, boo
struct xt_buf;
bool xlate_find_match(const struct iptables_command_state *cs, const char *p_name);
+bool xlate_find_protomatch(const struct iptables_command_state *cs, uint16_t proto);
int xlate_matches(const struct iptables_command_state *cs, struct xt_xlate *xl);
int xlate_action(const struct iptables_command_state *cs, bool goto_set,
struct xt_xlate *xl);
diff --git a/iptables/xtables-translate.c b/iptables/xtables-translate.c
index 8ebe523c..3d8617f0 100644
--- a/iptables/xtables-translate.c
+++ b/iptables/xtables-translate.c
@@ -131,7 +131,6 @@ bool xlate_find_match(const struct iptables_command_state *cs, const char *p_nam
{
struct xtables_rule_match *matchp;
- /* Skip redundant protocol, eg. ip protocol tcp tcp dport */
for (matchp = cs->matches; matchp; matchp = matchp->next) {
if (strcmp(matchp->match->name, p_name) == 0)
return true;
@@ -139,6 +138,22 @@ bool xlate_find_match(const struct iptables_command_state *cs, const char *p_nam
return false;
}
+bool xlate_find_protomatch(const struct iptables_command_state *cs,
+ uint16_t proto)
+{
+ struct protoent *pent;
+ int i;
+
+ /* Skip redundant protocol, eg. ip protocol tcp tcp dport */
+ for (i = 0; xtables_chain_protos[i].name != NULL; i++) {
+ if (xtables_chain_protos[i].num == proto &&
+ xlate_find_match(cs, xtables_chain_protos[i].name))
+ return true;
+ }
+ pent = getprotobynumber(proto);
+ return pent && xlate_find_match(cs, pent->p_name);
+}
+
const char *family2str[] = {
[NFPROTO_ARP] = "arp",
[NFPROTO_IPV4] = "ip",