From: Tomek Date: Sat, 15 Jul 2017 11:22:43 +0000 (+0200) Subject: [client] Initial client files X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=383d0c2c4b17aaae623f9144ffe1efcb5572ee54;p=thirdparty%2Fkea.git [client] Initial client files --- diff --git a/configure.ac b/configure.ac index 5b8d9947f6..d48a9ed474 100755 --- a/configure.ac +++ b/configure.ac @@ -1655,6 +1655,8 @@ AC_CONFIG_FILES([Makefile src/bin/agent/tests/ca_process_tests.sh src/bin/agent/tests/test_data_files_config.h src/bin/agent/tests/test_libraries.h + src/bin/client/Makefile + src/bin/client/tests/Makefile src/bin/d2/Makefile src/bin/d2/tests/Makefile src/bin/d2/tests/d2_process_tests.sh diff --git a/src/bin/Makefile.am b/src/bin/Makefile.am index d93cbf452f..e4c5c26e5e 100644 --- a/src/bin/Makefile.am +++ b/src/bin/Makefile.am @@ -1,5 +1,5 @@ # The following build order must be maintained. -SUBDIRS = dhcp4 dhcp6 d2 agent admin lfc keactrl +SUBDIRS = client dhcp4 dhcp6 d2 agent admin lfc keactrl if PERFDHCP SUBDIRS += perfdhcp diff --git a/src/bin/client/Makefile.am b/src/bin/client/Makefile.am new file mode 100644 index 0000000000..c5bb6d4a82 --- /dev/null +++ b/src/bin/client/Makefile.am @@ -0,0 +1,99 @@ +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 += $(BOOST_INCLUDES) +AM_CXXFLAGS = $(KEA_CXXFLAGS) + +if USE_STATIC_LINK +AM_LDFLAGS = -static +endif + +CLEANFILES = +man_MANS = kea-client.8 + +DISTCLEANFILES = $(man_MANS) + +EXTRA_DIST = $(man_MANS) kea-client.xml +EXTRA_DIST += client.dox +EXTRA_DIST += clnt_lexer.ll clnt_parser.yy + +if GENERATE_DOCS + +kea-client.8: kea-client.xml + @XSLTPROC@ --novalid --xinclude --nonet -o $@ \ + http://docbook.sourceforge.net/release/xsl/current/manpages/docbook.xsl \ + $(srcdir)/kea-client.xml +else + +$(man_MANS): + @echo Man generation disabled. Creating dummy $@. Configure with --enable-generate-docs to enable it. + @echo Man generation disabled. Remove this file, configure with --enable-generate-docs, and rebuild Kea > $@ + +endif + +noinst_LTLIBRARIES = libclnt.la + +libclnt_la_SOURCES = +libclnt_la_SOURCES += main.cc + +sbin_PROGRAMS = kea-client + +kea_client_LDADD = libclnt.la + +kea_client_LDADD += $(top_builddir)/src/lib/asiolink/libkea-asiolink.la +kea_client_LDADD += $(top_builddir)/src/lib/cc/libkea-cc.la +kea_client_LDADD += $(top_builddir)/src/lib/hooks/libkea-hooks.la +kea_client_LDADD += $(top_builddir)/src/lib/exceptions/libkea-exceptions.la +kea_client_LDADD += $(top_builddir)/src/lib/dhcp/libkea-dhcp++.la +kea_client_LDADD += $(BOOST_LIBS) + +kea_client_LDFLAGS = $(AM_LDFLAGS) $(CRYPTO_LDFLAGS) + +# too big +# kea_client_LDADD += $(top_builddir)/src/lib/cfgrpt/libcfgrpt.la + +# not needed: +#kea_client_LDADD += $(top_builddir)/src/lib/dhcpsrv/libkea-dhcpsrv.la +#kea_client_LDADD += $(top_builddir)/src/lib/eval/libkea-eval.la +#kea_client_LDADD += $(top_builddir)/src/lib/dhcp_ddns/libkea-dhcp_ddns.la +#kea_client_LDADD += $(top_builddir)/src/lib/stats/libkea-stats.la +#kea_client_LDADD += $(top_builddir)/src/lib/config/libkea-cfgclient.la +#kea_client_LDADD += $(top_builddir)/src/lib/dns/libkea-dns++.la +#kea_client_LDADD += $(top_builddir)/src/lib/cryptolink/libkea-cryptolink.la +#kea_client_LDADD += $(top_builddir)/src/lib/log/libkea-log.la +#kea_client_LDADD += $(top_builddir)/src/lib/util/threads/libkea-threads.la +#kea_client_LDADD += $(top_builddir)/src/lib/util/libkea-util.la +#kea_client_LDADD += $(top_builddir)/src/lib/exceptions/libkea-exceptions.la +#kea_client_LDADD += $(LOG4CPLUS_LIBS) $(CRYPTO_LIBS) $(BOOST_LIBS) + + +kea_clntdir = $(pkgdatadir) +kea_clnt_DATA = dhcp6.spec + +if GENERATE_PARSER + +parser: dhcp6_lexer.cc location.hh position.hh stack.hh dhcp6_parser.cc dhcp6_parser.h + @echo "Flex/bison files regenerated" + +# --- Flex/Bison stuff below -------------------------------------------------- +# When debugging grammar issues, it's useful to add -v to bison parameters. +# bison will generate parser.output file that explains the whole grammar. +# It can be used to manually follow what's going on in the parser. +# This is especially useful if yydebug_ is set to 1 as that variable +# will cause parser to print out its internal state. +# Call flex with -s to check that the default rule can be suppressed +# Call bison with -W to get warnings like unmarked empty rules +# Note C++11 deprecated register still used by flex < 2.6.0 +location.hh position.hh stack.hh clnt_parser.cc clnt_parser.h: clnt_parser.yy + $(YACC) --defines=clnt_parser.h --report=all --report-file=clnt_parser.report -o clnt_parser.cc clnt_parser.yy + +clnt_lexer.cc: clnt_lexer.ll + $(LEX) --prefix clnt_ -o clnt_lexer.cc clnt_lexer.ll + +else + +parser location.hh position.hh stack.hh clnt_parser.cc clnt_parser.h clnt_lexer.cc: + @echo Parser generation disabled. Configure with --enable-generate-parser to enable it. + +endif diff --git a/src/bin/client/client.dox b/src/bin/client/client.dox new file mode 100644 index 0000000000..44c5f0562e --- /dev/null +++ b/src/bin/client/client.dox @@ -0,0 +1,99 @@ +// Copyright (C) 2017 Internet Systems Consortium, Inc. ("ISC") +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +/** + @page client DHCPv4 and DHCPv6 client + +Kea now includes an exprimental DHCP protocols client. This client is able +to act as DHCPv4 client, as DHCPv6 client or both. + +@section clientRequirements Client Requirements + +There are many DHCP client implementations available, both open source and proprietary. +It doesn't make sense to implement yet another client that is very similar to existing +ones. In other words, the market is already saturated and we need to find a +competitive advantage to gain any significant adoption. + +At the same time, we need to find a way to retire ISC DHCP project completely. It +is not going to happen if we don't have a replacement for dhclient. + +Given the reasoning above, the following requirements has been defined: + +-# a single process supporting DHCPv4 and DHCPv6. One of the major architectural + failures of dhclient is the inability to gracefully co-exist on a dual-stack + host. Yes, it can be used to handle both v4 and v6, but the interaction between + them is not well defined. In particular, it's not possible to specify whether + v4 or v6 parameters are equal, one takes preference over another or one overrides + the other. There are two additional aspects that are currently unsolved. The + first one is DHCID records update in the DNS. In principle it is possible for + dhclient instance running as v4 client and another running as v6 client to + cooperate and not overwrite the record, but in practice the solution does not + work well and there are complaints. The second scenario that is not fully + addressed is DHCPv4-over-DHCPv6 client. Existing implementation in dhclient + is available, but it does not follow the spirit of the RFC. The problem is + that the logic behind starting 4o6 client (essentially v4 client sending messages + over DHCPv6) is dependant on the options received over plain DHCPv6 exchange. + This kind of inter-family logic is beyond the capabilities of dhclient. + +-# DHCPv6 is more important than DHCPv4. This document is being written in 2017. + Assuming a prototype is ready by end of the year and its productization takes + another year (note that client will most likely have little funding and our + priority is definitely the server, so client will mature slowly), we can + speculate that wider adoption would happen sometime in 2019. At that timeframe + it is likely that most new deployments will be either dual-stack or IPv6-only. + +-# Size does matter. DHCP client is just a step in the device booting and network + operations. While it makes sense to expect admins to install certain dependencies, + the client should be as small as possible. Also, there's a whole market of + embedded devices that expect the client to be very small. This is particularly + competitive market, with odhcp client being mere 20KB (written in plain C, + little configuration capabilities, v6 only). Therefore, the small size of + the client code is a priority. + +-# Hooks. There are essentially two approaches to how client consumes the +information received. One is a client implementing the changes (e.g. configuring +addresses on its own, updating /etc/resolv.conf etc.) while the alternative +approach assumes that an external script is called and user can write the +script on its own. dhclient implements the latter, while dibbler-client implements +both. Neither approach is better, they're simply better suited for different +situations. There are users who expect the client to just work out of the box +and don't want to be bothered with any scripts. On the other hand, there are +users (typically power users), who want to do certain custom operations. Those +favour the scripting approach. The scripting approach is particularly important +when handling prefix delegation (typically prefix received on uplink interface +is then split into subprefixes that are somehow used on downlink interfaces. +The split logic may become quite convoluted in certain cases). Therefore +it seems reasonable to have the ability to use both approaches or just one +that was selected. + +-# Dynamic environment. Another case where existing clients struggle are dynamic +scenarios. In particular, cases when interfaces appear and disappear. This +may mean PPP interfaces (that could be established and later torn down), +wifi links going out of range or virtual interfaces in VM environments. +Therefore the Kea client must support the following scenarios: + - configure an interface that is present at startup + - accept configuration for an interface that is not present at startup + - accept configuration for an interface that is present, but not up + - accept wildcard configuration for interfaces that may appear + - handle an event of an interface being handled disappearing + - handle an event of a not available interface to be configured to be + appearing + +-# OpenStack requirements. Tomek was contacted by Jean-Philippe Evrard from + Rackspace, asking for dibbler release. In the discussion it became apparent + that OpenStack uses Dibbler to configure DHCPv6 services, in particular + prefix delegation. They built a framework around it to control when + the client is started and how it handles the prefix. Some time ago + they submitted a patch to be able to run multiple instances of the client + on the same box. The exact use case is not clear, but it seems they + are using Linux Containers to deploy multiple OpenStack images on the + same bare metal. Therefore: + + - The client must be able to run more than one instance. + - The client must read and write everything to the directory it is being + run from. + + diff --git a/src/bin/client/main.cc b/src/bin/client/main.cc new file mode 100644 index 0000000000..d724bad66f --- /dev/null +++ b/src/bin/client/main.cc @@ -0,0 +1,39 @@ +// Copyright (C) 2017 Internet Systems Consortium, Inc. ("ISC") +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#include +#include +#include + +#include + +using namespace isc::client; +using namespace isc::process; +using namespace std; + +/// This file contains entry point (main() function) for standard DHCP-DDNS +/// process, kea-dhcp-ddns, component of Kea software suite. It fetches +/// the D2Controller singleton instance and invokes its launch method. +/// The exit value of the program will be EXIT_SUCCESS if there were no +/// errors, EXIT_FAILURE otherwise. +int main(int argc, char* argv[]) { + int ret = EXIT_SUCCESS; + + // Launch the controller passing in command line arguments. + // Exit program with the controller's return code. + try { + // Instantiate/fetch the client application controller singleton. + DControllerBasePtr& controller = ClntController::instance(); + + // 'false' value disables test mode. + controller->launch(argc, argv, false); + } catch (const isc::Exception& ex) { + std::cerr << "Service failed: " << ex.what() << std::endl; + ret = EXIT_FAILURE; + } + + return (ret); +} diff --git a/src/bin/client/tests/Makefile.am b/src/bin/client/tests/Makefile.am new file mode 100644 index 0000000000..4fb3148a6b --- /dev/null +++ b/src/bin/client/tests/Makefile.am @@ -0,0 +1,66 @@ +SHTESTS = +# The test of dynamic reconfiguration based on signals will work only +# if we are using file based configuration approach. +SHTESTS += clnt_process_tests.sh + +noinst_SCRIPTS = clnt_process_tests.sh + +EXTRA_DIST = clnt_process_tests.sh.in + +# test using command-line arguments, so use check-local target instead of TESTS +check-local: + for shtest in $(SHTESTS) ; do \ + echo Running test: $$shtest ; \ + export KEA_LOCKFILE_DIR=$(abs_top_builddir); \ + export KEA_PIDFILE_DIR=$(abs_top_builddir); \ + ${SHELL} $(abs_builddir)/$$shtest || exit ; \ + done + +AM_CPPFLAGS = -I$(top_srcdir)/src/lib -I$(top_builddir)/src/lib +AM_CPPFLAGS += -I$(top_builddir)/src/bin # for generated spec_config.h header +AM_CPPFLAGS += -I$(top_srcdir)/src/bin +AM_CPPFLAGS += $(BOOST_INCLUDES) +AM_CPPFLAGS += -DTEST_DATA_BUILDDIR=\"$(abs_top_builddir)/src/bin/client/tests\" +AM_CPPFLAGS += -DINSTALL_PROG=\"$(abs_top_srcdir)/install-sh\" +AM_CPPFLAGS += -DCFG_EXAMPLES=\"$(abs_top_srcdir)/doc/examples/client\" + +DISTCLEANFILES = clnt_process_tests.sh + +AM_CXXFLAGS = $(KEA_CXXFLAGS) + +if USE_STATIC_LINK +AM_LDFLAGS = -static +endif + +TESTS_ENVIRONMENT = \ + $(LIBTOOL) --mode=execute $(VALGRIND_COMMAND) + +TESTS = +if HAVE_GTEST + +TESTS += clnt_unittests + +clnt_unittests_SOURCES = clnt_unittests.cc + +clnt_unittests_CPPFLAGS = $(AM_CPPFLAGS) $(GTEST_INCLUDES) +clnt_unittests_LDFLAGS = $(AM_LDFLAGS) $(CRYPTO_LDFLAGS) +clnt_unittests_LDFLAGS += $(GTEST_LDFLAGS) + +clnt_unittests_LDADD = $(top_builddir)/src/bin/client/libclnt.la +clnt_unittests_LDADD += $(top_builddir)/src/lib/process/testutils/libprocesstest.la +clnt_unittests_LDADD += $(top_builddir)/src/lib/process/libkea-process.la +clnt_unittests_LDADD += $(top_builddir)/src/lib/testutils/libkea-testutils.la +clnt_unittests_LDADD += $(top_builddir)/src/lib/asiodns/libkea-asiodns.la +clnt_unittests_LDADD += $(top_builddir)/src/lib/dhcp/libkea-dhcp++.la +clnt_unittests_LDADD += $(top_builddir)/src/lib/asiolink/libkea-asiolink.la +clnt_unittests_LDADD += $(top_builddir)/src/lib/cc/libkea-cc.la +clnt_unittests_LDADD += $(top_builddir)/src/lib/hooks/libkea-hooks.la +clnt_unittests_LDADD += $(top_builddir)/src/lib/util/threads/libkea-threads.la +clnt_unittests_LDADD += $(top_builddir)/src/lib/util/libkea-util.la +clnt_unittests_LDADD += $(top_builddir)/src/lib/exceptions/libkea-exceptions.la +clnt_unittests_LDADD += $(LOG4CPLUS_LIBS) $(CRYPTO_LIBS) +clnt_unittests_LDADD += $(BOOST_LIBS) $(GTEST_LDADD) + +endif + +noinst_PROGRAMS = $(TESTS)