mirror of
https://gitlab.isc.org/isc-projects/kea
synced 2025-08-29 13:07:50 +00:00
parent
5b8e4c6da6
commit
cc7f318dd4
@ -1,3 +1,8 @@
|
||||
2109. [bug] fdupont
|
||||
Compatibility flags e.g. lenient-option-parsing were not
|
||||
saved by config-get and similar commands.
|
||||
(Gitlab #2790)
|
||||
|
||||
2108. [func] fdupont
|
||||
Added a new exclude-first-last-24 DHCPv4 compatibility flag
|
||||
which when set to true (default is false) skips addresses
|
||||
|
@ -594,6 +594,12 @@ configureDhcp4Server(Dhcpv4Srv& server, isc::data::ConstElementPtr config_set,
|
||||
ConstElementPtr compatibility = mutable_cfg->get("compatibility");
|
||||
if (compatibility) {
|
||||
for (auto kv : compatibility->mapValue()) {
|
||||
if (!kv.second || (kv.second->getType() != Element::boolean)) {
|
||||
isc_throw(DhcpConfigError,
|
||||
"compatibility parameter values must be "
|
||||
<< "boolean (" << kv.first << " at "
|
||||
<< kv.second->getPosition() << ")");
|
||||
}
|
||||
if (kv.first == "lenient-option-parsing") {
|
||||
CfgMgr::instance().getStagingCfg()->setLenientOptionParsing(
|
||||
kv.second->boolValue());
|
||||
|
@ -1680,18 +1680,106 @@ TEST_F(Dhcp4ParserTest, echoClientId) {
|
||||
// Now check that "false" configuration is really applied.
|
||||
ConstElementPtr status;
|
||||
EXPECT_NO_THROW(status = Dhcpv4SrvTest::configure(*srv_, json_false));
|
||||
checkResult(status, 0);
|
||||
ASSERT_FALSE(CfgMgr::instance().getStagingCfg()->getEchoClientId());
|
||||
|
||||
CfgMgr::instance().clear();
|
||||
|
||||
// Now check that "true" configuration is really applied.
|
||||
EXPECT_NO_THROW(status = Dhcpv4SrvTest::configure(*srv_, json_true));
|
||||
checkResult(status, 0);
|
||||
ASSERT_TRUE(CfgMgr::instance().getStagingCfg()->getEchoClientId());
|
||||
|
||||
// In any case revert back to the default value (true)
|
||||
CfgMgr::instance().getStagingCfg()->setEchoClientId(true);
|
||||
}
|
||||
|
||||
// Check whether it is possible to configure compatibility flags.
|
||||
TEST_F(Dhcp4ParserTest, compatibility) {
|
||||
string config = "{ " + genIfaceConfig() + "," +
|
||||
"\"rebind-timer\": 2000, "
|
||||
"\"renew-timer\": 1000, "
|
||||
"\"compatibility\": { "
|
||||
" \"lenient-option-parsing\": true,"
|
||||
" \"ignore-rai-link-selection\": true,"
|
||||
" \"exclude-first-last-24\": true"
|
||||
"},"
|
||||
"\"subnet4\": [ { "
|
||||
" \"pools\": [ { \"pool\": \"192.0.2.1 - 192.0.2.100\" } ],"
|
||||
" \"subnet\": \"192.0.2.0/24\" } ],"
|
||||
"\"valid-lifetime\": 4000 }";
|
||||
|
||||
ConstElementPtr json;
|
||||
ASSERT_NO_THROW(json = parseDHCP4(config)) << "bad config: " << config;
|
||||
extractConfig(config);
|
||||
|
||||
// Check defaults: they should be false.
|
||||
EXPECT_FALSE(CfgMgr::instance().getStagingCfg()->getLenientOptionParsing());
|
||||
EXPECT_FALSE(CfgMgr::instance().getStagingCfg()->getIgnoreRAILinkSelection());
|
||||
EXPECT_FALSE(CfgMgr::instance().getStagingCfg()->getExcludeFirstLast24());
|
||||
|
||||
// Check the configuration was really applied.
|
||||
ConstElementPtr status;
|
||||
EXPECT_NO_THROW(status = Dhcpv4SrvTest::configure(*srv_, json));
|
||||
checkResult(status, 0);
|
||||
|
||||
EXPECT_TRUE(CfgMgr::instance().getStagingCfg()->getLenientOptionParsing());
|
||||
EXPECT_TRUE(CfgMgr::instance().getStagingCfg()->getIgnoreRAILinkSelection());
|
||||
EXPECT_TRUE(CfgMgr::instance().getStagingCfg()->getExcludeFirstLast24());
|
||||
}
|
||||
|
||||
// Check that unknown compatibility flag raises error.
|
||||
TEST_F(Dhcp4ParserTest, compatibilityUnknown) {
|
||||
string config = "{ " + genIfaceConfig() + "," +
|
||||
"\"rebind-timer\": 2000, "
|
||||
"\"renew-timer\": 1000, "
|
||||
"\"compatibility\": { "
|
||||
" \"foo-bar\": true"
|
||||
"},"
|
||||
"\"subnet4\": [ { "
|
||||
" \"pools\": [ { \"pool\": \"192.0.2.1 - 192.0.2.100\" } ],"
|
||||
" \"subnet\": \"192.0.2.0/24\" } ],"
|
||||
"\"valid-lifetime\": 4000 }";
|
||||
|
||||
// Syntax is incorrect.
|
||||
EXPECT_THROW(parseDHCP4(config), Dhcp4ParseError);
|
||||
ConstElementPtr json;
|
||||
EXPECT_NO_THROW(json = parseJSON(config));
|
||||
|
||||
// Unknown keyword is detected.
|
||||
ConstElementPtr status;
|
||||
EXPECT_NO_THROW(status = Dhcpv4SrvTest::configure(*srv_, json));
|
||||
string expected = "unsupported compatibility parameter: ";
|
||||
expected += "foo-bar (<string>:1:127)";
|
||||
checkResult(status, 1, expected);
|
||||
}
|
||||
|
||||
// Check that not boolean compatibility flag value raises error.
|
||||
TEST_F(Dhcp4ParserTest, compatibilityNotBool) {
|
||||
string config = "{ " + genIfaceConfig() + "," +
|
||||
"\"rebind-timer\": 2000, "
|
||||
"\"renew-timer\": 1000, "
|
||||
"\"compatibility\": { "
|
||||
" \"lenient-option-parsing\": 1"
|
||||
"},"
|
||||
"\"subnet4\": [ { "
|
||||
" \"pools\": [ { \"pool\": \"192.0.2.1 - 192.0.2.100\" } ],"
|
||||
" \"subnet\": \"192.0.2.0/24\" } ],"
|
||||
"\"valid-lifetime\": 4000 }";
|
||||
|
||||
// Syntax is incorrect.
|
||||
EXPECT_THROW(parseDHCP4(config), Dhcp4ParseError);
|
||||
ConstElementPtr json;
|
||||
EXPECT_NO_THROW(json = parseJSON(config));
|
||||
|
||||
// Bad value type is detected.
|
||||
ConstElementPtr status;
|
||||
EXPECT_NO_THROW(status = Dhcpv4SrvTest::configure(*srv_, json));
|
||||
string expected = "compatibility parameter values must be boolean ";
|
||||
expected += "(lenient-option-parsing at <string>:1:142)";
|
||||
checkResult(status, 1, expected);
|
||||
}
|
||||
|
||||
// This test checks that the global match-client-id parameter is optional
|
||||
// and that values under the subnet are used.
|
||||
TEST_F(Dhcp4ParserTest, matchClientIdNoGlobal) {
|
||||
@ -7626,5 +7714,4 @@ TEST_F(Dhcp4ParserTest, parkedPacketLimit) {
|
||||
ASSERT_THROW(parseDHCP4(bad_limit), std::exception);
|
||||
}
|
||||
|
||||
|
||||
} // namespace
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -727,9 +727,20 @@ configureDhcp6Server(Dhcpv6Srv& server, isc::data::ConstElementPtr config_set,
|
||||
ConstElementPtr compatibility = mutable_cfg->get("compatibility");
|
||||
if (compatibility) {
|
||||
for (auto kv : compatibility->mapValue()) {
|
||||
if (!kv.second || (kv.second->getType() != Element::boolean)) {
|
||||
isc_throw(DhcpConfigError,
|
||||
"compatibility parameter values must be "
|
||||
<< "boolean (" << kv.first << " at "
|
||||
<< kv.second->getPosition() << ")");
|
||||
}
|
||||
if (kv.first == "lenient-option-parsing") {
|
||||
CfgMgr::instance().getStagingCfg()->setLenientOptionParsing(
|
||||
kv.second->boolValue());
|
||||
} else {
|
||||
isc_throw(DhcpConfigError,
|
||||
"unsupported compatibility parameter: "
|
||||
<< kv.first << " (" << kv.second->getPosition()
|
||||
<< ")");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1688,6 +1688,89 @@ TEST_F(Dhcp6ParserTest, reconfigureRemoveSubnet) {
|
||||
EXPECT_EQ(4, (*++subnet)->getID());
|
||||
}
|
||||
|
||||
// Check whether it is possible to configure compatibility flags.
|
||||
TEST_F(Dhcp6ParserTest, compatibility) {
|
||||
string config = "{ " + genIfaceConfig() + "," +
|
||||
"\"preferred-lifetime\": 3000,"
|
||||
"\"rebind-timer\": 2000, "
|
||||
"\"renew-timer\": 1000, "
|
||||
"\"compatibility\": { "
|
||||
" \"lenient-option-parsing\": true"
|
||||
"},"
|
||||
"\"subnet6\": [ { "
|
||||
" \"pools\": [ { \"pool\": \"2001:db8:1::1 - 2001:db8:1::ffff\" } ],"
|
||||
" \"subnet\": \"2001:db8:1::/64\" } ],"
|
||||
"\"valid-lifetime\": 4000 }";
|
||||
|
||||
ConstElementPtr json;
|
||||
ASSERT_NO_THROW(json = parseDHCP6(config)) << "bad config: " << config;
|
||||
extractConfig(config);
|
||||
|
||||
// Check defaults: they should be false.
|
||||
EXPECT_FALSE(CfgMgr::instance().getStagingCfg()->getLenientOptionParsing());
|
||||
|
||||
// Check the configuration was really applied.
|
||||
ConstElementPtr status;
|
||||
EXPECT_NO_THROW(status = Dhcpv6SrvTest::configure(srv_, json));
|
||||
checkResult(status, 0);
|
||||
|
||||
EXPECT_TRUE(CfgMgr::instance().getStagingCfg()->getLenientOptionParsing());
|
||||
}
|
||||
|
||||
// Check that unknown compatibility flag raises error.
|
||||
TEST_F(Dhcp6ParserTest, compatibilityUnknown) {
|
||||
string config = "{ " + genIfaceConfig() + "," +
|
||||
"\"preferred-lifetime\": 3000,"
|
||||
"\"rebind-timer\": 2000, "
|
||||
"\"renew-timer\": 1000, "
|
||||
"\"compatibility\": { "
|
||||
" \"foo-bar\": true"
|
||||
"},"
|
||||
"\"subnet6\": [ { "
|
||||
" \"pools\": [ { \"pool\": \"2001:db8:1::1 - 2001:db8:1::ffff\" } ],"
|
||||
" \"subnet\": \"2001:db8:1::/64\" } ],"
|
||||
"\"valid-lifetime\": 4000 }";
|
||||
|
||||
// Syntax is incorrect.
|
||||
EXPECT_THROW(parseDHCP6(config), Dhcp6ParseError);
|
||||
ConstElementPtr json;
|
||||
EXPECT_NO_THROW(json = parseJSON(config));
|
||||
|
||||
// Unknown keyword is detected.
|
||||
ConstElementPtr status;
|
||||
EXPECT_NO_THROW(status = Dhcpv6SrvTest::configure(srv_, json));
|
||||
string expected = "unsupported compatibility parameter: ";
|
||||
expected += "foo-bar (<string>:1:154)";
|
||||
checkResult(status, 1, expected);
|
||||
}
|
||||
|
||||
// Check that not boolean compatibility flag value raises error.
|
||||
TEST_F(Dhcp6ParserTest, compatibilityNotBool) {
|
||||
string config = "{ " + genIfaceConfig() + "," +
|
||||
"\"preferred-lifetime\": 3000,"
|
||||
"\"rebind-timer\": 2000, "
|
||||
"\"renew-timer\": 1000, "
|
||||
"\"compatibility\": { "
|
||||
" \"lenient-option-parsing\": 1"
|
||||
"},"
|
||||
"\"subnet6\": [ { "
|
||||
" \"pools\": [ { \"pool\": \"2001:db8:1::1 - 2001:db8:1::ffff\" } ],"
|
||||
" \"subnet\": \"2001:db8:1::/64\" } ],"
|
||||
"\"valid-lifetime\": 4000 }";
|
||||
|
||||
// Syntax is incorrect.
|
||||
EXPECT_THROW(parseDHCP6(config), Dhcp6ParseError);
|
||||
ConstElementPtr json;
|
||||
EXPECT_NO_THROW(json = parseJSON(config));
|
||||
|
||||
// Bad value type is detected.
|
||||
ConstElementPtr status;
|
||||
EXPECT_NO_THROW(status = Dhcpv6SrvTest::configure(srv_, json));
|
||||
string expected = "compatibility parameter values must be boolean ";
|
||||
expected += "(lenient-option-parsing at <string>:1:169)";
|
||||
checkResult(status, 1, expected);
|
||||
}
|
||||
|
||||
// This test checks if it is possible to override global values
|
||||
// on a per subnet basis.
|
||||
TEST_F(Dhcp6ParserTest, subnetLocal) {
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright (C) 2014-2022 Internet Systems Consortium, Inc. ("ISC")
|
||||
// Copyright (C) 2014-2023 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
|
||||
@ -48,7 +48,7 @@ SrvConfig::SrvConfig()
|
||||
d2_client_config_(new D2ClientConfig()),
|
||||
configured_globals_(new CfgGlobals()), cfg_consist_(new CfgConsistency()),
|
||||
lenient_option_parsing_(false), ignore_rai_link_selection_(false),
|
||||
reservations_lookup_first_(false) {
|
||||
exclude_first_last_24_(false), reservations_lookup_first_(false) {
|
||||
}
|
||||
|
||||
SrvConfig::SrvConfig(const uint32_t sequence)
|
||||
@ -67,7 +67,7 @@ SrvConfig::SrvConfig(const uint32_t sequence)
|
||||
d2_client_config_(new D2ClientConfig()),
|
||||
configured_globals_(new CfgGlobals()), cfg_consist_(new CfgConsistency()),
|
||||
lenient_option_parsing_(false), ignore_rai_link_selection_(false),
|
||||
reservations_lookup_first_(false) {
|
||||
exclude_first_last_24_(false), reservations_lookup_first_(false) {
|
||||
}
|
||||
|
||||
std::string
|
||||
@ -632,6 +632,21 @@ SrvConfig::toElement() const {
|
||||
}
|
||||
}
|
||||
|
||||
// Set compatibility flags.
|
||||
ElementPtr compatibility = Element::createMap();
|
||||
if (getLenientOptionParsing()) {
|
||||
compatibility->set("lenient-option-parsing", Element::create(true));
|
||||
}
|
||||
if (getIgnoreRAILinkSelection()) {
|
||||
compatibility->set("ignore-rai-link-selection", Element::create(true));
|
||||
}
|
||||
if (getExcludeFirstLast24()) {
|
||||
compatibility->set("exclude-first-last-24", Element::create(true));
|
||||
}
|
||||
if (compatibility->size() > 0) {
|
||||
dhcp->set("compatibility", compatibility);
|
||||
}
|
||||
|
||||
// Set decline-probation-period
|
||||
dhcp->set("decline-probation-period",
|
||||
Element::create(static_cast<long long>(decline_timer_)));
|
||||
|
@ -309,6 +309,38 @@ TEST_F(SrvConfigTest, echoClientId) {
|
||||
EXPECT_TRUE(conf1.getEchoClientId());
|
||||
}
|
||||
|
||||
// This test verifies that compatibility flags are correctly managed.
|
||||
TEST_F(SrvConfigTest, compatibility) {
|
||||
SrvConfig conf;
|
||||
|
||||
// Check that defaults are false.
|
||||
EXPECT_FALSE(conf.getLenientOptionParsing());
|
||||
EXPECT_FALSE(conf.getIgnoreRAILinkSelection());
|
||||
EXPECT_FALSE(conf.getExcludeFirstLast24());
|
||||
|
||||
// Check that they can be modified to true.
|
||||
conf.setLenientOptionParsing(true);
|
||||
conf.setIgnoreRAILinkSelection(true);
|
||||
conf.setExcludeFirstLast24(true);
|
||||
EXPECT_TRUE(conf.getLenientOptionParsing());
|
||||
EXPECT_TRUE(conf.getIgnoreRAILinkSelection());
|
||||
EXPECT_TRUE(conf.getExcludeFirstLast24());
|
||||
|
||||
// Check that default values can be restored.
|
||||
conf.setLenientOptionParsing(false);
|
||||
conf.setIgnoreRAILinkSelection(false);
|
||||
conf.setExcludeFirstLast24(false);
|
||||
EXPECT_FALSE(conf.getLenientOptionParsing());
|
||||
EXPECT_FALSE(conf.getIgnoreRAILinkSelection());
|
||||
EXPECT_FALSE(conf.getExcludeFirstLast24());
|
||||
|
||||
// Check the other constructor has the same default.
|
||||
SrvConfig conf1(1);
|
||||
EXPECT_FALSE(conf1.getLenientOptionParsing());
|
||||
EXPECT_FALSE(conf1.getIgnoreRAILinkSelection());
|
||||
EXPECT_FALSE(conf1.getExcludeFirstLast24());
|
||||
}
|
||||
|
||||
// This test verifies that host reservations lookup first flag can be configured.
|
||||
TEST_F(SrvConfigTest, reservationsLookupFirst) {
|
||||
SrvConfig conf;
|
||||
@ -600,10 +632,19 @@ TEST_F(SrvConfigTest, unparse) {
|
||||
CfgMgr::instance().setFamily(AF_INET);
|
||||
conf.setEchoClientId(false);
|
||||
conf.setDhcp4o6Port(6767);
|
||||
// Add compatibility flags.
|
||||
conf.setLenientOptionParsing(true);
|
||||
conf.setIgnoreRAILinkSelection(true);
|
||||
conf.setExcludeFirstLast24(true);
|
||||
params = "\"compatibility\": {\n";
|
||||
params += " \"lenient-option-parsing\": true,\n";
|
||||
params += " \"ignore-rai-link-selection\": true,\n";
|
||||
params += " \"exclude-first-last-24\": true\n";
|
||||
params += "},\n";
|
||||
// Add "configured globals"
|
||||
conf.addConfiguredGlobal("renew-timer", Element::create(777));
|
||||
conf.addConfiguredGlobal("comment", Element::create("bar"));
|
||||
params = "\"echo-client-id\": false,\n";
|
||||
params += "\"echo-client-id\": false,\n";
|
||||
params += "\"dhcp4o6-port\": 6767,\n";
|
||||
params += "\"renew-timer\": 777,\n";
|
||||
params += "\"comment\": \"bar\"\n";
|
||||
@ -612,7 +653,14 @@ TEST_F(SrvConfigTest, unparse) {
|
||||
|
||||
// Verify direct non-default parameters and configured globals
|
||||
CfgMgr::instance().setFamily(AF_INET6);
|
||||
params = ",\"dhcp4o6-port\": 6767,\n";
|
||||
// Add compatibility flag.
|
||||
conf.setIgnoreRAILinkSelection(false);
|
||||
conf.setExcludeFirstLast24(false);
|
||||
params = ",\"compatibility\": {\n";
|
||||
params += " \"lenient-option-parsing\": true\n";
|
||||
params += "},\n";
|
||||
// Add "configured globals"
|
||||
params += "\"dhcp4o6-port\": 6767,\n";
|
||||
params += "\"renew-timer\": 777,\n";
|
||||
params += "\"comment\": \"bar\"\n";
|
||||
isc::test::runToElementTest<SrvConfig>
|
||||
|
Loading…
x
Reference in New Issue
Block a user