SOURCES (LINUX_2_6): kernel-ipvs-nfct.patch (NEW) - http://www.ssi...

zbyniu zbyniu at pld-linux.org
Mon Jan 28 00:16:32 CET 2008


Author: zbyniu                       Date: Sun Jan 27 23:16:32 2008 GMT
Module: SOURCES                       Tag: LINUX_2_6
---- Log message:
- http://www.ssi.bg/~ja/nfct/ipvs-nfct-2.6.24-1.diff

---- Files affected:
SOURCES:
   kernel-ipvs-nfct.patch (NONE -> 1.1.4.2)  (NEW)

---- Diffs:

================================================================
Index: SOURCES/kernel-ipvs-nfct.patch
diff -u /dev/null SOURCES/kernel-ipvs-nfct.patch:1.1.4.2
--- /dev/null	Mon Jan 28 00:16:32 2008
+++ SOURCES/kernel-ipvs-nfct.patch	Mon Jan 28 00:16:27 2008
@@ -0,0 +1,753 @@
+diff -urNp v2.6.24/linux/include/net/ip_vs.h linux/include/net/ip_vs.h
+--- v2.6.24/linux/include/net/ip_vs.h	2008-01-25 10:45:05.000000000 +0200
++++ linux/include/net/ip_vs.h	2008-01-27 17:46:03.000000000 +0200
+@@ -9,6 +9,16 @@
+ #include <asm/types.h>		/* For __uXX types */
+ #include <linux/types.h>	/* For __beXX types in userland */
+ 
++#ifdef __KERNEL__
++#include <linux/skbuff.h>
++#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
++#include <net/netfilter/nf_conntrack.h>
++#include <net/netfilter/nf_conntrack_core.h>
++#include <net/netfilter/nf_conntrack_expect.h>
++#include <net/netfilter/nf_conntrack_helper.h>
++#endif
++#endif
++
+ #define IP_VS_VERSION_CODE	0x010201
+ #define NVERSION(version)			\
+ 	(version >> 16) & 0xFF,			\
+@@ -685,6 +695,16 @@ extern void ip_vs_init_hash_table(struct
+  */
+ 
+ /*
++ *      Netfilter connection tracking
++ *      (from ip_vs_nfct.c)
++ */
++extern int ip_vs_nfct_confirm(struct sk_buff *skb, struct ip_vs_conn *cp, unsigned int hooknum);
++extern void ip_vs_nfct_expect_related(struct sk_buff *skb,
++				      struct ip_vs_conn *cp,
++				      __be16 port, __u16 proto, int from_rs);
++extern void ip_vs_nfct_conn_drop(struct ip_vs_conn *cp);
++
++/*
+  *     IPVS connection entry hash table
+  */
+ #ifndef CONFIG_IP_VS_TAB_BITS
+@@ -855,8 +875,41 @@ extern int sysctl_ip_vs_expire_nodest_co
+ extern int sysctl_ip_vs_expire_quiescent_template;
+ extern int sysctl_ip_vs_sync_threshold[2];
+ extern int sysctl_ip_vs_nat_icmp_send;
++extern int sysctl_ip_vs_snat_reroute;
+ extern struct ip_vs_stats ip_vs_stats;
+ 
++#ifdef CONFIG_IP_VS_NFCT
++
++extern int sysctl_ip_vs_conntrack;
++
++static inline int ip_vs_use_conntrack(struct sk_buff *skb)
++{
++	return sysctl_ip_vs_conntrack && skb->nfct;
++}
++
++/* Returns boolean and skb is freed on failure */
++static inline int ip_vs_confirm_conntrack(struct sk_buff *skb, struct ip_vs_conn *cp, unsigned int hooknum)
++{
++	if (!ip_vs_use_conntrack(skb))
++		return 1;
++	return nf_ct_is_confirmed((struct nf_conn *) skb->nfct) ||
++		ip_vs_nfct_confirm(skb, cp, hooknum);
++}
++
++#else
++
++static inline int ip_vs_use_conntrack(struct sk_buff *skb)
++{
++	return 0;
++}
++
++static inline int ip_vs_confirm_conntrack(struct sk_buff *skb, struct ip_vs_conn *cp, unsigned int hooknum)
++{
++	return 1;
++}
++
++#endif
++
+ extern struct ip_vs_service *
+ ip_vs_service_get(__u32 fwmark, __u16 protocol, __be32 vaddr, __be16 vport);
+ 
+diff -urNp v2.6.24/linux/net/ipv4/ipvs/Kconfig linux/net/ipv4/ipvs/Kconfig
+--- v2.6.24/linux/net/ipv4/ipvs/Kconfig	2007-07-10 09:18:43.000000000 +0300
++++ linux/net/ipv4/ipvs/Kconfig	2008-01-27 17:46:03.000000000 +0200
+@@ -221,4 +221,12 @@ config	IP_VS_FTP
+ 	  If you want to compile it in kernel, say Y. To compile it as a
+ 	  module, choose M here. If unsure, say N.
+ 
++config	IP_VS_NFCT
++	bool "Netfilter connection tracking"
++	depends on NF_CONNTRACK
++	---help---
++	  The Netfilter connection tracking support allows the IPVS
++	  connection state to be exported to the Netfilter framework
++	  for filtering purposes.
++
+ endif # IP_VS
+diff -urNp v2.6.24/linux/net/ipv4/ipvs/Makefile linux/net/ipv4/ipvs/Makefile
+--- v2.6.24/linux/net/ipv4/ipvs/Makefile	2005-06-18 08:50:52.000000000 +0300
++++ linux/net/ipv4/ipvs/Makefile	2008-01-27 17:46:03.000000000 +0200
+@@ -9,10 +9,13 @@ ip_vs_proto-objs-$(CONFIG_IP_VS_PROTO_UD
+ ip_vs_proto-objs-$(CONFIG_IP_VS_PROTO_ESP) += ip_vs_proto_esp.o
+ ip_vs_proto-objs-$(CONFIG_IP_VS_PROTO_AH) += ip_vs_proto_ah.o
+ 
++ip_vs-extra_objs-y :=
++ip_vs-extra_objs-$(CONFIG_IP_VS_NFCT) += ip_vs_nfct.o
++
+ ip_vs-objs :=	ip_vs_conn.o ip_vs_core.o ip_vs_ctl.o ip_vs_sched.o	   \
+ 		ip_vs_xmit.o ip_vs_app.o ip_vs_sync.o	   		   \
+ 		ip_vs_est.o ip_vs_proto.o 				   \
+-		$(ip_vs_proto-objs-y)
++		$(ip_vs_proto-objs-y) $(ip_vs-extra_objs-y)
+ 
+ 
+ # IPVS core
+diff -urNp v2.6.24/linux/net/ipv4/ipvs/ip_vs_conn.c linux/net/ipv4/ipvs/ip_vs_conn.c
+--- v2.6.24/linux/net/ipv4/ipvs/ip_vs_conn.c	2008-01-25 10:45:06.000000000 +0200
++++ linux/net/ipv4/ipvs/ip_vs_conn.c	2008-01-27 17:46:03.000000000 +0200
+@@ -581,6 +581,11 @@ static void ip_vs_conn_expire(unsigned l
+ 		if (cp->control)
+ 			ip_vs_control_del(cp);
+ 
++#ifdef CONFIG_IP_VS_NFCT
++		if (sysctl_ip_vs_conntrack)
++			ip_vs_nfct_conn_drop(cp);
++#endif
++
+ 		if (unlikely(cp->app != NULL))
+ 			ip_vs_unbind_app(cp);
+ 		ip_vs_unbind_dest(cp);
+diff -urNp v2.6.24/linux/net/ipv4/ipvs/ip_vs_core.c linux/net/ipv4/ipvs/ip_vs_core.c
+--- v2.6.24/linux/net/ipv4/ipvs/ip_vs_core.c	2008-01-25 10:45:06.000000000 +0200
++++ linux/net/ipv4/ipvs/ip_vs_core.c	2008-01-27 17:56:11.000000000 +0200
+@@ -661,6 +661,8 @@ static int ip_vs_out_icmp(struct sk_buff
+ 
+ 	skb->ipvs_property = 1;
+ 	verdict = NF_ACCEPT;
++	if (sysctl_ip_vs_snat_reroute && ip_route_me_harder(skb, RTN_LOCAL))
++		verdict = NF_DROP;
+ 
+   out:
+ 	__ip_vs_conn_put(cp);
+@@ -761,19 +763,31 @@ ip_vs_out(unsigned int hooknum, struct s
+ 	if (!skb_make_writable(skb, ihl))
+ 		goto drop;
+ 
++	if (!ip_vs_confirm_conntrack(skb, cp, hooknum))
++		goto out;
++
+ 	/* mangle the packet */
+ 	if (pp->snat_handler && !pp->snat_handler(skb, pp, cp))
+ 		goto drop;
+ 	ip_hdr(skb)->saddr = cp->vaddr;
+ 	ip_send_check(ip_hdr(skb));
+ 
++	/*
++	 * nf_iterate does not expect change in the skb->dst->dev.
++	 * It looks like it is not fatal to enable this code for hooks
++	 * where our handlers are at the end of the chain list and
++	 * when all next handlers use skb->dst->dev and not outdev.
++	 * It will definitely route properly the inout NAT traffic
++	 * when multiple paths are used.
++	 */
++
+ 	/* For policy routing, packets originating from this
+ 	 * machine itself may be routed differently to packets
+ 	 * passing through.  We want this packet to be routed as
+ 	 * if it came from this machine itself.  So re-compute
+ 	 * the routing information.
+ 	 */
+-	if (ip_route_me_harder(skb, RTN_LOCAL) != 0)
++	if (sysctl_ip_vs_snat_reroute && ip_route_me_harder(skb, RTN_LOCAL) != 0)
+ 		goto drop;
+ 
+ 	IP_VS_DBG_PKT(10, pp, skb, 0, "After SNAT");
+@@ -788,8 +802,11 @@ ip_vs_out(unsigned int hooknum, struct s
+ 	return NF_ACCEPT;
+ 
+   drop:
+-	ip_vs_conn_put(cp);
+ 	kfree_skb(skb);
++
++  out:
++	ip_vs_conn_put(cp);
++	LeaveFunction(11);
+ 	return NF_STOLEN;
+ }
+ 
+diff -urNp v2.6.24/linux/net/ipv4/ipvs/ip_vs_ctl.c linux/net/ipv4/ipvs/ip_vs_ctl.c
+--- v2.6.24/linux/net/ipv4/ipvs/ip_vs_ctl.c	2008-01-25 10:45:06.000000000 +0200
++++ linux/net/ipv4/ipvs/ip_vs_ctl.c	2008-01-27 17:53:38.000000000 +0200
+@@ -81,6 +81,10 @@ int sysctl_ip_vs_expire_nodest_conn = 0;
+ int sysctl_ip_vs_expire_quiescent_template = 0;
+ int sysctl_ip_vs_sync_threshold[2] = { 3, 50 };
+ int sysctl_ip_vs_nat_icmp_send = 0;
++int sysctl_ip_vs_snat_reroute = 0;
++#ifdef CONFIG_IP_VS_NFCT
++int sysctl_ip_vs_conntrack = 0;
++#endif
+ 
+ 
+ #ifdef CONFIG_IP_VS_DEBUG
+@@ -1446,6 +1450,15 @@ static struct ctl_table vs_vars[] = {
+ 		.mode		= 0644,
+ 		.proc_handler	= &proc_dointvec,
+ 	},
++#ifdef CONFIG_IP_VS_NFCT
++	{
++		.procname	= "conntrack",
++		.data		= &sysctl_ip_vs_conntrack,
++		.maxlen		= sizeof(int),
++		.mode		= 0644,
++		.proc_handler	= &proc_dointvec,
++	},
++#endif
+ 	{
+ 		.procname	= "drop_entry",
+ 		.data		= &sysctl_ip_vs_drop_entry,
+@@ -1467,6 +1480,13 @@ static struct ctl_table vs_vars[] = {
+ 		.mode		= 0644,
+ 		.proc_handler	= &proc_do_defense_mode,
+ 	},
++	{
++		.procname	= "snat_reroute",
++		.data		= &sysctl_ip_vs_snat_reroute,
++		.maxlen		= sizeof(int),
++		.mode		= 0644,
++		.proc_handler	= &proc_dointvec,
++	},
+ #if 0
+ 	{
+ 		.procname	= "timeout_established",
+diff -urNp v2.6.24/linux/net/ipv4/ipvs/ip_vs_ftp.c linux/net/ipv4/ipvs/ip_vs_ftp.c
+--- v2.6.24/linux/net/ipv4/ipvs/ip_vs_ftp.c	2008-01-25 10:45:06.000000000 +0200
++++ linux/net/ipv4/ipvs/ip_vs_ftp.c	2008-01-27 17:55:29.000000000 +0200
+@@ -195,6 +195,11 @@ static int ip_vs_ftp_out(struct ip_vs_ap
+ 			ip_vs_control_add(n_cp, cp);
+ 		}
+ 
++#ifdef CONFIG_IP_VS_NFCT
++		if (skb->nfct)
++			ip_vs_nfct_expect_related(skb, n_cp, 0, IPPROTO_TCP, 0);
++#endif
++
+ 		/*
+ 		 * Replace the old passive address with the new one
+ 		 */
+@@ -327,6 +332,11 @@ static int ip_vs_ftp_in(struct ip_vs_app
+ 		ip_vs_control_add(n_cp, cp);
+ 	}
+ 
++#ifdef CONFIG_IP_VS_NFCT
++	if (skb->nfct)
++		ip_vs_nfct_expect_related(skb, n_cp, n_cp->dport, IPPROTO_TCP, 1);
++#endif
++
+ 	/*
+ 	 *	Move tunnel to listen state
+ 	 */
+diff -urNp v2.6.24/linux/net/ipv4/ipvs/ip_vs_nfct.c linux/net/ipv4/ipvs/ip_vs_nfct.c
+--- v2.6.24/linux/net/ipv4/ipvs/ip_vs_nfct.c	1970-01-01 02:00:00.000000000 +0200
++++ linux/net/ipv4/ipvs/ip_vs_nfct.c	2008-01-27 18:24:09.000000000 +0200
+@@ -0,0 +1,385 @@
++/*
++ * ip_vs_nfct.c:	Netfilter connection tracking support for IPVS
++ *
++ * Portions Copyright (C) 2001-2002
++ * Antefacto Ltd, 181 Parnell St, Dublin 1, Ireland.
++ *
++ * Portions Copyright (C) 2003-2008
++ * Julian Anastasov
++ *
++ *
++ * This code is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
++ *
++ *
++ * Authors:
++ * Ben North <ben at redfrontdoor.org>
++ * Julian Anastasov <ja at ssi.bg>		Reorganize and sync with latest kernels
++ *
++ *
++ * Current status:
++ *
++ * - provide conntrack confirmation for new and related connections, by
++ * this way we can see their proper conntrack state in all hooks
++ * - support for all forwarding methods, not only NAT
++ * - FTP support (NAT), ability to support other NAT apps with expectations
++ * - to correctly create expectations for related NAT connections the proper
++ * NF conntrack support must be already installed, eg. ip_vs_ftp requires
++ * nf_conntrack_ftp for the same ports
++ *
++ */
++
++#include <linux/module.h>
++#include <linux/types.h>
++#include <linux/kernel.h>
++#include <linux/errno.h>
++#include <linux/compiler.h>
++#include <linux/vmalloc.h>
++#include <linux/skbuff.h>
++#include <net/ip.h>
++#include <linux/netfilter.h>
++#include <linux/netfilter_ipv4.h>
++#include <net/ip_vs.h>
++
++
++EXPORT_SYMBOL(ip_vs_nfct_expect_related);
++
++
++#define FMT_TUPLE	"%u.%u.%u.%u:%u->%u.%u.%u.%u:%u/%u"
++#define ARG_TUPLE(t)	NIPQUAD((t)->src.u3.ip), ntohs((t)->src.u.all), \
++			NIPQUAD((t)->dst.u3.ip), ntohs((t)->dst.u.all), \
++			(t)->dst.protonum
++
++#define FMT_CONN	"%u.%u.%u.%u:%u->%u.%u.%u.%u:%u->%u.%u.%u.%u:%u/%u:%u"
++#define ARG_CONN(c)	NIPQUAD((c)->caddr), ntohs((c)->cport), \
++			NIPQUAD((c)->vaddr), ntohs((c)->vport), \
++			NIPQUAD((c)->daddr), ntohs((c)->dport), \
++			(c)->protocol, (c)->state
++
++/* Returns boolean and skb is freed on failure */
++static int __ip_vs_nfct_confirm(struct sk_buff *skb, struct ip_vs_conn *cp,
++				unsigned int hooknum)
++{
++	/*
++	 * The assumptions:
++	 * - the nfct is !NULL and is not confirmed
++	 * - we are called before any mangle
++	 */
++
++	struct iphdr *iph = ip_hdr(skb);
++	struct nf_conn *ct = (struct nf_conn *) skb->nfct;
++	struct nf_conntrack_tuple new_reply;
++	int ret = NF_DROP;
++	__be16 _ports[2], *pptr;
++#ifdef CONFIG_IP_VS_DEBUG
++	struct nf_conntrack_tuple *orig_tup =
++		&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple;
++	struct nf_conntrack_tuple *orig_rep =
++		&ct->tuplehash[IP_CT_DIR_REPLY].tuple;
++#endif
++#ifdef CONFIG_NF_NAT_NEEDED
++	int initialized = !!(ct->status & IPS_NAT_DONE_MASK);
++#else
++	int initialized = 0;
++#endif
++
++	IP_VS_DBG(7, "%s: ct=%p, init=%d, tuples=" FMT_TUPLE ", " FMT_TUPLE
++		", cp=" FMT_CONN "\n",
++		__FUNCTION__, ct, initialized,
++		ARG_TUPLE(orig_tup), ARG_TUPLE(orig_rep), ARG_CONN(cp));
++
++#ifdef CONFIG_NF_NAT_NEEDED
++	/*
++	 * This is really bad, may be we are trying to alter DNAT conn?
++	 * This is not supported, avoid the confirmation.
++	 */
++	if (initialized && ct->status & IPS_NAT_MASK) {
++#ifdef CONFIG_IP_VS_DEBUG
++		IP_VS_DBG(7, "%s: ct=%p, status=0x%lX, init=%d\n",
++			__FUNCTION__, ct, ct->status, initialized);
++#endif
++		return 1;
++	}
++#endif
++
++	if (IP_VS_FWD_METHOD(cp) != IP_VS_CONN_F_MASQ || NF_IP_FORWARD == hooknum)
++		goto confirm;
++
++	/*
++	 * Alter reply only for IP_VS_CONN_F_MASQ in outin direction.
++	 * For related connections in inout direction it is done in
++	 * expectfn callback.
++	 */
++
++	pptr = skb_header_pointer(skb, ip_hdrlen(skb),
++				  sizeof(_ports), _ports);
++	if (!pptr)
++		goto out;
++
++	new_reply = (struct nf_conntrack_tuple) {
++		.dst = { .protonum = iph->protocol, .dir = IP_CT_DIR_REPLY }};
++
++	new_reply.src.u3.ip = cp->daddr;
++	new_reply.src.u.tcp.port = cp->dport;
++	new_reply.src.l3num = PF_INET;
++	new_reply.dst.u3.ip = iph->saddr;
++	new_reply.dst.u.tcp.port = pptr[0];
++
++	nf_conntrack_alter_reply(ct, &new_reply);
++
++	IP_VS_DBG(7, "%s: ct=%p, init=%d, orig=" FMT_TUPLE
++		", new_reply=" FMT_TUPLE " => alter_reply\n",
++		__FUNCTION__, ct, initialized,
++		ARG_TUPLE(orig_tup), ARG_TUPLE(&new_reply));
++
++	/*
++	 * No need to rehash NAT info because we don't change source
++	 * address in original direction
++	 */
++
++confirm:
++
++	ret = __nf_conntrack_confirm(skb);
++
++	if (ret != NF_STOLEN) {
++		IP_VS_DBG(7, "%s: ct=%p, init=%d, orig=" FMT_TUPLE " => confirm ret=%d\n",
++			__FUNCTION__, ct, initialized, ARG_TUPLE(orig_tup), ret);
++	}
++
++	if (ret != NF_ACCEPT)
++		goto out;
++	return 1;
++
++out:
++	if (ret != NF_STOLEN)
++		kfree_skb(skb);
++	return 0;
++}
++
++/*
++ * Confirm (and optionally alter) the conntrack entry if needed
++ * because the IPVS packets do not reach ipv4_confirm.
++ */
++int ip_vs_nfct_confirm(struct sk_buff *skb, struct ip_vs_conn *cp,
++		       unsigned int hooknum)
++{
++	struct iphdr *iph = ip_hdr(skb);
++	struct nf_conn *ct = (struct nf_conn *) skb->nfct;
++
++	/* By the time we're sending the packet out the other
++	 * side, there should be a confirmed Netfilter CT entry
++	 * for this connection.  This may not be the case,
++	 * however, if it's a brand new connection, or if the NF
++	 * entry has timed out before ours has.  Either way, if
++	 * the NF CT entry is unconfirmed, confirm it, and deal
++	 * with reply tuple mangling at the same time.
++	 */
++
++	/* We only deal with TCP or UDP packets */
++	if (iph->protocol != IPPROTO_TCP && iph->protocol != IPPROTO_UDP)
++		return 1;
++
++	if (IP_VS_FWD_METHOD(cp) != IP_VS_CONN_F_MASQ) {
++		/*
++		 * Do not be surprised if non-NAT conntracks stay in SYN_SENT
++		 * state, may be the replies from the real server go
++		 * directly to client. In any case, keep them in REPLIED
++		 * state (ESTABLISHED).
++		 */
++		if (iph->protocol != IPPROTO_TCP ||
++		    IP_VS_TCP_S_ESTABLISHED == cp->state) {
++			set_bit(IPS_SEEN_REPLY_BIT, &ct->status);
++		}
++	}
++
++	/*
++	 * We assume the reused connections do not change their rip:rport
++	 * and we do not need to alter their conntrack reply
++	 */
++	return __ip_vs_nfct_confirm(skb, cp, hooknum);
++}
++
++/*
++ * We are called from init_conntrack() as expectfn handler
++ */
++
++static void ip_vs_nfct_expect_callback(struct nf_conn *ct,
++	struct nf_conntrack_expect *exp)
++{
++	struct nf_conntrack_tuple *orig, new_reply;
++	struct ip_vs_conn *cp;
++
++	if (exp->tuple.src.l3num != PF_INET)
++		return;
++
++	/* 
++	 * - We assume that no NF locks are held before this callback
++	 * - ip_vs_conn_out_get and ip_vs_conn_in_get should match their
++	 * expectations even if they use wildcard values, now we provide
++	 * the actual values from the newly created original conntrack direction
++	 * - the conntrack is confirmed when packet reaches IPVS hooks
++	 */
++
++	/* RS->CLIENT */
++	orig = &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple;
++	cp = ip_vs_conn_out_get(orig->dst.protonum,
++				orig->src.u3.ip, orig->src.u.tcp.port,
++				orig->dst.u3.ip, orig->dst.u.tcp.port);
++	if (cp) {
++		/* Change reply CLIENT->RS to CLIENT->VS */
++		new_reply = ct->tuplehash[IP_CT_DIR_REPLY].tuple;
++		IP_VS_DBG(7, "%s: ct=%p, status=0x%lX, tuples=" FMT_TUPLE ", " FMT_TUPLE
++			", found inout cp=" FMT_CONN "\n",
++			__FUNCTION__, ct, ct->status,
++			ARG_TUPLE(orig), ARG_TUPLE(&new_reply),
++			ARG_CONN(cp));
++		new_reply.dst.u3.ip = cp->vaddr;
++		new_reply.dst.u.tcp.port = cp->vport;
++		IP_VS_DBG(7, "%s: ct=%p, new tuples=" FMT_TUPLE ", " FMT_TUPLE
++			", inout cp=" FMT_CONN "\n",
++			__FUNCTION__, ct,
++			ARG_TUPLE(orig), ARG_TUPLE(&new_reply),
++			ARG_CONN(cp));
++		goto alter;
++	}
++
++	/* CLIENT->VS */
++	cp = ip_vs_conn_in_get(orig->dst.protonum,
++				orig->src.u3.ip, orig->src.u.tcp.port,
++				orig->dst.u3.ip, orig->dst.u.tcp.port);
++	if (cp) {
++		/* Change reply VS->CLIENT to RS->CLIENT */
++		new_reply = ct->tuplehash[IP_CT_DIR_REPLY].tuple;
++		IP_VS_DBG(7, "%s: ct=%p, status=0x%lX, tuples=" FMT_TUPLE ", " FMT_TUPLE
++			", found outin cp=" FMT_CONN "\n",
++			__FUNCTION__, ct, ct->status,
++			ARG_TUPLE(orig), ARG_TUPLE(&new_reply),
++			ARG_CONN(cp));
++		new_reply.src.u3.ip = cp->daddr;
++		new_reply.src.u.tcp.port = cp->dport;
++		IP_VS_DBG(7, "%s: ct=%p, new tuples=" FMT_TUPLE ", " FMT_TUPLE
++			", outin cp=" FMT_CONN "\n",
++			__FUNCTION__, ct,
++			ARG_TUPLE(orig), ARG_TUPLE(&new_reply),
++			ARG_CONN(cp));
++		goto alter;
++	}
++	IP_VS_DBG(7, "%s: ct=%p, status=0x%lX, tuple=" FMT_TUPLE " - unknown expect\n",
++		__FUNCTION__, ct, ct->status, ARG_TUPLE(orig));
++	return;
++
++alter:
++
++	/* Never alter conntrack for non-NAT conns */
++	if (IP_VS_FWD_METHOD(cp) == IP_VS_CONN_F_MASQ)
++		nf_conntrack_alter_reply(ct, &new_reply);
++	ip_vs_conn_put(cp);
++	return;
++}
++
++/*
++ * Create NF conntrack expectation with wildcard (optional) source port.
++ * Then the default callback function will alter the reply and will confirm
++ * the conntrack entry when the first packet comes.
++ */
++void ip_vs_nfct_expect_related(struct sk_buff *skb, struct ip_vs_conn *cp,
++			       __be16 port, __u16 proto, int from_rs)
++{
++	struct nf_conn *ct = (struct nf_conn *) skb->nfct;
++	struct nf_conntrack_expect *e;
++
++	if (!sysctl_ip_vs_conntrack)
++		return;
++
++	if (!ct) {
++		IP_VS_DBG(7, "%s: ct=%p for cp=" FMT_CONN "\n",
++			__FUNCTION__, ct, ARG_CONN(cp));
++		return;
++	}
++
++	if (!(e = nf_ct_expect_alloc(ct)))
++		return;
++
++	e->expectfn			= ip_vs_nfct_expect_callback;
++	e->helper			= NULL;
++	e->flags			= 0;
++	memset(&e->tuple, 0, sizeof(e->tuple));
++	e->tuple.src.u.tcp.port		= port;
++	e->tuple.src.l3num		= PF_INET;
++	e->tuple.dst.protonum		= proto;
++	memset(&e->mask, 0, sizeof(e->mask));
++	e->mask.src.u3.ip		= 0xffffffff;
++	e->mask.src.u.all		= port? 0xffff : 0;
++
++	if (from_rs) {
++		e->tuple.src.u3.ip = cp->daddr;
++		e->tuple.dst.u3.ip = cp->caddr;
++		e->tuple.dst.u.tcp.port = cp->cport;
++	} else {
++		e->tuple.src.u3.ip = cp->caddr;
<<Diff was trimmed, longer than 597 lines>>


More information about the pld-cvs-commit mailing list