summaryrefslogtreecommitdiff
path: root/agent/mibgroup/mibII/kernel_linux.c
diff options
context:
space:
mode:
Diffstat (limited to 'agent/mibgroup/mibII/kernel_linux.c')
-rw-r--r--agent/mibgroup/mibII/kernel_linux.c628
1 files changed, 628 insertions, 0 deletions
diff --git a/agent/mibgroup/mibII/kernel_linux.c b/agent/mibgroup/mibII/kernel_linux.c
new file mode 100644
index 0000000..b21a166
--- /dev/null
+++ b/agent/mibgroup/mibII/kernel_linux.c
@@ -0,0 +1,628 @@
+/*
+ * Linux kernel interface
+ *
+ */
+
+#include <net-snmp/net-snmp-config.h>
+#include <net-snmp/net-snmp-features.h>
+#include <net-snmp/net-snmp-includes.h>
+#include <net-snmp/agent/net-snmp-agent-includes.h>
+
+#if HAVE_STRING_H
+#include <string.h>
+#endif
+#include <sys/types.h>
+#if HAVE_SYS_PARAM_H
+#include <sys/param.h>
+#endif
+#include <errno.h>
+
+#include "kernel_linux.h"
+
+struct ip_mib cached_ip_mib;
+struct ip6_mib cached_ip6_mib;
+struct icmp_mib cached_icmp_mib;
+struct icmp6_mib cached_icmp6_mib;
+struct icmp4_msg_mib cached_icmp4_msg_mib;
+struct tcp_mib cached_tcp_mib;
+struct udp_mib cached_udp_mib;
+struct udp6_mib cached_udp6_mib;
+
+#define IP_STATS_LINE "Ip: %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu"
+#define ICMP_STATS_LINE "Icmp: %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu"
+#define ICMP_MSG_STATS_LINE "IcmpMsg: "
+#define TCP_STATS_LINE "Tcp: %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu"
+#define UDP_STATS_LINE "Udp: %lu %lu %lu %lu"
+#define IP6_STATS_LINE "Ip6"
+#define ICMP6_STATS_LINE "Icmp6"
+#define UDP6_STATS_LINE "Udp6"
+
+#define IP_STATS_PREFIX_LEN 4
+#define ICMP_STATS_PREFIX_LEN 6
+#define ICMP_MSG_STATS_PREFIX_LEN 9
+#define TCP_STATS_PREFIX_LEN 5
+#define UDP_STATS_PREFIX_LEN 5
+#define IP6_STATS_PREFIX_LEN 3
+#define ICMP6_STATS_PREFIX_LEN 5
+#define UDP6_STATS_PREFIX_LEN 4
+
+netsnmp_feature_child_of(linux_ip6_stat_all, libnetsnmpmibs)
+
+netsnmp_feature_child_of(linux_read_ip6_stat, linux_ip6_stat_all)
+
+int
+decode_icmp_msg(char *line, char *data, struct icmp4_msg_mib *msg)
+{
+ char *token, *saveptr, *lineptr, *saveptr1, *dataptr, *delim = NULL;
+ char line_cpy[1024];
+ char data_cpy[1024];
+ long index;
+
+ if(data == NULL)
+ return -1;
+
+ /*
+ * Since we are using strtok, there is a possiblity of the orginal data
+ * getting modified. So we take a local copy for this purpose even though
+ * its expensive.
+ */
+ strlcpy(line_cpy, line, sizeof(line_cpy));
+ strlcpy(data_cpy, data, sizeof(data_cpy));
+
+ lineptr = line_cpy;
+ dataptr = data_cpy;
+ saveptr1 = NULL;
+ while (1) {
+ if(NULL == (token = strtok_r(lineptr, " ", &saveptr)))
+ break;
+ lineptr = NULL;
+ errno = 0;
+ if (0 == strncmp(strsep(&token, "e"), "OutTyp", 6)) {
+ index = strtol(token, &delim, 0);
+ if (ERANGE == errno) {
+ continue;
+ } else if (index > LONG_MAX) {
+ continue;
+ } else if (index < LONG_MIN) {
+ continue;
+ }
+ if (NULL == (token = strtok_r(dataptr, " ", &saveptr1)))
+ break;
+ dataptr = NULL;
+ msg->vals[index].OutType = atoi(token);
+ } else {
+ index = strtol(token, &delim, 0);
+ if (ERANGE == errno) {
+ continue;
+ } else if (index > LONG_MAX) {
+ continue;
+ } else if (index < LONG_MIN) {
+ continue;
+ }
+ if(NULL == (token = strtok_r(dataptr, " ", &saveptr1)))
+ break;
+ dataptr = NULL;
+ msg->vals[index].InType = atoi(token);
+ }
+ }
+ return 0;
+}
+
+int
+linux_read_mibII_stats(void)
+{
+ FILE *in = fopen("/proc/net/snmp", "r");
+ char line[1024], data[1024];
+ int ret = 0;
+ if (!in) {
+ DEBUGMSGTL(("mibII/kernel_linux","Unable to open /proc/net/snmp"));
+ return -1;
+ }
+
+
+ memset(line, '\0', sizeof(line));
+ memset(data, '\0', sizeof(data));
+ while (line == fgets(line, sizeof(line), in)) {
+ if (!strncmp(line, IP_STATS_LINE, IP_STATS_PREFIX_LEN)) {
+ sscanf(line, IP_STATS_LINE,
+ &cached_ip_mib.ipForwarding,
+ &cached_ip_mib.ipDefaultTTL,
+ &cached_ip_mib.ipInReceives,
+ &cached_ip_mib.ipInHdrErrors,
+ &cached_ip_mib.ipInAddrErrors,
+ &cached_ip_mib.ipForwDatagrams,
+ &cached_ip_mib.ipInUnknownProtos,
+ &cached_ip_mib.ipInDiscards,
+ &cached_ip_mib.ipInDelivers,
+ &cached_ip_mib.ipOutRequests,
+ &cached_ip_mib.ipOutDiscards,
+ &cached_ip_mib.ipOutNoRoutes,
+ &cached_ip_mib.ipReasmTimeout,
+ &cached_ip_mib.ipReasmReqds,
+ &cached_ip_mib.ipReasmOKs,
+ &cached_ip_mib.ipReasmFails,
+ &cached_ip_mib.ipFragOKs,
+ &cached_ip_mib.ipFragFails,
+ &cached_ip_mib.ipFragCreates);
+ cached_ip_mib.ipRoutingDiscards = 0; /* XXX */
+ } else if (!strncmp(line, ICMP_STATS_LINE, ICMP_STATS_PREFIX_LEN)) {
+ sscanf(line, ICMP_STATS_LINE,
+ &cached_icmp_mib.icmpInMsgs,
+ &cached_icmp_mib.icmpInErrors,
+ &cached_icmp_mib.icmpInDestUnreachs,
+ &cached_icmp_mib.icmpInTimeExcds,
+ &cached_icmp_mib.icmpInParmProbs,
+ &cached_icmp_mib.icmpInSrcQuenchs,
+ &cached_icmp_mib.icmpInRedirects,
+ &cached_icmp_mib.icmpInEchos,
+ &cached_icmp_mib.icmpInEchoReps,
+ &cached_icmp_mib.icmpInTimestamps,
+ &cached_icmp_mib.icmpInTimestampReps,
+ &cached_icmp_mib.icmpInAddrMasks,
+ &cached_icmp_mib.icmpInAddrMaskReps,
+ &cached_icmp_mib.icmpOutMsgs,
+ &cached_icmp_mib.icmpOutErrors,
+ &cached_icmp_mib.icmpOutDestUnreachs,
+ &cached_icmp_mib.icmpOutTimeExcds,
+ &cached_icmp_mib.icmpOutParmProbs,
+ &cached_icmp_mib.icmpOutSrcQuenchs,
+ &cached_icmp_mib.icmpOutRedirects,
+ &cached_icmp_mib.icmpOutEchos,
+ &cached_icmp_mib.icmpOutEchoReps,
+ &cached_icmp_mib.icmpOutTimestamps,
+ &cached_icmp_mib.icmpOutTimestampReps,
+ &cached_icmp_mib.icmpOutAddrMasks,
+ &cached_icmp_mib.icmpOutAddrMaskReps);
+ } else if (!strncmp(line, ICMP_MSG_STATS_LINE, ICMP_MSG_STATS_PREFIX_LEN)) {
+ /*
+ * Note: We have to do this differently from other stats as the
+ * counters to this stats are dynamic. So we will not know the
+ * number of counters at a given time.
+ */
+ fgets(data, sizeof(data), in);
+ if(decode_icmp_msg(line + ICMP_MSG_STATS_PREFIX_LEN,
+ data + ICMP_MSG_STATS_PREFIX_LEN,
+ &cached_icmp4_msg_mib) < 0) {
+ continue;
+ }
+ ret = 1;
+ } else if (!strncmp(line, TCP_STATS_LINE, TCP_STATS_PREFIX_LEN)) {
+ int ret = sscanf(line, TCP_STATS_LINE,
+ &cached_tcp_mib.tcpRtoAlgorithm,
+ &cached_tcp_mib.tcpRtoMin,
+ &cached_tcp_mib.tcpRtoMax,
+ &cached_tcp_mib.tcpMaxConn,
+ &cached_tcp_mib.tcpActiveOpens,
+ &cached_tcp_mib.tcpPassiveOpens,
+ &cached_tcp_mib.tcpAttemptFails,
+ &cached_tcp_mib.tcpEstabResets,
+ &cached_tcp_mib.tcpCurrEstab,
+ &cached_tcp_mib.tcpInSegs,
+ &cached_tcp_mib.tcpOutSegs,
+ &cached_tcp_mib.tcpRetransSegs,
+ &cached_tcp_mib.tcpInErrs,
+ &cached_tcp_mib.tcpOutRsts);
+ cached_tcp_mib.tcpInErrsValid = (ret > 12) ? 1 : 0;
+ cached_tcp_mib.tcpOutRstsValid = (ret > 13) ? 1 : 0;
+ } else if (!strncmp(line, UDP_STATS_LINE, UDP_STATS_PREFIX_LEN)) {
+ sscanf(line, UDP_STATS_LINE,
+ &cached_udp_mib.udpInDatagrams,
+ &cached_udp_mib.udpNoPorts,
+ &cached_udp_mib.udpInErrors,
+ &cached_udp_mib.udpOutDatagrams);
+ }
+ }
+ fclose(in);
+
+ /*
+ * Tweak illegal values:
+ *
+ * valid values for ipForwarding are 1 == yup, 2 == nope
+ * a 0 is forbidden, so patch:
+ */
+ if (!cached_ip_mib.ipForwarding)
+ cached_ip_mib.ipForwarding = 2;
+
+ /*
+ * 0 is illegal for tcpRtoAlgorithm
+ * so assume `other' algorithm:
+ */
+ if (!cached_tcp_mib.tcpRtoAlgorithm)
+ cached_tcp_mib.tcpRtoAlgorithm = 1;
+
+ return ret;
+}
+
+int
+linux_read_ip_stat(struct ip_mib *ipstat)
+{
+ memset((char *) ipstat, (0), sizeof(*ipstat));
+ if (linux_read_mibII_stats() == -1)
+ return -1;
+ memcpy((char *) ipstat, (char *) &cached_ip_mib, sizeof(*ipstat));
+ return 0;
+}
+
+#ifndef NETSNMP_FEATURE_REMOVE_LINUX_READ_IP6_STAT
+int linux_read_ip6_stat( struct ip6_mib *ip6stat)
+{
+#ifdef NETSNMP_ENABLE_IPV6
+ FILE *in;
+ char line[1024];
+ unsigned long stats;
+ char *endp;
+ int match;
+#endif
+
+ memset((char *) ip6stat, (0), sizeof(*ip6stat));
+
+#ifdef NETSNMP_ENABLE_IPV6
+ DEBUGMSGTL(("mibII/kernel_linux/ip6stats",
+ "Reading /proc/net/snmp6 stats\n"));
+ if (NULL == (in = fopen("/proc/net/snmp6", "r"))) {
+ DEBUGMSGTL(("mibII/kernel_linux/ip6stats",
+ "Failed to open /proc/net/snmp6\n"));
+ return -1;
+ }
+
+ while (NULL != fgets(line, sizeof(line), in)) {
+ if (0 != strncmp(line, IP6_STATS_LINE, IP6_STATS_PREFIX_LEN))
+ continue;
+
+ if (1 != sscanf(line, "%*s %lu", &stats))
+ continue;
+
+ endp = strchr(line, ' ');
+ *endp = '\0';
+ DEBUGMSGTL(("mibII/kernel_linux/ip6stats", "Find tag: %s\n", line));
+
+ match = 1;
+ if (0 == strncmp(line + 3, "In", 2)) { /* In */
+ if (0 == strcmp(line + 5, "AddrErrors")) {
+ cached_ip6_mib.ip6InAddrErrors = stats;
+ } else if (0 == strcmp(line + 5, "Delivers")) {
+ cached_ip6_mib.ip6InDelivers = stats;
+ } else if (0 == strcmp(line + 5, "Discards")) {
+ cached_ip6_mib.ip6InDiscards = stats;
+ } else if (0 == strcmp(line + 5, "HdrErrors")) {
+ cached_ip6_mib.ip6InHdrErrors = stats;
+ } else if (0 == strcmp(line + 5, "McastPkts")) {
+ cached_ip6_mib.ip6InMcastPkts = stats;
+ } else if (0 == strcmp(line + 5, "NoRoutes")) {
+ cached_ip6_mib.ip6InNoRoutes = stats;
+ } else if (0 == strcmp(line + 5, "Receives")) {
+ cached_ip6_mib.ip6InReceives = stats;
+ } else if (0 == strcmp(line + 5, "TruncatedPkts")) {
+ cached_ip6_mib.ip6InTruncatedPkts = stats;
+ } else if (0 == strcmp(line + 5, "TooBigErrors")) {
+ cached_ip6_mib.ip6InTooBigErrors = stats;
+ } else if (0 == strcmp(line + 5, "UnknownProtos")) {
+ cached_ip6_mib.ip6InUnknownProtos = stats;
+ } else {
+ match = 0;
+ }
+ } else if (0 == strncmp(line + 3, "Out", 3)) { /* Out */
+ if (0 == strcmp(line + 6, "Discards")) {
+ cached_ip6_mib.ip6OutDiscards = stats;
+ } else if (0 == strcmp(line + 6, "ForwDatagrams")) {
+ cached_ip6_mib.ip6OutForwDatagrams = stats;
+ } else if (0 == strcmp(line + 6, "McastPkts")) {
+ cached_ip6_mib.ip6OutMcastPkts = stats;
+ } else if (0 == strcmp(line + 6, "NoRoutes")) {
+ cached_ip6_mib.ip6OutNoRoutes = stats;
+ } else if (0 == strcmp(line + 6, "Requests")) {
+ cached_ip6_mib.ip6OutRequests = stats;
+ } else {
+ match = 0;
+ }
+ } else if (0 == strncmp(line + 3, "Reasm", 5)) { /* Reasm */
+ if (0 == strcmp(line + 8, "Fails")) {
+ cached_ip6_mib.ip6ReasmFails = stats;
+ } else if (0 == strcmp(line + 8, "OKs")) {
+ cached_ip6_mib.ip6ReasmOKs = stats;
+ } else if (0 == strcmp(line + 8, "Reqds")) {
+ cached_ip6_mib.ip6ReasmReqds = stats;
+ } else if (0 == strcmp(line + 8, "Timeout")) {
+ cached_ip6_mib.ip6ReasmTimeout = stats;
+ } else {
+ match = 0;
+ }
+ } else if (0 == strncmp(line + 3, "Frag", 4)) { /* Frag */
+ if (0 == strcmp(line + 7, "Creates")) {
+ cached_ip6_mib.ip6FragCreates = stats;
+ } else if (0 == strcmp(line + 7, "Fails")) {
+ cached_ip6_mib.ip6FragFails = stats;
+ } else if (0 == strcmp(line + 7, "OKs")) {
+ cached_ip6_mib.ip6FragOKs = stats;
+ } else {
+ match = 0;
+ }
+ } else {
+ match = 0;
+ }
+
+ if(!match)
+ DEBUGMSGTL(("mibII/kernel_linux/ip6stats",
+ "%s is an unknown tag\n", line));
+ }
+
+ fclose(in);
+#endif
+
+ memcpy((char *) ip6stat, (char *) &cached_ip6_mib, sizeof(*ip6stat));
+ return 0;
+}
+#endif /* NETSNMP_FEATURE_REMOVE_LINUX_READ_IP6_STAT */
+
+int
+linux_read_icmp_msg_stat(struct icmp_mib *icmpstat,
+ struct icmp4_msg_mib *icmpmsgstat,
+ int *flag)
+{
+ int ret;
+
+ memset(icmpstat, 0, sizeof(*icmpstat));
+ memset(icmpmsgstat, 0, sizeof(*icmpmsgstat));
+
+ if ((ret = linux_read_mibII_stats()) == -1) {
+ return -1;
+ } else if (ret) {
+ memcpy(icmpmsgstat, &cached_icmp4_msg_mib, sizeof(*icmpmsgstat));
+ *flag = 1; /* We have a valid icmpmsg */
+ }
+
+ memcpy(icmpstat, &cached_icmp_mib, sizeof(*icmpstat));
+ return 0;
+}
+
+int
+linux_read_icmp_stat(struct icmp_mib *icmpstat)
+{
+ memset((char *) icmpstat, (0), sizeof(*icmpstat));
+ if (linux_read_mibII_stats() == -1)
+ return -1;
+ memcpy((char *) icmpstat, (char *) &cached_icmp_mib,
+ sizeof(*icmpstat));
+ return 0;
+}
+
+int
+linux_read_icmp6_parse(struct icmp6_mib *icmp6stat,
+ struct icmp6_msg_mib *icmp6msgstat,
+ int *support)
+{
+#ifdef NETSNMP_ENABLE_IPV6
+ FILE *in;
+ char line[1024];
+ char name[255];
+ unsigned long stats;
+ char *endp, *vals;
+ int match;
+#endif
+
+ memset(icmp6stat, 0, sizeof(*icmp6stat));
+ if (NULL != icmp6msgstat)
+ memset(icmp6msgstat, 0, sizeof(*icmp6msgstat));
+
+#ifdef NETSNMP_ENABLE_IPV6
+ DEBUGMSGTL(("mibII/kernel_linux/icmp6stats",
+ "Reading /proc/net/snmp6 stats\n"));
+ if (NULL == (in = fopen("/proc/net/snmp6", "r"))) {
+ DEBUGMSGTL(("mibII/kernel_linux/icmp6stats",
+ "Failed to open /proc/net/snmp6\n"));
+ return -1;
+ }
+
+ while (NULL != fgets(line, sizeof(line), in)) {
+ if (0 != strncmp(line, ICMP6_STATS_LINE, ICMP6_STATS_PREFIX_LEN))
+ continue;
+
+ if (2 != sscanf(line, "%s %lu", name, &stats))
+ continue;
+
+ endp = strchr(line, ' ');
+ *endp = '\0';
+ DEBUGMSGTL(("mibII/kernel_linux/icmp6stats", "Find tag: %s\n", line));
+
+ vals = name;
+ if (NULL != icmp6msgstat) {
+ if (0 == strncmp(name, "Icmp6OutType", 12)) {
+ strsep(&vals, "e");
+ icmp6msgstat->vals[atoi(vals)].OutType = stats;
+ *support = 1;
+ continue;
+ } else if (0 == strncmp(name, "Icmp6InType", 11)) {
+ strsep(&vals, "e");
+ icmp6msgstat->vals[atoi(vals)].InType = stats;
+ *support = 1;
+ continue;
+ }
+ }
+
+ match = 1;
+ if (0 == strncmp(line + 5, "In", 2)) { /* In */
+ if (0 == strcmp(line + 7, "DestUnreachs")) {
+ cached_icmp6_mib.icmp6InDestUnreachs = stats;
+ } else if (0 == strcmp(line + 7, "Echos")) {
+ cached_icmp6_mib.icmp6InEchos = stats;
+ } else if (0 == strcmp(line + 7, "EchoReplies")) {
+ cached_icmp6_mib.icmp6InEchoReplies = stats;
+ } else if (0 == strcmp(line + 7, "Errors")) {
+ cached_icmp6_mib.icmp6InErrors = stats;
+ } else if (0 == strcmp(line + 7, "GroupMembQueries")) {
+ cached_icmp6_mib.icmp6InGroupMembQueries = stats;
+ } else if (0 == strcmp(line + 7, "GroupMembReductions")) {
+ cached_icmp6_mib.icmp6InGroupMembReductions = stats;
+ } else if (0 == strcmp(line + 7, "GroupMembResponses")) {
+ cached_icmp6_mib.icmp6InGroupMembResponses = stats;
+ } else if (0 == strcmp(line + 7, "Msgs")) {
+ cached_icmp6_mib.icmp6InMsgs = stats;
+ } else if (0 == strcmp(line + 7, "NeighborAdvertisements")) {
+ cached_icmp6_mib.icmp6InNeighborAdvertisements = stats;
+ } else if (0 == strcmp(line + 7, "NeighborSolicits")) {
+ cached_icmp6_mib.icmp6InNeighborSolicits = stats;
+ } else if (0 == strcmp(line + 7, "PktTooBigs")) {
+ cached_icmp6_mib.icmp6InPktTooBigs = stats;
+ } else if (0 == strcmp(line + 7, "ParmProblems")) {
+ cached_icmp6_mib.icmp6InParmProblems = stats;
+ } else if (0 == strcmp(line + 7, "Redirects")) {
+ cached_icmp6_mib.icmp6InRedirects = stats;
+ } else if (0 == strcmp(line + 7, "RouterAdvertisements")) {
+ cached_icmp6_mib.icmp6InRouterAdvertisements = stats;
+ } else if (0 == strcmp(line + 7, "RouterSolicits")) {
+ cached_icmp6_mib.icmp6InRouterSolicits = stats;
+ } else if (0 == strcmp(line + 7, "TimeExcds")) {
+ cached_icmp6_mib.icmp6InTimeExcds = stats;
+ } else {
+ match = 0;
+ }
+ } else if (0 == strncmp(line + 5, "Out", 3)) { /* Out */
+ if (0 == strcmp(line + 8, "DestUnreachs")) {
+ cached_icmp6_mib.icmp6OutDestUnreachs = stats;
+ } else if (0 == strcmp(line + 8, "EchoReplies")) {
+ cached_icmp6_mib.icmp6OutEchoReplies = stats;
+ } else if (0 == strcmp(line + 8, "GroupMembReductions")) {
+ cached_icmp6_mib.icmp6OutGroupMembReductions = stats;
+ } else if (0 == strcmp(line + 8, "GroupMembResponses")) {
+ cached_icmp6_mib.icmp6OutGroupMembResponses = stats;
+ } else if (0 == strcmp(line + 8, "Msgs")) {
+ cached_icmp6_mib.icmp6OutMsgs = stats;
+ } else if (0 == strcmp(line + 8, "NeighborAdvertisements")) {
+ cached_icmp6_mib.icmp6OutNeighborAdvertisements = stats;
+ } else if (0 == strcmp(line + 8, "NeighborSolicits")) {
+ cached_icmp6_mib.icmp6OutNeighborSolicits = stats;
+ } else if (0 == strcmp(line + 8, "PktTooBigs")) {
+ cached_icmp6_mib.icmp6OutPktTooBigs = stats;
+ } else if (0 == strcmp(line + 8, "ParmProblems")) {
+ cached_icmp6_mib.icmp6OutParmProblems = stats;
+ } else if (0 == strcmp(line + 8, "Redirects")) {
+ cached_icmp6_mib.icmp6OutRedirects = stats;
+ } else if (0 == strcmp(line + 8, "RouterSolicits")) {
+ cached_icmp6_mib.icmp6OutRouterSolicits = stats;
+ } else if (0 == strcmp(line + 8, "TimeExcds")) {
+ cached_icmp6_mib.icmp6OutTimeExcds = stats;
+ } else {
+ match = 0;
+ }
+ } else {
+ match = 0;
+ }
+ if(!match)
+ DEBUGMSGTL(("mibII/kernel_linux/icmp6stats",
+ "%s is an unknown tag\n", line));
+ }
+
+ fclose(in);
+#endif
+
+ memcpy((char *) icmp6stat, (char *) &cached_icmp6_mib,
+ sizeof(*icmp6stat));
+ return 0;
+}
+
+int
+linux_read_icmp6_msg_stat(struct icmp6_mib *icmp6stat,
+ struct icmp6_msg_mib *icmp6msgstat,
+ int *support)
+{
+ if (linux_read_icmp6_parse(icmp6stat, icmp6msgstat, support) < 0)
+ return -1;
+ else
+ return 0;
+}
+
+int
+linux_read_icmp6_stat(struct icmp6_mib *icmp6stat)
+{
+ if (linux_read_icmp6_parse(icmp6stat, NULL, NULL) < 0)
+ return -1;
+ else
+ return 0;
+}
+
+int
+linux_read_tcp_stat(struct tcp_mib *tcpstat)
+{
+ memset((char *) tcpstat, (0), sizeof(*tcpstat));
+ if (linux_read_mibII_stats() == -1)
+ return -1;
+ memcpy((char *) tcpstat, (char *) &cached_tcp_mib, sizeof(*tcpstat));
+ return 0;
+}
+
+int
+linux_read_udp_stat(struct udp_mib *udpstat)
+{
+ memset((char *) udpstat, (0), sizeof(*udpstat));
+ if (linux_read_mibII_stats() == -1)
+ return -1;
+
+#ifdef NETSNMP_ENABLE_IPV6
+ {
+ struct udp6_mib udp6stat;
+ memset(&udp6stat, 0, sizeof(udp6stat));
+
+ if (linux_read_udp6_stat(&udp6stat) == 0) {
+ cached_udp_mib.udpOutDatagrams += udp6stat.udp6OutDatagrams;
+ cached_udp_mib.udpNoPorts += udp6stat.udp6NoPorts;
+ cached_udp_mib.udpInDatagrams += udp6stat.udp6InDatagrams;
+ cached_udp_mib.udpInErrors += udp6stat.udp6InErrors;
+ }
+ }
+#endif
+ memcpy((char *) udpstat, (char *) &cached_udp_mib, sizeof(*udpstat));
+ return 0;
+}
+
+int
+linux_read_udp6_stat(struct udp6_mib *udp6stat)
+{
+#ifdef NETSNMP_ENABLE_IPV6
+ FILE *in;
+ char line[1024];
+ unsigned long stats;
+ char *endp;
+#endif
+
+ memset(udp6stat, 0, sizeof(*udp6stat));
+
+#ifdef NETSNMP_ENABLE_IPV6
+ DEBUGMSGTL(("mibII/kernel_linux/udp6stats",
+ "Reading /proc/net/snmp6 stats\n"));
+ if (NULL == (in = fopen("/proc/net/snmp6", "r"))) {
+ DEBUGMSGTL(("mibII/kernel_linux/udp6stats",
+ "Failed to open /proc/net/snmp6\n"));
+ return -1;
+ }
+
+ while (NULL != fgets(line, sizeof(line), in)) {
+ if (0 != strncmp(line, UDP6_STATS_LINE, UDP6_STATS_PREFIX_LEN))
+ continue;
+
+ if (1 != sscanf(line, "%*s %lu", &stats))
+ continue;
+
+ endp = strchr(line, ' ');
+ *endp = '\0';
+ DEBUGMSGTL(("mibII/kernel_linux/udp6stats", "Find tag: %s\n", line));
+
+ if (0 == strcmp(line + 4, "OutDatagrams")) {
+ cached_udp6_mib.udp6OutDatagrams = stats;
+ } else if (0 == strcmp(line + 4, "NoPorts")) {
+ cached_udp6_mib.udp6NoPorts = stats;
+ } else if (0 == strcmp(line + 4, "InDatagrams")) {
+ cached_udp6_mib.udp6InDatagrams = stats;
+ } else if (0 == strcmp(line + 4, "InErrors")) {
+ cached_udp6_mib.udp6InErrors = stats;
+ } else {
+ DEBUGMSGTL(("mibII/kernel_linux/udp6stats",
+ "%s is an unknown tag\n", line));
+ }
+ }
+
+ fclose(in);
+#endif
+
+ memcpy((char *) udp6stat, (char *) &cached_udp6_mib, sizeof(*udp6stat));
+ return 0;
+}