Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 66620
b: refs/heads/master
c: 4cd57c8
h: refs/heads/master
v: v3
  • Loading branch information
Vlad Yasevich authored and David S. Miller committed Oct 10, 2007
1 parent 619d491 commit 76610a6
Show file tree
Hide file tree
Showing 6 changed files with 160 additions and 28 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 730fc3d05cd4ba4c9ce2de91f3d43349e95dbbf5
refs/heads/master: 4cd57c8078fae0a4b1bf421191e94626d0cba92a
1 change: 1 addition & 0 deletions trunk/include/net/sctp/sm.h
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,7 @@ int sctp_process_asconf_ack(struct sctp_association *asoc,
struct sctp_chunk *sctp_make_fwdtsn(const struct sctp_association *asoc,
__u32 new_cum_tsn, size_t nstreams,
struct sctp_fwdtsn_skip *skiplist);
struct sctp_chunk *sctp_make_auth(const struct sctp_association *asoc);

void sctp_chunk_assign_tsn(struct sctp_chunk *);
void sctp_chunk_assign_ssn(struct sctp_chunk *);
Expand Down
3 changes: 3 additions & 0 deletions trunk/include/net/sctp/structs.h
Original file line number Diff line number Diff line change
Expand Up @@ -798,6 +798,9 @@ struct sctp_packet {
/* This packet contains an AUTH chunk */
__u8 has_auth;

/* This packet contains at least 1 DATA chunk */
__u8 has_data;

/* SCTP cannot fragment this packet. So let ip fragment it. */
__u8 ipfragok;

Expand Down
12 changes: 12 additions & 0 deletions trunk/net/sctp/chunk.c
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,18 @@ struct sctp_datamsg *sctp_datamsg_from_user(struct sctp_association *asoc,

max = asoc->frag_point;

/* If the the peer requested that we authenticate DATA chunks
* we need to accound for bundling of the AUTH chunks along with
* DATA.
*/
if (sctp_auth_send_cid(SCTP_CID_DATA, asoc)) {
struct sctp_hmac *hmac_desc = sctp_auth_asoc_get_hmac(asoc);

if (hmac_desc)
max -= WORD_ROUND(sizeof(sctp_auth_chunk_t) +
hmac_desc->hmac_len);
}

whole = 0;
first_len = max;

Expand Down
131 changes: 104 additions & 27 deletions trunk/net/sctp/output.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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));
Expand All @@ -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
Expand All @@ -270,16 +316,31 @@ sctp_xmit_t sctp_packet_append_chunk(struct sctp_packet *packet,
/* 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);
Expand Down Expand Up @@ -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);

Expand Down Expand Up @@ -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
*
Expand Down Expand Up @@ -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,
Expand All @@ -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.
Expand Down
39 changes: 39 additions & 0 deletions trunk/net/sctp/sm_make_chunk.c
Original file line number Diff line number Diff line change
Expand Up @@ -1111,6 +1111,41 @@ struct sctp_chunk *sctp_make_op_error(const struct sctp_association *asoc,
return retval;
}

struct sctp_chunk *sctp_make_auth(const struct sctp_association *asoc)
{
struct sctp_chunk *retval;
struct sctp_hmac *hmac_desc;
struct sctp_authhdr auth_hdr;
__u8 *hmac;

/* Get the first hmac that the peer told us to use */
hmac_desc = sctp_auth_asoc_get_hmac(asoc);
if (unlikely(!hmac_desc))
return NULL;

retval = sctp_make_chunk(asoc, SCTP_CID_AUTH, 0,
hmac_desc->hmac_len + sizeof(sctp_authhdr_t));
if (!retval)
return NULL;

auth_hdr.hmac_id = htons(hmac_desc->hmac_id);
auth_hdr.shkey_id = htons(asoc->active_key_id);

retval->subh.auth_hdr = sctp_addto_chunk(retval, sizeof(sctp_authhdr_t),
&auth_hdr);

hmac = skb_put(retval->skb, hmac_desc->hmac_len);
memset(hmac, 0, hmac_desc->hmac_len);

/* Adjust the chunk header to include the empty MAC */
retval->chunk_hdr->length =
htons(ntohs(retval->chunk_hdr->length) + hmac_desc->hmac_len);
retval->chunk_end = skb_tail_pointer(retval->skb);

return retval;
}


/********************************************************************
* 2nd Level Abstractions
********************************************************************/
Expand Down Expand Up @@ -1225,6 +1260,10 @@ struct sctp_chunk *sctp_make_chunk(const struct sctp_association *asoc,
retval->chunk_hdr = chunk_hdr;
retval->chunk_end = ((__u8 *)chunk_hdr) + sizeof(struct sctp_chunkhdr);

/* Determine if the chunk needs to be authenticated */
if (sctp_auth_send_cid(type, asoc))
retval->auth = 1;

/* Set the skb to the belonging sock for accounting. */
skb->sk = sk;

Expand Down

0 comments on commit 76610a6

Please sign in to comment.