Commit 1feae724 authored by Marcin Siodelski's avatar Marcin Siodelski
Browse files

[3636] DHCPv4 server does not append the dot at the end of the hostname.

This patch has been proposed by Alexis Fidalgo. It was earlier reported
that Kea always appends a dot at the end of the hostname which may cause
some clients to fail on processing this option.
parent 69393d44
......@@ -817,7 +817,7 @@ Dhcpv4Srv::processHostnameOption(const OptionStringPtr& opt_hostname,
// If there are two labels, it means that the client has specified
// the unqualified name. We have to concatenate the unqalified name
// with the domain name.
opt_hostname_resp->setValue(d2_mgr.qualifyName(hostname));
opt_hostname_resp->setValue(d2_mgr.qualifyName(hostname,false));
}
answer->addOption(opt_hostname_resp);
......@@ -1071,10 +1071,13 @@ Dhcpv4Srv::assignLease(const Pkt4Ptr& question, Pkt4Ptr& answer) {
// hostname is empty, it means that server is responsible for
// generating the entire hostname for the client. The example of the
// client's name, generated from the IP address is: host-192-0-2-3.
if ((fqdn || opt_hostname) && lease->hostname_.empty()) {
lease->hostname_ = CfgMgr::instance()
.getD2ClientMgr().generateFqdn(lease->addr_);
if ((fqdn || opt_hostname) && lease->hostname_.empty()) {
if(fqdn) {
lease->hostname_ = CfgMgr::instance().getD2ClientMgr().generateFqdn(lease->addr_,true);
}
if(opt_hostname) {
lease->hostname_ = CfgMgr::instance().getD2ClientMgr().generateFqdn(lease->addr_,false);
}
// The operations below are rather safe, but we want to catch
// any potential exceptions (e.g. invalid lease database backend
// implementation) and log an error.
......
......@@ -139,7 +139,7 @@ public:
///
/// @return An std::string contained the generated FQDN.
std::string generatedNameFromAddress(const IOAddress& addr) {
return(CfgMgr::instance().getD2ClientMgr().generateFqdn(addr));
return(CfgMgr::instance().getD2ClientMgr().generateFqdn(addr,true));
}
// Get the Client FQDN Option from the given message.
......
......@@ -2609,7 +2609,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,true);
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
......
......@@ -171,31 +171,43 @@ D2ClientMgr::analyzeFqdn(const bool client_s, const bool client_n,
}
std::string
D2ClientMgr::generateFqdn(const asiolink::IOAddress& address) const {
D2ClientMgr::generateFqdn(const asiolink::IOAddress& address, bool appendDot) const {
std::string hostname = address.toText();
std::replace(hostname.begin(), hostname.end(),
(address.isV4() ? '.' : ':'), '-');
std::ostringstream gen_name;
gen_name << d2_client_config_->getGeneratedPrefix() << "-" << hostname;
return (qualifyName(gen_name.str()));
return (qualifyName(gen_name.str(),appendDot));
}
std::string
D2ClientMgr::qualifyName(const std::string& partial_name) const {
D2ClientMgr::qualifyName(const std::string& partial_name, bool appendDot) const {
std::ostringstream gen_name;
gen_name << partial_name << "." << d2_client_config_->getQualifyingSuffix();
// Tack on a trailing dot in case suffix doesn't have one.
std::string str = gen_name.str();
size_t len = str.length();
if ((len > 0) && (str[len - 1] != '.')) {
gen_name << ".";
//unless it's forced, will append trailing dot
if(appendDot) {
// Tack on a trailing dot in case suffix doesn't have one.
if ((len > 0) && (str[len - 1] != '.')) {
gen_name << ".";
}
} else {
//if a call with appendDot is false, remove the dot if exists
if ((len > 0) && (str[len - 1] == '.')) {
gen_name.str(str.substr(0,len-1));
}
}
return (gen_name.str());
}
void
D2ClientMgr::startSender(D2ClientErrorHandler error_handler) {
if (amSending()) {
......
......@@ -172,9 +172,10 @@ public:
/// ('.' for IPv4 or ':' for IPv6) replaced with a hyphen, '-'.
///
/// @param address IP address from which to derive the name (IPv4 or IPv6)
/// @param appendDot wether if a trailing dot should be appended or not
///
/// @return std::string containing the generated name.
std::string generateFqdn(const asiolink::IOAddress& address) const;
std::string generateFqdn(const asiolink::IOAddress& address, bool appendDot) const;
/// @brief Adds a qualifying suffix to a given domain name
///
......@@ -186,9 +187,10 @@ public:
/// one.
///
/// @param partial_name domain name to qualify
/// @param appendDot wether if a trailing dot should be appended or not
///
/// @return std::string containing the qualified name.
std::string qualifyName(const std::string& partial_name) const;
std::string qualifyName(const std::string& partial_name, bool appendDot) const;
/// @brief Set server FQDN flags based on configuration and a given FQDN
///
......@@ -465,7 +467,7 @@ D2ClientMgr::adjustDomainName(const T& fqdn, T& fqdn_resp) {
} else {
// If the supplied name is partial, qualify it by adding the suffix.
if (fqdn.getDomainNameType() == T::PARTIAL) {
fqdn_resp.setDomainName(qualifyName(fqdn.getDomainName()), T::FULL);
fqdn_resp.setDomainName(qualifyName(fqdn.getDomainName(),true), T::FULL);
}
}
}
......
......@@ -601,6 +601,8 @@ TEST(D2ClientMgr, qualifyName) {
// Create enabled configuration.
D2ClientConfigPtr cfg;
//append suffix and dot
ASSERT_NO_THROW(cfg.reset(new D2ClientConfig(true,
isc::asiolink::IOAddress("127.0.0.1"), 477,
isc::asiolink::IOAddress("127.0.0.1"), 478,
......@@ -612,9 +614,38 @@ TEST(D2ClientMgr, qualifyName) {
// Verify that the qualifying suffix gets appended with trailing dot added.
std::string partial_name = "somehost";
std::string qualified_name = mgr.qualifyName(partial_name);
std::string qualified_name = mgr.qualifyName(partial_name,true);
EXPECT_EQ("somehost.suffix.com.", qualified_name);
//append suffix but dot
ASSERT_NO_THROW(cfg.reset(new D2ClientConfig(true,
isc::asiolink::IOAddress("127.0.0.1"), 477,
isc::asiolink::IOAddress("127.0.0.1"), 478,
1024,
dhcp_ddns::NCR_UDP, dhcp_ddns::FMT_JSON,
false, false, true, false,
"prefix", "suffix.com")));
ASSERT_NO_THROW(mgr.setD2ClientConfig(cfg));
partial_name = "somehost";
qualified_name = mgr.qualifyName(partial_name,false); //false means no dot
EXPECT_EQ("somehost.suffix.com", qualified_name);
//append no suffix and not dot
ASSERT_NO_THROW(cfg.reset(new D2ClientConfig(true,
isc::asiolink::IOAddress("127.0.0.1"), 477,
isc::asiolink::IOAddress("127.0.0.1"), 478,
1024,
dhcp_ddns::NCR_UDP, dhcp_ddns::FMT_JSON,
false, false, true, false,
"prefix", ""))); //empty suffix
ASSERT_NO_THROW(mgr.setD2ClientConfig(cfg));
partial_name = "somehost";
qualified_name = mgr.qualifyName(partial_name,false); //false means no dot
EXPECT_EQ("somehost", qualified_name);
// Verify that the qualifying suffix gets appended with trailing dot added.
ASSERT_NO_THROW(cfg.reset(new D2ClientConfig(true,
isc::asiolink::IOAddress("127.0.0.1"), 477,
isc::asiolink::IOAddress("127.0.0.1"), 478,
......@@ -625,7 +656,7 @@ TEST(D2ClientMgr, qualifyName) {
ASSERT_NO_THROW(mgr.setD2ClientConfig(cfg));
// Verify that the qualifying suffix gets appended without dot added.
qualified_name = mgr.qualifyName(partial_name);
qualified_name = mgr.qualifyName(partial_name,true);
EXPECT_EQ("somehost.hasdot.com.", qualified_name);
}
......@@ -647,19 +678,19 @@ TEST(D2ClientMgr, generateFqdn) {
// Verify that it works with an IPv4 address.
asiolink::IOAddress v4address("192.0.2.75");
EXPECT_EQ("prefix-192-0-2-75.suffix.com.", mgr.generateFqdn(v4address));
EXPECT_EQ("prefix-192-0-2-75.suffix.com.", mgr.generateFqdn(v4address,true));
// Verify that it works with an IPv6 address.
asiolink::IOAddress v6address("2001:db8::2");
EXPECT_EQ("prefix-2001-db8--2.suffix.com.", mgr.generateFqdn(v6address));
EXPECT_EQ("prefix-2001-db8--2.suffix.com.", mgr.generateFqdn(v6address,true));
// Create a disabled config.
ASSERT_NO_THROW(cfg.reset(new D2ClientConfig()));
ASSERT_NO_THROW(mgr.setD2ClientConfig(cfg));
// Verify names generate properly with a disabled configuration.
EXPECT_EQ("myhost-192-0-2-75.example.com.", mgr.generateFqdn(v4address));
EXPECT_EQ("myhost-2001-db8--2.example.com.", mgr.generateFqdn(v6address));
EXPECT_EQ("myhost-192-0-2-75.example.com.", mgr.generateFqdn(v4address,true));
EXPECT_EQ("myhost-2001-db8--2.example.com.", mgr.generateFqdn(v6address,true));
}
/// @brief Tests adjustDomainName template method with Option4ClientFqdn
......
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