#include <string>
#include <sstream>
+#include <stdexcept>
#include <arpa/inet.h>
#include <ipfunc.hxx>
using namespace std;
+using namespace ip_type;
-unsigned ipfunc_turn_ip(unsigned int src)
+string CalculateNetworkAddresses (int mode, const string &ip, const string &netmask)
+{
+ int IP[4];
+ int NETMASK[4];
+ int OUTPUT[4];
+
+ string rtn;
+
+ try {
+ string::size_type base = 0;
+ string::size_type pos = 0;
+
+ // split ip
+ for (int i = 0; i < 4; i++) {
+ pos = ip.find(".", base);
+
+ if (pos == string::npos)
+ pos = ip.length();
+ if (pos != string::npos && pos-base > 0) {
+ // get single IP fragment and convert to integer
+ string ipfrag (ip, base, pos-base);
+ istringstream in(ipfrag);
+ int tmp;
+ if (!in.eof() && in >> tmp)
+ IP[i] = tmp;
+ }
+
+ // fix offset to leave out the "."
+ base = pos+1;
+ }
+
+ base = 0;
+ pos = 0;
+
+ // split netmask
+ for (int i = 0; i < 4; i++) {
+ pos = netmask.find(".", base);
+
+ if (pos == string::npos)
+ pos = netmask.length();
+ if (pos != string::npos && pos-base > 0) {
+ // get single IP fragment and convert to integer
+ string ipfrag (netmask, base, pos-base);
+ istringstream in(ipfrag);
+ int tmp;
+ if (!in.eof() && in >> tmp)
+ NETMASK[i] = tmp;
+ }
+
+ // fix offset to leave out the "."
+ base = pos+1;
+ }
+ } catch (...) {}
+
+ if (mode == 0) { // get network-base-address (by ANDing ip and netmask)
+ for (int i = 0; i < 4; i++)
+ OUTPUT[i] = IP[i]&NETMASK[i];
+ } else { // calculate broadcast address
+ /*
+ how it works:
+ -the broadcast address is an address with all host bits set
+
+ -check all netmask bits -> if the bit is cleared -> bit is host bit
+ -set all host bits in the IP adress to 1
+ */
+
+ // precopy IP to output
+ for (int i = 0; i < 4; i++)
+ OUTPUT[i] = IP[i];
+
+ for (int i = 0; i < 4; i++)
+ for (int j = 0; j < 8; j++) {
+ if (!(NETMASK[i]&1<<j)) // bit cleared?
+ OUTPUT[i] = OUTPUT[i]|1<<j; // set host bit
+ }
+ }
+
+ // convert final address back to string
+ ostringstream out;
+ out << OUTPUT[0] << "." << OUTPUT[1] << "." << OUTPUT[2] << "." << OUTPUT[3];
+ rtn = out.str();
+
+ return rtn;
+}
+
+// can decode IP, IP-IP (as range) and IP/MASK (as network)
+IP_RANGE::IP_RANGE(const std::string& ip)
+{
+ int delim_pos;
+ struct in_addr ia_ip1, ia_ip2;
+
+ if ((delim_pos=ip.find('/')) != string::npos ||
+ (delim_pos=ip.find('-')) != string::npos)
+ {
+ if (delim_pos+1 >= ip.size())
+ throw runtime_error("invalid IP given");
+
+ if (ip.at(delim_pos) == '/')
+ t=NETWORK;
+ else
+ t=RANGE;
+
+ load(t,ip.substr(0,delim_pos),ip.substr(delim_pos+1));
+ }
+ else
+ {
+ load(IP,ip,"");
+ }
+}
+
+void IP_RANGE::load(type t, const std::string& ip, const std::string& mask_or_end)
+{
+ struct in_addr ia_ip1, ia_ip2;
+
+ this->t=t;
+
+ if (t==IP)
+ {
+ if(!inet_aton(ip.c_str(),&ia_ip1))
+ throw runtime_error("invalid IP given");
+
+ this->ip=ia_ip1.s_addr;
+ this->mask=0xFFFFFFFF;
+ this->end=this->ip;
+ }
+ else if (t==NETWORK)
+ {
+ if(!inet_aton(ip.c_str(),&ia_ip1) || !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;
+
+ // 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)
+ {
+ if(!inet_aton(ip.c_str(),&ia_ip1) || !inet_aton(mask_or_end.c_str(),&ia_ip2))
+ throw runtime_error("invalid IP given");
+
+ this->ip=ia_ip1.s_addr;
+ this->end=ia_ip2.s_addr;
+ }
+}
+
+bool IP_RANGE::is_within(const IP_RANGE& a) const
+{
+ if (t != RANGE && a.t != RANGE)
+ {
+ // mask checking possible
+ if ((ip & a.mask) == a.ip && mask >= a.mask)
+ return true;
+ }
+ else
+ {
+ // no mask checking since we have a range somewhere
+ // use turn_ip because of network byte order
+ if (turn_ip(ip) >= turn_ip(a.ip) && turn_ip(end) <= turn_ip(a.end))
+ return true;
+ }
+
+ return false;
+}
+
+bool IP_RANGE::overlapping(const IP_RANGE& a) const
+{
+ if (t != RANGE && a.t != RANGE)
+ {
+ // mask checking possible
+ if ((ip & a.mask) == a.ip ||
+ (a.ip & mask) == ip)
+ return true;
+ }
+ else
+ {
+ // no mask checking since we have a range somewhere
+ // use turn_ip because of network byte order
+ if ((turn_ip(ip) >= turn_ip(a.ip) && turn_ip(ip) <= turn_ip(a.end)) ||
+ (turn_ip(a.ip) >= turn_ip(ip) && turn_ip(a.ip) <= turn_ip(end)))
+ return true;
+ }
+
+ return false;
+}
+
+std::string IP_RANGE::to_string(void) const
+{
+ struct in_addr ia_ip;
+ static const int bufsize=16;
+ char buffer[bufsize];
+ string output;
+
+ ia_ip.s_addr=ip;
+ if (!inet_ntop(AF_INET,&ia_ip,buffer,bufsize))
+ return "";
+
+ output=buffer;
+
+ if (t==NETWORK)
+ {
+ ia_ip.s_addr=mask;
+ if (!inet_ntop(AF_INET,&ia_ip,buffer,bufsize))
+ return "";
+
+ output=output+"/"+buffer;
+ }
+ else if (t==RANGE)
+ {
+ ia_ip.s_addr=end;
+ if (!inet_ntop(AF_INET,&ia_ip,buffer,bufsize))
+ return "";
+
+ output=output+"-"+buffer;
+ }
+
+ return output;
+}
+
+unsigned int IP_RANGE::turn_ip(unsigned int src)
{
int dst;
char* si=(char*)&src;
return dst;
}
-std::string ipfunc_format_ip(unsigned int ip)
+unsigned int IP_RANGE::calc_netmask_bits(unsigned int netmask)
{
- char buf[16]; // XXXyXXXyXXXyXXX + \0 termination
- memset (buf, 16, 0);
-
- ip = ipfunc_turn_ip(ip);
- unsigned char *p = (unsigned char*)&ip;
- snprintf(buf, 16, "%d.%d.%d.%d", (unsigned char)p[0], (unsigned char)p[1], (unsigned char)p[2], (unsigned char)p[3]);
-
- return (string(buf));
-}
-
-unsigned int ipfunc_netmask2cidr(unsigned int netmask) {
- switch (netmask) {
+ switch (netmask)
+ {
case 0x00000000:
return 0;
case 0x80000000:
}
}
-string CalculateNetworkAddresses (int mode, const string &ip, const string &netmask)
+std::string IP_RANGE::ip_string(unsigned int ip)
{
- int IP[4];
- int NETMASK[4];
- int OUTPUT[4];
-
- string rtn;
-
- try {
- string::size_type base = 0;
- string::size_type pos = 0;
-
- // split ip
- for (int i = 0; i < 4; i++) {
- pos = ip.find(".", base);
-
- if (pos == string::npos)
- pos = ip.length();
- if (pos != string::npos && pos-base > 0) {
- // get single IP fragment and convert to integer
- string ipfrag (ip, base, pos-base);
- istringstream in(ipfrag);
- int tmp;
- if (!in.eof() && in >> tmp)
- IP[i] = tmp;
- }
-
- // fix offset to leave out the "."
- base = pos+1;
- }
-
- base = 0;
- pos = 0;
-
- // split netmask
- for (int i = 0; i < 4; i++) {
- pos = netmask.find(".", base);
-
- if (pos == string::npos)
- pos = netmask.length();
- if (pos != string::npos && pos-base > 0) {
- // get single IP fragment and convert to integer
- string ipfrag (netmask, base, pos-base);
- istringstream in(ipfrag);
- int tmp;
- if (!in.eof() && in >> tmp)
- NETMASK[i] = tmp;
- }
-
- // fix offset to leave out the "."
- base = pos+1;
- }
- } catch (...) {}
-
- if (mode == 0) { // get network-base-address (by ANDing ip and netmask)
- for (int i = 0; i < 4; i++)
- OUTPUT[i] = IP[i]&NETMASK[i];
- } else { // calculate broadcast address
- /*
- how it works:
- -the broadcast address is an address with all host bits set
-
- -check all netmask bits -> if the bit is cleared -> bit is host bit
- -set all host bits in the IP adress to 1
- */
-
- // precopy IP to output
- for (int i = 0; i < 4; i++)
- OUTPUT[i] = IP[i];
-
- for (int i = 0; i < 4; i++)
- for (int j = 0; j < 8; j++) {
- if (!(NETMASK[i]&1<<j)) // bit cleared?
- OUTPUT[i] = OUTPUT[i]|1<<j; // set host bit
- }
- }
-
- // convert final address back to string
- ostringstream out;
- out << OUTPUT[0] << "." << OUTPUT[1] << "." << OUTPUT[2] << "." << OUTPUT[3];
- rtn = out.str();
-
- return rtn;
+ struct in_addr ia_ip;
+ static const int bufsize=16;
+ char buffer[bufsize];
+
+ ia_ip.s_addr=ip;
+ if (!inet_ntop(AF_INET,&ia_ip,buffer,bufsize))
+ return "";
+ else
+ return buffer;
}
#include <map>
#include <set>
-unsigned ipfunc_turn_ip(unsigned int src);
-std::string ipfunc_format_ip(unsigned int ip);
-unsigned int ipfunc_netmask2cidr(unsigned int netmask);
+#include <ip_type.hxx>
+class IP_RANGE
+{
+ private:
+ unsigned int ip;
+ unsigned int mask;
+ unsigned int end;
+ ip_type::type t;
+
+ public:
+ // the constructors throw runtime_error if the ip is invalid
+ 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(ip_type::type t, const std::string& ip, const std::string& mask_or_end="")
+ { load(t,ip,mask_or_end); }
+ void load(ip_type::type t, const std::string& ip, const std::string& mask_or_end="");
+
+ 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;
+
+ unsigned int get_mask_bits() const
+ { return calc_netmask_bits(mask); }
+ unsigned int get_broadcast() const
+ { return end; }
+ unsigned int get_base() const
+ { return ip; }
+
+ // static IP utility functions
+ static unsigned int turn_ip(unsigned int src);
+ static unsigned int calc_netmask_bits(unsigned int mask);
+ static std::string ip_string(unsigned int ip);
+};
+
+// DEPRECATED!!! use IP_RANGE instead
+inline unsigned ipfunc_turn_ip(unsigned int src)
+{
+ return IP_RANGE::turn_ip(src);
+}
+
+// DEPRECATED!!! use IP_RANGE instead
+inline unsigned int ipfunc_netmask2cidr(unsigned int netmask)
+{
+ return IP_RANGE::calc_netmask_bits(netmask);
+}
+
+// DEPRECATED!!! use IP_RANGE instead
+inline std::string ipfunc_format_ip(unsigned int ip)
+{
+ return IP_RANGE::ip_string(ip);
+}
+
+// DEPRECATED!!! use IP_RANGE instead
// mode 0: get network-base-address, other: broadcast-address
std::string CalculateNetworkAddresses (int mode, const std::string &ip, const std::string &netmask);