Commit fbbcf1fe authored by Bart De Schuymer's avatar Bart De Schuymer Committed by David S. Miller

[EBTABLES]: Add ARP MAC address filtering.

parent c6a8dbb5
......@@ -6,8 +6,10 @@
#define EBT_ARP_PTYPE 0x04
#define EBT_ARP_SRC_IP 0x08
#define EBT_ARP_DST_IP 0x10
#define EBT_ARP_SRC_MAC 0x20
#define EBT_ARP_DST_MAC 0x40
#define EBT_ARP_MASK (EBT_ARP_OPCODE | EBT_ARP_HTYPE | EBT_ARP_PTYPE | \
EBT_ARP_SRC_IP | EBT_ARP_DST_IP)
EBT_ARP_SRC_IP | EBT_ARP_DST_IP | EBT_ARP_SRC_MAC | EBT_ARP_DST_MAC)
#define EBT_ARP_MATCH "arp"
struct ebt_arp_info
......@@ -19,6 +21,10 @@ struct ebt_arp_info
uint32_t smsk;
uint32_t daddr;
uint32_t dmsk;
unsigned char smaddr[ETH_ALEN];
unsigned char smmsk[ETH_ALEN];
unsigned char dmaddr[ETH_ALEN];
unsigned char dmmsk[ETH_ALEN];
uint8_t bitmask;
uint8_t invflags;
};
......
......@@ -12,6 +12,7 @@
#include <linux/netfilter_bridge/ebtables.h>
#include <linux/netfilter_bridge/ebt_arp.h>
#include <linux/if_arp.h>
#include <linux/if_ether.h>
#include <linux/module.h>
static int ebt_filter_arp(const struct sk_buff *skb, const struct net_device *in,
......@@ -61,6 +62,52 @@ static int ebt_filter_arp(const struct sk_buff *skb, const struct net_device *in
return EBT_NOMATCH;
}
}
if (info->bitmask & (EBT_ARP_SRC_MAC | EBT_ARP_DST_MAC))
{
uint32_t arp_len = sizeof(struct arphdr) +
(2 * (((*skb).nh.arph)->ar_hln)) +
(2 * (((*skb).nh.arph)->ar_pln));
unsigned char dst[ETH_ALEN];
unsigned char src[ETH_ALEN];
/* Make sure the packet is long enough */
if ((((*skb).nh.raw) + arp_len) > (*skb).tail)
return EBT_NOMATCH;
/* MAC addresses are 6 bytes */
if (((*skb).nh.arph)->ar_hln != ETH_ALEN)
return EBT_NOMATCH;
if (info->bitmask & EBT_ARP_SRC_MAC) {
uint8_t verdict, i;
memcpy(&src, ((*skb).nh.raw) +
sizeof(struct arphdr),
ETH_ALEN);
verdict = 0;
for (i = 0; i < 6; i++)
verdict |= (src[i] ^ info->smaddr[i]) &
info->smmsk[i];
if (FWINV(verdict != 0, EBT_ARP_SRC_MAC))
return EBT_NOMATCH;
}
if (info->bitmask & EBT_ARP_DST_MAC) {
uint8_t verdict, i;
memcpy(&dst, ((*skb).nh.raw) +
sizeof(struct arphdr) +
(((*skb).nh.arph)->ar_hln) +
(((*skb).nh.arph)->ar_pln),
ETH_ALEN);
verdict = 0;
for (i = 0; i < 6; i++)
verdict |= (dst[i] ^ info->dmaddr[i]) &
info->dmmsk[i];
if (FWINV(verdict != 0, EBT_ARP_DST_MAC))
return EBT_NOMATCH;
}
}
return EBT_MATCH;
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment