Author: zbyniu                       Date: Wed Dec 12 12:22:36 2007 GMT
Module: SOURCES                       Tag: LINUX_2_6_22
---- Log message:
- support conntrack in ipvs

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

---- Diffs:

================================================================
Index: SOURCES/kernel-ipvs-nfct.patch
diff -u /dev/null SOURCES/kernel-ipvs-nfct.patch:1.1.2.1
--- /dev/null   Wed Dec 12 13:22:36 2007
+++ SOURCES/kernel-ipvs-nfct.patch      Wed Dec 12 13:22:30 2007
@@ -0,0 +1,762 @@
+diff -urNp v2.6.22/linux/include/net/ip_vs.h linux/include/net/ip_vs.h
+--- v2.6.22/linux/include/net/ip_vs.h  2007-02-11 01:06:29.000000000 +0200
++++ linux/include/net/ip_vs.h  2007-07-12 12:03:43.000000000 +0300
+@@ -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,                 \
+@@ -358,6 +368,8 @@ enum {
+       NET_IPV4_VS_SYNC_THRESHOLD=24,
+       NET_IPV4_VS_NAT_ICMP_SEND=25,
+       NET_IPV4_VS_EXPIRE_QUIESCENT_TEMPLATE=26,
++      NET_IPV4_VS_SNAT_REROUTE=27,
++      NET_IPV4_VS_CONNTRACK=28,
+       NET_IPV4_VS_LAST
+ };
+ 
+@@ -715,6 +727,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
+@@ -885,8 +907,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.22/linux/net/ipv4/ipvs/Kconfig linux/net/ipv4/ipvs/Kconfig
+--- v2.6.22/linux/net/ipv4/ipvs/Kconfig        2007-07-10 09:18:43.000000000 
+0300
++++ linux/net/ipv4/ipvs/Kconfig        2007-07-12 09:48:59.000000000 +0300
+@@ -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.22/linux/net/ipv4/ipvs/Makefile linux/net/ipv4/ipvs/Makefile
+--- v2.6.22/linux/net/ipv4/ipvs/Makefile       2005-06-18 08:50:52.000000000 
+0300
++++ linux/net/ipv4/ipvs/Makefile       2007-07-12 09:47:58.000000000 +0300
+@@ -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.22/linux/net/ipv4/ipvs/ip_vs_conn.c 
linux/net/ipv4/ipvs/ip_vs_conn.c
+--- v2.6.22/linux/net/ipv4/ipvs/ip_vs_conn.c   2007-04-28 17:55:11.000000000 
+0300
++++ linux/net/ipv4/ipvs/ip_vs_conn.c   2007-07-12 09:47:58.000000000 +0300
+@@ -562,6 +562,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.22/linux/net/ipv4/ipvs/ip_vs_core.c 
linux/net/ipv4/ipvs/ip_vs_core.c
+--- v2.6.22/linux/net/ipv4/ipvs/ip_vs_core.c   2007-07-10 09:18:43.000000000 
+0300
++++ linux/net/ipv4/ipvs/ip_vs_core.c   2007-07-12 09:47:58.000000000 +0300
+@@ -701,6 +701,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(pskb, RTN_LOCAL))
++              verdict = NF_DROP;
+ 
+   out:
+       __ip_vs_conn_put(cp);
+@@ -805,6 +807,9 @@ ip_vs_out(unsigned int hooknum, struct s
+       if (!ip_vs_make_skb_writable(pskb, ihl))
+               goto drop;
+ 
++      if (!ip_vs_confirm_conntrack(*pskb, cp, hooknum))
++              goto out;
++
+       /* mangle the packet */
+       if (pp->snat_handler && !pp->snat_handler(pskb, pp, cp))
+               goto drop;
+@@ -812,13 +817,23 @@ ip_vs_out(unsigned int hooknum, struct s
+       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(pskb, RTN_LOCAL) != 0)
++
++      if (sysctl_ip_vs_snat_reroute && ip_route_me_harder(pskb, RTN_LOCAL))
+               goto drop;
+       skb = *pskb;
+ 
+@@ -834,8 +849,11 @@ ip_vs_out(unsigned int hooknum, struct s
+       return NF_ACCEPT;
+ 
+   drop:
+-      ip_vs_conn_put(cp);
+       kfree_skb(*pskb);
++
++  out:
++      ip_vs_conn_put(cp);
++      LeaveFunction(11);
+       return NF_STOLEN;
+ }
+ 
+diff -urNp v2.6.22/linux/net/ipv4/ipvs/ip_vs_ctl.c 
linux/net/ipv4/ipvs/ip_vs_ctl.c
+--- v2.6.22/linux/net/ipv4/ipvs/ip_vs_ctl.c    2007-07-10 09:18:43.000000000 
+0300
++++ linux/net/ipv4/ipvs/ip_vs_ctl.c    2007-07-12 09:47:58.000000000 +0300
+@@ -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
+@@ -1424,6 +1428,16 @@ static struct ctl_table vs_vars[] = {
+               .mode           = 0644,
+               .proc_handler   = &proc_dointvec,
+       },
++#ifdef CONFIG_IP_VS_NFCT
++      {
++              .ctl_name       = NET_IPV4_VS_CONNTRACK,
++              .procname       = "conntrack",
++              .data           = &sysctl_ip_vs_conntrack,
++              .maxlen         = sizeof(int),
++              .mode           = 0644,
++              .proc_handler   = &proc_dointvec,
++      },
++#endif
+       {
+               .ctl_name       = NET_IPV4_VS_DROP_ENTRY,
+               .procname       = "drop_entry",
+@@ -1448,6 +1462,14 @@ static struct ctl_table vs_vars[] = {
+               .mode           = 0644,
+               .proc_handler   = &proc_do_defense_mode,
+       },
++      {
++              .ctl_name       = NET_IPV4_VS_SNAT_REROUTE,
++              .procname       = "snat_reroute",
++              .data           = &sysctl_ip_vs_snat_reroute,
++              .maxlen         = sizeof(int),
++              .mode           = 0644,
++              .proc_handler   = &proc_dointvec,
++      },
+ #if 0
+       {
+               .ctl_name       = NET_IPV4_VS_TO_ES,
+diff -urNp v2.6.22/linux/net/ipv4/ipvs/ip_vs_ftp.c 
linux/net/ipv4/ipvs/ip_vs_ftp.c
+--- v2.6.22/linux/net/ipv4/ipvs/ip_vs_ftp.c    2007-07-10 09:18:43.000000000 
+0300
++++ linux/net/ipv4/ipvs/ip_vs_ftp.c    2007-07-12 09:47:58.000000000 +0300
+@@ -194,6 +194,11 @@ static int ip_vs_ftp_out(struct ip_vs_ap
+                       ip_vs_control_add(n_cp, cp);
+               }
+ 
++#ifdef CONFIG_IP_VS_NFCT
++              if ((*pskb)->nfct)
++                      ip_vs_nfct_expect_related(*pskb, n_cp, 0, IPPROTO_TCP, 
0);
++#endif
++
+               /*
+                * Replace the old passive address with the new one
+                */
+@@ -326,6 +331,11 @@ static int ip_vs_ftp_in(struct ip_vs_app
+               ip_vs_control_add(n_cp, cp);
+       }
+ 
++#ifdef CONFIG_IP_VS_NFCT
++      if ((*pskb)->nfct)
++              ip_vs_nfct_expect_related(*pskb, n_cp, n_cp->dport, 
IPPROTO_TCP, 1);
++#endif
++
+       /*
+        *      Move tunnel to listen state
+        */
+diff -urNp v2.6.22/linux/net/ipv4/ipvs/ip_vs_nfct.c 
linux/net/ipv4/ipvs/ip_vs_nfct.c
+--- v2.6.22/linux/net/ipv4/ipvs/ip_vs_nfct.c   1970-01-01 02:00:00.000000000 
+0200
++++ linux/net/ipv4/ipvs/ip_vs_nfct.c   2007-07-12 12:04:31.000000000 +0300
+@@ -0,0 +1,389 @@
++/*
++ * 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-2007
++ * 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 <[EMAIL PROTECTED]>
++ * Julian Anastasov <[EMAIL PROTECTED]>               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_conntrack_expect_alloc(ct)))
++              return;
++
++      e->expectfn                     = ip_vs_nfct_expect_callback;
++      e->helper                       = NULL;
++      e->flags                        = 0;
++      memset(&e->tuple, 0, sizeof(e->tuple));
<<Diff was trimmed, longer than 597 lines>>
_______________________________________________
pld-cvs-commit mailing list
[email protected]
http://lists.pld-linux.org/mailman/listinfo/pld-cvs-commit

Reply via email to