Commit 41c4d829 authored by Marcin Siodelski's avatar Marcin Siodelski

[3035] Added stub implementation for the function processing client FQDN.

parent 13542119
......@@ -18,6 +18,8 @@
#include <dhcp/hwaddr.h>
#include <dhcp/iface_mgr.h>
#include <dhcp/option4_addrlst.h>
#include <dhcp/option4_client_fqdn.h>
#include <dhcp/option_custom.h>
#include <dhcp/option_int.h>
#include <dhcp/option_int_array.h>
#include <dhcp/pkt4.h>
......@@ -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<Option4ClientFqdn>
(query->getOption(DHO_FQDN));
if (fqdn) {
processClientFqdnOption(query, answer);
} else {
OptionCustomPtr hostname = boost::dynamic_pointer_cast<OptionCustom>
(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) {
......
......@@ -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
......
......@@ -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
......
......@@ -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;
......
// 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 <config.h>
#include <asiolink/io_address.h>
#include <dhcp/option4_client_fqdn.h>
#include <dhcp4/tests/dhcp4_test_utils.h>
#include <gtest/gtest.h>
#include <boost/scoped_ptr.hpp>
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
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