<arg><option>-V</option></arg>
<arg><option>-W</option></arg>
<arg><option>-d</option></arg>
+ <arg><option>-t</option></arg>
<arg><option>-c<replaceable class="parameter">config-file</replaceable></option></arg>
<arg><option>-p<replaceable class="parameter">port-number</replaceable></option></arg>
</cmdsynopsis>
</para></listitem>
</varlistentry>
+ <varlistentry>
+ <term><option>-t</option></term>
+ <listitem><para>
+ Check the syntax of the configuration file and report the first
+ error if any.
+ </para></listitem>
+ </varlistentry>
+
<varlistentry>
<term><option>-c</option></term>
<listitem><para>
#include <dhcp6/ctrl_dhcp6_srv.h>
#include <dhcp6/dhcp6_log.h>
+#include <dhcp6/parser_context.h>
#include <dhcpsrv/cfgmgr.h>
#include <log/logger_support.h>
#include <log/logger_manager.h>
#include <iostream>
+using namespace isc::data;
using namespace isc::dhcp;
using namespace std;
cerr << "Kea DHCPv6 server, version " << VERSION << endl;
cerr << endl;
cerr << "Usage: " << DHCP6_NAME
- << " -[v|V|W] [-d] [-c cfgfile] [-p port_number]" << endl;
+ << " -[v|V|W] [-d] [-t] [-c cfgfile] [-p port_number]" << endl;
cerr << " -v: print version number and exit." << endl;
cerr << " -V: print extended version and exit" << endl;
cerr << " -W: display the configuration report and exit" << endl;
cerr << " -d: debug mode with extra verbosity (former -v)" << endl;
+ cerr << " -t: check the configuration file syntax and exit" << endl;
cerr << " -c file: specify configuration file" << endl;
cerr << " -p number: specify non-standard port number 1-65535 "
<< "(useful for testing only)" << endl;
int port_number = DHCP6_SERVER_PORT; // The default. Any other values are
// useful for testing only.
bool verbose_mode = false; // Should server be verbose?
+ bool check_mode = false; // Check syntax
// The standard config file
std::string config_file("");
- while ((ch = getopt(argc, argv, "dvVWc:p:")) != -1) {
+ while ((ch = getopt(argc, argv, "dtvVWc:p:")) != -1) {
switch (ch) {
case 'd':
verbose_mode = true;
break;
+ case 't':
+ check_mode = true;
+ break;
+
case 'v':
cout << Dhcpv6Srv::getVersion(false) << endl;
return (EXIT_SUCCESS);
usage();
}
+ if (check_mode) {
+ try {
+ Parser6Context parser;
+ ConstElementPtr json;
+ json = parser.parseFile(config_file, Parser6Context::PARSER_DHCP6);
+ if (!json) {
+ cerr << "No configuration found" << endl;
+ return (EXIT_FAILURE);
+ }
+ if (verbose_mode) {
+ cerr << "Syntax check OK" << endl;
+ }
+ return (EXIT_SUCCESS);
+ } catch (const std::exception& ex) {
+ cerr << "Syntax check failed with " << ex.what() << endl;
+ }
+ return (EXIT_FAILURE);
+ }
int ret = EXIT_SUCCESS;
try {
]
}
}"
+# Invalid configuration (syntax error) to check that Kea can check syntax.
+CONFIG_BAD_SYNTAX="{
+ \"Dhcp6\":
+ {
+ \"interfaces\": [ ],
+ \"preferred-lifetime\": 3000,
+ \"valid-lifetime\": 4000,
+ \"renew-timer\": 1000,
+ \"rebind-timer\": 2000,
+ \"lease-database\":
+ {
+ \"type\": \"memfile\",
+ \"persist\": false
+ },
+ \"subnet6\": [
+ {
+ \"subnet\": \"2001:db8:1::/64\",
+ \"pool\": [ { \"pool\": \"2001:db8:1::10-2001:db8:1::100\" } ]
+ } ]
+ },
+
+ \"Logging\":
+ {
+ \"loggers\": [
+ {
+ \"name\": \"kea-dhcp6\",
+ \"output_options\": [
+ {
+ \"output\": \"$LOG_FILE\"
+ }
+ ],
+ \"severity\": \"INFO\"
+ }
+ ]
+ }
+}"
# Invalid configuration (negative preferred-lifetime) to check that Kea
# gracefully handles reconfiguration errors.
CONFIG_INVALID="{
\"Dhcp6\":
{
- \"interfaces\": [ ],
+ \"interfaces-config\": {
+ \"interfaces\": [ ]
+ },
\"preferred-lifetime\": -3,
\"valid-lifetime\": 4000,
\"renew-timer\": 1000,
# Import common test library.
. @abs_top_builddir@/src/lib/testutils/dhcp_test_lib.sh
+# This test verifies that syntax check works properly.
+syntax_check_test() {
+ # Log the start of the test and print test name.
+ test_start "dhcpv6_srv.syntax_check"
+ # Remove dangling Kea instances and remove log files.
+ cleanup
+ # Create correct configuration file.
+ create_config "${CONFIG}"
+ # Check it
+ printf "Running command %s.\n" "\"${bin_path}/${bin} -t -c ${CFG_FILE}\""
+ ${bin_path}/${bin} -t -c ${CFG_FILE}
+ exit_code=$?
+ if [ ${exit_code} -ne 0 ]; then
+ printf "ERROR: expected exit code 0, got ${exit_code}\n"
+ clean_exit 1
+ fi
+ # Create incorrect configuration file.
+ create_config "${CONFIG_BAD_SYNTAX}"
+ # Check it
+ printf "Running command %s.\n" "\"${bin_path}/${bin} -t -c ${CFG_FILE}\""
+ printf "A syntax error should be detected\n"
+ ${bin_path}/${bin} -t -c ${CFG_FILE}
+ if [ $? -eq 0 ]; then
+ printf "ERROR: expected exit code not 0, got 0\n"
+ clean_exit 1
+ fi
+ # All ok
+ clean_exit 0
+}
+
# This test verifies that DHCPv6 can be reconfigured with a SIGHUP signal.
dynamic_reconfiguration_test() {
# Log the start of the test and print test name.
shutdown_test "dhcpv6.sigterm_test" 15
shutdown_test "dhcpv6.sigint_test" 2
version_test "dhcpv6.version"
+syntax_check_test
logger_vars_test "dhcpv6.variables"
lfc_timer_test