|
@@ -110,7 +110,7 @@ static const struct sctp_paramhdr prsctp_param = {
|
|
* abort chunk.
|
|
* abort chunk.
|
|
*/
|
|
*/
|
|
void sctp_init_cause(struct sctp_chunk *chunk, __be16 cause_code,
|
|
void sctp_init_cause(struct sctp_chunk *chunk, __be16 cause_code,
|
|
- const void *payload, size_t paylen)
|
|
|
|
|
|
+ size_t paylen)
|
|
{
|
|
{
|
|
sctp_errhdr_t err;
|
|
sctp_errhdr_t err;
|
|
__u16 len;
|
|
__u16 len;
|
|
@@ -120,7 +120,6 @@ void sctp_init_cause(struct sctp_chunk *chunk, __be16 cause_code,
|
|
len = sizeof(sctp_errhdr_t) + paylen;
|
|
len = sizeof(sctp_errhdr_t) + paylen;
|
|
err.length = htons(len);
|
|
err.length = htons(len);
|
|
chunk->subh.err_hdr = sctp_addto_chunk(chunk, sizeof(sctp_errhdr_t), &err);
|
|
chunk->subh.err_hdr = sctp_addto_chunk(chunk, sizeof(sctp_errhdr_t), &err);
|
|
- sctp_addto_chunk(chunk, paylen, payload);
|
|
|
|
}
|
|
}
|
|
|
|
|
|
/* 3.3.2 Initiation (INIT) (1)
|
|
/* 3.3.2 Initiation (INIT) (1)
|
|
@@ -780,8 +779,8 @@ struct sctp_chunk *sctp_make_abort_no_data(
|
|
|
|
|
|
/* Put the tsn back into network byte order. */
|
|
/* Put the tsn back into network byte order. */
|
|
payload = htonl(tsn);
|
|
payload = htonl(tsn);
|
|
- sctp_init_cause(retval, SCTP_ERROR_NO_DATA, (const void *)&payload,
|
|
|
|
- sizeof(payload));
|
|
|
|
|
|
+ sctp_init_cause(retval, SCTP_ERROR_NO_DATA, sizeof(payload));
|
|
|
|
+ sctp_addto_chunk(retval, sizeof(payload), (const void *)&payload);
|
|
|
|
|
|
/* RFC 2960 6.4 Multi-homed SCTP Endpoints
|
|
/* RFC 2960 6.4 Multi-homed SCTP Endpoints
|
|
*
|
|
*
|
|
@@ -823,7 +822,8 @@ struct sctp_chunk *sctp_make_abort_user(const struct sctp_association *asoc,
|
|
goto err_copy;
|
|
goto err_copy;
|
|
}
|
|
}
|
|
|
|
|
|
- sctp_init_cause(retval, SCTP_ERROR_USER_ABORT, payload, paylen);
|
|
|
|
|
|
+ sctp_init_cause(retval, SCTP_ERROR_USER_ABORT, paylen);
|
|
|
|
+ sctp_addto_chunk(retval, paylen, payload);
|
|
|
|
|
|
if (paylen)
|
|
if (paylen)
|
|
kfree(payload);
|
|
kfree(payload);
|
|
@@ -850,15 +850,17 @@ struct sctp_chunk *sctp_make_abort_violation(
|
|
struct sctp_paramhdr phdr;
|
|
struct sctp_paramhdr phdr;
|
|
|
|
|
|
retval = sctp_make_abort(asoc, chunk, sizeof(sctp_errhdr_t) + paylen
|
|
retval = sctp_make_abort(asoc, chunk, sizeof(sctp_errhdr_t) + paylen
|
|
- + sizeof(sctp_chunkhdr_t));
|
|
|
|
|
|
+ + sizeof(sctp_paramhdr_t));
|
|
if (!retval)
|
|
if (!retval)
|
|
goto end;
|
|
goto end;
|
|
|
|
|
|
- sctp_init_cause(retval, SCTP_ERROR_PROTO_VIOLATION, payload, paylen);
|
|
|
|
|
|
+ sctp_init_cause(retval, SCTP_ERROR_PROTO_VIOLATION, paylen
|
|
|
|
+ + sizeof(sctp_paramhdr_t));
|
|
|
|
|
|
phdr.type = htons(chunk->chunk_hdr->type);
|
|
phdr.type = htons(chunk->chunk_hdr->type);
|
|
phdr.length = chunk->chunk_hdr->length;
|
|
phdr.length = chunk->chunk_hdr->length;
|
|
- sctp_addto_chunk(retval, sizeof(sctp_paramhdr_t), &phdr);
|
|
|
|
|
|
+ sctp_addto_chunk(retval, paylen, payload);
|
|
|
|
+ sctp_addto_param(retval, sizeof(sctp_paramhdr_t), &phdr);
|
|
|
|
|
|
end:
|
|
end:
|
|
return retval;
|
|
return retval;
|
|
@@ -955,7 +957,8 @@ struct sctp_chunk *sctp_make_op_error(const struct sctp_association *asoc,
|
|
if (!retval)
|
|
if (!retval)
|
|
goto nodata;
|
|
goto nodata;
|
|
|
|
|
|
- sctp_init_cause(retval, cause_code, payload, paylen);
|
|
|
|
|
|
+ sctp_init_cause(retval, cause_code, paylen);
|
|
|
|
+ sctp_addto_chunk(retval, paylen, payload);
|
|
|
|
|
|
nodata:
|
|
nodata:
|
|
return retval;
|
|
return retval;
|
|
@@ -1143,6 +1146,25 @@ void *sctp_addto_chunk(struct sctp_chunk *chunk, int len, const void *data)
|
|
return target;
|
|
return target;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+/* Append bytes to the end of a parameter. Will panic if chunk is not big
|
|
|
|
+ * enough.
|
|
|
|
+ */
|
|
|
|
+void *sctp_addto_param(struct sctp_chunk *chunk, int len, const void *data)
|
|
|
|
+{
|
|
|
|
+ void *target;
|
|
|
|
+ int chunklen = ntohs(chunk->chunk_hdr->length);
|
|
|
|
+
|
|
|
|
+ target = skb_put(chunk->skb, len);
|
|
|
|
+
|
|
|
|
+ memcpy(target, data, len);
|
|
|
|
+
|
|
|
|
+ /* Adjust the chunk length field. */
|
|
|
|
+ chunk->chunk_hdr->length = htons(chunklen + len);
|
|
|
|
+ chunk->chunk_end = skb_tail_pointer(chunk->skb);
|
|
|
|
+
|
|
|
|
+ return target;
|
|
|
|
+}
|
|
|
|
+
|
|
/* Append bytes from user space to the end of a chunk. Will panic if
|
|
/* Append bytes from user space to the end of a chunk. Will panic if
|
|
* chunk is not big enough.
|
|
* chunk is not big enough.
|
|
* Returns a kernel err value.
|
|
* Returns a kernel err value.
|
|
@@ -1477,7 +1499,8 @@ no_hmac:
|
|
__be32 n = htonl(usecs);
|
|
__be32 n = htonl(usecs);
|
|
|
|
|
|
sctp_init_cause(*errp, SCTP_ERROR_STALE_COOKIE,
|
|
sctp_init_cause(*errp, SCTP_ERROR_STALE_COOKIE,
|
|
- &n, sizeof(n));
|
|
|
|
|
|
+ sizeof(n));
|
|
|
|
+ sctp_addto_chunk(*errp, sizeof(n), &n);
|
|
*error = -SCTP_IERROR_STALE_COOKIE;
|
|
*error = -SCTP_IERROR_STALE_COOKIE;
|
|
} else
|
|
} else
|
|
*error = -SCTP_IERROR_NOMEM;
|
|
*error = -SCTP_IERROR_NOMEM;
|
|
@@ -1567,7 +1590,8 @@ static int sctp_process_missing_param(const struct sctp_association *asoc,
|
|
report.num_missing = htonl(1);
|
|
report.num_missing = htonl(1);
|
|
report.type = paramtype;
|
|
report.type = paramtype;
|
|
sctp_init_cause(*errp, SCTP_ERROR_MISS_PARAM,
|
|
sctp_init_cause(*errp, SCTP_ERROR_MISS_PARAM,
|
|
- &report, sizeof(report));
|
|
|
|
|
|
+ sizeof(report));
|
|
|
|
+ sctp_addto_chunk(*errp, sizeof(report), &report);
|
|
}
|
|
}
|
|
|
|
|
|
/* Stop processing this chunk. */
|
|
/* Stop processing this chunk. */
|
|
@@ -1585,7 +1609,7 @@ static int sctp_process_inv_mandatory(const struct sctp_association *asoc,
|
|
*errp = sctp_make_op_error_space(asoc, chunk, 0);
|
|
*errp = sctp_make_op_error_space(asoc, chunk, 0);
|
|
|
|
|
|
if (*errp)
|
|
if (*errp)
|
|
- sctp_init_cause(*errp, SCTP_ERROR_INV_PARAM, NULL, 0);
|
|
|
|
|
|
+ sctp_init_cause(*errp, SCTP_ERROR_INV_PARAM, 0);
|
|
|
|
|
|
/* Stop processing this chunk. */
|
|
/* Stop processing this chunk. */
|
|
return 0;
|
|
return 0;
|
|
@@ -1606,9 +1630,10 @@ static int sctp_process_inv_paramlength(const struct sctp_association *asoc,
|
|
*errp = sctp_make_op_error_space(asoc, chunk, payload_len);
|
|
*errp = sctp_make_op_error_space(asoc, chunk, payload_len);
|
|
|
|
|
|
if (*errp) {
|
|
if (*errp) {
|
|
- sctp_init_cause(*errp, SCTP_ERROR_PROTO_VIOLATION, error,
|
|
|
|
- sizeof(error));
|
|
|
|
- sctp_addto_chunk(*errp, sizeof(sctp_paramhdr_t), param);
|
|
|
|
|
|
+ sctp_init_cause(*errp, SCTP_ERROR_PROTO_VIOLATION,
|
|
|
|
+ sizeof(error) + sizeof(sctp_paramhdr_t));
|
|
|
|
+ sctp_addto_chunk(*errp, sizeof(error), error);
|
|
|
|
+ sctp_addto_param(*errp, sizeof(sctp_paramhdr_t), param);
|
|
}
|
|
}
|
|
|
|
|
|
return 0;
|
|
return 0;
|
|
@@ -1629,9 +1654,10 @@ static int sctp_process_hn_param(const struct sctp_association *asoc,
|
|
if (!*errp)
|
|
if (!*errp)
|
|
*errp = sctp_make_op_error_space(asoc, chunk, len);
|
|
*errp = sctp_make_op_error_space(asoc, chunk, len);
|
|
|
|
|
|
- if (*errp)
|
|
|
|
- sctp_init_cause(*errp, SCTP_ERROR_DNS_FAILED,
|
|
|
|
- param.v, len);
|
|
|
|
|
|
+ if (*errp) {
|
|
|
|
+ sctp_init_cause(*errp, SCTP_ERROR_DNS_FAILED, len);
|
|
|
|
+ sctp_addto_chunk(*errp, len, param.v);
|
|
|
|
+ }
|
|
|
|
|
|
/* Stop processing this chunk. */
|
|
/* Stop processing this chunk. */
|
|
return 0;
|
|
return 0;
|
|
@@ -1683,10 +1709,13 @@ static int sctp_process_unk_param(const struct sctp_association *asoc,
|
|
*errp = sctp_make_op_error_space(asoc, chunk,
|
|
*errp = sctp_make_op_error_space(asoc, chunk,
|
|
ntohs(chunk->chunk_hdr->length));
|
|
ntohs(chunk->chunk_hdr->length));
|
|
|
|
|
|
- if (*errp)
|
|
|
|
|
|
+ if (*errp) {
|
|
sctp_init_cause(*errp, SCTP_ERROR_UNKNOWN_PARAM,
|
|
sctp_init_cause(*errp, SCTP_ERROR_UNKNOWN_PARAM,
|
|
- param.v,
|
|
|
|
WORD_ROUND(ntohs(param.p->length)));
|
|
WORD_ROUND(ntohs(param.p->length)));
|
|
|
|
+ sctp_addto_chunk(*errp,
|
|
|
|
+ WORD_ROUND(ntohs(param.p->length)),
|
|
|
|
+ param.v);
|
|
|
|
+ }
|
|
|
|
|
|
break;
|
|
break;
|
|
case SCTP_PARAM_ACTION_SKIP:
|
|
case SCTP_PARAM_ACTION_SKIP:
|
|
@@ -1701,8 +1730,10 @@ static int sctp_process_unk_param(const struct sctp_association *asoc,
|
|
|
|
|
|
if (*errp) {
|
|
if (*errp) {
|
|
sctp_init_cause(*errp, SCTP_ERROR_UNKNOWN_PARAM,
|
|
sctp_init_cause(*errp, SCTP_ERROR_UNKNOWN_PARAM,
|
|
- param.v,
|
|
|
|
WORD_ROUND(ntohs(param.p->length)));
|
|
WORD_ROUND(ntohs(param.p->length)));
|
|
|
|
+ sctp_addto_chunk(*errp,
|
|
|
|
+ WORD_ROUND(ntohs(param.p->length)),
|
|
|
|
+ param.v);
|
|
} else {
|
|
} else {
|
|
/* If there is no memory for generating the ERROR
|
|
/* If there is no memory for generating the ERROR
|
|
* report as specified, an ABORT will be triggered
|
|
* report as specified, an ABORT will be triggered
|