summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/net/sctp/sctp.h1
-rw-r--r--net/sctp/adler32.c45
-rw-r--r--net/sctp/crc32c.c17
-rw-r--r--net/sctp/output.c93
4 files changed, 95 insertions, 61 deletions
diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h
index 8df5bc7983af..b589528d646d 100644
--- a/include/net/sctp/sctp.h
+++ b/include/net/sctp/sctp.h
@@ -153,6 +153,7 @@ extern int sctp_primitive_REQUESTHEARTBEAT(struct sctp_association *, void *arg)
extern __u32 sctp_start_cksum(__u8 *ptr, __u16 count);
extern __u32 sctp_update_cksum(__u8 *ptr, __u16 count, __u32 cksum);
extern __u32 sctp_end_cksum(__u32 cksum);
+extern __u32 sctp_update_copy_cksum(__u8 *, __u8 *, __u16 count, __u32 cksum);
/*
* sctp/input.c
diff --git a/net/sctp/adler32.c b/net/sctp/adler32.c
index 336620187cbb..93068b2d55cf 100644
--- a/net/sctp/adler32.c
+++ b/net/sctp/adler32.c
@@ -2,43 +2,43 @@
* Copyright (c) 1999-2000 Cisco, Inc.
* Copyright (c) 1999-2001 Motorola, Inc.
* Copyright (c) 2003 International Business Machines, Corp.
- *
+ *
* This file is part of the SCTP kernel reference Implementation
- *
- * This file has direct heritage from the SCTP user-level reference
+ *
+ * This file has direct heritage from the SCTP user-level reference
* implementation by R. Stewart, et al. These functions implement the
- * Adler-32 algorithm as specified by RFC 2960.
- *
- * The SCTP reference implementation is free software;
- * you can redistribute it and/or modify it under the terms of
+ * Adler-32 algorithm as specified by RFC 2960.
+ *
+ * The SCTP reference implementation is free software;
+ * you can redistribute it and/or modify it under the terms of
* the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
- *
- * The SCTP reference implementation is distributed in the hope that it
+ *
+ * The SCTP reference implementation is distributed in the hope that it
* will be useful, but WITHOUT ANY WARRANTY; without even the implied
* ************************
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
- *
+ *
* You should have received a copy of the GNU General Public License
* along with GNU CC; see the file COPYING. If not, write to
* the Free Software Foundation, 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- *
+ * Boston, MA 02111-1307, USA.
+ *
* Please send any bug reports or fixes you make to the
* email address(es):
* lksctp developers <lksctp-developers@lists.sourceforge.net>
- *
+ *
* Or submit a bug report through the following website:
* http://www.sf.net/projects/lksctp
*
- * Written or modified by:
+ * Written or modified by:
* Randall Stewart <rstewar1@email.mot.com>
* Ken Morneau <kmorneau@cisco.com>
* Qiaobing Xie <qxie1@email.mot.com>
* Sridhar Samudrala <sri@us.ibm.com>
- *
+ *
* Any bugs reported given to us we will try to fix... any fixes shared will
* be incorporated into the next SCTP release.
*/
@@ -65,7 +65,7 @@
* tad, but I have commented the original lines below
*/
-#include <linux/types.h>
+#include <linux/types.h>
#include <net/sctp/sctp.h>
#define BASE 65521 /* largest prime smaller than 65536 */
@@ -111,7 +111,7 @@ unsigned long update_adler32(unsigned long adler,
* This would then be (2 * BASE) - 2, which
* will still only do one subtract. On Intel
* this is much better to do this way and
- * avoid the divide. Have not -pg'd on
+ * avoid the divide. Have not -pg'd on
* sparc.
*/
if (s2 >= BASE) {
@@ -135,7 +135,7 @@ __u32 sctp_start_cksum(__u8 *ptr, __u16 count)
__u32 zero = 0L;
/* Calculate the CRC up to the checksum field. */
- adler = update_adler32(adler, ptr,
+ adler = update_adler32(adler, ptr,
sizeof(struct sctphdr) - sizeof(__u32));
/* Skip over the checksum field. */
adler = update_adler32(adler, (unsigned char *) &zero,
@@ -156,6 +156,15 @@ __u32 sctp_update_cksum(__u8 *ptr, __u16 count, __u32 adler)
return adler;
}
+__u32 sctp_update_copy_cksum(__u8 *to, __u8 *from, __u16 count, __u32 adler)
+{
+ /* Its not worth it to try harder. Adler32 is obsolescent. */
+ adler = update_adler32(adler, from, count);
+ memcpy(to, from, count);
+
+ return adler;
+}
+
__u32 sctp_end_cksum(__u32 adler)
{
return adler;
diff --git a/net/sctp/crc32c.c b/net/sctp/crc32c.c
index 8307ae67b9b8..bf20588d4901 100644
--- a/net/sctp/crc32c.c
+++ b/net/sctp/crc32c.c
@@ -170,6 +170,23 @@ __u32 sctp_update_cksum(__u8 *buffer, __u16 length, __u32 crc32)
return crc32;
}
+__u32 sctp_update_copy_cksum(__u8 *to, __u8 *from, __u16 length, __u32 crc32)
+{
+ __u32 i;
+ __u32 *_to = (__u32 *)to;
+ __u32 *_from = (__u32 *)from;
+
+ for (i = 0; i < (length/4); i++) {
+ _to[i] = _from[i];
+ CRC32C(crc32, from[i*4]);
+ CRC32C(crc32, from[i*4+1]);
+ CRC32C(crc32, from[i*4+2]);
+ CRC32C(crc32, from[i*4+3]);
+ }
+
+ return crc32;
+}
+
__u32 sctp_end_cksum(__u32 crc32)
{
__u32 result;
diff --git a/net/sctp/output.c b/net/sctp/output.c
index a269f68b6555..663132f22077 100644
--- a/net/sctp/output.c
+++ b/net/sctp/output.c
@@ -166,11 +166,11 @@ static sctp_xmit_t sctp_packet_bundle_sack(struct sctp_packet *pkt,
/* If sending DATA and haven't aleady bundled a SACK, try to
* bundle one in to the packet.
*/
- if (sctp_chunk_is_data(chunk) && !pkt->has_sack &&
+ if (sctp_chunk_is_data(chunk) && !pkt->has_sack &&
!pkt->has_cookie_echo) {
struct sctp_association *asoc;
asoc = pkt->transport->asoc;
-
+
if (asoc->a_rwnd > asoc->rwnd) {
struct sctp_chunk *sack;
asoc->a_rwnd = asoc->rwnd;
@@ -205,7 +205,7 @@ sctp_xmit_t sctp_packet_append_chunk(struct sctp_packet *packet,
if (retval != SCTP_XMIT_OK)
goto finish;
-
+
pmtu = ((packet->transport->asoc) ?
(packet->transport->asoc->pmtu) :
(packet->transport->pmtu));
@@ -259,7 +259,7 @@ append:
goto finish;
} else if (SCTP_CID_COOKIE_ECHO == chunk->chunk_hdr->type)
packet->has_cookie_echo = 1;
- else if (SCTP_CID_SACK == chunk->chunk_hdr->type)
+ else if (SCTP_CID_SACK == chunk->chunk_hdr->type)
packet->has_sack = 1;
/* It is OK to send this chunk. */
@@ -276,8 +276,8 @@ finish:
*/
int sctp_packet_transmit(struct sctp_packet *packet)
{
- struct sctp_transport *transport = packet->transport;
- struct sctp_association *asoc = transport->asoc;
+ struct sctp_transport *tp = packet->transport;
+ struct sctp_association *asoc = tp->asoc;
struct sctphdr *sh;
__u32 crc32;
struct sk_buff *nskb;
@@ -311,6 +311,32 @@ int sctp_packet_transmit(struct sctp_packet *packet)
*/
skb_set_owner_w(nskb, sk);
+ /* Build the SCTP header. */
+ sh = (struct sctphdr *)skb_push(nskb, sizeof(struct sctphdr));
+ sh->source = htons(packet->source_port);
+ sh->dest = htons(packet->destination_port);
+
+ /* From 6.8 Adler-32 Checksum Calculation:
+ * After the packet is constructed (containing the SCTP common
+ * header and one or more control or DATA chunks), the
+ * transmitter shall:
+ *
+ * 1) Fill in the proper Verification Tag in the SCTP common
+ * header and initialize the checksum field to 0's.
+ */
+ sh->vtag = htonl(packet->vtag);
+ sh->checksum = 0;
+
+
+ /* 2) Calculate the Adler-32 checksum of the whole packet,
+ * including the SCTP common header and all the
+ * chunks.
+ *
+ * Note: Adler-32 is no longer applicable, as has been replaced
+ * by CRC32-C as described in <draft-ietf-tsvwg-sctpcsum-02.txt>.
+ */
+ crc32 = sctp_start_cksum((__u8 *)sh, sizeof(struct sctphdr));
+
/**
* 6.10 Bundling
*
@@ -344,16 +370,20 @@ int sctp_packet_transmit(struct sctp_packet *packet)
* for a given destination transport address.
*/
if ((1 == chunk->num_times_sent) &&
- (!transport->rto_pending)) {
+ (!tp->rto_pending)) {
chunk->rtt_in_progress = 1;
- transport->rto_pending = 1;
+ tp->rto_pending = 1;
}
has_data = 1;
}
- memcpy(skb_put(nskb, chunk->skb->len),
- chunk->skb->data, chunk->skb->len);
padding = WORD_ROUND(chunk->skb->len) - chunk->skb->len;
- memset(skb_put(nskb, padding), 0, padding);
+ if (padding)
+ memset(skb_put(chunk->skb, padding), 0, padding);
+
+ crc32 = sctp_update_copy_cksum(skb_put(nskb, chunk->skb->len),
+ chunk->skb->data,
+ chunk->skb->len, crc32);
+
SCTP_DEBUG_PRINTK("%s %p[%s] %s 0x%x, %s %d, %s %d, %s %d, "
"%s %d\n",
"*** Chunk", chunk,
@@ -376,30 +406,7 @@ int sctp_packet_transmit(struct sctp_packet *packet)
sctp_free_chunk(chunk);
}
- /* Build the SCTP header. */
- sh = (struct sctphdr *)skb_push(nskb, sizeof(struct sctphdr));
- sh->source = htons(packet->source_port);
- sh->dest = htons(packet->destination_port);
-
- /* From 6.8 Adler-32 Checksum Calculation:
- * After the packet is constructed (containing the SCTP common
- * header and one or more control or DATA chunks), the
- * transmitter shall:
- *
- * 1) Fill in the proper Verification Tag in the SCTP common
- * header and initialize the checksum field to 0's.
- */
- sh->vtag = htonl(packet->vtag);
- sh->checksum = 0;
-
- /* 2) Calculate the Adler-32 checksum of the whole packet,
- * including the SCTP common header and all the
- * chunks.
- *
- * Note: Adler-32 is no longer applicable, as has been replaced
- * by CRC32-C as described in <draft-ietf-tsvwg-sctpcsum-02.txt>.
- */
- crc32 = sctp_start_cksum((__u8 *)sh, nskb->len);
+ /* Perform final transformation on checksum. */
crc32 = sctp_end_cksum(crc32);
/* 3) Put the resultant value into the checksum field in the
@@ -431,18 +438,18 @@ int sctp_packet_transmit(struct sctp_packet *packet)
*/
/* Dump that on IP! */
- if (asoc && asoc->peer.last_sent_to != transport) {
+ if (asoc && asoc->peer.last_sent_to != tp) {
/* Considering the multiple CPU scenario, this is a
* "correcter" place for last_sent_to. --xguo
*/
- asoc->peer.last_sent_to = transport;
+ asoc->peer.last_sent_to = tp;
}
if (has_data) {
struct timer_list *timer;
unsigned long timeout;
- transport->last_time_used = jiffies;
+ tp->last_time_used = jiffies;
/* Restart the AUTOCLOSE timer when sending data. */
if ((SCTP_STATE_ESTABLISHED == asoc->state) &&
@@ -455,21 +462,21 @@ int sctp_packet_transmit(struct sctp_packet *packet)
}
}
- dst = transport->dst;
+ dst = tp->dst;
/* The 'obsolete' field of dst is set to 2 when a dst is freed. */
if (!dst || (dst->obsolete > 1)) {
dst_release(dst);
- sctp_transport_route(transport, NULL, sctp_sk(sk));
+ sctp_transport_route(tp, NULL, sctp_sk(sk));
sctp_assoc_sync_pmtu(asoc);
}
- nskb->dst = dst_clone(transport->dst);
+ nskb->dst = dst_clone(tp->dst);
if (!nskb->dst)
goto no_route;
SCTP_DEBUG_PRINTK("***sctp_transmit_packet*** skb length %d\n",
nskb->len);
- (*transport->af_specific->sctp_xmit)(nskb, transport, packet->ipfragok);
+ (*tp->af_specific->sctp_xmit)(nskb, tp, packet->ipfragok);
out:
packet->size = SCTP_IP_OVERHEAD;
return err;
@@ -596,7 +603,7 @@ static sctp_xmit_t sctp_packet_append_data(struct sctp_packet *packet,
* if any previously transmitted data on the connection remains
* unacknowledged.
*/
- if (!sp->nodelay && SCTP_IP_OVERHEAD == packet->size &&
+ if (!sp->nodelay && SCTP_IP_OVERHEAD == packet->size &&
q->outstanding_bytes && SCTP_STATE_ESTABLISHED == asoc->state) {
unsigned len = datasize + q->out_qlen;