Server uses ipAddressTable and ipAddressPrefixTable to collect configured IP addresse...
authorVictor Kirhenshtein <victor@netxms.org>
Sat, 3 Jan 2015 22:05:58 +0000 (00:05 +0200)
committerVictor Kirhenshtein <victor@netxms.org>
Sat, 3 Jan 2015 22:05:58 +0000 (00:05 +0200)
ChangeLog
include/nxsnmp.h
src/server/core/interface.cpp
src/server/core/main.cpp
src/server/include/nxsrvapi.h
src/server/libnxsrv/iflist.cpp
src/server/libnxsrv/ndd.cpp

index 9cb673d..b3bacb4 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -15,6 +15,7 @@
 - Oracle Tuxedo monitoring subagent
 - Improved server performance with PostgreSQL
 - Alias and MTU collected and stored for interfaces
+- Server uses ipAddressTable and ipAddressPrefixTable to collect configured IP addresses when supported by monitored nodes
 - Management console:
     - New dashboard element "DCI summary table"
     - Cluster objects shown on status maps
@@ -23,7 +24,7 @@
     - Added 10 minutes, 12 hours, 5 days, 30 days, last year options in draw graph for last values tab (5, 7, and 30 days asks for confirmation of long task execution)
     - Fixed graphical problem (checkbox) in last values tab
     - Support for KitKat Wear and Lollipop, updated support library v4
-- Fixed issues: #61, #306, #381, #488, #565, #628, #634, #667, #672, #673, #674, #675, #677, #678, #679, #682, #684, #686, #688, #689, #691, #700, #704, #705, #709, #710
+- Fixed issues: #61, #306, #381, #488, #565, #628, #634, #667, #672, #673, #674, #675, #677, #678, #679, #682, #684, #686, #688, #689, #691, #698, #700, #704, #705, #709, #710
 
 
 *
index c98bc72..f37f1af 100644 (file)
@@ -378,6 +378,8 @@ public:
    int compare(const TCHAR *oid);
    int compare(const UINT32 *oid, size_t length);
        int compare(SNMP_ObjectId *oid);
+
+   bool isZeroDotZero() { return (m_length == 2) && (m_value[0] == 0) && (m_value[1] == 0); }
 };
 
 /**
index cb76497..dc3fd08 100644 (file)
@@ -138,7 +138,7 @@ Interface::~Interface()
  */
 UINT32 Interface::getPingTime()
 {
-   if((time(NULL) - m_pingLastTimeStamp) > g_dwStatusPollingInterval)
+   if ((time(NULL) - m_pingLastTimeStamp) > g_dwStatusPollingInterval)
    {
       updatePingData();
    }
index 6421bd9..dc92646 100644 (file)
@@ -1186,6 +1186,71 @@ int ProcessConsoleCommand(const TCHAR *pszCmdLine, CONSOLE_CTX pCtx)
                        ConsolePrintf(pCtx, _T("Session ID missing\n"));
                }
    }
+       else if (IsCommand(_T("POLL"), szBuffer, 2))
+       {
+               pArg = ExtractWord(pArg, szBuffer);
+               if (szBuffer[0] != 0)
+               {
+         int pollType;
+         if (IsCommand(_T("CONFIGURATION"), szBuffer, 1))
+         {
+            pollType = 1;
+         }
+         else if (IsCommand(_T("STATUS"), szBuffer, 1))
+         {
+            pollType = 2;
+         }
+         else if (IsCommand(_T("TOPOLOGY"), szBuffer, 1))
+         {
+            pollType = 3;
+         }
+         else
+         {
+            pollType = 0;
+         }
+
+         if (pollType > 0)
+         {
+               pArg = ExtractWord(pArg, szBuffer);
+                          UINT32 id = _tcstoul(szBuffer, NULL, 0);
+                          if (id != 0)
+                          {
+                                  Node *node = (Node *)FindObjectById(id, OBJECT_NODE);
+                                  if (node != NULL)
+                                  {
+                  switch(pollType)
+                  {
+                     case 1:
+                        node->configurationPoll(NULL, 0, -1, 0);
+                        break;
+                     case 2:
+                        node->statusPoll(NULL, 0, -1);
+                        break;
+                     case 3:
+                        node->topologyPoll(NULL, 0, -1);
+                        break;
+                  }
+                                  }
+                                  else
+                                  {
+                                          ConsolePrintf(pCtx, _T("ERROR: Node with ID %d does not exist\n\n"), id);
+                                  }
+                          }
+                          else
+                          {
+                                  ConsolePrintf(pCtx, _T("ERROR: Invalid or missing node ID\n\n"));
+                          }
+         }
+         else
+         {
+                       ConsolePrintf(pCtx, _T("Usage POLL [CONFIGURATION|STATUS|TOPOLOGY] <node>\n"));
+         }
+               }
+               else
+               {
+                       ConsolePrintf(pCtx, _T("Usage POLL [CONFIGURATION|STATUS|TOPOLOGY] <node>\n"));
+               }
+       }
        else if (IsCommand(_T("SET"), szBuffer, 3))
        {
                pArg = ExtractWord(pArg, szBuffer);
@@ -1767,6 +1832,7 @@ int ProcessConsoleCommand(const TCHAR *pszCmdLine, CONSOLE_CTX pCtx)
                                _T("   get <variable>            - Get value of server configuration variable\n")
                                _T("   help                      - Display this help\n")
                                _T("   ldapsync                  - Synchronize ldap users with local user database\n")
+            _T("   poll <type> <node>        - Initiate node poll\n")
                                _T("   raise <exception>         - Raise exception\n")
                                _T("   set <variable> <value>    - Set value of server configuration variable\n")
                                _T("   show components <node>    - Show physical components of given node\n")
index a184f89..b52864e 100644 (file)
@@ -238,6 +238,7 @@ private:
        int m_allocated;               // Number of allocated entries
    void *m_data;                  // Can be used by custom enumeration handlers
    NX_INTERFACE_INFO *m_interfaces;  // Interface entries
+   bool m_needPrefixWalk;
 
 public:
        InterfaceList(int initialAlloc = 8);
@@ -252,6 +253,9 @@ public:
 
        void setData(void *data) { m_data = data; }
        void *getData() { return m_data; }
+
+   bool isPrefixWalkNeeded() { return m_needPrefixWalk; }
+   void setPrefixWalkNeeded() { m_needPrefixWalk = true; }
 };
 
 /**
index 4976d03..79f292a 100644 (file)
@@ -31,6 +31,7 @@ InterfaceList::InterfaceList(int initialAlloc)
        m_size = 0;
        m_data = NULL;
        m_interfaces = (NX_INTERFACE_INFO *)malloc(sizeof(NX_INTERFACE_INFO) * m_allocated);
+   m_needPrefixWalk = false;
 }
 
 /**
index 52c1526..a17f75e 100644 (file)
@@ -182,7 +182,7 @@ static UINT32 HandlerIndexIfXTable(UINT32 dwVersion, SNMP_Variable *pVar, SNMP_T
 }
 
 /**
- * Handler for enumerating IP addresses
+ * Handler for enumerating IP addresses via ipAddrTable
  */
 static UINT32 HandlerIpAddr(UINT32 dwVersion, SNMP_Variable *pVar, SNMP_Transport *pTransport, void *pArg)
 {
@@ -209,28 +209,24 @@ static UINT32 HandlerIpAddr(UINT32 dwVersion, SNMP_Variable *pVar, SNMP_Transpor
    if (dwResult == SNMP_ERR_SUCCESS)
    {
                InterfaceList *ifList = (InterfaceList *)pArg;
-
-               for(int i = 0; i < ifList->size(); i++)
-               {
-         if (ifList->get(i)->index == index)
+      NX_INTERFACE_INFO *iface = ifList->findByIfIndex(index);
+      if (iface != NULL)
+      {
+         if (iface->ipAddr != 0)
          {
-            if (ifList->get(i)->ipAddr != 0)
-            {
-               // This interface entry already filled, so we have additional IP addresses
-               // on a single interface
-                                       NX_INTERFACE_INFO iface;
-                                       memcpy(&iface, ifList->get(i), sizeof(NX_INTERFACE_INFO));
-                                       iface.ipAddr = ntohl(pVar->getValueAsUInt());
-                                       iface.ipNetMask = dwNetMask;
-                                       ifList->add(&iface);
-            }
-                               else
-                               {
-                                       ifList->get(i)->ipAddr = ntohl(pVar->getValueAsUInt());
-                                       ifList->get(i)->ipNetMask = dwNetMask;
-                               }
-            break;
+            // This interface entry already filled, so we have additional IP addresses
+            // on a single interface
+                               NX_INTERFACE_INFO extIface;
+                               memcpy(&extIface, iface, sizeof(NX_INTERFACE_INFO));
+                               extIface.ipAddr = ntohl(pVar->getValueAsUInt());
+                               extIface.ipNetMask = dwNetMask;
+                               ifList->add(&extIface);
          }
+                       else
+                       {
+                               iface->ipAddr = ntohl(pVar->getValueAsUInt());
+                               iface->ipNetMask = dwNetMask;
+                       }
                }
    }
        else
@@ -244,6 +240,113 @@ static UINT32 HandlerIpAddr(UINT32 dwVersion, SNMP_Variable *pVar, SNMP_Transpor
 }
 
 /**
+ * Handler for enumerating IP addresses via ipAddressTable
+ */
+static UINT32 HandlerIpAddressTable(UINT32 version, SNMP_Variable *var, SNMP_Transport *snmp, void *arg)
+{
+   InterfaceList *ifList = (InterfaceList *)arg;
+
+   UINT32 oid[128];
+   size_t oidLen = var->getName()->getLength();
+   memcpy(oid, var->getName()->getValue(), oidLen * sizeof(UINT32));
+
+   // Check address family (1 = ipv4)
+   if (oid[10] != 1)
+      return SNMP_ERR_SUCCESS;
+
+   UINT32 ifIndex = var->getValueAsUInt();
+   NX_INTERFACE_INFO *iface = ifList->findByIfIndex(ifIndex);
+   if (iface == NULL)
+      return SNMP_ERR_SUCCESS;
+
+   // Build IP address from OID
+   UINT32 ipAddr = (oid[12] << 24) | (oid[13] << 16) | (oid[14] << 8) | oid[15];
+   if (iface->ipAddr == ipAddr)
+      return SNMP_ERR_SUCCESS;   // This IP already set from ipAddrTable
+
+   UINT32 netMask = 0;
+
+   // Get address type and prefix
+   SNMP_PDU request(SNMP_GET_REQUEST, SnmpNewRequestId(), snmp->getSnmpVersion());
+   oid[9] = 4; // ipAddressType
+   request.bindVariable(new SNMP_Variable(oid, oidLen));
+   oid[9] = 5; // ipAddressPrefix
+   request.bindVariable(new SNMP_Variable(oid, oidLen));
+   SNMP_PDU *response;
+   if (snmp->doRequest(&request, &response, g_snmpTimeout, 3) == SNMP_ERR_SUCCESS)
+   {
+      // check number of varbinds and address type (1 = unicast)
+      if ((response->getNumVariables() == 2) && (response->getVariable(0)->getValueAsInt() == 1))
+      {
+         SNMP_ObjectId *prefix = response->getVariable(1)->getValueAsObjectId();
+         if ((prefix != NULL) && !prefix->isZeroDotZero())
+         {
+            // Last element in ipAddressPrefixTable index is prefix length
+            UINT32 len = prefix->getValue()[prefix->getLength() - 1];
+            netMask = ((len > 0) && (len <= 32)) ? (0xFFFFFFFF << (32 - len)) : 0;
+         }
+         else
+         {
+            ifList->setPrefixWalkNeeded();
+         }
+         delete prefix;
+
+         if (iface->ipAddr != 0)
+         {
+            // This interface entry already filled, so we have additional IP addresses
+            // on a single interface
+                               NX_INTERFACE_INFO extIface;
+                               memcpy(&extIface, iface, sizeof(NX_INTERFACE_INFO));
+                               extIface.ipAddr = ipAddr;
+                               extIface.ipNetMask = netMask;
+                               ifList->add(&extIface);
+         }
+                       else
+                       {
+                               iface->ipAddr = ipAddr;
+                               iface->ipNetMask = netMask;
+                       }
+      }
+      delete response;
+   }
+
+   return SNMP_ERR_SUCCESS;
+}
+
+/**
+ * Handler for enumerating IP address prefixes via ipAddressPrefixTable
+ */
+static UINT32 HandlerIpAddressPrefixTable(UINT32 version, SNMP_Variable *var, SNMP_Transport *snmp, void *arg)
+{
+   InterfaceList *ifList = (InterfaceList *)arg;
+   const UINT32 *oid = var->getName()->getValue();
+   
+   // Check address family (1 = ipv4)
+   if (oid[10] != 1)
+      return SNMP_ERR_SUCCESS;
+
+   // Build IP address from OID
+   UINT32 prefix = (oid[13] << 24) | (oid[14] << 16) | (oid[15] << 8) | oid[16];
+   UINT32 mask = ((oid[17] > 0) && (oid[17] <= 32)) ? (0xFFFFFFFF << (32 - oid[17])) : 0;
+
+   // Find matching IP and set mask
+   for(int i = 0; i < ifList->size(); i++)
+   {
+      NX_INTERFACE_INFO *iface = ifList->get(i);
+      if (iface->index != oid[12])
+         continue;
+
+      if ((iface->ipAddr & mask) == prefix)
+      {
+         iface->ipNetMask = mask;
+         break;
+      }
+   }
+
+   return SNMP_ERR_SUCCESS;
+}
+
+/**
  * Get list of interfaces for given node
  *
  * @param snmp SNMP transport
@@ -404,6 +507,13 @@ InterfaceList *NetworkDeviceDriver::getInterfaces(SNMP_Transport *snmp, StringMa
                {
                        DbgPrintf(6, _T("NetworkDeviceDriver::getInterfaces(%p): SNMP WALK .1.3.6.1.2.1.4.20.1.1 failed (%s)"), snmp, SNMPGetErrorText(error));
                }
+
+      // Get IP addresses from ipAddressTable if available
+               SnmpWalk(snmp->getSnmpVersion(), snmp, _T(".1.3.6.1.2.1.4.34.1.3"), HandlerIpAddressTable, pIfList, FALSE);
+      if (pIfList->isPrefixWalkNeeded())
+      {
+               SnmpWalk(snmp->getSnmpVersion(), snmp, _T(".1.3.6.1.2.1.4.32.1.5"), HandlerIpAddressPrefixTable, pIfList, FALSE);
+      }
    }
        else
        {