From: Marcin Siodelski Date: Wed, 28 Aug 2013 12:46:29 +0000 (+0200) Subject: [3035] Added stub implementation for the function processing client FQDN. X-Git-Tag: bind10-1.2.0beta1-release~102^2~21^2~25 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=41c4d829e66dfce48146a227ed396bf249a41344;p=thirdparty%2Fkea.git [3035] Added stub implementation for the function processing client FQDN. --- diff --git a/src/bin/dhcp4/dhcp4_srv.cc b/src/bin/dhcp4/dhcp4_srv.cc index bf4f76b7c3..31efc5d99f 100644 --- a/src/bin/dhcp4/dhcp4_srv.cc +++ b/src/bin/dhcp4/dhcp4_srv.cc @@ -18,6 +18,8 @@ #include #include #include +#include +#include #include #include #include @@ -662,6 +664,34 @@ Dhcpv4Srv::appendBasicOptions(const Pkt4Ptr& question, Pkt4Ptr& msg) { } } +void +Dhcpv4Srv::processClientName(const Pkt4Ptr& query, Pkt4Ptr& answer) { + // It is possible that client has sent both Client FQDN and Hostname + // option. In such case, server should prefer Client FQDN option and + // ignore the Hostname option. + Option4ClientFqdnPtr fqdn = boost::dynamic_pointer_cast + (query->getOption(DHO_FQDN)); + if (fqdn) { + processClientFqdnOption(query, answer); + + } else { + OptionCustomPtr hostname = boost::dynamic_pointer_cast + (query->getOption(DHO_HOST_NAME)); + if (hostname) { + processHostnameOption(query, answer); + } + + } +} + +void +Dhcpv4Srv::processClientFqdnOption(const Pkt4Ptr&, Pkt4Ptr&) { +} + +void +Dhcpv4Srv::processHostnameOption(const Pkt4Ptr&, Pkt4Ptr&) { +} + void Dhcpv4Srv::assignLease(const Pkt4Ptr& question, Pkt4Ptr& answer) { diff --git a/src/bin/dhcp4/dhcp4_srv.h b/src/bin/dhcp4/dhcp4_srv.h index f53f2a7508..5ff6b57565 100644 --- a/src/bin/dhcp4/dhcp4_srv.h +++ b/src/bin/dhcp4/dhcp4_srv.h @@ -250,6 +250,56 @@ protected: /// @param msg the message to add options to. void appendBasicOptions(const Pkt4Ptr& question, Pkt4Ptr& msg); + /// @brief Processes Client FQDN and Hostname Options sent by a client. + /// + /// Client may send Client FQDN or Hostname option to communicate its name + /// to the server. Server may use this name to perform DNS update for the + /// lease being assigned to a client. If server takes responsibility for + /// updating DNS for a client it may communicate it by sending the Client + /// FQDN or Hostname %Option back to the client. Server select a different + /// name than requested by a client to update DNS. In such case, the server + /// stores this different name in its response. + /// + /// Client should not send both Client FQDN and Hostname options. However, + /// if client sends both options, server should prefer Client FQDN option + /// and ignore the Hostname option. If Client FQDN option is not present, + /// the Hostname option is processed. + /// + /// The Client FQDN %Option is processed by this function as described in + /// RFC4702. + /// + /// In response to a Hostname %Option sent by a client, the server may send + /// Hostname option with the same or different hostname. If different + /// hostname is sent, it is an indication to the client that server has + /// overridden the client's preferred name and will rather use this + /// different name to update DNS. However, since Hostname option doesn't + /// carry an information whether DNS update will be carried by the server + /// or not, the client is responsible for checking whether DNS update + /// has been performed. + /// + /// After successful processing options stored in the first parameter, + /// this function may add Client FQDN or Hostname option to the response + /// message. In some cases, server may cease to add any options to the + /// response, i.e. when server doesn't support DNS updates. + /// + /// @param query A DISCOVER or REQUEST message from a cient. + /// @param [out] answer A response message to be sent to a client. + void processClientName(const Pkt4Ptr& query, Pkt4Ptr& answer); + +private: + /// @brief Process Client FQDN %Option sent by a client. + /// + /// @param query A DISCOVER or REQUEST message from a cient. + /// @param [out] answer A response message to be sent to a client. + void processClientFqdnOption(const Pkt4Ptr& query, Pkt4Ptr& answer); + + /// @brief Process Hostname %Option sent by a client. + /// + /// @param query A DISCOVER or REQUEST message from a cient. + /// @param [out] answer A response message to be sent to a client. + void processHostnameOption(const Pkt4Ptr& query, Pkt4Ptr& answer); + +protected: /// @brief Attempts to renew received addresses /// /// Attempts to renew existing lease. This typically includes finding a lease that diff --git a/src/bin/dhcp4/tests/Makefile.am b/src/bin/dhcp4/tests/Makefile.am index 9390518ff4..cdeaae97ed 100644 --- a/src/bin/dhcp4/tests/Makefile.am +++ b/src/bin/dhcp4/tests/Makefile.am @@ -70,6 +70,7 @@ dhcp4_unittests_SOURCES += dhcp4_unittests.cc dhcp4_unittests_SOURCES += dhcp4_srv_unittest.cc dhcp4_unittests_SOURCES += ctrl_dhcp4_srv_unittest.cc dhcp4_unittests_SOURCES += config_parser_unittest.cc +dhcp4_unittests_SOURCES += fqdn_unittest.cc dhcp4_unittests_SOURCES += marker_file.cc nodist_dhcp4_unittests_SOURCES = ../dhcp4_messages.h ../dhcp4_messages.cc nodist_dhcp4_unittests_SOURCES += marker_file.h test_libraries.h diff --git a/src/bin/dhcp4/tests/dhcp4_test_utils.h b/src/bin/dhcp4/tests/dhcp4_test_utils.h index ff82ee9b69..e84e6dcd0a 100644 --- a/src/bin/dhcp4/tests/dhcp4_test_utils.h +++ b/src/bin/dhcp4/tests/dhcp4_test_utils.h @@ -132,6 +132,7 @@ public: using Dhcpv4Srv::processRelease; using Dhcpv4Srv::processDecline; using Dhcpv4Srv::processInform; + using Dhcpv4Srv::processClientName; using Dhcpv4Srv::getServerID; using Dhcpv4Srv::loadServerID; using Dhcpv4Srv::generateServerID; diff --git a/src/bin/dhcp4/tests/fqdn_unittest.cc b/src/bin/dhcp4/tests/fqdn_unittest.cc new file mode 100644 index 0000000000..656bd30aa4 --- /dev/null +++ b/src/bin/dhcp4/tests/fqdn_unittest.cc @@ -0,0 +1,143 @@ +// Copyright (C) 2013 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 +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH +// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, +// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE +// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +// PERFORMANCE OF THIS SOFTWARE. + +#include +#include +#include +#include + +#include +#include + +using namespace isc; +using namespace isc::asiolink; +using namespace isc::dhcp; +using namespace isc::test; + +namespace { +class FqdnDhcpv4SrvTest : public Dhcpv4SrvTest { +public: + FqdnDhcpv4SrvTest() : Dhcpv4SrvTest() { + srv_ = new NakedDhcpv4Srv(0); + } + + virtual ~FqdnDhcpv4SrvTest() { + delete srv_; + } + + // Create an instance of the DHCPv4 Client FQDN Option. + Option4ClientFqdnPtr + createClientFqdn(const uint8_t flags, + const std::string& fqdn_name, + const Option4ClientFqdn::DomainNameType fqdn_type) { + return (Option4ClientFqdnPtr(new Option4ClientFqdn(flags, + Option4ClientFqdn:: + RCODE_CLIENT(), + fqdn_name, + fqdn_type))); + } + + Option4ClientFqdnPtr getClientFqdnOption(const Pkt4Ptr& pkt) { + return (boost::dynamic_pointer_cast< + Option4ClientFqdn>(pkt->getOption(DHO_FQDN))); + } + + // Create a message holding DHCPv4 Client FQDN Option. + Pkt4Ptr generatePktWithFqdn(const uint8_t msg_type, + const uint8_t fqdn_flags, + const std::string& fqdn_domain_name, + const Option4ClientFqdn::DomainNameType + fqdn_type, + const bool include_prl) { + 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()); + } + // Client id is required. + pkt->addOption(generateClientId()); + + // Create Client FQDN Option with the specified flags and + // domain-name. + pkt->addOption(createClientFqdn(fqdn_flags, fqdn_domain_name, + fqdn_type)); + + // Control whether or not to request that server returns the FQDN + // option. Server may be configured to always return it or return + // only in case client requested it. + if (include_prl) { + OptionUint8ArrayPtr option_prl = + OptionUint8ArrayPtr(new OptionUint8Array(Option::V4, + DHO_DHCP_PARAMETER_REQUEST_LIST)); + option_prl->addValue(DHO_FQDN); + } + 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, + const std::string& exp_domain_name) { + ASSERT_TRUE(getClientFqdnOption(query)); + + Pkt4Ptr answer; + if (query->getType() == DHCPDISCOVER) { + answer.reset(new Pkt4(DHCPOFFER, 1234)); + + } else { + answer.reset(new Pkt4(DHCPACK, 1234)); + + } + ASSERT_NO_THROW(srv_->processClientName(query, answer)); + + Option4ClientFqdnPtr fqdn = getClientFqdnOption(answer); + ASSERT_TRUE(fqdn); + + const bool flag_n = (exp_flags & Option4ClientFqdn::FLAG_N) != 0; + const bool flag_s = (exp_flags & Option4ClientFqdn::FLAG_S) != 0; + const bool flag_o = (exp_flags & Option4ClientFqdn::FLAG_O) != 0; + const bool flag_e = (exp_flags & Option4ClientFqdn::FLAG_E) != 0; + + EXPECT_EQ(flag_n, fqdn->getFlag(Option4ClientFqdn::FLAG_N)); + EXPECT_EQ(flag_s, fqdn->getFlag(Option4ClientFqdn::FLAG_S)); + EXPECT_EQ(flag_o, fqdn->getFlag(Option4ClientFqdn::FLAG_O)); + EXPECT_EQ(flag_e, fqdn->getFlag(Option4ClientFqdn::FLAG_E)); + + EXPECT_EQ(exp_domain_name, fqdn->getDomainName()); + EXPECT_EQ(Option4ClientFqdn::FULL, fqdn->getDomainNameType()); + + } + +private: + NakedDhcpv4Srv* srv_; + +}; + +TEST_F(FqdnDhcpv4SrvTest, basic) { + Pkt4Ptr query = generatePktWithFqdn(DHCPREQUEST, + Option4ClientFqdn::FLAG_E | + Option4ClientFqdn::FLAG_S, + "myhost.example.com.", + Option4ClientFqdn::FULL, + true); + + testProcessFqdn(query, + Option4ClientFqdn::FLAG_E | Option4ClientFqdn::FLAG_S, + "myhost.example.com."); + +} + +} // end of anonymous namespace