linux/net/ipv6/sysctl_net_ipv6.c
<<
>>
Prefs
   1/*
   2 * sysctl_net_ipv6.c: sysctl interface to net IPV6 subsystem.
   3 *
   4 * Changes:
   5 * YOSHIFUJI Hideaki @USAGI:    added icmp sysctl table.
   6 */
   7
   8#include <linux/mm.h>
   9#include <linux/sysctl.h>
  10#include <linux/in6.h>
  11#include <linux/ipv6.h>
  12#include <linux/slab.h>
  13#include <linux/export.h>
  14#include <net/ndisc.h>
  15#include <net/ipv6.h>
  16#include <net/addrconf.h>
  17#include <net/inet_frag.h>
  18#ifdef CONFIG_NETLABEL
  19#include <net/calipso.h>
  20#endif
  21
  22static int one = 1;
  23static int auto_flowlabels_min;
  24static int auto_flowlabels_max = IP6_AUTO_FLOW_LABEL_MAX;
  25
  26
  27static struct ctl_table ipv6_table_template[] = {
  28        {
  29                .procname       = "bindv6only",
  30                .data           = &init_net.ipv6.sysctl.bindv6only,
  31                .maxlen         = sizeof(int),
  32                .mode           = 0644,
  33                .proc_handler   = proc_dointvec
  34        },
  35        {
  36                .procname       = "anycast_src_echo_reply",
  37                .data           = &init_net.ipv6.sysctl.anycast_src_echo_reply,
  38                .maxlen         = sizeof(int),
  39                .mode           = 0644,
  40                .proc_handler   = proc_dointvec
  41        },
  42        {
  43                .procname       = "flowlabel_consistency",
  44                .data           = &init_net.ipv6.sysctl.flowlabel_consistency,
  45                .maxlen         = sizeof(int),
  46                .mode           = 0644,
  47                .proc_handler   = proc_dointvec
  48        },
  49        {
  50                .procname       = "auto_flowlabels",
  51                .data           = &init_net.ipv6.sysctl.auto_flowlabels,
  52                .maxlen         = sizeof(int),
  53                .mode           = 0644,
  54                .proc_handler   = proc_dointvec_minmax,
  55                .extra1         = &auto_flowlabels_min,
  56                .extra2         = &auto_flowlabels_max
  57        },
  58        {
  59                .procname       = "fwmark_reflect",
  60                .data           = &init_net.ipv6.sysctl.fwmark_reflect,
  61                .maxlen         = sizeof(int),
  62                .mode           = 0644,
  63                .proc_handler   = proc_dointvec
  64        },
  65        {
  66                .procname       = "idgen_retries",
  67                .data           = &init_net.ipv6.sysctl.idgen_retries,
  68                .maxlen         = sizeof(int),
  69                .mode           = 0644,
  70                .proc_handler   = proc_dointvec,
  71        },
  72        {
  73                .procname       = "idgen_delay",
  74                .data           = &init_net.ipv6.sysctl.idgen_delay,
  75                .maxlen         = sizeof(int),
  76                .mode           = 0644,
  77                .proc_handler   = proc_dointvec_jiffies,
  78        },
  79        {
  80                .procname       = "flowlabel_state_ranges",
  81                .data           = &init_net.ipv6.sysctl.flowlabel_state_ranges,
  82                .maxlen         = sizeof(int),
  83                .mode           = 0644,
  84                .proc_handler   = proc_dointvec
  85        },
  86        {
  87                .procname       = "ip_nonlocal_bind",
  88                .data           = &init_net.ipv6.sysctl.ip_nonlocal_bind,
  89                .maxlen         = sizeof(int),
  90                .mode           = 0644,
  91                .proc_handler   = proc_dointvec
  92        },
  93        { }
  94};
  95
  96static struct ctl_table ipv6_rotable[] = {
  97        {
  98                .procname       = "mld_max_msf",
  99                .data           = &sysctl_mld_max_msf,
 100                .maxlen         = sizeof(int),
 101                .mode           = 0644,
 102                .proc_handler   = proc_dointvec
 103        },
 104        {
 105                .procname       = "mld_qrv",
 106                .data           = &sysctl_mld_qrv,
 107                .maxlen         = sizeof(int),
 108                .mode           = 0644,
 109                .proc_handler   = proc_dointvec_minmax,
 110                .extra1         = &one
 111        },
 112#ifdef CONFIG_NETLABEL
 113        {
 114                .procname       = "calipso_cache_enable",
 115                .data           = &calipso_cache_enabled,
 116                .maxlen         = sizeof(int),
 117                .mode           = 0644,
 118                .proc_handler   = proc_dointvec,
 119        },
 120        {
 121                .procname       = "calipso_cache_bucket_size",
 122                .data           = &calipso_cache_bucketsize,
 123                .maxlen         = sizeof(int),
 124                .mode           = 0644,
 125                .proc_handler   = proc_dointvec,
 126        },
 127#endif /* CONFIG_NETLABEL */
 128        { }
 129};
 130
 131static int __net_init ipv6_sysctl_net_init(struct net *net)
 132{
 133        struct ctl_table *ipv6_table;
 134        struct ctl_table *ipv6_route_table;
 135        struct ctl_table *ipv6_icmp_table;
 136        int err;
 137
 138        err = -ENOMEM;
 139        ipv6_table = kmemdup(ipv6_table_template, sizeof(ipv6_table_template),
 140                             GFP_KERNEL);
 141        if (!ipv6_table)
 142                goto out;
 143        ipv6_table[0].data = &net->ipv6.sysctl.bindv6only;
 144        ipv6_table[1].data = &net->ipv6.sysctl.anycast_src_echo_reply;
 145        ipv6_table[2].data = &net->ipv6.sysctl.flowlabel_consistency;
 146        ipv6_table[3].data = &net->ipv6.sysctl.auto_flowlabels;
 147        ipv6_table[4].data = &net->ipv6.sysctl.fwmark_reflect;
 148        ipv6_table[5].data = &net->ipv6.sysctl.idgen_retries;
 149        ipv6_table[6].data = &net->ipv6.sysctl.idgen_delay;
 150        ipv6_table[7].data = &net->ipv6.sysctl.flowlabel_state_ranges;
 151        ipv6_table[8].data = &net->ipv6.sysctl.ip_nonlocal_bind;
 152
 153        ipv6_route_table = ipv6_route_sysctl_init(net);
 154        if (!ipv6_route_table)
 155                goto out_ipv6_table;
 156
 157        ipv6_icmp_table = ipv6_icmp_sysctl_init(net);
 158        if (!ipv6_icmp_table)
 159                goto out_ipv6_route_table;
 160
 161        net->ipv6.sysctl.hdr = register_net_sysctl(net, "net/ipv6", ipv6_table);
 162        if (!net->ipv6.sysctl.hdr)
 163                goto out_ipv6_icmp_table;
 164
 165        net->ipv6.sysctl.route_hdr =
 166                register_net_sysctl(net, "net/ipv6/route", ipv6_route_table);
 167        if (!net->ipv6.sysctl.route_hdr)
 168                goto out_unregister_ipv6_table;
 169
 170        net->ipv6.sysctl.icmp_hdr =
 171                register_net_sysctl(net, "net/ipv6/icmp", ipv6_icmp_table);
 172        if (!net->ipv6.sysctl.icmp_hdr)
 173                goto out_unregister_route_table;
 174
 175        err = 0;
 176out:
 177        return err;
 178out_unregister_route_table:
 179        unregister_net_sysctl_table(net->ipv6.sysctl.route_hdr);
 180out_unregister_ipv6_table:
 181        unregister_net_sysctl_table(net->ipv6.sysctl.hdr);
 182out_ipv6_icmp_table:
 183        kfree(ipv6_icmp_table);
 184out_ipv6_route_table:
 185        kfree(ipv6_route_table);
 186out_ipv6_table:
 187        kfree(ipv6_table);
 188        goto out;
 189}
 190
 191static void __net_exit ipv6_sysctl_net_exit(struct net *net)
 192{
 193        struct ctl_table *ipv6_table;
 194        struct ctl_table *ipv6_route_table;
 195        struct ctl_table *ipv6_icmp_table;
 196
 197        ipv6_table = net->ipv6.sysctl.hdr->ctl_table_arg;
 198        ipv6_route_table = net->ipv6.sysctl.route_hdr->ctl_table_arg;
 199        ipv6_icmp_table = net->ipv6.sysctl.icmp_hdr->ctl_table_arg;
 200
 201        unregister_net_sysctl_table(net->ipv6.sysctl.icmp_hdr);
 202        unregister_net_sysctl_table(net->ipv6.sysctl.route_hdr);
 203        unregister_net_sysctl_table(net->ipv6.sysctl.hdr);
 204
 205        kfree(ipv6_table);
 206        kfree(ipv6_route_table);
 207        kfree(ipv6_icmp_table);
 208}
 209
 210static struct pernet_operations ipv6_sysctl_net_ops = {
 211        .init = ipv6_sysctl_net_init,
 212        .exit = ipv6_sysctl_net_exit,
 213};
 214
 215static struct ctl_table_header *ip6_header;
 216
 217int ipv6_sysctl_register(void)
 218{
 219        int err = -ENOMEM;
 220
 221        ip6_header = register_net_sysctl(&init_net, "net/ipv6", ipv6_rotable);
 222        if (!ip6_header)
 223                goto out;
 224
 225        err = register_pernet_subsys(&ipv6_sysctl_net_ops);
 226        if (err)
 227                goto err_pernet;
 228out:
 229        return err;
 230
 231err_pernet:
 232        unregister_net_sysctl_table(ip6_header);
 233        goto out;
 234}
 235
 236void ipv6_sysctl_unregister(void)
 237{
 238        unregister_net_sysctl_table(ip6_header);
 239        unregister_pernet_subsys(&ipv6_sysctl_net_ops);
 240}
 241