diff options
author | Phil Sutter <phil@nwl.cc> | 2016-08-04 10:11:56 (GMT) |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2016-08-08 19:51:58 (GMT) |
commit | 12474e8e58d82e2b815cd35956c0c06fab104ee7 (patch) | |
tree | 74c5fdb34f87f717342f0f4247156144eb055061 /net/sctp | |
parent | dca3f53c02e325bb19dfc05b1571b9a706226fea (diff) | |
download | linux-12474e8e58d82e2b815cd35956c0c06fab104ee7.tar.xz |
sctp_diag: Fix T3_rtx timer export
The asoc's timer value is not kept in asoc->timeouts array but in it's
primary transport instead.
Furthermore, we must export the timer only if it is pending, otherwise
the value will underrun when stored in an unsigned variable and
user space will only see a very large timeout value.
Signed-off-by: Phil Sutter <phil@nwl.cc>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/sctp')
-rw-r--r-- | net/sctp/sctp_diag.c | 14 |
1 files changed, 10 insertions, 4 deletions
diff --git a/net/sctp/sctp_diag.c b/net/sctp/sctp_diag.c index f69edcf..f728ef0 100644 --- a/net/sctp/sctp_diag.c +++ b/net/sctp/sctp_diag.c @@ -13,6 +13,7 @@ static void inet_diag_msg_sctpasoc_fill(struct inet_diag_msg *r, { union sctp_addr laddr, paddr; struct dst_entry *dst; + struct timer_list *t3_rtx = &asoc->peer.primary_path->T3_rtx_timer; laddr = list_entry(asoc->base.bind_addr.address_list.next, struct sctp_sockaddr_entry, list)->a; @@ -40,10 +41,15 @@ static void inet_diag_msg_sctpasoc_fill(struct inet_diag_msg *r, } r->idiag_state = asoc->state; - r->idiag_timer = SCTP_EVENT_TIMEOUT_T3_RTX; - r->idiag_retrans = asoc->rtx_data_chunks; - r->idiag_expires = jiffies_to_msecs( - asoc->timeouts[SCTP_EVENT_TIMEOUT_T3_RTX] - jiffies); + if (timer_pending(t3_rtx)) { + r->idiag_timer = SCTP_EVENT_TIMEOUT_T3_RTX; + r->idiag_retrans = asoc->rtx_data_chunks; + r->idiag_expires = jiffies_to_msecs(t3_rtx->expires - jiffies); + } else { + r->idiag_timer = 0; + r->idiag_retrans = 0; + r->idiag_expires = 0; + } } static int inet_diag_msg_sctpladdrs_fill(struct sk_buff *skb, |