blob: 91620fec84420338b785dc7371cc24d0c497a5cb [file] [log] [blame]
/*
* Interfaces MIB group implementation - interfaces.c
*
*/
#include <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>
#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(IFNET_NEEDS_KERNEL) && !defined(_KERNEL) && defined(IFNET_NEEDS_KERNEL_LATE)
#define _KERNEL 1
#define _I_DEFINED_KERNEL
#endif
#include <sys/socket.h>
#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
#include <net/if.h>
#if HAVE_NET_IF_VAR_H
#include <net/if_var.h>
#endif
#ifdef _I_DEFINED_KERNEL
#undef _KERNEL
#endif
#if HAVE_SYS_STREAM_H
#include <sys/stream.h>
#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
#include <netinet/ip.h>
#ifdef INET6
#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 INET6
#if HAVE_NETINET6_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
#include <net/if_dl.h>
#endif
#if HAVE_INET_MIB2_H
#include <inet/mib2.h>
#endif
#if HAVE_IOCTLS_H
#include <ioctls.h>
#endif
#if HAVE_DMALLOC_H
#include <dmalloc.h>
#endif
#include "mibincl.h"
#ifdef solaris2
#include "kernel_sunos5.h"
#else
#include "kernel.h"
#endif
#ifdef hpux
#include <sys/mib.h>
#include <netinet/mib_kern.h>
#endif /* hpux */
#if HAVE_SYS_SYSCTL_H
#include <sys/sysctl.h>
#ifdef freebsd3
# define USE_SYSCTL_IFLIST
#else
# if defined(CTL_NET) && !defined(freebsd2)
# 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 */
/* #include "../common_header.h" */
#include "system.h"
#include "snmp_logging.h"
#if HAVE_OSRELDATE_H
#include <osreldate.h>
#endif
#ifdef CAN_USE_SYSCTL
#include <sys/sysctl.h>
#endif
#include "interfaces.h"
#include "../struct.h"
#include "../util_funcs.h"
#include "auto_nlist.h"
#include "sysORTable.h"
static int Interface_Scan_Get_Count (void);
struct variable4 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}},
{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}},
{IFADMINSTATUS, ASN_INTEGER, RWRITE, var_ifEntry, 3, {2, 1, 7}},
{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, variable4, \
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
}
/*
* 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" },
{ 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 */
}
#ifdef USE_SYSCTL_IFLIST
static u_char * if_list = 0;
static const u_char * if_list_end;
static size_t if_list_size = 0;
/*
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
*/
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;
}
/*
header_interfaces(...
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
*/
static int
header_interfaces(struct variable *vp,
oid *name,
size_t *length,
int exact,
size_t *var_len,
WriteMethod **write_method)
{
#define INTERFACES_NAME_LENGTH 8
oid newname[MAX_OID_LEN];
int result;
DEBUGMSGTL(("mibII/interfaces", "var_interfaces: "));
DEBUGMSGOID(("mibII/interfaces", name, *length));
DEBUGMSG(("mibII/interfaces"," %d\n", exact));
memcpy( (char *)newname,(char *)vp->name, (int)vp->namelen * sizeof(oid));
newname[INTERFACES_NAME_LENGTH] = 0;
result = snmp_oid_compare(name, *length, newname, (int)vp->namelen + 1);
if ((exact && (result != 0)) || (!exact && (result >= 0)))
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 */
return MATCH_SUCCEEDED;
}
u_char *
var_interfaces(struct variable *vp,
oid *name,
size_t *length,
int exact,
size_t *var_len,
WriteMethod **write_method)
{
if (header_interfaces(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;
}
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;
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 NULL;
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 (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 NULL;
sifa->sifa_addr = *ia;
ia = get_in_address ((char *) (ifap+1)+8,
ifap->ifam_addrs &= ~RTA_NETMASK,
RTA_BRD);
if (ia == NULL)
return NULL;
sifa->sifa_broadcast = *ia;
++have_addr;
}
}
break;
default:
DEBUGMSGTL(("mibII/interfaces", "routing socket: unknown message type %d\n", ifp->ifm_type));
}
}
if (have_ifinfo && have_addr)
{
return 0;
}
else if (have_ifinfo && !(if_msg->ifm_flags & IFF_UP))
return 0;
else
{
return -1;
}
}
static int
Interface_Scan_Get_Count (void)
{
u_char *cp;
struct if_msghdr *ifp;
long n;
Interface_Scan_Init();
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 = 0;
}
if ((if_list = malloc (size)) == 0)
{
snmp_log(LOG_ERR,"out of memory allocating route table\n");
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];
struct small_ifaddr sifa;
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, &sifa) != 0)
return NULL;
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 IFTYPE:
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:
long_return = (u_long) if_msg.ifm_data.ifi_baudrate;
return (u_char *) &long_return;
case IFPHYSADDRESS:
/* XXX */
return NULL;
case IFADMINSTATUS:
long_return = if_msg.ifm_flags & IFF_RUNNING ? 1 : 2;
return (u_char *) &long_return;
case IFOPERSTATUS:
long_return = if_msg.ifm_flags & IFF_UP ? 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 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;
/* ifOutQLen */
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
static int Interface_Scan_By_Index (int, char *, struct ifnet *, struct in_ifaddr *);
static int Interface_Get_Ether_By_Index (int, u_char *);
#endif
/*********************
*
* Initialisation & common implementation functions
*
*********************/
#ifdef linux
typedef struct _conf_if_list {
char *name;
int type;
int speed;
struct _conf_if_list *next;
} conf_if_list;
conf_if_list *if_list;
struct ifnet *ifnetaddr_list;
#endif /* linux */
static int
header_interfaces(struct variable *vp,
oid *name,
size_t *length,
int exact,
size_t *var_len,
WriteMethod **write_method)
{
#define INTERFACES_NAME_LENGTH 8
oid newname[MAX_OID_LEN];
int result;
DEBUGMSGTL(("mibII/interfaces", "var_interfaces: "));
DEBUGMSGOID(("mibII/interfaces", name, *length));
DEBUGMSG(("mibII/interfaces"," %d\n", exact));
memcpy( (char *)newname,(char *)vp->name, (int)vp->namelen * sizeof(oid));
newname[INTERFACES_NAME_LENGTH] = 0;
result = snmp_oid_compare(name, *length, newname, vp->namelen + 1);
if ((exact && (result != 0)) || (!exact && (result >= 0)))
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 */
return MATCH_SUCCEEDED;
}
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, 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;
}
/*********************
*
* System specific implementation functions
*
*********************/
u_char *
var_interfaces(struct variable *vp,
oid *name,
size_t *length,
int exact,
size_t *var_len,
WriteMethod **write_method)
{
if (header_interfaces(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;
}
#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;
register int interface;
static struct in_ifaddr in_ifaddr;
static char Name[16];
register char *cp;
#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);
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 IFTYPE:
#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 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((long_return == 0) || (long_return == 1)) {
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 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);
*var_len = 6;
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;
return(u_char *) return_buf;
case IFADMINSTATUS:
long_return = ifnet.if_flags & IFF_RUNNING ? 1 : 2;
return (u_char *) &long_return;
case IFOPERSTATUS:
long_return = ifnet.if_flags & IFF_UP ? 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 {
gettimeofday(&now, (struct timezone *)0);
long_return = (u_long)
((now.tv_sec - ifnet.if_lastchange.tv_sec) * 100
+ (now.tv_usec - ifnet.if_lastchange.tv_usec) / 10000);
}
#else
#if NO_DUMMY_VALUES
return NULL;
#endif
long_return = 0; /* XXX */
#endif
return (u_char *) &long_return;
case IFINOCTETS:
#ifdef STRUCT_IFNET_HAS_IF_IBYTES
long_return = (u_long) ifnet.if_ibytes;
#else
#if NO_DUMMY_VALUES
return NULL;
#endif
long_return = (u_long) ifnet.if_ipackets * 308; /* XXX */
#endif
return (u_char *) &long_return;
case IFINUCASTPKTS:
{
long_return = (u_long) ifnet.if_ipackets;
#if STRUCT_IFNET_HAS_IF_IMCASTS
long_return -= (u_long) ifnet.if_imcasts;
#endif
}
return (u_char *) &long_return;
case IFINNUCASTPKTS:
#if STRUCT_IFNET_HAS_IF_IMCASTS
long_return = (u_long) ifnet.if_imcasts;
#else
#if 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
long_return = (u_long) ifnet.if_iqdrops;
#else
#if NO_DUMMY_VALUES
return NULL;
#endif
long_return = (u_long) 0; /* XXX */
#endif
return (u_char *) &long_return;
case IFINERRORS:
long_return = (u_long) ifnet.if_ierrors;
return (u_char *) &long_return;
case IFINUNKNOWNPROTOS:
#if STRUCT_IFNET_HAS_IF_NOPROTO
long_return = (u_long) ifnet.if_noproto;
#else
#if 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
long_return = (u_long) ifnet.if_obytes;
#else
#if NO_DUMMY_VALUES
return NULL;
#endif
long_return = (u_long) ifnet.if_opackets * 308; /* XXX */
#endif
return (u_char *) &long_return;
case IFOUTUCASTPKTS:
{
long_return = (u_long) ifnet.if_opackets;
#if STRUCT_IFNET_HAS_IF_OMCASTS
long_return -= (u_long) ifnet.if_omcasts;
#endif
}
return (u_char *) &long_return;
case IFOUTNUCASTPKTS:
#if STRUCT_IFNET_HAS_IF_OMCASTS
long_return = (u_long) ifnet.if_omcasts;
#else
#if NO_DUMMY_VALUES
return NULL;
#endif
long_return = (u_long) 0; /* XXX */
#endif
return (u_char *) &long_return;
case IFOUTDISCARDS:
long_return = ifnet.if_snd.ifq_drops;
return (u_char *) &long_return;
case IFOUTERRORS:
long_return = ifnet.if_oerrors;
return (u_char *) &long_return;
case IFOUTQLEN:
long_return = ifnet.if_snd.ifq_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;
}
#else /* 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;
register int interface;
static struct in_ifaddr in_ifaddrVar;
static char Name[16];
register char *cp;
#if STRUCT_IFNET_HAS_IF_LASTCHANGE_TV_SEC
struct timeval now;
#endif
struct nmparms hp_nmparms;
static mib_ifEntry hp_ifEntry;
int hp_fd;
int hp_len=sizeof(hp_ifEntry);
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_ifaddrVar);
/*
* 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 = &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 */
}
}
switch (vp->magic){
case IFINDEX:
long_return = interface;
return (u_char *) &long_return;
case IFDESCR:
if ( hp_fd != -1 )
cp = hp_ifEntry.ifDescr;
else
cp = Name;
*var_len = strlen(cp);
return (u_char *)cp;
case IFTYPE:
if ( hp_fd != -1 )
long_return = hp_ifEntry.ifType;
else
long_return = 1; /* OTHER */
return (u_char *) &long_return;
case IFMTU: {
long_return = (long) ifnet.if_mtu;
return (u_char *) &long_return;
}
case IFSPEED:
if ( hp_fd != -1 )
long_return = hp_ifEntry.ifSpeed;
else
long_return = (u_long) 1; /* OTHER */
return (u_char *) &long_return;
case IFPHYSADDRESS:
Interface_Get_Ether_By_Index(interface, return_buf);
*var_len = 6;
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;
return(u_char *) return_buf;
case IFADMINSTATUS:
long_return = ifnet.if_flags & IFF_RUNNING ? 1 : 2;
return (u_char *) &long_return;
case IFOPERSTATUS:
long_return = ifnet.if_flags & IFF_UP ? 1 : 2;
return (u_char *) &long_return;
case IFLASTCHANGE:
if ( hp_fd != -1 )
long_return = hp_ifEntry.ifLastChange;
else
long_return = 0; /* XXX */
return (u_char *) &long_return;
case IFINOCTETS:
if ( hp_fd != -1 )
long_return = hp_ifEntry.ifInOctets;
else
long_return = (u_long) ifnet.if_ipackets * 308; /* XXX */
return (u_char *) &long_return;
case IFINUCASTPKTS:
if ( hp_fd != -1 )
long_return = hp_ifEntry.ifInUcastPkts;
else
long_return = (u_long) ifnet.if_ipackets;
return (u_char *) &long_return;
case IFINNUCASTPKTS:
if ( hp_fd != -1 )
long_return = hp_ifEntry.ifInNUcastPkts;
else
long_return = (u_long) 0; /* XXX */
return (u_char *) &long_return;
case IFINDISCARDS:
if ( hp_fd != -1 )
long_return = hp_ifEntry.ifInDiscards;
else
long_return = (u_long) 0; /* XXX */
return (u_char *) &long_return;
case IFINERRORS:
return (u_char *) &ifnet.if_ierrors;
case IFINUNKNOWNPROTOS:
if ( hp_fd != -1 )
long_return = hp_ifEntry.ifInUnknownProtos;
else
long_return = (u_long) 0; /* XXX */
return (u_char *) &long_return;
case IFOUTOCTETS:
if ( hp_fd != -1 )
long_return = hp_ifEntry.ifOutOctets;
else
long_return = (u_long) ifnet.if_opackets * 308; /* XXX */
return (u_char *) &long_return;
case IFOUTUCASTPKTS:
if ( hp_fd != -1 )
long_return = hp_ifEntry.ifOutUcastPkts;
else
long_return = (u_long) ifnet.if_opackets;
return (u_char *) &long_return;
case IFOUTNUCASTPKTS:
if ( hp_fd != -1 )
long_return = hp_ifEntry.ifOutNUcastPkts;
else
long_return = (u_long) 0; /* XXX */
return (u_char *) &long_return;
case IFOUTDISCARDS:
return (u_char *) &ifnet.if_snd.ifq_drops;
case IFOUTERRORS:
return (u_char *) &ifnet.if_oerrors;
case IFOUTQLEN:
return (u_char *) &ifnet.if_snd.ifq_len;
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;
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;
}
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 IFTYPE:
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:
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;
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)
static struct in_ifaddr savein_ifaddr;
#endif
static struct ifnet *ifnetaddr, saveifnet, *saveifnetaddr;
static int saveIndex=0;
static char saveName[16];
void
Interface_Scan_Init (void)
{
#ifdef linux
char line [256], fullname [64], ifname_buf [64], *ifname, *ptr;
struct ifreq ifrq;
struct ifnet **ifnetaddr_ptr;
FILE *devin;
unsigned long rec_pkt, rec_oct, rec_err, snd_pkt, snd_oct, snd_err, coll;
int i, fd;
extern conf_if_list *if_list;
conf_if_list *if_ptr;
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";
const char *scan_line_to_use;
#endif
auto_nlist(IFNET_SYMBOL, (char *)&ifnetaddr, sizeof(ifnetaddr));
saveIndex=0;
#ifdef linux
/* 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;
while (*ifstart == ' ') ifstart++;
stats = strrchr(ifstart, ':');
*stats++ = 0;
strcpy(ifname_buf, ifstart);
while (*stats == ' ') stats++;
if ((scan_line_to_use == scan_line_2_2 &&
sscanf (stats, scan_line_to_use, &rec_oct, &rec_pkt, &rec_err, &snd_oct, &snd_pkt, &snd_err, &coll) != 7) ||
(scan_line_to_use == scan_line_2_0 &&
sscanf (stats, scan_line_to_use, &rec_pkt, &rec_err, &snd_pkt, &snd_err, &coll) != 5))
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;
nnew->if_ierrors = rec_err;
nnew->if_opackets = snd_pkt;
nnew->if_oerrors = snd_err;
nnew->if_collisions = coll;
if (scan_line_to_use == scan_line_2_2) {
nnew->if_ibytes = rec_oct; nnew->if_obytes = snd_oct;
}
else {
nnew->if_ibytes = rec_pkt*308; nnew->if_obytes = snd_pkt*308;
}
/* 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 : "0");
*ptr = 0;
strcpy (ifrq.ifr_name, ifname);
if (ioctl (fd, SIOCGIFADDR, &ifrq) < 0)
memset ((char *) &nnew->if_addr, 0, sizeof (nnew->if_addr));
else
nnew->if_addr = ifrq.ifr_addr;
strcpy (ifrq.ifr_name, ifname);
if (ioctl (fd, SIOCGIFBRDADDR, &ifrq) < 0)
memset ((char *)&nnew->ifu_broadaddr, 0, sizeof(nnew->ifu_broadaddr));
else
nnew->ifu_broadaddr = ifrq.ifr_broadaddr;
strcpy (ifrq.ifr_name, ifname);
if (ioctl (fd, SIOCGIFNETMASK, &ifrq) < 0)
memset ((char *)&nnew->ia_subnetmask, 0, sizeof(nnew->ia_subnetmask));
else
nnew->ia_subnetmask = ifrq.ifr_netmask;
strcpy (ifrq.ifr_name, ifname);
nnew->if_flags = ioctl (fd, SIOCGIFFLAGS, &ifrq) < 0
? 0 : ifrq.ifr_flags;
strcpy (ifrq.ifr_name, ifname);
if (ioctl(fd, SIOCGIFHWADDR, &ifrq) < 0)
memset (nnew->if_hwaddr,(0), 6);
else
memcpy (nnew->if_hwaddr, ifrq.ifr_hwaddr.sa_data, 6);
strcpy (ifrq.ifr_name, ifname);
nnew->if_metric = ioctl (fd, SIOCGIFMETRIC, &ifrq) < 0
? 0 : ifrq.ifr_metric;
#ifdef SIOCGIFMTU
strcpy (ifrq.ifr_name, ifname);
nnew->if_mtu = (ioctl (fd, SIOCGIFMTU, &ifrq) < 0)
? 0 : ifrq.ifr_mtu;
#else
nnew->if_mtu = 0;
#endif
for (if_ptr = if_list; if_ptr; if_ptr = if_ptr->next)
if (! strcmp (if_ptr->name, fullname))
break;
if (if_ptr) {
nnew->if_type = if_ptr->type;
nnew->if_speed = if_ptr->speed;
}
else {
nnew->if_type = if_type_from_name(nnew->if_name);
nnew->if_speed = nnew->if_type == 6 ? 10000000 :
nnew->if_type == 24 ? 10000000 : 0;
}
} /* 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
klookup((unsigned long)ifnetaddr, (char *)&ifnet, sizeof ifnet);
klookup((unsigned long)ifnet.if_name, (char *)saveName, sizeof saveName);
#else
ifnet = *ifnetaddr;
strcpy (saveName, ifnet.if_name);
#endif
if (strcmp(saveName, "ip") == 0) {
ifnetaddr = ifnet.if_next;
continue;
}
saveName[sizeof (saveName)-1] = '\0';
cp = (char *) strchr(saveName, '\0');
#ifdef linux
strcat (cp, ifnet.if_unit);
#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 */
}
#else
#if defined(netbsd1) || defined(openbsd2)
#define ia_next ia_list.tqe_next
#define if_next if_list.tqe_next
#endif
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;
#if !STRUCT_IFNET_HAS_IF_XNAME
register char *cp;
#endif
while (ifnetaddr) {
/*
* Get the "ifnet" structure and extract the device name
*/
klookup((unsigned long)ifnetaddr, (char *)&ifnet, sizeof ifnet);
#if STRUCT_IFNET_HAS_IF_XNAME
#if defined(netbsd1) || defined(openbsd2)
strncpy(saveName, ifnet.if_xname, sizeof saveName);
#else
klookup((unsigned long)ifnet.if_xname, (char *)saveName, sizeof saveName);
#endif
saveName[sizeof (saveName)-1] = '\0';
#else
klookup((unsigned long)ifnet.if_name, (char *)saveName, sizeof saveName);
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
*/
auto_nlist(IFADDR_SYMBOL, (char *)&ia, sizeof(ia));
while (ia) {
klookup((unsigned long)ia , (char *)&in_ifaddr, sizeof(in_ifaddr));
if (in_ifaddr.ia_ifp == ifnetaddr) break;
ia = in_ifaddr.ia_next;
}
#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)
*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 /* sunV3 */
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 */
}
static int Interface_Count=0;
static int Interface_Scan_Get_Count (void)
{
if (!Interface_Count) {
Interface_Scan_Init();
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)
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))
klookup((unsigned long)saveifnetaddr, (char *)&arpcom, sizeof arpcom);
#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) {
klookup(ifaddraddr, (char *)&ifaddr, sizeof ifaddr);
klookup((unsigned long)ifaddr.ifa_addr, (char *)&sadl, sizeof sadl);
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 */
}
#else /* solaris2 */
static 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)
{
int i, sd, ret;
char buf[1024];
struct ifconf ifconf;
struct ifreq *ifrp;
if (Name == 0)
return (0);
if ((sd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
return (0);
ifconf.ifc_buf = buf;
ifconf.ifc_len = sizeof(buf);
if (ioctl(sd, SIOCGIFCONF, &ifconf) == -1) {
ret = 0;
goto Return;
}
for (i = 1, ifrp = ifconf.ifc_req, ret = 0;
(char *)ifrp < (char *)ifconf.ifc_buf + ifconf.ifc_len; i++, ifrp++)
if (strncmp(Name, ifrp->ifr_name, Len) == 0) {
ret = i;
break;
} else
ret = 0;
Return:
close(sd);
return (ret); /* DONE */
}
#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;
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)
return;
cp = physaddrbuf = malloc(len);
if (physaddrbuf == 0)
return;
if (sysctl(mib, 6, physaddrbuf, &len, 0, 0) < 0) {
free(physaddrbuf);
physaddrbuf = 0;
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) {
free(physaddrs);
physaddrs = 0;
free(physaddrbuf);
physaddrbuf = 0;
}
ifm = (struct if_msghdr *)rtm;
ilen -= ifm->ifm_msglen;
cp += ifm->ifm_msglen;
rtm = (struct rt_msghdr *)cp;
while (ilen > 0 && rtm->rtm_type == RTM_NEWADDR) {
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;
}
rtm = (struct rt_msghdr *)cp;
}
}
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--);
if (i < nphysaddrs) {
*ap = LLADDR(physaddrs[i]);
*len = physaddrs[i]->sdl_alen;
return 0;
}
return -1;
}
static int
header_interfaces(struct variable *vp,
oid *name,
size_t *length,
int exact,
size_t *var_len,
WriteMethod **write_method)
{
#define INTERFACES_NAME_LENGTH 8
oid newname[MAX_OID_LEN];
int result;
DEBUGMSGTL(("mibII/interfaces", "var_interfaces: "));
DEBUGMSGOID(("mibII/interfaces", name, *length));
DEBUGMSG(("mibII/interfaces", " %d\n", exact));
memcpy(newname, vp->name, (int)vp->namelen * sizeof(oid));
newname[INTERFACES_NAME_LENGTH] = 0;
result = snmp_oid_compare(name, *length, newname, (int)vp->namelen + 1);
if ((exact && (result != 0)) || (!exact && (result >= 0)))
return MATCH_FAILED;
memcpy(name, newname, ((int)vp->namelen + 1) * sizeof(oid));
*length = vp->namelen + 1;
*write_method = 0;
*var_len = sizeof(long); /* default to 'long' results */
return MATCH_SUCCEEDED;
}
static int count_oid[5] = { CTL_NET, PF_LINK, NETLINK_GENERIC,
IFMIB_SYSTEM, IFMIB_IFCOUNT };
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;
static int count_oid[5] = { CTL_NET, PF_LINK, NETLINK_GENERIC,
IFMIB_SYSTEM, IFMIB_IFCOUNT };
size_t len;
#ifdef DODEBUG
DEBUGMSGTL(("mibII/interfaces", "var_ifEntry: "));
DEBUGMSGOID(("mibII/interfaces", name, *length));
DEBUGMSG(("mibII/interfaces"," %d\n", exact));
#endif
memcpy(newname, vp->name, (int)vp->namelen * sizeof(oid));
/* find "next" interface */
len = sizeof count;
if (sysctl(count_oid, 5, &count, &len, (void *)0, (size_t)0) < 0)
return MATCH_FAILED;
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) {
#ifdef DODEBUG
DEBUGMSGTL(("interfaces", "... index out of range\n"));
#endif
return MATCH_FAILED;
}
memcpy(name, newname, ((int)vp->namelen + 1) * sizeof(oid));
*length = vp->namelen + 1;
*write_method = 0;
*var_len = sizeof(long); /* default to 'long' results */
#ifdef DODEBUG
DEBUGMSGTL(("interfaces", "... get I/F stats "));
DEBUGMSGOID(("interfaces", name, *length));
DEBUGMSG(("interfaces","\n"));
#endif
return interface;
}
u_char *
var_interfaces(struct variable *vp,
oid *name,
size_t *length,
int exact,
size_t *var_len,
WriteMethod **write_method)
{
size_t len;
int count;
if (header_interfaces(vp, name, length, exact, var_len, write_method)
== MATCH_FAILED)
return NULL;
switch (vp->magic){
case IFNUMBER:
len = sizeof count;
if (sysctl(count_oid, 5, &count, &len, 0, 0) < 0)
return NULL;
long_return = count;
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 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;
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)
return NULL;
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 IFTYPE:
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:
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_RUNNING ? 1 : 2;
return (u_char *) &long_return;
case IFOPERSTATUS:
long_return = ifmd.ifmd_flags & IFF_UP ? 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 {
struct timeval now;
gettimeofday(&now, (struct timezone *)0);
long_return = (u_long)
((now.tv_sec
- ifmd.ifmd_data.ifi_lastchange.tv_sec) * 100
+ ((now.tv_usec
- ifmd.ifmd_data.ifi_lastchange.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