diff options
Diffstat (limited to 'net')
-rw-r--r-- | net/sctp/chunk.c | 12 | ||||
-rw-r--r-- | net/sctp/output.c | 131 | ||||
-rw-r--r-- | net/sctp/sm_make_chunk.c | 39 |
3 files changed, 155 insertions, 27 deletions
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. */ | ||
191 | static 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. */ |
189 | static sctp_xmit_t sctp_packet_bundle_sack(struct sctp_packet *pkt, | 224 | static 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 | ||
1114 | struct 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 | ||