Commit c15bf6e699f4c366f2d1e19ac5d7add21c6b5a19
Committed by
David S. Miller
1 parent
516299d2f5
Exists in
master
and in
4 other branches
[NETFILTER]: ebt_arp: add gratuitous arp filtering
The attached patch adds gratuitous arp filtering, more precisely: it allows checking that the IPv4 source address matches the IPv4 destination address inside the ARP header. It also adds a check for the hardware address type when matching MAC addresses (nothing critical, just for better consistency). Signed-off-by: Bart De Schuymer <bdschuym@pandora.be> Acked-by: Carl-Daniel Hailfinger <c-d.hailfinger.devel.2006@gmx.net> Signed-off-by: Patrick McHardy <kaber@trash.net> Signed-off-by: David S. Miller <davem@davemloft.net>
Showing 2 changed files with 25 additions and 27 deletions Side-by-side Diff
include/linux/netfilter_bridge/ebt_arp.h
... | ... | @@ -8,8 +8,10 @@ |
8 | 8 | #define EBT_ARP_DST_IP 0x10 |
9 | 9 | #define EBT_ARP_SRC_MAC 0x20 |
10 | 10 | #define EBT_ARP_DST_MAC 0x40 |
11 | +#define EBT_ARP_GRAT 0x80 | |
11 | 12 | #define EBT_ARP_MASK (EBT_ARP_OPCODE | EBT_ARP_HTYPE | EBT_ARP_PTYPE | \ |
12 | - EBT_ARP_SRC_IP | EBT_ARP_DST_IP | EBT_ARP_SRC_MAC | EBT_ARP_DST_MAC) | |
13 | + EBT_ARP_SRC_IP | EBT_ARP_DST_IP | EBT_ARP_SRC_MAC | EBT_ARP_DST_MAC | \ | |
14 | + EBT_ARP_GRAT) | |
13 | 15 | #define EBT_ARP_MATCH "arp" |
14 | 16 | |
15 | 17 | struct ebt_arp_info |
net/bridge/netfilter/ebt_arp.c
... | ... | @@ -35,40 +35,36 @@ |
35 | 35 | return EBT_NOMATCH; |
36 | 36 | |
37 | 37 | if (info->bitmask & (EBT_ARP_SRC_IP | EBT_ARP_DST_IP)) { |
38 | - __be32 _addr, *ap; | |
38 | + __be32 saddr, daddr, *sap, *dap; | |
39 | 39 | |
40 | - /* IPv4 addresses are always 4 bytes */ | |
41 | - if (ah->ar_pln != sizeof(__be32)) | |
40 | + if (ah->ar_pln != sizeof(__be32) || ah->ar_pro != htons(ETH_P_IP)) | |
42 | 41 | return EBT_NOMATCH; |
43 | - if (info->bitmask & EBT_ARP_SRC_IP) { | |
44 | - ap = skb_header_pointer(skb, sizeof(struct arphdr) + | |
45 | - ah->ar_hln, sizeof(_addr), | |
46 | - &_addr); | |
47 | - if (ap == NULL) | |
48 | - return EBT_NOMATCH; | |
49 | - if (FWINV(info->saddr != (*ap & info->smsk), | |
50 | - EBT_ARP_SRC_IP)) | |
51 | - return EBT_NOMATCH; | |
52 | - } | |
53 | - | |
54 | - if (info->bitmask & EBT_ARP_DST_IP) { | |
55 | - ap = skb_header_pointer(skb, sizeof(struct arphdr) + | |
56 | - 2*ah->ar_hln+sizeof(__be32), | |
57 | - sizeof(_addr), &_addr); | |
58 | - if (ap == NULL) | |
59 | - return EBT_NOMATCH; | |
60 | - if (FWINV(info->daddr != (*ap & info->dmsk), | |
61 | - EBT_ARP_DST_IP)) | |
62 | - return EBT_NOMATCH; | |
63 | - } | |
42 | + sap = skb_header_pointer(skb, sizeof(struct arphdr) + | |
43 | + ah->ar_hln, sizeof(saddr), | |
44 | + &saddr); | |
45 | + if (sap == NULL) | |
46 | + return EBT_NOMATCH; | |
47 | + dap = skb_header_pointer(skb, sizeof(struct arphdr) + | |
48 | + 2*ah->ar_hln+sizeof(saddr), | |
49 | + sizeof(daddr), &daddr); | |
50 | + if (dap == NULL) | |
51 | + return EBT_NOMATCH; | |
52 | + if (info->bitmask & EBT_ARP_SRC_IP && | |
53 | + FWINV(info->saddr != (*sap & info->smsk), EBT_ARP_SRC_IP)) | |
54 | + return EBT_NOMATCH; | |
55 | + if (info->bitmask & EBT_ARP_DST_IP && | |
56 | + FWINV(info->daddr != (*dap & info->dmsk), EBT_ARP_DST_IP)) | |
57 | + return EBT_NOMATCH; | |
58 | + if (info->bitmask & EBT_ARP_GRAT && | |
59 | + FWINV(*dap != *sap, EBT_ARP_GRAT)) | |
60 | + return EBT_NOMATCH; | |
64 | 61 | } |
65 | 62 | |
66 | 63 | if (info->bitmask & (EBT_ARP_SRC_MAC | EBT_ARP_DST_MAC)) { |
67 | 64 | unsigned char _mac[ETH_ALEN], *mp; |
68 | 65 | uint8_t verdict, i; |
69 | 66 | |
70 | - /* MAC addresses are 6 bytes */ | |
71 | - if (ah->ar_hln != ETH_ALEN) | |
67 | + if (ah->ar_hln != ETH_ALEN || ah->ar_hrd != htons(ARPHRD_ETHER)) | |
72 | 68 | return EBT_NOMATCH; |
73 | 69 | if (info->bitmask & EBT_ARP_SRC_MAC) { |
74 | 70 | mp = skb_header_pointer(skb, sizeof(struct arphdr), |