]> git.ipfire.org Git - thirdparty/iptables.git/commitdiff
xtables-compat: ebtables: allow checking for zero-mac
authorFlorian Westphal <fw@strlen.de>
Tue, 8 May 2018 14:31:29 +0000 (16:31 +0200)
committerFlorian Westphal <fw@strlen.de>
Thu, 10 May 2018 00:31:05 +0000 (02:31 +0200)
Allow checking for an all-zero mac address by replacing checks on the
address with a check on the option flag.

Its set when '-d' or '-s' appears on the command line and when seeing
a linklayer payload request for ether s/daddr.

Same for -p: s this flag gets removed during getopt when 'p' is encountered.

So, if its set, no need to check protocol type.

Signed-off-by: Florian Westphal <fw@strlen.de>
iptables/nft-bridge.c
iptables/nft-bridge.h
iptables/xtables-eb-translate.c
iptables/xtables-eb.c

index 86601774498fd27f2db98369c33cb9719f4acb41..bf8949a5f39bef94712ee93474e4a2a71738ef1f 100644 (file)
@@ -147,7 +147,6 @@ static int nft_bridge_add(struct nftnl_rule *r, void *data)
        struct ebt_match *iter;
        struct ebt_entry *fw = &cs->eb;
        uint32_t op;
-       char *addr;
 
        if (fw->in[0] != '\0') {
                op = nft_invflags2cmp(fw->invflags, EBT_IIN);
@@ -169,8 +168,7 @@ static int nft_bridge_add(struct nftnl_rule *r, void *data)
                add_logical_outiface(r, fw->logical_out, op);
        }
 
-       addr = ether_ntoa((struct ether_addr *) fw->sourcemac);
-       if (strcmp(addr, "0:0:0:0:0:0") != 0) {
+       if (fw->bitmask & EBT_ISOURCE) {
                op = nft_invflags2cmp(fw->invflags, EBT_ISOURCE);
                add_payload(r, offsetof(struct ethhdr, h_source), 6,
                            NFT_PAYLOAD_LL_HEADER);
@@ -179,8 +177,7 @@ static int nft_bridge_add(struct nftnl_rule *r, void *data)
                add_cmp_ptr(r, op, fw->sourcemac, 6);
        }
 
-       addr = ether_ntoa((struct ether_addr *) fw->destmac);
-       if (strcmp(addr, "0:0:0:0:0:0") != 0) {
+       if (fw->bitmask & EBT_IDEST) {
                op = nft_invflags2cmp(fw->invflags, EBT_IDEST);
                add_payload(r, offsetof(struct ethhdr, h_dest), 6,
                            NFT_PAYLOAD_LL_HEADER);
@@ -189,7 +186,7 @@ static int nft_bridge_add(struct nftnl_rule *r, void *data)
                add_cmp_ptr(r, op, fw->destmac, 6);
        }
 
-       if (fw->ethproto != 0) {
+       if ((fw->bitmask & EBT_NOPROTO) == 0) {
                op = nft_invflags2cmp(fw->invflags, EBT_IPROTO);
                add_payload(r, offsetof(struct ethhdr, h_proto), 2,
                            NFT_PAYLOAD_LL_HEADER);
@@ -277,6 +274,7 @@ static void nft_bridge_parse_payload(struct nft_xt_ctx *ctx,
                 } else {
                         memset(&fw->destmsk, 0xff, ETH_ALEN);
                 }
+               fw->bitmask |= EBT_IDEST;
                break;
        case offsetof(struct ethhdr, h_source):
                get_cmp_data(e, addr, sizeof(addr), &inv);
@@ -290,12 +288,14 @@ static void nft_bridge_parse_payload(struct nft_xt_ctx *ctx,
                 } else {
                         memset(&fw->sourcemsk, 0xff, ETH_ALEN);
                 }
+               fw->bitmask |= EBT_ISOURCE;
                break;
        case offsetof(struct ethhdr, h_proto):
                get_cmp_data(e, &ethproto, sizeof(ethproto), &inv);
                fw->ethproto = ethproto;
                if (inv)
                        fw->invflags |= EBT_IPROTO;
+               fw->bitmask &= ~EBT_NOPROTO;
                break;
        }
 }
@@ -413,6 +413,30 @@ static void print_mac(char option, const unsigned char *mac,
 }
 
 
+static void print_protocol(uint16_t ethproto, bool invert, unsigned int bitmask)
+{
+       struct ethertypeent *ent;
+
+       /* Dont print anything about the protocol if no protocol was
+        * specified, obviously this means any protocol will do. */
+       if (bitmask & EBT_NOPROTO)
+               return;
+
+       printf("-p ");
+       if (invert)
+               printf("! ");
+
+       if (bitmask & EBT_802_3) {
+               printf("length ");
+               return;
+       }
+
+       ent = getethertypebynumber(ntohs(ethproto));
+       if (!ent)
+               printf("0x%x ", ntohs(ethproto));
+       else
+               printf("%s ", ent->e_name);
+}
 
 static void nft_bridge_print_firewall(struct nftnl_rule *r, unsigned int num,
                                      unsigned int format)
@@ -424,29 +448,13 @@ static void nft_bridge_print_firewall(struct nftnl_rule *r, unsigned int num,
        if (format & FMT_LINENUMBERS)
                printf("%d ", num);
 
-       /* Dont print anything about the protocol if no protocol was
-        * specified, obviously this means any protocol will do. */
-       if (cs.eb.ethproto != 0) {
-               printf("-p ");
-               if (cs.eb.invflags & EBT_IPROTO)
-                       printf("! ");
-               if (cs.eb.bitmask & EBT_802_3)
-                       printf("Length ");
-               else {
-                       struct ethertypeent *ent;
-
-                       ent = getethertypebynumber(ntohs(cs.eb.ethproto));
-                       if (!ent)
-                               printf("0x%x ", ntohs(cs.eb.ethproto));
-                       else
-                               printf("%s ", ent->e_name);
-               }
-       }
-
-       print_mac('s', cs.eb.sourcemac, cs.eb.sourcemsk,
-                 cs.eb.invflags & EBT_ISOURCE);
-       print_mac('d', cs.eb.destmac, cs.eb.destmsk,
-                 cs.eb.invflags & EBT_IDEST);
+       print_protocol(cs.eb.ethproto, cs.eb.invflags & EBT_IPROTO, cs.eb.bitmask);
+       if (cs.eb.bitmask & EBT_ISOURCE)
+               print_mac('s', cs.eb.sourcemac, cs.eb.sourcemsk,
+                         cs.eb.invflags & EBT_ISOURCE);
+       if (cs.eb.bitmask & EBT_IDEST)
+               print_mac('d', cs.eb.destmac, cs.eb.destmsk,
+                         cs.eb.invflags & EBT_IDEST);
 
        print_iface("-i", cs.eb.in, cs.eb.invflags & EBT_IIN);
        print_iface("--logical-in", cs.eb.logical_in, cs.eb.invflags & EBT_ILOGICALIN);
@@ -628,7 +636,6 @@ 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};
-       char zero_msk[ETH_ALEN] = {};
        const char *addr;
        int ret;
 
@@ -642,7 +649,7 @@ static int nft_bridge_xlate(const void *data, struct xt_xlate *xl)
        xlate_ifname(xl, "meta obridgename", cs->eb.logical_out,
                     cs->eb.invflags & EBT_ILOGICALOUT);
 
-       if (cs->eb.ethproto != 0) {
+       if ((cs->eb.bitmask & EBT_NOPROTO) == 0) {
                xt_xlate_add(xl, "ether type %s 0x%x ",
                             cs->eb.invflags & EBT_IPROTO ? "!= " : "",
                             ntohs(cs->eb.ethproto));
@@ -651,7 +658,7 @@ static int nft_bridge_xlate(const void *data, struct xt_xlate *xl)
        if (cs->eb.bitmask & EBT_802_3)
                return 0;
 
-       if (memcmp(cs->eb.sourcemac, zero_msk, sizeof(cs->eb.sourcemac))) {
+       if (cs->eb.bitmask & EBT_ISOURCE) {
                addr = ether_ntoa((struct ether_addr *) cs->eb.sourcemac);
 
                xt_xlate_add(xl, "ether saddr %s%s ",
@@ -663,11 +670,11 @@ static int nft_bridge_xlate(const void *data, struct xt_xlate *xl)
                }
        }
 
-       if (memcmp(cs->eb.destmac, zero_msk, sizeof(cs->eb.destmac))) {
+       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_ISOURCE ? "!= " : "", addr);
+                            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);
index 3ee04640f162e442578dca62ba8fe1ca407aff29..8dcb151f9e36e35a523ab460ad01de0e9c856791 100644 (file)
@@ -15,9 +15,6 @@
 #define LIST_X   0x10
 #define LIST_MAC2 0x20
 
-/* Be backwards compatible, so don't use '+' in kernel */
-#define IF_WILDCARD 1
-
 extern unsigned char eb_mac_type_unicast[ETH_ALEN];
 extern unsigned char eb_msk_type_unicast[ETH_ALEN];
 extern unsigned char eb_mac_type_multicast[ETH_ALEN];
index 23d261e0a8adfb653af9a1114da75131fc67429d..e54415a2f1ed10d0681d9d285a2420356d016d33 100644 (file)
@@ -305,7 +305,6 @@ static void ebtables_parse_interface(const char *arg, char *vianame)
                if (*(c + 1) != '\0')
                        xtables_error(PARAMETER_PROBLEM,
                                      "Spurious characters after '+' wildcard");
-               *c = IF_WILDCARD;
        }
 }
 
@@ -392,6 +391,7 @@ static int do_commandeb_xlate(struct nft_handle *h, int argc, char *argv[], char
 
        /* prevent getopt to spoil our error reporting */
        opterr = false;
+       cs.eb.bitmask = EBT_NOPROTO;
 
        printf("nft ");
        /* Getopt saves the day */
index 5f8f0fb5856914e127c45f040ab2d50f62c429ca..ba26aca1018285856ae9846a43a239dc97f5244f 100644 (file)
@@ -790,6 +790,7 @@ int do_commandeb(struct nft_handle *h, int argc, char *argv[], char **table)
 
        /* prevent getopt to spoil our error reporting */
        opterr = false;
+       cs.eb.bitmask = EBT_NOPROTO;
 
        /* Getopt saves the day */
        while ((c = getopt_long(argc, argv,