Kea 2.7.1
simple_remove.cc
Go to the documentation of this file.
1// Copyright (C) 2013-2024 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
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 } else {
164 // Server list is exhausted, so fail the transaction.
166 }
167}
168
169void
171 if (doOnEntry()) {
172 // Clear the update attempts count on initial transition.
174 }
175
176 switch(getNextEvent()) {
177 case UPDATE_OK_EVT:
179 try {
182 } catch (const std::exception& ex) {
183 // While unlikely, the build might fail if we have invalid
184 // data. Should that be the case, we need to fail the
185 // transaction.
188 .arg(getRequestId())
189 .arg(getNcr()->toText())
190 .arg(ex.what());
192 break;
193 }
194
195 // Call sendUpdate() to initiate the async send. Note it also sets
196 // next event to NOP_EVT.
197 sendUpdate("Forward RR Remove");
198 break;
199
200 case IO_COMPLETED_EVT: {
201 switch (getDnsUpdateStatus()) {
202 case DNSClient::SUCCESS: {
203 // We successfully received a response packet from the server.
204 // The RCODE will be based on a value-dependent RRset search,
205 // see RFC 2136 section 3.2.3/3.2.4.
206 const dns::Rcode& rcode = getDnsUpdateResponse()->getRcode();
207 if ((rcode == dns::Rcode::NOERROR()) ||
208 (rcode == dns::Rcode::NXRRSET())) {
209 // We were able to remove them or they were not there (
210 // Rcode of NXRRSET means there are no matching RRsets).
211 // In either case, we consider it success and mark it as done.
213
214 // If request calls for reverse update then do that next,
215 // otherwise we can process ok.
216 if (getReverseDomain()) {
218 } else {
220 }
221 } else {
222 // Any other value means cease.
223 // If we get not authorized should try the next server in
224 // the list? @todo This needs some discussion perhaps.
226 .arg(getRequestId())
227 .arg(getCurrentServer()->toText())
228 .arg(getNcr()->getFqdn())
229 .arg(rcode.getCode());
231 }
232
233 break;
234 }
235
237 // No response from the server, log it and set up
238 // to select the next server for a retry.
240 .arg(getRequestId())
241 .arg(getNcr()->getFqdn())
242 .arg(getCurrentServer()->toText());
243
245 break;
246
247 case DNSClient::OTHER:
248 // We couldn't send to the current server, log it and set up
249 // to select the next server for a retry.
251 .arg(getRequestId())
252 .arg(getNcr()->getFqdn())
253 .arg(getCurrentServer()->toText());
254
256 break;
257
259 // A response was received but was corrupt. Retry it like an IO
260 // error.
262 .arg(getRequestId())
263 .arg(getCurrentServer()->toText())
264 .arg(getNcr()->getFqdn());
265
267 break;
268
269 default:
270 // Any other value and we will fail this transaction, something
271 // bigger is wrong.
274 .arg(getRequestId())
275 .arg(getDnsUpdateStatus())
276 .arg(getNcr()->getFqdn())
277 .arg(getCurrentServer()->toText());
278
280 break;
281 } // end switch on dns_status
282
283 break;
284 } // end case IO_COMPLETE_EVT
285
286 default:
287 // Event is invalid.
289 "Wrong event for context: " << getContextStr());
290 }
291}
292
293void
295 switch(getNextEvent()) {
297 // First time through for this transaction, so initialize server
298 // selection.
300 break;
302 // We failed to communicate with current server. Attempt to select
303 // another one below.
304 break;
305 default:
306 // Event is invalid.
308 "Wrong event for context: " << getContextStr());
309 }
310
311 // Select the next server from the list of forward servers.
312 if (selectNextServer()) {
313 // We have a server to try.
315 } else {
316 // Server list is exhausted, so fail the transaction.
318 }
319}
320
321
322void
324 if (doOnEntry()) {
325 // Clear the update attempts count on initial transition.
327 }
328
329 switch(getNextEvent()) {
331 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 // Call sendUpdate() to initiate the async send. Note it also sets
347 // next event to NOP_EVT.
348 sendUpdate("Reverse Remove");
349 break;
350
351 case IO_COMPLETED_EVT: {
352 switch (getDnsUpdateStatus()) {
353 case DNSClient::SUCCESS: {
354 // We successfully received a response packet from the server.
355 // The RCODE will be based on a value-dependent RRset search,
356 // see RFC 2136 section 3.2.3/3.2.4.
357 const dns::Rcode& rcode = getDnsUpdateResponse()->getRcode();
358 if ((rcode == dns::Rcode::NOERROR()) ||
359 (rcode == dns::Rcode::NXRRSET())) {
360 // We were able to remove the reverse mapping or they were
361 // not there (Rcode of NXRRSET means there are no matching
362 // RRsets). In either case, mark it as done.
365 } else {
366 // Per RFC4703 any other value means cease.
367 // If we get not authorized should try the next server in
368 // the list? @todo This needs some discussion perhaps.
370 .arg(getRequestId())
371 .arg(getCurrentServer()->toText())
372 .arg(getNcr()->getFqdn())
373 .arg(rcode.getCode());
375 }
376
377 break;
378 }
379
381 // No response from the server, log it and set up
382 // to select the next server for a retry.
384 .arg(getRequestId())
385 .arg(getNcr()->getFqdn())
386 .arg(getCurrentServer()->toText());
387
388 // If we are out of retries on this server, we go back and start
389 // all over on a new server.
391 break;
392
393
394 case DNSClient::OTHER:
395 // We couldn't send to the current server, log it and set up
396 // to select the next server for a retry.
398 .arg(getRequestId())
399 .arg(getNcr()->getFqdn())
400 .arg(getCurrentServer()->toText());
401
402 // If we are out of retries on this server, we go back and start
403 // all over on a new server.
405 break;
406
408 // A response was received but was corrupt. Retry it like an IO
409 // error.
411 .arg(getRequestId())
412 .arg(getCurrentServer()->toText())
413 .arg(getNcr()->getFqdn());
414
415 // If we are out of retries on this server, we go back and start
416 // all over on a new server.
418 break;
419
420 default:
421 // Any other value and we will fail this transaction, something
422 // bigger is wrong.
425 .arg(getRequestId())
426 .arg(getDnsUpdateStatus())
427 .arg(getNcr()->getFqdn())
428 .arg(getCurrentServer()->toText());
429
431 break;
432 } // end switch on dns_status
433
434 break;
435 } // end case IO_COMPLETE_EVT
436
437 default:
438 // Event is invalid.
440 "Wrong event for context: " << getContextStr());
441 }
442}
443
444
445void
447 switch(getNextEvent()) {
448 case UPDATE_OK_EVT:
450 .arg(getRequestId())
451 .arg(getNcr()->toText());
453 endModel();
454 break;
455 default:
456 // Event is invalid.
458 "Wrong event for context: " << getContextStr());
459 }
460}
461
462void
464 switch(getNextEvent()) {
470 .arg(getRequestId())
472 endModel();
473 break;
474 default:
475 // Event is invalid.
477 "Wrong event for context: " << getContextStr());
478 }
479}
480
481void
483 // Construct an empty request.
485
486 // There are no pre-requisites.
487
488 // Build the Update Section
489 // Construct dns::Name from NCR fqdn.
490 dns::Name fqdn(dns::Name(getNcr()->getFqdn()));
491
492 // Build the Update Section.
493
494 // Create the FQDN/IP 'delete' RR and add it to update section.
495 dns::RRsetPtr update(new dns::RRset(fqdn, dns::RRClass::ANY(),
497
498 request->addRRset(D2UpdateMessage::SECTION_UPDATE, update);
499
500 // Create the DHCID 'delete' RR and add it to the update section.
501 update.reset(new dns::RRset(fqdn, dns::RRClass::ANY(),
503 request->addRRset(D2UpdateMessage::SECTION_UPDATE, update);
504
505 // Set the transaction's update request to the new request.
506 setDnsUpdateRequest(request);
507}
508
509void
511 // Construct an empty request.
513
514 // Create the reverse IP address "FQDN".
515 std::string rev_addr = D2CfgMgr::reverseIpAddress(getNcr()->getIpAddress());
516 dns::Name rev_ip(rev_addr);
517
518 // There are no pre-requisites.
519
520 // Build the Update section.
521
522 // Create the FQDN/IP PTR 'delete' RR for this IP and add it to
523 // the update section.
524 dns::RRsetPtr update(new dns::RRset(rev_ip, dns::RRClass::ANY(),
526 request->addRRset(D2UpdateMessage::SECTION_UPDATE, update);
527
528 // Create the DHCID 'delete' RR and add it to the update section.
529 update.reset(new dns::RRset(rev_ip, dns::RRClass::ANY(),
531 request->addRRset(D2UpdateMessage::SECTION_UPDATE, update);
532
533 // Set the transaction's update request to the new request.
534 setDnsUpdateRequest(request);
535}
536
537} // namespace isc::d2
538} // namespace isc
static std::string reverseIpAddress(const std::string &address)
Generate a reverse order string for the given IP address.
@ TIMEOUT
No response, timeout.
Definition dns_client.h:60
@ OTHER
Other, unclassified error.
Definition dns_client.h:63
@ INVALID_RESPONSE
Response received but invalid.
Definition dns_client.h:62
@ SUCCESS
Response received and is ok.
Definition dns_client.h:59
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:287
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:554
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:266
virtual D2UpdateMessagePtr prepNewRequest(DdnsDomainPtr domain)
Creates a new DNS update request based on the given domain.
Definition nc_trans.cc:344
static const int UPDATE_FAILED_EVT
Issued when the attempted update fails to complete.
Definition nc_trans.h:141
const dns::RRType & getAddressRRType() const
Returns the DHCP data type for the lease address.
Definition nc_trans.cc:574
const dhcp_ddns::NameChangeRequestPtr & getNcr() const
Fetches the NameChangeRequest for this transaction.
Definition nc_trans.cc:426
void initServerSelection(const DdnsDomainPtr &domain)
Initializes server selection from the given DDNS domain.
Definition nc_trans.cc:456
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:436
virtual void defineStates()
Adds states defined by NameChangeTransaction to the state set.
Definition nc_trans.cc:258
virtual void sendUpdate(const std::string &comment="")
Send the update request to the current server.
Definition nc_trans.cc:193
void setForwardChangeCompleted(const bool value)
Sets the forward change completion flag to the given value.
Definition nc_trans.cc:329
bool selectNextServer()
Selects the next server in the current server list.
Definition nc_trans.cc:468
void setNcrStatus(const dhcp_ddns::NameChangeStatus &status)
Sets the status of the transaction's NameChangeRequest.
Definition nc_trans.cc:539
DdnsDomainPtr & getForwardDomain()
Fetches the forward DdnsDomain.
Definition nc_trans.cc:446
virtual void verifyEvents()
Validates the contents of the set of events.
Definition nc_trans.cc:243
void clearDnsUpdateRequest()
Destroys the current update request packet.
Definition nc_trans.cc:304
void clearUpdateAttempts()
Resets the update attempts count.
Definition nc_trans.cc:309
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:549
void setDnsUpdateRequest(D2UpdateMessagePtr &request)
Sets the update request packet to the given packet.
Definition nc_trans.cc:299
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:228
void setReverseChangeCompleted(const bool value)
Sets the reverse change completion flag to the given value.
Definition nc_trans.cc:334
const DnsServerInfoPtr & getCurrentServer() const
Fetches the currently selected server.
Definition nc_trans.cc:534
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:451
std::string transactionOutcomeString() const
Returns a string version of transaction outcome.
Definition nc_trans.cc:171
Thrown if the SimpleRemoveTransaction encounters a general error.
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.
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.
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:219
static const RRClass & ANY()
Definition rrclass.h:298
The RRTTL class encapsulates TTLs used in DNS resource records.
Definition rrttl.h:51
static const RRType & PTR()
Definition rrtype.h:303
static const RRType & DHCID()
Definition rrtype.h:327
The RRset class is a concrete derived class of BasicRRset which contains a pointer to an additional R...
Definition rrset.h:844
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:228
static const Rcode & NXRRSET()
A constant object for the NXRRSET Rcode (see Rcode::NXRRSET_CODE).
Definition rcode.h:276
void endModel()
Conducts a normal transition to the end of the model.
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.
unsigned int getNextEvent() const
Fetches the model's next event.
void transition(unsigned int state, unsigned int event)
Sets up the model to transition into given state with a given event.
bool doOnEntry()
Checks if on entry flag is true.
static const int START_EVT
Event issued to start the model execution.
const StatePtr getStateInternal(unsigned int value)
Fetches the state referred to by value.
std::string getContextStr() const
Convenience method which returns a string rendition of the current state and next event.
#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:622
const isc::log::MessageID DHCP_DDNS_FORWARD_REMOVE_RRS_TIMEOUT
Definition d2_messages.h:38
const isc::log::MessageID DHCP_DDNS_REVERSE_REMOVE_RESP_CORRUPT
Definition d2_messages.h:74
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:37
const isc::log::MessageID DHCP_DDNS_FORWARD_REMOVE_RRS_REJECTED
Definition d2_messages.h:36
const isc::log::MessageID DHCP_DDNS_REMOVE_SUCCEEDED
Definition d2_messages.h:68
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:34
const isc::log::MessageID DHCP_DDNS_REVERSE_REMOVE_TIMEOUT
Definition d2_messages.h:75
const isc::log::MessageID DHCP_DDNS_FORWARD_REMOVE_RRS_BAD_DNSCLIENT_STATUS
Definition d2_messages.h:33
const isc::log::MessageID DHCP_DDNS_REVERSE_REMOVE_IO_ERROR
Definition d2_messages.h:72
const isc::log::MessageID DHCP_DDNS_REVERSE_REMOVE_BAD_DNSCLIENT_STATUS
Definition d2_messages.h:70
const isc::log::MessageID DHCP_DDNS_REVERSE_REMOVE_BUILD_FAILURE
Definition d2_messages.h:71
const isc::log::MessageID DHCP_DDNS_REMOVE_FAILED
Definition d2_messages.h:67
const isc::log::MessageID DHCP_DDNS_FORWARD_REMOVE_RRS_IO_ERROR
Definition d2_messages.h:35
const isc::log::MessageID DHCP_DDNS_REVERSE_REMOVE_REJECTED
Definition d2_messages.h:73
boost::shared_ptr< NameChangeRequest > NameChangeRequestPtr
Defines a pointer to a NameChangeRequest.
Definition ncr_msg.h:241
boost::shared_ptr< AbstractRRset > RRsetPtr
A pointer-like type pointing to an RRset object.
Definition rrset.h:50
Defines the logger used by the top-level component of kea-lfc.