]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - net/ipv6/tcp_ipv6.c
net: convert BUG_TRAP to generic WARN_ON
[linux-2.6-omap-h63xx.git] / net / ipv6 / tcp_ipv6.c
index 30dbab7cc3ccafbeb5d17a98ab5c3d13495bba36..cff778b23a7feca249b9edab81c9d6afdee8597b 100644 (file)
@@ -323,8 +323,9 @@ static void tcp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
        int err;
        struct tcp_sock *tp;
        __u32 seq;
+       struct net *net = dev_net(skb->dev);
 
-       sk = inet6_lookup(dev_net(skb->dev), &tcp_hashinfo, &hdr->daddr,
+       sk = inet6_lookup(net, &tcp_hashinfo, &hdr->daddr,
                        th->dest, &hdr->saddr, th->source, skb->dev->ifindex);
 
        if (sk == NULL) {
@@ -339,7 +340,7 @@ static void tcp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
 
        bh_lock_sock(sk);
        if (sock_owned_by_user(sk))
-               NET_INC_STATS_BH(LINUX_MIB_LOCKDROPPEDICMPS);
+               NET_INC_STATS_BH(net, LINUX_MIB_LOCKDROPPEDICMPS);
 
        if (sk->sk_state == TCP_CLOSE)
                goto out;
@@ -348,7 +349,7 @@ static void tcp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
        seq = ntohl(th->seq);
        if (sk->sk_state != TCP_LISTEN &&
            !between(seq, tp->snd_una, tp->snd_nxt)) {
-               NET_INC_STATS_BH(LINUX_MIB_OUTOFWINDOWICMPS);
+               NET_INC_STATS_BH(net, LINUX_MIB_OUTOFWINDOWICMPS);
                goto out;
        }
 
@@ -420,10 +421,10 @@ static void tcp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
                /* ICMPs are not backlogged, hence we cannot get
                 * an established socket here.
                 */
-               BUG_TRAP(req->sk == NULL);
+               WARN_ON(req->sk != NULL);
 
                if (seq != tcp_rsk(req)->snt_isn) {
-                       NET_INC_STATS_BH(LINUX_MIB_OUTOFWINDOWICMPS);
+                       NET_INC_STATS_BH(net, LINUX_MIB_OUTOFWINDOWICMPS);
                        goto out;
                }
 
@@ -735,64 +736,105 @@ static int tcp_v6_parse_md5_keys (struct sock *sk, char __user *optval,
        return tcp_v6_md5_do_add(sk, &sin6->sin6_addr, newkey, cmd.tcpm_keylen);
 }
 
-static int tcp_v6_do_calc_md5_hash(char *md5_hash, struct tcp_md5sig_key *key,
-                                  struct in6_addr *saddr,
-                                  struct in6_addr *daddr,
-                                  struct tcphdr *th, unsigned int tcplen)
+static int tcp_v6_md5_hash_pseudoheader(struct tcp_md5sig_pool *hp,
+                                       struct in6_addr *daddr,
+                                       struct in6_addr *saddr, int nbytes)
 {
-       struct tcp_md5sig_pool *hp;
        struct tcp6_pseudohdr *bp;
-       int err;
-
-       hp = tcp_get_md5sig_pool();
-       if (!hp) {
-               printk(KERN_WARNING "%s(): hash pool not found...\n", __func__);
-               goto clear_hash_noput;
-       }
+       struct scatterlist sg;
 
        bp = &hp->md5_blk.ip6;
-
        /* 1. TCP pseudo-header (RFC2460) */
        ipv6_addr_copy(&bp->saddr, saddr);
        ipv6_addr_copy(&bp->daddr, daddr);
-       bp->len = htonl(tcplen);
-       bp->protocol = htonl(IPPROTO_TCP);
+       bp->protocol = cpu_to_be32(IPPROTO_TCP);
+       bp->len = cpu_to_be16(nbytes);
 
-       err = tcp_calc_md5_hash(md5_hash, key, sizeof(*bp),
-                               th, tcplen, hp);
+       sg_init_one(&sg, bp, sizeof(*bp));
+       return crypto_hash_update(&hp->md5_desc, &sg, sizeof(*bp));
+}
 
-       if (err)
+static int tcp_v6_md5_hash_hdr(char *md5_hash, struct tcp_md5sig_key *key,
+                              struct in6_addr *daddr, struct in6_addr *saddr,
+                              struct tcphdr *th)
+{
+       struct tcp_md5sig_pool *hp;
+       struct hash_desc *desc;
+
+       hp = tcp_get_md5sig_pool();
+       if (!hp)
+               goto clear_hash_noput;
+       desc = &hp->md5_desc;
+
+       if (crypto_hash_init(desc))
+               goto clear_hash;
+       if (tcp_v6_md5_hash_pseudoheader(hp, daddr, saddr, th->doff << 2))
+               goto clear_hash;
+       if (tcp_md5_hash_header(hp, th))
+               goto clear_hash;
+       if (tcp_md5_hash_key(hp, key))
+               goto clear_hash;
+       if (crypto_hash_final(desc, md5_hash))
                goto clear_hash;
 
-       /* Free up the crypto pool */
        tcp_put_md5sig_pool();
-out:
        return 0;
+
 clear_hash:
        tcp_put_md5sig_pool();
 clear_hash_noput:
        memset(md5_hash, 0, 16);
-       goto out;
+       return 1;
 }
 
-static int tcp_v6_calc_md5_hash(char *md5_hash, struct tcp_md5sig_key *key,
-                               struct sock *sk,
-                               struct dst_entry *dst,
-                               struct request_sock *req,
-                               struct tcphdr *th, unsigned int tcplen)
+static int tcp_v6_md5_hash_skb(char *md5_hash, struct tcp_md5sig_key *key,
+                              struct sock *sk, struct request_sock *req,
+                              struct sk_buff *skb)
 {
        struct in6_addr *saddr, *daddr;
+       struct tcp_md5sig_pool *hp;
+       struct hash_desc *desc;
+       struct tcphdr *th = tcp_hdr(skb);
 
        if (sk) {
                saddr = &inet6_sk(sk)->saddr;
                daddr = &inet6_sk(sk)->daddr;
-       } else {
+       } else if (req) {
                saddr = &inet6_rsk(req)->loc_addr;
                daddr = &inet6_rsk(req)->rmt_addr;
+       } else {
+               struct ipv6hdr *ip6h = ipv6_hdr(skb);
+               saddr = &ip6h->saddr;
+               daddr = &ip6h->daddr;
        }
-       return tcp_v6_do_calc_md5_hash(md5_hash, key,
-                                      saddr, daddr,
-                                      th, tcplen);
+
+       hp = tcp_get_md5sig_pool();
+       if (!hp)
+               goto clear_hash_noput;
+       desc = &hp->md5_desc;
+
+       if (crypto_hash_init(desc))
+               goto clear_hash;
+
+       if (tcp_v6_md5_hash_pseudoheader(hp, daddr, saddr, skb->len))
+               goto clear_hash;
+       if (tcp_md5_hash_header(hp, th))
+               goto clear_hash;
+       if (tcp_md5_hash_skb_data(hp, skb, th->doff << 2))
+               goto clear_hash;
+       if (tcp_md5_hash_key(hp, key))
+               goto clear_hash;
+       if (crypto_hash_final(desc, md5_hash))
+               goto clear_hash;
+
+       tcp_put_md5sig_pool();
+       return 0;
+
+clear_hash:
+       tcp_put_md5sig_pool();
+clear_hash_noput:
+       memset(md5_hash, 0, 16);
+       return 1;
 }
 
 static int tcp_v6_inbound_md5_hash (struct sock *sk, struct sk_buff *skb)
@@ -833,10 +875,10 @@ static int tcp_v6_inbound_md5_hash (struct sock *sk, struct sk_buff *skb)
        }
 
        /* check the signature */
-       genhash = tcp_v6_do_calc_md5_hash(newhash,
-                                         hash_expected,
-                                         &ip6h->saddr, &ip6h->daddr,
-                                         th, skb->len);
+       genhash = tcp_v6_md5_hash_skb(newhash,
+                                     hash_expected,
+                                     NULL, NULL, skb);
+
        if (genhash || memcmp(hash_location, newhash, 16) != 0) {
                if (net_ratelimit()) {
                        printk(KERN_INFO "MD5 Hash %s for "
@@ -973,10 +1015,9 @@ static void tcp_v6_send_reset(struct sock *sk, struct sk_buff *skb)
                               (TCPOPT_NOP << 16) |
                               (TCPOPT_MD5SIG << 8) |
                               TCPOLEN_MD5SIG);
-               tcp_v6_do_calc_md5_hash((__u8 *)&opt[1], key,
-                                       &ipv6_hdr(skb)->daddr,
-                                       &ipv6_hdr(skb)->saddr,
-                                       t1, tot_len);
+               tcp_v6_md5_hash_hdr((__u8 *)&opt[1], key,
+                                   &ipv6_hdr(skb)->daddr,
+                                   &ipv6_hdr(skb)->saddr, t1);
        }
 #endif
 
@@ -1004,8 +1045,8 @@ static void tcp_v6_send_reset(struct sock *sk, struct sk_buff *skb)
 
                if (xfrm_lookup(&buff->dst, &fl, NULL, 0) >= 0) {
                        ip6_xmit(ctl_sk, buff, &fl, NULL, 0);
-                       TCP_INC_STATS_BH(TCP_MIB_OUTSEGS);
-                       TCP_INC_STATS_BH(TCP_MIB_OUTRSTS);
+                       TCP_INC_STATS_BH(net, TCP_MIB_OUTSEGS);
+                       TCP_INC_STATS_BH(net, TCP_MIB_OUTRSTS);
                        return;
                }
        }
@@ -1063,10 +1104,9 @@ static void tcp_v6_send_ack(struct sk_buff *skb, u32 seq, u32 ack, u32 win, u32
        if (key) {
                *topt++ = htonl((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16) |
                                (TCPOPT_MD5SIG << 8) | TCPOLEN_MD5SIG);
-               tcp_v6_do_calc_md5_hash((__u8 *)topt, key,
-                                       &ipv6_hdr(skb)->daddr,
-                                       &ipv6_hdr(skb)->saddr,
-                                       t1, tot_len);
+               tcp_v6_md5_hash_hdr((__u8 *)topt, key,
+                                   &ipv6_hdr(skb)->daddr,
+                                   &ipv6_hdr(skb)->saddr, t1);
        }
 #endif
 
@@ -1089,7 +1129,7 @@ static void tcp_v6_send_ack(struct sk_buff *skb, u32 seq, u32 ack, u32 win, u32
        if (!ip6_dst_lookup(ctl_sk, &buff->dst, &fl)) {
                if (xfrm_lookup(&buff->dst, &fl, NULL, 0) >= 0) {
                        ip6_xmit(ctl_sk, buff, &fl, NULL, 0);
-                       TCP_INC_STATS_BH(TCP_MIB_OUTSEGS);
+                       TCP_INC_STATS_BH(net, TCP_MIB_OUTSEGS);
                        return;
                }
        }
@@ -1448,9 +1488,9 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
        return newsk;
 
 out_overflow:
-       NET_INC_STATS_BH(LINUX_MIB_LISTENOVERFLOWS);
+       NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENOVERFLOWS);
 out:
-       NET_INC_STATS_BH(LINUX_MIB_LISTENDROPS);
+       NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENDROPS);
        if (opt && opt != np->opt)
                sock_kfree_s(sk, opt, opt->tot_len);
        dst_release(dst);
@@ -1579,7 +1619,7 @@ discard:
        kfree_skb(skb);
        return 0;
 csum_err:
-       TCP_INC_STATS_BH(TCP_MIB_INERRS);
+       TCP_INC_STATS_BH(sock_net(sk), TCP_MIB_INERRS);
        goto discard;
 
 
@@ -1617,6 +1657,7 @@ static int tcp_v6_rcv(struct sk_buff *skb)
        struct tcphdr *th;
        struct sock *sk;
        int ret;
+       struct net *net = dev_net(skb->dev);
 
        if (skb->pkt_type != PACKET_HOST)
                goto discard_it;
@@ -1624,7 +1665,7 @@ static int tcp_v6_rcv(struct sk_buff *skb)
        /*
         *      Count it even if it's bad.
         */
-       TCP_INC_STATS_BH(TCP_MIB_INSEGS);
+       TCP_INC_STATS_BH(net, TCP_MIB_INSEGS);
 
        if (!pskb_may_pull(skb, sizeof(struct tcphdr)))
                goto discard_it;
@@ -1648,7 +1689,7 @@ static int tcp_v6_rcv(struct sk_buff *skb)
        TCP_SKB_CB(skb)->flags = ipv6_get_dsfield(ipv6_hdr(skb));
        TCP_SKB_CB(skb)->sacked = 0;
 
-       sk = __inet6_lookup(dev_net(skb->dev), &tcp_hashinfo,
+       sk = __inet6_lookup(net, &tcp_hashinfo,
                        &ipv6_hdr(skb)->saddr, th->source,
                        &ipv6_hdr(skb)->daddr, ntohs(th->dest),
                        inet6_iif(skb));
@@ -1696,7 +1737,7 @@ no_tcp_socket:
 
        if (skb->len < (th->doff<<2) || tcp_checksum_complete(skb)) {
 bad_packet:
-               TCP_INC_STATS_BH(TCP_MIB_INERRS);
+               TCP_INC_STATS_BH(net, TCP_MIB_INERRS);
        } else {
                tcp_v6_send_reset(NULL, skb);
        }
@@ -1721,7 +1762,7 @@ do_time_wait:
        }
 
        if (skb->len < (th->doff<<2) || tcp_checksum_complete(skb)) {
-               TCP_INC_STATS_BH(TCP_MIB_INERRS);
+               TCP_INC_STATS_BH(net, TCP_MIB_INERRS);
                inet_twsk_put(inet_twsk(sk));
                goto discard_it;
        }
@@ -1781,7 +1822,7 @@ static struct inet_connection_sock_af_ops ipv6_specific = {
 #ifdef CONFIG_TCP_MD5SIG
 static struct tcp_sock_af_ops tcp_sock_ipv6_specific = {
        .md5_lookup     =       tcp_v6_md5_lookup,
-       .calc_md5_hash  =       tcp_v6_calc_md5_hash,
+       .calc_md5_hash  =       tcp_v6_md5_hash_skb,
        .md5_add        =       tcp_v6_md5_add_func,
        .md5_parse      =       tcp_v6_parse_md5_keys,
 };
@@ -1813,7 +1854,7 @@ static struct inet_connection_sock_af_ops ipv6_mapped = {
 #ifdef CONFIG_TCP_MD5SIG
 static struct tcp_sock_af_ops tcp_sock_ipv6_mapped_specific = {
        .md5_lookup     =       tcp_v4_md5_lookup,
-       .calc_md5_hash  =       tcp_v4_calc_md5_hash,
+       .calc_md5_hash  =       tcp_v4_md5_hash_skb,
        .md5_add        =       tcp_v6_md5_add_func,
        .md5_parse      =       tcp_v6_parse_md5_keys,
 };