Commit ce14110b authored by Thomas Markwalder's avatar Thomas Markwalder

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

src/bin/dhcp6/ctrl_dhcp6_srv.cc
    Removed setting D2ClientCfg fetch function

src/bin/dhcp6/dhcp6_lexer.ll
src/bin/dhcp6/dhcp6_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/dhcp6/dhcp6_srv.cc
    Dhcpv6Srv::processClientFqdn()
    Dhcpv6Srv::createNameChangeRequests()
    Dhcpv6Srv::updateReservedFqdn()
    - use cxt.getDdnsParams()

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

src/bin/dhcp6/tests/config_parser_unittest.cc
src/bin/dhcp6/tests/fqdn_unittest.cc
src/bin/dhcp6/tests/get_config_unittest.cc
    Updated tests
parent 256feda6
......@@ -796,6 +796,9 @@ public:
EXPECT_TRUE(pool);
}
/// @brief Tests if the current config has a given global parameter value
/// @param name name of the global parameter expected to exist
/// @param value expected value of the global parameter
template <typename ValueType>
void checkGlobal(const std::string name, ValueType value) {
ConstElementPtr param;
......@@ -4281,6 +4284,9 @@ TEST_F(Dhcp4ParserTest, d2ClientConfigValid) {
EXPECT_EQ(dhcp_ddns::NCR_UDP, d2_client_config->getNcrProtocol());
EXPECT_EQ(dhcp_ddns::FMT_JSON, d2_client_config->getNcrFormat());
// ddns-send-updates should be global default
checkGlobal("ddns-send-updates", true);
// The following, deprecated dhcp-ddns parameters,
// should all have global default values.
checkGlobal("ddns-send-updates", true);
......
......@@ -332,8 +332,8 @@ public:
subnet_->setDdnsOverrideNoUpdate(mask & OVERRIDE_NO_UPDATE);
subnet_->setDdnsOverrideClientUpdate(mask & OVERRIDE_CLIENT_UPDATE);
subnet_->setDdnsReplaceClientNameMode((mask & REPLACE_CLIENT_NAME) ?
D2ClientConfig::RCM_WHEN_PRESENT
: D2ClientConfig::RCM_NEVER);
D2ClientConfig::RCM_WHEN_PRESENT
: D2ClientConfig::RCM_NEVER);
subnet_->setDdnsGeneratedPrefix("myhost");
subnet_->setDdnsQualifyingSuffix("example.com");
......
......@@ -375,13 +375,6 @@ ControlledDhcpv6Srv::commandConfigSetHandler(const string&,
isc::config::parseAnswer(rcode, result);
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 {
......
This diff is collapsed.
......@@ -310,6 +310,8 @@ ControlCharacterFill [^"\\]|\\{JSONEscapeSequence}
switch(driver.ctx_) {
case isc::dhcp::Parser6Context::DHCP6:
case isc::dhcp::Parser6Context::DHCP_DDNS:
case isc::dhcp::Parser6Context::SUBNET6:
case isc::dhcp::Parser6Context::SHARED_NETWORK:
return isc::dhcp::Dhcp6Parser::make_HOSTNAME_CHAR_SET(driver.loc_);
default:
return isc::dhcp::Dhcp6Parser::make_STRING("hostname-char-set", driver.loc_);
......@@ -320,6 +322,8 @@ ControlCharacterFill [^"\\]|\\{JSONEscapeSequence}
switch(driver.ctx_) {
case isc::dhcp::Parser6Context::DHCP6:
case isc::dhcp::Parser6Context::DHCP_DDNS:
case isc::dhcp::Parser6Context::SUBNET6:
case isc::dhcp::Parser6Context::SHARED_NETWORK:
return isc::dhcp::Dhcp6Parser::make_HOSTNAME_CHAR_REPLACEMENT(driver.loc_);
default:
return isc::dhcp::Dhcp6Parser::make_STRING("hostname-char-replacement", driver.loc_);
......@@ -892,6 +896,72 @@ ControlCharacterFill [^"\\]|\\{JSONEscapeSequence}
}
}
\"ddns-send-updates\" {
switch(driver.ctx_) {
case isc::dhcp::Parser6Context::DHCP6:
case isc::dhcp::Parser6Context::SUBNET6:
case isc::dhcp::Parser6Context::SHARED_NETWORK:
return isc::dhcp::Dhcp6Parser::make_DDNS_SEND_UPDATES(driver.loc_);
default:
return isc::dhcp::Dhcp6Parser::make_STRING("ddns-send-updates", driver.loc_);
}
}
\"ddns-override-no-update\" {
switch(driver.ctx_) {
case isc::dhcp::Parser6Context::DHCP6:
case isc::dhcp::Parser6Context::SUBNET6:
case isc::dhcp::Parser6Context::SHARED_NETWORK:
return isc::dhcp::Dhcp6Parser::make_DDNS_OVERRIDE_NO_UPDATE(driver.loc_);
default:
return isc::dhcp::Dhcp6Parser::make_STRING("ddns-override-no-update", driver.loc_);
}
}
\"ddns-override-client-update\" {
switch(driver.ctx_) {
case isc::dhcp::Parser6Context::DHCP6:
case isc::dhcp::Parser6Context::SUBNET6:
case isc::dhcp::Parser6Context::SHARED_NETWORK:
return isc::dhcp::Dhcp6Parser::make_DDNS_OVERRIDE_CLIENT_UPDATE(driver.loc_);
default:
return isc::dhcp::Dhcp6Parser::make_STRING("ddns-override-client-update", driver.loc_);
}
}
\"ddns-replace-client-name\" {
switch(driver.ctx_) {
case isc::dhcp::Parser6Context::DHCP6:
case isc::dhcp::Parser6Context::SUBNET6:
case isc::dhcp::Parser6Context::SHARED_NETWORK:
return isc::dhcp::Dhcp6Parser::make_DDNS_REPLACE_CLIENT_NAME(driver.loc_);
default:
return isc::dhcp::Dhcp6Parser::make_STRING("ddns-replace-client-name", driver.loc_);
}
}
\"ddns-generated-prefix\" {
switch(driver.ctx_) {
case isc::dhcp::Parser6Context::DHCP6:
case isc::dhcp::Parser6Context::SUBNET6:
case isc::dhcp::Parser6Context::SHARED_NETWORK:
return isc::dhcp::Dhcp6Parser::make_DDNS_GENERATED_PREFIX(driver.loc_);
default:
return isc::dhcp::Dhcp6Parser::make_STRING("ddns-generated-prefix", driver.loc_);
}
}
\"ddns-qualifying-suffix\" {
switch(driver.ctx_) {
case isc::dhcp::Parser6Context::DHCP6:
case isc::dhcp::Parser6Context::SUBNET6:
case isc::dhcp::Parser6Context::SHARED_NETWORK:
return isc::dhcp::Dhcp6Parser::make_DDNS_QUALIFYING_SUFFIX(driver.loc_);
default:
return isc::dhcp::Dhcp6Parser::make_STRING("ddns-qualifying-suffix", driver.loc_);
}
}
\"subnet6\" {
switch(driver.ctx_) {
case isc::dhcp::Parser6Context::DHCP6:
......
This diff is collapsed.
This diff is collapsed.
......@@ -99,6 +99,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"
SUBNET6 "subnet6"
OPTION_DEF "option-def"
OPTION_DATA "option-data"
......@@ -257,7 +263,7 @@ using namespace std;
%type <ElementPtr> hr_mode
%type <ElementPtr> duid_type
%type <ElementPtr> ncr_protocol_value
%type <ElementPtr> replace_client_name_value
%type <ElementPtr> ddns_replace_client_name_value
%printer { yyoutput << $$; } <*>;
......@@ -491,6 +497,12 @@ global_param: data_directory
| 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
;
......@@ -562,6 +574,79 @@ decline_probation_period: DECLINE_PROBATION_PERIOD COLON INTEGER {
ctx.stack_.back()->set("decline-probation-period", dpp);
};
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();
};
server_tag: SERVER_TAG {
ctx.enter(ctx.NO_KEYWORD);
} COLON STRING {
......@@ -1142,6 +1227,14 @@ subnet6_param: preferred_lifetime
| calculate_tee_times
| t1_percent
| t2_percent
| 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
;
......@@ -1268,6 +1361,14 @@ shared_network_param: name
| calculate_tee_times
| t1_percent
| t2_percent
| 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
;
......@@ -2108,12 +2209,12 @@ 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_hostname_char_set
| dep_hostname_char_replacement
| user_context
| comment
| unknown_map_entry
......@@ -2183,43 +2284,28 @@ 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_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)));
......@@ -2227,7 +2313,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)));
......@@ -2235,7 +2322,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)));
......
......@@ -1595,17 +1595,16 @@ void
Dhcpv6Srv::processClientFqdn(const Pkt6Ptr& question, const Pkt6Ptr& answer,
AllocEngine::ClientContext6& ctx) {
D2ClientMgr& d2_mgr = CfgMgr::instance().getD2ClientMgr();
DdnsParamsPtr ddns_params = ctx.getDdnsParams();
// Get Client FQDN Option from the client's message. If this option hasn't
// been included, do nothing.
Option6ClientFqdnPtr fqdn = boost::dynamic_pointer_cast<
Option6ClientFqdn>(question->getOption(D6O_CLIENT_FQDN));
if (!fqdn) {
D2ClientConfig::ReplaceClientNameMode replace_name_mode =
d2_mgr.getD2ClientConfig()->getReplaceClientNameMode();
if (d2_mgr.ddnsEnabled() &&
(replace_name_mode == D2ClientConfig::RCM_ALWAYS ||
replace_name_mode == D2ClientConfig::RCM_WHEN_NOT_PRESENT)) {
if (ddns_params->enable_updates_ &&
(ddns_params->replace_client_name_mode_ == D2ClientConfig::RCM_ALWAYS ||
ddns_params->replace_client_name_mode_ == D2ClientConfig::RCM_WHEN_NOT_PRESENT)) {
// Fabricate an empty "client" FQDN with flags requesting
// the server do all the updates. The flags will get modified
// below according the configuration options, the name will
......@@ -1635,19 +1634,19 @@ Dhcpv6Srv::processClientFqdn(const Pkt6Ptr& question, const Pkt6Ptr& answer,
// Set the server S, N, and O flags based on client's flags and
// current configuration.
d2_mgr.adjustFqdnFlags<Option6ClientFqdn>(*fqdn, *fqdn_resp);
d2_mgr.adjustFqdnFlags<Option6ClientFqdn>(*fqdn, *fqdn_resp, *ddns_params);
// If there's a reservation and it has a hostname specified, use it!
if (ctx.currentHost() && !ctx.currentHost()->getHostname().empty()) {
// Add the qualifying suffix.
// After #3765, this will only occur if the suffix is not empty.
fqdn_resp->setDomainName(d2_mgr.qualifyName(ctx.currentHost()->getHostname(),
true),
*ddns_params, true),
Option6ClientFqdn::FULL);
} else {
// Adjust the domain name based on domain name value and type sent by
// the client and current configuration.
d2_mgr.adjustDomainName<Option6ClientFqdn>(*fqdn, *fqdn_resp);
d2_mgr.adjustDomainName<Option6ClientFqdn>(*fqdn, *fqdn_resp, *ddns_params);
}
// Once we have the FQDN setup to use it for the lease hostname. This
......@@ -1668,7 +1667,7 @@ void
Dhcpv6Srv::createNameChangeRequests(const Pkt6Ptr& answer,
AllocEngine::ClientContext6& ctx) {
// Don't create NameChangeRequests if DNS updates are disabled.
if (!CfgMgr::instance().ddnsEnabled()) {
if (!(ctx.getDdnsParams()->enable_updates_)) {
return;
}
......@@ -3651,7 +3650,7 @@ Dhcpv6Srv::requiredClassify(const Pkt6Ptr& pkt, AllocEngine::ClientContext6& ctx
}
void
Dhcpv6Srv::updateReservedFqdn(const AllocEngine::ClientContext6& ctx,
Dhcpv6Srv::updateReservedFqdn(AllocEngine::ClientContext6& ctx,
const Pkt6Ptr& answer) {
if (!answer) {
isc_throw(isc::Unexpected, "an instance of the object encapsulating"
......@@ -3676,7 +3675,7 @@ Dhcpv6Srv::updateReservedFqdn(const AllocEngine::ClientContext6& ctx,
if (ctx.currentHost() &&
!ctx.currentHost()->getHostname().empty()) {
std::string new_name = CfgMgr::instance().getD2ClientMgr().
qualifyName(ctx.currentHost()->getHostname(), true);
qualifyName(ctx.currentHost()->getHostname(), *ctx.getDdnsParams(), true);
if (new_name != name) {
fqdn->setDomainName(new_name, Option6ClientFqdn::FULL);
......@@ -3723,7 +3722,7 @@ Dhcpv6Srv::generateFqdn(const Pkt6Ptr& answer,
// Get the IPv6 address acquired by the client.
IOAddress addr = iaaddr->getAddress();
std::string generated_name =
CfgMgr::instance().getD2ClientMgr().generateFqdn(addr);
CfgMgr::instance().getD2ClientMgr().generateFqdn(addr, *ctx.getDdnsParams());
LOG_DEBUG(ddns6_logger, DBG_DHCP6_DETAIL_DATA, DHCP6_DDNS_FQDN_GENERATED)
.arg(answer->getLabel())
......
......@@ -938,7 +938,7 @@ private:
///
/// @throw isc::Unexpected if specified message is NULL. This is treated
/// as a programmatic error.
void updateReservedFqdn(const AllocEngine::ClientContext6& ctx,
void updateReservedFqdn(AllocEngine::ClientContext6& ctx,
const Pkt6Ptr& answer);
/// @private
......
......@@ -451,6 +451,12 @@ configureDhcp6Server(Dhcpv6Srv& server, isc::data::ConstElementPtr config_set,
// Get the staging configuration.
srv_config = CfgMgr::instance().getStagingCfg();
// 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_config->moveDdnsParams(mutable_cfg);
// Set all default values if not specified by the user.
SimpleParser6::setAllDefaults(mutable_cfg);
......@@ -682,8 +688,13 @@ configureDhcp6Server(Dhcpv6Srv& 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;
......@@ -717,9 +728,6 @@ configureDhcp6Server(Dhcpv6Srv& 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_config->setD2ClientConfig(d2_client_cfg);
......
// Generated 201908191238
// 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 "dhcp6_parser.yy"
#line 14 "dhcp6_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 "dhcp6_parser.yy"
#line 14 "dhcp6_parser.yy" // location.cc:339
} } // isc::dhcp
#line 323 "location.hh"
#line 322 "location.hh" // location.cc:339
#endif // !YY_PARSER6_LOCATION_HH_INCLUDED
// Generated 201908191238
// 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 201908191238
// 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.
......
......@@ -967,6 +967,22 @@ public:
EXPECT_TRUE(pool);
}
/// @brief Tests if the current config has a given global parameter value
/// @param name name of the global parameter expected to exist
/// @param value expected value of the global parameter
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);
}
int rcode_; ///< Return code (see @ref isc::config::parseAnswer)
ControlledDhcpv6Srv srv_; ///< Instance of the ControlledDhcp6Srv used during tests
ConstElementPtr comment_; ///< Comment (see @ref isc::config::parseAnswer)
......@@ -4791,7 +4807,8 @@ TEST_F(Dhcp6ParserTest, d2ClientConfig) {
" \"sender-port\" : 778, "
" \"max-queue-size\" : 2048, "
" \"ncr-protocol\" : \"UDP\", "
" \"ncr-format\" : \"JSON\", "
" \"ncr-format\" : \"JSON\"}, "
#if 0
" \"override-no-update\" : true, "
" \"override-client-update\" : true, "
" \"replace-client-name\" : \"when-present\", "
......@@ -4799,6 +4816,7 @@ TEST_F(Dhcp6ParserTest, d2ClientConfig) {
" \"qualifying-suffix\" : \"test.suffix.\", "
" \"hostname-char-set\" : \"[^A-Za-z0-9_-]\", "
" \"hostname-char-replacement\" : \"x\" }, "
#endif
"\"valid-lifetime\": 4000 }";
// Convert the JSON string to configuration elements.
......@@ -4829,22 +4847,23 @@ TEST_F(Dhcp6ParserTest, 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());
// ddns-send-updates should be global default
checkGlobal("ddns-send-updates", true);
// 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(Dhcp6ParserTest, 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(Dhcp6ParserTest, d2ClientConfigMoveToGlobal) {
// 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());
......@@ -4873,9 +4892,9 @@ TEST_F(Dhcp6ParserTest, 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.
......@@ -4906,21 +4925,22 @@ TEST_F(Dhcp6ParserTest, 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(Dhcp6ParserTest, d2ClientConfigBoth) {
// Verify that the D2 configuration can be fetched and is set to disabled.
D2ClientConfigPtr d2_client_config = CfgMgr::instance().getD2ClientConfig();
......@@ -4946,15 +4966,21 @@ TEST_F(Dhcp6ParserTest, 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\", "