Kea 1.9.11
simple_remove.cc
Go to the documentation of this file.
1// Copyright (C) 2013-2021 Internet Systems Consortium, Inc. ("ISC")
2//
3// This Source Code Form is subject to the terms of the Mozilla Public
4// License, v. 2.0. If a copy of the MPL was not distributed with this
5// file, You can obtain one at http://mozilla.org/MPL/2.0/.
6
7#include <config.h>
8
9#include <d2/simple_remove.h>
10#include <d2srv/d2_cfg_mgr.h>
11#include <d2srv/d2_log.h>
12
13#include <functional>
14
15namespace isc {
16namespace d2 {
17
18
19// SimpleRemoveTransaction states
22
23// SimpleRemoveTransaction events
24// Currently SimpleRemoveTransaction does not define any events.
25
29 DdnsDomainPtr& forward_domain,
30 DdnsDomainPtr& reverse_domain,
31 D2CfgMgrPtr& cfg_mgr)
32 : NameChangeTransaction(io_service, ncr, forward_domain, reverse_domain,
33 cfg_mgr) {
34 if (ncr->getChangeType() != isc::dhcp_ddns::CHG_REMOVE) {
36 "SimpleRemoveTransaction, request type must be CHG_REMOVE");
37 }
38}
39
41}
42
43void
45 // Call superclass impl first.
47
48 // Define SimpleRemoveTransaction events.
49 // Currently SimpleRemoveTransaction does not define any events.
50 // defineEvent(TBD_EVENT, "TBD_EVT");
51}
52
53void
55 // Call superclass implementation first to verify its events. These are
56 // events common to all transactions, and they must be defined.
57 // SELECT_SERVER_EVT
58 // SERVER_SELECTED_EVT
59 // SERVER_IO_ERROR_EVT
60 // NO_MORE_SERVERS_EVT
61 // IO_COMPLETED_EVT
62 // UPDATE_OK_EVT
63 // UPDATE_FAILED_EVT
65
66 // Verify SimpleRemoveTransaction events by attempting to fetch them.
67 // Currently SimpleRemoveTransaction does not define any events.
68 // getEvent(TBD_EVENT);
69}
70
71void
73 // Call superclass impl first.
75
76 // Define SimpleRemoveTransaction states.
77 defineState(READY_ST, "READY_ST",
79
80 defineState(SELECTING_FWD_SERVER_ST, "SELECTING_FWD_SERVER_ST",
82 this));
83
84 defineState(SELECTING_REV_SERVER_ST, "SELECTING_REV_SERVER_ST",
86 this));
87
88 defineState(REMOVING_FWD_RRS_ST, "REMOVING_FWD_RRS_ST",
90 this));
91
92 defineState(REMOVING_REV_PTRS_ST, "REMOVING_REV_PTRS_ST",
94 this));
95
96 defineState(PROCESS_TRANS_OK_ST, "PROCESS_TRANS_OK_ST",
98 this));
99
100 defineState(PROCESS_TRANS_FAILED_ST, "PROCESS_TRANS_FAILED_ST",
102 this));
103}
104
105void
107 // Call superclass implementation first to verify its states. These are
108 // states common to all transactions, and they must be defined.
109 // READY_ST
110 // SELECTING_FWD_SERVER_ST
111 // SELECTING_REV_SERVER_ST
112 // PROCESS_TRANS_OK_ST
113 // PROCESS_TRANS_FAILED_ST
115
116 // Verify SimpleRemoveTransaction states by attempting to fetch them.
119}
120
121void
123 switch(getNextEvent()) {
124 case START_EVT:
125 if (getForwardDomain()) {
126 // Request includes a forward change, do that first.
128 } else {
129 // Reverse change only, transition accordingly.
131 }
132
133 break;
134 default:
135 // Event is invalid.
137 "Wrong event for context: " << getContextStr());
138 }
139}
140
141void
143 switch(getNextEvent()) {
145 // First time through for this transaction, so initialize server
146 // selection.
148 break;
150 // We failed to communicate with current server. Attempt to select
151 // another one below.
152 break;
153 default:
154 // Event is invalid.
156 "Wrong event for context: " << getContextStr());
157 }
158
159 // Select the next server from the list of forward servers.
160 if (selectNextServer()) {
161 // We have a server to try.
163 }
164 else {
165 // Server list is exhausted, so fail the transaction.
167 }
168}
169
170void
172 if (doOnEntry()) {
173 // Clear the request on initial transition. This allows us to reuse
174 // the request on retries if necessary.
176 }
177
178 switch(getNextEvent()) {
179 case UPDATE_OK_EVT:
181 if (!getDnsUpdateRequest()) {
182 // Request hasn't been constructed yet, so build it.
183 try {
185 } catch (const std::exception& ex) {
186 // While unlikely, the build might fail if we have invalid
187 // data. Should that be the case, we need to fail the
188 // transaction.
191 .arg(getRequestId())
192 .arg(getNcr()->toText())
193 .arg(ex.what());
195 break;
196 }
197 }
198
199 // Call sendUpdate() to initiate the async send. Note it also sets
200 // next event to NOP_EVT.
201 sendUpdate("Forward RR Remove");
202 break;
203
204 case IO_COMPLETED_EVT: {
205 switch (getDnsUpdateStatus()) {
206 case DNSClient::SUCCESS: {
207 // We successfully received a response packet from the server.
208 // The RCODE will be based on a value-dependent RRset search,
209 // see RFC 2136 section 3.2.3/3.2.4.
210 const dns::Rcode& rcode = getDnsUpdateResponse()->getRcode();
211 if ((rcode == dns::Rcode::NOERROR()) ||
212 (rcode == dns::Rcode::NXRRSET())) {
213 // We were able to remove them or they were not there (
214 // Rcode of NXRRSET means there are no matching RRsets).
215 // In either case, we consider it success and mark it as done.
217
218 // If request calls for reverse update then do that next,
219 // otherwise we can process ok.
220 if (getReverseDomain()) {
222 } else {
224 }
225 } else {
226 // Any other value means cease.
227 // If we get not authorized should try the next server in
228 // the list? @todo This needs some discussion perhaps.
230 .arg(getRequestId())
231 .arg(getCurrentServer()->toText())
232 .arg(getNcr()->getFqdn())
233 .arg(rcode.getCode());
235 }
236
237 break;
238 }
239
241 case DNSClient::OTHER:
242 // We couldn't send to the current server, log it and set up
243 // to select the next server for a retry.
244 // @note For now we treat OTHER as an IO error like TIMEOUT. It
245 // is not entirely clear if this is accurate.
247 .arg(getRequestId())
248 .arg(getNcr()->getFqdn())
249 .arg(getCurrentServer()->toText());
250
252 break;
253
255 // A response was received but was corrupt. Retry it like an IO
256 // error.
258 .arg(getRequestId())
259 .arg(getCurrentServer()->toText())
260 .arg(getNcr()->getFqdn());
261
263 break;
264
265 default:
266 // Any other value and we will fail this transaction, something
267 // bigger is wrong.
270 .arg(getRequestId())
271 .arg(getDnsUpdateStatus())
272 .arg(getNcr()->getFqdn())
273 .arg(getCurrentServer()->toText());
274
276 break;
277 } // end switch on dns_status
278
279 break;
280 } // end case IO_COMPLETE_EVT
281
282 default:
283 // Event is invalid.
285 "Wrong event for context: " << getContextStr());
286 }
287}
288
289
290void
292 switch(getNextEvent()) {
294 // First time through for this transaction, so initialize server
295 // selection.
297 break;
299 // We failed to communicate with current server. Attempt to select
300 // another one below.
301 break;
302 default:
303 // Event is invalid.
305 "Wrong event for context: " << getContextStr());
306 }
307
308 // Select the next server from the list of forward servers.
309 if (selectNextServer()) {
310 // We have a server to try.
312 }
313 else {
314 // Server list is exhausted, so fail the transaction.
316 }
317}
318
319
320void
322 if (doOnEntry()) {
323 // Clear the request on initial transition. This allows us to reuse
324 // the request on retries if necessary.
326 }
327
328 switch(getNextEvent()) {
330 if (!getDnsUpdateRequest()) {
331 // Request hasn't been constructed yet, so build it.
332 try {
334 } catch (const std::exception& ex) {
335 // While unlikely, the build might fail if we have invalid
336 // data. Should that be the case, we need to fail the
337 // transaction.
339 .arg(getRequestId())
340 .arg(getNcr()->toText())
341 .arg(ex.what());
343 break;
344 }
345 }
346
347 // Call sendUpdate() to initiate the async send. Note it also sets
348 // next event to NOP_EVT.
349 sendUpdate("Reverse Remove");
350 break;
351
352 case IO_COMPLETED_EVT: {
353 switch (getDnsUpdateStatus()) {
354 case DNSClient::SUCCESS: {
355 // We successfully received a response packet from the server.
356 // The RCODE will be based on a value-dependent RRset search,
357 // see RFC 2136 section 3.2.3/3.2.4.
358 const dns::Rcode& rcode = getDnsUpdateResponse()->getRcode();
359 if ((rcode == dns::Rcode::NOERROR()) ||
360 (rcode == dns::Rcode::NXRRSET())) {
361 // We were able to remove the reverse mapping or they were
362 // not there (Rcode of NXRRSET means there are no matching
363 // RRsets). In either case, mark it as done.
366 } else {
367 // Per RFC4703 any other value means cease.
368 // If we get not authorized should try the next server in
369 // the list? @todo This needs some discussion perhaps.
371 .arg(getRequestId())
372 .arg(getCurrentServer()->toText())
373 .arg(getNcr()->getFqdn())
374 .arg(rcode.getCode());
376 }
377
378 break;
379 }
380
382 case DNSClient::OTHER:
383 // We couldn't send to the current server, log it and set up
384 // to select the next server for a retry.
385 // @note For now we treat OTHER as an IO error like TIMEOUT. It
386 // is not entirely clear if this is accurate.
388 .arg(getRequestId())
389 .arg(getNcr()->getFqdn())
390 .arg(getCurrentServer()->toText());
391
392 // If we are out of retries on this server, we go back and start
393 // all over on a new server.
395 break;
396
398 // A response was received but was corrupt. Retry it like an IO
399 // error.
401 .arg(getRequestId())
402 .arg(getCurrentServer()->toText())
403 .arg(getNcr()->getFqdn());
404
405 // If we are out of retries on this server, we go back and start
406 // all over on a new server.
408 break;
409
410 default:
411 // Any other value and we will fail this transaction, something
412 // bigger is wrong.
415 .arg(getRequestId())
416 .arg(getDnsUpdateStatus())
417 .arg(getNcr()->getFqdn())
418 .arg(getCurrentServer()->toText());
419
421 break;
422 } // end switch on dns_status
423
424 break;
425 } // end case IO_COMPLETE_EVT
426
427 default:
428 // Event is invalid.
430 "Wrong event for context: " << getContextStr());
431 }
432}
433
434
435void
437 switch(getNextEvent()) {
438 case UPDATE_OK_EVT:
440 .arg(getRequestId())
441 .arg(getNcr()->toText());
443 endModel();
444 break;
445 default:
446 // Event is invalid.
448 "Wrong event for context: " << getContextStr());
449 }
450}
451
452void
454 switch(getNextEvent()) {
460 .arg(getRequestId())
462 endModel();
463 break;
464 default:
465 // Event is invalid.
467 "Wrong event for context: " << getContextStr());
468 }
469}
470
471void
473 // Construct an empty request.
475
476 // There are no pre-requisites.
477
478 // Build the Update Section
479 // Construct dns::Name from NCR fqdn.
480 dns::Name fqdn(dns::Name(getNcr()->getFqdn()));
481
482 // Build the Update Section.
483
484 // Create the FQDN/IP 'delete' RR and add it to update section.
485 dns::RRsetPtr update(new dns::RRset(fqdn, dns::RRClass::ANY(),
487
488 request->addRRset(D2UpdateMessage::SECTION_UPDATE, update);
489
490 // Create the DHCID 'delete' RR and add it to the update section.
491 update.reset(new dns::RRset(fqdn, dns::RRClass::ANY(),
493 request->addRRset(D2UpdateMessage::SECTION_UPDATE, update);
494
495 // Set the transaction's update request to the new request.
496 setDnsUpdateRequest(request);
497}
498
499void
501 // Construct an empty request.
503
504 // Create the reverse IP address "FQDN".
505 std::string rev_addr = D2CfgMgr::reverseIpAddress(getNcr()->getIpAddress());
506 dns::Name rev_ip(rev_addr);
507
508 // There are no pre-requisites.
509
510 // Build the Update section.
511
512 // Create the FQDN/IP PTR 'delete' RR for this IP and add it to
513 // the update section.
514 dns::RRsetPtr update(new dns::RRset(rev_ip, dns::RRClass::ANY(),
516 request->addRRset(D2UpdateMessage::SECTION_UPDATE, update);
517
518 // Create the DHCID 'delete' RR and add it to the update section.
519 update.reset(new dns::RRset(rev_ip, dns::RRClass::ANY(),
521 request->addRRset(D2UpdateMessage::SECTION_UPDATE, update);
522
523 // Set the transaction's update request to the new request.
524 setDnsUpdateRequest(request);
525}
526
527} // namespace isc::d2
528} // namespace isc
static std::string reverseIpAddress(const std::string &address)
Generate a reverse order string for the given IP address.
Definition: d2_cfg_mgr.cc:170
@ TIMEOUT
No response, timeout.
Definition: dns_client.h:62
@ OTHER
Other, unclassified error.
Definition: dns_client.h:65
@ INVALID_RESPONSE
Response received but invalid.
Definition: dns_client.h:64
@ SUCCESS
Response received and is ok.
Definition: dns_client.h:61
Embodies the "life-cycle" required to carry out a DDNS update.
Definition: nc_trans.h:77
static const int SELECTING_FWD_SERVER_ST
State in which forward DNS server selection is done.
Definition: nc_trans.h:91
void retryTransition(const int fail_to_state)
Determines the state and next event based on update attempts.
Definition: nc_trans.cc:286
static const int PROCESS_TRANS_FAILED_ST
State which processes an unsuccessful transaction conclusion.
Definition: nc_trans.h:105
static const int READY_ST
State from which a transaction is started.
Definition: nc_trans.h:83
const D2UpdateMessagePtr & getDnsUpdateResponse() const
Fetches the most recent DNS update response packet.
Definition: nc_trans.cc:549
static const int PROCESS_TRANS_OK_ST
State which processes successful transaction conclusion.
Definition: nc_trans.h:102
static const int UPDATE_OK_EVT
Issued when the attempted update successfully completed.
Definition: nc_trans.h:135
virtual void verifyStates()
Validates the contents of the set of states.
Definition: nc_trans.cc:265
virtual D2UpdateMessagePtr prepNewRequest(DdnsDomainPtr domain)
Creates a new DNS update request based on the given domain.
Definition: nc_trans.cc:339
static const int UPDATE_FAILED_EVT
Issued when the attempted update fails to complete.
Definition: nc_trans.h:141
const D2UpdateMessagePtr & getDnsUpdateRequest() const
Fetches the current DNS update request packet.
Definition: nc_trans.cc:539
const dns::RRType & getAddressRRType() const
Returns the DHCP data type for the lease address.
Definition: nc_trans.cc:569
const dhcp_ddns::NameChangeRequestPtr & getNcr() const
Fetches the NameChangeRequest for this transaction.
Definition: nc_trans.cc:421
void initServerSelection(const DdnsDomainPtr &domain)
Initializes server selection from the given DDNS domain.
Definition: nc_trans.cc:451
static const int IO_COMPLETED_EVT
Issued when a DNS update packet exchange has completed.
Definition: nc_trans.h:130
static const int SELECT_SERVER_EVT
Issued when a server needs to be selected.
Definition: nc_trans.h:113
static const int SERVER_IO_ERROR_EVT
Issued when an update fails due to an IO error.
Definition: nc_trans.h:119
std::string getRequestId() const
Fetches the request id that identifies this transaction.
Definition: nc_trans.cc:431
virtual void defineStates()
Adds states defined by NameChangeTransaction to the state set.
Definition: nc_trans.cc:257
virtual void sendUpdate(const std::string &comment="")
Send the update request to the current server.
Definition: nc_trans.cc:192
void setForwardChangeCompleted(const bool value)
Sets the forward change completion flag to the given value.
Definition: nc_trans.cc:324
bool selectNextServer()
Selects the next server in the current server list.
Definition: nc_trans.cc:463
void setNcrStatus(const dhcp_ddns::NameChangeStatus &status)
Sets the status of the transaction's NameChangeRequest.
Definition: nc_trans.cc:534
DdnsDomainPtr & getForwardDomain()
Fetches the forward DdnsDomain.
Definition: nc_trans.cc:441
virtual void verifyEvents()
Validates the contents of the set of events.
Definition: nc_trans.cc:242
void clearDnsUpdateRequest()
Destroys the current update request packet and resets update attempts count.
Definition: nc_trans.cc:303
static const int SELECTING_REV_SERVER_ST
State in which reverse DNS server selection is done.
Definition: nc_trans.h:99
DNSClient::Status getDnsUpdateStatus() const
Fetches the most recent DNS update status.
Definition: nc_trans.cc:544
void setDnsUpdateRequest(D2UpdateMessagePtr &request)
Sets the update request packet to the given packet.
Definition: nc_trans.cc:298
static const int NO_MORE_SERVERS_EVT
Issued when there are no more servers from which to select.
Definition: nc_trans.h:125
virtual void defineEvents()
Adds events defined by NameChangeTransaction to the event set.
Definition: nc_trans.cc:227
void setReverseChangeCompleted(const bool value)
Sets the reverse change completion flag to the given value.
Definition: nc_trans.cc:329
const DnsServerInfoPtr & getCurrentServer() const
Fetches the currently selected server.
Definition: nc_trans.cc:529
static const int SERVER_SELECTED_EVT
Issued when a server has been selected.
Definition: nc_trans.h:116
DdnsDomainPtr & getReverseDomain()
Fetches the reverse DdnsDomain.
Definition: nc_trans.cc:446
std::string transactionOutcomeString() const
Returns a string version of transaction outcome.
Definition: nc_trans.cc:170
Thrown if the SimpleRemoveTransaction encounters a general error.
Definition: simple_remove.h:18
void removingRevPtrsHandler()
State handler for REMOVING_REV_PTRS_ST.
virtual void defineEvents()
Adds events defined by SimpleRemoveTransaction to the event set.
void processRemoveOkHandler()
State handler for PROCESS_TRANS_OK_ST.
virtual void verifyEvents()
Validates the contents of the set of events.
void selectingFwdServerHandler()
State handler for SELECTING_FWD_SERVER_ST.
void buildRemoveRevPtrsRequest()
Builds a DNS request to remove a reverse DNS entry for a FQDN.
virtual void verifyStates()
Validates the contents of the set of states.
void processRemoveFailedHandler()
State handler for PROCESS_TRANS_FAILED_ST.
virtual ~SimpleRemoveTransaction()
Destructor.
SimpleRemoveTransaction(asiolink::IOServicePtr &io_service, dhcp_ddns::NameChangeRequestPtr &ncr, DdnsDomainPtr &forward_domain, DdnsDomainPtr &reverse_domain, D2CfgMgrPtr &cfg_mgr)
Event sent when replace attempt to fails with address not in use.
void buildRemoveFwdRRsRequest()
Builds a DNS request to remove all forward DNS RRs for a FQDN.
static const int REMOVING_REV_PTRS_ST
State that attempts to remove reverse PTR records.
Definition: simple_remove.h:57
void readyHandler()
State handler for READY_ST.
virtual void defineStates()
Adds states defined by SimpleRemoveTransaction to the state set.
static const int REMOVING_FWD_RRS_ST
State that attempts to remove FQDN/IP and DHCID RRs for an FQDN.
Definition: simple_remove.h:54
void selectingRevServerHandler()
State handler for SELECTING_REV_SERVER_ST.
void removingFwdRRsHandler()
State handler for REMOVING_FWD_RRS_ST.
The Name class encapsulates DNS names.
Definition: name.h:223
static const RRClass & ANY()
Definition: rrclass.h:301
The RRTTL class encapsulates TTLs used in DNS resource records.
Definition: rrttl.h:55
static const RRType & PTR()
Definition: rrtype.h:443
static const RRType & DHCID()
Definition: rrtype.h:503
The RRset class is a concrete derived class of BasicRRset which contains a pointer to an additional R...
Definition: rrset.h:847
DNS Response Codes (RCODEs) class.
Definition: rcode.h:40
static const Rcode & NOERROR()
A constant object for the NOERROR Rcode (see Rcode::NOERROR_CODE).
Definition: rcode.h:220
static const Rcode & NXRRSET()
A constant object for the NXRRSET Rcode (see Rcode::NXRRSET_CODE).
Definition: rcode.h:268
uint16_t getCode() const
Returns the Rcode code value.
Definition: rcode.h:106
void endModel()
Conducts a normal transition to the end of the model.
Definition: state_model.cc:271
void defineState(unsigned int value, const std::string &label, StateHandler handler, const StatePausing &state_pausing=STATE_PAUSE_NEVER)
Adds an state value and associated label to the set of states.
Definition: state_model.cc:196
unsigned int getNextEvent() const
Fetches the model's next event.
Definition: state_model.cc:373
void transition(unsigned int state, unsigned int event)
Sets up the model to transition into given state with a given event.
Definition: state_model.cc:264
bool doOnEntry()
Checks if on entry flag is true.
Definition: state_model.cc:339
static const int START_EVT
Event issued to start the model execution.
Definition: state_model.h:295
const StatePtr getStateInternal(unsigned int value)
Fetches the state referred to by value.
Definition: state_model.cc:219
std::string getContextStr() const
Convenience method which returns a string rendition of the current state and next event.
Definition: state_model.cc:443
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
#define LOG_ERROR(LOGGER, MESSAGE)
Macro to conveniently test error output and log it.
Definition: macros.h:32
#define LOG_INFO(LOGGER, MESSAGE)
Macro to conveniently test info output and log it.
Definition: macros.h:20
boost::shared_ptr< D2UpdateMessage > D2UpdateMessagePtr
Pointer to the DNS Update Message.
boost::shared_ptr< DdnsDomain > DdnsDomainPtr
Defines a pointer for DdnsDomain instances.
Definition: d2_config.h:612
const isc::log::MessageID DHCP_DDNS_REVERSE_REMOVE_RESP_CORRUPT
Definition: d2_messages.h:71
boost::shared_ptr< D2CfgMgr > D2CfgMgrPtr
Defines a shared pointer to D2CfgMgr.
Definition: d2_cfg_mgr.h:334
const isc::log::MessageID DHCP_DDNS_FORWARD_REMOVE_RRS_RESP_CORRUPT
Definition: d2_messages.h:36
const isc::log::MessageID DHCP_DDNS_FORWARD_REMOVE_RRS_REJECTED
Definition: d2_messages.h:35
const isc::log::MessageID DHCP_DDNS_REMOVE_SUCCEEDED
Definition: d2_messages.h:65
isc::log::Logger d2_to_dns_logger("d2-to-dns")
Definition: d2_log.h:20
const isc::log::MessageID DHCP_DDNS_FORWARD_REMOVE_RRS_BUILD_FAILURE
Definition: d2_messages.h:33
const isc::log::MessageID DHCP_DDNS_FORWARD_REMOVE_RRS_BAD_DNSCLIENT_STATUS
Definition: d2_messages.h:32
const isc::log::MessageID DHCP_DDNS_REVERSE_REMOVE_IO_ERROR
Definition: d2_messages.h:69
const isc::log::MessageID DHCP_DDNS_REVERSE_REMOVE_BAD_DNSCLIENT_STATUS
Definition: d2_messages.h:67
const isc::log::MessageID DHCP_DDNS_REVERSE_REMOVE_BUILD_FAILURE
Definition: d2_messages.h:68
const isc::log::MessageID DHCP_DDNS_REMOVE_FAILED
Definition: d2_messages.h:64
const isc::log::MessageID DHCP_DDNS_FORWARD_REMOVE_RRS_IO_ERROR
Definition: d2_messages.h:34
const isc::log::MessageID DHCP_DDNS_REVERSE_REMOVE_REJECTED
Definition: d2_messages.h:70
boost::shared_ptr< NameChangeRequest > NameChangeRequestPtr
Defines a pointer to a NameChangeRequest.
Definition: ncr_msg.h:212
boost::shared_ptr< AbstractRRset > RRsetPtr
A pointer-like type pointing to an RRset object.
Definition: rrset.h:47
Defines the logger used by the top-level component of kea-lfc.