summaryrefslogtreecommitdiffstats
path: root/kernel/linux/net/bridge/netfilter/ebt_arp.c
diff options
context:
space:
mode:
authorBart De Schuymer <bdschuym@pandora.be>2003-05-01 20:21:52 +0000
committerBart De Schuymer <bdschuym@pandora.be>2003-05-01 20:21:52 +0000
commit6caf621b0d616a03f1b698ed3dab0c5d29348620 (patch)
tree066dac5a983abeb7f1c939de5bb9610b0da0abf0 /kernel/linux/net/bridge/netfilter/ebt_arp.c
parent265fa6126245f9285c9bf2da535a798afa8242b5 (diff)
add arp mac address matching
Diffstat (limited to 'kernel/linux/net/bridge/netfilter/ebt_arp.c')
-rw-r--r--kernel/linux/net/bridge/netfilter/ebt_arp.c45
1 files changed, 45 insertions, 0 deletions
diff --git a/kernel/linux/net/bridge/netfilter/ebt_arp.c b/kernel/linux/net/bridge/netfilter/ebt_arp.c
index ba2a2ac..0b3ffe1 100644
--- a/kernel/linux/net/bridge/netfilter/ebt_arp.c
+++ b/kernel/linux/net/bridge/netfilter/ebt_arp.c
@@ -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,50 @@ 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;
}