Commit 256feda6 authored by Thomas Markwalder's avatar Thomas Markwalder

[#35,!517] Rework kea-dhcp4 parsing and server

src/bin/dhcp4/ctrl_dhcp4_srv.cc
    Removed setting D2ClientCfg fetch function

src/bin/dhcp4/dhcp4_lexer.ll
src/bin/dhcp4/dhcp4_parser.yy
    ddns-send-updates
    ddns-override-no-update
    ddns-override-client-update
    ddns-replace-client-name
    ddns-generated-prefix
    ddns-qualifying-suffix
        - added to DHCP4,SHARED_NETWORK,SUBNET4

    hostname-char-set
    hostname-char-replacement
        - added to SHARED_NETWORK,SUBNET4

src/bin/dhcp4/dhcp4_srv.cc

    Dhcpv4Srv::processClientFqdnOption()
    Dhcpv4Srv::processHostnameOption()
    Dhcpv4Srv::assignLease()
        Use scoped DdnsParams from context to make decisions, pass
        into D2ClientMgr functions, and supply hostname sanitizer

src/bin/dhcp4/json_config_parser.cc
    configureDhcp4Server()
    - use SrvConfig::moveDdnsParams() to move dhcp-ddns parameters
    - handle new "ddns-" globals

src/bin/dhcp4/tests/config_parser_unittest.cc
src/bin/dhcp4/tests/d2_unittest.cc
src/bin/dhcp4/tests/dhcp4_test_utils.cc
src/bin/dhcp4/tests/fqdn_unittest.cc
src/bin/dhcp4/tests/get_config_unittest.cc
    Updated and new tests
parent 77cfe4bc
......@@ -374,12 +374,6 @@ 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 {
......
This diff is collapsed.
......@@ -663,6 +663,72 @@ ControlCharacterFill [^"\\]|\\{JSONEscapeSequence}
}
}
\"ddns-send-updates\" {
switch(driver.ctx_) {
case isc::dhcp::Parser4Context::DHCP4:
case isc::dhcp::Parser4Context::SUBNET4:
case isc::dhcp::Parser4Context::SHARED_NETWORK:
return isc::dhcp::Dhcp4Parser::make_DDNS_SEND_UPDATES(driver.loc_);
default:
return isc::dhcp::Dhcp4Parser::make_STRING("ddns-send-updates", driver.loc_);
}
}
\"ddns-override-no-update\" {
switch(driver.ctx_) {
case isc::dhcp::Parser4Context::DHCP4:
case isc::dhcp::Parser4Context::SUBNET4:
case isc::dhcp::Parser4Context::SHARED_NETWORK:
return isc::dhcp::Dhcp4Parser::make_DDNS_OVERRIDE_NO_UPDATE(driver.loc_);
default:
return isc::dhcp::Dhcp4Parser::make_STRING("ddns-override-no-update", driver.loc_);
}
}
\"ddns-override-client-update\" {
switch(driver.ctx_) {
case isc::dhcp::Parser4Context::DHCP4:
case isc::dhcp::Parser4Context::SUBNET4:
case isc::dhcp::Parser4Context::SHARED_NETWORK:
return isc::dhcp::Dhcp4Parser::make_DDNS_OVERRIDE_CLIENT_UPDATE(driver.loc_);
default:
return isc::dhcp::Dhcp4Parser::make_STRING("ddns-override-client-update", driver.loc_);
}
}
\"ddns-replace-client-name\" {
switch(driver.ctx_) {
case isc::dhcp::Parser4Context::DHCP4:
case isc::dhcp::Parser4Context::SUBNET4:
case isc::dhcp::Parser4Context::SHARED_NETWORK:
return isc::dhcp::Dhcp4Parser::make_DDNS_REPLACE_CLIENT_NAME(driver.loc_);
default:
return isc::dhcp::Dhcp4Parser::make_STRING("ddns-replace-client-name", driver.loc_);
}
}
\"ddns-generated-prefix\" {
switch(driver.ctx_) {
case isc::dhcp::Parser4Context::DHCP4:
case isc::dhcp::Parser4Context::SUBNET4:
case isc::dhcp::Parser4Context::SHARED_NETWORK:
return isc::dhcp::Dhcp4Parser::make_DDNS_GENERATED_PREFIX(driver.loc_);
default:
return isc::dhcp::Dhcp4Parser::make_STRING("ddns-generated-prefix", driver.loc_);
}
}
\"ddns-qualifying-suffix\" {
switch(driver.ctx_) {
case isc::dhcp::Parser4Context::DHCP4:
case isc::dhcp::Parser4Context::SUBNET4:
case isc::dhcp::Parser4Context::SHARED_NETWORK:
return isc::dhcp::Dhcp4Parser::make_DDNS_QUALIFYING_SUFFIX(driver.loc_);
default:
return isc::dhcp::Dhcp4Parser::make_STRING("ddns-qualifying-suffix", driver.loc_);
}
}
\"subnet4\" {
switch(driver.ctx_) {
case isc::dhcp::Parser4Context::DHCP4:
......@@ -1489,6 +1555,8 @@ ControlCharacterFill [^"\\]|\\{JSONEscapeSequence}
switch(driver.ctx_) {
case isc::dhcp::Parser4Context::DHCP4:
case isc::dhcp::Parser4Context::DHCP_DDNS:
case isc::dhcp::Parser4Context::SUBNET4:
case isc::dhcp::Parser4Context::SHARED_NETWORK:
return isc::dhcp::Dhcp4Parser::make_HOSTNAME_CHAR_SET(driver.loc_);
default:
return isc::dhcp::Dhcp4Parser::make_STRING("hostname-char-set", driver.loc_);
......@@ -1499,6 +1567,8 @@ ControlCharacterFill [^"\\]|\\{JSONEscapeSequence}
switch(driver.ctx_) {
case isc::dhcp::Parser4Context::DHCP4:
case isc::dhcp::Parser4Context::DHCP_DDNS:
case isc::dhcp::Parser4Context::SUBNET4:
case isc::dhcp::Parser4Context::SHARED_NETWORK:
return isc::dhcp::Dhcp4Parser::make_HOSTNAME_CHAR_REPLACEMENT(driver.loc_);
default:
return isc::dhcp::Dhcp4Parser::make_STRING("hostname-char-replacement", driver.loc_);
......
This diff is collapsed.
This diff is collapsed.
......@@ -112,6 +112,12 @@ using namespace std;
T2_PERCENT "t2-percent"
DECLINE_PROBATION_PERIOD "decline-probation-period"
SERVER_TAG "server-tag"
DDNS_SEND_UPDATES "ddns-send-updates"
DDNS_OVERRIDE_NO_UPDATE "ddns-override-no-update"
DDNS_OVERRIDE_CLIENT_UPDATE "ddns-override-client-update"
DDNS_REPLACE_CLIENT_NAME "ddns-replace-client-name"
DDNS_GENERATED_PREFIX "ddns-generated-prefix"
DDNS_QUALIFYING_SUFFIX "ddns-qualifying-suffix"
SUBNET4 "subnet4"
SUBNET_4O6_INTERFACE "4o6-interface"
SUBNET_4O6_INTERFACE_ID "4o6-interface-id"
......@@ -252,7 +258,7 @@ using namespace std;
%type <ElementPtr> db_type
%type <ElementPtr> hr_mode
%type <ElementPtr> ncr_protocol_value
%type <ElementPtr> replace_client_name_value
%type <ElementPtr> ddns_replace_client_name_value
%printer { yyoutput << $$; } <*>;
......@@ -485,6 +491,12 @@ global_param: valid_lifetime
| loggers
| hostname_char_set
| hostname_char_replacement
| ddns_send_updates
| ddns_override_no_update
| ddns_override_client_update
| ddns_replace_client_name
| ddns_generated_prefix
| ddns_qualifying_suffix
| unknown_map_entry
;
......@@ -556,6 +568,78 @@ authoritative: AUTHORITATIVE COLON BOOLEAN {
ctx.stack_.back()->set("authoritative", prf);
};
ddns_send_updates: DDNS_SEND_UPDATES COLON BOOLEAN {
ElementPtr b(new BoolElement($3, ctx.loc2pos(@3)));
ctx.stack_.back()->set("ddns-send-updates", b);
};
ddns_override_no_update: DDNS_OVERRIDE_NO_UPDATE COLON BOOLEAN {
ElementPtr b(new BoolElement($3, ctx.loc2pos(@3)));
ctx.stack_.back()->set("ddns-override-no-update", b);
};
ddns_override_client_update: DDNS_OVERRIDE_CLIENT_UPDATE COLON BOOLEAN {
ElementPtr b(new BoolElement($3, ctx.loc2pos(@3)));
ctx.stack_.back()->set("ddns-override-client-update", b);
};
ddns_replace_client_name: DDNS_REPLACE_CLIENT_NAME {
ctx.enter(ctx.REPLACE_CLIENT_NAME);
} COLON ddns_replace_client_name_value {
ctx.stack_.back()->set("ddns-replace-client-name", $4);
ctx.leave();
};
ddns_replace_client_name_value:
WHEN_PRESENT {
$$ = ElementPtr(new StringElement("when-present", ctx.loc2pos(@1)));
}
| NEVER {
$$ = ElementPtr(new StringElement("never", ctx.loc2pos(@1)));
}
| ALWAYS {
$$ = ElementPtr(new StringElement("always", ctx.loc2pos(@1)));
}
| WHEN_NOT_PRESENT {
$$ = ElementPtr(new StringElement("when-not-present", ctx.loc2pos(@1)));
}
| BOOLEAN {
error(@1, "boolean values for the replace-client-name are "
"no longer supported");
}
;
ddns_generated_prefix: DDNS_GENERATED_PREFIX {
ctx.enter(ctx.NO_KEYWORD);
} COLON STRING {
ElementPtr s(new StringElement($4, ctx.loc2pos(@4)));
ctx.stack_.back()->set("ddns-generated-prefix", s);
ctx.leave();
};
ddns_qualifying_suffix: DDNS_QUALIFYING_SUFFIX {
ctx.enter(ctx.NO_KEYWORD);
} COLON STRING {
ElementPtr s(new StringElement($4, ctx.loc2pos(@4)));
ctx.stack_.back()->set("ddns-qualifying-suffix", s);
ctx.leave();
};
hostname_char_set: HOSTNAME_CHAR_SET {
ctx.enter(ctx.NO_KEYWORD);
} COLON STRING {
ElementPtr s(new StringElement($4, ctx.loc2pos(@4)));
ctx.stack_.back()->set("hostname-char-set", s);
ctx.leave();
};
hostname_char_replacement: HOSTNAME_CHAR_REPLACEMENT {
ctx.enter(ctx.NO_KEYWORD);
} COLON STRING {
ElementPtr s(new StringElement($4, ctx.loc2pos(@4)));
ctx.stack_.back()->set("hostname-char-replacement", s);
ctx.leave();
};
interfaces_config: INTERFACES_CONFIG {
ElementPtr i(new MapElement(ctx.loc2pos(@1)));
......@@ -1135,6 +1219,14 @@ subnet4_param: valid_lifetime
| calculate_tee_times
| t1_percent
| t2_percent
| ddns_send_updates
| ddns_override_no_update
| ddns_override_client_update
| ddns_replace_client_name
| ddns_generated_prefix
| ddns_qualifying_suffix
| hostname_char_set
| hostname_char_replacement
| unknown_map_entry
;
......@@ -1271,6 +1363,14 @@ shared_network_param: name
| calculate_tee_times
| t1_percent
| t2_percent
| ddns_send_updates
| ddns_override_no_update
| ddns_override_client_update
| ddns_replace_client_name
| ddns_generated_prefix
| ddns_qualifying_suffix
| hostname_char_set
| hostname_char_replacement
| unknown_map_entry
;
......@@ -1983,7 +2083,6 @@ dhcp_ddns_params: dhcp_ddns_param
;
dhcp_ddns_param: enable_updates
| qualifying_suffix
| server_ip
| server_port
| sender_ip
......@@ -1991,12 +2090,13 @@ dhcp_ddns_param: enable_updates
| max_queue_size
| ncr_protocol
| ncr_format
| override_no_update
| override_client_update
| replace_client_name
| generated_prefix
| hostname_char_set
| hostname_char_replacement
| dep_override_no_update
| dep_override_client_update
| dep_replace_client_name
| dep_generated_prefix
| dep_qualifying_suffix
| dep_hostname_char_set
| dep_hostname_char_replacement
| user_context
| comment
| unknown_map_entry
......@@ -2007,14 +2107,6 @@ enable_updates: ENABLE_UPDATES COLON BOOLEAN {
ctx.stack_.back()->set("enable-updates", b);
};
qualifying_suffix: QUALIFYING_SUFFIX {
ctx.enter(ctx.NO_KEYWORD);
} COLON STRING {
ElementPtr s(new StringElement($4, ctx.loc2pos(@4)));
ctx.stack_.back()->set("qualifying-suffix", s);
ctx.leave();
};
server_ip: SERVER_IP {
ctx.enter(ctx.NO_KEYWORD);
} COLON STRING {
......@@ -2066,43 +2158,37 @@ ncr_format: NCR_FORMAT {
ctx.leave();
};
override_no_update: OVERRIDE_NO_UPDATE COLON BOOLEAN {
// Deprecated, moved to global/network scopes. Eventually it should be removed.
dep_qualifying_suffix: QUALIFYING_SUFFIX {
ctx.enter(ctx.NO_KEYWORD);
} COLON STRING {
ElementPtr s(new StringElement($4, ctx.loc2pos(@4)));
ctx.stack_.back()->set("qualifying-suffix", s);
ctx.leave();
};
// Deprecated, moved to global/network scopes. Eventually it should be removed.
dep_override_no_update: OVERRIDE_NO_UPDATE COLON BOOLEAN {
ElementPtr b(new BoolElement($3, ctx.loc2pos(@3)));
ctx.stack_.back()->set("override-no-update", b);
};
override_client_update: OVERRIDE_CLIENT_UPDATE COLON BOOLEAN {
// Deprecated, moved to global/network scopes. Eventually it should be removed.
dep_override_client_update: OVERRIDE_CLIENT_UPDATE COLON BOOLEAN {
ElementPtr b(new BoolElement($3, ctx.loc2pos(@3)));
ctx.stack_.back()->set("override-client-update", b);
};
replace_client_name: REPLACE_CLIENT_NAME {
// Deprecated, moved to global/network scopes. Eventually it should be removed.
dep_replace_client_name: REPLACE_CLIENT_NAME {
ctx.enter(ctx.REPLACE_CLIENT_NAME);
} COLON replace_client_name_value {
} COLON ddns_replace_client_name_value {
ctx.stack_.back()->set("replace-client-name", $4);
ctx.leave();
};
replace_client_name_value:
WHEN_PRESENT {
$$ = ElementPtr(new StringElement("when-present", ctx.loc2pos(@1)));
}
| NEVER {
$$ = ElementPtr(new StringElement("never", ctx.loc2pos(@1)));
}
| ALWAYS {
$$ = ElementPtr(new StringElement("always", ctx.loc2pos(@1)));
}
| WHEN_NOT_PRESENT {
$$ = ElementPtr(new StringElement("when-not-present", ctx.loc2pos(@1)));
}
| BOOLEAN {
error(@1, "boolean values for the replace-client-name are "
"no longer supported");
}
;
generated_prefix: GENERATED_PREFIX {
// Deprecated, moved to global/network scopes. Eventually it should be removed.
dep_generated_prefix: GENERATED_PREFIX {
ctx.enter(ctx.NO_KEYWORD);
} COLON STRING {
ElementPtr s(new StringElement($4, ctx.loc2pos(@4)));
......@@ -2110,7 +2196,8 @@ generated_prefix: GENERATED_PREFIX {
ctx.leave();
};
hostname_char_set: HOSTNAME_CHAR_SET {
// Deprecated, moved to global/network scopes. Eventually it should be removed.
dep_hostname_char_set: HOSTNAME_CHAR_SET {
ctx.enter(ctx.NO_KEYWORD);
} COLON STRING {
ElementPtr s(new StringElement($4, ctx.loc2pos(@4)));
......@@ -2118,7 +2205,8 @@ hostname_char_set: HOSTNAME_CHAR_SET {
ctx.leave();
};
hostname_char_replacement: HOSTNAME_CHAR_REPLACEMENT {
// Deprecated, moved to global/network scopes. Eventually it should be removed.
dep_hostname_char_replacement: HOSTNAME_CHAR_REPLACEMENT {
ctx.enter(ctx.NO_KEYWORD);
} COLON STRING {
ElementPtr s(new StringElement($4, ctx.loc2pos(@4)));
......
......@@ -1710,8 +1710,8 @@ Dhcpv4Srv::processClientFqdnOption(Dhcpv4Exchange& ex) {
// Set the server S, N, and O flags based on client's flags and
// current configuration.
D2ClientMgr& d2_mgr = CfgMgr::instance().getD2ClientMgr();
d2_mgr.adjustFqdnFlags<Option4ClientFqdn>(*fqdn, *fqdn_resp);
d2_mgr.adjustFqdnFlags<Option4ClientFqdn>(*fqdn, *fqdn_resp,
*(ex.getContext()->getDdnsParams()));
// Carry over the client's E flag.
fqdn_resp->setFlag(Option4ClientFqdn::FLAG_E,
fqdn->getFlag(Option4ClientFqdn::FLAG_E));
......@@ -1720,12 +1720,14 @@ Dhcpv4Srv::processClientFqdnOption(Dhcpv4Exchange& ex) {
!ex.getContext()->currentHost()->getHostname().empty()) {
D2ClientMgr& d2_mgr = CfgMgr::instance().getD2ClientMgr();
fqdn_resp->setDomainName(d2_mgr.qualifyName(ex.getContext()->currentHost()->getHostname(),
true), Option4ClientFqdn::FULL);
*(ex.getContext()->getDdnsParams()), true),
Option4ClientFqdn::FULL);
} else {
// Adjust the domain name based on domain name value and type sent by the
// client and current configuration.
d2_mgr.adjustDomainName<Option4ClientFqdn>(*fqdn, *fqdn_resp);
d2_mgr.adjustDomainName<Option4ClientFqdn>(*fqdn, *fqdn_resp,
*(ex.getContext()->getDdnsParams()));
}
// Add FQDN option to the response message. Note that, there may be some
......@@ -1797,9 +1799,8 @@ Dhcpv4Srv::processHostnameOption(Dhcpv4Exchange& ex) {
// send back a hostname option, send this option with a reserved
// name for this client.
if (should_send_hostname) {
std::string hostname =
d2_mgr.qualifyName(ctx->currentHost()->getHostname(), false);
std::string hostname = d2_mgr.qualifyName(ctx->currentHost()->getHostname(),
*(ex.getContext()->getDdnsParams()), false);
// Convert hostname to lower case.
boost::algorithm::to_lower(hostname);
......@@ -1822,9 +1823,8 @@ Dhcpv4Srv::processHostnameOption(Dhcpv4Exchange& ex) {
// hostname option to this client if the client has included hostname option
// but there is no reservation, or the configuration of the server requires
// that we send the option regardless.
D2ClientConfig::ReplaceClientNameMode replace_name_mode =
d2_mgr.getD2ClientConfig()->getReplaceClientNameMode();
D2ClientConfig::ReplaceClientNameMode replace_name_mode
= ex.getContext()->getDdnsParams()->replace_client_name_mode_;
// If we don't have a hostname then either we'll supply it or do nothing.
if (!opt_hostname) {
......@@ -1898,8 +1898,9 @@ Dhcpv4Srv::processHostnameOption(Dhcpv4Exchange& ex) {
opt_hostname_resp.reset(new OptionString(Option::V4, DHO_HOST_NAME, "."));
} else {
// Sanitize the name the client sent us, if we're configured to do so.
isc::util::str::StringSanitizerPtr sanitizer = d2_mgr.getD2ClientConfig()
->getHostnameSanitizer();
isc::util::str::StringSanitizerPtr sanitizer
= ex.getContext()->getDdnsParams()->getHostnameSanitizer();
if (sanitizer) {
hostname = sanitizer->scrub(hostname);
}
......@@ -1915,8 +1916,10 @@ Dhcpv4Srv::processHostnameOption(Dhcpv4Exchange& ex) {
// hostname. We don't want to append the trailing dot because
// we don't know whether the hostname is partial or not and some
// clients do not handle the hostnames with the trailing dot.
opt_hostname_resp.reset(new OptionString(Option::V4, DHO_HOST_NAME,
d2_mgr.qualifyName(hostname, false)));
opt_hostname_resp.reset(
new OptionString(Option::V4, DHO_HOST_NAME,
d2_mgr.qualifyName(hostname, *(ex.getContext()->getDdnsParams()),
false)));
} else {
opt_hostname_resp.reset(new OptionString(Option::V4, DHO_HOST_NAME, hostname));
}
......@@ -2222,7 +2225,7 @@ Dhcpv4Srv::assignLease(Dhcpv4Exchange& ex) {
lease->hostname_ = CfgMgr::instance().getD2ClientMgr()
.qualifyName(ctx->currentHost()->getHostname(),
static_cast<bool>(fqdn));
*(ex.getContext()->getDdnsParams()), static_cast<bool>(fqdn));
should_update = true;
// If there has been Client FQDN or Hostname option sent, but the
......@@ -2237,7 +2240,8 @@ Dhcpv4Srv::assignLease(Dhcpv4Exchange& ex) {
// the hostname. Whether the trailing dot is appended or not is
// controlled by the second argument to the generateFqdn().
lease->hostname_ = CfgMgr::instance().getD2ClientMgr()
.generateFqdn(lease->addr_, static_cast<bool>(fqdn));
.generateFqdn(lease->addr_, *(ex.getContext()->getDdnsParams()),
static_cast<bool>(fqdn));
LOG_DEBUG(ddns4_logger, DBG_DHCP4_DETAIL, DHCP4_RESPONSE_HOSTNAME_GENERATE)
.arg(query->getLabel())
......@@ -2288,9 +2292,10 @@ Dhcpv4Srv::assignLease(Dhcpv4Exchange& ex) {
// Set T1 and T2 per configuration.
setTeeTimes(lease, subnet, resp);
// Create NameChangeRequests if DDNS is enabled and this is a
// real allocation.
if (!fake_allocation && CfgMgr::instance().ddnsEnabled()) {
if (!fake_allocation && (ex.getContext()->getDdnsParams()->enable_updates_)) {
try {
LOG_DEBUG(ddns4_logger, DBG_DHCP4_DETAIL, DHCP4_NCR_CREATE)
.arg(query->getLabel());
......
......@@ -350,6 +350,12 @@ configureDhcp4Server(Dhcpv4Srv& server, isc::data::ConstElementPtr config_set,
// default values and will insert derived values as well.
mutable_cfg = boost::const_pointer_cast<Element>(config_set);
// Relocate dhcp-ddns parameters that have moved to global scope.
// Rule is that a global value overrides the dhcp-ddns value, so
// we need to do this before we apply global defaults.
// Note this is done for backward compatibilty.
srv_cfg->moveDdnsParams(mutable_cfg);
// Set all default values if not specified by the user.
SimpleParser4::setAllDefaults(mutable_cfg);
......@@ -563,8 +569,13 @@ configureDhcp4Server(Dhcpv4Srv& server, isc::data::ConstElementPtr config_set,
(config_pair.first == "t2-percent") ||
(config_pair.first == "loggers") ||
(config_pair.first == "hostname-char-set") ||
(config_pair.first == "hostname-char-replacement")) {
(config_pair.first == "hostname-char-replacement") ||
(config_pair.first == "ddns-send-updates") ||
(config_pair.first == "ddns-override-no-update") ||
(config_pair.first == "ddns-override-client-update") ||
(config_pair.first == "ddns-replace-client-name") ||
(config_pair.first == "ddns-generated-prefix") ||
(config_pair.first == "ddns-qualifying-suffix")) {
CfgMgr::instance().getStagingCfg()->addConfiguredGlobal(config_pair.first,
config_pair.second);
continue;
......@@ -593,9 +604,6 @@ configureDhcp4Server(Dhcpv4Srv& server, isc::data::ConstElementPtr config_set,
// 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);
......
// Generated 201908191237
// A Bison parser, made by GNU Bison 3.4.1.
// A Bison parser, made by GNU Bison 3.2.1.
// Locations for Bison parsers in C++
// Copyright (C) 2002-2015, 2018-2019 Free Software Foundation, Inc.
// Copyright (C) 2002-2015, 2018 Free Software Foundation, Inc.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
......@@ -55,10 +54,9 @@
# endif
# endif
#line 14 "dhcp4_parser.yy"
#line 14 "dhcp4_parser.yy" // location.cc:339
namespace isc { namespace dhcp {
#line 60 "location.hh"
#line 60 "location.hh" // location.cc:339
/// A point in a source file.
class position
{
......@@ -318,8 +316,7 @@ namespace isc { namespace dhcp {
return ostr;
}
#line 14 "dhcp4_parser.yy"
#line 14 "dhcp4_parser.yy" // location.cc:339
} } // isc::dhcp
#line 323 "location.hh"
#line 322 "location.hh" // location.cc:339
#endif // !YY_PARSER4_LOCATION_HH_INCLUDED
// Generated 201908191237
// A Bison parser, made by GNU Bison 3.4.1.
// A Bison parser, made by GNU Bison 3.2.1.
// Starting with Bison 3.2, this file is useless: the structure it
// used to define is now defined in "location.hh".
......
// Generated 201908191237
// A Bison parser, made by GNU Bison 3.4.1.
// A Bison parser, made by GNU Bison 3.2.1.
// Starting with Bison 3.2, this file is useless: the structure it
// used to define is now defined with the parser itself.
......
......@@ -796,6 +796,19 @@ public:
EXPECT_TRUE(pool);
}
template <typename ValueType>
void checkGlobal(const std::string name, ValueType value) {
ConstElementPtr param;
ConstElementPtr exp_value;
param = CfgMgr::instance().getStagingCfg()->getConfiguredGlobal(name);
ASSERT_TRUE(param) << "global: " << name << ", expected but not found";
ASSERT_NO_THROW(exp_value = Element::create(value));
EXPECT_TRUE(param->equals(*exp_value)) << "global: " << name
<< isc::data::prettyPrint(param)
<< " does not match expected: "
<< isc::data::prettyPrint(exp_value);
}
boost::scoped_ptr<Dhcpv4Srv> srv_; ///< DHCP4 server under test
int rcode_; ///< Return code from element parsing
ConstElementPtr comment_; ///< Reason for parse fail
......@@ -4212,10 +4225,8 @@ TEST_F(Dhcp4ParserTest, selectedInterfacesAndAddresses) {
EXPECT_FALSE(test_config.socketOpen("eth1", "192.0.2.5"));
}
// This test checks the ability of the server to parse a configuration
// containing a full, valid dhcp-ddns (D2ClientConfig) entry.
TEST_F(Dhcp4ParserTest, d2ClientConfig) {
// This test verifies that valid d2CliengConfig works correctly.
TEST_F(Dhcp4ParserTest, d2ClientConfigValid) {
ConstElementPtr status;
// Verify that the D2 configuration can be fetched and is set to disabled.
......@@ -4239,14 +4250,7 @@ TEST_F(Dhcp4ParserTest, d2ClientConfig) {
" \"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\" }, "
" \"ncr-format\" : \"JSON\"}, "
"\"valid-lifetime\": 4000 }";
// Convert the JSON string to configuration elements.
......@@ -4276,22 +4280,20 @@ TEST_F(Dhcp4ParserTest, d2ClientConfig) {
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());
// The following, deprecated dhcp-ddns parameters,
// should all have global default values.
checkGlobal("ddns-send-updates", true);
checkGlobal("ddns-override-no-update", false);
checkGlobal("ddns-override-client-update", false);
checkGlobal("ddns-replace-client-name", "never");
checkGlobal("ddns-generated-prefix", "myhost");
checkGlobal("ddns-qualifying-suffix", "");
}
// 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) {
// This test verifies that valid but deprecated dhcp-ddns parameters
// get moved to the global scope when they do not already exist there.
TEST_F(Dhcp4ParserTest, d2ClientConfigMoveToGlobal) {
ConstElementPtr status;
// Verify that the D2 configuration can be fetched and is set to disabled.
......@@ -4320,9 +4322,9 @@ TEST_F(Dhcp4ParserTest, d2ClientConfigGlobal) {
" \"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\", "
" \"qualifying-suffix\" : \"test.suffix.\", "
" \"hostname-char-set\" : \"[^A-Z]\", "
" \"hostname-char-replacement\" : \"x\" }, "
"\"valid-lifetime\": 4000 }";
// Convert the JSON string to configuration elements.
......@@ -4352,21 +4354,22 @@ TEST_F(Dhcp4ParserTest, d2ClientConfigGlobal) {
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());
// ddns-send-updates should be global default
checkGlobal("ddns-send-updates", true);
// The following should all have been moved from dhcp-ddns.
checkGlobal("ddns-override-no-update", true);
checkGlobal("ddns-override-client-update", true);
checkGlobal("ddns-replace-client-name", "when-present");
checkGlobal("ddns-generated-prefix", "test.prefix");
checkGlobal("ddns-qualifying-suffix", "test.suffix.");
checkGlobal("hostname-char-set", "[^A-Z]");
checkGlobal("hostname-char-replacement", "x");
}
// 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).
// This test verifies that explicit global values override deprecated
// dhcp-ddns parameters (i.e. global scope wins)
TEST_F(Dhcp4ParserTest, d2ClientConfigBoth) {
ConstElementPtr status;
......@@ -4392,15 +4395,21 @@ TEST_F(Dhcp4ParserTest, d2ClientConfigBoth) {
" \"max-queue-size\" : 2048, "
" \"ncr-protocol\" : \"UDP\", "
" \"ncr-format\" : \"JSON\", "
" \"override-no-update\" : true, "
" \"override-client-update\" : true, "
" \"override-no-update\" : false, "
" \"override-client-update\" : false, "
" \"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\", "
" \"generated-prefix\" : \"d2.prefix\", "
" \"qualifying-suffix\" : \"d2.suffix.\", "
" \"hostname-char-set\" : \"[^0-9]\", "
" \"hostname-char-replacement\" : \"z\" }, "
" \"ddns-send-updates\" : false, "
" \"ddns-override-no-update\" : true, "
" \"ddns-override-client-update\" : true, "
" \"ddns-replace-client-name\" : \"always\", "
" \"ddns-generated-prefix\" : \"global.prefix\", "
" \"ddns-qualifying-suffix\" : \"global.suffix.\", "