[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>
This commit is contained in:
parent
516299d2f5
commit
c15bf6e699
|
@ -8,8 +8,10 @@
|
|||
#define EBT_ARP_DST_IP 0x10
|
||||
#define EBT_ARP_SRC_MAC 0x20
|
||||
#define EBT_ARP_DST_MAC 0x40
|
||||
#define EBT_ARP_GRAT 0x80
|
||||
#define EBT_ARP_MASK (EBT_ARP_OPCODE | EBT_ARP_HTYPE | EBT_ARP_PTYPE | \
|
||||
EBT_ARP_SRC_IP | EBT_ARP_DST_IP | EBT_ARP_SRC_MAC | EBT_ARP_DST_MAC)
|
||||
EBT_ARP_SRC_IP | EBT_ARP_DST_IP | EBT_ARP_SRC_MAC | EBT_ARP_DST_MAC | \
|
||||
EBT_ARP_GRAT)
|
||||
#define EBT_ARP_MATCH "arp"
|
||||
|
||||
struct ebt_arp_info
|
||||
|
|
|
@ -35,40 +35,36 @@ static int ebt_filter_arp(const struct sk_buff *skb, const struct net_device *in
|
|||
return EBT_NOMATCH;
|
||||
|
||||
if (info->bitmask & (EBT_ARP_SRC_IP | EBT_ARP_DST_IP)) {
|
||||
__be32 _addr, *ap;
|
||||
__be32 saddr, daddr, *sap, *dap;
|
||||
|
||||
/* IPv4 addresses are always 4 bytes */
|
||||
if (ah->ar_pln != sizeof(__be32))
|
||||
if (ah->ar_pln != sizeof(__be32) || ah->ar_pro != htons(ETH_P_IP))
|
||||
return EBT_NOMATCH;
|
||||
if (info->bitmask & EBT_ARP_SRC_IP) {
|
||||
ap = skb_header_pointer(skb, sizeof(struct arphdr) +
|
||||
ah->ar_hln, sizeof(_addr),
|
||||
&_addr);
|
||||
if (ap == NULL)
|
||||
sap = skb_header_pointer(skb, sizeof(struct arphdr) +
|
||||
ah->ar_hln, sizeof(saddr),
|
||||
&saddr);
|
||||
if (sap == NULL)
|
||||
return EBT_NOMATCH;
|
||||
if (FWINV(info->saddr != (*ap & info->smsk),
|
||||
EBT_ARP_SRC_IP))
|
||||
dap = skb_header_pointer(skb, sizeof(struct arphdr) +
|
||||
2*ah->ar_hln+sizeof(saddr),
|
||||
sizeof(daddr), &daddr);
|
||||
if (dap == NULL)
|
||||
return EBT_NOMATCH;
|
||||
}
|
||||
|
||||
if (info->bitmask & EBT_ARP_DST_IP) {
|
||||
ap = skb_header_pointer(skb, sizeof(struct arphdr) +
|
||||
2*ah->ar_hln+sizeof(__be32),
|
||||
sizeof(_addr), &_addr);
|
||||
if (ap == NULL)
|
||||
if (info->bitmask & EBT_ARP_SRC_IP &&
|
||||
FWINV(info->saddr != (*sap & info->smsk), EBT_ARP_SRC_IP))
|
||||
return EBT_NOMATCH;
|
||||
if (FWINV(info->daddr != (*ap & info->dmsk),
|
||||
EBT_ARP_DST_IP))
|
||||
if (info->bitmask & EBT_ARP_DST_IP &&
|
||||
FWINV(info->daddr != (*dap & info->dmsk), EBT_ARP_DST_IP))
|
||||
return EBT_NOMATCH;
|
||||
if (info->bitmask & EBT_ARP_GRAT &&
|
||||
FWINV(*dap != *sap, EBT_ARP_GRAT))
|
||||
return EBT_NOMATCH;
|
||||
}
|
||||
}
|
||||
|
||||
if (info->bitmask & (EBT_ARP_SRC_MAC | EBT_ARP_DST_MAC)) {
|
||||
unsigned char _mac[ETH_ALEN], *mp;
|
||||
uint8_t verdict, i;
|
||||
|
||||
/* MAC addresses are 6 bytes */
|
||||
if (ah->ar_hln != ETH_ALEN)
|
||||
if (ah->ar_hln != ETH_ALEN || ah->ar_hrd != htons(ARPHRD_ETHER))
|
||||
return EBT_NOMATCH;
|
||||
if (info->bitmask & EBT_ARP_SRC_MAC) {
|
||||
mp = skb_header_pointer(skb, sizeof(struct arphdr),
|
||||
|
|
Loading…
Reference in New Issue