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