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