Commit 42b1f1e4 authored by Thomas Markwalder's avatar Thomas Markwalder
Browse files

[master] Merge branch 'trac3282'

Implements use of dhcp-ddns configuration parameters in b10-dhcp4.
parents f6e165a5 587c5052
......@@ -335,13 +335,6 @@
"item_default": "JSON",
"item_description" : "Format of the update request packet"
},
{
"item_name": "remove-on-renew",
"item_type": "boolean",
"item_optional": true,
"item_default": false,
"item_description": "Enable requesting a DNS Remove, before a DNS Update on renewals"
},
{
"item_name": "always-include-fqdn",
......
......@@ -80,36 +80,6 @@ Dhcp4Hooks Hooks;
namespace isc {
namespace dhcp {
namespace {
// @todo 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.
// @todo Additional configuration parameter which we may consider is the one
// that controls whether the DHCP server sends the removal NameChangeRequest
// if it discovers that the entry for the particular client exists or that
// it always updates the DNS.
// 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;
// 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;
}
Dhcpv4Srv::Dhcpv4Srv(uint16_t port, const char* dbconfig, const bool use_bcast,
const bool direct_response_desired)
: shutdown_(true), alloc_engine_(), port_(port),
......@@ -596,8 +566,8 @@ Dhcpv4Srv::appendServerID(const Pkt4Ptr& response) {
// The source address for the outbound message should have been set already.
// This is the address that to the best of the server's knowledge will be
// available from the client.
// @todo: perhaps we should consider some more sophisticated server id
// generation, but for the current use cases, it should be ok.
/// @todo: perhaps we should consider some more sophisticated server id
/// generation, but for the current use cases, it should be ok.
response->addOption(OptionPtr(new Option4AddrLst(DHO_DHCP_SERVER_IDENTIFIER,
response->getLocalAddr()))
);
......@@ -666,8 +636,8 @@ Dhcpv4Srv::appendRequestedVendorOptions(const Pkt4Ptr& question, Pkt4Ptr& answer
uint32_t vendor_id = vendor_req->getVendorId();
// Let's try to get ORO within that vendor-option
/// @todo This is very specific to vendor-id=4491 (Cable Labs). Other vendors
/// may have different policies.
/// @todo This is very specific to vendor-id=4491 (Cable Labs). Other
/// vendors may have different policies.
OptionUint8ArrayPtr oro =
boost::dynamic_pointer_cast<OptionUint8Array>(vendor_req->getOption(DOCSIS3_V4_ORO));
......@@ -773,68 +743,19 @@ Dhcpv4Srv::processClientFqdnOption(const Option4ClientFqdnPtr& fqdn,
// response to a client.
Option4ClientFqdnPtr fqdn_resp(new Option4ClientFqdn(*fqdn));
// RFC4702, section 4 - set 'NOS' flags to 0.
fqdn_resp->setFlag(Option4ClientFqdn::FLAG_S, 0);
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 forward 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);
}
// Set the server S, N, and O flags based on client's flags and
// current configuration.
D2ClientMgr& d2_mgr = CfgMgr::instance().getD2ClientMgr();
d2_mgr.adjustFqdnFlags<Option4ClientFqdn>(*fqdn, *fqdn_resp);
// If client suppled partial or empty domain-name, server should generate
// one.
if (fqdn->getDomainNameType() == Option4ClientFqdn::PARTIAL) {
std::ostringstream name;
if (fqdn->getDomainName().empty() || FQDN_REPLACE_CLIENT_NAME) {
fqdn_resp->setDomainName("", Option4ClientFqdn::PARTIAL);
// Carry over the client's E flag.
fqdn_resp->setFlag(Option4ClientFqdn::FLAG_E,
fqdn->getFlag(Option4ClientFqdn::FLAG_E));
} 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. The empty domain-name is
// is set to indicate that the name must be generated when the new lease
// is acquired.
} else if(FQDN_REPLACE_CLIENT_NAME) {
fqdn_resp->setDomainName("", Option4ClientFqdn::PARTIAL);
}
// Adjust the domain name based on domain name value and type sent by the
// client and current configuration.
d2_mgr.adjustDomainName<Option4ClientFqdn>(*fqdn, *fqdn_resp);
// 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
......@@ -854,15 +775,20 @@ Dhcpv4Srv::processClientFqdnOption(const Option4ClientFqdnPtr& fqdn,
void
Dhcpv4Srv::processHostnameOption(const OptionCustomPtr& opt_hostname,
Pkt4Ptr& answer) {
// Fetch D2 configuration.
D2ClientMgr& d2_mgr = CfgMgr::instance().getD2ClientMgr();
// Do nothing if the DNS updates are disabled.
if (!FQDN_ENABLE_UPDATE) {
if (!d2_mgr.ddnsEnabled()) {
return;
}
std::string hostname = isc::util::str::trim(opt_hostname->readString());
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.
// If it isn't we ignore this option. (Per RFC 2131, section 3.14)
/// @todo It would be more liberal to accept this and let it fall into
/// the case of replace or less than two below.
if (label_count == 0) {
LOG_DEBUG(dhcp4_logger, DBG_DHCP4_DETAIL_DATA, DHCP4_EMPTY_HOSTNAME);
return;
......@@ -880,21 +806,20 @@ Dhcpv4Srv::processHostnameOption(const OptionCustomPtr& opt_hostname,
// By checking the number of labels present in the hostname we may infer
// whether client has sent the fully qualified or unqualified hostname.
// @todo We may want to reconsider whether it is appropriate for the
// client to send a root domain name as a Hostname. There are
// also extensions to the auto generation of the client's name,
// e.g. conversion to the puny code which may be considered at some point.
// For now, we just remain liberal and expect that the DNS will handle
// conversion if needed and possible.
if (FQDN_REPLACE_CLIENT_NAME || (label_count < 2)) {
/// @todo We may want to reconsider whether it is appropriate for the
/// client to send a root domain name as a Hostname. There are
/// also extensions to the auto generation of the client's name,
/// e.g. conversion to the puny code which may be considered at some point.
/// For now, we just remain liberal and expect that the DNS will handle
/// conversion if needed and possible.
if ((d2_mgr.getD2ClientConfig()->getReplaceClientName()) ||
(label_count < 2)) {
opt_hostname_resp->writeString("");
// 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.
} else if (label_count == 2) {
std::ostringstream resp_hostname;
resp_hostname << hostname << "." << FQDN_PARTIAL_SUFFIX << ".";
opt_hostname_resp->writeString(resp_hostname.str());
// 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));
}
answer->addOption(opt_hostname_resp);
......@@ -985,9 +910,9 @@ queueNameChangeRequest(const isc::dhcp_ddns::NameChangeType chg_type,
void
Dhcpv4Srv::sendNameChangeRequests() {
while (!name_change_reqs_.empty()) {
// @todo Once next NameChangeRequest is picked from the queue
// we should send it to the b10-dhcp_ddns module. Currently we
// just drop it.
/// @todo Once next NameChangeRequest is picked from the queue
/// we should send it to the b10-dhcp_ddns module. Currently we
/// just drop it.
name_change_reqs_.pop();
}
}
......@@ -1006,8 +931,8 @@ Dhcpv4Srv::assignLease(const Pkt4Ptr& question, Pkt4Ptr& answer) {
// thing this client can get is some global information (like DNS
// servers).
// perhaps this should be logged on some higher level? This is most likely
// configuration bug.
// perhaps this should be logged on some higher level? This is most
// likely configuration bug.
LOG_ERROR(dhcp4_logger, DHCP4_SUBNET_SELECTION_FAILED)
.arg(question->getRemoteAddr().toText())
.arg(serverReceivedPacketName(question->getType()));
......@@ -1020,7 +945,7 @@ Dhcpv4Srv::assignLease(const Pkt4Ptr& question, Pkt4Ptr& answer) {
// as siaddr has nothing to do with a lease, but otherwise we would have
// to select subnet twice (performance hit) or update too many functions
// at once.
// @todo: move subnet selection to a common code
/// @todo: move subnet selection to a common code
answer->setSiaddr(subnet->getSiaddr());
LOG_DEBUG(dhcp4_logger, DBG_DHCP4_DETAIL_DATA, DHCP4_SUBNET_SELECTED)
......@@ -1063,8 +988,8 @@ Dhcpv4Srv::assignLease(const Pkt4Ptr& question, Pkt4Ptr& answer) {
(answer->getOption(DHO_HOST_NAME));
if (opt_hostname) {
hostname = opt_hostname->readString();
// @todo It could be configurable what sort of updates the server
// is doing when Hostname option was sent.
/// @todo It could be configurable what sort of updates the
/// server is doing when Hostname option was sent.
fqdn_fwd = true;
fqdn_rev = true;
}
......@@ -1074,7 +999,7 @@ Dhcpv4Srv::assignLease(const Pkt4Ptr& question, Pkt4Ptr& answer) {
// will try to honour the hint, but it is just a hint - some other address
// may be used instead. If fake_allocation is set to false, the lease will
// be inserted into the LeaseMgr as well.
// @todo pass the actual FQDN data.
/// @todo pass the actual FQDN data.
Lease4Ptr old_lease;
Lease4Ptr lease = alloc_engine_->allocateLease4(subnet, client_id, hwaddr,
hint, fqdn_fwd, fqdn_rev,
......@@ -1099,14 +1024,9 @@ 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()) {
hostname = lease->addr_.toText();
// Replace dots with hyphens.
std::replace(hostname.begin(), hostname.end(), '.', '-');
ostringstream stream;
// The partial suffix will need to be replaced with the actual
// domain-name for the client when configuration is implemented.
stream << "host-" << hostname << "." << FQDN_PARTIAL_SUFFIX << ".";
lease->hostname_ = stream.str();
lease->hostname_ = CfgMgr::instance()
.getD2ClientMgr().generateFqdn(lease->addr_);
// The operations below are rather safe, but we want to catch
// any potential exceptions (e.g. invalid lease database backend
// implementation) and log an error.
......@@ -1138,22 +1058,18 @@ Dhcpv4Srv::assignLease(const Pkt4Ptr& question, Pkt4Ptr& answer) {
// Subnet mask (type 1)
answer->addOption(getNetmaskOption(subnet));
// @todo: send renew timer option (T1, option 58)
// @todo: send rebind timer option (T2, option 59)
/// @todo: send renew timer option (T1, option 58)
/// @todo: send rebind timer option (T2, option 59)
// @todo Currently the NameChangeRequests are always generated if
// real (not fake) allocation is being performed. Should we have
// control switch to enable/disable NameChangeRequest creation?
// Perhaps we need a way to detect whether the b10-dhcp-ddns module
// is up an running?
if (!fake_allocation) {
// Create NameChangeRequests if DDNS is enabled and this is a
// real allocation.
if (!fake_allocation && CfgMgr::instance().ddnsEnabled()) {
try {
createNameChangeRequests(lease, old_lease);
} catch (const Exception& ex) {
LOG_ERROR(dhcp4_logger, DHCP4_NCR_CREATION_FAILED)
.arg(ex.what());
}
}
} else {
......@@ -1194,8 +1110,8 @@ Dhcpv4Srv::adjustIfaceData(const Pkt4Ptr& query, const Pkt4Ptr& response) {
// address for the response. Instead, we have to check what address our
// socket is bound to and use it as a source address. This operation
// may throw if for some reason the socket is closed.
// @todo Consider an optimization that we use local address from
// the query if this address is not broadcast.
/// @todo Consider an optimization that we use local address from
/// the query if this address is not broadcast.
SocketInfo sock_info = IfaceMgr::instance().getSocket(*query);
// Set local adddress, port and interface.
response->setLocalAddr(sock_info.addr_);
......@@ -1310,7 +1226,7 @@ Pkt4Ptr
Dhcpv4Srv::processRequest(Pkt4Ptr& request) {
/// @todo Uncomment this (see ticket #3116)
// sanityCheck(request, MANDATORY);
/// sanityCheck(request, MANDATORY);
Pkt4Ptr ack = Pkt4Ptr
(new Pkt4(DHCPACK, request->getTransid()));
......@@ -1352,7 +1268,7 @@ void
Dhcpv4Srv::processRelease(Pkt4Ptr& release) {
/// @todo Uncomment this (see ticket #3116)
// sanityCheck(release, MANDATORY);
/// sanityCheck(release, MANDATORY);
// Try to find client-id
ClientIdPtr client_id;
......@@ -1377,7 +1293,7 @@ Dhcpv4Srv::processRelease(Pkt4Ptr& release) {
// Does the hardware address match? We don't want one client releasing
// second client's leases.
if (lease->hwaddr_ != release->getHWAddr()->hwaddr_) {
// @todo: Print hwaddr from lease as part of ticket #2589
/// @todo: Print hwaddr from lease as part of ticket #2589
LOG_DEBUG(dhcp4_logger, DBG_DHCP4_DETAIL, DHCP4_RELEASE_FAIL_WRONG_HWADDR)
.arg(release->getCiaddr().toText())
.arg(client_id ? client_id->toText() : "(no client-id)")
......@@ -1435,9 +1351,10 @@ Dhcpv4Srv::processRelease(Pkt4Ptr& release) {
.arg(client_id ? client_id->toText() : "(no client-id)")
.arg(release->getHWAddr()->toText());
// Remove existing DNS entries for the lease, if any.
queueNameChangeRequest(isc::dhcp_ddns::CHG_REMOVE, lease);
if (CfgMgr::instance().ddnsEnabled()) {
// Remove existing DNS entries for the lease, if any.
queueNameChangeRequest(isc::dhcp_ddns::CHG_REMOVE, lease);
}
} else {
// Release failed -
LOG_ERROR(dhcp4_logger, DHCP4_RELEASE_FAIL)
......@@ -1678,8 +1595,8 @@ Dhcpv4Srv::openActiveSockets(const uint16_t port,
}
// Let's reopen active sockets. openSockets4 will check internally whether
// sockets are marked active or inactive.
// @todo Optimization: we should not reopen all sockets but rather select
// those that have been affected by the new configuration.
/// @todo Optimization: we should not reopen all sockets but rather select
/// those that have been affected by the new configuration.
isc::dhcp::IfaceMgrErrorMsgCallback error_handler =
boost::bind(&Dhcpv4Srv::ifaceMgrSocket4ErrorHandler, _1);
if (!IfaceMgr::instance().openSockets4(port, use_bcast, error_handler)) {
......
......@@ -2712,7 +2712,6 @@ TEST_F(Dhcp4ParserTest, d2ClientConfig) {
" \"server-port\" : 777, "
" \"ncr-protocol\" : \"UDP\", "
" \"ncr-format\" : \"JSON\", "
" \"remove-on-renew\" : true, "
" \"always-include-fqdn\" : true, "
" \"allow-client-update\" : true, "
" \"override-no-update\" : true, "
......@@ -2745,7 +2744,6 @@ TEST_F(Dhcp4ParserTest, d2ClientConfig) {
EXPECT_EQ(777, d2_client_config->getServerPort());
EXPECT_EQ(dhcp_ddns::NCR_UDP, d2_client_config->getNcrProtocol());
EXPECT_EQ(dhcp_ddns::FMT_JSON, d2_client_config->getNcrFormat());
EXPECT_TRUE(d2_client_config->getRemoveOnRenew());
EXPECT_TRUE(d2_client_config->getAlwaysIncludeFqdn());
EXPECT_TRUE(d2_client_config->getOverrideNoUpdate());
EXPECT_TRUE(d2_client_config->getOverrideClientUpdate());
......@@ -2772,7 +2770,6 @@ TEST_F(Dhcp4ParserTest, invalidD2ClientConfig) {
" \"server-port\" : 5301, "
" \"ncr-protocol\" : \"UDP\", "
" \"ncr-format\" : \"JSON\", "
" \"remove-on-renew\" : true, "
" \"always-include-fqdn\" : true, "
" \"allow-client-update\" : true, "
" \"override-no-update\" : true, "
......
This diff is collapsed.
// Copyright (C) 2013 Internet Systems Consortium, Inc. ("ISC")
// Copyright (C) 2013-2014 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
......@@ -217,7 +217,6 @@ setDomainName(const std::string& domain_name,
} else {
try {
domain_name_.reset(new isc::dns::Name(name));
domain_name_type_ = name_type;
} catch (const Exception& ex) {
isc_throw(InvalidOption4FqdnDomainName,
......@@ -227,6 +226,8 @@ setDomainName(const std::string& domain_name,
}
}
domain_name_type_ = name_type;
}
void
......
// Copyright (C) 2013 Internet Systems Consortium, Inc. ("ISC")
// Copyright (C) 2013-2014 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
......@@ -188,7 +188,6 @@ setDomainName(const std::string& domain_name,
} else {
try {
domain_name_.reset(new isc::dns::Name(name, true));
domain_name_type_ = name_type;
} catch (const Exception& ex) {
isc_throw(InvalidOption6FqdnDomainName, "invalid domain-name value '"
......@@ -197,6 +196,8 @@ setDomainName(const std::string& domain_name,
}
}
domain_name_type_ = name_type;
}
void
......
// Copyright (C) 2013 Internet Systems Consortium, Inc. ("ISC")
// Copyright (C) 2013-2014 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
......@@ -615,6 +615,7 @@ TEST(Option4ClientFqdnTest, setDomainName) {
// Empty domain name (partial). This should be successful.
ASSERT_NO_THROW(option->setDomainName("", Option4ClientFqdn::PARTIAL));
EXPECT_TRUE(option->getDomainName().empty());
EXPECT_EQ(Option4ClientFqdn::PARTIAL, option->getDomainNameType());
// Fully qualified domain-names must not be empty.
EXPECT_THROW(option->setDomainName("", Option4ClientFqdn::FULL),
......
// Copyright (C) 2013 Internet Systems Consortium, Inc. ("ISC")
// Copyright (C) 2013-2014 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
......@@ -537,6 +537,7 @@ TEST(Option6ClientFqdnTest, setDomainName) {
// Empty domain name (partial). This should be successful.
ASSERT_NO_THROW(option->setDomainName("", Option6ClientFqdn::PARTIAL));
EXPECT_TRUE(option->getDomainName().empty());
EXPECT_EQ(Option6ClientFqdn::PARTIAL, option->getDomainNameType());
// Fully qualified domain-names must not be empty.
EXPECT_THROW(option->setDomainName("", Option6ClientFqdn::FULL),
......
// Copyright (C) 2012-2013 Internet Systems Consortium, Inc. ("ISC")
// Copyright (C) 2012-2014 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
......@@ -363,6 +363,10 @@ CfgMgr::getD2ClientConfig() const {
return (d2_client_mgr_.getD2ClientConfig());
}
D2ClientMgr&
CfgMgr::getD2ClientMgr() {
return (d2_client_mgr_);
}
CfgMgr::CfgMgr()
: datadir_(DHCP_DATA_DIR),
......
// Copyright (C) 2012-2013 Internet Systems Consortium, Inc. ("ISC")
// Copyright (C) 2012-2014 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
......@@ -341,7 +341,7 @@ public:
/// pointer.
void setD2ClientConfig(D2ClientConfigPtr& new_config);
/// @param Convenience method for checking if DHCP-DDNS updates are enabled.
/// @brief Convenience method for checking if DHCP-DDNS updates are enabled.
///
/// @return True if the D2 configuration is enabled.
bool ddnsEnabled();
......@@ -351,6 +351,11 @@ public:
/// @return a reference to the current configuration pointer.
const D2ClientConfigPtr& getD2ClientConfig() const;
/// @brief Fetches the DHCP-DDNS manager.
///
/// @return a reference to the DHCP-DDNS manager.
D2ClientMgr& getD2ClientMgr();
protected:
/// @brief Protected constructor.
......
......@@ -29,7 +29,6 @@ D2ClientConfig::D2ClientConfig(const bool enable_updates,
NameChangeProtocol& ncr_protocol,
const dhcp_ddns::
NameChangeFormat& ncr_format,
const bool remove_on_renew,
const bool always_include_fqdn,
const bool override_no_update,
const bool override_client_update,
......@@ -41,7 +40,6 @@ D2ClientConfig::D2ClientConfig(const bool enable_updates,
server_port_(server_port),
ncr_protocol_(ncr_protocol),
ncr_format_(ncr_format),
remove_on_renew_(remove_on_renew),
always_include_fqdn_(always_include_fqdn),
override_no_update_(override_no_update),
override_client_update_(override_client_update),
......@@ -57,13 +55,12 @@ D2ClientConfig::D2ClientConfig()
server_port_(0),
ncr_protocol_(dhcp_ddns::NCR_UDP),
ncr_format_(dhcp_ddns::FMT_JSON),
remove_on_renew_(false),
always_include_fqdn_(false),
override_no_update_(false),
override_client_update_(false),
replace_client_name_(false),
generated_prefix_(""),
qualifying_suffix_("") {
generated_prefix_("myhost"),
qualifying_suffix_("example.com") {
validateContents();
}
......@@ -83,9 +80,8 @@ D2ClientConfig::validateContents() {
<< " is not yet supported");
}
// @todo perhaps more validation we should do yet?
// Are there any invalid combinations of options we need to test against?
// Also do we care about validating contents if it's disabled?
/// @todo perhaps more validation we should do yet?
/// Are there any invalid combinations of options we need to test against?
}
bool
......@@ -95,7 +91,6 @@ D2ClientConfig::operator == (const D2ClientConfig& other) const {
(server_port_ == other.server_port_) &&
(ncr_protocol_ == other.ncr_protocol_) &&
(ncr_format_ == other.ncr_format_) &&
(remove_on_renew_ == other.remove_on_renew_) &&
(always_include_fqdn_ == other.always_include_fqdn_) &&
(override_no_update_ == other.override_no_update_) &&
(override_client_update_ == other.override_client_update_) &&
......@@ -119,7 +114,6 @@ D2ClientConfig::toText() const {
<< ", server_port: " << server_port_
<< ", ncr_protocol: " << ncr_protocol_
<< ", ncr_format: " << ncr_format_
<< ", remove_on_renew: " << (remove_on_renew_ ? "yes" : "no")
<< ", always_include_fqdn: " << (always_include_fqdn_ ?
"yes" : "no")
<< ", override_no_update: " << (override_no_update_ ?
......@@ -142,7 +136,7 @@ operator<<(std::ostream& os, const D2ClientConfig& config) {
}
D2ClientMgr::D2ClientMgr() : d2_client_config_(new D2ClientConfig()) {
// Default contstructor initializes with a disabled config.
// Default constructor initializes with a disabled configuration.
}
D2ClientMgr::~D2ClientMgr(){
......@@ -159,8 +153,8 @@ D2ClientMgr::setD2ClientConfig(D2ClientConfigPtr& new_config) {
// scenarios:
// 1. D2 was enabled but now it is disabled
// - destroy the sender, flush any queued
// 2. D2 is still enabled but server params have changed
// - preserve any queued, reconnect based on sender params
// 2. D2 is still enabled but server parameters have changed
// - preserve any queued, reconnect based on sender parameters
// 3. D2 was was disabled now it is enabled.
// - create sender
//
......@@ -181,5 +175,89 @@ D2ClientMgr::getD2ClientConfig() const {
return (d2_client_config_);
}
void
D2ClientMgr::analyzeFqdn(const bool client_s, const bool client_n,
bool& server_s, bool& server_n) const {
// Per RFC 4702 & 4704, the client N and S flags allow the client to
// request one of three options:
//
// N flag S flag Option
// ------------------------------------------------------------------
// 0 0 client wants to do forward updates (section 3.2)
// 0 1 client wants server to do forward updates (section 3.3)
// 1 0 client wants no one to do updates (section 3.4)
// 1 1 invalid combination
// (Note section numbers cited are for 4702, for 4704 see 5.1, 5.2, and 5.3)
//
// Make a bit mask from the client's flags and use it to set the response
// flags accordingly.
const uint8_t mask = ((client_n ? 2 : 0) + (client_s ? 1 : 0));
switch (mask) {
case 0:
// If updates are enabled and we are overriding client delegation
// then S flag should be true.
server_s = (d2_client_config_->getEnableUpdates() &&
d2_client_config_->getOverrideClientUpdate());
break;
case 1:
server_s = d2_client_config_->getEnableUpdates();
break;
case 2:
// If updates are enabled and we are overriding "no updates" then
// S flag should be true.
server_s = (d2_client_config_->getEnableUpdates() &&
d2_client_config_->getOverrideNoUpdate());
break;