root/net/ipv6/proc.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. sockstat6_seq_show
  2. snmp6_seq_show_icmpv6msg
  3. snmp6_seq_show_item
  4. snmp6_seq_show_item64
  5. snmp6_seq_show
  6. snmp6_dev_seq_show
  7. snmp6_register_dev
  8. snmp6_unregister_dev
  9. ipv6_proc_init_net
  10. ipv6_proc_exit_net
  11. ipv6_misc_proc_init
  12. ipv6_misc_proc_exit

   1 // SPDX-License-Identifier: GPL-2.0-or-later
   2 /*
   3  * INET         An implementation of the TCP/IP protocol suite for the LINUX
   4  *              operating system.  INET is implemented using the  BSD Socket
   5  *              interface as the means of communication with the user level.
   6  *
   7  *              This file implements the various access functions for the
   8  *              PROC file system.  This is very similar to the IPv4 version,
   9  *              except it reports the sockets in the INET6 address family.
  10  *
  11  * Authors:     David S. Miller (davem@caip.rutgers.edu)
  12  *              YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
  13  */
  14 #include <linux/socket.h>
  15 #include <linux/net.h>
  16 #include <linux/ipv6.h>
  17 #include <linux/proc_fs.h>
  18 #include <linux/seq_file.h>
  19 #include <linux/stddef.h>
  20 #include <linux/export.h>
  21 #include <net/net_namespace.h>
  22 #include <net/ip.h>
  23 #include <net/sock.h>
  24 #include <net/tcp.h>
  25 #include <net/udp.h>
  26 #include <net/transp_v6.h>
  27 #include <net/ipv6.h>
  28 
  29 #define MAX4(a, b, c, d) \
  30         max_t(u32, max_t(u32, a, b), max_t(u32, c, d))
  31 #define SNMP_MIB_MAX MAX4(UDP_MIB_MAX, TCP_MIB_MAX, \
  32                         IPSTATS_MIB_MAX, ICMP_MIB_MAX)
  33 
  34 static int sockstat6_seq_show(struct seq_file *seq, void *v)
  35 {
  36         struct net *net = seq->private;
  37 
  38         seq_printf(seq, "TCP6: inuse %d\n",
  39                        sock_prot_inuse_get(net, &tcpv6_prot));
  40         seq_printf(seq, "UDP6: inuse %d\n",
  41                        sock_prot_inuse_get(net, &udpv6_prot));
  42         seq_printf(seq, "UDPLITE6: inuse %d\n",
  43                         sock_prot_inuse_get(net, &udplitev6_prot));
  44         seq_printf(seq, "RAW6: inuse %d\n",
  45                        sock_prot_inuse_get(net, &rawv6_prot));
  46         seq_printf(seq, "FRAG6: inuse %u memory %lu\n",
  47                    atomic_read(&net->ipv6.fqdir->rhashtable.nelems),
  48                    frag_mem_limit(net->ipv6.fqdir));
  49         return 0;
  50 }
  51 
  52 static const struct snmp_mib snmp6_ipstats_list[] = {
  53 /* ipv6 mib according to RFC 2465 */
  54         SNMP_MIB_ITEM("Ip6InReceives", IPSTATS_MIB_INPKTS),
  55         SNMP_MIB_ITEM("Ip6InHdrErrors", IPSTATS_MIB_INHDRERRORS),
  56         SNMP_MIB_ITEM("Ip6InTooBigErrors", IPSTATS_MIB_INTOOBIGERRORS),
  57         SNMP_MIB_ITEM("Ip6InNoRoutes", IPSTATS_MIB_INNOROUTES),
  58         SNMP_MIB_ITEM("Ip6InAddrErrors", IPSTATS_MIB_INADDRERRORS),
  59         SNMP_MIB_ITEM("Ip6InUnknownProtos", IPSTATS_MIB_INUNKNOWNPROTOS),
  60         SNMP_MIB_ITEM("Ip6InTruncatedPkts", IPSTATS_MIB_INTRUNCATEDPKTS),
  61         SNMP_MIB_ITEM("Ip6InDiscards", IPSTATS_MIB_INDISCARDS),
  62         SNMP_MIB_ITEM("Ip6InDelivers", IPSTATS_MIB_INDELIVERS),
  63         SNMP_MIB_ITEM("Ip6OutForwDatagrams", IPSTATS_MIB_OUTFORWDATAGRAMS),
  64         SNMP_MIB_ITEM("Ip6OutRequests", IPSTATS_MIB_OUTPKTS),
  65         SNMP_MIB_ITEM("Ip6OutDiscards", IPSTATS_MIB_OUTDISCARDS),
  66         SNMP_MIB_ITEM("Ip6OutNoRoutes", IPSTATS_MIB_OUTNOROUTES),
  67         SNMP_MIB_ITEM("Ip6ReasmTimeout", IPSTATS_MIB_REASMTIMEOUT),
  68         SNMP_MIB_ITEM("Ip6ReasmReqds", IPSTATS_MIB_REASMREQDS),
  69         SNMP_MIB_ITEM("Ip6ReasmOKs", IPSTATS_MIB_REASMOKS),
  70         SNMP_MIB_ITEM("Ip6ReasmFails", IPSTATS_MIB_REASMFAILS),
  71         SNMP_MIB_ITEM("Ip6FragOKs", IPSTATS_MIB_FRAGOKS),
  72         SNMP_MIB_ITEM("Ip6FragFails", IPSTATS_MIB_FRAGFAILS),
  73         SNMP_MIB_ITEM("Ip6FragCreates", IPSTATS_MIB_FRAGCREATES),
  74         SNMP_MIB_ITEM("Ip6InMcastPkts", IPSTATS_MIB_INMCASTPKTS),
  75         SNMP_MIB_ITEM("Ip6OutMcastPkts", IPSTATS_MIB_OUTMCASTPKTS),
  76         SNMP_MIB_ITEM("Ip6InOctets", IPSTATS_MIB_INOCTETS),
  77         SNMP_MIB_ITEM("Ip6OutOctets", IPSTATS_MIB_OUTOCTETS),
  78         SNMP_MIB_ITEM("Ip6InMcastOctets", IPSTATS_MIB_INMCASTOCTETS),
  79         SNMP_MIB_ITEM("Ip6OutMcastOctets", IPSTATS_MIB_OUTMCASTOCTETS),
  80         SNMP_MIB_ITEM("Ip6InBcastOctets", IPSTATS_MIB_INBCASTOCTETS),
  81         SNMP_MIB_ITEM("Ip6OutBcastOctets", IPSTATS_MIB_OUTBCASTOCTETS),
  82         /* IPSTATS_MIB_CSUMERRORS is not relevant in IPv6 (no checksum) */
  83         SNMP_MIB_ITEM("Ip6InNoECTPkts", IPSTATS_MIB_NOECTPKTS),
  84         SNMP_MIB_ITEM("Ip6InECT1Pkts", IPSTATS_MIB_ECT1PKTS),
  85         SNMP_MIB_ITEM("Ip6InECT0Pkts", IPSTATS_MIB_ECT0PKTS),
  86         SNMP_MIB_ITEM("Ip6InCEPkts", IPSTATS_MIB_CEPKTS),
  87         SNMP_MIB_SENTINEL
  88 };
  89 
  90 static const struct snmp_mib snmp6_icmp6_list[] = {
  91 /* icmpv6 mib according to RFC 2466 */
  92         SNMP_MIB_ITEM("Icmp6InMsgs", ICMP6_MIB_INMSGS),
  93         SNMP_MIB_ITEM("Icmp6InErrors", ICMP6_MIB_INERRORS),
  94         SNMP_MIB_ITEM("Icmp6OutMsgs", ICMP6_MIB_OUTMSGS),
  95         SNMP_MIB_ITEM("Icmp6OutErrors", ICMP6_MIB_OUTERRORS),
  96         SNMP_MIB_ITEM("Icmp6InCsumErrors", ICMP6_MIB_CSUMERRORS),
  97         SNMP_MIB_SENTINEL
  98 };
  99 
 100 /* RFC 4293 v6 ICMPMsgStatsTable; named items for RFC 2466 compatibility */
 101 static const char *const icmp6type2name[256] = {
 102         [ICMPV6_DEST_UNREACH] = "DestUnreachs",
 103         [ICMPV6_PKT_TOOBIG] = "PktTooBigs",
 104         [ICMPV6_TIME_EXCEED] = "TimeExcds",
 105         [ICMPV6_PARAMPROB] = "ParmProblems",
 106         [ICMPV6_ECHO_REQUEST] = "Echos",
 107         [ICMPV6_ECHO_REPLY] = "EchoReplies",
 108         [ICMPV6_MGM_QUERY] = "GroupMembQueries",
 109         [ICMPV6_MGM_REPORT] = "GroupMembResponses",
 110         [ICMPV6_MGM_REDUCTION] = "GroupMembReductions",
 111         [ICMPV6_MLD2_REPORT] = "MLDv2Reports",
 112         [NDISC_ROUTER_ADVERTISEMENT] = "RouterAdvertisements",
 113         [NDISC_ROUTER_SOLICITATION] = "RouterSolicits",
 114         [NDISC_NEIGHBOUR_ADVERTISEMENT] = "NeighborAdvertisements",
 115         [NDISC_NEIGHBOUR_SOLICITATION] = "NeighborSolicits",
 116         [NDISC_REDIRECT] = "Redirects",
 117 };
 118 
 119 
 120 static const struct snmp_mib snmp6_udp6_list[] = {
 121         SNMP_MIB_ITEM("Udp6InDatagrams", UDP_MIB_INDATAGRAMS),
 122         SNMP_MIB_ITEM("Udp6NoPorts", UDP_MIB_NOPORTS),
 123         SNMP_MIB_ITEM("Udp6InErrors", UDP_MIB_INERRORS),
 124         SNMP_MIB_ITEM("Udp6OutDatagrams", UDP_MIB_OUTDATAGRAMS),
 125         SNMP_MIB_ITEM("Udp6RcvbufErrors", UDP_MIB_RCVBUFERRORS),
 126         SNMP_MIB_ITEM("Udp6SndbufErrors", UDP_MIB_SNDBUFERRORS),
 127         SNMP_MIB_ITEM("Udp6InCsumErrors", UDP_MIB_CSUMERRORS),
 128         SNMP_MIB_ITEM("Udp6IgnoredMulti", UDP_MIB_IGNOREDMULTI),
 129         SNMP_MIB_SENTINEL
 130 };
 131 
 132 static const struct snmp_mib snmp6_udplite6_list[] = {
 133         SNMP_MIB_ITEM("UdpLite6InDatagrams", UDP_MIB_INDATAGRAMS),
 134         SNMP_MIB_ITEM("UdpLite6NoPorts", UDP_MIB_NOPORTS),
 135         SNMP_MIB_ITEM("UdpLite6InErrors", UDP_MIB_INERRORS),
 136         SNMP_MIB_ITEM("UdpLite6OutDatagrams", UDP_MIB_OUTDATAGRAMS),
 137         SNMP_MIB_ITEM("UdpLite6RcvbufErrors", UDP_MIB_RCVBUFERRORS),
 138         SNMP_MIB_ITEM("UdpLite6SndbufErrors", UDP_MIB_SNDBUFERRORS),
 139         SNMP_MIB_ITEM("UdpLite6InCsumErrors", UDP_MIB_CSUMERRORS),
 140         SNMP_MIB_SENTINEL
 141 };
 142 
 143 static void snmp6_seq_show_icmpv6msg(struct seq_file *seq, atomic_long_t *smib)
 144 {
 145         char name[32];
 146         int i;
 147 
 148         /* print by name -- deprecated items */
 149         for (i = 0; i < ICMP6MSG_MIB_MAX; i++) {
 150                 int icmptype;
 151                 const char *p;
 152 
 153                 icmptype = i & 0xff;
 154                 p = icmp6type2name[icmptype];
 155                 if (!p) /* don't print un-named types here */
 156                         continue;
 157                 snprintf(name, sizeof(name), "Icmp6%s%s",
 158                         i & 0x100 ? "Out" : "In", p);
 159                 seq_printf(seq, "%-32s\t%lu\n", name,
 160                            atomic_long_read(smib + i));
 161         }
 162 
 163         /* print by number (nonzero only) - ICMPMsgStat format */
 164         for (i = 0; i < ICMP6MSG_MIB_MAX; i++) {
 165                 unsigned long val;
 166 
 167                 val = atomic_long_read(smib + i);
 168                 if (!val)
 169                         continue;
 170                 snprintf(name, sizeof(name), "Icmp6%sType%u",
 171                         i & 0x100 ?  "Out" : "In", i & 0xff);
 172                 seq_printf(seq, "%-32s\t%lu\n", name, val);
 173         }
 174 }
 175 
 176 /* can be called either with percpu mib (pcpumib != NULL),
 177  * or shared one (smib != NULL)
 178  */
 179 static void snmp6_seq_show_item(struct seq_file *seq, void __percpu *pcpumib,
 180                                 atomic_long_t *smib,
 181                                 const struct snmp_mib *itemlist)
 182 {
 183         unsigned long buff[SNMP_MIB_MAX];
 184         int i;
 185 
 186         if (pcpumib) {
 187                 memset(buff, 0, sizeof(unsigned long) * SNMP_MIB_MAX);
 188 
 189                 snmp_get_cpu_field_batch(buff, itemlist, pcpumib);
 190                 for (i = 0; itemlist[i].name; i++)
 191                         seq_printf(seq, "%-32s\t%lu\n",
 192                                    itemlist[i].name, buff[i]);
 193         } else {
 194                 for (i = 0; itemlist[i].name; i++)
 195                         seq_printf(seq, "%-32s\t%lu\n", itemlist[i].name,
 196                                    atomic_long_read(smib + itemlist[i].entry));
 197         }
 198 }
 199 
 200 static void snmp6_seq_show_item64(struct seq_file *seq, void __percpu *mib,
 201                                   const struct snmp_mib *itemlist, size_t syncpoff)
 202 {
 203         u64 buff64[SNMP_MIB_MAX];
 204         int i;
 205 
 206         memset(buff64, 0, sizeof(u64) * SNMP_MIB_MAX);
 207 
 208         snmp_get_cpu_field64_batch(buff64, itemlist, mib, syncpoff);
 209         for (i = 0; itemlist[i].name; i++)
 210                 seq_printf(seq, "%-32s\t%llu\n", itemlist[i].name, buff64[i]);
 211 }
 212 
 213 static int snmp6_seq_show(struct seq_file *seq, void *v)
 214 {
 215         struct net *net = (struct net *)seq->private;
 216 
 217         snmp6_seq_show_item64(seq, net->mib.ipv6_statistics,
 218                             snmp6_ipstats_list, offsetof(struct ipstats_mib, syncp));
 219         snmp6_seq_show_item(seq, net->mib.icmpv6_statistics,
 220                             NULL, snmp6_icmp6_list);
 221         snmp6_seq_show_icmpv6msg(seq, net->mib.icmpv6msg_statistics->mibs);
 222         snmp6_seq_show_item(seq, net->mib.udp_stats_in6,
 223                             NULL, snmp6_udp6_list);
 224         snmp6_seq_show_item(seq, net->mib.udplite_stats_in6,
 225                             NULL, snmp6_udplite6_list);
 226         return 0;
 227 }
 228 
 229 static int snmp6_dev_seq_show(struct seq_file *seq, void *v)
 230 {
 231         struct inet6_dev *idev = (struct inet6_dev *)seq->private;
 232 
 233         seq_printf(seq, "%-32s\t%u\n", "ifIndex", idev->dev->ifindex);
 234         snmp6_seq_show_item64(seq, idev->stats.ipv6,
 235                             snmp6_ipstats_list, offsetof(struct ipstats_mib, syncp));
 236         snmp6_seq_show_item(seq, NULL, idev->stats.icmpv6dev->mibs,
 237                             snmp6_icmp6_list);
 238         snmp6_seq_show_icmpv6msg(seq, idev->stats.icmpv6msgdev->mibs);
 239         return 0;
 240 }
 241 
 242 int snmp6_register_dev(struct inet6_dev *idev)
 243 {
 244         struct proc_dir_entry *p;
 245         struct net *net;
 246 
 247         if (!idev || !idev->dev)
 248                 return -EINVAL;
 249 
 250         net = dev_net(idev->dev);
 251         if (!net->mib.proc_net_devsnmp6)
 252                 return -ENOENT;
 253 
 254         p = proc_create_single_data(idev->dev->name, 0444,
 255                         net->mib.proc_net_devsnmp6, snmp6_dev_seq_show, idev);
 256         if (!p)
 257                 return -ENOMEM;
 258 
 259         idev->stats.proc_dir_entry = p;
 260         return 0;
 261 }
 262 
 263 int snmp6_unregister_dev(struct inet6_dev *idev)
 264 {
 265         struct net *net = dev_net(idev->dev);
 266         if (!net->mib.proc_net_devsnmp6)
 267                 return -ENOENT;
 268         if (!idev->stats.proc_dir_entry)
 269                 return -EINVAL;
 270         proc_remove(idev->stats.proc_dir_entry);
 271         idev->stats.proc_dir_entry = NULL;
 272         return 0;
 273 }
 274 
 275 static int __net_init ipv6_proc_init_net(struct net *net)
 276 {
 277         if (!proc_create_net_single("sockstat6", 0444, net->proc_net,
 278                         sockstat6_seq_show, NULL))
 279                 return -ENOMEM;
 280 
 281         if (!proc_create_net_single("snmp6", 0444, net->proc_net,
 282                         snmp6_seq_show, NULL))
 283                 goto proc_snmp6_fail;
 284 
 285         net->mib.proc_net_devsnmp6 = proc_mkdir("dev_snmp6", net->proc_net);
 286         if (!net->mib.proc_net_devsnmp6)
 287                 goto proc_dev_snmp6_fail;
 288         return 0;
 289 
 290 proc_dev_snmp6_fail:
 291         remove_proc_entry("snmp6", net->proc_net);
 292 proc_snmp6_fail:
 293         remove_proc_entry("sockstat6", net->proc_net);
 294         return -ENOMEM;
 295 }
 296 
 297 static void __net_exit ipv6_proc_exit_net(struct net *net)
 298 {
 299         remove_proc_entry("sockstat6", net->proc_net);
 300         remove_proc_entry("dev_snmp6", net->proc_net);
 301         remove_proc_entry("snmp6", net->proc_net);
 302 }
 303 
 304 static struct pernet_operations ipv6_proc_ops = {
 305         .init = ipv6_proc_init_net,
 306         .exit = ipv6_proc_exit_net,
 307 };
 308 
 309 int __init ipv6_misc_proc_init(void)
 310 {
 311         return register_pernet_subsys(&ipv6_proc_ops);
 312 }
 313 
 314 void ipv6_misc_proc_exit(void)
 315 {
 316         unregister_pernet_subsys(&ipv6_proc_ops);
 317 }

/* [<][>][^][v][top][bottom][index][help] */