Cleanup the handling of error causes for ERROR chunks. This fixes
an inconsistency of the padding handling. The final padding is now considered to be a chunk padding. MFC after: 1 week
This commit is contained in:
parent
8fbc5d1840
commit
86eda749af
@ -388,33 +388,32 @@ struct sctp_error_cause {
|
||||
} SCTP_PACKED;
|
||||
|
||||
struct sctp_error_invalid_stream {
|
||||
struct sctp_error_cause cause; /* code=SCTP_ERROR_INVALID_STREAM */
|
||||
struct sctp_error_cause cause; /* code=SCTP_CAUSE_INVALID_STREAM */
|
||||
uint16_t stream_id; /* stream id of the DATA in error */
|
||||
uint16_t reserved;
|
||||
} SCTP_PACKED;
|
||||
|
||||
struct sctp_error_missing_param {
|
||||
struct sctp_error_cause cause; /* code=SCTP_ERROR_MISSING_PARAM */
|
||||
struct sctp_error_cause cause; /* code=SCTP_CAUSE_MISSING_PARAM */
|
||||
uint32_t num_missing_params; /* number of missing parameters */
|
||||
/* uint16_t param_type's follow */
|
||||
uint16_t type[];
|
||||
} SCTP_PACKED;
|
||||
|
||||
struct sctp_error_stale_cookie {
|
||||
struct sctp_error_cause cause; /* code=SCTP_ERROR_STALE_COOKIE */
|
||||
struct sctp_error_cause cause; /* code=SCTP_CAUSE_STALE_COOKIE */
|
||||
uint32_t stale_time; /* time in usec of staleness */
|
||||
} SCTP_PACKED;
|
||||
|
||||
struct sctp_error_out_of_resource {
|
||||
struct sctp_error_cause cause; /* code=SCTP_ERROR_OUT_OF_RESOURCES */
|
||||
struct sctp_error_cause cause; /* code=SCTP_CAUSE_OUT_OF_RESOURCES */
|
||||
} SCTP_PACKED;
|
||||
|
||||
struct sctp_error_unresolv_addr {
|
||||
struct sctp_error_cause cause; /* code=SCTP_ERROR_UNRESOLVABLE_ADDR */
|
||||
|
||||
struct sctp_error_cause cause; /* code=SCTP_CAUSE_UNRESOLVABLE_ADDR */
|
||||
} SCTP_PACKED;
|
||||
|
||||
struct sctp_error_unrecognized_chunk {
|
||||
struct sctp_error_cause cause; /* code=SCTP_ERROR_UNRECOG_CHUNK */
|
||||
struct sctp_error_cause cause; /* code=SCTP_CAUSE_UNRECOG_CHUNK */
|
||||
struct sctp_chunkhdr ch;/* header from chunk in error */
|
||||
} SCTP_PACKED;
|
||||
|
||||
@ -423,6 +422,11 @@ struct sctp_error_no_user_data {
|
||||
uint32_t tsn; /* TSN of the empty data chunk */
|
||||
} SCTP_PACKED;
|
||||
|
||||
struct sctp_error_auth_invalid_hmac {
|
||||
struct sctp_error_cause cause; /* code=SCTP_CAUSE_UNSUPPORTED_HMACID */
|
||||
uint16_t hmac_id;
|
||||
} SCTP_PACKED;
|
||||
|
||||
/*
|
||||
* Main SCTP chunk types we place these here so natd and f/w's in user land
|
||||
* can find them.
|
||||
|
@ -1651,8 +1651,8 @@ sctp_handle_auth(struct sctp_tcb *stcb, struct sctp_auth_chunk *auth,
|
||||
|
||||
/* is the indicated HMAC supported? */
|
||||
if (!sctp_auth_is_supported_hmac(stcb->asoc.local_hmacs, hmac_id)) {
|
||||
struct mbuf *m_err;
|
||||
struct sctp_auth_invalid_hmac *err;
|
||||
struct mbuf *op_err;
|
||||
struct sctp_error_auth_invalid_hmac *cause;
|
||||
|
||||
SCTP_STAT_INCR(sctps_recvivalhmacid);
|
||||
SCTPDBG(SCTP_DEBUG_AUTH1,
|
||||
@ -1662,20 +1662,19 @@ sctp_handle_auth(struct sctp_tcb *stcb, struct sctp_auth_chunk *auth,
|
||||
* report this in an Error Chunk: Unsupported HMAC
|
||||
* Identifier
|
||||
*/
|
||||
m_err = sctp_get_mbuf_for_msg(sizeof(*err), 0, M_NOWAIT,
|
||||
1, MT_HEADER);
|
||||
if (m_err != NULL) {
|
||||
op_err = sctp_get_mbuf_for_msg(sizeof(struct sctp_error_auth_invalid_hmac),
|
||||
0, M_NOWAIT, 1, MT_HEADER);
|
||||
if (op_err != NULL) {
|
||||
/* pre-reserve some space */
|
||||
SCTP_BUF_RESV_UF(m_err, sizeof(struct sctp_chunkhdr));
|
||||
SCTP_BUF_RESV_UF(op_err, sizeof(struct sctp_chunkhdr));
|
||||
/* fill in the error */
|
||||
err = mtod(m_err, struct sctp_auth_invalid_hmac *);
|
||||
bzero(err, sizeof(*err));
|
||||
err->ph.param_type = htons(SCTP_CAUSE_UNSUPPORTED_HMACID);
|
||||
err->ph.param_length = htons(sizeof(*err));
|
||||
err->hmac_id = ntohs(hmac_id);
|
||||
SCTP_BUF_LEN(m_err) = sizeof(*err);
|
||||
cause = mtod(op_err, struct sctp_error_auth_invalid_hmac *);
|
||||
cause->cause.code = htons(SCTP_CAUSE_UNSUPPORTED_HMACID);
|
||||
cause->cause.length = htons(sizeof(struct sctp_error_auth_invalid_hmac));
|
||||
cause->hmac_id = ntohs(hmac_id);
|
||||
SCTP_BUF_LEN(op_err) = sizeof(struct sctp_error_auth_invalid_hmac);
|
||||
/* queue it */
|
||||
sctp_queue_op_err(stcb, m_err);
|
||||
sctp_queue_op_err(stcb, op_err);
|
||||
}
|
||||
return (-1);
|
||||
}
|
||||
|
@ -202,34 +202,6 @@ struct sctp_state_cookie { /* this is our definition... */
|
||||
*/
|
||||
} SCTP_PACKED;
|
||||
|
||||
|
||||
/* Used for NAT state error cause */
|
||||
struct sctp_missing_nat_state {
|
||||
uint16_t cause;
|
||||
uint16_t length;
|
||||
uint8_t data[];
|
||||
} SCTP_PACKED;
|
||||
|
||||
|
||||
struct sctp_inv_mandatory_param {
|
||||
uint16_t cause;
|
||||
uint16_t length;
|
||||
uint32_t num_param;
|
||||
uint16_t param;
|
||||
/*
|
||||
* We include this to 0 it since only a missing cookie will cause
|
||||
* this error.
|
||||
*/
|
||||
uint16_t resv;
|
||||
} SCTP_PACKED;
|
||||
|
||||
struct sctp_unresolv_addr {
|
||||
uint16_t cause;
|
||||
uint16_t length;
|
||||
uint16_t addr_type;
|
||||
uint16_t reserved; /* Only one invalid addr type */
|
||||
} SCTP_PACKED;
|
||||
|
||||
/* state cookie parameter */
|
||||
struct sctp_state_cookie_param {
|
||||
struct sctp_paramhdr ph;
|
||||
@ -370,28 +342,11 @@ struct sctp_shutdown_complete_chunk {
|
||||
struct sctp_chunkhdr ch;
|
||||
} SCTP_PACKED;
|
||||
|
||||
/* Oper error holding a stale cookie */
|
||||
struct sctp_stale_cookie_msg {
|
||||
struct sctp_paramhdr ph;/* really an error cause */
|
||||
uint32_t time_usec;
|
||||
} SCTP_PACKED;
|
||||
|
||||
struct sctp_adaptation_layer_indication {
|
||||
struct sctp_paramhdr ph;
|
||||
uint32_t indication;
|
||||
} SCTP_PACKED;
|
||||
|
||||
struct sctp_cookie_while_shutting_down {
|
||||
struct sctphdr sh;
|
||||
struct sctp_chunkhdr ch;
|
||||
struct sctp_paramhdr ph;/* really an error cause */
|
||||
} SCTP_PACKED;
|
||||
|
||||
struct sctp_shutdown_complete_msg {
|
||||
struct sctphdr sh;
|
||||
struct sctp_shutdown_complete_chunk shut_cmp;
|
||||
} SCTP_PACKED;
|
||||
|
||||
/*
|
||||
* draft-ietf-tsvwg-addip-sctp
|
||||
*/
|
||||
@ -554,12 +509,6 @@ struct sctp_auth_chunk {
|
||||
uint8_t hmac[];
|
||||
} SCTP_PACKED;
|
||||
|
||||
struct sctp_auth_invalid_hmac {
|
||||
struct sctp_paramhdr ph;
|
||||
uint16_t hmac_id;
|
||||
uint16_t padding;
|
||||
} SCTP_PACKED;
|
||||
|
||||
/*
|
||||
* we pre-reserve enough room for a ECNE or CWR AND a SACK with no missing
|
||||
* pieces. If ENCE is missing we could have a couple of blocks. This way we
|
||||
|
@ -1426,30 +1426,25 @@ sctp_process_a_data_chunk(struct sctp_tcb *stcb, struct sctp_association *asoc,
|
||||
}
|
||||
strmno = ntohs(ch->dp.stream_id);
|
||||
if (strmno >= asoc->streamincnt) {
|
||||
struct sctp_paramhdr *phdr;
|
||||
struct mbuf *mb;
|
||||
struct sctp_error_invalid_stream *cause;
|
||||
|
||||
mb = sctp_get_mbuf_for_msg((sizeof(struct sctp_paramhdr) * 2),
|
||||
op_err = sctp_get_mbuf_for_msg(sizeof(struct sctp_error_invalid_stream),
|
||||
0, M_NOWAIT, 1, MT_DATA);
|
||||
if (mb != NULL) {
|
||||
if (op_err != NULL) {
|
||||
/* add some space up front so prepend will work well */
|
||||
SCTP_BUF_RESV_UF(mb, sizeof(struct sctp_chunkhdr));
|
||||
phdr = mtod(mb, struct sctp_paramhdr *);
|
||||
SCTP_BUF_RESV_UF(op_err, sizeof(struct sctp_chunkhdr));
|
||||
cause = mtod(op_err, struct sctp_error_invalid_stream *);
|
||||
/*
|
||||
* Error causes are just param's and this one has
|
||||
* two back to back phdr, one with the error type
|
||||
* and size, the other with the streamid and a rsvd
|
||||
*/
|
||||
SCTP_BUF_LEN(mb) = (sizeof(struct sctp_paramhdr) * 2);
|
||||
phdr->param_type = htons(SCTP_CAUSE_INVALID_STREAM);
|
||||
phdr->param_length =
|
||||
htons(sizeof(struct sctp_paramhdr) * 2);
|
||||
phdr++;
|
||||
/* We insert the stream in the type field */
|
||||
phdr->param_type = ch->dp.stream_id;
|
||||
/* And set the length to 0 for the rsvd field */
|
||||
phdr->param_length = 0;
|
||||
sctp_queue_op_err(stcb, mb);
|
||||
SCTP_BUF_LEN(op_err) = sizeof(struct sctp_error_invalid_stream);
|
||||
cause->cause.code = htons(SCTP_CAUSE_INVALID_STREAM);
|
||||
cause->cause.length = htons(sizeof(struct sctp_error_invalid_stream));
|
||||
cause->stream_id = ch->dp.stream_id;
|
||||
cause->reserved = htons(0);
|
||||
sctp_queue_op_err(stcb, op_err);
|
||||
}
|
||||
SCTP_STAT_INCR(sctps_badsid);
|
||||
SCTP_TCB_LOCK_ASSERT(stcb);
|
||||
@ -2492,30 +2487,21 @@ sctp_process_data(struct mbuf **mm, int iphlen, int *offset, int length,
|
||||
/* unknown chunk type, use bit rules */
|
||||
if (ch->ch.chunk_type & 0x40) {
|
||||
/* Add a error report to the queue */
|
||||
struct mbuf *merr;
|
||||
struct sctp_paramhdr *phd;
|
||||
struct mbuf *op_err;
|
||||
struct sctp_gen_error_cause *cause;
|
||||
|
||||
merr = sctp_get_mbuf_for_msg(sizeof(*phd), 0, M_NOWAIT, 1, MT_DATA);
|
||||
if (merr) {
|
||||
phd = mtod(merr, struct sctp_paramhdr *);
|
||||
/*
|
||||
* We cheat and use param
|
||||
* type since we did not
|
||||
* bother to define a error
|
||||
* cause struct. They are
|
||||
* the same basic format
|
||||
* with different names.
|
||||
*/
|
||||
phd->param_type =
|
||||
htons(SCTP_CAUSE_UNRECOG_CHUNK);
|
||||
phd->param_length =
|
||||
htons(chk_length + sizeof(*phd));
|
||||
SCTP_BUF_LEN(merr) = sizeof(*phd);
|
||||
SCTP_BUF_NEXT(merr) = SCTP_M_COPYM(m, *offset, chk_length, M_NOWAIT);
|
||||
if (SCTP_BUF_NEXT(merr)) {
|
||||
sctp_queue_op_err(stcb, merr);
|
||||
op_err = sctp_get_mbuf_for_msg(sizeof(struct sctp_gen_error_cause),
|
||||
0, M_NOWAIT, 1, MT_DATA);
|
||||
if (op_err != NULL) {
|
||||
cause = mtod(op_err, struct sctp_gen_error_cause *);
|
||||
cause->code = htons(SCTP_CAUSE_UNRECOG_CHUNK);
|
||||
cause->length = htons(chk_length + sizeof(struct sctp_gen_error_cause));
|
||||
SCTP_BUF_LEN(op_err) = sizeof(struct sctp_gen_error_cause);
|
||||
SCTP_BUF_NEXT(op_err) = SCTP_M_COPYM(m, *offset, chk_length, M_NOWAIT);
|
||||
if (SCTP_BUF_NEXT(op_err) != NULL) {
|
||||
sctp_queue_op_err(stcb, op_err);
|
||||
} else {
|
||||
sctp_m_freem(merr);
|
||||
sctp_m_freem(op_err);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -530,25 +530,21 @@ sctp_process_init_ack(struct mbuf *m, int iphlen, int offset,
|
||||
* abandon the peer, its broke.
|
||||
*/
|
||||
if (retval == -3) {
|
||||
/* We abort with an error of missing mandatory param */
|
||||
op_err = sctp_generate_cause(SCTP_CAUSE_MISSING_PARAM, "");
|
||||
if (op_err) {
|
||||
/*
|
||||
* Expand beyond to include the mandatory
|
||||
* param cookie
|
||||
*/
|
||||
struct sctp_inv_mandatory_param *mp;
|
||||
size_t len;
|
||||
|
||||
SCTP_BUF_LEN(op_err) =
|
||||
sizeof(struct sctp_inv_mandatory_param);
|
||||
mp = mtod(op_err,
|
||||
struct sctp_inv_mandatory_param *);
|
||||
len = sizeof(struct sctp_error_missing_param) + sizeof(uint16_t);
|
||||
/* We abort with an error of missing mandatory param */
|
||||
op_err = sctp_get_mbuf_for_msg(len, 0, M_NOWAIT, 1, MT_DATA);
|
||||
if (op_err != NULL) {
|
||||
struct sctp_error_missing_param *cause;
|
||||
|
||||
SCTP_BUF_LEN(op_err) = len;
|
||||
cause = mtod(op_err, struct sctp_error_missing_param *);
|
||||
/* Subtract the reserved param */
|
||||
mp->length =
|
||||
htons(sizeof(struct sctp_inv_mandatory_param) - 2);
|
||||
mp->num_param = htonl(1);
|
||||
mp->param = htons(SCTP_STATE_COOKIE);
|
||||
mp->resv = 0;
|
||||
cause->cause.code = htons(SCTP_CAUSE_MISSING_PARAM);
|
||||
cause->cause.length = htons(len);
|
||||
cause->num_missing_params = htonl(1);
|
||||
cause->type[0] = htons(SCTP_STATE_COOKIE);
|
||||
}
|
||||
sctp_abort_association(stcb->sctp_ep, stcb, m, iphlen,
|
||||
src, dst, sh, op_err,
|
||||
@ -781,10 +777,10 @@ sctp_handle_abort(struct sctp_abort_chunk *abort,
|
||||
* Need to check the cause codes for our two magic nat
|
||||
* aborts which don't kill the assoc necessarily.
|
||||
*/
|
||||
struct sctp_missing_nat_state *natc;
|
||||
struct sctp_gen_error_cause *cause;
|
||||
|
||||
natc = (struct sctp_missing_nat_state *)(abort + 1);
|
||||
error = ntohs(natc->cause);
|
||||
cause = (struct sctp_gen_error_cause *)(abort + 1);
|
||||
error = ntohs(cause->code);
|
||||
if (error == SCTP_CAUSE_NAT_COLLIDING_STATE) {
|
||||
SCTPDBG(SCTP_DEBUG_INPUT2, "Received Colliding state abort flags:%x\n",
|
||||
abort->ch.chunk_flags);
|
||||
@ -2558,27 +2554,27 @@ sctp_handle_cookie_echo(struct mbuf *m, int iphlen, int offset,
|
||||
if (timevalcmp(&now, &time_expires, >)) {
|
||||
/* cookie is stale! */
|
||||
struct mbuf *op_err;
|
||||
struct sctp_stale_cookie_msg *scm;
|
||||
struct sctp_error_stale_cookie *cause;
|
||||
uint32_t tim;
|
||||
|
||||
op_err = sctp_get_mbuf_for_msg(sizeof(struct sctp_stale_cookie_msg),
|
||||
op_err = sctp_get_mbuf_for_msg(sizeof(struct sctp_error_stale_cookie),
|
||||
0, M_NOWAIT, 1, MT_DATA);
|
||||
if (op_err == NULL) {
|
||||
/* FOOBAR */
|
||||
return (NULL);
|
||||
}
|
||||
/* Set the len */
|
||||
SCTP_BUF_LEN(op_err) = sizeof(struct sctp_stale_cookie_msg);
|
||||
scm = mtod(op_err, struct sctp_stale_cookie_msg *);
|
||||
scm->ph.param_type = htons(SCTP_CAUSE_STALE_COOKIE);
|
||||
scm->ph.param_length = htons((sizeof(struct sctp_paramhdr) +
|
||||
SCTP_BUF_LEN(op_err) = sizeof(struct sctp_error_stale_cookie);
|
||||
cause = mtod(op_err, struct sctp_error_stale_cookie *);
|
||||
cause->cause.code = htons(SCTP_CAUSE_STALE_COOKIE);
|
||||
cause->cause.length = htons((sizeof(struct sctp_paramhdr) +
|
||||
(sizeof(uint32_t))));
|
||||
/* seconds to usec */
|
||||
tim = (now.tv_sec - time_expires.tv_sec) * 1000000;
|
||||
/* add in usec */
|
||||
if (tim == 0)
|
||||
tim = now.tv_usec - cookie->time_entered.tv_usec;
|
||||
scm->time_usec = htonl(tim);
|
||||
cause->stale_time = htonl(tim);
|
||||
sctp_send_operr_to(src, dst, sh, cookie->peers_vtag, op_err,
|
||||
mflowtype, mflowid, l_inp->fibnum,
|
||||
vrf_id, port);
|
||||
@ -5581,35 +5577,27 @@ process_control_chunks:
|
||||
unknown_chunk:
|
||||
/* it's an unknown chunk! */
|
||||
if ((ch->chunk_type & 0x40) && (stcb != NULL)) {
|
||||
struct mbuf *mm;
|
||||
struct sctp_paramhdr *phd;
|
||||
struct sctp_gen_error_cause *cause;
|
||||
int len;
|
||||
|
||||
mm = sctp_get_mbuf_for_msg(sizeof(struct sctp_paramhdr),
|
||||
op_err = sctp_get_mbuf_for_msg(sizeof(struct sctp_gen_error_cause),
|
||||
0, M_NOWAIT, 1, MT_DATA);
|
||||
if (mm) {
|
||||
if (op_err != NULL) {
|
||||
len = min(SCTP_SIZE32(chk_length), (uint32_t) (length - *offset));
|
||||
phd = mtod(mm, struct sctp_paramhdr *);
|
||||
/*
|
||||
* We cheat and use param type since
|
||||
* we did not bother to define a
|
||||
* error cause struct. They are the
|
||||
* same basic format with different
|
||||
* names.
|
||||
*/
|
||||
phd->param_type = htons(SCTP_CAUSE_UNRECOG_CHUNK);
|
||||
phd->param_length = htons(len + sizeof(*phd));
|
||||
SCTP_BUF_LEN(mm) = sizeof(*phd);
|
||||
SCTP_BUF_NEXT(mm) = SCTP_M_COPYM(m, *offset, len, M_NOWAIT);
|
||||
if (SCTP_BUF_NEXT(mm)) {
|
||||
cause = mtod(op_err, struct sctp_gen_error_cause *);
|
||||
cause->code = htons(SCTP_CAUSE_UNRECOG_CHUNK);
|
||||
cause->length = htons(len + sizeof(struct sctp_gen_error_cause));
|
||||
SCTP_BUF_LEN(op_err) = sizeof(struct sctp_gen_error_cause);
|
||||
SCTP_BUF_NEXT(op_err) = SCTP_M_COPYM(m, *offset, len, M_NOWAIT);
|
||||
if (SCTP_BUF_NEXT(op_err) != NULL) {
|
||||
#ifdef SCTP_MBUF_LOGGING
|
||||
if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MBUF_LOGGING_ENABLE) {
|
||||
sctp_log_mbc(SCTP_BUF_NEXT(mm), SCTP_MBUF_ICOPY);
|
||||
}
|
||||
#endif
|
||||
sctp_queue_op_err(stcb, mm);
|
||||
sctp_queue_op_err(stcb, op_err);
|
||||
} else {
|
||||
sctp_m_freem(mm);
|
||||
sctp_m_freem(op_err);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user