Commit 22c667a6 authored by Thomas Markwalder's avatar Thomas Markwalder
Browse files

[master] Merge branch 'trac3034'

b10-dhcp6 parses and uses ddns-dhcp configuration
parents a3e73038 fbcacb9e
......@@ -640,6 +640,8 @@ DhcpConfigParser* createGlobal6DhcpConfigParser(const std::string& config_id) {
parser = new DbAccessParser(config_id);
} else if (config_id.compare("hooks-libraries") == 0) {
parser = new HooksLibrariesParser(config_id);
} else if (config_id.compare("dhcp-ddns") == 0) {
parser = new D2ClientConfigParser(config_id);
} else {
isc_throw(NotImplemented,
"Parser error: Global configuration parameter not supported: "
......
......@@ -352,7 +352,94 @@
}
} ]
}
}
},
{ "item_name": "dhcp-ddns",
"item_type": "map",
"item_optional": false,
"item_default": {"enable-updates": false},
"item_description" : "Contains parameters pertaining DHCP-driven DDNS updates",
"map_item_spec": [
{
"item_name": "enable-updates",
"item_type": "boolean",
"item_optional": false,
"item_default": false,
"item_description" : "Enables DDNS update processing"
},
{
"item_name": "server-ip",
"item_type": "string",
"item_optional": true,
"item_default": "127.0.0.1",
"item_description" : "IP address of b10-dhcp-ddns (IPv4 or IPv6)"
},
{
"item_name": "server-port",
"item_type": "integer",
"item_optional": true,
"item_default": 53001,
"item_description" : "port number of b10-dhcp-ddns"
},
{
"item_name": "ncr-protocol",
"item_type": "string",
"item_optional": true,
"item_default": "UDP",
"item_description" : "Socket protocol to use with b10-dhcp-ddns"
},
{
"item_name": "ncr-format",
"item_type": "string",
"item_optional": true,
"item_default": "JSON",
"item_description" : "Format of the update request packet"
},
{
"item_name": "always-include-fqdn",
"item_type": "boolean",
"item_optional": true,
"item_default": false,
"item_description": "Enable always including the FQDN option in its response"
},
{
"item_name": "override-no-update",
"item_type": "boolean",
"item_optional": true,
"item_default": false,
"item_description": "Do update, even if client requested no updates with N flag"
},
{
"item_name": "override-client-update",
"item_type": "boolean",
"item_optional": true,
"item_default": false,
"item_description": "Server performs an update even if client requested delegation"
},
{
"item_name": "replace-client-name",
"item_type": "boolean",
"item_optional": true,
"item_default": false,
"item_description": "Should server replace the domain-name supplied by the client"
},
{
"item_name": "generated-prefix",
"item_type": "string",
"item_optional": true,
"item_default": "myhost",
"item_description": "Prefix to use when generating the client's name"
},
{
"item_name": "qualifying-suffix",
"item_type": "string",
"item_optional": true,
"item_default": "example.com",
"item_description": "Fully qualified domain-name suffix if partial name provided by client"
},
]
},
],
"commands": [
{
......
......@@ -102,31 +102,6 @@ namespace dhcp {
const std::string Dhcpv6Srv::VENDOR_CLASS_PREFIX("VENDOR_CLASS_");
namespace {
// The following constants describe server's behavior with respect to the
// DHCPv6 Client FQDN Option sent by a client. They will be removed
// when DDNS parameters for DHCPv6 are implemented with the ticket #3034.
// Enable AAAA RR update delegation to the client (Disabled).
const bool FQDN_ALLOW_CLIENT_UPDATE = false;
// Globally enable updates (Enabled).
const bool FQDN_ENABLE_UPDATE = true;
// The partial name generated for the client if empty name has been
// supplied.
const char* FQDN_GENERATED_PARTIAL_NAME = "myhost";
// Do update, even if client requested no updates with N flag (Disabled).
const bool FQDN_OVERRIDE_NO_UPDATE = false;
// Server performs an update when client requested delegation (Enabled).
const bool FQDN_OVERRIDE_CLIENT_UPDATE = true;
// The fully qualified domain-name suffix if partial name provided by
// a client.
const char* FQDN_PARTIAL_SUFFIX = "example.com";
// Should server replace the domain-name supplied by the client (Disabled).
const bool FQDN_REPLACE_CLIENT_NAME = false;
}
/// @brief file name of a server-id file
///
/// Server must store its duid in persistent storage that must not change
......@@ -1016,69 +991,18 @@ Dhcpv6Srv::processClientFqdn(const Pkt6Ptr& question, const Pkt6Ptr& answer) {
LOG_DEBUG(dhcp6_logger, DBG_DHCP6_DETAIL,
DHCP6_DDNS_RECEIVE_FQDN).arg(fqdn->toText());
// Prepare the FQDN option which will be included in the response to
// the client.
// Create the DHCPv6 Client FQDN Option to be included in the server's
// response to a client.
Option6ClientFqdnPtr fqdn_resp(new Option6ClientFqdn(*fqdn));
// RFC 4704, section 6. - all flags set to 0.
fqdn_resp->resetFlags();
// Conditions when N flag has to be set to indicate that server will not
// perform DNS updates:
// 1. Updates are globally disabled,
// 2. Client requested no update and server respects it,
// 3. Client requested that the AAAA update is delegated to the client but
// server neither respects delegation of updates nor it is configured
// to send update on its own when client requested delegation.
if (!FQDN_ENABLE_UPDATE ||
(fqdn->getFlag(Option6ClientFqdn::FLAG_N) &&
!FQDN_OVERRIDE_NO_UPDATE) ||
(!fqdn->getFlag(Option6ClientFqdn::FLAG_S) &&
!FQDN_ALLOW_CLIENT_UPDATE && !FQDN_OVERRIDE_CLIENT_UPDATE)) {
fqdn_resp->setFlag(Option6ClientFqdn::FLAG_N, true);
// Conditions when S flag is set to indicate that server will perform
// DNS update on its own:
// 1. Client requested that server performs DNS update and DNS updates are
// globally enabled
// 2. Client requested that server delegates AAAA update to the client but
// server doesn't respect delegation and it is configured to perform
// an update on its own when client requested delegation.
} else if (fqdn->getFlag(Option6ClientFqdn::FLAG_S) ||
(!fqdn->getFlag(Option6ClientFqdn::FLAG_S) &&
!FQDN_ALLOW_CLIENT_UPDATE && FQDN_OVERRIDE_CLIENT_UPDATE)) {
fqdn_resp->setFlag(Option6ClientFqdn::FLAG_S, true);
}
// Server MUST set the O flag if it has overridden the client's setting
// of S flag.
if (fqdn->getFlag(Option6ClientFqdn::FLAG_S) !=
fqdn_resp->getFlag(Option6ClientFqdn::FLAG_S)) {
fqdn_resp->setFlag(Option6ClientFqdn::FLAG_O, true);
}
// If client supplied partial or empty domain-name, server should
// generate one.
if (fqdn->getDomainNameType() == Option6ClientFqdn::PARTIAL) {
std::ostringstream name;
if (fqdn->getDomainName().empty() || FQDN_REPLACE_CLIENT_NAME) {
fqdn->setDomainName("", Option6ClientFqdn::PARTIAL);
} else {
name << fqdn->getDomainName();
name << "." << FQDN_PARTIAL_SUFFIX;
fqdn_resp->setDomainName(name.str(), Option6ClientFqdn::FULL);
}
// Server may be configured to replace a name supplied by a client,
// even if client supplied fully qualified domain-name.
} else if (FQDN_REPLACE_CLIENT_NAME) {
std::ostringstream name;
name << FQDN_GENERATED_PARTIAL_NAME << "." << FQDN_PARTIAL_SUFFIX;
fqdn_resp->setDomainName(name.str(), Option6ClientFqdn::FULL);
// 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<Option6ClientFqdn>(*fqdn, *fqdn_resp);
}
// 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);
// The FQDN has been processed successfully. Let's append it to the
// response to be sent to a client. Note that the Client FQDN option is
......@@ -1090,7 +1014,7 @@ Dhcpv6Srv::processClientFqdn(const Pkt6Ptr& question, const Pkt6Ptr& answer) {
void
Dhcpv6Srv::createNameChangeRequests(const Pkt6Ptr& answer) {
// Don't create NameChangeRequests if DNS updates are disabled.
if (!FQDN_ENABLE_UPDATE) {
if (!CfgMgr::instance().ddnsEnabled()) {
return;
}
......@@ -1177,7 +1101,7 @@ Dhcpv6Srv::createNameChangeRequests(const Pkt6Ptr& answer) {
void
Dhcpv6Srv::createRemovalNameChangeRequest(const Lease6Ptr& lease) {
// Don't create NameChangeRequests if DNS updates are disabled.
if (!FQDN_ENABLE_UPDATE) {
if (!CfgMgr::instance().ddnsEnabled()) {
return;
}
......@@ -1299,14 +1223,11 @@ Dhcpv6Srv::assignIA_NA(const Subnet6Ptr& subnet, const DuidPtr& duid,
Option6ClientFqdnPtr fqdn = boost::dynamic_pointer_cast<
Option6ClientFqdn>(answer->getOption(D6O_CLIENT_FQDN));
if (fqdn) {
// Flag S must not coexist with flag N being set to 1, so if S=1
// server takes responsibility for both reverse and forward updates.
// Otherwise, we have to check N.
/// @todo For now, we assert that if we are doing forward we are also
/// doing reverse.
if (fqdn->getFlag(Option6ClientFqdn::FLAG_S)) {
do_fwd = true;
do_rev = true;
} else if (!fqdn->getFlag(Option6ClientFqdn::FLAG_N)) {
do_rev = true;
}
}
// Set hostname only in case any of the updates is being performed.
......@@ -1557,11 +1478,11 @@ Dhcpv6Srv::renewIA_NA(const Subnet6Ptr& subnet, const DuidPtr& duid,
Option6ClientFqdnPtr fqdn = boost::dynamic_pointer_cast<
Option6ClientFqdn>(answer->getOption(D6O_CLIENT_FQDN));
if (fqdn) {
// For now, we assert that if we are doing forward we are also
// doing reverse.
if (fqdn->getFlag(Option6ClientFqdn::FLAG_S)) {
do_fwd = true;
do_rev = true;
} else if (!fqdn->getFlag(Option6ClientFqdn::FLAG_N)) {
do_rev = true;
}
}
......@@ -2501,17 +2422,8 @@ Dhcpv6Srv::generateFqdn(const Pkt6Ptr& answer) {
}
// Get the IPv6 address acquired by the client.
IOAddress addr = iaaddr->getAddress();
std::string hostname = addr.toText();
// Colons may not be ok for FQDNs so let's replace them with hyphens.
std::replace(hostname.begin(), hostname.end(), ':', '-');
std::ostringstream stream;
// The final FQDN consists of the partial domain name and the suffix.
// For example, if the acquired address is 2001:db8:1::2, the generated
// FQDN may be:
// host-2001-db8:1--2.example.com.
// where prefix 'host' should be configurable. The domain name suffix
// should also be configurable.
stream << "host-" << hostname << "." << FQDN_PARTIAL_SUFFIX << ".";
std::string generated_name =
CfgMgr::instance().getD2ClientMgr().generateFqdn(addr);
try {
// The lease has been acquired but the FQDN for this lease hasn't
// been updated in the lease database. We now have new FQDN
......@@ -2522,7 +2434,7 @@ Dhcpv6Srv::generateFqdn(const Pkt6Ptr& answer) {
Lease6Ptr lease =
LeaseMgrFactory::instance().getLease6(Lease::TYPE_NA, addr);
if (lease) {
lease->hostname_ = stream.str();
lease->hostname_ = generated_name;
LeaseMgrFactory::instance().updateLease6(lease);
} else {
......@@ -2533,13 +2445,12 @@ Dhcpv6Srv::generateFqdn(const Pkt6Ptr& answer) {
" client");
}
}
// Set the generated FQDN in the Client FQDN option.
fqdn->setDomainName(stream.str(), Option6ClientFqdn::FULL);
fqdn->setDomainName(generated_name, Option6ClientFqdn::FULL);
} catch (const Exception& ex) {
LOG_ERROR(dhcp6_logger, DHCP6_NAME_GEN_UPDATE_FAIL)
.arg(hostname)
.arg(addr.toText())
.arg(ex.what());
}
}
......
......@@ -405,6 +405,7 @@ protected:
/// objects and store them in the internal queue. Requests created by this
/// function are only adding or updating DNS records. In order to generate
/// requests for DNS records removal, use @c createRemovalNameChangeRequest.
/// If ddns updates are disabled, this method returns immediately.
///
/// @todo Add support for multiple IAADDR options in the IA_NA.
///
......@@ -422,6 +423,7 @@ protected:
/// Note that this function will not remove the entries which server hadn't
/// added. This is the case, when client performs forward DNS update on its
/// own.
/// If ddns updates are disabled, this method returns immediately.
///
/// @param lease A lease for which the the removal of corresponding DNS
/// records will be performed.
......
......@@ -347,6 +347,7 @@ public:
"\"renew-timer\": 1000, "
"\"valid-lifetime\": 4000, "
"\"subnet6\": [ ], "
"\"dhcp-ddns\": { \"enable-updates\" : false }, "
"\"option-def\": [ ], "
"\"option-data\": [ ] }";
static_cast<void>(executeConfiguration(config,
......@@ -3091,5 +3092,113 @@ TEST_F(Dhcp6ParserTest, classifySubnets) {
EXPECT_TRUE (subnets->at(3)->clientSupported(classes));
}
// This test checks the ability of the server to parse a configuration
// containing a full, valid dhcp-ddns (D2ClientConfig) entry.
TEST_F(Dhcp6ParserTest, d2ClientConfig) {
ConstElementPtr status;
// Verify that the D2 configuraiton 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 = "{ \"interfaces\": [ \"*\" ],"
"\"rebind-timer\": 2000, "
"\"renew-timer\": 1000, "
"\"subnet6\": [ { "
" \"pool\": [ \"2001:db8:1::/80\" ],"
" \"subnet\": \"2001:db8:1::/64\" } ], "
" \"dhcp-ddns\" : {"
" \"enable-updates\" : true, "
" \"server-ip\" : \"192.168.2.1\", "
" \"server-port\" : 777, "
" \"ncr-protocol\" : \"UDP\", "
" \"ncr-format\" : \"JSON\", "
" \"always-include-fqdn\" : true, "
" \"allow-client-update\" : true, "
" \"override-no-update\" : true, "
" \"override-client-update\" : true, "
" \"replace-client-name\" : true, "
" \"generated-prefix\" : \"test.prefix\", "
" \"qualifying-suffix\" : \"test.suffix.\" },"
"\"valid-lifetime\": 4000 }";
// Convert the JSON string to configuration elements.
ElementPtr config;
ASSERT_NO_THROW(config = Element::fromJSON(config_str));
// Pass the configuration in for parsing.
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("192.168.2.1", d2_client_config->getServerIp().toText());
EXPECT_EQ(777, 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->getAlwaysIncludeFqdn());
EXPECT_TRUE(d2_client_config->getOverrideNoUpdate());
EXPECT_TRUE(d2_client_config->getOverrideClientUpdate());
EXPECT_TRUE(d2_client_config->getReplaceClientName());
EXPECT_EQ("test.prefix", d2_client_config->getGeneratedPrefix());
EXPECT_EQ("test.suffix.", d2_client_config->getQualifyingSuffix());
}
// This test checks the ability of the server to handle a configuration
// containing an invalid dhcp-ddns (D2ClientConfig) entry.
TEST_F(Dhcp6ParserTest, invalidD2ClientConfig) {
ConstElementPtr status;
// Configuration string with an invalid D2 client config,
// "server-ip" is missing.
string config_str = "{ \"interfaces\": [ \"*\" ],"
"\"rebind-timer\": 2000, "
"\"renew-timer\": 1000, "
"\"subnet6\": [ { "
" \"pool\": [ \"2001:db8:1::/80\" ],"
" \"subnet\": \"2001:db8:1::/64\" } ], "
" \"dhcp-ddns\" : {"
" \"enable-updates\" : true, "
" \"server-port\" : 5301, "
" \"ncr-protocol\" : \"UDP\", "
" \"ncr-format\" : \"JSON\", "
" \"always-include-fqdn\" : true, "
" \"allow-client-update\" : true, "
" \"override-no-update\" : true, "
" \"override-client-update\" : true, "
" \"replace-client-name\" : true, "
" \"generated-prefix\" : \"test.prefix\", "
" \"qualifying-suffix\" : \"test.suffix.\" },"
"\"valid-lifetime\": 4000 }";
// Convert the JSON string to configuration elements.
ElementPtr config;
ASSERT_NO_THROW(config = Element::fromJSON(config_str));
// Configuration should not throw, but should fail.
EXPECT_NO_THROW(status = configureDhcp6Server(srv_, config));
// check if returned status is failed.
checkResult(status, 1);
// Verify that the D2 configuraiton 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());
}
};
......@@ -43,20 +43,63 @@ namespace {
/// @brief A test fixture class for testing DHCPv6 Client FQDN Option handling.
class FqdnDhcpv6SrvTest : public Dhcpv6SrvTest {
public:
// Reference to D2ClientMgr singleton
D2ClientMgr& d2_mgr_;
// Bit Constants for turning on and off DDNS configuration options.
// (Defined here as these are only meaningful to this class.)
static const uint16_t ALWAYS_INCLUDE_FQDN = 1;
static const uint16_t OVERRIDE_NO_UPDATE = 2;
static const uint16_t OVERRIDE_CLIENT_UPDATE = 4;
static const uint16_t REPLACE_CLIENT_NAME = 8;
/// @brief Constructor
FqdnDhcpv6SrvTest()
: Dhcpv6SrvTest() {
: Dhcpv6SrvTest(), d2_mgr_(CfgMgr::instance().getD2ClientMgr()) {
// generateClientId assigns DUID to duid_.
generateClientId();
lease_.reset(new Lease6(Lease::TYPE_NA, IOAddress("2001:db8:1::1"),
duid_, 1234, 501, 502, 503,
504, 1, 0));
// Config DDNS to be enabled, all controls off
enableD2();
}
/// @brief Destructor
virtual ~FqdnDhcpv6SrvTest() {
// Default constructor creates a config with DHCP-DDNS updates
// disabled.
D2ClientConfigPtr cfg(new D2ClientConfig());
CfgMgr::instance().setD2ClientConfig(cfg);
}
/// @brief Sets the server's DDNS configuration to ddns updates disabled.
void disableD2() {
// Default constructor creates a config with DHCP-DDNS updates
// disabled.
D2ClientConfigPtr cfg(new D2ClientConfig());
CfgMgr::instance().setD2ClientConfig(cfg);
}
/// @brief Enables DHCP-DDNS updates with the given options enabled.
///
/// Replaces the current D2ClientConfiguration with a configuration
/// which as updates enabled and the control options set based upon
/// the bit mask of options.
///
/// @param mask Bit mask of configuration options that should be enabled.
void enableD2(const uint16_t mask = 0) {
D2ClientConfigPtr cfg;
ASSERT_NO_THROW(cfg.reset(new D2ClientConfig(true,
isc::asiolink::IOAddress("127.0.0.1"), 53001,
dhcp_ddns::NCR_UDP, dhcp_ddns::FMT_JSON,
(mask & ALWAYS_INCLUDE_FQDN),
(mask & OVERRIDE_NO_UPDATE),
(mask & OVERRIDE_CLIENT_UPDATE),
(mask & REPLACE_CLIENT_NAME),
"myhost", "example.com")));
ASSERT_NO_THROW(CfgMgr::instance().setD2ClientConfig(cfg));
}
/// @brief Construct the DHCPv6 Client FQDN option using flags and
......@@ -376,6 +419,13 @@ public:
/// @param addr A string representation of the IPv6 address held in the
/// NameChangeRequest.
/// @param dhcid An expected DHCID value.
/// @note This value is the value that is produced by
/// dhcp_ddns::D2Dhcid::crateDigest() with the appropriate arguments. This
/// method uses encryption tools to produce the value which cannot be
/// easily duplicated by hand. It is more or less necessary to generate
/// these values programmatically and place them here. Should the
/// underlying implementation of createDigest() change these test values
/// will likely need to be updated as well.
/// @param expires A timestamp when the lease associated with the
/// NameChangeRequest expires.
/// @param len A valid lifetime of the lease associated with the
......@@ -443,6 +493,7 @@ TEST_F(FqdnDhcpv6SrvTest, noUpdate) {
// Test server's response when client requests that server delegates the AAAA
// update to the client and this delegation is not allowed.
TEST_F(FqdnDhcpv6SrvTest, clientAAAAUpdateNotAllowed) {
enableD2(OVERRIDE_CLIENT_UPDATE);
testFqdn(DHCPV6_SOLICIT, 0, "myhost.example.com.",
Option6ClientFqdn::FULL,
Option6ClientFqdn::FLAG_S | Option6ClientFqdn::FLAG_O,
......@@ -545,6 +596,34 @@ TEST_F(FqdnDhcpv6SrvTest, createNameChangeRequests) {
}
// Checks that NameChangeRequests to add entries are not
// created when ddns updates are disabled.
TEST_F(FqdnDhcpv6SrvTest, noAddRequestsWhenDisabled) {
NakedDhcpv6Srv srv(0);
// Disable DDNS udpates.
disableD2();
// Create Reply message with Client Id and Server id.
Pkt6Ptr answer = generateMessageWithIds(DHCPV6_REPLY, srv);
// Create three IAs, each having different address.
addIA(1234, IOAddress("2001:db8:1::1"), answer);
// Use domain name in upper case. It should be converted to lower-case
// before DHCID is calculated. So, we should get the same result as if
// we typed domain name in lower-case.
Option6ClientFqdnPtr fqdn = createClientFqdn(Option6ClientFqdn::FLAG_S,
"MYHOST.EXAMPLE.COM",
Option6ClientFqdn::FULL);
answer->addOption(fqdn);
// Create NameChangeRequest for the first allocated address.
ASSERT_NO_THROW(srv.createNameChangeRequests(answer));
ASSERT_TRUE(srv.name_change_reqs_.empty());
}
// Test creation of the NameChangeRequest to remove both forward and reverse
// mapping for the given lease.
TEST_F(FqdnDhcpv6SrvTest, createRemovalNameChangeRequestFwdRev) {
......@@ -569,6 +648,27 @@ TEST_F(FqdnDhcpv6SrvTest, createRemovalNameChangeRequestFwdRev) {
}
// Checks that NameChangeRequests to remove entries are not created
// when ddns updates are disabled.
TEST_F(FqdnDhcpv6SrvTest, noRemovalsWhenDisabled) {
NakedDhcpv6Srv srv(0);
// Disable DDNS updates.
disableD2();
lease_->fqdn_fwd_ = true;
lease_->fqdn_rev_ = true;
// Part of the domain name is in upper case, to test that it gets converted
// to lower case before DHCID is computed. So, we should get the same DHCID
// as if we typed domain-name in lower case.
lease_->hostname_ = "MYHOST.example.com.";
ASSERT_NO_THROW(srv.createRemovalNameChangeRequest(lease_));
ASSERT_TRUE(srv.name_change_reqs_.empty());
}
// Test creation of the NameChangeRequest to remove reverse mapping for the
// given lease.
TEST_F(FqdnDhcpv6SrvTest, createRemovalNameChangeRequestRev) {
......@@ -821,13 +921,13 @@ TEST_F(FqdnDhcpv6SrvTest, processRequestEmptyFqdn) {
NakedDhcpv6Srv srv(0);
testProcessMessage(DHCPV6_REQUEST, "",
"host-2001-db8-1-1--dead-beef.example.com.",
"myhost-2001-db8-1-1--dead-beef.example.com.",
srv, false);
ASSERT_EQ(1, srv.name_change_reqs_.size());
verifyNameChangeRequest(srv, isc::dhcp_ddns::CHG_ADD, true, true,
"2001:db8:1:1::dead:beef",
"0002018D6874B105A5C92DBBD6E4F6C80A93161"
"BC03996F0CD0EB75800DEF997C29961",
"000201C905E54BE12DE6AF92ADE72752B9F362"
"13B5A8BC9D217548CD739B4CF31AFB1B",
0, 4000);
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment