5 * Bart De Schuymer <bdschuym@pandora.be>
6 * Tim Gardner <timg@tpi.com>
12 #include <linux/netfilter_bridge/ebtables.h>
13 #include <linux/netfilter_bridge/ebt_arp.h>
14 #include <linux/if_arp.h>
15 #include <linux/if_ether.h>
16 #include <linux/module.h>
18 static int ebt_filter_arp(const struct sk_buff *skb, const struct net_device *in,
19 const struct net_device *out, const void *data, unsigned int datalen)
21 struct ebt_arp_info *info = (struct ebt_arp_info *)data;
24 if (skb_copy_bits(skb, 0, &arph, sizeof(arph)))
26 if (info->bitmask & EBT_ARP_OPCODE && FWINV(info->opcode !=
27 arph.ar_op, EBT_ARP_OPCODE))
29 if (info->bitmask & EBT_ARP_HTYPE && FWINV(info->htype !=
30 arph.ar_hrd, EBT_ARP_HTYPE))
32 if (info->bitmask & EBT_ARP_PTYPE && FWINV(info->ptype !=
33 arph.ar_pro, EBT_ARP_PTYPE))
36 if (info->bitmask & (EBT_ARP_SRC_IP | EBT_ARP_DST_IP)) {
39 /* IPv4 addresses are always 4 bytes */
40 if (arph.ar_pln != sizeof(uint32_t))
42 if (info->bitmask & EBT_ARP_SRC_IP) {
43 if (skb_copy_bits(skb, sizeof(struct arphdr) +
44 arph.ar_hln, &addr, sizeof(addr)))
46 if (FWINV(info->saddr != (addr & info->smsk),
51 if (info->bitmask & EBT_ARP_DST_IP) {
52 if (skb_copy_bits(skb, sizeof(struct arphdr) +
53 2*arph.ar_hln + sizeof(uint32_t), &addr,
56 if (FWINV(info->daddr != (addr & info->dmsk),
62 if (info->bitmask & (EBT_ARP_SRC_MAC | EBT_ARP_DST_MAC)) {
63 unsigned char mac[ETH_ALEN];
66 /* MAC addresses are 6 bytes */
67 if (arph.ar_hln != ETH_ALEN)
69 if (info->bitmask & EBT_ARP_SRC_MAC) {
70 if (skb_copy_bits(skb, sizeof(struct arphdr), &mac,
74 for (i = 0; i < 6; i++)
75 verdict |= (mac[i] ^ info->smaddr[i]) &
77 if (FWINV(verdict != 0, EBT_ARP_SRC_MAC))
81 if (info->bitmask & EBT_ARP_DST_MAC) {
82 if (skb_copy_bits(skb, sizeof(struct arphdr) +
83 arph.ar_hln + arph.ar_pln, &mac, ETH_ALEN))
86 for (i = 0; i < 6; i++)
87 verdict |= (mac[i] ^ info->dmaddr[i]) &
89 if (FWINV(verdict != 0, EBT_ARP_DST_MAC))
97 static int ebt_arp_check(const char *tablename, unsigned int hookmask,
98 const struct ebt_entry *e, void *data, unsigned int datalen)
100 struct ebt_arp_info *info = (struct ebt_arp_info *)data;
102 if (datalen != EBT_ALIGN(sizeof(struct ebt_arp_info)))
104 if ((e->ethproto != __constant_htons(ETH_P_ARP) &&
105 e->ethproto != __constant_htons(ETH_P_RARP)) ||
106 e->invflags & EBT_IPROTO)
108 if (info->bitmask & ~EBT_ARP_MASK || info->invflags & ~EBT_ARP_MASK)
113 static struct ebt_match filter_arp =
115 .name = EBT_ARP_MATCH,
116 .match = ebt_filter_arp,
117 .check = ebt_arp_check,
121 static int __init init(void)
123 return ebt_register_match(&filter_arp);
126 static void __exit fini(void)
128 ebt_unregister_match(&filter_arp);
133 MODULE_LICENSE("GPL");