io_address.h 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343
  1. // Copyright (C) 2010,2015 Internet Systems Consortium, Inc. ("ISC")
  2. //
  3. // Permission to use, copy, modify, and/or distribute this software for any
  4. // purpose with or without fee is hereby granted, provided that the above
  5. // copyright notice and this permission notice appear in all copies.
  6. //
  7. // THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
  8. // REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
  9. // AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
  10. // INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
  11. // LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
  12. // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  13. // PERFORMANCE OF THIS SOFTWARE.
  14. #ifndef IO_ADDRESS_H
  15. #define IO_ADDRESS_H 1
  16. // IMPORTANT NOTE: only very few ASIO headers files can be included in
  17. // this file. In particular, asio.hpp should never be included here.
  18. // See the description of the namespace below.
  19. #include <unistd.h> // for some network system calls
  20. #include <stdint.h> // for uint32_t
  21. #include <boost/asio/ip/address.hpp>
  22. #include <functional>
  23. #include <string>
  24. #include <vector>
  25. #include <exceptions/exceptions.h>
  26. namespace isc {
  27. namespace asiolink {
  28. /// Defines length of IPv6 address.
  29. const static size_t V6ADDRESS_LEN = 16;
  30. /// Defines length of IPv4 address.
  31. const static size_t V4ADDRESS_LEN = 4;
  32. /// \brief The \c IOAddress class represents an IP addresses (version
  33. /// agnostic)
  34. ///
  35. /// This class is a wrapper for the ASIO \c ip::address class.
  36. class IOAddress {
  37. public:
  38. ///
  39. /// \name Constructors and Destructor
  40. ///
  41. /// This class is copyable. We use default versions of copy constructor
  42. /// and the assignment operator.
  43. /// We use the default destructor.
  44. //@{
  45. /// \brief Constructor from string.
  46. ///
  47. /// This constructor converts a textual representation of IPv4 and IPv6
  48. /// addresses into an IOAddress object.
  49. /// If \c address_str is not a valid representation of any type of
  50. /// address, an exception of class \c IOError will be thrown.
  51. /// This constructor allocates memory for the object, and if that fails
  52. /// a corresponding standard exception will be thrown.
  53. ///
  54. /// \param address_str Textual representation of address.
  55. IOAddress(const std::string& address_str);
  56. /// \brief Constructor from an ASIO \c ip::address object.
  57. ///
  58. /// This constructor is intended to be used within the wrapper
  59. /// implementation; user applications of the wrapper API won't use it.
  60. ///
  61. /// This constructor never throws an exception.
  62. ///
  63. /// \param asio_address The ASIO \c ip::address to be converted.
  64. IOAddress(const boost::asio::ip::address& asio_address);
  65. //@}
  66. /// @brief Constructor for ip::address_v4 object.
  67. ///
  68. /// This constructor is intented to be used when constructing
  69. /// IPv4 address out of uint32_t type. Passed value must be in
  70. /// network byte order
  71. ///
  72. /// @param v4address IPv4 address represnted by uint32_t
  73. IOAddress(uint32_t v4address);
  74. /// \brief Convert the address to a string.
  75. ///
  76. /// This method is basically expected to be exception free, but
  77. /// generating the string will involve resource allocation,
  78. /// and if it fails the corresponding standard exception will be thrown.
  79. ///
  80. /// \return A string representation of the address.
  81. std::string toText() const;
  82. /// \brief Returns the address family
  83. ///
  84. /// \return AF_INET for IPv4 or AF_INET6 for IPv6.
  85. short getFamily() const;
  86. /// \brief Convenience function to check for an IPv4 address
  87. ///
  88. /// \return true if the address is a V4 address
  89. bool isV4() const {
  90. return (asio_address_.is_v4());
  91. }
  92. /// \brief Convenience function to check if it is an IPv4 zero address.
  93. ///
  94. /// \return true if the address is the zero IPv4 address.
  95. bool isV4Zero() const {
  96. return (equals(IPV4_ZERO_ADDRESS()));
  97. }
  98. /// \brief Convenience function to check if it is an IPv4 broadcast
  99. /// address.
  100. ///
  101. /// \return true if the address is the broadcast IPv4 address.
  102. bool isV4Bcast() const {
  103. return (equals(IPV4_BCAST_ADDRESS()));
  104. }
  105. /// \brief Convenience function to check for an IPv6 address
  106. ///
  107. /// \return true if the address is a V6 address
  108. bool isV6() const {
  109. return (asio_address_.is_v6());
  110. }
  111. /// \brief Convenience function to check if it is an IPv4 zero address.
  112. ///
  113. /// \return true if the address is the zero IPv4 address.
  114. bool isV6Zero() const {
  115. return (equals(IPV6_ZERO_ADDRESS()));
  116. }
  117. /// \brief checks whether and address is IPv6 and is link-local
  118. ///
  119. /// \return true if the address is IPv6 link-local, false otherwise
  120. bool isV6LinkLocal() const;
  121. /// \brief checks whether and address is IPv6 and is multicast
  122. ///
  123. /// \return true if the address is IPv6 multicast, false otherwise
  124. bool isV6Multicast() const;
  125. /// \brief Creates an address from over wire data.
  126. ///
  127. /// \param family AF_NET for IPv4 or AF_NET6 for IPv6.
  128. /// \param data pointer to first char of data
  129. ///
  130. /// \return Created IOAddress object
  131. static IOAddress fromBytes(short family, const uint8_t* data);
  132. /// \brief Return address as set of bytes
  133. ///
  134. /// \return Contents of the address as a set of bytes in network-byte
  135. /// order.
  136. std::vector<uint8_t> toBytes() const;
  137. /// \brief Compare addresses for equality
  138. ///
  139. /// \param other Address to compare against.
  140. ///
  141. /// \return true if addresses are equal, false if not.
  142. bool equals(const IOAddress& other) const {
  143. return (asio_address_ == other.asio_address_);
  144. }
  145. /// \brief Compare addresses for equality
  146. ///
  147. /// \param other Address to compare against.
  148. ///
  149. /// \return true if addresses are equal, false if not.
  150. bool operator==(const IOAddress& other) const {
  151. return equals(other);
  152. }
  153. /// \brief Compare addresses for inequality
  154. ///
  155. /// \param other Address to compare against.
  156. ///
  157. /// \return false if addresses are equal, true if not.
  158. bool nequals(const IOAddress& other) const {
  159. return (!equals(other));
  160. }
  161. /// \brief Checks if one address is smaller than the other
  162. ///
  163. /// \param other Address to compare against.
  164. ///
  165. /// \return true if this address is smaller than the other address.
  166. ///
  167. /// It is useful for comparing which address is bigger.
  168. /// Operations within one protocol family are obvious.
  169. /// Comparisons between v4 and v6 will allways return v4
  170. /// being smaller. This follows boost::boost::asio::ip implementation
  171. bool lessThan(const IOAddress& other) const {
  172. if (this->getFamily() == other.getFamily()) {
  173. if (this->getFamily() == AF_INET6) {
  174. return (this->asio_address_.to_v6() < other.asio_address_.to_v6());
  175. } else {
  176. return (this->asio_address_.to_v4() < other.asio_address_.to_v4());
  177. }
  178. }
  179. return (this->getFamily() < other.getFamily());
  180. }
  181. /// \brief Checks if one address is smaller or equal than the other
  182. ///
  183. /// \param other Address to compare against.
  184. ///
  185. /// \return true if this address is smaller than the other address.
  186. bool smallerEqual(const IOAddress& other) const {
  187. if (equals(other)) {
  188. return (true);
  189. }
  190. return (lessThan(other));
  191. }
  192. /// \brief Checks if one address is smaller than the other
  193. ///
  194. /// \param other Address to compare against.
  195. ///
  196. /// See \ref lessThan method for details.
  197. bool operator<(const IOAddress& other) const {
  198. return (lessThan(other));
  199. }
  200. /// \brief Checks if one address is smaller or equal than the other
  201. ///
  202. /// \param other Address to compare against.
  203. ///
  204. /// See \ref smallerEqual method for details.
  205. bool operator<=(const IOAddress& other) const {
  206. return (smallerEqual(other));
  207. }
  208. /// \brief Compare addresses for inequality
  209. ///
  210. /// \param other Address to compare against.
  211. ///
  212. /// \return false if addresses are equal, true if not.
  213. bool operator!=(const IOAddress& other) const {
  214. return (nequals(other));
  215. }
  216. /// @brief Subtracts one address from another (a - b)
  217. ///
  218. /// Treats addresses as integers and subtracts them. For example:
  219. /// @code
  220. /// 192.0.2.5 - 192.0.2.0 = 0.0.0.5
  221. /// fe80::abcd - fe80:: = ::abcd
  222. /// @endcode
  223. ///
  224. /// It is possible to subtract greater from lesser address, e.g.
  225. /// 192.168.56.10 - 192.168.67.20, but please do understand that
  226. /// the address space is a finite field in mathematical sense, so
  227. /// you may end up with a result that is greater then any of the
  228. /// addresses you specified. Also, subtraction is not commutative,
  229. /// so a - b != b - a.
  230. ///
  231. /// This operation is essential for calculating the number of
  232. /// leases in a pool, where we need to calculate (max - min).
  233. /// @throw BadValue if addresses are of different family
  234. /// @param a address to be subtracted from
  235. /// @param b address to be subtracted
  236. /// @return IOAddress object that represents the difference
  237. static IOAddress subtract(const IOAddress& a, const IOAddress& b);
  238. /// @brief Returns an address increased by one
  239. ///
  240. /// This method works for both IPv4 and IPv6 addresses. For example,
  241. /// increase 192.0.2.255 will become 192.0.3.0.
  242. ///
  243. /// Address space is a finite field in the mathematical sense, so keep
  244. /// in mind that the address space "loops". 255.255.255.255 increased
  245. /// by one gives 0.0.0.0. The same is true for maximum value of IPv6
  246. /// (all 1's) looping to ::.
  247. ///
  248. /// @todo Determine if we have a use-case for increasing the address
  249. /// by more than one. Increase by one is used in AllocEngine. This method
  250. /// could take extra parameter that specifies the value by which the
  251. /// address should be increased.
  252. ///
  253. /// @param addr address to be increased
  254. /// @return address increased by one
  255. static IOAddress
  256. increase(const IOAddress& addr);
  257. /// \brief Converts IPv4 address to uint32_t
  258. ///
  259. /// Will throw BadValue exception if that is not IPv4
  260. /// address.
  261. ///
  262. /// \return uint32_t that represents IPv4 address in
  263. /// network byte order
  264. operator uint32_t () const;
  265. /// @name Methods returning @c IOAddress objects encapsulating typical addresses.
  266. ///
  267. //@{
  268. /// @brief Returns an address set to all zeros.
  269. static const IOAddress& IPV4_ZERO_ADDRESS() {
  270. static IOAddress address(0);
  271. return (address);
  272. }
  273. /// @brief Returns a "255.255.255.255" broadcast address.
  274. static const IOAddress& IPV4_BCAST_ADDRESS() {
  275. static IOAddress address(0xFFFFFFFF);
  276. return (address);
  277. }
  278. /// @brief Returns an IPv6 zero address.
  279. static const IOAddress& IPV6_ZERO_ADDRESS() {
  280. static IOAddress address("::");
  281. return (address);
  282. }
  283. //@}
  284. private:
  285. boost::asio::ip::address asio_address_;
  286. };
  287. /// \brief Insert the IOAddress as a string into stream.
  288. ///
  289. /// This method converts the \c address into a string and inserts it
  290. /// into the output stream \c os.
  291. ///
  292. /// This function overloads the global operator<< to behave as described
  293. /// in ostream::operator<< but applied to \c IOAddress objects.
  294. ///
  295. /// \param os A \c std::ostream object on which the insertion operation is
  296. /// performed.
  297. /// \param address The \c IOAddress object output by the operation.
  298. /// \return A reference to the same \c std::ostream object referenced by
  299. /// parameter \c os after the insertion operation.
  300. std::ostream&
  301. operator<<(std::ostream& os, const IOAddress& address);
  302. } // namespace asiolink
  303. } // namespace isc
  304. #endif // IO_ADDRESS_H