Commit bd67a84f authored by Francis Dupont's avatar Francis Dupont

[5145b] Reverted trac5126 merge

parent 7eef7d97
...@@ -201,21 +201,6 @@ for retry in "none" "--std=c++11" "--std=c++0x" "--std=c++1x" "fail"; do ...@@ -201,21 +201,6 @@ for retry in "none" "--std=c++11" "--std=c++0x" "--std=c++1x" "fail"; do
[AC_MSG_RESULT([no]) [AC_MSG_RESULT([no])
continue]) continue])
AC_MSG_CHECKING(template alias)
feature="template alias"
AC_COMPILE_IFELSE(
[AC_LANG_PROGRAM(
[template<int i>
class I {
public: int get() { return i; };
};
using Zero = I<0>;],
[Zero Z;
return Z.get();])],
[AC_MSG_RESULT([yes])],
[AC_MSG_RESULT([no])
continue])
AC_MSG_CHECKING(lambda support) AC_MSG_CHECKING(lambda support)
feature="lambda" feature="lambda"
AC_COMPILE_IFELSE( AC_COMPILE_IFELSE(
...@@ -1482,11 +1467,11 @@ AC_ARG_ENABLE(generate_parser, [AC_HELP_STRING([--enable-generate-parser], ...@@ -1482,11 +1467,11 @@ AC_ARG_ENABLE(generate_parser, [AC_HELP_STRING([--enable-generate-parser],
enable_generate_parser=$enableval, enable_generate_parser=no) enable_generate_parser=$enableval, enable_generate_parser=no)
# Check if flex is avaible. Flex is not needed for building Kea sources, # Check if flex is avaible. Flex is not needed for building Kea sources,
# unless you want to regenerate grammars # unless you want to regenerate grammar in src/lib/eval
AC_PROG_LEX AC_PROG_LEX
# Check if bison is available. Bison is not needed for building Kea sources, # Check if bison is available. Bison is not needed for building Kea sources,
# unless you want to regenerate grammars # unless you want to regenerate grammar in src/lib/eval
AC_PROG_YACC AC_PROG_YACC
if test "x$enable_generate_parser" != "xno"; then if test "x$enable_generate_parser" != "xno"; then
...@@ -1500,7 +1485,7 @@ if test "x$enable_generate_parser" != "xno"; then ...@@ -1500,7 +1485,7 @@ if test "x$enable_generate_parser" != "xno"; then
fi fi
# Ok, let's check if we have at least 3.0.0 version of the bison. The code used # Ok, let's check if we have at least 3.0.0 version of the bison. The code used
# to generate parsers is roughly based on bison 3.0 examples. # to generate src/lib/eval parser is roughly based on bison 3.0 examples.
cat > bisontest.y << EOF cat > bisontest.y << EOF
%require "3.0.0" %require "3.0.0"
%token X %token X
...@@ -1614,28 +1599,20 @@ AM_COND_IF([HAVE_OPTRESET], [AC_DEFINE([HAVE_OPTRESET], [1], [Check for optreset ...@@ -1614,28 +1599,20 @@ AM_COND_IF([HAVE_OPTRESET], [AC_DEFINE([HAVE_OPTRESET], [1], [Check for optreset
AC_DEFINE([CONFIG_H_WAS_INCLUDED], [1], [config.h inclusion marker]) AC_DEFINE([CONFIG_H_WAS_INCLUDED], [1], [config.h inclusion marker])
AC_CONFIG_FILES([Makefile AC_CONFIG_FILES([compatcheck/Makefile
compatcheck/Makefile
dns++.pc dns++.pc
doc/Makefile
doc/design/Makefile
doc/design/datasrc/Makefile doc/design/datasrc/Makefile
doc/design/Makefile
doc/guide/Makefile doc/guide/Makefile
doc/Makefile
doc/version.ent doc/version.ent
ext/Makefile
ext/coroutine/Makefile ext/coroutine/Makefile
ext/gtest/Makefile ext/gtest/Makefile
ext/Makefile
m4macros/Makefile m4macros/Makefile
Makefile
src/Makefile src/Makefile
src/bin/Makefile src/bin/Makefile
src/bin/admin/Makefile
src/bin/admin/kea-admin
src/bin/admin/tests/Makefile
src/bin/admin/tests/cql_tests.sh
src/bin/admin/tests/data/Makefile
src/bin/admin/tests/memfile_tests.sh
src/bin/admin/tests/mysql_tests.sh
src/bin/admin/tests/pgsql_tests.sh
src/bin/agent/Makefile src/bin/agent/Makefile
src/bin/agent/tests/Makefile src/bin/agent/tests/Makefile
src/bin/agent/tests/ca_process_tests.sh src/bin/agent/tests/ca_process_tests.sh
...@@ -1667,6 +1644,15 @@ AC_CONFIG_FILES([Makefile ...@@ -1667,6 +1644,15 @@ AC_CONFIG_FILES([Makefile
src/bin/perfdhcp/Makefile src/bin/perfdhcp/Makefile
src/bin/perfdhcp/tests/Makefile src/bin/perfdhcp/tests/Makefile
src/bin/perfdhcp/tests/testdata/Makefile src/bin/perfdhcp/tests/testdata/Makefile
src/bin/admin/Makefile
src/bin/admin/kea-admin
src/bin/admin/tests/Makefile
src/bin/admin/tests/data/Makefile
src/bin/admin/tests/memfile_tests.sh
src/bin/admin/tests/mysql_tests.sh
src/bin/admin/tests/pgsql_tests.sh
src/bin/admin/tests/cql_tests.sh
src/bin/agent/tests/test_libraries.h
src/hooks/Makefile src/hooks/Makefile
src/hooks/dhcp/Makefile src/hooks/dhcp/Makefile
src/hooks/dhcp/user_chk/Makefile src/hooks/dhcp/user_chk/Makefile
...@@ -1699,8 +1685,6 @@ AC_CONFIG_FILES([Makefile ...@@ -1699,8 +1685,6 @@ AC_CONFIG_FILES([Makefile
src/lib/dns/gen-rdatacode.py src/lib/dns/gen-rdatacode.py
src/lib/dns/tests/Makefile src/lib/dns/tests/Makefile
src/lib/dns/tests/testdata/Makefile src/lib/dns/tests/testdata/Makefile
src/lib/eval/Makefile
src/lib/eval/tests/Makefile
src/lib/exceptions/Makefile src/lib/exceptions/Makefile
src/lib/exceptions/tests/Makefile src/lib/exceptions/tests/Makefile
src/lib/hooks/Makefile src/lib/hooks/Makefile
...@@ -1726,10 +1710,10 @@ AC_CONFIG_FILES([Makefile ...@@ -1726,10 +1710,10 @@ AC_CONFIG_FILES([Makefile
src/lib/process/spec_config.h.pre src/lib/process/spec_config.h.pre
src/lib/process/tests/Makefile src/lib/process/tests/Makefile
src/lib/process/testutils/Makefile src/lib/process/testutils/Makefile
src/lib/stats/Makefile
src/lib/stats/tests/Makefile
src/lib/testutils/Makefile src/lib/testutils/Makefile
src/lib/testutils/dhcp_test_lib.sh src/lib/testutils/dhcp_test_lib.sh
src/lib/stats/Makefile
src/lib/stats/tests/Makefile
src/lib/util/Makefile src/lib/util/Makefile
src/lib/util/io/Makefile src/lib/util/io/Makefile
src/lib/util/python/Makefile src/lib/util/python/Makefile
...@@ -1739,10 +1723,11 @@ AC_CONFIG_FILES([Makefile ...@@ -1739,10 +1723,11 @@ AC_CONFIG_FILES([Makefile
src/lib/util/threads/Makefile src/lib/util/threads/Makefile
src/lib/util/threads/tests/Makefile src/lib/util/threads/tests/Makefile
src/lib/util/unittests/Makefile src/lib/util/unittests/Makefile
src/lib/eval/Makefile
src/lib/eval/tests/Makefile
src/share/Makefile src/share/Makefile
src/share/database/Makefile src/share/database/Makefile
src/share/database/scripts/Makefile src/share/database/scripts/Makefile
src/share/database/scripts/cql/Makefile
src/share/database/scripts/mysql/Makefile src/share/database/scripts/mysql/Makefile
src/share/database/scripts/mysql/upgrade_1.0_to_2.0.sh src/share/database/scripts/mysql/upgrade_1.0_to_2.0.sh
src/share/database/scripts/mysql/upgrade_2.0_to_3.0.sh src/share/database/scripts/mysql/upgrade_2.0_to_3.0.sh
...@@ -1752,16 +1737,17 @@ AC_CONFIG_FILES([Makefile ...@@ -1752,16 +1737,17 @@ AC_CONFIG_FILES([Makefile
src/share/database/scripts/pgsql/Makefile src/share/database/scripts/pgsql/Makefile
src/share/database/scripts/pgsql/upgrade_1.0_to_2.0.sh src/share/database/scripts/pgsql/upgrade_1.0_to_2.0.sh
src/share/database/scripts/pgsql/upgrade_2.0_to_3.0.sh src/share/database/scripts/pgsql/upgrade_2.0_to_3.0.sh
src/share/database/scripts/cql/Makefile
tools/Makefile tools/Makefile
tools/path_replacer.sh tools/path_replacer.sh
]) ])
AC_CONFIG_COMMANDS([permissions], [ AC_CONFIG_COMMANDS([permissions], [
chmod +x src/bin/admin/kea-admin
chmod +x src/bin/dhcp4/tests/dhcp4_process_tests.sh chmod +x src/bin/dhcp4/tests/dhcp4_process_tests.sh
chmod +x src/bin/dhcp6/tests/dhcp6_process_tests.sh chmod +x src/bin/dhcp6/tests/dhcp6_process_tests.sh
chmod +x src/bin/keactrl/keactrl chmod +x src/bin/keactrl/keactrl
chmod +x src/bin/keactrl/tests/keactrl_tests.sh chmod +x src/bin/keactrl/tests/keactrl_tests.sh
chmod +x src/bin/admin/kea-admin
chmod +x src/lib/dns/gen-rdatacode.py chmod +x src/lib/dns/gen-rdatacode.py
chmod +x src/lib/log/tests/console_test.sh chmod +x src/lib/log/tests/console_test.sh
chmod +x src/lib/log/tests/destination_test.sh chmod +x src/lib/log/tests/destination_test.sh
......
// Copyright (C) 2015-2017 Internet Systems Consortium, Inc. ("ISC") // Copyright (C) 2015-2016 Internet Systems Consortium, Inc. ("ISC")
// //
// This Source Code Form is subject to the terms of the Mozilla Public // 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 // License, v. 2.0. If a copy of the MPL was not distributed with this
...@@ -35,7 +35,7 @@ Dhcp4to6Ipc& Dhcp4to6Ipc::instance() { ...@@ -35,7 +35,7 @@ Dhcp4to6Ipc& Dhcp4to6Ipc::instance() {
} }
void Dhcp4to6Ipc::open() { void Dhcp4to6Ipc::open() {
uint16_t port = CfgMgr::instance().getStagingCfg()->getDhcp4o6Port(); uint32_t port = CfgMgr::instance().getStagingCfg()->getDhcp4o6Port();
if (port == 0) { if (port == 0) {
Dhcp4o6IpcBase::close(); Dhcp4o6IpcBase::close();
return; return;
...@@ -45,7 +45,8 @@ void Dhcp4to6Ipc::open() { ...@@ -45,7 +45,8 @@ void Dhcp4to6Ipc::open() {
} }
int old_fd = socket_fd_; int old_fd = socket_fd_;
socket_fd_ = Dhcp4o6IpcBase::open(port, ENDPOINT_TYPE_V4); socket_fd_ = Dhcp4o6IpcBase::open(static_cast<uint16_t>(port),
ENDPOINT_TYPE_V4);
if ((old_fd == -1) && (socket_fd_ != old_fd)) { if ((old_fd == -1) && (socket_fd_ != old_fd)) {
IfaceMgr::instance().addExternalSocket(socket_fd_, IfaceMgr::instance().addExternalSocket(socket_fd_,
Dhcp4to6Ipc::handler); Dhcp4to6Ipc::handler);
......
...@@ -341,9 +341,24 @@ public: ...@@ -341,9 +341,24 @@ public:
cfg->setDeclinePeriod(probation_period); cfg->setDeclinePeriod(probation_period);
// Set the DHCPv4-over-DHCPv6 interserver port. // Set the DHCPv4-over-DHCPv6 interserver port.
uint16_t dhcp4o6_port = getUint16(global, "dhcp4o6-port"); // @todo Change for uint16_t
uint32_t dhcp4o6_port = getUint32(global, "dhcp4o6-port");
cfg->setDhcp4o6Port(dhcp4o6_port); cfg->setDhcp4o6Port(dhcp4o6_port);
} }
private:
/// @brief Returns a value converted to uint32_t
///
/// Instantiation of getIntType() to uint32_t
///
/// @param scope specified parameter will be extracted from this scope
/// @param name name of the parameter
/// @return an uint32_t value
uint32_t getUint32(isc::data::ConstElementPtr scope,
const std::string& name) {
return (getIntType<uint32_t>(scope, name));
}
}; };
} // anonymous namespace } // anonymous namespace
......
...@@ -4557,6 +4557,14 @@ TEST_F(Dhcp4ParserTest, invalidClientClassDictionary) { ...@@ -4557,6 +4557,14 @@ TEST_F(Dhcp4ParserTest, invalidClientClassDictionary) {
" } ] \n" " } ] \n"
"} \n"; "} \n";
ConstElementPtr json;
ASSERT_NO_THROW(json = parseJSON(config));
ConstElementPtr status;
EXPECT_NO_THROW(status = configureDhcp4Server(*srv_, json));
ASSERT_TRUE(status);
checkResult(status, 1);
EXPECT_THROW(parseDHCP4(config), Dhcp4ParseError); EXPECT_THROW(parseDHCP4(config), Dhcp4ParseError);
} }
......
// Copyright (C) 2015-2017 Internet Systems Consortium, Inc. ("ISC") // Copyright (C) 2015-2016 Internet Systems Consortium, Inc. ("ISC")
// //
// This Source Code Form is subject to the terms of the Mozilla Public // 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 // License, v. 2.0. If a copy of the MPL was not distributed with this
...@@ -34,7 +34,7 @@ Dhcp6to4Ipc& Dhcp6to4Ipc::instance() { ...@@ -34,7 +34,7 @@ Dhcp6to4Ipc& Dhcp6to4Ipc::instance() {
} }
void Dhcp6to4Ipc::open() { void Dhcp6to4Ipc::open() {
uint16_t port = CfgMgr::instance().getStagingCfg()->getDhcp4o6Port(); uint32_t port = CfgMgr::instance().getStagingCfg()->getDhcp4o6Port();
if (port == 0) { if (port == 0) {
Dhcp4o6IpcBase::close(); Dhcp4o6IpcBase::close();
return; return;
...@@ -44,7 +44,8 @@ void Dhcp6to4Ipc::open() { ...@@ -44,7 +44,8 @@ void Dhcp6to4Ipc::open() {
} }
int old_fd = socket_fd_; int old_fd = socket_fd_;
socket_fd_ = Dhcp4o6IpcBase::open(port, ENDPOINT_TYPE_V6); socket_fd_ = Dhcp4o6IpcBase::open(static_cast<uint16_t>(port),
ENDPOINT_TYPE_V6);
if ((old_fd == -1) && (socket_fd_ != old_fd)) { if ((old_fd == -1) && (socket_fd_ != old_fd)) {
IfaceMgr::instance().addExternalSocket(socket_fd_, IfaceMgr::instance().addExternalSocket(socket_fd_,
Dhcp6to4Ipc::handler); Dhcp6to4Ipc::handler);
......
...@@ -214,6 +214,18 @@ public: ...@@ -214,6 +214,18 @@ public:
private: private:
/// @brief Get an uint8_t value
///
/// Instantiation of getIntType() to uint8_t
///
/// @param scope specified parameter will be extracted from this scope
/// @param name name of the parameter
/// @return uint8_t value
/// @throw isc::dhcp::DhcpConfigError when it is not an uint8_t
uint8_t getUint8(ConstElementPtr scope, const std::string& name) {
return (getIntType<uint8_t>(scope, name));
}
/// Pointer to the created pool object. /// Pointer to the created pool object.
isc::dhcp::Pool6Ptr pool_; isc::dhcp::Pool6Ptr pool_;
...@@ -535,9 +547,24 @@ public: ...@@ -535,9 +547,24 @@ public:
srv_config->setDeclinePeriod(probation_period); srv_config->setDeclinePeriod(probation_period);
// Set the DHCPv4-over-DHCPv6 interserver port. // Set the DHCPv4-over-DHCPv6 interserver port.
uint16_t dhcp4o6_port = getUint16(global, "dhcp4o6-port"); // @todo Change for uint16_t
uint32_t dhcp4o6_port = getUint32(global, "dhcp4o6-port");
srv_config->setDhcp4o6Port(dhcp4o6_port); srv_config->setDhcp4o6Port(dhcp4o6_port);
} }
private:
/// @brief Returns a value converted to uint32_t
///
/// Instantiation of getIntType() to uint32_t
///
/// @param scope specified parameter will be extracted from this scope
/// @param name name of the parameter
/// @return an uint32_t value
uint32_t getUint32(isc::data::ConstElementPtr scope,
const std::string& name) {
return (getIntType<uint32_t>(scope, name));
}
}; };
} // anonymous namespace } // anonymous namespace
......
...@@ -4969,6 +4969,13 @@ TEST_F(Dhcp6ParserTest, invalidClientClassDictionary) { ...@@ -4969,6 +4969,13 @@ TEST_F(Dhcp6ParserTest, invalidClientClassDictionary) {
" } ] \n" " } ] \n"
"} \n"; "} \n";
ConstElementPtr json = parseJSON(config);
ConstElementPtr status;
EXPECT_NO_THROW(status = configureDhcp6Server(srv_, json));
ASSERT_TRUE(status);
checkResult(status, 1);
EXPECT_THROW(parseDHCP6(config), Dhcp6ParseError); EXPECT_THROW(parseDHCP6(config), Dhcp6ParseError);
} }
......
...@@ -74,7 +74,7 @@ SimpleParser::getPosition(const std::string& name, const data::ConstElementPtr p ...@@ -74,7 +74,7 @@ SimpleParser::getPosition(const std::string& name, const data::ConstElementPtr p
} }
ConstElementPtr elem = parent->get(name); ConstElementPtr elem = parent->get(name);
if (!elem) { if (!elem) {
return (parent->getPosition()); return (data::Element::ZERO_POSITION());
} }
return (elem->getPosition()); return (elem->getPosition());
} }
......
...@@ -104,9 +104,9 @@ class SimpleParser { ...@@ -104,9 +104,9 @@ class SimpleParser {
/// @brief Utility method that returns position of an element /// @brief Utility method that returns position of an element
/// ///
/// It's mostly useful for logging. If the element is missing /// It's mostly useful for logging. When any necessary parameter is
/// the parent position is returned or ZERO_POSITION if parent /// missing (either parent is null or it doesn't contain specified
/// is null. /// name) ZERO_POSITION is returned.
/// ///
/// @param name position of that element will be returned /// @param name position of that element will be returned
/// @param parent parent element (optional) /// @param parent parent element (optional)
...@@ -203,44 +203,6 @@ protected: ...@@ -203,44 +203,6 @@ protected:
<< "' (" << getPosition(name, scope) << ")"); << "' (" << getPosition(name, scope) << ")");
} }
} }
/// @brief Returns a value converted to uint32_t
///
/// Instantiation of getIntType() to uint32_t
///
/// @param scope specified parameter will be extracted from this scope
/// @param name name of the parameter
/// @return an uint32_t value
/// @throw isc::dhcp::DhcpConfigError when it is not an uint32_t
uint32_t getUint32(isc::data::ConstElementPtr scope,
const std::string& name) {
return (getIntType<uint32_t>(scope, name));
}
/// @brief Returns a value converted to uint16_t
///
/// Instantiation of getIntType() to uint16_t
///
/// @param scope specified parameter will be extracted from this scope
/// @param name name of the parameter
/// @return an uint16_t value
/// @throw isc::dhcp::DhcpConfigError when it is not an uint16_t
uint16_t getUint16(isc::data::ConstElementPtr scope,
const std::string& name) {
return (getIntType<uint16_t>(scope, name));
}
/// @brief Get an uint8_t value
///
/// Instantiation of getIntType() to uint8_t
///
/// @param scope specified parameter will be extracted from this scope
/// @param name name of the parameter
/// @return uint8_t value
/// @throw isc::dhcp::DhcpConfigError when it is not an uint8_t
uint8_t getUint8(ConstElementPtr scope, const std::string& name) {
return (getIntType<uint8_t>(scope, name));
}
}; };
}; };
......
...@@ -58,9 +58,14 @@ public: ...@@ -58,9 +58,14 @@ public:
class SimpleParserClassTest : public SimpleParser { class SimpleParserClassTest : public SimpleParser {
public: public:
/// @brief Instantiation of getIntType for uint8_t
/// Make getUint8 public ///
using SimpleParser::getUint8; /// @param scope specified parameter will be extracted from this scope
/// @param name name of the parameter for error report
/// @return an uint8_t value
uint8_t getUint8(ConstElementPtr scope, const std::string& name) {
return (getIntType<uint8_t>(scope, name));
}
/// @brief Instantiation of getAndConvert /// @brief Instantiation of getAndConvert
/// ///
......
...@@ -62,87 +62,86 @@ void ...@@ -62,87 +62,86 @@ void
ClientClassDefParser::parse(ClientClassDictionaryPtr& class_dictionary, ClientClassDefParser::parse(ClientClassDictionaryPtr& class_dictionary,
ConstElementPtr class_def_cfg, ConstElementPtr class_def_cfg,
uint16_t family) { uint16_t family) {
// name is now mandatory
std::string name = getString(class_def_cfg, "name");
if (name.empty()) {
isc_throw(DhcpConfigError,
"not empty parameter 'name' is required "
<< getPosition("name", class_def_cfg) << ")");
}
// Parse matching expression try {
ExpressionPtr match_expr; std::string name;
ConstElementPtr test = class_def_cfg->get("test"); std::string next_server_txt = "0.0.0.0";
if (test) { std::string sname;
ExpressionParser parser; std::string filename;
parser.parse(match_expr, test, family); ExpressionPtr match_expr;
} CfgOptionPtr options(new CfgOption());
// Parse the elements that make up the client class definition.
BOOST_FOREACH(ConfigPair param, class_def_cfg->mapValue()) {
std::string entry(param.first);
ConstElementPtr value(param.second);
if (entry == "name") {
name = value->stringValue();
} else if (entry == "test") {
ExpressionParser parser;
parser.parse(match_expr, value, family);
} else if (entry == "option-data") {
OptionDataListParser opts_parser(family);
opts_parser.parse(options, value);
} else if (entry == "next-server") {
next_server_txt = value->stringValue();
} else if (entry == "server-hostname") {
sname = value->stringValue();
} else if (entry == "boot-file-name") {
filename = value->stringValue();
} else {
isc_throw(DhcpConfigError, "invalid parameter '" << entry
<< "' (" << value->getPosition() << ")");
}
}
// Parse option data // name is now mandatory
CfgOptionPtr options(new CfgOption()); if (name.empty()) {
ConstElementPtr option_data = class_def_cfg->get("option-data"); isc_throw(DhcpConfigError,
if (option_data) { "not empty parameter 'name' is required");
OptionDataListParser opts_parser(family); }
opts_parser.parse(options, option_data);
}
// Let's try to parse the next-server field // Let's parse the next-server field
IOAddress next_server("0.0.0.0"); IOAddress next_server("0.0.0.0");
if (class_def_cfg->contains("next-server")) {
std::string next_server_txt = getString(class_def_cfg, "next-server");
try { try {
next_server = IOAddress(next_server_txt); next_server = IOAddress(next_server_txt);
} catch (const IOError& ex) { } catch (const IOError& ex) {
isc_throw(DhcpConfigError, isc_throw(DhcpConfigError, "Invalid next-server value specified: '"
"Invalid next-server value specified: '" << next_server_txt);
<< next_server_txt << "' ("
<< getPosition("next-server", class_def_cfg) << ")");
} }
if (next_server.getFamily() != AF_INET) { if (next_server.getFamily() != AF_INET) {
isc_throw(DhcpConfigError, "Invalid next-server value: '" isc_throw(DhcpConfigError, "Invalid next-server value: '"
<< next_server_txt << next_server_txt << "', must be IPv4 address");
<< "', must be IPv4 address ("
<< getPosition("next-server", class_def_cfg) << ")");
} }
if (next_server.isV4Bcast()) { if (next_server.isV4Bcast()) {
isc_throw(DhcpConfigError, "Invalid next-server value: '"