libdhcp++.dox 14 KB

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