Browse Source

[master] Merge branch 'trac3806'

# Conflicts:
#	doc/guide/logging.xml
Marcin Siodelski 10 years ago
parent
commit
7b148c2dd5

+ 74 - 34
doc/guide/logging.xml

@@ -85,25 +85,46 @@
           </para>
 
           <para>
-            If you want to specify logging for one specific library within a
-            daemon, you set the name to
-            <replaceable>daemon.library</replaceable>.  For example, the logger
-            used by the code from libdhcpsrv used in kea-dhcp4 binary has the
-            full name of <quote>kea-dhcp4.dhcpsrv</quote>. If there is no entry
-            in Logging for a particular library, it will use the configuration
-            given for the whole daemon.
+            When diagnosing the problem with the server's operation it is often
+            desired to use the DEBUG logging level to obtain the verbose output
+            from the server and libraries it uses. However, high verbosity may
+            be an overkill for the logging system in cases when the server
+            is processing high volume traffic. To mitigate this problem, Kea
+            is using multiple loggers, which can be configured independently
+            and which are responsible for logging messages from different
+            functional parts of the server. If the user, trying to diagnose the
+            problem, has a reasonably high confidence that the problem origins
+            in a specific function of the server, or the problem is related
+            to the specific type of operation, he may enable high verbosity
+            only for the relevant logger, thus limiting the debug messages
+            to the required minimum.
           </para>
 
           <para>
-            To illustrate this, suppose you want the dhcpsrv library
-            to log messages of severity DEBUG, and the rest of the
-            DHCPv4 server code to log messages of severity INFO. To achieve
-            this you specify two loggers, one with the name
-            <quote>kea-dhcp4</quote> and severity INFO, and one with
-            the name <quote>kea-dhcp4.dhcpsrv</quote> with severity
-            DEBUG. As there are no entries for other libraries,
-            they will use the configuration for the daemon
-            (<quote>kea-dhcp4</quote>), so giving the desired behavior.
+            The loggers are associated with a particular library or binary
+            of Kea. However, each library or binary may (and usually does)
+            include multiple loggers. For example, the DHCPv4 server binary
+            contains separate loggers for: packet parsing, for dropped packets,
+            for callouts etc. Each logger "derives" its configuration from the
+            root logger. In the typical case, the root logger configuration
+            is the only logging configuration specified in the configuration
+            file. Creating a specific configuration for the selected logger,
+            thus overriding the configuration settings specified in the
+            root logger configuration, requires putting its configuration
+            aside of the root logger's configuration with some of the
+            parameters modified.
+          </para>
+
+          <para>
+            To illustrate this, suppose you are using the DHCPv4 server
+            with the root logger <quote>kea-dhcp4</quote> logging at the
+            INFO level. In order to enable DEBUG verbosity for the DHCPv4
+            packet drops, you must create configuration entry for the
+            logger called <quote>kea-dhcp4.bad_packet</quote> and specify
+            severity DEBUG for this logger. All other configuration
+            parameters may be omited for this logger if the logger should
+            use the default values specified in the root logger's
+            configuration.
           </para>
 
         <!-- we don't support asterisk anymore.
@@ -129,21 +150,6 @@
           </para>
 
           <para>
-            One final note about the naming. When specifying the daemon name
-            within a logger, use the name of the binary file,
-            e.g. <quote>kea-dhcp4</quote> for the DHCPv4 server,
-            <quote>kea-dhcp6</quote> for the DHCPv6 server, etc. When the
-            message is logged, the message will include the name of the process
-            (e.g. <quote>kea-dhcp4</quote>) followed by the specific component
-            in that process, e.g. <quote>hooks</quote>.  It is possible to
-            specify either just the process name (<quote>kea-dhcp4</quote>, will
-            apply to everything logged within that process) or process name
-            followed by specific logger,
-            e.g. <quote>kea-dhcp4.hooks</quote>. That will apply only to
-            messages originating from that component.
-          </para>
-
-          <para>
             Currently defined loggers are:
           </para>
 
@@ -158,7 +164,7 @@
             <simpara><command>kea-dhcp4.bad_packet</command> - this is the
             logger used by the DHCPv4 server deamon for logging inbound client
             packets that were dropped or to which the server responded with a
-            NAK.  The allows adminstrators to configure a separate log
+            DHCPNAK. The allows adminstrators to configure a separate log
             output that contains only packet drop and reject entries.</simpara>
           </listitem>
           <listitem>
@@ -175,7 +181,9 @@
           <listitem>
             <simpara><command>kea-dhcp4.hooks</command> - this logger is used
             to log messages related to management of hooks libraries, e.g.
-            registration and deregistration of the libraries.</simpara>
+            registration and deregistration of the libraries, and to the
+            initialization of the callouts execution for various hook points
+            within the DHCPv4 server.</simpara>
           </listitem>
           <listitem>
             <simpara><command>kea-dhcp4.callouts</command> - this logger is used
@@ -184,12 +192,44 @@
             </simpara>
           </listitem>
           <listitem>
+            <simpara><command>kea-dhcp4.ddns</command> - this logger is used by
+            the DHCPv4 server to log messages related to the Client FQDN and
+            Hostname option processing. It also includes log messages
+            related to the relevant DNS updates.</simpara>
+          </listitem>
+          <listitem>
             <simpara><command>kea-dhcp4.hosts</command> - this logger is used
             within the libdhcpsrv and it logs messages related to the management
             of the DHCPv4 host reservations, i.e. retrieval of the resevations
             and adding new reservations.</simpara>
           </listitem>
           <listitem>
+            <simpara><command>kea-dhcp4.leases</command> - this logger is used
+            by the DHCPv4 server to log messages related to the lease allocation.
+            The messages include detailed information about the allocated or
+            offered leases, errors during the lease allocation etc.
+            </simpara>
+          </listitem>
+          <listitem>
+            <simpara><command>kea-dhcp4.options</command> - this logger is
+            used by the DHCPv4 server to log messages related to processing
+            of the options in the DHCPv4 messages, i.e. parsing options,
+            encoding options into on-wire format and packet classification
+            using options contained in the received packets.</simpara>
+          </listitem>
+          <listitem>
+            <simpara><command>kea-dhcp4.packets</command> - this logger
+            is mostly used to log messages related to transmission of the DHCPv4
+            packets, i.e. packet reception and sending a response. Such messages
+            include the information about the source and destination IP addresses
+            and interfaces used to transmit packets. This logger is also used
+            to log messages related to subnet selection, as this selection is
+            usually based on the IP addresses and/or interface names, which can
+            be retrieved from the received packet, even before the DHCPv4 message
+            carried in the packet is parsed.
+            </simpara>
+          </listitem>
+          <listitem>
             <simpara><command>kea-dhcp6</command> - this is the root logger for
             the DHCPv6 server. All components used by the DHCPv6 server inherit
             the settings from this logger if there is no specialized logger
@@ -208,7 +248,7 @@
           </listitem>
           <listitem>
             <simpara><command>kea-dhcp6.hooks</command> - this logger is used
-            to log messages related to management of hooks libraries, e.g.
+            during DHCPv6 hooks operation, i.e. anything related to user
             registration and deregistration of the libraries.</simpara>
           </listitem>
           <listitem>

+ 11 - 2
src/bin/dhcp4/dhcp4_log.cc

@@ -12,7 +12,8 @@
 // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 // PERFORMANCE OF THIS SOFTWARE.
 
-/// Defines the logger used by the top-level component of kea-dhcp4.
+/// @file dhcp4_log.cc
+/// Contains the loggers used by the DHCPv4 server component.
 
 #include <dhcp4/dhcp4_log.h>
 
@@ -21,10 +22,18 @@ namespace dhcp {
 
 const char* DHCP4_ROOT_LOGGER_NAME = "kea-dhcp4";
 const char* DHCP4_APP_LOGGER_NAME = "dhcp4";
-const char* DHCP4_BAD_PACKET_LOGGER_NAME = "bad-packet";
+const char* DHCP4_BAD_PACKET_LOGGER_NAME = "bad-packets";
+const char* DHCP4_PACKET_LOGGER_NAME = "packets";
+const char* DHCP4_OPTIONS_LOGGER_NAME = "options";
+const char* DHCP4_DDNS_LOGGER_NAME = "ddns";
+const char* DHCP4_LEASE_LOGGER_NAME = "leases";
 
 isc::log::Logger dhcp4_logger(DHCP4_APP_LOGGER_NAME);
 isc::log::Logger bad_packet_logger(DHCP4_BAD_PACKET_LOGGER_NAME);
+isc::log::Logger packet_logger(DHCP4_PACKET_LOGGER_NAME);
+isc::log::Logger options_logger(DHCP4_OPTIONS_LOGGER_NAME);
+isc::log::Logger ddns_logger(DHCP4_DDNS_LOGGER_NAME);
+isc::log::Logger lease_logger(DHCP4_LEASE_LOGGER_NAME);
 
 } // namespace dhcp
 } // namespace isc

+ 88 - 27
src/bin/dhcp4/dhcp4_log.h

@@ -12,6 +12,9 @@
 // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 // PERFORMANCE OF THIS SOFTWARE.
 
+/// @file dhcp4_log.h
+/// Contains declarations for loggers used by the DHCPv4 server component.
+
 #ifndef DHCP4_LOG_H
 #define DHCP4_LOG_H
 
@@ -22,52 +25,110 @@
 namespace isc {
 namespace dhcp {
 
-/// Defines the name of the root level "default" logger for kea dhcp4 server.
-extern const char* DHCP4_ROOT_LOGGER_NAME;
-
-/// \brief DHCP4 Logging
-///
-/// Defines the levels used to output debug messages in the non-library part of
-/// the kea-dhcp4 program.  Higher numbers equate to more verbose (and detailed)
-/// output.
+/// @name Constants defining debug levels for logging in DHCPv4 server.
+//@{
 
-// Debug levels used to log information during startup and shutdown.
+/// @brief Debug level used to log information during server startup.
 const int DBG_DHCP4_START = DBGLVL_START_SHUT;
+
+/// @brief Debug level used to log information during server shutdown.
 const int DBG_DHCP4_SHUT = DBGLVL_START_SHUT;
 
-// Debug level used to log setting information (such as configuration changes).
+/// @brief Debug level used to log receiving commands.
 const int DBG_DHCP4_COMMAND = DBGLVL_COMMAND;
 
-// Trace basic operations within the code.
+/// @brief Debug level used to trace basic operations within the code.
 const int DBG_DHCP4_BASIC = DBGLVL_TRACE_BASIC;
 
-// Trace hook related operations
+/// @brief Debug level used to trace hook related operations
 const int DBG_DHCP4_HOOKS = DBGLVL_TRACE_BASIC;
 
-// Trace detailed operations, including errors raised when processing invalid
-// packets.  (These are not logged at severities of WARN or higher for fear
-// that a set of deliberately invalid packets set to the server could overwhelm
-// the logging.)
+/// @brief Debug level used to log the traces with some basic data.
+///
+/// The basic data includes summary information, e.g. summary of the
+/// information returned by a particular function. It may also include
+/// more detailed information in cases when it is warranted and the
+/// extraction of the data doesn't impact the server's performance
+/// significantly.
+const int DBG_DHCP4_BASIC_DATA = DBGLVL_TRACE_BASIC_DATA;
+
+/// @brief Debug level used to trace detailed errors.
+///
+/// Trace detailed operations, including errors raised when processing invalid
+/// packets.  (These are not logged at severities of WARN or higher for fear
+/// that a set of deliberately invalid packets set to the server could overwhelm
+/// the logging.)
 const int DBG_DHCP4_DETAIL = DBGLVL_TRACE_DETAIL;
 
-// This level is used to log the contents of packets received and sent.
+/// @brief This level is used to log the contents of packets received and sent.
 const int DBG_DHCP4_DETAIL_DATA = DBGLVL_TRACE_DETAIL_DATA;
 
-/// Define the logger for the "dhcp4" module part of kea-dhcp4.  We could define
-/// a logger in each file, but we would want to define a common name to avoid
-/// spelling mistakes, so it is just one small step from there to define a
-/// module-common logger.
+//@}
+
+/// @name Constants holding names of loggers for the DHCPv4 server.
+//@{
+
+/// @brief Defines the name of the root level (default) logger.
+extern const char* DHCP4_ROOT_LOGGER_NAME;
+
+/// @brief Name of the base logger for DHCPv4 server.
 extern const char* DHCP4_APP_LOGGER_NAME;
-extern isc::log::Logger dhcp4_logger;
 
-/// Define a separate logger to which bad packets are logged.  This allows
-/// users to segregate them into a separate log destination for easy monitoring
-/// and diagnostics.  Here "bad packet" are packets that are either dropped
-/// (i.e malformed, unsupported types) or packets that are rejected and NAKed
-/// for logical reasons.
+/// @brief Name of the logger for rejected packets.
 extern const char* DHCP4_BAD_PACKET_LOGGER_NAME;
+
+/// @brief Name of the logger for processed packets.
+extern const char* DHCP4_PACKET_LOGGER_NAME;
+
+/// @brief Name of the logger for options parser.
+extern const char* DHCP4_OPTIONS_LOGGER_NAME;
+
+/// @brief Name of the logger for hostname or FQDN processing.
+extern const char* DHCP4_DDNS_LOGGER_NAME;
+
+/// @brief Name of the logger for lease allocation logic.
+extern const char* DHCP4_LEASE_LOGGER_NAME;
+
+//@}
+
+/// @name Loggers used by the DHCPv4 server
+//@{
+
+/// @brief Base logger for DHCPv4 server.
+extern isc::log::Logger dhcp4_logger;
+
+/// @brief Logger for rejected packets.
+///
+/// Here "bad packets" are packets that are either dropped (i.e malformed,
+/// unsupported types) or packets that are rejected and NAKed for logical
+/// reasons.
 extern isc::log::Logger bad_packet_logger;
 
+/// @brief Logger for processed packets.
+///
+/// This logger is used to issue log messages related to the reception and
+/// sending DHCP packets.
+extern isc::log::Logger packet_logger;
+
+/// @brief Logger for options parser.
+///
+/// This logger is used to issue log messages related to processing of the
+/// DHCP options 
+extern isc::log::Logger options_logger;
+
+/// @brief Logger for Hostname or FQDN processing.
+///
+/// This logger is used to issue log messages related to processing the
+/// hostnames, FQDNs and sending name change requests to D2.
+extern isc::log::Logger ddns_logger;
+
+/// @brief Logger for lease allocation logic.
+///
+/// This logger is used to issue log messages related to lease allocation.
+extern isc::log::Logger lease_logger;
+
+//@}
+
 } // namespace dhcp4
 } // namespace isc
 

+ 271 - 74
src/bin/dhcp4/dhcp4_messages.mes

@@ -19,6 +19,43 @@ This message is printed when DHCPv4 server enabled an interface to be used
 to receive DHCPv4 traffic. IPv4 socket on this interface will be opened once
 Interface Manager starts up procedure of opening sockets.
 
+% DHCP4_BUFFER_RECEIVE_FAIL error on attempt to receive packet: %1
+The DHCPv4 server tried to receive a packet but an error
+occurred during this attempt. The reason for the error is included in
+the message.
+
+% DHCP4_BUFFER_RECEIVED received buffer from %1:%2 to %3:%4 over interface %5
+This debug message is logged when the server has received a packet
+over the socket. When the message is logged the contents of the received
+packet hasn't been parsed yet. The only available information is the
+interface and the source and destination addresses/ports.
+
+% DHCP4_BUFFER_UNPACK parsing buffer received from %1 to %2 over interface %3
+This debug message is issued when the server starts parsing the received
+buffer holding the DHCPv4 message. The arguments specify the source and
+destination addresses as well as the interface over which the buffer has
+been received.
+
+% DHCP4_BUFFER_WAIT waiting for next DHCPv4 packet with timeout %1 ms
+This debug message is issued when the server enters the state when it
+waits for new packets. The argument specifies the timeout for the server
+to wait for the packet. When this time elapses the server will pass
+through its main loop to perform handling of any pending signals
+and timers. After that, it will enter the wait state again.
+
+% DHCP4_BUFFER_WAIT_SIGNAL signal received while waiting for next packet, next waiting signal is %1
+This debug message is issued when the server was waiting for the
+packet, but the wait has been interrupted by the signal received
+by the process. The signal will be handled before the server starts
+waiting for next packets. The argument specifies the next signal to
+be handled by the server.
+
+% DHCP4_BUFFER_WAIT_TIMEOUT timeout %1 ms reached while waiting for the next packet
+This debug message is issued when the timeout has occurred while
+waiting for the next packet. The server will now handle signals
+received and ready timers before waiting for next packets again.
+The argument specifies the timeout value in milliseconds.
+
 % DHCP4_CCSESSION_STARTED control channel session started on socket %1
 A debug message issued during startup after the DHCPv4 server has
 successfully established a session with the Kea control channel.
@@ -27,14 +64,43 @@ successfully established a session with the Kea control channel.
 This debug message is issued just before the DHCPv4 server attempts
 to establish a session with the Kea control channel.
 
-% DHCP4_CLASS_ASSIGNED client packet has been assigned to the following class(es): %1
+% DHCP4_CLASS_ASSIGNED %1: client packet has been assigned to the following class(es): %2
 This debug message informs that incoming packet has been assigned to specified
 class or classes. This is a normal behavior and indicates successful operation.
-
-% DHCP4_CLIENT_NAME_PROC_FAIL failed to process the fqdn or hostname sent by a client: %1
+The first argument specifies the client and transaction identification
+information. The second argument includes all classes to which the
+packet has been assigned.
+
+% DHCP4_CLIENT_FQDN_PROCESS %1: processing Client FQDN option
+This debug message is issued when the server starts processing the Client
+FQDN option sent in the client's query. The argument includes the
+client and transaction identification information.
+
+% DHCP4_CLIENT_FQDN_DATA %1: Client sent FQDN option: %2
+This debug message includes the detailed information extracted from the
+Client FQDN option sent in the query. The first argument includes the
+client and transaction identification information. The second argument
+specifies the detailed information about the FQDN option received
+by the server.
+
+% DHCP4_CLIENT_HOSTNAME_PROCESS %1: processing client's Hostname option
+This debug message is issued when the server starts processing the Hostname
+option sent in the client's query. The argument includes the client and
+transaction identification information.
+
+% DHCP4_CLIENT_HOSTNAME_DATA %1: client sent Hostname option: %2
+This debug message includes the detailed information extracted from the
+Hostname option sent in the query. The first argument includes the
+client and transaction identification information. The second argument
+specifies the hostname carried in the Hostname option sent by the
+client.
+
+% DHCP4_CLIENT_NAME_PROC_FAIL %1: failed to process the fqdn or hostname sent by a client: %2
 This debug message is issued when the DHCP server was unable to process the
 FQDN or Hostname option sent by a client. This is likely because the client's
-name was malformed or due to internal server error.
+name was malformed or due to internal server error. The first argument
+contains the client and transaction identification information. The
+second argument holds the detailed description of the error.
 
 % DHCP4_COMMAND_RECEIVED received command %1, arguments: %2
 A debug message listing the command (and possible arguments) received
@@ -89,9 +155,10 @@ This error message is logged when the attempt to compute DHCID for a specified
 lease has failed. The lease details and reason for failure is logged in the
 message.
 
-% DHCP4_DISCOVER_CLASS_PROCESSING_FAILED client class specific processing failed for DHCPDISCOVER
+% DHCP4_DISCOVER_CLASS_PROCESSING_FAILED %1: client class specific processing failed for DHCPDISCOVER
 This debug message means that the server processing that is unique for each
 client class has reported a failure. The response packet will not be sent.
+The argument holds the client and transaction identification information.
 
 % DHCP4_DYNAMIC_RECONFIGURATION initiate server reconfiguration using file: %1, after receiving SIGHUP signal
 This is the info message logged when the DHCPv4 server starts reconfiguration
@@ -101,72 +168,95 @@ as a result of receiving SIGHUP signal.
 This is an error message logged when the dynamic reconfiguration of the
 DHCP server failed.
 
-% DHCP4_EMPTY_HOSTNAME received empty hostname from the client, skipping processing of this option
+% DHCP4_EMPTY_HOSTNAME %1: received empty hostname from the client, skipping processing of this option
 This debug message is issued when the server received an empty Hostname option
 from a client. Server does not process empty Hostname options and therefore
-option is skipped.
+option is skipped. The argument holds the client and transaction identification
+information.
 
 % DHCP4_HOOKS_LIBS_RELOAD_FAIL reload of hooks libraries failed
 A "libreload" command was issued to reload the hooks libraries but for
 some reason the reload failed.  Other error messages issued from the
 hooks framework will indicate the nature of the problem.
 
-% DHCP4_HOOK_BUFFER_RCVD_SKIP received DHCPv4 buffer was dropped because a callout set the skip flag.
+% DHCP4_HOOK_BUFFER_RCVD_SKIP received buffer from %1 to %2 over interface %3 was dropped because a callout set the skip flag
 This debug message is printed when a callout installed on buffer4_receive
 hook point set the skip flag. For this particular hook point, the
 setting of the flag by a callout instructs the server to drop the packet.
+The arguments specify the source and destination address as well as
+the name of the interface over which the buffer has been received.
 
-% DHCP4_HOOK_BUFFER_SEND_SKIP prepared DHCPv4 response was dropped because a callout set the skip flag.
+% DHCP4_HOOK_BUFFER_SEND_SKIP %1: prepared response is dropped because a callout set the skip flag.
 This debug message is printed when a callout installed on buffer4_send
 hook point set the skip flag. For this particular hook point, the
 setting of the flag by a callout instructs the server to drop the packet.
 Server completed all the processing (e.g. may have assigned, updated
 or released leases), but the response will not be send to the client.
 
-% DHCP4_HOOK_LEASE4_RELEASE_SKIP DHCPv4 lease was not released because a callout set the skip flag.
+% DHCP4_HOOK_LEASE4_RELEASE_SKIP %1: lease was not released because a callout set the skip flag.
 This debug message is printed when a callout installed on lease4_release
 hook point set the skip flag. For this particular hook point, the
 setting of the flag by a callout instructs the server to not release
 a lease.
 
-% DHCP4_HOOK_PACKET_RCVD_SKIP received DHCPv4 packet was dropped, because a callout set the skip flag.
+% DHCP4_HOOK_PACKET_RCVD_SKIP %1: packet is dropped, because a callout set the skip flag.
 This debug message is printed when a callout installed on the pkt4_receive
 hook point sets the skip flag. For this particular hook point, the
 setting of the flag instructs the server to drop the packet.
 
-% DHCP4_HOOK_PACKET_SEND_SKIP prepared DHCPv6 response was not sent, because a callout set skip flag.
+% DHCP4_HOOK_PACKET_SEND_SKIP %1: prepared response is not sent, because a callout set skip flag.
 This debug message is printed when a callout installed on the pkt4_send
 hook point sets the skip flag. For this particular hook point, the setting
 of the flag instructs the server to drop the packet. This means that
 the client will not get any response, even though the server processed
 client's request and acted on it (e.g. possibly allocated a lease).
 
-% DHCP4_HOOK_SUBNET4_SELECT_SKIP no subnet was selected, because a callout set skip flag.
+% DHCP4_HOOK_SUBNET4_SELECT_SKIP %1: no subnet was selected, because a callout set skip flag.
 This debug message is printed when a callout installed on the
 subnet4_select hook point sets the skip flag. For this particular hook
 point, the setting of the flag instructs the server not to choose a
 subnet, an action that severely limits further processing; the server
 will be only able to offer global options - no addresses will be assigned.
+The argument specifies the client and transaction identification
+information.
 
-% DHCP4_INFORM_CLASS_PROCESSING_FAILED client class specific processing failed for DHCPINFORM
+% DHCP4_INFORM_CLASS_PROCESSING_FAILED %1: client class specific processing failed for DHCPINFORM
 This debug message means that the server processing that is unique for each
 client class has reported a failure. The response packet will not be sent.
+The argument specifies the client and the transaction identification
+information.
+
+% DHCP4_INFORM_DIRECT_REPLY %1: DHCPACK in reply to the DHCPINFORM will be sent directly to %2 over %3
+This debug message is issued when the DHCPACK will be sent directly to the
+client, rather than via a relay. The first argument contains the client
+and transaction identification information. The second argument contains
+the client's address to which the response will be sent. The third argument
+contains the local interface name.
 
 % DHCP4_INIT_FAIL failed to initialize Kea server: %1
 The server has failed to initialize. This may be because the configuration
 was not successful, or it encountered any other critical error on startup.
 Attached error message provides more details about the issue.
 
-% DHCP4_LEASE_ADVERT lease %1 advertised (client client-id %2, hwaddr %3)
-This debug message indicates that the server successfully advertised
-a lease. It is up to the client to choose one server out of other advertised
-and continue allocation with that server. This is a normal behavior and
-indicates successful operation.
+% DHCP4_INIT_REBOOT %1: client is in INIT-REBOOT state and requests address %2
+This debug message is issued when the client is in the INIT-REBOOT state and
+is requesting an address it is using to be allocated for it. The first argument
+includes the client and transaction identification information. The second
+argument specifies the requested IP address.
+
+% DHCP4_LEASE_ADVERT %1: lease %2 will be advertised
+This debug message indicates that the server has found the lease to be
+offered to the client. It is up to the client to choose one server out of
+those which offered leases and continue allocation with that server.
+The first argument specifies the client and the transaction identification
+information. The second argument specifies the address to be offered.
 
-% DHCP4_LEASE_ALLOC lease %1 has been allocated for client-id %2, hwaddr %3
+% DHCP4_LEASE_ALLOC %1: lease %2 has been allocated
 This debug message indicates that the server successfully granted a lease
-in response to client's REQUEST message. This is a normal behavior and
-indicates successful operation.
+in response to client's DHCPREQUEST message. The lease information will
+be sent to the client in the DHCPACK message. The first argument
+contains the client and the transaction identification information. The
+second argument contains the allocated address.
 
 % DHCP4_LEASE_DATABASE_TIMERS_EXEC_FAIL failed to execute timer-based functions for lease database: %1
 A warning message executed when a server process is unable to execute
@@ -175,26 +265,40 @@ action is a Lease File Cleanup. One of the reasons for the failure is
 a misconfiguration of the lease database, whereby the lease database
 hasn't been selected.
 
-% DHCP4_NAME_GEN_UPDATE_FAIL failed to update the lease after generating name for a client: %1
+% DHCP4_NAME_GEN_UPDATE_FAIL %1: failed to update the lease after generating name %2 for a client: %3
 This message indicates the failure when trying to update the lease and/or
 options in the server's response with the hostname generated by the server
 from the acquired address. The message argument indicates the reason for the
-failure.
-
-% DHCP4_NCR_CREATION_FAILED failed to generate name change requests for DNS: %1
+failure. The first argument includes the client and the transaction
+identification information. The second argument specifies the hostname.
+The third argument contains the error details.
+
+% DHCP4_NCR_CREATE %1: DDNS updates enabled, therefore sending name change requests
+This debug message message is issued when the server is starting to send
+name change requests to the D2 module to update records for the client
+in the DNS. This includes removal of old records and addition of the
+new records as required. Details of the name change requests will be
+logged in additional log entries. The argument includes the client
+and the transaction identification information.
+
+% DHCP4_NCR_CREATION_FAILED %1: failed to generate name change requests for DNS: %2
 This message indicates that server was unable to generate NameChangeRequests
 which should be sent to the kea-dhcp_ddns module to create
 new DNS records for the lease being acquired or to update existing records
-for the renewed lease. The reason for the failure is printed in the logged
-message.
+for the renewed lease. The first argument contains the client and transaction
+identification information. The second argument includes the reason for the
+failure. 
 
 % DHCP4_NOT_RUNNING DHCPv4 server is not running
 A warning message is issued when an attempt is made to shut down the
 DHCPv4 server but it is not running.
 
-% DHCP4_NO_LEASE_INIT_REBOOT no lease for address %1 requested by INIT-REBOOT client (id: %2, hwaddr: %3)
+% DHCP4_NO_LEASE_INIT_REBOOT %1: no lease for address %2 requested by INIT-REBOOT client
 This debug message is issued when the client being in the INIT-REBOOT state
 requested an address but this client is unknown. The server will not respond.
+The first argument includes the client and the transaction id identification
+information. The second argument includes the IP address requested by the
+client.
 
 % DHCP4_NO_SOCKETS_OPEN no interface configured to listen to DHCP traffic
 This warning message is issued when current server configuration specifies
@@ -209,7 +313,7 @@ server is about to open sockets on the specified port.
 A warning message issued when IfaceMgr fails to open and bind a socket. The reason
 for the failure is appended as an argument of the log message.
 
-% DHCP4_PACKET_DROP_0001 %1: failed to parse incoming packet - %2
+% DHCP4_PACKET_DROP_0001 failed to parse packet from %1 to %2, received over interace %3, reason: %4
 The DHCPv4 server has received a packet that it is unable to
 interpret. The reason why the packet is invalid is included in the message.
 
@@ -229,61 +333,92 @@ the message has been received.
 
 % DHCP4_PACKET_DROP_0004 %1, from interface %2: missing msg-type option
 This is a debug message informing that incoming DHCPv4 packet did not
-have mandatory DHCP message type option and thus was dropped.
+have mandatory DHCP message type option and thus was dropped. The
+arguments specify the client and transaction identification information,
+as well as the interface on which the message has been received.
 
 % DHCP4_PACKET_DROP_0005 %1: unrecognized type %2 in option 53
 This debug message indicates that the message type carried in DHCPv4 option
 53 is unrecognized by the server. The valid message types are listed
 on the IANA website: http://www.iana.org/assignments/bootp-dhcp-parameters/bootp-dhcp-parameters.xhtml#message-type-53.
-The message will not be processed by the server.
+The message will not be processed by the server. The arguments specify
+the client and transaction identification information, as well as the
+received message type.
 
 % DHCP4_PACKET_DROP_0006 %1: unsupported DHCPv4 message type %2
 This debug message indicates that the message type carried in DHCPv4 option
 53 is valid but the message will not be processed by the server. This includes
-messages being normally sent by the server to the client, such as Offer, ACK,
-NAK etc.
+messages being normally sent by the server to the client, such as DHCPOFFER,
+DHCPACK, DHCPNAK etc. The first argument specifies the client and transaction
+identification information. The second argument specifies the message type.
 
-% DHCP4_PACKET_DROP_0007 %1: failed to process packet - %2
+% DHCP4_PACKET_DROP_0007 %1: failed to process packet: %2
 This is a general catch-all message indicating that the processing of a
 received packet failed.  The reason is given in the message.  The server
-will not send a response but will instead ignore the packet.
+will not send a response but will instead ignore the packet. The first
+argument contains the client and transaction identification information.
+The second argument includes the details of the error.
 
 % DHCP4_PACKET_NAK_0001 %1: failed to select a subnet for incoming packet, src %2, type %3
 This error message is output when a packet was received from a subnet
 for which the DHCPv4 server has not been configured. The most probable
-cause is a misconfiguration of the server.
+cause is a misconfiguration of the server. The first argument contains
+the client and transaction identification information. The second argument
+contains the source address of the packet. The third argument contains
+the name of the received packet.
 
 % DHCP4_PACKET_NAK_0002 %1: invalid address %2 requested by INIT-REBOOT
 This debug message is issued when the client being in the INIT-REBOOT state
 requested an address which is not assigned to him. The server will respond
-to this client with DHCPNAK.
+to this client with DHCPNAK. The first argument contains the client and
+the transaction identification information. The second arguments holds the
+address requested by the client.
 
 % DHCP4_PACKET_NAK_0003 %1: failed to advertise a lease, client sent ciaddr %2, requested-ip-address %3
 This message indicates that the server has failed to offer a lease to
 the specified client after receiving a DISCOVER message from it. There are
-many possible reasons for such a failure.
+many possible reasons for such a failure. The first argument contains
+the client and the transaction identification information. The second
+argument contains the address in the ciaddr field. The third
+argument contains the IP address in the requested-ip-address option
+(if present).
 
 % DHCP4_PACKET_NAK_0004 %1: failed to grant a lease, client sent ciaddr %2, requested-ip-address %3
 This message indicates that the server failed to grant a lease to the
 specified client after receiving a REQUEST message from it.  There are many
 possible reasons for such a failure. Additional messages will indicate the
-reason.
-
-% DHCP4_PACKET_RECEIVED %1 (type %2) packet received on interface %3
+reason. The first argument contains the client and the transaction
+identification information. The second argument contains the address in
+the ciaddr field. The third argument contains the IP address in the
+requested-ip-address option (if present).
+
+% DHCP4_PACKET_PACK %1: preparing on-wire format of the packet to be sent
+This debug message is issued when the server starts preparing the on-wire
+format of the packet to be sent back to the client. The argument specifies
+the client and the transaction identification information.
+
+% DHCP4_PACKET_PACK_FAIL %1: preparing on-wire-format of the packet to be sent failed %2
+This error message is issued when preparing an on-wire format of the packet
+has failed. The first argument identifies the client and the DHCP transaction.
+The second argument includes the error string.
+
+% DHCP4_PACKET_RECEIVED %1: %2 (type %3) received from %4 to %5 on interface %6
 A debug message noting that the server has received the specified type of
 packet on the specified interface.  Note that a packet marked as UNKNOWN
 may well be a valid DHCP packet, just a type not expected by the server
 (e.g. it will report a received OFFER packet as UNKNOWN).
 
-% DHCP4_PACKET_RECEIVE_FAIL error on attempt to receive packet: %1
-The DHCPv4 server tried to receive a packet but an error
-occurred during this attempt. The reason for the error is included in
-the message.
+% DHCP4_PACKET_SEND %1: sending packet %2 (type %3) from %4:%5 to %6:%7 on interface %8
+This debug message is issued when the server is sending the response to
+the client. The arguments specify the client identification information
+(HW address and client identifier), DHCP message name and type, source
+address and port, destination address and port and the interface name.
 
-% DHCP4_PACKET_SEND_FAIL failed to send DHCPv4 packet: %1
+% DHCP4_PACKET_SEND_FAIL %1: failed to send DHCPv4 packet: %2
 This error is output if the DHCPv4 server fails to send an assembled
-DHCP message to a client. The reason for the error is included in the
-message.
+DHCP message to a client. The first argument includes the client and
+the transaction identification information. The second argument includes
+the reason for failure.
 
 % DHCP4_PARSER_COMMIT_EXCEPTION parser failed to commit changes
 On receipt of message containing details to a change of the DHCPv4
@@ -317,8 +452,10 @@ of the named configuration element, or the creation succeeded but the
 parsing actions and committal of changes failed.  The reason for the
 failure is given in the message.
 
-% DHCP4_QUERY_DATA received packet type %1, data is <%2>
-A debug message listing the data received from the client.
+% DHCP4_QUERY_DATA %1, packet details: %2
+A debug message printing the details of the received packet. The first
+argument includes the client and the transaction identification
+information.
 
 % DHCP4_QUEUE_NCR name change request to %1 DNS entry queued: %2
 A debug message which is logged when the NameChangeRequest to add or remove
@@ -326,49 +463,92 @@ a DNS entries for a particular lease has been queued. The first parameter of
 this log message indicates whether the DNS entry is to be added or removed.
 The second parameter carries the details of the NameChangeRequest.
 
-% DHCP4_RELEASE address %1 belonging to client-id %2, hwaddr %3 was released properly.
+% DHCP4_RELEASE %1: address %2 was released properly.
 This debug message indicates that an address was released properly. It
-is a normal operation during client shutdown.
+is a normal operation during client shutdown. The first argument includes
+the client and transaction identification information. The second argument
+includes the released IP address.
 
-% DHCP4_RELEASE_EXCEPTION exception %1 while trying to release address %2
+% DHCP4_RELEASE_EXCEPTION %1: while trying to release address %2 an exception occured: %3
 This message is output when an error was encountered during an attempt
-to process a RELEASE message. The error will not affect the client,
-which does not expect any response from the server for RELEASE
+to process a DHCPRELEASE message. The error will not affect the client,
+which does not expect any response from the server for DHCPRELEASE
 messages. Depending on the nature of problem, it may affect future
-server operation.
+server operation. The first argument includes the client and the
+transaction identification information. The second argument
+includes the IP address which release was attempted. The last
+argument includes the detailed error description.
 
-% DHCP4_RELEASE_FAIL failed to remove lease for address %1 for duid %2, hwaddr %3
+% DHCP4_RELEASE_FAIL %1: failed to remove lease for address %2
 This error message indicates that the software failed to remove a
 lease from the lease database. It is probably due to an error during a
 database operation: resolution will most likely require administrator
 intervention (e.g. check if DHCP process has sufficient privileges to
 update the database). It may also be triggered if a lease was manually
-removed from the database during RELEASE message processing.
-
-% DHCP4_RELEASE_FAIL_NO_LEASE client (client-id %1, hwaddr %2) tried to release address, %3, but there is no such lease.
-This warning message is printed when client attempts to release a lease,
-but no such lease is known to the server.
-
-% DHCP4_RELEASE_FAIL_WRONG_CLIENT_ID client (client-id %2) tried to release address %1, but it belongs to client (client-id %3)
+removed from the database during RELEASE message processing. The
+first argument includes the client and the transaction identification
+information. The second argument holds the IP address which release
+was attempted.
+
+% DHCP4_RELEASE_FAIL_NO_LEASE %1: client is trying to release non-existing lease %2
+This debug message is printed when client attempts to release a lease,
+but no such lease is known to the server. The first argument contains
+the client and transaction identification information. The second
+argument contains the address which the client is trying to release.
+
+% DHCP4_RELEASE_FAIL_WRONG_CLIENT_ID %1: client tried to release address %2, but this address is leased to different client using client id %3
 This warning message indicates that client tried to release an address
 that belongs to a different client. This should not happen in normal
 circumstances and may indicate a misconfiguration of the client.  However,
 since the client releasing the address will stop using it anyway, there
 is a good chance that the situation will correct itself.
 
-% DHCP4_RELEASE_FAIL_WRONG_HWADDR client (client-id %2) tried to release address %1, but sent from a wrong hardware address (%3)
+% DHCP4_RELEASE_FAIL_WRONG_HWADDR %1: client tried to release address %2, but this address is leased to different client using HW address %3
 This warning message indicates that client tried to release an address
 that does belong to it, but the lease information was associated with
 a different hardware address. One possible reason for using different
 hardware address is that a cloned virtual machine was not updated and
-both clones use the same client-id.
-
-% DHCP4_REQUEST_CLASS_PROCESSING_FAILED client class specific processing failed for DHCPREQUEST
+both clones use the same client-id. The first argument includes the
+client and the transaction identification information. The second
+argument includes the address which release was attempted. The
+third argumnet includes the HW address of the lease owner.
+
+% DHCP4_RESPONSE_FQDN_DATA %1: including FQDN option in the server's response: %2
+This debug message is issued when the server is adding the Client FQDN
+option in its response to the client. The first argument includes the
+client and transaction identification information. The second argument
+includes the details of the FQDN option being included. Note that the
+name carried in the FQDN option may be modified by the server when
+the lease is acquired for the client.
+
+% DHCP4_RESPONSE_HOSTNAME_DATA %1: including Hostname option in the server's response: %2
+This debug message is issued when the server is adding the Hostname
+option in its response to the client. The first argument includes the
+client and transaction identification information. The second argument
+includes the details of the FQDN option being included. Note that the
+name carried in the Hostname option may be modified by the server when
+the lease is acquired for the client.
+
+% DHCP4_RESPONSE_HOSTNAME_GENERATE %1: server has generated hostname %2 for the client
+This debug message includes the auto-generated hostname which will be used
+for the client which message is processed. Hostnames may need to be generated
+when required by the server's configuration or when the client hasn't
+supplied its hostname. The first argument includes the client and the
+transaction identification information. The second argument holds the
+generated hostname.
+
+% DHCP4_REQUEST_CLASS_PROCESSING_FAILED %1: client class specific processing failed for DHCPREQUEST
 This debug message means that the server processing that is unique for each
 client class has reported a failure. The response packet will not be sent.
+The argument contains the client and transaction identification
+information.
 
-% DHCP4_RESPONSE_DATA responding with packet type %1, data is <%2>
-A debug message listing the data returned to the client.
+% DHCP4_RESPONSE_DATA %1: responding with packet %2 (type %3), packet details: %4
+A debug message including the detailed data about the packet being sent
+to the client. The first argument contains the client and the transaction
+identification information. The second and third argument contains the
+packet name and type respectively. The fourth argument contains detailed
+packet information.
 
 % DHCP4_SERVER_FAILED server failed: %1
 The DHCPv4 server has encountered a fatal error and is terminating.
@@ -403,7 +583,24 @@ This is a debug message issued during the DHCPv4 server startup.
 It lists some information about the parameters with which the server
 is running.
 
-% DHCP4_SUBNET_SELECTED the %1 subnet was selected for client assignment
+% DHCP4_SUBNET_DATA %1: the selected subnet details: %2
+This debug message includes the details of the subnet selected fot
+the client. The first argument includes the client and the
+transaction identification information. The second arguments
+includes the subnet details.
+
+% DHCP4_SUBNET_SELECTED %1: the subnet with ID %2 was selected for client assignments
 This is a debug message noting the selection of a subnet to be used for
-address and option assignment.  Subnet selection is one of the early
-steps in the processing of incoming client message.
+address and option assignment. Subnet selection is one of the early
+steps in the processing of incoming client message. The first
+argument includes the client and the transaction identification
+information. The second argument holds the selected subnet id.
+
+% DHCP4_SUBNET_SELECTION_FAILED %1: failed to select subnet for the client
+This debug message indicates that the server failed to select the
+subnet for the client which has sent a message to the server.
+The server will not be able to offer any lease to the client and
+will drop its message if the received message was DHCPDISCOVER,
+and will send DHCPNAK if the received message was DHCPREQUEST.
+The argument includes the client and the transaction identification
+information.

+ 198 - 135
src/bin/dhcp4/dhcp4_srv.cc

@@ -38,6 +38,7 @@
 #include <dhcpsrv/utils.h>
 #include <dhcpsrv/utils.h>
 #include <hooks/callout_handle.h>
+#include <hooks/hooks_log.h>
 #include <hooks/hooks_manager.h>
 #include <util/strutil.h>
 
@@ -278,8 +279,9 @@ Dhcpv4Srv::selectSubnet(const Pkt4Ptr& query) const {
         // will be selected. Packet processing will continue, but it will
         // be severely limited (i.e. only global options will be assigned)
         if (callout_handle->getSkip()) {
-            LOG_DEBUG(dhcp4_logger, DBG_DHCP4_HOOKS,
-                      DHCP4_HOOK_SUBNET4_SELECT_SKIP);
+            LOG_DEBUG(hooks_logger, DBG_DHCP4_HOOKS,
+                      DHCP4_HOOK_SUBNET4_SELECT_SKIP)
+                .arg(query->getLabel());
             return (Subnet4Ptr());
         }
 
@@ -287,6 +289,23 @@ Dhcpv4Srv::selectSubnet(const Pkt4Ptr& query) const {
         callout_handle->getArgument("subnet4", subnet);
     }
 
+    if (subnet) {
+        // Log at higher debug level that subnet has been found.
+        LOG_DEBUG(packet_logger, DBG_DHCP4_BASIC_DATA, DHCP4_SUBNET_SELECTED)
+            .arg(query->getLabel())
+            .arg(subnet->getID());
+        // Log detailed information about the selected subnet at the
+        // lower debug level.
+        LOG_DEBUG(packet_logger, DBG_DHCP4_DETAIL_DATA, DHCP4_SUBNET_DATA)
+            .arg(query->getLabel())
+            .arg(subnet->toText());
+
+    } else {
+        LOG_DEBUG(packet_logger, DBG_DHCP4_DETAIL,
+                  DHCP4_SUBNET_SELECTION_FAILED)
+            .arg(query->getLabel());
+    }
+
     return (subnet);
 }
 
@@ -318,17 +337,39 @@ Dhcpv4Srv::run() {
             if (timeout == 0) {
                 timeout = 1000;
             }
+            LOG_DEBUG(packet_logger, DBG_DHCP4_DETAIL, DHCP4_BUFFER_WAIT).arg(timeout);
             query = receivePacket(timeout);
 
+            // Log if packet has arrived. We can't log the detailed information
+            // about the DHCP message because it hasn't been unpacked/parsed
+            // yet, and it can't be parsed at this point because hooks will
+            // have to process it first. The only information available at this
+            // point are: the interface, source address and destination addresses
+            // and ports.
+            if (query) {
+                LOG_DEBUG(packet_logger, DBG_DHCP4_BASIC, DHCP4_BUFFER_RECEIVED)
+                    .arg(query->getRemoteAddr().toText())
+                    .arg(query->getRemotePort())
+                    .arg(query->getLocalAddr().toText())
+                    .arg(query->getLocalPort())
+                    .arg(query->getIface());
+
+            } else {
+                LOG_DEBUG(packet_logger, DBG_DHCP4_DETAIL, DHCP4_BUFFER_WAIT_TIMEOUT)
+                    .arg(timeout);
+            }
+
         } catch (const SignalInterruptOnSelect) {
             // Packet reception interrupted because a signal has been received.
             // This is not an error because we might have received a SIGTERM,
             // SIGINT or SIGHUP which are handled by the server. For signals
             // that are not handled by the server we rely on the default
             // behavior of the system, but there is nothing we should log here.
+            LOG_DEBUG(packet_logger, DBG_DHCP4_DETAIL, DHCP4_BUFFER_WAIT_SIGNAL)
+                .arg(signal_set_->getNext());
         } catch (const std::exception& e) {
             // Log all other errors.
-            LOG_ERROR(dhcp4_logger, DHCP4_PACKET_RECEIVE_FAIL).arg(e.what());
+            LOG_ERROR(packet_logger, DHCP4_BUFFER_RECEIVE_FAIL).arg(e.what());
         }
 
         // Handle next signal received by the process. It must be called after
@@ -353,7 +394,8 @@ Dhcpv4Srv::run() {
         }
 
         // Timeout may be reached or signal received, which breaks select()
-        // with no reception occurred
+        // with no reception occurred. No need to log anything here because
+        // we have logged right after the call to receivePacket().
         if (!query) {
             continue;
         }
@@ -389,7 +431,10 @@ Dhcpv4Srv::run() {
             // stage means that callouts did the parsing already, so server
             // should skip parsing.
             if (callout_handle->getSkip()) {
-                LOG_DEBUG(dhcp4_logger, DBG_DHCP4_HOOKS, DHCP4_HOOK_BUFFER_RCVD_SKIP);
+                LOG_DEBUG(hooks_logger, DBG_DHCP4_DETAIL, DHCP4_HOOK_BUFFER_RCVD_SKIP)
+                    .arg(query->getRemoteAddr().toText())
+                    .arg(query->getLocalAddr().toText())
+                    .arg(query->getIface());
                 skip_unpack = true;
             }
 
@@ -400,12 +445,18 @@ Dhcpv4Srv::run() {
         // indicated they did it
         if (!skip_unpack) {
             try {
+                LOG_DEBUG(options_logger, DBG_DHCP4_DETAIL, DHCP4_BUFFER_UNPACK)
+                    .arg(query->getRemoteAddr().toText())
+                    .arg(query->getLocalAddr().toText())
+                    .arg(query->getIface());
                 query->unpack();
             } catch (const std::exception& e) {
                 // Failed to parse the packet.
                 LOG_DEBUG(bad_packet_logger, DBG_DHCP4_DETAIL,
                           DHCP4_PACKET_DROP_0001)
-                    .arg(query->getLabel())
+                    .arg(query->getRemoteAddr().toText())
+                    .arg(query->getLocalAddr().toText())
+                    .arg(query->getIface())
                     .arg(e.what());
                 continue;
             }
@@ -425,12 +476,15 @@ Dhcpv4Srv::run() {
         // We have sanity checked (in accept() that the Message Type option
         // exists, so we can safely get it here.
         int type = query->getType();
-        LOG_DEBUG(dhcp4_logger, DBG_DHCP4_DETAIL, DHCP4_PACKET_RECEIVED)
-            .arg(serverReceivedPacketName(type))
+        LOG_DEBUG(packet_logger, DBG_DHCP4_BASIC_DATA, DHCP4_PACKET_RECEIVED)
+            .arg(query->getLabel())
+            .arg(query->getName())
             .arg(type)
+            .arg(query->getRemoteAddr())
+            .arg(query->getLocalAddr())
             .arg(query->getIface());
-        LOG_DEBUG(dhcp4_logger, DBG_DHCP4_DETAIL_DATA, DHCP4_QUERY_DATA)
-            .arg(type)
+        LOG_DEBUG(packet_logger, DBG_DHCP4_DETAIL_DATA, DHCP4_QUERY_DATA)
+            .arg(query->getLabel())
             .arg(query->toText());
 
         // Let's execute all callouts registered for pkt4_receive
@@ -451,7 +505,8 @@ Dhcpv4Srv::run() {
             // processing step would to process the packet, so skip at this
             // stage means drop.
             if (callout_handle->getSkip()) {
-                LOG_DEBUG(dhcp4_logger, DBG_DHCP4_HOOKS, DHCP4_HOOK_PACKET_RCVD_SKIP);
+                LOG_DEBUG(hooks_logger, DBG_DHCP4_HOOKS, DHCP4_HOOK_PACKET_RCVD_SKIP)
+                    .arg(query->getLabel());
                 continue;
             }
 
@@ -497,17 +552,10 @@ Dhcpv4Srv::run() {
             // (The problem is logged as a debug message because debug is
             // disabled by default - it prevents a DDOS attack based on the
             // sending of problem packets.)
-            if (dhcp4_logger.isDebugEnabled(DBG_DHCP4_BASIC)) {
-                std::string source = "unknown";
-                HWAddrPtr hwptr = query->getHWAddr();
-                if (hwptr) {
-                    source = hwptr->toText();
-                }
-                LOG_DEBUG(bad_packet_logger, DBG_DHCP4_BASIC,
-                          DHCP4_PACKET_DROP_0007)
-                    .arg(query->getLabel())
-                    .arg(e.what());
-            }
+            LOG_DEBUG(bad_packet_logger, DBG_DHCP4_BASIC,
+                      DHCP4_PACKET_DROP_0007)
+                .arg(query->getLabel())
+                .arg(e.what());
         }
 
         if (!rsp) {
@@ -539,16 +587,20 @@ Dhcpv4Srv::run() {
             // processing step would to send the packet, so skip at this
             // stage means "drop response".
             if (callout_handle->getSkip()) {
-                LOG_DEBUG(dhcp4_logger, DBG_DHCP4_HOOKS, DHCP4_HOOK_PACKET_SEND_SKIP);
+                LOG_DEBUG(hooks_logger, DBG_DHCP4_HOOKS, DHCP4_HOOK_PACKET_SEND_SKIP)
+                    .arg(query->getLabel());
                 skip_pack = true;
             }
         }
 
         if (!skip_pack) {
             try {
+                LOG_DEBUG(options_logger, DBG_DHCP4_DETAIL, DHCP4_PACKET_PACK)
+                    .arg(rsp->getLabel());
                 rsp->pack();
             } catch (const std::exception& e) {
-                LOG_ERROR(dhcp4_logger, DHCP4_PACKET_SEND_FAIL)
+                LOG_ERROR(options_logger, DHCP4_PACKET_PACK_FAIL)
+                    .arg(rsp->getLabel())
                     .arg(e.what());
             }
         }
@@ -575,21 +627,35 @@ Dhcpv4Srv::run() {
                 // processing step would to parse the packet, so skip at this
                 // stage means drop.
                 if (callout_handle->getSkip()) {
-                    LOG_DEBUG(dhcp4_logger, DBG_DHCP4_HOOKS,
-                              DHCP4_HOOK_BUFFER_SEND_SKIP);
+                    LOG_DEBUG(hooks_logger, DBG_DHCP4_HOOKS,
+                              DHCP4_HOOK_BUFFER_SEND_SKIP)
+                        .arg(rsp->getLabel());
                     continue;
                 }
 
                 callout_handle->getArgument("response4", rsp);
             }
 
-            LOG_DEBUG(dhcp4_logger, DBG_DHCP4_DETAIL_DATA,
+            LOG_DEBUG(packet_logger, DBG_DHCP4_BASIC, DHCP4_PACKET_SEND)
+                .arg(rsp->getLabel())
+                .arg(rsp->getName())
+                .arg(static_cast<int>(rsp->getType()))
+                .arg(rsp->getLocalAddr())
+                .arg(rsp->getLocalPort())
+                .arg(rsp->getRemoteAddr())
+                .arg(rsp->getRemotePort())
+                .arg(rsp->getIface());
+
+            LOG_DEBUG(packet_logger, DBG_DHCP4_DETAIL_DATA,
                       DHCP4_RESPONSE_DATA)
-                .arg(static_cast<int>(rsp->getType())).arg(rsp->toText());
-
+                .arg(rsp->getLabel())
+                .arg(rsp->getName())
+                .arg(static_cast<int>(rsp->getType()))
+                .arg(rsp->toText());
             sendPacket(rsp);
         } catch (const std::exception& e) {
-            LOG_ERROR(dhcp4_logger, DHCP4_PACKET_SEND_FAIL)
+            LOG_ERROR(packet_logger, DHCP4_PACKET_SEND_FAIL)
+                .arg(rsp->getLabel())
                 .arg(e.what());
         }
     }
@@ -818,16 +884,20 @@ Dhcpv4Srv::processClientName(Dhcpv4Exchange& ex) {
         Option4ClientFqdnPtr fqdn = boost::dynamic_pointer_cast<Option4ClientFqdn>
             (ex.getQuery()->getOption(DHO_FQDN));
         if (fqdn) {
+            LOG_DEBUG(ddns_logger, DBG_DHCP4_DETAIL, DHCP4_CLIENT_FQDN_PROCESS)
+                .arg(ex.getQuery()->getLabel());
             processClientFqdnOption(ex);
 
         } else {
             OptionStringPtr hostname = boost::dynamic_pointer_cast<OptionString>
                 (ex.getQuery()->getOption(DHO_HOST_NAME));
             if (hostname) {
+                LOG_DEBUG(ddns_logger, DBG_DHCP4_DETAIL, DHCP4_CLIENT_HOSTNAME_PROCESS)
+                    .arg(ex.getQuery()->getLabel());
                 processHostnameOption(ex);
             }
         }
-    } catch (const Exception& ex) {
+    } catch (const Exception& e) {
         // In some rare cases it is possible that the client's name processing
         // fails. For example, the Hostname option may be malformed, or there
         // may be an error in the server's logic which would cause multiple
@@ -836,8 +906,9 @@ Dhcpv4Srv::processClientName(Dhcpv4Exchange& ex) {
         // from the log. We don't want to throw an exception here because,
         // it will impact the processing of the whole packet. We rather want
         // the processing to continue, even if the client's name is wrong.
-        LOG_DEBUG(dhcp4_logger, DBG_DHCP4_DETAIL_DATA, DHCP4_CLIENT_NAME_PROC_FAIL)
-            .arg(ex.what());
+        LOG_DEBUG(ddns_logger, DBG_DHCP4_DETAIL_DATA, DHCP4_CLIENT_NAME_PROC_FAIL)
+            .arg(ex.getQuery()->getLabel())
+            .arg(e.what());
     }
 }
 
@@ -847,6 +918,10 @@ Dhcpv4Srv::processClientFqdnOption(Dhcpv4Exchange& ex) {
     Option4ClientFqdnPtr fqdn = boost::dynamic_pointer_cast<
         Option4ClientFqdn>(ex.getQuery()->getOption(DHO_FQDN));
 
+    LOG_DEBUG(ddns_logger, DBG_DHCP4_DETAIL_DATA, DHCP4_CLIENT_FQDN_DATA)
+        .arg(ex.getQuery()->getLabel())
+        .arg(fqdn->toText());
+
     // Create the DHCPv4 Client FQDN Option to be included in the server's
     // response to a client.
     Option4ClientFqdnPtr fqdn_resp(new Option4ClientFqdn(*fqdn));
@@ -883,6 +958,9 @@ Dhcpv4Srv::processClientFqdnOption(Dhcpv4Exchange& ex) {
     // If we don't store the option in the response message, we will have to
     // propagate it in the different way to the functions which acquire the
     // lease. This would require modifications to the API of this class.
+    LOG_DEBUG(ddns_logger, DBG_DHCP4_DETAIL_DATA, DHCP4_RESPONSE_FQDN_DATA)
+        .arg(ex.getQuery()->getLabel())
+        .arg(fqdn_resp->toText());
     ex.getResponse()->addOption(fqdn_resp);
 }
 
@@ -892,6 +970,10 @@ Dhcpv4Srv::processHostnameOption(Dhcpv4Exchange& ex) {
     OptionStringPtr opt_hostname = boost::dynamic_pointer_cast<OptionString>
         (ex.getQuery()->getOption(DHO_HOST_NAME));
 
+    LOG_DEBUG(ddns_logger, DBG_DHCP4_DETAIL_DATA, DHCP4_CLIENT_HOSTNAME_DATA)
+        .arg(ex.getQuery()->getLabel())
+        .arg(opt_hostname->getValue());
+
     // Fetch D2 configuration.
     D2ClientMgr& d2_mgr = CfgMgr::instance().getD2ClientMgr();
 
@@ -907,7 +989,8 @@ Dhcpv4Srv::processHostnameOption(Dhcpv4Exchange& ex) {
     /// @todo It would be more liberal to accept this and let it fall into
     /// the case  of replace or less than two below.
     if (label_count == 0) {
-        LOG_DEBUG(dhcp4_logger, DBG_DHCP4_DETAIL_DATA, DHCP4_EMPTY_HOSTNAME);
+        LOG_DEBUG(ddns_logger, DBG_DHCP4_DETAIL_DATA, DHCP4_EMPTY_HOSTNAME)
+            .arg(ex.getQuery()->getLabel());
         return;
     }
     // Copy construct the hostname provided by the client. It is entirely
@@ -950,7 +1033,10 @@ Dhcpv4Srv::processHostnameOption(Dhcpv4Exchange& ex) {
         // clients do not handle the hostnames with the trailing dot.
         opt_hostname_resp->setValue(d2_mgr.qualifyName(hostname, false));
     }
-
+    
+    LOG_DEBUG(ddns_logger, DBG_DHCP4_DETAIL_DATA, DHCP4_RESPONSE_HOSTNAME_DATA)
+        .arg(ex.getQuery()->getLabel())
+        .arg(opt_hostname_resp->getValue());
     ex.getResponse()->addOption(opt_hostname_resp);
 }
 
@@ -1016,7 +1102,7 @@ queueNameChangeRequest(const isc::dhcp_ddns::NameChangeType chg_type,
     try {
         dhcid  = computeDhcid(lease);
     } catch (const DhcidComputeError& ex) {
-        LOG_ERROR(dhcp4_logger, DHCP4_DHCID_COMPUTE_ERROR)
+        LOG_ERROR(ddns_logger, DHCP4_DHCID_COMPUTE_ERROR)
             .arg(lease->toText())
             .arg(ex.what());
         return;
@@ -1032,7 +1118,7 @@ queueNameChangeRequest(const isc::dhcp_ddns::NameChangeType chg_type,
                                                     lease->valid_lft_),
                                                    lease->valid_lft_));
 
-    LOG_DEBUG(dhcp4_logger, DBG_DHCP4_DETAIL_DATA, DHCP4_QUEUE_NCR)
+    LOG_DEBUG(ddns_logger, DBG_DHCP4_DETAIL_DATA, DHCP4_QUEUE_NCR)
         .arg(chg_type == CHG_ADD ? "add" : "remove")
         .arg(ncr->toText());
 
@@ -1054,18 +1140,13 @@ Dhcpv4Srv::assignLease(Dhcpv4Exchange& ex) {
     if (!subnet) {
         // This particular client is out of luck today. We do not have
         // information about the subnet he is connected to. This likely means
-        // misconfiguration of the server (or some relays). We will continue to
-        // process this message, but our response will be almost useless: no
-        // addresses or prefixes, no subnet specific configuration etc. The only
-        // thing this client can get is some global information (like DNS
-        // servers).
-
-        // perhaps this should be logged on some higher level? This is most
-        // likely configuration bug.
+        // misconfiguration of the server (or some relays).
+
+        // Perhaps this should be logged on some higher level?
         LOG_ERROR(bad_packet_logger, DHCP4_PACKET_NAK_0001)
             .arg(query->getLabel())
             .arg(query->getRemoteAddr().toText())
-            .arg(serverReceivedPacketName(query->getType()));
+            .arg(query->getName());
         resp->setType(DHCPNAK);
         resp->setYiaddr(IOAddress::IPV4_ZERO_ADDRESS());
         return;
@@ -1078,9 +1159,6 @@ Dhcpv4Srv::assignLease(Dhcpv4Exchange& ex) {
     /// @todo: move subnet selection to a common code
     resp->setSiaddr(subnet->getSiaddr());
 
-    LOG_DEBUG(dhcp4_logger, DBG_DHCP4_DETAIL_DATA, DHCP4_SUBNET_SELECTED)
-        .arg(subnet->toText());
-
     // Get client-id. It is not mandatory in DHCPv4.
     ClientIdPtr client_id = ex.getContext()->clientid_;
 
@@ -1093,7 +1171,7 @@ Dhcpv4Srv::assignLease(Dhcpv4Exchange& ex) {
     // ciaddr.
     OptionCustomPtr opt_requested_address = boost::dynamic_pointer_cast<
         OptionCustom>(query->getOption(DHO_DHCP_REQUESTED_ADDRESS));
-    IOAddress hint(0);
+    IOAddress hint(IOAddress::IPV4_ZERO_ADDRESS());
     if (opt_requested_address) {
         hint = opt_requested_address->readAddress();
 
@@ -1117,6 +1195,11 @@ Dhcpv4Srv::assignLease(Dhcpv4Exchange& ex) {
     // determine whether the client's notion of the address is correct
     // and whether the client is known, i.e., has a lease.
     if (!fake_allocation && !opt_serverid && opt_requested_address) {
+
+        LOG_DEBUG(lease_logger, DBG_DHCP4_DETAIL, DHCP4_INIT_REBOOT)
+            .arg(query->getLabel())
+            .arg(hint.toText());
+
         Lease4Ptr lease;
         if (hwaddr) {
             lease = LeaseMgrFactory::instance().getLease4(*hwaddr,
@@ -1139,11 +1222,10 @@ Dhcpv4Srv::assignLease(Dhcpv4Exchange& ex) {
         }
         // Now check the second error case: unknown client.
         if (!lease) {
-            LOG_DEBUG(dhcp4_logger, DBG_DHCP4_DETAIL,
+            LOG_DEBUG(bad_packet_logger, DBG_DHCP4_DETAIL,
                       DHCP4_NO_LEASE_INIT_REBOOT)
-                .arg(hint.toText())
-                .arg(client_id ? client_id->toText():"(no client-id)")
-                .arg(hwaddr ? hwaddr->toText():"(no hwaddr info)");
+                .arg(query->getLabel())
+                .arg(hint.toText());
 
             ex.deleteResponse();
             return;
@@ -1167,6 +1249,7 @@ Dhcpv4Srv::assignLease(Dhcpv4Exchange& ex) {
     } else {
         opt_hostname = boost::dynamic_pointer_cast<OptionString>
             (resp->getOption(DHO_HOST_NAME));
+
         if (opt_hostname) {
             hostname = opt_hostname->getValue();
             // DHO_HOST_NAME is string option which cannot be blank,
@@ -1196,11 +1279,10 @@ Dhcpv4Srv::assignLease(Dhcpv4Exchange& ex) {
     if (lease) {
         // We have a lease! Let's set it in the packet and send it back to
         // the client.
-        LOG_DEBUG(dhcp4_logger, DBG_DHCP4_DETAIL, fake_allocation?
-                  DHCP4_LEASE_ADVERT:DHCP4_LEASE_ALLOC)
-            .arg(lease->addr_.toText())
-            .arg(client_id?client_id->toText():"(no client-id)")
-            .arg(hwaddr?hwaddr->toText():"(no hwaddr info)");
+        LOG_DEBUG(lease_logger, DBG_DHCP4_BASIC_DATA, fake_allocation?
+                  DHCP4_LEASE_ADVERT : DHCP4_LEASE_ALLOC)
+            .arg(query->getLabel())
+            .arg(lease->addr_.toText());
 
         resp->setYiaddr(lease->addr_);
 
@@ -1221,6 +1303,7 @@ Dhcpv4Srv::assignLease(Dhcpv4Exchange& ex) {
         // generating the entire hostname for the client. The example of the
         // client's name, generated from the IP address is: host-192-0-2-3.
         if ((fqdn || opt_hostname) && lease->hostname_.empty()) {
+
             // Note that if we have received the hostname option, rather than
             // Client FQDN the trailing dot is not appended to the generated
             // hostname because some clients don't handle the trailing dot in
@@ -1229,6 +1312,10 @@ Dhcpv4Srv::assignLease(Dhcpv4Exchange& ex) {
             lease->hostname_ = CfgMgr::instance().getD2ClientMgr()
                 .generateFqdn(lease->addr_, static_cast<bool>(fqdn));
 
+            LOG_DEBUG(ddns_logger, DBG_DHCP4_DETAIL, DHCP4_RESPONSE_HOSTNAME_GENERATE)
+                .arg(query->getLabel())
+                .arg(lease->hostname_);
+
             // The operations below are rather safe, but we want to catch
             // any potential exceptions (e.g. invalid lease database backend
             // implementation) and log an error.
@@ -1250,7 +1337,9 @@ Dhcpv4Srv::assignLease(Dhcpv4Exchange& ex) {
                 }
 
             } catch (const Exception& ex) {
-                LOG_ERROR(dhcp4_logger, DHCP4_NAME_GEN_UPDATE_FAIL)
+                LOG_ERROR(ddns_logger, DHCP4_NAME_GEN_UPDATE_FAIL)
+                    .arg(query->getLabel())
+                    .arg(lease->hostname_)
                     .arg(ex.what());
             }
         }
@@ -1283,19 +1372,21 @@ Dhcpv4Srv::assignLease(Dhcpv4Exchange& ex) {
         // real allocation.
         if (!fake_allocation && CfgMgr::instance().ddnsEnabled()) {
             try {
+                LOG_DEBUG(ddns_logger, DBG_DHCP4_DETAIL, DHCP4_NCR_CREATE)
+                    .arg(query->getLabel());
                 createNameChangeRequests(lease, ctx->old_lease_);
+
             } catch (const Exception& ex) {
-                LOG_ERROR(dhcp4_logger, DHCP4_NCR_CREATION_FAILED)
+                LOG_ERROR(ddns_logger, DHCP4_NCR_CREATION_FAILED)
+                    .arg(query->getLabel())
                     .arg(ex.what());
             }
         }
 
     } else {
         // Allocation engine did not allocate a lease. The engine logged
-        // cause of that failure. The only thing left is to insert
-        // status code to pass the sad news to the client.
-
-        LOG_DEBUG(dhcp4_logger, DBG_DHCP4_DETAIL, fake_allocation ?
+        // cause of that failure.
+        LOG_DEBUG(bad_packet_logger, DBG_DHCP4_DETAIL, fake_allocation ?
                   DHCP4_PACKET_NAK_0003 : DHCP4_PACKET_NAK_0004)
             .arg(query->getLabel())
             .arg(query->getCiaddr().toText())
@@ -1508,7 +1599,8 @@ Dhcpv4Srv::processDiscover(Pkt4Ptr& discover) {
     /// doing class specific processing.
     if (!classSpecificProcessing(ex)) {
         /// @todo add more verbosity here
-        LOG_DEBUG(dhcp4_logger, DBG_DHCP4_BASIC, DHCP4_DISCOVER_CLASS_PROCESSING_FAILED);
+        LOG_DEBUG(options_logger, DBG_DHCP4_DETAIL, DHCP4_DISCOVER_CLASS_PROCESSING_FAILED)
+            .arg(discover->getLabel());
     }
 
     return (ex.getResponse());
@@ -1557,7 +1649,8 @@ Dhcpv4Srv::processRequest(Pkt4Ptr& request) {
     /// doing class specific processing.
     if (!classSpecificProcessing(ex)) {
         /// @todo add more verbosity here
-        LOG_DEBUG(dhcp4_logger, DBG_DHCP4_BASIC, DHCP4_REQUEST_CLASS_PROCESSING_FAILED);
+        LOG_DEBUG(options_logger, DBG_DHCP4_DETAIL, DHCP4_REQUEST_CLASS_PROCESSING_FAILED)
+            .arg(ex.getQuery()->getLabel());
     }
 
     return (ex.getResponse());
@@ -1581,34 +1674,30 @@ Dhcpv4Srv::processRelease(Pkt4Ptr& release) {
 
         if (!lease) {
             // No such lease - bogus release
-            LOG_DEBUG(dhcp4_logger, DBG_DHCP4_DETAIL,
-                      DHCP4_RELEASE_FAIL_NO_LEASE)
-                      .arg(client_id ? client_id->toText() : "(no client-id)")
-                      .arg(release->getHWAddr() ?
-                           release->getHWAddr()->toText() : "(no hwaddr info)")
-                      .arg(release->getCiaddr().toText());
+            LOG_DEBUG(lease_logger, DBG_DHCP4_DETAIL, DHCP4_RELEASE_FAIL_NO_LEASE)
+                .arg(release->getLabel())
+                .arg(release->getCiaddr().toText());
             return;
         }
 
         // Does the hardware address match? We don't want one client releasing
-        // second client's leases. Note that we're comparing the hardware
+        // another client's leases. Note that we're comparing the hardware
         // addresses only, not hardware types or sources of the hardware
         // addresses. Thus we don't use HWAddr::equals().
         if (lease->hwaddr_->hwaddr_ != release->getHWAddr()->hwaddr_) {
-            /// @todo: Print hwaddr from lease as part of ticket #2589
-            LOG_DEBUG(dhcp4_logger, DBG_DHCP4_DETAIL, DHCP4_RELEASE_FAIL_WRONG_HWADDR)
+            LOG_DEBUG(lease_logger, DBG_DHCP4_DETAIL, DHCP4_RELEASE_FAIL_WRONG_HWADDR)
+                .arg(release->getLabel())
                 .arg(release->getCiaddr().toText())
-                .arg(client_id ? client_id->toText() : "(no client-id)")
-                .arg(release->getHWAddr()->toText());
+                .arg(lease->hwaddr_->toText(false));
             return;
         }
 
         // Does the lease have client-id info? If it has, then check it with what
         // the client sent us.
         if (lease->client_id_ && client_id && *lease->client_id_ != *client_id) {
-            LOG_DEBUG(dhcp4_logger, DBG_DHCP4_DETAIL, DHCP4_RELEASE_FAIL_WRONG_CLIENT_ID)
+            LOG_DEBUG(lease_logger, DBG_DHCP4_DETAIL, DHCP4_RELEASE_FAIL_WRONG_CLIENT_ID)
+                .arg(release->getLabel())
                 .arg(release->getCiaddr().toText())
-                .arg(client_id->toText())
                 .arg(lease->client_id_->toText());
             return;
         }
@@ -1637,41 +1726,40 @@ Dhcpv4Srv::processRelease(Pkt4Ptr& release) {
             // stage means "drop response".
             if (callout_handle->getSkip()) {
                 skip = true;
-                LOG_DEBUG(dhcp4_logger, DBG_DHCP4_HOOKS,
-                          DHCP4_HOOK_LEASE4_RELEASE_SKIP);
+                LOG_DEBUG(hooks_logger, DBG_DHCP4_HOOKS,
+                          DHCP4_HOOK_LEASE4_RELEASE_SKIP)
+                    .arg(release->getLabel());
             }
         }
 
-        // Ok, hw and client-id match - let's release the lease.
+        // Callout didn't indicate to skip the release process. Let's release
+        // the lease.
         if (!skip) {
             bool success = LeaseMgrFactory::instance().deleteLease(lease->addr_);
 
             if (success) {
                 // Release successful
-                LOG_DEBUG(dhcp4_logger, DBG_DHCP4_DETAIL, DHCP4_RELEASE)
-                    .arg(lease->addr_.toText())
-                    .arg(client_id ? client_id->toText() : "(no client-id)")
-                    .arg(release->getHWAddr()->toText());
+                LOG_DEBUG(lease_logger, DBG_DHCP4_DETAIL, DHCP4_RELEASE)
+                    .arg(release->getLabel())
+                    .arg(lease->addr_.toText());
 
                 if (CfgMgr::instance().ddnsEnabled()) {
                     // Remove existing DNS entries for the lease, if any.
                     queueNameChangeRequest(isc::dhcp_ddns::CHG_REMOVE, lease);
                 }
             } else {
-                // Release failed -
-                LOG_ERROR(dhcp4_logger, DHCP4_RELEASE_FAIL)
-                    .arg(lease->addr_.toText())
-                .arg(client_id ? client_id->toText() : "(no client-id)")
-                    .arg(release->getHWAddr()->toText());
+                // Release failed
+                LOG_ERROR(lease_logger, DHCP4_RELEASE_FAIL)
+                    .arg(release->getLabel())
+                    .arg(lease->addr_.toText());
             }
         }
     } catch (const isc::Exception& ex) {
-        // Rethrow the exception with a bit more data.
-        LOG_ERROR(dhcp4_logger, DHCP4_RELEASE_EXCEPTION)
-            .arg(ex.what())
-            .arg(release->getYiaddr());
+        LOG_ERROR(lease_logger, DHCP4_RELEASE_EXCEPTION)
+            .arg(release->getLabel())
+            .arg(release->getCiaddr())
+            .arg(ex.what());
     }
-
 }
 
 void
@@ -1699,6 +1787,10 @@ Dhcpv4Srv::processInform(Pkt4Ptr& inform) {
     // be cleared (these fields were copied by the copyDefaultFields function).
     // Also Relay Agent Options should be removed if present.
     if (ack->getRemoteAddr() != inform->getGiaddr()) {
+        LOG_DEBUG(packet_logger, DBG_DHCP4_DETAIL, DHCP4_INFORM_DIRECT_REPLY)
+            .arg(inform->getLabel())
+            .arg(ack->getRemoteAddr())
+            .arg(ack->getIface());
         ack->setHops(0);
         ack->setGiaddr(IOAddress::IPV4_ZERO_ADDRESS());
         ack->delOption(DHO_DHCP_AGENT_OPTIONS);
@@ -1710,44 +1802,14 @@ Dhcpv4Srv::processInform(Pkt4Ptr& inform) {
     /// @todo: decide whether we want to add a new hook point for
     /// doing class specific processing.
     if (!classSpecificProcessing(ex)) {
-        /// @todo add more verbosity here
-        LOG_DEBUG(dhcp4_logger, DBG_DHCP4_BASIC, DHCP4_INFORM_CLASS_PROCESSING_FAILED);
+        LOG_DEBUG(options_logger, DBG_DHCP4_DETAIL,
+                  DHCP4_INFORM_CLASS_PROCESSING_FAILED)
+            .arg(inform->getLabel());
     }
 
     return (ex.getResponse());
 }
 
-const char*
-Dhcpv4Srv::serverReceivedPacketName(uint8_t type) {
-    static const char* DISCOVER = "DISCOVER";
-    static const char* REQUEST = "REQUEST";
-    static const char* RELEASE = "RELEASE";
-    static const char* DECLINE = "DECLINE";
-    static const char* INFORM = "INFORM";
-    static const char* UNKNOWN = "UNKNOWN";
-
-    switch (type) {
-    case DHCPDISCOVER:
-        return (DISCOVER);
-
-    case DHCPREQUEST:
-        return (REQUEST);
-
-    case DHCPRELEASE:
-        return (RELEASE);
-
-    case DHCPDECLINE:
-        return (DECLINE);
-
-    case DHCPINFORM:
-        return (INFORM);
-
-    default:
-        ;
-    }
-    return (UNKNOWN);
-}
-
 bool
 Dhcpv4Srv::accept(const Pkt4Ptr& query) const {
     // Check that the message type is accepted by the server. We rely on the
@@ -1904,7 +1966,7 @@ Dhcpv4Srv::sanityCheck(const Pkt4Ptr& query, RequirementLevel serverid) {
         if (server_id) {
             isc_throw(RFCViolation, "Server-id option was not expected, but "
                       << "received in "
-                      << serverReceivedPacketName(query->getType()));
+                      << query->getName());
         }
         break;
 
@@ -1912,7 +1974,7 @@ Dhcpv4Srv::sanityCheck(const Pkt4Ptr& query, RequirementLevel serverid) {
         if (!server_id) {
             isc_throw(RFCViolation, "Server-id option was expected, but not "
                       " received in message "
-                      << serverReceivedPacketName(query->getType()));
+                      << query->getName());
         }
         break;
 
@@ -1934,7 +1996,7 @@ Dhcpv4Srv::sanityCheck(const Pkt4Ptr& query, RequirementLevel serverid) {
     if (!client_id || client_id->len() == client_id->getHeaderLen()) {
         isc_throw(RFCViolation, "Missing or useless client-id and no HW address "
                   " provided in message "
-                  << serverReceivedPacketName(query->getType()));
+                  << query->getName());
     }
 }
 
@@ -2073,7 +2135,8 @@ void Dhcpv4Srv::classifyPacket(const Pkt4Ptr& pkt) {
     }
 
     if (!classes.empty()) {
-        LOG_DEBUG(dhcp4_logger, DBG_DHCP4_BASIC, DHCP4_CLASS_ASSIGNED)
+        LOG_DEBUG(options_logger, DBG_DHCP4_BASIC, DHCP4_CLASS_ASSIGNED)
+            .arg(pkt->getLabel())
             .arg(classes);
     }
 }
@@ -2136,7 +2199,7 @@ void
 Dhcpv4Srv::d2ClientErrorHandler(const
                                 dhcp_ddns::NameChangeSender::Result result,
                                 dhcp_ddns::NameChangeRequestPtr& ncr) {
-    LOG_ERROR(dhcp4_logger, DHCP4_DDNS_REQUEST_SEND_FAILED).
+    LOG_ERROR(ddns_logger, DHCP4_DDNS_REQUEST_SEND_FAILED).
               arg(result).arg((ncr ? ncr->toText() : " NULL "));
     // We cannot communicate with kea-dhcp-ddns, suspend further updates.
     /// @todo We may wish to revisit this, but for now we will simply turn

+ 0 - 19
src/bin/dhcp4/dhcp4_srv.h

@@ -199,25 +199,6 @@ public:
     /// @brief Instructs the server to shut down.
     void shutdown();
 
-    /// @brief Return textual type of packet received by server
-    ///
-    /// Returns the name of valid packet received by the server (e.g. DISCOVER).
-    /// If the packet is unknown - or if it is a valid DHCP packet but not one
-    /// expected to be received by the server (such as an OFFER), the string
-    /// "UNKNOWN" is returned.  This method is used in debug messages.
-    ///
-    /// As the operation of the method does not depend on any server state, it
-    /// is declared static.
-    ///
-    /// @todo: This should be named static Pkt4::getName()
-    ///
-    /// @param type DHCPv4 packet type
-    ///
-    /// @return Pointer to "const" string containing the packet name.
-    ///         Note that this string is statically allocated and MUST NOT
-    ///         be freed by the caller.
-    static const char* serverReceivedPacketName(uint8_t type);
-
     ///
     /// @name Public accessors returning values required to (re)open sockets.
     ///

+ 0 - 32
src/bin/dhcp4/tests/dhcp4_srv_unittest.cc

@@ -436,38 +436,6 @@ TEST_F(Dhcpv4SrvTest, processDecline) {
     EXPECT_NO_THROW(srv.processDecline(pkt));
 }
 
-TEST_F(Dhcpv4SrvTest, serverReceivedPacketName) {
-    // Check all possible packet types
-    for (int itype = 0; itype < 256; ++itype) {
-        uint8_t type = itype;
-
-        switch (type) {
-        case DHCPDECLINE:
-            EXPECT_STREQ("DECLINE", Dhcpv4Srv::serverReceivedPacketName(type));
-            break;
-
-        case DHCPDISCOVER:
-            EXPECT_STREQ("DISCOVER", Dhcpv4Srv::serverReceivedPacketName(type));
-            break;
-
-        case DHCPINFORM:
-            EXPECT_STREQ("INFORM", Dhcpv4Srv::serverReceivedPacketName(type));
-            break;
-
-        case DHCPRELEASE:
-            EXPECT_STREQ("RELEASE", Dhcpv4Srv::serverReceivedPacketName(type));
-            break;
-
-        case DHCPREQUEST:
-            EXPECT_STREQ("REQUEST", Dhcpv4Srv::serverReceivedPacketName(type));
-            break;
-
-        default:
-            EXPECT_STREQ("UNKNOWN", Dhcpv4Srv::serverReceivedPacketName(type));
-        }
-    }
-}
-
 // This test verifies that incoming DISCOVER can be handled properly, that an
 // OFFER is generated, that the response has an address and that address
 // really belongs to the configured pool.

+ 36 - 15
src/lib/dhcp/option.cc

@@ -195,29 +195,50 @@ bool Option::delOption(uint16_t opt_type) {
 }
 
 
-std::string Option::toText(int indent /* =0 */ ) {
-    std::stringstream tmp;
-
-    for (int i = 0; i < indent; i++)
-        tmp << " ";
-
-    tmp << "type=" << type_ << ", len=" << len()-getHeaderLen() << ": ";
+std::string Option::toText(int indent) {
+    std::stringstream output;
+    output << headerToText(indent) << ": ";
 
     for (unsigned int i = 0; i < data_.size(); i++) {
         if (i) {
-            tmp << ":";
+            output << ":";
         }
-        tmp << setfill('0') << setw(2) << hex
+        output << setfill('0') << setw(2) << hex
             << static_cast<unsigned short>(data_[i]);
     }
 
-    // print suboptions
-    for (OptionCollection::const_iterator opt = options_.begin();
-         opt != options_.end();
-         ++opt) {
-        tmp << (*opt).second->toText(indent+2);
+    // Append suboptions.
+    output << suboptionsToText(indent + 2);
+
+    return (output.str());
+}
+
+std::string
+Option::headerToText(const int indent) {
+    std::stringstream output;
+    for (int i = 0; i < indent; i++)
+        output << " ";
+
+    int field_len = (getUniverse() == V4 ? 3 : 5);
+    output << "type=" << std::setw(field_len) << std::setfill('0')
+           << type_ << ", len=" << std::setw(field_len) << std::setfill('0')
+           << len()-getHeaderLen();
+    return (output.str());
+}
+
+std::string
+Option::suboptionsToText(const int indent) const {
+    std::stringstream output;
+
+    if (!options_.empty()) {
+        output << "," << std::endl << "options:";
+        for (OptionCollection::const_iterator opt = options_.begin();
+             opt != options_.end(); ++opt) {
+            output << std::endl << (*opt).second->toText(indent);
+        }
     }
-    return tmp.str();
+
+    return (output.str());
 }
 
 uint16_t

+ 26 - 2
src/lib/dhcp/option.h

@@ -1,4 +1,4 @@
-// Copyright (C) 2011-2014 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2011-2015 Internet Systems Consortium, Inc. ("ISC")
 //
 // Permission to use, copy, modify, and/or distribute this software for any
 // purpose with or without fee is hereby granted, provided that the above
@@ -423,7 +423,31 @@ protected:
     /// those into one exception which can be documented here.
     void unpackOptions(const OptionBuffer& buf);
 
-    /// @brief A private method used for option correctness.
+    /// @brief Returns option header in the textual format.
+    ///
+    /// This protected method should be called by the derived classes in
+    /// their respective @c toText implementations.
+    ///
+    /// @param indent Number of spaces to insert before the text.
+    ///
+    /// @return Option header in the textual format.
+    std::string headerToText(const int indent = 0);
+
+    /// @brief Returns collection of suboptions in the textual format.
+    ///
+    /// This protected method should be called by the derived classes
+    /// in their respective @c toText implementations to append the
+    /// suboptions held by this option. Note that there are some
+    /// option types which don't have suboptions because they contain
+    /// variable length fields. For such options this method is not
+    /// called.
+    ///
+    /// @param indent Number of spaces to insert before the text.
+    ///
+    //// @return Suboptions in the textual format.
+    std::string suboptionsToText(const int indent = 0) const;
+
+    /// @brief A protected method used for option correctness.
     ///
     /// It is used in constructors. In there are any problems detected
     /// (like specifying type > 255 for DHCPv4 option), it will throw

+ 6 - 11
src/lib/dhcp/option4_addrlst.cc

@@ -1,4 +1,4 @@
-// Copyright (C) 2011-2012 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2011-2012,2015 Internet Systems Consortium, Inc. ("ISC")
 //
 // Permission to use, copy, modify, and/or distribute this software for any
 // purpose with or without fee is hereby granted, provided that the above
@@ -120,21 +120,16 @@ uint16_t Option4AddrLst::len() {
     return (getHeaderLen() + addrs_.size() * V4ADDRESS_LEN);
 }
 
-std::string Option4AddrLst::toText(int indent /* =0 */ ) {
-    std::stringstream tmp;
-
-    for (int i = 0; i < indent; i++) {
-        tmp << " ";
-    }
-
-    tmp << "type=" << type_ << ", len=" << len()-getHeaderLen() << ":";
+std::string Option4AddrLst::toText(int indent) {
+    std::stringstream output;
+    output << headerToText(indent) << ":";
 
     for (AddressContainer::const_iterator addr = addrs_.begin();
          addr != addrs_.end(); ++addr) {
-        tmp << " " << (*addr);
+        output << " " << (*addr);
     }
 
-    return tmp.str();
+    return (output.str());
 }
 
 } // end of isc::dhcp namespace

+ 6 - 9
src/lib/dhcp/option6_addrlst.cc

@@ -1,4 +1,4 @@
-// Copyright (C) 2011-2012, 2015 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2011-2012,2015 Internet Systems Consortium, Inc. ("ISC")
 //
 // Permission to use, copy, modify, and/or distribute this software for any
 // purpose with or without fee is hereby granted, provided that the above
@@ -97,18 +97,15 @@ void Option6AddrLst::unpack(OptionBufferConstIter begin,
     }
 }
 
-std::string Option6AddrLst::toText(int indent /* =0 */) {
-    stringstream tmp;
-    for (int i = 0; i < indent; i++)
-        tmp << " ";
-
-    tmp << "type=" << type_ << " " << addrs_.size() << "addr(s): ";
+std::string Option6AddrLst::toText(int indent) {
+    stringstream output;
+    output << headerToText(indent) << ":";
 
     for (AddressContainer::const_iterator addr = addrs_.begin();
          addr != addrs_.end(); ++addr) {
-        tmp << *addr << " ";
+        output << " " << *addr;
     }
-    return tmp.str();
+    return (output.str());
 }
 
 uint16_t Option6AddrLst::len() {

+ 13 - 30
src/lib/dhcp/option_custom.cc

@@ -1,4 +1,4 @@
-// Copyright (C) 2012-2013, 2015 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2012-2013,2015 Internet Systems Consortium, Inc. ("ISC")
 //
 // Permission to use, copy, modify, and/or distribute this software for any
 // purpose with or without fee is hereby granted, provided that the above
@@ -349,17 +349,17 @@ OptionCustom::dataFieldToText(const OptionDataType data_type,
         text << readAddress(index);
         break;
     case OPT_FQDN_TYPE:
-        text << readFqdn(index);
+        text << "\"" << readFqdn(index) << "\"";
         break;
     case OPT_STRING_TYPE:
-        text << readString(index);
+        text << "\"" << readString(index) << "\"";
         break;
     default:
         ;
     }
 
     // Append data field type in brackets.
-    text << " ( " << OptionDataTypeUtil::getDataTypeName(data_type) << " ) ";
+    text << " (" << OptionDataTypeUtil::getDataTypeName(data_type) << ")";
 
     return (text.str());
 }
@@ -532,13 +532,9 @@ void OptionCustom::initialize(const OptionBufferConstIter first,
 }
 
 std::string OptionCustom::toText(int indent) {
-    std::stringstream tmp;
+    std::stringstream output;
 
-    for (int i = 0; i < indent; ++i)
-        tmp << " ";
-
-    tmp << "type=" << type_ << ", len=" << len()-getHeaderLen()
-        << ", data fields:" << std::endl;
+    output << headerToText(indent) << ":";
 
     OptionDataType data_type = definition_.getType();
     if (data_type == OPT_RECORD_TYPE) {
@@ -550,13 +546,8 @@ std::string OptionCustom::toText(int indent) {
         // with them.
         for (OptionDefinition::RecordFieldsConstIter field = fields.begin();
              field != fields.end(); ++field) {
-            for (int j = 0; j < indent + 2; ++j) {
-                tmp << " ";
-            }
-            tmp << "#" << std::distance(fields.begin(), field) << " "
-                << dataFieldToText(*field, std::distance(fields.begin(),
-                                                         field))
-                << std::endl;
+            output << " " << dataFieldToText(*field, std::distance(fields.begin(),
+                                                                   field));
         }
     } else {
         // For non-record types we iterate over all buffers
@@ -565,22 +556,14 @@ std::string OptionCustom::toText(int indent) {
         // and non-arrays as they only differ in such a way that
         // non-arrays have just single data field.
         for (unsigned int i = 0; i < getDataFieldsNum(); ++i) {
-            for (int j = 0; j < indent + 2; ++j) {
-                tmp << " ";
-            }
-            tmp << "#" << i << " "
-                << dataFieldToText(definition_.getType(), i)
-                << std::endl;
+            output << " " << dataFieldToText(definition_.getType(), i);
         }
     }
 
-    // print suboptions
-    for (OptionCollection::const_iterator opt = options_.begin();
-         opt != options_.end();
-         ++opt) {
-        tmp << (*opt).second->toText(indent+2);
-    }
-    return tmp.str();
+    // Append suboptions.
+    output << suboptionsToText(indent + 2);
+
+    return (output.str());
 }
 
 } // end of isc::dhcp namespace

+ 31 - 0
src/lib/dhcp/option_int.h

@@ -21,6 +21,7 @@
 #include <util/io_utilities.h>
 
 #include <stdint.h>
+#include <sstream>
 
 namespace isc {
 namespace dhcp {
@@ -205,6 +206,36 @@ public:
         return (length);
     }
 
+    /// @brief Returns option carrying an integer value in the textual
+    /// format.
+    ///
+    /// The returned value also includes the suboptions if present.
+    ///
+    /// @param indent Number of spaces to be inserted before the text.
+    virtual std::string toText(int indent = 0) {
+        std::stringstream output;
+        output << headerToText(indent) << ": ";
+
+        // For 1 byte long data types we need to cast to the integer
+        // because they are usually implemented as "char" types, in
+        // which case the character rather than number would be printed.
+        if (OptionDataTypeTraits<T>::len == 1) {
+            output << static_cast<int>(getValue());
+        } else {
+            output << getValue();
+        }
+
+        // Append data type name.
+        output << " ("
+               << OptionDataTypeUtil::getDataTypeName(OptionDataTypeTraits<T>::type)
+               << ")";
+
+        // Append suboptions.
+        output << suboptionsToText(indent + 2);
+
+        return (output.str());
+    }
+
 private:
 
     T value_;  ///< Value conveyed by the option.

+ 21 - 2
src/lib/dhcp/option_int_array.h

@@ -1,4 +1,4 @@
-// Copyright (C) 2012-2013 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2012-2013,2015 Internet Systems Consortium, Inc. ("ISC")
 //
 // Permission to use, copy, modify, and/or distribute this software for any
 // purpose with or without fee is hereby granted, provided that the above
@@ -19,7 +19,7 @@
 #include <dhcp/option.h>
 #include <dhcp/option_data_types.h>
 #include <util/io_utilities.h>
-
+#include <sstream>
 #include <stdint.h>
 
 namespace isc {
@@ -249,6 +249,25 @@ public:
         return (length);
     }
 
+    /// @brief Returns textual representation of the option.
+    ///
+    /// @param indent Number of space characters to be inserted before
+    /// the text.
+    ///
+    /// @return textual representation of the option.
+    virtual std::string toText(int indent = 0) {
+        std::stringstream output;
+        output << headerToText(indent) << ":";
+
+        std::string data_type = OptionDataTypeUtil::getDataTypeName(OptionDataTypeTraits<T>::type);
+        for (typename std::vector<T>::const_iterator value = values_.begin();
+             value != values_.end(); ++value) {
+            output << " " << *value << "(" << data_type << ")";
+        }
+
+        return (output.str());
+    }
+
 private:
 
     std::vector<T> values_;

+ 11 - 1
src/lib/dhcp/option_string.cc

@@ -1,4 +1,4 @@
-// Copyright (C) 2013 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2013,2015 Internet Systems Consortium, Inc. ("ISC")
 //
 // Permission to use, copy, modify, and/or distribute this software for any
 // purpose with or without fee is hereby granted, provided that the above
@@ -13,6 +13,7 @@
 // PERFORMANCE OF THIS SOFTWARE.
 
 #include <dhcp/option_string.h>
+#include <sstream>
 
 namespace isc {
 namespace dhcp {
@@ -82,5 +83,14 @@ OptionString::unpack(OptionBufferConstIter begin,
     setData(begin, end);
 }
 
+std::string
+OptionString::toText(int indent) {
+    std::ostringstream output;
+    output << headerToText(indent) << ": "
+           << "\"" << getValue() << "\" (string)";
+
+    return (output.str());
+}
+
 } // end of isc::dhcp namespace
 } // end of isc namespace

+ 8 - 1
src/lib/dhcp/option_string.h

@@ -1,4 +1,4 @@
-// Copyright (C) 2013 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2013,2015 Internet Systems Consortium, Inc. ("ISC")
 //
 // Permission to use, copy, modify, and/or distribute this software for any
 // purpose with or without fee is hereby granted, provided that the above
@@ -103,6 +103,13 @@ public:
     /// @throw isc::OutOfRange if provided buffer is truncated.
     virtual void unpack(OptionBufferConstIter begin, OptionBufferConstIter end);
 
+    /// @brief Returns option information in the textual format.
+    ///
+    /// @param indent Number of space characters to be inserted before
+    /// the text.
+    ///
+    /// @return Option information in the textual format.
+    virtual std::string toText(int indent = 0);
 };
 
 /// Pointer to the OptionString object.

+ 28 - 3
src/lib/dhcp/option_vendor.cc

@@ -1,4 +1,4 @@
-// Copyright (C) 2013, 2015 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2013,2015 Internet Systems Consortium, Inc. ("ISC")
 //
 // Permission to use, copy, modify, and/or distribute this software for any
 // purpose with or without fee is hereby granted, provided that the above
@@ -17,6 +17,7 @@
 #include <dhcp/dhcp4.h>
 #include <dhcp/dhcp6.h>
 #include <dhcp/option_vendor.h>
+#include <sstream>
 
 using namespace isc::dhcp;
 
@@ -42,8 +43,7 @@ void OptionVendor::pack(isc::util::OutputBuffer& buf) {
         // Calculate and store data-len as follows:
         // data-len = total option length - header length
         //            - enterprise id field length - data-len field size
-        buf.writeUint8(len() - getHeaderLen() -
-                       sizeof(uint32_t) - sizeof(uint8_t));
+        buf.writeUint8(dataLen());
     }
 
     packOptions(buf);
@@ -85,3 +85,28 @@ uint16_t OptionVendor::len() {
     }
     return (length);
 }
+
+uint8_t
+OptionVendor::dataLen() {
+    // Calculate and store data-len as follows:
+    // data-len = total option length - header length
+    //            - enterprise id field length - data-len field size
+    return (len() - getHeaderLen() - sizeof(uint32_t) - sizeof(uint8_t));
+}
+
+std::string
+OptionVendor::toText(int indent) {
+    std::stringstream output;
+    output << headerToText(indent) << ": "
+           << getVendorId() << " (uint32)";
+
+    // For the DHCPv4 there is one more field.
+    if (getUniverse() == Option::V4) {
+        output << " " << static_cast<int>(dataLen()) << " (uint8)";
+    }
+
+    // Append suboptions.
+    output << suboptionsToText(indent + 2);
+
+    return (output.str());
+}

+ 18 - 1
src/lib/dhcp/option_vendor.h

@@ -1,4 +1,4 @@
-// Copyright (C) 2013 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2013,2015 Internet Systems Consortium, Inc. ("ISC")
 //
 // Permission to use, copy, modify, and/or distribute this software for any
 // purpose with or without fee is hereby granted, provided that the above
@@ -92,8 +92,25 @@ public:
     /// @return length of this option
     virtual uint16_t len();
 
+    /// @brief Returns the option in the textual format.
+    ///
+    /// @param indent Number of spaces to be inserted before the text.
+    ///
+    /// @return Vendor option in the textual format.
+    virtual std::string toText(int indent = 0);
+
 private:
 
+    /// @brief Calculates the data-len value for DHCPv4.
+    ///
+    /// The data-len field is only present in DHCPv4 space. It follows
+    /// the vendor-id field. This method is called from the
+    /// @c OptionVendor::pack and @c OptionVendor::toText to calculate
+    /// this value.
+    ///
+    /// @return Returns calculated data-len value.
+    uint8_t dataLen();
+
     uint32_t vendor_id_;  ///< Enterprise-id
 };
 

+ 12 - 1
src/lib/dhcp/pkt.h

@@ -161,7 +161,7 @@ public:
     /// implementations of this method.
     ///
     /// @return string with text representation
-    virtual std::string toText() = 0;
+    virtual std::string toText() const = 0;
 
     /// @brief Returns packet size in binary format.
     ///
@@ -193,6 +193,17 @@ public:
     /// @param type message type to be set
     virtual void setType(uint8_t type) = 0;
 
+    /// @brief Returns name of the DHCP message.
+    ///
+    /// For all unsupported messages the derived classes must return
+    /// "UNKNOWN".
+    ///
+    /// @return Ponter to "const" string containing DHCP message name.
+    /// The implementations in the derived classes should statically
+    /// allocate returned strings and the caller must not release the
+    /// returned pointer.
+    virtual const char* getName() const = 0;
+
     /// @brief Sets transaction-id value.
     ///
     /// @param transid transaction-id to be set.

+ 80 - 15
src/lib/dhcp/pkt4.cc

@@ -282,6 +282,54 @@ void Pkt4::setType(uint8_t dhcp_type) {
     }
 }
 
+const char*
+Pkt4::getName(const uint8_t type) {
+    static const char* DHCPDISCOVER_NAME = "DHCPDISCOVER";
+    static const char* DHCPOFFER_NAME = "DHCPOFFER";
+    static const char* DHCPREQUEST_NAME = "DHCPREQUEST";
+    static const char* DHCPDECLINE_NAME = "DHCPDECLINE";
+    static const char* DHCPACK_NAME = "DHCPACK";
+    static const char* DHCPNAK_NAME = "DHCPNAK";
+    static const char* DHCPRELEASE_NAME = "DHCPRELEASE";
+    static const char* DHCPINFORM_NAME = "DHCPINFORM";
+    static const char* UNKNOWN_NAME = "UNKNOWN";
+
+    switch (type) {
+        case DHCPDISCOVER:
+            return (DHCPDISCOVER_NAME);
+
+        case DHCPOFFER:
+            return (DHCPOFFER_NAME);
+
+        case DHCPREQUEST:
+            return (DHCPREQUEST_NAME);
+
+        case DHCPDECLINE:
+            return (DHCPDECLINE_NAME);
+
+        case DHCPACK:
+            return (DHCPACK_NAME);
+
+        case DHCPNAK:
+            return (DHCPNAK_NAME);
+
+        case DHCPRELEASE:
+            return (DHCPRELEASE_NAME);
+
+        case DHCPINFORM:
+            return (DHCPINFORM_NAME);
+
+        default:
+            ;
+    }
+    return (UNKNOWN_NAME);
+}
+
+const char*
+Pkt4::getName() const {
+    return (Pkt4::getName(getType()));
+}
+
 std::string
 Pkt4::getLabel() const {
 
@@ -301,30 +349,47 @@ std::string
 Pkt4::makeLabel(const HWAddrPtr& hwaddr, const ClientIdPtr& client_id,
                 const uint32_t transid) {
     stringstream label;
-    label << "hwaddr=[" << (hwaddr ? hwaddr->toText() : "no info")
-          << "], client-id=[" << (client_id ? client_id->toText() : "no info")
-          << "], transid=0x" << hex << transid << dec;
+    label << "[" << (hwaddr ? hwaddr->toText() : "no hwaddr info")
+          << "], cid=[" << (client_id ? client_id->toText() : "no info")
+          << "], tid=0x" << hex << transid << dec;
 
     return label.str();
 }
 
 
 std::string
-Pkt4::toText() {
-    stringstream tmp;
-    tmp << "localAddr=" << local_addr_ << ":" << local_port_
-        << " remoteAddr=" << remote_addr_
-        << ":" << remote_port_ << ", msgtype=" << static_cast<int>(getType())
-        << ", transid=0x" << hex << transid_ << dec << endl;
-
-    for (isc::dhcp::OptionCollection::iterator opt=options_.begin();
-         opt != options_.end();
-         ++opt) {
-        tmp << "  " << opt->second->toText() << std::endl;
+Pkt4::toText() const {
+    stringstream output;
+    output << "local_address=" << local_addr_ << ":" << local_port_
+        << ", remote_adress=" << remote_addr_
+        << ":" << remote_port_ << ", msg_type=";
+
+    // Try to obtain message type. This may throw if the Message Type option is
+    // not present. Therefore we guard it with try-catch, because we don't want
+    // toText method to throw.
+    try {
+        uint8_t msg_type = getType();
+        output << getName(msg_type) << " (" << static_cast<int>(msg_type) << ")";
+
+    } catch (...) {
+        // Message Type option is missing.
+        output << "(missing)";
     }
 
+    output << ", transid=0x" << hex << transid_ << dec;
+
+    if (!options_.empty()) {
+        output << "," << std::endl << "options:";
+        for (isc::dhcp::OptionCollection::const_iterator opt = options_.begin();
+             opt != options_.end(); ++opt) {
+            output << std::endl << opt->second->toText(2);
+        }
+
+    } else {
+        output << ", message contains no options";
+    }
 
-    return tmp.str();
+    return (output.str());
 }
 
 void

+ 17 - 1
src/lib/dhcp/pkt4.h

@@ -137,7 +137,7 @@ public:
     /// This function is useful mainly for debugging.
     ///
     /// @return string with text representation
-    std::string toText();
+    std::string toText() const;
 
     /// @brief Returns the size of the required buffer to build the packet.
     ///
@@ -244,6 +244,22 @@ public:
     /// @param type message type to be set
     void setType(uint8_t type);
 
+    /// @brief Returns name of the DHCP message.
+    ///
+    /// @param type DHCPv4 message type which name should be returned.
+    ///
+    /// @return Pointer to the "const" string containing DHCP message name.
+    /// If the message type is unsupported the "UNKNOWN" is returned.
+    /// The caller must not release the returned pointer.
+    static const char* getName(const uint8_t type);
+
+    /// @brief Returns name of the DHCP message.
+    ///
+    /// @return Pointer to the "const" string containing DHCP message name.
+    /// If the message type is unsupported the "UNKNOWN" is returned.
+    /// The caller must not release the returned pointer.
+    const char* getName() const;
+
     /// @brief Returns sname field
     ///
     /// Note: This is 64 bytes long field. It doesn't have to be

+ 3 - 3
src/lib/dhcp/pkt6.cc

@@ -496,14 +496,14 @@ Pkt6::getMACFromDUID() {
 }
 
 std::string
-Pkt6::toText() {
+Pkt6::toText() const {
     stringstream tmp;
     tmp << "localAddr=[" << local_addr_ << "]:" << local_port_
         << " remoteAddr=[" << remote_addr_
         << "]:" << remote_port_ << endl;
     tmp << "msgtype=" << static_cast<int>(msg_type_) << ", transid=0x" <<
         hex << transid_ << dec << endl;
-    for (isc::dhcp::OptionCollection::iterator opt=options_.begin();
+    for (isc::dhcp::OptionCollection::const_iterator opt=options_.begin();
          opt != options_.end();
          ++opt) {
         tmp << opt->second->toText() << std::endl;
@@ -525,7 +525,7 @@ Pkt6::getOptions(uint16_t opt_type) {
 }
 
 const char*
-Pkt6::getName(uint8_t type) {
+Pkt6::getName(const uint8_t type) {
     static const char* CONFIRM = "CONFIRM";
     static const char* DECLINE = "DECLINE";
     static const char* INFORMATION_REQUEST = "INFORMATION_REQUEST";

+ 3 - 3
src/lib/dhcp/pkt6.h

@@ -162,7 +162,7 @@ public:
     /// This function is useful mainly for debugging.
     ///
     /// @return string with text representation
-    virtual std::string toText();
+    virtual std::string toText() const;
 
     /// @brief Returns length of the packet.
     ///
@@ -232,7 +232,7 @@ public:
     /// @param relay structure with necessary relay information
     void addRelayInfo(const RelayInfo& relay);
 
-    /// @brief Return textual type of packet.
+    /// @brief Returns name of the DHCPv6 message.
     ///
     /// Returns the name of valid packet received by the server (e.g. SOLICIT).
     /// If the packet is unknown - or if it is a valid DHCP packet but not one
@@ -248,7 +248,7 @@ public:
     /// @return Pointer to "const" string containing the packet name.
     ///         Note that this string is statically allocated and MUST NOT
     ///         be freed by the caller.
-    static const char* getName(uint8_t type);
+    static const char* getName(const uint8_t type);
 
     /// @brief returns textual representation of packet type.
     ///

+ 35 - 1
src/lib/dhcp/tests/option_custom_unittest.cc

@@ -1,4 +1,4 @@
-// Copyright (C) 2012-2013 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2012-2013,2015 Internet Systems Consortium, Inc. ("ISC")
 //
 // Permission to use, copy, modify, and/or distribute this software for any
 // purpose with or without fee is hereby granted, provided that the above
@@ -1570,4 +1570,38 @@ TEST_F(OptionCustomTest, invalidIndex) {
     EXPECT_THROW(option->readInteger<uint32_t>(11), isc::OutOfRange);
 }
 
+// This test checks that the custom option holding a record of data
+// fields can be presented in the textual format.
+TEST_F(OptionCustomTest, toTextRecord) {
+    OptionDefinition opt_def("foo", 123, "record");
+    opt_def.addRecordField("uint32");
+    opt_def.addRecordField("string");
+
+    OptionCustom option(opt_def, Option::V4);
+    option.writeInteger<uint32_t>(10);
+    option.writeString("lorem ipsum", 1);
+
+    EXPECT_EQ("type=123, len=015: 10 (uint32) \"lorem ipsum\" (string)",
+              option.toText());
+}
+
+// This test checks that the custom option holding other data type
+// than "record" be presented in the textual format.
+TEST_F(OptionCustomTest, toTextNoRecord) {
+    OptionDefinition opt_def("foo", 234, "uint32");
+
+    OptionCustom option(opt_def, Option::V6);
+    option.writeInteger<uint32_t>(123456);
+
+    OptionDefinition sub_opt_def("bar", 333, "fqdn");
+    OptionCustomPtr sub_opt(new OptionCustom(sub_opt_def, Option::V6));
+    sub_opt->writeFqdn("myhost.example.org.");
+    option.addOption(sub_opt);
+
+    EXPECT_EQ("type=00234, len=00028: 123456 (uint32),\n"
+              "options:\n"
+              "  type=00333, len=00020: \"myhost.example.org.\" (fqdn)",
+              option.toText());
+}
+
 } // anonymous namespace

+ 13 - 1
src/lib/dhcp/tests/option_int_array_unittest.cc

@@ -1,4 +1,4 @@
-// Copyright (C) 2012 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2012,2015 Internet Systems Consortium, Inc. ("ISC")
 //
 // Permission to use, copy, modify, and/or distribute this software for any
 // purpose with or without fee is hereby granted, provided that the above
@@ -464,4 +464,16 @@ TEST_F(OptionIntArrayTest, addValuesInt32) {
     addValuesTest<int16_t>();
 }
 
+// This test checks that the option is correctly converted into
+// the textual format.
+TEST_F(OptionIntArrayTest, toText) {
+    OptionUint32Array option(Option::V4, 128);
+    option.addValue(1);
+    option.addValue(32);
+    option.addValue(324);
+
+    EXPECT_EQ("type=128, len=012: 1(uint32) 32(uint32) 324(uint32)",
+              option.toText());
+}
+
 } // anonymous namespace

+ 16 - 1
src/lib/dhcp/tests/option_int_unittest.cc

@@ -1,4 +1,4 @@
-// Copyright (C) 2012 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2012,2015 Internet Systems Consortium, Inc. ("ISC")
 //
 // Permission to use, copy, modify, and/or distribute this software for any
 // purpose with or without fee is hereby granted, provided that the above
@@ -560,4 +560,19 @@ TEST_F(OptionIntTest, unpackSuboptions6) {
     ASSERT_FALSE(subopt);
 }
 
+// This test checks that the toText function returns the option in the
+// textual format correctly.
+TEST_F(OptionIntTest, toText) {
+    OptionUint32 option(Option::V4, 128, 345678);
+    EXPECT_EQ("type=128, len=004: 345678 (uint32)", option.toText());
+
+    option.addOption(OptionPtr(new OptionUint16(Option::V4, 1, 234)));
+    option.addOption(OptionPtr(new OptionUint8(Option::V4, 3, 22)));
+    EXPECT_EQ("type=128, len=011: 345678 (uint32),\n"
+              "options:\n"
+              "  type=001, len=002: 234 (uint16)\n"
+              "  type=003, len=001: 22 (uint8)",
+              option.toText());
+}
+
 } // anonymous namespace

+ 15 - 1
src/lib/dhcp/tests/option_string_unittest.cc

@@ -1,4 +1,4 @@
-// Copyright (C) 2013 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2013,2015  Internet Systems Consortium, Inc. ("ISC")
 //
 // Permission to use, copy, modify, and/or distribute this software for any
 // purpose with or without fee is hereby granted, provided that the above
@@ -157,4 +157,18 @@ TEST_F(OptionStringTest, pack) {
     EXPECT_TRUE(option_value == test_string);
 }
 
+// This test checks that the DHCP option holding a single string is
+// correctly returned in the textual format.
+TEST_F(OptionStringTest, toText) {
+    // V4 option
+    std::string option_value("lorem ipsum");
+    OptionString optv4(Option::V4, 122, option_value);
+    EXPECT_EQ("type=122, len=011: \"lorem ipsum\" (string)", optv4.toText());
+
+    // V6 option
+    option_value = "is a filler text";
+    OptionString optv6(Option::V6, 512, option_value);
+    EXPECT_EQ("type=00512, len=00016: \"is a filler text\" (string)", optv6.toText());
+}
+
 } // anonymous namespace

+ 3 - 3
src/lib/dhcp/tests/option_unittest.cc

@@ -1,4 +1,4 @@
-// Copyright (C) 2011-2014 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2011-2015 Internet Systems Consortium, Inc. ("ISC")
 //
 // Permission to use, copy, modify, and/or distribute this software for any
 // purpose with or without fee is hereby granted, provided that the above
@@ -233,7 +233,7 @@ TEST_F(OptionTest, v4_toText) {
 
     Option opt(Option::V4, 253, buf);
 
-    EXPECT_EQ("type=253, len=3: 00:0f:ff", opt.toText());
+    EXPECT_EQ("type=253, len=003: 00:0f:ff", opt.toText());
 }
 
 // Tests simple constructor
@@ -443,7 +443,7 @@ TEST_F(OptionTest, v6_toText) {
     buf_[2] = 0xff;
 
     OptionPtr opt(new Option(Option::V6, 258, buf_.begin(), buf_.begin() + 3 ));
-    EXPECT_EQ("type=258, len=3: 00:0f:ff", opt->toText());
+    EXPECT_EQ("type=00258, len=00003: 00:0f:ff", opt->toText());
 }
 
 

+ 26 - 1
src/lib/dhcp/tests/option_vendor_unittest.cc

@@ -1,4 +1,4 @@
-// Copyright (C) 2013 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2013,2015 Internet Systems Consortium, Inc. ("ISC")
 //
 // Permission to use, copy, modify, and/or distribute this software for any
 // purpose with or without fee is hereby granted, provided that the above
@@ -19,6 +19,7 @@
 #include <dhcp/docsis3_option_defs.h>
 #include <dhcp/libdhcp++.h>
 #include <dhcp/option_vendor.h>
+#include <dhcp/option_int.h>
 #include <dhcp/option_int_array.h>
 #include <exceptions/exceptions.h>
 #include <util/buffer.h>
@@ -237,4 +238,28 @@ TEST_F(OptionVendorTest, packUnpack6) {
     EXPECT_FALSE(memcmp(&binary[0], output.getData(), output.getLength()));
 }
 
+// Tests that the vendor option is correctly returned in the textual
+// format for DHCPv4 case.
+TEST_F(OptionVendorTest, toText4) {
+    OptionVendor option(Option::V4, 1024);
+    option.addOption(OptionPtr(new OptionUint32(Option::V4, 1, 100)));
+
+    EXPECT_EQ("type=125, len=011: 1024 (uint32) 6 (uint8),\n"
+              "options:\n"
+              "  type=001, len=004: 100 (uint32)",
+              option.toText());
+}
+
+// Tests that the vendor option is correctly returned in the textual
+// format for DHCPv6 case.
+TEST_F(OptionVendorTest, toText6) {
+    OptionVendor option(Option::V6, 2048);
+    option.addOption(OptionPtr(new OptionUint16(Option::V6, 1, 100)));
+
+    EXPECT_EQ("type=00017, len=00010: 2048 (uint32),\n"
+              "options:\n"
+              "  type=00001, len=00002: 100 (uint16)",
+              option.toText());
+}
+
 }

+ 89 - 7
src/lib/dhcp/tests/pkt4_unittest.cc

@@ -18,7 +18,9 @@
 #include <dhcp/dhcp4.h>
 #include <dhcp/libdhcp++.h>
 #include <dhcp/docsis3_option_defs.h>
+#include <dhcp/option_int.h>
 #include <dhcp/option_string.h>
+#include <dhcp/option4_addrlst.h>
 #include <dhcp/pkt4.h>
 #include <exceptions/exceptions.h>
 #include <util/buffer.h>
@@ -884,11 +886,11 @@ TEST_F(Pkt4Test, getLabel) {
     Pkt4 pkt(DHCPOFFER, 1234);
 
     // Verify makeLabel() handles empty values
-    EXPECT_EQ ("hwaddr=[no info], client-id=[no info], transid=0x0",
+    EXPECT_EQ ("[no hwaddr info], cid=[no info], tid=0x0",
                Pkt4::makeLabel(HWAddrPtr(), ClientIdPtr(), 0));
 
     // Verify an "empty" packet label is as we expect
-    EXPECT_EQ ("hwaddr=[hwtype=1 ], client-id=[no info], transid=0x4d2",
+    EXPECT_EQ ("[hwtype=1 ], cid=[no info], tid=0x4d2",
                pkt.getLabel());
 
     // Set that packet hardware address, then verify getLabel
@@ -897,8 +899,8 @@ TEST_F(Pkt4Test, getLabel) {
     HWAddrPtr dummy_hwaddr(new HWAddr(hw, sizeof(hw), hw_type));
     pkt.setHWAddr(dummy_hwaddr);
 
-    EXPECT_EQ ("hwaddr=[hwtype=123 02:04:06:08:0a:0c],"
-               " client-id=[no info], transid=0x4d2", pkt.getLabel());
+    EXPECT_EQ ("[hwtype=123 02:04:06:08:0a:0c],"
+               " cid=[no info], tid=0x4d2", pkt.getLabel());
 
     // Add a client id to the packet then verify getLabel
     OptionBuffer clnt_id(4);
@@ -907,13 +909,93 @@ TEST_F(Pkt4Test, getLabel) {
     }
 
     OptionPtr opt(new Option(Option::V4, DHO_DHCP_CLIENT_IDENTIFIER,
-                                 clnt_id.begin(), clnt_id.begin() + 4));
+                             clnt_id.begin(), clnt_id.begin() + 4));
     pkt.addOption(opt);
 
-    EXPECT_EQ ("hwaddr=[hwtype=123 02:04:06:08:0a:0c],"
-               " client-id=[64:65:66:67], transid=0x4d2",
+    EXPECT_EQ ("[hwtype=123 02:04:06:08:0a:0c],"
+               " cid=[64:65:66:67], tid=0x4d2",
                pkt.getLabel());
 
 }
 
+// Tests that the correct DHCPv4 message name is returned for various
+// message types.
+TEST_F(Pkt4Test, getName) {
+    // Check all possible packet types
+    for (int itype = 0; itype < 256; ++itype) {
+        uint8_t type = itype;
+
+        switch (type) {
+        case DHCPDISCOVER:
+            EXPECT_STREQ("DHCPDISCOVER", Pkt4::getName(type));
+            break;
+
+        case DHCPOFFER:
+            EXPECT_STREQ("DHCPOFFER", Pkt4::getName(type));
+            break;
+
+        case DHCPREQUEST:
+            EXPECT_STREQ("DHCPREQUEST", Pkt4::getName(type));
+            break;
+
+        case DHCPDECLINE:
+            EXPECT_STREQ("DHCPDECLINE", Pkt4::getName(type));
+            break;
+
+        case DHCPACK:
+            EXPECT_STREQ("DHCPACK", Pkt4::getName(type));
+            break;
+
+        case DHCPNAK:
+            EXPECT_STREQ("DHCPNAK", Pkt4::getName(type));
+            break;
+
+        case DHCPRELEASE:
+            EXPECT_STREQ("DHCPRELEASE", Pkt4::getName(type));
+            break;
+
+        case DHCPINFORM:
+            EXPECT_STREQ("DHCPINFORM", Pkt4::getName(type));
+            break;
+
+        default:
+            EXPECT_STREQ("UNKNOWN", Pkt4::getName(type));
+        }
+    }
+}
+
+// This test checks that the packet data are correctly converted to the
+// textual format.
+TEST_F(Pkt4Test, toText) {
+    Pkt4 pkt(DHCPDISCOVER, 2543);
+    pkt.setLocalAddr(IOAddress("192.0.2.34"));
+    pkt.setRemoteAddr(IOAddress("192.10.33.4"));
+
+    pkt.addOption(OptionPtr(new Option4AddrLst(123, IOAddress("192.0.2.3"))));
+    pkt.addOption(OptionPtr(new OptionUint32(Option::V4, 156, 123456)));
+    pkt.addOption(OptionPtr(new OptionString(Option::V4, 87, "lorem ipsum")));
+
+    EXPECT_EQ("local_address=192.0.2.34:67, remote_adress=192.10.33.4:68, "
+              "msg_type=DHCPDISCOVER (1), transid=0x9ef,\n"
+              "options:\n"
+              "  type=053, len=001: 01\n"
+              "  type=087, len=011: \"lorem ipsum\" (string)\n"
+              "  type=123, len=004: 192.0.2.3\n"
+              "  type=156, len=004: 123456 (uint32)",
+              pkt.toText());
+
+    // Now remove all options, including Message Type and check if the
+    // information about lack of any options is displayed properly.
+    pkt.delOption(123);
+    pkt.delOption(156);
+    pkt.delOption(87);
+    pkt.delOption(53);
+
+    EXPECT_EQ("local_address=192.0.2.34:67, remote_adress=192.10.33.4:68, "
+              "msg_type=(missing), transid=0x9ef, "
+              "message contains no options",
+              pkt.toText());
+
+}
+
 } // end of anonymous namespace

+ 1 - 2
src/lib/dhcpsrv/tests/dhcp_parsers_unittest.cc

@@ -533,8 +533,7 @@ TEST_F(ParseConfigTest, basicOptionDataTest) {
     ASSERT_TRUE(opt_ptr);
 
     // Verify that the option definition is correct.
-    std::string val = "type=100, len=4, data fields:\n "
-                      " #0 192.0.2.0 ( ipv4-address ) \n";
+    std::string val = "type=00100, len=00004: 192.0.2.0 (ipv4-address)";
 
     EXPECT_EQ(val, opt_ptr->toText());
 }