summaryrefslogtreecommitdiff
path: root/agent/mibgroup/mibII/interfaces.c
diff options
context:
space:
mode:
Diffstat (limited to 'agent/mibgroup/mibII/interfaces.c')
-rw-r--r--agent/mibgroup/mibII/interfaces.c2867
1 files changed, 2867 insertions, 0 deletions
diff --git a/agent/mibgroup/mibII/interfaces.c b/agent/mibgroup/mibII/interfaces.c
new file mode 100644
index 0000000..a723108
--- /dev/null
+++ b/agent/mibgroup/mibII/interfaces.c
@@ -0,0 +1,2867 @@
+/*
+ * Interfaces MIB group implementation - interfaces.c
+ *
+ */
+
+/* Portions of this file are subject to the following copyright(s). See
+ * the Net-SNMP's COPYING file for more details and other copyrights
+ * that may apply:
+ */
+/*
+ * Portions of this file are copyrighted by:
+ * Copyright © 2003 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms specified in the COPYING file
+ * distributed with the Net-SNMP package.
+ */
+
+#include <net-snmp/net-snmp-config.h>
+
+#if defined(IFNET_NEEDS_KERNEL) && !defined(_KERNEL) && !defined(IFNET_NEEDS_KERNEL_LATE)
+#define _KERNEL 1
+#define _I_DEFINED_KERNEL
+#endif
+
+#if HAVE_STRING_H
+#include <string.h>
+#else
+#include <strings.h>
+#endif
+
+#if HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#if HAVE_SYS_PARAM_H
+#include <sys/param.h>
+#endif
+#include <sys/types.h>
+#if HAVE_WINSOCK_H
+#include <winsock.h>
+#endif
+#if defined(IFNET_NEEDS_KERNEL) && !defined(_KERNEL) && defined(IFNET_NEEDS_KERNEL_LATE)
+#define _KERNEL 1
+#define _I_DEFINED_KERNEL
+#endif
+#if HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
+#ifndef STREAM_NEEDS_KERNEL_ISLANDS
+#if HAVE_SYS_STREAM_H
+#include <sys/stream.h>
+#endif
+#endif
+#if HAVE_SYS_SOCKETVAR_H
+#include <sys/socketvar.h>
+#endif
+
+#if TIME_WITH_SYS_TIME
+# if defined (WIN32) || defined (cygwin)
+# include <sys/timeb.h>
+# else
+# include <sys/time.h>
+# endif
+# include <time.h>
+#else
+# if HAVE_SYS_TIME_H
+# include <sys/time.h>
+# else
+# include <time.h>
+# endif
+#endif
+#if HAVE_SYS_SOCKIO_H
+#include <sys/sockio.h>
+#endif
+#if HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+#if HAVE_SYS_IOCTL_H
+#include <sys/ioctl.h>
+#endif
+#if HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+#if HAVE_NET_IF_H
+#include <net/if.h>
+#endif
+#if HAVE_NETINET_IN_VAR_H
+#include <netinet/in_var.h>
+#endif
+#if HAVE_NET_IF_VAR_H
+#include <net/if_var.h>
+#endif
+#ifdef _I_DEFINED_KERNEL
+#undef _KERNEL
+#endif
+#ifdef STREAM_NEEDS_KERNEL_ISLANDS
+#if HAVE_SYS_STREAM_H
+#include <sys/stream.h>
+#endif
+#endif
+#if HAVE_NET_ROUTE_H
+#include <net/route.h>
+#endif
+#if HAVE_NETINET_IN_SYSTM_H
+#include <netinet/in_systm.h>
+#endif
+#if HAVE_SYS_HASHING_H
+#include <sys/hashing.h>
+#endif
+#if HAVE_NETINET_IN_VAR_H
+#include <netinet/in_var.h>
+#endif
+#if HAVE_NETINET_IP_H
+#include <netinet/ip.h>
+#endif
+#ifdef NETSNMP_ENABLE_IPV6
+#if HAVE_NETINET_IP6_H
+#include <netinet/ip6.h>
+#endif
+#endif
+#if HAVE_SYS_QUEUE_H
+#include <sys/queue.h>
+#endif
+#if HAVE_NETINET_IP_VAR_H
+#include <netinet/ip_var.h>
+#endif
+#ifdef NETSNMP_ENABLE_IPV6
+#if HAVE_NETNETSNMP_ENABLE_IPV6_IP6_VAR_H
+#include <netinet6/ip6_var.h>
+#endif
+#endif
+#if HAVE_NETINET_IN_PCB_H
+#include <netinet/in_pcb.h>
+#endif
+#if HAVE_NETINET_IF_ETHER_H
+#include <netinet/if_ether.h>
+#endif
+#if HAVE_NET_IF_TYPES_H
+#include <net/if_types.h>
+#endif
+#if HAVE_NET_IF_DL_H
+#ifndef dynix
+#include <net/if_dl.h>
+#else
+#include <sys/net/if_dl.h>
+#endif
+#endif
+#if HAVE_INET_MIB2_H
+#include <inet/mib2.h>
+#endif
+#if HAVE_IOCTLS_H
+#include <ioctls.h>
+#endif
+
+#ifdef solaris2
+# include <errno.h>
+#include "kernel_sunos5.h"
+#else
+#include "kernel.h"
+#endif
+
+#ifdef hpux
+#include <sys/mib.h>
+#include <netinet/mib_kern.h>
+#endif /* hpux */
+
+#ifdef cygwin
+#include <windows.h>
+#endif
+
+#if HAVE_SYS_SYSCTL_H
+#include <sys/sysctl.h>
+
+#if defined(freebsd3) || defined(freebsd4) || defined(freebsd5)
+# define USE_SYSCTL_IFLIST
+#else
+# if defined(CTL_NET) && !defined(freebsd2) && !defined(netbsd1)
+# ifdef PF_ROUTE
+# ifdef NET_RT_IFLIST
+# ifndef netbsd1
+# define USE_SYSCTL_IFLIST
+# endif
+# endif
+# endif
+# endif
+#endif /* defined(freebsd3) */
+#endif /* HAVE_SYS_SYSCTL_H */
+
+#if HAVE_OSRELDATE_H
+#include <osreldate.h>
+#endif
+#ifdef NETSNMP_CAN_USE_SYSCTL
+#include <sys/sysctl.h>
+#endif
+
+#include <net-snmp/net-snmp-includes.h>
+#include <net-snmp/agent/net-snmp-agent-includes.h>
+#include <net-snmp/agent/auto_nlist.h>
+#include <net-snmp/data_access/interface.h>
+
+#include "interfaces.h"
+#include "struct.h"
+#include "util_funcs.h"
+#include "sysORTable.h"
+
+/* if you want caching enabled for speed retrival purposes, set this to 5?*/
+#define MINLOADFREQ 0 /* min reload frequency in seconds */
+#ifdef linux
+static unsigned long LastLoad = 0; /* ET in secs at last table load */
+#endif
+
+extern struct timeval starttime;
+
+struct variable3 interfaces_variables[] = {
+ {IFNUMBER, ASN_INTEGER, RONLY, var_interfaces, 1, {1}},
+ {IFINDEX, ASN_INTEGER, RONLY, var_ifEntry, 3, {2, 1, 1}},
+ {IFDESCR, ASN_OCTET_STR, RONLY, var_ifEntry, 3, {2, 1, 2}},
+ {NETSNMP_IFTYPE, ASN_INTEGER, RONLY, var_ifEntry, 3, {2, 1, 3}},
+ {IFMTU, ASN_INTEGER, RONLY, var_ifEntry, 3, {2, 1, 4}},
+ {IFSPEED, ASN_GAUGE, RONLY, var_ifEntry, 3, {2, 1, 5}},
+ {IFPHYSADDRESS, ASN_OCTET_STR, RONLY, var_ifEntry, 3, {2, 1, 6}},
+#if defined (WIN32) || defined (cygwin)
+ {IFADMINSTATUS, ASN_INTEGER, RWRITE, var_ifEntry, 3, {2, 1, 7}},
+#else
+ {IFADMINSTATUS, ASN_INTEGER, RONLY, var_ifEntry, 3, {2, 1, 7}},
+#endif
+ {IFOPERSTATUS, ASN_INTEGER, RONLY, var_ifEntry, 3, {2, 1, 8}},
+ {IFLASTCHANGE, ASN_TIMETICKS, RONLY, var_ifEntry, 3, {2, 1, 9}},
+ {IFINOCTETS, ASN_COUNTER, RONLY, var_ifEntry, 3, {2, 1, 10}},
+ {IFINUCASTPKTS, ASN_COUNTER, RONLY, var_ifEntry, 3, {2, 1, 11}},
+ {IFINNUCASTPKTS, ASN_COUNTER, RONLY, var_ifEntry, 3, {2, 1, 12}},
+ {IFINDISCARDS, ASN_COUNTER, RONLY, var_ifEntry, 3, {2, 1, 13}},
+ {IFINERRORS, ASN_COUNTER, RONLY, var_ifEntry, 3, {2, 1, 14}},
+ {IFINUNKNOWNPROTOS, ASN_COUNTER, RONLY, var_ifEntry, 3, {2, 1, 15}},
+ {IFOUTOCTETS, ASN_COUNTER, RONLY, var_ifEntry, 3, {2, 1, 16}},
+ {IFOUTUCASTPKTS, ASN_COUNTER, RONLY, var_ifEntry, 3, {2, 1, 17}},
+ {IFOUTNUCASTPKTS, ASN_COUNTER, RONLY, var_ifEntry, 3, {2, 1, 18}},
+ {IFOUTDISCARDS, ASN_COUNTER, RONLY, var_ifEntry, 3, {2, 1, 19}},
+ {IFOUTERRORS, ASN_COUNTER, RONLY, var_ifEntry, 3, {2, 1, 20}},
+ {IFOUTQLEN, ASN_GAUGE, RONLY, var_ifEntry, 3, {2, 1, 21}},
+ {IFSPECIFIC, ASN_OBJECT_ID, RONLY, var_ifEntry, 3, {2, 1, 22}}
+};
+
+/*
+ * Define the OID pointer to the top of the mib tree that we're
+ * registering underneath, and the OID of the MIB module
+ */
+oid interfaces_variables_oid[] = { SNMP_OID_MIB2, 2 };
+oid interfaces_module_oid[] = { SNMP_OID_MIB2, 31 };
+
+void
+init_interfaces(void)
+{
+ /*
+ * register ourselves with the agent to handle our mib tree
+ */
+ REGISTER_MIB("mibII/interfaces", interfaces_variables, variable3,
+ interfaces_variables_oid);
+ REGISTER_SYSOR_ENTRY(interfaces_module_oid,
+ "The MIB module to describe generic objects for network interface sub-layers");
+
+#ifndef USE_SYSCTL_IFLIST
+#if HAVE_NET_IF_MIB_H
+ init_interfaces_setup();
+#endif
+#endif
+#ifdef solaris2
+ init_kernel_sunos5();
+#endif
+}
+
+#ifdef linux
+/*
+ * if_type_from_name
+ * Return interface type using the interface name as a clue.
+ * Returns 1 to imply "other" type if name not recognized.
+ */
+static int
+if_type_from_name(const char *pcch)
+{
+ typedef struct _match_if {
+ int mi_type;
+ const char *mi_name;
+ } *pmatch_if, match_if;
+
+ static match_if lmatch_if[] = {
+ {24, "lo"},
+ {6, "eth"},
+ {9, "tr"},
+ {23, "ppp"},
+ {28, "sl"},
+ {0, 0} /* end of list */
+ };
+
+ int ii, len;
+ register pmatch_if pm;
+
+ for (ii = 0, pm = lmatch_if; pm->mi_name; pm++) {
+ len = strlen(pm->mi_name);
+ if (0 == strncmp(pcch, pm->mi_name, len)) {
+ return (pm->mi_type);
+ }
+ }
+ return (1); /* in case search fails */
+}
+#endif
+
+
+#ifdef linux
+static struct ifnet *ifnetaddr_list;
+#endif
+
+
+/*
+ * header_ifEntry(...
+ * Arguments:
+ * vp IN - pointer to variable entry that points here
+ * name IN/OUT - IN/name requested, OUT/name found
+ * length IN/OUT - length of IN/OUT oid's
+ * exact IN - TRUE if an exact match was requested
+ * var_len OUT - length of variable or 0 if function returned
+ * write_method
+ *
+ */
+#if !defined (WIN32) && !defined (cygwin)
+static int
+header_ifEntry(struct variable *vp,
+ oid * name,
+ size_t * length,
+ int exact, size_t * var_len, WriteMethod ** write_method)
+{
+#define IFENTRY_NAME_LENGTH 10
+ oid newname[MAX_OID_LEN];
+ register int interface;
+ int result, count;
+
+ DEBUGMSGTL(("mibII/interfaces", "var_ifEntry: "));
+ DEBUGMSGOID(("mibII/interfaces", name, *length));
+ DEBUGMSG(("mibII/interfaces", " %d\n", exact));
+
+ memcpy((char *) newname, (char *) vp->name,
+ (int) vp->namelen * sizeof(oid));
+ /*
+ * find "next" interface
+ */
+ count = Interface_Scan_Get_Count();
+ for (interface = 1; interface <= count; interface++) {
+ newname[IFENTRY_NAME_LENGTH] = (oid) interface;
+ result =
+ snmp_oid_compare(name, *length, newname,
+ (int) vp->namelen + 1);
+ if ((exact && (result == 0)) || (!exact && (result < 0)))
+ break;
+ }
+ if (interface > count) {
+ DEBUGMSGTL(("mibII/interfaces", "... index out of range\n"));
+ return MATCH_FAILED;
+ }
+
+
+ memcpy((char *) name, (char *) newname,
+ ((int) vp->namelen + 1) * sizeof(oid));
+ *length = vp->namelen + 1;
+ *write_method = 0;
+ *var_len = sizeof(long); /* default to 'long' results */
+
+ DEBUGMSGTL(("mibII/interfaces", "... get I/F stats "));
+ DEBUGMSGOID(("mibII/interfaces", name, *length));
+ DEBUGMSG(("mibII/interfaces", "\n"));
+
+ return interface;
+}
+
+
+
+u_char *
+var_interfaces(struct variable * vp,
+ oid * name,
+ size_t * length,
+ int exact, size_t * var_len, WriteMethod ** write_method)
+{
+ if (header_generic(vp, name, length, exact, var_len, write_method) ==
+ MATCH_FAILED)
+ return NULL;
+
+ switch (vp->magic) {
+ case IFNUMBER:
+ long_return = Interface_Scan_Get_Count();
+ return (u_char *) & long_return;
+ default:
+ DEBUGMSGTL(("snmpd", "unknown sub-id %d in var_interfaces\n",
+ vp->magic));
+ }
+ return NULL;
+}
+
+#ifdef USE_SYSCTL_IFLIST
+
+static u_char *if_list = 0;
+static const u_char *if_list_end;
+static size_t if_list_size = 0;
+
+struct small_ifaddr {
+ struct in_addr sifa_addr;
+ struct in_addr sifa_netmask;
+ struct in_addr sifa_broadcast;
+};
+
+extern const struct sockaddr *get_address(const void *, int, int);
+extern const struct in_addr *get_in_address(const void *, int, int);
+static int Interface_Scan_By_Index(int, struct if_msghdr *, char *,
+ struct small_ifaddr *);
+static int Interface_Get_Ether_By_Index(int, u_char *);
+
+static int
+Interface_Scan_By_Index(int iindex,
+ struct if_msghdr *if_msg,
+ char *if_name, struct small_ifaddr *sifa)
+{
+ u_char *cp;
+ struct if_msghdr *ifp;
+ int have_ifinfo = 0, have_addr = 0;
+
+ if (NULL != sifa)
+ memset(sifa, 0, sizeof(*sifa));
+ for (cp = if_list; cp < if_list_end; cp += ifp->ifm_msglen) {
+ ifp = (struct if_msghdr *) cp;
+ DEBUGMSGTL(("mibII/interfaces", "ifm_type = %d, ifm_index = %d\n",
+ ifp->ifm_type, ifp->ifm_index));
+
+ switch (ifp->ifm_type) {
+ case RTM_IFINFO:
+ {
+ const struct sockaddr *a;
+
+ if (ifp->ifm_index == iindex) {
+ a = get_address(ifp + 1, ifp->ifm_addrs, RTA_IFP);
+ if (a == NULL)
+ return 0;
+ strncpy(if_name,
+ ((const struct sockaddr_in *) a)->sin_zero,
+ ((const u_char *) a)[5]);
+ if_name[((const u_char *) a)[5]] = 0;
+ *if_msg = *ifp;
+ ++have_ifinfo;
+ }
+ }
+ break;
+ case RTM_NEWADDR:
+ {
+ struct ifa_msghdr *ifap = (struct ifa_msghdr *) cp;
+
+ if ((NULL != sifa) && (ifap->ifam_index == iindex)) {
+ const struct in_addr *ia;
+
+ /*
+ * I don't know why the normal get_address() doesn't
+ * work on IRIX 6.2. Maybe this has to do with the
+ * existence of struct sockaddr_new. Hopefully, on
+ * other systems we can simply use get_in_address
+ * three times, with (ifap+1) as the starting
+ * address.
+ */
+
+ sifa->sifa_netmask =
+ *((struct in_addr *) ((char *) (ifap + 1) + 4));
+ ia = get_in_address((char *) (ifap + 1) + 8,
+ ifap->ifam_addrs &=
+ ~RTA_NETMASK, RTA_IFA);
+ if (ia == NULL)
+ return 0;
+
+ sifa->sifa_addr = *ia;
+ ia = get_in_address((char *) (ifap + 1) + 8,
+ ifap->ifam_addrs &= ~RTA_NETMASK,
+ RTA_BRD);
+ if (ia == NULL)
+ return 0;
+
+ sifa->sifa_broadcast = *ia;
+ ++have_addr;
+ }
+ }
+ break;
+ default:
+ DEBUGMSGTL(("mibII/interfaces",
+ "routing socket: unknown message type %d\n",
+ ifp->ifm_type));
+ }
+ }
+ if (have_ifinfo && (NULL == sifa) || (have_addr)) {
+ return 0;
+ } else if (have_ifinfo && !(if_msg->ifm_flags & IFF_UP))
+ return 0;
+ else {
+ return -1;
+ }
+}
+
+int
+Interface_Scan_Get_Count(void)
+{
+ u_char *cp;
+ struct if_msghdr *ifp;
+ long n = 0;
+
+ Interface_Scan_Init();
+
+ if (if_list_size) {
+ for (cp = if_list, n = 0; cp < if_list_end; cp += ifp->ifm_msglen) {
+ ifp = (struct if_msghdr *) cp;
+
+ if (ifp->ifm_type == RTM_IFINFO) {
+ ++n;
+ }
+ }
+ }
+ return n;
+}
+
+void
+Interface_Scan_Init(void)
+{
+ int name[] = { CTL_NET, PF_ROUTE, 0, 0, NET_RT_IFLIST, 0 };
+ size_t size;
+
+ if (sysctl(name, sizeof(name) / sizeof(int), 0, &size, 0, 0) == -1) {
+ snmp_log(LOG_ERR, "sysctl size fail\n");
+ } else {
+ if (if_list == 0 || if_list_size < size) {
+ if (if_list != 0) {
+ free(if_list);
+ }
+ if_list = NULL;
+ if_list_size = 0;
+ if_list_end = 0;
+ if ((if_list = malloc(size)) == NULL) {
+ snmp_log(LOG_ERR,
+ "out of memory allocating route table (size = %d)\n", size);
+ return;
+ }
+ if_list_size = size;
+ } else {
+ size = if_list_size;
+ }
+ if (sysctl(name, sizeof(name) / sizeof(int),
+ if_list, &size, 0, 0) == -1) {
+ snmp_log(LOG_ERR, "sysctl get fail\n");
+ }
+ if_list_end = if_list + size;
+ }
+}
+
+u_char *
+var_ifEntry(struct variable *vp,
+ oid * name,
+ size_t * length,
+ int exact, size_t * var_len, WriteMethod ** write_method)
+{
+ int interface;
+ struct if_msghdr if_msg;
+ static char if_name[100];
+ conf_if_list *if_ptr;
+ char *cp;
+
+ interface =
+ header_ifEntry(vp, name, length, exact, var_len, write_method);
+ if (interface == MATCH_FAILED)
+ return NULL;
+
+ if (Interface_Scan_By_Index(interface, &if_msg, if_name, NULL) != 0)
+ return NULL;
+ if_ptr = netsnmp_access_interface_entry_overrides_get(if_name);
+
+ switch (vp->magic) {
+ case IFINDEX:
+ long_return = interface;
+ return (u_char *) & long_return;
+ case IFDESCR:
+ cp = if_name;
+ *var_len = strlen(if_name);
+ return (u_char *) cp;
+ case NETSNMP_IFTYPE:
+ if (if_ptr)
+ long_return = if_ptr->type;
+ else
+ long_return = (long) if_msg.ifm_data.ifi_type;
+ return (u_char *) & long_return;
+ case IFMTU:
+ long_return = (long) if_msg.ifm_data.ifi_mtu;
+ return (u_char *) & long_return;
+ case IFSPEED:
+ if (if_ptr)
+ long_return = if_ptr->speed;
+ else {
+#if STRUCT_IFNET_HAS_IF_BAUDRATE_IFS_VALUE
+ long_return = (u_long) if_msg.ifm_data.ifi_baudrate.ifs_value <<
+ if_msg.ifm_data.ifi_baudrate.ifs_log2;
+#else
+ long_return = (u_long) if_msg.ifm_data.ifi_baudrate;
+#endif
+ }
+ return (u_char *) & long_return;
+ case IFPHYSADDRESS:
+ /*
+ * XXX
+ */
+ return NULL;
+ case IFADMINSTATUS:
+ long_return = if_msg.ifm_flags & IFF_UP ? 1 : 2;
+ return (u_char *) & long_return;
+ case IFOPERSTATUS:
+ long_return = if_msg.ifm_flags & IFF_RUNNING ? 1 : 2;
+ return (u_char *) & long_return;
+ /*
+ * ifLastChange
+ */
+ case IFINOCTETS:
+ long_return = (u_long) if_msg.ifm_data.ifi_ibytes;
+ return (u_char *) & long_return;
+ case IFINUCASTPKTS:
+ long_return =
+ (u_long) if_msg.ifm_data.ifi_ipackets -
+ if_msg.ifm_data.ifi_imcasts;
+ return (u_char *) & long_return;
+ case IFINNUCASTPKTS:
+ long_return = (u_long) if_msg.ifm_data.ifi_imcasts;
+ return (u_char *) & long_return;
+ case IFINDISCARDS:
+ long_return = (u_long) if_msg.ifm_data.ifi_iqdrops;
+ return (u_char *) & long_return;
+ case IFINERRORS:
+ long_return = (u_long) if_msg.ifm_data.ifi_ierrors;
+ return (u_char *) & long_return;
+ case IFINUNKNOWNPROTOS:
+ long_return = (u_long) if_msg.ifm_data.ifi_noproto;
+ return (u_char *) & long_return;
+ case IFOUTOCTETS:
+ long_return = (u_long) if_msg.ifm_data.ifi_obytes;
+ return (u_char *) & long_return;
+ case IFOUTUCASTPKTS:
+ long_return =
+ (u_long) if_msg.ifm_data.ifi_opackets -
+ if_msg.ifm_data.ifi_omcasts;
+ return (u_char *) & long_return;
+ case IFOUTNUCASTPKTS:
+ long_return = (u_long) if_msg.ifm_data.ifi_omcasts;
+ return (u_char *) & long_return;
+ case IFOUTDISCARDS:
+#ifdef if_odrops
+ long_return = (u_long) if_msg.ifm_data.ifi_odrops;
+#else
+#if NETSNMP_NO_DUMMY_VALUES
+ return NULL;
+#endif
+ long_return = 0;
+#endif
+ return (u_char *) & long_return;
+ case IFOUTERRORS:
+ long_return = (u_long) if_msg.ifm_data.ifi_oerrors;
+ return (u_char *) & long_return;
+ case IFLASTCHANGE:
+#ifdef irix6
+ long_return = 0;
+#else
+ if (if_msg.ifm_data.ifi_lastchange.tv_sec == 0 &&
+ if_msg.ifm_data.ifi_lastchange.tv_usec == 0)
+ long_return = 0;
+ else if (if_msg.ifm_data.ifi_lastchange.tv_sec < starttime.tv_sec)
+ long_return = 0;
+ else {
+ long_return = (u_long)
+ ((if_msg.ifm_data.ifi_lastchange.tv_sec -
+ starttime.tv_sec) * 100 +
+ (if_msg.ifm_data.ifi_lastchange.tv_usec -
+ starttime.tv_usec) / 10000);
+ }
+#endif
+ return (u_char *) & long_return;
+ default:
+ return 0;
+ }
+}
+
+int
+Interface_Scan_Next(short *Index,
+ char *Name,
+ struct ifnet *Retifnet, struct in_ifaddr *Retin_ifaddr)
+{
+ return 0;
+}
+
+#else /* not USE_SYSCTL_IFLIST */
+
+ /*********************
+ *
+ * Kernel & interface information,
+ * and internal forward declarations
+ *
+ *********************/
+
+#ifndef HAVE_NET_IF_MIB_H
+
+#ifndef solaris2
+#ifndef hpux11
+static int Interface_Scan_By_Index(int, char *, struct ifnet *,
+ struct in_ifaddr *);
+static int Interface_Get_Ether_By_Index(int, u_char *);
+#else
+static int Interface_Scan_By_Index(int, char *, nmapi_phystat *);
+#endif
+#endif
+
+
+
+ /*********************
+ *
+ * System specific implementation functions
+ *
+ *********************/
+
+
+#ifndef solaris2
+#ifndef hpux
+
+u_char *
+var_ifEntry(struct variable *vp,
+ oid * name,
+ size_t * length,
+ int exact, size_t * var_len, WriteMethod ** write_method)
+{
+ static struct ifnet ifnet;
+ int interface;
+ static struct in_ifaddr in_ifaddr;
+ static char Name[16];
+ char *cp;
+ conf_if_list *if_ptr;
+#if STRUCT_IFNET_HAS_IF_LASTCHANGE_TV_SEC
+ struct timeval now;
+#endif
+
+ interface =
+ header_ifEntry(vp, name, length, exact, var_len, write_method);
+ if (interface == MATCH_FAILED)
+ return NULL;
+
+ Interface_Scan_By_Index(interface, Name, &ifnet, &in_ifaddr);
+ if_ptr = netsnmp_access_interface_entry_overrides_get(Name);
+
+ switch (vp->magic) {
+ case IFINDEX:
+ long_return = interface;
+ return (u_char *) & long_return;
+ case IFDESCR:
+ cp = Name;
+ *var_len = strlen(cp);
+ return (u_char *) cp;
+ case NETSNMP_IFTYPE:
+ if (if_ptr)
+ long_return = if_ptr->type;
+ else {
+#if STRUCT_IFNET_HAS_IF_TYPE
+ long_return = ifnet.if_type;
+#else
+ long_return = 1; /* OTHER */
+#endif
+ }
+ return (u_char *) & long_return;
+ case IFMTU:{
+ long_return = (long) ifnet.if_mtu;
+ return (u_char *) & long_return;
+ }
+ case IFSPEED:
+ if (if_ptr)
+ long_return = if_ptr->speed;
+ else {
+#if STRUCT_IFNET_HAS_IF_BAUDRATE
+ long_return = ifnet.if_baudrate;
+#elif STRUCT_IFNET_HAS_IF_SPEED
+ long_return = ifnet.if_speed;
+#elif STRUCT_IFNET_HAS_IF_TYPE && defined(IFT_ETHER)
+ if (ifnet.if_type == IFT_ETHER)
+ long_return = 10000000;
+ if (ifnet.if_type == IFT_P10)
+ long_return = 10000000;
+ if (ifnet.if_type == IFT_P80)
+ long_return = 80000000;
+ if (ifnet.if_type == IFT_ISDNBASIC)
+ long_return = 64000; /* EDSS1 only */
+ if (ifnet.if_type == IFT_ISDNPRIMARY)
+ long_return = 64000 * 30;
+#else
+#if NETSNMP_NO_DUMMY_VALUES
+ return NULL;
+#endif
+ long_return = (u_long) 10000000;
+#endif
+ }
+ return (u_char *) & long_return;
+ case IFPHYSADDRESS:
+ Interface_Get_Ether_By_Index(interface, return_buf);
+#if defined(aix4) || defined(aix5) || defined(aix6)
+ *var_len = 0;
+#else
+ if ((return_buf[0] == 0) && (return_buf[1] == 0) &&
+ (return_buf[2] == 0) && (return_buf[3] == 0) &&
+ (return_buf[4] == 0) && (return_buf[5] == 0))
+ *var_len = 0;
+ else
+ *var_len = 6;
+#endif
+ return (u_char *) return_buf;
+ case IFADMINSTATUS:
+ long_return = ifnet.if_flags & IFF_UP ? 1 : 2;
+ return (u_char *) & long_return;
+ case IFOPERSTATUS:
+ long_return = ifnet.if_flags & IFF_RUNNING ? 1 : 2;
+ return (u_char *) & long_return;
+ case IFLASTCHANGE:
+#if defined(STRUCT_IFNET_HAS_IF_LASTCHANGE_TV_SEC) && !(defined(freebsd2) && __FreeBSD_version < 199607)
+ /*
+ * XXX - SNMP's ifLastchange is time when op. status changed
+ * * FreeBSD's if_lastchange is time when packet was input or output
+ * * (at least in 2.1.0-RELEASE. Changed in later versions of the kernel?)
+ */
+ /*
+ * FreeBSD's if_lastchange before the 2.1.5 release is the time when
+ * * a packet was last input or output. In the 2.1.5 and later releases,
+ * * this is fixed, thus the 199607 comparison.
+ */
+ if (ifnet.if_lastchange.tv_sec == 0 &&
+ ifnet.if_lastchange.tv_usec == 0)
+ long_return = 0;
+ else if (ifnet.if_lastchange.tv_sec < starttime.tv_sec)
+ long_return = 0;
+ else {
+ long_return = (u_long)
+ ((ifnet.if_lastchange.tv_sec - starttime.tv_sec) * 100
+ + (ifnet.if_lastchange.tv_usec -
+ starttime.tv_usec) / 10000);
+ }
+#else
+#if NETSNMP_NO_DUMMY_VALUES
+ return NULL;
+#endif
+ long_return = 0; /* XXX */
+#endif
+ return (u_char *) & long_return;
+ case IFINOCTETS:
+#ifdef STRUCT_IFNET_HAS_IF_IBYTES
+#if defined(aix4) || defined(aix5) || defined(aix6)
+ long_return = (u_long) ifnet.if_ibytes & 0xffffffff;
+#else
+ long_return = (u_long) ifnet.if_ibytes;
+#endif
+#else
+#if NETSNMP_NO_DUMMY_VALUES
+ return NULL;
+#endif
+ long_return = (u_long) ifnet.if_ipackets * 308; /* XXX */
+#endif
+ return (u_char *) & long_return;
+ case IFINUCASTPKTS:
+ {
+#if defined(aix4) || defined(aix5) || defined(aix6)
+ long_return = (u_long) ifnet.if_ipackets & 0xffffffff;
+#else
+ long_return = (u_long) ifnet.if_ipackets;
+#endif
+#if STRUCT_IFNET_HAS_IF_IMCASTS
+#if defined(aix4) || defined(aix5) || defined(aix6)
+ long_return -= (u_long) ifnet.if_imcasts & 0xffffffff;
+#else
+ long_return -= (u_long) ifnet.if_imcasts;
+#endif
+#endif
+ }
+ return (u_char *) & long_return;
+ case IFINNUCASTPKTS:
+#if STRUCT_IFNET_HAS_IF_IMCASTS
+#if defined(aix4) || defined(aix5) || defined(aix6)
+ long_return = (u_long) ifnet.if_imcasts & 0xffffffff;
+#else
+ long_return = (u_long) ifnet.if_imcasts;
+#endif
+#else
+#if NETSNMP_NO_DUMMY_VALUES
+ return NULL;
+#endif
+ long_return = (u_long) 0; /* XXX */
+#endif
+ return (u_char *) & long_return;
+ case IFINDISCARDS:
+#if STRUCT_IFNET_HAS_IF_IQDROPS
+#if defined(aix4) || defined(aix5) || defined(aix6)
+ long_return = (u_long) ifnet.if_iqdrops & 0xffffffff;
+#else
+ long_return = (u_long) ifnet.if_iqdrops;
+#endif
+#else
+#if NETSNMP_NO_DUMMY_VALUES
+ return NULL;
+#endif
+ long_return = (u_long) 0; /* XXX */
+#endif
+ return (u_char *) & long_return;
+ case IFINERRORS:
+#if defined(aix4) || defined(aix5) || defined(aix6)
+ long_return = (u_long) ifnet.if_ierrors & 0xffffffff;
+#else
+ long_return = (u_long) ifnet.if_ierrors;
+#endif
+ return (u_char *) & long_return;
+ case IFINUNKNOWNPROTOS:
+#if STRUCT_IFNET_HAS_IF_NOPROTO
+#if defined(aix4) || defined(aix5) || defined(aix6)
+ long_return = (u_long) ifnet.if_noproto & 0xffffffff;
+#else
+ long_return = (u_long) ifnet.if_noproto;
+#endif
+#else
+#if NETSNMP_NO_DUMMY_VALUES
+ return NULL;
+#endif
+ long_return = (u_long) 0; /* XXX */
+#endif
+ return (u_char *) & long_return;
+ case IFOUTOCTETS:
+#ifdef STRUCT_IFNET_HAS_IF_OBYTES
+#if defined(aix4) || defined(aix5) || defined(aix6)
+ long_return = (u_long) ifnet.if_obytes & 0xffffffff;
+#else
+ long_return = (u_long) ifnet.if_obytes;
+#endif
+#else
+#if NETSNMP_NO_DUMMY_VALUES
+ return NULL;
+#endif
+ long_return = (u_long) ifnet.if_opackets * 308; /* XXX */
+#endif
+ return (u_char *) & long_return;
+ case IFOUTUCASTPKTS:
+ {
+#if defined(aix4) || defined(aix5) || defined(aix6)
+ long_return = (u_long) ifnet.if_opackets & 0xffffffff;
+#else
+ long_return = (u_long) ifnet.if_opackets;
+#endif
+#if STRUCT_IFNET_HAS_IF_OMCASTS
+#if defined(aix4) || defined(aix5) || defined(aix6)
+ long_return -= (u_long) ifnet.if_omcasts & 0xffffffff;
+#else
+ long_return -= (u_long) ifnet.if_omcasts;
+#endif
+#endif
+ }
+ return (u_char *) & long_return;
+ case IFOUTNUCASTPKTS:
+#if STRUCT_IFNET_HAS_IF_OMCASTS
+#if defined(aix4) || defined(aix5) || defined(aix6)
+ long_return = (u_long) ifnet.if_omcasts & 0xffffffff;
+#else
+ long_return = (u_long) ifnet.if_omcasts;
+#endif
+#else
+#if NETSNMP_NO_DUMMY_VALUES
+ return NULL;
+#endif
+ long_return = (u_long) 0; /* XXX */
+#endif
+ return (u_char *) & long_return;
+ case IFOUTDISCARDS:
+#if defined(aix4) || defined(aix5) || defined(aix6)
+ long_return = ifnet.if_snd.ifq_drops & 0xffffffff;
+#else
+ long_return = ifnet.if_snd.ifq_drops;
+#endif
+ return (u_char *) & long_return;
+ case IFOUTERRORS:
+#if defined(aix4) || defined(aix5) || defined(aix6)
+ long_return = ifnet.if_oerrors & 0xffffffff;
+#else
+ long_return = ifnet.if_oerrors;
+#endif
+ return (u_char *) & long_return;
+ case IFOUTQLEN:
+#if defined(aix4) || defined(aix5) || defined(aix6)
+ long_return = ifnet.if_snd.ifq_len & 0xffffffff;
+#else
+ long_return = ifnet.if_snd.ifq_len;
+#endif
+ return (u_char *) & long_return;
+ case IFSPECIFIC:
+ *var_len = nullOidLen;
+ return (u_char *) nullOid;
+ default:
+ DEBUGMSGTL(("snmpd", "unknown sub-id %d in var_ifEntry\n",
+ vp->magic));
+ }
+ return NULL;
+}
+
+#else /* hpux */
+
+u_char *
+var_ifEntry(struct variable *vp,
+ oid * name,
+ size_t * length,
+ int exact, size_t * var_len, WriteMethod ** write_method)
+{
+#if defined(hpux11)
+ static nmapi_phystat ifnet;
+#else
+ static struct ifnet ifnet;
+#endif
+ register int interface;
+#if !defined(hpux11)
+ static struct in_ifaddr in_ifaddrVar;
+#endif
+#if defined(hpux11)
+ static char Name[MAX_PHYSADDR_LEN];
+#else
+ static char Name[16];
+#endif
+ register char *cp;
+#if STRUCT_IFNET_HAS_IF_LASTCHANGE_TV_SEC
+ struct timeval now;
+#endif
+#if !defined(hpux11)
+ struct nmparms hp_nmparms;
+ static mib_ifEntry hp_ifEntry;
+ int hp_fd;
+ int hp_len = sizeof(hp_ifEntry);
+#endif
+ conf_if_list *if_ptr;
+
+ interface =
+ header_ifEntry(vp, name, length, exact, var_len, write_method);
+ if (interface == MATCH_FAILED)
+ return NULL;
+
+#if defined(hpux11)
+ Interface_Scan_By_Index(interface, Name, &ifnet);
+#else
+ Interface_Scan_By_Index(interface, Name, &ifnet, &in_ifaddrVar);
+#endif
+
+#if !defined(hpux11)
+ /*
+ * Additional information about the interfaces is available under
+ * HP-UX through the network management interface '/dev/netman'
+ */
+ hp_ifEntry.ifIndex = interface;
+ hp_nmparms.objid = ID_ifEntry;
+ hp_nmparms.buffer = (char *) &hp_ifEntry;
+ hp_nmparms.len = &hp_len;
+ if ((hp_fd = open("/dev/netman", O_RDONLY)) != -1) {
+ if (ioctl(hp_fd, NMIOGET, &hp_nmparms) != -1) {
+ close(hp_fd);
+ } else {
+ close(hp_fd);
+ hp_fd = -1; /* failed */
+ }
+ }
+#endif
+ if_ptr = netsnmp_access_interface_entry_overrides_get(Name);
+
+ switch (vp->magic) {
+ case IFINDEX:
+ long_return = interface;
+ return (u_char *) & long_return;
+ case IFDESCR:
+#if defined(hpux11)
+ cp = ifnet.if_entry.ifDescr;
+#else
+ if (hp_fd != -1)
+ cp = hp_ifEntry.ifDescr;
+ else
+ cp = Name;
+#endif
+ *var_len = strlen(cp);
+ return (u_char *) cp;
+ case NETSNMP_IFTYPE:
+ if (if_ptr)
+ long_return = if_ptr->type;
+ else {
+#if defined(hpux11)
+ long_return = ifnet.if_entry.ifType;
+#else
+ if (hp_fd != -1)
+ long_return = hp_ifEntry.ifType;
+ else
+ long_return = 1; /* OTHER */
+#endif
+ }
+ return (u_char *) & long_return;
+ case IFMTU:{
+#if defined(hpux11)
+ long_return = (long) ifnet.if_entry.ifMtu;
+#else
+ long_return = (long) ifnet.if_mtu;
+#endif
+ return (u_char *) & long_return;
+ }
+ case IFSPEED:
+ if (if_ptr)
+ long_return = if_ptr->speed;
+ else {
+#if defined(hpux11)
+ long_return = ifnet.if_entry.ifSpeed;
+#else
+ if (hp_fd != -1)
+ long_return = hp_ifEntry.ifSpeed;
+ else
+ long_return = (u_long) 1; /* OTHER */
+#endif
+ }
+ return (u_char *) & long_return;
+ case IFPHYSADDRESS:
+#if defined(hpux11)
+ *var_len = ifnet.if_entry.ifPhysAddress.o_length;
+ return (u_char *) ifnet.if_entry.ifPhysAddress.o_bytes;
+#else
+ Interface_Get_Ether_By_Index(interface, return_buf);
+ if ((return_buf[0] == 0) && (return_buf[1] == 0) &&
+ (return_buf[2] == 0) && (return_buf[3] == 0) &&
+ (return_buf[4] == 0) && (return_buf[5] == 0))
+ *var_len = 0;
+ else
+ *var_len = 6;
+ return (u_char *) return_buf;
+#endif
+ case IFADMINSTATUS:
+#if defined(hpux11)
+ long_return = ifnet.if_entry.ifAdmin;
+#else
+ long_return = ifnet.if_flags & IFF_UP ? 1 : 2;
+#endif
+ return (u_char *) & long_return;
+ case IFOPERSTATUS:
+#if defined(hpux11)
+ long_return = ifnet.if_entry.ifOper;
+#else
+ long_return = ifnet.if_flags & IFF_RUNNING ? 1 : 2;
+#endif
+ return (u_char *) & long_return;
+ case IFLASTCHANGE:
+#if defined(hpux11)
+ long_return = ifnet.if_entry.ifLastChange;
+#else
+ if (hp_fd != -1)
+ long_return = hp_ifEntry.ifLastChange;
+ else
+ long_return = 0; /* XXX */
+#endif
+ return (u_char *) & long_return;
+ case IFINOCTETS:
+#if defined(hpux11)
+ long_return = ifnet.if_entry.ifInOctets;
+#else
+ if (hp_fd != -1)
+ long_return = hp_ifEntry.ifInOctets;
+ else
+ long_return = (u_long) ifnet.if_ipackets * 308; /* XXX */
+#endif
+ return (u_char *) & long_return;
+ case IFINUCASTPKTS:
+#if defined(hpux11)
+ long_return = ifnet.if_entry.ifInUcastPkts;
+#else
+ if (hp_fd != -1)
+ long_return = hp_ifEntry.ifInUcastPkts;
+ else
+ long_return = (u_long) ifnet.if_ipackets;
+#endif
+ return (u_char *) & long_return;
+ case IFINNUCASTPKTS:
+#if defined(hpux11)
+ long_return = ifnet.if_entry.ifInNUcastPkts;
+#else
+ if (hp_fd != -1)
+ long_return = hp_ifEntry.ifInNUcastPkts;
+ else
+ long_return = (u_long) 0; /* XXX */
+#endif
+ return (u_char *) & long_return;
+ case IFINDISCARDS:
+#if defined(hpux11)
+ long_return = ifnet.if_entry.ifInDiscards;
+#else
+ if (hp_fd != -1)
+ long_return = hp_ifEntry.ifInDiscards;
+ else
+ long_return = (u_long) 0; /* XXX */
+#endif
+ return (u_char *) & long_return;
+ case IFINERRORS:
+#if defined(hpux11)
+ long_return = ifnet.if_entry.ifInErrors;
+#else
+ long_return = ifnet.if_ierrors;
+#endif
+ return (u_char *) & long_return;
+ case IFINUNKNOWNPROTOS:
+#if defined(hpux11)
+ long_return = ifnet.if_entry.ifInUnknownProtos;
+#else
+ if (hp_fd != -1)
+ long_return = hp_ifEntry.ifInUnknownProtos;
+ else
+ long_return = (u_long) 0; /* XXX */
+#endif
+ return (u_char *) & long_return;
+ case IFOUTOCTETS:
+#if defined(hpux11)
+ long_return = ifnet.if_entry.ifOutOctets;
+#else
+ if (hp_fd != -1)
+ long_return = hp_ifEntry.ifOutOctets;
+ else
+ long_return = (u_long) ifnet.if_opackets * 308; /* XXX */
+#endif
+ return (u_char *) & long_return;
+ case IFOUTUCASTPKTS:
+#if defined(hpux11)
+ long_return = ifnet.if_entry.ifOutUcastPkts;
+#else
+ if (hp_fd != -1)
+ long_return = hp_ifEntry.ifOutUcastPkts;
+ else
+ long_return = (u_long) ifnet.if_opackets;
+#endif
+ return (u_char *) & long_return;
+ case IFOUTNUCASTPKTS:
+#if defined(hpux11)
+ long_return = ifnet.if_entry.ifOutNUcastPkts;
+#else
+ if (hp_fd != -1)
+ long_return = hp_ifEntry.ifOutNUcastPkts;
+ else
+ long_return = (u_long) 0; /* XXX */
+#endif
+ return (u_char *) & long_return;
+ case IFOUTDISCARDS:
+#if defined(hpux11)
+ long_return = ifnet.if_entry.ifOutDiscards;
+#else
+ long_return = ifnet.if_snd.ifq_drops;
+#endif
+ return (u_char *) & long_return;
+ case IFOUTERRORS:
+#if defined(hpux11)
+ long_return = ifnet.if_entry.ifOutErrors;
+#else
+ long_return = ifnet.if_oerrors;
+#endif
+ return (u_char *) & long_return;
+ case IFOUTQLEN:
+#if defined(hpux11)
+ long_return = ifnet.if_entry.ifOutQlen;
+#else
+ long_return = ifnet.if_snd.ifq_len;
+#endif
+ return (u_char *) & long_return;
+ case IFSPECIFIC:
+ *var_len = nullOidLen;
+ return (u_char *) nullOid;
+ default:
+ DEBUGMSGTL(("snmpd", "unknown sub-id %d in var_ifEntry\n",
+ vp->magic));
+ }
+ return NULL;
+}
+
+#endif /* hpux */
+#else /* solaris2 */
+
+static int
+IF_cmp(void *addr, void *ep)
+{
+ DEBUGMSGTL(("mibII/interfaces", "... IF_cmp %d %d\n",
+ ((mib2_ifEntry_t *) ep)->ifIndex,
+ ((mib2_ifEntry_t *) addr)->ifIndex));
+ if (((mib2_ifEntry_t *) ep)->ifIndex ==
+ ((mib2_ifEntry_t *) addr)->ifIndex)
+ return (0);
+ else
+ return (1);
+}
+
+u_char *
+var_ifEntry(struct variable * vp,
+ oid * name,
+ size_t * length,
+ int exact, size_t * var_len, WriteMethod ** write_method)
+{
+ int interface;
+ mib2_ifEntry_t ifstat;
+ conf_if_list *if_ptr = NULL;
+
+ interface =
+ header_ifEntry(vp, name, length, exact, var_len, write_method);
+ if (interface == MATCH_FAILED)
+ return NULL;
+
+ if (getMibstat(MIB_INTERFACES, &ifstat, sizeof(mib2_ifEntry_t),
+ GET_EXACT, &IF_cmp, &interface) != 0) {
+ DEBUGMSGTL(("mibII/interfaces", "... no mib stats\n"));
+ return NULL;
+ }
+ /*
+ * hmmm.. where to get the interface name to check overrides?
+ *
+ * if_ptr = netsnmp_access_interface_entry_overrides_get(Name);
+ */
+ switch (vp->magic) {
+ case IFINDEX:
+ long_return = ifstat.ifIndex;
+ return (u_char *) & long_return;
+ case IFDESCR:
+ *var_len = ifstat.ifDescr.o_length;
+ (void) memcpy(return_buf, ifstat.ifDescr.o_bytes, *var_len);
+ return (u_char *) return_buf;
+ case NETSNMP_IFTYPE:
+ if (if_ptr)
+ long_return = if_ptr->type;
+ else
+ long_return = (u_long) ifstat.ifType;
+ return (u_char *) & long_return;
+ case IFMTU:
+ long_return = (u_long) ifstat.ifMtu;
+ return (u_char *) & long_return;
+ case IFSPEED:
+ if (if_ptr)
+ long_return = if_ptr->speed;
+ else
+ long_return = (u_long) ifstat.ifSpeed;
+ return (u_char *) & long_return;
+ case IFPHYSADDRESS:
+ *var_len = ifstat.ifPhysAddress.o_length;
+ (void) memcpy(return_buf, ifstat.ifPhysAddress.o_bytes, *var_len);
+ return (u_char *) return_buf;
+ case IFADMINSTATUS:
+ long_return = (u_long) ifstat.ifAdminStatus;
+ return (u_char *) & long_return;
+ case IFOPERSTATUS:
+ long_return = (u_long) ifstat.ifOperStatus;
+ return (u_char *) & long_return;
+ case IFLASTCHANGE:
+ long_return = (u_long) ifstat.ifLastChange;
+ return (u_char *) & long_return;
+ case IFINOCTETS:
+ long_return = (u_long) ifstat.ifInOctets;
+ return (u_char *) & long_return;
+ case IFINUCASTPKTS:
+ long_return = (u_long) ifstat.ifInUcastPkts;
+ return (u_char *) & long_return;
+ case IFINNUCASTPKTS:
+ long_return = (u_long) ifstat.ifInNUcastPkts;
+ return (u_char *) & long_return;
+ case IFINDISCARDS:
+ long_return = (u_long) ifstat.ifInDiscards;
+ return (u_char *) & long_return;
+ case IFINERRORS:
+ long_return = (u_long) ifstat.ifInErrors;
+ return (u_char *) & long_return;
+ case IFINUNKNOWNPROTOS:
+ long_return = (u_long) ifstat.ifInUnknownProtos;
+ return (u_char *) & long_return;
+ case IFOUTOCTETS:
+ long_return = (u_long) ifstat.ifOutOctets;
+ return (u_char *) & long_return;
+ case IFOUTUCASTPKTS:
+ long_return = (u_long) ifstat.ifOutUcastPkts;
+ return (u_char *) & long_return;
+ case IFOUTNUCASTPKTS:
+ long_return = (u_long) ifstat.ifOutNUcastPkts;
+ return (u_char *) & long_return;
+ case IFOUTDISCARDS:
+ long_return = (u_long) ifstat.ifOutDiscards;
+ return (u_char *) & long_return;
+ case IFOUTERRORS:
+ long_return = (u_long) ifstat.ifOutErrors;
+ return (u_char *) & long_return;
+ case IFOUTQLEN:
+ long_return = (u_long) ifstat.ifOutQLen;
+ return (u_char *) & long_return;
+ case IFSPECIFIC:
+ long_return = (u_long) ifstat.ifSpecific;
+ return (u_char *) & long_return;
+ default:
+ DEBUGMSGTL(("snmpd", "unknown sub-id %d in var_ifEntry\n",
+ vp->magic));
+ }
+ return NULL;
+}
+
+#endif /* solaris2 */
+
+
+
+ /*********************
+ *
+ * Internal implementation functions
+ *
+ *********************/
+
+
+#ifndef solaris2
+
+#if !defined(sunV3) && !defined(linux) && !defined(hpux11)
+static struct in_ifaddr savein_ifaddr;
+#endif
+#if !defined(hpux11)
+static struct ifnet *ifnetaddr, saveifnet, *saveifnetaddr;
+static char saveName[16];
+#endif
+static int saveIndex = 0;
+
+/**
+* Determines network interface speed. It is system specific. Only linux
+* realization is made.
+*/
+unsigned int getIfSpeed(int fd, struct ifreq ifr, unsigned int defaultspeed)
+{
+#ifdef linux
+ /** temporary expose internal until this module can be re-written */
+ extern unsigned int
+ netsnmp_linux_interface_get_if_speed(int fd, const char *name,
+ unsigned long long defaultspeed);
+
+ return netsnmp_linux_interface_get_if_speed(fd, ifr.ifr_name, defaultspeed);
+#else /*!linux*/
+ return defaultspeed;
+#endif
+}
+
+void
+Interface_Scan_Init(void)
+{
+#ifdef linux
+ char line[256], ifname_buf[64], *ifname, *ptr;
+ struct ifreq ifrq;
+ struct ifnet **ifnetaddr_ptr;
+ FILE *devin;
+ int i, fd;
+ conf_if_list *if_ptr;
+ /*
+ * scanline_2_2:
+ * [ IN ]
+ * byte pkts errs drop fifo frame cmprs mcst |
+ * [ OUT ]
+ * byte pkts errs drop fifo colls carrier compressed
+ */
+#ifdef SCNuMAX
+ uintmax_t rec_pkt, rec_oct, rec_err, rec_drop;
+ uintmax_t snd_pkt, snd_oct, snd_err, snd_drop, coll;
+ const char *scan_line_2_2 =
+ "%" SCNuMAX " %" SCNuMAX " %" SCNuMAX " %" SCNuMAX
+ " %*" SCNuMAX " %*" SCNuMAX " %*" SCNuMAX " %*" SCNuMAX
+ " %" SCNuMAX " %" SCNuMAX " %" SCNuMAX " %" SCNuMAX
+ " %*" SCNuMAX " %" SCNuMAX;
+ const char *scan_line_2_0 =
+ "%" SCNuMAX " %" SCNuMAX " %*" SCNuMAX " %*" SCNuMAX
+ " %*" SCNuMAX " %" SCNuMAX " %" SCNuMAX " %*" SCNuMAX
+ " %*" SCNuMAX " %" SCNuMAX;
+#else
+ unsigned long rec_pkt, rec_oct, rec_err, rec_drop;
+ unsigned long snd_pkt, snd_oct, snd_err, snd_drop, coll;
+ const char *scan_line_2_2 =
+ "%lu %lu %lu %lu %*lu %*lu %*lu %*lu %lu %lu %lu %lu %*lu %lu";
+ const char *scan_line_2_0 =
+ "%lu %lu %*lu %*lu %*lu %lu %lu %*lu %*lu %lu";
+#endif
+ const char *scan_line_to_use;
+ struct timeval et; /* elapsed time */
+
+#endif
+
+#if !defined(hpux11) && defined(IFNET_SYMBOL)
+ auto_nlist(IFNET_SYMBOL, (char *) &ifnetaddr, sizeof(ifnetaddr));
+#endif
+ saveIndex = 0;
+
+
+#ifdef linux
+ /* disallow reloading of structures too often */
+ gettimeofday ( &et, ( struct timezone * ) 0 ); /* get time-of-day */
+ if ( et.tv_sec < LastLoad + MINLOADFREQ ) { /* only reload so often */
+ ifnetaddr = ifnetaddr_list; /* initialize pointer */
+ return;
+ }
+ LastLoad = et.tv_sec;
+
+ /*
+ * free old list:
+ */
+ while (ifnetaddr_list) {
+ struct ifnet *old = ifnetaddr_list;
+ ifnetaddr_list = ifnetaddr_list->if_next;
+ free(old->if_name);
+ free(old->if_unit);
+ free(old);
+ }
+
+ ifnetaddr = 0;
+ ifnetaddr_ptr = &ifnetaddr_list;
+
+ if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
+ DEBUGMSGTL(("snmpd",
+ "socket open failure in Interface_Scan_Init\n"));
+ return; /** exit (1); **/
+ }
+
+ /*
+ * build up ifnetaddr list by hand:
+ */
+
+ /*
+ * at least linux v1.3.53 says EMFILE without reason...
+ */
+ if (!(devin = fopen("/proc/net/dev", "r"))) {
+ close(fd);
+ snmp_log(LOG_ERR, "cannot open /proc/net/dev - continuing...\n");
+ return; /** exit (1); **/
+ }
+
+ i = 0;
+
+ /*
+ * read the second line (a header) and determine the fields we
+ * should read from. This should be done in a better way by
+ * actually looking for the field names we want. But thats too
+ * much work for today. -- Wes
+ */
+ fgets(line, sizeof(line), devin);
+ fgets(line, sizeof(line), devin);
+ if (strstr(line, "compressed")) {
+ scan_line_to_use = scan_line_2_2;
+ DEBUGMSGTL(("mibII/interfaces",
+ "using linux 2.2 kernel /proc/net/dev\n"));
+ } else {
+ scan_line_to_use = scan_line_2_0;
+ DEBUGMSGTL(("mibII/interfaces",
+ "using linux 2.0 kernel /proc/net/dev\n"));
+ }
+
+
+ while (fgets(line, sizeof(line), devin)) {
+ struct ifnet *nnew;
+ char *stats, *ifstart = line;
+
+ if (line[strlen(line) - 1] == '\n')
+ line[strlen(line) - 1] = '\0';
+
+ while (*ifstart && *ifstart == ' ')
+ ifstart++;
+
+ if (!*ifstart || ((stats = strrchr(ifstart, ':')) == NULL)) {
+ snmp_log(LOG_ERR,
+ "/proc/net/dev data format error, line ==|%s|", line);
+ continue;
+ }
+ if ((scan_line_to_use == scan_line_2_2) && ((stats - line) < 6)) {
+ snmp_log(LOG_ERR,
+ "/proc/net/dev data format error, line ==|%s|", line);
+ }
+
+ *stats = 0;
+ strncpy(ifname_buf, ifstart, sizeof(ifname_buf));
+ ifname_buf[ sizeof(ifname_buf)-1 ] = 0;
+ *stats++ = ':';
+ while (*stats == ' ')
+ stats++;
+
+ if ((scan_line_to_use == scan_line_2_2 &&
+ sscanf(stats, scan_line_to_use, &rec_oct, &rec_pkt, &rec_err,
+ &rec_drop, &snd_oct, &snd_pkt, &snd_err, &snd_drop,
+ &coll) != 9) || (scan_line_to_use == scan_line_2_0
+ && sscanf(stats, scan_line_to_use,
+ &rec_pkt, &rec_err,
+ &snd_pkt, &snd_err,
+ &coll) != 5)) {
+ if ((scan_line_to_use == scan_line_2_2)
+ && !strstr(line, "No statistics available"))
+ snmp_log(LOG_ERR,
+ "/proc/net/dev data format error, line ==|%s|",
+ line);
+ continue;
+ }
+
+ nnew = (struct ifnet *) calloc(1, sizeof(struct ifnet));
+ if (nnew == NULL)
+ break; /* alloc error */
+
+ /*
+ * chain in:
+ */
+ *ifnetaddr_ptr = nnew;
+ ifnetaddr_ptr = &nnew->if_next;
+ i++;
+
+ /*
+ * linux previous to 1.3.~13 may miss transmitted loopback pkts:
+ */
+ if (!strcmp(ifname_buf, "lo") && rec_pkt > 0 && !snd_pkt)
+ snd_pkt = rec_pkt;
+
+ nnew->if_ipackets = rec_pkt & 0xffffffff;
+ nnew->if_ierrors = rec_err;
+ nnew->if_opackets = snd_pkt & 0xffffffff;
+ nnew->if_oerrors = snd_err;
+ nnew->if_collisions = coll;
+ if (scan_line_to_use == scan_line_2_2) {
+ nnew->if_ibytes = rec_oct & 0xffffffff;
+ nnew->if_obytes = snd_oct & 0xffffffff;
+ nnew->if_iqdrops = rec_drop;
+ nnew->if_snd.ifq_drops = snd_drop;
+ } else {
+ nnew->if_ibytes = (rec_pkt * 308) & 0xffffffff;
+ nnew->if_obytes = (snd_pkt * 308) & 0xffffffff;
+ }
+
+ /*
+ * ifnames are given as `` eth0'': split in ``eth'' and ``0'':
+ */
+ for (ifname = ifname_buf; *ifname && *ifname == ' '; ifname++);
+
+ /*
+ * set name and interface# :
+ */
+ nnew->if_name = (char *) strdup(ifname);
+ for (ptr = nnew->if_name; *ptr && (*ptr < '0' || *ptr > '9');
+ ptr++);
+ nnew->if_unit = strdup(*ptr ? ptr : "");
+ *ptr = 0;
+
+ strncpy(ifrq.ifr_name, ifname, sizeof(ifrq.ifr_name));
+ ifrq.ifr_name[ sizeof(ifrq.ifr_name)-1 ] = 0;
+ if (ioctl(fd, SIOCGIFADDR, &ifrq) < 0)
+ memset((char *) &nnew->if_addr, 0, sizeof(nnew->if_addr));
+ else
+ nnew->if_addr = ifrq.ifr_addr;
+
+ strncpy(ifrq.ifr_name, ifname, sizeof(ifrq.ifr_name));
+ ifrq.ifr_name[ sizeof(ifrq.ifr_name)-1 ] = 0;
+ if (ioctl(fd, SIOCGIFBRDADDR, &ifrq) < 0)
+ memset((char *) &nnew->ifu_broadaddr, 0,
+ sizeof(nnew->ifu_broadaddr));
+ else
+ nnew->ifu_broadaddr = ifrq.ifr_broadaddr;
+
+ strncpy(ifrq.ifr_name, ifname, sizeof(ifrq.ifr_name));
+ ifrq.ifr_name[ sizeof(ifrq.ifr_name)-1 ] = 0;
+ if (ioctl(fd, SIOCGIFNETMASK, &ifrq) < 0)
+ memset((char *) &nnew->ia_subnetmask, 0,
+ sizeof(nnew->ia_subnetmask));
+ else
+ nnew->ia_subnetmask = ifrq.ifr_netmask;
+
+ strncpy(ifrq.ifr_name, ifname, sizeof(ifrq.ifr_name));
+ ifrq.ifr_name[ sizeof(ifrq.ifr_name)-1 ] = 0;
+ nnew->if_flags = ioctl(fd, SIOCGIFFLAGS, &ifrq) < 0
+ ? 0 : ifrq.ifr_flags;
+
+ nnew->if_type = 0;
+
+ /*
+ * NOTE: this ioctl does not guarantee 6 bytes of a physaddr.
+ * In particular, a 'sit0' interface only appears to get back
+ * 4 bytes of sa_data.
+ */
+ memset(ifrq.ifr_hwaddr.sa_data, (0), IFHWADDRLEN);
+ strncpy(ifrq.ifr_name, ifname, sizeof(ifrq.ifr_name));
+ ifrq.ifr_name[ sizeof(ifrq.ifr_name)-1 ] = 0;
+ if (ioctl(fd, SIOCGIFHWADDR, &ifrq) < 0)
+ memset(nnew->if_hwaddr, (0), IFHWADDRLEN);
+ else {
+ memcpy(nnew->if_hwaddr, ifrq.ifr_hwaddr.sa_data, IFHWADDRLEN);
+
+#ifdef ARPHRD_LOOPBACK
+ switch (ifrq.ifr_hwaddr.sa_family) {
+ case ARPHRD_ETHER:
+ nnew->if_type = 6;
+ break;
+ case ARPHRD_TUNNEL:
+ case ARPHRD_TUNNEL6:
+#ifdef ARPHRD_IPGRE
+ case ARPHRD_IPGRE:
+#endif
+ case ARPHRD_SIT:
+ nnew->if_type = 131;
+ break; /* tunnel */
+ case ARPHRD_SLIP:
+ case ARPHRD_CSLIP:
+ case ARPHRD_SLIP6:
+ case ARPHRD_CSLIP6:
+ nnew->if_type = 28;
+ break; /* slip */
+ case ARPHRD_PPP:
+ nnew->if_type = 23;
+ break; /* ppp */
+ case ARPHRD_LOOPBACK:
+ nnew->if_type = 24;
+ break; /* softwareLoopback */
+ case ARPHRD_FDDI:
+ nnew->if_type = 15;
+ break;
+ case ARPHRD_ARCNET:
+ nnew->if_type = 35;
+ break;
+ case ARPHRD_LOCALTLK:
+ nnew->if_type = 42;
+ break;
+#ifdef ARPHRD_HIPPI
+ case ARPHRD_HIPPI:
+ nnew->if_type = 47;
+ break;
+#endif
+#ifdef ARPHRD_ATM
+ case ARPHRD_ATM:
+ nnew->if_type = 37;
+ break;
+#endif
+ /*
+ * XXX: more if_arp.h:ARPHDR_xxx to IANAifType mappings...
+ */
+ }
+#endif
+ }
+
+ strncpy(ifrq.ifr_name, ifname, sizeof(ifrq.ifr_name));
+ ifrq.ifr_name[ sizeof(ifrq.ifr_name)-1 ] = 0;
+ nnew->if_metric = ioctl(fd, SIOCGIFMETRIC, &ifrq) < 0
+ ? 0 : ifrq.ifr_metric;
+
+#ifdef SIOCGIFMTU
+ strncpy(ifrq.ifr_name, ifname, sizeof(ifrq.ifr_name));
+ ifrq.ifr_name[ sizeof(ifrq.ifr_name)-1 ] = 0;
+ nnew->if_mtu = (ioctl(fd, SIOCGIFMTU, &ifrq) < 0)
+ ? 0 : ifrq.ifr_mtu;
+#else
+ nnew->if_mtu = 0;
+#endif
+
+ if_ptr = netsnmp_access_interface_entry_overrides_get(ifname);
+ if (if_ptr) {
+ nnew->if_type = if_ptr->type;
+ nnew->if_speed = if_ptr->speed;
+ } else {
+ /*
+ * do only guess if_type from name, if we could not read
+ * * it before from SIOCGIFHWADDR
+ */
+ unsigned int defaultspeed = NOMINAL_LINK_SPEED;
+ if (!(nnew->if_flags & IFF_RUNNING)) {
+ /*
+ * use speed 0 if the if speed cannot be determined *and* the
+ * interface is down
+ */
+ defaultspeed = 0;
+ }
+
+ if (!nnew->if_type)
+ nnew->if_type = if_type_from_name(nnew->if_name);
+ switch(nnew->if_type) {
+ case 6:
+ nnew->if_speed = getIfSpeed(fd, ifrq, defaultspeed);
+ break;
+ case 24:
+ nnew->if_speed = 10000000;
+ break;
+ case 9:
+ nnew->if_speed = 4000000;
+ break;
+ default:
+ nnew->if_speed = 0;
+ }
+ /*Zero speed means link problem*/
+ if(nnew->if_speed == 0 && nnew->if_flags & IFF_UP){
+ nnew->if_flags &= ~IFF_RUNNING;
+ }
+ }
+
+ } /* while (fgets ... */
+
+ ifnetaddr = ifnetaddr_list;
+
+ if (snmp_get_do_debugging()) {
+ {
+ struct ifnet *x = ifnetaddr;
+ DEBUGMSGTL(("mibII/interfaces", "* see: known interfaces:"));
+ while (x) {
+ DEBUGMSG(("mibII/interfaces", " %s", x->if_name));
+ x = x->if_next;
+ }
+ DEBUGMSG(("mibII/interfaces", "\n"));
+ } /* XXX */
+ }
+
+ fclose(devin);
+ close(fd);
+#endif /* linux */
+}
+
+
+
+#if defined(sunV3) || defined(linux)
+/*
+ * ** 4.2 BSD doesn't have ifaddr
+ * **
+ */
+int
+Interface_Scan_Next(short *Index,
+ char *Name,
+ struct ifnet *Retifnet, struct in_ifaddr *dummy)
+{
+ struct ifnet ifnet;
+ register char *cp;
+
+ while (ifnetaddr) {
+ /*
+ * Get the "ifnet" structure and extract the device name
+ */
+#ifndef linux
+ if (!NETSNMP_KLOOKUP(ifnetaddr, (char *) &ifnet, sizeof ifnet)) {
+ DEBUGMSGTL(("mibII/interfaces:Interface_Scan_Next", "klookup failed\n"));
+ break;
+ }
+
+ if (!NETSNMP_KLOOKUP(ifnet.if_name, (char *) saveName, sizeof saveName)) {
+ DEBUGMSGTL(("mibII/interfaces:Interface_Scan_Next", "klookup failed\n"));
+ break;
+ }
+
+ /*
+ * The purpose of this comparison is lost in the mists of time.
+ * It's been around at least cmu-snmp 2.1.2 for SUNv3 systems and
+ * was applied to linux systems during the cmu-snmp-linux project.
+ * No-one now knows what it was intended for, and it breaks IPv6
+ * tunnel interfaces, so it's been moved out of the Linux code block.
+ */
+ if (strcmp(saveName, "ip") == 0) {
+ ifnetaddr = ifnet.if_next;
+ continue;
+ }
+#else
+ ifnet = *ifnetaddr;
+ strncpy(saveName, ifnet.if_name, sizeof(saveName));
+#endif
+
+ saveName[sizeof(saveName) - 1] = '\0';
+ cp = (char *) strchr(saveName, '\0');
+#ifdef linux
+ strncat(cp, ifnet.if_unit, sizeof(saveName)-strlen(saveName)-1);
+ saveName[sizeof(saveName) - 1] = '\0';
+#else
+ string_append_int(cp, ifnet.if_unit);
+#endif
+ if (1 || strcmp(saveName, "lo0") != 0) { /* XXX */
+
+ if (Index)
+ *Index = ++saveIndex;
+ if (Retifnet)
+ *Retifnet = ifnet;
+ if (Name)
+ strcpy(Name, saveName);
+ saveifnet = ifnet;
+ saveifnetaddr = ifnetaddr;
+ ifnetaddr = ifnet.if_next;
+
+ return (1); /* DONE */
+ }
+ ifnetaddr = ifnet.if_next;
+ }
+ return (0); /* EOF */
+}
+
+#ifdef linux
+int
+Interface_Index_By_Name(char *Name, int Len)
+{
+ short ifIndex = 0;
+ char ifName[20];
+
+ Interface_Scan_Init();
+ while (Interface_Scan_Next(&ifIndex, ifName, NULL, NULL)
+ && strcmp(Name, ifName));
+ return ifIndex;
+}
+#endif
+
+
+#else /* sunV3 || linux */
+
+#if defined(netbsd1) || defined(openbsd2)
+#define ia_next ia_list.tqe_next
+#define if_next if_list.tqe_next
+#endif
+
+#if defined(hpux11)
+
+int
+Interface_Scan_Next(short *Index, char *Name, nmapi_phystat * Retifnet)
+{
+ static nmapi_phystat *if_ptr = (nmapi_phystat *) 0;
+ int count = Interface_Scan_Get_Count();
+ unsigned int ulen;
+ int ret;
+
+ if (!if_ptr) {
+ if (count)
+ if_ptr =
+ (nmapi_phystat *) malloc(sizeof(nmapi_phystat) * count);
+ else
+ return (0); /* EOF */
+ }
+
+ if (saveIndex >= count)
+ return (0); /* EOF */
+
+ ulen = (unsigned int) count *sizeof(nmapi_phystat);
+ if ((ret = get_physical_stat(if_ptr, &ulen)) < 0)
+ return (0); /* EOF */
+
+ if (Retifnet)
+ *Retifnet = if_ptr[saveIndex];
+ if (Name)
+ strcpy(Name, if_ptr[saveIndex].nm_device);
+ saveIndex++;
+ if (Index)
+ *Index = saveIndex;
+ return (1); /* DONE */
+}
+
+#else /* hpux11 */
+
+int
+Interface_Scan_Next(short *Index,
+ char *Name,
+ struct ifnet *Retifnet, struct in_ifaddr *Retin_ifaddr)
+{
+ struct ifnet ifnet;
+ struct in_ifaddr *ia, in_ifaddr;
+ short has_ipaddr = 0;
+#if !STRUCT_IFNET_HAS_IF_XNAME
+ register char *cp;
+#endif
+
+ while (ifnetaddr) {
+ /*
+ * Get the "ifnet" structure and extract the device name
+ */
+ if (!NETSNMP_KLOOKUP(ifnetaddr, (char *) &ifnet, sizeof ifnet)) {
+ DEBUGMSGTL(("mibII/interfaces:Interface_Scan_Next", "klookup failed\n"));
+ break;
+ }
+#if STRUCT_IFNET_HAS_IF_XNAME
+#if defined(netbsd1) || defined(openbsd2)
+ strncpy(saveName, ifnet.if_xname, sizeof saveName);
+#else
+ if (!NETSNMP_KLOOKUP(ifnet.if_xname, (char *) saveName, sizeof saveName)) {
+ DEBUGMSGTL(("mibII/interfaces:Interface_Scan_Next", "klookup failed\n"));
+ break;
+ }
+#endif
+ saveName[sizeof(saveName) - 1] = '\0';
+#else
+ if (!NETSNMP_KLOOKUP(ifnet.if_name, (char *) saveName, sizeof saveName)) {
+ DEBUGMSGTL(("mibII/interfaces:Interface_Scan_Next", "klookup failed\n"));
+ break;
+ }
+
+ saveName[sizeof(saveName) - 1] = '\0';
+ cp = strchr(saveName, '\0');
+ string_append_int(cp, ifnet.if_unit);
+#endif
+ if (1 || strcmp(saveName, "lo0") != 0) { /* XXX */
+ /*
+ * Try to find an address for this interface
+ */
+
+#ifdef netbsd1
+ ia = (struct in_ifaddr *) ifnet.if_addrlist.tqh_first;
+#elif defined(IFADDR_SYMBOL)
+ auto_nlist(IFADDR_SYMBOL, (char *) &ia, sizeof(ia));
+#endif
+ while (ia) {
+ if (!NETSNMP_KLOOKUP(ia, (char *) &in_ifaddr, sizeof(in_ifaddr))) {
+ DEBUGMSGTL(("mibII/interfaces:Interface_Scan_Next", "klookup failed\n"));
+ break;
+ }
+ {
+#ifdef netbsd1
+#define CP(x) ((char *)(x))
+ char *cp;
+ struct sockaddr *sa;
+ cp = (CP(in_ifaddr.ia_ifa.ifa_addr) - CP(ia)) +
+ CP(&in_ifaddr);
+ sa = (struct sockaddr *) cp;
+
+ if (sa->sa_family == AF_INET)
+#endif
+ if (in_ifaddr.ia_ifp == ifnetaddr) {
+ has_ipaddr = 1; /* this IF has IP-address */
+ break;
+ }
+ }
+#ifdef netbsd1
+ ia = (struct in_ifaddr *) in_ifaddr.ia_ifa.ifa_list.
+ tqe_next;
+#else
+ ia = in_ifaddr.ia_next;
+#endif
+ }
+
+#if !defined(netbsd1) && !defined(freebsd2) && !defined(openbsd2) && !defined(STRUCT_IFNET_HAS_IF_ADDRLIST)
+ ifnet.if_addrlist = (struct ifaddr *) ia; /* WRONG DATA TYPE; ONLY A FLAG */
+#endif
+ /*
+ * ifnet.if_addrlist = (struct ifaddr *)&ia->ia_ifa;
+ *
+ * WRONG DATA TYPE; ONLY A FLAG
+ */
+
+ if (Index)
+ *Index = ++saveIndex;
+ if (Retifnet)
+ *Retifnet = ifnet;
+ if (Retin_ifaddr && has_ipaddr) /* assign the in_ifaddr only
+ * if the IF has IP-address */
+ *Retin_ifaddr = in_ifaddr;
+ if (Name)
+ strcpy(Name, saveName);
+ saveifnet = ifnet;
+ saveifnetaddr = ifnetaddr;
+ savein_ifaddr = in_ifaddr;
+ ifnetaddr = ifnet.if_next;
+
+ return (1); /* DONE */
+ }
+ ifnetaddr = ifnet.if_next;
+ }
+ return (0); /* EOF */
+}
+
+#endif /* hpux11 */
+
+#endif /* sunV3 || linux */
+
+#if defined(hpux11)
+
+static int
+Interface_Scan_By_Index(int Index, char *Name, nmapi_phystat * Retifnet)
+{
+ short i;
+
+ Interface_Scan_Init();
+ while (Interface_Scan_Next(&i, Name, Retifnet)) {
+ if (i == Index)
+ break;
+ }
+ if (i != Index)
+ return (-1); /* Error, doesn't exist */
+ return (0); /* DONE */
+}
+
+#else /* hpux11 */
+
+static int
+Interface_Scan_By_Index(int Index,
+ char *Name,
+ struct ifnet *Retifnet,
+ struct in_ifaddr *Retin_ifaddr)
+{
+ short i;
+
+ Interface_Scan_Init();
+ while (Interface_Scan_Next(&i, Name, Retifnet, Retin_ifaddr)) {
+ if (i == Index)
+ break;
+ }
+ if (i != Index)
+ return (-1); /* Error, doesn't exist */
+ return (0); /* DONE */
+}
+
+#endif /* hpux11 */
+
+static int Interface_Count = 0;
+
+#if defined(hpux11)
+
+int
+Interface_Scan_Get_Count(void)
+{
+ if (!Interface_Count) {
+ int fd;
+ struct nmparms p;
+ int val;
+ unsigned int ulen;
+ int ret;
+
+ if ((fd = open_mib("/dev/ip", O_RDONLY, 0, NM_ASYNC_OFF)) >= 0) {
+ p.objid = ID_ifNumber;
+ p.buffer = (void *) &val;
+ ulen = sizeof(int);
+ p.len = &ulen;
+ if ((ret = get_mib_info(fd, &p)) == 0)
+ Interface_Count = val;
+ close_mib(fd);
+ }
+ }
+ return (Interface_Count);
+}
+
+#else /* hpux11 */
+
+static time_t scan_time = 0;
+
+int
+Interface_Scan_Get_Count(void)
+{
+ time_t time_now = time(NULL);
+
+ if (!Interface_Count || (time_now > scan_time + 60)) {
+ scan_time = time_now;
+ Interface_Scan_Init();
+ Interface_Count = 0;
+ while (Interface_Scan_Next(NULL, NULL, NULL, NULL) != 0) {
+ Interface_Count++;
+ }
+ }
+ return (Interface_Count);
+}
+
+
+static int
+Interface_Get_Ether_By_Index(int Index, u_char * EtherAddr)
+{
+ short i;
+#if !(defined(linux) || defined(netbsd1) || defined(bsdi2) || defined(openbsd2))
+ struct arpcom arpcom;
+#else /* is linux or netbsd1 */
+ struct arpcom {
+ char ac_enaddr[6];
+ } arpcom;
+#if defined(netbsd1) || defined(bsdi2) || defined(openbsd2)
+ struct sockaddr_dl sadl;
+ struct ifaddr ifaddr;
+ u_long ifaddraddr;
+#endif
+#endif
+
+#if defined(mips) || defined(hpux) || defined(osf4) || defined(osf3) || defined(osf5)
+ memset(arpcom.ac_enaddr, 0, sizeof(arpcom.ac_enaddr));
+#else
+ memset(&arpcom.ac_enaddr, 0, sizeof(arpcom.ac_enaddr));
+#endif
+ memset(EtherAddr, 0, sizeof(arpcom.ac_enaddr));
+
+ if (saveIndex != Index) { /* Optimization! */
+
+ Interface_Scan_Init();
+
+ while (Interface_Scan_Next((short *) &i, NULL, NULL, NULL) != 0) {
+ if (i == Index)
+ break;
+ }
+ if (i != Index)
+ return (-1); /* Error, doesn't exist */
+ }
+#ifdef freebsd2
+ if (saveifnet.if_type != IFT_ETHER) {
+ return (0); /* Not an ethernet if */
+ }
+#endif
+ /*
+ * the arpcom structure is an extended ifnet structure which
+ * contains the ethernet address.
+ */
+#ifndef linux
+#if !(defined(netbsd1) || defined(bsdi2) || defined(openbsd2))
+ if (!NETSNMP_KLOOKUP(saveifnetaddr, (char *) &arpcom, sizeof arpcom)) {
+ DEBUGMSGTL(("mibII/interfaces:Interface_Get_Ether_By_Index", "klookup failed\n"));
+ return 0;
+ }
+#else /* netbsd1 or bsdi2 or openbsd2 */
+
+#if defined(netbsd1) || defined(openbsd2)
+#define if_addrlist if_addrlist.tqh_first
+#define ifa_next ifa_list.tqe_next
+#endif
+
+ ifaddraddr = (unsigned long) saveifnet.if_addrlist;
+ while (ifaddraddr) {
+ if (!NETSNMP_KLOOKUP(ifaddraddr, (char *) &ifaddr, sizeof ifaddr)) {
+ DEBUGMSGTL(("mibII/interfaces:Interface_Get_Ether_By_Index", "klookup failed\n"));
+ break;
+ }
+ if (!NETSNMP_KLOOKUP(ifaddr.ifa_addr, (char *) &sadl, sizeof sadl)) {
+ DEBUGMSGTL(("mibII/interfaces:Interface_Get_Ether_By_Index", "klookup failed\n"));
+ break;
+ }
+ if (sadl.sdl_family == AF_LINK
+ && (saveifnet.if_type == IFT_ETHER
+ || saveifnet.if_type == IFT_ISO88025
+ || saveifnet.if_type == IFT_FDDI)) {
+ memcpy(arpcom.ac_enaddr, sadl.sdl_data + sadl.sdl_nlen,
+ sizeof(arpcom.ac_enaddr));
+ break;
+ }
+ ifaddraddr = (unsigned long) ifaddr.ifa_next;
+ }
+#endif /* netbsd1 or bsdi2 or openbsd2 */
+
+#else /* linux */
+ memcpy(arpcom.ac_enaddr, saveifnetaddr->if_hwaddr, 6);
+#endif
+ if (strncmp("lo", saveName, 2) == 0) {
+ /*
+ * Loopback doesn't have a HW addr, so return 00:00:00:00:00:00
+ */
+ memset(EtherAddr, 0, sizeof(arpcom.ac_enaddr));
+
+ } else {
+
+#if defined(mips) || defined(hpux) || defined(osf4) || defined(osf3)
+ memcpy(EtherAddr, (char *) arpcom.ac_enaddr,
+ sizeof(arpcom.ac_enaddr));
+#else
+ memcpy(EtherAddr, (char *) &arpcom.ac_enaddr,
+ sizeof(arpcom.ac_enaddr));
+#endif
+
+
+ }
+ return (0); /* DONE */
+}
+
+#endif /* hpux11 */
+
+#else /* solaris2 */
+
+int
+Interface_Scan_Get_Count(void)
+{
+ int i, sd;
+
+ if ((sd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
+ return (0);
+ if (ioctl(sd, SIOCGIFNUM, &i) == -1) {
+ close(sd);
+ return (0);
+ } else {
+ close(sd);
+ return (i);
+ }
+}
+
+int
+Interface_Index_By_Name(char *Name, int Len)
+{
+ return (solaris2_if_nametoindex(Name, Len));
+}
+
+#endif /* solaris2 */
+
+#else /* HAVE_NET_IF_MIB_H */
+
+/*
+ * This code attempts to do the right thing for FreeBSD. Note that
+ * the statistics could be gathered through use of of the
+ * net.route.0.link.iflist.0 sysctl (which we already use to get the
+ * hardware address of the interfaces), rather than using the ifmib
+ * code, but eventually I will implement dot3Stats and we will have to
+ * use the ifmib interface. ifmib is also a much more natural way of
+ * mapping the SNMP MIB onto sysctl(3).
+ */
+
+#include <net/if.h>
+#include <net/if_dl.h>
+#include <net/if_mib.h>
+#include <net/route.h>
+
+static int header_interfaces(struct variable *, oid *, size_t *, int,
+ size_t *, WriteMethod ** write);
+static int header_ifEntry(struct variable *, oid *, size_t *, int,
+ size_t *, WriteMethod ** write);
+u_char *var_ifEntry(struct variable *, oid *, size_t *, int,
+ size_t *, WriteMethod ** write);
+
+static char *physaddrbuf;
+static int nphysaddrs;
+struct sockaddr_dl **physaddrs;
+
+void
+init_interfaces_setup(void)
+{
+ int naddrs, ilen, bit;
+ static int mib[6]
+ = { CTL_NET, PF_ROUTE, 0, AF_LINK, NET_RT_IFLIST, 0 };
+ char *cp;
+ size_t len;
+ struct rt_msghdr *rtm;
+ struct if_msghdr *ifm;
+ struct ifa_msghdr *ifam;
+ struct sockaddr *sa;
+
+ DEBUGMSGTL(("mibII:freebsd", "init_interfaces_setup\n"));
+
+ naddrs = 0;
+ if (physaddrs)
+ free(physaddrs);
+ if (physaddrbuf)
+ free(physaddrbuf);
+ physaddrbuf = 0;
+ physaddrs = 0;
+ nphysaddrs = 0;
+ len = 0;
+ if (sysctl(mib, 6, 0, &len, 0, 0) < 0) {
+ DEBUGMSGTL(("mibII:freebsd", "sysctl 1 < 0\n"));
+ return;
+ }
+
+ cp = physaddrbuf = malloc(len);
+ if (physaddrbuf == 0)
+ return;
+ if (sysctl(mib, 6, physaddrbuf, &len, 0, 0) < 0) {
+ free(physaddrbuf);
+ physaddrbuf = 0;
+ DEBUGMSGTL(("mibII:freebsd", "sysctl 2 < 0\n"));
+ return;
+ }
+
+ loop:
+ ilen = len;
+ cp = physaddrbuf;
+ while (ilen > 0) {
+ rtm = (struct rt_msghdr *) cp;
+ if (rtm->rtm_version != RTM_VERSION || rtm->rtm_type != RTM_IFINFO) {
+ DEBUGMSGTL(("mibII:freebsd", "version:%d/%d type:%d/%d\n",
+ rtm->rtm_version, RTM_VERSION, rtm->rtm_type, RTM_IFINFO));
+ free(physaddrs);
+ physaddrs = 0;
+ free(physaddrbuf);
+ physaddrbuf = 0;
+ }
+ ifm = (struct if_msghdr *) rtm;
+#if defined(freebsd3) || defined(freebsd4) || defined(freebsd5)
+ if (physaddrs != 0)
+ physaddrs[naddrs] = (void *) (ifm + 1);
+ naddrs++;
+#endif
+ ilen -= ifm->ifm_msglen;
+ cp += ifm->ifm_msglen;
+ rtm = (struct rt_msghdr *) cp;
+ while (ilen > 0 && rtm->rtm_type == RTM_NEWADDR) {
+#if defined(freebsd3) || defined(freebsd4) || defined(freebsd5)
+ ilen -= rtm->rtm_msglen;
+ cp += rtm->rtm_msglen;
+#else
+ int is_alias = 0;
+ ifam = (struct ifa_msghdr *) rtm;
+ ilen -= sizeof(*ifam);
+ cp += sizeof(*ifam);
+ sa = (struct sockaddr *) cp;
+#define ROUND(x) (((x) + sizeof(long) - 1) & ~sizeof(long))
+ for (bit = 1; bit && ilen > 0; bit <<= 1) {
+ if (!(ifam->ifam_addrs & bit))
+ continue;
+ ilen -= ROUND(sa->sa_len);
+ cp += ROUND(sa->sa_len);
+
+ if (bit == RTA_IFA) {
+ if (physaddrs)
+#define satosdl(sa) ((struct sockaddr_dl *)(sa))
+ physaddrs[naddrs++]
+ = satosdl(sa);
+ else
+ naddrs++;
+ }
+ sa = (struct sockaddr *) cp;
+ }
+#endif
+ rtm = (struct rt_msghdr *) cp;
+ }
+ }
+ DEBUGMSGTL(("mibII:freebsd", "found %d addrs\n", naddrs));
+ if (physaddrs) {
+ nphysaddrs = naddrs;
+ return;
+ }
+ physaddrs = malloc(naddrs * sizeof(*physaddrs));
+ if (physaddrs == 0)
+ return;
+ naddrs = 0;
+ goto loop;
+
+}
+
+static int
+get_phys_address(int iindex, char **ap, int *len)
+{
+ int i;
+ int once = 1;
+
+ do {
+ for (i = 0; i < nphysaddrs; i++) {
+ if (physaddrs[i]->sdl_index == iindex)
+ break;
+ }
+ if (i < nphysaddrs)
+ break;
+ init_interfaces_setup();
+ } while (once--);
+
+ DEBUGMSGTL(("mibII:freebsd", "get_phys_address %d/%d\n", i, nphysaddrs));
+ if (i < nphysaddrs) {
+ *ap = LLADDR(physaddrs[i]);
+ *len = physaddrs[i]->sdl_alen;
+ return 0;
+ }
+ return -1;
+}
+
+int
+Interface_Scan_Get_Count(void)
+{
+ static int count_oid[5] = { CTL_NET, PF_LINK, NETLINK_GENERIC,
+ IFMIB_SYSTEM, IFMIB_IFCOUNT
+ };
+ size_t len;
+ int count;
+
+ len = sizeof count;
+ if (sysctl(count_oid, 5, &count, &len, (void *) 0, (size_t) 0) < 0) {
+ DEBUGMSGTL(("mibII:freebsd", "Interface_Scan_Get_Count err\n"));
+ return -1;
+ }
+ DEBUGMSGTL(("mibII:freebsd", "Interface_Scan_Get_Count %d\n", count));
+ return count;
+}
+
+
+u_char *
+var_ifEntry(struct variable * vp,
+ oid * name,
+ size_t * length,
+ int exact, size_t * var_len, WriteMethod ** write_method)
+{
+ int interface;
+ static int sname[6] = { CTL_NET, PF_LINK, NETLINK_GENERIC,
+ IFMIB_IFDATA, 0, IFDATA_GENERAL
+ };
+ static struct ifmibdata ifmd;
+ size_t len;
+ char *cp;
+ conf_if_list *if_ptr = NULL;
+
+ interface = header_ifEntry(vp, name, length, exact, var_len,
+ write_method);
+ if (interface == MATCH_FAILED)
+ return NULL;
+
+ sname[4] = interface;
+ len = sizeof ifmd;
+ if (sysctl(sname, 6, &ifmd, &len, 0, 0) < 0) {
+ DEBUGMSGTL(("mibII:freebsd", "var_ifEntry sysctl err\n"));
+ return NULL;
+ }
+ /*
+ * hmmm.. where to get the interface name to check overrides?
+ *
+ * if_ptr = netsnmp_access_interface_entry_overrides_get(Name);
+ */
+
+ switch (vp->magic) {
+ case IFINDEX:
+ long_return = interface;
+ return (u_char *) & long_return;
+ case IFDESCR:
+ cp = ifmd.ifmd_name;
+ *var_len = strlen(cp);
+ return (u_char *) cp;
+ case NETSNMP_IFTYPE:
+ if (if_ptr)
+ long_return = if_ptr->type;
+ else
+ long_return = ifmd.ifmd_data.ifi_type;
+ return (u_char *) & long_return;
+ case IFMTU:
+ long_return = (long) ifmd.ifmd_data.ifi_mtu;
+ return (u_char *) & long_return;
+ case IFSPEED:
+ if (if_ptr)
+ long_return = if_ptr->speed;
+ else
+ long_return = ifmd.ifmd_data.ifi_baudrate;
+ return (u_char *) & long_return;
+ case IFPHYSADDRESS:
+ {
+ char *cp;
+ if (get_phys_address(interface, &cp, var_len))
+ return NULL;
+ else
+ return cp;
+ }
+ case IFADMINSTATUS:
+ long_return = ifmd.ifmd_flags & IFF_UP ? 1 : 2;
+ return (u_char *) & long_return;
+ case IFOPERSTATUS:
+ long_return = ifmd.ifmd_flags & IFF_RUNNING ? 1 : 2;
+ return (u_char *) & long_return;
+ case IFLASTCHANGE:
+ if (ifmd.ifmd_data.ifi_lastchange.tv_sec == 0 &&
+ ifmd.ifmd_data.ifi_lastchange.tv_usec == 0) {
+ long_return = 0;
+ } else if (ifmd.ifmd_data.ifi_lastchange.tv_sec < starttime.tv_sec) {
+ long_return = 0;
+ } else {
+ long_return = (u_long)
+ ((ifmd.ifmd_data.ifi_lastchange.tv_sec -
+ starttime.tv_sec) * 100 +
+ ((ifmd.ifmd_data.ifi_lastchange.tv_usec -
+ starttime.tv_usec) / 10000));
+ }
+ return (u_char *) & long_return;
+ case IFINOCTETS:
+ long_return = (u_long) ifmd.ifmd_data.ifi_ibytes;
+ return (u_char *) & long_return;
+ case IFINUCASTPKTS:
+ long_return = (u_long) ifmd.ifmd_data.ifi_ipackets;
+ long_return -= (u_long) ifmd.ifmd_data.ifi_imcasts;
+ return (u_char *) & long_return;
+ case IFINNUCASTPKTS:
+ long_return = (u_long) ifmd.ifmd_data.ifi_imcasts;
+ return (u_char *) & long_return;
+ case IFINDISCARDS:
+ long_return = (u_long) ifmd.ifmd_data.ifi_iqdrops;
+ return (u_char *) & long_return;
+ case IFINERRORS:
+ long_return = ifmd.ifmd_data.ifi_ierrors;
+ return (u_char *) & long_return;
+ case IFINUNKNOWNPROTOS:
+ long_return = (u_long) ifmd.ifmd_data.ifi_noproto;
+ return (u_char *) & long_return;
+ case IFOUTOCTETS:
+ long_return = (u_long) ifmd.ifmd_data.ifi_obytes;
+ return (u_char *) & long_return;
+ case IFOUTUCASTPKTS:
+ long_return = (u_long) ifmd.ifmd_data.ifi_opackets;
+ long_return -= (u_long) ifmd.ifmd_data.ifi_omcasts;
+ return (u_char *) & long_return;
+ case IFOUTNUCASTPKTS:
+ long_return = (u_long) ifmd.ifmd_data.ifi_omcasts;
+ return (u_char *) & long_return;
+ case IFOUTDISCARDS:
+ long_return = ifmd.ifmd_snd_drops;
+ return (u_char *) & long_return;
+ case IFOUTERRORS:
+ long_return = ifmd.ifmd_data.ifi_oerrors;
+ return (u_char *) & long_return;
+ case IFOUTQLEN:
+ long_return = ifmd.ifmd_snd_len;
+ return (u_char *) & long_return;
+ case IFSPECIFIC:
+ *var_len = nullOidLen;
+ return (u_char *) nullOid;
+ default:
+ DEBUGMSGTL(("snmpd", "unknown sub-id %d in var_ifEntry\n",
+ vp->magic));
+ }
+ return NULL;
+}
+
+#endif /* HAVE_NET_IF_MIB_H */
+#endif /* !USE_SYSCTL_IFLIST */
+
+#else /* WIN32 cygwin */
+#include <iphlpapi.h>
+
+WriteMethod writeIfEntry;
+long admin_status = 0;
+long oldadmin_status = 0;
+
+static int
+header_ifEntry(struct variable *vp,
+ oid * name,
+ size_t * length,
+ int exact, size_t * var_len, WriteMethod ** write_method)
+{
+#define IFENTRY_NAME_LENGTH 10
+ oid newname[MAX_OID_LEN];
+ register int ifIndex;
+ int result, count;
+ DWORD status = NO_ERROR;
+ DWORD statusRetry = NO_ERROR;
+ DWORD dwActualSize = 0;
+ PMIB_IFTABLE pIfTable = NULL;
+
+ DEBUGMSGTL(("mibII/interfaces", "var_ifEntry: "));
+ DEBUGMSGOID(("mibII/interfaces", name, *length));
+ DEBUGMSG(("mibII/interfaces", " %d\n", exact));
+
+ memcpy((char *) newname, (char *) vp->name,
+ (int) vp->namelen * sizeof(oid));
+ /*
+ * find "next" ifIndex
+ */
+
+
+ /*
+ * query for buffer size needed
+ */
+ status = GetIfTable(pIfTable, &dwActualSize, TRUE);
+
+ if (status == ERROR_INSUFFICIENT_BUFFER) {
+ /*
+ * need more space
+ */
+ pIfTable = (PMIB_IFTABLE) malloc(dwActualSize);
+ if (pIfTable != NULL) {
+ /*
+ * Get the sorted IF table
+ */
+ GetIfTable(pIfTable, &dwActualSize, TRUE);
+ }
+ }
+ count = pIfTable->dwNumEntries;
+ for (ifIndex = 0; ifIndex < count; ifIndex++) {
+ newname[IFENTRY_NAME_LENGTH] =
+ (oid) pIfTable->table[ifIndex].dwIndex;
+ result =
+ snmp_oid_compare(name, *length, newname,
+ (int) vp->namelen + 1);
+ if ((exact && (result == 0)) || (!exact && (result < 0)))
+ break;
+ }
+ if (ifIndex > count) {
+ DEBUGMSGTL(("mibII/interfaces", "... index out of range\n"));
+ return MATCH_FAILED;
+ }
+
+
+ memcpy((char *) name, (char *) newname,
+ ((int) vp->namelen + 1) * sizeof(oid));
+ *length = vp->namelen + 1;
+ *write_method = 0;
+ *var_len = sizeof(long); /* default to 'long' results */
+
+ DEBUGMSGTL(("mibII/interfaces", "... get I/F stats "));
+ DEBUGMSGOID(("mibII/interfaces", name, *length));
+ DEBUGMSG(("mibII/interfaces", "\n"));
+
+ count = pIfTable->table[ifIndex].dwIndex;
+ free(pIfTable);
+ return count;
+}
+
+
+
+u_char *
+var_interfaces(struct variable * vp,
+ oid * name,
+ size_t * length,
+ int exact, size_t * var_len, WriteMethod ** write_method)
+{
+ if (header_generic(vp, name, length, exact, var_len, write_method) ==
+ MATCH_FAILED)
+ return NULL;
+
+ switch (vp->magic) {
+ case IFNUMBER:
+ GetNumberOfInterfaces(&long_return);
+ return (u_char *) & long_return;
+ default:
+ DEBUGMSGTL(("snmpd", "unknown sub-id %d in var_interfaces\n",
+ vp->magic));
+ }
+ return NULL;
+}
+
+u_char *
+var_ifEntry(struct variable * vp,
+ oid * name,
+ size_t * length,
+ int exact, size_t * var_len, WriteMethod ** write_method)
+{
+ int ifIndex;
+ static MIB_IFROW ifRow;
+ conf_if_list *if_ptr = NULL;
+
+ ifIndex =
+ header_ifEntry(vp, name, length, exact, var_len, write_method);
+ if (ifIndex == MATCH_FAILED)
+ return NULL;
+ /*
+ * hmmm.. where to get the interface name to check overrides?
+ *
+ * if_ptr = netsnmp_access_interface_entry_overrides_get(Name);
+ */
+
+ /*
+ * Get the If Table Row by passing index as argument
+ */
+ ifRow.dwIndex = ifIndex;
+ if (GetIfEntry(&ifRow) != NO_ERROR)
+ return NULL;
+ switch (vp->magic) {
+ case IFINDEX:
+ long_return = ifIndex;
+ return (u_char *) & long_return;
+ case IFDESCR:
+ *var_len = ifRow.dwDescrLen;
+ return (u_char *) ifRow.bDescr;
+ case NETSNMP_IFTYPE:
+ if (if_ptr)
+ long_return = if_ptr->type;
+ else
+ long_return = ifRow.dwType;
+ return (u_char *) & long_return;
+ case IFMTU:
+ long_return = (long) ifRow.dwMtu;
+ return (u_char *) & long_return;
+ case IFSPEED:
+ if (if_ptr)
+ long_return = if_ptr->speed;
+ else
+ long_return = (long) ifRow.dwSpeed;
+ return (u_char *) & long_return;
+ case IFPHYSADDRESS:
+ *var_len = ifRow.dwPhysAddrLen;
+ memcpy(return_buf, ifRow.bPhysAddr, *var_len);
+ return (u_char *) return_buf;
+ case IFADMINSTATUS:
+ long_return = ifRow.dwAdminStatus;
+ admin_status = long_return;
+ *write_method = writeIfEntry;
+ return (u_char *) & long_return;
+ case IFOPERSTATUS:
+ long_return =
+ (MIB_IF_OPER_STATUS_OPERATIONAL == ifRow.dwOperStatus) ? 1 : 2;
+ return (u_char *) & long_return;
+ case IFLASTCHANGE:
+ long_return = 0 /* XXX not a UNIX epochal time ifRow.dwLastChange */ ;
+ return (u_char *) & long_return;
+ case IFINOCTETS:
+ long_return = ifRow.dwInOctets;
+ return (u_char *) & long_return;
+ case IFINUCASTPKTS:
+ long_return = ifRow.dwInUcastPkts;
+ return (u_char *) & long_return;
+ case IFINNUCASTPKTS:
+ long_return = ifRow.dwInNUcastPkts;
+ return (u_char *) & long_return;
+ case IFINDISCARDS:
+ long_return = ifRow.dwInDiscards;
+ return (u_char *) & long_return;
+ case IFINERRORS:
+ long_return = ifRow.dwInErrors;
+ return (u_char *) & long_return;
+ case IFINUNKNOWNPROTOS:
+ long_return = ifRow.dwInUnknownProtos;
+ return (u_char *) & long_return;
+ case IFOUTOCTETS:
+ long_return = ifRow.dwOutOctets;
+ return (u_char *) & long_return;
+ case IFOUTUCASTPKTS:
+ long_return = ifRow.dwOutUcastPkts;
+ return (u_char *) & long_return;
+ case IFOUTNUCASTPKTS:
+ long_return = ifRow.dwOutNUcastPkts;
+ return (u_char *) & long_return;
+ case IFOUTDISCARDS:
+ long_return = ifRow.dwOutDiscards;
+ return (u_char *) & long_return;
+ case IFOUTERRORS:
+ long_return = ifRow.dwOutErrors;
+ return (u_char *) & long_return;
+ case IFOUTQLEN:
+ long_return = ifRow.dwOutQLen;
+ return (u_char *) & long_return;
+ case IFSPECIFIC:
+ *var_len = nullOidLen;
+ return (u_char *) nullOid;
+ default:
+ DEBUGMSGTL(("snmpd", "unknown sub-id %d in var_ifEntry\n",
+ vp->magic));
+ }
+ return NULL;
+}
+
+
+int
+writeIfEntry(int action,
+ u_char * var_val,
+ u_char var_val_type,
+ size_t var_val_len,
+ u_char * statP, oid * name, size_t name_len)
+{
+ MIB_IFROW ifEntryRow;
+ if ((char) name[9] != IFADMINSTATUS) {
+ return SNMP_ERR_NOTWRITABLE;
+ }
+
+ switch (action) {
+ case RESERVE1: /* Check values for acceptability */
+ if (var_val_type != ASN_INTEGER) {
+ snmp_log(LOG_ERR, "not integer\n");
+ return SNMP_ERR_WRONGTYPE;
+ }
+ if (var_val_len > sizeof(int)) {
+ snmp_log(LOG_ERR, "bad length\n");
+ return SNMP_ERR_WRONGLENGTH;
+ }
+
+ /*
+ * The dwAdminStatus member can be MIB_IF_ADMIN_STATUS_UP or MIB_IF_ADMIN_STATUS_DOWN
+ */
+ if (!(((int) (*var_val) == MIB_IF_ADMIN_STATUS_UP) ||
+ ((int) (*var_val) == MIB_IF_ADMIN_STATUS_DOWN))) {
+ snmp_log(LOG_ERR, "not supported admin state\n");
+ return SNMP_ERR_WRONGVALUE;
+ }
+ break;
+
+ case RESERVE2: /* Allocate memory and similar resources */
+ break;
+
+ case ACTION:
+ /*
+ * Save the old value, in case of UNDO
+ */
+
+ oldadmin_status = admin_status;
+ admin_status = (int) *var_val;
+ break;
+
+ case UNDO: /* Reverse the SET action and free resources */
+ admin_status = oldadmin_status;
+ break;
+
+ case COMMIT: /* Confirm the SET, performing any irreversible actions,
+ * and free resources */
+ ifEntryRow.dwIndex = (int) name[10];
+ ifEntryRow.dwAdminStatus = admin_status;
+ /*
+ * Only UP and DOWN status are supported. Thats why done in COMMIT
+ */
+ if (SetIfEntry(&ifEntryRow) != NO_ERROR) {
+ snmp_log(LOG_ERR,
+ "Error in writeIfEntry case COMMIT with index: %d & adminStatus %d\n",
+ ifEntryRow.dwIndex, ifEntryRow.dwAdminStatus);
+ return SNMP_ERR_COMMITFAILED;
+ }
+
+ case FREE: /* Free any resources allocated */
+ /*
+ * No resources have been allocated
+ */
+ break;
+ }
+ return SNMP_ERR_NOERROR;
+} /* end of writeIfEntry */
+#endif /* WIN32 cygwin */