1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
|
/*
* NATv6: IPv6-to-IPv6 Network Prefix Translation as
* proposed in RFC 6296.
* Based on MAP66 (c) 2010 sven-ola()gmx.de
* (c) 2011 mschiffer()universe-factory.net "I'm the one to blame for any problems with this version ;P"
*/
#include <linux/module.h>
#include <linux/version.h>
#include <linux/icmpv6.h>
#include <linux/netfilter_ipv6/ip6_tables.h>
#include <net/ipv6.h>
#include "ip6t_NPTV6_common.h"
MODULE_AUTHOR("Matthias Schiffer <mschiffer()universe-factory.net>");
MODULE_DESCRIPTION("Xtables: Source NPTv6 - IPv6-to-IPv6 Network Prefix Translation");
MODULE_LICENSE("GPL");
static unsigned int snptv6_tg6(struct sk_buff *skb, const struct xt_action_param *par)
{
struct ipv6hdr* hdr = ipv6_hdr(skb);
const struct ip6t_nptv6_info *info = par->targinfo;
pr_devel("SNPTV6: enter in=%s, out=%s, saddr=" NIP6_FMT ", daddr=" NIP6_FMT "\n",
NULL != par->in ? par->in->name : "",
NULL != par->out ? par->out->name : "",
NIP6(hdr->saddr), NIP6(hdr->daddr));
if (!skb_make_writable(skb, sizeof(struct ipv6hdr))) {
pr_devel("SNPTV6: unwriteable, dropped\n");
return NF_DROP;
}
hdr = ipv6_hdr(skb);
if (!translate_address(&hdr->saddr, &info->nptv6_prefix, info->nptv6_prefix_len)) {
pr_devel("SNPTV6: untranslatable address\n");
icmpv6_send(skb, ICMPV6_DEST_UNREACH, ICMPV6_NOT_NEIGHBOUR, 0);
return NF_DROP;
}
pr_devel("SNPTV6: exit in=%s, out=%s, saddr=" NIP6_FMT ", daddr=" NIP6_FMT "\n",
NULL != par->in ? par->in->name : "",
NULL != par->out ? par->out->name : "",
NIP6(hdr->saddr), NIP6(hdr->daddr));
return NF_ACCEPT;
}
static CHECKENTRY_RET snptv6_tg6_check(const struct xt_tgchk_param *par)
{
const struct ip6t_nptv6_info *info = par->targinfo;
if (info->nptv6_prefix_len > 64) {
printk("SNPTV6: Prefix length longer than 64 given\n");
return CHECKENTRY_RET_EINVAL;
}
return CHECKENTRY_RET_SUCCESS;
}
static struct xt_target snptv6_tg6_reg __read_mostly = {
.name = "SNPTV6",
.family = NFPROTO_IPV6,
.target = snptv6_tg6,
.checkentry = snptv6_tg6_check,
.targetsize = sizeof(struct ip6t_nptv6_info),
.table = "mangle",
.hooks = (1 << NF_INET_POST_ROUTING) | (1 << NF_INET_LOCAL_IN),
.me = THIS_MODULE,
};
static int __init snptv6_tg6_init(void)
{
return xt_register_target(&snptv6_tg6_reg);
}
static void __exit snptv6_tg6_exit(void)
{
xt_unregister_target(&snptv6_tg6_reg);
}
module_init(snptv6_tg6_init);
module_exit(snptv6_tg6_exit);
|