xorp

ipnet.hh

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__
 All Classes Namespaces Functions Variables Typedefs Enumerations