]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - net/ipv4/route.c
ipv4: Disable route secret interval on zero interval
[linux-2.6-omap-h63xx.git] / net / ipv4 / route.c
index 16fc6f454a3188426807fb30a4cc1e25618b6d2b..cca921ea855004f726906a9ed9f24249c7c0592b 100644 (file)
@@ -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;
 }