4 * Copyright (C) 2009 Internet Systems Consortium, Inc. ("ISC")
6 * Permission to use, copy, modify, and/or distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
10 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
11 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
12 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
13 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
14 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
15 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
16 * PERFORMANCE OF THIS SOFTWARE.
19 /* Id: client.c,v 1.6 2009/10/27 22:46:13 each Exp */
25 #include <isc/mutex.h>
26 #include <isc/sockaddr.h>
27 #include <isc/socket.h>
29 #include <isc/timer.h>
33 #include <dns/client.h>
35 #include <dns/dispatch.h>
36 #include <dns/events.h>
37 #include <dns/forward.h>
38 #include <dns/keytable.h>
39 #include <dns/message.h>
41 #include <dns/rdata.h>
42 #include <dns/rdatalist.h>
43 #include <dns/rdataset.h>
44 #include <dns/rdatatype.h>
45 #include <dns/rdatasetiter.h>
46 #include <dns/rdatastruct.h>
47 #include <dns/request.h>
48 #include <dns/resolver.h>
49 #include <dns/result.h>
56 #define DNS_CLIENT_MAGIC ISC_MAGIC('D', 'N', 'S', 'c')
57 #define DNS_CLIENT_VALID(c) ISC_MAGIC_VALID(c, DNS_CLIENT_MAGIC)
59 #define RCTX_MAGIC ISC_MAGIC('R', 'c', 't', 'x')
60 #define RCTX_VALID(c) ISC_MAGIC_VALID(c, RCTX_MAGIC)
62 #define REQCTX_MAGIC ISC_MAGIC('R', 'q', 'c', 'x')
63 #define REQCTX_VALID(c) ISC_MAGIC_VALID(c, REQCTX_MAGIC)
65 #define UCTX_MAGIC ISC_MAGIC('U', 'c', 't', 'x')
66 #define UCTX_VALID(c) ISC_MAGIC_VALID(c, UCTX_MAGIC)
68 #define MAX_RESTARTS 16
76 unsigned int attributes
;
80 isc_taskmgr_t
*taskmgr
;
82 isc_socketmgr_t
*socketmgr
;
83 isc_timermgr_t
*timermgr
;
84 dns_dispatchmgr_t
*dispatchmgr
;
85 dns_dispatch_t
*dispatchv4
;
86 dns_dispatch_t
*dispatchv6
;
88 unsigned int update_timeout
;
89 unsigned int update_udptimeout
;
90 unsigned int update_udpretries
;
91 unsigned int find_timeout
;
92 unsigned int find_udpretries
;
95 unsigned int references
;
96 dns_viewlist_t viewlist
;
97 ISC_LIST(struct resctx
) resctxs
;
98 ISC_LIST(struct reqctx
) reqctxs
;
99 ISC_LIST(struct updatectx
) updatectxs
;
103 * Timeout/retry constants for dynamic update borrowed from nsupdate
105 #define DEF_UPDATE_TIMEOUT 300
106 #define MIN_UPDATE_TIMEOUT 30
107 #define DEF_UPDATE_UDPTIMEOUT 3
108 #define DEF_UPDATE_UDPRETRIES 3
110 #define DEF_FIND_TIMEOUT 5
111 #define DEF_FIND_UDPRETRIES 3
113 #define DNS_CLIENTATTR_OWNCTX 0x01
115 #define DNS_CLIENTVIEW_NAME "dnsclient"
118 * Internal state for a single name resolution procedure
120 typedef struct resctx
{
124 dns_client_t
*client
;
125 isc_boolean_t want_dnssec
;
128 ISC_LINK(struct resctx
) link
;
131 unsigned int restarts
;
132 dns_fixedname_t name
;
133 dns_rdatatype_t type
;
135 dns_namelist_t namelist
;
137 dns_clientresevent_t
*event
;
138 isc_boolean_t canceled
;
139 dns_rdataset_t
*rdataset
;
140 dns_rdataset_t
*sigrdataset
;
144 * Argument of an internal event for synchronous name resolution.
146 typedef struct resarg
{
149 dns_client_t
*client
;
154 isc_result_t vresult
;
155 dns_namelist_t
*namelist
;
156 dns_clientrestrans_t
*trans
;
157 isc_boolean_t canceled
;
161 * Internal state for a single DNS request
163 typedef struct reqctx
{
167 dns_client_t
*client
;
168 unsigned int parseoptions
;
171 ISC_LINK(struct reqctx
) link
;
172 isc_boolean_t canceled
;
173 dns_tsigkey_t
*tsigkey
;
174 dns_request_t
*request
;
175 dns_clientreqevent_t
*event
;
179 * Argument of an internal event for synchronous DNS request.
181 typedef struct reqarg
{
184 dns_client_t
*client
;
189 dns_clientreqtrans_t
*trans
;
190 isc_boolean_t canceled
;
194 * Argument of an internal event for synchronous name resolution.
196 typedef struct updatearg
{
199 dns_client_t
*client
;
204 dns_clientupdatetrans_t
*trans
;
205 isc_boolean_t canceled
;
209 * Internal state for a single dynamic update procedure
211 typedef struct updatectx
{
215 dns_client_t
*client
;
218 dns_request_t
*updatereq
;
219 dns_request_t
*soareq
;
220 dns_clientrestrans_t
*restrans
;
221 dns_clientrestrans_t
*restrans2
;
222 isc_boolean_t canceled
;
225 ISC_LINK(struct updatectx
) link
;
226 dns_clientupdatestate_t state
;
227 dns_rdataclass_t rdclass
;
229 dns_message_t
*updatemsg
;
230 dns_message_t
*soaquery
;
231 dns_clientupdateevent_t
*event
;
232 dns_tsigkey_t
*tsigkey
;
234 dns_name_t
*firstname
;
236 dns_fixedname_t zonefname
;
237 dns_name_t
*zonename
;
238 isc_sockaddrlist_t servers
;
239 unsigned int nservers
;
240 isc_sockaddr_t
*currentserver
;
241 struct updatectx
*bp4
;
242 struct updatectx
*bp6
;
245 static isc_result_t
request_soa(updatectx_t
*uctx
);
246 static void client_resfind(resctx_t
*rctx
, dns_fetchevent_t
*event
);
247 static isc_result_t
send_update(updatectx_t
*uctx
);
250 getudpdispatch(int family
, dns_dispatchmgr_t
*dispatchmgr
,
251 isc_socketmgr_t
*socketmgr
, isc_taskmgr_t
*taskmgr
,
252 isc_boolean_t is_shared
, dns_dispatch_t
**dispp
)
254 unsigned int attrs
, attrmask
;
256 dns_dispatch_t
*disp
;
257 unsigned buffersize
, maxbuffers
, maxrequests
, buckets
, increment
;
261 attrs
|= DNS_DISPATCHATTR_UDP
;
264 attrs
|= DNS_DISPATCHATTR_IPV4
;
267 attrs
|= DNS_DISPATCHATTR_IPV6
;
273 attrmask
|= DNS_DISPATCHATTR_UDP
;
274 attrmask
|= DNS_DISPATCHATTR_TCP
;
275 attrmask
|= DNS_DISPATCHATTR_IPV4
;
276 attrmask
|= DNS_DISPATCHATTR_IPV6
;
278 isc_sockaddr_anyofpf(&sa
, family
);
281 maxbuffers
= is_shared
? 1000 : 8;
283 buckets
= is_shared
? 16411 : 3;
284 increment
= is_shared
? 16433 : 5;
287 result
= dns_dispatch_getudp(dispatchmgr
, socketmgr
,
289 buffersize
, maxbuffers
, maxrequests
,
291 attrs
, attrmask
, &disp
);
292 if (result
== ISC_R_SUCCESS
)
299 dns_client_createview(isc_mem_t
*mctx
, dns_rdataclass_t rdclass
,
300 unsigned int options
, isc_taskmgr_t
*taskmgr
,
301 unsigned int ntasks
, isc_socketmgr_t
*socketmgr
,
302 isc_timermgr_t
*timermgr
, dns_dispatchmgr_t
*dispatchmgr
,
303 dns_dispatch_t
*dispatchv4
, dns_dispatch_t
*dispatchv6
,
307 dns_view_t
*view
= NULL
;
310 result
= dns_view_create(mctx
, rdclass
, DNS_CLIENTVIEW_NAME
, &view
);
311 if (result
!= ISC_R_SUCCESS
)
314 /* Initialize view security roots */
315 result
= dns_view_initsecroots(view
, mctx
);
316 if (result
!= ISC_R_SUCCESS
) {
317 dns_view_detach(&view
);
321 result
= dns_view_createresolver(view
, taskmgr
, ntasks
, socketmgr
,
322 timermgr
, 0, dispatchmgr
,
323 dispatchv4
, dispatchv6
);
324 if (result
!= ISC_R_SUCCESS
) {
325 dns_view_detach(&view
);
331 * XXX: it may be better if specific DB implementations can be
332 * specified via some configuration knob.
334 if ((options
& DNS_CLIENTCREATEOPT_USECACHE
) != 0)
338 result
= dns_db_create(mctx
, dbtype
, dns_rootname
, dns_dbtype_cache
,
339 rdclass
, 0, NULL
, &view
->cachedb
);
340 if (result
!= ISC_R_SUCCESS
) {
341 dns_view_detach(&view
);
346 return (ISC_R_SUCCESS
);
350 dns_client_create(dns_client_t
**clientp
, unsigned int options
) {
352 isc_mem_t
*mctx
= NULL
;
353 isc_appctx_t
*actx
= NULL
;
354 isc_taskmgr_t
*taskmgr
= NULL
;
355 isc_socketmgr_t
*socketmgr
= NULL
;
356 isc_timermgr_t
*timermgr
= NULL
;
358 result
= isc_mem_create(0, 0, &mctx
);
359 if (result
!= ISC_R_SUCCESS
)
361 result
= isc_appctx_create(mctx
, &actx
);
362 if (result
!= ISC_R_SUCCESS
)
364 result
= isc_app_ctxstart(actx
);
365 if (result
!= ISC_R_SUCCESS
)
367 result
= isc_taskmgr_createinctx(mctx
, actx
, 1, 0, &taskmgr
);
368 if (result
!= ISC_R_SUCCESS
)
370 result
= isc_socketmgr_createinctx(mctx
, actx
, &socketmgr
);
371 if (result
!= ISC_R_SUCCESS
)
373 result
= isc_timermgr_createinctx(mctx
, actx
, &timermgr
);
374 if (result
!= ISC_R_SUCCESS
)
377 result
= dns_client_createx(mctx
, actx
, taskmgr
, socketmgr
, timermgr
,
379 if (result
!= ISC_R_SUCCESS
)
382 (*clientp
)->attributes
|= DNS_CLIENTATTR_OWNCTX
;
384 /* client has its own reference to mctx, so we can detach it here */
385 isc_mem_detach(&mctx
);
387 return (ISC_R_SUCCESS
);
390 if (timermgr
!= NULL
)
391 isc_timermgr_destroy(&timermgr
);
392 if (socketmgr
!= NULL
)
393 isc_socketmgr_destroy(&socketmgr
);
395 isc_taskmgr_destroy(&taskmgr
);
397 isc_appctx_destroy(&actx
);
398 isc_mem_detach(&mctx
);
404 dns_client_createx(isc_mem_t
*mctx
, isc_appctx_t
*actx
, isc_taskmgr_t
*taskmgr
,
405 isc_socketmgr_t
*socketmgr
, isc_timermgr_t
*timermgr
,
406 unsigned int options
, dns_client_t
**clientp
)
408 dns_client_t
*client
;
410 dns_dispatchmgr_t
*dispatchmgr
= NULL
;
411 dns_dispatch_t
*dispatchv4
= NULL
;
412 dns_dispatch_t
*dispatchv6
= NULL
;
413 dns_view_t
*view
= NULL
;
415 REQUIRE(mctx
!= NULL
);
416 REQUIRE(taskmgr
!= NULL
);
417 REQUIRE(timermgr
!= NULL
);
418 REQUIRE(socketmgr
!= NULL
);
419 REQUIRE(clientp
!= NULL
&& *clientp
== NULL
);
421 client
= isc_mem_get(mctx
, sizeof(*client
));
423 return (ISC_R_NOMEMORY
);
425 result
= isc_mutex_init(&client
->lock
);
426 if (result
!= ISC_R_SUCCESS
) {
427 isc_mem_put(mctx
, client
, sizeof(*client
));
432 client
->taskmgr
= taskmgr
;
433 client
->socketmgr
= socketmgr
;
434 client
->timermgr
= timermgr
;
437 result
= isc_task_create(client
->taskmgr
, 0, &client
->task
);
438 if (result
!= ISC_R_SUCCESS
)
441 result
= dns_dispatchmgr_create(mctx
, NULL
, &dispatchmgr
);
442 if (result
!= ISC_R_SUCCESS
)
444 client
->dispatchmgr
= dispatchmgr
;
446 /* TODO: whether to use dispatch v4 or v6 should be configurable */
447 result
= getudpdispatch(AF_INET
, dispatchmgr
, socketmgr
,
448 taskmgr
, ISC_TRUE
, &dispatchv4
);
449 if (result
!= ISC_R_SUCCESS
)
451 client
->dispatchv4
= dispatchv4
;
452 result
= getudpdispatch(AF_INET6
, dispatchmgr
, socketmgr
,
453 taskmgr
, ISC_TRUE
, &dispatchv6
);
454 if (result
!= ISC_R_SUCCESS
)
456 client
->dispatchv6
= dispatchv6
;
458 /* Create the default view for class IN */
459 result
= dns_client_createview(mctx
, dns_rdataclass_in
, options
,
460 taskmgr
, 31, socketmgr
, timermgr
,
461 dispatchmgr
, dispatchv4
, dispatchv6
,
463 if (result
!= ISC_R_SUCCESS
)
465 ISC_LIST_INIT(client
->viewlist
);
466 ISC_LIST_APPEND(client
->viewlist
, view
, link
);
468 dns_view_freeze(view
); /* too early? */
470 ISC_LIST_INIT(client
->resctxs
);
471 ISC_LIST_INIT(client
->reqctxs
);
472 ISC_LIST_INIT(client
->updatectxs
);
475 isc_mem_attach(mctx
, &client
->mctx
);
477 client
->update_timeout
= DEF_UPDATE_TIMEOUT
;
478 client
->update_udptimeout
= DEF_UPDATE_UDPTIMEOUT
;
479 client
->update_udpretries
= DEF_UPDATE_UDPRETRIES
;
480 client
->find_timeout
= DEF_FIND_TIMEOUT
;
481 client
->find_udpretries
= DEF_FIND_UDPRETRIES
;
483 client
->references
= 1;
484 client
->magic
= DNS_CLIENT_MAGIC
;
488 return (ISC_R_SUCCESS
);
491 if (dispatchv4
!= NULL
)
492 dns_dispatch_detach(&dispatchv4
);
493 if (dispatchv6
!= NULL
)
494 dns_dispatch_detach(&dispatchv6
);
495 if (dispatchmgr
!= NULL
)
496 dns_dispatchmgr_destroy(&dispatchmgr
);
497 if (client
->task
!= NULL
)
498 isc_task_detach(&client
->task
);
499 isc_mem_put(mctx
, client
, sizeof(*client
));
505 destroyclient(dns_client_t
**clientp
) {
506 dns_client_t
*client
= *clientp
;
509 while ((view
= ISC_LIST_HEAD(client
->viewlist
)) != NULL
) {
510 ISC_LIST_UNLINK(client
->viewlist
, view
, link
);
511 dns_view_detach(&view
);
514 if (client
->dispatchv4
!= NULL
)
515 dns_dispatch_detach(&client
->dispatchv4
);
516 if (client
->dispatchv6
!= NULL
)
517 dns_dispatch_detach(&client
->dispatchv6
);
519 dns_dispatchmgr_destroy(&client
->dispatchmgr
);
521 isc_task_detach(&client
->task
);
524 * If the client has created its own running environments,
527 if ((client
->attributes
& DNS_CLIENTATTR_OWNCTX
) != 0) {
528 isc_taskmgr_destroy(&client
->taskmgr
);
529 isc_timermgr_destroy(&client
->timermgr
);
530 isc_socketmgr_destroy(&client
->socketmgr
);
532 isc_app_ctxfinish(client
->actx
);
533 isc_appctx_destroy(&client
->actx
);
536 DESTROYLOCK(&client
->lock
);
539 isc_mem_putanddetach(&client
->mctx
, client
, sizeof(*client
));
545 dns_client_destroy(dns_client_t
**clientp
) {
546 dns_client_t
*client
;
547 isc_boolean_t destroyok
= ISC_FALSE
;
549 REQUIRE(clientp
!= NULL
);
551 REQUIRE(DNS_CLIENT_VALID(client
));
554 client
->references
--;
555 if (client
->references
== 0 && ISC_LIST_EMPTY(client
->resctxs
) &&
556 ISC_LIST_EMPTY(client
->reqctxs
) &&
557 ISC_LIST_EMPTY(client
->updatectxs
)) {
558 destroyok
= ISC_TRUE
;
560 UNLOCK(&client
->lock
);
563 destroyclient(&client
);
569 dns_client_setservers(dns_client_t
*client
, dns_rdataclass_t rdclass
,
570 dns_name_t
*namespace, isc_sockaddrlist_t
*addrs
)
573 dns_view_t
*view
= NULL
;
575 REQUIRE(DNS_CLIENT_VALID(client
));
576 REQUIRE(addrs
!= NULL
);
578 if (namespace == NULL
)
579 namespace = dns_rootname
;
582 result
= dns_viewlist_find(&client
->viewlist
, DNS_CLIENTVIEW_NAME
,
584 if (result
!= ISC_R_SUCCESS
) {
585 UNLOCK(&client
->lock
);
588 UNLOCK(&client
->lock
);
590 result
= dns_fwdtable_add(view
->fwdtable
, namespace, addrs
,
593 dns_view_detach(&view
);
599 dns_client_clearservers(dns_client_t
*client
, dns_rdataclass_t rdclass
,
600 dns_name_t
*namespace)
603 dns_view_t
*view
= NULL
;
605 REQUIRE(DNS_CLIENT_VALID(client
));
607 if (namespace == NULL
)
608 namespace = dns_rootname
;
611 result
= dns_viewlist_find(&client
->viewlist
, DNS_CLIENTVIEW_NAME
,
613 if (result
!= ISC_R_SUCCESS
) {
614 UNLOCK(&client
->lock
);
617 UNLOCK(&client
->lock
);
619 result
= dns_fwdtable_delete(view
->fwdtable
, namespace);
621 dns_view_detach(&view
);
627 getrdataset(isc_mem_t
*mctx
, dns_rdataset_t
**rdatasetp
) {
628 dns_rdataset_t
*rdataset
;
630 REQUIRE(mctx
!= NULL
);
631 REQUIRE(rdatasetp
!= NULL
&& *rdatasetp
== NULL
);
633 rdataset
= isc_mem_get(mctx
, sizeof(*rdataset
));
634 if (rdataset
== NULL
)
635 return (ISC_R_NOMEMORY
);
637 dns_rdataset_init(rdataset
);
639 *rdatasetp
= rdataset
;
641 return (ISC_R_SUCCESS
);
645 putrdataset(isc_mem_t
*mctx
, dns_rdataset_t
**rdatasetp
) {
646 dns_rdataset_t
*rdataset
;
648 REQUIRE(rdatasetp
!= NULL
);
649 rdataset
= *rdatasetp
;
650 REQUIRE(rdataset
!= NULL
);
652 if (dns_rdataset_isassociated(rdataset
))
653 dns_rdataset_disassociate(rdataset
);
655 isc_mem_put(mctx
, rdataset
, sizeof(*rdataset
));
661 fetch_done(isc_task_t
*task
, isc_event_t
*event
) {
662 resctx_t
*rctx
= event
->ev_arg
;
663 dns_fetchevent_t
*fevent
;
665 REQUIRE(event
->ev_type
== DNS_EVENT_FETCHDONE
);
666 REQUIRE(RCTX_VALID(rctx
));
667 REQUIRE(rctx
->task
== task
);
668 fevent
= (dns_fetchevent_t
*)event
;
670 client_resfind(rctx
, fevent
);
673 static inline isc_result_t
674 start_fetch(resctx_t
*rctx
) {
678 * The caller must be holding the rctx's lock.
681 REQUIRE(rctx
->fetch
== NULL
);
683 result
= dns_resolver_createfetch(rctx
->view
->resolver
,
684 dns_fixedname_name(&rctx
->name
),
687 rctx
->task
, fetch_done
, rctx
,
696 view_find(resctx_t
*rctx
, dns_db_t
**dbp
, dns_dbnode_t
**nodep
,
697 dns_name_t
*foundname
)
700 dns_name_t
*name
= dns_fixedname_name(&rctx
->name
);
701 dns_rdatatype_t type
;
703 if (rctx
->type
== dns_rdatatype_rrsig
)
704 type
= dns_rdatatype_any
;
708 result
= dns_view_find(rctx
->view
, name
, type
, 0, 0, ISC_FALSE
,
709 dbp
, nodep
, foundname
, rctx
->rdataset
,
716 client_resfind(resctx_t
*rctx
, dns_fetchevent_t
*event
) {
718 isc_result_t result
, tresult
;
719 isc_result_t vresult
= ISC_R_SUCCESS
;
720 isc_boolean_t want_restart
;
721 isc_boolean_t send_event
= ISC_FALSE
;
722 dns_name_t
*name
, *prefix
;
723 dns_fixedname_t foundname
, fixed
;
724 dns_rdataset_t
*trdataset
;
725 dns_rdata_t rdata
= DNS_RDATA_INIT
;
726 unsigned int nlabels
;
728 dns_namereln_t namereln
;
729 dns_rdata_cname_t cname
;
730 dns_rdata_dname_t dname
;
732 REQUIRE(RCTX_VALID(rctx
));
736 mctx
= rctx
->view
->mctx
;
738 result
= ISC_R_SUCCESS
;
739 name
= dns_fixedname_name(&rctx
->name
);
742 dns_name_t
*fname
= NULL
;
743 dns_name_t
*ansname
= NULL
;
745 dns_dbnode_t
*node
= NULL
;
748 want_restart
= ISC_FALSE
;
750 if (event
== NULL
&& !rctx
->canceled
) {
751 dns_fixedname_init(&foundname
);
752 fname
= dns_fixedname_name(&foundname
);
753 INSIST(!dns_rdataset_isassociated(rctx
->rdataset
));
754 INSIST(rctx
->sigrdataset
== NULL
||
755 !dns_rdataset_isassociated(rctx
->sigrdataset
));
756 result
= view_find(rctx
, &db
, &node
, fname
);
757 if (result
== ISC_R_NOTFOUND
) {
759 * We don't know anything about the name.
764 dns_db_detachnode(db
, &node
);
768 result
= start_fetch(rctx
);
769 if (result
!= ISC_R_SUCCESS
) {
770 putrdataset(mctx
, &rctx
->rdataset
);
771 if (rctx
->sigrdataset
!= NULL
)
774 send_event
= ISC_TRUE
;
779 INSIST(event
->fetch
== rctx
->fetch
);
780 dns_resolver_destroyfetch(&rctx
->fetch
);
783 result
= event
->result
;
784 vresult
= event
->vresult
;
785 fname
= dns_fixedname_name(&event
->foundname
);
786 INSIST(event
->rdataset
== rctx
->rdataset
);
787 INSIST(event
->sigrdataset
== rctx
->sigrdataset
);
791 * If we've been canceled, forget about the result.
794 result
= ISC_R_CANCELED
;
797 * Otherwise, get some resource for copying the
800 ansname
= isc_mem_get(mctx
, sizeof(*ansname
));
802 tresult
= ISC_R_NOMEMORY
;
806 aname
= dns_fixedname_name(&rctx
->name
);
807 dns_name_init(ansname
, NULL
);
808 tresult
= dns_name_dup(aname
, mctx
, ansname
);
809 if (tresult
!= ISC_R_SUCCESS
)
810 isc_mem_put(mctx
, ansname
,
813 if (tresult
!= ISC_R_SUCCESS
)
819 send_event
= ISC_TRUE
;
821 * This case is handled in the main line below.
826 * Add the CNAME to the answer list.
828 trdataset
= rctx
->rdataset
;
829 ISC_LIST_APPEND(ansname
->list
, rctx
->rdataset
, link
);
830 rctx
->rdataset
= NULL
;
831 if (rctx
->sigrdataset
!= NULL
) {
832 ISC_LIST_APPEND(ansname
->list
,
833 rctx
->sigrdataset
, link
);
834 rctx
->sigrdataset
= NULL
;
836 ISC_LIST_APPEND(rctx
->namelist
, ansname
, link
);
840 * Copy the CNAME's target into the lookup's
841 * query name and start over.
843 tresult
= dns_rdataset_first(trdataset
);
844 if (tresult
!= ISC_R_SUCCESS
)
846 dns_rdataset_current(trdataset
, &rdata
);
847 tresult
= dns_rdata_tostruct(&rdata
, &cname
, NULL
);
848 dns_rdata_reset(&rdata
);
849 if (tresult
!= ISC_R_SUCCESS
)
851 tresult
= dns_name_copy(&cname
.cname
, name
, NULL
);
852 dns_rdata_freestruct(&cname
);
853 if (tresult
== ISC_R_SUCCESS
)
854 want_restart
= ISC_TRUE
;
860 * Add the DNAME to the answer list.
862 trdataset
= rctx
->rdataset
;
863 ISC_LIST_APPEND(ansname
->list
, rctx
->rdataset
, link
);
864 rctx
->rdataset
= NULL
;
865 if (rctx
->sigrdataset
!= NULL
) {
866 ISC_LIST_APPEND(ansname
->list
,
867 rctx
->sigrdataset
, link
);
868 rctx
->sigrdataset
= NULL
;
870 ISC_LIST_APPEND(rctx
->namelist
, ansname
, link
);
873 namereln
= dns_name_fullcompare(name
, fname
, &order
,
875 INSIST(namereln
== dns_namereln_subdomain
);
877 * Get the target name of the DNAME.
879 tresult
= dns_rdataset_first(trdataset
);
880 if (tresult
!= ISC_R_SUCCESS
) {
884 dns_rdataset_current(trdataset
, &rdata
);
885 tresult
= dns_rdata_tostruct(&rdata
, &dname
, NULL
);
886 dns_rdata_reset(&rdata
);
887 if (tresult
!= ISC_R_SUCCESS
) {
892 * Construct the new query name and start over.
894 dns_fixedname_init(&fixed
);
895 prefix
= dns_fixedname_name(&fixed
);
896 dns_name_split(name
, nlabels
, prefix
, NULL
);
897 tresult
= dns_name_concatenate(prefix
, &dname
.dname
,
899 dns_rdata_freestruct(&dname
);
900 if (tresult
== ISC_R_SUCCESS
)
901 want_restart
= ISC_TRUE
;
905 case DNS_R_NCACHENXDOMAIN
:
906 case DNS_R_NCACHENXRRSET
:
907 ISC_LIST_APPEND(ansname
->list
, rctx
->rdataset
, link
);
908 ISC_LIST_APPEND(rctx
->namelist
, ansname
, link
);
910 rctx
->rdataset
= NULL
;
911 /* What about sigrdataset? */
912 if (rctx
->sigrdataset
!= NULL
)
913 putrdataset(mctx
, &rctx
->sigrdataset
);
914 send_event
= ISC_TRUE
;
917 if (rctx
->rdataset
!= NULL
)
918 putrdataset(mctx
, &rctx
->rdataset
);
919 if (rctx
->sigrdataset
!= NULL
)
920 putrdataset(mctx
, &rctx
->sigrdataset
);
921 send_event
= ISC_TRUE
;
925 if (rctx
->type
== dns_rdatatype_any
) {
927 dns_rdatasetiter_t
*rdsiter
= NULL
;
929 tresult
= dns_db_allrdatasets(db
, node
, NULL
, 0,
931 if (tresult
!= ISC_R_SUCCESS
) {
936 tresult
= dns_rdatasetiter_first(rdsiter
);
937 while (tresult
== ISC_R_SUCCESS
) {
938 dns_rdatasetiter_current(rdsiter
,
940 if (rctx
->rdataset
->type
!= 0) {
941 ISC_LIST_APPEND(ansname
->list
,
945 rctx
->rdataset
= NULL
;
948 * We're not interested in this
951 dns_rdataset_disassociate(
954 tresult
= dns_rdatasetiter_next(rdsiter
);
956 if (tresult
== ISC_R_SUCCESS
&&
957 rctx
->rdataset
== NULL
) {
958 tresult
= getrdataset(mctx
,
960 if (tresult
!= ISC_R_SUCCESS
) {
968 * We didn't match any rdatasets (which means
969 * something went wrong in this
972 result
= DNS_R_SERVFAIL
; /* better code? */
974 ISC_LIST_APPEND(rctx
->namelist
, ansname
, link
);
977 dns_rdatasetiter_destroy(&rdsiter
);
978 if (tresult
!= ISC_R_NOMORE
)
979 result
= DNS_R_SERVFAIL
; /* ditto */
981 result
= ISC_R_SUCCESS
;
985 * This is the "normal" case -- an ordinary question
986 * to which we've got the answer.
988 ISC_LIST_APPEND(ansname
->list
, rctx
->rdataset
, link
);
989 rctx
->rdataset
= NULL
;
990 if (rctx
->sigrdataset
!= NULL
) {
991 ISC_LIST_APPEND(ansname
->list
,
992 rctx
->sigrdataset
, link
);
993 rctx
->sigrdataset
= NULL
;
995 ISC_LIST_APPEND(rctx
->namelist
, ansname
, link
);
1001 * Free temporary resources
1003 if (ansname
!= NULL
) {
1004 dns_rdataset_t
*rdataset
;
1006 while ((rdataset
= ISC_LIST_HEAD(ansname
->list
))
1008 ISC_LIST_UNLINK(ansname
->list
, rdataset
, link
);
1009 putrdataset(mctx
, &rdataset
);
1011 dns_name_free(ansname
, mctx
);
1012 isc_mem_put(mctx
, ansname
, sizeof(*ansname
));
1016 dns_db_detachnode(db
, &node
);
1020 isc_event_free(ISC_EVENT_PTR(&event
));
1023 * Limit the number of restarts.
1025 if (want_restart
&& rctx
->restarts
== MAX_RESTARTS
) {
1026 want_restart
= ISC_FALSE
;
1027 result
= ISC_R_QUOTA
;
1028 send_event
= ISC_TRUE
;
1032 * Prepare further find with new resources
1035 INSIST(rctx
->rdataset
== NULL
&&
1036 rctx
->sigrdataset
== NULL
);
1038 result
= getrdataset(mctx
, &rctx
->rdataset
);
1039 if (result
== ISC_R_SUCCESS
&& rctx
->want_dnssec
) {
1040 result
= getrdataset(mctx
, &rctx
->sigrdataset
);
1041 if (result
!= ISC_R_SUCCESS
) {
1042 putrdataset(mctx
, &rctx
->rdataset
);
1046 if (result
!= ISC_R_SUCCESS
) {
1047 want_restart
= ISC_FALSE
;
1048 send_event
= ISC_TRUE
;
1051 } while (want_restart
);
1056 while ((name
= ISC_LIST_HEAD(rctx
->namelist
)) != NULL
) {
1057 ISC_LIST_UNLINK(rctx
->namelist
, name
, link
);
1058 ISC_LIST_APPEND(rctx
->event
->answerlist
, name
, link
);
1061 rctx
->event
->result
= result
;
1062 rctx
->event
->vresult
= vresult
;
1063 task
= rctx
->event
->ev_sender
;
1064 rctx
->event
->ev_sender
= rctx
;
1065 isc_task_sendanddetach(&task
, ISC_EVENT_PTR(&rctx
->event
));
1068 UNLOCK(&rctx
->lock
);
1072 resolve_done(isc_task_t
*task
, isc_event_t
*event
) {
1073 resarg_t
*resarg
= event
->ev_arg
;
1074 dns_clientresevent_t
*rev
= (dns_clientresevent_t
*)event
;
1079 LOCK(&resarg
->lock
);
1081 resarg
->result
= rev
->result
;
1082 resarg
->vresult
= rev
->vresult
;
1083 while ((name
= ISC_LIST_HEAD(rev
->answerlist
)) != NULL
) {
1084 ISC_LIST_UNLINK(rev
->answerlist
, name
, link
);
1085 ISC_LIST_APPEND(*resarg
->namelist
, name
, link
);
1088 dns_client_destroyrestrans(&resarg
->trans
);
1089 isc_event_free(&event
);
1091 if (!resarg
->canceled
) {
1092 UNLOCK(&resarg
->lock
);
1094 /* Exit from the internal event loop */
1095 isc_app_ctxsuspend(resarg
->actx
);
1098 * We have already exited from the loop (due to some
1099 * unexpected event). Just clean the arg up.
1101 UNLOCK(&resarg
->lock
);
1102 DESTROYLOCK(&resarg
->lock
);
1103 isc_mem_put(resarg
->client
->mctx
, resarg
, sizeof(*resarg
));
1108 dns_client_resolve(dns_client_t
*client
, dns_name_t
*name
,
1109 dns_rdataclass_t rdclass
, dns_rdatatype_t type
,
1110 unsigned int options
, dns_namelist_t
*namelist
)
1112 isc_result_t result
;
1116 REQUIRE(DNS_CLIENT_VALID(client
));
1117 REQUIRE(namelist
!= NULL
&& ISC_LIST_EMPTY(*namelist
));
1119 if ((client
->attributes
& DNS_CLIENTATTR_OWNCTX
) == 0 &&
1120 (options
& DNS_CLIENTRESOPT_ALLOWRUN
) == 0) {
1122 * If the client is run under application's control, we need
1123 * to create a new running (sub)environment for this
1124 * particular resolution.
1126 return (ISC_R_NOTIMPLEMENTED
); /* XXXTBD */
1128 actx
= client
->actx
;
1130 resarg
= isc_mem_get(client
->mctx
, sizeof(*resarg
));
1132 return (ISC_R_NOMEMORY
);
1134 result
= isc_mutex_init(&resarg
->lock
);
1135 if (result
!= ISC_R_SUCCESS
) {
1136 isc_mem_put(client
->mctx
, resarg
, sizeof(*resarg
));
1140 resarg
->actx
= actx
;
1141 resarg
->client
= client
;
1142 resarg
->result
= DNS_R_SERVFAIL
;
1143 resarg
->namelist
= namelist
;
1144 resarg
->trans
= NULL
;
1145 resarg
->canceled
= ISC_FALSE
;
1146 result
= dns_client_startresolve(client
, name
, rdclass
, type
, options
,
1147 client
->task
, resolve_done
, resarg
,
1149 if (result
!= ISC_R_SUCCESS
) {
1150 DESTROYLOCK(&resarg
->lock
);
1151 isc_mem_put(client
->mctx
, resarg
, sizeof(*resarg
));
1156 * Start internal event loop. It blocks until the entire process
1159 result
= isc_app_ctxrun(actx
);
1161 LOCK(&resarg
->lock
);
1162 if (result
== ISC_R_SUCCESS
|| result
== ISC_R_SUSPEND
)
1163 result
= resarg
->result
;
1164 if (result
!= ISC_R_SUCCESS
&& resarg
->vresult
!= ISC_R_SUCCESS
) {
1166 * If this lookup failed due to some error in DNSSEC
1167 * validation, return the validation error code.
1168 * XXX: or should we pass the validation result separately?
1170 result
= resarg
->vresult
;
1172 if (resarg
->trans
!= NULL
) {
1174 * Unusual termination (perhaps due to signal). We need some
1175 * tricky cleanup process.
1177 resarg
->canceled
= ISC_TRUE
;
1178 dns_client_cancelresolve(resarg
->trans
);
1180 UNLOCK(&resarg
->lock
);
1182 /* resarg will be freed in the event handler. */
1184 UNLOCK(&resarg
->lock
);
1186 DESTROYLOCK(&resarg
->lock
);
1187 isc_mem_put(client
->mctx
, resarg
, sizeof(*resarg
));
1194 dns_client_startresolve(dns_client_t
*client
, dns_name_t
*name
,
1195 dns_rdataclass_t rdclass
, dns_rdatatype_t type
,
1196 unsigned int options
, isc_task_t
*task
,
1197 isc_taskaction_t action
, void *arg
,
1198 dns_clientrestrans_t
**transp
)
1200 dns_view_t
*view
= NULL
;
1201 dns_clientresevent_t
*event
= NULL
;
1202 resctx_t
*rctx
= NULL
;
1203 isc_task_t
*clone
= NULL
;
1205 isc_result_t result
;
1206 dns_rdataset_t
*rdataset
, *sigrdataset
;
1207 isc_boolean_t want_dnssec
;
1209 REQUIRE(DNS_CLIENT_VALID(client
));
1210 REQUIRE(transp
!= NULL
&& *transp
== NULL
);
1212 LOCK(&client
->lock
);
1213 result
= dns_viewlist_find(&client
->viewlist
, DNS_CLIENTVIEW_NAME
,
1215 UNLOCK(&client
->lock
);
1216 if (result
!= ISC_R_SUCCESS
)
1219 mctx
= client
->mctx
;
1222 want_dnssec
= ISC_TF((options
& DNS_CLIENTRESOPT_NODNSSEC
) == 0);
1225 * Prepare some intermediate resources
1228 isc_task_attach(task
, &clone
);
1229 event
= (dns_clientresevent_t
*)
1230 isc_event_allocate(mctx
, clone
, DNS_EVENT_CLIENTRESDONE
,
1231 action
, arg
, sizeof(*event
));
1232 if (event
== NULL
) {
1233 result
= ISC_R_NOMEMORY
;
1236 event
->result
= DNS_R_SERVFAIL
;
1237 ISC_LIST_INIT(event
->answerlist
);
1239 rctx
= isc_mem_get(mctx
, sizeof(*rctx
));
1241 result
= ISC_R_NOMEMORY
;
1243 result
= isc_mutex_init(&rctx
->lock
);
1244 if (result
!= ISC_R_SUCCESS
) {
1245 isc_mem_put(mctx
, rctx
, sizeof(*rctx
));
1249 if (result
!= ISC_R_SUCCESS
)
1252 result
= getrdataset(mctx
, &rdataset
);
1253 if (result
!= ISC_R_SUCCESS
)
1255 rctx
->rdataset
= rdataset
;
1258 result
= getrdataset(mctx
, &sigrdataset
);
1259 if (result
!= ISC_R_SUCCESS
)
1262 rctx
->sigrdataset
= sigrdataset
;
1264 dns_fixedname_init(&rctx
->name
);
1265 result
= dns_name_copy(name
, dns_fixedname_name(&rctx
->name
), NULL
);
1266 if (result
!= ISC_R_SUCCESS
)
1269 rctx
->client
= client
;
1270 ISC_LINK_INIT(rctx
, link
);
1271 rctx
->canceled
= ISC_FALSE
;
1272 rctx
->task
= client
->task
;
1277 rctx
->want_dnssec
= want_dnssec
;
1278 ISC_LIST_INIT(rctx
->namelist
);
1279 rctx
->event
= event
;
1281 rctx
->magic
= RCTX_MAGIC
;
1283 LOCK(&client
->lock
);
1284 ISC_LIST_APPEND(client
->resctxs
, rctx
, link
);
1285 UNLOCK(&client
->lock
);
1287 client_resfind(rctx
, NULL
);
1289 *transp
= (dns_clientrestrans_t
*)rctx
;
1291 return (ISC_R_SUCCESS
);
1294 if (rdataset
!= NULL
)
1295 putrdataset(client
->mctx
, &rdataset
);
1296 if (sigrdataset
!= NULL
)
1297 putrdataset(client
->mctx
, &sigrdataset
);
1299 DESTROYLOCK(&rctx
->lock
);
1300 isc_mem_put(mctx
, rctx
, sizeof(*rctx
));
1303 isc_event_free(ISC_EVENT_PTR(&event
));
1304 isc_task_detach(&clone
);
1305 dns_view_detach(&view
);
1311 dns_client_cancelresolve(dns_clientrestrans_t
*trans
) {
1314 REQUIRE(trans
!= NULL
);
1315 rctx
= (resctx_t
*)trans
;
1316 REQUIRE(RCTX_VALID(rctx
));
1320 if (!rctx
->canceled
) {
1321 rctx
->canceled
= ISC_TRUE
;
1322 if (rctx
->fetch
!= NULL
)
1323 dns_resolver_cancelfetch(rctx
->fetch
);
1326 UNLOCK(&rctx
->lock
);
1330 dns_client_freeresanswer(dns_client_t
*client
, dns_namelist_t
*namelist
) {
1332 dns_rdataset_t
*rdataset
;
1334 REQUIRE(DNS_CLIENT_VALID(client
));
1335 REQUIRE(namelist
!= NULL
);
1337 while ((name
= ISC_LIST_HEAD(*namelist
)) != NULL
) {
1338 ISC_LIST_UNLINK(*namelist
, name
, link
);
1339 while ((rdataset
= ISC_LIST_HEAD(name
->list
)) != NULL
) {
1340 ISC_LIST_UNLINK(name
->list
, rdataset
, link
);
1341 putrdataset(client
->mctx
, &rdataset
);
1343 dns_name_free(name
, client
->mctx
);
1344 isc_mem_put(client
->mctx
, name
, sizeof(*name
));
1349 dns_client_destroyrestrans(dns_clientrestrans_t
**transp
) {
1352 dns_client_t
*client
;
1353 isc_boolean_t need_destroyclient
= ISC_FALSE
;
1355 REQUIRE(transp
!= NULL
);
1356 rctx
= (resctx_t
*)*transp
;
1357 REQUIRE(RCTX_VALID(rctx
));
1358 REQUIRE(rctx
->fetch
== NULL
);
1359 REQUIRE(rctx
->event
== NULL
);
1360 client
= rctx
->client
;
1361 REQUIRE(DNS_CLIENT_VALID(client
));
1363 mctx
= client
->mctx
;
1364 dns_view_detach(&rctx
->view
);
1366 LOCK(&client
->lock
);
1368 INSIST(ISC_LINK_LINKED(rctx
, link
));
1369 ISC_LIST_UNLINK(client
->resctxs
, rctx
, link
);
1371 if (client
->references
== 0 && ISC_LIST_EMPTY(client
->resctxs
) &&
1372 ISC_LIST_EMPTY(client
->reqctxs
) &&
1373 ISC_LIST_EMPTY(client
->updatectxs
))
1374 need_destroyclient
= ISC_TRUE
;
1376 UNLOCK(&client
->lock
);
1378 INSIST(ISC_LIST_EMPTY(rctx
->namelist
));
1380 DESTROYLOCK(&rctx
->lock
);
1383 isc_mem_put(mctx
, rctx
, sizeof(*rctx
));
1385 if (need_destroyclient
)
1386 destroyclient(&client
);
1392 dns_client_addtrustedkey(dns_client_t
*client
, dns_rdataclass_t rdclass
,
1393 dns_name_t
*keyname
, isc_buffer_t
*keydatabuf
)
1395 isc_result_t result
;
1396 dns_view_t
*view
= NULL
;
1397 dst_key_t
*dstkey
= NULL
;
1398 dns_keytable_t
*secroots
= NULL
;
1400 REQUIRE(DNS_CLIENT_VALID(client
));
1402 LOCK(&client
->lock
);
1403 result
= dns_viewlist_find(&client
->viewlist
, DNS_CLIENTVIEW_NAME
,
1405 UNLOCK(&client
->lock
);
1406 if (result
!= ISC_R_SUCCESS
)
1409 result
= dns_view_getsecroots(view
, &secroots
);
1410 if (result
!= ISC_R_SUCCESS
)
1413 result
= dst_key_fromdns(keyname
, rdclass
, keydatabuf
, client
->mctx
,
1415 if (result
!= ISC_R_SUCCESS
)
1418 result
= dns_keytable_add(secroots
, ISC_FALSE
, &dstkey
);
1422 dns_view_detach(&view
);
1423 if (secroots
!= NULL
)
1424 dns_keytable_detach(&secroots
);
1429 * Simple request routines
1432 request_done(isc_task_t
*task
, isc_event_t
*event
) {
1433 dns_requestevent_t
*reqev
= NULL
;
1434 dns_request_t
*request
;
1435 isc_result_t result
, eresult
;
1440 REQUIRE(event
->ev_type
== DNS_EVENT_REQUESTDONE
);
1441 reqev
= (dns_requestevent_t
*)event
;
1442 request
= reqev
->request
;
1443 result
= eresult
= reqev
->result
;
1444 ctx
= reqev
->ev_arg
;
1445 REQUIRE(REQCTX_VALID(ctx
));
1447 isc_event_free(&event
);
1451 if (eresult
== ISC_R_SUCCESS
) {
1452 result
= dns_request_getresponse(request
, ctx
->event
->rmessage
,
1456 if (ctx
->tsigkey
!= NULL
)
1457 dns_tsigkey_detach(&ctx
->tsigkey
);
1460 ctx
->event
->result
= ISC_R_CANCELED
;
1462 ctx
->event
->result
= result
;
1463 task
= ctx
->event
->ev_sender
;
1464 ctx
->event
->ev_sender
= ctx
;
1465 isc_task_sendanddetach(&task
, ISC_EVENT_PTR(&ctx
->event
));
1471 localrequest_done(isc_task_t
*task
, isc_event_t
*event
) {
1472 reqarg_t
*reqarg
= event
->ev_arg
;
1473 dns_clientreqevent_t
*rev
=(dns_clientreqevent_t
*)event
;
1477 REQUIRE(event
->ev_type
== DNS_EVENT_CLIENTREQDONE
);
1479 LOCK(&reqarg
->lock
);
1481 reqarg
->result
= rev
->result
;
1482 dns_client_destroyreqtrans(&reqarg
->trans
);
1483 isc_event_free(&event
);
1485 if (!reqarg
->canceled
) {
1486 UNLOCK(&reqarg
->lock
);
1488 /* Exit from the internal event loop */
1489 isc_app_ctxsuspend(reqarg
->actx
);
1492 * We have already exited from the loop (due to some
1493 * unexpected event). Just clean the arg up.
1495 UNLOCK(&reqarg
->lock
);
1496 DESTROYLOCK(&reqarg
->lock
);
1497 isc_mem_put(reqarg
->client
->mctx
, reqarg
, sizeof(*reqarg
));
1502 dns_client_request(dns_client_t
*client
, dns_message_t
*qmessage
,
1503 dns_message_t
*rmessage
, isc_sockaddr_t
*server
,
1504 unsigned int options
, unsigned int parseoptions
,
1505 dns_tsec_t
*tsec
, unsigned int timeout
,
1506 unsigned int udptimeout
, unsigned int udpretries
)
1510 isc_result_t result
;
1512 REQUIRE(DNS_CLIENT_VALID(client
));
1513 REQUIRE(qmessage
!= NULL
);
1514 REQUIRE(rmessage
!= NULL
);
1516 if ((client
->attributes
& DNS_CLIENTATTR_OWNCTX
) == 0 &&
1517 (options
& DNS_CLIENTREQOPT_ALLOWRUN
) == 0) {
1519 * If the client is run under application's control, we need
1520 * to create a new running (sub)environment for this
1521 * particular resolution.
1523 return (ISC_R_NOTIMPLEMENTED
); /* XXXTBD */
1525 actx
= client
->actx
;
1527 reqarg
= isc_mem_get(client
->mctx
, sizeof(*reqarg
));
1529 return (ISC_R_NOMEMORY
);
1531 result
= isc_mutex_init(&reqarg
->lock
);
1532 if (result
!= ISC_R_SUCCESS
) {
1533 isc_mem_put(client
->mctx
, reqarg
, sizeof(*reqarg
));
1537 reqarg
->actx
= actx
;
1538 reqarg
->client
= client
;
1539 reqarg
->trans
= NULL
;
1540 reqarg
->canceled
= ISC_FALSE
;
1542 result
= dns_client_startrequest(client
, qmessage
, rmessage
, server
,
1543 options
, parseoptions
, tsec
, timeout
,
1544 udptimeout
, udpretries
,
1545 client
->task
, localrequest_done
,
1546 reqarg
, &reqarg
->trans
);
1547 if (result
!= ISC_R_SUCCESS
) {
1548 DESTROYLOCK(&reqarg
->lock
);
1549 isc_mem_put(client
->mctx
, reqarg
, sizeof(*reqarg
));
1554 * Start internal event loop. It blocks until the entire process
1557 result
= isc_app_ctxrun(actx
);
1559 LOCK(&reqarg
->lock
);
1560 if (result
== ISC_R_SUCCESS
|| result
== ISC_R_SUSPEND
)
1561 result
= reqarg
->result
;
1562 if (reqarg
->trans
!= NULL
) {
1564 * Unusual termination (perhaps due to signal). We need some
1565 * tricky cleanup process.
1567 reqarg
->canceled
= ISC_TRUE
;
1568 dns_client_cancelresolve(reqarg
->trans
);
1570 UNLOCK(&reqarg
->lock
);
1572 /* reqarg will be freed in the event handler. */
1574 UNLOCK(&reqarg
->lock
);
1576 DESTROYLOCK(&reqarg
->lock
);
1577 isc_mem_put(client
->mctx
, reqarg
, sizeof(*reqarg
));
1584 dns_client_startrequest(dns_client_t
*client
, dns_message_t
*qmessage
,
1585 dns_message_t
*rmessage
, isc_sockaddr_t
*server
,
1586 unsigned int options
, unsigned int parseoptions
,
1587 dns_tsec_t
*tsec
, unsigned int timeout
,
1588 unsigned int udptimeout
, unsigned int udpretries
,
1589 isc_task_t
*task
, isc_taskaction_t action
, void *arg
,
1590 dns_clientreqtrans_t
**transp
)
1592 isc_result_t result
;
1593 dns_view_t
*view
= NULL
;
1594 isc_task_t
*clone
= NULL
;
1595 dns_clientreqevent_t
*event
= NULL
;
1596 reqctx_t
*ctx
= NULL
;
1597 dns_tsectype_t tsectype
= dns_tsectype_none
;
1601 REQUIRE(DNS_CLIENT_VALID(client
));
1602 REQUIRE(qmessage
!= NULL
);
1603 REQUIRE(rmessage
!= NULL
);
1604 REQUIRE(transp
!= NULL
&& *transp
== NULL
);
1607 tsectype
= dns_tsec_gettype(tsec
);
1608 if (tsectype
!= dns_tsectype_tsig
)
1609 return (ISC_R_NOTIMPLEMENTED
); /* XXX */
1612 LOCK(&client
->lock
);
1613 result
= dns_viewlist_find(&client
->viewlist
, DNS_CLIENTVIEW_NAME
,
1614 qmessage
->rdclass
, &view
);
1615 UNLOCK(&client
->lock
);
1616 if (result
!= ISC_R_SUCCESS
)
1620 isc_task_attach(task
, &clone
);
1621 event
= (dns_clientreqevent_t
*)
1622 isc_event_allocate(client
->mctx
, clone
,
1623 DNS_EVENT_CLIENTREQDONE
,
1624 action
, arg
, sizeof(*event
));
1625 if (event
== NULL
) {
1626 result
= ISC_R_NOMEMORY
;
1630 ctx
= isc_mem_get(client
->mctx
, sizeof(*ctx
));
1632 result
= ISC_R_NOMEMORY
;
1634 result
= isc_mutex_init(&ctx
->lock
);
1635 if (result
!= ISC_R_SUCCESS
) {
1636 isc_mem_put(client
->mctx
, ctx
, sizeof(*ctx
));
1640 if (result
!= ISC_R_SUCCESS
)
1643 ctx
->client
= client
;
1644 ISC_LINK_INIT(ctx
, link
);
1645 ctx
->parseoptions
= parseoptions
;
1646 ctx
->canceled
= ISC_FALSE
;
1648 ctx
->event
->rmessage
= rmessage
;
1649 ctx
->tsigkey
= NULL
;
1651 dns_tsec_getkey(tsec
, &ctx
->tsigkey
);
1653 ctx
->magic
= REQCTX_MAGIC
;
1655 LOCK(&client
->lock
);
1656 ISC_LIST_APPEND(client
->reqctxs
, ctx
, link
);
1657 UNLOCK(&client
->lock
);
1659 ctx
->request
= NULL
;
1660 result
= dns_request_createvia3(view
->requestmgr
, qmessage
, NULL
,
1661 server
, options
, ctx
->tsigkey
,
1662 timeout
, udptimeout
, udpretries
,
1663 client
->task
, request_done
, ctx
,
1665 if (result
== ISC_R_SUCCESS
) {
1666 dns_view_detach(&view
);
1667 *transp
= (dns_clientreqtrans_t
*)ctx
;
1668 return (ISC_R_SUCCESS
);
1673 LOCK(&client
->lock
);
1674 ISC_LIST_UNLINK(client
->reqctxs
, ctx
, link
);
1675 UNLOCK(&client
->lock
);
1676 DESTROYLOCK(&ctx
->lock
);
1677 isc_mem_put(client
->mctx
, ctx
, sizeof(*ctx
));
1680 isc_event_free(ISC_EVENT_PTR(&event
));
1681 isc_task_detach(&clone
);
1682 dns_view_detach(&view
);
1688 dns_client_cancelrequest(dns_clientreqtrans_t
*trans
) {
1691 REQUIRE(trans
!= NULL
);
1692 ctx
= (reqctx_t
*)trans
;
1693 REQUIRE(REQCTX_VALID(ctx
));
1697 if (!ctx
->canceled
) {
1698 ctx
->canceled
= ISC_TRUE
;
1699 if (ctx
->request
!= NULL
)
1700 dns_request_cancel(ctx
->request
);
1707 dns_client_destroyreqtrans(dns_clientreqtrans_t
**transp
) {
1710 dns_client_t
*client
;
1711 isc_boolean_t need_destroyclient
= ISC_FALSE
;
1713 REQUIRE(transp
!= NULL
);
1714 ctx
= (reqctx_t
*)*transp
;
1715 REQUIRE(REQCTX_VALID(ctx
));
1716 client
= ctx
->client
;
1717 REQUIRE(DNS_CLIENT_VALID(client
));
1718 REQUIRE(ctx
->event
== NULL
);
1719 REQUIRE(ctx
->request
!= NULL
);
1721 dns_request_destroy(&ctx
->request
);
1722 mctx
= client
->mctx
;
1724 LOCK(&client
->lock
);
1726 INSIST(ISC_LINK_LINKED(ctx
, link
));
1727 ISC_LIST_UNLINK(client
->reqctxs
, ctx
, link
);
1729 if (client
->references
== 0 && ISC_LIST_EMPTY(client
->resctxs
) &&
1730 ISC_LIST_EMPTY(client
->reqctxs
) &&
1731 ISC_LIST_EMPTY(client
->updatectxs
)) {
1732 need_destroyclient
= ISC_TRUE
;
1735 UNLOCK(&client
->lock
);
1737 DESTROYLOCK(&ctx
->lock
);
1740 isc_mem_put(mctx
, ctx
, sizeof(*ctx
));
1742 if (need_destroyclient
)
1743 destroyclient(&client
);
1749 * Dynamic update routines
1752 rcode2result(dns_rcode_t rcode
) {
1753 /* XXX: isn't there a similar function? */
1755 case dns_rcode_formerr
:
1756 return (DNS_R_FORMERR
);
1757 case dns_rcode_servfail
:
1758 return (DNS_R_SERVFAIL
);
1759 case dns_rcode_nxdomain
:
1760 return (DNS_R_NXDOMAIN
);
1761 case dns_rcode_notimp
:
1762 return (DNS_R_NOTIMP
);
1763 case dns_rcode_refused
:
1764 return (DNS_R_REFUSED
);
1765 case dns_rcode_yxdomain
:
1766 return (DNS_R_YXDOMAIN
);
1767 case dns_rcode_yxrrset
:
1768 return (DNS_R_YXRRSET
);
1769 case dns_rcode_nxrrset
:
1770 return (DNS_R_NXRRSET
);
1771 case dns_rcode_notauth
:
1772 return (DNS_R_NOTAUTH
);
1773 case dns_rcode_notzone
:
1774 return (DNS_R_NOTZONE
);
1775 case dns_rcode_badvers
:
1776 return (DNS_R_BADVERS
);
1779 return (ISC_R_FAILURE
);
1783 update_sendevent(updatectx_t
*uctx
, isc_result_t result
) {
1786 dns_message_destroy(&uctx
->updatemsg
);
1787 if (uctx
->tsigkey
!= NULL
)
1788 dns_tsigkey_detach(&uctx
->tsigkey
);
1789 if (uctx
->sig0key
!= NULL
)
1790 dst_key_free(&uctx
->sig0key
);
1793 uctx
->event
->result
= ISC_R_CANCELED
;
1795 uctx
->event
->result
= result
;
1796 uctx
->event
->state
= uctx
->state
;
1797 task
= uctx
->event
->ev_sender
;
1798 uctx
->event
->ev_sender
= uctx
;
1799 isc_task_sendanddetach(&task
, ISC_EVENT_PTR(&uctx
->event
));
1803 update_done(isc_task_t
*task
, isc_event_t
*event
) {
1804 isc_result_t result
;
1805 dns_requestevent_t
*reqev
= NULL
;
1806 dns_request_t
*request
;
1807 dns_message_t
*answer
= NULL
;
1808 updatectx_t
*uctx
= event
->ev_arg
;
1809 dns_client_t
*client
;
1810 unsigned int timeout
;
1814 REQUIRE(event
->ev_type
== DNS_EVENT_REQUESTDONE
);
1815 reqev
= (dns_requestevent_t
*)event
;
1816 request
= reqev
->request
;
1817 REQUIRE(UCTX_VALID(uctx
));
1818 client
= uctx
->client
;
1819 REQUIRE(DNS_CLIENT_VALID(client
));
1821 result
= reqev
->result
;
1822 if (result
!= ISC_R_SUCCESS
)
1825 result
= dns_message_create(client
->mctx
, DNS_MESSAGE_INTENTPARSE
,
1827 if (result
!= ISC_R_SUCCESS
)
1829 uctx
->state
= dns_clientupdatestate_done
;
1830 result
= dns_request_getresponse(request
, answer
,
1831 DNS_MESSAGEPARSE_PRESERVEORDER
);
1832 if (result
== ISC_R_SUCCESS
&& answer
->rcode
!= dns_rcode_noerror
)
1833 result
= rcode2result(answer
->rcode
);
1837 dns_message_destroy(&answer
);
1838 isc_event_free(&event
);
1841 uctx
->currentserver
= ISC_LIST_NEXT(uctx
->currentserver
, link
);
1842 dns_request_destroy(&uctx
->updatereq
);
1843 if (result
!= ISC_R_SUCCESS
&& !uctx
->canceled
&&
1844 uctx
->currentserver
!= NULL
) {
1845 dns_message_renderreset(uctx
->updatemsg
);
1846 dns_message_settsigkey(uctx
->updatemsg
, NULL
);
1848 timeout
= client
->update_timeout
/ uctx
->nservers
;
1849 if (timeout
< MIN_UPDATE_TIMEOUT
)
1850 timeout
= MIN_UPDATE_TIMEOUT
;
1851 result
= dns_request_createvia3(uctx
->view
->requestmgr
,
1854 uctx
->currentserver
, 0,
1857 client
->update_udptimeout
,
1858 client
->update_udpretries
,
1862 UNLOCK(&uctx
->lock
);
1864 if (result
== ISC_R_SUCCESS
) {
1865 /* XXX: should we keep the 'done' state here? */
1866 uctx
->state
= dns_clientupdatestate_sent
;
1870 UNLOCK(&uctx
->lock
);
1872 update_sendevent(uctx
, result
);
1876 send_update(updatectx_t
*uctx
) {
1877 isc_result_t result
;
1878 dns_name_t
*name
= NULL
;
1879 dns_rdataset_t
*rdataset
= NULL
;
1880 dns_client_t
*client
= uctx
->client
;
1881 unsigned int timeout
;
1883 REQUIRE(uctx
->zonename
!= NULL
&& uctx
->currentserver
!= NULL
);
1885 result
= dns_message_gettempname(uctx
->updatemsg
, &name
);
1886 if (result
!= ISC_R_SUCCESS
)
1888 dns_name_init(name
, NULL
);
1889 dns_name_clone(uctx
->zonename
, name
);
1890 result
= dns_message_gettemprdataset(uctx
->updatemsg
, &rdataset
);
1891 if (result
!= ISC_R_SUCCESS
) {
1892 dns_message_puttempname(uctx
->updatemsg
, &name
);
1895 dns_rdataset_makequestion(rdataset
, uctx
->rdclass
, dns_rdatatype_soa
);
1896 ISC_LIST_INIT(name
->list
);
1897 ISC_LIST_APPEND(name
->list
, rdataset
, link
);
1898 dns_message_addname(uctx
->updatemsg
, name
, DNS_SECTION_ZONE
);
1899 if (uctx
->tsigkey
== NULL
&& uctx
->sig0key
!= NULL
) {
1900 result
= dns_message_setsig0key(uctx
->updatemsg
,
1902 if (result
!= ISC_R_SUCCESS
)
1905 timeout
= client
->update_timeout
/ uctx
->nservers
;
1906 if (timeout
< MIN_UPDATE_TIMEOUT
)
1907 timeout
= MIN_UPDATE_TIMEOUT
;
1908 result
= dns_request_createvia3(uctx
->view
->requestmgr
,
1910 NULL
, uctx
->currentserver
, 0,
1911 uctx
->tsigkey
, timeout
,
1912 client
->update_udptimeout
,
1913 client
->update_udpretries
,
1914 client
->task
, update_done
, uctx
,
1916 if (result
== ISC_R_SUCCESS
&&
1917 uctx
->state
== dns_clientupdatestate_prepare
) {
1918 uctx
->state
= dns_clientupdatestate_sent
;
1925 resolveaddr_done(isc_task_t
*task
, isc_event_t
*event
) {
1926 isc_result_t result
;
1928 dns_rdatatype_t qtype
;
1929 dns_clientresevent_t
*rev
= (dns_clientresevent_t
*)event
;
1931 dns_rdataset_t
*rdataset
;
1933 isc_boolean_t completed
= ISC_FALSE
;
1937 REQUIRE(event
->ev_arg
!= NULL
);
1938 uctx
= *(updatectx_t
**)event
->ev_arg
;
1939 REQUIRE(UCTX_VALID(uctx
));
1941 if (event
->ev_arg
== &uctx
->bp4
) {
1943 qtype
= dns_rdatatype_a
;
1945 dns_client_destroyrestrans(&uctx
->restrans
);
1946 UNLOCK(&uctx
->lock
);
1948 INSIST(event
->ev_arg
== &uctx
->bp6
);
1950 qtype
= dns_rdatatype_aaaa
;
1952 dns_client_destroyrestrans(&uctx
->restrans2
);
1953 UNLOCK(&uctx
->lock
);
1956 result
= rev
->result
;
1957 if (result
!= ISC_R_SUCCESS
)
1960 for (name
= ISC_LIST_HEAD(rev
->answerlist
); name
!= NULL
;
1961 name
= ISC_LIST_NEXT(name
, link
)) {
1962 for (rdataset
= ISC_LIST_HEAD(name
->list
);
1964 rdataset
= ISC_LIST_NEXT(rdataset
, link
)) {
1965 if (!dns_rdataset_isassociated(rdataset
))
1967 if (rdataset
->type
!= qtype
)
1970 for (result
= dns_rdataset_first(rdataset
);
1971 result
== ISC_R_SUCCESS
;
1972 result
= dns_rdataset_next(rdataset
)) {
1974 dns_rdata_in_a_t rdata_a
;
1975 dns_rdata_in_aaaa_t rdata_aaaa
;
1978 sa
= isc_mem_get(uctx
->client
->mctx
,
1982 * If we fail to get a sockaddr,
1983 we simply move forward with the
1984 * addresses we've got so far.
1989 dns_rdata_init(&rdata
);
1992 dns_rdataset_current(rdataset
, &rdata
);
1993 dns_rdata_tostruct(&rdata
, &rdata_a
,
1995 isc_sockaddr_fromin(sa
,
1998 dns_rdata_freestruct(&rdata_a
);
2001 dns_rdataset_current(rdataset
, &rdata
);
2002 dns_rdata_tostruct(&rdata
, &rdata_aaaa
,
2004 isc_sockaddr_fromin6(sa
,
2005 &rdata_aaaa
.in6_addr
,
2007 dns_rdata_freestruct(&rdata_aaaa
);
2011 ISC_LINK_INIT(sa
, link
);
2012 ISC_LIST_APPEND(uctx
->servers
, sa
, link
);
2019 dns_client_freeresanswer(uctx
->client
, &rev
->answerlist
);
2020 isc_event_free(&event
);
2023 if (uctx
->restrans
== NULL
&& uctx
->restrans2
== NULL
)
2024 completed
= ISC_TRUE
;
2025 UNLOCK(&uctx
->lock
);
2028 INSIST(uctx
->currentserver
== NULL
);
2029 uctx
->currentserver
= ISC_LIST_HEAD(uctx
->servers
);
2030 if (uctx
->currentserver
!= NULL
&& !uctx
->canceled
)
2033 if (result
== ISC_R_SUCCESS
)
2034 result
= ISC_R_NOTFOUND
;
2035 update_sendevent(uctx
, result
);
2041 process_soa(updatectx_t
*uctx
, dns_rdataset_t
*soaset
, dns_name_t
*soaname
) {
2042 isc_result_t result
;
2043 dns_rdata_t soarr
= DNS_RDATA_INIT
;
2044 dns_rdata_soa_t soa
;
2047 result
= dns_rdataset_first(soaset
);
2048 if (result
!= ISC_R_SUCCESS
)
2050 dns_rdata_init(&soarr
);
2051 dns_rdataset_current(soaset
, &soarr
);
2052 result
= dns_rdata_tostruct(&soarr
, &soa
, NULL
);
2053 if (result
!= ISC_R_SUCCESS
)
2056 dns_name_init(&primary
, NULL
);
2057 dns_name_clone(&soa
.origin
, &primary
);
2059 if (uctx
->zonename
== NULL
) {
2060 uctx
->zonename
= dns_fixedname_name(&uctx
->zonefname
);
2061 result
= dns_name_copy(soaname
, uctx
->zonename
, NULL
);
2062 if (result
!= ISC_R_SUCCESS
)
2066 if (uctx
->currentserver
!= NULL
)
2067 result
= send_update(uctx
);
2070 * Get addresses of the primary server. We don't use the ADB
2071 * feature so that we could avoid caching data.
2075 result
= dns_client_startresolve(uctx
->client
, &primary
,
2078 0, uctx
->client
->task
,
2079 resolveaddr_done
, &uctx
->bp4
,
2081 if (result
== ISC_R_SUCCESS
) {
2083 result
= dns_client_startresolve(uctx
->client
,
2087 0, uctx
->client
->task
,
2092 UNLOCK(&uctx
->lock
);
2096 dns_rdata_freestruct(&soa
);
2102 receive_soa(isc_task_t
*task
, isc_event_t
*event
) {
2103 dns_requestevent_t
*reqev
= NULL
;
2105 dns_client_t
*client
;
2106 isc_result_t result
, eresult
;
2107 dns_request_t
*request
;
2108 dns_message_t
*rcvmsg
= NULL
;
2109 dns_section_t section
;
2110 dns_rdataset_t
*soaset
= NULL
;
2113 dns_message_t
*soaquery
= NULL
;
2114 isc_sockaddr_t
*addr
;
2115 isc_boolean_t seencname
= ISC_FALSE
;
2116 isc_boolean_t droplabel
= ISC_FALSE
;
2118 unsigned int nlabels
;
2122 REQUIRE(event
->ev_type
== DNS_EVENT_REQUESTDONE
);
2123 reqev
= (dns_requestevent_t
*)event
;
2124 request
= reqev
->request
;
2125 result
= eresult
= reqev
->result
;
2126 uctx
= reqev
->ev_arg
;
2127 client
= uctx
->client
;
2128 soaquery
= uctx
->soaquery
;
2129 addr
= uctx
->currentserver
;
2130 INSIST(addr
!= NULL
);
2132 isc_event_free(&event
);
2134 if (eresult
!= ISC_R_SUCCESS
) {
2139 result
= dns_message_create(uctx
->client
->mctx
,
2140 DNS_MESSAGE_INTENTPARSE
, &rcvmsg
);
2141 if (result
!= ISC_R_SUCCESS
)
2143 result
= dns_request_getresponse(request
, rcvmsg
,
2144 DNS_MESSAGEPARSE_PRESERVEORDER
);
2146 if (result
== DNS_R_TSIGERRORSET
) {
2147 dns_request_t
*newrequest
= NULL
;
2149 /* Retry SOA request without TSIG */
2150 dns_message_destroy(&rcvmsg
);
2151 dns_message_renderreset(uctx
->soaquery
);
2152 result
= dns_request_createvia3(uctx
->view
->requestmgr
,
2153 uctx
->soaquery
, NULL
, addr
, 0,
2155 client
->find_timeout
* 20,
2156 client
->find_timeout
, 3,
2160 if (result
== ISC_R_SUCCESS
) {
2162 dns_request_destroy(&uctx
->soareq
);
2163 uctx
->soareq
= newrequest
;
2164 UNLOCK(&uctx
->lock
);
2171 section
= DNS_SECTION_ANSWER
;
2173 if (rcvmsg
->rcode
!= dns_rcode_noerror
&&
2174 rcvmsg
->rcode
!= dns_rcode_nxdomain
) {
2175 result
= rcode2result(rcvmsg
->rcode
);
2181 section
= DNS_SECTION_ANSWER
;
2183 section
= DNS_SECTION_AUTHORITY
;
2185 droplabel
= ISC_TRUE
;
2189 result
= dns_message_firstname(rcvmsg
, section
);
2190 if (result
!= ISC_R_SUCCESS
) {
2194 while (result
== ISC_R_SUCCESS
) {
2196 dns_message_currentname(rcvmsg
, section
, &name
);
2198 result
= dns_message_findtype(name
, dns_rdatatype_soa
, 0,
2200 if (result
== ISC_R_SUCCESS
)
2202 if (section
== DNS_SECTION_ANSWER
) {
2203 dns_rdataset_t
*tset
= NULL
;
2204 if (dns_message_findtype(name
, dns_rdatatype_cname
, 0,
2205 &tset
) == ISC_R_SUCCESS
2207 dns_message_findtype(name
, dns_rdatatype_dname
, 0,
2208 &tset
) == ISC_R_SUCCESS
2211 seencname
= ISC_TRUE
;
2216 result
= dns_message_nextname(rcvmsg
, section
);
2219 if (soaset
== NULL
&& !seencname
) {
2225 droplabel
= ISC_TRUE
;
2229 result
= process_soa(uctx
, soaset
, name
);
2233 result
= dns_message_firstname(soaquery
, DNS_SECTION_QUESTION
);
2234 INSIST(result
== ISC_R_SUCCESS
);
2236 dns_message_currentname(soaquery
, DNS_SECTION_QUESTION
, &name
);
2237 nlabels
= dns_name_countlabels(name
);
2239 result
= DNS_R_SERVFAIL
; /* is there a better error? */
2241 dns_name_init(&tname
, NULL
);
2242 dns_name_getlabelsequence(name
, 1, nlabels
- 1,
2244 dns_name_clone(&tname
, name
);
2245 dns_request_destroy(&request
);
2247 uctx
->soareq
= NULL
;
2248 UNLOCK(&uctx
->lock
);
2249 dns_message_renderreset(soaquery
);
2250 dns_message_settsigkey(soaquery
, NULL
);
2251 result
= dns_request_createvia3(uctx
->view
->requestmgr
,
2253 uctx
->currentserver
, 0,
2255 client
->find_timeout
*
2257 client
->find_timeout
,
2264 if (!droplabel
|| result
!= ISC_R_SUCCESS
) {
2265 dns_message_destroy(&uctx
->soaquery
);
2267 dns_request_destroy(&uctx
->soareq
);
2268 UNLOCK(&uctx
->lock
);
2272 dns_message_destroy(&rcvmsg
);
2274 if (result
!= ISC_R_SUCCESS
)
2275 update_sendevent(uctx
, result
);
2279 request_soa(updatectx_t
*uctx
) {
2280 isc_result_t result
;
2281 dns_message_t
*soaquery
= uctx
->soaquery
;
2282 dns_name_t
*name
= NULL
;
2283 dns_rdataset_t
*rdataset
= NULL
;
2285 if (soaquery
== NULL
) {
2286 result
= dns_message_create(uctx
->client
->mctx
,
2287 DNS_MESSAGE_INTENTRENDER
,
2289 if (result
!= ISC_R_SUCCESS
)
2292 soaquery
->flags
|= DNS_MESSAGEFLAG_RD
;
2293 result
= dns_message_gettempname(soaquery
, &name
);
2294 if (result
!= ISC_R_SUCCESS
)
2296 result
= dns_message_gettemprdataset(soaquery
, &rdataset
);
2297 if (result
!= ISC_R_SUCCESS
)
2299 dns_rdataset_makequestion(rdataset
, uctx
->rdclass
, dns_rdatatype_soa
);
2300 dns_name_clone(uctx
->firstname
, name
);
2301 ISC_LIST_APPEND(name
->list
, rdataset
, link
);
2302 dns_message_addname(soaquery
, name
, DNS_SECTION_QUESTION
);
2306 result
= dns_request_createvia3(uctx
->view
->requestmgr
,
2307 soaquery
, NULL
, uctx
->currentserver
, 0,
2309 uctx
->client
->find_timeout
* 20,
2310 uctx
->client
->find_timeout
, 3,
2311 uctx
->client
->task
, receive_soa
, uctx
,
2313 if (result
== ISC_R_SUCCESS
) {
2314 uctx
->soaquery
= soaquery
;
2315 return (ISC_R_SUCCESS
);
2319 if (rdataset
!= NULL
) {
2320 ISC_LIST_UNLINK(name
->list
, rdataset
, link
); /* for safety */
2321 dns_message_puttemprdataset(soaquery
, &rdataset
);
2324 dns_message_puttempname(soaquery
, &name
);
2325 dns_message_destroy(&soaquery
);
2331 resolvesoa_done(isc_task_t
*task
, isc_event_t
*event
) {
2332 dns_clientresevent_t
*rev
= (dns_clientresevent_t
*)event
;
2334 dns_name_t
*name
, tname
;
2335 dns_rdataset_t
*rdataset
= NULL
;
2336 isc_result_t result
= rev
->result
;
2337 unsigned int nlabels
;
2341 uctx
= event
->ev_arg
;
2342 REQUIRE(UCTX_VALID(uctx
));
2345 dns_client_destroyrestrans(&uctx
->restrans
);
2346 UNLOCK(&uctx
->lock
);
2348 uctx
= event
->ev_arg
;
2349 if (result
!= ISC_R_SUCCESS
&&
2350 result
!= DNS_R_NCACHENXDOMAIN
&&
2351 result
!= DNS_R_NCACHENXRRSET
) {
2352 /* XXX: what about DNSSEC failure? */
2356 for (name
= ISC_LIST_HEAD(rev
->answerlist
); name
!= NULL
;
2357 name
= ISC_LIST_NEXT(name
, link
)) {
2358 for (rdataset
= ISC_LIST_HEAD(name
->list
);
2360 rdataset
= ISC_LIST_NEXT(rdataset
, link
)) {
2361 if (dns_rdataset_isassociated(rdataset
) &&
2362 rdataset
->type
== dns_rdatatype_soa
)
2367 if (rdataset
== NULL
) {
2368 /* Drop one label and retry resolution. */
2369 nlabels
= dns_name_countlabels(&uctx
->soaqname
);
2371 result
= DNS_R_SERVFAIL
; /* is there a better error? */
2374 dns_name_init(&tname
, NULL
);
2375 dns_name_getlabelsequence(&uctx
->soaqname
, 1, nlabels
- 1,
2377 dns_name_clone(&tname
, &uctx
->soaqname
);
2379 result
= dns_client_startresolve(uctx
->client
, &uctx
->soaqname
,
2381 dns_rdatatype_soa
, 0,
2383 resolvesoa_done
, uctx
,
2386 result
= process_soa(uctx
, rdataset
, &uctx
->soaqname
);
2389 dns_client_freeresanswer(uctx
->client
, &rev
->answerlist
);
2390 isc_event_free(&event
);
2392 if (result
!= ISC_R_SUCCESS
)
2393 update_sendevent(uctx
, result
);
2397 copy_name(isc_mem_t
*mctx
, dns_message_t
*msg
, dns_name_t
*name
,
2398 dns_name_t
**newnamep
)
2400 isc_result_t result
;
2401 dns_name_t
*newname
= NULL
;
2403 isc_buffer_t
*namebuf
= NULL
, *rdatabuf
= NULL
;
2404 dns_rdatalist_t
*rdatalist
;
2405 dns_rdataset_t
*rdataset
, *newrdataset
;
2406 dns_rdata_t rdata
= DNS_RDATA_INIT
, *newrdata
;
2408 result
= dns_message_gettempname(msg
, &newname
);
2409 if (result
!= ISC_R_SUCCESS
)
2411 result
= isc_buffer_allocate(mctx
, &namebuf
, DNS_NAME_MAXWIRE
);
2412 if (result
!= ISC_R_SUCCESS
)
2414 dns_name_init(newname
, NULL
);
2415 dns_name_setbuffer(newname
, namebuf
);
2416 dns_message_takebuffer(msg
, &namebuf
);
2417 result
= dns_name_copy(name
, newname
, NULL
);
2418 if (result
!= ISC_R_SUCCESS
)
2421 for (rdataset
= ISC_LIST_HEAD(name
->list
); rdataset
!= NULL
;
2422 rdataset
= ISC_LIST_NEXT(rdataset
, link
)) {
2424 result
= dns_message_gettemprdatalist(msg
, &rdatalist
);
2425 if (result
!= ISC_R_SUCCESS
)
2427 dns_rdatalist_init(rdatalist
);
2428 rdatalist
->type
= rdataset
->type
;
2429 rdatalist
->rdclass
= rdataset
->rdclass
;
2430 rdatalist
->covers
= rdataset
->covers
;
2431 rdatalist
->ttl
= rdataset
->ttl
;
2433 result
= dns_rdataset_first(rdataset
);
2434 while (result
== ISC_R_SUCCESS
) {
2435 dns_rdata_reset(&rdata
);
2436 dns_rdataset_current(rdataset
, &rdata
);
2439 result
= dns_message_gettemprdata(msg
, &newrdata
);
2440 if (result
!= ISC_R_SUCCESS
)
2442 dns_rdata_toregion(&rdata
, &r
);
2444 result
= isc_buffer_allocate(mctx
, &rdatabuf
,
2446 if (result
!= ISC_R_SUCCESS
)
2448 isc_buffer_putmem(rdatabuf
, r
.base
, r
.length
);
2449 isc_buffer_usedregion(rdatabuf
, &r
);
2450 dns_rdata_init(newrdata
);
2451 dns_rdata_fromregion(newrdata
, rdata
.rdclass
,
2453 newrdata
->flags
= rdata
.flags
;
2455 ISC_LIST_APPEND(rdatalist
->rdata
, newrdata
, link
);
2456 dns_message_takebuffer(msg
, &rdatabuf
);
2458 result
= dns_rdataset_next(rdataset
);
2462 result
= dns_message_gettemprdataset(msg
, &newrdataset
);
2463 if (result
!= ISC_R_SUCCESS
)
2465 dns_rdataset_init(newrdataset
);
2466 dns_rdatalist_tordataset(rdatalist
, newrdataset
);
2468 ISC_LIST_APPEND(newname
->list
, newrdataset
, link
);
2471 *newnamep
= newname
;
2473 return (ISC_R_SUCCESS
);
2476 dns_message_puttempname(msg
, &newname
);
2483 internal_update_callback(isc_task_t
*task
, isc_event_t
*event
) {
2484 updatearg_t
*uarg
= event
->ev_arg
;
2485 dns_clientupdateevent_t
*uev
= (dns_clientupdateevent_t
*)event
;
2491 uarg
->result
= uev
->result
;
2493 dns_client_destroyupdatetrans(&uarg
->trans
);
2494 isc_event_free(&event
);
2496 if (!uarg
->canceled
) {
2497 UNLOCK(&uarg
->lock
);
2499 /* Exit from the internal event loop */
2500 isc_app_ctxsuspend(uarg
->actx
);
2503 * We have already exited from the loop (due to some
2504 * unexpected event). Just clean the arg up.
2506 UNLOCK(&uarg
->lock
);
2507 DESTROYLOCK(&uarg
->lock
);
2508 isc_mem_put(uarg
->client
->mctx
, uarg
, sizeof(*uarg
));
2513 dns_client_update(dns_client_t
*client
, dns_rdataclass_t rdclass
,
2514 dns_name_t
*zonename
, dns_namelist_t
*prerequisites
,
2515 dns_namelist_t
*updates
, isc_sockaddrlist_t
*servers
,
2516 dns_tsec_t
*tsec
, unsigned int options
)
2518 isc_result_t result
;
2522 REQUIRE(DNS_CLIENT_VALID(client
));
2524 if ((client
->attributes
& DNS_CLIENTATTR_OWNCTX
) == 0 &&
2525 (options
& DNS_CLIENTRESOPT_ALLOWRUN
) == 0) {
2527 * If the client is run under application's control, we need
2528 * to create a new running (sub)environment for this
2529 * particular resolution.
2531 return (ISC_R_NOTIMPLEMENTED
); /* XXXTBD */
2533 actx
= client
->actx
;
2535 uarg
= isc_mem_get(client
->mctx
, sizeof(*uarg
));
2537 return (ISC_R_NOMEMORY
);
2539 result
= isc_mutex_init(&uarg
->lock
);
2540 if (result
!= ISC_R_SUCCESS
) {
2541 isc_mem_put(client
->mctx
, uarg
, sizeof(*uarg
));
2546 uarg
->client
= client
;
2547 uarg
->result
= ISC_R_FAILURE
;
2549 uarg
->canceled
= ISC_FALSE
;
2551 result
= dns_client_startupdate(client
, rdclass
, zonename
,
2552 prerequisites
, updates
, servers
,
2553 tsec
, options
, client
->task
,
2554 internal_update_callback
, uarg
,
2556 if (result
!= ISC_R_SUCCESS
) {
2557 DESTROYLOCK(&uarg
->lock
);
2558 isc_mem_put(client
->mctx
, uarg
, sizeof(*uarg
));
2563 * Start internal event loop. It blocks until the entire process
2566 result
= isc_app_ctxrun(actx
);
2569 if (result
== ISC_R_SUCCESS
|| result
== ISC_R_SUSPEND
)
2570 result
= uarg
->result
;
2572 if (uarg
->trans
!= NULL
) {
2574 * Unusual termination (perhaps due to signal). We need some
2575 * tricky cleanup process.
2577 uarg
->canceled
= ISC_TRUE
;
2578 dns_client_cancelupdate(uarg
->trans
);
2580 UNLOCK(&uarg
->lock
);
2582 /* uarg will be freed in the event handler. */
2584 UNLOCK(&uarg
->lock
);
2586 DESTROYLOCK(&uarg
->lock
);
2587 isc_mem_put(client
->mctx
, uarg
, sizeof(*uarg
));
2594 dns_client_startupdate(dns_client_t
*client
, dns_rdataclass_t rdclass
,
2595 dns_name_t
*zonename
, dns_namelist_t
*prerequisites
,
2596 dns_namelist_t
*updates
, isc_sockaddrlist_t
*servers
,
2597 dns_tsec_t
*tsec
, unsigned int options
,
2598 isc_task_t
*task
, isc_taskaction_t action
, void *arg
,
2599 dns_clientupdatetrans_t
**transp
)
2601 dns_view_t
*view
= NULL
;
2602 isc_result_t result
;
2603 dns_name_t
*name
, *newname
;
2605 isc_task_t
*clone
= NULL
;
2606 dns_section_t section
= DNS_SECTION_UPDATE
;
2607 isc_sockaddr_t
*server
, *sa
= NULL
;
2608 dns_tsectype_t tsectype
= dns_tsectype_none
;
2612 REQUIRE(DNS_CLIENT_VALID(client
));
2613 REQUIRE(transp
!= NULL
&& *transp
== NULL
);
2614 REQUIRE(updates
!= NULL
);
2615 REQUIRE(task
!= NULL
);
2618 tsectype
= dns_tsec_gettype(tsec
);
2619 if (tsectype
!= dns_tsectype_tsig
)
2620 return (ISC_R_NOTIMPLEMENTED
); /* XXX */
2623 LOCK(&client
->lock
);
2624 result
= dns_viewlist_find(&client
->viewlist
, DNS_CLIENTVIEW_NAME
,
2626 UNLOCK(&client
->lock
);
2627 if (result
!= ISC_R_SUCCESS
)
2630 /* Create a context and prepare some resources */
2631 uctx
= isc_mem_get(client
->mctx
, sizeof(*uctx
));
2633 dns_view_detach(&view
);
2634 return (ISC_R_NOMEMORY
);
2636 result
= isc_mutex_init(&uctx
->lock
);
2637 if (result
!= ISC_R_SUCCESS
) {
2638 dns_view_detach(&view
);
2639 isc_mem_put(client
->mctx
, uctx
, sizeof(*uctx
));
2640 return (ISC_R_NOMEMORY
);
2643 isc_task_attach(task
, &clone
);
2644 uctx
->client
= client
;
2645 ISC_LINK_INIT(uctx
, link
);
2646 uctx
->state
= dns_clientupdatestate_prepare
;
2648 uctx
->rdclass
= rdclass
;
2649 uctx
->canceled
= ISC_FALSE
;
2650 uctx
->updatemsg
= NULL
;
2651 uctx
->soaquery
= NULL
;
2652 uctx
->updatereq
= NULL
;
2653 uctx
->restrans
= NULL
;
2654 uctx
->restrans2
= NULL
;
2657 uctx
->soareq
= NULL
;
2659 uctx
->tsigkey
= NULL
;
2660 uctx
->sig0key
= NULL
;
2661 uctx
->zonename
= NULL
;
2662 dns_name_init(&uctx
->soaqname
, NULL
);
2663 ISC_LIST_INIT(uctx
->servers
);
2665 uctx
->currentserver
= NULL
;
2666 dns_fixedname_init(&uctx
->zonefname
);
2668 dns_tsec_getkey(tsec
, &uctx
->tsigkey
);
2669 uctx
->event
= (dns_clientupdateevent_t
*)
2670 isc_event_allocate(client
->mctx
, clone
, DNS_EVENT_UPDATEDONE
,
2671 action
, arg
, sizeof(*uctx
->event
));
2672 if (uctx
->event
== NULL
)
2674 if (zonename
!= NULL
) {
2675 uctx
->zonename
= dns_fixedname_name(&uctx
->zonefname
);
2676 result
= dns_name_copy(zonename
, uctx
->zonename
, NULL
);
2678 if (servers
!= NULL
) {
2679 for (server
= ISC_LIST_HEAD(*servers
);
2681 server
= ISC_LIST_NEXT(server
, link
)) {
2682 sa
= isc_mem_get(client
->mctx
, sizeof(*sa
));
2685 sa
->type
= server
->type
;
2686 sa
->length
= server
->length
;
2687 ISC_LINK_INIT(sa
, link
);
2688 ISC_LIST_APPEND(uctx
->servers
, sa
, link
);
2689 if (uctx
->currentserver
== NULL
)
2690 uctx
->currentserver
= sa
;
2695 /* Make update message */
2696 result
= dns_message_create(client
->mctx
, DNS_MESSAGE_INTENTRENDER
,
2698 if (result
!= ISC_R_SUCCESS
)
2700 uctx
->updatemsg
->opcode
= dns_opcode_update
;
2702 if (prerequisites
!= NULL
) {
2703 for (name
= ISC_LIST_HEAD(*prerequisites
); name
!= NULL
;
2704 name
= ISC_LIST_NEXT(name
, link
)) {
2706 result
= copy_name(client
->mctx
, uctx
->updatemsg
,
2708 if (result
!= ISC_R_SUCCESS
)
2710 dns_message_addname(uctx
->updatemsg
, newname
,
2711 DNS_SECTION_PREREQUISITE
);
2715 for (name
= ISC_LIST_HEAD(*updates
); name
!= NULL
;
2716 name
= ISC_LIST_NEXT(name
, link
)) {
2718 result
= copy_name(client
->mctx
, uctx
->updatemsg
, name
,
2720 if (result
!= ISC_R_SUCCESS
)
2722 dns_message_addname(uctx
->updatemsg
, newname
,
2723 DNS_SECTION_UPDATE
);
2726 uctx
->firstname
= NULL
;
2727 result
= dns_message_firstname(uctx
->updatemsg
, section
);
2728 if (result
== ISC_R_NOMORE
) {
2729 section
= DNS_SECTION_PREREQUISITE
;
2730 result
= dns_message_firstname(uctx
->updatemsg
, section
);
2732 if (result
!= ISC_R_SUCCESS
)
2734 dns_message_currentname(uctx
->updatemsg
, section
, &uctx
->firstname
);
2736 uctx
->magic
= UCTX_MAGIC
;
2738 LOCK(&client
->lock
);
2739 ISC_LIST_APPEND(client
->updatectxs
, uctx
, link
);
2740 UNLOCK(&client
->lock
);
2742 if (uctx
->zonename
!= NULL
&& uctx
->currentserver
!= NULL
) {
2743 result
= send_update(uctx
);
2744 if (result
!= ISC_R_SUCCESS
)
2746 } else if (uctx
->currentserver
!= NULL
) {
2747 result
= request_soa(uctx
);
2748 if (result
!= ISC_R_SUCCESS
)
2751 dns_name_clone(uctx
->firstname
, &uctx
->soaqname
);
2752 result
= dns_client_startresolve(uctx
->client
, &uctx
->soaqname
,
2754 dns_rdatatype_soa
, 0,
2755 client
->task
, resolvesoa_done
,
2756 uctx
, &uctx
->restrans
);
2757 if (result
!= ISC_R_SUCCESS
)
2761 *transp
= (dns_clientupdatetrans_t
*)uctx
;
2763 return (ISC_R_SUCCESS
);
2766 if (ISC_LINK_LINKED(uctx
, link
)) {
2767 LOCK(&client
->lock
);
2768 ISC_LIST_UNLINK(client
->updatectxs
, uctx
, link
);
2769 UNLOCK(&client
->lock
);
2771 if (uctx
->updatemsg
!= NULL
)
2772 dns_message_destroy(&uctx
->updatemsg
);
2773 while ((sa
= ISC_LIST_HEAD(uctx
->servers
)) != NULL
) {
2774 ISC_LIST_UNLINK(uctx
->servers
, sa
, link
);
2775 isc_mem_put(client
->mctx
, sa
, sizeof(*sa
));
2777 if (uctx
->event
!= NULL
)
2778 isc_event_free(ISC_EVENT_PTR(&uctx
->event
));
2779 if (uctx
->tsigkey
!= NULL
)
2780 dns_tsigkey_detach(&uctx
->tsigkey
);
2781 isc_task_detach(&clone
);
2782 DESTROYLOCK(&uctx
->lock
);
2784 isc_mem_put(client
->mctx
, uctx
, sizeof(*uctx
));
2785 dns_view_detach(&view
);
2791 dns_client_cancelupdate(dns_clientupdatetrans_t
*trans
) {
2794 REQUIRE(trans
!= NULL
);
2795 uctx
= (updatectx_t
*)trans
;
2796 REQUIRE(UCTX_VALID(uctx
));
2800 if (!uctx
->canceled
) {
2801 uctx
->canceled
= ISC_TRUE
;
2802 if (uctx
->updatereq
!= NULL
)
2803 dns_request_cancel(uctx
->updatereq
);
2804 if (uctx
->soareq
!= NULL
)
2805 dns_request_cancel(uctx
->soareq
);
2806 if (uctx
->restrans
!= NULL
)
2807 dns_client_cancelresolve(&uctx
->restrans
);
2808 if (uctx
->restrans2
!= NULL
)
2809 dns_client_cancelresolve(&uctx
->restrans2
);
2812 UNLOCK(&uctx
->lock
);
2816 dns_client_destroyupdatetrans(dns_clientupdatetrans_t
**transp
) {
2819 dns_client_t
*client
;
2820 isc_boolean_t need_destroyclient
= ISC_FALSE
;
2823 REQUIRE(transp
!= NULL
);
2824 uctx
= (updatectx_t
*)*transp
;
2825 REQUIRE(UCTX_VALID(uctx
));
2826 client
= uctx
->client
;
2827 REQUIRE(DNS_CLIENT_VALID(client
));
2828 REQUIRE(uctx
->updatereq
== NULL
&& uctx
->updatemsg
== NULL
&&
2829 uctx
->soareq
== NULL
&& uctx
->soaquery
== NULL
&&
2830 uctx
->event
== NULL
&& uctx
->tsigkey
== NULL
&&
2831 uctx
->sig0key
== NULL
);
2833 mctx
= client
->mctx
;
2834 dns_view_detach(&uctx
->view
);
2835 while ((sa
= ISC_LIST_HEAD(uctx
->servers
)) != NULL
) {
2836 ISC_LIST_UNLINK(uctx
->servers
, sa
, link
);
2837 isc_mem_put(mctx
, sa
, sizeof(*sa
));
2840 LOCK(&client
->lock
);
2842 INSIST(ISC_LINK_LINKED(uctx
, link
));
2843 ISC_LIST_UNLINK(client
->updatectxs
, uctx
, link
);
2845 if (client
->references
== 0 && ISC_LIST_EMPTY(client
->resctxs
) &&
2846 ISC_LIST_EMPTY(client
->reqctxs
) &&
2847 ISC_LIST_EMPTY(client
->updatectxs
))
2848 need_destroyclient
= ISC_TRUE
;
2850 UNLOCK(&client
->lock
);
2852 DESTROYLOCK(&uctx
->lock
);
2855 isc_mem_put(mctx
, uctx
, sizeof(*uctx
));
2857 if (need_destroyclient
)
2858 destroyclient(&client
);
2864 dns_client_mctx(dns_client_t
*client
) {
2866 REQUIRE(DNS_CLIENT_VALID(client
));
2867 return (client
->mctx
);
2871 isc_buffer_t buffer
;
2872 dns_rdataset_t rdataset
;
2873 dns_rdatalist_t rdatalist
;
2877 unsigned char data
[0];
2878 } dns_client_updaterec_t
;
2881 dns_client_updaterec(dns_client_updateop_t op
, dns_name_t
*owner
,
2882 dns_rdatatype_t type
, dns_rdata_t
*source
,
2883 dns_ttl_t ttl
, dns_name_t
*target
,
2884 dns_rdataset_t
*rdataset
, dns_rdatalist_t
*rdatalist
,
2885 dns_rdata_t
*rdata
, isc_mem_t
*mctx
)
2887 dns_client_updaterec_t
*updaterec
;
2888 size_t size
= sizeof(dns_client_updaterec_t
);
2889 isc_buffer_t
*b
= NULL
;
2891 REQUIRE(op
< updateop_max
);
2892 REQUIRE(owner
!= NULL
);
2893 REQUIRE((rdataset
!= NULL
&& rdatalist
!= NULL
&& rdata
!= NULL
) ||
2894 (rdataset
== NULL
&& rdatalist
== NULL
&& rdata
== NULL
&&
2896 if (op
== updateop_add
)
2897 REQUIRE(source
!= NULL
);
2898 if (source
!= NULL
) {
2899 REQUIRE(source
->type
== type
);
2900 REQUIRE(op
== updateop_add
|| op
== updateop_delete
||
2901 op
== updateop_exist
);
2904 size
+= owner
->length
;
2906 size
+= source
->length
;
2908 if (rdataset
== NULL
) {
2909 updaterec
= isc_mem_get(mctx
, size
);
2910 if (updaterec
== NULL
)
2911 return (ISC_R_NOMEMORY
);
2912 rdataset
= &updaterec
->rdataset
;
2913 rdatalist
= &updaterec
->rdatalist
;
2914 rdata
= &updaterec
->rdata
;
2915 dns_rdataset_init(rdataset
);
2916 dns_rdatalist_init(&updaterec
->rdatalist
);
2917 dns_rdata_init(&updaterec
->rdata
);
2918 isc_buffer_init(b
, b
+ 1,
2919 size
- sizeof(dns_client_updaterec_t
));
2920 dns_name_copy(owner
, target
, b
);
2921 if (source
!= NULL
) {
2923 dns_rdata_clone(source
, rdata
);
2924 dns_rdata_toregion(rdata
, &r
);
2925 rdata
->data
= isc_buffer_used(b
);
2926 isc_buffer_copyregion(b
, &r
);
2929 updaterec
->mctx
= NULL
;
2930 isc_mem_attach(mctx
, &updaterec
->mctx
);
2931 } else if (source
!= NULL
)
2932 dns_rdata_clone(source
, rdata
);
2937 case updateop_delete
:
2938 if (source
!= NULL
) {
2940 dns_rdata_makedelete(rdata
);
2942 dns_rdata_deleterrset(rdata
, type
);
2944 case updateop_notexist
:
2945 dns_rdata_notexist(rdata
, type
);
2947 case updateop_exist
:
2948 if (source
== NULL
) {
2950 dns_rdata_exists(rdata
, type
);
2958 rdatalist
->type
= rdata
->type
;
2959 rdatalist
->rdclass
= rdata
->rdclass
;
2960 if (source
!= NULL
) {
2961 rdatalist
->covers
= dns_rdata_covers(rdata
);
2962 rdatalist
->ttl
= ttl
;
2964 ISC_LIST_APPEND(rdatalist
->rdata
, rdata
, link
);
2965 dns_rdatalist_tordataset(rdatalist
, rdataset
);
2966 ISC_LIST_APPEND(target
->list
, rdataset
, link
);
2968 target
->attributes
|= DNS_NAMEATTR_HASUPDATEREC
;
2969 dns_name_setbuffer(target
, b
);
2971 if (op
== updateop_add
|| op
== updateop_delete
)
2972 target
->attributes
|= DNS_NAMEATTR_UPDATE
;
2974 target
->attributes
|= DNS_NAMEATTR_PREREQUISITE
;
2975 return (ISC_R_SUCCESS
);
2979 dns_client_freeupdate(dns_name_t
**namep
) {
2980 dns_client_updaterec_t
*updaterec
;
2981 dns_rdatalist_t
*rdatalist
;
2982 dns_rdataset_t
*rdataset
;
2986 REQUIRE(namep
!= NULL
&& *namep
!= NULL
);
2989 for (rdataset
= ISC_LIST_HEAD(name
->list
);
2991 rdataset
= ISC_LIST_HEAD(name
->list
)) {
2992 ISC_LIST_UNLINK(name
->list
, rdataset
, link
);
2994 dns_rdatalist_fromrdataset(rdataset
, &rdatalist
);
2995 if (rdatalist
== NULL
) {
2996 dns_rdataset_disassociate(rdataset
);
2999 for (rdata
= ISC_LIST_HEAD(rdatalist
->rdata
);
3001 rdata
= ISC_LIST_HEAD(rdatalist
->rdata
))
3002 ISC_LIST_UNLINK(rdatalist
->rdata
, rdata
, link
);
3003 dns_rdataset_disassociate(rdataset
);
3006 if ((name
->attributes
& DNS_NAMEATTR_HASUPDATEREC
) != 0) {
3007 updaterec
= (dns_client_updaterec_t
*)name
->buffer
;
3008 INSIST(updaterec
!= NULL
);
3009 isc_mem_putanddetach(&updaterec
->mctx
, updaterec
,