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 18 static unsigned int 19 ebt_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, 55 (struct net_device *)xt_in(par), 56 *diptr, shp, info->mac, shp); 57 58 return info->target; 59 } 60 61 static int ebt_arpreply_tg_check(const struct xt_tgchk_param *par) 62 { 63 const struct ebt_arpreply_info *info = par->targinfo; 64 const struct ebt_entry *e = par->entryinfo; 65 66 if (BASE_CHAIN && info->target == EBT_RETURN) 67 return -EINVAL; 68 if (e->ethproto != htons(ETH_P_ARP) || 69 e->invflags & EBT_IPROTO) 70 return -EINVAL; 71 if (ebt_invalid_target(info->target)) 72 return -EINVAL; 73 74 return 0; 75 } 76 77 static struct xt_target ebt_arpreply_tg_reg __read_mostly = { 78 .name = "arpreply", 79 .revision = 0, 80 .family = NFPROTO_BRIDGE, 81 .table = "nat", 82 .hooks = (1 << NF_BR_NUMHOOKS) | (1 << NF_BR_PRE_ROUTING), 83 .target = ebt_arpreply_tg, 84 .checkentry = ebt_arpreply_tg_check, 85 .targetsize = sizeof(struct ebt_arpreply_info), 86 .me = THIS_MODULE, 87 }; 88 89 static int __init ebt_arpreply_init(void) 90 { 91 return xt_register_target(&ebt_arpreply_tg_reg); 92 } 93 94 static void __exit ebt_arpreply_fini(void) 95 { 96 xt_unregister_target(&ebt_arpreply_tg_reg); 97 } 98 99 module_init(ebt_arpreply_init); 100 module_exit(ebt_arpreply_fini); 101 MODULE_DESCRIPTION("Ebtables: ARP reply target"); 102 MODULE_LICENSE("GPL"); 103