added method InetAddress::isLinkLocal(); added method InetAddressList::get(); fixed...
authorVictor Kirhenshtein <victor@netxms.org>
Tue, 3 Mar 2015 21:24:10 +0000 (23:24 +0200)
committerVictor Kirhenshtein <victor@netxms.org>
Tue, 3 Mar 2015 21:24:10 +0000 (23:24 +0200)
include/nms_util.h
src/libnetxms/inetaddr.cpp
tests/test-libnetxms/test-libnetxms.cpp

index 926ef7e..8a3f35b 100644 (file)
@@ -893,14 +893,15 @@ public:
    InetAddress();
    InetAddress(UINT32 addr);
    InetAddress(UINT32 addr, UINT32 mask);
-   InetAddress(BYTE *addr);
+   InetAddress(const BYTE *addr, int maskBits = 128);
 
    bool isAnyLocal() const;
    bool isLoopback() const;
    bool isMulticast() const;
    bool isBroadcast() const;
+   bool isLinkLocal() const;
    bool isValid() const { return m_family != AF_UNSPEC; }
-   bool isValidUnicast() const { return isValid() && !isAnyLocal() && !isLoopback() && !isMulticast() && !isBroadcast(); }
+   bool isValidUnicast() const { return isValid() && !isAnyLocal() && !isLoopback() && !isMulticast() && !isBroadcast() && !isLinkLocal(); }
 
    int getFamily() const { return m_family; }
    UINT32 getAddressV4() const { return (m_family == AF_INET) ? m_addr.v4 : 0; }
@@ -952,9 +953,11 @@ public:
 
    void add(const InetAddress& addr);
    void remove(const InetAddress& addr);
+   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(); }
    bool hasAddress(const InetAddress& addr) const { return indexOf(addr) != -1; }
+   const InetAddress& findAddress(const InetAddress& addr) const { int idx = indexOf(addr); return (idx != -1) ? *m_list->get(idx) : InetAddress::INVALID; }
    const InetAddress& findSameSubnetAddress(const InetAddress& addr) const;
    const InetAddress& getFirstUnicastAddress() const;
    const InetAddress& getFirstUnicastAddressV4() const;
index a0a5e1b..9d048bf 100644 (file)
  */
 const InetAddress InetAddress::INVALID = InetAddress();
 
+/**
+ * IPv4 link local subnet
+ */
+static const InetAddress IPV4_LINK_LOCAL = InetAddress(0xA9FE0000, 0xFFFF0000);
+
+/**
+ * IPv6 link local subnet
+ */
+static const InetAddress IPV6_LINK_LOCAL = InetAddress((const BYTE *)"\xfe\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 10);
+
 /**
  * Create IPv4 address object
  */
@@ -51,11 +61,11 @@ InetAddress::InetAddress(UINT32 addr, UINT32 mask)
 /**
  * Create IPv6 address object
  */
-InetAddress::InetAddress(BYTE *addr)
+InetAddress::InetAddress(const BYTE *addr, int maskBits)
 {
    m_family = AF_INET6;
    memcpy(m_addr.v6, addr, 16);
-   m_maskBits = 128;
+   m_maskBits = maskBits;
 }
 
 /**
@@ -99,6 +109,14 @@ bool InetAddress::isBroadcast() const
    return (m_family == AF_INET) ? (m_addr.v4 == 0xFFFFFFFF) : false;
 }
 
+/**
+ * Returns true if address is a link local address
+ */
+bool InetAddress::isLinkLocal() const
+{
+   return (m_family == AF_INET) ? IPV4_LINK_LOCAL.contain(*this) : IPV6_LINK_LOCAL.contain(*this);
+}
+
 /**
  * Convert to string
  */
@@ -152,7 +170,7 @@ InetAddress InetAddress::getSubnetAddress() const
    {
       int b = m_maskBits / 8;
       int shift = m_maskBits % 8;
-      BYTE mask = (shift > 0) ? (BYTE)((1 << (8 - shift)) & 0xFF) : 0;
+      BYTE mask = (shift > 0) ? (BYTE)(0xFF << (8 - shift)) : 0;
       addr.m_addr.v6[b] &= mask;
       for(int i = b + 1; i < 16; i++)
          addr.m_addr.v6[i] = 0;
@@ -170,20 +188,6 @@ bool InetAddress::isSubnetBroadcast(int maskBits) const
       UINT32 mask = 0xFFFFFFFF << (32 - maskBits);
       return (m_addr.v4 & (~mask)) == (~mask);
    }
-   if (m_family == AF_INET6)
-   {
-      BYTE addr[16];
-      memcpy(addr, m_addr.v6, 16);
-      if (maskBits < 128)
-      {
-         int b = maskBits / 8;
-         int shift = maskBits % 8;
-         addr[b] |= ((BYTE)0xFF >> shift);
-         for(int i = b + 1; i < 16; i++)
-            addr[i] = 0xFF;
-      }
-      return !memcmp(addr, m_addr.v6, 16);
-   }
    return false;
 }
 
@@ -208,7 +212,7 @@ bool InetAddress::contain(const InetAddress &a) const
       {
          int b = m_maskBits / 8;
          int shift = m_maskBits % 8;
-         BYTE mask = (shift > 0) ? (BYTE)((1 << (8 - shift)) & 0xFF) : 0;
+         BYTE mask = (shift > 0) ? (BYTE)(0xFF << (8 - shift)) : 0;
          addr[b] &= mask;
          for(int i = b + 1; i < 16; i++)
             addr[i] = 0;
@@ -240,7 +244,7 @@ bool InetAddress::sameSubnet(const InetAddress &a) const
       {
          int b = m_maskBits / 8;
          int shift = m_maskBits % 8;
-         BYTE mask = (shift > 0) ? (BYTE)((1 << (8 - shift)) & 0xFF) : 0;
+         BYTE mask = (shift > 0) ? (BYTE)(0xFF << (8 - shift)) : 0;
          addr1[b] &= mask;
          addr2[b] &= mask;
          for(int i = b + 1; i < 16; i++)
index defeadd..666cf37 100644 (file)
@@ -268,7 +268,7 @@ static void TestString()
  */
 static void TestInetAddress()
 {
-   InetAddress a;
+   InetAddress a, b, c;
 
    StartTest(_T("InetAddress - isSubnetBroadcast() - IPv4"));
    a = InetAddress::parse("192.168.0.255");
@@ -278,9 +278,45 @@ static void TestInetAddress()
 
    StartTest(_T("InetAddress - isSubnetBroadcast() - IPv6"));
    a = InetAddress::parse("fe80::ffff:ffff:ffff:ffff");
-   AssertTrue(a.isSubnetBroadcast(64));
+   AssertFalse(a.isSubnetBroadcast(64));
    AssertFalse(a.isSubnetBroadcast(63));
    EndTest();
+
+   StartTest(_T("InetAddress - isLinkLocal() - IPv4"));
+   a = InetAddress::parse("169.254.17.198");
+   AssertTrue(a.isLinkLocal());
+   a = InetAddress::parse("192.168.1.1");
+   AssertFalse(a.isLinkLocal());
+   EndTest();
+
+   StartTest(_T("InetAddress - isLinkLocal() - IPv6"));
+   a = InetAddress::parse("fe80::1");
+   AssertTrue(a.isLinkLocal());
+   a = InetAddress::parse("2000:1234::1");
+   AssertFalse(a.isLinkLocal());
+   EndTest();
+
+   StartTest(_T("InetAddress - sameSubnet() - IPv4"));
+   a = InetAddress::parse("192.168.1.43");
+   a.setMaskBits(23);
+   b = InetAddress::parse("192.168.0.180");
+   b.setMaskBits(23);
+   c = InetAddress::parse("192.168.2.22");
+   c.setMaskBits(23);
+   AssertTrue(a.sameSubnet(b));
+   AssertFalse(a.sameSubnet(c));
+   EndTest();
+
+   StartTest(_T("InetAddress - sameSubnet() - IPv6"));
+   a = InetAddress::parse("2000:1234:1000:1000::1");
+   a.setMaskBits(62);
+   b = InetAddress::parse("2000:1234:1000:1001::cdef:1");
+   b.setMaskBits(62);
+   c = InetAddress::parse("2000:1234:1000:1007::1");
+   c.setMaskBits(62);
+   AssertTrue(a.sameSubnet(b));
+   AssertFalse(a.sameSubnet(c));
+   EndTest();
 }
 
 /**