All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/9] tproxy: add IPv6 support
@ 2010-10-20 11:21 KOVACS Krisztian
  2010-10-20 11:21 ` [PATCH 1/9] tproxy: split off ipv6 defragmentation to a separate module KOVACS Krisztian
                   ` (8 more replies)
  0 siblings, 9 replies; 27+ messages in thread
From: KOVACS Krisztian @ 2010-10-20 11:21 UTC (permalink / raw)
  To: netdev, netfilter-devel; +Cc: Patrick McHardy, David Miller

The following series adds IPv6 support for tproxy. The parts touching
non-Netfilter code include exporting the UDP lookup function, adding the
sockopt infrastructure for getting the original destination address and
allowing non-local binds if the IP_TRANSPARENT socket option is set.

Netfilter changes are splitting the defragmentation code off of conntrack,
adding IPv6 socket lookup helpers to the tproxy core module and updating the
socket match and the TPROXY target.

The last patch in the series tries to make it easier to use the TPROXY target
by selecting a meaningful address to redirect to in case the user did not
explicitly specify it with '--on-ip'.

---

Balazs Scheidler (9):
      tproxy: split off ipv6 defragmentation to a separate module
      tproxy: added const specifiers to udp lookup functions
      tproxy: added udp6_lib_lookup function
      tproxy: added tproxy sockopt interface in the IPV6 layer
      tproxy: allow non-local binds of IPv6 sockets if IP_TRANSPARENT is enabled
      tproxy: added IPv6 socket lookup function to nf_tproxy_core
      tproxy: added IPv6 support to the TPROXY target
      tproxy: added IPv6 support to the socket match
      tproxy: use the interface primary IP address as a default value for --on-ip


 include/linux/in6.h                            |    4 
 include/linux/ipv6.h                           |    4 
 include/linux/netfilter/xt_TPROXY.h            |   15 +
 include/net/netfilter/ipv6/nf_defrag_ipv6.h    |    6 
 include/net/netfilter/nf_tproxy_core.h         |   72 +++++
 include/net/udp.h                              |    3 
 net/ipv6/af_inet6.c                            |    2 
 net/ipv6/datagram.c                            |   19 +
 net/ipv6/ipv6_sockglue.c                       |   23 ++
 net/ipv6/netfilter/Makefile                    |    5 
 net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c |   78 ------
 net/ipv6/netfilter/nf_conntrack_reasm.c        |   12 +
 net/ipv6/netfilter/nf_defrag_ipv6_hooks.c      |  131 ++++++++++
 net/ipv6/udp.c                                 |   16 +
 net/netfilter/xt_TPROXY.c                      |  324 +++++++++++++++++++++---
 net/netfilter/xt_socket.c                      |  165 +++++++++++-
 16 files changed, 740 insertions(+), 139 deletions(-)
 create mode 100644 include/net/netfilter/ipv6/nf_defrag_ipv6.h
 create mode 100644 net/ipv6/netfilter/nf_defrag_ipv6_hooks.c

-- 
KOVACS Krisztian


^ permalink raw reply	[flat|nested] 27+ messages in thread

* [PATCH 1/9] tproxy: split off ipv6 defragmentation to a separate module
  2010-10-20 11:21 [PATCH 0/9] tproxy: add IPv6 support KOVACS Krisztian
@ 2010-10-20 11:21 ` KOVACS Krisztian
  2010-10-20 11:21 ` [PATCH 8/9] tproxy: added IPv6 support to the socket match KOVACS Krisztian
                   ` (7 subsequent siblings)
  8 siblings, 0 replies; 27+ messages in thread
From: KOVACS Krisztian @ 2010-10-20 11:21 UTC (permalink / raw)
  To: netdev, netfilter-devel; +Cc: Patrick McHardy, David Miller

From: Balazs Scheidler <bazsi@balabit.hu>

Like with IPv4, TProxy needs IPv6 defragmentation but does not
require connection tracking. Since defragmentation was coupled
with conntrack, I split off the two, creating an nf_defrag_ipv6 module,
similar to the already existing nf_defrag_ipv4.

Signed-off-by: Balazs Scheidler <bazsi@balabit.hu>
Signed-off-by: KOVACS Krisztian <hidden@balabit.hu>
---
 include/net/netfilter/ipv6/nf_defrag_ipv6.h    |    6 +
 net/ipv6/netfilter/Makefile                    |    5 +
 net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c |   78 +-------------
 net/ipv6/netfilter/nf_conntrack_reasm.c        |   12 ++
 net/ipv6/netfilter/nf_defrag_ipv6_hooks.c      |  131 ++++++++++++++++++++++++
 5 files changed, 154 insertions(+), 78 deletions(-)
 create mode 100644 include/net/netfilter/ipv6/nf_defrag_ipv6.h
 create mode 100644 net/ipv6/netfilter/nf_defrag_ipv6_hooks.c

diff --git a/include/net/netfilter/ipv6/nf_defrag_ipv6.h b/include/net/netfilter/ipv6/nf_defrag_ipv6.h
new file mode 100644
index 0000000..94dd54d
--- /dev/null
+++ b/include/net/netfilter/ipv6/nf_defrag_ipv6.h
@@ -0,0 +1,6 @@
+#ifndef _NF_DEFRAG_IPV6_H
+#define _NF_DEFRAG_IPV6_H
+
+extern void nf_defrag_ipv6_enable(void);
+
+#endif /* _NF_DEFRAG_IPV6_H */
diff --git a/net/ipv6/netfilter/Makefile b/net/ipv6/netfilter/Makefile
index aafbba3..3f8e4a3 100644
--- a/net/ipv6/netfilter/Makefile
+++ b/net/ipv6/netfilter/Makefile
@@ -11,10 +11,11 @@ obj-$(CONFIG_IP6_NF_RAW) += ip6table_raw.o
 obj-$(CONFIG_IP6_NF_SECURITY) += ip6table_security.o
 
 # objects for l3 independent conntrack
-nf_conntrack_ipv6-objs  :=  nf_conntrack_l3proto_ipv6.o nf_conntrack_proto_icmpv6.o nf_conntrack_reasm.o
+nf_conntrack_ipv6-objs  :=  nf_conntrack_l3proto_ipv6.o nf_conntrack_proto_icmpv6.o
+nf_defrag_ipv6-objs := nf_defrag_ipv6_hooks.o nf_conntrack_reasm.o
 
 # l3 independent conntrack
-obj-$(CONFIG_NF_CONNTRACK_IPV6) += nf_conntrack_ipv6.o
+obj-$(CONFIG_NF_CONNTRACK_IPV6) += nf_conntrack_ipv6.o nf_defrag_ipv6.o
 
 # matches
 obj-$(CONFIG_IP6_NF_MATCH_AH) += ip6t_ah.o
diff --git a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
index ff43461..c8af58b 100644
--- a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
+++ b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
@@ -16,7 +16,6 @@
 #include <linux/module.h>
 #include <linux/skbuff.h>
 #include <linux/icmp.h>
-#include <linux/sysctl.h>
 #include <net/ipv6.h>
 #include <net/inet_frag.h>
 
@@ -29,6 +28,7 @@
 #include <net/netfilter/nf_conntrack_core.h>
 #include <net/netfilter/nf_conntrack_zones.h>
 #include <net/netfilter/ipv6/nf_conntrack_ipv6.h>
+#include <net/netfilter/ipv6/nf_defrag_ipv6.h>
 #include <net/netfilter/nf_log.h>
 
 static bool ipv6_pkt_to_tuple(const struct sk_buff *skb, unsigned int nhoff,
@@ -189,53 +189,6 @@ out:
 	return nf_conntrack_confirm(skb);
 }
 
-static enum ip6_defrag_users nf_ct6_defrag_user(unsigned int hooknum,
-						struct sk_buff *skb)
-{
-	u16 zone = NF_CT_DEFAULT_ZONE;
-
-	if (skb->nfct)
-		zone = nf_ct_zone((struct nf_conn *)skb->nfct);
-
-#ifdef CONFIG_BRIDGE_NETFILTER
-	if (skb->nf_bridge &&
-	    skb->nf_bridge->mask & BRNF_NF_BRIDGE_PREROUTING)
-		return IP6_DEFRAG_CONNTRACK_BRIDGE_IN + zone;
-#endif
-	if (hooknum == NF_INET_PRE_ROUTING)
-		return IP6_DEFRAG_CONNTRACK_IN + zone;
-	else
-		return IP6_DEFRAG_CONNTRACK_OUT + zone;
-
-}
-
-static unsigned int ipv6_defrag(unsigned int hooknum,
-				struct sk_buff *skb,
-				const struct net_device *in,
-				const struct net_device *out,
-				int (*okfn)(struct sk_buff *))
-{
-	struct sk_buff *reasm;
-
-	/* Previously seen (loopback)?  */
-	if (skb->nfct && !nf_ct_is_template((struct nf_conn *)skb->nfct))
-		return NF_ACCEPT;
-
-	reasm = nf_ct_frag6_gather(skb, nf_ct6_defrag_user(hooknum, skb));
-	/* queued */
-	if (reasm == NULL)
-		return NF_STOLEN;
-
-	/* error occured or not fragmented */
-	if (reasm == skb)
-		return NF_ACCEPT;
-
-	nf_ct_frag6_output(hooknum, reasm, (struct net_device *)in,
-			   (struct net_device *)out, okfn);
-
-	return NF_STOLEN;
-}
-
 static unsigned int __ipv6_conntrack_in(struct net *net,
 					unsigned int hooknum,
 					struct sk_buff *skb,
@@ -288,13 +241,6 @@ static unsigned int ipv6_conntrack_local(unsigned int hooknum,
 
 static struct nf_hook_ops ipv6_conntrack_ops[] __read_mostly = {
 	{
-		.hook		= ipv6_defrag,
-		.owner		= THIS_MODULE,
-		.pf		= NFPROTO_IPV6,
-		.hooknum	= NF_INET_PRE_ROUTING,
-		.priority	= NF_IP6_PRI_CONNTRACK_DEFRAG,
-	},
-	{
 		.hook		= ipv6_conntrack_in,
 		.owner		= THIS_MODULE,
 		.pf		= NFPROTO_IPV6,
@@ -309,13 +255,6 @@ static struct nf_hook_ops ipv6_conntrack_ops[] __read_mostly = {
 		.priority	= NF_IP6_PRI_CONNTRACK,
 	},
 	{
-		.hook		= ipv6_defrag,
-		.owner		= THIS_MODULE,
-		.pf		= NFPROTO_IPV6,
-		.hooknum	= NF_INET_LOCAL_OUT,
-		.priority	= NF_IP6_PRI_CONNTRACK_DEFRAG,
-	},
-	{
 		.hook		= ipv6_confirm,
 		.owner		= THIS_MODULE,
 		.pf		= NFPROTO_IPV6,
@@ -387,10 +326,6 @@ struct nf_conntrack_l3proto nf_conntrack_l3proto_ipv6 __read_mostly = {
 	.nlattr_to_tuple	= ipv6_nlattr_to_tuple,
 	.nla_policy		= ipv6_nla_policy,
 #endif
-#ifdef CONFIG_SYSCTL
-	.ctl_table_path		= nf_net_netfilter_sysctl_path,
-	.ctl_table		= nf_ct_ipv6_sysctl_table,
-#endif
 	.me			= THIS_MODULE,
 };
 
@@ -403,16 +338,12 @@ static int __init nf_conntrack_l3proto_ipv6_init(void)
 	int ret = 0;
 
 	need_conntrack();
+	nf_defrag_ipv6_enable();
 
-	ret = nf_ct_frag6_init();
-	if (ret < 0) {
-		pr_err("nf_conntrack_ipv6: can't initialize frag6.\n");
-		return ret;
-	}
 	ret = nf_conntrack_l4proto_register(&nf_conntrack_l4proto_tcp6);
 	if (ret < 0) {
 		pr_err("nf_conntrack_ipv6: can't register tcp.\n");
-		goto cleanup_frag6;
+		return ret;
 	}
 
 	ret = nf_conntrack_l4proto_register(&nf_conntrack_l4proto_udp6);
@@ -450,8 +381,6 @@ static int __init nf_conntrack_l3proto_ipv6_init(void)
 	nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_udp6);
  cleanup_tcp:
 	nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_tcp6);
- cleanup_frag6:
-	nf_ct_frag6_cleanup();
 	return ret;
 }
 
@@ -463,7 +392,6 @@ static void __exit nf_conntrack_l3proto_ipv6_fini(void)
 	nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_icmpv6);
 	nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_udp6);
 	nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_tcp6);
-	nf_ct_frag6_cleanup();
 }
 
 module_init(nf_conntrack_l3proto_ipv6_init);
diff --git a/net/ipv6/netfilter/nf_conntrack_reasm.c b/net/ipv6/netfilter/nf_conntrack_reasm.c
index 138a8b3..bb669b4 100644
--- a/net/ipv6/netfilter/nf_conntrack_reasm.c
+++ b/net/ipv6/netfilter/nf_conntrack_reasm.c
@@ -73,7 +73,7 @@ static struct inet_frags nf_frags;
 static struct netns_frags nf_init_frags;
 
 #ifdef CONFIG_SYSCTL
-struct ctl_table nf_ct_ipv6_sysctl_table[] = {
+struct ctl_table nf_ct_frag6_sysctl_table[] = {
 	{
 		.procname	= "nf_conntrack_frag6_timeout",
 		.data		= &nf_init_frags.timeout,
@@ -97,6 +97,8 @@ struct ctl_table nf_ct_ipv6_sysctl_table[] = {
 	},
 	{ }
 };
+
+static struct ctl_table_header *nf_ct_frag6_sysctl_header;
 #endif
 
 static unsigned int nf_hashfn(struct inet_frag_queue *q)
@@ -623,11 +625,19 @@ int nf_ct_frag6_init(void)
 	inet_frags_init_net(&nf_init_frags);
 	inet_frags_init(&nf_frags);
 
+	nf_ct_frag6_sysctl_header = register_sysctl_paths(nf_net_netfilter_sysctl_path,
+							  nf_ct_frag6_sysctl_table);
+	if (!nf_ct_frag6_sysctl_header)
+		return -ENOMEM;
+
 	return 0;
 }
 
 void nf_ct_frag6_cleanup(void)
 {
+	unregister_sysctl_table(nf_ct_frag6_sysctl_header);
+	nf_ct_frag6_sysctl_header = NULL;
+
 	inet_frags_fini(&nf_frags);
 
 	nf_init_frags.low_thresh = 0;
diff --git a/net/ipv6/netfilter/nf_defrag_ipv6_hooks.c b/net/ipv6/netfilter/nf_defrag_ipv6_hooks.c
new file mode 100644
index 0000000..99abfb5
--- /dev/null
+++ b/net/ipv6/netfilter/nf_defrag_ipv6_hooks.c
@@ -0,0 +1,131 @@
+/* (C) 1999-2001 Paul `Rusty' Russell
+ * (C) 2002-2004 Netfilter Core Team <coreteam@netfilter.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/types.h>
+#include <linux/ipv6.h>
+#include <linux/in6.h>
+#include <linux/netfilter.h>
+#include <linux/module.h>
+#include <linux/skbuff.h>
+#include <linux/icmp.h>
+#include <linux/sysctl.h>
+#include <net/ipv6.h>
+#include <net/inet_frag.h>
+
+#include <linux/netfilter_ipv6.h>
+#include <linux/netfilter_bridge.h>
+#include <net/netfilter/nf_conntrack.h>
+#include <net/netfilter/nf_conntrack_helper.h>
+#include <net/netfilter/nf_conntrack_l4proto.h>
+#include <net/netfilter/nf_conntrack_l3proto.h>
+#include <net/netfilter/nf_conntrack_core.h>
+#include <net/netfilter/nf_conntrack_zones.h>
+#include <net/netfilter/ipv6/nf_conntrack_ipv6.h>
+#include <net/netfilter/ipv6/nf_defrag_ipv6.h>
+
+static enum ip6_defrag_users nf_ct6_defrag_user(unsigned int hooknum,
+						struct sk_buff *skb)
+{
+	u16 zone = NF_CT_DEFAULT_ZONE;
+
+	if (skb->nfct)
+		zone = nf_ct_zone((struct nf_conn *)skb->nfct);
+
+#ifdef CONFIG_BRIDGE_NETFILTER
+	if (skb->nf_bridge &&
+	    skb->nf_bridge->mask & BRNF_NF_BRIDGE_PREROUTING)
+		return IP6_DEFRAG_CONNTRACK_BRIDGE_IN + zone;
+#endif
+	if (hooknum == NF_INET_PRE_ROUTING)
+		return IP6_DEFRAG_CONNTRACK_IN + zone;
+	else
+		return IP6_DEFRAG_CONNTRACK_OUT + zone;
+
+}
+
+static unsigned int ipv6_defrag(unsigned int hooknum,
+				struct sk_buff *skb,
+				const struct net_device *in,
+				const struct net_device *out,
+				int (*okfn)(struct sk_buff *))
+{
+	struct sk_buff *reasm;
+
+	/* Previously seen (loopback)?	*/
+	if (skb->nfct && !nf_ct_is_template((struct nf_conn *)skb->nfct))
+		return NF_ACCEPT;
+
+	reasm = nf_ct_frag6_gather(skb, nf_ct6_defrag_user(hooknum, skb));
+	/* queued */
+	if (reasm == NULL)
+		return NF_STOLEN;
+
+	/* error occured or not fragmented */
+	if (reasm == skb)
+		return NF_ACCEPT;
+
+	nf_ct_frag6_output(hooknum, reasm, (struct net_device *)in,
+			   (struct net_device *)out, okfn);
+
+	return NF_STOLEN;
+}
+
+static struct nf_hook_ops ipv6_defrag_ops[] = {
+	{
+		.hook		= ipv6_defrag,
+		.owner		= THIS_MODULE,
+		.pf		= NFPROTO_IPV6,
+		.hooknum	= NF_INET_PRE_ROUTING,
+		.priority	= NF_IP6_PRI_CONNTRACK_DEFRAG,
+	},
+	{
+		.hook		= ipv6_defrag,
+		.owner		= THIS_MODULE,
+		.pf		= NFPROTO_IPV6,
+		.hooknum	= NF_INET_LOCAL_OUT,
+		.priority	= NF_IP6_PRI_CONNTRACK_DEFRAG,
+	},
+};
+
+static int __init nf_defrag_init(void)
+{
+	int ret = 0;
+
+	ret = nf_ct_frag6_init();
+	if (ret < 0) {
+		pr_err("nf_defrag_ipv6: can't initialize frag6.\n");
+		return ret;
+	}
+	ret = nf_register_hooks(ipv6_defrag_ops, ARRAY_SIZE(ipv6_defrag_ops));
+	if (ret < 0) {
+		pr_err("nf_defrag_ipv6: can't register hooks\n");
+		goto cleanup_frag6;
+	}
+	return ret;
+
+cleanup_frag6:
+	nf_ct_frag6_cleanup();
+	return ret;
+
+}
+
+static void __exit nf_defrag_fini(void)
+{
+	nf_unregister_hooks(ipv6_defrag_ops, ARRAY_SIZE(ipv6_defrag_ops));
+	nf_ct_frag6_cleanup();
+}
+
+void nf_defrag_ipv6_enable(void)
+{
+}
+EXPORT_SYMBOL_GPL(nf_defrag_ipv6_enable);
+
+module_init(nf_defrag_init);
+module_exit(nf_defrag_fini);
+
+MODULE_LICENSE("GPL");



^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH 2/9] tproxy: added const specifiers to udp lookup functions
  2010-10-20 11:21 [PATCH 0/9] tproxy: add IPv6 support KOVACS Krisztian
                   ` (6 preceding siblings ...)
  2010-10-20 11:21 ` [PATCH 5/9] tproxy: allow non-local binds of IPv6 sockets if IP_TRANSPARENT is enabled KOVACS Krisztian
@ 2010-10-20 11:21 ` KOVACS Krisztian
  2010-10-20 11:21 ` [PATCH 3/9] tproxy: added udp6_lib_lookup function KOVACS Krisztian
  8 siblings, 0 replies; 27+ messages in thread
From: KOVACS Krisztian @ 2010-10-20 11:21 UTC (permalink / raw)
  To: netdev, netfilter-devel; +Cc: Patrick McHardy, David Miller

From: Balazs Scheidler <bazsi@balabit.hu>

The parameters for various UDP lookup functions were non-const, even though
they could be const. TProxy has some const references and instead of
downcasting it, I added const specifiers along the path.

Signed-off-by: Balazs Scheidler <bazsi@balabit.hu>
Signed-off-by: KOVACS Krisztian <hidden@balabit.hu>
---
 net/ipv6/udp.c |    8 ++++----
 1 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c
index 5acb356..33e3683 100644
--- a/net/ipv6/udp.c
+++ b/net/ipv6/udp.c
@@ -122,8 +122,8 @@ static void udp_v6_rehash(struct sock *sk)
 
 static inline int compute_score(struct sock *sk, struct net *net,
 				unsigned short hnum,
-				struct in6_addr *saddr, __be16 sport,
-				struct in6_addr *daddr, __be16 dport,
+				const struct in6_addr *saddr, __be16 sport,
+				const struct in6_addr *daddr, __be16 dport,
 				int dif)
 {
 	int score = -1;
@@ -239,8 +239,8 @@ exact_match:
 }
 
 static struct sock *__udp6_lib_lookup(struct net *net,
-				      struct in6_addr *saddr, __be16 sport,
-				      struct in6_addr *daddr, __be16 dport,
+				      const struct in6_addr *saddr, __be16 sport,
+				      const struct in6_addr *daddr, __be16 dport,
 				      int dif, struct udp_table *udptable)
 {
 	struct sock *sk, *result;



^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH 3/9] tproxy: added udp6_lib_lookup function
  2010-10-20 11:21 [PATCH 0/9] tproxy: add IPv6 support KOVACS Krisztian
                   ` (7 preceding siblings ...)
  2010-10-20 11:21 ` [PATCH 2/9] tproxy: added const specifiers to udp lookup functions KOVACS Krisztian
@ 2010-10-20 11:21 ` KOVACS Krisztian
  8 siblings, 0 replies; 27+ messages in thread
From: KOVACS Krisztian @ 2010-10-20 11:21 UTC (permalink / raw)
  To: netdev, netfilter-devel; +Cc: Patrick McHardy, David Miller

From: Balazs Scheidler <bazsi@balabit.hu>

Just like with IPv4, we need access to the UDP hash table to look up local
sockets, but instead of exporting the global udp_table, export a lookup
function.

Signed-off-by: Balazs Scheidler <bazsi@balabit.hu>
Signed-off-by: KOVACS Krisztian <hidden@balabit.hu>
---
 include/net/udp.h |    3 +++
 net/ipv6/udp.c    |    8 ++++++++
 2 files changed, 11 insertions(+), 0 deletions(-)

diff --git a/include/net/udp.h b/include/net/udp.h
index a184d34..200b828 100644
--- a/include/net/udp.h
+++ b/include/net/udp.h
@@ -183,6 +183,9 @@ extern int udp_lib_setsockopt(struct sock *sk, int level, int optname,
 extern struct sock *udp4_lib_lookup(struct net *net, __be32 saddr, __be16 sport,
 				    __be32 daddr, __be16 dport,
 				    int dif);
+extern struct sock *udp6_lib_lookup(struct net *net, const struct in6_addr *saddr, __be16 sport,
+				    const struct in6_addr *daddr, __be16 dport,
+				    int dif);
 
 /*
  * 	SNMP statistics for UDP and UDP-Lite
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c
index 33e3683..c84dad4 100644
--- a/net/ipv6/udp.c
+++ b/net/ipv6/udp.c
@@ -320,6 +320,14 @@ static struct sock *__udp6_lib_lookup_skb(struct sk_buff *skb,
 				 udptable);
 }
 
+struct sock *udp6_lib_lookup(struct net *net, const struct in6_addr *saddr, __be16 sport,
+			     const struct in6_addr *daddr, __be16 dport, int dif)
+{
+	return __udp6_lib_lookup(net, saddr, sport, daddr, dport, dif, &udp_table);
+}
+EXPORT_SYMBOL_GPL(udp6_lib_lookup);
+
+
 /*
  * 	This should be easy, if there is something there we
  * 	return it, otherwise we block.



^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH 5/9] tproxy: allow non-local binds of IPv6 sockets if IP_TRANSPARENT is enabled
  2010-10-20 11:21 [PATCH 0/9] tproxy: add IPv6 support KOVACS Krisztian
                   ` (5 preceding siblings ...)
  2010-10-20 11:21 ` [PATCH 7/9] tproxy: added IPv6 support to the TPROXY target KOVACS Krisztian
@ 2010-10-20 11:21 ` KOVACS Krisztian
  2010-10-20 12:45   ` YOSHIFUJI Hideaki
  2010-10-20 11:21 ` [PATCH 2/9] tproxy: added const specifiers to udp lookup functions KOVACS Krisztian
  2010-10-20 11:21 ` [PATCH 3/9] tproxy: added udp6_lib_lookup function KOVACS Krisztian
  8 siblings, 1 reply; 27+ messages in thread
From: KOVACS Krisztian @ 2010-10-20 11:21 UTC (permalink / raw)
  To: netdev, netfilter-devel; +Cc: Patrick McHardy, David Miller

From: Balazs Scheidler <bazsi@balabit.hu>

Signed-off-by: Balazs Scheidler <bazsi@balabit.hu>
Signed-off-by: KOVACS Krisztian <hidden@balabit.hu>
---
 net/ipv6/af_inet6.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c
index 6022098..9480572 100644
--- a/net/ipv6/af_inet6.c
+++ b/net/ipv6/af_inet6.c
@@ -343,7 +343,7 @@ int inet6_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
 			 */
 			v4addr = LOOPBACK4_IPV6;
 			if (!(addr_type & IPV6_ADDR_MULTICAST))	{
-				if (!ipv6_chk_addr(net, &addr->sin6_addr,
+				if (!inet->transparent && !ipv6_chk_addr(net, &addr->sin6_addr,
 						   dev, 0)) {
 					err = -EADDRNOTAVAIL;
 					goto out_unlock;



^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH 8/9] tproxy: added IPv6 support to the socket match
  2010-10-20 11:21 [PATCH 0/9] tproxy: add IPv6 support KOVACS Krisztian
  2010-10-20 11:21 ` [PATCH 1/9] tproxy: split off ipv6 defragmentation to a separate module KOVACS Krisztian
@ 2010-10-20 11:21 ` KOVACS Krisztian
  2010-10-20 11:21 ` [PATCH 9/9] tproxy: use the interface primary IP address as a default value for --on-ip KOVACS Krisztian
                   ` (6 subsequent siblings)
  8 siblings, 0 replies; 27+ messages in thread
From: KOVACS Krisztian @ 2010-10-20 11:21 UTC (permalink / raw)
  To: netdev, netfilter-devel; +Cc: Patrick McHardy, David Miller

From: Balazs Scheidler <bazsi@balabit.hu>

The ICMP extraction bits were contributed by Harry Mason.

Signed-off-by: Balazs Scheidler <bazsi@balabit.hu>
Signed-off-by: KOVACS Krisztian <hidden@balabit.hu>
---
 net/netfilter/xt_socket.c |  165 ++++++++++++++++++++++++++++++++++++++++++---
 1 files changed, 154 insertions(+), 11 deletions(-)

diff --git a/net/netfilter/xt_socket.c b/net/netfilter/xt_socket.c
index 266faa0..1dc2784 100644
--- a/net/netfilter/xt_socket.c
+++ b/net/netfilter/xt_socket.c
@@ -14,6 +14,7 @@
 #include <linux/skbuff.h>
 #include <linux/netfilter/x_tables.h>
 #include <linux/netfilter_ipv4/ip_tables.h>
+#include <linux/netfilter_ipv6/ip6_tables.h>
 #include <net/tcp.h>
 #include <net/udp.h>
 #include <net/icmp.h>
@@ -21,6 +22,7 @@
 #include <net/inet_sock.h>
 #include <net/netfilter/nf_tproxy_core.h>
 #include <net/netfilter/ipv4/nf_defrag_ipv4.h>
+#include <net/netfilter/ipv6/nf_defrag_ipv6.h>
 
 #include <linux/netfilter/xt_socket.h>
 
@@ -30,7 +32,7 @@
 #endif
 
 static int
-extract_icmp_fields(const struct sk_buff *skb,
+extract_icmp4_fields(const struct sk_buff *skb,
 		    u8 *protocol,
 		    __be32 *raddr,
 		    __be32 *laddr,
@@ -86,7 +88,6 @@ extract_icmp_fields(const struct sk_buff *skb,
 	return 0;
 }
 
-
 static bool
 socket_match(const struct sk_buff *skb, struct xt_action_param *par,
 	     const struct xt_socket_mtinfo1 *info)
@@ -115,7 +116,7 @@ socket_match(const struct sk_buff *skb, struct xt_action_param *par,
 		dport = hp->dest;
 
 	} else if (iph->protocol == IPPROTO_ICMP) {
-		if (extract_icmp_fields(skb, &protocol, &saddr, &daddr,
+		if (extract_icmp4_fields(skb, &protocol, &saddr, &daddr,
 					&sport, &dport))
 			return false;
 	} else {
@@ -165,32 +166,157 @@ socket_match(const struct sk_buff *skb, struct xt_action_param *par,
 			sk = NULL;
 	}
 
-	pr_debug("proto %u %08x:%u -> %08x:%u (orig %08x:%u) sock %p\n",
-		 protocol, ntohl(saddr), ntohs(sport),
-		 ntohl(daddr), ntohs(dport),
-		 ntohl(iph->daddr), hp ? ntohs(hp->dest) : 0, sk);
+	pr_debug("proto %u %pI4:%u -> %pI4:%u (orig %pI4:%u) sock %p\n",
+		 protocol, &saddr, ntohs(sport),
+		 &daddr, ntohs(dport),
+		 &iph->daddr, hp ? ntohs(hp->dest) : 0, sk);
 
 	return (sk != NULL);
 }
 
 static bool
-socket_mt_v0(const struct sk_buff *skb, struct xt_action_param *par)
+socket_mt4_v0(const struct sk_buff *skb, struct xt_action_param *par)
 {
 	return socket_match(skb, par, NULL);
 }
 
 static bool
-socket_mt_v1(const struct sk_buff *skb, struct xt_action_param *par)
+socket_mt4_v1(const struct sk_buff *skb, struct xt_action_param *par)
 {
 	return socket_match(skb, par, par->matchinfo);
 }
 
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+
+static int
+extract_icmp6_fields(const struct sk_buff *skb,
+		     unsigned int outside_hdrlen,
+		     u8 *protocol,
+		     struct in6_addr **raddr,
+		     struct in6_addr **laddr,
+		     __be16 *rport,
+		     __be16 *lport)
+{
+	struct ipv6hdr *inside_iph, _inside_iph;
+	struct icmp6hdr *icmph, _icmph;
+	__be16 *ports, _ports[2];
+	u8 inside_nexthdr;
+	int inside_hdrlen;
+
+	icmph = skb_header_pointer(skb, outside_hdrlen,
+				   sizeof(_icmph), &_icmph);
+	if (icmph == NULL)
+		return 1;
+
+	if (icmph->icmp6_type & ICMPV6_INFOMSG_MASK)
+		return 1;
+
+	inside_iph = skb_header_pointer(skb, outside_hdrlen + sizeof(_icmph), sizeof(_inside_iph), &_inside_iph);
+	if (inside_iph == NULL)
+		return 1;
+	inside_nexthdr = inside_iph->nexthdr;
+
+	inside_hdrlen = ipv6_skip_exthdr(skb, outside_hdrlen + sizeof(_icmph) + sizeof(_inside_iph), &inside_nexthdr);
+	if (inside_hdrlen < 0)
+		return 1; /* hjm: Packet has no/incomplete transport layer headers. */
+
+	if (inside_nexthdr != IPPROTO_TCP &&
+	    inside_nexthdr != IPPROTO_UDP)
+		return 1;
+
+	ports = skb_header_pointer(skb, inside_hdrlen,
+				   sizeof(_ports), &_ports);
+	if (ports == NULL)
+		return 1;
+
+	/* the inside IP packet is the one quoted from our side, thus
+	 * its saddr is the local address */
+	*protocol = inside_nexthdr;
+	*laddr = &inside_iph->saddr;
+	*lport = ports[0];
+	*raddr = &inside_iph->daddr;
+	*rport = ports[1];
+
+	return 0;
+}
+
+static bool
+socket_mt6_v1(const struct sk_buff *skb, struct xt_action_param *par)
+{
+	struct ipv6hdr *iph = ipv6_hdr(skb);
+	struct udphdr _hdr, *hp = NULL;
+	struct sock *sk;
+	struct in6_addr *daddr, *saddr;
+	__be16 dport, sport;
+	int thoff;
+	u8 tproto;
+	const struct xt_socket_mtinfo1 *info = (struct xt_socket_mtinfo1 *) par->matchinfo;
+
+	tproto = ipv6_find_hdr(skb, &thoff, -1, NULL);
+	if (tproto < 0) {
+		pr_debug("unable to find transport header in IPv6 packet, dropping\n");
+		return NF_DROP;
+	}
+
+	if (tproto == IPPROTO_UDP || tproto == IPPROTO_TCP) {
+		hp = skb_header_pointer(skb, thoff,
+					sizeof(_hdr), &_hdr);
+		if (hp == NULL)
+			return false;
+
+		saddr = &iph->saddr;
+		sport = hp->source;
+		daddr = &iph->daddr;
+		dport = hp->dest;
+
+	} else if (tproto == IPPROTO_ICMPV6) {
+		if (extract_icmp6_fields(skb, thoff, &tproto, &saddr, &daddr,
+					 &sport, &dport))
+			return false;
+	} else {
+		return false;
+	}
+
+	sk = nf_tproxy_get_sock_v6(dev_net(skb->dev), tproto,
+				   saddr, daddr, sport, dport, par->in, NFT_LOOKUP_ANY);
+	if (sk != NULL) {
+		bool wildcard;
+		bool transparent = true;
+
+		/* Ignore sockets listening on INADDR_ANY */
+		wildcard = (sk->sk_state != TCP_TIME_WAIT &&
+			    ipv6_addr_any(&inet6_sk(sk)->rcv_saddr));
+
+		/* Ignore non-transparent sockets,
+		   if XT_SOCKET_TRANSPARENT is used */
+		if (info && info->flags & XT_SOCKET_TRANSPARENT)
+			transparent = ((sk->sk_state != TCP_TIME_WAIT &&
+					inet_sk(sk)->transparent) ||
+				       (sk->sk_state == TCP_TIME_WAIT &&
+					inet_twsk(sk)->tw_transparent));
+
+		nf_tproxy_put_sock(sk);
+
+		if (wildcard || !transparent)
+			sk = NULL;
+	}
+
+	pr_debug("proto %u %pI6:%u -> %pI6:%u "
+		 "(orig %pI6:%u) sock %p\n",
+		 tproto, saddr, ntohs(sport),
+		 daddr, ntohs(dport),
+		 &iph->daddr, hp ? ntohs(hp->dest) : 0, sk);
+
+	return (sk != NULL);
+}
+#endif
+
 static struct xt_match socket_mt_reg[] __read_mostly = {
 	{
 		.name		= "socket",
 		.revision	= 0,
 		.family		= NFPROTO_IPV4,
-		.match		= socket_mt_v0,
+		.match		= socket_mt4_v0,
 		.hooks		= (1 << NF_INET_PRE_ROUTING) |
 				  (1 << NF_INET_LOCAL_IN),
 		.me		= THIS_MODULE,
@@ -199,17 +325,33 @@ static struct xt_match socket_mt_reg[] __read_mostly = {
 		.name		= "socket",
 		.revision	= 1,
 		.family		= NFPROTO_IPV4,
-		.match		= socket_mt_v1,
+		.match		= socket_mt4_v1,
 		.matchsize	= sizeof(struct xt_socket_mtinfo1),
 		.hooks		= (1 << NF_INET_PRE_ROUTING) |
 				  (1 << NF_INET_LOCAL_IN),
 		.me		= THIS_MODULE,
 	},
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+	{
+		.name		= "socket",
+		.revision	= 1,
+		.family		= NFPROTO_IPV6,
+		.match		= socket_mt6_v1,
+		.matchsize	= sizeof(struct xt_socket_mtinfo1),
+		.hooks		= (1 << NF_INET_PRE_ROUTING) |
+				  (1 << NF_INET_LOCAL_IN),
+		.me		= THIS_MODULE,
+	},
+#endif
 };
 
 static int __init socket_mt_init(void)
 {
 	nf_defrag_ipv4_enable();
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+	nf_defrag_ipv6_enable();
+#endif
+
 	return xt_register_matches(socket_mt_reg, ARRAY_SIZE(socket_mt_reg));
 }
 
@@ -225,3 +367,4 @@ MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Krisztian Kovacs, Balazs Scheidler");
 MODULE_DESCRIPTION("x_tables socket match module");
 MODULE_ALIAS("ipt_socket");
+MODULE_ALIAS("ip6t_socket");



^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH 9/9] tproxy: use the interface primary IP address as a default value for --on-ip
  2010-10-20 11:21 [PATCH 0/9] tproxy: add IPv6 support KOVACS Krisztian
  2010-10-20 11:21 ` [PATCH 1/9] tproxy: split off ipv6 defragmentation to a separate module KOVACS Krisztian
  2010-10-20 11:21 ` [PATCH 8/9] tproxy: added IPv6 support to the socket match KOVACS Krisztian
@ 2010-10-20 11:21 ` KOVACS Krisztian
  2010-10-21  9:12   ` Jan Engelhardt
  2010-10-20 11:21 ` [PATCH 4/9] tproxy: added tproxy sockopt interface in the IPV6 layer KOVACS Krisztian
                   ` (5 subsequent siblings)
  8 siblings, 1 reply; 27+ messages in thread
From: KOVACS Krisztian @ 2010-10-20 11:21 UTC (permalink / raw)
  To: netdev, netfilter-devel; +Cc: Patrick McHardy, David Miller

From: Balazs Scheidler <bazsi@balabit.hu>

The REDIRECT target and the older TProxy versions used the primary address
of the incoming interface as the default value of the --on-ip parameter.
This was unintentionally changed during the initial TProxy submission and
caused confusion among users.

Since IPv6 has no notion of primary address, we just select the first address
on the list: this way the socket lookup finds wildcard bound sockets
properly and we cannot really do better without the user telling us the
IPv6 address of the proxy.

This is implemented for both IPv4 and IPv6.

Signed-off-by: Balazs Scheidler <bazsi@balabit.hu>
Signed-off-by: KOVACS Krisztian <hidden@balabit.hu>
---
 net/netfilter/xt_TPROXY.c |  198 +++++++++++++++++++++++++++++----------------
 1 files changed, 128 insertions(+), 70 deletions(-)

diff --git a/net/netfilter/xt_TPROXY.c b/net/netfilter/xt_TPROXY.c
index 6ce76d6..a90ff20 100644
--- a/net/netfilter/xt_TPROXY.c
+++ b/net/netfilter/xt_TPROXY.c
@@ -16,15 +16,41 @@
 #include <net/checksum.h>
 #include <net/udp.h>
 #include <net/inet_sock.h>
-
+#include <linux/inetdevice.h>
 #include <linux/netfilter/x_tables.h>
 #include <linux/netfilter_ipv4/ip_tables.h>
-#include <linux/netfilter_ipv6/ip6_tables.h>
-#include <linux/netfilter/xt_TPROXY.h>
 
 #include <net/netfilter/ipv4/nf_defrag_ipv4.h>
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+#include <net/if_inet6.h>
+#include <net/addrconf.h>
+#include <linux/netfilter_ipv6/ip6_tables.h>
 #include <net/netfilter/ipv6/nf_defrag_ipv6.h>
+#endif
+
 #include <net/netfilter/nf_tproxy_core.h>
+#include <linux/netfilter/xt_TPROXY.h>
+
+static inline __be32
+tproxy_laddr4(struct sk_buff *skb, __be32 user_laddr, __be32 daddr)
+{
+	struct in_device *indev;
+	__be32 laddr;
+
+	if (user_laddr)
+		return user_laddr;
+
+	laddr = 0;
+	rcu_read_lock();
+	indev = __in_dev_get_rcu(skb->dev);
+	for_primary_ifa(indev) {
+		laddr = ifa->ifa_local;
+		break;
+	} endfor_ifa(indev);
+	rcu_read_unlock();
+
+	return laddr ? laddr : daddr;
+}
 
 /**
  * tproxy_handle_time_wait4() - handle IPv4 TCP TIME_WAIT reopen redirections
@@ -75,60 +101,6 @@ tproxy_handle_time_wait4(struct sk_buff *skb, __be32 laddr, __be16 lport,
 	return sk;
 }
 
-/**
- * tproxy_handle_time_wait6() - handle IPv6 TCP TIME_WAIT reopen redirections
- * @skb:	The skb being processed.
- * @tproto:	Transport protocol.
- * @thoff:	Transport protocol header offset.
- * @par:	Iptables target parameters.
- * @sk:		The TIME_WAIT TCP socket found by the lookup.
- *
- * We have to handle SYN packets arriving to TIME_WAIT sockets
- * differently: instead of reopening the connection we should rather
- * redirect the new connection to the proxy if there's a listener
- * socket present.
- *
- * tproxy_handle_time_wait6() consumes the socket reference passed in.
- *
- * Returns the listener socket if there's one, the TIME_WAIT socket if
- * no such listener is found, or NULL if the TCP header is incomplete.
- */
-static struct sock *
-tproxy_handle_time_wait6(struct sk_buff *skb, int tproto, int thoff,
-			 const struct xt_action_param *par,
-			 struct sock *sk)
-{
-	const struct ipv6hdr *iph = ipv6_hdr(skb);
-	struct tcphdr _hdr, *hp;
-	const struct xt_tproxy_target_info_v1 *tgi = par->targinfo;
-
-	hp = skb_header_pointer(skb, thoff, sizeof(_hdr), &_hdr);
-	if (hp == NULL) {
-		inet_twsk_put(inet_twsk(sk));
-		return NULL;
-	}
-
-	if (hp->syn && !hp->rst && !hp->ack && !hp->fin) {
-		/* SYN to a TIME_WAIT socket, we'd rather redirect it
-		 * to a listener socket if there's one */
-		struct sock *sk2;
-
-		sk2 = nf_tproxy_get_sock_v6(dev_net(skb->dev), tproto,
-					    &iph->saddr,
-					    !ipv6_addr_any(&tgi->laddr.in6) ? &tgi->laddr.in6 : &iph->daddr,
-					    hp->source,
-					    tgi->lport ? tgi->lport : hp->dest,
-					    skb->dev, NFT_LOOKUP_LISTENER);
-		if (sk2) {
-			inet_twsk_deschedule(inet_twsk(sk), &tcp_death_row);
-			inet_twsk_put(inet_twsk(sk));
-			sk = sk2;
-		}
-	}
-
-	return sk;
-}
-
 static unsigned int
 tproxy_tg4(struct sk_buff *skb, __be32 laddr, __be16 lport,
 	   u_int32_t mark_mask, u_int32_t mark_value)
@@ -150,6 +122,10 @@ tproxy_tg4(struct sk_buff *skb, __be32 laddr, __be16 lport,
 				   hp->source, hp->dest,
 				   skb->dev, NFT_LOOKUP_ESTABLISHED);
 
+	laddr = tproxy_laddr4(skb, laddr, iph->daddr);
+	if (!lport)
+		lport = hp->dest;
+
 	/* UDP has no TCP_TIME_WAIT state, so we never enter here */
 	if (sk && sk->sk_state == TCP_TIME_WAIT)
 		/* reopening a TIME_WAIT connection needs special handling */
@@ -158,8 +134,8 @@ tproxy_tg4(struct sk_buff *skb, __be32 laddr, __be16 lport,
 		/* no, there's no established connection, check if
 		 * there's a listener on the redirected addr/port */
 		sk = nf_tproxy_get_sock_v4(dev_net(skb->dev), iph->protocol,
-					   iph->saddr, laddr ? laddr : iph->daddr,
-					   hp->source, lport ? lport : hp->dest,
+					   iph->saddr, laddr,
+					   hp->source, lport,
 					   skb->dev, NFT_LOOKUP_LISTENER);
 
 	/* NOTE: assign_sock consumes our sk reference */
@@ -174,9 +150,9 @@ tproxy_tg4(struct sk_buff *skb, __be32 laddr, __be16 lport,
 		return NF_ACCEPT;
 	}
 
-	pr_debug("no socket, dropping: proto %u %08x:%u -> %08x:%u, mark: %x\n",
-		 iph->protocol, ntohl(iph->daddr), ntohs(hp->dest),
-		 ntohl(laddr), ntohs(lport), skb->mark);
+	pr_debug("no socket, dropping: proto %u %pI4:%u -> %pI4:%u, mark: %x\n",
+		 iph->protocol, &iph->saddr, ntohs(hp->source),
+		 &iph->daddr, ntohs(hp->dest), skb->mark);
 	return NF_DROP;
 }
 
@@ -197,6 +173,85 @@ tproxy_tg4_v1(struct sk_buff *skb, const struct xt_action_param *par)
 }
 
 #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+
+static inline const struct in6_addr *
+tproxy_laddr6(struct sk_buff *skb, const struct in6_addr *user_laddr, const struct in6_addr *daddr)
+{
+	struct inet6_dev *indev;
+	struct inet6_ifaddr *ifa;
+	struct in6_addr *laddr;
+
+	if (!ipv6_addr_any(user_laddr))
+		return user_laddr;
+	laddr = NULL;
+
+	rcu_read_lock();
+	indev = __in6_dev_get(skb->dev);
+	if (indev)
+		list_for_each_entry(ifa, &indev->addr_list, if_list) {
+			/* FIXME: address selection */
+			laddr = &ifa->addr;
+			break;
+		}
+	rcu_read_unlock();
+
+	return laddr ? laddr : daddr;
+}
+
+/**
+ * tproxy_handle_time_wait6() - handle IPv6 TCP TIME_WAIT reopen redirections
+ * @skb:	The skb being processed.
+ * @tproto:	Transport protocol.
+ * @thoff:	Transport protocol header offset.
+ * @par:	Iptables target parameters.
+ * @sk:		The TIME_WAIT TCP socket found by the lookup.
+ *
+ * We have to handle SYN packets arriving to TIME_WAIT sockets
+ * differently: instead of reopening the connection we should rather
+ * redirect the new connection to the proxy if there's a listener
+ * socket present.
+ *
+ * tproxy_handle_time_wait6() consumes the socket reference passed in.
+ *
+ * Returns the listener socket if there's one, the TIME_WAIT socket if
+ * no such listener is found, or NULL if the TCP header is incomplete.
+ */
+static struct sock *
+tproxy_handle_time_wait6(struct sk_buff *skb, int tproto, int thoff,
+			 const struct xt_action_param *par,
+			 struct sock *sk)
+{
+	const struct ipv6hdr *iph = ipv6_hdr(skb);
+	struct tcphdr _hdr, *hp;
+	const struct xt_tproxy_target_info_v1 *tgi = par->targinfo;
+
+	hp = skb_header_pointer(skb, thoff, sizeof(_hdr), &_hdr);
+	if (hp == NULL) {
+		inet_twsk_put(inet_twsk(sk));
+		return NULL;
+	}
+
+	if (hp->syn && !hp->rst && !hp->ack && !hp->fin) {
+		/* SYN to a TIME_WAIT socket, we'd rather redirect it
+		 * to a listener socket if there's one */
+		struct sock *sk2;
+
+		sk2 = nf_tproxy_get_sock_v6(dev_net(skb->dev), tproto,
+					    &iph->saddr,
+					    tproxy_laddr6(skb, &tgi->laddr.in6, &iph->daddr),
+					    hp->source,
+					    tgi->lport ? tgi->lport : hp->dest,
+					    skb->dev, NFT_LOOKUP_LISTENER);
+		if (sk2) {
+			inet_twsk_deschedule(inet_twsk(sk), &tcp_death_row);
+			inet_twsk_put(inet_twsk(sk));
+			sk = sk2;
+		}
+	}
+
+	return sk;
+}
+
 static unsigned int
 tproxy_tg6_v1(struct sk_buff *skb, const struct xt_action_param *par)
 {
@@ -204,6 +259,8 @@ tproxy_tg6_v1(struct sk_buff *skb, const struct xt_action_param *par)
 	const struct xt_tproxy_target_info_v1 *tgi = par->targinfo;
 	struct udphdr _hdr, *hp;
 	struct sock *sk;
+	const struct in6_addr *laddr;
+	__be16 lport;
 	int thoff;
 	int tproto;
 
@@ -228,6 +285,9 @@ tproxy_tg6_v1(struct sk_buff *skb, const struct xt_action_param *par)
 				   hp->source, hp->dest,
 				   par->in, NFT_LOOKUP_ESTABLISHED);
 
+	laddr = tproxy_laddr6(skb, &tgi->laddr.in6, &iph->daddr);
+	lport = tgi->lport ? tgi->lport : hp->dest;
+
 	/* UDP has no TCP_TIME_WAIT state, so we never enter here */
 	if (sk && sk->sk_state == TCP_TIME_WAIT)
 		/* reopening a TIME_WAIT connection needs special handling */
@@ -236,10 +296,8 @@ tproxy_tg6_v1(struct sk_buff *skb, const struct xt_action_param *par)
 		/* no there's no established connection, check if
 		 * there's a listener on the redirected addr/port */
 		sk = nf_tproxy_get_sock_v6(dev_net(skb->dev), tproto,
-					   &iph->saddr,
-					   !ipv6_addr_any(&tgi->laddr.in6) ? &tgi->laddr.in6 : &iph->daddr,
-					   hp->source,
-					   tgi->lport ? tgi->lport : hp->dest,
+					   &iph->saddr, laddr,
+					   hp->source, lport,
 					   par->in, NFT_LOOKUP_LISTENER);
 
 	/* NOTE: assign_sock consumes our sk reference */
@@ -249,14 +307,14 @@ tproxy_tg6_v1(struct sk_buff *skb, const struct xt_action_param *par)
 		skb->mark = (skb->mark & ~tgi->mark_mask) ^ tgi->mark_value;
 
 		pr_debug("redirecting: proto %u %pI6:%u -> %pI6:%u, mark: %x\n",
-			 tproto, &iph->saddr, ntohs(hp->dest),
-			 &tgi->laddr.in6, ntohs(tgi->lport), skb->mark);
+			 tproto, &iph->saddr, ntohs(hp->source),
+			 laddr, ntohs(lport), skb->mark);
 		return NF_ACCEPT;
 	}
 
 	pr_debug("no socket, dropping: proto %u %pI6:%u -> %pI6:%u, mark: %x\n",
-		 tproto, &iph->saddr, ntohs(hp->dest),
-		 &tgi->laddr.in6, ntohs(tgi->lport), skb->mark);
+		 tproto, &iph->saddr, ntohs(hp->source),
+		 &iph->daddr, ntohs(hp->dest), skb->mark);
 	return NF_DROP;
 }
 



^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH 7/9] tproxy: added IPv6 support to the TPROXY target
  2010-10-20 11:21 [PATCH 0/9] tproxy: add IPv6 support KOVACS Krisztian
                   ` (4 preceding siblings ...)
  2010-10-20 11:21 ` [PATCH 6/9] tproxy: added IPv6 socket lookup function to nf_tproxy_core KOVACS Krisztian
@ 2010-10-20 11:21 ` KOVACS Krisztian
  2010-10-21  8:47   ` Jan Engelhardt
  2010-10-20 11:21 ` [PATCH 5/9] tproxy: allow non-local binds of IPv6 sockets if IP_TRANSPARENT is enabled KOVACS Krisztian
                   ` (2 subsequent siblings)
  8 siblings, 1 reply; 27+ messages in thread
From: KOVACS Krisztian @ 2010-10-20 11:21 UTC (permalink / raw)
  To: netdev, netfilter-devel; +Cc: Patrick McHardy, David Miller

From: Balazs Scheidler <bazsi@balabit.hu>

This requires a new revision as the old target structure was
IPv4 specific.

Signed-off-by: Balazs Scheidler <bazsi@balabit.hu>
Signed-off-by: KOVACS Krisztian <hidden@balabit.hu>
---
 include/linux/netfilter/xt_TPROXY.h |   15 +-
 net/netfilter/xt_TPROXY.c           |  262 ++++++++++++++++++++++++++++++-----
 2 files changed, 236 insertions(+), 41 deletions(-)

diff --git a/include/linux/netfilter/xt_TPROXY.h b/include/linux/netfilter/xt_TPROXY.h
index 152e8f9..7b4e06d 100644
--- a/include/linux/netfilter/xt_TPROXY.h
+++ b/include/linux/netfilter/xt_TPROXY.h
@@ -1,14 +1,21 @@
-#ifndef _XT_TPROXY_H_target
-#define _XT_TPROXY_H_target
+#ifndef _XT_TPROXY_H
+#define _XT_TPROXY_H
 
 /* TPROXY target is capable of marking the packet to perform
  * redirection. We can get rid of that whenever we get support for
  * mutliple targets in the same rule. */
-struct xt_tproxy_target_info {
+struct xt_tproxy_target_info_v0 {
 	u_int32_t mark_mask;
 	u_int32_t mark_value;
 	__be32 laddr;
 	__be16 lport;
 };
 
-#endif /* _XT_TPROXY_H_target */
+struct xt_tproxy_target_info_v1 {
+	u_int32_t mark_mask;
+	u_int32_t mark_value;
+	union nf_inet_addr laddr;
+	__be16 lport;
+};
+
+#endif /* _XT_TPROXY_H */
diff --git a/net/netfilter/xt_TPROXY.c b/net/netfilter/xt_TPROXY.c
index 67cbed8..6ce76d6 100644
--- a/net/netfilter/xt_TPROXY.c
+++ b/net/netfilter/xt_TPROXY.c
@@ -1,7 +1,7 @@
 /*
  * Transparent proxy support for Linux/iptables
  *
- * Copyright (c) 2006-2007 BalaBit IT Ltd.
+ * Copyright (c) 2006-2010 BalaBit IT Ltd.
  * Author: Balazs Scheidler, Krisztian Kovacs
  *
  * This program is free software; you can redistribute it and/or modify
@@ -19,15 +19,18 @@
 
 #include <linux/netfilter/x_tables.h>
 #include <linux/netfilter_ipv4/ip_tables.h>
+#include <linux/netfilter_ipv6/ip6_tables.h>
 #include <linux/netfilter/xt_TPROXY.h>
 
 #include <net/netfilter/ipv4/nf_defrag_ipv4.h>
+#include <net/netfilter/ipv6/nf_defrag_ipv6.h>
 #include <net/netfilter/nf_tproxy_core.h>
 
 /**
- * tproxy_handle_time_wait() - handle TCP TIME_WAIT reopen redirections
+ * tproxy_handle_time_wait4() - handle IPv4 TCP TIME_WAIT reopen redirections
  * @skb:	The skb being processed.
- * @par:	Iptables target parameters.
+ * @laddr:	IPv4 address to redirect to or zero.
+ * @lport:	TCP port to redirect to or zero.
  * @sk:		The TIME_WAIT TCP socket found by the lookup.
  *
  * We have to handle SYN packets arriving to TIME_WAIT sockets
@@ -35,16 +38,16 @@
  * redirect the new connection to the proxy if there's a listener
  * socket present.
  *
- * tproxy_handle_time_wait() consumes the socket reference passed in.
+ * tproxy_handle_time_wait4() consumes the socket reference passed in.
  *
  * Returns the listener socket if there's one, the TIME_WAIT socket if
  * no such listener is found, or NULL if the TCP header is incomplete.
  */
 static struct sock *
-tproxy_handle_time_wait(struct sk_buff *skb, const struct xt_action_param *par, struct sock *sk)
+tproxy_handle_time_wait4(struct sk_buff *skb, __be32 laddr, __be16 lport,
+			struct sock *sk)
 {
 	const struct iphdr *iph = ip_hdr(skb);
-	const struct xt_tproxy_target_info *tgi = par->targinfo;
 	struct tcphdr _hdr, *hp;
 
 	hp = skb_header_pointer(skb, ip_hdrlen(skb), sizeof(_hdr), &_hdr);
@@ -59,13 +62,64 @@ tproxy_handle_time_wait(struct sk_buff *skb, const struct xt_action_param *par,
 		struct sock *sk2;
 
 		sk2 = nf_tproxy_get_sock_v4(dev_net(skb->dev), iph->protocol,
-					    iph->saddr, tgi->laddr ? tgi->laddr : iph->daddr,
-					    hp->source, tgi->lport ? tgi->lport : hp->dest,
-					    par->in, NFT_LOOKUP_LISTENER);
+					    iph->saddr, laddr ? laddr : iph->daddr,
+					    hp->source, lport ? lport : hp->dest,
+					    skb->dev, NFT_LOOKUP_LISTENER);
+		if (sk2) {
+			inet_twsk_deschedule(inet_twsk(sk), &tcp_death_row);
+			inet_twsk_put(inet_twsk(sk));
+			sk = sk2;
+		}
+	}
+
+	return sk;
+}
+
+/**
+ * tproxy_handle_time_wait6() - handle IPv6 TCP TIME_WAIT reopen redirections
+ * @skb:	The skb being processed.
+ * @tproto:	Transport protocol.
+ * @thoff:	Transport protocol header offset.
+ * @par:	Iptables target parameters.
+ * @sk:		The TIME_WAIT TCP socket found by the lookup.
+ *
+ * We have to handle SYN packets arriving to TIME_WAIT sockets
+ * differently: instead of reopening the connection we should rather
+ * redirect the new connection to the proxy if there's a listener
+ * socket present.
+ *
+ * tproxy_handle_time_wait6() consumes the socket reference passed in.
+ *
+ * Returns the listener socket if there's one, the TIME_WAIT socket if
+ * no such listener is found, or NULL if the TCP header is incomplete.
+ */
+static struct sock *
+tproxy_handle_time_wait6(struct sk_buff *skb, int tproto, int thoff,
+			 const struct xt_action_param *par,
+			 struct sock *sk)
+{
+	const struct ipv6hdr *iph = ipv6_hdr(skb);
+	struct tcphdr _hdr, *hp;
+	const struct xt_tproxy_target_info_v1 *tgi = par->targinfo;
+
+	hp = skb_header_pointer(skb, thoff, sizeof(_hdr), &_hdr);
+	if (hp == NULL) {
+		inet_twsk_put(inet_twsk(sk));
+		return NULL;
+	}
+
+	if (hp->syn && !hp->rst && !hp->ack && !hp->fin) {
+		/* SYN to a TIME_WAIT socket, we'd rather redirect it
+		 * to a listener socket if there's one */
+		struct sock *sk2;
+
+		sk2 = nf_tproxy_get_sock_v6(dev_net(skb->dev), tproto,
+					    &iph->saddr,
+					    !ipv6_addr_any(&tgi->laddr.in6) ? &tgi->laddr.in6 : &iph->daddr,
+					    hp->source,
+					    tgi->lport ? tgi->lport : hp->dest,
+					    skb->dev, NFT_LOOKUP_LISTENER);
 		if (sk2) {
-			/* yeah, there's one, let's kill the TIME_WAIT
-			 * socket and redirect to the listener
-			 */
 			inet_twsk_deschedule(inet_twsk(sk), &tcp_death_row);
 			inet_twsk_put(inet_twsk(sk));
 			sk = sk2;
@@ -76,10 +130,10 @@ tproxy_handle_time_wait(struct sk_buff *skb, const struct xt_action_param *par,
 }
 
 static unsigned int
-tproxy_tg(struct sk_buff *skb, const struct xt_action_param *par)
+tproxy_tg4(struct sk_buff *skb, __be32 laddr, __be16 lport,
+	   u_int32_t mark_mask, u_int32_t mark_value)
 {
 	const struct iphdr *iph = ip_hdr(skb);
-	const struct xt_tproxy_target_info *tgi = par->targinfo;
 	struct udphdr _hdr, *hp;
 	struct sock *sk;
 
@@ -87,39 +141,140 @@ tproxy_tg(struct sk_buff *skb, const struct xt_action_param *par)
 	if (hp == NULL)
 		return NF_DROP;
 
+	/* check if there's an ongoing connection on the packet
+	 * addresses, this happens if the redirect already happened
+	 * and the current packet belongs to an already established
+	 * connection */
 	sk = nf_tproxy_get_sock_v4(dev_net(skb->dev), iph->protocol,
 				   iph->saddr, iph->daddr,
 				   hp->source, hp->dest,
-				   par->in, NFT_LOOKUP_ESTABLISHED);
+				   skb->dev, NFT_LOOKUP_ESTABLISHED);
 
 	/* UDP has no TCP_TIME_WAIT state, so we never enter here */
 	if (sk && sk->sk_state == TCP_TIME_WAIT)
-		sk = tproxy_handle_time_wait(skb, par, sk);
+		/* reopening a TIME_WAIT connection needs special handling */
+		sk = tproxy_handle_time_wait4(skb, laddr, lport, sk);
 	else if (!sk)
+		/* no, there's no established connection, check if
+		 * there's a listener on the redirected addr/port */
 		sk = nf_tproxy_get_sock_v4(dev_net(skb->dev), iph->protocol,
-					   iph->saddr, tgi->laddr ? tgi->laddr : iph->daddr,
-					   hp->source, tgi->lport ? tgi->lport : hp->dest,
-					   par->in, NFT_LOOKUP_LISTENER);
+					   iph->saddr, laddr ? laddr : iph->daddr,
+					   hp->source, lport ? lport : hp->dest,
+					   skb->dev, NFT_LOOKUP_LISTENER);
 
 	/* NOTE: assign_sock consumes our sk reference */
 	if (sk && nf_tproxy_assign_sock(skb, sk)) {
 		/* This should be in a separate target, but we don't do multiple
 		   targets on the same rule yet */
-		skb->mark = (skb->mark & ~tgi->mark_mask) ^ tgi->mark_value;
+		skb->mark = (skb->mark & ~mark_mask) ^ mark_value;
 
-		pr_debug("redirecting: proto %u %08x:%u -> %08x:%u, mark: %x\n",
-			 iph->protocol, ntohl(iph->daddr), ntohs(hp->dest),
-			 ntohl(tgi->laddr), ntohs(tgi->lport), skb->mark);
+		pr_debug("redirecting: proto %u %pI4:%u -> %pI4:%u, mark: %x\n",
+			 iph->protocol, &iph->daddr, ntohs(hp->dest),
+			 &laddr, ntohs(lport), skb->mark);
 		return NF_ACCEPT;
 	}
 
 	pr_debug("no socket, dropping: proto %u %08x:%u -> %08x:%u, mark: %x\n",
 		 iph->protocol, ntohl(iph->daddr), ntohs(hp->dest),
-		 ntohl(tgi->laddr), ntohs(tgi->lport), skb->mark);
+		 ntohl(laddr), ntohs(lport), skb->mark);
+	return NF_DROP;
+}
+
+static unsigned int
+tproxy_tg4_v0(struct sk_buff *skb, const struct xt_action_param *par)
+{
+	const struct xt_tproxy_target_info_v0 *tgi = par->targinfo;
+
+	return tproxy_tg4(skb, tgi->laddr, tgi->lport, tgi->mark_mask, tgi->mark_value);
+}
+
+static unsigned int
+tproxy_tg4_v1(struct sk_buff *skb, const struct xt_action_param *par)
+{
+	const struct xt_tproxy_target_info_v1 *tgi = par->targinfo;
+
+	return tproxy_tg4(skb, tgi->laddr.ip, tgi->lport, tgi->mark_mask, tgi->mark_value);
+}
+
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+static unsigned int
+tproxy_tg6_v1(struct sk_buff *skb, const struct xt_action_param *par)
+{
+	const struct ipv6hdr *iph = ipv6_hdr(skb);
+	const struct xt_tproxy_target_info_v1 *tgi = par->targinfo;
+	struct udphdr _hdr, *hp;
+	struct sock *sk;
+	int thoff;
+	int tproto;
+
+	tproto = ipv6_find_hdr(skb, &thoff, -1, NULL);
+	if (tproto < 0) {
+		pr_debug("unable to find transport header in IPv6 packet, dropping\n");
+		return NF_DROP;
+	}
+
+	hp = skb_header_pointer(skb, thoff, sizeof(_hdr), &_hdr);
+	if (hp == NULL) {
+		pr_debug("unable to grab transport header contents in IPv6 packet, dropping\n");
+		return NF_DROP;
+	}
+
+	/* check if there's an ongoing connection on the packet
+	 * addresses, this happens if the redirect already happened
+	 * and the current packet belongs to an already established
+	 * connection */
+	sk = nf_tproxy_get_sock_v6(dev_net(skb->dev), tproto,
+				   &iph->saddr, &iph->daddr,
+				   hp->source, hp->dest,
+				   par->in, NFT_LOOKUP_ESTABLISHED);
+
+	/* UDP has no TCP_TIME_WAIT state, so we never enter here */
+	if (sk && sk->sk_state == TCP_TIME_WAIT)
+		/* reopening a TIME_WAIT connection needs special handling */
+		sk = tproxy_handle_time_wait6(skb, tproto, thoff, par, sk);
+	else if (!sk)
+		/* no there's no established connection, check if
+		 * there's a listener on the redirected addr/port */
+		sk = nf_tproxy_get_sock_v6(dev_net(skb->dev), tproto,
+					   &iph->saddr,
+					   !ipv6_addr_any(&tgi->laddr.in6) ? &tgi->laddr.in6 : &iph->daddr,
+					   hp->source,
+					   tgi->lport ? tgi->lport : hp->dest,
+					   par->in, NFT_LOOKUP_LISTENER);
+
+	/* NOTE: assign_sock consumes our sk reference */
+	if (sk && nf_tproxy_assign_sock(skb, sk)) {
+		/* This should be in a separate target, but we don't do multiple
+		   targets on the same rule yet */
+		skb->mark = (skb->mark & ~tgi->mark_mask) ^ tgi->mark_value;
+
+		pr_debug("redirecting: proto %u %pI6:%u -> %pI6:%u, mark: %x\n",
+			 tproto, &iph->saddr, ntohs(hp->dest),
+			 &tgi->laddr.in6, ntohs(tgi->lport), skb->mark);
+		return NF_ACCEPT;
+	}
+
+	pr_debug("no socket, dropping: proto %u %pI6:%u -> %pI6:%u, mark: %x\n",
+		 tproto, &iph->saddr, ntohs(hp->dest),
+		 &tgi->laddr.in6, ntohs(tgi->lport), skb->mark);
 	return NF_DROP;
 }
 
-static int tproxy_tg_check(const struct xt_tgchk_param *par)
+static int tproxy_tg6_check(const struct xt_tgchk_param *par)
+{
+	const struct ip6t_ip6 *i = par->entryinfo;
+
+	if ((i->proto == IPPROTO_TCP || i->proto == IPPROTO_UDP)
+	    && !(i->flags & IP6T_INV_PROTO))
+		return 0;
+
+	pr_info("Can be used only in combination with "
+		"either -p tcp or -p udp\n");
+	return -EINVAL;
+}
+#endif
+
+static int tproxy_tg4_check(const struct xt_tgchk_param *par)
 {
 	const struct ipt_ip *i = par->entryinfo;
 
@@ -132,31 +287,64 @@ static int tproxy_tg_check(const struct xt_tgchk_param *par)
 	return -EINVAL;
 }
 
-static struct xt_target tproxy_tg_reg __read_mostly = {
-	.name		= "TPROXY",
-	.family		= AF_INET,
-	.table		= "mangle",
-	.target		= tproxy_tg,
-	.targetsize	= sizeof(struct xt_tproxy_target_info),
-	.checkentry	= tproxy_tg_check,
-	.hooks		= 1 << NF_INET_PRE_ROUTING,
-	.me		= THIS_MODULE,
+static struct xt_target tproxy_tg_reg[] __read_mostly = {
+	{
+		.name		= "TPROXY",
+		.family		= NFPROTO_IPV4,
+		.table		= "mangle",
+		.target		= tproxy_tg4_v0,
+		.revision	= 0,
+		.targetsize	= sizeof(struct xt_tproxy_target_info_v0),
+		.checkentry	= tproxy_tg4_check,
+		.hooks		= 1 << NF_INET_PRE_ROUTING,
+		.me		= THIS_MODULE,
+	},
+	{
+		.name		= "TPROXY",
+		.family		= NFPROTO_IPV4,
+		.table		= "mangle",
+		.target		= tproxy_tg4_v1,
+		.revision	= 1,
+		.targetsize	= sizeof(struct xt_tproxy_target_info_v1),
+		.checkentry	= tproxy_tg4_check,
+		.hooks		= 1 << NF_INET_PRE_ROUTING,
+		.me		= THIS_MODULE,
+	},
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+	{
+		.name		= "TPROXY",
+		.family		= NFPROTO_IPV6,
+		.table		= "mangle",
+		.target		= tproxy_tg6_v1,
+		.revision	= 1,
+		.targetsize	= sizeof(struct xt_tproxy_target_info_v1),
+		.checkentry	= tproxy_tg6_check,
+		.hooks		= 1 << NF_INET_PRE_ROUTING,
+		.me		= THIS_MODULE,
+	},
+#endif
+
 };
 
 static int __init tproxy_tg_init(void)
 {
 	nf_defrag_ipv4_enable();
-	return xt_register_target(&tproxy_tg_reg);
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+	nf_defrag_ipv6_enable();
+#endif
+
+	return xt_register_targets(tproxy_tg_reg, ARRAY_SIZE(tproxy_tg_reg));
 }
 
 static void __exit tproxy_tg_exit(void)
 {
-	xt_unregister_target(&tproxy_tg_reg);
+	xt_unregister_targets(tproxy_tg_reg, ARRAY_SIZE(tproxy_tg_reg));
 }
 
 module_init(tproxy_tg_init);
 module_exit(tproxy_tg_exit);
 MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Krisztian Kovacs");
+MODULE_AUTHOR("Balazs Scheidler, Krisztian Kovacs");
 MODULE_DESCRIPTION("Netfilter transparent proxy (TPROXY) target module.");
 MODULE_ALIAS("ipt_TPROXY");
+MODULE_ALIAS("ip6t_TPROXY");



^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH 6/9] tproxy: added IPv6 socket lookup function to nf_tproxy_core
  2010-10-20 11:21 [PATCH 0/9] tproxy: add IPv6 support KOVACS Krisztian
                   ` (3 preceding siblings ...)
  2010-10-20 11:21 ` [PATCH 4/9] tproxy: added tproxy sockopt interface in the IPV6 layer KOVACS Krisztian
@ 2010-10-20 11:21 ` KOVACS Krisztian
  2010-10-21  8:42   ` Jan Engelhardt
  2010-10-20 11:21 ` [PATCH 7/9] tproxy: added IPv6 support to the TPROXY target KOVACS Krisztian
                   ` (3 subsequent siblings)
  8 siblings, 1 reply; 27+ messages in thread
From: KOVACS Krisztian @ 2010-10-20 11:21 UTC (permalink / raw)
  To: netdev, netfilter-devel; +Cc: Patrick McHardy, David Miller

From: Balazs Scheidler <bazsi@balabit.hu>

Signed-off-by: Balazs Scheidler <bazsi@balabit.hu>
Signed-off-by: KOVACS Krisztian <hidden@balabit.hu>
---
 include/net/netfilter/nf_tproxy_core.h |   72 ++++++++++++++++++++++++++++++++
 1 files changed, 71 insertions(+), 1 deletions(-)

diff --git a/include/net/netfilter/nf_tproxy_core.h b/include/net/netfilter/nf_tproxy_core.h
index 1027d7f..cd85b3b 100644
--- a/include/net/netfilter/nf_tproxy_core.h
+++ b/include/net/netfilter/nf_tproxy_core.h
@@ -5,7 +5,8 @@
 #include <linux/in.h>
 #include <linux/skbuff.h>
 #include <net/sock.h>
-#include <net/inet_sock.h>
+#include <net/inet_hashtables.h>
+#include <net/inet6_hashtables.h>
 #include <net/tcp.h>
 
 #define NFT_LOOKUP_ANY         0
@@ -130,6 +131,75 @@ nf_tproxy_get_sock_v4(struct net *net, const u8 protocol,
 	return sk;
 }
 
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+static inline struct sock *
+nf_tproxy_get_sock_v6(struct net *net, const u8 protocol,
+		      const struct in6_addr *saddr, const struct in6_addr *daddr,
+		      const __be16 sport, const __be16 dport,
+		      const struct net_device *in, int lookup_type)
+{
+	struct sock *sk;
+
+	/* look up socket */
+	switch (protocol) {
+	case IPPROTO_TCP:
+		switch (lookup_type) {
+		case NFT_LOOKUP_ANY:
+			sk = inet6_lookup(net, &tcp_hashinfo,
+					  saddr, sport, daddr, dport,
+					  in->ifindex);
+			break;
+		case NFT_LOOKUP_LISTENER:
+			sk = inet6_lookup_listener(net, &tcp_hashinfo,
+						   daddr, ntohs(dport),
+						   in->ifindex);
+
+			/* NOTE: we return listeners even if bound to
+			 * 0.0.0.0, those are filtered out in
+			 * xt_socket, since xt_TPROXY needs 0 bound
+			 * listeners too */
+
+			break;
+		case NFT_LOOKUP_ESTABLISHED:
+			sk = __inet6_lookup_established(net, &tcp_hashinfo,
+							saddr, sport, daddr, ntohs(dport),
+							in->ifindex);
+			break;
+		default:
+			WARN_ON(1);
+			sk = NULL;
+			break;
+		}
+		break;
+	case IPPROTO_UDP:
+		sk = udp6_lib_lookup(net, saddr, sport, daddr, dport,
+				     in->ifindex);
+		if (sk && lookup_type != NFT_LOOKUP_ANY) {
+			int connected = (sk->sk_state == TCP_ESTABLISHED);
+			int wildcard = ipv6_addr_any(&inet6_sk(sk)->rcv_saddr);
+
+			/* NOTE: we return listeners even if bound to
+			 * 0.0.0.0, those are filtered out in
+			 * xt_socket, since xt_TPROXY needs 0 bound
+			 * listeners too */
+			if ((lookup_type == NFT_LOOKUP_ESTABLISHED && (!connected || wildcard)) ||
+			    (lookup_type == NFT_LOOKUP_LISTENER && connected)) {
+				sock_put(sk);
+				sk = NULL;
+			}
+		}
+		break;
+	default:
+		WARN_ON(1);
+		sk = NULL;
+	}
+
+	pr_debug("tproxy socket lookup: proto %u %pI6:%u -> %pI6:%u, lookup type: %d, sock %p\n",
+		 protocol, saddr, ntohs(sport), daddr, ntohs(dport), lookup_type, sk);
+
+	return sk;
+}
+#endif
 
 static inline void
 nf_tproxy_put_sock(struct sock *sk)



^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH 4/9] tproxy: added tproxy sockopt interface in the IPV6 layer
  2010-10-20 11:21 [PATCH 0/9] tproxy: add IPv6 support KOVACS Krisztian
                   ` (2 preceding siblings ...)
  2010-10-20 11:21 ` [PATCH 9/9] tproxy: use the interface primary IP address as a default value for --on-ip KOVACS Krisztian
@ 2010-10-20 11:21 ` KOVACS Krisztian
  2010-10-21  8:39   ` Jan Engelhardt
  2010-10-20 11:21 ` [PATCH 6/9] tproxy: added IPv6 socket lookup function to nf_tproxy_core KOVACS Krisztian
                   ` (4 subsequent siblings)
  8 siblings, 1 reply; 27+ messages in thread
From: KOVACS Krisztian @ 2010-10-20 11:21 UTC (permalink / raw)
  To: netdev, netfilter-devel; +Cc: Patrick McHardy, David Miller

From: Balazs Scheidler <bazsi@balabit.hu>

Support for IPV6_RECVORIGDSTADDR sockopt for UDP sockets were contributed by
Harry Mason.

Signed-off-by: Balazs Scheidler <bazsi@balabit.hu>
Signed-off-by: KOVACS Krisztian <hidden@balabit.hu>
---
 include/linux/in6.h      |    4 ++++
 include/linux/ipv6.h     |    4 +++-
 net/ipv6/datagram.c      |   19 +++++++++++++++++++
 net/ipv6/ipv6_sockglue.c |   23 +++++++++++++++++++++++
 4 files changed, 49 insertions(+), 1 deletions(-)

diff --git a/include/linux/in6.h b/include/linux/in6.h
index c4bf46f..097a34b 100644
--- a/include/linux/in6.h
+++ b/include/linux/in6.h
@@ -268,6 +268,10 @@ struct in6_flowlabel_req {
 /* RFC5082: Generalized Ttl Security Mechanism */
 #define IPV6_MINHOPCOUNT		73
 
+#define IPV6_ORIGDSTADDR        74
+#define IPV6_RECVORIGDSTADDR    IPV6_ORIGDSTADDR
+#define IPV6_TRANSPARENT        75
+
 /*
  * Multicast Routing:
  * see include/linux/mroute6.h.
diff --git a/include/linux/ipv6.h b/include/linux/ipv6.h
index e62683b..8e429d0 100644
--- a/include/linux/ipv6.h
+++ b/include/linux/ipv6.h
@@ -341,7 +341,9 @@ struct ipv6_pinfo {
 				odstopts:1,
                                 rxflow:1,
 				rxtclass:1,
-				rxpmtu:1;
+				rxpmtu:1,
+				rxorigdstaddr:1;
+				/* 2 bits hole */
 		} bits;
 		__u16		all;
 	} rxopt;
diff --git a/net/ipv6/datagram.c b/net/ipv6/datagram.c
index ef371aa..320bdb8 100644
--- a/net/ipv6/datagram.c
+++ b/net/ipv6/datagram.c
@@ -577,6 +577,25 @@ int datagram_recv_ctl(struct sock *sk, struct msghdr *msg, struct sk_buff *skb)
 		u8 *ptr = nh + opt->dst1;
 		put_cmsg(msg, SOL_IPV6, IPV6_2292DSTOPTS, (ptr[1]+1)<<3, ptr);
 	}
+	if (np->rxopt.bits.rxorigdstaddr) {
+		struct sockaddr_in6 sin6;
+		u16 *ports = (u16 *) skb_transport_header(skb);
+
+		if (skb_transport_offset(skb) + 4 <= skb->len) {
+			/* All current transport protocols have the port numbers in the
+			 * first four bytes of the transport header and this function is
+			 * written with this assumption in mind.
+			 */
+
+			sin6.sin6_family = AF_INET6;
+			ipv6_addr_copy(&sin6.sin6_addr, &ipv6_hdr(skb)->daddr);
+			sin6.sin6_port = ports[1];
+			sin6.sin6_flowinfo = 0;
+			sin6.sin6_scope_id = 0;
+
+			put_cmsg(msg, SOL_IPV6, IPV6_ORIGDSTADDR, sizeof(sin6), &sin6);
+		}
+	}
 	return 0;
 }
 
diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c
index a7f66bc..0553867 100644
--- a/net/ipv6/ipv6_sockglue.c
+++ b/net/ipv6/ipv6_sockglue.c
@@ -342,6 +342,21 @@ static int do_ipv6_setsockopt(struct sock *sk, int level, int optname,
 		retv = 0;
 		break;
 
+	case IPV6_TRANSPARENT:
+		if (optlen < sizeof(int))
+			goto e_inval;
+		/* we don't have a separate transparent bit for IPV6 we use the one in the IPv4 socket */
+		inet_sk(sk)->transparent = valbool;
+		retv = 0;
+		break;
+
+	case IPV6_RECVORIGDSTADDR:
+		if (optlen < sizeof(int))
+			goto e_inval;
+		np->rxopt.bits.rxorigdstaddr = valbool;
+		retv = 0;
+		break;
+
 	case IPV6_HOPOPTS:
 	case IPV6_RTHDRDSTOPTS:
 	case IPV6_RTHDR:
@@ -1104,6 +1119,14 @@ static int do_ipv6_getsockopt(struct sock *sk, int level, int optname,
 		break;
 	}
 
+	case IPV6_TRANSPARENT:
+		val = inet_sk(sk)->transparent;
+		break;
+
+	case IPV6_RECVORIGDSTADDR:
+		val = np->rxopt.bits.rxorigdstaddr;
+		break;
+
 	case IPV6_UNICAST_HOPS:
 	case IPV6_MULTICAST_HOPS:
 	{



^ permalink raw reply related	[flat|nested] 27+ messages in thread

* Re: [PATCH 5/9] tproxy: allow non-local binds of IPv6 sockets if IP_TRANSPARENT is enabled
  2010-10-20 11:21 ` [PATCH 5/9] tproxy: allow non-local binds of IPv6 sockets if IP_TRANSPARENT is enabled KOVACS Krisztian
@ 2010-10-20 12:45   ` YOSHIFUJI Hideaki
  2010-10-20 14:07     ` Balazs Scheidler
  0 siblings, 1 reply; 27+ messages in thread
From: YOSHIFUJI Hideaki @ 2010-10-20 12:45 UTC (permalink / raw)
  To: KOVACS Krisztian; +Cc: netdev, netfilter-devel, Patrick McHardy, David Miller

Hello.

(2010/10/20 20:21), KOVACS Krisztian wrote:
> From: Balazs Scheidler<bazsi@balabit.hu>
> 
> Signed-off-by: Balazs Scheidler<bazsi@balabit.hu>
> Signed-off-by: KOVACS Krisztian<hidden@balabit.hu>
> ---
>   net/ipv6/af_inet6.c |    2 +-
>   1 files changed, 1 insertions(+), 1 deletions(-)
> 
> diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c
> index 6022098..9480572 100644
> --- a/net/ipv6/af_inet6.c
> +++ b/net/ipv6/af_inet6.c
> @@ -343,7 +343,7 @@ int inet6_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
>   			 */
>   			v4addr = LOOPBACK4_IPV6;
>   			if (!(addr_type&  IPV6_ADDR_MULTICAST))	{
> -				if (!ipv6_chk_addr(net,&addr->sin6_addr,
> +				if (!inet->transparent&&  !ipv6_chk_addr(net,&addr->sin6_addr,
>   						   dev, 0)) {
>   					err = -EADDRNOTAVAIL;
>   					goto out_unlock;
> 
> 

As I wrote before in other thread, this does not seem sufficient --
well, it is sufficient to allow non-local bind, but before we're
allowing this, we need add checks of source address in sending side.

Regards,

--yoshfuji

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH 5/9] tproxy: allow non-local binds of IPv6 sockets if IP_TRANSPARENT is enabled
  2010-10-20 12:45   ` YOSHIFUJI Hideaki
@ 2010-10-20 14:07     ` Balazs Scheidler
  2010-10-21 21:24       ` YOSHIFUJI Hideaki
  0 siblings, 1 reply; 27+ messages in thread
From: Balazs Scheidler @ 2010-10-20 14:07 UTC (permalink / raw)
  To: YOSHIFUJI Hideaki
  Cc: KOVACS Krisztian, netdev, netfilter-devel, Patrick McHardy, David Miller

On Wed, 2010-10-20 at 21:45 +0900, YOSHIFUJI Hideaki wrote:
> (2010/10/20 20:21), KOVACS Krisztian wrote:
> > From: Balazs Scheidler<bazsi@balabit.hu>
> > 
> > Signed-off-by: Balazs Scheidler<bazsi@balabit.hu>
> > Signed-off-by: KOVACS Krisztian<hidden@balabit.hu>
> > ---
> >   net/ipv6/af_inet6.c |    2 +-
> >   1 files changed, 1 insertions(+), 1 deletions(-)
> > 
> > diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c
> > index 6022098..9480572 100644
> > --- a/net/ipv6/af_inet6.c
> > +++ b/net/ipv6/af_inet6.c
> > @@ -343,7 +343,7 @@ int inet6_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
> >   			 */
> >   			v4addr = LOOPBACK4_IPV6;
> >   			if (!(addr_type&  IPV6_ADDR_MULTICAST))	{
> > -				if (!ipv6_chk_addr(net,&addr->sin6_addr,
> > +				if (!inet->transparent&&  !ipv6_chk_addr(net,&addr->sin6_addr,
> >   						   dev, 0)) {
> >   					err = -EADDRNOTAVAIL;
> >   					goto out_unlock;
> > 
> > 
> 
> As I wrote before in other thread, this does not seem sufficient --
> well, it is sufficient to allow non-local bind, but before we're
> allowing this, we need add checks of source address in sending side.

Can you please elaborate or point us to the other thread? Is it some
kind of address-type check that we miss?

-- 
Bazsi



^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH 4/9] tproxy: added tproxy sockopt interface in the IPV6 layer
  2010-10-20 11:21 ` [PATCH 4/9] tproxy: added tproxy sockopt interface in the IPV6 layer KOVACS Krisztian
@ 2010-10-21  8:39   ` Jan Engelhardt
  2010-10-21  8:46     ` KOVACS Krisztian
  0 siblings, 1 reply; 27+ messages in thread
From: Jan Engelhardt @ 2010-10-21  8:39 UTC (permalink / raw)
  To: KOVACS Krisztian; +Cc: netdev, netfilter-devel, Patrick McHardy, David Miller

On Wednesday 2010-10-20 13:21, KOVACS Krisztian wrote:

>@@ -268,6 +268,10 @@ struct in6_flowlabel_req {
> /* RFC5082: Generalized Ttl Security Mechanism */
> #define IPV6_MINHOPCOUNT		73
> 
>+#define IPV6_ORIGDSTADDR        74
>+#define IPV6_RECVORIGDSTADDR    IPV6_ORIGDSTADDR
>+#define IPV6_TRANSPARENT        75
>+

Why do we actually need two names for the same thing?

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH 6/9] tproxy: added IPv6 socket lookup function to nf_tproxy_core
  2010-10-20 11:21 ` [PATCH 6/9] tproxy: added IPv6 socket lookup function to nf_tproxy_core KOVACS Krisztian
@ 2010-10-21  8:42   ` Jan Engelhardt
  2010-10-21  9:48     ` KOVACS Krisztian
  0 siblings, 1 reply; 27+ messages in thread
From: Jan Engelhardt @ 2010-10-21  8:42 UTC (permalink / raw)
  To: KOVACS Krisztian; +Cc: netdev, netfilter-devel, Patrick McHardy, David Miller


On Wednesday 2010-10-20 13:21, KOVACS Krisztian wrote:
>+
>+	pr_debug("tproxy socket lookup: proto %u %pI6:%u -> %pI6:%u, lookup type: %d, sock %p\n",
>+		 protocol, saddr, ntohs(sport), daddr, ntohs(dport), lookup_type, sk);

Shorts should preferably be used with %hd/%hu.

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH 4/9] tproxy: added tproxy sockopt interface in the IPV6 layer
  2010-10-21  8:39   ` Jan Engelhardt
@ 2010-10-21  8:46     ` KOVACS Krisztian
  2010-10-21 21:09       ` YOSHIFUJI Hideaki
  0 siblings, 1 reply; 27+ messages in thread
From: KOVACS Krisztian @ 2010-10-21  8:46 UTC (permalink / raw)
  To: Jan Engelhardt; +Cc: netdev, netfilter-devel, Patrick McHardy, David Miller

Hi,

On Thu, 2010-10-21 at 10:39 +0200, Jan Engelhardt wrote:
> On Wednesday 2010-10-20 13:21, KOVACS Krisztian wrote:
> 
> >@@ -268,6 +268,10 @@ struct in6_flowlabel_req {
> > /* RFC5082: Generalized Ttl Security Mechanism */
> > #define IPV6_MINHOPCOUNT		73
> > 
> >+#define IPV6_ORIGDSTADDR        74
> >+#define IPV6_RECVORIGDSTADDR    IPV6_ORIGDSTADDR
> >+#define IPV6_TRANSPARENT        75
> >+
> 
> Why do we actually need two names for the same thing?

IPV6_RECVORIGDSTADDR is the name of the socket option you're supposed to
set if you require the original destination address. IPV6_ORIGDSTADDR is
the name of the ancillary message you get with the actual address in it.
Just like we have it for IP_TOS/IP_RECVTOS, for example.

--KK




^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH 7/9] tproxy: added IPv6 support to the TPROXY target
  2010-10-20 11:21 ` [PATCH 7/9] tproxy: added IPv6 support to the TPROXY target KOVACS Krisztian
@ 2010-10-21  8:47   ` Jan Engelhardt
  2010-10-21  8:50     ` KOVACS Krisztian
  0 siblings, 1 reply; 27+ messages in thread
From: Jan Engelhardt @ 2010-10-21  8:47 UTC (permalink / raw)
  To: KOVACS Krisztian; +Cc: netdev, netfilter-devel, Patrick McHardy, David Miller


On Wednesday 2010-10-20 13:21, KOVACS Krisztian wrote:
> 
> /* TPROXY target is capable of marking the packet to perform
>  * redirection. We can get rid of that whenever we get support for
>  * mutliple targets in the same rule. */
>-struct xt_tproxy_target_info {
>+struct xt_tproxy_target_info_v0 {
> 	u_int32_t mark_mask;
> 	u_int32_t mark_value;
> 	__be32 laddr;
> 	__be16 lport;
> };

You cannot change the struct name either, or it may break userspace
compilations.


^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH 7/9] tproxy: added IPv6 support to the TPROXY target
  2010-10-21  8:47   ` Jan Engelhardt
@ 2010-10-21  8:50     ` KOVACS Krisztian
  2010-10-21  9:14       ` Jan Engelhardt
  0 siblings, 1 reply; 27+ messages in thread
From: KOVACS Krisztian @ 2010-10-21  8:50 UTC (permalink / raw)
  To: Jan Engelhardt; +Cc: netdev, netfilter-devel, Patrick McHardy, David Miller

Hi,

On Thu, 2010-10-21 at 10:47 +0200, Jan Engelhardt wrote:
> On Wednesday 2010-10-20 13:21, KOVACS Krisztian wrote:
> > 
> > /* TPROXY target is capable of marking the packet to perform
> >  * redirection. We can get rid of that whenever we get support for
> >  * mutliple targets in the same rule. */
> >-struct xt_tproxy_target_info {
> >+struct xt_tproxy_target_info_v0 {
> > 	u_int32_t mark_mask;
> > 	u_int32_t mark_value;
> > 	__be32 laddr;
> > 	__be16 lport;
> > };
> 
> You cannot change the struct name either, or it may break userspace
> compilations.

True, though iptables has its own copy of the header anyway.

--KK



^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH 9/9] tproxy: use the interface primary IP address as a default value for --on-ip
  2010-10-20 11:21 ` [PATCH 9/9] tproxy: use the interface primary IP address as a default value for --on-ip KOVACS Krisztian
@ 2010-10-21  9:12   ` Jan Engelhardt
  2010-10-21 10:32     ` KOVACS Krisztian
  0 siblings, 1 reply; 27+ messages in thread
From: Jan Engelhardt @ 2010-10-21  9:12 UTC (permalink / raw)
  To: KOVACS Krisztian; +Cc: netdev, netfilter-devel, Patrick McHardy, David Miller


On Wednesday 2010-10-20 13:21, KOVACS Krisztian wrote:
>+
>+	if (!ipv6_addr_any(user_laddr))
>+		return user_laddr;
>+	laddr = NULL;
>+
>+	rcu_read_lock();
>+	indev = __in6_dev_get(skb->dev);
>+	if (indev)
>+		list_for_each_entry(ifa, &indev->addr_list, if_list) {
>+			/* FIXME: address selection */

Per our realworld discussion, I believe we should add checks for
some conditions (RFC 4862 section 2):

1. ignore tentative addresses

	if (ifa->ifa_flags & IFA_F_TENTATIVE)
		continue;

2. tests for when the interface's ifa->preferred_lft == 0/deprecatedness:

	if (ctinfo == IP_CT_NEW/RELATED && (ifa->ifa_flags & IFA_F_DEPRECATED))
		continue;

3. check for invalid addresses
(There might be a flag like tentative..)

	if (ifa->valid_lft == 0)
		continue;


^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH 7/9] tproxy: added IPv6 support to the TPROXY target
  2010-10-21  8:50     ` KOVACS Krisztian
@ 2010-10-21  9:14       ` Jan Engelhardt
  2010-10-21  9:33         ` KOVACS Krisztian
  0 siblings, 1 reply; 27+ messages in thread
From: Jan Engelhardt @ 2010-10-21  9:14 UTC (permalink / raw)
  To: KOVACS Krisztian; +Cc: netdev, netfilter-devel, Patrick McHardy, David Miller

On Thursday 2010-10-21 10:50, KOVACS Krisztian wrote:

>Hi,
>
>On Thu, 2010-10-21 at 10:47 +0200, Jan Engelhardt wrote:
>> On Wednesday 2010-10-20 13:21, KOVACS Krisztian wrote:
>> > 
>> > /* TPROXY target is capable of marking the packet to perform
>> >  * redirection. We can get rid of that whenever we get support for
>> >  * mutliple targets in the same rule. */
>> >-struct xt_tproxy_target_info {
>> >+struct xt_tproxy_target_info_v0 {
>> > 	u_int32_t mark_mask;
>> > 	u_int32_t mark_value;
>> > 	__be32 laddr;
>> > 	__be16 lport;
>> > };
>> 
>> You cannot change the struct name either, or it may break userspace
>> compilations.
>
>True, though iptables has its own copy of the header anyway.

There is - or so I always hear - other userspace programs.

As for iptables, we only do the copy so that it compiles independent of 
the kernel version. You have to assume that the headers can be updated 
at any time.

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH 7/9] tproxy: added IPv6 support to the TPROXY target
  2010-10-21  9:14       ` Jan Engelhardt
@ 2010-10-21  9:33         ` KOVACS Krisztian
  0 siblings, 0 replies; 27+ messages in thread
From: KOVACS Krisztian @ 2010-10-21  9:33 UTC (permalink / raw)
  To: Jan Engelhardt; +Cc: netdev, netfilter-devel, Patrick McHardy, David Miller

Hi,

On Thu, 2010-10-21 at 11:14 +0200, Jan Engelhardt wrote:
> On Thursday 2010-10-21 10:50, KOVACS Krisztian wrote:
> 
> >Hi,
> >
> >On Thu, 2010-10-21 at 10:47 +0200, Jan Engelhardt wrote:
> >> On Wednesday 2010-10-20 13:21, KOVACS Krisztian wrote:
> >> > 
> >> > /* TPROXY target is capable of marking the packet to perform
> >> >  * redirection. We can get rid of that whenever we get support for
> >> >  * mutliple targets in the same rule. */
> >> >-struct xt_tproxy_target_info {
> >> >+struct xt_tproxy_target_info_v0 {
> >> > 	u_int32_t mark_mask;
> >> > 	u_int32_t mark_value;
> >> > 	__be32 laddr;
> >> > 	__be16 lport;
> >> > };
> >> 
> >> You cannot change the struct name either, or it may break userspace
> >> compilations.
> >
> >True, though iptables has its own copy of the header anyway.
> 
> There is - or so I always hear - other userspace programs.
> 
> As for iptables, we only do the copy so that it compiles independent of 
> the kernel version. You have to assume that the headers can be updated 
> at any time.

Sure, I wasn't implying we shouldn't fix this in the patch, I just doubt
there's anything else other than iptables using this and iptables itself
isn't affected.

Anyway, I've fixed it. Thanks, Jan.

--KK



^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH 6/9] tproxy: added IPv6 socket lookup function to nf_tproxy_core
  2010-10-21  8:42   ` Jan Engelhardt
@ 2010-10-21  9:48     ` KOVACS Krisztian
  0 siblings, 0 replies; 27+ messages in thread
From: KOVACS Krisztian @ 2010-10-21  9:48 UTC (permalink / raw)
  To: Jan Engelhardt; +Cc: netdev, netfilter-devel, Patrick McHardy, David Miller

Hi,

On Thu, 2010-10-21 at 10:42 +0200, Jan Engelhardt wrote:
> On Wednesday 2010-10-20 13:21, KOVACS Krisztian wrote:
> >+
> >+	pr_debug("tproxy socket lookup: proto %u %pI6:%u -> %pI6:%u, lookup type: %d, sock %p\n",
> >+		 protocol, saddr, ntohs(sport), daddr, ntohs(dport), lookup_type, sk);
> 
> Shorts should preferably be used with %hd/%hu.

Fixed, thanks Jan.

--KK



^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH 9/9] tproxy: use the interface primary IP address as a default value for --on-ip
  2010-10-21  9:12   ` Jan Engelhardt
@ 2010-10-21 10:32     ` KOVACS Krisztian
  0 siblings, 0 replies; 27+ messages in thread
From: KOVACS Krisztian @ 2010-10-21 10:32 UTC (permalink / raw)
  To: Jan Engelhardt; +Cc: netdev, netfilter-devel, Patrick McHardy, David Miller

Hi,

On Thu, 2010-10-21 at 11:12 +0200, Jan Engelhardt wrote:
> On Wednesday 2010-10-20 13:21, KOVACS Krisztian wrote:
> >+
> >+	if (!ipv6_addr_any(user_laddr))
> >+		return user_laddr;
> >+	laddr = NULL;
> >+
> >+	rcu_read_lock();
> >+	indev = __in6_dev_get(skb->dev);
> >+	if (indev)
> >+		list_for_each_entry(ifa, &indev->addr_list, if_list) {
> >+			/* FIXME: address selection */
> 
> Per our realworld discussion, I believe we should add checks for
> some conditions (RFC 4862 section 2):
> 
> 1. ignore tentative addresses
> 
> 	if (ifa->ifa_flags & IFA_F_TENTATIVE)
> 		continue;

Yep, we should definitely do that.

> 2. tests for when the interface's ifa->preferred_lft == 0/deprecatedness:
> 
> 	if (ctinfo == IP_CT_NEW/RELATED && (ifa->ifa_flags & IFA_F_DEPRECATED))
> 		continue;

Well, we can use the TPROXY target without conntrack so we cannot really
check if ctinfo==IP_CT_NEW/RELATED. However, we do address selection
only in case no established socket was found for the skb, so I think
it's safe to ignore addresses with IFA_F_DEPRECATED set.

Something like

	if (ifa->ifa_flags & (IFA_F_TENTATIVE | IFA_F_DEPRECATED))
		continue;

> 3. check for invalid addresses
> (There might be a flag like tentative..)
> 
> 	if (ifa->valid_lft == 0)
> 		continue;

I didn't find such a flag and it seems that valid_lft contains the
lifetime in seconds, so I think it's not that simple. The addrconf.c
code does something like this:

	unsigned long age = (jiffies - ifp->tstamp) / HZ;
	if (age >= ifp->valid_lft) {
		/* not valid */
	}

The code also sets the deprecated flag when the preferred lifetime
expires and I think valid_lft must be less or equal to prefered_lft. If
this is the case then I think this case should be already covered by
checking for IFA_F_DEPRECATED above.

--KK



^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH 4/9] tproxy: added tproxy sockopt interface in the IPV6 layer
  2010-10-21  8:46     ` KOVACS Krisztian
@ 2010-10-21 21:09       ` YOSHIFUJI Hideaki
  0 siblings, 0 replies; 27+ messages in thread
From: YOSHIFUJI Hideaki @ 2010-10-21 21:09 UTC (permalink / raw)
  To: KOVACS Krisztian
  Cc: Jan Engelhardt, netdev, netfilter-devel, Patrick McHardy,
	David Miller, yoshfuji

On 2010-10-21, KOVACS Krisztian wrote:
> Hi,
> 
> On Thu, 2010-10-21 at 10:39 +0200, Jan Engelhardt wrote:
> > On Wednesday 2010-10-20 13:21, KOVACS Krisztian wrote:
> > 
> > >@@ -268,6 +268,10 @@ struct in6_flowlabel_req {
> > > /* RFC5082: Generalized Ttl Security Mechanism */
> > > #define IPV6_MINHOPCOUNT		73
> > > 
> > >+#define IPV6_ORIGDSTADDR        74
> > >+#define IPV6_RECVORIGDSTADDR    IPV6_ORIGDSTADDR
> > >+#define IPV6_TRANSPARENT        75
> > >+
> > 
> > Why do we actually need two names for the same thing?
> 
> IPV6_RECVORIGDSTADDR is the name of the socket option you're supposed to
> set if you require the original destination address. IPV6_ORIGDSTADDR is
> the name of the ancillary message you get with the actual address in it.
> Just like we have it for IP_TOS/IP_RECVTOS, for example.

I agree.

--yoshfuji


^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH 5/9] tproxy: allow non-local binds of IPv6 sockets if IP_TRANSPARENT is enabled
  2010-10-20 14:07     ` Balazs Scheidler
@ 2010-10-21 21:24       ` YOSHIFUJI Hideaki
  2010-10-23 14:48         ` Balazs Scheidler
  0 siblings, 1 reply; 27+ messages in thread
From: YOSHIFUJI Hideaki @ 2010-10-21 21:24 UTC (permalink / raw)
  To: Balazs Scheidler
  Cc: KOVACS Krisztian, netdev, netfilter-devel, Patrick McHardy,
	David Miller, yoshfuji

Hello.

2010-10-20, Balazs Scheidler wrote:
> On Wed, 2010-10-20 at 21:45 +0900, YOSHIFUJI Hideaki wrote:
> > (2010/10/20 20:21), KOVACS Krisztian wrote:
> > > From: Balazs Scheidler<bazsi@balabit.hu>
> > > 
> > > Signed-off-by: Balazs Scheidler<bazsi@balabit.hu>
> > > Signed-off-by: KOVACS Krisztian<hidden@balabit.hu>
> > > ---
> > >   net/ipv6/af_inet6.c |    2 +-
> > >   1 files changed, 1 insertions(+), 1 deletions(-)
> > > 
> > > diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c
> > > index 6022098..9480572 100644
> > > --- a/net/ipv6/af_inet6.c
> > > +++ b/net/ipv6/af_inet6.c
> > > @@ -343,7 +343,7 @@ int inet6_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
> > >   			 */
> > >   			v4addr = LOOPBACK4_IPV6;
> > >   			if (!(addr_type&  IPV6_ADDR_MULTICAST))	{
> > > -				if (!ipv6_chk_addr(net,&addr->sin6_addr,
> > > +				if (!inet->transparent&&  !ipv6_chk_addr(net,&addr->sin6_addr,
> > >   						   dev, 0)) {
> > >   					err = -EADDRNOTAVAIL;
> > >   					goto out_unlock;
> > > 
> > > 
> > 
> > As I wrote before in other thread, this does not seem sufficient --
> > well, it is sufficient to allow non-local bind, but before we're
> > allowing this, we need add checks of source address in sending side.
> 
> Can you please elaborate or point us to the other thread? Is it some
> kind of address-type check that we miss?

Please see my comment at:
<http://kerneltrap.org/mailarchive/linux-netdev/2010/7/5/6280572>

This will result in allowing non-privileged users easily sending from
non-local / unauthorized address, which is not good, and which should
not be allowed from security aspects.

Regards,

--yoshfuji


^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH 5/9] tproxy: allow non-local binds of IPv6 sockets if IP_TRANSPARENT is enabled
  2010-10-21 21:24       ` YOSHIFUJI Hideaki
@ 2010-10-23 14:48         ` Balazs Scheidler
  2010-10-24  5:03           ` YOSHIFUJI Hideaki
  2010-10-24 23:08           ` David Miller
  0 siblings, 2 replies; 27+ messages in thread
From: Balazs Scheidler @ 2010-10-23 14:48 UTC (permalink / raw)
  To: YOSHIFUJI Hideaki
  Cc: KOVACS Krisztian, netdev, netfilter-devel, Patrick McHardy, David Miller

On Fri, 2010-10-22 at 06:24 +0900, YOSHIFUJI Hideaki wrote:
> Hello.
> 
> 2010-10-20, Balazs Scheidler wrote:
> > On Wed, 2010-10-20 at 21:45 +0900, YOSHIFUJI Hideaki wrote:
> > > (2010/10/20 20:21), KOVACS Krisztian wrote:
> > > > From: Balazs Scheidler<bazsi@balabit.hu>
> > > > 
> > > > Signed-off-by: Balazs Scheidler<bazsi@balabit.hu>
> > > > Signed-off-by: KOVACS Krisztian<hidden@balabit.hu>
> > > > ---
> > > >   net/ipv6/af_inet6.c |    2 +-
> > > >   1 files changed, 1 insertions(+), 1 deletions(-)
> > > > 
> > > > diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c
> > > > index 6022098..9480572 100644
> > > > --- a/net/ipv6/af_inet6.c
> > > > +++ b/net/ipv6/af_inet6.c
> > > > @@ -343,7 +343,7 @@ int inet6_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
> > > >   			 */
> > > >   			v4addr = LOOPBACK4_IPV6;
> > > >   			if (!(addr_type&  IPV6_ADDR_MULTICAST))	{
> > > > -				if (!ipv6_chk_addr(net,&addr->sin6_addr,
> > > > +				if (!inet->transparent&&  !ipv6_chk_addr(net,&addr->sin6_addr,
> > > >   						   dev, 0)) {
> > > >   					err = -EADDRNOTAVAIL;
> > > >   					goto out_unlock;
> > > > 
> > > > 
> > > 
> > > As I wrote before in other thread, this does not seem sufficient --
> > > well, it is sufficient to allow non-local bind, but before we're
> > > allowing this, we need add checks of source address in sending side.
> > 
> > Can you please elaborate or point us to the other thread? Is it some
> > kind of address-type check that we miss?
> 
> Please see my comment at:
> <http://kerneltrap.org/mailarchive/linux-netdev/2010/7/5/6280572>
> 
> This will result in allowing non-privileged users easily sending from
> non-local / unauthorized address, which is not good, and which should
> not be allowed from security aspects.

IP_TRANSPARENT requires root (more precisely CAP_NET_ADMIN privielges)
for IPV6.

However as I see right now this check was missed from the IPv6
implementation.

Is that enough as a safeguard? e.g. something like this:

diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c
index 0553867..f683d2c 100644
--- a/net/ipv6/ipv6_sockglue.c
+++ b/net/ipv6/ipv6_sockglue.c
@@ -343,6 +343,10 @@ static int do_ipv6_setsockopt(struct sock *sk, int level, int optname,
                break;
 
        case IPV6_TRANSPARENT:
+                if (!capable(CAP_NET_ADMIN)) {
+                        retv = -EPERM;
+                        break;
+                }
                if (optlen < sizeof(int))
                        goto e_inval;
                /* we don't have a separate transparent bit for IPV6 we use the one in the IPv4 socket */



-- 
Bazsi



^ permalink raw reply related	[flat|nested] 27+ messages in thread

* Re: [PATCH 5/9] tproxy: allow non-local binds of IPv6 sockets if IP_TRANSPARENT is enabled
  2010-10-23 14:48         ` Balazs Scheidler
@ 2010-10-24  5:03           ` YOSHIFUJI Hideaki
  2010-10-24 23:08           ` David Miller
  1 sibling, 0 replies; 27+ messages in thread
From: YOSHIFUJI Hideaki @ 2010-10-24  5:03 UTC (permalink / raw)
  To: Balazs Scheidler
  Cc: KOVACS Krisztian, netdev, netfilter-devel, Patrick McHardy,
	David Miller, yoshfuji

On 2010-10-23, Balazs Scheidler wrote:
> On Fri, 2010-10-22 at 06:24 +0900, YOSHIFUJI Hideaki wrote:
> > Hello.
> > 
> > 2010-10-20, Balazs Scheidler wrote:
> > > On Wed, 2010-10-20 at 21:45 +0900, YOSHIFUJI Hideaki wrote:
> > > > (2010/10/20 20:21), KOVACS Krisztian wrote:
> > > > > From: Balazs Scheidler<bazsi@balabit.hu>
> > > > > 
> > > > > Signed-off-by: Balazs Scheidler<bazsi@balabit.hu>
> > > > > Signed-off-by: KOVACS Krisztian<hidden@balabit.hu>
> > > > > ---
> > > > >   net/ipv6/af_inet6.c |    2 +-
> > > > >   1 files changed, 1 insertions(+), 1 deletions(-)
> > > > > 
> > > > > diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c
> > > > > index 6022098..9480572 100644
> > > > > --- a/net/ipv6/af_inet6.c
> > > > > +++ b/net/ipv6/af_inet6.c
> > > > > @@ -343,7 +343,7 @@ int inet6_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
> > > > >   			 */
> > > > >   			v4addr = LOOPBACK4_IPV6;
> > > > >   			if (!(addr_type&  IPV6_ADDR_MULTICAST))	{
> > > > > -				if (!ipv6_chk_addr(net,&addr->sin6_addr,
> > > > > +				if (!inet->transparent&&  !ipv6_chk_addr(net,&addr->sin6_addr,
> > > > >   						   dev, 0)) {
> > > > >   					err = -EADDRNOTAVAIL;
> > > > >   					goto out_unlock;
> > > > > 
> > > > > 
> > > > 
> > > > As I wrote before in other thread, this does not seem sufficient --
> > > > well, it is sufficient to allow non-local bind, but before we're
> > > > allowing this, we need add checks of source address in sending side.
> > > 
> > > Can you please elaborate or point us to the other thread? Is it some
> > > kind of address-type check that we miss?
> > 
> > Please see my comment at:
> > <http://kerneltrap.org/mailarchive/linux-netdev/2010/7/5/6280572>
> > 
> > This will result in allowing non-privileged users easily sending from
> > non-local / unauthorized address, which is not good, and which should
> > not be allowed from security aspects.
> 
> IP_TRANSPARENT requires root (more precisely CAP_NET_ADMIN privielges)
> for IPV6.
> 
> However as I see right now this check was missed from the IPv6
> implementation.
> 
> Is that enough as a safeguard? e.g. something like this:
> 
> diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c
> index 0553867..f683d2c 100644
> --- a/net/ipv6/ipv6_sockglue.c
> +++ b/net/ipv6/ipv6_sockglue.c
> @@ -343,6 +343,10 @@ static int do_ipv6_setsockopt(struct sock *sk, int level, int optname,
>                 break;
>  
>         case IPV6_TRANSPARENT:
> +                if (!capable(CAP_NET_ADMIN)) {
> +                        retv = -EPERM;
> +                        break;
> +                }
>                 if (optlen < sizeof(int))
>                         goto e_inval;
>                 /* we don't have a separate transparent bit for IPV6 we use the one in the IPv4 socket */
> 
> 
> 

I think it is the thing we must to have.  Thanks.

Acked-by: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>

--yoshfuji


^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH 5/9] tproxy: allow non-local binds of IPv6 sockets if IP_TRANSPARENT is enabled
  2010-10-23 14:48         ` Balazs Scheidler
  2010-10-24  5:03           ` YOSHIFUJI Hideaki
@ 2010-10-24 23:08           ` David Miller
  1 sibling, 0 replies; 27+ messages in thread
From: David Miller @ 2010-10-24 23:08 UTC (permalink / raw)
  To: bazsi; +Cc: yoshfuji, hidden, netdev, netfilter-devel, kaber

From: Balazs Scheidler <bazsi@balabit.hu>
Date: Sat, 23 Oct 2010 16:48:14 +0200

> IP_TRANSPARENT requires root (more precisely CAP_NET_ADMIN privielges)
> for IPV6.
> 
> However as I see right now this check was missed from the IPv6
> implementation.
> 
> Is that enough as a safeguard? e.g. something like this:

Applied, thanks everyone.

^ permalink raw reply	[flat|nested] 27+ messages in thread

end of thread, other threads:[~2010-10-24 23:08 UTC | newest]

Thread overview: 27+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-10-20 11:21 [PATCH 0/9] tproxy: add IPv6 support KOVACS Krisztian
2010-10-20 11:21 ` [PATCH 1/9] tproxy: split off ipv6 defragmentation to a separate module KOVACS Krisztian
2010-10-20 11:21 ` [PATCH 8/9] tproxy: added IPv6 support to the socket match KOVACS Krisztian
2010-10-20 11:21 ` [PATCH 9/9] tproxy: use the interface primary IP address as a default value for --on-ip KOVACS Krisztian
2010-10-21  9:12   ` Jan Engelhardt
2010-10-21 10:32     ` KOVACS Krisztian
2010-10-20 11:21 ` [PATCH 4/9] tproxy: added tproxy sockopt interface in the IPV6 layer KOVACS Krisztian
2010-10-21  8:39   ` Jan Engelhardt
2010-10-21  8:46     ` KOVACS Krisztian
2010-10-21 21:09       ` YOSHIFUJI Hideaki
2010-10-20 11:21 ` [PATCH 6/9] tproxy: added IPv6 socket lookup function to nf_tproxy_core KOVACS Krisztian
2010-10-21  8:42   ` Jan Engelhardt
2010-10-21  9:48     ` KOVACS Krisztian
2010-10-20 11:21 ` [PATCH 7/9] tproxy: added IPv6 support to the TPROXY target KOVACS Krisztian
2010-10-21  8:47   ` Jan Engelhardt
2010-10-21  8:50     ` KOVACS Krisztian
2010-10-21  9:14       ` Jan Engelhardt
2010-10-21  9:33         ` KOVACS Krisztian
2010-10-20 11:21 ` [PATCH 5/9] tproxy: allow non-local binds of IPv6 sockets if IP_TRANSPARENT is enabled KOVACS Krisztian
2010-10-20 12:45   ` YOSHIFUJI Hideaki
2010-10-20 14:07     ` Balazs Scheidler
2010-10-21 21:24       ` YOSHIFUJI Hideaki
2010-10-23 14:48         ` Balazs Scheidler
2010-10-24  5:03           ` YOSHIFUJI Hideaki
2010-10-24 23:08           ` David Miller
2010-10-20 11:21 ` [PATCH 2/9] tproxy: added const specifiers to udp lookup functions KOVACS Krisztian
2010-10-20 11:21 ` [PATCH 3/9] tproxy: added udp6_lib_lookup function KOVACS Krisztian

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.