diff --git a/configure.ac b/configure.ac
index 8221cdb522..348708fde1 100644
--- a/configure.ac
+++ b/configure.ac
@@ -775,6 +775,8 @@ AC_CONFIG_FILES([Makefile
src/bin/auth/Makefile
src/bin/auth/tests/Makefile
src/bin/auth/benchmarks/Makefile
+ src/bin/dhcp6/Makefile
+ src/bin/dhcp6/tests/Makefile
src/bin/resolver/Makefile
src/bin/resolver/tests/Makefile
src/bin/sockcreator/Makefile
@@ -904,6 +906,7 @@ AC_OUTPUT([doc/version.ent
src/bin/msgq/run_msgq.sh
src/bin/auth/auth.spec.pre
src/bin/auth/spec_config.h.pre
+ src/bin/dhcp6/spec_config.h.pre
src/bin/tests/process_rename_test.py
src/lib/config/tests/data_def_unittests_config.h
src/lib/python/isc/config/tests/config_test
diff --git a/src/bin/Makefile.am b/src/bin/Makefile.am
index 23d660cd0d..06d8df2e76 100644
--- a/src/bin/Makefile.am
+++ b/src/bin/Makefile.am
@@ -1,4 +1,4 @@
SUBDIRS = bind10 bindctl cfgmgr loadzone msgq host cmdctl auth xfrin xfrout \
- usermgr zonemgr stats tests resolver sockcreator
+ usermgr zonemgr stats tests resolver sockcreator dhcp6
check-recursive: all-recursive
diff --git a/src/bin/bind10/bind10.py.in b/src/bin/bind10/bind10.py.in
index 648d085089..48d641d282 100755
--- a/src/bin/bind10/bind10.py.in
+++ b/src/bin/bind10/bind10.py.in
@@ -220,6 +220,8 @@ class BoB:
self.ccs = None
self.cfg_start_auth = True
self.cfg_start_resolver = False
+ self.cfg_start_dhcp6 = False
+ self.cfg_start_dhcp4 = False
self.started_auth_family = False
self.started_resolver_family = False
self.curproc = None
@@ -549,6 +551,9 @@ class BoB:
def start_stats_httpd(self, c_channel_env):
self.start_simple("b10-stats-httpd", c_channel_env)
+ def start_dhcp6(self, c_channel_env):
+ self.start_simple("b10-dhcp6", c_channel_env)
+
def start_cmdctl(self, c_channel_env):
"""
Starts the command control process
@@ -600,11 +605,14 @@ class BoB:
self.start_stats(c_channel_env)
self.start_stats_httpd(c_channel_env)
self.start_cmdctl(c_channel_env)
-
+
+ if self.cfg_start_dhcp6:
+ self.start_dhcp6(c_channel_env)
+
def startup(self):
"""
Start the BoB instance.
-
+
Returns None if successful, otherwise an string describing the
problem.
"""
diff --git a/src/bin/bind10/run_bind10.sh.in b/src/bin/bind10/run_bind10.sh.in
index 3a36e01d24..8dfdd50aec 100755
--- a/src/bin/bind10/run_bind10.sh.in
+++ b/src/bin/bind10/run_bind10.sh.in
@@ -20,7 +20,7 @@ export PYTHON_EXEC
BIND10_PATH=@abs_top_builddir@/src/bin/bind10
-PATH=@abs_top_builddir@/src/bin/msgq:@abs_top_builddir@/src/bin/auth:@abs_top_builddir@/src/bin/resolver:@abs_top_builddir@/src/bin/cfgmgr:@abs_top_builddir@/src/bin/cmdctl:@abs_top_builddir@/src/bin/stats:@abs_top_builddir@/src/bin/xfrin:@abs_top_builddir@/src/bin/xfrout:@abs_top_builddir@/src/bin/zonemgr:$PATH
+PATH=@abs_top_builddir@/src/bin/msgq:@abs_top_builddir@/src/bin/auth:@abs_top_builddir@/src/bin/resolver:@abs_top_builddir@/src/bin/cfgmgr:@abs_top_builddir@/src/bin/cmdctl:@abs_top_builddir@/src/bin/stats:@abs_top_builddir@/src/bin/xfrin:@abs_top_builddir@/src/bin/xfrout:@abs_top_builddir@/src/bin/zonemgr:@abs_top_builddir@/src/bin/dhcp6:$PATH
export PATH
PYTHONPATH=@abs_top_builddir@/src/lib/python:@abs_top_builddir@/src/lib/dns/python/.libs:@abs_top_builddir@/src/lib/xfr/.libs:@abs_top_builddir@/src/lib/log/.libs:@abs_top_builddir@/src/lib/util/io/.libs
diff --git a/src/bin/bind10/tests/bind10_test.py.in b/src/bin/bind10/tests/bind10_test.py.in
index 2ffe2b4c1c..91d326c339 100644
--- a/src/bin/bind10/tests/bind10_test.py.in
+++ b/src/bin/bind10/tests/bind10_test.py.in
@@ -111,6 +111,9 @@ class TestBoB(unittest.TestCase):
self.assertEqual(bob.cfg_start_auth, True)
self.assertEqual(bob.cfg_start_resolver, False)
+ self.assertEqual(bob.cfg_start_dhcp4, False)
+ self.assertEqual(bob.cfg_start_dhcp6, False)
+
def test_init_alternate_socket(self):
bob = BoB("alt_socket_file")
self.assertEqual(bob.verbose, False)
@@ -125,6 +128,8 @@ class TestBoB(unittest.TestCase):
self.assertEqual(bob.nocache, False)
self.assertEqual(bob.cfg_start_auth, True)
self.assertEqual(bob.cfg_start_resolver, False)
+ self.assertEqual(bob.cfg_start_dhcp4, False)
+ self.assertEqual(bob.cfg_start_dhcp6, False)
def test_command_handler(self):
class DummySession():
@@ -247,6 +252,16 @@ class MockBob(BoB):
self.processes[12] = ProcessInfo('b10-cmdctl', ['/bin/false'])
self.processes[12].pid = 12
+ def start_dhcp6(self, c_channel_env):
+ self.dhcp6 = True
+ self.processes[13] = ProcessInfo('b10-dhcp6', ['/bin/false'])
+ self.processes[13]
+
+ def start_dhcp4(self, c_channel_env):
+ self.dhcp4 = True
+ self.processes[14] = ProcessInfo('b10-dhcp4', ['/bin/false'])
+ self.processes[14]
+
# We don't really use all of these stop_ methods. But it might turn out
# someone would add some stop_ method to BoB and we want that one overriden
# in case he forgets to update the tests.
@@ -359,6 +374,24 @@ class TestStartStopProcessesBob(unittest.TestCase):
"""
self.check_started(bob, True, False, True)
+ def check_started_dhcp(self, bob, v4, v6):
+ """
+ Check if proper combinations of DHCPv4 and DHCpv6 can be started
+ """
+ v4found = 0
+ v6found = 0
+
+ for pid in bob.processes:
+ if (bob.processes[pid].name == "b10-dhcp4"):
+ v4found += 1
+ if (bob.processes[pid].name == "b10-dhcp6"):
+ v6found += 1
+
+ # there should be exactly one DHCPv4 daemon (if v4==True)
+ # there should be exactly one DHCPv6 daemon (if v6==True)
+ self.assertEqual(v4==True, v4found==1)
+ self.assertEqual(v6==True, v6found==1)
+
# Checks the processes started when starting neither auth nor resolver
# is specified.
def test_start_none(self):
@@ -524,6 +557,40 @@ class TestStartStopProcessesBob(unittest.TestCase):
bob.config_handler({'start_auth': True, 'start_resolver': True})
+ # Checks that DHCP (v4 and v6) processes are started when expected
+ def test_start_dhcp(self):
+
+ # Create BoB and ensure correct initialization
+ bob = MockBob()
+ self.check_preconditions(bob)
+
+ # don't care about DNS stuff
+ bob.cfg_start_auth = False
+ bob.cfg_start_resolver = False
+
+ # v4 and v6 disabled
+ bob.cfg_start_dhcp6 = False
+ bob.cfg_start_dhcp4 = False
+ bob.start_all_processes()
+ self.check_started_dhcp(bob, False, False)
+
+ # v6 only enabled
+ bob.cfg_start_dhcp6 = True
+ bob.cfg_start_dhcp4 = False
+ bob.start_all_processes()
+ self.check_started_dhcp(bob, False, True)
+
+ # uncomment when dhcpv4 becomes implemented
+ # v4 only enabled
+ #bob.cfg_start_dhcp6 = False
+ #bob.cfg_start_dhcp4 = True
+ #self.check_started_dhcp(bob, True, False)
+
+ # both v4 and v6 enabled
+ #bob.cfg_start_dhcp6 = True
+ #bob.cfg_start_dhcp4 = True
+ #self.check_started_dhcp(bob, True, True)
+
class TestBossCmd(unittest.TestCase):
def test_ping(self):
"""
diff --git a/src/bin/dhcp6/.gitignore b/src/bin/dhcp6/.gitignore
new file mode 100644
index 0000000000..6a6060bbe4
--- /dev/null
+++ b/src/bin/dhcp6/.gitignore
@@ -0,0 +1,9 @@
+*~
+Makefile
+Makefile.in
+*.o
+.deps
+.libs
+b10-dhcp6
+spec_config.h
+spec_config.h.pre
diff --git a/src/bin/dhcp6/Makefile.am b/src/bin/dhcp6/Makefile.am
new file mode 100644
index 0000000000..8d341cb947
--- /dev/null
+++ b/src/bin/dhcp6/Makefile.am
@@ -0,0 +1,52 @@
+SUBDIRS = . tests
+
+AM_CPPFLAGS = -I$(top_srcdir)/src/lib -I$(top_builddir)/src/lib
+AM_CPPFLAGS += -I$(top_srcdir)/src/bin -I$(top_builddir)/src/bin
+AM_CPPFLAGS += -I$(top_srcdir)/src/lib/dns -I$(top_builddir)/src/lib/dns
+AM_CPPFLAGS += -I$(top_srcdir)/src/lib/cc -I$(top_builddir)/src/lib/cc
+AM_CPPFLAGS += -I$(top_srcdir)/src/lib/asiolink
+AM_CPPFLAGS += -I$(top_builddir)/src/lib/asiolink
+AM_CPPFLAGS += $(BOOST_INCLUDES)
+
+AM_CXXFLAGS = $(B10_CXXFLAGS)
+
+if USE_STATIC_LINK
+AM_LDFLAGS = -static
+endif
+
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+
+CLEANFILES = *.gcno *.gcda spec_config.h
+
+man_MANS = b10-dhcp6.8
+EXTRA_DIST = $(man_MANS) dhcp6.spec
+
+#if ENABLE_MAN
+#b10-dhcp6.8: b10-dhcp6.xml
+# xsltproc --novalid --xinclude --nonet -o $@ http://docbook.sourceforge.net/release/xsl/current/manpages/docbook.xsl $(srcdir)/b10-dhcp6.xml
+#endif
+
+spec_config.h: spec_config.h.pre
+ $(SED) -e "s|@@LOCALSTATEDIR@@|$(localstatedir)|" spec_config.h.pre >$@
+
+BUILT_SOURCES = spec_config.h
+pkglibexec_PROGRAMS = b10-dhcp6
+b10_dhcp6_SOURCES = main.cc
+b10_dhcp6_SOURCES += dhcp6.h
+b10_dhcp6_LDADD = $(top_builddir)/src/lib/datasrc/libdatasrc.la
+b10_dhcp6_LDADD += $(top_builddir)/src/lib/dns/libdns++.la
+b10_dhcp6_LDADD += $(top_builddir)/src/lib/config/libcfgclient.la
+b10_dhcp6_LDADD += $(top_builddir)/src/lib/cc/libcc.la
+b10_dhcp6_LDADD += $(top_builddir)/src/lib/exceptions/libexceptions.la
+b10_dhcp6_LDADD += $(top_builddir)/src/lib/asiodns/libasiodns.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/xfr/libxfr.la
+b10_dhcp6_LDADD += $(top_builddir)/src/lib/server_common/libserver_common.la
+b10_dhcp6_LDADD += $(SQLITE_LIBS)
+
+# TODO: config.h.in is wrong because doesn't honor pkgdatadir
+# and can't use @datadir@ because doesn't expand default ${prefix}
+b10_dhcp6dir = $(pkgdatadir)
+b10_dhcp6_DATA = dhcp6.spec
+
diff --git a/src/bin/dhcp6/b10-dhcp6.8 b/src/bin/dhcp6/b10-dhcp6.8
new file mode 100644
index 0000000000..14a5621932
--- /dev/null
+++ b/src/bin/dhcp6/b10-dhcp6.8
@@ -0,0 +1,50 @@
+'\" t
+.\" Title: b10-dhpc6
+.\" Author: [FIXME: author] [see http://docbook.sf.net/el/author]
+.\" Generator: DocBook XSL Stylesheets v1.75.2
+.\" Date: March 8, 2011
+.\" Manual: BIND10
+.\" Source: BIND10
+.\" Language: English
+.\"
+.TH "B10\-DHCP6" "8" "March 8, 2011" "BIND10" "BIND10"
+.\" -----------------------------------------------------------------
+.\" * set default formatting
+.\" -----------------------------------------------------------------
+.\" disable hyphenation
+.nh
+.\" disable justification (adjust text to left margin only)
+.ad l
+.\" -----------------------------------------------------------------
+.\" * MAIN CONTENT STARTS HERE *
+.\" -----------------------------------------------------------------
+.SH "NAME"
+b10-dhcp6 \- DHCPv6 daemon in BIND10 architecture
+.SH "SYNOPSIS"
+.HP \w'\fBb10\-dhcp6\fR\ 'u
+\fBb10\-dhcp6\fR [\fB\-u\ \fR\fB\fIusername\fR\fR] [\fB\-v\fR]
+.SH "DESCRIPTION"
+.PP
+The
+\fBb10\-dhcp6\fR
+daemon will provide DHCPv6 server implementation when it becomes functional.
+.PP
+.SH "SEE ALSO"
+.PP
+
+\fBb10-cfgmgr\fR(8),
+\fBb10-loadzone\fR(8),
+\fBb10-msgq\fR(8),
+\fBb10-stats\fR(8),
+\fBb10-zonemgr\fR(8),
+\fBbind10\fR(8),
+BIND 10 Guide\&.
+.SH "HISTORY"
+.PP
+The
+\fBb10\-dhcp6\fR
+daemon was first coded in June 2011\&.
+.SH "COPYRIGHT"
+.br
+Copyright \(co 2011 Internet Systems Consortium, Inc. ("ISC")
+.br
diff --git a/src/bin/dhcp6/dhcp6.h b/src/bin/dhcp6/dhcp6.h
new file mode 100644
index 0000000000..322b06cecc
--- /dev/null
+++ b/src/bin/dhcp6/dhcp6.h
@@ -0,0 +1,213 @@
+/* dhcp6.h
+
+ DHCPv6 Protocol structures... */
+
+/*
+ * Copyright (c) 2006-2011 by Internet Systems Consortium, Inc. ("ISC")
+ *
+ * Permission to use, copy, modify, and 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.
+ *
+ * Internet Systems Consortium, Inc.
+ * 950 Charter Street
+ * Redwood City, CA 94063
+ *
+ * https://www.isc.org/
+ */
+
+
+/* DHCPv6 Option codes: */
+
+#define D6O_CLIENTID 1 /* RFC3315 */
+#define D6O_SERVERID 2
+#define D6O_IA_NA 3
+#define D6O_IA_TA 4
+#define D6O_IAADDR 5
+#define D6O_ORO 6
+#define D6O_PREFERENCE 7
+#define D6O_ELAPSED_TIME 8
+#define D6O_RELAY_MSG 9
+/* Option code 10 unassigned. */
+#define D6O_AUTH 11
+#define D6O_UNICAST 12
+#define D6O_STATUS_CODE 13
+#define D6O_RAPID_COMMIT 14
+#define D6O_USER_CLASS 15
+#define D6O_VENDOR_CLASS 16
+#define D6O_VENDOR_OPTS 17
+#define D6O_INTERFACE_ID 18
+#define D6O_RECONF_MSG 19
+#define D6O_RECONF_ACCEPT 20
+#define D6O_SIP_SERVERS_DNS 21 /* RFC3319 */
+#define D6O_SIP_SERVERS_ADDR 22 /* RFC3319 */
+#define D6O_NAME_SERVERS 23 /* RFC3646 */
+#define D6O_DOMAIN_SEARCH 24 /* RFC3646 */
+#define D6O_IA_PD 25 /* RFC3633 */
+#define D6O_IAPREFIX 26 /* RFC3633 */
+#define D6O_NIS_SERVERS 27 /* RFC3898 */
+#define D6O_NISP_SERVERS 28 /* RFC3898 */
+#define D6O_NIS_DOMAIN_NAME 29 /* RFC3898 */
+#define D6O_NISP_DOMAIN_NAME 30 /* RFC3898 */
+#define D6O_SNTP_SERVERS 31 /* RFC4075 */
+#define D6O_INFORMATION_REFRESH_TIME 32 /* RFC4242 */
+#define D6O_BCMCS_SERVER_D 33 /* RFC4280 */
+#define D6O_BCMCS_SERVER_A 34 /* RFC4280 */
+/* 35 is unassigned */
+#define D6O_GEOCONF_CIVIC 36 /* RFC4776 */
+#define D6O_REMOTE_ID 37 /* RFC4649 */
+#define D6O_SUBSCRIBER_ID 38 /* RFC4580 */
+#define D6O_CLIENT_FQDN 39 /* RFC4704 */
+#define D6O_PANA_AGENT 40 /* paa-option */
+#define D6O_NEW_POSIX_TIMEZONE 41 /* RFC4833 */
+#define D6O_NEW_TZDB_TIMEZONE 42 /* RFC4833 */
+#define D6O_ERO 43 /* RFC4994 */
+#define D6O_LQ_QUERY 44 /* RFC5007 */
+#define D6O_CLIENT_DATA 45 /* RFC5007 */
+#define D6O_CLT_TIME 46 /* RFC5007 */
+#define D6O_LQ_RELAY_DATA 47 /* RFC5007 */
+#define D6O_LQ_CLIENT_LINK 48 /* RFC5007 */
+
+/*
+ * Status Codes, from RFC 3315 section 24.4, and RFC 3633, 5007.
+ */
+#define STATUS_Success 0
+#define STATUS_UnspecFail 1
+#define STATUS_NoAddrsAvail 2
+#define STATUS_NoBinding 3
+#define STATUS_NotOnLink 4
+#define STATUS_UseMulticast 5
+#define STATUS_NoPrefixAvail 6
+#define STATUS_UnknownQueryType 7
+#define STATUS_MalformedQuery 8
+#define STATUS_NotConfigured 9
+#define STATUS_NotAllowed 10
+
+/*
+ * DHCPv6 message types, defined in section 5.3 of RFC 3315
+ */
+#define DHCPV6_SOLICIT 1
+#define DHCPV6_ADVERTISE 2
+#define DHCPV6_REQUEST 3
+#define DHCPV6_CONFIRM 4
+#define DHCPV6_RENEW 5
+#define DHCPV6_REBIND 6
+#define DHCPV6_REPLY 7
+#define DHCPV6_RELEASE 8
+#define DHCPV6_DECLINE 9
+#define DHCPV6_RECONFIGURE 10
+#define DHCPV6_INFORMATION_REQUEST 11
+#define DHCPV6_RELAY_FORW 12
+#define DHCPV6_RELAY_REPL 13
+#define DHCPV6_LEASEQUERY 14
+#define DHCPV6_LEASEQUERY_REPLY 15
+
+extern const char *dhcpv6_type_names[];
+extern const int dhcpv6_type_name_max;
+
+/* DUID type definitions (RFC3315 section 9).
+ */
+#define DUID_LLT 1
+#define DUID_EN 2
+#define DUID_LL 3
+
+/* Offsets into IA_*'s where Option spaces commence. */
+#define IA_NA_OFFSET 12 /* IAID, T1, T2, all 4 octets each */
+#define IA_TA_OFFSET 4 /* IAID only, 4 octets */
+#define IA_PD_OFFSET 12 /* IAID, T1, T2, all 4 octets each */
+
+/* Offset into IAADDR's where Option spaces commence. */
+#define IAADDR_OFFSET 24
+
+/* Offset into IAPREFIX's where Option spaces commence. */
+#define IAPREFIX_OFFSET 25
+
+/* Offset into LQ_QUERY's where Option spaces commence. */
+#define LQ_QUERY_OFFSET 17
+
+/*
+ * DHCPv6 well-known multicast addressess, from section 5.1 of RFC 3315
+ */
+#define All_DHCP_Relay_Agents_and_Servers "FF02::1:2"
+#define All_DHCP_Servers "FF05::1:3"
+
+/*
+ * DHCPv6 Retransmission Constants (RFC3315 section 5.5, RFC 5007)
+ */
+
+#define SOL_MAX_DELAY 1
+#define SOL_TIMEOUT 1
+#define SOL_MAX_RT 120
+#define REQ_TIMEOUT 1
+#define REQ_MAX_RT 30
+#define REQ_MAX_RC 10
+#define CNF_MAX_DELAY 1
+#define CNF_TIMEOUT 1
+#define CNF_MAX_RT 4
+#define CNF_MAX_RD 10
+#define REN_TIMEOUT 10
+#define REN_MAX_RT 600
+#define REB_TIMEOUT 10
+#define REB_MAX_RT 600
+#define INF_MAX_DELAY 1
+#define INF_TIMEOUT 1
+#define INF_MAX_RT 120
+#define REL_TIMEOUT 1
+#define REL_MAX_RC 5
+#define DEC_TIMEOUT 1
+#define DEC_MAX_RC 5
+#define REC_TIMEOUT 2
+#define REC_MAX_RC 8
+#define HOP_COUNT_LIMIT 32
+#define LQ6_TIMEOUT 1
+#define LQ6_MAX_RT 10
+#define LQ6_MAX_RC 5
+
+/*
+ * Normal packet format, defined in section 6 of RFC 3315
+ */
+struct dhcpv6_packet {
+ unsigned char msg_type;
+ unsigned char transaction_id[3];
+ unsigned char options[FLEXIBLE_ARRAY_MEMBER];
+};
+
+/* Offset into DHCPV6 Reply packets where Options spaces commence. */
+#define REPLY_OPTIONS_INDEX 4
+
+/*
+ * Relay packet format, defined in section 7 of RFC 3315
+ */
+struct dhcpv6_relay_packet {
+ unsigned char msg_type;
+ unsigned char hop_count;
+ unsigned char link_address[16];
+ unsigned char peer_address[16];
+ unsigned char options[FLEXIBLE_ARRAY_MEMBER];
+};
+
+/* Leasequery query-types (RFC 5007) */
+
+#define LQ6QT_BY_ADDRESS 1
+#define LQ6QT_BY_CLIENTID 2
+
+/*
+ * DUID time starts 2000-01-01.
+ * This constant is the number of seconds since 1970-01-01,
+ * when the Unix epoch began.
+ */
+#define DUID_TIME_EPOCH 946684800
+
+/* Information-Request Time option (RFC 4242) */
+
+#define IRT_DEFAULT 86400
+#define IRT_MINIMUM 600
+
diff --git a/src/bin/dhcp6/dhcp6.spec b/src/bin/dhcp6/dhcp6.spec
new file mode 100644
index 0000000000..0e7e8523b0
--- /dev/null
+++ b/src/bin/dhcp6/dhcp6.spec
@@ -0,0 +1,14 @@
+{
+ "module_spec": {
+ "module_name": "dhcp6",
+ "module_description": "DHCPv6 daemon",
+ "config_data": [
+ { "item_name": "interface",
+ "item_type": "string",
+ "item_optional": false,
+ "item_default": "eth0"
+ }
+ ],
+ "commands": []
+ }
+}
diff --git a/src/bin/dhcp6/main.cc b/src/bin/dhcp6/main.cc
new file mode 100644
index 0000000000..75af3d9240
--- /dev/null
+++ b/src/bin/dhcp6/main.cc
@@ -0,0 +1,122 @@
+// Copyright (C) 2009-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.
+
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+
+#include
+#include
+#include
+
+#include
+#include
+
+#include
+
+
+using namespace std;
+using namespace isc::util;
+using namespace isc::data;
+using namespace isc::cc;
+using namespace isc::config;
+using namespace isc::util;
+
+namespace {
+
+bool verbose_mode = false;
+
+void
+usage() {
+ cerr << "Usage: b10-dhcp6 [-u user] [-v]"
+ << endl;
+ cerr << "\t-u: change process UID to the specified user" << endl;
+ cerr << "\t-v: verbose output" << endl;
+ exit(1);
+}
+} // end of anonymous namespace
+
+int
+main(int argc, char* argv[]) {
+ int ch;
+ const char* uid = NULL;
+ bool cache = true;
+
+ while ((ch = getopt(argc, argv, ":nu:v")) != -1) {
+ switch (ch) {
+ case 'n':
+ cache = false;
+ break;
+ case 'u':
+ uid = optarg;
+ break;
+ case 'v':
+ verbose_mode = true;
+ isc::log::denabled = true;
+ break;
+ case '?':
+ default:
+ usage();
+ }
+ }
+
+ if (argc - optind > 0) {
+ usage();
+ }
+
+ int ret = 0;
+
+ // XXX: we should eventually pass io_service here.
+#if 0
+ Session* cc_session = NULL;
+ Session* xfrin_session = NULL;
+ Session* statistics_session = NULL;
+ bool xfrin_session_established = false; // XXX (see Trac #287)
+ bool statistics_session_established = false; // XXX (see Trac #287)
+ ModuleCCSession* config_session = NULL;
+#endif
+ try {
+ string specfile;
+ if (getenv("B10_FROM_BUILD")) {
+ specfile = string(getenv("B10_FROM_BUILD")) +
+ "/src/bin/auth/dhcp6.spec";
+ } else {
+ specfile = string(DHCP6_SPECFILE_LOCATION);
+ }
+
+ // auth_server = new AuthSrv(cache, xfrout_client);
+ // auth_server->setVerbose(verbose_mode);
+ cout << "[b10-dhcp6] Initiating DHCPv6 operation." << endl;
+
+ } catch (const std::exception& ex) {
+ cerr << "[b10-dhcp6] Server failed: " << ex.what() << endl;
+ ret = 1;
+ }
+
+ while (true) {
+ sleep(10);
+ cout << "[b10-dhcp6] I'm alive." << endl;
+ }
+
+ return (ret);
+}
diff --git a/src/bin/dhcp6/spec_config.h.pre.in b/src/bin/dhcp6/spec_config.h.pre.in
new file mode 100644
index 0000000000..42775b282f
--- /dev/null
+++ b/src/bin/dhcp6/spec_config.h.pre.in
@@ -0,0 +1,15 @@
+// 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.
+
+#define DHCP6_SPECFILE_LOCATION "@prefix@/share/@PACKAGE@/dhcp6.spec"
diff --git a/src/bin/dhcp6/tests/Makefile.am b/src/bin/dhcp6/tests/Makefile.am
new file mode 100644
index 0000000000..a0290c7cd7
--- /dev/null
+++ b/src/bin/dhcp6/tests/Makefile.am
@@ -0,0 +1,14 @@
+PYCOVERAGE_RUN = @PYCOVERAGE_RUN@
+#PYTESTS = args_test.py bind10_test.py
+# NOTE: this has a generated test found in the builddir
+PYTESTS = dhcp6_test.py
+EXTRA_DIST = $(PYTESTS)
+
+# test using command-line arguments, so use check-local target instead of TESTS
+check-local:
+ for pytest in $(PYTESTS) ; do \
+ echo Running test: $$pytest ; \
+ env PYTHONPATH=$(abs_top_srcdir)/src/lib/python:$(abs_top_builddir)/src/lib/python:$(abs_top_builddir)/src/bin/bind10 \
+ BIND10_MSGQ_SOCKET_FILE=$(abs_top_builddir)/msgq_socket \
+ $(PYCOVERAGE_RUN) $(abs_srcdir)/$$pytest || exit ; \
+ done
diff --git a/src/bin/dhcp6/tests/dhcp6_test.py b/src/bin/dhcp6/tests/dhcp6_test.py
new file mode 100644
index 0000000000..61ec009606
--- /dev/null
+++ b/src/bin/dhcp6/tests/dhcp6_test.py
@@ -0,0 +1,65 @@
+# Copyright (C) 2011 Internet Systems Consortium.
+#
+# Permission to use, copy, modify, and 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 INTERNET SYSTEMS CONSORTIUM
+# DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
+# INTERNET SYSTEMS CONSORTIUM 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.
+
+from bind10 import ProcessInfo, parse_args, dump_pid, unlink_pid_file, _BASETIME
+
+import unittest
+import sys
+import os
+import signal
+import socket
+from isc.net.addr import IPAddr
+import time
+import isc
+
+class TestDhcpv6Daemon(unittest.TestCase):
+ def setUp(self):
+ # redirect stdout to a pipe so we can check that our
+ # process spawning is doing the right thing with stdout
+ self.old_stdout = os.dup(sys.stdout.fileno())
+ self.pipes = os.pipe()
+ os.dup2(self.pipes[1], sys.stdout.fileno())
+ os.close(self.pipes[1])
+ # note that we use dup2() to restore the original stdout
+ # to the main program ASAP in each test... this prevents
+ # hangs reading from the child process (as the pipe is only
+ # open in the child), and also insures nice pretty output
+
+ def tearDown(self):
+ # clean up our stdout munging
+ os.dup2(self.old_stdout, sys.stdout.fileno())
+ os.close(self.pipes[0])
+
+ def test_alive(self):
+ """
+ Simple test. Checks that b10-dhcp6 can be started and prints out info
+ about starting DHCPv6 operation.
+ """
+ pi = ProcessInfo('Test Process', [ '../b10-dhcp6' , '-v' ])
+ pi.spawn()
+ time.sleep(1)
+ os.dup2(self.old_stdout, sys.stdout.fileno())
+ self.assertNotEqual(pi.process, None)
+ self.assertTrue(type(pi.pid) is int)
+ output = os.read(self.pipes[0], 4096)
+ self.assertEqual( str(output).count("[b10-dhcp6] Initiating DHCPv6 operation."), 1)
+
+ # kill this process
+ # XXX: b10-dhcp6 is too dumb to understand 'shutdown' command for now,
+ # so let's just kill the bastard
+ os.kill(pi.pid, signal.SIGTERM)
+
+if __name__ == '__main__':
+ unittest.main()