Browse Source

Merge branch 'trac990'

Tomek Mrugalski 14 years ago
parent
commit
4a590df96a

+ 3 - 0
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

+ 1 - 1
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

+ 10 - 2
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.
         """

+ 1 - 1
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

+ 67 - 0
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):
         """

+ 9 - 0
src/bin/dhcp6/.gitignore

@@ -0,0 +1,9 @@
+*~
+Makefile
+Makefile.in
+*.o
+.deps
+.libs
+b10-dhcp6
+spec_config.h
+spec_config.h.pre

+ 52 - 0
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
+

+ 50 - 0
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 <http://docbook.sf.net/>
+.\"      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

+ 213 - 0
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
+ *   <info@isc.org>
+ *   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
+

+ 14 - 0
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": []
+  }
+}

+ 122 - 0
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 <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 <exceptions/exceptions.h>
+#include <cc/session.h>
+#include <config/ccsession.h>
+
+#include <util/buffer.h>
+#include <log/dummylog.h>
+
+#include <dhcp6/spec_config.h>
+
+
+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);
+}

+ 15 - 0
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"

+ 14 - 0
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

+ 65 - 0
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()