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()