- fix send_failed notification contents
- Reorder send failed to be in correct order. - Fixed calulation of init-ack to be right off mbuf lengths instead of the precalculated value. This will fix one 64 bit platform issue.
This commit is contained in:
parent
74fd40c90c
commit
d00aff5d79
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=170462
@ -1034,7 +1034,7 @@ sctp_hmac(uint16_t hmac_algo, uint8_t * key, uint32_t keylen,
|
||||
/* mbuf version */
|
||||
uint32_t
|
||||
sctp_hmac_m(uint16_t hmac_algo, uint8_t * key, uint32_t keylen,
|
||||
struct mbuf *m, uint32_t m_offset, uint8_t * digest)
|
||||
struct mbuf *m, uint32_t m_offset, uint8_t * digest, uint32_t trailer)
|
||||
{
|
||||
uint32_t digestlen;
|
||||
uint32_t blocklen;
|
||||
@ -1087,8 +1087,13 @@ sctp_hmac_m(uint16_t hmac_algo, uint8_t * key, uint32_t keylen,
|
||||
}
|
||||
/* now use the rest of the mbuf chain for the text */
|
||||
while (m_tmp != NULL) {
|
||||
sctp_hmac_update(hmac_algo, &ctx, mtod(m_tmp, uint8_t *) + m_offset,
|
||||
SCTP_BUF_LEN(m_tmp) - m_offset);
|
||||
if ((SCTP_BUF_NEXT(m_tmp) == NULL) && trailer) {
|
||||
sctp_hmac_update(hmac_algo, &ctx, mtod(m_tmp, uint8_t *) + m_offset,
|
||||
SCTP_BUF_LEN(m_tmp) - (trailer + m_offset));
|
||||
} else {
|
||||
sctp_hmac_update(hmac_algo, &ctx, mtod(m_tmp, uint8_t *) + m_offset,
|
||||
SCTP_BUF_LEN(m_tmp) - m_offset);
|
||||
}
|
||||
|
||||
/* clear the offset since it's only for the first mbuf */
|
||||
m_offset = 0;
|
||||
@ -1206,7 +1211,7 @@ sctp_compute_hmac_m(uint16_t hmac_algo, sctp_key_t * key, struct mbuf *m,
|
||||
key->keylen = digestlen;
|
||||
bcopy(temp, key->key, key->keylen);
|
||||
}
|
||||
return (sctp_hmac_m(hmac_algo, key->key, key->keylen, m, m_offset, digest));
|
||||
return (sctp_hmac_m(hmac_algo, key->key, key->keylen, m, m_offset, digest, 0));
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -182,7 +182,7 @@ extern int sctp_auth_is_supported_hmac(sctp_hmaclist_t * list, uint16_t id);
|
||||
/* mbuf versions */
|
||||
extern uint32_t
|
||||
sctp_hmac_m(uint16_t hmac_algo, uint8_t * key, uint32_t keylen,
|
||||
struct mbuf *m, uint32_t m_offset, uint8_t * digest);
|
||||
struct mbuf *m, uint32_t m_offset, uint8_t * digest, uint32_t trailer);
|
||||
extern uint32_t
|
||||
sctp_compute_hmac_m(uint16_t hmac_algo, sctp_key_t * key, struct mbuf *m,
|
||||
uint32_t m_offset, uint8_t * digest);
|
||||
|
@ -1852,12 +1852,12 @@ sctp_handle_cookie_echo(struct mbuf *m, int iphlen, int offset,
|
||||
/* it's the old cookie */
|
||||
(void)sctp_hmac_m(SCTP_HMAC,
|
||||
(uint8_t *) ep->secret_key[(int)ep->last_secret_number],
|
||||
SCTP_SECRET_SIZE, m, cookie_offset, calc_sig);
|
||||
SCTP_SECRET_SIZE, m, cookie_offset, calc_sig, 0);
|
||||
} else {
|
||||
/* it's the current cookie */
|
||||
(void)sctp_hmac_m(SCTP_HMAC,
|
||||
(uint8_t *) ep->secret_key[(int)ep->current_secret_number],
|
||||
SCTP_SECRET_SIZE, m, cookie_offset, calc_sig);
|
||||
SCTP_SECRET_SIZE, m, cookie_offset, calc_sig, 0);
|
||||
}
|
||||
/* get the signature */
|
||||
SCTP_INP_RUNLOCK(l_inp);
|
||||
@ -1870,12 +1870,21 @@ sctp_handle_cookie_echo(struct mbuf *m, int iphlen, int offset,
|
||||
/* compare the received digest with the computed digest */
|
||||
if (memcmp(calc_sig, sig, SCTP_SIGNATURE_SIZE) != 0) {
|
||||
/* try the old cookie? */
|
||||
printf("Signature size is %d\n", SCTP_SIGNATURE_SIZE);
|
||||
printf("Signature %x %x %x %x %x %x %x %x\n",
|
||||
sig[0], sig[1], sig[2], sig[3],
|
||||
sig[4], sig[5], sig[6], sig[7]);
|
||||
|
||||
printf("Calc Signature %x %x %x %x %x %x %x %x\n",
|
||||
calc_sig[0], calc_sig[1], calc_sig[2], calc_sig[3],
|
||||
calc_sig[4], calc_sig[5], calc_sig[6], calc_sig[7]);
|
||||
|
||||
if ((cookie->time_entered.tv_sec == (long)ep->time_of_secret_change) &&
|
||||
(ep->current_secret_number != ep->last_secret_number)) {
|
||||
/* compute digest with old */
|
||||
(void)sctp_hmac_m(SCTP_HMAC,
|
||||
(uint8_t *) ep->secret_key[(int)ep->last_secret_number],
|
||||
SCTP_SECRET_SIZE, m, cookie_offset, calc_sig);
|
||||
SCTP_SECRET_SIZE, m, cookie_offset, calc_sig, 0);
|
||||
/* compare */
|
||||
if (memcmp(calc_sig, sig, SCTP_SIGNATURE_SIZE) == 0)
|
||||
cookie_ok = 1;
|
||||
|
@ -3083,12 +3083,12 @@ sctp_find_cmsg(int c_type, void *data, struct mbuf *control, int cpsize)
|
||||
|
||||
static struct mbuf *
|
||||
sctp_add_cookie(struct sctp_inpcb *inp, struct mbuf *init, int init_offset,
|
||||
struct mbuf *initack, int initack_offset, struct sctp_state_cookie *stc_in)
|
||||
struct mbuf *initack, int initack_offset, struct sctp_state_cookie *stc_in, uint8_t ** signature)
|
||||
{
|
||||
struct mbuf *copy_init, *copy_initack, *m_at, *sig, *mret;
|
||||
struct sctp_state_cookie *stc;
|
||||
struct sctp_paramhdr *ph;
|
||||
uint8_t *signature;
|
||||
uint8_t *foo;
|
||||
int sig_offset;
|
||||
uint16_t cookie_sz;
|
||||
|
||||
@ -3156,15 +3156,12 @@ sctp_add_cookie(struct sctp_inpcb *inp, struct mbuf *init, int init_offset,
|
||||
SCTP_BUF_LEN(sig) = 0;
|
||||
SCTP_BUF_NEXT(m_at) = sig;
|
||||
sig_offset = 0;
|
||||
signature = (uint8_t *) (mtod(sig, caddr_t)+sig_offset);
|
||||
/* Time to sign the cookie */
|
||||
(void)sctp_hmac_m(SCTP_HMAC,
|
||||
(uint8_t *) inp->sctp_ep.secret_key[(int)(inp->sctp_ep.current_secret_number)],
|
||||
SCTP_SECRET_SIZE, mret, sizeof(struct sctp_paramhdr),
|
||||
(uint8_t *) signature);
|
||||
foo = (uint8_t *) (mtod(sig, caddr_t)+sig_offset);
|
||||
memset(foo, 0, SCTP_SIGNATURE_SIZE);
|
||||
printf("%p is address for signature\n", foo);
|
||||
*signature = foo;
|
||||
SCTP_BUF_LEN(sig) += SCTP_SIGNATURE_SIZE;
|
||||
cookie_sz += SCTP_SIGNATURE_SIZE;
|
||||
|
||||
ph->param_length = htons(cookie_sz);
|
||||
return (mret);
|
||||
}
|
||||
@ -4494,9 +4491,10 @@ sctp_send_initiate_ack(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
|
||||
struct sockaddr *to;
|
||||
struct sctp_state_cookie stc;
|
||||
struct sctp_nets *net = NULL;
|
||||
uint8_t *signature = NULL;
|
||||
int cnt_inits_to = 0;
|
||||
uint16_t his_limit, i_want;
|
||||
int abort_flag, padval, sz_of;
|
||||
int abort_flag, padval;
|
||||
int num_ext;
|
||||
int p_len;
|
||||
|
||||
@ -5004,8 +5002,6 @@ sctp_send_initiate_ack(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
|
||||
m_at = SCTP_BUF_NEXT(m_at);
|
||||
}
|
||||
}
|
||||
/* Get total size of init packet */
|
||||
sz_of = SCTP_SIZE32(ntohs(init_chk->ch.chunk_length));
|
||||
/* pre-calulate the size and update pkt header and chunk header */
|
||||
p_len = 0;
|
||||
for (m_tmp = m; m_tmp; m_tmp = SCTP_BUF_NEXT(m_tmp)) {
|
||||
@ -5015,40 +5011,20 @@ sctp_send_initiate_ack(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
|
||||
break;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Figure now the size of the cookie. We know the size of the
|
||||
* INIT-ACK. The Cookie is going to be the size of INIT, INIT-ACK,
|
||||
* COOKIE-STRUCTURE and SIGNATURE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* take our earlier INIT calc and add in the sz we just calculated
|
||||
* minus the size of the sctphdr (its not included in chunk size
|
||||
*/
|
||||
|
||||
/* add once for the INIT-ACK */
|
||||
sz_of += (p_len - sizeof(struct sctphdr));
|
||||
|
||||
/* add a second time for the INIT-ACK in the cookie */
|
||||
sz_of += (p_len - sizeof(struct sctphdr));
|
||||
|
||||
/* Now add the cookie header and cookie message struct */
|
||||
sz_of += sizeof(struct sctp_state_cookie_param);
|
||||
/* ...and add the size of our signature */
|
||||
sz_of += SCTP_SIGNATURE_SIZE;
|
||||
initackm_out->msg.ch.chunk_length = htons(sz_of);
|
||||
|
||||
/* Now we must build a cookie */
|
||||
m_cookie = sctp_add_cookie(inp, init_pkt, offset, m,
|
||||
sizeof(struct sctphdr), &stc);
|
||||
sizeof(struct sctphdr), &stc, &signature);
|
||||
if (m_cookie == NULL) {
|
||||
/* memory problem */
|
||||
sctp_m_freem(m);
|
||||
return;
|
||||
}
|
||||
printf("signature is set to %p\n", signature);
|
||||
/* Now append the cookie to the end and update the space/size */
|
||||
SCTP_BUF_NEXT(m_tmp) = m_cookie;
|
||||
for (; m_tmp; m_tmp = SCTP_BUF_NEXT(m_tmp)) {
|
||||
|
||||
for (m_tmp = m_cookie; m_tmp; m_tmp = SCTP_BUF_NEXT(m_tmp)) {
|
||||
p_len += SCTP_BUF_LEN(m_tmp);
|
||||
if (SCTP_BUF_NEXT(m_tmp) == NULL) {
|
||||
/* m_tmp should now point to last one */
|
||||
@ -5056,7 +5032,25 @@ sctp_send_initiate_ack(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
|
||||
break;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Place in the size, but we don't include the last pad (if any) in
|
||||
* the INIT-ACK.
|
||||
*/
|
||||
initackm_out->msg.ch.chunk_length = htons((p_len - sizeof(struct sctphdr)));
|
||||
|
||||
/*
|
||||
* Time to sign the cookie, we don't sign over the cookie signature
|
||||
* though thus we set trailer.
|
||||
*/
|
||||
(void)sctp_hmac_m(SCTP_HMAC,
|
||||
(uint8_t *) inp->sctp_ep.secret_key[(int)(inp->sctp_ep.current_secret_number)],
|
||||
SCTP_SECRET_SIZE, m_cookie, sizeof(struct sctp_paramhdr),
|
||||
(uint8_t *) signature, SCTP_SIGNATURE_SIZE);
|
||||
printf("signed first 4 bytes are %x %x %x %x\n",
|
||||
signature[0],
|
||||
signature[1],
|
||||
signature[2],
|
||||
signature[3]);
|
||||
/*
|
||||
* We sifa 0 here to NOT set IP_DF if its IPv4, we ignore the return
|
||||
* here since the timer will drive a retranmission.
|
||||
|
@ -260,7 +260,7 @@ struct sctp_send_failed {
|
||||
uint32_t ssf_error;
|
||||
struct sctp_sndrcvinfo ssf_info;
|
||||
sctp_assoc_t ssf_assoc_id;
|
||||
uint8_t ssf_data[4];
|
||||
uint8_t ssf_data[0];
|
||||
};
|
||||
|
||||
/* flag that indicates state of data */
|
||||
|
@ -2925,6 +2925,7 @@ sctp_notify_send_failed(struct sctp_tcb *stcb, uint32_t error,
|
||||
ssf->ssf_length = length;
|
||||
ssf->ssf_error = error;
|
||||
/* not exactly what the user sent in, but should be close :) */
|
||||
bzero(&ssf->ssf_info, sizeof(ssf->ssf_info));
|
||||
ssf->ssf_info.sinfo_stream = chk->rec.data.stream_number;
|
||||
ssf->ssf_info.sinfo_ssn = chk->rec.data.stream_seq;
|
||||
ssf->ssf_info.sinfo_flags = chk->rec.data.rcv_flags;
|
||||
@ -2976,7 +2977,7 @@ sctp_notify_send_failed2(struct sctp_tcb *stcb, uint32_t error,
|
||||
return;
|
||||
|
||||
length = sizeof(struct sctp_send_failed) + sp->length;
|
||||
m_notify = sctp_get_mbuf_for_msg(sizeof(struct sctp_adaption_event), 0, M_DONTWAIT, 1, MT_DATA);
|
||||
m_notify = sctp_get_mbuf_for_msg(sizeof(struct sctp_send_failed), 0, M_DONTWAIT, 1, MT_DATA);
|
||||
if (m_notify == NULL)
|
||||
/* no space left */
|
||||
return;
|
||||
@ -2990,6 +2991,7 @@ sctp_notify_send_failed2(struct sctp_tcb *stcb, uint32_t error,
|
||||
ssf->ssf_length = length;
|
||||
ssf->ssf_error = error;
|
||||
/* not exactly what the user sent in, but should be close :) */
|
||||
bzero(&ssf->ssf_info, sizeof(ssf->ssf_info));
|
||||
ssf->ssf_info.sinfo_stream = sp->stream;
|
||||
ssf->ssf_info.sinfo_ssn = sp->strseq;
|
||||
ssf->ssf_info.sinfo_flags = sp->sinfo_flags;
|
||||
@ -3458,6 +3460,69 @@ sctp_report_all_outbound(struct sctp_tcb *stcb, int holds_lock)
|
||||
if (holds_lock == 0) {
|
||||
SCTP_TCB_SEND_LOCK(stcb);
|
||||
}
|
||||
/* sent queue SHOULD be empty */
|
||||
if (!TAILQ_EMPTY(&asoc->sent_queue)) {
|
||||
chk = TAILQ_FIRST(&asoc->sent_queue);
|
||||
while (chk) {
|
||||
TAILQ_REMOVE(&asoc->sent_queue, chk, sctp_next);
|
||||
asoc->sent_queue_cnt--;
|
||||
if (chk->data) {
|
||||
/*
|
||||
* trim off the sctp chunk header(it should
|
||||
* be there)
|
||||
*/
|
||||
if (chk->send_size >= sizeof(struct sctp_data_chunk)) {
|
||||
m_adj(chk->data, sizeof(struct sctp_data_chunk));
|
||||
sctp_mbuf_crush(chk->data);
|
||||
chk->send_size -= sizeof(struct sctp_data_chunk);
|
||||
}
|
||||
}
|
||||
sctp_free_bufspace(stcb, asoc, chk, 1);
|
||||
sctp_ulp_notify(SCTP_NOTIFY_DG_FAIL, stcb,
|
||||
SCTP_NOTIFY_DATAGRAM_SENT, chk);
|
||||
if (chk->data) {
|
||||
sctp_m_freem(chk->data);
|
||||
chk->data = NULL;
|
||||
}
|
||||
if (chk->whoTo)
|
||||
sctp_free_remote_addr(chk->whoTo);
|
||||
chk->whoTo = NULL;
|
||||
sctp_free_a_chunk(stcb, chk);
|
||||
/* sa_ignore FREED_MEMORY */
|
||||
chk = TAILQ_FIRST(&asoc->sent_queue);
|
||||
}
|
||||
}
|
||||
/* pending send queue SHOULD be empty */
|
||||
if (!TAILQ_EMPTY(&asoc->send_queue)) {
|
||||
chk = TAILQ_FIRST(&asoc->send_queue);
|
||||
while (chk) {
|
||||
TAILQ_REMOVE(&asoc->send_queue, chk, sctp_next);
|
||||
asoc->send_queue_cnt--;
|
||||
if (chk->data) {
|
||||
/*
|
||||
* trim off the sctp chunk header(it should
|
||||
* be there)
|
||||
*/
|
||||
if (chk->send_size >= sizeof(struct sctp_data_chunk)) {
|
||||
m_adj(chk->data, sizeof(struct sctp_data_chunk));
|
||||
sctp_mbuf_crush(chk->data);
|
||||
chk->send_size -= sizeof(struct sctp_data_chunk);
|
||||
}
|
||||
}
|
||||
sctp_free_bufspace(stcb, asoc, chk, 1);
|
||||
sctp_ulp_notify(SCTP_NOTIFY_DG_FAIL, stcb, SCTP_NOTIFY_DATAGRAM_UNSENT, chk);
|
||||
if (chk->data) {
|
||||
sctp_m_freem(chk->data);
|
||||
chk->data = NULL;
|
||||
}
|
||||
if (chk->whoTo)
|
||||
sctp_free_remote_addr(chk->whoTo);
|
||||
chk->whoTo = NULL;
|
||||
sctp_free_a_chunk(stcb, chk);
|
||||
/* sa_ignore FREED_MEMORY */
|
||||
chk = TAILQ_FIRST(&asoc->send_queue);
|
||||
}
|
||||
}
|
||||
for (i = 0; i < stcb->asoc.streamoutcnt; i++) {
|
||||
/* For each stream */
|
||||
outs = &stcb->asoc.strmout[i];
|
||||
@ -3484,67 +3549,6 @@ sctp_report_all_outbound(struct sctp_tcb *stcb, int holds_lock)
|
||||
}
|
||||
}
|
||||
|
||||
/* pending send queue SHOULD be empty */
|
||||
if (!TAILQ_EMPTY(&asoc->send_queue)) {
|
||||
chk = TAILQ_FIRST(&asoc->send_queue);
|
||||
while (chk) {
|
||||
TAILQ_REMOVE(&asoc->send_queue, chk, sctp_next);
|
||||
asoc->send_queue_cnt--;
|
||||
if (chk->data) {
|
||||
/*
|
||||
* trim off the sctp chunk header(it should
|
||||
* be there)
|
||||
*/
|
||||
if (chk->send_size >= sizeof(struct sctp_data_chunk)) {
|
||||
m_adj(chk->data, sizeof(struct sctp_data_chunk));
|
||||
sctp_mbuf_crush(chk->data);
|
||||
}
|
||||
}
|
||||
sctp_free_bufspace(stcb, asoc, chk, 1);
|
||||
sctp_ulp_notify(SCTP_NOTIFY_DG_FAIL, stcb, SCTP_NOTIFY_DATAGRAM_UNSENT, chk);
|
||||
if (chk->data) {
|
||||
sctp_m_freem(chk->data);
|
||||
chk->data = NULL;
|
||||
}
|
||||
if (chk->whoTo)
|
||||
sctp_free_remote_addr(chk->whoTo);
|
||||
chk->whoTo = NULL;
|
||||
sctp_free_a_chunk(stcb, chk);
|
||||
/* sa_ignore FREED_MEMORY */
|
||||
chk = TAILQ_FIRST(&asoc->send_queue);
|
||||
}
|
||||
}
|
||||
/* sent queue SHOULD be empty */
|
||||
if (!TAILQ_EMPTY(&asoc->sent_queue)) {
|
||||
chk = TAILQ_FIRST(&asoc->sent_queue);
|
||||
while (chk) {
|
||||
TAILQ_REMOVE(&asoc->sent_queue, chk, sctp_next);
|
||||
asoc->sent_queue_cnt--;
|
||||
if (chk->data) {
|
||||
/*
|
||||
* trim off the sctp chunk header(it should
|
||||
* be there)
|
||||
*/
|
||||
if (chk->send_size >= sizeof(struct sctp_data_chunk)) {
|
||||
m_adj(chk->data, sizeof(struct sctp_data_chunk));
|
||||
sctp_mbuf_crush(chk->data);
|
||||
}
|
||||
}
|
||||
sctp_free_bufspace(stcb, asoc, chk, 1);
|
||||
sctp_ulp_notify(SCTP_NOTIFY_DG_FAIL, stcb,
|
||||
SCTP_NOTIFY_DATAGRAM_SENT, chk);
|
||||
if (chk->data) {
|
||||
sctp_m_freem(chk->data);
|
||||
chk->data = NULL;
|
||||
}
|
||||
if (chk->whoTo)
|
||||
sctp_free_remote_addr(chk->whoTo);
|
||||
chk->whoTo = NULL;
|
||||
sctp_free_a_chunk(stcb, chk);
|
||||
/* sa_ignore FREED_MEMORY */
|
||||
chk = TAILQ_FIRST(&asoc->sent_queue);
|
||||
}
|
||||
}
|
||||
if (holds_lock == 0) {
|
||||
SCTP_TCB_SEND_UNLOCK(stcb);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user