/* * 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 #include #include #include #include #include "ip6t_NPTV6_common.h" MODULE_AUTHOR("Matthias Schiffer "); 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 int 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 -EINVAL; } return 0; } 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), .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);