406 lines
15 KiB
Diff
406 lines
15 KiB
Diff
From 12cb1f471833a7e145bdf7cb4d471d0bd74d73f0 Mon Sep 17 00:00:00 2001
|
|
From: Mitsuru Chinen <mitch@linux.vnet.ibm.com>
|
|
Date: Mon, 20 Oct 2008 16:08:06 +0900
|
|
Subject: [PATCH] Fix for Internet Address Table
|
|
|
|
From net-snmp patch tracker:
|
|
[ 1692817 ] ipAddressTable fixes
|
|
http://sourceforge.net/tracker/index.php?func=detail&aid=1692817&group_id=12694&atid=312694
|
|
|
|
[ 1712645 ] meaningful log message on duplicate IP address
|
|
http://sourceforge.net/tracker/index.php?func=detail&aid=1712645&group_id=12694&atid=312694
|
|
|
|
[ 1810660 ] Fix broadcast addresses in ipAddressTable on 64 bit
|
|
linux
|
|
http://sourceforge.net/tracker/index.php?func=detail&aid=1810660&group_id=12694&atid=312694
|
|
|
|
Signed-off-by: Mitsuru Chinen <mitch@linux.vnet.ibm.com>
|
|
---
|
|
.../mibgroup/ip-mib/data_access/ipaddress_ioctl.c | 63 +++++++++-
|
|
.../mibgroup/ip-mib/data_access/ipaddress_ioctl.h | 13 ++
|
|
.../mibgroup/ip-mib/data_access/ipaddress_linux.c | 121 ++++++++++++++++++--
|
|
.../ip-mib/ipAddressTable/ipAddressTable.c | 5 +-
|
|
include/net-snmp/library/container.h | 2 +-
|
|
snmplib/container.c | 2 +-
|
|
6 files changed, 189 insertions(+), 17 deletions(-)
|
|
|
|
diff --git a/agent/mibgroup/ip-mib/data_access/ipaddress_ioctl.c b/agent/mibgroup/ip-mib/data_access/ipaddress_ioctl.c
|
|
index d5e78f0..085653d 100644
|
|
--- a/agent/mibgroup/ip-mib/data_access/ipaddress_ioctl.c
|
|
+++ b/agent/mibgroup/ip-mib/data_access/ipaddress_ioctl.c
|
|
@@ -135,7 +135,9 @@ _netsnmp_ioctl_ipaddress_container_load_v4(netsnmp_container *container,
|
|
struct ifreq *ifrp;
|
|
struct sockaddr save_addr;
|
|
struct sockaddr_in * si;
|
|
- netsnmp_ipaddress_entry *entry;
|
|
+ netsnmp_ipaddress_entry *entry, *bcastentry;
|
|
+ struct address_flag_info addr_info;
|
|
+ in_addr_t ipval;
|
|
_ioctl_extras *extras;
|
|
|
|
if ((sd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
|
|
@@ -184,6 +186,7 @@ _netsnmp_ioctl_ipaddress_container_load_v4(netsnmp_container *container,
|
|
netsnmp_assert(AF_INET == ifrp->ifr_addr.sa_family);
|
|
si = (struct sockaddr_in *) &ifrp->ifr_addr;
|
|
entry->ia_address_len = sizeof(si->sin_addr.s_addr);
|
|
+ ipval = si->sin_addr.s_addr;
|
|
memcpy(entry->ia_address, &si->sin_addr.s_addr,
|
|
entry->ia_address_len);
|
|
|
|
@@ -220,6 +223,26 @@ _netsnmp_ioctl_ipaddress_container_load_v4(netsnmp_container *container,
|
|
}
|
|
|
|
/*
|
|
+ * get broadcast
|
|
+ */
|
|
+ memset(&addr_info, 0, sizeof(struct address_flag_info));
|
|
+#if defined (NETSNMP_ENABLE_IPV6)
|
|
+ addr_info = netsnmp_access_other_info_get(entry->if_index, AF_INET);
|
|
+ if(addr_info.bcastflg) {
|
|
+ bcastentry = netsnmp_access_ipaddress_entry_create();
|
|
+ if(NULL == entry) {
|
|
+ rc = -3;
|
|
+ break;
|
|
+ }
|
|
+ bcastentry->if_index = entry->if_index;
|
|
+ bcastentry->ns_ia_index = ++idx_offset;
|
|
+ bcastentry->ia_address_len = sizeof(addr_info.inp->s_addr);
|
|
+ memcpy(bcastentry->ia_address, &addr_info.inp->s_addr,
|
|
+ bcastentry->ia_address_len);
|
|
+ }
|
|
+#endif
|
|
+
|
|
+ /*
|
|
* get netmask
|
|
*/
|
|
ifrp->ifr_addr = save_addr;
|
|
@@ -232,7 +255,10 @@ _netsnmp_ioctl_ipaddress_container_load_v4(netsnmp_container *container,
|
|
netsnmp_assert(AF_INET == ifrp->ifr_addr.sa_family);
|
|
si = (struct sockaddr_in *) &ifrp->ifr_addr;
|
|
entry->ia_prefix_len =
|
|
- netsnmp_ipaddress_ipv4_prefix_len(si->sin_addr.s_addr);
|
|
+ netsnmp_ipaddress_ipv4_prefix_len(ntohl(si->sin_addr.s_addr));
|
|
+ if(addr_info.bcastflg)
|
|
+ bcastentry->ia_prefix_len = entry->ia_prefix_len;
|
|
+
|
|
|
|
/*
|
|
* get flags
|
|
@@ -246,7 +272,12 @@ _netsnmp_ioctl_ipaddress_container_load_v4(netsnmp_container *container,
|
|
}
|
|
extras->flags = ifrp->ifr_flags;
|
|
|
|
- entry->ia_type = IPADDRESSTYPE_UNICAST; /* assume unicast? */
|
|
+ if(addr_info.bcastflg)
|
|
+ bcastentry->ia_type = IPADDRESSTYPE_BROADCAST;
|
|
+ if(addr_info.anycastflg)
|
|
+ entry->ia_type = IPADDRESSTYPE_ANYCAST;
|
|
+ else
|
|
+ entry->ia_type = IPADDRESSTYPE_UNICAST;
|
|
|
|
/** entry->ia_prefix_oid ? */
|
|
|
|
@@ -256,12 +287,23 @@ _netsnmp_ioctl_ipaddress_container_load_v4(netsnmp_container *container,
|
|
* always preferred(1).
|
|
*/
|
|
entry->ia_status = IPADDRESSSTATUSTC_PREFERRED;
|
|
+ if(addr_info.bcastflg)
|
|
+ bcastentry->ia_status = IPADDRESSSTATUSTC_PREFERRED;
|
|
|
|
/*
|
|
* can we figure out if an address is from DHCP?
|
|
* use manual until then...
|
|
*/
|
|
- entry->ia_origin = IPADDRESSORIGINTC_MANUAL;
|
|
+ if(IS_APIPA(ipval)) {
|
|
+ entry->ia_origin = IPADDRESSORIGINTC_RANDOM;
|
|
+ if(addr_info.bcastflg)
|
|
+ bcastentry->ia_origin = IPADDRESSORIGINTC_RANDOM;
|
|
+ }
|
|
+ else {
|
|
+ entry->ia_origin = IPADDRESSORIGINTC_MANUAL;
|
|
+ if(addr_info.bcastflg)
|
|
+ bcastentry->ia_origin = IPADDRESSORIGINTC_MANUAL;
|
|
+ }
|
|
|
|
DEBUGIF("access:ipaddress:container") {
|
|
DEBUGMSGT_NC(("access:ipaddress:container",
|
|
@@ -279,12 +321,21 @@ _netsnmp_ioctl_ipaddress_container_load_v4(netsnmp_container *container,
|
|
/*
|
|
* add entry to container
|
|
*/
|
|
- if (CONTAINER_INSERT(container, entry) < 0)
|
|
- {
|
|
+ if(addr_info.bcastflg){
|
|
+ if (CONTAINER_INSERT(container, bcastentry) < 0) {
|
|
+ DEBUGMSGTL(("access:ipaddress:container","error with ipaddress_entry: insert broadcast entry into container failed.\n"));
|
|
+ netsnmp_access_ipaddress_entry_free(bcastentry);
|
|
+ netsnmp_access_ipaddress_entry_free(entry);
|
|
+ continue;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if (CONTAINER_INSERT(container, entry) < 0) {
|
|
DEBUGMSGTL(("access:ipaddress:container","error with ipaddress_entry: insert into container failed.\n"));
|
|
netsnmp_access_ipaddress_entry_free(entry);
|
|
continue;
|
|
}
|
|
+
|
|
}
|
|
|
|
/*
|
|
diff --git a/agent/mibgroup/ip-mib/data_access/ipaddress_ioctl.h b/agent/mibgroup/ip-mib/data_access/ipaddress_ioctl.h
|
|
index a7a0ea2..fc9774f 100644
|
|
--- a/agent/mibgroup/ip-mib/data_access/ipaddress_ioctl.h
|
|
+++ b/agent/mibgroup/ip-mib/data_access/ipaddress_ioctl.h
|
|
@@ -2,6 +2,17 @@
|
|
extern "C" {
|
|
#endif
|
|
|
|
+/*
|
|
+ * struct for netlink extras
|
|
+ */
|
|
+struct address_flag_info {
|
|
+ int bcastflg;
|
|
+ int anycastflg;
|
|
+ struct in_addr *inp;
|
|
+};
|
|
+
|
|
+#define IS_APIPA(a) (((in_addr_t)(a << 16)) == 0xFEA90000)
|
|
+
|
|
int
|
|
_netsnmp_ioctl_ipaddress_container_load_v4(netsnmp_container *container,
|
|
int idx_offset);
|
|
@@ -13,6 +24,8 @@ _netsnmp_ioctl_ipaddress_remove_v4(netsnmp_ipaddress_entry * entry);
|
|
int
|
|
netsnmp_access_ipaddress_ioctl_get_interface_count(int sd, struct ifconf * ifc);
|
|
|
|
+struct address_flag_info
|
|
+netsnmp_access_other_info_get(int index, int family);
|
|
|
|
/*
|
|
* struct ioctl for arch_data
|
|
diff --git a/agent/mibgroup/ip-mib/data_access/ipaddress_linux.c b/agent/mibgroup/ip-mib/data_access/ipaddress_linux.c
|
|
index 8cb06a2..ac37578 100644
|
|
--- a/agent/mibgroup/ip-mib/data_access/ipaddress_linux.c
|
|
+++ b/agent/mibgroup/ip-mib/data_access/ipaddress_linux.c
|
|
@@ -19,6 +19,7 @@
|
|
#if defined (NETSNMP_ENABLE_IPV6)
|
|
#include <linux/types.h>
|
|
#include <asm/types.h>
|
|
+#include <linux/netlink.h>
|
|
#include <linux/rtnetlink.h>
|
|
#endif
|
|
|
|
@@ -188,6 +189,7 @@ _load_v6(netsnmp_container *container, int idx_offset)
|
|
netsnmp_ipaddress_entry *entry;
|
|
_ioctl_extras *extras;
|
|
static int log_open_err = 1;
|
|
+ struct address_flag_info addr_info;
|
|
|
|
netsnmp_assert(NULL != container);
|
|
|
|
@@ -268,6 +270,10 @@ _load_v6(netsnmp_container *container, int idx_offset)
|
|
* every time it is called.
|
|
*/
|
|
entry->if_index = netsnmp_access_interface_index_find(if_name);
|
|
+ memset(&addr_info, 0, sizeof(struct address_flag_info));
|
|
+#if defined (NETSNMP_ENABLE_IPV6)
|
|
+ addr_info = netsnmp_access_other_info_get(entry->if_index, AF_INET6);
|
|
+#endif
|
|
|
|
/*
|
|
#define IPADDRESSSTATUSTC_PREFERRED 1
|
|
@@ -278,7 +284,7 @@ _load_v6(netsnmp_container *container, int idx_offset)
|
|
#define IPADDRESSSTATUSTC_TENTATIVE 6
|
|
#define IPADDRESSSTATUSTC_DUPLICATE 7
|
|
*/
|
|
- if(flags & IFA_F_PERMANENT)
|
|
+ if((flags & IFA_F_PERMANENT) || (!flags) || (flags & IFA_F_TEMPORARY))
|
|
entry->ia_status = IPADDRESSSTATUSTC_PREFERRED; /* ?? */
|
|
else if(flags & IFA_F_DEPRECATED)
|
|
entry->ia_status = IPADDRESSSTATUSTC_DEPRECATED;
|
|
@@ -294,7 +300,7 @@ _load_v6(netsnmp_container *container, int idx_offset)
|
|
* if it's not multi, it must be uni.
|
|
* (an ipv6 address is never broadcast)
|
|
*/
|
|
- if (IN6_IS_ADDR_MULTICAST(entry->ia_address))
|
|
+ if(addr_info.anycastflg)
|
|
entry->ia_type = IPADDRESSTYPE_ANYCAST;
|
|
else
|
|
entry->ia_type = IPADDRESSTYPE_UNICAST;
|
|
@@ -314,18 +320,28 @@ _load_v6(netsnmp_container *container, int idx_offset)
|
|
*
|
|
* are 'local' address assigned by link layer??
|
|
*/
|
|
- if (IN6_IS_ADDR_LINKLOCAL(entry->ia_address) ||
|
|
- IN6_IS_ADDR_SITELOCAL(entry->ia_address))
|
|
- entry->ia_origin = IPADDRESSORIGINTC_LINKLAYER;
|
|
- else
|
|
- entry->ia_origin = IPADDRESSORIGINTC_MANUAL;
|
|
+ if (!flags)
|
|
+ entry->ia_origin = IPADDRESSORIGINTC_LINKLAYER;
|
|
+ else if (flags & IFA_F_TEMPORARY)
|
|
+ entry->ia_origin = IPADDRESSORIGINTC_RANDOM;
|
|
+ else if (IN6_IS_ADDR_LINKLOCAL(entry->ia_address))
|
|
+ entry->ia_origin = IPADDRESSORIGINTC_LINKLAYER;
|
|
+ else
|
|
+ entry->ia_origin = IPADDRESSORIGINTC_MANUAL;
|
|
+
|
|
+ if(entry->ia_origin == IPADDRESSORIGINTC_LINKLAYER)
|
|
+ entry->ia_storagetype = STORAGETYPE_PERMANENT;
|
|
|
|
/* xxx-rks: what can we do with scope? */
|
|
|
|
/*
|
|
* add entry to container
|
|
*/
|
|
- CONTAINER_INSERT(container, entry);
|
|
+ if (CONTAINER_INSERT(container, entry) < 0) {
|
|
+ DEBUGMSGTL(("access:ipaddress:container","error with ipaddress_entry: insert into container failed.\n"));
|
|
+ netsnmp_access_ipaddress_entry_free(entry);
|
|
+ continue;
|
|
+ }
|
|
}
|
|
|
|
fclose(in);
|
|
@@ -335,4 +351,93 @@ _load_v6(netsnmp_container *container, int idx_offset)
|
|
|
|
return idx_offset;
|
|
}
|
|
+
|
|
+struct address_flag_info
|
|
+netsnmp_access_other_info_get(int index, int family)
|
|
+{
|
|
+ struct {
|
|
+ struct nlmsghdr n;
|
|
+ struct ifaddrmsg r;
|
|
+ char buf[1024];
|
|
+ } req;
|
|
+ struct address_flag_info addr;
|
|
+ struct rtattr *rta;
|
|
+ int status;
|
|
+ char buf[16384];
|
|
+ struct nlmsghdr *nlmp;
|
|
+ struct ifaddrmsg *rtmp;
|
|
+ struct rtattr *rtatp;
|
|
+ int rtattrlen;
|
|
+ int sd;
|
|
+
|
|
+ memset(&addr, 0, sizeof(struct address_flag_info));
|
|
+ sd = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE);
|
|
+ if(sd < 0) {
|
|
+ snmp_log(LOG_ERR, "could not open netlink socket\n");
|
|
+ return addr;
|
|
+ }
|
|
+
|
|
+ memset(&req, 0, sizeof(req));
|
|
+ req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg));
|
|
+ req.n.nlmsg_flags = NLM_F_REQUEST | NLM_F_ROOT;
|
|
+ req.n.nlmsg_type = RTM_GETADDR;
|
|
+ req.r.ifa_family = family;
|
|
+ rta = (struct rtattr *)(((char *)&req) + NLMSG_ALIGN(req.n.nlmsg_len));
|
|
+ if(family == AF_INET)
|
|
+ rta->rta_len = RTA_LENGTH(4);
|
|
+ else
|
|
+ rta->rta_len = RTA_LENGTH(16);
|
|
+
|
|
+ status = send(sd, &req, req.n.nlmsg_len, 0);
|
|
+ if (status < 0) {
|
|
+ snmp_log(LOG_ERR, "could not send netlink request\n");
|
|
+ return addr;
|
|
+ }
|
|
+
|
|
+ status = recv(sd, buf, sizeof(buf), 0);
|
|
+ if (status < 0) {
|
|
+ snmp_log (LOG_ERR, "could not recieve netlink request\n");
|
|
+ return addr;
|
|
+ }
|
|
+
|
|
+ if(status == 0) {
|
|
+ snmp_log (LOG_ERR, "nothing to read\n");
|
|
+ return addr;
|
|
+ }
|
|
+
|
|
+ for(nlmp = (struct nlmsghdr *)buf; status > sizeof(*nlmp);) {
|
|
+ int len = nlmp->nlmsg_len;
|
|
+ int req_len = len - sizeof(*nlmp);
|
|
+
|
|
+ if (req_len < 0 || len > status) {
|
|
+ snmp_log (LOG_ERR, "invalid netlink message\n");
|
|
+ return addr;
|
|
+ }
|
|
+
|
|
+ if (!NLMSG_OK(nlmp, status)) {
|
|
+ snmp_log (LOG_ERR, "invalid NLMSG message\n");
|
|
+ return addr;
|
|
+ }
|
|
+ rtmp = (struct ifaddrmsg *)NLMSG_DATA(nlmp);
|
|
+ rtatp = (struct rtattr *)IFA_RTA(rtmp);
|
|
+ rtattrlen = IFA_PAYLOAD(nlmp);
|
|
+ if(index == rtmp->ifa_index){
|
|
+ for (; RTA_OK(rtatp, rtattrlen); rtatp = RTA_NEXT(rtatp, rtattrlen)) {
|
|
+ if(rtatp->rta_type == IFA_BROADCAST){
|
|
+ addr.inp = (struct in_addr *)RTA_DATA(rtatp);
|
|
+ addr.bcastflg = 1;
|
|
+ }
|
|
+ if(rtatp->rta_type == IFA_ANYCAST){
|
|
+ addr.inp = (struct in_addr *)RTA_DATA(rtatp);
|
|
+ addr.anycastflg = 1;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ status -= NLMSG_ALIGN(len);
|
|
+ nlmp = (struct nlmsghdr*)((char*)nlmp + NLMSG_ALIGN(len));
|
|
+ }
|
|
+ close(sd);
|
|
+ return addr;
|
|
+}
|
|
#endif
|
|
+
|
|
diff --git a/agent/mibgroup/ip-mib/ipAddressTable/ipAddressTable.c b/agent/mibgroup/ip-mib/ipAddressTable/ipAddressTable.c
|
|
index e695ab3..8bb3cbc 100644
|
|
--- a/agent/mibgroup/ip-mib/ipAddressTable/ipAddressTable.c
|
|
+++ b/agent/mibgroup/ip-mib/ipAddressTable/ipAddressTable.c
|
|
@@ -942,7 +942,10 @@ ipAddressRowStatus_get(ipAddressTable_rowreq_ctx * rowreq_ctx,
|
|
netsnmp_assert(NULL != ipAddressRowStatus_val_ptr);
|
|
|
|
/** WARNING: this code might not work for netsnmp_ipaddress_entry */
|
|
- (*ipAddressRowStatus_val_ptr) = rowreq_ctx->ipAddressRowStatus;
|
|
+ if(rowreq_ctx->data->if_index)
|
|
+ (*ipAddressRowStatus_val_ptr) = rowreq_ctx->ipAddressRowStatus;
|
|
+ else
|
|
+ (*ipAddressRowStatus_val_ptr) = ROWSTATUS_NOTREADY;
|
|
|
|
return MFD_SUCCESS;
|
|
} /* ipAddressRowStatus_get */
|
|
diff --git a/include/net-snmp/library/container.h b/include/net-snmp/library/container.h
|
|
index f88fa21..22684aa 100644
|
|
--- a/include/net-snmp/library/container.h
|
|
+++ b/include/net-snmp/library/container.h
|
|
@@ -358,7 +358,7 @@ extern "C" {
|
|
if(x) {
|
|
int rc = x->insert(x,k);
|
|
if(rc)
|
|
- snmp_log(LOG_ERR,"error on subcontainer '%s' insert (%d)\n",
|
|
+ snmp_log(LOG_DEBUG,"error on subcontainer '%s' insert (%d)\n",
|
|
x->container_name ? x->container_name : "", rc);
|
|
else {
|
|
rc = CONTAINER_INSERT_HELPER(x->next, k);
|
|
diff --git a/snmplib/container.c b/snmplib/container.c
|
|
index e34e922..1255f0a 100644
|
|
--- a/snmplib/container.c
|
|
+++ b/snmplib/container.c
|
|
@@ -275,7 +275,7 @@ int CONTAINER_INSERT_HELPER(netsnmp_container* x, const void* k)
|
|
if(x) {
|
|
int rc = x->insert(x,k);
|
|
if(rc)
|
|
- snmp_log(LOG_ERR,"error on subcontainer '%s' insert (%d)\n",
|
|
+ snmp_log(LOG_DEBUG,"error on subcontainer '%s' insert (%d)\n",
|
|
x->container_name ? x->container_name : "", rc);
|
|
else {
|
|
rc = CONTAINER_INSERT_HELPER(x->next, k);
|
|
--
|
|
1.6.0.2
|
|
|