ipvs: Store ipvs not net in struct ip_vs_conn
[deliverable/linux.git] / net / netfilter / ipvs / ip_vs_proto_tcp.c
index 8e92beb0cca9920238421af8a5b5206869c357e0..e00623a885187faba38e167b0e33e892a3f55d73 100644 (file)
@@ -40,19 +40,43 @@ tcp_conn_schedule(int af, struct sk_buff *skb, struct ip_vs_proto_data *pd,
        struct ip_vs_service *svc;
        struct tcphdr _tcph, *th;
        struct netns_ipvs *ipvs;
+       __be16 _ports[2], *ports = NULL;
 
-       th = skb_header_pointer(skb, iph->len, sizeof(_tcph), &_tcph);
-       if (th == NULL) {
+       net = skb_net(skb);
+       ipvs = net_ipvs(net);
+
+       /* In the event of icmp, we're only guaranteed to have the first 8
+        * bytes of the transport header, so we only check the rest of the
+        * TCP packet for non-ICMP packets
+        */
+       if (likely(!ip_vs_iph_icmp(iph))) {
+               th = skb_header_pointer(skb, iph->len, sizeof(_tcph), &_tcph);
+               if (th) {
+                       if (th->rst || !(sysctl_sloppy_tcp(ipvs) || th->syn))
+                               return 1;
+                       ports = &th->source;
+               }
+       } else {
+               ports = skb_header_pointer(
+                       skb, iph->len, sizeof(_ports), &_ports);
+       }
+
+       if (!ports) {
                *verdict = NF_DROP;
                return 0;
        }
-       net = skb_net(skb);
-       ipvs = net_ipvs(net);
+
        /* No !th->ack check to allow scheduling on SYN+ACK for Active FTP */
        rcu_read_lock();
-       if ((th->syn || sysctl_sloppy_tcp(ipvs)) && !th->rst &&
-           (svc = ip_vs_service_find(net, af, skb->mark, iph->protocol,
-                                     &iph->daddr, th->dest))) {
+
+       if (likely(!ip_vs_iph_inverse(iph)))
+               svc = ip_vs_service_find(net, af, skb->mark, iph->protocol,
+                                        &iph->daddr, ports[1]);
+       else
+               svc = ip_vs_service_find(net, af, skb->mark, iph->protocol,
+                                        &iph->saddr, ports[0]);
+
+       if (svc) {
                int ignored;
 
                if (ip_vs_todrop(ipvs)) {
@@ -609,7 +633,7 @@ tcp_unregister_app(struct net *net, struct ip_vs_app *inc)
 static int
 tcp_app_conn_bind(struct ip_vs_conn *cp)
 {
-       struct netns_ipvs *ipvs = net_ipvs(ip_vs_conn_net(cp));
+       struct netns_ipvs *ipvs = cp->ipvs;
        int hash;
        struct ip_vs_app *inc;
        int result = 0;
This page took 0.028025 seconds and 5 git commands to generate.