diff options
Diffstat (limited to 'net/ipv4/route.c')
-rw-r--r-- | net/ipv4/route.c | 79 |
1 files changed, 69 insertions, 10 deletions
diff --git a/net/ipv4/route.c b/net/ipv4/route.c index 790de32cd7d4..6fe799de9b96 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c | |||
@@ -2835,6 +2835,7 @@ static int ipv4_sysctl_rtcache_flush(ctl_table *ctl, int write, | |||
2835 | { | 2835 | { |
2836 | if (write) { | 2836 | if (write) { |
2837 | int flush_delay; | 2837 | int flush_delay; |
2838 | struct net *net; | ||
2838 | static DEFINE_MUTEX(flush_mutex); | 2839 | static DEFINE_MUTEX(flush_mutex); |
2839 | 2840 | ||
2840 | mutex_lock(&flush_mutex); | 2841 | mutex_lock(&flush_mutex); |
@@ -2843,7 +2844,8 @@ static int ipv4_sysctl_rtcache_flush(ctl_table *ctl, int write, | |||
2843 | ctl->data = NULL; | 2844 | ctl->data = NULL; |
2844 | mutex_unlock(&flush_mutex); | 2845 | mutex_unlock(&flush_mutex); |
2845 | 2846 | ||
2846 | rt_cache_flush(&init_net, flush_delay); | 2847 | net = (struct net *)ctl->extra1; |
2848 | rt_cache_flush(net, flush_delay); | ||
2847 | return 0; | 2849 | return 0; |
2848 | } | 2850 | } |
2849 | 2851 | ||
@@ -2859,24 +2861,18 @@ static int ipv4_sysctl_rtcache_flush_strategy(ctl_table *table, | |||
2859 | size_t newlen) | 2861 | size_t newlen) |
2860 | { | 2862 | { |
2861 | int delay; | 2863 | int delay; |
2864 | struct net *net; | ||
2862 | if (newlen != sizeof(int)) | 2865 | if (newlen != sizeof(int)) |
2863 | return -EINVAL; | 2866 | return -EINVAL; |
2864 | if (get_user(delay, (int __user *)newval)) | 2867 | if (get_user(delay, (int __user *)newval)) |
2865 | return -EFAULT; | 2868 | return -EFAULT; |
2866 | rt_cache_flush(&init_net, delay); | 2869 | net = (struct net *)table->extra1; |
2870 | rt_cache_flush(net, delay); | ||
2867 | return 0; | 2871 | return 0; |
2868 | } | 2872 | } |
2869 | 2873 | ||
2870 | ctl_table ipv4_route_table[] = { | 2874 | ctl_table ipv4_route_table[] = { |
2871 | { | 2875 | { |
2872 | .ctl_name = NET_IPV4_ROUTE_FLUSH, | ||
2873 | .procname = "flush", | ||
2874 | .maxlen = sizeof(int), | ||
2875 | .mode = 0200, | ||
2876 | .proc_handler = &ipv4_sysctl_rtcache_flush, | ||
2877 | .strategy = &ipv4_sysctl_rtcache_flush_strategy, | ||
2878 | }, | ||
2879 | { | ||
2880 | .ctl_name = NET_IPV4_ROUTE_GC_THRESH, | 2876 | .ctl_name = NET_IPV4_ROUTE_GC_THRESH, |
2881 | .procname = "gc_thresh", | 2877 | .procname = "gc_thresh", |
2882 | .data = &ipv4_dst_ops.gc_thresh, | 2878 | .data = &ipv4_dst_ops.gc_thresh, |
@@ -3014,6 +3010,66 @@ ctl_table ipv4_route_table[] = { | |||
3014 | }, | 3010 | }, |
3015 | { .ctl_name = 0 } | 3011 | { .ctl_name = 0 } |
3016 | }; | 3012 | }; |
3013 | |||
3014 | static __net_initdata struct ctl_path ipv4_route_path[] = { | ||
3015 | { .procname = "net", .ctl_name = CTL_NET, }, | ||
3016 | { .procname = "ipv4", .ctl_name = NET_IPV4, }, | ||
3017 | { .procname = "route", .ctl_name = NET_IPV4_ROUTE, }, | ||
3018 | { }, | ||
3019 | }; | ||
3020 | |||
3021 | |||
3022 | static struct ctl_table ipv4_route_flush_table[] = { | ||
3023 | { | ||
3024 | .ctl_name = NET_IPV4_ROUTE_FLUSH, | ||
3025 | .procname = "flush", | ||
3026 | .maxlen = sizeof(int), | ||
3027 | .mode = 0200, | ||
3028 | .proc_handler = &ipv4_sysctl_rtcache_flush, | ||
3029 | .strategy = &ipv4_sysctl_rtcache_flush_strategy, | ||
3030 | }, | ||
3031 | { .ctl_name = 0 }, | ||
3032 | }; | ||
3033 | |||
3034 | static __net_init int sysctl_route_net_init(struct net *net) | ||
3035 | { | ||
3036 | struct ctl_table *tbl; | ||
3037 | |||
3038 | tbl = ipv4_route_flush_table; | ||
3039 | if (net != &init_net) { | ||
3040 | tbl = kmemdup(tbl, sizeof(ipv4_route_flush_table), GFP_KERNEL); | ||
3041 | if (tbl == NULL) | ||
3042 | goto err_dup; | ||
3043 | } | ||
3044 | tbl[0].extra1 = net; | ||
3045 | |||
3046 | net->ipv4.route_hdr = | ||
3047 | register_net_sysctl_table(net, ipv4_route_path, tbl); | ||
3048 | if (net->ipv4.route_hdr == NULL) | ||
3049 | goto err_reg; | ||
3050 | return 0; | ||
3051 | |||
3052 | err_reg: | ||
3053 | if (tbl != ipv4_route_flush_table) | ||
3054 | kfree(tbl); | ||
3055 | err_dup: | ||
3056 | return -ENOMEM; | ||
3057 | } | ||
3058 | |||
3059 | static __net_exit void sysctl_route_net_exit(struct net *net) | ||
3060 | { | ||
3061 | struct ctl_table *tbl; | ||
3062 | |||
3063 | tbl = net->ipv4.route_hdr->ctl_table_arg; | ||
3064 | unregister_net_sysctl_table(net->ipv4.route_hdr); | ||
3065 | BUG_ON(tbl == ipv4_route_flush_table); | ||
3066 | kfree(tbl); | ||
3067 | } | ||
3068 | |||
3069 | static __net_initdata struct pernet_operations sysctl_route_ops = { | ||
3070 | .init = sysctl_route_net_init, | ||
3071 | .exit = sysctl_route_net_exit, | ||
3072 | }; | ||
3017 | #endif | 3073 | #endif |
3018 | 3074 | ||
3019 | #ifdef CONFIG_NET_CLS_ROUTE | 3075 | #ifdef CONFIG_NET_CLS_ROUTE |
@@ -3090,6 +3146,9 @@ int __init ip_rt_init(void) | |||
3090 | #endif | 3146 | #endif |
3091 | rtnl_register(PF_INET, RTM_GETROUTE, inet_rtm_getroute, NULL); | 3147 | rtnl_register(PF_INET, RTM_GETROUTE, inet_rtm_getroute, NULL); |
3092 | 3148 | ||
3149 | #ifdef CONFIG_SYSCTL | ||
3150 | register_pernet_subsys(&sysctl_route_ops); | ||
3151 | #endif | ||
3093 | return rc; | 3152 | return rc; |
3094 | } | 3153 | } |
3095 | 3154 | ||