11da177e4SLinus Torvalds /* module that allows mangling of the arp payload */ 21da177e4SLinus Torvalds #include <linux/module.h> 32ca7b0acSHerbert 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 127eb35586SJan Engelhardt target(struct sk_buff *skb, const struct xt_target_param *par) 131da177e4SLinus Torvalds { 147eb35586SJan Engelhardt const struct arpt_mangle *mangle = par->targinfo; 155452e425SJan Engelhardt const struct arphdr *arp; 161da177e4SLinus Torvalds unsigned char *arpptr; 171da177e4SLinus Torvalds int pln, hln; 181da177e4SLinus Torvalds 19eb1197bcSJoonwoo Park if (!skb_make_writable(skb, skb->len)) 201da177e4SLinus Torvalds return NF_DROP; 211da177e4SLinus Torvalds 223db05feaSHerbert Xu arp = arp_hdr(skb); 233db05feaSHerbert Xu arpptr = skb_network_header(skb) + sizeof(*arp); 241da177e4SLinus Torvalds pln = arp->ar_pln; 251da177e4SLinus Torvalds hln = arp->ar_hln; 261da177e4SLinus Torvalds /* We assume that pln and hln were checked in the match */ 271da177e4SLinus Torvalds if (mangle->flags & ARPT_MANGLE_SDEV) { 281da177e4SLinus Torvalds if (ARPT_DEV_ADDR_LEN_MAX < hln || 293db05feaSHerbert Xu (arpptr + hln > skb_tail_pointer(skb))) 301da177e4SLinus Torvalds return NF_DROP; 311da177e4SLinus Torvalds memcpy(arpptr, mangle->src_devaddr, hln); 321da177e4SLinus Torvalds } 331da177e4SLinus Torvalds arpptr += hln; 341da177e4SLinus Torvalds if (mangle->flags & ARPT_MANGLE_SIP) { 351da177e4SLinus Torvalds if (ARPT_MANGLE_ADDR_LEN_MAX < pln || 363db05feaSHerbert Xu (arpptr + pln > skb_tail_pointer(skb))) 371da177e4SLinus Torvalds return NF_DROP; 381da177e4SLinus Torvalds memcpy(arpptr, &mangle->u_s.src_ip, pln); 391da177e4SLinus Torvalds } 401da177e4SLinus Torvalds arpptr += pln; 411da177e4SLinus Torvalds if (mangle->flags & ARPT_MANGLE_TDEV) { 421da177e4SLinus Torvalds if (ARPT_DEV_ADDR_LEN_MAX < hln || 433db05feaSHerbert Xu (arpptr + hln > skb_tail_pointer(skb))) 441da177e4SLinus Torvalds return NF_DROP; 451da177e4SLinus Torvalds memcpy(arpptr, mangle->tgt_devaddr, hln); 461da177e4SLinus Torvalds } 471da177e4SLinus Torvalds arpptr += hln; 481da177e4SLinus Torvalds if (mangle->flags & ARPT_MANGLE_TIP) { 491da177e4SLinus Torvalds if (ARPT_MANGLE_ADDR_LEN_MAX < pln || 503db05feaSHerbert Xu (arpptr + pln > skb_tail_pointer(skb))) 511da177e4SLinus Torvalds return NF_DROP; 521da177e4SLinus Torvalds memcpy(arpptr, &mangle->u_t.tgt_ip, pln); 531da177e4SLinus Torvalds } 541da177e4SLinus Torvalds return mangle->target; 551da177e4SLinus Torvalds } 561da177e4SLinus Torvalds 57*af5d6dc2SJan Engelhardt static bool checkentry(const struct xt_tgchk_param *par) 581da177e4SLinus Torvalds { 59*af5d6dc2SJan Engelhardt const struct arpt_mangle *mangle = par->targinfo; 601da177e4SLinus Torvalds 611da177e4SLinus Torvalds if (mangle->flags & ~ARPT_MANGLE_MASK || 621da177e4SLinus Torvalds !(mangle->flags & ARPT_MANGLE_MASK)) 63e1931b78SJan Engelhardt return false; 641da177e4SLinus Torvalds 651da177e4SLinus Torvalds if (mangle->target != NF_DROP && mangle->target != NF_ACCEPT && 661da177e4SLinus Torvalds mangle->target != ARPT_CONTINUE) 67e1931b78SJan Engelhardt return false; 68e1931b78SJan Engelhardt return true; 691da177e4SLinus Torvalds } 701da177e4SLinus Torvalds 7195eea855SJan Engelhardt static struct xt_target arpt_mangle_reg __read_mostly = { 721da177e4SLinus Torvalds .name = "mangle", 73ee999d8bSJan Engelhardt .family = NFPROTO_ARP, 741da177e4SLinus Torvalds .target = target, 75aa83c1abSPatrick McHardy .targetsize = sizeof(struct arpt_mangle), 761da177e4SLinus Torvalds .checkentry = checkentry, 771da177e4SLinus Torvalds .me = THIS_MODULE, 781da177e4SLinus Torvalds }; 791da177e4SLinus Torvalds 8065b4b4e8SAndrew Morton static int __init arpt_mangle_init(void) 811da177e4SLinus Torvalds { 823bb0362dSJan Engelhardt return xt_register_target(&arpt_mangle_reg); 831da177e4SLinus Torvalds } 841da177e4SLinus Torvalds 8565b4b4e8SAndrew Morton static void __exit arpt_mangle_fini(void) 861da177e4SLinus Torvalds { 873bb0362dSJan Engelhardt xt_unregister_target(&arpt_mangle_reg); 881da177e4SLinus Torvalds } 891da177e4SLinus Torvalds 9065b4b4e8SAndrew Morton module_init(arpt_mangle_init); 9165b4b4e8SAndrew Morton module_exit(arpt_mangle_fini); 92