From 5e2b473a64bc772a5fb08d121fbfd969ca652bec Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Tue, 15 May 2018 00:48:01 +0200 Subject: xtables-compat: extend generic tests for masks and wildcards This uncovered broken translation of ethernet + mask. Signed-off-by: Florian Westphal --- extensions/generic.txlate | 15 ++++++++++ iptables/nft-bridge.c | 73 +++++++++++++++++++++++++++-------------------- 2 files changed, 57 insertions(+), 31 deletions(-) diff --git a/extensions/generic.txlate b/extensions/generic.txlate index 1140bb89..b38fbd1f 100644 --- a/extensions/generic.txlate +++ b/extensions/generic.txlate @@ -3,3 +3,18 @@ nft insert rule ip filter OUTPUT ip protocol udp ip daddr 8.8.8.8 counter accept iptables-translate -F -t nat nft flush table ip nat + +iptables-translate -I INPUT -i iifname -s 10.0.0.0/8 +nft insert rule ip filter INPUT iifname "iifname" ip saddr 10.0.0.0/8 counter + +iptables-translate -A INPUT -i iif+ ! -d 10.0.0.0/8 +nft add rule ip filter INPUT iifname "iif*" ip daddr != 10.0.0.0/8 counter + +ebtables-translate -I INPUT -i iname --logical-in ilogname -s 0:0:0:0:0:0 +nft insert rule bridge filter INPUT iifname "iname" meta ibrname "ilogname" ether saddr 00:00:00:00:00:00 counter + +ebtables-translate -A FORWARD ! -i iname --logical-in ilogname -o out+ --logical-out lout+ -d 1:2:3:4:de:af +nft add rule bridge filter FORWARD iifname != "iname" meta ibrname "ilogname" oifname "out*" meta obrname "lout*" ether daddr 01:02:03:04:de:af counter + +ebtables-translate -I INPUT -p ip -d 1:2:3:4:5:6/ff:ff:ff:ff:00:00 +nft insert rule bridge filter INPUT ether type 0x800 ether daddr 01:02:03:04:00:00 and ff:ff:ff:ff:00:00 == 01:02:03:04:00:00 counter diff --git a/iptables/nft-bridge.c b/iptables/nft-bridge.c index fb19fea3..917d802e 100644 --- a/iptables/nft-bridge.c +++ b/iptables/nft-bridge.c @@ -631,22 +631,51 @@ static int xlate_ebaction(const struct iptables_command_state *cs, struct xt_xla return ret; } +static void xlate_mac(struct xt_xlate *xl, const unsigned char *mac) +{ + int i; + + xt_xlate_add(xl, "%02x", mac[0]); + + for (i=1; i < ETH_ALEN; i++) + xt_xlate_add(xl, ":%02x", mac[i]); +} + +static void nft_bridge_xlate_mac(struct xt_xlate *xl, const char *type, bool invert, + const unsigned char *mac, const unsigned char *mask) +{ + char one_msk[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; + + xt_xlate_add(xl, "ether %s %s", type, invert ? "!= " : ""); + + xlate_mac(xl, mac); + + if (memcmp(mask, one_msk, ETH_ALEN)) { + int i; + xt_xlate_add(xl, " and "); + + xlate_mac(xl, mask); + + xt_xlate_add(xl, " == %02x", mac[0] & mask[0]); + for (i=1; i < ETH_ALEN; i++) + xt_xlate_add(xl, ":%02x", mac[i] & mask[i]); + } + + xt_xlate_add(xl, " "); +} static int nft_bridge_xlate(const void *data, struct xt_xlate *xl) { const struct iptables_command_state *cs = data; - char one_msk[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; - const char *addr; int ret; xlate_ifname(xl, "iifname", cs->eb.in, cs->eb.invflags & EBT_IIN); + xlate_ifname(xl, "meta ibrname", cs->eb.logical_in, + cs->eb.invflags & EBT_ILOGICALIN); xlate_ifname(xl, "oifname", cs->eb.out, cs->eb.invflags & EBT_IOUT); - - xlate_ifname(xl, "meta ibridgename", cs->eb.logical_in, - cs->eb.invflags & EBT_ILOGICALIN); - xlate_ifname(xl, "meta obridgename", cs->eb.logical_out, + xlate_ifname(xl, "meta obrname", cs->eb.logical_out, cs->eb.invflags & EBT_ILOGICALOUT); if ((cs->eb.bitmask & EBT_NOPROTO) == 0) { @@ -667,7 +696,7 @@ static int nft_bridge_xlate(const void *data, struct xt_xlate *xl) } if (!implicit || !xlate_find_match(cs, implicit)) - xt_xlate_add(xl, "ether type %s 0x%x ", + xt_xlate_add(xl, "ether type %s0x%x ", cs->eb.invflags & EBT_IPROTO ? "!= " : "", ntohs(cs->eb.ethproto)); } @@ -675,30 +704,12 @@ static int nft_bridge_xlate(const void *data, struct xt_xlate *xl) if (cs->eb.bitmask & EBT_802_3) return 0; - if (cs->eb.bitmask & EBT_ISOURCE) { - addr = ether_ntoa((struct ether_addr *) cs->eb.sourcemac); - - xt_xlate_add(xl, "ether saddr %s%s ", - cs->eb.invflags & EBT_ISOURCE ? "!= " : "", addr); - - if (memcmp(cs->eb.sourcemsk, one_msk, sizeof(cs->eb.sourcemsk))) { - addr = ether_ntoa((struct ether_addr *) cs->eb.sourcemsk); - xt_xlate_add(xl, "and %s ", addr); - } - } - - if (cs->eb.bitmask & EBT_IDEST) { - addr = ether_ntoa((struct ether_addr *) cs->eb.destmac); - - xt_xlate_add(xl, "ether daddr %s %s ", - cs->eb.invflags & EBT_IDEST ? "!= " : "", addr); - - if (memcmp(cs->eb.destmsk, one_msk, sizeof(cs->eb.destmsk))) { - addr = ether_ntoa((struct ether_addr *) cs->eb.destmsk); - xt_xlate_add(xl, "and %s ", addr); - } - } - + if (cs->eb.bitmask & EBT_ISOURCE) + nft_bridge_xlate_mac(xl, "saddr", cs->eb.invflags & EBT_ISOURCE, + cs->eb.sourcemac, cs->eb.sourcemsk); + if (cs->eb.bitmask & EBT_IDEST) + nft_bridge_xlate_mac(xl, "daddr", cs->eb.invflags & EBT_IDEST, + cs->eb.destmac, cs->eb.destmsk); ret = xlate_ebmatches(cs, xl); if (ret == 0) return ret; -- cgit v1.2.3