1/* 2 * ebt_arpreply 3 * 4 * Authors: 5 * Grzegorz Borowiak <grzes@gnu.univ.gda.pl> 6 * Bart De Schuymer <bdschuym@pandora.be> 7 * 8 * August, 2003 9 * 10 */ 11#include <linux/if_arp.h> 12#include <net/arp.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_arpreply.h> 17 18static unsigned int 19ebt_arpreply_tg(struct sk_buff *skb, const struct xt_action_param *par) 20{ 21 const struct ebt_arpreply_info *info = par->targinfo; 22 const __be32 *siptr, *diptr; 23 __be32 _sip, _dip; 24 const struct arphdr *ap; 25 struct arphdr _ah; 26 const unsigned char *shp; 27 unsigned char _sha[ETH_ALEN]; 28 29 ap = skb_header_pointer(skb, 0, sizeof(_ah), &_ah); 30 if (ap == NULL) 31 return EBT_DROP; 32 33 if (ap->ar_op != htons(ARPOP_REQUEST) || 34 ap->ar_hln != ETH_ALEN || 35 ap->ar_pro != htons(ETH_P_IP) || 36 ap->ar_pln != 4) 37 return EBT_CONTINUE; 38 39 shp = skb_header_pointer(skb, sizeof(_ah), ETH_ALEN, &_sha); 40 if (shp == NULL) 41 return EBT_DROP; 42 43 siptr = skb_header_pointer(skb, sizeof(_ah) + ETH_ALEN, 44 sizeof(_sip), &_sip); 45 if (siptr == NULL) 46 return EBT_DROP; 47 48 diptr = skb_header_pointer(skb, 49 sizeof(_ah) + 2 * ETH_ALEN + sizeof(_sip), 50 sizeof(_dip), &_dip); 51 if (diptr == NULL) 52 return EBT_DROP; 53 54 arp_send(ARPOP_REPLY, ETH_P_ARP, *siptr, (struct net_device *)par->in, 55 *diptr, shp, info->mac, shp); 56 57 return info->target; 58} 59 60static int ebt_arpreply_tg_check(const struct xt_tgchk_param *par) 61{ 62 const struct ebt_arpreply_info *info = par->targinfo; 63 const struct ebt_entry *e = par->entryinfo; 64 65 if (BASE_CHAIN && info->target == EBT_RETURN) 66 return -EINVAL; 67 if (e->ethproto != htons(ETH_P_ARP) || 68 e->invflags & EBT_IPROTO) 69 return -EINVAL; 70 return 0; 71} 72 73static struct xt_target ebt_arpreply_tg_reg __read_mostly = { 74 .name = "arpreply", 75 .revision = 0, 76 .family = NFPROTO_BRIDGE, 77 .table = "nat", 78 .hooks = (1 << NF_BR_NUMHOOKS) | (1 << NF_BR_PRE_ROUTING), 79 .target = ebt_arpreply_tg, 80 .checkentry = ebt_arpreply_tg_check, 81 .targetsize = sizeof(struct ebt_arpreply_info), 82 .me = THIS_MODULE, 83}; 84 85static int __init ebt_arpreply_init(void) 86{ 87 return xt_register_target(&ebt_arpreply_tg_reg); 88} 89 90static void __exit ebt_arpreply_fini(void) 91{ 92 xt_unregister_target(&ebt_arpreply_tg_reg); 93} 94 95module_init(ebt_arpreply_init); 96module_exit(ebt_arpreply_fini); 97MODULE_DESCRIPTION("Ebtables: ARP reply target"); 98MODULE_LICENSE("GPL"); 99