libdhcp++.dox 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263
  1. // Copyright (C) 2012-2017 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. /**
  7. @page libdhcp libkea-dhcp++ - Low Level DHCP Library
  8. @section libdhcpIntro Libdhcp++ Library Introduction
  9. libdhcp++ is an all-purpose DHCP-manipulation library, written in
  10. C++. It offers packet parsing and assembly, DHCPv4 and DHCPv6
  11. options parsing and assembly, interface detection (currently on
  12. Linux, FreeBSD, NetBSD, OpenBSD, Max OS X, and Solaris 11) and socket operations.
  13. It is a generic purpose library that
  14. can be used by server, client, relay, performance tools and other DHCP-related
  15. tools. For server specific library, see \ref libdhcpsrv. Please do not
  16. add any server-specific code to libdhcp++ and use \ref libdhcpsrv instead.
  17. The following classes for packet manipulation are implemented:
  18. - isc::dhcp::Pkt4 - represents a DHCPv4 packet.
  19. - isc::dhcp::Pkt6 - represents a DHCPv6 packet.
  20. - isc::dhcp::Pkt4o6 - represents a DHCPv4-over-DHCPv6 packet.
  21. The following pointer types are defined: \c Pkt4Ptr, \c Pkt6Ptr and Pkt4o6Ptr.
  22. They are smart pointers using the \c boost::shared_ptr type. There are no const
  23. versions of packet types defined, as we assume that hooks can modify any
  24. aspect of the packet at almost any stage of processing.
  25. Both packet types use a collection of \ref isc::dhcp::Option objects to
  26. represent DHCPv4 and DHCPv6 options. The base class @c Option can be used to
  27. represent generic option that contains collection of
  28. bytes. Depending on whether the option is instantiated as a DHCPv4 or DHCPv6
  29. option, it will adjust its header (DHCPv4 options use 1 octet for
  30. type and 1 octet for length, while DHCPv6 options use 2 bytes for
  31. each).
  32. There are many specialized classes that are intended to handle options having
  33. specific formats:
  34. - isc::dhcp::Option4AddrLst -- DHCPv4 option, contains one or more IPv4 addresses;
  35. - isc::dhcp::Option6AddrLst -- DHCPv6 option, contains one or more IPv6 addresses;
  36. - isc::dhcp::Option4ClientFqdn -- DHCPv4 Client FQDN option;
  37. - isc::dhcp::Option6ClientFqdn -- DHCPv6 Client FQDN option;
  38. - isc::dhcp::Option6IAAddr -- DHCPv6 option, represents an IAADDR option (an option that
  39. contains IPv6 address with extra parameters);
  40. - isc::dhcp::Option6IAPrefix -- DHCPv6 option, represents an IAPREFIX option (an option
  41. that contains IPv6 prefix in prefix delegation);
  42. - isc::dhcp::Option6IA -- DHCPv6 option used to store IA_NA and its suboptions.
  43. - isc::dhcp::Option6StatusCode -- DHCPv6 option, carries a status code to the client;
  44. - isc::dhcp::OptionCustom -- Represents an option having many different formats, where
  45. data fields can be accessed in a convenient way;
  46. - isc::dhcp::OptionInt -- DHCPv4 or DHCPv6 option, carries a single numeric value;
  47. - isc::dhcp::OptionString -- DHCPv4 or DHCPv6 option, carries a text value;
  48. - isc::dhcp::OptionVendor -- DHCPv4 or DHCPv6 option, carries Vendor Specific
  49. Information;
  50. - isc::dhcp::OptionVendorClass -- DHCPv4 or DHCPv6 option, contains vendor class
  51. information.
  52. Various options can store sub-options (i.e. options that are stored within an
  53. option rather than in a message directly). This functionality is commonly used in
  54. DHCPv6, but is rarely used in DHCPv4. \ref isc::dhcp::Option::addOption(),
  55. \ref isc::dhcp::Option::delOption(), \ref isc::dhcp::Option::getOption() can
  56. be used to add, remove and retrieve sub-options from within an option.
  57. @section libdhcpDhcp4o6 DHCPv4-over-DHCPv6 support
  58. The DHCPv4-over-DHCPv6 packet class (\c Pkt4o6) is derived from
  59. the DHCPv4 packet class (\c Pkt4) with:
  60. - un extra member pointing to the encapsulating DHCPv6 packet, accessible
  61. by \ref isc::dhcp::Pkt4o6::getPkt6()
  62. - a specialized isc::dhcp::Pkt::pack() method which builds the wire-format
  63. data of the whole DHCPv6-over-DHCPv4 packet.
  64. To avoid the extra overhead of dynamic casts the isc::dhcp::Pkt4::isDhcp4o6()
  65. virtual method returns true for \c Pkt4o6 instances and false for others.
  66. @section libdhcpRelay Relay v6 support in Pkt6
  67. DHCPv6 clients that are not connected to the same link as DHCPv6
  68. servers need relays to reach the server. Each relay receives a message
  69. on a client facing interface, encapsulates it into RELAY_MSG option
  70. and sends as RELAY_FORW message towards the server (or the next relay,
  71. which is closer to the server). This procedure can be repeated up to
  72. 32 times. Kea is able to support up to 32 relays. Each traversed relay
  73. may add certain options. The most obvious example is interface-id
  74. option, but there may be other options as well. Each relay may add such
  75. an option, regardless of whether other relays added it before. Thanks
  76. to encapsulation, those options are separated and it is possible to
  77. differentiate which relay inserted specific instance of an option.
  78. Interface-id is used to identify a subnet (or interface) the original message
  79. came from and is used for that purpose on two occasions. First, the server
  80. uses the interface-id included by the first relay (the one closest to
  81. the client) to select appropriate subnet for a given request. Server includes
  82. that interface-id in its copy, when sending data back to the client.
  83. This will be used by the relay to choose proper interface when forwarding
  84. response towards the client.
  85. The Pkt6 class has a public \c Pkt6::relay_info_ field, which is of type \c Pkt6::RelayInfo.
  86. This is a simple structure that represents the information in each RELAY_FORW
  87. or RELAY_REPL message. It is important to understand the order in which
  88. the data appear here. Consider the following network:
  89. \verbatim
  90. client-------relay1-----relay2-----relay3----server
  91. \endverbatim
  92. Client will transmit SOLICIT message. Relay1 will forward it as
  93. RELAY_FORW with SOLICIT in it. Relay2 forward it as RELAY_FORW with
  94. RELAY_FORW with SOLICIT in it. Finally the third relay will add yet
  95. another RELAY_FORW around it. The server will parse the packet and
  96. create \c Pkt6 object for it. Its relay_info_ will have 3
  97. elements. Packet parsing is done in reverse order, compare to the
  98. order the packet traversed in the network. The first element
  99. (relay_info_[0]) will represent relay3 information (the "last" relay or
  100. in other words the one closest to the server). The second element
  101. will represent relay2. The third element (relay_info_[2]) will represent
  102. the first relay (relay1) or in other words the one closest to the client.
  103. Packets sent by the server must maintain the same encapsulation order.
  104. This is easy to do - just copy data from client's message object into
  105. server's response object. See @ref isc::dhcp::Pkt6::RelayInfo for details.
  106. @section libdhcpIfaceMgr Interface Manager
  107. Interface Manager (or IfaceMgr) is an abstraction layer for low-level
  108. network operations. In particular, it provides information about existing
  109. network interfaces See @ref isc::dhcp::Iface class and
  110. @ref isc::dhcp::IfaceMgr::detectIfaces() and @ref isc::dhcp::IfaceMgr::getIface().
  111. Generic parts of the code are contained in the @ref isc::dhcp::IfaceMgr class in
  112. src/lib/dhcp/iface_mgr.cc file. OS-specific code is located in separate
  113. files, e.g. iface_mgr_linux.cc, iface_mgr_bsd. The separation should be
  114. maintained when developing additional code.
  115. Other useful methods are dedicated to transmission
  116. (\ref isc::dhcp::IfaceMgr::send(), 2 overloads) and reception
  117. (\ref isc::dhcp::IfaceMgr::receive4() and \ref isc::dhcp::IfaceMgr::receive6()).
  118. Note that \c receive4() and \c receive6() methods may return NULL, e.g.
  119. when timeout is reached or if the DHCP daemon receives a signal.
  120. @section libdhcpPktFilter Switchable Packet Filter objects used by Interface Manager
  121. The well known problem of DHCPv4 implementation is that it must be able to
  122. provision devices which don't have an IPv4 address yet (the IPv4 address is
  123. one of the configuration parameters provided by DHCP server to a client).
  124. One way to communicate with such a device is to send server's response to
  125. a broadcast address. An obvious drawback of this approach is that the server's
  126. response will be received and processed by all clients in the particular
  127. network. Therefore, the preferred approach is that the server unicasts its
  128. response to a new address being assigned for the client. This client will
  129. identify itself as a target of this message by checking chaddr and/or
  130. Client Identifier value. At the same time, the other clients in the network
  131. will not receive the unicast message. The major problem that arises with this
  132. approach is that the client without an IP address doesn't respond to ARP
  133. messages. As a result, server's response will not be sent over IP/UDP
  134. socket because the system kernel will fail to resolve client's link-layer
  135. address.
  136. Kea supports the use of raw sockets to create a complete Data-link/IP/UDP/DHCPv4
  137. stack. By creating each layer of the outgoing packet, the Kea logic has full
  138. control over the frame contents and it may bypass the use of ARP to inject the
  139. link layer address into the frame.
  140. The low level operations on raw sockets are implemented within the "packet
  141. filtering" classes derived from @c isc::dhcp::PktFilter. The implementation
  142. of these classes is specific to the operating system. On Linux the
  143. @c isc::dhcp::PktFilterLPF is used. On BSD systems the
  144. @c isc::dhcp::PktFilterBPF is used.
  145. The raw sockets are bound to a specific interface, not to the IP address/UDP port.
  146. Therefore, the system kernel doesn't have means to verify that Kea is listening
  147. to the DHCP traffic on the specific address and port. This has two major implications:
  148. - It is possible to run another DHCPv4 sever instance which will bind socket to the
  149. same address and port.
  150. - An attempt to send a unicast message to the DHCPv4 server will result in ICMP
  151. "Port Unreachable" message being sent by the kernel (which is unaware that the
  152. DHCPv4 service is actually running).
  153. In order to overcome these issues, the packet filtering classes open a
  154. regular IP/UDP socket which coexists with the raw socket. The socket is referred
  155. to as "fallback socket" in the Kea code. All packets received through this socket
  156. are discarded.
  157. @section libdhcpPktFilter6 Switchable Packet Filters for DHCPv6
  158. The DHCPv6 implementation doesn't suffer from the problems described in \ref
  159. libdhcpPktFilter. Therefore, the socket creation and methods used to send
  160. and receive DHCPv6 messages are common for all OSes. However, there is
  161. still a need to customize the operations on the sockets to reliably unit test
  162. the \ref isc::dhcp::IfaceMgr logic.
  163. The \ref isc::dhcp::IfaceMgr::openSockets6 function examines configuration
  164. of detected interfaces for their availability to listen DHCPv6 traffic. For
  165. all running interfaces (except local loopback) it will try to open a socket
  166. and bind it to the link-local or global unicast address. The socket will
  167. not be opened on the interface which is down or for which it was explicitly
  168. specified that it should not be used to listen to DHCPv6 messages. There is
  169. a substantial amount of logic in this function that has to be unit tested for
  170. various interface configurations, e.g.:
  171. - multiple interfaces with link-local addresses only
  172. - multiple interfaces, some of them having global unicast addresses,
  173. - multiple interfaces, some of them disabled
  174. - no interfaces
  175. The \ref isc::dhcp::IfaceMgr::openSockets6 function attempts to open
  176. sockets on detected interfaces. At the same time, the number of interfaces,
  177. and their configuration is specific to OS where the tests are being run.
  178. So the test doesn't have any means to configure interfaces for the test case
  179. being run. Moreover, a unit test should not change the configuration of the
  180. system. For example, a change to the configuration of the interface which
  181. is used to access the machine running a test, may effectively break the
  182. access to this machine.
  183. In order to overcome the problem described above, the unit tests use
  184. fake interfaces which can be freely added, configured and removed from the
  185. \ref isc::dhcp::IfaceMgr. Obviously, it is not possible to open a socket
  186. on a fake interface, nor use it to send or receive IP packets. To mimic
  187. socket operations on fake interfaces it is required that the functions
  188. which open sockets, send messages and receive messages have to be
  189. customizable. This is achieved by implementation of replaceable packet
  190. filter objects which derive from the \ref isc::dhcp::PktFilter6 class.
  191. The default implementation of this class is \ref isc::dhcp::PktFilterInet6
  192. which creates a regular datagram IPv6/UDPv6 socket. The unit tests use a
  193. stub implementation isc::dhcp::test::PktFilter6Stub which contains no-op
  194. functions.
  195. Use \ref isc::dhcp::IfaceMgr::setPacketFilter function to set the custom packet
  196. filter object to be used by Interface Manager.
  197. @section libdhcpErrorLogging Logging non-fatal errors in IfaceMgr
  198. The libdhcp++ is a common library, meant to be used by various components,
  199. such as DHCP servers, relays and clients. It is also used by a perfdhcp
  200. benchmarking application. It provides a basic capabilities for these
  201. applications to perform operations on DHCP messages such as encoding
  202. or decoding them. It also provides capabilities to perform low level
  203. operations on sockets. Since libdhcp++ is a common library, its dependency
  204. on other BINDX modules should be minimal. In particular, errors occurring
  205. in the libdhcp++ are reported using exceptions, not a BINDX logger. This
  206. works well in most cases, but there are some cases in which it is
  207. undesired for a function to throw an exception in case of non-fatal error.
  208. The typical case, when exception should not be thrown, is when the \ref
  209. isc::dhcp::IfaceMgr::openSockets4 or \ref isc::dhcp::IfaceMgr::openSockets6
  210. fails to open a socket on one of the interfaces. This should not preclude
  211. the function from attempting to open sockets on other interfaces, which
  212. would be the case if exception was thrown.
  213. In such cases the IfaceMgr makes use of error handler callback function
  214. which may be installed by a caller. This function must implement the
  215. isc::dhcp::IfaceMgrErrorMsgCallback. Note that it is allowed to pass a NULL
  216. value instead, which would result falling back to a default behavior and
  217. exception will be thrown. If non-NULL value is provided, the
  218. \ref isc::dhcp::IfaceMgr will call error handler function and pass an
  219. error string as an argument. The handler function may use its logging
  220. mechanism to log this error message. In particular, the DHCP server
  221. will use BINDX logger to log the error message.
  222. */