From a0105b80c6b6066bdd3002e3b129d00cfabbf4c5 Mon Sep 17 00:00:00 2001 From: Gerd v. Egidy Date: Sat, 4 Sep 2004 22:36:15 +0000 Subject: [PATCH] libi2ncommon: (tomj) improve to_cidr() function (returns IP_RANGE now) --- src/ipfunc.cpp | 63 ++++++++++++++++++++++++++---------- src/ipfunc.hxx | 14 +++++++- test/ip_range.cpp | 91 +++++++++++++++++++++++++++++------------------------ 3 files changed, 107 insertions(+), 61 deletions(-) diff --git a/src/ipfunc.cpp b/src/ipfunc.cpp index bb9e547..626f9e7 100644 --- a/src/ipfunc.cpp +++ b/src/ipfunc.cpp @@ -17,10 +17,8 @@ using namespace std; using namespace ip_type; -#include - // 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 IP_RANGE::to_cidr(void) const +vector IP_RANGE::to_cidr(void) const { - vector cidrs; + vector 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; diff --git a/src/ipfunc.hxx b/src/ipfunc.hxx index dead12f..6f238aa 100644 --- a/src/ipfunc.hxx +++ b/src/ipfunc.hxx @@ -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 to_cidr(void) const; + + // returns the complete range in cidr blocks + std::vector to_cidr(void) const; unsigned int get_mask_bits() const { return calc_netmask_bits(mask); } diff --git a/test/ip_range.cpp b/test/ip_range.cpp index 037b0b4..b018d72 100644 --- a/test/ip_range.cpp +++ b/test/ip_range.cpp @@ -15,9 +15,36 @@ #include +namespace CppUnit +{ + +template<> +struct assertion_traits > +{ + static bool equal( const std::vector& x, const std::vector& y ) + { + return x == y; + } + + static std::string toString( const std::vector& x ) + { + std::ostringstream os; + + for (std::vector::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 &a, const vector &b) - { - if (a.size() != b.size()) - throw runtime_error("vector sizes don't match"); - - for(vector::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 cidrs = range.to_cidr(); + vector cidrs = range.to_cidr(); - vector check_cidrs; + vector 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::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 cidrs = range.to_cidr(); + vector cidrs = range.to_cidr(); - vector check_cidrs; + vector 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 cidrs = range.to_cidr(); + vector cidrs = range.to_cidr(); - vector check_cidrs; + vector 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 cidrs = range.to_cidr(); + vector cidrs = range.to_cidr(); - vector check_cidrs; + vector 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 cidrs = range.to_cidr(); + vector cidrs = range.to_cidr(); - vector check_cidrs; + vector 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 cidrs = range.to_cidr(); + vector cidrs = range.to_cidr(); - vector check_cidrs; + vector 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 cidrs = range.to_cidr(); + vector cidrs = range.to_cidr(); - vector check_cidrs; + vector 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); } }; -- 1.7.1