aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/net/sctp/sm.h2
-rw-r--r--include/net/sctp/structs.h1
-rw-r--r--net/sctp/sm_make_chunk.c73
-rw-r--r--net/sctp/sm_statefuns.c4
4 files changed, 56 insertions, 24 deletions
diff --git a/include/net/sctp/sm.h b/include/net/sctp/sm.h
index 73cb9943c8a..991c85bb9e3 100644
--- a/include/net/sctp/sm.h
+++ b/include/net/sctp/sm.h
@@ -214,7 +214,7 @@ struct sctp_chunk *sctp_make_shutdown_ack(const struct sctp_association *asoc,
214 const struct sctp_chunk *); 214 const struct sctp_chunk *);
215struct sctp_chunk *sctp_make_shutdown_complete(const struct sctp_association *, 215struct sctp_chunk *sctp_make_shutdown_complete(const struct sctp_association *,
216 const struct sctp_chunk *); 216 const struct sctp_chunk *);
217void sctp_init_cause(struct sctp_chunk *, __be16 cause, const void *, size_t); 217void sctp_init_cause(struct sctp_chunk *, __be16 cause, size_t);
218struct sctp_chunk *sctp_make_abort(const struct sctp_association *, 218struct sctp_chunk *sctp_make_abort(const struct sctp_association *,
219 const struct sctp_chunk *, 219 const struct sctp_chunk *,
220 const size_t hint); 220 const size_t hint);
diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h
index ee4559b1130..c0d5848c33d 100644
--- a/include/net/sctp/structs.h
+++ b/include/net/sctp/structs.h
@@ -726,6 +726,7 @@ int sctp_user_addto_chunk(struct sctp_chunk *chunk, int off, int len,
726 struct iovec *data); 726 struct iovec *data);
727void sctp_chunk_free(struct sctp_chunk *); 727void sctp_chunk_free(struct sctp_chunk *);
728void *sctp_addto_chunk(struct sctp_chunk *, int len, const void *data); 728void *sctp_addto_chunk(struct sctp_chunk *, int len, const void *data);
729void *sctp_addto_param(struct sctp_chunk *, int len, const void *data);
729struct sctp_chunk *sctp_chunkify(struct sk_buff *, 730struct sctp_chunk *sctp_chunkify(struct sk_buff *,
730 const struct sctp_association *, 731 const struct sctp_association *,
731 struct sock *); 732 struct sock *);
diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c
index 93df833f34f..adc5e593472 100644
--- a/net/sctp/sm_make_chunk.c
+++ b/net/sctp/sm_make_chunk.c
@@ -110,7 +110,7 @@ static const struct sctp_paramhdr prsctp_param = {
110 * abort chunk. 110 * abort chunk.
111 */ 111 */
112void sctp_init_cause(struct sctp_chunk *chunk, __be16 cause_code, 112void sctp_init_cause(struct sctp_chunk *chunk, __be16 cause_code,
113 const void *payload, size_t paylen) 113 size_t paylen)
114{ 114{
115 sctp_errhdr_t err; 115 sctp_errhdr_t err;
116 __u16 len; 116 __u16 len;
@@ -120,7 +120,6 @@ void sctp_init_cause(struct sctp_chunk *chunk, __be16 cause_code,
120 len = sizeof(sctp_errhdr_t) + paylen; 120 len = sizeof(sctp_errhdr_t) + paylen;
121 err.length = htons(len); 121 err.length = htons(len);
122 chunk->subh.err_hdr = sctp_addto_chunk(chunk, sizeof(sctp_errhdr_t), &err); 122 chunk->subh.err_hdr = sctp_addto_chunk(chunk, sizeof(sctp_errhdr_t), &err);
123 sctp_addto_chunk(chunk, paylen, payload);
124} 123}
125 124
126/* 3.3.2 Initiation (INIT) (1) 125/* 3.3.2 Initiation (INIT) (1)
@@ -780,8 +779,8 @@ struct sctp_chunk *sctp_make_abort_no_data(
780 779
781 /* Put the tsn back into network byte order. */ 780 /* Put the tsn back into network byte order. */
782 payload = htonl(tsn); 781 payload = htonl(tsn);
783 sctp_init_cause(retval, SCTP_ERROR_NO_DATA, (const void *)&payload, 782 sctp_init_cause(retval, SCTP_ERROR_NO_DATA, sizeof(payload));
784 sizeof(payload)); 783 sctp_addto_chunk(retval, sizeof(payload), (const void *)&payload);
785 784
786 /* RFC 2960 6.4 Multi-homed SCTP Endpoints 785 /* RFC 2960 6.4 Multi-homed SCTP Endpoints
787 * 786 *
@@ -823,7 +822,8 @@ struct sctp_chunk *sctp_make_abort_user(const struct sctp_association *asoc,
823 goto err_copy; 822 goto err_copy;
824 } 823 }
825 824
826 sctp_init_cause(retval, SCTP_ERROR_USER_ABORT, payload, paylen); 825 sctp_init_cause(retval, SCTP_ERROR_USER_ABORT, paylen);
826 sctp_addto_chunk(retval, paylen, payload);
827 827
828 if (paylen) 828 if (paylen)
829 kfree(payload); 829 kfree(payload);
@@ -850,15 +850,17 @@ struct sctp_chunk *sctp_make_abort_violation(
850 struct sctp_paramhdr phdr; 850 struct sctp_paramhdr phdr;
851 851
852 retval = sctp_make_abort(asoc, chunk, sizeof(sctp_errhdr_t) + paylen 852 retval = sctp_make_abort(asoc, chunk, sizeof(sctp_errhdr_t) + paylen
853 + sizeof(sctp_chunkhdr_t)); 853 + sizeof(sctp_paramhdr_t));
854 if (!retval) 854 if (!retval)
855 goto end; 855 goto end;
856 856
857 sctp_init_cause(retval, SCTP_ERROR_PROTO_VIOLATION, payload, paylen); 857 sctp_init_cause(retval, SCTP_ERROR_PROTO_VIOLATION, paylen
858 + sizeof(sctp_paramhdr_t));
858 859
859 phdr.type = htons(chunk->chunk_hdr->type); 860 phdr.type = htons(chunk->chunk_hdr->type);
860 phdr.length = chunk->chunk_hdr->length; 861 phdr.length = chunk->chunk_hdr->length;
861 sctp_addto_chunk(retval, sizeof(sctp_paramhdr_t), &phdr); 862 sctp_addto_chunk(retval, paylen, payload);
863 sctp_addto_param(retval, sizeof(sctp_paramhdr_t), &phdr);
862 864
863end: 865end:
864 return retval; 866 return retval;
@@ -955,7 +957,8 @@ struct sctp_chunk *sctp_make_op_error(const struct sctp_association *asoc,
955 if (!retval) 957 if (!retval)
956 goto nodata; 958 goto nodata;
957 959
958 sctp_init_cause(retval, cause_code, payload, paylen); 960 sctp_init_cause(retval, cause_code, paylen);
961 sctp_addto_chunk(retval, paylen, payload);
959 962
960nodata: 963nodata:
961 return retval; 964 return retval;
@@ -1143,6 +1146,25 @@ void *sctp_addto_chunk(struct sctp_chunk *chunk, int len, const void *data)
1143 return target; 1146 return target;
1144} 1147}
1145 1148
1149/* Append bytes to the end of a parameter. Will panic if chunk is not big
1150 * enough.
1151 */
1152void *sctp_addto_param(struct sctp_chunk *chunk, int len, const void *data)
1153{
1154 void *target;
1155 int chunklen = ntohs(chunk->chunk_hdr->length);
1156
1157 target = skb_put(chunk->skb, len);
1158
1159 memcpy(target, data, len);
1160
1161 /* Adjust the chunk length field. */
1162 chunk->chunk_hdr->length = htons(chunklen + len);
1163 chunk->chunk_end = skb_tail_pointer(chunk->skb);
1164
1165 return target;
1166}
1167
1146/* Append bytes from user space to the end of a chunk. Will panic if 1168/* Append bytes from user space to the end of a chunk. Will panic if
1147 * chunk is not big enough. 1169 * chunk is not big enough.
1148 * Returns a kernel err value. 1170 * Returns a kernel err value.
@@ -1477,7 +1499,8 @@ no_hmac:
1477 __be32 n = htonl(usecs); 1499 __be32 n = htonl(usecs);
1478 1500
1479 sctp_init_cause(*errp, SCTP_ERROR_STALE_COOKIE, 1501 sctp_init_cause(*errp, SCTP_ERROR_STALE_COOKIE,
1480 &n, sizeof(n)); 1502 sizeof(n));
1503 sctp_addto_chunk(*errp, sizeof(n), &n);
1481 *error = -SCTP_IERROR_STALE_COOKIE; 1504 *error = -SCTP_IERROR_STALE_COOKIE;
1482 } else 1505 } else
1483 *error = -SCTP_IERROR_NOMEM; 1506 *error = -SCTP_IERROR_NOMEM;
@@ -1567,7 +1590,8 @@ static int sctp_process_missing_param(const struct sctp_association *asoc,
1567 report.num_missing = htonl(1); 1590 report.num_missing = htonl(1);
1568 report.type = paramtype; 1591 report.type = paramtype;
1569 sctp_init_cause(*errp, SCTP_ERROR_MISS_PARAM, 1592 sctp_init_cause(*errp, SCTP_ERROR_MISS_PARAM,
1570 &report, sizeof(report)); 1593 sizeof(report));
1594 sctp_addto_chunk(*errp, sizeof(report), &report);
1571 } 1595 }
1572 1596
1573 /* Stop processing this chunk. */ 1597 /* Stop processing this chunk. */
@@ -1585,7 +1609,7 @@ static int sctp_process_inv_mandatory(const struct sctp_association *asoc,
1585 *errp = sctp_make_op_error_space(asoc, chunk, 0); 1609 *errp = sctp_make_op_error_space(asoc, chunk, 0);
1586 1610
1587 if (*errp) 1611 if (*errp)
1588 sctp_init_cause(*errp, SCTP_ERROR_INV_PARAM, NULL, 0); 1612 sctp_init_cause(*errp, SCTP_ERROR_INV_PARAM, 0);
1589 1613
1590 /* Stop processing this chunk. */ 1614 /* Stop processing this chunk. */
1591 return 0; 1615 return 0;
@@ -1606,9 +1630,10 @@ static int sctp_process_inv_paramlength(const struct sctp_association *asoc,
1606 *errp = sctp_make_op_error_space(asoc, chunk, payload_len); 1630 *errp = sctp_make_op_error_space(asoc, chunk, payload_len);
1607 1631
1608 if (*errp) { 1632 if (*errp) {
1609 sctp_init_cause(*errp, SCTP_ERROR_PROTO_VIOLATION, error, 1633 sctp_init_cause(*errp, SCTP_ERROR_PROTO_VIOLATION,
1610 sizeof(error)); 1634 sizeof(error) + sizeof(sctp_paramhdr_t));
1611 sctp_addto_chunk(*errp, sizeof(sctp_paramhdr_t), param); 1635 sctp_addto_chunk(*errp, sizeof(error), error);
1636 sctp_addto_param(*errp, sizeof(sctp_paramhdr_t), param);
1612 } 1637 }
1613 1638
1614 return 0; 1639 return 0;
@@ -1629,9 +1654,10 @@ static int sctp_process_hn_param(const struct sctp_association *asoc,
1629 if (!*errp) 1654 if (!*errp)
1630 *errp = sctp_make_op_error_space(asoc, chunk, len); 1655 *errp = sctp_make_op_error_space(asoc, chunk, len);
1631 1656
1632 if (*errp) 1657 if (*errp) {
1633 sctp_init_cause(*errp, SCTP_ERROR_DNS_FAILED, 1658 sctp_init_cause(*errp, SCTP_ERROR_DNS_FAILED, len);
1634 param.v, len); 1659 sctp_addto_chunk(*errp, len, param.v);
1660 }
1635 1661
1636 /* Stop processing this chunk. */ 1662 /* Stop processing this chunk. */
1637 return 0; 1663 return 0;
@@ -1683,10 +1709,13 @@ static int sctp_process_unk_param(const struct sctp_association *asoc,
1683 *errp = sctp_make_op_error_space(asoc, chunk, 1709 *errp = sctp_make_op_error_space(asoc, chunk,
1684 ntohs(chunk->chunk_hdr->length)); 1710 ntohs(chunk->chunk_hdr->length));
1685 1711
1686 if (*errp) 1712 if (*errp) {
1687 sctp_init_cause(*errp, SCTP_ERROR_UNKNOWN_PARAM, 1713 sctp_init_cause(*errp, SCTP_ERROR_UNKNOWN_PARAM,
1688 param.v,
1689 WORD_ROUND(ntohs(param.p->length))); 1714 WORD_ROUND(ntohs(param.p->length)));
1715 sctp_addto_chunk(*errp,
1716 WORD_ROUND(ntohs(param.p->length)),
1717 param.v);
1718 }
1690 1719
1691 break; 1720 break;
1692 case SCTP_PARAM_ACTION_SKIP: 1721 case SCTP_PARAM_ACTION_SKIP:
@@ -1701,8 +1730,10 @@ static int sctp_process_unk_param(const struct sctp_association *asoc,
1701 1730
1702 if (*errp) { 1731 if (*errp) {
1703 sctp_init_cause(*errp, SCTP_ERROR_UNKNOWN_PARAM, 1732 sctp_init_cause(*errp, SCTP_ERROR_UNKNOWN_PARAM,
1704 param.v,
1705 WORD_ROUND(ntohs(param.p->length))); 1733 WORD_ROUND(ntohs(param.p->length)));
1734 sctp_addto_chunk(*errp,
1735 WORD_ROUND(ntohs(param.p->length)),
1736 param.v);
1706 } else { 1737 } else {
1707 /* If there is no memory for generating the ERROR 1738 /* If there is no memory for generating the ERROR
1708 * report as specified, an ABORT will be triggered 1739 * report as specified, an ABORT will be triggered
diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c
index 71cad56dd73..350d4765472 100644
--- a/net/sctp/sm_statefuns.c
+++ b/net/sctp/sm_statefuns.c
@@ -3362,7 +3362,7 @@ sctp_disposition_t sctp_sf_do_asconf_ack(const struct sctp_endpoint *ep,
3362 abort = sctp_make_abort(asoc, asconf_ack, 3362 abort = sctp_make_abort(asoc, asconf_ack,
3363 sizeof(sctp_errhdr_t)); 3363 sizeof(sctp_errhdr_t));
3364 if (abort) { 3364 if (abort) {
3365 sctp_init_cause(abort, SCTP_ERROR_ASCONF_ACK, NULL, 0); 3365 sctp_init_cause(abort, SCTP_ERROR_ASCONF_ACK, 0);
3366 sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, 3366 sctp_add_cmd_sf(commands, SCTP_CMD_REPLY,
3367 SCTP_CHUNK(abort)); 3367 SCTP_CHUNK(abort));
3368 } 3368 }
@@ -3392,7 +3392,7 @@ sctp_disposition_t sctp_sf_do_asconf_ack(const struct sctp_endpoint *ep,
3392 abort = sctp_make_abort(asoc, asconf_ack, 3392 abort = sctp_make_abort(asoc, asconf_ack,
3393 sizeof(sctp_errhdr_t)); 3393 sizeof(sctp_errhdr_t));
3394 if (abort) { 3394 if (abort) {
3395 sctp_init_cause(abort, SCTP_ERROR_RSRC_LOW, NULL, 0); 3395 sctp_init_cause(abort, SCTP_ERROR_RSRC_LOW, 0);
3396 sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, 3396 sctp_add_cmd_sf(commands, SCTP_CMD_REPLY,
3397 SCTP_CHUNK(abort)); 3397 SCTP_CHUNK(abort));
3398 } 3398 }