nc_add.cc 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697
  1. // Copyright (C) 2013 Internet Systems Consortium, Inc. ("ISC")
  2. //
  3. // Permission to use, copy, modify, and/or distribute this software for any
  4. // purpose with or without fee is hereby granted, provided that the above
  5. // copyright notice and this permission notice appear in all copies.
  6. //
  7. // THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
  8. // REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
  9. // AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
  10. // INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
  11. // LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
  12. // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  13. // PERFORMANCE OF THIS SOFTWARE.
  14. #include <d2/d2_log.h>
  15. #include <d2/d2_cfg_mgr.h>
  16. #include <d2/nc_add.h>
  17. #include <boost/function.hpp>
  18. #include <boost/bind.hpp>
  19. #include <util/buffer.h>
  20. #include <dns/rdataclass.h>
  21. namespace isc {
  22. namespace d2 {
  23. // NameAddTransaction states
  24. const int NameAddTransaction::ADDING_FWD_ADDRS_ST;
  25. const int NameAddTransaction::REPLACING_FWD_ADDRS_ST;
  26. const int NameAddTransaction::REPLACING_REV_PTRS_ST;
  27. // NameAddTransaction events
  28. const int NameAddTransaction::FQDN_IN_USE_EVT;
  29. const int NameAddTransaction::FQDN_NOT_IN_USE_EVT;
  30. NameAddTransaction::
  31. NameAddTransaction(IOServicePtr& io_service,
  32. dhcp_ddns::NameChangeRequestPtr& ncr,
  33. DdnsDomainPtr& forward_domain,
  34. DdnsDomainPtr& reverse_domain)
  35. : NameChangeTransaction(io_service, ncr, forward_domain, reverse_domain) {
  36. if (ncr->getChangeType() != isc::dhcp_ddns::CHG_ADD) {
  37. isc_throw (NameAddTransactionError,
  38. "NameAddTransaction, request type must be CHG_ADD");
  39. }
  40. }
  41. NameAddTransaction::~NameAddTransaction(){
  42. }
  43. void
  44. NameAddTransaction::defineEvents() {
  45. // Call superclass impl first.
  46. NameChangeTransaction::defineEvents();
  47. // Define NameAddTransaction events.
  48. defineEvent(FQDN_IN_USE_EVT, "FQDN_IN_USE_EVT");
  49. defineEvent(FQDN_NOT_IN_USE_EVT, "FQDN_NOT_IN_USE_EVT");
  50. }
  51. void
  52. NameAddTransaction::verifyEvents() {
  53. // Call superclass implementation first to verify its events. These are
  54. // events common to all transactions, and they must be defined.
  55. // SELECT_SERVER_EVT
  56. // SERVER_SELECTED_EVT
  57. // SERVER_IO_ERROR_EVT
  58. // NO_MORE_SERVERS_EVT
  59. // IO_COMPLETED_EVT
  60. // UPDATE_OK_EVT
  61. // UPDATE_FAILED_EVT
  62. NameChangeTransaction::verifyEvents();
  63. // Verify NameAddTransaction events by attempting to fetch them.
  64. getEvent(FQDN_IN_USE_EVT);
  65. getEvent(FQDN_NOT_IN_USE_EVT);
  66. }
  67. void
  68. NameAddTransaction::defineStates() {
  69. // Call superclass impl first.
  70. NameChangeTransaction::defineStates();
  71. // Define NameAddTransaction states.
  72. defineState(READY_ST, "READY_ST",
  73. boost::bind(&NameAddTransaction::readyHandler, this));
  74. defineState(SELECTING_FWD_SERVER_ST, "SELECTING_FWD_SERVER_ST",
  75. boost::bind(&NameAddTransaction::selectingFwdServerHandler, this));
  76. defineState(SELECTING_REV_SERVER_ST, "SELECTING_REV_SERVER_ST",
  77. boost::bind(&NameAddTransaction::selectingRevServerHandler, this));
  78. defineState(ADDING_FWD_ADDRS_ST, "ADDING_FWD_ADDRS_ST",
  79. boost::bind(&NameAddTransaction::addingFwdAddrsHandler, this));
  80. defineState(REPLACING_FWD_ADDRS_ST, "REPLACING_FWD_ADDRS_ST",
  81. boost::bind(&NameAddTransaction::replacingFwdAddrsHandler, this));
  82. defineState(REPLACING_REV_PTRS_ST, "REPLACING_REV_PTRS_ST",
  83. boost::bind(&NameAddTransaction::replacingRevPtrsHandler, this));
  84. defineState(PROCESS_TRANS_OK_ST, "PROCESS_TRANS_OK_ST",
  85. boost::bind(&NameAddTransaction::processAddOkHandler, this));
  86. defineState(PROCESS_TRANS_FAILED_ST, "PROCESS_TRANS_FAILED_ST",
  87. boost::bind(&NameAddTransaction::processAddFailedHandler, this));
  88. }
  89. void
  90. NameAddTransaction::verifyStates() {
  91. // Call superclass implementation first to verify its states. These are
  92. // states common to all transactions, and they must be defined.
  93. // READY_ST
  94. // SELECTING_FWD_SERVER_ST
  95. // SELECTING_REV_SERVER_ST
  96. // PROCESS_TRANS_OK_ST
  97. // PROCESS_TRANS_FAILED_ST
  98. NameChangeTransaction::verifyStates();
  99. // Verify NameAddTransaction states by attempting to fetch them.
  100. getState(ADDING_FWD_ADDRS_ST);
  101. getState(REPLACING_FWD_ADDRS_ST);
  102. getState(REPLACING_REV_PTRS_ST);
  103. }
  104. void
  105. NameAddTransaction::readyHandler() {
  106. switch(getNextEvent()) {
  107. case START_EVT:
  108. if (getForwardDomain()) {
  109. // Request includes a forward change, do that first.
  110. transition(SELECTING_FWD_SERVER_ST, SELECT_SERVER_EVT);
  111. } else {
  112. // Reverse change only, transition accordingly.
  113. transition(SELECTING_REV_SERVER_ST, SELECT_SERVER_EVT);
  114. }
  115. break;
  116. default:
  117. // Event is invalid.
  118. isc_throw(NameAddTransactionError,
  119. "Wrong event for context: " << getContextStr());
  120. }
  121. }
  122. void
  123. NameAddTransaction::selectingFwdServerHandler() {
  124. switch(getNextEvent()) {
  125. case SELECT_SERVER_EVT:
  126. // First time through for this transaction, so initialize server
  127. // selection.
  128. initServerSelection(getForwardDomain());
  129. break;
  130. case SERVER_IO_ERROR_EVT:
  131. // We failed to communicate with current server. Attempt to select
  132. // another one below.
  133. break;
  134. default:
  135. // Event is invalid.
  136. isc_throw(NameAddTransactionError,
  137. "Wrong event for context: " << getContextStr());
  138. }
  139. // Select the next server from the list of forward servers.
  140. if (selectNextServer()) {
  141. // We have a server to try.
  142. transition(ADDING_FWD_ADDRS_ST, SERVER_SELECTED_EVT);
  143. }
  144. else {
  145. // Server list is exhausted, so fail the transaction.
  146. transition(PROCESS_TRANS_FAILED_ST, NO_MORE_SERVERS_EVT);
  147. }
  148. }
  149. void
  150. NameAddTransaction::addingFwdAddrsHandler() {
  151. if (doOnEntry()) {
  152. // Clear the request on initial transition. This allows us to reuse
  153. // the request on retries if necessary.
  154. clearDnsUpdateRequest();
  155. }
  156. switch(getNextEvent()) {
  157. case SERVER_SELECTED_EVT:
  158. if (!getDnsUpdateRequest()) {
  159. // Request hasn't been constructed yet, so build it.
  160. try {
  161. buildAddFwdAddressRequest();
  162. } catch (const std::exception& ex) {
  163. // While unlikely, the build might fail if we have invalid
  164. // data. Should that be the case, we need to fail the
  165. // transaction.
  166. LOG_ERROR(dctl_logger, DHCP_DDNS_FORWARD_ADD_BUILD_FAILURE)
  167. .arg(getNcr()->toText())
  168. .arg(ex.what());
  169. transition(PROCESS_TRANS_FAILED_ST, UPDATE_FAILED_EVT);
  170. break;
  171. }
  172. }
  173. // Call sendUpdate() to initiate the async send. Note it also sets
  174. // next event to NOP_EVT.
  175. sendUpdate();
  176. break;
  177. case IO_COMPLETED_EVT: {
  178. switch (getDnsUpdateStatus()) {
  179. case DNSClient::SUCCESS: {
  180. // We successfully received a response packet from the server.
  181. const dns::Rcode& rcode = getDnsUpdateResponse()->getRcode();
  182. if (rcode == dns::Rcode::NOERROR()) {
  183. // We were able to add it. Mark it as done.
  184. setForwardChangeCompleted(true);
  185. // If request calls for reverse update then do that next,
  186. // otherwise we can process ok.
  187. if (getReverseDomain()) {
  188. transition(SELECTING_REV_SERVER_ST, SELECT_SERVER_EVT);
  189. } else {
  190. transition(PROCESS_TRANS_OK_ST, UPDATE_OK_EVT);
  191. }
  192. } else if (rcode == dns::Rcode::YXDOMAIN()) {
  193. // FQDN is in use so we need to attempt to replace
  194. // forward address.
  195. transition(REPLACING_FWD_ADDRS_ST, FQDN_IN_USE_EVT);
  196. } else {
  197. // Per RFC4703 any other value means cease.
  198. // If we get not authorized should we try the next server in
  199. // the list? @todo This needs some discussion perhaps.
  200. LOG_ERROR(dctl_logger, DHCP_DDNS_FORWARD_ADD_REJECTED)
  201. .arg(getCurrentServer()->getIpAddress())
  202. .arg(getNcr()->getFqdn())
  203. .arg(rcode.getCode());
  204. transition(PROCESS_TRANS_FAILED_ST, UPDATE_FAILED_EVT);
  205. }
  206. break;
  207. }
  208. case DNSClient::TIMEOUT:
  209. case DNSClient::OTHER:
  210. // We couldn't send to the current server, log it and set up
  211. // to select the next server for a retry.
  212. // @note For now we treat OTHER as an IO error like TIMEOUT. It
  213. // is not entirely clear if this is accurate.
  214. LOG_ERROR(dctl_logger, DHCP_DDNS_FORWARD_ADD_IO_ERROR)
  215. .arg(getNcr()->getFqdn())
  216. .arg(getCurrentServer()->getIpAddress());
  217. retryTransition(SELECTING_FWD_SERVER_ST);
  218. break;
  219. case DNSClient::INVALID_RESPONSE:
  220. // A response was received but was corrupt. Retry it like an IO
  221. // error.
  222. LOG_ERROR(dctl_logger, DHCP_DDNS_FORWARD_ADD_RESP_CORRUPT)
  223. .arg(getCurrentServer()->getIpAddress())
  224. .arg(getNcr()->getFqdn());
  225. retryTransition(SELECTING_FWD_SERVER_ST);
  226. break;
  227. default:
  228. // Any other value and we will fail this transaction, something
  229. // bigger is wrong.
  230. LOG_ERROR(dctl_logger, DHCP_DDNS_FORWARD_ADD_BAD_DNSCLIENT_STATUS)
  231. .arg(getDnsUpdateStatus())
  232. .arg(getNcr()->getFqdn())
  233. .arg(getCurrentServer()->getIpAddress());
  234. transition(PROCESS_TRANS_FAILED_ST, UPDATE_FAILED_EVT);
  235. break;
  236. } // end switch on dns_status
  237. break;
  238. } // end case IO_COMPLETE_EVT
  239. default:
  240. // Event is invalid.
  241. isc_throw(NameAddTransactionError,
  242. "Wrong event for context: " << getContextStr());
  243. }
  244. }
  245. void
  246. NameAddTransaction::replacingFwdAddrsHandler() {
  247. if (doOnEntry()) {
  248. // Clear the request on initial transition. This allows us to reuse
  249. // the request on retries if necessary.
  250. clearDnsUpdateRequest();
  251. }
  252. switch(getNextEvent()) {
  253. case FQDN_IN_USE_EVT:
  254. case SERVER_SELECTED_EVT:
  255. if (!getDnsUpdateRequest()) {
  256. // Request hasn't been constructed yet, so build it.
  257. try {
  258. buildReplaceFwdAddressRequest();
  259. } catch (const std::exception& ex) {
  260. // While unlikely, the build might fail if we have invalid
  261. // data. Should that be the case, we need to fail the
  262. // transaction.
  263. LOG_ERROR(dctl_logger, DHCP_DDNS_FORWARD_REPLACE_BUILD_FAILURE)
  264. .arg(getNcr()->toText())
  265. .arg(ex.what());
  266. transition(PROCESS_TRANS_FAILED_ST, UPDATE_FAILED_EVT);
  267. break;
  268. }
  269. }
  270. // Call sendUpdate() to initiate the async send. Note it also sets
  271. // next event to NOP_EVT.
  272. sendUpdate();
  273. break;
  274. case IO_COMPLETED_EVT: {
  275. switch (getDnsUpdateStatus()) {
  276. case DNSClient::SUCCESS: {
  277. // We successfully received a response packet from the server.
  278. const dns::Rcode& rcode = getDnsUpdateResponse()->getRcode();
  279. if (rcode == dns::Rcode::NOERROR()) {
  280. // We were able to replace the forward mapping. Mark it as done.
  281. setForwardChangeCompleted(true);
  282. // If request calls for reverse update then do that next,
  283. // otherwise we can process ok.
  284. if (getReverseDomain()) {
  285. transition(SELECTING_REV_SERVER_ST, SELECT_SERVER_EVT);
  286. } else {
  287. transition(PROCESS_TRANS_OK_ST, UPDATE_OK_EVT);
  288. }
  289. } else if (rcode == dns::Rcode::NXDOMAIN()) {
  290. // FQDN is NOT in use so go back and do the forward add address.
  291. // Covers the case that it was there when we tried to add it,
  292. // but has since been removed per RFC 4703.
  293. transition(ADDING_FWD_ADDRS_ST, SERVER_SELECTED_EVT);
  294. } else {
  295. // Per RFC4703 any other value means cease.
  296. // If we get not authorized should try the next server in
  297. // the list? @todo This needs some discussion perhaps.
  298. LOG_ERROR(dctl_logger, DHCP_DDNS_FORWARD_REPLACE_REJECTED)
  299. .arg(getCurrentServer()->getIpAddress())
  300. .arg(getNcr()->getFqdn())
  301. .arg(rcode.getCode());
  302. transition(PROCESS_TRANS_FAILED_ST, UPDATE_FAILED_EVT);
  303. }
  304. break;
  305. }
  306. case DNSClient::TIMEOUT:
  307. case DNSClient::OTHER:
  308. // We couldn't send to the current server, log it and set up
  309. // to select the next server for a retry.
  310. // @note For now we treat OTHER as an IO error like TIMEOUT. It
  311. // is not entirely clear if this is accurate.
  312. LOG_ERROR(dctl_logger, DHCP_DDNS_FORWARD_REPLACE_IO_ERROR)
  313. .arg(getNcr()->getFqdn())
  314. .arg(getCurrentServer()->getIpAddress());
  315. // If we are out of retries on this server, we go back and start
  316. // all over on a new server.
  317. retryTransition(SELECTING_FWD_SERVER_ST);
  318. break;
  319. case DNSClient::INVALID_RESPONSE:
  320. // A response was received but was corrupt. Retry it like an IO
  321. // error.
  322. LOG_ERROR(dctl_logger, DHCP_DDNS_FORWARD_REPLACE_RESP_CORRUPT)
  323. .arg(getCurrentServer()->getIpAddress())
  324. .arg(getNcr()->getFqdn());
  325. // If we are out of retries on this server, we go back and start
  326. // all over on a new server.
  327. retryTransition(SELECTING_FWD_SERVER_ST);
  328. break;
  329. default:
  330. // Any other value and we will fail this transaction, something
  331. // bigger is wrong.
  332. LOG_ERROR(dctl_logger,
  333. DHCP_DDNS_FORWARD_REPLACE_BAD_DNSCLIENT_STATUS)
  334. .arg(getDnsUpdateStatus())
  335. .arg(getNcr()->getFqdn())
  336. .arg(getCurrentServer()->getIpAddress());
  337. transition(PROCESS_TRANS_FAILED_ST, UPDATE_FAILED_EVT);
  338. break;
  339. } // end switch on dns_status
  340. break;
  341. } // end case IO_COMPLETE_EVT
  342. default:
  343. // Event is invalid.
  344. isc_throw(NameAddTransactionError,
  345. "Wrong event for context: " << getContextStr());
  346. }
  347. }
  348. void
  349. NameAddTransaction::selectingRevServerHandler() {
  350. switch(getNextEvent()) {
  351. case SELECT_SERVER_EVT:
  352. // First time through for this transaction, so initialize server
  353. // selection.
  354. initServerSelection(getReverseDomain());
  355. break;
  356. case SERVER_IO_ERROR_EVT:
  357. // We failed to communicate with current server. Attempt to select
  358. // another one below.
  359. break;
  360. default:
  361. // Event is invalid.
  362. isc_throw(NameAddTransactionError,
  363. "Wrong event for context: " << getContextStr());
  364. }
  365. // Select the next server from the list of forward servers.
  366. if (selectNextServer()) {
  367. // We have a server to try.
  368. transition(REPLACING_REV_PTRS_ST, SERVER_SELECTED_EVT);
  369. }
  370. else {
  371. // Server list is exhausted, so fail the transaction.
  372. transition(PROCESS_TRANS_FAILED_ST, NO_MORE_SERVERS_EVT);
  373. }
  374. }
  375. void
  376. NameAddTransaction::replacingRevPtrsHandler() {
  377. if (doOnEntry()) {
  378. // Clear the request on initial transition. This allows us to reuse
  379. // the request on retries if necessary.
  380. clearDnsUpdateRequest();
  381. }
  382. switch(getNextEvent()) {
  383. case SERVER_SELECTED_EVT:
  384. if (!getDnsUpdateRequest()) {
  385. // Request hasn't been constructed yet, so build it.
  386. try {
  387. buildReplaceRevPtrsRequest();
  388. } catch (const std::exception& ex) {
  389. // While unlikely, the build might fail if we have invalid
  390. // data. Should that be the case, we need to fail the
  391. // transaction.
  392. LOG_ERROR(dctl_logger, DHCP_DDNS_REVERSE_REPLACE_BUILD_FAILURE)
  393. .arg(getNcr()->toText())
  394. .arg(ex.what());
  395. transition(PROCESS_TRANS_FAILED_ST, UPDATE_FAILED_EVT);
  396. break;
  397. }
  398. }
  399. // Call sendUpdate() to initiate the async send. Note it also sets
  400. // next event to NOP_EVT.
  401. sendUpdate();
  402. break;
  403. case IO_COMPLETED_EVT: {
  404. switch (getDnsUpdateStatus()) {
  405. case DNSClient::SUCCESS: {
  406. // We successfully received a response packet from the server.
  407. const dns::Rcode& rcode = getDnsUpdateResponse()->getRcode();
  408. if (rcode == dns::Rcode::NOERROR()) {
  409. // We were able to update the reverse mapping. Mark it as done.
  410. setReverseChangeCompleted(true);
  411. transition(PROCESS_TRANS_OK_ST, UPDATE_OK_EVT);
  412. } else {
  413. // Per RFC4703 any other value means cease.
  414. // If we get not authorized should try the next server in
  415. // the list? @todo This needs some discussion perhaps.
  416. LOG_ERROR(dctl_logger, DHCP_DDNS_REVERSE_REPLACE_REJECTED)
  417. .arg(getCurrentServer()->getIpAddress())
  418. .arg(getNcr()->getFqdn())
  419. .arg(rcode.getCode());
  420. transition(PROCESS_TRANS_FAILED_ST, UPDATE_FAILED_EVT);
  421. }
  422. break;
  423. }
  424. case DNSClient::TIMEOUT:
  425. case DNSClient::OTHER:
  426. // We couldn't send to the current server, log it and set up
  427. // to select the next server for a retry.
  428. // @note For now we treat OTHER as an IO error like TIMEOUT. It
  429. // is not entirely clear if this is accurate.
  430. LOG_ERROR(dctl_logger, DHCP_DDNS_REVERSE_REPLACE_IO_ERROR)
  431. .arg(getNcr()->getFqdn())
  432. .arg(getCurrentServer()->getIpAddress());
  433. // If we are out of retries on this server, we go back and start
  434. // all over on a new server.
  435. retryTransition(SELECTING_REV_SERVER_ST);
  436. break;
  437. case DNSClient::INVALID_RESPONSE:
  438. // A response was received but was corrupt. Retry it like an IO
  439. // error.
  440. LOG_ERROR(dctl_logger, DHCP_DDNS_REVERSE_REPLACE_RESP_CORRUPT)
  441. .arg(getCurrentServer()->getIpAddress())
  442. .arg(getNcr()->getFqdn());
  443. // If we are out of retries on this server, we go back and start
  444. // all over on a new server.
  445. retryTransition(SELECTING_REV_SERVER_ST);
  446. break;
  447. default:
  448. // Any other value and we will fail this transaction, something
  449. // bigger is wrong.
  450. LOG_ERROR(dctl_logger,
  451. DHCP_DDNS_REVERSE_REPLACE_BAD_DNSCLIENT_STATUS)
  452. .arg(getDnsUpdateStatus())
  453. .arg(getNcr()->getFqdn())
  454. .arg(getCurrentServer()->getIpAddress());
  455. transition(PROCESS_TRANS_FAILED_ST, UPDATE_FAILED_EVT);
  456. break;
  457. } // end switch on dns_status
  458. break;
  459. } // end case IO_COMPLETE_EVT
  460. default:
  461. // Event is invalid.
  462. isc_throw(NameAddTransactionError,
  463. "Wrong event for context: " << getContextStr());
  464. }
  465. }
  466. void
  467. NameAddTransaction::processAddOkHandler() {
  468. switch(getNextEvent()) {
  469. case UPDATE_OK_EVT:
  470. LOG_DEBUG(dctl_logger, DBGLVL_TRACE_DETAIL, DHCP_DDNS_ADD_SUCCEEDED)
  471. .arg(getNcr()->toText());
  472. setNcrStatus(dhcp_ddns::ST_COMPLETED);
  473. endModel();
  474. break;
  475. default:
  476. // Event is invalid.
  477. isc_throw(NameAddTransactionError,
  478. "Wrong event for context: " << getContextStr());
  479. }
  480. }
  481. void
  482. NameAddTransaction::processAddFailedHandler() {
  483. switch(getNextEvent()) {
  484. case UPDATE_FAILED_EVT:
  485. case NO_MORE_SERVERS_EVT:
  486. LOG_ERROR(dctl_logger, DHCP_DDNS_ADD_FAILED).arg(getNcr()->toText())
  487. .arg(getContextStr());
  488. setNcrStatus(dhcp_ddns::ST_FAILED);
  489. endModel();
  490. break;
  491. default:
  492. // Event is invalid.
  493. isc_throw(NameAddTransactionError,
  494. "Wrong event for context: " << getContextStr());
  495. }
  496. }
  497. void
  498. NameAddTransaction::buildAddFwdAddressRequest() {
  499. // Construct an empty request.
  500. D2UpdateMessagePtr request = prepNewRequest(getForwardDomain());
  501. // Construct dns::Name from NCR fqdn.
  502. dns::Name fqdn(dns::Name(getNcr()->getFqdn()));
  503. // Content on this request is based on RFC 4703, section 5.3.1
  504. // First build the Prerequisite Section.
  505. // Create 'FQDN Is Not In Use' prerequisite and add it to the
  506. // prerequisite section.
  507. // Based on RFC 2136, section 2.4.5
  508. dns::RRsetPtr prereq(new dns::RRset(fqdn, dns::RRClass::NONE(),
  509. dns::RRType::ANY(), dns::RRTTL(0)));
  510. request->addRRset(D2UpdateMessage::SECTION_PREREQUISITE, prereq);
  511. // Next build the Update Section.
  512. // Create the FQDN/IP 'add' RR and add it to the to update section.
  513. // Based on RFC 2136, section 2.5.1
  514. dns::RRsetPtr update(new dns::RRset(fqdn, dns::RRClass::IN(),
  515. getAddressRRType(), dns::RRTTL(0)));
  516. addLeaseAddressRdata(update);
  517. request->addRRset(D2UpdateMessage::SECTION_UPDATE, update);
  518. // Now create the FQDN/DHCID 'add' RR and add it to update section.
  519. // Based on RFC 2136, section 2.5.1
  520. update.reset(new dns::RRset(fqdn, dns::RRClass::IN(),
  521. dns::RRType::DHCID(), dns::RRTTL(0)));
  522. addDhcidRdata(update);
  523. request->addRRset(D2UpdateMessage::SECTION_UPDATE, update);
  524. // Set the transaction's update request to the new request.
  525. setDnsUpdateRequest(request);
  526. }
  527. void
  528. NameAddTransaction::buildReplaceFwdAddressRequest() {
  529. // Construct an empty request.
  530. D2UpdateMessagePtr request = prepNewRequest(getForwardDomain());
  531. // Construct dns::Name from NCR fqdn.
  532. dns::Name fqdn(dns::Name(getNcr()->getFqdn()));
  533. // Content on this request is based on RFC 4703, section 5.3.2
  534. // First build the Prerequisite Section.
  535. // Create an 'FQDN Is In Use' prerequisite and add it to the
  536. // pre-requisite section.
  537. // Based on RFC 2136, section 2.4.4
  538. dns::RRsetPtr prereq(new dns::RRset(fqdn, dns::RRClass::ANY(),
  539. dns::RRType::ANY(), dns::RRTTL(0)));
  540. request->addRRset(D2UpdateMessage::SECTION_PREREQUISITE, prereq);
  541. // Create an DHCID matches prerequisite RR and add it to the
  542. // pre-requisite section.
  543. // Based on RFC 2136, section 2.4.2.
  544. prereq.reset(new dns::RRset(fqdn, dns::RRClass::IN(),
  545. dns::RRType::DHCID(), dns::RRTTL(0)));
  546. addDhcidRdata(prereq);
  547. request->addRRset(D2UpdateMessage::SECTION_PREREQUISITE, prereq);
  548. // Next build the Update Section.
  549. // Create the FQDN/IP 'delete' RR and add it to the update section.
  550. // Based on RFC 2136, section 2.5.2
  551. dns::RRsetPtr update(new dns::RRset(fqdn, dns::RRClass::ANY(),
  552. getAddressRRType(), dns::RRTTL(0)));
  553. request->addRRset(D2UpdateMessage::SECTION_UPDATE, update);
  554. // Create the FQDN/IP 'add' RR and add it to the update section.
  555. // Based on RFC 2136, section 2.5.1
  556. update.reset(new dns::RRset(fqdn, dns::RRClass::IN(),
  557. getAddressRRType(), dns::RRTTL(0)));
  558. addLeaseAddressRdata(update);
  559. request->addRRset(D2UpdateMessage::SECTION_UPDATE, update);
  560. // Set the transaction's update request to the new request.
  561. setDnsUpdateRequest(request);
  562. }
  563. void
  564. NameAddTransaction::buildReplaceRevPtrsRequest() {
  565. // Construct an empty request.
  566. D2UpdateMessagePtr request = prepNewRequest(getReverseDomain());
  567. // Create the reverse IP address "FQDN".
  568. std::string rev_addr = D2CfgMgr::reverseIpAddress(getNcr()->getIpAddress());
  569. dns::Name rev_ip(rev_addr);
  570. // Content on this request is based on RFC 4703, section 5.4
  571. // Reverse replacement has no prerequisites so straight on to
  572. // building the Update section.
  573. // Create the PTR 'delete' RR and add it to update section.
  574. dns::RRsetPtr update(new dns::RRset(rev_ip, dns::RRClass::ANY(),
  575. dns::RRType::PTR(), dns::RRTTL(0)));
  576. request->addRRset(D2UpdateMessage::SECTION_UPDATE, update);
  577. // Create the DHCID 'delete' RR and add it to the update section.
  578. update.reset(new dns::RRset(rev_ip, dns::RRClass::ANY(),
  579. dns::RRType::DHCID(), dns::RRTTL(0)));
  580. request->addRRset(D2UpdateMessage::SECTION_UPDATE, update);
  581. // Create the FQDN/IP PTR 'add' RR, add the FQDN as the PTR Rdata
  582. // then add it to update section.
  583. update.reset(new dns::RRset(rev_ip, dns::RRClass::IN(),
  584. dns::RRType::PTR(), dns::RRTTL(0)));
  585. addPtrRdata(update);
  586. request->addRRset(D2UpdateMessage::SECTION_UPDATE, update);
  587. // Create the FQDN/IP PTR 'add' RR, add the DHCID Rdata
  588. // then add it to update section.
  589. update.reset(new dns::RRset(rev_ip, dns::RRClass::IN(),
  590. dns::RRType::DHCID(), dns::RRTTL(0)));
  591. addDhcidRdata(update);
  592. request->addRRset(D2UpdateMessage::SECTION_UPDATE, update);
  593. // Set the transaction's update request to the new request.
  594. setDnsUpdateRequest(request);
  595. }
  596. } // namespace isc::d2
  597. } // namespace isc