aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBart De Schuymer <bdschuym@pandora.be>2007-04-13 01:15:06 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2007-04-26 01:28:58 -0400
commitc15bf6e699f4c366f2d1e19ac5d7add21c6b5a19 (patch)
tree2bcd680115a8b07cd6d7493b134ae2d36fe637be
parent516299d2f5b6f9703b9b388faf91898dc636a678 (diff)
[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>
-rw-r--r--include/linux/netfilter_bridge/ebt_arp.h4
-rw-r--r--net/bridge/netfilter/ebt_arp.c48
2 files changed, 25 insertions, 27 deletions
diff --git a/include/linux/netfilter_bridge/ebt_arp.h b/include/linux/netfilter_bridge/ebt_arp.h
index 97e4dbde1f89..cbf4843b6b0f 100644
--- a/include/linux/netfilter_bridge/ebt_arp.h
+++ b/include/linux/netfilter_bridge/ebt_arp.h
@@ -8,8 +8,10 @@
8#define EBT_ARP_DST_IP 0x10 8#define EBT_ARP_DST_IP 0x10
9#define EBT_ARP_SRC_MAC 0x20 9#define EBT_ARP_SRC_MAC 0x20
10#define EBT_ARP_DST_MAC 0x40 10#define EBT_ARP_DST_MAC 0x40
11#define EBT_ARP_GRAT 0x80
11#define EBT_ARP_MASK (EBT_ARP_OPCODE | EBT_ARP_HTYPE | EBT_ARP_PTYPE | \ 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#define EBT_ARP_MATCH "arp" 15#define EBT_ARP_MATCH "arp"
14 16
15struct ebt_arp_info 17struct ebt_arp_info
diff --git a/net/bridge/netfilter/ebt_arp.c b/net/bridge/netfilter/ebt_arp.c
index 9c599800a900..1a46952a56d9 100644
--- a/net/bridge/netfilter/ebt_arp.c
+++ b/net/bridge/netfilter/ebt_arp.c
@@ -35,40 +35,36 @@ static int ebt_filter_arp(const struct sk_buff *skb, const struct net_device *in
35 return EBT_NOMATCH; 35 return EBT_NOMATCH;
36 36
37 if (info->bitmask & (EBT_ARP_SRC_IP | EBT_ARP_DST_IP)) { 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 */ 40 if (ah->ar_pln != sizeof(__be32) || ah->ar_pro != htons(ETH_P_IP))
41 if (ah->ar_pln != sizeof(__be32)) 41 return EBT_NOMATCH;
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))
42 return EBT_NOMATCH; 60 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 }
64 } 61 }
65 62
66 if (info->bitmask & (EBT_ARP_SRC_MAC | EBT_ARP_DST_MAC)) { 63 if (info->bitmask & (EBT_ARP_SRC_MAC | EBT_ARP_DST_MAC)) {
67 unsigned char _mac[ETH_ALEN], *mp; 64 unsigned char _mac[ETH_ALEN], *mp;
68 uint8_t verdict, i; 65 uint8_t verdict, i;
69 66
70 /* MAC addresses are 6 bytes */ 67 if (ah->ar_hln != ETH_ALEN || ah->ar_hrd != htons(ARPHRD_ETHER))
71 if (ah->ar_hln != ETH_ALEN)
72 return EBT_NOMATCH; 68 return EBT_NOMATCH;
73 if (info->bitmask & EBT_ARP_SRC_MAC) { 69 if (info->bitmask & EBT_ARP_SRC_MAC) {
74 mp = skb_header_pointer(skb, sizeof(struct arphdr), 70 mp = skb_header_pointer(skb, sizeof(struct arphdr),