1 // SPDX-License-Identifier: GPL-2.0-only 2 /* module that allows mangling of the arp payload */ 3 #include <linux/module.h> 4 #include <linux/netfilter.h> 5 #include <linux/netfilter_arp/arpt_mangle.h> 6 #include <net/sock.h> 7 8 MODULE_LICENSE("GPL"); 9 MODULE_AUTHOR("Bart De Schuymer <bdschuym@pandora.be>"); 10 MODULE_DESCRIPTION("arptables arp payload mangle target"); 11 12 static unsigned int 13 target(struct sk_buff *skb, const struct xt_action_param *par) 14 { 15 const struct arpt_mangle *mangle = par->targinfo; 16 const struct arphdr *arp; 17 unsigned char *arpptr; 18 int pln, hln; 19 20 if (!skb_make_writable(skb, skb->len)) 21 return NF_DROP; 22 23 arp = arp_hdr(skb); 24 arpptr = skb_network_header(skb) + sizeof(*arp); 25 pln = arp->ar_pln; 26 hln = arp->ar_hln; 27 /* We assume that pln and hln were checked in the match */ 28 if (mangle->flags & ARPT_MANGLE_SDEV) { 29 if (ARPT_DEV_ADDR_LEN_MAX < hln || 30 (arpptr + hln > skb_tail_pointer(skb))) 31 return NF_DROP; 32 memcpy(arpptr, mangle->src_devaddr, hln); 33 } 34 arpptr += hln; 35 if (mangle->flags & ARPT_MANGLE_SIP) { 36 if (ARPT_MANGLE_ADDR_LEN_MAX < pln || 37 (arpptr + pln > skb_tail_pointer(skb))) 38 return NF_DROP; 39 memcpy(arpptr, &mangle->u_s.src_ip, pln); 40 } 41 arpptr += pln; 42 if (mangle->flags & ARPT_MANGLE_TDEV) { 43 if (ARPT_DEV_ADDR_LEN_MAX < hln || 44 (arpptr + hln > skb_tail_pointer(skb))) 45 return NF_DROP; 46 memcpy(arpptr, mangle->tgt_devaddr, hln); 47 } 48 arpptr += hln; 49 if (mangle->flags & ARPT_MANGLE_TIP) { 50 if (ARPT_MANGLE_ADDR_LEN_MAX < pln || 51 (arpptr + pln > skb_tail_pointer(skb))) 52 return NF_DROP; 53 memcpy(arpptr, &mangle->u_t.tgt_ip, pln); 54 } 55 return mangle->target; 56 } 57 58 static int checkentry(const struct xt_tgchk_param *par) 59 { 60 const struct arpt_mangle *mangle = par->targinfo; 61 62 if (mangle->flags & ~ARPT_MANGLE_MASK || 63 !(mangle->flags & ARPT_MANGLE_MASK)) 64 return -EINVAL; 65 66 if (mangle->target != NF_DROP && mangle->target != NF_ACCEPT && 67 mangle->target != XT_CONTINUE) 68 return -EINVAL; 69 return 0; 70 } 71 72 static struct xt_target arpt_mangle_reg __read_mostly = { 73 .name = "mangle", 74 .family = NFPROTO_ARP, 75 .target = target, 76 .targetsize = sizeof(struct arpt_mangle), 77 .checkentry = checkentry, 78 .me = THIS_MODULE, 79 }; 80 81 static int __init arpt_mangle_init(void) 82 { 83 return xt_register_target(&arpt_mangle_reg); 84 } 85 86 static void __exit arpt_mangle_fini(void) 87 { 88 xt_unregister_target(&arpt_mangle_reg); 89 } 90 91 module_init(arpt_mangle_init); 92 module_exit(arpt_mangle_fini); 93