[xt_RAWNAT 3/3] xt_RAWNAT code

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



origin git://computergmbh.de/linux patchomatic

commit df4f8a4974253e72ccf806c532c7d04daa514474
Author: Jan Engelhardt <jengelh@xxxxxxxxxxxxxxx>
Date:   Sun Jan 13 17:03:25 2008 +0100

    [NETFILTER]: xt_RAWNAT target
    
    xt_RAWNAT can be used to do static network address translation
    without depending on connection tracking. Together with the previous
    patch to add a POSTROUTING chain to the "raw" table, it is possible
    to use xt_RAWNAT even when conntrack is enabled.
    
    Signed-off-by: Jan Engelhardt <jengelh@xxxxxxxxxxxxxxx>

diff --git a/include/linux/netfilter/xt_RAWNAT.h b/include/linux/netfilter/xt_RAWNAT.h
new file mode 100644
index 0000000..f948166
--- /dev/null
+++ b/include/linux/netfilter/xt_RAWNAT.h
@@ -0,0 +1,9 @@
+#ifndef _LINUX_NETFILTER_XT_TARGET_RAWNAT
+#define _LINUX_NETFILTER_XT_TARGET_RAWNAT 1
+
+struct xt_rawnat_tginfo {
+	union nf_inet_addr addr;
+	uint8_t mask;
+};
+
+#endif /* _LINUX_NETFILTER_XT_TARGET_RAWNAT */
diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig
index eec3d24..7611e1b 100644
--- a/net/netfilter/Kconfig
+++ b/net/netfilter/Kconfig
@@ -385,6 +385,15 @@ config NETFILTER_XT_TARGET_RATEEST
 
 	  To compile it as a module, choose M here.  If unsure, say N.
 
+config NETFILTER_XT_TARGET_RAWNAT
+	tristate '"RAWNAT" raw address translation w/o conntrack'
+	depends on NETFILTER_XTABLES
+	depends on IP_NF_RAW || IP_NF6_RAW
+	---help---
+	This option adds the RAWSNAT and RAWDNAT targets which can do Network
+	Address Translation (no port translation) without requiring Netfilter
+	connection tracking.
+
 config NETFILTER_XT_TARGET_REJECT
 	tristate '"REJECT" target support'
 	depends on NETFILTER_XTABLES
diff --git a/net/netfilter/Makefile b/net/netfilter/Makefile
index b170ef1..e5132fd 100644
--- a/net/netfilter/Makefile
+++ b/net/netfilter/Makefile
@@ -47,6 +47,7 @@ obj-$(CONFIG_NETFILTER_XT_TARGET_NFLOG) += xt_NFLOG.o
 obj-$(CONFIG_NETFILTER_XT_TARGET_NFQUEUE) += xt_NFQUEUE.o
 obj-$(CONFIG_NETFILTER_XT_TARGET_NOTRACK) += xt_NOTRACK.o
 obj-$(CONFIG_NETFILTER_XT_TARGET_RATEEST) += xt_RATEEST.o
+obj-$(CONFIG_NETFILTER_XT_TARGET_RAWNAT) += xt_RAWNAT.o
 obj-$(CONFIG_NETFILTER_XT_TARGET_REJECT) += xt_REJECT.o
 obj-$(CONFIG_NETFILTER_XT_TARGET_SECMARK) += xt_SECMARK.o
 obj-$(CONFIG_NETFILTER_XT_TARGET_STEAL) += xt_STEAL.o
diff --git a/net/netfilter/xt_RAWNAT.c b/net/netfilter/xt_RAWNAT.c
new file mode 100644
index 0000000..a5a68da
--- /dev/null
+++ b/net/netfilter/xt_RAWNAT.c
@@ -0,0 +1,195 @@
+/*
+ *	xt_RAWNAT - Netfilter module to do untracked NAT
+ *
+ *	Copyright © CC Computer Consultants GmbH, 2008
+ *	Jan Engelhardt <jengelh@xxxxxxxxxxxxxxx>
+ */
+#include <linux/ip.h>
+#include <linux/ipv6.h>
+#include <linux/module.h>
+#include <linux/skbuff.h>
+#include <linux/netfilter.h>
+#include <linux/netfilter/nf_conntrack_common.h>
+#include <linux/netfilter/x_tables.h>
+#include <linux/netfilter/xt_RAWNAT.h>
+#include <net/netfilter/nf_conntrack.h>
+
+static inline u_int32_t
+remask(u_int32_t addr, u_int32_t repl, unsigned int shift)
+{
+	u_int32_t mask = (left == 32) ? 0 : (~(u_int32_t)0 >> shift);
+	return htonl((ntohl(addr) & ~mask) | ntohl(repl));
+}
+
+static void
+rawnat_ipv6_mask(__be32 *addr, const __be32 *repl, unsigned int mask)
+{
+	switch (mask) {
+		case 0:
+			break;
+		case 1 ... 31:
+			addr[0] = remask(addr[0], repl[0], mask);
+			break;
+		case 32:
+			addr[0] = repl[0];
+			break;
+		case 33 ... 63:
+			addr[0] = repl[0];
+			addr[1] = remask(addr[1], repl[1], mask - 64);
+			break;
+		case 64:
+			addr[0] = repl[0];
+			addr[1] = repl[1];
+			break;
+		case 65 ... 95:
+			addr[0] = repl[0];
+			addr[1] = repl[1];
+			addr[2] = remask(addr[2], repl[2], mask - 96);
+		case 96:
+			addr[0] = repl[0];
+			addr[1] = repl[1];
+			addr[2] = repl[2];
+			break;
+		case 97 ... 127:
+			addr[0] = repl[0];
+			addr[1] = repl[1];
+			addr[2] = repl[2];
+			addr[3] = remask(addr[3], repl[3], mask - 128);
+			break;
+		case 128:
+			addr[0] = repl[0];
+			addr[1] = repl[1];
+			addr[2] = repl[2];
+			addr[3] = repl[3];
+			break;
+	}
+}
+
+static unsigned int
+rawsnat_tg4(struct sk_buff *skb, const struct net_device *in,
+            const struct net_device *out, unsigned int hooknum,
+            const struct xt_target *target, const void *targinfo)
+{
+	const struct xt_rawnat_tginfo *info = targinfo;
+	struct iphdr *iph;
+	u_int32_t na;
+
+	if (!skb_make_writable(skb, sizeof(struct iphdr)))
+		return NF_DROP;
+
+	iph = ip_hdr(skb);
+	na  = remask(iph->saddr, info->addr.ip, info->mask);
+	csum_replace4(&iph->check, iph->saddr, na);
+	iph->saddr = na;
+	return XT_CONTINUE;
+}
+
+static unsigned int
+rawdnat_tg4(struct sk_buff *skb, const struct net_device *in,
+            const struct net_device *out, unsigned int hooknum,
+            const struct xt_target *target, const void *targinfo)
+{
+	const struct xt_rawnat_tginfo *info = targinfo;
+	struct iphdr *iph;
+	u_int32_t na;
+
+	if (!skb_make_writable(skb, sizeof(struct iphdr)))
+		return NF_DROP;
+
+	iph = ip_hdr(skb);
+	na  = remask(iph->daddr, info->addr.ip, info->mask);
+	csum_replace4(&iph->check, iph->daddr, na);
+	iph->daddr = na;
+	return XT_CONTINUE;
+}
+
+static unsigned int
+rawsnat_tg6(struct sk_buff *skb, const struct net_device *in,
+            const struct net_device *out, unsigned int hooknum,
+            const struct xt_target *target, const void *targinfo)
+{
+	const struct xt_rawnat_tginfo *info = targinfo;
+	struct ipv6hdr *iph;
+
+	if (!skb_make_writable(skb, sizeof(struct ipv6hdr)))
+		return NF_DROP;
+
+	iph = ipv6_hdr(skb);
+	rawnat_ipv6_mask(iph->saddr.s6_addr32, info->addr.ip6, info->mask);
+	return XT_CONTINUE;
+}
+
+static unsigned int
+rawdnat_tg6(struct sk_buff *skb, const struct net_device *in,
+            const struct net_device *out, unsigned int hooknum,
+            const struct xt_target *target, const void *targinfo)
+{
+	const struct xt_rawnat_tginfo *info = targinfo;
+	struct ipv6hdr *iph;
+
+	if (!skb_make_writable(skb, sizeof(struct ipv6hdr)))
+		return NF_DROP;
+
+	iph = ipv6_hdr(skb);
+	rawnat_ipv6_mask(iph->daddr.s6_addr32, info->addr.ip6, info->mask);
+	return XT_CONTINUE;
+}
+
+static struct xt_target rawnat_tg_reg[] __read_mostly = {
+	{
+		.name       = "RAWSNAT",
+		.revision   = 0,
+		.family     = AF_INET,
+		.table      = "raw",
+		.target     = rawsnat_tg4,
+		.targetsize = sizeof(struct xt_rawnat_tginfo),
+		.me         = THIS_MODULE,
+	},
+	{
+		.name       = "RAWSNAT",
+		.revision   = 0,
+		.family     = AF_INET6,
+		.table      = "raw",
+		.target     = rawsnat_tg6,
+		.targetsize = sizeof(struct xt_rawnat_tginfo),
+		.me         = THIS_MODULE,
+	},
+	{
+		.name       = "RAWDNAT",
+		.revision   = 0,
+		.family     = AF_INET,
+		.table      = "raw",
+		.target     = rawdnat_tg4,
+		.targetsize = sizeof(struct xt_rawnat_tginfo),
+		.me         = THIS_MODULE,
+	},
+	{
+		.name       = "RAWDNAT",
+		.revision   = 0,
+		.family     = AF_INET6,
+		.table      = "raw",
+		.target     = rawdnat_tg6,
+		.targetsize = sizeof(struct xt_rawnat_tginfo),
+		.me         = THIS_MODULE,
+	},
+};
+
+static int __init rawnat_tg_init(void)
+{
+	return xt_register_targets(rawnat_tg_reg, ARRAY_SIZE(rawnat_tg_reg));
+}
+
+static void __exit rawnat_tg_exit(void)
+{
+	xt_unregister_targets(rawnat_tg_reg, ARRAY_SIZE(rawnat_tg_reg));
+}
+
+module_init(rawnat_tg_init);
+module_exit(rawnat_tg_exit);
+MODULE_AUTHOR("Jan Engelhardt <jengelh@xxxxxxxxxxxxxxx>");
+MODULE_DESCRIPTION("Netfilter: conntrack-less raw NAT");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("ipt_RAWSNAT");
+MODULE_ALIAS("ipt_RAWDNAT");
+MODULE_ALIAS("ip6t_RAWSNAT");
+MODULE_ALIAS("ip6t_RAWDNAT");
-
To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Netfitler Users]     [LARTC]     [Bugtraq]     [Yosemite Forum]

  Powered by Linux