blob: a2fa49aeb9ae17031728cff14bbfcb431c6c4b41 [file] [log] [blame]
/*
* Interface MIB architecture support
*/
#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>
#include <linux/types.h>
#include <asm/types.h>
static int _load_v4(netsnmp_arp_access *access);
netsnmp_arp_access *
netsnmp_access_arp_create(u_int init_flags,
NetsnmpAccessArpUpdate *update_hook,
NetsnmpAccessArpGC *gc_hook,
int *cache_timeout, int *cache_flags,
char *cache_expired)
{
netsnmp_arp_access *access;
access = SNMP_MALLOC_TYPEDEF(netsnmp_arp_access);
if (NULL == access) {
snmp_log(LOG_ERR,"malloc error in netsnmp_access_arp_create\n");
return NULL;
}
access->arch_magic = NULL;
access->magic = NULL;
access->update_hook = update_hook;
access->gc_hook = gc_hook;
access->synchronized = 0;
if (cache_timeout != NULL)
*cache_timeout = 5;
if (cache_flags != NULL)
*cache_flags |= NETSNMP_CACHE_DONT_FREE_BEFORE_LOAD
| NETSNMP_CACHE_AUTO_RELOAD;
access->cache_expired = cache_expired;
return access;
}
int netsnmp_access_arp_delete(netsnmp_arp_access *access)
{
if (NULL == access)
return 0;
netsnmp_access_arp_unload(access);
free(access);
return 0;
}
int netsnmp_access_arp_load(netsnmp_arp_access *access)
{
int rc = 0;
access->generation++;
rc =_load_v4(access);
access->gc_hook(access);
access->synchronized = (rc == 0);
return rc;
}
int netsnmp_access_arp_unload(netsnmp_arp_access *access)
{
access->synchronized = 0;
return 0;
}
/**
*/
static int
_load_v4(netsnmp_arp_access *access)
{
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 != access);
#define PROCFILE "/proc/net/arp"
if (!(in = fopen(PROCFILE, "r"))) {
snmp_log(LOG_DEBUG,"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;
unsigned 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->generation = access->generation;
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
*/
access->update_hook(access, entry);
}
fclose(in);
return 0;
}