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/nc_remove.h>
10 #include <d2srv/d2_cfg_mgr.h>
11 #include <d2srv/d2_log.h>
12
13 #include <functional>
14
15 namespace isc {
16 namespace d2 {
17
18
19 // NameRemoveTransaction states
20 const int NameRemoveTransaction::REMOVING_FWD_ADDRS_ST;
21 const int NameRemoveTransaction::REMOVING_FWD_RRS_ST;
22 const int NameRemoveTransaction::REMOVING_REV_PTRS_ST;
23
24 // NameRemoveTransaction events
25 // Currently NameRemoveTransaction does not define any events.
26
27 NameRemoveTransaction::
NameRemoveTransaction(asiolink::IOServicePtr & io_service,dhcp_ddns::NameChangeRequestPtr & ncr,DdnsDomainPtr & forward_domain,DdnsDomainPtr & reverse_domain,D2CfgMgrPtr & cfg_mgr)28 NameRemoveTransaction(asiolink::IOServicePtr& io_service,
29 dhcp_ddns::NameChangeRequestPtr& ncr,
30 DdnsDomainPtr& forward_domain,
31 DdnsDomainPtr& reverse_domain,
32 D2CfgMgrPtr& cfg_mgr)
33 : NameChangeTransaction(io_service, ncr, forward_domain, reverse_domain,
34 cfg_mgr) {
35 if (ncr->getChangeType() != isc::dhcp_ddns::CHG_REMOVE) {
36 isc_throw (NameRemoveTransactionError,
37 "NameRemoveTransaction, request type must be CHG_REMOVE");
38 }
39 }
40
~NameRemoveTransaction()41 NameRemoveTransaction::~NameRemoveTransaction(){
42 }
43
44 void
defineEvents()45 NameRemoveTransaction::defineEvents() {
46 // Call superclass impl first.
47 NameChangeTransaction::defineEvents();
48
49 // Define NameRemoveTransaction events.
50 // Currently NameRemoveTransaction does not define any events.
51 // defineEvent(TBD_EVENT, "TBD_EVT");
52 }
53
54 void
verifyEvents()55 NameRemoveTransaction::verifyEvents() {
56 // Call superclass implementation first to verify its events. These are
57 // events common to all transactions, and they must be defined.
58 // SELECT_SERVER_EVT
59 // SERVER_SELECTED_EVT
60 // SERVER_IO_ERROR_EVT
61 // NO_MORE_SERVERS_EVT
62 // IO_COMPLETED_EVT
63 // UPDATE_OK_EVT
64 // UPDATE_FAILED_EVT
65 NameChangeTransaction::verifyEvents();
66
67 // Verify NameRemoveTransaction events by attempting to fetch them.
68 // Currently NameRemoveTransaction does not define any events.
69 // getEvent(TBD_EVENT);
70 }
71
72 void
defineStates()73 NameRemoveTransaction::defineStates() {
74 // Call superclass impl first.
75 NameChangeTransaction::defineStates();
76
77 // Define NameRemoveTransaction states.
78 defineState(READY_ST, "READY_ST",
79 std::bind(&NameRemoveTransaction::readyHandler, this));
80
81 defineState(SELECTING_FWD_SERVER_ST, "SELECTING_FWD_SERVER_ST",
82 std::bind(&NameRemoveTransaction::selectingFwdServerHandler,
83 this));
84
85 defineState(SELECTING_REV_SERVER_ST, "SELECTING_REV_SERVER_ST",
86 std::bind(&NameRemoveTransaction::selectingRevServerHandler,
87 this));
88
89 defineState(REMOVING_FWD_ADDRS_ST, "REMOVING_FWD_ADDRS_ST",
90 std::bind(&NameRemoveTransaction::removingFwdAddrsHandler,
91 this));
92
93 defineState(REMOVING_FWD_RRS_ST, "REMOVING_FWD_RRS_ST",
94 std::bind(&NameRemoveTransaction::removingFwdRRsHandler,
95 this));
96
97 defineState(REMOVING_REV_PTRS_ST, "REMOVING_REV_PTRS_ST",
98 std::bind(&NameRemoveTransaction::removingRevPtrsHandler,
99 this));
100
101 defineState(PROCESS_TRANS_OK_ST, "PROCESS_TRANS_OK_ST",
102 std::bind(&NameRemoveTransaction::processRemoveOkHandler,
103 this));
104
105 defineState(PROCESS_TRANS_FAILED_ST, "PROCESS_TRANS_FAILED_ST",
106 std::bind(&NameRemoveTransaction::processRemoveFailedHandler,
107 this));
108 }
109
110 void
verifyStates()111 NameRemoveTransaction::verifyStates() {
112 // Call superclass implementation first to verify its states. These are
113 // states common to all transactions, and they must be defined.
114 // READY_ST
115 // SELECTING_FWD_SERVER_ST
116 // SELECTING_REV_SERVER_ST
117 // PROCESS_TRANS_OK_ST
118 // PROCESS_TRANS_FAILED_ST
119 NameChangeTransaction::verifyStates();
120
121 // Verify NameRemoveTransaction states by attempting to fetch them.
122 getStateInternal(REMOVING_FWD_ADDRS_ST);
123 getStateInternal(REMOVING_FWD_RRS_ST);
124 getStateInternal(REMOVING_REV_PTRS_ST);
125 }
126
127 void
readyHandler()128 NameRemoveTransaction::readyHandler() {
129 switch(getNextEvent()) {
130 case START_EVT:
131 if (getForwardDomain()) {
132 // Request includes a forward change, do that first.
133 transition(SELECTING_FWD_SERVER_ST, SELECT_SERVER_EVT);
134 } else {
135 // Reverse change only, transition accordingly.
136 transition(SELECTING_REV_SERVER_ST, SELECT_SERVER_EVT);
137 }
138
139 break;
140 default:
141 // Event is invalid.
142 isc_throw(NameRemoveTransactionError,
143 "Wrong event for context: " << getContextStr());
144 }
145 }
146
147 void
selectingFwdServerHandler()148 NameRemoveTransaction::selectingFwdServerHandler() {
149 switch(getNextEvent()) {
150 case SELECT_SERVER_EVT:
151 // First time through for this transaction, so initialize server
152 // selection.
153 initServerSelection(getForwardDomain());
154 break;
155 case SERVER_IO_ERROR_EVT:
156 // We failed to communicate with current server. Attempt to select
157 // another one below.
158 break;
159 default:
160 // Event is invalid.
161 isc_throw(NameRemoveTransactionError,
162 "Wrong event for context: " << getContextStr());
163 }
164
165 // Select the next server from the list of forward servers.
166 if (selectNextServer()) {
167 // We have a server to try.
168 transition(REMOVING_FWD_ADDRS_ST, SERVER_SELECTED_EVT);
169 }
170 else {
171 // Server list is exhausted, so fail the transaction.
172 transition(PROCESS_TRANS_FAILED_ST, NO_MORE_SERVERS_EVT);
173 }
174 }
175
176 void
removingFwdAddrsHandler()177 NameRemoveTransaction::removingFwdAddrsHandler() {
178 if (doOnEntry()) {
179 // Clear the update attempts count on initial transition.
180 clearUpdateAttempts();
181 }
182
183 switch(getNextEvent()) {
184 case SERVER_SELECTED_EVT:
185 try {
186 clearDnsUpdateRequest();
187 buildRemoveFwdAddressRequest();
188 } catch (const std::exception& ex) {
189 // While unlikely, the build might fail if we have invalid
190 // data. Should that be the case, we need to fail the
191 // transaction.
192 LOG_ERROR(d2_to_dns_logger,
193 DHCP_DDNS_FORWARD_REMOVE_ADDRS_BUILD_FAILURE)
194 .arg(getRequestId())
195 .arg(getNcr()->toText())
196 .arg(ex.what());
197 transition(PROCESS_TRANS_FAILED_ST, UPDATE_FAILED_EVT);
198 break;
199 }
200
201 // Call sendUpdate() to initiate the async send. Note it also sets
202 // next event to NOP_EVT.
203 sendUpdate("Forward A/AAAA Remove");
204 break;
205
206 case IO_COMPLETED_EVT: {
207 switch (getDnsUpdateStatus()) {
208 case DNSClient::SUCCESS: {
209 // We successfully received a response packet from the server.
210 // The RCODE will be based on a value-dependent RRset search,
211 // see RFC 2136 section 3.2.3/3.2.4.
212 const dns::Rcode& rcode = getDnsUpdateResponse()->getRcode();
213 if ((rcode == dns::Rcode::NOERROR()) ||
214 (rcode == dns::Rcode::NXRRSET())) {
215 // We were able to remove it or it wasn't there, now we
216 // need to remove any other RRs for this FQDN.
217 transition(REMOVING_FWD_RRS_ST, UPDATE_OK_EVT);
218 } else {
219 // Per RFC4703 any other value means cease.
220 // If we get not authorized should we try the next server in
221 // the list? @todo This needs some discussion perhaps.
222 LOG_ERROR(d2_to_dns_logger, DHCP_DDNS_FORWARD_REMOVE_ADDRS_REJECTED)
223 .arg(getRequestId())
224 .arg(getCurrentServer()->toText())
225 .arg(getNcr()->getFqdn())
226 .arg(rcode.getCode());
227 transition(PROCESS_TRANS_FAILED_ST, UPDATE_FAILED_EVT);
228 }
229
230 break;
231 }
232
233 case DNSClient::TIMEOUT:
234 case DNSClient::OTHER:
235 // We couldn't send to the current server, log it and set up
236 // to select the next server for a retry.
237 // @note For now we treat OTHER as an IO error like TIMEOUT. It
238 // is not entirely clear if this is accurate.
239 LOG_ERROR(d2_to_dns_logger, DHCP_DDNS_FORWARD_REMOVE_ADDRS_IO_ERROR)
240 .arg(getRequestId())
241 .arg(getNcr()->getFqdn())
242 .arg(getCurrentServer()->toText());
243
244 retryTransition(SELECTING_FWD_SERVER_ST);
245 break;
246
247 case DNSClient::INVALID_RESPONSE:
248 // A response was received but was corrupt. Retry it like an IO
249 // error.
250 LOG_ERROR(d2_to_dns_logger, DHCP_DDNS_FORWARD_REMOVE_ADDRS_RESP_CORRUPT)
251 .arg(getRequestId())
252 .arg(getCurrentServer()->toText())
253 .arg(getNcr()->getFqdn());
254
255 retryTransition(SELECTING_FWD_SERVER_ST);
256 break;
257
258 default:
259 // Any other value and we will fail this transaction, something
260 // bigger is wrong.
261 LOG_ERROR(d2_to_dns_logger,
262 DHCP_DDNS_FORWARD_REMOVE_ADDRS_BAD_DNSCLIENT_STATUS)
263 .arg(getRequestId())
264 .arg(getDnsUpdateStatus())
265 .arg(getNcr()->getFqdn())
266 .arg(getCurrentServer()->toText());
267
268 transition(PROCESS_TRANS_FAILED_ST, UPDATE_FAILED_EVT);
269 break;
270 } // end switch on dns_status
271
272 break;
273 } // end case IO_COMPLETE_EVT
274
275 default:
276 // Event is invalid.
277 isc_throw(NameRemoveTransactionError,
278 "Wrong event for context: " << getContextStr());
279 }
280 }
281
282
283 void
removingFwdRRsHandler()284 NameRemoveTransaction::removingFwdRRsHandler() {
285 if (doOnEntry()) {
286 // Clear the update attempts count on initial transition.
287 clearUpdateAttempts();
288 }
289
290 switch(getNextEvent()) {
291 case UPDATE_OK_EVT:
292 case SERVER_SELECTED_EVT:
293 try {
294 clearDnsUpdateRequest();
295 buildRemoveFwdRRsRequest();
296 } catch (const std::exception& ex) {
297 // While unlikely, the build might fail if we have invalid
298 // data. Should that be the case, we need to fail the
299 // transaction.
300 LOG_ERROR(d2_to_dns_logger,
301 DHCP_DDNS_FORWARD_REMOVE_RRS_BUILD_FAILURE)
302 .arg(getRequestId())
303 .arg(getNcr()->toText())
304 .arg(ex.what());
305 transition(PROCESS_TRANS_FAILED_ST, UPDATE_FAILED_EVT);
306 break;
307 }
308
309 // Call sendUpdate() to initiate the async send. Note it also sets
310 // next event to NOP_EVT.
311 sendUpdate("Forward RR Remove");
312 break;
313
314 case IO_COMPLETED_EVT: {
315 switch (getDnsUpdateStatus()) {
316 case DNSClient::SUCCESS: {
317 // We successfully received a response packet from the server.
318 // The RCODE will be based on a value-dependent RRset search,
319 // see RFC 2136 section 3.2.3/3.2.4.
320 const dns::Rcode& rcode = getDnsUpdateResponse()->getRcode();
321 if ((rcode == dns::Rcode::NOERROR()) ||
322 (rcode == dns::Rcode::NXRRSET())) {
323 // We were able to remove them or they were not there (
324 // Rcode of NXRRSET means there are no matching RRsets).
325 // In either case, we consider it success and mark it as done.
326 setForwardChangeCompleted(true);
327
328 // If request calls for reverse update then do that next,
329 // otherwise we can process ok.
330 if (getReverseDomain()) {
331 transition(SELECTING_REV_SERVER_ST, SELECT_SERVER_EVT);
332 } else {
333 transition(PROCESS_TRANS_OK_ST, UPDATE_OK_EVT);
334 }
335 } else {
336 // Per RFC4703 any other value means cease.
337 // If we get not authorized should try the next server in
338 // the list? @todo This needs some discussion perhaps.
339 LOG_ERROR(d2_to_dns_logger, DHCP_DDNS_FORWARD_REMOVE_RRS_REJECTED)
340 .arg(getRequestId())
341 .arg(getCurrentServer()->toText())
342 .arg(getNcr()->getFqdn())
343 .arg(rcode.getCode());
344 transition(PROCESS_TRANS_FAILED_ST, UPDATE_FAILED_EVT);
345 }
346
347 break;
348 }
349
350 case DNSClient::TIMEOUT:
351 case DNSClient::OTHER:
352 // We couldn't send to the current server, log it and set up
353 // to select the next server for a retry.
354 // @note For now we treat OTHER as an IO error like TIMEOUT. It
355 // is not entirely clear if this is accurate.
356 LOG_ERROR(d2_to_dns_logger, DHCP_DDNS_FORWARD_REMOVE_RRS_IO_ERROR)
357 .arg(getRequestId())
358 .arg(getNcr()->getFqdn())
359 .arg(getCurrentServer()->toText());
360
361 // @note If we exhaust the IO retries for the current server
362 // due to IO failures, we will abort the remaining updates.
363 // The rational is that we are only in this state, if the remove
364 // of the forward address RR succeeded (removingFwdAddrsHandler)
365 // on the current server. Therefore we should not attempt another
366 // removal on a different server. This is perhaps a point
367 // for discussion.
368 // @todo Should we go ahead with the reverse remove?
369 retryTransition(PROCESS_TRANS_FAILED_ST);
370 break;
371
372 case DNSClient::INVALID_RESPONSE:
373 // A response was received but was corrupt. Retry it like an IO
374 // error.
375 LOG_ERROR(d2_to_dns_logger, DHCP_DDNS_FORWARD_REMOVE_RRS_RESP_CORRUPT)
376 .arg(getRequestId())
377 .arg(getCurrentServer()->toText())
378 .arg(getNcr()->getFqdn());
379
380 // If we are out of retries on this server abandon the transaction.
381 // (Same logic as the case for TIMEOUT above).
382 retryTransition(PROCESS_TRANS_FAILED_ST);
383 break;
384
385 default:
386 // Any other value and we will fail this transaction, something
387 // bigger is wrong.
388 LOG_ERROR(d2_to_dns_logger,
389 DHCP_DDNS_FORWARD_REMOVE_RRS_BAD_DNSCLIENT_STATUS)
390 .arg(getRequestId())
391 .arg(getDnsUpdateStatus())
392 .arg(getNcr()->getFqdn())
393 .arg(getCurrentServer()->toText());
394
395 transition(PROCESS_TRANS_FAILED_ST, UPDATE_FAILED_EVT);
396 break;
397 } // end switch on dns_status
398
399 break;
400 } // end case IO_COMPLETE_EVT
401
402 default:
403 // Event is invalid.
404 isc_throw(NameRemoveTransactionError,
405 "Wrong event for context: " << getContextStr());
406 }
407 }
408
409
410 void
selectingRevServerHandler()411 NameRemoveTransaction::selectingRevServerHandler() {
412 switch(getNextEvent()) {
413 case SELECT_SERVER_EVT:
414 // First time through for this transaction, so initialize server
415 // selection.
416 initServerSelection(getReverseDomain());
417 break;
418 case SERVER_IO_ERROR_EVT:
419 // We failed to communicate with current server. Attempt to select
420 // another one below.
421 break;
422 default:
423 // Event is invalid.
424 isc_throw(NameRemoveTransactionError,
425 "Wrong event for context: " << getContextStr());
426 }
427
428 // Select the next server from the list of forward servers.
429 if (selectNextServer()) {
430 // We have a server to try.
431 transition(REMOVING_REV_PTRS_ST, SERVER_SELECTED_EVT);
432 }
433 else {
434 // Server list is exhausted, so fail the transaction.
435 transition(PROCESS_TRANS_FAILED_ST, NO_MORE_SERVERS_EVT);
436 }
437 }
438
439
440 void
removingRevPtrsHandler()441 NameRemoveTransaction::removingRevPtrsHandler() {
442 if (doOnEntry()) {
443 // Clear the update attempts count on initial transition.
444 clearUpdateAttempts();
445 }
446
447 switch(getNextEvent()) {
448 case SERVER_SELECTED_EVT:
449 try {
450 clearDnsUpdateRequest();
451 buildRemoveRevPtrsRequest();
452 } catch (const std::exception& ex) {
453 // While unlikely, the build might fail if we have invalid
454 // data. Should that be the case, we need to fail the
455 // transaction.
456 LOG_ERROR(d2_to_dns_logger, DHCP_DDNS_REVERSE_REMOVE_BUILD_FAILURE)
457 .arg(getRequestId())
458 .arg(getNcr()->toText())
459 .arg(ex.what());
460 transition(PROCESS_TRANS_FAILED_ST, UPDATE_FAILED_EVT);
461 break;
462 }
463
464 // Call sendUpdate() to initiate the async send. Note it also sets
465 // next event to NOP_EVT.
466 sendUpdate("Reverse Remove");
467 break;
468
469 case IO_COMPLETED_EVT: {
470 switch (getDnsUpdateStatus()) {
471 case DNSClient::SUCCESS: {
472 // We successfully received a response packet from the server.
473 // The RCODE will be based on a value-dependent RRset search,
474 // see RFC 2136 section 3.2.3/3.2.4.
475 const dns::Rcode& rcode = getDnsUpdateResponse()->getRcode();
476 if ((rcode == dns::Rcode::NOERROR()) ||
477 (rcode == dns::Rcode::NXRRSET())) {
478 // We were able to remove the reverse mapping or they were
479 // not there (Rcode of NXRRSET means there are no matching
480 // RRsets). In either case, mark it as done.
481 setReverseChangeCompleted(true);
482 transition(PROCESS_TRANS_OK_ST, UPDATE_OK_EVT);
483 } else {
484 // Per RFC4703 any other value means cease.
485 // If we get not authorized should try the next server in
486 // the list? @todo This needs some discussion perhaps.
487 LOG_ERROR(d2_to_dns_logger, DHCP_DDNS_REVERSE_REMOVE_REJECTED)
488 .arg(getRequestId())
489 .arg(getCurrentServer()->toText())
490 .arg(getNcr()->getFqdn())
491 .arg(rcode.getCode());
492 transition(PROCESS_TRANS_FAILED_ST, UPDATE_FAILED_EVT);
493 }
494
495 break;
496 }
497
498 case DNSClient::TIMEOUT:
499 case DNSClient::OTHER:
500 // We couldn't send to the current server, log it and set up
501 // to select the next server for a retry.
502 // @note For now we treat OTHER as an IO error like TIMEOUT. It
503 // is not entirely clear if this is accurate.
504 LOG_ERROR(d2_to_dns_logger, DHCP_DDNS_REVERSE_REMOVE_IO_ERROR)
505 .arg(getRequestId())
506 .arg(getNcr()->getFqdn())
507 .arg(getCurrentServer()->toText());
508
509 // If we are out of retries on this server, we go back and start
510 // all over on a new server.
511 retryTransition(SELECTING_REV_SERVER_ST);
512 break;
513
514 case DNSClient::INVALID_RESPONSE:
515 // A response was received but was corrupt. Retry it like an IO
516 // error.
517 LOG_ERROR(d2_to_dns_logger, DHCP_DDNS_REVERSE_REMOVE_RESP_CORRUPT)
518 .arg(getRequestId())
519 .arg(getCurrentServer()->toText())
520 .arg(getNcr()->getFqdn());
521
522 // If we are out of retries on this server, we go back and start
523 // all over on a new server.
524 retryTransition(SELECTING_REV_SERVER_ST);
525 break;
526
527 default:
528 // Any other value and we will fail this transaction, something
529 // bigger is wrong.
530 LOG_ERROR(d2_to_dns_logger,
531 DHCP_DDNS_REVERSE_REMOVE_BAD_DNSCLIENT_STATUS)
532 .arg(getRequestId())
533 .arg(getDnsUpdateStatus())
534 .arg(getNcr()->getFqdn())
535 .arg(getCurrentServer()->toText());
536
537 transition(PROCESS_TRANS_FAILED_ST, UPDATE_FAILED_EVT);
538 break;
539 } // end switch on dns_status
540
541 break;
542 } // end case IO_COMPLETE_EVT
543
544 default:
545 // Event is invalid.
546 isc_throw(NameRemoveTransactionError,
547 "Wrong event for context: " << getContextStr());
548 }
549 }
550
551
552 void
processRemoveOkHandler()553 NameRemoveTransaction::processRemoveOkHandler() {
554 switch(getNextEvent()) {
555 case UPDATE_OK_EVT:
556 LOG_INFO(d2_to_dns_logger, DHCP_DDNS_REMOVE_SUCCEEDED)
557 .arg(getRequestId())
558 .arg(getNcr()->toText());
559 setNcrStatus(dhcp_ddns::ST_COMPLETED);
560 endModel();
561 break;
562 default:
563 // Event is invalid.
564 isc_throw(NameRemoveTransactionError,
565 "Wrong event for context: " << getContextStr());
566 }
567 }
568
569 void
processRemoveFailedHandler()570 NameRemoveTransaction::processRemoveFailedHandler() {
571 switch(getNextEvent()) {
572 case UPDATE_FAILED_EVT:
573 case NO_MORE_SERVERS_EVT:
574 case SERVER_IO_ERROR_EVT:
575 setNcrStatus(dhcp_ddns::ST_FAILED);
576 LOG_ERROR(d2_to_dns_logger, DHCP_DDNS_REMOVE_FAILED)
577 .arg(getRequestId())
578 .arg(transactionOutcomeString());
579 endModel();
580 break;
581 default:
582 // Event is invalid.
583 isc_throw(NameRemoveTransactionError,
584 "Wrong event for context: " << getContextStr());
585 }
586 }
587
588 void
buildRemoveFwdAddressRequest()589 NameRemoveTransaction::buildRemoveFwdAddressRequest() {
590 // Construct an empty request.
591 D2UpdateMessagePtr request = prepNewRequest(getForwardDomain());
592
593 // Content on this request is based on RFC 4703, section 5.5, paragraph 4.
594 // Construct dns::Name from NCR fqdn.
595 dns::Name fqdn(dns::Name(getNcr()->getFqdn()));
596 // First build the Prerequisite Section
597
598 // Create an DHCID matches prerequisite RR and add it to the
599 // pre-requisite section
600 // Based on RFC 2136, section 2.4.2.
601 dns::RRsetPtr prereq(new dns::RRset(fqdn, dns::RRClass::IN(),
602 dns::RRType::DHCID(), dns::RRTTL(0)));
603 addDhcidRdata(prereq);
604 request->addRRset(D2UpdateMessage::SECTION_PREREQUISITE, prereq);
605
606 // Next build the Update Section
607
608 // Create the FQDN/IP 'delete' RR and add it to the update section.
609 // Add the RR to update section.
610 // Based on 2136 section 2.5.4
611 dns::RRsetPtr update(new dns::RRset(fqdn, dns::RRClass::NONE(),
612 getAddressRRType(), dns::RRTTL(0)));
613 addLeaseAddressRdata(update);
614 request->addRRset(D2UpdateMessage::SECTION_UPDATE, update);
615
616 // Set the transaction's update request to the new request.
617 setDnsUpdateRequest(request);
618 }
619
620 void
buildRemoveFwdRRsRequest()621 NameRemoveTransaction::buildRemoveFwdRRsRequest() {
622 // Construct an empty request.
623 D2UpdateMessagePtr request = prepNewRequest(getForwardDomain());
624
625 // Construct dns::Name from NCR fqdn.
626 dns::Name fqdn(dns::Name(getNcr()->getFqdn()));
627
628 // Content on this request is based on RFC 4703, section 5.5, paragraph 5.
629 // First build the Prerequisite Section.
630
631 // Now create an DHCID matches prerequisite RR.
632 // Set the RR's RData to DHCID.
633 // Add it to the pre-requisite section.
634 // Based on RFC 2136, section 2.4.2.
635 dns::RRsetPtr prereq(new dns::RRset(fqdn, dns::RRClass::IN(),
636 dns::RRType::DHCID(), dns::RRTTL(0)));
637 addDhcidRdata(prereq);
638 request->addRRset(D2UpdateMessage::SECTION_PREREQUISITE, prereq);
639
640 // Create an assertion that there are no A RRs for the FQDN.
641 // Add it to the pre-reqs.
642 // Based on RFC 2136, section 2.4.3.
643 prereq.reset(new dns::RRset(fqdn, dns::RRClass::NONE(),
644 dns::RRType::A(), dns::RRTTL(0)));
645 request->addRRset(D2UpdateMessage::SECTION_PREREQUISITE, prereq);
646
647 // Create an assertion that there are no A RRs for the FQDN.
648 // Add it to the pre-reqs.
649 // Based on RFC 2136, section 2.4.3.
650 prereq.reset(new dns::RRset(fqdn, dns::RRClass::NONE(),
651 dns::RRType::AAAA(), dns::RRTTL(0)));
652 request->addRRset(D2UpdateMessage::SECTION_PREREQUISITE, prereq);
653
654 // Next build the Update Section.
655
656 // Create the 'delete' of all RRs for FQDN.
657 // Set the message RData to lease address.
658 // Add the RR to update section.
659 // Based on RFC 2136, section 2.5.3.
660 dns::RRsetPtr update(new dns::RRset(fqdn, dns::RRClass::ANY(),
661 dns::RRType::ANY(), dns::RRTTL(0)));
662 request->addRRset(D2UpdateMessage::SECTION_UPDATE, update);
663
664 // Set the transaction's update request to the new request.
665 setDnsUpdateRequest(request);
666 }
667
668 void
buildRemoveRevPtrsRequest()669 NameRemoveTransaction::buildRemoveRevPtrsRequest() {
670 // Construct an empty request.
671 D2UpdateMessagePtr request = prepNewRequest(getReverseDomain());
672
673 // Create the reverse IP address "FQDN".
674 std::string rev_addr = D2CfgMgr::reverseIpAddress(getNcr()->getIpAddress());
675 dns::Name rev_ip(rev_addr);
676
677 // Content on this request is based on RFC 4703, section 5.5, paragraph 2.
678 // First build the Prerequisite Section.
679 // (Note that per RFC 4703, section 5.4, there is no need to validate
680 // DHCID RR for PTR entries.)
681
682 // Create an assertion that the PTRDNAME in the PTR record matches the
683 // client's FQDN for the address that was released.
684 // Based on RFC 2136, section 3.2.3
685 dns::RRsetPtr prereq(new dns::RRset(rev_ip, dns::RRClass::IN(),
686 dns::RRType::PTR(), dns::RRTTL(0)));
687 addPtrRdata(prereq);
688 request->addRRset(D2UpdateMessage::SECTION_PREREQUISITE, prereq);
689
690 // Now, build the Update section.
691
692 // Create a delete of any RRs for the FQDN and add it to update section.
693 // Based on RFC 2136, section 3.4.2.3
694 dns::RRsetPtr update(new dns::RRset(rev_ip, dns::RRClass::ANY(),
695 dns::RRType::ANY(), dns::RRTTL(0)));
696 request->addRRset(D2UpdateMessage::SECTION_UPDATE, update);
697
698 // Set the transaction's update request to the new request.
699 setDnsUpdateRequest(request);
700 }
701
702 } // namespace isc::d2
703 } // namespace isc
704