summaryrefslogtreecommitdiffstats
path: root/iptables/nft-ipv4.c
diff options
context:
space:
mode:
authorPhil Sutter <phil@nwl.cc>2021-03-02 14:50:07 +0100
committerPhil Sutter <phil@nwl.cc>2021-03-09 09:27:33 +0100
commit46f9d3a9a61ee80fa94b7fa7b3b36045c92606ae (patch)
treef14a80399d455fe8a40812449decd394021c62de /iptables/nft-ipv4.c
parent330f5df03ad589b46865ceedf2a54cf10a4225ba (diff)
xtables-translate: Fix translation of odd netmasks
Iptables supports netmasks which are not prefixes to match on (or ignore) arbitrary bits in an address. Yet nftables' prefix notation is available for real prefixes only, so translation is not as trivial - print bitmask syntax for those cases. Signed-off-by: Phil Sutter <phil@nwl.cc>
Diffstat (limited to 'iptables/nft-ipv4.c')
-rw-r--r--iptables/nft-ipv4.c42
1 files changed, 30 insertions, 12 deletions
diff --git a/iptables/nft-ipv4.c b/iptables/nft-ipv4.c
index fdc15c6f..0d32a300 100644
--- a/iptables/nft-ipv4.c
+++ b/iptables/nft-ipv4.c
@@ -383,6 +383,32 @@ static void nft_ipv4_post_parse(int command,
" source or destination IP addresses");
}
+static void xlate_ipv4_addr(const char *selector, const struct in_addr *addr,
+ const struct in_addr *mask,
+ bool inv, struct xt_xlate *xl)
+{
+ const char *op = inv ? "!= " : "";
+ int cidr;
+
+ if (!inv && !addr->s_addr && !mask->s_addr)
+ return;
+
+ cidr = xtables_ipmask_to_cidr(mask);
+ switch (cidr) {
+ case -1:
+ /* inet_ntoa() is not reentrant */
+ xt_xlate_add(xl, "%s & %s ", selector, inet_ntoa(*mask));
+ xt_xlate_add(xl, "%s %s ", inv ? "!=" : "==", inet_ntoa(*addr));
+ break;
+ case 32:
+ xt_xlate_add(xl, "%s %s%s ", selector, op, inet_ntoa(*addr));
+ break;
+ default:
+ xt_xlate_add(xl, "%s %s%s/%d ", selector, op, inet_ntoa(*addr),
+ cidr);
+ }
+}
+
static int nft_ipv4_xlate(const void *data, struct xt_xlate *xl)
{
const struct iptables_command_state *cs = data;
@@ -417,18 +443,10 @@ static int nft_ipv4_xlate(const void *data, struct xt_xlate *xl)
}
}
- if (cs->fw.ip.src.s_addr != 0) {
- xt_xlate_add(xl, "ip saddr %s%s%s ",
- cs->fw.ip.invflags & IPT_INV_SRCIP ? "!= " : "",
- inet_ntoa(cs->fw.ip.src),
- xtables_ipmask_to_numeric(&cs->fw.ip.smsk));
- }
- if (cs->fw.ip.dst.s_addr != 0) {
- xt_xlate_add(xl, "ip daddr %s%s%s ",
- cs->fw.ip.invflags & IPT_INV_DSTIP ? "!= " : "",
- inet_ntoa(cs->fw.ip.dst),
- xtables_ipmask_to_numeric(&cs->fw.ip.dmsk));
- }
+ xlate_ipv4_addr("ip saddr", &cs->fw.ip.src, &cs->fw.ip.smsk,
+ cs->fw.ip.invflags & IPT_INV_SRCIP, xl);
+ xlate_ipv4_addr("ip daddr", &cs->fw.ip.dst, &cs->fw.ip.dmsk,
+ cs->fw.ip.invflags & IPT_INV_DSTIP, xl);
ret = xlate_matches(cs, xl);
if (!ret)