tcp: fix length used for checksum in a reset
authorIlpo Järvinen <ilpo.jarvinen@helsinki.fi>
Wed, 8 Oct 2008 18:34:06 +0000 (11:34 -0700)
committerDavid S. Miller <davem@davemloft.net>
Wed, 8 Oct 2008 18:34:06 +0000 (11:34 -0700)
While looking for some common code I came across difference
in checksum calculation between tcp_v6_send_(reset|ack) I
couldn't explain. I checked both v4 and v6 and found out that
both seem to have the same "feature". I couldn't find anything
in rfc nor anywhere else which would state that md5 option
should be ignored like it was in case of reset so I came to
a conclusion that this is probably a genuine bug. I suspect
that addition of md5 just was fooled by the excessive
copy-paste code in those functions and the reset part was
never tested well enough to find out the problem.

Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@helsinki.fi>
Signed-off-by: David S. Miller <davem@davemloft.net>
net/ipv4/tcp_ipv4.c
net/ipv6/tcp_ipv6.c

index 24ffc5e1d3dab2aabe8eaea47e0ca1198bf302c7..ba46769c6e97ead6e0c24cf127b20d72b87dc461 100644 (file)
@@ -589,7 +589,7 @@ static void tcp_v4_send_reset(struct sock *sk, struct sk_buff *skb)
 #endif
        arg.csum = csum_tcpudp_nofold(ip_hdr(skb)->daddr,
                                      ip_hdr(skb)->saddr, /* XXX */
-                                     sizeof(struct tcphdr), IPPROTO_TCP, 0);
+                                     arg.iov[0].iov_len, IPPROTO_TCP, 0);
        arg.csumoffset = offsetof(struct tcphdr, check) / 2;
        arg.flags = (sk && inet_sk(sk)->transparent) ? IP_REPLY_ARG_NOSRCCHECK : 0;
 
index 424d9c4a67ac39b95ca16fb50ff3e2fc6eb80df1..e8b0fdd9edb82f01159a3393ddb05ca77aedd8ae 100644 (file)
@@ -1012,14 +1012,14 @@ static void tcp_v6_send_reset(struct sock *sk, struct sk_buff *skb)
        }
 #endif
 
-       buff->csum = csum_partial((char *)t1, sizeof(*t1), 0);
+       buff->csum = csum_partial((char *)t1, tot_len, 0);
 
        memset(&fl, 0, sizeof(fl));
        ipv6_addr_copy(&fl.fl6_dst, &ipv6_hdr(skb)->saddr);
        ipv6_addr_copy(&fl.fl6_src, &ipv6_hdr(skb)->daddr);
 
        t1->check = csum_ipv6_magic(&fl.fl6_src, &fl.fl6_dst,
-                                   sizeof(*t1), IPPROTO_TCP,
+                                   tot_len, IPPROTO_TCP,
                                    buff->csum);
 
        fl.proto = IPPROTO_TCP;