diff -urN v2.4.23/linux/include/linux/netfilter_ipv4/ip_nat.h linux/include/linux/netfilter_ipv4/ip_nat.h --- v2.4.23/linux/include/linux/netfilter_ipv4/ip_nat.h 2002-11-29 03:00:12.000000000 +0200 +++ linux/include/linux/netfilter_ipv4/ip_nat.h 2003-11-30 12:02:42.893178024 +0200 @@ -129,5 +129,9 @@ extern u_int16_t ip_nat_cheat_check(u_int32_t oldvalinv, u_int32_t newval, u_int16_t oldcheck); + +extern void ip_nat_replace_in_hashes(struct ip_conntrack *conntrack, + struct ip_nat_info *info); + #endif /*__KERNEL__*/ #endif diff -urN v2.4.23/linux/include/net/ip_vs.h linux/include/net/ip_vs.h --- v2.4.23/linux/include/net/ip_vs.h 2003-11-28 22:04:13.000000000 +0200 +++ linux/include/net/ip_vs.h 2003-11-30 11:58:29.297730392 +0200 @@ -317,6 +317,8 @@ NET_IPV4_VS_EXPIRE_NODEST_CONN=23, NET_IPV4_VS_SYNC_THRESHOLD=24, NET_IPV4_VS_NAT_ICMP_SEND=25, + NET_IPV4_VS_SNAT_REROUTE=26, + NET_IPV4_VS_CONNTRACK=27, NET_IPV4_VS_LAST }; @@ -562,6 +564,17 @@ */ /* + * Netfilter connection tracking + * (from ip_vs_nfct.c) + */ +extern int ip_vs_nfct_confirm(struct sk_buff *skb, struct ip_vs_conn *cp, + union ip_vs_tphdr h); +extern void ip_vs_nfct_expect_related(struct sk_buff *skb, + struct ip_vs_conn *cp, + __u16 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 @@ -702,8 +715,20 @@ extern int sysctl_ip_vs_expire_nodest_conn; extern int sysctl_ip_vs_sync_threshold; 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; +} + +#endif + extern struct ip_vs_service *ip_vs_service_get(__u32 fwmark, __u16 protocol, __u32 vaddr, __u16 vport); diff -urN v2.4.23/linux/net/ipv4/ipvs/Config.in linux/net/ipv4/ipvs/Config.in --- v2.4.23/linux/net/ipv4/ipvs/Config.in 2003-11-28 22:04:14.000000000 +0200 +++ linux/net/ipv4/ipvs/Config.in 2003-11-30 11:58:12.897223648 +0200 @@ -21,6 +21,7 @@ dep_tristate ' never queue scheduling' CONFIG_IP_VS_NQ $CONFIG_IP_VS comment 'IPVS application helper' dep_tristate ' FTP protocol helper' CONFIG_IP_VS_FTP $CONFIG_IP_VS + dep_mbool ' Netfilter connection tracking' CONFIG_IP_VS_NFCT $CONFIG_IP_VS $CONFIG_IP_NF_CONNTRACK fi endmenu diff -urN v2.4.23/linux/net/ipv4/ipvs/ip_vs_conn.c linux/net/ipv4/ipvs/ip_vs_conn.c --- v2.4.23/linux/net/ipv4/ipvs/ip_vs_conn.c 2003-11-28 22:04:14.000000000 +0200 +++ linux/net/ipv4/ipvs/ip_vs_conn.c 2003-11-30 11:58:12.898223496 +0200 @@ -638,6 +638,21 @@ } } +#ifdef CONFIG_IP_VS_NFCT + if (ip_vs_use_conntrack(skb)) { + union ip_vs_tphdr h; + int verdict; + + h.raw = skb->nh.raw + skb->nh.iph->ihl * 4; + verdict = ip_vs_nfct_confirm(skb, cp, h); + + if (verdict != NF_ACCEPT) { + ip_rt_put(rt); + goto tx_error; + } + } +#endif + /* drop old route */ dst_release(skb->dst); skb->dst = &rt->u.dst; @@ -756,6 +771,16 @@ if (ip_vs_skb_cow(skb, rt->u.dst.dev->hard_header_len, &iph, &h.raw)) return NF_DROP; +#ifdef CONFIG_IP_VS_NFCT + /* Confirm the conn before the app handlers, useful for UDP apps */ + if (ip_vs_use_conntrack(skb)) { + int verdict = ip_vs_nfct_confirm(skb, cp, h); + + if (verdict != NF_ACCEPT) + return verdict; + } +#endif + /* mangle the packet */ iph->daddr = cp->daddr; h.portp[1] = cp->dport; @@ -911,6 +936,21 @@ old_iph = skb->nh.iph; } +#ifdef CONFIG_IP_VS_NFCT + if (ip_vs_use_conntrack(skb)) { + union ip_vs_tphdr h; + int verdict; + + h.raw = (char *) old_iph + old_iph->ihl * 4; + verdict = ip_vs_nfct_confirm(skb, cp, h); + + if (verdict != NF_ACCEPT) { + ip_rt_put(rt); + goto tx_error; + } + } +#endif + skb->nh.raw = skb_push(skb, sizeof(struct iphdr)); memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt)); @@ -987,6 +1027,21 @@ } } +#ifdef CONFIG_IP_VS_NFCT + if (ip_vs_use_conntrack(skb)) { + union ip_vs_tphdr h; + int verdict; + + h.raw = skb->nh.raw + skb->nh.iph->ihl * 4; + verdict = ip_vs_nfct_confirm(skb, cp, h); + + if (verdict != NF_ACCEPT) { + ip_rt_put(rt); + goto tx_error; + } + } +#endif + /* drop old route */ dst_release(skb->dst); skb->dst = &rt->u.dst; @@ -1214,6 +1269,11 @@ 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 + ip_vs_unbind_dest(cp); ip_vs_unbind_app(cp); ip_vs_timeout_detach(cp); diff -urN v2.4.23/linux/net/ipv4/ipvs/ip_vs_core.c linux/net/ipv4/ipvs/ip_vs_core.c --- v2.4.23/linux/net/ipv4/ipvs/ip_vs_core.c 2003-11-28 22:04:14.000000000 +0200 +++ linux/net/ipv4/ipvs/ip_vs_core.c 2003-11-30 11:58:12.899223344 +0200 @@ -621,6 +621,9 @@ skb->nfcache |= NFC_IPVS_PROPERTY; + if (sysctl_ip_vs_snat_reroute && ip_route_me_harder(skb_p)) + return NF_DROP; + return NF_ACCEPT; } @@ -811,6 +814,25 @@ skb->nfcache |= NFC_IPVS_PROPERTY; + /* + * 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 (sysctl_ip_vs_snat_reroute && ip_route_me_harder(skb_p)) + return NF_DROP; + LeaveFunction(11); return NF_ACCEPT; } diff -urN v2.4.23/linux/net/ipv4/ipvs/ip_vs_ctl.c linux/net/ipv4/ipvs/ip_vs_ctl.c --- v2.4.23/linux/net/ipv4/ipvs/ip_vs_ctl.c 2003-11-28 22:04:14.000000000 +0200 +++ linux/net/ipv4/ipvs/ip_vs_ctl.c 2003-11-30 11:58:12.901223040 +0200 @@ -79,6 +79,10 @@ int sysctl_ip_vs_expire_nodest_conn = 0; int sysctl_ip_vs_sync_threshold = 3; 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 static int sysctl_ip_vs_debug_level = 0; @@ -1379,6 +1383,11 @@ {NET_IPV4_VS_AMDROPRATE, "am_droprate", &sysctl_ip_vs_am_droprate, sizeof(int), 0644, NULL, &proc_dointvec}, +#ifdef CONFIG_IP_VS_NFCT + {NET_IPV4_VS_CONNTRACK, "conntrack", + &sysctl_ip_vs_conntrack, sizeof(int), 0644, NULL, + &proc_dointvec}, +#endif {NET_IPV4_VS_DROP_ENTRY, "drop_entry", &sysctl_ip_vs_drop_entry, sizeof(int), 0644, NULL, &ip_vs_sysctl_defense_mode}, @@ -1388,6 +1397,9 @@ {NET_IPV4_VS_SECURE_TCP, "secure_tcp", &sysctl_ip_vs_secure_tcp, sizeof(int), 0644, NULL, &ip_vs_sysctl_defense_mode}, + {NET_IPV4_VS_SNAT_REROUTE, "snat_reroute", + &sysctl_ip_vs_snat_reroute, sizeof(int), 0644, NULL, + &proc_dointvec}, {NET_IPV4_VS_TO_ES, "timeout_established", &vs_timeout_table_dos.timeout[IP_VS_S_ESTABLISHED], sizeof(int), 0644, NULL, &proc_dointvec_jiffies}, diff -urN v2.4.23/linux/net/ipv4/ipvs/ip_vs_ftp.c linux/net/ipv4/ipvs/ip_vs_ftp.c --- v2.4.23/linux/net/ipv4/ipvs/ip_vs_ftp.c 2003-11-28 22:04:14.000000000 +0200 +++ linux/net/ipv4/ipvs/ip_vs_ftp.c 2003-11-30 11:58:12.902222888 +0200 @@ -202,6 +202,11 @@ atomic_inc(&cp->dest->inactconns); } +#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 */ @@ -328,6 +333,11 @@ atomic_inc(&cp->dest->inactconns); } +#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 -urN v2.4.23/linux/net/ipv4/ipvs/ip_vs_nfct.c linux/net/ipv4/ipvs/ip_vs_nfct.c --- v2.4.23/linux/net/ipv4/ipvs/ip_vs_nfct.c 1970-01-01 02:00:00.000000000 +0200 +++ linux/net/ipv4/ipvs/ip_vs_nfct.c 2003-11-30 12:22:59.798180344 +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 + * 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 + * Julian Anastasov 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 + * ip_conntrack_ftp for the same ports + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined(CONFIG_IP_NF_CONNTRACK) || defined(CONFIG_IP_NF_CONNTRACK_MODULE) +#include +#include +#ifdef CONFIG_IP_NF_NAT_NEEDED +#include +#endif +#endif + +#include + + +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.ip), ntohs((t)->src.u.all), \ + NIPQUAD((t)->dst.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 + +static int __ip_vs_nfct_confirm(struct sk_buff *skb, struct ip_vs_conn *cp, + union ip_vs_tphdr h) +{ + /* + * The assumptions: + * - the nfct is !NULL and is not confirmed + * - we are called before any mangle + */ + + struct iphdr *iph = skb->nh.iph; + struct ip_conntrack *ct = (struct ip_conntrack *) skb->nfct->master; + struct ip_conntrack_tuple new_reply; + int ret; +#ifdef CONFIG_IP_VS_DEBUG + struct ip_conntrack_tuple *orig_tup = + &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple; + struct ip_conntrack_tuple *orig_rep = + &ct->tuplehash[IP_CT_DIR_REPLY].tuple; +#ifdef CONFIG_IP_NF_NAT_NEEDED + int initialized = ct->nat.info.initialized; +#else + int initialized = 0; +#endif +#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_IP_NF_NAT_NEEDED + /* + * This is really bad, may be we are trying to alter DNAT conn? + * This is not supported, avoid the confirmation. + */ + if (ct->nat.info.initialized && ct->nat.info.num_manips) { +#ifdef CONFIG_IP_VS_DEBUG + int i; + + IP_VS_DBG(7, "%s: ct=%p, manips=%d, init=%d\n", + __FUNCTION__, ct, ct->nat.info.num_manips, + ct->nat.info.initialized); + for (i = 0; i < ct->nat.info.num_manips; i++) { + IP_VS_DBG(7, "%s: ct=%p, manip[%d]: type=%d, hook=%d, dir=%d, to %u.%u.%u.%u:%u\n", + __FUNCTION__, ct, i, + ct->nat.info.manips[i].maniptype, + ct->nat.info.manips[i].hooknum, + ct->nat.info.manips[i].direction, + NIPQUAD(ct->nat.info.manips[i].manip.ip), + ntohs(ct->nat.info.manips[i].manip.u.all)); + } +#endif + return NF_ACCEPT; + } +#endif + + if (IP_VS_FWD_METHOD(cp) != IP_VS_CONN_F_MASQ) + goto confirm; + + new_reply.src.ip = cp->daddr; + new_reply.src.u.tcp.port = cp->dport; + new_reply.dst.ip = iph->saddr; + new_reply.dst.u.tcp.port = h.portp[0]; + new_reply.dst.protonum = iph->protocol; + + ret = ip_conntrack_alter_reply(ct, &new_reply); + + IP_VS_DBG(7, "%s: ct=%p, init=%d, orig=" FMT_TUPLE + ", new_reply=" FMT_TUPLE " => alter_reply ret=%d\n", + __FUNCTION__, ct, initialized, + ARG_TUPLE(orig_tup), ARG_TUPLE(&new_reply), ret); + +#ifdef CONFIG_IP_NF_NAT_NEEDED + /* Update the NAT hashes if the conntrack has valid NAT info */ + if (ct->nat.info.initialized) + ip_nat_replace_in_hashes(ct, &ct->nat.info); +#endif + +confirm: + + ret = __ip_conntrack_confirm(skb->nfct); + + IP_VS_DBG(7, "%s: ct=%p, init=%d, orig=" FMT_TUPLE " => confirm ret=%d\n", + __FUNCTION__, ct, initialized, ARG_TUPLE(orig_tup), ret); + + return ret; +} + +/* + * Confirm (and optionally alter) the conntrack entry if needed + * because the IPVS packets do not reach ip_confirm. + */ +int ip_vs_nfct_confirm(struct sk_buff *skb, struct ip_vs_conn *cp, + union ip_vs_tphdr h) +{ + struct iphdr *iph = skb->nh.iph; + struct ip_conntrack *ct; + + /* 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. + */ + + ct = (struct ip_conntrack *) skb->nfct->master; + + /* We only deal with TCP or UDP packets */ + if (iph->protocol != IPPROTO_TCP && iph->protocol != IPPROTO_UDP) + return NF_ACCEPT; + + 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_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 !is_confirmed(ct) ? __ip_vs_nfct_confirm(skb, cp, h) : NF_ACCEPT; +} + +/* + * We are called from init_conntrack() as expectfn handler + */ + +static int ip_vs_nfct_expect_callback(struct ip_conntrack *ct) +{ + struct ip_conntrack_tuple *orig, new_reply; + struct ip_vs_conn *cp; + + /* + * - 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 + * - We are able to confirm the out->in related connections + * at the usual place (ip_vs_nfct_confirm) but we still have to + * confirm the in->out related connections, so we do it here for + * all kinds of related conns. + */ + + /* RS->CLIENT */ + orig = &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple; + cp = ip_vs_conn_out_get(orig->dst.protonum, + orig->src.ip, orig->src.u.tcp.port, + orig->dst.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, tuples=" FMT_TUPLE ", " FMT_TUPLE + ", found inout cp=" FMT_CONN "\n", + __FUNCTION__, ct, + ARG_TUPLE(orig), ARG_TUPLE(&new_reply), + ARG_CONN(cp)); + new_reply.dst.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.ip, orig->src.u.tcp.port, + orig->dst.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, tuples=" FMT_TUPLE ", " FMT_TUPLE + ", found outin cp=" FMT_CONN "\n", + __FUNCTION__, ct, + ARG_TUPLE(orig), ARG_TUPLE(&new_reply), + ARG_CONN(cp)); + new_reply.src.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, tuple=" FMT_TUPLE " - unknown expect\n", + __FUNCTION__, ct, ARG_TUPLE(orig)); + return 0; + +alter: + + /* Never alter conntrack for non-NAT conns */ + if (IP_VS_FWD_METHOD(cp) == IP_VS_CONN_F_MASQ) + ip_conntrack_alter_reply(ct, &new_reply); + ip_vs_conn_put(cp); + + /* And confirm the connection. Note that + * __ip_conntrack_confirm() needs a (struct + * nf_ct_info *), and we could probably use + * _ESTABLISHED or _NEW, but for tidiness we use + * the truthful one. + */ + __ip_conntrack_confirm(&ct->infos[IP_CT_RELATED]); + + return 0; +} + +/* + * 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, + __u16 port, __u16 proto, int from_rs) +{ + struct ip_conntrack *ct = (struct ip_conntrack *) skb->nfct->master; + struct ip_conntrack_expect e = { .expectfn = ip_vs_nfct_expect_callback }; + + if (!sysctl_ip_vs_conntrack) + return; + + if (!ct->helper) { + /* + * It is a bad idea to create expectation if ct has no helper. + * Please, load the proper conntrack support for cp->vport first. + */ + IP_VS_DBG(7, "%s: ct=%p, no ct->helper for cp=" FMT_CONN "\n", + __FUNCTION__, ct, ARG_CONN(cp)); + return; + } + + if (from_rs) { + e.tuple.src.ip = cp->daddr; + e.tuple.dst.ip = cp->caddr; + e.tuple.dst.u.tcp.port = cp->cport; + } else { + e.tuple.src.ip = cp->caddr; + e.tuple.dst.ip = cp->vaddr; + e.tuple.dst.u.tcp.port = cp->vport; + } + e.tuple.src.u.tcp.port = port; + e.tuple.dst.protonum = proto; + e.mask.src.ip = 0xffffffff; + e.mask.src.u.all = port? 0xffff : 0; + e.mask.dst.ip = 0xffffffff; + e.mask.dst.u.all = 0xffff; + e.mask.dst.protonum = 0xffff; + + IP_VS_DBG(7, "%s: ct=%p, expect tuple=" FMT_TUPLE "\n", + __FUNCTION__, ct, ARG_TUPLE(&e.tuple)); + ip_conntrack_expect_related(ct, &e); +} + +/* + * Our connection was terminated, try to drop the conntrack immediately + */ +void ip_vs_nfct_conn_drop(struct ip_vs_conn *cp) +{ + struct ip_conntrack_tuple_hash *h; + struct ip_conntrack *ct; + struct ip_conntrack_tuple tuple; + + if (!cp->cport) + return; + + tuple.src.ip = cp->caddr; + tuple.src.u.all = cp->cport; + tuple.dst.ip = cp->vaddr; + tuple.dst.u.all = cp->vport; + tuple.dst.protonum = cp->protocol; + + IP_VS_DBG(7, "%s: dropping conntrack with tuple=" FMT_TUPLE + " for conn " FMT_CONN "\n", + __FUNCTION__, ARG_TUPLE(&tuple), ARG_CONN(cp)); + + h = ip_conntrack_find_get(&tuple, NULL); + if (h) { + ct = h->ctrack; + if (del_timer(&ct->timeout)) { + IP_VS_DBG(7, "%s: ct=%p, deleted conntrack timer for tuple=" + FMT_TUPLE "\n", + __FUNCTION__, ct, ARG_TUPLE(&tuple)); + if (ct->timeout.function) + ct->timeout.function(ct->timeout.data); + } else { + IP_VS_DBG(7, "%s: ct=%p, no conntrack timer for tuple=" + FMT_TUPLE "\n", + __FUNCTION__, ct, ARG_TUPLE(&tuple)); + } + ip_conntrack_put(ct); + } else { + IP_VS_DBG(7, "%s: no conntrack for tuple=" FMT_TUPLE "\n", + __FUNCTION__, ARG_TUPLE(&tuple)); + } +} + diff -urN v2.4.23/linux/net/ipv4/ipvs/Makefile linux/net/ipv4/ipvs/Makefile --- v2.4.23/linux/net/ipv4/ipvs/Makefile 2003-11-28 22:04:14.000000000 +0200 +++ linux/net/ipv4/ipvs/Makefile 2003-11-30 11:58:12.903222736 +0200 @@ -11,8 +11,15 @@ export-objs := ip_vs_core.o ip_vs_app.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_app.o ip_vs_sync.o ip_vs_est.o + ip_vs_app.o ip_vs_sync.o ip_vs_est.o \ + $(ip_vs-extra_objs-y) +ifeq ($(CONFIG_IP_VS_NFCT),y) +export-objs += ip_vs_nfct.o +endif ifeq ($(CONFIG_IP_VS),y) obj-y := $(ip_vs-objs) diff -urN v2.4.23/linux/net/ipv4/netfilter/ip_conntrack_standalone.c linux/net/ipv4/netfilter/ip_conntrack_standalone.c --- v2.4.23/linux/net/ipv4/netfilter/ip_conntrack_standalone.c 2003-11-28 22:04:14.000000000 +0200 +++ linux/net/ipv4/netfilter/ip_conntrack_standalone.c 2003-11-30 12:02:42.894177872 +0200 @@ -458,6 +458,7 @@ EXPORT_SYMBOL(ip_conntrack_protocol_register); EXPORT_SYMBOL(ip_conntrack_protocol_unregister); EXPORT_SYMBOL(invert_tuplepr); +EXPORT_SYMBOL(__ip_conntrack_confirm); EXPORT_SYMBOL(ip_conntrack_alter_reply); EXPORT_SYMBOL(ip_conntrack_destroyed); EXPORT_SYMBOL(ip_conntrack_get); diff -urN v2.4.23/linux/net/ipv4/netfilter/ip_nat_core.c linux/net/ipv4/netfilter/ip_nat_core.c --- v2.4.23/linux/net/ipv4/netfilter/ip_nat_core.c 2003-11-28 22:04:14.000000000 +0200 +++ linux/net/ipv4/netfilter/ip_nat_core.c 2003-11-30 12:02:42.895177720 +0200 @@ -707,6 +707,17 @@ list_prepend(&byipsproto[ipsprotohash], &info->byipsproto); } +void ip_nat_replace_in_hashes(struct ip_conntrack *conntrack, + struct ip_nat_info *info) +{ + WRITE_LOCK(&ip_nat_lock); + if (!info->initialized) + place_in_hashes(conntrack, info); + else + replace_in_hashes(conntrack, info); + WRITE_UNLOCK(&ip_nat_lock); +} + static void manip_pkt(u_int16_t proto, struct iphdr *iph, size_t len, const struct ip_conntrack_manip *manip, diff -urN v2.4.23/linux/net/ipv4/netfilter/ip_nat_standalone.c linux/net/ipv4/netfilter/ip_nat_standalone.c --- v2.4.23/linux/net/ipv4/netfilter/ip_nat_standalone.c 2003-11-28 22:04:14.000000000 +0200 +++ linux/net/ipv4/netfilter/ip_nat_standalone.c 2003-11-30 12:02:42.896177568 +0200 @@ -355,5 +355,6 @@ EXPORT_SYMBOL(ip_nat_cheat_check); EXPORT_SYMBOL(ip_nat_mangle_tcp_packet); EXPORT_SYMBOL(ip_nat_mangle_udp_packet); +EXPORT_SYMBOL(ip_nat_replace_in_hashes); EXPORT_SYMBOL(ip_nat_used_tuple); MODULE_LICENSE("GPL");