From: Francis Dupont Date: Tue, 11 Jun 2019 00:10:18 +0000 (+0200) Subject: [540-recommend-moving-hostname-char-set-and-hostname-char-replacement-out-of-dhcp... X-Git-Tag: Kea-1.6.0-beta2~298 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=772569640aa779ba2e41212b8f492bff8b2f2165;p=thirdparty%2Fkea.git [540-recommend-moving-hostname-char-set-and-hostname-char-replacement-out-of-dhcp-ddns] Checkpoint between DHCPv6 regen --- diff --git a/src/bin/dhcp4/ctrl_dhcp4_srv.cc b/src/bin/dhcp4/ctrl_dhcp4_srv.cc index 9081571139..0bda963150 100644 --- a/src/bin/dhcp4/ctrl_dhcp4_srv.cc +++ b/src/bin/dhcp4/ctrl_dhcp4_srv.cc @@ -373,6 +373,12 @@ ControlledDhcpv4Srv::commandConfigSetHandler(const string&, if (rcode == 0) { CfgMgr::instance().getStagingCfg()->applyLoggingCfg(); + // Update the fetch globals callback. + auto cfg = CfgMgr::instance().getStagingCfg()->getD2ClientConfig(); + cfg->setFetchGlobalsFn([]() -> ConstElementPtr { + return (CfgMgr::instance().getCurrentCfg()->getConfiguredGlobals()); + }); + // Use new configuration. CfgMgr::instance().commit(); } else { diff --git a/src/bin/dhcp4/json_config_parser.cc b/src/bin/dhcp4/json_config_parser.cc index 227e2a2274..885c145cc8 100644 --- a/src/bin/dhcp4/json_config_parser.cc +++ b/src/bin/dhcp4/json_config_parser.cc @@ -368,6 +368,9 @@ configureDhcp4Server(Dhcpv4Srv& server, isc::data::ConstElementPtr config_set, // early. Dhcp4ConfigParser global_parser; + // D2 client configuration. + D2ClientConfigPtr d2_client_cfg; + // Make parsers grouping. const std::map& values_map = mutable_cfg->mapValue(); @@ -445,8 +448,7 @@ configureDhcp4Server(Dhcpv4Srv& server, isc::data::ConstElementPtr config_set, // Apply defaults D2ClientConfigParser::setAllDefaults(config_pair.second); D2ClientConfigParser parser; - D2ClientConfigPtr cfg = parser.parse(config_pair.second); - srv_cfg->setD2ClientConfig(cfg); + d2_client_cfg = parser.parse(config_pair.second); continue; } @@ -557,7 +559,9 @@ configureDhcp4Server(Dhcpv4Srv& server, isc::data::ConstElementPtr config_set, (config_pair.first == "calculate-tee-times") || (config_pair.first == "t1-percent") || (config_pair.first == "t2-percent") || - (config_pair.first == "loggers")) { + (config_pair.first == "loggers") || + (config_pair.first == "hostname-char-set") || + (config_pair.first == "hostname-char-replacement")) { CfgMgr::instance().getStagingCfg()->addConfiguredGlobal(config_pair.first, config_pair.second); @@ -584,6 +588,16 @@ configureDhcp4Server(Dhcpv4Srv& server, isc::data::ConstElementPtr config_set, // defined as part of shared networks. global_parser.sanityChecks(srv_cfg, mutable_cfg); + // Validate D2 client confuguration. + if (!d2_client_cfg) { + d2_client_cfg.reset(new D2ClientConfig()); + d2_client_cfg->setFetchGlobalsFn([]() -> ConstElementPtr { + return (CfgMgr::instance().getStagingCfg()->getConfiguredGlobals()); + }); + } + d2_client_cfg->validateContents(); + srv_cfg->setD2ClientConfig(d2_client_cfg); + } catch (const isc::Exception& ex) { LOG_ERROR(dhcp4_logger, DHCP4_PARSER_FAIL) .arg(config_pair.first).arg(ex.what()); diff --git a/src/bin/dhcp4/tests/config_parser_unittest.cc b/src/bin/dhcp4/tests/config_parser_unittest.cc index d492e43fb0..2ee1bca774 100644 --- a/src/bin/dhcp4/tests/config_parser_unittest.cc +++ b/src/bin/dhcp4/tests/config_parser_unittest.cc @@ -4170,6 +4170,165 @@ TEST_F(Dhcp4ParserTest, d2ClientConfig) { EXPECT_EQ(D2ClientConfig::RCM_WHEN_PRESENT, d2_client_config->getReplaceClientNameMode()); EXPECT_EQ("test.prefix", d2_client_config->getGeneratedPrefix()); EXPECT_EQ("test.suffix.", d2_client_config->getQualifyingSuffix()); + EXPECT_FALSE(d2_client_config->getHostnameCharSet().unspecified()); + EXPECT_EQ("[^A-Za-z0-9_-]", d2_client_config->getHostnameCharSet().get()); + EXPECT_FALSE(d2_client_config->getHostnameCharReplacement().unspecified()); + EXPECT_EQ("x", d2_client_config->getHostnameCharReplacement().get()); + EXPECT_TRUE(d2_client_config->getHostnameSanitizer()); +} + +// This test checks the ability of the server to parse a configuration +// containing a full, valid dhcp-ddns (D2ClientConfig) entry with +// hostname-char-* at the global scope. +TEST_F(Dhcp4ParserTest, d2ClientConfigGlobal) { + ConstElementPtr status; + + // Verify that the D2 configuration can be fetched and is set to disabled. + D2ClientConfigPtr d2_client_config = CfgMgr::instance().getD2ClientConfig(); + EXPECT_FALSE(d2_client_config->getEnableUpdates()); + + // Verify that the convenience method agrees. + ASSERT_FALSE(CfgMgr::instance().ddnsEnabled()); + + string config_str = "{ " + genIfaceConfig() + "," + + "\"rebind-timer\": 2000, " + "\"renew-timer\": 1000, " + "\"subnet4\": [ { " + " \"pools\": [ { \"pool\": \"192.0.2.1 - 192.0.2.100\" } ]," + " \"subnet\": \"192.0.2.0/24\" } ]," + " \"dhcp-ddns\" : {" + " \"enable-updates\" : true, " + " \"server-ip\" : \"192.168.2.1\", " + " \"server-port\" : 777, " + " \"sender-ip\" : \"192.168.2.2\", " + " \"sender-port\" : 778, " + " \"max-queue-size\" : 2048, " + " \"ncr-protocol\" : \"UDP\", " + " \"ncr-format\" : \"JSON\", " + " \"override-no-update\" : true, " + " \"override-client-update\" : true, " + " \"replace-client-name\" : \"when-present\", " + " \"generated-prefix\" : \"test.prefix\", " + " \"qualifying-suffix\" : \"test.suffix.\" }," + "\"hostname-char-set\" : \"[^A-Za-z0-9_-]\", " + "\"hostname-char-replacement\" : \"x\", " + "\"valid-lifetime\": 4000 }"; + + // Convert the JSON string to configuration elements. + ConstElementPtr config; + ASSERT_NO_THROW(config = parseDHCP4(config_str, true)); + extractConfig(config_str); + + // Pass the configuration in for parsing. + EXPECT_NO_THROW(status = configureDhcp4Server(*srv_, config)); + + // check if returned status is OK + checkResult(status, 0); + + // Verify that DHCP-DDNS updating is enabled. + EXPECT_TRUE(CfgMgr::instance().ddnsEnabled()); + + // Verify that the D2 configuration can be retrieved. + d2_client_config = CfgMgr::instance().getD2ClientConfig(); + ASSERT_TRUE(d2_client_config); + + // Verify that the configuration values are correct. + EXPECT_TRUE(d2_client_config->getEnableUpdates()); + EXPECT_EQ("192.168.2.1", d2_client_config->getServerIp().toText()); + EXPECT_EQ(777, d2_client_config->getServerPort()); + EXPECT_EQ("192.168.2.2", d2_client_config->getSenderIp().toText()); + EXPECT_EQ(778, d2_client_config->getSenderPort()); + EXPECT_EQ(2048, d2_client_config->getMaxQueueSize()); + EXPECT_EQ(dhcp_ddns::NCR_UDP, d2_client_config->getNcrProtocol()); + EXPECT_EQ(dhcp_ddns::FMT_JSON, d2_client_config->getNcrFormat()); + EXPECT_TRUE(d2_client_config->getOverrideNoUpdate()); + EXPECT_TRUE(d2_client_config->getOverrideClientUpdate()); + EXPECT_EQ(D2ClientConfig::RCM_WHEN_PRESENT, d2_client_config->getReplaceClientNameMode()); + EXPECT_EQ("test.prefix", d2_client_config->getGeneratedPrefix()); + EXPECT_EQ("test.suffix.", d2_client_config->getQualifyingSuffix()); + EXPECT_FALSE(d2_client_config->getHostnameCharSet().unspecified()); + EXPECT_EQ("[^A-Za-z0-9_-]", d2_client_config->getHostnameCharSet().get()); + EXPECT_FALSE(d2_client_config->getHostnameCharReplacement().unspecified()); + EXPECT_EQ("x", d2_client_config->getHostnameCharReplacement().get()); + EXPECT_TRUE(d2_client_config->getHostnameSanitizer()); +} + +// This test checks the ability of the server to parse a configuration +// containing a full, valid dhcp-ddns (D2ClientConfig) entry with +// hostname-char-* at the local and global scopes (local has the priority). +TEST_F(Dhcp4ParserTest, d2ClientConfigBoth) { + ConstElementPtr status; + + // Verify that the D2 configuration can be fetched and is set to disabled. + D2ClientConfigPtr d2_client_config = CfgMgr::instance().getD2ClientConfig(); + EXPECT_FALSE(d2_client_config->getEnableUpdates()); + + // Verify that the convenience method agrees. + ASSERT_FALSE(CfgMgr::instance().ddnsEnabled()); + + string config_str = "{ " + genIfaceConfig() + "," + + "\"rebind-timer\": 2000, " + "\"renew-timer\": 1000, " + "\"subnet4\": [ { " + " \"pools\": [ { \"pool\": \"192.0.2.1 - 192.0.2.100\" } ]," + " \"subnet\": \"192.0.2.0/24\" } ]," + " \"dhcp-ddns\" : {" + " \"enable-updates\" : true, " + " \"server-ip\" : \"192.168.2.1\", " + " \"server-port\" : 777, " + " \"sender-ip\" : \"192.168.2.2\", " + " \"sender-port\" : 778, " + " \"max-queue-size\" : 2048, " + " \"ncr-protocol\" : \"UDP\", " + " \"ncr-format\" : \"JSON\", " + " \"override-no-update\" : true, " + " \"override-client-update\" : true, " + " \"replace-client-name\" : \"when-present\", " + " \"generated-prefix\" : \"test.prefix\", " + " \"qualifying-suffix\" : \"test.suffix.\", " + " \"hostname-char-set\" : \"[^A-Za-z0-9_-]\", " + " \"hostname-char-replacement\" : \"x\" }, " + "\"hostname-char-set\" : \"[^A-Z]\", " + "\"hostname-char-replacement\" : \"z\", " + "\"valid-lifetime\": 4000 }"; + + // Convert the JSON string to configuration elements. + ConstElementPtr config; + ASSERT_NO_THROW(config = parseDHCP4(config_str, true)); + extractConfig(config_str); + + // Pass the configuration in for parsing. + EXPECT_NO_THROW(status = configureDhcp4Server(*srv_, config)); + + // check if returned status is OK + checkResult(status, 0); + + // Verify that DHCP-DDNS updating is enabled. + EXPECT_TRUE(CfgMgr::instance().ddnsEnabled()); + + // Verify that the D2 configuration can be retrieved. + d2_client_config = CfgMgr::instance().getD2ClientConfig(); + ASSERT_TRUE(d2_client_config); + + // Verify that the configuration values are correct. + EXPECT_TRUE(d2_client_config->getEnableUpdates()); + EXPECT_EQ("192.168.2.1", d2_client_config->getServerIp().toText()); + EXPECT_EQ(777, d2_client_config->getServerPort()); + EXPECT_EQ("192.168.2.2", d2_client_config->getSenderIp().toText()); + EXPECT_EQ(778, d2_client_config->getSenderPort()); + EXPECT_EQ(2048, d2_client_config->getMaxQueueSize()); + EXPECT_EQ(dhcp_ddns::NCR_UDP, d2_client_config->getNcrProtocol()); + EXPECT_EQ(dhcp_ddns::FMT_JSON, d2_client_config->getNcrFormat()); + EXPECT_TRUE(d2_client_config->getOverrideNoUpdate()); + EXPECT_TRUE(d2_client_config->getOverrideClientUpdate()); + EXPECT_EQ(D2ClientConfig::RCM_WHEN_PRESENT, d2_client_config->getReplaceClientNameMode()); + EXPECT_EQ("test.prefix", d2_client_config->getGeneratedPrefix()); + EXPECT_EQ("test.suffix.", d2_client_config->getQualifyingSuffix()); + EXPECT_FALSE(d2_client_config->getHostnameCharSet().unspecified()); + EXPECT_EQ("[^A-Za-z0-9_-]", d2_client_config->getHostnameCharSet().get()); + EXPECT_FALSE(d2_client_config->getHostnameCharReplacement().unspecified()); + EXPECT_EQ("x", d2_client_config->getHostnameCharReplacement().get()); + EXPECT_TRUE(d2_client_config->getHostnameSanitizer()); } // This test checks the ability of the server to handle a configuration diff --git a/src/bin/dhcp4/tests/dhcp4_test_utils.cc b/src/bin/dhcp4/tests/dhcp4_test_utils.cc index e9147dfc2b..c223984eab 100644 --- a/src/bin/dhcp4/tests/dhcp4_test_utils.cc +++ b/src/bin/dhcp4/tests/dhcp4_test_utils.cc @@ -635,6 +635,10 @@ Dhcpv4SrvTest::configure(const std::string& config, NakedDhcpv4Srv& srv, } ); if (commit) { + auto cfg = CfgMgr::instance().getStagingCfg()->getD2ClientConfig(); + cfg->setFetchGlobalsFn([]() -> ConstElementPtr { + return (CfgMgr::instance().getCurrentCfg()->getConfiguredGlobals()); + }); CfgMgr::instance().commit(); } } @@ -680,6 +684,10 @@ Dhcpv4SrvTest::configureWithStatus(const std::string& config, NakedDhcpv4Srv& sr cfg_db->createManagers(); } ); if (commit) { + auto cfg = CfgMgr::instance().getStagingCfg()->getD2ClientConfig(); + cfg->setFetchGlobalsFn([]() -> ConstElementPtr { + return (CfgMgr::instance().getCurrentCfg()->getConfiguredGlobals()); + }); CfgMgr::instance().commit(); } } diff --git a/src/bin/dhcp4/tests/fqdn_unittest.cc b/src/bin/dhcp4/tests/fqdn_unittest.cc index 6f3ae43530..b208430a34 100644 --- a/src/bin/dhcp4/tests/fqdn_unittest.cc +++ b/src/bin/dhcp4/tests/fqdn_unittest.cc @@ -197,6 +197,31 @@ const char* CONFIGS[] = { "\"qualifying-suffix\": \"example.org\"" "}" "}", + // 7 + // Configuration which enables DNS updates and hostname sanitization. + // the second at the global scope. + "{ \"interfaces-config\": {" + " \"interfaces\": [ \"*\" ]" + "}," + "\"valid-lifetime\": 3000," + "\"subnet4\": [ { " + " \"subnet\": \"10.0.0.0/24\", " + " \"id\": 1," + " \"pools\": [ { \"pool\": \"10.0.0.10-10.0.0.100\" } ]," + " \"option-data\": [ {" + " \"name\": \"routers\"," + " \"data\": \"10.0.0.200,10.0.0.201\"" + " } ]," + " \"reservations\": [" + " {" + " \"hw-address\": \"aa:bb:cc:dd:ee:ff\"," + " \"hostname\": \"unique-xxx-host.example.org\"" + " }" + " ]" + " }]," + "\"hostname-char-set\" : \"[^A-Za-z0-9.-]\"," + "\"hostname-char-replacement\" : \"x\"" + "}" }; class NameDhcpv4SrvTest : public Dhcpv4SrvTest { @@ -503,11 +528,11 @@ public: " \"pools\": [ { \"pool\": \"10.0.0.10-10.0.0.10\" } ]" " }]," "\"dhcp-ddns\": {" - "\"enable-updates\": true," - "\"qualifying-suffix\": \"fake-suffix.isc.org.\"," - "\"hostname-char-set\": \"[^A-Za-z0-9.-]\"," - "\"hostname-char-replacement\": \"x\"," - "\"replace-client-name\": \"%s\"" + " \"enable-updates\": true," + " \"qualifying-suffix\": \"fake-suffix.isc.org.\"," + " \"hostname-char-set\": \"[^A-Za-z0-9.-]\"," + " \"hostname-char-replacement\": \"x\"," + " \"replace-client-name\": \"%s\"" "}}"; // Create the configuration and configure the server @@ -1798,6 +1823,68 @@ TEST_F(NameDhcpv4SrvTest, sanitizeHost) { } } +// Verifies that setting global hostname-char-set sanitizes Hostname option +// values received from clients. +TEST_F(NameDhcpv4SrvTest, sanitizeHostGlobal) { + Dhcp4Client client(Dhcp4Client::SELECTING); + + // Configure DHCP server. + configure(CONFIGS[7], *client.getServer()); + + // Make sure that DDNS is not enabled. + ASSERT_FALSE(CfgMgr::instance().ddnsEnabled()); + + struct Scenario { + std::string description_; + std::string original_; + std::string sanitized_; + }; + + std::vector scenarios = { + { + "unqualified host name with invalid characters", + "one-&$_-host", + "one-xxx-host" + }, + { + "qualified host name with invalid characters", + "two-&$_-host.other.org", + "two-xxx-host.other.org" + }, + { + "unqualified host name with all valid characters", + "three-ok-host", + "three-ok-host" + }, + { + "qualified host name with valid characters", + "four-ok-host.other.org", + "four-ok-host.other.org" + } + }; + + Pkt4Ptr resp; + OptionStringPtr hostname; + for (auto scenario : scenarios) { + SCOPED_TRACE((scenario).description_); + { + // Set the hostname option. + ASSERT_NO_THROW(client.includeHostname((scenario).original_)); + + // Send the DHCPDISCOVER and make sure that the server responded. + ASSERT_NO_THROW(client.doDiscover()); + resp = client.getContext().response_; + ASSERT_TRUE(resp); + ASSERT_EQ(DHCPOFFER, static_cast(resp->getType())); + + // Make sure the response hostname is what we expect. + hostname = boost::dynamic_pointer_cast(resp->getOption(DHO_HOST_NAME)); + ASSERT_TRUE(hostname); + EXPECT_EQ((scenario).sanitized_, hostname->getValue()); + } + } +} + // Verifies that setting hostname-char-set sanitizes FQDN option // values received from clients. TEST_F(NameDhcpv4SrvTest, sanitizeFqdn) { @@ -1867,5 +1954,72 @@ TEST_F(NameDhcpv4SrvTest, sanitizeFqdn) { } } +// Verifies that setting global hostname-char-set sanitizes FQDN option +// values received from clients. +TEST_F(NameDhcpv4SrvTest, sanitizeFqdnGlobal) { + Dhcp4Client client(Dhcp4Client::SELECTING); + + // Configure DHCP server. + configure(CONFIGS[7], *client.getServer()); + + // Make sure that DDNS is not enabled. + ASSERT_FALSE(CfgMgr::instance().ddnsEnabled()); + + struct Scenario { + std::string description_; + std::string original_; + Option4ClientFqdn::DomainNameType name_type_; + std::string sanitized_; + }; + + std::vector scenarios = { + { + "unqualified FQDN with invalid characters", + "one-&*_-host", + Option4ClientFqdn::PARTIAL, + "one-xxx-host." + }, + { + "qualified FQDN with invalid characters", + "two-&*_-host.other.org", + Option4ClientFqdn::FULL, + "two-xxx-host.other.org." + }, + { + "unqualified FQDN name with all valid characters", + "three-ok-host", + Option4ClientFqdn::PARTIAL, + "three-ok-host." + }, + { + "qualified FQDN name with valid characters", + "four-ok-host.other.org", + Option4ClientFqdn::FULL, + "four-ok-host.other.org." + } + }; + + Pkt4Ptr resp; + Option4ClientFqdnPtr fqdn; + for (auto scenario = scenarios.begin(); scenario != scenarios.end(); ++scenario) { + SCOPED_TRACE((*scenario).description_); + { + // Set the hostname option. + ASSERT_NO_THROW(client.includeHostname((*scenario).original_)); + ASSERT_NO_THROW(client.includeFQDN(0, (*scenario).original_, (*scenario).name_type_)); + + // Send the DHCPDISCOVER and make sure that the server responded. + ASSERT_NO_THROW(client.doDiscover()); + resp = client.getContext().response_; + ASSERT_TRUE(resp); + ASSERT_EQ(DHCPOFFER, static_cast(resp->getType())); + + // Make sure the response fqdn is what we expect. + fqdn = boost::dynamic_pointer_cast(resp->getOption(DHO_FQDN)); + ASSERT_TRUE(fqdn); + EXPECT_EQ((*scenario).sanitized_, fqdn->getDomainName()); + } + } +} } // end of anonymous namespace diff --git a/src/bin/dhcp4/tests/get_config_unittest.cc b/src/bin/dhcp4/tests/get_config_unittest.cc index 62b2945ae2..0b62c8d3ef 100644 --- a/src/bin/dhcp4/tests/get_config_unittest.cc +++ b/src/bin/dhcp4/tests/get_config_unittest.cc @@ -2064,8 +2064,6 @@ const char* UNPARSED_CONFIGS[] = { " \"dhcp-ddns\": {\n" " \"enable-updates\": false,\n" " \"generated-prefix\": \"myhost\",\n" -" \"hostname-char-replacement\": \"\",\n" -" \"hostname-char-set\": \"\",\n" " \"max-queue-size\": 1024,\n" " \"ncr-format\": \"JSON\",\n" " \"ncr-protocol\": \"UDP\",\n" @@ -2129,8 +2127,6 @@ const char* UNPARSED_CONFIGS[] = { " \"dhcp-ddns\": {\n" " \"enable-updates\": false,\n" " \"generated-prefix\": \"myhost\",\n" -" \"hostname-char-replacement\": \"\",\n" -" \"hostname-char-set\": \"\",\n" " \"max-queue-size\": 1024,\n" " \"ncr-format\": \"JSON\",\n" " \"ncr-protocol\": \"UDP\",\n" @@ -2221,8 +2217,6 @@ const char* UNPARSED_CONFIGS[] = { " \"dhcp-ddns\": {\n" " \"enable-updates\": false,\n" " \"generated-prefix\": \"myhost\",\n" -" \"hostname-char-replacement\": \"\",\n" -" \"hostname-char-set\": \"\",\n" " \"max-queue-size\": 1024,\n" " \"ncr-format\": \"JSON\",\n" " \"ncr-protocol\": \"UDP\",\n" @@ -2313,8 +2307,6 @@ const char* UNPARSED_CONFIGS[] = { " \"dhcp-ddns\": {\n" " \"enable-updates\": false,\n" " \"generated-prefix\": \"myhost\",\n" -" \"hostname-char-replacement\": \"\",\n" -" \"hostname-char-set\": \"\",\n" " \"max-queue-size\": 1024,\n" " \"ncr-format\": \"JSON\",\n" " \"ncr-protocol\": \"UDP\",\n" @@ -2407,8 +2399,6 @@ const char* UNPARSED_CONFIGS[] = { " \"dhcp-ddns\": {\n" " \"enable-updates\": false,\n" " \"generated-prefix\": \"myhost\",\n" -" \"hostname-char-replacement\": \"\",\n" -" \"hostname-char-set\": \"\",\n" " \"max-queue-size\": 1024,\n" " \"ncr-format\": \"JSON\",\n" " \"ncr-protocol\": \"UDP\",\n" @@ -2585,8 +2575,6 @@ const char* UNPARSED_CONFIGS[] = { " \"dhcp-ddns\": {\n" " \"enable-updates\": false,\n" " \"generated-prefix\": \"myhost\",\n" -" \"hostname-char-replacement\": \"\",\n" -" \"hostname-char-set\": \"\",\n" " \"max-queue-size\": 1024,\n" " \"ncr-format\": \"JSON\",\n" " \"ncr-protocol\": \"UDP\",\n" @@ -2763,8 +2751,6 @@ const char* UNPARSED_CONFIGS[] = { " \"dhcp-ddns\": {\n" " \"enable-updates\": false,\n" " \"generated-prefix\": \"myhost\",\n" -" \"hostname-char-replacement\": \"\",\n" -" \"hostname-char-set\": \"\",\n" " \"max-queue-size\": 1024,\n" " \"ncr-format\": \"JSON\",\n" " \"ncr-protocol\": \"UDP\",\n" @@ -2859,8 +2845,6 @@ const char* UNPARSED_CONFIGS[] = { " \"dhcp-ddns\": {\n" " \"enable-updates\": false,\n" " \"generated-prefix\": \"myhost\",\n" -" \"hostname-char-replacement\": \"\",\n" -" \"hostname-char-set\": \"\",\n" " \"max-queue-size\": 1024,\n" " \"ncr-format\": \"JSON\",\n" " \"ncr-protocol\": \"UDP\",\n" @@ -2955,8 +2939,6 @@ const char* UNPARSED_CONFIGS[] = { " \"dhcp-ddns\": {\n" " \"enable-updates\": false,\n" " \"generated-prefix\": \"myhost\",\n" -" \"hostname-char-replacement\": \"\",\n" -" \"hostname-char-set\": \"\",\n" " \"max-queue-size\": 1024,\n" " \"ncr-format\": \"JSON\",\n" " \"ncr-protocol\": \"UDP\",\n" @@ -3051,8 +3033,6 @@ const char* UNPARSED_CONFIGS[] = { " \"dhcp-ddns\": {\n" " \"enable-updates\": false,\n" " \"generated-prefix\": \"myhost\",\n" -" \"hostname-char-replacement\": \"\",\n" -" \"hostname-char-set\": \"\",\n" " \"max-queue-size\": 1024,\n" " \"ncr-format\": \"JSON\",\n" " \"ncr-protocol\": \"UDP\",\n" @@ -3145,8 +3125,6 @@ const char* UNPARSED_CONFIGS[] = { " \"dhcp-ddns\": {\n" " \"enable-updates\": false,\n" " \"generated-prefix\": \"myhost\",\n" -" \"hostname-char-replacement\": \"\",\n" -" \"hostname-char-set\": \"\",\n" " \"max-queue-size\": 1024,\n" " \"ncr-format\": \"JSON\",\n" " \"ncr-protocol\": \"UDP\",\n" @@ -3239,8 +3217,6 @@ const char* UNPARSED_CONFIGS[] = { " \"dhcp-ddns\": {\n" " \"enable-updates\": false,\n" " \"generated-prefix\": \"myhost\",\n" -" \"hostname-char-replacement\": \"\",\n" -" \"hostname-char-set\": \"\",\n" " \"max-queue-size\": 1024,\n" " \"ncr-format\": \"JSON\",\n" " \"ncr-protocol\": \"UDP\",\n" @@ -3361,8 +3337,6 @@ const char* UNPARSED_CONFIGS[] = { " \"dhcp-ddns\": {\n" " \"enable-updates\": false,\n" " \"generated-prefix\": \"myhost\",\n" -" \"hostname-char-replacement\": \"\",\n" -" \"hostname-char-set\": \"\",\n" " \"max-queue-size\": 1024,\n" " \"ncr-format\": \"JSON\",\n" " \"ncr-protocol\": \"UDP\",\n" @@ -3483,8 +3457,6 @@ const char* UNPARSED_CONFIGS[] = { " \"dhcp-ddns\": {\n" " \"enable-updates\": false,\n" " \"generated-prefix\": \"myhost\",\n" -" \"hostname-char-replacement\": \"\",\n" -" \"hostname-char-set\": \"\",\n" " \"max-queue-size\": 1024,\n" " \"ncr-format\": \"JSON\",\n" " \"ncr-protocol\": \"UDP\",\n" @@ -3605,8 +3577,6 @@ const char* UNPARSED_CONFIGS[] = { " \"dhcp-ddns\": {\n" " \"enable-updates\": false,\n" " \"generated-prefix\": \"myhost\",\n" -" \"hostname-char-replacement\": \"\",\n" -" \"hostname-char-set\": \"\",\n" " \"max-queue-size\": 1024,\n" " \"ncr-format\": \"JSON\",\n" " \"ncr-protocol\": \"UDP\",\n" @@ -3727,8 +3697,6 @@ const char* UNPARSED_CONFIGS[] = { " \"dhcp-ddns\": {\n" " \"enable-updates\": false,\n" " \"generated-prefix\": \"myhost\",\n" -" \"hostname-char-replacement\": \"\",\n" -" \"hostname-char-set\": \"\",\n" " \"max-queue-size\": 1024,\n" " \"ncr-format\": \"JSON\",\n" " \"ncr-protocol\": \"UDP\",\n" @@ -3821,8 +3789,6 @@ const char* UNPARSED_CONFIGS[] = { " \"dhcp-ddns\": {\n" " \"enable-updates\": false,\n" " \"generated-prefix\": \"myhost\",\n" -" \"hostname-char-replacement\": \"\",\n" -" \"hostname-char-set\": \"\",\n" " \"max-queue-size\": 1024,\n" " \"ncr-format\": \"JSON\",\n" " \"ncr-protocol\": \"UDP\",\n" @@ -3951,8 +3917,6 @@ const char* UNPARSED_CONFIGS[] = { " \"dhcp-ddns\": {\n" " \"enable-updates\": false,\n" " \"generated-prefix\": \"myhost\",\n" -" \"hostname-char-replacement\": \"\",\n" -" \"hostname-char-set\": \"\",\n" " \"max-queue-size\": 1024,\n" " \"ncr-format\": \"JSON\",\n" " \"ncr-protocol\": \"UDP\",\n" @@ -4045,8 +4009,6 @@ const char* UNPARSED_CONFIGS[] = { " \"dhcp-ddns\": {\n" " \"enable-updates\": false,\n" " \"generated-prefix\": \"myhost\",\n" -" \"hostname-char-replacement\": \"\",\n" -" \"hostname-char-set\": \"\",\n" " \"max-queue-size\": 1024,\n" " \"ncr-format\": \"JSON\",\n" " \"ncr-protocol\": \"UDP\",\n" @@ -4118,8 +4080,6 @@ const char* UNPARSED_CONFIGS[] = { " \"dhcp-ddns\": {\n" " \"enable-updates\": false,\n" " \"generated-prefix\": \"myhost\",\n" -" \"hostname-char-replacement\": \"\",\n" -" \"hostname-char-set\": \"\",\n" " \"max-queue-size\": 1024,\n" " \"ncr-format\": \"JSON\",\n" " \"ncr-protocol\": \"UDP\",\n" @@ -4191,8 +4151,6 @@ const char* UNPARSED_CONFIGS[] = { " \"dhcp-ddns\": {\n" " \"enable-updates\": false,\n" " \"generated-prefix\": \"myhost\",\n" -" \"hostname-char-replacement\": \"\",\n" -" \"hostname-char-set\": \"\",\n" " \"max-queue-size\": 1024,\n" " \"ncr-format\": \"JSON\",\n" " \"ncr-protocol\": \"UDP\",\n" @@ -4273,8 +4231,6 @@ const char* UNPARSED_CONFIGS[] = { " \"dhcp-ddns\": {\n" " \"enable-updates\": false,\n" " \"generated-prefix\": \"myhost\",\n" -" \"hostname-char-replacement\": \"\",\n" -" \"hostname-char-set\": \"\",\n" " \"max-queue-size\": 1024,\n" " \"ncr-format\": \"JSON\",\n" " \"ncr-protocol\": \"UDP\",\n" @@ -4346,8 +4302,6 @@ const char* UNPARSED_CONFIGS[] = { " \"dhcp-ddns\": {\n" " \"enable-updates\": false,\n" " \"generated-prefix\": \"myhost\",\n" -" \"hostname-char-replacement\": \"\",\n" -" \"hostname-char-set\": \"\",\n" " \"max-queue-size\": 1024,\n" " \"ncr-format\": \"JSON\",\n" " \"ncr-protocol\": \"UDP\",\n" @@ -4419,8 +4373,6 @@ const char* UNPARSED_CONFIGS[] = { " \"dhcp-ddns\": {\n" " \"enable-updates\": false,\n" " \"generated-prefix\": \"myhost\",\n" -" \"hostname-char-replacement\": \"\",\n" -" \"hostname-char-set\": \"\",\n" " \"max-queue-size\": 1024,\n" " \"ncr-format\": \"JSON\",\n" " \"ncr-protocol\": \"UDP\",\n" @@ -4492,8 +4444,6 @@ const char* UNPARSED_CONFIGS[] = { " \"dhcp-ddns\": {\n" " \"enable-updates\": false,\n" " \"generated-prefix\": \"myhost\",\n" -" \"hostname-char-replacement\": \"\",\n" -" \"hostname-char-set\": \"\",\n" " \"max-queue-size\": 1024,\n" " \"ncr-format\": \"JSON\",\n" " \"ncr-protocol\": \"UDP\",\n" @@ -4565,8 +4515,6 @@ const char* UNPARSED_CONFIGS[] = { " \"dhcp-ddns\": {\n" " \"enable-updates\": false,\n" " \"generated-prefix\": \"myhost\",\n" -" \"hostname-char-replacement\": \"\",\n" -" \"hostname-char-set\": \"\",\n" " \"max-queue-size\": 1024,\n" " \"ncr-format\": \"JSON\",\n" " \"ncr-protocol\": \"UDP\",\n" @@ -4676,8 +4624,6 @@ const char* UNPARSED_CONFIGS[] = { " \"dhcp-ddns\": {\n" " \"enable-updates\": false,\n" " \"generated-prefix\": \"myhost\",\n" -" \"hostname-char-replacement\": \"\",\n" -" \"hostname-char-set\": \"\",\n" " \"max-queue-size\": 1024,\n" " \"ncr-format\": \"JSON\",\n" " \"ncr-protocol\": \"UDP\",\n" @@ -4787,8 +4733,6 @@ const char* UNPARSED_CONFIGS[] = { " \"dhcp-ddns\": {\n" " \"enable-updates\": false,\n" " \"generated-prefix\": \"myhost\",\n" -" \"hostname-char-replacement\": \"\",\n" -" \"hostname-char-set\": \"\",\n" " \"max-queue-size\": 1024,\n" " \"ncr-format\": \"JSON\",\n" " \"ncr-protocol\": \"UDP\",\n" @@ -4908,8 +4852,6 @@ const char* UNPARSED_CONFIGS[] = { " \"dhcp-ddns\": {\n" " \"enable-updates\": false,\n" " \"generated-prefix\": \"myhost\",\n" -" \"hostname-char-replacement\": \"\",\n" -" \"hostname-char-set\": \"\",\n" " \"max-queue-size\": 1024,\n" " \"ncr-format\": \"JSON\",\n" " \"ncr-protocol\": \"UDP\",\n" @@ -5009,8 +4951,6 @@ const char* UNPARSED_CONFIGS[] = { " \"dhcp-ddns\": {\n" " \"enable-updates\": false,\n" " \"generated-prefix\": \"myhost\",\n" -" \"hostname-char-replacement\": \"\",\n" -" \"hostname-char-set\": \"\",\n" " \"max-queue-size\": 1024,\n" " \"ncr-format\": \"JSON\",\n" " \"ncr-protocol\": \"UDP\",\n" @@ -5156,8 +5096,6 @@ const char* UNPARSED_CONFIGS[] = { " \"dhcp-ddns\": {\n" " \"enable-updates\": false,\n" " \"generated-prefix\": \"myhost\",\n" -" \"hostname-char-replacement\": \"\",\n" -" \"hostname-char-set\": \"\",\n" " \"max-queue-size\": 1024,\n" " \"ncr-format\": \"JSON\",\n" " \"ncr-protocol\": \"UDP\",\n" @@ -5276,8 +5214,6 @@ const char* UNPARSED_CONFIGS[] = { " \"dhcp-ddns\": {\n" " \"enable-updates\": false,\n" " \"generated-prefix\": \"myhost\",\n" -" \"hostname-char-replacement\": \"\",\n" -" \"hostname-char-set\": \"\",\n" " \"max-queue-size\": 1024,\n" " \"ncr-format\": \"JSON\",\n" " \"ncr-protocol\": \"UDP\",\n" @@ -5416,8 +5352,6 @@ const char* UNPARSED_CONFIGS[] = { " \"dhcp-ddns\": {\n" " \"enable-updates\": false,\n" " \"generated-prefix\": \"myhost\",\n" -" \"hostname-char-replacement\": \"\",\n" -" \"hostname-char-set\": \"\",\n" " \"max-queue-size\": 1024,\n" " \"ncr-format\": \"JSON\",\n" " \"ncr-protocol\": \"UDP\",\n" @@ -5527,8 +5461,6 @@ const char* UNPARSED_CONFIGS[] = { " \"dhcp-ddns\": {\n" " \"enable-updates\": false,\n" " \"generated-prefix\": \"myhost\",\n" -" \"hostname-char-replacement\": \"\",\n" -" \"hostname-char-set\": \"\",\n" " \"max-queue-size\": 1024,\n" " \"ncr-format\": \"JSON\",\n" " \"ncr-protocol\": \"UDP\",\n" @@ -5643,8 +5575,6 @@ const char* UNPARSED_CONFIGS[] = { " \"dhcp-ddns\": {\n" " \"enable-updates\": false,\n" " \"generated-prefix\": \"myhost\",\n" -" \"hostname-char-replacement\": \"\",\n" -" \"hostname-char-set\": \"\",\n" " \"max-queue-size\": 1024,\n" " \"ncr-format\": \"JSON\",\n" " \"ncr-protocol\": \"UDP\",\n" @@ -5754,8 +5684,6 @@ const char* UNPARSED_CONFIGS[] = { " \"dhcp-ddns\": {\n" " \"enable-updates\": false,\n" " \"generated-prefix\": \"myhost\",\n" -" \"hostname-char-replacement\": \"\",\n" -" \"hostname-char-set\": \"\",\n" " \"max-queue-size\": 1024,\n" " \"ncr-format\": \"JSON\",\n" " \"ncr-protocol\": \"UDP\",\n" @@ -5855,8 +5783,6 @@ const char* UNPARSED_CONFIGS[] = { " \"dhcp-ddns\": {\n" " \"enable-updates\": false,\n" " \"generated-prefix\": \"myhost\",\n" -" \"hostname-char-replacement\": \"\",\n" -" \"hostname-char-set\": \"\",\n" " \"max-queue-size\": 1024,\n" " \"ncr-format\": \"JSON\",\n" " \"ncr-protocol\": \"UDP\",\n" @@ -5993,8 +5919,6 @@ const char* UNPARSED_CONFIGS[] = { " \"dhcp-ddns\": {\n" " \"enable-updates\": false,\n" " \"generated-prefix\": \"myhost\",\n" -" \"hostname-char-replacement\": \"\",\n" -" \"hostname-char-set\": \"\",\n" " \"max-queue-size\": 1024,\n" " \"ncr-format\": \"JSON\",\n" " \"ncr-protocol\": \"UDP\",\n" @@ -6102,8 +6026,6 @@ const char* UNPARSED_CONFIGS[] = { " \"dhcp-ddns\": {\n" " \"enable-updates\": false,\n" " \"generated-prefix\": \"myhost\",\n" -" \"hostname-char-replacement\": \"\",\n" -" \"hostname-char-set\": \"\",\n" " \"max-queue-size\": 1024,\n" " \"ncr-format\": \"JSON\",\n" " \"ncr-protocol\": \"UDP\",\n" @@ -6215,8 +6137,6 @@ const char* UNPARSED_CONFIGS[] = { " \"dhcp-ddns\": {\n" " \"enable-updates\": false,\n" " \"generated-prefix\": \"myhost\",\n" -" \"hostname-char-replacement\": \"\",\n" -" \"hostname-char-set\": \"\",\n" " \"max-queue-size\": 1024,\n" " \"ncr-format\": \"JSON\",\n" " \"ncr-protocol\": \"UDP\",\n" @@ -6280,8 +6200,6 @@ const char* UNPARSED_CONFIGS[] = { " \"dhcp-ddns\": {\n" " \"enable-updates\": false,\n" " \"generated-prefix\": \"myhost\",\n" -" \"hostname-char-replacement\": \"\",\n" -" \"hostname-char-set\": \"\",\n" " \"max-queue-size\": 1024,\n" " \"ncr-format\": \"JSON\",\n" " \"ncr-protocol\": \"UDP\",\n" @@ -6439,8 +6357,6 @@ const char* UNPARSED_CONFIGS[] = { " \"dhcp-ddns\": {\n" " \"enable-updates\": false,\n" " \"generated-prefix\": \"myhost\",\n" -" \"hostname-char-replacement\": \"\",\n" -" \"hostname-char-set\": \"\",\n" " \"max-queue-size\": 1024,\n" " \"ncr-format\": \"JSON\",\n" " \"ncr-protocol\": \"UDP\",\n" @@ -6533,8 +6449,6 @@ const char* UNPARSED_CONFIGS[] = { " \"dhcp-ddns\": {\n" " \"enable-updates\": false,\n" " \"generated-prefix\": \"myhost\",\n" -" \"hostname-char-replacement\": \"\",\n" -" \"hostname-char-set\": \"\",\n" " \"max-queue-size\": 1024,\n" " \"ncr-format\": \"JSON\",\n" " \"ncr-protocol\": \"UDP\",\n" @@ -6627,8 +6541,6 @@ const char* UNPARSED_CONFIGS[] = { " \"dhcp-ddns\": {\n" " \"enable-updates\": false,\n" " \"generated-prefix\": \"myhost\",\n" -" \"hostname-char-replacement\": \"\",\n" -" \"hostname-char-set\": \"\",\n" " \"max-queue-size\": 1024,\n" " \"ncr-format\": \"JSON\",\n" " \"ncr-protocol\": \"UDP\",\n" @@ -6808,8 +6720,6 @@ const char* UNPARSED_CONFIGS[] = { " \"dhcp-ddns\": {\n" " \"enable-updates\": false,\n" " \"generated-prefix\": \"myhost\",\n" -" \"hostname-char-replacement\": \"\",\n" -" \"hostname-char-set\": \"\",\n" " \"max-queue-size\": 1024,\n" " \"ncr-format\": \"JSON\",\n" " \"ncr-protocol\": \"UDP\",\n" @@ -6917,8 +6827,6 @@ const char* UNPARSED_CONFIGS[] = { " \"dhcp-ddns\": {\n" " \"enable-updates\": false,\n" " \"generated-prefix\": \"myhost\",\n" -" \"hostname-char-replacement\": \"\",\n" -" \"hostname-char-set\": \"\",\n" " \"max-queue-size\": 1024,\n" " \"ncr-format\": \"JSON\",\n" " \"ncr-protocol\": \"UDP\",\n" @@ -7170,8 +7078,6 @@ const char* UNPARSED_CONFIGS[] = { " \"dhcp-ddns\": {\n" " \"enable-updates\": false,\n" " \"generated-prefix\": \"myhost\",\n" -" \"hostname-char-replacement\": \"\",\n" -" \"hostname-char-set\": \"\",\n" " \"max-queue-size\": 1024,\n" " \"ncr-format\": \"JSON\",\n" " \"ncr-protocol\": \"UDP\",\n" @@ -7294,8 +7200,6 @@ const char* UNPARSED_CONFIGS[] = { " \"dhcp-ddns\": {\n" " \"enable-updates\": false,\n" " \"generated-prefix\": \"myhost\",\n" -" \"hostname-char-replacement\": \"\",\n" -" \"hostname-char-set\": \"\",\n" " \"max-queue-size\": 1024,\n" " \"ncr-format\": \"JSON\",\n" " \"ncr-protocol\": \"UDP\",\n" @@ -7472,8 +7376,6 @@ const char* UNPARSED_CONFIGS[] = { " \"dhcp-ddns\": {\n" " \"enable-updates\": false,\n" " \"generated-prefix\": \"myhost\",\n" -" \"hostname-char-replacement\": \"\",\n" -" \"hostname-char-set\": \"\",\n" " \"max-queue-size\": 1024,\n" " \"ncr-format\": \"JSON\",\n" " \"ncr-protocol\": \"UDP\",\n" @@ -7594,8 +7496,6 @@ const char* UNPARSED_CONFIGS[] = { " \"dhcp-ddns\": {\n" " \"enable-updates\": false,\n" " \"generated-prefix\": \"myhost\",\n" -" \"hostname-char-replacement\": \"\",\n" -" \"hostname-char-set\": \"\",\n" " \"max-queue-size\": 1024,\n" " \"ncr-format\": \"JSON\",\n" " \"ncr-protocol\": \"UDP\",\n" @@ -7657,8 +7557,6 @@ const char* UNPARSED_CONFIGS[] = { " \"dhcp-ddns\": {\n" " \"enable-updates\": false,\n" " \"generated-prefix\": \"myhost\",\n" -" \"hostname-char-replacement\": \"\",\n" -" \"hostname-char-set\": \"\",\n" " \"max-queue-size\": 1024,\n" " \"ncr-format\": \"JSON\",\n" " \"ncr-protocol\": \"UDP\",\n" @@ -7720,8 +7618,6 @@ const char* UNPARSED_CONFIGS[] = { " \"dhcp-ddns\": {\n" " \"enable-updates\": false,\n" " \"generated-prefix\": \"myhost\",\n" -" \"hostname-char-replacement\": \"\",\n" -" \"hostname-char-set\": \"\",\n" " \"max-queue-size\": 1024,\n" " \"ncr-format\": \"JSON\",\n" " \"ncr-protocol\": \"UDP\",\n" @@ -7783,8 +7679,6 @@ const char* UNPARSED_CONFIGS[] = { " \"dhcp-ddns\": {\n" " \"enable-updates\": false,\n" " \"generated-prefix\": \"myhost\",\n" -" \"hostname-char-replacement\": \"\",\n" -" \"hostname-char-set\": \"\",\n" " \"max-queue-size\": 1024,\n" " \"ncr-format\": \"JSON\",\n" " \"ncr-protocol\": \"UDP\",\n" @@ -7846,8 +7740,6 @@ const char* UNPARSED_CONFIGS[] = { " \"dhcp-ddns\": {\n" " \"enable-updates\": false,\n" " \"generated-prefix\": \"myhost\",\n" -" \"hostname-char-replacement\": \"\",\n" -" \"hostname-char-set\": \"\",\n" " \"max-queue-size\": 1024,\n" " \"ncr-format\": \"JSON\",\n" " \"ncr-protocol\": \"UDP\",\n" @@ -7940,8 +7832,6 @@ const char* UNPARSED_CONFIGS[] = { " \"dhcp-ddns\": {\n" " \"enable-updates\": false,\n" " \"generated-prefix\": \"myhost\",\n" -" \"hostname-char-replacement\": \"\",\n" -" \"hostname-char-set\": \"\",\n" " \"max-queue-size\": 1024,\n" " \"ncr-format\": \"JSON\",\n" " \"ncr-protocol\": \"UDP\",\n" @@ -8034,8 +7924,6 @@ const char* UNPARSED_CONFIGS[] = { " \"dhcp-ddns\": {\n" " \"enable-updates\": false,\n" " \"generated-prefix\": \"myhost\",\n" -" \"hostname-char-replacement\": \"\",\n" -" \"hostname-char-set\": \"\",\n" " \"max-queue-size\": 1024,\n" " \"ncr-format\": \"JSON\",\n" " \"ncr-protocol\": \"UDP\",\n" @@ -8128,8 +8016,6 @@ const char* UNPARSED_CONFIGS[] = { " \"dhcp-ddns\": {\n" " \"enable-updates\": false,\n" " \"generated-prefix\": \"myhost\",\n" -" \"hostname-char-replacement\": \"\",\n" -" \"hostname-char-set\": \"\",\n" " \"max-queue-size\": 1024,\n" " \"ncr-format\": \"JSON\",\n" " \"ncr-protocol\": \"UDP\",\n" @@ -8222,8 +8108,6 @@ const char* UNPARSED_CONFIGS[] = { " \"dhcp-ddns\": {\n" " \"enable-updates\": false,\n" " \"generated-prefix\": \"myhost\",\n" -" \"hostname-char-replacement\": \"\",\n" -" \"hostname-char-set\": \"\",\n" " \"max-queue-size\": 1024,\n" " \"ncr-format\": \"JSON\",\n" " \"ncr-protocol\": \"UDP\",\n" @@ -8342,8 +8226,6 @@ const char* UNPARSED_CONFIGS[] = { " \"dhcp-ddns\": {\n" " \"enable-updates\": false,\n" " \"generated-prefix\": \"myhost\",\n" -" \"hostname-char-replacement\": \"\",\n" -" \"hostname-char-set\": \"\",\n" " \"max-queue-size\": 1024,\n" " \"ncr-format\": \"JSON\",\n" " \"ncr-protocol\": \"UDP\",\n" @@ -8436,8 +8318,6 @@ const char* UNPARSED_CONFIGS[] = { " \"dhcp-ddns\": {\n" " \"enable-updates\": false,\n" " \"generated-prefix\": \"myhost\",\n" -" \"hostname-char-replacement\": \"\",\n" -" \"hostname-char-set\": \"\",\n" " \"max-queue-size\": 1024,\n" " \"ncr-format\": \"JSON\",\n" " \"ncr-protocol\": \"UDP\",\n" @@ -8530,8 +8410,6 @@ const char* UNPARSED_CONFIGS[] = { " \"dhcp-ddns\": {\n" " \"enable-updates\": false,\n" " \"generated-prefix\": \"myhost\",\n" -" \"hostname-char-replacement\": \"\",\n" -" \"hostname-char-set\": \"\",\n" " \"max-queue-size\": 1024,\n" " \"ncr-format\": \"JSON\",\n" " \"ncr-protocol\": \"UDP\",\n" @@ -8625,8 +8503,6 @@ const char* UNPARSED_CONFIGS[] = { " \"dhcp-ddns\": {\n" " \"enable-updates\": false,\n" " \"generated-prefix\": \"myhost\",\n" -" \"hostname-char-replacement\": \"\",\n" -" \"hostname-char-set\": \"\",\n" " \"max-queue-size\": 1024,\n" " \"ncr-format\": \"JSON\",\n" " \"ncr-protocol\": \"UDP\",\n" @@ -8724,8 +8600,6 @@ const char* UNPARSED_CONFIGS[] = { " \"dhcp-ddns\": {\n" " \"enable-updates\": false,\n" " \"generated-prefix\": \"myhost\",\n" -" \"hostname-char-replacement\": \"\",\n" -" \"hostname-char-set\": \"\",\n" " \"max-queue-size\": 1024,\n" " \"ncr-format\": \"JSON\",\n" " \"ncr-protocol\": \"UDP\",\n" @@ -8823,8 +8697,6 @@ const char* UNPARSED_CONFIGS[] = { " \"dhcp-ddns\": {\n" " \"enable-updates\": false,\n" " \"generated-prefix\": \"myhost\",\n" -" \"hostname-char-replacement\": \"\",\n" -" \"hostname-char-set\": \"\",\n" " \"max-queue-size\": 1024,\n" " \"ncr-format\": \"JSON\",\n" " \"ncr-protocol\": \"UDP\",\n" @@ -8941,8 +8813,6 @@ const char* UNPARSED_CONFIGS[] = { " \"comment\": \"No dynamic DNS\",\n" " \"enable-updates\": false,\n" " \"generated-prefix\": \"myhost\",\n" -" \"hostname-char-replacement\": \"\",\n" -" \"hostname-char-set\": \"\",\n" " \"max-queue-size\": 1024,\n" " \"ncr-format\": \"JSON\",\n" " \"ncr-protocol\": \"UDP\",\n" @@ -9095,8 +8965,6 @@ const char* UNPARSED_CONFIGS[] = { " \"dhcp-ddns\": {\n" " \"enable-updates\": false,\n" " \"generated-prefix\": \"myhost\",\n" -" \"hostname-char-replacement\": \"\",\n" -" \"hostname-char-set\": \"\",\n" " \"max-queue-size\": 1024,\n" " \"ncr-format\": \"JSON\",\n" " \"ncr-protocol\": \"UDP\",\n" @@ -9272,8 +9140,6 @@ const char* UNPARSED_CONFIGS[] = { " \"dhcp-ddns\": {\n" " \"enable-updates\": false,\n" " \"generated-prefix\": \"myhost\",\n" -" \"hostname-char-replacement\": \"\",\n" -" \"hostname-char-set\": \"\",\n" " \"max-queue-size\": 1024,\n" " \"ncr-format\": \"JSON\",\n" " \"ncr-protocol\": \"UDP\",\n" diff --git a/src/bin/dhcp6/ctrl_dhcp6_srv.cc b/src/bin/dhcp6/ctrl_dhcp6_srv.cc index d38ba4433c..ee95de32cd 100644 --- a/src/bin/dhcp6/ctrl_dhcp6_srv.cc +++ b/src/bin/dhcp6/ctrl_dhcp6_srv.cc @@ -375,6 +375,12 @@ ControlledDhcpv6Srv::commandConfigSetHandler(const string&, if (rcode == CONTROL_RESULT_SUCCESS) { CfgMgr::instance().getStagingCfg()->applyLoggingCfg(); + // Update the fetch globals callback. + auto cfg = CfgMgr::instance().getStagingCfg()->getD2ClientConfig(); + cfg->setFetchGlobalsFn([]() -> ConstElementPtr { + return (CfgMgr::instance().getCurrentCfg()->getConfiguredGlobals()); + }); + // Use new configuration. CfgMgr::instance().commit(); } else { diff --git a/src/bin/dhcp6/json_config_parser.cc b/src/bin/dhcp6/json_config_parser.cc index a0068ecf8f..ff6cce7e13 100644 --- a/src/bin/dhcp6/json_config_parser.cc +++ b/src/bin/dhcp6/json_config_parser.cc @@ -473,6 +473,9 @@ configureDhcp6Server(Dhcpv6Srv& server, isc::data::ConstElementPtr config_set, // early. Dhcp6ConfigParser global_parser; + // D2 client configuration. + D2ClientConfigPtr d2_client_cfg; + BOOST_FOREACH(config_pair, values_map) { // In principle we could have the following code structured as a series // of long if else if clauses. That would give a marginal performance @@ -567,8 +570,7 @@ configureDhcp6Server(Dhcpv6Srv& server, isc::data::ConstElementPtr config_set, // Apply defaults D2ClientConfigParser::setAllDefaults(config_pair.second); D2ClientConfigParser parser; - D2ClientConfigPtr cfg = parser.parse(config_pair.second); - srv_config->setD2ClientConfig(cfg); + d2_client_cfg = parser.parse(config_pair.second); continue; } @@ -674,7 +676,9 @@ configureDhcp6Server(Dhcpv6Srv& server, isc::data::ConstElementPtr config_set, (config_pair.first == "calculate-tee-times") || (config_pair.first == "t1-percent") || (config_pair.first == "t2-percent") || - (config_pair.first == "loggers")) { + (config_pair.first == "loggers") || + (config_pair.first == "hostname-char-set") || + (config_pair.first == "hostname-char-replacement")) { CfgMgr::instance().getStagingCfg()->addConfiguredGlobal(config_pair.first, config_pair.second); @@ -706,6 +710,16 @@ configureDhcp6Server(Dhcpv6Srv& server, isc::data::ConstElementPtr config_set, // defined as part of shared networks. global_parser.sanityChecks(srv_config, mutable_cfg); + // Validate D2 client confuguration. + if (!d2_client_cfg) { + d2_client_cfg.reset(new D2ClientConfig()); + d2_client_cfg->setFetchGlobalsFn([]() -> ConstElementPtr { + return (CfgMgr::instance().getStagingCfg()->getConfiguredGlobals()); + }); + } + d2_client_cfg->validateContents(); + srv_config->setD2ClientConfig(d2_client_cfg); + } catch (const isc::Exception& ex) { LOG_ERROR(dhcp6_logger, DHCP6_PARSER_FAIL) .arg(config_pair.first).arg(ex.what()); diff --git a/src/bin/dhcp6/tests/config_parser_unittest.cc b/src/bin/dhcp6/tests/config_parser_unittest.cc index 9084da14e9..5b32232d84 100644 --- a/src/bin/dhcp6/tests/config_parser_unittest.cc +++ b/src/bin/dhcp6/tests/config_parser_unittest.cc @@ -4627,8 +4627,167 @@ TEST_F(Dhcp6ParserTest, d2ClientConfig) { EXPECT_EQ(D2ClientConfig::RCM_WHEN_PRESENT, d2_client_config->getReplaceClientNameMode()); EXPECT_EQ("test.prefix", d2_client_config->getGeneratedPrefix()); EXPECT_EQ("test.suffix.", d2_client_config->getQualifyingSuffix()); + EXPECT_FALSE(d2_client_config->getHostnameCharSet().unspecified()); EXPECT_EQ("[^A-Za-z0-9_-]", d2_client_config->getHostnameCharSet().get()); + EXPECT_FALSE(d2_client_config->getHostnameCharReplacement().unspecified()); EXPECT_EQ("x", d2_client_config->getHostnameCharReplacement().get()); + EXPECT_TRUE(d2_client_config->getHostnameSanitizer()); +} + +// This test checks the ability of the server to parse a configuration +// containing a full, valid dhcp-ddns (D2ClientConfig) entry with +// hostname-char-* at the global scope. +TEST_F(Dhcp6ParserTest, d2ClientConfigGlobal) { + // Verify that the D2 configuration can be fetched and is set to disabled. + D2ClientConfigPtr d2_client_config = CfgMgr::instance().getD2ClientConfig(); + EXPECT_FALSE(d2_client_config->getEnableUpdates()); + + // Verify that the convenience method agrees. + ASSERT_FALSE(CfgMgr::instance().ddnsEnabled()); + + string config_str = "{ " + genIfaceConfig() + "," + "\"preferred-lifetime\": 3000," + "\"valid-lifetime\": 4000," + "\"rebind-timer\": 2000, " + "\"renew-timer\": 1000, " + "\"subnet6\": [ { " + " \"pools\": [ { \"pool\": \"2001:db8:1::/80\" } ]," + " \"subnet\": \"2001:db8:1::/64\" } ], " + " \"dhcp-ddns\" : {" + " \"enable-updates\" : true, " + " \"server-ip\" : \"3001::1\", " + " \"server-port\" : 777, " + " \"sender-ip\" : \"3001::2\", " + " \"sender-port\" : 778, " + " \"max-queue-size\" : 2048, " + " \"ncr-protocol\" : \"UDP\", " + " \"ncr-format\" : \"JSON\", " + " \"override-no-update\" : true, " + " \"override-client-update\" : true, " + " \"replace-client-name\" : \"when-present\", " + " \"generated-prefix\" : \"test.prefix\", " + " \"qualifying-suffix\" : \"test.suffix.\" }, " + "\"hostname-char-set\" : \"[^A-Za-z0-9_-]\", " + "\"hostname-char-replacement\" : \"x\", " + "\"valid-lifetime\": 4000 }"; + + // Convert the JSON string to configuration elements. + ConstElementPtr config; + ASSERT_NO_THROW(config = parseDHCP6(config_str)); + extractConfig(config_str); + + // Pass the configuration in for parsing. + ConstElementPtr status; + EXPECT_NO_THROW(status = configureDhcp6Server(srv_, config)); + + // check if returned status is OK + checkResult(status, 0); + + // Verify that DHCP-DDNS updating is enabled. + EXPECT_TRUE(CfgMgr::instance().ddnsEnabled()); + + // Verify that the D2 configuration can be retrieved. + d2_client_config = CfgMgr::instance().getD2ClientConfig(); + ASSERT_TRUE(d2_client_config); + + // Verify that the configuration values are correct. + EXPECT_TRUE(d2_client_config->getEnableUpdates()); + EXPECT_EQ("3001::1", d2_client_config->getServerIp().toText()); + EXPECT_EQ(777, d2_client_config->getServerPort()); + EXPECT_EQ("3001::2", d2_client_config->getSenderIp().toText()); + EXPECT_EQ(778, d2_client_config->getSenderPort()); + EXPECT_EQ(2048, d2_client_config->getMaxQueueSize()); + EXPECT_EQ(dhcp_ddns::NCR_UDP, d2_client_config->getNcrProtocol()); + EXPECT_EQ(dhcp_ddns::FMT_JSON, d2_client_config->getNcrFormat()); + EXPECT_TRUE(d2_client_config->getOverrideNoUpdate()); + EXPECT_TRUE(d2_client_config->getOverrideClientUpdate()); + EXPECT_EQ(D2ClientConfig::RCM_WHEN_PRESENT, d2_client_config->getReplaceClientNameMode()); + EXPECT_EQ("test.prefix", d2_client_config->getGeneratedPrefix()); + EXPECT_EQ("test.suffix.", d2_client_config->getQualifyingSuffix()); + EXPECT_FALSE(d2_client_config->getHostnameCharSet().unspecified()); + EXPECT_EQ("[^A-Za-z0-9_-]", d2_client_config->getHostnameCharSet().get()); + EXPECT_FALSE(d2_client_config->getHostnameCharReplacement().unspecified()); + EXPECT_EQ("x", d2_client_config->getHostnameCharReplacement().get()); + EXPECT_TRUE(d2_client_config->getHostnameSanitizer()); +} + +// This test checks the ability of the server to parse a configuration +// containing a full, valid dhcp-ddns (D2ClientConfig) entry with +// hostname-char-* at the local and global scopes (local has the priority). +TEST_F(Dhcp6ParserTest, d2ClientConfigBoth) { + // Verify that the D2 configuration can be fetched and is set to disabled. + D2ClientConfigPtr d2_client_config = CfgMgr::instance().getD2ClientConfig(); + EXPECT_FALSE(d2_client_config->getEnableUpdates()); + + // Verify that the convenience method agrees. + ASSERT_FALSE(CfgMgr::instance().ddnsEnabled()); + + string config_str = "{ " + genIfaceConfig() + "," + "\"preferred-lifetime\": 3000," + "\"valid-lifetime\": 4000," + "\"rebind-timer\": 2000, " + "\"renew-timer\": 1000, " + "\"subnet6\": [ { " + " \"pools\": [ { \"pool\": \"2001:db8:1::/80\" } ]," + " \"subnet\": \"2001:db8:1::/64\" } ], " + " \"dhcp-ddns\" : {" + " \"enable-updates\" : true, " + " \"server-ip\" : \"3001::1\", " + " \"server-port\" : 777, " + " \"sender-ip\" : \"3001::2\", " + " \"sender-port\" : 778, " + " \"max-queue-size\" : 2048, " + " \"ncr-protocol\" : \"UDP\", " + " \"ncr-format\" : \"JSON\", " + " \"override-no-update\" : true, " + " \"override-client-update\" : true, " + " \"replace-client-name\" : \"when-present\", " + " \"generated-prefix\" : \"test.prefix\", " + " \"qualifying-suffix\" : \"test.suffix.\", " + " \"hostname-char-set\" : \"[^A-Za-z0-9_-]\", " + " \"hostname-char-replacement\" : \"x\" }, " + "\"hostname-char-set\" : \"[^A-Z]\", " + "\"hostname-char-replacement\" : \"z\", " + "\"valid-lifetime\": 4000 }"; + + // Convert the JSON string to configuration elements. + ConstElementPtr config; + ASSERT_NO_THROW(config = parseDHCP6(config_str)); + extractConfig(config_str); + + // Pass the configuration in for parsing. + ConstElementPtr status; + EXPECT_NO_THROW(status = configureDhcp6Server(srv_, config)); + + // check if returned status is OK + checkResult(status, 0); + + // Verify that DHCP-DDNS updating is enabled. + EXPECT_TRUE(CfgMgr::instance().ddnsEnabled()); + + // Verify that the D2 configuration can be retrieved. + d2_client_config = CfgMgr::instance().getD2ClientConfig(); + ASSERT_TRUE(d2_client_config); + + // Verify that the configuration values are correct. + EXPECT_TRUE(d2_client_config->getEnableUpdates()); + EXPECT_EQ("3001::1", d2_client_config->getServerIp().toText()); + EXPECT_EQ(777, d2_client_config->getServerPort()); + EXPECT_EQ("3001::2", d2_client_config->getSenderIp().toText()); + EXPECT_EQ(778, d2_client_config->getSenderPort()); + EXPECT_EQ(2048, d2_client_config->getMaxQueueSize()); + EXPECT_EQ(dhcp_ddns::NCR_UDP, d2_client_config->getNcrProtocol()); + EXPECT_EQ(dhcp_ddns::FMT_JSON, d2_client_config->getNcrFormat()); + EXPECT_TRUE(d2_client_config->getOverrideNoUpdate()); + EXPECT_TRUE(d2_client_config->getOverrideClientUpdate()); + EXPECT_EQ(D2ClientConfig::RCM_WHEN_PRESENT, d2_client_config->getReplaceClientNameMode()); + EXPECT_EQ("test.prefix", d2_client_config->getGeneratedPrefix()); + EXPECT_EQ("test.suffix.", d2_client_config->getQualifyingSuffix()); + EXPECT_FALSE(d2_client_config->getHostnameCharSet().unspecified()); + EXPECT_EQ("[^A-Za-z0-9_-]", d2_client_config->getHostnameCharSet().get()); + EXPECT_FALSE(d2_client_config->getHostnameCharReplacement().unspecified()); + EXPECT_EQ("x", d2_client_config->getHostnameCharReplacement().get()); + EXPECT_TRUE(d2_client_config->getHostnameSanitizer()); } // This test checks the ability of the server to handle a configuration diff --git a/src/bin/dhcp6/tests/get_config_unittest.cc b/src/bin/dhcp6/tests/get_config_unittest.cc index b581ce5cfa..55fbfc0807 100644 --- a/src/bin/dhcp6/tests/get_config_unittest.cc +++ b/src/bin/dhcp6/tests/get_config_unittest.cc @@ -1841,8 +1841,6 @@ const char* UNPARSED_CONFIGS[] = { " \"dhcp-ddns\": {\n" " \"enable-updates\": false,\n" " \"generated-prefix\": \"myhost\",\n" -" \"hostname-char-replacement\": \"\",\n" -" \"hostname-char-set\": \"\",\n" " \"max-queue-size\": 1024,\n" " \"ncr-format\": \"JSON\",\n" " \"ncr-protocol\": \"UDP\",\n" @@ -1911,8 +1909,6 @@ const char* UNPARSED_CONFIGS[] = { " \"dhcp-ddns\": {\n" " \"enable-updates\": false,\n" " \"generated-prefix\": \"myhost\",\n" -" \"hostname-char-replacement\": \"\",\n" -" \"hostname-char-set\": \"\",\n" " \"max-queue-size\": 1024,\n" " \"ncr-format\": \"JSON\",\n" " \"ncr-protocol\": \"UDP\",\n" @@ -2007,8 +2003,6 @@ const char* UNPARSED_CONFIGS[] = { " \"dhcp-ddns\": {\n" " \"enable-updates\": false,\n" " \"generated-prefix\": \"myhost\",\n" -" \"hostname-char-replacement\": \"\",\n" -" \"hostname-char-set\": \"\",\n" " \"max-queue-size\": 1024,\n" " \"ncr-format\": \"JSON\",\n" " \"ncr-protocol\": \"UDP\",\n" @@ -2178,8 +2172,6 @@ const char* UNPARSED_CONFIGS[] = { " \"dhcp-ddns\": {\n" " \"enable-updates\": false,\n" " \"generated-prefix\": \"myhost\",\n" -" \"hostname-char-replacement\": \"\",\n" -" \"hostname-char-set\": \"\",\n" " \"max-queue-size\": 1024,\n" " \"ncr-format\": \"JSON\",\n" " \"ncr-protocol\": \"UDP\",\n" @@ -2349,8 +2341,6 @@ const char* UNPARSED_CONFIGS[] = { " \"dhcp-ddns\": {\n" " \"enable-updates\": false,\n" " \"generated-prefix\": \"myhost\",\n" -" \"hostname-char-replacement\": \"\",\n" -" \"hostname-char-set\": \"\",\n" " \"max-queue-size\": 1024,\n" " \"ncr-format\": \"JSON\",\n" " \"ncr-protocol\": \"UDP\",\n" @@ -2520,8 +2510,6 @@ const char* UNPARSED_CONFIGS[] = { " \"dhcp-ddns\": {\n" " \"enable-updates\": false,\n" " \"generated-prefix\": \"myhost\",\n" -" \"hostname-char-replacement\": \"\",\n" -" \"hostname-char-set\": \"\",\n" " \"max-queue-size\": 1024,\n" " \"ncr-format\": \"JSON\",\n" " \"ncr-protocol\": \"UDP\",\n" @@ -2616,8 +2604,6 @@ const char* UNPARSED_CONFIGS[] = { " \"dhcp-ddns\": {\n" " \"enable-updates\": false,\n" " \"generated-prefix\": \"myhost\",\n" -" \"hostname-char-replacement\": \"\",\n" -" \"hostname-char-set\": \"\",\n" " \"max-queue-size\": 1024,\n" " \"ncr-format\": \"JSON\",\n" " \"ncr-protocol\": \"UDP\",\n" @@ -2713,8 +2699,6 @@ const char* UNPARSED_CONFIGS[] = { " \"dhcp-ddns\": {\n" " \"enable-updates\": false,\n" " \"generated-prefix\": \"myhost\",\n" -" \"hostname-char-replacement\": \"\",\n" -" \"hostname-char-set\": \"\",\n" " \"max-queue-size\": 1024,\n" " \"ncr-format\": \"JSON\",\n" " \"ncr-protocol\": \"UDP\",\n" @@ -2810,8 +2794,6 @@ const char* UNPARSED_CONFIGS[] = { " \"dhcp-ddns\": {\n" " \"enable-updates\": false,\n" " \"generated-prefix\": \"myhost\",\n" -" \"hostname-char-replacement\": \"\",\n" -" \"hostname-char-set\": \"\",\n" " \"max-queue-size\": 1024,\n" " \"ncr-format\": \"JSON\",\n" " \"ncr-protocol\": \"UDP\",\n" @@ -2939,8 +2921,6 @@ const char* UNPARSED_CONFIGS[] = { " \"dhcp-ddns\": {\n" " \"enable-updates\": false,\n" " \"generated-prefix\": \"myhost\",\n" -" \"hostname-char-replacement\": \"\",\n" -" \"hostname-char-set\": \"\",\n" " \"max-queue-size\": 1024,\n" " \"ncr-format\": \"JSON\",\n" " \"ncr-protocol\": \"UDP\",\n" @@ -3035,8 +3015,6 @@ const char* UNPARSED_CONFIGS[] = { " \"dhcp-ddns\": {\n" " \"enable-updates\": false,\n" " \"generated-prefix\": \"myhost\",\n" -" \"hostname-char-replacement\": \"\",\n" -" \"hostname-char-set\": \"\",\n" " \"max-queue-size\": 1024,\n" " \"ncr-format\": \"JSON\",\n" " \"ncr-protocol\": \"UDP\",\n" @@ -3133,8 +3111,6 @@ const char* UNPARSED_CONFIGS[] = { " \"dhcp-ddns\": {\n" " \"enable-updates\": false,\n" " \"generated-prefix\": \"myhost\",\n" -" \"hostname-char-replacement\": \"\",\n" -" \"hostname-char-set\": \"\",\n" " \"max-queue-size\": 1024,\n" " \"ncr-format\": \"JSON\",\n" " \"ncr-protocol\": \"UDP\",\n" @@ -3233,8 +3209,6 @@ const char* UNPARSED_CONFIGS[] = { " \"dhcp-ddns\": {\n" " \"enable-updates\": false,\n" " \"generated-prefix\": \"myhost\",\n" -" \"hostname-char-replacement\": \"\",\n" -" \"hostname-char-set\": \"\",\n" " \"max-queue-size\": 1024,\n" " \"ncr-format\": \"JSON\",\n" " \"ncr-protocol\": \"UDP\",\n" @@ -3348,8 +3322,6 @@ const char* UNPARSED_CONFIGS[] = { " \"dhcp-ddns\": {\n" " \"enable-updates\": false,\n" " \"generated-prefix\": \"myhost\",\n" -" \"hostname-char-replacement\": \"\",\n" -" \"hostname-char-set\": \"\",\n" " \"max-queue-size\": 1024,\n" " \"ncr-format\": \"JSON\",\n" " \"ncr-protocol\": \"UDP\",\n" @@ -3446,8 +3418,6 @@ const char* UNPARSED_CONFIGS[] = { " \"dhcp-ddns\": {\n" " \"enable-updates\": false,\n" " \"generated-prefix\": \"myhost\",\n" -" \"hostname-char-replacement\": \"\",\n" -" \"hostname-char-set\": \"\",\n" " \"max-queue-size\": 1024,\n" " \"ncr-format\": \"JSON\",\n" " \"ncr-protocol\": \"UDP\",\n" @@ -3524,8 +3494,6 @@ const char* UNPARSED_CONFIGS[] = { " \"dhcp-ddns\": {\n" " \"enable-updates\": false,\n" " \"generated-prefix\": \"myhost\",\n" -" \"hostname-char-replacement\": \"\",\n" -" \"hostname-char-set\": \"\",\n" " \"max-queue-size\": 1024,\n" " \"ncr-format\": \"JSON\",\n" " \"ncr-protocol\": \"UDP\",\n" @@ -3602,8 +3570,6 @@ const char* UNPARSED_CONFIGS[] = { " \"dhcp-ddns\": {\n" " \"enable-updates\": false,\n" " \"generated-prefix\": \"myhost\",\n" -" \"hostname-char-replacement\": \"\",\n" -" \"hostname-char-set\": \"\",\n" " \"max-queue-size\": 1024,\n" " \"ncr-format\": \"JSON\",\n" " \"ncr-protocol\": \"UDP\",\n" @@ -3689,8 +3655,6 @@ const char* UNPARSED_CONFIGS[] = { " \"dhcp-ddns\": {\n" " \"enable-updates\": false,\n" " \"generated-prefix\": \"myhost\",\n" -" \"hostname-char-replacement\": \"\",\n" -" \"hostname-char-set\": \"\",\n" " \"max-queue-size\": 1024,\n" " \"ncr-format\": \"JSON\",\n" " \"ncr-protocol\": \"UDP\",\n" @@ -3767,8 +3731,6 @@ const char* UNPARSED_CONFIGS[] = { " \"dhcp-ddns\": {\n" " \"enable-updates\": false,\n" " \"generated-prefix\": \"myhost\",\n" -" \"hostname-char-replacement\": \"\",\n" -" \"hostname-char-set\": \"\",\n" " \"max-queue-size\": 1024,\n" " \"ncr-format\": \"JSON\",\n" " \"ncr-protocol\": \"UDP\",\n" @@ -3845,8 +3807,6 @@ const char* UNPARSED_CONFIGS[] = { " \"dhcp-ddns\": {\n" " \"enable-updates\": false,\n" " \"generated-prefix\": \"myhost\",\n" -" \"hostname-char-replacement\": \"\",\n" -" \"hostname-char-set\": \"\",\n" " \"max-queue-size\": 1024,\n" " \"ncr-format\": \"JSON\",\n" " \"ncr-protocol\": \"UDP\",\n" @@ -3958,8 +3918,6 @@ const char* UNPARSED_CONFIGS[] = { " \"dhcp-ddns\": {\n" " \"enable-updates\": false,\n" " \"generated-prefix\": \"myhost\",\n" -" \"hostname-char-replacement\": \"\",\n" -" \"hostname-char-set\": \"\",\n" " \"max-queue-size\": 1024,\n" " \"ncr-format\": \"JSON\",\n" " \"ncr-protocol\": \"UDP\",\n" @@ -4071,8 +4029,6 @@ const char* UNPARSED_CONFIGS[] = { " \"dhcp-ddns\": {\n" " \"enable-updates\": false,\n" " \"generated-prefix\": \"myhost\",\n" -" \"hostname-char-replacement\": \"\",\n" -" \"hostname-char-set\": \"\",\n" " \"max-queue-size\": 1024,\n" " \"ncr-format\": \"JSON\",\n" " \"ncr-protocol\": \"UDP\",\n" @@ -4194,8 +4150,6 @@ const char* UNPARSED_CONFIGS[] = { " \"dhcp-ddns\": {\n" " \"enable-updates\": false,\n" " \"generated-prefix\": \"myhost\",\n" -" \"hostname-char-replacement\": \"\",\n" -" \"hostname-char-set\": \"\",\n" " \"max-queue-size\": 1024,\n" " \"ncr-format\": \"JSON\",\n" " \"ncr-protocol\": \"UDP\",\n" @@ -4300,8 +4254,6 @@ const char* UNPARSED_CONFIGS[] = { " \"dhcp-ddns\": {\n" " \"enable-updates\": false,\n" " \"generated-prefix\": \"myhost\",\n" -" \"hostname-char-replacement\": \"\",\n" -" \"hostname-char-set\": \"\",\n" " \"max-queue-size\": 1024,\n" " \"ncr-format\": \"JSON\",\n" " \"ncr-protocol\": \"UDP\",\n" @@ -4449,8 +4401,6 @@ const char* UNPARSED_CONFIGS[] = { " \"dhcp-ddns\": {\n" " \"enable-updates\": false,\n" " \"generated-prefix\": \"myhost\",\n" -" \"hostname-char-replacement\": \"\",\n" -" \"hostname-char-set\": \"\",\n" " \"max-queue-size\": 1024,\n" " \"ncr-format\": \"JSON\",\n" " \"ncr-protocol\": \"UDP\",\n" @@ -4588,8 +4538,6 @@ const char* UNPARSED_CONFIGS[] = { " \"dhcp-ddns\": {\n" " \"enable-updates\": false,\n" " \"generated-prefix\": \"myhost\",\n" -" \"hostname-char-replacement\": \"\",\n" -" \"hostname-char-set\": \"\",\n" " \"max-queue-size\": 1024,\n" " \"ncr-format\": \"JSON\",\n" " \"ncr-protocol\": \"UDP\",\n" @@ -4737,8 +4685,6 @@ const char* UNPARSED_CONFIGS[] = { " \"dhcp-ddns\": {\n" " \"enable-updates\": false,\n" " \"generated-prefix\": \"myhost\",\n" -" \"hostname-char-replacement\": \"\",\n" -" \"hostname-char-set\": \"\",\n" " \"max-queue-size\": 1024,\n" " \"ncr-format\": \"JSON\",\n" " \"ncr-protocol\": \"UDP\",\n" @@ -4848,8 +4794,6 @@ const char* UNPARSED_CONFIGS[] = { " \"dhcp-ddns\": {\n" " \"enable-updates\": false,\n" " \"generated-prefix\": \"myhost\",\n" -" \"hostname-char-replacement\": \"\",\n" -" \"hostname-char-set\": \"\",\n" " \"max-queue-size\": 1024,\n" " \"ncr-format\": \"JSON\",\n" " \"ncr-protocol\": \"UDP\",\n" @@ -4963,8 +4907,6 @@ const char* UNPARSED_CONFIGS[] = { " \"dhcp-ddns\": {\n" " \"enable-updates\": false,\n" " \"generated-prefix\": \"myhost\",\n" -" \"hostname-char-replacement\": \"\",\n" -" \"hostname-char-set\": \"\",\n" " \"max-queue-size\": 1024,\n" " \"ncr-format\": \"JSON\",\n" " \"ncr-protocol\": \"UDP\",\n" @@ -5033,8 +4975,6 @@ const char* UNPARSED_CONFIGS[] = { " \"dhcp-ddns\": {\n" " \"enable-updates\": false,\n" " \"generated-prefix\": \"myhost\",\n" -" \"hostname-char-replacement\": \"\",\n" -" \"hostname-char-set\": \"\",\n" " \"max-queue-size\": 1024,\n" " \"ncr-format\": \"JSON\",\n" " \"ncr-protocol\": \"UDP\",\n" @@ -5103,8 +5043,6 @@ const char* UNPARSED_CONFIGS[] = { " \"dhcp-ddns\": {\n" " \"enable-updates\": false,\n" " \"generated-prefix\": \"myhost\",\n" -" \"hostname-char-replacement\": \"\",\n" -" \"hostname-char-set\": \"\",\n" " \"max-queue-size\": 1024,\n" " \"ncr-format\": \"JSON\",\n" " \"ncr-protocol\": \"UDP\",\n" @@ -5199,8 +5137,6 @@ const char* UNPARSED_CONFIGS[] = { " \"dhcp-ddns\": {\n" " \"enable-updates\": false,\n" " \"generated-prefix\": \"myhost\",\n" -" \"hostname-char-replacement\": \"\",\n" -" \"hostname-char-set\": \"\",\n" " \"max-queue-size\": 1024,\n" " \"ncr-format\": \"JSON\",\n" " \"ncr-protocol\": \"UDP\",\n" @@ -5295,8 +5231,6 @@ const char* UNPARSED_CONFIGS[] = { " \"dhcp-ddns\": {\n" " \"enable-updates\": false,\n" " \"generated-prefix\": \"myhost\",\n" -" \"hostname-char-replacement\": \"\",\n" -" \"hostname-char-set\": \"\",\n" " \"max-queue-size\": 1024,\n" " \"ncr-format\": \"JSON\",\n" " \"ncr-protocol\": \"UDP\",\n" @@ -5469,8 +5403,6 @@ const char* UNPARSED_CONFIGS[] = { " \"dhcp-ddns\": {\n" " \"enable-updates\": false,\n" " \"generated-prefix\": \"myhost\",\n" -" \"hostname-char-replacement\": \"\",\n" -" \"hostname-char-set\": \"\",\n" " \"max-queue-size\": 1024,\n" " \"ncr-format\": \"JSON\",\n" " \"ncr-protocol\": \"UDP\",\n" @@ -5580,8 +5512,6 @@ const char* UNPARSED_CONFIGS[] = { " \"dhcp-ddns\": {\n" " \"enable-updates\": false,\n" " \"generated-prefix\": \"myhost\",\n" -" \"hostname-char-replacement\": \"\",\n" -" \"hostname-char-set\": \"\",\n" " \"max-queue-size\": 1024,\n" " \"ncr-format\": \"JSON\",\n" " \"ncr-protocol\": \"UDP\",\n" @@ -5795,8 +5725,6 @@ const char* UNPARSED_CONFIGS[] = { " \"dhcp-ddns\": {\n" " \"enable-updates\": false,\n" " \"generated-prefix\": \"myhost\",\n" -" \"hostname-char-replacement\": \"\",\n" -" \"hostname-char-set\": \"\",\n" " \"max-queue-size\": 1024,\n" " \"ncr-format\": \"JSON\",\n" " \"ncr-protocol\": \"UDP\",\n" @@ -6016,8 +5944,6 @@ const char* UNPARSED_CONFIGS[] = { " \"dhcp-ddns\": {\n" " \"enable-updates\": false,\n" " \"generated-prefix\": \"myhost\",\n" -" \"hostname-char-replacement\": \"\",\n" -" \"hostname-char-set\": \"\",\n" " \"max-queue-size\": 1024,\n" " \"ncr-format\": \"JSON\",\n" " \"ncr-protocol\": \"UDP\",\n" @@ -6135,8 +6061,6 @@ const char* UNPARSED_CONFIGS[] = { " \"dhcp-ddns\": {\n" " \"enable-updates\": false,\n" " \"generated-prefix\": \"myhost\",\n" -" \"hostname-char-replacement\": \"\",\n" -" \"hostname-char-set\": \"\",\n" " \"max-queue-size\": 1024,\n" " \"ncr-format\": \"JSON\",\n" " \"ncr-protocol\": \"UDP\",\n" @@ -6205,8 +6129,6 @@ const char* UNPARSED_CONFIGS[] = { " \"dhcp-ddns\": {\n" " \"enable-updates\": false,\n" " \"generated-prefix\": \"myhost\",\n" -" \"hostname-char-replacement\": \"\",\n" -" \"hostname-char-set\": \"\",\n" " \"max-queue-size\": 1024,\n" " \"ncr-format\": \"JSON\",\n" " \"ncr-protocol\": \"UDP\",\n" @@ -6275,8 +6197,6 @@ const char* UNPARSED_CONFIGS[] = { " \"dhcp-ddns\": {\n" " \"enable-updates\": false,\n" " \"generated-prefix\": \"myhost\",\n" -" \"hostname-char-replacement\": \"\",\n" -" \"hostname-char-set\": \"\",\n" " \"max-queue-size\": 1024,\n" " \"ncr-format\": \"JSON\",\n" " \"ncr-protocol\": \"UDP\",\n" @@ -6471,8 +6391,6 @@ const char* UNPARSED_CONFIGS[] = { " \"dhcp-ddns\": {\n" " \"enable-updates\": false,\n" " \"generated-prefix\": \"myhost\",\n" -" \"hostname-char-replacement\": \"\",\n" -" \"hostname-char-set\": \"\",\n" " \"max-queue-size\": 1024,\n" " \"ncr-format\": \"JSON\",\n" " \"ncr-protocol\": \"UDP\",\n" @@ -6592,8 +6510,6 @@ const char* UNPARSED_CONFIGS[] = { " \"dhcp-ddns\": {\n" " \"enable-updates\": false,\n" " \"generated-prefix\": \"myhost\",\n" -" \"hostname-char-replacement\": \"\",\n" -" \"hostname-char-set\": \"\",\n" " \"max-queue-size\": 1024,\n" " \"ncr-format\": \"JSON\",\n" " \"ncr-protocol\": \"UDP\",\n" @@ -6662,8 +6578,6 @@ const char* UNPARSED_CONFIGS[] = { " \"dhcp-ddns\": {\n" " \"enable-updates\": false,\n" " \"generated-prefix\": \"myhost\",\n" -" \"hostname-char-replacement\": \"\",\n" -" \"hostname-char-set\": \"\",\n" " \"max-queue-size\": 1024,\n" " \"ncr-format\": \"JSON\",\n" " \"ncr-protocol\": \"UDP\",\n" @@ -6730,8 +6644,6 @@ const char* UNPARSED_CONFIGS[] = { " \"dhcp-ddns\": {\n" " \"enable-updates\": false,\n" " \"generated-prefix\": \"myhost\",\n" -" \"hostname-char-replacement\": \"\",\n" -" \"hostname-char-set\": \"\",\n" " \"max-queue-size\": 1024,\n" " \"ncr-format\": \"JSON\",\n" " \"ncr-protocol\": \"UDP\",\n" @@ -6798,8 +6710,6 @@ const char* UNPARSED_CONFIGS[] = { " \"dhcp-ddns\": {\n" " \"enable-updates\": false,\n" " \"generated-prefix\": \"myhost\",\n" -" \"hostname-char-replacement\": \"\",\n" -" \"hostname-char-set\": \"\",\n" " \"max-queue-size\": 1024,\n" " \"ncr-format\": \"JSON\",\n" " \"ncr-protocol\": \"UDP\",\n" @@ -6866,8 +6776,6 @@ const char* UNPARSED_CONFIGS[] = { " \"dhcp-ddns\": {\n" " \"enable-updates\": false,\n" " \"generated-prefix\": \"myhost\",\n" -" \"hostname-char-replacement\": \"\",\n" -" \"hostname-char-set\": \"\",\n" " \"max-queue-size\": 1024,\n" " \"ncr-format\": \"JSON\",\n" " \"ncr-protocol\": \"UDP\",\n" @@ -6948,8 +6856,6 @@ const char* UNPARSED_CONFIGS[] = { " \"dhcp-ddns\": {\n" " \"enable-updates\": false,\n" " \"generated-prefix\": \"myhost\",\n" -" \"hostname-char-replacement\": \"\",\n" -" \"hostname-char-set\": \"\",\n" " \"max-queue-size\": 1024,\n" " \"ncr-format\": \"JSON\",\n" " \"ncr-protocol\": \"UDP\",\n" @@ -7044,8 +6950,6 @@ const char* UNPARSED_CONFIGS[] = { " \"dhcp-ddns\": {\n" " \"enable-updates\": false,\n" " \"generated-prefix\": \"myhost\",\n" -" \"hostname-char-replacement\": \"\",\n" -" \"hostname-char-set\": \"\",\n" " \"max-queue-size\": 1024,\n" " \"ncr-format\": \"JSON\",\n" " \"ncr-protocol\": \"UDP\",\n" @@ -7140,8 +7044,6 @@ const char* UNPARSED_CONFIGS[] = { " \"dhcp-ddns\": {\n" " \"enable-updates\": false,\n" " \"generated-prefix\": \"myhost\",\n" -" \"hostname-char-replacement\": \"\",\n" -" \"hostname-char-set\": \"\",\n" " \"max-queue-size\": 1024,\n" " \"ncr-format\": \"JSON\",\n" " \"ncr-protocol\": \"UDP\",\n" @@ -7237,8 +7139,6 @@ const char* UNPARSED_CONFIGS[] = { " \"dhcp-ddns\": {\n" " \"enable-updates\": false,\n" " \"generated-prefix\": \"myhost\",\n" -" \"hostname-char-replacement\": \"\",\n" -" \"hostname-char-set\": \"\",\n" " \"max-queue-size\": 1024,\n" " \"ncr-format\": \"JSON\",\n" " \"ncr-protocol\": \"UDP\",\n" @@ -7339,8 +7239,6 @@ const char* UNPARSED_CONFIGS[] = { " \"dhcp-ddns\": {\n" " \"enable-updates\": false,\n" " \"generated-prefix\": \"myhost\",\n" -" \"hostname-char-replacement\": \"\",\n" -" \"hostname-char-set\": \"\",\n" " \"max-queue-size\": 1024,\n" " \"ncr-format\": \"JSON\",\n" " \"ncr-protocol\": \"UDP\",\n" @@ -7441,8 +7339,6 @@ const char* UNPARSED_CONFIGS[] = { " \"dhcp-ddns\": {\n" " \"enable-updates\": false,\n" " \"generated-prefix\": \"myhost\",\n" -" \"hostname-char-replacement\": \"\",\n" -" \"hostname-char-set\": \"\",\n" " \"max-queue-size\": 1024,\n" " \"ncr-format\": \"JSON\",\n" " \"ncr-protocol\": \"UDP\",\n" @@ -7539,8 +7435,6 @@ const char* UNPARSED_CONFIGS[] = { " \"dhcp-ddns\": {\n" " \"enable-updates\": false,\n" " \"generated-prefix\": \"myhost\",\n" -" \"hostname-char-replacement\": \"\",\n" -" \"hostname-char-set\": \"\",\n" " \"max-queue-size\": 1024,\n" " \"ncr-format\": \"JSON\",\n" " \"ncr-protocol\": \"UDP\",\n" @@ -7638,8 +7532,6 @@ const char* UNPARSED_CONFIGS[] = { " \"dhcp-ddns\": {\n" " \"enable-updates\": false,\n" " \"generated-prefix\": \"myhost\",\n" -" \"hostname-char-replacement\": \"\",\n" -" \"hostname-char-set\": \"\",\n" " \"max-queue-size\": 1024,\n" " \"ncr-format\": \"JSON\",\n" " \"ncr-protocol\": \"UDP\",\n" @@ -7742,8 +7634,6 @@ const char* UNPARSED_CONFIGS[] = { " \"dhcp-ddns\": {\n" " \"enable-updates\": false,\n" " \"generated-prefix\": \"myhost\",\n" -" \"hostname-char-replacement\": \"\",\n" -" \"hostname-char-set\": \"\",\n" " \"max-queue-size\": 1024,\n" " \"ncr-format\": \"JSON\",\n" " \"ncr-protocol\": \"UDP\",\n" @@ -7853,8 +7743,6 @@ const char* UNPARSED_CONFIGS[] = { " \"comment\": \"No dynamic DNS\",\n" " \"enable-updates\": false,\n" " \"generated-prefix\": \"myhost\",\n" -" \"hostname-char-replacement\": \"\",\n" -" \"hostname-char-set\": \"\",\n" " \"max-queue-size\": 1024,\n" " \"ncr-format\": \"JSON\",\n" " \"ncr-protocol\": \"UDP\",\n" @@ -8016,8 +7904,6 @@ const char* UNPARSED_CONFIGS[] = { " \"dhcp-ddns\": {\n" " \"enable-updates\": false,\n" " \"generated-prefix\": \"myhost\",\n" -" \"hostname-char-replacement\": \"\",\n" -" \"hostname-char-set\": \"\",\n" " \"max-queue-size\": 1024,\n" " \"ncr-format\": \"JSON\",\n" " \"ncr-protocol\": \"UDP\",\n" diff --git a/src/lib/dhcpsrv/d2_client_cfg.cc b/src/lib/dhcpsrv/d2_client_cfg.cc index 520cd3ce9b..0433aef08f 100644 --- a/src/lib/dhcpsrv/d2_client_cfg.cc +++ b/src/lib/dhcpsrv/d2_client_cfg.cc @@ -8,6 +8,7 @@ #include #include +#include #include #include diff --git a/src/lib/dhcpsrv/d2_client_cfg.h b/src/lib/dhcpsrv/d2_client_cfg.h index bd88cb4631..4fdec9c81c 100644 --- a/src/lib/dhcpsrv/d2_client_cfg.h +++ b/src/lib/dhcpsrv/d2_client_cfg.h @@ -295,10 +295,11 @@ public: /// @return a pointer to unparsed configuration virtual isc::data::ElementPtr toElement() const; -protected: /// @brief Validates member values. /// /// Method is used by the constructor to validate member contents. + /// Should be called when parsing is complete to (re)compute + /// the hostname sanitizer. /// /// @throw D2ClientError if given an invalid protocol or format. virtual void validateContents(); diff --git a/src/lib/dhcpsrv/parsers/dhcp_parsers.cc b/src/lib/dhcpsrv/parsers/dhcp_parsers.cc index 9e62161bce..a920754db0 100644 --- a/src/lib/dhcpsrv/parsers/dhcp_parsers.cc +++ b/src/lib/dhcpsrv/parsers/dhcp_parsers.cc @@ -1493,7 +1493,7 @@ D2ClientConfigParser::parse(isc::data::ConstElementPtr client_config) { // parameters to a subnet we need to set a callback function for // the d2 client config to allow for fetching global parameters. new_config->setFetchGlobalsFn([]() -> ConstElementPtr { - return (CfgMgr::instance().getCurrentCfg()->getConfiguredGlobals()); + return (CfgMgr::instance().getStagingCfg()->getConfiguredGlobals()); }); return(new_config); diff --git a/src/lib/dhcpsrv/parsers/simple_parser6.cc b/src/lib/dhcpsrv/parsers/simple_parser6.cc index 0e744e2e26..4d907db92b 100644 --- a/src/lib/dhcpsrv/parsers/simple_parser6.cc +++ b/src/lib/dhcpsrv/parsers/simple_parser6.cc @@ -70,7 +70,9 @@ const SimpleKeywords SimpleParser6::GLOBAL6_PARAMETERS = { { "calculate-tee-times", Element::boolean }, { "t1-percent", Element::real }, { "t2-percent", Element::real }, - { "loggers", Element::list } + { "loggers", Element::list }, + { "hostname-char-set", Element::string }, + { "hostname-char-replacement", Element::string } }; /// @brief This table defines default values for option definitions in DHCPv6. diff --git a/src/lib/dhcpsrv/tests/d2_client_unittest.cc b/src/lib/dhcpsrv/tests/d2_client_unittest.cc index bedd42b0c4..e1b59a4429 100644 --- a/src/lib/dhcpsrv/tests/d2_client_unittest.cc +++ b/src/lib/dhcpsrv/tests/d2_client_unittest.cc @@ -1,4 +1,4 @@ -// Copyright (C) 2012-2018 Internet Systems Consortium, Inc. ("ISC") +// Copyright (C) 2012-2019 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 @@ -127,7 +127,9 @@ TEST(D2ClientConfigTest, constructorsAndAccessors) { EXPECT_EQ(d2_client_config->getGeneratedPrefix(), generated_prefix); EXPECT_EQ(d2_client_config->getQualifyingSuffix(), qualifying_suffix); + EXPECT_FALSE(d2_client_config->getHostnameCharSet().unspecified()); EXPECT_EQ(d2_client_config->getHostnameCharSet(), hostname_char_set); + EXPECT_FALSE(d2_client_config->getHostnameCharReplacement().unspecified()); EXPECT_EQ(d2_client_config->getHostnameCharReplacement(), hostname_char_replacement); EXPECT_TRUE(d2_client_config->getHostnameSanitizer()); @@ -180,6 +182,53 @@ TEST(D2ClientConfigTest, constructorsAndAccessors) { hostname_char_replacement)), D2ClientError); + Optional opt_hostname_char_set("", true); + Optional opt_hostname_char_replacement("", true); + + // Veeify that constructor handles optional hostname char stuff. + ASSERT_NO_THROW(d2_client_config.reset(new + D2ClientConfig(enable_updates, + server_ip, + server_port, + sender_ip, + sender_port, + max_queue_size, + ncr_protocol, + ncr_format, + override_no_update, + override_client_update, + replace_client_name_mode, + generated_prefix, + qualifying_suffix, + opt_hostname_char_set, + opt_hostname_char_replacement))); + ASSERT_TRUE(d2_client_config); + + // Verify that the accessors return the expected values. + EXPECT_TRUE(d2_client_config->getHostnameCharSet().unspecified()); + EXPECT_EQ(d2_client_config->getHostnameCharSet(), opt_hostname_char_set); + EXPECT_TRUE(d2_client_config->getHostnameCharReplacement().unspecified()); + EXPECT_EQ(d2_client_config->getHostnameCharReplacement(), opt_hostname_char_replacement); + EXPECT_FALSE(d2_client_config->getHostnameSanitizer()); + + // Verify what toElement returns. + expected = "{\n" + "\"enable-updates\": true,\n" + "\"server-ip\": \"127.0.0.1\",\n" + "\"server-port\": 477,\n" + "\"sender-ip\": \"127.0.0.1\",\n" + "\"sender-port\": 478,\n" + "\"max-queue-size\": 2048,\n" + "\"ncr-protocol\": \"UDP\",\n" + "\"ncr-format\": \"JSON\",\n" + "\"override-no-update\": true,\n" + "\"override-client-update\": true,\n" + "\"replace-client-name\": \"when-present\",\n" + "\"generated-prefix\": \"the_prefix\",\n" + "\"qualifying-suffix\": \"the.suffix.\"\n" + "}\n"; + runToElementTest(expected, *d2_client_config); + /// @todo if additional validation is added to ctor, this test needs to /// expand accordingly. } diff --git a/src/lib/dhcpsrv/tests/dhcp_parsers_unittest.cc b/src/lib/dhcpsrv/tests/dhcp_parsers_unittest.cc index 57f2171113..231af76def 100644 --- a/src/lib/dhcpsrv/tests/dhcp_parsers_unittest.cc +++ b/src/lib/dhcpsrv/tests/dhcp_parsers_unittest.cc @@ -216,6 +216,14 @@ public: continue; } + // Save global hostname-char-*. + if ((config_pair.first == "hostname-char-set") || + (config_pair.first == "hostname-char-replacement")) { + CfgMgr::instance().getStagingCfg()->addConfiguredGlobal(config_pair.first, + config_pair.second); + continue; + } + if (config_pair.first == "hooks-libraries") { HooksLibrariesParser hook_parser; HooksConfig& libraries = @@ -254,6 +262,7 @@ public: // Used to be done by parser commit D2ClientConfigParser parser; D2ClientConfigPtr cfg = parser.parse(d2_client_config->second); + cfg->validateContents(); CfgMgr::instance().setD2ClientConfig(cfg); } @@ -1683,13 +1692,13 @@ TEST_F(ParseConfigTest, hexOptionData) { "0C:00:03:01:C0:00:03:02", // colons "0x0C000301C0000302", // 0x "C 0 3 1 C0 0 3 02", // one or two digit octets - "0x0c000301C0000302" // upper or lower case digits + "0x0c000301C0000302" // upper or lower case digits }; for (auto hex_str : valid_hexes) { - ostringstream os; + ostringstream os; os << - "{ \n" + "{ \n" " \"option-data\": [ { \n" " \"name\": \"domain-name-servers\", \n" " \"code \": 6, \n" @@ -2261,6 +2270,11 @@ TEST_F(ParseConfigTest, validD2Config) { EXPECT_EQ("test.suffix.", d2_client_config->getQualifyingSuffix()); ASSERT_TRUE(d2_client_config->getContext()); EXPECT_EQ("{ \"foo\": \"bar\" }", d2_client_config->getContext()->str()); + EXPECT_FALSE(d2_client_config->getHostnameCharSet().unspecified()); + EXPECT_EQ("[^A-Z]", d2_client_config->getHostnameCharSet().get()); + EXPECT_FALSE(d2_client_config->getHostnameCharReplacement().unspecified()); + EXPECT_EQ("*", d2_client_config->getHostnameCharReplacement().get()); + EXPECT_TRUE(d2_client_config->getHostnameSanitizer()); // Verify that the configuration object unparses. ConstElementPtr expected; @@ -2315,6 +2329,251 @@ TEST_F(ParseConfigTest, validD2Config) { EXPECT_EQ("", d2_client_config->getQualifyingSuffix()); ASSERT_TRUE(d2_client_config->getContext()); EXPECT_EQ("{ \"foo\": \"bar\" }", d2_client_config->getContext()->str()); + EXPECT_FALSE(d2_client_config->getHostnameCharSet().unspecified()); + EXPECT_EQ("[^A-Z]", d2_client_config->getHostnameCharSet().get()); + EXPECT_FALSE(d2_client_config->getHostnameCharReplacement().unspecified()); + EXPECT_EQ("*", d2_client_config->getHostnameCharReplacement().get()); + EXPECT_TRUE(d2_client_config->getHostnameSanitizer()); + + ASSERT_NO_THROW(expected = Element::fromJSON(config_str2)->get("dhcp-ddns")); + ASSERT_TRUE(expected); + runToElementTest(expected, *d2_client_config); +} + +/// @brief Checks that a valid, enabled D2 client configuration works correctly +/// with hostname-char stuff moved to global. +TEST_F(ParseConfigTest, validD2ConfigGlobal) { + + // Configuration string containing valid values. + std::string config_str = + "{ \"dhcp-ddns\" :" + " {" + " \"enable-updates\" : true, " + " \"server-ip\" : \"192.0.2.0\", " + " \"server-port\" : 3432, " + " \"sender-ip\" : \"192.0.2.1\", " + " \"sender-port\" : 3433, " + " \"max-queue-size\" : 2048, " + " \"ncr-protocol\" : \"UDP\", " + " \"ncr-format\" : \"JSON\", " + " \"override-no-update\" : true, " + " \"override-client-update\" : true, " + " \"replace-client-name\" : \"when-present\", " + " \"generated-prefix\" : \"test.prefix\", " + " \"qualifying-suffix\" : \"test.suffix.\", " + " \"user-context\": { \"foo\": \"bar\" } " + " }," + " \"hostname-char-set\" : \"[^A-Z]\", " + " \"hostname-char-replacement\" : \"*\" " + "}"; + + // Verify that the configuration string parses. + int rcode = parseConfiguration(config_str); + ASSERT_TRUE(rcode == 0) << error_text_; + + // Verify that DHCP-DDNS is enabled and we can fetch the configuration. + EXPECT_TRUE(CfgMgr::instance().ddnsEnabled()); + D2ClientConfigPtr d2_client_config; + ASSERT_NO_THROW(d2_client_config = CfgMgr::instance().getD2ClientConfig()); + ASSERT_TRUE(d2_client_config); + + // Verify that the configuration values are as expected. + EXPECT_TRUE(d2_client_config->getEnableUpdates()); + EXPECT_EQ("192.0.2.0", d2_client_config->getServerIp().toText()); + EXPECT_EQ(3432, d2_client_config->getServerPort()); + EXPECT_EQ(dhcp_ddns::NCR_UDP, d2_client_config->getNcrProtocol()); + EXPECT_EQ(dhcp_ddns::FMT_JSON, d2_client_config->getNcrFormat()); + EXPECT_TRUE(d2_client_config->getOverrideNoUpdate()); + EXPECT_TRUE(d2_client_config->getOverrideClientUpdate()); + EXPECT_EQ(D2ClientConfig::RCM_WHEN_PRESENT, d2_client_config->getReplaceClientNameMode()); + EXPECT_EQ("test.prefix", d2_client_config->getGeneratedPrefix()); + EXPECT_EQ("test.suffix.", d2_client_config->getQualifyingSuffix()); + ASSERT_TRUE(d2_client_config->getContext()); + EXPECT_EQ("{ \"foo\": \"bar\" }", d2_client_config->getContext()->str()); + EXPECT_FALSE(d2_client_config->getHostnameCharSet().unspecified()); + EXPECT_EQ("[^A-Z]", d2_client_config->getHostnameCharSet().get()); + EXPECT_FALSE(d2_client_config->getHostnameCharReplacement().unspecified()); + EXPECT_EQ("*", d2_client_config->getHostnameCharReplacement().get()); + EXPECT_TRUE(d2_client_config->getHostnameSanitizer()); + + // Verify that the configuration object unparses. + ConstElementPtr expected; + ASSERT_NO_THROW(expected = Element::fromJSON(config_str)->get("dhcp-ddns")); + ASSERT_TRUE(expected); + runToElementTest(expected, *d2_client_config); + + // Another valid Configuration string. + // This one is disabled, has IPV6 server ip, control flags false, + // empty prefix/suffix + std::string config_str2 = + "{ \"dhcp-ddns\" :" + " {" + " \"enable-updates\" : false, " + " \"server-ip\" : \"2001:db8::\", " + " \"server-port\" : 43567, " + " \"sender-ip\" : \"2001:db8::1\", " + " \"sender-port\" : 3433, " + " \"max-queue-size\" : 2048, " + " \"ncr-protocol\" : \"UDP\", " + " \"ncr-format\" : \"JSON\", " + " \"override-no-update\" : false, " + " \"override-client-update\" : false, " + " \"replace-client-name\" : \"never\", " + " \"generated-prefix\" : \"\", " + " \"qualifying-suffix\" : \"\", " + " \"user-context\": { \"foo\": \"bar\" } " + " }," + " \"hostname-char-set\" : \"[^A-Z]\", " + " \"hostname-char-replacement\" : \"*\" " + "}"; + + // Verify that the configuration string parses. + rcode = parseConfiguration(config_str2); + ASSERT_TRUE(rcode == 0) << error_text_; + + // Verify that DHCP-DDNS is disabled and we can fetch the configuration. + EXPECT_FALSE(CfgMgr::instance().ddnsEnabled()); + ASSERT_NO_THROW(d2_client_config = CfgMgr::instance().getD2ClientConfig()); + ASSERT_TRUE(d2_client_config); + + // Verify that the configuration values are as expected. + EXPECT_FALSE(d2_client_config->getEnableUpdates()); + EXPECT_EQ("2001:db8::", d2_client_config->getServerIp().toText()); + EXPECT_EQ(43567, d2_client_config->getServerPort()); + EXPECT_EQ(dhcp_ddns::NCR_UDP, d2_client_config->getNcrProtocol()); + EXPECT_EQ(dhcp_ddns::FMT_JSON, d2_client_config->getNcrFormat()); + EXPECT_FALSE(d2_client_config->getOverrideNoUpdate()); + EXPECT_FALSE(d2_client_config->getOverrideClientUpdate()); + EXPECT_EQ(D2ClientConfig::RCM_NEVER, d2_client_config->getReplaceClientNameMode()); + EXPECT_EQ("", d2_client_config->getGeneratedPrefix()); + EXPECT_EQ("", d2_client_config->getQualifyingSuffix()); + ASSERT_TRUE(d2_client_config->getContext()); + EXPECT_EQ("{ \"foo\": \"bar\" }", d2_client_config->getContext()->str()); + EXPECT_FALSE(d2_client_config->getHostnameCharSet().unspecified()); + EXPECT_EQ("[^A-Z]", d2_client_config->getHostnameCharSet().get()); + EXPECT_FALSE(d2_client_config->getHostnameCharReplacement().unspecified()); + EXPECT_EQ("*", d2_client_config->getHostnameCharReplacement().get()); + EXPECT_TRUE(d2_client_config->getHostnameSanitizer()); + + ASSERT_NO_THROW(expected = Element::fromJSON(config_str2)->get("dhcp-ddns")); + ASSERT_TRUE(expected); + runToElementTest(expected, *d2_client_config); +} + +/// @brief Checks that a valid, enabled D2 client configuration works correctly +/// with hostname-char stuff in both local and global (local has the priority). +TEST_F(ParseConfigTest, validD2ConfigBoth) { + + // Configuration string containing valid values. + std::string config_str = + "{ \"dhcp-ddns\" :" + " {" + " \"enable-updates\" : true, " + " \"server-ip\" : \"192.0.2.0\", " + " \"server-port\" : 3432, " + " \"sender-ip\" : \"192.0.2.1\", " + " \"sender-port\" : 3433, " + " \"max-queue-size\" : 2048, " + " \"ncr-protocol\" : \"UDP\", " + " \"ncr-format\" : \"JSON\", " + " \"override-no-update\" : true, " + " \"override-client-update\" : true, " + " \"replace-client-name\" : \"when-present\", " + " \"generated-prefix\" : \"test.prefix\", " + " \"qualifying-suffix\" : \"test.suffix.\", " + " \"user-context\": { \"foo\": \"bar\" } " + " }," + " \"hostname-char-set\" : \"[^A-Z]\", " + " \"hostname-char-replacement\" : \"*\" " + "}"; + + // Verify that the configuration string parses. + int rcode = parseConfiguration(config_str); + ASSERT_TRUE(rcode == 0) << error_text_; + + // Verify that DHCP-DDNS is enabled and we can fetch the configuration. + EXPECT_TRUE(CfgMgr::instance().ddnsEnabled()); + D2ClientConfigPtr d2_client_config; + ASSERT_NO_THROW(d2_client_config = CfgMgr::instance().getD2ClientConfig()); + ASSERT_TRUE(d2_client_config); + + // Verify that the configuration values are as expected. + EXPECT_TRUE(d2_client_config->getEnableUpdates()); + EXPECT_EQ("192.0.2.0", d2_client_config->getServerIp().toText()); + EXPECT_EQ(3432, d2_client_config->getServerPort()); + EXPECT_EQ(dhcp_ddns::NCR_UDP, d2_client_config->getNcrProtocol()); + EXPECT_EQ(dhcp_ddns::FMT_JSON, d2_client_config->getNcrFormat()); + EXPECT_TRUE(d2_client_config->getOverrideNoUpdate()); + EXPECT_TRUE(d2_client_config->getOverrideClientUpdate()); + EXPECT_EQ(D2ClientConfig::RCM_WHEN_PRESENT, d2_client_config->getReplaceClientNameMode()); + EXPECT_EQ("test.prefix", d2_client_config->getGeneratedPrefix()); + EXPECT_EQ("test.suffix.", d2_client_config->getQualifyingSuffix()); + ASSERT_TRUE(d2_client_config->getContext()); + EXPECT_EQ("{ \"foo\": \"bar\" }", d2_client_config->getContext()->str()); + EXPECT_FALSE(d2_client_config->getHostnameCharSet().unspecified()); + EXPECT_EQ("[^A-Z]", d2_client_config->getHostnameCharSet().get()); + EXPECT_FALSE(d2_client_config->getHostnameCharReplacement().unspecified()); + EXPECT_EQ("*", d2_client_config->getHostnameCharReplacement().get()); + EXPECT_TRUE(d2_client_config->getHostnameSanitizer()); + + // Verify that the configuration object unparses. + ConstElementPtr expected; + ASSERT_NO_THROW(expected = Element::fromJSON(config_str)->get("dhcp-ddns")); + ASSERT_TRUE(expected); + runToElementTest(expected, *d2_client_config); + + // Another valid Configuration string. + // This one is disabled, has IPV6 server ip, control flags false, + // empty prefix/suffix + std::string config_str2 = + "{ \"dhcp-ddns\" :" + " {" + " \"enable-updates\" : false, " + " \"server-ip\" : \"2001:db8::\", " + " \"server-port\" : 43567, " + " \"sender-ip\" : \"2001:db8::1\", " + " \"sender-port\" : 3433, " + " \"max-queue-size\" : 2048, " + " \"ncr-protocol\" : \"UDP\", " + " \"ncr-format\" : \"JSON\", " + " \"override-no-update\" : false, " + " \"override-client-update\" : false, " + " \"replace-client-name\" : \"never\", " + " \"generated-prefix\" : \"\", " + " \"qualifying-suffix\" : \"\", " + " \"user-context\": { \"foo\": \"bar\" } " + " }," + " \"hostname-char-set\" : \"[^A-Z]\", " + " \"hostname-char-replacement\" : \"*\" " + "}"; + + // Verify that the configuration string parses. + rcode = parseConfiguration(config_str2); + ASSERT_TRUE(rcode == 0) << error_text_; + + // Verify that DHCP-DDNS is disabled and we can fetch the configuration. + EXPECT_FALSE(CfgMgr::instance().ddnsEnabled()); + ASSERT_NO_THROW(d2_client_config = CfgMgr::instance().getD2ClientConfig()); + ASSERT_TRUE(d2_client_config); + + // Verify that the configuration values are as expected. + EXPECT_FALSE(d2_client_config->getEnableUpdates()); + EXPECT_EQ("2001:db8::", d2_client_config->getServerIp().toText()); + EXPECT_EQ(43567, d2_client_config->getServerPort()); + EXPECT_EQ(dhcp_ddns::NCR_UDP, d2_client_config->getNcrProtocol()); + EXPECT_EQ(dhcp_ddns::FMT_JSON, d2_client_config->getNcrFormat()); + EXPECT_FALSE(d2_client_config->getOverrideNoUpdate()); + EXPECT_FALSE(d2_client_config->getOverrideClientUpdate()); + EXPECT_EQ(D2ClientConfig::RCM_NEVER, d2_client_config->getReplaceClientNameMode()); + EXPECT_EQ("", d2_client_config->getGeneratedPrefix()); + EXPECT_EQ("", d2_client_config->getQualifyingSuffix()); + ASSERT_TRUE(d2_client_config->getContext()); + EXPECT_EQ("{ \"foo\": \"bar\" }", d2_client_config->getContext()->str()); + EXPECT_FALSE(d2_client_config->getHostnameCharSet().unspecified()); + EXPECT_EQ("[^A-Z]", d2_client_config->getHostnameCharSet().get()); + EXPECT_FALSE(d2_client_config->getHostnameCharReplacement().unspecified()); + EXPECT_EQ("*", d2_client_config->getHostnameCharReplacement().get()); + EXPECT_TRUE(d2_client_config->getHostnameSanitizer()); ASSERT_NO_THROW(expected = Element::fromJSON(config_str2)->get("dhcp-ddns")); ASSERT_TRUE(expected); @@ -2345,6 +2604,36 @@ TEST_F(ParseConfigTest, validDisabledD2Config) { ASSERT_NO_THROW(d2_client_config = CfgMgr::instance().getD2ClientConfig()); EXPECT_TRUE(d2_client_config); EXPECT_FALSE(d2_client_config->getEnableUpdates()); + EXPECT_TRUE(d2_client_config->getHostnameCharSet().unspecified()); + EXPECT_TRUE(d2_client_config->getHostnameCharReplacement().unspecified()); + EXPECT_FALSE(d2_client_config->getHostnameSanitizer()); + + // Retry with hostname-char-* globals. + std::string config_str2 = + "{ \"dhcp-ddns\" :" + " {" + " \"enable-updates\" : false" + " }," + " \"hostname-char-set\" : \"[^A-Z]\", " + " \"hostname-char-replacement\" : \"*\" " + "}"; + + // Verify that the configuration string parses. + rcode = parseConfiguration(config_str2); + ASSERT_TRUE(rcode == 0) << error_text_; + + // Verify that DHCP-DDNS is disabled. + EXPECT_FALSE(CfgMgr::instance().ddnsEnabled()); + + // Make sure fetched config agrees. + ASSERT_NO_THROW(d2_client_config = CfgMgr::instance().getD2ClientConfig()); + EXPECT_TRUE(d2_client_config); + EXPECT_FALSE(d2_client_config->getEnableUpdates()); + EXPECT_FALSE(d2_client_config->getHostnameCharSet().unspecified()); + EXPECT_EQ("[^A-Z]", d2_client_config->getHostnameCharSet().get()); + EXPECT_FALSE(d2_client_config->getHostnameCharReplacement().unspecified()); + EXPECT_EQ("*", d2_client_config->getHostnameCharReplacement().get()); + EXPECT_TRUE(d2_client_config->getHostnameSanitizer()); } /// @brief Checks that given a partial configuration, parser supplies @@ -2394,6 +2683,11 @@ TEST_F(ParseConfigTest, parserDefaultsD2Config) { d2_client_config->getGeneratedPrefix()); EXPECT_EQ("test.suffix.", d2_client_config->getQualifyingSuffix()); + EXPECT_TRUE(d2_client_config->getHostnameCharSet().unspecified()); + EXPECT_TRUE(d2_client_config->getHostnameCharSet().empty()); + EXPECT_TRUE(d2_client_config->getHostnameCharReplacement().unspecified()); + EXPECT_TRUE(d2_client_config->getHostnameCharReplacement().empty()); + EXPECT_FALSE(d2_client_config->getHostnameSanitizer()); }