summaryrefslogtreecommitdiffstats
path: root/kernel/linux2.5/net/bridge/netfilter/ebt_arp.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/linux2.5/net/bridge/netfilter/ebt_arp.c')
-rw-r--r--kernel/linux2.5/net/bridge/netfilter/ebt_arp.c45
1 files changed, 45 insertions, 0 deletions
diff --git a/kernel/linux2.5/net/bridge/netfilter/ebt_arp.c b/kernel/linux2.5/net/bridge/netfilter/ebt_arp.c
index 35d2608..0d1650b 100644
--- a/kernel/linux2.5/net/bridge/netfilter/ebt_arp.c
+++ b/kernel/linux2.5/net/bridge/netfilter/ebt_arp.c
@@ -13,6 +13,7 @@
#include <linux/netfilter_bridge/ebt_arp.h>
#include <linux/if_arp.h>
#include <linux/module.h>
+#include <linux/if_ether.h>
static int ebt_filter_arp(const struct sk_buff *skb, const struct net_device *in,
const struct net_device *out, const void *data, unsigned int datalen)
@@ -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;
}