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;
}
}
+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)
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;
{ 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;
// 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); }
#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);
CPPUNIT_TEST(Range2Cidr5);
CPPUNIT_TEST(Range2Cidr6);
CPPUNIT_TEST(Range2Cidr7);
-
+
CPPUNIT_TEST_SUITE_END();
{
}
- 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");
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");
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");
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);
}
};