aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/net/sctp/sm.h1
-rw-r--r--include/net/sctp/structs.h3
-rw-r--r--net/sctp/chunk.c12
-rw-r--r--net/sctp/output.c131
-rw-r--r--net/sctp/sm_make_chunk.c39
5 files changed, 159 insertions, 27 deletions
diff --git a/include/net/sctp/sm.h b/include/net/sctp/sm.h
index e8e3a64eb322..148cdb4b9606 100644
--- a/include/net/sctp/sm.h
+++ b/include/net/sctp/sm.h
@@ -256,6 +256,7 @@ int sctp_process_asconf_ack(struct sctp_association *asoc,
256struct sctp_chunk *sctp_make_fwdtsn(const struct sctp_association *asoc, 256struct sctp_chunk *sctp_make_fwdtsn(const struct sctp_association *asoc,
257 __u32 new_cum_tsn, size_t nstreams, 257 __u32 new_cum_tsn, size_t nstreams,
258 struct sctp_fwdtsn_skip *skiplist); 258 struct sctp_fwdtsn_skip *skiplist);
259struct sctp_chunk *sctp_make_auth(const struct sctp_association *asoc);
259 260
260void sctp_chunk_assign_tsn(struct sctp_chunk *); 261void sctp_chunk_assign_tsn(struct sctp_chunk *);
261void sctp_chunk_assign_ssn(struct sctp_chunk *); 262void sctp_chunk_assign_ssn(struct sctp_chunk *);
diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h
index 18b06afacea0..31841c3a7fe8 100644
--- a/include/net/sctp/structs.h
+++ b/include/net/sctp/structs.h
@@ -798,6 +798,9 @@ struct sctp_packet {
798 /* This packet contains an AUTH chunk */ 798 /* This packet contains an AUTH chunk */
799 __u8 has_auth; 799 __u8 has_auth;
800 800
801 /* This packet contains at least 1 DATA chunk */
802 __u8 has_data;
803
801 /* SCTP cannot fragment this packet. So let ip fragment it. */ 804 /* SCTP cannot fragment this packet. So let ip fragment it. */
802 __u8 ipfragok; 805 __u8 ipfragok;
803 806
diff --git a/net/sctp/chunk.c b/net/sctp/chunk.c
index 77fb7b06a9c4..619d0f2dee51 100644
--- a/net/sctp/chunk.c
+++ b/net/sctp/chunk.c
@@ -194,6 +194,18 @@ struct sctp_datamsg *sctp_datamsg_from_user(struct sctp_association *asoc,
194 194
195 max = asoc->frag_point; 195 max = asoc->frag_point;
196 196
197 /* If the the peer requested that we authenticate DATA chunks
198 * we need to accound for bundling of the AUTH chunks along with
199 * DATA.
200 */
201 if (sctp_auth_send_cid(SCTP_CID_DATA, asoc)) {
202 struct sctp_hmac *hmac_desc = sctp_auth_asoc_get_hmac(asoc);
203
204 if (hmac_desc)
205 max -= WORD_ROUND(sizeof(sctp_auth_chunk_t) +
206 hmac_desc->hmac_len);
207 }
208
197 whole = 0; 209 whole = 0;
198 first_len = max; 210 first_len = max;
199 211
diff --git a/net/sctp/output.c b/net/sctp/output.c
index 49b9f5f031a4..847639d542c0 100644
--- a/net/sctp/output.c
+++ b/net/sctp/output.c
@@ -80,6 +80,7 @@ struct sctp_packet *sctp_packet_config(struct sctp_packet *packet,
80 packet->has_cookie_echo = 0; 80 packet->has_cookie_echo = 0;
81 packet->has_sack = 0; 81 packet->has_sack = 0;
82 packet->has_auth = 0; 82 packet->has_auth = 0;
83 packet->has_data = 0;
83 packet->ipfragok = 0; 84 packet->ipfragok = 0;
84 packet->auth = NULL; 85 packet->auth = NULL;
85 86
@@ -124,6 +125,7 @@ struct sctp_packet *sctp_packet_init(struct sctp_packet *packet,
124 packet->has_cookie_echo = 0; 125 packet->has_cookie_echo = 0;
125 packet->has_sack = 0; 126 packet->has_sack = 0;
126 packet->has_auth = 0; 127 packet->has_auth = 0;
128 packet->has_data = 0;
127 packet->ipfragok = 0; 129 packet->ipfragok = 0;
128 packet->malloced = 0; 130 packet->malloced = 0;
129 packet->auth = NULL; 131 packet->auth = NULL;
@@ -185,6 +187,39 @@ sctp_xmit_t sctp_packet_transmit_chunk(struct sctp_packet *packet,
185 return retval; 187 return retval;
186} 188}
187 189
190/* Try to bundle an auth chunk into the packet. */
191static sctp_xmit_t sctp_packet_bundle_auth(struct sctp_packet *pkt,
192 struct sctp_chunk *chunk)
193{
194 struct sctp_association *asoc = pkt->transport->asoc;
195 struct sctp_chunk *auth;
196 sctp_xmit_t retval = SCTP_XMIT_OK;
197
198 /* if we don't have an association, we can't do authentication */
199 if (!asoc)
200 return retval;
201
202 /* See if this is an auth chunk we are bundling or if
203 * auth is already bundled.
204 */
205 if (chunk->chunk_hdr->type == SCTP_CID_AUTH || pkt->auth)
206 return retval;
207
208 /* if the peer did not request this chunk to be authenticated,
209 * don't do it
210 */
211 if (!chunk->auth)
212 return retval;
213
214 auth = sctp_make_auth(asoc);
215 if (!auth)
216 return retval;
217
218 retval = sctp_packet_append_chunk(pkt, auth);
219
220 return retval;
221}
222
188/* Try to bundle a SACK with the packet. */ 223/* Try to bundle a SACK with the packet. */
189static sctp_xmit_t sctp_packet_bundle_sack(struct sctp_packet *pkt, 224static sctp_xmit_t sctp_packet_bundle_sack(struct sctp_packet *pkt,
190 struct sctp_chunk *chunk) 225 struct sctp_chunk *chunk)
@@ -231,12 +266,17 @@ sctp_xmit_t sctp_packet_append_chunk(struct sctp_packet *packet,
231 SCTP_DEBUG_PRINTK("%s: packet:%p chunk:%p\n", __FUNCTION__, packet, 266 SCTP_DEBUG_PRINTK("%s: packet:%p chunk:%p\n", __FUNCTION__, packet,
232 chunk); 267 chunk);
233 268
234 retval = sctp_packet_bundle_sack(packet, chunk); 269 /* Try to bundle AUTH chunk */
235 psize = packet->size; 270 retval = sctp_packet_bundle_auth(packet, chunk);
271 if (retval != SCTP_XMIT_OK)
272 goto finish;
236 273
274 /* Try to bundle SACK chunk */
275 retval = sctp_packet_bundle_sack(packet, chunk);
237 if (retval != SCTP_XMIT_OK) 276 if (retval != SCTP_XMIT_OK)
238 goto finish; 277 goto finish;
239 278
279 psize = packet->size;
240 pmtu = ((packet->transport->asoc) ? 280 pmtu = ((packet->transport->asoc) ?
241 (packet->transport->asoc->pathmtu) : 281 (packet->transport->asoc->pathmtu) :
242 (packet->transport->pathmtu)); 282 (packet->transport->pathmtu));
@@ -245,10 +285,16 @@ sctp_xmit_t sctp_packet_append_chunk(struct sctp_packet *packet,
245 285
246 /* Decide if we need to fragment or resubmit later. */ 286 /* Decide if we need to fragment or resubmit later. */
247 if (too_big) { 287 if (too_big) {
248 /* Both control chunks and data chunks with TSNs are 288 /* It's OK to fragmet at IP level if any one of the following
249 * non-fragmentable. 289 * is true:
290 * 1. The packet is empty (meaning this chunk is greater
291 * the MTU)
292 * 2. The chunk we are adding is a control chunk
293 * 3. The packet doesn't have any data in it yet and data
294 * requires authentication.
250 */ 295 */
251 if (sctp_packet_empty(packet) || !sctp_chunk_is_data(chunk)) { 296 if (sctp_packet_empty(packet) || !sctp_chunk_is_data(chunk) ||
297 (!packet->has_data && chunk->auth)) {
252 /* We no longer do re-fragmentation. 298 /* We no longer do re-fragmentation.
253 * Just fragment at the IP layer, if we 299 * Just fragment at the IP layer, if we
254 * actually hit this condition 300 * actually hit this condition
@@ -270,16 +316,31 @@ append:
270 /* DATA is a special case since we must examine both rwnd and cwnd 316 /* DATA is a special case since we must examine both rwnd and cwnd
271 * before we send DATA. 317 * before we send DATA.
272 */ 318 */
273 if (sctp_chunk_is_data(chunk)) { 319 switch (chunk->chunk_hdr->type) {
320 case SCTP_CID_DATA:
274 retval = sctp_packet_append_data(packet, chunk); 321 retval = sctp_packet_append_data(packet, chunk);
275 /* Disallow SACK bundling after DATA. */ 322 /* Disallow SACK bundling after DATA. */
276 packet->has_sack = 1; 323 packet->has_sack = 1;
324 /* Disallow AUTH bundling after DATA */
325 packet->has_auth = 1;
326 /* Let it be knows that packet has DATA in it */
327 packet->has_data = 1;
277 if (SCTP_XMIT_OK != retval) 328 if (SCTP_XMIT_OK != retval)
278 goto finish; 329 goto finish;
279 } else if (SCTP_CID_COOKIE_ECHO == chunk->chunk_hdr->type) 330 break;
331 case SCTP_CID_COOKIE_ECHO:
280 packet->has_cookie_echo = 1; 332 packet->has_cookie_echo = 1;
281 else if (SCTP_CID_SACK == chunk->chunk_hdr->type) 333 break;
334
335 case SCTP_CID_SACK:
282 packet->has_sack = 1; 336 packet->has_sack = 1;
337 break;
338
339 case SCTP_CID_AUTH:
340 packet->has_auth = 1;
341 packet->auth = chunk;
342 break;
343 }
283 344
284 /* It is OK to send this chunk. */ 345 /* It is OK to send this chunk. */
285 list_add_tail(&chunk->list, &packet->chunk_list); 346 list_add_tail(&chunk->list, &packet->chunk_list);
@@ -307,6 +368,8 @@ int sctp_packet_transmit(struct sctp_packet *packet)
307 int padding; /* How much padding do we need? */ 368 int padding; /* How much padding do we need? */
308 __u8 has_data = 0; 369 __u8 has_data = 0;
309 struct dst_entry *dst = tp->dst; 370 struct dst_entry *dst = tp->dst;
371 unsigned char *auth = NULL; /* pointer to auth in skb data */
372 __u32 cksum_buf_len = sizeof(struct sctphdr);
310 373
311 SCTP_DEBUG_PRINTK("%s: packet:%p\n", __FUNCTION__, packet); 374 SCTP_DEBUG_PRINTK("%s: packet:%p\n", __FUNCTION__, packet);
312 375
@@ -360,16 +423,6 @@ int sctp_packet_transmit(struct sctp_packet *packet)
360 sh->vtag = htonl(packet->vtag); 423 sh->vtag = htonl(packet->vtag);
361 sh->checksum = 0; 424 sh->checksum = 0;
362 425
363 /* 2) Calculate the Adler-32 checksum of the whole packet,
364 * including the SCTP common header and all the
365 * chunks.
366 *
367 * Note: Adler-32 is no longer applicable, as has been replaced
368 * by CRC32-C as described in <draft-ietf-tsvwg-sctpcsum-02.txt>.
369 */
370 if (!(dst->dev->features & NETIF_F_NO_CSUM))
371 crc32 = sctp_start_cksum((__u8 *)sh, sizeof(struct sctphdr));
372
373 /** 426 /**
374 * 6.10 Bundling 427 * 6.10 Bundling
375 * 428 *
@@ -420,14 +473,16 @@ int sctp_packet_transmit(struct sctp_packet *packet)
420 if (padding) 473 if (padding)
421 memset(skb_put(chunk->skb, padding), 0, padding); 474 memset(skb_put(chunk->skb, padding), 0, padding);
422 475
423 if (dst->dev->features & NETIF_F_NO_CSUM) 476 /* if this is the auth chunk that we are adding,
424 memcpy(skb_put(nskb, chunk->skb->len), 477 * store pointer where it will be added and put
478 * the auth into the packet.
479 */
480 if (chunk == packet->auth)
481 auth = skb_tail_pointer(nskb);
482
483 cksum_buf_len += chunk->skb->len;
484 memcpy(skb_put(nskb, chunk->skb->len),
425 chunk->skb->data, chunk->skb->len); 485 chunk->skb->data, chunk->skb->len);
426 else
427 crc32 = sctp_update_copy_cksum(skb_put(nskb,
428 chunk->skb->len),
429 chunk->skb->data,
430 chunk->skb->len, crc32);
431 486
432 SCTP_DEBUG_PRINTK("%s %p[%s] %s 0x%x, %s %d, %s %d, %s %d\n", 487 SCTP_DEBUG_PRINTK("%s %p[%s] %s 0x%x, %s %d, %s %d, %s %d\n",
433 "*** Chunk", chunk, 488 "*** Chunk", chunk,
@@ -449,9 +504,31 @@ int sctp_packet_transmit(struct sctp_packet *packet)
449 sctp_chunk_free(chunk); 504 sctp_chunk_free(chunk);
450 } 505 }
451 506
452 /* Perform final transformation on checksum. */ 507 /* SCTP-AUTH, Section 6.2
453 if (!(dst->dev->features & NETIF_F_NO_CSUM)) 508 * The sender MUST calculate the MAC as described in RFC2104 [2]
509 * using the hash function H as described by the MAC Identifier and
510 * the shared association key K based on the endpoint pair shared key
511 * described by the shared key identifier. The 'data' used for the
512 * computation of the AUTH-chunk is given by the AUTH chunk with its
513 * HMAC field set to zero (as shown in Figure 6) followed by all
514 * chunks that are placed after the AUTH chunk in the SCTP packet.
515 */
516 if (auth)
517 sctp_auth_calculate_hmac(asoc, nskb,
518 (struct sctp_auth_chunk *)auth,
519 GFP_ATOMIC);
520
521 /* 2) Calculate the Adler-32 checksum of the whole packet,
522 * including the SCTP common header and all the
523 * chunks.
524 *
525 * Note: Adler-32 is no longer applicable, as has been replaced
526 * by CRC32-C as described in <draft-ietf-tsvwg-sctpcsum-02.txt>.
527 */
528 if (!(dst->dev->features & NETIF_F_NO_CSUM)) {
529 crc32 = sctp_start_cksum((__u8 *)sh, cksum_buf_len);
454 crc32 = sctp_end_cksum(crc32); 530 crc32 = sctp_end_cksum(crc32);
531 }
455 532
456 /* 3) Put the resultant value into the checksum field in the 533 /* 3) Put the resultant value into the checksum field in the
457 * common header, and leave the rest of the bits unchanged. 534 * common header, and leave the rest of the bits unchanged.
diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c
index 4c02875786ac..fa2ba543183d 100644
--- a/net/sctp/sm_make_chunk.c
+++ b/net/sctp/sm_make_chunk.c
@@ -1111,6 +1111,41 @@ nodata:
1111 return retval; 1111 return retval;
1112} 1112}
1113 1113
1114struct sctp_chunk *sctp_make_auth(const struct sctp_association *asoc)
1115{
1116 struct sctp_chunk *retval;
1117 struct sctp_hmac *hmac_desc;
1118 struct sctp_authhdr auth_hdr;
1119 __u8 *hmac;
1120
1121 /* Get the first hmac that the peer told us to use */
1122 hmac_desc = sctp_auth_asoc_get_hmac(asoc);
1123 if (unlikely(!hmac_desc))
1124 return NULL;
1125
1126 retval = sctp_make_chunk(asoc, SCTP_CID_AUTH, 0,
1127 hmac_desc->hmac_len + sizeof(sctp_authhdr_t));
1128 if (!retval)
1129 return NULL;
1130
1131 auth_hdr.hmac_id = htons(hmac_desc->hmac_id);
1132 auth_hdr.shkey_id = htons(asoc->active_key_id);
1133
1134 retval->subh.auth_hdr = sctp_addto_chunk(retval, sizeof(sctp_authhdr_t),
1135 &auth_hdr);
1136
1137 hmac = skb_put(retval->skb, hmac_desc->hmac_len);
1138 memset(hmac, 0, hmac_desc->hmac_len);
1139
1140 /* Adjust the chunk header to include the empty MAC */
1141 retval->chunk_hdr->length =
1142 htons(ntohs(retval->chunk_hdr->length) + hmac_desc->hmac_len);
1143 retval->chunk_end = skb_tail_pointer(retval->skb);
1144
1145 return retval;
1146}
1147
1148
1114/******************************************************************** 1149/********************************************************************
1115 * 2nd Level Abstractions 1150 * 2nd Level Abstractions
1116 ********************************************************************/ 1151 ********************************************************************/
@@ -1225,6 +1260,10 @@ struct sctp_chunk *sctp_make_chunk(const struct sctp_association *asoc,
1225 retval->chunk_hdr = chunk_hdr; 1260 retval->chunk_hdr = chunk_hdr;
1226 retval->chunk_end = ((__u8 *)chunk_hdr) + sizeof(struct sctp_chunkhdr); 1261 retval->chunk_end = ((__u8 *)chunk_hdr) + sizeof(struct sctp_chunkhdr);
1227 1262
1263 /* Determine if the chunk needs to be authenticated */
1264 if (sctp_auth_send_cid(type, asoc))
1265 retval->auth = 1;
1266
1228 /* Set the skb to the belonging sock for accounting. */ 1267 /* Set the skb to the belonging sock for accounting. */
1229 skb->sk = sk; 1268 skb->sk = sk;
1230 1269