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
;
22 struct arphdr _arph
, *ah
;
24 ah
= skb_header_pointer(skb
, 0, sizeof(_arph
), &_arph
);
27 if (info
->bitmask
& EBT_ARP_OPCODE
&& FWINV(info
->opcode
!=
28 ah
->ar_op
, EBT_ARP_OPCODE
))
30 if (info
->bitmask
& EBT_ARP_HTYPE
&& FWINV(info
->htype
!=
31 ah
->ar_hrd
, EBT_ARP_HTYPE
))
33 if (info
->bitmask
& EBT_ARP_PTYPE
&& FWINV(info
->ptype
!=
34 ah
->ar_pro
, EBT_ARP_PTYPE
))
37 if (info
->bitmask
& (EBT_ARP_SRC_IP
| EBT_ARP_DST_IP
)) {
38 __be32 saddr
, daddr
, *sap
, *dap
;
40 if (ah
->ar_pln
!= sizeof(__be32
) || ah
->ar_pro
!= htons(ETH_P_IP
))
42 sap
= skb_header_pointer(skb
, sizeof(struct arphdr
) +
43 ah
->ar_hln
, sizeof(saddr
),
47 dap
= skb_header_pointer(skb
, sizeof(struct arphdr
) +
48 2*ah
->ar_hln
+sizeof(saddr
),
49 sizeof(daddr
), &daddr
);
52 if (info
->bitmask
& EBT_ARP_SRC_IP
&&
53 FWINV(info
->saddr
!= (*sap
& info
->smsk
), EBT_ARP_SRC_IP
))
55 if (info
->bitmask
& EBT_ARP_DST_IP
&&
56 FWINV(info
->daddr
!= (*dap
& info
->dmsk
), EBT_ARP_DST_IP
))
58 if (info
->bitmask
& EBT_ARP_GRAT
&&
59 FWINV(*dap
!= *sap
, EBT_ARP_GRAT
))
63 if (info
->bitmask
& (EBT_ARP_SRC_MAC
| EBT_ARP_DST_MAC
)) {
64 unsigned char _mac
[ETH_ALEN
], *mp
;
67 if (ah
->ar_hln
!= ETH_ALEN
|| ah
->ar_hrd
!= htons(ARPHRD_ETHER
))
69 if (info
->bitmask
& EBT_ARP_SRC_MAC
) {
70 mp
= skb_header_pointer(skb
, sizeof(struct arphdr
),
75 for (i
= 0; i
< 6; i
++)
76 verdict
|= (mp
[i
] ^ info
->smaddr
[i
]) &
78 if (FWINV(verdict
!= 0, EBT_ARP_SRC_MAC
))
82 if (info
->bitmask
& EBT_ARP_DST_MAC
) {
83 mp
= skb_header_pointer(skb
, sizeof(struct arphdr
) +
84 ah
->ar_hln
+ ah
->ar_pln
,
89 for (i
= 0; i
< 6; i
++)
90 verdict
|= (mp
[i
] ^ info
->dmaddr
[i
]) &
92 if (FWINV(verdict
!= 0, EBT_ARP_DST_MAC
))
100 static int ebt_arp_check(const char *tablename
, unsigned int hookmask
,
101 const struct ebt_entry
*e
, void *data
, unsigned int datalen
)
103 struct ebt_arp_info
*info
= (struct ebt_arp_info
*)data
;
105 if (datalen
!= EBT_ALIGN(sizeof(struct ebt_arp_info
)))
107 if ((e
->ethproto
!= htons(ETH_P_ARP
) &&
108 e
->ethproto
!= htons(ETH_P_RARP
)) ||
109 e
->invflags
& EBT_IPROTO
)
111 if (info
->bitmask
& ~EBT_ARP_MASK
|| info
->invflags
& ~EBT_ARP_MASK
)
116 static struct ebt_match filter_arp
=
118 .name
= EBT_ARP_MATCH
,
119 .match
= ebt_filter_arp
,
120 .check
= ebt_arp_check
,
124 static int __init
ebt_arp_init(void)
126 return ebt_register_match(&filter_arp
);
129 static void __exit
ebt_arp_fini(void)
131 ebt_unregister_match(&filter_arp
);
134 module_init(ebt_arp_init
);
135 module_exit(ebt_arp_fini
);
136 MODULE_LICENSE("GPL");