diff options
author | Bart De Schuymer <bdschuym@pandora.be> | 2003-05-03 18:13:34 +0000 |
---|---|---|
committer | Bart De Schuymer <bdschuym@pandora.be> | 2003-05-03 18:13:34 +0000 |
commit | 8f3864732f38c72c018138269b3e2109c3b3cd40 (patch) | |
tree | 4158e922d1934f2a4b8287c54009a02daa5be30a /kernel/linux2.5/net/bridge/netfilter/ebt_arp.c | |
parent | a3d12c061c5143c29de790a342a36e434aa3e728 (diff) |
update to 2.5.68+pkttype
Diffstat (limited to 'kernel/linux2.5/net/bridge/netfilter/ebt_arp.c')
-rw-r--r-- | kernel/linux2.5/net/bridge/netfilter/ebt_arp.c | 45 |
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; } |