net: Introduce sk_route_nocaps
[safe/jmp/linux-2.6] / net / ipv6 / tcp_ipv6.c
index 5d2e430..2b7c3a1 100644 (file)
@@ -353,6 +353,11 @@ static void tcp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
        if (sk->sk_state == TCP_CLOSE)
                goto out;
 
+       if (ipv6_hdr(skb)->hop_limit < inet6_sk(sk)->min_hopcount) {
+               NET_INC_STATS_BH(net, LINUX_MIB_TCPMINTTLDROP);
+               goto out;
+       }
+
        tp = tcp_sk(sk);
        seq = ntohl(th->seq);
        if (sk->sk_state != TCP_LISTEN &&
@@ -599,7 +604,7 @@ static int tcp_v6_md5_do_add(struct sock *sk, struct in6_addr *peer,
                                kfree(newkey);
                                return -ENOMEM;
                        }
-                       sk->sk_route_caps &= ~NETIF_F_GSO_MASK;
+                       sk_nocaps_add(sk, NETIF_F_GSO_MASK);
                }
                if (tcp_alloc_md5sig_pool(sk) == NULL) {
                        kfree(newkey);
@@ -736,7 +741,7 @@ static int tcp_v6_parse_md5_keys (struct sock *sk, char __user *optval,
                        return -ENOMEM;
 
                tp->md5sig_info = p;
-               sk->sk_route_caps &= ~NETIF_F_GSO_MASK;
+               sk_nocaps_add(sk, NETIF_F_GSO_MASK);
        }
 
        newkey = kmemdup(cmd.tcpm_key, cmd.tcpm_keylen, GFP_KERNEL);
@@ -1054,6 +1059,9 @@ static void tcp_v6_send_response(struct sk_buff *skb, u32 seq, u32 ack, u32 win,
        ipv6_addr_copy(&fl.fl6_dst, &ipv6_hdr(skb)->saddr);
        ipv6_addr_copy(&fl.fl6_src, &ipv6_hdr(skb)->daddr);
 
+       buff->ip_summed = CHECKSUM_PARTIAL;
+       buff->csum = 0;
+
        __tcp_v6_send_check(buff, &fl.fl6_src, &fl.fl6_dst);
 
        fl.proto = IPPROTO_TCP;
@@ -1675,6 +1683,7 @@ ipv6_pktoptions:
 static int tcp_v6_rcv(struct sk_buff *skb)
 {
        struct tcphdr *th;
+       struct ipv6hdr *hdr;
        struct sock *sk;
        int ret;
        struct net *net = dev_net(skb->dev);
@@ -1701,12 +1710,13 @@ static int tcp_v6_rcv(struct sk_buff *skb)
                goto bad_packet;
 
        th = tcp_hdr(skb);
+       hdr = ipv6_hdr(skb);
        TCP_SKB_CB(skb)->seq = ntohl(th->seq);
        TCP_SKB_CB(skb)->end_seq = (TCP_SKB_CB(skb)->seq + th->syn + th->fin +
                                    skb->len - th->doff*4);
        TCP_SKB_CB(skb)->ack_seq = ntohl(th->ack_seq);
        TCP_SKB_CB(skb)->when = 0;
-       TCP_SKB_CB(skb)->flags = ipv6_get_dsfield(ipv6_hdr(skb));
+       TCP_SKB_CB(skb)->flags = ipv6_get_dsfield(hdr);
        TCP_SKB_CB(skb)->sacked = 0;
 
        sk = __inet6_lookup_skb(&tcp_hashinfo, skb, th->source, th->dest);
@@ -1717,6 +1727,11 @@ process:
        if (sk->sk_state == TCP_TIME_WAIT)
                goto do_time_wait;
 
+       if (hdr->hop_limit < inet6_sk(sk)->min_hopcount) {
+               NET_INC_STATS_BH(net, LINUX_MIB_TCPMINTTLDROP);
+               goto discard_and_relse;
+       }
+
        if (!xfrm6_policy_check(sk, XFRM_POLICY_IN, skb))
                goto discard_and_relse;