Browse Source

[master] Merge branch 'trac3636'

Marcin Siodelski 10 years ago
parent
commit
450867e698

+ 14 - 5
src/bin/dhcp4/dhcp4_srv.cc

@@ -1,4 +1,4 @@
-// Copyright (C) 2011-2014 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2011-2015 Internet Systems Consortium, Inc. ("ISC")
 //
 // Permission to use, copy, modify, and/or distribute this software for any
 // purpose with or without fee is hereby granted, provided that the above
@@ -816,8 +816,12 @@ Dhcpv4Srv::processHostnameOption(const OptionStringPtr& opt_hostname,
     } else if (label_count == 2) {
         // 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));
+        // with the domain name. The false value passed as a second argument
+        // indicates that the trailing dot should not be appended to the
+        // 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->setValue(d2_mgr.qualifyName(hostname, false));
     }
 
     answer->addOption(opt_hostname_resp);
@@ -1072,8 +1076,13 @@ Dhcpv4Srv::assignLease(const Pkt4Ptr& question, Pkt4Ptr& answer) {
         // 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_);
+            // Note that if we have received the hostname option, rather than
+            // Client FQDN the trailing dot is not appended to the generated
+            // hostname because some clients don't handle the trailing dot in
+            // 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));
 
             // The operations below are rather safe, but we want to catch
             // any potential exceptions (e.g. invalid lease database backend

+ 9 - 4
src/bin/dhcp4/tests/fqdn_unittest.cc

@@ -1,4 +1,4 @@
-// Copyright (C) 2013-2014 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2013-2015 Internet Systems Consortium, Inc. ("ISC")
 //
 // Permission to use, copy, modify, and/or distribute this software for any
 // purpose with or without fee is hereby granted, provided that the above
@@ -136,10 +136,15 @@ public:
     /// names are correct.
     ///
     /// @param addr IP address used in the lease.
+    /// @param trailing_dot A boolean flag which indicates whether the
+    /// trailing dot should be appended to the end of the hostname.
+    /// The defatult value is "true" which means that it should.
     ///
     /// @return An std::string contained the generated FQDN.
-    std::string generatedNameFromAddress(const IOAddress& addr) {
-        return(CfgMgr::instance().getD2ClientMgr().generateFqdn(addr));
+    std::string generatedNameFromAddress(const IOAddress& addr,
+                                         const bool trailing_dot = true) {
+        return(CfgMgr::instance().getD2ClientMgr()
+               .generateFqdn(addr, trailing_dot));
     }
 
     // Get the Client FQDN Option from the given message.
@@ -617,7 +622,7 @@ TEST_F(NameDhcpv4SrvTest, serverUpdateUnqualifiedHostname) {
     ASSERT_NO_THROW(hostname =  processHostname(query));
 
     ASSERT_TRUE(hostname);
-    EXPECT_EQ("myhost.example.com.", hostname->getValue());
+    EXPECT_EQ("myhost.example.com", hostname->getValue());
 
 }
 

+ 1 - 1
src/bin/dhcp6/dhcp6_srv.cc

@@ -1,4 +1,4 @@
-// Copyright (C) 2011-2014 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2011-2015 Internet Systems Consortium, Inc. ("ISC")
 //
 // Permission to use, copy, modify, and/or distribute this software for any
 // purpose with or without fee is hereby granted, provided that the above

+ 4 - 1
src/lib/dhcp_ddns/ncr_msg.cc

@@ -1,4 +1,4 @@
-// Copyright (C) 2013 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2013, 2015 Internet Systems Consortium, Inc. ("ISC")
 //
 // Permission to use, copy, modify, and/or distribute this software for any
 // purpose with or without fee is hereby granted, provided that the above
@@ -220,6 +220,9 @@ NameChangeRequest::NameChangeRequest(const NameChangeType change_type,
     dhcid_(dhcid), lease_expires_on_(lease_expires_on),
     lease_length_(lease_length), status_(ST_NEW) {
 
+    // User setter to validate fqdn.
+    setFqdn(fqdn);
+
     // User setter to validate address.
     setIpAddress(ip_address);
 

+ 23 - 7
src/lib/dhcpsrv/d2_client_mgr.cc

@@ -1,4 +1,4 @@
-// Copyright (C) 2014 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2014-2015 Internet Systems Consortium, Inc. ("ISC")
 //
 // Permission to use, copy, modify, and/or distribute this software for any
 // purpose with or without fee is hereby granted, provided that the above
@@ -171,26 +171,42 @@ 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,
+                          const bool trailing_dot) 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(), trailing_dot));
 }
 
+
 std::string
-D2ClientMgr::qualifyName(const std::string& partial_name) const {
+D2ClientMgr::qualifyName(const std::string& partial_name,
+                         const bool trailing_dot) 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 << ".";
+
+    if(trailing_dot) {
+        // If trailing dot should be added but there is no trailing dot,
+        // append it.
+        if ((len > 0) && (str[len - 1] != '.')) {
+            gen_name << ".";
+        }
+
+    } else {
+        // If the trailing dot should not be appended but it is present,
+        // remove it.
+        if ((len > 0) && (str[len - 1] == '.')) {
+            gen_name.str(str.substr(0,len-1));
+        }
+
     }
 
     return (gen_name.str());

+ 9 - 5
src/lib/dhcpsrv/d2_client_mgr.h

@@ -172,9 +172,12 @@ public:
     /// ('.' for IPv4 or ':' for IPv6) replaced with a hyphen, '-'.
     ///
     /// @param address IP address from which to derive the name (IPv4 or IPv6)
+    /// @param trailing_dot A boolean value which indicates whether trailing
+    /// dot should be appended (if true) or not (false).
     ///
     /// @return std::string containing the generated name.
-    std::string generateFqdn(const asiolink::IOAddress& address) const;
+    std::string generateFqdn(const asiolink::IOAddress& address,
+                             const bool trailing_dot = true) const;
 
     /// @brief Adds a qualifying suffix to a given domain name
     ///
@@ -182,13 +185,14 @@ public:
     /// a partial domain name as follows:
     ///
     ///     <partial_name>.<qualifying-suffix>.
-    /// Note it will add a trailing '.' should qualifying-suffix not end with
-    /// one.
     ///
     /// @param partial_name domain name to qualify
+    /// @param trailing_dot A boolean value which indicates whether trailing
+    /// dot should be appended (if true) or not (false).
     ///
     /// @return std::string containing the qualified name.
-    std::string qualifyName(const std::string& partial_name) const;
+    std::string qualifyName(const std::string& partial_name,
+                            const bool trailing_dot) const;
 
     /// @brief Set server FQDN flags based on configuration and a given FQDN
     ///
@@ -465,7 +469,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);
         }
     }
 }

+ 37 - 6
src/lib/dhcpsrv/tests/d2_client_unittest.cc

@@ -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