net-snmp/Add-IPv6-support-on-Internet-Address-Translation-Tab.patch

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