tree c2163130b2a2e1bc8ced9ee70b4c87fcbe7cdf8e
parent a019d6fe2b9da68ea4ba6cf3c4e86fc1dbf554c3
author Yoshifumi Nishida <[EMAIL PROTECTED]> Wed, 10 Aug 2005 10:15:35 -0700
committer David S. Miller <[EMAIL PROTECTED]> Tue, 30 Aug 2005 05:49:55 -0700

[DCCP]: Fix checksum routines

Signed-off-by: Yoshifumi Nishida <[EMAIL PROTECTED]>
Signed-off-by: Arnaldo Carvalho de Melo <[EMAIL PROTECTED]>
Signed-off-by: David S. Miller <[EMAIL PROTECTED]>

 net/dccp/dccp.h   |    3 ++-
 net/dccp/ipv4.c   |   38 ++++++++++++++++++++------------------
 net/dccp/output.c |    9 ++++++---
 3 files changed, 28 insertions(+), 22 deletions(-)

diff --git a/net/dccp/dccp.h b/net/dccp/dccp.h
--- a/net/dccp/dccp.h
+++ b/net/dccp/dccp.h
@@ -242,7 +242,8 @@ extern int     dccp_setsockopt(struct soc
                                   char *optval, int optlen);
 extern void       dccp_shutdown(struct sock *sk, int how);
 
-extern int        dccp_v4_checksum(struct sk_buff *skb);
+extern int        dccp_v4_checksum(const struct sk_buff *skb,
+                                   const u32 saddr, const u32 daddr);
 
 extern int        dccp_v4_send_reset(struct sock *sk, enum dccp_reset_codes 
code);
 extern void       dccp_send_close(struct sock *sk);
diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c
--- a/net/dccp/ipv4.c
+++ b/net/dccp/ipv4.c
@@ -802,9 +802,9 @@ static struct sock *dccp_v4_hnd_req(stru
        return sk;
 }
 
-int dccp_v4_checksum(struct sk_buff *skb)
+int dccp_v4_checksum(const struct sk_buff *skb, const u32 saddr, const u32 
daddr)
 {
-       struct dccp_hdr* dh = dccp_hdr(skb);
+       const struct dccp_hdr* dh = dccp_hdr(skb);
        int checksum_len;
        u32 tmp;
 
@@ -816,24 +816,24 @@ int dccp_v4_checksum(struct sk_buff *skb
        }
 
        tmp = csum_partial((unsigned char *)dh, checksum_len, 0);
-       return csum_fold(tmp);
+       return csum_tcpudp_magic(saddr, daddr, checksum_len, IPPROTO_DCCP, tmp);
 }
 
-static int dccp_v4_verify_checksum(struct sk_buff *skb)
+static int dccp_v4_verify_checksum(struct sk_buff *skb,
+                                  const u32 saddr, const u32 daddr)
 {
-       struct dccp_hdr *th = dccp_hdr(skb);
-       const u16 remote_checksum = th->dccph_checksum;
-       u16 local_checksum;
-
-       /* FIXME: don't mess with skb payload */
-       th->dccph_checksum = 0; /* zero it for computation */
-
-       local_checksum = dccp_v4_checksum(skb);
-
-       /* FIXME: don't mess with skb payload */
-       th->dccph_checksum = remote_checksum; /* put it back */
+       struct dccp_hdr *dh = dccp_hdr(skb);
+       int checksum_len;
+       u32 tmp;
 
-       return remote_checksum == local_checksum ? 0 : -1;
+       if (dh->dccph_cscov == 0)
+               checksum_len = skb->len;
+       else {
+               checksum_len = (dh->dccph_cscov + dh->dccph_x) * sizeof(u32);
+               checksum_len = checksum_len < skb->len ? checksum_len : 
skb->len;
+       }
+       tmp = csum_partial((unsigned char *)dh, checksum_len, 0);
+       return csum_tcpudp_magic(saddr, daddr, checksum_len, IPPROTO_DCCP, tmp) 
== 0 ? 0 : -1;
 }
 
 static struct dst_entry* dccp_v4_route_skb(struct sock *sk,
@@ -902,7 +902,8 @@ void dccp_v4_ctl_send_reset(struct sk_bu
        dccp_hdr_set_seq(dh, DCCP_SKB_CB(rxskb)->dccpd_ack_seq);
        dccp_hdr_set_ack(dccp_hdr_ack_bits(skb), DCCP_SKB_CB(rxskb)->dccpd_seq);
 
-       dh->dccph_checksum = dccp_v4_checksum(skb);
+       dh->dccph_checksum = dccp_v4_checksum(skb, rxskb->nh.iph->saddr,
+                                             rxskb->nh.iph->daddr);
 
        bh_lock_sock(dccp_ctl_socket->sk);
        err = ip_build_and_send_pkt(skb, dccp_ctl_socket->sk,
@@ -1024,7 +1025,8 @@ static inline int dccp_invalid_packet(st
        }
 
        /* If the header checksum is incorrect, drop packet and return */
-       if (dccp_v4_verify_checksum(skb) < 0) {
+       if (dccp_v4_verify_checksum(skb, skb->nh.iph->saddr,
+                                   skb->nh.iph->daddr) < 0) {
                dccp_pr_debug("header checksum is incorrect\n");
                return 1;
        }
diff --git a/net/dccp/output.c b/net/dccp/output.c
--- a/net/dccp/output.c
+++ b/net/dccp/output.c
@@ -93,7 +93,8 @@ int dccp_transmit_skb(struct sock *sk, s
                        break;
                }
 
-               dh->dccph_checksum = dccp_v4_checksum(skb);
+               dh->dccph_checksum = dccp_v4_checksum(skb, inet->saddr,
+                                                     inet->daddr);
 
                if (dcb->dccpd_type == DCCP_PKT_ACK ||
                    dcb->dccpd_type == DCCP_PKT_DATAACK)
@@ -193,7 +194,8 @@ struct sk_buff *dccp_make_response(struc
        dccp_hdr_set_seq(dh, dccp_rsk(req)->dreq_iss);
        dccp_hdr_set_ack(dccp_hdr_ack_bits(skb), dccp_rsk(req)->dreq_isr);
 
-       dh->dccph_checksum = dccp_v4_checksum(skb);
+       dh->dccph_checksum = dccp_v4_checksum(skb, inet_rsk(req)->loc_addr,
+                                             inet_rsk(req)->rmt_addr);
 
        DCCP_INC_STATS(DCCP_MIB_OUTSEGS);
        return skb;
@@ -242,7 +244,8 @@ struct sk_buff *dccp_make_reset(struct s
 
        dccp_hdr_reset(skb)->dccph_reset_code = code;
 
-       dh->dccph_checksum = dccp_v4_checksum(skb);
+       dh->dccph_checksum = dccp_v4_checksum(skb, inet_sk(sk)->saddr,
+                                             inet_sk(sk)->daddr);
 
        DCCP_INC_STATS(DCCP_MIB_OUTSEGS);
        return skb;
-
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to