libi2ncommon: (tomj) improve to_cidr() function (returns IP_RANGE now)
authorGerd v. Egidy <gerd.von.egidy@intra2net.com>
Sat, 4 Sep 2004 22:36:15 +0000 (22:36 +0000)
committerGerd v. Egidy <gerd.von.egidy@intra2net.com>
Sat, 4 Sep 2004 22:36:15 +0000 (22:36 +0000)
src/ipfunc.cpp
src/ipfunc.hxx
test/ip_range.cpp

index bb9e547..626f9e7 100644 (file)
 using namespace std;
 using namespace ip_type;
 
-#include <iostream>
-
 // can decode IP, IP-IP (as range) and IP/MASK (as network)
-IP_RANGE::IP_RANGE(const std::string& ip)
+void IP_RANGE::load(const std::string& ip)
 {
     int delim_pos;
     struct in_addr ia_ip1, ia_ip2;
@@ -105,6 +103,43 @@ void IP_RANGE::load(type t, const std::string& ip, const std::string& mask_or_en
     }
 }
 
+void IP_RANGE::load(type t, unsigned int ip, unsigned int mask_or_end)
+{
+    struct in_addr ia_ip1, ia_ip2;
+
+    this->t=t;
+        
+    if (t==IP)
+    {
+        this->ip=ip;
+        this->mask=0xFFFFFFFF;
+        this->end=this->ip;
+    }
+    else if (t==NETWORK)
+    {
+        this->ip=ip;
+        this->mask=mask_or_end;
+        
+        // make sure ip is really the network address
+        this->ip=(this->ip & this->mask);
+        
+        // calculate end of the network (=broadcast addr)
+        this->end=((this->mask ^ 0xFFFFFFFF) | this->ip);
+    }
+    else if (t==RANGE)
+    {
+        this->ip=ip;
+        this->end=mask_or_end;
+        
+        // Automatically turn IP if IP & end are swapped
+        if (turn_ip(this->ip) > turn_ip(this->end)) {
+            unsigned int tmp = this->ip;
+            this->ip = this->end;
+            this->end = tmp;
+        }
+    }
+}
+
 bool IP_RANGE::is_within(const IP_RANGE& a) const
 {
     if (t != RANGE && a.t != RANGE)
@@ -209,33 +244,25 @@ std::string IP_RANGE::to_string(void) const
     return output;    
 }
 
-vector<string> IP_RANGE::to_cidr(void) const
+vector<IP_RANGE> IP_RANGE::to_cidr(void) const
 {
-    vector<string> cidrs;
+    vector<IP_RANGE> cidrs;
     
-    if (t==IP) {
-        cidrs.push_back(to_string()+"/32");
-    } else if (t==NETWORK) {
-        ostringstream out;
-        out << ip_string(ip) << "/" << get_mask_bits();
-        cidrs.push_back(out.str());
-    } else if (t==RANGE) {
+    if (t==IP || t==NETWORK) {
+        cidrs.push_back(*this);
+    } else {
         // do the real work
         unsigned int cidr_addr = turn_ip(ip), cidr_end = turn_ip(end);
         
         // special case: 0.0.0.0-255.255.255.255
         if (cidr_addr == 0 && cidr_end == 0xFFFFFFFF) {
-            cidrs.push_back("0.0.0.0/0");
+            cidrs.push_back(IP_RANGE(ip_type::NETWORK,0,0));
         } else {
-            ostringstream out;
-            
             unsigned int bit = 0, mask = 0;
             while (cidr_addr <= cidr_end) {
                 mask |= (1 << bit);
                 if ((cidr_addr & mask) || ((cidr_addr | mask) > cidr_end)) {
-                    out.str("");
-                    out << ip_string(turn_ip(cidr_addr)) << "/" << 32-bit;
-                    cidrs.push_back(out.str());
+                    cidrs.push_back(IP_RANGE(ip_type::NETWORK,turn_ip(cidr_addr),calc_netmask_from_cidr(32-bit)));
                     
                     cidr_addr += (1 << bit);
                     bit = 0;
index dead12f..6f238aa 100644 (file)
@@ -35,10 +35,18 @@ class IP_RANGE
             { ip=0; mask=0; end=0; t=ip_type::IP; }
         IP_RANGE(const IP_RANGE &r)
             { t=r.t; ip=r.ip; mask=r.mask; end=r.end; }
-        IP_RANGE(const std::string& ip);                     // can decode IP-IP (as range) and IP/MASK (as network)
+        IP_RANGE(const char* ip)
+            { load(ip); }
+        IP_RANGE(const std::string& ip)
+            { load(ip); }
         IP_RANGE(ip_type::type t, const std::string& ip, const std::string& mask_or_end="")
             { load(t,ip,mask_or_end); }
+        IP_RANGE(ip_type::type t, unsigned int ip, unsigned int mask_or_end=0)
+            { load(t,ip,mask_or_end); }
+        
+        void load(const std::string& ip);                     // can decode IP-IP (as range) and IP/MASK (as network)
         void load(ip_type::type t, const std::string& ip, const std::string& mask_or_end="");
+        void load(ip_type::type t, unsigned int ip, unsigned int mask_or_end=0);
 
         bool is_within(const IP_RANGE& a) const;
         bool overlapping(const IP_RANGE& a) const;
@@ -47,7 +55,9 @@ class IP_RANGE
         
         // returns the complete IP_RANGE
         std::string to_string(void) const;
-        std::vector<std::string> to_cidr(void) const;
+        
+        // returns the complete range in cidr blocks        
+        std::vector<IP_RANGE> to_cidr(void) const;
         
         unsigned int get_mask_bits() const
             { return calc_netmask_bits(mask); }
index 037b0b4..b018d72 100644 (file)
 
 #include <ipfunc.hxx>
 
+namespace CppUnit
+{
+
+template<> 
+struct assertion_traits<std::vector<IP_RANGE> >
+{
+    static bool equal( const std::vector<IP_RANGE>& x, const std::vector<IP_RANGE>& y )
+    {
+        return x == y;
+    }
+    static std::string toString( const std::vector<IP_RANGE>& x )
+    {
+        std::ostringstream os;
+        
+        for (std::vector<IP_RANGE>::const_iterator i=x.begin(); i!=x.end(); i++)
+        {
+            if (os.str().length())
+                os << ", ";
+            os << i->to_string();
+        }
+        return os.str();
+    }
+};
+
+}
+
 using namespace std;
 using namespace CppUnit;
-
+     
 class ip_range : public TestFixture
 {
     CPPUNIT_TEST_SUITE(ip_range);
@@ -74,7 +101,7 @@ class ip_range : public TestFixture
     CPPUNIT_TEST(Range2Cidr5);
     CPPUNIT_TEST(Range2Cidr6);
     CPPUNIT_TEST(Range2Cidr7);
-    
+
     CPPUNIT_TEST_SUITE_END();
     
     
@@ -88,19 +115,6 @@ class ip_range : public TestFixture
         {
         }
 
-        void compare_vector(const vector<string> &a, const vector<string> &b)
-        {
-            if (a.size() != b.size())
-                throw runtime_error("vector sizes don't match");
-            
-            for(vector<string>::const_iterator i=a.begin(), ie=a.end(),
-                check_i = b.begin(); i != ie; i++, check_i++)
-            {
-                if (*i != *check_i)
-                    throw runtime_error(*i + " doesn't match " + *check_i);
-            }
-        }
-        
         void ConstructIP1()
         {
             IP_RANGE i("192.168.1.1");
@@ -443,9 +457,9 @@ class ip_range : public TestFixture
         void Range2Cidr1()
         {
             IP_RANGE range("192.168.1.100-192.168.1.227");
-            vector<string> cidrs = range.to_cidr();
+            vector<IP_RANGE> cidrs = range.to_cidr();
             
-            vector<string> check_cidrs;
+            vector<IP_RANGE> check_cidrs;
             check_cidrs.push_back("192.168.1.100/30");
             check_cidrs.push_back("192.168.1.104/29");
             check_cidrs.push_back("192.168.1.112/28");
@@ -453,75 +467,70 @@ class ip_range : public TestFixture
             check_cidrs.push_back("192.168.1.192/27");
             check_cidrs.push_back("192.168.1.224/30");
 
-/*
-            cerr << "Range: " << range.to_string() << endl;
-            for(vector<string>::const_iterator i=cidrs.begin(), ie=cidrs.end(); i != ie; i++)
-                cerr << *i << endl;
-*/        
-            compare_vector(cidrs, check_cidrs);
+            CPPUNIT_ASSERT_EQUAL(check_cidrs,cidrs);
         }
 
         void Range2Cidr2()
         {
             IP_RANGE range("0.0.0.0-255.255.255.255");
-            vector<string> cidrs = range.to_cidr();
+            vector<IP_RANGE> cidrs = range.to_cidr();
             
-            vector<string> check_cidrs;
+            vector<IP_RANGE> check_cidrs;
             check_cidrs.push_back("0.0.0.0/0");
 
-            compare_vector(cidrs, check_cidrs);
+            CPPUNIT_ASSERT_EQUAL(check_cidrs,cidrs);
         }
 
         void Range2Cidr3()
         {
             IP_RANGE range("192.168.1.3");
-            vector<string> cidrs = range.to_cidr();
+            vector<IP_RANGE> cidrs = range.to_cidr();
             
-            vector<string> check_cidrs;
+            vector<IP_RANGE> check_cidrs;
             check_cidrs.push_back("192.168.1.3/32");
 
-            compare_vector(cidrs, check_cidrs);
+            CPPUNIT_ASSERT_EQUAL(check_cidrs,cidrs);
         }
 
         void Range2Cidr4()
         {
             IP_RANGE range("172.16.0.0/16");
-            vector<string> cidrs = range.to_cidr();
+            vector<IP_RANGE> cidrs = range.to_cidr();
             
-            vector<string> check_cidrs;
+            vector<IP_RANGE> check_cidrs;
             check_cidrs.push_back("172.16.0.0/16");
 
-            compare_vector(cidrs, check_cidrs);
+            CPPUNIT_ASSERT_EQUAL(check_cidrs,cidrs);
         }
 
         void Range2Cidr5()
         {
             IP_RANGE range(ip_type::NETWORK, "172.16.0.0", "255.255.0.0");
-            vector<string> cidrs = range.to_cidr();
+            vector<IP_RANGE> cidrs = range.to_cidr();
             
-            vector<string> check_cidrs;
+            vector<IP_RANGE> check_cidrs;
             check_cidrs.push_back("172.16.0.0/16");
 
-            compare_vector(cidrs, check_cidrs);
+            CPPUNIT_ASSERT_EQUAL(check_cidrs,cidrs);
         }
         void Range2Cidr6()
         {
             IP_RANGE range("192.168.1.0-192.168.2.0");
-            vector<string> cidrs = range.to_cidr();
+            vector<IP_RANGE> cidrs = range.to_cidr();
             
-            vector<string> check_cidrs;
+            vector<IP_RANGE> check_cidrs;
             check_cidrs.push_back("192.168.1.0/24");
             check_cidrs.push_back("192.168.2.0/32");
 
-            compare_vector(cidrs, check_cidrs);
+            CPPUNIT_ASSERT_EQUAL(check_cidrs,cidrs);
         }
 
         void Range2Cidr7()
         {
             IP_RANGE range("0.0.0.1-255.255.255.254");
-            vector<string> cidrs = range.to_cidr();
+            vector<IP_RANGE> cidrs = range.to_cidr();
             
-            vector<string> check_cidrs;
+            vector<IP_RANGE> check_cidrs;
             check_cidrs.push_back("0.0.0.1/32");
             check_cidrs.push_back("0.0.0.2/31");
             check_cidrs.push_back("0.0.0.4/30");
@@ -585,7 +594,7 @@ class ip_range : public TestFixture
             check_cidrs.push_back("255.255.255.252/31");
             check_cidrs.push_back("255.255.255.254/32");
 
-            compare_vector(cidrs, check_cidrs);
+            CPPUNIT_ASSERT_EQUAL(check_cidrs,cidrs);
         }
 };