aboutsummaryrefslogtreecommitdiffstats
path: root/net/sctp/sm_make_chunk.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/sctp/sm_make_chunk.c')
-rw-r--r--net/sctp/sm_make_chunk.c118
1 files changed, 76 insertions, 42 deletions
diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c
index 17cb400ecd6a..d8261f3d7715 100644
--- a/net/sctp/sm_make_chunk.c
+++ b/net/sctp/sm_make_chunk.c
@@ -108,7 +108,7 @@ static const struct sctp_paramhdr prsctp_param = {
108 cpu_to_be16(sizeof(struct sctp_paramhdr)), 108 cpu_to_be16(sizeof(struct sctp_paramhdr)),
109}; 109};
110 110
111/* A helper to initialize to initialize an op error inside a 111/* A helper to initialize an op error inside a
112 * provided chunk, as most cause codes will be embedded inside an 112 * provided chunk, as most cause codes will be embedded inside an
113 * abort chunk. 113 * abort chunk.
114 */ 114 */
@@ -125,6 +125,29 @@ void sctp_init_cause(struct sctp_chunk *chunk, __be16 cause_code,
125 chunk->subh.err_hdr = sctp_addto_chunk(chunk, sizeof(sctp_errhdr_t), &err); 125 chunk->subh.err_hdr = sctp_addto_chunk(chunk, sizeof(sctp_errhdr_t), &err);
126} 126}
127 127
128/* A helper to initialize an op error inside a
129 * provided chunk, as most cause codes will be embedded inside an
130 * abort chunk. Differs from sctp_init_cause in that it won't oops
131 * if there isn't enough space in the op error chunk
132 */
133int sctp_init_cause_fixed(struct sctp_chunk *chunk, __be16 cause_code,
134 size_t paylen)
135{
136 sctp_errhdr_t err;
137 __u16 len;
138
139 /* Cause code constants are now defined in network order. */
140 err.cause = cause_code;
141 len = sizeof(sctp_errhdr_t) + paylen;
142 err.length = htons(len);
143
144 if (skb_tailroom(chunk->skb) > len)
145 return -ENOSPC;
146 chunk->subh.err_hdr = sctp_addto_chunk_fixed(chunk,
147 sizeof(sctp_errhdr_t),
148 &err);
149 return 0;
150}
128/* 3.3.2 Initiation (INIT) (1) 151/* 3.3.2 Initiation (INIT) (1)
129 * 152 *
130 * This chunk is used to initiate a SCTP association between two 153 * This chunk is used to initiate a SCTP association between two
@@ -208,7 +231,8 @@ struct sctp_chunk *sctp_make_init(const struct sctp_association *asoc,
208 sp = sctp_sk(asoc->base.sk); 231 sp = sctp_sk(asoc->base.sk);
209 num_types = sp->pf->supported_addrs(sp, types); 232 num_types = sp->pf->supported_addrs(sp, types);
210 233
211 chunksize = sizeof(init) + addrs_len + SCTP_SAT_LEN(num_types); 234 chunksize = sizeof(init) + addrs_len;
235 chunksize += WORD_ROUND(SCTP_SAT_LEN(num_types));
212 chunksize += sizeof(ecap_param); 236 chunksize += sizeof(ecap_param);
213 237
214 if (sctp_prsctp_enable) 238 if (sctp_prsctp_enable)
@@ -238,14 +262,14 @@ struct sctp_chunk *sctp_make_init(const struct sctp_association *asoc,
238 /* Add HMACS parameter length if any were defined */ 262 /* Add HMACS parameter length if any were defined */
239 auth_hmacs = (sctp_paramhdr_t *)asoc->c.auth_hmacs; 263 auth_hmacs = (sctp_paramhdr_t *)asoc->c.auth_hmacs;
240 if (auth_hmacs->length) 264 if (auth_hmacs->length)
241 chunksize += ntohs(auth_hmacs->length); 265 chunksize += WORD_ROUND(ntohs(auth_hmacs->length));
242 else 266 else
243 auth_hmacs = NULL; 267 auth_hmacs = NULL;
244 268
245 /* Add CHUNKS parameter length */ 269 /* Add CHUNKS parameter length */
246 auth_chunks = (sctp_paramhdr_t *)asoc->c.auth_chunks; 270 auth_chunks = (sctp_paramhdr_t *)asoc->c.auth_chunks;
247 if (auth_chunks->length) 271 if (auth_chunks->length)
248 chunksize += ntohs(auth_chunks->length); 272 chunksize += WORD_ROUND(ntohs(auth_chunks->length));
249 else 273 else
250 auth_chunks = NULL; 274 auth_chunks = NULL;
251 275
@@ -255,7 +279,8 @@ struct sctp_chunk *sctp_make_init(const struct sctp_association *asoc,
255 279
256 /* If we have any extensions to report, account for that */ 280 /* If we have any extensions to report, account for that */
257 if (num_ext) 281 if (num_ext)
258 chunksize += sizeof(sctp_supported_ext_param_t) + num_ext; 282 chunksize += WORD_ROUND(sizeof(sctp_supported_ext_param_t) +
283 num_ext);
259 284
260 /* RFC 2960 3.3.2 Initiation (INIT) (1) 285 /* RFC 2960 3.3.2 Initiation (INIT) (1)
261 * 286 *
@@ -397,13 +422,13 @@ struct sctp_chunk *sctp_make_init_ack(const struct sctp_association *asoc,
397 422
398 auth_hmacs = (sctp_paramhdr_t *)asoc->c.auth_hmacs; 423 auth_hmacs = (sctp_paramhdr_t *)asoc->c.auth_hmacs;
399 if (auth_hmacs->length) 424 if (auth_hmacs->length)
400 chunksize += ntohs(auth_hmacs->length); 425 chunksize += WORD_ROUND(ntohs(auth_hmacs->length));
401 else 426 else
402 auth_hmacs = NULL; 427 auth_hmacs = NULL;
403 428
404 auth_chunks = (sctp_paramhdr_t *)asoc->c.auth_chunks; 429 auth_chunks = (sctp_paramhdr_t *)asoc->c.auth_chunks;
405 if (auth_chunks->length) 430 if (auth_chunks->length)
406 chunksize += ntohs(auth_chunks->length); 431 chunksize += WORD_ROUND(ntohs(auth_chunks->length));
407 else 432 else
408 auth_chunks = NULL; 433 auth_chunks = NULL;
409 434
@@ -412,17 +437,25 @@ struct sctp_chunk *sctp_make_init_ack(const struct sctp_association *asoc,
412 } 437 }
413 438
414 if (num_ext) 439 if (num_ext)
415 chunksize += sizeof(sctp_supported_ext_param_t) + num_ext; 440 chunksize += WORD_ROUND(sizeof(sctp_supported_ext_param_t) +
441 num_ext);
416 442
417 /* Now allocate and fill out the chunk. */ 443 /* Now allocate and fill out the chunk. */
418 retval = sctp_make_chunk(asoc, SCTP_CID_INIT_ACK, 0, chunksize); 444 retval = sctp_make_chunk(asoc, SCTP_CID_INIT_ACK, 0, chunksize);
419 if (!retval) 445 if (!retval)
420 goto nomem_chunk; 446 goto nomem_chunk;
421 447
422 /* Per the advice in RFC 2960 6.4, send this reply to 448 /* RFC 2960 6.4 Multi-homed SCTP Endpoints
423 * the source of the INIT packet. 449 *
450 * An endpoint SHOULD transmit reply chunks (e.g., SACK,
451 * HEARTBEAT ACK, * etc.) to the same destination transport
452 * address from which it received the DATA or control chunk
453 * to which it is replying.
454 *
455 * [INIT ACK back to where the INIT came from.]
424 */ 456 */
425 retval->transport = chunk->transport; 457 retval->transport = chunk->transport;
458
426 retval->subh.init_hdr = 459 retval->subh.init_hdr =
427 sctp_addto_chunk(retval, sizeof(initack), &initack); 460 sctp_addto_chunk(retval, sizeof(initack), &initack);
428 retval->param_hdr.v = sctp_addto_chunk(retval, addrs_len, addrs.v); 461 retval->param_hdr.v = sctp_addto_chunk(retval, addrs_len, addrs.v);
@@ -461,18 +494,6 @@ struct sctp_chunk *sctp_make_init_ack(const struct sctp_association *asoc,
461 /* We need to remove the const qualifier at this point. */ 494 /* We need to remove the const qualifier at this point. */
462 retval->asoc = (struct sctp_association *) asoc; 495 retval->asoc = (struct sctp_association *) asoc;
463 496
464 /* RFC 2960 6.4 Multi-homed SCTP Endpoints
465 *
466 * An endpoint SHOULD transmit reply chunks (e.g., SACK,
467 * HEARTBEAT ACK, * etc.) to the same destination transport
468 * address from which it received the DATA or control chunk
469 * to which it is replying.
470 *
471 * [INIT ACK back to where the INIT came from.]
472 */
473 if (chunk)
474 retval->transport = chunk->transport;
475
476nomem_chunk: 497nomem_chunk:
477 kfree(cookie); 498 kfree(cookie);
478nomem_cookie: 499nomem_cookie:
@@ -1129,6 +1150,24 @@ nodata:
1129 return retval; 1150 return retval;
1130} 1151}
1131 1152
1153/* Create an Operation Error chunk of a fixed size,
1154 * specifically, max(asoc->pathmtu, SCTP_DEFAULT_MAXSEGMENT)
1155 * This is a helper function to allocate an error chunk for
1156 * for those invalid parameter codes in which we may not want
1157 * to report all the errors, if the incomming chunk is large
1158 */
1159static inline struct sctp_chunk *sctp_make_op_error_fixed(
1160 const struct sctp_association *asoc,
1161 const struct sctp_chunk *chunk)
1162{
1163 size_t size = asoc ? asoc->pathmtu : 0;
1164
1165 if (!size)
1166 size = SCTP_DEFAULT_MAXSEGMENT;
1167
1168 return sctp_make_op_error_space(asoc, chunk, size);
1169}
1170
1132/* Create an Operation Error chunk. */ 1171/* Create an Operation Error chunk. */
1133struct sctp_chunk *sctp_make_op_error(const struct sctp_association *asoc, 1172struct sctp_chunk *sctp_make_op_error(const struct sctp_association *asoc,
1134 const struct sctp_chunk *chunk, 1173 const struct sctp_chunk *chunk,
@@ -1210,7 +1249,6 @@ struct sctp_chunk *sctp_chunkify(struct sk_buff *skb,
1210 INIT_LIST_HEAD(&retval->list); 1249 INIT_LIST_HEAD(&retval->list);
1211 retval->skb = skb; 1250 retval->skb = skb;
1212 retval->asoc = (struct sctp_association *)asoc; 1251 retval->asoc = (struct sctp_association *)asoc;
1213 retval->resent = 0;
1214 retval->has_tsn = 0; 1252 retval->has_tsn = 0;
1215 retval->has_ssn = 0; 1253 retval->has_ssn = 0;
1216 retval->rtt_in_progress = 0; 1254 retval->rtt_in_progress = 0;
@@ -1371,6 +1409,18 @@ void *sctp_addto_chunk(struct sctp_chunk *chunk, int len, const void *data)
1371 return target; 1409 return target;
1372} 1410}
1373 1411
1412/* Append bytes to the end of a chunk. Returns NULL if there isn't sufficient
1413 * space in the chunk
1414 */
1415void *sctp_addto_chunk_fixed(struct sctp_chunk *chunk,
1416 int len, const void *data)
1417{
1418 if (skb_tailroom(chunk->skb) > len)
1419 return sctp_addto_chunk(chunk, len, data);
1420 else
1421 return NULL;
1422}
1423
1374/* Append bytes from user space to the end of a chunk. Will panic if 1424/* Append bytes from user space to the end of a chunk. Will panic if
1375 * chunk is not big enough. 1425 * chunk is not big enough.
1376 * Returns a kernel err value. 1426 * Returns a kernel err value.
@@ -1974,13 +2024,12 @@ static sctp_ierror_t sctp_process_unk_param(const struct sctp_association *asoc,
1974 * returning multiple unknown parameters. 2024 * returning multiple unknown parameters.
1975 */ 2025 */
1976 if (NULL == *errp) 2026 if (NULL == *errp)
1977 *errp = sctp_make_op_error_space(asoc, chunk, 2027 *errp = sctp_make_op_error_fixed(asoc, chunk);
1978 ntohs(chunk->chunk_hdr->length));
1979 2028
1980 if (*errp) { 2029 if (*errp) {
1981 sctp_init_cause(*errp, SCTP_ERROR_UNKNOWN_PARAM, 2030 sctp_init_cause_fixed(*errp, SCTP_ERROR_UNKNOWN_PARAM,
1982 WORD_ROUND(ntohs(param.p->length))); 2031 WORD_ROUND(ntohs(param.p->length)));
1983 sctp_addto_chunk(*errp, 2032 sctp_addto_chunk_fixed(*errp,
1984 WORD_ROUND(ntohs(param.p->length)), 2033 WORD_ROUND(ntohs(param.p->length)),
1985 param.v); 2034 param.v);
1986 } else { 2035 } else {
@@ -3315,21 +3364,6 @@ int sctp_process_asconf_ack(struct sctp_association *asoc,
3315 sctp_chunk_free(asconf); 3364 sctp_chunk_free(asconf);
3316 asoc->addip_last_asconf = NULL; 3365 asoc->addip_last_asconf = NULL;
3317 3366
3318 /* Send the next asconf chunk from the addip chunk queue. */
3319 if (!list_empty(&asoc->addip_chunk_list)) {
3320 struct list_head *entry = asoc->addip_chunk_list.next;
3321 asconf = list_entry(entry, struct sctp_chunk, list);
3322
3323 list_del_init(entry);
3324
3325 /* Hold the chunk until an ASCONF_ACK is received. */
3326 sctp_chunk_hold(asconf);
3327 if (sctp_primitive_ASCONF(asoc, asconf))
3328 sctp_chunk_free(asconf);
3329 else
3330 asoc->addip_last_asconf = asconf;
3331 }
3332
3333 return retval; 3367 return retval;
3334} 3368}
3335 3369