From: Thomas Markwalder Date: Wed, 19 Feb 2014 14:09:00 +0000 (-0500) Subject: [3340] b10-dhcp4 now handles DHO_HOST_NAME as a OptionString X-Git-Tag: bind10-1.2.0beta1-release~29^2 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=5d8fd663f29c59f2cdb5bca1908aa69b4012f446;p=thirdparty%2Fkea.git [3340] b10-dhcp4 now handles DHO_HOST_NAME as a OptionString Modified Dhcpv4Srv to handle DHO_HOST_NAME as an OptionString rather than an OptionCustom. --- diff --git a/src/bin/dhcp4/dhcp4_srv.cc b/src/bin/dhcp4/dhcp4_srv.cc index 0608b936c4..7b3ab2d60d 100644 --- a/src/bin/dhcp4/dhcp4_srv.cc +++ b/src/bin/dhcp4/dhcp4_srv.cc @@ -701,12 +701,11 @@ Dhcpv4Srv::processClientName(const Pkt4Ptr& query, Pkt4Ptr& answer) { processClientFqdnOption(fqdn, answer); } else { - OptionCustomPtr hostname = boost::dynamic_pointer_cast + OptionStringPtr hostname = boost::dynamic_pointer_cast (query->getOption(DHO_HOST_NAME)); if (hostname) { processHostnameOption(hostname, answer); } - } } catch (const Exception& ex) { // In some rare cases it is possible that the client's name processing @@ -759,7 +758,7 @@ Dhcpv4Srv::processClientFqdnOption(const Option4ClientFqdnPtr& fqdn, } void -Dhcpv4Srv::processHostnameOption(const OptionCustomPtr& opt_hostname, +Dhcpv4Srv::processHostnameOption(const OptionStringPtr& opt_hostname, Pkt4Ptr& answer) { // Fetch D2 configuration. D2ClientMgr& d2_mgr = CfgMgr::instance().getD2ClientMgr(); @@ -769,7 +768,7 @@ Dhcpv4Srv::processHostnameOption(const OptionCustomPtr& opt_hostname, return; } - std::string hostname = isc::util::str::trim(opt_hostname->readString()); + 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. // If it isn't we ignore this option. (Per RFC 2131, section 3.14) @@ -783,7 +782,7 @@ Dhcpv4Srv::processHostnameOption(const OptionCustomPtr& opt_hostname, // possible that we will use the hostname option provided by the client // to perform the DNS update and we will send the same option to him to // indicate that we accepted this hostname. - OptionCustomPtr opt_hostname_resp(new OptionCustom(*opt_hostname)); + OptionStringPtr opt_hostname_resp(new OptionString(*opt_hostname)); // The hostname option may be unqualified or fully qualified. The lab_count // holds the number of labels for the name. The number of 1 means that @@ -800,12 +799,14 @@ Dhcpv4Srv::processHostnameOption(const OptionCustomPtr& opt_hostname, /// conversion if needed and possible. if ((d2_mgr.getD2ClientConfig()->getReplaceClientName()) || (label_count < 2)) { - opt_hostname_resp->writeString(""); + // Set to root domain to signal later on that we should replace it. + // DHO_HOST_NAME is a string option which cannot be empty. + opt_hostname_resp->setValue("."); } 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->writeString(d2_mgr.qualifyName(hostname)); + opt_hostname_resp->setValue(d2_mgr.qualifyName(hostname)); } answer->addOption(opt_hostname_resp); @@ -956,7 +957,7 @@ Dhcpv4Srv::assignLease(const Pkt4Ptr& question, Pkt4Ptr& answer) { std::string hostname; bool fqdn_fwd = false; bool fqdn_rev = false; - OptionCustomPtr opt_hostname; + OptionStringPtr opt_hostname; Option4ClientFqdnPtr fqdn = boost::dynamic_pointer_cast< Option4ClientFqdn>(answer->getOption(DHO_FQDN)); if (fqdn) { @@ -964,10 +965,17 @@ Dhcpv4Srv::assignLease(const Pkt4Ptr& question, Pkt4Ptr& answer) { fqdn_fwd = fqdn->getFlag(Option4ClientFqdn::FLAG_S); fqdn_rev = !fqdn->getFlag(Option4ClientFqdn::FLAG_N); } else { - opt_hostname = boost::dynamic_pointer_cast + opt_hostname = boost::dynamic_pointer_cast (answer->getOption(DHO_HOST_NAME)); if (opt_hostname) { - hostname = opt_hostname->readString(); + hostname = opt_hostname->getValue(); + // DHO_HOST_NAME is string option which cannot be blank, + // we use "." to know we should replace it with a fully + // generated name. The local string variable needs to be + // blank in logic below. + if (hostname == ".") { + hostname = ""; + } /// @todo It could be configurable what sort of updates the /// server is doing when Hostname option was sent. fqdn_fwd = true; @@ -1021,7 +1029,7 @@ Dhcpv4Srv::assignLease(const Pkt4Ptr& question, Pkt4Ptr& answer) { fqdn->setDomainName(lease->hostname_, Option4ClientFqdn::FULL); } else if (opt_hostname) { - opt_hostname->writeString(lease->hostname_); + opt_hostname->setValue(lease->hostname_); } } catch (const Exception& ex) { diff --git a/src/bin/dhcp4/dhcp4_srv.h b/src/bin/dhcp4/dhcp4_srv.h index b08df2c89f..b5f2fb0401 100644 --- a/src/bin/dhcp4/dhcp4_srv.h +++ b/src/bin/dhcp4/dhcp4_srv.h @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -452,10 +453,10 @@ private: /// prepare the Hostname option to be sent back to the client in the /// server's response. /// - /// @param opt_hostname An @c OptionCustom object encapsulating the Hostname + /// @param opt_hostname An @c OptionString object encapsulating the Hostname /// %Option. /// @param [out] answer A response message to be sent to a client. - void processHostnameOption(const OptionCustomPtr& opt_hostname, + void processHostnameOption(const OptionStringPtr& opt_hostname, Pkt4Ptr& answer); protected: diff --git a/src/bin/dhcp4/tests/fqdn_unittest.cc b/src/bin/dhcp4/tests/fqdn_unittest.cc index 4215e92544..9c80e13765 100644 --- a/src/bin/dhcp4/tests/fqdn_unittest.cc +++ b/src/bin/dhcp4/tests/fqdn_unittest.cc @@ -118,11 +118,11 @@ public: } // Create an instance of the Hostname option. - OptionCustomPtr + OptionStringPtr createHostname(const std::string& hostname) { - OptionDefinition def("hostname", DHO_HOST_NAME, "string"); - OptionCustomPtr opt_hostname(new OptionCustom(def, Option::V4)); - opt_hostname->writeString(hostname); + OptionStringPtr opt_hostname(new OptionString(Option::V4, + DHO_HOST_NAME, + hostname)); return (opt_hostname); } @@ -147,9 +147,9 @@ public: } // get the Hostname option from the given message. - OptionCustomPtr getHostnameOption(const Pkt4Ptr& pkt) { + OptionStringPtr getHostnameOption(const Pkt4Ptr& pkt) { return (boost::dynamic_pointer_cast< - OptionCustom>(pkt->getOption(DHO_HOST_NAME))); + OptionString>(pkt->getOption(DHO_HOST_NAME))); } // Create a message holding DHCPv4 Client FQDN Option. @@ -264,7 +264,7 @@ public: // 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. - OptionCustomPtr processHostname(const Pkt4Ptr& query) { + OptionStringPtr processHostname(const Pkt4Ptr& query) { if (!getHostnameOption(query)) { ADD_FAILURE() << "Hostname option not carried in the query"; } @@ -279,7 +279,7 @@ public: } srv_->processClientName(query, answer); - OptionCustomPtr hostname = getHostnameOption(answer); + OptionStringPtr hostname = getHostnameOption(answer); return (hostname); } @@ -571,29 +571,20 @@ TEST_F(NameDhcpv4SrvTest, serverUpdateHostname) { Pkt4Ptr query; ASSERT_NO_THROW(query = generatePktWithHostname(DHCPREQUEST, "myhost.example.com.")); - OptionCustomPtr hostname; + OptionStringPtr hostname; ASSERT_NO_THROW(hostname = processHostname(query)); ASSERT_TRUE(hostname); - EXPECT_EQ("myhost.example.com.", hostname->readString()); + EXPECT_EQ("myhost.example.com.", hostname->getValue()); } -// Test that the server skips processing of the empty Hostname option. -TEST_F(NameDhcpv4SrvTest, serverUpdateEmptyHostname) { - Pkt4Ptr query; - ASSERT_NO_THROW(query = generatePktWithHostname(DHCPREQUEST, "")); - OptionCustomPtr hostname; - ASSERT_NO_THROW(hostname = processHostname(query)); - EXPECT_FALSE(hostname); -} - // Test that the server skips processing of a wrong Hostname option. TEST_F(NameDhcpv4SrvTest, serverUpdateWrongHostname) { Pkt4Ptr query; ASSERT_NO_THROW(query = generatePktWithHostname(DHCPREQUEST, "abc..example.com")); - OptionCustomPtr hostname; + OptionStringPtr hostname; ASSERT_NO_THROW(hostname = processHostname(query)); EXPECT_FALSE(hostname); } @@ -620,11 +611,11 @@ TEST_F(NameDhcpv4SrvTest, serverUpdateForwardPartialNameFqdn) { TEST_F(NameDhcpv4SrvTest, serverUpdateUnqualifiedHostname) { Pkt4Ptr query; ASSERT_NO_THROW(query = generatePktWithHostname(DHCPREQUEST, "myhost")); - OptionCustomPtr hostname; + OptionStringPtr hostname; ASSERT_NO_THROW(hostname = processHostname(query)); ASSERT_TRUE(hostname); - EXPECT_EQ("myhost.example.com.", hostname->readString()); + EXPECT_EQ("myhost.example.com.", hostname->getValue()); } @@ -818,7 +809,7 @@ TEST_F(NameDhcpv4SrvTest, processRequestEmptyDomainNameDisabled) { // Test that server generates client's hostname from the IP address assigned // to it when Hostname option carries the top level domain-name. -TEST_F(NameDhcpv4SrvTest, processRequestEmptyHostname) { +TEST_F(NameDhcpv4SrvTest, processRequestTopLevelHostname) { IfaceMgrTestConfig test_config(true); IfaceMgr::instance().openSockets4();