summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorrrs <rrs@FreeBSD.org>2007-06-09 13:46:57 +0000
committerrrs <rrs@FreeBSD.org>2007-06-09 13:46:57 +0000
commit4ecfa17662f61c5918ac2f9a900430917a2de0d2 (patch)
tree1afec9873efbc725a9bb5c46d940784789c46118
parentaf285a5d356346bc793bdb7693bb0ab8399d24b9 (diff)
downloadFreeBSD-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.c13
-rw-r--r--sys/netinet/sctp_auth.h2
-rw-r--r--sys/netinet/sctp_input.c15
-rw-r--r--sys/netinet/sctp_output.c66
-rw-r--r--sys/netinet/sctp_uio.h2
-rw-r--r--sys/netinet/sctputil.c88
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);
}
OpenPOWER on IntegriCloud