Commit | Line | Data |
---|---|---|
09c434b8 | 1 | // SPDX-License-Identifier: GPL-2.0-only |
1da177e4 LT |
2 | /* module that allows mangling of the arp payload */ |
3 | #include <linux/module.h> | |
2ca7b0ac | 4 | #include <linux/netfilter.h> |
1da177e4 LT |
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 | |
4b560b44 | 13 | target(struct sk_buff *skb, const struct xt_action_param *par) |
1da177e4 | 14 | { |
7eb35586 | 15 | const struct arpt_mangle *mangle = par->targinfo; |
5452e425 | 16 | const struct arphdr *arp; |
1da177e4 LT |
17 | unsigned char *arpptr; |
18 | int pln, hln; | |
19 | ||
eb1197bc | 20 | if (!skb_make_writable(skb, skb->len)) |
2ca7b0ac | 21 | return NF_DROP; |
1da177e4 | 22 | |
3db05fea HX |
23 | arp = arp_hdr(skb); |
24 | arpptr = skb_network_header(skb) + sizeof(*arp); | |
1da177e4 LT |
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 || | |
3db05fea | 30 | (arpptr + hln > skb_tail_pointer(skb))) |
1da177e4 LT |
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 || | |
3db05fea | 37 | (arpptr + pln > skb_tail_pointer(skb))) |
1da177e4 LT |
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 || | |
3db05fea | 44 | (arpptr + hln > skb_tail_pointer(skb))) |
1da177e4 LT |
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 || | |
3db05fea | 51 | (arpptr + pln > skb_tail_pointer(skb))) |
1da177e4 LT |
52 | return NF_DROP; |
53 | memcpy(arpptr, &mangle->u_t.tgt_ip, pln); | |
54 | } | |
55 | return mangle->target; | |
56 | } | |
57 | ||
135367b8 | 58 | static int checkentry(const struct xt_tgchk_param *par) |
1da177e4 | 59 | { |
af5d6dc2 | 60 | const struct arpt_mangle *mangle = par->targinfo; |
1da177e4 LT |
61 | |
62 | if (mangle->flags & ~ARPT_MANGLE_MASK || | |
63 | !(mangle->flags & ARPT_MANGLE_MASK)) | |
9d0db8b6 | 64 | return -EINVAL; |
1da177e4 LT |
65 | |
66 | if (mangle->target != NF_DROP && mangle->target != NF_ACCEPT && | |
243bf6e2 | 67 | mangle->target != XT_CONTINUE) |
9d0db8b6 PNA |
68 | return -EINVAL; |
69 | return 0; | |
1da177e4 LT |
70 | } |
71 | ||
95eea855 | 72 | static struct xt_target arpt_mangle_reg __read_mostly = { |
aa83c1ab | 73 | .name = "mangle", |
ee999d8b | 74 | .family = NFPROTO_ARP, |
aa83c1ab PM |
75 | .target = target, |
76 | .targetsize = sizeof(struct arpt_mangle), | |
77 | .checkentry = checkentry, | |
78 | .me = THIS_MODULE, | |
1da177e4 LT |
79 | }; |
80 | ||
65b4b4e8 | 81 | static int __init arpt_mangle_init(void) |
1da177e4 | 82 | { |
3bb0362d | 83 | return xt_register_target(&arpt_mangle_reg); |
1da177e4 LT |
84 | } |
85 | ||
65b4b4e8 | 86 | static void __exit arpt_mangle_fini(void) |
1da177e4 | 87 | { |
3bb0362d | 88 | xt_unregister_target(&arpt_mangle_reg); |
1da177e4 LT |
89 | } |
90 | ||
65b4b4e8 AM |
91 | module_init(arpt_mangle_init); |
92 | module_exit(arpt_mangle_fini); |