|
@@ -2914,6 +2914,68 @@ static int ipv4_sysctl_rtcache_flush_strategy(ctl_table *table,
|
|
|
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[] = {
|
|
|
{
|
|
|
.ctl_name = NET_IPV4_ROUTE_GC_THRESH,
|
|
@@ -3048,8 +3110,8 @@ static ctl_table ipv4_route_table[] = {
|
|
|
.data = &ip_rt_secret_interval,
|
|
|
.maxlen = sizeof(int),
|
|
|
.mode = 0644,
|
|
|
- .proc_handler = &proc_dointvec_jiffies,
|
|
|
- .strategy = &sysctl_jiffies,
|
|
|
+ .proc_handler = &ipv4_sysctl_rt_secret_interval,
|
|
|
+ .strategy = &ipv4_sysctl_rt_secret_interval_strategy,
|
|
|
},
|
|
|
{ .ctl_name = 0 }
|
|
|
};
|
|
@@ -3126,10 +3188,12 @@ static __net_init int rt_secret_timer_init(struct net *net)
|
|
|
net->ipv4.rt_secret_timer.data = (unsigned long)net;
|
|
|
init_timer_deferrable(&net->ipv4.rt_secret_timer);
|
|
|
|
|
|
- net->ipv4.rt_secret_timer.expires =
|
|
|
- jiffies + net_random() % ip_rt_secret_interval +
|
|
|
- ip_rt_secret_interval;
|
|
|
- add_timer(&net->ipv4.rt_secret_timer);
|
|
|
+ if (ip_rt_secret_interval) {
|
|
|
+ net->ipv4.rt_secret_timer.expires =
|
|
|
+ jiffies + net_random() % ip_rt_secret_interval +
|
|
|
+ ip_rt_secret_interval;
|
|
|
+ add_timer(&net->ipv4.rt_secret_timer);
|
|
|
+ }
|
|
|
return 0;
|
|
|
}
|
|
|
|