- 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:
Randall Stewart 2007-06-09 13:46:57 +00:00
parent 74fd40c90c
commit d00aff5d79
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=170462
6 changed files with 119 additions and 107 deletions

View File

@ -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

View File

@ -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);

View File

@ -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;

View File

@ -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.

View File

@ -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 */

View File

@ -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);
}