aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/net/sctp/checksum.h15
-rw-r--r--net/netfilter/ipvs/ip_vs_proto_sctp.c23
-rw-r--r--net/netfilter/nf_nat_proto_sctp.c8
-rw-r--r--net/sctp/input.c10
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. */
89static 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,
66static void sctp_nat_csum(struct sk_buff *skb, sctp_sctphdr_t *sctph, 66static 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. */