5 * Grzegorz Borowiak <grzes@gnu.univ.gda.pl>
6 * Bart De Schuymer <bdschuym@pandora.be>
12 #include <linux/netfilter_bridge/ebtables.h>
13 #include <linux/netfilter_bridge/ebt_arpreply.h>
14 #include <linux/if_arp.h>
16 #include <linux/module.h>
18 static int ebt_target_reply(struct sk_buff
**pskb
, unsigned int hooknr
,
19 const struct net_device
*in
, const struct net_device
*out
,
20 const void *data
, unsigned int datalen
)
22 struct ebt_arpreply_info
*info
= (struct ebt_arpreply_info
*)data
;
23 u32 _sip
, *siptr
, _dip
, *diptr
;
24 struct arphdr _ah
, *ap
;
25 unsigned char _sha
[ETH_ALEN
], *shp
;
26 struct sk_buff
*skb
= *pskb
;
28 ap
= skb_header_pointer(skb
, 0, sizeof(_ah
), &_ah
);
32 if (ap
->ar_op
!= htons(ARPOP_REQUEST
) ||
33 ap
->ar_hln
!= ETH_ALEN
||
34 ap
->ar_pro
!= htons(ETH_P_IP
) ||
38 shp
= skb_header_pointer(skb
, sizeof(_ah
), ETH_ALEN
, &_sha
);
42 siptr
= skb_header_pointer(skb
, sizeof(_ah
) + ETH_ALEN
,
47 diptr
= skb_header_pointer(skb
,
48 sizeof(_ah
) + 2 * ETH_ALEN
+ sizeof(_sip
),
53 arp_send(ARPOP_REPLY
, ETH_P_ARP
, *siptr
, (struct net_device
*)in
,
54 *diptr
, shp
, info
->mac
, shp
);
59 static int ebt_target_reply_check(const char *tablename
, unsigned int hookmask
,
60 const struct ebt_entry
*e
, void *data
, unsigned int datalen
)
62 struct ebt_arpreply_info
*info
= (struct ebt_arpreply_info
*)data
;
64 if (datalen
!= EBT_ALIGN(sizeof(struct ebt_arpreply_info
)))
66 if (BASE_CHAIN
&& info
->target
== EBT_RETURN
)
68 if (e
->ethproto
!= htons(ETH_P_ARP
) ||
69 e
->invflags
& EBT_IPROTO
)
72 if (strcmp(tablename
, "nat") || hookmask
& ~(1 << NF_BR_PRE_ROUTING
))
77 static struct ebt_target reply_target
=
79 .name
= EBT_ARPREPLY_TARGET
,
80 .target
= ebt_target_reply
,
81 .check
= ebt_target_reply_check
,
85 static int __init
init(void)
87 return ebt_register_target(&reply_target
);
90 static void __exit
fini(void)
92 ebt_unregister_target(&reply_target
);
97 MODULE_LICENSE("GPL");