mirror of
https://github.com/opnsense/src.git
synced 2026-05-28 04:12:45 -04:00
Cleanup the RTO calculation and perform some consistency checks
before computing the RTO. This should fix an overflow issue reported by Felix Weinrank in https://github.com/sctplab/usrsctp/issues/375 for the userland stack and found by running a fuzz tester. MFC after: 3 days
This commit is contained in:
parent
38a1def12f
commit
44f2a3272e
4 changed files with 45 additions and 45 deletions
|
|
@ -3108,13 +3108,12 @@ sctp_process_segment_range(struct sctp_tcb *stcb, struct sctp_tmit_chunk **p_tp1
|
|||
* update RTO too ?
|
||||
*/
|
||||
if (tp1->do_rtt) {
|
||||
if (*rto_ok) {
|
||||
tp1->whoTo->RTO =
|
||||
sctp_calculate_rto(stcb,
|
||||
&stcb->asoc,
|
||||
tp1->whoTo,
|
||||
&tp1->sent_rcv_time,
|
||||
SCTP_RTT_FROM_DATA);
|
||||
if (*rto_ok &&
|
||||
sctp_calculate_rto(stcb,
|
||||
&stcb->asoc,
|
||||
tp1->whoTo,
|
||||
&tp1->sent_rcv_time,
|
||||
SCTP_RTT_FROM_DATA)) {
|
||||
*rto_ok = 0;
|
||||
}
|
||||
if (tp1->whoTo->rto_needed == 0) {
|
||||
|
|
@ -4086,16 +4085,12 @@ sctp_express_handle_sack(struct sctp_tcb *stcb, uint32_t cumack,
|
|||
|
||||
/* update RTO too? */
|
||||
if (tp1->do_rtt) {
|
||||
if (rto_ok) {
|
||||
tp1->whoTo->RTO =
|
||||
/*
|
||||
* sa_ignore
|
||||
* NO_NULL_CHK
|
||||
*/
|
||||
sctp_calculate_rto(stcb,
|
||||
asoc, tp1->whoTo,
|
||||
&tp1->sent_rcv_time,
|
||||
SCTP_RTT_FROM_DATA);
|
||||
if (rto_ok &&
|
||||
sctp_calculate_rto(stcb,
|
||||
&stcb->asoc,
|
||||
tp1->whoTo,
|
||||
&tp1->sent_rcv_time,
|
||||
SCTP_RTT_FROM_DATA)) {
|
||||
rto_ok = 0;
|
||||
}
|
||||
if (tp1->whoTo->rto_needed == 0) {
|
||||
|
|
@ -4704,12 +4699,12 @@ hopeless_peer:
|
|||
|
||||
/* update RTO too? */
|
||||
if (tp1->do_rtt) {
|
||||
if (rto_ok) {
|
||||
tp1->whoTo->RTO =
|
||||
sctp_calculate_rto(stcb,
|
||||
asoc, tp1->whoTo,
|
||||
&tp1->sent_rcv_time,
|
||||
SCTP_RTT_FROM_DATA);
|
||||
if (rto_ok &&
|
||||
sctp_calculate_rto(stcb,
|
||||
&stcb->asoc,
|
||||
tp1->whoTo,
|
||||
&tp1->sent_rcv_time,
|
||||
SCTP_RTT_FROM_DATA)) {
|
||||
rto_ok = 0;
|
||||
}
|
||||
if (tp1->whoTo->rto_needed == 0) {
|
||||
|
|
|
|||
|
|
@ -548,7 +548,7 @@ sctp_process_init_ack(struct mbuf *m, int iphlen, int offset,
|
|||
asoc->primary_destination, SCTP_FROM_SCTP_INPUT + SCTP_LOC_3);
|
||||
|
||||
/* calculate the RTO */
|
||||
net->RTO = sctp_calculate_rto(stcb, asoc, net, &asoc->time_entered,
|
||||
sctp_calculate_rto(stcb, asoc, net, &asoc->time_entered,
|
||||
SCTP_RTT_FROM_NON_DATA);
|
||||
retval = sctp_send_cookie_echo(m, offset, initack_limit, stcb, net);
|
||||
return (retval);
|
||||
|
|
@ -648,7 +648,7 @@ sctp_handle_heartbeat_ack(struct sctp_heartbeat_chunk *cp,
|
|||
tv.tv_sec = cp->heartbeat.hb_info.time_value_1;
|
||||
tv.tv_usec = cp->heartbeat.hb_info.time_value_2;
|
||||
/* Now lets do a RTO with this */
|
||||
r_net->RTO = sctp_calculate_rto(stcb, &stcb->asoc, r_net, &tv,
|
||||
sctp_calculate_rto(stcb, &stcb->asoc, r_net, &tv,
|
||||
SCTP_RTT_FROM_NON_DATA);
|
||||
if (!(r_net->dest_state & SCTP_ADDR_REACHABLE)) {
|
||||
r_net->dest_state |= SCTP_ADDR_REACHABLE;
|
||||
|
|
@ -1674,8 +1674,7 @@ sctp_process_cookie_existing(struct mbuf *m, int iphlen, int offset,
|
|||
old.tv_sec = cookie->time_entered.tv_sec;
|
||||
old.tv_usec = cookie->time_entered.tv_usec;
|
||||
net->hb_responded = 1;
|
||||
net->RTO = sctp_calculate_rto(stcb, asoc, net,
|
||||
&old,
|
||||
sctp_calculate_rto(stcb, asoc, net, &old,
|
||||
SCTP_RTT_FROM_NON_DATA);
|
||||
|
||||
if (stcb->asoc.sctp_autoclose_ticks &&
|
||||
|
|
@ -2399,8 +2398,7 @@ sctp_process_cookie_new(struct mbuf *m, int iphlen, int offset,
|
|||
/* calculate the RTT and set the encaps port */
|
||||
old.tv_sec = cookie->time_entered.tv_sec;
|
||||
old.tv_usec = cookie->time_entered.tv_usec;
|
||||
(*netp)->RTO = sctp_calculate_rto(stcb, asoc, *netp,
|
||||
&old, SCTP_RTT_FROM_NON_DATA);
|
||||
sctp_calculate_rto(stcb, asoc, *netp, &old, SCTP_RTT_FROM_NON_DATA);
|
||||
}
|
||||
/* respond with a COOKIE-ACK */
|
||||
sctp_send_cookie_ack(stcb);
|
||||
|
|
@ -2976,8 +2974,7 @@ sctp_handle_cookie_ack(struct sctp_cookie_ack_chunk *cp SCTP_UNUSED,
|
|||
SCTP_STAT_INCR_COUNTER32(sctps_activeestab);
|
||||
SCTP_STAT_INCR_GAUGE32(sctps_currestab);
|
||||
if (asoc->overall_error_count == 0) {
|
||||
net->RTO = sctp_calculate_rto(stcb, asoc, net,
|
||||
&asoc->time_entered,
|
||||
sctp_calculate_rto(stcb, asoc, net, &asoc->time_entered,
|
||||
SCTP_RTT_FROM_NON_DATA);
|
||||
}
|
||||
(void)SCTP_GETTIME_TIMEVAL(&asoc->time_entered);
|
||||
|
|
|
|||
|
|
@ -2469,25 +2469,24 @@ sctp_mtu_size_reset(struct sctp_inpcb *inp,
|
|||
|
||||
|
||||
/*
|
||||
* given an association and starting time of the current RTT period return
|
||||
* RTO in number of msecs net should point to the current network
|
||||
* Given an association and starting time of the current RTT period, update
|
||||
* RTO in number of msecs. net should point to the current network.
|
||||
* Return 1, if an RTO update was performed, return 0 if no update was
|
||||
* performed due to invalid starting point.
|
||||
*/
|
||||
|
||||
uint32_t
|
||||
int
|
||||
sctp_calculate_rto(struct sctp_tcb *stcb,
|
||||
struct sctp_association *asoc,
|
||||
struct sctp_nets *net,
|
||||
struct timeval *old,
|
||||
int rtt_from_sack)
|
||||
{
|
||||
/*-
|
||||
* given an association and the starting time of the current RTT
|
||||
* period (in value1/value2) return RTO in number of msecs.
|
||||
*/
|
||||
struct timeval now;
|
||||
uint64_t rtt_us; /* RTT in us */
|
||||
int32_t rtt; /* RTT in ms */
|
||||
uint32_t new_rto;
|
||||
int first_measure = 0;
|
||||
struct timeval now;
|
||||
|
||||
/************************/
|
||||
/* 1. calculate new RTT */
|
||||
|
|
@ -2498,10 +2497,19 @@ sctp_calculate_rto(struct sctp_tcb *stcb,
|
|||
} else {
|
||||
(void)SCTP_GETTIME_TIMEVAL(&now);
|
||||
}
|
||||
if ((old->tv_sec > now.tv_sec) ||
|
||||
((old->tv_sec == now.tv_sec) && (old->tv_sec > now.tv_sec))) {
|
||||
/* The starting point is in the future. */
|
||||
return (0);
|
||||
}
|
||||
timevalsub(&now, old);
|
||||
rtt_us = (uint64_t)1000000 * (uint64_t)now.tv_sec + (uint64_t)now.tv_usec;
|
||||
if (rtt_us > SCTP_RTO_UPPER_BOUND * 1000) {
|
||||
/* The RTT is larger than a sane value. */
|
||||
return (0);
|
||||
}
|
||||
/* store the current RTT in us */
|
||||
net->rtt = (uint64_t)1000000 * (uint64_t)now.tv_sec +
|
||||
(uint64_t)now.tv_usec;
|
||||
net->rtt = rtt_us;
|
||||
/* compute rtt in ms */
|
||||
rtt = (int32_t)(net->rtt / 1000);
|
||||
if ((asoc->cc_functions.sctp_rtt_calculated) && (rtt_from_sack == SCTP_RTT_FROM_DATA)) {
|
||||
|
|
@ -2533,7 +2541,7 @@ sctp_calculate_rto(struct sctp_tcb *stcb,
|
|||
* Paper "Congestion Avoidance and Control", Annex A.
|
||||
*
|
||||
* (net->lastsa >> SCTP_RTT_SHIFT) is the srtt
|
||||
* (net->lastsa >> SCTP_RTT_VAR_SHIFT) is the rttvar
|
||||
* (net->lastsv >> SCTP_RTT_VAR_SHIFT) is the rttvar
|
||||
*/
|
||||
if (net->RTO_measured) {
|
||||
rtt -= (net->lastsa >> SCTP_RTT_SHIFT);
|
||||
|
|
@ -2574,8 +2582,8 @@ sctp_calculate_rto(struct sctp_tcb *stcb,
|
|||
if (new_rto > stcb->asoc.maxrto) {
|
||||
new_rto = stcb->asoc.maxrto;
|
||||
}
|
||||
/* we are now returning the RTO */
|
||||
return (new_rto);
|
||||
net->RTO = new_rto;
|
||||
return (1);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -133,7 +133,7 @@ uint32_t sctp_get_next_mtu(uint32_t);
|
|||
void
|
||||
sctp_timeout_handler(void *);
|
||||
|
||||
uint32_t
|
||||
int
|
||||
sctp_calculate_rto(struct sctp_tcb *, struct sctp_association *,
|
||||
struct sctp_nets *, struct timeval *, int);
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue