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
= (void *)data
;
23 const __be32
*siptr
, *diptr
;
25 const struct arphdr
*ap
;
27 const unsigned char *shp
;
28 unsigned char _sha
[ETH_ALEN
];
30 ap
= skb_header_pointer(skb
, 0, sizeof(_ah
), &_ah
);
34 if (ap
->ar_op
!= htons(ARPOP_REQUEST
) ||
35 ap
->ar_hln
!= ETH_ALEN
||
36 ap
->ar_pro
!= htons(ETH_P_IP
) ||
40 shp
= skb_header_pointer(skb
, sizeof(_ah
), ETH_ALEN
, &_sha
);
44 siptr
= skb_header_pointer(skb
, sizeof(_ah
) + ETH_ALEN
,
49 diptr
= skb_header_pointer(skb
,
50 sizeof(_ah
) + 2 * ETH_ALEN
+ sizeof(_sip
),
55 arp_send(ARPOP_REPLY
, ETH_P_ARP
, *siptr
, (struct net_device
*)in
,
56 *diptr
, shp
, info
->mac
, shp
);
61 static int ebt_target_reply_check(const char *tablename
, unsigned int hookmask
,
62 const struct ebt_entry
*e
, void *data
, unsigned int datalen
)
64 const struct ebt_arpreply_info
*info
= data
;
66 if (datalen
!= EBT_ALIGN(sizeof(struct ebt_arpreply_info
)))
68 if (BASE_CHAIN
&& info
->target
== EBT_RETURN
)
70 if (e
->ethproto
!= htons(ETH_P_ARP
) ||
71 e
->invflags
& EBT_IPROTO
)
74 if (strcmp(tablename
, "nat") || hookmask
& ~(1 << NF_BR_PRE_ROUTING
))
79 static struct ebt_target reply_target __read_mostly
= {
80 .name
= EBT_ARPREPLY_TARGET
,
81 .target
= ebt_target_reply
,
82 .check
= ebt_target_reply_check
,
86 static int __init
ebt_arpreply_init(void)
88 return ebt_register_target(&reply_target
);
91 static void __exit
ebt_arpreply_fini(void)
93 ebt_unregister_target(&reply_target
);
96 module_init(ebt_arpreply_init
);
97 module_exit(ebt_arpreply_fini
);
98 MODULE_DESCRIPTION("Ebtables: ARP reply target");
99 MODULE_LICENSE("GPL");