]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blobdiff - net/ipv6/tcp_ipv6.c
net: tcp: rename TCP_INC_STATS_BH
[mirror_ubuntu-bionic-kernel.git] / net / ipv6 / tcp_ipv6.c
index 5c8c842730286ea4212222769d124f9e3d611333..52ca8fac74291ceaece20322d314caef6e7f6316 100644 (file)
@@ -66,7 +66,7 @@
 #include <linux/proc_fs.h>
 #include <linux/seq_file.h>
 
-#include <linux/crypto.h>
+#include <crypto/hash.h>
 #include <linux/scatterlist.h>
 
 static void    tcp_v6_send_reset(const struct sock *sk, struct sk_buff *skb);
@@ -234,7 +234,7 @@ static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr,
        fl6.fl6_dport = usin->sin6_port;
        fl6.fl6_sport = inet->inet_sport;
 
-       opt = rcu_dereference_protected(np->opt, sock_owned_by_user(sk));
+       opt = rcu_dereference_protected(np->opt, lockdep_sock_is_held(sk));
        final_p = fl6_update_dst(&fl6, opt, &final);
 
        security_sk_classify_flow(sk, flowi6_to_flowi(&fl6));
@@ -439,7 +439,7 @@ static int tcp_v6_send_synack(const struct sock *sk, struct dst_entry *dst,
                              struct flowi *fl,
                              struct request_sock *req,
                              struct tcp_fastopen_cookie *foc,
-                             bool attach_req)
+                             enum tcp_synack_type synack_type)
 {
        struct inet_request_sock *ireq = inet_rsk(req);
        struct ipv6_pinfo *np = inet6_sk(sk);
@@ -452,7 +452,7 @@ static int tcp_v6_send_synack(const struct sock *sk, struct dst_entry *dst,
                                               IPPROTO_TCP)) == NULL)
                goto done;
 
-       skb = tcp_make_synack(sk, dst, req, foc, attach_req);
+       skb = tcp_make_synack(sk, dst, req, foc, synack_type);
 
        if (skb) {
                __tcp_v6_send_check(skb, &ireq->ir_v6_loc_addr,
@@ -541,7 +541,8 @@ static int tcp_v6_md5_hash_pseudoheader(struct tcp_md5sig_pool *hp,
        bp->len = cpu_to_be32(nbytes);
 
        sg_init_one(&sg, bp, sizeof(*bp));
-       return crypto_hash_update(&hp->md5_desc, &sg, sizeof(*bp));
+       ahash_request_set_crypt(hp->md5_req, &sg, NULL, sizeof(*bp));
+       return crypto_ahash_update(hp->md5_req);
 }
 
 static int tcp_v6_md5_hash_hdr(char *md5_hash, struct tcp_md5sig_key *key,
@@ -549,14 +550,14 @@ static int tcp_v6_md5_hash_hdr(char *md5_hash, struct tcp_md5sig_key *key,
                               const struct tcphdr *th)
 {
        struct tcp_md5sig_pool *hp;
-       struct hash_desc *desc;
+       struct ahash_request *req;
 
        hp = tcp_get_md5sig_pool();
        if (!hp)
                goto clear_hash_noput;
-       desc = &hp->md5_desc;
+       req = hp->md5_req;
 
-       if (crypto_hash_init(desc))
+       if (crypto_ahash_init(req))
                goto clear_hash;
        if (tcp_v6_md5_hash_pseudoheader(hp, daddr, saddr, th->doff << 2))
                goto clear_hash;
@@ -564,7 +565,8 @@ static int tcp_v6_md5_hash_hdr(char *md5_hash, struct tcp_md5sig_key *key,
                goto clear_hash;
        if (tcp_md5_hash_key(hp, key))
                goto clear_hash;
-       if (crypto_hash_final(desc, md5_hash))
+       ahash_request_set_crypt(req, NULL, md5_hash, 0);
+       if (crypto_ahash_final(req))
                goto clear_hash;
 
        tcp_put_md5sig_pool();
@@ -584,7 +586,7 @@ static int tcp_v6_md5_hash_skb(char *md5_hash,
 {
        const struct in6_addr *saddr, *daddr;
        struct tcp_md5sig_pool *hp;
-       struct hash_desc *desc;
+       struct ahash_request *req;
        const struct tcphdr *th = tcp_hdr(skb);
 
        if (sk) { /* valid for establish/request sockets */
@@ -599,9 +601,9 @@ static int tcp_v6_md5_hash_skb(char *md5_hash,
        hp = tcp_get_md5sig_pool();
        if (!hp)
                goto clear_hash_noput;
-       desc = &hp->md5_desc;
+       req = hp->md5_req;
 
-       if (crypto_hash_init(desc))
+       if (crypto_ahash_init(req))
                goto clear_hash;
 
        if (tcp_v6_md5_hash_pseudoheader(hp, daddr, saddr, skb->len))
@@ -612,7 +614,8 @@ static int tcp_v6_md5_hash_skb(char *md5_hash,
                goto clear_hash;
        if (tcp_md5_hash_key(hp, key))
                goto clear_hash;
-       if (crypto_hash_final(desc, md5_hash))
+       ahash_request_set_crypt(req, NULL, md5_hash, 0);
+       if (crypto_ahash_final(req))
                goto clear_hash;
 
        tcp_put_md5sig_pool();
@@ -822,9 +825,9 @@ static void tcp_v6_send_response(const struct sock *sk, struct sk_buff *skb, u32
        if (!IS_ERR(dst)) {
                skb_dst_set(buff, dst);
                ip6_xmit(ctl_sk, buff, &fl6, NULL, tclass);
-               TCP_INC_STATS_BH(net, TCP_MIB_OUTSEGS);
+               __TCP_INC_STATS(net, TCP_MIB_OUTSEGS);
                if (rst)
-                       TCP_INC_STATS_BH(net, TCP_MIB_OUTRSTS);
+                       __TCP_INC_STATS(net, TCP_MIB_OUTRSTS);
                return;
        }
 
@@ -855,6 +858,7 @@ static void tcp_v6_send_reset(const struct sock *sk, struct sk_buff *skb)
                return;
 
 #ifdef CONFIG_TCP_MD5SIG
+       rcu_read_lock();
        hash_location = tcp_parse_md5sig_option(th);
        if (sk && sk_fullsock(sk)) {
                key = tcp_v6_md5_do_lookup(sk, &ipv6h->saddr);
@@ -867,20 +871,20 @@ static void tcp_v6_send_reset(const struct sock *sk, struct sk_buff *skb)
                 * no RST generated if md5 hash doesn't match.
                 */
                sk1 = inet6_lookup_listener(dev_net(skb_dst(skb)->dev),
-                                          &tcp_hashinfo, &ipv6h->saddr,
+                                          &tcp_hashinfo, NULL, 0,
+                                          &ipv6h->saddr,
                                           th->source, &ipv6h->daddr,
                                           ntohs(th->source), tcp_v6_iif(skb));
                if (!sk1)
-                       return;
+                       goto out;
 
-               rcu_read_lock();
                key = tcp_v6_md5_do_lookup(sk1, &ipv6h->saddr);
                if (!key)
-                       goto release_sk1;
+                       goto out;
 
                genhash = tcp_v6_md5_hash_skb(newhash, key, NULL, skb);
                if (genhash || memcmp(hash_location, newhash, 16) != 0)
-                       goto release_sk1;
+                       goto out;
        }
 #endif
 
@@ -894,11 +898,8 @@ static void tcp_v6_send_reset(const struct sock *sk, struct sk_buff *skb)
        tcp_v6_send_response(sk, skb, seq, ack_seq, 0, 0, 0, oif, key, 1, 0, 0);
 
 #ifdef CONFIG_TCP_MD5SIG
-release_sk1:
-       if (sk1) {
-               rcu_read_unlock();
-               sock_put(sk1);
-       }
+out:
+       rcu_read_unlock();
 #endif
 }
 
@@ -963,7 +964,7 @@ static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb)
                                &tcp_request_sock_ipv6_ops, sk, skb);
 
 drop:
-       NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENDROPS);
+       tcp_listendrop(sk);
        return 0; /* don't send reset */
 }
 
@@ -1168,7 +1169,7 @@ out_overflow:
 out_nonewsk:
        dst_release(dst);
 out:
-       NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENDROPS);
+       tcp_listendrop(sk);
        return NULL;
 }
 
@@ -1275,8 +1276,8 @@ discard:
        kfree_skb(skb);
        return 0;
 csum_err:
-       TCP_INC_STATS_BH(sock_net(sk), TCP_MIB_CSUMERRORS);
-       TCP_INC_STATS_BH(sock_net(sk), TCP_MIB_INERRS);
+       __TCP_INC_STATS(sock_net(sk), TCP_MIB_CSUMERRORS);
+       __TCP_INC_STATS(sock_net(sk), TCP_MIB_INERRS);
        goto discard;
 
 
@@ -1347,6 +1348,7 @@ static int tcp_v6_rcv(struct sk_buff *skb)
 {
        const struct tcphdr *th;
        const struct ipv6hdr *hdr;
+       bool refcounted;
        struct sock *sk;
        int ret;
        struct net *net = dev_net(skb->dev);
@@ -1357,7 +1359,7 @@ static int tcp_v6_rcv(struct sk_buff *skb)
        /*
         *      Count it even if it's bad.
         */
-       TCP_INC_STATS_BH(net, TCP_MIB_INSEGS);
+       __TCP_INC_STATS(net, TCP_MIB_INSEGS);
 
        if (!pskb_may_pull(skb, sizeof(struct tcphdr)))
                goto discard_it;
@@ -1376,8 +1378,9 @@ static int tcp_v6_rcv(struct sk_buff *skb)
        hdr = ipv6_hdr(skb);
 
 lookup:
-       sk = __inet6_lookup_skb(&tcp_hashinfo, skb, th->source, th->dest,
-                               inet6_iif(skb));
+       sk = __inet6_lookup_skb(&tcp_hashinfo, skb, __tcp_hdrlen(th),
+                               th->source, th->dest, inet6_iif(skb),
+                               &refcounted);
        if (!sk)
                goto no_tcp_socket;
 
@@ -1400,6 +1403,7 @@ process:
                        goto lookup;
                }
                sock_hold(sk);
+               refcounted = true;
                nsk = tcp_check_req(sk, skb, req, false);
                if (!nsk) {
                        reqsk_put(req);
@@ -1442,7 +1446,7 @@ process:
        sk_incoming_cpu_update(sk);
 
        bh_lock_sock_nested(sk);
-       tcp_sk(sk)->segs_in += max_t(u16, 1, skb_shinfo(skb)->gso_segs);
+       tcp_segs_in(tcp_sk(sk), skb);
        ret = 0;
        if (!sock_owned_by_user(sk)) {
                if (!tcp_prequeue(sk, skb))
@@ -1456,7 +1460,8 @@ process:
        bh_unlock_sock(sk);
 
 put_and_return:
-       sock_put(sk);
+       if (refcounted)
+               sock_put(sk);
        return ret ? -1 : 0;
 
 no_tcp_socket:
@@ -1467,9 +1472,9 @@ no_tcp_socket:
 
        if (tcp_checksum_complete(skb)) {
 csum_error:
-               TCP_INC_STATS_BH(net, TCP_MIB_CSUMERRORS);
+               __TCP_INC_STATS(net, TCP_MIB_CSUMERRORS);
 bad_packet:
-               TCP_INC_STATS_BH(net, TCP_MIB_INERRS);
+               __TCP_INC_STATS(net, TCP_MIB_INERRS);
        } else {
                tcp_v6_send_reset(NULL, skb);
        }
@@ -1479,7 +1484,9 @@ discard_it:
        return 0;
 
 discard_and_relse:
-       sock_put(sk);
+       sk_drops_add(sk, skb);
+       if (refcounted)
+               sock_put(sk);
        goto discard_it;
 
 do_time_wait:
@@ -1501,6 +1508,7 @@ do_time_wait:
                struct sock *sk2;
 
                sk2 = inet6_lookup_listener(dev_net(skb->dev), &tcp_hashinfo,
+                                           skb, __tcp_hdrlen(th),
                                            &ipv6_hdr(skb)->saddr, th->source,
                                            &ipv6_hdr(skb)->daddr,
                                            ntohs(th->dest), tcp_v6_iif(skb));
@@ -1509,6 +1517,7 @@ do_time_wait:
                        inet_twsk_deschedule_put(tw);
                        sk = sk2;
                        tcp_v6_restore_cb(skb);
+                       refcounted = false;
                        goto process;
                }
                /* Fall through to ACK */
@@ -1866,7 +1875,7 @@ struct proto tcpv6_prot = {
        .sendpage               = tcp_sendpage,
        .backlog_rcv            = tcp_v6_do_rcv,
        .release_cb             = tcp_release_cb,
-       .hash                   = inet_hash,
+       .hash                   = inet6_hash,
        .unhash                 = inet_unhash,
        .get_port               = inet_csk_get_port,
        .enter_memory_pressure  = tcp_enter_memory_pressure,