2005-04-16 15:20:36 -07:00
/*
* INET An implementation of the TCP / IP protocol suite for the LINUX
* operating system . INET is implemented using the BSD Socket
* interface as the means of communication with the user level .
*
* This file implements the various access functions for the
* PROC file system . This is very similar to the IPv4 version ,
* except it reports the sockets in the INET6 address family .
*
* Authors : David S . Miller ( davem @ caip . rutgers . edu )
2014-08-24 21:53:10 +01:00
* YOSHIFUJI Hideaki < yoshfuji @ linux - ipv6 . org >
2005-04-16 15:20:36 -07:00
*
* This program is free software ; you can redistribute it and / or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation ; either version
* 2 of the License , or ( at your option ) any later version .
*/
# include <linux/socket.h>
# include <linux/net.h>
# include <linux/ipv6.h>
# include <linux/proc_fs.h>
# include <linux/seq_file.h>
# include <linux/stddef.h>
2011-07-15 11:47:34 -04:00
# include <linux/export.h>
2007-09-12 12:01:34 +02:00
# include <net/net_namespace.h>
2007-04-24 21:54:09 -07:00
# include <net/ip.h>
2005-04-16 15:20:36 -07:00
# include <net/sock.h>
# include <net/tcp.h>
2007-12-11 11:30:32 -08:00
# include <net/udp.h>
2005-04-16 15:20:36 -07:00
# include <net/transp_v6.h>
# include <net/ipv6.h>
2016-09-30 11:29:00 +08:00
# define MAX4(a, b, c, d) \
max_t ( u32 , max_t ( u32 , a , b ) , max_t ( u32 , c , d ) )
# define SNMP_MIB_MAX MAX4(UDP_MIB_MAX, TCP_MIB_MAX, \
IPSTATS_MIB_MAX , ICMP_MIB_MAX )
2005-04-16 15:20:36 -07:00
static int sockstat6_seq_show ( struct seq_file * seq , void * v )
{
2008-03-31 19:43:43 -07:00
struct net * net = seq - > private ;
2014-07-24 16:50:33 +02:00
unsigned int frag_mem = ip6_frag_mem ( net ) ;
2008-03-31 19:43:43 -07:00
2005-04-16 15:20:36 -07:00
seq_printf ( seq , " TCP6: inuse %d \n " ,
2008-03-31 19:43:43 -07:00
sock_prot_inuse_get ( net , & tcpv6_prot ) ) ;
2005-04-16 15:20:36 -07:00
seq_printf ( seq , " UDP6: inuse %d \n " ,
2008-03-31 19:43:43 -07:00
sock_prot_inuse_get ( net , & udpv6_prot ) ) ;
2006-11-27 11:10:57 -08:00
seq_printf ( seq , " UDPLITE6: inuse %d \n " ,
2008-03-31 19:43:43 -07:00
sock_prot_inuse_get ( net , & udplitev6_prot ) ) ;
2005-04-16 15:20:36 -07:00
seq_printf ( seq , " RAW6: inuse %d \n " ,
2008-03-31 19:43:43 -07:00
sock_prot_inuse_get ( net , & rawv6_prot ) ) ;
2014-07-24 16:50:33 +02:00
seq_printf ( seq , " FRAG6: inuse %u memory %u \n " , ! ! frag_mem , frag_mem ) ;
2005-04-16 15:20:36 -07:00
return 0 ;
}
2008-10-07 14:46:47 -07:00
static int sockstat6_seq_open ( struct inode * inode , struct file * file )
{
return single_open_net ( inode , file , sockstat6_seq_show ) ;
}
static const struct file_operations sockstat6_seq_fops = {
. owner = THIS_MODULE ,
. open = sockstat6_seq_open ,
. read = seq_read ,
. llseek = seq_lseek ,
. release = single_release_net ,
} ;
2010-01-22 10:17:26 +00:00
static const struct snmp_mib snmp6_ipstats_list [ ] = {
2005-04-16 15:20:36 -07:00
/* ipv6 mib according to RFC 2465 */
2009-04-27 02:45:02 -07:00
SNMP_MIB_ITEM ( " Ip6InReceives " , IPSTATS_MIB_INPKTS ) ,
2005-04-16 15:20:36 -07:00
SNMP_MIB_ITEM ( " Ip6InHdrErrors " , IPSTATS_MIB_INHDRERRORS ) ,
SNMP_MIB_ITEM ( " Ip6InTooBigErrors " , IPSTATS_MIB_INTOOBIGERRORS ) ,
SNMP_MIB_ITEM ( " Ip6InNoRoutes " , IPSTATS_MIB_INNOROUTES ) ,
SNMP_MIB_ITEM ( " Ip6InAddrErrors " , IPSTATS_MIB_INADDRERRORS ) ,
SNMP_MIB_ITEM ( " Ip6InUnknownProtos " , IPSTATS_MIB_INUNKNOWNPROTOS ) ,
SNMP_MIB_ITEM ( " Ip6InTruncatedPkts " , IPSTATS_MIB_INTRUNCATEDPKTS ) ,
SNMP_MIB_ITEM ( " Ip6InDiscards " , IPSTATS_MIB_INDISCARDS ) ,
SNMP_MIB_ITEM ( " Ip6InDelivers " , IPSTATS_MIB_INDELIVERS ) ,
SNMP_MIB_ITEM ( " Ip6OutForwDatagrams " , IPSTATS_MIB_OUTFORWDATAGRAMS ) ,
2009-04-27 02:45:02 -07:00
SNMP_MIB_ITEM ( " Ip6OutRequests " , IPSTATS_MIB_OUTPKTS ) ,
2005-04-16 15:20:36 -07:00
SNMP_MIB_ITEM ( " Ip6OutDiscards " , IPSTATS_MIB_OUTDISCARDS ) ,
SNMP_MIB_ITEM ( " Ip6OutNoRoutes " , IPSTATS_MIB_OUTNOROUTES ) ,
SNMP_MIB_ITEM ( " Ip6ReasmTimeout " , IPSTATS_MIB_REASMTIMEOUT ) ,
SNMP_MIB_ITEM ( " Ip6ReasmReqds " , IPSTATS_MIB_REASMREQDS ) ,
SNMP_MIB_ITEM ( " Ip6ReasmOKs " , IPSTATS_MIB_REASMOKS ) ,
SNMP_MIB_ITEM ( " Ip6ReasmFails " , IPSTATS_MIB_REASMFAILS ) ,
SNMP_MIB_ITEM ( " Ip6FragOKs " , IPSTATS_MIB_FRAGOKS ) ,
SNMP_MIB_ITEM ( " Ip6FragFails " , IPSTATS_MIB_FRAGFAILS ) ,
SNMP_MIB_ITEM ( " Ip6FragCreates " , IPSTATS_MIB_FRAGCREATES ) ,
SNMP_MIB_ITEM ( " Ip6InMcastPkts " , IPSTATS_MIB_INMCASTPKTS ) ,
SNMP_MIB_ITEM ( " Ip6OutMcastPkts " , IPSTATS_MIB_OUTMCASTPKTS ) ,
2009-04-27 02:45:02 -07:00
SNMP_MIB_ITEM ( " Ip6InOctets " , IPSTATS_MIB_INOCTETS ) ,
SNMP_MIB_ITEM ( " Ip6OutOctets " , IPSTATS_MIB_OUTOCTETS ) ,
SNMP_MIB_ITEM ( " Ip6InMcastOctets " , IPSTATS_MIB_INMCASTOCTETS ) ,
SNMP_MIB_ITEM ( " Ip6OutMcastOctets " , IPSTATS_MIB_OUTMCASTOCTETS ) ,
SNMP_MIB_ITEM ( " Ip6InBcastOctets " , IPSTATS_MIB_INBCASTOCTETS ) ,
SNMP_MIB_ITEM ( " Ip6OutBcastOctets " , IPSTATS_MIB_OUTBCASTOCTETS ) ,
2013-05-31 05:37:57 +00:00
/* IPSTATS_MIB_CSUMERRORS is not relevant in IPv6 (no checksum) */
2013-08-06 03:32:11 -07:00
SNMP_MIB_ITEM ( " Ip6InNoECTPkts " , IPSTATS_MIB_NOECTPKTS ) ,
SNMP_MIB_ITEM ( " Ip6InECT1Pkts " , IPSTATS_MIB_ECT1PKTS ) ,
SNMP_MIB_ITEM ( " Ip6InECT0Pkts " , IPSTATS_MIB_ECT0PKTS ) ,
SNMP_MIB_ITEM ( " Ip6InCEPkts " , IPSTATS_MIB_CEPKTS ) ,
2005-04-16 15:20:36 -07:00
SNMP_MIB_SENTINEL
} ;
2010-01-22 10:17:26 +00:00
static const struct snmp_mib snmp6_icmp6_list [ ] = {
2007-09-16 16:52:35 -07:00
/* icmpv6 mib according to RFC 2466 */
2005-04-16 15:20:36 -07:00
SNMP_MIB_ITEM ( " Icmp6InMsgs " , ICMP6_MIB_INMSGS ) ,
SNMP_MIB_ITEM ( " Icmp6InErrors " , ICMP6_MIB_INERRORS ) ,
SNMP_MIB_ITEM ( " Icmp6OutMsgs " , ICMP6_MIB_OUTMSGS ) ,
2010-04-03 15:09:04 -07:00
SNMP_MIB_ITEM ( " Icmp6OutErrors " , ICMP6_MIB_OUTERRORS ) ,
2013-04-29 08:39:56 +00:00
SNMP_MIB_ITEM ( " Icmp6InCsumErrors " , ICMP6_MIB_CSUMERRORS ) ,
2005-04-16 15:20:36 -07:00
SNMP_MIB_SENTINEL
} ;
2007-09-16 16:52:35 -07:00
/* RFC 4293 v6 ICMPMsgStatsTable; named items for RFC 2466 compatibility */
2009-08-05 10:42:58 -07:00
static const char * const icmp6type2name [ 256 ] = {
2007-09-16 16:52:35 -07:00
[ ICMPV6_DEST_UNREACH ] = " DestUnreachs " ,
[ ICMPV6_PKT_TOOBIG ] = " PktTooBigs " ,
[ ICMPV6_TIME_EXCEED ] = " TimeExcds " ,
[ ICMPV6_PARAMPROB ] = " ParmProblems " ,
2008-01-21 03:05:43 -08:00
[ ICMPV6_ECHO_REQUEST ] = " Echos " ,
2007-09-16 16:52:35 -07:00
[ ICMPV6_ECHO_REPLY ] = " EchoReplies " ,
[ ICMPV6_MGM_QUERY ] = " GroupMembQueries " ,
[ ICMPV6_MGM_REPORT ] = " GroupMembResponses " ,
[ ICMPV6_MGM_REDUCTION ] = " GroupMembReductions " ,
[ ICMPV6_MLD2_REPORT ] = " MLDv2Reports " ,
[ NDISC_ROUTER_ADVERTISEMENT ] = " RouterAdvertisements " ,
[ NDISC_ROUTER_SOLICITATION ] = " RouterSolicits " ,
[ NDISC_NEIGHBOUR_ADVERTISEMENT ] = " NeighborAdvertisements " ,
[ NDISC_NEIGHBOUR_SOLICITATION ] = " NeighborSolicits " ,
2008-01-21 03:05:43 -08:00
[ NDISC_REDIRECT ] = " Redirects " ,
2007-09-16 16:52:35 -07:00
} ;
2010-01-22 10:17:26 +00:00
static const struct snmp_mib snmp6_udp6_list [ ] = {
2005-04-16 15:20:36 -07:00
SNMP_MIB_ITEM ( " Udp6InDatagrams " , UDP_MIB_INDATAGRAMS ) ,
SNMP_MIB_ITEM ( " Udp6NoPorts " , UDP_MIB_NOPORTS ) ,
SNMP_MIB_ITEM ( " Udp6InErrors " , UDP_MIB_INERRORS ) ,
SNMP_MIB_ITEM ( " Udp6OutDatagrams " , UDP_MIB_OUTDATAGRAMS ) ,
2010-10-30 16:17:23 -07:00
SNMP_MIB_ITEM ( " Udp6RcvbufErrors " , UDP_MIB_RCVBUFERRORS ) ,
SNMP_MIB_ITEM ( " Udp6SndbufErrors " , UDP_MIB_SNDBUFERRORS ) ,
2013-04-29 08:39:56 +00:00
SNMP_MIB_ITEM ( " Udp6InCsumErrors " , UDP_MIB_CSUMERRORS ) ,
2014-11-06 10:37:54 -08:00
SNMP_MIB_ITEM ( " Udp6IgnoredMulti " , UDP_MIB_IGNOREDMULTI ) ,
2005-04-16 15:20:36 -07:00
SNMP_MIB_SENTINEL
} ;
2010-01-22 10:17:26 +00:00
static const struct snmp_mib snmp6_udplite6_list [ ] = {
2006-11-27 11:10:57 -08:00
SNMP_MIB_ITEM ( " UdpLite6InDatagrams " , UDP_MIB_INDATAGRAMS ) ,
SNMP_MIB_ITEM ( " UdpLite6NoPorts " , UDP_MIB_NOPORTS ) ,
SNMP_MIB_ITEM ( " UdpLite6InErrors " , UDP_MIB_INERRORS ) ,
SNMP_MIB_ITEM ( " UdpLite6OutDatagrams " , UDP_MIB_OUTDATAGRAMS ) ,
2010-10-30 16:17:23 -07:00
SNMP_MIB_ITEM ( " UdpLite6RcvbufErrors " , UDP_MIB_RCVBUFERRORS ) ,
SNMP_MIB_ITEM ( " UdpLite6SndbufErrors " , UDP_MIB_SNDBUFERRORS ) ,
2013-04-29 08:39:56 +00:00
SNMP_MIB_ITEM ( " UdpLite6InCsumErrors " , UDP_MIB_CSUMERRORS ) ,
2006-11-27 11:10:57 -08:00
SNMP_MIB_SENTINEL
} ;
2011-11-13 01:24:04 +00:00
static void snmp6_seq_show_icmpv6msg ( struct seq_file * seq , atomic_long_t * smib )
2007-09-16 16:52:35 -07:00
{
2008-11-20 04:20:10 -08:00
char name [ 32 ] ;
2007-09-16 16:52:35 -07:00
int i ;
/* print by name -- deprecated items */
for ( i = 0 ; i < ICMP6MSG_MIB_MAX ; i + + ) {
int icmptype ;
2009-08-05 10:42:58 -07:00
const char * p ;
2007-09-16 16:52:35 -07:00
icmptype = i & 0xff ;
p = icmp6type2name [ icmptype ] ;
if ( ! p ) /* don't print un-named types here */
continue ;
2008-11-20 04:20:10 -08:00
snprintf ( name , sizeof ( name ) , " Icmp6%s%s " ,
2007-09-16 16:52:35 -07:00
i & 0x100 ? " Out " : " In " , p ) ;
seq_printf ( seq , " %-32s \t %lu \n " , name ,
2011-11-13 01:24:04 +00:00
atomic_long_read ( smib + i ) ) ;
2007-09-16 16:52:35 -07:00
}
/* print by number (nonzero only) - ICMPMsgStat format */
for ( i = 0 ; i < ICMP6MSG_MIB_MAX ; i + + ) {
unsigned long val ;
2011-11-13 01:24:04 +00:00
val = atomic_long_read ( smib + i ) ;
2007-09-16 16:52:35 -07:00
if ( ! val )
continue ;
2008-11-20 04:20:10 -08:00
snprintf ( name , sizeof ( name ) , " Icmp6%sType%u " ,
2007-09-16 16:52:35 -07:00
i & 0x100 ? " Out " : " In " , i & 0xff ) ;
seq_printf ( seq , " %-32s \t %lu \n " , name , val ) ;
}
}
2011-05-19 01:14:23 +00:00
/* can be called either with percpu mib (pcpumib != NULL),
* or shared one ( smib ! = NULL )
*/
2014-05-12 16:52:02 -07:00
static void snmp6_seq_show_item ( struct seq_file * seq , void __percpu * pcpumib ,
2011-05-19 01:14:23 +00:00
atomic_long_t * smib ,
2010-01-22 10:17:26 +00:00
const struct snmp_mib * itemlist )
2005-04-16 15:20:36 -07:00
{
2016-09-30 11:29:00 +08:00
unsigned long buff [ SNMP_MIB_MAX ] ;
2005-04-16 15:20:36 -07:00
int i ;
2010-06-30 13:31:19 -07:00
2016-09-30 11:29:00 +08:00
if ( pcpumib ) {
memset ( buff , 0 , sizeof ( unsigned long ) * SNMP_MIB_MAX ) ;
snmp_get_cpu_field_batch ( buff , itemlist , pcpumib ) ;
for ( i = 0 ; itemlist [ i ] . name ; i + + )
seq_printf ( seq , " %-32s \t %lu \n " ,
itemlist [ i ] . name , buff [ i ] ) ;
} else {
for ( i = 0 ; itemlist [ i ] . name ; i + + )
seq_printf ( seq , " %-32s \t %lu \n " , itemlist [ i ] . name ,
atomic_long_read ( smib + itemlist [ i ] . entry ) ) ;
2011-05-19 01:14:23 +00:00
}
2005-04-16 15:20:36 -07:00
}
2014-05-05 15:55:55 -07:00
static void snmp6_seq_show_item64 ( struct seq_file * seq , void __percpu * mib ,
2010-06-30 13:31:19 -07:00
const struct snmp_mib * itemlist , size_t syncpoff )
{
2016-09-30 11:29:00 +08:00
u64 buff64 [ SNMP_MIB_MAX ] ;
2010-06-30 13:31:19 -07:00
int i ;
2016-09-30 11:29:00 +08:00
memset ( buff64 , 0 , sizeof ( unsigned long ) * SNMP_MIB_MAX ) ;
snmp_get_cpu_field64_batch ( buff64 , itemlist , mib , syncpoff ) ;
2010-06-30 13:31:19 -07:00
for ( i = 0 ; itemlist [ i ] . name ; i + + )
2016-09-30 11:29:00 +08:00
seq_printf ( seq , " %-32s \t %llu \n " , itemlist [ i ] . name , buff64 [ i ] ) ;
2010-06-30 13:31:19 -07:00
}
2005-04-16 15:20:36 -07:00
static int snmp6_seq_show ( struct seq_file * seq , void * v )
{
2008-10-07 14:47:37 -07:00
struct net * net = ( struct net * ) seq - > private ;
2014-05-05 15:55:55 -07:00
snmp6_seq_show_item64 ( seq , net - > mib . ipv6_statistics ,
2010-06-30 13:31:19 -07:00
snmp6_ipstats_list , offsetof ( struct ipstats_mib , syncp ) ) ;
2014-05-12 16:52:02 -07:00
snmp6_seq_show_item ( seq , net - > mib . icmpv6_statistics ,
2011-05-19 01:14:23 +00:00
NULL , snmp6_icmp6_list ) ;
2011-11-13 01:24:04 +00:00
snmp6_seq_show_icmpv6msg ( seq , net - > mib . icmpv6msg_statistics - > mibs ) ;
2014-05-12 16:52:02 -07:00
snmp6_seq_show_item ( seq , net - > mib . udp_stats_in6 ,
2011-05-19 01:14:23 +00:00
NULL , snmp6_udp6_list ) ;
2014-05-12 16:52:02 -07:00
snmp6_seq_show_item ( seq , net - > mib . udplite_stats_in6 ,
2011-05-19 01:14:23 +00:00
NULL , snmp6_udplite6_list ) ;
2005-04-16 15:20:36 -07:00
return 0 ;
}
static int snmp6_seq_open ( struct inode * inode , struct file * file )
{
2008-10-07 14:47:37 -07:00
return single_open_net ( inode , file , snmp6_seq_show ) ;
2005-04-16 15:20:36 -07:00
}
2007-02-12 00:55:35 -08:00
static const struct file_operations snmp6_seq_fops = {
2005-04-16 15:20:36 -07:00
. owner = THIS_MODULE ,
. open = snmp6_seq_open ,
. read = seq_read ,
. llseek = seq_lseek ,
2008-10-07 14:47:37 -07:00
. release = single_release_net ,
2005-04-16 15:20:36 -07:00
} ;
2008-10-07 14:47:12 -07:00
static int snmp6_dev_seq_show ( struct seq_file * seq , void * v )
{
struct inet6_dev * idev = ( struct inet6_dev * ) seq - > private ;
seq_printf ( seq , " %-32s \t %u \n " , " ifIndex " , idev - > dev - > ifindex ) ;
2014-05-05 15:55:55 -07:00
snmp6_seq_show_item64 ( seq , idev - > stats . ipv6 ,
2012-01-17 12:45:36 +00:00
snmp6_ipstats_list , offsetof ( struct ipstats_mib , syncp ) ) ;
2011-05-19 01:14:23 +00:00
snmp6_seq_show_item ( seq , NULL , idev - > stats . icmpv6dev - > mibs ,
2010-02-16 15:20:26 +00:00
snmp6_icmp6_list ) ;
2011-11-13 01:24:04 +00:00
snmp6_seq_show_icmpv6msg ( seq , idev - > stats . icmpv6msgdev - > mibs ) ;
2008-10-07 14:47:12 -07:00
return 0 ;
}
static int snmp6_dev_seq_open ( struct inode * inode , struct file * file )
{
2013-03-31 18:16:14 -04:00
return single_open ( file , snmp6_dev_seq_show , PDE_DATA ( inode ) ) ;
2008-10-07 14:47:12 -07:00
}
static const struct file_operations snmp6_dev_seq_fops = {
. owner = THIS_MODULE ,
. open = snmp6_dev_seq_open ,
. read = seq_read ,
. llseek = seq_lseek ,
. release = single_release ,
} ;
2005-04-16 15:20:36 -07:00
int snmp6_register_dev ( struct inet6_dev * idev )
{
struct proc_dir_entry * p ;
2008-10-07 14:45:55 -07:00
struct net * net ;
2005-04-16 15:20:36 -07:00
if ( ! idev | | ! idev - > dev )
return - EINVAL ;
2008-10-07 14:45:55 -07:00
net = dev_net ( idev - > dev ) ;
if ( ! net - > mib . proc_net_devsnmp6 )
2005-04-16 15:20:36 -07:00
return - ENOENT ;
2008-05-02 02:46:55 -07:00
p = proc_create_data ( idev - > dev - > name , S_IRUGO ,
2008-10-07 14:47:12 -07:00
net - > mib . proc_net_devsnmp6 ,
& snmp6_dev_seq_fops , idev ) ;
2005-04-16 15:20:36 -07:00
if ( ! p )
return - ENOMEM ;
idev - > stats . proc_dir_entry = p ;
return 0 ;
}
int snmp6_unregister_dev ( struct inet6_dev * idev )
{
2008-10-07 14:45:55 -07:00
struct net * net = dev_net ( idev - > dev ) ;
if ( ! net - > mib . proc_net_devsnmp6 )
2005-04-16 15:20:36 -07:00
return - ENOENT ;
2010-01-10 00:43:03 +00:00
if ( ! idev - > stats . proc_dir_entry )
2005-04-16 15:20:36 -07:00
return - EINVAL ;
2013-04-12 17:27:28 +01:00
proc_remove ( idev - > stats . proc_dir_entry ) ;
2007-04-28 21:16:39 -07:00
idev - > stats . proc_dir_entry = NULL ;
2005-04-16 15:20:36 -07:00
return 0 ;
}
2010-01-17 03:35:32 +00:00
static int __net_init ipv6_proc_init_net ( struct net * net )
2008-03-31 19:42:37 -07:00
{
2013-02-18 01:34:54 +00:00
if ( ! proc_create ( " sockstat6 " , S_IRUGO , net - > proc_net ,
& sockstat6_seq_fops ) )
2008-03-31 19:42:37 -07:00
return - ENOMEM ;
2008-10-07 14:46:18 -07:00
2013-02-18 01:34:54 +00:00
if ( ! proc_create ( " snmp6 " , S_IRUGO , net - > proc_net , & snmp6_seq_fops ) )
2008-10-07 14:46:18 -07:00
goto proc_snmp6_fail ;
net - > mib . proc_net_devsnmp6 = proc_mkdir ( " dev_snmp6 " , net - > proc_net ) ;
if ( ! net - > mib . proc_net_devsnmp6 )
goto proc_dev_snmp6_fail ;
2008-03-31 19:42:37 -07:00
return 0 ;
2008-10-07 14:46:18 -07:00
2012-08-12 22:31:58 +00:00
proc_dev_snmp6_fail :
2013-02-18 01:34:56 +00:00
remove_proc_entry ( " snmp6 " , net - > proc_net ) ;
2008-10-07 14:46:18 -07:00
proc_snmp6_fail :
2013-02-18 01:34:56 +00:00
remove_proc_entry ( " sockstat6 " , net - > proc_net ) ;
2008-10-07 14:46:18 -07:00
return - ENOMEM ;
2008-03-31 19:42:37 -07:00
}
2010-01-17 03:35:32 +00:00
static void __net_exit ipv6_proc_exit_net ( struct net * net )
2008-03-31 19:42:37 -07:00
{
2013-02-18 01:34:56 +00:00
remove_proc_entry ( " sockstat6 " , net - > proc_net ) ;
remove_proc_entry ( " dev_snmp6 " , net - > proc_net ) ;
remove_proc_entry ( " snmp6 " , net - > proc_net ) ;
2008-03-31 19:42:37 -07:00
}
static struct pernet_operations ipv6_proc_ops = {
. init = ipv6_proc_init_net ,
. exit = ipv6_proc_exit_net ,
} ;
2005-04-16 15:20:36 -07:00
int __init ipv6_misc_proc_init ( void )
{
2008-10-07 14:46:18 -07:00
return register_pernet_subsys ( & ipv6_proc_ops ) ;
2005-04-16 15:20:36 -07:00
}
void ipv6_misc_proc_exit ( void )
{
2008-03-31 19:42:37 -07:00
unregister_pernet_subsys ( & ipv6_proc_ops ) ;
2005-04-16 15:20:36 -07:00
}