Merge branch 'acpi-general'
[cascardo/linux.git] / net / ipv6 / tcp_ipv6.c
index a3e60cc..26175bf 100644 (file)
@@ -403,8 +403,9 @@ static void tcp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
                tp->mtu_info = ntohl(info);
                if (!sock_owned_by_user(sk))
                        tcp_v6_mtu_reduced(sk);
-               else
-                       set_bit(TCP_MTU_REDUCED_DEFERRED, &tp->tsq_flags);
+               else if (!test_and_set_bit(TCP_MTU_REDUCED_DEFERRED,
+                                          &tp->tsq_flags))
+                       sock_hold(sk);
                goto out;
        }
 
@@ -475,7 +476,7 @@ static int tcp_v6_send_synack(struct sock *sk, struct dst_entry *dst,
        if (!dst && (dst = inet6_csk_route_req(sk, fl6, req)) == NULL)
                goto done;
 
-       skb = tcp_make_synack(sk, dst, req, rvp);
+       skb = tcp_make_synack(sk, dst, req, rvp, NULL);
 
        if (skb) {
                __tcp_v6_send_check(skb, &treq->loc_addr, &treq->rmt_addr);
@@ -762,6 +763,8 @@ static struct sk_buff **tcp6_gro_receive(struct sk_buff **head,
                                         struct sk_buff *skb)
 {
        const struct ipv6hdr *iph = skb_gro_network_header(skb);
+       __wsum wsum;
+       __sum16 sum;
 
        switch (skb->ip_summed) {
        case CHECKSUM_COMPLETE:
@@ -770,11 +773,23 @@ static struct sk_buff **tcp6_gro_receive(struct sk_buff **head,
                        skb->ip_summed = CHECKSUM_UNNECESSARY;
                        break;
                }
-
-               /* fall through */
-       case CHECKSUM_NONE:
+flush:
                NAPI_GRO_CB(skb)->flush = 1;
                return NULL;
+
+       case CHECKSUM_NONE:
+               wsum = ~csum_unfold(csum_ipv6_magic(&iph->saddr, &iph->daddr,
+                                                   skb_gro_len(skb),
+                                                   IPPROTO_TCP, 0));
+               sum = csum_fold(skb_checksum(skb,
+                                            skb_gro_offset(skb),
+                                            skb_gro_len(skb),
+                                            wsum));
+               if (sum)
+                       goto flush;
+
+               skb->ip_summed = CHECKSUM_UNNECESSARY;
+               break;
        }
 
        return tcp_gro_receive(head, skb);
@@ -862,7 +877,8 @@ static void tcp_v6_send_response(struct sk_buff *skb, u32 seq, u32 ack, u32 win,
        __tcp_v6_send_check(buff, &fl6.saddr, &fl6.daddr);
 
        fl6.flowi6_proto = IPPROTO_TCP;
-       fl6.flowi6_oif = inet6_iif(skb);
+       if (ipv6_addr_type(&fl6.daddr) & IPV6_ADDR_LINKLOCAL)
+               fl6.flowi6_oif = inet6_iif(skb);
        fl6.fl6_dport = t1->dest;
        fl6.fl6_sport = t1->source;
        security_skb_classify_flow(skb, flowi6_to_flowi(&fl6));
@@ -987,7 +1003,7 @@ static struct sock *tcp_v6_hnd_req(struct sock *sk,struct sk_buff *skb)
                                   &ipv6_hdr(skb)->saddr,
                                   &ipv6_hdr(skb)->daddr, inet6_iif(skb));
        if (req)
-               return tcp_check_req(sk, skb, req, prev);
+               return tcp_check_req(sk, skb, req, prev, false);
 
        nsk = __inet6_lookup_established(sock_net(sk), &tcp_hashinfo,
                        &ipv6_hdr(skb)->saddr, th->source,
@@ -1168,7 +1184,6 @@ static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb)
        }
 have_isn:
        tcp_rsk(req)->snt_isn = isn;
-       tcp_rsk(req)->snt_synack = tcp_time_stamp;
 
        if (security_inet_conn_request(sk, skb, req))
                goto drop_and_release;
@@ -1179,6 +1194,8 @@ have_isn:
            want_cookie)
                goto drop_and_free;
 
+       tcp_rsk(req)->snt_synack = tcp_time_stamp;
+       tcp_rsk(req)->listener = NULL;
        inet6_csk_reqsk_queue_hash_add(sk, req, TCP_TIMEOUT_INIT);
        return 0;
 
@@ -1346,9 +1363,7 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
                newtp->advmss = tcp_sk(sk)->rx_opt.user_mss;
 
        tcp_initialize_rcv_mss(newsk);
-       if (tcp_rsk(req)->snt_synack)
-               tcp_valid_rtt_meas(newsk,
-                   tcp_time_stamp - tcp_rsk(req)->snt_synack);
+       tcp_synack_rtt_meas(newsk, req);
        newtp->total_retrans = req->retrans;
 
        newinet->inet_daddr = newinet->inet_saddr = LOOPBACK4_IPV6;
@@ -1828,7 +1843,7 @@ static void tcp_v6_destroy_sock(struct sock *sk)
 #ifdef CONFIG_PROC_FS
 /* Proc filesystem TCPv6 sock list dumping. */
 static void get_openreq6(struct seq_file *seq,
-                        const struct sock *sk, struct request_sock *req, int i, int uid)
+                        const struct sock *sk, struct request_sock *req, int i, kuid_t uid)
 {
        int ttd = req->expires - jiffies;
        const struct in6_addr *src = &inet6_rsk(req)->loc_addr;
@@ -1852,7 +1867,7 @@ static void get_openreq6(struct seq_file *seq,
                   1,   /* timers active (only the expire timer) */
                   jiffies_to_clock_t(ttd),
                   req->retrans,
-                  uid,
+                  from_kuid_munged(seq_user_ns(seq), uid),
                   0,  /* non standard timer */
                   0, /* open_requests have no inode */
                   0, req);
@@ -1900,9 +1915,9 @@ static void get_tcp6_sock(struct seq_file *seq, struct sock *sp, int i)
                   tp->write_seq-tp->snd_una,
                   (sp->sk_state == TCP_LISTEN) ? sp->sk_ack_backlog : (tp->rcv_nxt - tp->copied_seq),
                   timer_active,
-                  jiffies_to_clock_t(timer_expires - jiffies),
+                  jiffies_delta_to_clock_t(timer_expires - jiffies),
                   icsk->icsk_retransmits,
-                  sock_i_uid(sp),
+                  from_kuid_munged(seq_user_ns(seq), sock_i_uid(sp)),
                   icsk->icsk_probes_out,
                   sock_i_ino(sp),
                   atomic_read(&sp->sk_refcnt), sp,
@@ -1920,10 +1935,7 @@ static void get_timewait6_sock(struct seq_file *seq,
        const struct in6_addr *dest, *src;
        __u16 destp, srcp;
        const struct inet6_timewait_sock *tw6 = inet6_twsk((struct sock *)tw);
-       int ttd = tw->tw_ttd - jiffies;
-
-       if (ttd < 0)
-               ttd = 0;
+       long delta = tw->tw_ttd - jiffies;
 
        dest = &tw6->tw_v6_daddr;
        src  = &tw6->tw_v6_rcv_saddr;
@@ -1939,7 +1951,7 @@ static void get_timewait6_sock(struct seq_file *seq,
                   dest->s6_addr32[0], dest->s6_addr32[1],
                   dest->s6_addr32[2], dest->s6_addr32[3], destp,
                   tw->tw_substate, 0, 0,
-                  3, jiffies_to_clock_t(ttd), 0, 0, 0, 0,
+                  3, jiffies_delta_to_clock_t(delta), 0, 0, 0, 0,
                   atomic_read(&tw->tw_refcnt), tw);
 }