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)
{
}
else if (t==NETWORK)
{
- if(!inet_aton(ip.c_str(),&ia_ip1) || !inet_aton(mask_or_end.c_str(),&ia_ip2))
+ // TODO: Better IP checks: "16" != "0.0.0.16"
+ if(!inet_aton(ip.c_str(),&ia_ip1))
throw runtime_error("invalid IP given");
+ // Check if mask is in cidr notation
+ if (mask_or_end.find(".") == string::npos) {
+ unsigned int calc_mask = 0;
+ istringstream in(mask_or_end);
+ in >> calc_mask;
+
+ if(calc_mask > 32)
+ throw runtime_error("invalid cidr mask given");
+
+ ia_ip2.s_addr = calc_netmask_from_cidr(calc_mask);
+ } else
+ if (!inet_aton(mask_or_end.c_str(),&ia_ip2))
+ throw runtime_error("invalid IP given");
+
this->ip=ia_ip1.s_addr;
this->mask=ia_ip2.s_addr;
return output;
}
+vector<string> IP_RANGE::to_cidr(void) const
+{
+ vector<string> 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) {
+ // 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");
+ } 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());
+
+ cidr_addr += (1 << bit);
+ bit = 0;
+ mask = 0;
+ } else {
+ bit++;
+ }
+ }
+ }
+ }
+
+ return cidrs;
+}
+
unsigned int IP_RANGE::turn_ip(unsigned int src)
{
int dst;
unsigned int IP_RANGE::calc_netmask_bits(unsigned int netmask)
{
+ netmask = turn_ip(netmask);
+
switch (netmask)
{
case 0x00000000:
}
}
+unsigned int IP_RANGE::calc_netmask_from_cidr(unsigned int cidr)
+{
+ unsigned int rtn=0;
+
+ switch (cidr)
+ {
+ case 0:
+ rtn=0x00000000;
+ break;
+ case 1:
+ rtn=0x80000000;
+ break;
+ case 2:
+ rtn=0xC0000000;
+ break;
+ case 3:
+ rtn=0xE0000000;
+ break;
+ case 4:
+ rtn=0xE0000000;
+ break;
+ case 5:
+ rtn=0xF8000000;
+ break;
+ case 6:
+ rtn=0xFC000000;
+ break;
+ case 7:
+ rtn=0xFE000000;
+ break;
+ case 8:
+ rtn=0xFF000000;
+ break;
+ case 9:
+ rtn=0xFF800000;
+ break;
+ case 10:
+ rtn=0xFFC00000;
+ break;
+ case 11:
+ rtn=0xFFE00000;
+ break;
+ case 12:
+ rtn=0xFFF00000;
+ break;
+ case 13:
+ rtn=0xFFF80000;
+ break;
+ case 14:
+ rtn=0xFFFC0000;
+ break;
+ case 15:
+ rtn=0xFFFE0000;
+ break;
+ case 16:
+ rtn=0xFFFF0000;
+ break;
+ case 17:
+ rtn=0xFFFF8000;
+ break;
+ case 18:
+ rtn=0xFFFFC000;
+ break;
+ case 19:
+ rtn=0xFFFFE000;
+ break;
+ case 20:
+ rtn=0xFFFFF000;
+ break;
+ case 21:
+ rtn=0xFFFFF800;
+ break;
+ case 22:
+ rtn=0xFFFFFC00;
+ break;
+ case 23:
+ rtn=0xFFFFFE00;
+ break;
+ case 24:
+ rtn=0xFFFFFF00;
+ break;
+ case 25:
+ rtn=0xFFFFFF80;
+ break;
+ case 26:
+ rtn=0xFFFFFFC0;
+ break;
+ case 27:
+ rtn=0xFFFFFFE0;
+ break;
+ case 28:
+ rtn=0xFFFFFFF0;
+ break;
+ case 29:
+ rtn=0xFFFFFFF8;
+ break;
+ case 30:
+ rtn=0xFFFFFFFC;
+ break;
+ case 31:
+ rtn=0xFFFFFFFE;
+ break;
+ case 32:
+ default:
+ rtn=0xFFFFFFFF;
+ }
+
+ return turn_ip(rtn);
+}
+
std::string IP_RANGE::ip_string(unsigned int ip)
{
struct in_addr ia_ip;
else
return buffer;
}
-
CPPUNIT_TEST(ConstructIP2);
CPPUNIT_TEST(ConstructNet1);
CPPUNIT_TEST(ConstructNet2);
+ CPPUNIT_TEST(ConstructNet3);
CPPUNIT_TEST(ConstructRange1);
CPPUNIT_TEST(ConstructRange2);
CPPUNIT_TEST(ConstructRangeSwap);
CPPUNIT_TEST(OperatorPlus2);
CPPUNIT_TEST(OperatorPlusOverflow);
CPPUNIT_TEST(OperatorMinus);
+ CPPUNIT_TEST(NetmaskToBits1);
+ CPPUNIT_TEST(NetmaskToBits2);
+ CPPUNIT_TEST(NetmaskToBits3);
+ CPPUNIT_TEST(NetmaskToBits4);
+ CPPUNIT_TEST(Range2Cidr1);
+ CPPUNIT_TEST(Range2Cidr2);
+ CPPUNIT_TEST(Range2Cidr3);
+ CPPUNIT_TEST(Range2Cidr4);
+ CPPUNIT_TEST(Range2Cidr5);
+ CPPUNIT_TEST(Range2Cidr6);
+ CPPUNIT_TEST(Range2Cidr7);
CPPUNIT_TEST_SUITE_END();
+
+
public:
void setUp()
{
{
}
+ 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");
CPPUNIT_ASSERT_EQUAL(string("192.168.1.0/255.255.255.0"),i.to_string());
}
+ void ConstructNet3()
+ {
+ IP_RANGE i("172.16.0.0/16");
+ CPPUNIT_ASSERT_EQUAL(string("172.16.0.0/255.255.0.0"),i.to_string());
+ }
+
void ConstructRange1()
{
IP_RANGE i("192.168.1.5-192.168.3.1");
CPPUNIT_ASSERT_EQUAL(256,a-b);
}
+
+ void NetmaskToBits1()
+ {
+ IP_RANGE a("255.255.255.255");
+ int bits = a.calc_netmask_bits(a.get_base());
+ CPPUNIT_ASSERT_EQUAL(32,bits);
+ }
+
+ void NetmaskToBits2()
+ {
+ IP_RANGE a("255.255.255.0");
+ int bits = a.calc_netmask_bits(a.get_base());
+ CPPUNIT_ASSERT_EQUAL(24,bits);
+ }
+
+ void NetmaskToBits3()
+ {
+ IP_RANGE a("255.255.0.0");
+ int bits = a.calc_netmask_bits(a.get_base());
+ CPPUNIT_ASSERT_EQUAL(16,bits);
+ }
+
+ void NetmaskToBits4()
+ {
+ IP_RANGE a("255.0.0.0");
+ int bits = a.calc_netmask_bits(a.get_base());
+ CPPUNIT_ASSERT_EQUAL(8,bits);
+ }
+ void Range2Cidr1()
+ {
+ IP_RANGE range("192.168.1.100-192.168.1.227");
+ vector<string> cidrs = range.to_cidr();
+
+ vector<string> 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.128/26");
+ 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);
+ }
+
+ void Range2Cidr2()
+ {
+ IP_RANGE range("0.0.0.0-255.255.255.255");
+ vector<string> cidrs = range.to_cidr();
+
+ vector<string> check_cidrs;
+ check_cidrs.push_back("0.0.0.0/0");
+
+ compare_vector(cidrs, check_cidrs);
+ }
+
+ void Range2Cidr3()
+ {
+ IP_RANGE range("192.168.1.3");
+ vector<string> cidrs = range.to_cidr();
+
+ vector<string> check_cidrs;
+ check_cidrs.push_back("192.168.1.3/32");
+
+ compare_vector(cidrs, check_cidrs);
+ }
+
+ void Range2Cidr4()
+ {
+ IP_RANGE range("172.16.0.0/16");
+ vector<string> cidrs = range.to_cidr();
+
+ vector<string> check_cidrs;
+ check_cidrs.push_back("172.16.0.0/16");
+
+ compare_vector(cidrs, check_cidrs);
+ }
+
+ void Range2Cidr5()
+ {
+ IP_RANGE range(ip_type::NETWORK, "172.16.0.0", "255.255.0.0");
+ vector<string> cidrs = range.to_cidr();
+
+ vector<string> check_cidrs;
+ check_cidrs.push_back("172.16.0.0/16");
+
+ compare_vector(cidrs, check_cidrs);
+ }
+ void Range2Cidr6()
+ {
+ IP_RANGE range("192.168.1.0-192.168.2.0");
+ vector<string> cidrs = range.to_cidr();
+
+ vector<string> 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);
+ }
+
+ void Range2Cidr7()
+ {
+ IP_RANGE range("0.0.0.1-255.255.255.254");
+ vector<string> cidrs = range.to_cidr();
+
+ vector<string> 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("0.0.0.8/29");
+ check_cidrs.push_back("0.0.0.16/28");
+ check_cidrs.push_back("0.0.0.32/27");
+ check_cidrs.push_back("0.0.0.64/26");
+ check_cidrs.push_back("0.0.0.128/25");
+ check_cidrs.push_back("0.0.1.0/24");
+ check_cidrs.push_back("0.0.2.0/23");
+ check_cidrs.push_back("0.0.4.0/22");
+ check_cidrs.push_back("0.0.8.0/21");
+ check_cidrs.push_back("0.0.16.0/20");
+ check_cidrs.push_back("0.0.32.0/19");
+ check_cidrs.push_back("0.0.64.0/18");
+ check_cidrs.push_back("0.0.128.0/17");
+ check_cidrs.push_back("0.1.0.0/16");
+ check_cidrs.push_back("0.2.0.0/15");
+ check_cidrs.push_back("0.4.0.0/14");
+ check_cidrs.push_back("0.8.0.0/13");
+ check_cidrs.push_back("0.16.0.0/12");
+ check_cidrs.push_back("0.32.0.0/11");
+ check_cidrs.push_back("0.64.0.0/10");
+ check_cidrs.push_back("0.128.0.0/9");
+ check_cidrs.push_back("1.0.0.0/8");
+ check_cidrs.push_back("2.0.0.0/7");
+ check_cidrs.push_back("4.0.0.0/6");
+ check_cidrs.push_back("8.0.0.0/5");
+ check_cidrs.push_back("16.0.0.0/4");
+ check_cidrs.push_back("32.0.0.0/3");
+ check_cidrs.push_back("64.0.0.0/2");
+ check_cidrs.push_back("128.0.0.0/2");
+ check_cidrs.push_back("192.0.0.0/3");
+ check_cidrs.push_back("224.0.0.0/4");
+ check_cidrs.push_back("240.0.0.0/5");
+ check_cidrs.push_back("248.0.0.0/6");
+ check_cidrs.push_back("252.0.0.0/7");
+ check_cidrs.push_back("254.0.0.0/8");
+ check_cidrs.push_back("255.0.0.0/9");
+ check_cidrs.push_back("255.128.0.0/10");
+ check_cidrs.push_back("255.192.0.0/11");
+ check_cidrs.push_back("255.224.0.0/12");
+ check_cidrs.push_back("255.240.0.0/13");
+ check_cidrs.push_back("255.248.0.0/14");
+ check_cidrs.push_back("255.252.0.0/15");
+ check_cidrs.push_back("255.254.0.0/16");
+ check_cidrs.push_back("255.255.0.0/17");
+ check_cidrs.push_back("255.255.128.0/18");
+ check_cidrs.push_back("255.255.192.0/19");
+ check_cidrs.push_back("255.255.224.0/20");
+ check_cidrs.push_back("255.255.240.0/21");
+ check_cidrs.push_back("255.255.248.0/22");
+ check_cidrs.push_back("255.255.252.0/23");
+ check_cidrs.push_back("255.255.254.0/24");
+ check_cidrs.push_back("255.255.255.0/25");
+ check_cidrs.push_back("255.255.255.128/26");
+ check_cidrs.push_back("255.255.255.192/27");
+ check_cidrs.push_back("255.255.255.224/28");
+ check_cidrs.push_back("255.255.255.240/29");
+ check_cidrs.push_back("255.255.255.248/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_TEST_SUITE_REGISTRATION(ip_range);