#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);