Browse Source

[1545] Add logging to the DHCPv6 server code

Stephen Morris 12 years ago
parent
commit
9c0444c02e

+ 13 - 4
src/bin/dhcp6/Makefile.am

@@ -13,7 +13,7 @@ endif
 
 
 pkglibexecdir = $(libexecdir)/@PACKAGE@
 pkglibexecdir = $(libexecdir)/@PACKAGE@
 
 
-CLEANFILES = spec_config.h
+CLEANFILES = spec_config.h dhcp6_messages.h dhcp6_messages.cc
 
 
 man_MANS = b10-dhcp6.8
 man_MANS = b10-dhcp6.8
 DISTCLEANFILES = $(man_MANS)
 DISTCLEANFILES = $(man_MANS)
@@ -37,11 +37,20 @@ endif
 spec_config.h: spec_config.h.pre
 spec_config.h: spec_config.h.pre
 	$(SED) -e "s|@@LOCALSTATEDIR@@|$(localstatedir)|" spec_config.h.pre >$@
 	$(SED) -e "s|@@LOCALSTATEDIR@@|$(localstatedir)|" spec_config.h.pre >$@
 
 
-BUILT_SOURCES = spec_config.h
+dhcp6_messages.h dhcp6_messages.cc: dhcp6_messages.mes
+	$(top_builddir)/src/lib/log/compiler/message $(top_srcdir)/src/bin/dhcp6/dhcp6_messages.mes
+
+BUILT_SOURCES = spec_config.h dhcp6_messages.h dhcp6_messages.cc
+
 pkglibexec_PROGRAMS = b10-dhcp6
 pkglibexec_PROGRAMS = b10-dhcp6
 
 
-b10_dhcp6_SOURCES = main.cc dhcp6_srv.cc dhcp6_srv.h
+b10_dhcp6_SOURCES  = main.cc
 b10_dhcp6_SOURCES += ctrl_dhcp6_srv.cc ctrl_dhcp6_srv.h
 b10_dhcp6_SOURCES += ctrl_dhcp6_srv.cc ctrl_dhcp6_srv.h
+b10_dhcp6_SOURCES += dhcp6_log.cc dhcp6_log.h
+b10_dhcp6_SOURCES += dhcp6_srv.cc dhcp6_srv.h
+
+nodist_b10_dhcp6_SOURCES = dhcp6_messages.h dhcp6_messages.cc
+EXTRA_DIST += dhcp6_messages.mes
 
 
 if USE_CLANGPP
 if USE_CLANGPP
 # Disable unused parameter warning caused by some of the
 # Disable unused parameter warning caused by some of the
@@ -49,7 +58,7 @@ if USE_CLANGPP
 b10_dhcp6_CXXFLAGS = -Wno-unused-parameter
 b10_dhcp6_CXXFLAGS = -Wno-unused-parameter
 endif
 endif
 
 
-b10_dhcp6_LDADD = $(top_builddir)/src/lib/exceptions/libb10-exceptions.la
+b10_dhcp6_LDADD  = $(top_builddir)/src/lib/exceptions/libb10-exceptions.la
 b10_dhcp6_LDADD += $(top_builddir)/src/lib/asiolink/libb10-asiolink.la
 b10_dhcp6_LDADD += $(top_builddir)/src/lib/asiolink/libb10-asiolink.la
 b10_dhcp6_LDADD += $(top_builddir)/src/lib/log/libb10-log.la
 b10_dhcp6_LDADD += $(top_builddir)/src/lib/log/libb10-log.la
 b10_dhcp6_LDADD += $(top_builddir)/src/lib/dhcp/libb10-dhcp++.la
 b10_dhcp6_LDADD += $(top_builddir)/src/lib/dhcp/libb10-dhcp++.la

+ 23 - 20
src/bin/dhcp6/ctrl_dhcp6_srv.cc

@@ -13,28 +13,30 @@
 // PERFORMANCE OF THIS SOFTWARE.
 // PERFORMANCE OF THIS SOFTWARE.
 
 
 #include <config.h>
 #include <config.h>
+
 #include <cassert>
 #include <cassert>
 #include <iostream>
 #include <iostream>
 
 
-#include <cc/session.h>
+#include <asiolink/asiolink.h>
 #include <cc/data.h>
 #include <cc/data.h>
-#include <exceptions/exceptions.h>
+#include <cc/session.h>
 #include <cc/session.h>
 #include <cc/session.h>
 #include <config/ccsession.h>
 #include <config/ccsession.h>
-#include <util/buffer.h>
-#include <dhcp6/spec_config.h>
 #include <dhcp6/ctrl_dhcp6_srv.h>
 #include <dhcp6/ctrl_dhcp6_srv.h>
+#include <dhcp6/dhcp6_log.h>
+#include <dhcp6/spec_config.h>
 #include <dhcp/iface_mgr.h>
 #include <dhcp/iface_mgr.h>
-#include <asiolink/asiolink.h>
+#include <exceptions/exceptions.h>
+#include <util/buffer.h>
 
 
-using namespace std;
-using namespace isc::util;
-using namespace isc::dhcp;
-using namespace isc::util;
-using namespace isc::data;
+using namespace isc::asiolink;
 using namespace isc::cc;
 using namespace isc::cc;
 using namespace isc::config;
 using namespace isc::config;
-using namespace isc::asiolink;
+using namespace isc::data;
+using namespace isc::dhcp;
+using namespace isc::log;
+using namespace isc::util;
+using namespace std;
 
 
 namespace isc {
 namespace isc {
 namespace dhcp {
 namespace dhcp {
@@ -43,7 +45,8 @@ ControlledDhcpv6Srv* ControlledDhcpv6Srv::server_ = NULL;
 
 
 ConstElementPtr
 ConstElementPtr
 ControlledDhcpv6Srv::dhcp6ConfigHandler(ConstElementPtr new_config) {
 ControlledDhcpv6Srv::dhcp6ConfigHandler(ConstElementPtr new_config) {
-    cout << "b10-dhcp6: Received new config:" << new_config->str() << endl;
+    LOG_DEBUG(dhcp6_logger, DBG_DHCP6_COMMAND, DHCP6_CONFIG_UPDATE)
+              .arg(new_config->str());
     ConstElementPtr answer = isc::config::createAnswer(0,
     ConstElementPtr answer = isc::config::createAnswer(0,
                              "Thank you for sending config.");
                              "Thank you for sending config.");
     return (answer);
     return (answer);
@@ -51,13 +54,14 @@ ControlledDhcpv6Srv::dhcp6ConfigHandler(ConstElementPtr new_config) {
 
 
 ConstElementPtr
 ConstElementPtr
 ControlledDhcpv6Srv::dhcp6CommandHandler(const string& command, ConstElementPtr args) {
 ControlledDhcpv6Srv::dhcp6CommandHandler(const string& command, ConstElementPtr args) {
-    cout << "b10-dhcp6: Received new command: [" << command << "], args="
-         << args->str() << endl;
+    LOG_DEBUG(dhcp6_logger, DBG_DHCP6_COMMAND, DHCP6_COMMAND_RECEIVED)
+              .arg(command).arg(args->str());
+
     if (command == "shutdown") {
     if (command == "shutdown") {
         if (ControlledDhcpv6Srv::server_) {
         if (ControlledDhcpv6Srv::server_) {
             ControlledDhcpv6Srv::server_->shutdown();
             ControlledDhcpv6Srv::server_->shutdown();
         } else {
         } else {
-            cout << "Server not initialized yet or already shut down." << endl;
+            LOG_WARN(dhcp6_logger, DHCP6_NOT_RUNNING);
             ConstElementPtr answer = isc::config::createAnswer(1,
             ConstElementPtr answer = isc::config::createAnswer(1,
                                      "Shutdown failure.");
                                      "Shutdown failure.");
             return (answer);
             return (answer);
@@ -93,10 +97,9 @@ void ControlledDhcpv6Srv::establishSession() {
 
 
     /// @todo: Check if session is not established already. Throw, if it is.
     /// @todo: Check if session is not established already. Throw, if it is.
     
     
-    cout << "b10-dhcp6: my specfile is " << specfile << endl;
-    
+    LOG_DEBUG(dhcp6_logger, DBG_DHCP6_START, DHCP6_CCSESSION_STARTING)
+              .arg(specfile);
     cc_session_ = new Session(io_service_.get_io_service());
     cc_session_ = new Session(io_service_.get_io_service());
-
     config_session_ = new ModuleCCSession(specfile, *cc_session_,
     config_session_ = new ModuleCCSession(specfile, *cc_session_,
                                           dhcp6ConfigHandler,
                                           dhcp6ConfigHandler,
                                           dhcp6CommandHandler, false);
                                           dhcp6CommandHandler, false);
@@ -106,8 +109,8 @@ void ControlledDhcpv6Srv::establishSession() {
     /// control with the "select" model of the DHCP server.  This is
     /// control with the "select" model of the DHCP server.  This is
     /// fully explained in \ref dhcpv6Session.
     /// fully explained in \ref dhcpv6Session.
     int ctrl_socket = cc_session_->getSocketDesc();
     int ctrl_socket = cc_session_->getSocketDesc();
-    cout << "b10-dhcp6: Control session started, socket="
-         << ctrl_socket << endl;
+    LOG_DEBUG(dhcp6_logger, DBG_DHCP6_START, DHCP6_CCSESSION_STARTED)
+              .arg(ctrl_socket);
     IfaceMgr::instance().set_session_socket(ctrl_socket, sessionReader);
     IfaceMgr::instance().set_session_socket(ctrl_socket, sessionReader);
 }
 }
 
 

+ 26 - 0
src/bin/dhcp6/dhcp6_log.cc

@@ -0,0 +1,26 @@
+// Copyright (C) 2011  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.
+
+/// Defines the logger used by the top-level component of b10-dhcp6.
+
+#include "dhcp6_log.h"
+
+namespace isc {
+namespace dhcp {
+
+isc::log::Logger dhcp6_logger("dhcp6");
+
+} // namespace dhcp
+} // namespace isc
+

+ 59 - 0
src/bin/dhcp6/dhcp6_log.h

@@ -0,0 +1,59 @@
+// Copyright (C) 2011  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 __DHCP6_LOG__H
+#define __DHCP6_LOG__H
+
+#include <log/macros.h>
+#include <log/logger_support.h>
+#include <dhcp6/dhcp6_messages.h>
+
+namespace isc {
+namespace dhcp {
+
+/// \brief DHCP6 Logging
+///
+/// Defines the levels used to output debug messages in the non-library part of
+/// the b10-dhcp6 program.  Higher numbers equate to more verbose (and detailed)
+/// output.
+
+// Debug levels used to log information during startup and shutdown.
+const int DBG_DHCP6_START = DBGLVL_START_SHUT;
+const int DBG_DHCP6_SHUT = DBGLVL_START_SHUT;
+
+// Debug level used to log setting information (such as configuration changes).
+const int DBG_DHCP6_COMMAND = DBGLVL_COMMAND;
+
+// Trace basic operations within the code.
+const int DBG_DHCP6_BASIC = 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.)
+const int DBG_DHCP6_DETAIL = DBGLVL_TRACE_DETAIL;
+
+// 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 b10-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.
+extern isc::log::Logger dhcp6_logger;
+
+} // namespace dhcp6
+} // namespace isc
+
+#endif // __DHCP6_LOG__H

+ 88 - 27
src/bin/dhcp6/dhcp6_srv.cc

@@ -14,23 +14,25 @@
 
 
 #include <stdlib.h>
 #include <stdlib.h>
 #include <time.h>
 #include <time.h>
+
+#include <asiolink/io_address.h>
+#include <dhcp6/dhcp6_log.h>
+#include <dhcp6/dhcp6_srv.h>
 #include <dhcp/dhcp6.h>
 #include <dhcp/dhcp6.h>
-#include <dhcp/pkt6.h>
 #include <dhcp/iface_mgr.h>
 #include <dhcp/iface_mgr.h>
-#include <dhcp6/dhcp6_srv.h>
-#include <dhcp/option6_ia.h>
-#include <dhcp/option6_iaaddr.h>
 #include <dhcp/option6_addrlst.h>
 #include <dhcp/option6_addrlst.h>
-#include <asiolink/io_address.h>
+#include <dhcp/option6_iaaddr.h>
+#include <dhcp/option6_ia.h>
+#include <dhcp/pkt6.h>
 #include <exceptions/exceptions.h>
 #include <exceptions/exceptions.h>
 #include <util/io_utilities.h>
 #include <util/io_utilities.h>
 #include <util/range_utilities.h>
 #include <util/range_utilities.h>
 
 
-using namespace std;
 using namespace isc;
 using namespace isc;
-using namespace isc::dhcp;
 using namespace isc::asiolink;
 using namespace isc::asiolink;
+using namespace isc::dhcp;
 using namespace isc::util;
 using namespace isc::util;
+using namespace std;
 
 
 const std::string HARDCODED_LEASE = "2001:db8:1::1234:abcd";
 const std::string HARDCODED_LEASE = "2001:db8:1::1234:abcd";
 const uint32_t HARDCODED_T1 = 1500; // in seconds
 const uint32_t HARDCODED_T1 = 1500; // in seconds
@@ -40,14 +42,14 @@ const uint32_t HARDCODED_VALID_LIFETIME = 7200; // in seconds
 const std::string HARDCODED_DNS_SERVER = "2001:db8:1::1";
 const std::string HARDCODED_DNS_SERVER = "2001:db8:1::1";
 
 
 Dhcpv6Srv::Dhcpv6Srv(uint16_t port) {
 Dhcpv6Srv::Dhcpv6Srv(uint16_t port) {
-    cout << "Initialization: opening sockets on port " << port << endl;
+    LOG_DEBUG(dhcp6_logger, DBG_DHCP6_START, DHCP6_OPEN_SOCKET).arg(port);
 
 
-    // first call to instance() will create IfaceMgr (it's a singleton)
+    // First call to instance() will create IfaceMgr (it's a singleton)
     // it may throw something if things go wrong
     // it may throw something if things go wrong
     try {
     try {
 
 
         if (IfaceMgr::instance().countIfaces() == 0) {
         if (IfaceMgr::instance().countIfaces() == 0) {
-            cout << "Failed to detect any network interfaces. Aborting." << endl;
+            LOG_ERROR(dhcp6_logger, DHCP6_NO_INTERFACES);
             shutdown_ = true;
             shutdown_ = true;
             return;
             return;
         }
         }
@@ -59,7 +61,7 @@ Dhcpv6Srv::Dhcpv6Srv(uint16_t port) {
         /// @todo: instantiate LeaseMgr here once it is imlpemented.
         /// @todo: instantiate LeaseMgr here once it is imlpemented.
 
 
     } catch (const std::exception &e) {
     } catch (const std::exception &e) {
-        cerr << "Error during DHCPv4 server startup: " << e.what() << endl;
+        LOG_ERROR(dhcp6_logger, DHCP6_SRV_CONSTRUCT_ERROR).arg(e.what());
         shutdown_ = true;
         shutdown_ = true;
         return;
         return;
     }
     }
@@ -68,13 +70,11 @@ Dhcpv6Srv::Dhcpv6Srv(uint16_t port) {
 }
 }
 
 
 Dhcpv6Srv::~Dhcpv6Srv() {
 Dhcpv6Srv::~Dhcpv6Srv() {
-    cout << "DHCPv6 Srv shutdown." << endl;
-
     IfaceMgr::instance().closeSockets();
     IfaceMgr::instance().closeSockets();
 }
 }
 
 
 void Dhcpv6Srv::shutdown() {
 void Dhcpv6Srv::shutdown() {
-    cout << "b10-dhcp6: DHCPv6 server shutdown." << endl;
+    LOG_DEBUG(dhcp6_logger, DBG_DHCP6_BASIC, DHCP6_SHUTDOWN_REQUEST);
     shutdown_ = true;
     shutdown_ = true;
 }
 }
 
 
@@ -89,42 +89,58 @@ bool Dhcpv6Srv::run() {
 
 
         if (query) {
         if (query) {
             if (!query->unpack()) {
             if (!query->unpack()) {
-                cout << "Failed to parse incoming packet" << endl;
+                LOG_DEBUG(dhcp6_logger, DBG_DHCP6_DETAIL,
+                          DHCP6_PACKET_PARSE_FAIL);
                 continue;
                 continue;
             }
             }
+            LOG_DEBUG(dhcp6_logger, DBG_DHCP6_DETAIL, DHCP6_PACKET_RECEIVED)
+                      .arg(serverReceivedPacketName(query->getType()))
+                      .arg(query->getType());
+            LOG_DEBUG(dhcp6_logger, DBG_DHCP6_DETAIL_DATA, DHCP6_QUERY_DATA)
+                      .arg(query->getType())
+                      .arg(query->getBuffer().getLength())
+                      .arg(query->toText());
+
             switch (query->getType()) {
             switch (query->getType()) {
             case DHCPV6_SOLICIT:
             case DHCPV6_SOLICIT:
                 rsp = processSolicit(query);
                 rsp = processSolicit(query);
                 break;
                 break;
+
             case DHCPV6_REQUEST:
             case DHCPV6_REQUEST:
                 rsp = processRequest(query);
                 rsp = processRequest(query);
                 break;
                 break;
+
             case DHCPV6_RENEW:
             case DHCPV6_RENEW:
                 rsp = processRenew(query);
                 rsp = processRenew(query);
                 break;
                 break;
+
             case DHCPV6_REBIND:
             case DHCPV6_REBIND:
                 rsp = processRebind(query);
                 rsp = processRebind(query);
                 break;
                 break;
+
             case DHCPV6_CONFIRM:
             case DHCPV6_CONFIRM:
                 rsp = processConfirm(query);
                 rsp = processConfirm(query);
                 break;
                 break;
+
             case DHCPV6_RELEASE:
             case DHCPV6_RELEASE:
                 rsp = processRelease(query);
                 rsp = processRelease(query);
                 break;
                 break;
+
             case DHCPV6_DECLINE:
             case DHCPV6_DECLINE:
                 rsp = processDecline(query);
                 rsp = processDecline(query);
                 break;
                 break;
+
             case DHCPV6_INFORMATION_REQUEST:
             case DHCPV6_INFORMATION_REQUEST:
                 rsp = processInfRequest(query);
                 rsp = processInfRequest(query);
                 break;
                 break;
+
             default:
             default:
-                cout << "Unknown pkt type received:"
-                     << query->getType() << endl;
+                // Only action is to output a message if debug is enabled,
+                // and that will be covered by the debug statement before
+                // the "switch" statement.
+                ;
             }
             }
 
 
-            cout << "Received " << query->getBuffer().getLength() << " bytes packet type="
-                 << query->getType() << endl;
-            cout << query->toText();
             if (rsp) {
             if (rsp) {
                 rsp->setRemoteAddr(query->getRemoteAddr());
                 rsp->setRemoteAddr(query->getRemoteAddr());
                 rsp->setLocalAddr(query->getLocalAddr());
                 rsp->setLocalAddr(query->getLocalAddr());
@@ -132,14 +148,16 @@ bool Dhcpv6Srv::run() {
                 rsp->setLocalPort(DHCP6_SERVER_PORT);
                 rsp->setLocalPort(DHCP6_SERVER_PORT);
                 rsp->setIndex(query->getIndex());
                 rsp->setIndex(query->getIndex());
                 rsp->setIface(query->getIface());
                 rsp->setIface(query->getIface());
-                cout << "Replying with:" << rsp->getType() << endl;
-                cout << rsp->toText();
-                cout << "----" << endl;
-                if (!rsp->pack()) {
-                    cout << "Failed to assemble response packet." << endl;
-                    continue;
+
+                LOG_DEBUG(dhcp6_logger, DBG_DHCP6_DETAIL_DATA,
+                          DHCP6_RESPONSE_DATA)
+                          .arg(rsp->getType()).arg(rsp->toText());
+
+                if (rsp->pack()) {
+                    IfaceMgr::instance().send(rsp);
+                } else {
+                    LOG_ERROR(dhcp6_logger, DHCP6_PACK_FAIL);
                 }
                 }
-                IfaceMgr::instance().send(rsp);
             }
             }
         }
         }
 
 
@@ -350,3 +368,46 @@ Pkt6Ptr Dhcpv6Srv::processInfRequest(const Pkt6Ptr& infRequest) {
     Pkt6Ptr reply(new Pkt6(DHCPV6_REPLY, infRequest->getTransid()));
     Pkt6Ptr reply(new Pkt6(DHCPV6_REPLY, infRequest->getTransid()));
     return reply;
     return reply;
 }
 }
+
+const char*
+Dhcpv6Srv::serverReceivedPacketName(uint8_t type) {
+    static const char* CONFIRM = "CONFIRM";
+    static const char* DECLINE = "DECLINE";
+    static const char* INFORMATION_REQUEST = "INFORMATION_REQUEST";
+    static const char* REBIND = "REBIND";
+    static const char* RELEASE = "RELEASE";
+    static const char* RENEW = "RENEW";
+    static const char* REQUEST = "REQUEST";
+    static const char* SOLICIT = "SOLICIT";
+    static const char* UNKNOWN = "UNKNOWN";
+
+    switch (type) {
+    case DHCPV6_CONFIRM:
+        return (CONFIRM);
+
+    case DHCPV6_DECLINE:
+        return (DECLINE);
+
+    case DHCPV6_INFORMATION_REQUEST:
+        return (INFORMATION_REQUEST);
+
+    case DHCPV6_REBIND:
+        return (REBIND);
+
+    case DHCPV6_RELEASE:
+        return (RELEASE);
+
+    case DHCPV6_RENEW:
+        return (RENEW);
+
+    case DHCPV6_REQUEST:
+        return (REQUEST);
+
+    case DHCPV6_SOLICIT:
+        return (SOLICIT);
+
+    default:
+        ;
+    }
+    return (UNKNOWN);
+}

+ 18 - 0
src/bin/dhcp6/dhcp6_srv.h

@@ -69,6 +69,24 @@ public:
 
 
     /// @brief Instructs the server to shut down.
     /// @brief Instructs the server to shut down.
     void shutdown();
     void shutdown();
+
+    /// @brief Return textual type of packet received by server
+    ///
+    /// Returns the name of valid packet received by the server (e.g. DISCOVER).
+    /// If the packet is unknown - or if it is a valid DHCP packet but not one
+    /// expected to be received by the server (such as an OFFER), the string
+    /// "UNKNOWN" is returned.  This methos is used in debug messages.
+    ///
+    /// As the operation of the method does not depend on any server state, it
+    /// is declared static.
+    ///
+    /// @param type DHCPv4 packet type
+    ///
+    /// @return Pointer to "const" string containing the packet name.
+    ///         Note that this string is statically allocated and MUST NOT
+    ///         be freed by the caller.
+    static const char* serverReceivedPacketName(uint8_t type);
+
 protected:
 protected:
     /// @brief Processes incoming SOLICIT and returns response.
     /// @brief Processes incoming SOLICIT and returns response.
     ///
     ///

+ 27 - 31
src/bin/dhcp6/main.cc

@@ -14,13 +14,15 @@
 
 
 #include <config.h>
 #include <config.h>
 #include <iostream>
 #include <iostream>
-#include <log/dummylog.h>
-#include <log/logger_support.h>
-#include <dhcp6/ctrl_dhcp6_srv.h>
+
 #include <boost/lexical_cast.hpp>
 #include <boost/lexical_cast.hpp>
 
 
-using namespace std;
+#include <dhcp6/ctrl_dhcp6_srv.h>
+#include <dhcp6/dhcp6_log.h>
+#include <log/logger_support.h>
+
 using namespace isc::dhcp;
 using namespace isc::dhcp;
+using namespace std;
 
 
 /// This file contains entry point (main() function) for standard DHCPv6 server
 /// This file contains entry point (main() function) for standard DHCPv6 server
 /// component for BIND10 framework. It parses command-line arguments and
 /// component for BIND10 framework. It parses command-line arguments and
@@ -37,11 +39,10 @@ const char* const DHCP6_NAME = "b10-dhcp6";
 
 
 void
 void
 usage() {
 usage() {
-    cerr << "Usage: b10-dhcp6 [-v]"
-         << endl;
-    cerr << "\t-v: verbose output" << endl;
-    cerr << "\t-s: stand-alone mode (don't connect to BIND10)" << endl;
-    cerr << "\t-p number: specify non-standard port number 1-65535 "
+    cerr << "Usage: " << DHCP6_NAME << " [-v] [-s] [-p number]" << endl;
+    cerr << "  -v: verbose output" << endl;
+    cerr << "  -s: stand-alone mode (don't connect to BIND10)" << endl;
+    cerr << "  -p number: specify non-standard port number 1-65535 "
          << "(useful for testing only)" << endl;
          << "(useful for testing only)" << endl;
     exit(EXIT_FAILURE);
     exit(EXIT_FAILURE);
 }
 }
@@ -52,18 +53,19 @@ main(int argc, char* argv[]) {
     int ch;
     int ch;
     int port_number = DHCP6_SERVER_PORT; // The default. Any other values are
     int port_number = DHCP6_SERVER_PORT; // The default. Any other values are
                                          // useful for testing only.
                                          // useful for testing only.
+    bool stand_alone = false;  // Should be connect to BIND10 msgq?
     bool verbose_mode = false; // Should server be verbose?
     bool verbose_mode = false; // Should server be verbose?
-    bool stand_alone = false; // should be connect to BIND10 msgq?
 
 
     while ((ch = getopt(argc, argv, "vsp:")) != -1) {
     while ((ch = getopt(argc, argv, "vsp:")) != -1) {
         switch (ch) {
         switch (ch) {
         case 'v':
         case 'v':
             verbose_mode = true;
             verbose_mode = true;
-            isc::log::denabled = true;
             break;
             break;
+
         case 's':
         case 's':
             stand_alone = true;
             stand_alone = true;
             break;
             break;
+
         case 'p':
         case 'p':
             try {
             try {
                 port_number = boost::lexical_cast<int>(optarg);
                 port_number = boost::lexical_cast<int>(optarg);
@@ -78,51 +80,45 @@ main(int argc, char* argv[]) {
                 usage();
                 usage();
             }
             }
             break;
             break;
-        case ':':
+
         default:
         default:
             usage();
             usage();
         }
         }
     }
     }
 
 
+    // Check for extraneous parameters.
+    if (argc > optind) {
+        usage();
+    }
+
     // Initialize logging.  If verbose, we'll use maximum verbosity.
     // Initialize logging.  If verbose, we'll use maximum verbosity.
     isc::log::initLogger(DHCP6_NAME,
     isc::log::initLogger(DHCP6_NAME,
                          (verbose_mode ? isc::log::DEBUG : isc::log::INFO),
                          (verbose_mode ? isc::log::DEBUG : isc::log::INFO),
                          isc::log::MAX_DEBUG_LEVEL, NULL);
                          isc::log::MAX_DEBUG_LEVEL, NULL);
-
-    cout << "b10-dhcp6: My pid=" << getpid() << ", binding to port "
-         << port_number << ", verbose " << (verbose_mode?"yes":"no")
-         << ", stand-alone=" << (stand_alone?"yes":"no") << endl;
-
-    if (argc - optind > 0) {
-        usage();
-    }
+    LOG_INFO(dhcp6_logger, DHCP6_STARTING);
+    LOG_DEBUG(dhcp6_logger, DBG_DHCP6_START, DHCP6_START_INFO)
+              .arg(getpid()).arg(port_number).arg(verbose_mode ? "yes" : "no")
+              .arg(stand_alone ? "yes" : "no" );
 
 
     int ret = EXIT_SUCCESS;
     int ret = EXIT_SUCCESS;
-
     try {
     try {
-
-        cout << "b10-dhcp6: Initiating DHCPv6 server operation." << endl;
-
-        /// @todo: pass verbose to the actual server once logging is implemented
         ControlledDhcpv6Srv server(port_number);
         ControlledDhcpv6Srv server(port_number);
-
         if (!stand_alone) {
         if (!stand_alone) {
             try {
             try {
                 server.establishSession();
                 server.establishSession();
             } catch (const std::exception& ex) {
             } catch (const std::exception& ex) {
-                cerr << "Failed to establish BIND10 session. "
-                    "Running in stand-alone mode:" << ex.what() << endl;
+                LOG_ERROR(dhcp6_logger, DHCP6_SESSION_FAIL).arg(ex.what());
                 // Let's continue. It is useful to have the ability to run 
                 // Let's continue. It is useful to have the ability to run 
                 // DHCP server in stand-alone mode, e.g. for testing
                 // DHCP server in stand-alone mode, e.g. for testing
             }
             }
         } else {
         } else {
-            cout << "Skipping connection to the BIND10 msgq." << endl;
+            LOG_DEBUG(dhcp6_logger, DBG_DHCP6_START, DHCP6_STANDALONE);
         }
         }
-
         server.run();
         server.run();
+        LOG_INFO(dhcp6_logger, DHCP6_SHUTDOWN);
 
 
     } catch (const std::exception& ex) {
     } catch (const std::exception& ex) {
-        cerr << "[b10-dhcp6] Server failed: " << ex.what() << endl;
+        LOG_FATAL(dhcp6_logger, DHCP6_SERVER_FAILED).arg(ex.what());
         ret = EXIT_FAILURE;
         ret = EXIT_FAILURE;
     }
     }
 
 

+ 5 - 2
src/bin/dhcp6/tests/Makefile.am

@@ -42,10 +42,13 @@ if HAVE_GTEST
 
 
 TESTS += dhcp6_unittests
 TESTS += dhcp6_unittests
 
 
-dhcp6_unittests_SOURCES = ../dhcp6_srv.h ../dhcp6_srv.cc ../ctrl_dhcp6_srv.cc
-dhcp6_unittests_SOURCES += dhcp6_unittests.cc
+dhcp6_unittests_SOURCES  = dhcp6_unittests.cc
 dhcp6_unittests_SOURCES += dhcp6_srv_unittest.cc
 dhcp6_unittests_SOURCES += dhcp6_srv_unittest.cc
 dhcp6_unittests_SOURCES += ctrl_dhcp6_srv_unittest.cc
 dhcp6_unittests_SOURCES += ctrl_dhcp6_srv_unittest.cc
+dhcp6_unittests_SOURCES += ../dhcp6_srv.h ../dhcp6_srv.cc
+dhcp6_unittests_SOURCES += ../dhcp6_log.h ../dhcp6_log.cc
+dhcp6_unittests_SOURCES += ../dhcp6_messages.h ../dhcp6_messages.cc
+dhcp6_unittests_SOURCES += ../ctrl_dhcp6_srv.cc
 
 
 if USE_CLANGPP
 if USE_CLANGPP
 # Disable unused parameter warning caused by some of the
 # Disable unused parameter warning caused by some of the

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

@@ -223,4 +223,49 @@ TEST_F(Dhcpv6SrvTest, Solicit_basic) {
     // more checks to be implemented
     // more checks to be implemented
 }
 }
 
 
+TEST_F(Dhcpv6SrvTest, serverReceivedPacketName) {
+    // Check all possible packet types
+    for (int itype = 0; itype < 256; ++itype) {
+        uint8_t type = itype;
+
+        switch (type) {
+        case DHCPV6_CONFIRM:
+            EXPECT_STREQ("CONFIRM", Dhcpv6Srv::serverReceivedPacketName(type));
+            break;
+
+        case DHCPV6_DECLINE:
+            EXPECT_STREQ("DECLINE", Dhcpv6Srv::serverReceivedPacketName(type));
+            break;
+
+        case DHCPV6_INFORMATION_REQUEST:
+            EXPECT_STREQ("INFORMATION_REQUEST",
+                         Dhcpv6Srv::serverReceivedPacketName(type));
+            break;
+
+        case DHCPV6_REBIND:
+            EXPECT_STREQ("REBIND", Dhcpv6Srv::serverReceivedPacketName(type));
+            break;
+
+        case DHCPV6_RELEASE:
+            EXPECT_STREQ("RELEASE", Dhcpv6Srv::serverReceivedPacketName(type));
+            break;
+
+        case DHCPV6_RENEW:
+            EXPECT_STREQ("RENEW", Dhcpv6Srv::serverReceivedPacketName(type));
+            break;
+
+        case DHCPV6_REQUEST:
+            EXPECT_STREQ("REQUEST", Dhcpv6Srv::serverReceivedPacketName(type));
+            break;
+
+        case DHCPV6_SOLICIT:
+            EXPECT_STREQ("SOLICIT", Dhcpv6Srv::serverReceivedPacketName(type));
+            break;
+
+        default:
+            EXPECT_STREQ("UNKNOWN", Dhcpv6Srv::serverReceivedPacketName(type));
+        }
+    }
 }
 }
+
+}   // oF ANONYMOUS NAMESPACE

+ 24 - 25
src/bin/dhcp6/tests/dhcp6_test.py

@@ -27,16 +27,23 @@ import fcntl
 
 
 class TestDhcpv6Daemon(unittest.TestCase):
 class TestDhcpv6Daemon(unittest.TestCase):
     def setUp(self):
     def setUp(self):
-        # don't redirect stdout/stderr here as we want to print out things
+        # Don't redirect stdout/stderr here as we want to print out things
         # during the test
         # during the test
-        pass
+        #
+        # However, we do want to set the logging lock directory to somewhere
+        # to which we can write - use the current working directory.  We then
+        # set the appropriate environment variable.
+        lockdir_envvar = "B10_LOCKFILE_DIR_FROM_BUILD"
+        lockdir = os.getenv(lockdir_envvar)
+        if lockdir is None:
+            os.putenv(lockdir_envvar, os.getcwd())
 
 
     def tearDown(self):
     def tearDown(self):
         pass
         pass
 
 
     def runCommand(self, params, wait=1):
     def runCommand(self, params, wait=1):
         """
         """
-        This method runs a command and returns a touple: (returncode, stdout, stderr)
+        This method runs a command and returns a tuple: (returncode, stdout, stderr)
         """
         """
         ## @todo: Convert this into generic method and reuse it in dhcp4 and dhcp6
         ## @todo: Convert this into generic method and reuse it in dhcp4 and dhcp6
 
 
@@ -79,9 +86,9 @@ class TestDhcpv6Daemon(unittest.TestCase):
         fcntl.fcntl(fd, fcntl.F_SETFL, fl | os.O_NONBLOCK)
         fcntl.fcntl(fd, fcntl.F_SETFL, fl | os.O_NONBLOCK)
 
 
         # There's potential problem if b10-dhcp4 prints out more
         # There's potential problem if b10-dhcp4 prints out more
-        # than 4k of text
+        # than 16k of text
         try:
         try:
-            output = os.read(self.stdout_pipes[0], 4096)
+            output = os.read(self.stdout_pipes[0], 16384)
         except OSError:
         except OSError:
             print("No data available from stdout")
             print("No data available from stdout")
             output = ""
             output = ""
@@ -91,7 +98,7 @@ class TestDhcpv6Daemon(unittest.TestCase):
             output = ""
             output = ""
 
 
         try:
         try:
-            error = os.read(self.stderr_pipes[0], 4096)
+            error = os.read(self.stderr_pipes[0], 16384)
         except OSError:
         except OSError:
             print("No data available on stderr")
             print("No data available on stderr")
             error = ""
             error = ""
@@ -130,8 +137,8 @@ class TestDhcpv6Daemon(unittest.TestCase):
         print("Note: Purpose of some of the tests is to check if DHCPv6 server can be started,")
         print("Note: Purpose of some of the tests is to check if DHCPv6 server can be started,")
         print("      not that is can bind sockets correctly. Please ignore binding errors.")
         print("      not that is can bind sockets correctly. Please ignore binding errors.")
         (returncode, output, error) = self.runCommand(["../b10-dhcp6", "-v"])
         (returncode, output, error) = self.runCommand(["../b10-dhcp6", "-v"])
-
-        self.assertEqual( str(output).count("b10-dhcp6: Initiating DHCPv6 server operation."), 1)
+        output_text = str(output) + str(error)
+        self.assertEqual(output_text.count("DHCP6_STARTING"), 1)
 
 
     def test_portnumber_0(self):
     def test_portnumber_0(self):
         print("Check that specifying port number 0 is not allowed.")
         print("Check that specifying port number 0 is not allowed.")
@@ -180,27 +187,19 @@ class TestDhcpv6Daemon(unittest.TestCase):
     def test_portnumber_nonroot(self):
     def test_portnumber_nonroot(self):
         print("Check that specifying unprivileged port number will work.")
         print("Check that specifying unprivileged port number will work.")
 
 
-        (returncode, output, error) = self.runCommand(['../b10-dhcp6', '-s', '-p', '10547'])
-
-        # When invalid port number is specified, return code must not be success
-        # TODO: Temporarily commented out as socket binding on systems that do not have
-        #       interface detection implemented currently fails.
-        # self.assertTrue(returncode == 0)
-
-        self.assertEqual( str(output).count("opening sockets on port 10547"), 1)
+        # Check that there is a message about running with an unprivileged port
+        (returncode, output, error) = self.runCommand(['../b10-dhcp6', '-v', '-s', '-p', '10547'])
+        output_text = str(output) + str(error)
+        self.assertEqual(output_text.count("DHCP6_OPEN_SOCKET opening sockets on port 10547"), 1)
 
 
     def test_skip_msgq(self):
     def test_skip_msgq(self):
         print("Check that connection to BIND10 msgq can be disabled.")
         print("Check that connection to BIND10 msgq can be disabled.")
 
 
-        (returncode, output, error) = self.runCommand(['../b10-dhcp6', '-s', '-p', '10547'])
-
-        # When invalid port number is specified, return code must not be success
-        # TODO: Temporarily commented out as socket binding on systems that do not have
-        #       interface detection implemented currently fails.
-        # self.assertTrue(returncode == 0)
-
-        self.assertEqual( str(output).count("Skipping connection to the BIND10 msgq."), 1)
-
+        # Check that the system outputs a message on one of its streams about running
+        # standalone.
+        (returncode, output, error) = self.runCommand(['../b10-dhcp6', '-v', '-s', '-p', '10547'])
+        output_text = str(output) + str(error)
+        self.assertEqual(output_text.count("DHCP6_STANDALONE"), 1)
 
 
 if __name__ == '__main__':
 if __name__ == '__main__':
     unittest.main()
     unittest.main()