Commit c6153b5b authored by Herbert Xu's avatar Herbert Xu Committed by David S. Miller

ipv4: Disable route secret interval on zero interval

Let me first state that disabling the route cache hash rebuild
should not be done without extensive analysis on the risk profile
and careful deliberation.

However, there are times when this can be done safely or for
testing.  For example, when you have mechanisms for ensuring
that offending parties do not exist in your network.

This patch lets the user disable the rebuild if the interval is
set to zero.  This also incidentally fixes a divide-by-zero error
with name-spaces.

In addition, this patch makes the effect of an interval change
immediate rather than it taking effect at the next rebuild as
is currently the case.
Signed-off-by: default avatarHerbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 323c0488
...@@ -2914,6 +2914,68 @@ static int ipv4_sysctl_rtcache_flush_strategy(ctl_table *table, ...@@ -2914,6 +2914,68 @@ static int ipv4_sysctl_rtcache_flush_strategy(ctl_table *table,
return 0; return 0;
} }
static void rt_secret_reschedule(int old)
{
struct net *net;
int new = ip_rt_secret_interval;
int diff = new - old;
if (!diff)
return;
rtnl_lock();
for_each_net(net) {
int deleted = del_timer_sync(&net->ipv4.rt_secret_timer);
if (!new)
continue;
if (deleted) {
long time = net->ipv4.rt_secret_timer.expires - jiffies;
if (time <= 0 || (time += diff) <= 0)
time = 0;
net->ipv4.rt_secret_timer.expires = time;
} else
net->ipv4.rt_secret_timer.expires = new;
net->ipv4.rt_secret_timer.expires += jiffies;
add_timer(&net->ipv4.rt_secret_timer);
}
rtnl_unlock();
}
static int ipv4_sysctl_rt_secret_interval(ctl_table *ctl, int write,
struct file *filp,
void __user *buffer, size_t *lenp,
loff_t *ppos)
{
int old = ip_rt_secret_interval;
int ret = proc_dointvec_jiffies(ctl, write, filp, buffer, lenp, ppos);
rt_secret_reschedule(old);
return ret;
}
static int ipv4_sysctl_rt_secret_interval_strategy(ctl_table *table,
int __user *name,
int nlen,
void __user *oldval,
size_t __user *oldlenp,
void __user *newval,
size_t newlen)
{
int old = ip_rt_secret_interval;
int ret = sysctl_jiffies(table, name, nlen, oldval, oldlenp, newval,
newlen);
rt_secret_reschedule(old);
return ret;
}
static ctl_table ipv4_route_table[] = { static ctl_table ipv4_route_table[] = {
{ {
.ctl_name = NET_IPV4_ROUTE_GC_THRESH, .ctl_name = NET_IPV4_ROUTE_GC_THRESH,
...@@ -3048,8 +3110,8 @@ static ctl_table ipv4_route_table[] = { ...@@ -3048,8 +3110,8 @@ static ctl_table ipv4_route_table[] = {
.data = &ip_rt_secret_interval, .data = &ip_rt_secret_interval,
.maxlen = sizeof(int), .maxlen = sizeof(int),
.mode = 0644, .mode = 0644,
.proc_handler = &proc_dointvec_jiffies, .proc_handler = &ipv4_sysctl_rt_secret_interval,
.strategy = &sysctl_jiffies, .strategy = &ipv4_sysctl_rt_secret_interval_strategy,
}, },
{ .ctl_name = 0 } { .ctl_name = 0 }
}; };
...@@ -3126,10 +3188,12 @@ static __net_init int rt_secret_timer_init(struct net *net) ...@@ -3126,10 +3188,12 @@ static __net_init int rt_secret_timer_init(struct net *net)
net->ipv4.rt_secret_timer.data = (unsigned long)net; net->ipv4.rt_secret_timer.data = (unsigned long)net;
init_timer_deferrable(&net->ipv4.rt_secret_timer); init_timer_deferrable(&net->ipv4.rt_secret_timer);
net->ipv4.rt_secret_timer.expires = if (ip_rt_secret_interval) {
jiffies + net_random() % ip_rt_secret_interval + net->ipv4.rt_secret_timer.expires =
ip_rt_secret_interval; jiffies + net_random() % ip_rt_secret_interval +
add_timer(&net->ipv4.rt_secret_timer); ip_rt_secret_interval;
add_timer(&net->ipv4.rt_secret_timer);
}
return 0; return 0;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment