to check -s 1.2.3.4, we need to add the size of the hardware address
to the arp header to obtain the offset where the ipv4 address begins:

base_arphdr
HW_ADDR
IP_ADDR (src)
IP_ADDR (target)

In arptables-classic, the kernel will add dev->addr_len to the
arp header base address to obtain the correct location, but we cannot
do this in nf_tables, at least not at this time (we need a fixed offset
value).

code does:

  op = nft_invflags2cmp(fw->arp.invflags, ARPT_INV_TGTIP);
  add_addr(r, sizeof(struct arphdr) + fw->arp.arhln + ...

but if user did not provide "--h-length 6" argument, then this won't
work even for ethernet, as the payload expression will be told to load
the first 4 bytes of arp header source mac address (sender hw address).

Fix this by pre-initialising arhlen to 6.
We also need to set up arhrd.  Otherwise, src/dst mac can't be used:

arptables -A INPUT -i lo --destination-mac 11:22:33:44:55:66
arptables v1.8.1 (nf_tables):  RULE_APPEND failed (Invalid argument): rule in 
chain INPUT

This means that matching won't work for AX25, NETROM etc, however,
arptables "classic" can't  parse non-ethernet addresses, and makes
ETH_ALEN assumptions in several spots, so this should be fine from
compatibility point of view.

Signed-off-by: Florian Westphal <f...@strlen.de>
---
 iptables/xtables-arp.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/iptables/xtables-arp.c b/iptables/xtables-arp.c
index a791ecceb88b..bde35e5dcb9c 100644
--- a/iptables/xtables-arp.c
+++ b/iptables/xtables-arp.c
@@ -905,6 +905,8 @@ int do_commandarp(struct nft_handle *h, int argc, char 
*argv[], char **table,
 {
        struct iptables_command_state cs = {
                .jumpto = "",
+               .arp.arp.arhln = 6,
+               .arp.arp.arhrd = htons(ARPHRD_ETHER),
        };
        int invert = 0;
        unsigned int nsaddrs = 0, ndaddrs = 0;
-- 
2.18.1

Reply via email to