blob: 75d94c0081111eff3ecd92411ab19d3a5ad502f0 [file] [log] [blame]
/*
* Interface MIB architecture support
*
* $Id$
*/
#include <net-snmp/net-snmp-config.h>
#include <net-snmp/net-snmp-includes.h>
#include <net-snmp/agent/net-snmp-agent-includes.h>
#include <net-snmp/data_access/arp.h>
#include <net-snmp/data_access/interface.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <net/if_arp.h>
#include <arpa/inet.h>
int _load_v4(netsnmp_container *container, int idx_offset);
/**
*/
int
netsnmp_access_arp_container_arch_load(netsnmp_container *container)
{
int rc = 0, idx_offset = 0;
rc = _load_v4(container, idx_offset);
if(rc < 0) {
u_int flags = NETSNMP_ACCESS_ARP_FREE_KEEP_CONTAINER;
netsnmp_access_arp_container_free(container, flags);
return rc;
}
#if defined (NETSNMP_ENABLE_IPV6) && 0 /* xx-rks: arp for v6? */
idx_offset = rc;
rc = _load_v6(container, idx_offset);
if(rc < 0) {
u_int flags = NETSNMP_ACCESS_ARP_FREE_KEEP_CONTAINER;
netsnmp_access_arp_container_free(container, flags);
}
#endif
/*
* return no errors (0) if we found any interfaces
*/
if(rc > 0)
rc = 0;
return rc;
}
/**
*/
int
_load_v4(netsnmp_container *container, int idx_offset)
{
FILE *in;
char line[128];
int rc = 0;
netsnmp_arp_entry *entry;
char arp[3*NETSNMP_ACCESS_ARP_PHYSADDR_BUF_SIZE+1];
char *arp_token;
int i;
netsnmp_assert(NULL != container);
#define PROCFILE "/proc/net/arp"
if (!(in = fopen(PROCFILE, "r"))) {
snmp_log(LOG_ERR,"could not open " PROCFILE "\n");
return -2;
}
/*
* Get rid of the header line
*/
fgets(line, sizeof(line), in);
/*
* IP address | HW | Flag | HW address | Mask | Device
* 192.168.1.4 0x1 0x2 00:40:63:CC:1C:8C * eth0
*/
while (fgets(line, sizeof(line), in)) {
int za, zb, zc, zd;
int tmp_flags;
char ifname[21];
rc = sscanf(line,
"%d.%d.%d.%d 0x%*x 0x%x %96s %*[^ ] %20s\n",
&za, &zb, &zc, &zd, &tmp_flags, arp, ifname);
if (7 != rc) {
snmp_log(LOG_ERR, PROCFILE " data format error (%d!=12)\n", rc);
snmp_log(LOG_ERR, " line ==|%s|\n", line);
continue;
}
DEBUGMSGTL(("access:arp:container",
"ip addr %d.%d.%d.%d, flags 0x%X, hw addr "
"%s, name %s\n",
za,zb,zc,zd, tmp_flags, arp, ifname ));
/*
*/
entry = netsnmp_access_arp_entry_create();
if(NULL == entry) {
rc = -3;
break;
}
/*
* look up ifIndex
*/
entry->if_index = netsnmp_access_interface_index_find(ifname);
if(0 == entry->if_index) {
snmp_log(LOG_ERR,"couldn't find ifIndex for '%s', skipping\n",
ifname);
netsnmp_access_arp_entry_free(entry);
continue;
}
/*
* now that we've passed all the possible 'continue', assign
* index offset.
*/
entry->ns_arp_index = ++idx_offset;
/*
* parse ip addr
*/
entry->arp_ipaddress[0] = za;
entry->arp_ipaddress[1] = zb;
entry->arp_ipaddress[2] = zc;
entry->arp_ipaddress[3] = zd;
entry->arp_ipaddress_len = 4;
/*
* parse hw addr
*/
for (arp_token = strtok(arp, ":"), i=0; arp_token != NULL; arp_token = strtok(NULL, ":"), i++) {
entry->arp_physaddress[i] = strtol(arp_token, NULL, 16);
}
entry->arp_physaddress_len = i;
/*
* what can we do with hw? from arp manpage:
default value of this parameter is ether (i.e. hardware code
0x01 for IEEE 802.3 10Mbps Ethernet). Other values might
include network technologies such as ARCnet (arcnet) , PROnet
(pronet) , AX.25 (ax25) and NET/ROM (netrom).
*/
/*
* parse mask
*/
/* xxx-rks: what is mask? how to interpret '*'? */
/*
* process type
*/
if(tmp_flags & ATF_PERM)
entry->arp_type = INETNETTOMEDIATYPE_STATIC;
else
entry->arp_type = INETNETTOMEDIATYPE_DYNAMIC;
/*
* process status
* if flags are 0, we can't tell the difference between
* stale or incomplete.
*/
if(tmp_flags & ATF_COM)
entry->arp_state = INETNETTOMEDIASTATE_REACHABLE;
else
entry->arp_state = INETNETTOMEDIASTATE_UNKNOWN;
/*
* add entry to container
*/
if (CONTAINER_INSERT(container, entry) < 0)
{
DEBUGMSGTL(("access:arp:container","error with arp_entry: insert into container failed.\n"));
netsnmp_access_arp_entry_free(entry);
continue;
}
}
fclose(in);
if( rc < 0 )
return rc;
return idx_offset;
}