diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-13 12:15:43 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-13 12:15:43 +0000 |
commit | f5f56e1a1c4d9e9496fcb9d81131066a964ccd23 (patch) | |
tree | 49e44c6f87febed37efb953ab5485aa49f6481a7 /src/lib/dhcp/libdhcp++.dox | |
parent | Initial commit. (diff) | |
download | isc-kea-f5f56e1a1c4d9e9496fcb9d81131066a964ccd23.tar.xz isc-kea-f5f56e1a1c4d9e9496fcb9d81131066a964ccd23.zip |
Adding upstream version 2.4.1.upstream/2.4.1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/lib/dhcp/libdhcp++.dox')
-rw-r--r-- | src/lib/dhcp/libdhcp++.dox | 280 |
1 files changed, 280 insertions, 0 deletions
diff --git a/src/lib/dhcp/libdhcp++.dox b/src/lib/dhcp/libdhcp++.dox new file mode 100644 index 0000000..ef47dd7 --- /dev/null +++ b/src/lib/dhcp/libdhcp++.dox @@ -0,0 +1,280 @@ +// Copyright (C) 2012-2020 Internet Systems Consortium, Inc. ("ISC") +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +/** +@page libdhcp libkea-dhcp++ - Low Level DHCP Library + +@section libdhcpIntro Libdhcp++ Library Introduction + +libdhcp++ is an all-purpose DHCP-manipulation library, written in +C++. It offers packet parsing and assembly, DHCPv4 and DHCPv6 +options parsing and assembly, interface detection (currently on +Linux, FreeBSD, NetBSD, OpenBSD, Max OS X, and Solaris 11) and socket operations. +It is a generic purpose library that +can be used by server, client, relay, performance tools and other DHCP-related +tools. For server specific library, see \ref libdhcpsrv. Please do not +add any server-specific code to libdhcp++ and use \ref libdhcpsrv instead. + +The following classes for packet manipulation are implemented: + +- isc::dhcp::Pkt4 - represents a DHCPv4 packet. +- isc::dhcp::Pkt6 - represents a DHCPv6 packet. +- isc::dhcp::Pkt4o6 - represents a DHCPv4-over-DHCPv6 packet. + +The following pointer types are defined: \c Pkt4Ptr, \c Pkt6Ptr and Pkt4o6Ptr. +They are smart pointers using the \c boost::shared_ptr type. There are no const +versions of packet types defined, as we assume that hooks can modify any +aspect of the packet at almost any stage of processing. + +Both packet types use a collection of \ref isc::dhcp::Option objects to +represent DHCPv4 and DHCPv6 options. The base class @c Option can be used to +represent generic option that contains collection of +bytes. Depending on whether the option is instantiated as a DHCPv4 or DHCPv6 +option, it will adjust its header (DHCPv4 options use 1 octet for +type and 1 octet for length, while DHCPv6 options use 2 bytes for +each). + +There are many specialized classes that are intended to handle options having +specific formats: +- isc::dhcp::Option4AddrLst -- DHCPv4 option, contains one or more IPv4 addresses; +- isc::dhcp::Option6AddrLst -- DHCPv6 option, contains one or more IPv6 addresses; +- isc::dhcp::Option4ClientFqdn -- DHCPv4 Client FQDN option; +- isc::dhcp::Option6ClientFqdn -- DHCPv6 Client FQDN option; +- isc::dhcp::Option6IAAddr -- DHCPv6 option, represents an IAADDR option (an option that + contains IPv6 address with extra parameters); +- isc::dhcp::Option6IAPrefix -- DHCPv6 option, represents an IAPREFIX option (an option + that contains IPv6 prefix in prefix delegation); +- isc::dhcp::Option6IA -- DHCPv6 option used to store IA_NA and its suboptions. +- isc::dhcp::Option6StatusCode -- DHCPv6 option, carries a status code to the client; +- isc::dhcp::OptionCustom -- Represents an option having many different formats, where + data fields can be accessed in a convenient way; +- isc::dhcp::OptionInt -- DHCPv4 or DHCPv6 option, carries a single numeric value; +- isc::dhcp::OptionString -- DHCPv4 or DHCPv6 option, carries a text value; +- isc::dhcp::OptionVendor -- DHCPv4 or DHCPv6 option, carries Vendor Specific + Information; +- isc::dhcp::OptionVendorClass -- DHCPv4 or DHCPv6 option, contains vendor class + information. + +Various options can store sub-options (i.e. options that are stored within an +option rather than in a message directly). This functionality is commonly used in +DHCPv6, but is rarely used in DHCPv4. \ref isc::dhcp::Option::addOption(), +\ref isc::dhcp::Option::delOption(), \ref isc::dhcp::Option::getOption() can +be used to add, remove and retrieve sub-options from within an option. + +@section libdhcpDhcp4o6 DHCPv4-over-DHCPv6 support + +The DHCPv4-over-DHCPv6 packet class (\c Pkt4o6) is derived from +the DHCPv4 packet class (\c Pkt4) with: + +- un extra member pointing to the encapsulating DHCPv6 packet, accessible + by \ref isc::dhcp::Pkt4o6::getPkt6() +- a specialized isc::dhcp::Pkt::pack() method which builds the wire-format + data of the whole DHCPv6-over-DHCPv4 packet. + +To avoid the extra overhead of dynamic casts the isc::dhcp::Pkt4::isDhcp4o6() +virtual method returns true for \c Pkt4o6 instances and false for others. + +@section libdhcpRelay Relay v6 support in Pkt6 + +DHCPv6 clients that are not connected to the same link as DHCPv6 +servers need relays to reach the server. Each relay receives a message +on a client facing interface, encapsulates it into RELAY_MSG option +and sends as RELAY_FORW message towards the server (or the next relay, +which is closer to the server). This procedure can be repeated up to +32 times. Kea is able to support up to 32 relays. Each traversed relay +may add certain options. The most obvious example is interface-id +option, but there may be other options as well. Each relay may add such +an option, regardless of whether other relays added it before. Thanks +to encapsulation, those options are separated and it is possible to +differentiate which relay inserted specific instance of an option. + +Interface-id is used to identify a subnet (or interface) the original message +came from and is used for that purpose on two occasions. First, the server +uses the interface-id included by the first relay (the one closest to +the client) to select appropriate subnet for a given request. Server includes +that interface-id in its copy, when sending data back to the client. +This will be used by the relay to choose proper interface when forwarding +response towards the client. + +The Pkt6 class has a public \c Pkt6::relay_info_ field, which is of type \c Pkt6::RelayInfo. +This is a simple structure that represents the information in each RELAY_FORW +or RELAY_REPL message. It is important to understand the order in which +the data appear here. Consider the following network: + +\verbatim +client-------relay1-----relay2-----relay3----server +\endverbatim + +Client will transmit SOLICIT message. Relay1 will forward it as +RELAY_FORW with SOLICIT in it. Relay2 forward it as RELAY_FORW with +RELAY_FORW with SOLICIT in it. Finally the third relay will add yet +another RELAY_FORW around it. The server will parse the packet and +create \c Pkt6 object for it. Its relay_info_ will have 3 +elements. Packet parsing is done in reverse order, compare to the +order the packet traversed in the network. The first element +(relay_info_[0]) will represent relay3 information (the "last" relay or +in other words the one closest to the server). The second element +will represent relay2. The third element (relay_info_[2]) will represent +the first relay (relay1) or in other words the one closest to the client. + +Packets sent by the server must maintain the same encapsulation order. +This is easy to do - just copy data from client's message object into +server's response object. See @ref isc::dhcp::Pkt6::RelayInfo for details. + +@section libdhcpIfaceMgr Interface Manager + +Interface Manager (or IfaceMgr) is an abstraction layer for low-level +network operations. In particular, it provides information about existing +network interfaces See @ref isc::dhcp::Iface class and +@ref isc::dhcp::IfaceMgr::detectIfaces() and @ref isc::dhcp::IfaceMgr::getIface(). + +Generic parts of the code are contained in the @ref isc::dhcp::IfaceMgr class in +src/lib/dhcp/iface_mgr.cc file. OS-specific code is located in separate +files, e.g. iface_mgr_linux.cc, iface_mgr_bsd. The separation should be +maintained when developing additional code. + +Other useful methods are dedicated to transmission +(\ref isc::dhcp::IfaceMgr::send(), 2 overloads) and reception +(\ref isc::dhcp::IfaceMgr::receive4() and \ref isc::dhcp::IfaceMgr::receive6()). +Note that \c receive4() and \c receive6() methods may return NULL, e.g. +when timeout is reached or if the DHCP daemon receives a signal. + +@section libdhcpPktFilter Switchable Packet Filter objects used by Interface Manager + +The well known problem of DHCPv4 implementation is that it must be able to +provision devices which don't have an IPv4 address yet (the IPv4 address is +one of the configuration parameters provided by DHCP server to a client). +One way to communicate with such a device is to send server's response to +a broadcast address. An obvious drawback of this approach is that the server's +response will be received and processed by all clients in the particular +network. Therefore, the preferred approach is that the server unicasts its +response to a new address being assigned for the client. This client will +identify itself as a target of this message by checking chaddr and/or +Client Identifier value. At the same time, the other clients in the network +will not receive the unicast message. The major problem that arises with this +approach is that the client without an IP address doesn't respond to ARP +messages. As a result, server's response will not be sent over IP/UDP +socket because the system kernel will fail to resolve client's link-layer +address. + +Kea supports the use of raw sockets to create a complete Data-link/IP/UDP/DHCPv4 +stack. By creating each layer of the outgoing packet, the Kea logic has full +control over the frame contents and it may bypass the use of ARP to inject the +link layer address into the frame. + +The low level operations on raw sockets are implemented within the "packet +filtering" classes derived from @c isc::dhcp::PktFilter. The implementation +of these classes is specific to the operating system. On Linux the +@c isc::dhcp::PktFilterLPF is used. On BSD systems the +@c isc::dhcp::PktFilterBPF is used. + +The raw sockets are bound to a specific interface, not to the IP address/UDP port. +Therefore, the system kernel doesn't have means to verify that Kea is listening +to the DHCP traffic on the specific address and port. This has two major implications: +- It is possible to run another DHCPv4 sever instance which will bind socket to the +same address and port. +- An attempt to send a unicast message to the DHCPv4 server will result in ICMP +"Port Unreachable" message being sent by the kernel (which is unaware that the +DHCPv4 service is actually running). + +In order to overcome these issues, the packet filtering classes open a +regular IP/UDP socket which coexists with the raw socket. The socket is referred +to as "fallback socket" in the Kea code. All packets received through this socket +are discarded. + +@section libdhcpPktFilter6 Switchable Packet Filters for DHCPv6 + +The DHCPv6 implementation doesn't suffer from the problems described in \ref +libdhcpPktFilter. Therefore, the socket creation and methods used to send +and receive DHCPv6 messages are common for all OSes. However, there is +still a need to customize the operations on the sockets to reliably unit test +the \ref isc::dhcp::IfaceMgr logic. + +The \ref isc::dhcp::IfaceMgr::openSockets6 function examines configuration +of detected interfaces for their availability to listen DHCPv6 traffic. For +all running interfaces (except local loopback) it will try to open a socket +and bind it to the link-local or global unicast address. The socket will +not be opened on the interface which is down or for which it was explicitly +specified that it should not be used to listen to DHCPv6 messages. There is +a substantial amount of logic in this function that has to be unit tested for +various interface configurations, e.g.: +- multiple interfaces with link-local addresses only +- multiple interfaces, some of them having global unicast addresses, +- multiple interfaces, some of them disabled +- no interfaces + +The \ref isc::dhcp::IfaceMgr::openSockets6 function attempts to open +sockets on detected interfaces. At the same time, the number of interfaces, +and their configuration is specific to OS where the tests are being run. +So the test doesn't have any means to configure interfaces for the test case +being run. Moreover, a unit test should not change the configuration of the +system. For example, a change to the configuration of the interface which +is used to access the machine running a test, may effectively break the +access to this machine. + +In order to overcome the problem described above, the unit tests use +fake interfaces which can be freely added, configured and removed from the +\ref isc::dhcp::IfaceMgr. Obviously, it is not possible to open a socket +on a fake interface, nor use it to send or receive IP packets. To mimic +socket operations on fake interfaces it is required that the functions +which open sockets, send messages and receive messages have to be +customizable. This is achieved by implementation of replaceable packet +filter objects which derive from the \ref isc::dhcp::PktFilter6 class. +The default implementation of this class is \ref isc::dhcp::PktFilterInet6 +which creates a regular datagram IPv6/UDPv6 socket. The unit tests use a +stub implementation isc::dhcp::test::PktFilter6Stub which contains no-op +functions. + +Use \ref isc::dhcp::IfaceMgr::setPacketFilter function to set the custom packet +filter object to be used by Interface Manager. + +@section libdhcpErrorLogging Logging non-fatal errors in IfaceMgr + +The libdhcp++ is a common library, meant to be used by various components, +such as DHCP servers, relays and clients. It is also used by a perfdhcp +benchmarking application. It provides a basic capabilities for these +applications to perform operations on DHCP messages such as encoding +or decoding them. It also provides capabilities to perform low level +operations on sockets. Since libdhcp++ is a common library, its dependency +on other BINDX modules should be minimal. In particular, errors occurring +in the libdhcp++ are reported using exceptions, not a BINDX logger. This +works well in most cases, but there are some cases in which it is +undesired for a function to throw an exception in case of non-fatal error. + +The typical case, when exception should not be thrown, is when the \ref +isc::dhcp::IfaceMgr::openSockets4 or \ref isc::dhcp::IfaceMgr::openSockets6 +fails to open a socket on one of the interfaces. This should not preclude +the function from attempting to open sockets on other interfaces, which +would be the case if exception was thrown. + +In such cases the IfaceMgr makes use of error handler callback function +which may be installed by a caller. This function must implement the +isc::dhcp::IfaceMgrErrorMsgCallback. Note that it is allowed to pass a NULL +value instead, which would result falling back to a default behavior and +exception will be thrown. If non-NULL value is provided, the +\ref isc::dhcp::IfaceMgr will call error handler function and pass an +error string as an argument. The handler function may use its logging +mechanism to log this error message. In particular, the DHCP server +will use BINDX logger to log the error message. + +@section libdhcpMTConsiderations Multi-Threading Consideration for DHCP library + +By default APIs provided by the DHCP library are not thread safe. +For instance packets or options are not thread safe. Exception are: + + - external sockets are thread safe (the container used to manage external + socket is thread safe so one can for instance delete an external socket + at any time). + + - interface lookup cache is Kea thread safe (i.e. thread safe when the + multi-threading mode is true). + + - interface send method is thread safe (mainly because it does not change + any internal state). + + - packet queue ring is thread safe. + +*/ |