[TCP]: Fix scatterlist handling in MD5 signature support.
[safe/jmp/linux-2.6] / net / ipv4 / tcp_ipv4.c
index f6793b4..ad759f1 100644 (file)
@@ -62,6 +62,7 @@
 #include <linux/init.h>
 #include <linux/times.h>
 
+#include <net/net_namespace.h>
 #include <net/icmp.h>
 #include <net/inet_hashtables.h>
 #include <net/tcp.h>
@@ -88,7 +89,7 @@ int sysctl_tcp_low_latency __read_mostly;
 #define ICMP_MIN_LENGTH 8
 
 /* Socket used for sending RSTs */
-static struct socket *tcp_socket;
+static struct socket *tcp_socket __read_mostly;
 
 void tcp_v4_send_check(struct sock *sk, int len, struct sk_buff *skb);
 
@@ -125,10 +126,10 @@ void tcp_unhash(struct sock *sk)
 
 static inline __u32 tcp_v4_init_sequence(struct sk_buff *skb)
 {
-       return secure_tcp_sequence_number(skb->nh.iph->daddr,
-                                         skb->nh.iph->saddr,
-                                         skb->h.th->dest,
-                                         skb->h.th->source);
+       return secure_tcp_sequence_number(ip_hdr(skb)->daddr,
+                                         ip_hdr(skb)->saddr,
+                                         tcp_hdr(skb)->dest,
+                                         tcp_hdr(skb)->source);
 }
 
 int tcp_twsk_unique(struct sock *sk, struct sock *sktw, void *twp)
@@ -149,7 +150,7 @@ int tcp_twsk_unique(struct sock *sk, struct sock *sktw, void *twp)
         */
        if (tcptw->tw_ts_recent_stamp &&
            (twp == NULL || (sysctl_tcp_tw_reuse &&
-                            xtime.tv_sec - tcptw->tw_ts_recent_stamp > 1))) {
+                            get_seconds() - tcptw->tw_ts_recent_stamp > 1))) {
                tp->write_seq = tcptw->tw_snd_nxt + 65535 + 2;
                if (tp->write_seq == 0)
                        tp->write_seq = 1;
@@ -192,8 +193,11 @@ int tcp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
                               RT_CONN_FLAGS(sk), sk->sk_bound_dev_if,
                               IPPROTO_TCP,
                               inet->sport, usin->sin_port, sk, 1);
-       if (tmp < 0)
+       if (tmp < 0) {
+               if (tmp == -ENETUNREACH)
+                       IP_INC_STATS_BH(IPSTATS_MIB_OUTNOROUTES);
                return tmp;
+       }
 
        if (rt->rt_flags & (RTCF_MULTICAST | RTCF_BROADCAST)) {
                ip_rt_put(rt);
@@ -224,7 +228,7 @@ int tcp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
                 * when trying new connection.
                 */
                if (peer != NULL &&
-                   peer->tcp_ts_stamp + TCP_PAWS_MSL >= xtime.tv_sec) {
+                   peer->tcp_ts_stamp + TCP_PAWS_MSL >= get_seconds()) {
                        tp->rx_opt.ts_recent_stamp = peer->tcp_ts_stamp;
                        tp->rx_opt.ts_recent = peer->tcp_ts;
                }
@@ -354,8 +358,8 @@ void tcp_v4_err(struct sk_buff *skb, u32 info)
        struct tcphdr *th = (struct tcphdr *)(skb->data + (iph->ihl << 2));
        struct tcp_sock *tp;
        struct inet_sock *inet;
-       int type = skb->h.icmph->type;
-       int code = skb->h.icmph->code;
+       const int type = icmp_hdr(skb)->type;
+       const int code = icmp_hdr(skb)->code;
        struct sock *sk;
        __u32 seq;
        int err;
@@ -499,11 +503,12 @@ out:
 void tcp_v4_send_check(struct sock *sk, int len, struct sk_buff *skb)
 {
        struct inet_sock *inet = inet_sk(sk);
-       struct tcphdr *th = skb->h.th;
+       struct tcphdr *th = tcp_hdr(skb);
 
        if (skb->ip_summed == CHECKSUM_PARTIAL) {
                th->check = ~tcp_v4_check(len, inet->saddr,
                                          inet->daddr, 0);
+               skb->csum_start = skb_transport_header(skb) - skb->head;
                skb->csum_offset = offsetof(struct tcphdr, check);
        } else {
                th->check = tcp_v4_check(len, inet->saddr, inet->daddr,
@@ -515,17 +520,18 @@ void tcp_v4_send_check(struct sock *sk, int len, struct sk_buff *skb)
 
 int tcp_v4_gso_send_check(struct sk_buff *skb)
 {
-       struct iphdr *iph;
+       const struct iphdr *iph;
        struct tcphdr *th;
 
        if (!pskb_may_pull(skb, sizeof(*th)))
                return -EINVAL;
 
-       iph = skb->nh.iph;
-       th = skb->h.th;
+       iph = ip_hdr(skb);
+       th = tcp_hdr(skb);
 
        th->check = 0;
        th->check = ~tcp_v4_check(skb->len, iph->saddr, iph->daddr, 0);
+       skb->csum_start = skb_transport_header(skb) - skb->head;
        skb->csum_offset = offsetof(struct tcphdr, check);
        skb->ip_summed = CHECKSUM_PARTIAL;
        return 0;
@@ -546,7 +552,7 @@ int tcp_v4_gso_send_check(struct sk_buff *skb)
 
 static void tcp_v4_send_reset(struct sock *sk, struct sk_buff *skb)
 {
-       struct tcphdr *th = skb->h.th;
+       struct tcphdr *th = tcp_hdr(skb);
        struct {
                struct tcphdr th;
 #ifdef CONFIG_TCP_MD5SIG
@@ -585,7 +591,7 @@ static void tcp_v4_send_reset(struct sock *sk, struct sk_buff *skb)
        arg.iov[0].iov_len  = sizeof(rep.th);
 
 #ifdef CONFIG_TCP_MD5SIG
-       key = sk ? tcp_v4_md5_do_lookup(sk, skb->nh.iph->daddr) : NULL;
+       key = sk ? tcp_v4_md5_do_lookup(sk, ip_hdr(skb)->daddr) : NULL;
        if (key) {
                rep.opt[0] = htonl((TCPOPT_NOP << 24) |
                                   (TCPOPT_NOP << 16) |
@@ -597,14 +603,14 @@ static void tcp_v4_send_reset(struct sock *sk, struct sk_buff *skb)
 
                tcp_v4_do_calc_md5_hash((__u8 *)&rep.opt[1],
                                        key,
-                                       skb->nh.iph->daddr,
-                                       skb->nh.iph->saddr,
+                                       ip_hdr(skb)->daddr,
+                                       ip_hdr(skb)->saddr,
                                        &rep.th, IPPROTO_TCP,
                                        arg.iov[0].iov_len);
        }
 #endif
-       arg.csum = csum_tcpudp_nofold(skb->nh.iph->daddr,
-                                     skb->nh.iph->saddr, /* XXX */
+       arg.csum = csum_tcpudp_nofold(ip_hdr(skb)->daddr,
+                                     ip_hdr(skb)->saddr, /* XXX */
                                      sizeof(struct tcphdr), IPPROTO_TCP, 0);
        arg.csumoffset = offsetof(struct tcphdr, check) / 2;
 
@@ -622,7 +628,7 @@ static void tcp_v4_send_ack(struct tcp_timewait_sock *twsk,
                            struct sk_buff *skb, u32 seq, u32 ack,
                            u32 win, u32 ts)
 {
-       struct tcphdr *th = skb->h.th;
+       struct tcphdr *th = tcp_hdr(skb);
        struct {
                struct tcphdr th;
                __be32 opt[(TCPOLEN_TSTAMP_ALIGNED >> 2)
@@ -670,7 +676,7 @@ static void tcp_v4_send_ack(struct tcp_timewait_sock *twsk,
         * skb->sk) holds true, but we program defensively.
         */
        if (!twsk && skb->sk) {
-               key = tcp_v4_md5_do_lookup(skb->sk, skb->nh.iph->daddr);
+               key = tcp_v4_md5_do_lookup(skb->sk, ip_hdr(skb)->daddr);
        } else if (twsk && twsk->tw_md5_keylen) {
                tw_key.key = twsk->tw_md5_key;
                tw_key.keylen = twsk->tw_md5_keylen;
@@ -690,16 +696,18 @@ static void tcp_v4_send_ack(struct tcp_timewait_sock *twsk,
 
                tcp_v4_do_calc_md5_hash((__u8 *)&rep.opt[offset],
                                        key,
-                                       skb->nh.iph->daddr,
-                                       skb->nh.iph->saddr,
+                                       ip_hdr(skb)->daddr,
+                                       ip_hdr(skb)->saddr,
                                        &rep.th, IPPROTO_TCP,
                                        arg.iov[0].iov_len);
        }
 #endif
-       arg.csum = csum_tcpudp_nofold(skb->nh.iph->daddr,
-                                     skb->nh.iph->saddr, /* XXX */
+       arg.csum = csum_tcpudp_nofold(ip_hdr(skb)->daddr,
+                                     ip_hdr(skb)->saddr, /* XXX */
                                      arg.iov[0].iov_len, IPPROTO_TCP, 0);
        arg.csumoffset = offsetof(struct tcphdr, check) / 2;
+       if (twsk)
+               arg.bound_dev_if = twsk->tw_sk.tw_bound_dev_if;
 
        ip_send_reply(tcp_socket->sk, skb, &arg, arg.iov[0].iov_len);
 
@@ -745,7 +753,7 @@ static int tcp_v4_send_synack(struct sock *sk, struct request_sock *req,
        skb = tcp_make_synack(sk, dst, req);
 
        if (skb) {
-               struct tcphdr *th = skb->h.th;
+               struct tcphdr *th = tcp_hdr(skb);
 
                th->check = tcp_v4_check(skb->len,
                                         ireq->loc_addr,
@@ -781,7 +789,7 @@ static void syn_flood_warning(struct sk_buff *skb)
                warntime = jiffies;
                printk(KERN_INFO
                       "possible SYN flooding on port %d. Sending cookies.\n",
-                      ntohs(skb->h.th->dest));
+                      ntohs(tcp_hdr(skb)->dest));
        }
 }
 #endif
@@ -826,8 +834,7 @@ static struct tcp_md5sig_key *
                return NULL;
        for (i = 0; i < tp->md5sig_info->entries4; i++) {
                if (tp->md5sig_info->keys4[i].addr == addr)
-                       return (struct tcp_md5sig_key *)
-                                               &tp->md5sig_info->keys4[i];
+                       return &tp->md5sig_info->keys4[i].base;
        }
        return NULL;
 }
@@ -858,9 +865,9 @@ int tcp_v4_md5_do_add(struct sock *sk, __be32 addr,
        key = (struct tcp4_md5sig_key *)tcp_v4_md5_do_lookup(sk, addr);
        if (key) {
                /* Pre-existing entry - just update that one. */
-               kfree(key->key);
-               key->key = newkey;
-               key->keylen = newkeylen;
+               kfree(key->base.key);
+               key->base.key = newkey;
+               key->base.keylen = newkeylen;
        } else {
                struct tcp_md5sig_info *md5sig;
 
@@ -871,6 +878,7 @@ int tcp_v4_md5_do_add(struct sock *sk, __be32 addr,
                                kfree(newkey);
                                return -ENOMEM;
                        }
+                       sk->sk_route_caps &= ~NETIF_F_GSO_MASK;
                }
                if (tcp_alloc_md5sig_pool() == NULL) {
                        kfree(newkey);
@@ -898,9 +906,9 @@ int tcp_v4_md5_do_add(struct sock *sk, __be32 addr,
                        md5sig->alloced4++;
                }
                md5sig->entries4++;
-               md5sig->keys4[md5sig->entries4 - 1].addr   = addr;
-               md5sig->keys4[md5sig->entries4 - 1].key    = newkey;
-               md5sig->keys4[md5sig->entries4 - 1].keylen = newkeylen;
+               md5sig->keys4[md5sig->entries4 - 1].addr        = addr;
+               md5sig->keys4[md5sig->entries4 - 1].base.key    = newkey;
+               md5sig->keys4[md5sig->entries4 - 1].base.keylen = newkeylen;
        }
        return 0;
 }
@@ -922,7 +930,7 @@ int tcp_v4_md5_do_del(struct sock *sk, __be32 addr)
        for (i = 0; i < tp->md5sig_info->entries4; i++) {
                if (tp->md5sig_info->keys4[i].addr == addr) {
                        /* Free the key */
-                       kfree(tp->md5sig_info->keys4[i].key);
+                       kfree(tp->md5sig_info->keys4[i].base.key);
                        tp->md5sig_info->entries4--;
 
                        if (tp->md5sig_info->entries4 == 0) {
@@ -956,7 +964,7 @@ static void tcp_v4_clear_md5_list(struct sock *sk)
        if (tp->md5sig_info->entries4) {
                int i;
                for (i = 0; i < tp->md5sig_info->entries4; i++)
-                       kfree(tp->md5sig_info->keys4[i].key);
+                       kfree(tp->md5sig_info->keys4[i].base.key);
                tp->md5sig_info->entries4 = 0;
                tcp_free_md5sig_pool();
        }
@@ -1000,7 +1008,7 @@ static int tcp_v4_parse_md5_keys(struct sock *sk, char __user *optval,
                        return -EINVAL;
 
                tp->md5sig_info = p;
-
+               sk->sk_route_caps &= ~NETIF_F_GSO_MASK;
        }
 
        newkey = kmemdup(cmd.tcpm_key, cmd.tcpm_keylen, GFP_KERNEL);
@@ -1047,6 +1055,9 @@ static int tcp_v4_do_calc_md5_hash(char *md5_hash, struct tcp_md5sig_key *key,
        bp->pad = 0;
        bp->protocol = protocol;
        bp->len = htons(tcplen);
+
+       sg_init_table(sg, 4);
+
        sg_set_buf(&sg[block++], bp, sizeof(*bp));
        nbytes += sizeof(*bp);
 
@@ -1072,6 +1083,8 @@ static int tcp_v4_do_calc_md5_hash(char *md5_hash, struct tcp_md5sig_key *key,
        sg_set_buf(&sg[block++], key->key, key->keylen);
        nbytes += key->keylen;
 
+       sg_mark_end(sg, block);
+
        /* Now store the Hash into the packet */
        err = crypto_hash_init(desc);
        if (err)
@@ -1133,8 +1146,8 @@ static int tcp_v4_inbound_md5_hash(struct sock *sk, struct sk_buff *skb)
         */
        __u8 *hash_location = NULL;
        struct tcp_md5sig_key *hash_expected;
-       struct iphdr *iph = skb->nh.iph;
-       struct tcphdr *th = skb->h.th;
+       const struct iphdr *iph = ip_hdr(skb);
+       struct tcphdr *th = tcp_hdr(skb);
        int length = (th->doff << 2) - sizeof(struct tcphdr);
        int genhash;
        unsigned char *ptr;
@@ -1251,8 +1264,8 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb)
        struct inet_request_sock *ireq;
        struct tcp_options_received tmp_opt;
        struct request_sock *req;
-       __be32 saddr = skb->nh.iph->saddr;
-       __be32 daddr = skb->nh.iph->daddr;
+       __be32 saddr = ip_hdr(skb)->saddr;
+       __be32 daddr = ip_hdr(skb)->daddr;
        __u32 isn = TCP_SKB_CB(skb)->when;
        struct dst_entry *dst = NULL;
 #ifdef CONFIG_SYN_COOKIES
@@ -1327,7 +1340,7 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb)
        ireq->rmt_addr = saddr;
        ireq->opt = tcp_v4_save_options(sk, skb);
        if (!want_cookie)
-               TCP_ECN_create_request(req, skb->h.th);
+               TCP_ECN_create_request(req, tcp_hdr(skb));
 
        if (want_cookie) {
 #ifdef CONFIG_SYN_COOKIES
@@ -1351,7 +1364,7 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb)
                    (dst = inet_csk_route_req(sk, req)) != NULL &&
                    (peer = rt_get_peer((struct rtable *)dst)) != NULL &&
                    peer->v4daddr == saddr) {
-                       if (xtime.tv_sec < peer->tcp_ts_stamp + TCP_PAWS_MSL &&
+                       if (get_seconds() < peer->tcp_ts_stamp + TCP_PAWS_MSL &&
                            (s32)(peer->tcp_ts - req->ts_recent) >
                                                        TCP_PAWS_WINDOW) {
                                NET_INC_STATS_BH(LINUX_MIB_PAWSPASSIVEREJECTED);
@@ -1375,7 +1388,7 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb)
                        LIMIT_NETDEBUG(KERN_DEBUG "TCP: drop open "
                                       "request from %u.%u.%u.%u/%u\n",
                                       NIPQUAD(saddr),
-                                      ntohs(skb->h.th->source));
+                                      ntohs(tcp_hdr(skb)->source));
                        dst_release(dst);
                        goto drop_and_free;
                }
@@ -1439,7 +1452,7 @@ struct sock *tcp_v4_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
        newinet->opt          = ireq->opt;
        ireq->opt             = NULL;
        newinet->mc_index     = inet_iif(skb);
-       newinet->mc_ttl       = skb->nh.iph->ttl;
+       newinet->mc_ttl       = ip_hdr(skb)->ttl;
        inet_csk(newsk)->icsk_ext_hdr_len = 0;
        if (newinet->opt)
                inet_csk(newsk)->icsk_ext_hdr_len = newinet->opt->optlen;
@@ -1481,8 +1494,8 @@ exit:
 
 static struct sock *tcp_v4_hnd_req(struct sock *sk, struct sk_buff *skb)
 {
-       struct tcphdr *th = skb->h.th;
-       struct iphdr *iph = skb->nh.iph;
+       struct tcphdr *th = tcp_hdr(skb);
+       const struct iphdr *iph = ip_hdr(skb);
        struct sock *nsk;
        struct request_sock **prev;
        /* Find possible connection requests. */
@@ -1491,9 +1504,8 @@ static struct sock *tcp_v4_hnd_req(struct sock *sk, struct sk_buff *skb)
        if (req)
                return tcp_check_req(sk, skb, req, prev);
 
-       nsk = inet_lookup_established(&tcp_hashinfo, skb->nh.iph->saddr,
-                                     th->source, skb->nh.iph->daddr,
-                                     th->dest, inet_iif(skb));
+       nsk = inet_lookup_established(&tcp_hashinfo, iph->saddr, th->source,
+                                     iph->daddr, th->dest, inet_iif(skb));
 
        if (nsk) {
                if (nsk->sk_state != TCP_TIME_WAIT) {
@@ -1513,15 +1525,17 @@ static struct sock *tcp_v4_hnd_req(struct sock *sk, struct sk_buff *skb)
 
 static __sum16 tcp_v4_checksum_init(struct sk_buff *skb)
 {
+       const struct iphdr *iph = ip_hdr(skb);
+
        if (skb->ip_summed == CHECKSUM_COMPLETE) {
-               if (!tcp_v4_check(skb->len, skb->nh.iph->saddr,
-                                 skb->nh.iph->daddr, skb->csum)) {
+               if (!tcp_v4_check(skb->len, iph->saddr,
+                                 iph->daddr, skb->csum)) {
                        skb->ip_summed = CHECKSUM_UNNECESSARY;
                        return 0;
                }
        }
 
-       skb->csum = csum_tcpudp_nofold(skb->nh.iph->saddr, skb->nh.iph->daddr,
+       skb->csum = csum_tcpudp_nofold(iph->saddr, iph->daddr,
                                       skb->len, IPPROTO_TCP, 0);
 
        if (skb->len <= 76) {
@@ -1555,7 +1569,7 @@ int tcp_v4_do_rcv(struct sock *sk, struct sk_buff *skb)
 
        if (sk->sk_state == TCP_ESTABLISHED) { /* Fast path */
                TCP_CHECK_TIMER(sk);
-               if (tcp_rcv_established(sk, skb, skb->h.th, skb->len)) {
+               if (tcp_rcv_established(sk, skb, tcp_hdr(skb), skb->len)) {
                        rsk = sk;
                        goto reset;
                }
@@ -1563,7 +1577,7 @@ int tcp_v4_do_rcv(struct sock *sk, struct sk_buff *skb)
                return 0;
        }
 
-       if (skb->len < (skb->h.th->doff << 2) || tcp_checksum_complete(skb))
+       if (skb->len < tcp_hdrlen(skb) || tcp_checksum_complete(skb))
                goto csum_err;
 
        if (sk->sk_state == TCP_LISTEN) {
@@ -1581,7 +1595,7 @@ int tcp_v4_do_rcv(struct sock *sk, struct sk_buff *skb)
        }
 
        TCP_CHECK_TIMER(sk);
-       if (tcp_rcv_state_process(sk, skb, skb->h.th, skb->len)) {
+       if (tcp_rcv_state_process(sk, skb, tcp_hdr(skb), skb->len)) {
                rsk = sk;
                goto reset;
        }
@@ -1610,6 +1624,7 @@ csum_err:
 
 int tcp_v4_rcv(struct sk_buff *skb)
 {
+       const struct iphdr *iph;
        struct tcphdr *th;
        struct sock *sk;
        int ret;
@@ -1623,7 +1638,7 @@ int tcp_v4_rcv(struct sk_buff *skb)
        if (!pskb_may_pull(skb, sizeof(struct tcphdr)))
                goto discard_it;
 
-       th = skb->h.th;
+       th = tcp_hdr(skb);
 
        if (th->doff < sizeof(struct tcphdr) / 4)
                goto bad_packet;
@@ -1634,23 +1649,21 @@ int tcp_v4_rcv(struct sk_buff *skb)
         * Packet length and doff are validated by header prediction,
         * provided case of th->doff==0 is eliminated.
         * So, we defer the checks. */
-       if ((skb->ip_summed != CHECKSUM_UNNECESSARY &&
-            tcp_v4_checksum_init(skb)))
+       if (!skb_csum_unnecessary(skb) && tcp_v4_checksum_init(skb))
                goto bad_packet;
 
-       th = skb->h.th;
+       th = tcp_hdr(skb);
+       iph = ip_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   = skb->nh.iph->tos;
+       TCP_SKB_CB(skb)->flags   = iph->tos;
        TCP_SKB_CB(skb)->sacked  = 0;
 
-       sk = __inet_lookup(&tcp_hashinfo, skb->nh.iph->saddr, th->source,
-                          skb->nh.iph->daddr, th->dest,
-                          inet_iif(skb));
-
+       sk = __inet_lookup(&tcp_hashinfo, iph->saddr, th->source,
+                          iph->daddr, th->dest, inet_iif(skb));
        if (!sk)
                goto no_tcp_socket;
 
@@ -1724,8 +1737,7 @@ do_time_wait:
        switch (tcp_timewait_state_process(inet_twsk(sk), skb, th)) {
        case TCP_TW_SYN: {
                struct sock *sk2 = inet_lookup_listener(&tcp_hashinfo,
-                                                       skb->nh.iph->daddr,
-                                                       th->dest,
+                                                       iph->daddr, th->dest,
                                                        inet_iif(skb));
                if (sk2) {
                        inet_twsk_deschedule(inet_twsk(sk), &tcp_death_row);
@@ -1770,7 +1782,7 @@ int tcp_v4_remember_stamp(struct sock *sk)
 
        if (peer) {
                if ((s32)(peer->tcp_ts - tp->rx_opt.ts_recent) <= 0 ||
-                   (peer->tcp_ts_stamp + TCP_PAWS_MSL < xtime.tv_sec &&
+                   (peer->tcp_ts_stamp + TCP_PAWS_MSL < get_seconds() &&
                     peer->tcp_ts_stamp <= tp->rx_opt.ts_recent_stamp)) {
                        peer->tcp_ts_stamp = tp->rx_opt.ts_recent_stamp;
                        peer->tcp_ts = tp->rx_opt.ts_recent;
@@ -1791,7 +1803,7 @@ int tcp_v4_tw_remember_stamp(struct inet_timewait_sock *tw)
                const struct tcp_timewait_sock *tcptw = tcp_twsk((struct sock *)tw);
 
                if ((s32)(peer->tcp_ts - tcptw->tw_ts_recent) <= 0 ||
-                   (peer->tcp_ts_stamp + TCP_PAWS_MSL < xtime.tv_sec &&
+                   (peer->tcp_ts_stamp + TCP_PAWS_MSL < get_seconds() &&
                     peer->tcp_ts_stamp <= tcptw->tw_ts_recent_stamp)) {
                        peer->tcp_ts_stamp = tcptw->tw_ts_recent_stamp;
                        peer->tcp_ts       = tcptw->tw_ts_recent;
@@ -1890,7 +1902,7 @@ int tcp_v4_destroy_sock(struct sock *sk)
        tcp_cleanup_congestion_control(sk);
 
        /* Cleanup up the write buffer. */
-       sk_stream_writequeue_purge(sk);
+       tcp_write_queue_purge(sk);
 
        /* Cleans up our, hopefully empty, out_of_order_queue. */
        __skb_queue_purge(&tp->out_of_order_queue);
@@ -2038,10 +2050,7 @@ static void *established_get_first(struct seq_file *seq)
                struct hlist_node *node;
                struct inet_timewait_sock *tw;
 
-               /* We can reschedule _before_ having picked the target: */
-               cond_resched_softirq();
-
-               read_lock(&tcp_hashinfo.ehash[st->bucket].lock);
+               read_lock_bh(&tcp_hashinfo.ehash[st->bucket].lock);
                sk_for_each(sk, node, &tcp_hashinfo.ehash[st->bucket].chain) {
                        if (sk->sk_family != st->family) {
                                continue;
@@ -2058,7 +2067,7 @@ static void *established_get_first(struct seq_file *seq)
                        rc = tw;
                        goto out;
                }
-               read_unlock(&tcp_hashinfo.ehash[st->bucket].lock);
+               read_unlock_bh(&tcp_hashinfo.ehash[st->bucket].lock);
                st->state = TCP_SEQ_STATE_ESTABLISHED;
        }
 out:
@@ -2085,14 +2094,11 @@ get_tw:
                        cur = tw;
                        goto out;
                }
-               read_unlock(&tcp_hashinfo.ehash[st->bucket].lock);
+               read_unlock_bh(&tcp_hashinfo.ehash[st->bucket].lock);
                st->state = TCP_SEQ_STATE_ESTABLISHED;
 
-               /* We can reschedule between buckets: */
-               cond_resched_softirq();
-
                if (++st->bucket < tcp_hashinfo.ehash_size) {
-                       read_lock(&tcp_hashinfo.ehash[st->bucket].lock);
+                       read_lock_bh(&tcp_hashinfo.ehash[st->bucket].lock);
                        sk = sk_head(&tcp_hashinfo.ehash[st->bucket].chain);
                } else {
                        cur = NULL;
@@ -2137,7 +2143,6 @@ static void *tcp_get_idx(struct seq_file *seq, loff_t pos)
 
        if (!rc) {
                inet_listen_unlock(&tcp_hashinfo);
-               local_bh_disable();
                st->state = TCP_SEQ_STATE_ESTABLISHED;
                rc        = established_get_idx(seq, pos);
        }
@@ -2170,7 +2175,6 @@ static void *tcp_seq_next(struct seq_file *seq, void *v, loff_t *pos)
                rc = listening_get_next(seq, v);
                if (!rc) {
                        inet_listen_unlock(&tcp_hashinfo);
-                       local_bh_disable();
                        st->state = TCP_SEQ_STATE_ESTABLISHED;
                        rc        = established_get_first(seq);
                }
@@ -2202,8 +2206,7 @@ static void tcp_seq_stop(struct seq_file *seq, void *v)
        case TCP_SEQ_STATE_TIME_WAIT:
        case TCP_SEQ_STATE_ESTABLISHED:
                if (v)
-                       read_unlock(&tcp_hashinfo.ehash[st->bucket].lock);
-               local_bh_enable();
+                       read_unlock_bh(&tcp_hashinfo.ehash[st->bucket].lock);
                break;
        }
 }
@@ -2252,7 +2255,7 @@ int tcp_proc_register(struct tcp_seq_afinfo *afinfo)
        afinfo->seq_fops->llseek        = seq_lseek;
        afinfo->seq_fops->release       = seq_release_private;
 
-       p = proc_net_fops_create(afinfo->name, S_IRUGO, afinfo->seq_fops);
+       p = proc_net_fops_create(&init_net, afinfo->name, S_IRUGO, afinfo->seq_fops);
        if (p)
                p->data = afinfo;
        else
@@ -2264,7 +2267,7 @@ void tcp_proc_unregister(struct tcp_seq_afinfo *afinfo)
 {
        if (!afinfo)
                return;
-       proc_net_remove(afinfo->name);
+       proc_net_remove(&init_net, afinfo->name);
        memset(afinfo->seq_fops, 0, sizeof(*afinfo->seq_fops));
 }
 
@@ -2427,7 +2430,6 @@ struct proto tcp_prot = {
        .shutdown               = tcp_shutdown,
        .setsockopt             = tcp_setsockopt,
        .getsockopt             = tcp_getsockopt,
-       .sendmsg                = tcp_sendmsg,
        .recvmsg                = tcp_recvmsg,
        .backlog_rcv            = tcp_v4_do_rcv,
        .hash                   = tcp_v4_hash,
@@ -2473,6 +2475,5 @@ EXPORT_SYMBOL(tcp_v4_syn_recv_sock);
 EXPORT_SYMBOL(tcp_proc_register);
 EXPORT_SYMBOL(tcp_proc_unregister);
 #endif
-EXPORT_SYMBOL(sysctl_local_port_range);
 EXPORT_SYMBOL(sysctl_tcp_low_latency);