blob: a5e52a9f0a124e3dd84c164cb5159f120b33071c [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/* module that allows mangling of the arp payload */
2#include <linux/module.h>
Herbert Xu2ca7b0a2007-10-14 00:39:55 -07003#include <linux/netfilter.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -07004#include <linux/netfilter_arp/arpt_mangle.h>
5#include <net/sock.h>
6
7MODULE_LICENSE("GPL");
8MODULE_AUTHOR("Bart De Schuymer <bdschuym@pandora.be>");
9MODULE_DESCRIPTION("arptables arp payload mangle target");
10
11static unsigned int
Jan Engelhardt4b560b42009-07-05 19:43:26 +020012target(struct sk_buff *skb, const struct xt_action_param *par)
Linus Torvalds1da177e2005-04-16 15:20:36 -070013{
Jan Engelhardt7eb35582008-10-08 11:35:19 +020014 const struct arpt_mangle *mangle = par->targinfo;
Jan Engelhardt5452e422008-04-14 11:15:35 +020015 const struct arphdr *arp;
Linus Torvalds1da177e2005-04-16 15:20:36 -070016 unsigned char *arpptr;
17 int pln, hln;
18
Joonwoo Parkeb1197b2008-02-19 17:18:47 -080019 if (!skb_make_writable(skb, skb->len))
Herbert Xu2ca7b0a2007-10-14 00:39:55 -070020 return NF_DROP;
Linus Torvalds1da177e2005-04-16 15:20:36 -070021
Herbert Xu3db05fe2007-10-15 00:53:15 -070022 arp = arp_hdr(skb);
23 arpptr = skb_network_header(skb) + sizeof(*arp);
Linus Torvalds1da177e2005-04-16 15:20:36 -070024 pln = arp->ar_pln;
25 hln = arp->ar_hln;
26 /* We assume that pln and hln were checked in the match */
27 if (mangle->flags & ARPT_MANGLE_SDEV) {
28 if (ARPT_DEV_ADDR_LEN_MAX < hln ||
Herbert Xu3db05fe2007-10-15 00:53:15 -070029 (arpptr + hln > skb_tail_pointer(skb)))
Linus Torvalds1da177e2005-04-16 15:20:36 -070030 return NF_DROP;
31 memcpy(arpptr, mangle->src_devaddr, hln);
32 }
33 arpptr += hln;
34 if (mangle->flags & ARPT_MANGLE_SIP) {
35 if (ARPT_MANGLE_ADDR_LEN_MAX < pln ||
Herbert Xu3db05fe2007-10-15 00:53:15 -070036 (arpptr + pln > skb_tail_pointer(skb)))
Linus Torvalds1da177e2005-04-16 15:20:36 -070037 return NF_DROP;
38 memcpy(arpptr, &mangle->u_s.src_ip, pln);
39 }
40 arpptr += pln;
41 if (mangle->flags & ARPT_MANGLE_TDEV) {
42 if (ARPT_DEV_ADDR_LEN_MAX < hln ||
Herbert Xu3db05fe2007-10-15 00:53:15 -070043 (arpptr + hln > skb_tail_pointer(skb)))
Linus Torvalds1da177e2005-04-16 15:20:36 -070044 return NF_DROP;
45 memcpy(arpptr, mangle->tgt_devaddr, hln);
46 }
47 arpptr += hln;
48 if (mangle->flags & ARPT_MANGLE_TIP) {
49 if (ARPT_MANGLE_ADDR_LEN_MAX < pln ||
Herbert Xu3db05fe2007-10-15 00:53:15 -070050 (arpptr + pln > skb_tail_pointer(skb)))
Linus Torvalds1da177e2005-04-16 15:20:36 -070051 return NF_DROP;
52 memcpy(arpptr, &mangle->u_t.tgt_ip, pln);
53 }
54 return mangle->target;
55}
56
Jan Engelhardt135367b2010-03-19 17:16:42 +010057static int checkentry(const struct xt_tgchk_param *par)
Linus Torvalds1da177e2005-04-16 15:20:36 -070058{
Jan Engelhardtaf5d6dc2008-10-08 11:35:19 +020059 const struct arpt_mangle *mangle = par->targinfo;
Linus Torvalds1da177e2005-04-16 15:20:36 -070060
61 if (mangle->flags & ~ARPT_MANGLE_MASK ||
62 !(mangle->flags & ARPT_MANGLE_MASK))
Pablo Neira Ayuso9d0db8b2011-02-01 16:03:46 +010063 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -070064
65 if (mangle->target != NF_DROP && mangle->target != NF_ACCEPT &&
Jan Engelhardt243bf6e2010-10-13 16:28:00 +020066 mangle->target != XT_CONTINUE)
Pablo Neira Ayuso9d0db8b2011-02-01 16:03:46 +010067 return -EINVAL;
68 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070069}
70
Jan Engelhardt95eea852008-04-14 11:15:43 +020071static struct xt_target arpt_mangle_reg __read_mostly = {
Patrick McHardyaa83c1a2006-03-20 18:01:28 -080072 .name = "mangle",
Jan Engelhardtee999d82008-10-08 11:35:01 +020073 .family = NFPROTO_ARP,
Patrick McHardyaa83c1a2006-03-20 18:01:28 -080074 .target = target,
75 .targetsize = sizeof(struct arpt_mangle),
76 .checkentry = checkentry,
77 .me = THIS_MODULE,
Linus Torvalds1da177e2005-04-16 15:20:36 -070078};
79
Andrew Morton65b4b4e2006-03-28 16:37:06 -080080static int __init arpt_mangle_init(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -070081{
Jan Engelhardt3bb03622008-04-14 11:15:44 +020082 return xt_register_target(&arpt_mangle_reg);
Linus Torvalds1da177e2005-04-16 15:20:36 -070083}
84
Andrew Morton65b4b4e2006-03-28 16:37:06 -080085static void __exit arpt_mangle_fini(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -070086{
Jan Engelhardt3bb03622008-04-14 11:15:44 +020087 xt_unregister_target(&arpt_mangle_reg);
Linus Torvalds1da177e2005-04-16 15:20:36 -070088}
89
Andrew Morton65b4b4e2006-03-28 16:37:06 -080090module_init(arpt_mangle_init);
91module_exit(arpt_mangle_fini);