blob: a1ca16d0f072aa0939b66b430e7ffe6343c7c1d6 [file] [log] [blame]
/*
* ipSystemStatsTable and ipIfStatsTable interface MIB architecture support
*
* $Id$
*/
#include <net-snmp/net-snmp-config.h>
#include <net-snmp/net-snmp-includes.h>
#include <net-snmp/agent/net-snmp-agent-includes.h>
#include <net-snmp/data_access/ipstats.h>
#include <net-snmp/data_access/systemstats.h>
#include "../ipSystemStatsTable/ipSystemStatsTable.h"
#if defined(NETSNMP_IFNET_NEEDS_KERNEL) && !defined(_KERNEL)
#define _KERNEL 1
#define _I_DEFINED_KERNEL
#endif
#if NETSNMP_IFNET_NEEDS_KERNEL_STRUCTURES
#define _KERNEL_STRUCTURES
#endif
#include <sys/types.h>
#include <dirent.h>
#include <ctype.h>
#include <sys/param.h>
#include <sys/sysctl.h>
#include <sys/protosw.h>
#include <net/if.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <netinet/ip_icmp.h>
#include <netinet/ip_var.h>
#if HAVE_NETINET6_IP6_VAR_H
#include <netinet6/ip6_var.h>
#endif
#ifndef freebsd7
#include <netinet6/in6_var.h>
#endif
#ifdef darwin
/* This struct is in netinet6/ip6_var.h which Apple for obscure reasons
* do not distribute as part of /usr/include :-(
*/
struct ip6stat {
u_quad_t ip6s_total; /* total packets received */
u_quad_t ip6s_tooshort; /* packet too short */
u_quad_t ip6s_toosmall; /* not enough data */
u_quad_t ip6s_fragments; /* fragments received */
u_quad_t ip6s_fragdropped; /* frags dropped(dups, out of space) */
u_quad_t ip6s_fragtimeout; /* fragments timed out */
u_quad_t ip6s_fragoverflow; /* fragments that exceeded limit */
u_quad_t ip6s_forward; /* packets forwarded */
u_quad_t ip6s_cantforward; /* packets rcvd for unreachable dest */
u_quad_t ip6s_redirectsent; /* packets forwarded on same net */
u_quad_t ip6s_delivered; /* datagrams delivered to upper level*/
u_quad_t ip6s_localout; /* total ip packets generated here */
u_quad_t ip6s_odropped; /* lost packets due to nobufs, etc. */
u_quad_t ip6s_reassembled; /* total packets reassembled ok */
u_quad_t ip6s_fragmented; /* datagrams sucessfully fragmented */
u_quad_t ip6s_ofragments; /* output fragments created */
u_quad_t ip6s_cantfrag; /* don't fragment flag was set, etc. */
u_quad_t ip6s_badoptions; /* error in option processing */
u_quad_t ip6s_noroute; /* packets discarded due to no route */
u_quad_t ip6s_badvers; /* ip6 version != 6 */
u_quad_t ip6s_rawout; /* total raw ip packets generated */
u_quad_t ip6s_badscope; /* scope error */
u_quad_t ip6s_notmember; /* don't join this multicast group */
u_quad_t ip6s_nxthist[256]; /* next header history */
u_quad_t ip6s_m1; /* one mbuf */
u_quad_t ip6s_m2m[32]; /* two or more mbuf */
u_quad_t ip6s_mext1; /* one ext mbuf */
u_quad_t ip6s_mext2m; /* two or more ext mbuf */
u_quad_t ip6s_exthdrtoolong; /* ext hdr are not continuous */
u_quad_t ip6s_nogif; /* no match gif found */
u_quad_t ip6s_toomanyhdr; /* discarded due to too many headers */
/*
* statistics for improvement of the source address selection
* algorithm:
* XXX: hardcoded 16 = # of ip6 multicast scope types + 1
*/
/* number of times that address selection fails */
u_quad_t ip6s_sources_none;
/* number of times that an address on the outgoing I/F is chosen */
u_quad_t ip6s_sources_sameif[16];
/* number of times that an address on a non-outgoing I/F is chosen */
u_quad_t ip6s_sources_otherif[16];
/*
* number of times that an address that has the same scope
* from the destination is chosen.
*/
u_quad_t ip6s_sources_samescope[16];
/*
* number of times that an address that has a different scope
* from the destination is chosen.
*/
u_quad_t ip6s_sources_otherscope[16];
/* number of times that an deprecated address is chosen */
u_quad_t ip6s_sources_deprecated[16];
u_quad_t ip6s_forward_cachehit;
u_quad_t ip6s_forward_cachemiss;
};
#endif /* darwin*/
static int _systemstats_v4(netsnmp_container* container, u_int load_flags);
#if defined (NETSNMP_ENABLE_IPV6)
static int _systemstats_v6(netsnmp_container* container, u_int load_flags);
#endif
static int ncpus;
void
netsnmp_access_systemstats_arch_init(void)
{
int ncpu_mib[] = { CTL_HW, HW_NCPU };
size_t siz = sizeof(ncpus);
if (sysctl(ncpu_mib, 2, &ncpus, &siz, NULL, 0) < 0) {
snmp_log_perror("hw.ncpu");
ncpus = 1;
}
}
/*
*
* @retval 0 success
* @retval -1 no container specified
* @retval -2 could not open file
* @retval -3 could not create entry (probably malloc)
* @retval -4 file format error
*/
int
netsnmp_access_systemstats_container_arch_load(netsnmp_container* container,
u_int load_flags)
{
int rc1;
#if defined (NETSNMP_ENABLE_IPV6)
int rc2;
#endif
if (NULL == container) {
snmp_log(LOG_ERR, "no container specified/found for access_systemstats_\n");
return -1;
}
/*
* load v4 and v6 stats. Even if one fails, try the other.
* If they have the same rc, return it. if the differ, return
* the smaller one. No log messages, since each individual function
* would have logged its own message.
*/
rc1 = _systemstats_v4(container, load_flags);
#if defined (NETSNMP_ENABLE_IPV6)
rc2 = _systemstats_v6(container, load_flags);
if ((rc1 == rc2) || (rc1 < rc2))
return rc1;
return rc2;
#else
return rc1;
#endif
}
/*
* Based on load_flags, load ipSystemStatsTable or ipIfStatsTable for ipv4 entries.
*/
#ifdef __NetBSD__
static int
_systemstats_v4(netsnmp_container* container, u_int load_flags)
{
netsnmp_systemstats_entry *entry = NULL;
uint64_t ipstat[IP_NSTATS];
size_t len = sizeof(ipstat);
if (sysctlbyname("net.inet.ip.stats", &ipstat, &len, NULL, 0) < 0) {
NETSNMP_LOGONCE((LOG_ERR, "Cannot sysctlbyname net.inet.ip.stats\n"));
return -2;
}
DEBUGMSGTL(("access:systemstats:container:arch", "load v4 (flags %x)\n",
load_flags));
netsnmp_assert(container != NULL); /* load function shoulda checked this */
if (load_flags & NETSNMP_ACCESS_SYSTEMSTATS_LOAD_IFTABLE) {
/* we do not support ipIfStatsTable for ipv4 */
return 0;
}
entry = netsnmp_access_systemstats_entry_create(1, 0,
"ipSystemStatsTable.ipv4");
if(NULL == entry) {
snmp_log(LOG_ERR, "systemstats_v4: cannot create entry\n");
netsnmp_access_systemstats_container_free(container,
NETSNMP_ACCESS_SYSTEMSTATS_FREE_NOFLAGS);
return -3;
}
/*
* OK - we've now got (or created) the data structure for
* this systemstats, including any "static" information.
* Now parse the rest of the line (i.e. starting from 'stats')
* to extract the relevant statistics, and populate
* data structure accordingly.
*/
entry->stats.HCInReceives.low = ipstat[IP_STAT_TOTAL] & 0xffffffff;
entry->stats.HCInReceives.high = ipstat[IP_STAT_TOTAL] >> 32;
entry->stats.InHdrErrors = ipstat[IP_STAT_BADSUM]
+ ipstat[IP_STAT_TOOSHORT] + ipstat[IP_STAT_TOOSMALL]
+ ipstat[IP_STAT_BADHLEN] + ipstat[IP_STAT_BADLEN];
entry->stats.InAddrErrors = ipstat[IP_STAT_CANTFORWARD];
entry->stats.HCOutForwDatagrams.low = ipstat[IP_STAT_FORWARD] & 0xffffffff;
entry->stats.HCOutForwDatagrams.high = ipstat[IP_STAT_FORWARD] >> 32;
entry->stats.InUnknownProtos = ipstat[IP_STAT_NOPROTO];
entry->stats.InDiscards = ipstat[IP_STAT_FRAGDROPPED];
entry->stats.HCInDelivers.low = ipstat[IP_STAT_DELIVERED] & 0xffffffff;
entry->stats.HCInDelivers.high = ipstat[IP_STAT_DELIVERED] >> 32;
entry->stats.HCOutRequests.low = ipstat[IP_STAT_LOCALOUT] & 0xffffffff;
entry->stats.HCOutRequests.high = ipstat[IP_STAT_LOCALOUT] >> 32;
entry->stats.HCOutDiscards.low = ipstat[IP_STAT_ODROPPED] & 0xffffffff;
entry->stats.HCOutDiscards.high = ipstat[IP_STAT_ODROPPED] >> 32;
entry->stats.HCOutNoRoutes.low = ipstat[IP_STAT_NOGIF] & 0xffffffff;
entry->stats.HCOutNoRoutes.high = ipstat[IP_STAT_NOGIF] >> 32;
/* entry->stats. = scan_vals[12]; / * ReasmTimeout */
entry->stats.ReasmReqds = ipstat[IP_STAT_FRAGMENTS];
entry->stats.ReasmOKs = ipstat[IP_STAT_REASSEMBLED];
entry->stats.ReasmFails = ipstat[IP_STAT_FRAGDROPPED]
+ ipstat[IP_STAT_FRAGTIMEOUT];
entry->stats.HCOutFragOKs.low = ipstat[IP_STAT_FRAGMENTS] & 0xffffffff;
entry->stats.HCOutFragOKs.high = ipstat[IP_STAT_FRAGMENTS] >> 32;
entry->stats.HCOutFragFails.low = ipstat[IP_STAT_CANTFRAG] & 0xffffffff;
entry->stats.HCOutFragFails.high = ipstat[IP_STAT_CANTFRAG] >> 32;
entry->stats.HCOutFragCreates.low = ipstat[IP_STAT_OFRAGMENTS] & 0xffffffff;
entry->stats.HCOutFragCreates.high = ipstat[IP_STAT_OFRAGMENTS] >> 32;
entry->stats.columnAvail[IPSYSTEMSTATSTABLE_HCINRECEIVES] = 1;
entry->stats.columnAvail[IPSYSTEMSTATSTABLE_INHDRERRORS] = 1;
entry->stats.columnAvail[IPSYSTEMSTATSTABLE_INADDRERRORS] = 1;
entry->stats.columnAvail[IPSYSTEMSTATSTABLE_HCOUTFORWDATAGRAMS] = 1;
entry->stats.columnAvail[IPSYSTEMSTATSTABLE_INUNKNOWNPROTOS] = 1;
entry->stats.columnAvail[IPSYSTEMSTATSTABLE_INDISCARDS] = 1;
entry->stats.columnAvail[IPSYSTEMSTATSTABLE_HCINDELIVERS] = 1;
entry->stats.columnAvail[IPSYSTEMSTATSTABLE_HCOUTREQUESTS] = 1;
entry->stats.columnAvail[IPSYSTEMSTATSTABLE_HCOUTDISCARDS] = 1;
entry->stats.columnAvail[IPSYSTEMSTATSTABLE_HCOUTNOROUTES] = 1;
entry->stats.columnAvail[IPSYSTEMSTATSTABLE_REASMREQDS] = 1;
entry->stats.columnAvail[IPSYSTEMSTATSTABLE_REASMOKS] = 1;
entry->stats.columnAvail[IPSYSTEMSTATSTABLE_REASMFAILS] = 1;
entry->stats.columnAvail[IPSYSTEMSTATSTABLE_HCOUTFRAGOKS] = 1;
entry->stats.columnAvail[IPSYSTEMSTATSTABLE_HCOUTFRAGFAILS] = 1;
entry->stats.columnAvail[IPSYSTEMSTATSTABLE_HCOUTFRAGCREATES] = 1;
entry->stats.columnAvail[IPSYSTEMSTATSTABLE_DISCONTINUITYTIME] = 1;
entry->stats.columnAvail[IPSYSTEMSTATSTABLE_REFRESHRATE] = 1;
/*
* add to container
*/
if (CONTAINER_INSERT(container, entry) < 0)
{
snmp_log(LOG_ERR, "error with systemstats_v4: insert into container failed.\n");
netsnmp_access_systemstats_entry_free(entry);
}
return 0;
}
#if defined (NETSNMP_ENABLE_IPV6)
static int
_systemstats_v6_load_systemstats(netsnmp_container* container, u_int load_flags)
{
netsnmp_systemstats_entry *entry = NULL;
uint64_t ipstat[IP6_NSTATS];
size_t len = sizeof(ipstat);
if (sysctlbyname("net.inet6.ip6.stats", &ipstat, &len, NULL, 0) < 0) {
NETSNMP_LOGONCE((LOG_ERR, "Cannot sysctlbyname net.inet6.ip6.stats\n"));
return -2;
}
DEBUGMSGTL(("access:systemstats:container:arch", "load v6 (flags %x)\n",
load_flags));
netsnmp_assert(container != NULL); /* load function shoulda checked this */
entry = netsnmp_access_systemstats_entry_create(2, 0,
"ipSystemStatsTable.ipv6");
if(NULL == entry) {
snmp_log(LOG_ERR, "systemstats_v6_load_systemstats: cannot create entry\n");
netsnmp_access_systemstats_container_free(container,
NETSNMP_ACCESS_SYSTEMSTATS_FREE_NOFLAGS);
return -3;
}
/*
* OK - we've now got (or created) the data structure for
* this systemstats, including any "static" information.
*/
entry->stats.HCInReceives.low = ipstat[IP6_STAT_TOTAL] & 0xffffffff;
entry->stats.HCInReceives.high = ipstat[IP6_STAT_TOTAL] >> 32;
entry->stats.InHdrErrors = ipstat[IP6_STAT_BADOPTIONS]
+ ipstat[IP6_STAT_TOOSHORT] + ipstat[IP6_STAT_TOOSMALL]
+ ipstat[IP6_STAT_TOOMANYHDR] + ipstat[IP6_STAT_EXTHDRTOOLONG];
entry->stats.InAddrErrors = ipstat[IP6_STAT_CANTFORWARD];
entry->stats.HCOutForwDatagrams.low = ipstat[IP6_STAT_FORWARD] & 0xffffffff;
entry->stats.HCOutForwDatagrams.high = ipstat[IP6_STAT_FORWARD] >> 32;
entry->stats.InDiscards = ipstat[IP6_STAT_FRAGDROPPED];
entry->stats.HCInDelivers.low = ipstat[IP6_STAT_DELIVERED] & 0xffffffff;
entry->stats.HCInDelivers.high = ipstat[IP6_STAT_DELIVERED] >> 32;
entry->stats.HCOutRequests.low = ipstat[IP6_STAT_LOCALOUT] & 0xffffffff;
entry->stats.HCOutRequests.high = ipstat[IP6_STAT_LOCALOUT] >> 32;
entry->stats.HCOutDiscards.low = ipstat[IP6_STAT_ODROPPED] & 0xffffffff;
entry->stats.HCOutDiscards.high = ipstat[IP6_STAT_ODROPPED] >> 32;
entry->stats.HCOutNoRoutes.low = ipstat[IP6_STAT_NOGIF] & 0xffffffff;
entry->stats.HCOutNoRoutes.high = ipstat[IP6_STAT_NOGIF] >> 32;
/* entry->stats. = scan_vals[12]; / * ReasmTimeout */
entry->stats.ReasmReqds = ipstat[IP6_STAT_FRAGMENTS];
entry->stats.ReasmOKs = ipstat[IP6_STAT_REASSEMBLED];
entry->stats.ReasmFails = ipstat[IP6_STAT_FRAGDROPPED]
+ ipstat[IP6_STAT_FRAGTIMEOUT];
entry->stats.HCOutFragOKs.low = ipstat[IP6_STAT_FRAGMENTS] & 0xffffffff;
entry->stats.HCOutFragOKs.high = ipstat[IP6_STAT_FRAGMENTS] >> 32;
entry->stats.HCOutFragFails.low = ipstat[IP6_STAT_CANTFRAG] & 0xffffffff;
entry->stats.HCOutFragFails.high = ipstat[IP6_STAT_CANTFRAG] >> 32;
entry->stats.HCOutFragCreates.low = ipstat[IP6_STAT_OFRAGMENTS] & 0xffffffff;
entry->stats.HCOutFragCreates.high = ipstat[IP6_STAT_OFRAGMENTS] >> 32;
entry->stats.columnAvail[IPSYSTEMSTATSTABLE_HCINRECEIVES] = 1;
entry->stats.columnAvail[IPSYSTEMSTATSTABLE_INHDRERRORS] = 1;
entry->stats.columnAvail[IPSYSTEMSTATSTABLE_INADDRERRORS] = 1;
entry->stats.columnAvail[IPSYSTEMSTATSTABLE_HCOUTFORWDATAGRAMS] = 1;
entry->stats.columnAvail[IPSYSTEMSTATSTABLE_INDISCARDS] = 1;
entry->stats.columnAvail[IPSYSTEMSTATSTABLE_HCINDELIVERS] = 1;
entry->stats.columnAvail[IPSYSTEMSTATSTABLE_HCOUTREQUESTS] = 1;
entry->stats.columnAvail[IPSYSTEMSTATSTABLE_HCOUTDISCARDS] = 1;
entry->stats.columnAvail[IPSYSTEMSTATSTABLE_HCOUTNOROUTES] = 1;
entry->stats.columnAvail[IPSYSTEMSTATSTABLE_REASMREQDS] = 1;
entry->stats.columnAvail[IPSYSTEMSTATSTABLE_REASMOKS] = 1;
entry->stats.columnAvail[IPSYSTEMSTATSTABLE_REASMFAILS] = 1;
entry->stats.columnAvail[IPSYSTEMSTATSTABLE_HCOUTFRAGOKS] = 1;
entry->stats.columnAvail[IPSYSTEMSTATSTABLE_HCOUTFRAGFAILS] = 1;
entry->stats.columnAvail[IPSYSTEMSTATSTABLE_HCOUTFRAGCREATES] = 1;
entry->stats.columnAvail[IPSYSTEMSTATSTABLE_DISCONTINUITYTIME] = 1;
entry->stats.columnAvail[IPSYSTEMSTATSTABLE_REFRESHRATE] = 1;
/*
* add to container
*/
if (CONTAINER_INSERT(container, entry) < 0)
{
snmp_log(LOG_ERR, "systemstats_v6_load_systemstats: cannot insert entry\n");
DEBUGMSGTL(("access:systemstats:container","error with systemstats_entry: insert into container failed.\n"));
netsnmp_access_systemstats_entry_free(entry);
}
return 0;
}
/*
* load ipIfStatsTable for ipv6 entries
*/
static int
_systemstats_v6_load_ifstats(netsnmp_container* container, u_int load_flags)
{
struct if_nameindex *ifs = if_nameindex();
int ix;
int rc = 0;
for (ix = 0; ifs[ix].if_index; ix++) {
struct in6_ifstat *ifs6;
struct in6_ifreq ifr;
int s;
memset(&ifr, 0, sizeof(ifr));
strncpy(ifr.ifr_name, ifs[ix].if_name, sizeof(ifr.ifr_name)-1);
if ((s = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
rc = -1;
break;
}
if (ioctl(s, SIOCGIFSTAT_IN6, (caddr_t)&ifr) < 0) {
rc = -2;
close(s);
break;
}
close(s);
ifs6 = &ifr.ifr_ifru.ifru_stat;
}
if_freenameindex(ifs);
return rc;
}
#endif
#else
static int
_systemstats_v4(netsnmp_container* container, u_int load_flags)
{
netsnmp_systemstats_entry *entry = NULL;
#ifdef __DragonFly__
size_t len = ncpus*sizeof(struct ip_stats);
struct ip_stats *ipstat = malloc(len);
int c;
#else
size_t len = sizeof(struct ipstat);
struct ipstat *ipstat = malloc(len);
#endif
int mib[] = { CTL_NET, PF_INET, IPPROTO_IP, IPCTL_STATS };
if (sysctl(mib, sizeof(mib) / sizeof(mib[0]), ipstat, &len, NULL, 0) == -1) {
snmp_log_perror("Cannot sysctlbyname net.inet.ip.stats");
free(ipstat);
return -2;
}
DEBUGMSGTL(("access:systemstats:container:arch", "load v4 (flags %x)\n",
load_flags));
netsnmp_assert(container != NULL); /* load function shoulda checked this */
if (load_flags & NETSNMP_ACCESS_SYSTEMSTATS_LOAD_IFTABLE) {
/* we do not support ipIfStatsTable for ipv4 */
free(ipstat);
return 0;
}
entry = netsnmp_access_systemstats_entry_create(1, 0,
"ipSystemStatsTable.ipv4");
if(NULL == entry) {
netsnmp_access_systemstats_container_free(container,
NETSNMP_ACCESS_SYSTEMSTATS_FREE_NOFLAGS);
free(ipstat);
return -3;
}
/*
* OK - we've now got (or created) the data structure for
* this systemstats, including any "static" information.
* Now parse the rest of the line (i.e. starting from 'stats')
* to extract the relevant statistics, and populate
* data structure accordingly.
*/
#ifdef dragonfly
for (c = 1; c < ncpus; c++) {
int i, n = sizeof(struct ip_stats)/sizeof(u_long);
u_long *up = (u_long *)ipstat;
u_long *cp = (u_long *)(ipstat+c);
for (i = 0; i < n; i++) {
*up += *cp;
up++;
cp++;
}
}
#endif
entry->stats.HCInReceives.low = ipstat->ips_total & 0xffffffff;
#ifndef darwin
entry->stats.HCInReceives.high = ipstat->ips_total >> 32;
#endif
entry->stats.InHdrErrors = ipstat->ips_badsum + ipstat->ips_tooshort
+ ipstat->ips_toosmall + ipstat->ips_badhlen
+ ipstat->ips_badlen;
entry->stats.InAddrErrors = ipstat->ips_cantforward;
entry->stats.HCOutForwDatagrams.low = ipstat->ips_forward & 0xffffffff;
#ifndef darwin
entry->stats.HCOutForwDatagrams.high = ipstat->ips_forward >> 32;
#endif
entry->stats.InUnknownProtos = ipstat->ips_noproto;
entry->stats.InDiscards = ipstat->ips_fragdropped;
entry->stats.HCInDelivers.low = ipstat->ips_delivered & 0xffffffff;
#ifndef darwin
entry->stats.HCInDelivers.high = ipstat->ips_delivered >> 32;
#endif
entry->stats.HCOutRequests.low = ipstat->ips_localout & 0xffffffff;
#ifndef darwin
entry->stats.HCOutRequests.high = ipstat->ips_localout >> 32;
#endif
entry->stats.HCOutDiscards.low = ipstat->ips_odropped & 0xffffffff;
#ifndef darwin
entry->stats.HCOutDiscards.high = ipstat->ips_odropped >> 32;
#endif
entry->stats.HCOutNoRoutes.low = ipstat->ips_nogif & 0xffffffff;
#ifndef darwin
entry->stats.HCOutNoRoutes.high = ipstat->ips_nogif >> 32;
#endif
/* entry->stats. = scan_vals[12]; / * ReasmTimeout */
entry->stats.ReasmReqds = ipstat->ips_fragments;
entry->stats.ReasmOKs = ipstat->ips_reassembled;
entry->stats.ReasmFails = ipstat->ips_fragdropped + ipstat->ips_fragtimeout;
entry->stats.HCOutFragOKs.low = ipstat->ips_fragments & 0xffffffff;
#ifndef darwin
entry->stats.HCOutFragOKs.high = ipstat->ips_fragments >> 32;
#endif
entry->stats.HCOutFragFails.low = ipstat->ips_cantfrag & 0xffffffff;
#ifndef darwin
entry->stats.HCOutFragFails.high = ipstat->ips_cantfrag >> 32;
#endif
entry->stats.HCOutFragCreates.low = ipstat->ips_ofragments & 0xffffffff;
#ifndef darwin
entry->stats.HCOutFragCreates.high = ipstat->ips_ofragments >> 32;
#endif
entry->stats.columnAvail[IPSYSTEMSTATSTABLE_HCINRECEIVES] = 1;
entry->stats.columnAvail[IPSYSTEMSTATSTABLE_INHDRERRORS] = 1;
entry->stats.columnAvail[IPSYSTEMSTATSTABLE_INADDRERRORS] = 1;
entry->stats.columnAvail[IPSYSTEMSTATSTABLE_HCOUTFORWDATAGRAMS] = 1;
entry->stats.columnAvail[IPSYSTEMSTATSTABLE_INUNKNOWNPROTOS] = 1;
entry->stats.columnAvail[IPSYSTEMSTATSTABLE_INDISCARDS] = 1;
entry->stats.columnAvail[IPSYSTEMSTATSTABLE_HCINDELIVERS] = 1;
entry->stats.columnAvail[IPSYSTEMSTATSTABLE_HCOUTREQUESTS] = 1;
entry->stats.columnAvail[IPSYSTEMSTATSTABLE_HCOUTDISCARDS] = 1;
entry->stats.columnAvail[IPSYSTEMSTATSTABLE_HCOUTNOROUTES] = 1;
entry->stats.columnAvail[IPSYSTEMSTATSTABLE_REASMREQDS] = 1;
entry->stats.columnAvail[IPSYSTEMSTATSTABLE_REASMOKS] = 1;
entry->stats.columnAvail[IPSYSTEMSTATSTABLE_REASMFAILS] = 1;
entry->stats.columnAvail[IPSYSTEMSTATSTABLE_HCOUTFRAGOKS] = 1;
entry->stats.columnAvail[IPSYSTEMSTATSTABLE_HCOUTFRAGFAILS] = 1;
entry->stats.columnAvail[IPSYSTEMSTATSTABLE_HCOUTFRAGCREATES] = 1;
entry->stats.columnAvail[IPSYSTEMSTATSTABLE_DISCONTINUITYTIME] = 1;
entry->stats.columnAvail[IPSYSTEMSTATSTABLE_REFRESHRATE] = 1;
/*
* add to container
*/
if (CONTAINER_INSERT(container, entry) < 0)
{
DEBUGMSGTL(("access:systemstats:container","error with systemstats_entry: insert into container failed.\n"));
netsnmp_access_systemstats_entry_free(entry);
}
free(ipstat);
return 0;
}
#if defined (NETSNMP_ENABLE_IPV6)
/*
* load ipSystemStatsTable for ipv6 entries
*/
static int
_systemstats_v6_load_systemstats(netsnmp_container* container, u_int load_flags)
{
struct ip6stat ip6stat;
int mib[] = { CTL_NET, AF_INET6, IPPROTO_IPV6, IPV6CTL_STATS };
size_t len = sizeof(ip6stat);
netsnmp_systemstats_entry *entry = NULL;
if (sysctl(mib, sizeof(mib) / sizeof(mib[0]), &ip6stat, &len, NULL, 0) == -1) {
NETSNMP_LOGONCE((LOG_ERR, "Cannot sysctl(CTL_NET, AF_INET6, IPPROTO_IPV6, IPV6CTL_STATS)\n"));
return -1;
}
entry = netsnmp_access_systemstats_entry_create(2, 0,
"ipSystemStatsTable.ipv6");
if(NULL == entry)
return -3;
entry->stats.HCInReceives.low = ip6stat.ip6s_total & 0xffffffff;
entry->stats.HCInReceives.high = ip6stat.ip6s_total >> 32;
entry->stats.columnAvail[IPSYSTEMSTATSTABLE_HCINRECEIVES] = 1;
/*
entry->stats.HCInOctets.low = scan_val & 0xffffffff;
entry->stats.HCInOctets.high = scan_val >> 32;
entry->stats.columnAvail[IPSYSTEMSTATSTABLE_HCINOCTETS] = 1;
*/
entry->stats.InHdrErrors = ip6stat.ip6s_badoptions + ip6stat.ip6s_tooshort
+ ip6stat.ip6s_toosmall + ip6stat.ip6s_badvers
+ ip6stat.ip6s_toomanyhdr;
#if HAVE_STRUCT_IP6STAT_IP6S_EXTHDRTOOLONG
entry->stats.InHdrErrors += ip6stat.ip6s_exthdrtoolong;
#endif
entry->stats.columnAvail[IPSYSTEMSTATSTABLE_INHDRERRORS] = 1;
entry->stats.HCInNoRoutes.low = ip6stat.ip6s_cantforward & 0xffffffff;
entry->stats.HCInNoRoutes.high = ip6stat.ip6s_cantforward >> 32;
entry->stats.columnAvail[IPSYSTEMSTATSTABLE_HCINNOROUTES] = 1;
/*
entry->stats.inAddrErrors = 0;
entry->stats.columnAvail[IPSYSTEMSTATSTABLE_INADDRERRORS] = 1;
entry->stats.InUnknownProtos = scan_val;
entry->stats.columnAvail[IPSYSTEMSTATSTABLE_INUNKNOWNPROTOS] = 1;
entry->stats.InTruncatedPkts = scan_val & 0xffffffff;
entry->stats.columnAvail[IPSYSTEMSTATSTABLE_INTRUNCATEDPKTS] = 1;
*/
entry->stats.HCInForwDatagrams.low = ip6stat.ip6s_forward & 0xffffffff;
entry->stats.HCInForwDatagrams.high = ip6stat.ip6s_forward >> 32;
entry->stats.columnAvail[IPSYSTEMSTATSTABLE_HCINFORWDATAGRAMS] = 1;
entry->stats.ReasmReqds = ip6stat.ip6s_fragments;
entry->stats.columnAvail[IPSYSTEMSTATSTABLE_REASMREQDS] = 1;
entry->stats.ReasmOKs = ip6stat.ip6s_reassembled;
entry->stats.columnAvail[IPSYSTEMSTATSTABLE_REASMOKS] = 1;
entry->stats.ReasmFails = ip6stat.ip6s_fragdropped + ip6stat.ip6s_fragtimeout;
entry->stats.columnAvail[IPSYSTEMSTATSTABLE_REASMFAILS] = 1;
entry->stats.InDiscards = ip6stat.ip6s_fragdropped;
entry->stats.columnAvail[IPSYSTEMSTATSTABLE_INDISCARDS] = 1;
entry->stats.HCInDelivers.low = ip6stat.ip6s_delivered & 0xffffffff;
entry->stats.HCInDelivers.high = ip6stat.ip6s_delivered >> 32;
entry->stats.columnAvail[IPSYSTEMSTATSTABLE_HCINDELIVERS] = 1;
entry->stats.HCOutRequests.low = ip6stat.ip6s_localout & 0xffffffff;
entry->stats.HCOutRequests.high = ip6stat.ip6s_localout >> 32;
entry->stats.columnAvail[IPSYSTEMSTATSTABLE_HCOUTREQUESTS] = 1;
entry->stats.HCOutNoRoutes.low = ip6stat.ip6s_noroute & 0xffffffff;
entry->stats.HCOutNoRoutes.high = ip6stat.ip6s_noroute >> 32;
entry->stats.columnAvail[IPSYSTEMSTATSTABLE_HCOUTNOROUTES] = 1;
entry->stats.HCOutForwDatagrams.low = ip6stat.ip6s_forward & 0xffffffff;
entry->stats.HCOutForwDatagrams.high = ip6stat.ip6s_forward >> 32;
entry->stats.columnAvail[IPSYSTEMSTATSTABLE_HCOUTFORWDATAGRAMS] = 1;
entry->stats.HCOutDiscards.low = ip6stat.ip6s_odropped & 0xffffffff;
entry->stats.HCOutDiscards.high = ip6stat.ip6s_odropped >> 32;
entry->stats.columnAvail[IPSYSTEMSTATSTABLE_HCOUTDISCARDS] = 1;
entry->stats.HCOutFragReqds.low = (ip6stat.ip6s_fragmented + ip6stat.ip6s_cantfrag) & 0xffffffff;
entry->stats.HCOutFragReqds.high = (ip6stat.ip6s_fragmented + ip6stat.ip6s_cantfrag) >> 32;
entry->stats.columnAvail[IPSYSTEMSTATSTABLE_HCOUTFRAGREQDS] = 1;
entry->stats.HCOutFragOKs.low = ip6stat.ip6s_fragmented & 0xffffffff;
entry->stats.HCOutFragOKs.high = ip6stat.ip6s_fragmented >> 32;
entry->stats.columnAvail[IPSYSTEMSTATSTABLE_HCOUTFRAGOKS] = 1;
entry->stats.HCOutFragFails.low = ip6stat.ip6s_cantfrag & 0xffffffff;
entry->stats.HCOutFragFails.high = ip6stat.ip6s_cantfrag >> 32;
entry->stats.columnAvail[IPSYSTEMSTATSTABLE_HCOUTFRAGFAILS] = 1;
entry->stats.HCOutFragCreates.low = ip6stat.ip6s_ofragments & 0xffffffff;
entry->stats.HCOutFragCreates.high = ip6stat.ip6s_ofragments >> 32;
entry->stats.columnAvail[IPSYSTEMSTATSTABLE_HCOUTFRAGCREATES] = 1;
/*
entry->stats.HCOutTransmits.low = scan_val & 0xffffffff;
entry->stats.HCOutTransmits.high = scan_val >> 32;
entry->stats.columnAvail[IPSYSTEMSTATSTABLE_HCOUTTRANSMITS] = 1;
entry->stats.HCOutMcastOctets.low = scan_val & 0xffffffff;
entry->stats.HCOutMcastOctets.high = scan_val >> 32;
entry->stats.columnAvail[IPSYSTEMSTATSTABLE_HCOUTMCASTOCTETS] = 1;
entry->stats.HCInMcastPkts.low = scan_val & 0xffffffff;
entry->stats.HCInMcastPkts.high = scan_val >> 32;
entry->stats.columnAvail[IPSYSTEMSTATSTABLE_HCINMCASTPKTS] = 1;
entry->stats.HCInMcastOctets.low = scan_val & 0xffffffff;
entry->stats.HCInMcastOctets.high = scan_val >> 32;
entry->stats.columnAvail[IPSYSTEMSTATSTABLE_HCINMCASTOCTETS] = 1;
entry->stats.HCOutMcastPkts.low = scan_val & 0xffffffff;
entry->stats.HCOutMcastPkts.high = scan_val >> 32;
entry->stats.columnAvail[IPSYSTEMSTATSTABLE_HCOUTMCASTPKTS] = 1;
entry->stats.HCOutOctets.low = scan_val & 0xffffffff;
entry->stats.HCOutOctets.high = scan_val >> 32;
entry->stats.columnAvail[IPSYSTEMSTATSTABLE_HCOUTOCTETS] = 1;
entry->stats.HCInBcastPkts.low = scan_val & 0xffffffff;
entry->stats.HCInBcastPkts.high = scan_val >> 32;
entry->stats.columnAvail[IPSYSTEMSTATSTABLE_HCINBCASTPKTS] = 1;
entry->stats.HCOutBcastPkts.low = scan_val & 0xffffffff;
entry->stats.HCOutBcastPkts.high = scan_val >> 32;
entry->stats.columnAvail[IPSYSTEMSTATSTABLE_HCOUTBCASTPKTS] = 1;
*/
/*
* add to container
*/
if (CONTAINER_INSERT(container, entry) < 0) {
DEBUGMSGTL(("access:systemstats:container","error with systemstats_entry: insert into container failed.\n"));
netsnmp_access_systemstats_entry_free(entry);
}
return 1;
}
#define DEV_SNMP6_DIRNAME "/proc/net/dev_snmp6"
#define IFINDEX_LINE "ifIndex"
#define DEV_FILENAME_LEN 64
/*
* load ipIfStatsTable for ipv6 entries
*/
static int
_systemstats_v6_load_ifstats(netsnmp_container* container, u_int load_flags)
{
DIR *dev_snmp6_dir;
struct dirent *dev_snmp6_entry;
char dev_filename[DEV_FILENAME_LEN];
FILE *devin;
char line[1024];
char *start = line;
int rc;
char *scan_str;
uintmax_t scan_val;
netsnmp_systemstats_entry *entry = NULL;
/*
* try to open /proc/net/dev_snmp6 directory. If we can't, that' ok -
* maybe it is not supported by the current running kernel.
*/
if ((dev_snmp6_dir = opendir(DEV_SNMP6_DIRNAME)) == NULL) {
DEBUGMSGTL(("access:ifstats",
"Failed to load IPv6 IfStats Table (linux)\n"));
return 0;
}
/*
* Read each per interface statistics proc file
*/
rc = 0;
while ((dev_snmp6_entry = readdir(dev_snmp6_dir)) != NULL) {
if (dev_snmp6_entry->d_name[0] == '.')
continue;
if (snprintf(dev_filename, DEV_FILENAME_LEN, "%s/%s", DEV_SNMP6_DIRNAME,
dev_snmp6_entry->d_name) > DEV_FILENAME_LEN) {
snmp_log(LOG_ERR, "Interface name %s is too long\n",
dev_snmp6_entry->d_name);
continue;
}
if (NULL == (devin = fopen(dev_filename, "r"))) {
snmp_log(LOG_ERR, "Failed to open %s\n", dev_filename);
continue;
}
/*
* If a stat file name is made of digits, the name is interface index.
* If it is an interface name, the file includes a line labeled ifIndex.
*/
if (isdigit(dev_snmp6_entry->d_name[0])) {
scan_val = strtoull(dev_snmp6_entry->d_name, NULL, 0);
} else {
if (NULL == (start = fgets(line, sizeof(line), devin))) {
snmp_log(LOG_ERR, "%s doesn't include any lines\n",
dev_filename);
fclose(devin);
continue;
}
if (0 != strncmp(start, IFINDEX_LINE, 7)) {
snmp_log(LOG_ERR, "%s doesn't include ifIndex line",
dev_filename);
fclose(devin);
continue;
}
scan_str = strrchr(line, ' ');
if (NULL == scan_str) {
snmp_log(LOG_ERR, "%s is wrong format", dev_filename);
fclose(devin);
continue;
}
scan_val = strtoull(scan_str, NULL, 0);
}
entry = netsnmp_access_systemstats_entry_create(2, scan_val,
"ipIfStatsTable.ipv6");
if(NULL == entry) {
fclose(devin);
closedir(dev_snmp6_dir);
return -3;
}
/* _systemstats_v6_load_file(entry, devin); */
CONTAINER_INSERT(container, entry);
fclose(devin);
}
closedir(dev_snmp6_dir);
return 0;
}
#endif /* NETSNMP_ENABLE_IPV6 */
#endif
#ifdef NETSNMP_ENABLE_IPV6
/*
* Based on load_flags, load ipSystemStatsTable or ipIfStatsTable for ipv6 entries.
*/
static int
_systemstats_v6(netsnmp_container* container, u_int load_flags)
{
DEBUGMSGTL(("access:systemstats:container:arch", "load v6 (flags %u)\n",
load_flags));
netsnmp_assert(container != NULL); /* load function shoulda checked this */
if (load_flags & NETSNMP_ACCESS_SYSTEMSTATS_LOAD_IFTABLE) {
/* load ipIfStatsTable */
return _systemstats_v6_load_ifstats(container, load_flags);
} else {
/* load ipSystemStatsTable */
return _systemstats_v6_load_systemstats(container, load_flags);
}
}
#endif /* NETSNMP_ENABLE_IPV6 */