libi2ncommon: (gerd) add ip functions from libcnfcheck into libi2ncommon
authorGerd v. Egidy <gerd.von.egidy@intra2net.com>
Wed, 25 Aug 2004 10:40:34 +0000 (10:40 +0000)
committerGerd v. Egidy <gerd.von.egidy@intra2net.com>
Wed, 25 Aug 2004 10:40:34 +0000 (10:40 +0000)
src/Makefile.am
src/ip_type.hxx [new file with mode: 0644]
src/ipfunc.cpp
src/ipfunc.hxx

index 0f5bc55..4273e63 100644 (file)
@@ -4,7 +4,7 @@ INCLUDES = -I$(top_srcdir)/src @LIBGETTEXT_CFLAGS@ $(all_includes)
 
 # the library search path.
 lib_LTLIBRARIES =  libi2ncommon.la
-include_HEADERS = insocketstream.hxx oftmpstream.hxx pipestream.hxx filefunc.hxx stringfunc.hxx timefunc.hxx ipfunc.hxx
+include_HEADERS = insocketstream.hxx oftmpstream.hxx pipestream.hxx filefunc.hxx stringfunc.hxx timefunc.hxx ipfunc.hxx ip_type.hxx
 libi2ncommon_la_SOURCES = oftmpstream.cpp ipfunc.cpp timefunc.cpp filefunc.cpp stringfunc.cpp
 
 # Note:  If you specify a:b:c as the version in the next line,
diff --git a/src/ip_type.hxx b/src/ip_type.hxx
new file mode 100644 (file)
index 0000000..d13d87d
--- /dev/null
@@ -0,0 +1,14 @@
+/***************************************************************************
+ *   Copyright (C) 2004 by Intra2net AG                                    *
+ *   info@intra2net.com                                                    *
+ ***************************************************************************/
+
+#ifndef __IP_TYPE
+#define __IP_TYPE
+
+namespace ip_type
+{
+    enum type { IP, RANGE, NETWORK };
+};
+
+#endif
index 7d88db8..62c8667 100644 (file)
 
 #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;
@@ -29,20 +253,10 @@ unsigned ipfunc_turn_ip(unsigned int 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:
@@ -113,88 +327,16 @@ unsigned int ipfunc_netmask2cidr(unsigned int netmask) {
     }
 }
 
-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;
 }
 
index a2f08e3..a4e2a24 100644 (file)
 #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);