diff options
author | rrs <rrs@FreeBSD.org> | 2007-06-09 13:46:57 +0000 |
---|---|---|
committer | rrs <rrs@FreeBSD.org> | 2007-06-09 13:46:57 +0000 |
commit | 4ecfa17662f61c5918ac2f9a900430917a2de0d2 (patch) | |
tree | 1afec9873efbc725a9bb5c46d940784789c46118 | |
parent | af285a5d356346bc793bdb7693bb0ab8399d24b9 (diff) | |
download | FreeBSD-src-4ecfa17662f61c5918ac2f9a900430917a2de0d2.zip FreeBSD-src-4ecfa17662f61c5918ac2f9a900430917a2de0d2.tar.gz |
- 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.
-rw-r--r-- | sys/netinet/sctp_auth.c | 13 | ||||
-rw-r--r-- | sys/netinet/sctp_auth.h | 2 | ||||
-rw-r--r-- | sys/netinet/sctp_input.c | 15 | ||||
-rw-r--r-- | sys/netinet/sctp_output.c | 66 | ||||
-rw-r--r-- | sys/netinet/sctp_uio.h | 2 | ||||
-rw-r--r-- | sys/netinet/sctputil.c | 88 |
6 files changed, 99 insertions, 87 deletions
diff --git a/sys/netinet/sctp_auth.c b/sys/netinet/sctp_auth.c index 579bb3f..53a2740 100644 --- a/sys/netinet/sctp_auth.c +++ b/sys/netinet/sctp_auth.c @@ -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 diff --git a/sys/netinet/sctp_auth.h b/sys/netinet/sctp_auth.h index 532af90..be7e6a0 100644 --- a/sys/netinet/sctp_auth.h +++ b/sys/netinet/sctp_auth.h @@ -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); diff --git a/sys/netinet/sctp_input.c b/sys/netinet/sctp_input.c index adc4ce9..1c4bb2e 100644 --- a/sys/netinet/sctp_input.c +++ b/sys/netinet/sctp_input.c @@ -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; diff --git a/sys/netinet/sctp_output.c b/sys/netinet/sctp_output.c index fcc347b..5fd251d 100644 --- a/sys/netinet/sctp_output.c +++ b/sys/netinet/sctp_output.c @@ -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,8 +5032,26 @@ 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. */ diff --git a/sys/netinet/sctp_uio.h b/sys/netinet/sctp_uio.h index a7d8aed..1510f9c 100644 --- a/sys/netinet/sctp_uio.h +++ b/sys/netinet/sctp_uio.h @@ -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 */ diff --git a/sys/netinet/sctputil.c b/sys/netinet/sctputil.c index 2afafcc..9dcc551 100644 --- a/sys/netinet/sctputil.c +++ b/sys/netinet/sctputil.c @@ -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,38 +3460,12 @@ sctp_report_all_outbound(struct sctp_tcb *stcb, int holds_lock) if (holds_lock == 0) { SCTP_TCB_SEND_LOCK(stcb); } - for (i = 0; i < stcb->asoc.streamoutcnt; i++) { - /* For each stream */ - outs = &stcb->asoc.strmout[i]; - /* clean up any sends there */ - stcb->asoc.locked_on_sending = NULL; - sp = TAILQ_FIRST(&outs->outqueue); - while (sp) { - stcb->asoc.stream_queue_cnt--; - TAILQ_REMOVE(&outs->outqueue, sp, next); - sctp_free_spbufspace(stcb, asoc, sp); - sctp_ulp_notify(SCTP_NOTIFY_SPECIAL_SP_FAIL, stcb, - SCTP_NOTIFY_DATAGRAM_UNSENT, (void *)sp); - if (sp->data) { - sctp_m_freem(sp->data); - sp->data = NULL; - } - if (sp->net) - sctp_free_remote_addr(sp->net); - sp->net = NULL; - /* Free the chunk */ - sctp_free_a_strmoq(stcb, sp); - /* sa_ignore FREED_MEMORY */ - sp = TAILQ_FIRST(&outs->outqueue); - } - } - - /* pending send queue SHOULD be empty */ - if (!TAILQ_EMPTY(&asoc->send_queue)) { - 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->send_queue, chk, sctp_next); - asoc->send_queue_cnt--; + TAILQ_REMOVE(&asoc->sent_queue, chk, sctp_next); + asoc->sent_queue_cnt--; if (chk->data) { /* * trim off the sctp chunk header(it should @@ -3498,10 +3474,12 @@ sctp_report_all_outbound(struct sctp_tcb *stcb, int holds_lock) 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); + sctp_ulp_notify(SCTP_NOTIFY_DG_FAIL, stcb, + SCTP_NOTIFY_DATAGRAM_SENT, chk); if (chk->data) { sctp_m_freem(chk->data); chk->data = NULL; @@ -3511,15 +3489,15 @@ sctp_report_all_outbound(struct sctp_tcb *stcb, int holds_lock) chk->whoTo = NULL; sctp_free_a_chunk(stcb, chk); /* sa_ignore FREED_MEMORY */ - chk = TAILQ_FIRST(&asoc->send_queue); + chk = TAILQ_FIRST(&asoc->sent_queue); } } - /* sent queue SHOULD be empty */ - if (!TAILQ_EMPTY(&asoc->sent_queue)) { - 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->sent_queue, chk, sctp_next); - asoc->sent_queue_cnt--; + TAILQ_REMOVE(&asoc->send_queue, chk, sctp_next); + asoc->send_queue_cnt--; if (chk->data) { /* * trim off the sctp chunk header(it should @@ -3528,11 +3506,11 @@ sctp_report_all_outbound(struct sctp_tcb *stcb, int holds_lock) 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); + sctp_ulp_notify(SCTP_NOTIFY_DG_FAIL, stcb, SCTP_NOTIFY_DATAGRAM_UNSENT, chk); if (chk->data) { sctp_m_freem(chk->data); chk->data = NULL; @@ -3542,9 +3520,35 @@ sctp_report_all_outbound(struct sctp_tcb *stcb, int holds_lock) chk->whoTo = NULL; sctp_free_a_chunk(stcb, chk); /* sa_ignore FREED_MEMORY */ - chk = TAILQ_FIRST(&asoc->sent_queue); + chk = TAILQ_FIRST(&asoc->send_queue); + } + } + for (i = 0; i < stcb->asoc.streamoutcnt; i++) { + /* For each stream */ + outs = &stcb->asoc.strmout[i]; + /* clean up any sends there */ + stcb->asoc.locked_on_sending = NULL; + sp = TAILQ_FIRST(&outs->outqueue); + while (sp) { + stcb->asoc.stream_queue_cnt--; + TAILQ_REMOVE(&outs->outqueue, sp, next); + sctp_free_spbufspace(stcb, asoc, sp); + sctp_ulp_notify(SCTP_NOTIFY_SPECIAL_SP_FAIL, stcb, + SCTP_NOTIFY_DATAGRAM_UNSENT, (void *)sp); + if (sp->data) { + sctp_m_freem(sp->data); + sp->data = NULL; + } + if (sp->net) + sctp_free_remote_addr(sp->net); + sp->net = NULL; + /* Free the chunk */ + sctp_free_a_strmoq(stcb, sp); + /* sa_ignore FREED_MEMORY */ + sp = TAILQ_FIRST(&outs->outqueue); } } + if (holds_lock == 0) { SCTP_TCB_SEND_UNLOCK(stcb); } |