Commit f4566355 authored by Tomek Mrugalski's avatar Tomek Mrugalski 🛰
Browse files

[1708] msgq support in DHCPv6 added.

parent 713e3482
...@@ -72,11 +72,13 @@ ...@@ -72,11 +72,13 @@
* DHCPv6 server component does not support relayed traffic yet, as * DHCPv6 server component does not support relayed traffic yet, as
* support for relay decapsulation is not implemented yet. * support for relay decapsulation is not implemented yet.
* *
* DHCPv6 server component does not listen to BIND10 message queue.
*
* DHCPv6 server component does not use BIND10 logging yet. * DHCPv6 server component does not use BIND10 logging yet.
* *
* DHCPv6 server component is not integrated with boss yet. * @section dhcpv6Session BIND10 message queue integration
*
* DHCPv4 server component is now integrated with BIND10 message queue.
* It follows the same principle as DHCPv4. See \ref dhcpv4Session for
* details.
* *
* @page libdhcp libdhcp++ * @page libdhcp libdhcp++
* *
......
This diff is collapsed.
This diff is collapsed.
...@@ -2455,7 +2455,7 @@ then change those defaults with config set Resolver/forward_addresses[0]/address ...@@ -2455,7 +2455,7 @@ then change those defaults with config set Resolver/forward_addresses[0]/address
&gt; <userinput>config commit</userinput></screen></para> &gt; <userinput>config commit</userinput></screen></para>
<para> <para>
At start, the server will detect available network interfaces During start-up the server will detect available network interfaces
and will attempt to open UDP sockets on all interfaces that and will attempt to open UDP sockets on all interfaces that
are up, running, are not loopback, and have IPv4 address are up, running, are not loopback, and have IPv4 address
assigned. assigned.
...@@ -2465,17 +2465,8 @@ then change those defaults with config set Resolver/forward_addresses[0]/address ...@@ -2465,17 +2465,8 @@ then change those defaults with config set Resolver/forward_addresses[0]/address
will respond to them with OFFER and ACK, respectively. will respond to them with OFFER and ACK, respectively.
Since the DHCPv4 server opens privileged ports, it requires root Since the DHCPv4 server opens privileged ports, it requires root
access. Make sure you run this daemon as root.</para> access. Make sure you run this daemon as root.
</para>
<note>
<para>
Integration with <command>bind10</command> is
planned. Ultimately, <command>b10-dhcp4</command> will not
be started directly, but rather via
<command>bind10</command>. Please be aware of this planned
change.
</para>
</note>
</section> </section>
...@@ -2640,22 +2631,25 @@ const std::string HARDCODED_SERVER_ID = "192.0.2.1";</screen> ...@@ -2640,22 +2631,25 @@ const std::string HARDCODED_SERVER_ID = "192.0.2.1";</screen>
</para> </para>
<para> <para>
The DHCPv6 server is implemented as <command>b10-dhcp6</command> <command>b10-dhcp6</command> is a BIND10 component and is being
daemon. As it is not configurable yet, it is fully autonomous, run under BIND10 framework. To add a DHCPv6 process to the set of running
that is it does not interact with <command>b10-cfgmgr</command>. BIND10 services, you can use following commands in <command>bindctl</command>:
To start DHCPv6 server, simply input: <screen>&gt; <userinput>config add Boss/components b10-dhcp6</userinput>
&gt; <userinput>config set Boss/components/b10-dhcp6/kind dispensable</userinput>
<screen> &gt; <userinput>config commit</userinput></screen>
#<userinput>cd src/bin/dhcp6</userinput> </para>
#<userinput>./b10-dhcp6</userinput>
</screen>
Depending on your installation, <command>b10-dhcp6</command> <para>
binary may reside in src/bin/dhcp6 in your source code To shutdown running <command>b10-dhcp6</command>, please use the
directory, in /usr/local/bin/b10-dhcp6 or other directory following command:
you specified during compilation. <screen>&gt; <userinput>Dhcp6 shutdown</userinput></screen>
or
<screen>&gt; <userinput>config remove Boss/components b10-dhcp6</userinput>
&gt; <userinput>config commit</userinput></screen>
</para>
At start, server will detect available network interfaces <para>
During start-up the server will detect available network interfaces
and will attempt to open UDP sockets on all interfaces that and will attempt to open UDP sockets on all interfaces that
are up, running, are not loopback, are multicast-capable, and are up, running, are not loopback, are multicast-capable, and
have IPv6 address assigned. have IPv6 address assigned.
...@@ -2668,16 +2662,6 @@ const std::string HARDCODED_SERVER_ID = "192.0.2.1";</screen> ...@@ -2668,16 +2662,6 @@ const std::string HARDCODED_SERVER_ID = "192.0.2.1";</screen>
access. Make sure you run this daemon as root. access. Make sure you run this daemon as root.
</para> </para>
<note>
<para>
Integration with <command>bind10</command> is
planned. Ultimately, <command>b10-dhcp6</command> will not
be started directly, but rather via
<command>bind10</command>. Please be aware of this planned
change.
</para>
</note>
</section> </section>
<section id="dhcp6-config"> <section id="dhcp6-config">
...@@ -2691,7 +2675,7 @@ const std::string HARDCODED_SERVER_ID = "192.0.2.1";</screen> ...@@ -2691,7 +2675,7 @@ const std::string HARDCODED_SERVER_ID = "192.0.2.1";</screen>
<para> <para>
At this stage of development, the only way to alter server At this stage of development, the only way to alter server
configuration is to tweak its source code. To do so, please configuration is to tweak its source code. To do so, please
edit src/bin/dhcp6/dhcp6_srv.cc file and modify following edit src/bin/dhcp6/dhcp6_srv.cc file, modify the following
parameters and recompile: parameters and recompile:
<screen> <screen>
const std::string HARDCODED_LEASE = "2001:db8:1::1234:abcd"; const std::string HARDCODED_LEASE = "2001:db8:1::1234:abcd";
......
<html><head><meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"><title>BIND 10 Messages Manual</title><link rel="stylesheet" href="./bind10-guide.css" type="text/css"><meta name="generator" content="DocBook XSL Stylesheets V1.75.2"><meta name="description" content="BIND 10 is a Domain Name System (DNS) suite managed by Internet Systems Consortium (ISC). It includes DNS libraries and modular components for controlling authoritative and recursive DNS servers. This is the messages manual for BIND 10 version 20120405. The most up-to-date version of this document, along with other documents for BIND 10, can be found at ."></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="book" title="BIND 10 Messages Manual"><div class="titlepage"><div><div><h1 class="title"><a name="id1168229451102"></a>BIND 10 Messages Manual</h1></div><div><p class="releaseinfo">This is the messages manual for BIND 10 version <html><head><meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"><title>BIND 10 Messages Manual</title><link rel="stylesheet" type="text/css" href="./bind10-guide.css"><meta name="generator" content="DocBook XSL Stylesheets V1.76.1"><meta name="description" content="BIND 10 is a Domain Name System (DNS) suite managed by Internet Systems Consortium (ISC). It includes DNS libraries and modular components for controlling authoritative and recursive DNS servers. This is the messages manual for BIND 10 version 20120405. The most up-to-date version of this document, along with other documents for BIND 10, can be found at ."></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="book" title="BIND 10 Messages Manual"><div class="titlepage"><div><div><h1 class="title"><a name="idm25567040"></a>BIND 10 Messages Manual</h1></div><div><p class="releaseinfo">This is the messages manual for BIND 10 version
20120405.</p></div><div><p class="copyright">Copyright © 2011-2012 Internet Systems Consortium, Inc.</p></div><div><div class="abstract" title="Abstract"><p class="title"><b>Abstract</b></p><p>BIND 10 is a Domain Name System (DNS) suite managed by 20120405.</p></div><div><p class="copyright">Copyright © 2011-2012 Internet Systems Consortium, Inc.</p></div><div><div class="abstract" title="Abstract"><p class="title"><b>Abstract</b></p><p>BIND 10 is a Domain Name System (DNS) suite managed by
Internet Systems Consortium (ISC). It includes DNS libraries Internet Systems Consortium (ISC). It includes DNS libraries
and modular components for controlling authoritative and and modular components for controlling authoritative and
......
...@@ -33,6 +33,7 @@ BUILT_SOURCES = spec_config.h ...@@ -33,6 +33,7 @@ BUILT_SOURCES = spec_config.h
pkglibexec_PROGRAMS = b10-dhcp6 pkglibexec_PROGRAMS = b10-dhcp6
b10_dhcp6_SOURCES = main.cc dhcp6_srv.cc dhcp6_srv.h b10_dhcp6_SOURCES = main.cc dhcp6_srv.cc dhcp6_srv.h
b10_dhcp6_SOURCES += ctrl_dhcp6_srv.cc ctrl_dhcp6_srv.h
if USE_CLANGPP if USE_CLANGPP
# Disable unused parameter warning caused by some of the # Disable unused parameter warning caused by some of the
...@@ -44,6 +45,8 @@ b10_dhcp6_LDADD = $(top_builddir)/src/lib/exceptions/libexceptions.la ...@@ -44,6 +45,8 @@ b10_dhcp6_LDADD = $(top_builddir)/src/lib/exceptions/libexceptions.la
b10_dhcp6_LDADD += $(top_builddir)/src/lib/asiolink/libasiolink.la b10_dhcp6_LDADD += $(top_builddir)/src/lib/asiolink/libasiolink.la
b10_dhcp6_LDADD += $(top_builddir)/src/lib/log/liblog.la b10_dhcp6_LDADD += $(top_builddir)/src/lib/log/liblog.la
b10_dhcp6_LDADD += $(top_builddir)/src/lib/dhcp/libdhcp++.la b10_dhcp6_LDADD += $(top_builddir)/src/lib/dhcp/libdhcp++.la
b10_dhcp6_LDADD += $(top_builddir)/src/lib/config/libcfgclient.la
b10_dhcp6_LDADD += $(top_builddir)/src/lib/cc/libcc.la
b10_dhcp6dir = $(pkgdatadir) b10_dhcp6dir = $(pkgdatadir)
b10_dhcp6_DATA = dhcp6.spec b10_dhcp6_DATA = dhcp6.spec
// Copyright (C) 2012 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 <cassert>
#include <iostream>
#include <cc/session.h>
#include <cc/data.h>
#include <exceptions/exceptions.h>
#include <cc/session.h>
#include <config/ccsession.h>
#include <util/buffer.h>
#include <dhcp6/spec_config.h>
#include <dhcp6/ctrl_dhcp6_srv.h>
#include <dhcp/iface_mgr.h>
#include <asiolink/asiolink.h>
using namespace std;
using namespace isc::util;
using namespace isc::dhcp;
using namespace isc::util;
using namespace isc::data;
using namespace isc::cc;
using namespace isc::config;
using namespace isc::asiolink;
namespace isc {
namespace dhcp {
ControlledDhcpv6Srv* ControlledDhcpv6Srv::server_ = NULL;
ConstElementPtr
ControlledDhcpv6Srv::dhcp6ConfigHandler(ConstElementPtr new_config) {
cout << "b10-dhcp6: Received new config:" << new_config->str() << endl;
ConstElementPtr answer = isc::config::createAnswer(0,
"Thank you for sending config.");
return (answer);
}
ConstElementPtr
ControlledDhcpv6Srv::dhcp6CommandHandler(const string& command, ConstElementPtr args) {
cout << "b10-dhcp6: Received new command: [" << command << "], args="
<< args->str() << endl;
if (command == "shutdown") {
if (ControlledDhcpv6Srv::server_) {
ControlledDhcpv6Srv::server_->shutdown();
} else {
cout << "Server not initialized yet or already shut down." << endl;
ConstElementPtr answer = isc::config::createAnswer(1,
"Shutdown failure.");
return (answer);
}
ConstElementPtr answer = isc::config::createAnswer(0,
"Shutting down.");
return (answer);
}
ConstElementPtr answer = isc::config::createAnswer(1,
"Unrecognized command.");
return (answer);
}
void ControlledDhcpv6Srv::sessionReader(void) {
// Process one asio event. If there are more events, iface_mgr will call
// this callback more than once.
if (server_) {
server_->io_service_.run_one();
}
}
void ControlledDhcpv6Srv::establishSession() {
string specfile;
if (getenv("B10_FROM_BUILD")) {
specfile = string(getenv("B10_FROM_BUILD")) +
"/src/bin/dhcp6/dhcp6.spec";
} else {
specfile = string(DHCP6_SPECFILE_LOCATION);
}
/// @todo: Check if session is not established already. Throw, if it is.
cout << "b10-dhcp6: my specfile is " << specfile << endl;
cc_session_ = new Session(io_service_.get_io_service());
config_session_ = new ModuleCCSession(specfile, *cc_session_,
dhcp6ConfigHandler,
dhcp6CommandHandler, false);
config_session_->start();
/// Integrate the asynchronous I/O model of BIND 10 configuration
/// control with the "select" model of the DHCP server. This is
/// fully explained in \ref dhcpv6Session.
int ctrl_socket = cc_session_->getSocketDesc();
cout << "b10-dhcp6: Control session started, socket="
<< ctrl_socket << endl;
IfaceMgr::instance().set_session_socket(ctrl_socket, sessionReader);
}
void ControlledDhcpv6Srv::disconnectSession() {
if (config_session_) {
delete config_session_;
config_session_ = NULL;
}
if (cc_session_) {
cc_session_->disconnect();
delete cc_session_;
cc_session_ = NULL;
}
// deregister session socket
IfaceMgr::instance().set_session_socket(IfaceMgr::INVALID_SOCKET, NULL);
}
ControlledDhcpv6Srv::ControlledDhcpv6Srv(uint16_t port /*= DHCP6_SERVER_PORT*/)
:Dhcpv6Srv(port), cc_session_(NULL), config_session_(NULL) {
server_ = this; // remember this instance for use in callback
}
void ControlledDhcpv6Srv::shutdown() {
io_service_.stop(); // Stop ASIO transmissions
Dhcpv6Srv::shutdown(); // Initiate DHCPv6 shutdown procedure.
}
ControlledDhcpv6Srv::~ControlledDhcpv6Srv() {
disconnectSession();
server_ = NULL; // forget this instance. There should be no callback anymore
// at this stage anyway.
}
isc::data::ConstElementPtr
ControlledDhcpv6Srv::execDhcpv6ServerCommand(const std::string& command_id,
isc::data::ConstElementPtr args) {
try {
return (dhcp6CommandHandler(command_id, args));
} catch (const Exception& ex) {
ConstElementPtr answer = isc::config::createAnswer(1, ex.what());
return (answer);
}
}
};
};
// Copyright (C) 2012 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 CTRL_DHCPV6_SRV_H
#define CTRL_DHCPV6_SRV_H
#include <dhcp6/dhcp6_srv.h>
#include <asiolink/asiolink.h>
#include <cc/session.h>
#include <config/ccsession.h>
#include <cc/data.h>
namespace isc {
namespace dhcp {
/// @brief Controlled version of the DHCPv6 server
///
/// This is a class that is responsible for establishing connection
/// with msqg (receving commands and configuration). This is an extended
/// version of Dhcpv6Srv class that is purely a DHCPv6 server, without
/// external control. ControlledDhcpv6Srv should be used in typical BIND10
/// (i.e. featuring msgq) environment, while Dhcpv6Srv should be used in
/// embedded environments.
///
/// For detailed explanation or relations between main(), ControlledDhcpv6Srv,
/// Dhcpv6Srv and other classes, see \ref dhcpv6Session.
class ControlledDhcpv6Srv : public isc::dhcp::Dhcpv6Srv {
public:
/// @brief Constructor
///
/// @param port UDP port to be opened for DHCP traffic
ControlledDhcpv6Srv(uint16_t port = DHCP6_SERVER_PORT);
/// @brief Destructor.
~ControlledDhcpv6Srv();
/// @brief Establishes msgq session.
///
/// Creates session that will be used to receive commands and updated
/// configuration from boss (or indirectly from user via bindctl).
void establishSession();
/// @brief Terminates existing msgq session.
///
/// This method terminates existing session with msgq. After calling
/// it, no further messages over msgq (commands or configuration updates)
/// may be received.
///
/// It is ok to call this method when session is disconnected already.
void disconnectSession();
/// @brief Initiates shutdown procedure for the whole DHCPv6 server.
void shutdown();
/// @brief Session callback, processes received commands.
///
/// @param command_id text represenation of the command (e.g. "shutdown")
/// @param args optional parameters
///
/// @return status of the command
static isc::data::ConstElementPtr
execDhcpv6ServerCommand(const std::string& command,
isc::data::ConstElementPtr args);
protected:
/// @brief Static pointer to the sole instance of the DHCP server.
///
/// This is required for config and command handlers to gain access to
/// the server
static ControlledDhcpv6Srv* server_;
/// @brief A callback for handling incoming configuration updates.
///
/// As pointer to this method is used a callback in ASIO used in
/// ModuleCCSession, it has to be static.
///
/// @param new_config textual representation of the new configuration
///
/// @return status of the config update
static isc::data::ConstElementPtr
dhcp6ConfigHandler(isc::data::ConstElementPtr new_config);
/// @brief A callback for handling incoming commands.
///
/// @param command textual representation of the command
/// @param args parameters of the command
///
/// @return status of the processed command
static isc::data::ConstElementPtr
dhcp6CommandHandler(const std::string& command, isc::data::ConstElementPtr args);
/// @brief Callback that will be called from iface_mgr when command/config arrives.
///
/// This static callback method is called from IfaceMgr::receive6() method,
/// when there is a new command or configuration sent over msgq.
static void sessionReader(void);
/// @brief IOService object, used for all ASIO operations.
isc::asiolink::IOService io_service_;
/// @brief Helper session object that represents raw connection to msgq.
isc::cc::Session* cc_session_;
/// @brief Session that receives configuation and commands
isc::config::ModuleCCSession* config_session_;
};
}; // namespace isc::dhcp
}; // namespace isc
#endif
...@@ -48,12 +48,12 @@ Dhcpv6Srv::Dhcpv6Srv(uint16_t port) { ...@@ -48,12 +48,12 @@ Dhcpv6Srv::Dhcpv6Srv(uint16_t port) {
IfaceMgr::instance(); IfaceMgr::instance();
} catch (const std::exception &e) { } catch (const std::exception &e) {
cout << "Failed to instantiate InterfaceManager:" << e.what() << ". Aborting." << endl; cout << "Failed to instantiate InterfaceManager:" << e.what() << ". Aborting." << endl;
shutdown = true; shutdown_ = true;
} }
if (IfaceMgr::instance().countIfaces() == 0) { if (IfaceMgr::instance().countIfaces() == 0) {
cout << "Failed to detect any network interfaces. Aborting." << endl; cout << "Failed to detect any network interfaces. Aborting." << endl;
shutdown = true; shutdown_ = true;
} }
// Now try to open IPv6 sockets on detected interfaces. // Now try to open IPv6 sockets on detected interfaces.
...@@ -63,7 +63,7 @@ Dhcpv6Srv::Dhcpv6Srv(uint16_t port) { ...@@ -63,7 +63,7 @@ Dhcpv6Srv::Dhcpv6Srv(uint16_t port) {
setServerID(); setServerID();
shutdown = false; shutdown_ = false;
} }
Dhcpv6Srv::~Dhcpv6Srv() { Dhcpv6Srv::~Dhcpv6Srv() {
...@@ -72,8 +72,13 @@ Dhcpv6Srv::~Dhcpv6Srv() { ...@@ -72,8 +72,13 @@ Dhcpv6Srv::~Dhcpv6Srv() {
IfaceMgr::instance().closeSockets(); IfaceMgr::instance().closeSockets();
} }
void Dhcpv6Srv::shutdown() {
cout << "b10-dhcp6: DHCPv6 server shutdown." << endl;
shutdown_ = true;
}
bool Dhcpv6Srv::run() { bool Dhcpv6Srv::run() {
while (!shutdown) { while (!shutdown_) {
// client's message and server's response // client's message and server's response
Pkt6Ptr query = IfaceMgr::instance().receive6(); Pkt6Ptr query = IfaceMgr::instance().receive6();
......
...@@ -67,6 +67,8 @@ public: ...@@ -67,6 +67,8 @@ public:
/// critical error. /// critical error.
bool run(); bool run();
/// @brief Instructs the server to shut down.
void shutdown();
protected: protected:
/// @brief Processes incoming SOLICIT and returns response. /// @brief Processes incoming SOLICIT and returns response.
/// ///
...@@ -184,7 +186,7 @@ protected: ...@@ -184,7 +186,7 @@ protected:
/// indicates if shutdown is in progress. Setting it to true will /// indicates if shutdown is in progress. Setting it to true will
/// initiate server shutdown procedure. /// initiate server shutdown procedure.
volatile bool shutdown; volatile bool shutdown_;
}; };
}; // namespace isc::dhcp }; // namespace isc::dhcp
......
...@@ -13,47 +13,34 @@ ...@@ -13,47 +13,34 @@
// PERFORMANCE OF THIS SOFTWARE. // PERFORMANCE OF THIS SOFTWARE.
#include <config.h> #include <config.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/select.h>
#include <netdb.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <errno.h>
#include <cassert>
#include <iostream> #include <iostream>
#include <exceptions/exceptions.h>
#if 0
// TODO cc is not used yet. It should be eventually
#include <cc/session.h>
#include <config/ccsession.h>
#endif
#include <util/buffer.h>
#include <log/dummylog.h> #include <log/dummylog.h>
#include <log/logger_support.h>
#include <dhcp6/spec_config.h> #include <dhcp6/ctrl_dhcp6_srv.h>
#include "dhcp6/dhcp6_srv.h"
using namespace std; using namespace std;
using namespace isc::util;
using namespace isc;
using namespace isc::dhcp; using namespace isc::dhcp;
/// This file contains entry point (main() function) for standard DHCPv6 server
/// component for BIND10 framework. It parses command-line arguments and
/// instantiates ControlledDhcpv6Srv class that is responsible for establishing
/// connection with msgq (receiving commands and configuration) and also
/// creating Dhcpv6 server object as well.
///
/// For detailed explanation or relations between main(), ControlledDhcpv6Srv,
/// Dhcpv6Srv and other classes, see \ref dhcpv6Session.
namespace { namespace {
bool verbose_mode = false; const char* const DHCP6_NAME = "b10-dhcp6";
void void
usage() { usage() {
cerr << "Usage: b10-dhcp6 [-v]" cerr << "Usage: b10-dhcp6 [-v]"
<< endl; << endl;
cerr << "\t-v: verbose output" << endl; cerr << "\t-v: verbose output" << endl;
cerr << "\t-p number: specify non-standard port number 1-65535 (useful for testing only)" << endl; cerr << "\t-p number: specify non-standard port number 1-65535 "
<< "(useful for testing only)" << endl;
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
} // end of anonymous namespace } // end of anonymous namespace
...@@ -63,6 +50,7 @@ main(int argc, char* argv[]) { ...@@ -63,6 +50,7 @@ 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.