cfg_iface.h 14 KB

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