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