11da177e4SLinus Torvalds /* module that allows mangling of the arp payload */ 21da177e4SLinus Torvalds #include <linux/module.h> 3*2ca7b0acSHerbert Xu #include <linux/netfilter.h> 41da177e4SLinus Torvalds #include <linux/netfilter_arp/arpt_mangle.h> 51da177e4SLinus Torvalds #include <net/sock.h> 61da177e4SLinus Torvalds 71da177e4SLinus Torvalds MODULE_LICENSE("GPL"); 81da177e4SLinus Torvalds MODULE_AUTHOR("Bart De Schuymer <bdschuym@pandora.be>"); 91da177e4SLinus Torvalds MODULE_DESCRIPTION("arptables arp payload mangle target"); 101da177e4SLinus Torvalds 111da177e4SLinus Torvalds static unsigned int 12c4986734SPatrick McHardy target(struct sk_buff **pskb, 13c4986734SPatrick McHardy const struct net_device *in, const struct net_device *out, 14c4986734SPatrick McHardy unsigned int hooknum, const struct xt_target *target, 15fe1cb108SPatrick McHardy const void *targinfo) 161da177e4SLinus Torvalds { 171da177e4SLinus Torvalds const struct arpt_mangle *mangle = targinfo; 181da177e4SLinus Torvalds struct arphdr *arp; 191da177e4SLinus Torvalds unsigned char *arpptr; 201da177e4SLinus Torvalds int pln, hln; 211da177e4SLinus Torvalds 22*2ca7b0acSHerbert Xu if (skb_make_writable(*pskb, (*pskb)->len)) 231da177e4SLinus Torvalds return NF_DROP; 241da177e4SLinus Torvalds 25d0a92be0SArnaldo Carvalho de Melo arp = arp_hdr(*pskb); 26d56f90a7SArnaldo Carvalho de Melo arpptr = skb_network_header(*pskb) + sizeof(*arp); 271da177e4SLinus Torvalds pln = arp->ar_pln; 281da177e4SLinus Torvalds hln = arp->ar_hln; 291da177e4SLinus Torvalds /* We assume that pln and hln were checked in the match */ 301da177e4SLinus Torvalds if (mangle->flags & ARPT_MANGLE_SDEV) { 311da177e4SLinus Torvalds if (ARPT_DEV_ADDR_LEN_MAX < hln || 3227a884dcSArnaldo Carvalho de Melo (arpptr + hln > skb_tail_pointer(*pskb))) 331da177e4SLinus Torvalds return NF_DROP; 341da177e4SLinus Torvalds memcpy(arpptr, mangle->src_devaddr, hln); 351da177e4SLinus Torvalds } 361da177e4SLinus Torvalds arpptr += hln; 371da177e4SLinus Torvalds if (mangle->flags & ARPT_MANGLE_SIP) { 381da177e4SLinus Torvalds if (ARPT_MANGLE_ADDR_LEN_MAX < pln || 3927a884dcSArnaldo Carvalho de Melo (arpptr + pln > skb_tail_pointer(*pskb))) 401da177e4SLinus Torvalds return NF_DROP; 411da177e4SLinus Torvalds memcpy(arpptr, &mangle->u_s.src_ip, pln); 421da177e4SLinus Torvalds } 431da177e4SLinus Torvalds arpptr += pln; 441da177e4SLinus Torvalds if (mangle->flags & ARPT_MANGLE_TDEV) { 451da177e4SLinus Torvalds if (ARPT_DEV_ADDR_LEN_MAX < hln || 4627a884dcSArnaldo Carvalho de Melo (arpptr + hln > skb_tail_pointer(*pskb))) 471da177e4SLinus Torvalds return NF_DROP; 481da177e4SLinus Torvalds memcpy(arpptr, mangle->tgt_devaddr, hln); 491da177e4SLinus Torvalds } 501da177e4SLinus Torvalds arpptr += hln; 511da177e4SLinus Torvalds if (mangle->flags & ARPT_MANGLE_TIP) { 521da177e4SLinus Torvalds if (ARPT_MANGLE_ADDR_LEN_MAX < pln || 5327a884dcSArnaldo Carvalho de Melo (arpptr + pln > skb_tail_pointer(*pskb))) 541da177e4SLinus Torvalds return NF_DROP; 551da177e4SLinus Torvalds memcpy(arpptr, &mangle->u_t.tgt_ip, pln); 561da177e4SLinus Torvalds } 571da177e4SLinus Torvalds return mangle->target; 581da177e4SLinus Torvalds } 591da177e4SLinus Torvalds 60e1931b78SJan Engelhardt static bool 61c4986734SPatrick McHardy checkentry(const char *tablename, const void *e, const struct xt_target *target, 62efa74165SPatrick McHardy void *targinfo, unsigned int hook_mask) 631da177e4SLinus Torvalds { 641da177e4SLinus Torvalds const struct arpt_mangle *mangle = targinfo; 651da177e4SLinus Torvalds 661da177e4SLinus Torvalds if (mangle->flags & ~ARPT_MANGLE_MASK || 671da177e4SLinus Torvalds !(mangle->flags & ARPT_MANGLE_MASK)) 68e1931b78SJan Engelhardt return false; 691da177e4SLinus Torvalds 701da177e4SLinus Torvalds if (mangle->target != NF_DROP && mangle->target != NF_ACCEPT && 711da177e4SLinus Torvalds mangle->target != ARPT_CONTINUE) 72e1931b78SJan Engelhardt return false; 73e1931b78SJan Engelhardt return true; 741da177e4SLinus Torvalds } 751da177e4SLinus Torvalds 769f15c530SPatrick McHardy static struct arpt_target arpt_mangle_reg __read_mostly = { 771da177e4SLinus Torvalds .name = "mangle", 781da177e4SLinus Torvalds .target = target, 79aa83c1abSPatrick McHardy .targetsize = sizeof(struct arpt_mangle), 801da177e4SLinus Torvalds .checkentry = checkentry, 811da177e4SLinus Torvalds .me = THIS_MODULE, 821da177e4SLinus Torvalds }; 831da177e4SLinus Torvalds 8465b4b4e8SAndrew Morton static int __init arpt_mangle_init(void) 851da177e4SLinus Torvalds { 861da177e4SLinus Torvalds if (arpt_register_target(&arpt_mangle_reg)) 871da177e4SLinus Torvalds return -EINVAL; 881da177e4SLinus Torvalds 891da177e4SLinus Torvalds return 0; 901da177e4SLinus Torvalds } 911da177e4SLinus Torvalds 9265b4b4e8SAndrew Morton static void __exit arpt_mangle_fini(void) 931da177e4SLinus Torvalds { 941da177e4SLinus Torvalds arpt_unregister_target(&arpt_mangle_reg); 951da177e4SLinus Torvalds } 961da177e4SLinus Torvalds 9765b4b4e8SAndrew Morton module_init(arpt_mangle_init); 9865b4b4e8SAndrew Morton module_exit(arpt_mangle_fini); 99