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@xxxxxxxxx> --- iptables/nft-bridge.c | 73 ++++++++++++++++++++++------------------- iptables/nft-bridge.h | 3 -- iptables/xtables-eb-translate.c | 2 +- iptables/xtables-eb.c | 1 + 4 files changed, 42 insertions(+), 37 deletions(-) diff --git a/iptables/nft-bridge.c b/iptables/nft-bridge.c index 86601774498f..83410297139d 100644 --- a/iptables/nft-bridge.c +++ b/iptables/nft-bridge.c @@ -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, ðproto, 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; @@ -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); diff --git a/iptables/nft-bridge.h b/iptables/nft-bridge.h index 3ee04640f162..8dcb151f9e36 100644 --- a/iptables/nft-bridge.h +++ b/iptables/nft-bridge.h @@ -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]; diff --git a/iptables/xtables-eb-translate.c b/iptables/xtables-eb-translate.c index 23d261e0a8ad..e54415a2f1ed 100644 --- a/iptables/xtables-eb-translate.c +++ b/iptables/xtables-eb-translate.c @@ -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 */ diff --git a/iptables/xtables-eb.c b/iptables/xtables-eb.c index 5f8f0fb58569..ba26aca10182 100644 --- a/iptables/xtables-eb.c +++ b/iptables/xtables-eb.c @@ -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, -- 2.16.1 -- To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html