dhcp4.dox 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319
  1. // Copyright (C) 2012-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. /**
  15. @page dhcp4 DHCPv4 Server Component
  16. Kea includes the "kea-dhcp4" component, which is the DHCPv4 server
  17. implementation. This component is built around the
  18. @ref isc::dhcp::Dhcpv4Srv class which controls all major operations
  19. performed by the server such as: DHCP messages processing, callouts
  20. execution for many hook points, FQDN processing and interactions with the
  21. "kea-dhcp-ddns" component, lease allocation, system signals handling etc.
  22. The "kea-dhcp4" component requires linking with many different libraries
  23. to obtain access to common functions like: interfaces and sockets
  24. management, configuration parsing, leases management and allocation,
  25. hooks infrastructure, statistics management etc.
  26. The following sections walk through some of the details of the "kea-dhcp4"
  27. component implementation.
  28. @section dhcpv4ConfigParser Configuration Parser in DHCPv4
  29. The common configuration parsers for the DHCP servers are located in the
  30. src/lib/dhcpsrv/parsers/ directory. Parsers specific to the DHCPv4 component
  31. are located in the src/bin/dhcp4/json_config_parser.cc. These parsers derive
  32. from the common configuration parsers and customize their behavior. For
  33. example: the @c Subnet4ConfigParser is used to parse parameters
  34. describing a single subnet. It derives from the @c
  35. isc::dhcp::SubnetConfigParser, which implements the common base for both
  36. DHCPv4 and DHCPv6 subnets. The @ref isc::dhcp::Subnet4ConfigParser
  37. implements the @c initSubnet abstract method, which creates an instance of
  38. the DHCPv4 subnet. This method is invoked by the parent class.
  39. Some parsers for the DHCPv4 server derive from the isc::dhcp::DhcpConfigParser
  40. class directly. This is an abstract class, defining a basic interface for
  41. all configuration parsers. All DHCPv4 parsers deriving from this class
  42. directly have their entire implementation in the
  43. src/bin/dhcp4/json_config_parser.cc.
  44. @section dhcpv4ConfigInherit DHCPv4 configuration inheritance
  45. One notable useful feature of DHCP configuration is its parameter inheritance.
  46. For example, the "renew-timer" value may be specified at a global scope and it then
  47. applies to all subnets. However, some subnets may have it overwritten with subnet
  48. specific values that takes precedence over global values that are considered
  49. defaults. The parameters inheritance is implemented by means of the "global
  50. context". The global context is represented by the @ref isc::dhcp::ParserContext
  51. class and it holds pointers to storage of different kinds, e.g. text parameters,
  52. numeric parameters etc. When the server is parsing the top level configuration
  53. parameters it passes pointers to the storages of the appropriate kind, to the
  54. parsers being invoked to parse the global values. Parsers will store the
  55. parsed values into these storages. Once the global parameters are stored in the
  56. global context, the parsers for the nested configuration parameters are invoked.
  57. These parsers check the presence of the parameters overriding the values of
  58. the global parameters. If a value is not present, the values from the global
  59. context is used.
  60. A good example of inheritance is the implementation of the @ref
  61. isc::dhcp::SubnetConfigParser. The @c getParam method is used throughout the
  62. class to obtain values of the parameters defining a subnet. It first checks
  63. if the specific value is present in the local values storage. If it is not
  64. present, it uses the value from the global context.
  65. @code
  66. isc::dhcp::Triplet<uint32_t>
  67. SubnetConfigParser::getParam(const std::string& name) {
  68. uint32_t value = 0;
  69. try {
  70. // look for local value
  71. value = uint32_values_->getParam(name);
  72. } catch (const DhcpConfigError &) {
  73. try {
  74. // no local, use global value
  75. value = global_context_->uint32_values_->getParam(name);
  76. } catch (const DhcpConfigError &) {
  77. isc_throw(DhcpConfigError, "Mandatory parameter " << name
  78. << " missing (no global default and no subnet-"
  79. << "specific value)");
  80. }
  81. }
  82. return (Triplet<uint32_t>(value));
  83. }
  84. @endcode
  85. Note that if the value is neither present in the local storage nor in the global
  86. context an error is signalled.
  87. Parameter inheritance is done once, during the reconfiguration phase.
  88. Reconfigurations are rare, so extra logic here is not a problem. On the other
  89. hand, values of those parameters may be used thousands times per second, so
  90. access to these parameters must be as efficient as possible. In fact,
  91. currently the code has to only call @c Subnet4::getT1(), regardless if the
  92. "renew-timer" has been specified as a global or subnet specific value.
  93. Debugging a configuration parser may be confusing. Therefore there is a special
  94. class called DebugParser. It does not configure anything, but just
  95. accepts any parameter of any type. If requested to commit configuration, it will
  96. print out received parameter name and its value. This class is not currently used,
  97. but it is convenient to have it every time a new parameter is added to the DHCP
  98. configuration. For that purpose it should be left in the code.
  99. @section dhcpv4OptionsParse Custom functions to parse message options
  100. The DHCPv4 server implementation provides a generic support to define option
  101. formats and set option values. A number of options formats have been defined
  102. for standard options in libdhcp++. However, the formats for vendor specific
  103. options are dynamically configured by the server's administrator and thus can't
  104. be stored in libdhcp++. Such option formats are stored in the
  105. @ref isc::dhcp::CfgMgr. The libdhcp++ provides functions for recursive parsing
  106. of options which may be encapsulated by other options up to any level of
  107. encapsulation, but these functions are unaware of the option formats defined
  108. in the @ref isc::dhcp::CfgMgr because they belong to a different library.
  109. Therefore, the generic functions @ref isc::dhcp::LibDHCP::unpackOptions4 and
  110. @ref isc::dhcp::LibDHCP::unpackOptions6 are only useful to parse standard
  111. options whose definitions are provided in the libdhcp++. In order to overcome
  112. this problem a callback mechanism has been implemented in @c Option and @c Pkt4
  113. classes. By installing a callback function on an instance of @c Pkt4, the
  114. server may provide a custom implementation of the options parsing algorithm.
  115. This callback function will take precedence over the @c LibDHCP::unpackOptions4
  116. and @c LibDHCP::unpackOptions6 functions. With this approach, the callback is
  117. implemented within the context of the server and it has access to all objects
  118. which define its configuration (including dynamically created option
  119. definitions).
  120. @section dhcpv4DDNSIntegration DHCPv4 Server Support for the Dynamic DNS Updates
  121. The DHCPv4 server supports processing of the DHCPv4 Client FQDN option (RFC4702)
  122. and the DHCPv4 Host Name option (RFC2132). A client may send one of these options
  123. to convey its fully qualified or partial name to the server. The server may use
  124. this name to perform DNS updates for the client. If server receives both options
  125. in the same message, the DHCPv4 Client FQDN %Option is processed and the Host
  126. Name option is ignored. If only Host Name Option is present in the client's
  127. message, it is used to update DNS.
  128. The server may be configured to use a different name to perform DNS update for the
  129. client. In this case the server will return one of the DHCPv4 Client FQDN or
  130. Host Name %Option in its response with the name which was selected for the
  131. client to indicate that this name will be used to perform DNS update.
  132. The kea-dhcp-ddns process is responsible for the actual communication with the
  133. DNS, i.e. to send DNS update messages. The kea-dhcp4 module is responsible for
  134. generating @ref isc::dhcp_ddns::NameChangeRequest and sending it to
  135. the kea-dhcp-ddns module. The @ref isc::dhcp_ddns::NameChangeRequest object
  136. represents changes to the DNS bindings, related to acquisition, renewal or
  137. release of the DHCP lease. The kea-dhcp4 module implements the simple FIFO queue
  138. of the NameChangeRequest objects. The module logic, which processes the incoming
  139. DHCPv4 Client FQDN and Host Name Options puts these requests into the FIFO queue.
  140. @todo Currently the FIFO queue is not processed after the NameChangeRequests are
  141. generated and added to it. In the future implementation steps it is planned to
  142. create a code which will check if there are any outstanding requests in the queue
  143. and send them to the kea-dhcp-ddns module when server is idle waiting for DHCP
  144. messages.
  145. When client gets an address from the server, a DHCPv4 server may generate 0, 1
  146. or 2 NameChangeRequests during single message processing. Server generates no
  147. NameChangeRequests if it is not configured to update DNS or it rejects the DNS
  148. update for any other reason.
  149. The server may generate one NameChangeRequest in the case where a client acquires a new
  150. lease or it releases an existing one. In the former case, the NameChangeRequest
  151. type is CHG_ADD, which indicates that the kea-dhcp-ddns module should add a new
  152. DNS binding for the client, and it is assumed that there is no DNS binding for
  153. this client already. In the latter case, the NameChangeRequest type is CHG_REMOVE
  154. to indicate to the kea-dhcp-ddns module that an existing DNS binding should be
  155. removed from the DNS. The binding consists of the forward and reverse mapping.
  156. The server may only remove the mapping which it had added. Therefore, the lease
  157. database holds the information which updates (no update, reverse only update,
  158. forward only update or both reverse and forward update) have been performed when
  159. the lease was acquired or renewed. Server checks this information to make a
  160. decision which mapping it is supposed to remove when lease is released.
  161. The server may generate two NameChangeRequests in the case where client is
  162. renewing a lease and it already has a DNS binding for that lease. The DHCPv4
  163. server will check if there is an existing lease for the client which has sent a
  164. message and if DNS Updates had been performed for this lease. If the notion of
  165. client's FQDN changes, comparing to the information stored in the lease
  166. database, the DHCPv4 has to remove an existing binding from the DNS and then add
  167. a new binding according to the new FQDN information received from the client. If
  168. the client's FQDN information (including the client's name and type of update
  169. performed) doesn't change comparing to the NameChangeRequest is not generated.
  170. The DHCPv4 Client FQDN %Option comprises flags which communicate to the server
  171. what updates (if any) client expects the server to perform. Server may be
  172. configured to obey client's preference or to do FQDN processing in a different way.
  173. If the server overrides client's preference it will communicate it by sending
  174. the DHCPv4 Client FQDN %Option in its responses to a client, with the appropriate
  175. flags set.
  176. @todo Note: the current implementation doesn't allow configuration of the
  177. server's behaviour with respect to DNS Updates. This is planned for the future.
  178. The default behaviour is constituted by the set of constants defined in the
  179. (upper part of) dhcp4_srv.cc file. Once the configuration is implemented,
  180. these constants will be removed.
  181. @section dhcpv4Classifier DHCPv4 Client Classification
  182. The Kea DHCPv4 currently supports two classification modes: simplified client
  183. classification (that was an early implementation that used values of vendor class option)
  184. and full client classification.
  185. @subsection dhcpv4ClassifierSimple Simple Client Classification in DHCPv4
  186. The Kea DHCPv4 server supports simplified client classification. It is called
  187. "simplified", because the incoming packets are classified based on the content
  188. of the vendor class (60) option. More flexible classification was added in 1.0
  189. and is described in @ref dhcpv4ClassifierFull .
  190. For each incoming packet, @ref isc::dhcp::Dhcpv4Srv::classifyPacket() method is called.
  191. It attempts to extract content of the vendor class option and interpret as a name
  192. of the class. For now, the code has been tested with two classes used in cable modem
  193. networks: eRouter1.0 and docsis3.0, but any other content of the vendor class option will
  194. be interpreted as a class name.
  195. In principle any given packet can belong to zero or more classes. As the current
  196. classifier is very modest, there's only one way to assign a class (based on vendor class
  197. option), the ability to assign more than one class to a packet is not yet exercised.
  198. Nevertheless, there is such a possibility and it will be used in a near future. To
  199. check whether a packet belongs to given class, isc::dhcp::Pkt4::inClass method should
  200. be used.
  201. The code sometimes refers to this classification as "simple" or 'built-in", because
  202. it does not require any configuration and thus is built into the server logic.
  203. @subsection dhcpv4ClassifierFull Full Client Classification in DHCPv4
  204. Kea 1.0 introduced full client classification. Each client class consists of a name
  205. and an expression that can be evaluated on an incoming packet. If it evaluates to
  206. true, this packet is considered a member of said class. Class definitions are stored
  207. in isc::dhcp::ClientClassDef objects that are kept in isc::dhcp::ClientClassDictionary.
  208. This is convenient as there are often multiple classes associated with a given scope.
  209. As of Kea 1.0, the only supported scope is global, but there are plans to support
  210. class definitions that are subnet specific.
  211. Client classification is done in isc::dhcp::Dhcpv4Srv::classifyPacket. First, the old
  212. "built-in" (see @ref dhcpv4ClassifierSimple) classification is called. Then the code
  213. iterates over all class definitions and for each class definition it calls
  214. isc::dhcp::evaluate, which is implemented in libeval (see @ref dhcpEval). If the
  215. evaluation is successful, the class name is added to the packet (by calling
  216. isc::dhcp::pkt::addClass).
  217. If packet belongs to at least one class, this fact is logged. If there are any
  218. exceptions raised during class evaluation, an error is logged and the code attempts
  219. to evaluate the next class.
  220. @subsection dhcpv4ClassifierUsage How client classification information is used in DHCPv4
  221. Currently there is a short code section that alternates packet processing depending on
  222. which class it belongs to. (It is planned to move that capability to an external hook
  223. library, see ticket #3275.) The class specific behavior is:
  224. - docsis3.0 packets have siaddr (next server) field set
  225. - docsis3.0 packets have file field set to the content of the boot-file-name option
  226. - eRouter1.0 packets have siaddr (next server) field cleared
  227. Aforementioned modifications are conducted in
  228. @ref isc::dhcp::Dhcpv4Srv::vendorClassSpecificProcessing.
  229. It is possible to define class restrictions in subnet, so a given subnet is only
  230. accessible to clients that belong to a given class. That is implemented as
  231. isc::dhcp::Pkt4::classes_ being passed in isc::dhcp::Dhcpv4Srv::selectSubnet()
  232. to isc::dhcp::CfgMgr::getSubnet4(). Currently this capability is usable, but
  233. the number of scenarios it supports is limited.
  234. Finally, it is possible to define client class-specific options, so clients belonging
  235. to a class foo, will get options associated with class foo. This is implemented in
  236. isc::dhcp::Dhcpv4Srv::buildCfgOptionList.
  237. @section dhcpv4ConfigBackend Configuration backend for DHCPv4
  238. Earlier Kea vesions had a concept of backends, which were implementations of
  239. different ways how configuration could be delivered to Kea. It seems that the
  240. concept of backends didn't get much enthusiasm from users and having multiple
  241. backends was cumbersome to maintain, so it was removed in 1.0.
  242. @section dhcpv4SignalBasedReconfiguration Reconfiguring DHCPv4 server with SIGHUP signal
  243. Online reconfiguration (reconfiguration without a need to restart the server) is an
  244. important feature which is supported by all modern DHCP servers. When using the JSON
  245. configuration backend, a configuration file name is specified with a command line
  246. option of the DHCP server binary. The configuration file is used to configure the
  247. server at startup. If the initial configuration fails, the server will fail to start.
  248. If the server starts and configures successfully it will use the initial configuration
  249. until it is reconfigured.
  250. The reconfiguration request can be triggered externally (from other process) by editing
  251. a configuration file and sending a SIGHUP signal to DHCP server process. After receiving
  252. the SIGHUP signal, the server will re-read the configuration file specified at startup.
  253. If the reconfiguration fails, the server will continue to run and use the last good
  254. configuration.
  255. The signal handler for SIGHUP (also for SIGTERM and SIGINT) are installed in the
  256. kea_controller.cc using the @c isc::util::SignalSet class. The
  257. @c isc::dhcp::Dhcp4Srv calls @c isc::dhcp::Daemon::handleSignal on each pass
  258. through the main loop. This method fetches the last received signal and calls
  259. a handler function defined in the kea_controller.cc. The handler function
  260. calls a static function @c configure defined in the kea_controller.cc.
  261. The signal handler reconfigures the server using the configuration file
  262. specified at server startup. The location of this file is held in the
  263. @c Daemon class.
  264. @section dhcpv4Other Other DHCPv4 topics
  265. For hooks API support in DHCPv4, see @ref dhcpv4Hooks.
  266. */