sctp: Fix malformed "Invalid Stream Identifier" error

The "Invalid Stream Identifier" error has a 16 bit reserved
field at the end, thus making the parameter length be 8 bytes.
We've never supplied that reserved field making wireshark
tag the packet as malformed.

Reported-by: Chris Dischino <cdischino@sonusnet.com>
Signed-off-by: Vlad Yasevich <vladislav.yasevich@hp.com>
This commit is contained in:
Vlad Yasevich 2009-11-23 15:53:56 -05:00
parent b93d647174
commit 6383cfb3ed
3 changed files with 19 additions and 10 deletions

View file

@ -243,7 +243,8 @@ struct sctp_chunk *sctp_make_op_error(const struct sctp_association *,
const struct sctp_chunk *chunk, const struct sctp_chunk *chunk,
__be16 cause_code, __be16 cause_code,
const void *payload, const void *payload,
size_t paylen); size_t paylen,
size_t reserve_tail);
struct sctp_chunk *sctp_make_asconf_update_ip(struct sctp_association *, struct sctp_chunk *sctp_make_asconf_update_ip(struct sctp_association *,
union sctp_addr *, union sctp_addr *,

View file

@ -987,7 +987,10 @@ static void *sctp_addto_param(struct sctp_chunk *chunk, int len,
target = skb_put(chunk->skb, len); target = skb_put(chunk->skb, len);
memcpy(target, data, len); if (data)
memcpy(target, data, len);
else
memset(target, 0, len);
/* Adjust the chunk length field. */ /* Adjust the chunk length field. */
chunk->chunk_hdr->length = htons(chunklen + len); chunk->chunk_hdr->length = htons(chunklen + len);
@ -1129,16 +1132,18 @@ nodata:
struct sctp_chunk *sctp_make_op_error(const struct sctp_association *asoc, struct sctp_chunk *sctp_make_op_error(const struct sctp_association *asoc,
const struct sctp_chunk *chunk, const struct sctp_chunk *chunk,
__be16 cause_code, const void *payload, __be16 cause_code, const void *payload,
size_t paylen) size_t paylen, size_t reserve_tail)
{ {
struct sctp_chunk *retval; struct sctp_chunk *retval;
retval = sctp_make_op_error_space(asoc, chunk, paylen); retval = sctp_make_op_error_space(asoc, chunk, paylen + reserve_tail);
if (!retval) if (!retval)
goto nodata; goto nodata;
sctp_init_cause(retval, cause_code, paylen); sctp_init_cause(retval, cause_code, paylen + reserve_tail);
sctp_addto_chunk(retval, paylen, payload); sctp_addto_chunk(retval, paylen, payload);
if (reserve_tail)
sctp_addto_param(retval, reserve_tail, NULL);
nodata: nodata:
return retval; return retval;

View file

@ -1720,7 +1720,7 @@ static sctp_disposition_t sctp_sf_do_dupcook_a(const struct sctp_endpoint *ep,
err = sctp_make_op_error(asoc, chunk, err = sctp_make_op_error(asoc, chunk,
SCTP_ERROR_COOKIE_IN_SHUTDOWN, SCTP_ERROR_COOKIE_IN_SHUTDOWN,
NULL, 0); NULL, 0, 0);
if (err) if (err)
sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, sctp_add_cmd_sf(commands, SCTP_CMD_REPLY,
SCTP_CHUNK(err)); SCTP_CHUNK(err));
@ -3977,7 +3977,7 @@ sctp_disposition_t sctp_sf_eat_auth(const struct sctp_endpoint *ep,
err_chunk = sctp_make_op_error(asoc, chunk, err_chunk = sctp_make_op_error(asoc, chunk,
SCTP_ERROR_UNSUP_HMAC, SCTP_ERROR_UNSUP_HMAC,
&auth_hdr->hmac_id, &auth_hdr->hmac_id,
sizeof(__u16)); sizeof(__u16), 0);
if (err_chunk) { if (err_chunk) {
sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, sctp_add_cmd_sf(commands, SCTP_CMD_REPLY,
SCTP_CHUNK(err_chunk)); SCTP_CHUNK(err_chunk));
@ -4069,7 +4069,8 @@ sctp_disposition_t sctp_sf_unk_chunk(const struct sctp_endpoint *ep,
hdr = unk_chunk->chunk_hdr; hdr = unk_chunk->chunk_hdr;
err_chunk = sctp_make_op_error(asoc, unk_chunk, err_chunk = sctp_make_op_error(asoc, unk_chunk,
SCTP_ERROR_UNKNOWN_CHUNK, hdr, SCTP_ERROR_UNKNOWN_CHUNK, hdr,
WORD_ROUND(ntohs(hdr->length))); WORD_ROUND(ntohs(hdr->length)),
0);
if (err_chunk) { if (err_chunk) {
sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, sctp_add_cmd_sf(commands, SCTP_CMD_REPLY,
SCTP_CHUNK(err_chunk)); SCTP_CHUNK(err_chunk));
@ -4088,7 +4089,8 @@ sctp_disposition_t sctp_sf_unk_chunk(const struct sctp_endpoint *ep,
hdr = unk_chunk->chunk_hdr; hdr = unk_chunk->chunk_hdr;
err_chunk = sctp_make_op_error(asoc, unk_chunk, err_chunk = sctp_make_op_error(asoc, unk_chunk,
SCTP_ERROR_UNKNOWN_CHUNK, hdr, SCTP_ERROR_UNKNOWN_CHUNK, hdr,
WORD_ROUND(ntohs(hdr->length))); WORD_ROUND(ntohs(hdr->length)),
0);
if (err_chunk) { if (err_chunk) {
sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, sctp_add_cmd_sf(commands, SCTP_CMD_REPLY,
SCTP_CHUNK(err_chunk)); SCTP_CHUNK(err_chunk));
@ -6052,7 +6054,8 @@ static int sctp_eat_data(const struct sctp_association *asoc,
err = sctp_make_op_error(asoc, chunk, SCTP_ERROR_INV_STRM, err = sctp_make_op_error(asoc, chunk, SCTP_ERROR_INV_STRM,
&data_hdr->stream, &data_hdr->stream,
sizeof(data_hdr->stream)); sizeof(data_hdr->stream),
sizeof(u16));
if (err) if (err)
sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, sctp_add_cmd_sf(commands, SCTP_CMD_REPLY,
SCTP_CHUNK(err)); SCTP_CHUNK(err));