From c24a8a9cbbf252c2bc1fafc7aee00247cf5f55fd Mon Sep 17 00:00:00 2001 From: Gerd v. Egidy Date: Wed, 25 Aug 2004 10:40:34 +0000 Subject: [PATCH] libi2ncommon: (gerd) add ip functions from libcnfcheck into libi2ncommon --- src/Makefile.am | 2 +- src/ip_type.hxx | 14 +++ src/ipfunc.cpp | 334 +++++++++++++++++++++++++++++++++++++++---------------- src/ipfunc.hxx | 61 ++++++++++- 4 files changed, 311 insertions(+), 100 deletions(-) create mode 100644 src/ip_type.hxx diff --git a/src/Makefile.am b/src/Makefile.am index 0f5bc55..4273e63 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -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 index 0000000..d13d87d --- /dev/null +++ b/src/ip_type.hxx @@ -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 diff --git a/src/ipfunc.cpp b/src/ipfunc.cpp index 7d88db8..62c8667 100644 --- a/src/ipfunc.cpp +++ b/src/ipfunc.cpp @@ -8,14 +8,238 @@ #include #include +#include #include #include 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<= 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< #include -unsigned ipfunc_turn_ip(unsigned int src); -std::string ipfunc_format_ip(unsigned int ip); -unsigned int ipfunc_netmask2cidr(unsigned int netmask); +#include +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); -- 1.7.1