From: Marcin Siodelski Date: Mon, 2 Sep 2013 15:19:53 +0000 (+0200) Subject: [3035] Implemented DHCPv4 srv function to process an FQDN option. X-Git-Tag: bind10-1.2.0beta1-release~102^2~21^2~23 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=fcedc148b175e78928bf0f46d904e088ef549b00;p=thirdparty%2Fkea.git [3035] Implemented DHCPv4 srv function to process an FQDN option. --- diff --git a/src/bin/dhcp4/dhcp4_srv.cc b/src/bin/dhcp4/dhcp4_srv.cc index 253270a2ed..d60cfe4e4f 100644 --- a/src/bin/dhcp4/dhcp4_srv.cc +++ b/src/bin/dhcp4/dhcp4_srv.cc @@ -76,6 +76,34 @@ Dhcp4Hooks Hooks; namespace isc { namespace dhcp { +namespace { + +// The following constants describe server's behavior with respect to the +// DHCPv4 Client FQDN Option sent by a client. They will be removed +// when DDNS parameters for DHCPv4 are implemented with the ticket #3033. + +// Should server always include the FQDN option in its response, regardless +// if it has been requested in Parameter Request List Option (Disabled). +const bool FQDN_ALWAYS_INCLUDE = false; +// Enable A RR update delegation to the client (Disabled). +const bool FQDN_ALLOW_CLIENT_UPDATE = false; +// Globally enable updates (Enabled). +const bool FQDN_ENABLE_UPDATE = true; +// The partial name generated for the client if empty name has been +// supplied. +const char* FQDN_GENERATED_PARTIAL_NAME = "myhost"; +// Do update, even if client requested no updates with N flag (Disabled). +const bool FQDN_OVERRIDE_NO_UPDATE = false; +// Server performs an update when client requested delegation (Enabled). +const bool FQDN_OVERRIDE_CLIENT_UPDATE = true; +// The fully qualified domain-name suffix if partial name provided by +// a client. +const char* FQDN_PARTIAL_SUFFIX = "example.com"; +// Should server replace the domain-name supplied by the client (Disabled). +const bool FQDN_REPLACE_CLIENT_NAME = false; + +} + /// @brief file name of a server-id file /// /// Server must store its server identifier in persistent storage that must not @@ -695,6 +723,74 @@ Dhcpv4Srv::processClientFqdnOption(const Option4ClientFqdnPtr& fqdn, fqdn_resp->setFlag(Option4ClientFqdn::FLAG_O, 0); fqdn_resp->setFlag(Option4ClientFqdn::FLAG_N, 0); + // Conditions when N flag has to be set to indicate that server will not + // perform DNS updates: + // 1. Updates are globally disabled, + // 2. Client requested no update and server respects it, + // 3. Client requested that the foward DNS update is delegated to the client + // but server neither respects requests for forward update delegation nor + // it is configured to send update on its own when client requested + // delegation. + if (!FQDN_ENABLE_UPDATE || + (fqdn->getFlag(Option4ClientFqdn::FLAG_N) && + !FQDN_OVERRIDE_NO_UPDATE) || + (!fqdn->getFlag(Option4ClientFqdn::FLAG_S) && + !FQDN_ALLOW_CLIENT_UPDATE && !FQDN_OVERRIDE_CLIENT_UPDATE)) { + fqdn_resp->setFlag(Option4ClientFqdn::FLAG_N, true); + + // Conditions when S flag is set to indicate that server will perform DNS + // update on its own: + // 1. Client requested that server performs DNS update and DNS updates are + // globally enabled. + // 2. Client requested that server delegates forward update to the client + // but server doesn't respect requests for delegation and it is + // configured to perform an update on its own when client requested the + // delegation. + } else if (fqdn->getFlag(Option4ClientFqdn::FLAG_S) || + (!fqdn->getFlag(Option4ClientFqdn::FLAG_S) && + !FQDN_ALLOW_CLIENT_UPDATE && FQDN_OVERRIDE_CLIENT_UPDATE)) { + fqdn_resp->setFlag(Option4ClientFqdn::FLAG_S, true); + } + + // Server MUST set the O flag if it has overriden the client's setting + // of S flag. + if (fqdn->getFlag(Option4ClientFqdn::FLAG_S) != + fqdn_resp->getFlag(Option4ClientFqdn::FLAG_S)) { + fqdn_resp->setFlag(Option4ClientFqdn::FLAG_O, true); + } + + // If client suppled partial or empty domain-name, server should generate + // one. + if (fqdn->getDomainNameType() == Option4ClientFqdn::PARTIAL) { + std::ostringstream name; + if (fqdn->getDomainName().empty()) { + name << FQDN_GENERATED_PARTIAL_NAME; + } else { + name << fqdn->getDomainName(); + } + name << "." << FQDN_PARTIAL_SUFFIX; + fqdn_resp->setDomainName(name.str(), Option4ClientFqdn::FULL); + + // Server may be configured to replace a name supplied by a client, even if + // client supplied fully qualified domain-name. + } else if(FQDN_REPLACE_CLIENT_NAME) { + std::ostringstream name; + name << FQDN_GENERATED_PARTIAL_NAME << "." << FQDN_PARTIAL_SUFFIX; + fqdn_resp->setDomainName(name.str(), Option4ClientFqdn::FULL); + } + + // Add FQDN option to the response message. Note that, there may be some + // cases when server may choose not to include the FQDN option in a + // response to a client. In such cases, the FQDN should be removed from the + // outgoing message. In theory we could cease to include the FQDN option + // in this function until it is confirmed that it should be included. + // However, we include it here for simplicity. Functions used to acquire + // lease for a client will scan the response message for FQDN and if it + // is found they will take necessary actions to store the FQDN information + // in the lease database as well as to generate NameChangeRequests to DNS. + // If we don't store the option in the reponse message, we will have to + // propagate it in the different way to the functions which acquire the + // lease. This would require modifications to the API of this class. answer->addOption(fqdn_resp); } diff --git a/src/bin/dhcp4/tests/fqdn_unittest.cc b/src/bin/dhcp4/tests/fqdn_unittest.cc index 0b4c2c95d8..ac549a994d 100644 --- a/src/bin/dhcp4/tests/fqdn_unittest.cc +++ b/src/bin/dhcp4/tests/fqdn_unittest.cc @@ -174,13 +174,25 @@ TEST_F(FqdnDhcpv4SrvTest, serverUpdateForwardNoName) { } +// Test server's response when client requests no DNS update. +TEST_F(FqdnDhcpv4SrvTest, noUpdate) { + Pkt4Ptr query = generatePktWithFqdn(DHCPREQUEST, + Option4ClientFqdn::FLAG_E | + Option4ClientFqdn::FLAG_N, + "myhost.example.com.", + Option4ClientFqdn::FULL, + true); + testProcessFqdn(query, Option4ClientFqdn::FLAG_E | Option4ClientFqdn::FLAG_N, + "myhost.example.com."); +} + // Test that server does not accept delegation of the forward DNS update // to a client. TEST_F(FqdnDhcpv4SrvTest, clientUpdateNotAllowed) { Pkt4Ptr query = generatePktWithFqdn(DHCPREQUEST, Option4ClientFqdn::FLAG_E, "myhost.example.com.", - Option4ClientFqdn::PARTIAL, + Option4ClientFqdn::FULL, true); testProcessFqdn(query, Option4ClientFqdn::FLAG_E |