mirror of
https://gitlab.isc.org/isc-projects/kea
synced 2025-08-22 09:57:41 +00:00
718 lines
27 KiB
C++
718 lines
27 KiB
C++
// Copyright (C) 2023 Internet Systems Consortium, Inc. ("ISC")
|
|
//
|
|
// This Source Code Form is subject to the terms of the Mozilla Public
|
|
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
//
|
|
#include <config.h>
|
|
|
|
#include <d2/check_exists_remove.h>
|
|
#include <d2srv/d2_cfg_mgr.h>
|
|
#include <d2srv/d2_log.h>
|
|
|
|
#include <functional>
|
|
|
|
namespace isc {
|
|
namespace d2 {
|
|
|
|
|
|
// CheckExistsRemoveTransaction states
|
|
const int CheckExistsRemoveTransaction::REMOVING_FWD_ADDRS_ST;
|
|
const int CheckExistsRemoveTransaction::REMOVING_FWD_RRS_ST;
|
|
const int CheckExistsRemoveTransaction::REMOVING_REV_PTRS_ST;
|
|
|
|
// CheckExistsRemoveTransaction events
|
|
// Currently CheckExistsRemoveTransaction does not define any events.
|
|
|
|
CheckExistsRemoveTransaction::
|
|
CheckExistsRemoveTransaction(asiolink::IOServicePtr& io_service,
|
|
dhcp_ddns::NameChangeRequestPtr& ncr,
|
|
DdnsDomainPtr& forward_domain,
|
|
DdnsDomainPtr& reverse_domain,
|
|
D2CfgMgrPtr& cfg_mgr)
|
|
: NameChangeTransaction(io_service, ncr, forward_domain, reverse_domain,
|
|
cfg_mgr) {
|
|
if (ncr->getChangeType() != isc::dhcp_ddns::CHG_REMOVE) {
|
|
isc_throw (CheckExistsRemoveTransactionError,
|
|
"CheckExistsRemoveTransaction, request type must be CHG_REMOVE");
|
|
}
|
|
}
|
|
|
|
CheckExistsRemoveTransaction::~CheckExistsRemoveTransaction(){
|
|
}
|
|
|
|
void
|
|
CheckExistsRemoveTransaction::defineEvents() {
|
|
// Call superclass impl first.
|
|
NameChangeTransaction::defineEvents();
|
|
|
|
// Define CheckExistsRemoveTransaction events.
|
|
// Currently CheckExistsRemoveTransaction does not define any events.
|
|
// defineEvent(TBD_EVENT, "TBD_EVT");
|
|
}
|
|
|
|
void
|
|
CheckExistsRemoveTransaction::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 CheckExistsRemoveTransaction events by attempting to fetch them.
|
|
// Currently CheckExistsRemoveTransaction does not define any events.
|
|
// getEvent(TBD_EVENT);
|
|
}
|
|
|
|
void
|
|
CheckExistsRemoveTransaction::defineStates() {
|
|
// Call superclass impl first.
|
|
NameChangeTransaction::defineStates();
|
|
|
|
// Define CheckExistsRemoveTransaction states.
|
|
defineState(READY_ST, "READY_ST",
|
|
std::bind(&CheckExistsRemoveTransaction::readyHandler, this));
|
|
|
|
defineState(SELECTING_FWD_SERVER_ST, "SELECTING_FWD_SERVER_ST",
|
|
std::bind(&CheckExistsRemoveTransaction::selectingFwdServerHandler,
|
|
this));
|
|
|
|
defineState(SELECTING_REV_SERVER_ST, "SELECTING_REV_SERVER_ST",
|
|
std::bind(&CheckExistsRemoveTransaction::selectingRevServerHandler,
|
|
this));
|
|
|
|
defineState(REMOVING_FWD_ADDRS_ST, "REMOVING_FWD_ADDRS_ST",
|
|
std::bind(&CheckExistsRemoveTransaction::removingFwdAddrsHandler,
|
|
this));
|
|
|
|
defineState(REMOVING_FWD_RRS_ST, "REMOVING_FWD_RRS_ST",
|
|
std::bind(&CheckExistsRemoveTransaction::removingFwdRRsHandler,
|
|
this));
|
|
|
|
defineState(REMOVING_REV_PTRS_ST, "REMOVING_REV_PTRS_ST",
|
|
std::bind(&CheckExistsRemoveTransaction::removingRevPtrsHandler,
|
|
this));
|
|
|
|
defineState(PROCESS_TRANS_OK_ST, "PROCESS_TRANS_OK_ST",
|
|
std::bind(&CheckExistsRemoveTransaction::processRemoveOkHandler,
|
|
this));
|
|
|
|
defineState(PROCESS_TRANS_FAILED_ST, "PROCESS_TRANS_FAILED_ST",
|
|
std::bind(&CheckExistsRemoveTransaction::processRemoveFailedHandler,
|
|
this));
|
|
}
|
|
|
|
void
|
|
CheckExistsRemoveTransaction::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 CheckExistsRemoveTransaction states by attempting to fetch them.
|
|
getStateInternal(REMOVING_FWD_ADDRS_ST);
|
|
getStateInternal(REMOVING_FWD_RRS_ST);
|
|
getStateInternal(REMOVING_REV_PTRS_ST);
|
|
}
|
|
|
|
void
|
|
CheckExistsRemoveTransaction::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(CheckExistsRemoveTransactionError,
|
|
"Wrong event for context: " << getContextStr());
|
|
}
|
|
}
|
|
|
|
void
|
|
CheckExistsRemoveTransaction::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(CheckExistsRemoveTransactionError,
|
|
"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
|
|
CheckExistsRemoveTransaction::removingFwdAddrsHandler() {
|
|
if (doOnEntry()) {
|
|
// Clear the update attempts count on initial transition.
|
|
clearUpdateAttempts();
|
|
}
|
|
|
|
switch(getNextEvent()) {
|
|
case SERVER_SELECTED_EVT:
|
|
try {
|
|
clearDnsUpdateRequest();
|
|
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(d2_to_dns_logger,
|
|
DHCP_DDNS_FORWARD_REMOVE_ADDRS_BUILD_FAILURE)
|
|
.arg(getRequestId())
|
|
.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("Forward A/AAAA Remove");
|
|
break;
|
|
|
|
case IO_COMPLETED_EVT: {
|
|
switch (getDnsUpdateStatus()) {
|
|
case DNSClient::SUCCESS: {
|
|
// We successfully received a response packet from the server.
|
|
// The RCODE will be based on a value-dependent RRset search,
|
|
// see RFC 2136 section 3.2.3/3.2.4.
|
|
const dns::Rcode& rcode = getDnsUpdateResponse()->getRcode();
|
|
if ((rcode == dns::Rcode::NOERROR()) ||
|
|
(rcode == dns::Rcode::NXRRSET())) {
|
|
// 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(d2_to_dns_logger, DHCP_DDNS_FORWARD_REMOVE_ADDRS_REJECTED)
|
|
.arg(getRequestId())
|
|
.arg(getCurrentServer()->toText())
|
|
.arg(getNcr()->getFqdn())
|
|
.arg(rcode.getCode());
|
|
transition(PROCESS_TRANS_FAILED_ST, UPDATE_FAILED_EVT);
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
case DNSClient::TIMEOUT:
|
|
// No response from the server, log it and set up
|
|
// to select the next server for a retry.
|
|
LOG_ERROR(d2_to_dns_logger, DHCP_DDNS_FORWARD_REMOVE_ADDRS_TIMEOUT)
|
|
.arg(getRequestId())
|
|
.arg(getNcr()->getFqdn())
|
|
.arg(getCurrentServer()->toText());
|
|
|
|
retryTransition(SELECTING_FWD_SERVER_ST);
|
|
break;
|
|
|
|
case DNSClient::OTHER:
|
|
// We couldn't send to the current server, log it and set up
|
|
// to select the next server for a retry.
|
|
LOG_ERROR(d2_to_dns_logger, DHCP_DDNS_FORWARD_REMOVE_ADDRS_IO_ERROR)
|
|
.arg(getRequestId())
|
|
.arg(getNcr()->getFqdn())
|
|
.arg(getCurrentServer()->toText());
|
|
|
|
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(d2_to_dns_logger, DHCP_DDNS_FORWARD_REMOVE_ADDRS_RESP_CORRUPT)
|
|
.arg(getRequestId())
|
|
.arg(getCurrentServer()->toText())
|
|
.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(d2_to_dns_logger,
|
|
DHCP_DDNS_FORWARD_REMOVE_ADDRS_BAD_DNSCLIENT_STATUS)
|
|
.arg(getRequestId())
|
|
.arg(getDnsUpdateStatus())
|
|
.arg(getNcr()->getFqdn())
|
|
.arg(getCurrentServer()->toText());
|
|
|
|
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(CheckExistsRemoveTransactionError,
|
|
"Wrong event for context: " << getContextStr());
|
|
}
|
|
}
|
|
|
|
|
|
void
|
|
CheckExistsRemoveTransaction::removingFwdRRsHandler() {
|
|
if (doOnEntry()) {
|
|
// Clear the update attempts count on initial transition.
|
|
clearUpdateAttempts();
|
|
}
|
|
|
|
switch(getNextEvent()) {
|
|
case UPDATE_OK_EVT:
|
|
case SERVER_SELECTED_EVT:
|
|
try {
|
|
clearDnsUpdateRequest();
|
|
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(d2_to_dns_logger,
|
|
DHCP_DDNS_FORWARD_REMOVE_RRS_BUILD_FAILURE)
|
|
.arg(getRequestId())
|
|
.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("Forward RR Remove");
|
|
break;
|
|
|
|
case IO_COMPLETED_EVT: {
|
|
switch (getDnsUpdateStatus()) {
|
|
case DNSClient::SUCCESS: {
|
|
// We successfully received a response packet from the server.
|
|
// The RCODE will be based on a value-dependent RRset search,
|
|
// see RFC 2136 section 3.2.3/3.2.4.
|
|
const dns::Rcode& rcode = getDnsUpdateResponse()->getRcode();
|
|
if ((rcode == dns::Rcode::NOERROR()) ||
|
|
(rcode == dns::Rcode::NXRRSET())) {
|
|
// We were able to remove them or they were not there (
|
|
// Rcode of NXRRSET means there are no matching RRsets).
|
|
// In either case, we consider it success and 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(d2_to_dns_logger, DHCP_DDNS_FORWARD_REMOVE_RRS_REJECTED)
|
|
.arg(getRequestId())
|
|
.arg(getCurrentServer()->toText())
|
|
.arg(getNcr()->getFqdn())
|
|
.arg(rcode.getCode());
|
|
transition(PROCESS_TRANS_FAILED_ST, UPDATE_FAILED_EVT);
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
case DNSClient::TIMEOUT:
|
|
// No response from the server, log it and set up
|
|
// to select the next server for a retry.
|
|
LOG_ERROR(d2_to_dns_logger, DHCP_DDNS_FORWARD_REMOVE_RRS_TIMEOUT)
|
|
.arg(getRequestId())
|
|
.arg(getNcr()->getFqdn())
|
|
.arg(getCurrentServer()->toText());
|
|
|
|
// @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::OTHER:
|
|
// We couldn't send to the current server, log it and set up
|
|
// to select the next server for a retry.
|
|
LOG_ERROR(d2_to_dns_logger, DHCP_DDNS_FORWARD_REMOVE_RRS_IO_ERROR)
|
|
.arg(getRequestId())
|
|
.arg(getNcr()->getFqdn())
|
|
.arg(getCurrentServer()->toText());
|
|
|
|
// @note same commentary as in TIMEOUT above case.
|
|
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(d2_to_dns_logger, DHCP_DDNS_FORWARD_REMOVE_RRS_RESP_CORRUPT)
|
|
.arg(getRequestId())
|
|
.arg(getCurrentServer()->toText())
|
|
.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(d2_to_dns_logger,
|
|
DHCP_DDNS_FORWARD_REMOVE_RRS_BAD_DNSCLIENT_STATUS)
|
|
.arg(getRequestId())
|
|
.arg(getDnsUpdateStatus())
|
|
.arg(getNcr()->getFqdn())
|
|
.arg(getCurrentServer()->toText());
|
|
|
|
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(CheckExistsRemoveTransactionError,
|
|
"Wrong event for context: " << getContextStr());
|
|
}
|
|
}
|
|
|
|
|
|
void
|
|
CheckExistsRemoveTransaction::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(CheckExistsRemoveTransactionError,
|
|
"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
|
|
CheckExistsRemoveTransaction::removingRevPtrsHandler() {
|
|
if (doOnEntry()) {
|
|
// Clear the update attempts count on initial transition.
|
|
clearUpdateAttempts();
|
|
}
|
|
|
|
switch(getNextEvent()) {
|
|
case SERVER_SELECTED_EVT:
|
|
try {
|
|
clearDnsUpdateRequest();
|
|
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(d2_to_dns_logger, DHCP_DDNS_REVERSE_REMOVE_BUILD_FAILURE)
|
|
.arg(getRequestId())
|
|
.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("Reverse Remove");
|
|
break;
|
|
|
|
case IO_COMPLETED_EVT: {
|
|
switch (getDnsUpdateStatus()) {
|
|
case DNSClient::SUCCESS: {
|
|
// We successfully received a response packet from the server.
|
|
// The RCODE will be based on a value-dependent RRset search,
|
|
// see RFC 2136 section 3.2.3/3.2.4.
|
|
const dns::Rcode& rcode = getDnsUpdateResponse()->getRcode();
|
|
if ((rcode == dns::Rcode::NOERROR()) ||
|
|
(rcode == dns::Rcode::NXRRSET())) {
|
|
// We were able to remove the reverse mapping or they were
|
|
// not there (Rcode of NXRRSET means there are no matching
|
|
// RRsets). In either case, mark it as done.
|
|
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(d2_to_dns_logger, DHCP_DDNS_REVERSE_REMOVE_REJECTED)
|
|
.arg(getRequestId())
|
|
.arg(getCurrentServer()->toText())
|
|
.arg(getNcr()->getFqdn())
|
|
.arg(rcode.getCode());
|
|
transition(PROCESS_TRANS_FAILED_ST, UPDATE_FAILED_EVT);
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
case DNSClient::TIMEOUT:
|
|
// No response from the server, log it and set up
|
|
// to select the next server for a retry.
|
|
LOG_ERROR(d2_to_dns_logger, DHCP_DDNS_REVERSE_REMOVE_TIMEOUT)
|
|
.arg(getRequestId())
|
|
.arg(getNcr()->getFqdn())
|
|
.arg(getCurrentServer()->toText());
|
|
|
|
// 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::OTHER:
|
|
// We couldn't send to the current server, log it and set up
|
|
// to select the next server for a retry.
|
|
LOG_ERROR(d2_to_dns_logger, DHCP_DDNS_REVERSE_REMOVE_IO_ERROR)
|
|
.arg(getRequestId())
|
|
.arg(getNcr()->getFqdn())
|
|
.arg(getCurrentServer()->toText());
|
|
|
|
// 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(d2_to_dns_logger, DHCP_DDNS_REVERSE_REMOVE_RESP_CORRUPT)
|
|
.arg(getRequestId())
|
|
.arg(getCurrentServer()->toText())
|
|
.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(d2_to_dns_logger,
|
|
DHCP_DDNS_REVERSE_REMOVE_BAD_DNSCLIENT_STATUS)
|
|
.arg(getRequestId())
|
|
.arg(getDnsUpdateStatus())
|
|
.arg(getNcr()->getFqdn())
|
|
.arg(getCurrentServer()->toText());
|
|
|
|
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(CheckExistsRemoveTransactionError,
|
|
"Wrong event for context: " << getContextStr());
|
|
}
|
|
}
|
|
|
|
|
|
void
|
|
CheckExistsRemoveTransaction::processRemoveOkHandler() {
|
|
switch(getNextEvent()) {
|
|
case UPDATE_OK_EVT:
|
|
LOG_INFO(d2_to_dns_logger, DHCP_DDNS_REMOVE_SUCCEEDED)
|
|
.arg(getRequestId())
|
|
.arg(getNcr()->toText());
|
|
setNcrStatus(dhcp_ddns::ST_COMPLETED);
|
|
endModel();
|
|
break;
|
|
default:
|
|
// Event is invalid.
|
|
isc_throw(CheckExistsRemoveTransactionError,
|
|
"Wrong event for context: " << getContextStr());
|
|
}
|
|
}
|
|
|
|
void
|
|
CheckExistsRemoveTransaction::processRemoveFailedHandler() {
|
|
switch(getNextEvent()) {
|
|
case UPDATE_FAILED_EVT:
|
|
case NO_MORE_SERVERS_EVT:
|
|
case SERVER_IO_ERROR_EVT:
|
|
setNcrStatus(dhcp_ddns::ST_FAILED);
|
|
LOG_ERROR(d2_to_dns_logger, DHCP_DDNS_REMOVE_FAILED)
|
|
.arg(getRequestId())
|
|
.arg(transactionOutcomeString());
|
|
endModel();
|
|
break;
|
|
default:
|
|
// Event is invalid.
|
|
isc_throw(CheckExistsRemoveTransactionError,
|
|
"Wrong event for context: " << getContextStr());
|
|
}
|
|
}
|
|
|
|
void
|
|
CheckExistsRemoveTransaction::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 exists prerequisite RR and add it to the
|
|
// pre-requisite section
|
|
// Based on RFC 2136, section 2.4.1
|
|
dns::RRsetPtr prereq(new dns::RRset(fqdn, dns::RRClass::ANY(),
|
|
dns::RRType::DHCID(), dns::RRTTL(0)));
|
|
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 RFC 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
|
|
CheckExistsRemoveTransaction::buildRemoveFwdRRsRequest() {
|
|
// Construct an empty request.
|
|
D2UpdateMessagePtr request = prepNewRequest(getForwardDomain());
|
|
|
|
// Construct dns::Name from NCR fqdn.
|
|
dns::Name fqdn(dns::Name(getNcr()->getFqdn()));
|
|
|
|
// First build the Prerequisite Section.
|
|
|
|
// 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.
|
|
dns::RRsetPtr prereq(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 AAAA 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 DHCID RRs for FQDN.
|
|
// Add the RR to update section.
|
|
// Based on RFC 2136, section 2.5.2.
|
|
dns::RRsetPtr update(new dns::RRset(fqdn, dns::RRClass::ANY(),
|
|
dns::RRType::DHCID(), dns::RRTTL(0)));
|
|
request->addRRset(D2UpdateMessage::SECTION_UPDATE, update);
|
|
|
|
// Set the transaction's update request to the new request.
|
|
setDnsUpdateRequest(request);
|
|
}
|
|
|
|
void
|
|
CheckExistsRemoveTransaction::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
|