aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4/route.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv4/route.c')
-rw-r--r--net/ipv4/route.c100
1 files changed, 90 insertions, 10 deletions
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index 16fc6f454a31..6ee5354c9aa1 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -2914,6 +2914,68 @@ static int ipv4_sysctl_rtcache_flush_strategy(ctl_table *table,
2914 return 0; 2914 return 0;
2915} 2915}
2916 2916
2917static void rt_secret_reschedule(int old)
2918{
2919 struct net *net;
2920 int new = ip_rt_secret_interval;
2921 int diff = new - old;
2922
2923 if (!diff)
2924 return;
2925
2926 rtnl_lock();
2927 for_each_net(net) {
2928 int deleted = del_timer_sync(&net->ipv4.rt_secret_timer);
2929
2930 if (!new)
2931 continue;
2932
2933 if (deleted) {
2934 long time = net->ipv4.rt_secret_timer.expires - jiffies;
2935
2936 if (time <= 0 || (time += diff) <= 0)
2937 time = 0;
2938
2939 net->ipv4.rt_secret_timer.expires = time;
2940 } else
2941 net->ipv4.rt_secret_timer.expires = new;
2942
2943 net->ipv4.rt_secret_timer.expires += jiffies;
2944 add_timer(&net->ipv4.rt_secret_timer);
2945 }
2946 rtnl_unlock();
2947}
2948
2949static int ipv4_sysctl_rt_secret_interval(ctl_table *ctl, int write,
2950 struct file *filp,
2951 void __user *buffer, size_t *lenp,
2952 loff_t *ppos)
2953{
2954 int old = ip_rt_secret_interval;
2955 int ret = proc_dointvec_jiffies(ctl, write, filp, buffer, lenp, ppos);
2956
2957 rt_secret_reschedule(old);
2958
2959 return ret;
2960}
2961
2962static int ipv4_sysctl_rt_secret_interval_strategy(ctl_table *table,
2963 int __user *name,
2964 int nlen,
2965 void __user *oldval,
2966 size_t __user *oldlenp,
2967 void __user *newval,
2968 size_t newlen)
2969{
2970 int old = ip_rt_secret_interval;
2971 int ret = sysctl_jiffies(table, name, nlen, oldval, oldlenp, newval,
2972 newlen);
2973
2974 rt_secret_reschedule(old);
2975
2976 return ret;
2977}
2978
2917static ctl_table ipv4_route_table[] = { 2979static ctl_table ipv4_route_table[] = {
2918 { 2980 {
2919 .ctl_name = NET_IPV4_ROUTE_GC_THRESH, 2981 .ctl_name = NET_IPV4_ROUTE_GC_THRESH,
@@ -3048,20 +3110,29 @@ static ctl_table ipv4_route_table[] = {
3048 .data = &ip_rt_secret_interval, 3110 .data = &ip_rt_secret_interval,
3049 .maxlen = sizeof(int), 3111 .maxlen = sizeof(int),
3050 .mode = 0644, 3112 .mode = 0644,
3051 .proc_handler = &proc_dointvec_jiffies, 3113 .proc_handler = &ipv4_sysctl_rt_secret_interval,
3052 .strategy = &sysctl_jiffies, 3114 .strategy = &ipv4_sysctl_rt_secret_interval_strategy,
3053 }, 3115 },
3054 { .ctl_name = 0 } 3116 { .ctl_name = 0 }
3055}; 3117};
3056 3118
3057static __net_initdata struct ctl_path ipv4_route_path[] = { 3119static struct ctl_table empty[1];
3120
3121static struct ctl_table ipv4_skeleton[] =
3122{
3123 { .procname = "route", .ctl_name = NET_IPV4_ROUTE,
3124 .mode = 0555, .child = ipv4_route_table},
3125 { .procname = "neigh", .ctl_name = NET_IPV4_NEIGH,
3126 .mode = 0555, .child = empty},
3127 { }
3128};
3129
3130static __net_initdata struct ctl_path ipv4_path[] = {
3058 { .procname = "net", .ctl_name = CTL_NET, }, 3131 { .procname = "net", .ctl_name = CTL_NET, },
3059 { .procname = "ipv4", .ctl_name = NET_IPV4, }, 3132 { .procname = "ipv4", .ctl_name = NET_IPV4, },
3060 { .procname = "route", .ctl_name = NET_IPV4_ROUTE, },
3061 { }, 3133 { },
3062}; 3134};
3063 3135
3064
3065static struct ctl_table ipv4_route_flush_table[] = { 3136static struct ctl_table ipv4_route_flush_table[] = {
3066 { 3137 {
3067 .ctl_name = NET_IPV4_ROUTE_FLUSH, 3138 .ctl_name = NET_IPV4_ROUTE_FLUSH,
@@ -3074,6 +3145,13 @@ static struct ctl_table ipv4_route_flush_table[] = {
3074 { .ctl_name = 0 }, 3145 { .ctl_name = 0 },
3075}; 3146};
3076 3147
3148static __net_initdata struct ctl_path ipv4_route_path[] = {
3149 { .procname = "net", .ctl_name = CTL_NET, },
3150 { .procname = "ipv4", .ctl_name = NET_IPV4, },
3151 { .procname = "route", .ctl_name = NET_IPV4_ROUTE, },
3152 { },
3153};
3154
3077static __net_init int sysctl_route_net_init(struct net *net) 3155static __net_init int sysctl_route_net_init(struct net *net)
3078{ 3156{
3079 struct ctl_table *tbl; 3157 struct ctl_table *tbl;
@@ -3126,10 +3204,12 @@ static __net_init int rt_secret_timer_init(struct net *net)
3126 net->ipv4.rt_secret_timer.data = (unsigned long)net; 3204 net->ipv4.rt_secret_timer.data = (unsigned long)net;
3127 init_timer_deferrable(&net->ipv4.rt_secret_timer); 3205 init_timer_deferrable(&net->ipv4.rt_secret_timer);
3128 3206
3129 net->ipv4.rt_secret_timer.expires = 3207 if (ip_rt_secret_interval) {
3130 jiffies + net_random() % ip_rt_secret_interval + 3208 net->ipv4.rt_secret_timer.expires =
3131 ip_rt_secret_interval; 3209 jiffies + net_random() % ip_rt_secret_interval +
3132 add_timer(&net->ipv4.rt_secret_timer); 3210 ip_rt_secret_interval;
3211 add_timer(&net->ipv4.rt_secret_timer);
3212 }
3133 return 0; 3213 return 0;
3134} 3214}
3135 3215
@@ -3223,7 +3303,7 @@ int __init ip_rt_init(void)
3223 */ 3303 */
3224void __init ip_static_sysctl_init(void) 3304void __init ip_static_sysctl_init(void)
3225{ 3305{
3226 register_sysctl_paths(ipv4_route_path, ipv4_route_table); 3306 register_sysctl_paths(ipv4_path, ipv4_skeleton);
3227} 3307}
3228#endif 3308#endif
3229 3309