11da177e4SLinus Torvalds /* 21da177e4SLinus Torvalds * ebt_arpreply 31da177e4SLinus Torvalds * 41da177e4SLinus Torvalds * Authors: 51da177e4SLinus Torvalds * Grzegorz Borowiak <grzes@gnu.univ.gda.pl> 61da177e4SLinus Torvalds * Bart De Schuymer <bdschuym@pandora.be> 71da177e4SLinus Torvalds * 81da177e4SLinus Torvalds * August, 2003 91da177e4SLinus Torvalds * 101da177e4SLinus Torvalds */ 111da177e4SLinus Torvalds #include <linux/if_arp.h> 121da177e4SLinus Torvalds #include <net/arp.h> 131da177e4SLinus Torvalds #include <linux/module.h> 1418219d3fSJan Engelhardt #include <linux/netfilter/x_tables.h> 1518219d3fSJan Engelhardt #include <linux/netfilter_bridge/ebtables.h> 1618219d3fSJan Engelhardt #include <linux/netfilter_bridge/ebt_arpreply.h> 171da177e4SLinus Torvalds 182d06d4a5SJan Engelhardt static unsigned int 194b560b44SJan Engelhardt ebt_arpreply_tg(struct sk_buff *skb, const struct xt_action_param *par) 201da177e4SLinus Torvalds { 217eb35586SJan Engelhardt const struct ebt_arpreply_info *info = par->targinfo; 22abfdf1c4SJan Engelhardt const __be32 *siptr, *diptr; 23abfdf1c4SJan Engelhardt __be32 _sip, _dip; 24abfdf1c4SJan Engelhardt const struct arphdr *ap; 25abfdf1c4SJan Engelhardt struct arphdr _ah; 26abfdf1c4SJan Engelhardt const unsigned char *shp; 27abfdf1c4SJan Engelhardt unsigned char _sha[ETH_ALEN]; 281da177e4SLinus Torvalds 291da177e4SLinus Torvalds ap = skb_header_pointer(skb, 0, sizeof(_ah), &_ah); 301da177e4SLinus Torvalds if (ap == NULL) 311da177e4SLinus Torvalds return EBT_DROP; 321da177e4SLinus Torvalds 331da177e4SLinus Torvalds if (ap->ar_op != htons(ARPOP_REQUEST) || 341da177e4SLinus Torvalds ap->ar_hln != ETH_ALEN || 351da177e4SLinus Torvalds ap->ar_pro != htons(ETH_P_IP) || 361da177e4SLinus Torvalds ap->ar_pln != 4) 371da177e4SLinus Torvalds return EBT_CONTINUE; 381da177e4SLinus Torvalds 391da177e4SLinus Torvalds shp = skb_header_pointer(skb, sizeof(_ah), ETH_ALEN, &_sha); 401da177e4SLinus Torvalds if (shp == NULL) 411da177e4SLinus Torvalds return EBT_DROP; 421da177e4SLinus Torvalds 431da177e4SLinus Torvalds siptr = skb_header_pointer(skb, sizeof(_ah) + ETH_ALEN, 441da177e4SLinus Torvalds sizeof(_sip), &_sip); 451da177e4SLinus Torvalds if (siptr == NULL) 461da177e4SLinus Torvalds return EBT_DROP; 471da177e4SLinus Torvalds 481da177e4SLinus Torvalds diptr = skb_header_pointer(skb, 491da177e4SLinus Torvalds sizeof(_ah) + 2 * ETH_ALEN + sizeof(_sip), 501da177e4SLinus Torvalds sizeof(_dip), &_dip); 511da177e4SLinus Torvalds if (diptr == NULL) 521da177e4SLinus Torvalds return EBT_DROP; 531da177e4SLinus Torvalds 54613dbd95SPablo Neira Ayuso arp_send(ARPOP_REPLY, ETH_P_ARP, *siptr, 55613dbd95SPablo Neira Ayuso (struct net_device *)xt_in(par), 561da177e4SLinus Torvalds *diptr, shp, info->mac, shp); 571da177e4SLinus Torvalds 581da177e4SLinus Torvalds return info->target; 591da177e4SLinus Torvalds } 601da177e4SLinus Torvalds 61135367b8SJan Engelhardt static int ebt_arpreply_tg_check(const struct xt_tgchk_param *par) 621da177e4SLinus Torvalds { 63af5d6dc2SJan Engelhardt const struct ebt_arpreply_info *info = par->targinfo; 64af5d6dc2SJan Engelhardt const struct ebt_entry *e = par->entryinfo; 651da177e4SLinus Torvalds 661da177e4SLinus Torvalds if (BASE_CHAIN && info->target == EBT_RETURN) 67d6b00a53SJan Engelhardt return -EINVAL; 681da177e4SLinus Torvalds if (e->ethproto != htons(ETH_P_ARP) || 691da177e4SLinus Torvalds e->invflags & EBT_IPROTO) 70d6b00a53SJan Engelhardt return -EINVAL; 71c953d635SGao Feng if (ebt_invalid_target(info->target)) 72c953d635SGao Feng return -EINVAL; 73c953d635SGao Feng 74d6b00a53SJan Engelhardt return 0; 751da177e4SLinus Torvalds } 761da177e4SLinus Torvalds 77043ef46cSJan Engelhardt static struct xt_target ebt_arpreply_tg_reg __read_mostly = { 78043ef46cSJan Engelhardt .name = "arpreply", 79001a18d3SJan Engelhardt .revision = 0, 80001a18d3SJan Engelhardt .family = NFPROTO_BRIDGE, 81f2ff525cSJan Engelhardt .table = "nat", 82f2ff525cSJan Engelhardt .hooks = (1 << NF_BR_NUMHOOKS) | (1 << NF_BR_PRE_ROUTING), 832d06d4a5SJan Engelhardt .target = ebt_arpreply_tg, 842d06d4a5SJan Engelhardt .checkentry = ebt_arpreply_tg_check, 85fc0e3df4SFlorian Westphal .targetsize = sizeof(struct ebt_arpreply_info), 861da177e4SLinus Torvalds .me = THIS_MODULE, 871da177e4SLinus Torvalds }; 881da177e4SLinus Torvalds 8965b4b4e8SAndrew Morton static int __init ebt_arpreply_init(void) 901da177e4SLinus Torvalds { 91043ef46cSJan Engelhardt return xt_register_target(&ebt_arpreply_tg_reg); 921da177e4SLinus Torvalds } 931da177e4SLinus Torvalds 9465b4b4e8SAndrew Morton static void __exit ebt_arpreply_fini(void) 951da177e4SLinus Torvalds { 96043ef46cSJan Engelhardt xt_unregister_target(&ebt_arpreply_tg_reg); 971da177e4SLinus Torvalds } 981da177e4SLinus Torvalds 9965b4b4e8SAndrew Morton module_init(ebt_arpreply_init); 10065b4b4e8SAndrew Morton module_exit(ebt_arpreply_fini); 101f776c4cdSJan Engelhardt MODULE_DESCRIPTION("Ebtables: ARP reply target"); 1021da177e4SLinus Torvalds MODULE_LICENSE("GPL"); 103