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.c112
1 files changed, 77 insertions, 35 deletions
diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c
index 51c4d7fef1d2..79856c924525 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;
@@ -1128,7 +1131,7 @@ void *sctp_addto_chunk(struct sctp_chunk *chunk, int len, const void *data)
1128 void *target; 1131 void *target;
1129 void *padding; 1132 void *padding;
1130 int chunklen = ntohs(chunk->chunk_hdr->length); 1133 int chunklen = ntohs(chunk->chunk_hdr->length);
1131 int padlen = chunklen % 4; 1134 int padlen = WORD_ROUND(chunklen) - chunklen;
1132 1135
1133 padding = skb_put(chunk->skb, padlen); 1136 padding = skb_put(chunk->skb, padlen);
1134 target = skb_put(chunk->skb, len); 1137 target = skb_put(chunk->skb, len);
@@ -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.
@@ -1174,25 +1196,36 @@ out:
1174 */ 1196 */
1175void sctp_chunk_assign_ssn(struct sctp_chunk *chunk) 1197void sctp_chunk_assign_ssn(struct sctp_chunk *chunk)
1176{ 1198{
1199 struct sctp_datamsg *msg;
1200 struct sctp_chunk *lchunk;
1201 struct sctp_stream *stream;
1177 __u16 ssn; 1202 __u16 ssn;
1178 __u16 sid; 1203 __u16 sid;
1179 1204
1180 if (chunk->has_ssn) 1205 if (chunk->has_ssn)
1181 return; 1206 return;
1182 1207
1183 /* This is the last possible instant to assign a SSN. */ 1208 /* All fragments will be on the same stream */
1184 if (chunk->chunk_hdr->flags & SCTP_DATA_UNORDERED) { 1209 sid = ntohs(chunk->subh.data_hdr->stream);
1185 ssn = 0; 1210 stream = &chunk->asoc->ssnmap->out;
1186 } else {
1187 sid = ntohs(chunk->subh.data_hdr->stream);
1188 if (chunk->chunk_hdr->flags & SCTP_DATA_LAST_FRAG)
1189 ssn = sctp_ssn_next(&chunk->asoc->ssnmap->out, sid);
1190 else
1191 ssn = sctp_ssn_peek(&chunk->asoc->ssnmap->out, sid);
1192 }
1193 1211
1194 chunk->subh.data_hdr->ssn = htons(ssn); 1212 /* Now assign the sequence number to the entire message.
1195 chunk->has_ssn = 1; 1213 * All fragments must have the same stream sequence number.
1214 */
1215 msg = chunk->msg;
1216 list_for_each_entry(lchunk, &msg->chunks, frag_list) {
1217 if (lchunk->chunk_hdr->flags & SCTP_DATA_UNORDERED) {
1218 ssn = 0;
1219 } else {
1220 if (lchunk->chunk_hdr->flags & SCTP_DATA_LAST_FRAG)
1221 ssn = sctp_ssn_next(stream, sid);
1222 else
1223 ssn = sctp_ssn_peek(stream, sid);
1224 }
1225
1226 lchunk->subh.data_hdr->ssn = htons(ssn);
1227 lchunk->has_ssn = 1;
1228 }
1196} 1229}
1197 1230
1198/* Helper function to assign a TSN if needed. This assumes that both 1231/* Helper function to assign a TSN if needed. This assumes that both
@@ -1466,7 +1499,8 @@ no_hmac:
1466 __be32 n = htonl(usecs); 1499 __be32 n = htonl(usecs);
1467 1500
1468 sctp_init_cause(*errp, SCTP_ERROR_STALE_COOKIE, 1501 sctp_init_cause(*errp, SCTP_ERROR_STALE_COOKIE,
1469 &n, sizeof(n)); 1502 sizeof(n));
1503 sctp_addto_chunk(*errp, sizeof(n), &n);
1470 *error = -SCTP_IERROR_STALE_COOKIE; 1504 *error = -SCTP_IERROR_STALE_COOKIE;
1471 } else 1505 } else
1472 *error = -SCTP_IERROR_NOMEM; 1506 *error = -SCTP_IERROR_NOMEM;
@@ -1556,7 +1590,8 @@ static int sctp_process_missing_param(const struct sctp_association *asoc,
1556 report.num_missing = htonl(1); 1590 report.num_missing = htonl(1);
1557 report.type = paramtype; 1591 report.type = paramtype;
1558 sctp_init_cause(*errp, SCTP_ERROR_MISS_PARAM, 1592 sctp_init_cause(*errp, SCTP_ERROR_MISS_PARAM,
1559 &report, sizeof(report)); 1593 sizeof(report));
1594 sctp_addto_chunk(*errp, sizeof(report), &report);
1560 } 1595 }
1561 1596
1562 /* Stop processing this chunk. */ 1597 /* Stop processing this chunk. */
@@ -1574,7 +1609,7 @@ static int sctp_process_inv_mandatory(const struct sctp_association *asoc,
1574 *errp = sctp_make_op_error_space(asoc, chunk, 0); 1609 *errp = sctp_make_op_error_space(asoc, chunk, 0);
1575 1610
1576 if (*errp) 1611 if (*errp)
1577 sctp_init_cause(*errp, SCTP_ERROR_INV_PARAM, NULL, 0); 1612 sctp_init_cause(*errp, SCTP_ERROR_INV_PARAM, 0);
1578 1613
1579 /* Stop processing this chunk. */ 1614 /* Stop processing this chunk. */
1580 return 0; 1615 return 0;
@@ -1595,9 +1630,10 @@ static int sctp_process_inv_paramlength(const struct sctp_association *asoc,
1595 *errp = sctp_make_op_error_space(asoc, chunk, payload_len); 1630 *errp = sctp_make_op_error_space(asoc, chunk, payload_len);
1596 1631
1597 if (*errp) { 1632 if (*errp) {
1598 sctp_init_cause(*errp, SCTP_ERROR_PROTO_VIOLATION, error, 1633 sctp_init_cause(*errp, SCTP_ERROR_PROTO_VIOLATION,
1599 sizeof(error)); 1634 sizeof(error) + sizeof(sctp_paramhdr_t));
1600 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);
1601 } 1637 }
1602 1638
1603 return 0; 1639 return 0;
@@ -1618,9 +1654,10 @@ static int sctp_process_hn_param(const struct sctp_association *asoc,
1618 if (!*errp) 1654 if (!*errp)
1619 *errp = sctp_make_op_error_space(asoc, chunk, len); 1655 *errp = sctp_make_op_error_space(asoc, chunk, len);
1620 1656
1621 if (*errp) 1657 if (*errp) {
1622 sctp_init_cause(*errp, SCTP_ERROR_DNS_FAILED, 1658 sctp_init_cause(*errp, SCTP_ERROR_DNS_FAILED, len);
1623 param.v, len); 1659 sctp_addto_chunk(*errp, len, param.v);
1660 }
1624 1661
1625 /* Stop processing this chunk. */ 1662 /* Stop processing this chunk. */
1626 return 0; 1663 return 0;
@@ -1672,10 +1709,13 @@ static int sctp_process_unk_param(const struct sctp_association *asoc,
1672 *errp = sctp_make_op_error_space(asoc, chunk, 1709 *errp = sctp_make_op_error_space(asoc, chunk,
1673 ntohs(chunk->chunk_hdr->length)); 1710 ntohs(chunk->chunk_hdr->length));
1674 1711
1675 if (*errp) 1712 if (*errp) {
1676 sctp_init_cause(*errp, SCTP_ERROR_UNKNOWN_PARAM, 1713 sctp_init_cause(*errp, SCTP_ERROR_UNKNOWN_PARAM,
1677 param.v,
1678 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 }
1679 1719
1680 break; 1720 break;
1681 case SCTP_PARAM_ACTION_SKIP: 1721 case SCTP_PARAM_ACTION_SKIP:
@@ -1690,8 +1730,10 @@ static int sctp_process_unk_param(const struct sctp_association *asoc,
1690 1730
1691 if (*errp) { 1731 if (*errp) {
1692 sctp_init_cause(*errp, SCTP_ERROR_UNKNOWN_PARAM, 1732 sctp_init_cause(*errp, SCTP_ERROR_UNKNOWN_PARAM,
1693 param.v,
1694 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);
1695 } else { 1737 } else {
1696 /* If there is no memory for generating the ERROR 1738 /* If there is no memory for generating the ERROR
1697 * report as specified, an ABORT will be triggered 1739 * report as specified, an ABORT will be triggered
@@ -1791,7 +1833,7 @@ int sctp_verify_init(const struct sctp_association *asoc,
1791 * VIOLATION error. We build the ERROR chunk here and let the normal 1833 * VIOLATION error. We build the ERROR chunk here and let the normal
1792 * error handling code build and send the packet. 1834 * error handling code build and send the packet.
1793 */ 1835 */
1794 if (param.v < (void*)chunk->chunk_end - sizeof(sctp_paramhdr_t)) { 1836 if (param.v != (void*)chunk->chunk_end) {
1795 sctp_process_inv_paramlength(asoc, param.p, chunk, errp); 1837 sctp_process_inv_paramlength(asoc, param.p, chunk, errp);
1796 return 0; 1838 return 0;
1797 } 1839 }