diff options
-rw-r--r-- | include/net/sctp/checksum.h | 15 | ||||
-rw-r--r-- | net/netfilter/ipvs/ip_vs_proto_sctp.c | 23 | ||||
-rw-r--r-- | net/netfilter/nf_nat_proto_sctp.c | 8 | ||||
-rw-r--r-- | net/sctp/input.c | 10 |
4 files changed, 20 insertions, 36 deletions
diff --git a/include/net/sctp/checksum.h b/include/net/sctp/checksum.h index 78b88aa8c810..483e6303458d 100644 --- a/include/net/sctp/checksum.h +++ b/include/net/sctp/checksum.h | |||
@@ -85,4 +85,19 @@ static inline __le32 sctp_end_cksum(__u32 crc32) | |||
85 | return cpu_to_le32(~crc32); | 85 | return cpu_to_le32(~crc32); |
86 | } | 86 | } |
87 | 87 | ||
88 | /* Calculate the CRC32C checksum of an SCTP packet. */ | ||
89 | static inline __le32 sctp_compute_cksum(const struct sk_buff *skb, | ||
90 | unsigned int offset) | ||
91 | { | ||
92 | const struct sk_buff *iter; | ||
93 | |||
94 | __u32 crc32 = sctp_start_cksum(skb->data + offset, | ||
95 | skb_headlen(skb) - offset); | ||
96 | skb_walk_frags(skb, iter) | ||
97 | crc32 = sctp_update_cksum((__u8 *) iter->data, | ||
98 | skb_headlen(iter), crc32); | ||
99 | |||
100 | return sctp_end_cksum(crc32); | ||
101 | } | ||
102 | |||
88 | #endif /* __sctp_checksum_h__ */ | 103 | #endif /* __sctp_checksum_h__ */ |
diff --git a/net/netfilter/ipvs/ip_vs_proto_sctp.c b/net/netfilter/ipvs/ip_vs_proto_sctp.c index 3c0da8728036..23e596e438b3 100644 --- a/net/netfilter/ipvs/ip_vs_proto_sctp.c +++ b/net/netfilter/ipvs/ip_vs_proto_sctp.c | |||
@@ -66,15 +66,7 @@ sctp_conn_schedule(int af, struct sk_buff *skb, struct ip_vs_proto_data *pd, | |||
66 | static void sctp_nat_csum(struct sk_buff *skb, sctp_sctphdr_t *sctph, | 66 | static void sctp_nat_csum(struct sk_buff *skb, sctp_sctphdr_t *sctph, |
67 | unsigned int sctphoff) | 67 | unsigned int sctphoff) |
68 | { | 68 | { |
69 | __u32 crc32; | 69 | sctph->checksum = sctp_compute_cksum(skb, sctphoff); |
70 | struct sk_buff *iter; | ||
71 | |||
72 | crc32 = sctp_start_cksum((__u8 *)sctph, skb_headlen(skb) - sctphoff); | ||
73 | skb_walk_frags(skb, iter) | ||
74 | crc32 = sctp_update_cksum((u8 *) iter->data, | ||
75 | skb_headlen(iter), crc32); | ||
76 | sctph->checksum = sctp_end_cksum(crc32); | ||
77 | |||
78 | skb->ip_summed = CHECKSUM_UNNECESSARY; | 70 | skb->ip_summed = CHECKSUM_UNNECESSARY; |
79 | } | 71 | } |
80 | 72 | ||
@@ -151,10 +143,7 @@ sctp_csum_check(int af, struct sk_buff *skb, struct ip_vs_protocol *pp) | |||
151 | { | 143 | { |
152 | unsigned int sctphoff; | 144 | unsigned int sctphoff; |
153 | struct sctphdr *sh, _sctph; | 145 | struct sctphdr *sh, _sctph; |
154 | struct sk_buff *iter; | 146 | __le32 cmp, val; |
155 | __le32 cmp; | ||
156 | __le32 val; | ||
157 | __u32 tmp; | ||
158 | 147 | ||
159 | #ifdef CONFIG_IP_VS_IPV6 | 148 | #ifdef CONFIG_IP_VS_IPV6 |
160 | if (af == AF_INET6) | 149 | if (af == AF_INET6) |
@@ -168,13 +157,7 @@ sctp_csum_check(int af, struct sk_buff *skb, struct ip_vs_protocol *pp) | |||
168 | return 0; | 157 | return 0; |
169 | 158 | ||
170 | cmp = sh->checksum; | 159 | cmp = sh->checksum; |
171 | 160 | val = sctp_compute_cksum(skb, sctphoff); | |
172 | tmp = sctp_start_cksum((__u8 *) sh, skb_headlen(skb)); | ||
173 | skb_walk_frags(skb, iter) | ||
174 | tmp = sctp_update_cksum((__u8 *) iter->data, | ||
175 | skb_headlen(iter), tmp); | ||
176 | |||
177 | val = sctp_end_cksum(tmp); | ||
178 | 161 | ||
179 | if (val != cmp) { | 162 | if (val != cmp) { |
180 | /* CRC failure, dump it. */ | 163 | /* CRC failure, dump it. */ |
diff --git a/net/netfilter/nf_nat_proto_sctp.c b/net/netfilter/nf_nat_proto_sctp.c index 396e55d46f90..754536f2c674 100644 --- a/net/netfilter/nf_nat_proto_sctp.c +++ b/net/netfilter/nf_nat_proto_sctp.c | |||
@@ -34,9 +34,7 @@ sctp_manip_pkt(struct sk_buff *skb, | |||
34 | const struct nf_conntrack_tuple *tuple, | 34 | const struct nf_conntrack_tuple *tuple, |
35 | enum nf_nat_manip_type maniptype) | 35 | enum nf_nat_manip_type maniptype) |
36 | { | 36 | { |
37 | struct sk_buff *frag; | ||
38 | sctp_sctphdr_t *hdr; | 37 | sctp_sctphdr_t *hdr; |
39 | __u32 crc32; | ||
40 | 38 | ||
41 | if (!skb_make_writable(skb, hdroff + sizeof(*hdr))) | 39 | if (!skb_make_writable(skb, hdroff + sizeof(*hdr))) |
42 | return false; | 40 | return false; |
@@ -51,11 +49,7 @@ sctp_manip_pkt(struct sk_buff *skb, | |||
51 | hdr->dest = tuple->dst.u.sctp.port; | 49 | hdr->dest = tuple->dst.u.sctp.port; |
52 | } | 50 | } |
53 | 51 | ||
54 | crc32 = sctp_start_cksum((u8 *)hdr, skb_headlen(skb) - hdroff); | 52 | hdr->checksum = sctp_compute_cksum(skb, hdroff); |
55 | skb_walk_frags(skb, frag) | ||
56 | crc32 = sctp_update_cksum((u8 *)frag->data, skb_headlen(frag), | ||
57 | crc32); | ||
58 | hdr->checksum = sctp_end_cksum(crc32); | ||
59 | 53 | ||
60 | return true; | 54 | return true; |
61 | } | 55 | } |
diff --git a/net/sctp/input.c b/net/sctp/input.c index 7993495a4c0f..fa91aff02388 100644 --- a/net/sctp/input.c +++ b/net/sctp/input.c | |||
@@ -87,15 +87,7 @@ static inline int sctp_rcv_checksum(struct net *net, struct sk_buff *skb) | |||
87 | { | 87 | { |
88 | struct sctphdr *sh = sctp_hdr(skb); | 88 | struct sctphdr *sh = sctp_hdr(skb); |
89 | __le32 cmp = sh->checksum; | 89 | __le32 cmp = sh->checksum; |
90 | struct sk_buff *list; | 90 | __le32 val = sctp_compute_cksum(skb, 0); |
91 | __le32 val; | ||
92 | __u32 tmp = sctp_start_cksum((__u8 *)sh, skb_headlen(skb)); | ||
93 | |||
94 | skb_walk_frags(skb, list) | ||
95 | tmp = sctp_update_cksum((__u8 *)list->data, skb_headlen(list), | ||
96 | tmp); | ||
97 | |||
98 | val = sctp_end_cksum(tmp); | ||
99 | 91 | ||
100 | if (val != cmp) { | 92 | if (val != cmp) { |
101 | /* CRC failure, dump it. */ | 93 | /* CRC failure, dump it. */ |