|
xorp
|
00001 // -*- c-basic-offset: 4; tab-width: 8; indent-tabs-mode: t -*- 00002 // vim:set sts=4 ts=8: 00003 00004 // Copyright (c) 2001-2011 XORP, Inc and Others 00005 // 00006 // This program is free software; you can redistribute it and/or modify 00007 // it under the terms of the GNU Lesser General Public License, Version 00008 // 2.1, June 1999 as published by the Free Software Foundation. 00009 // Redistribution and/or modification of this program under the terms of 00010 // any other version of the GNU Lesser General Public License is not 00011 // permitted. 00012 // 00013 // This program is distributed in the hope that it will be useful, but 00014 // WITHOUT ANY WARRANTY; without even the implied warranty of 00015 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For more details, 00016 // see the GNU Lesser General Public License, Version 2.1, a copy of 00017 // which can be found in the XORP LICENSE.lgpl file. 00018 // 00019 // XORP, Inc, 2953 Bunker Hill Lane, Suite 204, Santa Clara, CA 95054, USA; 00020 // http://xorp.net 00021 00022 // $XORP: xorp/libxorp/ipnet.hh,v 1.38 2009/01/05 18:30:57 jtc Exp $ 00023 00024 #ifndef __LIBXORP_IPNET_HH__ 00025 #define __LIBXORP_IPNET_HH__ 00026 00027 #include "xorp.h" 00028 #include "exceptions.hh" 00029 #include "c_format.hh" 00030 #include "range.hh" 00031 #include "utils.hh" 00032 #include "ipv4.hh" 00033 #include "ipv6.hh" 00034 00040 template <class A> 00041 class IPNet { 00042 public: 00048 IPNet() : _prefix_len(0) {} 00049 00057 IPNet(const A& a, uint8_t prefix_len) throw (InvalidNetmaskLength) 00058 : _masked_addr(a), _prefix_len(prefix_len) 00059 { 00060 if (prefix_len > A::addr_bitlen()) 00061 xorp_throw(InvalidNetmaskLength, prefix_len); 00062 _masked_addr = a.mask_by_prefix_len(prefix_len); 00063 } 00064 00071 IPNet(const char *from_cstring) 00072 throw (InvalidString, InvalidNetmaskLength) 00073 { 00074 initialize_from_string(from_cstring); 00075 } 00076 00082 IPNet(const IPNet& n) { 00083 _masked_addr = n.masked_addr(); 00084 _prefix_len = n.prefix_len(); 00085 } 00086 00093 IPNet& operator=(const IPNet& n) { 00094 _masked_addr = n.masked_addr(); 00095 _prefix_len = n.prefix_len(); 00096 return *this; 00097 } 00098 00106 bool operator==(const IPNet& other) const { 00107 return ((prefix_len() == other.prefix_len()) && 00108 (masked_addr() == other.masked_addr())); 00109 } 00110 00118 bool operator<(const IPNet& other) const; 00119 00128 IPNet& operator--(); 00129 00138 IPNet& operator++(); 00139 00147 bool operator==(const U32Range& range) const { 00148 return (prefix_len() == range); 00149 } 00150 00158 bool operator!=(const U32Range& range) const { 00159 return (prefix_len() != range); 00160 } 00161 00169 bool operator<(const U32Range& range) const { 00170 return (prefix_len() < range); 00171 }; 00172 00181 bool operator<=(const U32Range& range) const { 00182 return (prefix_len() <= range); 00183 }; 00184 00192 bool operator>(const U32Range& range) const { 00193 return (prefix_len() > range); 00194 }; 00195 00204 bool operator>=(const U32Range& range) const { 00205 return (prefix_len() >= range); 00206 }; 00207 00214 string str() const; 00215 00221 bool is_valid() const { return _prefix_len != 0; } 00222 00229 bool is_overlap(const IPNet& other) const; 00230 00239 bool contains(const IPNet& other) const; 00240 00247 bool contains(const A& addr) const { 00248 return addr.mask_by_prefix_len(_prefix_len) == _masked_addr; 00249 } 00250 00259 uint32_t overlap(const IPNet& other) const; 00260 00266 static int af() { return A::af(); } 00267 00273 const A& masked_addr() const { return _masked_addr; } 00274 00275 A& masked_addr_nc() { return _masked_addr; } 00276 00282 uint8_t prefix_len() const { return _prefix_len; } 00283 00284 void set_prefix_len(uint8_t v) { _prefix_len = v; } 00285 00291 A netmask() const { return _masked_addr.make_prefix(_prefix_len); } 00292 00305 bool is_unicast() const; 00306 00317 static const IPNet<A> ip_multicast_base_prefix() { 00318 return IPNet(A::MULTICAST_BASE(), 00319 A::ip_multicast_base_address_mask_len()); 00320 } 00321 00334 static const IPNet<A> ip_class_a_base_prefix(); 00335 00348 static const IPNet<A> ip_class_b_base_prefix(); 00349 00362 static const IPNet<A> ip_class_c_base_prefix(); 00363 00376 static const IPNet<A> ip_experimental_base_prefix(); 00377 00383 bool is_multicast() const { 00384 return (ip_multicast_base_prefix().contains(*this)); 00385 } 00386 00396 bool is_class_a() const; 00397 00407 bool is_class_b() const; 00408 00418 bool is_class_c() const; 00419 00429 bool is_experimental() const; 00430 00436 A top_addr() const { return _masked_addr | ~netmask(); } 00437 00444 static IPNet<A> common_subnet(const IPNet<A> x, const IPNet<A> y) { 00445 return IPNet<A>(x.masked_addr(), x.overlap(y)); 00446 } 00447 00448 private: 00449 void initialize_from_string(const char *s) 00450 throw (InvalidString, InvalidNetmaskLength); 00451 00452 A _masked_addr; 00453 uint8_t _prefix_len; 00454 }; 00455 00456 /* ------------------------------------------------------------------------- */ 00457 /* Deferred method definitions */ 00458 00459 template <class A> bool 00460 IPNet<A>::operator<(const IPNet& other) const 00461 { 00462 #if 1 00463 /* 00464 * say x = A/B and y = C/D, then 00465 * 00466 * x < y : 00467 * 00468 * if x.contains(y) // equal is fine 00469 * return false 00470 * else if y.strictly_contains(x) // equal already taken care of 00471 * return true 00472 * else 00473 * return A < C 00474 * 00475 * |---x---| 00476 * x=y |---y---| 00477 * x>y |-y-| 00478 * x<y |------y-------| 00479 * x<y |-----y---------| 00480 * x<y |--y-| 00481 */ 00482 if (masked_addr().af() != other.masked_addr().af()) 00483 return (masked_addr().af() < other.masked_addr().af()); 00484 00485 if (this->contains(other)) 00486 return false; 00487 else if (other.contains(*this)) 00488 return true; 00489 else 00490 return this->masked_addr() < other.masked_addr(); 00491 00492 #else // old code 00493 const A& maddr_him = other.masked_addr(); 00494 uint8_t his_prefix_len = other.prefix_len(); 00495 00496 //the ordering is important because we want the longest match to 00497 //be first. For example, we want the following: 00498 // 128.16.0.0/24 < 128.16.64.0/24 < 128.16.0.0/16 < 128.17.0.0/24 00499 00500 if (_prefix_len == his_prefix_len) return _masked_addr < maddr_him; 00501 00502 // we need to check the case when one subnet is a subset of 00503 // the other 00504 if (_prefix_len < his_prefix_len) { 00505 A test_addr(maddr_him.mask_by_prefix_len(_prefix_len)); 00506 if (_masked_addr == test_addr) { 00507 //his subnet is a subset of mine, so he goes first. 00508 return (false); 00509 } 00510 } else if (_prefix_len > his_prefix_len) { 00511 A test_addr(_masked_addr.mask_by_prefix_len(his_prefix_len)); 00512 if (maddr_him == test_addr) { 00513 //my subnet is a subset of his, so I go first. 00514 return (true); 00515 } 00516 } 00517 //the subnets don't overlap (or are identical), so just order by address 00518 if (_masked_addr < maddr_him) { 00519 return (true); 00520 } 00521 return (false); 00522 #endif 00523 } 00524 00525 template <class A> string 00526 IPNet<A>::str() const 00527 { 00528 return _masked_addr.str() + c_format("/%u", XORP_UINT_CAST(_prefix_len)); 00529 } 00530 00531 template <class A> bool 00532 IPNet<A>::is_overlap(const IPNet<A>& other) const 00533 { 00534 if (masked_addr().af() != other.masked_addr().af()) 00535 return (false); 00536 00537 if (prefix_len() > other.prefix_len()) { 00538 // I have smaller prefix size 00539 IPNet other_masked(masked_addr(), other.prefix_len()); 00540 return (other_masked.masked_addr() == other.masked_addr()); 00541 } 00542 if (prefix_len() < other.prefix_len()) { 00543 // I have bigger prefix size 00544 IPNet other_masked(other.masked_addr(), prefix_len()); 00545 return (other_masked.masked_addr() == masked_addr()); 00546 } 00547 // Same prefix size 00548 return (other.masked_addr() == masked_addr()); 00549 } 00550 00551 template <class A> bool 00552 IPNet<A>::contains(const IPNet<A>& other) const 00553 { 00554 if (masked_addr().af() != other.masked_addr().af()) 00555 return (false); 00556 00557 if (prefix_len() > other.prefix_len()) { 00558 // I have smaller prefix size, hence I don't contain other. 00559 return (false); 00560 } 00561 if (prefix_len() < other.prefix_len()) { 00562 // I have bigger prefix size 00563 IPNet other_masked(other.masked_addr(), prefix_len()); 00564 return (other_masked.masked_addr() == masked_addr()); 00565 } 00566 // Same prefix size 00567 return (other.masked_addr() == masked_addr()); 00568 } 00569 00570 template <class A> void 00571 IPNet<A>::initialize_from_string(const char *cp) 00572 throw (InvalidString, InvalidNetmaskLength) 00573 { 00574 char *slash = strrchr(const_cast<char*>(cp), '/'); 00575 if (slash == 0) 00576 xorp_throw(InvalidString, "Missing slash"); 00577 00578 if (*(slash + 1) == 0) 00579 xorp_throw(InvalidString, "Missing prefix length"); 00580 char *n = slash + 1; 00581 while (*n != 0) { 00582 if (*n < '0' || *n > '9') { 00583 xorp_throw(InvalidString, "Bad prefix length"); 00584 } 00585 n++; 00586 } 00587 _prefix_len = atoi(slash + 1); 00588 00589 string addr = string(cp, slash - cp); 00590 00591 _masked_addr = A(addr.c_str()).mask_by_prefix_len(_prefix_len); 00592 } 00593 00594 template <class A> IPNet<A>& 00595 IPNet<A>::operator--() 00596 { 00597 _masked_addr = _masked_addr >> (_masked_addr.addr_bitlen() - _prefix_len); 00598 --_masked_addr; 00599 _masked_addr = _masked_addr << (_masked_addr.addr_bitlen() - _prefix_len); 00600 return (*this); 00601 } 00602 00603 template <class A> IPNet<A>& 00604 IPNet<A>::operator++() 00605 { 00606 _masked_addr = _masked_addr >> (_masked_addr.addr_bitlen() - _prefix_len); 00607 ++_masked_addr; 00608 _masked_addr = _masked_addr << (_masked_addr.addr_bitlen() - _prefix_len); 00609 return (*this); 00610 } 00611 00612 template <class A> 00613 inline uint32_t 00614 IPNet<A>::overlap(const IPNet<A>& other) const 00615 { 00616 if (masked_addr().af() != other.masked_addr().af()) 00617 return 0; 00618 00619 A xor_addr = masked_addr() ^ other.masked_addr(); 00620 uint32_t done = xor_addr.leading_zero_count(); 00621 00622 uint32_t p = (prefix_len() < other.prefix_len()) ? 00623 prefix_len() : other.prefix_len(); 00624 if (done > p) 00625 done = p; 00626 return done; 00627 } 00628 00637 template <class A> uint32_t 00638 overlap(const IPNet<A>& a1, const IPNet<A>& a2) 00639 { 00640 return a1.overlap(a2); 00641 } 00642 00643 #endif // __LIBXORP_IPNET_HH__