335 lines
11 KiB
Diff
335 lines
11 KiB
Diff
From ecd91d8a2b532bd1a987369e76d75fef454f2bcf Mon Sep 17 00:00:00 2001
|
|
From: Mitsuru Chinen <mitch@linux.vnet.ibm.com>
|
|
Date: Mon, 20 Oct 2008 17:33:11 +0900
|
|
Subject: [PATCH] Add IPv6 support on Internet Address Translation Table
|
|
|
|
[ 1708243 ] add linux support for ipDefaultRouterTable OID to net-snmp
|
|
http://sourceforge.net/tracker/index.php?func=detail&aid=1708243&group_id=12694&atid=312694
|
|
|
|
[ 1724602 ] [Linux] ipDefaultRouterTable improvement
|
|
http://sourceforge.net/tracker/index.php?func=detail&aid=1724602&group_id=12694&atid=312694
|
|
|
|
[ 1728223 ] [Linux] add configure check for netlink socket
|
|
http://sourceforge.net/tracker/index.php?func=detail&aid=1728223&group_id=12694&atid=312694
|
|
|
|
Signed-off-by: Mitsuru Chinen <mitch@linux.vnet.ibm.com>
|
|
---
|
|
agent/mibgroup/ip-mib/data_access/arp_linux.c | 243 +++++++++++++++++++-
|
|
.../inetNetToMediaTable_data_access.c | 2 +-
|
|
configure.in | 10 +
|
|
3 files changed, 249 insertions(+), 6 deletions(-)
|
|
|
|
diff --git a/agent/mibgroup/ip-mib/data_access/arp_linux.c b/agent/mibgroup/ip-mib/data_access/arp_linux.c
|
|
index e1d20c1..a25e4d8 100644
|
|
--- a/agent/mibgroup/ip-mib/data_access/arp_linux.c
|
|
+++ b/agent/mibgroup/ip-mib/data_access/arp_linux.c
|
|
@@ -14,9 +14,32 @@
|
|
#include <netinet/in.h>
|
|
#include <net/if_arp.h>
|
|
#include <arpa/inet.h>
|
|
+#include <linux/types.h>
|
|
+#include <asm/types.h>
|
|
+#ifdef NETSNMP_ENABLE_IPV6
|
|
+#ifdef HAVE_LINUX_RTNETLINK_H
|
|
+#include <linux/rtnetlink.h>
|
|
+#define NIP6(addr) \
|
|
+ ntohs((addr).s6_addr16[0]), \
|
|
+ ntohs((addr).s6_addr16[1]), \
|
|
+ ntohs((addr).s6_addr16[2]), \
|
|
+ ntohs((addr).s6_addr16[3]), \
|
|
+ ntohs((addr).s6_addr16[4]), \
|
|
+ ntohs((addr).s6_addr16[5]), \
|
|
+ ntohs((addr).s6_addr16[6]), \
|
|
+ ntohs((addr).s6_addr16[7])
|
|
+#define NIP6_FMT "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x"
|
|
+#endif
|
|
+#endif
|
|
|
|
int _load_v4(netsnmp_container *container, int idx_offset);
|
|
-
|
|
+static int _load_v6(netsnmp_container *container, int idx_offset);
|
|
+#ifdef HAVE_LINUX_RTNETLINK_H
|
|
+int get_translation_table_info (int sd, int *status,
|
|
+ char *buff, size_t size);
|
|
+int fillup_entry_info(netsnmp_arp_entry *entry,
|
|
+ struct nlmsghdr *nlmp);
|
|
+#endif
|
|
/**
|
|
*/
|
|
int
|
|
@@ -28,11 +51,10 @@ netsnmp_access_arp_container_arch_load(netsnmp_container *container)
|
|
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;
|
|
+#if defined (NETSNMP_ENABLE_IPV6)
|
|
+ idx_offset = (rc < 0) ? 0 : rc;
|
|
|
|
rc = _load_v6(container, idx_offset);
|
|
if(rc < 0) {
|
|
@@ -64,7 +86,7 @@ _load_v4(netsnmp_container *container, int idx_offset)
|
|
|
|
#define PROCFILE "/proc/net/arp"
|
|
if (!(in = fopen(PROCFILE, "r"))) {
|
|
- snmp_log(LOG_ERR,"could not open " PROCFILE "\n");
|
|
+ snmp_log(LOG_DEBUG,"could not open " PROCFILE "\n");
|
|
return -2;
|
|
}
|
|
|
|
@@ -192,3 +214,214 @@ _load_v4(netsnmp_container *container, int idx_offset)
|
|
|
|
return idx_offset;
|
|
}
|
|
+
|
|
+#if defined (NETSNMP_ENABLE_IPV6)
|
|
+static int
|
|
+_load_v6(netsnmp_container *container, int idx_offset)
|
|
+{
|
|
+ char buffer[16384];
|
|
+#if defined(HAVE_LINUX_RTNETLINK_H)
|
|
+ struct nlmsghdr *nlmp;
|
|
+#endif
|
|
+ int sd = 0;
|
|
+ int status = 0;
|
|
+ int rc = 0;
|
|
+ int len, req_len;
|
|
+ netsnmp_arp_entry *entry;
|
|
+
|
|
+ netsnmp_assert(NULL != container);
|
|
+#if defined(HAVE_LINUX_RTNETLINK_H)
|
|
+ if((sd = socket (PF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE)) < 0) {
|
|
+ snmp_log(LOG_ERR,"Unable to create netlink socket\n");
|
|
+ return -2;
|
|
+ }
|
|
+
|
|
+ if(get_translation_table_info (sd, &status, buffer, sizeof(buffer)) < 0) {
|
|
+ snmp_log(LOG_ERR,"Unable to fetch translation table info\n");
|
|
+ close(sd);
|
|
+ return -2;
|
|
+ }
|
|
+
|
|
+ for (nlmp = (struct nlmsghdr *)buffer; status > sizeof(*nlmp); ) {
|
|
+ len = nlmp->nlmsg_len;
|
|
+ req_len = len - sizeof(*nlmp);
|
|
+ if (req_len < 0 || len > status) {
|
|
+ snmp_log(LOG_ERR,"invalid length\n");
|
|
+ return -2;
|
|
+ }
|
|
+ if (!NLMSG_OK (nlmp, status)) {
|
|
+ snmp_log(LOG_ERR,"NLMSG not OK\n");
|
|
+ return -2;
|
|
+ }
|
|
+ entry = netsnmp_access_arp_entry_create();
|
|
+ if(NULL == entry) {
|
|
+ rc = -3;
|
|
+ break;
|
|
+ }
|
|
+ entry->ns_arp_index = ++idx_offset;
|
|
+ if(fillup_entry_info (entry, nlmp) < 0) {
|
|
+ DEBUGMSGTL(("access:arp:load_v6", "filling entry info failed\n"));
|
|
+ netsnmp_access_arp_entry_free(entry);
|
|
+ status -= NLMSG_ALIGN(len);
|
|
+ nlmp = (struct nlmsghdr*)((char*)nlmp + NLMSG_ALIGN(len));
|
|
+ continue;
|
|
+ }
|
|
+ CONTAINER_INSERT(container, entry);
|
|
+ status -= NLMSG_ALIGN(len);
|
|
+ nlmp = (struct nlmsghdr*)((char*)nlmp + NLMSG_ALIGN(len));
|
|
+ }
|
|
+
|
|
+ close(sd);
|
|
+#endif
|
|
+ if(rc<0) {
|
|
+ return rc;
|
|
+ }
|
|
+
|
|
+ return idx_offset;
|
|
+}
|
|
+#if defined(HAVE_LINUX_RTNETLINK_H)
|
|
+int
|
|
+get_translation_table_info (int sd, int *status, char *buff, size_t size)
|
|
+{
|
|
+ struct {
|
|
+ struct nlmsghdr n;
|
|
+ struct ndmsg r;
|
|
+ char buf[1024];
|
|
+ } req;
|
|
+ struct rtattr *rta;
|
|
+
|
|
+ memset(&req, 0, sizeof(req));
|
|
+ req.n.nlmsg_len = NLMSG_LENGTH (sizeof(struct ndmsg));
|
|
+ req.n.nlmsg_flags = NLM_F_REQUEST | NLM_F_ROOT;
|
|
+ req.n.nlmsg_type = RTM_GETNEIGH;
|
|
+
|
|
+ req.r.ndm_family = AF_INET6;
|
|
+ rta = (struct rtattr *)(((char *)&req) + NLMSG_ALIGN(req.n.nlmsg_len));
|
|
+ rta->rta_len = RTA_LENGTH(16);
|
|
+
|
|
+ if(send(sd, &req, req.n.nlmsg_len, 0) < 0) {
|
|
+ snmp_log(LOG_ERR,"Sending request failed\n");
|
|
+ return -1;
|
|
+ }
|
|
+ if((*status = recv(sd, buff, size, 0)) < 0) {
|
|
+ snmp_log(LOG_ERR,"Recieving request failed\n");
|
|
+ return -1;
|
|
+ }
|
|
+ if(*status == 0) {
|
|
+ snmp_log(LOG_ERR,"End of file\n");
|
|
+ return -1;
|
|
+ }
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+int
|
|
+fillup_entry_info(netsnmp_arp_entry *entry, struct nlmsghdr *nlmp)
|
|
+{
|
|
+ struct ndmsg *rtmp;
|
|
+ struct in6_addr *in6p;
|
|
+ struct rtattr *tb[NDA_MAX+1], *rta;
|
|
+ size_t in_len, out_len;
|
|
+ unsigned int i;
|
|
+ int length;
|
|
+ char addr[40];
|
|
+ u_char *buf;
|
|
+ u_char *hwaddr;
|
|
+
|
|
+ rtmp = (struct ndmsg *)NLMSG_DATA(nlmp);
|
|
+ if (nlmp->nlmsg_type != RTM_NEWNEIGH && nlmp->nlmsg_type != RTM_DELNEIGH)
|
|
+ return -1;
|
|
+
|
|
+ if(rtmp->ndm_state != NUD_NOARP) {
|
|
+ memset(tb, 0, sizeof(struct rtattr *) * (NDA_MAX + 1));
|
|
+ length = nlmp->nlmsg_len - NLMSG_LENGTH(sizeof(*rtmp));
|
|
+ /* this is what the kernel-removed NDA_RTA define did */
|
|
+ rta = ((struct rtattr*)(((char*)(rtmp)) +
|
|
+ NLMSG_ALIGN(sizeof(struct ndmsg))));
|
|
+ while (RTA_OK(rta, length)) {
|
|
+ if (rta->rta_type <= NDA_MAX)
|
|
+ tb[rta->rta_type] = rta;
|
|
+ rta = RTA_NEXT(rta,length);
|
|
+ }
|
|
+ if(length)
|
|
+ return -1;
|
|
+ /* Fill up the index
|
|
+ */
|
|
+ entry->if_index = rtmp->ndm_ifindex;
|
|
+ /* Fill up ip address */
|
|
+ if (tb[NDA_DST]) {
|
|
+ memset(&addr, '\0', sizeof(addr));
|
|
+ in6p = (struct in6_addr *)RTA_DATA(tb[NDA_DST]);
|
|
+ sprintf(addr, NIP6_FMT, NIP6(*in6p));
|
|
+ in_len = entry->arp_ipaddress_len = sizeof(entry->arp_ipaddress);
|
|
+ netsnmp_assert(16 == in_len);
|
|
+ out_len = 0;
|
|
+ buf = entry->arp_ipaddress;
|
|
+ if(1 != netsnmp_hex_to_binary(&buf, &in_len,
|
|
+ &out_len, 0, addr, ":")) {
|
|
+ snmp_log(LOG_ERR,"error parsing '%s', skipping\n",
|
|
+ entry->arp_ipaddress);
|
|
+ return -1;
|
|
+ }
|
|
+ netsnmp_assert(16 == out_len);
|
|
+ entry->arp_ipaddress_len = out_len;
|
|
+ }
|
|
+ if (tb[NDA_LLADDR]) {
|
|
+ memset(&addr, '\0', sizeof(addr));
|
|
+ hwaddr = RTA_DATA(tb[NDA_LLADDR]);
|
|
+ entry->arp_physaddress_len = RTA_PAYLOAD(tb[NDA_LLADDR]);
|
|
+ buf = entry->arp_physaddress;
|
|
+ for (i = 0; i < entry->arp_physaddress_len; i++)
|
|
+ entry->arp_physaddress[i] = hwaddr[i];
|
|
+ }
|
|
+
|
|
+ switch (rtmp->ndm_state) {
|
|
+ case NUD_INCOMPLETE:
|
|
+ entry->arp_state = INETNETTOMEDIASTATE_INCOMPLETE;
|
|
+ break;
|
|
+ case NUD_REACHABLE:
|
|
+ case NUD_PERMANENT:
|
|
+ entry->arp_state = INETNETTOMEDIASTATE_REACHABLE;
|
|
+ break;
|
|
+ case NUD_STALE:
|
|
+ entry->arp_state = INETNETTOMEDIASTATE_STALE;
|
|
+ break;
|
|
+ case NUD_DELAY:
|
|
+ entry->arp_state = INETNETTOMEDIASTATE_DELAY;
|
|
+ break;
|
|
+ case NUD_PROBE:
|
|
+ entry->arp_state = INETNETTOMEDIASTATE_PROBE;
|
|
+ break;
|
|
+ case NUD_FAILED:
|
|
+ entry->arp_state = INETNETTOMEDIASTATE_INVALID;
|
|
+ break;
|
|
+ case NUD_NONE:
|
|
+ entry->arp_state = INETNETTOMEDIASTATE_UNKNOWN;
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ switch (rtmp->ndm_state) {
|
|
+ case NUD_INCOMPLETE:
|
|
+ case NUD_FAILED :
|
|
+ case NUD_NONE :
|
|
+ entry->arp_type = INETNETTOMEDIATYPE_INVALID;
|
|
+ break;
|
|
+ case NUD_REACHABLE:
|
|
+ case NUD_STALE :
|
|
+ case NUD_DELAY :
|
|
+ case NUD_PROBE :
|
|
+ entry->arp_type = INETNETTOMEDIATYPE_DYNAMIC;
|
|
+ break;
|
|
+ case NUD_PERMANENT:
|
|
+ entry->arp_type = INETNETTOMEDIATYPE_STATIC;
|
|
+ break;
|
|
+ default:
|
|
+ entry->arp_type = INETNETTOMEDIATYPE_LOCAL;
|
|
+ break;
|
|
+ }
|
|
+ } else {
|
|
+ return -1; /* could not create data for this interface */
|
|
+ }
|
|
+ return 0;
|
|
+}
|
|
+#endif
|
|
+#endif
|
|
diff --git a/agent/mibgroup/ip-mib/inetNetToMediaTable/inetNetToMediaTable_data_access.c b/agent/mibgroup/ip-mib/inetNetToMediaTable/inetNetToMediaTable_data_access.c
|
|
index cad942c..dcc7900 100644
|
|
--- a/agent/mibgroup/ip-mib/inetNetToMediaTable/inetNetToMediaTable_data_access.c
|
|
+++ b/agent/mibgroup/ip-mib/inetNetToMediaTable/inetNetToMediaTable_data_access.c
|
|
@@ -155,7 +155,7 @@ _snarf_arp_entry(netsnmp_arp_entry *arp_entry,
|
|
inetAddressType = INETADDRESSTYPE_IPV4;
|
|
break;
|
|
|
|
- case 6:
|
|
+ case 16:
|
|
inetAddressType = INETADDRESSTYPE_IPV6;
|
|
break;
|
|
|
|
diff --git a/configure.in b/configure.in
|
|
index c5e05ba..220506a 100644
|
|
--- a/configure.in
|
|
+++ b/configure.in
|
|
@@ -3365,6 +3365,16 @@ AC_CHECK_HEADERS(linux/rtnetlink.h,,,
|
|
#include <linux/netlink.h>
|
|
#endif
|
|
]])
|
|
+# linux rtnetlink
|
|
+AC_CHECK_HEADERS(linux/rtnetlink.h,,,
|
|
+[[
|
|
+#if HAVE_ASM_TYPES_H
|
|
+#include <asm/types.h>
|
|
+#endif
|
|
+#if HAVE_SYS_SOCKET_H
|
|
+#include <sys/socket.h>
|
|
+#endif
|
|
+]])
|
|
# BSDi3 headers
|
|
AC_CHECK_HEADERS(sys/stat.h)
|
|
# BSDi3/IRIX headers
|
|
--
|
|
1.6.0.2
|
|
|