PageRenderTime 63ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 1ms

/contrib/bind9/lib/dns/client.c

https://bitbucket.org/freebsd/freebsd-head/
C | 3023 lines | 2383 code | 428 blank | 212 comment | 707 complexity | dad12cffac10c77aabbcef2dc0bad2bb MD5 | raw file
Possible License(s): MPL-2.0-no-copyleft-exception, BSD-3-Clause, LGPL-2.0, LGPL-2.1, BSD-2-Clause, 0BSD, JSON, AGPL-1.0, GPL-2.0
  1. /*
  2. * Copyright (C) 2009-2012 Internet Systems Consortium, Inc. ("ISC")
  3. *
  4. * Permission to use, copy, modify, and/or distribute this software for any
  5. * purpose with or without fee is hereby granted, provided that the above
  6. * copyright notice and this permission notice appear in all copies.
  7. *
  8. * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
  9. * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
  10. * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
  11. * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
  12. * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
  13. * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  14. * PERFORMANCE OF THIS SOFTWARE.
  15. */
  16. /* $Id$ */
  17. #include <config.h>
  18. #include <stddef.h>
  19. #include <isc/app.h>
  20. #include <isc/mem.h>
  21. #include <isc/mutex.h>
  22. #include <isc/sockaddr.h>
  23. #include <isc/socket.h>
  24. #include <isc/task.h>
  25. #include <isc/timer.h>
  26. #include <isc/util.h>
  27. #include <dns/adb.h>
  28. #include <dns/client.h>
  29. #include <dns/db.h>
  30. #include <dns/dispatch.h>
  31. #include <dns/events.h>
  32. #include <dns/forward.h>
  33. #include <dns/keytable.h>
  34. #include <dns/message.h>
  35. #include <dns/name.h>
  36. #include <dns/rdata.h>
  37. #include <dns/rdatalist.h>
  38. #include <dns/rdataset.h>
  39. #include <dns/rdatatype.h>
  40. #include <dns/rdatasetiter.h>
  41. #include <dns/rdatastruct.h>
  42. #include <dns/request.h>
  43. #include <dns/resolver.h>
  44. #include <dns/result.h>
  45. #include <dns/tsec.h>
  46. #include <dns/tsig.h>
  47. #include <dns/view.h>
  48. #include <dst/dst.h>
  49. #define DNS_CLIENT_MAGIC ISC_MAGIC('D', 'N', 'S', 'c')
  50. #define DNS_CLIENT_VALID(c) ISC_MAGIC_VALID(c, DNS_CLIENT_MAGIC)
  51. #define RCTX_MAGIC ISC_MAGIC('R', 'c', 't', 'x')
  52. #define RCTX_VALID(c) ISC_MAGIC_VALID(c, RCTX_MAGIC)
  53. #define REQCTX_MAGIC ISC_MAGIC('R', 'q', 'c', 'x')
  54. #define REQCTX_VALID(c) ISC_MAGIC_VALID(c, REQCTX_MAGIC)
  55. #define UCTX_MAGIC ISC_MAGIC('U', 'c', 't', 'x')
  56. #define UCTX_VALID(c) ISC_MAGIC_VALID(c, UCTX_MAGIC)
  57. #define MAX_RESTARTS 16
  58. /*%
  59. * DNS client object
  60. */
  61. struct dns_client {
  62. /* Unlocked */
  63. unsigned int magic;
  64. unsigned int attributes;
  65. isc_mutex_t lock;
  66. isc_mem_t *mctx;
  67. isc_appctx_t *actx;
  68. isc_taskmgr_t *taskmgr;
  69. isc_task_t *task;
  70. isc_socketmgr_t *socketmgr;
  71. isc_timermgr_t *timermgr;
  72. dns_dispatchmgr_t *dispatchmgr;
  73. dns_dispatch_t *dispatchv4;
  74. dns_dispatch_t *dispatchv6;
  75. unsigned int update_timeout;
  76. unsigned int update_udptimeout;
  77. unsigned int update_udpretries;
  78. unsigned int find_timeout;
  79. unsigned int find_udpretries;
  80. /* Locked */
  81. unsigned int references;
  82. dns_viewlist_t viewlist;
  83. ISC_LIST(struct resctx) resctxs;
  84. ISC_LIST(struct reqctx) reqctxs;
  85. ISC_LIST(struct updatectx) updatectxs;
  86. };
  87. /*%
  88. * Timeout/retry constants for dynamic update borrowed from nsupdate
  89. */
  90. #define DEF_UPDATE_TIMEOUT 300
  91. #define MIN_UPDATE_TIMEOUT 30
  92. #define DEF_UPDATE_UDPTIMEOUT 3
  93. #define DEF_UPDATE_UDPRETRIES 3
  94. #define DEF_FIND_TIMEOUT 5
  95. #define DEF_FIND_UDPRETRIES 3
  96. #define DNS_CLIENTATTR_OWNCTX 0x01
  97. #define DNS_CLIENTVIEW_NAME "dnsclient"
  98. /*%
  99. * Internal state for a single name resolution procedure
  100. */
  101. typedef struct resctx {
  102. /* Unlocked */
  103. unsigned int magic;
  104. isc_mutex_t lock;
  105. dns_client_t *client;
  106. isc_boolean_t want_dnssec;
  107. /* Locked */
  108. ISC_LINK(struct resctx) link;
  109. isc_task_t *task;
  110. dns_view_t *view;
  111. unsigned int restarts;
  112. dns_fixedname_t name;
  113. dns_rdatatype_t type;
  114. dns_fetch_t *fetch;
  115. dns_namelist_t namelist;
  116. isc_result_t result;
  117. dns_clientresevent_t *event;
  118. isc_boolean_t canceled;
  119. dns_rdataset_t *rdataset;
  120. dns_rdataset_t *sigrdataset;
  121. } resctx_t;
  122. /*%
  123. * Argument of an internal event for synchronous name resolution.
  124. */
  125. typedef struct resarg {
  126. /* Unlocked */
  127. isc_appctx_t *actx;
  128. dns_client_t *client;
  129. isc_mutex_t lock;
  130. /* Locked */
  131. isc_result_t result;
  132. isc_result_t vresult;
  133. dns_namelist_t *namelist;
  134. dns_clientrestrans_t *trans;
  135. isc_boolean_t canceled;
  136. } resarg_t;
  137. /*%
  138. * Internal state for a single DNS request
  139. */
  140. typedef struct reqctx {
  141. /* Unlocked */
  142. unsigned int magic;
  143. isc_mutex_t lock;
  144. dns_client_t *client;
  145. unsigned int parseoptions;
  146. /* Locked */
  147. ISC_LINK(struct reqctx) link;
  148. isc_boolean_t canceled;
  149. dns_tsigkey_t *tsigkey;
  150. dns_request_t *request;
  151. dns_clientreqevent_t *event;
  152. } reqctx_t;
  153. /*%
  154. * Argument of an internal event for synchronous DNS request.
  155. */
  156. typedef struct reqarg {
  157. /* Unlocked */
  158. isc_appctx_t *actx;
  159. dns_client_t *client;
  160. isc_mutex_t lock;
  161. /* Locked */
  162. isc_result_t result;
  163. dns_clientreqtrans_t *trans;
  164. isc_boolean_t canceled;
  165. } reqarg_t;
  166. /*%
  167. * Argument of an internal event for synchronous name resolution.
  168. */
  169. typedef struct updatearg {
  170. /* Unlocked */
  171. isc_appctx_t *actx;
  172. dns_client_t *client;
  173. isc_mutex_t lock;
  174. /* Locked */
  175. isc_result_t result;
  176. dns_clientupdatetrans_t *trans;
  177. isc_boolean_t canceled;
  178. } updatearg_t;
  179. /*%
  180. * Internal state for a single dynamic update procedure
  181. */
  182. typedef struct updatectx {
  183. /* Unlocked */
  184. unsigned int magic;
  185. isc_mutex_t lock;
  186. dns_client_t *client;
  187. /* Locked */
  188. dns_request_t *updatereq;
  189. dns_request_t *soareq;
  190. dns_clientrestrans_t *restrans;
  191. dns_clientrestrans_t *restrans2;
  192. isc_boolean_t canceled;
  193. /* Task Locked */
  194. ISC_LINK(struct updatectx) link;
  195. dns_clientupdatestate_t state;
  196. dns_rdataclass_t rdclass;
  197. dns_view_t *view;
  198. dns_message_t *updatemsg;
  199. dns_message_t *soaquery;
  200. dns_clientupdateevent_t *event;
  201. dns_tsigkey_t *tsigkey;
  202. dst_key_t *sig0key;
  203. dns_name_t *firstname;
  204. dns_name_t soaqname;
  205. dns_fixedname_t zonefname;
  206. dns_name_t *zonename;
  207. isc_sockaddrlist_t servers;
  208. unsigned int nservers;
  209. isc_sockaddr_t *currentserver;
  210. struct updatectx *bp4;
  211. struct updatectx *bp6;
  212. } updatectx_t;
  213. static isc_result_t request_soa(updatectx_t *uctx);
  214. static void client_resfind(resctx_t *rctx, dns_fetchevent_t *event);
  215. static isc_result_t send_update(updatectx_t *uctx);
  216. static isc_result_t
  217. getudpdispatch(int family, dns_dispatchmgr_t *dispatchmgr,
  218. isc_socketmgr_t *socketmgr, isc_taskmgr_t *taskmgr,
  219. isc_boolean_t is_shared, dns_dispatch_t **dispp)
  220. {
  221. unsigned int attrs, attrmask;
  222. isc_sockaddr_t sa;
  223. dns_dispatch_t *disp;
  224. unsigned buffersize, maxbuffers, maxrequests, buckets, increment;
  225. isc_result_t result;
  226. attrs = 0;
  227. attrs |= DNS_DISPATCHATTR_UDP;
  228. switch (family) {
  229. case AF_INET:
  230. attrs |= DNS_DISPATCHATTR_IPV4;
  231. break;
  232. case AF_INET6:
  233. attrs |= DNS_DISPATCHATTR_IPV6;
  234. break;
  235. default:
  236. INSIST(0);
  237. }
  238. attrmask = 0;
  239. attrmask |= DNS_DISPATCHATTR_UDP;
  240. attrmask |= DNS_DISPATCHATTR_TCP;
  241. attrmask |= DNS_DISPATCHATTR_IPV4;
  242. attrmask |= DNS_DISPATCHATTR_IPV6;
  243. isc_sockaddr_anyofpf(&sa, family);
  244. buffersize = 4096;
  245. maxbuffers = is_shared ? 1000 : 8;
  246. maxrequests = 32768;
  247. buckets = is_shared ? 16411 : 3;
  248. increment = is_shared ? 16433 : 5;
  249. disp = NULL;
  250. result = dns_dispatch_getudp(dispatchmgr, socketmgr,
  251. taskmgr, &sa,
  252. buffersize, maxbuffers, maxrequests,
  253. buckets, increment,
  254. attrs, attrmask, &disp);
  255. if (result == ISC_R_SUCCESS)
  256. *dispp = disp;
  257. return (result);
  258. }
  259. static isc_result_t
  260. dns_client_createview(isc_mem_t *mctx, dns_rdataclass_t rdclass,
  261. unsigned int options, isc_taskmgr_t *taskmgr,
  262. unsigned int ntasks, isc_socketmgr_t *socketmgr,
  263. isc_timermgr_t *timermgr, dns_dispatchmgr_t *dispatchmgr,
  264. dns_dispatch_t *dispatchv4, dns_dispatch_t *dispatchv6,
  265. dns_view_t **viewp)
  266. {
  267. isc_result_t result;
  268. dns_view_t *view = NULL;
  269. const char *dbtype;
  270. result = dns_view_create(mctx, rdclass, DNS_CLIENTVIEW_NAME, &view);
  271. if (result != ISC_R_SUCCESS)
  272. return (result);
  273. /* Initialize view security roots */
  274. result = dns_view_initsecroots(view, mctx);
  275. if (result != ISC_R_SUCCESS) {
  276. dns_view_detach(&view);
  277. return (result);
  278. }
  279. result = dns_view_createresolver(view, taskmgr, ntasks, socketmgr,
  280. timermgr, 0, dispatchmgr,
  281. dispatchv4, dispatchv6);
  282. if (result != ISC_R_SUCCESS) {
  283. dns_view_detach(&view);
  284. return (result);
  285. }
  286. /*
  287. * Set cache DB.
  288. * XXX: it may be better if specific DB implementations can be
  289. * specified via some configuration knob.
  290. */
  291. if ((options & DNS_CLIENTCREATEOPT_USECACHE) != 0)
  292. dbtype = "rbt";
  293. else
  294. dbtype = "ecdb";
  295. result = dns_db_create(mctx, dbtype, dns_rootname, dns_dbtype_cache,
  296. rdclass, 0, NULL, &view->cachedb);
  297. if (result != ISC_R_SUCCESS) {
  298. dns_view_detach(&view);
  299. return (result);
  300. }
  301. *viewp = view;
  302. return (ISC_R_SUCCESS);
  303. }
  304. isc_result_t
  305. dns_client_create(dns_client_t **clientp, unsigned int options) {
  306. isc_result_t result;
  307. isc_mem_t *mctx = NULL;
  308. isc_appctx_t *actx = NULL;
  309. isc_taskmgr_t *taskmgr = NULL;
  310. isc_socketmgr_t *socketmgr = NULL;
  311. isc_timermgr_t *timermgr = NULL;
  312. result = isc_mem_create(0, 0, &mctx);
  313. if (result != ISC_R_SUCCESS)
  314. return (result);
  315. result = isc_appctx_create(mctx, &actx);
  316. if (result != ISC_R_SUCCESS)
  317. goto cleanup;
  318. result = isc_app_ctxstart(actx);
  319. if (result != ISC_R_SUCCESS)
  320. goto cleanup;
  321. result = isc_taskmgr_createinctx(mctx, actx, 1, 0, &taskmgr);
  322. if (result != ISC_R_SUCCESS)
  323. goto cleanup;
  324. result = isc_socketmgr_createinctx(mctx, actx, &socketmgr);
  325. if (result != ISC_R_SUCCESS)
  326. goto cleanup;
  327. result = isc_timermgr_createinctx(mctx, actx, &timermgr);
  328. if (result != ISC_R_SUCCESS)
  329. goto cleanup;
  330. result = dns_client_createx(mctx, actx, taskmgr, socketmgr, timermgr,
  331. options, clientp);
  332. if (result != ISC_R_SUCCESS)
  333. goto cleanup;
  334. (*clientp)->attributes |= DNS_CLIENTATTR_OWNCTX;
  335. /* client has its own reference to mctx, so we can detach it here */
  336. isc_mem_detach(&mctx);
  337. return (ISC_R_SUCCESS);
  338. cleanup:
  339. if (taskmgr != NULL)
  340. isc_taskmgr_destroy(&taskmgr);
  341. if (timermgr != NULL)
  342. isc_timermgr_destroy(&timermgr);
  343. if (socketmgr != NULL)
  344. isc_socketmgr_destroy(&socketmgr);
  345. if (actx != NULL)
  346. isc_appctx_destroy(&actx);
  347. isc_mem_detach(&mctx);
  348. return (result);
  349. }
  350. isc_result_t
  351. dns_client_createx(isc_mem_t *mctx, isc_appctx_t *actx, isc_taskmgr_t *taskmgr,
  352. isc_socketmgr_t *socketmgr, isc_timermgr_t *timermgr,
  353. unsigned int options, dns_client_t **clientp)
  354. {
  355. dns_client_t *client;
  356. isc_result_t result;
  357. dns_dispatchmgr_t *dispatchmgr = NULL;
  358. dns_dispatch_t *dispatchv4 = NULL;
  359. dns_dispatch_t *dispatchv6 = NULL;
  360. dns_view_t *view = NULL;
  361. REQUIRE(mctx != NULL);
  362. REQUIRE(taskmgr != NULL);
  363. REQUIRE(timermgr != NULL);
  364. REQUIRE(socketmgr != NULL);
  365. REQUIRE(clientp != NULL && *clientp == NULL);
  366. client = isc_mem_get(mctx, sizeof(*client));
  367. if (client == NULL)
  368. return (ISC_R_NOMEMORY);
  369. result = isc_mutex_init(&client->lock);
  370. if (result != ISC_R_SUCCESS) {
  371. isc_mem_put(mctx, client, sizeof(*client));
  372. return (result);
  373. }
  374. client->actx = actx;
  375. client->taskmgr = taskmgr;
  376. client->socketmgr = socketmgr;
  377. client->timermgr = timermgr;
  378. client->task = NULL;
  379. result = isc_task_create(client->taskmgr, 0, &client->task);
  380. if (result != ISC_R_SUCCESS)
  381. goto cleanup;
  382. result = dns_dispatchmgr_create(mctx, NULL, &dispatchmgr);
  383. if (result != ISC_R_SUCCESS)
  384. goto cleanup;
  385. client->dispatchmgr = dispatchmgr;
  386. /* TODO: whether to use dispatch v4 or v6 should be configurable */
  387. client->dispatchv4 = NULL;
  388. client->dispatchv6 = NULL;
  389. result = getudpdispatch(AF_INET, dispatchmgr, socketmgr,
  390. taskmgr, ISC_TRUE, &dispatchv4);
  391. if (result == ISC_R_SUCCESS)
  392. client->dispatchv4 = dispatchv4;
  393. result = getudpdispatch(AF_INET6, dispatchmgr, socketmgr,
  394. taskmgr, ISC_TRUE, &dispatchv6);
  395. if (result == ISC_R_SUCCESS)
  396. client->dispatchv6 = dispatchv6;
  397. /* We need at least one of the dispatchers */
  398. if (dispatchv4 == NULL && dispatchv6 == NULL) {
  399. INSIST(result != ISC_R_SUCCESS);
  400. goto cleanup;
  401. }
  402. /* Create the default view for class IN */
  403. result = dns_client_createview(mctx, dns_rdataclass_in, options,
  404. taskmgr, 31, socketmgr, timermgr,
  405. dispatchmgr, dispatchv4, dispatchv6,
  406. &view);
  407. if (result != ISC_R_SUCCESS)
  408. goto cleanup;
  409. ISC_LIST_INIT(client->viewlist);
  410. ISC_LIST_APPEND(client->viewlist, view, link);
  411. dns_view_freeze(view); /* too early? */
  412. ISC_LIST_INIT(client->resctxs);
  413. ISC_LIST_INIT(client->reqctxs);
  414. ISC_LIST_INIT(client->updatectxs);
  415. client->mctx = NULL;
  416. isc_mem_attach(mctx, &client->mctx);
  417. client->update_timeout = DEF_UPDATE_TIMEOUT;
  418. client->update_udptimeout = DEF_UPDATE_UDPTIMEOUT;
  419. client->update_udpretries = DEF_UPDATE_UDPRETRIES;
  420. client->find_timeout = DEF_FIND_TIMEOUT;
  421. client->find_udpretries = DEF_FIND_UDPRETRIES;
  422. client->references = 1;
  423. client->magic = DNS_CLIENT_MAGIC;
  424. *clientp = client;
  425. return (ISC_R_SUCCESS);
  426. cleanup:
  427. if (dispatchv4 != NULL)
  428. dns_dispatch_detach(&dispatchv4);
  429. if (dispatchv6 != NULL)
  430. dns_dispatch_detach(&dispatchv6);
  431. if (dispatchmgr != NULL)
  432. dns_dispatchmgr_destroy(&dispatchmgr);
  433. if (client->task != NULL)
  434. isc_task_detach(&client->task);
  435. isc_mem_put(mctx, client, sizeof(*client));
  436. return (result);
  437. }
  438. static void
  439. destroyclient(dns_client_t **clientp) {
  440. dns_client_t *client = *clientp;
  441. dns_view_t *view;
  442. while ((view = ISC_LIST_HEAD(client->viewlist)) != NULL) {
  443. ISC_LIST_UNLINK(client->viewlist, view, link);
  444. dns_view_detach(&view);
  445. }
  446. if (client->dispatchv4 != NULL)
  447. dns_dispatch_detach(&client->dispatchv4);
  448. if (client->dispatchv6 != NULL)
  449. dns_dispatch_detach(&client->dispatchv6);
  450. dns_dispatchmgr_destroy(&client->dispatchmgr);
  451. isc_task_detach(&client->task);
  452. /*
  453. * If the client has created its own running environments,
  454. * destroy them.
  455. */
  456. if ((client->attributes & DNS_CLIENTATTR_OWNCTX) != 0) {
  457. isc_taskmgr_destroy(&client->taskmgr);
  458. isc_timermgr_destroy(&client->timermgr);
  459. isc_socketmgr_destroy(&client->socketmgr);
  460. isc_app_ctxfinish(client->actx);
  461. isc_appctx_destroy(&client->actx);
  462. }
  463. DESTROYLOCK(&client->lock);
  464. client->magic = 0;
  465. isc_mem_putanddetach(&client->mctx, client, sizeof(*client));
  466. *clientp = NULL;
  467. }
  468. void
  469. dns_client_destroy(dns_client_t **clientp) {
  470. dns_client_t *client;
  471. isc_boolean_t destroyok = ISC_FALSE;
  472. REQUIRE(clientp != NULL);
  473. client = *clientp;
  474. REQUIRE(DNS_CLIENT_VALID(client));
  475. LOCK(&client->lock);
  476. client->references--;
  477. if (client->references == 0 && ISC_LIST_EMPTY(client->resctxs) &&
  478. ISC_LIST_EMPTY(client->reqctxs) &&
  479. ISC_LIST_EMPTY(client->updatectxs)) {
  480. destroyok = ISC_TRUE;
  481. }
  482. UNLOCK(&client->lock);
  483. if (destroyok)
  484. destroyclient(&client);
  485. *clientp = NULL;
  486. }
  487. isc_result_t
  488. dns_client_setservers(dns_client_t *client, dns_rdataclass_t rdclass,
  489. dns_name_t *namespace, isc_sockaddrlist_t *addrs)
  490. {
  491. isc_result_t result;
  492. dns_view_t *view = NULL;
  493. REQUIRE(DNS_CLIENT_VALID(client));
  494. REQUIRE(addrs != NULL);
  495. if (namespace == NULL)
  496. namespace = dns_rootname;
  497. LOCK(&client->lock);
  498. result = dns_viewlist_find(&client->viewlist, DNS_CLIENTVIEW_NAME,
  499. rdclass, &view);
  500. if (result != ISC_R_SUCCESS) {
  501. UNLOCK(&client->lock);
  502. return (result);
  503. }
  504. UNLOCK(&client->lock);
  505. result = dns_fwdtable_add(view->fwdtable, namespace, addrs,
  506. dns_fwdpolicy_only);
  507. dns_view_detach(&view);
  508. return (result);
  509. }
  510. isc_result_t
  511. dns_client_clearservers(dns_client_t *client, dns_rdataclass_t rdclass,
  512. dns_name_t *namespace)
  513. {
  514. isc_result_t result;
  515. dns_view_t *view = NULL;
  516. REQUIRE(DNS_CLIENT_VALID(client));
  517. if (namespace == NULL)
  518. namespace = dns_rootname;
  519. LOCK(&client->lock);
  520. result = dns_viewlist_find(&client->viewlist, DNS_CLIENTVIEW_NAME,
  521. rdclass, &view);
  522. if (result != ISC_R_SUCCESS) {
  523. UNLOCK(&client->lock);
  524. return (result);
  525. }
  526. UNLOCK(&client->lock);
  527. result = dns_fwdtable_delete(view->fwdtable, namespace);
  528. dns_view_detach(&view);
  529. return (result);
  530. }
  531. static isc_result_t
  532. getrdataset(isc_mem_t *mctx, dns_rdataset_t **rdatasetp) {
  533. dns_rdataset_t *rdataset;
  534. REQUIRE(mctx != NULL);
  535. REQUIRE(rdatasetp != NULL && *rdatasetp == NULL);
  536. rdataset = isc_mem_get(mctx, sizeof(*rdataset));
  537. if (rdataset == NULL)
  538. return (ISC_R_NOMEMORY);
  539. dns_rdataset_init(rdataset);
  540. *rdatasetp = rdataset;
  541. return (ISC_R_SUCCESS);
  542. }
  543. static void
  544. putrdataset(isc_mem_t *mctx, dns_rdataset_t **rdatasetp) {
  545. dns_rdataset_t *rdataset;
  546. REQUIRE(rdatasetp != NULL);
  547. rdataset = *rdatasetp;
  548. REQUIRE(rdataset != NULL);
  549. if (dns_rdataset_isassociated(rdataset))
  550. dns_rdataset_disassociate(rdataset);
  551. isc_mem_put(mctx, rdataset, sizeof(*rdataset));
  552. *rdatasetp = NULL;
  553. }
  554. static void
  555. fetch_done(isc_task_t *task, isc_event_t *event) {
  556. resctx_t *rctx = event->ev_arg;
  557. dns_fetchevent_t *fevent;
  558. REQUIRE(event->ev_type == DNS_EVENT_FETCHDONE);
  559. REQUIRE(RCTX_VALID(rctx));
  560. REQUIRE(rctx->task == task);
  561. fevent = (dns_fetchevent_t *)event;
  562. client_resfind(rctx, fevent);
  563. }
  564. static inline isc_result_t
  565. start_fetch(resctx_t *rctx) {
  566. isc_result_t result;
  567. /*
  568. * The caller must be holding the rctx's lock.
  569. */
  570. REQUIRE(rctx->fetch == NULL);
  571. result = dns_resolver_createfetch(rctx->view->resolver,
  572. dns_fixedname_name(&rctx->name),
  573. rctx->type,
  574. NULL, NULL, NULL, 0,
  575. rctx->task, fetch_done, rctx,
  576. rctx->rdataset,
  577. rctx->sigrdataset,
  578. &rctx->fetch);
  579. return (result);
  580. }
  581. static isc_result_t
  582. view_find(resctx_t *rctx, dns_db_t **dbp, dns_dbnode_t **nodep,
  583. dns_name_t *foundname)
  584. {
  585. isc_result_t result;
  586. dns_name_t *name = dns_fixedname_name(&rctx->name);
  587. dns_rdatatype_t type;
  588. if (rctx->type == dns_rdatatype_rrsig)
  589. type = dns_rdatatype_any;
  590. else
  591. type = rctx->type;
  592. result = dns_view_find(rctx->view, name, type, 0, 0, ISC_FALSE,
  593. dbp, nodep, foundname, rctx->rdataset,
  594. rctx->sigrdataset);
  595. return (result);
  596. }
  597. static void
  598. client_resfind(resctx_t *rctx, dns_fetchevent_t *event) {
  599. isc_mem_t *mctx;
  600. isc_result_t tresult, result = ISC_R_SUCCESS;
  601. isc_result_t vresult = ISC_R_SUCCESS;
  602. isc_boolean_t want_restart;
  603. isc_boolean_t send_event = ISC_FALSE;
  604. dns_name_t *name, *prefix;
  605. dns_fixedname_t foundname, fixed;
  606. dns_rdataset_t *trdataset;
  607. dns_rdata_t rdata = DNS_RDATA_INIT;
  608. unsigned int nlabels;
  609. int order;
  610. dns_namereln_t namereln;
  611. dns_rdata_cname_t cname;
  612. dns_rdata_dname_t dname;
  613. REQUIRE(RCTX_VALID(rctx));
  614. LOCK(&rctx->lock);
  615. mctx = rctx->view->mctx;
  616. name = dns_fixedname_name(&rctx->name);
  617. do {
  618. dns_name_t *fname = NULL;
  619. dns_name_t *ansname = NULL;
  620. dns_db_t *db = NULL;
  621. dns_dbnode_t *node = NULL;
  622. rctx->restarts++;
  623. want_restart = ISC_FALSE;
  624. if (event == NULL && !rctx->canceled) {
  625. dns_fixedname_init(&foundname);
  626. fname = dns_fixedname_name(&foundname);
  627. INSIST(!dns_rdataset_isassociated(rctx->rdataset));
  628. INSIST(rctx->sigrdataset == NULL ||
  629. !dns_rdataset_isassociated(rctx->sigrdataset));
  630. result = view_find(rctx, &db, &node, fname);
  631. if (result == ISC_R_NOTFOUND) {
  632. /*
  633. * We don't know anything about the name.
  634. * Launch a fetch.
  635. */
  636. if (node != NULL) {
  637. INSIST(db != NULL);
  638. dns_db_detachnode(db, &node);
  639. }
  640. if (db != NULL)
  641. dns_db_detach(&db);
  642. result = start_fetch(rctx);
  643. if (result != ISC_R_SUCCESS) {
  644. putrdataset(mctx, &rctx->rdataset);
  645. if (rctx->sigrdataset != NULL)
  646. putrdataset(mctx,
  647. &rctx->sigrdataset);
  648. send_event = ISC_TRUE;
  649. }
  650. goto done;
  651. }
  652. } else {
  653. INSIST(event != NULL);
  654. INSIST(event->fetch == rctx->fetch);
  655. dns_resolver_destroyfetch(&rctx->fetch);
  656. db = event->db;
  657. node = event->node;
  658. result = event->result;
  659. vresult = event->vresult;
  660. fname = dns_fixedname_name(&event->foundname);
  661. INSIST(event->rdataset == rctx->rdataset);
  662. INSIST(event->sigrdataset == rctx->sigrdataset);
  663. }
  664. /*
  665. * If we've been canceled, forget about the result.
  666. */
  667. if (rctx->canceled)
  668. result = ISC_R_CANCELED;
  669. else {
  670. /*
  671. * Otherwise, get some resource for copying the
  672. * result.
  673. */
  674. ansname = isc_mem_get(mctx, sizeof(*ansname));
  675. if (ansname == NULL)
  676. tresult = ISC_R_NOMEMORY;
  677. else {
  678. dns_name_t *aname;
  679. aname = dns_fixedname_name(&rctx->name);
  680. dns_name_init(ansname, NULL);
  681. tresult = dns_name_dup(aname, mctx, ansname);
  682. if (tresult != ISC_R_SUCCESS)
  683. isc_mem_put(mctx, ansname,
  684. sizeof(*ansname));
  685. }
  686. if (tresult != ISC_R_SUCCESS)
  687. result = tresult;
  688. }
  689. switch (result) {
  690. case ISC_R_SUCCESS:
  691. send_event = ISC_TRUE;
  692. /*
  693. * This case is handled in the main line below.
  694. */
  695. break;
  696. case DNS_R_CNAME:
  697. /*
  698. * Add the CNAME to the answer list.
  699. */
  700. trdataset = rctx->rdataset;
  701. ISC_LIST_APPEND(ansname->list, rctx->rdataset, link);
  702. rctx->rdataset = NULL;
  703. if (rctx->sigrdataset != NULL) {
  704. ISC_LIST_APPEND(ansname->list,
  705. rctx->sigrdataset, link);
  706. rctx->sigrdataset = NULL;
  707. }
  708. ISC_LIST_APPEND(rctx->namelist, ansname, link);
  709. ansname = NULL;
  710. /*
  711. * Copy the CNAME's target into the lookup's
  712. * query name and start over.
  713. */
  714. tresult = dns_rdataset_first(trdataset);
  715. if (tresult != ISC_R_SUCCESS)
  716. goto done;
  717. dns_rdataset_current(trdataset, &rdata);
  718. tresult = dns_rdata_tostruct(&rdata, &cname, NULL);
  719. dns_rdata_reset(&rdata);
  720. if (tresult != ISC_R_SUCCESS)
  721. goto done;
  722. tresult = dns_name_copy(&cname.cname, name, NULL);
  723. dns_rdata_freestruct(&cname);
  724. if (tresult == ISC_R_SUCCESS)
  725. want_restart = ISC_TRUE;
  726. else
  727. result = tresult;
  728. goto done;
  729. case DNS_R_DNAME:
  730. /*
  731. * Add the DNAME to the answer list.
  732. */
  733. trdataset = rctx->rdataset;
  734. ISC_LIST_APPEND(ansname->list, rctx->rdataset, link);
  735. rctx->rdataset = NULL;
  736. if (rctx->sigrdataset != NULL) {
  737. ISC_LIST_APPEND(ansname->list,
  738. rctx->sigrdataset, link);
  739. rctx->sigrdataset = NULL;
  740. }
  741. ISC_LIST_APPEND(rctx->namelist, ansname, link);
  742. ansname = NULL;
  743. namereln = dns_name_fullcompare(name, fname, &order,
  744. &nlabels);
  745. INSIST(namereln == dns_namereln_subdomain);
  746. /*
  747. * Get the target name of the DNAME.
  748. */
  749. tresult = dns_rdataset_first(trdataset);
  750. if (tresult != ISC_R_SUCCESS) {
  751. result = tresult;
  752. goto done;
  753. }
  754. dns_rdataset_current(trdataset, &rdata);
  755. tresult = dns_rdata_tostruct(&rdata, &dname, NULL);
  756. dns_rdata_reset(&rdata);
  757. if (tresult != ISC_R_SUCCESS) {
  758. result = tresult;
  759. goto done;
  760. }
  761. /*
  762. * Construct the new query name and start over.
  763. */
  764. dns_fixedname_init(&fixed);
  765. prefix = dns_fixedname_name(&fixed);
  766. dns_name_split(name, nlabels, prefix, NULL);
  767. tresult = dns_name_concatenate(prefix, &dname.dname,
  768. name, NULL);
  769. dns_rdata_freestruct(&dname);
  770. if (tresult == ISC_R_SUCCESS)
  771. want_restart = ISC_TRUE;
  772. else
  773. result = tresult;
  774. goto done;
  775. case DNS_R_NCACHENXDOMAIN:
  776. case DNS_R_NCACHENXRRSET:
  777. ISC_LIST_APPEND(ansname->list, rctx->rdataset, link);
  778. ISC_LIST_APPEND(rctx->namelist, ansname, link);
  779. ansname = NULL;
  780. rctx->rdataset = NULL;
  781. /* What about sigrdataset? */
  782. if (rctx->sigrdataset != NULL)
  783. putrdataset(mctx, &rctx->sigrdataset);
  784. send_event = ISC_TRUE;
  785. goto done;
  786. default:
  787. if (rctx->rdataset != NULL)
  788. putrdataset(mctx, &rctx->rdataset);
  789. if (rctx->sigrdataset != NULL)
  790. putrdataset(mctx, &rctx->sigrdataset);
  791. send_event = ISC_TRUE;
  792. goto done;
  793. }
  794. if (rctx->type == dns_rdatatype_any) {
  795. int n = 0;
  796. dns_rdatasetiter_t *rdsiter = NULL;
  797. tresult = dns_db_allrdatasets(db, node, NULL, 0,
  798. &rdsiter);
  799. if (tresult != ISC_R_SUCCESS) {
  800. result = tresult;
  801. goto done;
  802. }
  803. tresult = dns_rdatasetiter_first(rdsiter);
  804. while (tresult == ISC_R_SUCCESS) {
  805. dns_rdatasetiter_current(rdsiter,
  806. rctx->rdataset);
  807. if (rctx->rdataset->type != 0) {
  808. ISC_LIST_APPEND(ansname->list,
  809. rctx->rdataset,
  810. link);
  811. n++;
  812. rctx->rdataset = NULL;
  813. } else {
  814. /*
  815. * We're not interested in this
  816. * rdataset.
  817. */
  818. dns_rdataset_disassociate(
  819. rctx->rdataset);
  820. }
  821. tresult = dns_rdatasetiter_next(rdsiter);
  822. if (tresult == ISC_R_SUCCESS &&
  823. rctx->rdataset == NULL) {
  824. tresult = getrdataset(mctx,
  825. &rctx->rdataset);
  826. if (tresult != ISC_R_SUCCESS) {
  827. result = tresult;
  828. POST(result);
  829. break;
  830. }
  831. }
  832. }
  833. if (n == 0) {
  834. /*
  835. * We didn't match any rdatasets (which means
  836. * something went wrong in this
  837. * implementation).
  838. */
  839. result = DNS_R_SERVFAIL; /* better code? */
  840. POST(result);
  841. } else {
  842. ISC_LIST_APPEND(rctx->namelist, ansname, link);
  843. ansname = NULL;
  844. }
  845. dns_rdatasetiter_destroy(&rdsiter);
  846. if (tresult != ISC_R_NOMORE)
  847. result = DNS_R_SERVFAIL; /* ditto */
  848. else
  849. result = ISC_R_SUCCESS;
  850. goto done;
  851. } else {
  852. /*
  853. * This is the "normal" case -- an ordinary question
  854. * to which we've got the answer.
  855. */
  856. ISC_LIST_APPEND(ansname->list, rctx->rdataset, link);
  857. rctx->rdataset = NULL;
  858. if (rctx->sigrdataset != NULL) {
  859. ISC_LIST_APPEND(ansname->list,
  860. rctx->sigrdataset, link);
  861. rctx->sigrdataset = NULL;
  862. }
  863. ISC_LIST_APPEND(rctx->namelist, ansname, link);
  864. ansname = NULL;
  865. }
  866. done:
  867. /*
  868. * Free temporary resources
  869. */
  870. if (ansname != NULL) {
  871. dns_rdataset_t *rdataset;
  872. while ((rdataset = ISC_LIST_HEAD(ansname->list))
  873. != NULL) {
  874. ISC_LIST_UNLINK(ansname->list, rdataset, link);
  875. putrdataset(mctx, &rdataset);
  876. }
  877. dns_name_free(ansname, mctx);
  878. isc_mem_put(mctx, ansname, sizeof(*ansname));
  879. }
  880. if (node != NULL)
  881. dns_db_detachnode(db, &node);
  882. if (db != NULL)
  883. dns_db_detach(&db);
  884. if (event != NULL)
  885. isc_event_free(ISC_EVENT_PTR(&event));
  886. /*
  887. * Limit the number of restarts.
  888. */
  889. if (want_restart && rctx->restarts == MAX_RESTARTS) {
  890. want_restart = ISC_FALSE;
  891. result = ISC_R_QUOTA;
  892. send_event = ISC_TRUE;
  893. }
  894. /*
  895. * Prepare further find with new resources
  896. */
  897. if (want_restart) {
  898. INSIST(rctx->rdataset == NULL &&
  899. rctx->sigrdataset == NULL);
  900. result = getrdataset(mctx, &rctx->rdataset);
  901. if (result == ISC_R_SUCCESS && rctx->want_dnssec) {
  902. result = getrdataset(mctx, &rctx->sigrdataset);
  903. if (result != ISC_R_SUCCESS) {
  904. putrdataset(mctx, &rctx->rdataset);
  905. }
  906. }
  907. if (result != ISC_R_SUCCESS) {
  908. want_restart = ISC_FALSE;
  909. send_event = ISC_TRUE;
  910. }
  911. }
  912. } while (want_restart);
  913. if (send_event) {
  914. isc_task_t *task;
  915. while ((name = ISC_LIST_HEAD(rctx->namelist)) != NULL) {
  916. ISC_LIST_UNLINK(rctx->namelist, name, link);
  917. ISC_LIST_APPEND(rctx->event->answerlist, name, link);
  918. }
  919. rctx->event->result = result;
  920. rctx->event->vresult = vresult;
  921. task = rctx->event->ev_sender;
  922. rctx->event->ev_sender = rctx;
  923. isc_task_sendanddetach(&task, ISC_EVENT_PTR(&rctx->event));
  924. }
  925. UNLOCK(&rctx->lock);
  926. }
  927. static void
  928. resolve_done(isc_task_t *task, isc_event_t *event) {
  929. resarg_t *resarg = event->ev_arg;
  930. dns_clientresevent_t *rev = (dns_clientresevent_t *)event;
  931. dns_name_t *name;
  932. UNUSED(task);
  933. LOCK(&resarg->lock);
  934. resarg->result = rev->result;
  935. resarg->vresult = rev->vresult;
  936. while ((name = ISC_LIST_HEAD(rev->answerlist)) != NULL) {
  937. ISC_LIST_UNLINK(rev->answerlist, name, link);
  938. ISC_LIST_APPEND(*resarg->namelist, name, link);
  939. }
  940. dns_client_destroyrestrans(&resarg->trans);
  941. isc_event_free(&event);
  942. if (!resarg->canceled) {
  943. UNLOCK(&resarg->lock);
  944. /* Exit from the internal event loop */
  945. isc_app_ctxsuspend(resarg->actx);
  946. } else {
  947. /*
  948. * We have already exited from the loop (due to some
  949. * unexpected event). Just clean the arg up.
  950. */
  951. UNLOCK(&resarg->lock);
  952. DESTROYLOCK(&resarg->lock);
  953. isc_mem_put(resarg->client->mctx, resarg, sizeof(*resarg));
  954. }
  955. }
  956. isc_result_t
  957. dns_client_resolve(dns_client_t *client, dns_name_t *name,
  958. dns_rdataclass_t rdclass, dns_rdatatype_t type,
  959. unsigned int options, dns_namelist_t *namelist)
  960. {
  961. isc_result_t result;
  962. isc_appctx_t *actx;
  963. resarg_t *resarg;
  964. REQUIRE(DNS_CLIENT_VALID(client));
  965. REQUIRE(namelist != NULL && ISC_LIST_EMPTY(*namelist));
  966. if ((client->attributes & DNS_CLIENTATTR_OWNCTX) == 0 &&
  967. (options & DNS_CLIENTRESOPT_ALLOWRUN) == 0) {
  968. /*
  969. * If the client is run under application's control, we need
  970. * to create a new running (sub)environment for this
  971. * particular resolution.
  972. */
  973. return (ISC_R_NOTIMPLEMENTED); /* XXXTBD */
  974. } else
  975. actx = client->actx;
  976. resarg = isc_mem_get(client->mctx, sizeof(*resarg));
  977. if (resarg == NULL)
  978. return (ISC_R_NOMEMORY);
  979. result = isc_mutex_init(&resarg->lock);
  980. if (result != ISC_R_SUCCESS) {
  981. isc_mem_put(client->mctx, resarg, sizeof(*resarg));
  982. return (result);
  983. }
  984. resarg->actx = actx;
  985. resarg->client = client;
  986. resarg->result = DNS_R_SERVFAIL;
  987. resarg->namelist = namelist;
  988. resarg->trans = NULL;
  989. resarg->canceled = ISC_FALSE;
  990. result = dns_client_startresolve(client, name, rdclass, type, options,
  991. client->task, resolve_done, resarg,
  992. &resarg->trans);
  993. if (result != ISC_R_SUCCESS) {
  994. DESTROYLOCK(&resarg->lock);
  995. isc_mem_put(client->mctx, resarg, sizeof(*resarg));
  996. return (result);
  997. }
  998. /*
  999. * Start internal event loop. It blocks until the entire process
  1000. * is completed.
  1001. */
  1002. result = isc_app_ctxrun(actx);
  1003. LOCK(&resarg->lock);
  1004. if (result == ISC_R_SUCCESS || result == ISC_R_SUSPEND)
  1005. result = resarg->result;
  1006. if (result != ISC_R_SUCCESS && resarg->vresult != ISC_R_SUCCESS) {
  1007. /*
  1008. * If this lookup failed due to some error in DNSSEC
  1009. * validation, return the validation error code.
  1010. * XXX: or should we pass the validation result separately?
  1011. */
  1012. result = resarg->vresult;
  1013. }
  1014. if (resarg->trans != NULL) {
  1015. /*
  1016. * Unusual termination (perhaps due to signal). We need some
  1017. * tricky cleanup process.
  1018. */
  1019. resarg->canceled = ISC_TRUE;
  1020. dns_client_cancelresolve(resarg->trans);
  1021. UNLOCK(&resarg->lock);
  1022. /* resarg will be freed in the event handler. */
  1023. } else {
  1024. UNLOCK(&resarg->lock);
  1025. DESTROYLOCK(&resarg->lock);
  1026. isc_mem_put(client->mctx, resarg, sizeof(*resarg));
  1027. }
  1028. return (result);
  1029. }
  1030. isc_result_t
  1031. dns_client_startresolve(dns_client_t *client, dns_name_t *name,
  1032. dns_rdataclass_t rdclass, dns_rdatatype_t type,
  1033. unsigned int options, isc_task_t *task,
  1034. isc_taskaction_t action, void *arg,
  1035. dns_clientrestrans_t **transp)
  1036. {
  1037. dns_view_t *view = NULL;
  1038. dns_clientresevent_t *event = NULL;
  1039. resctx_t *rctx = NULL;
  1040. isc_task_t *clone = NULL;
  1041. isc_mem_t *mctx;
  1042. isc_result_t result;
  1043. dns_rdataset_t *rdataset, *sigrdataset;
  1044. isc_boolean_t want_dnssec;
  1045. REQUIRE(DNS_CLIENT_VALID(client));
  1046. REQUIRE(transp != NULL && *transp == NULL);
  1047. LOCK(&client->lock);
  1048. result = dns_viewlist_find(&client->viewlist, DNS_CLIENTVIEW_NAME,
  1049. rdclass, &view);
  1050. UNLOCK(&client->lock);
  1051. if (result != ISC_R_SUCCESS)
  1052. return (result);
  1053. mctx = client->mctx;
  1054. rdataset = NULL;
  1055. sigrdataset = NULL;
  1056. want_dnssec = ISC_TF((options & DNS_CLIENTRESOPT_NODNSSEC) == 0);
  1057. /*
  1058. * Prepare some intermediate resources
  1059. */
  1060. clone = NULL;
  1061. isc_task_attach(task, &clone);
  1062. event = (dns_clientresevent_t *)
  1063. isc_event_allocate(mctx, clone, DNS_EVENT_CLIENTRESDONE,
  1064. action, arg, sizeof(*event));
  1065. if (event == NULL) {
  1066. result = ISC_R_NOMEMORY;
  1067. goto cleanup;
  1068. }
  1069. event->result = DNS_R_SERVFAIL;
  1070. ISC_LIST_INIT(event->answerlist);
  1071. rctx = isc_mem_get(mctx, sizeof(*rctx));
  1072. if (rctx == NULL)
  1073. result = ISC_R_NOMEMORY;
  1074. else {
  1075. result = isc_mutex_init(&rctx->lock);
  1076. if (result != ISC_R_SUCCESS) {
  1077. isc_mem_put(mctx, rctx, sizeof(*rctx));
  1078. rctx = NULL;
  1079. }
  1080. }
  1081. if (result != ISC_R_SUCCESS)
  1082. goto cleanup;
  1083. result = getrdataset(mctx, &rdataset);
  1084. if (result != ISC_R_SUCCESS)
  1085. goto cleanup;
  1086. rctx->rdataset = rdataset;
  1087. if (want_dnssec) {
  1088. result = getrdataset(mctx, &sigrdataset);
  1089. if (result != ISC_R_SUCCESS)
  1090. goto cleanup;
  1091. }
  1092. rctx->sigrdataset = sigrdataset;
  1093. dns_fixedname_init(&rctx->name);
  1094. result = dns_name_copy(name, dns_fixedname_name(&rctx->name), NULL);
  1095. if (result != ISC_R_SUCCESS)
  1096. goto cleanup;
  1097. rctx->client = client;
  1098. ISC_LINK_INIT(rctx, link);
  1099. rctx->canceled = ISC_FALSE;
  1100. rctx->task = client->task;
  1101. rctx->type = type;
  1102. rctx->view = view;
  1103. rctx->restarts = 0;
  1104. rctx->fetch = NULL;
  1105. rctx->want_dnssec = want_dnssec;
  1106. ISC_LIST_INIT(rctx->namelist);
  1107. rctx->event = event;
  1108. rctx->magic = RCTX_MAGIC;
  1109. LOCK(&client->lock);
  1110. ISC_LIST_APPEND(client->resctxs, rctx, link);
  1111. UNLOCK(&client->lock);
  1112. client_resfind(rctx, NULL);
  1113. *transp = (dns_clientrestrans_t *)rctx;
  1114. return (ISC_R_SUCCESS);
  1115. cleanup:
  1116. if (rdataset != NULL)
  1117. putrdataset(client->mctx, &rdataset);
  1118. if (sigrdataset != NULL)
  1119. putrdataset(client->mctx, &sigrdataset);
  1120. if (rctx != NULL) {
  1121. DESTROYLOCK(&rctx->lock);
  1122. isc_mem_put(mctx, rctx, sizeof(*rctx));
  1123. }
  1124. if (event != NULL)
  1125. isc_event_free(ISC_EVENT_PTR(&event));
  1126. isc_task_detach(&clone);
  1127. dns_view_detach(&view);
  1128. return (result);
  1129. }
  1130. void
  1131. dns_client_cancelresolve(dns_clientrestrans_t *trans) {
  1132. resctx_t *rctx;
  1133. REQUIRE(trans != NULL);
  1134. rctx = (resctx_t *)trans;
  1135. REQUIRE(RCTX_VALID(rctx));
  1136. LOCK(&rctx->lock);
  1137. if (!rctx->canceled) {
  1138. rctx->canceled = ISC_TRUE;
  1139. if (rctx->fetch != NULL)
  1140. dns_resolver_cancelfetch(rctx->fetch);
  1141. }
  1142. UNLOCK(&rctx->lock);
  1143. }
  1144. void
  1145. dns_client_freeresanswer(dns_client_t *client, dns_namelist_t *namelist) {
  1146. dns_name_t *name;
  1147. dns_rdataset_t *rdataset;
  1148. REQUIRE(DNS_CLIENT_VALID(client));
  1149. REQUIRE(namelist != NULL);
  1150. while ((name = ISC_LIST_HEAD(*namelist)) != NULL) {
  1151. ISC_LIST_UNLINK(*namelist, name, link);
  1152. while ((rdataset = ISC_LIST_HEAD(name->list)) != NULL) {
  1153. ISC_LIST_UNLINK(name->list, rdataset, link);
  1154. putrdataset(client->mctx, &rdataset);
  1155. }
  1156. dns_name_free(name, client->mctx);
  1157. isc_mem_put(client->mctx, name, sizeof(*name));
  1158. }
  1159. }
  1160. void
  1161. dns_client_destroyrestrans(dns_clientrestrans_t **transp) {
  1162. resctx_t *rctx;
  1163. isc_mem_t *mctx;
  1164. dns_client_t *client;
  1165. isc_boolean_t need_destroyclient = ISC_FALSE;
  1166. REQUIRE(transp != NULL);
  1167. rctx = (resctx_t *)*transp;
  1168. REQUIRE(RCTX_VALID(rctx));
  1169. REQUIRE(rctx->fetch == NULL);
  1170. REQUIRE(rctx->event == NULL);
  1171. client = rctx->client;
  1172. REQUIRE(DNS_CLIENT_VALID(client));
  1173. mctx = client->mctx;
  1174. dns_view_detach(&rctx->view);
  1175. LOCK(&client->lock);
  1176. INSIST(ISC_LINK_LINKED(rctx, link));
  1177. ISC_LIST_UNLINK(client->resctxs, rctx, link);
  1178. if (client->references == 0 && ISC_LIST_EMPTY(client->resctxs) &&
  1179. ISC_LIST_EMPTY(client->reqctxs) &&
  1180. ISC_LIST_EMPTY(client->updatectxs))
  1181. need_destroyclient = ISC_TRUE;
  1182. UNLOCK(&client->lock);
  1183. INSIST(ISC_LIST_EMPTY(rctx->namelist));
  1184. DESTROYLOCK(&rctx->lock);
  1185. rctx->magic = 0;
  1186. isc_mem_put(mctx, rctx, sizeof(*rctx));
  1187. if (need_destroyclient)
  1188. destroyclient(&client);
  1189. *transp = NULL;
  1190. }
  1191. isc_result_t
  1192. dns_client_addtrustedkey(dns_client_t *client, dns_rdataclass_t rdclass,
  1193. dns_name_t *keyname, isc_buffer_t *keydatabuf)
  1194. {
  1195. isc_result_t result;
  1196. dns_view_t *view = NULL;
  1197. dst_key_t *dstkey = NULL;
  1198. dns_keytable_t *secroots = NULL;
  1199. REQUIRE(DNS_CLIENT_VALID(client));
  1200. LOCK(&client->lock);
  1201. result = dns_viewlist_find(&client->viewlist, DNS_CLIENTVIEW_NAME,
  1202. rdclass, &view);
  1203. UNLOCK(&client->lock);
  1204. if (result != ISC_R_SUCCESS)
  1205. goto cleanup;
  1206. result = dns_view_getsecroots(view, &secroots);
  1207. if (result != ISC_R_SUCCESS)
  1208. goto cleanup;
  1209. result = dst_key_fromdns(keyname, rdclass, keydatabuf, client->mctx,
  1210. &dstkey);
  1211. if (result != ISC_R_SUCCESS)
  1212. goto cleanup;
  1213. result = dns_keytable_add(secroots, ISC_FALSE, &dstkey);
  1214. cleanup:
  1215. if (dstkey != NULL)
  1216. dst_key_free(&dstkey);
  1217. if (view != NULL)
  1218. dns_view_detach(&view);
  1219. if (secroots != NULL)
  1220. dns_keytable_detach(&secroots);
  1221. return (result);
  1222. }
  1223. /*%
  1224. * Simple request routines
  1225. */
  1226. static void
  1227. request_done(isc_task_t *task, isc_event_t *event) {
  1228. dns_requestevent_t *reqev = NULL;
  1229. dns_request_t *request;
  1230. isc_result_t result, eresult;
  1231. reqctx_t *ctx;
  1232. UNUSED(task);
  1233. REQUIRE(event->ev_type == DNS_EVENT_REQUESTDONE);
  1234. reqev = (dns_requestevent_t *)event;
  1235. request = reqev->request;
  1236. result = eresult = reqev->result;
  1237. ctx = reqev->ev_arg;
  1238. REQUIRE(REQCTX_VALID(ctx));
  1239. isc_event_free(&event);
  1240. LOCK(&ctx->lock);
  1241. if (eresult == ISC_R_SUCCESS) {
  1242. result = dns_request_getresponse(request, ctx->event->rmessage,
  1243. ctx->parseoptions);
  1244. }
  1245. if (ctx->tsigkey != NULL)
  1246. dns_tsigkey_detach(&ctx->tsigkey);
  1247. if (ctx->canceled)
  1248. ctx->event->result = ISC_R_CANCELED;
  1249. else
  1250. ctx->event->result = result;
  1251. task = ctx->event->ev_sender;
  1252. ctx->event->ev_sender = ctx;
  1253. isc_task_sendanddetach(&task, ISC_EVENT_PTR(&ctx->event));
  1254. UNLOCK(&ctx->lock);
  1255. }
  1256. static void
  1257. localrequest_done(isc_task_t *task, isc_event_t *event) {
  1258. reqarg_t *reqarg = event->ev_arg;
  1259. dns_clientreqevent_t *rev =(dns_clientreqevent_t *)event;
  1260. UNUSED(task);
  1261. REQUIRE(event->ev_type == DNS_EVENT_CLIENTREQDONE);
  1262. LOCK(&reqarg->lock);
  1263. reqarg->result = rev->result;
  1264. dns_client_destroyreqtrans(&reqarg->trans);
  1265. isc_event_free(&event);
  1266. if (!reqarg->canceled) {
  1267. UNLOCK(&reqarg->lock);
  1268. /* Exit from the internal event loop */
  1269. isc_app_ctxsuspend(reqarg->actx);
  1270. } else {
  1271. /*
  1272. * We have already exited from the loop (due to some
  1273. * unexpected event). Just clean the arg up.
  1274. */
  1275. UNLOCK(&reqarg->lock);
  1276. DESTROYLOCK(&reqarg->lock);
  1277. isc_mem_put(reqarg->client->mctx, reqarg, sizeof(*reqarg));
  1278. }
  1279. }
  1280. isc_result_t
  1281. dns_client_request(dns_client_t *client, dns_message_t *qmessage,
  1282. dns_message_t *rmessage, isc_sockaddr_t *server,
  1283. unsigned int options, unsigned int parseoptions,
  1284. dns_tsec_t *tsec, unsigned int timeout,
  1285. unsigned int udptimeout, unsigned int udpretries)
  1286. {
  1287. isc_appctx_t *actx;
  1288. reqarg_t *reqarg;
  1289. isc_result_t result;
  1290. REQUIRE(DNS_CLIENT_VALID(client));
  1291. REQUIRE(qmessage != NULL);
  1292. REQUIRE(rmessage != NULL);
  1293. if ((client->attributes & DNS_CLIENTATTR_OWNCTX) == 0 &&
  1294. (options & DNS_CLIENTREQOPT_ALLOWRUN) == 0) {
  1295. /*
  1296. * If the client is run under application's control, we need
  1297. * to create a new running (sub)environment for this
  1298. * particular resolution.
  1299. */
  1300. return (ISC_R_NOTIMPLEMENTED); /* XXXTBD */
  1301. } else
  1302. actx = client->actx;
  1303. reqarg = isc_mem_get(client->mctx, sizeof(*reqarg));
  1304. if (reqarg == NULL)
  1305. return (ISC_R_NOMEMORY);
  1306. result = isc_mutex_init(&reqarg->lock);
  1307. if (result != ISC_R_SUCCESS) {
  1308. isc_mem_put(client->mctx, reqarg, sizeof(*reqarg));
  1309. return (result);
  1310. }
  1311. reqarg->actx = actx;
  1312. reqarg->client = client;
  1313. reqarg->trans = NULL;
  1314. reqarg->canceled = ISC_FALSE;
  1315. result = dns_client_startrequest(client, qmessage, rmessage, server,
  1316. options, parseoptions, tsec, timeout,
  1317. udptimeout, udpretries,
  1318. client->task, localrequest_done,
  1319. reqarg, &reqarg->trans);
  1320. if (result != ISC_R_SUCCESS) {
  1321. DESTROYLOCK(&reqarg->lock);
  1322. isc_mem_put(client->mctx, reqarg, sizeof(*reqarg));
  1323. return (result);
  1324. }
  1325. /*
  1326. * Start internal event loop. It blocks until the entire process
  1327. * is completed.
  1328. */
  1329. result = isc_app_ctxrun(actx);
  1330. LOCK(&reqarg->lock);
  1331. if (result == ISC_R_SUCCESS || result == ISC_R_SUSPEND)
  1332. result = reqarg->result;
  1333. if (reqarg->trans != NULL) {
  1334. /*
  1335. * Unusual termination (perhaps due to signal). We need some
  1336. * tricky cleanup process.
  1337. */
  1338. reqarg->canceled = ISC_TRUE;
  1339. dns_client_cancelresolve(reqarg->trans);
  1340. UNLOCK(&reqarg->lock);
  1341. /* reqarg will be freed in the event handler. */
  1342. } else {
  1343. UNLOCK(&reqarg->lock);
  1344. DESTROYLOCK(&reqarg->lock);
  1345. isc_mem_put(client->mctx, reqarg, sizeof(*reqarg));
  1346. }
  1347. return (result);
  1348. }
  1349. isc_result_t
  1350. dns_client_startrequest(dns_client_t *client, dns_message_t *qmessage,
  1351. dns_message_t *rmessage, isc_sockaddr_t *server,
  1352. unsigned int options, unsigned int parseoptions,
  1353. dns_tsec_t *tsec, unsigned int timeout,
  1354. unsigned int udptimeout, unsigned int udpretries,
  1355. isc_task_t *task, isc_taskaction_t action, void *arg,
  1356. dns_clientreqtrans_t **transp)
  1357. {
  1358. isc_result_t result;
  1359. dns_view_t *view = NULL;
  1360. isc_task_t *clone = NULL;
  1361. dns_clientreqevent_t *event = NULL;
  1362. reqctx_t *ctx = NULL;
  1363. dns_tsectype_t tsectype = dns_tsectype_none;
  1364. UNUSED(options);
  1365. REQUIRE(DNS_CLIENT_VALID(client));
  1366. REQUIRE(qmessage != NULL);
  1367. REQUIRE(rmessage != NULL);
  1368. REQUIRE(transp != NULL && *transp == NULL);
  1369. if (tsec != NULL) {
  1370. tsectype = dns_tsec_gettype(tsec);
  1371. if (tsectype != dns_tsectype_tsig)
  1372. return (ISC_R_NOTIMPLEMENTED); /* XXX */
  1373. }
  1374. LOCK(&client->lock);
  1375. result = dns_viewlist_find(&client->viewlist, DNS_CLIENTVIEW_NAME,
  1376. qmessage->rdclass, &view);
  1377. UNLOCK(&client->lock);
  1378. if (result != ISC_R_SUCCESS)
  1379. return (result);
  1380. clone = NULL;
  1381. isc_task_attach(task, &clone);
  1382. event = (dns_clientreqevent_t *)
  1383. isc_event_allocate(client->mctx, clone,
  1384. DNS_EVENT_CLIENTREQDONE,
  1385. action, arg, sizeof(*event));
  1386. if (event == NULL) {
  1387. result = ISC_R_NOMEMORY;
  1388. goto cleanup;
  1389. }
  1390. ctx = isc_mem_get(client->mctx, sizeof(*ctx));
  1391. if (ctx == NULL)
  1392. result = ISC_R_NOMEMORY;
  1393. else {
  1394. result = isc_mutex_init(&ctx->lock);
  1395. if (result != ISC_R_SUCCESS) {
  1396. isc_mem_put(client->mctx, ctx, sizeof(*ctx));
  1397. ctx = NULL;
  1398. }
  1399. }
  1400. if (result != ISC_R_SUCCESS)
  1401. goto cleanup;
  1402. ctx->client = client;
  1403. ISC_LINK_INIT(ctx, link);
  1404. ctx->parseoptions = parseoptions;
  1405. ctx->canceled = ISC_FALSE;
  1406. ctx->event = event;
  1407. ctx->event->rmessage = rmessage;
  1408. ctx->tsigkey = NULL;
  1409. if (tsec != NULL)
  1410. dns_tsec_getkey(tsec, &ctx->tsigkey);
  1411. ctx->magic = REQCTX_MAGIC;
  1412. LOCK(&client->lock);
  1413. ISC_LIST_APPEND(client->reqctxs, ctx, link);
  1414. UNLOCK(&client->lock);
  1415. ctx->request = NULL;
  1416. result = dns_request_createvia3(view->requestmgr, qmessage, NULL,
  1417. server, options, ctx->tsigkey,
  1418. timeout, udptimeout, udpretries,
  1419. client->task, request_done, ctx,
  1420. &ctx->request);
  1421. if (result == ISC_R_SUCCESS) {
  1422. dns_view_detach(&view);
  1423. *transp = (dns_clientreqtrans_t *)ctx;
  1424. return (ISC_R_SUCCESS);
  1425. }
  1426. cleanup:
  1427. if (ctx != NULL) {
  1428. LOCK(&client->lock);
  1429. ISC_LIST_UNLINK(client->reqctxs, ctx, link);
  1430. UNLOCK(&client->lock);
  1431. DESTROYLOCK(&ctx->lock);
  1432. isc_mem_put(client->mctx, ctx, sizeof(*ctx));
  1433. }
  1434. if (event != NULL)
  1435. isc_event_free(ISC_EVENT_PTR(&event));
  1436. isc_task_detach(&clone);
  1437. dns_view_detach(&view);
  1438. return (result);
  1439. }
  1440. void
  1441. dns_client_cancelrequest(dns_clientreqtrans_t *trans) {
  1442. reqctx_t *ctx;
  1443. REQUIRE(trans != NULL);
  1444. ctx = (reqctx_t *)trans;
  1445. REQUIRE(REQCTX_VALID(ctx));
  1446. LOCK(&ctx->lock);
  1447. if (!ctx->canceled) {
  1448. ctx->canceled = ISC_TRUE;
  1449. if (ctx->request != NULL)
  1450. dns_request_cancel(ctx->request);
  1451. }
  1452. UNLOCK(&ctx->lock);
  1453. }
  1454. void
  1455. dns_client_destroyreqtrans(dns_clientreqtrans_t **transp) {
  1456. reqctx_t *ctx;
  1457. isc_mem_t *mctx;
  1458. dns_client_t *client;
  1459. isc_boolean_t need_destroyclient = ISC_FALSE;
  1460. REQUIRE(transp != NULL);
  1461. ctx = (reqctx_t *)*transp;
  1462. REQUIRE(REQCTX_VALID(ctx));
  1463. client = ctx->client;
  1464. REQUIRE(DNS_CLIENT_VALID(client));
  1465. REQUIRE(ctx->event == NULL);
  1466. REQUIRE(ctx->request != NULL);
  1467. dns_request_destroy(&ctx->request);
  1468. mctx = client->mctx;
  1469. LOCK(&client->lock);
  1470. INSIST(ISC_LINK_LINKED(ctx, link));
  1471. ISC_LIST_UNLINK(client->reqctxs, ctx, link);
  1472. if (client->references == 0 && ISC_LIST_EMPTY(client->resctxs) &&
  1473. ISC_LIST_EMPTY(client->reqctxs) &&
  1474. ISC_LIST_EMPTY(client->updatectxs)) {
  1475. need_destroyclient = ISC_TRUE;
  1476. }
  1477. UNLOCK(&client->lock);
  1478. DESTROYLOCK(&ctx->lock);
  1479. ctx->magic = 0;
  1480. isc_mem_put(mctx, ctx, sizeof(*ctx));
  1481. if (need_destroyclient)
  1482. destroyclient(&client);
  1483. *transp = NULL;
  1484. }
  1485. /*%
  1486. * Dynamic update routines
  1487. */
  1488. static isc_result_t
  1489. rcode2result(dns_rcode_t rcode) {
  1490. /* XXX: isn't there a similar function? */
  1491. switch (rcode) {
  1492. case dns_rcode_formerr:
  1493. return (DNS_R_FORMERR);
  1494. case dns_rcode_servfail:
  1495. return (DNS_R_SERVFAIL);
  1496. case dns_rcode_nxdomain:
  1497. return (DNS_R_NXDOMAIN);
  1498. case dns_rcode_notimp:
  1499. return (DNS_R_NOTIMP);
  1500. case dns_rcode_refused:
  1501. return (DNS_R_REFUSED);
  1502. case dns_rcode_yxdomain:
  1503. return (DNS_R_YXDOMAIN);
  1504. case dns_rcode_yxrrset:
  1505. return (DNS_R_YXRRSET);
  1506. case dns_rcode_nxrrset:
  1507. return (DNS_R_NXRRSET);
  1508. case dns_rcode_notauth:
  1509. return (DNS_R_NOTAUTH);
  1510. case dns_rcode_notzone:
  1511. return (DNS_R_NOTZONE);
  1512. case dns_rcode_badvers:
  1513. return (DNS_R_BADVERS);
  1514. }
  1515. return (ISC_R_FAILURE);
  1516. }
  1517. static void
  1518. update_sendevent(updatectx_t *uctx, isc_result_t result) {
  1519. isc_task_t *task;
  1520. dns_message_destroy(&uctx->updatemsg);
  1521. if (uctx->tsigkey != NULL)
  1522. dns_tsigkey_detach(&uctx->tsigkey);
  1523. if (uctx->sig0key != NULL)
  1524. dst_key_free(&uctx->sig0key);
  1525. if (uctx->canceled)
  1526. uctx->event->result = ISC_R_CANCELED;
  1527. else
  1528. uctx->event->result = result;
  1529. uctx->event->state = uctx->state;
  1530. task = uctx->event->ev_sender;
  1531. uctx->event->ev_sender = uctx;
  1532. isc_task_sendanddetach(&task, ISC_EVENT_PTR(&uctx->event));
  1533. }
  1534. static void
  1535. update_done(isc_task_t *task, isc_event_t *event) {
  1536. isc_result_t result;
  1537. dns_requestevent_t *reqev = NULL;
  1538. dns_request_t *request;
  1539. dns_message_t *answer = NULL;
  1540. updatectx_t *uctx = event->ev_arg;
  1541. dns_client_t *client;
  1542. unsigned int timeout;
  1543. UNUSED(task);
  1544. REQUIRE(event->ev_type == DNS_EVENT_REQUESTDONE);
  1545. reqev = (dns_requestevent_t *)event;
  1546. request = reqev->request;
  1547. REQUIRE(UCTX_VALID(uctx));
  1548. client = uctx->client;
  1549. REQUIRE(DNS_CLIENT_VALID(client));
  1550. result = reqev->result;
  1551. if (result != ISC_R_SUCCESS)
  1552. goto out;
  1553. result = dns_message_create(client->mctx, DNS_MESSAGE_INTENTPARSE,
  1554. &answer);
  1555. if (result != ISC_R_SUCCESS)
  1556. goto out;
  1557. uctx->state = dns_clientupdatestate_done;
  1558. result = dns_request_getresponse(request, answer,
  1559. DNS_MESSAGEPARSE_PRESERVEORDER);
  1560. if (result == ISC_R_SUCCESS && answer->rcode != dns_rcode_noerror)
  1561. result = rcode2result(answer->rcode);
  1562. out:
  1563. if (answer != NULL)
  1564. dns_message_destroy(&answer);
  1565. isc_event_free(&event);
  1566. LOCK(&uctx->lock);
  1567. uctx->currentserver = ISC_LIST_NEXT(uctx->currentserver, link);
  1568. dns_request_destroy(&uctx->updatereq);
  1569. if (result != ISC_R_SUCCESS && !uctx->canceled &&
  1570. uctx->currentserver != NULL) {
  1571. dns_message_renderreset(uctx->updatemsg);
  1572. dns_message_settsigkey(uctx->updatemsg, NULL);
  1573. timeout = client->update_timeout / uctx->nservers;
  1574. if (timeout < MIN_UPDATE_TIMEOUT)
  1575. timeout = MIN_UPDATE_TIMEOUT;
  1576. result = dns_request_createvia3(uctx->view->requestmgr,
  1577. uctx->updatemsg,
  1578. NULL,
  1579. uctx->currentserver, 0,
  1580. uctx->tsigkey,
  1581. timeout,
  1582. client->update_udptimeout,
  1583. client->update_udpretries,
  1584. client->task,
  1585. update_done, uctx,
  1586. &uctx->updatereq);
  1587. UNLOCK(&uctx->lock);
  1588. if (result == ISC_R_SUCCESS) {
  1589. /* XXX: should we keep the 'done' state here? */
  1590. uctx->state = dns_clientupdatestate_sent;
  1591. return;
  1592. }
  1593. } else
  1594. UNLOCK(&uctx->lock);
  1595. update_sendevent(uctx, result);
  1596. }
  1597. static isc_result_t
  1598. send_update(updatectx_t *uctx) {
  1599. isc_result_t result;
  1600. dns_name_t *name = NULL;
  1601. dns_rdataset_t *rdataset = NULL;
  1602. dns_client_t *client = uctx->client;
  1603. unsigned int timeout;
  1604. REQUIRE(uctx->zonename != NULL && uctx->currentserver != NULL);
  1605. result = dns_message_gettempname(uctx->updatemsg, &name);
  1606. if (result != ISC_R_SUCCESS)
  1607. return (result);
  1608. dns_name_init(name, NULL);
  1609. dns_name_clone(uctx->zonename, name);
  1610. result = dns_message_gettemprdataset(uctx->updatemsg, &rdataset);
  1611. if (result != ISC_R_SUCCESS) {
  1612. dns_message_puttempname(uctx->updatemsg, &name);
  1613. return (result);
  1614. }
  1615. dns_rdataset_makequestion(rdataset, uctx->rdclass, dns_rdatatype_soa);
  1616. ISC_LIST_INIT(name->list);
  1617. ISC_LIST_APPEND(name->list, rdataset, link);
  1618. dns_message_addname(uctx->updatemsg, name, DNS_SECTION_ZONE);
  1619. if (uctx->tsigkey == NULL && uctx->sig0key != NULL) {
  1620. result = dns_message_setsig0key(uctx->updatemsg,
  1621. uctx->sig0key);
  1622. if (result != ISC_R_SUCCESS)
  1623. return (result);
  1624. }
  1625. timeout = client->update_timeout / uctx->nservers;
  1626. if (timeout < MIN_UPDATE_TIMEOUT)
  1627. timeout = MIN_UPDATE_TIMEOUT;
  1628. result = dns_request_createvia3(uctx->view->requestmgr,
  1629. uctx->updatemsg,
  1630. NULL, uctx->currentserver, 0,
  1631. uctx->tsigkey, timeout,
  1632. client->update_udptimeout,
  1633. client->update_udpretries,
  1634. client->task, update_done, uctx,
  1635. &uctx->updatereq);
  1636. if (result == ISC_R_SUCCESS &&
  1637. uctx->state == dns_clientupdatestate_prepare) {
  1638. uctx->state = dns_clientupdatestate_sent;
  1639. }
  1640. return (result);
  1641. }
  1642. static void
  1643. resolveaddr_done(isc_task_t *task, isc_event_t *event) {
  1644. isc_result_t result;
  1645. int family;
  1646. dns_rdatatype_t qtype;
  1647. dns_clientresevent_t *rev = (dns_clientresevent_t *)event;
  1648. dns_name_t *name;
  1649. dns_rdataset_t *rdataset;
  1650. updatectx_t *uctx;
  1651. isc_boolean_t completed = ISC_FALSE;
  1652. UNUSED(task);
  1653. REQUIRE(event->ev_arg != NULL);
  1654. uctx = *(updatectx_t **)event->ev_arg;
  1655. REQUIRE(UCTX_VALID(uctx));
  1656. if (event->ev_arg == &uctx->bp4) {
  1657. family = AF_INET;
  1658. qtype = dns_rdatatype_a;
  1659. LOCK(&uctx->lock);
  1660. dns_client_destroyrestrans(&uctx->restrans);
  1661. UNLOCK(&uctx->lock);
  1662. } else {
  1663. INSIST(event->ev_arg == &uctx->bp6);
  1664. family = AF_INET6;
  1665. qtype = dns_rdatatype_aaaa;
  1666. LOCK(&uctx->lock);
  1667. dns_client_destroyrestrans(&uctx->restrans2);
  1668. UNLOCK(&uctx->lock);
  1669. }
  1670. result = rev->result;
  1671. if (result != ISC_R_SUCCESS)
  1672. goto done;
  1673. for (name = ISC_LIST_HEAD(rev->answerlist); name != NULL;
  1674. name = ISC_LIST_NEXT(name, link)) {
  1675. for (rdataset = ISC_LIST_HEAD(name->list);
  1676. rdataset != NULL;
  1677. rdataset = ISC_LIST_NEXT(rdataset, link)) {
  1678. if (!dns_rdataset_isassociated(rdataset))
  1679. continue;
  1680. if (rdataset->type != qtype)
  1681. continue;
  1682. for (result = dns_rdataset_first(rdataset);
  1683. result == ISC_R_SUCCESS;
  1684. result = dns_rdataset_next(rdataset)) {
  1685. dns_rdata_t rdata;
  1686. dns_rdata_in_a_t rdata_a;
  1687. dns_rdata_in_aaaa_t rdata_aaaa;
  1688. isc_sockaddr_t *sa;
  1689. sa = isc_mem_get(uctx->client->mctx,
  1690. sizeof(*sa));
  1691. if (sa == NULL) {
  1692. /*
  1693. * If we fail to get a sockaddr,
  1694. we simply move forward with the
  1695. * addresses we've got so far.
  1696. */
  1697. goto done;
  1698. }
  1699. dns_rdata_init(&rdata);
  1700. switch (family) {
  1701. case AF_INET:
  1702. dns_rdataset_current(rdataset, &rdata);
  1703. dns_rdata_tostruct(&rdata, &rdata_a,
  1704. NULL);
  1705. isc_sockaddr_fromin(sa,
  1706. &rdata_a.in_addr,
  1707. 53);
  1708. dns_rdata_freestruct(&rdata_a);
  1709. break;
  1710. case AF_INET6:
  1711. dns_rdataset_current(rdataset, &rdata);
  1712. dns_rdata_tostruct(&rdata, &rdata_aaaa,
  1713. NULL);
  1714. isc_sockaddr_fromin6(sa,
  1715. &rdata_aaaa.in6_addr,
  1716. 53);
  1717. dns_rdata_freestruct(&rdata_aaaa);
  1718. break;
  1719. }
  1720. ISC_LINK_INIT(sa, link);
  1721. ISC_LIST_APPEND(uctx->servers, sa, link);
  1722. uctx->nservers++;
  1723. }
  1724. }
  1725. }
  1726. done:
  1727. dns_client_freeresanswer(uctx->client, &rev->answerlist);
  1728. isc_event_free(&event);
  1729. LOCK(&uctx->lock);
  1730. if (uctx->restrans == NULL && uctx->restrans2 == NULL)
  1731. completed = ISC_TRUE;
  1732. UNLOCK(&uctx->lock);
  1733. if (completed) {
  1734. INSIST(uctx->currentserver == NULL);
  1735. uctx->currentserver = ISC_LIST_HEAD(uctx->servers);
  1736. if (uctx->currentserver != NULL && !uctx->canceled)
  1737. send_update(uctx);
  1738. else {
  1739. if (result == ISC_R_SUCCESS)
  1740. result = ISC_R_NOTFOUND;
  1741. update_sendevent(uctx, result);
  1742. }
  1743. }
  1744. }
  1745. static isc_result_t
  1746. process_soa(updatectx_t *uctx, dns_rdataset_t *soaset, dns_name_t *soaname) {
  1747. isc_result_t result;
  1748. dns_rdata_t soarr = DNS_RDATA_INIT;
  1749. dns_rdata_soa_t soa;
  1750. dns_name_t primary;
  1751. result = dns_rdataset_first(soaset);
  1752. if (result != ISC_R_SUCCESS)
  1753. return (result);
  1754. dns_rdata_init(&soarr);
  1755. dns_rdataset_current(soaset, &soarr);
  1756. result = dns_rdata_tostruct(&soarr, &soa, NULL);
  1757. if (result != ISC_R_SUCCESS)
  1758. return (result);
  1759. dns_name_init(&primary, NULL);
  1760. dns_name_clone(&soa.origin, &primary);
  1761. if (uctx->zonename == NULL) {
  1762. uctx->zonename = dns_fixedname_name(&uctx->zonefname);
  1763. result = dns_name_copy(soaname, uctx->zonename, NULL);
  1764. if (result != ISC_R_SUCCESS)
  1765. goto out;
  1766. }
  1767. if (uctx->currentserver != NULL)
  1768. result = send_update(uctx);
  1769. else {
  1770. /*
  1771. * Get addresses of the primary server. We don't use the ADB
  1772. * feature so that we could avoid caching data.
  1773. */
  1774. LOCK(&uctx->lock);
  1775. uctx->bp4 = uctx;
  1776. result = dns_client_startresolve(uctx->client, &primary,
  1777. uctx->rdclass,
  1778. dns_rdatatype_a,
  1779. 0, uctx->client->task,
  1780. resolveaddr_done, &uctx->bp4,
  1781. &uctx->restrans);
  1782. if (result == ISC_R_SUCCESS) {
  1783. uctx->bp6 = uctx;
  1784. result = dns_client_startresolve(uctx->client,
  1785. &primary,
  1786. uctx->rdclass,
  1787. dns_rdatatype_aaaa,
  1788. 0, uctx->client->task,
  1789. resolveaddr_done,
  1790. &uctx->bp6,
  1791. &uctx->restrans2);
  1792. }
  1793. UNLOCK(&uctx->lock);
  1794. }
  1795. out:
  1796. dns_rdata_freestruct(&soa);
  1797. return (result);
  1798. }
  1799. static void
  1800. receive_soa(isc_task_t *task, isc_event_t *event) {
  1801. dns_requestevent_t *reqev = NULL;
  1802. updatectx_t *uctx;
  1803. dns_client_t *client;
  1804. isc_result_t result, eresult;
  1805. dns_request_t *request;
  1806. dns_message_t *rcvmsg = NULL;
  1807. dns_section_t section;
  1808. dns_rdataset_t *soaset = NULL;
  1809. int pass = 0;
  1810. dns_name_t *name;
  1811. dns_message_t *soaquery = NULL;
  1812. isc_sockaddr_t *addr;
  1813. isc_boolean_t seencname = ISC_FALSE;
  1814. isc_boolean_t droplabel = ISC_FALSE;
  1815. dns_name_t tname;
  1816. unsigned int nlabels;
  1817. UNUSED(task);
  1818. REQUIRE(event->ev_type == DNS_EVENT_REQUESTDONE);
  1819. reqev = (dns_requestevent_t *)event;
  1820. request = reqev->request;
  1821. result = eresult = reqev->result;
  1822. POST(result);
  1823. uctx = reqev->ev_arg;
  1824. client = uctx->client;
  1825. soaquery = uctx->soaquery;
  1826. addr = uctx->currentserver;
  1827. INSIST(addr != NULL);
  1828. isc_event_free(&event);
  1829. if (eresult != ISC_R_SUCCESS) {
  1830. result = eresult;
  1831. goto out;
  1832. }
  1833. result = dns_message_create(uctx->client->mctx,
  1834. DNS_MESSAGE_INTENTPARSE, &rcvmsg);
  1835. if (result != ISC_R_SUCCESS)
  1836. goto out;
  1837. result = dns_request_getresponse(request, rcvmsg,
  1838. DNS_MESSAGEPARSE_PRESERVEORDER);
  1839. if (result == DNS_R_TSIGERRORSET) {
  1840. dns_request_t *newrequest = NULL;
  1841. /* Retry SOA request without TSIG */
  1842. dns_message_destroy(&rcvmsg);
  1843. dns_message_renderreset(uctx->soaquery);
  1844. result = dns_request_createvia3(uctx->view->requestmgr,
  1845. uctx->soaquery, NULL, addr, 0,
  1846. NULL,
  1847. client->find_timeout * 20,
  1848. client->find_timeout, 3,
  1849. uctx->client->task,
  1850. receive_soa, uctx,
  1851. &newrequest);
  1852. if (result == ISC_R_SUCCESS) {
  1853. LOCK(&uctx->lock);
  1854. dns_request_destroy(&uctx->soareq);
  1855. uctx->soareq = newrequest;
  1856. UNLOCK(&uctx->lock);
  1857. return;
  1858. }
  1859. goto out;
  1860. }
  1861. section = DNS_SECTION_ANSWER;
  1862. POST(section);
  1863. if (rcvmsg->rcode != dns_rcode_noerror &&
  1864. rcvmsg->rcode != dns_rcode_nxdomain) {
  1865. result = rcode2result(rcvmsg->rcode);
  1866. goto out;
  1867. }
  1868. lookforsoa:
  1869. if (pass == 0)
  1870. section = DNS_SECTION_ANSWER;
  1871. else if (pass == 1)
  1872. section = DNS_SECTION_AUTHORITY;
  1873. else {
  1874. droplabel = ISC_TRUE;
  1875. goto out;
  1876. }
  1877. result = dns_message_firstname(rcvmsg, section);
  1878. if (result != ISC_R_SUCCESS) {
  1879. pass++;
  1880. goto lookforsoa;
  1881. }
  1882. while (result == ISC_R_SUCCESS) {
  1883. name = NULL;
  1884. dns_message_currentname(rcvmsg, section, &name);
  1885. soaset = NULL;
  1886. result = dns_message_findtype(name, dns_rdatatype_soa, 0,
  1887. &soaset);
  1888. if (result == ISC_R_SUCCESS)
  1889. break;
  1890. if (section == DNS_SECTION_ANSWER) {
  1891. dns_rdataset_t *tset = NULL;
  1892. if (dns_message_findtype(name, dns_rdatatype_cname, 0,
  1893. &tset) == ISC_R_SUCCESS
  1894. ||
  1895. dns_message_findtype(name, dns_rdatatype_dname, 0,
  1896. &tset) == ISC_R_SUCCESS
  1897. )
  1898. {
  1899. seencname = ISC_TRUE;
  1900. break;
  1901. }
  1902. }
  1903. result = dns_message_nextname(rcvmsg, section);
  1904. }
  1905. if (soaset == NULL && !seencname) {
  1906. pass++;
  1907. goto lookforsoa;
  1908. }
  1909. if (seencname) {
  1910. droplabel = ISC_TRUE;
  1911. goto out;
  1912. }
  1913. result = process_soa(uctx, soaset, name);
  1914. out:
  1915. if (droplabel) {
  1916. result = dns_message_firstname(soaquery, DNS_SECTION_QUESTION);
  1917. INSIST(result == ISC_R_SUCCESS);
  1918. name = NULL;
  1919. dns_message_currentname(soaquery, DNS_SECTION_QUESTION, &name);
  1920. nlabels = dns_name_countlabels(name);
  1921. if (nlabels == 1)
  1922. result = DNS_R_SERVFAIL; /* is there a better error? */
  1923. else {
  1924. dns_name_init(&tname, NULL);
  1925. dns_name_getlabelsequence(name, 1, nlabels - 1,
  1926. &tname);
  1927. dns_name_clone(&tname, name);
  1928. dns_request_destroy(&request);
  1929. LOCK(&uctx->lock);
  1930. uctx->soareq = NULL;
  1931. UNLOCK(&uctx->lock);
  1932. dns_message_renderreset(soaquery);
  1933. dns_message_settsigkey(soaquery, NULL);
  1934. result = dns_request_createvia3(uctx->view->requestmgr,
  1935. soaquery, NULL,
  1936. uctx->currentserver, 0,
  1937. uctx->tsigkey,
  1938. client->find_timeout *
  1939. 20,
  1940. client->find_timeout,
  1941. 3, client->task,
  1942. receive_soa, uctx,
  1943. &uctx->soareq);
  1944. }
  1945. }
  1946. if (!droplabel || result != ISC_R_SUCCESS) {
  1947. dns_message_destroy(&uctx->soaquery);
  1948. LOCK(&uctx->lock);
  1949. dns_request_destroy(&uctx->soareq);
  1950. UNLOCK(&uctx->lock);
  1951. }
  1952. if (rcvmsg != NULL)
  1953. dns_message_destroy(&rcvmsg);
  1954. if (result != ISC_R_SUCCESS)
  1955. update_sendevent(uctx, result);
  1956. }
  1957. static isc_result_t
  1958. request_soa(updatectx_t *uctx) {
  1959. isc_result_t result;
  1960. dns_message_t *soaquery = uctx->soaquery;
  1961. dns_name_t *name = NULL;
  1962. dns_rdataset_t *rdataset = NULL;
  1963. if (soaquery == NULL) {
  1964. result = dns_message_create(uctx->client->mctx,
  1965. DNS_MESSAGE_INTENTRENDER,
  1966. &soaquery);
  1967. if (result != ISC_R_SUCCESS)
  1968. return (result);
  1969. }
  1970. soaquery->flags |= DNS_MESSAGEFLAG_RD;
  1971. result = dns_message_gettempname(soaquery, &name);
  1972. if (result != ISC_R_SUCCESS)
  1973. goto fail;
  1974. result = dns_message_gettemprdataset(soaquery, &rdataset);
  1975. if (result != ISC_R_SUCCESS)
  1976. goto fail;
  1977. dns_rdataset_makequestion(rdataset, uctx->rdclass, dns_rdatatype_soa);
  1978. dns_name_clone(uctx->firstname, name);
  1979. ISC_LIST_APPEND(name->list, rdataset, link);
  1980. dns_message_addname(soaquery, name, DNS_SECTION_QUESTION);
  1981. rdataset = NULL;
  1982. name = NULL;
  1983. result = dns_request_createvia3(uctx->view->requestmgr,
  1984. soaquery, NULL, uctx->currentserver, 0,
  1985. uctx->tsigkey,
  1986. uctx->client->find_timeout * 20,
  1987. uctx->client->find_timeout, 3,
  1988. uctx->client->task, receive_soa, uctx,
  1989. &uctx->soareq);
  1990. if (result == ISC_R_SUCCESS) {
  1991. uctx->soaquery = soaquery;
  1992. return (ISC_R_SUCCESS);
  1993. }
  1994. fail:
  1995. if (rdataset != NULL) {
  1996. ISC_LIST_UNLINK(name->list, rdataset, link); /* for safety */
  1997. dns_message_puttemprdataset(soaquery, &rdataset);
  1998. }
  1999. if (name != NULL)
  2000. dns_message_puttempname(soaquery, &name);
  2001. dns_message_destroy(&soaquery);
  2002. return (result);
  2003. }
  2004. static void
  2005. resolvesoa_done(isc_task_t *task, isc_event_t *event) {
  2006. dns_clientresevent_t *rev = (dns_clientresevent_t *)event;
  2007. updatectx_t *uctx;
  2008. dns_name_t *name, tname;
  2009. dns_rdataset_t *rdataset = NULL;
  2010. isc_result_t result = rev->result;
  2011. unsigned int nlabels;
  2012. UNUSED(task);
  2013. uctx = event->ev_arg;
  2014. REQUIRE(UCTX_VALID(uctx));
  2015. LOCK(&uctx->lock);
  2016. dns_client_destroyrestrans(&uctx->restrans);
  2017. UNLOCK(&uctx->lock);
  2018. uctx = event->ev_arg;
  2019. if (result != ISC_R_SUCCESS &&
  2020. result != DNS_R_NCACHENXDOMAIN &&
  2021. result != DNS_R_NCACHENXRRSET) {
  2022. /* XXX: what about DNSSEC failure? */
  2023. goto out;
  2024. }
  2025. for (name = ISC_LIST_HEAD(rev->answerlist); name != NULL;
  2026. name = ISC_LIST_NEXT(name, link)) {
  2027. for (rdataset = ISC_LIST_HEAD(name->list);
  2028. rdataset != NULL;
  2029. rdataset = ISC_LIST_NEXT(rdataset, link)) {
  2030. if (dns_rdataset_isassociated(rdataset) &&
  2031. rdataset->type == dns_rdatatype_soa)
  2032. break;
  2033. }
  2034. }
  2035. if (rdataset == NULL) {
  2036. /* Drop one label and retry resolution. */
  2037. nlabels = dns_name_countlabels(&uctx->soaqname);
  2038. if (nlabels == 1) {
  2039. result = DNS_R_SERVFAIL; /* is there a better error? */
  2040. goto out;
  2041. }
  2042. dns_name_init(&tname, NULL);
  2043. dns_name_getlabelsequence(&uctx->soaqname, 1, nlabels - 1,
  2044. &tname);
  2045. dns_name_clone(&tname, &uctx->soaqname);
  2046. result = dns_client_startresolve(uctx->client, &uctx->soaqname,
  2047. uctx->rdclass,
  2048. dns_rdatatype_soa, 0,
  2049. uctx->client->task,
  2050. resolvesoa_done, uctx,
  2051. &uctx->restrans);
  2052. } else
  2053. result = process_soa(uctx, rdataset, &uctx->soaqname);
  2054. out:
  2055. dns_client_freeresanswer(uctx->client, &rev->answerlist);
  2056. isc_event_free(&event);
  2057. if (result != ISC_R_SUCCESS)
  2058. update_sendevent(uctx, result);
  2059. }
  2060. static isc_result_t
  2061. copy_name(isc_mem_t *mctx, dns_message_t *msg, dns_name_t *name,
  2062. dns_name_t **newnamep)
  2063. {
  2064. isc_result_t result;
  2065. dns_name_t *newname = NULL;
  2066. isc_region_t r;
  2067. isc_buffer_t *namebuf = NULL, *rdatabuf = NULL;
  2068. dns_rdatalist_t *rdatalist;
  2069. dns_rdataset_t *rdataset, *newrdataset;
  2070. dns_rdata_t rdata = DNS_RDATA_INIT, *newrdata;
  2071. result = dns_message_gettempname(msg, &newname);
  2072. if (result != ISC_R_SUCCESS)
  2073. return (result);
  2074. result = isc_buffer_allocate(mctx, &namebuf, DNS_NAME_MAXWIRE);
  2075. if (result != ISC_R_SUCCESS)
  2076. goto fail;
  2077. dns_name_init(newname, NULL);
  2078. dns_name_setbuffer(newname, namebuf);
  2079. dns_message_takebuffer(msg, &namebuf);
  2080. result = dns_name_copy(name, newname, NULL);
  2081. if (result != ISC_R_SUCCESS)
  2082. goto fail;
  2083. for (rdataset = ISC_LIST_HEAD(name->list); rdataset != NULL;
  2084. rdataset = ISC_LIST_NEXT(rdataset, link)) {
  2085. rdatalist = NULL;
  2086. result = dns_message_gettemprdatalist(msg, &rdatalist);
  2087. if (result != ISC_R_SUCCESS)
  2088. goto fail;
  2089. dns_rdatalist_init(rdatalist);
  2090. rdatalist->type = rdataset->type;
  2091. rdatalist->rdclass = rdataset->rdclass;
  2092. rdatalist->covers = rdataset->covers;
  2093. rdatalist->ttl = rdataset->ttl;
  2094. result = dns_rdataset_first(rdataset);
  2095. while (result == ISC_R_SUCCESS) {
  2096. dns_rdata_reset(&rdata);
  2097. dns_rdataset_current(rdataset, &rdata);
  2098. newrdata = NULL;
  2099. result = dns_message_gettemprdata(msg, &newrdata);
  2100. if (result != ISC_R_SUCCESS)
  2101. goto fail;
  2102. dns_rdata_toregion(&rdata, &r);
  2103. rdatabuf = NULL;
  2104. result = isc_buffer_allocate(mctx, &rdatabuf,
  2105. r.length);
  2106. if (result != ISC_R_SUCCESS)
  2107. goto fail;
  2108. isc_buffer_putmem(rdatabuf, r.base, r.length);
  2109. isc_buffer_usedregion(rdatabuf, &r);
  2110. dns_rdata_init(newrdata);
  2111. dns_rdata_fromregion(newrdata, rdata.rdclass,
  2112. rdata.type, &r);
  2113. newrdata->flags = rdata.flags;
  2114. ISC_LIST_APPEND(rdatalist->rdata, newrdata, link);
  2115. dns_message_takebuffer(msg, &rdatabuf);
  2116. result = dns_rdataset_next(rdataset);
  2117. }
  2118. newrdataset = NULL;
  2119. result = dns_message_gettemprdataset(msg, &newrdataset);
  2120. if (result != ISC_R_SUCCESS)
  2121. goto fail;
  2122. dns_rdataset_init(newrdataset);
  2123. dns_rdatalist_tordataset(rdatalist, newrdataset);
  2124. ISC_LIST_APPEND(newname->list, newrdataset, link);
  2125. }
  2126. *newnamep = newname;
  2127. return (ISC_R_SUCCESS);
  2128. fail:
  2129. dns_message_puttempname(msg, &newname);
  2130. return (result);
  2131. }
  2132. static void
  2133. internal_update_callback(isc_task_t *task, isc_event_t *event) {
  2134. updatearg_t *uarg = event->ev_arg;
  2135. dns_clientupdateevent_t *uev = (dns_clientupdateevent_t *)event;
  2136. UNUSED(task);
  2137. LOCK(&uarg->lock);
  2138. uarg->result = uev->result;
  2139. dns_client_destroyupdatetrans(&uarg->trans);
  2140. isc_event_free(&event);
  2141. if (!uarg->canceled) {
  2142. UNLOCK(&uarg->lock);
  2143. /* Exit from the internal event loop */
  2144. isc_app_ctxsuspend(uarg->actx);
  2145. } else {
  2146. /*
  2147. * We have already exited from the loop (due to some
  2148. * unexpected event). Just clean the arg up.
  2149. */
  2150. UNLOCK(&uarg->lock);
  2151. DESTROYLOCK(&uarg->lock);
  2152. isc_mem_put(uarg->client->mctx, uarg, sizeof(*uarg));
  2153. }
  2154. }
  2155. isc_result_t
  2156. dns_client_update(dns_client_t *client, dns_rdataclass_t rdclass,
  2157. dns_name_t *zonename, dns_namelist_t *prerequisites,
  2158. dns_namelist_t *updates, isc_sockaddrlist_t *servers,
  2159. dns_tsec_t *tsec, unsigned int options)
  2160. {
  2161. isc_result_t result;
  2162. isc_appctx_t *actx;
  2163. updatearg_t *uarg;
  2164. REQUIRE(DNS_CLIENT_VALID(client));
  2165. if ((client->attributes & DNS_CLIENTATTR_OWNCTX) == 0 &&
  2166. (options & DNS_CLIENTRESOPT_ALLOWRUN) == 0) {
  2167. /*
  2168. * If the client is run under application's control, we need
  2169. * to create a new running (sub)environment for this
  2170. * particular resolution.
  2171. */
  2172. return (ISC_R_NOTIMPLEMENTED); /* XXXTBD */
  2173. } else
  2174. actx = client->actx;
  2175. uarg = isc_mem_get(client->mctx, sizeof(*uarg));
  2176. if (uarg == NULL)
  2177. return (ISC_R_NOMEMORY);
  2178. result = isc_mutex_init(&uarg->lock);
  2179. if (result != ISC_R_SUCCESS) {
  2180. isc_mem_put(client->mctx, uarg, sizeof(*uarg));
  2181. return (result);
  2182. }
  2183. uarg->actx = actx;
  2184. uarg->client = client;
  2185. uarg->result = ISC_R_FAILURE;
  2186. uarg->trans = NULL;
  2187. uarg->canceled = ISC_FALSE;
  2188. result = dns_client_startupdate(client, rdclass, zonename,
  2189. prerequisites, updates, servers,
  2190. tsec, options, client->task,
  2191. internal_update_callback, uarg,
  2192. &uarg->trans);
  2193. if (result != ISC_R_SUCCESS) {
  2194. DESTROYLOCK(&uarg->lock);
  2195. isc_mem_put(client->mctx, uarg, sizeof(*uarg));
  2196. return (result);
  2197. }
  2198. /*
  2199. * Start internal event loop. It blocks until the entire process
  2200. * is completed.
  2201. */
  2202. result = isc_app_ctxrun(actx);
  2203. LOCK(&uarg->lock);
  2204. if (result == ISC_R_SUCCESS || result == ISC_R_SUSPEND)
  2205. result = uarg->result;
  2206. if (uarg->trans != NULL) {
  2207. /*
  2208. * Unusual termination (perhaps due to signal). We need some
  2209. * tricky cleanup process.
  2210. */
  2211. uarg->canceled = ISC_TRUE;
  2212. dns_client_cancelupdate(uarg->trans);
  2213. UNLOCK(&uarg->lock);
  2214. /* uarg will be freed in the event handler. */
  2215. } else {
  2216. UNLOCK(&uarg->lock);
  2217. DESTROYLOCK(&uarg->lock);
  2218. isc_mem_put(client->mctx, uarg, sizeof(*uarg));
  2219. }
  2220. return (result);
  2221. }
  2222. isc_result_t
  2223. dns_client_startupdate(dns_client_t *client, dns_rdataclass_t rdclass,
  2224. dns_name_t *zonename, dns_namelist_t *prerequisites,
  2225. dns_namelist_t *updates, isc_sockaddrlist_t *servers,
  2226. dns_tsec_t *tsec, unsigned int options,
  2227. isc_task_t *task, isc_taskaction_t action, void *arg,
  2228. dns_clientupdatetrans_t **transp)
  2229. {
  2230. dns_view_t *view = NULL;
  2231. isc_result_t result;
  2232. dns_name_t *name, *newname;
  2233. updatectx_t *uctx;
  2234. isc_task_t *clone = NULL;
  2235. dns_section_t section = DNS_SECTION_UPDATE;
  2236. isc_sockaddr_t *server, *sa = NULL;
  2237. dns_tsectype_t tsectype = dns_tsectype_none;
  2238. UNUSED(options);
  2239. REQUIRE(DNS_CLIENT_VALID(client));
  2240. REQUIRE(transp != NULL && *transp == NULL);
  2241. REQUIRE(updates != NULL);
  2242. REQUIRE(task != NULL);
  2243. if (tsec != NULL) {
  2244. tsectype = dns_tsec_gettype(tsec);
  2245. if (tsectype != dns_tsectype_tsig)
  2246. return (ISC_R_NOTIMPLEMENTED); /* XXX */
  2247. }
  2248. LOCK(&client->lock);
  2249. result = dns_viewlist_find(&client->viewlist, DNS_CLIENTVIEW_NAME,
  2250. rdclass, &view);
  2251. UNLOCK(&client->lock);
  2252. if (result != ISC_R_SUCCESS)
  2253. return (result);
  2254. /* Create a context and prepare some resources */
  2255. uctx = isc_mem_get(client->mctx, sizeof(*uctx));
  2256. if (uctx == NULL) {
  2257. dns_view_detach(&view);
  2258. return (ISC_R_NOMEMORY);
  2259. }
  2260. result = isc_mutex_init(&uctx->lock);
  2261. if (result != ISC_R_SUCCESS) {
  2262. dns_view_detach(&view);
  2263. isc_mem_put(client->mctx, uctx, sizeof(*uctx));
  2264. return (ISC_R_NOMEMORY);
  2265. }
  2266. clone = NULL;
  2267. isc_task_attach(task, &clone);
  2268. uctx->client = client;
  2269. ISC_LINK_INIT(uctx, link);
  2270. uctx->state = dns_clientupdatestate_prepare;
  2271. uctx->view = view;
  2272. uctx->rdclass = rdclass;
  2273. uctx->canceled = ISC_FALSE;
  2274. uctx->updatemsg = NULL;
  2275. uctx->soaquery = NULL;
  2276. uctx->updatereq = NULL;
  2277. uctx->restrans = NULL;
  2278. uctx->restrans2 = NULL;
  2279. uctx->bp4 = NULL;
  2280. uctx->bp6 = NULL;
  2281. uctx->soareq = NULL;
  2282. uctx->event = NULL;
  2283. uctx->tsigkey = NULL;
  2284. uctx->sig0key = NULL;
  2285. uctx->zonename = NULL;
  2286. dns_name_init(&uctx->soaqname, NULL);
  2287. ISC_LIST_INIT(uctx->servers);
  2288. uctx->nservers = 0;
  2289. uctx->currentserver = NULL;
  2290. dns_fixedname_init(&uctx->zonefname);
  2291. if (tsec != NULL)
  2292. dns_tsec_getkey(tsec, &uctx->tsigkey);
  2293. uctx->event = (dns_clientupdateevent_t *)
  2294. isc_event_allocate(client->mctx, clone, DNS_EVENT_UPDATEDONE,
  2295. action, arg, sizeof(*uctx->event));
  2296. if (uctx->event == NULL)
  2297. goto fail;
  2298. if (zonename != NULL) {
  2299. uctx->zonename = dns_fixedname_name(&uctx->zonefname);
  2300. result = dns_name_copy(zonename, uctx->zonename, NULL);
  2301. }
  2302. if (servers != NULL) {
  2303. for (server = ISC_LIST_HEAD(*servers);
  2304. server != NULL;
  2305. server = ISC_LIST_NEXT(server, link)) {
  2306. sa = isc_mem_get(client->mctx, sizeof(*sa));
  2307. if (sa == NULL)
  2308. goto fail;
  2309. sa->type = server->type;
  2310. sa->length = server->length;
  2311. ISC_LINK_INIT(sa, link);
  2312. ISC_LIST_APPEND(uctx->servers, sa, link);
  2313. if (uctx->currentserver == NULL)
  2314. uctx->currentserver = sa;
  2315. uctx->nservers++;
  2316. }
  2317. }
  2318. /* Make update message */
  2319. result = dns_message_create(client->mctx, DNS_MESSAGE_INTENTRENDER,
  2320. &uctx->updatemsg);
  2321. if (result != ISC_R_SUCCESS)
  2322. goto fail;
  2323. uctx->updatemsg->opcode = dns_opcode_update;
  2324. if (prerequisites != NULL) {
  2325. for (name = ISC_LIST_HEAD(*prerequisites); name != NULL;
  2326. name = ISC_LIST_NEXT(name, link)) {
  2327. newname = NULL;
  2328. result = copy_name(client->mctx, uctx->updatemsg,
  2329. name, &newname);
  2330. if (result != ISC_R_SUCCESS)
  2331. goto fail;
  2332. dns_message_addname(uctx->updatemsg, newname,
  2333. DNS_SECTION_PREREQUISITE);
  2334. }
  2335. }
  2336. for (name = ISC_LIST_HEAD(*updates); name != NULL;
  2337. name = ISC_LIST_NEXT(name, link)) {
  2338. newname = NULL;
  2339. result = copy_name(client->mctx, uctx->updatemsg, name,
  2340. &newname);
  2341. if (result != ISC_R_SUCCESS)
  2342. goto fail;
  2343. dns_message_addname(uctx->updatemsg, newname,
  2344. DNS_SECTION_UPDATE);
  2345. }
  2346. uctx->firstname = NULL;
  2347. result = dns_message_firstname(uctx->updatemsg, section);
  2348. if (result == ISC_R_NOMORE) {
  2349. section = DNS_SECTION_PREREQUISITE;
  2350. result = dns_message_firstname(uctx->updatemsg, section);
  2351. }
  2352. if (result != ISC_R_SUCCESS)
  2353. goto fail;
  2354. dns_message_currentname(uctx->updatemsg, section, &uctx->firstname);
  2355. uctx->magic = UCTX_MAGIC;
  2356. LOCK(&client->lock);
  2357. ISC_LIST_APPEND(client->updatectxs, uctx, link);
  2358. UNLOCK(&client->lock);
  2359. if (uctx->zonename != NULL && uctx->currentserver != NULL) {
  2360. result = send_update(uctx);
  2361. if (result != ISC_R_SUCCESS)
  2362. goto fail;
  2363. } else if (uctx->currentserver != NULL) {
  2364. result = request_soa(uctx);
  2365. if (result != ISC_R_SUCCESS)
  2366. goto fail;
  2367. } else {
  2368. dns_name_clone(uctx->firstname, &uctx->soaqname);
  2369. result = dns_client_startresolve(uctx->client, &uctx->soaqname,
  2370. uctx->rdclass,
  2371. dns_rdatatype_soa, 0,
  2372. client->task, resolvesoa_done,
  2373. uctx, &uctx->restrans);
  2374. if (result != ISC_R_SUCCESS)
  2375. goto fail;
  2376. }
  2377. *transp = (dns_clientupdatetrans_t *)uctx;
  2378. return (ISC_R_SUCCESS);
  2379. fail:
  2380. if (ISC_LINK_LINKED(uctx, link)) {
  2381. LOCK(&client->lock);
  2382. ISC_LIST_UNLINK(client->updatectxs, uctx, link);
  2383. UNLOCK(&client->lock);
  2384. }
  2385. if (uctx->updatemsg != NULL)
  2386. dns_message_destroy(&uctx->updatemsg);
  2387. while ((sa = ISC_LIST_HEAD(uctx->servers)) != NULL) {
  2388. ISC_LIST_UNLINK(uctx->servers, sa, link);
  2389. isc_mem_put(client->mctx, sa, sizeof(*sa));
  2390. }
  2391. if (uctx->event != NULL)
  2392. isc_event_free(ISC_EVENT_PTR(&uctx->event));
  2393. if (uctx->tsigkey != NULL)
  2394. dns_tsigkey_detach(&uctx->tsigkey);
  2395. isc_task_detach(&clone);
  2396. DESTROYLOCK(&uctx->lock);
  2397. uctx->magic = 0;
  2398. isc_mem_put(client->mctx, uctx, sizeof(*uctx));
  2399. dns_view_detach(&view);
  2400. return (result);
  2401. }
  2402. void
  2403. dns_client_cancelupdate(dns_clientupdatetrans_t *trans) {
  2404. updatectx_t *uctx;
  2405. REQUIRE(trans != NULL);
  2406. uctx = (updatectx_t *)trans;
  2407. REQUIRE(UCTX_VALID(uctx));
  2408. LOCK(&uctx->lock);
  2409. if (!uctx->canceled) {
  2410. uctx->canceled = ISC_TRUE;
  2411. if (uctx->updatereq != NULL)
  2412. dns_request_cancel(uctx->updatereq);
  2413. if (uctx->soareq != NULL)
  2414. dns_request_cancel(uctx->soareq);
  2415. if (uctx->restrans != NULL)
  2416. dns_client_cancelresolve(uctx->restrans);
  2417. if (uctx->restrans2 != NULL)
  2418. dns_client_cancelresolve(uctx->restrans2);
  2419. }
  2420. UNLOCK(&uctx->lock);
  2421. }
  2422. void
  2423. dns_client_destroyupdatetrans(dns_clientupdatetrans_t **transp) {
  2424. updatectx_t *uctx;
  2425. isc_mem_t *mctx;
  2426. dns_client_t *client;
  2427. isc_boolean_t need_destroyclient = ISC_FALSE;
  2428. isc_sockaddr_t *sa;
  2429. REQUIRE(transp != NULL);
  2430. uctx = (updatectx_t *)*transp;
  2431. REQUIRE(UCTX_VALID(uctx));
  2432. client = uctx->client;
  2433. REQUIRE(DNS_CLIENT_VALID(client));
  2434. REQUIRE(uctx->updatereq == NULL && uctx->updatemsg == NULL &&
  2435. uctx->soareq == NULL && uctx->soaquery == NULL &&
  2436. uctx->event == NULL && uctx->tsigkey == NULL &&
  2437. uctx->sig0key == NULL);
  2438. mctx = client->mctx;
  2439. dns_view_detach(&uctx->view);
  2440. while ((sa = ISC_LIST_HEAD(uctx->servers)) != NULL) {
  2441. ISC_LIST_UNLINK(uctx->servers, sa, link);
  2442. isc_mem_put(mctx, sa, sizeof(*sa));
  2443. }
  2444. LOCK(&client->lock);
  2445. INSIST(ISC_LINK_LINKED(uctx, link));
  2446. ISC_LIST_UNLINK(client->updatectxs, uctx, link);
  2447. if (client->references == 0 && ISC_LIST_EMPTY(client->resctxs) &&
  2448. ISC_LIST_EMPTY(client->reqctxs) &&
  2449. ISC_LIST_EMPTY(client->updatectxs))
  2450. need_destroyclient = ISC_TRUE;
  2451. UNLOCK(&client->lock);
  2452. DESTROYLOCK(&uctx->lock);
  2453. uctx->magic = 0;
  2454. isc_mem_put(mctx, uctx, sizeof(*uctx));
  2455. if (need_destroyclient)
  2456. destroyclient(&client);
  2457. *transp = NULL;
  2458. }
  2459. isc_mem_t *
  2460. dns_client_mctx(dns_client_t *client) {
  2461. REQUIRE(DNS_CLIENT_VALID(client));
  2462. return (client->mctx);
  2463. }
  2464. typedef struct {
  2465. isc_buffer_t buffer;
  2466. dns_rdataset_t rdataset;
  2467. dns_rdatalist_t rdatalist;
  2468. dns_rdata_t rdata;
  2469. size_t size;
  2470. isc_mem_t * mctx;
  2471. unsigned char data[FLEXIBLE_ARRAY_MEMBER];
  2472. } dns_client_updaterec_t;
  2473. isc_result_t
  2474. dns_client_updaterec(dns_client_updateop_t op, dns_name_t *owner,
  2475. dns_rdatatype_t type, dns_rdata_t *source,
  2476. dns_ttl_t ttl, dns_name_t *target,
  2477. dns_rdataset_t *rdataset, dns_rdatalist_t *rdatalist,
  2478. dns_rdata_t *rdata, isc_mem_t *mctx)
  2479. {
  2480. dns_client_updaterec_t *updaterec = NULL;
  2481. size_t size = offsetof(dns_client_updaterec_t, data);
  2482. REQUIRE(op < updateop_max);
  2483. REQUIRE(owner != NULL);
  2484. REQUIRE((rdataset != NULL && rdatalist != NULL && rdata != NULL) ||
  2485. (rdataset == NULL && rdatalist == NULL && rdata == NULL &&
  2486. mctx != NULL));
  2487. if (op == updateop_add)
  2488. REQUIRE(source != NULL);
  2489. if (source != NULL) {
  2490. REQUIRE(source->type == type);
  2491. REQUIRE(op == updateop_add || op == updateop_delete ||
  2492. op == updateop_exist);
  2493. }
  2494. size += owner->length;
  2495. if (source != NULL)
  2496. size += source->length;
  2497. if (rdataset == NULL) {
  2498. updaterec = isc_mem_get(mctx, size);
  2499. if (updaterec == NULL)
  2500. return (ISC_R_NOMEMORY);
  2501. rdataset = &updaterec->rdataset;
  2502. rdatalist = &updaterec->rdatalist;
  2503. rdata = &updaterec->rdata;
  2504. dns_rdataset_init(rdataset);
  2505. dns_rdatalist_init(&updaterec->rdatalist);
  2506. dns_rdata_init(&updaterec->rdata);
  2507. isc_buffer_init(&updaterec->buffer, updaterec->data,
  2508. size - offsetof(dns_client_updaterec_t, data));
  2509. dns_name_copy(owner, target, &updaterec->buffer);
  2510. if (source != NULL) {
  2511. isc_region_t r;
  2512. dns_rdata_clone(source, rdata);
  2513. dns_rdata_toregion(rdata, &r);
  2514. rdata->data = isc_buffer_used(&updaterec->buffer);
  2515. isc_buffer_copyregion(&updaterec->buffer, &r);
  2516. }
  2517. updaterec->mctx = NULL;
  2518. isc_mem_attach(mctx, &updaterec->mctx);
  2519. } else if (source != NULL)
  2520. dns_rdata_clone(source, rdata);
  2521. switch (op) {
  2522. case updateop_add:
  2523. break;
  2524. case updateop_delete:
  2525. if (source != NULL) {
  2526. ttl = 0;
  2527. dns_rdata_makedelete(rdata);
  2528. } else
  2529. dns_rdata_deleterrset(rdata, type);
  2530. break;
  2531. case updateop_notexist:
  2532. dns_rdata_notexist(rdata, type);
  2533. break;
  2534. case updateop_exist:
  2535. if (source == NULL) {
  2536. ttl = 0;
  2537. dns_rdata_exists(rdata, type);
  2538. }
  2539. case updateop_none:
  2540. break;
  2541. default:
  2542. INSIST(0);
  2543. }
  2544. rdatalist->type = rdata->type;
  2545. rdatalist->rdclass = rdata->rdclass;
  2546. if (source != NULL) {
  2547. rdatalist->covers = dns_rdata_covers(rdata);
  2548. rdatalist->ttl = ttl;
  2549. }
  2550. ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
  2551. dns_rdatalist_tordataset(rdatalist, rdataset);
  2552. ISC_LIST_APPEND(target->list, rdataset, link);
  2553. if (updaterec != NULL) {
  2554. target->attributes |= DNS_NAMEATTR_HASUPDATEREC;
  2555. dns_name_setbuffer(target, &updaterec->buffer);
  2556. }
  2557. if (op == updateop_add || op == updateop_delete)
  2558. target->attributes |= DNS_NAMEATTR_UPDATE;
  2559. else
  2560. target->attributes |= DNS_NAMEATTR_PREREQUISITE;
  2561. return (ISC_R_SUCCESS);
  2562. }
  2563. void
  2564. dns_client_freeupdate(dns_name_t **namep) {
  2565. dns_client_updaterec_t *updaterec;
  2566. dns_rdatalist_t *rdatalist;
  2567. dns_rdataset_t *rdataset;
  2568. dns_rdata_t *rdata;
  2569. dns_name_t *name;
  2570. REQUIRE(namep != NULL && *namep != NULL);
  2571. name = *namep;
  2572. for (rdataset = ISC_LIST_HEAD(name->list);
  2573. rdataset != NULL;
  2574. rdataset = ISC_LIST_HEAD(name->list)) {
  2575. ISC_LIST_UNLINK(name->list, rdataset, link);
  2576. rdatalist = NULL;
  2577. dns_rdatalist_fromrdataset(rdataset, &rdatalist);
  2578. if (rdatalist == NULL) {
  2579. dns_rdataset_disassociate(rdataset);
  2580. continue;
  2581. }
  2582. for (rdata = ISC_LIST_HEAD(rdatalist->rdata);
  2583. rdata != NULL;
  2584. rdata = ISC_LIST_HEAD(rdatalist->rdata))
  2585. ISC_LIST_UNLINK(rdatalist->rdata, rdata, link);
  2586. dns_rdataset_disassociate(rdataset);
  2587. }
  2588. if ((name->attributes & DNS_NAMEATTR_HASUPDATEREC) != 0) {
  2589. updaterec = (dns_client_updaterec_t *)name->buffer;
  2590. INSIST(updaterec != NULL);
  2591. isc_mem_putanddetach(&updaterec->mctx, updaterec,
  2592. updaterec->size);
  2593. *namep = NULL;
  2594. }
  2595. }