mirror of
https://gitlab.isc.org/isc-projects/kea
synced 2025-08-31 05:55:28 +00:00
Merge branch 'trac3088' (adds d2::NameRemoveTransaction)
Conflicts: src/bin/d2/d2_messages.mes
This commit is contained in:
@@ -65,6 +65,7 @@ b10_dhcp_ddns_SOURCES += d2_zone.cc d2_zone.h
|
||||
b10_dhcp_ddns_SOURCES += dns_client.cc dns_client.h
|
||||
b10_dhcp_ddns_SOURCES += labeled_value.cc labeled_value.h
|
||||
b10_dhcp_ddns_SOURCES += nc_add.cc nc_add.h
|
||||
b10_dhcp_ddns_SOURCES += nc_remove.cc nc_remove.h
|
||||
b10_dhcp_ddns_SOURCES += nc_trans.cc nc_trans.h
|
||||
b10_dhcp_ddns_SOURCES += state_model.cc state_model.h
|
||||
|
||||
|
@@ -325,19 +325,19 @@ message but the attempt to send it suffered a unexpected error. This is most
|
||||
likely a programmatic error, rather than a communications issue. Some or all
|
||||
of the DNS updates requested as part of this request did not succeed.
|
||||
|
||||
% DHCP_DDNS_FORWARD_ADD_BUILD_FAILURE A DNS update message to add a forward DNS entry could not be constructed for this request: %1, reason: %2
|
||||
% DHCP_DDNS_FORWARD_ADD_BUILD_FAILURE DNS udpate message to add a forward DNS entry could not be constructed for this request: %1, reason: %2
|
||||
This is an error message issued when an error occurs attempting to construct
|
||||
the server bound packet requesting a forward address addition. This is due
|
||||
to invalid data contained in the NameChangeRequest. The request will be aborted.
|
||||
This is most likely a configuration issue.
|
||||
|
||||
% DHCP_DDNS_FORWARD_REPLACE_BUILD_FAILURE A DNS update message to replace a forward DNS entry could not be constructed from this request: %1, reason: %2
|
||||
% DHCP_DDNS_FORWARD_REPLACE_BUILD_FAILURE DNS update message to replace a forward DNS entry could not be constructed from this request: %1, reason: %2
|
||||
This is an error message issued when an error occurs attempting to construct
|
||||
the server bound packet requesting a forward address replacement. This is
|
||||
due to invalid data contained in the NameChangeRequest. The request will be
|
||||
aborted. This is most likely a configuration issue.
|
||||
|
||||
% DHCP_DDNS_REVERSE_REPLACE_BUILD_FAILURE A DNS update message to replace a reverse DNS entry could not be constructed from this request: %1, reason: %2
|
||||
% DHCP_DDNS_REVERSE_REPLACE_BUILD_FAILURE DNS update message to replace a reverse DNS entry could not be constructed from this request: %1, reason: %2
|
||||
This is an error message issued when an error occurs attempting to construct
|
||||
the server bound packet requesting a reverse PTR replacement. This is
|
||||
due to invalid data contained in the NameChangeRequest. The request will be
|
||||
@@ -347,7 +347,94 @@ aborted. This is most likely a configuration issue.
|
||||
This is a debug message issued after DHCP_DDNS has submitted DNS mapping
|
||||
additions which were received and accepted by an appropriate DNS server.
|
||||
|
||||
% DHCP_DDNS_ADD_FAILED DHCP_DDNS failed attempting to make DNS mapping additions for this request: %1
|
||||
% DHCP_DDNS_ADD_FAILED DHCP_DDNS failed attempting to make DNS mapping additions for this request: %1, event: %2
|
||||
This is an error message issued after DHCP_DDNS attempts to submit DNS mapping
|
||||
entry additions have failed. The precise reason for the failure should be
|
||||
documented in preceding log entries.
|
||||
|
||||
% DHCP_DDNS_FORWARD_REMOVE_ADDRS_BUILD_FAILURE DNS udpate message to remove a forward DNS Address entry could not be constructed for this request: %1, reason: %2
|
||||
This is an error message issued when an error occurs attempting to construct
|
||||
the server bound packet requesting a forward address (A or AAAA) removal. This
|
||||
is due to invalid data contained in the NameChangeRequest. The request will be
|
||||
aborted. This is most likely a configuration issue.
|
||||
|
||||
% DHCP_DDNS_FORWARD_REMOVE_ADDRS_REJECTED DNS Server, %1, rejected a DNS update request to remove the forward address mapping for FQDN, %2, with an RCODE: %3
|
||||
This is an error message issued when an update was rejected by the DNS server
|
||||
it was sent to for the reason given by the RCODE. The rcode values are defined
|
||||
in RFC 2136.
|
||||
|
||||
% DHCP_DDNS_FORWARD_REMOVE_ADDRS_IO_ERROR DHCP_DDNS encountered an IO error sending a forward mapping address removal for FQDN %1 to DNS server %2
|
||||
This is an error message issued when a communication error occurs while
|
||||
DHCP_DDNS is carrying out a forward address remove. The application will retry
|
||||
against the same server or others as appropriate.
|
||||
|
||||
% DHCP_DDNS_FORWARD_REMOVE_ADDRS_RESP_CORRUPT DHCP_DDNS received a corrupt response from the DNS server, %1, while removing forward address mapping for FQDN, %2
|
||||
This is an error message issued when the response received by DHCP_DDNS, to a
|
||||
update request to remove a forward address mapping, is mangled or malformed.
|
||||
The application will retry against the same server or others as appropriate.
|
||||
|
||||
% DHCP_DDNS_FORWARD_REMOVE_ADDRS_BAD_DNSCLIENT_STATUS DHCP_DDNS received an unknown DNSClient status: %1, while removing a forward address mapping for FQDN %2 to DNS server %3
|
||||
This is an error message issued when DNSClient returns an unrecognized status
|
||||
while DHCP_DDNS was removing a forward address mapping. The request will be
|
||||
aborted. This is most likely a programmatic issue and should be reported.
|
||||
|
||||
% DHCP_DDNS_FORWARD_REMOVE_RRS_BUILD_FAILURE DNS udpate message to remove forward DNS RR entries could not be constructed for this request: %1, reason: %2
|
||||
This is an error message issued when an error occurs attempting to construct
|
||||
the server bound packet requesting forward RR (DHCID RR) removal. This is due
|
||||
to invalid data contained in the NameChangeRequest. The request will be aborted.This is most likely a configuration issue.
|
||||
|
||||
% DHCP_DDNS_FORWARD_REMOVE_RRS_REJECTED DNS Server, %1, rejected a DNS update request to remove forward RR entries for FQDN, %2, with an RCODE: %3
|
||||
This is an error message issued when an update was rejected by the DNS server
|
||||
it was sent to for the reason given by the RCODE. The rcode values are defined
|
||||
in RFC 2136.
|
||||
|
||||
% DHCP_DDNS_FORWARD_REMOVE_RRS_IO_ERROR DHCP_DDNS encountered an IO error sending a forward RR removal for FQDN %1 to DNS server %2
|
||||
This is an error message issued when a communication error occurs while
|
||||
DHCP_DDNS is carrying out a forward RR remove. The application will retry
|
||||
against the same server.
|
||||
|
||||
% DHCP_DDNS_FORWARD_REMOVE_RRS_RESP_CORRUPT DHCP_DDNS received a corrupt response from the DNS server, %1, while removing forward RRs for FQDN, %2
|
||||
This is an error message issued when the response received by DHCP_DDNS, to a
|
||||
update request to remove forward RRs mapping, is mangled or malformed.
|
||||
The application will retry against the same server or others as appropriate.
|
||||
|
||||
% DHCP_DDNS_FORWARD_REMOVE_RRS_BAD_DNSCLIENT_STATUS DHCP_DDNS received an unknown DNSClient status: %1, while removing forward RRs for FQDN %2 to DNS server %3
|
||||
This is an error message issued when DNSClient returns an unrecognized status
|
||||
while DHCP_DDNS was removing forward RRs. The request will be aborted. This is
|
||||
most likely a programmatic issue and should be reported.
|
||||
|
||||
% DHCP_DDNS_REVERSE_REMOVE_BUILD_FAILURE DNS update message to remove a reverse DNS entry could not be constructed from this request: %1, reason: %2
|
||||
This is an error message issued when an error occurs attempting to construct
|
||||
the server bound packet requesting a reverse PTR removal. This is
|
||||
due to invalid data contained in the NameChangeRequest. The request will be
|
||||
aborted. This is most likely a configuration issue.
|
||||
|
||||
% DHCP_DDNS_REVERSE_REMOVE_REJECTED DNS Server, %1, rejected a DNS update request to remove the reverse mapping for FQDN, %2, with an RCODE: %3
|
||||
This is an error message issued when an update was rejected by the DNS server
|
||||
it was sent to for the reason given by the RCODE. The rcode values are defined
|
||||
in RFC 2136.
|
||||
|
||||
% DHCP_DDNS_REVERSE_REMOVE_IO_ERROR DHCP_DDNS encountered an IO error sending a reverse mapping remove for FQDN %1 to DNS server %2
|
||||
This is an error message issued when a communication error occurs while
|
||||
DHCP_DDNS is carrying out a reverse address update. The application will
|
||||
retry against the same server or others as appropriate.
|
||||
|
||||
% DHCP_DDNS_REVERSE_REMOVE_RESP_CORRUPT DHCP_DDNS received a corrupt response from the DNS server, %1, while removing reverse address mapping for FQDN, %2
|
||||
This is an error message issued when the response received by DHCP_DDNS, to a
|
||||
update request to remove a reverse address, is mangled or malformed.
|
||||
The application will retry against the same server or others as appropriate.
|
||||
|
||||
% DHCP_DDNS_REVERSE_REMOVE_BAD_DNSCLIENT_STATUS DHCP_DDNS received an unknown DNSClient status: %1, while removing reverse address mapping for FQDN %2 to DNS server %3
|
||||
This is an error message issued when DNSClient returns an unrecognized status
|
||||
while DHCP_DDNS was removing a reverse address mapping. The request will be
|
||||
aborted. This is most likely a programmatic issue and should be reported.
|
||||
|
||||
% DHCP_DDNS_REMOVE_SUCCEEDED DHCP_DDNS successfully removed the DNS mapping addition for this request: %1
|
||||
This is a debug message issued after DHCP_DDNS has submitted DNS mapping
|
||||
removals which were received and accepted by an appropriate DNS server.
|
||||
|
||||
% DHCP_DDNS_REMOVE_FAILED DHCP_DDNS failed attempting to make DNS mapping removals for this request: %1, event: %2
|
||||
This is an error message issued after DHCP_DDNS attempts to submit DNS mapping
|
||||
entry removals have failed. The precise reason for the failure should be
|
||||
documented in preceding log entries.
|
||||
|
||||
|
@@ -54,17 +54,25 @@ NameAddTransaction::defineEvents() {
|
||||
// Call superclass impl first.
|
||||
NameChangeTransaction::defineEvents();
|
||||
|
||||
// Define NCT events.
|
||||
// Define NameAddTransaction events.
|
||||
defineEvent(FQDN_IN_USE_EVT, "FQDN_IN_USE_EVT");
|
||||
defineEvent(FQDN_NOT_IN_USE_EVT, "FQDN_NOT_IN_USE_EVT");
|
||||
}
|
||||
|
||||
void
|
||||
NameAddTransaction::verifyEvents() {
|
||||
// Call superclass impl first.
|
||||
// Call superclass implementation first to verify its events. These are
|
||||
// events common to all transactions, and they must be defined.
|
||||
// SELECT_SERVER_EVT
|
||||
// SERVER_SELECTED_EVT
|
||||
// SERVER_IO_ERROR_EVT
|
||||
// NO_MORE_SERVERS_EVT
|
||||
// IO_COMPLETED_EVT
|
||||
// UPDATE_OK_EVT
|
||||
// UPDATE_FAILED_EVT
|
||||
NameChangeTransaction::verifyEvents();
|
||||
|
||||
// Verify NCT events.
|
||||
// Verify NameAddTransaction events by attempting to fetch them.
|
||||
getEvent(FQDN_IN_USE_EVT);
|
||||
getEvent(FQDN_NOT_IN_USE_EVT);
|
||||
}
|
||||
@@ -74,7 +82,7 @@ NameAddTransaction::defineStates() {
|
||||
// Call superclass impl first.
|
||||
NameChangeTransaction::defineStates();
|
||||
|
||||
// Define the states.
|
||||
// Define NameAddTransaction states.
|
||||
defineState(READY_ST, "READY_ST",
|
||||
boost::bind(&NameAddTransaction::readyHandler, this));
|
||||
|
||||
@@ -102,10 +110,16 @@ NameAddTransaction::defineStates() {
|
||||
}
|
||||
void
|
||||
NameAddTransaction::verifyStates() {
|
||||
// Call superclass impl first.
|
||||
// Call superclass implementation first to verify its states. These are
|
||||
// states common to all transactions, and they must be defined.
|
||||
// READY_ST
|
||||
// SELECTING_FWD_SERVER_ST
|
||||
// SELECTING_REV_SERVER_ST
|
||||
// PROCESS_TRANS_OK_ST
|
||||
// PROCESS_TRANS_FAILED_ST
|
||||
NameChangeTransaction::verifyStates();
|
||||
|
||||
// Verify NCT states. This ensures that derivations provide the handlers.
|
||||
// Verify NameAddTransaction states by attempting to fetch them.
|
||||
getState(ADDING_FWD_ADDRS_ST);
|
||||
getState(REPLACING_FWD_ADDRS_ST);
|
||||
getState(REPLACING_REV_PTRS_ST);
|
||||
@@ -541,7 +555,9 @@ void
|
||||
NameAddTransaction::processAddFailedHandler() {
|
||||
switch(getNextEvent()) {
|
||||
case UPDATE_FAILED_EVT:
|
||||
LOG_ERROR(dctl_logger, DHCP_DDNS_ADD_FAILED).arg(getNcr()->toText());
|
||||
case NO_MORE_SERVERS_EVT:
|
||||
LOG_ERROR(dctl_logger, DHCP_DDNS_ADD_FAILED).arg(getNcr()->toText())
|
||||
.arg(getContextStr());
|
||||
setNcrStatus(dhcp_ddns::ST_FAILED);
|
||||
endModel();
|
||||
break;
|
||||
@@ -560,27 +576,28 @@ NameAddTransaction::buildAddFwdAddressRequest() {
|
||||
// Construct dns::Name from NCR fqdn.
|
||||
dns::Name fqdn(dns::Name(getNcr()->getFqdn()));
|
||||
|
||||
// Content on this request is based on RFC 4703, section 5.3.1
|
||||
// First build the Prerequisite Section.
|
||||
|
||||
// Create 'FQDN Is Not In Use' prerequisite (RFC 2136, section 2.4.5)
|
||||
// Add the RR to prerequisite section.
|
||||
// Create 'FQDN Is Not In Use' prerequisite and add it to the
|
||||
// prerequisite section.
|
||||
// Based on RFC 2136, section 2.4.5
|
||||
dns::RRsetPtr prereq(new dns::RRset(fqdn, dns::RRClass::NONE(),
|
||||
dns::RRType::ANY(), dns::RRTTL(0)));
|
||||
request->addRRset(D2UpdateMessage::SECTION_PREREQUISITE, prereq);
|
||||
|
||||
// Next build the Update Section.
|
||||
|
||||
// Create the FQDN/IP 'add' RR (RFC 2136, section 2.5.1)
|
||||
// Set the message RData to lease address.
|
||||
// Add the RR to update section.
|
||||
// Create the FQDN/IP 'add' RR and add it to the to update section.
|
||||
// Based on RFC 2136, section 2.5.1
|
||||
dns::RRsetPtr update(new dns::RRset(fqdn, dns::RRClass::IN(),
|
||||
getAddressRRType(), dns::RRTTL(0)));
|
||||
|
||||
addLeaseAddressRdata(update);
|
||||
request->addRRset(D2UpdateMessage::SECTION_UPDATE, update);
|
||||
// Now create the FQDN/DHCID 'add' RR per RFC 4701)
|
||||
// Set the message RData to DHCID.
|
||||
// Add the RR to update section.
|
||||
|
||||
// Now create the FQDN/DHCID 'add' RR and add it to update section.
|
||||
// Based on RFC 2136, section 2.5.1
|
||||
update.reset(new dns::RRset(fqdn, dns::RRClass::IN(),
|
||||
dns::RRType::DHCID(), dns::RRTTL(0)));
|
||||
addDhcidRdata(update);
|
||||
@@ -598,17 +615,19 @@ NameAddTransaction::buildReplaceFwdAddressRequest() {
|
||||
// Construct dns::Name from NCR fqdn.
|
||||
dns::Name fqdn(dns::Name(getNcr()->getFqdn()));
|
||||
|
||||
// Content on this request is based on RFC 4703, section 5.3.2
|
||||
// First build the Prerequisite Section.
|
||||
|
||||
// Create an 'FQDN Is In Use' prerequisite (RFC 2136, section 2.4.4)
|
||||
// Add it to the pre-requisite section.
|
||||
// Create an 'FQDN Is In Use' prerequisite and add it to the
|
||||
// pre-requisite section.
|
||||
// Based on RFC 2136, section 2.4.4
|
||||
dns::RRsetPtr prereq(new dns::RRset(fqdn, dns::RRClass::ANY(),
|
||||
dns::RRType::ANY(), dns::RRTTL(0)));
|
||||
request->addRRset(D2UpdateMessage::SECTION_PREREQUISITE, prereq);
|
||||
|
||||
// Now create an DHCID matches prerequisite RR.
|
||||
// Set the RR's RData to DHCID.
|
||||
// Add it to the pre-requisite section.
|
||||
// Create an DHCID matches prerequisite RR and add it to the
|
||||
// pre-requisite section.
|
||||
// Based on RFC 2136, section 2.4.2.
|
||||
prereq.reset(new dns::RRset(fqdn, dns::RRClass::IN(),
|
||||
dns::RRType::DHCID(), dns::RRTTL(0)));
|
||||
addDhcidRdata(prereq);
|
||||
@@ -616,16 +635,14 @@ NameAddTransaction::buildReplaceFwdAddressRequest() {
|
||||
|
||||
// Next build the Update Section.
|
||||
|
||||
// Create the FQDN/IP 'delete' RR (RFC 2136, section 2.5.1)
|
||||
// Set the message RData to lease address.
|
||||
// Add the RR to update section.
|
||||
// Create the FQDN/IP 'delete' RR and add it to the update section.
|
||||
// Based on RFC 2136, section 2.5.2
|
||||
dns::RRsetPtr update(new dns::RRset(fqdn, dns::RRClass::ANY(),
|
||||
getAddressRRType(), dns::RRTTL(0)));
|
||||
request->addRRset(D2UpdateMessage::SECTION_UPDATE, update);
|
||||
|
||||
// Create the FQDN/IP 'add' RR (RFC 2136, section 2.5.1)
|
||||
// Set the message RData to lease address.
|
||||
// Add the RR to update section.
|
||||
// Create the FQDN/IP 'add' RR and add it to the update section.
|
||||
// Based on RFC 2136, section 2.5.1
|
||||
update.reset(new dns::RRset(fqdn, dns::RRClass::IN(),
|
||||
getAddressRRType(), dns::RRTTL(0)));
|
||||
addLeaseAddressRdata(update);
|
||||
@@ -644,6 +661,7 @@ NameAddTransaction::buildReplaceRevPtrsRequest() {
|
||||
std::string rev_addr = D2CfgMgr::reverseIpAddress(getNcr()->getIpAddress());
|
||||
dns::Name rev_ip(rev_addr);
|
||||
|
||||
// Content on this request is based on RFC 4703, section 5.4
|
||||
// Reverse replacement has no prerequisites so straight on to
|
||||
// building the Update section.
|
||||
|
||||
|
@@ -34,9 +34,10 @@ public:
|
||||
/// @brief Embodies the "life-cycle" required to carry out a DDNS Add update.
|
||||
///
|
||||
/// NameAddTransaction implements a state machine for adding (or replacing) a
|
||||
/// forward DNS mapping. This state machine is based upon the processing logic
|
||||
/// described in RFC 4703, Sections 5.3 and 5.4. That logic may be paraphrased
|
||||
/// as follows:
|
||||
/// forward and/or reverse DNS mapping. This state machine is based upon the
|
||||
/// processing logic described in RFC 4703, Sections 5.3 and 5.4. That logic
|
||||
/// may be paraphrased as follows:
|
||||
///
|
||||
/// @code
|
||||
///
|
||||
/// If the request includes a forward change:
|
||||
@@ -109,7 +110,8 @@ protected:
|
||||
/// @brief Validates the contents of the set of events.
|
||||
///
|
||||
/// Invokes NameChangeTransaction's implementation and then verifies the
|
||||
/// Add transaction's events.
|
||||
/// Add transaction's. This tests that the needed events are in the event
|
||||
/// dictionary.
|
||||
///
|
||||
/// @throw StateModelError if an event value is undefined.
|
||||
virtual void verifyEvents();
|
||||
@@ -125,7 +127,8 @@ protected:
|
||||
/// @brief Validates the contents of the set of states.
|
||||
///
|
||||
/// Invokes NameChangeTransaction's implementation and then verifies the
|
||||
/// Add transaction's states.
|
||||
/// Add transaction's states. This tests that the needed states are in the
|
||||
/// state dictionary.
|
||||
///
|
||||
/// @throw StateModelError if an event value is undefined.
|
||||
virtual void verifyStates();
|
||||
@@ -166,7 +169,7 @@ protected:
|
||||
/// handler simply attempts to select the next server.
|
||||
///
|
||||
/// Transitions to:
|
||||
/// - ADDING_REV_PTRS_ST with next event of SERVER_SELECTED upon successful
|
||||
/// - ADDING_FWD_ADDRS_ST with next event of SERVER_SELECTED upon successful
|
||||
/// server selection
|
||||
///
|
||||
/// - PROCESS_TRANS_FAILED with next event of NO_MORE_SERVERS_EVT upon
|
||||
@@ -329,7 +332,7 @@ protected:
|
||||
/// - PROCESS_TRANS_OK_ST with a next event of UPDATE_OK_EVT upon
|
||||
/// successful replacement.
|
||||
///
|
||||
/// - PROCESS_TRANS_FAILED_ST with a next event of UPDATE_OK_EVT If the
|
||||
/// - PROCESS_TRANS_FAILED_ST with a next event of UPDATE_FAILED_EVT If the
|
||||
/// DNS server rejected the update for any reason or the IO completed
|
||||
/// with an unrecognized status.
|
||||
///
|
||||
@@ -365,8 +368,10 @@ protected:
|
||||
/// @brief State handler for PROCESS_TRANS_FAILED_ST.
|
||||
///
|
||||
/// Entered from:
|
||||
/// - SELECTING_FWD_SERVER_ST with a next event of NO_MORE_SERVERS
|
||||
/// - ADDING_FWD_ADDRS_ST with a next event of UPDATE_FAILED_EVT
|
||||
/// - REPLACING_FWD_ADDRS_ST with a next event of UPDATE_FAILED_EVT
|
||||
/// - SELECTING_REV_SERVER_ST with a next event of NO_MORE_SERVERS
|
||||
/// - REPLACING_REV_PTRS_ST with a next event of UPDATE_FAILED_EVT
|
||||
///
|
||||
/// Sets the transaction status to indicate failure and ends
|
||||
@@ -438,7 +443,7 @@ protected:
|
||||
void buildReplaceRevPtrsRequest();
|
||||
};
|
||||
|
||||
/// @brief Defines a pointer to a NameChangeTransaction.
|
||||
/// @brief Defines a pointer to a NameAddTransaction.
|
||||
typedef boost::shared_ptr<NameAddTransaction> NameAddTransactionPtr;
|
||||
|
||||
} // namespace isc::d2
|
||||
|
695
src/bin/d2/nc_remove.cc
Normal file
695
src/bin/d2/nc_remove.cc
Normal file
@@ -0,0 +1,695 @@
|
||||
// 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 <d2/d2_log.h>
|
||||
#include <d2/d2_cfg_mgr.h>
|
||||
#include <d2/nc_remove.h>
|
||||
|
||||
#include <boost/function.hpp>
|
||||
#include <boost/bind.hpp>
|
||||
|
||||
namespace isc {
|
||||
namespace d2 {
|
||||
|
||||
|
||||
// NameRemoveTransaction states
|
||||
const int NameRemoveTransaction::REMOVING_FWD_ADDRS_ST;
|
||||
const int NameRemoveTransaction::REMOVING_FWD_RRS_ST;
|
||||
const int NameRemoveTransaction::REMOVING_REV_PTRS_ST;
|
||||
|
||||
// NameRemoveTransaction events
|
||||
// Currently NameRemoveTransaction does not define any events.
|
||||
|
||||
NameRemoveTransaction::
|
||||
NameRemoveTransaction(IOServicePtr& io_service,
|
||||
dhcp_ddns::NameChangeRequestPtr& ncr,
|
||||
DdnsDomainPtr& forward_domain,
|
||||
DdnsDomainPtr& reverse_domain)
|
||||
: NameChangeTransaction(io_service, ncr, forward_domain, reverse_domain) {
|
||||
if (ncr->getChangeType() != isc::dhcp_ddns::CHG_REMOVE) {
|
||||
isc_throw (NameRemoveTransactionError,
|
||||
"NameRemoveTransaction, request type must be CHG_REMOVE");
|
||||
}
|
||||
}
|
||||
|
||||
NameRemoveTransaction::~NameRemoveTransaction(){
|
||||
}
|
||||
|
||||
void
|
||||
NameRemoveTransaction::defineEvents() {
|
||||
// Call superclass impl first.
|
||||
NameChangeTransaction::defineEvents();
|
||||
|
||||
// Define NameRemoveTransaction events.
|
||||
// Currently NameRemoveTransaction does not define any events.
|
||||
// defineEvent(TBD_EVENT, "TBD_EVT");
|
||||
}
|
||||
|
||||
void
|
||||
NameRemoveTransaction::verifyEvents() {
|
||||
// Call superclass implementation first to verify its events. These are
|
||||
// events common to all transactions, and they must be defined.
|
||||
// SELECT_SERVER_EVT
|
||||
// SERVER_SELECTED_EVT
|
||||
// SERVER_IO_ERROR_EVT
|
||||
// NO_MORE_SERVERS_EVT
|
||||
// IO_COMPLETED_EVT
|
||||
// UPDATE_OK_EVT
|
||||
// UPDATE_FAILED_EVT
|
||||
NameChangeTransaction::verifyEvents();
|
||||
|
||||
// Verify NameRemoveTransaction events by attempting to fetch them.
|
||||
// Currently NameRemoveTransaction does not define any events.
|
||||
// getEvent(TBD_EVENT);
|
||||
}
|
||||
|
||||
void
|
||||
NameRemoveTransaction::defineStates() {
|
||||
// Call superclass impl first.
|
||||
NameChangeTransaction::defineStates();
|
||||
|
||||
// Define NameRemoveTransaction states.
|
||||
defineState(READY_ST, "READY_ST",
|
||||
boost::bind(&NameRemoveTransaction::readyHandler, this));
|
||||
|
||||
defineState(SELECTING_FWD_SERVER_ST, "SELECTING_FWD_SERVER_ST",
|
||||
boost::bind(&NameRemoveTransaction::selectingFwdServerHandler,
|
||||
this));
|
||||
|
||||
defineState(SELECTING_REV_SERVER_ST, "SELECTING_REV_SERVER_ST",
|
||||
boost::bind(&NameRemoveTransaction::selectingRevServerHandler,
|
||||
this));
|
||||
|
||||
defineState(REMOVING_FWD_ADDRS_ST, "REMOVING_FWD_ADDRS_ST",
|
||||
boost::bind(&NameRemoveTransaction::removingFwdAddrsHandler,
|
||||
this));
|
||||
|
||||
defineState(REMOVING_FWD_RRS_ST, "REMOVING_FWD_RRS_ST",
|
||||
boost::bind(&NameRemoveTransaction::removingFwdRRsHandler,
|
||||
this));
|
||||
|
||||
defineState(REMOVING_REV_PTRS_ST, "REMOVING_REV_PTRS_ST",
|
||||
boost::bind(&NameRemoveTransaction::removingRevPtrsHandler,
|
||||
this));
|
||||
|
||||
defineState(PROCESS_TRANS_OK_ST, "PROCESS_TRANS_OK_ST",
|
||||
boost::bind(&NameRemoveTransaction::processRemoveOkHandler,
|
||||
this));
|
||||
|
||||
defineState(PROCESS_TRANS_FAILED_ST, "PROCESS_TRANS_FAILED_ST",
|
||||
boost::bind(&NameRemoveTransaction::processRemoveFailedHandler,
|
||||
this));
|
||||
}
|
||||
|
||||
void
|
||||
NameRemoveTransaction::verifyStates() {
|
||||
// Call superclass implementation first to verify its states. These are
|
||||
// states common to all transactions, and they must be defined.
|
||||
// READY_ST
|
||||
// SELECTING_FWD_SERVER_ST
|
||||
// SELECTING_REV_SERVER_ST
|
||||
// PROCESS_TRANS_OK_ST
|
||||
// PROCESS_TRANS_FAILED_ST
|
||||
NameChangeTransaction::verifyStates();
|
||||
|
||||
// Verify NameRemoveTransaction states by attempting to fetch them.
|
||||
getState(REMOVING_FWD_ADDRS_ST);
|
||||
getState(REMOVING_FWD_RRS_ST);
|
||||
getState(REMOVING_REV_PTRS_ST);
|
||||
}
|
||||
|
||||
void
|
||||
NameRemoveTransaction::readyHandler() {
|
||||
switch(getNextEvent()) {
|
||||
case START_EVT:
|
||||
if (getForwardDomain()) {
|
||||
// Request includes a forward change, do that first.
|
||||
transition(SELECTING_FWD_SERVER_ST, SELECT_SERVER_EVT);
|
||||
} else {
|
||||
// Reverse change only, transition accordingly.
|
||||
transition(SELECTING_REV_SERVER_ST, SELECT_SERVER_EVT);
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
// Event is invalid.
|
||||
isc_throw(NameRemoveTransactionError,
|
||||
"Wrong event for context: " << getContextStr());
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
NameRemoveTransaction::selectingFwdServerHandler() {
|
||||
switch(getNextEvent()) {
|
||||
case SELECT_SERVER_EVT:
|
||||
// First time through for this transaction, so initialize server
|
||||
// selection.
|
||||
initServerSelection(getForwardDomain());
|
||||
break;
|
||||
case SERVER_IO_ERROR_EVT:
|
||||
// We failed to communicate with current server. Attempt to select
|
||||
// another one below.
|
||||
break;
|
||||
default:
|
||||
// Event is invalid.
|
||||
isc_throw(NameRemoveTransactionError,
|
||||
"Wrong event for context: " << getContextStr());
|
||||
}
|
||||
|
||||
// Select the next server from the list of forward servers.
|
||||
if (selectNextServer()) {
|
||||
// We have a server to try.
|
||||
transition(REMOVING_FWD_ADDRS_ST, SERVER_SELECTED_EVT);
|
||||
}
|
||||
else {
|
||||
// Server list is exhausted, so fail the transaction.
|
||||
transition(PROCESS_TRANS_FAILED_ST, NO_MORE_SERVERS_EVT);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
NameRemoveTransaction::removingFwdAddrsHandler() {
|
||||
if (doOnEntry()) {
|
||||
// Clear the request on initial transition. This allows us to reuse
|
||||
// the request on retries if necessary.
|
||||
clearDnsUpdateRequest();
|
||||
}
|
||||
|
||||
switch(getNextEvent()) {
|
||||
case SERVER_SELECTED_EVT:
|
||||
if (!getDnsUpdateRequest()) {
|
||||
// Request hasn't been constructed yet, so build it.
|
||||
try {
|
||||
buildRemoveFwdAddressRequest();
|
||||
} catch (const std::exception& ex) {
|
||||
// While unlikely, the build might fail if we have invalid
|
||||
// data. Should that be the case, we need to fail the
|
||||
// transaction.
|
||||
LOG_ERROR(dctl_logger,
|
||||
DHCP_DDNS_FORWARD_REMOVE_ADDRS_BUILD_FAILURE)
|
||||
.arg(getNcr()->toText())
|
||||
.arg(ex.what());
|
||||
transition(PROCESS_TRANS_FAILED_ST, UPDATE_FAILED_EVT);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Call sendUpdate() to initiate the async send. Note it also sets
|
||||
// next event to NOP_EVT.
|
||||
sendUpdate();
|
||||
break;
|
||||
|
||||
case IO_COMPLETED_EVT: {
|
||||
switch (getDnsUpdateStatus()) {
|
||||
case DNSClient::SUCCESS: {
|
||||
// We successfully received a response packet from the server.
|
||||
const dns::Rcode& rcode = getDnsUpdateResponse()->getRcode();
|
||||
if ((rcode == dns::Rcode::NOERROR()) ||
|
||||
(rcode == dns::Rcode::NXDOMAIN())) {
|
||||
// We were able to remove it or it wasn't there, now we
|
||||
// need to remove any other RRs for this FQDN.
|
||||
transition(REMOVING_FWD_RRS_ST, UPDATE_OK_EVT);
|
||||
} else {
|
||||
// Per RFC4703 any other value means cease.
|
||||
// If we get not authorized should we try the next server in
|
||||
// the list? @todo This needs some discussion perhaps.
|
||||
LOG_ERROR(dctl_logger, DHCP_DDNS_FORWARD_REMOVE_ADDRS_REJECTED)
|
||||
.arg(getCurrentServer()->getIpAddress())
|
||||
.arg(getNcr()->getFqdn())
|
||||
.arg(rcode.getCode());
|
||||
transition(PROCESS_TRANS_FAILED_ST, UPDATE_FAILED_EVT);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case DNSClient::TIMEOUT:
|
||||
case DNSClient::OTHER:
|
||||
// We couldn't send to the current server, log it and set up
|
||||
// to select the next server for a retry.
|
||||
// @note For now we treat OTHER as an IO error like TIMEOUT. It
|
||||
// is not entirely clear if this is accurate.
|
||||
LOG_ERROR(dctl_logger, DHCP_DDNS_FORWARD_REMOVE_ADDRS_IO_ERROR)
|
||||
.arg(getNcr()->getFqdn())
|
||||
.arg(getCurrentServer()->getIpAddress());
|
||||
|
||||
retryTransition(SELECTING_FWD_SERVER_ST);
|
||||
break;
|
||||
|
||||
case DNSClient::INVALID_RESPONSE:
|
||||
// A response was received but was corrupt. Retry it like an IO
|
||||
// error.
|
||||
LOG_ERROR(dctl_logger, DHCP_DDNS_FORWARD_REMOVE_ADDRS_RESP_CORRUPT)
|
||||
.arg(getCurrentServer()->getIpAddress())
|
||||
.arg(getNcr()->getFqdn());
|
||||
|
||||
retryTransition(SELECTING_FWD_SERVER_ST);
|
||||
break;
|
||||
|
||||
default:
|
||||
// Any other value and we will fail this transaction, something
|
||||
// bigger is wrong.
|
||||
LOG_ERROR(dctl_logger,
|
||||
DHCP_DDNS_FORWARD_REMOVE_ADDRS_BAD_DNSCLIENT_STATUS)
|
||||
.arg(getDnsUpdateStatus())
|
||||
.arg(getNcr()->getFqdn())
|
||||
.arg(getCurrentServer()->getIpAddress());
|
||||
|
||||
transition(PROCESS_TRANS_FAILED_ST, UPDATE_FAILED_EVT);
|
||||
break;
|
||||
} // end switch on dns_status
|
||||
|
||||
break;
|
||||
} // end case IO_COMPLETE_EVT
|
||||
|
||||
default:
|
||||
// Event is invalid.
|
||||
isc_throw(NameRemoveTransactionError,
|
||||
"Wrong event for context: " << getContextStr());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
NameRemoveTransaction::removingFwdRRsHandler() {
|
||||
if (doOnEntry()) {
|
||||
// Clear the request on initial transition. This allows us to reuse
|
||||
// the request on retries if necessary.
|
||||
clearDnsUpdateRequest();
|
||||
}
|
||||
|
||||
switch(getNextEvent()) {
|
||||
case UPDATE_OK_EVT:
|
||||
case SERVER_SELECTED_EVT:
|
||||
if (!getDnsUpdateRequest()) {
|
||||
// Request hasn't been constructed yet, so build it.
|
||||
try {
|
||||
buildRemoveFwdRRsRequest();
|
||||
} catch (const std::exception& ex) {
|
||||
// While unlikely, the build might fail if we have invalid
|
||||
// data. Should that be the case, we need to fail the
|
||||
// transaction.
|
||||
LOG_ERROR(dctl_logger,
|
||||
DHCP_DDNS_FORWARD_REMOVE_RRS_BUILD_FAILURE)
|
||||
.arg(getNcr()->toText())
|
||||
.arg(ex.what());
|
||||
transition(PROCESS_TRANS_FAILED_ST, UPDATE_FAILED_EVT);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Call sendUpdate() to initiate the async send. Note it also sets
|
||||
// next event to NOP_EVT.
|
||||
sendUpdate();
|
||||
break;
|
||||
|
||||
case IO_COMPLETED_EVT: {
|
||||
switch (getDnsUpdateStatus()) {
|
||||
case DNSClient::SUCCESS: {
|
||||
// We successfully received a response packet from the server.
|
||||
const dns::Rcode& rcode = getDnsUpdateResponse()->getRcode();
|
||||
// @todo Not sure if NXDOMAIN is ok here, but I think so.
|
||||
// A Rcode of NXDOMAIN would mean there are no RRs for the FQDN,
|
||||
// which is fine. We were asked to delete them, they are not there
|
||||
// so all is well.
|
||||
if ((rcode == dns::Rcode::NOERROR()) ||
|
||||
(rcode == dns::Rcode::NXDOMAIN())) {
|
||||
// We were able to remove the forward mapping. Mark it as done.
|
||||
setForwardChangeCompleted(true);
|
||||
|
||||
// If request calls for reverse update then do that next,
|
||||
// otherwise we can process ok.
|
||||
if (getReverseDomain()) {
|
||||
transition(SELECTING_REV_SERVER_ST, SELECT_SERVER_EVT);
|
||||
} else {
|
||||
transition(PROCESS_TRANS_OK_ST, UPDATE_OK_EVT);
|
||||
}
|
||||
} else {
|
||||
// Per RFC4703 any other value means cease.
|
||||
// If we get not authorized should try the next server in
|
||||
// the list? @todo This needs some discussion perhaps.
|
||||
LOG_ERROR(dctl_logger, DHCP_DDNS_FORWARD_REMOVE_RRS_REJECTED)
|
||||
.arg(getCurrentServer()->getIpAddress())
|
||||
.arg(getNcr()->getFqdn())
|
||||
.arg(rcode.getCode());
|
||||
transition(PROCESS_TRANS_FAILED_ST, UPDATE_FAILED_EVT);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case DNSClient::TIMEOUT:
|
||||
case DNSClient::OTHER:
|
||||
// We couldn't send to the current server, log it and set up
|
||||
// to select the next server for a retry.
|
||||
// @note For now we treat OTHER as an IO error like TIMEOUT. It
|
||||
// is not entirely clear if this is accurate.
|
||||
LOG_ERROR(dctl_logger, DHCP_DDNS_FORWARD_REMOVE_RRS_IO_ERROR)
|
||||
.arg(getNcr()->getFqdn())
|
||||
.arg(getCurrentServer()->getIpAddress());
|
||||
|
||||
// @note If we exhaust the IO retries for the current server
|
||||
// due to IO failures, we will abort the remaining updates.
|
||||
// The rational is that we are only in this state, if the remove
|
||||
// of the forward address RR succeeded (removingFwdAddrsHandler)
|
||||
// on the current server. Therefore we should not attempt another
|
||||
// removal on a different server. This is perhaps a point
|
||||
// for discussion.
|
||||
// @todo Should we go ahead with the reverse remove?
|
||||
retryTransition(PROCESS_TRANS_FAILED_ST);
|
||||
break;
|
||||
|
||||
case DNSClient::INVALID_RESPONSE:
|
||||
// A response was received but was corrupt. Retry it like an IO
|
||||
// error.
|
||||
LOG_ERROR(dctl_logger, DHCP_DDNS_FORWARD_REMOVE_RRS_RESP_CORRUPT)
|
||||
.arg(getCurrentServer()->getIpAddress())
|
||||
.arg(getNcr()->getFqdn());
|
||||
|
||||
// If we are out of retries on this server abandon the transaction.
|
||||
// (Same logic as the case for TIMEOUT above).
|
||||
retryTransition(PROCESS_TRANS_FAILED_ST);
|
||||
break;
|
||||
|
||||
default:
|
||||
// Any other value and we will fail this transaction, something
|
||||
// bigger is wrong.
|
||||
LOG_ERROR(dctl_logger,
|
||||
DHCP_DDNS_FORWARD_REMOVE_RRS_BAD_DNSCLIENT_STATUS)
|
||||
.arg(getDnsUpdateStatus())
|
||||
.arg(getNcr()->getFqdn())
|
||||
.arg(getCurrentServer()->getIpAddress());
|
||||
|
||||
transition(PROCESS_TRANS_FAILED_ST, UPDATE_FAILED_EVT);
|
||||
break;
|
||||
} // end switch on dns_status
|
||||
|
||||
break;
|
||||
} // end case IO_COMPLETE_EVT
|
||||
|
||||
default:
|
||||
// Event is invalid.
|
||||
isc_throw(NameRemoveTransactionError,
|
||||
"Wrong event for context: " << getContextStr());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
NameRemoveTransaction::selectingRevServerHandler() {
|
||||
switch(getNextEvent()) {
|
||||
case SELECT_SERVER_EVT:
|
||||
// First time through for this transaction, so initialize server
|
||||
// selection.
|
||||
initServerSelection(getReverseDomain());
|
||||
break;
|
||||
case SERVER_IO_ERROR_EVT:
|
||||
// We failed to communicate with current server. Attempt to select
|
||||
// another one below.
|
||||
break;
|
||||
default:
|
||||
// Event is invalid.
|
||||
isc_throw(NameRemoveTransactionError,
|
||||
"Wrong event for context: " << getContextStr());
|
||||
}
|
||||
|
||||
// Select the next server from the list of forward servers.
|
||||
if (selectNextServer()) {
|
||||
// We have a server to try.
|
||||
transition(REMOVING_REV_PTRS_ST, SERVER_SELECTED_EVT);
|
||||
}
|
||||
else {
|
||||
// Server list is exhausted, so fail the transaction.
|
||||
transition(PROCESS_TRANS_FAILED_ST, NO_MORE_SERVERS_EVT);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
NameRemoveTransaction::removingRevPtrsHandler() {
|
||||
if (doOnEntry()) {
|
||||
// Clear the request on initial transition. This allows us to reuse
|
||||
// the request on retries if necessary.
|
||||
clearDnsUpdateRequest();
|
||||
}
|
||||
|
||||
switch(getNextEvent()) {
|
||||
case SERVER_SELECTED_EVT:
|
||||
if (!getDnsUpdateRequest()) {
|
||||
// Request hasn't been constructed yet, so build it.
|
||||
try {
|
||||
buildRemoveRevPtrsRequest();
|
||||
} catch (const std::exception& ex) {
|
||||
// While unlikely, the build might fail if we have invalid
|
||||
// data. Should that be the case, we need to fail the
|
||||
// transaction.
|
||||
LOG_ERROR(dctl_logger, DHCP_DDNS_REVERSE_REMOVE_BUILD_FAILURE)
|
||||
.arg(getNcr()->toText())
|
||||
.arg(ex.what());
|
||||
transition(PROCESS_TRANS_FAILED_ST, UPDATE_FAILED_EVT);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Call sendUpdate() to initiate the async send. Note it also sets
|
||||
// next event to NOP_EVT.
|
||||
sendUpdate();
|
||||
break;
|
||||
|
||||
case IO_COMPLETED_EVT: {
|
||||
switch (getDnsUpdateStatus()) {
|
||||
case DNSClient::SUCCESS: {
|
||||
// We successfully received a response packet from the server.
|
||||
const dns::Rcode& rcode = getDnsUpdateResponse()->getRcode();
|
||||
if ((rcode == dns::Rcode::NOERROR()) ||
|
||||
(rcode == dns::Rcode::NXDOMAIN())) {
|
||||
// We were able to update the reverse mapping. Mark it as done.
|
||||
// @todo For now we are also treating NXDOMAIN as success.
|
||||
setReverseChangeCompleted(true);
|
||||
transition(PROCESS_TRANS_OK_ST, UPDATE_OK_EVT);
|
||||
} else {
|
||||
// Per RFC4703 any other value means cease.
|
||||
// If we get not authorized should try the next server in
|
||||
// the list? @todo This needs some discussion perhaps.
|
||||
LOG_ERROR(dctl_logger, DHCP_DDNS_REVERSE_REMOVE_REJECTED)
|
||||
.arg(getCurrentServer()->getIpAddress())
|
||||
.arg(getNcr()->getFqdn())
|
||||
.arg(rcode.getCode());
|
||||
transition(PROCESS_TRANS_FAILED_ST, UPDATE_FAILED_EVT);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case DNSClient::TIMEOUT:
|
||||
case DNSClient::OTHER:
|
||||
// We couldn't send to the current server, log it and set up
|
||||
// to select the next server for a retry.
|
||||
// @note For now we treat OTHER as an IO error like TIMEOUT. It
|
||||
// is not entirely clear if this is accurate.
|
||||
LOG_ERROR(dctl_logger, DHCP_DDNS_REVERSE_REMOVE_IO_ERROR)
|
||||
.arg(getNcr()->getFqdn())
|
||||
.arg(getCurrentServer()->getIpAddress());
|
||||
|
||||
// If we are out of retries on this server, we go back and start
|
||||
// all over on a new server.
|
||||
retryTransition(SELECTING_REV_SERVER_ST);
|
||||
break;
|
||||
|
||||
case DNSClient::INVALID_RESPONSE:
|
||||
// A response was received but was corrupt. Retry it like an IO
|
||||
// error.
|
||||
LOG_ERROR(dctl_logger, DHCP_DDNS_REVERSE_REMOVE_RESP_CORRUPT)
|
||||
.arg(getCurrentServer()->getIpAddress())
|
||||
.arg(getNcr()->getFqdn());
|
||||
|
||||
// If we are out of retries on this server, we go back and start
|
||||
// all over on a new server.
|
||||
retryTransition(SELECTING_REV_SERVER_ST);
|
||||
break;
|
||||
|
||||
default:
|
||||
// Any other value and we will fail this transaction, something
|
||||
// bigger is wrong.
|
||||
LOG_ERROR(dctl_logger,
|
||||
DHCP_DDNS_REVERSE_REMOVE_BAD_DNSCLIENT_STATUS)
|
||||
.arg(getDnsUpdateStatus())
|
||||
.arg(getNcr()->getFqdn())
|
||||
.arg(getCurrentServer()->getIpAddress());
|
||||
|
||||
transition(PROCESS_TRANS_FAILED_ST, UPDATE_FAILED_EVT);
|
||||
break;
|
||||
} // end switch on dns_status
|
||||
|
||||
break;
|
||||
} // end case IO_COMPLETE_EVT
|
||||
|
||||
default:
|
||||
// Event is invalid.
|
||||
isc_throw(NameRemoveTransactionError,
|
||||
"Wrong event for context: " << getContextStr());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
NameRemoveTransaction::processRemoveOkHandler() {
|
||||
switch(getNextEvent()) {
|
||||
case UPDATE_OK_EVT:
|
||||
LOG_DEBUG(dctl_logger, DBGLVL_TRACE_DETAIL, DHCP_DDNS_REMOVE_SUCCEEDED)
|
||||
.arg(getNcr()->toText());
|
||||
setNcrStatus(dhcp_ddns::ST_COMPLETED);
|
||||
endModel();
|
||||
break;
|
||||
default:
|
||||
// Event is invalid.
|
||||
isc_throw(NameRemoveTransactionError,
|
||||
"Wrong event for context: " << getContextStr());
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
NameRemoveTransaction::processRemoveFailedHandler() {
|
||||
switch(getNextEvent()) {
|
||||
case UPDATE_FAILED_EVT:
|
||||
case NO_MORE_SERVERS_EVT:
|
||||
case SERVER_IO_ERROR_EVT:
|
||||
LOG_ERROR(dctl_logger, DHCP_DDNS_REMOVE_FAILED).arg(getNcr()->toText())
|
||||
.arg(getEventLabel(getNextEvent()));
|
||||
setNcrStatus(dhcp_ddns::ST_FAILED);
|
||||
endModel();
|
||||
break;
|
||||
default:
|
||||
// Event is invalid.
|
||||
isc_throw(NameRemoveTransactionError,
|
||||
"Wrong event for context: " << getContextStr());
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
NameRemoveTransaction::buildRemoveFwdAddressRequest() {
|
||||
// Construct an empty request.
|
||||
D2UpdateMessagePtr request = prepNewRequest(getForwardDomain());
|
||||
|
||||
// Content on this request is based on RFC 4703, section 5.5, paragraph 4.
|
||||
// Construct dns::Name from NCR fqdn.
|
||||
dns::Name fqdn(dns::Name(getNcr()->getFqdn()));
|
||||
// First build the Prerequisite Section
|
||||
|
||||
// Create an DHCID matches prerequisite RR and add it to the
|
||||
// pre-requisite section
|
||||
// Based on RFC 2136, section 2.4.2.
|
||||
dns::RRsetPtr prereq(new dns::RRset(fqdn, dns::RRClass::IN(),
|
||||
dns::RRType::DHCID(), dns::RRTTL(0)));
|
||||
addDhcidRdata(prereq);
|
||||
request->addRRset(D2UpdateMessage::SECTION_PREREQUISITE, prereq);
|
||||
|
||||
// Next build the Update Section
|
||||
|
||||
// Create the FQDN/IP 'delete' RR and add it to the update section.
|
||||
// Add the RR to update section.
|
||||
// Based on 2136 section 2.5.4
|
||||
dns::RRsetPtr update(new dns::RRset(fqdn, dns::RRClass::NONE(),
|
||||
getAddressRRType(), dns::RRTTL(0)));
|
||||
addLeaseAddressRdata(update);
|
||||
request->addRRset(D2UpdateMessage::SECTION_UPDATE, update);
|
||||
|
||||
// Set the transaction's update request to the new request.
|
||||
setDnsUpdateRequest(request);
|
||||
}
|
||||
|
||||
void
|
||||
NameRemoveTransaction::buildRemoveFwdRRsRequest() {
|
||||
// Construct an empty request.
|
||||
D2UpdateMessagePtr request = prepNewRequest(getForwardDomain());
|
||||
|
||||
// Construct dns::Name from NCR fqdn.
|
||||
dns::Name fqdn(dns::Name(getNcr()->getFqdn()));
|
||||
|
||||
// Content on this request is based on RFC 4703, section 5.5, paragraph 5.
|
||||
// First build the Prerequisite Section.
|
||||
|
||||
// Now create an DHCID matches prerequisite RR.
|
||||
// Set the RR's RData to DHCID.
|
||||
// Add it to the pre-requisite section.
|
||||
// Based on RFC 2136, section 2.4.2.
|
||||
dns::RRsetPtr prereq(new dns::RRset(fqdn, dns::RRClass::IN(),
|
||||
dns::RRType::DHCID(), dns::RRTTL(0)));
|
||||
addDhcidRdata(prereq);
|
||||
request->addRRset(D2UpdateMessage::SECTION_PREREQUISITE, prereq);
|
||||
|
||||
// Create an assertion that there are no A RRs for the FQDN.
|
||||
// Add it to the pre-reqs.
|
||||
// Based on RFC 2136, section 2.4.3.
|
||||
prereq.reset(new dns::RRset(fqdn, dns::RRClass::NONE(),
|
||||
dns::RRType::A(), dns::RRTTL(0)));
|
||||
request->addRRset(D2UpdateMessage::SECTION_PREREQUISITE, prereq);
|
||||
|
||||
// Create an assertion that there are no A RRs for the FQDN.
|
||||
// Add it to the pre-reqs.
|
||||
// Based on RFC 2136, section 2.4.3.
|
||||
prereq.reset(new dns::RRset(fqdn, dns::RRClass::NONE(),
|
||||
dns::RRType::AAAA(), dns::RRTTL(0)));
|
||||
request->addRRset(D2UpdateMessage::SECTION_PREREQUISITE, prereq);
|
||||
|
||||
// Next build the Update Section.
|
||||
|
||||
// Create the 'delete' of all RRs for FQDN.
|
||||
// Set the message RData to lease address.
|
||||
// Add the RR to update section.
|
||||
// Based on RFC 2136, section 2.5.3.
|
||||
dns::RRsetPtr update(new dns::RRset(fqdn, dns::RRClass::ANY(),
|
||||
dns::RRType::ANY(), dns::RRTTL(0)));
|
||||
request->addRRset(D2UpdateMessage::SECTION_UPDATE, update);
|
||||
|
||||
// Set the transaction's update request to the new request.
|
||||
setDnsUpdateRequest(request);
|
||||
}
|
||||
|
||||
void
|
||||
NameRemoveTransaction::buildRemoveRevPtrsRequest() {
|
||||
// Construct an empty request.
|
||||
D2UpdateMessagePtr request = prepNewRequest(getReverseDomain());
|
||||
|
||||
// Create the reverse IP address "FQDN".
|
||||
std::string rev_addr = D2CfgMgr::reverseIpAddress(getNcr()->getIpAddress());
|
||||
dns::Name rev_ip(rev_addr);
|
||||
|
||||
// Content on this request is based on RFC 4703, section 5.5, paragraph 2.
|
||||
// First build the Prerequisite Section.
|
||||
// (Note that per RFC 4703, section 5.4, there is no need to validate
|
||||
// DHCID RR for PTR entries.)
|
||||
|
||||
// Create an assertion that the PTRDNAME in the PTR record matches the
|
||||
// client's FQDN for the address that was released.
|
||||
// Based on RFC 2136, section 3.2.3
|
||||
dns::RRsetPtr prereq(new dns::RRset(rev_ip, dns::RRClass::IN(),
|
||||
dns::RRType::PTR(), dns::RRTTL(0)));
|
||||
addPtrRdata(prereq);
|
||||
request->addRRset(D2UpdateMessage::SECTION_PREREQUISITE, prereq);
|
||||
|
||||
// Now, build the Update section.
|
||||
|
||||
// Create a delete of any RRs for the FQDN and add it to update section.
|
||||
// Based on RFC 2136, section 3.4.2.3
|
||||
dns::RRsetPtr update(new dns::RRset(rev_ip, dns::RRClass::ANY(),
|
||||
dns::RRType::ANY(), dns::RRTTL(0)));
|
||||
request->addRRset(D2UpdateMessage::SECTION_UPDATE, update);
|
||||
|
||||
// Set the transaction's update request to the new request.
|
||||
setDnsUpdateRequest(request);
|
||||
}
|
||||
|
||||
} // namespace isc::d2
|
||||
} // namespace isc
|
435
src/bin/d2/nc_remove.h
Normal file
435
src/bin/d2/nc_remove.h
Normal file
@@ -0,0 +1,435 @@
|
||||
// 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.
|
||||
|
||||
#ifndef NC_REMOVE_H
|
||||
#define NC_REMOVE_H
|
||||
|
||||
/// @file nc_remove.h This file defines the class NameRemoveTransaction.
|
||||
|
||||
#include <d2/nc_trans.h>
|
||||
|
||||
namespace isc {
|
||||
namespace d2 {
|
||||
|
||||
/// @brief Thrown if the NameRemoveTransaction encounters a general error.
|
||||
class NameRemoveTransactionError : public isc::Exception {
|
||||
public:
|
||||
NameRemoveTransactionError(const char* file, size_t line,
|
||||
const char* what) :
|
||||
isc::Exception(file, line, what) { };
|
||||
};
|
||||
|
||||
/// @brief Embodies the "life-cycle" required to carry out a DDNS Remove update.
|
||||
///
|
||||
/// NameRemoveTransaction implements a state machine for removing a forward
|
||||
/// and/or reverse DNS mappings. This state machine is based upon the processing
|
||||
/// logic described in RFC 4703, Section 5.5. That logic may be paraphrased as
|
||||
/// follows:
|
||||
///
|
||||
/// @code
|
||||
///
|
||||
/// If the request includes a forward change:
|
||||
/// Select a forward server
|
||||
/// Send the server a request to remove client's specific forward address RR
|
||||
/// If it succeeds or the server responds with name no longer in use
|
||||
/// Send a server a request to delete any other RRs for that FQDN, such
|
||||
/// as the DHCID RR.
|
||||
/// otherwise
|
||||
/// abandon the update
|
||||
///
|
||||
/// If the request includes a reverse change:
|
||||
/// Select a reverse server
|
||||
/// Send a server a request to delete reverse entry (PTR RR)
|
||||
///
|
||||
/// @endcode
|
||||
///
|
||||
/// This class derives from NameChangeTransaction from which it inherits
|
||||
/// states, events, and methods common to NameChangeRequest processing.
|
||||
class NameRemoveTransaction : public NameChangeTransaction {
|
||||
public:
|
||||
|
||||
//@{ Additional states needed for NameRemove state model.
|
||||
/// @brief State that attempts to remove specific forward address record.
|
||||
static const int REMOVING_FWD_ADDRS_ST = NCT_DERIVED_STATE_MIN + 1;
|
||||
|
||||
/// @brief State that attempts to remove any other forward RRs for the DHCID
|
||||
static const int REMOVING_FWD_RRS_ST = NCT_DERIVED_STATE_MIN + 2;
|
||||
|
||||
/// @brief State that attempts to remove reverse PTR records
|
||||
static const int REMOVING_REV_PTRS_ST = NCT_DERIVED_STATE_MIN + 3;
|
||||
//@}
|
||||
|
||||
//@{ Additional events needed for NameRemove state model.
|
||||
/// @brief Event sent when replace attempt to fails with address not in use.
|
||||
/// @todo Currently none have been identified.
|
||||
//@}
|
||||
|
||||
/// @brief Constructor
|
||||
///
|
||||
/// Instantiates an Remove transaction that is ready to be started.
|
||||
///
|
||||
/// @param io_service IO service to be used for IO processing
|
||||
/// @param ncr is the NameChangeRequest to fulfill
|
||||
/// @param forward_domain is the domain to use for forward DNS updates
|
||||
/// @param reverse_domain is the domain to use for reverse DNS updates
|
||||
///
|
||||
/// @throw NameRemoveTransaction error if given request is not a CHG_REMOVE,
|
||||
/// NameChangeTransaction error for base class construction errors.
|
||||
NameRemoveTransaction(IOServicePtr& io_service,
|
||||
dhcp_ddns::NameChangeRequestPtr& ncr,
|
||||
DdnsDomainPtr& forward_domain,
|
||||
DdnsDomainPtr& reverse_domain);
|
||||
|
||||
/// @brief Destructor
|
||||
virtual ~NameRemoveTransaction();
|
||||
|
||||
protected:
|
||||
/// @brief Adds events defined by NameRemoveTransaction to the event set.
|
||||
///
|
||||
/// Invokes NameChangeTransaction's implementation and then defines the
|
||||
/// events unique to NCR Remove transaction processing.
|
||||
///
|
||||
/// @throw StateModelError if an event definition is invalid or a duplicate.
|
||||
virtual void defineEvents();
|
||||
|
||||
/// @brief Validates the contents of the set of events.
|
||||
///
|
||||
/// Invokes NameChangeTransaction's implementation and then verifies the
|
||||
/// Remove transaction's events. This tests that the needed events are in
|
||||
/// the event dictionary.
|
||||
///
|
||||
/// @throw StateModelError if an event value is undefined.
|
||||
virtual void verifyEvents();
|
||||
|
||||
/// @brief Adds states defined by NameRemoveTransaction to the state set.
|
||||
///
|
||||
/// Invokes NameChangeTransaction's implementation and then defines the
|
||||
/// states unique to NCR Remove transaction processing.
|
||||
///
|
||||
/// @throw StateModelError if an state definition is invalid or a duplicate.
|
||||
virtual void defineStates();
|
||||
|
||||
/// @brief Validates the contents of the set of states.
|
||||
///
|
||||
/// Invokes NameChangeTransaction's implementation and then verifies the
|
||||
/// Remove transaction's states. This tests that the needed states are in
|
||||
/// the state dictionary.
|
||||
///
|
||||
/// @throw StateModelError if an event value is undefined.
|
||||
virtual void verifyStates();
|
||||
|
||||
/// @brief State handler for READY_ST.
|
||||
///
|
||||
/// Entered from:
|
||||
/// - INIT_ST with next event of START_EVT
|
||||
///
|
||||
/// The READY_ST is the state the model transitions into when the inherited
|
||||
/// method, startTransaction() is invoked. This handler, therefore, is the
|
||||
/// entry point into the state model execution. Its primary task is to
|
||||
/// determine whether to start with a forward DNS change or a reverse DNS
|
||||
/// change.
|
||||
///
|
||||
/// Transitions to:
|
||||
/// - SELECTING_FWD_SERVER_ST with next event of SERVER_SELECT_ST if request
|
||||
/// includes a forward change.
|
||||
///
|
||||
/// - SELECTING_REV_SERVER_ST with next event of SERVER_SELECT_ST if request
|
||||
/// includes only a reverse change.
|
||||
///
|
||||
/// @throw NameRemoveTransactionError if upon entry next event is not
|
||||
/// START_EVT.
|
||||
void readyHandler();
|
||||
|
||||
/// @brief State handler for SELECTING_FWD_SERVER_ST.
|
||||
///
|
||||
/// Entered from:
|
||||
/// - READY_ST with next event of SELECT_SERVER_EVT
|
||||
/// - REMOVING_FWD_ADDRS_ST with next event of SERVER_IO_ERROR_EVT
|
||||
///
|
||||
/// Selects the server to be used from the forward domain for the forward
|
||||
/// DNS update. If next event is SELECT_SERVER_EVT the handler initializes
|
||||
/// the forward domain's server selection mechanism and then attempts to
|
||||
/// select the next server. If next event is SERVER_IO_ERROR_EVT then the
|
||||
/// handler simply attempts to select the next server.
|
||||
///
|
||||
/// Transitions to:
|
||||
/// - REMOVING_FWD_ADDRS_ST with next event of SERVER_SELECTED upon
|
||||
/// successful server selection
|
||||
///
|
||||
/// - PROCESS_TRANS_FAILED with next event of NO_MORE_SERVERS_EVT upon
|
||||
/// failure to select a server
|
||||
///
|
||||
/// @throw NameRemoveTransactionError if upon entry next event is not
|
||||
/// SELECT_SERVER_EVT or SERVER_IO_ERROR_EVT.
|
||||
void selectingFwdServerHandler();
|
||||
|
||||
/// @brief State handler for SELECTING_REV_SERVER_ST.
|
||||
///
|
||||
/// Entered from:
|
||||
/// - READY_ST with next event of SELECT_SERVER_EVT
|
||||
/// - REMOVING_FWD_RRS_ST with next event of SELECT_SERVER_EVT
|
||||
/// - REMOVING_REV_PTRS_ST with next event of SERVER_IO_ERROR_EVT
|
||||
///
|
||||
/// Selects the server to be used from the reverse domain for the reverse
|
||||
/// DNS update. If next event is SELECT_SERVER_EVT the handler initializes
|
||||
/// the reverse domain's server selection mechanism and then attempts to
|
||||
/// select the next server. If next event is SERVER_IO_ERROR_EVT then the
|
||||
/// handler simply attempts to select the next server.
|
||||
///
|
||||
/// Transitions to:
|
||||
/// - REMOVING_REV_PTRS_ST with next event of SERVER_SELECTED upon
|
||||
/// successful server selection
|
||||
///
|
||||
/// - PROCESS_TRANS_FAILED with next event of NO_MORE_SERVERS_EVT upon
|
||||
/// failure to select a server
|
||||
///
|
||||
/// @throw NameRemoveTransactionError if upon entry next event is not
|
||||
/// SELECT_SERVER_EVT or SERVER_IO_ERROR_EVT.
|
||||
void selectingRevServerHandler();
|
||||
|
||||
/// @brief State handler for REMOVING_FWD_ADDRS_ST.
|
||||
///
|
||||
/// Entered from:
|
||||
/// - SELECTING_FWD_SERVER with next event of SERVER_SELECTED_EVT
|
||||
///
|
||||
/// Attempts to remove the forward DNS entry for a given FQDN, provided
|
||||
/// a DHCID RR exists which matches the requesting DHCID. If this is
|
||||
/// first invocation of the handler after transitioning into this state,
|
||||
/// any previous update request context is deleted. If next event
|
||||
/// is SERVER_SELECTED_EVT, the handler builds the forward remove request,
|
||||
/// schedules an asynchronous send via sendUpdate(), and returns. Note
|
||||
/// that sendUpdate will post NOP_EVT as next event.
|
||||
///
|
||||
/// Posting the NOP_EVT will cause runModel() to suspend execution of
|
||||
/// the state model thus affecting a "wait" for the update IO to complete.
|
||||
/// Update completion occurs via the DNSClient callback operator() method
|
||||
/// inherited from NameChangeTransaction. When invoked this callback will
|
||||
/// post a next event of IO_COMPLETED_EVT and then invoke runModel which
|
||||
/// resumes execution of the state model.
|
||||
///
|
||||
/// When the handler is invoked with a next event of IO_COMPELTED_EVT,
|
||||
/// the DNS update status is checked and acted upon accordingly:
|
||||
///
|
||||
/// Transitions to:
|
||||
/// - REMOVING_FWD_RRS_ST with next event of UPDATE_OK_EVT upon successful
|
||||
/// removal or RCODE of indication FQDN is no longer in use (NXDOMAIN).
|
||||
///
|
||||
/// - PROCESS_TRANS_FAILED_ST with next event of UPDATE_FAILED_EVT if the
|
||||
/// DNS server rejected the update for any reason or the IO completed
|
||||
/// with an unrecognized status.
|
||||
///
|
||||
/// - RE-ENTER this state with next event of SERVER_SELECTED_EVT if
|
||||
/// there was an IO error communicating with the server and the number of
|
||||
/// per server retries has not been exhausted.
|
||||
///
|
||||
/// - SELECTING_FWD_SERVER_ST with next event of SERVER_IO_ERROR_EVT if
|
||||
/// there was an IO error communicating with the server and the number of
|
||||
/// per server retries has been exhausted.
|
||||
///
|
||||
/// @throw NameRemoveTransactionError if upon entry next event is not
|
||||
/// SERVER_SELECTED_EVT or IO_COMPLETE_EVT
|
||||
void removingFwdAddrsHandler();
|
||||
|
||||
/// @brief State handler for REMOVING_FWD_RRS_ST.
|
||||
///
|
||||
/// Entered from:
|
||||
/// - REMOVING_FWD_ADDRS_ST with next event of UPDATE_OK_EVT
|
||||
///
|
||||
/// Attempts to delete any remaining RRs associated with the given FQDN
|
||||
/// such as the DHCID RR. If this is first invocation of the handler after
|
||||
/// transitioning into this state, any previous update request context is
|
||||
/// deleted and the handler builds the forward remove request. It then
|
||||
/// schedules an asynchronous send via sendUpdate(),
|
||||
/// and returns. Note that sendUpdate will post NOP_EVT as the next event.
|
||||
///
|
||||
/// Posting the NOP_EVT will cause runModel() to suspend execution of
|
||||
/// the state model thus affecting a "wait" for the update IO to complete.
|
||||
/// Update completion occurs via the DNSClient callback operator() method
|
||||
/// inherited from NameChangeTransaction. When invoked this callback will
|
||||
/// post a next event of IO_COMPLETED_EVT and then invoke runModel which
|
||||
/// resumes execution of the state model.
|
||||
///
|
||||
/// When the handler is invoked with a next event of IO_COMPELTED_EVT,
|
||||
/// the DNS update status is checked and acted upon accordingly:
|
||||
///
|
||||
/// Transitions to:
|
||||
/// - SELECTING_REV_SERVER_ST with a next event of SELECT_SERVER_EVT upon
|
||||
/// successful completion and the request includes a reverse DNS update.
|
||||
///
|
||||
/// - PROCESS_TRANS_OK_ST with next event of UPDATE_OK_EVT upon successful
|
||||
/// completion and the request does not include a reverse DNS update.
|
||||
///
|
||||
/// - PROCESS_TRANS_FAILED_ST with a next event of UPDATE_FAILED_EVT if the
|
||||
/// DNS server rejected the update for any other reason or the IO completed
|
||||
/// with an unrecognized status.
|
||||
///
|
||||
/// - RE-ENTER this state with a next event of SERVER_SELECTED_EVT if
|
||||
/// there was an IO error communicating with the server and the number of
|
||||
/// per server retries has not been exhausted.
|
||||
///
|
||||
/// - PROCESS_TRANS_FAILED_ST with a next event of SERVER_IO_ERROR_EVT if
|
||||
/// there we have reached maximum number of retries without success on the
|
||||
/// current server.
|
||||
///
|
||||
/// @note If we exhaust the IO retries for the current server due to IO
|
||||
/// failures, we will abort the remaining updates. The rational is that
|
||||
/// we are only in this state, if the remove of the forward address RR
|
||||
/// succeeded (removingFwdAddrsHandler) on the current server so we should
|
||||
/// not attempt another removal on a different server. This is perhaps a
|
||||
/// point for discussion. @todo Should we go ahead with the reverse remove?
|
||||
///
|
||||
/// @throw NameRemoveTransactionError if upon entry next event is not:
|
||||
/// UPDATE_OK_EVT or IO_COMPLETE_EVT
|
||||
void removingFwdRRsHandler();
|
||||
|
||||
/// @brief State handler for REMOVING_REV_PTRS_ST.
|
||||
///
|
||||
/// Entered from:
|
||||
/// - SELECTING_REV_SERVER_ST with a next event of SERVER_SELECTED_EVT
|
||||
///
|
||||
/// Attempts to delete a reverse DNS entry for a given FQDN. If this is
|
||||
/// first invocation of the handler after transitioning into this state,
|
||||
/// any previous update request context is deleted. If next event is
|
||||
/// SERVER_SELECTED_EVT, the handler builds the reverse remove request,
|
||||
/// schedules an asynchronous send via sendUpdate(), and then returns.
|
||||
/// Note that sendUpdate will post NOP_EVT as next event.
|
||||
///
|
||||
/// Posting the NOP_EVT will cause runModel() to suspend execution of
|
||||
/// the state model thus affecting a "wait" for the update IO to complete.
|
||||
/// Update completion occurs via the DNSClient callback operator() method
|
||||
/// inherited from NameChangeTransaction. When invoked this callback will
|
||||
/// post a next event of IO_COMPLETED_EVT and then invoke runModel which
|
||||
/// resumes execution of the state model.
|
||||
///
|
||||
/// When the handler is invoked with a next event of IO_COMPELTED_EVT,
|
||||
/// the DNS update status is checked and acted upon accordingly:
|
||||
///
|
||||
/// Transitions to:
|
||||
/// - PROCESS_TRANS_OK_ST with a next event of UPDATE_OK_EVT upon
|
||||
/// successful completion.
|
||||
///
|
||||
/// - PROCESS_TRANS_FAILED_ST with a next event of UPDATE_FAILED_EVT If the
|
||||
/// DNS server rejected the update for any reason or the IO completed
|
||||
/// with an unrecognized status.
|
||||
///
|
||||
/// - RE-ENTER this state with a next event of SERVER_SELECTED_EVT if
|
||||
/// there was an IO error communicating with the server and the number of
|
||||
/// per server retries has not been exhausted.
|
||||
///
|
||||
/// - SELECTING_REV_SERVER_ST with next event of SERVER_IO_ERROR_EVT if
|
||||
/// there was an IO error communicating with the server and the number of
|
||||
/// per server retries has been exhausted.
|
||||
///
|
||||
/// @throw NameRemoveTransactionError if upon entry next event is not:
|
||||
/// SERVER_SELECTED_EVT or IO_COMPLETED_EVT
|
||||
void removingRevPtrsHandler();
|
||||
|
||||
/// @brief State handler for PROCESS_TRANS_OK_ST.
|
||||
///
|
||||
/// Entered from:
|
||||
/// - REMOVING_FWD_RRS_ST with a next event of UPDATE_OK_EVT
|
||||
/// - REMOVING_REV_PTRS_ST with a next event of UPDATE_OK_EVT
|
||||
///
|
||||
/// Sets the transaction action status to indicate success and ends
|
||||
/// model execution.
|
||||
///
|
||||
/// Transitions to:
|
||||
/// - END_ST with a next event of END_EVT.
|
||||
///
|
||||
/// @throw NameRemoveTransactionError if upon entry next event is not:
|
||||
/// UPDATE_OK_EVT
|
||||
void processRemoveOkHandler();
|
||||
|
||||
/// @brief State handler for PROCESS_TRANS_FAILED_ST.
|
||||
///
|
||||
/// Entered from:
|
||||
/// - SELECTING_FWD_SERVER_ST with a next event of NO_MORE_SERVERS
|
||||
/// - REMOVING_FWD_ADDRS_ST with a next event of UPDATE_FAILED_EVT
|
||||
/// - REMOVING_FWD_RRS_ST with a next event of UPDATE_FAILED_EVT
|
||||
/// - REMOVING_FWD_RRS_ST with a next event of SERVER_IO_ERROR_EVT
|
||||
/// - SELECTING_REV_SERVER_ST with a next event of NO_MORE_SERVERS
|
||||
/// - REMOVING_REV_PTRS_ST with a next event of UPDATE_FAILED_EVT
|
||||
///
|
||||
/// Sets the transaction status to indicate failure and ends
|
||||
/// model execution.
|
||||
///
|
||||
/// Transitions to:
|
||||
/// - END_ST with a next event of FAIL_EVT.
|
||||
///
|
||||
/// @throw NameRemoveTransactionError if upon entry next event is not:
|
||||
/// UPDATE_FAILED_EVT
|
||||
void processRemoveFailedHandler();
|
||||
|
||||
/// @brief Builds a DNS request to remove a forward DNS address for a FQDN.
|
||||
///
|
||||
/// Constructs a DNS update request, based upon the NCR, for removing a
|
||||
/// forward DNS address mapping. Once constructed, the request is stored as
|
||||
/// the transaction's DNS update request.
|
||||
///
|
||||
/// The request content is adherent to RFC 4703 section 5.5, paragraph 4.
|
||||
///
|
||||
/// Prerequisite RRsets:
|
||||
/// 1. An assertion that a matching DHCID RR exists
|
||||
///
|
||||
/// Updates RRsets:
|
||||
/// 1. A delete of the FQDN/IP RR (type A for IPv4, AAAA for IPv6)
|
||||
///
|
||||
/// @throw This method does not throw but underlying methods may.
|
||||
void buildRemoveFwdAddressRequest();
|
||||
|
||||
/// @brief Builds a DNS request to remove all forward DNS RRs for a FQDN.
|
||||
///
|
||||
/// Constructs a DNS update request, based upon the NCR, for removing any
|
||||
/// remaining forward DNS RRs, once all A or AAAA entries for the FQDN
|
||||
/// have been removed. Once constructed, the request is stored as the
|
||||
/// transaction's DNS update request.
|
||||
///
|
||||
/// The request content is adherent to RFC 4703 section 5.5, paragraph 5.
|
||||
///
|
||||
/// Prerequisite RRsets:
|
||||
/// 1. An assertion that a matching DHCID RR exists
|
||||
/// 2. An assertion that no A RRs for the FQDN exist
|
||||
/// 3. An assertion that no AAAA RRs for the FQDN exist
|
||||
///
|
||||
/// Updates RRsets:
|
||||
/// 1. A delete of all RRs for the FQDN
|
||||
///
|
||||
/// @throw This method does not throw but underlying methods may.
|
||||
void buildRemoveFwdRRsRequest();
|
||||
|
||||
/// @brief Builds a DNS request to remove a reverse DNS entry for a FQDN
|
||||
///
|
||||
/// Constructs a DNS update request, based upon the NCR, for removing a
|
||||
/// reverse DNS mapping. Once constructed, the request is stored as
|
||||
/// the transaction's DNS update request.
|
||||
///
|
||||
/// The request content is adherent to RFC 4703 section 5.5, paragraph 2:
|
||||
///
|
||||
/// Prerequisite RRsets:
|
||||
/// 1. An assertion that a PTR record matching the client's FQDN exists.
|
||||
///
|
||||
/// Updates RRsets:
|
||||
/// 1. A delete of all RRs for the FQDN
|
||||
///
|
||||
/// @throw This method does not throw but underlying methods may.
|
||||
void buildRemoveRevPtrsRequest();
|
||||
};
|
||||
|
||||
/// @brief Defines a pointer to a NameRemoveTransaction.
|
||||
typedef boost::shared_ptr<NameRemoveTransaction> NameRemoveTransactionPtr;
|
||||
|
||||
|
||||
} // namespace isc::d2
|
||||
} // namespace isc
|
||||
#endif
|
@@ -14,6 +14,7 @@
|
||||
|
||||
#include <d2/d2_log.h>
|
||||
#include <d2/nc_trans.h>
|
||||
#include <dns/rdata.h>
|
||||
|
||||
namespace isc {
|
||||
namespace d2 {
|
||||
@@ -181,14 +182,14 @@ NameChangeTransaction::onModelFailure(const std::string& explanation) {
|
||||
}
|
||||
|
||||
void
|
||||
NameChangeTransaction::retryTransition(const int server_sel_state) {
|
||||
NameChangeTransaction::retryTransition(const int fail_to_state) {
|
||||
if (update_attempts_ < MAX_UPDATE_TRIES_PER_SERVER) {
|
||||
// Re-enter the current state with same server selected.
|
||||
transition(getCurrState(), SERVER_SELECTED_EVT);
|
||||
} else {
|
||||
// Transition to given server selection state if we are out
|
||||
// Transition to given fail_to_state state if we are out
|
||||
// of retries.
|
||||
transition(server_sel_state, SERVER_IO_ERROR_EVT);
|
||||
transition(fail_to_state, SERVER_IO_ERROR_EVT);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -262,13 +263,13 @@ NameChangeTransaction::addLeaseAddressRdata(dns::RRsetPtr& rrset) {
|
||||
|
||||
try {
|
||||
// Manufacture an RData from the lease address then add it to the RR.
|
||||
dns::rdata::ConstRdataPtr rdata;
|
||||
if (ncr_->isV4()) {
|
||||
dns::rdata::in::A a_rdata(ncr_->getIpAddress());
|
||||
rrset->addRdata(a_rdata);
|
||||
rdata.reset(new dns::rdata::in::A(ncr_->getIpAddress()));
|
||||
} else {
|
||||
dns::rdata::in::AAAA rdata(ncr_->getIpAddress());
|
||||
rrset->addRdata(rdata);
|
||||
rdata.reset(new dns::rdata::in::AAAA(ncr_->getIpAddress()));
|
||||
}
|
||||
rrset->addRdata(rdata);
|
||||
} catch (const std::exception& ex) {
|
||||
isc_throw(NameChangeTransactionError, "Cannot add address rdata: "
|
||||
<< ex.what());
|
||||
@@ -285,12 +286,14 @@ NameChangeTransaction::addDhcidRdata(dns::RRsetPtr& rrset) {
|
||||
try {
|
||||
const std::vector<uint8_t>& ncr_dhcid = ncr_->getDhcid().getBytes();
|
||||
util::InputBuffer buffer(ncr_dhcid.data(), ncr_dhcid.size());
|
||||
dns::rdata::in::DHCID rdata(buffer, ncr_dhcid.size());
|
||||
dns::rdata::ConstRdataPtr rdata (new dns::rdata::in::
|
||||
DHCID(buffer, ncr_dhcid.size()));
|
||||
rrset->addRdata(rdata);
|
||||
} catch (const std::exception& ex) {
|
||||
isc_throw(NameChangeTransactionError, "Cannot add DCHID rdata: "
|
||||
<< ex.what());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
@@ -301,7 +304,8 @@ NameChangeTransaction::addPtrRdata(dns::RRsetPtr& rrset) {
|
||||
}
|
||||
|
||||
try {
|
||||
dns::rdata::generic::PTR rdata(getNcr()->getFqdn());
|
||||
dns::rdata::ConstRdataPtr rdata(new dns::rdata::generic::
|
||||
PTR(getNcr()->getFqdn()));
|
||||
rrset->addRdata(rdata);
|
||||
} catch (const std::exception& ex) {
|
||||
isc_throw(NameChangeTransactionError, "Cannot add PTR rdata: "
|
||||
@@ -412,7 +416,7 @@ NameChangeTransaction::getUpdateAttempts() const {
|
||||
|
||||
const dns::RRType&
|
||||
NameChangeTransaction::getAddressRRType() const {
|
||||
return (ncr_->isV4() ? dns::RRType::A(): dns::RRType::AAAA());
|
||||
return (ncr_->isV4() ? dns::RRType::A() : dns::RRType::AAAA());
|
||||
}
|
||||
|
||||
} // namespace isc::d2
|
||||
|
@@ -277,10 +277,10 @@ protected:
|
||||
/// If the maximum number of attempts has been reached, it will transition
|
||||
/// to the given state with a next event of SERVER_IO_ERROR_EVT.
|
||||
///
|
||||
/// @param server_sel_state State to transition to if maximum attempts
|
||||
/// @param fail_to_state State to transition to if maximum attempts
|
||||
/// have been tried.
|
||||
///
|
||||
void retryTransition(const int server_sel_state);
|
||||
void retryTransition(const int fail_to_state);
|
||||
|
||||
/// @brief Sets the update request packet to the given packet.
|
||||
///
|
||||
@@ -435,13 +435,13 @@ public:
|
||||
|
||||
/// @brief Fetches the forward DdnsDomain.
|
||||
///
|
||||
/// @return A pointer reference to the forward DdnsDomain. If
|
||||
/// @return A pointer reference to the forward DdnsDomain. If
|
||||
/// the request does not include a forward change, the pointer will empty.
|
||||
DdnsDomainPtr& getForwardDomain();
|
||||
|
||||
/// @brief Fetches the reverse DdnsDomain.
|
||||
///
|
||||
/// @return A pointer reference to the reverse DdnsDomain. If
|
||||
/// @return A pointer reference to the reverse DdnsDomain. If
|
||||
/// the request does not include a reverse change, the pointer will empty.
|
||||
DdnsDomainPtr& getReverseDomain();
|
||||
|
||||
|
@@ -67,6 +67,7 @@ d2_unittests_SOURCES += ../d2_zone.cc ../d2_zone.h
|
||||
d2_unittests_SOURCES += ../dns_client.cc ../dns_client.h
|
||||
d2_unittests_SOURCES += ../labeled_value.cc ../labeled_value.h
|
||||
d2_unittests_SOURCES += ../nc_add.cc ../nc_add.h
|
||||
d2_unittests_SOURCES += ../nc_remove.cc ../nc_remove.h
|
||||
d2_unittests_SOURCES += ../nc_trans.cc ../nc_trans.h
|
||||
d2_unittests_SOURCES += ../state_model.cc ../state_model.h
|
||||
d2_unittests_SOURCES += d_test_stubs.cc d_test_stubs.h
|
||||
@@ -83,6 +84,7 @@ d2_unittests_SOURCES += d2_zone_unittests.cc
|
||||
d2_unittests_SOURCES += dns_client_unittests.cc
|
||||
d2_unittests_SOURCES += labeled_value_unittests.cc
|
||||
d2_unittests_SOURCES += nc_add_unittests.cc
|
||||
d2_unittests_SOURCES += nc_remove_unittests.cc
|
||||
d2_unittests_SOURCES += nc_test_utils.cc nc_test_utils.h
|
||||
d2_unittests_SOURCES += nc_trans_unittests.cc
|
||||
d2_unittests_SOURCES += state_model_unittests.cc
|
||||
|
@@ -407,14 +407,14 @@ TEST_F(NameAddTransactionTest, buildForwardAdd) {
|
||||
NameAddStubPtr name_add;
|
||||
ASSERT_NO_THROW(name_add = makeTransaction4());
|
||||
ASSERT_NO_THROW(name_add->buildAddFwdAddressRequest());
|
||||
checkForwardAddRequest(*name_add);
|
||||
checkAddFwdAddressRequest(*name_add);
|
||||
|
||||
// Create a IPv6 forward add transaction.
|
||||
// Verify the request builds without error.
|
||||
// and then verify the request contents.
|
||||
ASSERT_NO_THROW(name_add = makeTransaction6());
|
||||
ASSERT_NO_THROW(name_add->buildAddFwdAddressRequest());
|
||||
checkForwardAddRequest(*name_add);
|
||||
checkAddFwdAddressRequest(*name_add);
|
||||
}
|
||||
|
||||
/// @brief Tests construction of a DNS update request for replacing a forward
|
||||
@@ -426,14 +426,14 @@ TEST_F(NameAddTransactionTest, buildReplaceFwdAddressRequest) {
|
||||
NameAddStubPtr name_add;
|
||||
ASSERT_NO_THROW(name_add = makeTransaction4());
|
||||
ASSERT_NO_THROW(name_add->buildReplaceFwdAddressRequest());
|
||||
checkForwardReplaceRequest(*name_add);
|
||||
checkReplaceFwdAddressRequest(*name_add);
|
||||
|
||||
// Create a IPv6 forward replace transaction.
|
||||
// Verify the request builds without error.
|
||||
// and then verify the request contents.
|
||||
ASSERT_NO_THROW(name_add = makeTransaction6());
|
||||
ASSERT_NO_THROW(name_add->buildReplaceFwdAddressRequest());
|
||||
checkForwardReplaceRequest(*name_add);
|
||||
checkReplaceFwdAddressRequest(*name_add);
|
||||
}
|
||||
|
||||
/// @brief Tests the construction of a DNS update request for replacing a
|
||||
@@ -445,14 +445,14 @@ TEST_F(NameAddTransactionTest, buildReplaceRevPtrsRequest) {
|
||||
NameAddStubPtr name_add;
|
||||
ASSERT_NO_THROW(name_add = makeTransaction4());
|
||||
ASSERT_NO_THROW(name_add->buildReplaceRevPtrsRequest());
|
||||
checkReverseReplaceRequest(*name_add);
|
||||
checkReplaceRevPtrsRequest(*name_add);
|
||||
|
||||
// Create a IPv6 reverse replace transaction.
|
||||
// Verify the request builds without error.
|
||||
// and then verify the request contents.
|
||||
ASSERT_NO_THROW(name_add = makeTransaction6());
|
||||
ASSERT_NO_THROW(name_add->buildReplaceRevPtrsRequest());
|
||||
checkReverseReplaceRequest(*name_add);
|
||||
checkReplaceRevPtrsRequest(*name_add);
|
||||
}
|
||||
|
||||
// Tests the readyHandler functionality.
|
||||
@@ -632,7 +632,7 @@ TEST_F(NameAddTransactionTest, addingFwdAddrsHandler_FwdOnlyAddOK) {
|
||||
EXPECT_NO_THROW(name_add->addingFwdAddrsHandler());
|
||||
|
||||
// Verify that an update message was constructed properly.
|
||||
checkForwardAddRequest(*name_add);
|
||||
checkAddFwdAddressRequest(*name_add);
|
||||
|
||||
// Verify that we are still in this state and next event is NOP_EVT.
|
||||
// This indicates we "sent" the message and are waiting for IO completion.
|
||||
@@ -943,7 +943,7 @@ TEST_F(NameAddTransactionTest, replacingFwdAddrsHandler_FwdOnlyAddOK) {
|
||||
EXPECT_NO_THROW(name_add->replacingFwdAddrsHandler());
|
||||
|
||||
// Verify that an update message was constructed properly.
|
||||
checkForwardReplaceRequest(*name_add);
|
||||
checkReplaceFwdAddressRequest(*name_add);
|
||||
|
||||
// Verify that we are still in this state and next event is NOP_EVT.
|
||||
// This indicates we "sent" the message and are waiting for IO completion.
|
||||
@@ -1366,7 +1366,7 @@ TEST_F(NameAddTransactionTest, replacingRevPtrsHandler_FwdOnlyAddOK) {
|
||||
EXPECT_NO_THROW(name_add->replacingRevPtrsHandler());
|
||||
|
||||
// Verify that an update message was constructed properly.
|
||||
checkReverseReplaceRequest(*name_add);
|
||||
checkReplaceRevPtrsRequest(*name_add);
|
||||
|
||||
// Verify that we are still in this state and next event is NOP_EVT.
|
||||
// This indicates we "sent" the message and are waiting for IO completion.
|
||||
@@ -1419,8 +1419,7 @@ TEST_F(NameAddTransactionTest, replacingRevPtrsHandler_OtherRcode) {
|
||||
name_add->fakeResponse(DNSClient::SUCCESS, dns::Rcode::REFUSED());
|
||||
|
||||
// Run replacingRevPtrsHandler again to process the response.
|
||||
//EXPECT_NO_THROW(name_add->replacingRevPtrsHandler());
|
||||
(name_add->replacingRevPtrsHandler());
|
||||
EXPECT_NO_THROW(name_add->replacingRevPtrsHandler());
|
||||
|
||||
// Completion flags should still be false.
|
||||
EXPECT_FALSE(name_add->getForwardChangeCompleted());
|
||||
@@ -1634,6 +1633,29 @@ TEST_F(NameAddTransactionTest, processAddFailedHandler) {
|
||||
EXPECT_THROW(name_add->processAddFailedHandler(), NameAddTransactionError);
|
||||
}
|
||||
|
||||
// Tests the processAddFailedHandler functionality.
|
||||
// It verifies behavior for posted event of NO_MORE_SERVERS_EVT.
|
||||
TEST_F(NameAddTransactionTest, processAddFailedHandler_NoMoreServers) {
|
||||
NameAddStubPtr name_remove;
|
||||
// Create and prep a transaction, poised to run the handler.
|
||||
ASSERT_NO_THROW(name_remove =
|
||||
prepHandlerTest(NameChangeTransaction::
|
||||
PROCESS_TRANS_FAILED_ST,
|
||||
NameChangeTransaction::
|
||||
NO_MORE_SERVERS_EVT));
|
||||
|
||||
// Run processAddFailedHandler.
|
||||
EXPECT_NO_THROW(name_remove->processAddFailedHandler());
|
||||
|
||||
// Verify that a server was selected.
|
||||
EXPECT_EQ(dhcp_ddns::ST_FAILED, name_remove->getNcrStatus());
|
||||
|
||||
// Verify that the model has ended. (Remember, the transaction failed NOT
|
||||
// the model. The model should have ended normally.)
|
||||
EXPECT_EQ(StateModel::END_ST, name_remove->getCurrState());
|
||||
EXPECT_EQ(StateModel::END_EVT, name_remove->getNextEvent());
|
||||
}
|
||||
|
||||
// Tests addingFwdAddrsHandler with the following scenario:
|
||||
//
|
||||
// The request includes only a forward change.
|
||||
|
1872
src/bin/d2/tests/nc_remove_unittests.cc
Normal file
1872
src/bin/d2/tests/nc_remove_unittests.cc
Normal file
File diff suppressed because it is too large
Load Diff
@@ -29,6 +29,11 @@ namespace d2 {
|
||||
const char* TEST_DNS_SERVER_IP = "127.0.0.1";
|
||||
size_t TEST_DNS_SERVER_PORT = 5301;
|
||||
|
||||
const bool HAS_RDATA = true;
|
||||
const bool NO_RDATA = false;
|
||||
|
||||
//*************************** FauxServer class ***********************
|
||||
|
||||
FauxServer::FauxServer(asiolink::IOService& io_service,
|
||||
asiolink::IOAddress& address, size_t port)
|
||||
:io_service_(io_service), address_(address), port_(port),
|
||||
@@ -136,6 +141,135 @@ FauxServer::requestHandler(const asio::error_code& error,
|
||||
}
|
||||
}
|
||||
|
||||
//********************** TransactionTest class ***********************
|
||||
|
||||
const unsigned int TransactionTest::FORWARD_CHG = 0x01;
|
||||
const unsigned int TransactionTest::REVERSE_CHG = 0x02;
|
||||
const unsigned int TransactionTest::FWD_AND_REV_CHG = REVERSE_CHG | FORWARD_CHG;
|
||||
|
||||
TransactionTest::TransactionTest()
|
||||
: io_service_(new isc::asiolink::IOService()), ncr_(),
|
||||
timer_(*io_service_), run_time_(0) {
|
||||
}
|
||||
|
||||
TransactionTest::~TransactionTest() {
|
||||
}
|
||||
|
||||
void
|
||||
TransactionTest::runTimedIO(int run_time) {
|
||||
run_time_ = run_time;
|
||||
timer_.setup(boost::bind(&TransactionTest::timesUp, this), run_time_);
|
||||
io_service_->run();
|
||||
}
|
||||
|
||||
void
|
||||
TransactionTest::timesUp() {
|
||||
io_service_->stop();
|
||||
FAIL() << "Test Time: " << run_time_ << " expired";
|
||||
}
|
||||
|
||||
void
|
||||
TransactionTest::setupForIPv4Transaction(dhcp_ddns::NameChangeType chg_type,
|
||||
int change_mask) {
|
||||
const char* msg_str =
|
||||
"{"
|
||||
" \"change_type\" : 0 , "
|
||||
" \"forward_change\" : true , "
|
||||
" \"reverse_change\" : true , "
|
||||
" \"fqdn\" : \"my.forward.example.com.\" , "
|
||||
" \"ip_address\" : \"192.168.2.1\" , "
|
||||
" \"dhcid\" : \"0102030405060708\" , "
|
||||
" \"lease_expires_on\" : \"20130121132405\" , "
|
||||
" \"lease_length\" : 1300 "
|
||||
"}";
|
||||
|
||||
// Create NameChangeRequest from JSON string.
|
||||
ncr_ = dhcp_ddns::NameChangeRequest::fromJSON(msg_str);
|
||||
|
||||
// Set the change type.
|
||||
ncr_->setChangeType(chg_type);
|
||||
|
||||
// If the change mask does not include a forward change clear the
|
||||
// forward domain; otherwise create the domain and its servers.
|
||||
if (!(change_mask & FORWARD_CHG)) {
|
||||
ncr_->setForwardChange(false);
|
||||
forward_domain_.reset();
|
||||
} else {
|
||||
// Create the forward domain and then its servers.
|
||||
forward_domain_ = makeDomain("example.com.");
|
||||
addDomainServer(forward_domain_, "forward.example.com",
|
||||
"127.0.0.1", 5301);
|
||||
addDomainServer(forward_domain_, "forward2.example.com",
|
||||
"127.0.0.1", 5302);
|
||||
}
|
||||
|
||||
// If the change mask does not include a reverse change clear the
|
||||
// reverse domain; otherwise create the domain and its servers.
|
||||
if (!(change_mask & REVERSE_CHG)) {
|
||||
ncr_->setReverseChange(false);
|
||||
reverse_domain_.reset();
|
||||
} else {
|
||||
// Create the reverse domain and its server.
|
||||
reverse_domain_ = makeDomain("2.168.192.in.addr.arpa.");
|
||||
addDomainServer(reverse_domain_, "reverse.example.com",
|
||||
"127.0.0.1", 5301);
|
||||
addDomainServer(reverse_domain_, "reverse2.example.com",
|
||||
"127.0.0.1", 5302);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
TransactionTest::setupForIPv6Transaction(dhcp_ddns::NameChangeType chg_type,
|
||||
int change_mask) {
|
||||
const char* msg_str =
|
||||
"{"
|
||||
" \"change_type\" : 0 , "
|
||||
" \"forward_change\" : true , "
|
||||
" \"reverse_change\" : true , "
|
||||
" \"fqdn\" : \"my6.forward.example.com.\" , "
|
||||
" \"ip_address\" : \"2001:1::100\" , "
|
||||
" \"dhcid\" : \"0102030405060708\" , "
|
||||
" \"lease_expires_on\" : \"20130121132405\" , "
|
||||
" \"lease_length\" : 1300 "
|
||||
"}";
|
||||
|
||||
// Create NameChangeRequest from JSON string.
|
||||
ncr_ = makeNcrFromString(msg_str);
|
||||
|
||||
// Set the change type.
|
||||
ncr_->setChangeType(chg_type);
|
||||
|
||||
// If the change mask does not include a forward change clear the
|
||||
// forward domain; otherwise create the domain and its servers.
|
||||
if (!(change_mask & FORWARD_CHG)) {
|
||||
ncr_->setForwardChange(false);
|
||||
forward_domain_.reset();
|
||||
} else {
|
||||
// Create the forward domain and then its servers.
|
||||
forward_domain_ = makeDomain("example.com.");
|
||||
addDomainServer(forward_domain_, "fwd6-server.example.com",
|
||||
"::1", 5301);
|
||||
addDomainServer(forward_domain_, "fwd6-server2.example.com",
|
||||
"::1", 5302);
|
||||
}
|
||||
|
||||
// If the change mask does not include a reverse change clear the
|
||||
// reverse domain; otherwise create the domain and its servers.
|
||||
if (!(change_mask & REVERSE_CHG)) {
|
||||
ncr_->setReverseChange(false);
|
||||
reverse_domain_.reset();
|
||||
} else {
|
||||
// Create the reverse domain and its server.
|
||||
reverse_domain_ = makeDomain("1.2001.ip6.arpa.");
|
||||
addDomainServer(reverse_domain_, "rev6-server.example.com",
|
||||
"::1", 5301);
|
||||
addDomainServer(reverse_domain_, "rev6-server2.example.com",
|
||||
"::1", 5302);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//********************** Functions ****************************
|
||||
|
||||
void
|
||||
checkRRCount(const D2UpdateMessagePtr& request,
|
||||
@@ -158,13 +292,15 @@ checkZone(const D2UpdateMessagePtr& request, const std::string& exp_zone_name) {
|
||||
void
|
||||
checkRR(dns::RRsetPtr rrset, const std::string& exp_name,
|
||||
const dns::RRClass& exp_class, const dns::RRType& exp_type,
|
||||
unsigned int exp_ttl, dhcp_ddns::NameChangeRequestPtr ncr) {
|
||||
unsigned int exp_ttl, dhcp_ddns::NameChangeRequestPtr ncr,
|
||||
bool has_rdata) {
|
||||
// Verify the FQDN/DHCID RR fields.
|
||||
EXPECT_EQ(exp_name, rrset->getName().toText());
|
||||
EXPECT_EQ(exp_class.getCode(), rrset->getClass().getCode());
|
||||
EXPECT_EQ(exp_type.getCode(), rrset->getType().getCode());
|
||||
EXPECT_EQ(exp_ttl, rrset->getTTL().getValue());
|
||||
if (exp_type == dns::RRType::ANY() || exp_class == dns::RRClass::ANY()) {
|
||||
if ((!has_rdata) ||
|
||||
(exp_type == dns::RRType::ANY() || exp_class == dns::RRClass::ANY())) {
|
||||
// ANY types do not have RData
|
||||
ASSERT_EQ(0, rrset->getRdataCount());
|
||||
return;
|
||||
@@ -229,7 +365,7 @@ void addDomainServer(DdnsDomainPtr& domain, const std::string& name,
|
||||
|
||||
// Verifies that the contents of the given transaction's DNS update request
|
||||
// is correct for adding a forward DNS entry
|
||||
void checkForwardAddRequest(NameChangeTransaction& tran) {
|
||||
void checkAddFwdAddressRequest(NameChangeTransaction& tran) {
|
||||
const D2UpdateMessagePtr& request = tran.getDnsUpdateRequest();
|
||||
ASSERT_TRUE(request);
|
||||
|
||||
@@ -276,7 +412,7 @@ void checkForwardAddRequest(NameChangeTransaction& tran) {
|
||||
|
||||
// Verifies that the contents of the given transaction's DNS update request
|
||||
// is correct for replacing a forward DNS entry
|
||||
void checkForwardReplaceRequest(NameChangeTransaction& tran) {
|
||||
void checkReplaceFwdAddressRequest(NameChangeTransaction& tran) {
|
||||
const D2UpdateMessagePtr& request = tran.getDnsUpdateRequest();
|
||||
ASSERT_TRUE(request);
|
||||
|
||||
@@ -332,7 +468,7 @@ void checkForwardReplaceRequest(NameChangeTransaction& tran) {
|
||||
|
||||
// Verifies that the contents of the given transaction's DNS update request
|
||||
// is correct for replacing a reverse DNS entry
|
||||
void checkReverseReplaceRequest(NameChangeTransaction& tran) {
|
||||
void checkReplaceRevPtrsRequest(NameChangeTransaction& tran) {
|
||||
const D2UpdateMessagePtr& request = tran.getDnsUpdateRequest();
|
||||
ASSERT_TRUE(request);
|
||||
|
||||
@@ -390,5 +526,133 @@ void checkReverseReplaceRequest(NameChangeTransaction& tran) {
|
||||
ASSERT_NO_THROW(request->toWire(renderer));
|
||||
}
|
||||
|
||||
void checkRemoveFwdAddressRequest(NameChangeTransaction& tran) {
|
||||
const D2UpdateMessagePtr& request = tran.getDnsUpdateRequest();
|
||||
ASSERT_TRUE(request);
|
||||
|
||||
// Safety check.
|
||||
dhcp_ddns::NameChangeRequestPtr ncr = tran.getNcr();
|
||||
ASSERT_TRUE(ncr);
|
||||
|
||||
std::string exp_zone_name = tran.getForwardDomain()->getName();
|
||||
std::string exp_fqdn = ncr->getFqdn();
|
||||
|
||||
// Verify the zone section.
|
||||
checkZone(request, exp_zone_name);
|
||||
|
||||
// Verify there is 1 RR in the PREREQUISITE Section.
|
||||
checkRRCount(request, D2UpdateMessage::SECTION_PREREQUISITE, 1);
|
||||
|
||||
// Verify the DHCID matching assertion RR.
|
||||
dns::RRsetPtr rrset;
|
||||
ASSERT_TRUE(rrset = getRRFromSection(request, D2UpdateMessage::
|
||||
SECTION_PREREQUISITE, 0));
|
||||
checkRR(rrset, exp_fqdn, dns::RRClass::IN(), dns::RRType::DHCID(),
|
||||
0, ncr);
|
||||
|
||||
// Verify there is 1 RR in the UPDATE Section.
|
||||
checkRRCount(request, D2UpdateMessage::SECTION_UPDATE, 1);
|
||||
|
||||
// Verify the FQDN/IP delete RR.
|
||||
const dns::RRType& exp_ip_rr_type = tran.getAddressRRType();
|
||||
ASSERT_TRUE(rrset = getRRFromSection(request, D2UpdateMessage::
|
||||
SECTION_UPDATE, 0));
|
||||
checkRR(rrset, exp_fqdn, dns::RRClass::NONE(), exp_ip_rr_type,
|
||||
0, ncr);
|
||||
|
||||
// Verify that it will render toWire without throwing.
|
||||
dns::MessageRenderer renderer;
|
||||
ASSERT_NO_THROW(request->toWire(renderer));
|
||||
}
|
||||
|
||||
void checkRemoveFwdRRsRequest(NameChangeTransaction& tran) {
|
||||
const D2UpdateMessagePtr& request = tran.getDnsUpdateRequest();
|
||||
ASSERT_TRUE(request);
|
||||
|
||||
// Safety check.
|
||||
dhcp_ddns::NameChangeRequestPtr ncr = tran.getNcr();
|
||||
ASSERT_TRUE(ncr);
|
||||
|
||||
std::string exp_zone_name = tran.getForwardDomain()->getName();
|
||||
std::string exp_fqdn = ncr->getFqdn();
|
||||
|
||||
// Verify the zone section.
|
||||
checkZone(request, exp_zone_name);
|
||||
|
||||
// Verify there is 1 RR in the PREREQUISITE Section.
|
||||
checkRRCount(request, D2UpdateMessage::SECTION_PREREQUISITE, 3);
|
||||
|
||||
// Verify the DHCID matches assertion.
|
||||
dns::RRsetPtr rrset;
|
||||
ASSERT_TRUE(rrset = getRRFromSection(request, D2UpdateMessage::
|
||||
SECTION_PREREQUISITE, 0));
|
||||
checkRR(rrset, exp_fqdn, dns::RRClass::IN(), dns::RRType::DHCID(),
|
||||
0, ncr);
|
||||
|
||||
// Verify the NO A RRs assertion.
|
||||
ASSERT_TRUE(rrset = getRRFromSection(request, D2UpdateMessage::
|
||||
SECTION_PREREQUISITE, 1));
|
||||
checkRR(rrset, exp_fqdn, dns::RRClass::NONE(), dns::RRType::A(),
|
||||
0, ncr, NO_RDATA);
|
||||
|
||||
// Verify the NO AAAA RRs assertion.
|
||||
ASSERT_TRUE(rrset = getRRFromSection(request, D2UpdateMessage::
|
||||
SECTION_PREREQUISITE, 2));
|
||||
checkRR(rrset, exp_fqdn, dns::RRClass::NONE(), dns::RRType::AAAA(),
|
||||
0, ncr, NO_RDATA);
|
||||
|
||||
// Verify there is 1 RR in the UPDATE Section.
|
||||
checkRRCount(request, D2UpdateMessage::SECTION_UPDATE, 1);
|
||||
|
||||
// Verify the delete all for the FQDN RR.
|
||||
ASSERT_TRUE(rrset = getRRFromSection(request, D2UpdateMessage::
|
||||
SECTION_UPDATE, 0));
|
||||
checkRR(rrset, exp_fqdn, dns::RRClass::ANY(), dns::RRType::ANY(),
|
||||
0, ncr);
|
||||
|
||||
// Verify that it will render toWire without throwing.
|
||||
dns::MessageRenderer renderer;
|
||||
ASSERT_NO_THROW(request->toWire(renderer));
|
||||
}
|
||||
|
||||
void checkRemoveRevPtrsRequest(NameChangeTransaction& tran) {
|
||||
const D2UpdateMessagePtr& request = tran.getDnsUpdateRequest();
|
||||
ASSERT_TRUE(request);
|
||||
|
||||
// Safety check.
|
||||
dhcp_ddns::NameChangeRequestPtr ncr = tran.getNcr();
|
||||
ASSERT_TRUE(ncr);
|
||||
|
||||
std::string exp_zone_name = tran.getReverseDomain()->getName();
|
||||
std::string exp_rev_addr = D2CfgMgr::reverseIpAddress(ncr->getIpAddress());
|
||||
|
||||
// Verify the zone section.
|
||||
checkZone(request, exp_zone_name);
|
||||
|
||||
// Verify there is 1 RR in the PREREQUISITE Section.
|
||||
checkRRCount(request, D2UpdateMessage::SECTION_PREREQUISITE, 1);
|
||||
|
||||
// Verify the FQDN-PTRNAME assertion RR.
|
||||
dns::RRsetPtr rrset;
|
||||
ASSERT_TRUE(rrset = getRRFromSection(request, D2UpdateMessage::
|
||||
SECTION_PREREQUISITE, 0));
|
||||
checkRR(rrset, exp_rev_addr, dns::RRClass::IN(), dns::RRType::PTR(),
|
||||
0, ncr);
|
||||
|
||||
// Verify there is 1 RR in the UPDATE Section.
|
||||
checkRRCount(request, D2UpdateMessage::SECTION_UPDATE, 1);
|
||||
|
||||
// Verify the delete all for the FQDN RR.
|
||||
ASSERT_TRUE(rrset = getRRFromSection(request, D2UpdateMessage::
|
||||
SECTION_UPDATE, 0));
|
||||
checkRR(rrset, exp_rev_addr, dns::RRClass::ANY(), dns::RRType::ANY(),
|
||||
0, ncr);
|
||||
|
||||
// Verify that it will render toWire without throwing.
|
||||
dns::MessageRenderer renderer;
|
||||
ASSERT_NO_THROW(request->toWire(renderer));
|
||||
}
|
||||
|
||||
|
||||
}; // namespace isc::d2
|
||||
}; // namespace isc
|
||||
|
@@ -21,6 +21,7 @@
|
||||
|
||||
#include <asio/ip/udp.hpp>
|
||||
#include <asio/socket_base.hpp>
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
namespace isc {
|
||||
namespace d2 {
|
||||
@@ -94,6 +95,68 @@ public:
|
||||
const dns::Rcode& response_rcode);
|
||||
};
|
||||
|
||||
/// @brief Base class Test fixture for testing transactions.
|
||||
class TransactionTest : public ::testing::Test {
|
||||
public:
|
||||
IOServicePtr io_service_;
|
||||
dhcp_ddns::NameChangeRequestPtr ncr_;
|
||||
DdnsDomainPtr forward_domain_;
|
||||
DdnsDomainPtr reverse_domain_;
|
||||
asiolink::IntervalTimer timer_;
|
||||
int run_time_;
|
||||
|
||||
/// #brief constants used to specify change directions for a transaction.
|
||||
static const unsigned int FORWARD_CHG; // Only forward change.
|
||||
static const unsigned int REVERSE_CHG; // Only reverse change.
|
||||
static const unsigned int FWD_AND_REV_CHG; // Both forward and reverse.
|
||||
|
||||
TransactionTest();
|
||||
virtual ~TransactionTest();
|
||||
|
||||
/// @brief Run the IO service for no more than a given amount of time.
|
||||
///
|
||||
/// Uses an IntervalTimer to interrupt the invocation of IOService run(),
|
||||
/// after the given number of milliseconds elapse. The timer executes
|
||||
/// the timesUp() method if it expires.
|
||||
///
|
||||
/// @param run_time amount of time in milliseconds to allow run to execute.
|
||||
void runTimedIO(int run_time);
|
||||
|
||||
/// @brief IO Timer expiration handler
|
||||
///
|
||||
/// Stops the IOSerivce and fails the current test.
|
||||
virtual void timesUp();
|
||||
|
||||
/// @brief Creates a transaction which requests an IPv4 DNS update.
|
||||
///
|
||||
/// The transaction is constructed around a predefined (i.e. "canned")
|
||||
/// IPv4 NameChangeRequest. The request has both forward and reverse DNS
|
||||
/// changes requested. Based upon the change mask, the transaction
|
||||
/// will have either the forward, reverse, or both domains populated.
|
||||
///
|
||||
/// @param change_type selects the type of change requested, CHG_ADD or
|
||||
/// CHG_REMOVE.
|
||||
/// @param change_mask determines which change directions are requested
|
||||
/// FORWARD_CHG, REVERSE_CHG, or FWD_AND_REV_CHG.
|
||||
void setupForIPv4Transaction(dhcp_ddns::NameChangeType change_type,
|
||||
int change_mask);
|
||||
|
||||
/// @brief Creates a transaction which requests an IPv6 DNS update.
|
||||
///
|
||||
/// The transaction is constructed around a predefined (i.e. "canned")
|
||||
/// IPv6 NameChangeRequest. The request has both forward and reverse DNS
|
||||
/// changes requested. Based upon the change mask, the transaction
|
||||
/// will have either the forward, reverse, or both domains populated.
|
||||
///
|
||||
/// @param change_type selects the type of change requested, CHG_ADD or
|
||||
/// CHG_REMOVE.
|
||||
/// @param change_mask determines which change directions are requested
|
||||
/// FORWARD_CHG, REVERSE_CHG, or FWD_AND_REV_CHG.
|
||||
void setupForIPv6Transaction(dhcp_ddns::NameChangeType change_type,
|
||||
int change_mask);
|
||||
};
|
||||
|
||||
|
||||
/// @brief Tests the number of RRs in a request section against a given count.
|
||||
///
|
||||
/// This function actually returns the number of RRsetPtrs in a section. Since
|
||||
@@ -124,9 +187,14 @@ extern void checkZone(const D2UpdateMessagePtr& request,
|
||||
/// @param exp_typ expected RRType value of RRset
|
||||
/// @param exp_ttl expected TTL value of RRset
|
||||
/// @param ncr NameChangeRequest on which the RRset is based
|
||||
/// @param has_rdata if true, RRset's rdata will be checked based on it's
|
||||
/// RRType. Set this to false if the RRset's type supports Rdata but it does
|
||||
/// not contain it. For instance, prerequisites of type NONE have no Rdata
|
||||
/// where udpates of type NONE may.
|
||||
extern void checkRR(dns::RRsetPtr rrset, const std::string& exp_name,
|
||||
const dns::RRClass& exp_class, const dns::RRType& exp_type,
|
||||
unsigned int exp_ttl, dhcp_ddns::NameChangeRequestPtr ncr);
|
||||
unsigned int exp_ttl, dhcp_ddns::NameChangeRequestPtr ncr,
|
||||
bool has_rdata=true);
|
||||
|
||||
/// @brief Fetches an RR(set) from a given section of a request
|
||||
///
|
||||
@@ -163,7 +231,7 @@ extern dns::RRsetPtr getRRFromSection(const D2UpdateMessagePtr& request,
|
||||
/// adding a forward DNS mapping.
|
||||
///
|
||||
/// @param tran Transaction containing the request to be verified.
|
||||
extern void checkForwardAddRequest(NameChangeTransaction& tran);
|
||||
extern void checkAddFwdAddressRequest(NameChangeTransaction& tran);
|
||||
|
||||
/// @brief Verifies a forward mapping replacement DNS update request
|
||||
///
|
||||
@@ -171,7 +239,7 @@ extern void checkForwardAddRequest(NameChangeTransaction& tran);
|
||||
/// replacing a forward DNS mapping.
|
||||
///
|
||||
/// @param tran Transaction containing the request to be verified.
|
||||
extern void checkForwardReplaceRequest(NameChangeTransaction& tran);
|
||||
extern void checkReplaceFwdAddressRequest(NameChangeTransaction& tran);
|
||||
|
||||
/// @brief Verifies a reverse mapping replacement DNS update request
|
||||
///
|
||||
@@ -179,7 +247,32 @@ extern void checkForwardReplaceRequest(NameChangeTransaction& tran);
|
||||
/// replacing a reverse DNS mapping.
|
||||
///
|
||||
/// @param tran Transaction containing the request to be verified.
|
||||
extern void checkReverseReplaceRequest(NameChangeTransaction& tran);
|
||||
extern void checkReplaceRevPtrsRequest(NameChangeTransaction& tran);
|
||||
|
||||
/// @brief Verifies a forward address removal DNS update request
|
||||
///
|
||||
/// Tests that the DNS Update request for a given transaction, is correct for
|
||||
/// removing the forward address DNS entry.
|
||||
///
|
||||
/// @param tran Transaction containing the request to be verified.
|
||||
extern void checkRemoveFwdAddressRequest(NameChangeTransaction& tran);
|
||||
|
||||
/// @brief Verifies a forward RR removal DNS update request
|
||||
///
|
||||
/// Tests that the DNS Update request for a given transaction, is correct for
|
||||
/// removing forward RR DNS entries.
|
||||
///
|
||||
/// @param tran Transaction containing the request to be verified.
|
||||
extern void checkRemoveFwdRRsRequest(NameChangeTransaction& tran);
|
||||
|
||||
/// @brief Verifies a reverse mapping removal DNS update request
|
||||
///
|
||||
/// Tests that the DNS Update request for a given transaction, is correct for
|
||||
/// removing a reverse DNS mapping.
|
||||
///
|
||||
/// @param tran Transaction containing the request to be verified.
|
||||
extern void checkRemoveRevPtrsRequest(NameChangeTransaction& tran);
|
||||
|
||||
|
||||
/// @brief Creates a NameChangeRequest from JSON string.
|
||||
///
|
||||
|
@@ -997,19 +997,10 @@ TEST_F(NameChangeTransactionTest, addLeaseAddressRData) {
|
||||
ASSERT_NO_THROW(name_change = makeCannedTransaction());
|
||||
dhcp_ddns::NameChangeRequestPtr ncr = name_change->getNcr();
|
||||
|
||||
// Test a lease rdata add failure.
|
||||
// As you cannot stuff an invalid address into an NCR, the only failure
|
||||
// that can be induced is a mismatch between the RData and the RRset.
|
||||
// Attempt to add a lease address Rdata, this should fail.
|
||||
// Create an Any class/Any type RRset, they are not allowed to contain
|
||||
// rdata.
|
||||
dns::RRsetPtr rrset(new dns::RRset(dns::Name("bs"), dns::RRClass::ANY(),
|
||||
dns::RRType::ANY(), dns::RRTTL(0)));
|
||||
ASSERT_THROW(name_change->addLeaseAddressRdata(rrset), std::exception);
|
||||
|
||||
// Verify we can add a lease RData to an valid RRset.
|
||||
rrset.reset(new dns::RRset(dns::Name("bs"), dns::RRClass::IN(),
|
||||
name_change->getAddressRRType(), dns::RRTTL(0)));
|
||||
dns::RRsetPtr rrset(new dns::RRset(dns::Name("bs"), dns::RRClass::IN(),
|
||||
name_change->getAddressRRType(),
|
||||
dns::RRTTL(0)));
|
||||
ASSERT_NO_THROW(name_change->addLeaseAddressRdata(rrset));
|
||||
|
||||
// Verify the Rdata was added and the value is correct.
|
||||
@@ -1026,14 +1017,9 @@ TEST_F(NameChangeTransactionTest, addDhcidRdata) {
|
||||
ASSERT_NO_THROW(name_change = makeCannedTransaction());
|
||||
dhcp_ddns::NameChangeRequestPtr ncr = name_change->getNcr();
|
||||
|
||||
// Test a DHCID rdata add failure.
|
||||
dns::RRsetPtr rrset(new dns::RRset(dns::Name("bs"), dns::RRClass::ANY(),
|
||||
dns::RRType::ANY(), dns::RRTTL(0)));
|
||||
ASSERT_THROW(name_change->addDhcidRdata(rrset), std::exception);
|
||||
|
||||
// Verify we can add a lease RData to an valid RRset.
|
||||
rrset.reset(new dns::RRset(dns::Name("bs"), dns::RRClass::IN(),
|
||||
dns::RRType::DHCID(), dns::RRTTL(0)));
|
||||
dns::RRsetPtr rrset(new dns::RRset(dns::Name("bs"), dns::RRClass::IN(),
|
||||
dns::RRType::DHCID(), dns::RRTTL(0)));
|
||||
ASSERT_NO_THROW(name_change->addDhcidRdata(rrset));
|
||||
|
||||
// Verify the Rdata was added and the value is correct.
|
||||
@@ -1053,14 +1039,9 @@ TEST_F(NameChangeTransactionTest, addPtrRdata) {
|
||||
ASSERT_NO_THROW(name_change = makeCannedTransaction());
|
||||
dhcp_ddns::NameChangeRequestPtr ncr = name_change->getNcr();
|
||||
|
||||
// Test a PTR rdata add failure.
|
||||
dns::RRsetPtr rrset(new dns::RRset(dns::Name("bs"), dns::RRClass::ANY(),
|
||||
dns::RRType::ANY(), dns::RRTTL(0)));
|
||||
ASSERT_THROW(name_change->addPtrRdata(rrset), std::exception);
|
||||
|
||||
// Verify we can add a PTR RData to an valid RRset.
|
||||
rrset.reset(new dns::RRset(dns::Name("bs"), dns::RRClass::IN(),
|
||||
dns::RRType::PTR(), dns::RRTTL(0)));
|
||||
dns::RRsetPtr rrset (new dns::RRset(dns::Name("bs"), dns::RRClass::IN(),
|
||||
dns::RRType::PTR(), dns::RRTTL(0)));
|
||||
ASSERT_NO_THROW(name_change->addPtrRdata(rrset));
|
||||
|
||||
// Verify the Rdata was added and the value is correct.
|
||||
|
Reference in New Issue
Block a user