Parcourir la source

[master] Merge branch 'trac3807'

Marcin Siodelski il y a 10 ans
Parent
commit
c95ebdaf39
35 fichiers modifiés avec 1725 ajouts et 716 suppressions
  1. 67 34
      doc/guide/logging.xml
  2. 45 38
      src/bin/dhcp4/dhcp4_messages.mes
  3. 2 2
      src/bin/dhcp4/dhcp4_srv.cc
  4. 17 3
      src/bin/dhcp6/dhcp6_log.cc
  5. 88 19
      src/bin/dhcp6/dhcp6_log.h
  6. 287 174
      src/bin/dhcp6/dhcp6_messages.mes
  7. 340 290
      src/bin/dhcp6/dhcp6_srv.cc
  8. 7 16
      src/bin/dhcp6/dhcp6_srv.h
  9. 7 6
      src/bin/dhcp6/tests/dhcp6_client.cc
  10. 0 24
      src/bin/dhcp6/tests/dhcp6_srv_unittest.cc
  11. 4 3
      src/bin/dhcp6/tests/dhcp6_test_utils.cc
  12. 4 4
      src/bin/dhcp6/tests/dhcp6_test_utils.h
  13. 15 15
      src/bin/dhcp6/tests/fqdn_unittest.cc
  14. 1 0
      src/lib/dhcp/Makefile.am
  15. 8 2
      src/lib/dhcp/option.cc
  16. 4 1
      src/lib/dhcp/option.h
  17. 10 18
      src/lib/dhcp/option6_ia.cc
  18. 9 15
      src/lib/dhcp/option6_iaaddr.cc
  19. 9 15
      src/lib/dhcp/option6_iaprefix.cc
  20. 142 0
      src/lib/dhcp/option6_status_code.cc
  21. 118 0
      src/lib/dhcp/option6_status_code.h
  22. 12 0
      src/lib/dhcp/option_definition.cc
  23. 6 1
      src/lib/dhcp/option_definition.h
  24. 1 1
      src/lib/dhcp/pkt4.h
  25. 64 0
      src/lib/dhcp/pkt6.cc
  26. 43 14
      src/lib/dhcp/pkt6.h
  27. 1 0
      src/lib/dhcp/tests/Makefile.am
  28. 3 2
      src/lib/dhcp/tests/libdhcp++_unittest.cc
  29. 17 0
      src/lib/dhcp/tests/option4_addrlst_unittest.cc
  30. 18 1
      src/lib/dhcp/tests/option6_addrlst_unittest.cc
  31. 43 2
      src/lib/dhcp/tests/option6_ia_unittest.cc
  32. 23 1
      src/lib/dhcp/tests/option6_iaaddr_unittest.cc
  33. 21 1
      src/lib/dhcp/tests/option6_iaprefix_unittest.cc
  34. 177 0
      src/lib/dhcp/tests/option6_status_code_unittest.cc
  35. 112 14
      src/lib/dhcp/tests/pkt6_unittest.cc

+ 67 - 34
doc/guide/logging.xml

@@ -120,7 +120,7 @@
             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
+            logger called <quote>kea-dhcp4.bad-packets</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
@@ -161,31 +161,13 @@
             provided.</simpara>
           </listitem>
           <listitem>
-            <simpara><command>kea-dhcp4.bad_packet</command> - this is the
+            <simpara><command>kea-dhcp4.bad-packets</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
             DHCPNAK. The allows adminstrators to configure a separate log
             output that contains only packet drop and reject entries.</simpara>
           </listitem>
           <listitem>
-            <simpara><command>kea-dhcp4.dhcp4</command> - this is the logger
-            used solely by the DHCPv4 server deamon. This logger does not
-            specify logging settings for libraries used by the deamon.</simpara>
-          </listitem>
-          <listitem>
-            <simpara><command>kea-dhcp4.dhcpsrv</command> - this logger is used
-            by the libdhcpsrv library. This covers mostly DHCP engine (the lease
-            allocation and renewal process), database operations and
-            configuration.</simpara>
-          </listitem>
-          <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, 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
             to log messages pertaining to the callouts registration and execution
             for the particular hook point.
@@ -198,6 +180,21 @@
             related to the relevant DNS updates.</simpara>
           </listitem>
           <listitem>
+            <simpara><command>kea-dhcp4.dhcp4</command> - this is the logger
+            by the DHCPv4 server deamon to log basic operations.</simpara>
+          </listitem>
+          <listitem>
+            <simpara><command>kea-dhcp4.dhcpsrv</command> - this is a base
+            logger for the libdhcpsrv library.</simpara>
+          </listitem>
+          <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, and to the
+            initialization of the callouts execution for various hook points
+            within the DHCPv4 server.</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
@@ -236,20 +233,9 @@
             provided.</simpara>
           </listitem>
           <listitem>
-            <simpara><command>kea-dhcp6.dhcp6</command> - this is the logger
-            used solely by the DHCPv6 server deamon. This logger does not
-            specify logging settings for libraries used by the daemon.</simpara>
-          </listitem>
-          <listitem>
-            <simpara><command>kea-dhcp6.dhcpsrv</command> - this logger is used
-            by the libdhcpsrv library. This covers mostly DHCP engine (the lease
-            allocation and renewal process), database operations and
-            configuration.</simpara>
-          </listitem>
-          <listitem>
-            <simpara><command>kea-dhcp6.hooks</command> - this logger is used
-            during DHCPv6 hooks operation, i.e. anything related to user
-            registration and deregistration of the libraries.</simpara>
+            <simpara><command>kea-dhcp6.bad-packets</command> - this is the
+            logger used by the DHCPv6 server deamon for logging inbound client
+            packets that were dropped.</simpara>
           </listitem>
           <listitem>
             <simpara><command>kea-dhcp6.callouts</command> - this logger is used
@@ -258,12 +244,59 @@
             </simpara>
           </listitem>
           <listitem>
+            <simpara><command>kea-dhcp6.ddns</command> - this logger is used by
+            the DHCPv6 server to log messages related to the Client FQDN option
+            processing. It also includes log messages related to the relevant
+            DNS updates.</simpara>
+          </listitem>
+          <listitem>
+            <simpara><command>kea-dhcp6.dhcp6</command> - this is the logger
+            used DHCPv6 server deamon to log basic operations.</simpara>
+          </listitem>
+          <listitem>
+            <simpara><command>kea-dhcp6.dhcpsrv</command> - this is a base
+            logger for the libdhcpsrv library.</simpara>
+          </listitem>
+          <listitem>
+            <simpara><command>kea-dhcp6.hooks</command> - this logger is used
+            to log messages related to management of hooks libraries, e.g.
+            registration and deregistration of the libraries, and to the
+            initialization of the callouts execution for various hook points
+            within the DHCPv6 server.</simpara>
+          </listitem>
+          <listitem>
             <simpara><command>kea-dhcp6.hosts</command> - this logger is used
             within the libdhcpsrv and it logs messages related to the management
             of the DHCPv6 host reservations, i.e. retrieval of the resevations
             and adding new reservations.</simpara>
           </listitem>
           <listitem>
+            <simpara><command>kea-dhcp6.leases</command> - this logger is used
+            by the DHCPv6 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-dhcp6.options</command> - this logger is
+            used by the DHCPv6 server to log messages related to processing
+            of the options in the DHCPv6 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-dhcp6.packets</command> - this logger
+            is mostly used to log messages related to transmission of the DHCPv6
+            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 DHCPv6 message
+            carried in the packet is parsed.
+            </simpara>
+          </listitem>
+          <listitem>
             <simpara><command>kea-dhcp-ddns</command> - this is the root logger for
             the kea-dhcp-ddns deamon. All components used by this deamon inherit
             the settings from this logger if there is no specialized logger

+ 45 - 38
src/bin/dhcp4/dhcp4_messages.mes

@@ -28,12 +28,12 @@ the message.
 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.
+interface and the source and destination IPv4 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
+destination IPv4 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
@@ -43,6 +43,14 @@ 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_INTERRUPTED interrupted wait for the next packet due to timeout, signal or external socket callback (timeout value is %1)
+This debug message is issued when the server intrrupts waiting
+for reception of the next DHCPv6 message due to timeout, signal
+or reception of the data over socket other than used for DHCPv4
+message transmission. 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_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
@@ -50,12 +58,6 @@ 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.
@@ -197,7 +199,7 @@ hooks framework will indicate the nature of the problem.
 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 arguments specify the source and destination IPv4 address as well as
 the name of the interface over which the buffer has been received.
 
 % DHCP4_HOOK_BUFFER_SEND_SKIP %1: prepared response is dropped because a callout set the skip flag.
@@ -244,8 +246,8 @@ information.
 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.
+the client's IPv4 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
@@ -254,23 +256,23 @@ Attached error message provides more details about the issue.
 
 % 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.
+is requesting an IPv4 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 IPv4 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.
+information. The second argument specifies the IPv4 address to be offered.
 
 % 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 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.
+second argument contains the allocated IPv4 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
@@ -282,8 +284,8 @@ hasn't been selected.
 % 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. The first argument includes the client and the transaction
+from the acquired IPv4 address. The message argument indicates the reason
+for the 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.
 
@@ -309,10 +311,10 @@ DHCPv4 server but it is not running.
 
 % 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.
+requested an IPv4 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 IPv4 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
@@ -378,23 +380,23 @@ 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. The first argument contains
 the client and transaction identification information. The second argument
-contains the source address of the packet. The third argument contains
+contains the source IPv4 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
+requested an IPv4 address which is not assigned to him. The server will respond
 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.
+IPv4 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. 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
+argument contains the IPv4 address in the ciaddr field. The third
+argument contains the IPv4 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
@@ -402,8 +404,8 @@ 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. 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
+identification information. The second argument contains the IPv4 address
+in the ciaddr field. The third argument contains the IPv4 address in the
 requested-ip-address option (if present).
 
 % DHCP4_PACKET_PACK %1: preparing on-wire format of the packet to be sent
@@ -418,15 +420,19 @@ 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).
+packet on the specified interface. The first argument specifies the
+client and transaction identification information. The second and third
+argument specify the name of the DHCPv4 message and its numeric type
+respectively. The remaining arguments specify the source IPv4 address,
+destination IPv4 address and the name of the interface on which the
+message has been received.
 
 % 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.
+IPv4 address and port, destination IPv4 address and port and the
+interface name.
 
 % DHCP4_PACKET_SEND_FAIL %1: failed to send DHCPv4 packet: %2
 This error is output if the DHCPv4 server fails to send an assembled
@@ -481,7 +487,7 @@ The second parameter carries the details of the NameChangeRequest.
 This debug message indicates that an address was released properly. It
 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.
+includes the released IPv4 address.
 
 % 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
@@ -490,7 +496,7 @@ which does not expect any response from the server for DHCPRELEASE
 messages. Depending on the nature of problem, it may affect future
 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
+includes the IPv4 address which release was attempted. The last
 argument includes the detailed error description.
 
 % DHCP4_RELEASE_FAIL %1: failed to remove lease for address %2
@@ -501,7 +507,7 @@ 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. The
 first argument includes the client and the transaction identification
-information. The second argument holds the IP address which release
+information. The second argument holds the IPv4 address which release
 was attempted.
 
 % DHCP4_RELEASE_FAIL_NO_SUBNET %1: client is trying to release a lease %2 from a subnet which cannot be selected.
@@ -514,7 +520,8 @@ the address which the client is trying to release.
 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.
+argument contains the IPv4 address which the client is trying to
+release.
 
 % DHCP4_RELEASE_FAIL_WRONG_CLIENT %1: client is trying to release the lease %2 which belongs to a different client
 This debug message is issued when a client is trying to release the
@@ -595,7 +602,7 @@ It lists some information about the parameters with which the server
 is running.
 
 % DHCP4_SUBNET_DATA %1: the selected subnet details: %2
-This debug message includes the details of the subnet selected fot
+This debug message includes the details of the subnet selected for
 the client. The first argument includes the client and the
 transaction identification information. The second arguments
 includes the subnet details.

+ 2 - 2
src/bin/dhcp4/dhcp4_srv.cc

@@ -368,7 +368,7 @@ Dhcpv4Srv::run() {
                     .arg(query->getIface());
 
             } else {
-                LOG_DEBUG(packet_logger, DBG_DHCP4_DETAIL, DHCP4_BUFFER_WAIT_TIMEOUT)
+                LOG_DEBUG(packet_logger, DBG_DHCP4_DETAIL, DHCP4_BUFFER_WAIT_INTERRUPTED)
                     .arg(timeout);
             }
 
@@ -377,7 +377,7 @@ Dhcpv4Srv::run() {
             // 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.
+            // behavior of the system.
             LOG_DEBUG(packet_logger, DBG_DHCP4_DETAIL, DHCP4_BUFFER_WAIT_SIGNAL)
                 .arg(signal_set_->getNext());
         } catch (const std::exception& e) {

+ 17 - 3
src/bin/dhcp6/dhcp6_log.cc

@@ -1,4 +1,4 @@
-// Copyright (C) 2012, 2014 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
@@ -12,14 +12,28 @@
 // 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-dhcp6.
+/// @file dhcp6_log.cc
+/// Contains the loggers used by the DHCPv6 server component.
 
 #include <dhcp6/dhcp6_log.h>
 
 namespace isc {
 namespace dhcp {
 
-isc::log::Logger dhcp6_logger("dhcp6");
+const char* DHCP6_ROOT_LOGGER_NAME = "kea-dhcp6";
+const char* DHCP6_APP_LOGGER_NAME = "dhcp6";
+const char* DHCP6_BAD_PACKET_LOGGER_NAME = "bad-packets";
+const char* DHCP6_PACKET_LOGGER_NAME = "packets";
+const char* DHCP6_OPTIONS_LOGGER_NAME = "options";
+const char* DHCP6_DDNS_LOGGER_NAME = "ddns";
+const char* DHCP6_LEASE_LOGGER_NAME = "leases";
+
+isc::log::Logger dhcp6_logger(DHCP6_APP_LOGGER_NAME);
+isc::log::Logger bad_packet_logger(DHCP6_BAD_PACKET_LOGGER_NAME);
+isc::log::Logger packet_logger(DHCP6_PACKET_LOGGER_NAME);
+isc::log::Logger options_logger(DHCP6_OPTIONS_LOGGER_NAME);
+isc::log::Logger ddns_logger(DHCP6_DDNS_LOGGER_NAME);
+isc::log::Logger lease_logger(DHCP6_LEASE_LOGGER_NAME);
 
 } // namespace dhcp
 } // namespace isc

+ 88 - 19
src/bin/dhcp6/dhcp6_log.h

@@ -1,4 +1,4 @@
-// Copyright (C) 2012, 2014 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
@@ -22,40 +22,109 @@
 namespace isc {
 namespace dhcp {
 
-/// \brief DHCP6 Logging
-///
-/// Defines the levels used to output debug messages in the non-library part of
-/// the kea-dhcp6 program.  Higher numbers equate to more verbose (and detailed)
-/// output.
+/// @name Constants defining debug levels for logging in DHCPv6 server.
+//@{
 
-// Debug levels used to log information during startup and shutdown.
+/// @brief Debug level used to log information during server startup.
 const int DBG_DHCP6_START = DBGLVL_START_SHUT;
+
+/// @brief Debug level used to log information during server shutdown.
 const int DBG_DHCP6_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_DHCP6_COMMAND = DBGLVL_COMMAND;
 
-// Trace basic operations within the code.
+/// @brief Debug level used to trace basic operations within the code.
 const int DBG_DHCP6_BASIC = DBGLVL_TRACE_BASIC;
 
-// Trace hook related operations
+/// @brief Debug level used to trace hook related operations
 const int DBG_DHCP6_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_DHCP6_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_DHCP6_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_DHCP6_DETAIL_DATA = DBGLVL_TRACE_DETAIL_DATA;
 
-/// Define the logger for the "dhcp6" module part of kea-dhcp6.  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 DHCPv6 server.
+//@{
+
+/// @brief Defines the name of the root level (default) logger.
+extern const char* DHCP6_ROOT_LOGGER_NAME;
+
+/// @brief Name of the base logger for DHCPv6 server.
+extern const char* DHCP6_APP_LOGGER_NAME;
+
+/// @brief Name of the logger for rejected packets.
+extern const char* DHCP6_BAD_PACKET_LOGGER_NAME;
+
+/// @brief Name of the logger for processed packets.
+extern const char* DHCP6_PACKET_LOGGER_NAME;
+
+/// @brief Name of the logger for options parser.
+extern const char* DHCP6_OPTIONS_LOGGER_NAME;
+
+/// @brief Name of the logger for hostname or FQDN processing.
+extern const char* DHCP6_DDNS_LOGGER_NAME;
+
+/// @brief Name of the logger for lease allocation logic.
+extern const char* DHCP6_LEASE_LOGGER_NAME;
+
+//@}
+
+/// @name Loggers used by the DHCPv6 server
+//@{
+
+/// @brief Base logger for DHCPv6 server.
 extern isc::log::Logger dhcp6_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 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 dhcp6
 } // namespace isc
 

+ 287 - 174
src/bin/dhcp6/dhcp6_messages.mes

@@ -19,6 +19,52 @@ This message is printed when DHCPv6 server enabled an interface to be used
 to receive DHCPv6 traffic. IPv6 socket on this interface will be opened once
 Interface Manager starts up procedure of opening sockets.
 
+% DHCP6_ADD_GLOBAL_STATUS_CODE %1: adding Status Code to DHCPv6 packet: %2
+This message is logged when the server is adding the top-level
+Status Code option. The first argument includes the client and the
+transaction identification information. The second argument includes
+the details of the status code.
+
+% DHCP6_ADD_STATUS_CODE_FOR_IA %1: adding Status Code to IA with iaid=%2: %3
+This message is logged when the server is adding the Status Code
+option to an IA. The first argument includes the client and the
+transaction identification information. The second argument specifies
+the IAID. The third argument includes the details of the status code.
+
+% DHCP6_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.
+
+% DHCP6_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 DHCPv6 message. The arguments specify the source and
+destination addresses as well as the interface over which the buffer has
+been received.
+
+% DHCP6_BUFFER_WAIT waiting for next DHCPv6 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.
+
+% DHCP6_BUFFER_WAIT_INTERRUPTED interrupted wait for the next packet due to timeout, signal or external socket callback (timeout value is %1)
+This debug message is issued when the server intrrupts waiting
+for reception of the next DHCPv6 message due to timeout, signal
+or reception of the data over socket other than used for DHCPv6
+message transmission. The server will now handle signals
+received and ready timers before waiting for next packets again.
+The argument specifies the timeout value in milliseconds.
+
+% DHCP6_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.
+
 % DHCP6_CCSESSION_STARTED control channel session started on socket %1
 A debug message issued during startup after the IPv6 DHCP server has
 successfully established a session with the Kea control channel.
@@ -31,11 +77,6 @@ to establish a session with the Kea control channel.
 This debug message informs that incoming packet has been assigned to specified
 class or classes. This is a norma
 
-% DHCP6_CLIENTID_MISSING mandatory client-id option is missing, message from %1 dropped
-This error message indicates that the received message is being dropped
-because it does not include the mandatory client-id option necessary for
-address assignment.  The most likely cause is a problem with the client.
-
 % DHCP6_COMMAND_RECEIVED received command %1, arguments: %2
 A debug message listing the command (and possible arguments) received
 from the Kea control system by the IPv6 DHCP server.
@@ -83,37 +124,82 @@ lease and other information.
 This debug message is logged when the new Name Change Request has been created
 to perform the DNS Update, which adds new RRs.
 
-% DHCP6_DDNS_CREATE_REMOVE_NAME_CHANGE_REQUEST created name change request: %1
+% DHCP6_DDNS_CREATE_REMOVE_NAME_CHANGE_REQUEST %1: created name change request: %2
 This debug message is logged when the new Name Change Request has been created
-to perform the DNS Update, which removes RRs from the DNS.
+to perform the DNS Update, which removes RRs from the DNS. The first argument
+includes the client and transaction identification information. The second
+argument specifies the details of the generated name change request.
+
+% DHCP6_DDNS_FQDN_GENERATED %1: generated FQDN for the client: %2
+This debug message is logged when the server generated FQDN (name)
+for the client which message is processed. The names may be
+generated by the server when required by the server's policy or
+when the client doesn't provide any specific FQDN in its message
+to the server. The first argument includes the client and
+transaction identification information. The second argument includes
+the generated FQDN.
+
+% DHCP6_DDNS_GENERATED_FQDN_UPDATE_FAIL %1: failed to update the lease using address %2, after generating FQDN for a client, reason: %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 first argument includes the client and the
+transaction identification information. The second argument is a leased
+address. The third argument includes the reason for the failure.
 
-% DHCP6_DDNS_LEASE_ASSIGN_FQDN_CHANGE FQDN for the allocated lease: %1 has changed. New values: hostname = %2, reverse mapping = %3, forward mapping = %4
+% DHCP6_DDNS_LEASE_ASSIGN_FQDN_CHANGE FQDN %1: FQDN for the allocated lease: %2 has changed. New values: hostname = %3, reverse mapping = %4, forward mapping = %5
 This debug message is logged when FQDN mapping for a particular lease has
 been changed by the recent Request message. This mapping will be changed in DNS.
+The first argument includes the client and the transaction identification
+information. The second argument holds the details about the lease for which
+the FQDN information and/or mappings have changed. The remaining arguments
+hold the new FQDN information and flags for mappings.
 
-% DHCP6_DDNS_LEASE_RENEW_FQDN_CHANGE FQDN for the renewed lease: %1 has changed. New values: hostname = %2, reverse mapping = %3, forward mapping = %4
+% DHCP6_DDNS_LEASE_RENEW_FQDN_CHANGE FQDN %1: FQDN for the renewed lease: %2 has changed. New values: hostname = %3, reverse mapping = %4, forward mapping = %5
 This debug message is logged when FQDN mapping for a particular lease has been
 changed by the recent Renew message. This mapping will be changed in DNS.
+The first argument includes the client and the transaction identification
+information. The second argument holds the details about the lease for which
+the FQDN information and/or mappings have changed. The remaining arguments
+hold the new FQDN information and flags for mappings.
 
-% DHCP6_DDNS_RECEIVE_FQDN received DHCPv6 Client FQDN Option: %1
+% DHCP6_DDNS_RECEIVE_FQDN %1: received DHCPv6 Client FQDN option: %2
 This debug message is logged when server has found the DHCPv6 Client FQDN Option
-sent by a client and started processing it.
+sent by a client and started processing it. The first argument includes the
+client and transaction identification information. The second argument
+includes the received FQDN.
 
-% DHCP6_DDNS_REMOVE_INVALID_HOSTNAME invalid FQDN: %1 for the lease: %2 when removing DNS bindings
+% DHCP6_DDNS_REMOVE_INVALID_HOSTNAME %1: invalid FQDN %2 for the lease: %3 when removing DNS bindings
 This error message is issued when a lease being deleted contains an indication
 that the DNS Update has been performed for it, but the FQDN held in the lease
 database has invalid format and can't be transformed to the canonical on-wire
-format.
+format. The first argument includes the client and transaction identification
+information.
 
 % DHCP6_DDNS_REQUEST_SEND_FAILED failed sending a request to kea-dhcp-ddns, error: %1,  ncr: %2
 This error message indicates that IPv6 DHCP server failed to send a DDNS
 update reqeust to the DHCP-DDNS server. This is most likely a configuration or
 networking error.
 
+% DHCP6_DDNS_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.
+
 % DHCP6_DDNS_SEND_FQDN sending DHCPv6 Client FQDN Option to the client: %1
 This debug message is logged when server includes an DHCPv6 Client FQDN Option
 in its response to the client.
 
+% DHCP6_DDNS_SKIP_REMOVE_NAME_CHANGE_REQUEST %1: name change request creation skipped for lease: %2
+This debug message is logged when the server determines that removal
+name change request should not be sent to the DNS, because the DNS
+updates are disabled on the DHCP server, or no DNS update has been
+performed for the processed lease. The first argument includes the
+client and the transaction identification information. The second
+argument provides the details of the lease.
+
 % DHCP6_DEACTIVATE_INTERFACE deactivate interface %1
 This message is printed when DHCPv6 server disables an interface from being
 used to receive DHCPv6 traffic. Sockets on this interface will not be opened
@@ -127,19 +213,7 @@ as a result of receiving SIGHUP signal.
 This is an error message logged when the dynamic reconfiguration of the
 DHCP server failed.
 
-% DHCP6_EXTEND_LEASE_SUBNET_SELECTED the %1 subnet was selected for client extending its lease
-This is a debug message informing that a given subnet was selected. It will
-be used for extending lifetime of the lease. This is one of the early steps
-in the processing of incoming client message.
-
-% DHCP6_EXTEND_LEASE_SUBNET_SELECT_FAILED failed to select a subnet for received %1: src=%2 type=%3
-This warning message is output when a Renew or Rebind was received from a
-subnet for which the DHCPv6 server has not been configured. The cause is
-most likely due to a misconfiguration of the server. The packet processing
-will continue, but the response will only contain generic configuration
-parameters and no addresses or prefixes.
-
-% DHCP6_EXTEND_NA_UNKNOWN received unknown IA_NA from client (duid=%1, iaid=%2) in subnet %3
+% DHCP6_EXTEND_NA_UNKNOWN %1: received unknown IA_NA with iaid=%2 in subnet %3
 This warning message is printed when client attempts to extend the lease
 for the address (in the IA_NA option) but no such lease is known by the server.
 It typically means that client has attempted to use its lease past its
@@ -147,6 +221,9 @@ lifetime: causes of this include a adjustment of the client's date/time
 setting or poor support on the client for sleep/recovery. A properly
 implemented client will recover from such a situation by restarting the
 lease allocation process after receiving a negative reply from the server.
+The first argument includes the client and the transaction identification
+information. The second argument holds IAID. The third argument holds the
+subnet information.
 
 An alternative cause could be that the server has lost its database
 recently and does not recognize its well-behaving clients. This is more
@@ -154,96 +231,67 @@ probable if you see many such messages. Clients will recover from this,
 but they will most likely get a different IP addresses and experience
 a brief service interruption.
 
-% DHCP6_EXTEND_NA_UNKNOWN_SUBNET %1 message received from client on unknown subnet (duid=%2, iaid=%3)
-A warning message indicating that a client is attempting to extend lease lifetime
-for the address, but the server does not have any information about the subnet this
-client belongs to. This may mean that faulty the mobile client changed its location
-and is trying to renew its old address (client is supposed to send confirm, not renew
-in such cases, according to RFC3315) or the server configuration has changed and
-information about existing subnet was removed. Note that in a sense this is worse
-case of DHCP6_EXTEND_NA_UNKNOWN, as not only the lease is unknown, but also the subnet
-is. Depending on the reasons of this condition, it may or may not correct on its own.
-
-% DHCP6_EXTEND_PD_NO_BINDING client sent a %1 message to extend lifetimes of prefixes for an unknown binding: duid=%2, iaid=%3, subnet=%4
-This warning message is logged when a client attempts to extend the lifetime of the
-prefix it is using, but the server was unable to find the binding to which
-this lease belongs. This error condition has different implications for the
-Renew and Rebind messages. For the former, the server will respond with NoBinding
-status code. For the latter, the server will discard the message.
-
-% DHCP6_EXTEND_PD_UNKNOWN_SUBNET %1 message received from client on unknown subnet (duid=%2, iaid=%3)
-A warning message indicating that a client is attempting to extend lease lifetime
-for the prefix, but the server doesn't have any information about the subnet this
-client belongs to.
-
 % DHCP6_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.
 
-% DHCP6_HOOK_BUFFER_RCVD_SKIP received DHCPv6 buffer was dropped because a callout set the skip flag
+% DHCP6_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 buffer6_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.
 
-% DHCP6_HOOK_BUFFER_SEND_SKIP prepared DHCPv6 response was dropped because a callout set the skip flag
+% DHCP6_HOOK_BUFFER_SEND_SKIP %1: prepared DHCPv6 response was dropped because a callout set the skip flag
 This debug message is printed when a callout installed on buffer6_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.
+The argument includes the client and transaction identification
+information.
 
-% DHCP6_HOOK_LEASE6_EXTEND_SKIP DHCPv6 lease lifetime was not extended because a callout set the skip flag for message %1
-or lease6_rebind hook point set the skip flag. For this particular hook
-point, the setting of the flag by a callout instructs the server to not
-extend the lifetime for a lease. If client requested renewal of multiples
-leases (by sending multiple IA options), the server will skip the renewal
-of the one in question and will proceed with other renewals as usual.
-
-% DHCP6_HOOK_LEASE6_RELEASE_NA_SKIP DHCPv6 address lease was not released because a callout set the skip flag
+% DHCP6_HOOK_LEASE6_RELEASE_NA_SKIP %1: DHCPv6 address lease was not released because a callout set the skip flag
 This debug message is printed when a callout installed on the
 lease6_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. If a client requested the release of multiples leases
 (by sending multiple IA options), the server will retain this particular
-lease and proceed with other releases as usual.
+lease and proceed with other releases as usual. The argument holds the
+client and transaction identification information.
 
-% DHCP6_HOOK_LEASE6_RELEASE_PD_SKIP DHCPv6 prefix lease was not released because a callout set the skip flag
+% DHCP6_HOOK_LEASE6_RELEASE_PD_SKIP %1: prefix lease was not released because a callout set the skip flag
 This debug message is printed when a callout installed on lease6_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. If client requested release of multiples leases (by sending
 multiple IA options), the server will retains this particular lease and
-will proceed with other renewals as usual.
-
-% DHCP6_HOOK_LEASE6_RENEW_SKIP DHCPv6 lease was not renewed because a callout set the skip flag
-This debug message is printed when a callout installed on lease6_renew
-hook point set the skip flag. For this particular hook point, the setting
-of the flag by a callout instructs the server to not renew a lease. If
-client requested renewal of multiples leases (by sending multiple IA
-options), the server will skip the renewal of the one in question and
-will proceed with other renewals as usual.
+will proceed with other renewals as usual. The argument holds the
+client and transaction identification information.
 
-% DHCP6_HOOK_PACKET_RCVD_SKIP received DHCPv6 packet was dropped because a callout set the skip flag
+% DHCP6_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 pkt6_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.
+hook point sets the skip flag. For this particular hook point, the
+setting of the flag instructs the server to drop the packet.
 
-% DHCP6_HOOK_PACKET_SEND_SKIP prepared DHCPv6 response was not sent because a callout set the skip flag
+% DHCP6_HOOK_PACKET_SEND_SKIP %1: prepared DHCPv6 response was not sent because a callout set the skip flag
 This debug message is printed when a callout installed on the pkt6_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. This
 effectively 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).
+allocated a lease). The argument specifies the client and transaction
+identification information.
 
-% DHCP6_HOOK_SUBNET6_SELECT_SKIP no subnet was selected because a callout set the skip flag
+% DHCP6_HOOK_SUBNET6_SELECT_SKIP %1: no subnet was selected because a callout set the skip flag
 This debug message is printed when a callout installed on the
 subnet6_select hook point set 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 or prefixes
-will be assigned.
+will be assigned. The argument holds the client and transaction
+identification information.
 
 % DHCP6_INIT_FAIL failed to initialize Kea server: %1
 The server has failed to establish communication with the rest of Kea,
@@ -251,28 +299,42 @@ failed to read JSON configuration file or excountered any other critical
 issue that prevents it from starting up properly. Attached error message
 provides more details about the issue.
 
-% DHCP6_LEASE_ADVERT address lease %1 advertised (client duid=%2, iaid=%3)
-This debug message indicates that the server successfully advertised
-an address lease. It is up to the client to choose one server out of the
-advertised servers and continue allocation with that server. This
-is a normal behavior and indicates successful operation.
+% DHCP6_LEASE_ADVERT %1: lease for address %2 and iaid=%3 will be advertised
+This debug message indicates that the server will advertise an
+address to the client in the ADVERTISE message. The client will
+request allocation of this address with the REQUEST message sent
+in the next message exchange. The first argument includes the client
+and transaction identification information. The remaining arguments
+hold the allocated address and IAID.
 
-% DHCP6_LEASE_ADVERT_FAIL failed to advertise an address lease for client duid=%1, iaid=%2
+% DHCP6_LEASE_ADVERT_FAIL %1: failed to advertise an address lease for iaid=%2
 This message indicates that in response to a received SOLICIT, the server
 failed to advertise a non-temporary lease for a given client. There may
 be many reasons for such failure. Each failure is logged in a separate
-log entry.
+log entry. The first argument holds the client and transaction identification
+information. The second argument holds the IAID.
 
-% DHCP6_LEASE_ALLOC address lease %1 has been allocated (client duid=%2, iaid=%3)
+% DHCP6_LEASE_ALLOC %1: lease for address %2 and iaid=%3 has been allocated
 This debug message indicates that in response to a client's REQUEST
 message, the server successfully granted an non-temporary address
 lease. This is a normal behavior and indicates successful operation.
+The first argument includes the client and transaction identification
+information. The remaining arguments hold the allocated address and
+IAID.
 
-% DHCP6_LEASE_ALLOC_FAIL failed to grant an address lease for client duid=%1, iaid=%2
+% DHCP6_LEASE_ALLOC_FAIL %1: failed to grant an address lease for iaid=%2
 This message indicates that in response to a received REQUEST, the server
 failed to grant a non-temporary address lease for the client. There may
 be many reasons for such failure. Each failure is logged in a separate
-log entry.
+log entry. The first argument holds the client and transaction identification
+information. The second argument holds the IAID.
+
+% DHCP6_LEASE_DATA %1: detailed lease information for iaid=%2: %3
+This debug message is used to print the detailed information about the
+allocated lease or a lease which will be advertised to the client.
+The first argument holds the client and the transaction identification
+information. The second argument holds the IAID. The third argument
+holds the detailed lease information.
 
 % DHCP6_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
@@ -281,24 +343,24 @@ 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.
 
-% DHCP6_LEASE_NA_WITHOUT_DUID address lease for address %1 does not have a DUID
+% DHCP6_LEASE_NA_WITHOUT_DUID %1: address lease for address %2 does not have a DUID
 This error message indicates a database consistency problem. The lease
 database has an entry indicating that the given address is in use,
 but the lease does not contain any client identification. This is most
 likely due to a software error: please raise a bug report. As a temporary
-workaround, manually remove the lease entry from the database.
+workaround, manually remove the lease entry from the database. The first
+argument includes the client and transaction identification information.
+The second argument holds the address to be released.
 
-% DHCP6_LEASE_PD_WITHOUT_DUID prefix lease for address %1 does not have a DUID
+% DHCP6_LEASE_PD_WITHOUT_DUID %1: lease for prefix %2/%3 does not have a DUID
 This error message indicates a database consistency failure. The lease
 database has an entry indicating that the given prefix is in use,
 but the lease does not contain any client identification. This is most
 likely due to a software error: please raise a bug report. As a temporary
-workaround, manually remove the lease entry from the database.
-
-% DHCP6_NAME_GEN_UPDATE_FAIL failed to update the lease using address %1, after generating FQDN for a client, reason: %2
-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.
+workaround, manually remove the lease entry from the database. The
+first argument includes client and transaction identification
+information. The second and third argument hold the prefix and the
+prefix length.
 
 % DHCP6_NOT_RUNNING IPv6 DHCP server is not running
 A warning message is issued when an attempt is made to shut down the
@@ -321,26 +383,33 @@ 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.
 
-% DHCP6_PACKET_MISMATCH_SERVERID_DROP dropping packet %1 (transid=%2, interface=%3) having mismatched server identifier
+% DHCP6_PACKET_DROP_PARSE_FAIL 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.
+
+% DHCP6_PACKET_DROP_SERVERID_MISMATCH %1: dropping packet with server identifier: %2, server is using: %3
 A debug message noting that server has received message with server identifier
 option that not matching server identifier that server is using.
 
-% DHCP6_PACKET_PARSE_FAIL failed to parse incoming packet: %1
-The DHCPv6 server has received a packet that it is unable to interpret.
-There may be many causes: truncated header, truncated or malformed option,
-trailing padding that contains garbage etc. More information is specified
-as a parameter.
+% DHCP6_PACKET_DROP_UNICAST %1: dropping unicast %2 packet as this packet should be sent to multicast
+This debug message is issued when the server drops the unicast packet,
+because packets of this type must be sent to multicast. The first argument
+specifies the client and transaction identification information, the
+second argument specifies packet type.
 
 % DHCP6_PACKET_PROCESS_FAIL processing of %1 message received from %2 failed: %3
 This is a general catch-all message indicating that the processing of the
 specified packet type from the indicated address failed.  The reason is given in the
 message.  The server will not send a response but will instead ignore the packet.
 
-% DHCP6_PACKET_RECEIVED %1 packet received
-A debug message noting that the server has received the specified type
-of packet.  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).
+% DHCP6_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. The first argument specifies the
+client and transaction identification information. The second and third
+argument specify the name of the DHCPv6 message and its numeric type
+respectively. The remaining arguments specify the source address,
+destination IP address and the name of the interface on which the
+message has been received.
 
 % DHCP6_PACKET_RECEIVE_FAIL error on attempt to receive packet: %1
 The IPv6 DHCP server tried to receive a packet but an error
@@ -394,96 +463,142 @@ 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.
 
-% DHCP6_PD_LEASE_ADVERT prefix lease %1/%2 advertised (client duid=%3, iaid=%4)
-This debug message indicates that the server successfully advertised
-a prefix lease. It is up to the client to choose one server out of the
-advertised servers and continue allocation with that server. This
-is a normal behavior and indicates successful operation.
+% DHCP6_PD_LEASE_ADVERT %1: lease for prefix %2/%3 and iaid=%4 will be advertised
+This debug message indicates that the server will advertise a
+prefix to the client in the ADVERTISE message. The client will
+request allocation of this prefix with the REQUEST message sent
+in the next message exchange. The first argument includes the client
+and transaction identification information. The remaining arguments
+hold the allocated prefix, prefix length and IAID.
 
-% DHCP6_PD_LEASE_ADVERT_FAIL failed to advertise a prefix lease for client duid=%1, iaid=%2
+% DHCP6_PD_LEASE_ADVERT_FAIL %1: failed to advertise a prefix lease for iaid=%2
 This message indicates that in response to a received SOLICIT, the
-server failed to advertise a prefix lease for the client. There may
+server failed to advertise a prefix lease for a given client. There may
 be many reasons for such failure. Each failure is logged in a separate
-log entry.
+log entry. The first argument holds the client and transaction identification
+information. The second argument holds the IAID.
 
-% DHCP6_PD_LEASE_ALLOC prefix lease %1/%2 has been allocated (client duid=%3, iaid=%4)
+% DHCP6_PD_LEASE_ALLOC %1: lease for prefix %2/%3 and iaid=%4 has been allocated
 This debug message indicates that in response to a client's REQUEST
-message, the server successfully granted a prefix delegation lease. This
-is a normal behavior and indicates successful operation.
-
-% DHCP6_PD_LEASE_ALLOC_FAIL failed to grant a prefix lease for client duid=%1, iaid=%2
-This message indicates that the server failed to grant (in response to
-received REQUEST) a prefix lease for a given client. There may be many reasons
-for such failure. Each failure is logged in a separate log entry.
+message, the server successfully granted an non-temporary address
+lease. This is a normal behavior and indicates successful operation.
+The first argument includes the client and transaction identification
+information. The remaining arguments hold the allocated prefix,
+prefix lenngth and and IAID.
 
-% DHCP6_PROCESS_IA_NA_REQUEST server is processing IA_NA option (duid=%1, iaid=%2, hint=%3)
+% DHCP6_PD_LEASE_ALLOC_FAIL %1: failed to grant a prefix lease for iaid=%2
+This message indicates that in response to a received REQUEST, the server
+failed to grant a prefix lease for the client. There may be many reasons
+for such failure. Each failure is logged in a separate log entry. The first
+argument holds the client and transaction identification information.
+The second argument holds the IAID.
+
+% DHCP6_PROCESS_IA_NA_EXTEND %1: extending lease lifetime for IA_NA option with iaid=%2
+This message is logged when the server is starting to extend the lifetime
+of the address lease associated with the particular IAID. The first argument
+includes the client and transaction identification information. The second
+argument contains the IAID.
+
+% DHCP6_PROCESS_IA_NA_RELEASE %1: releasing lease for IA_NA option with iaid=%2
+This message is logged when the server is trying to release the client's
+as a result of receiving the RELEASE message. The first argument
+includes the client and transaction identification information. The second
+argument contains the IAID.
+
+% DHCP6_PROCESS_IA_NA_REQUEST %1: server is processing IA_NA option with iaid=%2 and hint=%3
 This is a debug message that indicates the processing of a received
-IA_NA option. It may optionally contain an address that may be used by
-the server as a hint for possible requested address.
-
-% DHCP6_PROCESS_IA_PD_REQUEST server is processing IA_PD option (duid=%1, iaid=%2, hint=%3)
+IA_NA option. The first argument contains the client and the transaction
+identification information. The second argument holds the IAID of the
+IA_NA option. The third argument may hold the hint for the server
+about the address that the client would like to have allocated.
+If there is no hint, the argument should provide the text indicating
+that the hint hasn't been sent.
+
+% DHCP6_PROCESS_IA_PD_EXTEND %1: extending lease lifetime for IA_PD option with iaid=%2
+This message is logged when the server is starting to extend the lifetime
+of the prefix lease associated with the particular IAID. The first argument
+includes the client and transaction identification information. The second
+argument contains the IAID.
+
+% DHCP6_PROCESS_IA_PD_REQUEST %1: server is processing IA_PD option with iaid=%2 and hint=%3
 This is a debug message that indicates a processing of received IA_PD
-option. It may optionally contain an prefix that may be used by the server
-as a hint for possible requested prefix.
-
-% DHCP6_QUERY_DATA received packet length %1, data length %2, data is %3
-A debug message listing the data received from the client or relay.
-
-% DHCP6_RELEASE_MISSING_CLIENTID client (address=%1) sent RELEASE message without mandatory client-id
-This warning message indicates that client sent RELEASE message without
-mandatory client-id option. This is most likely caused by a buggy client
-(or a relay that malformed forwarded message). This request will not be
-processed and a response with error status code will be sent back.
-
-% DHCP6_RELEASE_NA address %1 belonging to client duid=%2, iaid=%3 was released properly
+option. The first argument contains the client and the transaction
+identification information. The second argument holds the IAID of the
+IA_PD option. The third argument may hold the hint for the server
+about the prefix that the client would like to have allocated.
+If there is no hint, the argument should provide the text indicating
+that the hint hasn't been sent.
+
+% DHCP6_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.
+
+% DHCP6_RELEASE_NA %1: binding for address %2 and iaid=%3 was released properly
 This debug message indicates that an address was released properly. It
 is a normal operation during client shutdown.
 
-% DHCP6_RELEASE_NA_FAIL failed to remove address lease for address %1 for duid=%2, iaid=%3
+% DHCP6_RELEASE_NA_FAIL %1: failed to remove address lease for address %2 and iaid=%3
 This error message indicates that the software failed to remove an address
 lease from the lease database.  It 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.
+removed from the database during RELEASE message processing. The first
+argument holds the client and transaction identification information.
+The second and third argument hold the released address and IAID
+respectively.
 
-% DHCP6_RELEASE_NA_FAIL_WRONG_DUID client (duid=%1) tried to release address %2, but it belongs to another client (duid=%3)
+% DHCP6_RELEASE_NA_FAIL_WRONG_DUID %1: client tried to release address %2, but it belongs to another client using duid=%3
 This warning message indicates that a 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.
 
-% DHCP6_RELEASE_NA_FAIL_WRONG_IAID client (duid=%1) tried to release address %2, but it used wrong IAID (expected %3, but got %4)
+% DHCP6_RELEASE_NA_FAIL_WRONG_IAID %1: client tried to release address %2, but it used wrong IAID (expected %3, but got %4)
 This warning message indicates that client tried to release an address
 that does belong to it, but the address was expected to be in a different
 IA (identity association) container. This probably means that the client's
 support for multiple addresses is flawed.
 
-% DHCP6_RELEASE_PD prefix %1 belonging to client duid=%2, iaid=%3 was released properly
+% DHCP6_RELEASE_PD %1: prefix %2/%3 for iaid=%4 was released properly
 This debug message indicates that a prefix was released properly. It
-is a normal operation during client shutdown.
+is a normal operation during client shutdown. The first argument holds
+the client and transaction identification information. The second and
+third argument define the prefix and its length. The fourth argument
+holds IAID.
 
-% DHCP6_RELEASE_PD_FAIL failed to remove prefix lease for address %1 for duid=%2, iaid=%3
+% DHCP6_RELEASE_PD_FAIL %1: failed to release prefix %2/%3 for iaid=%4
 This error message indicates that the software failed to remove a prefix
 lease from the lease database.  It 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.
+removed from the database during RELEASE message processing. The
+first argument hold the client and transaction identification
+information. The second and third argument define the prefix and
+its length. The fourth argument holds the IAID.
 
-% DHCP6_RELEASE_PD_FAIL_WRONG_DUID client (duid=%1) tried to release prefix %2, but it belongs to another client (duid=%3)
+% DHCP6_RELEASE_PD_FAIL_WRONG_DUID %1: client tried to release prefix %2/%3, but it belongs to another client (duid=%4)
 This warning message indicates that client tried to release a prefix
 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 prefix will stop using it anyway, there
-is a good chance that the situation will correct itself.
+is a good chance that the situation will correct itself. The first
+argument includes the client and the transaction identification
+information. The second and third argument include the prefix and
+prefix length. The last argument holds the DUID of the client holding
+the lease.
 
-% DHCP6_RELEASE_PD_FAIL_WRONG_IAID client (duid=%1) tried to release prefix %2, but it used wrong IAID (expected %3, but got %4)
+% DHCP6_RELEASE_PD_FAIL_WRONG_IAID %1: client tried to release prefix %2/%3, but it used wrong IAID (expected %4, but got %5)
 This warning message indicates that client tried to release a prefix
 that does belong to it, but the address was expected to be in a different
 IA (identity association) container. This probably means that the client's
-support for multiple prefixes is flawed.
+support for multiple prefixes is flawed. The first argument includes the
+client and transaction identification information. The second and third
+argument identify the prefix. The fourth and fifth argument hold the
+expected IAID and IAID found respectively.
 
 % DHCP6_REQUIRED_OPTIONS_CHECK_FAIL %1 message received from %2 failed the following check: %3
 This message indicates that received DHCPv6 packet is invalid.  This may be due
@@ -565,17 +680,26 @@ This is a debug message issued during the IPv6 DHCP server startup.
 It lists some information about the parameters with which the server
 is running.
 
-% DHCP6_SUBNET_SELECTED the %1 subnet was selected for client assignment
-This is a debug message informing that a given subnet was selected. It will
-be used for address and option assignment. This is one of the early steps
-in the processing of incoming client message.
-
-% DHCP6_SUBNET_SELECTION_FAILED failed to select a subnet for incoming packet, src=%1 type=%2
-This warning message is output when a packet was received from a subnet for
-which the DHCPv6 server has not been configured. The cause is most likely due
-to a misconfiguration of the server. The packet processing will continue, but
-the response will only contain generic configuration parameters and no
-addresses or prefixes.
+% DHCP6_SUBNET_DATA %1: the selected subnet details: %2
+This debug message includes the details of the subnet selected for
+the client. The first argument includes the client and the
+transaction identification information. The second argument
+includes the subnet details.
+
+% DHCP6_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. The first
+argument includes the client and the transaction identification
+information. The second argument holds the selected subnet id.
+
+% DHCP6_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 cause is likely due to a misconfiguration of the server. The packet
+processing will continue, but the response will only contain generic
+configuration and no addresses or prefixes. The argument includes
+the client and the transaction identification information.
 
 % DHCP6_UNKNOWN_MSG_RECEIVED received unknown message (type %d) on interface %2
 This debug message is printed when server receives a message of unknown type.
@@ -583,14 +707,3 @@ That could either mean missing functionality or invalid or broken relay or clien
 The list of formally defined message types is available here:
 http://www.iana.org/assignments/dhcpv6-parameters.
 
-% DHCP6_UNKNOWN_RELEASE_NA received RELEASE from unknown client (IA_NA, duid=%1, iaid=%2)
-This warning message is printed when client attempts to release an address
-lease, but no such lease is known by the server. See the explanation
-of the status code DHCP6_UNKNOWN_RENEW_NA for possible reasons for
-such behavior.
-
-% DHCP6_UNKNOWN_RELEASE_PD received RELEASE from unknown client (IA_PD, duid=%1, iaid=%2)
-This warning message is printed when client attempts to release an prefix
-lease, but no such lease is known by the server. See the explanation
-of the status code DHCP6_UNKNOWN_RENEW_PD for possible reasons for
-such behavior.

Fichier diff supprimé car celui-ci est trop grand
+ 340 - 290
src/bin/dhcp6/dhcp6_srv.cc


+ 7 - 16
src/bin/dhcp6/dhcp6_srv.h

@@ -255,13 +255,6 @@ protected:
     /// @return Reply message to be sent to the client.
     Pkt6Ptr processInfRequest(const Pkt6Ptr& inf_request);
 
-    /// @brief Creates status-code option.
-    ///
-    /// @param code status code value (see RFC3315)
-    /// @param text textual explanation (will be sent in status code option)
-    /// @return status-code option
-    OptionPtr createStatusCode(uint16_t code, const std::string& text);
-
     /// @brief Selects a subnet for a given client's packet.
     ///
     /// @param question client's message
@@ -530,9 +523,12 @@ protected:
     /// own.
     /// If ddns updates are disabled, this method returns immediately.
     ///
+    /// @param query A pointer to the packet sent by the client for which the
+    /// name change request should be sent.
     /// @param lease A lease for which the the removal of corresponding DNS
     /// records will be performed.
-    void createRemovalNameChangeRequest(const Lease6Ptr& lease);
+    void createRemovalNameChangeRequest(const Pkt6Ptr& query,
+                                        const Lease6Ptr& lease);
 
     /// @brief Attempts to extend the lifetime of IAs.
     ///
@@ -728,21 +724,16 @@ private:
     /// If there are any differences (different fwd or rev flags, or different
     /// hostname) a DNS update for removing entry will be generated.
     ///
+    /// @param query a pointer to the client's message
     /// @param old_lease old version of the lease
     /// @param new_lease new version of the lease (may be NULL)
     /// @param hostname specifies hostname (for printing purposes)
     /// @param do_fwd specifies if reverse updates are enabled (for printing purposes)
     /// @param do_rev specifies if reverse updates are enabled (for printing purposes)
-    void conditionalNCRRemoval(Lease6Ptr& old_lease, Lease6Ptr& new_lease,
-                               const std::string& hostname,
+    void conditionalNCRRemoval(const Pkt6Ptr& query, Lease6Ptr& old_lease,
+                               Lease6Ptr& new_lease, const std::string& hostname,
                                bool do_fwd, bool do_rev);
 
-    /// @brief Utility method that extracts DUID from client-id option
-    ///
-    /// @param pkt the message that contains client-id option
-    /// @return extracted DUID (or NULL if client-id is missing)
-    DuidPtr extractClientId(const Pkt6Ptr& pkt);
-
     /// @brief Allocation Engine.
     /// Pointer to the allocation engine that we are currently using
     /// It must be a pointer, because we will support changing engines

+ 7 - 6
src/bin/dhcp6/tests/dhcp6_client.cc

@@ -17,6 +17,7 @@
 #include <dhcp/option_custom.h>
 #include <dhcp/option6_ia.h>
 #include <dhcp/option6_iaaddr.h>
+#include <dhcp/option6_status_code.h>
 #include <dhcp/option_int_array.h>
 #include <dhcp/pkt6.h>
 #include <dhcpsrv/lease.h>
@@ -143,10 +144,10 @@ Dhcp6Client::applyRcvdConfiguration(const Pkt6Ptr& reply) {
                 {
                     // Check if the server has sent status code. If no status
                     // code, assume the status code to be 0.
-                    OptionCustomPtr status_code = boost::dynamic_pointer_cast<
-                        OptionCustom>(ia->getOption(D6O_STATUS_CODE));
+                    Option6StatusCodePtr status_code = boost::dynamic_pointer_cast<
+                        Option6StatusCode>(ia->getOption(D6O_STATUS_CODE));
                     lease_info.status_code_ =
-                        status_code ? status_code->readInteger<uint16_t>(0) : 0;
+                        status_code ? status_code->getStatusCode() : 0;
                 }
                 break;
 
@@ -159,13 +160,13 @@ Dhcp6Client::applyRcvdConfiguration(const Pkt6Ptr& reply) {
     }
 
     // Get the global status code.
-    OptionCustomPtr status_code = boost::dynamic_pointer_cast<
-        OptionCustom>(reply->getOption(D6O_STATUS_CODE));
+    Option6StatusCodePtr status_code = boost::dynamic_pointer_cast<
+        Option6StatusCode>(reply->getOption(D6O_STATUS_CODE));
     // If status code has been sent, we override the default status code:
     // Success and record that we have received the status code.
     if (status_code) {
         config_.received_status_code_ = true;
-        config_.status_code_ = status_code->readInteger<uint16_t>(0);
+        config_.status_code_ = status_code->getStatusCode();
     }
 }
 

+ 0 - 24
src/bin/dhcp6/tests/dhcp6_srv_unittest.cc

@@ -1019,30 +1019,6 @@ TEST_F(Dhcpv6SrvTest, pdReleaseReject) {
     testReleaseReject(Lease::TYPE_PD, IOAddress("2001:db8:1:2::"));
 }
 
-// This test verifies if the status code option is generated properly.
-TEST_F(Dhcpv6SrvTest, StatusCode) {
-    NakedDhcpv6Srv srv(0);
-
-    // a dummy content for client-id
-    uint8_t expected[] = {
-        0x0, 0xD, // option code = 13
-        0x0, 0x7, // option length = 7
-        0x0, 0x3, // status code = 3
-        0x41, 0x42, 0x43, 0x44, 0x45 // string value ABCDE
-    };
-    // Create the option.
-    OptionPtr status = srv.createStatusCode(3, "ABCDE");
-    // Allocate an output buffer. We will store the option
-    // in wire format here.
-    OutputBuffer buf(sizeof(expected));
-    // Prepare the wire format.
-    ASSERT_NO_THROW(status->pack(buf));
-    // Check that the option buffer has valid length (option header + data).
-    ASSERT_EQ(sizeof(expected), buf.getLength());
-    // Verify the contents of the option.
-    EXPECT_EQ(0, memcmp(expected, buf.getData(), sizeof(expected)));
-}
-
 // This test verifies if the sanityCheck() really checks options presence.
 TEST_F(Dhcpv6SrvTest, sanityCheck) {
     NakedDhcpv6Srv srv(0);

+ 4 - 3
src/bin/dhcp6/tests/dhcp6_test_utils.cc

@@ -14,6 +14,7 @@
 
 #include <config.h>
 #include <gtest/gtest.h>
+#include <dhcp/option6_status_code.h>
 #include <dhcp6/tests/dhcp6_test_utils.h>
 #include <dhcp6/json_config_parser.h>
 #include <util/pointer_util.h>
@@ -832,8 +833,8 @@ NakedDhcpv6SrvTest::checkIA_NAStatusCode(
     EXPECT_EQ(expected_t1, ia->getT1());
     EXPECT_EQ(expected_t2, ia->getT2());
 
-    isc::dhcp::OptionCustomPtr status =
-        boost::dynamic_pointer_cast<isc::dhcp::OptionCustom>
+    isc::dhcp::Option6StatusCodePtr status =
+        boost::dynamic_pointer_cast<isc::dhcp::Option6StatusCode>
         (ia->getOption(D6O_STATUS_CODE));
 
     // It is ok to not include status success as this is the default
@@ -850,7 +851,7 @@ NakedDhcpv6SrvTest::checkIA_NAStatusCode(
         // status code option content is just a text explanation
         // what went wrong.
         EXPECT_EQ(static_cast<uint16_t>(expected_status_code),
-                  status->readInteger<uint16_t>(0));
+                  status->getStatusCode());
     }
 }
 

+ 4 - 4
src/bin/dhcp6/tests/dhcp6_test_utils.h

@@ -25,6 +25,7 @@
 #include <dhcp/option6_ia.h>
 #include <dhcp/option6_iaaddr.h>
 #include <dhcp/option6_iaprefix.h>
+#include <dhcp/option6_status_code.h>
 #include <dhcp/option_int_array.h>
 #include <dhcp/option_custom.h>
 #include <dhcp/option.h>
@@ -101,7 +102,6 @@ public:
     using Dhcpv6Srv::processClientFqdn;
     using Dhcpv6Srv::createNameChangeRequests;
     using Dhcpv6Srv::createRemovalNameChangeRequest;
-    using Dhcpv6Srv::createStatusCode;
     using Dhcpv6Srv::selectSubnet;
     using Dhcpv6Srv::testServerID;
     using Dhcpv6Srv::testUnicast;
@@ -256,8 +256,8 @@ public:
     void checkMsgStatusCode(const isc::dhcp::Pkt6Ptr& msg,
                             uint16_t expected_status)
     {
-        isc::dhcp::OptionCustomPtr status =
-            boost::dynamic_pointer_cast<isc::dhcp::OptionCustom>
+        isc::dhcp::Option6StatusCodePtr status =
+            boost::dynamic_pointer_cast<isc::dhcp::Option6StatusCode>
                 (msg->getOption(D6O_STATUS_CODE));
 
         // It is ok to not include status success as this is the default
@@ -273,7 +273,7 @@ public:
             // status code option content is just a text explanation
             // what went wrong.
             EXPECT_EQ(static_cast<uint16_t>(expected_status),
-                      status->readInteger<uint16_t>(0));
+                      status->getStatusCode());
         }
     }
 

+ 15 - 15
src/bin/dhcp6/tests/fqdn_unittest.cc

@@ -22,6 +22,7 @@
 #include <dhcp/option6_client_fqdn.h>
 #include <dhcp/option6_ia.h>
 #include <dhcp/option6_iaaddr.h>
+#include <dhcp/option6_status_code.h>
 #include <dhcp/option_int_array.h>
 #include <dhcpsrv/lease.h>
 #include <dhcp/tests/iface_mgr_test_config.h>
@@ -256,16 +257,9 @@ public:
     /// Status Code option.
     ///
     /// @return An object representing the Status Code option.
-    OptionCustomPtr createStatusCode(const uint16_t code,
+    Option6StatusCodePtr createStatusCode(const uint16_t code,
                                      const std::string& msg) {
-        OptionDefinition def("status-code", D6O_STATUS_CODE, "record");
-        def.addRecordField("uint16");
-        def.addRecordField("string");
-        OptionCustomPtr opt_status(new OptionCustom(def, Option::V6));
-        opt_status->writeInteger(code);
-        if (!msg.empty()) {
-            opt_status->writeString(msg, 1);
-        }
+        Option6StatusCodePtr opt_status(new Option6StatusCode(code, msg));
         return (opt_status);
     }
 
@@ -731,7 +725,8 @@ TEST_F(FqdnDhcpv6SrvTest, createRemovalNameChangeRequestFwdRev) {
     // as if we typed domain-name in lower case.
     lease_->hostname_ = "MYHOST.example.com.";
 
-    ASSERT_NO_THROW(srv_->createRemovalNameChangeRequest(lease_));
+    Pkt6Ptr pkt(new Pkt6(DHCPREQUEST, 1234));
+    ASSERT_NO_THROW(srv_->createRemovalNameChangeRequest(pkt, lease_));
 
     ASSERT_EQ(1, d2_mgr_.getQueueSize());
     verifyNameChangeRequest(isc::dhcp_ddns::CHG_REMOVE, true, true,
@@ -756,7 +751,8 @@ TEST_F(FqdnDhcpv6SrvTest, noRemovalsWhenDisabled) {
     lease_->hostname_ = "MYHOST.example.com.";
 
     // When DDNS is disabled an attempt to send a request will throw.
-    ASSERT_NO_THROW(srv_->createRemovalNameChangeRequest(lease_));
+    Pkt6Ptr pkt(new Pkt6(DHCPREQUEST, 1234));
+    ASSERT_NO_THROW(srv_->createRemovalNameChangeRequest(pkt, lease_));
 }
 
 
@@ -767,7 +763,8 @@ TEST_F(FqdnDhcpv6SrvTest, createRemovalNameChangeRequestRev) {
     lease_->fqdn_rev_ = true;
     lease_->hostname_ = "myhost.example.com.";
 
-    ASSERT_NO_THROW(srv_->createRemovalNameChangeRequest(lease_));
+    Pkt6Ptr pkt(new Pkt6(DHCPREQUEST, 1234));
+    ASSERT_NO_THROW(srv_->createRemovalNameChangeRequest(pkt, lease_));
 
     ASSERT_EQ(1, d2_mgr_.getQueueSize());
 
@@ -785,7 +782,8 @@ TEST_F(FqdnDhcpv6SrvTest, createRemovalNameChangeRequestNoUpdate) {
     lease_->fqdn_fwd_ = false;
     lease_->fqdn_rev_ = false;
 
-    ASSERT_NO_THROW(srv_->createRemovalNameChangeRequest(lease_));
+    Pkt6Ptr pkt(new Pkt6(DHCPREQUEST, 1234));
+    ASSERT_NO_THROW(srv_->createRemovalNameChangeRequest(pkt, lease_));
 
     ASSERT_EQ(0, d2_mgr_.getQueueSize());
 
@@ -798,7 +796,8 @@ TEST_F(FqdnDhcpv6SrvTest, createRemovalNameChangeRequestNoHostname) {
     lease_->fqdn_rev_ = true;
     lease_->hostname_ = "";
 
-    ASSERT_NO_THROW(srv_->createRemovalNameChangeRequest(lease_));
+    Pkt6Ptr pkt(new Pkt6(DHCPREQUEST, 1234));
+    ASSERT_NO_THROW(srv_->createRemovalNameChangeRequest(pkt, lease_));
 
     ASSERT_EQ(0, d2_mgr_.getQueueSize());
 
@@ -812,7 +811,8 @@ TEST_F(FqdnDhcpv6SrvTest, createRemovalNameChangeRequestWrongHostname) {
     lease_->fqdn_rev_ = true;
     lease_->hostname_ = "myhost..example.com.";
 
-    ASSERT_NO_THROW(srv_->createRemovalNameChangeRequest(lease_));
+    Pkt6Ptr pkt(new Pkt6(DHCPREQUEST, 1234));
+    ASSERT_NO_THROW(srv_->createRemovalNameChangeRequest(pkt, lease_));
 
     ASSERT_EQ(0, d2_mgr_.getQueueSize());
 

+ 1 - 0
src/lib/dhcp/Makefile.am

@@ -32,6 +32,7 @@ libkea_dhcp___la_SOURCES += option6_iaaddr.cc option6_iaaddr.h
 libkea_dhcp___la_SOURCES += option6_iaprefix.cc option6_iaprefix.h
 libkea_dhcp___la_SOURCES += option6_addrlst.cc option6_addrlst.h
 libkea_dhcp___la_SOURCES += option6_client_fqdn.cc option6_client_fqdn.h
+libkea_dhcp___la_SOURCES += option6_status_code.cc option6_status_code.h
 libkea_dhcp___la_SOURCES += option_vendor.cc option_vendor.h
 libkea_dhcp___la_SOURCES += option_vendor_class.cc option_vendor_class.h
 libkea_dhcp___la_SOURCES += option_int.h

+ 8 - 2
src/lib/dhcp/option.cc

@@ -214,14 +214,20 @@ std::string Option::toText(int indent) {
 }
 
 std::string
-Option::headerToText(const int indent) {
+Option::headerToText(const int indent, const std::string& type_name) {
     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')
+           << type_;
+
+    if (!type_name.empty()) {
+        output << "(" << type_name << ")";
+    }
+
+    output << ", len=" << std::setw(field_len) << std::setfill('0')
            << len()-getHeaderLen();
     return (output.str());
 }

+ 4 - 1
src/lib/dhcp/option.h

@@ -429,9 +429,12 @@ protected:
     /// their respective @c toText implementations.
     ///
     /// @param indent Number of spaces to insert before the text.
+    /// @param type_name Option type name. If empty, the option name
+    /// is omitted.
     ///
     /// @return Option header in the textual format.
-    std::string headerToText(const int indent = 0);
+    std::string headerToText(const int indent = 0,
+                             const std::string& type_name = "");
 
     /// @brief Returns collection of suboptions in the textual format.
     ///

+ 10 - 18
src/lib/dhcp/option6_ia.cc

@@ -84,32 +84,24 @@ void Option6IA::unpack(OptionBufferConstIter begin,
     unpackOptions(OptionBuffer(begin, end));
 }
 
-std::string Option6IA::toText(int indent /* = 0*/) {
-    stringstream tmp;
+std::string Option6IA::toText(int indent) {
+    stringstream output;
 
-    for (int i=0; i<indent; i++)
-        tmp << " ";
-    tmp << "type=" << type_;
-
-    switch (type_) {
+    switch(getType()) {
     case D6O_IA_NA:
-        tmp << "(IA_NA)";
+        output << headerToText(indent, "IA_NA");
         break;
     case D6O_IA_PD:
-        tmp << "(IA_PD)";
+        output << headerToText(indent, "IA_PD");
         break;
     default:
-        tmp << "(unknown)";
+        output << headerToText(indent);
     }
-    tmp << " iaid=" << iaid_ << ", t1=" << t1_ << ", t2=" << t2_
-        << " " << options_.size() << " sub-options:" << endl;
 
-    for (OptionCollection::const_iterator opt=options_.begin();
-         opt!=options_.end();
-         ++opt) {
-        tmp << (*opt).second->toText(indent+2);
-    }
-    return tmp.str();
+    output << ": iaid=" << iaid_ << ", t1=" << t1_ << ", t2=" << t2_
+           << suboptionsToText(indent + 2);
+
+    return (output.str());
 }
 
 uint16_t Option6IA::len() {

+ 9 - 15
src/lib/dhcp/option6_iaaddr.cc

@@ -89,21 +89,15 @@ void Option6IAAddr::unpack(OptionBuffer::const_iterator begin,
     unpackOptions(OptionBuffer(begin, end));
 }
 
-std::string Option6IAAddr::toText(int indent /* =0 */) {
-    stringstream tmp;
-    for (int i=0; i<indent; i++)
-        tmp << " ";
-
-    tmp << "type=" << type_ << "(IAADDR) addr=" << addr_
-        << ", preferred-lft=" << preferred_  << ", valid-lft="
-        << valid_ << endl;
-
-    for (OptionCollection::const_iterator opt=options_.begin();
-         opt!=options_.end();
-         ++opt) {
-        tmp << (*opt).second->toText(indent+2);
-    }
-    return tmp.str();
+std::string Option6IAAddr::toText(int indent) {
+    std::stringstream output;
+    output << headerToText(indent, "IAADDR") << ": "
+           << "address=" << addr_
+           << ", preferred-lft=" << preferred_
+           << ", valid-lft=" << valid_;
+
+    output << suboptionsToText(indent + 2);
+    return (output.str());
 }
 
 uint16_t Option6IAAddr::len() {

+ 9 - 15
src/lib/dhcp/option6_iaprefix.cc

@@ -97,21 +97,15 @@ void Option6IAPrefix::unpack(OptionBuffer::const_iterator begin,
     unpackOptions(OptionBuffer(begin, end));
 }
 
-std::string Option6IAPrefix::toText(int indent /* =0 */) {
-    stringstream tmp;
-    for (int i=0; i<indent; i++)
-        tmp << " ";
-
-    tmp << "type=" << type_ << "(IAPREFIX) prefix=" << addr_ << "/"
-        << static_cast<int>(prefix_len_) << ", preferred-lft="
-        << preferred_ << ", valid-lft=" << valid_ << endl;
-
-    for (OptionCollection::const_iterator opt=options_.begin();
-         opt!=options_.end();
-         ++opt) {
-        tmp << (*opt).second->toText(indent + 2);
-    }
-    return tmp.str();
+std::string Option6IAPrefix::toText(int indent) {
+    std::stringstream output;
+    output << headerToText(indent, "IAPREFIX") << ": "
+           << "prefix=" << addr_ << "/" << static_cast<int>(prefix_len_)
+           << ", preferred-lft=" << preferred_
+           << ", valid-lft=" << valid_;
+
+    output << suboptionsToText(indent + 2);
+    return (output.str());
 }
 
 uint16_t Option6IAPrefix::len() {

+ 142 - 0
src/lib/dhcp/option6_status_code.cc

@@ -0,0 +1,142 @@
+// Copyright (C) 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
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+// AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+// PERFORMANCE OF THIS SOFTWARE.
+
+#include <config.h>
+
+#include <dhcp/dhcp6.h>
+#include <dhcp/option6_status_code.h>
+#include <util/io_utilities.h>
+#include <iterator>
+#include <sstream>
+
+using namespace isc;
+using namespace isc::dhcp;
+
+namespace {
+
+/// @brief Minimum length of the option (when status message is empty).
+const size_t OPTION6_STATUS_CODE_MIN_LEN = sizeof(uint16_t);
+
+}; // end of anonymous namespace
+
+namespace isc {
+namespace dhcp {
+
+Option6StatusCode::Option6StatusCode(const uint16_t status_code,
+                                     const std::string& status_message)
+    : Option(Option::V6, D6O_STATUS_CODE),
+      status_code_(status_code), status_message_(status_message) {
+}
+
+Option6StatusCode::Option6StatusCode(OptionBufferConstIter begin,
+                                     OptionBufferConstIter end)
+    : Option(Option::V6, D6O_STATUS_CODE),
+      status_code_(STATUS_Success), status_message_() {
+
+    // Parse data 
+    unpack(begin, end);
+}
+
+void
+Option6StatusCode::pack(isc::util::OutputBuffer& buf) {
+    // Pack option header.
+    packHeader(buf);
+    // Write numeric status code.
+    buf.writeUint16(getStatusCode());
+    // If there is any status message, write it.
+    if (!status_message_.empty()) {
+        buf.writeData(&status_message_[0], status_message_.size());
+    }
+
+    // Status code has no options, so leave here.
+}
+
+void
+Option6StatusCode::unpack(OptionBufferConstIter begin, OptionBufferConstIter end) {
+    // Make sure that the option is not truncated.
+    if (std::distance(begin, end) < OPTION6_STATUS_CODE_MIN_LEN) {
+        isc_throw(OutOfRange, "Status Code option ("
+                  << D6O_STATUS_CODE << ") truncated");
+    }
+
+    status_code_ = util::readUint16(&(*begin), std::distance(begin, end));
+    begin += sizeof(uint16_t);
+
+    status_message_.assign(begin, end);
+}
+
+uint16_t
+Option6StatusCode::len() {
+    return (getHeaderLen() + sizeof(uint16_t) + status_message_.size());
+}
+
+std::string
+Option6StatusCode::toText(int indent) {
+    std::ostringstream output;
+    output << headerToText(indent) << ": " << dataToText();
+
+    return (output.str());
+}
+
+std::string
+Option6StatusCode::dataToText() const {
+    std::ostringstream output;
+    // Add status code name and numeric status code.
+    output << getStatusCodeName() << "(" << getStatusCode() << ") ";
+
+    // Include status message in quotes if status code is
+    // non-empty.
+    if (!status_message_.empty()) {
+        output << "\"" << status_message_ << "\"";
+
+    } else {
+        output << "(no status message)";
+    }
+
+    return (output.str());
+}
+
+std::string
+Option6StatusCode::getStatusCodeName() const {
+    switch (getStatusCode()) {
+    case STATUS_Success:
+        return ("Success");
+    case STATUS_UnspecFail:
+        return ("UnspecFail");
+    case STATUS_NoAddrsAvail:
+        return ("NoAddrsAvail");
+    case STATUS_NoBinding:
+        return ("NoBinding");
+    case STATUS_NotOnLink:
+        return ("NotOnLink");
+    case STATUS_UseMulticast:
+        return ("UseMulticast");
+    case STATUS_NoPrefixAvail:
+        return ("NoPrefixAvail");
+    case STATUS_UnknownQueryType:
+        return ("UnknownQueryType");
+    case STATUS_MalformedQuery:
+        return ("MalformedQuery");
+    case STATUS_NotConfigured:
+        return ("NotConfigured");
+    case STATUS_NotAllowed:
+        return ("NotAllowed");
+    default:
+        ;
+    }
+    return ("(unknown status code)");
+}
+
+} // end of namespace isc::dhcp
+} // end of namespace isc

+ 118 - 0
src/lib/dhcp/option6_status_code.h

@@ -0,0 +1,118 @@
+// Copyright (C) 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
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+// AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+// PERFORMANCE OF THIS SOFTWARE.
+
+#ifndef OPTION6_STATUS_CODE_H
+#define OPTION6_STATUS_CODE_H
+
+#include <dhcp/option.h>
+#include <boost/shared_ptr.hpp>
+#include <stdint.h>
+#include <string>
+
+namespace isc {
+namespace dhcp {
+
+class Option6StatusCode;
+
+/// @brief Pointer to the @c isc::dhcp::Option6StatusCode.
+typedef boost::shared_ptr<Option6StatusCode> Option6StatusCodePtr;
+
+/// @brief This class represents Status Code option (13) from RFC3315.
+class Option6StatusCode: public Option {
+public:
+    /// @brief Constructor, used for options constructed (during transmission).
+    ///
+    /// @param status_code Numeric status code, e.g. STATUS_NoAddrsAvail.
+    /// @param status_message Textual message for the statuscode.
+    Option6StatusCode(const uint16_t status_code, const std::string& status_message);
+
+    /// @brief Constructor, used for received options.
+    ///
+    /// @throw OutOfRange if specified option is truncated
+    ///
+    /// @param begin Iterator to first byte of option data
+    /// @param end Iterator to end of option data (first byte after option end).
+    Option6StatusCode(OptionBufferConstIter begin, OptionBufferConstIter end);
+
+    /// @brief Writes option in wire-format.
+    ///
+    /// Writes option in wire-format to buf, returns pointer to first unused
+    /// byte after stored option.
+    ///
+    /// @param [out] buf Pointer to the output buffer.
+    virtual void pack(isc::util::OutputBuffer& buf);
+
+    /// @brief Parses received buffer.
+    ///
+    /// @param begin Iterator to first byte of option data
+    /// @param end Iterator to end of option data (first byte after option end)
+    virtual void unpack(OptionBufferConstIter begin, OptionBufferConstIter end);
+
+    /// @brief Returns total length of the option.
+    ///
+    /// The returned length is a sum of the option header and data fields.
+    virtual uint16_t len();
+
+    /// @brief Returns textual representation of the option.
+    ///
+    /// @param indent Number of spaces before printing text.
+    virtual std::string toText(int indent = 0);
+
+    /// @brief Returns textual representation of the option data.
+    ///
+    /// This method returns only the status code and the status
+    /// message. It excludes the option header.
+    std::string dataToText() const;
+
+    /// @brief Returns numeric status code.
+    uint16_t getStatusCode() const {
+        return (status_code_);        
+    }
+
+    /// @brief Returns the name of the status code.
+    std::string getStatusCodeName() const;
+
+    /// @brief Sets new numeric status code.
+    ///
+    /// @param status_code New numeric status code.
+    void setStatusCode(const uint16_t status_code) {
+        status_code_ = status_code;
+    }
+
+    /// @brief Returns status message.
+    const std::string& getStatusMessage() const {
+        return (status_message_);
+    }
+
+    /// @brief Sets new status message.
+    ///
+    /// @param status_message New status message (empty string is allowed).
+    void setStatusMessage(const std::string& status_message) {
+        status_message_ = status_message;
+    }
+
+private:
+
+    /// @brief Numeric status code.
+    uint16_t status_code_;
+
+    /// @brief Textual message.
+    std::string status_message_;
+
+};
+
+} // isc::dhcp namespace
+} // isc namespace
+
+#endif // OPTION6_STATUS_CODE_H

+ 12 - 0
src/lib/dhcp/option_definition.cc

@@ -22,6 +22,7 @@
 #include <dhcp/option6_iaaddr.h>
 #include <dhcp/option6_iaprefix.h>
 #include <dhcp/option6_client_fqdn.h>
+#include <dhcp/option6_status_code.h>
 #include <dhcp/option_custom.h>
 #include <dhcp/option_definition.h>
 #include <dhcp/option_int.h>
@@ -428,6 +429,14 @@ OptionDefinition::haveVendorClass6Format() const {
 }
 
 bool
+OptionDefinition::haveStatusCodeFormat() const {
+    return (haveType(OPT_RECORD_TYPE) &&
+            (record_fields_.size() == 2) &&
+            (record_fields_[0] == OPT_UINT16_TYPE) &&
+            (record_fields_[1] == OPT_STRING_TYPE));
+}
+
+bool
 OptionDefinition::convertToBool(const std::string& value_str) const {
     // Case insensitve check that the input is one of: "true" or "false".
     if (boost::iequals(value_str, "true")) {
@@ -684,6 +693,9 @@ OptionDefinition::factorySpecialFormatOption(Option::Universe u,
         } else if (getCode() == D6O_VENDOR_CLASS && haveVendorClass6Format()) {
             // Vendor Class (option code 16).
             return (OptionPtr(new OptionVendorClass(Option::V6, begin, end)));
+        } else if (getCode() == D6O_STATUS_CODE && haveStatusCodeFormat()) {
+            // Status Code (option code 13)
+            return (OptionPtr(new Option6StatusCode(begin, end)));
         }
     } else {
         if ((getCode() == DHO_FQDN) && haveFqdn4Format()) {

+ 6 - 1
src/lib/dhcp/option_definition.h

@@ -1,4 +1,4 @@
-// Copyright (C) 2012-2014 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
@@ -365,6 +365,11 @@ public:
     /// @return true if option has the format of DHCPv6 Vendor Class option.
     bool haveVendorClass6Format() const;
 
+    /// @brief Check if the option has format of DHCPv6 Status Code option.
+    ///
+    /// @return true if option has the format of DHCPv6 Status code option.
+    bool haveStatusCodeFormat() const;
+
     /// @brief Option factory.
     ///
     /// This function creates an instance of DHCP option using

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

@@ -231,7 +231,7 @@ public:
     /// @param type message type to be set
     void setType(uint8_t type);
 
-    /// @brief Returns name of the DHCP message.
+    /// @brief Returns name of the DHCP message for a given type number.
     ///
     /// @param type DHCPv4 message type which name should be returned.
     ///

+ 64 - 0
src/lib/dhcp/pkt6.cc

@@ -496,6 +496,36 @@ Pkt6::getMACFromDUID() {
 }
 
 std::string
+Pkt6::makeLabel(const DuidPtr duid, const uint32_t transid,
+                const HWAddrPtr& hwaddr) {
+    std::stringstream label;
+    // DUID should be present at all times, so explicitly inform when
+    // it is no present (no info).
+    label << "duid=[" << (duid ? duid->toText() : "no info")
+          << "],";
+
+    // HW address is typically not carried in the DHCPv6 mmessages
+    // and can be extracted using various, but not fully reliable,
+    // techniques. If it is not present, don't print anything.
+    if (hwaddr) {
+        label << " [" << hwaddr->toText() << "],";
+    }
+
+    // Transaction id is always there.
+    label << " tid=0x" << std::hex << transid << std::dec;
+
+    return (label.str());
+}
+
+std::string
+Pkt6::getLabel() const {
+    /// @todo Do not print HW address as it is unclear how it should
+    /// be retrieved if there is no access to user configuration which
+    /// specifies the order of various techniques to be used to retrieve
+    /// it.
+    return (makeLabel(getClientId(), getTransid(), HWAddrPtr()));}
+
+std::string
 Pkt6::toText() const {
     stringstream tmp;
     tmp << "localAddr=[" << local_addr_ << "]:" << local_port_
@@ -511,6 +541,12 @@ Pkt6::toText() const {
     return tmp.str();
 }
 
+DuidPtr
+Pkt6::getClientId() const {
+    OptionPtr opt_duid = getOption(D6O_CLIENTID);
+    return (opt_duid ? DuidPtr(new DUID(opt_duid->getData())) : DuidPtr());
+}
+
 isc::dhcp::OptionCollection
 Pkt6::getOptions(uint16_t opt_type) {
     isc::dhcp::OptionCollection found;
@@ -526,17 +562,27 @@ Pkt6::getOptions(uint16_t opt_type) {
 
 const char*
 Pkt6::getName(const uint8_t type) {
+    static const char* ADVERTISE = "ADVERTISE";
     static const char* CONFIRM = "CONFIRM";
     static const char* DECLINE = "DECLINE";
     static const char* INFORMATION_REQUEST = "INFORMATION_REQUEST";
+    static const char* LEASEQUERY = "LEASEQUERY";
+    static const char* LEASEQUERY_REPLY = "LEASEQUERY_REPLY";
     static const char* REBIND = "REBIND";
+    static const char* RECONFIGURE = "RECONFIGURE";
+    static const char* RELAY_FORW = "RELAY_FORWARD";
+    static const char* RELAY_REPL = "RELAY_REPLY";
     static const char* RELEASE = "RELEASE";
     static const char* RENEW = "RENEW";
+    static const char* REPLY = "REPLY";
     static const char* REQUEST = "REQUEST";
     static const char* SOLICIT = "SOLICIT";
     static const char* UNKNOWN = "UNKNOWN";
 
     switch (type) {
+    case DHCPV6_ADVERTISE:
+        return (ADVERTISE);
+
     case DHCPV6_CONFIRM:
         return (CONFIRM);
 
@@ -546,15 +592,33 @@ Pkt6::getName(const uint8_t type) {
     case DHCPV6_INFORMATION_REQUEST:
         return (INFORMATION_REQUEST);
 
+    case DHCPV6_LEASEQUERY:
+        return (LEASEQUERY);
+
+    case DHCPV6_LEASEQUERY_REPLY:
+        return (LEASEQUERY_REPLY);
+
     case DHCPV6_REBIND:
         return (REBIND);
 
+    case DHCPV6_RECONFIGURE:
+        return (RECONFIGURE);
+
+    case DHCPV6_RELAY_FORW:
+        return (RELAY_FORW);
+
+    case DHCPV6_RELAY_REPL:
+        return (RELAY_REPL);
+
     case DHCPV6_RELEASE:
         return (RELEASE);
 
     case DHCPV6_RENEW:
         return (RENEW);
 
+    case DHCPV6_REPLY:
+        return (REPLY);
+
     case DHCPV6_REQUEST:
         return (REQUEST);
 

+ 43 - 14
src/lib/dhcp/pkt6.h

@@ -16,6 +16,7 @@
 #define PKT6_H
 
 #include <asiolink/io_address.h>
+#include <dhcp/duid.h>
 #include <dhcp/option.h>
 #include <dhcp/pkt.h>
 
@@ -157,6 +158,34 @@ public:
         proto_ = proto;
     }
 
+    /// @brief Returns text representation of the given packet identifiers.
+    ///
+    /// @note The parameters are ordered from the one that should be available
+    /// almost at all times, to the one that is optional. This allows for
+    /// providing default values for the parameters that may not be available
+    /// in some places in the code where @c Pkt6::makeLabel is called.
+    ///
+    /// @param duid Pointer to the client identifier or NULL.
+    /// @param transid Numeric transaction id to include in the string.
+    /// @param hwaddr Hardware address to include in the string or NULL.
+    ///
+    /// @return String with text representation of the packet identifiers.
+    static std::string makeLabel(const DuidPtr duid, const uint32_t transid,
+                                 const HWAddrPtr& hwaddr);
+
+    /// @brief Returns text representation of the primary packet identifiers
+    ///
+    /// This method is intended to be used to provide a consistent way to
+    /// identify packets within log statements.  It is an instance-level
+    /// wrapper around static makeLabel(). See this method for string
+    /// content.
+    ///
+    /// @note Currently this method doesn't include the HW address in the
+    /// returned text.
+    ///
+    /// @return string with text representation
+    virtual std::string getLabel() const;
+
     /// @brief Returns text representation of the packet.
     ///
     /// This function is useful mainly for debugging.
@@ -186,6 +215,11 @@ public:
     /// @param type message type to be set
     virtual void setType(uint8_t type) { msg_type_=type; };
 
+    /// @brief Retrieves the DUID from the Client Identifier option.
+    ///
+    /// @return Pointer to the DUID or NULL if the option doesn't exist.
+    DuidPtr getClientId() const;
+
     /// @brief returns option inserted by relay
     ///
     /// Returns an option from specified relay scope (inserted by a given relay
@@ -232,32 +266,27 @@ public:
     /// @param relay structure with necessary relay information
     void addRelayInfo(const RelayInfo& relay);
 
-    /// @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
-    /// expected to be received by the server (such as an ADVERTISE), the string
-    /// "UNKNOWN" is returned.  This method is used in debug messages.
+    /// @brief Returns name of the DHCPv6 message for a given type number.
     ///
     /// As the operation of the method does not depend on any server state, it
     /// is declared static. There is also non-static getName() method that
     /// works on Pkt6 objects.
     ///
-    /// @param type DHCPv6 packet type
+    /// @param type DHCPv6 message type which name should be returned.
     ///
-    /// @return Pointer to "const" string containing the packet name.
-    ///         Note that this string is statically allocated and MUST NOT
-    ///         be freed by the caller.
+    /// @return Pointer to "const" string containing the message name. If
+    /// the message type is unknnown the "UNKNOWN" is returned. The caller
+    /// must not release the returned pointer.
     static const char* getName(const uint8_t type);
 
-    /// @brief returns textual representation of packet type.
+    /// @brief Returns name of the DHCPv6 message.
     ///
     /// This method requires an object. There is also static version, which
     /// requires one parameter (type).
     ///
-    /// @return Pointer to "const" string containing packet name.
-    ///         Note that this string is statically allocated and MUST NOT
-    ///         be freed by the caller.
+    /// @return Pointer to "const" string containing the message name. If
+    /// the message type is unknnown the "UNKNOWN" is returned. The caller
+    /// must not release the returned pointer.
     const char* getName() const;
 
     /// @brief copies relay information from client's packet to server's response

+ 1 - 0
src/lib/dhcp/tests/Makefile.am

@@ -59,6 +59,7 @@ libdhcp___unittests_SOURCES += option6_client_fqdn_unittest.cc
 libdhcp___unittests_SOURCES += option6_ia_unittest.cc
 libdhcp___unittests_SOURCES += option6_iaaddr_unittest.cc
 libdhcp___unittests_SOURCES += option6_iaprefix_unittest.cc
+libdhcp___unittests_SOURCES += option6_status_code_unittest.cc
 libdhcp___unittests_SOURCES += option_int_unittest.cc
 libdhcp___unittests_SOURCES += option_int_array_unittest.cc
 libdhcp___unittests_SOURCES += option_data_types_unittest.cc

+ 3 - 2
src/lib/dhcp/tests/libdhcp++_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
@@ -25,6 +25,7 @@
 #include <dhcp/option6_ia.h>
 #include <dhcp/option6_iaaddr.h>
 #include <dhcp/option6_iaprefix.h>
+#include <dhcp/option6_status_code.h>
 #include <dhcp/option_custom.h>
 #include <dhcp/option_int.h>
 #include <dhcp/option_int_array.h>
@@ -1026,7 +1027,7 @@ TEST_F(LibDhcpTest, stdOptionDefs6) {
                                     typeid(Option));
 
     LibDhcpTest::testStdOptionDefs6(D6O_STATUS_CODE, begin, end,
-                                    typeid(OptionCustom));
+                                    typeid(Option6StatusCode));
 
     LibDhcpTest::testStdOptionDefs6(D6O_RAPID_COMMIT, begin, end,
                                     typeid(Option));

+ 17 - 0
src/lib/dhcp/tests/option4_addrlst_unittest.cc

@@ -252,4 +252,21 @@ TEST_F(Option4AddrLstTest, setAddresses) {
     EXPECT_NO_THROW(opt.reset());
 }
 
+// This test checks that the option holding IPv4 address list can
+// be converted to textual format.
+TEST_F(Option4AddrLstTest, toText) {
+    Option4AddrLst opt(111);
+    // Generate a few IPv4 addresses.
+    Option4AddrLst::AddressContainer addresses;
+    for (int i = 2; i < 6; ++i) {
+        std::stringstream s;
+        s << "192.0.2." << i;
+        addresses.push_back(IOAddress(s.str()));
+    }
+    opt.setAddresses(addresses);
+
+    EXPECT_EQ("type=111, len=016: 192.0.2.2 192.0.2.3 192.0.2.4 192.0.2.5",
+              opt.toText());
+}
+
 } // namespace

+ 18 - 1
src/lib/dhcp/tests/option6_addrlst_unittest.cc

@@ -1,4 +1,4 @@
-// Copyright (C) 2011-2013 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
@@ -234,4 +234,21 @@ TEST_F(Option6AddrLstTest, setAddress) {
     EXPECT_NO_THROW(opt1.reset());
 }
 
+// This test checks that the option holding IPv6 address list can
+// be converted to textual format.
+TEST_F(Option6AddrLstTest, toText) {
+    Option6AddrLst opt(1234, IOAddress("2001:db8:1::1"));
+    // Generate a few IPv6 addresses.
+    Option6AddrLst::AddressContainer addresses;
+    for (int i = 2; i < 6; ++i) {
+        std::stringstream s;
+        s << "2001:db8:1::" << i;
+        addresses.push_back(IOAddress(s.str()));
+    }
+    opt.setAddresses(addresses);
+
+    EXPECT_EQ("type=01234, len=00064: 2001:db8:1::2 2001:db8:1::3 "
+              "2001:db8:1::4 2001:db8:1::5", opt.toText());
+}
+
 } // namespace

+ 43 - 2
src/lib/dhcp/tests/option6_ia_unittest.cc

@@ -1,4 +1,4 @@
-// Copyright (C) 2011-2012 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
@@ -258,7 +258,7 @@ TEST_F(Option6IATest, pdSuboptionsPack) {
 }
 
 // test if option can parse suboptions
-TEST_F(Option6IATest, suboptions_unpack) {
+TEST_F(Option6IATest, suboptionsUnpack) {
     // sizeof (expected) = 48 bytes
     const uint8_t expected[] = {
         D6O_IA_NA / 256, D6O_IA_NA % 256, // type
@@ -323,4 +323,45 @@ TEST_F(Option6IATest, suboptions_unpack) {
     EXPECT_NO_THROW(ia.reset());
 }
 
+// This test checks that the IA_NA option is correctly converted to the
+// textual format.
+TEST_F(Option6IATest, toTextNA) {
+    Option6IA ia(D6O_IA_NA, 1234);
+    ia.setT1(200);
+    ia.setT2(300);
+
+    ia.addOption(OptionPtr(new Option6IAAddr(D6O_IAADDR, IOAddress("2001:db8:1::1"),
+                                             500, 600)));
+    ia.addOption(OptionPtr(new Option6IAAddr(D6O_IAADDR, IOAddress("2001:db8:1::2"),
+                                             450, 550)));
+
+    EXPECT_EQ("type=00003(IA_NA), len=00068: iaid=1234, t1=200, t2=300,\n"
+              "options:\n"
+              "  type=00005(IAADDR), len=00024: address=2001:db8:1::1, "
+              "preferred-lft=500, valid-lft=600\n"
+              "  type=00005(IAADDR), len=00024: address=2001:db8:1::2, "
+              "preferred-lft=450, valid-lft=550", ia.toText());
+}
+
+// This test checks that the IA_PD option is correctly converted to the
+// textual format.
+TEST_F(Option6IATest, toTextPD) {
+    Option6IA ia(D6O_IA_PD, 2345);
+    ia.setT1(200);
+    ia.setT2(300);
+
+    ia.addOption(OptionPtr(new Option6IAPrefix(D6O_IAPREFIX, IOAddress("2001:db8:1::"),
+                                               72, 500, 600)));
+    ia.addOption(OptionPtr(new Option6IAPrefix(D6O_IAPREFIX, IOAddress("2001:db8:1::"),
+                                               64, 450, 550)));
+
+    EXPECT_EQ("type=00025(IA_PD), len=00070: iaid=2345, t1=200, t2=300,\n"
+              "options:\n"
+              "  type=00026(IAPREFIX), len=00025: prefix=2001:db8:1::/72, "
+              "preferred-lft=500, valid-lft=600\n"
+              "  type=00026(IAPREFIX), len=00025: prefix=2001:db8:1::/64, "
+              "preferred-lft=450, valid-lft=550",
+              ia.toText());
+}
+
 }

+ 23 - 1
src/lib/dhcp/tests/option6_iaaddr_unittest.cc

@@ -1,4 +1,4 @@
-// Copyright (C) 2011-2013 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
@@ -16,6 +16,7 @@
 
 #include <dhcp/dhcp6.h>
 #include <dhcp/option.h>
+#include <dhcp/option_int.h>
 #include <dhcp/option6_iaaddr.h>
 #include <util/buffer.h>
 
@@ -29,6 +30,7 @@
 
 using namespace std;
 using namespace isc;
+using namespace isc::asiolink;
 using namespace isc::dhcp;
 using namespace isc::util;
 
@@ -121,4 +123,24 @@ TEST_F(Option6IAAddrTest, negative) {
                                1000, 2000), BadValue);
 }
 
+// Tests that option can be converted to textual format.
+TEST_F(Option6IAAddrTest, toText) {
+    // Create option without suboptions.
+    Option6IAAddr opt(D6O_IAADDR, IOAddress("2001:db8:1::1"), 300, 400);
+    EXPECT_EQ("type=00005(IAADDR), len=00024: address=2001:db8:1::1,"
+              " preferred-lft=300, valid-lft=400",
+              opt.toText());
+
+    // Add suboptions and make sure they are printed.
+    opt.addOption(OptionPtr(new OptionUint32(Option::V6, 123, 234)));
+    opt.addOption(OptionPtr(new OptionUint32(Option::V6, 222, 333)));
+
+    EXPECT_EQ("type=00005(IAADDR), len=00040: address=2001:db8:1::1,"
+              " preferred-lft=300, valid-lft=400,\noptions:\n"
+              "  type=00123, len=00004: 234 (uint32)\n"
+              "  type=00222, len=00004: 333 (uint32)",
+              opt.toText());
+
+}
+
 }

+ 21 - 1
src/lib/dhcp/tests/option6_iaprefix_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
@@ -16,6 +16,7 @@
 
 #include <dhcp/dhcp6.h>
 #include <dhcp/option.h>
+#include <dhcp/option_int.h>
 #include <dhcp/option6_iaprefix.h>
 #include <util/buffer.h>
 
@@ -256,4 +257,23 @@ TEST_F(Option6IAPrefixTest, negative) {
                  BadValue);
 }
 
+// Checks if the option is converted to textual format correctly.
+TEST_F(Option6IAPrefixTest, toText) {
+    // Create option without suboptions.
+    Option6IAPrefix opt(D6O_IAPREFIX, IOAddress("2001:db8:1::"), 64, 300, 400);
+    EXPECT_EQ("type=00026(IAPREFIX), len=00025: prefix=2001:db8:1::/64,"
+              " preferred-lft=300, valid-lft=400",
+              opt.toText());
+
+    // Add suboptions and make sure they are printed.
+    opt.addOption(OptionPtr(new OptionUint32(Option::V6, 123, 234)));
+    opt.addOption(OptionPtr(new OptionUint32(Option::V6, 222, 333)));
+
+    EXPECT_EQ("type=00026(IAPREFIX), len=00041: prefix=2001:db8:1::/64,"
+              " preferred-lft=300, valid-lft=400,\noptions:\n"
+              "  type=00123, len=00004: 234 (uint32)\n"
+              "  type=00222, len=00004: 333 (uint32)",
+              opt.toText());
+}
+
 }

+ 177 - 0
src/lib/dhcp/tests/option6_status_code_unittest.cc

@@ -0,0 +1,177 @@
+// Copyright (C) 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
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+// AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+// PERFORMANCE OF THIS SOFTWARE.
+
+#include <config.h>
+
+#include <dhcp/dhcp6.h>
+#include <dhcp/option.h>
+#include <dhcp/option6_status_code.h>
+#include <gtest/gtest.h>
+#include <cstring>
+
+using namespace isc;
+using namespace isc::dhcp;
+
+namespace {
+
+// This test verifies that the option can be created and that the
+// accessor methods return correct values used for the object
+// construction.
+TEST(Option6StatusCodeTest, accessors) {
+    Option6StatusCode status1(STATUS_NoAddrsAvail, "Sorry, NoAddrsAvail");
+    EXPECT_EQ(STATUS_NoAddrsAvail, status1.getStatusCode());
+    EXPECT_EQ("Sorry, NoAddrsAvail", status1.getStatusMessage());
+
+    Option6StatusCode status2(STATUS_NoBinding, "There is NoBinding");
+    EXPECT_EQ(STATUS_NoBinding, status2.getStatusCode());
+    EXPECT_EQ("There is NoBinding", status2.getStatusMessage());
+}
+
+// This test verifies that the status code and status message may
+// be modified.
+TEST(Option6StatusCodeTest, modifiers) {
+    Option6StatusCode status(STATUS_NoAddrsAvail, "Sorry, NoAddrsAvail");
+    ASSERT_EQ(STATUS_NoAddrsAvail, status.getStatusCode());
+    ASSERT_EQ("Sorry, NoAddrsAvail", status.getStatusMessage());
+
+    ASSERT_NO_THROW(status.setStatusCode(STATUS_Success));
+    ASSERT_NO_THROW(status.setStatusMessage("Success"));
+
+    EXPECT_EQ(STATUS_Success, status.getStatusCode());
+    EXPECT_EQ("Success", status.getStatusMessage());
+}
+
+// This test verifies that the option returns its length correctly.
+TEST(Option6StatusCodeTest, length) {
+    Option6StatusCode status(STATUS_Success, "");
+    EXPECT_EQ(6, status.len());
+
+    ASSERT_NO_THROW(status.setStatusMessage("non-empty message"));
+    EXPECT_EQ(23, status.len());
+}
+
+// This test verifies that the option can be encoded into the wire
+// format.
+TEST(Option6StatusCodeTest, pack) {
+    Option6StatusCode status(STATUS_NoBinding, "text");
+    util::OutputBuffer buf(10);
+    ASSERT_NO_THROW(status.pack(buf));
+
+    const uint8_t ref[] = {
+        0, 13, // Option code is 13
+        0, 6,  // Length is 6
+        0, 3,  // NoBinding
+        't', 'e', 'x', 't'
+    };
+
+    ASSERT_EQ(sizeof(ref), buf.getLength());
+    const void* packed = buf.getData();
+    EXPECT_EQ(0, memcmp(static_cast<const void*>(ref), packed, sizeof(ref)));
+}
+
+// This test verifies that the option can be encoded into the
+// wire format when the status message is empty.
+TEST(Option6StatusCodeTest, packEmptyStatusMessage) {
+    Option6StatusCode status(STATUS_NoAddrsAvail, "");
+    util::OutputBuffer buf(10);
+    ASSERT_NO_THROW(status.pack(buf));
+
+    const uint8_t ref[] = {
+        0, 13, // Option code is 13
+        0, 2,  // Length is 2
+        0, 2,  // NoAddrsAvail
+    };
+
+    ASSERT_EQ(sizeof(ref), buf.getLength());
+    const void* packed = buf.getData();
+    EXPECT_EQ(0, memcmp(static_cast<const void*>(ref), packed, sizeof(ref)));
+}
+
+
+// This test verifies that the option can be parsed from the wire
+// format.
+TEST(Option6StatusCodeTest, unpack) {
+    const uint8_t wire_data[] = {
+        0, 1,          // status code = UnspecFail
+        'x', 'y', 'z', // short text: xyz
+    };
+    OptionBuffer buf(wire_data, wire_data + sizeof(wire_data));
+
+    // Create option from buffer.
+    Option6StatusCodePtr status;
+    ASSERT_NO_THROW(status.reset(new Option6StatusCode(buf.begin(), buf.end())));
+
+    // Verify that the data was parsed correctly.
+    EXPECT_EQ(STATUS_UnspecFail, status->getStatusCode());
+    EXPECT_EQ("xyz", status->getStatusMessage());
+
+    // Remove the status message and leave only the status code.
+    buf.resize(2);
+    // Modify the status code.
+    buf[1] = 0;
+
+    ASSERT_NO_THROW(status.reset(new Option6StatusCode(buf.begin(), buf.end())));
+    EXPECT_EQ(STATUS_Success, status->getStatusCode());
+    EXPECT_TRUE(status->getStatusMessage().empty());
+}
+
+// This test verifies that the option data can be presented
+// in the textual form.
+TEST(Option6StatusCodeTest, dataToText) {
+    Option6StatusCode status(STATUS_NoBinding, "Sorry, no binding");
+    EXPECT_EQ("NoBinding(3) \"Sorry, no binding\"",
+              status.dataToText());
+}
+
+// This test verifies that the option can be presented in the
+// textual form.
+TEST(Option6StatusCodeTest, toText) {
+    Option6StatusCode status(STATUS_NoAddrsAvail, "Sorry, no address");
+    EXPECT_EQ("type=00013, len=00019: NoAddrsAvail(2) \"Sorry, no address\"",
+              status.toText());
+
+    Option6StatusCode status_empty(STATUS_NoBinding, "");
+    EXPECT_EQ("type=00013, len=00002: NoBinding(3) (no status message)",
+              status_empty.toText());
+}
+
+
+/// @brief Test that the status code name is returned correctly.
+///
+/// @param expected_name Expected name.
+/// @param status_code Status code for which test is performed.
+void testStatusName(const std::string& expected_name,
+                    const uint16_t status_code) {
+    Option6StatusCode status(status_code, "some text");
+    EXPECT_EQ(expected_name, status.getStatusCodeName());
+}
+
+// This test verifies that the status code name is
+// returned correctly.
+TEST(Option6StatusCodeTest, getStatusCodeName) {
+    testStatusName("Success", STATUS_Success);
+    testStatusName("UnspecFail", STATUS_UnspecFail);
+    testStatusName("NoAddrsAvail", STATUS_NoAddrsAvail);
+    testStatusName("NoBinding", STATUS_NoBinding);
+    testStatusName("NotOnLink", STATUS_NotOnLink);
+    testStatusName("UseMulticast", STATUS_UseMulticast);
+    testStatusName("NoPrefixAvail", STATUS_NoPrefixAvail);
+    testStatusName("UnknownQueryType", STATUS_UnknownQueryType);
+    testStatusName("MalformedQuery", STATUS_MalformedQuery);
+    testStatusName("NotConfigured", STATUS_NotConfigured);
+    testStatusName("NotAllowed", STATUS_NotAllowed);
+    testStatusName("(unknown status code)", 1234);
+}
+
+} // anonymous namespace

+ 112 - 14
src/lib/dhcp/tests/pkt6_unittest.cc

@@ -129,9 +129,9 @@ public:
     /// length as an input. This constructor is normally used to parse
     /// received packets. It stores the packet in a data_ field and
     /// therefore unpack() can be called to parse it.
-    Pkt6Ptr packAndClone() {
-        Pkt6Ptr parent(new Pkt6(DHCPV6_SOLICIT, 0x020304));
-
+    ///
+    /// @param parent Packet from which the new packet should be created.
+    Pkt6Ptr packAndClone(Pkt6Ptr& parent) {
         OptionPtr opt1(new Option(Option::V6, 1));
         OptionPtr opt2(new Option(Option::V6, 2));
         OptionPtr opt3(new Option(Option::V6, 100));
@@ -141,17 +141,8 @@ public:
         parent->addOption(opt2);
         parent->addOption(opt3);
 
-        EXPECT_EQ(DHCPV6_SOLICIT, parent->getType());
-
-        // Calculated length should be 16
-        EXPECT_EQ(Pkt6::DHCPV6_PKT_HDR_LEN + 3 * Option::OPTION6_HDR_LEN,
-                  parent->len());
-
         EXPECT_NO_THROW(parent->pack());
 
-        EXPECT_EQ(Pkt6::DHCPV6_PKT_HDR_LEN + 3 * Option::OPTION6_HDR_LEN,
-                  parent->len());
-
         // Create second packet,based on assembled data from the first one
         Pkt6Ptr clone(new Pkt6(static_cast<const uint8_t*>
                                (parent->getBuffer().getData()),
@@ -306,7 +297,8 @@ TEST_F(Pkt6Test, unpack_solicit1) {
 
 TEST_F(Pkt6Test, packUnpack) {
     // Create an on-wire representation of the test packet and clone it.
-    Pkt6Ptr clone = packAndClone();
+    Pkt6Ptr pkt(new Pkt6(DHCPV6_SOLICIT, 0x020304));
+    Pkt6Ptr clone = packAndClone(pkt);
 
     // Now recreate options list
     ASSERT_NO_THROW(clone->unpack());
@@ -383,7 +375,8 @@ TEST_F(Pkt6Test, unpackMalformed) {
 // the option parsing algorithm by installing a callback function.
 TEST_F(Pkt6Test, packUnpackWithCallback) {
     // Create an on-wire representation of the test packet and clone it.
-    Pkt6Ptr clone = packAndClone();
+    Pkt6Ptr pkt(new Pkt6(DHCPV6_SOLICIT, 0x020304));
+    Pkt6Ptr clone = packAndClone(pkt);
 
     // Install the custom callback function. We expect that this function
     // will be called to parse options in the packet instead of
@@ -516,6 +509,10 @@ TEST_F(Pkt6Test, getName) {
         uint8_t type = itype;
 
         switch (type) {
+        case DHCPV6_ADVERTISE:
+            EXPECT_STREQ("ADVERTISE", Pkt6::getName(type));
+            break;
+
         case DHCPV6_CONFIRM:
             EXPECT_STREQ("CONFIRM", Pkt6::getName(type));
             break;
@@ -529,10 +526,30 @@ TEST_F(Pkt6Test, getName) {
                          Pkt6::getName(type));
             break;
 
+        case DHCPV6_LEASEQUERY:
+            EXPECT_STREQ("LEASEQUERY", Pkt6::getName(type));
+            break;
+
+        case DHCPV6_LEASEQUERY_REPLY:
+            EXPECT_STREQ("LEASEQUERY_REPLY", Pkt6::getName(type));
+            break;
+
         case DHCPV6_REBIND:
             EXPECT_STREQ("REBIND", Pkt6::getName(type));
             break;
 
+        case DHCPV6_RECONFIGURE:
+            EXPECT_STREQ("RECONFIGURE", Pkt6::getName(type));
+            break;
+
+        case DHCPV6_RELAY_FORW:
+            EXPECT_STREQ("RELAY_FORWARD", Pkt6::getName(type));
+            break;
+
+        case DHCPV6_RELAY_REPL:
+            EXPECT_STREQ("RELAY_REPLY", Pkt6::getName(type));
+            break;
+
         case DHCPV6_RELEASE:
             EXPECT_STREQ("RELEASE", Pkt6::getName(type));
             break;
@@ -541,6 +558,10 @@ TEST_F(Pkt6Test, getName) {
             EXPECT_STREQ("RENEW", Pkt6::getName(type));
             break;
 
+        case DHCPV6_REPLY:
+            EXPECT_STREQ("REPLY", Pkt6::getName(type));
+            break;
+
         case DHCPV6_REQUEST:
             EXPECT_STREQ("REQUEST", Pkt6::getName(type));
             break;
@@ -1327,5 +1348,82 @@ TEST_F(Pkt6Test, rsoo) {
 
 }
 
+// Verify that the DUID can be extracted from the DHCPv6 packet
+// holding Client Identifier option.
+TEST_F(Pkt6Test, getClientId) {
+    // Create a packet.
+    Pkt6Ptr pkt(new Pkt6(DHCPV6_SOLICIT, 0x2312));
+    // Initially, the packet should hold no DUID.
+    EXPECT_FALSE(pkt->getClientId());
+
+    // Create DUID and add it to the packet.
+    const uint8_t duid_data[] = { 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 0 };
+    OptionBuffer duid_vec(duid_data, duid_data + sizeof(duid_data) - 1);
+    pkt->addOption(OptionPtr(new Option(Option::V6, D6O_CLIENTID,
+                                        duid_vec.begin(),
+                                        duid_vec.end())));
+
+    // Simulate the packet transmission over the wire, i.e. create on
+    // wire representation of the packet, and then parse it.
+    Pkt6Ptr pkt_clone = packAndClone(pkt);
+    ASSERT_NO_THROW(pkt_clone->unpack());
+
+    // This time the DUID should be returned.
+    DuidPtr duid = pkt_clone->getClientId();
+    ASSERT_TRUE(duid);
+
+    // And it should be equal to the one that we used to create
+    // the packet.
+    EXPECT_TRUE(duid->getDuid() == duid_vec);
+}
+
+// This test verfies that it is possible to obtain the packet
+// identifiers (DUID, HW Address, transaction id) in the textual
+// format.
+TEST_F(Pkt6Test, makeLabel) {
+    DuidPtr duid(new DUID(DUID::fromText("0102020202030303030303")));
+    HWAddrPtr hwaddr(new HWAddr(HWAddr::fromText("01:02:03:04:05:06",
+                                                 HTYPE_ETHER)));
+
+    // Specify DUID and no HW Address.
+    EXPECT_EQ("duid=[01:02:02:02:02:03:03:03:03:03:03], tid=0x123",
+              Pkt6::makeLabel(duid, 0x123, HWAddrPtr()));
+
+    // Specify HW Address and no DUID.
+    EXPECT_EQ("duid=[no info], [hwtype=1 01:02:03:04:05:06], tid=0x123",
+              Pkt6::makeLabel(DuidPtr(), 0x123, hwaddr));
+
+    // Specify both DUID and HW Address.
+    EXPECT_EQ("duid=[01:02:02:02:02:03:03:03:03:03:03], "
+              "[hwtype=1 01:02:03:04:05:06], tid=0x123",
+              Pkt6::makeLabel(duid, 0x123, hwaddr));
+
+    // Specify neither DUID nor HW Address.
+    EXPECT_EQ("duid=[no info], tid=0x0",
+              Pkt6::makeLabel(DuidPtr(), 0x0, HWAddrPtr()));
+}
+
+// This test verifies that it is possible to obtain the packet
+// identifiers in the textual format from the packet instance.
+TEST_F(Pkt6Test, getLabel) {
+    // Create a packet.
+    Pkt6Ptr pkt(new Pkt6(DHCPV6_SOLICIT, 0x2312));
+    EXPECT_EQ("duid=[no info], tid=0x2312",
+              pkt->getLabel());
+
+    DuidPtr duid(new DUID(DUID::fromText("0102020202030303030303")));
+    pkt->addOption(OptionPtr(new Option(Option::V6, D6O_CLIENTID,
+                                        duid->getDuid().begin(),
+                                        duid->getDuid().end())));
+
+    // Simulate the packet transmission over the wire, i.e. create on
+    // wire representation of the packet, and then parse it.
+    Pkt6Ptr pkt_clone = packAndClone(pkt);
+    ASSERT_NO_THROW(pkt_clone->unpack());
+
+    EXPECT_EQ("duid=[01:02:02:02:02:03:03:03:03:03:03], tid=0x2312",
+              pkt_clone->getLabel());
+
+}
 
 }