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