Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > 20db51d70e6b59a061db97ce9b89c771 > files > 23

net-snmp-5.3.2.2-14.el5.src.rpm

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;
+}
+