18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * INET An implementation of the TCP/IP protocol suite for the LINUX 48c2ecf20Sopenharmony_ci * operating system. INET is implemented using the BSD Socket 58c2ecf20Sopenharmony_ci * interface as the means of communication with the user level. 68c2ecf20Sopenharmony_ci * 78c2ecf20Sopenharmony_ci * This file implements the various access functions for the 88c2ecf20Sopenharmony_ci * PROC file system. This is very similar to the IPv4 version, 98c2ecf20Sopenharmony_ci * except it reports the sockets in the INET6 address family. 108c2ecf20Sopenharmony_ci * 118c2ecf20Sopenharmony_ci * Authors: David S. Miller (davem@caip.rutgers.edu) 128c2ecf20Sopenharmony_ci * YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org> 138c2ecf20Sopenharmony_ci */ 148c2ecf20Sopenharmony_ci#include <linux/socket.h> 158c2ecf20Sopenharmony_ci#include <linux/net.h> 168c2ecf20Sopenharmony_ci#include <linux/ipv6.h> 178c2ecf20Sopenharmony_ci#include <linux/proc_fs.h> 188c2ecf20Sopenharmony_ci#include <linux/seq_file.h> 198c2ecf20Sopenharmony_ci#include <linux/stddef.h> 208c2ecf20Sopenharmony_ci#include <linux/export.h> 218c2ecf20Sopenharmony_ci#include <net/net_namespace.h> 228c2ecf20Sopenharmony_ci#include <net/ip.h> 238c2ecf20Sopenharmony_ci#include <net/sock.h> 248c2ecf20Sopenharmony_ci#include <net/tcp.h> 258c2ecf20Sopenharmony_ci#include <net/udp.h> 268c2ecf20Sopenharmony_ci#include <net/transp_v6.h> 278c2ecf20Sopenharmony_ci#include <net/ipv6.h> 288c2ecf20Sopenharmony_ci 298c2ecf20Sopenharmony_ci#define MAX4(a, b, c, d) \ 308c2ecf20Sopenharmony_ci max_t(u32, max_t(u32, a, b), max_t(u32, c, d)) 318c2ecf20Sopenharmony_ci#define SNMP_MIB_MAX MAX4(UDP_MIB_MAX, TCP_MIB_MAX, \ 328c2ecf20Sopenharmony_ci IPSTATS_MIB_MAX, ICMP_MIB_MAX) 338c2ecf20Sopenharmony_ci 348c2ecf20Sopenharmony_cistatic int sockstat6_seq_show(struct seq_file *seq, void *v) 358c2ecf20Sopenharmony_ci{ 368c2ecf20Sopenharmony_ci struct net *net = seq->private; 378c2ecf20Sopenharmony_ci 388c2ecf20Sopenharmony_ci seq_printf(seq, "TCP6: inuse %d\n", 398c2ecf20Sopenharmony_ci sock_prot_inuse_get(net, &tcpv6_prot)); 408c2ecf20Sopenharmony_ci seq_printf(seq, "UDP6: inuse %d\n", 418c2ecf20Sopenharmony_ci sock_prot_inuse_get(net, &udpv6_prot)); 428c2ecf20Sopenharmony_ci seq_printf(seq, "UDPLITE6: inuse %d\n", 438c2ecf20Sopenharmony_ci sock_prot_inuse_get(net, &udplitev6_prot)); 448c2ecf20Sopenharmony_ci seq_printf(seq, "RAW6: inuse %d\n", 458c2ecf20Sopenharmony_ci sock_prot_inuse_get(net, &rawv6_prot)); 468c2ecf20Sopenharmony_ci seq_printf(seq, "FRAG6: inuse %u memory %lu\n", 478c2ecf20Sopenharmony_ci atomic_read(&net->ipv6.fqdir->rhashtable.nelems), 488c2ecf20Sopenharmony_ci frag_mem_limit(net->ipv6.fqdir)); 498c2ecf20Sopenharmony_ci return 0; 508c2ecf20Sopenharmony_ci} 518c2ecf20Sopenharmony_ci 528c2ecf20Sopenharmony_cistatic const struct snmp_mib snmp6_ipstats_list[] = { 538c2ecf20Sopenharmony_ci/* ipv6 mib according to RFC 2465 */ 548c2ecf20Sopenharmony_ci SNMP_MIB_ITEM("Ip6InReceives", IPSTATS_MIB_INPKTS), 558c2ecf20Sopenharmony_ci SNMP_MIB_ITEM("Ip6InHdrErrors", IPSTATS_MIB_INHDRERRORS), 568c2ecf20Sopenharmony_ci SNMP_MIB_ITEM("Ip6InTooBigErrors", IPSTATS_MIB_INTOOBIGERRORS), 578c2ecf20Sopenharmony_ci SNMP_MIB_ITEM("Ip6InNoRoutes", IPSTATS_MIB_INNOROUTES), 588c2ecf20Sopenharmony_ci SNMP_MIB_ITEM("Ip6InAddrErrors", IPSTATS_MIB_INADDRERRORS), 598c2ecf20Sopenharmony_ci SNMP_MIB_ITEM("Ip6InUnknownProtos", IPSTATS_MIB_INUNKNOWNPROTOS), 608c2ecf20Sopenharmony_ci SNMP_MIB_ITEM("Ip6InTruncatedPkts", IPSTATS_MIB_INTRUNCATEDPKTS), 618c2ecf20Sopenharmony_ci SNMP_MIB_ITEM("Ip6InDiscards", IPSTATS_MIB_INDISCARDS), 628c2ecf20Sopenharmony_ci SNMP_MIB_ITEM("Ip6InDelivers", IPSTATS_MIB_INDELIVERS), 638c2ecf20Sopenharmony_ci SNMP_MIB_ITEM("Ip6OutForwDatagrams", IPSTATS_MIB_OUTFORWDATAGRAMS), 648c2ecf20Sopenharmony_ci SNMP_MIB_ITEM("Ip6OutRequests", IPSTATS_MIB_OUTPKTS), 658c2ecf20Sopenharmony_ci SNMP_MIB_ITEM("Ip6OutDiscards", IPSTATS_MIB_OUTDISCARDS), 668c2ecf20Sopenharmony_ci SNMP_MIB_ITEM("Ip6OutNoRoutes", IPSTATS_MIB_OUTNOROUTES), 678c2ecf20Sopenharmony_ci SNMP_MIB_ITEM("Ip6ReasmTimeout", IPSTATS_MIB_REASMTIMEOUT), 688c2ecf20Sopenharmony_ci SNMP_MIB_ITEM("Ip6ReasmReqds", IPSTATS_MIB_REASMREQDS), 698c2ecf20Sopenharmony_ci SNMP_MIB_ITEM("Ip6ReasmOKs", IPSTATS_MIB_REASMOKS), 708c2ecf20Sopenharmony_ci SNMP_MIB_ITEM("Ip6ReasmFails", IPSTATS_MIB_REASMFAILS), 718c2ecf20Sopenharmony_ci SNMP_MIB_ITEM("Ip6FragOKs", IPSTATS_MIB_FRAGOKS), 728c2ecf20Sopenharmony_ci SNMP_MIB_ITEM("Ip6FragFails", IPSTATS_MIB_FRAGFAILS), 738c2ecf20Sopenharmony_ci SNMP_MIB_ITEM("Ip6FragCreates", IPSTATS_MIB_FRAGCREATES), 748c2ecf20Sopenharmony_ci SNMP_MIB_ITEM("Ip6InMcastPkts", IPSTATS_MIB_INMCASTPKTS), 758c2ecf20Sopenharmony_ci SNMP_MIB_ITEM("Ip6OutMcastPkts", IPSTATS_MIB_OUTMCASTPKTS), 768c2ecf20Sopenharmony_ci SNMP_MIB_ITEM("Ip6InOctets", IPSTATS_MIB_INOCTETS), 778c2ecf20Sopenharmony_ci SNMP_MIB_ITEM("Ip6OutOctets", IPSTATS_MIB_OUTOCTETS), 788c2ecf20Sopenharmony_ci SNMP_MIB_ITEM("Ip6InMcastOctets", IPSTATS_MIB_INMCASTOCTETS), 798c2ecf20Sopenharmony_ci SNMP_MIB_ITEM("Ip6OutMcastOctets", IPSTATS_MIB_OUTMCASTOCTETS), 808c2ecf20Sopenharmony_ci SNMP_MIB_ITEM("Ip6InBcastOctets", IPSTATS_MIB_INBCASTOCTETS), 818c2ecf20Sopenharmony_ci SNMP_MIB_ITEM("Ip6OutBcastOctets", IPSTATS_MIB_OUTBCASTOCTETS), 828c2ecf20Sopenharmony_ci /* IPSTATS_MIB_CSUMERRORS is not relevant in IPv6 (no checksum) */ 838c2ecf20Sopenharmony_ci SNMP_MIB_ITEM("Ip6InNoECTPkts", IPSTATS_MIB_NOECTPKTS), 848c2ecf20Sopenharmony_ci SNMP_MIB_ITEM("Ip6InECT1Pkts", IPSTATS_MIB_ECT1PKTS), 858c2ecf20Sopenharmony_ci SNMP_MIB_ITEM("Ip6InECT0Pkts", IPSTATS_MIB_ECT0PKTS), 868c2ecf20Sopenharmony_ci SNMP_MIB_ITEM("Ip6InCEPkts", IPSTATS_MIB_CEPKTS), 878c2ecf20Sopenharmony_ci SNMP_MIB_SENTINEL 888c2ecf20Sopenharmony_ci}; 898c2ecf20Sopenharmony_ci 908c2ecf20Sopenharmony_cistatic const struct snmp_mib snmp6_icmp6_list[] = { 918c2ecf20Sopenharmony_ci/* icmpv6 mib according to RFC 2466 */ 928c2ecf20Sopenharmony_ci SNMP_MIB_ITEM("Icmp6InMsgs", ICMP6_MIB_INMSGS), 938c2ecf20Sopenharmony_ci SNMP_MIB_ITEM("Icmp6InErrors", ICMP6_MIB_INERRORS), 948c2ecf20Sopenharmony_ci SNMP_MIB_ITEM("Icmp6OutMsgs", ICMP6_MIB_OUTMSGS), 958c2ecf20Sopenharmony_ci SNMP_MIB_ITEM("Icmp6OutErrors", ICMP6_MIB_OUTERRORS), 968c2ecf20Sopenharmony_ci SNMP_MIB_ITEM("Icmp6InCsumErrors", ICMP6_MIB_CSUMERRORS), 978c2ecf20Sopenharmony_ci SNMP_MIB_SENTINEL 988c2ecf20Sopenharmony_ci}; 998c2ecf20Sopenharmony_ci 1008c2ecf20Sopenharmony_ci/* RFC 4293 v6 ICMPMsgStatsTable; named items for RFC 2466 compatibility */ 1018c2ecf20Sopenharmony_cistatic const char *const icmp6type2name[256] = { 1028c2ecf20Sopenharmony_ci [ICMPV6_DEST_UNREACH] = "DestUnreachs", 1038c2ecf20Sopenharmony_ci [ICMPV6_PKT_TOOBIG] = "PktTooBigs", 1048c2ecf20Sopenharmony_ci [ICMPV6_TIME_EXCEED] = "TimeExcds", 1058c2ecf20Sopenharmony_ci [ICMPV6_PARAMPROB] = "ParmProblems", 1068c2ecf20Sopenharmony_ci [ICMPV6_ECHO_REQUEST] = "Echos", 1078c2ecf20Sopenharmony_ci [ICMPV6_ECHO_REPLY] = "EchoReplies", 1088c2ecf20Sopenharmony_ci [ICMPV6_MGM_QUERY] = "GroupMembQueries", 1098c2ecf20Sopenharmony_ci [ICMPV6_MGM_REPORT] = "GroupMembResponses", 1108c2ecf20Sopenharmony_ci [ICMPV6_MGM_REDUCTION] = "GroupMembReductions", 1118c2ecf20Sopenharmony_ci [ICMPV6_MLD2_REPORT] = "MLDv2Reports", 1128c2ecf20Sopenharmony_ci [NDISC_ROUTER_ADVERTISEMENT] = "RouterAdvertisements", 1138c2ecf20Sopenharmony_ci [NDISC_ROUTER_SOLICITATION] = "RouterSolicits", 1148c2ecf20Sopenharmony_ci [NDISC_NEIGHBOUR_ADVERTISEMENT] = "NeighborAdvertisements", 1158c2ecf20Sopenharmony_ci [NDISC_NEIGHBOUR_SOLICITATION] = "NeighborSolicits", 1168c2ecf20Sopenharmony_ci [NDISC_REDIRECT] = "Redirects", 1178c2ecf20Sopenharmony_ci}; 1188c2ecf20Sopenharmony_ci 1198c2ecf20Sopenharmony_ci 1208c2ecf20Sopenharmony_cistatic const struct snmp_mib snmp6_udp6_list[] = { 1218c2ecf20Sopenharmony_ci SNMP_MIB_ITEM("Udp6InDatagrams", UDP_MIB_INDATAGRAMS), 1228c2ecf20Sopenharmony_ci SNMP_MIB_ITEM("Udp6NoPorts", UDP_MIB_NOPORTS), 1238c2ecf20Sopenharmony_ci SNMP_MIB_ITEM("Udp6InErrors", UDP_MIB_INERRORS), 1248c2ecf20Sopenharmony_ci SNMP_MIB_ITEM("Udp6OutDatagrams", UDP_MIB_OUTDATAGRAMS), 1258c2ecf20Sopenharmony_ci SNMP_MIB_ITEM("Udp6RcvbufErrors", UDP_MIB_RCVBUFERRORS), 1268c2ecf20Sopenharmony_ci SNMP_MIB_ITEM("Udp6SndbufErrors", UDP_MIB_SNDBUFERRORS), 1278c2ecf20Sopenharmony_ci SNMP_MIB_ITEM("Udp6InCsumErrors", UDP_MIB_CSUMERRORS), 1288c2ecf20Sopenharmony_ci SNMP_MIB_ITEM("Udp6IgnoredMulti", UDP_MIB_IGNOREDMULTI), 1298c2ecf20Sopenharmony_ci SNMP_MIB_SENTINEL 1308c2ecf20Sopenharmony_ci}; 1318c2ecf20Sopenharmony_ci 1328c2ecf20Sopenharmony_cistatic const struct snmp_mib snmp6_udplite6_list[] = { 1338c2ecf20Sopenharmony_ci SNMP_MIB_ITEM("UdpLite6InDatagrams", UDP_MIB_INDATAGRAMS), 1348c2ecf20Sopenharmony_ci SNMP_MIB_ITEM("UdpLite6NoPorts", UDP_MIB_NOPORTS), 1358c2ecf20Sopenharmony_ci SNMP_MIB_ITEM("UdpLite6InErrors", UDP_MIB_INERRORS), 1368c2ecf20Sopenharmony_ci SNMP_MIB_ITEM("UdpLite6OutDatagrams", UDP_MIB_OUTDATAGRAMS), 1378c2ecf20Sopenharmony_ci SNMP_MIB_ITEM("UdpLite6RcvbufErrors", UDP_MIB_RCVBUFERRORS), 1388c2ecf20Sopenharmony_ci SNMP_MIB_ITEM("UdpLite6SndbufErrors", UDP_MIB_SNDBUFERRORS), 1398c2ecf20Sopenharmony_ci SNMP_MIB_ITEM("UdpLite6InCsumErrors", UDP_MIB_CSUMERRORS), 1408c2ecf20Sopenharmony_ci SNMP_MIB_SENTINEL 1418c2ecf20Sopenharmony_ci}; 1428c2ecf20Sopenharmony_ci 1438c2ecf20Sopenharmony_cistatic void snmp6_seq_show_icmpv6msg(struct seq_file *seq, atomic_long_t *smib) 1448c2ecf20Sopenharmony_ci{ 1458c2ecf20Sopenharmony_ci char name[32]; 1468c2ecf20Sopenharmony_ci int i; 1478c2ecf20Sopenharmony_ci 1488c2ecf20Sopenharmony_ci /* print by name -- deprecated items */ 1498c2ecf20Sopenharmony_ci for (i = 0; i < ICMP6MSG_MIB_MAX; i++) { 1508c2ecf20Sopenharmony_ci int icmptype; 1518c2ecf20Sopenharmony_ci const char *p; 1528c2ecf20Sopenharmony_ci 1538c2ecf20Sopenharmony_ci icmptype = i & 0xff; 1548c2ecf20Sopenharmony_ci p = icmp6type2name[icmptype]; 1558c2ecf20Sopenharmony_ci if (!p) /* don't print un-named types here */ 1568c2ecf20Sopenharmony_ci continue; 1578c2ecf20Sopenharmony_ci snprintf(name, sizeof(name), "Icmp6%s%s", 1588c2ecf20Sopenharmony_ci i & 0x100 ? "Out" : "In", p); 1598c2ecf20Sopenharmony_ci seq_printf(seq, "%-32s\t%lu\n", name, 1608c2ecf20Sopenharmony_ci atomic_long_read(smib + i)); 1618c2ecf20Sopenharmony_ci } 1628c2ecf20Sopenharmony_ci 1638c2ecf20Sopenharmony_ci /* print by number (nonzero only) - ICMPMsgStat format */ 1648c2ecf20Sopenharmony_ci for (i = 0; i < ICMP6MSG_MIB_MAX; i++) { 1658c2ecf20Sopenharmony_ci unsigned long val; 1668c2ecf20Sopenharmony_ci 1678c2ecf20Sopenharmony_ci val = atomic_long_read(smib + i); 1688c2ecf20Sopenharmony_ci if (!val) 1698c2ecf20Sopenharmony_ci continue; 1708c2ecf20Sopenharmony_ci snprintf(name, sizeof(name), "Icmp6%sType%u", 1718c2ecf20Sopenharmony_ci i & 0x100 ? "Out" : "In", i & 0xff); 1728c2ecf20Sopenharmony_ci seq_printf(seq, "%-32s\t%lu\n", name, val); 1738c2ecf20Sopenharmony_ci } 1748c2ecf20Sopenharmony_ci} 1758c2ecf20Sopenharmony_ci 1768c2ecf20Sopenharmony_ci/* can be called either with percpu mib (pcpumib != NULL), 1778c2ecf20Sopenharmony_ci * or shared one (smib != NULL) 1788c2ecf20Sopenharmony_ci */ 1798c2ecf20Sopenharmony_cistatic void snmp6_seq_show_item(struct seq_file *seq, void __percpu *pcpumib, 1808c2ecf20Sopenharmony_ci atomic_long_t *smib, 1818c2ecf20Sopenharmony_ci const struct snmp_mib *itemlist) 1828c2ecf20Sopenharmony_ci{ 1838c2ecf20Sopenharmony_ci unsigned long buff[SNMP_MIB_MAX]; 1848c2ecf20Sopenharmony_ci int i; 1858c2ecf20Sopenharmony_ci 1868c2ecf20Sopenharmony_ci if (pcpumib) { 1878c2ecf20Sopenharmony_ci memset(buff, 0, sizeof(unsigned long) * SNMP_MIB_MAX); 1888c2ecf20Sopenharmony_ci 1898c2ecf20Sopenharmony_ci snmp_get_cpu_field_batch(buff, itemlist, pcpumib); 1908c2ecf20Sopenharmony_ci for (i = 0; itemlist[i].name; i++) 1918c2ecf20Sopenharmony_ci seq_printf(seq, "%-32s\t%lu\n", 1928c2ecf20Sopenharmony_ci itemlist[i].name, buff[i]); 1938c2ecf20Sopenharmony_ci } else { 1948c2ecf20Sopenharmony_ci for (i = 0; itemlist[i].name; i++) 1958c2ecf20Sopenharmony_ci seq_printf(seq, "%-32s\t%lu\n", itemlist[i].name, 1968c2ecf20Sopenharmony_ci atomic_long_read(smib + itemlist[i].entry)); 1978c2ecf20Sopenharmony_ci } 1988c2ecf20Sopenharmony_ci} 1998c2ecf20Sopenharmony_ci 2008c2ecf20Sopenharmony_cistatic void snmp6_seq_show_item64(struct seq_file *seq, void __percpu *mib, 2018c2ecf20Sopenharmony_ci const struct snmp_mib *itemlist, size_t syncpoff) 2028c2ecf20Sopenharmony_ci{ 2038c2ecf20Sopenharmony_ci u64 buff64[SNMP_MIB_MAX]; 2048c2ecf20Sopenharmony_ci int i; 2058c2ecf20Sopenharmony_ci 2068c2ecf20Sopenharmony_ci memset(buff64, 0, sizeof(u64) * SNMP_MIB_MAX); 2078c2ecf20Sopenharmony_ci 2088c2ecf20Sopenharmony_ci snmp_get_cpu_field64_batch(buff64, itemlist, mib, syncpoff); 2098c2ecf20Sopenharmony_ci for (i = 0; itemlist[i].name; i++) 2108c2ecf20Sopenharmony_ci seq_printf(seq, "%-32s\t%llu\n", itemlist[i].name, buff64[i]); 2118c2ecf20Sopenharmony_ci} 2128c2ecf20Sopenharmony_ci 2138c2ecf20Sopenharmony_cistatic int snmp6_seq_show(struct seq_file *seq, void *v) 2148c2ecf20Sopenharmony_ci{ 2158c2ecf20Sopenharmony_ci struct net *net = (struct net *)seq->private; 2168c2ecf20Sopenharmony_ci 2178c2ecf20Sopenharmony_ci snmp6_seq_show_item64(seq, net->mib.ipv6_statistics, 2188c2ecf20Sopenharmony_ci snmp6_ipstats_list, offsetof(struct ipstats_mib, syncp)); 2198c2ecf20Sopenharmony_ci snmp6_seq_show_item(seq, net->mib.icmpv6_statistics, 2208c2ecf20Sopenharmony_ci NULL, snmp6_icmp6_list); 2218c2ecf20Sopenharmony_ci snmp6_seq_show_icmpv6msg(seq, net->mib.icmpv6msg_statistics->mibs); 2228c2ecf20Sopenharmony_ci snmp6_seq_show_item(seq, net->mib.udp_stats_in6, 2238c2ecf20Sopenharmony_ci NULL, snmp6_udp6_list); 2248c2ecf20Sopenharmony_ci snmp6_seq_show_item(seq, net->mib.udplite_stats_in6, 2258c2ecf20Sopenharmony_ci NULL, snmp6_udplite6_list); 2268c2ecf20Sopenharmony_ci return 0; 2278c2ecf20Sopenharmony_ci} 2288c2ecf20Sopenharmony_ci 2298c2ecf20Sopenharmony_cistatic int snmp6_dev_seq_show(struct seq_file *seq, void *v) 2308c2ecf20Sopenharmony_ci{ 2318c2ecf20Sopenharmony_ci struct inet6_dev *idev = (struct inet6_dev *)seq->private; 2328c2ecf20Sopenharmony_ci 2338c2ecf20Sopenharmony_ci seq_printf(seq, "%-32s\t%u\n", "ifIndex", idev->dev->ifindex); 2348c2ecf20Sopenharmony_ci snmp6_seq_show_item64(seq, idev->stats.ipv6, 2358c2ecf20Sopenharmony_ci snmp6_ipstats_list, offsetof(struct ipstats_mib, syncp)); 2368c2ecf20Sopenharmony_ci snmp6_seq_show_item(seq, NULL, idev->stats.icmpv6dev->mibs, 2378c2ecf20Sopenharmony_ci snmp6_icmp6_list); 2388c2ecf20Sopenharmony_ci snmp6_seq_show_icmpv6msg(seq, idev->stats.icmpv6msgdev->mibs); 2398c2ecf20Sopenharmony_ci return 0; 2408c2ecf20Sopenharmony_ci} 2418c2ecf20Sopenharmony_ci 2428c2ecf20Sopenharmony_ciint snmp6_register_dev(struct inet6_dev *idev) 2438c2ecf20Sopenharmony_ci{ 2448c2ecf20Sopenharmony_ci struct proc_dir_entry *p; 2458c2ecf20Sopenharmony_ci struct net *net; 2468c2ecf20Sopenharmony_ci 2478c2ecf20Sopenharmony_ci if (!idev || !idev->dev) 2488c2ecf20Sopenharmony_ci return -EINVAL; 2498c2ecf20Sopenharmony_ci 2508c2ecf20Sopenharmony_ci net = dev_net(idev->dev); 2518c2ecf20Sopenharmony_ci if (!net->mib.proc_net_devsnmp6) 2528c2ecf20Sopenharmony_ci return -ENOENT; 2538c2ecf20Sopenharmony_ci 2548c2ecf20Sopenharmony_ci p = proc_create_single_data(idev->dev->name, 0444, 2558c2ecf20Sopenharmony_ci net->mib.proc_net_devsnmp6, snmp6_dev_seq_show, idev); 2568c2ecf20Sopenharmony_ci if (!p) 2578c2ecf20Sopenharmony_ci return -ENOMEM; 2588c2ecf20Sopenharmony_ci 2598c2ecf20Sopenharmony_ci idev->stats.proc_dir_entry = p; 2608c2ecf20Sopenharmony_ci return 0; 2618c2ecf20Sopenharmony_ci} 2628c2ecf20Sopenharmony_ci 2638c2ecf20Sopenharmony_ciint snmp6_unregister_dev(struct inet6_dev *idev) 2648c2ecf20Sopenharmony_ci{ 2658c2ecf20Sopenharmony_ci struct net *net = dev_net(idev->dev); 2668c2ecf20Sopenharmony_ci if (!net->mib.proc_net_devsnmp6) 2678c2ecf20Sopenharmony_ci return -ENOENT; 2688c2ecf20Sopenharmony_ci if (!idev->stats.proc_dir_entry) 2698c2ecf20Sopenharmony_ci return -EINVAL; 2708c2ecf20Sopenharmony_ci proc_remove(idev->stats.proc_dir_entry); 2718c2ecf20Sopenharmony_ci idev->stats.proc_dir_entry = NULL; 2728c2ecf20Sopenharmony_ci return 0; 2738c2ecf20Sopenharmony_ci} 2748c2ecf20Sopenharmony_ci 2758c2ecf20Sopenharmony_cistatic int __net_init ipv6_proc_init_net(struct net *net) 2768c2ecf20Sopenharmony_ci{ 2778c2ecf20Sopenharmony_ci if (!proc_create_net_single("sockstat6", 0444, net->proc_net, 2788c2ecf20Sopenharmony_ci sockstat6_seq_show, NULL)) 2798c2ecf20Sopenharmony_ci return -ENOMEM; 2808c2ecf20Sopenharmony_ci 2818c2ecf20Sopenharmony_ci if (!proc_create_net_single("snmp6", 0444, net->proc_net, 2828c2ecf20Sopenharmony_ci snmp6_seq_show, NULL)) 2838c2ecf20Sopenharmony_ci goto proc_snmp6_fail; 2848c2ecf20Sopenharmony_ci 2858c2ecf20Sopenharmony_ci net->mib.proc_net_devsnmp6 = proc_mkdir("dev_snmp6", net->proc_net); 2868c2ecf20Sopenharmony_ci if (!net->mib.proc_net_devsnmp6) 2878c2ecf20Sopenharmony_ci goto proc_dev_snmp6_fail; 2888c2ecf20Sopenharmony_ci return 0; 2898c2ecf20Sopenharmony_ci 2908c2ecf20Sopenharmony_ciproc_dev_snmp6_fail: 2918c2ecf20Sopenharmony_ci remove_proc_entry("snmp6", net->proc_net); 2928c2ecf20Sopenharmony_ciproc_snmp6_fail: 2938c2ecf20Sopenharmony_ci remove_proc_entry("sockstat6", net->proc_net); 2948c2ecf20Sopenharmony_ci return -ENOMEM; 2958c2ecf20Sopenharmony_ci} 2968c2ecf20Sopenharmony_ci 2978c2ecf20Sopenharmony_cistatic void __net_exit ipv6_proc_exit_net(struct net *net) 2988c2ecf20Sopenharmony_ci{ 2998c2ecf20Sopenharmony_ci remove_proc_entry("sockstat6", net->proc_net); 3008c2ecf20Sopenharmony_ci remove_proc_entry("dev_snmp6", net->proc_net); 3018c2ecf20Sopenharmony_ci remove_proc_entry("snmp6", net->proc_net); 3028c2ecf20Sopenharmony_ci} 3038c2ecf20Sopenharmony_ci 3048c2ecf20Sopenharmony_cistatic struct pernet_operations ipv6_proc_ops = { 3058c2ecf20Sopenharmony_ci .init = ipv6_proc_init_net, 3068c2ecf20Sopenharmony_ci .exit = ipv6_proc_exit_net, 3078c2ecf20Sopenharmony_ci}; 3088c2ecf20Sopenharmony_ci 3098c2ecf20Sopenharmony_ciint __init ipv6_misc_proc_init(void) 3108c2ecf20Sopenharmony_ci{ 3118c2ecf20Sopenharmony_ci return register_pernet_subsys(&ipv6_proc_ops); 3128c2ecf20Sopenharmony_ci} 3138c2ecf20Sopenharmony_ci 3148c2ecf20Sopenharmony_civoid ipv6_misc_proc_exit(void) 3158c2ecf20Sopenharmony_ci{ 3168c2ecf20Sopenharmony_ci unregister_pernet_subsys(&ipv6_proc_ops); 3178c2ecf20Sopenharmony_ci} 318