summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFlorian Westphal <fw@strlen.de>2018-05-08 16:31:29 +0200
committerFlorian Westphal <fw@strlen.de>2018-05-10 02:31:05 +0200
commit07f4ca96816886635acfb9478b2d04929938eb78 (patch)
tree4e75aef91de288c9e814580703a77cc71bd73e28
parent0ca2d2a2a5994a6131ad32aedbc42b530ac529bd (diff)
xtables-compat: ebtables: allow checking for zero-mac
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>
-rw-r--r--iptables/nft-bridge.c75
-rw-r--r--iptables/nft-bridge.h3
-rw-r--r--iptables/xtables-eb-translate.c2
-rw-r--r--iptables/xtables-eb.c1
4 files changed, 43 insertions, 38 deletions
diff --git a/iptables/nft-bridge.c b/iptables/nft-bridge.c
index 86601774..bf8949a5 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, &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);
diff --git a/iptables/nft-bridge.h b/iptables/nft-bridge.h
index 3ee04640..8dcb151f 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 23d261e0..e54415a2 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 5f8f0fb5..ba26aca1 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,