|
@@ -108,7 +108,7 @@ static const struct sctp_paramhdr prsctp_param = {
|
|
|
cpu_to_be16(sizeof(struct sctp_paramhdr)),
|
|
|
};
|
|
|
|
|
|
-/* A helper to initialize to initialize an op error inside a
|
|
|
+/* A helper to initialize an op error inside a
|
|
|
* provided chunk, as most cause codes will be embedded inside an
|
|
|
* abort chunk.
|
|
|
*/
|
|
@@ -125,6 +125,29 @@ void sctp_init_cause(struct sctp_chunk *chunk, __be16 cause_code,
|
|
|
chunk->subh.err_hdr = sctp_addto_chunk(chunk, sizeof(sctp_errhdr_t), &err);
|
|
|
}
|
|
|
|
|
|
+/* A helper to initialize an op error inside a
|
|
|
+ * provided chunk, as most cause codes will be embedded inside an
|
|
|
+ * abort chunk. Differs from sctp_init_cause in that it won't oops
|
|
|
+ * if there isn't enough space in the op error chunk
|
|
|
+ */
|
|
|
+int sctp_init_cause_fixed(struct sctp_chunk *chunk, __be16 cause_code,
|
|
|
+ size_t paylen)
|
|
|
+{
|
|
|
+ sctp_errhdr_t err;
|
|
|
+ __u16 len;
|
|
|
+
|
|
|
+ /* Cause code constants are now defined in network order. */
|
|
|
+ err.cause = cause_code;
|
|
|
+ len = sizeof(sctp_errhdr_t) + paylen;
|
|
|
+ err.length = htons(len);
|
|
|
+
|
|
|
+ if (skb_tailroom(chunk->skb) > len)
|
|
|
+ return -ENOSPC;
|
|
|
+ chunk->subh.err_hdr = sctp_addto_chunk_fixed(chunk,
|
|
|
+ sizeof(sctp_errhdr_t),
|
|
|
+ &err);
|
|
|
+ return 0;
|
|
|
+}
|
|
|
/* 3.3.2 Initiation (INIT) (1)
|
|
|
*
|
|
|
* This chunk is used to initiate a SCTP association between two
|
|
@@ -1132,6 +1155,24 @@ nodata:
|
|
|
return retval;
|
|
|
}
|
|
|
|
|
|
+/* Create an Operation Error chunk of a fixed size,
|
|
|
+ * specifically, max(asoc->pathmtu, SCTP_DEFAULT_MAXSEGMENT)
|
|
|
+ * This is a helper function to allocate an error chunk for
|
|
|
+ * for those invalid parameter codes in which we may not want
|
|
|
+ * to report all the errors, if the incomming chunk is large
|
|
|
+ */
|
|
|
+static inline struct sctp_chunk *sctp_make_op_error_fixed(
|
|
|
+ const struct sctp_association *asoc,
|
|
|
+ const struct sctp_chunk *chunk)
|
|
|
+{
|
|
|
+ size_t size = asoc ? asoc->pathmtu : 0;
|
|
|
+
|
|
|
+ if (!size)
|
|
|
+ size = SCTP_DEFAULT_MAXSEGMENT;
|
|
|
+
|
|
|
+ return sctp_make_op_error_space(asoc, chunk, size);
|
|
|
+}
|
|
|
+
|
|
|
/* Create an Operation Error chunk. */
|
|
|
struct sctp_chunk *sctp_make_op_error(const struct sctp_association *asoc,
|
|
|
const struct sctp_chunk *chunk,
|
|
@@ -1374,6 +1415,18 @@ void *sctp_addto_chunk(struct sctp_chunk *chunk, int len, const void *data)
|
|
|
return target;
|
|
|
}
|
|
|
|
|
|
+/* Append bytes to the end of a chunk. Returns NULL if there isn't sufficient
|
|
|
+ * space in the chunk
|
|
|
+ */
|
|
|
+void *sctp_addto_chunk_fixed(struct sctp_chunk *chunk,
|
|
|
+ int len, const void *data)
|
|
|
+{
|
|
|
+ if (skb_tailroom(chunk->skb) > len)
|
|
|
+ return sctp_addto_chunk(chunk, len, data);
|
|
|
+ else
|
|
|
+ return NULL;
|
|
|
+}
|
|
|
+
|
|
|
/* Append bytes from user space to the end of a chunk. Will panic if
|
|
|
* chunk is not big enough.
|
|
|
* Returns a kernel err value.
|
|
@@ -1977,13 +2030,12 @@ static sctp_ierror_t sctp_process_unk_param(const struct sctp_association *asoc,
|
|
|
* returning multiple unknown parameters.
|
|
|
*/
|
|
|
if (NULL == *errp)
|
|
|
- *errp = sctp_make_op_error_space(asoc, chunk,
|
|
|
- ntohs(chunk->chunk_hdr->length));
|
|
|
+ *errp = sctp_make_op_error_fixed(asoc, chunk);
|
|
|
|
|
|
if (*errp) {
|
|
|
- sctp_init_cause(*errp, SCTP_ERROR_UNKNOWN_PARAM,
|
|
|
+ sctp_init_cause_fixed(*errp, SCTP_ERROR_UNKNOWN_PARAM,
|
|
|
WORD_ROUND(ntohs(param.p->length)));
|
|
|
- sctp_addto_chunk(*errp,
|
|
|
+ sctp_addto_chunk_fixed(*errp,
|
|
|
WORD_ROUND(ntohs(param.p->length)),
|
|
|
param.v);
|
|
|
} else {
|