5 * Bart De Schuymer <bdschuym@pandora.be>
6 * Tim Gardner <timg@tpi.com>
11 #include <linux/if_arp.h>
12 #include <linux/if_ether.h>
13 #include <linux/module.h>
14 #include <linux/netfilter/x_tables.h>
15 #include <linux/netfilter_bridge/ebtables.h>
16 #include <linux/netfilter_bridge/ebt_arp.h>
19 ebt_arp_mt(const struct sk_buff
*skb
, struct xt_action_param
*par
)
21 const struct ebt_arp_info
*info
= par
->matchinfo
;
22 const struct arphdr
*ah
;
25 ah
= skb_header_pointer(skb
, 0, sizeof(_arph
), &_arph
);
28 if ((info
->bitmask
& EBT_ARP_OPCODE
) &&
29 NF_INVF(info
, EBT_ARP_OPCODE
, info
->opcode
!= ah
->ar_op
))
31 if ((info
->bitmask
& EBT_ARP_HTYPE
) &&
32 NF_INVF(info
, EBT_ARP_HTYPE
, info
->htype
!= ah
->ar_hrd
))
34 if ((info
->bitmask
& EBT_ARP_PTYPE
) &&
35 NF_INVF(info
, EBT_ARP_PTYPE
, info
->ptype
!= ah
->ar_pro
))
38 if (info
->bitmask
& (EBT_ARP_SRC_IP
| EBT_ARP_DST_IP
| EBT_ARP_GRAT
)) {
39 const __be32
*sap
, *dap
;
42 if (ah
->ar_pln
!= sizeof(__be32
) || ah
->ar_pro
!= htons(ETH_P_IP
))
44 sap
= skb_header_pointer(skb
, sizeof(struct arphdr
) +
45 ah
->ar_hln
, sizeof(saddr
),
49 dap
= skb_header_pointer(skb
, sizeof(struct arphdr
) +
50 2*ah
->ar_hln
+sizeof(saddr
),
51 sizeof(daddr
), &daddr
);
54 if ((info
->bitmask
& EBT_ARP_SRC_IP
) &&
55 NF_INVF(info
, EBT_ARP_SRC_IP
,
56 info
->saddr
!= (*sap
& info
->smsk
)))
58 if ((info
->bitmask
& EBT_ARP_DST_IP
) &&
59 NF_INVF(info
, EBT_ARP_DST_IP
,
60 info
->daddr
!= (*dap
& info
->dmsk
)))
62 if ((info
->bitmask
& EBT_ARP_GRAT
) &&
63 NF_INVF(info
, EBT_ARP_GRAT
, *dap
!= *sap
))
67 if (info
->bitmask
& (EBT_ARP_SRC_MAC
| EBT_ARP_DST_MAC
)) {
68 const unsigned char *mp
;
69 unsigned char _mac
[ETH_ALEN
];
71 if (ah
->ar_hln
!= ETH_ALEN
|| ah
->ar_hrd
!= htons(ARPHRD_ETHER
))
73 if (info
->bitmask
& EBT_ARP_SRC_MAC
) {
74 mp
= skb_header_pointer(skb
, sizeof(struct arphdr
),
78 if (NF_INVF(info
, EBT_ARP_SRC_MAC
,
79 !ether_addr_equal_masked(mp
, info
->smaddr
,
84 if (info
->bitmask
& EBT_ARP_DST_MAC
) {
85 mp
= skb_header_pointer(skb
, sizeof(struct arphdr
) +
86 ah
->ar_hln
+ ah
->ar_pln
,
90 if (NF_INVF(info
, EBT_ARP_DST_MAC
,
91 !ether_addr_equal_masked(mp
, info
->dmaddr
,
100 static int ebt_arp_mt_check(const struct xt_mtchk_param
*par
)
102 const struct ebt_arp_info
*info
= par
->matchinfo
;
103 const struct ebt_entry
*e
= par
->entryinfo
;
105 if ((e
->ethproto
!= htons(ETH_P_ARP
) &&
106 e
->ethproto
!= htons(ETH_P_RARP
)) ||
107 e
->invflags
& EBT_IPROTO
)
109 if (info
->bitmask
& ~EBT_ARP_MASK
|| info
->invflags
& ~EBT_ARP_MASK
)
114 static struct xt_match ebt_arp_mt_reg __read_mostly
= {
117 .family
= NFPROTO_BRIDGE
,
119 .checkentry
= ebt_arp_mt_check
,
120 .matchsize
= sizeof(struct ebt_arp_info
),
124 static int __init
ebt_arp_init(void)
126 return xt_register_match(&ebt_arp_mt_reg
);
129 static void __exit
ebt_arp_fini(void)
131 xt_unregister_match(&ebt_arp_mt_reg
);
134 module_init(ebt_arp_init
);
135 module_exit(ebt_arp_fini
);
136 MODULE_DESCRIPTION("Ebtables: ARP protocol packet match");
137 MODULE_LICENSE("GPL");