00001
00002
00003
00004
00005
00006
00007
00008
00009 static const char rcsid[] __attribute__((used)) = "$Id: IPPrefix.cpp 1243 2014-11-21 01:01:24Z sella $";
00010
00011 #include "IPPrefix.h"
00012 #include "../util/String.h"
00013 #include "../util/CommonMacro.h"
00014
00015 #include <string.h>
00016
00017 #define HASH_ALGO_INT1
00018
00019 using namespace sella::net;
00020 using namespace sella::util;
00021
00022 union __sockaddr_union {
00023 struct sockaddr_storage *ss;
00024 struct sockaddr *sa;
00025 struct sockaddr_in *sa_in;
00026 struct sockaddr_in6 *sa_in6;
00027 };
00028
00029 IPPrefix::IPPrefix(const IPAddress &address, uint8_t cidr) throw (AddressException) :
00030 address(address),
00031 cidr(cidr),
00032 mask{0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF},
00033 hcache(0)
00034 {
00035 this->address.applyCIDR(cidr);
00036
00037 generateMask();
00038 }
00039
00040 IPPrefix::IPPrefix(const std::string &address, uint8_t cidr) throw (AddressException) :
00041 address(address),
00042 cidr(cidr),
00043 mask{0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF},
00044 hcache(0)
00045 {
00046 this->address.applyCIDR(cidr);
00047
00048 generateMask();
00049 }
00050
00051 IPPrefix::IPPrefix(const std::string &prefix) throw (AddressException) :
00052 mask{0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF},
00053 hcache(0)
00054 {
00055 const auto &parts = String::split(prefix, "/");
00056
00057 if (parts.empty()) {
00058 THROW(AddressException, "unable to parse prefix: '%s' does not represent a valid IPv4 or IPv6 prefix", prefix.c_str());
00059 } else if (parts.size() == 1) {
00060 address = IPAddress(parts.at(0));
00061 cidr = (address.getFamily() == AF_INET) ? 32 : 128;
00062 } else {
00063 address = IPAddress(parts.at(0));
00064 cidr = std::stoi(parts.at(1));
00065 }
00066
00067 this->address.applyCIDR(cidr);
00068
00069 generateMask();
00070 }
00071
00072 IPPrefix::IPPrefix(const IPPrefix &other) throw () :
00073 address(other.address),
00074 cidr(other.cidr),
00075 scache(other.scache),
00076 hcache(other.hcache)
00077 {
00078 memcpy(mask, other.mask, sizeof(mask));
00079 }
00080
00081 IPPrefix::IPPrefix(const IPPrefix &&other) throw () :
00082 address(std::move(other.address)),
00083 cidr(other.cidr),
00084 scache(std::move(other.scache)),
00085 hcache(other.hcache)
00086 {
00087 memcpy(mask, other.mask, sizeof(mask));
00088 }
00089
00090 IPPrefix::~IPPrefix() throw () { }
00091
00092 IPPrefix& IPPrefix::operator=(const IPPrefix &other) throw () {
00093 if (this != &other) {
00094 this->address = other.address;
00095 this->cidr = other.cidr;
00096 memcpy(this->mask, other.mask, sizeof(mask));
00097 this->scache = other.scache;
00098 this->hcache = other.hcache;
00099 }
00100
00101 return *this;
00102 }
00103
00104 IPPrefix& IPPrefix::operator=(const IPPrefix &&other) throw () {
00105 if (this != &other) {
00106 this->address = std::move(other.address);
00107 this->cidr = other.cidr;
00108 memcpy(this->mask, other.mask, sizeof(mask));
00109 this->scache = std::move(other.scache);
00110 this->hcache = other.hcache;
00111 }
00112
00113 return *this;
00114 }
00115
00116 bool IPPrefix::operator==(const IPPrefix &other) const throw () {
00117 return (this->cidr == other.cidr) ? ((this->address == other.address) ? true : false) : false;
00118 }
00119
00120 bool IPPrefix::operator!=(const IPPrefix &other) const throw () {
00121 return !(*this == other);
00122 }
00123
00124 bool IPPrefix::operator>=(const IPPrefix &other) const throw () {
00125 return (this->address < other.address) ? false : ((this->address > other.address) ? true : (this->cidr >= other.cidr) ? true : false);
00126 }
00127
00128 bool IPPrefix::operator<=(const IPPrefix &other) const throw () {
00129 return (this->address > other.address) ? false : ((this->address < other.address) ? true : (this->cidr <= other.cidr) ? true : false);
00130 }
00131
00132 bool IPPrefix::operator>(const IPPrefix &other) const throw () {
00133 return (this->address > other.address) ? true : ((this->address < other.address) ? false : (this->cidr > other.cidr) ? true : false);
00134 }
00135
00136 bool IPPrefix::operator<(const IPPrefix &other) const throw () {
00137 return (this->address < other.address) ? true : ((this->address > other.address) ? false : (this->cidr < other.cidr) ? true : false);
00138 }
00139
00140 bool IPPrefix::operator<<(const IPPrefix &other) const throw () {
00141 return other.contains(*this, false);
00142 }
00143
00144 bool IPPrefix::operator<<=(const IPPrefix &other) const throw () {
00145 return other.contains(*this, true);
00146 }
00147
00148 bool IPPrefix::operator>>(const IPPrefix &other) const throw () {
00149 return this->contains(other, false);
00150 }
00151
00152 bool IPPrefix::operator>>=(const IPPrefix &other) const throw () {
00153 return this->contains(other, true);
00154 }
00155
00156 bool IPPrefix::operator<<(const IPAddress &other) const throw () {
00157 return !(this->contains(other, true));
00158 }
00159
00160 bool IPPrefix::operator<<=(const IPAddress &other) const throw () {
00161 return !(this->contains(other, false));
00162 }
00163
00164 bool IPPrefix::operator>>(const IPAddress &other) const throw () {
00165 return this->contains(other, false);
00166 }
00167
00168 bool IPPrefix::operator>>=(const IPAddress &other) const throw () {
00169 return this->contains(other, true);
00170 }
00171
00172 bool IPPrefix::contains(const IPPrefix &other, bool orEquals) const throw () {
00173 bool cmp;
00174
00175 if (this->getFamily() != other.getFamily()) {
00176 return false;
00177 }
00178
00179 if (this->getFamily() == AF_INET) {
00180 const uint32_t &a = this->address.getIPv4AddressStructure().s_addr;
00181 const uint32_t &b = other.address.getIPv4AddressStructure().s_addr;
00182 const uint32_t &m = this->mask[0];
00183
00184 cmp = ((ntohl(a) & m) == (ntohl(b) & m));
00185 } else {
00186 const uint64_t *a = (const uint64_t*) this->address.getIPv6AddressStructure().s6_addr;
00187 const uint64_t *b = (const uint64_t*) other.address.getIPv6AddressStructure().s6_addr;
00188 const uint64_t *m = (const uint64_t*) this->mask;
00189
00190 cmp = ((ntohll(a[0]) & m[0]) == (ntohll(b[0]) & m[0]) && (ntohll(a[1]) & m[1]) == (ntohll(b[1]) & m[1]));
00191 }
00192
00193 return (orEquals) ? cmp : (cmp && this->cidr != other.cidr);
00194 }
00195
00196 bool IPPrefix::contains(const IPAddress &other, bool orEquals) const throw () {
00197 bool cmp;
00198 uint8_t ocidr;
00199
00200 if (this->getFamily() != other.getFamily()) {
00201 return false;
00202 }
00203
00204 if (this->getFamily() == AF_INET) {
00205 const uint32_t &a = this->address.getIPv4AddressStructure().s_addr;
00206 const uint32_t &b = other.getIPv4AddressStructure().s_addr;
00207 const uint32_t &m = this->mask[0];
00208
00209 ocidr = 32;
00210 cmp = ((ntohl(a) & m) == (ntohl(b) & m));
00211 } else {
00212 const uint64_t *a = (const uint64_t*) this->address.getIPv6AddressStructure().s6_addr;
00213 const uint64_t *b = (const uint64_t*) other.getIPv6AddressStructure().s6_addr;
00214 const uint64_t *m = (const uint64_t*) this->mask;
00215
00216 ocidr = 128;
00217 cmp = ((ntohll(a[0]) & m[0]) == (ntohll(b[0]) & m[0]) && (ntohll(a[1]) & m[1]) == (ntohll(b[1]) & m[1]));
00218 }
00219
00220 return (orEquals) ? cmp : (cmp && this->cidr != ocidr);
00221 }
00222
00223 int IPPrefix::getFamily(void) const throw () {
00224 return address.getFamily();
00225 }
00226
00227 const IPAddress& IPPrefix::getIPAddress(void) const throw () {
00228 return this->address;
00229 }
00230
00231
00232 uint8_t IPPrefix::getCIDR(void) const throw () {
00233 return this->cidr;
00234 }
00235
00236 IPAddress IPPrefix::getNetmask(void) const throw () {
00237 if (getFamily() == AF_INET) {
00238 return IPAddress("255.255.255.255", IPAddress::IPv4Required, cidr);
00239 } else {
00240 return IPAddress("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", IPAddress::IPv6Required, cidr);
00241 }
00242 }
00243
00244 IPAddress IPPrefix::getInverseMask(void) const throw () {
00245 return ~(getNetmask());
00246 }
00247
00248 IPAddress IPPrefix::getNetwork(void) const throw () {
00249 return getIPAddress();
00250 }
00251
00252 IPAddress::vector IPPrefix::getIPAddresses(bool usable) const throw () {
00253 IPAddress::vector addresses;
00254 IPAddress address = getIPAddress();
00255
00256 if (usable) {
00257 if (getFamily() == AF_INET && cidr < 31) {
00258 ++address;
00259 } else if (getFamily() == AF_INET6 && cidr < 127) {
00260 ++address;
00261 }
00262 }
00263
00264 while (contains(address, true)) {
00265 addresses.push_back(address++);
00266 }
00267
00268 if (usable) {
00269 if (getFamily() == AF_INET && cidr < 31) {
00270 addresses.pop_back();
00271 } else if (getFamily() == AF_INET6 && cidr < 127) {
00272 addresses.pop_back();
00273 }
00274 }
00275
00276 return addresses;
00277 }
00278
00279 const std::string& IPPrefix::str(void) const throw (AddressException) {
00280 if (scache.empty()) {
00281 scache = String::sprintf("%s/%u", this->address.c_str(), cidr);
00282 }
00283
00284 return scache;
00285 }
00286
00287 const char* IPPrefix::c_str(void) const throw (AddressException) {
00288 return str().c_str();
00289 }
00290
00291 uint32_t IPPrefix::getU32(void) const throw () {
00292 uint32_t c = cidr;
00293
00294 return (address.getU32() ^ (c | c << 4 | c << 8 | c << 12 | c << 16 | c << 20 | c << 24 | c << 28));
00295 }
00296
00297 uint32_t IPPrefix::getHash(void) const throw () {
00298 if (hcache != 0) {
00299 return hcache;
00300 }
00301
00302 #if defined HASH_ALGO_INT1
00303 uint32_t k = getU32();
00304
00305 hcache = ((k & 0xF0F0F0F0) >> 4) | ((k & 0x0F0F0F0F) << 4);
00306 #elif defined HASH_ALGO_INT2
00307 uint32_t k = getU32();
00308
00309 hcache = (k<<16)^(k>>16)^k;
00310 #elif defined HASH_ALGO_INT3
00311 hcache = getU32();
00312 #else
00313 #error No hash algo selected.
00314 #endif
00315
00316 return hcache;
00317 }
00318
00319 bool IPPrefix::empty(void) const throw () {
00320 return (address.empty());
00321 }
00322
00323 void IPPrefix::clear(void) throw () {
00324 address.clear();
00325 cidr = 0;
00326 mask = {0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF};
00327 scache.clear();
00328 hcache = 0;
00329 }
00330
00331 const IPPrefix::shared IPPrefix::shared_ptr(const IPAddress &address, uint8_t cidr) throw (AddressException) {
00332 return std::make_shared<IPPrefix>(address, cidr);
00333 }
00334
00335 const IPPrefix::shared IPPrefix::shared_ptr(const std::string &address, uint8_t cidr) throw (AddressException) {
00336 return std::make_shared<IPPrefix>(address, cidr);
00337 }
00338
00339 const IPPrefix::shared IPPrefix::shared_ptr(const std::string &prefix) throw (AddressException) {
00340 return std::make_shared<IPPrefix>(prefix);
00341 }
00342
00343 void IPPrefix::generateMask(void) throw () {
00344 if (address.getFamily() == AF_INET) {
00345 if (cidr == 0) {
00346 mask[0] = 0;
00347 } else {
00348 mask[0] = 0xFFFFFFFF >> (32 - cidr) << (32 - cidr);
00349 }
00350
00351
00352 } else {
00353 for (int i = 4; i > cidr / 32 - 1; i--) {
00354 if (i == cidr / 32 && cidr % 32 != 0) {
00355 mask[i] = 0xFFFFFFFF >> (32 - cidr % 32) << (32 - cidr % 32);
00356 } else {
00357 mask[i] = 0;
00358 }
00359 }
00360
00361
00362 }
00363 }
00364
00365
00366
00367