summaryrefslogtreecommitdiffstats
path: root/src/lib/asiolink/io_address.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/asiolink/io_address.h')
-rw-r--r--src/lib/asiolink/io_address.h329
1 files changed, 329 insertions, 0 deletions
diff --git a/src/lib/asiolink/io_address.h b/src/lib/asiolink/io_address.h
new file mode 100644
index 0000000..d08753b
--- /dev/null
+++ b/src/lib/asiolink/io_address.h
@@ -0,0 +1,329 @@
+// Copyright (C) 2010-2023 Internet Systems Consortium, Inc. ("ISC")
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#ifndef IO_ADDRESS_H
+#define IO_ADDRESS_H 1
+
+// IMPORTANT NOTE: only very few ASIO headers files can be included in
+// this file. In particular, asio.hpp should never be included here.
+// See the description of the namespace below.
+#include <unistd.h> // for some network system calls
+#include <stdint.h> // for uint32_t
+#include <boost/asio/ip/address.hpp>
+
+#include <functional>
+#include <string>
+#include <vector>
+
+#include <exceptions/exceptions.h>
+
+namespace isc {
+namespace asiolink {
+
+ /// Defines length of IPv6 address (in binary format).
+ static constexpr size_t V6ADDRESS_LEN = 16;
+
+ /// Defines length of IPv4 address (in binary format).
+ static constexpr size_t V4ADDRESS_LEN = 4;
+
+ /// @brief Maximum size of an IPv4 address represented as a text string. 12
+ /// digits plus 3 full stops (dots).
+ static constexpr size_t V4ADDRESS_TEXT_MAX_LEN = 15u;
+
+ /// @brief Maximum size of an IPv6 address represented as a text string. 32
+ /// hexadecimal characters written in 8 groups of four, plus 7 colon
+ /// separators.
+ static constexpr size_t V6ADDRESS_TEXT_MAX_LEN = 39u;
+
+/// \brief The \c IOAddress class represents an IP addresses (version
+/// agnostic)
+///
+/// This class is a wrapper for the ASIO \c ip::address class.
+class IOAddress {
+public:
+
+ /// \brief An \c IOAddress hash enabling the use in the unordered
+ /// STL containers.
+ struct Hash {
+ /// \brief A hashing operator.
+ ///
+ /// \param io_address an address to be hashed.
+ /// \return a hashing result.
+ size_t operator()(const IOAddress &io_address) const;
+ };
+
+ ///
+ /// \name Constructors and Destructor
+ ///
+ /// This class is copyable. We use default versions of copy constructor
+ /// and the assignment operator.
+ /// We use the default destructor.
+ //@{
+ /// \brief Constructor from string.
+ ///
+ /// This constructor converts a textual representation of IPv4 and IPv6
+ /// addresses into an IOAddress object.
+ /// If \c address_str is not a valid representation of any type of
+ /// address, an exception of class \c IOError will be thrown.
+ /// This constructor allocates memory for the object, and if that fails
+ /// a corresponding standard exception will be thrown.
+ ///
+ /// \param address_str Textual representation of address.
+ IOAddress(const std::string& address_str);
+
+ /// \brief Constructor from an ASIO \c ip::address object.
+ ///
+ /// This constructor is intended to be used within the wrapper
+ /// implementation; user applications of the wrapper API won't use it.
+ ///
+ /// This constructor never throws an exception.
+ ///
+ /// \param asio_address The ASIO \c ip::address to be converted.
+ IOAddress(const boost::asio::ip::address& asio_address);
+ //@}
+
+ /// @brief Constructor for ip::address_v4 object.
+ ///
+ /// This constructor is intended to be used when constructing
+ /// IPv4 address out of uint32_t type. Passed value must be in
+ /// network byte order
+ ///
+ /// @param v4address IPv4 address represented by uint32_t
+ IOAddress(uint32_t v4address);
+
+ /// \brief Convert the address to a string.
+ ///
+ /// This method is basically expected to be exception free, but
+ /// generating the string will involve resource allocation,
+ /// and if it fails the corresponding standard exception will be thrown.
+ ///
+ /// \return A string representation of the address.
+ std::string toText() const;
+
+ /// \brief Returns the address family
+ ///
+ /// \return AF_INET for IPv4 or AF_INET6 for IPv6.
+ short getFamily() const;
+
+ /// \brief Convenience function to check for an IPv4 address
+ ///
+ /// \return true if the address is a V4 address
+ bool isV4() const {
+ return (asio_address_.is_v4());
+ }
+
+ /// \brief Convenience function to check if it is an IPv4 zero address.
+ ///
+ /// \return true if the address is the zero IPv4 address.
+ bool isV4Zero() const {
+ return (equals(IPV4_ZERO_ADDRESS()));
+ }
+
+ /// \brief Convenience function to check if it is an IPv4 broadcast
+ /// address.
+ ///
+ /// \return true if the address is the broadcast IPv4 address.
+ bool isV4Bcast() const {
+ return (equals(IPV4_BCAST_ADDRESS()));
+ }
+
+ /// \brief Convenience function to check for an IPv6 address
+ ///
+ /// \return true if the address is a V6 address
+ bool isV6() const {
+ return (asio_address_.is_v6());
+ }
+
+ /// \brief Convenience function to check if it is an IPv4 zero address.
+ ///
+ /// \return true if the address is the zero IPv4 address.
+ bool isV6Zero() const {
+ return (equals(IPV6_ZERO_ADDRESS()));
+ }
+
+ /// \brief checks whether and address is IPv6 and is link-local
+ ///
+ /// \return true if the address is IPv6 link-local, false otherwise
+ bool isV6LinkLocal() const;
+
+ /// \brief checks whether and address is IPv6 and is multicast
+ ///
+ /// \return true if the address is IPv6 multicast, false otherwise
+ bool isV6Multicast() const;
+
+ /// \brief Creates an address from over wire data.
+ ///
+ /// \param family AF_INET for IPv4 or AF_INET6 for IPv6.
+ /// \param data pointer to first char of data
+ ///
+ /// \return Created IOAddress object
+ static IOAddress fromBytes(short family, const uint8_t* data);
+
+ /// \brief Return address as set of bytes
+ ///
+ /// \return Contents of the address as a set of bytes in network-byte
+ /// order.
+ std::vector<uint8_t> toBytes() const;
+
+ /// \brief Compare addresses for equality
+ ///
+ /// \param other Address to compare against.
+ ///
+ /// \return true if addresses are equal, false if not.
+ bool equals(const IOAddress& other) const {
+ return (asio_address_ == other.asio_address_);
+ }
+
+ /// \brief Compare addresses for equality
+ ///
+ /// \param other Address to compare against.
+ ///
+ /// \return true if addresses are equal, false if not.
+ bool operator==(const IOAddress& other) const {
+ return equals(other);
+ }
+
+ /// \brief Compare addresses for inequality
+ ///
+ /// \param other Address to compare against.
+ ///
+ /// \return false if addresses are equal, true if not.
+ bool nequals(const IOAddress& other) const {
+ return (!equals(other));
+ }
+
+ /// \brief Checks if one address is smaller than the other
+ ///
+ /// \param other Address to compare against.
+ bool operator<(const IOAddress& other) const {
+ return (asio_address_ < other.asio_address_);
+ }
+
+ /// \brief Checks if one address is smaller or equal than the other
+ ///
+ /// \param other Address to compare against.
+ bool operator<=(const IOAddress& other) const {
+ return (asio_address_ <= other.asio_address_);
+ }
+
+ /// \brief Compare addresses for inequality
+ ///
+ /// \param other Address to compare against.
+ ///
+ /// \return false if addresses are equal, true if not.
+ bool operator!=(const IOAddress& other) const {
+ return (nequals(other));
+ }
+
+ /// @brief Subtracts one address from another (a - b)
+ ///
+ /// Treats addresses as integers and subtracts them. For example:
+ /// @code
+ /// 192.0.2.5 - 192.0.2.0 = 0.0.0.5
+ /// fe80::abcd - fe80:: = ::abcd
+ /// @endcode
+ ///
+ /// It is possible to subtract greater from lesser address, e.g.
+ /// 192.168.56.10 - 192.168.67.20, but please do understand that
+ /// the address space is a finite field in mathematical sense, so
+ /// you may end up with a result that is greater then any of the
+ /// addresses you specified. Also, subtraction is not commutative,
+ /// so a - b != b - a.
+ ///
+ /// This operation is essential for calculating the number of
+ /// leases in a pool, where we need to calculate (max - min).
+ /// @throw BadValue if addresses are of different family
+ /// @param a address to be subtracted from
+ /// @param b address to be subtracted
+ /// @return IOAddress object that represents the difference
+ static IOAddress subtract(const IOAddress& a, const IOAddress& b);
+
+ /// @brief Returns an address increased by one
+ ///
+ /// This method works for both IPv4 and IPv6 addresses. For example,
+ /// increase 192.0.2.255 will become 192.0.3.0.
+ ///
+ /// Address space is a finite field in the mathematical sense, so keep
+ /// in mind that the address space "loops". 255.255.255.255 increased
+ /// by one gives 0.0.0.0. The same is true for maximum value of IPv6
+ /// (all 1's) looping to ::.
+ ///
+ /// @todo Determine if we have a use-case for increasing the address
+ /// by more than one. Increase by one is used in AllocEngine. This method
+ /// could take extra parameter that specifies the value by which the
+ /// address should be increased.
+ ///
+ /// @param addr address to be increased
+ /// @return address increased by one
+ static IOAddress
+ increase(const IOAddress& addr);
+
+ /// \brief Converts IPv4 address to uint32_t
+ ///
+ /// Will throw BadValue exception if that is not IPv4
+ /// address.
+ ///
+ /// \return uint32_t that represents IPv4 address in
+ /// network byte order
+ uint32_t toUint32() const;
+
+ /// @name Methods returning @c IOAddress objects encapsulating typical addresses.
+ ///
+ //@{
+ /// @brief Returns an address set to all zeros.
+ static const IOAddress& IPV4_ZERO_ADDRESS() {
+ static IOAddress address(0);
+ return (address);
+ }
+
+ /// @brief Returns a "255.255.255.255" broadcast address.
+ static const IOAddress& IPV4_BCAST_ADDRESS() {
+ static IOAddress address(0xFFFFFFFF);
+ return (address);
+ }
+
+ /// @brief Returns an IPv6 zero address.
+ static const IOAddress& IPV6_ZERO_ADDRESS() {
+ static IOAddress address("::");
+ return (address);
+ }
+
+ //@}
+
+private:
+ boost::asio::ip::address asio_address_;
+};
+
+/// \brief Insert the IOAddress as a string into stream.
+///
+/// This method converts the \c address into a string and inserts it
+/// into the output stream \c os.
+///
+/// This function overloads the global operator<< to behave as described
+/// in ostream::operator<< but applied to \c IOAddress objects.
+///
+/// \param os A \c std::ostream object on which the insertion operation is
+/// performed.
+/// \param address The \c IOAddress object output by the operation.
+/// \return A reference to the same \c std::ostream object referenced by
+/// parameter \c os after the insertion operation.
+std::ostream&
+operator<<(std::ostream& os, const IOAddress& address);
+
+/// \brief Hash the IOAddress.
+///
+/// This method allows boost multi-index hashed indexes on IOAddresses.
+/// It follows the requirement with equality: if two addresses are equal
+/// their hashes are equal, if two addresses are not equal their hashes
+/// are almost surely not equal.
+///
+/// \param address A \c IOAddress to hash.
+/// \return The hash of the IOAddress.
+size_t hash_value(const IOAddress& address);
+
+} // namespace asiolink
+} // namespace isc
+#endif // IO_ADDRESS_H