This is an automated email from the ASF dual-hosted git repository. bneradt pushed a commit to branch dev-1-0-14 in repository https://gitbox.apache.org/repos/asf/trafficserver-libswoc.git
commit 914c5c28946f14a079834a8eb70973855f948cf4 Author: Alan M. Carroll <[email protected]> AuthorDate: Mon Mar 2 07:23:42 2020 -0600 Better testing of network extraction. --- swoc++/include/swoc/swoc_ip.h | 930 ++++++++++++++++++++++++++---------------- swoc++/src/swoc_ip.cc | 42 ++ unit_tests/test_ip.cc | 283 +++++++++++-- 3 files changed, 861 insertions(+), 394 deletions(-) diff --git a/swoc++/include/swoc/swoc_ip.h b/swoc++/include/swoc/swoc_ip.h index 736a6e6..788c727 100644 --- a/swoc++/include/swoc/swoc_ip.h +++ b/swoc++/include/swoc/swoc_ip.h @@ -14,8 +14,7 @@ #include <swoc/RBTree.h> #include <values.h> -namespace swoc -{ +namespace swoc { class IP4Addr; class IP6Addr; class IPAddr; @@ -46,10 +45,12 @@ union IPEndpoint { /// Default construct invalid instance. IPEndpoint(); + /// Construct from the @a text representation of an address. - IPEndpoint(string_view const &text); + IPEndpoint(string_view const&text); + // Construct from @a IPAddr - IPEndpoint(IPAddr const &addr); + IPEndpoint(IPAddr const&addr); /** Break a string in to IP address relevant tokens. * @@ -62,7 +63,8 @@ union IPEndpoint { * Any of the out parameters can be @c nullptr in which case they are not updated. * This parses and discards the IPv6 brackets. */ - static bool tokenize(string_view src, string_view *host = nullptr, string_view *port = nullptr, string_view *rest = nullptr); + static bool tokenize(string_view src, string_view *host = nullptr, string_view *port = nullptr + , string_view *rest = nullptr); /** Parse a string for an IP address. @@ -71,16 +73,16 @@ union IPEndpoint { @return @c true on success, @c false otherwise. */ - bool parse(string_view const &str); + bool parse(string_view const&str); /// Invalidate a @c sockaddr. static void invalidate(sockaddr *addr); /// Invalidate this endpoint. - self_type &invalidate(); + self_type&invalidate(); /// Copy constructor. - self_type &operator=(self_type const &that); + self_type&operator=(self_type const&that); /** Copy (assign) the contents of @a src to @a dst. * @@ -96,18 +98,20 @@ union IPEndpoint { /** Assign from a socket address. The entire address (all parts) are copied if the @a ip is valid. */ - self_type &assign(sockaddr const *addr); + self_type&assign(sockaddr const *addr); /// Assign from an @a addr and @a port. - self_type &assign(IPAddr const &addr, in_port_t port = 0); + self_type&assign(IPAddr const&addr, in_port_t port = 0); /// Copy to @a sa. - const self_type &fill(sockaddr *addr) const; + const self_type&fill(sockaddr *addr) const; /// Test for valid IP address. bool is_valid() const; + /// Test for IPv4. bool is_ip4() const; + /// Test for IPv6. bool is_ip6() const; @@ -123,28 +127,34 @@ union IPEndpoint { /// Set to be the ANY address for family @a family. /// @a family must be @c AF_INET or @c AF_INET6. /// @return This object. - self_type &set_to_any(int family); + self_type&set_to_any(int family); /// Set to be loopback address for family @a family. /// @a family must be @c AF_INET or @c AF_INET6. /// @return This object. - self_type &set_to_loopback(int family); + self_type&set_to_loopback(int family); /// Port in network order. - in_port_t &port(); + in_port_t&port(); + /// Port in network order. in_port_t port() const; + /// Port in host horder. in_port_t host_order_port() const; + /// Port in network order from @a sockaddr. - static in_port_t &port(sockaddr *sa); + static in_port_t&port(sockaddr *sa); + /// Port in network order from @a sockaddr. static in_port_t port(sockaddr const *sa); + /// Port in host order directly from a @c sockaddr static in_port_t host_order_port(sockaddr const *sa); /// Automatic conversion to @c sockaddr. operator sockaddr *() { return &sa; } + /// Automatic conversion to @c sockaddr. operator sockaddr const *() const { return &sa; } @@ -158,6 +168,7 @@ union IPEndpoint { class IP4Addr { using self_type = IP4Addr; ///< Self reference type. friend class IP4Range; + public: static constexpr size_t SIZE = sizeof(in_addr_t); ///< Size of IPv4 address in bytes. static constexpr size_t WIDTH = BITSPERBYTE * SIZE; ///< # of bits in an address. @@ -170,44 +181,50 @@ public: /// @note Host order seems odd, but all of the standard network macro values such as @c INADDR_LOOPBACK /// are in host order. explicit constexpr IP4Addr(in_addr_t addr); + /// Construct from @c sockaddr_in. explicit IP4Addr(sockaddr_in const *sa); + /// Construct from text representation. /// If the @a text is invalid the result is an invalid instance. - IP4Addr(string_view const &text); + IP4Addr(string_view const&text); + /// Construct from generic address @a addr. - explicit IP4Addr(IPAddr const& addr); + explicit IP4Addr(IPAddr const&addr); /// Assign from IPv4 raw address. - self_type &operator=(in_addr_t ip); + self_type&operator=(in_addr_t ip); + /// Set to the address in @a addr. - self_type &operator=(sockaddr_in const *sa); + self_type&operator=(sockaddr_in const *sa); /// Increment address. - self_type &operator++(); + self_type&operator++(); /// Decrement address. - self_type &operator--(); + self_type&operator--(); /** Byte access. * * @param idx Byte index. * @return The byte at @a idx in the address. */ - uint8_t operator [] (unsigned idx) const { + uint8_t operator[](unsigned idx) const { return reinterpret_cast<bytes const&>(_addr)[idx]; } /// Apply @a mask to address, leaving the network portion. - self_type &operator&=(IPMask const& mask); + self_type&operator&=(IPMask const&mask); + /// Apply @a mask to address, creating the broadcast address. - self_type &operator|=(IPMask const& mask); + self_type&operator|=(IPMask const&mask); /// Write this adddress and @a port to the sockaddr @a sa. sockaddr_in *fill(sockaddr_in *sa, in_port_t port = 0) const; /// @return The address in network order. in_addr_t network_order() const; + /// @return The address in host order. in_addr_t host_order() const; @@ -217,10 +234,10 @@ public: @return @c true on success, @c false otherwise. */ - bool load(string_view const &text); + bool load(string_view const&text); /// Standard ternary compare. - int cmp(self_type const &that) const; + int cmp(self_type const&that) const; /// Get the IP address family. /// @return @c AF_INET @@ -237,14 +254,14 @@ public: * @param n Number of bits to shift left. * @return @a this. */ - self_type & operator <<= (unsigned n); + self_type&operator<<=(unsigned n); /** Right shift. * * @param n Number of bits to shift right. * @return @a this. */ - self_type & operator >>= (unsigned n); + self_type&operator>>=(unsigned n); /** Bitwise AND. * @@ -253,7 +270,7 @@ public: * * The bits in @a this are set to the bitwise AND of the corresponding bits in @a this and @a that. */ - self_type & operator &= (self_type const& that); + self_type&operator&=(self_type const&that); /** Bitwise OR. * @@ -262,7 +279,7 @@ public: * * The bits in @a this are set to the bitwise OR of the corresponding bits in @a this and @a that. */ - self_type & operator |= (self_type const& that); + self_type&operator|=(self_type const&that); /** Convert between network and host order. * @@ -278,10 +295,13 @@ protected: /// Access by bytes. using bytes = std::array<uint8_t, 4>; - friend bool operator==(self_type const &, self_type const &); - friend bool operator!=(self_type const &, self_type const &); - friend bool operator<(self_type const &, self_type const &); - friend bool operator<=(self_type const &, self_type const &); + friend bool operator==(self_type const&, self_type const&); + + friend bool operator!=(self_type const&, self_type const&); + + friend bool operator<(self_type const&, self_type const&); + + friend bool operator<=(self_type const&, self_type const&); in_addr_t _addr = INADDR_ANY; ///< Address in host order. }; @@ -292,10 +312,12 @@ protected: class IP6Addr { using self_type = IP6Addr; ///< Self reference type. friend class IP6Range; + friend class IPMask; + public: static constexpr size_t WIDTH = 128; ///< Number of bits in the address. - static constexpr size_t SIZE = WIDTH / BITSPERBYTE; ///< Size of address in bytes. + static constexpr size_t SIZE = WIDTH / BITSPERBYTE; ///< Size of address in bytes. using quad_type = uint16_t; ///< Size of one segment of an IPv6 address. static constexpr size_t N_QUADS = SIZE / sizeof(quad_type); ///< # of quads in an IPv6 address. @@ -334,34 +356,36 @@ public: static const self_type MAX; IP6Addr() = default; ///< Default constructor - 0 address. - IP6Addr(self_type const& that) = default; + IP6Addr(self_type const&that) = default; /// Construct using IPv6 @a addr. - explicit IP6Addr(in6_addr const & addr); + explicit IP6Addr(in6_addr const&addr); + /// Construct from @c sockaddr_in. explicit IP6Addr(sockaddr_in6 const *addr) { *this = addr; } + /// Construct from text representation. /// If the @a text is invalid the result is an invalid instance. - IP6Addr(string_view const& text); + IP6Addr(string_view const&text); /// Construct from generic @a addr. - IP6Addr(IPAddr const& addr); + IP6Addr(IPAddr const&addr); /** Left shift. * * @param n Number of bits to shift left. * @return @a this. */ - self_type & operator <<= (unsigned n); + self_type&operator<<=(unsigned n); /** Right shift. * * @param n Number of bits to shift right. * @return @a this. */ - self_type & operator >>= (unsigned n); + self_type&operator>>=(unsigned n); /** Bitwise AND. * @@ -370,7 +394,7 @@ public: * * The bits in @a this are set to the bitwise AND of the corresponding bits in @a this and @a that. */ - self_type & operator &= (self_type const& that); + self_type&operator&=(self_type const&that); /** Bitwise OR. * @@ -379,24 +403,25 @@ public: * * The bits in @a this are set to the bitwise OR of the corresponding bits in @a this and @a that. */ - self_type & operator |= (self_type const& that); + self_type&operator|=(self_type const&that); /// Increment address. - self_type &operator++(); + self_type&operator++(); /// Decrement address. - self_type &operator--(); + self_type&operator--(); /// Assign from IPv6 raw address. - self_type &operator=(in6_addr const& ip); + self_type&operator=(in6_addr const&ip); + /// Set to the address in @a addr. - self_type &operator=(sockaddr_in6 const *addr); + self_type&operator=(sockaddr_in6 const *addr); /// Write to @c sockaddr using network order and @a port. sockaddr *copy_to(sockaddr *sa, in_port_t port = 0) const; /// Copy address to @a addr in network order. - in6_addr & copy_to(in6_addr & addr) const; + in6_addr©_to(in6_addr&addr) const; /// Return the address in network order. in6_addr network_order() const; @@ -408,10 +433,10 @@ public: @return @c true on success, @c false otherwise. */ - bool load(string_view const &str); + bool load(string_view const&str); /// Generic compare. - int cmp(self_type const &that) const; + int cmp(self_type const&that) const; /// Get the address family. /// @return The address family. @@ -423,26 +448,31 @@ public: /// Test for loopback bool is_multicast() const { return IN6_IS_ADDR_MULTICAST(_addr._raw.data()); } - self_type & clear() { + self_type&clear() { _addr._store[0] = _addr._store[1] = 0; return *this; } - self_type & operator &= (IPMask const& mask); - self_type & operator |= (IPMask const& mask); + self_type&operator&=(IPMask const&mask); + + self_type&operator|=(IPMask const&mask); + + static void reorder(in6_addr&dst, raw_type const&src); - static void reorder(in6_addr & dst, raw_type const & src); - static void reorder(raw_type & dst, in6_addr const& src); + static void reorder(raw_type&dst, in6_addr const&src); protected: - friend bool operator==(self_type const &, self_type const &); - friend bool operator!=(self_type const &, self_type const &); - friend bool operator<(self_type const &, self_type const &); - friend bool operator<=(self_type const &, self_type const &); + friend bool operator==(self_type const&, self_type const&); + + friend bool operator!=(self_type const&, self_type const&); + + friend bool operator<(self_type const&, self_type const&); + + friend bool operator<=(self_type const&, self_type const&); /// Type for digging around inside the address, with the various forms of access. union { - word_store_type _store = {0 }; ///< 0 is MSW, 1 is LSW. + word_store_type _store = {0}; ///< 0 is MSW, 1 is LSW. quad_store_type _quad; ///< By quad. raw_type _raw; ///< By byte. } _addr; @@ -452,7 +482,7 @@ protected: /// Index of quads in @a _addr._quad. /// This converts from the position in the text format to the quads in the binary format. - static constexpr std::array<unsigned, N_QUADS> QUAD_IDX = { 3,2,1,0,7,6,5,4 }; + static constexpr std::array<unsigned, N_QUADS> QUAD_IDX = {3, 2, 1, 0, 7, 6, 5, 4}; static void reorder(unsigned char dst[WORD_SIZE], unsigned char const src[WORD_SIZE]); @@ -463,94 +493,115 @@ protected: */ IP6Addr(word_store_type::value_type msw, word_store_type::value_type lsw) : _addr{msw, lsw} {} - friend IP6Addr operator & (IP6Addr const& addr, IPMask const& mask); - friend IP6Addr operator | (IP6Addr const& addr, IPMask const& mask); + friend IP6Addr operator&(IP6Addr const&addr, IPMask const&mask); + + friend IP6Addr operator|(IP6Addr const&addr, IPMask const&mask); }; /** Storage for an IP address. */ class IPAddr { friend class IPRange; + using self_type = IPAddr; ///< Self reference type. public: IPAddr() = default; ///< Default constructor - invalid result. - IPAddr(self_type const& that) = default; ///< Copy constructor. + IPAddr(self_type const&that) = default; ///< Copy constructor. /// Construct using IPv4 @a addr. explicit IPAddr(in_addr_t addr); + /// Construct using an IPv4 @a addr - IPAddr(IP4Addr const &addr) : _family(AF_INET), _addr{addr} {} + IPAddr(IP4Addr const&addr) : _family(AF_INET), _addr{addr} {} + /// Construct using IPv6 @a addr. - explicit IPAddr(in6_addr const &addr); + explicit IPAddr(in6_addr const&addr); + /// construct using an IPv6 @a addr - IPAddr(IP6Addr const &addr) : _family(AF_INET6), _addr{addr} {} + IPAddr(IP6Addr const&addr) : _family(AF_INET6), _addr{addr} {} + /// Construct from @c sockaddr. explicit IPAddr(sockaddr const *addr); + /// Construct from @c IPEndpoint. - explicit IPAddr(IPEndpoint const &addr); + explicit IPAddr(IPEndpoint const&addr); + /// Construct from text representation. /// If the @a text is invalid the result is an invalid instance. - explicit IPAddr(string_view const& text); + explicit IPAddr(string_view const&text); /// Set to the address in @a addr. - self_type &assign(sockaddr const *addr); + self_type&assign(sockaddr const *addr); + /// Set to the address in @a addr. - self_type &assign(sockaddr_in const *addr); + self_type&assign(sockaddr_in const *addr); + /// Set to the address in @a addr. - self_type &assign(sockaddr_in6 const *addr); + self_type&assign(sockaddr_in6 const *addr); + /// Set to the address in @a addr. - self_type &assign(in_addr_t addr); + self_type&assign(in_addr_t addr); + /// Set to address in @a addr. - self_type &assign(in6_addr const &addr); + self_type&assign(in6_addr const&addr); /// Assign from end point. - self_type &operator=(IPEndpoint const &ip); + self_type&operator=(IPEndpoint const&ip); + /// Assign from IPv4 raw address. - self_type &operator=(in_addr_t ip); + self_type&operator=(in_addr_t ip); + /// Assign from IPv6 raw address. - self_type &operator=(in6_addr const &ip); + self_type&operator=(in6_addr const&ip); + /// Assign from @c sockaddr - self_type &operator=(sockaddr const *addr); + self_type&operator=(sockaddr const *addr); + + self_type&operator&=(IPMask const&mask); - self_type &operator&=(IPMask const& mask); - self_type &operator|=(IPMask const& mask); + self_type&operator|=(IPMask const&mask); /** Parse a string and load the result in @a this. * * @param text Text to parse. * @return @c true on success, @c false otherwise. */ - bool load(string_view const &text); + bool load(string_view const&text); /// Generic compare. - int cmp(self_type const &that) const; + int cmp(self_type const&that) const; /// Test for same address family. /// @c return @c true if @a that is the same address family as @a this. - bool isCompatibleWith(self_type const &that); + bool isCompatibleWith(self_type const&that); /// Get the address family. /// @return The address family. sa_family_t family() const; + /// Test for IPv4. bool is_ip4() const; + /// Test for IPv6. bool is_ip6() const; in_addr_t network_ip4() const; + in6_addr network_ip6() const; explicit operator IP4Addr const&() const { return _addr._ip4; } - explicit operator IP4Addr &() { return _addr._ip4; } + + explicit operator IP4Addr&() { return _addr._ip4; } explicit operator IP6Addr const&() const { return _addr._ip6; } - explicit operator IP6Addr &() { return _addr._ip6; } + + explicit operator IP6Addr&() { return _addr._ip6; } /// Test for validity. bool is_valid() const; /// Make invalid. - self_type &invalidate(); + self_type&invalidate(); /// Test for multicast bool is_multicast() const; @@ -562,7 +613,8 @@ public: static self_type const INVALID; protected: - friend bool operator==(self_type const &, self_type const &); + friend bool operator==(self_type const&, self_type const&); + friend IP4Addr; friend IP6Addr; @@ -574,11 +626,14 @@ protected: uint64_t _u64[IP6Addr::SIZE / sizeof(uint64_t)]; ///< As 64 bit chunks. constexpr raw_addr_type(); + raw_addr_type(in_addr_t addr) : _ip4(addr) {} - raw_addr_type(in6_addr const& addr) : _ip6(addr) {} - raw_addr_type(IP4Addr const& addr) : _ip4(addr) {} - raw_addr_type(IP6Addr const& addr) : _ip6(addr) {} + raw_addr_type(in6_addr const&addr) : _ip6(addr) {} + + raw_addr_type(IP4Addr const&addr) : _ip4(addr) {} + + raw_addr_type(IP6Addr const&addr) : _ip6(addr) {} } _addr; sa_family_t _family{AF_UNSPEC}; ///< Protocol family. @@ -591,46 +646,59 @@ protected: class IPMask { using self_type = IPMask; ///< Self reference type. friend class IP4Addr; + friend class IP6Addr; public: using raw_type = uint8_t; ///< Storage for mask width. IPMask() = default; + explicit IPMask(raw_type count); /// @return @c true if the mask is valid, @c false if not. bool is_valid() const; - bool load(string_view const& text); + /** Parse mask from @a text. + * + * @param text A number in string format. + * @return @a true if a valid CIDR value, @c false if not. + */ + bool load(string_view const&text); /** Copmute a mask for the network at @a addr. * @param addr Lower bound of network. * @return The width of the largest network starting at @a addr. */ - static self_type mask_for(IPAddr const& addr); + static self_type mask_for(IPAddr const&addr); /** Copmute a mask for the network at @a addr. * @param addr Lower bound of network. * @return A mask with the width of the largest network starting at @a addr. */ - static self_type mask_for(IP4Addr const& addr); + static self_type mask_for(IP4Addr const&addr); /** Copmute a mask for the network at @a addr. * @param addr Lower bound of network. * @return A mask with the width of the largest network starting at @a addr. */ - static self_type mask_for(IP6Addr const& addr); + static self_type mask_for(IP6Addr const&addr); + + /// Force @a this to an invalid state. + self_type&clear() { + _cidr = INVALID; + return *this; + } /// The width of the mask. raw_type width() const; - self_type & operator<<= (raw_type n) { + self_type&operator<<=(raw_type n) { _cidr -= n; return *this; } - self_type & operator>>= (raw_type n) { + self_type&operator>>=(raw_type n) { _cidr += n; return *this; } @@ -676,11 +744,11 @@ public: IP4Range() = default; /// Construct from an network expressed as @a addr and @a mask. - IP4Range(IP4Addr const& addr, IPMask const& mask); + IP4Range(IP4Addr const&addr, IPMask const&mask); /// Construct from super type. /// @internal Why do I have to do this, even though the super type constructors are inherited? - IP4Range(super_type const& r) : super_type(r) {} + IP4Range(super_type const&r) : super_type(r) {} /** Construct range from @a text. * @@ -690,7 +758,7 @@ public: * This results in a zero address if @a text is not a valid string. If this should be checked, * use @c load. */ - IP4Range(string_view const& text); + IP4Range(string_view const&text); /** Set @a this range. * @@ -698,7 +766,7 @@ public: * @param mask CIDR mask to compute maximum adddress from @a addr. * @return @a this */ - self_type & assign(IP4Addr const& addr, IPMask const& mask); + self_type&assign(IP4Addr const&addr, IPMask const&mask); /** Assign to this range from text. * @@ -741,9 +809,10 @@ public: using range_type = IP4Range; ///< Import base range type. /// Construct from @a range. - explicit NetSource(range_type const& range); + explicit NetSource(range_type const&range); + /// Copy constructor. - NetSource(self_type const& that) = default; + NetSource(self_type const&that) = default; /// This class acts as a container and an iterator. using iterator = self_type; @@ -754,27 +823,30 @@ public: iterator end() const; ///< Past last network. /// @return The current network. - IP4Net operator * () const; + IP4Net operator*() const; + /// Access @a this as if it were an @c IP4Net. - self_type * operator -> (); + self_type *operator->(); /// Iterator support. /// @areturn The current network address. - IP4Addr const& addr() const; + IP4Addr const&addr() const; + /// Iterator support. /// @return The current network mask. IPMask mask() const; /// Move to next network. - self_type & operator++(); + self_type&operator++(); + /// Move to next network. self_type operator++(int); /// Equality. - bool operator == (self_type const& that); + bool operator==(self_type const&that); /// Inequality. - bool operator != (self_type const& that); + bool operator!=(self_type const&that); protected: IP4Range _range; ///< Remaining range. @@ -783,7 +855,9 @@ protected: IPMask::raw_type _cidr = IP4Addr::WIDTH; ///< Current CIDR value. void search_wider(); + void search_narrower(); + bool is_valid(IP4Addr mask); }; @@ -796,7 +870,7 @@ public: /// Construct from super type. /// @internal Why do I have to do this, even though the super type constructors are inherited? - IP6Range(super_type const& r) : super_type(r) {} + IP6Range(super_type const&r) : super_type(r) {} /** Construct range from @a text. * @@ -806,7 +880,7 @@ public: * This results in a zero address if @a text is not a valid string. If this should be checked, * use @c load. */ - IP6Range(string_view const& text); + IP6Range(string_view const&text); /** Set @a this range. * @@ -814,7 +888,7 @@ public: * @param mask CIDR mask to compute maximum adddress from @a addr. * @return @a this */ - self_type & assign(IP6Addr const& addr, IPMask const& mask); + self_type&assign(IP6Addr const&addr, IPMask const&mask); /** Assign to this range from text. * @@ -857,9 +931,10 @@ public: using range_type = IP6Range; ///< Import base range type. /// Construct from @a range. - explicit NetSource(range_type const& range); + explicit NetSource(range_type const&range); + /// Copy constructor. - NetSource(self_type const& that) = default; + NetSource(self_type const&that) = default; /// This class acts as a container and an iterator. using iterator = self_type; @@ -870,35 +945,40 @@ public: iterator end() const; ///< Past last network. /// @return The current network. - IP6Net operator * () const; + IP6Net operator*() const; + /// Access @a this as if it were an @c IP6Net. - self_type * operator -> (); + self_type *operator->(); /// Iterator support. /// @areturn The current network address. - IP6Addr const& addr() const; + IP6Addr const&addr() const; + /// Iterator support. /// @return The current network mask. IPMask mask() const; /// Move to next network. - self_type & operator++(); + self_type&operator++(); + /// Move to next network. self_type operator++(int); /// Equality. - bool operator == (self_type const& that); + bool operator==(self_type const&that); /// Inequality. - bool operator != (self_type const& that); + bool operator!=(self_type const&that); protected: IP6Range _range; ///< Remaining range. - IPMask _mask { IP6Addr::WIDTH } ; ///< Current CIDR value. + IPMask _mask{IP6Addr::WIDTH}; ///< Current CIDR value. void search_wider(); + void search_narrower(); - bool is_valid(IPMask const& mask); + + bool is_valid(IPMask const&mask); }; class IPRange { @@ -906,24 +986,27 @@ class IPRange { public: /// Default constructor - construct invalid range. IPRange() = default; + /// Construct from an IPv4 @a range. - IPRange(IP4Range const& range); + IPRange(IP4Range const&range); + /// Construct from an IPv6 @a range. - IPRange(IP6Range const& range); + IPRange(IP6Range const&range); + /** Construct from a string format. * * @param text Text form of range. * * The string can be a single address, two addresses separated by a dash '-' or a CIDR network. */ - IPRange(string_view const& text); + IPRange(string_view const&text); /** Check if @a this range is the IP address @a family. * * @param family IP address family. * @return @c true if this is @a family, @c false if not. */ - bool is(sa_family_t family) const ; + bool is(sa_family_t family) const; /** Load the range from @a text. * @@ -933,19 +1016,23 @@ public: * A successful parse means @a this was loaded with the specified range. If not the range is * marked as invalid. */ - bool load(std::string_view const& text); + bool load(std::string_view const&text); /// @return The minimum address in the range. IPAddr min() const; + /// @return The maximum address in the range. IPAddr max() const; bool empty() const; - operator IP4Range & () { return _range._ip4; } - operator IP6Range & () { return _range._ip6; } - operator IP4Range const & () const { return _range._ip4; } - operator IP6Range const & () const { return _range._ip6; } + operator IP4Range&() { return _range._ip4; } + + operator IP6Range&() { return _range._ip6; } + + operator IP4Range const&() const { return _range._ip4; } + + operator IP6Range const&() const { return _range._ip6; } protected: /** Range container. @@ -961,9 +1048,9 @@ protected: std::monostate _nil; ///< Make constructor easier to implement. IP4Range _ip4; ///< IPv4 range. IP6Range _ip6; ///< IPv6 range. - } _range { std::monostate{} }; + } _range{std::monostate{}}; /// Family of @a _range. - sa_family_t _family { AF_UNSPEC }; + sa_family_t _family{AF_UNSPEC}; }; /// An IPv4 network. @@ -971,7 +1058,7 @@ class IP4Net { using self_type = IP4Net; ///< Self reference type. public: IP4Net() = default; ///< Construct invalid network. - IP4Net(self_type const& that) = default; ///< Copy constructor. + IP4Net(self_type const&that) = default; ///< Copy constructor. /** Construct from @a addr and @a mask. * @@ -984,6 +1071,17 @@ public: */ IP4Net(IP4Addr addr, IPMask mask); + IP4Net(swoc::TextView text) { + this->load(text); + } + + /** Parse network as @a text. + * + * @param text String describing the network in CIDR format. + * @return @c true if a valid string, @c false if not. + */ + bool load(swoc::TextView text); + /// @return @c true if the network is valid, @c false if not. bool is_valid() const; @@ -994,11 +1092,31 @@ public: IP4Addr upper_bound() const; /// @return The mask for the network. - IPMask const& mask() const; + IPMask const&mask() const; /// @return A range that exactly covers the network. IP4Range as_range() const; + /** Assign an @a addr and @a mask to @a this. + * + * @param addr Network addres. + * @param mask Network mask. + * @return @a this. + */ + self_type&assign(IP4Addr const&addr, IPMask const&mask); + + /// Reset network to invalid state. + self_type&clear() { + _mask.clear(); + return *this; + } + + /// Equality. + bool operator==(self_type const&that) const; + + /// Inequality + bool operator!=(self_type const&that) const; + protected: IP4Addr _addr; ///< Network address (also lower_bound). IPMask _mask; ///< Network mask. @@ -1008,7 +1126,7 @@ class IP6Net { using self_type = IP6Net; ///< Self reference type. public: IP6Net() = default; ///< Construct invalid network. - IP6Net(self_type const& that) = default; ///< Copy constructor. + IP6Net(self_type const&that) = default; ///< Copy constructor. /** Construct from @a addr and @a mask. * @@ -1021,6 +1139,13 @@ public: */ IP6Net(IP6Addr addr, IPMask mask); + /** Parse network as @a text. + * + * @param text String describing the network in CIDR format. + * @return @c true if a valid string, @c false if not. + */ + bool load(swoc::TextView text); + /// @return @c true if the network is valid, @c false if not. bool is_valid() const; @@ -1031,11 +1156,31 @@ public: IP6Addr upper_bound() const; /// @return The mask for the network. - IPMask const& mask() const; + IPMask const&mask() const; /// @return A range that exactly covers the network. IP6Range as_range() const; + /** Assign an @a addr and @a mask to @a this. + * + * @param addr Network addres. + * @param mask Network mask. + * @return @a this. + */ + self_type&assign(IP6Addr const&addr, IPMask const&mask); + + /// Reset network to invalid state. + self_type&clear() { + _mask.clear(); + return *this; + } + + /// Equality. + bool operator==(self_type const&that) const; + + /// Inequality + bool operator!=(self_type const&that) const; + protected: IP6Addr _addr; ///< Network address (also lower_bound). IPMask _mask; ///< Network mask. @@ -1050,29 +1195,32 @@ public: static constexpr char SEPARATOR = '/'; // the character used between the address and mask IPNet() = default; - IPNet(const IPAddr &addr, const IPMask &mask); - operator IPAddr const &() const; - operator IPMask const &() const; + IPNet(const IPAddr&addr, const IPMask&mask); - IPAddr const &addr() const; + operator IPAddr const&() const; - IPMask const &mask() const; + operator IPMask const&() const; + + IPAddr const&addr() const; + + IPMask const&mask() const; IPAddr lower_bound() const; + IPAddr upper_bound() const; IPRange as_range() const; - bool contains(IPAddr const &addr) const; + bool contains(IPAddr const&addr) const; // computes this is strict subset of other - bool is_subnet_of(self_type const &that); + bool is_subnet_of(self_type const&that); // Check if there are any addresses in both @a this and @a that. - bool intersects(self_type const &that); + bool intersects(self_type const&that); - self_type &assign(IPAddr const &addr, IPMask const &mask); + self_type&assign(IPAddr const&addr, IPMask const&mask); protected: IPAddr _addr; @@ -1093,7 +1241,7 @@ protected: * - Cheap to copy. * - Comparable via the equality and inequality operators. */ -template <typename PAYLOAD> class IPSpace { +template<typename PAYLOAD> class IPSpace { using self_type = IPSpace; using IP4Space = DiscreteSpace<IP4Addr, PAYLOAD>; using IP6Space = DiscreteSpace<IP6Addr, PAYLOAD>; @@ -1112,7 +1260,7 @@ public: * * All addresses in @a r are set to have the @a payload. */ - self_type & mark(IPRange const &range, PAYLOAD const &payload); + self_type&mark(IPRange const&range, PAYLOAD const&payload); /** Fill the @a range with @a payload. * @@ -1122,7 +1270,7 @@ public: * * Addresses in @a range are set to have @a payload if the address does not already have a payload. */ - self_type & fill(IPRange const& range, PAYLOAD const& payload); + self_type&fill(IPRange const&range, PAYLOAD const&payload); /** Blend @a color in to the @a range. * @@ -1143,17 +1291,17 @@ public: * @c PAYLOAD @a p, @a p is updated by invoking <tt>blender(p, color)</tt>, with the expectation * that @a p will be updated in place. */ - template < typename F , typename U = PAYLOAD > - self_type & blend(IPRange const& range, U const& color, F && blender); + template<typename F, typename U = PAYLOAD> + self_type&blend(IPRange const&range, U const&color, F&&blender); - template < typename F , typename U = PAYLOAD > - self_type & blend(IP4Range const& range, U const& color, F && blender) { + template<typename F, typename U = PAYLOAD> + self_type&blend(IP4Range const&range, U const&color, F&&blender) { _ip4.blend(range, color, blender); return *this; } - template < typename F , typename U = PAYLOAD > - self_type & blend(IP6Range const& range, U const& color, F && blender) { + template<typename F, typename U = PAYLOAD> + self_type&blend(IP6Range const&range, U const&color, F&&blender) { _ip6.blend(range, color, blender); return *this; } @@ -1163,7 +1311,7 @@ public: * @param addr Address to find. * @return The payload if any, @c nullptr if the address is not in the space. */ - PAYLOAD *find(IP4Addr const &addr) { + PAYLOAD *find(IP4Addr const&addr) { return _ip4.find(addr); } @@ -1172,7 +1320,7 @@ public: * @param addr Address to find. * @return The payload if any, @c nullptr if the address is not in the space. */ - PAYLOAD *find(IP6Addr const &addr) { + PAYLOAD *find(IP6Addr const&addr) { return _ip6.find(addr); } @@ -1181,7 +1329,7 @@ public: * @param addr Address to find. * @return The payload if any, @c nullptr if the address is not in the space. */ - PAYLOAD *find(IPAddr const &addr) { + PAYLOAD *find(IPAddr const&addr) { if (addr.is_ip4()) { return _ip4.find(IP4Addr{addr}); } else if (addr.is_ip6()) { @@ -1205,12 +1353,13 @@ public: class const_iterator { using self_type = const_iterator; ///< Self reference type. friend class IPSpace; + public: using value_type = std::tuple<IPRange const, PAYLOAD const&>; /// Import for API compliance. // STL algorithm compliance. using iterator_category = std::bidirectional_iterator_tag; using pointer = value_type *; - using reference = value_type &; + using reference = value_type&; using difference_type = int; /// Default constructor. @@ -1219,12 +1368,12 @@ public: /// Pre-increment. /// Move to the next element in the list. /// @return The iterator. - self_type &operator++(); + self_type&operator++(); /// Pre-decrement. /// Move to the previous element in the list. /// @return The iterator. - self_type &operator--(); + self_type&operator--(); /// Post-increment. /// Move to the next element in the list. @@ -1238,17 +1387,17 @@ public: /// Dereference. /// @return A reference to the referent. - value_type const& operator*() const; + value_type const&operator*() const; /// Dereference. /// @return A pointer to the referent. - value_type const* operator->() const; + value_type const *operator->() const; /// Equality - bool operator==(self_type const &that) const; + bool operator==(self_type const&that) const; /// Inequality - bool operator!=(self_type const &that) const; + bool operator!=(self_type const&that) const; protected: // These are stored non-const to make implementing @c iterator easier. This class provides the @@ -1259,11 +1408,11 @@ public: typename IP4Space::iterator _iter_4; ///< IPv4 sub-space iterator. typename IP6Space::iterator _iter_6; ///< IPv6 sub-space iterator. /// Current value. - value_type _value { IPRange{}, *null_payload }; + value_type _value{IPRange{}, *null_payload}; /// Dummy payload. /// @internal Used to initialize @c value_type for invalid iterators. - static constexpr PAYLOAD * null_payload = nullptr; + static constexpr PAYLOAD *null_payload = nullptr; /** Internal constructor. * @@ -1272,7 +1421,8 @@ public: * * In practice, both iterators should be either the beginning or ending iterator for the subspace. */ - const_iterator(typename IP4Space::iterator const& iter4, typename IP6Space::iterator const& iter6); + const_iterator(typename IP4Space::iterator const&iter4 + , typename IP6Space::iterator const&iter6); }; /** Iterator. @@ -1284,13 +1434,15 @@ public: class iterator : public const_iterator { using self_type = iterator; using super_type = const_iterator; + friend class IPSpace; + public: public: /// Value type of iteration. using value_type = std::tuple<IPRange const, PAYLOAD&>; using pointer = value_type *; - using reference = value_type &; + using reference = value_type&; /// Default constructor. iterator() = default; @@ -1298,30 +1450,38 @@ public: /// Pre-increment. /// Move to the next element in the list. /// @return The iterator. - self_type &operator++(); + self_type&operator++(); /// Pre-decrement. /// Move to the previous element in the list. /// @return The iterator. - self_type &operator--(); + self_type&operator--(); /// Post-increment. /// Move to the next element in the list. /// @return The iterator value before the increment. - self_type operator++(int) { self_type zret{*this}; ++*this; return zret; } + self_type operator++(int) { + self_type zret{*this}; + ++*this; + return zret; + } /// Post-decrement. /// Move to the previous element in the list. /// @return The iterator value before the decrement. - self_type operator--(int) { self_type zret{*this}; --*this; return zret; } + self_type operator--(int) { + self_type zret{*this}; + --*this; + return zret; + } /// Dereference. /// @return A reference to the referent. - value_type const& operator*() const; + value_type const&operator*() const; /// Dereference. /// @return A pointer to the referent. - value_type const* operator->() const; + value_type const *operator->() const; protected: using super_type::super_type; /// Inherit supertype constructors. @@ -1329,10 +1489,12 @@ public: /// @return A constant iterator to the first element. const_iterator begin() const; + /// @return A constent iterator past the last element. const_iterator end() const; iterator begin() { return iterator{_ip4.begin(), _ip6.begin()}; } + iterator end() { return iterator{_ip4.end(), _ip6.end()}; } protected: @@ -1341,15 +1503,18 @@ protected: }; template<typename PAYLOAD> -IPSpace<PAYLOAD>::const_iterator::const_iterator(typename IP4Space::iterator const& iter4, typename IP6Space::iterator const& iter6) : _iter_4(iter4), _iter_6(iter6) { +IPSpace<PAYLOAD>::const_iterator::const_iterator(typename IP4Space::iterator const&iter4 + , typename IP6Space::iterator const&iter6) + : _iter_4(iter4), _iter_6(iter6) { if (_iter_4.has_next()) { new(&_value) value_type{_iter_4->range(), _iter_4->payload()}; } else if (_iter_6.has_next()) { new(&_value) value_type{_iter_6->range(), _iter_6->payload()}; } } + template<typename PAYLOAD> -auto IPSpace<PAYLOAD>::const_iterator::operator++() -> self_type & { +auto IPSpace<PAYLOAD>::const_iterator::operator++() -> self_type& { bool incr_p = false; if (_iter_4.has_next()) { ++_iter_4; @@ -1366,7 +1531,7 @@ auto IPSpace<PAYLOAD>::const_iterator::operator++() -> self_type & { return *this; } } - new (&_value) value_type{IPRange{}, *null_payload}; + new(&_value) value_type{IPRange{}, *null_payload}; return *this; } @@ -1378,10 +1543,10 @@ auto IPSpace<PAYLOAD>::const_iterator::operator++(int) -> self_type { } template<typename PAYLOAD> -auto IPSpace<PAYLOAD>::const_iterator::operator--() -> self_type & { +auto IPSpace<PAYLOAD>::const_iterator::operator--() -> self_type& { if (_iter_6.has_prev()) { --_iter_6; - new (&_value) value_type{_iter_6->range(), _iter_6->payload()}; + new(&_value) value_type{_iter_6->range(), _iter_6->payload()}; return *this; } if (_iter_4.has_prev()) { @@ -1389,7 +1554,7 @@ auto IPSpace<PAYLOAD>::const_iterator::operator--() -> self_type & { new(&_value) value_type{_iter_4->range(), _iter_4->payload()}; return *this; } - new (&_value) value_type{IPRange{}, *null_payload}; + new(&_value) value_type{IPRange{}, *null_payload}; return *this; } @@ -1416,19 +1581,19 @@ auto IPSpace<PAYLOAD>::const_iterator::operator->() const -> value_type const * template<typename PAYLOAD> bool -IPSpace<PAYLOAD>::const_iterator::operator==(self_type const& that) const { +IPSpace<PAYLOAD>::const_iterator::operator==(self_type const&that) const { return _iter_4 == that._iter_4 && _iter_6 == that._iter_6; } template<typename PAYLOAD> bool -IPSpace<PAYLOAD>::const_iterator::operator!=(self_type const& that) const { +IPSpace<PAYLOAD>::const_iterator::operator!=(self_type const&that) const { return _iter_4 != that._iter_4 || _iter_6 != that._iter_6; } template<typename PAYLOAD> -auto IPSpace<PAYLOAD>::iterator::operator->() const -> value_type const* { - return static_cast<value_type*>(&super_type::_value); +auto IPSpace<PAYLOAD>::iterator::operator->() const -> value_type const * { + return static_cast<value_type *>(&super_type::_value); } template<typename PAYLOAD> @@ -1437,13 +1602,13 @@ auto IPSpace<PAYLOAD>::iterator::operator*() const -> value_type const& { } template<typename PAYLOAD> -auto IPSpace<PAYLOAD>::iterator::operator++() -> self_type & { +auto IPSpace<PAYLOAD>::iterator::operator++() -> self_type& { this->super_type::operator++(); return *this; } template<typename PAYLOAD> -auto IPSpace<PAYLOAD>::iterator::operator--() -> self_type & { +auto IPSpace<PAYLOAD>::iterator::operator--() -> self_type& { this->super_type::operator--(); return *this; } @@ -1455,40 +1620,40 @@ inline constexpr IPAddr::raw_addr_type::raw_addr_type() : _ip4(INADDR_ANY) {} inline IPAddr::IPAddr(in_addr_t addr) : _family(AF_INET), _addr(addr) {} -inline IPAddr::IPAddr(in6_addr const &addr) : _family(AF_INET6), _addr(addr) {} +inline IPAddr::IPAddr(in6_addr const&addr) : _family(AF_INET6), _addr(addr) {} inline IPAddr::IPAddr(sockaddr const *addr) { this->assign(addr); } -inline IPAddr::IPAddr(IPEndpoint const &addr) { +inline IPAddr::IPAddr(IPEndpoint const&addr) { this->assign(&addr.sa); } -inline IPAddr::IPAddr(string_view const& text) { +inline IPAddr::IPAddr(string_view const&text) { this->load(text); } -inline IPAddr & +inline IPAddr& IPAddr::operator=(in_addr_t addr) { - _family = AF_INET; + _family = AF_INET; _addr._ip4 = addr; return *this; } -inline IPAddr & -IPAddr::operator=(in6_addr const &addr) { - _family = AF_INET6; +inline IPAddr& +IPAddr::operator=(in6_addr const&addr) { + _family = AF_INET6; _addr._ip6 = addr; return *this; } -inline IPAddr & -IPAddr::operator=(IPEndpoint const &addr) { +inline IPAddr& +IPAddr::operator=(IPEndpoint const&addr) { return this->assign(&addr.sa); } -inline IPAddr & +inline IPAddr& IPAddr::operator=(sockaddr const *addr) { return this->assign(addr); } @@ -1509,56 +1674,53 @@ IPAddr::is_ip6() const { } inline bool -IPAddr::isCompatibleWith(self_type const &that) { +IPAddr::isCompatibleWith(self_type const&that) { return this->is_valid() && _family == that._family; } inline bool IPAddr::is_loopback() const { - return (AF_INET == _family && 0x7F == _addr._octet[0]) || (AF_INET6 == _family && IN6_IS_ADDR_LOOPBACK(&_addr._ip6)); + return (AF_INET == _family && 0x7F == _addr._octet[0]) || + (AF_INET6 == _family && IN6_IS_ADDR_LOOPBACK(&_addr._ip6)); } inline bool -operator==(IPAddr const &lhs, IPAddr const &rhs) { - if (lhs._family != rhs._family) +operator==(IPAddr const&lhs, IPAddr const&rhs) { + if (lhs._family != rhs._family) { return false; - switch (lhs._family) - { - case AF_INET: - return lhs._addr._ip4 == rhs._addr._ip4; - case AF_INET6: - return 0 == memcmp(&lhs._addr._ip6, &rhs._addr._ip6, IP6Addr::SIZE); - case AF_UNSPEC: - return true; - default: - break; + } + switch (lhs._family) { + case AF_INET:return lhs._addr._ip4 == rhs._addr._ip4; + case AF_INET6:return 0 == memcmp(&lhs._addr._ip6, &rhs._addr._ip6, IP6Addr::SIZE); + case AF_UNSPEC:return true; + default:break; } return false; } inline bool -operator!=(IPAddr const &lhs, IPAddr const &rhs) { +operator!=(IPAddr const&lhs, IPAddr const&rhs) { return !(lhs == rhs); } -inline IPAddr & +inline IPAddr& IPAddr::assign(in_addr_t addr) { - _family = AF_INET; + _family = AF_INET; _addr._ip4 = addr; return *this; } -inline IPAddr & -IPAddr::assign(in6_addr const &addr) { - _family = AF_INET6; +inline IPAddr& +IPAddr::assign(in6_addr const&addr) { + _family = AF_INET6; _addr._ip6 = addr; return *this; } -inline IPAddr & +inline IPAddr& IPAddr::assign(sockaddr_in const *addr) { if (addr) { - _family = AF_INET; + _family = AF_INET; _addr._ip4 = addr; } else { _family = AF_UNSPEC; @@ -1566,10 +1728,10 @@ IPAddr::assign(sockaddr_in const *addr) { return *this; } -inline IPAddr & +inline IPAddr& IPAddr::assign(sockaddr_in6 const *addr) { if (addr) { - _family = AF_INET6; + _family = AF_INET6; _addr._ip6 = addr->sin6_addr; } else { _family = AF_UNSPEC; @@ -1582,60 +1744,67 @@ IPAddr::is_valid() const { return _family == AF_INET || _family == AF_INET6; } -inline IPAddr & +inline IPAddr& IPAddr::invalidate() { _family = AF_UNSPEC; return *this; } // Associated operators. -bool operator==(IPAddr const &lhs, sockaddr const *rhs); +bool operator==(IPAddr const&lhs, sockaddr const *rhs); + inline bool -operator==(sockaddr const *lhs, IPAddr const &rhs) { +operator==(sockaddr const *lhs, IPAddr const&rhs) { return rhs == lhs; } + inline bool -operator!=(IPAddr const &lhs, sockaddr const *rhs) { +operator!=(IPAddr const&lhs, sockaddr const *rhs) { return !(lhs == rhs); } + inline bool -operator!=(sockaddr const *lhs, IPAddr const &rhs) { +operator!=(sockaddr const *lhs, IPAddr const&rhs) { return !(rhs == lhs); } + inline bool -operator==(IPAddr const &lhs, IPEndpoint const &rhs) { +operator==(IPAddr const&lhs, IPEndpoint const&rhs) { return lhs == &rhs.sa; } + inline bool -operator==(IPEndpoint const &lhs, IPAddr const &rhs) { +operator==(IPEndpoint const&lhs, IPAddr const&rhs) { return &lhs.sa == rhs; } + inline bool -operator!=(IPAddr const &lhs, IPEndpoint const &rhs) { +operator!=(IPAddr const&lhs, IPEndpoint const&rhs) { return !(lhs == &rhs.sa); } + inline bool -operator!=(IPEndpoint const &lhs, IPAddr const &rhs) { +operator!=(IPEndpoint const&lhs, IPAddr const&rhs) { return !(rhs == &lhs.sa); } inline bool -operator<(IPAddr const &lhs, IPAddr const &rhs) { +operator<(IPAddr const&lhs, IPAddr const&rhs) { return -1 == lhs.cmp(rhs); } inline bool -operator>=(IPAddr const &lhs, IPAddr const &rhs) { +operator>=(IPAddr const&lhs, IPAddr const&rhs) { return lhs.cmp(rhs) >= 0; } inline bool -operator>(IPAddr const &lhs, IPAddr const &rhs) { +operator>(IPAddr const&lhs, IPAddr const&rhs) { return 1 == lhs.cmp(rhs); } inline bool -operator<=(IPAddr const &lhs, IPAddr const &rhs) { +operator<=(IPAddr const&lhs, IPAddr const&rhs) { return lhs.cmp(rhs) <= 0; } @@ -1655,11 +1824,11 @@ inline IPEndpoint::IPEndpoint() { sa.sa_family = AF_UNSPEC; } -inline IPEndpoint::IPEndpoint(IPAddr const &addr) { +inline IPEndpoint::IPEndpoint(IPAddr const&addr) { this->assign(addr); } -inline IPEndpoint & +inline IPEndpoint& IPEndpoint::invalidate() { sa.sa_family = AF_UNSPEC; return *this; @@ -1675,19 +1844,19 @@ IPEndpoint::is_valid() const { return sa.sa_family == AF_INET || sa.sa_family == AF_INET6; } -inline IPEndpoint & -IPEndpoint::operator=(self_type const &that) { +inline IPEndpoint& +IPEndpoint::operator=(self_type const&that) { self_type::assign(&sa, &that.sa); return *this; } -inline IPEndpoint & +inline IPEndpoint& IPEndpoint::assign(sockaddr const *src) { self_type::assign(&sa, src); return *this; } -inline IPEndpoint const & +inline IPEndpoint const& IPEndpoint::fill(sockaddr *addr) const { self_type::assign(addr, &sa); return *this; @@ -1708,7 +1877,7 @@ IPEndpoint::family() const { return sa.sa_family; } -inline in_port_t & +inline in_port_t& IPEndpoint::port() { return self_type::port(&sa); } @@ -1723,14 +1892,11 @@ IPEndpoint::host_order_port() const { return ntohs(this->port()); } -inline in_port_t & +inline in_port_t& IPEndpoint::port(sockaddr *sa) { - switch (sa->sa_family) - { - case AF_INET: - return reinterpret_cast<sockaddr_in *>(sa)->sin_port; - case AF_INET6: - return reinterpret_cast<sockaddr_in6 *>(sa)->sin6_port; + switch (sa->sa_family) { + case AF_INET:return reinterpret_cast<sockaddr_in *>(sa)->sin_port; + case AF_INET6:return reinterpret_cast<sockaddr_in6 *>(sa)->sin6_port; } // Force a failure upstream by returning a null reference. return *static_cast<in_port_t *>(nullptr); @@ -1750,41 +1916,42 @@ IPEndpoint::host_order_port(sockaddr const *sa) { inline constexpr IP4Addr::IP4Addr(in_addr_t addr) : _addr(addr) {} -inline IP4Addr::IP4Addr(std::string_view const& text) { - if (! this->load(text)) { +inline IP4Addr::IP4Addr(std::string_view const&text) { + if (!this->load(text)) { _addr = INADDR_ANY; } } -inline IP4Addr::IP4Addr(IPAddr const& addr) : _addr(addr._family == AF_INET ? addr._addr._ip4._addr : INADDR_ANY) {} +inline IP4Addr::IP4Addr(IPAddr const&addr) : _addr( + addr._family == AF_INET ? addr._addr._ip4._addr : INADDR_ANY) {} -inline IP4Addr& IP4Addr::operator<<=(unsigned n) { +inline IP4Addr&IP4Addr::operator<<=(unsigned n) { _addr <<= n; return *this; } -inline IP4Addr& IP4Addr::operator>>=(unsigned n) { +inline IP4Addr&IP4Addr::operator>>=(unsigned n) { _addr >>= n; return *this; } -inline IP4Addr& IP4Addr::operator&=(self_type const& that) { +inline IP4Addr&IP4Addr::operator&=(self_type const&that) { _addr &= that._addr; return *this; } -inline IP4Addr& IP4Addr::operator|=(self_type const& that) { +inline IP4Addr&IP4Addr::operator|=(self_type const&that) { _addr |= that._addr; return *this; } -inline IP4Addr & +inline IP4Addr& IP4Addr::operator++() { ++_addr; return *this; } -inline IP4Addr & +inline IP4Addr& IP4Addr::operator--() { --_addr; return *this; @@ -1799,64 +1966,65 @@ inline in_addr_t IP4Addr::host_order() const { } inline auto -IP4Addr::operator=(in_addr_t ip) -> self_type & { +IP4Addr::operator=(in_addr_t ip) -> self_type& { _addr = ntohl(ip); return *this; } -inline bool operator == (IP4Addr const& lhs, IP4Addr const& rhs) { +inline bool operator==(IP4Addr const&lhs, IP4Addr const&rhs) { return lhs._addr == rhs._addr; } -inline bool operator != (IP4Addr const& lhs, IP4Addr const& rhs) { +inline bool operator!=(IP4Addr const&lhs, IP4Addr const&rhs) { return lhs._addr != rhs._addr; } -inline bool operator < (IP4Addr const& lhs, IP4Addr const& rhs) { +inline bool operator<(IP4Addr const&lhs, IP4Addr const&rhs) { return lhs._addr < rhs._addr; } -inline bool operator <= (IP4Addr const& lhs, IP4Addr const& rhs) { +inline bool operator<=(IP4Addr const&lhs, IP4Addr const&rhs) { return lhs._addr <= rhs._addr; } -inline bool operator > (IP4Addr const& lhs, IP4Addr const& rhs) { +inline bool operator>(IP4Addr const&lhs, IP4Addr const&rhs) { return rhs < lhs; } -inline bool operator >= (IP4Addr const& lhs, IP4Addr const& rhs) { +inline bool operator>=(IP4Addr const&lhs, IP4Addr const&rhs) { return rhs <= lhs; } -inline IP4Addr & IP4Addr::operator&=(IPMask const& mask) { +inline IP4Addr&IP4Addr::operator&=(IPMask const&mask) { _addr &= mask.as_ip4()._addr; return *this; } -inline IP4Addr & IP4Addr::operator|=(IPMask const& mask) { +inline IP4Addr&IP4Addr::operator|=(IPMask const&mask) { _addr |= ~(mask.as_ip4()._addr); return *this; } constexpr in_addr_t IP4Addr::reorder(in_addr_t src) { - return ((src & 0xFF) << 24) | (((src >> 8) & 0xFF) << 16) | (((src >> 16) & 0xFF) << 8) | ((src >> 24) & 0xFF); + return ((src & 0xFF) << 24) | (((src >> 8) & 0xFF) << 16) | (((src >> 16) & 0xFF) << 8) | + ((src >> 24) & 0xFF); } // --- -inline IP6Addr::IP6Addr(in6_addr const& addr) { +inline IP6Addr::IP6Addr(in6_addr const&addr) { *this = addr; } -inline IP6Addr::IP6Addr(std::string_view const& text) { - if (! this->load(text)) { +inline IP6Addr::IP6Addr(std::string_view const&text) { + if (!this->load(text)) { this->clear(); } } -inline IP6Addr::IP6Addr(IPAddr const& addr) : _addr{addr._addr._ip6._addr} {} +inline IP6Addr::IP6Addr(IPAddr const&addr) : _addr{addr._addr._ip6._addr} {} -inline in6_addr& IP6Addr::copy_to(in6_addr & addr) const { +inline in6_addr&IP6Addr::copy_to(in6_addr&addr) const { self_type::reorder(addr, _addr._raw); return addr; } @@ -1866,19 +2034,19 @@ inline in6_addr IP6Addr::network_order() const { return this->copy_to(zret); } -inline auto IP6Addr::operator = (in6_addr const& addr) -> self_type & { +inline auto IP6Addr::operator=(in6_addr const&addr) -> self_type& { self_type::reorder(_addr._raw, addr); return *this; } -inline auto IP6Addr::operator = (sockaddr_in6 const* addr) -> self_type & { +inline auto IP6Addr::operator=(sockaddr_in6 const *addr) -> self_type& { if (addr) { return *this = addr->sin6_addr; } this->clear(); } -inline IP6Addr & +inline IP6Addr& IP6Addr::operator++() { if (++(_addr._store[1]) == 0) { ++(_addr._store[0]); @@ -1886,7 +2054,7 @@ IP6Addr::operator++() { return *this; } -inline IP6Addr & +inline IP6Addr& IP6Addr::operator--() { if (--(_addr._store[1]) == ~static_cast<uint64_t >(0)) { --(_addr._store[0]); @@ -1895,48 +2063,50 @@ IP6Addr::operator--() { } inline void IP6Addr::reorder(unsigned char dst[WORD_SIZE], unsigned char const src[WORD_SIZE]) { - for (size_t idx = 0 ; idx < WORD_SIZE ; ++idx ) { + for (size_t idx = 0; idx < WORD_SIZE; ++idx) { dst[idx] = src[WORD_SIZE - (idx + 1)]; } } -inline bool operator == (IP6Addr const& lhs, IP6Addr const& rhs) { +inline bool operator==(IP6Addr const&lhs, IP6Addr const&rhs) { return lhs._addr._store[0] == rhs._addr._store[0] && lhs._addr._store[1] == rhs._addr._store[1]; } -inline bool operator != (IP6Addr const& lhs, IP6Addr const& rhs) { +inline bool operator!=(IP6Addr const&lhs, IP6Addr const&rhs) { return lhs._addr._store[0] != rhs._addr._store[0] || lhs._addr._store[1] != rhs._addr._store[1]; } -inline bool operator < (IP6Addr const& lhs, IP6Addr const& rhs) { - return lhs._addr._store[0] < rhs._addr._store[0] || (lhs._addr._store[0] == rhs._addr._store[0] && lhs._addr._store[1] < rhs._addr._store[1]); +inline bool operator<(IP6Addr const&lhs, IP6Addr const&rhs) { + return lhs._addr._store[0] < rhs._addr._store[0] || + (lhs._addr._store[0] == rhs._addr._store[0] && lhs._addr._store[1] < rhs._addr._store[1]); } -inline bool operator > (IP6Addr const& lhs, IP6Addr const& rhs) { +inline bool operator>(IP6Addr const&lhs, IP6Addr const&rhs) { return rhs < lhs; } -inline bool operator <= (IP6Addr const& lhs, IP6Addr const& rhs) { - return lhs._addr._store[0] < rhs._addr._store[0] || (lhs._addr._store[0] == rhs._addr._store[0] && lhs._addr._store[1] <= rhs._addr._store[1]); +inline bool operator<=(IP6Addr const&lhs, IP6Addr const&rhs) { + return lhs._addr._store[0] < rhs._addr._store[0] || + (lhs._addr._store[0] == rhs._addr._store[0] && lhs._addr._store[1] <= rhs._addr._store[1]); } -inline bool operator >= (IP6Addr const& lhs, IP6Addr const& rhs) { +inline bool operator>=(IP6Addr const&lhs, IP6Addr const&rhs) { return rhs <= lhs; } -inline IP6Addr& IP6Addr::operator &= (IPMask const& mask) { +inline IP6Addr&IP6Addr::operator&=(IPMask const&mask) { if (mask._cidr < WORD_WIDTH) { _addr._store[MSW] &= (~word_type{0} << (WORD_WIDTH - mask._cidr)); _addr._store[LSW] = 0; - } else if (mask._cidr < WIDTH){ + } else if (mask._cidr < WIDTH) { _addr._store[LSW] &= (~word_type{0} << (2 * WORD_WIDTH - mask._cidr)); } return *this; } -inline IP6Addr& IP6Addr::operator |= (IPMask const& mask) { +inline IP6Addr&IP6Addr::operator|=(IPMask const&mask) { if (mask._cidr < WORD_WIDTH) { _addr._store[MSW] |= (~word_type{0} >> mask._cidr); _addr._store[LSW] = ~word_type{0}; @@ -1948,65 +2118,65 @@ inline IP6Addr& IP6Addr::operator |= (IPMask const& mask) { // Disambiguating comparisons. -inline bool operator == (IPAddr const& lhs, IP4Addr const& rhs) { +inline bool operator==(IPAddr const&lhs, IP4Addr const&rhs) { return lhs.is_ip4() && static_cast<IP4Addr const&>(lhs) == rhs; } -inline bool operator != (IPAddr const& lhs, IP4Addr const& rhs) { - return ! lhs.is_ip4() || static_cast<IP4Addr const&>(lhs) != rhs; +inline bool operator!=(IPAddr const&lhs, IP4Addr const&rhs) { + return !lhs.is_ip4() || static_cast<IP4Addr const&>(lhs) != rhs; } -inline bool operator == (IP4Addr const& lhs, IPAddr const& rhs) { +inline bool operator==(IP4Addr const&lhs, IPAddr const&rhs) { return rhs.is_ip4() && lhs == static_cast<IP4Addr const&>(rhs); } -inline bool operator != (IP4Addr const& lhs, IPAddr const& rhs) { - return ! rhs.is_ip4() || lhs != static_cast<IP4Addr const&>(rhs); +inline bool operator!=(IP4Addr const&lhs, IPAddr const&rhs) { + return !rhs.is_ip4() || lhs != static_cast<IP4Addr const&>(rhs); } -inline bool operator == (IPAddr const& lhs, IP6Addr const& rhs) { +inline bool operator==(IPAddr const&lhs, IP6Addr const&rhs) { return lhs.is_ip6() && static_cast<IP6Addr const&>(lhs) == rhs; } -inline bool operator != (IPAddr const& lhs, IP6Addr const& rhs) { - return ! lhs.is_ip6() || static_cast<IP6Addr const&>(lhs) != rhs; +inline bool operator!=(IPAddr const&lhs, IP6Addr const&rhs) { + return !lhs.is_ip6() || static_cast<IP6Addr const&>(lhs) != rhs; } -inline bool operator == (IP6Addr const& lhs, IPAddr const& rhs) { +inline bool operator==(IP6Addr const&lhs, IPAddr const&rhs) { return rhs.is_ip6() && lhs == static_cast<IP6Addr const&>(rhs); } -inline bool operator != (IP6Addr const& lhs, IPAddr const& rhs) { - return ! rhs.is_ip6() || lhs != static_cast<IP6Addr const&>(rhs); +inline bool operator!=(IP6Addr const&lhs, IPAddr const&rhs) { + return !rhs.is_ip6() || lhs != static_cast<IP6Addr const&>(rhs); } // +++ IPRange +++ -inline IP4Range::IP4Range(string_view const& text) { +inline IP4Range::IP4Range(string_view const&text) { this->load(text); } -inline auto IP4Range::networks() const -> NetSource { - return { NetSource{*this} }; +inline auto IP4Range::networks() const -> NetSource { + return {NetSource{*this}}; } -inline IP6Range::IP6Range(string_view const& text) { +inline IP6Range::IP6Range(string_view const&text) { this->load(text); } -inline auto IP6Range::networks() const -> NetSource { - return { NetSource{*this} }; +inline auto IP6Range::networks() const -> NetSource { + return {NetSource{*this}}; } -inline IPRange::IPRange(IP4Range const& range) : _family(AF_INET) { +inline IPRange::IPRange(IP4Range const&range) : _family(AF_INET) { _range._ip4 = range; } -inline IPRange::IPRange(IP6Range const& range) : _family(AF_INET6) { +inline IPRange::IPRange(IP6Range const&range) : _family(AF_INET6) { _range._ip6 = range; } -inline IPRange::IPRange(string_view const& text) { +inline IPRange::IPRange(string_view const&text) { this->load(text); } @@ -2023,17 +2193,17 @@ inline auto IPMask::width() const -> raw_type { } inline bool -operator==(IPMask const &lhs, IPMask const &rhs) { +operator==(IPMask const&lhs, IPMask const&rhs) { return lhs.width() == rhs.width(); } inline bool -operator!=(IPMask const &lhs, IPMask const &rhs) { +operator!=(IPMask const&lhs, IPMask const&rhs) { return lhs.width() != rhs.width(); } inline bool -operator<(IPMask const &lhs, IPMask const &rhs) { +operator<(IPMask const&lhs, IPMask const&rhs) { return lhs.width() < rhs.width(); } @@ -2041,69 +2211,107 @@ inline IP4Addr IPMask::as_ip4() const { static constexpr auto MASK = ~in_addr_t{0}; in_addr_t addr = MASK; if (_cidr < IP4Addr::WIDTH) { - addr <<=IP4Addr::WIDTH - _cidr; + addr <<= IP4Addr::WIDTH - _cidr; } - return IP4Addr{ addr }; + return IP4Addr{addr}; } // +++ mixed operators +++ -inline IP4Addr operator & (IP4Addr const& addr, IPMask const& mask) { +inline IP4Addr operator&(IP4Addr const&addr, IPMask const&mask) { return IP4Addr{addr} &= mask; } -inline IP4Addr operator | (IP4Addr const& addr, IPMask const& mask) { - return IP4Addr {addr} |= mask; +inline IP4Addr operator|(IP4Addr const&addr, IPMask const&mask) { + return IP4Addr{addr} |= mask; } -inline IP6Addr operator & (IP6Addr const& addr, IPMask const& mask) { +inline IP6Addr operator&(IP6Addr const&addr, IPMask const&mask) { return IP6Addr{addr} &= mask; } -inline IP6Addr operator | (IP6Addr const& addr, IPMask const& mask) { +inline IP6Addr operator|(IP6Addr const&addr, IPMask const&mask) { return IP6Addr{addr} |= mask; } -inline IPAddr operator & (IPAddr const& addr, IPMask const& mask) { +inline IPAddr operator&(IPAddr const&addr, IPMask const&mask) { return IPAddr{addr} &= mask; } -inline IPAddr operator | (IPAddr const& addr, IPMask const& mask) { - return IPAddr {addr} |= mask; +inline IPAddr operator|(IPAddr const&addr, IPMask const&mask) { + return IPAddr{addr} |= mask; } // +++ IPNet +++ inline IP4Net::IP4Net(swoc::IP4Addr addr, swoc::IPMask mask) : _addr(addr & mask), _mask(mask) {} -inline IPMask const& IP4Net::mask() const { return _mask; } + +inline IPMask const&IP4Net::mask() const { return _mask; } + inline bool IP4Net::is_valid() const { return _mask.is_valid(); } + inline IP4Addr IP4Net::lower_bound() const { return _addr; } + inline IP4Addr IP4Net::upper_bound() const { return _addr | _mask; } -inline IP4Range IP4Net::as_range() const { return { this->lower_bound(), this->upper_bound()}; } + +inline IP4Range IP4Net::as_range() const { return {this->lower_bound(), this->upper_bound()}; } + +inline bool IP4Net::operator==(self_type const&that) const { + return _mask == that._mask && _addr == that._addr; +} + +inline bool IP4Net::operator!=(self_type const&that) const { + return _mask != that._mask || _addr != that._addr; +} + +inline IP4Net::self_type&IP4Net::assign(IP4Addr const&addr, IPMask const&mask) { + _addr = addr & mask; + _mask = mask; + return *this; +} inline IP6Net::IP6Net(swoc::IP6Addr addr, swoc::IPMask mask) : _addr(addr & mask), _mask(mask) {} -inline IPMask const& IP6Net::mask() const { return _mask; } + +inline IPMask const&IP6Net::mask() const { return _mask; } + inline bool IP6Net::is_valid() const { return _mask.is_valid(); } + inline IP6Addr IP6Net::lower_bound() const { return _addr; } + inline IP6Addr IP6Net::upper_bound() const { return _addr | _mask; } -inline IP6Range IP6Net::as_range() const { return { this->lower_bound(), this->upper_bound()}; } -inline IPNet::IPNet(IPAddr const &addr, IPMask const &mask) : _addr(addr & mask), _mask(mask) {} +inline IP6Range IP6Net::as_range() const { return {this->lower_bound(), this->upper_bound()}; } -inline IPNet::operator IPAddr const &() const { +inline bool IP6Net::operator==(self_type const&that) const { + return _mask == that._mask && _addr == that._addr; +} + +inline bool IP6Net::operator!=(self_type const&that) const { + return _mask != that._mask || _addr != that._addr; +} + +inline IP6Net::self_type&IP6Net::assign(IP6Addr const&addr, IPMask const&mask) { + _addr = addr & mask; + _mask = mask; + return *this; +} + +inline IPNet::IPNet(IPAddr const&addr, IPMask const&mask) : _addr(addr & mask), _mask(mask) {} + +inline IPNet::operator IPAddr const&() const { return _addr; } -inline IPNet::operator IPMask const &() const { +inline IPNet::operator IPMask const&() const { return _mask; } -inline IPAddr const & +inline IPAddr const& IPNet::addr() const { return _addr; } -inline IPMask const & +inline IPMask const& IPNet::mask() const { return _mask; } @@ -2131,18 +2339,19 @@ inline IP4Range::NetSource::iterator IP4Range::NetSource::end() const { return self_type{range_type{}}; } -inline IPMask IP4Range::NetSource::mask() const { return IPMask{ _cidr }; } +inline IPMask IP4Range::NetSource::mask() const { return IPMask{_cidr}; } inline auto IP4Range::NetSource::operator->() -> self_type * { return this; } -inline IP4Addr const& IP4Range::NetSource::addr() const { return _range.min(); } +inline IP4Addr const&IP4Range::NetSource::addr() const { return _range.min(); } -inline bool IP4Range::NetSource::operator==(IP4Range::NetSource::self_type const& that) { - return ((_cidr == that._cidr) && (_range == that._range)) || (_range.empty() && that._range.empty()); +inline bool IP4Range::NetSource::operator==(IP4Range::NetSource::self_type const&that) { + return ((_cidr == that._cidr) && (_range == that._range)) || + (_range.empty() && that._range.empty()); } inline bool IP4Range::NetSource::operator!=(IP4Range::NetSource::self_type const&that) { - return ! (*this == that); + return !(*this == that); } inline IP6Range::NetSource::iterator IP6Range::NetSource::begin() const { @@ -2159,22 +2368,24 @@ inline IP6Net IP6Range::NetSource::operator*() const { inline auto IP6Range::NetSource::operator->() -> self_type * { return this; } -inline bool IP6Range::NetSource::is_valid(IPMask const& mask) { +inline bool IP6Range::NetSource::is_valid(IPMask const&mask) { return ((_range.min() & mask) == _range.min()) && ((_range.min() | mask) <= _range.max()); } -inline bool IP6Range::NetSource::operator==(IP6Range::NetSource::self_type const& that) { - return ((_mask == that._mask) && (_range == that._range)) || (_range.empty() && that._range.empty()); +inline bool IP6Range::NetSource::operator==(IP6Range::NetSource::self_type const&that) { + return ((_mask == that._mask) && (_range == that._range)) || + (_range.empty() && that._range.empty()); } inline bool IP6Range::NetSource::operator!=(IP6Range::NetSource::self_type const&that) { - return ! (*this == that); + return !(*this == that); } // --- IPSpace -template < typename PAYLOAD > auto IPSpace<PAYLOAD>::mark(IPRange const &range, PAYLOAD const &payload) -> self_type & { +template<typename PAYLOAD> +auto IPSpace<PAYLOAD>::mark(IPRange const&range, PAYLOAD const&payload) -> self_type& { if (range.is(AF_INET)) { _ip4.mark(range, payload); } else if (range.is(AF_INET6)) { @@ -2183,7 +2394,8 @@ template < typename PAYLOAD > auto IPSpace<PAYLOAD>::mark(IPRange const &range, return *this; } -template < typename PAYLOAD > auto IPSpace<PAYLOAD>::fill(IPRange const &range, PAYLOAD const &payload) -> self_type & { +template<typename PAYLOAD> +auto IPSpace<PAYLOAD>::fill(IPRange const&range, PAYLOAD const&payload) -> self_type& { if (range.is(AF_INET6)) { _ip6.fill(range, payload); } else if (range.is(AF_INET)) { @@ -2193,8 +2405,8 @@ template < typename PAYLOAD > auto IPSpace<PAYLOAD>::fill(IPRange const &range, } template<typename PAYLOAD> -template<typename F, typename U > -auto IPSpace<PAYLOAD>::blend(IPRange const&range, U const&color, F&&blender) -> self_type & { +template<typename F, typename U> +auto IPSpace<PAYLOAD>::blend(IPRange const&range, U const&color, F&&blender) -> self_type& { if (range.is(AF_INET)) { _ip4.blend(range, color, blender); } else if (range.is(AF_INET6)) { @@ -2211,13 +2423,13 @@ void IPSpace<PAYLOAD>::clear() { template<typename PAYLOAD> auto IPSpace<PAYLOAD>::begin() const -> const_iterator { - auto nc_this = const_cast<self_type*>(this); + auto nc_this = const_cast<self_type *>(this); return const_iterator(nc_this->_ip4.begin(), nc_this->_ip6.begin()); } template<typename PAYLOAD> auto IPSpace<PAYLOAD>::end() const -> const_iterator { - auto nc_this = const_cast<self_type*>(this); + auto nc_this = const_cast<self_type *>(this); return const_iterator(nc_this->_ip4.end(), nc_this->_ip6.end()); } @@ -2225,34 +2437,36 @@ auto IPSpace<PAYLOAD>::end() const -> const_iterator { namespace std { -template <> class tuple_size<swoc::IP4Net> : public std::integral_constant<size_t, 2> {}; +template<> class tuple_size<swoc::IP4Net> : public std::integral_constant<size_t, 2> { +}; -template < size_t IDX > class tuple_element<IDX, swoc::IP4Net> { +template<size_t IDX> class tuple_element<IDX, swoc::IP4Net> { static_assert("swoc::IP4Net tuple index out of range"); }; -template <> class tuple_element<0, swoc::IP4Net> { +template<> class tuple_element<0, swoc::IP4Net> { public: using type = swoc::IP4Addr; }; -template <> class tuple_element<1, swoc::IP4Net> { +template<> class tuple_element<1, swoc::IP4Net> { public: using type = swoc::IPMask; }; -template <> class tuple_size<swoc::IP6Net> : public std::integral_constant<size_t, 2> {}; +template<> class tuple_size<swoc::IP6Net> : public std::integral_constant<size_t, 2> { +}; -template < size_t IDX > class tuple_element<IDX, swoc::IP6Net> { +template<size_t IDX> class tuple_element<IDX, swoc::IP6Net> { static_assert("swoc::IP6Net tuple index out of range"); }; -template <> class tuple_element<0, swoc::IP6Net> { +template<> class tuple_element<0, swoc::IP6Net> { public: using type = swoc::IP6Addr; }; -template <> class tuple_element<1, swoc::IP6Net> { +template<> class tuple_element<1, swoc::IP6Net> { public: using type = swoc::IPMask; }; @@ -2261,8 +2475,8 @@ public: namespace swoc { -template < size_t IDX > typename std::tuple_element<IDX, IP4Net>::type -get(swoc::IP4Net const& net) { +template<size_t IDX> typename std::tuple_element<IDX, IP4Net>::type +get(swoc::IP4Net const&net) { if constexpr (IDX == 0) { return net.lower_bound(); } else if constexpr (IDX == 1) { @@ -2270,8 +2484,8 @@ get(swoc::IP4Net const& net) { } } -template < size_t IDX > typename std::tuple_element<IDX, IP6Net>::type -get(swoc::IP6Net const& net) { +template<size_t IDX> typename std::tuple_element<IDX, IP6Net>::type +get(swoc::IP6Net const&net) { if constexpr (IDX == 0) { return net.lower_bound(); } else if constexpr (IDX == 1) { diff --git a/swoc++/src/swoc_ip.cc b/swoc++/src/swoc_ip.cc index 283b557..c53a0b0 100644 --- a/swoc++/src/swoc_ip.cc +++ b/swoc++/src/swoc_ip.cc @@ -618,6 +618,48 @@ IP6Addr IPMask::as_ip6() const { return { MASK, MASK }; } +// ++ IPNet ++ + +bool IP4Net::load(TextView text) { + auto idx = text.find('/'); + if (idx != text.npos) { + if (idx + 1 < text.size()) { // must have something past the separator or it's bogus. + IP4Addr addr; + if (addr.load(text.substr(0, idx))) { // load the address + IPMask mask; + text.remove_prefix(idx + 1); // drop address and separator. + if (mask.load(text)) { + this->assign(addr, mask); + return true; + } + } + } + } + + this->clear(); + return false; +} + +bool IP6Net::load(TextView text) { + auto idx = text.find('/'); + if (idx != text.npos) { + if (idx + 1 < text.size()) { // must have something past the separator or it's bogus. + IP6Addr addr; + if (addr.load(text.substr(0, idx))) { // load the address + IPMask mask; + text.remove_prefix(idx + 1); // drop address and separator. + if (mask.load(text)) { + this->assign(addr, mask); + return true; + } + } + } + } + + this->clear(); + return false; +} + // +++ IP4Range +++ IP4Range::IP4Range(swoc::IP4Addr const&addr, swoc::IPMask const&mask) { diff --git a/unit_tests/test_ip.cc b/unit_tests/test_ip.cc index 711282b..286d590 100644 --- a/unit_tests/test_ip.cc +++ b/unit_tests/test_ip.cc @@ -28,6 +28,9 @@ using swoc::IP6Range; using swoc::IPAddr; using swoc::IPRange; + +using swoc::IPMask; + using W = swoc::LocalBufferWriter<256>; TEST_CASE("Basic IP", "[libswoc][ip]") { @@ -63,7 +66,7 @@ TEST_CASE("Basic IP", "[libswoc][ip]") { REQUIRE(s.rest == rest); } - IP4Addr alpha { "172.96.12.134"}; + IP4Addr alpha{"172.96.12.134"}; CHECK(alpha == IP4Addr{"172.96.12.134"}); CHECK(alpha == IP4Addr{IPAddr{"172.96.12.134"}}); CHECK(alpha == IPAddr{IPEndpoint{"172.96.12.134:80"}}); @@ -275,7 +278,8 @@ TEST_CASE("IP ranges and networks", "[libswoc][ip][net][range]") { swoc::IP4Range r_2{"1.1.2.0-1.1.2.97"}; swoc::IP4Range r_3{"1.1.0.0-1.2.0.0"}; swoc::IP4Range r_4{"10.33.45.19-10.33.45.76"}; - swoc::IP6Range r_5{"2001:1f2d:c587:24c3:9128:3349:3cee:143-ffee:1f2d:c587:24c3:9128:3349:3cFF:FFFF"_tv}; + swoc::IP6Range r_5{ + "2001:1f2d:c587:24c3:9128:3349:3cee:143-ffee:1f2d:c587:24c3:9128:3349:3cFF:FFFF"_tv}; CHECK(true == r_0.empty()); CHECK(false == r_1.empty()); @@ -288,11 +292,218 @@ TEST_CASE("IP ranges and networks", "[libswoc][ip][net][range]") { swoc::IP6Addr a_1{"2001:1f2d:c587:24c4::"}; CHECK(a_1 == (a_1 & swoc::IPMask{62})); - for ( auto const& [ addr, mask ] : r_4.networks()) { - std::cout << W().print("{}/{}\n", addr, mask.width()); + std::array<swoc::IP4Net, 7> r_4_nets = + {{ + "10.33.45.19/32"_tv + , "10.33.45.20/30"_tv + , "10.33.45.24/29"_tv + , "10.33.45.32/27"_tv + , "10.33.45.64/29"_tv + , "10.33.45.72/30"_tv + , "10.33.45.76/32"_tv + }}; + auto r4_net = r_4_nets.begin(); + for (auto const&net : r_4.networks()) { + REQUIRE(r4_net != r_4_nets.end()); + CHECK(*r4_net == net); + ++r4_net; } - for ( auto const& [ addr, mask ] : r_5.networks()) { - std::cout << W().print("{}/{}\n", addr, mask.width()); + + std::array<swoc::IP6Net, 130> r_5_nets = + {{ + {IP6Addr{ + "2001:1f2d:c587:24c3:9128:3349:3cee:143"}, IPMask{ + 128}} + , {IP6Addr{ + "2001:1f2d:c587:24c3:9128:3349:3cee:144"}, IPMask{126}} + , {IP6Addr{ + "2001:1f2d:c587:24c3:9128:3349:3cee:148"}, IPMask{125}} + , {IP6Addr{ + "2001:1f2d:c587:24c3:9128:3349:3cee:150"}, IPMask{124}} + , {IP6Addr{ + "2001:1f2d:c587:24c3:9128:3349:3cee:160"}, IPMask{123}} + , {IP6Addr{ + "2001:1f2d:c587:24c3:9128:3349:3cee:180"}, IPMask{121}} + , {IP6Addr{ + "2001:1f2d:c587:24c3:9128:3349:3cee:200"}, IPMask{119}} + , {IP6Addr{ + "2001:1f2d:c587:24c3:9128:3349:3cee:400"}, IPMask{118}} + , {IP6Addr{ + "2001:1f2d:c587:24c3:9128:3349:3cee:800"}, IPMask{117}} + , {IP6Addr{ + "2001:1f2d:c587:24c3:9128:3349:3cee:1000"}, IPMask{116}} + , {IP6Addr{ + "2001:1f2d:c587:24c3:9128:3349:3cee:2000"}, IPMask{115}} + , {IP6Addr{ + "2001:1f2d:c587:24c3:9128:3349:3cee:4000"}, IPMask{114}} + , {IP6Addr{ + "2001:1f2d:c587:24c3:9128:3349:3cee:8000"}, IPMask{113}} + , {IP6Addr{ + "2001:1f2d:c587:24c3:9128:3349:3cef:0"}, IPMask{112}} + , {IP6Addr{ + "2001:1f2d:c587:24c3:9128:3349:3cf0:0"}, IPMask{108}} + , {IP6Addr{ + "2001:1f2d:c587:24c3:9128:3349:3d00:0"}, IPMask{104}} + , {IP6Addr{ + "2001:1f2d:c587:24c3:9128:3349:3e00:0"}, IPMask{103}} + , {IP6Addr{ + "2001:1f2d:c587:24c3:9128:3349:4000:0"}, IPMask{98}} + , {IP6Addr{ + "2001:1f2d:c587:24c3:9128:3349:8000:0"}, IPMask{97}} + , {IP6Addr{ + "2001:1f2d:c587:24c3:9128:334a::"}, IPMask{95}} + , {IP6Addr{ + "2001:1f2d:c587:24c3:9128:334c::"}, IPMask{94}} + , {IP6Addr{ + "2001:1f2d:c587:24c3:9128:3350::"}, IPMask{92}} + , {IP6Addr{ + "2001:1f2d:c587:24c3:9128:3360::"}, IPMask{91}} + , {IP6Addr{ + "2001:1f2d:c587:24c3:9128:3380::"}, IPMask{89}} + , {IP6Addr{ + "2001:1f2d:c587:24c3:9128:3400::"}, IPMask{86}} + , {IP6Addr{ + "2001:1f2d:c587:24c3:9128:3800::"}, IPMask{85}} + , {IP6Addr{ + "2001:1f2d:c587:24c3:9128:4000::"}, IPMask{82}} + , {IP6Addr{ + "2001:1f2d:c587:24c3:9128:8000::"}, IPMask{81}} + , {IP6Addr{"2001:1f2d:c587:24c3:9129::"}, IPMask{ + 80}} + , {IP6Addr{"2001:1f2d:c587:24c3:912a::"}, IPMask{ + 79}} + , {IP6Addr{"2001:1f2d:c587:24c3:912c::"}, IPMask{ + 78}} + , {IP6Addr{"2001:1f2d:c587:24c3:9130::"}, IPMask{ + 76}} + , {IP6Addr{"2001:1f2d:c587:24c3:9140::"}, IPMask{ + 74}} + , {IP6Addr{"2001:1f2d:c587:24c3:9180::"}, IPMask{ + 73}} + , {IP6Addr{"2001:1f2d:c587:24c3:9200::"}, IPMask{ + 71}} + , {IP6Addr{"2001:1f2d:c587:24c3:9400::"}, IPMask{ + 70}} + , {IP6Addr{"2001:1f2d:c587:24c3:9800::"}, IPMask{ + 69}} + , {IP6Addr{"2001:1f2d:c587:24c3:a000::"}, IPMask{ + 67}} + , {IP6Addr{"2001:1f2d:c587:24c3:c000::"}, IPMask{ + 66}} + , {IP6Addr{"2001:1f2d:c587:24c4::"}, IPMask{62}} + , {IP6Addr{"2001:1f2d:c587:24c8::"}, IPMask{61}} + , {IP6Addr{"2001:1f2d:c587:24d0::"}, IPMask{60}} + , {IP6Addr{"2001:1f2d:c587:24e0::"}, IPMask{59}} + , {IP6Addr{"2001:1f2d:c587:2500::"}, IPMask{56}} + , {IP6Addr{"2001:1f2d:c587:2600::"}, IPMask{55}} + , {IP6Addr{"2001:1f2d:c587:2800::"}, IPMask{53}} + , {IP6Addr{"2001:1f2d:c587:3000::"}, IPMask{52}} + , {IP6Addr{"2001:1f2d:c587:4000::"}, IPMask{50}} + , {IP6Addr{"2001:1f2d:c587:8000::"}, IPMask{49}} + , {IP6Addr{"2001:1f2d:c588::"}, IPMask{45}} + , {IP6Addr{"2001:1f2d:c590::"}, IPMask{44}} + , {IP6Addr{"2001:1f2d:c5a0::"}, IPMask{43}} + , {IP6Addr{"2001:1f2d:c5c0::"}, IPMask{42}} + , {IP6Addr{"2001:1f2d:c600::"}, IPMask{39}} + , {IP6Addr{"2001:1f2d:c800::"}, IPMask{37}} + , {IP6Addr{"2001:1f2d:d000::"}, IPMask{36}} + , {IP6Addr{"2001:1f2d:e000::"}, IPMask{35}} + , {IP6Addr{"2001:1f2e::"}, IPMask{31}} + , {IP6Addr{"2001:1f30::"}, IPMask{28}} + , {IP6Addr{"2001:1f40::"}, IPMask{26}} + , {IP6Addr{"2001:1f80::"}, IPMask{25}} + , {IP6Addr{"2001:2000::"}, IPMask{19}} + , {IP6Addr{"2001:4000::"}, IPMask{18}} + , {IP6Addr{"2001:8000::"}, IPMask{17}} + , {IP6Addr{"2002::"}, IPMask{15}} + , {IP6Addr{"2004::"}, IPMask{14}} + , {IP6Addr{"2008::"}, IPMask{13}} + , {IP6Addr{"2010::"}, IPMask{12}} + , {IP6Addr{"2020::"}, IPMask{11}} + , {IP6Addr{"2040::"}, IPMask{10}} + , {IP6Addr{"2080::"}, IPMask{9}} + , {IP6Addr{"2100::"}, IPMask{8}} + , {IP6Addr{"2200::"}, IPMask{7}} + , {IP6Addr{"2400::"}, IPMask{6}} + , {IP6Addr{"2800::"}, IPMask{5}} + , {IP6Addr{"3000::"}, IPMask{4}} + , {IP6Addr{"4000::"}, IPMask{2}} + , {IP6Addr{"8000::"}, IPMask{2}} + , {IP6Addr{"c000::"}, IPMask{3}} + , {IP6Addr{"e000::"}, IPMask{4}} + , {IP6Addr{"f000::"}, IPMask{5}} + , {IP6Addr{"f800::"}, IPMask{6}} + , {IP6Addr{"fc00::"}, IPMask{7}} + , {IP6Addr{"fe00::"}, IPMask{8}} + , {IP6Addr{"ff00::"}, IPMask{9}} + , {IP6Addr{"ff80::"}, IPMask{10}} + , {IP6Addr{"ffc0::"}, IPMask{11}} + , {IP6Addr{"ffe0::"}, IPMask{13}} + , {IP6Addr{"ffe8::"}, IPMask{14}} + , {IP6Addr{"ffec::"}, IPMask{15}} + , {IP6Addr{"ffee::"}, IPMask{20}} + , {IP6Addr{"ffee:1000::"}, IPMask{21}} + , {IP6Addr{"ffee:1800::"}, IPMask{22}} + , {IP6Addr{"ffee:1c00::"}, IPMask{23}} + , {IP6Addr{"ffee:1e00::"}, IPMask{24}} + , {IP6Addr{"ffee:1f00::"}, IPMask{27}} + , {IP6Addr{"ffee:1f20::"}, IPMask{29}} + , {IP6Addr{"ffee:1f28::"}, IPMask{30}} + , {IP6Addr{"ffee:1f2c::"}, IPMask{32}} + , {IP6Addr{"ffee:1f2d::"}, IPMask{33}} + , {IP6Addr{"ffee:1f2d:8000::"}, IPMask{34}} + , {IP6Addr{"ffee:1f2d:c000::"}, IPMask{38}} + , {IP6Addr{"ffee:1f2d:c400::"}, IPMask{40}} + , {IP6Addr{"ffee:1f2d:c500::"}, IPMask{41}} + , {IP6Addr{"ffee:1f2d:c580::"}, IPMask{46}} + , {IP6Addr{"ffee:1f2d:c584::"}, IPMask{47}} + , {IP6Addr{"ffee:1f2d:c586::"}, IPMask{48}} + , {IP6Addr{"ffee:1f2d:c587::"}, IPMask{51}} + , {IP6Addr{"ffee:1f2d:c587:2000::"}, IPMask{54}} + , {IP6Addr{"ffee:1f2d:c587:2400::"}, IPMask{57}} + , {IP6Addr{"ffee:1f2d:c587:2480::"}, IPMask{58}} + , {IP6Addr{"ffee:1f2d:c587:24c0::"}, IPMask{63}} + , {IP6Addr{"ffee:1f2d:c587:24c2::"}, IPMask{64}} + , {IP6Addr{"ffee:1f2d:c587:24c3::"}, IPMask{65}} + , {IP6Addr{"ffee:1f2d:c587:24c3:8000::"}, IPMask{ + 68}} + , {IP6Addr{"ffee:1f2d:c587:24c3:9000::"}, IPMask{ + 72}} + , {IP6Addr{"ffee:1f2d:c587:24c3:9100::"}, IPMask{ + 75}} + , {IP6Addr{"ffee:1f2d:c587:24c3:9120::"}, IPMask{ + 77}} + , {IP6Addr{"ffee:1f2d:c587:24c3:9128::"}, IPMask{ + 83}} + , {IP6Addr{ + "ffee:1f2d:c587:24c3:9128:2000::"}, IPMask{84}} + , {IP6Addr{ + "ffee:1f2d:c587:24c3:9128:3000::"}, IPMask{87}} + , {IP6Addr{ + "ffee:1f2d:c587:24c3:9128:3200::"}, IPMask{88}} + , {IP6Addr{ + "ffee:1f2d:c587:24c3:9128:3300::"}, IPMask{90}} + , {IP6Addr{ + "ffee:1f2d:c587:24c3:9128:3340::"}, IPMask{93}} + , {IP6Addr{ + "ffee:1f2d:c587:24c3:9128:3348::"}, IPMask{96}} + , {IP6Addr{ + "ffee:1f2d:c587:24c3:9128:3349::"}, IPMask{99}} + , {IP6Addr{ + "ffee:1f2d:c587:24c3:9128:3349:2000:0"}, IPMask{100}} + , {IP6Addr{ + "ffee:1f2d:c587:24c3:9128:3349:3000:0"}, IPMask{101}} + , {IP6Addr{ + "ffee:1f2d:c587:24c3:9128:3349:3800:0"}, IPMask{102}} + , {IP6Addr{ + "ffee:1f2d:c587:24c3:9128:3349:3c00:0"}, IPMask{104}} + }}; + + auto r5_net = r_5_nets.begin(); + for (auto const&[addr, mask] : r_5.networks()) { + REQUIRE(r5_net != r_5_nets.end()); + CHECK(*r5_net == swoc::IP6Net{addr, mask}); + ++r5_net; } } @@ -368,15 +579,15 @@ TEST_CASE("IP Space Int", "[libswoc][ip][ipspace]") { std::array<std::tuple<TextView, int>, 9> ranges = { { - { "100.0.0.0-100.0.0.255", 0 } - , { "100.0.1.0-100.0.1.255", 1 } - , { "100.0.2.0-100.0.2.255", 2 } - , { "100.0.3.0-100.0.3.255", 3 } - , { "100.0.4.0-100.0.4.255", 4 } - , { "100.0.5.0-100.0.5.255", 5 } - , { "100.0.6.0-100.0.6.255", 6 } - , { "100.0.0.0-100.0.0.255", 31 } - , { "100.0.1.0-100.0.1.255", 30 } + {"100.0.0.0-100.0.0.255", 0} + , {"100.0.1.0-100.0.1.255", 1} + , {"100.0.2.0-100.0.2.255", 2} + , {"100.0.3.0-100.0.3.255", 3} + , {"100.0.4.0-100.0.4.255", 4} + , {"100.0.5.0-100.0.5.255", 5} + , {"100.0.6.0-100.0.6.255", 6} + , {"100.0.0.0-100.0.0.255", 31} + , {"100.0.1.0-100.0.1.255", 30} }}; space.clear(); @@ -420,7 +631,7 @@ TEST_CASE("IPSpace bitset", "[libswoc][ipspace][bitset]") { TEST_CASE("IPSpace docJJ", "[libswoc][ipspace][docJJ]") { using PAYLOAD = std::bitset<32>; using Space = swoc::IPSpace<PAYLOAD>; - auto blender = [](PAYLOAD& lhs, PAYLOAD const& rhs) -> bool { + auto blender = [](PAYLOAD&lhs, PAYLOAD const&rhs) -> bool { lhs |= rhs; return true; }; @@ -434,26 +645,26 @@ TEST_CASE("IPSpace docJJ", "[libswoc][ipspace][docJJ]") { std::array<std::tuple<TextView, std::initializer_list<unsigned>>, 9> ranges = { { - { "100.0.0.0-100.0.0.255", { 0 } } - , { "100.0.1.0-100.0.1.255", { 1 } } - , { "100.0.2.0-100.0.2.255", { 2 } } - , { "100.0.3.0-100.0.3.255", { 3 } } - , { "100.0.4.0-100.0.4.255", { 4 } } - , { "100.0.5.0-100.0.5.255", { 5 } } - , { "100.0.6.0-100.0.6.255", { 6 } } - , { "100.0.0.0-100.0.0.255", { 31 } } - , { "100.0.1.0-100.0.1.255", { 30 } } + {"100.0.0.0-100.0.0.255", {0}} + , {"100.0.1.0-100.0.1.255", {1}} + , {"100.0.2.0-100.0.2.255", {2}} + , {"100.0.3.0-100.0.3.255", {3}} + , {"100.0.4.0-100.0.4.255", {4}} + , {"100.0.5.0-100.0.5.255", {5}} + , {"100.0.6.0-100.0.6.255", {6}} + , {"100.0.0.0-100.0.0.255", {31}} + , {"100.0.1.0-100.0.1.255", {30}} }}; std::array<std::initializer_list<unsigned>, 7> results = {{ - { 0, 31 } - , { 1, 30 } - , { 2 } - , { 3 } - , { 4 } - , { 5 } - , { 6 } - }}; + {0, 31} + , {1, 30} + , {2} + , {3} + , {4} + , {5} + , {6} + }}; Space space; @@ -467,15 +678,15 @@ TEST_CASE("IPSpace docJJ", "[libswoc][ipspace][docJJ]") { unsigned idx; idx = 0; - for ( auto const& [ range, bits ] : space) { + for (auto const&[range, bits] : space) { REQUIRE(idx < results.size()); CHECK(bits == make_bits(results[idx])); ++idx; } idx = results.size(); - for ( auto spot = space.end() ; spot != space.begin() ; ) { - auto const& [ range, bits ] { *--spot }; + for (auto spot = space.end(); spot != space.begin();) { + auto const&[range, bits]{*--spot}; REQUIRE(idx > 0); --idx; CHECK(bits == make_bits(results[idx]));
