Commit 45e56d7a authored by Thomas Markwalder's avatar Thomas Markwalder

[master] DDNS parameter, replace-client-name, now supports multiple modes

    Merges in trac4259.
parents 61407bba 0c3f04e8
......@@ -129,7 +129,7 @@ strings <userinput>path</userinput>/kea-dhcp4 | sed -n 's/;;;; //p'
If the file already exists and contains the PID of a live process,
the server will issue a DHCP4_ALREADY_RUNNING log message and exit. It
is possible, though unlikely, that the file is a remnant of a system crash
and the process to which the PID belongs is unrelated to Kea. In such a
and the process to which the PID belongs is unrelated to Kea. In such a
case it would be necessary to manually delete the PID file.
</para>
......@@ -1777,7 +1777,7 @@ It is merely echoed by the server
</section>
<section id="dhcp4-ddns-config">
<title>Configuring DHCPv4 for DDNS</title>
<title>DDNS for DHCPv4</title>
<para>
As mentioned earlier, kea-dhcp4 can be configured to generate requests to the
DHCP-DDNS server (referred to here as "D2" ) to update DNS entries. These requests are known as
......@@ -1852,7 +1852,7 @@ It is merely echoed by the server
<command>"override-client-update": false</command>
</simpara></listitem>
<listitem><simpara>
<command>"replace-client-name": false</command>
<command>"replace-client-name": "never"</command>
</simpara></listitem>
<listitem><simpara>
<command>"generated-prefix": "myhost"</command>
......@@ -2078,38 +2078,62 @@ It is merely echoed by the server
supply a portion or all of that name based upon what it receives from
the client in the DHCP REQUEST.</para>
<para>
The rules for determining the FQDN option are as follows:
The default rules for constructing the FQDN that will be used for DNS
entries are:
<orderedlist>
<listitem><para>
If configured to do, so ignore the DHCPREQUEST contents and generate a
FQDN using a configurable prefix and suffix.
If the DHCPREQUEST contains the client FQDN option, the candidate name
is taken from there, otherwise it is taken from the Host Name option.
</para></listitem>
<listitem><para>
If the DHCPREQUEST contains the client FQDN option, the candidate
name is taken from there, otherwise it is taken from the Host Name option.
The candidate name may then be modified:
<orderedlist>
<listitem><para>
If the candidate name is a fully qualified domain name, use it.
If the candidate name is a partial (i.e. unqualified) name then add a
configurable suffix to the name and use the result as the FQDN.
</para></listitem>
<listitem><para>
If the candidate name is a partial (i.e. unqualified) name then
add a configurable suffix to the name and use the result as the FQDN.
If the candidate name provided is empty, generate a FQDN using a
configurable prefix and suffix.
</para></listitem>
<listitem><para>
If the candidate name is a empty, generate a FQDN using a
configurable prefix and suffix.
If the client provided neither option, then no DNS action will be taken.
</para></listitem>
</orderedlist>
These rules can amended by setting the
<command>replace-client-name</command> parameter which provides the
following modes of behavior:
<itemizedlist>
<listitem><para>
<command>never</command> - Use the name the client sent. If the client
sent no name, do not generate one. This is the default mode.
</para></listitem>
</orderedlist>
To instruct kea-dhcp4 to always generate the FQDN for a client, set the
parameter <command>replace-client-name</command> to true as follows:
<listitem><para>
<command>always</command> - Replace the name the client sent. If the
client sent no name, generate one for the client.
</para></listitem>
<listitem><para>
<command>when-present</command> - Replace the name the client sent.
If the client sent no name, do not generate one.
</para></listitem>
<listitem><para>
<command>when-not-present</command> - Use the name the client sent.
If the client sent no name, generate one for the client.
</para></listitem>
</itemizedlist>
<note>
Note that formerly, this parameter was a boolean and permitted only values
of <command>true</command> and <command>false</command>. Boolean values
will still be accepted but may eventually be deprecated. A value of
<command>true</command> equates to <command>when-present</command>,
<command>false</command> equates to <command>never</command>.
</note>
For example, To instruct kea-dhcp4 to always generate the FQDN for a
client, set the parameter <command>replace-client-name</command> to
<command>always</command> as follows:
</para>
<screen>
"Dhcp4": {
"dhcp-ddns": {
<userinput>"replace-client-name": true</userinput>,
<userinput>"replace-client-name": "always"</userinput>,
...
},
...
......
......@@ -1744,7 +1744,7 @@ should include options from the isc option space:
</section>
<section id="dhcp6-ddns-config">
<title>Configuring DHCPv6 for DDNS</title>
<title>DDNS for DHCPv6</title>
<para>
As mentioned earlier, kea-dhcp6 can be configured to generate requests to
the DHCP-DDNS server (referred to here as "D2") to update
......@@ -1820,7 +1820,7 @@ should include options from the isc option space:
<command>"override-client-update": false</command>
</simpara></listitem>
<listitem><simpara>
<command>"replace-client-name": false</command>
<command>"replace-client-name": "never"</command>
</simpara></listitem>
<listitem><simpara>
<command>"generated-prefix": "myhost"</command>
......@@ -1926,14 +1926,14 @@ should include options from the isc option space:
In general, kea-dhcp6 will generate DDNS update requests when:
<orderedlist>
<listitem><para>
A new lease is granted in response to a DHCP REQUEST
A new lease is granted in response to a REQUEST
</para></listitem>
<listitem><para>
An existing lease is renewed but the FQDN associated with it has
changed.
</para></listitem>
<listitem><para>
An existing lease is released in response to a DHCP RELEASE
An existing lease is released in response to a RELEASE
</para></listitem>
</orderedlist>
In the second case, lease renewal, two DDNS requests will be issued: one
......@@ -1944,7 +1944,7 @@ should include options from the isc option space:
discussed next.
</para>
<para>
kea-dhcp6 will generate a DDNS update request only if the DHCP REQUEST
kea-dhcp6 will generate a DDNS update request only if the REQUEST
contains the FQDN option (code 39). By default kea-dhcp6 will
respect the FQDN N and S flags specified by the client as shown in the
following table:
......@@ -2041,42 +2041,67 @@ should include options from the isc option space:
<section id="dhcpv6-fqdn-name-generation">
<title>kea-dhcp6 name generation for DDNS update requests</title>
<para>Each NameChangeRequest must of course include the fully qualified domain
name whose DNS entries are to be affected. kea-dhcp6 can be configured to
supply a portion or all of that name based upon what it receives from
the client in the DHCP REQUEST.</para>
<para>The rules for determining the FQDN option are as follows:
<para>Each NameChangeRequest must of course include the fully qualified
domain name whose DNS entries are to be affected. kea-dhcp6 can be
configured to supply a portion or all of that name based upon what it
receives from the client.</para>
<para>
The default rules for constructing the FQDN that will be used for DNS
entries are:
<orderedlist>
<listitem><para>
If configured to do so ignore the REQUEST contents and generate a
FQDN using a configurable prefix and suffix.
If the DHCPREQUEST contains the client FQDN option, the candidate name
is taken from there.
</para></listitem>
<listitem><para>
Otherwise, using the domain name value from the client FQDN option as
the candidate name:
<orderedlist>
<listitem><para>
If the candidate name is a fully qualified domain name then use it.
If the candidate name is a partial (i.e. unqualified) name then add a
configurable suffix to the name and use the result as the FQDN.
</para></listitem>
<listitem><para>
If the candidate name is a partial (i.e. unqualified) name then
add a configurable suffix to the name and use the result as the FQDN.
If the candidate name provided is empty, generate a FQDN using a
configurable prefix and suffix.
</para></listitem>
<listitem><para>
If the candidate name is a empty then generate a FQDN using a
configurable prefix and suffix.
If the client provided neither option, then no DNS action will be taken.
</para></listitem>
</orderedlist>
These rules can amended by setting the
<command>replace-client-name</command> parameter which provides the
following modes of behavior:
<itemizedlist>
<listitem><para>
<command>never</command> - Use the name the client sent. If the client
sent no name, do not generate one. This is the default mode.
</para></listitem>
</orderedlist>
To instruct kea-dhcp6 to always generate a FQDN, set the parameter
"replace-client-name" to true:
<listitem><para>
<command>always</command> - Replace the name the client sent. If the
client sent no name, generate one for the client.
</para></listitem>
<listitem><para>
<command>when-present</command> - Replace the name the client sent.
If the client sent no name, do not generate one.
</para></listitem>
<listitem><para>
<command>when-not-present</command> - Use the name the client sent.
If the client sent no name, generate one for the client.
</para></listitem>
</itemizedlist>
<note>
Note that formerly, this parameter was a boolean and permitted only values
of <command>true</command> and <command>false</command>. Boolean values
will still be accepted but may eventually be deprecated. A value of
<command>true</command> equates to <command>when-present</command>,
<command>false</command> equates to <command>never</command>.
</note>
For example, To instruct kea-dhcp6 to always generate the FQDN for a
client, set the parameter <command>replace-client-name</command> to
<command>always</command> as follows:
</para>
<screen>
"Dhcp6": {
"dhcp-ddns": {
<userinput>"replace-client-name": true</userinput>,
<userinput>"replace-client-name": "always"</userinput>,
...
},
...
......
......@@ -607,9 +607,9 @@
},
{
"item_name": "replace-client-name",
"item_type": "boolean",
"item_type": "string",
"item_optional": true,
"item_default": false,
"item_default": "never",
"item_description": "Should server replace the domain-name supplied by the client"
},
{
......
# Copyright (C) 2012-2015 Internet Systems Consortium, Inc. ("ISC")
# Copyright (C) 2012-2016 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
......@@ -217,6 +217,11 @@ from a client. Server does not process empty Hostname options and therefore
option is skipped. The argument holds the client and transaction identification
information.
% DHCP4_GENERATE_FQDN %1: client did not send a FQDN or hostname; FQDN will be be generated for the client
This debug message is issued when the server did not receive a Hostname option
from the client and hostname generation is enabled. This provides a means to
create DNS entries for unsophisticated clients.
% DHCP4_HANDLE_SIGNAL_EXCEPTION An exception was thrown while handing signal: %1
This error message is printed when an ISC or standard exception was raised during signal
processing. This likely indicates a coding error and should be reported to ISC.
......
......@@ -1073,13 +1073,10 @@ Dhcpv4Srv::processClientName(Dhcpv4Exchange& ex) {
processClientFqdnOption(ex);
} else {
OptionStringPtr hostname = boost::dynamic_pointer_cast<OptionString>
(ex.getQuery()->getOption(DHO_HOST_NAME));
if (hostname) {
LOG_DEBUG(ddns4_logger, DBG_DHCP4_DETAIL, DHCP4_CLIENT_HOSTNAME_PROCESS)
LOG_DEBUG(ddns4_logger, DBG_DHCP4_DETAIL,
DHCP4_CLIENT_HOSTNAME_PROCESS)
.arg(ex.getQuery()->getLabel());
processHostnameOption(ex);
}
processHostnameOption(ex);
}
} catch (const Exception& e) {
// In some rare cases it is possible that the client's name processing
......@@ -1150,14 +1147,6 @@ Dhcpv4Srv::processClientFqdnOption(Dhcpv4Exchange& ex) {
void
Dhcpv4Srv::processHostnameOption(Dhcpv4Exchange& ex) {
// Obtain the Hostname option from the client's message.
OptionStringPtr opt_hostname = boost::dynamic_pointer_cast<OptionString>
(ex.getQuery()->getOption(DHO_HOST_NAME));
LOG_DEBUG(ddns4_logger, DBG_DHCP4_DETAIL_DATA, DHCP4_CLIENT_HOSTNAME_DATA)
.arg(ex.getQuery()->getLabel())
.arg(opt_hostname->getValue());
// Fetch D2 configuration.
D2ClientMgr& d2_mgr = CfgMgr::instance().getD2ClientMgr();
......@@ -1166,6 +1155,36 @@ Dhcpv4Srv::processHostnameOption(Dhcpv4Exchange& ex) {
return;
}
D2ClientConfig::ReplaceClientNameMode replace_name_mode =
d2_mgr.getD2ClientConfig()->getReplaceClientNameMode();
// Obtain the Hostname option from the client's message.
OptionStringPtr opt_hostname = boost::dynamic_pointer_cast<OptionString>
(ex.getQuery()->getOption(DHO_HOST_NAME));
// If we don't have a hostname then either we'll supply it or do nothing.
if (!opt_hostname) {
// If we're configured to supply it then add it to the response.
// Use the root domain to signal later on that we should replace it.
if (replace_name_mode == D2ClientConfig::RCM_ALWAYS ||
replace_name_mode == D2ClientConfig::RCM_WHEN_NOT_PRESENT) {
LOG_DEBUG(ddns4_logger, DBG_DHCP4_DETAIL_DATA,
DHCP4_GENERATE_FQDN)
.arg(ex.getQuery()->getLabel());
OptionStringPtr opt_hostname_resp(new OptionString(Option::V4,
DHO_HOST_NAME,
"."));
ex.getResponse()->addOption(opt_hostname_resp);
}
return;
}
// Client sent us a hostname option so figure out what to do with it.
LOG_DEBUG(ddns4_logger, DBG_DHCP4_DETAIL_DATA, DHCP4_CLIENT_HOSTNAME_DATA)
.arg(ex.getQuery()->getLabel())
.arg(opt_hostname->getValue());
std::string hostname = isc::util::str::trim(opt_hostname->getValue());
unsigned int label_count = OptionDataTypeUtil::getLabelCount(hostname);
// The hostname option sent by the client should be at least 1 octet long.
......@@ -1195,14 +1214,16 @@ Dhcpv4Srv::processHostnameOption(Dhcpv4Exchange& ex) {
opt_hostname_resp->setValue(d2_mgr.qualifyName(ex.getContext()->host_->getHostname(),
false));
} else if ((d2_mgr.getD2ClientConfig()->getReplaceClientName()) ||
(label_count < 2)) {
} else if ((replace_name_mode == D2ClientConfig::RCM_ALWAYS ||
replace_name_mode == D2ClientConfig::RCM_WHEN_PRESENT)
|| label_count < 2) {
// Set to root domain to signal later on that we should replace it.
// DHO_HOST_NAME is a string option which cannot be empty.
/// @todo We may want to reconsider whether it is appropriate for the
/// client to send a root domain name as a Hostname. There are
/// also extensions to the auto generation of the client's name,
/// e.g. conversion to the puny code which may be considered at some point.
/// e.g. conversion to the puny code which may be considered at some
/// point.
/// For now, we just remain liberal and expect that the DNS will handle
/// conversion if needed and possible.
opt_hostname_resp->setValue(".");
......
......@@ -3176,7 +3176,7 @@ TEST_F(Dhcp4ParserTest, d2ClientConfig) {
" \"allow-client-update\" : true, "
" \"override-no-update\" : true, "
" \"override-client-update\" : true, "
" \"replace-client-name\" : true, "
" \"replace-client-name\" : \"when-present\", "
" \"generated-prefix\" : \"test.prefix\", "
" \"qualifying-suffix\" : \"test.suffix.\" },"
"\"valid-lifetime\": 4000 }";
......@@ -3210,7 +3210,7 @@ TEST_F(Dhcp4ParserTest, d2ClientConfig) {
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(D2ClientConfig::RCM_WHEN_PRESENT, d2_client_config->getReplaceClientNameMode());
EXPECT_EQ("test.prefix", d2_client_config->getGeneratedPrefix());
EXPECT_EQ("test.suffix.", d2_client_config->getQualifyingSuffix());
}
......@@ -3238,7 +3238,7 @@ TEST_F(Dhcp4ParserTest, invalidD2ClientConfig) {
" \"allow-client-update\" : true, "
" \"override-no-update\" : true, "
" \"override-client-update\" : true, "
" \"replace-client-name\" : true, "
" \"replace-client-name\" : \"when-present\", "
" \"generated-prefix\" : \"test.prefix\", "
" \"qualifying-suffix\" : \"test.suffix.\" },"
"\"valid-lifetime\": 4000 }";
......
// Copyright (C) 2013-2015 Internet Systems Consortium, Inc. ("ISC")
// Copyright (C) 2013-2016 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
......@@ -128,6 +128,20 @@ public:
static const uint16_t OVERRIDE_CLIENT_UPDATE = 4;
static const uint16_t REPLACE_CLIENT_NAME = 8;
// Enum used to specify whether a client (packet) should include
// the hostname option
enum ClientNameFlag {
CLIENT_NAME_PRESENT,
CLIENT_NAME_NOT_PRESENT
};
// Enum used to specify whether the server should replace/supply
// the hostname or not
enum ReplacementFlag {
NAME_REPLACED,
NAME_NOT_REPLACED
};
NameDhcpv4SrvTest()
: Dhcpv4SrvTest(),
d2_mgr_(CfgMgr::instance().getD2ClientMgr()),
......@@ -172,7 +186,9 @@ public:
(mask & ALWAYS_INCLUDE_FQDN),
(mask & OVERRIDE_NO_UPDATE),
(mask & OVERRIDE_CLIENT_UPDATE),
(mask & REPLACE_CLIENT_NAME),
((mask & REPLACE_CLIENT_NAME) ?
D2ClientConfig::RCM_WHEN_PRESENT
: D2ClientConfig::RCM_NEVER),
"myhost", "example.com")));
ASSERT_NO_THROW(CfgMgr::instance().setD2ClientConfig(cfg));
ASSERT_NO_THROW(srv_->startD2());
......@@ -184,7 +200,8 @@ public:
const bool fqdn_fwd,
const bool fqdn_rev) {
const uint8_t hwaddr_data[] = { 0, 1, 2, 3, 4, 5, 6 };
HWAddrPtr hwaddr(new HWAddr(hwaddr_data, sizeof(hwaddr_data), HTYPE_ETHER));
HWAddrPtr hwaddr(new HWAddr(hwaddr_data, sizeof(hwaddr_data),
HTYPE_ETHER));
Lease4Ptr lease(new Lease4(addr, hwaddr,
&generateClientId()->getData()[0],
generateClientId()->getData().size(),
......@@ -309,6 +326,20 @@ public:
}
// Create a message holding of a given type
Pkt4Ptr generatePkt(const uint8_t msg_type) {
Pkt4Ptr pkt = Pkt4Ptr(new Pkt4(msg_type, 1234));
pkt->setRemoteAddr(IOAddress("192.0.2.3"));
// For DISCOVER we don't include server id, because client broadcasts
// the message to all servers.
if (msg_type != DHCPDISCOVER) {
pkt->addOption(srv_->getServerID());
}
pkt->addOption(generateClientId());
return (pkt);
}
// Test that server generates the appropriate FQDN option in response to
// client's FQDN option.
void testProcessFqdn(const Pkt4Ptr& query, const uint8_t exp_flags,
......@@ -338,6 +369,79 @@ public:
}
// Test that the server's processes the hostname (or lack thereof)
// in a client request correctly, according to the replace-client-name
// mode configuration parameter.
//
// @param mode - value to use client-name-replacment parameter - for
// mode labels such as NEVER and ALWAYS must incluce enclosing quotes:
// "\"NEVER\"". This allows us to also pass in boolean literals which
// are unquoted.
// @param client_name_flag - specifies whether or not the client request
// should contain a hostname option
// @param exp_replacement_flag - specifies whether or not the server is
// expected to replace (or supply) the hostname in its response
void testReplaceClientNameMode(const char* mode,
enum ClientNameFlag client_name_flag,
enum ReplacementFlag exp_replacement_flag) {
// Configuration "template" with a replaceable mode parameter
const char* config_template =
"{ \"interfaces-config\": {"
" \"interfaces\": [ \"*\" ]"
"},"
"\"valid-lifetime\": 3000,"
"\"subnet4\": [ { "
" \"subnet\": \"10.0.0.0/24\", "
" \"id\": 1,"
" \"pools\": [ { \"pool\": \"10.0.0.10-10.0.0.10\" } ]"
" }],"
"\"dhcp-ddns\": {"
"\"enable-updates\": true,"
"\"qualifying-suffix\": \"fake-suffix.isc.org.\","
"\"replace-client-name\": %s"
"}}";
// Create the configuration and configure the server
char config_buf[1024];
sprintf(config_buf, config_template, mode);
ASSERT_NO_THROW(configure(config_buf, srv_)) << "configuration failed";
// Build our client packet
Pkt4Ptr query;
if (client_name_flag == CLIENT_NAME_PRESENT) {
ASSERT_NO_THROW(query = generatePktWithHostname(DHCPREQUEST,
"my.example.com."));
} else {
ASSERT_NO_THROW(query = generatePkt(DHCPREQUEST));
}
// Run the packet through the server, extracting the hostname option
// from the response. If the option isn't present the returned pointer
// will be null.
OptionStringPtr hostname;
ASSERT_NO_THROW(
hostname = processHostname(query,
client_name_flag == CLIENT_NAME_PRESENT)
) << "processHostname throw an exception";
// Verify the contents (or lack thereof) of the hostname
if (exp_replacement_flag == NAME_REPLACED) {
ASSERT_TRUE(hostname)
<< "No host name, it should have the replacement name \".\"";
EXPECT_EQ(".", hostname->getValue());
} else {
if (client_name_flag == CLIENT_NAME_PRESENT) {
ASSERT_TRUE(hostname)
<< "No host name, expected original from client";
EXPECT_EQ("my.example.com.", hostname->getValue());
} else {
ASSERT_FALSE(hostname)
<< "Host name is: " << hostname
<< ", it should have been null";
}
}
}
/// @brief Checks the packet's FQDN option flags against a given mask
///
/// @param pkt IPv4 packet whose FQDN flags should be checked.
......@@ -358,12 +462,20 @@ public:
}
// Processes the Hostname option in the client's message and returns
// the hostname option which would be sent to the client. It will
// throw NULL pointer if the hostname option is not to be included
// in the response.
OptionStringPtr processHostname(const Pkt4Ptr& query) {
if (!getHostnameOption(query)) {
/// @brief Invokes Dhcpv4Srv::processHostname on the given packet
///
/// Processes the Hostname option in the client's message and returns
/// the hostname option which would be sent to the client. It will
/// return empty if the hostname option is not to be included
/// server's response.
/// @param query - client packet to process
/// @param must_have_host - flag indicating whether or not the client
/// packet must contain the hostname option
///
/// @return a pointer to the hostname option constructed by the server
OptionStringPtr processHostname(const Pkt4Ptr& query,
bool must_have_host = true) {
if (!getHostnameOption(query) && must_have_host) {
ADD_FAILURE() << "Hostname option not carried in the query";
}
......@@ -383,7 +495,26 @@ public:
}
// Verify that NameChangeRequest holds valid values.
///@brief Verify that NameChangeRequest holds valid values.
///
/// Pulls the NCR from the top of the send queue and checks it's content
/// against a number of expected parameters.
///
/// @param type - expected NCR change type, CHG_ADD or CHG_REMOVE
/// @param reverse - flag indicating whether or not the NCR specifies
/// reverse change
/// @param forward - flag indication whether or not the NCR specifies
/// forward change
/// @param addr - expected lease address in the NCR
/// @param fqdn - expected FQDN in the NCR
/// @param dhcid - expected DHCID in the NCR (comparison is performed only
/// if the value supplied is not empty):w
/// @param cltt - cltt value from the lease the NCR for which the NCR
/// was generated expected value for
/// @param len - expected lease length in the NCR
/// @param not_strict_expire_check - when true the comparison of the NCR
/// lease expiration time is conducted as greater than or equal to rather
/// equal to CLTT plus lease lenght.
void verifyNameChangeRequest(const isc::dhcp_ddns::NameChangeType type,
const bool reverse, const bool forward,
const std::string& addr,
......@@ -408,9 +539,9 @@ public:
}
// In some cases, the test doesn't have access to the last transmission
// time for the particular client. In such cases, the test can use the
// current time as cltt but the it may not check the lease expiration time
// for equality but rather check that the lease expiration time is not
// greater than the current time + lease lifetime.
// current time as cltt but the it may not check the lease expiration
// time for equality but rather check that the lease expiration time
// is not greater than the current time + lease lifetime.
if (not_strict_expire_check) {
EXPECT_GE(cltt + len, ncr->getLeaseExpiresOn());
} else {
......@@ -1281,4 +1412,43 @@ TEST_F(NameDhcpv4SrvTest, emptyFqdn) {
}
// Verifies that the replace-client-name behavior is correct for each of
// the supported modes.
TEST_F(NameDhcpv4SrvTest, replaceClientNameModeTest) {
// We pass mode labels in with enclosing quotes so we can also test
// unquoted boolean literals true/false
testReplaceClientNameMode("\"never\"",
CLIENT_NAME_NOT_PRESENT, NAME_NOT_REPLACED);
testReplaceClientNameMode("\"never\"",
CLIENT_NAME_PRESENT, NAME_NOT_REPLACED);
testReplaceClientNameMode("\"always\"",
CLIENT_NAME_NOT_PRESENT, NAME_REPLACED);
testReplaceClientNameMode("\"always\"",
CLIENT_NAME_PRESENT, NAME_REPLACED);
testReplaceClientNameMode("\"when-present\"",
CLIENT_NAME_NOT_PRESENT, NAME_NOT_REPLACED);
testReplaceClientNameMode("\"when-present\"",
CLIENT_NAME_PRESENT, NAME_REPLACED);
testReplaceClientNameMode("\"when-not-present\"",
CLIENT_NAME_NOT_PRESENT, NAME_REPLACED);
testReplaceClientNameMode("\"when-not-present\"",
CLIENT_NAME_PRESENT, NAME_NOT_REPLACED);
// Verify that boolean false produces the same result as RCM_NEVER
testReplaceClientNameMode("false",
CLIENT_NAME_NOT_PRESENT, NAME_NOT_REPLACED);
testReplaceClientNameMode("false",
CLIENT_NAME_PRESENT, NAME_NOT_REPLACED);
// Verify that boolean true produces the same result as RCM_WHEN_PRESENT
testReplaceClientNameMode("true",
CLIENT_NAME_NOT_PRESENT, NAME_NOT_REPLACED);
testReplaceClientNameMode("true",
CLIENT_NAME_PRESENT, NAME_REPLACED);
}
} // end of anonymous namespace
......@@ -711,9 +711,9 @@
},
{
"item_name": "replace-client-name",
"item_type": "boolean",