Fix ipAddressTable: ipAddressAddr, ipAddressType, ipAddressOrigin, ipAddressRowStatus, ipAddressStorageType Source: http://sourceforge.net/tracker/index.php?func=detail&aid=1692817&group_id=12694&atid=312694 http://sourceforge.net/tracker/index.php?func=detail&aid=1810660&group_id=12694&atid=312694 Index: agent/mibgroup/ip-mib/ipAddressTable/ipAddressTable.c =================================================================== --- agent/mibgroup/ip-mib/ipAddressTable/ipAddressTable.c (revision 16015) +++ agent/mibgroup/ip-mib/ipAddressTable/ipAddressTable.c (working copy) @@ -942,7 +942,10 @@ 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 */ Index: agent/mibgroup/ip-mib/data_access/ipaddress_ioctl.c Index: agent/mibgroup/ip-mib/data_access/ipaddress_ioctl.c =================================================================== --- agent/mibgroup/ip-mib/data_access/ipaddress_ioctl.c (revision 16015) +++ agent/mibgroup/ip-mib/data_access/ipaddress_ioctl.c (working copy) @@ -135,7 +135,9 @@ 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_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); @@ -213,6 +216,25 @@ } /* + * get broadcast + */ + memset(&addr_info, 0, sizeof(struct address_flag_info)); + 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); + } + + + /* * get netmask */ ifrp->ifr_addr = save_addr; @@ -225,8 +247,11 @@ 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 */ @@ -239,7 +264,12 @@ } 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 ? */ @@ -249,12 +279,23 @@ * 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", @@ -313,9 +313,17 @@ /* * add entry to container */ + static int logged = 0; + if(addr_info.bcastflg){ + rc = CONTAINER_TRY_INSERT(container, bcastentry); + if (rc < 0) { + netsnmp_access_ipaddress_entry_free(bcastentry); + rc = 0; + } + } + rc = CONTAINER_TRY_INSERT(container, entry); if (rc < 0) { - static int logged = 0; if (!logged) { snmp_log(LOG_NOTICE, "Duplicate IP address detected, some interfaces may not be visible in IP-MIB\n"); logged = 1; Index: agent/mibgroup/ip-mib/data_access/ipaddress_ioctl.h =================================================================== --- agent/mibgroup/ip-mib/data_access/ipaddress_ioctl.h (revision 16015) +++ agent/mibgroup/ip-mib/data_access/ipaddress_ioctl.h (working copy) @@ -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 @@ 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 Index: agent/mibgroup/ip-mib/data_access/ipaddress_linux.c =================================================================== --- agent/mibgroup/ip-mib/data_access/ipaddress_linux.c (revision 16015) +++ agent/mibgroup/ip-mib/data_access/ipaddress_linux.c (working copy) @@ -187,6 +187,7 @@ netsnmp_ipaddress_entry *entry; _ioctl_extras *extras; static int log_open_err = 1; + struct address_flag_info addr_info; netsnmp_assert(NULL != container); @@ -267,6 +268,8 @@ * every time it is called. */ entry->if_index = netsnmp_access_interface_index_find(if_name); + memset(&addr_info, 0, sizeof(struct address_flag_info)); + addr_info = netsnmp_access_other_info_get(entry->if_index, AF_INET6); /* #define IPADDRESSSTATUSTC_PREFERRED 1 @@ -277,7 +280,7 @@ #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; @@ -293,7 +296,7 @@ * 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; @@ -313,12 +316,18 @@ * * 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? */ /* @@ -335,3 +344,92 @@ return idx_offset; } #endif + +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; +} +