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 <net/ndisc.h>
  14#include <net/ipv6.h>
  15#include <net/addrconf.h>
  16#include <net/inet_frag.h>
  17
  18static struct ctl_table empty[1];
  19
  20static ctl_table ipv6_table_template[] = {
  21        {
  22                .procname       = "route",
  23                .maxlen         = 0,
  24                .mode           = 0555,
  25                .child          = ipv6_route_table_template
  26        },
  27        {
  28                .procname       = "icmp",
  29                .maxlen         = 0,
  30                .mode           = 0555,
  31                .child          = ipv6_icmp_table_template
  32        },
  33        {
  34                .procname       = "bindv6only",
  35                .data           = &init_net.ipv6.sysctl.bindv6only,
  36                .maxlen         = sizeof(int),
  37                .mode           = 0644,
  38                .proc_handler   = proc_dointvec
  39        },
  40        {
  41                .procname       = "neigh",
  42                .maxlen         = 0,
  43                .mode           = 0555,
  44                .child          = empty,
  45        },
  46        { }
  47};
  48
  49static ctl_table ipv6_rotable[] = {
  50        {
  51                .procname       = "mld_max_msf",
  52                .data           = &sysctl_mld_max_msf,
  53                .maxlen         = sizeof(int),
  54                .mode           = 0644,
  55                .proc_handler   = proc_dointvec
  56        },
  57        { }
  58};
  59
  60struct ctl_path net_ipv6_ctl_path[] = {
  61        { .procname = "net", },
  62        { .procname = "ipv6", },
  63        { },
  64};
  65EXPORT_SYMBOL_GPL(net_ipv6_ctl_path);
  66
  67static int __net_init ipv6_sysctl_net_init(struct net *net)
  68{
  69        struct ctl_table *ipv6_table;
  70        struct ctl_table *ipv6_route_table;
  71        struct ctl_table *ipv6_icmp_table;
  72        int err;
  73
  74        err = -ENOMEM;
  75        ipv6_table = kmemdup(ipv6_table_template, sizeof(ipv6_table_template),
  76                             GFP_KERNEL);
  77        if (!ipv6_table)
  78                goto out;
  79
  80        ipv6_route_table = ipv6_route_sysctl_init(net);
  81        if (!ipv6_route_table)
  82                goto out_ipv6_table;
  83        ipv6_table[0].child = ipv6_route_table;
  84
  85        ipv6_icmp_table = ipv6_icmp_sysctl_init(net);
  86        if (!ipv6_icmp_table)
  87                goto out_ipv6_route_table;
  88        ipv6_table[1].child = ipv6_icmp_table;
  89
  90        ipv6_table[2].data = &net->ipv6.sysctl.bindv6only;
  91
  92        net->ipv6.sysctl.table = register_net_sysctl_table(net, net_ipv6_ctl_path,
  93                                                           ipv6_table);
  94        if (!net->ipv6.sysctl.table)
  95                goto out_ipv6_icmp_table;
  96
  97        err = 0;
  98out:
  99        return err;
 100
 101out_ipv6_icmp_table:
 102        kfree(ipv6_icmp_table);
 103out_ipv6_route_table:
 104        kfree(ipv6_route_table);
 105out_ipv6_table:
 106        kfree(ipv6_table);
 107        goto out;
 108}
 109
 110static void __net_exit ipv6_sysctl_net_exit(struct net *net)
 111{
 112        struct ctl_table *ipv6_table;
 113        struct ctl_table *ipv6_route_table;
 114        struct ctl_table *ipv6_icmp_table;
 115
 116        ipv6_table = net->ipv6.sysctl.table->ctl_table_arg;
 117        ipv6_route_table = ipv6_table[0].child;
 118        ipv6_icmp_table = ipv6_table[1].child;
 119
 120        unregister_net_sysctl_table(net->ipv6.sysctl.table);
 121
 122        kfree(ipv6_table);
 123        kfree(ipv6_route_table);
 124        kfree(ipv6_icmp_table);
 125}
 126
 127static struct pernet_operations ipv6_sysctl_net_ops = {
 128        .init = ipv6_sysctl_net_init,
 129        .exit = ipv6_sysctl_net_exit,
 130};
 131
 132static struct ctl_table_header *ip6_header;
 133
 134int ipv6_sysctl_register(void)
 135{
 136        int err = -ENOMEM;
 137
 138        ip6_header = register_net_sysctl_rotable(net_ipv6_ctl_path, ipv6_rotable);
 139        if (ip6_header == NULL)
 140                goto out;
 141
 142        err = register_pernet_subsys(&ipv6_sysctl_net_ops);
 143        if (err)
 144                goto err_pernet;
 145out:
 146        return err;
 147
 148err_pernet:
 149        unregister_net_sysctl_table(ip6_header);
 150        goto out;
 151}
 152
 153void ipv6_sysctl_unregister(void)
 154{
 155        unregister_net_sysctl_table(ip6_header);
 156        unregister_pernet_subsys(&ipv6_sysctl_net_ops);
 157}
 158
 159static struct ctl_table_header *ip6_base;
 160
 161int ipv6_static_sysctl_register(void)
 162{
 163        ip6_base = register_sysctl_paths(net_ipv6_ctl_path, empty);
 164        if (ip6_base == NULL)
 165                return -ENOMEM;
 166        return 0;
 167}
 168
 169void ipv6_static_sysctl_unregister(void)
 170{
 171        unregister_net_sysctl_table(ip6_base);
 172}
 173