|
@@ -80,6 +80,7 @@ struct sctp_packet *sctp_packet_config(struct sctp_packet *packet,
|
|
|
packet->has_cookie_echo = 0;
|
|
|
packet->has_sack = 0;
|
|
|
packet->has_auth = 0;
|
|
|
+ packet->has_data = 0;
|
|
|
packet->ipfragok = 0;
|
|
|
packet->auth = NULL;
|
|
|
|
|
@@ -124,6 +125,7 @@ struct sctp_packet *sctp_packet_init(struct sctp_packet *packet,
|
|
|
packet->has_cookie_echo = 0;
|
|
|
packet->has_sack = 0;
|
|
|
packet->has_auth = 0;
|
|
|
+ packet->has_data = 0;
|
|
|
packet->ipfragok = 0;
|
|
|
packet->malloced = 0;
|
|
|
packet->auth = NULL;
|
|
@@ -185,6 +187,39 @@ sctp_xmit_t sctp_packet_transmit_chunk(struct sctp_packet *packet,
|
|
|
return retval;
|
|
|
}
|
|
|
|
|
|
+/* Try to bundle an auth chunk into the packet. */
|
|
|
+static sctp_xmit_t sctp_packet_bundle_auth(struct sctp_packet *pkt,
|
|
|
+ struct sctp_chunk *chunk)
|
|
|
+{
|
|
|
+ struct sctp_association *asoc = pkt->transport->asoc;
|
|
|
+ struct sctp_chunk *auth;
|
|
|
+ sctp_xmit_t retval = SCTP_XMIT_OK;
|
|
|
+
|
|
|
+ /* if we don't have an association, we can't do authentication */
|
|
|
+ if (!asoc)
|
|
|
+ return retval;
|
|
|
+
|
|
|
+ /* See if this is an auth chunk we are bundling or if
|
|
|
+ * auth is already bundled.
|
|
|
+ */
|
|
|
+ if (chunk->chunk_hdr->type == SCTP_CID_AUTH || pkt->auth)
|
|
|
+ return retval;
|
|
|
+
|
|
|
+ /* if the peer did not request this chunk to be authenticated,
|
|
|
+ * don't do it
|
|
|
+ */
|
|
|
+ if (!chunk->auth)
|
|
|
+ return retval;
|
|
|
+
|
|
|
+ auth = sctp_make_auth(asoc);
|
|
|
+ if (!auth)
|
|
|
+ return retval;
|
|
|
+
|
|
|
+ retval = sctp_packet_append_chunk(pkt, auth);
|
|
|
+
|
|
|
+ return retval;
|
|
|
+}
|
|
|
+
|
|
|
/* Try to bundle a SACK with the packet. */
|
|
|
static sctp_xmit_t sctp_packet_bundle_sack(struct sctp_packet *pkt,
|
|
|
struct sctp_chunk *chunk)
|
|
@@ -231,12 +266,17 @@ sctp_xmit_t sctp_packet_append_chunk(struct sctp_packet *packet,
|
|
|
SCTP_DEBUG_PRINTK("%s: packet:%p chunk:%p\n", __FUNCTION__, packet,
|
|
|
chunk);
|
|
|
|
|
|
- retval = sctp_packet_bundle_sack(packet, chunk);
|
|
|
- psize = packet->size;
|
|
|
+ /* Try to bundle AUTH chunk */
|
|
|
+ retval = sctp_packet_bundle_auth(packet, chunk);
|
|
|
+ if (retval != SCTP_XMIT_OK)
|
|
|
+ goto finish;
|
|
|
|
|
|
+ /* Try to bundle SACK chunk */
|
|
|
+ retval = sctp_packet_bundle_sack(packet, chunk);
|
|
|
if (retval != SCTP_XMIT_OK)
|
|
|
goto finish;
|
|
|
|
|
|
+ psize = packet->size;
|
|
|
pmtu = ((packet->transport->asoc) ?
|
|
|
(packet->transport->asoc->pathmtu) :
|
|
|
(packet->transport->pathmtu));
|
|
@@ -245,10 +285,16 @@ sctp_xmit_t sctp_packet_append_chunk(struct sctp_packet *packet,
|
|
|
|
|
|
/* Decide if we need to fragment or resubmit later. */
|
|
|
if (too_big) {
|
|
|
- /* Both control chunks and data chunks with TSNs are
|
|
|
- * non-fragmentable.
|
|
|
+ /* It's OK to fragmet at IP level if any one of the following
|
|
|
+ * is true:
|
|
|
+ * 1. The packet is empty (meaning this chunk is greater
|
|
|
+ * the MTU)
|
|
|
+ * 2. The chunk we are adding is a control chunk
|
|
|
+ * 3. The packet doesn't have any data in it yet and data
|
|
|
+ * requires authentication.
|
|
|
*/
|
|
|
- if (sctp_packet_empty(packet) || !sctp_chunk_is_data(chunk)) {
|
|
|
+ if (sctp_packet_empty(packet) || !sctp_chunk_is_data(chunk) ||
|
|
|
+ (!packet->has_data && chunk->auth)) {
|
|
|
/* We no longer do re-fragmentation.
|
|
|
* Just fragment at the IP layer, if we
|
|
|
* actually hit this condition
|
|
@@ -270,16 +316,31 @@ append:
|
|
|
/* DATA is a special case since we must examine both rwnd and cwnd
|
|
|
* before we send DATA.
|
|
|
*/
|
|
|
- if (sctp_chunk_is_data(chunk)) {
|
|
|
+ switch (chunk->chunk_hdr->type) {
|
|
|
+ case SCTP_CID_DATA:
|
|
|
retval = sctp_packet_append_data(packet, chunk);
|
|
|
/* Disallow SACK bundling after DATA. */
|
|
|
packet->has_sack = 1;
|
|
|
+ /* Disallow AUTH bundling after DATA */
|
|
|
+ packet->has_auth = 1;
|
|
|
+ /* Let it be knows that packet has DATA in it */
|
|
|
+ packet->has_data = 1;
|
|
|
if (SCTP_XMIT_OK != retval)
|
|
|
goto finish;
|
|
|
- } else if (SCTP_CID_COOKIE_ECHO == chunk->chunk_hdr->type)
|
|
|
+ break;
|
|
|
+ case SCTP_CID_COOKIE_ECHO:
|
|
|
packet->has_cookie_echo = 1;
|
|
|
- else if (SCTP_CID_SACK == chunk->chunk_hdr->type)
|
|
|
+ break;
|
|
|
+
|
|
|
+ case SCTP_CID_SACK:
|
|
|
packet->has_sack = 1;
|
|
|
+ break;
|
|
|
+
|
|
|
+ case SCTP_CID_AUTH:
|
|
|
+ packet->has_auth = 1;
|
|
|
+ packet->auth = chunk;
|
|
|
+ break;
|
|
|
+ }
|
|
|
|
|
|
/* It is OK to send this chunk. */
|
|
|
list_add_tail(&chunk->list, &packet->chunk_list);
|
|
@@ -307,6 +368,8 @@ int sctp_packet_transmit(struct sctp_packet *packet)
|
|
|
int padding; /* How much padding do we need? */
|
|
|
__u8 has_data = 0;
|
|
|
struct dst_entry *dst = tp->dst;
|
|
|
+ unsigned char *auth = NULL; /* pointer to auth in skb data */
|
|
|
+ __u32 cksum_buf_len = sizeof(struct sctphdr);
|
|
|
|
|
|
SCTP_DEBUG_PRINTK("%s: packet:%p\n", __FUNCTION__, packet);
|
|
|
|
|
@@ -360,16 +423,6 @@ int sctp_packet_transmit(struct sctp_packet *packet)
|
|
|
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>.
|
|
|
- */
|
|
|
- if (!(dst->dev->features & NETIF_F_NO_CSUM))
|
|
|
- crc32 = sctp_start_cksum((__u8 *)sh, sizeof(struct sctphdr));
|
|
|
-
|
|
|
/**
|
|
|
* 6.10 Bundling
|
|
|
*
|
|
@@ -420,14 +473,16 @@ int sctp_packet_transmit(struct sctp_packet *packet)
|
|
|
if (padding)
|
|
|
memset(skb_put(chunk->skb, padding), 0, padding);
|
|
|
|
|
|
- if (dst->dev->features & NETIF_F_NO_CSUM)
|
|
|
- memcpy(skb_put(nskb, chunk->skb->len),
|
|
|
+ /* if this is the auth chunk that we are adding,
|
|
|
+ * store pointer where it will be added and put
|
|
|
+ * the auth into the packet.
|
|
|
+ */
|
|
|
+ if (chunk == packet->auth)
|
|
|
+ auth = skb_tail_pointer(nskb);
|
|
|
+
|
|
|
+ cksum_buf_len += chunk->skb->len;
|
|
|
+ memcpy(skb_put(nskb, chunk->skb->len),
|
|
|
chunk->skb->data, chunk->skb->len);
|
|
|
- else
|
|
|
- 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\n",
|
|
|
"*** Chunk", chunk,
|
|
@@ -449,9 +504,31 @@ int sctp_packet_transmit(struct sctp_packet *packet)
|
|
|
sctp_chunk_free(chunk);
|
|
|
}
|
|
|
|
|
|
- /* Perform final transformation on checksum. */
|
|
|
- if (!(dst->dev->features & NETIF_F_NO_CSUM))
|
|
|
+ /* SCTP-AUTH, Section 6.2
|
|
|
+ * The sender MUST calculate the MAC as described in RFC2104 [2]
|
|
|
+ * using the hash function H as described by the MAC Identifier and
|
|
|
+ * the shared association key K based on the endpoint pair shared key
|
|
|
+ * described by the shared key identifier. The 'data' used for the
|
|
|
+ * computation of the AUTH-chunk is given by the AUTH chunk with its
|
|
|
+ * HMAC field set to zero (as shown in Figure 6) followed by all
|
|
|
+ * chunks that are placed after the AUTH chunk in the SCTP packet.
|
|
|
+ */
|
|
|
+ if (auth)
|
|
|
+ sctp_auth_calculate_hmac(asoc, nskb,
|
|
|
+ (struct sctp_auth_chunk *)auth,
|
|
|
+ GFP_ATOMIC);
|
|
|
+
|
|
|
+ /* 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>.
|
|
|
+ */
|
|
|
+ if (!(dst->dev->features & NETIF_F_NO_CSUM)) {
|
|
|
+ crc32 = sctp_start_cksum((__u8 *)sh, cksum_buf_len);
|
|
|
crc32 = sctp_end_cksum(crc32);
|
|
|
+ }
|
|
|
|
|
|
/* 3) Put the resultant value into the checksum field in the
|
|
|
* common header, and leave the rest of the bits unchanged.
|