cfg_iface.h 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338
  1. // Copyright (C) 2014-2015 Internet Systems Consortium, Inc. ("ISC")
  2. //
  3. // This Source Code Form is subject to the terms of the Mozilla Public
  4. // License, v. 2.0. If a copy of the MPL was not distributed with this
  5. // file, You can obtain one at http://mozilla.org/MPL/2.0/.
  6. #ifndef CFG_IFACE_H
  7. #define CFG_IFACE_H
  8. #include <asiolink/io_address.h>
  9. #include <dhcp/iface_mgr.h>
  10. #include <boost/shared_ptr.hpp>
  11. #include <map>
  12. #include <set>
  13. #include <string>
  14. namespace isc {
  15. namespace dhcp {
  16. /// @brief Exception thrown when duplicated interface names specified.
  17. class DuplicateIfaceName : public Exception {
  18. public:
  19. DuplicateIfaceName(const char* file, size_t line, const char* what) :
  20. isc::Exception(file, line, what) { };
  21. };
  22. /// @brief Exception thrown when specified interface name is invalid.
  23. class InvalidIfaceName : public Exception {
  24. public:
  25. InvalidIfaceName(const char* file, size_t line, const char* what) :
  26. isc::Exception(file, line, what) { };
  27. };
  28. /// @brief Exception thrown when specified interface doesn't exist in a system.
  29. class NoSuchIface : public Exception {
  30. public:
  31. NoSuchIface(const char* file, size_t line, const char* what) :
  32. isc::Exception(file, line, what) { };
  33. };
  34. /// @brief Exception thrown when duplicated address specified.
  35. class DuplicateAddress : public Exception {
  36. public:
  37. DuplicateAddress(const char* file, size_t line, const char* what) :
  38. isc::Exception(file, line, what) { };
  39. };
  40. /// @brief Exception thrown when specified unicast address is not assigned
  41. /// to the interface specified.
  42. class NoSuchAddress : public Exception {
  43. public:
  44. NoSuchAddress(const char* file, size_t line, const char* what) :
  45. isc::Exception(file, line, what) { };
  46. };
  47. /// @brief Exception thrown when invalid socket type has been specified
  48. /// for the given family.
  49. class InvalidSocketType : public Exception {
  50. public:
  51. InvalidSocketType(const char* file, size_t line, const char* what) :
  52. isc::Exception(file, line, what) { };
  53. };
  54. /// @brief Represents selection of interfaces for DHCP server.
  55. ///
  56. /// This class manages selection of interfaces on which the DHCP server is
  57. /// listening to queries. The interfaces are selected in the server
  58. /// configuration by their names or by the pairs of interface names and
  59. /// addresses, e.g. eth0/2001:db8:1::1 (DHCPv6) or e.g. eth0/192.168.8.1
  60. /// (DHCPv4).
  61. ///
  62. /// This class also accepts "wildcard" interface name which, if specified,
  63. /// instructs the server to listen on all available interfaces.
  64. ///
  65. /// Once interfaces have been specified the sockets (either IPv4 or IPv6)
  66. /// can be opened by calling @c CfgIface::openSockets function. Kea
  67. /// offers configuration parameters to control the types of sockets to be
  68. /// opened by the DHCPv4 server. In small deployments it is requires that
  69. /// the server can handle messages from the directly connected clients
  70. /// which don't have an address yet. Unicasting the response to such
  71. /// client is possible by the use of raw sockets. In larger deployments
  72. /// it is often the case that whole traffic is received via relays, and
  73. /// in such case the use of UDP sockets is preferred. The type of the
  74. /// sockets to be opened is specified using one of the
  75. /// @c CfgIface::useSocketType method variants. The @c CfgIface::SocketType
  76. /// enumeration specifies the possible values.
  77. ///
  78. /// @warning This class makes use of the AF_INET and AF_INET6 family literals,
  79. /// but it doesn't verify that the address family value passed as @c uint16_t
  80. /// parameter is equal to one of them. It is a callers responsibility to
  81. /// guarantee that the address family value is correct.
  82. ///
  83. /// The interface name is passed as an argument of the @ref CfgIface::use
  84. /// function which controls the selection of the interface on which the
  85. /// DHCP queries should be received by the server. The interface name
  86. /// passed as the argument of this function may appear in one of the following
  87. /// formats:
  88. /// - interface-name, e.g. eth0
  89. /// - interface-name/address, e.g. eth0/2001:db8:1::1 or eth0/192.168.8.1
  90. ///
  91. /// Extraneous spaces surrounding the interface name and/or address
  92. /// are accepted. For example: eth0 / 2001:db8:1::1 will be accepted.
  93. ///
  94. /// When only interface name is specified (without an address) it is allowed
  95. /// to use the "wildcard" interface name (*) which indicates that the server
  96. /// should open sockets on all interfaces. When IPv6 is in use, the sockets
  97. /// will be bound to the link local addresses. Wildcard interface names are
  98. /// not allowed when specifying a unicast address. For example:
  99. /// */2001:db8:1::1 is not allowed.
  100. ///
  101. /// The DHCPv6 configuration accepts simultaneous use of the "interface-name"
  102. /// and "interface-name/address" tuple for the same interface, e.g.
  103. /// "eth0", "eth0/2001:db8:1::1" specifies that the server should open a
  104. /// socket and bind to link local address as well as open a socket bound to
  105. /// the specified unicast address.
  106. ///
  107. /// The DHCPv4 configuration doesn't accept the simulatenous use of the
  108. /// "interface-name" and the "interface-name/address" tuple for the
  109. /// given interface. When the "interface-name" is specified it implies
  110. /// that the sockets will be opened on for all addresses configured on
  111. /// this interface. If the tuple of "interface-name/address" is specified
  112. /// there will be only one socket opened and bound to the specified address.
  113. /// This socket will be configured to listen to the broadcast messages
  114. /// reaching the interface as well as unicast messages sent to the address
  115. /// to which it is bound. It is allowed to select multiple addresses on the
  116. /// particular interface explicitly, e.g. "eth0/192.168.8.1",
  117. /// "eth0/192.168.8.2".
  118. class CfgIface {
  119. public:
  120. /// @brief Socket type used by the DHCPv4 server.
  121. enum SocketType {
  122. /// Raw socket, used for direct DHCPv4 traffic.
  123. SOCKET_RAW,
  124. /// Datagram socket, i.e. IP/UDP socket.
  125. SOCKET_UDP
  126. };
  127. /// @brief Keyword used to enable all interfaces.
  128. ///
  129. /// This keyword can be used instead of the interface name to specify
  130. /// that DHCP server should listen on all interfaces.
  131. static const char* ALL_IFACES_KEYWORD;
  132. /// @brief Constructor.
  133. CfgIface();
  134. /// @brief Convenience function which closes all open sockets.
  135. void closeSockets() const;
  136. /// @brief Compares two @c CfgIface objects for equality.
  137. ///
  138. /// @param other An object to be compared with this object.
  139. ///
  140. /// @return true if objects are equal, false otherwise.
  141. bool equals(const CfgIface& other) const;
  142. /// @brief Tries to open sockets on selected interfaces.
  143. ///
  144. /// This function opens sockets bound to link-local address as well as
  145. /// sockets bound to unicast address. See @c CfgIface::use function
  146. /// documentation for details how to specify interfaces and unicast
  147. /// addresses to bind the sockets to.
  148. ///
  149. /// @param family Address family (AF_INET or AF_INET6).
  150. /// @param port Port number to be used to bind sockets to.
  151. /// @param use_bcast A boolean flag which indicates if the broadcast
  152. /// traffic should be received through the socket. This parameter is
  153. /// ignored for IPv6.
  154. void openSockets(const uint16_t family, const uint16_t port,
  155. const bool use_bcast = true) const;
  156. /// @brief Puts the interface configuration into default state.
  157. ///
  158. /// This function removes interface names from the set.
  159. void reset();
  160. /// @brief Select interface to be used to receive DHCP traffic.
  161. ///
  162. /// @ref CfgIface for a detail explaination of the interface name argument.
  163. ///
  164. /// @param family Address family (AF_INET or AF_INET6).
  165. /// @param iface_name Explicit interface name, a wildcard name (*) of
  166. /// the interface(s) or the pair of iterface/unicast-address to be used
  167. /// to receive DHCP traffic.
  168. ///
  169. /// @throw InvalidIfaceName If the interface name is incorrect, e.g. empty.
  170. /// @throw NoSuchIface If the specified interface is not present.
  171. /// @throw NoSuchAddress If the specified unicast address is not assigned
  172. /// to the interface.
  173. /// @throw DuplicateIfaceName If the interface is already selected, i.e.
  174. /// @throw IOError when specified unicast address is invalid.
  175. /// @c CfgIface::use has been already called for this interface.
  176. void use(const uint16_t family, const std::string& iface_name);
  177. /// @brief Sets the specified socket type to be used by the server.
  178. ///
  179. /// Supported socket types for DHCPv4 are:
  180. /// - @c SOCKET_RAW
  181. /// - @c SOCKET_UDP
  182. ///
  183. /// @param family Address family (AF_INET or AF_INET6).
  184. /// @param socket_type Socket type.
  185. ///
  186. /// @throw InvalidSocketType if the unsupported socket type has been
  187. /// specified for the address family. Currently, the socket type
  188. /// can only be selected for the AF_INET family.
  189. void useSocketType(const uint16_t family, const SocketType& socket_type);
  190. /// @brief Sets the specified socket type specified in textual format.
  191. ///
  192. /// The following names of the socket types are currently supported, and
  193. /// can be passed in the @c socket_type parameter:
  194. /// - raw - for raw sockets,
  195. /// - udp - for the IP/UDP datagram sockets,
  196. ///
  197. /// @param family Address family (AF_INET or AF_INET6)
  198. /// @param socket_type_name Socket type in the textual format.
  199. ///
  200. /// @throw InvalidSocketType if the unsupported socket type has been
  201. /// specified for the address family. Currently, the socket type
  202. /// can only be selected for the AF_INET family.
  203. void useSocketType(const uint16_t family,
  204. const std::string& socket_type_name);
  205. /// @brief Returns the socket type in the textual format.
  206. std::string socketTypeToText() const;
  207. /// @brief Converts the socket type in the textual format to the type
  208. /// represented by the @c SocketType.
  209. ///
  210. /// @throw InvalidSocketType if the specified value of the @c socket_type_name
  211. /// is invalid.
  212. SocketType textToSocketType(const std::string& socket_type_name) const;
  213. /// @brief Equality operator.
  214. ///
  215. /// @param other Object to be compared with this object.
  216. ///
  217. /// @return true if objects are equal, false otherwise.
  218. bool operator==(const CfgIface& other) const {
  219. return (equals(other));
  220. }
  221. /// @brief Inequality operator.
  222. ///
  223. /// @param other Object to be compared with this object.
  224. ///
  225. /// @return true if objects are not equal, false otherwise.
  226. bool operator!=(const CfgIface& other) const {
  227. return (!equals(other));
  228. }
  229. private:
  230. /// @brief Checks if multiple IPv4 addresses has been activated on any
  231. /// interface.
  232. ///
  233. /// This method is useful to check if the current configuration uses
  234. /// multiple IPv4 addresses on any interface. This is important when
  235. /// using raw sockets to recieve messages from the clients because
  236. /// each packet may be received multiple times when it is sent from
  237. /// a directly connected client. If this is the case, a warning must
  238. /// be logged.
  239. ///
  240. /// @return true if multiple addresses are activated on any interface,
  241. /// false otherwise.
  242. bool multipleAddressesPerInterfaceActive() const;
  243. /// @brief Selects or deselects interfaces.
  244. ///
  245. /// This function selects all interfaces to receive DHCP traffic or
  246. /// deselects all interfaces so as none of them receives a DHCP traffic.
  247. ///
  248. /// @param family Address family (AF_INET or AF_INET6).
  249. /// @param inactive A boolean value which indicates if all interfaces
  250. /// (except loopback) should be selected or deselected.
  251. /// @param loopback_inactive A boolean value which indicates if loopback
  252. /// interface should be selected or deselected.
  253. /// should be deselected/inactive (true) or selected/active (false).
  254. void setState(const uint16_t family, const bool inactive,
  255. const bool loopback_inactive) const;
  256. /// @brief Selects or deselects addresses on the interface.
  257. ///
  258. /// This function selects all address on the interface to receive DHCP
  259. /// traffic or deselects all addresses so as none of them receives the
  260. /// DHCP traffic.
  261. ///
  262. /// @param family Address family (AF_INET or AF_INET6).
  263. /// @param active A boolean value which indicates if all addresses should
  264. /// be active (if true), or inactive (if false).
  265. /// @param iface An interface on which addresses are selected/deselected.
  266. void setIfaceAddrsState(const uint16_t family, const bool active,
  267. Iface& iface) const;
  268. /// @brief Error handler for executed when opening a socket fail.
  269. ///
  270. /// A pointer to this function is passed to the @c IfaceMgr::openSockets4
  271. /// or @c IfaceMgr::openSockets6. These functions call this handler when
  272. /// they fail to open a socket. The handler logs an error passed in the
  273. /// parameter.
  274. ///
  275. /// @param errmsg Error message being logged by the function.
  276. static void socketOpenErrorHandler(const std::string& errmsg);
  277. /// @brief Represents a set of interface names.
  278. typedef std::set<std::string> IfaceSet;
  279. /// @brief A set of interface names specified by the user.
  280. IfaceSet iface_set_;
  281. /// @brief A map of interfaces and addresses to which the server
  282. /// should bind sockets.
  283. typedef std::multimap<std::string, asiolink::IOAddress> ExplicitAddressMap;
  284. /// @brief A map which holds the pairs of interface names and addresses
  285. /// for which the sockets should be opened.
  286. ExplicitAddressMap address_map_;
  287. /// @brief A booolean value which indicates that the wildcard interface name
  288. /// has been specified (*).
  289. bool wildcard_used_;
  290. /// @brief A type of the sockets used by the DHCP server.
  291. SocketType socket_type_;
  292. };
  293. /// @brief A pointer to the @c CfgIface .
  294. typedef boost::shared_ptr<CfgIface> CfgIfacePtr;
  295. /// @brief A pointer to the const @c CfgIface.
  296. typedef boost::shared_ptr<const CfgIface> ConstCfgIfacePtr;
  297. }
  298. }
  299. #endif // CFG_IFACE_H