aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJulian Anastasov <ja@ssi.bg>2010-09-21 11:38:57 -0400
committerPatrick McHardy <kaber@trash.net>2010-09-21 11:38:57 -0400
commit8a8030407f55a6aaedb51167c1a2383311fcd707 (patch)
tree585f2963a56e528a06f0f3180985faa8a368d3b8
parentf4bc17cdd205ebaa3807c2aa973719bb5ce6a5b2 (diff)
ipvs: make rerouting optional with snat_reroute
Add new sysctl flag "snat_reroute". Recent kernels use ip_route_me_harder() to route LVS-NAT responses properly by VIP when there are multiple paths to client. But setups that do not have alternative default routes can skip this routing lookup by using snat_reroute=0. Signed-off-by: Julian Anastasov <ja@ssi.bg> Signed-off-by: Patrick McHardy <kaber@trash.net>
-rw-r--r--include/net/ip_vs.h1
-rw-r--r--net/netfilter/ipvs/ip_vs_core.c37
-rw-r--r--net/netfilter/ipvs/ip_vs_ctl.c8
3 files changed, 38 insertions, 8 deletions
diff --git a/include/net/ip_vs.h b/include/net/ip_vs.h
index e8ec5231eae9..3915a4f4cd30 100644
--- a/include/net/ip_vs.h
+++ b/include/net/ip_vs.h
@@ -801,6 +801,7 @@ extern int sysctl_ip_vs_expire_quiescent_template;
801extern int sysctl_ip_vs_sync_threshold[2]; 801extern int sysctl_ip_vs_sync_threshold[2];
802extern int sysctl_ip_vs_nat_icmp_send; 802extern int sysctl_ip_vs_nat_icmp_send;
803extern int sysctl_ip_vs_conntrack; 803extern int sysctl_ip_vs_conntrack;
804extern int sysctl_ip_vs_snat_reroute;
804extern struct ip_vs_stats ip_vs_stats; 805extern struct ip_vs_stats ip_vs_stats;
805extern const struct ctl_path net_vs_ctl_path[]; 806extern const struct ctl_path net_vs_ctl_path[];
806 807
diff --git a/net/netfilter/ipvs/ip_vs_core.c b/net/netfilter/ipvs/ip_vs_core.c
index 7fbc80d81fe8..06c388bf4e33 100644
--- a/net/netfilter/ipvs/ip_vs_core.c
+++ b/net/netfilter/ipvs/ip_vs_core.c
@@ -929,20 +929,31 @@ handle_response(int af, struct sk_buff *skb, struct ip_vs_protocol *pp,
929 ip_send_check(ip_hdr(skb)); 929 ip_send_check(ip_hdr(skb));
930 } 930 }
931 931
932 /*
933 * nf_iterate does not expect change in the skb->dst->dev.
934 * It looks like it is not fatal to enable this code for hooks
935 * where our handlers are at the end of the chain list and
936 * when all next handlers use skb->dst->dev and not outdev.
937 * It will definitely route properly the inout NAT traffic
938 * when multiple paths are used.
939 */
940
932 /* For policy routing, packets originating from this 941 /* For policy routing, packets originating from this
933 * machine itself may be routed differently to packets 942 * machine itself may be routed differently to packets
934 * passing through. We want this packet to be routed as 943 * passing through. We want this packet to be routed as
935 * if it came from this machine itself. So re-compute 944 * if it came from this machine itself. So re-compute
936 * the routing information. 945 * the routing information.
937 */ 946 */
947 if (sysctl_ip_vs_snat_reroute) {
938#ifdef CONFIG_IP_VS_IPV6 948#ifdef CONFIG_IP_VS_IPV6
939 if (af == AF_INET6) { 949 if (af == AF_INET6) {
940 if (ip6_route_me_harder(skb) != 0) 950 if (ip6_route_me_harder(skb) != 0)
941 goto drop; 951 goto drop;
942 } else 952 } else
943#endif 953#endif
944 if (ip_route_me_harder(skb, RTN_LOCAL) != 0) 954 if (ip_route_me_harder(skb, RTN_LOCAL) != 0)
945 goto drop; 955 goto drop;
956 }
946 957
947 IP_VS_DBG_PKT(10, pp, skb, 0, "After SNAT"); 958 IP_VS_DBG_PKT(10, pp, skb, 0, "After SNAT");
948 959
@@ -991,8 +1002,13 @@ ip_vs_out(unsigned int hooknum, struct sk_buff *skb,
991 if (unlikely(iph.protocol == IPPROTO_ICMPV6)) { 1002 if (unlikely(iph.protocol == IPPROTO_ICMPV6)) {
992 int related, verdict = ip_vs_out_icmp_v6(skb, &related); 1003 int related, verdict = ip_vs_out_icmp_v6(skb, &related);
993 1004
994 if (related) 1005 if (related) {
1006 if (sysctl_ip_vs_snat_reroute &&
1007 NF_ACCEPT == verdict &&
1008 ip6_route_me_harder(skb))
1009 verdict = NF_DROP;
995 return verdict; 1010 return verdict;
1011 }
996 ip_vs_fill_iphdr(af, skb_network_header(skb), &iph); 1012 ip_vs_fill_iphdr(af, skb_network_header(skb), &iph);
997 } 1013 }
998 } else 1014 } else
@@ -1000,8 +1016,13 @@ ip_vs_out(unsigned int hooknum, struct sk_buff *skb,
1000 if (unlikely(iph.protocol == IPPROTO_ICMP)) { 1016 if (unlikely(iph.protocol == IPPROTO_ICMP)) {
1001 int related, verdict = ip_vs_out_icmp(skb, &related); 1017 int related, verdict = ip_vs_out_icmp(skb, &related);
1002 1018
1003 if (related) 1019 if (related) {
1020 if (sysctl_ip_vs_snat_reroute &&
1021 NF_ACCEPT == verdict &&
1022 ip_route_me_harder(skb, RTN_LOCAL))
1023 verdict = NF_DROP;
1004 return verdict; 1024 return verdict;
1025 }
1005 ip_vs_fill_iphdr(af, skb_network_header(skb), &iph); 1026 ip_vs_fill_iphdr(af, skb_network_header(skb), &iph);
1006 } 1027 }
1007 1028
diff --git a/net/netfilter/ipvs/ip_vs_ctl.c b/net/netfilter/ipvs/ip_vs_ctl.c
index d2d842f292c6..e637cd0384b1 100644
--- a/net/netfilter/ipvs/ip_vs_ctl.c
+++ b/net/netfilter/ipvs/ip_vs_ctl.c
@@ -91,6 +91,7 @@ int sysctl_ip_vs_nat_icmp_send = 0;
91#ifdef CONFIG_IP_VS_NFCT 91#ifdef CONFIG_IP_VS_NFCT
92int sysctl_ip_vs_conntrack; 92int sysctl_ip_vs_conntrack;
93#endif 93#endif
94int sysctl_ip_vs_snat_reroute = 1;
94 95
95 96
96#ifdef CONFIG_IP_VS_DEBUG 97#ifdef CONFIG_IP_VS_DEBUG
@@ -1599,6 +1600,13 @@ static struct ctl_table vs_vars[] = {
1599 .mode = 0644, 1600 .mode = 0644,
1600 .proc_handler = proc_do_defense_mode, 1601 .proc_handler = proc_do_defense_mode,
1601 }, 1602 },
1603 {
1604 .procname = "snat_reroute",
1605 .data = &sysctl_ip_vs_snat_reroute,
1606 .maxlen = sizeof(int),
1607 .mode = 0644,
1608 .proc_handler = &proc_dointvec,
1609 },
1602#if 0 1610#if 0
1603 { 1611 {
1604 .procname = "timeout_established", 1612 .procname = "timeout_established",