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
*skb
, 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 __be32 _sip
, *siptr
, _dip
, *diptr
;
24 struct arphdr _ah
, *ap
;
25 unsigned char _sha
[ETH_ALEN
], *shp
;
27 ap
= skb_header_pointer(skb
, 0, sizeof(_ah
), &_ah
);
31 if (ap
->ar_op
!= htons(ARPOP_REQUEST
) ||
32 ap
->ar_hln
!= ETH_ALEN
||
33 ap
->ar_pro
!= htons(ETH_P_IP
) ||
37 shp
= skb_header_pointer(skb
, sizeof(_ah
), ETH_ALEN
, &_sha
);
41 siptr
= skb_header_pointer(skb
, sizeof(_ah
) + ETH_ALEN
,
46 diptr
= skb_header_pointer(skb
,
47 sizeof(_ah
) + 2 * ETH_ALEN
+ sizeof(_sip
),
52 arp_send(ARPOP_REPLY
, ETH_P_ARP
, *siptr
, (struct net_device
*)in
,
53 *diptr
, shp
, info
->mac
, shp
);
58 static int ebt_target_reply_check(const char *tablename
, unsigned int hookmask
,
59 const struct ebt_entry
*e
, void *data
, unsigned int datalen
)
61 struct ebt_arpreply_info
*info
= (struct ebt_arpreply_info
*)data
;
63 if (datalen
!= EBT_ALIGN(sizeof(struct ebt_arpreply_info
)))
65 if (BASE_CHAIN
&& info
->target
== EBT_RETURN
)
67 if (e
->ethproto
!= htons(ETH_P_ARP
) ||
68 e
->invflags
& EBT_IPROTO
)
71 if (strcmp(tablename
, "nat") || hookmask
& ~(1 << NF_BR_PRE_ROUTING
))
76 static struct ebt_target reply_target
=
78 .name
= EBT_ARPREPLY_TARGET
,
79 .target
= ebt_target_reply
,
80 .check
= ebt_target_reply_check
,
84 static int __init
ebt_arpreply_init(void)
86 return ebt_register_target(&reply_target
);
89 static void __exit
ebt_arpreply_fini(void)
91 ebt_unregister_target(&reply_target
);
94 module_init(ebt_arpreply_init
);
95 module_exit(ebt_arpreply_fini
);
96 MODULE_LICENSE("GPL");