finished server side conversion to multiple IP addresses per interface; partial IPv6...
authorVictor Kirhenshtein <victor@netxms.org>
Wed, 4 Mar 2015 11:55:14 +0000 (13:55 +0200)
committerVictor Kirhenshtein <victor@netxms.org>
Wed, 4 Mar 2015 11:55:14 +0000 (13:55 +0200)
58 files changed:
include/netxmsdb.h
include/nms_util.h
include/nxevent.h
netxms.sln
sql/events.in
sql/schema.in
src/java/client/netxms-client/src/main/java/org/netxms/client/NXCObjectCreationData.java
src/java/client/netxms-client/src/main/java/org/netxms/client/NXCSession.java
src/java/client/netxms-client/src/test/java/org/netxms/client/ObjectTest.java
src/java/netxms-eclipse/ObjectManager/src/org/netxms/ui/eclipse/objectmanager/actions/CreateInterface.java
src/java/netxms-eclipse/ObjectManager/src/org/netxms/ui/eclipse/objectmanager/dialogs/CreateInterfaceDialog.java
src/libnetxms/inetaddr.cpp
src/server/core/accesspoint.cpp
src/server/core/actions.cpp
src/server/core/cluster.cpp
src/server/core/dcobject.cpp
src/server/core/dctarget.cpp
src/server/core/events.cpp
src/server/core/inaddr_index.cpp
src/server/core/interface.cpp
src/server/core/locks.cpp
src/server/core/main.cpp
src/server/core/netinfo.cpp
src/server/core/netobj.cpp
src/server/core/node.cpp
src/server/core/np.cpp
src/server/core/nxsl_classes.cpp
src/server/core/objects.cpp
src/server/core/poll.cpp
src/server/core/session.cpp
src/server/core/subnet.cpp
src/server/core/tools.cpp
src/server/core/vpnconn.cpp
src/server/core/zone.cpp
src/server/drivers/at/at.cpp
src/server/drivers/baystack/baystack.cpp
src/server/drivers/cat2900xl/cat2900xl.cpp
src/server/drivers/catalyst/catalyst.cpp
src/server/drivers/cisco-esw/cisco-esw.cpp
src/server/drivers/cisco-sb/cisco-sb.cpp
src/server/drivers/dell-pwc/dell-pwc.cpp
src/server/drivers/dlink/dlink.cpp
src/server/drivers/h3c/h3c.cpp
src/server/drivers/hpsw/hpsw.cpp
src/server/drivers/lib/avaya-ers/vlan-if.cpp
src/server/drivers/mikrotik/mikrotik.cpp
src/server/drivers/netscreen/netscreen.cpp
src/server/drivers/ping3/ping3.cpp
src/server/drivers/procurve/procurve.cpp
src/server/include/nms_core.h
src/server/include/nms_locks.h
src/server/include/nms_objects.h
src/server/include/nxsrvapi.h
src/server/libnxsrv/agent.cpp
src/server/libnxsrv/iflist.cpp
src/server/libnxsrv/ndd.cpp
src/server/tools/nxdbmgr/check.cpp
src/server/tools/nxdbmgr/upgrade.cpp

index 5b7914a..34dada5 100644 (file)
@@ -23,6 +23,6 @@
 #ifndef _netxmsdb_h
 #define _netxmsdb_h
 
-#define DB_FORMAT_VERSION   346
+#define DB_FORMAT_VERSION   348
 
 #endif
index 8a3f35b..6fe1473 100644 (file)
@@ -952,7 +952,10 @@ public:
    ~InetAddressList();
 
    void add(const InetAddress& addr);
+   void add(const InetAddressList& addrList);
+   void replace(const InetAddress& addr);
    void remove(const InetAddress& addr);
+   void clear() { m_list->clear(); }
    const InetAddress& get(int index) const { const InetAddress *a = m_list->get(index); return (a != NULL) ? *a : InetAddress::INVALID; }
 
    int size() const { return m_list->size(); }
@@ -962,6 +965,7 @@ public:
    const InetAddress& getFirstUnicastAddress() const;
    const InetAddress& getFirstUnicastAddressV4() const;
    bool hasValidUnicastAddress() const { return getFirstUnicastAddress().isValid(); }
+   bool isLoopbackOnly() const;
 
    const ObjectArray<InetAddress> *getList() const { return m_list; }
 };
index bd1faec..9ab59f8 100644 (file)
 #define EVENT_AP_UNADOPTED                73
 #define EVENT_AP_DOWN                     74
 #define EVENT_IF_MASK_CHANGED             75
+#define EVENT_IF_IPADDR_ADDED             76
+#define EVENT_IF_IPADDR_DELETED           77
 
 #define EVENT_SNMP_UNMATCHED_TRAP         500
 #define EVENT_SNMP_COLD_START             501
index 50955c5..933a128 100644 (file)
@@ -348,6 +348,7 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "avaya-ers", "src\server\dri
        ProjectSection(ProjectDependencies) = postProject
                {7DC90EE4-E31C-4F12-8F1E-81F10E9099FB} = {7DC90EE4-E31C-4F12-8F1E-81F10E9099FB}
                {CB89D905-C8BE-4027-B2D8-F96C245E9160} = {CB89D905-C8BE-4027-B2D8-F96C245E9160}
+               {B1745870-F3ED-4ACB-B813-0C4F47EF0793} = {B1745870-F3ED-4ACB-B813-0C4F47EF0793}
        EndProjectSection
 EndProject
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cisco", "src\server\drivers\lib\cisco\cisco.vcproj", "{375F95BD-EFBA-4AA3-8DA3-E79779A12896}"
@@ -371,6 +372,7 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "portech", "src\server\smsdr
 EndProject
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "netscreen", "src\server\drivers\netscreen\netscreen.vcproj", "{500DE9BF-6FC1-4ACB-91A9-308BA1D37F37}"
        ProjectSection(ProjectDependencies) = postProject
+               {B1745870-F3ED-4ACB-B813-0C4F47EF0793} = {B1745870-F3ED-4ACB-B813-0C4F47EF0793}
                {CB89D905-C8BE-4027-B2D8-F96C245E9160} = {CB89D905-C8BE-4027-B2D8-F96C245E9160}
                {7DC90EE4-E31C-4F12-8F1E-81F10E9099FB} = {7DC90EE4-E31C-4F12-8F1E-81F10E9099FB}
        EndProjectSection
index 87efa37..7e3081c 100644 (file)
@@ -882,6 +882,34 @@ INSERT INTO event_cfg (event_code,event_name,severity,flags,message,description)
          '   6) Interface old mask'
       );
 
+   INSERT INTO event_cfg (event_code,event_name,severity,flags,message,description) VALUES
+      (
+         EVENT_IF_IPADDR_ADDED, 'SYS_IF_IPADDR_ADDED',
+         EVENT_SEVERITY_NORMAL, 1,
+         'IP address %3/%4 added to interface "%2"',
+         'Generated when IP address added to interface.' CONCAT CRLF CONCAT
+         'Parameters:' CONCAT CRLF CONCAT
+         '   1) Interface object ID' CONCAT CRLF CONCAT
+         '   2) Interface name' CONCAT CRLF CONCAT
+         '   3) IP address' CONCAT CRLF CONCAT
+         '   4) Network mask' CONCAT CRLF CONCAT
+         '   5) Interface index'
+      );
+      
+   INSERT INTO event_cfg (event_code,event_name,severity,flags,message,description) VALUES
+      (
+         EVENT_IF_IPADDR_DELETED, 'SYS_IF_IPADDR_DELETED',
+         EVENT_SEVERITY_NORMAL, 1,
+         'IP address %3/%4 deleted from interface "%2"',
+         'Generated when IP address deleted from interface.' CONCAT CRLF CONCAT
+         'Parameters:' CONCAT CRLF CONCAT
+         '   1) Interface object ID' CONCAT CRLF CONCAT
+         '   2) Interface name' CONCAT CRLF CONCAT
+         '   3) IP address' CONCAT CRLF CONCAT
+         '   4) Network mask' CONCAT CRLF CONCAT
+         '   5) Interface index'
+      );
+
 /*
 ** SNMP traps
 */
index 2340d02..ae389a0 100644 (file)
@@ -349,8 +349,6 @@ CREATE TABLE interfaces
        id integer not null,
        node_id integer not null,
        flags integer not null,
-       ip_addr varchar(48) not null,
-       ip_netmask integer not null,
        if_type integer not null,
        if_index integer not null,
    mtu integer not null,
@@ -371,6 +369,16 @@ CREATE TABLE interfaces
        PRIMARY KEY(id)
 ) TABLE_TYPE;
 
+/*
+** Interface IP addresses
+*/
+CREATE TABLE interface_address_list
+(
+   iface_id integer not null,
+       ip_addr varchar(48) not null,
+       ip_netmask integer not null,
+   PRIMARY KEY(iface_id,ip_addr)
+) TABLE_TYPE;
 
 /*
 ** Network services
index 1a17881..3e9a9f3 100644 (file)
@@ -20,6 +20,7 @@ package org.netxms.client;
 
 import java.net.InetAddress;
 import java.net.UnknownHostException;
+import org.netxms.base.InetAddressEx;
 import org.netxms.client.objects.AbstractObject;
 import org.netxms.client.objects.NetworkService;
 
@@ -42,8 +43,7 @@ public class NXCObjectCreationData
        private String primaryName;
        private int agentPort;
        private int snmpPort;
-       private InetAddress ipAddress;
-       private InetAddress ipNetMask;
+       private InetAddressEx ipAddress;
        private long agentProxyId;
        private long snmpProxyId;
        private int mapType;
@@ -83,8 +83,7 @@ public class NXCObjectCreationData
                
                try
                {
-                       ipAddress = InetAddress.getByName("127.0.0.1");
-                       ipNetMask = InetAddress.getByName("0.0.0.0");
+                       ipAddress = new InetAddressEx(InetAddress.getByName("127.0.0.1"), 8);
                }
                catch(UnknownHostException e)
                {
@@ -199,7 +198,7 @@ public class NXCObjectCreationData
        /**
         * @return the ipAddress
         */
-       public InetAddress getIpAddress()
+       public InetAddressEx getIpAddress()
        {
                return ipAddress;
        }
@@ -207,28 +206,12 @@ public class NXCObjectCreationData
        /**
         * @param ipAddress the ipAddress to set
         */
-       public void setIpAddress(InetAddress ipAddress)
+       public void setIpAddress(InetAddressEx ipAddress)
        {
                this.ipAddress = ipAddress;
        }
 
        /**
-        * @return the ipNetMask
-        */
-       public InetAddress getIpNetMask()
-       {
-               return ipNetMask;
-       }
-
-       /**
-        * @param ipNetMask the ipNetMask to set
-        */
-       public void setIpNetMask(InetAddress ipNetMask)
-       {
-               this.ipNetMask = ipNetMask;
-       }
-
-       /**
         * @return the agentProxyId
         */
        public long getAgentProxyId()
index dde0d58..5aefdf7 100644 (file)
@@ -3712,7 +3712,6 @@ public class NXCSession implements Session, ScriptLibraryManager, UserManager, S
          case AbstractObject.OBJECT_NODE:
             if (data.getPrimaryName() != null) msg.setField(NXCPCodes.VID_PRIMARY_NAME, data.getPrimaryName());
             msg.setField(NXCPCodes.VID_IP_ADDRESS, data.getIpAddress());
-            msg.setField(NXCPCodes.VID_IP_NETMASK, data.getIpNetMask());
             msg.setFieldInt16(NXCPCodes.VID_AGENT_PORT, data.getAgentPort());
             msg.setFieldInt16(NXCPCodes.VID_SNMP_PORT, data.getSnmpPort());
             msg.setFieldInt32(NXCPCodes.VID_CREATION_FLAGS, data.getCreationFlags());
@@ -3741,7 +3740,6 @@ public class NXCSession implements Session, ScriptLibraryManager, UserManager, S
          case AbstractObject.OBJECT_INTERFACE:
             msg.setField(NXCPCodes.VID_MAC_ADDR, data.getMacAddress().getValue());
             msg.setField(NXCPCodes.VID_IP_ADDRESS, data.getIpAddress());
-            msg.setField(NXCPCodes.VID_IP_NETMASK, data.getIpNetMask());
             msg.setFieldInt32(NXCPCodes.VID_IF_TYPE, data.getIfType());
             msg.setFieldInt32(NXCPCodes.VID_IF_INDEX, data.getIfIndex());
             msg.setFieldInt32(NXCPCodes.VID_IF_SLOT, data.getSlot());
index 4308dac..ba85fcf 100644 (file)
@@ -20,6 +20,7 @@ package org.netxms.client;
 
 import java.net.InetAddress;
 import java.util.Set;
+import org.netxms.base.InetAddressEx;
 import org.netxms.client.objects.EntireNetwork;
 import org.netxms.client.objects.AbstractObject;
 import org.netxms.client.objects.Node;
@@ -111,7 +112,7 @@ public class ObjectTest extends SessionTest
                
                NXCObjectCreationData cd = new NXCObjectCreationData(AbstractObject.OBJECT_NODE, "TestNode", 2);
                cd.setCreationFlags(NXCObjectCreationData.CF_CREATE_UNMANAGED);
-               cd.setIpAddress(InetAddress.getByName("192.168.10.1"));
+               cd.setIpAddress(new InetAddressEx(InetAddress.getByName("192.168.10.1"), 0));
                long id = session.createObject(cd);
                assertFalse(id == 0);
 
index 5e68469..cda9995 100644 (file)
@@ -73,7 +73,6 @@ public class CreateInterface implements IObjectActionDelegate
                                NXCObjectCreationData cd = new NXCObjectCreationData(AbstractObject.OBJECT_INTERFACE, dlg.getName(), parentId);
                                cd.setMacAddress(dlg.getMacAddress());
                                cd.setIpAddress(dlg.getIpAddress());
-                               cd.setIpNetMask(dlg.getIpNetMask());
                                cd.setPhysicalPort(dlg.isPhysicalPort());
                                cd.setSlot(dlg.getSlot());
                                cd.setPort(dlg.getPort());
index ecebbf4..469f4f3 100644 (file)
@@ -18,7 +18,9 @@
  */
 package org.netxms.ui.eclipse.objectmanager.dialogs;
 
+import java.net.Inet4Address;
 import java.net.InetAddress;
+import java.net.UnknownHostException;
 import org.eclipse.jface.dialogs.Dialog;
 import org.eclipse.swt.SWT;
 import org.eclipse.swt.events.SelectionEvent;
@@ -29,6 +31,7 @@ import org.eclipse.swt.widgets.Button;
 import org.eclipse.swt.widgets.Composite;
 import org.eclipse.swt.widgets.Control;
 import org.eclipse.swt.widgets.Shell;
+import org.netxms.base.InetAddressEx;
 import org.netxms.client.MacAddress;
 import org.netxms.ui.eclipse.objectmanager.Messages;
 import org.netxms.ui.eclipse.tools.IPAddressValidator;
@@ -46,6 +49,8 @@ import org.netxms.ui.eclipse.widgets.LabeledText;
  */
 public class CreateInterfaceDialog extends Dialog
 {
+   private static final int DEFAULT_MASK_BITS = 8;
+   
        private LabeledText nameField;
        private LabeledText macAddrField;
        private LabeledText ipAddrField;
@@ -56,8 +61,7 @@ public class CreateInterfaceDialog extends Dialog
        
        private String name;
        private MacAddress macAddress;
-       private InetAddress ipAddress;
-       private InetAddress ipNetMask;
+       private InetAddressEx ipAddress;
        private int ifIndex;
        private int ifType;
        private int slot;
@@ -193,8 +197,8 @@ public class CreateInterfaceDialog extends Dialog
                {
                        name = nameField.getText().trim();
                        macAddress = macAddrField.getText().trim().isEmpty() ? new MacAddress() : MacAddress.parseMacAddress(macAddrField.getText());
-                       ipAddress = ipAddrField.getText().trim().isEmpty() ? InetAddress.getByName("0.0.0.0") : InetAddress.getByName(ipAddrField.getText()); //$NON-NLS-1$
-                       ipNetMask = ipMaskField.getText().trim().isEmpty() ? InetAddress.getByName("0.0.0.0") : InetAddress.getByName(ipMaskField.getText()); //$NON-NLS-1$
+                       InetAddress addr = ipAddrField.getText().trim().isEmpty() ? InetAddress.getByName("0.0.0.0") : InetAddress.getByName(ipAddrField.getText()); //$NON-NLS-1$
+                       ipAddress = new InetAddressEx(addr, getMaskBits(ipMaskField.getText().trim(), addr instanceof Inet4Address ? 32 : 128));
                        slot = physicalPort ? Integer.parseInt(slotField.getText()) : 0;
                        port = physicalPort ? Integer.parseInt(portField.getText()) : 0;
                        
@@ -205,6 +209,32 @@ public class CreateInterfaceDialog extends Dialog
                        MessageDialogHelper.openError(getShell(), Messages.get().CreateInterfaceDialog_Error, String.format("Internal error: %s", e.getMessage())); //$NON-NLS-1$
                }
        }
+       
+       private int getMaskBits(String mask, int maxBits)
+       {
+          if (mask.isEmpty())
+             return DEFAULT_MASK_BITS;
+          
+          try
+          {
+             int bits = Integer.parseInt(mask);
+             return ((bits >= 0) && (bits <= maxBits)) ? bits : DEFAULT_MASK_BITS;
+          }
+          catch(NumberFormatException e)
+          {
+          }
+          
+          try
+          {
+             InetAddress addr = InetAddress.getByName(mask);
+             return InetAddressEx.bitsInMask(addr);
+          }
+          catch(UnknownHostException e)
+          {
+          }
+          
+          return DEFAULT_MASK_BITS;
+       }
 
        /**
         * @return the name
@@ -233,20 +263,12 @@ public class CreateInterfaceDialog extends Dialog
        /**
         * @return the ipAddress
         */
-       public InetAddress getIpAddress()
+       public InetAddressEx getIpAddress()
        {
                return ipAddress;
        }
 
        /**
-        * @return the ipNetMask
-        */
-       public InetAddress getIpNetMask()
-       {
-               return ipNetMask;
-       }
-
-       /**
         * @return the ifIndex
         */
        public int getIfIndex()
index 9d048bf..c255af0 100644 (file)
@@ -488,6 +488,15 @@ void InetAddressList::add(const InetAddress &addr)
 }
 
 /**
+ * Add multiple addresses to list
+ */
+void InetAddressList::add(const InetAddressList &addrList)
+{
+   for(int i = 0; i < addrList.m_list->size(); i++)
+      add(*(addrList.m_list->get(i)));
+}
+
+/**
  * Remove address from list
  */
 void InetAddressList::remove(const InetAddress &addr)
@@ -498,6 +507,18 @@ void InetAddressList::remove(const InetAddress &addr)
 }
 
 /**
+ * Replace IP address (update it's properties - currently only network mask)
+ */
+void InetAddressList::replace(const InetAddress& addr)
+{
+   int index = indexOf(addr);
+   if (index != -1)
+   {
+      m_list->get(index)->setMaskBits(addr.getMaskBits());
+   }
+}
+
+/**
  * Get index in list of given address
  */
 int InetAddressList::indexOf(const InetAddress &addr) const
@@ -549,3 +570,18 @@ const InetAddress& InetAddressList::findSameSubnetAddress(const InetAddress& add
    }
    return InetAddress::INVALID;
 }
+
+/**
+ * Check if all addresses in list are loopback
+ */
+bool InetAddressList::isLoopbackOnly() const
+{
+   if (m_list->size() == 0)
+      return false;
+   for(int i = 0; i < m_list->size(); i++)
+   {
+      if (!m_list->get(i)->isLoopback())
+         return false;
+   }
+   return true;
+}
index a8222a9..381d6c7 100644 (file)
@@ -199,6 +199,7 @@ bool AccessPoint::deleteFromDatabase(DB_HANDLE hdb)
 void AccessPoint::fillMessage(NXCPMessage *msg)
 {
    DataCollectionTarget::fillMessage(msg);
+   msg->setField(VID_IP_ADDRESS, m_ipAddress);
        msg->setField(VID_NODE_ID, m_nodeId);
        msg->setField(VID_MAC_ADDR, m_macAddr, MAC_ADDR_LENGTH);
        msg->setField(VID_VENDOR, CHECK_NULL_EX(m_vendor));
index 894e0e5..a218e46 100644 (file)
@@ -297,7 +297,10 @@ static BOOL ForwardEvent(const TCHAR *server, Event *event)
                object = FindObjectById(event->getSourceId());
                if (object != NULL)
                {
-                       msg.setField(VID_IP_ADDRESS, object->getIpAddress());
+         if (object->getObjectClass() == OBJECT_NODE)
+         {
+                          msg.setField(VID_IP_ADDRESS, ((Node *)object)->getIpAddress());
+         }
                        msg.setField(VID_EVENT_CODE, event->getCode());
                        msg.setField(VID_EVENT_NAME, event->getName());
                        if (event->getUserTag() != NULL)
index ce291f3..f94b4bc 100644 (file)
@@ -534,7 +534,7 @@ void Cluster::statusPoll(ClientSession *pSession, UINT32 dwRqId, int nPoller)
                                {
                                        for(k = 0; k < m_dwNumResources; k++)
                                        {
-                  if (m_pResourceList[k].ipAddr.equals(pIfList->get(j)->ipAddr))
+                  if (pIfList->get(j)->hasAddress(m_pResourceList[k].ipAddr))
                                                {
                                                        if (m_pResourceList[k].dwCurrOwner != ppPollList[i]->getId())
                                                        {
index 274c03d..96e4ffa 100644 (file)
@@ -323,10 +323,10 @@ void DCObject::expandMacros(const TCHAR *src, TCHAR *dst, size_t dstLen)
                }
                else if (!_tcscmp(macro, _T("node_primary_ip")))
                {
-                       if (m_pNode != NULL)
+                       if ((m_pNode != NULL) && (m_pNode->getObjectClass() == OBJECT_NODE))
                        {
                                TCHAR ipAddr[64];
-                               temp += m_pNode->getIpAddress().toString(ipAddr);
+                               temp += ((Node *)m_pNode)->getIpAddress().toString(ipAddr);
                        }
                        else
                        {
index 6a86569..f7f7958 100644 (file)
@@ -521,59 +521,6 @@ UINT32 DataCollectionTarget::getInternalItem(const TCHAR *param, size_t bufSize,
          dwError = DCE_NOT_SUPPORTED;
       }
    }
-   else if (MatchString(_T("PingTime(*)"), param, FALSE))
-   {
-      NetObj *object = objectFromParameter(param);
-      if ((object != NULL) && (object->getObjectClass() == OBJECT_INTERFACE))
-      {
-         UINT32 value = ((Interface *)object)->getPingTime();
-         if (value == 10000)
-            dwError = DCE_COMM_ERROR;
-         else
-            _sntprintf(buffer, bufSize, _T("%d"), value);
-      }
-      else
-      {
-         dwError = DCE_NOT_SUPPORTED;
-      }
-   }
-   else if (!_tcsicmp(_T("PingTime"), param))
-   {
-      if (m_ipAddress.isValid())
-      {
-         Interface *iface = NULL;
-
-         // Find interface for primary IP
-         LockChildList(FALSE);
-         for(int i = 0; i < (int)m_dwChildCount; i++)
-         {
-            if ((m_pChildList[i]->getObjectClass() == OBJECT_INTERFACE) && m_pChildList[i]->getIpAddress().equals(m_ipAddress))
-            {
-               iface = (Interface *)m_pChildList[i];
-               break;
-            }
-         }
-         UnlockChildList();
-
-         UINT32 value = 10000;
-         if (iface != NULL)
-         {
-            value = iface->getPingTime();
-         }
-         else
-         {
-            value = getPingTime();
-         }
-         if (value == 10000)
-            dwError = DCE_COMM_ERROR;
-         else
-            _sntprintf(buffer, bufSize, _T("%d"), value);
-      }
-      else
-      {
-         dwError = DCE_NOT_SUPPORTED;
-      }
-   }
    else
    {
       dwError = DCE_NOT_SUPPORTED;
index f9a3480..9488a40 100644 (file)
@@ -273,7 +273,7 @@ TCHAR *Event::expandText(Event *event, UINT32 sourceObject, const TCHAR *textTem
                case 'a':   // IP address of event source
                   dwSize += 64;
                   pText = (TCHAR *)realloc(pText, dwSize * sizeof(TCHAR));
-                  pObject->getIpAddress().toString(&pText[dwPos]);
+                  GetObjectIpAddress(pObject).toString(&pText[dwPos]);
                   dwPos = (UINT32)_tcslen(pText);
                   break;
                case 'g':   // Source object's GUID
index f722f10..68c4ad1 100644 (file)
@@ -30,6 +30,7 @@ struct InetAddressIndexEntry
 {
    UT_hash_handle hh;
    BYTE key[18];
+   InetAddress addr;
    NetObj *object;
 };
 
@@ -59,7 +60,7 @@ InetAddressIndex::~InetAddressIndex()
 /**
  * Put object into index
  *
- * @param key object's key
+ * @param addr IP address
  * @param object object
  * @return true if existing object was replaced
  */
@@ -81,6 +82,7 @@ bool InetAddressIndex::put(const InetAddress& addr, NetObj *object)
    {
       entry = (InetAddressIndexEntry *)malloc(sizeof(InetAddressIndexEntry));
       memcpy(entry->key, key, 18);
+      entry->addr = addr;
       HASH_ADD_KEYPTR(hh, m_root, entry->key, 18, entry);
       replace = false;
    }
@@ -91,6 +93,24 @@ bool InetAddressIndex::put(const InetAddress& addr, NetObj *object)
 }
 
 /**
+ * Put object into index
+ *
+ * @param addrList IP address list
+ * @param object object
+ * @return true if existing object was replaced
+ */
+bool InetAddressIndex::put(const InetAddressList *addrList, NetObj *object)
+{
+   bool replaced = false;
+   for(int i = 0; i < addrList->size(); i++)
+   {
+      if (put(addrList->get(i), object))
+         replaced = true;
+   }
+   return replaced;
+}
+
+/**
  * Remove object from index
  */
 void InetAddressIndex::remove(const InetAddress& addr)
@@ -197,13 +217,13 @@ ObjectArray<NetObj> *InetAddressIndex::getObjects(bool updateRefCount, bool (*fi
 /**
  * Execute given callback for each object
  */
-void InetAddressIndex::forEach(void (*callback)(NetObj *, void *), void *data)
+void InetAddressIndex::forEach(void (*callback)(const InetAddress& addr, NetObj *, void *), void *data)
 {
    RWLockReadLock(m_lock, INFINITE);
    InetAddressIndexEntry *entry, *tmp;
    HASH_ITER(hh, m_root, entry, tmp)
    {
-      callback(entry->object, data);
+      callback(entry->addr, entry->object, data);
    }
    RWLockUnlock(m_lock);
 }
index ba447ce..b7c8a20 100644 (file)
@@ -55,16 +55,16 @@ Interface::Interface() : NetObj()
 /**
  * Constructor for "fake" interface object
  */
-Interface::Interface(const InetAddress& addr, UINT32 zoneId, bool bSyntheticMask) : NetObj()
+Interface::Interface(const InetAddressList& addrList, UINT32 zoneId, bool bSyntheticMask) : NetObj()
 {
        m_flags = bSyntheticMask ? IF_SYNTHETIC_MASK : 0;
-   if (addr.isLoopback())
+   if (addrList.isLoopbackOnly())
                m_flags |= IF_LOOPBACK;
 
        _tcscpy(m_name, _T("unknown"));
    _tcscpy(m_description, _T("unknown"));
    m_alias[0] = 0;
-   m_ipAddress = addr;
+   m_ipAddressList.add(addrList);
    m_index = 1;
    m_type = IFTYPE_OTHER;
    m_mtu = 0;
@@ -90,10 +90,10 @@ Interface::Interface(const InetAddress& addr, UINT32 zoneId, bool bSyntheticMask
 /**
  * Constructor for normal interface object
  */
-Interface::Interface(const TCHAR *name, const TCHAR *descr, UINT32 index, const InetAddress& addr, UINT32 ifType, UINT32 zoneId)
+Interface::Interface(const TCHAR *name, const TCHAR *descr, UINT32 index, const InetAddressList& addrList, UINT32 ifType, UINT32 zoneId)
           : NetObj()
 {
-   if (addr.isLoopback() || (ifType == IFTYPE_SOFTWARE_LOOPBACK))
+   if ((ifType == IFTYPE_SOFTWARE_LOOPBACK) || addrList.isLoopbackOnly())
                m_flags = IF_LOOPBACK;
        else
                m_flags = 0;
@@ -104,7 +104,7 @@ Interface::Interface(const TCHAR *name, const TCHAR *descr, UINT32 index, const
    m_index = index;
    m_type = ifType;
    m_mtu = 0;
-   m_ipAddress = addr;
+   m_ipAddressList.add(addrList);
        m_bridgePortNumber = 0;
        m_slotNumber = 0;
        m_portNumber = 0;
@@ -157,7 +157,7 @@ BOOL Interface::loadFromDatabase(UINT32 dwId)
       return FALSE;
 
        DB_STATEMENT hStmt = DBPrepare(g_hCoreDB,
-               _T("SELECT ip_addr,ip_netmask,if_type,if_index,node_id,")
+               _T("SELECT if_type,if_index,node_id,")
                _T("mac_addr,flags,required_polls,bridge_port,phy_slot,")
                _T("phy_port,peer_node_id,peer_if_id,description,")
                _T("dot1x_pae_state,dot1x_backend_state,admin_state,")
@@ -175,27 +175,25 @@ BOOL Interface::loadFromDatabase(UINT32 dwId)
 
    if (DBGetNumRows(hResult) != 0)
    {
-      m_ipAddress = DBGetFieldInetAddr(hResult, 0, 0);
-      m_ipAddress.setMaskBits(DBGetFieldLong(hResult, 0, 1));
-      m_type = DBGetFieldULong(hResult, 0, 2);
-      m_index = DBGetFieldULong(hResult, 0, 3);
-      UINT32 nodeId = DBGetFieldULong(hResult, 0, 4);
-               DBGetFieldByteArray2(hResult, 0, 5, m_macAddr, MAC_ADDR_LENGTH, 0);
-               m_flags = DBGetFieldULong(hResult, 0, 6);
-      m_requiredPollCount = DBGetFieldLong(hResult, 0, 7);
-               m_bridgePortNumber = DBGetFieldULong(hResult, 0, 8);
-               m_slotNumber = DBGetFieldULong(hResult, 0, 9);
-               m_portNumber = DBGetFieldULong(hResult, 0, 10);
-               m_peerNodeId = DBGetFieldULong(hResult, 0, 11);
-               m_peerInterfaceId = DBGetFieldULong(hResult, 0, 12);
-               DBGetField(hResult, 0, 13, m_description, MAX_DB_STRING);
-               m_dot1xPaeAuthState = (WORD)DBGetFieldLong(hResult, 0, 14);
-               m_dot1xBackendAuthState = (WORD)DBGetFieldLong(hResult, 0, 15);
-               m_adminState = (WORD)DBGetFieldLong(hResult, 0, 16);
-               m_operState = (WORD)DBGetFieldLong(hResult, 0, 17);
-               m_peerDiscoveryProtocol = (LinkLayerProtocol)DBGetFieldLong(hResult, 0, 18);
-               DBGetField(hResult, 0, 19, m_alias, MAX_DB_STRING);
-               m_mtu = DBGetFieldULong(hResult, 0, 20);
+      m_type = DBGetFieldULong(hResult, 0, 0);
+      m_index = DBGetFieldULong(hResult, 0, 1);
+      UINT32 nodeId = DBGetFieldULong(hResult, 0, 2);
+               DBGetFieldByteArray2(hResult, 0, 3, m_macAddr, MAC_ADDR_LENGTH, 0);
+               m_flags = DBGetFieldULong(hResult, 0, 4);
+      m_requiredPollCount = DBGetFieldLong(hResult, 0, 5);
+               m_bridgePortNumber = DBGetFieldULong(hResult, 0, 6);
+               m_slotNumber = DBGetFieldULong(hResult, 0, 7);
+               m_portNumber = DBGetFieldULong(hResult, 0, 8);
+               m_peerNodeId = DBGetFieldULong(hResult, 0, 9);
+               m_peerInterfaceId = DBGetFieldULong(hResult, 0, 10);
+               DBGetField(hResult, 0, 11, m_description, MAX_DB_STRING);
+               m_dot1xPaeAuthState = (WORD)DBGetFieldLong(hResult, 0, 12);
+               m_dot1xBackendAuthState = (WORD)DBGetFieldLong(hResult, 0, 13);
+               m_adminState = (WORD)DBGetFieldLong(hResult, 0, 14);
+               m_operState = (WORD)DBGetFieldLong(hResult, 0, 15);
+               m_peerDiscoveryProtocol = (LinkLayerProtocol)DBGetFieldLong(hResult, 0, 16);
+               DBGetField(hResult, 0, 17, m_alias, MAX_DB_STRING);
+               m_mtu = DBGetFieldULong(hResult, 0, 18);
 
       m_pingTime = PING_TIME_TIMEOUT;
       m_pingLastTimeStamp = 0;
@@ -229,12 +227,47 @@ BOOL Interface::loadFromDatabase(UINT32 dwId)
    DBFreeResult(hResult);
        DBFreeStatement(hStmt);
 
+   // Read IP addresses
+   hStmt = DBPrepare(g_hCoreDB, _T("SELECT ip_addr,ip_netmask FROM interface_address_list WHERE iface_id = ?"));
+   if (hStmt != NULL)
+   {
+      DBBind(hStmt, 1, DB_SQLTYPE_INTEGER, m_id);
+      hResult = DBSelectPrepared(hStmt);
+      if (hResult != NULL)
+      {
+         int count = DBGetNumRows(hResult);
+         for(int i = 0; i < count; i++)
+         {
+            InetAddress addr = DBGetFieldInetAddr(hResult, i, 0);
+            addr.setMaskBits(DBGetFieldLong(hResult, i, 1));
+            if (addr.isValid())
+               m_ipAddressList.add(addr);
+         }
+         DBFreeResult(hResult);
+      }
+      DBFreeStatement(hStmt);
+   }
+
    // Load access list
    loadACLFromDB();
 
        // Validate loopback flag
-       if (m_ipAddress.isLoopback() || (m_type == IFTYPE_SOFTWARE_LOOPBACK))
+       if (m_type == IFTYPE_SOFTWARE_LOOPBACK)
+   {
                m_flags |= IF_LOOPBACK;
+   }
+   else
+   {
+      const ObjectArray<InetAddress> *list = m_ipAddressList.getList();
+      int count = 0;
+      for(int i = 0; i < list->size(); i++)
+      {
+         if (list->get(i)->isLoopback())
+            count++;
+      }
+      if (count == list->size()) // all loopback addresses
+               m_flags |= IF_LOOPBACK;
+   }
 
    return bResult;
 }
@@ -244,7 +277,7 @@ BOOL Interface::loadFromDatabase(UINT32 dwId)
  */
 BOOL Interface::saveToDatabase(DB_HANDLE hdb)
 {
-   TCHAR szMacStr[16], szIpAddr[64];
+   TCHAR szMacStr[16];
    UINT32 dwNodeId;
 
    lockProperties();
@@ -267,8 +300,7 @@ BOOL Interface::saveToDatabase(DB_HANDLE hdb)
    if (IsDatabaseRecordExist(hdb, _T("interfaces"), _T("id"), m_id))
        {
                hStmt = DBPrepare(hdb,
-                       _T("UPDATE interfaces SET ip_addr=?,ip_netmask=?,")
-         _T("node_id=?,if_type=?,if_index=?,mac_addr=?,flags=?,")
+                       _T("UPDATE interfaces SET node_id=?,if_type=?,if_index=?,mac_addr=?,flags=?,")
                        _T("required_polls=?,bridge_port=?,phy_slot=?,phy_port=?,")
                        _T("peer_node_id=?,peer_if_id=?,description=?,admin_state=?,")
                        _T("oper_state=?,dot1x_pae_state=?,dot1x_backend_state=?,")
@@ -277,10 +309,10 @@ BOOL Interface::saveToDatabase(DB_HANDLE hdb)
    else
        {
                hStmt = DBPrepare(hdb,
-                       _T("INSERT INTO interfaces (ip_addr,ip_netmask,node_id,if_type,if_index,mac_addr,")
+                       _T("INSERT INTO interfaces (node_id,if_type,if_index,mac_addr,")
                        _T("flags,required_polls,bridge_port,phy_slot,phy_port,peer_node_id,peer_if_id,description,")
          _T("admin_state,oper_state,dot1x_pae_state,dot1x_backend_state,peer_proto,alias,mtu,id) ")
-                       _T("VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)"));
+                       _T("VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)"));
        }
        if (hStmt == NULL)
        {
@@ -288,32 +320,65 @@ BOOL Interface::saveToDatabase(DB_HANDLE hdb)
                return FALSE;
        }
 
-       DBBind(hStmt, 1, DB_SQLTYPE_VARCHAR, m_ipAddress.toString(szIpAddr), DB_BIND_STATIC);
-       DBBind(hStmt, 2, DB_SQLTYPE_INTEGER, m_ipAddress.getMaskBits());
-       DBBind(hStmt, 3, DB_SQLTYPE_INTEGER, dwNodeId);
-       DBBind(hStmt, 4, DB_SQLTYPE_INTEGER, m_type);
-       DBBind(hStmt, 5, DB_SQLTYPE_INTEGER, m_index);
-       DBBind(hStmt, 6, DB_SQLTYPE_VARCHAR, BinToStr(m_macAddr, MAC_ADDR_LENGTH, szMacStr), DB_BIND_STATIC);
-       DBBind(hStmt, 7, DB_SQLTYPE_INTEGER, m_flags);
-       DBBind(hStmt, 8, DB_SQLTYPE_INTEGER, (LONG)m_requiredPollCount);
-       DBBind(hStmt, 9, DB_SQLTYPE_INTEGER, m_bridgePortNumber);
-       DBBind(hStmt, 10, DB_SQLTYPE_INTEGER, m_slotNumber);
-       DBBind(hStmt, 11, DB_SQLTYPE_INTEGER, m_portNumber);
-       DBBind(hStmt, 12, DB_SQLTYPE_INTEGER, m_peerNodeId);
-       DBBind(hStmt, 13, DB_SQLTYPE_INTEGER, m_peerInterfaceId);
-       DBBind(hStmt, 14, DB_SQLTYPE_VARCHAR, m_description, DB_BIND_STATIC);
-       DBBind(hStmt, 15, DB_SQLTYPE_INTEGER, (UINT32)m_adminState);
-       DBBind(hStmt, 16, DB_SQLTYPE_INTEGER, (UINT32)m_operState);
-       DBBind(hStmt, 17, DB_SQLTYPE_INTEGER, (UINT32)m_dot1xPaeAuthState);
-       DBBind(hStmt, 18, DB_SQLTYPE_INTEGER, (UINT32)m_dot1xBackendAuthState);
-       DBBind(hStmt, 19, DB_SQLTYPE_INTEGER, (INT32)m_peerDiscoveryProtocol);
-       DBBind(hStmt, 20, DB_SQLTYPE_VARCHAR, m_alias, DB_BIND_STATIC);
-       DBBind(hStmt, 21, DB_SQLTYPE_INTEGER, m_mtu);
-       DBBind(hStmt, 22, DB_SQLTYPE_INTEGER, m_id);
+       DBBind(hStmt, 1, DB_SQLTYPE_INTEGER, dwNodeId);
+       DBBind(hStmt, 2, DB_SQLTYPE_INTEGER, m_type);
+       DBBind(hStmt, 3, DB_SQLTYPE_INTEGER, m_index);
+       DBBind(hStmt, 4, DB_SQLTYPE_VARCHAR, BinToStr(m_macAddr, MAC_ADDR_LENGTH, szMacStr), DB_BIND_STATIC);
+       DBBind(hStmt, 5, DB_SQLTYPE_INTEGER, m_flags);
+       DBBind(hStmt, 6, DB_SQLTYPE_INTEGER, (LONG)m_requiredPollCount);
+       DBBind(hStmt, 7, DB_SQLTYPE_INTEGER, m_bridgePortNumber);
+       DBBind(hStmt, 8, DB_SQLTYPE_INTEGER, m_slotNumber);
+       DBBind(hStmt, 9, DB_SQLTYPE_INTEGER, m_portNumber);
+       DBBind(hStmt, 10, DB_SQLTYPE_INTEGER, m_peerNodeId);
+       DBBind(hStmt, 11, DB_SQLTYPE_INTEGER, m_peerInterfaceId);
+       DBBind(hStmt, 12, DB_SQLTYPE_VARCHAR, m_description, DB_BIND_STATIC);
+       DBBind(hStmt, 13, DB_SQLTYPE_INTEGER, (UINT32)m_adminState);
+       DBBind(hStmt, 14, DB_SQLTYPE_INTEGER, (UINT32)m_operState);
+       DBBind(hStmt, 15, DB_SQLTYPE_INTEGER, (UINT32)m_dot1xPaeAuthState);
+       DBBind(hStmt, 16, DB_SQLTYPE_INTEGER, (UINT32)m_dot1xBackendAuthState);
+       DBBind(hStmt, 17, DB_SQLTYPE_INTEGER, (INT32)m_peerDiscoveryProtocol);
+       DBBind(hStmt, 18, DB_SQLTYPE_VARCHAR, m_alias, DB_BIND_STATIC);
+       DBBind(hStmt, 19, DB_SQLTYPE_INTEGER, m_mtu);
+       DBBind(hStmt, 20, DB_SQLTYPE_INTEGER, m_id);
 
        BOOL success = DBExecute(hStmt);
        DBFreeStatement(hStmt);
 
+   // Save IP addresses
+   if (success)
+   {
+      success = FALSE;
+
+               hStmt = DBPrepare(hdb, _T("DELETE FROM interface_address_list WHERE iface_id = ?"));
+      if (hStmt != NULL)
+      {
+         DBBind(hStmt, 1, DB_SQLTYPE_INTEGER, m_id);
+         success = DBExecute(hStmt);
+         DBFreeStatement(hStmt);
+      }
+   }
+
+   if (success && (m_ipAddressList.size() > 0))
+   {
+      success = FALSE;
+
+               hStmt = DBPrepare(hdb, _T("INSERT INTO interface_address_list (iface_id,ip_addr,ip_netmask) VALUES (?,?,?)"));
+      if (hStmt != NULL)
+      {
+         DBBind(hStmt, 1, DB_SQLTYPE_INTEGER, m_id);
+         const ObjectArray<InetAddress> *list = m_ipAddressList.getList();
+         for(int i = 0; (i < list->size()) && success; i++)
+         {
+            InetAddress *a = list->get(i);
+            TCHAR buffer[64];
+            DBBind(hStmt, 2, DB_SQLTYPE_VARCHAR, a->toString(buffer), DB_BIND_STATIC);
+            DBBind(hStmt, 3, DB_SQLTYPE_INTEGER, a->getMaskBits());
+            success = DBExecute(hStmt);
+         }
+         DBFreeStatement(hStmt);
+      }
+   }
+
    // Save access list
        if (success)
                success = saveACLToDB(hdb);
@@ -334,13 +399,15 @@ bool Interface::deleteFromDatabase(DB_HANDLE hdb)
    bool success = NetObj::deleteFromDatabase(hdb);
    if (success)
       success = executeQueryOnObject(hdb, _T("DELETE FROM interfaces WHERE id=?"));
+   if (success)
+      success = executeQueryOnObject(hdb, _T("DELETE FROM interface_address_list WHERE iface_id=?"));
    return success;
 }
 
 /**
  * Perform status poll on interface
  */
-void Interface::statusPoll(ClientSession *session, UINT32 rqId, Queue *eventQueue, bool clusterSync, SNMP_Transport *snmpTransport, UINT32 nodeIcmpProxy)
+void Interface::statusPoll(ClientSession *session, UINT32 rqId, Queue *eventQueue, Cluster *cluster, SNMP_Transport *snmpTransport, UINT32 nodeIcmpProxy)
 {
    m_pollRequestor = session;
    Node *pNode = getParentNode();
@@ -396,7 +463,7 @@ void Interface::statusPoll(ClientSession *session, UINT32 rqId, Queue *eventQueu
    if (bNeedPoll)
    {
                // Pings cannot be used for cluster sync interfaces
-      if ((pNode->getFlags() & NF_DISABLE_ICMP) || clusterSync || !m_ipAddress.isValid() || isLoopback())
+      if ((pNode->getFlags() & NF_DISABLE_ICMP) || isLoopback() || !m_ipAddressList.hasValidUnicastAddress())
       {
                        // Interface doesn't have an IP address, so we can't ping it
                        sendPollerMsg(rqId, POLLER_WARNING _T("      Interface status cannot be determined\r\n"));
@@ -404,88 +471,7 @@ void Interface::statusPoll(ClientSession *session, UINT32 rqId, Queue *eventQueu
       }
       else
       {
-         // Use ICMP ping as a last option
-                       UINT32 icmpProxy = nodeIcmpProxy;
-
-                       if (IsZoningEnabled() && (m_zoneId != 0) && (icmpProxy == 0))
-                       {
-                               Zone *zone = (Zone *)g_idxZoneByGUID.get(m_zoneId);
-                               if (zone != NULL)
-                               {
-                                       icmpProxy = zone->getIcmpProxy();
-                               }
-                       }
-
-                       if (icmpProxy != 0)
-                       {
-                               sendPollerMsg(rqId, _T("      Starting ICMP ping via proxy\r\n"));
-                               DbgPrintf(7, _T("Interface::StatusPoll(%d,%s): ping via proxy [%u]"), m_id, m_name, icmpProxy);
-                               Node *proxyNode = (Node *)g_idxNodeById.get(icmpProxy);
-                               if ((proxyNode != NULL) && proxyNode->isNativeAgent() && !proxyNode->isDown())
-                               {
-                                       DbgPrintf(7, _T("Interface::StatusPoll(%d,%s): proxy node found: %s"), m_id, m_name, proxyNode->getName());
-                                       AgentConnection *conn = proxyNode->createAgentConnection();
-                                       if (conn != NULL)
-                                       {
-                                               TCHAR parameter[128], buffer[64];
-
-                                               _sntprintf(parameter, 128, _T("Icmp.Ping(%s)"), m_ipAddress.toString(buffer));
-                                               if (conn->getParameter(parameter, 64, buffer) == ERR_SUCCESS)
-                                               {
-                                                       DbgPrintf(7, _T("Interface::StatusPoll(%d,%s): proxy response: \"%s\""), m_id, m_name, buffer);
-                                                       TCHAR *eptr;
-                                                       long value = _tcstol(buffer, &eptr, 10);
-                                                       if ((*eptr == 0) && (value >= 0))
-                                                       {
-                        m_pingLastTimeStamp = time(NULL);
-                        m_pingTime = value;
-                                                               if (value < 10000)
-                                                               {
-                                                                       adminState = IF_ADMIN_STATE_UP;
-                                                                       operState = IF_OPER_STATE_UP;
-                                                               }
-                                                               else
-                                                               {
-                                                                       adminState = IF_ADMIN_STATE_UNKNOWN;
-                                                                       operState = IF_OPER_STATE_DOWN;
-                                                               }
-                                                       }
-                                               }
-                                               conn->disconnect();
-                                               delete conn;
-                                       }
-                                       else
-                                       {
-                                               DbgPrintf(7, _T("Interface::StatusPoll(%d,%s): cannot connect to agent on proxy node"), m_id, m_name);
-                                               sendPollerMsg(rqId, POLLER_ERROR _T("      Unable to establish connection with proxy node\r\n"));
-                                       }
-                               }
-                               else
-                               {
-                                       DbgPrintf(7, _T("Interface::StatusPoll(%d,%s): proxy node not available"), m_id, m_name);
-                                       sendPollerMsg(rqId, POLLER_ERROR _T("      ICMP proxy not available\r\n"));
-                               }
-                       }
-                       else    // not using ICMP proxy
-                       {
-                               sendPollerMsg(rqId, _T("      Starting ICMP ping\r\n"));
-                               DbgPrintf(7, _T("Interface::StatusPoll(%d,%s): calling IcmpPing(%s,3,%d,%d,%d)"), 
-               m_id, m_name, (const TCHAR *)m_ipAddress.toString(), g_icmpPingTimeout, m_pingTime, g_icmpPingSize);
-                               UINT32 dwPingStatus = IcmpPing(m_ipAddress, 3, g_icmpPingTimeout, &m_pingTime, g_icmpPingSize);
-            m_pingLastTimeStamp = time(NULL);
-                               if (dwPingStatus == ICMP_SUCCESS)
-                               {
-                                       adminState = IF_ADMIN_STATE_UP;
-                                       operState = IF_OPER_STATE_UP;
-                               }
-                               else
-                               {
-               m_pingTime = PING_TIME_TIMEOUT;
-                                       adminState = IF_ADMIN_STATE_UNKNOWN;
-                                       operState = IF_OPER_STATE_DOWN;
-                               }
-                               DbgPrintf(7, _T("Interface::StatusPoll(%d,%s): ping result %d, adminState=%d, operState=%d"), m_id, m_name, dwPingStatus, adminState, operState);
-                       }
+         icmpStatusPoll(rqId, nodeIcmpProxy, cluster, &adminState, &operState);
       }
    }
 
@@ -528,7 +514,7 @@ void Interface::statusPoll(ClientSession *session, UINT32 rqId, Queue *eventQueu
        if ((pNode->getFlags() & NF_IS_8021X) && isPhysicalPort() && (snmpTransport != NULL))
        {
                DbgPrintf(5, _T("StatusPoll(%s): Checking 802.1x state for interface %s"), pNode->getName(), m_name);
-               paeStatusPoll(session, rqId, snmpTransport, pNode);
+               paeStatusPoll(rqId, snmpTransport, pNode);
                if ((m_dot1xPaeAuthState == PAE_STATE_FORCE_UNAUTH) && (newStatus < STATUS_MAJOR))
                        newStatus = STATUS_MAJOR;
        }
@@ -590,9 +576,10 @@ void Interface::statusPoll(ClientSession *session, UINT32 rqId, Queue *eventQueu
       if (!m_isSystem)
       {
                   sendPollerMsg(rqId, _T("      Interface status changed to %s\r\n"), GetStatusAsText(m_iStatus, true));
+         const InetAddress& addr = m_ipAddressList.getFirstUnicastAddress();
                   PostEventEx(eventQueue,
                               (expectedState == IF_EXPECTED_STATE_DOWN) ? statusToEventInverted[m_iStatus] : statusToEvent[m_iStatus],
-                                                  pNode->getId(), "dsAdd", m_id, m_name, &m_ipAddress, m_ipAddress.getMaskBits(), m_index);
+                     pNode->getId(), "dsAdd", m_id, m_name, &addr, addr.getMaskBits(), m_index);
       }
    }
        else if (expectedState == IF_EXPECTED_STATE_IGNORE)
@@ -648,24 +635,34 @@ void Interface::updatePingData()
          if (conn != NULL)
          {
             TCHAR parameter[128], buffer[64];
-
-            _sntprintf(parameter, 128, _T("Icmp.Ping(%s)"), m_ipAddress.toString(buffer));
-            if (conn->getParameter(parameter, 64, buffer) == ERR_SUCCESS)
+            const ObjectArray<InetAddress> *list = m_ipAddressList.getList();
+            long value = -1;
+            for(int i = 0; (i < list->size()) && ((value == 10000) || (value == -1)); i++)
             {
-               DbgPrintf(7, _T("Interface::updatePingData:  proxy response: \"%s\""), buffer);
-               TCHAR *eptr;
-               long value = _tcstol(buffer, &eptr, 10);
-               m_pingLastTimeStamp = time(NULL);
-               if ((*eptr == 0) && (value >= 0) && (value < 10000))
-               {
-                  m_pingTime = value;
-               }
-               else
-               {
-                  m_pingTime = PING_TIME_TIMEOUT;
-                  DbgPrintf(7, _T("Interface::updatePingData: incorrect value: %d or error while parsing: %s"), value, eptr);
+               const InetAddress *a = list->get(i);
+                                  _sntprintf(parameter, 128, _T("Icmp.Ping(%s)"), a->toString(buffer));
+                                  if (conn->getParameter(parameter, 64, buffer) == ERR_SUCCESS)
+                                  {
+                  DbgPrintf(7, _T("Interface::updatePingData: proxy response: \"%s\""), buffer);
+                                          TCHAR *eptr;
+                                          long value = _tcstol(buffer, &eptr, 10);
+                  if (*eptr != 0)
+                  {
+                     value = -1;
+                  }
                }
             }
+
+                               if (value >= 0)
+                               {
+               m_pingTime = value;
+                               }
+            else
+            {
+               m_pingTime = PING_TIME_TIMEOUT;
+               DbgPrintf(7, _T("Interface::updatePingData: incorrect value or error while parsing"));
+            }
+            m_pingLastTimeStamp = time(NULL);
             conn->disconnect();
             delete conn;
          }
@@ -681,10 +678,18 @@ void Interface::updatePingData()
    }
    else        // not using ICMP proxy
    {
-      UINT32 dwPingStatus = IcmpPing(m_ipAddress, 3, g_icmpPingTimeout, &m_pingTime, g_icmpPingSize);
+      const ObjectArray<InetAddress> *list = m_ipAddressList.getList();
+      UINT32 dwPingStatus = ICMP_TIMEOUT;
+      for(int i = 0; (i < list->size()) && (dwPingStatus != ICMP_SUCCESS); i++)
+      {
+         const InetAddress *a = list->get(i);
+                  DbgPrintf(7, _T("Interface::StatusPoll(%d,%s): calling IcmpPing(%s,3,%d,%d,%d)"), 
+            m_id, m_name, (const TCHAR *)a->toString(), g_icmpPingTimeout, m_pingTime, g_icmpPingSize);
+                  dwPingStatus = IcmpPing(*a, 3, g_icmpPingTimeout, &m_pingTime, g_icmpPingSize);
+      }
       if (dwPingStatus != ICMP_SUCCESS)
       {
-         DbgPrintf(7, _T("Interface::updatePingData: error getting ping %d"), dwPingStatus);
+         DbgPrintf(7, _T("Interface::updatePingData: error: %d"), dwPingStatus);
          m_pingTime = PING_TIME_TIMEOUT;
       }
       m_pingLastTimeStamp = time(NULL);
@@ -692,9 +697,120 @@ void Interface::updatePingData()
 }
 
 /**
+ * Do ICMP part of status poll
+ */
+void Interface::icmpStatusPoll(UINT32 rqId, UINT32 nodeIcmpProxy, Cluster *cluster, InterfaceAdminState *adminState, InterfaceOperState *operState)
+{
+   // Use ICMP ping as a last option
+       UINT32 icmpProxy = nodeIcmpProxy;
+
+       if (IsZoningEnabled() && (m_zoneId != 0) && (icmpProxy == 0))
+       {
+               Zone *zone = (Zone *)g_idxZoneByGUID.get(m_zoneId);
+               if (zone != NULL)
+               {
+                       icmpProxy = zone->getIcmpProxy();
+               }
+       }
+
+       if (icmpProxy != 0)
+       {
+               sendPollerMsg(rqId, _T("      Starting ICMP ping via proxy\r\n"));
+               DbgPrintf(7, _T("Interface::StatusPoll(%d,%s): ping via proxy [%u]"), m_id, m_name, icmpProxy);
+               Node *proxyNode = (Node *)g_idxNodeById.get(icmpProxy);
+               if ((proxyNode != NULL) && proxyNode->isNativeAgent() && !proxyNode->isDown())
+               {
+                       DbgPrintf(7, _T("Interface::StatusPoll(%d,%s): proxy node found: %s"), m_id, m_name, proxyNode->getName());
+                       AgentConnection *conn = proxyNode->createAgentConnection();
+                       if (conn != NULL)
+                       {
+                               TCHAR parameter[128], buffer[64];
+            const ObjectArray<InetAddress> *list = m_ipAddressList.getList();
+            long value = -1;
+            for(int i = 0; (i < list->size()) && ((value == 10000) || (value == -1)); i++)
+            {
+               const InetAddress *a = list->get(i);
+               if (a->isValidUnicast() && ((cluster == NULL) || !cluster->isSyncAddr(*a)))
+               {
+                                     _sntprintf(parameter, 128, _T("Icmp.Ping(%s)"), a->toString(buffer));
+                                     if (conn->getParameter(parameter, 64, buffer) == ERR_SUCCESS)
+                                     {
+                                             DbgPrintf(7, _T("Interface::StatusPoll(%d,%s): proxy response: \"%s\""), m_id, m_name, buffer);
+                                             TCHAR *eptr;
+                                             long value = _tcstol(buffer, &eptr, 10);
+                     if (*eptr != 0)
+                     {
+                        value = -1;
+                     }
+                  }
+               }
+            }
+
+                               if (value >= 0)
+                               {
+               m_pingTime = value;
+                                       if (value < 10000)
+                                       {
+                                               *adminState = IF_ADMIN_STATE_UP;
+                                               *operState = IF_OPER_STATE_UP;
+                                       }
+                                       else
+                                       {
+                                               *adminState = IF_ADMIN_STATE_UNKNOWN;
+                                               *operState = IF_OPER_STATE_DOWN;
+                                       }
+                               }
+            m_pingLastTimeStamp = time(NULL);
+                               conn->disconnect();
+                               delete conn;
+                       }
+                       else
+                       {
+                               DbgPrintf(7, _T("Interface::StatusPoll(%d,%s): cannot connect to agent on proxy node"), m_id, m_name);
+                               sendPollerMsg(rqId, POLLER_ERROR _T("      Unable to establish connection with proxy node\r\n"));
+                       }
+               }
+               else
+               {
+                       DbgPrintf(7, _T("Interface::StatusPoll(%d,%s): proxy node not available"), m_id, m_name);
+                       sendPollerMsg(rqId, POLLER_ERROR _T("      ICMP proxy not available\r\n"));
+               }
+       }
+       else    // not using ICMP proxy
+       {
+               sendPollerMsg(rqId, _T("      Starting ICMP ping\r\n"));
+      const ObjectArray<InetAddress> *list = m_ipAddressList.getList();
+      UINT32 dwPingStatus = ICMP_TIMEOUT;
+      for(int i = 0; (i < list->size()) && (dwPingStatus != ICMP_SUCCESS); i++)
+      {
+         const InetAddress *a = list->get(i);
+         if (a->isValidUnicast() && ((cluster == NULL) || !cluster->isSyncAddr(*a)))
+         {
+                     DbgPrintf(7, _T("Interface::StatusPoll(%d,%s): calling IcmpPing(%s,3,%d,%d,%d)"), 
+               m_id, m_name, (const TCHAR *)a->toString(), g_icmpPingTimeout, m_pingTime, g_icmpPingSize);
+                     dwPingStatus = IcmpPing(*a, 3, g_icmpPingTimeout, &m_pingTime, g_icmpPingSize);
+         }
+      }
+      m_pingLastTimeStamp = time(NULL);
+               if (dwPingStatus == ICMP_SUCCESS)
+               {
+                       *adminState = IF_ADMIN_STATE_UP;
+                       *operState = IF_OPER_STATE_UP;
+               }
+               else
+               {
+         m_pingTime = PING_TIME_TIMEOUT;
+                       *adminState = IF_ADMIN_STATE_UNKNOWN;
+                       *operState = IF_OPER_STATE_DOWN;
+               }
+               DbgPrintf(7, _T("Interface::StatusPoll(%d,%s): ping result %d, adminState=%d, operState=%d"), m_id, m_name, dwPingStatus, adminState, operState);
+       }
+}
+
+/**
  * PAE (802.1x) status poll
  */
-void Interface::paeStatusPoll(ClientSession *pSession, UINT32 rqId, SNMP_Transport *pTransport, Node *node)
+void Interface::paeStatusPoll(UINT32 rqId, SNMP_Transport *pTransport, Node *node)
 {
        static const TCHAR *paeStateText[] =
        {
@@ -858,17 +974,21 @@ void Interface::setExpectedState(int state)
  */
 UINT32 Interface::wakeUp()
 {
-   UINT32 dwAddr, dwResult = RCC_NO_MAC_ADDRESS;
+   UINT32 rcc = RCC_NO_MAC_ADDRESS;
 
    if (memcmp(m_macAddr, "\x00\x00\x00\x00\x00\x00", 6))
    {
-      dwAddr = htonl(m_ipAddress.getAddressV4() | ~(0xFFFFFFFF << m_ipAddress.getMaskBits()));
-      if (SendMagicPacket(dwAddr, m_macAddr, 5))
-         dwResult = RCC_SUCCESS;
-      else
-         dwResult = RCC_COMM_FAILURE;
+      const InetAddress addr = m_ipAddressList.getFirstUnicastAddressV4();
+      if (addr.isValid())
+      {
+         UINT32 destAddr = htonl(addr.getAddressV4() | ~(0xFFFFFFFF << addr.getMaskBits()));
+         if (SendMagicPacket(destAddr, m_macAddr, 5))
+            rcc = RCC_SUCCESS;
+         else
+            rcc = RCC_COMM_FAILURE;
+      }
    }
-   return dwResult;
+   return rcc;
 }
 
 /**
@@ -900,32 +1020,6 @@ UINT32 Interface::getParentNodeId()
 }
 
 /**
- * Change interface's IP address
- */
-void Interface::setIpAddr(const InetAddress& newAddr)
-{
-   UpdateInterfaceIndex(m_ipAddress, newAddr, this);
-   lockProperties();
-   m_ipAddress = newAddr;
-   setModified();
-   unlockProperties();
-}
-
-/**
- * Change interface's IP subnet mask
- */
-void Interface::setIpNetMask(int maskBits)
-{
-   int oldNetMask = m_ipAddress.getMaskBits();
-   lockProperties();
-   m_ipAddress.setMaskBits(maskBits);
-   setModified();
-   unlockProperties();
-   PostEvent(EVENT_IF_MASK_CHANGED, m_id, "dsAddd", m_id,
-                m_name, &m_ipAddress, m_ipAddress.getMaskBits(), m_index, oldNetMask);
-}
-
-/**
  * Update zone ID. New zone ID taken from parent node.
  */
 void Interface::updateZoneId()
@@ -997,9 +1091,9 @@ void Interface::setPeer(Node *node, Interface *iface, LinkLayerProtocol protocol
          _T("remoteIfId"), _T("remoteIfIndex"), _T("remoteIfName"), _T("remoteIfIP"),
          _T("remoteIfMAC"), _T("protocol") };
       PostEventWithNames(EVENT_IF_PEER_CHANGED, getParentNodeId(), "ddsAhdsddsAhd", names,
-         m_id, m_index, m_name, &m_ipAddress, m_macAddr, node->getId(), node->getName(),
-         iface->getId(), iface->getIfIndex(), iface->getName(), &iface->getIpAddress(), iface->getMacAddr(),
-         protocol);
+         m_id, m_index, m_name, &m_ipAddressList.getFirstUnicastAddress(), m_macAddr, 
+         node->getId(), node->getName(), iface->getId(), iface->getIfIndex(), iface->getName(), 
+         &iface->getIpAddressList()->getFirstUnicastAddress(), iface->getMacAddr(), protocol);
    }
 }
 
@@ -1015,3 +1109,61 @@ void Interface::setMacAddr(const BYTE *pbNewMac)
    setModified();
    unlockProperties();
 }
+
+/** 
+ * Set IP address (should be used only for fake interfaces with single IP)
+ */
+void Interface::setIpAddress(const InetAddress& addr)
+{
+   lockProperties();
+   if (m_ipAddressList.size() == 1)
+   {
+      UpdateInterfaceIndex(m_ipAddressList.get(0), addr, this);
+      m_ipAddressList.clear();
+      m_ipAddressList.add(addr);
+      setModified();
+   }
+   unlockProperties();
+}
+
+/**
+ * Get first usable IP address
+ */
+const InetAddress& Interface::getFirstIpAddress()
+{
+   const InetAddress& a = m_ipAddressList.getFirstUnicastAddress();
+   return a.isValid() ? a : m_ipAddressList.get(0);
+}
+
+/**
+ * Add IP address
+ */
+void Interface::addIpAddress(const InetAddress& addr)
+{
+   lockProperties();
+   m_ipAddressList.add(addr);
+   setModified();
+   unlockProperties();
+}
+
+/**
+ * Delete IP address
+ */
+void Interface::deleteIpAddress(InetAddress addr)
+{
+   lockProperties();
+   m_ipAddressList.remove(addr);
+   setModified();
+   unlockProperties();
+}
+
+/**
+ * Change network mask for IP address
+ */
+void Interface::setNetMask(const InetAddress& addr)
+{
+   lockProperties();
+   m_ipAddressList.replace(addr);
+   setModified();
+   unlockProperties();
+}
index 23e7ca9..8ba08a8 100644 (file)
@@ -61,12 +61,12 @@ static LOCK_INFO m_locks[NUMBER_OF_LOCKS] =
  * Lock entire database and clear all other locks
  * Will return FALSE if someone already locked database
  */
-BOOL InitLocks(UINT32 *pdwIpAddr, TCHAR *pszInfo)
+BOOL InitLocks(InetAddress *ipAddr, TCHAR *pszInfo)
 {
    BOOL bSuccess = FALSE;
    TCHAR szBuffer[256];
 
-   *pdwIpAddr = UNLOCKED;
+   *ipAddr = InetAddress();
    pszInfo[0] = 0;
 
    // Check current database lock status
@@ -74,7 +74,7 @@ BOOL InitLocks(UINT32 *pdwIpAddr, TCHAR *pszInfo)
        DbgPrintf(6, _T("DBLockStatus=\"%s\""), szBuffer);
    if (!_tcscmp(szBuffer, _T("UNLOCKED")))
    {
-      IpToStr(GetLocalIpAddr(), szBuffer);
+      GetLocalIpAddr().toString(szBuffer);
       ConfigWriteStr(_T("DBLockStatus"), szBuffer, FALSE);
       GetSysInfoStr(szBuffer, sizeof(szBuffer));
       ConfigWriteStr(_T("DBLockInfo"), szBuffer, TRUE);
@@ -86,7 +86,7 @@ BOOL InitLocks(UINT32 *pdwIpAddr, TCHAR *pszInfo)
    {
       if (_tcscmp(szBuffer, _T("ERROR")))
       {
-         *pdwIpAddr = ntohl(_t_inet_addr(szBuffer));
+         *ipAddr = InetAddress::parse(szBuffer);
          ConfigReadStr(_T("DBLockInfo"), pszInfo, 256, _T("<error>"));
       }
    }
index dedeb16..9a89b2b 100644 (file)
@@ -559,7 +559,6 @@ static void LogConsoleWriter(const TCHAR *format, ...)
 BOOL NXCORE_EXPORTABLE Initialize()
 {
        int i, iDBVersion;
-       UINT32 dwAddr;
        TCHAR szInfo[256];
 
        g_serverStartTime = time(NULL);
@@ -730,16 +729,17 @@ BOOL NXCORE_EXPORTABLE Initialize()
 
        // Initialize locks
 retry_db_lock:
-       if (!InitLocks(&dwAddr, szInfo))
+   InetAddress addr;
+       if (!InitLocks(&addr, szInfo))
        {
-               if (dwAddr == UNLOCKED)    // Some SQL problems
+      if (!addr.isValid())    // Some SQL problems
                {
                        nxlog_write(MSG_INIT_LOCKS_FAILED, EVENTLOG_ERROR_TYPE, NULL);
                }
                else     // Database already locked by another server instance
                {
                        // Check for lock from crashed/terminated local process
-                       if (dwAddr == GetLocalIpAddr())
+                       if (GetLocalIpAddr().equals(addr))
                        {
                                UINT32 dwPID;
 
@@ -751,7 +751,7 @@ retry_db_lock:
                                        goto retry_db_lock;
                                }
                        }
-                       nxlog_write(MSG_DB_LOCKED, EVENTLOG_ERROR_TYPE, "as", dwAddr, szInfo);
+                       nxlog_write(MSG_DB_LOCKED, EVENTLOG_ERROR_TYPE, "As", &addr, szInfo);
                }
                return FALSE;
        }
@@ -1085,10 +1085,10 @@ static bool IsCommand(const TCHAR *cmdTemplate, TCHAR *pszString, int iMinChars)
 /**
  * Dump index callback (by IP address)
  */
-static void DumpIndexCallbackByInetAddr(NetObj *object, void *data)
+static void DumpIndexCallbackByInetAddr(const InetAddress& addr, NetObj *object, void *data)
 {
        TCHAR buffer[64];
-       ConsolePrintf((CONSOLE_CTX)data, _T("%-40s %p %s [%d]\n"), object->getIpAddress().toString(buffer), object, object->getName(), (int)object->getId());
+       ConsolePrintf((CONSOLE_CTX)data, _T("%-40s %p %s [%d]\n"), addr.toString(buffer), object, object->getName(), (int)object->getId());
 }
 
 /**
index ca24594..12213ad 100644 (file)
@@ -240,7 +240,6 @@ static ARP_CACHE *SysGetLocalArpCache()
 static InterfaceList *SysGetLocalIfList()
 {
    InterfaceList *pIfList = NULL;
-       NX_INTERFACE_INFO iface;
 
 #ifdef _WIN32
    DWORD dwSize;
@@ -306,14 +305,20 @@ static InterfaceList *SysGetLocalIfList()
          // Compose result for each ip address
          for(pAddr = &pInfo->IpAddressList; pAddr != NULL; pAddr = pAddr->Next)
          {
-                               memset(&iface, 0, sizeof(NX_INTERFACE_INFO));
-            nx_strncpy(iface.name, szAdapterName, MAX_OBJECT_NAME);
-            memcpy(iface.macAddr, pInfo->Address, MAC_ADDR_LENGTH);
-            iface.index = pInfo->Index;
-            iface.ipAddr = ntohl(inet_addr(pAddr->IpAddress.String));
-            iface.ipNetMask = ntohl(inet_addr(pAddr->IpMask.String));
-            iface.type = pInfo->Type;
-                               pIfList->add(&iface);
+            InterfaceInfo *iface = pIfList->findByIfIndex(pInfo->Index);
+            if (iface != NULL)
+            {
+               iface->ipAddrList.add(InetAddress(ntohl(inet_addr(pAddr->IpAddress.String)), ntohl(inet_addr(pAddr->IpMask.String))));
+            }
+            else
+            {
+               iface = new InterfaceInfo(pInfo->Index);
+               nx_strncpy(iface->name, szAdapterName, MAX_OBJECT_NAME);
+               memcpy(iface->macAddr, pInfo->Address, MAC_ADDR_LENGTH);
+               iface->ipAddrList.add(InetAddress(ntohl(inet_addr(pAddr->IpAddress.String)), ntohl(inet_addr(pAddr->IpMask.String))));
+               iface->type = pInfo->Type;
+                                  pIfList->add(iface);
+            }
          }
       }
    }
@@ -332,19 +337,27 @@ static InterfaceList *SysGetLocalIfList()
          pIfList = new InterfaceList(list.size());
          for(i = 0; i < list.size(); i++)
          {
-                               memset(&iface, 0, sizeof(NX_INTERFACE_INFO));
             TCHAR *pTemp = _tcsdup(list.get(i));
             TCHAR *pBuf = pTemp;
 
             // Index
+            UINT32 ifIndex = 0;
             pChar = _tcschr(pBuf, ' ');
             if (pChar != NULL)
             {
                *pChar = 0;
-               iface.index = _tcstoul(pBuf, NULL, 10);
+               ifIndex = _tcstoul(pBuf, NULL, 10);
                pBuf = pChar + 1;
             }
 
+            bool newInterface = false;
+            InterfaceInfo *iface = pIfList->findByIndex(ifIndex);
+            if (iface == NULL)
+            {
+               iface = new InterfaceInfo(ifIndex);
+               newInterface = true;
+            }
+
             // Address and mask
             pChar = _tcschr(pBuf, _T(' '));
             if (pChar != NULL)
@@ -363,35 +376,38 @@ static InterfaceList *SysGetLocalIfList()
                {
                   pSlash = defaultMask;
                }
-               iface.ipAddr = ntohl(_t_inet_addr(pBuf));
-               dwBits = _tcstoul(pSlash, NULL, 10);
-               iface.ipNetMask = (dwBits == 32) ? 0xFFFFFFFF : (~(0xFFFFFFFF >> dwBits));
+               InetAddress addr = InetAddress::parse(pBuf);
+               addr.setMaskBits(_tcstol(pSlash, NULL, 10));
+               iface->ipAddrList.add(new InetAddress(addr));
                pBuf = pChar + 1;
             }
 
-            // Interface type
-            pChar = _tcschr(pBuf, ' ');
-            if (pChar != NULL)
+            if (newInterface)
             {
-               *pChar = 0;
-               iface.type = _tcstoul(pBuf, NULL, 10);
-               pBuf = pChar + 1;
-            }
+               // Interface type
+               pChar = _tcschr(pBuf, ' ');
+               if (pChar != NULL)
+               {
+                  *pChar = 0;
+                  iface.type = _tcstoul(pBuf, NULL, 10);
+                  pBuf = pChar + 1;
+               }
 
-            // MAC address
-            pChar = _tcschr(pBuf, ' ');
-            if (pChar != NULL)
-            {
-               *pChar = 0;
-               StrToBin(pBuf, iface.macAddr, MAC_ADDR_LENGTH);
-               pBuf = pChar + 1;
-            }
+               // MAC address
+               pChar = _tcschr(pBuf, ' ');
+               if (pChar != NULL)
+               {
+                  *pChar = 0;
+                  StrToBin(pBuf, iface.macAddr, MAC_ADDR_LENGTH);
+                  pBuf = pChar + 1;
+               }
 
-            // Name
-            nx_strncpy(iface.name, pBuf, MAX_OBJECT_NAME - 1);
+               // Name
+               nx_strncpy(iface.name, pBuf, MAX_OBJECT_NAME - 1);
 
+                               pIfList->add(iface);
+            }
             free(pTemp);
-                               pIfList->add(&iface);
          }
       }
    }
index d5b907f..967e906 100644 (file)
@@ -919,7 +919,6 @@ void NetObj::fillMessage(NXCPMessage *pMsg)
        pMsg->setField(VID_GUID, m_guid, UUID_LENGTH);
    pMsg->setField(VID_OBJECT_NAME, m_name);
    pMsg->setField(VID_OBJECT_STATUS, (WORD)m_iStatus);
-   pMsg->setField(VID_IP_ADDRESS, m_ipAddress);
    pMsg->setField(VID_IS_DELETED, (WORD)(m_isDeleted ? 1 : 0));
    pMsg->setField(VID_IS_SYSTEM, (WORD)(m_isSystem ? 1 : 0));
 
index 2dc20b3..9519c8b 100644 (file)
@@ -622,13 +622,23 @@ void Node::addVrrpInterfaces(InterfaceList *ifList)
                                continue;       // Do not add interfaces if router is not in master state
 
                        // Get netmask for this VR
-                       UINT32 netmask = 0;
+                       int maskBits = 0;
                        for(j = 0; j < ifList->size(); j++)
-                               if (ifList->get(j)->index == router->getIfIndex())
+         {
+            InterfaceInfo *iface = ifList->get(j);
+                               if (iface->index == router->getIfIndex())
                                {
-                                       netmask = ifList->get(j)->ipNetMask;
+               for(int k = 0; k < iface->ipAddrList.size(); k++)
+               {
+                  const InetAddress& addr = iface->ipAddrList.get(k);
+                  if (addr.getSubnetAddress().contain(router->getVip(0)))
+                  {
+                     maskBits = addr.getMaskBits();
+                  }
+               }
                                        break;
                                }
+         }
 
                        // Walk through all VR virtual IPs
                        for(j = 0; j < router->getVipCount(); j++)
@@ -638,18 +648,18 @@ void Node::addVrrpInterfaces(InterfaceList *ifList)
                                if (vip != 0)
                                {
                                        for(k = 0; k < ifList->size(); k++)
-                                               if (ifList->get(k)->ipAddr == vip)
+                  if (ifList->get(k)->hasAddress(vip))
                                                        break;
                                        if (k == ifList->size())
                                        {
-                                               NX_INTERFACE_INFO iface;
-                                               memset(&iface, 0, sizeof(NX_INTERFACE_INFO));
-                                               _sntprintf(iface.name, MAX_DB_STRING, _T("vrrp.%u.%u.%d"), router->getId(), router->getIfIndex(), j);
-                                               memcpy(iface.macAddr, router->getVirtualMacAddr(), MAC_ADDR_LENGTH);
-                                               iface.ipAddr = vip;
-                                               iface.ipNetMask = netmask;
-                                               ifList->add(&iface);
-                                               DbgPrintf(6, _T("Node::addVrrpInterfaces(node=%s [%d]): added interface %s"), m_name, (int)m_id, iface.name);
+                                               InterfaceInfo *iface = new InterfaceInfo(0);
+                                               _sntprintf(iface->name, MAX_DB_STRING, _T("vrrp.%u.%u.%d"), router->getId(), router->getIfIndex(), j);
+                                               memcpy(iface->macAddr, router->getVirtualMacAddr(), MAC_ADDR_LENGTH);
+                  InetAddress addr(vip);
+                  addr.setMaskBits(maskBits);
+                  iface->ipAddrList.add(addr);
+                                               ifList->add(iface);
+                                               DbgPrintf(6, _T("Node::addVrrpInterfaces(node=%s [%d]): added interface %s"), m_name, (int)m_id, iface->name);
                                        }
                                }
                        }
@@ -772,7 +782,7 @@ Interface *Node::findInterfaceByIP(const InetAddress& addr)
       if (m_pChildList[i]->getObjectClass() == OBJECT_INTERFACE)
       {
          pInterface = (Interface *)m_pChildList[i];
-                       if (pInterface->getIpAddress().equals(addr))
+         if (pInterface->getIpAddressList()->hasAddress(addr))
          {
             UnlockChildList();
             return pInterface;
@@ -900,7 +910,7 @@ bool Node::isMyIP(const InetAddress& addr)
    for(i = 0; i < m_dwChildCount; i++)
       if (m_pChildList[i]->getObjectClass() == OBJECT_INTERFACE)
       {
-         if (((Interface *)m_pChildList[i])->getIpAddress().equals(addr))
+         if (((Interface *)m_pChildList[i])->getIpAddressList()->hasAddress(addr))
          {
             UnlockChildList();
             return true;
@@ -915,10 +925,8 @@ bool Node::isMyIP(const InetAddress& addr)
  */
 Interface *Node::createNewInterface(const InetAddress& ipAddr, BYTE *macAddr)
 {
-   NX_INTERFACE_INFO info;
-   memset(&info, 0, sizeof(info));
-   info.ipAddr = ipAddr.getAddressV4();
-   info.ipNetMask = 0xFFFFFFFF << (32 - ipAddr.getMaskBits());
+   InterfaceInfo info(1);
+   info.ipAddrList.add(ipAddr);
    if (macAddr != NULL)
       memcpy(info.macAddr, macAddr, MAC_ADDR_LENGTH);
    return createNewInterface(&info, false);
@@ -927,75 +935,74 @@ Interface *Node::createNewInterface(const InetAddress& ipAddr, BYTE *macAddr)
 /**
  * Create new interface
  */
-Interface *Node::createNewInterface(NX_INTERFACE_INFO *info, bool manuallyCreated)
+Interface *Node::createNewInterface(InterfaceInfo *info, bool manuallyCreated)
 {
-   Interface *pInterface;
-   Subnet *pSubnet = NULL;
-       Cluster *pCluster;
        bool bSyntheticMask = false;
+   TCHAR buffer[64];
 
-       DbgPrintf(5, _T("Node::createNewInterface(%08X/%08X, %s, %d, %d, bp=%d, slot=%d, port=%d) called for node %s [%d]"),
-//      (const TCHAR *)info->ipAddr.toString(), info->ipAddr.getMaskBits(), info->name, info->index, info->type, info->bridgePort, info->slot, info->port, m_name, m_id);
-      info->ipAddr, info->ipNetMask, info->name, info->index, info->type, info->bridgePort, info->slot, info->port, m_name, m_id);
+       DbgPrintf(5, _T("Node::createNewInterface(%s, %d, %d, bp=%d, slot=%d, port=%d) called for node %s [%d]"),
+      info->name, info->index, info->type, info->bridgePort, info->slot, info->port, m_name, m_id);
+   for(int i = 0; i < info->ipAddrList.size(); i++)
+   {
+      const InetAddress& addr = info->ipAddrList.get(i);
+      DbgPrintf(5, _T("Node::createNewInterface(%s): IP address %s/%d"), info->name, addr.toString(buffer), addr.getMaskBits());
+   }
 
    // Find subnet to place interface object to
-       if ((info->ipAddr != 0) && (info->type != IFTYPE_SOFTWARE_LOOPBACK) && ((info->ipAddr & 0xFF000000) != 0x7F000000))
+       if (info->type != IFTYPE_SOFTWARE_LOOPBACK)
    {
-               pCluster = getMyCluster();
-               bool addToSubnet = (pCluster != NULL) ? !pCluster->isSyncAddr(info->ipAddr) : true;
-               DbgPrintf(5, _T("Node::createNewInterface: node=%s [%d] cluster=%s [%d] add=%s"),
-                         m_name, m_id, (pCluster != NULL) ? pCluster->getName() : _T("(null)"),
-                (pCluster != NULL) ? pCluster->getId() : 0, addToSubnet ? _T("yes") : _T("no"));
-               if (addToSubnet)
-               {
-                       pSubnet = FindSubnetForNode(m_zoneId, info->ipAddr);
-                       if (pSubnet == NULL)
-                       {
-                               // Check if netmask is 0 (detect), and if yes, create
-                               // new subnet with class mask
-                               if (info->ipNetMask == 0)
-                               {
-                                       bSyntheticMask = true;
-                                       if (info->ipAddr < 0xE0000000)
-                                       {
-                                               info->ipNetMask = 0xFFFFFF00;   // Class A, B or C
-                                       }
-                                       else
-                                       {
-                                               TCHAR szBuffer[16];
-
-                                               // Multicast address??
-                                               DbgPrintf(2, _T("Attempt to create interface object with multicast address %s"),
-                                                                        IpToStr(info->ipAddr, szBuffer));
-                                       }
-                               }
+               Cluster *pCluster = getMyCluster();
+      for(int i = 0; i < info->ipAddrList.size(); i++)
+      {
+         InetAddress addr = info->ipAddrList.get(i);
+         bool addToSubnet = addr.isValidUnicast() && ((pCluster == NULL) || !pCluster->isSyncAddr(addr));
+                  DbgPrintf(5, _T("Node::createNewInterface: node=%s [%d] ip=%s/%d cluster=%s [%d] add=%s"),
+                            m_name, m_id, addr.toString(buffer), addr.getMaskBits(), 
+                   (pCluster != NULL) ? pCluster->getName() : _T("(null)"),
+                   (pCluster != NULL) ? pCluster->getId() : 0, addToSubnet ? _T("yes") : _T("no"));
+                  if (addToSubnet)
+                  {
+                          Subnet *pSubnet = FindSubnetForNode(m_zoneId, addr);
+                          if (pSubnet == NULL)
+                          {
+                                  // Check if netmask is 0 (detect), and if yes, create
+                                  // new subnet with class mask
+               if (addr.getMaskBits() == 0)
+                                  {
+                                          bSyntheticMask = true;
+                  addr.setMaskBits((addr.getFamily() == AF_INET) ? 24 : 64);
+                                  }
 
-                               // Create new subnet object
-                               // Ignore mask 255.255.255.255 - some point-to-point interfaces can have such mask
-                               // Ignore mask 255.255.255.254 - it's invalid
-                               if ((info->ipAddr < 0xE0000000) && (info->ipNetMask != 0xFFFFFFFF) && (info->ipNetMask != 0xFFFFFFFE))
-                               {
-                                       pSubnet = createSubnet(InetAddress(info->ipAddr, info->ipNetMask), bSyntheticMask);
-                               }
-                       }
-                       else
-                       {
-                               // Set correct netmask if we was asked for it
-                               if (info->ipNetMask == 0)
-                               {
-                                       info->ipNetMask = 0xFFFFFFFF << (32 - pSubnet->getIpAddress().getMaskBits());
-                                       bSyntheticMask = pSubnet->isSyntheticMask();
-                               }
-                       }
-               }
+                                  // Create new subnet object
+               if (addr.getHostBits() >= 2)
+                                  {
+                                          pSubnet = createSubnet(addr, bSyntheticMask);
+                                  }
+                          }
+                          else
+                          {
+                                  // Set correct netmask if we was asked for it
+               if (addr.getMaskBits() == 0)
+                                  {
+                  addr.setMaskBits(pSubnet->getIpAddress().getMaskBits());
+                                          bSyntheticMask = pSubnet->isSyntheticMask();
+                                  }
+                          }
+            if (pSubnet != NULL)
+            {
+               pSubnet->addNode(this);
+            }
+         }  // addToSubnet
+               } // loop by address list
    }
 
    // Create interface object
+   Interface *pInterface;
    if (info->name[0] != 0)
-               pInterface = new Interface(info->name, (info->description[0] != 0) ? info->description : info->name,
-                                 info->index, InetAddress(info->ipAddr, info->ipNetMask), info->type, m_zoneId);
+               pInterface = new Interface(info->name, (info->description[0] != 0) ? info->description : info->name, 
+                                 info->index, info->ipAddrList, info->type, m_zoneId);
    else
-      pInterface = new Interface(InetAddress(info->ipAddr, info->ipNetMask), m_zoneId, bSyntheticMask);
+      pInterface = new Interface(info->ipAddrList, m_zoneId, bSyntheticMask);
    pInterface->setMacAddr(info->macAddr);
        pInterface->setBridgePortNumber(info->bridgePort);
        pInterface->setSlotNumber(info->slot);
@@ -1010,22 +1017,10 @@ Interface *Node::createNewInterface(NX_INTERFACE_INFO *info, bool manuallyCreate
    if (!m_isHidden)
       pInterface->unhide();
    if (!pInterface->isSystem())
-      PostEvent(EVENT_INTERFACE_ADDED, m_id, "dsAdd", pInterface->getId(),
-                pInterface->getName(), &pInterface->getIpAddress(),
-                pInterface->getIpAddress().getMaskBits(), pInterface->getIfIndex());
-
-   // Bind node to appropriate subnet
-   if (pSubnet != NULL)
    {
-      pSubnet->addNode(this);
-
-      // Check if subnet mask is correct on interface
-      if ((pSubnet->getIpAddress().getMaskBits() != pInterface->getIpAddress().getMaskBits()) && !pSubnet->isSyntheticMask() && (info->ipNetMask != 0xFFFFFFFF))
-               {
-         PostEvent(EVENT_INCORRECT_NETMASK, m_id, "idsdd", pInterface->getId(),
-                   pInterface->getIfIndex(), pInterface->getName(),
-                   pInterface->getIpAddress().getMaskBits(), pSubnet->getIpAddress().getMaskBits());
-               }
+      const InetAddress& addr = pInterface->getFirstIpAddress();
+      PostEvent(EVENT_INTERFACE_ADDED, m_id, "dsAdd", pInterface->getId(),
+                pInterface->getName(), &addr, addr.getMaskBits(), pInterface->getIfIndex());
    }
 
        return pInterface;
@@ -1034,44 +1029,46 @@ Interface *Node::createNewInterface(NX_INTERFACE_INFO *info, bool manuallyCreate
 /**
  * Delete interface from node
  */
-void Node::deleteInterface(Interface *pInterface)
+void Node::deleteInterface(Interface *iface)
 {
-   UINT32 i;
-
-       DbgPrintf(5, _T("Node::deleteInterface(node=%s [%d], interface=%s [%d])"), m_name, m_id, pInterface->getName(), pInterface->getId());
+       DbgPrintf(5, _T("Node::deleteInterface(node=%s [%d], interface=%s [%d])"), m_name, m_id, iface->getName(), iface->getId());
 
    // Check if we should unlink node from interface's subnet
-   if (pInterface->getIpAddress().isValidUnicast() && !pInterface->isExcludedFromTopology())
+   if (!iface->isExcludedFromTopology())
    {
-      BOOL bUnlink = TRUE;
+      const ObjectArray<InetAddress> *list = iface->getIpAddressList()->getList();
+      for(int i = 0; i < list->size(); i++)
+      {
+         bool doUnlink = true;
+         const InetAddress *addr = list->get(i);
 
-      LockChildList(FALSE);
-      for(i = 0; i < m_dwChildCount; i++)
-         if (m_pChildList[i]->getObjectClass() == OBJECT_INTERFACE)
-            if (m_pChildList[i] != pInterface)
-               if (((Interface *)m_pChildList[i])->getIpAddress().getSubnetAddress().equals(pInterface->getIpAddress().getSubnetAddress()))
-               {
-                  bUnlink = FALSE;
-                  break;
-               }
-      UnlockChildList();
+         LockChildList(FALSE);
+         for(UINT32 j = 0; j < m_dwChildCount; i++)
+            if ((m_pChildList[i]->getObjectClass() == OBJECT_INTERFACE) && (m_pChildList[i] != iface) &&
+                ((Interface *)m_pChildList[i])->getIpAddressList()->findSameSubnetAddress(*addr).isValid())
+            {
+               doUnlink = false;
+               break;
+            }
+         UnlockChildList();
 
-      if (bUnlink)
-      {
-         // Last interface in subnet, should unlink node
-         Subnet *pSubnet = FindSubnetByIP(m_zoneId, pInterface->getIpAddress().getSubnetAddress());
-         if (pSubnet != NULL)
+         if (doUnlink)
          {
-            DeleteParent(pSubnet);
-            pSubnet->DeleteChild(this);
+            // Last interface in subnet, should unlink node
+            Subnet *pSubnet = FindSubnetByIP(m_zoneId, addr->getSubnetAddress());
+            if (pSubnet != NULL)
+            {
+               DeleteParent(pSubnet);
+               pSubnet->DeleteChild(this);
+            }
+                          DbgPrintf(5, _T("Node::deleteInterface(node=%s [%d], interface=%s [%d]): unlinked from subnet %s [%d]"),
+                                    m_name, m_id, iface->getName(), iface->getId(),
+                                                   (pSubnet != NULL) ? pSubnet->getName() : _T("(null)"),
+                                                   (pSubnet != NULL) ? pSubnet->getId() : 0);
          }
-                       DbgPrintf(5, _T("Node::deleteInterface(node=%s [%d], interface=%s [%d]): unlinked from subnet %s [%d]"),
-                                 m_name, m_id, pInterface->getName(), pInterface->getId(),
-                                                (pSubnet != NULL) ? pSubnet->getName() : _T("(null)"),
-                                                (pSubnet != NULL) ? pSubnet->getId() : 0);
       }
    }
-       pInterface->deleteObject();
+       iface->deleteObject();
 }
 
 /**
@@ -1291,9 +1288,7 @@ restart_agent_check:
       {
          case OBJECT_INTERFACE:
                           DbgPrintf(7, _T("StatusPoll(%s): polling interface %d [%s]"), m_name, ppPollList[i]->getId(), ppPollList[i]->getName());
-            ((Interface *)ppPollList[i])->statusPoll(pSession, dwRqId, pQueue,
-                                       (pCluster != NULL) ? pCluster->isSyncAddr(((Interface *)ppPollList[i])->getIpAddress()) : FALSE,
-                                       pTransport, m_icmpProxy);
+            ((Interface *)ppPollList[i])->statusPoll(pSession, dwRqId, pQueue, pCluster, pTransport, m_icmpProxy);
             break;
          case OBJECT_NETWORKSERVICE:
                           DbgPrintf(7, _T("StatusPoll(%s): polling network service %d [%s]"), m_name, ppPollList[i]->getId(), ppPollList[i]->getName());
@@ -2454,7 +2449,7 @@ bool Node::confPollSnmp(UINT32 dwRqId)
                   newAp = true;
                                        }
                                        ap->attachToNode(m_id);
-               ap->setIpAddr(info->getIpAddr());
+               ap->setIpAddress(info->getIpAddr());
                                        if ((info->getState() == AP_ADOPTED) || newAp)
                {
                                           ap->updateRadioInterfaces(info->getRadioInterfaces());
@@ -2580,18 +2575,6 @@ BOOL Node::updateInterfaceConfiguration(UINT32 dwRqId, int maskBits)
    if (pIfList != NULL)
    {
                DbgPrintf(6, _T("Node::updateInterfaceConfiguration(%s [%u]): got %d interfaces"), m_name, m_id, pIfList->size());
-               // Remove cluster virtual interfaces from list
-               if (pCluster != NULL)
-               {
-                       for(i = 0; i < pIfList->size(); i++)
-                       {
-                               if (pCluster->isVirtualAddr(pIfList->get(i)->ipAddr))
-                               {
-                                       pIfList->remove(i);
-                                       i--;
-                               }
-                       }
-               }
 
       // Find non-existing interfaces
       LockChildList(FALSE);
@@ -2605,8 +2588,7 @@ BOOL Node::updateInterfaceConfiguration(UINT32 dwRqId, int maskBits)
                                {
                                        for(j = 0; j < pIfList->size(); j++)
                                        {
-                                               if ((pIfList->get(j)->index == pInterface->getIfIndex()) &&
-                                                        pInterface->getIpAddress().equals(pIfList->get(j)->ipAddr))
+                                               if (pIfList->get(j)->index == pInterface->getIfIndex())
                                                        break;
                                        }
 
@@ -2626,8 +2608,8 @@ BOOL Node::updateInterfaceConfiguration(UINT32 dwRqId, int maskBits)
          for(j = 0; j < iDelCount; j++)
          {
             sendPollerMsg(dwRqId, POLLER_WARNING _T("   Interface \"%s\" is no longer exist\r\n"), ppDeleteList[j]->getName());
-            PostEvent(EVENT_INTERFACE_DELETED, m_id, "dsAd", ppDeleteList[j]->getIfIndex(),
-                      ppDeleteList[j]->getName(), &ppDeleteList[j]->getIpAddress(), ppDeleteList[j]->getIpAddress().getMaskBits());
+            const InetAddress& addr = ppDeleteList[j]->getFirstIpAddress();
+            PostEvent(EVENT_INTERFACE_DELETED, m_id, "dsAd", ppDeleteList[j]->getIfIndex(), ppDeleteList[j]->getName(), &addr, addr.getMaskBits());
             deleteInterface(ppDeleteList[j]);
          }
          hasChanges = TRUE;
@@ -2637,7 +2619,7 @@ BOOL Node::updateInterfaceConfiguration(UINT32 dwRqId, int maskBits)
       // Add new interfaces and check configuration of existing
       for(j = 0; j < pIfList->size(); j++)
       {
-                       NX_INTERFACE_INFO *ifInfo = pIfList->get(j);
+                       InterfaceInfo *ifInfo = pIfList->get(j);
          BOOL bNewInterface = TRUE;
 
          LockChildList(FALSE);
@@ -2647,11 +2629,11 @@ BOOL Node::updateInterfaceConfiguration(UINT32 dwRqId, int maskBits)
             {
                Interface *pInterface = (Interface *)m_pChildList[i];
 
-               if ((ifInfo->index == pInterface->getIfIndex()) &&
-                   pInterface->getIpAddress().equals(ifInfo->ipAddr))
+               if (ifInfo->index == pInterface->getIfIndex())
                {
                   // Existing interface, check configuration
-                  if (memcmp(ifInfo->macAddr, "\x00\x00\x00\x00\x00\x00", MAC_ADDR_LENGTH) && memcmp(ifInfo->macAddr, pInterface->getMacAddr(), MAC_ADDR_LENGTH))
+                  if (memcmp(ifInfo->macAddr, "\x00\x00\x00\x00\x00\x00", MAC_ADDR_LENGTH) && 
+                      memcmp(ifInfo->macAddr, pInterface->getMacAddr(), MAC_ADDR_LENGTH))
                   {
                      TCHAR szOldMac[16], szNewMac[16];
 
@@ -2690,10 +2672,42 @@ BOOL Node::updateInterfaceConfiguration(UINT32 dwRqId, int maskBits)
                                                {
                                                        pInterface->setPhysicalPortFlag(ifInfo->isPhysicalPort);
                                                }
-                                               if ((ifInfo->ipNetMask != 0) && (ifInfo->ipNetMask != pInterface->getIpAddress().getMaskBits()))
-                                               {
-                                                       pInterface->setIpNetMask(BitsInMask(ifInfo->ipNetMask));
-                                               }
+
+                  // Check for deleted IPs and changed masks
+                  const InetAddressList *ifList = pInterface->getIpAddressList();
+                  for(int n = 0; n < ifList->size(); n++)
+                  {
+                     const InetAddress& ifAddr = ifList->get(n);
+                     const InetAddress& addr = ifInfo->ipAddrList.findAddress(ifAddr);
+                     if (addr.isValid())
+                     {
+                        if (addr.getMaskBits() != ifAddr.getMaskBits())
+                        {
+                           PostEvent(EVENT_IF_MASK_CHANGED, m_id, "dsAddd", pInterface->getId(), pInterface->getName(),
+                                     &addr, addr.getMaskBits(), pInterface->getIfIndex(), ifAddr.getMaskBits());
+                           pInterface->setNetMask(addr);
+                        }
+                     }
+                     else
+                     {
+                        PostEvent(EVENT_IF_IPADDR_DELETED, m_id, "dsAdd", pInterface->getId(), pInterface->getName(),
+                                  &ifAddr, ifAddr.getMaskBits(), pInterface->getIfIndex());
+                        pInterface->deleteIpAddress(ifAddr);
+                     }
+                  }
+
+                  // Check for added IPs
+                  for(int m = 0; m < ifInfo->ipAddrList.size(); m++)
+                  {
+                     const InetAddress& addr = ifInfo->ipAddrList.get(m);
+                     if (!ifList->hasAddress(addr))
+                     {
+                        pInterface->addIpAddress(addr);
+                        PostEvent(EVENT_IF_IPADDR_ADDED, m_id, "dsAdd", pInterface->getId(), pInterface->getName(),
+                                  &addr, addr.getMaskBits(), pInterface->getIfIndex());
+                     }
+                  }
+
                   bNewInterface = FALSE;
                   break;
                }
@@ -2733,8 +2747,9 @@ BOOL Node::updateInterfaceConfiguration(UINT32 dwRqId, int maskBits)
          {
             sendPollerMsg(dwRqId, POLLER_WARNING _T("   Interface \"%s\" is no longer exist\r\n"),
                           ppDeleteList[j]->getName());
+            const InetAddress& addr = ppDeleteList[j]->getIpAddressList()->getFirstUnicastAddress();
             PostEvent(EVENT_INTERFACE_DELETED, m_id, "dsAd", ppDeleteList[j]->getIfIndex(),
-                      ppDeleteList[j]->getName(), &ppDeleteList[j]->getIpAddress(), ppDeleteList[j]->getIpAddress().getMaskBits());
+                      ppDeleteList[j]->getName(), &addr, addr.getMaskBits());
             deleteInterface(ppDeleteList[j]);
          }
          safe_free(ppDeleteList);
@@ -2749,7 +2764,7 @@ BOOL Node::updateInterfaceConfiguration(UINT32 dwRqId, int maskBits)
          if (pInterface->isFake())
          {
             // Check if primary IP is different from interface's IP
-            if (!pInterface->getIpAddress().equals(m_ipAddress))
+            if (!pInterface->getIpAddressList()->hasAddress(m_ipAddress))
             {
                deleteInterface(pInterface);
                                        if (m_ipAddress.isValidUnicast())
@@ -2809,8 +2824,8 @@ BOOL Node::updateInterfaceConfiguration(UINT32 dwRqId, int maskBits)
                DbgPrintf(6, _T("Node::updateInterfaceConfiguration(%s [%u]): pflist == NULL, dwCount = %u"), m_name, m_id, dwCount);
    }
 
-   checkSubnetBinding(pIfList);
        delete pIfList;
+   checkSubnetBinding();
 
        sendPollerMsg(dwRqId, _T("Interface configuration check finished\r\n"));
        return hasChanges;
@@ -3797,6 +3812,59 @@ UINT32 Node::getInternalItem(const TCHAR *param, size_t bufSize, TCHAR *buffer)
          rc = DCE_NOT_SUPPORTED;
       }
    }
+   else if (MatchString(_T("PingTime(*)"), param, FALSE))
+   {
+      NetObj *object = objectFromParameter(param);
+      if ((object != NULL) && (object->getObjectClass() == OBJECT_INTERFACE))
+      {
+         UINT32 value = ((Interface *)object)->getPingTime();
+         if (value == 10000)
+            rc = DCE_COMM_ERROR;
+         else
+            _sntprintf(buffer, bufSize, _T("%d"), value);
+      }
+      else
+      {
+         rc = DCE_NOT_SUPPORTED;
+      }
+   }
+   else if (!_tcsicmp(_T("PingTime"), param))
+   {
+      if (m_ipAddress.isValid())
+      {
+         Interface *iface = NULL;
+
+         // Find interface for primary IP
+         LockChildList(FALSE);
+         for(int i = 0; i < (int)m_dwChildCount; i++)
+         {
+            if ((m_pChildList[i]->getObjectClass() == OBJECT_INTERFACE) && ((Interface *)m_pChildList[i])->getIpAddressList()->hasAddress(m_ipAddress))
+            {
+               iface = (Interface *)m_pChildList[i];
+               break;
+            }
+         }
+         UnlockChildList();
+
+         UINT32 value = 10000;
+         if (iface != NULL)
+         {
+            value = iface->getPingTime();
+         }
+         else
+         {
+            value = getPingTime();
+         }
+         if (value == 10000)
+            rc = DCE_COMM_ERROR;
+         else
+            _sntprintf(buffer, bufSize, _T("%d"), value);
+      }
+      else
+      {
+         rc = DCE_NOT_SUPPORTED;
+      }
+   }
    else if (!_tcsicmp(param, _T("WirelessController.AdoptedAPCount")))
    {
       if (m_dwFlags & NF_IS_WIFI_CONTROLLER)
@@ -3956,6 +4024,7 @@ UINT32 Node::getTableForClient(const TCHAR *name, Table **table)
 void Node::fillMessage(NXCPMessage *pMsg)
 {
    DataCollectionTarget::fillMessage(pMsg);
+   pMsg->setField(VID_IP_ADDRESS, m_ipAddress);
        pMsg->setField(VID_PRIMARY_NAME, m_primaryName);
    pMsg->setField(VID_FLAGS, m_dwFlags);
    pMsg->setField(VID_RUNTIME_FLAGS, m_dwDynamicFlags);
@@ -4060,7 +4129,7 @@ UINT32 Node::modifyFromMessage(NXCPMessage *pRequest, BOOL bAlreadyLocked)
       UINT32 i;
       for(i = 0; i < m_dwChildCount; i++)
          if ((m_pChildList[i]->getObjectClass() == OBJECT_INTERFACE) &&
-             m_pChildList[i]->getIpAddress().equals(ipAddr))
+             ((Interface *)m_pChildList[i])->getIpAddressList()->hasAddress(ipAddr))
             break;
       UnlockChildList();
       if (i == m_dwChildCount)
@@ -4192,33 +4261,26 @@ UINT32 Node::wakeUp()
    for(i = 0; i < m_dwChildCount; i++)
       if ((m_pChildList[i]->getObjectClass() == OBJECT_INTERFACE) &&
           (m_pChildList[i]->Status() != STATUS_UNMANAGED) &&
-          m_pChildList[i]->getIpAddress().isValidUnicast())
+          ((Interface *)m_pChildList[i])->getIpAddressList()->getFirstUnicastAddressV4().isValid())
       {
-         if(memcmp(((Interface *)m_pChildList[i])->getMacAddr(), "\x00\x00\x00\x00\x00\x00", 6))
-         {
-            dwResult = ((Interface *)m_pChildList[i])->wakeUp();
+         dwResult = ((Interface *)m_pChildList[i])->wakeUp();
+         if (dwResult == RCC_SUCCESS)
             break;
-         }
-         else
-         {
-            dwResult = RCC_NO_MAC_ADDRESS;
-         }
       }
 
-   //If no interface found try to find interface in unmanaged state
-   for(i = 0; i < m_dwChildCount; i++)
-      if ((m_pChildList[i]->getObjectClass() == OBJECT_INTERFACE) && m_pChildList[i]->getIpAddress().isValidUnicast())
-      {
-         if (memcmp(((Interface *)m_pChildList[i])->getMacAddr(), "\x00\x00\x00\x00\x00\x00", 6))
+   // If no interface found try to find interface in unmanaged state
+   if (dwResult != RCC_SUCCESS)
+   {
+      for(i = 0; i < m_dwChildCount; i++)
+         if ((m_pChildList[i]->getObjectClass() == OBJECT_INTERFACE) &&
+             (m_pChildList[i]->Status() == STATUS_UNMANAGED) &&
+             ((Interface *)m_pChildList[i])->getIpAddressList()->getFirstUnicastAddressV4().isValid())
          {
             dwResult = ((Interface *)m_pChildList[i])->wakeUp();
-            break;
+            if (dwResult == RCC_SUCCESS)
+               break;
          }
-         else
-         {
-            dwResult = RCC_NO_MAC_ADDRESS;
-         }
-      }
+   }
 
    UnlockChildList();
    return dwResult;
@@ -4537,7 +4599,7 @@ void Node::changeIPAddress(const InetAddress& ipAddr)
                        {
                                if (((Interface *)m_pChildList[i])->isFake())
                                {
-                                       ((Interface *)m_pChildList[i])->setIpAddr(ipAddr);
+                                       ((Interface *)m_pChildList[i])->setIpAddress(ipAddr);
                                }
                        }
                }
@@ -4670,7 +4732,14 @@ bool Node::getOutwardInterface(const InetAddress& destAddr, InetAddress *srcAddr
          {
             *srcIfIndex = m_pRoutingTable->pRoutes[i].dwIfIndex;
             Interface *iface = findInterfaceByIndex(m_pRoutingTable->pRoutes[i].dwIfIndex);
-            *srcAddr = ((iface != NULL) && iface->getIpAddress().isValidUnicast()) ? iface->getIpAddress() : m_ipAddress;  // use primary IP if outward interface does not have Ip address or cannot be found
+            if (iface != NULL)
+            {
+               *srcAddr = iface->getIpAddressList()->getFirstUnicastAddressV4();
+            }
+            else
+            {
+               *srcAddr = m_ipAddress;  // use primary IP if outward interface does not have IP address or cannot be found
+            }
             found = true;
             break;
          }
@@ -4711,24 +4780,22 @@ bool Node::getNextHop(const InetAddress& srcAddr, const InetAddress& destAddr, I
                                break;
                        }
                }
-               else if ((m_pChildList[i]->getObjectClass() == OBJECT_INTERFACE) && m_pChildList[i]->getIpAddress().isValid())
+               else if ((m_pChildList[i]->getObjectClass() == OBJECT_INTERFACE) &&
+               ((Interface *)m_pChildList[i])->getIpAddressList()->findSameSubnetAddress(destAddr).isValid())
                {
-                       if (m_pChildList[i]->getIpAddress().sameSubnet(destAddr))
+                       *nextHop = destAddr;
+                       *ifIndex = ((Interface *)m_pChildList[i])->getIfIndex();
+                       *isVpn = false;
+         nx_strncpy(name, m_pChildList[i]->getName(), MAX_OBJECT_NAME);
+                       if (m_pChildList[i]->Status() == SEVERITY_NORMAL)  /* TODO: use separate link status */
                        {
-                               *nextHop = destAddr;
-                               *ifIndex = ((Interface *)m_pChildList[i])->getIfIndex();
-                               *isVpn = false;
-            nx_strncpy(name, m_pChildList[i]->getName(), MAX_OBJECT_NAME);
-                               if (m_pChildList[i]->Status() == SEVERITY_NORMAL)  /* TODO: use separate link status */
-                               {
-                                       // found operational interface
-                                       nextHopFound = true;
-                                       break;
-                               }
-                               // non-operational interface found, continue search
-                               // but will use this interface if other suitable interfaces will not be found
-                               nonFunctionalInterfaceFound = true;
+                               // found operational interface
+                               nextHopFound = true;
+                               break;
                        }
+                       // non-operational interface found, continue search
+                       // but will use this interface if other suitable interfaces will not be found
+                       nonFunctionalInterfaceFound = true;
                }
        }
        UnlockChildList();
@@ -4745,7 +4812,8 @@ bool Node::getNextHop(const InetAddress& srcAddr, const InetAddress& destAddr, I
              ((destAddr.getAddressV4() & m_pRoutingTable->pRoutes[i].dwDestMask) == m_pRoutingTable->pRoutes[i].dwDestAddr))
          {
             Interface *iface = findInterfaceByIndex(m_pRoutingTable->pRoutes[i].dwIfIndex);
-            if ((m_pRoutingTable->pRoutes[i].dwNextHop == 0) && (iface != NULL) && (iface->getIpAddress().getHostBits() == 0))
+            if ((m_pRoutingTable->pRoutes[i].dwNextHop == 0) && (iface != NULL) && 
+                (iface->getIpAddressList()->getFirstUnicastAddressV4().getHostBits() == 0))
             {
                // On Linux XEN VMs can be pointed by individual host routes to virtual interfaces
                // where each vif has netmask 255.255.255.255 and next hop in routing table set to 0.0.0.0
@@ -5106,15 +5174,19 @@ BOOL Node::resolveName(BOOL useOnlyDNS)
                LockChildList(FALSE);
                for(UINT32 i = 0; i < m_dwChildCount; i++)
                {
-                       if ((m_pChildList[i]->getObjectClass() == OBJECT_INTERFACE) &&
-                           !((Interface *)m_pChildList[i])->isLoopback() && m_pChildList[i]->getIpAddress().isValidUnicast())
+                       if ((m_pChildList[i]->getObjectClass() == OBJECT_INTERFACE) && !((Interface *)m_pChildList[i])->isLoopback())
                        {
-            if (m_pChildList[i]->getIpAddress().getHostByAddr(name, MAX_OBJECT_NAME) != NULL)
+            const InetAddressList *list = ((Interface *)m_pChildList[i])->getIpAddressList();
+            for(int n = 0; n < list->size(); n++)
             {
-                                       nx_strncpy(m_name, name, MAX_OBJECT_NAME);
-                                       bSuccess = TRUE;
-                                       break;
-                               }
+               const InetAddress& a = list->get(i);
+               if (a.isValidUnicast() && (a.getHostByAddr(name, MAX_OBJECT_NAME) != NULL))
+               {
+                                          nx_strncpy(m_name, name, MAX_OBJECT_NAME);
+                                          bSuccess = TRUE;
+                                          break;
+                                  }
+            }
                        }
                }
                UnlockChildList();
@@ -5514,8 +5586,8 @@ void Node::topologyPoll(ClientSession *pSession, UINT32 dwRqId, int nPoller)
                if ((node != NULL) && (ws->ipAddr == 0))
                {
                   Interface *iface = node->findInterfaceByMAC(ws->macAddr);
-                  if ((iface != NULL) && iface->getIpAddress().isValidUnicast())
-                     ws->ipAddr = iface->getIpAddress().getAddressV4();
+                  if ((iface != NULL) && iface->getIpAddressList()->getFirstUnicastAddressV4().isValid())
+                     ws->ipAddr = iface->getIpAddressList()->getFirstUnicastAddressV4().getAddressV4();
                   else
                      ws->ipAddr = node->getIpAddress().getAddressV4();
                }
@@ -5699,106 +5771,114 @@ Subnet *Node::createSubnet(const InetAddress& baseAddr, bool syntheticMask)
 /**
  * Check subnet bindings
  */
-void Node::checkSubnetBinding(InterfaceList *pIfList)
+void Node::checkSubnetBinding()
 {
-       Cluster *pCluster = NULL;
-   bool hasIfaceForPrimaryIp = false;
+       Cluster *pCluster = getMyCluster();
 
-   if (pIfList != NULL)
+   // Build consolidated IP address list
+   InetAddressList addrList;
+   LockChildList(FALSE);
+   for(UINT32 n = 0; n < m_dwChildCount; n++)
    {
-          pCluster = getMyCluster();
-
-          // Check if we have subnet bindings for all interfaces
-          DbgPrintf(5, _T("Checking subnet bindings for node %s [%d]"), m_name, m_id);
-          for(int i = 0; i < pIfList->size(); i++)
-          {
-                  NX_INTERFACE_INFO *iface = pIfList->get(i);
-                  if (iface->ipAddr != 0)
-                  {
-                          Interface *pInterface = findInterfaceByIndex(iface->index);
-                          if ((pInterface == NULL) || !pInterface->getIpAddress().equals(iface->ipAddr))
-                          {
-                                  nxlog_write(MSG_INTERNAL_ERROR, EVENTLOG_WARNING_TYPE, "s", _T("Cannot find interface object in Node::checkSubnetBinding()"));
-                                  break;       // Something goes really wrong
-                          }
+      if (m_pChildList[n]->getObjectClass() != OBJECT_INTERFACE)
+         continue;
+      Interface *iface = (Interface *)m_pChildList[n];
+      if (iface->isLoopback() || iface->isExcludedFromTopology())
+         continue;
+      for(int m = 0; m < iface->getIpAddressList()->size(); m++)
+      {
+         const InetAddress& a = iface->getIpAddressList()->get(m);
+         if (a.isValidUnicast())
+            addrList.add(a);
+      }
+   }
+   UnlockChildList();
 
-                          if (pInterface->getIpAddress().equals(m_ipAddress))
-               hasIfaceForPrimaryIp = true;
+   // Check if we have subnet bindings for all interfaces
+   DbgPrintf(5, _T("Checking subnet bindings for node %s [%d]"), m_name, m_id);
+   for(int i = 0; i < addrList.size(); i++)
+   {
+      const InetAddress& addr = addrList.get(i);
 
-                          if (pInterface->isExcludedFromTopology())
-                                  continue;
+          Interface *iface = findInterfaceByIP(addr);
+      if (iface == NULL)
+          {
+                  nxlog_write(MSG_INTERNAL_ERROR, EVENTLOG_WARNING_TYPE, "s", _T("Cannot find interface object in Node::checkSubnetBinding()"));
+                  continue;    // Something goes really wrong
+          }
 
-                          // Is cluster interconnect interface?
-                          bool isSync = (pCluster != NULL) ? pCluster->isSyncAddr(pInterface->getIpAddress()) : false;
+          // Is cluster interconnect interface?
+          bool isSync = (pCluster != NULL) ? pCluster->isSyncAddr(addr) : false;
 
-                          Subnet *pSubnet = FindSubnetForNode(m_zoneId, iface->ipAddr);
-                          if (pSubnet != NULL)
-                          {
-                                  if (isSync)
-                                  {
-                                          pSubnet = NULL;      // No further checks on this subnet
-                                  }
-                                  else
-                                  {
-                  if (pSubnet->isSyntheticMask() && !pInterface->isSyntheticMask())
-                                          {
-                                                  DbgPrintf(4, _T("Setting correct netmask for subnet %s [%d] from node %s [%d]"),
-                                                                           pSubnet->getName(), pSubnet->getId(), m_name, m_id);
-                     if ((pInterface->getIpAddress().getHostBits() < 2) && (getParentCount() > 1))
-                     {
-                        /* Delete subnet object if we try to change it's netmask to 255.255.255.255 or 255.255.255.254 and
-                         node has more than one parent. hasIfaceForPrimaryIp paramteter should prevent us from going in
-                         loop(creating and deleting all the time subnet). */
-                        pSubnet->deleteObject();
-                        pSubnet = NULL;   // prevent binding to deleted subnet
-                     }
-                     else
-                     {
-                        pSubnet->setCorrectMask(pInterface->getIpAddress().getSubnetAddress());
-                     }
-                                          }
-
-                                          // Check if node is linked to this subnet
-                                          if ((pSubnet != NULL) && !pSubnet->isChild(m_id))
-                                          {
-                                                  DbgPrintf(4, _T("Restored link between subnet %s [%d] and node %s [%d]"),
-                                                                           pSubnet->getName(), pSubnet->getId(), m_name, m_id);
-                                                  pSubnet->addNode(this);
-                                          }
-                                  }
-                          }
-                          else if (!isSync)
+          Subnet *pSubnet = FindSubnetForNode(m_zoneId, addr);
+          if (pSubnet != NULL)
+          {
+                  if (isSync)
+                  {
+                          pSubnet = NULL;      // No further checks on this subnet
+                  }
+                  else
+                  {
+            if (pSubnet->isSyntheticMask() && !iface->isSyntheticMask())
                           {
-               DbgPrintf(6, _T("Missing subnet for interface %s [%d]"), iface->name, iface->index);
-
-                                  // Ignore mask 255.255.255.255 - some point-to-point interfaces can have such mask
-                                  // Ignore mask 255.255.255.254 - it's invalid
-                                  if ((iface->ipNetMask != 0xFFFFFFFF) && (iface->ipNetMask != 0xFFFFFFFE))
+                                  DbgPrintf(4, _T("Setting correct netmask for subnet %s [%d] from node %s [%d]"),
+                                                           pSubnet->getName(), pSubnet->getId(), m_name, m_id);
+               if ((addr.getHostBits() < 2) && (getParentCount() > 1))
                {
-                  pSubnet = createSubnet(InetAddress(iface->ipAddr, iface->ipNetMask), false);
-                                          pSubnet->addNode(this);
+                  /* Delete subnet object if we try to change it's netmask to 255.255.255.255 or 255.255.255.254 and
+                   node has more than one parent. hasIfaceForPrimaryIp paramteter should prevent us from going in
+                   loop(creating and deleting all the time subnet). */
+                  pSubnet->deleteObject();
+                  pSubnet = NULL;   // prevent binding to deleted subnet
                }
                else
                {
-                  DbgPrintf(6, _T("Subnet not required for interface %s [%d]"), iface->name, iface->index);
+                  pSubnet->setCorrectMask(addr.getSubnetAddress());
                }
                           }
 
-                          // Check if subnet mask is correct on interface
-                          if ((pSubnet != NULL) && (pSubnet->getIpAddress().getMaskBits() != pInterface->getIpAddress().getMaskBits()) && (iface->ipNetMask != 0xFFFFFFFF))
+                          // Check if node is linked to this subnet
+                          if ((pSubnet != NULL) && !pSubnet->isChild(m_id))
                           {
-                                  PostEvent(EVENT_INCORRECT_NETMASK, m_id, "idsdd", pInterface->getId(),
-                                                           pInterface->getIfIndex(), pInterface->getName(),
-                                                           pInterface->getIpAddress().getMaskBits(), pSubnet->getIpAddress().getMaskBits());
+                                  DbgPrintf(4, _T("Restored link between subnet %s [%d] and node %s [%d]"),
+                                                           pSubnet->getName(), pSubnet->getId(), m_name, m_id);
+                                  pSubnet->addNode(this);
                           }
                   }
           }
+          else if (!isSync)
+          {
+         DbgPrintf(6, _T("Missing subnet for address %s/%d on interface %s [%d]"), 
+            (const TCHAR *)addr.toString(), addr.getMaskBits(), iface->getName(), iface->getIfIndex());
+
+                  // Ignore mask 255.255.255.255 - some point-to-point interfaces can have such mask
+                  // Ignore mask 255.255.255.254 - it's invalid
+         if (addr.getHostBits() >= 2)
+         {
+            pSubnet = createSubnet(addr, false);
+                          pSubnet->addNode(this);
+         }
+         else
+         {
+            DbgPrintf(6, _T("Subnet not required for address %s/%d on interface %s [%d]"), 
+               (const TCHAR *)addr.toString(), addr.getMaskBits(), iface->getName(), iface->getIfIndex());
+         }
+          }
+
+          // Check if subnet mask is correct on interface
+      if ((pSubnet != NULL) && (pSubnet->getIpAddress().getMaskBits() != addr.getMaskBits()) && (addr.getHostBits() > 0))
+          {
+         Interface *iface = findInterfaceByIP(addr);
+                  PostEvent(EVENT_INCORRECT_NETMASK, m_id, "idsdd", iface->getId(),
+                                           iface->getIfIndex(), iface->getName(),
+                                           addr.getMaskBits(), pSubnet->getIpAddress().getMaskBits());
+          }
    }
 
    // Some devices may report interface list, but without IP
    // To prevent such nodes from hanging at top of the tree, attempt
    // to find subnet node primary IP
-   if (m_ipAddress.isValidUnicast() && !(m_dwFlags & NF_REMOTE_AGENT) && !hasIfaceForPrimaryIp)
+   if (m_ipAddress.isValidUnicast() && !(m_dwFlags & NF_REMOTE_AGENT) && !addrList.hasAddress(m_ipAddress))
    {
           Subnet *pSubnet = FindSubnetForNode(m_zoneId, m_ipAddress);
       if (pSubnet != NULL)
@@ -5831,28 +5911,20 @@ void Node::checkSubnetBinding(InterfaceList *pIfList)
                        if (pSubnet->getIpAddress().contain(m_ipAddress) && !(m_dwFlags & NF_REMOTE_AGENT))
             continue;   // primary IP is in given subnet
 
-         UINT32 j;
-                       for(j = 0; j < m_dwChildCount; j++)
+         int j;
+         for(j = 0; j < addrList.size(); j++)
                        {
-                               if (m_pChildList[j]->getObjectClass() == OBJECT_INTERFACE)
+            const InetAddress& addr = addrList.get(j);
+                               if (pSubnet->getIpAddress().contain(addr))
                                {
-                                       if (((Interface *)m_pChildList[j])->isExcludedFromTopology())
-                                               continue;
-
-                                       if (pSubnet->getIpAddress().contain(m_pChildList[j]->getIpAddress()))
-                                       {
-                                               if (pCluster != NULL)
-                                               {
-                                                       if (pCluster->isSyncAddr(m_pChildList[j]->getIpAddress()))
-                                                       {
-                                                               j = m_dwChildCount;     // Cause to unbind from this subnet
-                                                       }
-                                               }
-                                               break;
+                                       if ((pCluster != NULL) && pCluster->isSyncAddr(addr))
+               {
+                                               j = addrList.size();    // Cause to unbind from this subnet
                                        }
+                                       break;
                                }
                        }
-                       if (j == m_dwChildCount)
+                       if (j == addrList.size())
                        {
                                DbgPrintf(4, _T("Node::CheckSubnetBinding(): Subnet %s [%d] is incorrect for node %s [%d]"),
                                                         pSubnet->getName(), pSubnet->getId(), m_name, m_id);
@@ -5890,7 +5962,7 @@ void Node::updateInterfaceNames(ClientSession *pSession, UINT32 dwRqId)
       // Check names of existing interfaces
       for(int j = 0; j < pIfList->size(); j++)
       {
-         NX_INTERFACE_INFO *ifInfo = pIfList->get(j);
+         InterfaceInfo *ifInfo = pIfList->get(j);
 
          LockChildList(FALSE);
          for(UINT32 i = 0; i < m_dwChildCount; i++)
index cfddacf..1920858 100644 (file)
@@ -193,7 +193,7 @@ Node NXCORE_EXPORTABLE *PollNewNode(const InetAddress& ipAddr, UINT32 dwCreation
    if (dwCreationFlags & NXC_NCF_CREATE_UNMANAGED)
    {
       pNode->setMgmtStatus(FALSE);
-      pNode->checkSubnetBinding(NULL);
+      pNode->checkSubnetBinding();
    }
 
    // Add default DCIs
@@ -471,7 +471,7 @@ static BOOL AcceptNewNode(const InetAddress& addr, UINT32 zoneId, BYTE *macAddr)
                }
 
                Node *oldNode = iface->getParentNode();
-               if (iface->getIpAddress().equals(oldNode->getIpAddress()))
+      if (iface->getIpAddressList()->hasAddress(oldNode->getIpAddress()))
                {
                        // we should change node's primary IP only if old IP for this MAC was also node's primary IP
                        TCHAR szOldIpAddr[16];
index 983d4d5..4937dcf 100644 (file)
@@ -153,7 +153,7 @@ NXSL_Value *NXSL_NetObjClass::getAttr(NXSL_Object *pObject, const TCHAR *pszAttr
    else if (!_tcscmp(pszAttr, _T("ipAddr")))
    {
       TCHAR buffer[64];
-      object->getIpAddress().toString(buffer);
+      GetObjectIpAddress(object).toString(buffer);
       pValue = new NXSL_Value(buffer);
    }
    else if (!_tcscmp(pszAttr, _T("type")))
@@ -608,12 +608,12 @@ NXSL_Value *NXSL_InterfaceClass::getAttr(NXSL_Object *pObject, const TCHAR *pszA
    else if (!_tcscmp(pszAttr, _T("ipAddr")))
    {
       TCHAR buffer[64];
-      iface->getIpAddress().toString(buffer);
+      iface->getIpAddressList()->getFirstUnicastAddress().toString(buffer);
       pValue = new NXSL_Value(buffer);
    }
    else if (!_tcscmp(pszAttr, _T("ipNetMask")))
    {
-      pValue = new NXSL_Value(iface->getIpAddress().getMaskBits());
+      pValue = new NXSL_Value(iface->getIpAddressList()->getFirstUnicastAddress().getMaskBits());
    }
    else if (!_tcscmp(pszAttr, _T("isExcludedFromTopology")))
    {
index 1286e8e..afd8d22 100644 (file)
@@ -363,8 +363,8 @@ void NetObjInsert(NetObj *pObject, BOOL bNewObject)
                }
                else
                {
-                  if (pObject->getIpAddress().isValidUnicast())
-                                             g_idxNodeByAddr.put(pObject->getIpAddress(), pObject);
+                  if (((Node *)pObject)->getIpAddress().isValidUnicast())
+                                             g_idxNodeByAddr.put(((Node *)pObject)->getIpAddress(), pObject);
                }
             }
             break;
@@ -379,7 +379,7 @@ void NetObjInsert(NetObj *pObject, BOOL bNewObject)
             MacDbAddAccessPoint((AccessPoint *)pObject);
             break;
          case OBJECT_SUBNET:
-            if (pObject->getIpAddress().isValidUnicast())
+            if (((Subnet *)pObject)->getIpAddress().isValidUnicast())
             {
                                        if (IsZoningEnabled())
                                        {
@@ -396,14 +396,17 @@ void NetObjInsert(NetObj *pObject, BOOL bNewObject)
                                        }
                                        else
                                        {
-                                               g_idxSubnetByAddr.put(pObject->getIpAddress(), pObject);
+                                               g_idxSubnetByAddr.put(((Subnet *)pObject)->getIpAddress(), pObject);
                                        }
                if (bNewObject)
-                  PostEvent(EVENT_SUBNET_ADDED, g_dwMgmtNode, "isAd", pObject->getId(), pObject->getName(), &pObject->getIpAddress(), pObject->getIpAddress().getMaskBits());
+               {
+                  PostEvent(EVENT_SUBNET_ADDED, g_dwMgmtNode, "isAd", pObject->getId(), pObject->getName(), 
+                     &((Subnet *)pObject)->getIpAddress(), ((Subnet *)pObject)->getIpAddress().getMaskBits());
+               }
             }
             break;
          case OBJECT_INTERFACE:
-            if (pObject->getIpAddress().isValidUnicast() && !((Interface *)pObject)->isExcludedFromTopology())
+            if (!((Interface *)pObject)->isExcludedFromTopology())
             {
                                        if (IsZoningEnabled())
                                        {
@@ -420,9 +423,7 @@ void NetObjInsert(NetObj *pObject, BOOL bNewObject)
                                        }
                                        else
                                        {
-                                               if (g_idxInterfaceByAddr.put(pObject->getIpAddress(), pObject))
-                                                       DbgPrintf(1, _T("WARNING: duplicate interface IP address %s (interface object %s [%d])"),
-                                                                                (const TCHAR *)pObject->getIpAddress().toString(), pObject->getName(), (int)pObject->getId());
+                                               g_idxInterfaceByAddr.put(((Interface *)pObject)->getIpAddressList(), pObject);
                                        }
             }
             MacDbAddInterface((Interface *)pObject);
@@ -519,8 +520,8 @@ void NetObjDeleteFromIndexes(NetObj *pObject)
             }
             else
             {
-                             if (pObject->getIpAddress().isValidUnicast())
-                                     g_idxNodeByAddr.remove(pObject->getIpAddress());
+                             if (((Node *)pObject)->getIpAddress().isValidUnicast())
+                                     g_idxNodeByAddr.remove(((Node *)pObject)->getIpAddress());
             }
          }
          break;
@@ -535,7 +536,7 @@ void NetObjDeleteFromIndexes(NetObj *pObject)
          MacDbRemove(((AccessPoint *)pObject)->getMacAddr());
          break;
       case OBJECT_SUBNET:
-         if (pObject->getIpAddress().isValidUnicast())
+         if (((Subnet *)pObject)->getIpAddress().isValidUnicast())
          {
                                if (IsZoningEnabled())
                                {
@@ -552,35 +553,40 @@ void NetObjDeleteFromIndexes(NetObj *pObject)
                                }
                                else
                                {
-                                       g_idxSubnetByAddr.remove(pObject->getIpAddress());
+                                       g_idxSubnetByAddr.remove(((Subnet *)pObject)->getIpAddress());
                                }
          }
          break;
       case OBJECT_INTERFACE:
-         if (pObject->getIpAddress().isValidUnicast())
-         {
-                               if (IsZoningEnabled())
+                       if (IsZoningEnabled())
+                       {
+                               Zone *zone = (Zone *)g_idxZoneByGUID.get(((Interface *)pObject)->getZoneId());
+                               if (zone != NULL)
                                {
-                                       Zone *zone = (Zone *)g_idxZoneByGUID.get(((Interface *)pObject)->getZoneId());
-                                       if (zone != NULL)
-                                       {
-                                               zone->removeFromIndex((Interface *)pObject);
-                                       }
-                                       else
-                                       {
-                                               DbgPrintf(2, _T("Cannot find zone object with GUID=%d for interface object %s [%d]"),
-                                                         (int)((Interface *)pObject)->getZoneId(), pObject->getName(), (int)pObject->getId());
-                                       }
+                                       zone->removeFromIndex((Interface *)pObject);
                                }
                                else
                                {
-                                       NetObj *o = g_idxInterfaceByAddr.get(pObject->getIpAddress());
-                                       if ((o != NULL) && (o->getId() == pObject->getId()))
-                                       {
-                                               g_idxInterfaceByAddr.remove(pObject->getIpAddress());
-                                       }
+                                       DbgPrintf(2, _T("Cannot find zone object with GUID=%d for interface object %s [%d]"),
+                                                 (int)((Interface *)pObject)->getZoneId(), pObject->getName(), (int)pObject->getId());
                                }
-         }
+                       }
+                       else
+                       {
+            const ObjectArray<InetAddress> *list = ((Interface *)pObject)->getIpAddressList()->getList();
+            for(int i = 0; i < list->size(); i++)
+            {
+               InetAddress *addr = list->get(i);
+               if (addr->isValidUnicast())
+               {
+                                     NetObj *o = g_idxInterfaceByAddr.get(*addr);
+                                     if ((o != NULL) && (o->getId() == pObject->getId()))
+                                     {
+                                             g_idxInterfaceByAddr.remove(*addr);
+                                     }
+               }
+            }
+                       }
          MacDbRemove(((Interface *)pObject)->getMacAddr());
          break;
       case OBJECT_ZONE:
@@ -686,6 +692,20 @@ Node NXCORE_EXPORTABLE *FindNodeByIP(UINT32 zoneId, const InetAddress& ipAddr)
 }
 
 /**
+ * Find node by IP address using first match from IP address list
+ */
+Node NXCORE_EXPORTABLE *FindNodeByIP(UINT32 zoneId, const InetAddressList *ipAddrList)
+{
+   for(int i = 0; i < ipAddrList->size(); i++)
+   {
+      Node *node = FindNodeByIP(zoneId, ipAddrList->get(i));
+      if (node != NULL)
+         return node;
+   }
+   return NULL;
+}
+
+/**
  * Find interface by IP address
  */
 Interface NXCORE_EXPORTABLE *FindInterfaceByIP(UINT32 zoneId, const InetAddress& ipAddr)
@@ -818,7 +838,7 @@ struct SUBNET_MATCHING_DATA
 /**
  * Subnet matching callback
  */
-static void SubnetMatchCallback(NetObj *object, void *arg)
+static void SubnetMatchCallback(const InetAddress& addr, NetObj *object, void *arg)
 {
    SUBNET_MATCHING_DATA *data = (SUBNET_MATCHING_DATA *)arg;
    if (((Subnet *)object)->getIpAddress().contain(data->ipAddr))
@@ -1754,9 +1774,8 @@ static void DumpObjectCallback(NetObj *object, void *data)
    CONTAINER_CATEGORY *pCat;
 
        ConsolePrintf(pCtx, _T("Object ID %d \"%s\"\n")
-                       _T("   Class: %s  Primary IP: %s  Status: %s  IsModified: %d  IsDeleted: %d\n"),
+                       _T("   Class: %s  Status: %s  IsModified: %d  IsDeleted: %d\n"),
                                          object->getId(), object->getName(), (object->getObjectClass() < OBJECT_CUSTOM) ? g_szClassName[object->getObjectClass()] : _T("Custom"),
-                 object->getIpAddress().toString(dd->buffer),
                  GetStatusAsText(object->Status(), true),
                  object->isModified(), object->isDeleted());
    ConsolePrintf(pCtx, _T("   Parents: <%s>\n   Childs: <%s>\n"), 
@@ -1768,14 +1787,26 @@ static void DumpObjectCallback(NetObj *object, void *data)
    switch(object->getObjectClass())
    {
       case OBJECT_NODE:
-         ConsolePrintf(pCtx, _T("   IsSNMP: %d IsAgent: %d IsLocal: %d OID: %s\n"),
+         ConsolePrintf(pCtx, _T("   Primary IP: %s\n   IsSNMP: %d IsAgent: %d IsLocal: %d OID: %s\n"),
+                       ((Node *)object)->getIpAddress().toString(dd->buffer),
                        ((Node *)object)->isSNMPSupported(),
                        ((Node *)object)->isNativeAgent(),
                        ((Node *)object)->isLocalManagement(),
                        ((Node *)object)->getObjectId());
          break;
       case OBJECT_SUBNET:
-         ConsolePrintf(pCtx, _T("   Network mask: %d\n"), object->getIpAddress().getMaskBits());
+         ConsolePrintf(pCtx, _T("   IP address: %s/%d\n"), ((Subnet *)object)->getIpAddress().toString(dd->buffer), ((Subnet *)object)->getIpAddress().getMaskBits());
+         break;
+      case OBJECT_ACCESSPOINT:
+         ConsolePrintf(pCtx, _T("   IP address: %s\n"), ((AccessPoint *)object)->getIpAddress().toString(dd->buffer));
+         break;
+      case OBJECT_INTERFACE:
+         ConsolePrintf(pCtx, _T("   MAC address: %s\n"), MACToStr(((Interface *)object)->getMacAddr(), dd->buffer));
+         for(int n = 0; n < ((Interface *)object)->getIpAddressList()->size(); n++)
+         {
+            const InetAddress& a = ((Interface *)object)->getIpAddressList()->get(n);
+            ConsolePrintf(pCtx, _T("   IP address: %s/%d\n"), a.toString(dd->buffer), a.getMaskBits());
+         }
          break;
       case OBJECT_CONTAINER:
          pCat = FindContainerCategory(((Container *)object)->getCategory());
index 8ff6ce9..fc80be6 100644 (file)
@@ -55,14 +55,14 @@ static int m_iNumPollers = 0;
 /**
  * Create management node object
  */
-static void CreateManagementNode(UINT32 ipAddr, UINT32 netMask)
+static void CreateManagementNode(const InetAddress& addr)
 {
        TCHAR buffer[256];
 
-       Node *pNode = new Node(ipAddr, NF_IS_LOCAL_MGMT, 0, 0, 0);
+       Node *pNode = new Node(addr, NF_IS_LOCAL_MGMT, 0, 0, 0);
    NetObjInsert(pNode, TRUE);
        pNode->setName(GetLocalHostName(buffer, 256));
-   pNode->configurationPoll(NULL, 0, -1, BitsInMask(netMask));
+   pNode->configurationPoll(NULL, 0, -1, addr.getMaskBits());
    pNode->unhide();
    g_dwMgmtNode = pNode->getId();   // Set local management node ID
    PostEvent(EVENT_NODE_ADDED, pNode->getId(), NULL);
@@ -155,10 +155,10 @@ void CheckForMgmtNode()
    {
       for(i = 0; i < pIfList->size(); i++)
       {
-         NX_INTERFACE_INFO *iface = pIfList->get(i);
-         if ((iface->type == IFTYPE_SOFTWARE_LOOPBACK) || ((iface->ipAddr & 0xFF000000) == 0x7F000000) || (iface->ipAddr == 0))
+         InterfaceInfo *iface = pIfList->get(i);
+         if (iface->type == IFTYPE_SOFTWARE_LOOPBACK)
             continue;
-         if ((pNode = FindNodeByIP(0, iface->ipAddr)) != NULL)
+         if ((pNode = FindNodeByIP(0, &iface->ipAddrList)) != NULL)
          {
             // Check management node flag
             if (!(pNode->getFlags() & NF_IS_LOCAL_MGMT))
@@ -175,11 +175,18 @@ void CheckForMgmtNode()
          // Find interface with IP address
          for(i = 0; i < pIfList->size(); i++)
          {
-            NX_INTERFACE_INFO *iface = pIfList->get(i);
-            if ((iface->type != IFTYPE_SOFTWARE_LOOPBACK) && ((iface->ipAddr & 0xFF000000) != 0x7F000000) && (iface->ipAddr != 0))
+            InterfaceInfo *iface = pIfList->get(i);
+            if ((iface->type == IFTYPE_SOFTWARE_LOOPBACK) || (iface->ipAddrList.size() == 0))
+               continue;
+
+            for(int j = 0; j < iface->ipAddrList.size(); j++)
             {
-                               CreateManagementNode(iface->ipAddr, iface->ipNetMask);
-               break;
+               const InetAddress& addr = iface->ipAddrList.get(j);
+               if (addr.isValidUnicast())
+               {
+                                  CreateManagementNode(addr);
+                  break;
+               }
             }
          }
       }
@@ -205,7 +212,7 @@ void CheckForMgmtNode()
                }
                else
                {
-                       CreateManagementNode(0, 0);
+                       CreateManagementNode(InetAddress());
                }
        }
 }
@@ -429,33 +436,40 @@ static void CheckPotentialNode(Node *node, const InetAddress& ipAddr, UINT32 ifI
                 (g_nodePollerQueue.find((void *)&ipAddr, PollerQueueElementComparator) == NULL))
    {
       Interface *pInterface = node->findInterfaceByIndex(ifIndex);
-      if ((pInterface != NULL) && pInterface->getIpAddress().sameSubnet(ipAddr))
+      if (pInterface != NULL)
                {
-                       DbgPrintf(6, _T("DiscoveryPoller(): interface found: %s [%d] addr=%s/%d ifIndex=%d"),
-                                 pInterface->getName(), pInterface->getId(), pInterface->getIpAddress().toString(buffer),
-                                 pInterface->getIpAddress().getMaskBits(), pInterface->getIfIndex());
-         if (!ipAddr.isSubnetBroadcast(pInterface->getIpAddress().getMaskBits()))
+         const InetAddress& interfaceAddress = pInterface->getIpAddressList()->findSameSubnetAddress(ipAddr);
+         if (interfaceAddress.isValidUnicast())
          {
-            NEW_NODE *pInfo;
-                               TCHAR buffer[64];
-
-            pInfo = (NEW_NODE *)malloc(sizeof(NEW_NODE));
-            pInfo->ipAddr = ipAddr;
-            pInfo->ipAddr.setMaskBits(pInterface->getIpAddress().getMaskBits());
-                               pInfo->zoneId = node->getZoneId();
-                               pInfo->ignoreFilter = FALSE;
-                               if (macAddr == NULL)
-                                       memset(pInfo->bMacAddr, 0, MAC_ADDR_LENGTH);
-                               else
-                                       memcpy(pInfo->bMacAddr, macAddr, MAC_ADDR_LENGTH);
-                               DbgPrintf(5, _T("DiscoveryPoller(): new node queued: %s/%d"),
-                                         pInfo->ipAddr.toString(buffer), pInfo->ipAddr.getMaskBits());
-            g_nodePollerQueue.Put(pInfo);
+                          DbgPrintf(6, _T("DiscoveryPoller(): interface found: %s [%d] addr=%s/%d ifIndex=%d"),
+               pInterface->getName(), pInterface->getId(), interfaceAddress.toString(buffer), interfaceAddress.getMaskBits(), pInterface->getIfIndex());
+            if (!ipAddr.isSubnetBroadcast(interfaceAddress.getMaskBits()))
+            {
+               NEW_NODE *pInfo;
+                                  TCHAR buffer[64];
+
+               pInfo = (NEW_NODE *)malloc(sizeof(NEW_NODE));
+               pInfo->ipAddr = ipAddr;
+               pInfo->ipAddr.setMaskBits(interfaceAddress.getMaskBits());
+                                  pInfo->zoneId = node->getZoneId();
+                                  pInfo->ignoreFilter = FALSE;
+                                  if (macAddr == NULL)
+                                          memset(pInfo->bMacAddr, 0, MAC_ADDR_LENGTH);
+                                  else
+                                          memcpy(pInfo->bMacAddr, macAddr, MAC_ADDR_LENGTH);
+                                  DbgPrintf(5, _T("DiscoveryPoller(): new node queued: %s/%d"),
+                                            pInfo->ipAddr.toString(buffer), pInfo->ipAddr.getMaskBits());
+               g_nodePollerQueue.Put(pInfo);
+            }
+                          else
+                          {
+               DbgPrintf(6, _T("DiscoveryPoller(): potential node %s rejected - broadcast/multicast address"), ipAddr.toString(buffer));
+                          }
+         }
+         else
+         {
+                       DbgPrintf(6, _T("DiscoveryPoller(): interface object found but IP address not found"));
          }
-                       else
-                       {
-            DbgPrintf(6, _T("DiscoveryPoller(): potential node %s rejected - broadcast/multicast address"), ipAddr.toString(buffer));
-                       }
                }
                else
                {
@@ -479,7 +493,7 @@ static void CheckHostRoute(Node *node, ROUTE *route)
 
        DbgPrintf(6, _T("DiscoveryPoller(): checking host route %s at %d"), IpToStr(route->dwDestAddr, buffer), route->dwIfIndex);
        iface = node->findInterfaceByIndex(route->dwIfIndex);
-       if ((iface != NULL) && iface->getIpAddress().sameSubnet(route->dwDestAddr))
+       if ((iface != NULL) && iface->getIpAddressList()->findSameSubnetAddress(route->dwDestAddr).isValidUnicast())
        {
                CheckPotentialNode(node, route->dwDestAddr, route->dwIfIndex);
        }
index 9acb1ec..73f03cb 100644 (file)
@@ -4584,12 +4584,11 @@ void ClientSession::createObject(NXCPMessage *pRequest)
                                                                   break;
                                                           case OBJECT_INTERFACE:
                            {
-                              NX_INTERFACE_INFO ifInfo;
-                              memset(&ifInfo, 0, sizeof(ifInfo));
+                              InterfaceInfo ifInfo(pRequest->getFieldAsUInt32(VID_IF_INDEX));
                               nx_strncpy(ifInfo.name, szObjectName, MAX_DB_STRING);
-                              ifInfo.ipAddr = pRequest->getFieldAsUInt32(VID_IP_ADDRESS);
-                              ifInfo.ipNetMask = pRequest->getFieldAsUInt32(VID_IP_NETMASK);
-                              ifInfo.index = pRequest->getFieldAsUInt32(VID_IF_INDEX);
+                              InetAddress addr = pRequest->getFieldAsInetAddress(VID_IP_ADDRESS);
+                              if (addr.isValidUnicast())
+                                 ifInfo.ipAddrList.add(addr);
                               ifInfo.type = pRequest->getFieldAsUInt32(VID_IF_TYPE);
                                                                      pRequest->getFieldAsBinary(VID_MAC_ADDR, ifInfo.macAddr, MAC_ADDR_LENGTH);
                               ifInfo.slot = pRequest->getFieldAsUInt32(VID_IF_SLOT);
@@ -11588,7 +11587,7 @@ void ClientSession::findMacAddress(NXCPMessage *request)
              msg.setField(VID_LOCAL_NODE_ID, localNodeId);
                   msg.setField(VID_LOCAL_INTERFACE_ID, localIfId);
                   msg.setField(VID_MAC_ADDR, macAddr, MAC_ADDR_LENGTH);
-                  msg.setField(VID_IP_ADDRESS, (localIf != NULL) ? localIf->getIpAddress() : InetAddress());
+         msg.setField(VID_IP_ADDRESS, (localIf != NULL) ? localIf->getIpAddressList()->getFirstUnicastAddress() : InetAddress::INVALID);
                   msg.setField(VID_CONNECTION_TYPE, (UINT16)type);
          if (cp->getObjectClass() == OBJECT_INTERFACE)
             debugPrintf(5, _T("findMacAddress: nodeId=%d ifId=%d ifName=%s ifIndex=%d"), node->getId(), cp->getId(), cp->getName(), ((Interface *)cp)->getIfIndex());
index 0f75242..6e9d073 100644 (file)
@@ -150,6 +150,7 @@ bool Subnet::deleteFromDatabase(DB_HANDLE hdb)
 void Subnet::fillMessage(NXCPMessage *pMsg)
 {
    NetObj::fillMessage(pMsg);
+   pMsg->setField(VID_IP_ADDRESS, m_ipAddress);
    pMsg->setField(VID_ZONE_ID, m_zoneId);
        pMsg->setField(VID_SYNTHETIC_MASK, (WORD)(m_bSyntheticMask ? 1 : 0));
 }
index e60be26..4d6d91f 100644 (file)
@@ -101,25 +101,32 @@ TCHAR *GetLocalHostName(TCHAR *buffer, size_t bufSize)
 /**
  * Get IP address for local machine
  */
-UINT32 GetLocalIpAddr()
+InetAddress GetLocalIpAddr()
 {
-   InterfaceList *pIfList;
-   UINT32 dwAddr = 0;
-   int i;
-
-   pIfList = GetLocalInterfaceList();
+   InetAddress addr;
+   InterfaceList *pIfList = GetLocalInterfaceList();
    if (pIfList != NULL)
    {
       // Find first interface with IP address
-      for(i = 0; i < pIfList->size(); i++)
-                       if ((pIfList->get(i)->ipAddr != 0) && ((pIfList->get(i)->ipAddr & 0xFF000000) != 0x7F000000))
+      for(int i = 0; i < pIfList->size(); i++)
+      {
+         InterfaceInfo *iface = pIfList->get(i);
+         if (iface->type == IFTYPE_SOFTWARE_LOOPBACK)
+            continue;
+         for(int j = 0; j < iface->ipAddrList.size(); j++)
          {
-            dwAddr = pIfList->get(i)->ipAddr;
-            break;
+            const InetAddress& a = iface->ipAddrList.get(j);
+            if (a.isValidUnicast())
+            {
+               addr = a;
+               goto stop;
+            }
          }
+      }
+stop:
       delete pIfList;
    }
-   return dwAddr;
+   return addr;
 }
 
 /**
index b3ea54e..76c6d0c 100644 (file)
@@ -317,7 +317,7 @@ InetAddress VPNConnector::getPeerGatewayAddr()
    if (pObject != NULL)
    {
       if (pObject->getObjectClass() == OBJECT_NODE)
-         return pObject->getIpAddress();
+         return ((Node *)pObject)->getIpAddress();
    }
    return InetAddress();
 }
index 4a6cfd8..cdb1906 100644 (file)
@@ -1,6 +1,6 @@
 /* 
 ** NetXMS - Network Management System
-** Copyright (C) 2003-2014 Victor Kirhenshtein
+** Copyright (C) 2003-2015 Victor Kirhenshtein
 **
 ** This program is free software; you can redistribute it and/or modify
 ** it under the terms of the GNU General Public License as published by
@@ -211,3 +211,23 @@ bool Zone::showThresholdSummary()
 {
        return true;
 }
+
+/**
+ * Remove interface from index
+ */
+void Zone::removeFromIndex(Interface *iface)
+{
+   const ObjectArray<InetAddress> *list = iface->getIpAddressList()->getList();
+   for(int i = 0; i < list->size(); i++)
+   {
+      InetAddress *addr = list->get(i);
+      if (addr->isValidUnicast())
+      {
+             NetObj *o = m_idxInterfaceByAddr->get(*addr);
+             if ((o != NULL) && (o->getId() == iface->getId()))
+             {
+                     m_idxInterfaceByAddr->remove(*addr);
+             }
+      }
+   }
+}
index a0a20c5..3b1c17c 100644 (file)
@@ -106,7 +106,7 @@ InterfaceList *AlliedTelesisDriver::getInterfaces(SNMP_Transport *snmp, StringMa
       // Find physical ports
       for(int i = 0; i < ifList->size(); i++)
       {
-         NX_INTERFACE_INFO *iface = ifList->get(i);
+         InterfaceInfo *iface = ifList->get(i);
          if (isGS950)
          {
             // GS950 does not support atiIfExtnTable so we use ifConnectorPresent from ifXTable
index 958e0cd..1ac2e76 100644 (file)
@@ -134,7 +134,7 @@ InterfaceList *BayStackDriver::getInterfaces(SNMP_Transport *snmp, StringMap *at
        // TODO: does it really needed?
    for(int i = 0; i < ifList->size(); i++)
    {
-               NX_INTERFACE_INFO *iface = ifList->get(i);
+               InterfaceInfo *iface = ifList->get(i);
 
                const TCHAR *ptr;
       if ((ptr = _tcsstr(iface->name, _T("- Port"))) != NULL)
@@ -192,26 +192,24 @@ InterfaceList *BayStackDriver::getInterfaces(SNMP_Transport *snmp, StringMap *at
 
                        // Add management virtual interface if management IP is missing in interface list
                        for(i = 0; i < ifList->size(); i++)
-                               if (ifList->get(i)->ipAddr == mgmtIpAddr)
+         {
+            if (ifList->get(i)->hasAddress(mgmtIpAddr))
                                        break;
+         }
                        if (i == ifList->size())
                        {
-                               NX_INTERFACE_INFO iface;
-
-                               memset(&iface, 0, sizeof(NX_INTERFACE_INFO));
-                               iface.ipAddr = mgmtIpAddr;
-                               iface.ipNetMask = mgmtNetMask;
-            iface.type = IFTYPE_OTHER;
-                               _tcscpy(iface.name, _T("MGMT"));
-                               memcpy(iface.macAddr, baseMacAddr, MAC_ADDR_LENGTH);
-                               ifList->add(&iface);
+            InterfaceInfo *iface = new InterfaceInfo(0);
+            iface->ipAddrList.add(InetAddress(mgmtIpAddr, mgmtNetMask));
+                               _tcscpy(iface->name, _T("MGMT"));
+                               memcpy(iface->macAddr, baseMacAddr, MAC_ADDR_LENGTH);
+                               ifList->add(iface);
                        }
                }
 
                // Update wrongly reported MAC addresses
                for(int i = 0; i < ifList->size(); i++)
                {
-                       NX_INTERFACE_INFO *curr = ifList->get(i);
+                       InterfaceInfo *curr = ifList->get(i);
                        if ((curr->slot != 0) &&
                                 (!memcmp(curr->macAddr, "\x00\x00\x00\x00\x00\x00", MAC_ADDR_LENGTH) ||
                             !memcmp(curr->macAddr, baseMacAddr, MAC_ADDR_LENGTH)))
index 89b0393..c36a5d8 100644 (file)
@@ -87,8 +87,7 @@ bool Cat2900Driver::isDeviceSupported(SNMP_Transport *snmp, const TCHAR *oid)
 static UINT32 HandlerPortList(UINT32 version, SNMP_Variable *var, SNMP_Transport *transport, void *arg)
 {
        InterfaceList *ifList = (InterfaceList *)arg;
-
-       NX_INTERFACE_INFO *iface = ifList->findByIfIndex(var->getValueAsUInt());
+       InterfaceInfo *iface = ifList->findByIfIndex(var->getValueAsUInt());
        if (iface != NULL)
        {
                size_t nameLen = var->getName()->getLength();
index 3049af2..1e8df8c 100644 (file)
@@ -77,7 +77,7 @@ static UINT32 HandlerPortList(UINT32 version, SNMP_Variable *var, SNMP_Transport
 {
        InterfaceList *ifList = (InterfaceList *)arg;
 
-       NX_INTERFACE_INFO *iface = ifList->findByIfIndex(var->getValueAsUInt());
+       InterfaceInfo *iface = ifList->findByIfIndex(var->getValueAsUInt());
        if (iface != NULL)
        {
                size_t nameLen = var->getName()->getLength();
index a070e66..4b53656 100644 (file)
@@ -86,7 +86,7 @@ InterfaceList *CiscoEswDriver::getInterfaces(SNMP_Transport *snmp, StringMap *at
        // Find physical ports
        for(int i = 0; i < ifList->size(); i++)
        {
-               NX_INTERFACE_INFO *iface = ifList->get(i);
+               InterfaceInfo *iface = ifList->get(i);
                if ((iface->type == IFTYPE_ETHERNET_CSMACD) && (iface->index <= 48))
                {
                        iface->isPhysicalPort = true;
index 901cf96..5aa5297 100644 (file)
@@ -98,7 +98,7 @@ InterfaceList *CiscoSbDriver::getInterfaces(SNMP_Transport *snmp, StringMap *att
        // Find physical ports
        for(int i = 0; i < ifList->size(); i++)
        {
-               NX_INTERFACE_INFO *iface = ifList->get(i);
+               InterfaceInfo *iface = ifList->get(i);
                if (iface->index < 1000)
                {
                        iface->isPhysicalPort = true;
index 80d6e23..7f50e3d 100644 (file)
@@ -95,7 +95,7 @@ InterfaceList *PowerConnectDriver::getInterfaces(SNMP_Transport *snmp, StringMap
        // Find physical ports
        for(int i = 0; i < ifList->size(); i++)
        {
-               NX_INTERFACE_INFO *iface = ifList->get(i);
+               InterfaceInfo *iface = ifList->get(i);
                if (iface->type == IFTYPE_ETHERNET_CSMACD)
                {
                        iface->isPhysicalPort = true;
index 5f86183..5fc76c2 100644 (file)
@@ -95,7 +95,7 @@ InterfaceList *DLinkDriver::getInterfaces(SNMP_Transport *snmp, StringMap *attri
        // Find physical ports
        for(int i = 0; i < ifList->size(); i++)
        {
-               NX_INTERFACE_INFO *iface = ifList->get(i);
+               InterfaceInfo *iface = ifList->get(i);
                if (iface->index < 1024)
                {
                        iface->isPhysicalPort = true;
index 2be89a6..0631b88 100644 (file)
@@ -90,7 +90,7 @@ static UINT32 PortWalkHandler(UINT32 snmpVersion, SNMP_Variable *var, SNMP_Trans
    UINT32 ifIndex = var->getValueAsUInt();
    for(int i = 0; i < ifList->size(); i++)
    {
-      NX_INTERFACE_INFO *iface = ifList->get(i);
+      InterfaceInfo *iface = ifList->get(i);
       if (iface->index == ifIndex)
       {
          iface->isPhysicalPort = true;
index 11fdd27..d5d0c4c 100644 (file)
@@ -90,7 +90,7 @@ static UINT32 PortWalkHandler(UINT32 snmpVersion, SNMP_Variable *var, SNMP_Trans
    UINT32 ifIndex = var->getValueAsUInt();
    for(int i = 0; i < ifList->size(); i++)
    {
-      NX_INTERFACE_INFO *iface = ifList->get(i);
+      InterfaceInfo *iface = ifList->get(i);
       if (iface->index == ifIndex)
       {
          iface->isPhysicalPort = true;
index 4501410..34562ff 100644 (file)
 
 #include "avaya-ers.h"
 
-
-//
-// VLAN information structure
-//
-
+/**
+ * VLAN information structure
+ */
 struct VLAN_INFO
 {
    TCHAR szName[MAX_OBJECT_NAME];
@@ -36,13 +34,15 @@ struct VLAN_INFO
    BYTE bMacAddr[MAC_ADDR_LENGTH];
 };
 
+/**
+ * VLAN list structure
+ */
 struct VLAN_LIST
 {
    UINT32 dwNumVlans;
    VLAN_INFO *pList;
 };
 
-
 /**
  * Handler for VLAN enumeration on Avaya ERS
  */
@@ -102,29 +102,33 @@ static UINT32 HandlerRapidCityIfList(UINT32 dwVersion, SNMP_Variable *pVar, SNMP
    // Create new interface only if we have VLAN with same interface index
    if (dwVlanIndex < pVlanList->dwNumVlans)
    {
-               NX_INTERFACE_INFO iface;
-
-               memset(&iface, 0, sizeof(NX_INTERFACE_INFO));
-      iface.index = dwIfIndex;
-      _tcscpy(iface.name, pVlanList->pList[dwVlanIndex].szName);
-      iface.type = IFTYPE_L2VLAN;
-      memcpy(iface.macAddr, pVlanList->pList[dwVlanIndex].bMacAddr, MAC_ADDR_LENGTH);
+               InterfaceInfo *iface = new InterfaceInfo(dwIfIndex);
+      _tcscpy(iface->name, pVlanList->pList[dwVlanIndex].szName);
+      iface->type = IFTYPE_L2VLAN;
+      memcpy(iface->macAddr, pVlanList->pList[dwVlanIndex].bMacAddr, MAC_ADDR_LENGTH);
       
       size_t nameLen = pVar->getName()->getLength();
 
       // Get IP address
+      UINT32 ipAddr, ipNetMask;
+
       memcpy(oidName, pVar->getName()->getValue(), nameLen * sizeof(UINT32));
       oidName[nameLen - 6] = 2;
-      dwResult = SnmpGet(dwVersion, pTransport, NULL, oidName, nameLen, &iface.ipAddr, sizeof(UINT32), 0);
+      dwResult = SnmpGet(dwVersion, pTransport, NULL, oidName, nameLen, &ipAddr, sizeof(UINT32), 0);
 
       if (dwResult == SNMP_ERR_SUCCESS)
       {
          // Get netmask
          oidName[nameLen - 6] = 3;
-         dwResult = SnmpGet(dwVersion, pTransport, NULL, oidName, nameLen, &iface.ipNetMask, sizeof(UINT32), 0);
+         dwResult = SnmpGet(dwVersion, pTransport, NULL, oidName, nameLen, &ipNetMask, sizeof(UINT32), 0);
+      }
+
+      if (dwResult == SNMP_ERR_SUCCESS)
+      {
+         iface->ipAddrList.add(InetAddress(ipAddr, ipNetMask));
       }
 
-               pIfList->add(&iface);
+               pIfList->add(iface);
    }
    else
    {
index ac5f5c5..f22001c 100644 (file)
@@ -84,7 +84,7 @@ InterfaceList *MikrotikDriver::getInterfaces(SNMP_Transport *snmp, StringMap *at
 
    for(int i = 0; i < ifList->size(); i++)
    {
-      NX_INTERFACE_INFO *iface = ifList->get(i);
+      InterfaceInfo *iface = ifList->get(i);
       if (iface->type == IFTYPE_ETHERNET_CSMACD)
       {
          iface->isPhysicalPort = true;
index 0243058..be8d02e 100644 (file)
@@ -1,7 +1,7 @@
 /* 
 ** NetXMS - Network Management System
 ** Driver for Netscreen firewalls
-** Copyright (C) 2003-2011 Victor Kirhenshtein
+** Copyright (C) 2003-2015 Victor Kirhenshtein
 **
 ** This program is free software; you can redistribute it and/or modify
 ** it under the terms of the GNU Lesser General Public License as published by
@@ -92,32 +92,45 @@ static UINT32 HandlerIfList(UINT32 snmpVersion, SNMP_Variable *varbind, SNMP_Tra
        UINT32 oidName[MAX_OID_LEN];
        memcpy(oidName, varbind->getName()->getValue(), nameLen * sizeof(UINT32));
 
-       NX_INTERFACE_INFO iface;
-       memset(&iface, 0, sizeof(NX_INTERFACE_INFO));
-       iface.index = varbind->getValueAsUInt();
+       InterfaceInfo *iface = new InterfaceInfo(varbind->getValueAsUInt());
 
        oidName[10] = 2;        // nsIfName
-       UINT32 rc = SnmpGet(snmpVersion, transport, NULL, oidName, nameLen, iface.name, MAX_DB_STRING * sizeof(TCHAR), SG_STRING_RESULT);
+       UINT32 rc = SnmpGet(snmpVersion, transport, NULL, oidName, nameLen, iface->name, MAX_DB_STRING * sizeof(TCHAR), SG_STRING_RESULT);
        if (rc != SNMP_ERR_SUCCESS)
+   {
+      delete iface;
                return rc;
-       nx_strncpy(iface.description, iface.name, MAX_DB_STRING);
+   }
+       nx_strncpy(iface->description, iface->name, MAX_DB_STRING);
 
        oidName[10] = 11;       // nsIfMAC
-       rc = SnmpGet(snmpVersion, transport, NULL, oidName, nameLen, iface.macAddr, 6, SG_RAW_RESULT);
+       rc = SnmpGet(snmpVersion, transport, NULL, oidName, nameLen, iface->macAddr, 6, SG_RAW_RESULT);
        if (rc != SNMP_ERR_SUCCESS)
+   {
+      delete iface;
                return rc;
+   }
 
        oidName[10] = 6;        // nsIfIp
-       rc = SnmpGet(snmpVersion, transport, NULL, oidName, nameLen, &iface.ipAddr, sizeof(UINT32), 0);
+   UINT32 ipAddr;
+       rc = SnmpGet(snmpVersion, transport, NULL, oidName, nameLen, &ipAddr, sizeof(UINT32), 0);
        if (rc != SNMP_ERR_SUCCESS)
+   {
+      delete iface;
                return rc;
+   }
 
        oidName[10] = 7;        // nsIfNetmask
-       rc = SnmpGet(snmpVersion, transport, NULL, oidName, nameLen, &iface.ipNetMask, sizeof(UINT32), 0);
+   UINT32 ipNetMask;
+       rc = SnmpGet(snmpVersion, transport, NULL, oidName, nameLen, &ipNetMask, sizeof(UINT32), 0);
        if (rc != SNMP_ERR_SUCCESS)
+   {
+      delete iface;
                return rc;
+   }
 
-       ifList->add(&iface);
+   iface->ipAddrList.add(InetAddress(ipAddr, ipNetMask));
+       ifList->add(iface);
        return SNMP_ERR_SUCCESS;
 }
 
@@ -140,7 +153,7 @@ InterfaceList *NetscreenDriver::getInterfaces(SNMP_Transport *snmp, StringMap *a
                // Fix interface indexes
                for(int i = 0; i < ifList->size(); i++)
                {
-                       NX_INTERFACE_INFO *iface = ifList->get(i);
+                       InterfaceInfo *iface = ifList->get(i);
                        int j;
                        for(j = 0; j < stdIfList->size(); j++)
                        {
@@ -152,7 +165,7 @@ InterfaceList *NetscreenDriver::getInterfaces(SNMP_Transport *snmp, StringMap *a
                        }
                        if (j == stdIfList->size())
                        {
-                               // Interface nt found in standard interface list (usually tunnel interface)
+                               // Interface not found in standard interface list (usually tunnel interface)
                                iface->index += 32768;
                        }
                }
index 8f47eb4..dc941b1 100644 (file)
@@ -106,22 +106,18 @@ InterfaceList *Ping3Driver::getInterfaces(SNMP_Transport *snmp, StringMap *attri
       {
          ifList = new InterfaceList(1);
 
-         NX_INTERFACE_INFO iface;
-         memset(&iface, 0, sizeof(NX_INTERFACE_INFO));
-
-         _tcscpy(iface.name, _T("eth0"));
-         iface.index = 1;
-         iface.type = IFTYPE_ETHERNET_CSMACD;
-         iface.isPhysicalPort = true;
-
-         response->getVariable(0)->getRawValue((BYTE *)&iface.ipAddr, sizeof(UINT32));
-         response->getVariable(1)->getRawValue((BYTE *)&iface.ipNetMask, sizeof(UINT32));
-         response->getVariable(0)->getRawValue(iface.macAddr, MAC_ADDR_LENGTH);
-
-         iface.ipAddr = ntohl(iface.ipAddr);
-         iface.ipNetMask = ntohl(iface.ipNetMask);
-
-         ifList->add(&iface);
+         InterfaceInfo *iface = new InterfaceInfo(1);
+         _tcscpy(iface->name, _T("eth0"));
+         iface->type = IFTYPE_ETHERNET_CSMACD;
+         iface->isPhysicalPort = true;
+
+         UINT32 ipAddr, ipNetMask;
+         response->getVariable(0)->getRawValue((BYTE *)&ipAddr, sizeof(UINT32));
+         response->getVariable(1)->getRawValue((BYTE *)&ipNetMask, sizeof(UINT32));
+         response->getVariable(0)->getRawValue(iface->macAddr, MAC_ADDR_LENGTH);
+
+         iface->ipAddrList.add(InetAddress(ntohl(ipAddr), ntohl(ipNetMask)));
+         ifList->add(iface);
       }
       delete response;
    }
index c38202c..fc64e51 100644 (file)
@@ -108,7 +108,7 @@ InterfaceList *ProCurveDriver::getInterfaces(SNMP_Transport *snmp, StringMap *at
        // Find physical ports
        for(int i = 0; i < ifList->size(); i++)
        {
-               NX_INTERFACE_INFO *iface = ifList->get(i);
+               InterfaceInfo *iface = ifList->get(i);
                if (iface->type == IFTYPE_ETHERNET_CSMACD)
                {
                        iface->isPhysicalPort = true;
index d153613..cebae91 100644 (file)
@@ -895,7 +895,7 @@ bool IsLoggedIn(UINT32 dwUserId);
 bool NXCORE_EXPORTABLE KillClientSession(int id);
 
 void GetSysInfoStr(TCHAR *pszBuffer, int nMaxSize);
-UINT32 GetLocalIpAddr();
+InetAddress GetLocalIpAddr();
 TCHAR *GetLocalHostName(TCHAR *buffer, size_t bufSize);
 
 BOOL ExecCommand(TCHAR *pszCommand);
index 538a477..dcf3632 100644 (file)
@@ -44,7 +44,7 @@
 /*** Functions ***/
 #ifndef _NETXMS_DB_SCHEMA_
 
-BOOL InitLocks(UINT32 *pdwIpAddr, TCHAR *pszInfo);
+BOOL InitLocks(InetAddress *ipAddr, TCHAR *pszInfo);
 BOOL LockComponent(UINT32 dwId, int sessionId, const TCHAR *pszOwnerInfo, UINT32 *pdwCurrentOwner, TCHAR *pszCurrentOwnerInfo);
 void UnlockComponent(UINT32 dwId);
 void RemoveAllSessionLocks(int sessionId);
index c0f7610..b224feb 100644 (file)
@@ -198,14 +198,16 @@ public:
    ~InetAddressIndex();
 
        bool put(const InetAddress& addr, NetObj *object);
+       bool put(const InetAddressList *addrList, NetObj *object);
        void remove(const InetAddress& addr);
+       void remove(const InetAddressList *addrList);
        NetObj *get(const InetAddress& addr);
        NetObj *find(bool (*comparator)(NetObj *, void *), void *data);
 
        int size();
        ObjectArray<NetObj> *getObjects(bool updateRefCount, bool (*filter)(NetObj *, void *) = NULL, void *userData = NULL);
 
-       void forEach(void (*callback)(NetObj *, void *), void *data);
+       void forEach(void (*callback)(const InetAddress&, NetObj *, void *), void *data);
 };
 
 /**
@@ -371,7 +373,6 @@ protected:
    MUTEX m_mutexRefCount;     // Reference counter access mutex
    RWLOCK m_rwlockParentList; // Lock for parent list
    RWLOCK m_rwlockChildList;  // Lock for child list
-   InetAddress m_ipAddress;
        GeoLocation m_geoLocation;
    PostalAddress *m_postalAddress;
    ClientSession *m_pollRequestor;
@@ -436,7 +437,6 @@ public:
 
    virtual int getObjectClass() { return OBJECT_GENERIC; }
 
-   const InetAddress& getIpAddress() { return m_ipAddress; }
    UINT32 getId() { return m_id; }
    const TCHAR *getName() { return m_name; }
    int Status() { return m_iStatus; }
@@ -649,19 +649,22 @@ public:
    UINT32 getLastValues(NXCPMessage *msg, bool objectTooltipOnly, bool includeNoValueObjects);
 };
 
+class Cluster;
+
 /**
  * Interface class
  */
 class NXCORE_EXPORTABLE Interface : public NetObj
 {
 protected:
+   UINT32 m_index;
+   BYTE m_macAddr[MAC_ADDR_LENGTH];
+   InetAddressList m_ipAddressList;
        UINT32 m_flags;
        TCHAR m_description[MAX_DB_STRING];     // Interface description - value of ifDescr for SNMP, equals to name for NetXMS agent
        TCHAR m_alias[MAX_DB_STRING];   // Interface alias - value of ifAlias for SNMP, empty for NetXMS agent
-   UINT32 m_index;
    UINT32 m_type;
    UINT32 m_mtu;
-   BYTE m_macAddr[MAC_ADDR_LENGTH];
        UINT32 m_bridgePortNumber;              // 802.1D port number
        UINT32 m_slotNumber;                            // Vendor/device specific slot number
        UINT32 m_portNumber;                            // Vendor/device specific port number
@@ -680,15 +683,16 @@ protected:
    UINT32 m_pingTime;
    time_t m_pingLastTimeStamp;
 
-       void paeStatusPoll(ClientSession *pSession, UINT32 dwRqId, SNMP_Transport *pTransport, Node *node);
+   void icmpStatusPoll(UINT32 rqId, UINT32 nodeIcmpProxy, Cluster *cluster, InterfaceAdminState *adminState, InterfaceOperState *operState);
+       void paeStatusPoll(UINT32 rqId, SNMP_Transport *pTransport, Node *node);
 
 protected:
    virtual void onObjectDelete(UINT32 dwObjectId);
 
 public:
    Interface();
-   Interface(const InetAddress& addr, UINT32 zoneId, bool bSyntheticMask);
-   Interface(const TCHAR *name, const TCHAR *descr, UINT32 index, const InetAddress& addr, UINT32 ifType, UINT32 zoneId);
+   Interface(const InetAddressList& addrList, UINT32 zoneId, bool bSyntheticMask);
+   Interface(const TCHAR *name, const TCHAR *descr, UINT32 index, const InetAddressList& addrList, UINT32 ifType, UINT32 zoneId);
    virtual ~Interface();
 
    virtual int getObjectClass() { return OBJECT_INTERFACE; }
@@ -699,6 +703,8 @@ public:
    Node *getParentNode();
    UINT32 getParentNodeId();
 
+   const InetAddressList *getIpAddressList() { return &m_ipAddressList; }
+   const InetAddress& getFirstIpAddress();
    UINT32 getZoneId() { return m_zoneId; }
    UINT32 getIfIndex() { return m_index; }
    UINT32 getIfType() { return m_type; }
@@ -732,8 +738,7 @@ public:
    void setLastDownEventId(QWORD id) { m_lastDownEventId = id; }
 
    void setMacAddr(const BYTE *pbNewMac);
-   void setIpAddr(const InetAddress& newAddr);
-   void setIpNetMask(int maskBits);
+   void setIpAddress(const InetAddress& addr);
    void setBridgePortNumber(UINT32 bpn) { m_bridgePortNumber = bpn; setModified(); }
    void setSlotNumber(UINT32 slot) { m_slotNumber = slot; setModified(); }
    void setPortNumber(UINT32 port) { m_portNumber = port; setModified(); }
@@ -743,10 +748,13 @@ public:
    void clearPeer() { lockProperties(); m_peerNodeId = 0; m_peerInterfaceId = 0; m_peerDiscoveryProtocol = LL_PROTO_UNKNOWN; setModified(); unlockProperties(); }
    void setDescription(const TCHAR *descr) { lockProperties(); nx_strncpy(m_description, descr, MAX_DB_STRING); setModified(); unlockProperties(); }
    void setAlias(const TCHAR *alias) { lockProperties(); nx_strncpy(m_alias, alias, MAX_DB_STRING); setModified(); unlockProperties(); }
+   void addIpAddress(const InetAddress& addr);
+   void deleteIpAddress(InetAddress addr);
+   void setNetMask(const InetAddress& addr);
 
        void updateZoneId();
 
-   void statusPoll(ClientSession *session, UINT32 rqId, Queue *eventQueue, bool clusterSync, SNMP_Transport *snmpTransport, UINT32 nodeIcmpProxy);
+   void statusPoll(ClientSession *session, UINT32 rqId, Queue *eventQueue, Cluster *cluster, SNMP_Transport *snmpTransport, UINT32 nodeIcmpProxy);
 
        virtual void fillMessage(NXCPMessage *pMsg);
    virtual UINT32 modifyFromMessage(NXCPMessage *pRequest, BOOL bAlreadyLocked = FALSE);
@@ -768,6 +776,7 @@ protected:
                          // If 0, m_pHostNode->m_dwPollerNode will be used
    UINT16 m_proto;        // Protocol (TCP, UDP, etc.)
    UINT16 m_port;         // TCP or UDP port number
+   InetAddress m_ipAddress;
    TCHAR *m_request;  // Service-specific request
    TCHAR *m_response; // Service-specific expected response
        int m_pendingStatus;
@@ -895,6 +904,7 @@ protected:
        TCHAR *m_osVersion;
        TCHAR *m_userId;
        LONG m_batteryLevel;
+   InetAddress m_ipAddress;
 
 public:
    MobileDevice();
@@ -926,6 +936,7 @@ public:
 class NXCORE_EXPORTABLE AccessPoint : public DataCollectionTarget
 {
 protected:
+   InetAddress m_ipAddress;
        UINT32 m_nodeId;
        BYTE m_macAddr[MAC_ADDR_LENGTH];
        TCHAR *m_vendor;
@@ -954,15 +965,15 @@ public:
    void statusPoll(ClientSession *session, UINT32 rqId, Queue *eventQueue, Node *controller);
 
        BYTE *getMacAddr() { return m_macAddr; }
+   const InetAddress& getIpAddress() { return m_ipAddress; }
        bool isMyRadio(int rfIndex);
        bool isMyRadio(const BYTE *macAddr);
        void getRadioName(int rfIndex, TCHAR *buffer, size_t bufSize);
    AccessPointState getState() { return m_state; }
    Node *getParentNode();
 
-   void setIpAddr(const InetAddress& ipAddr) { lockProperties(); m_ipAddress = ipAddr; setModified(); unlockProperties(); }
-
        void attachToNode(UINT32 nodeId);
+   void setIpAddress(const InetAddress& addr) { lockProperties(); m_ipAddress = addr; setModified(); unlockProperties(); }
        void updateRadioInterfaces(ObjectArray<RadioInterfaceInfo> *ri);
        void updateInfo(const TCHAR *vendor, const TCHAR *model, const TCHAR *serialNumber);
    void updateState(AccessPointState state);
@@ -1026,6 +1037,7 @@ class NXCORE_EXPORTABLE Node : public DataCollectionTarget
        friend class Subnet;
 
 protected:
+   InetAddress m_ipAddress;
        TCHAR m_primaryName[MAX_DNS_NAME];
    UINT32 m_dwFlags;
    UINT32 m_dwDynamicFlags;       // Flags used at runtime by server
@@ -1160,6 +1172,7 @@ public:
 
        Cluster *getMyCluster();
 
+   const InetAddress& getIpAddress() { return m_ipAddress; }
    UINT32 getZoneId() { return m_zoneId; }
    UINT32 getFlags() { return m_dwFlags; }
    UINT32 getRuntimeFlags() { return m_dwDynamicFlags; }
@@ -1195,9 +1208,9 @@ public:
        time_t getDownTime() const { return m_downSince; }
 
    void addInterface(Interface *pInterface) { AddChild(pInterface); pInterface->AddParent(this); }
-   Interface *createNewInterface(NX_INTERFACE_INFO *ifInfo, bool manuallyCreated);
+   Interface *createNewInterface(InterfaceInfo *ifInfo, bool manuallyCreated);
    Interface *createNewInterface(const InetAddress& ipAddr, BYTE *macAddr);
-   void deleteInterface(Interface *pInterface);
+   void deleteInterface(Interface *iface);
 
        void setPrimaryName(const TCHAR *name) { nx_strncpy(m_primaryName, name, MAX_DNS_NAME); }
        void setAgentPort(WORD port) { m_agentPort = port; }
@@ -1238,7 +1251,7 @@ public:
        void resolveVlanPorts(VlanList *vlanList);
        void updateInterfaceNames(ClientSession *pSession, UINT32 dwRqId);
    void updateRoutingTable();
-       void checkSubnetBinding(InterfaceList *pIfList);
+       void checkSubnetBinding();
 
    bool isReadyForStatusPoll();
    bool isReadyForConfigurationPoll();
@@ -1470,6 +1483,7 @@ class NXCORE_EXPORTABLE Subnet : public NetObj
        friend void Node::buildIPTopologyInternal(nxmap_ObjList &topology, int nDepth, UINT32 seedSubnet, bool vpnLink, bool includeEndNodes);
 
 protected:
+   InetAddress m_ipAddress;
    UINT32 m_zoneId;
        bool m_bSyntheticMask;
 
@@ -1493,6 +1507,7 @@ public:
 
        virtual bool showThresholdSummary();
 
+   const InetAddress& getIpAddress() { return m_ipAddress; }
    UINT32 getZoneId() { return m_zoneId; }
        bool isSyntheticMask() { return m_bSyntheticMask; }
 
@@ -1668,10 +1683,10 @@ public:
    void addSubnet(Subnet *pSubnet) { AddChild(pSubnet); pSubnet->AddParent(this); }
 
        void addToIndex(Subnet *subnet) { m_idxSubnetByAddr->put(subnet->getIpAddress(), subnet); }
-       void addToIndex(Interface *iface) { m_idxInterfaceByAddr->put(iface->getIpAddress(), iface); }
+   void addToIndex(Interface *iface) { m_idxInterfaceByAddr->put(iface->getIpAddressList(), iface); }
        void addToIndex(Node *node) { m_idxNodeByAddr->put(node->getIpAddress(), node); }
        void removeFromIndex(Subnet *subnet) { m_idxSubnetByAddr->remove(subnet->getIpAddress()); }
-       void removeFromIndex(Interface *iface) { m_idxInterfaceByAddr->remove(iface->getIpAddress()); }
+       void removeFromIndex(Interface *iface);
        void removeFromIndex(Node *node) { m_idxNodeByAddr->remove(node->getIpAddress()); }
        void updateInterfaceIndex(const InetAddress& oldIp, const InetAddress& newIp, Interface *iface);
        Subnet *getSubnetByAddr(const InetAddress& ipAddr) { return (Subnet *)m_idxSubnetByAddr->get(ipAddr); }
@@ -1680,7 +1695,7 @@ public:
        Subnet *findSubnet(bool (*comparator)(NetObj *, void *), void *data) { return (Subnet *)m_idxSubnetByAddr->find(comparator, data); }
        Interface *findInterface(bool (*comparator)(NetObj *, void *), void *data) { return (Interface *)m_idxInterfaceByAddr->find(comparator, data); }
        Node *findNode(bool (*comparator)(NetObj *, void *), void *data) { return (Node *)m_idxNodeByAddr->find(comparator, data); }
-   void forEachSubnet(void (*callback)(NetObj *, void *), void *data) { m_idxSubnetByAddr->forEach(callback, data); }
+   void forEachSubnet(void (*callback)(const InetAddress& addr, NetObj *, void *), void *data) { m_idxSubnetByAddr->forEach(callback, data); }
 };
 
 /**
@@ -2163,6 +2178,19 @@ public:
        UINT32 getNodeId() { return m_nodeId; }
 };
 
+/**
+ * Get IP address for object
+ */
+inline const InetAddress& GetObjectIpAddress(NetObj *object)
+{
+   if (object->getObjectClass() == OBJECT_NODE)
+      return ((Node *)object)->getIpAddress();
+   if (object->getObjectClass() == OBJECT_SUBNET)
+      return ((Subnet *)object)->getIpAddress();
+   if (object->getObjectClass() == OBJECT_ACCESSPOINT)
+      return ((AccessPoint *)object)->getIpAddress();
+   return InetAddress::INVALID;
+}
 
 //
 // Container category information
@@ -2202,6 +2230,7 @@ NetObj NXCORE_EXPORTABLE *FindObjectByGUID(uuid_t guid, int objClass);
 const TCHAR NXCORE_EXPORTABLE *GetObjectName(DWORD id, const TCHAR *defaultName);
 Template NXCORE_EXPORTABLE *FindTemplateByName(const TCHAR *pszName);
 Node NXCORE_EXPORTABLE *FindNodeByIP(UINT32 zoneId, const InetAddress& ipAddr);
+Node NXCORE_EXPORTABLE *FindNodeByIP(UINT32 zoneId, const InetAddressList *ipAddrList);
 Node NXCORE_EXPORTABLE *FindNodeByMAC(const BYTE *macAddr);
 Node NXCORE_EXPORTABLE *FindNodeByBridgeId(const BYTE *bridgeId);
 Node NXCORE_EXPORTABLE *FindNodeByLLDPId(const TCHAR *lldpId);
index 0cb0d30..84008c7 100644 (file)
@@ -209,24 +209,41 @@ typedef struct
 /**
  * Interface information structure used by discovery functions and AgentConnection class
  */
-typedef struct
+class InterfaceInfo
 {
+public:
+   UINT32 index;
    TCHAR name[MAX_DB_STRING];                  // Interface display name
        TCHAR description[MAX_DB_STRING];       // Value of ifDescr MIB variable for SNMP agents
        TCHAR alias[MAX_DB_STRING];     // Value of ifDescr MIB variable for SNMP agents
-   UINT32 index;
    UINT32 type;
    UINT32 mtu;
        UINT32 bridgePort;
        UINT32 slot;
        UINT32 port;
-   UINT32 ipAddr;
-   UINT32 ipNetMask;
+   InetAddressList ipAddrList;
    BYTE macAddr[MAC_ADDR_LENGTH];
-   int numSecondary;      // Number of secondary IP's on this interface
        bool isPhysicalPort;
    bool isSystem;
-} NX_INTERFACE_INFO;
+
+   InterfaceInfo(UINT32 ifIndex)
+   { 
+      index = ifIndex;
+      name[0] = 0;
+      description[0] = 0;
+      alias[0] = 0;
+      type = IFTYPE_OTHER;
+      mtu = 1500;
+      bridgePort = 0;
+      slot = 0;
+      port = 0;
+      memset(macAddr, 0, sizeof(macAddr));
+      isPhysicalPort = false;
+      isSystem = false;
+   }
+
+   bool hasAddress(const InetAddress& addr) { return ipAddrList.hasAddress(addr); }
+};
 
 /**
  * Interface list used by discovery functions and AgentConnection class
@@ -234,22 +251,20 @@ typedef struct
 class LIBNXSRV_EXPORTABLE InterfaceList
 {
 private:
-   int m_size;                                  // Number of valid entries
-       int m_allocated;               // Number of allocated entries
+   ObjectArray<InterfaceInfo> *m_interfaces;
    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);
        ~InterfaceList();
 
-       void add(NX_INTERFACE_INFO *iface);
-       void remove(int index);
+   void add(InterfaceInfo *iface) { m_interfaces->add(iface); }
+   void remove(int index) { m_interfaces->remove(index); }
 
-       int size() { return m_size; }
-       NX_INTERFACE_INFO *get(int index) { return ((index >= 0) && (index < m_size)) ? &m_interfaces[index] : NULL; }
-       NX_INTERFACE_INFO *findByIfIndex(UINT32 ifIndex);
+       int size() { return m_interfaces->size(); }
+       InterfaceInfo *get(int index) { return m_interfaces->get(index); }
+       InterfaceInfo *findByIfIndex(UINT32 ifIndex);
 
        void setData(void *data) { m_data = data; }
        void *getData() { return m_data; }
index 1401c15..f3f34b7 100644 (file)
@@ -613,8 +613,6 @@ void AgentConnection::destroyResultData()
 InterfaceList *AgentConnection::getInterfaceList()
 {
    InterfaceList *pIfList = NULL;
-       NX_INTERFACE_INFO iface;
-   UINT32 i, dwBits;
    TCHAR *pChar, *pBuf;
 
    if (getList(_T("Net.InterfaceList")) == ERR_SUCCESS)
@@ -623,17 +621,17 @@ InterfaceList *AgentConnection::getInterfaceList()
 
       // Parse result set. Each line should have the following format:
       // index ip_address/mask_bits iftype mac_address name
-      for(i = 0; i < m_dwNumDataLines; i++)
+      for(UINT i = 0; i < m_dwNumDataLines; i++)
       {
          pBuf = m_ppDataLines[i];
-                       memset(&iface, 0, sizeof(NX_INTERFACE_INFO));
+         InterfaceInfo *iface = new InterfaceInfo(0);
 
          // Index
          pChar = _tcschr(pBuf, ' ');
          if (pChar != NULL)
          {
             *pChar = 0;
-            iface.index = _tcstoul(pBuf, NULL, 10);
+            iface->index = _tcstoul(pBuf, NULL, 10);
             pBuf = pChar + 1;
          }
 
@@ -655,9 +653,9 @@ InterfaceList *AgentConnection::getInterfaceList()
             {
                pSlash = defaultMask;
             }
-            iface.ipAddr = ntohl(_t_inet_addr(pBuf));
-            dwBits = _tcstoul(pSlash, NULL, 10);
-            iface.ipNetMask = (dwBits == 32) ? 0xFFFFFFFF : (~(0xFFFFFFFF >> dwBits));
+            InetAddress addr = InetAddress::parse(pBuf);
+            addr.setMaskBits(_tcstol(pSlash, NULL, 10));
+            iface->ipAddrList.add(addr);
             pBuf = pChar + 1;
          }
 
@@ -666,7 +664,7 @@ InterfaceList *AgentConnection::getInterfaceList()
          if (pChar != NULL)
          {
             *pChar = 0;
-            iface.type = _tcstoul(pBuf, NULL, 10);
+            iface->type = _tcstoul(pBuf, NULL, 10);
             pBuf = pChar + 1;
          }
 
@@ -675,15 +673,15 @@ InterfaceList *AgentConnection::getInterfaceList()
          if (pChar != NULL)
          {
             *pChar = 0;
-            StrToBin(pBuf, iface.macAddr, MAC_ADDR_LENGTH);
+            StrToBin(pBuf, iface->macAddr, MAC_ADDR_LENGTH);
             pBuf = pChar + 1;
          }
 
          // Name (set description to name)
-         nx_strncpy(iface.name, pBuf, MAX_DB_STRING);
-                       nx_strncpy(iface.description, pBuf, MAX_DB_STRING);
+         nx_strncpy(iface->name, pBuf, MAX_DB_STRING);
+                       nx_strncpy(iface->description, pBuf, MAX_DB_STRING);
 
-                       pIfList->add(&iface);
+                       pIfList->add(iface);
       }
 
       lock();
index 79f292a..8a2e025 100644 (file)
  */
 InterfaceList::InterfaceList(int initialAlloc)
 {
-       m_allocated = initialAlloc;
-       m_size = 0;
+       m_interfaces = new ObjectArray<InterfaceInfo>(initialAlloc, 32, true);
        m_data = NULL;
-       m_interfaces = (NX_INTERFACE_INFO *)malloc(sizeof(NX_INTERFACE_INFO) * m_allocated);
    m_needPrefixWalk = false;
 }
 
@@ -39,42 +37,17 @@ InterfaceList::InterfaceList(int initialAlloc)
  */
 InterfaceList::~InterfaceList()
 {
-       safe_free(m_interfaces);
-}
-
-/**
- * Add new interface
- */
-void InterfaceList::add(NX_INTERFACE_INFO *iface)
-{
-       if (m_size == m_allocated)
-       {
-               m_allocated += 32;
-               m_interfaces = (NX_INTERFACE_INFO *)realloc(m_interfaces, sizeof(NX_INTERFACE_INFO) * m_allocated);
-       }
-       memcpy(&m_interfaces[m_size++], iface, sizeof(NX_INTERFACE_INFO));
+       delete m_interfaces;
 }
 
 /**
  * Find interface entry by ifIndex
  */
-NX_INTERFACE_INFO *InterfaceList::findByIfIndex(UINT32 ifIndex)
+InterfaceInfo *InterfaceList::findByIfIndex(UINT32 ifIndex)
 {
    // Delete loopback interface(s) from list
-   for(int i = 0; i < m_size; i++)
-               if (m_interfaces[i].index == ifIndex)
-                       return &m_interfaces[i];
+   for(int i = 0; i < m_interfaces->size(); i++)
+      if (m_interfaces->get(i)->index == ifIndex)
+                       return m_interfaces->get(i);
        return NULL;
 }
-
-/**
- * Remove entry
- */
-void InterfaceList::remove(int index)
-{
-       if ((index < 0) || (index >= m_size))
-               return;
-
-       m_size--;
-       memmove(&m_interfaces[index], &m_interfaces[index + 1], sizeof(NX_INTERFACE_INFO) * (m_size - index));
-}
index ac04b2d..4ceb1ab 100644 (file)
@@ -157,10 +157,7 @@ void NetworkDeviceDriver::analyzeDevice(SNMP_Transport *snmp, const TCHAR *oid,
  */
 static UINT32 HandlerIndex(UINT32 dwVersion, SNMP_Variable *pVar, SNMP_Transport *pTransport, void *pArg)
 {
-       NX_INTERFACE_INFO info;
-       memset(&info, 0, sizeof(NX_INTERFACE_INFO));
-       info.index = pVar->getValueAsUInt();
-       ((InterfaceList *)pArg)->add(&info);
+       ((InterfaceList *)pArg)->add(new InterfaceInfo(pVar->getValueAsUInt()));
    return SNMP_ERR_SUCCESS;
 }
 
@@ -173,10 +170,7 @@ static UINT32 HandlerIndexIfXTable(UINT32 dwVersion, SNMP_Variable *pVar, SNMP_T
    UINT32 index = name->getValue()[name->getLength() - 1];
    if (((InterfaceList *)pArg)->findByIfIndex(index) == NULL)
    {
-          NX_INTERFACE_INFO info;
-          memset(&info, 0, sizeof(NX_INTERFACE_INFO));
-      info.index = index;
-          ((InterfaceList *)pArg)->add(&info);
+          ((InterfaceList *)pArg)->add(new InterfaceInfo(index));
    }
    return SNMP_ERR_SUCCESS;
 }
@@ -209,24 +203,10 @@ static UINT32 HandlerIpAddr(UINT32 dwVersion, SNMP_Variable *pVar, SNMP_Transpor
    if (dwResult == SNMP_ERR_SUCCESS)
    {
                InterfaceList *ifList = (InterfaceList *)pArg;
-      NX_INTERFACE_INFO *iface = ifList->findByIfIndex(index);
+      InterfaceInfo *iface = ifList->findByIfIndex(index);
       if (iface != NULL)
       {
-         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 = ntohl(pVar->getValueAsUInt());
-                               extIface.ipNetMask = dwNetMask;
-                               ifList->add(&extIface);
-         }
-                       else
-                       {
-                               iface->ipAddr = ntohl(pVar->getValueAsUInt());
-                               iface->ipNetMask = dwNetMask;
-                       }
+         iface->ipAddrList.add(InetAddress(ntohl(pVar->getValueAsUInt()), BitsInMask(dwNetMask)));
                }
    }
        else
@@ -250,22 +230,31 @@ static UINT32 HandlerIpAddressTable(UINT32 version, SNMP_Variable *var, SNMP_Tra
    size_t oidLen = var->getName()->getLength();
    memcpy(oid, var->getName()->getValue(), oidLen * sizeof(UINT32));
 
-   // Check address family (1 = ipv4)
-   if (oid[10] != 1)
+   // Check address family (1 = ipv4, 2 = ipv6)
+   if ((oid[10] != 1) && (oid[10] != 2))
       return SNMP_ERR_SUCCESS;
 
    UINT32 ifIndex = var->getValueAsUInt();
-   NX_INTERFACE_INFO *iface = ifList->findByIfIndex(ifIndex);
+   InterfaceInfo *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)
+   InetAddress addr;
+   if (oid[10] == 1)
+   {
+      addr = InetAddress((UINT32)((oid[12] << 24) | (oid[13] << 16) | (oid[14] << 8) | oid[15]));
+   }
+   else
+   {
+      BYTE bytes[16];
+      for(int i = 12, j = 0; j < 16; i++, j++)
+         bytes[j] = (BYTE)oid[i];
+      addr = InetAddress(bytes);
+   }
+   if (iface->hasAddress(addr))
       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
@@ -282,34 +271,17 @@ static UINT32 HandlerIpAddressTable(UINT32 version, SNMP_Variable *var, SNMP_Tra
          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;
+            addr.setMaskBits((int)prefix->getValue()[prefix->getLength() - 1]);
          }
          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;
-                       }
+         iface->ipAddrList.add(addr);
       }
       delete response;
    }
-
    return SNMP_ERR_SUCCESS;
 }
 
@@ -321,28 +293,39 @@ static UINT32 HandlerIpAddressPrefixTable(UINT32 version, SNMP_Variable *var, SN
    InterfaceList *ifList = (InterfaceList *)arg;
    const UINT32 *oid = var->getName()->getValue();
    
-   // Check address family (1 = ipv4)
-   if (oid[10] != 1)
+   // Check address family (1 = ipv4, 2 = ipv6)
+   if ((oid[10] != 1) && (oid[10] != 2))
       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;
+   InetAddress prefix;
+   if (oid[10] == 1)
+   {
+      prefix = InetAddress((UINT32)((oid[13] << 24) | (oid[14] << 16) | (oid[15] << 8) | oid[16]));
+      prefix.setMaskBits((int)oid[17]);
+   }
+   else
+   {
+      BYTE bytes[16];
+      for(int i = 13, j = 0; j < 16; i++, j++)
+         bytes[j] = (BYTE)oid[i];
+      prefix = InetAddress(bytes);
+      prefix.setMaskBits((int)oid[29]);
+   }
 
    // Find matching IP and set mask
-   for(int i = 0; i < ifList->size(); i++)
+   InterfaceInfo *iface = ifList->findByIfIndex(oid[12]);
+   if (iface != NULL)
    {
-      NX_INTERFACE_INFO *iface = ifList->get(i);
-      if (iface->index != oid[12])
-         continue;
-
-      if ((iface->ipAddr & mask) == prefix)
+      for(int i = 0; i < iface->ipAddrList.size(); i++)
       {
-         iface->ipNetMask = mask;
-         break;
+         InetAddress *addr = iface->ipAddrList.getList()->get(i);
+         if ((addr != NULL) && prefix.contain(*addr))
+         {
+            addr->setMaskBits(prefix.getMaskBits());
+         }
       }
    }
-
    return SNMP_ERR_SUCCESS;
 }
 
@@ -389,7 +372,7 @@ InterfaceList *NetworkDeviceDriver::getInterfaces(SNMP_Transport *snmp, StringMa
       // Enumerate interfaces
                for(i = 0; i < pIfList->size(); i++)
       {
-                       NX_INTERFACE_INFO *iface = pIfList->get(i);
+                       InterfaceInfo *iface = pIfList->get(i);
 
                        // Get interface description
              _sntprintf(szOid, 128, _T(".1.3.6.1.2.1.2.2.1.2.%d"), iface->index);
index b86a4c0..9ba0661 100644 (file)
@@ -140,32 +140,31 @@ static BOOL FindSubnetForNode(DWORD id, const TCHAR *name)
        DB_RESULT hResult, hResult2;
        TCHAR query[256], buffer[32];
        int i, count;
-       DWORD addr, mask, subnet;
        BOOL success = FALSE;
 
        // Read list of interfaces of given node
-       _sntprintf(query, 256, _T("SELECT ip_addr,ip_netmask FROM interfaces WHERE node_id=%d"), id);
+       _sntprintf(query, 256, _T("SELECT l.ip_addr,l.ip_netmask FROM interfaces i INNER JOIN interface_address_list l ON l.iface_id = i.id WHERE node_id=%d"), id);
        hResult = SQLSelect(query);
        if (hResult != NULL)
        {
                count = DBGetNumRows(hResult);
                for(i = 0; i < count; i++)
                {
-                       addr = DBGetFieldIPAddr(hResult, i, 0);
-                       mask = DBGetFieldIPAddr(hResult, i, 1);
-                       subnet = addr & mask;
+                       InetAddress addr = DBGetFieldInetAddr(hResult, i, 0);
+         addr.setMaskBits(DBGetFieldLong(hResult, i, 1));
+         InetAddress subnet = addr.getSubnetAddress();
                        
-                       _sntprintf(query, 256, _T("SELECT id FROM subnets WHERE ip_addr='%s'"), IpToStr(subnet, buffer));
+         _sntprintf(query, 256, _T("SELECT id FROM subnets WHERE ip_addr='%s'"), subnet.toString(buffer));
                        hResult2 = SQLSelect(query);
                        if (hResult2 != NULL)
                        {
                                if (DBGetNumRows(hResult2) > 0)
                                {
-                                       subnet = DBGetFieldULong(hResult2, 0, 0);
+                                       UINT32 subnetId = DBGetFieldULong(hResult2, 0, 0);
                                        m_iNumErrors++;
-                                       if (GetYesNo(_T("\rUnlinked node object %d (\"%s\") can be linked to subnet %d (%s). Link?"), id, name, subnet, buffer))
+                                       if (GetYesNo(_T("\rUnlinked node object %d (\"%s\") can be linked to subnet %d (%s). Link?"), id, name, subnetId, buffer))
                                        {
-                                               _sntprintf(query, 256, _T("INSERT INTO nsmap (subnet_id,node_id) VALUES (%d,%d)"), subnet, id);
+                                               _sntprintf(query, 256, _T("INSERT INTO nsmap (subnet_id,node_id) VALUES (%d,%d)"), subnetId, id);
                                                if (SQLQuery(query))
                                                {
                                                        success = TRUE;
index da38a29..17c44a9 100644 (file)
@@ -437,6 +437,76 @@ static BOOL ConvertNetMasks(const TCHAR *table, const TCHAR *column, const TCHAR
 }
 
 /**
+ * Upgrade from V347 to V348
+ */
+static BOOL H_UpgradeFromV347(int currVersion, int newVersion)
+{
+   CHK_EXEC(CreateEventTemplate(EVENT_IF_IPADDR_ADDED, _T("SYS_IF_IPADDR_ADDED"), SEVERITY_NORMAL, EF_LOG,
+         _T("IP address %3/%4 added to interface \"%2\""),
+         _T("Generated when IP address added to interface.\r\n")
+         _T("Parameters:\r\n")
+         _T("    1) Interface object ID\r\n")
+         _T("    2) Interface name\r\n")
+         _T("    3) IP address\r\n")
+         _T("    4) Network mask\r\n")
+         _T("    5) Interface index")));
+
+   CHK_EXEC(CreateEventTemplate(EVENT_IF_IPADDR_DELETED, _T("SYS_IF_IPADDR_DELETED"), SEVERITY_NORMAL, EF_LOG,
+         _T("IP address %3/%4 deleted from interface \"%2\""),
+         _T("Generated when IP address deleted from interface.\r\n")
+         _T("Parameters:\r\n")
+         _T("    1) Interface object ID\r\n")
+         _T("    2) Interface name\r\n")
+         _T("    3) IP address\r\n")
+         _T("    4) Network mask\r\n")
+         _T("    5) Interface index")));
+
+   CHK_EXEC(SQLQuery(_T("UPDATE metadata SET var_value='348' WHERE var_name='SchemaVersion'")));
+   return TRUE;
+}
+
+/**
+ * Upgrade from V346 to V347
+ */
+static BOOL H_UpgradeFromV346(int currVersion, int newVersion)
+{
+   CHK_EXEC(CreateTable(
+      _T("CREATE TABLE interface_address_list (")
+      _T("   iface_id integer not null,")
+      _T("      ip_addr varchar(48) not null,")
+      _T("      ip_netmask integer not null,")
+      _T("   PRIMARY KEY(iface_id,ip_addr))")));
+
+   DB_RESULT hResult = SQLSelect(_T("SELECT id,ip_addr,ip_netmask FROM interfaces WHERE ip_addr<>'0.0.0.0'"));
+   if (hResult != NULL)
+   {
+      int count = DBGetNumRows(hResult);
+      for(int i = 0; i < count; i++)
+      {
+         TCHAR query[256], addr[64];
+         _sntprintf(query, 256, _T("INSERT INTO interface_address_list (iface_id,ip_addr,ip_netmask) VALUES (%d,'%s',%d)"),
+            DBGetFieldLong(hResult, i, 0), DBGetField(hResult, i, 1, addr, 64), DBGetFieldLong(hResult, i, 2));
+         CHK_EXEC(SQLQuery(query));
+      }
+      DBFreeResult(hResult);
+   }
+   else
+   {
+      if (!g_bIgnoreErrors)
+         return FALSE;
+   }
+
+   static TCHAR batch[] =
+      _T("ALTER TABLE interfaces DROP COLUMN ip_addr\n")
+      _T("ALTER TABLE interfaces DROP COLUMN ip_netmask\n")
+      _T("<END>");
+   CHK_EXEC(SQLBatch(batch));
+
+   CHK_EXEC(SQLQuery(_T("UPDATE metadata SET var_value='347' WHERE var_name='SchemaVersion'")));
+   return TRUE;
+}
+
+/**
  * Upgrade from V345 to V346
  */
 static BOOL H_UpgradeFromV345(int currVersion, int newVersion)
@@ -502,7 +572,7 @@ static BOOL H_UpgradeFromV344(int currVersion, int newVersion)
  */
 static BOOL H_UpgradeFromV343(int currVersion, int newVersion)
 {
-    static TCHAR batch[] =
+   static TCHAR batch[] =
       _T("ALTER TABLE interfaces ADD mtu integer\n")
       _T("ALTER TABLE interfaces ADD alias varchar(255)\n")
       _T("UPDATE interfaces SET mtu=0\n")
@@ -8390,6 +8460,8 @@ static struct
    { 343, 344, H_UpgradeFromV343 },
    { 344, 345, H_UpgradeFromV344 },
    { 345, 346, H_UpgradeFromV345 },
+   { 346, 347, H_UpgradeFromV346 },
+   { 347, 348, H_UpgradeFromV347 },
    { 0, 0, NULL }
 };