Search
j0ke.net Open Build Service
>
Projects
>
GFS
>
net-snmp
> Fix-for-Internet-Address-Table.patch
Sign Up
|
Log In
Username
Password
Cancel
Overview
Repositories
Revisions
Requests
Users
Advanced
Attributes
Meta
File Fix-for-Internet-Address-Table.patch of Package net-snmp
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