Hi,
I had a look in route timer queues in netinet and netinet6 and found
some inconsistencies.
- Timeout was a mixture of int, u_int and long. Make timeout
int with sysctl bounds checking and make absolute time time_t.
- Some code assumes that ..._timeout_q can be NULL and at some
places this is checked. Better make sure that all queues always
exist. The pool_get is only called from initialization and from
syscall, so PR_WAITOK is possible.
- The only special hack I kept is when ip_mtudisc is set to 0.
Then I destroy the queue and generate an empty one.
- If redirect timeout is 0, it does not time out. Adopt IPv6 to
behavior of IPv4.
- sysctl net.inet6.icmp6.redirtimeout had no effect as the queue
timeout was not modified. Make icmp6_sysctl() look like
icmp_sysctl().
ok?
bluhm
Index: net/route.c
===================================================================
RCS file: /cvs/src/sys/net/route.c,v
retrieving revision 1.404
diff -u -p -r1.404 route.c
--- net/route.c 19 Apr 2022 19:19:31 -0000 1.404
+++ net/route.c 19 Apr 2022 20:31:49 -0000
@@ -1399,13 +1399,11 @@ rt_timer_init(void)
}
struct rttimer_queue *
-rt_timer_queue_create(u_int timeout)
+rt_timer_queue_create(int timeout)
{
struct rttimer_queue *rtq;
- rtq = pool_get(&rttimer_queue_pool, PR_NOWAIT | PR_ZERO);
- if (rtq == NULL)
- return (NULL);
+ rtq = pool_get(&rttimer_queue_pool, PR_WAITOK | PR_ZERO);
rtq->rtq_timeout = timeout;
rtq->rtq_count = 0;
@@ -1416,7 +1414,7 @@ rt_timer_queue_create(u_int timeout)
}
void
-rt_timer_queue_change(struct rttimer_queue *rtq, long timeout)
+rt_timer_queue_change(struct rttimer_queue *rtq, int timeout)
{
rtq->rtq_timeout = timeout;
}
@@ -1470,10 +1468,10 @@ rt_timer_add(struct rtentry *rt, void (*
struct rttimer *), struct rttimer_queue *queue, u_int rtableid)
{
struct rttimer *r;
- long current_time;
+ time_t current_time;
current_time = getuptime();
- rt->rt_expire = getuptime() + queue->rtq_timeout;
+ rt->rt_expire = current_time + queue->rtq_timeout;
/*
* If there's already a timer with this action, destroy it before
@@ -1514,7 +1512,7 @@ rt_timer_timer(void *arg)
struct timeout *to = (struct timeout *)arg;
struct rttimer_queue *rtq;
struct rttimer *r;
- long current_time;
+ time_t current_time;
current_time = getuptime();
Index: net/route.h
===================================================================
RCS file: /cvs/src/sys/net/route.h,v
retrieving revision 1.188
diff -u -p -r1.188 route.h
--- net/route.h 19 Apr 2022 15:44:56 -0000 1.188
+++ net/route.h 19 Apr 2022 20:31:49 -0000
@@ -411,10 +411,10 @@ struct rttimer {
};
struct rttimer_queue {
- long rtq_timeout;
- unsigned long rtq_count;
TAILQ_HEAD(, rttimer) rtq_head;
LIST_ENTRY(rttimer_queue) rtq_link;
+ unsigned long rtq_count;
+ int rtq_timeout;
};
const char *rtlabel_id2name(u_int16_t);
@@ -456,8 +456,8 @@ int rt_timer_add(struct rtentry *,
void(*)(struct rtentry *, struct rttimer *),
struct rttimer_queue *, u_int);
void rt_timer_remove_all(struct rtentry *);
-struct rttimer_queue *rt_timer_queue_create(u_int);
-void rt_timer_queue_change(struct rttimer_queue *, long);
+struct rttimer_queue *rt_timer_queue_create(int);
+void rt_timer_queue_change(struct rttimer_queue *, int);
void rt_timer_queue_destroy(struct rttimer_queue *);
unsigned long rt_timer_queue_count(struct rttimer_queue *);
void rt_timer_timer(void *);
Index: netinet/ip_icmp.c
===================================================================
RCS file: /cvs/src/sys/netinet/ip_icmp.c,v
retrieving revision 1.187
diff -u -p -r1.187 ip_icmp.c
--- netinet/ip_icmp.c 26 Jul 2021 20:44:44 -0000 1.187
+++ netinet/ip_icmp.c 19 Apr 2022 20:31:50 -0000
@@ -120,7 +120,7 @@ int icmp_redirtimeout = 10 * 60;
static int icmperrpps_count = 0;
static struct timeval icmperrppslim_last;
-static struct rttimer_queue *icmp_redirect_timeout_q = NULL;
+struct rttimer_queue *icmp_redirect_timeout_q;
struct cpumem *icmpcounters;
const struct sysctl_bounded_args icmpctl_vars[] = {
@@ -141,15 +141,8 @@ int icmp_sysctl_icmpstat(void *, size_t
void
icmp_init(void)
{
+ icmp_redirect_timeout_q = rt_timer_queue_create(icmp_redirtimeout);
icmpcounters = counters_alloc(icps_ncounters);
- /*
- * This is only useful if the user initializes redirtimeout to
- * something other than zero.
- */
- if (icmp_redirtimeout != 0) {
- icmp_redirect_timeout_q =
- rt_timer_queue_create(icmp_redirtimeout);
- }
}
struct mbuf *
@@ -640,12 +633,11 @@ reflect:
#endif
rtredirect(sintosa(&sdst), sintosa(&sgw),
sintosa(&ssrc), &newrt, m->m_pkthdr.ph_rtableid);
- if (newrt != NULL && icmp_redirtimeout != 0) {
- (void)rt_timer_add(newrt, icmp_redirect_timeout,
+ if (newrt != NULL && icmp_redirtimeout > 0) {
+ rt_timer_add(newrt, icmp_redirect_timeout,
icmp_redirect_timeout_q, m->m_pkthdr.ph_rtableid);
}
- if (newrt != NULL)
- rtfree(newrt);
+ rtfree(newrt);
pfctlinput(PRC_REDIRECT_HOST, sintosa(&sdst));
break;
}
@@ -889,21 +881,11 @@ icmp_sysctl(int *name, u_int namelen, vo
switch (name[0]) {
case ICMPCTL_REDIRTIMEOUT:
-
NET_LOCK();
- error = sysctl_int(oldp, oldlenp, newp, newlen,
- &icmp_redirtimeout);
- if (icmp_redirect_timeout_q != NULL) {
- if (icmp_redirtimeout == 0) {
- rt_timer_queue_destroy(icmp_redirect_timeout_q);
- icmp_redirect_timeout_q = NULL;
- } else
- rt_timer_queue_change(icmp_redirect_timeout_q,
- icmp_redirtimeout);
- } else if (icmp_redirtimeout > 0) {
- icmp_redirect_timeout_q =
- rt_timer_queue_create(icmp_redirtimeout);
- }
+ error = sysctl_int_bounded(oldp, oldlenp, newp, newlen,
+ &icmp_redirtimeout, 0, INT_MAX);
+ rt_timer_queue_change(icmp_redirect_timeout_q,
+ icmp_redirtimeout);
NET_UNLOCK();
break;
Index: netinet/ip_input.c
===================================================================
RCS file: /cvs/src/sys/netinet/ip_input.c,v
retrieving revision 1.366
diff -u -p -r1.366 ip_input.c
--- netinet/ip_input.c 22 Feb 2022 01:35:40 -0000 1.366
+++ netinet/ip_input.c 19 Apr 2022 20:31:50 -0000
@@ -91,10 +91,10 @@ int ipsendredirects = 1;
int ip_dosourceroute = 0;
int ip_defttl = IPDEFTTL;
int ip_mtudisc = 1;
-u_int ip_mtudisc_timeout = IPMTUDISCTIMEOUT;
+int ip_mtudisc_timeout = IPMTUDISCTIMEOUT;
int ip_directedbcast = 0;
-struct rttimer_queue *ip_mtudisc_timeout_q = NULL;
+struct rttimer_queue *ip_mtudisc_timeout_q;
/* Protects `ipq' and `ip_frags'. */
struct mutex ipq_mutex = MUTEX_INITIALIZER(IPL_SOFTNET);
@@ -201,9 +201,7 @@ ip_init(void)
pr->pr_protocol < IPPROTO_MAX)
ip_protox[pr->pr_protocol] = pr - inetsw;
LIST_INIT(&ipq);
- if (ip_mtudisc != 0)
- ip_mtudisc_timeout_q =
- rt_timer_queue_create(ip_mtudisc_timeout);
+ ip_mtudisc_timeout_q = rt_timer_queue_create(ip_mtudisc_timeout);
/* Fill in list of ports not to allocate dynamically. */
memset(&baddynamicports, 0, sizeof(baddynamicports));
@@ -1616,24 +1614,20 @@ ip_sysctl(int *name, u_int namelen, void
return (error);
case IPCTL_MTUDISC:
NET_LOCK();
- error = sysctl_int(oldp, oldlenp, newp, newlen,
- &ip_mtudisc);
- if (ip_mtudisc != 0 && ip_mtudisc_timeout_q == NULL) {
+ error = sysctl_int(oldp, oldlenp, newp, newlen, &ip_mtudisc);
+ if (ip_mtudisc == 0) {
+ rt_timer_queue_destroy(ip_mtudisc_timeout_q);
ip_mtudisc_timeout_q =
rt_timer_queue_create(ip_mtudisc_timeout);
- } else if (ip_mtudisc == 0 && ip_mtudisc_timeout_q != NULL) {
- rt_timer_queue_destroy(ip_mtudisc_timeout_q);
- ip_mtudisc_timeout_q = NULL;
}
NET_UNLOCK();
return error;
case IPCTL_MTUDISCTIMEOUT:
NET_LOCK();
- error = sysctl_int(oldp, oldlenp, newp, newlen,
- &ip_mtudisc_timeout);
- if (ip_mtudisc_timeout_q != NULL)
- rt_timer_queue_change(ip_mtudisc_timeout_q,
- ip_mtudisc_timeout);
+ error = sysctl_int_bounded(oldp, oldlenp, newp, newlen,
+ &ip_mtudisc_timeout, 0, INT_MAX);
+ rt_timer_queue_change(ip_mtudisc_timeout_q,
+ ip_mtudisc_timeout);
NET_UNLOCK();
return (error);
#ifdef IPSEC
Index: netinet/ip_var.h
===================================================================
RCS file: /cvs/src/sys/netinet/ip_var.h,v
retrieving revision 1.90
diff -u -p -r1.90 ip_var.h
--- netinet/ip_var.h 25 Feb 2022 23:51:03 -0000 1.90
+++ netinet/ip_var.h 19 Apr 2022 20:31:50 -0000
@@ -204,7 +204,7 @@ extern int ip_defttl; /* default IP tt
#define IPMTUDISCTIMEOUT (10 * 60) /* as per RFC 1191 */
extern int ip_mtudisc; /* mtu discovery */
-extern u_int ip_mtudisc_timeout; /* seconds to timeout mtu discovery */
+extern int ip_mtudisc_timeout; /* seconds to timeout mtu discovery */
extern int ipport_firstauto; /* min port for port allocation */
extern int ipport_lastauto; /* max port for port allocation */
Index: netinet6/icmp6.c
===================================================================
RCS file: /cvs/src/sys/netinet6/icmp6.c,v
retrieving revision 1.238
diff -u -p -r1.238 icmp6.c
--- netinet6/icmp6.c 22 Feb 2022 01:15:02 -0000 1.238
+++ netinet6/icmp6.c 19 Apr 2022 20:31:52 -0000
@@ -118,7 +118,7 @@ struct icmp6_mtudisc_callback {
LIST_HEAD(, icmp6_mtudisc_callback) icmp6_mtudisc_callbacks =
LIST_HEAD_INITIALIZER(icmp6_mtudisc_callbacks);
-struct rttimer_queue *icmp6_mtudisc_timeout_q = NULL;
+struct rttimer_queue *icmp6_mtudisc_timeout_q;
/* XXX do these values make any sense? */
static int icmp6_mtudisc_hiwat = 1280;
@@ -127,7 +127,7 @@ static int icmp6_mtudisc_lowat = 256;
/*
* keep track of # of redirect routes.
*/
-static struct rttimer_queue *icmp6_redirect_timeout_q = NULL;
+struct rttimer_queue *icmp6_redirect_timeout_q;
/* XXX experimental, turned off */
static int icmp6_redirect_lowat = -1;
@@ -1404,12 +1404,11 @@ icmp6_redirect_input(struct mbuf *m, int
memcpy(&ssrc.sin6_addr, &src6, sizeof(struct in6_addr));
rtredirect(sin6tosa(&sdst), sin6tosa(&sgw), sin6tosa(&ssrc),
&newrt, m->m_pkthdr.ph_rtableid);
-
- if (newrt) {
- (void)rt_timer_add(newrt, icmp6_redirect_timeout,
+ if (newrt != NULL && icmp6_redirtimeout > 0) {
+ rt_timer_add(newrt, icmp6_redirect_timeout,
icmp6_redirect_timeout_q, m->m_pkthdr.ph_rtableid);
- rtfree(newrt);
}
+ rtfree(newrt);
}
/* finally update cached route in each socket via pfctlinput */
{
@@ -1881,7 +1880,6 @@ icmp6_redirect_timeout(struct rtentry *r
}
const struct sysctl_bounded_args icmpv6ctl_vars[] = {
- { ICMPV6CTL_REDIRTIMEOUT, &icmp6_redirtimeout, 0, INT_MAX },
{ ICMPV6CTL_ND6_DELAY, &nd6_delay, 0, INT_MAX },
{ ICMPV6CTL_ND6_UMAXTRIES, &nd6_umaxtries, 0, INT_MAX },
{ ICMPV6CTL_ND6_MMAXTRIES, &nd6_mmaxtries, 0, INT_MAX },
@@ -1916,19 +1914,30 @@ icmp6_sysctl(int *name, u_int namelen, v
/* All sysctl names at this level are terminal. */
if (namelen != 1)
- return ENOTDIR;
+ return (ENOTDIR);
switch (name[0]) {
+ case ICMPV6CTL_REDIRTIMEOUT:
+ NET_LOCK();
+ error = sysctl_int_bounded(oldp, oldlenp, newp, newlen,
+ &icmp6_redirtimeout, 0, INT_MAX);
+ rt_timer_queue_change(icmp6_redirect_timeout_q,
+ icmp6_redirtimeout);
+ NET_UNLOCK();
+ break;
case ICMPV6CTL_STATS:
- return icmp6_sysctl_icmp6stat(oldp, oldlenp, newp);
+ error = icmp6_sysctl_icmp6stat(oldp, oldlenp, newp);
+ break;
+
default:
NET_LOCK();
error = sysctl_bounded_arr(icmpv6ctl_vars,
nitems(icmpv6ctl_vars), name, namelen, oldp, oldlenp, newp,
newlen);
NET_UNLOCK();
- return (error);
+ break;
}
- /* NOTREACHED */
+
+ return (error);
}
Index: netinet6/ip6_input.c
===================================================================
RCS file: /cvs/src/sys/netinet6/ip6_input.c,v
retrieving revision 1.240
diff -u -p -r1.240 ip6_input.c
--- netinet6/ip6_input.c 22 Feb 2022 01:35:41 -0000 1.240
+++ netinet6/ip6_input.c 19 Apr 2022 20:31:52 -0000
@@ -1454,11 +1454,10 @@ ip6_sysctl(int *name, u_int namelen, voi
#endif
case IPV6CTL_MTUDISCTIMEOUT:
NET_LOCK();
- error = sysctl_int(oldp, oldlenp, newp, newlen,
- &ip6_mtudisc_timeout);
- if (icmp6_mtudisc_timeout_q != NULL)
- rt_timer_queue_change(icmp6_mtudisc_timeout_q,
- ip6_mtudisc_timeout);
+ error = sysctl_int_bounded(oldp, oldlenp, newp, newlen,
+ &ip6_mtudisc_timeout, 0, INT_MAX);
+ rt_timer_queue_change(icmp6_mtudisc_timeout_q,
+ ip6_mtudisc_timeout);
NET_UNLOCK();
return (error);
case IPV6CTL_IFQUEUE: