2951 lines
88 KiB
C
2951 lines
88 KiB
C
/*
|
|
* 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.
|
|
*
|
|
* Portions of this file are copyrighted by:
|
|
* Copyright (c) 2016 VMware, 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>
|
|
#include <net-snmp/net-snmp-features.h>
|
|
|
|
netsnmp_feature_provide(interface_legacy)
|
|
|
|
#if defined(NETSNMP_IFNET_NEEDS_KERNEL) && !defined(_KERNEL) && !defined(NETSNMP_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 defined(NETSNMP_IFNET_NEEDS_KERNEL) && !defined(_KERNEL) && defined(NETSNMP_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
|
|
# include <sys/time.h>
|
|
# 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 */
|
|
|
|
#if defined(cygwin) || defined(mingw32)
|
|
#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/agent/sysORTable.h>
|
|
#include <net-snmp/data_access/interface.h>
|
|
|
|
#include "interfaces.h"
|
|
#include "struct.h"
|
|
#include "util_funcs.h"
|
|
#include "util_funcs/header_generic.h"
|
|
|
|
/* if you want caching enabled for speed retrieval 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
|
|
|
|
#define starttime (*(const struct timeval*)netsnmp_get_agent_starttime())
|
|
|
|
struct variable3 interfaces_variables[] = {
|
|
{NETSNMP_IFNUMBER, ASN_INTEGER, NETSNMP_OLDAPI_RONLY,
|
|
var_interfaces, 1, {1}},
|
|
{NETSNMP_IFINDEX, ASN_INTEGER, NETSNMP_OLDAPI_RONLY,
|
|
var_ifEntry, 3, {2, 1, 1}},
|
|
{NETSNMP_IFDESCR, ASN_OCTET_STR, NETSNMP_OLDAPI_RONLY,
|
|
var_ifEntry, 3, {2, 1, 2}},
|
|
{NETSNMP_IFTYPE, ASN_INTEGER, NETSNMP_OLDAPI_RONLY,
|
|
var_ifEntry, 3, {2, 1, 3}},
|
|
{NETSNMP_IFMTU, ASN_INTEGER, NETSNMP_OLDAPI_RONLY,
|
|
var_ifEntry, 3, {2, 1, 4}},
|
|
{NETSNMP_IFSPEED, ASN_GAUGE, NETSNMP_OLDAPI_RONLY,
|
|
var_ifEntry, 3, {2, 1, 5}},
|
|
{NETSNMP_IFPHYSADDRESS, ASN_OCTET_STR, NETSNMP_OLDAPI_RONLY,
|
|
var_ifEntry, 3, {2, 1, 6}},
|
|
#ifndef NETSNMP_NO_WRITE_SUPPORT
|
|
#if defined (WIN32) || defined (cygwin)
|
|
{NETSNMP_IFADMINSTATUS, ASN_INTEGER, NETSNMP_OLDAPI_RWRITE,
|
|
var_ifEntry, 3, {2, 1, 7}},
|
|
#else
|
|
{NETSNMP_IFADMINSTATUS, ASN_INTEGER, NETSNMP_OLDAPI_RONLY,
|
|
var_ifEntry, 3, {2, 1, 7}},
|
|
#endif
|
|
#else /* !NETSNMP_NO_WRITE_SUPPORT */
|
|
{NETSNMP_IFADMINSTATUS, ASN_INTEGER, NETSNMP_OLDAPI_RONLY,
|
|
var_ifEntry, 3, {2, 1, 7}},
|
|
#endif /* !NETSNMP_NO_WRITE_SUPPORT */
|
|
{NETSNMP_IFOPERSTATUS, ASN_INTEGER, NETSNMP_OLDAPI_RONLY,
|
|
var_ifEntry, 3, {2, 1, 8}},
|
|
{NETSNMP_IFLASTCHANGE, ASN_TIMETICKS, NETSNMP_OLDAPI_RONLY,
|
|
var_ifEntry, 3, {2, 1, 9}},
|
|
{NETSNMP_IFINOCTETS, ASN_COUNTER, NETSNMP_OLDAPI_RONLY,
|
|
var_ifEntry, 3, {2, 1, 10}},
|
|
{NETSNMP_IFINUCASTPKTS, ASN_COUNTER, NETSNMP_OLDAPI_RONLY,
|
|
var_ifEntry, 3, {2, 1, 11}},
|
|
{NETSNMP_IFINNUCASTPKTS, ASN_COUNTER, NETSNMP_OLDAPI_RONLY,
|
|
var_ifEntry, 3, {2, 1, 12}},
|
|
{NETSNMP_IFINDISCARDS, ASN_COUNTER, NETSNMP_OLDAPI_RONLY,
|
|
var_ifEntry, 3, {2, 1, 13}},
|
|
{NETSNMP_IFINERRORS, ASN_COUNTER, NETSNMP_OLDAPI_RONLY,
|
|
var_ifEntry, 3, {2, 1, 14}},
|
|
{NETSNMP_IFINUNKNOWNPROTOS, ASN_COUNTER, NETSNMP_OLDAPI_RONLY,
|
|
var_ifEntry, 3, {2, 1, 15}},
|
|
{NETSNMP_IFOUTOCTETS, ASN_COUNTER, NETSNMP_OLDAPI_RONLY,
|
|
var_ifEntry, 3, {2, 1, 16}},
|
|
{NETSNMP_IFOUTUCASTPKTS, ASN_COUNTER, NETSNMP_OLDAPI_RONLY,
|
|
var_ifEntry, 3, {2, 1, 17}},
|
|
{NETSNMP_IFOUTNUCASTPKTS, ASN_COUNTER, NETSNMP_OLDAPI_RONLY,
|
|
var_ifEntry, 3, {2, 1, 18}},
|
|
{NETSNMP_IFOUTDISCARDS, ASN_COUNTER, NETSNMP_OLDAPI_RONLY,
|
|
var_ifEntry, 3, {2, 1, 19}},
|
|
{NETSNMP_IFOUTERRORS, ASN_COUNTER, NETSNMP_OLDAPI_RONLY,
|
|
var_ifEntry, 3, {2, 1, 20}},
|
|
{NETSNMP_IFOUTQLEN, ASN_GAUGE, NETSNMP_OLDAPI_RONLY,
|
|
var_ifEntry, 3, {2, 1, 21}},
|
|
{NETSNMP_IFSPECIFIC, ASN_OBJECT_ID, NETSNMP_OLDAPI_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 len;
|
|
register pmatch_if pm;
|
|
|
|
for (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 NETSNMP_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;
|
|
};
|
|
|
|
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;
|
|
sprintf(if_name, "%.*s", ((const u_char *) a)[5],
|
|
((const struct sockaddr_in *) a)->sin_zero);
|
|
*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 NETSNMP_IFINDEX:
|
|
long_return = interface;
|
|
return (u_char *) & long_return;
|
|
case NETSNMP_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 NETSNMP_IFMTU:
|
|
long_return = (long) if_msg.ifm_data.ifi_mtu;
|
|
return (u_char *) & long_return;
|
|
case NETSNMP_IFSPEED:
|
|
if (if_ptr)
|
|
long_return = if_ptr->speed;
|
|
else {
|
|
#if HAVE_STRUCT_IFNET_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 NETSNMP_IFPHYSADDRESS:
|
|
/*
|
|
* XXX
|
|
*/
|
|
return NULL;
|
|
case NETSNMP_IFADMINSTATUS:
|
|
long_return = if_msg.ifm_flags & IFF_UP ? 1 : 2;
|
|
return (u_char *) & long_return;
|
|
case NETSNMP_IFOPERSTATUS:
|
|
long_return = if_msg.ifm_flags & IFF_RUNNING ? 1 : 2;
|
|
return (u_char *) & long_return;
|
|
/*
|
|
* ifLastChange
|
|
*/
|
|
case NETSNMP_IFINOCTETS:
|
|
long_return = (u_long) if_msg.ifm_data.ifi_ibytes;
|
|
return (u_char *) & long_return;
|
|
case NETSNMP_IFINUCASTPKTS:
|
|
long_return =
|
|
(u_long) if_msg.ifm_data.ifi_ipackets -
|
|
if_msg.ifm_data.ifi_imcasts;
|
|
return (u_char *) & long_return;
|
|
case NETSNMP_IFINNUCASTPKTS:
|
|
long_return = (u_long) if_msg.ifm_data.ifi_imcasts;
|
|
return (u_char *) & long_return;
|
|
case NETSNMP_IFINDISCARDS:
|
|
long_return = (u_long) if_msg.ifm_data.ifi_iqdrops;
|
|
return (u_char *) & long_return;
|
|
case NETSNMP_IFINERRORS:
|
|
long_return = (u_long) if_msg.ifm_data.ifi_ierrors;
|
|
return (u_char *) & long_return;
|
|
case NETSNMP_IFINUNKNOWNPROTOS:
|
|
long_return = (u_long) if_msg.ifm_data.ifi_noproto;
|
|
return (u_char *) & long_return;
|
|
case NETSNMP_IFOUTOCTETS:
|
|
long_return = (u_long) if_msg.ifm_data.ifi_obytes;
|
|
return (u_char *) & long_return;
|
|
case NETSNMP_IFOUTUCASTPKTS:
|
|
long_return =
|
|
(u_long) if_msg.ifm_data.ifi_opackets -
|
|
if_msg.ifm_data.ifi_omcasts;
|
|
return (u_char *) & long_return;
|
|
case NETSNMP_IFOUTNUCASTPKTS:
|
|
long_return = (u_long) if_msg.ifm_data.ifi_omcasts;
|
|
return (u_char *) & long_return;
|
|
case NETSNMP_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 NETSNMP_IFOUTERRORS:
|
|
long_return = (u_long) if_msg.ifm_data.ifi_oerrors;
|
|
return (u_char *) & long_return;
|
|
case NETSNMP_IFLASTCHANGE:
|
|
#ifdef irix6
|
|
long_return = 0;
|
|
#else
|
|
if (if_msg.ifm_data.ifi_lastchange.tv_sec == 0 &&
|
|
#if STRUCT_IFNET_HAS_IF_LASTCHANGE_TV_NSEC
|
|
if_msg.ifm_data.ifi_lastchange.tv_nsec == 0
|
|
#else
|
|
if_msg.ifm_data.ifi_lastchange.tv_usec == 0
|
|
#endif
|
|
)
|
|
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 STRUCT_IFNET_HAS_IF_LASTCHANGE_TV_NSEC
|
|
if_msg.ifm_data.ifi_lastchange.tv_nsec / 1000
|
|
#else
|
|
if_msg.ifm_data.ifi_lastchange.tv_usec
|
|
#endif
|
|
- 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;
|
|
}
|
|
|
|
int
|
|
Interface_Scan_NextInt(int *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;
|
|
|
|
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 NETSNMP_IFINDEX:
|
|
long_return = interface;
|
|
return (u_char *) & long_return;
|
|
case NETSNMP_IFDESCR:
|
|
cp = Name;
|
|
*var_len = strlen(cp);
|
|
return (u_char *) cp;
|
|
case NETSNMP_IFTYPE:
|
|
if (if_ptr)
|
|
long_return = if_ptr->type;
|
|
else {
|
|
#if HAVE_STRUCT_IFNET_IF_TYPE
|
|
long_return = ifnet.if_type;
|
|
#else
|
|
long_return = 1; /* OTHER */
|
|
#endif
|
|
}
|
|
return (u_char *) & long_return;
|
|
case NETSNMP_IFMTU:{
|
|
long_return = (long) ifnet.if_mtu;
|
|
return (u_char *) & long_return;
|
|
}
|
|
case NETSNMP_IFSPEED:
|
|
if (if_ptr)
|
|
long_return = if_ptr->speed;
|
|
else {
|
|
#if HAVE_STRUCT_IFNET_IF_BAUDRATE
|
|
long_return = ifnet.if_baudrate;
|
|
#elif HAVE_STRUCT_IFNET_IF_SPEED
|
|
long_return = ifnet.if_speed;
|
|
#elif HAVE_STRUCT_IFNET_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 NETSNMP_IFPHYSADDRESS:
|
|
Interface_Get_Ether_By_Index(interface, return_buf);
|
|
#if defined(aix4) || defined(aix5) || defined(aix6) || defined(aix7)
|
|
*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 NETSNMP_IFADMINSTATUS:
|
|
long_return = ifnet.if_flags & IFF_UP ? 1 : 2;
|
|
return (u_char *) & long_return;
|
|
case NETSNMP_IFOPERSTATUS:
|
|
long_return = ifnet.if_flags & IFF_RUNNING ? 1 : 2;
|
|
return (u_char *) & long_return;
|
|
case NETSNMP_IFLASTCHANGE:
|
|
#if defined(HAVE_STRUCT_IFNET_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 NETSNMP_IFINOCTETS:
|
|
#ifdef HAVE_STRUCT_IFNET_IF_IBYTES
|
|
#if defined(aix4) || defined(aix5) || defined(aix6) || defined(aix7)
|
|
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 NETSNMP_IFINUCASTPKTS:
|
|
{
|
|
#if defined(aix4) || defined(aix5) || defined(aix6) || defined(aix7)
|
|
long_return = (u_long) ifnet.if_ipackets & 0xffffffff;
|
|
#else
|
|
long_return = (u_long) ifnet.if_ipackets;
|
|
#endif
|
|
#if HAVE_STRUCT_IFNET_IF_IMCASTS
|
|
#if defined(aix4) || defined(aix5) || defined(aix6) || defined(aix7)
|
|
long_return -= (u_long) ifnet.if_imcasts & 0xffffffff;
|
|
#else
|
|
long_return -= (u_long) ifnet.if_imcasts;
|
|
#endif
|
|
#endif
|
|
}
|
|
return (u_char *) & long_return;
|
|
case NETSNMP_IFINNUCASTPKTS:
|
|
#if HAVE_STRUCT_IFNET_IF_IMCASTS
|
|
#if defined(aix4) || defined(aix5) || defined(aix6) || defined(aix7)
|
|
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 NETSNMP_IFINDISCARDS:
|
|
#if HAVE_STRUCT_IFNET_IF_IQDROPS
|
|
#if defined(aix4) || defined(aix5) || defined(aix6) || defined(aix7)
|
|
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 NETSNMP_IFINERRORS:
|
|
#if defined(aix4) || defined(aix5) || defined(aix6) || defined(aix7)
|
|
long_return = (u_long) ifnet.if_ierrors & 0xffffffff;
|
|
#else
|
|
long_return = (u_long) ifnet.if_ierrors;
|
|
#endif
|
|
return (u_char *) & long_return;
|
|
case NETSNMP_IFINUNKNOWNPROTOS:
|
|
#if HAVE_STRUCT_IFNET_IF_NOPROTO
|
|
#if defined(aix4) || defined(aix5) || defined(aix6) || defined(aix7)
|
|
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 NETSNMP_IFOUTOCTETS:
|
|
#ifdef HAVE_STRUCT_IFNET_IF_OBYTES
|
|
#if defined(aix4) || defined(aix5) || defined(aix6) || defined(aix7)
|
|
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 NETSNMP_IFOUTUCASTPKTS:
|
|
{
|
|
#if defined(aix4) || defined(aix5) || defined(aix6) || defined(aix7)
|
|
long_return = (u_long) ifnet.if_opackets & 0xffffffff;
|
|
#else
|
|
long_return = (u_long) ifnet.if_opackets;
|
|
#endif
|
|
#if HAVE_STRUCT_IFNET_IF_OMCASTS
|
|
#if defined(aix4) || defined(aix5) || defined(aix6) || defined(aix7)
|
|
long_return -= (u_long) ifnet.if_omcasts & 0xffffffff;
|
|
#else
|
|
long_return -= (u_long) ifnet.if_omcasts;
|
|
#endif
|
|
#endif
|
|
}
|
|
return (u_char *) & long_return;
|
|
case NETSNMP_IFOUTNUCASTPKTS:
|
|
#if HAVE_STRUCT_IFNET_IF_OMCASTS
|
|
#if defined(aix4) || defined(aix5) || defined(aix6) || defined(aix7)
|
|
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 NETSNMP_IFOUTDISCARDS:
|
|
#if defined(aix4) || defined(aix5) || defined(aix6) || defined(aix7)
|
|
long_return = ifnet.if_snd.ifq_drops & 0xffffffff;
|
|
#else
|
|
long_return = ifnet.if_snd.ifq_drops;
|
|
#endif
|
|
return (u_char *) & long_return;
|
|
case NETSNMP_IFOUTERRORS:
|
|
#if defined(aix4) || defined(aix5) || defined(aix6) || defined(aix7)
|
|
long_return = ifnet.if_oerrors & 0xffffffff;
|
|
#else
|
|
long_return = ifnet.if_oerrors;
|
|
#endif
|
|
return (u_char *) & long_return;
|
|
case NETSNMP_IFOUTQLEN:
|
|
#if defined(aix4) || defined(aix5) || defined(aix6) || defined(aix7)
|
|
long_return = ifnet.if_snd.ifq_len & 0xffffffff;
|
|
#else
|
|
long_return = ifnet.if_snd.ifq_len;
|
|
#endif
|
|
return (u_char *) & long_return;
|
|
case NETSNMP_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 HAVE_STRUCT_IFNET_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 NETSNMP_IFINDEX:
|
|
long_return = interface;
|
|
return (u_char *) & long_return;
|
|
case NETSNMP_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 NETSNMP_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 NETSNMP_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 NETSNMP_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 NETSNMP_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 NETSNMP_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 NETSNMP_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 NETSNMP_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 NETSNMP_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 NETSNMP_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 NETSNMP_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 NETSNMP_IFINERRORS:
|
|
#if defined(hpux11)
|
|
long_return = ifnet.if_entry.ifInErrors;
|
|
#else
|
|
long_return = ifnet.if_ierrors;
|
|
#endif
|
|
return (u_char *) & long_return;
|
|
case NETSNMP_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 NETSNMP_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 NETSNMP_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 NETSNMP_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 NETSNMP_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 NETSNMP_IFOUTERRORS:
|
|
#if defined(hpux11)
|
|
long_return = ifnet.if_entry.ifOutErrors;
|
|
#else
|
|
long_return = ifnet.if_oerrors;
|
|
#endif
|
|
return (u_char *) & long_return;
|
|
case NETSNMP_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 NETSNMP_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 NETSNMP_IFINDEX:
|
|
long_return = ifstat.ifIndex;
|
|
return (u_char *) & long_return;
|
|
case NETSNMP_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 NETSNMP_IFMTU:
|
|
long_return = (u_long) ifstat.ifMtu;
|
|
return (u_char *) & long_return;
|
|
case NETSNMP_IFSPEED:
|
|
if (if_ptr)
|
|
long_return = if_ptr->speed;
|
|
else
|
|
long_return = (u_long) ifstat.ifSpeed;
|
|
return (u_char *) & long_return;
|
|
case NETSNMP_IFPHYSADDRESS:
|
|
*var_len = ifstat.ifPhysAddress.o_length;
|
|
(void) memcpy(return_buf, ifstat.ifPhysAddress.o_bytes, *var_len);
|
|
return (u_char *) return_buf;
|
|
case NETSNMP_IFADMINSTATUS:
|
|
long_return = (u_long) ifstat.ifAdminStatus;
|
|
return (u_char *) & long_return;
|
|
case NETSNMP_IFOPERSTATUS:
|
|
long_return = (u_long) ifstat.ifOperStatus;
|
|
return (u_char *) & long_return;
|
|
case NETSNMP_IFLASTCHANGE:
|
|
long_return = (u_long) ifstat.ifLastChange;
|
|
return (u_char *) & long_return;
|
|
case NETSNMP_IFINOCTETS:
|
|
long_return = (u_long) ifstat.ifInOctets;
|
|
return (u_char *) & long_return;
|
|
case NETSNMP_IFINUCASTPKTS:
|
|
long_return = (u_long) ifstat.ifInUcastPkts;
|
|
return (u_char *) & long_return;
|
|
case NETSNMP_IFINNUCASTPKTS:
|
|
long_return = (u_long) ifstat.ifInNUcastPkts;
|
|
return (u_char *) & long_return;
|
|
case NETSNMP_IFINDISCARDS:
|
|
long_return = (u_long) ifstat.ifInDiscards;
|
|
return (u_char *) & long_return;
|
|
case NETSNMP_IFINERRORS:
|
|
long_return = (u_long) ifstat.ifInErrors;
|
|
return (u_char *) & long_return;
|
|
case NETSNMP_IFINUNKNOWNPROTOS:
|
|
long_return = (u_long) ifstat.ifInUnknownProtos;
|
|
return (u_char *) & long_return;
|
|
case NETSNMP_IFOUTOCTETS:
|
|
long_return = (u_long) ifstat.ifOutOctets;
|
|
return (u_char *) & long_return;
|
|
case NETSNMP_IFOUTUCASTPKTS:
|
|
long_return = (u_long) ifstat.ifOutUcastPkts;
|
|
return (u_char *) & long_return;
|
|
case NETSNMP_IFOUTNUCASTPKTS:
|
|
long_return = (u_long) ifstat.ifOutNUcastPkts;
|
|
return (u_char *) & long_return;
|
|
case NETSNMP_IFOUTDISCARDS:
|
|
long_return = (u_long) ifstat.ifOutDiscards;
|
|
return (u_char *) & long_return;
|
|
case NETSNMP_IFOUTERRORS:
|
|
long_return = (u_long) ifstat.ifOutErrors;
|
|
return (u_char *) & long_return;
|
|
case NETSNMP_IFOUTQLEN:
|
|
long_return = (u_long) ifstat.ifOutQLen;
|
|
return (u_char *) & long_return;
|
|
case NETSNMP_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
|
|
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 */
|
|
netsnmp_get_monotonic_clock(&et);
|
|
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);
|
|
NETSNMP_LOGONCE((LOG_ERR, "cannot open /proc/net/dev.\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;
|
|
|
|
/* Ignore interfaces with no statistics. */
|
|
if (strstr(line, "No statistics available."))
|
|
continue;
|
|
|
|
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;
|
|
strlcpy(ifname_buf, ifstart, sizeof(ifname_buf));
|
|
*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_DEBUG,
|
|
"/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;
|
|
|
|
strlcpy(ifrq.ifr_name, ifname, sizeof(ifrq.ifr_name));
|
|
if (ioctl(fd, SIOCGIFADDR, &ifrq) < 0)
|
|
memset((char *) &nnew->if_addr, 0, sizeof(nnew->if_addr));
|
|
else
|
|
nnew->if_addr = ifrq.ifr_addr;
|
|
|
|
strlcpy(ifrq.ifr_name, ifname, sizeof(ifrq.ifr_name));
|
|
if (ioctl(fd, SIOCGIFBRDADDR, &ifrq) < 0)
|
|
memset((char *) &nnew->ifu_broadaddr, 0,
|
|
sizeof(nnew->ifu_broadaddr));
|
|
else
|
|
nnew->ifu_broadaddr = ifrq.ifr_broadaddr;
|
|
|
|
strlcpy(ifrq.ifr_name, ifname, sizeof(ifrq.ifr_name));
|
|
if (ioctl(fd, SIOCGIFNETMASK, &ifrq) < 0)
|
|
memset((char *) &nnew->ia_subnetmask, 0,
|
|
sizeof(nnew->ia_subnetmask));
|
|
else
|
|
nnew->ia_subnetmask = ifrq.ifr_netmask;
|
|
|
|
strlcpy(ifrq.ifr_name, ifname, sizeof(ifrq.ifr_name));
|
|
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);
|
|
strlcpy(ifrq.ifr_name, ifname, sizeof(ifrq.ifr_name));
|
|
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
|
|
}
|
|
|
|
strlcpy(ifrq.ifr_name, ifname, sizeof(ifrq.ifr_name));
|
|
nnew->if_metric = ioctl(fd, SIOCGIFMETRIC, &ifrq) < 0
|
|
? 0 : ifrq.ifr_metric;
|
|
|
|
#ifdef SIOCGIFMTU
|
|
strlcpy(ifrq.ifr_name, ifname, sizeof(ifrq.ifr_name));
|
|
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)
|
|
{
|
|
int returnIndex = 0;
|
|
int ret;
|
|
if (Index)
|
|
returnIndex = *Index;
|
|
|
|
ret = Interface_Scan_NextInt( &returnIndex, Name, Retifnet, dummy );
|
|
if (Index)
|
|
*Index = (returnIndex & 0x8fff);
|
|
return ret;
|
|
}
|
|
|
|
int
|
|
Interface_Scan_NextInt(int *Index,
|
|
char *Name,
|
|
struct ifnet *Retifnet, struct in_ifaddr *dummy)
|
|
{
|
|
struct ifnet ifnet;
|
|
#if !defined(linux)
|
|
register char *cp;
|
|
#endif
|
|
|
|
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;
|
|
strlcpy(saveName, ifnet.if_name, sizeof(saveName));
|
|
#endif
|
|
|
|
saveName[sizeof(saveName) - 1] = '\0';
|
|
#ifdef linux
|
|
strlcat(saveName, ifnet.if_unit, sizeof(saveName));
|
|
#else
|
|
#ifdef NETSNMP_FEATURE_CHECKIN
|
|
/* this exists here just so we don't copy ifdef logic elsewhere */
|
|
netsnmp_feature_require(string_append_int);
|
|
#endif
|
|
cp = (char *) strchr(saveName, '\0');
|
|
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)
|
|
{
|
|
int ifIndex = 0;
|
|
char ifName[20];
|
|
|
|
Interface_Scan_Init();
|
|
while (Interface_Scan_NextInt(&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)
|
|
{
|
|
int returnIndex = 0;
|
|
int ret;
|
|
if (Index)
|
|
returnIndex = *Index;
|
|
|
|
ret = Interface_Scan_NextInt( &returnIndex, Name, Retifnet );
|
|
if (Index)
|
|
*Index = (returnIndex & 0x8fff);
|
|
return ret;
|
|
}
|
|
|
|
|
|
int
|
|
Interface_Scan_NextInt(int *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);
|
|
if (if_ptr == NULL)
|
|
return (0);
|
|
|
|
} 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)
|
|
{
|
|
int returnIndex = 0;
|
|
int ret;
|
|
if (Index)
|
|
returnIndex = *Index;
|
|
|
|
ret = Interface_Scan_NextInt( &returnIndex, Name, Retifnet, Retin_ifaddr );
|
|
if (Index)
|
|
*Index = (returnIndex & 0x8fff);
|
|
return ret;
|
|
}
|
|
|
|
|
|
int
|
|
Interface_Scan_NextInt(int *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 !HAVE_STRUCT_IFNET_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 HAVE_STRUCT_IFNET_IF_XNAME
|
|
#if defined(netbsd1) || defined(openbsd2)
|
|
strlcpy(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');
|
|
#ifdef NETSNMP_FEATURE_CHECKIN
|
|
/* this exists here just so we don't copy ifdef logic elsewhere */
|
|
netsnmp_feature_require(string_append_int);
|
|
#endif
|
|
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(HAVE_STRUCT_IFNET_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)
|
|
{
|
|
int i;
|
|
|
|
Interface_Scan_Init();
|
|
while (Interface_Scan_NextInt(&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)
|
|
{
|
|
int i;
|
|
|
|
Interface_Scan_Init();
|
|
while (Interface_Scan_NextInt(&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 */
|
|
|
|
int
|
|
Interface_Scan_Get_Count(void)
|
|
{
|
|
static time_t scan_time = 0;
|
|
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_NextInt(NULL, NULL, NULL, NULL) != 0) {
|
|
Interface_Count++;
|
|
}
|
|
}
|
|
return (Interface_Count);
|
|
}
|
|
|
|
|
|
static int
|
|
Interface_Get_Ether_By_Index(int Index, u_char * EtherAddr)
|
|
{
|
|
int 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_NextInt(&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);
|
|
|
|
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 NETSNMP_IFINDEX:
|
|
long_return = interface;
|
|
return (u_char *) & long_return;
|
|
case NETSNMP_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 NETSNMP_IFMTU:
|
|
long_return = (long) ifmd.ifmd_data.ifi_mtu;
|
|
return (u_char *) & long_return;
|
|
case NETSNMP_IFSPEED:
|
|
if (if_ptr)
|
|
long_return = if_ptr->speed;
|
|
else
|
|
long_return = ifmd.ifmd_data.ifi_baudrate;
|
|
return (u_char *) & long_return;
|
|
case NETSNMP_IFPHYSADDRESS:
|
|
{
|
|
char *cp;
|
|
if (get_phys_address(interface, &cp, var_len))
|
|
return NULL;
|
|
else
|
|
return cp;
|
|
}
|
|
case NETSNMP_IFADMINSTATUS:
|
|
long_return = ifmd.ifmd_flags & IFF_UP ? 1 : 2;
|
|
return (u_char *) & long_return;
|
|
case NETSNMP_IFOPERSTATUS:
|
|
long_return = ifmd.ifmd_flags & IFF_RUNNING ? 1 : 2;
|
|
return (u_char *) & long_return;
|
|
case NETSNMP_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 NETSNMP_IFINOCTETS:
|
|
long_return = (u_long) ifmd.ifmd_data.ifi_ibytes;
|
|
return (u_char *) & long_return;
|
|
case NETSNMP_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 NETSNMP_IFINNUCASTPKTS:
|
|
long_return = (u_long) ifmd.ifmd_data.ifi_imcasts;
|
|
return (u_char *) & long_return;
|
|
case NETSNMP_IFINDISCARDS:
|
|
long_return = (u_long) ifmd.ifmd_data.ifi_iqdrops;
|
|
return (u_char *) & long_return;
|
|
case NETSNMP_IFINERRORS:
|
|
long_return = ifmd.ifmd_data.ifi_ierrors;
|
|
return (u_char *) & long_return;
|
|
case NETSNMP_IFINUNKNOWNPROTOS:
|
|
long_return = (u_long) ifmd.ifmd_data.ifi_noproto;
|
|
return (u_char *) & long_return;
|
|
case NETSNMP_IFOUTOCTETS:
|
|
long_return = (u_long) ifmd.ifmd_data.ifi_obytes;
|
|
return (u_char *) & long_return;
|
|
case NETSNMP_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 NETSNMP_IFOUTNUCASTPKTS:
|
|
long_return = (u_long) ifmd.ifmd_data.ifi_omcasts;
|
|
return (u_char *) & long_return;
|
|
case NETSNMP_IFOUTDISCARDS:
|
|
long_return = ifmd.ifmd_snd_drops;
|
|
return (u_char *) & long_return;
|
|
case NETSNMP_IFOUTERRORS:
|
|
long_return = ifmd.ifmd_data.ifi_oerrors;
|
|
return (u_char *) & long_return;
|
|
case NETSNMP_IFOUTQLEN:
|
|
long_return = ifmd.ifmd_snd_len;
|
|
return (u_char *) & long_return;
|
|
case NETSNMP_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 */
|
|
|
|
#elif defined(HAVE_IPHLPAPI_H) /* WIN32 cygwin */
|
|
#include <iphlpapi.h>
|
|
|
|
#ifndef NETSNMP_NO_WRITE_SUPPORT
|
|
WriteMethod writeIfEntry;
|
|
#endif /* !NETSNMP_NO_WRITE_SUPPORT */
|
|
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 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
|
|
*/
|
|
|
|
status = GetIfTable(pIfTable, &dwActualSize, TRUE);
|
|
if (status == ERROR_INSUFFICIENT_BUFFER) {
|
|
pIfTable = malloc(dwActualSize);
|
|
if (pIfTable)
|
|
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"));
|
|
count = MATCH_FAILED;
|
|
goto out;
|
|
}
|
|
|
|
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;
|
|
out:
|
|
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 NETSNMP_IFNUMBER:
|
|
netsnmp_assert(sizeof(DWORD) == sizeof(long_return));
|
|
GetNumberOfInterfaces((DWORD *) &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 NETSNMP_IFINDEX:
|
|
long_return = ifIndex;
|
|
return (u_char *) & long_return;
|
|
case NETSNMP_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 NETSNMP_IFMTU:
|
|
long_return = (long) ifRow.dwMtu;
|
|
return (u_char *) & long_return;
|
|
case NETSNMP_IFSPEED:
|
|
if (if_ptr)
|
|
long_return = (long) if_ptr->speed;
|
|
else
|
|
long_return = (long) ifRow.dwSpeed;
|
|
return (u_char *) & long_return;
|
|
case NETSNMP_IFPHYSADDRESS:
|
|
*var_len = ifRow.dwPhysAddrLen;
|
|
memcpy(return_buf, ifRow.bPhysAddr, *var_len);
|
|
return (u_char *) return_buf;
|
|
case NETSNMP_IFADMINSTATUS:
|
|
long_return = ifRow.dwAdminStatus;
|
|
admin_status = long_return;
|
|
#ifndef NETSNMP_NO_WRITE_SUPPORT
|
|
*write_method = writeIfEntry;
|
|
#endif /* !NETSNMP_NO_WRITE_SUPPORT */
|
|
return (u_char *) & long_return;
|
|
case NETSNMP_IFOPERSTATUS:
|
|
long_return =
|
|
(MIB_IF_OPER_STATUS_OPERATIONAL == ifRow.dwOperStatus) ? 1 : 2;
|
|
return (u_char *) & long_return;
|
|
case NETSNMP_IFLASTCHANGE:
|
|
long_return = 0 /* XXX not a UNIX epochal time ifRow.dwLastChange */ ;
|
|
return (u_char *) & long_return;
|
|
case NETSNMP_IFINOCTETS:
|
|
long_return = ifRow.dwInOctets;
|
|
return (u_char *) & long_return;
|
|
case NETSNMP_IFINUCASTPKTS:
|
|
long_return = ifRow.dwInUcastPkts;
|
|
return (u_char *) & long_return;
|
|
case NETSNMP_IFINNUCASTPKTS:
|
|
long_return = ifRow.dwInNUcastPkts;
|
|
return (u_char *) & long_return;
|
|
case NETSNMP_IFINDISCARDS:
|
|
long_return = ifRow.dwInDiscards;
|
|
return (u_char *) & long_return;
|
|
case NETSNMP_IFINERRORS:
|
|
long_return = ifRow.dwInErrors;
|
|
return (u_char *) & long_return;
|
|
case NETSNMP_IFINUNKNOWNPROTOS:
|
|
long_return = ifRow.dwInUnknownProtos;
|
|
return (u_char *) & long_return;
|
|
case NETSNMP_IFOUTOCTETS:
|
|
long_return = ifRow.dwOutOctets;
|
|
return (u_char *) & long_return;
|
|
case NETSNMP_IFOUTUCASTPKTS:
|
|
long_return = ifRow.dwOutUcastPkts;
|
|
return (u_char *) & long_return;
|
|
case NETSNMP_IFOUTNUCASTPKTS:
|
|
long_return = ifRow.dwOutNUcastPkts;
|
|
return (u_char *) & long_return;
|
|
case NETSNMP_IFOUTDISCARDS:
|
|
long_return = ifRow.dwOutDiscards;
|
|
return (u_char *) & long_return;
|
|
case NETSNMP_IFOUTERRORS:
|
|
long_return = ifRow.dwOutErrors;
|
|
return (u_char *) & long_return;
|
|
case NETSNMP_IFOUTQLEN:
|
|
long_return = ifRow.dwOutQLen;
|
|
return (u_char *) & long_return;
|
|
case NETSNMP_IFSPECIFIC:
|
|
*var_len = nullOidLen;
|
|
return (u_char *) nullOid;
|
|
default:
|
|
DEBUGMSGTL(("snmpd", "unknown sub-id %d in var_ifEntry\n",
|
|
vp->magic));
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
|
|
#ifndef NETSNMP_NO_WRITE_SUPPORT
|
|
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] != NETSNMP_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: %lu & adminStatus %lu\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 /* !NETSNMP_NO_WRITE_SUPPORT */
|
|
#endif /* WIN32 cygwin */
|