blob: b814f60641150f1708f7cfb7faeccdac22cd9152 [file] [log] [blame]
/*
* Interface MIB architecture support
*
* $Id: ipv6scopezone_linux.c 14170 2007-04-29 02:22:12Z varun_c $
*/
#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/scopezone.h>
#if defined (NETSNMP_ENABLE_IPV6)
static int _scopezone_v6(netsnmp_container* container, int idx_offset);
#endif
/*
*
* @retval 0 success
* @retval -1 no container specified
* @retval -2 could not open file
* @retval -3 could not create entry (probably malloc)
* @retval -4 file format error
*/
int
netsnmp_access_scopezone_container_arch_load(netsnmp_container* container,
u_int load_flags)
{
int rc1 = 0, idx_offset = 0;
#if defined (NETSNMP_ENABLE_IPV6)
if (NULL == container) {
snmp_log(LOG_ERR, "no container specified/found for access_scopezone_\n");
return -1;
}
rc1 = _scopezone_v6(container, idx_offset);
#endif
if(rc1 > 0)
rc1 = 0;
return rc1;
}
#if defined (NETSNMP_ENABLE_IPV6)
/* scope identifiers, from kernel - include/net/ipv6.h */
#define IPV6_ADDR_LOOPBACK 0x0010U
#define IPV6_ADDR_LINKLOCAL 0x0020U
#define IPV6_ADDR_SITELOCAL 0x0040U
static int
_scopezone_v6(netsnmp_container* container, int idx_offset)
{
/*
* On Linux, we support only link-local scope zones.
* Each interface, which has link-local address, gets unique scope
* zone index.
*/
FILE *in;
char line[80], addr[40];
int if_index, pfx_len, scope, flags, rc = 0;
int last_if_index = -1;
netsnmp_v6scopezone_entry *entry;
netsnmp_assert(NULL != container);
#define PROCFILE "/proc/net/if_inet6"
if (!(in = fopen(PROCFILE, "r"))) {
DEBUGMSGTL(("access:scopezone:container","could not open " PROCFILE "\n"));
return -2;
}
/*
* address index prefix_len scope status if_name
*/
while (fgets(line, sizeof(line), in)) {
/*
* fe800000000000000200e8fffe5b5c93 05 40 20 80 eth0
* A D P S F I
* A: address
* D: device number
* P: prefix len
* S: scope (see include/net/ipv6.h, net/ipv6/addrconf.c)
* F: flags (see include/linux/rtnetlink.h, net/ipv6/addrconf.c)
* I: interface
*/
rc = sscanf(line, "%39s %04x %02x %02x %02x\n",
addr, &if_index, &pfx_len, &scope, &flags);
if( 5 != rc ) {
snmp_log(LOG_ERR, PROCFILE " data format error (%d!=5), line ==|%s|\n",
rc, line);
continue;
}
DEBUGMSGTL(("access:scopezone:container",
"addr %s, index %d, pfx %d, scope %d, flags 0x%X\n",
addr, if_index, pfx_len, scope, flags));
if (! (scope & IPV6_ADDR_LINKLOCAL)) {
DEBUGMSGTL(("access:scopezone:container",
"The address is not link-local, skipping\n"));
continue;
}
/*
* Check that the interface was not inserted before, just in case
* one interface has two or more link-local addresses.
*/
if (last_if_index == if_index) {
DEBUGMSGTL(("access:scopezone:container",
"The interface was already inserted, skipping\n"));
continue;
}
last_if_index = if_index;
entry = netsnmp_access_scopezone_entry_create();
if(NULL == entry) {
rc = -3;
break;
}
entry->ns_scopezone_index = ++idx_offset;
entry->index = if_index;
entry->scopezone_linklocal = if_index;
CONTAINER_INSERT(container, entry);
}
fclose(in);
if(rc<0)
return rc;
return idx_offset;
}
#endif