diff options
author | Yoshifumi Nishida <nishida@csl.sony.co.jp> | 2005-08-09 23:15:35 -0400 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2005-08-29 18:49:55 -0400 |
commit | 95b81ef794278c835b321f6376b0522cd5df59b7 (patch) | |
tree | c2163130b2a2e1bc8ced9ee70b4c87fcbe7cdf8e /net | |
parent | a019d6fe2b9da68ea4ba6cf3c4e86fc1dbf554c3 (diff) |
[DCCP]: Fix checksum routines
Signed-off-by: Yoshifumi Nishida <nishida@csl.sony.co.jp>
Signed-off-by: Arnaldo Carvalho de Melo <acme@ghostprotocols.net>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r-- | net/dccp/dccp.h | 3 | ||||
-rw-r--r-- | net/dccp/ipv4.c | 38 | ||||
-rw-r--r-- | net/dccp/output.c | 9 |
3 files changed, 28 insertions, 22 deletions
diff --git a/net/dccp/dccp.h b/net/dccp/dccp.h index fb83454102c1..55b690ab61ae 100644 --- a/net/dccp/dccp.h +++ b/net/dccp/dccp.h | |||
@@ -242,7 +242,8 @@ extern int dccp_setsockopt(struct sock *sk, int level, int optname, | |||
242 | char *optval, int optlen); | 242 | char *optval, int optlen); |
243 | extern void dccp_shutdown(struct sock *sk, int how); | 243 | extern void dccp_shutdown(struct sock *sk, int how); |
244 | 244 | ||
245 | extern int dccp_v4_checksum(struct sk_buff *skb); | 245 | extern int dccp_v4_checksum(const struct sk_buff *skb, |
246 | const u32 saddr, const u32 daddr); | ||
246 | 247 | ||
247 | extern int dccp_v4_send_reset(struct sock *sk, enum dccp_reset_codes code); | 248 | extern int dccp_v4_send_reset(struct sock *sk, enum dccp_reset_codes code); |
248 | extern void dccp_send_close(struct sock *sk); | 249 | extern void dccp_send_close(struct sock *sk); |
diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c index 083bacaecb3b..7b90606ec10e 100644 --- a/net/dccp/ipv4.c +++ b/net/dccp/ipv4.c | |||
@@ -802,9 +802,9 @@ static struct sock *dccp_v4_hnd_req(struct sock *sk, struct sk_buff *skb) | |||
802 | return sk; | 802 | return sk; |
803 | } | 803 | } |
804 | 804 | ||
805 | int dccp_v4_checksum(struct sk_buff *skb) | 805 | int dccp_v4_checksum(const struct sk_buff *skb, const u32 saddr, const u32 daddr) |
806 | { | 806 | { |
807 | struct dccp_hdr* dh = dccp_hdr(skb); | 807 | const struct dccp_hdr* dh = dccp_hdr(skb); |
808 | int checksum_len; | 808 | int checksum_len; |
809 | u32 tmp; | 809 | u32 tmp; |
810 | 810 | ||
@@ -816,24 +816,24 @@ int dccp_v4_checksum(struct sk_buff *skb) | |||
816 | } | 816 | } |
817 | 817 | ||
818 | tmp = csum_partial((unsigned char *)dh, checksum_len, 0); | 818 | tmp = csum_partial((unsigned char *)dh, checksum_len, 0); |
819 | return csum_fold(tmp); | 819 | return csum_tcpudp_magic(saddr, daddr, checksum_len, IPPROTO_DCCP, tmp); |
820 | } | 820 | } |
821 | 821 | ||
822 | static int dccp_v4_verify_checksum(struct sk_buff *skb) | 822 | static int dccp_v4_verify_checksum(struct sk_buff *skb, |
823 | const u32 saddr, const u32 daddr) | ||
823 | { | 824 | { |
824 | struct dccp_hdr *th = dccp_hdr(skb); | 825 | struct dccp_hdr *dh = dccp_hdr(skb); |
825 | const u16 remote_checksum = th->dccph_checksum; | 826 | int checksum_len; |
826 | u16 local_checksum; | 827 | u32 tmp; |
827 | |||
828 | /* FIXME: don't mess with skb payload */ | ||
829 | th->dccph_checksum = 0; /* zero it for computation */ | ||
830 | |||
831 | local_checksum = dccp_v4_checksum(skb); | ||
832 | |||
833 | /* FIXME: don't mess with skb payload */ | ||
834 | th->dccph_checksum = remote_checksum; /* put it back */ | ||
835 | 828 | ||
836 | return remote_checksum == local_checksum ? 0 : -1; | 829 | if (dh->dccph_cscov == 0) |
830 | checksum_len = skb->len; | ||
831 | else { | ||
832 | checksum_len = (dh->dccph_cscov + dh->dccph_x) * sizeof(u32); | ||
833 | checksum_len = checksum_len < skb->len ? checksum_len : skb->len; | ||
834 | } | ||
835 | tmp = csum_partial((unsigned char *)dh, checksum_len, 0); | ||
836 | return csum_tcpudp_magic(saddr, daddr, checksum_len, IPPROTO_DCCP, tmp) == 0 ? 0 : -1; | ||
837 | } | 837 | } |
838 | 838 | ||
839 | static struct dst_entry* dccp_v4_route_skb(struct sock *sk, | 839 | static struct dst_entry* dccp_v4_route_skb(struct sock *sk, |
@@ -902,7 +902,8 @@ void dccp_v4_ctl_send_reset(struct sk_buff *rxskb) | |||
902 | dccp_hdr_set_seq(dh, DCCP_SKB_CB(rxskb)->dccpd_ack_seq); | 902 | dccp_hdr_set_seq(dh, DCCP_SKB_CB(rxskb)->dccpd_ack_seq); |
903 | dccp_hdr_set_ack(dccp_hdr_ack_bits(skb), DCCP_SKB_CB(rxskb)->dccpd_seq); | 903 | dccp_hdr_set_ack(dccp_hdr_ack_bits(skb), DCCP_SKB_CB(rxskb)->dccpd_seq); |
904 | 904 | ||
905 | dh->dccph_checksum = dccp_v4_checksum(skb); | 905 | dh->dccph_checksum = dccp_v4_checksum(skb, rxskb->nh.iph->saddr, |
906 | rxskb->nh.iph->daddr); | ||
906 | 907 | ||
907 | bh_lock_sock(dccp_ctl_socket->sk); | 908 | bh_lock_sock(dccp_ctl_socket->sk); |
908 | err = ip_build_and_send_pkt(skb, dccp_ctl_socket->sk, | 909 | err = ip_build_and_send_pkt(skb, dccp_ctl_socket->sk, |
@@ -1024,7 +1025,8 @@ static inline int dccp_invalid_packet(struct sk_buff *skb) | |||
1024 | } | 1025 | } |
1025 | 1026 | ||
1026 | /* If the header checksum is incorrect, drop packet and return */ | 1027 | /* If the header checksum is incorrect, drop packet and return */ |
1027 | if (dccp_v4_verify_checksum(skb) < 0) { | 1028 | if (dccp_v4_verify_checksum(skb, skb->nh.iph->saddr, |
1029 | skb->nh.iph->daddr) < 0) { | ||
1028 | dccp_pr_debug("header checksum is incorrect\n"); | 1030 | dccp_pr_debug("header checksum is incorrect\n"); |
1029 | return 1; | 1031 | return 1; |
1030 | } | 1032 | } |
diff --git a/net/dccp/output.c b/net/dccp/output.c index 22ca2910d4f2..4945eaa9d1a4 100644 --- a/net/dccp/output.c +++ b/net/dccp/output.c | |||
@@ -93,7 +93,8 @@ int dccp_transmit_skb(struct sock *sk, struct sk_buff *skb) | |||
93 | break; | 93 | break; |
94 | } | 94 | } |
95 | 95 | ||
96 | dh->dccph_checksum = dccp_v4_checksum(skb); | 96 | dh->dccph_checksum = dccp_v4_checksum(skb, inet->saddr, |
97 | inet->daddr); | ||
97 | 98 | ||
98 | if (dcb->dccpd_type == DCCP_PKT_ACK || | 99 | if (dcb->dccpd_type == DCCP_PKT_ACK || |
99 | dcb->dccpd_type == DCCP_PKT_DATAACK) | 100 | dcb->dccpd_type == DCCP_PKT_DATAACK) |
@@ -193,7 +194,8 @@ struct sk_buff *dccp_make_response(struct sock *sk, struct dst_entry *dst, | |||
193 | dccp_hdr_set_seq(dh, dccp_rsk(req)->dreq_iss); | 194 | dccp_hdr_set_seq(dh, dccp_rsk(req)->dreq_iss); |
194 | dccp_hdr_set_ack(dccp_hdr_ack_bits(skb), dccp_rsk(req)->dreq_isr); | 195 | dccp_hdr_set_ack(dccp_hdr_ack_bits(skb), dccp_rsk(req)->dreq_isr); |
195 | 196 | ||
196 | dh->dccph_checksum = dccp_v4_checksum(skb); | 197 | dh->dccph_checksum = dccp_v4_checksum(skb, inet_rsk(req)->loc_addr, |
198 | inet_rsk(req)->rmt_addr); | ||
197 | 199 | ||
198 | DCCP_INC_STATS(DCCP_MIB_OUTSEGS); | 200 | DCCP_INC_STATS(DCCP_MIB_OUTSEGS); |
199 | return skb; | 201 | return skb; |
@@ -242,7 +244,8 @@ struct sk_buff *dccp_make_reset(struct sock *sk, struct dst_entry *dst, | |||
242 | 244 | ||
243 | dccp_hdr_reset(skb)->dccph_reset_code = code; | 245 | dccp_hdr_reset(skb)->dccph_reset_code = code; |
244 | 246 | ||
245 | dh->dccph_checksum = dccp_v4_checksum(skb); | 247 | dh->dccph_checksum = dccp_v4_checksum(skb, inet_sk(sk)->saddr, |
248 | inet_sk(sk)->daddr); | ||
246 | 249 | ||
247 | DCCP_INC_STATS(DCCP_MIB_OUTSEGS); | 250 | DCCP_INC_STATS(DCCP_MIB_OUTSEGS); |
248 | return skb; | 251 | return skb; |