mirror of
https://gitlab.isc.org/isc-projects/kea
synced 2025-08-30 05:27:55 +00:00
[#3049] kea-dhcp4 parsing and UTs
Fully functional in kea-dhcp4 (excluding doc update and CB support) /doc/examples/kea4/all-keys.json Added entries to a pool /src/bin/dhcp4/dhcp4_lexer.ll /src/bin/dhcp4/dhcp4_parser.yy Added parameters to pools /src/bin/dhcp4/dhcp4_srv.cc Added comment /src/bin/dhcp4/tests/config_parser_unittest.cc TEST_F(Dhcp4ParserTest, poolDdnsParameters) - new test /src/bin/dhcp4/tests/fqdn_unittest.cc TEST_F(NameDhcpv4SrvTest, poolDdnsParametersTest) - new test /src/bin/dhcp4/tests/get_config_unittest.cc Updated /src/lib/dhcpsrv/parsers/base_network_parser.* Moved DDNS parameter parsing to a function template to allow use by any class type /src/lib/dhcpsrv/parsers/dhcp_parsers.cc Added DDNS parameter parsing to PoolParser /src/lib/dhcpsrv/parsers/simple_parser4.cc Added paramters to pool /src/lib/dhcpsrv/tests/dhcp_parsers_unittest.cc TEST_F(DhcpParserTest, validDdnsParmatersPool4) - new test
This commit is contained in:
parent
1f7dddcfab
commit
bfe892dfa2
@ -1153,7 +1153,51 @@
|
||||
|
||||
// List of client classes which must be evaluated when this pool
|
||||
// is selected for client assignments.
|
||||
"evaluate-additional-classes": [ "late" ]
|
||||
"evaluate-additional-classes": [ "late" ],
|
||||
|
||||
// Pool-level value. See description at the global level.
|
||||
"ddns-generated-prefix": "mypool",
|
||||
|
||||
// Pool-level value. See description at the global level.
|
||||
"ddns-override-client-update": false,
|
||||
|
||||
// Pool-level value. See description at the global level.
|
||||
"ddns-override-no-update": false,
|
||||
|
||||
// Pool-level value. See description at the global level.
|
||||
"ddns-qualifying-suffix": "pool.example.com.",
|
||||
|
||||
// Pool-level value. See description at the global level.
|
||||
"ddns-replace-client-name": "always",
|
||||
|
||||
// Pool-level value. See description at the global level.
|
||||
"ddns-send-updates": true,
|
||||
|
||||
// Pool-level value. See description at the global level.
|
||||
"ddns-update-on-renew": false,
|
||||
|
||||
// Pool-level value. See description at the global level.
|
||||
"ddns-conflict-resolution-mode": "check-with-dhcid",
|
||||
|
||||
// Pool-level value. See description at the global level.
|
||||
"ddns-ttl-percent": 0.55,
|
||||
|
||||
// Pool-level value. See description at the global level.
|
||||
// You cannot specify both ddns-ttl and any of ddns-ttl-percent,
|
||||
// ddns-ttl-min, or ddns-ttl-max. They are mutually exclusive.
|
||||
// "ddns-ttl": 500,
|
||||
|
||||
// Pool-evel value. See description at the global level.
|
||||
"ddns-ttl-min": 10000,
|
||||
|
||||
// Pool-level value. See description at the global level.
|
||||
"ddns-ttl-max": 20000,
|
||||
|
||||
// Pool-level value. See description at the global level.
|
||||
"hostname-char-replacement": "x",
|
||||
|
||||
// Pool-level value. See description at the global level.
|
||||
"hostname-char-set": "[^A-Za-z0-9.-]"
|
||||
},
|
||||
{
|
||||
// Restricts this pool to allow only clients
|
||||
|
@ -1145,7 +1145,8 @@ Messages printed on debuglevel 55
|
||||
- DHCP6_QUERY_DATA
|
||||
- DHCP6_RESPONSE_DATA
|
||||
- DHCP6_SUBNET_DATA
|
||||
- DHCPSRV_DDNS_TTL_PERCENT_TOO_SMALL
|
||||
- DHCPSRV_DDNS_TTL_TOO_LARGE
|
||||
- DHCPSRV_DDNS_TTL_TOO_SMALL
|
||||
- DHCPSRV_MEMFILE_LEASE_LOAD
|
||||
- DHCPSRV_QUEUE_NCR
|
||||
- DHCP_DDNS_AT_MAX_TRANSACTIONS
|
||||
|
@ -8585,19 +8585,19 @@ the database access parameters are changed: in the latter case, the
|
||||
server closes the currently open database, and opens a database using
|
||||
the new parameters.
|
||||
|
||||
DHCPSRV_DDNS_TTL_PERCENT_TOO_SMALL
|
||||
==================================
|
||||
DHCPSRV_DDNS_TTL_TOO_SMALL
|
||||
==========================
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
ddns-ttl-percent %1 of lease lifetime %2 is too small, ignoring it
|
||||
%1 of lease life time %2 is %3, using minimum of %4 instead.
|
||||
|
||||
Logged at debug log level 55.
|
||||
A debug message issued when the DDNS TTL value calculated using the
|
||||
ddns-ttl-percent is zero. Kea will ignore the value and calculate
|
||||
the DDNS TTL as though ddsn-ttl-percent were not specified. The
|
||||
value of ddns-ttl-percent and the lease lifetime are shown in
|
||||
the message details.
|
||||
ddns-ttl-percent if specified or (0.33 if not) is too small. Kea will
|
||||
ignore the value and use the minimum (ddns-ttl-min if specified or 600
|
||||
seconds if not). The message details include the percentage, the lease
|
||||
life time, the calculated TTL, and the value actually used.
|
||||
|
||||
DHCPSRV_DHCP4O6_RECEIVED_BAD_PACKET
|
||||
===================================
|
||||
@ -10012,6 +10012,16 @@ A debug message issued when one of the registered interval timers
|
||||
is unregistered from the Timer Manager. The name of the timer is
|
||||
included in the message.
|
||||
|
||||
DHCPSRV_UNKNOWN_DB
|
||||
==================
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
unknown database type: %1
|
||||
|
||||
The database access string specified a database type (given in the
|
||||
message) that is unknown to the software. This is a configuration error.
|
||||
|
||||
****
|
||||
DHCP
|
||||
****
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2016-2024 Internet Systems Consortium, Inc. ("ISC")
|
||||
/* Copyright (C) 2016-2025 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
|
||||
@ -764,6 +764,7 @@ ControlCharacterFill [^"\\]|\\["\\/bfnrtu]
|
||||
case isc::dhcp::Parser4Context::DHCP4:
|
||||
case isc::dhcp::Parser4Context::SUBNET4:
|
||||
case isc::dhcp::Parser4Context::SHARED_NETWORK:
|
||||
case isc::dhcp::Parser4Context::POOLS:
|
||||
return isc::dhcp::Dhcp4Parser::make_DDNS_SEND_UPDATES(driver.loc_);
|
||||
default:
|
||||
return isc::dhcp::Dhcp4Parser::make_STRING("ddns-send-updates", driver.loc_);
|
||||
@ -775,6 +776,7 @@ ControlCharacterFill [^"\\]|\\["\\/bfnrtu]
|
||||
case isc::dhcp::Parser4Context::DHCP4:
|
||||
case isc::dhcp::Parser4Context::SUBNET4:
|
||||
case isc::dhcp::Parser4Context::SHARED_NETWORK:
|
||||
case isc::dhcp::Parser4Context::POOLS:
|
||||
return isc::dhcp::Dhcp4Parser::make_DDNS_OVERRIDE_NO_UPDATE(driver.loc_);
|
||||
default:
|
||||
return isc::dhcp::Dhcp4Parser::make_STRING("ddns-override-no-update", driver.loc_);
|
||||
@ -786,6 +788,7 @@ ControlCharacterFill [^"\\]|\\["\\/bfnrtu]
|
||||
case isc::dhcp::Parser4Context::DHCP4:
|
||||
case isc::dhcp::Parser4Context::SUBNET4:
|
||||
case isc::dhcp::Parser4Context::SHARED_NETWORK:
|
||||
case isc::dhcp::Parser4Context::POOLS:
|
||||
return isc::dhcp::Dhcp4Parser::make_DDNS_OVERRIDE_CLIENT_UPDATE(driver.loc_);
|
||||
default:
|
||||
return isc::dhcp::Dhcp4Parser::make_STRING("ddns-override-client-update", driver.loc_);
|
||||
@ -797,6 +800,7 @@ ControlCharacterFill [^"\\]|\\["\\/bfnrtu]
|
||||
case isc::dhcp::Parser4Context::DHCP4:
|
||||
case isc::dhcp::Parser4Context::SUBNET4:
|
||||
case isc::dhcp::Parser4Context::SHARED_NETWORK:
|
||||
case isc::dhcp::Parser4Context::POOLS:
|
||||
return isc::dhcp::Dhcp4Parser::make_DDNS_REPLACE_CLIENT_NAME(driver.loc_);
|
||||
default:
|
||||
return isc::dhcp::Dhcp4Parser::make_STRING("ddns-replace-client-name", driver.loc_);
|
||||
@ -808,6 +812,7 @@ ControlCharacterFill [^"\\]|\\["\\/bfnrtu]
|
||||
case isc::dhcp::Parser4Context::DHCP4:
|
||||
case isc::dhcp::Parser4Context::SUBNET4:
|
||||
case isc::dhcp::Parser4Context::SHARED_NETWORK:
|
||||
case isc::dhcp::Parser4Context::POOLS:
|
||||
return isc::dhcp::Dhcp4Parser::make_DDNS_GENERATED_PREFIX(driver.loc_);
|
||||
default:
|
||||
return isc::dhcp::Dhcp4Parser::make_STRING("ddns-generated-prefix", driver.loc_);
|
||||
@ -819,6 +824,7 @@ ControlCharacterFill [^"\\]|\\["\\/bfnrtu]
|
||||
case isc::dhcp::Parser4Context::DHCP4:
|
||||
case isc::dhcp::Parser4Context::SUBNET4:
|
||||
case isc::dhcp::Parser4Context::SHARED_NETWORK:
|
||||
case isc::dhcp::Parser4Context::POOLS:
|
||||
return isc::dhcp::Dhcp4Parser::make_DDNS_QUALIFYING_SUFFIX(driver.loc_);
|
||||
default:
|
||||
return isc::dhcp::Dhcp4Parser::make_STRING("ddns-qualifying-suffix", driver.loc_);
|
||||
@ -830,6 +836,7 @@ ControlCharacterFill [^"\\]|\\["\\/bfnrtu]
|
||||
case isc::dhcp::Parser4Context::DHCP4:
|
||||
case isc::dhcp::Parser4Context::SUBNET4:
|
||||
case isc::dhcp::Parser4Context::SHARED_NETWORK:
|
||||
case isc::dhcp::Parser4Context::POOLS:
|
||||
return isc::dhcp::Dhcp4Parser::make_DDNS_UPDATE_ON_RENEW(driver.loc_);
|
||||
default:
|
||||
return isc::dhcp::Dhcp4Parser::make_STRING("ddns-update-on-renew", driver.loc_);
|
||||
@ -852,6 +859,7 @@ ControlCharacterFill [^"\\]|\\["\\/bfnrtu]
|
||||
case isc::dhcp::Parser4Context::DHCP4:
|
||||
case isc::dhcp::Parser4Context::SUBNET4:
|
||||
case isc::dhcp::Parser4Context::SHARED_NETWORK:
|
||||
case isc::dhcp::Parser4Context::POOLS:
|
||||
return isc::dhcp::Dhcp4Parser::make_DDNS_CONFLICT_RESOLUTION_MODE(driver.loc_);
|
||||
default:
|
||||
return isc::dhcp::Dhcp4Parser::make_STRING("ddns-conflict-resolution-mode", driver.loc_);
|
||||
@ -899,6 +907,7 @@ ControlCharacterFill [^"\\]|\\["\\/bfnrtu]
|
||||
case isc::dhcp::Parser4Context::DHCP4:
|
||||
case isc::dhcp::Parser4Context::SUBNET4:
|
||||
case isc::dhcp::Parser4Context::SHARED_NETWORK:
|
||||
case isc::dhcp::Parser4Context::POOLS:
|
||||
return isc::dhcp::Dhcp4Parser::make_DDNS_TTL_PERCENT(driver.loc_);
|
||||
default:
|
||||
return isc::dhcp::Dhcp4Parser::make_STRING("ddns-ttl-percent", driver.loc_);
|
||||
@ -910,6 +919,7 @@ ControlCharacterFill [^"\\]|\\["\\/bfnrtu]
|
||||
case isc::dhcp::Parser4Context::DHCP4:
|
||||
case isc::dhcp::Parser4Context::SUBNET4:
|
||||
case isc::dhcp::Parser4Context::SHARED_NETWORK:
|
||||
case isc::dhcp::Parser4Context::POOLS:
|
||||
return isc::dhcp::Dhcp4Parser::make_DDNS_TTL(driver.loc_);
|
||||
default:
|
||||
return isc::dhcp::Dhcp4Parser::make_STRING("ddns-ttl", driver.loc_);
|
||||
@ -921,6 +931,7 @@ ControlCharacterFill [^"\\]|\\["\\/bfnrtu]
|
||||
case isc::dhcp::Parser4Context::DHCP4:
|
||||
case isc::dhcp::Parser4Context::SUBNET4:
|
||||
case isc::dhcp::Parser4Context::SHARED_NETWORK:
|
||||
case isc::dhcp::Parser4Context::POOLS:
|
||||
return isc::dhcp::Dhcp4Parser::make_DDNS_TTL_MIN(driver.loc_);
|
||||
default:
|
||||
return isc::dhcp::Dhcp4Parser::make_STRING("ddns-ttl-min", driver.loc_);
|
||||
@ -932,6 +943,7 @@ ControlCharacterFill [^"\\]|\\["\\/bfnrtu]
|
||||
case isc::dhcp::Parser4Context::DHCP4:
|
||||
case isc::dhcp::Parser4Context::SUBNET4:
|
||||
case isc::dhcp::Parser4Context::SHARED_NETWORK:
|
||||
case isc::dhcp::Parser4Context::POOLS:
|
||||
return isc::dhcp::Dhcp4Parser::make_DDNS_TTL_MAX(driver.loc_);
|
||||
default:
|
||||
return isc::dhcp::Dhcp4Parser::make_STRING("ddns-ttl-max", driver.loc_);
|
||||
@ -1993,6 +2005,7 @@ ControlCharacterFill [^"\\]|\\["\\/bfnrtu]
|
||||
case isc::dhcp::Parser4Context::DHCP4:
|
||||
case isc::dhcp::Parser4Context::SUBNET4:
|
||||
case isc::dhcp::Parser4Context::SHARED_NETWORK:
|
||||
case isc::dhcp::Parser4Context::POOLS:
|
||||
return isc::dhcp::Dhcp4Parser::make_HOSTNAME_CHAR_SET(driver.loc_);
|
||||
default:
|
||||
return isc::dhcp::Dhcp4Parser::make_STRING("hostname-char-set", driver.loc_);
|
||||
@ -2004,6 +2017,7 @@ ControlCharacterFill [^"\\]|\\["\\/bfnrtu]
|
||||
case isc::dhcp::Parser4Context::DHCP4:
|
||||
case isc::dhcp::Parser4Context::SUBNET4:
|
||||
case isc::dhcp::Parser4Context::SHARED_NETWORK:
|
||||
case isc::dhcp::Parser4Context::POOLS:
|
||||
return isc::dhcp::Dhcp4Parser::make_HOSTNAME_CHAR_REPLACEMENT(driver.loc_);
|
||||
default:
|
||||
return isc::dhcp::Dhcp4Parser::make_STRING("hostname-char-replacement", driver.loc_);
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -5712,7 +5712,7 @@ switch (yykind)
|
||||
/// Constants.
|
||||
enum
|
||||
{
|
||||
yylast_ = 1448, ///< Last index in yytable_.
|
||||
yylast_ = 1608, ///< Last index in yytable_.
|
||||
yynnts_ = 481, ///< Number of nonterminal symbols.
|
||||
yyfinal_ = 28 ///< Termination state number.
|
||||
};
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2016-2024 Internet Systems Consortium, Inc. ("ISC")
|
||||
/* Copyright (C) 2016-2025 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
|
||||
@ -2210,6 +2210,20 @@ pool_param: pool_entry
|
||||
| network_client_classes
|
||||
| require_client_classes
|
||||
| evaluate_additional_classes
|
||||
| ddns_send_updates
|
||||
| ddns_override_no_update
|
||||
| ddns_override_client_update
|
||||
| ddns_replace_client_name
|
||||
| ddns_generated_prefix
|
||||
| ddns_qualifying_suffix
|
||||
| ddns_update_on_renew
|
||||
| ddns_conflict_resolution_mode
|
||||
| ddns_ttl_percent
|
||||
| ddns_ttl
|
||||
| ddns_ttl_min
|
||||
| ddns_ttl_max
|
||||
| hostname_char_set
|
||||
| hostname_char_replacement
|
||||
| user_context
|
||||
| comment
|
||||
| unknown_map_entry
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright (C) 2011-2024 Internet Systems Consortium, Inc. ("ISC")
|
||||
// Copyright (C) 2011-2025 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
|
||||
@ -3179,6 +3179,8 @@ Dhcpv4Srv::assignLease(Dhcpv4Exchange& ex) {
|
||||
|
||||
bool reprocess_client_name = false;
|
||||
if (lease) {
|
||||
// Since we have a lease check for pool-level DDNS parameters.
|
||||
// If there are any we need to call processClientName() again.
|
||||
auto ddns_params = ex.getContext()->getDdnsParams();
|
||||
auto pool = ddns_params->setPoolFromAddress(lease->addr_);
|
||||
if (pool) {
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright (C) 2012-2024 Internet Systems Consortium, Inc. ("ISC")
|
||||
// Copyright (C) 2012-2025 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
|
||||
@ -8450,4 +8450,125 @@ TEST_F(Dhcp4ParserTest, ddnsTtlMax) {
|
||||
EXPECT_EQ(750, subnet->getDdnsTtlMax(Network::Inheritance::GLOBAL).get());
|
||||
}
|
||||
|
||||
TEST_F(Dhcp4ParserTest, poolDdnsParameters) {
|
||||
string config = R"(
|
||||
{
|
||||
"valid-lifetime": 4000,
|
||||
"subnet4": [{
|
||||
"id": 1,
|
||||
"subnet": "192.0.0.0/16",
|
||||
"pools": [{
|
||||
"pool": "192.0.1.0/24",
|
||||
"ddns-send-updates": true,
|
||||
"ddns-override-no-update": true,
|
||||
"ddns-override-client-update": true,
|
||||
"ddns-replace-client-name": "always",
|
||||
"ddns-generated-prefix": "prefix",
|
||||
"ddns-qualifying-suffix": "suffix",
|
||||
"hostname-char-set": "[a-z]",
|
||||
"hostname-char-replacement": "X",
|
||||
"ddns-update-on-renew": true,
|
||||
"ddns-ttl-percent": 0.5,
|
||||
"ddns-conflict-resolution-mode": "check-with-dhcid",
|
||||
"ddns-ttl-min": 200,
|
||||
"ddns-ttl-max": 500
|
||||
},
|
||||
{
|
||||
"pool": "192.0.2.0/24",
|
||||
"ddns-ttl": 300
|
||||
}]
|
||||
}]
|
||||
}
|
||||
)";
|
||||
|
||||
ConstElementPtr json;
|
||||
ASSERT_NO_THROW(json = parseDHCP4(config));
|
||||
extractConfig(config);
|
||||
|
||||
ConstElementPtr status;
|
||||
EXPECT_NO_THROW(status = Dhcpv4SrvTest::configure(*srv_, json));
|
||||
|
||||
// returned value should be 0 (success)
|
||||
checkResult(status, 0);
|
||||
|
||||
// Commit it so global inheritance works.
|
||||
CfgMgr::instance().commit();
|
||||
|
||||
ConstSubnet4Ptr subnet = CfgMgr::instance().getCurrentCfg()->
|
||||
getCfgSubnets4()->selectSubnet(IOAddress("192.0.0.0"));
|
||||
ASSERT_TRUE(subnet);
|
||||
|
||||
const PoolCollection pools = subnet->getPools(Lease::TYPE_V4);
|
||||
ASSERT_GE(pools.size(), 2);
|
||||
|
||||
// First pool specifies all but ddns-ttl.
|
||||
PoolPtr pool = pools.at(0);
|
||||
ASSERT_TRUE(pool);
|
||||
|
||||
ASSERT_FALSE(pool->getDdnsSendUpdates().unspecified());
|
||||
EXPECT_TRUE(pool->getDdnsSendUpdates().get());
|
||||
|
||||
ASSERT_FALSE(pool->getDdnsOverrideNoUpdate().unspecified());
|
||||
EXPECT_TRUE(pool->getDdnsOverrideNoUpdate().get());
|
||||
|
||||
ASSERT_FALSE(pool->getDdnsOverrideClientUpdate().unspecified());
|
||||
EXPECT_TRUE(pool->getDdnsOverrideClientUpdate().get());
|
||||
|
||||
ASSERT_FALSE(pool->getDdnsReplaceClientNameMode().unspecified());
|
||||
EXPECT_EQ(pool->getDdnsReplaceClientNameMode().get(),
|
||||
D2ClientConfig::RCM_ALWAYS);
|
||||
|
||||
ASSERT_FALSE(pool->getDdnsGeneratedPrefix().unspecified());
|
||||
EXPECT_EQ(pool->getDdnsGeneratedPrefix().get(), "prefix");
|
||||
|
||||
ASSERT_FALSE(pool->getDdnsQualifyingSuffix().unspecified());
|
||||
EXPECT_EQ(pool->getDdnsQualifyingSuffix().get(), "suffix");
|
||||
|
||||
ASSERT_FALSE(pool->getHostnameCharSet().unspecified());
|
||||
EXPECT_EQ(pool->getHostnameCharSet().get(), "[a-z]");
|
||||
|
||||
ASSERT_FALSE(pool->getHostnameCharReplacement().unspecified());
|
||||
EXPECT_EQ(pool->getHostnameCharReplacement().get(), "X");
|
||||
|
||||
ASSERT_FALSE(pool->getDdnsUpdateOnRenew().unspecified());
|
||||
EXPECT_TRUE(pool->getDdnsUpdateOnRenew().get());
|
||||
|
||||
ASSERT_FALSE(pool->getDdnsTtlPercent().unspecified());
|
||||
EXPECT_EQ(pool->getDdnsTtlPercent().get(), 0.5);
|
||||
|
||||
ASSERT_FALSE(pool->getDdnsConflictResolutionMode().unspecified());
|
||||
EXPECT_EQ(pool->getDdnsConflictResolutionMode().get(), "check-with-dhcid");
|
||||
|
||||
ASSERT_TRUE(pool->getDdnsTtl().unspecified());
|
||||
|
||||
ASSERT_FALSE(pool->getDdnsTtlMin().unspecified());
|
||||
EXPECT_EQ(pool->getDdnsTtlMin().get(), 200);
|
||||
|
||||
ASSERT_FALSE(pool->getDdnsTtlMax().unspecified());
|
||||
EXPECT_EQ(pool->getDdnsTtlMax().get(), 500);
|
||||
|
||||
// Second pool only specifies ddns-ttl.
|
||||
pool = pools.at(1);
|
||||
ASSERT_TRUE(pool);
|
||||
|
||||
ASSERT_TRUE(pool->getDdnsSendUpdates().unspecified());
|
||||
ASSERT_TRUE(pool->getDdnsOverrideNoUpdate().unspecified());
|
||||
ASSERT_TRUE(pool->getDdnsOverrideClientUpdate().unspecified());
|
||||
ASSERT_TRUE(pool->getDdnsReplaceClientNameMode().unspecified());
|
||||
ASSERT_TRUE(pool->getDdnsGeneratedPrefix().unspecified());
|
||||
ASSERT_TRUE(pool->getDdnsQualifyingSuffix().unspecified());
|
||||
ASSERT_TRUE(pool->getHostnameCharSet().unspecified());
|
||||
ASSERT_TRUE(pool->getHostnameCharReplacement().unspecified());
|
||||
ASSERT_TRUE(pool->getDdnsUpdateOnRenew().unspecified());
|
||||
ASSERT_TRUE(pool->getDdnsTtlPercent().unspecified());
|
||||
ASSERT_TRUE(pool->getDdnsConflictResolutionMode().unspecified());
|
||||
ASSERT_TRUE(pool->getDdnsTtlMin().unspecified());
|
||||
|
||||
ASSERT_FALSE(pool->getDdnsTtl().unspecified());
|
||||
EXPECT_EQ(pool->getDdnsTtl().get(), 300);
|
||||
|
||||
ASSERT_TRUE(pool->getDdnsTtlMax().unspecified());
|
||||
}
|
||||
|
||||
|
||||
} // namespace
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright (C) 2013-2024 Internet Systems Consortium, Inc. ("ISC")
|
||||
// Copyright (C) 2013-2025 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
|
||||
@ -772,7 +772,7 @@ public:
|
||||
|
||||
}
|
||||
|
||||
/// @brief Verifies that DDNS TTL parameters are used when specified.
|
||||
/// @brief Verifies that DDNS TTL parameters are used when specified.
|
||||
///
|
||||
/// @param valid_flt lease life time
|
||||
/// @param ddns_ttl_percent expected configured value for ddns-ttl-percent
|
||||
@ -786,10 +786,10 @@ public:
|
||||
Optional<uint32_t> ddns_ttl_max = Optional<uint32_t>()) {
|
||||
|
||||
std::string config_header = R"(
|
||||
{
|
||||
{
|
||||
"interfaces-config": { "interfaces": [ "*" ] },
|
||||
"subnet4": [ {
|
||||
"subnet": "10.0.0.0/24",
|
||||
"subnet": "10.0.0.0/24",
|
||||
"interface": "eth1",
|
||||
"id": 1,
|
||||
"pools": [ { "pool": "10.0.0.10-10.0.0.10" } ]
|
||||
@ -859,13 +859,135 @@ public:
|
||||
resp->getYiaddr().toText(),
|
||||
"client1.example.com.", "",
|
||||
time(NULL), lease->valid_lft_, true,
|
||||
CHECK_WITH_DHCID,
|
||||
ddns_ttl_percent,
|
||||
ddns_ttl,
|
||||
ddns_ttl_min,
|
||||
CHECK_WITH_DHCID,
|
||||
ddns_ttl_percent,
|
||||
ddns_ttl,
|
||||
ddns_ttl_min,
|
||||
ddns_ttl_max);
|
||||
}
|
||||
|
||||
/// @brief Verifies that DDNS parameters specified at the pool level
|
||||
/// are used when specified. We don't verify all of them, just enough
|
||||
/// enough to ensure proper scoping of values.
|
||||
void testPoolDdnsParameters() {
|
||||
std::string config = R"(
|
||||
{
|
||||
"interfaces-config": { "interfaces": [ "*" ] },
|
||||
"dhcp-ddns": { "enable-updates": true },
|
||||
"subnet4": [{
|
||||
"subnet": "10.0.0.0/24",
|
||||
"interface": "eth1",
|
||||
"id": 1,
|
||||
"ddns-qualifying-suffix": "subfix.com",
|
||||
"pools": [{
|
||||
"pool": "10.0.0.10-10.0.0.10",
|
||||
"ddns-qualifying-suffix": "poolfix.com",
|
||||
},
|
||||
{
|
||||
"pool": "10.0.0.11-10.0.0.11"
|
||||
},
|
||||
{
|
||||
"pool": "10.0.0.12-10.0.0.12",
|
||||
"ddns-send-updates": false
|
||||
}]
|
||||
}],
|
||||
"valid-lifetime": 400
|
||||
})";
|
||||
|
||||
// Load theconfiguration with D2 enabled.
|
||||
ASSERT_NO_FATAL_FAILURE(configure(config, *srv_));
|
||||
ASSERT_TRUE(CfgMgr::instance().ddnsEnabled());
|
||||
|
||||
// Create a client and get a lease.
|
||||
Dhcp4Client client1(srv_, Dhcp4Client::SELECTING);
|
||||
client1.setIfaceName("eth1");
|
||||
client1.setIfaceIndex(ETH1_INDEX);
|
||||
ASSERT_NO_THROW(client1.includeHostname("client1"));
|
||||
|
||||
// Do the DORA.
|
||||
ASSERT_NO_THROW(client1.doDORA());
|
||||
Pkt4Ptr resp = client1.getContext().response_;
|
||||
ASSERT_TRUE(resp);
|
||||
ASSERT_EQ(DHCPACK, static_cast<int>(resp->getType()));
|
||||
|
||||
// Make sure the lease is in the database and hostname uses the
|
||||
// first pool's qualifying suffix.
|
||||
Lease4Ptr lease = LeaseMgrFactory::instance().getLease4(IOAddress("10.0.0.10"));
|
||||
ASSERT_TRUE(lease);
|
||||
EXPECT_EQ("client1.poolfix.com", lease->hostname_);
|
||||
|
||||
// Verify the hostname option sent in the response.
|
||||
OptionStringPtr hostname;
|
||||
hostname = boost::dynamic_pointer_cast<OptionString>(resp->getOption(DHO_HOST_NAME));
|
||||
ASSERT_TRUE(hostname);
|
||||
EXPECT_EQ("client1.poolfix.com", hostname->getValue());
|
||||
|
||||
// Verify that an NCR was generated correctly.
|
||||
ASSERT_EQ(1, CfgMgr::instance().getD2ClientMgr().getQueueSize());
|
||||
verifyNameChangeRequest(isc::dhcp_ddns::CHG_ADD, true, true,
|
||||
resp->getYiaddr().toText(),
|
||||
"client1.poolfix.com.", "",
|
||||
time(NULL), lease->valid_lft_, true,
|
||||
CHECK_WITH_DHCID);
|
||||
|
||||
// Create another client and get a lease.
|
||||
Dhcp4Client client2(srv_, Dhcp4Client::SELECTING);
|
||||
client2.setIfaceName("eth1");
|
||||
client2.setIfaceIndex(ETH1_INDEX);
|
||||
ASSERT_NO_THROW(client2.includeHostname("client2"));
|
||||
|
||||
// Do the DORA.
|
||||
ASSERT_NO_THROW(client2.doDORA());
|
||||
resp = client2.getContext().response_;
|
||||
ASSERT_TRUE(resp);
|
||||
ASSERT_EQ(DHCPACK, static_cast<int>(resp->getType()));
|
||||
|
||||
// Make sure the lease is in the database and hostname uses the subnet's
|
||||
// qualifying suffix.
|
||||
lease = LeaseMgrFactory::instance().getLease4(IOAddress("10.0.0.11"));
|
||||
ASSERT_TRUE(lease);
|
||||
EXPECT_EQ("client2.subfix.com", lease->hostname_);
|
||||
|
||||
// Verify the hostname option sent in the response.
|
||||
hostname = boost::dynamic_pointer_cast<OptionString>(resp->getOption(DHO_HOST_NAME));
|
||||
ASSERT_TRUE(hostname);
|
||||
EXPECT_EQ("client2.subfix.com", hostname->getValue());
|
||||
|
||||
// Verify that an NCR was generated correctly.
|
||||
ASSERT_EQ(1, CfgMgr::instance().getD2ClientMgr().getQueueSize());
|
||||
verifyNameChangeRequest(isc::dhcp_ddns::CHG_ADD, true, true,
|
||||
resp->getYiaddr().toText(),
|
||||
"client2.subfix.com.", "",
|
||||
time(NULL), lease->valid_lft_, true,
|
||||
CHECK_WITH_DHCID);
|
||||
|
||||
// Create another third client and get a lease.
|
||||
Dhcp4Client client3(srv_, Dhcp4Client::SELECTING);
|
||||
client3.setIfaceName("eth1");
|
||||
client3.setIfaceIndex(ETH1_INDEX);
|
||||
ASSERT_NO_THROW(client3.includeHostname("client3"));
|
||||
|
||||
// Do the DORA.
|
||||
ASSERT_NO_THROW(client3.doDORA());
|
||||
resp = client3.getContext().response_;
|
||||
ASSERT_TRUE(resp);
|
||||
ASSERT_EQ(DHCPACK, static_cast<int>(resp->getType()));
|
||||
|
||||
// Make sure the lease is in the database and hostname uses the subnet suffix.
|
||||
lease = LeaseMgrFactory::instance().getLease4(IOAddress("10.0.0.12"));
|
||||
ASSERT_TRUE(lease);
|
||||
EXPECT_EQ("client3.subfix.com", lease->hostname_);
|
||||
|
||||
// Verify the hostname option sent in the response.
|
||||
hostname = boost::dynamic_pointer_cast<OptionString>(resp->getOption(DHO_HOST_NAME));
|
||||
ASSERT_TRUE(hostname);
|
||||
EXPECT_EQ("client3.subfix.com", hostname->getValue());
|
||||
|
||||
// There should not be an NCR in the queue since the third pool
|
||||
// disables DDNS updates.
|
||||
ASSERT_EQ(0, CfgMgr::instance().getD2ClientMgr().getQueueSize());
|
||||
}
|
||||
|
||||
///@brief Verify that NameChangeRequest holds valid values.
|
||||
///
|
||||
/// Pulls the NCR from the top of the send queue and checks its content
|
||||
@ -927,7 +1049,7 @@ public:
|
||||
// time for equality but rather check that the lease expiration time
|
||||
// is not greater than the current time + lease lifetime.
|
||||
|
||||
uint32_t ttl = calculateDdnsTtl(valid_lft, ddns_ttl_percent,
|
||||
uint32_t ttl = calculateDdnsTtl(valid_lft, ddns_ttl_percent,
|
||||
ddns_ttl, ddns_ttl_min, ddns_ttl_max);
|
||||
|
||||
if (not_strict_expire_check) {
|
||||
@ -3072,7 +3194,7 @@ TEST_F(NameDhcpv4SrvTest, ddnsTtlTest) {
|
||||
testDdnsTtlParameters(2100, // valid lft
|
||||
Optional<double>(), // percent
|
||||
999, // ttl
|
||||
Optional<uint32_t>(), // min
|
||||
Optional<uint32_t>(), // min
|
||||
Optional<uint32_t>()); // max
|
||||
}
|
||||
|
||||
@ -3080,7 +3202,7 @@ TEST_F(NameDhcpv4SrvTest, ddnsTtlTest) {
|
||||
TEST_F(NameDhcpv4SrvTest, ddnsTtlMinTest) {
|
||||
testDdnsTtlParameters(2100, // valid lft
|
||||
Optional<double>(), // percent
|
||||
Optional<uint32_t>(), // ttl
|
||||
Optional<uint32_t>(), // ttl
|
||||
800, // ttl-min
|
||||
Optional<uint32_t>()); // ttl-max
|
||||
}
|
||||
@ -3089,9 +3211,14 @@ TEST_F(NameDhcpv4SrvTest, ddnsTtlMinTest) {
|
||||
TEST_F(NameDhcpv4SrvTest, ddnsTtlMaxTest) {
|
||||
testDdnsTtlParameters(2100, // valid lft
|
||||
Optional<double>(), // percent
|
||||
Optional<uint32_t>(), // ttl
|
||||
Optional<uint32_t>(), // ttl
|
||||
Optional<uint32_t>(), // ttl-min
|
||||
500); // ttl-max
|
||||
500); // ttl-max
|
||||
}
|
||||
|
||||
// Verify pool-level DDNS pararmeters are used.
|
||||
TEST_F(NameDhcpv4SrvTest, poolDdnsParametersTest) {
|
||||
testPoolDdnsParameters();
|
||||
}
|
||||
|
||||
} // end of anonymous namespace
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright (C) 2017-2024 Internet Systems Consortium, Inc. ("ISC")
|
||||
// Copyright (C) 2017-2025 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
|
||||
@ -2724,6 +2724,38 @@ const char* EXTRACTED_CONFIGS[] = {
|
||||
" }\n"
|
||||
" ],\n"
|
||||
" \"valid-lifetime\": 4000\n"
|
||||
" }\n",
|
||||
// CONFIGURATION 87
|
||||
"{\n"
|
||||
" \"subnet4\": [\n"
|
||||
" {\n"
|
||||
" \"id\": 1,\n"
|
||||
" \"pools\": [\n"
|
||||
" {\n"
|
||||
" \"ddns-conflict-resolution-mode\": \"check-with-dhcid\",\n"
|
||||
" \"ddns-generated-prefix\": \"prefix\",\n"
|
||||
" \"ddns-override-client-update\": true,\n"
|
||||
" \"ddns-override-no-update\": true,\n"
|
||||
" \"ddns-qualifying-suffix\": \"suffix\",\n"
|
||||
" \"ddns-replace-client-name\": \"always\",\n"
|
||||
" \"ddns-send-updates\": true,\n"
|
||||
" \"ddns-ttl-max\": 500,\n"
|
||||
" \"ddns-ttl-min\": 200,\n"
|
||||
" \"ddns-ttl-percent\": 0.5,\n"
|
||||
" \"ddns-update-on-renew\": true,\n"
|
||||
" \"hostname-char-replacement\": \"X\",\n"
|
||||
" \"hostname-char-set\": \"[a-z]\",\n"
|
||||
" \"pool\": \"192.0.1.0/24\"\n"
|
||||
" },\n"
|
||||
" {\n"
|
||||
" \"ddns-ttl\": 300,\n"
|
||||
" \"pool\": \"192.0.2.0/24\"\n"
|
||||
" }\n"
|
||||
" ],\n"
|
||||
" \"subnet\": \"192.0.0.0/16\"\n"
|
||||
" }\n"
|
||||
" ],\n"
|
||||
" \"valid-lifetime\": 4000\n"
|
||||
" }\n"
|
||||
};
|
||||
|
||||
@ -14119,6 +14151,134 @@ const char* UNPARSED_CONFIGS[] = {
|
||||
" \"t1-percent\": 0.5,\n"
|
||||
" \"t2-percent\": 0.875,\n"
|
||||
" \"valid-lifetime\": 4000\n"
|
||||
" }\n",
|
||||
// CONFIGURATION 87
|
||||
"{\n"
|
||||
" \"allocator\": \"iterative\",\n"
|
||||
" \"authoritative\": false,\n"
|
||||
" \"boot-file-name\": \"\",\n"
|
||||
" \"calculate-tee-times\": false,\n"
|
||||
" \"ddns-conflict-resolution-mode\": \"check-with-dhcid\",\n"
|
||||
" \"ddns-generated-prefix\": \"myhost\",\n"
|
||||
" \"ddns-override-client-update\": false,\n"
|
||||
" \"ddns-override-no-update\": false,\n"
|
||||
" \"ddns-qualifying-suffix\": \"\",\n"
|
||||
" \"ddns-replace-client-name\": \"never\",\n"
|
||||
" \"ddns-send-updates\": true,\n"
|
||||
" \"ddns-update-on-renew\": false,\n"
|
||||
" \"decline-probation-period\": 86400,\n"
|
||||
" \"dhcp-ddns\": {\n"
|
||||
" \"enable-updates\": false,\n"
|
||||
" \"max-queue-size\": 1024,\n"
|
||||
" \"ncr-format\": \"JSON\",\n"
|
||||
" \"ncr-protocol\": \"UDP\",\n"
|
||||
" \"sender-ip\": \"0.0.0.0\",\n"
|
||||
" \"sender-port\": 0,\n"
|
||||
" \"server-ip\": \"127.0.0.1\",\n"
|
||||
" \"server-port\": 53001\n"
|
||||
" },\n"
|
||||
" \"dhcp-queue-control\": {\n"
|
||||
" \"capacity\": 64,\n"
|
||||
" \"enable-queue\": false,\n"
|
||||
" \"queue-type\": \"kea-ring4\"\n"
|
||||
" },\n"
|
||||
" \"dhcp4o6-port\": 0,\n"
|
||||
" \"early-global-reservations-lookup\": false,\n"
|
||||
" \"echo-client-id\": true,\n"
|
||||
" \"expired-leases-processing\": {\n"
|
||||
" \"flush-reclaimed-timer-wait-time\": 25,\n"
|
||||
" \"hold-reclaimed-time\": 3600,\n"
|
||||
" \"max-reclaim-leases\": 100,\n"
|
||||
" \"max-reclaim-time\": 250,\n"
|
||||
" \"reclaim-timer-wait-time\": 10,\n"
|
||||
" \"unwarned-reclaim-cycles\": 5\n"
|
||||
" },\n"
|
||||
" \"hooks-libraries\": [ ],\n"
|
||||
" \"host-reservation-identifiers\": [ \"hw-address\", \"duid\", \"circuit-id\", \"client-id\" ],\n"
|
||||
" \"hostname-char-replacement\": \"\",\n"
|
||||
" \"hostname-char-set\": \"[^A-Za-z0-9.-]\",\n"
|
||||
" \"interfaces-config\": {\n"
|
||||
" \"interfaces\": [ ],\n"
|
||||
" \"re-detect\": false\n"
|
||||
" },\n"
|
||||
" \"ip-reservations-unique\": true,\n"
|
||||
" \"lease-database\": {\n"
|
||||
" \"type\": \"memfile\"\n"
|
||||
" },\n"
|
||||
" \"match-client-id\": true,\n"
|
||||
" \"multi-threading\": {\n"
|
||||
" \"enable-multi-threading\": true,\n"
|
||||
" \"packet-queue-size\": 64,\n"
|
||||
" \"thread-pool-size\": 0\n"
|
||||
" },\n"
|
||||
" \"next-server\": \"0.0.0.0\",\n"
|
||||
" \"option-data\": [ ],\n"
|
||||
" \"option-def\": [ ],\n"
|
||||
" \"parked-packet-limit\": 256,\n"
|
||||
" \"reservations-global\": false,\n"
|
||||
" \"reservations-in-subnet\": true,\n"
|
||||
" \"reservations-lookup-first\": false,\n"
|
||||
" \"reservations-out-of-pool\": false,\n"
|
||||
" \"sanity-checks\": {\n"
|
||||
" \"extended-info-checks\": \"fix\",\n"
|
||||
" \"lease-checks\": \"warn\"\n"
|
||||
" },\n"
|
||||
" \"server-hostname\": \"\",\n"
|
||||
" \"server-tag\": \"\",\n"
|
||||
" \"shared-networks\": [ ],\n"
|
||||
" \"stash-agent-options\": false,\n"
|
||||
" \"statistic-default-sample-age\": 0,\n"
|
||||
" \"statistic-default-sample-count\": 20,\n"
|
||||
" \"store-extended-info\": false,\n"
|
||||
" \"subnet4\": [\n"
|
||||
" {\n"
|
||||
" \"4o6-interface\": \"\",\n"
|
||||
" \"4o6-interface-id\": \"\",\n"
|
||||
" \"4o6-subnet\": \"\",\n"
|
||||
" \"allocator\": \"iterative\",\n"
|
||||
" \"calculate-tee-times\": false,\n"
|
||||
" \"id\": 1,\n"
|
||||
" \"max-valid-lifetime\": 4000,\n"
|
||||
" \"min-valid-lifetime\": 4000,\n"
|
||||
" \"option-data\": [ ],\n"
|
||||
" \"pools\": [\n"
|
||||
" {\n"
|
||||
" \"ddns-conflict-resolution-mode\": \"check-with-dhcid\",\n"
|
||||
" \"ddns-generated-prefix\": \"prefix\",\n"
|
||||
" \"ddns-override-client-update\": true,\n"
|
||||
" \"ddns-override-no-update\": true,\n"
|
||||
" \"ddns-qualifying-suffix\": \"suffix\",\n"
|
||||
" \"ddns-replace-client-name\": \"always\",\n"
|
||||
" \"ddns-send-updates\": true,\n"
|
||||
" \"ddns-ttl-max\": 500,\n"
|
||||
" \"ddns-ttl-min\": 200,\n"
|
||||
" \"ddns-ttl-percent\": 0.5,\n"
|
||||
" \"ddns-update-on-renew\": true,\n"
|
||||
" \"hostname-char-replacement\": \"X\",\n"
|
||||
" \"hostname-char-set\": \"[a-z]\",\n"
|
||||
" \"option-data\": [ ],\n"
|
||||
" \"pool\": \"192.0.1.0/24\"\n"
|
||||
" },\n"
|
||||
" {\n"
|
||||
" \"ddns-ttl\": 300,\n"
|
||||
" \"option-data\": [ ],\n"
|
||||
" \"pool\": \"192.0.2.0/24\"\n"
|
||||
" }\n"
|
||||
" ],\n"
|
||||
" \"relay\": {\n"
|
||||
" \"ip-addresses\": [ ]\n"
|
||||
" },\n"
|
||||
" \"reservations\": [ ],\n"
|
||||
" \"store-extended-info\": false,\n"
|
||||
" \"subnet\": \"192.0.0.0/16\",\n"
|
||||
" \"t1-percent\": 0.5,\n"
|
||||
" \"t2-percent\": 0.875,\n"
|
||||
" \"valid-lifetime\": 4000\n"
|
||||
" }\n"
|
||||
" ],\n"
|
||||
" \"t1-percent\": 0.5,\n"
|
||||
" \"t2-percent\": 0.875,\n"
|
||||
" \"valid-lifetime\": 4000\n"
|
||||
" }\n"
|
||||
};
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright (C) 2019-2024 Internet Systems Consortium, Inc. ("ISC")
|
||||
// Copyright (C) 2019-2025 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
|
||||
@ -140,108 +140,7 @@ BaseNetworkParser::parseCacheParams(const ConstElementPtr& network_data,
|
||||
void
|
||||
BaseNetworkParser::parseDdnsParams(const data::ConstElementPtr& network_data,
|
||||
NetworkPtr& network) {
|
||||
|
||||
if (network_data->contains("ddns-send-updates")) {
|
||||
network->setDdnsSendUpdates(getBoolean(network_data, "ddns-send-updates"));
|
||||
}
|
||||
|
||||
if (network_data->contains("ddns-override-no-update")) {
|
||||
network->setDdnsOverrideNoUpdate(getBoolean(network_data, "ddns-override-no-update"));
|
||||
}
|
||||
|
||||
if (network_data->contains("ddns-override-client-update")) {
|
||||
network->setDdnsOverrideClientUpdate(getBoolean(network_data, "ddns-override-client-update"));
|
||||
}
|
||||
|
||||
if (network_data->contains("ddns-replace-client-name")) {
|
||||
network->setDdnsReplaceClientNameMode(getAndConvert<D2ClientConfig::ReplaceClientNameMode,
|
||||
D2ClientConfig::stringToReplaceClientNameMode>
|
||||
(network_data, "ddns-replace-client-name",
|
||||
"ReplaceClientName mode"));
|
||||
}
|
||||
|
||||
if (network_data->contains("ddns-generated-prefix")) {
|
||||
network->setDdnsGeneratedPrefix(getString(network_data, "ddns-generated-prefix"));
|
||||
}
|
||||
|
||||
if (network_data->contains("ddns-qualifying-suffix")) {
|
||||
network->setDdnsQualifyingSuffix(getString(network_data, "ddns-qualifying-suffix"));
|
||||
}
|
||||
|
||||
std::string hostname_char_set;
|
||||
if (network_data->contains("hostname-char-set")) {
|
||||
hostname_char_set = getString(network_data, "hostname-char-set");
|
||||
network->setHostnameCharSet(hostname_char_set);
|
||||
}
|
||||
|
||||
std::string hostname_char_replacement;
|
||||
if (network_data->contains("hostname-char-replacement")) {
|
||||
hostname_char_replacement = getString(network_data, "hostname-char-replacement");
|
||||
network->setHostnameCharReplacement(hostname_char_replacement);
|
||||
}
|
||||
|
||||
// We need to validate sanitizer values here so we can detect problems and
|
||||
// cause a configuration. We don't retain the compilation because it's not
|
||||
// something we can inherit.
|
||||
if (!hostname_char_set.empty()) {
|
||||
try {
|
||||
str::StringSanitizerPtr sanitizer(new str::StringSanitizer(hostname_char_set,
|
||||
hostname_char_replacement));
|
||||
} catch (const std::exception& ex) {
|
||||
isc_throw(BadValue, "hostname-char-set '" << hostname_char_set
|
||||
<< "' is not a valid regular expression");
|
||||
}
|
||||
}
|
||||
|
||||
if (network_data->contains("ddns-update-on-renew")) {
|
||||
network->setDdnsUpdateOnRenew(getBoolean(network_data, "ddns-update-on-renew"));
|
||||
}
|
||||
|
||||
bool has_ddns_ttl = false;
|
||||
uint32_t ddns_ttl = 0;
|
||||
if (network_data->contains("ddns-ttl")) {
|
||||
ddns_ttl = getInteger(network_data, "ddns-ttl");
|
||||
network->setDdnsTtl(ddns_ttl);
|
||||
has_ddns_ttl = true;
|
||||
}
|
||||
|
||||
if (network_data->contains("ddns-ttl-percent")) {
|
||||
if (has_ddns_ttl) {
|
||||
isc_throw(BadValue, "cannot specify both ddns-ttl-percent and ddns-ttl");
|
||||
}
|
||||
|
||||
network->setDdnsTtlPercent(getDouble(network_data, "ddns-ttl-percent"));
|
||||
}
|
||||
|
||||
uint32_t ddns_ttl_min = 0;
|
||||
if (network_data->contains("ddns-ttl-min")) {
|
||||
if (has_ddns_ttl) {
|
||||
isc_throw(BadValue, "cannot specify both ddns-ttl-min and ddns-ttl");
|
||||
}
|
||||
|
||||
ddns_ttl_min = getInteger(network_data, "ddns-ttl-min");
|
||||
network->setDdnsTtlMin(ddns_ttl_min);
|
||||
}
|
||||
|
||||
if (network_data->contains("ddns-ttl-max")) {
|
||||
if (has_ddns_ttl) {
|
||||
isc_throw(BadValue, "cannot specify both ddns-ttl-max and ddns-ttl");
|
||||
}
|
||||
|
||||
uint32_t ddns_ttl_max = getInteger(network_data, "ddns-ttl-max");
|
||||
if (ddns_ttl_max < ddns_ttl_min) {
|
||||
isc_throw(BadValue, "ddns-ttl-max: " << ddns_ttl_max
|
||||
<< " must be greater than ddns-ttl-min: " << ddns_ttl_min);
|
||||
}
|
||||
|
||||
network->setDdnsTtlMax(ddns_ttl_max);
|
||||
}
|
||||
|
||||
// For backward compatibility, ddns-conflict-resolution-mode is optional.
|
||||
if (network_data->contains("ddns-conflict-resolution-mode")) {
|
||||
network->setDdnsConflictResolutionMode(getString(network_data,
|
||||
"ddns-conflict-resolution-mode"));
|
||||
}
|
||||
parseDdnsParameters(network_data, network);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright (C) 2019-2024 Internet Systems Consortium, Inc. ("ISC")
|
||||
// Copyright (C) 2019-2025 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
|
||||
@ -146,6 +146,136 @@ public:
|
||||
/// @throw DhcpConfigError if both entries are present.
|
||||
static void getClientClassesElem(data::ConstElementPtr params,
|
||||
ClassAdderFunc adder_func);
|
||||
|
||||
/// @brief Parses parameters pertaining to DDNS behavior.
|
||||
///
|
||||
/// The parsed parameters are:
|
||||
/// - ddns-send-updates
|
||||
/// - ddns-override-no-update
|
||||
/// - ddns-override-client-update
|
||||
/// - ddns-replace-client-name
|
||||
/// - ddns-generated-prefix
|
||||
/// - ddns-qualifying-suffix
|
||||
/// - ddns-use-conflict-resolution (retained for backward compatibility)
|
||||
/// - ddns-update-on-renew
|
||||
/// - ddns-ttl-percent
|
||||
/// - ddns-conflict-resolution-mode
|
||||
///
|
||||
/// Owner types are expected to have public setters for each of these
|
||||
/// paramters.
|
||||
///
|
||||
/// @tparam DdnsOwnerPtr pointer to the class type that owns the DDNS parameters
|
||||
/// @param config configuration element holding the DDNS paramters to parse.
|
||||
/// @param owner Pointer to the DDNS parameter owner object into which parsed values
|
||||
/// should be stored.
|
||||
/// @throw BadValue for various invalid values.
|
||||
template<typename DdnsOwnerTypePtr>
|
||||
void parseDdnsParameters(const data::ConstElementPtr& config,
|
||||
DdnsOwnerTypePtr owner) {
|
||||
|
||||
if (config->contains("ddns-send-updates")) {
|
||||
owner->setDdnsSendUpdates(getBoolean(config, "ddns-send-updates"));
|
||||
}
|
||||
|
||||
if (config->contains("ddns-override-no-update")) {
|
||||
owner->setDdnsOverrideNoUpdate(getBoolean(config, "ddns-override-no-update"));
|
||||
}
|
||||
|
||||
if (config->contains("ddns-override-client-update")) {
|
||||
owner->setDdnsOverrideClientUpdate(getBoolean(config, "ddns-override-client-update"));
|
||||
}
|
||||
|
||||
if (config->contains("ddns-replace-client-name")) {
|
||||
owner->setDdnsReplaceClientNameMode(getAndConvert<D2ClientConfig::ReplaceClientNameMode,
|
||||
D2ClientConfig::stringToReplaceClientNameMode>
|
||||
(config, "ddns-replace-client-name",
|
||||
"ReplaceClientName mode"));
|
||||
}
|
||||
|
||||
if (config->contains("ddns-generated-prefix")) {
|
||||
owner->setDdnsGeneratedPrefix(getString(config, "ddns-generated-prefix"));
|
||||
}
|
||||
|
||||
if (config->contains("ddns-qualifying-suffix")) {
|
||||
owner->setDdnsQualifyingSuffix(getString(config, "ddns-qualifying-suffix"));
|
||||
}
|
||||
|
||||
std::string hostname_char_set;
|
||||
if (config->contains("hostname-char-set")) {
|
||||
hostname_char_set = getString(config, "hostname-char-set");
|
||||
owner->setHostnameCharSet(hostname_char_set);
|
||||
}
|
||||
|
||||
std::string hostname_char_replacement;
|
||||
if (config->contains("hostname-char-replacement")) {
|
||||
hostname_char_replacement = getString(config, "hostname-char-replacement");
|
||||
owner->setHostnameCharReplacement(hostname_char_replacement);
|
||||
}
|
||||
|
||||
// We need to validate sanitizer values here so we can detect problems and
|
||||
// cause a configuration. We don't retain the compilation because it's not
|
||||
// something we can inherit.
|
||||
if (!hostname_char_set.empty()) {
|
||||
try {
|
||||
util::str::StringSanitizerPtr sanitizer(
|
||||
new util::str::StringSanitizer(hostname_char_set,
|
||||
hostname_char_replacement));
|
||||
} catch (const std::exception& ex) {
|
||||
isc_throw(BadValue, "hostname-char-set '" << hostname_char_set
|
||||
<< "' is not a valid regular expression");
|
||||
}
|
||||
}
|
||||
|
||||
if (config->contains("ddns-update-on-renew")) {
|
||||
owner->setDdnsUpdateOnRenew(getBoolean(config, "ddns-update-on-renew"));
|
||||
}
|
||||
|
||||
bool has_ddns_ttl = false;
|
||||
uint32_t ddns_ttl = 0;
|
||||
if (config->contains("ddns-ttl")) {
|
||||
ddns_ttl = getInteger(config, "ddns-ttl");
|
||||
owner->setDdnsTtl(ddns_ttl);
|
||||
has_ddns_ttl = true;
|
||||
}
|
||||
|
||||
if (config->contains("ddns-ttl-percent")) {
|
||||
if (has_ddns_ttl) {
|
||||
isc_throw(BadValue, "cannot specify both ddns-ttl-percent and ddns-ttl");
|
||||
}
|
||||
|
||||
owner->setDdnsTtlPercent(getDouble(config, "ddns-ttl-percent"));
|
||||
}
|
||||
|
||||
uint32_t ddns_ttl_min = 0;
|
||||
if (config->contains("ddns-ttl-min")) {
|
||||
if (has_ddns_ttl) {
|
||||
isc_throw(BadValue, "cannot specify both ddns-ttl-min and ddns-ttl");
|
||||
}
|
||||
|
||||
ddns_ttl_min = getInteger(config, "ddns-ttl-min");
|
||||
owner->setDdnsTtlMin(ddns_ttl_min);
|
||||
}
|
||||
|
||||
if (config->contains("ddns-ttl-max")) {
|
||||
if (has_ddns_ttl) {
|
||||
isc_throw(BadValue, "cannot specify both ddns-ttl-max and ddns-ttl");
|
||||
}
|
||||
|
||||
uint32_t ddns_ttl_max = getInteger(config, "ddns-ttl-max");
|
||||
if (ddns_ttl_max < ddns_ttl_min) {
|
||||
isc_throw(BadValue, "ddns-ttl-max: " << ddns_ttl_max
|
||||
<< " must be greater than ddns-ttl-min: " << ddns_ttl_min);
|
||||
}
|
||||
|
||||
owner->setDdnsTtlMax(ddns_ttl_max);
|
||||
}
|
||||
|
||||
// For backward compatibility, ddns-conflict-resolution-mode is optional.
|
||||
if (config->contains("ddns-conflict-resolution-mode")) {
|
||||
owner->setDdnsConflictResolutionMode(getString(config,
|
||||
"ddns-conflict-resolution-mode"));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
} // end of namespace isc::dhcp
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright (C) 2013-2024 Internet Systems Consortium, Inc. ("ISC")
|
||||
// Copyright (C) 2013-2025 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
|
||||
@ -537,6 +537,10 @@ PoolParser::parse(PoolStoragePtr pools,
|
||||
BaseNetworkParser::getAdditionalClassesElem(pool_structure,
|
||||
std::bind(&Pool::addAdditionalClass,
|
||||
pool, ph::_1));
|
||||
|
||||
// Parse DDNS behavioral parameters.
|
||||
BaseNetworkParser parser;
|
||||
parser.parseDdnsParameters(pool_structure, pool);
|
||||
}
|
||||
|
||||
boost::shared_ptr<OptionDataListParser>
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright (C) 2016-2024 Internet Systems Consortium, Inc. ("ISC")
|
||||
// Copyright (C) 2016-2025 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
|
||||
@ -332,16 +332,30 @@ const ParamsList SimpleParser4::INHERIT_TO_SUBNET4 = {
|
||||
/// list and map types for entries.
|
||||
/// Order follows pool_param rules in bison grammar.
|
||||
const SimpleKeywords SimpleParser4::POOL4_PARAMETERS = {
|
||||
{ "pool", Element::string },
|
||||
{ "pool-id", Element::integer },
|
||||
{ "option-data", Element::list },
|
||||
{ "client-class", Element::string },
|
||||
{ "client-classes", Element::list },
|
||||
{ "require-client-classes", Element::list },
|
||||
{ "evaluate-additional-classes", Element::list },
|
||||
{ "user-context", Element::map },
|
||||
{ "comment", Element::string },
|
||||
{ "metadata", Element::map }
|
||||
{ "pool", Element::string },
|
||||
{ "pool-id", Element::integer },
|
||||
{ "option-data", Element::list },
|
||||
{ "client-class", Element::string },
|
||||
{ "client-classes", Element::list },
|
||||
{ "require-client-classes", Element::list },
|
||||
{ "evaluate-additional-classes", Element::list },
|
||||
{ "user-context", Element::map },
|
||||
{ "comment", Element::string },
|
||||
{ "metadata", Element::map },
|
||||
{ "ddns-send-updates", Element::boolean },
|
||||
{ "ddns-override-no-update", Element::boolean },
|
||||
{ "ddns-override-client-update", Element::boolean },
|
||||
{ "ddns-replace-client-name", Element::string },
|
||||
{ "ddns-generated-prefix", Element::string },
|
||||
{ "ddns-qualifying-suffix", Element::string },
|
||||
{ "hostname-char-set", Element::string },
|
||||
{ "hostname-char-replacement", Element::string },
|
||||
{ "ddns-update-on-renew", Element::boolean },
|
||||
{ "ddns-ttl-percent", Element::real },
|
||||
{ "ddns-conflict-resolution-mode", Element::string },
|
||||
{ "ddns-ttl", Element::integer },
|
||||
{ "ddns-ttl-min", Element::integer },
|
||||
{ "ddns-ttl-max", Element::integer }
|
||||
};
|
||||
|
||||
/// @brief This table defines all shared network parameters for DHCPv4.
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright (C) 2012-2024 Internet Systems Consortium, Inc. ("ISC")
|
||||
// Copyright (C) 2012-2025 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
|
||||
@ -4337,4 +4337,110 @@ TEST_F(DhcpParserTest, invalidDdnsTtlParmatersSubnet6) {
|
||||
invalidDdnsTtlParmatersSubnet<Subnet6ConfigParser>(AF_INET6);
|
||||
}
|
||||
|
||||
// Verifies valid DDNS parameters in v4 pools. As this uses the
|
||||
// same parser as Network derivatives we skip retesting all the
|
||||
// invalid permuations. This test ensures all supported
|
||||
// parameters can be set.
|
||||
TEST_F(DhcpParserTest, validDdnsParmatersPool4) {
|
||||
|
||||
std::string config =
|
||||
R"^([{
|
||||
"pool": "192.0.1.0/24",
|
||||
"ddns-send-updates": true,
|
||||
"ddns-override-no-update": true,
|
||||
"ddns-override-client-update": true,
|
||||
"ddns-replace-client-name": "always",
|
||||
"ddns-generated-prefix": "prefix",
|
||||
"ddns-qualifying-suffix": "suffix",
|
||||
"hostname-char-set": "[a-z]",
|
||||
"hostname-char-replacement": "X",
|
||||
"ddns-update-on-renew": true,
|
||||
"ddns-ttl-percent": 0.5,
|
||||
"ddns-conflict-resolution-mode": "check-with-dhcid",
|
||||
"ddns-ttl-min": 200,
|
||||
"ddns-ttl-max": 500
|
||||
},
|
||||
{
|
||||
"pool": "192.0.2.0/24",
|
||||
"ddns-ttl": 300
|
||||
}])^";
|
||||
|
||||
ElementPtr config_element = Element::fromJSON(config);
|
||||
|
||||
PoolStoragePtr pools(new PoolStorage());
|
||||
Pools4ListParser parser;
|
||||
ASSERT_NO_THROW_LOG(parser.parse(pools, config_element));
|
||||
|
||||
// Should have two pools.
|
||||
ASSERT_EQ(pools->size(), 2);
|
||||
|
||||
// First pool specifies all but ddns-ttl.
|
||||
PoolPtr pool = (*pools)[0];
|
||||
ASSERT_TRUE(pool);
|
||||
|
||||
ASSERT_FALSE(pool->getDdnsSendUpdates().unspecified());
|
||||
EXPECT_TRUE(pool->getDdnsSendUpdates().get());
|
||||
|
||||
ASSERT_FALSE(pool->getDdnsOverrideNoUpdate().unspecified());
|
||||
EXPECT_TRUE(pool->getDdnsOverrideNoUpdate().get());
|
||||
|
||||
ASSERT_FALSE(pool->getDdnsOverrideClientUpdate().unspecified());
|
||||
EXPECT_TRUE(pool->getDdnsOverrideClientUpdate().get());
|
||||
|
||||
ASSERT_FALSE(pool->getDdnsReplaceClientNameMode().unspecified());
|
||||
EXPECT_EQ(pool->getDdnsReplaceClientNameMode().get(),
|
||||
D2ClientConfig::RCM_ALWAYS);
|
||||
|
||||
ASSERT_FALSE(pool->getDdnsGeneratedPrefix().unspecified());
|
||||
EXPECT_EQ(pool->getDdnsGeneratedPrefix().get(), "prefix");
|
||||
|
||||
ASSERT_FALSE(pool->getDdnsQualifyingSuffix().unspecified());
|
||||
EXPECT_EQ(pool->getDdnsQualifyingSuffix().get(), "suffix");
|
||||
|
||||
ASSERT_FALSE(pool->getHostnameCharSet().unspecified());
|
||||
EXPECT_EQ(pool->getHostnameCharSet().get(), "[a-z]");
|
||||
|
||||
ASSERT_FALSE(pool->getHostnameCharReplacement().unspecified());
|
||||
EXPECT_EQ(pool->getHostnameCharReplacement().get(), "X");
|
||||
|
||||
ASSERT_FALSE(pool->getDdnsUpdateOnRenew().unspecified());
|
||||
EXPECT_TRUE(pool->getDdnsUpdateOnRenew().get());
|
||||
|
||||
ASSERT_FALSE(pool->getDdnsTtlPercent().unspecified());
|
||||
EXPECT_EQ(pool->getDdnsTtlPercent().get(), 0.5);
|
||||
|
||||
ASSERT_FALSE(pool->getDdnsConflictResolutionMode().unspecified());
|
||||
EXPECT_EQ(pool->getDdnsConflictResolutionMode().get(), "check-with-dhcid");
|
||||
|
||||
ASSERT_TRUE(pool->getDdnsTtl().unspecified());
|
||||
|
||||
ASSERT_FALSE(pool->getDdnsTtlMin().unspecified());
|
||||
EXPECT_EQ(pool->getDdnsTtlMin().get(), 200);
|
||||
|
||||
ASSERT_FALSE(pool->getDdnsTtlMax().unspecified());
|
||||
EXPECT_EQ(pool->getDdnsTtlMax().get(), 500);
|
||||
|
||||
// Second pool only specifies ddns-ttl.
|
||||
pool = (*pools)[1];
|
||||
ASSERT_TRUE(pool);
|
||||
|
||||
ASSERT_TRUE(pool->getDdnsSendUpdates().unspecified());
|
||||
ASSERT_TRUE(pool->getDdnsOverrideNoUpdate().unspecified());
|
||||
ASSERT_TRUE(pool->getDdnsOverrideClientUpdate().unspecified());
|
||||
ASSERT_TRUE(pool->getDdnsReplaceClientNameMode().unspecified());
|
||||
ASSERT_TRUE(pool->getDdnsGeneratedPrefix().unspecified());
|
||||
ASSERT_TRUE(pool->getDdnsQualifyingSuffix().unspecified());
|
||||
ASSERT_TRUE(pool->getHostnameCharSet().unspecified());
|
||||
ASSERT_TRUE(pool->getHostnameCharReplacement().unspecified());
|
||||
ASSERT_TRUE(pool->getDdnsUpdateOnRenew().unspecified());
|
||||
ASSERT_TRUE(pool->getDdnsTtlPercent().unspecified());
|
||||
ASSERT_TRUE(pool->getDdnsConflictResolutionMode().unspecified());
|
||||
ASSERT_TRUE(pool->getDdnsTtlMin().unspecified());
|
||||
|
||||
ASSERT_FALSE(pool->getDdnsTtl().unspecified());
|
||||
EXPECT_EQ(pool->getDdnsTtl().get(), 300);
|
||||
|
||||
ASSERT_TRUE(pool->getDdnsTtlMax().unspecified());
|
||||
}
|
||||
|
||||
} // Anonymous namespace
|
||||
|
Loading…
x
Reference in New Issue
Block a user