Merge git://www.linux-watchdog.org/linux-watchdog
[cascardo/linux.git] / net / netfilter / xt_socket.c
index 2ec08f0..49d14ec 100644 (file)
@@ -112,14 +112,15 @@ extract_icmp4_fields(const struct sk_buff *skb,
  *     box.
  */
 static struct sock *
-xt_socket_get_sock_v4(struct net *net, const u8 protocol,
+xt_socket_get_sock_v4(struct net *net, struct sk_buff *skb, const int doff,
+                     const u8 protocol,
                      const __be32 saddr, const __be32 daddr,
                      const __be16 sport, const __be16 dport,
                      const struct net_device *in)
 {
        switch (protocol) {
        case IPPROTO_TCP:
-               return __inet_lookup(net, &tcp_hashinfo,
+               return __inet_lookup(net, &tcp_hashinfo, skb, doff,
                                     saddr, sport, daddr, dport,
                                     in->ifindex);
        case IPPROTO_UDP:
@@ -148,6 +149,8 @@ static struct sock *xt_socket_lookup_slow_v4(struct net *net,
                                             const struct net_device *indev)
 {
        const struct iphdr *iph = ip_hdr(skb);
+       struct sk_buff *data_skb = NULL;
+       int doff = 0;
        __be32 uninitialized_var(daddr), uninitialized_var(saddr);
        __be16 uninitialized_var(dport), uninitialized_var(sport);
        u8 uninitialized_var(protocol);
@@ -169,6 +172,10 @@ static struct sock *xt_socket_lookup_slow_v4(struct net *net,
                sport = hp->source;
                daddr = iph->daddr;
                dport = hp->dest;
+               data_skb = (struct sk_buff *)skb;
+               doff = iph->protocol == IPPROTO_TCP ?
+                       ip_hdrlen(skb) + __tcp_hdrlen((struct tcphdr *)hp) :
+                       ip_hdrlen(skb) + sizeof(*hp);
 
        } else if (iph->protocol == IPPROTO_ICMP) {
                if (extract_icmp4_fields(skb, &protocol, &saddr, &daddr,
@@ -198,8 +205,8 @@ static struct sock *xt_socket_lookup_slow_v4(struct net *net,
        }
 #endif
 
-       return xt_socket_get_sock_v4(net, protocol, saddr, daddr,
-                                    sport, dport, indev);
+       return xt_socket_get_sock_v4(net, data_skb, doff, protocol, saddr,
+                                    daddr, sport, dport, indev);
 }
 
 static bool
@@ -318,14 +325,15 @@ extract_icmp6_fields(const struct sk_buff *skb,
 }
 
 static struct sock *
-xt_socket_get_sock_v6(struct net *net, const u8 protocol,
+xt_socket_get_sock_v6(struct net *net, struct sk_buff *skb, int doff,
+                     const u8 protocol,
                      const struct in6_addr *saddr, const struct in6_addr *daddr,
                      const __be16 sport, const __be16 dport,
                      const struct net_device *in)
 {
        switch (protocol) {
        case IPPROTO_TCP:
-               return inet6_lookup(net, &tcp_hashinfo,
+               return inet6_lookup(net, &tcp_hashinfo, skb, doff,
                                    saddr, sport, daddr, dport,
                                    in->ifindex);
        case IPPROTO_UDP:
@@ -343,6 +351,8 @@ static struct sock *xt_socket_lookup_slow_v6(struct net *net,
        __be16 uninitialized_var(dport), uninitialized_var(sport);
        const struct in6_addr *daddr = NULL, *saddr = NULL;
        struct ipv6hdr *iph = ipv6_hdr(skb);
+       struct sk_buff *data_skb = NULL;
+       int doff = 0;
        int thoff = 0, tproto;
 
        tproto = ipv6_find_hdr(skb, &thoff, -1, NULL, NULL);
@@ -362,6 +372,10 @@ static struct sock *xt_socket_lookup_slow_v6(struct net *net,
                sport = hp->source;
                daddr = &iph->daddr;
                dport = hp->dest;
+               data_skb = (struct sk_buff *)skb;
+               doff = tproto == IPPROTO_TCP ?
+                       thoff + __tcp_hdrlen((struct tcphdr *)hp) :
+                       thoff + sizeof(*hp);
 
        } else if (tproto == IPPROTO_ICMPV6) {
                struct ipv6hdr ipv6_var;
@@ -373,7 +387,7 @@ static struct sock *xt_socket_lookup_slow_v6(struct net *net,
                return NULL;
        }
 
-       return xt_socket_get_sock_v6(net, tproto, saddr, daddr,
+       return xt_socket_get_sock_v6(net, data_skb, doff, tproto, saddr, daddr,
                                     sport, dport, indev);
 }