00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include <config.h>
00021 #include <ctype.h>
00022
00023 #include <isc/counter.h>
00024 #include <isc/log.h>
00025 #include <isc/platform.h>
00026 #include <isc/print.h>
00027 #include <isc/string.h>
00028 #include <isc/random.h>
00029 #include <isc/socket.h>
00030 #include <isc/stats.h>
00031 #include <isc/task.h>
00032 #include <isc/timer.h>
00033 #include <isc/util.h>
00034
00035 #ifdef AES_SIT
00036 #include <isc/aes.h>
00037 #else
00038 #include <isc/hmacsha.h>
00039 #endif
00040
00041 #include <dns/acl.h>
00042 #include <dns/adb.h>
00043 #include <dns/badcache.h>
00044 #include <dns/cache.h>
00045 #include <dns/db.h>
00046 #include <dns/dispatch.h>
00047 #include <dns/ds.h>
00048 #include <dns/edns.h>
00049 #include <dns/events.h>
00050 #include <dns/forward.h>
00051 #include <dns/keytable.h>
00052 #include <dns/log.h>
00053 #include <dns/message.h>
00054 #include <dns/ncache.h>
00055 #include <dns/nsec.h>
00056 #include <dns/nsec3.h>
00057 #include <dns/opcode.h>
00058 #include <dns/peer.h>
00059 #include <dns/rbt.h>
00060 #include <dns/rcode.h>
00061 #include <dns/rdata.h>
00062 #include <dns/rdataclass.h>
00063 #include <dns/rdatalist.h>
00064 #include <dns/rdataset.h>
00065 #include <dns/rdatastruct.h>
00066 #include <dns/rdatatype.h>
00067 #include <dns/resolver.h>
00068 #include <dns/result.h>
00069 #include <dns/rootns.h>
00070 #include <dns/stats.h>
00071 #include <dns/tsig.h>
00072 #include <dns/validator.h>
00073
00074 #ifdef WANT_QUERYTRACE
00075 #define RTRACE(m) isc_log_write(dns_lctx, \
00076 DNS_LOGCATEGORY_RESOLVER, \
00077 DNS_LOGMODULE_RESOLVER, \
00078 ISC_LOG_DEBUG(3), \
00079 "res %p: %s", res, (m))
00080 #define RRTRACE(r, m) isc_log_write(dns_lctx, \
00081 DNS_LOGCATEGORY_RESOLVER, \
00082 DNS_LOGMODULE_RESOLVER, \
00083 ISC_LOG_DEBUG(3), \
00084 "res %p: %s", (r), (m))
00085 #define FCTXTRACE(m) \
00086 isc_log_write(dns_lctx, \
00087 DNS_LOGCATEGORY_RESOLVER, \
00088 DNS_LOGMODULE_RESOLVER, \
00089 ISC_LOG_DEBUG(3), \
00090 "fctx %p(%s): %s", \
00091 fctx, fctx->info, (m))
00092 #define FCTXTRACE2(m1, m2) \
00093 isc_log_write(dns_lctx, \
00094 DNS_LOGCATEGORY_RESOLVER, \
00095 DNS_LOGMODULE_RESOLVER, \
00096 ISC_LOG_DEBUG(3), \
00097 "fctx %p(%s): %s %s", \
00098 fctx, fctx->info, (m1), (m2))
00099 #define FCTXTRACE3(m, res) \
00100 isc_log_write(dns_lctx, \
00101 DNS_LOGCATEGORY_RESOLVER, \
00102 DNS_LOGMODULE_RESOLVER, \
00103 ISC_LOG_DEBUG(3), \
00104 "fctx %p(%s): [result: %s] %s", \
00105 fctx, fctx->info, \
00106 isc_result_totext(res), (m))
00107 #define FCTXTRACE4(m1, m2, res) \
00108 isc_log_write(dns_lctx, \
00109 DNS_LOGCATEGORY_RESOLVER, \
00110 DNS_LOGMODULE_RESOLVER, \
00111 ISC_LOG_DEBUG(3), \
00112 "fctx %p(%s): [result: %s] %s %s", \
00113 fctx, fctx->info, \
00114 isc_result_totext(res), (m1), (m2))
00115 #define FTRACE(m) isc_log_write(dns_lctx, \
00116 DNS_LOGCATEGORY_RESOLVER, \
00117 DNS_LOGMODULE_RESOLVER, \
00118 ISC_LOG_DEBUG(3), \
00119 "fetch %p (fctx %p(%s)): %s", \
00120 fetch, fetch->private, \
00121 fetch->private->info, (m))
00122 #define QTRACE(m) isc_log_write(dns_lctx, \
00123 DNS_LOGCATEGORY_RESOLVER, \
00124 DNS_LOGMODULE_RESOLVER, \
00125 ISC_LOG_DEBUG(3), \
00126 "resquery %p (fctx %p(%s)): %s", \
00127 query, query->fctx, \
00128 query->fctx->info, (m))
00129 #else
00130 #define RTRACE(m) do { UNUSED(m); } while (0)
00131 #define RRTRACE(r, m) do { UNUSED(r); UNUSED(m); } while (0)
00132 #define FCTXTRACE(m) do { UNUSED(m); } while (0)
00133 #define FCTXTRACE2(m1, m2) do { UNUSED(m1); UNUSED(m2); } while (0)
00134 #define FCTXTRACE3(m1, res) do { UNUSED(m1); UNUSED(res); } while (0)
00135 #define FCTXTRACE4(m1, m2, res) \
00136 do { UNUSED(m1); UNUSED(m2); UNUSED(res); } while (0)
00137 #define FTRACE(m) do { UNUSED(m); } while (0)
00138 #define QTRACE(m) do { UNUSED(m); } while (0)
00139 #endif
00140
00141 #define US_PER_SEC 1000000U
00142
00143
00144
00145 #define MAX_SINGLE_QUERY_TIMEOUT 9U
00146 #define MAX_SINGLE_QUERY_TIMEOUT_US (MAX_SINGLE_QUERY_TIMEOUT*US_PER_SEC)
00147
00148
00149
00150
00151 #define MINIMUM_QUERY_TIMEOUT (MAX_SINGLE_QUERY_TIMEOUT + 1U)
00152
00153
00154 #ifndef DEFAULT_QUERY_TIMEOUT
00155 #define DEFAULT_QUERY_TIMEOUT MINIMUM_QUERY_TIMEOUT
00156 #endif
00157
00158 #ifndef MAXIMUM_QUERY_TIMEOUT
00159 #define MAXIMUM_QUERY_TIMEOUT 30
00160 #endif
00161
00162
00163 #ifndef DEFAULT_RECURSION_DEPTH
00164 #define DEFAULT_RECURSION_DEPTH 7
00165 #endif
00166
00167
00168 #ifndef DEFAULT_MAX_QUERIES
00169 #define DEFAULT_MAX_QUERIES 75
00170 #endif
00171
00172
00173
00174
00175 #define RECV_BUFFER_SIZE 4096
00176
00177
00178
00179
00180
00181 #define MAX_EDNS0_TIMEOUTS 3
00182
00183 #define DNS_RESOLVER_BADCACHESIZE 1021
00184 #define DNS_RESOLVER_BADCACHETTL(fctx) \
00185 (((fctx)->res->lame_ttl > 30 ) ? (fctx)->res->lame_ttl : 30)
00186
00187 typedef struct fetchctx fetchctx_t;
00188
00189 typedef struct query {
00190
00191 unsigned int magic;
00192 fetchctx_t * fctx;
00193 isc_mem_t * mctx;
00194 dns_dispatchmgr_t * dispatchmgr;
00195 dns_dispatch_t * dispatch;
00196 isc_boolean_t exclusivesocket;
00197 dns_adbaddrinfo_t * addrinfo;
00198 isc_socket_t * tcpsocket;
00199 isc_time_t start;
00200 dns_messageid_t id;
00201 dns_dispentry_t * dispentry;
00202 ISC_LINK(struct query) link;
00203 isc_buffer_t buffer;
00204 isc_buffer_t *tsig;
00205 dns_tsigkey_t *tsigkey;
00206 isc_socketevent_t sendevent;
00207 isc_dscp_t dscp;
00208 int ednsversion;
00209 unsigned int options;
00210 unsigned int attributes;
00211 unsigned int sends;
00212 unsigned int connects;
00213 unsigned int udpsize;
00214 unsigned char data[512];
00215 } resquery_t;
00216
00217 struct tried {
00218 isc_sockaddr_t addr;
00219 unsigned int count;
00220 ISC_LINK(struct tried) link;
00221 };
00222
00223 #define QUERY_MAGIC ISC_MAGIC('Q', '!', '!', '!')
00224 #define VALID_QUERY(query) ISC_MAGIC_VALID(query, QUERY_MAGIC)
00225
00226 #define RESQUERY_ATTR_CANCELED 0x02
00227
00228 #define RESQUERY_CONNECTING(q) ((q)->connects > 0)
00229 #define RESQUERY_CANCELED(q) (((q)->attributes & \
00230 RESQUERY_ATTR_CANCELED) != 0)
00231 #define RESQUERY_SENDING(q) ((q)->sends > 0)
00232
00233 typedef enum {
00234 fetchstate_init = 0,
00235 fetchstate_active,
00236 fetchstate_done
00237 } fetchstate;
00238
00239 typedef enum {
00240 badns_unreachable = 0,
00241 badns_response,
00242 badns_validation
00243 } badnstype_t;
00244
00245 struct fetchctx {
00246
00247 unsigned int magic;
00248 dns_resolver_t * res;
00249 dns_name_t name;
00250 dns_rdatatype_t type;
00251 unsigned int options;
00252 unsigned int bucketnum;
00253 char * info;
00254 isc_mem_t * mctx;
00255
00256
00257 fetchstate state;
00258 isc_boolean_t want_shutdown;
00259 isc_boolean_t cloned;
00260 isc_boolean_t spilled;
00261 unsigned int references;
00262 isc_event_t control_event;
00263 ISC_LINK(struct fetchctx) link;
00264 ISC_LIST(dns_fetchevent_t) events;
00265
00266 dns_name_t domain;
00267 dns_rdataset_t nameservers;
00268 unsigned int attributes;
00269 isc_timer_t * timer;
00270 isc_time_t expires;
00271 isc_interval_t interval;
00272 dns_message_t * qmessage;
00273 dns_message_t * rmessage;
00274 ISC_LIST(resquery_t) queries;
00275 dns_adbfindlist_t finds;
00276 dns_adbfind_t * find;
00277 dns_adbfindlist_t altfinds;
00278 dns_adbfind_t * altfind;
00279 dns_adbaddrinfolist_t forwaddrs;
00280 dns_adbaddrinfolist_t altaddrs;
00281 dns_forwarderlist_t forwarders;
00282 dns_fwdpolicy_t fwdpolicy;
00283 isc_sockaddrlist_t bad;
00284 ISC_LIST(struct tried) edns;
00285 ISC_LIST(struct tried) edns512;
00286 isc_sockaddrlist_t bad_edns;
00287 dns_validator_t * validator;
00288 ISC_LIST(dns_validator_t) validators;
00289 dns_db_t * cache;
00290 dns_adb_t * adb;
00291 isc_boolean_t ns_ttl_ok;
00292 isc_uint32_t ns_ttl;
00293 isc_counter_t * qc;
00294
00295
00296
00297
00298 unsigned int pending;
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308 unsigned int restarts;
00309
00310
00311
00312
00313
00314
00315 unsigned int timeouts;
00316
00317
00318
00319
00320 dns_name_t nsname;
00321 dns_fetch_t * nsfetch;
00322 dns_rdataset_t nsrrset;
00323
00324
00325
00326
00327 unsigned int nqueries;
00328
00329
00330
00331
00332
00333 const char * reason;
00334
00335
00336
00337
00338 isc_uint32_t rand_buf;
00339 isc_uint32_t rand_bits;
00340
00341
00342
00343
00344 isc_result_t result;
00345 isc_result_t vresult;
00346 int exitline;
00347 isc_time_t start;
00348 isc_uint64_t duration;
00349 isc_boolean_t logged;
00350 unsigned int querysent;
00351 unsigned int referrals;
00352 unsigned int lamecount;
00353 unsigned int neterr;
00354 unsigned int badresp;
00355 unsigned int adberr;
00356 unsigned int findfail;
00357 unsigned int valfail;
00358 isc_boolean_t timeout;
00359 dns_adbaddrinfo_t *addrinfo;
00360 isc_sockaddr_t *client;
00361 unsigned int depth;
00362 };
00363
00364 #define FCTX_MAGIC ISC_MAGIC('F', '!', '!', '!')
00365 #define VALID_FCTX(fctx) ISC_MAGIC_VALID(fctx, FCTX_MAGIC)
00366
00367 #define FCTX_ATTR_HAVEANSWER 0x0001
00368 #define FCTX_ATTR_GLUING 0x0002
00369 #define FCTX_ATTR_ADDRWAIT 0x0004
00370 #define FCTX_ATTR_SHUTTINGDOWN 0x0008
00371 #define FCTX_ATTR_WANTCACHE 0x0010
00372 #define FCTX_ATTR_WANTNCACHE 0x0020
00373 #define FCTX_ATTR_NEEDEDNS0 0x0040
00374 #define FCTX_ATTR_TRIEDFIND 0x0080
00375 #define FCTX_ATTR_TRIEDALT 0x0100
00376
00377 #define HAVE_ANSWER(f) (((f)->attributes & FCTX_ATTR_HAVEANSWER) != \
00378 0)
00379 #define GLUING(f) (((f)->attributes & FCTX_ATTR_GLUING) != \
00380 0)
00381 #define ADDRWAIT(f) (((f)->attributes & FCTX_ATTR_ADDRWAIT) != \
00382 0)
00383 #define SHUTTINGDOWN(f) (((f)->attributes & FCTX_ATTR_SHUTTINGDOWN) \
00384 != 0)
00385 #define WANTCACHE(f) (((f)->attributes & FCTX_ATTR_WANTCACHE) != 0)
00386 #define WANTNCACHE(f) (((f)->attributes & FCTX_ATTR_WANTNCACHE) != 0)
00387 #define NEEDEDNS0(f) (((f)->attributes & FCTX_ATTR_NEEDEDNS0) != 0)
00388 #define TRIEDFIND(f) (((f)->attributes & FCTX_ATTR_TRIEDFIND) != 0)
00389 #define TRIEDALT(f) (((f)->attributes & FCTX_ATTR_TRIEDALT) != 0)
00390
00391 typedef struct {
00392 dns_adbaddrinfo_t * addrinfo;
00393 fetchctx_t * fctx;
00394 } dns_valarg_t;
00395
00396 struct dns_fetch {
00397 unsigned int magic;
00398 isc_mem_t * mctx;
00399 fetchctx_t * private;
00400 };
00401
00402 #define DNS_FETCH_MAGIC ISC_MAGIC('F', 't', 'c', 'h')
00403 #define DNS_FETCH_VALID(fetch) ISC_MAGIC_VALID(fetch, DNS_FETCH_MAGIC)
00404
00405 typedef struct fctxbucket {
00406 isc_task_t * task;
00407 isc_mutex_t lock;
00408 ISC_LIST(fetchctx_t) fctxs;
00409 isc_boolean_t exiting;
00410 isc_mem_t * mctx;
00411 } fctxbucket_t;
00412
00413 typedef struct alternate {
00414 isc_boolean_t isaddress;
00415 union {
00416 isc_sockaddr_t addr;
00417 struct {
00418 dns_name_t name;
00419 in_port_t port;
00420 } _n;
00421 } _u;
00422 ISC_LINK(struct alternate) link;
00423 } alternate_t;
00424
00425 struct dns_resolver {
00426
00427 unsigned int magic;
00428 isc_mem_t * mctx;
00429 isc_mutex_t lock;
00430 isc_mutex_t nlock;
00431 isc_mutex_t primelock;
00432 dns_rdataclass_t rdclass;
00433 isc_socketmgr_t * socketmgr;
00434 isc_timermgr_t * timermgr;
00435 isc_taskmgr_t * taskmgr;
00436 dns_view_t * view;
00437 isc_boolean_t frozen;
00438 unsigned int options;
00439 dns_dispatchmgr_t * dispatchmgr;
00440 dns_dispatchset_t * dispatches4;
00441 isc_boolean_t exclusivev4;
00442 dns_dispatchset_t * dispatches6;
00443 isc_dscp_t querydscp4;
00444 isc_dscp_t querydscp6;
00445 isc_boolean_t exclusivev6;
00446 unsigned int nbuckets;
00447 fctxbucket_t * buckets;
00448 isc_uint32_t lame_ttl;
00449 ISC_LIST(alternate_t) alternates;
00450 isc_uint16_t udpsize;
00451 #if USE_ALGLOCK
00452 isc_rwlock_t alglock;
00453 #endif
00454 dns_rbt_t * algorithms;
00455 dns_rbt_t * digests;
00456 #if USE_MBSLOCK
00457 isc_rwlock_t mbslock;
00458 #endif
00459 dns_rbt_t * mustbesecure;
00460 unsigned int spillatmax;
00461 unsigned int spillatmin;
00462 isc_timer_t * spillattimer;
00463 isc_boolean_t zero_no_soa_ttl;
00464 unsigned int query_timeout;
00465 unsigned int maxdepth;
00466 unsigned int maxqueries;
00467
00468
00469 unsigned int references;
00470 isc_boolean_t exiting;
00471 isc_eventlist_t whenshutdown;
00472 unsigned int activebuckets;
00473 isc_boolean_t priming;
00474 unsigned int spillat;
00475
00476 dns_badcache_t * badcache;
00477
00478
00479 dns_fetch_t * primefetch;
00480
00481 unsigned int nfctx;
00482 };
00483
00484 #define RES_MAGIC ISC_MAGIC('R', 'e', 's', '!')
00485 #define VALID_RESOLVER(res) ISC_MAGIC_VALID(res, RES_MAGIC)
00486
00487
00488
00489
00490
00491 #define FCTX_ADDRINFO_MARK 0x0001
00492 #define FCTX_ADDRINFO_FORWARDER 0x1000
00493 #define FCTX_ADDRINFO_TRIED 0x2000
00494 #define FCTX_ADDRINFO_EDNSOK 0x4000
00495 #define FCTX_ADDRINFO_NOSIT 0x8000
00496
00497 #define UNMARKED(a) (((a)->flags & FCTX_ADDRINFO_MARK) \
00498 == 0)
00499 #define ISFORWARDER(a) (((a)->flags & \
00500 FCTX_ADDRINFO_FORWARDER) != 0)
00501 #define TRIED(a) (((a)->flags & \
00502 FCTX_ADDRINFO_TRIED) != 0)
00503 #define NOSIT(a) (((a)->flags & \
00504 FCTX_ADDRINFO_NOSIT) != 0)
00505 #define EDNSOK(a) (((a)->flags & \
00506 FCTX_ADDRINFO_EDNSOK) != 0)
00507
00508
00509 #define NXDOMAIN(r) (((r)->attributes & DNS_RDATASETATTR_NXDOMAIN) != 0)
00510 #define NEGATIVE(r) (((r)->attributes & DNS_RDATASETATTR_NEGATIVE) != 0)
00511
00512 static void destroy(dns_resolver_t *res);
00513 static void empty_bucket(dns_resolver_t *res);
00514 static isc_result_t resquery_send(resquery_t *query);
00515 static void resquery_response(isc_task_t *task, isc_event_t *event);
00516 static void resquery_connected(isc_task_t *task, isc_event_t *event);
00517 static void fctx_try(fetchctx_t *fctx, isc_boolean_t retrying,
00518 isc_boolean_t badcache);
00519 static void fctx_destroy(fetchctx_t *fctx);
00520 static isc_boolean_t fctx_unlink(fetchctx_t *fctx);
00521 static isc_result_t ncache_adderesult(dns_message_t *message,
00522 dns_db_t *cache, dns_dbnode_t *node,
00523 dns_rdatatype_t covers,
00524 isc_stdtime_t now, dns_ttl_t maxttl,
00525 isc_boolean_t optout,
00526 isc_boolean_t secure,
00527 dns_rdataset_t *ardataset,
00528 isc_result_t *eresultp);
00529 static void validated(isc_task_t *task, isc_event_t *event);
00530 static isc_boolean_t maybe_destroy(fetchctx_t *fctx, isc_boolean_t locked);
00531 static void add_bad(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo,
00532 isc_result_t reason, badnstype_t badtype);
00533 static inline isc_result_t findnoqname(fetchctx_t *fctx, dns_name_t *name,
00534 dns_rdatatype_t type,
00535 dns_name_t **noqname);
00536 static void fctx_increference(fetchctx_t *fctx);
00537 static isc_boolean_t fctx_decreference(fetchctx_t *fctx);
00538
00539
00540
00541
00542 static inline void
00543 inc_stats(dns_resolver_t *res, isc_statscounter_t counter) {
00544 if (res->view->resstats != NULL)
00545 isc_stats_increment(res->view->resstats, counter);
00546 }
00547
00548 static inline void
00549 dec_stats(dns_resolver_t *res, isc_statscounter_t counter) {
00550 if (res->view->resstats != NULL)
00551 isc_stats_decrement(res->view->resstats, counter);
00552 }
00553
00554 static isc_result_t
00555 valcreate(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo, dns_name_t *name,
00556 dns_rdatatype_t type, dns_rdataset_t *rdataset,
00557 dns_rdataset_t *sigrdataset, unsigned int valoptions,
00558 isc_task_t *task)
00559 {
00560 dns_validator_t *validator = NULL;
00561 dns_valarg_t *valarg;
00562 isc_result_t result;
00563
00564 valarg = isc_mem_get(fctx->mctx, sizeof(*valarg));
00565 if (valarg == NULL)
00566 return (ISC_R_NOMEMORY);
00567
00568 valarg->fctx = fctx;
00569 valarg->addrinfo = addrinfo;
00570
00571 if (!ISC_LIST_EMPTY(fctx->validators))
00572 INSIST((valoptions & DNS_VALIDATOR_DEFER) != 0);
00573
00574 result = dns_validator_create(fctx->res->view, name, type, rdataset,
00575 sigrdataset, fctx->rmessage,
00576 valoptions, task, validated, valarg,
00577 &validator);
00578 if (result == ISC_R_SUCCESS) {
00579 inc_stats(fctx->res, dns_resstatscounter_val);
00580 if ((valoptions & DNS_VALIDATOR_DEFER) == 0) {
00581 INSIST(fctx->validator == NULL);
00582 fctx->validator = validator;
00583 }
00584 ISC_LIST_APPEND(fctx->validators, validator, link);
00585 } else
00586 isc_mem_put(fctx->mctx, valarg, sizeof(*valarg));
00587 return (result);
00588 }
00589
00590 static isc_boolean_t
00591 rrsig_fromchildzone(fetchctx_t *fctx, dns_rdataset_t *rdataset) {
00592 dns_namereln_t namereln;
00593 dns_rdata_rrsig_t rrsig;
00594 dns_rdata_t rdata = DNS_RDATA_INIT;
00595 int order;
00596 isc_result_t result;
00597 unsigned int labels;
00598
00599 for (result = dns_rdataset_first(rdataset);
00600 result == ISC_R_SUCCESS;
00601 result = dns_rdataset_next(rdataset)) {
00602 dns_rdataset_current(rdataset, &rdata);
00603 result = dns_rdata_tostruct(&rdata, &rrsig, NULL);
00604 RUNTIME_CHECK(result == ISC_R_SUCCESS);
00605 namereln = dns_name_fullcompare(&rrsig.signer, &fctx->domain,
00606 &order, &labels);
00607 if (namereln == dns_namereln_subdomain)
00608 return (ISC_TRUE);
00609 dns_rdata_reset(&rdata);
00610 }
00611 return (ISC_FALSE);
00612 }
00613
00614 static isc_boolean_t
00615 fix_mustbedelegationornxdomain(dns_message_t *message, fetchctx_t *fctx) {
00616 dns_name_t *name;
00617 dns_name_t *domain = &fctx->domain;
00618 dns_rdataset_t *rdataset;
00619 dns_rdatatype_t type;
00620 isc_result_t result;
00621 isc_boolean_t keep_auth = ISC_FALSE;
00622
00623 if (message->rcode == dns_rcode_nxdomain)
00624 return (ISC_FALSE);
00625
00626
00627
00628
00629
00630
00631
00632
00633
00634
00635
00636
00637
00638
00639
00640
00641
00642
00643
00644
00645
00646
00647
00648
00649
00650
00651
00652
00653
00654
00655
00656
00657 if (message->counts[DNS_SECTION_ANSWER] != 0 &&
00658 (fctx->type == dns_rdatatype_ns ||
00659 fctx->type == dns_rdatatype_ds ||
00660 fctx->type == dns_rdatatype_soa ||
00661 fctx->type == dns_rdatatype_any ||
00662 fctx->type == dns_rdatatype_rrsig ||
00663 fctx->type == dns_rdatatype_dnskey)) {
00664 result = dns_message_firstname(message, DNS_SECTION_ANSWER);
00665 while (result == ISC_R_SUCCESS) {
00666 name = NULL;
00667 dns_message_currentname(message, DNS_SECTION_ANSWER,
00668 &name);
00669 for (rdataset = ISC_LIST_HEAD(name->list);
00670 rdataset != NULL;
00671 rdataset = ISC_LIST_NEXT(rdataset, link)) {
00672 if (!dns_name_equal(name, &fctx->name))
00673 continue;
00674 type = rdataset->type;
00675
00676
00677
00678 if (type == dns_rdatatype_rrsig &&
00679 rrsig_fromchildzone(fctx, rdataset))
00680 return (ISC_FALSE);
00681
00682
00683
00684 if (fctx->type == type &&
00685 (type == dns_rdatatype_ds ||
00686 type == dns_rdatatype_ns ||
00687 type == dns_rdatatype_soa ||
00688 type == dns_rdatatype_dnskey))
00689 return (ISC_FALSE);
00690
00691
00692
00693 if (fctx->type == dns_rdatatype_any &&
00694 (type == dns_rdatatype_ns ||
00695 type == dns_rdatatype_ds ||
00696 type == dns_rdatatype_soa ||
00697 type == dns_rdatatype_dnskey))
00698 return (ISC_FALSE);
00699 }
00700 result = dns_message_nextname(message,
00701 DNS_SECTION_ANSWER);
00702 }
00703 }
00704
00705
00706
00707
00708 if (fctx->type == dns_rdatatype_ds &&
00709 message->counts[DNS_SECTION_ANSWER] == 0)
00710 return (ISC_FALSE);
00711
00712
00713 if (message->counts[DNS_SECTION_AUTHORITY] == 0)
00714 goto munge;
00715
00716 result = dns_message_firstname(message, DNS_SECTION_AUTHORITY);
00717 while (result == ISC_R_SUCCESS) {
00718 name = NULL;
00719 dns_message_currentname(message, DNS_SECTION_AUTHORITY, &name);
00720 for (rdataset = ISC_LIST_HEAD(name->list);
00721 rdataset != NULL;
00722 rdataset = ISC_LIST_NEXT(rdataset, link)) {
00723 type = rdataset->type;
00724 if (type == dns_rdatatype_soa &&
00725 dns_name_equal(name, domain))
00726 keep_auth = ISC_TRUE;
00727
00728 if (type != dns_rdatatype_ns &&
00729 type != dns_rdatatype_soa &&
00730 type != dns_rdatatype_rrsig)
00731 continue;
00732
00733 if (type == dns_rdatatype_rrsig) {
00734 if (rrsig_fromchildzone(fctx, rdataset))
00735 return (ISC_FALSE);
00736 else
00737 continue;
00738 }
00739
00740
00741 if (dns_name_equal(name, domain)) {
00742
00743
00744
00745
00746
00747
00748
00749
00750
00751 if (message->counts[DNS_SECTION_ANSWER] == 0 &&
00752 fctx->type == dns_rdatatype_any)
00753 return (ISC_FALSE);
00754 } else if (dns_name_issubdomain(name, domain)) {
00755
00756 return (ISC_FALSE);
00757 }
00758 }
00759 result = dns_message_nextname(message, DNS_SECTION_AUTHORITY);
00760 }
00761
00762 munge:
00763 message->rcode = dns_rcode_nxdomain;
00764 message->counts[DNS_SECTION_ANSWER] = 0;
00765 if (!keep_auth)
00766 message->counts[DNS_SECTION_AUTHORITY] = 0;
00767 message->counts[DNS_SECTION_ADDITIONAL] = 0;
00768 return (ISC_TRUE);
00769 }
00770
00771 static inline isc_result_t
00772 fctx_starttimer(fetchctx_t *fctx) {
00773
00774
00775
00776
00777
00778
00779
00780 return (isc_timer_reset(fctx->timer, isc_timertype_once,
00781 &fctx->expires, NULL, ISC_TRUE));
00782 }
00783
00784 static inline void
00785 fctx_stoptimer(fetchctx_t *fctx) {
00786 isc_result_t result;
00787
00788
00789
00790
00791
00792
00793
00794 result = isc_timer_reset(fctx->timer, isc_timertype_inactive,
00795 NULL, NULL, ISC_TRUE);
00796 if (result != ISC_R_SUCCESS) {
00797 UNEXPECTED_ERROR(__FILE__, __LINE__,
00798 "isc_timer_reset(): %s",
00799 isc_result_totext(result));
00800 }
00801 }
00802
00803
00804 static inline isc_result_t
00805 fctx_startidletimer(fetchctx_t *fctx, isc_interval_t *interval) {
00806
00807
00808
00809
00810 return (isc_timer_reset(fctx->timer, isc_timertype_once,
00811 &fctx->expires, interval, ISC_FALSE));
00812 }
00813
00814
00815
00816
00817
00818 #define fctx_stopidletimer fctx_starttimer
00819
00820 static inline void
00821 resquery_destroy(resquery_t **queryp) {
00822 dns_resolver_t *res;
00823 isc_boolean_t empty;
00824 resquery_t *query;
00825 fetchctx_t *fctx;
00826 unsigned int bucket;
00827
00828 REQUIRE(queryp != NULL);
00829 query = *queryp;
00830 REQUIRE(!ISC_LINK_LINKED(query, link));
00831
00832 INSIST(query->tcpsocket == NULL);
00833
00834 fctx = query->fctx;
00835 res = fctx->res;
00836 bucket = fctx->bucketnum;
00837
00838 fctx->nqueries--;
00839
00840 LOCK(&res->buckets[bucket].lock);
00841 empty = fctx_decreference(query->fctx);
00842 UNLOCK(&res->buckets[bucket].lock);
00843
00844 query->magic = 0;
00845 isc_mem_put(query->mctx, query, sizeof(*query));
00846 *queryp = NULL;
00847
00848 if (empty)
00849 empty_bucket(res);
00850 }
00851
00852 static void
00853 fctx_cancelquery(resquery_t **queryp, dns_dispatchevent_t **deventp,
00854 isc_time_t *finish, isc_boolean_t no_response)
00855 {
00856 fetchctx_t *fctx;
00857 resquery_t *query;
00858 unsigned int rtt, rttms;
00859 unsigned int factor;
00860 dns_adbfind_t *find;
00861 dns_adbaddrinfo_t *addrinfo;
00862 isc_socket_t *sock;
00863 isc_stdtime_t now;
00864
00865 query = *queryp;
00866 fctx = query->fctx;
00867
00868 FCTXTRACE("cancelquery");
00869
00870 REQUIRE(!RESQUERY_CANCELED(query));
00871
00872 query->attributes |= RESQUERY_ATTR_CANCELED;
00873
00874
00875
00876
00877 if (finish != NULL || no_response) {
00878 if (finish != NULL) {
00879
00880
00881
00882
00883 rtt = (unsigned int)isc_time_microdiff(finish,
00884 &query->start);
00885 factor = DNS_ADB_RTTADJDEFAULT;
00886
00887 rttms = rtt / 1000;
00888 if (rttms < DNS_RESOLVER_QRYRTTCLASS0) {
00889 inc_stats(fctx->res,
00890 dns_resstatscounter_queryrtt0);
00891 } else if (rttms < DNS_RESOLVER_QRYRTTCLASS1) {
00892 inc_stats(fctx->res,
00893 dns_resstatscounter_queryrtt1);
00894 } else if (rttms < DNS_RESOLVER_QRYRTTCLASS2) {
00895 inc_stats(fctx->res,
00896 dns_resstatscounter_queryrtt2);
00897 } else if (rttms < DNS_RESOLVER_QRYRTTCLASS3) {
00898 inc_stats(fctx->res,
00899 dns_resstatscounter_queryrtt3);
00900 } else if (rttms < DNS_RESOLVER_QRYRTTCLASS4) {
00901 inc_stats(fctx->res,
00902 dns_resstatscounter_queryrtt4);
00903 } else {
00904 inc_stats(fctx->res,
00905 dns_resstatscounter_queryrtt5);
00906 }
00907 } else {
00908 isc_uint32_t value;
00909 isc_uint32_t mask;
00910
00911
00912
00913
00914
00915 INSIST(no_response);
00916 isc_random_get(&value);
00917 if (query->addrinfo->srtt > 800000)
00918 mask = 0x3fff;
00919 else if (query->addrinfo->srtt > 400000)
00920 mask = 0x7fff;
00921 else if (query->addrinfo->srtt > 200000)
00922 mask = 0xffff;
00923 else if (query->addrinfo->srtt > 100000)
00924 mask = 0x1ffff;
00925 else if (query->addrinfo->srtt > 50000)
00926 mask = 0x3ffff;
00927 else if (query->addrinfo->srtt > 25000)
00928 mask = 0x7ffff;
00929 else
00930 mask = 0xfffff;
00931 if ((query->options & DNS_FETCHOPT_NOEDNS0) == 0)
00932 dns_adb_ednsto(fctx->adb, query->addrinfo,
00933 query->udpsize);
00934 else
00935 dns_adb_timeout(fctx->adb, query->addrinfo);
00936
00937
00938
00939
00940
00941 if ((query->options & DNS_FETCHOPT_NOEDNS0) == 0 &&
00942 !EDNSOK(query->addrinfo)) {
00943 mask >>= 2;
00944 }
00945 rtt = query->addrinfo->srtt + (value & mask);
00946 if (rtt > MAX_SINGLE_QUERY_TIMEOUT_US)
00947 rtt = MAX_SINGLE_QUERY_TIMEOUT_US;
00948
00949
00950
00951 factor = DNS_ADB_RTTADJREPLACE;
00952 }
00953 dns_adb_adjustsrtt(fctx->adb, query->addrinfo, rtt, factor);
00954 }
00955
00956
00957 if (!TRIED(query->addrinfo)) {
00958 dns_adb_changeflags(fctx->adb, query->addrinfo,
00959 FCTX_ADDRINFO_TRIED, FCTX_ADDRINFO_TRIED);
00960 }
00961
00962
00963
00964
00965 isc_stdtime_get(&now);
00966 if (finish != NULL)
00967 for (addrinfo = ISC_LIST_HEAD(fctx->forwaddrs);
00968 addrinfo != NULL;
00969 addrinfo = ISC_LIST_NEXT(addrinfo, publink))
00970 if (UNMARKED(addrinfo))
00971 dns_adb_agesrtt(fctx->adb, addrinfo, now);
00972
00973 if (finish != NULL && TRIEDFIND(fctx))
00974 for (find = ISC_LIST_HEAD(fctx->finds);
00975 find != NULL;
00976 find = ISC_LIST_NEXT(find, publink))
00977 for (addrinfo = ISC_LIST_HEAD(find->list);
00978 addrinfo != NULL;
00979 addrinfo = ISC_LIST_NEXT(addrinfo, publink))
00980 if (UNMARKED(addrinfo))
00981 dns_adb_agesrtt(fctx->adb, addrinfo,
00982 now);
00983
00984 if (finish != NULL && TRIEDALT(fctx)) {
00985 for (addrinfo = ISC_LIST_HEAD(fctx->altaddrs);
00986 addrinfo != NULL;
00987 addrinfo = ISC_LIST_NEXT(addrinfo, publink))
00988 if (UNMARKED(addrinfo))
00989 dns_adb_agesrtt(fctx->adb, addrinfo, now);
00990 for (find = ISC_LIST_HEAD(fctx->altfinds);
00991 find != NULL;
00992 find = ISC_LIST_NEXT(find, publink))
00993 for (addrinfo = ISC_LIST_HEAD(find->list);
00994 addrinfo != NULL;
00995 addrinfo = ISC_LIST_NEXT(addrinfo, publink))
00996 if (UNMARKED(addrinfo))
00997 dns_adb_agesrtt(fctx->adb, addrinfo,
00998 now);
00999 }
01000
01001
01002
01003
01004
01005
01006
01007 if (RESQUERY_CONNECTING(query)) {
01008
01009
01010
01011 if (query->tcpsocket != NULL) {
01012 isc_socket_cancel(query->tcpsocket, NULL,
01013 ISC_SOCKCANCEL_CONNECT);
01014 } else if (query->dispentry != NULL) {
01015 INSIST(query->exclusivesocket);
01016 sock = dns_dispatch_getentrysocket(query->dispentry);
01017 if (sock != NULL)
01018 isc_socket_cancel(sock, NULL,
01019 ISC_SOCKCANCEL_CONNECT);
01020 }
01021 } else if (RESQUERY_SENDING(query)) {
01022
01023
01024
01025 if (query->exclusivesocket && query->dispentry != NULL)
01026 sock = dns_dispatch_getentrysocket(query->dispentry);
01027 else
01028 sock = dns_dispatch_getsocket(query->dispatch);
01029 if (sock != NULL)
01030 isc_socket_cancel(sock, NULL, ISC_SOCKCANCEL_SEND);
01031 }
01032
01033 if (query->dispentry != NULL)
01034 dns_dispatch_removeresponse(&query->dispentry, deventp);
01035
01036 ISC_LIST_UNLINK(fctx->queries, query, link);
01037
01038 if (query->tsig != NULL)
01039 isc_buffer_free(&query->tsig);
01040
01041 if (query->tsigkey != NULL)
01042 dns_tsigkey_detach(&query->tsigkey);
01043
01044 if (query->dispatch != NULL)
01045 dns_dispatch_detach(&query->dispatch);
01046
01047 if (! (RESQUERY_CONNECTING(query) || RESQUERY_SENDING(query)))
01048
01049
01050
01051 resquery_destroy(&query);
01052 }
01053
01054 static void
01055 fctx_cancelqueries(fetchctx_t *fctx, isc_boolean_t no_response) {
01056 resquery_t *query, *next_query;
01057
01058 FCTXTRACE("cancelqueries");
01059
01060 for (query = ISC_LIST_HEAD(fctx->queries);
01061 query != NULL;
01062 query = next_query) {
01063 next_query = ISC_LIST_NEXT(query, link);
01064 fctx_cancelquery(&query, NULL, NULL, no_response);
01065 }
01066 }
01067
01068 static void
01069 fctx_cleanupfinds(fetchctx_t *fctx) {
01070 dns_adbfind_t *find, *next_find;
01071
01072 REQUIRE(ISC_LIST_EMPTY(fctx->queries));
01073
01074 for (find = ISC_LIST_HEAD(fctx->finds);
01075 find != NULL;
01076 find = next_find) {
01077 next_find = ISC_LIST_NEXT(find, publink);
01078 ISC_LIST_UNLINK(fctx->finds, find, publink);
01079 dns_adb_destroyfind(&find);
01080 }
01081 fctx->find = NULL;
01082 }
01083
01084 static void
01085 fctx_cleanupaltfinds(fetchctx_t *fctx) {
01086 dns_adbfind_t *find, *next_find;
01087
01088 REQUIRE(ISC_LIST_EMPTY(fctx->queries));
01089
01090 for (find = ISC_LIST_HEAD(fctx->altfinds);
01091 find != NULL;
01092 find = next_find) {
01093 next_find = ISC_LIST_NEXT(find, publink);
01094 ISC_LIST_UNLINK(fctx->altfinds, find, publink);
01095 dns_adb_destroyfind(&find);
01096 }
01097 fctx->altfind = NULL;
01098 }
01099
01100 static void
01101 fctx_cleanupforwaddrs(fetchctx_t *fctx) {
01102 dns_adbaddrinfo_t *addr, *next_addr;
01103
01104 REQUIRE(ISC_LIST_EMPTY(fctx->queries));
01105
01106 for (addr = ISC_LIST_HEAD(fctx->forwaddrs);
01107 addr != NULL;
01108 addr = next_addr) {
01109 next_addr = ISC_LIST_NEXT(addr, publink);
01110 ISC_LIST_UNLINK(fctx->forwaddrs, addr, publink);
01111 dns_adb_freeaddrinfo(fctx->adb, &addr);
01112 }
01113 }
01114
01115 static void
01116 fctx_cleanupaltaddrs(fetchctx_t *fctx) {
01117 dns_adbaddrinfo_t *addr, *next_addr;
01118
01119 REQUIRE(ISC_LIST_EMPTY(fctx->queries));
01120
01121 for (addr = ISC_LIST_HEAD(fctx->altaddrs);
01122 addr != NULL;
01123 addr = next_addr) {
01124 next_addr = ISC_LIST_NEXT(addr, publink);
01125 ISC_LIST_UNLINK(fctx->altaddrs, addr, publink);
01126 dns_adb_freeaddrinfo(fctx->adb, &addr);
01127 }
01128 }
01129
01130 static inline void
01131 fctx_stopeverything(fetchctx_t *fctx, isc_boolean_t no_response) {
01132 FCTXTRACE("stopeverything");
01133 fctx_cancelqueries(fctx, no_response);
01134 fctx_cleanupfinds(fctx);
01135 fctx_cleanupaltfinds(fctx);
01136 fctx_cleanupforwaddrs(fctx);
01137 fctx_cleanupaltaddrs(fctx);
01138 fctx_stoptimer(fctx);
01139 }
01140
01141 static inline void
01142 fctx_sendevents(fetchctx_t *fctx, isc_result_t result, int line) {
01143 dns_fetchevent_t *event, *next_event;
01144 isc_task_t *task;
01145 unsigned int count = 0;
01146 isc_interval_t i;
01147 isc_boolean_t logit = ISC_FALSE;
01148 isc_time_t now;
01149 unsigned int old_spillat;
01150 unsigned int new_spillat = 0;
01151
01152
01153
01154
01155
01156 REQUIRE(fctx->state == fetchstate_done);
01157
01158 FCTXTRACE("sendevents");
01159
01160
01161
01162
01163 fctx->result = result;
01164 fctx->exitline = line;
01165 TIME_NOW(&now);
01166 fctx->duration = isc_time_microdiff(&now, &fctx->start);
01167
01168 for (event = ISC_LIST_HEAD(fctx->events);
01169 event != NULL;
01170 event = next_event) {
01171 next_event = ISC_LIST_NEXT(event, ev_link);
01172 ISC_LIST_UNLINK(fctx->events, event, ev_link);
01173 task = event->ev_sender;
01174 event->ev_sender = fctx;
01175 event->vresult = fctx->vresult;
01176 if (!HAVE_ANSWER(fctx))
01177 event->result = result;
01178
01179 INSIST(result != ISC_R_SUCCESS ||
01180 dns_rdataset_isassociated(event->rdataset) ||
01181 fctx->type == dns_rdatatype_any ||
01182 fctx->type == dns_rdatatype_rrsig ||
01183 fctx->type == dns_rdatatype_sig);
01184
01185
01186
01187
01188 if (dns_rdataset_isassociated(event->rdataset) &&
01189 NEGATIVE(event->rdataset)) {
01190 INSIST(event->result == DNS_R_NCACHENXDOMAIN ||
01191 event->result == DNS_R_NCACHENXRRSET);
01192 }
01193
01194 isc_task_sendanddetach(&task, ISC_EVENT_PTR(&event));
01195 count++;
01196 }
01197
01198 if ((fctx->attributes & FCTX_ATTR_HAVEANSWER) != 0 &&
01199 fctx->spilled &&
01200 (count < fctx->res->spillatmax || fctx->res->spillatmax == 0)) {
01201 LOCK(&fctx->res->lock);
01202 if (count == fctx->res->spillat && !fctx->res->exiting) {
01203 old_spillat = fctx->res->spillat;
01204 fctx->res->spillat += 5;
01205 if (fctx->res->spillat > fctx->res->spillatmax &&
01206 fctx->res->spillatmax != 0)
01207 fctx->res->spillat = fctx->res->spillatmax;
01208 new_spillat = fctx->res->spillat;
01209 if (new_spillat != old_spillat) {
01210 logit = ISC_TRUE;
01211 }
01212 isc_interval_set(&i, 20 * 60, 0);
01213 result = isc_timer_reset(fctx->res->spillattimer,
01214 isc_timertype_ticker, NULL,
01215 &i, ISC_TRUE);
01216 RUNTIME_CHECK(result == ISC_R_SUCCESS);
01217 }
01218 UNLOCK(&fctx->res->lock);
01219 if (logit)
01220 isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER,
01221 DNS_LOGMODULE_RESOLVER, ISC_LOG_NOTICE,
01222 "clients-per-query increased to %u",
01223 new_spillat);
01224 }
01225 }
01226
01227 static inline void
01228 log_edns(fetchctx_t *fctx) {
01229 char domainbuf[DNS_NAME_FORMATSIZE];
01230
01231 if (fctx->reason == NULL)
01232 return;
01233
01234
01235
01236
01237
01238 dns_name_format(&fctx->domain, domainbuf, sizeof(domainbuf));
01239 isc_log_write(dns_lctx, DNS_LOGCATEGORY_EDNS_DISABLED,
01240 DNS_LOGMODULE_RESOLVER, ISC_LOG_INFO,
01241 "success resolving '%s' (in '%s'?) after %s",
01242 fctx->info, domainbuf, fctx->reason);
01243
01244 fctx->reason = NULL;
01245 }
01246
01247 static void
01248 fctx_done(fetchctx_t *fctx, isc_result_t result, int line) {
01249 dns_resolver_t *res;
01250 isc_boolean_t no_response = ISC_FALSE;
01251
01252 REQUIRE(line >= 0);
01253
01254 FCTXTRACE("done");
01255
01256 res = fctx->res;
01257
01258 if (result == ISC_R_SUCCESS) {
01259
01260
01261
01262 log_edns(fctx);
01263 no_response = ISC_TRUE;
01264 }
01265
01266 fctx->reason = NULL;
01267 fctx_stopeverything(fctx, no_response);
01268
01269 LOCK(&res->buckets[fctx->bucketnum].lock);
01270
01271 fctx->state = fetchstate_done;
01272 fctx->attributes &= ~FCTX_ATTR_ADDRWAIT;
01273 fctx_sendevents(fctx, result, line);
01274
01275 UNLOCK(&res->buckets[fctx->bucketnum].lock);
01276 }
01277
01278 static void
01279 process_sendevent(resquery_t *query, isc_event_t *event) {
01280 isc_socketevent_t *sevent = (isc_socketevent_t *)event;
01281 isc_boolean_t destroy_query = ISC_FALSE;
01282 isc_boolean_t retry = ISC_FALSE;
01283 isc_result_t result;
01284 fetchctx_t *fctx;
01285
01286 fctx = query->fctx;
01287
01288 if (RESQUERY_CANCELED(query)) {
01289 if (query->sends == 0 && query->connects == 0) {
01290
01291
01292
01293
01294 if (query->tcpsocket != NULL)
01295 isc_socket_detach(&query->tcpsocket);
01296 destroy_query = ISC_TRUE;
01297 }
01298 } else {
01299 switch (sevent->result) {
01300 case ISC_R_SUCCESS:
01301 break;
01302
01303 case ISC_R_HOSTUNREACH:
01304 case ISC_R_NETUNREACH:
01305 case ISC_R_NOPERM:
01306 case ISC_R_ADDRNOTAVAIL:
01307 case ISC_R_CONNREFUSED:
01308 FCTXTRACE3("query canceled in sendevent(): "
01309 "no route to host; no response",
01310 sevent->result);
01311
01312
01313
01314
01315 add_bad(fctx, query->addrinfo, sevent->result,
01316 badns_unreachable);
01317 fctx_cancelquery(&query, NULL, NULL, ISC_TRUE);
01318 retry = ISC_TRUE;
01319 break;
01320
01321 default:
01322 FCTXTRACE3("query canceled in sendevent() due to "
01323 "unexpected event result; responding",
01324 sevent->result);
01325
01326 fctx_cancelquery(&query, NULL, NULL, ISC_FALSE);
01327 break;
01328 }
01329 }
01330
01331 if (event->ev_type == ISC_SOCKEVENT_CONNECT)
01332 isc_event_free(&event);
01333
01334 if (retry) {
01335
01336
01337
01338
01339 fctx->attributes &= ~FCTX_ATTR_ADDRWAIT;
01340 result = fctx_stopidletimer(fctx);
01341 if (result != ISC_R_SUCCESS)
01342 fctx_done(fctx, result, __LINE__);
01343 else
01344 fctx_try(fctx, ISC_TRUE, ISC_FALSE);
01345 }
01346
01347 if (destroy_query)
01348 resquery_destroy(&query);
01349 }
01350
01351 static void
01352 resquery_udpconnected(isc_task_t *task, isc_event_t *event) {
01353 resquery_t *query = event->ev_arg;
01354
01355 REQUIRE(event->ev_type == ISC_SOCKEVENT_CONNECT);
01356
01357 QTRACE("udpconnected");
01358
01359 UNUSED(task);
01360
01361 INSIST(RESQUERY_CONNECTING(query));
01362
01363 query->connects--;
01364
01365 process_sendevent(query, event);
01366 }
01367
01368 static void
01369 resquery_senddone(isc_task_t *task, isc_event_t *event) {
01370 resquery_t *query = event->ev_arg;
01371
01372 REQUIRE(event->ev_type == ISC_SOCKEVENT_SENDDONE);
01373
01374 QTRACE("senddone");
01375
01376
01377
01378
01379
01380
01381
01382
01383
01384 UNUSED(task);
01385
01386 INSIST(RESQUERY_SENDING(query));
01387
01388 query->sends--;
01389
01390 process_sendevent(query, event);
01391 }
01392
01393 static inline isc_result_t
01394 fctx_addopt(dns_message_t *message, unsigned int version,
01395 isc_uint16_t udpsize, dns_ednsopt_t *ednsopts, size_t count)
01396 {
01397 dns_rdataset_t *rdataset = NULL;
01398 isc_result_t result;
01399
01400 result = dns_message_buildopt(message, &rdataset, version, udpsize,
01401 DNS_MESSAGEEXTFLAG_DO, ednsopts, count);
01402 if (result != ISC_R_SUCCESS)
01403 return (result);
01404 return (dns_message_setopt(message, rdataset));
01405 }
01406
01407 static inline void
01408 fctx_setretryinterval(fetchctx_t *fctx, unsigned int rtt) {
01409 unsigned int seconds;
01410 unsigned int us;
01411
01412
01413
01414
01415
01416 if (fctx->restarts < 3)
01417 us = 800000;
01418 else
01419 us = (800000 << (fctx->restarts - 2));
01420
01421
01422
01423
01424
01425 if (rtt < 50000)
01426 rtt += 50000;
01427 else if (rtt < 100000)
01428 rtt += 100000;
01429 else
01430 rtt += 200000;
01431
01432
01433
01434
01435 if (us < rtt)
01436 us = rtt;
01437
01438
01439
01440
01441 if (us > MAX_SINGLE_QUERY_TIMEOUT_US)
01442 us = MAX_SINGLE_QUERY_TIMEOUT_US;
01443
01444 seconds = us / US_PER_SEC;
01445 us -= seconds * US_PER_SEC;
01446 isc_interval_set(&fctx->interval, seconds, us * 1000);
01447 }
01448
01449 static isc_result_t
01450 fctx_query(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo,
01451 unsigned int options)
01452 {
01453 dns_resolver_t *res;
01454 isc_task_t *task;
01455 isc_result_t result;
01456 resquery_t *query;
01457 isc_sockaddr_t addr;
01458 isc_boolean_t have_addr = ISC_FALSE;
01459 unsigned int srtt;
01460 isc_dscp_t dscp = -1;
01461
01462 FCTXTRACE("query");
01463
01464 res = fctx->res;
01465 task = res->buckets[fctx->bucketnum].task;
01466
01467 srtt = addrinfo->srtt;
01468
01469
01470
01471
01472
01473 if (ISFORWARDER(addrinfo) && srtt < 1000000)
01474 srtt = 1000000;
01475
01476 fctx_setretryinterval(fctx, srtt);
01477 result = fctx_startidletimer(fctx, &fctx->interval);
01478 if (result != ISC_R_SUCCESS)
01479 return (result);
01480
01481 INSIST(ISC_LIST_EMPTY(fctx->validators));
01482
01483 dns_message_reset(fctx->rmessage, DNS_MESSAGE_INTENTPARSE);
01484
01485 query = isc_mem_get(fctx->mctx, sizeof(*query));
01486 if (query == NULL) {
01487 result = ISC_R_NOMEMORY;
01488 goto stop_idle_timer;
01489 }
01490 query->mctx = fctx->mctx;
01491 query->options = options;
01492 query->attributes = 0;
01493 query->sends = 0;
01494 query->connects = 0;
01495 query->dscp = addrinfo->dscp;
01496
01497
01498
01499
01500 query->addrinfo = addrinfo;
01501 TIME_NOW(&query->start);
01502
01503
01504
01505
01506
01507
01508 query->dispatchmgr = res->dispatchmgr;
01509 query->dispatch = NULL;
01510 query->exclusivesocket = ISC_FALSE;
01511 query->tcpsocket = NULL;
01512 if (res->view->peers != NULL) {
01513 dns_peer_t *peer = NULL;
01514 isc_netaddr_t dstip;
01515 isc_boolean_t usetcp = ISC_FALSE;
01516 isc_netaddr_fromsockaddr(&dstip, &addrinfo->sockaddr);
01517 result = dns_peerlist_peerbyaddr(res->view->peers,
01518 &dstip, &peer);
01519 if (result == ISC_R_SUCCESS) {
01520 result = dns_peer_getquerysource(peer, &addr);
01521 if (result == ISC_R_SUCCESS)
01522 have_addr = ISC_TRUE;
01523 result = dns_peer_getquerydscp(peer, &dscp);
01524 if (result == ISC_R_SUCCESS)
01525 query->dscp = dscp;
01526 result = dns_peer_getforcetcp(peer, &usetcp);
01527 if (result == ISC_R_SUCCESS && usetcp)
01528 query->options |= DNS_FETCHOPT_TCP;
01529 }
01530 }
01531
01532 dscp = -1;
01533 if ((query->options & DNS_FETCHOPT_TCP) != 0) {
01534 int pf;
01535
01536 pf = isc_sockaddr_pf(&addrinfo->sockaddr);
01537 if (!have_addr) {
01538 switch (pf) {
01539 case PF_INET:
01540 result = dns_dispatch_getlocaladdress(
01541 res->dispatches4->dispatches[0],
01542 &addr);
01543 dscp = dns_resolver_getquerydscp4(fctx->res);
01544 break;
01545 case PF_INET6:
01546 result = dns_dispatch_getlocaladdress(
01547 res->dispatches6->dispatches[0],
01548 &addr);
01549 dscp = dns_resolver_getquerydscp6(fctx->res);
01550 break;
01551 default:
01552 result = ISC_R_NOTIMPLEMENTED;
01553 break;
01554 }
01555 if (result != ISC_R_SUCCESS)
01556 goto cleanup_query;
01557 }
01558 isc_sockaddr_setport(&addr, 0);
01559 if (query->dscp == -1)
01560 query->dscp = dscp;
01561
01562 result = isc_socket_create(res->socketmgr, pf,
01563 isc_sockettype_tcp,
01564 &query->tcpsocket);
01565 if (result != ISC_R_SUCCESS)
01566 goto cleanup_query;
01567
01568 #ifndef BROKEN_TCP_BIND_BEFORE_CONNECT
01569 result = isc_socket_bind(query->tcpsocket, &addr, 0);
01570 if (result != ISC_R_SUCCESS)
01571 goto cleanup_socket;
01572 #endif
01573
01574
01575
01576 } else {
01577 if (have_addr) {
01578 unsigned int attrs, attrmask;
01579 attrs = DNS_DISPATCHATTR_UDP;
01580 switch (isc_sockaddr_pf(&addr)) {
01581 case AF_INET:
01582 attrs |= DNS_DISPATCHATTR_IPV4;
01583 dscp = dns_resolver_getquerydscp4(fctx->res);
01584 break;
01585 case AF_INET6:
01586 attrs |= DNS_DISPATCHATTR_IPV6;
01587 dscp = dns_resolver_getquerydscp6(fctx->res);
01588 break;
01589 default:
01590 result = ISC_R_NOTIMPLEMENTED;
01591 goto cleanup_query;
01592 }
01593 attrmask = DNS_DISPATCHATTR_UDP;
01594 attrmask |= DNS_DISPATCHATTR_TCP;
01595 attrmask |= DNS_DISPATCHATTR_IPV4;
01596 attrmask |= DNS_DISPATCHATTR_IPV6;
01597 result = dns_dispatch_getudp(res->dispatchmgr,
01598 res->socketmgr,
01599 res->taskmgr, &addr,
01600 4096, 20000, 32768, 16411,
01601 16433, attrs, attrmask,
01602 &query->dispatch);
01603 if (result != ISC_R_SUCCESS)
01604 goto cleanup_query;
01605 } else {
01606 switch (isc_sockaddr_pf(&addrinfo->sockaddr)) {
01607 case PF_INET:
01608 dns_dispatch_attach(
01609 dns_resolver_dispatchv4(res),
01610 &query->dispatch);
01611 query->exclusivesocket = res->exclusivev4;
01612 dscp = dns_resolver_getquerydscp4(fctx->res);
01613 break;
01614 case PF_INET6:
01615 dns_dispatch_attach(
01616 dns_resolver_dispatchv6(res),
01617 &query->dispatch);
01618 query->exclusivesocket = res->exclusivev6;
01619 dscp = dns_resolver_getquerydscp6(fctx->res);
01620 break;
01621 default:
01622 result = ISC_R_NOTIMPLEMENTED;
01623 goto cleanup_query;
01624 }
01625 }
01626
01627 if (query->dscp == -1)
01628 query->dscp = dscp;
01629
01630
01631
01632
01633
01634
01635
01636 INSIST(query->dispatch != NULL);
01637 }
01638
01639 query->dispentry = NULL;
01640 fctx_increference(fctx);
01641 query->fctx = fctx;
01642 query->tsig = NULL;
01643 query->tsigkey = NULL;
01644 ISC_LINK_INIT(query, link);
01645 query->magic = QUERY_MAGIC;
01646
01647 if ((query->options & DNS_FETCHOPT_TCP) != 0) {
01648
01649
01650
01651
01652
01653 if (query->dscp != -1)
01654 isc_socket_dscp(query->tcpsocket, query->dscp);
01655 result = isc_socket_connect(query->tcpsocket,
01656 &addrinfo->sockaddr, task,
01657 resquery_connected, query);
01658 if (result != ISC_R_SUCCESS)
01659 goto cleanup_socket;
01660 query->connects++;
01661 QTRACE("connecting via TCP");
01662 } else {
01663 result = resquery_send(query);
01664 if (result != ISC_R_SUCCESS)
01665 goto cleanup_dispatch;
01666 }
01667
01668 fctx->querysent++;
01669
01670 ISC_LIST_APPEND(fctx->queries, query, link);
01671 query->fctx->nqueries++;
01672 if (isc_sockaddr_pf(&addrinfo->sockaddr) == PF_INET)
01673 inc_stats(res, dns_resstatscounter_queryv4);
01674 else
01675 inc_stats(res, dns_resstatscounter_queryv6);
01676 if (res->view->resquerystats != NULL)
01677 dns_rdatatypestats_increment(res->view->resquerystats,
01678 fctx->type);
01679
01680 return (ISC_R_SUCCESS);
01681
01682 cleanup_socket:
01683 isc_socket_detach(&query->tcpsocket);
01684
01685 cleanup_dispatch:
01686 if (query->dispatch != NULL)
01687 dns_dispatch_detach(&query->dispatch);
01688
01689 cleanup_query:
01690 if (query->connects == 0) {
01691 query->magic = 0;
01692 isc_mem_put(fctx->mctx, query, sizeof(*query));
01693 }
01694
01695 stop_idle_timer:
01696 RUNTIME_CHECK(fctx_stopidletimer(fctx) == ISC_R_SUCCESS);
01697
01698 return (result);
01699 }
01700
01701 static isc_boolean_t
01702 bad_edns(fetchctx_t *fctx, isc_sockaddr_t *address) {
01703 isc_sockaddr_t *sa;
01704
01705 for (sa = ISC_LIST_HEAD(fctx->bad_edns);
01706 sa != NULL;
01707 sa = ISC_LIST_NEXT(sa, link)) {
01708 if (isc_sockaddr_equal(sa, address))
01709 return (ISC_TRUE);
01710 }
01711
01712 return (ISC_FALSE);
01713 }
01714
01715 static void
01716 add_bad_edns(fetchctx_t *fctx, isc_sockaddr_t *address) {
01717 isc_sockaddr_t *sa;
01718
01719 if (bad_edns(fctx, address))
01720 return;
01721
01722 sa = isc_mem_get(fctx->mctx, sizeof(*sa));
01723 if (sa == NULL)
01724 return;
01725
01726 *sa = *address;
01727 ISC_LIST_INITANDAPPEND(fctx->bad_edns, sa, link);
01728 }
01729
01730 static struct tried *
01731 triededns(fetchctx_t *fctx, isc_sockaddr_t *address) {
01732 struct tried *tried;
01733
01734 for (tried = ISC_LIST_HEAD(fctx->edns);
01735 tried != NULL;
01736 tried = ISC_LIST_NEXT(tried, link)) {
01737 if (isc_sockaddr_equal(&tried->addr, address))
01738 return (tried);
01739 }
01740
01741 return (NULL);
01742 }
01743
01744 static void
01745 add_triededns(fetchctx_t *fctx, isc_sockaddr_t *address) {
01746 struct tried *tried;
01747
01748 tried = triededns(fctx, address);
01749 if (tried != NULL) {
01750 tried->count++;
01751 return;
01752 }
01753
01754 tried = isc_mem_get(fctx->mctx, sizeof(*tried));
01755 if (tried == NULL)
01756 return;
01757
01758 tried->addr = *address;
01759 tried->count = 1;
01760 ISC_LIST_INITANDAPPEND(fctx->edns, tried, link);
01761 }
01762
01763 static struct tried *
01764 triededns512(fetchctx_t *fctx, isc_sockaddr_t *address) {
01765 struct tried *tried;
01766
01767 for (tried = ISC_LIST_HEAD(fctx->edns512);
01768 tried != NULL;
01769 tried = ISC_LIST_NEXT(tried, link)) {
01770 if (isc_sockaddr_equal(&tried->addr, address))
01771 return (tried);
01772 }
01773
01774 return (NULL);
01775 }
01776
01777 static void
01778 add_triededns512(fetchctx_t *fctx, isc_sockaddr_t *address) {
01779 struct tried *tried;
01780
01781 tried = triededns512(fctx, address);
01782 if (tried != NULL) {
01783 tried->count++;
01784 return;
01785 }
01786
01787 tried = isc_mem_get(fctx->mctx, sizeof(*tried));
01788 if (tried == NULL)
01789 return;
01790
01791 tried->addr = *address;
01792 tried->count = 1;
01793 ISC_LIST_INITANDAPPEND(fctx->edns512, tried, link);
01794 }
01795
01796 #ifdef ISC_PLATFORM_USESIT
01797 static void
01798 compute_cc(resquery_t *query, unsigned char *sit, size_t len) {
01799 #ifdef AES_SIT
01800 unsigned char digest[ISC_AES_BLOCK_LENGTH];
01801 unsigned char input[16];
01802 isc_netaddr_t netaddr;
01803 unsigned int i;
01804
01805 INSIST(len >= 8U);
01806
01807 isc_netaddr_fromsockaddr(&netaddr, &query->addrinfo->sockaddr);
01808 switch (netaddr.family) {
01809 case AF_INET:
01810 memmove(input, (unsigned char *)&netaddr.type.in, 4);
01811 memset(input + 4, 0, 12);
01812 break;
01813 case AF_INET6:
01814 memmove(input, (unsigned char *)&netaddr.type.in6, 16);
01815 break;
01816 }
01817 isc_aes128_crypt(query->fctx->res->view->secret, input, digest);
01818 for (i = 0; i < 8; i++)
01819 digest[i] ^= digest[i + 8];
01820 memmove(sit, digest, 8);
01821 #endif
01822 #ifdef HMAC_SHA1_SIT
01823 unsigned char digest[ISC_SHA1_DIGESTLENGTH];
01824 isc_netaddr_t netaddr;
01825 isc_hmacsha1_t hmacsha1;
01826
01827 INSIST(len >= 8U);
01828
01829 isc_hmacsha1_init(&hmacsha1, query->fctx->res->view->secret,
01830 ISC_SHA1_DIGESTLENGTH);
01831 isc_netaddr_fromsockaddr(&netaddr, &query->addrinfo->sockaddr);
01832 switch (netaddr.family) {
01833 case AF_INET:
01834 isc_hmacsha1_update(&hmacsha1,
01835 (unsigned char *)&netaddr.type.in, 4);
01836 break;
01837 case AF_INET6:
01838 isc_hmacsha1_update(&hmacsha1,
01839 (unsigned char *)&netaddr.type.in6, 16);
01840 break;
01841 }
01842 isc_hmacsha1_sign(&hmacsha1, digest, sizeof(digest));
01843 memmove(sit, digest, 8);
01844 isc_hmacsha1_invalidate(&hmacsha1);
01845 #endif
01846 #ifdef HMAC_SHA256_SIT
01847 unsigned char digest[ISC_SHA256_DIGESTLENGTH];
01848 isc_netaddr_t netaddr;
01849 isc_hmacsha256_t hmacsha256;
01850
01851 INSIST(len >= 8U);
01852
01853 isc_hmacsha256_init(&hmacsha256, query->fctx->res->view->secret,
01854 ISC_SHA256_DIGESTLENGTH);
01855 isc_netaddr_fromsockaddr(&netaddr, &query->addrinfo->sockaddr);
01856 switch (netaddr.family) {
01857 case AF_INET:
01858 isc_hmacsha256_update(&hmacsha256,
01859 (unsigned char *)&netaddr.type.in, 4);
01860 break;
01861 case AF_INET6:
01862 isc_hmacsha256_update(&hmacsha256,
01863 (unsigned char *)&netaddr.type.in6, 16);
01864 break;
01865 }
01866 isc_hmacsha256_sign(&hmacsha256, digest, sizeof(digest));
01867 memmove(sit, digest, 8);
01868 isc_hmacsha256_invalidate(&hmacsha256);
01869 #endif
01870 }
01871 #endif
01872
01873 static isc_result_t
01874 issecuredomain(dns_view_t *view, dns_name_t *name, dns_rdatatype_t type,
01875 isc_stdtime_t now, isc_boolean_t checknta,
01876 isc_boolean_t *issecure)
01877 {
01878 dns_name_t suffix;
01879 unsigned int labels;
01880
01881
01882
01883
01884
01885
01886
01887 labels = dns_name_countlabels(name);
01888 if (dns_rdatatype_atparent(type) && labels > 1) {
01889 dns_name_init(&suffix, NULL);
01890 dns_name_getlabelsequence(name, 1, labels - 1, &suffix);
01891 name = &suffix;
01892 }
01893
01894 return (dns_view_issecuredomain(view, name, now, checknta, issecure));
01895 }
01896
01897 static isc_boolean_t
01898 wouldvalidate(fetchctx_t *fctx) {
01899 isc_boolean_t secure_domain;
01900 isc_result_t result;
01901 isc_stdtime_t now;
01902
01903 if (!fctx->res->view->enablevalidation)
01904 return (ISC_FALSE);
01905
01906 if (fctx->res->view->dlv != NULL)
01907 return (ISC_TRUE);
01908
01909 isc_stdtime_get(&now);
01910 result = dns_view_issecuredomain(fctx->res->view, &fctx->name,
01911 now, ISC_TRUE, &secure_domain);
01912 if (result != ISC_R_SUCCESS)
01913 return (ISC_FALSE);
01914 return (secure_domain);
01915 }
01916
01917 static isc_result_t
01918 resquery_send(resquery_t *query) {
01919 fetchctx_t *fctx;
01920 isc_result_t result;
01921 dns_name_t *qname = NULL;
01922 dns_rdataset_t *qrdataset = NULL;
01923 isc_region_t r;
01924 dns_resolver_t *res;
01925 isc_task_t *task;
01926 isc_socket_t *sock;
01927 isc_buffer_t tcpbuffer;
01928 isc_sockaddr_t *address;
01929 isc_buffer_t *buffer;
01930 isc_netaddr_t ipaddr;
01931 dns_tsigkey_t *tsigkey = NULL;
01932 dns_peer_t *peer = NULL;
01933 isc_boolean_t useedns;
01934 dns_compress_t cctx;
01935 isc_boolean_t cleanup_cctx = ISC_FALSE;
01936 isc_boolean_t secure_domain;
01937 isc_boolean_t connecting = ISC_FALSE;
01938 dns_ednsopt_t ednsopts[DNS_EDNSOPTIONS];
01939 unsigned ednsopt = 0;
01940 isc_uint16_t hint = 0, udpsize = 0;
01941
01942 fctx = query->fctx;
01943 QTRACE("send");
01944
01945 res = fctx->res;
01946 task = res->buckets[fctx->bucketnum].task;
01947 address = NULL;
01948
01949 if ((query->options & DNS_FETCHOPT_TCP) != 0) {
01950
01951
01952
01953 isc_buffer_init(&tcpbuffer, query->data, sizeof(query->data));
01954 isc_buffer_init(&query->buffer, query->data + 2,
01955 sizeof(query->data) - 2);
01956 buffer = &tcpbuffer;
01957 } else {
01958 isc_buffer_init(&query->buffer, query->data,
01959 sizeof(query->data));
01960 buffer = &query->buffer;
01961 }
01962
01963 result = dns_message_gettempname(fctx->qmessage, &qname);
01964 if (result != ISC_R_SUCCESS)
01965 goto cleanup_temps;
01966 result = dns_message_gettemprdataset(fctx->qmessage, &qrdataset);
01967 if (result != ISC_R_SUCCESS)
01968 goto cleanup_temps;
01969
01970
01971
01972
01973 result = dns_dispatch_addresponse2(query->dispatch,
01974 &query->addrinfo->sockaddr,
01975 task,
01976 resquery_response,
01977 query,
01978 &query->id,
01979 &query->dispentry,
01980 res->socketmgr);
01981 if (result != ISC_R_SUCCESS)
01982 goto cleanup_temps;
01983
01984 fctx->qmessage->opcode = dns_opcode_query;
01985
01986
01987
01988
01989 dns_name_init(qname, NULL);
01990 dns_name_clone(&fctx->name, qname);
01991 dns_rdataset_init(qrdataset);
01992 dns_rdataset_makequestion(qrdataset, res->rdclass, fctx->type);
01993 ISC_LIST_APPEND(qname->list, qrdataset, link);
01994 dns_message_addname(fctx->qmessage, qname, DNS_SECTION_QUESTION);
01995 qname = NULL;
01996 qrdataset = NULL;
01997
01998
01999
02000
02001
02002 if ((query->options & DNS_FETCHOPT_RECURSIVE) != 0 ||
02003 ISFORWARDER(query->addrinfo))
02004 fctx->qmessage->flags |= DNS_MESSAGEFLAG_RD;
02005
02006
02007
02008
02009
02010
02011 if ((query->options & DNS_FETCHOPT_NOCDFLAG) != 0)
02012
02013 ;
02014 else if ((query->options & DNS_FETCHOPT_NOVALIDATE) != 0)
02015 fctx->qmessage->flags |= DNS_MESSAGEFLAG_CD;
02016 else if (res->view->enablevalidation &&
02017 ((fctx->qmessage->flags & DNS_MESSAGEFLAG_RD) != 0))
02018 {
02019 isc_boolean_t checknta =
02020 ISC_TF((query->options & DNS_FETCHOPT_NONTA) == 0);
02021 result = issecuredomain(res->view, &fctx->name, fctx->type,
02022 isc_time_seconds(&query->start),
02023 checknta, &secure_domain);
02024 if (result != ISC_R_SUCCESS)
02025 secure_domain = ISC_FALSE;
02026 if (res->view->dlv != NULL)
02027 secure_domain = ISC_TRUE;
02028 if (secure_domain)
02029 fctx->qmessage->flags |= DNS_MESSAGEFLAG_CD;
02030 }
02031
02032
02033
02034
02035 fctx->qmessage->id = query->id;
02036
02037
02038
02039
02040 result = dns_compress_init(&cctx, -1, fctx->res->mctx);
02041 if (result != ISC_R_SUCCESS)
02042 goto cleanup_message;
02043 cleanup_cctx = ISC_TRUE;
02044
02045 result = dns_message_renderbegin(fctx->qmessage, &cctx,
02046 &query->buffer);
02047 if (result != ISC_R_SUCCESS)
02048 goto cleanup_message;
02049
02050 result = dns_message_rendersection(fctx->qmessage,
02051 DNS_SECTION_QUESTION, 0);
02052 if (result != ISC_R_SUCCESS)
02053 goto cleanup_message;
02054
02055 peer = NULL;
02056 isc_netaddr_fromsockaddr(&ipaddr, &query->addrinfo->sockaddr);
02057 (void) dns_peerlist_peerbyaddr(fctx->res->view->peers, &ipaddr, &peer);
02058
02059
02060
02061
02062
02063 if ((query->addrinfo->flags & DNS_FETCHOPT_NOEDNS0) == 0 &&
02064 peer != NULL &&
02065 dns_peer_getsupportedns(peer, &useedns) == ISC_R_SUCCESS &&
02066 !useedns)
02067 {
02068 query->options |= DNS_FETCHOPT_NOEDNS0;
02069 dns_adb_changeflags(fctx->adb, query->addrinfo,
02070 DNS_FETCHOPT_NOEDNS0,
02071 DNS_FETCHOPT_NOEDNS0);
02072 }
02073
02074
02075 if ((query->addrinfo->flags & DNS_FETCHOPT_NOEDNS0) != 0)
02076 query->options |= DNS_FETCHOPT_NOEDNS0;
02077
02078
02079 if ((query->options & DNS_FETCHOPT_NOEDNS0) == 0 &&
02080 dns_adb_noedns(fctx->adb, query->addrinfo))
02081 query->options |= DNS_FETCHOPT_NOEDNS0;
02082
02083 if (fctx->timeout && (query->options & DNS_FETCHOPT_NOEDNS0) == 0) {
02084 isc_sockaddr_t *sockaddr = &query->addrinfo->sockaddr;
02085 struct tried *tried;
02086
02087 if (fctx->timeouts > (MAX_EDNS0_TIMEOUTS * 2) &&
02088 (!EDNSOK(query->addrinfo) || !wouldvalidate(fctx))) {
02089 query->options |= DNS_FETCHOPT_NOEDNS0;
02090 fctx->reason = "disabling EDNS";
02091 } else if ((tried = triededns512(fctx, sockaddr)) != NULL &&
02092 tried->count >= 2U &&
02093 (!EDNSOK(query->addrinfo) || !wouldvalidate(fctx))) {
02094 query->options |= DNS_FETCHOPT_NOEDNS0;
02095 fctx->reason = "disabling EDNS";
02096 } else if ((tried = triededns(fctx, sockaddr)) != NULL) {
02097 if (tried->count == 1U) {
02098 hint = dns_adb_getudpsize(fctx->adb,
02099 query->addrinfo);
02100 } else if (tried->count >= 2U) {
02101 query->options |= DNS_FETCHOPT_EDNS512;
02102 fctx->reason = "reducing the advertised EDNS "
02103 "UDP packet size to 512 octets";
02104 }
02105 }
02106 }
02107 fctx->timeout = ISC_FALSE;
02108
02109
02110
02111
02112
02113 if ((query->options & DNS_FETCHOPT_NOEDNS0) == 0) {
02114 if ((query->addrinfo->flags & DNS_FETCHOPT_NOEDNS0) == 0) {
02115 unsigned int version = DNS_EDNS_VERSION;
02116 unsigned int flags = query->addrinfo->flags;
02117 isc_boolean_t reqnsid = res->view->requestnsid;
02118 #ifdef ISC_PLATFORM_USESIT
02119 isc_boolean_t reqsit = res->view->requestsit;
02120 unsigned char sit[64];
02121 #endif
02122
02123 if ((flags & FCTX_ADDRINFO_EDNSOK) != 0 &&
02124 (query->options & DNS_FETCHOPT_EDNS512) == 0) {
02125 udpsize = dns_adb_probesize2(fctx->adb,
02126 query->addrinfo,
02127 fctx->timeouts);
02128 if (udpsize > res->udpsize)
02129 udpsize = res->udpsize;
02130 }
02131
02132 if (peer != NULL)
02133 (void)dns_peer_getudpsize(peer, &udpsize);
02134
02135 if (udpsize == 0U && res->udpsize == 512U)
02136 udpsize = 512;
02137
02138
02139
02140
02141 if (udpsize == 512U)
02142 query->options |= DNS_FETCHOPT_EDNS512;
02143
02144
02145
02146
02147 if (hint != 0U)
02148 udpsize = hint;
02149
02150
02151
02152
02153
02154 if (udpsize == 0U)
02155 udpsize = 512;
02156
02157 if ((flags & DNS_FETCHOPT_EDNSVERSIONSET) != 0) {
02158 version = flags & DNS_FETCHOPT_EDNSVERSIONMASK;
02159 version >>= DNS_FETCHOPT_EDNSVERSIONSHIFT;
02160 }
02161
02162
02163 if (peer != NULL) {
02164 isc_uint8_t ednsversion;
02165 (void) dns_peer_getrequestnsid(peer, &reqnsid);
02166 #ifdef ISC_PLATFORM_USESIT
02167 (void) dns_peer_getrequestsit(peer, &reqsit);
02168 #endif
02169 result = dns_peer_getednsversion(peer,
02170 &ednsversion);
02171 if (result == ISC_R_SUCCESS &&
02172 ednsversion < version)
02173 version = ednsversion;
02174 }
02175 #ifdef ISC_PLATFORM_USESIT
02176 if (NOSIT(query->addrinfo))
02177 reqsit = ISC_FALSE;
02178 #endif
02179 if (reqnsid) {
02180 INSIST(ednsopt < DNS_EDNSOPTIONS);
02181 ednsopts[ednsopt].code = DNS_OPT_NSID;
02182 ednsopts[ednsopt].length = 0;
02183 ednsopts[ednsopt].value = NULL;
02184 ednsopt++;
02185 }
02186 #ifdef ISC_PLATFORM_USESIT
02187 #if DNS_EDNS_VERSION > 0
02188
02189
02190
02191
02192
02193 if (version < 1)
02194 reqsit = ISC_FALSE;
02195 #endif
02196 if (reqsit) {
02197 INSIST(ednsopt < DNS_EDNSOPTIONS);
02198 ednsopts[ednsopt].code = DNS_OPT_SIT;
02199 ednsopts[ednsopt].length = (isc_uint16_t)
02200 dns_adb_getsit(fctx->adb,
02201 query->addrinfo,
02202 sit, sizeof(sit));
02203 if (ednsopts[ednsopt].length != 0) {
02204 ednsopts[ednsopt].value = sit;
02205 inc_stats(fctx->res,
02206 dns_resstatscounter_sitout);
02207 } else {
02208 compute_cc(query, sit, sizeof(sit));
02209 ednsopts[ednsopt].value = sit;
02210 ednsopts[ednsopt].length = 8;
02211 inc_stats(fctx->res,
02212 dns_resstatscounter_sitcc);
02213 }
02214 ednsopt++;
02215 }
02216 #endif
02217 query->ednsversion = version;
02218 result = fctx_addopt(fctx->qmessage, version,
02219 udpsize, ednsopts, ednsopt);
02220 if (reqnsid && result == ISC_R_SUCCESS) {
02221 query->options |= DNS_FETCHOPT_WANTNSID;
02222 } else if (result != ISC_R_SUCCESS) {
02223
02224
02225
02226
02227
02228 query->options |= DNS_FETCHOPT_NOEDNS0;
02229 query->ednsversion = -1;
02230 udpsize = 0;
02231 }
02232 } else {
02233
02234
02235
02236
02237
02238 query->options |= DNS_FETCHOPT_NOEDNS0;
02239 query->ednsversion = -1;
02240 }
02241 } else
02242 query->ednsversion = -1;
02243
02244
02245
02246
02247 query->udpsize = udpsize;
02248
02249
02250
02251
02252 if (NEEDEDNS0(fctx) && (query->options & DNS_FETCHOPT_NOEDNS0) != 0) {
02253 result = DNS_R_SERVFAIL;
02254 goto cleanup_message;
02255 }
02256
02257 if (udpsize > 512U)
02258 add_triededns(fctx, &query->addrinfo->sockaddr);
02259
02260 if (udpsize == 512U)
02261 add_triededns512(fctx, &query->addrinfo->sockaddr);
02262
02263
02264
02265
02266 if ((query->options & DNS_FETCHOPT_NOEDNS0) != 0)
02267 fctx->qmessage->flags &= ~DNS_MESSAGEFLAG_CD;
02268
02269
02270
02271
02272 result = dns_view_getpeertsig(fctx->res->view, &ipaddr, &tsigkey);
02273 if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND)
02274 goto cleanup_message;
02275
02276 if (tsigkey != NULL) {
02277 result = dns_message_settsigkey(fctx->qmessage, tsigkey);
02278 dns_tsigkey_detach(&tsigkey);
02279 if (result != ISC_R_SUCCESS)
02280 goto cleanup_message;
02281 }
02282
02283 result = dns_message_rendersection(fctx->qmessage,
02284 DNS_SECTION_ADDITIONAL, 0);
02285 if (result != ISC_R_SUCCESS)
02286 goto cleanup_message;
02287
02288 result = dns_message_renderend(fctx->qmessage);
02289 if (result != ISC_R_SUCCESS)
02290 goto cleanup_message;
02291
02292 dns_compress_invalidate(&cctx);
02293 cleanup_cctx = ISC_FALSE;
02294
02295 if (dns_message_gettsigkey(fctx->qmessage) != NULL) {
02296 dns_tsigkey_attach(dns_message_gettsigkey(fctx->qmessage),
02297 &query->tsigkey);
02298 result = dns_message_getquerytsig(fctx->qmessage,
02299 fctx->res->mctx,
02300 &query->tsig);
02301 if (result != ISC_R_SUCCESS)
02302 goto cleanup_message;
02303 }
02304
02305
02306
02307
02308
02309 if ((query->options & DNS_FETCHOPT_TCP) != 0) {
02310 isc_buffer_usedregion(&query->buffer, &r);
02311 isc_buffer_putuint16(&tcpbuffer, (isc_uint16_t)r.length);
02312 isc_buffer_add(&tcpbuffer, r.length);
02313 }
02314
02315
02316
02317
02318 dns_message_logfmtpacket2(fctx->qmessage, "sending packet to",
02319 &query->addrinfo->sockaddr,
02320 DNS_LOGCATEGORY_RESOLVER,
02321 DNS_LOGMODULE_PACKETS,
02322 &dns_master_style_comment,
02323 ISC_LOG_DEBUG(11),
02324 fctx->res->mctx);
02325
02326
02327
02328
02329 dns_message_reset(fctx->qmessage, DNS_MESSAGE_INTENTRENDER);
02330
02331 if (query->exclusivesocket)
02332 sock = dns_dispatch_getentrysocket(query->dispentry);
02333 else
02334 sock = dns_dispatch_getsocket(query->dispatch);
02335
02336
02337
02338 if ((query->options & DNS_FETCHOPT_TCP) == 0) {
02339 address = &query->addrinfo->sockaddr;
02340 if (query->exclusivesocket) {
02341 result = isc_socket_connect(sock, address, task,
02342 resquery_udpconnected,
02343 query);
02344 if (result != ISC_R_SUCCESS)
02345 goto cleanup_message;
02346 connecting = ISC_TRUE;
02347 query->connects++;
02348 }
02349 }
02350 isc_buffer_usedregion(buffer, &r);
02351
02352
02353
02354
02355
02356 memset(&query->sendevent, 0, sizeof(query->sendevent));
02357 ISC_EVENT_INIT(&query->sendevent, sizeof(query->sendevent), 0, NULL,
02358 ISC_SOCKEVENT_SENDDONE, resquery_senddone, query,
02359 NULL, NULL, NULL);
02360
02361 if (query->dscp == -1) {
02362 query->sendevent.attributes &= ~ISC_SOCKEVENTATTR_DSCP;
02363 query->sendevent.dscp = 0;
02364 } else {
02365 query->sendevent.attributes |= ISC_SOCKEVENTATTR_DSCP;
02366 query->sendevent.dscp = query->dscp;
02367 if ((query->options & DNS_FETCHOPT_TCP) != 0)
02368 isc_socket_dscp(sock, query->dscp);
02369 }
02370
02371 result = isc_socket_sendto2(sock, &r, task, address, NULL,
02372 &query->sendevent, 0);
02373 if (result != ISC_R_SUCCESS) {
02374 if (connecting) {
02375
02376
02377
02378
02379
02380
02381 query->fctx->nqueries++;
02382 query->attributes |= RESQUERY_ATTR_CANCELED;
02383 }
02384 goto cleanup_message;
02385 }
02386
02387 query->sends++;
02388
02389 QTRACE("sent");
02390
02391 return (ISC_R_SUCCESS);
02392
02393 cleanup_message:
02394 if (cleanup_cctx)
02395 dns_compress_invalidate(&cctx);
02396
02397 dns_message_reset(fctx->qmessage, DNS_MESSAGE_INTENTRENDER);
02398
02399
02400
02401
02402 dns_dispatch_removeresponse(&query->dispentry, NULL);
02403
02404 cleanup_temps:
02405 if (qname != NULL)
02406 dns_message_puttempname(fctx->qmessage, &qname);
02407 if (qrdataset != NULL)
02408 dns_message_puttemprdataset(fctx->qmessage, &qrdataset);
02409
02410 return (result);
02411 }
02412
02413 static void
02414 resquery_connected(isc_task_t *task, isc_event_t *event) {
02415 isc_socketevent_t *sevent = (isc_socketevent_t *)event;
02416 resquery_t *query = event->ev_arg;
02417 isc_boolean_t retry = ISC_FALSE;
02418 isc_interval_t interval;
02419 isc_result_t result;
02420 unsigned int attrs;
02421 fetchctx_t *fctx;
02422
02423 REQUIRE(event->ev_type == ISC_SOCKEVENT_CONNECT);
02424 REQUIRE(VALID_QUERY(query));
02425
02426 QTRACE("connected");
02427
02428 UNUSED(task);
02429
02430
02431
02432
02433
02434
02435
02436
02437
02438 query->connects--;
02439 fctx = query->fctx;
02440
02441 if (RESQUERY_CANCELED(query)) {
02442
02443
02444
02445
02446 isc_socket_detach(&query->tcpsocket);
02447 resquery_destroy(&query);
02448 } else {
02449 switch (sevent->result) {
02450 case ISC_R_SUCCESS:
02451
02452
02453
02454
02455
02456
02457
02458 isc_interval_set(&interval, 20, 0);
02459 result = fctx_startidletimer(query->fctx, &interval);
02460 if (result != ISC_R_SUCCESS) {
02461 FCTXTRACE("query canceled: idle timer failed; "
02462 "responding");
02463
02464 fctx_cancelquery(&query, NULL, NULL, ISC_FALSE);
02465 fctx_done(fctx, result, __LINE__);
02466 break;
02467 }
02468
02469
02470
02471
02472 attrs = 0;
02473 attrs |= DNS_DISPATCHATTR_TCP;
02474 attrs |= DNS_DISPATCHATTR_PRIVATE;
02475 attrs |= DNS_DISPATCHATTR_CONNECTED;
02476 if (isc_sockaddr_pf(&query->addrinfo->sockaddr) ==
02477 AF_INET)
02478 attrs |= DNS_DISPATCHATTR_IPV4;
02479 else
02480 attrs |= DNS_DISPATCHATTR_IPV6;
02481 attrs |= DNS_DISPATCHATTR_MAKEQUERY;
02482
02483 result = dns_dispatch_createtcp(query->dispatchmgr,
02484 query->tcpsocket,
02485 query->fctx->res->taskmgr,
02486 4096, 2, 1, 1, 3, attrs,
02487 &query->dispatch);
02488
02489
02490
02491
02492
02493
02494 isc_socket_detach(&query->tcpsocket);
02495
02496 if (result == ISC_R_SUCCESS)
02497 result = resquery_send(query);
02498
02499 if (result != ISC_R_SUCCESS) {
02500 FCTXTRACE("query canceled: "
02501 "resquery_send() failed; responding");
02502
02503 fctx_cancelquery(&query, NULL, NULL, ISC_FALSE);
02504 fctx_done(fctx, result, __LINE__);
02505 }
02506 break;
02507
02508 case ISC_R_NETUNREACH:
02509 case ISC_R_HOSTUNREACH:
02510 case ISC_R_CONNREFUSED:
02511 case ISC_R_NOPERM:
02512 case ISC_R_ADDRNOTAVAIL:
02513 case ISC_R_CONNECTIONRESET:
02514 FCTXTRACE3("query canceled in connected(): "
02515 "no route to host; no response",
02516 sevent->result);
02517
02518
02519
02520
02521 isc_socket_detach(&query->tcpsocket);
02522 fctx_cancelquery(&query, NULL, NULL, ISC_TRUE);
02523 retry = ISC_TRUE;
02524 break;
02525
02526 default:
02527 FCTXTRACE3("query canceled in connected() due to "
02528 "unexpected event result; responding",
02529 sevent->result);
02530
02531 isc_socket_detach(&query->tcpsocket);
02532 fctx_cancelquery(&query, NULL, NULL, ISC_FALSE);
02533 break;
02534 }
02535 }
02536
02537 isc_event_free(&event);
02538
02539 if (retry) {
02540
02541
02542
02543
02544 fctx->attributes &= ~FCTX_ATTR_ADDRWAIT;
02545 result = fctx_stopidletimer(fctx);
02546 if (result != ISC_R_SUCCESS)
02547 fctx_done(fctx, result, __LINE__);
02548 else
02549 fctx_try(fctx, ISC_TRUE, ISC_FALSE);
02550 }
02551 }
02552
02553 static void
02554 fctx_finddone(isc_task_t *task, isc_event_t *event) {
02555 fetchctx_t *fctx;
02556 dns_adbfind_t *find;
02557 dns_resolver_t *res;
02558 isc_boolean_t want_try = ISC_FALSE;
02559 isc_boolean_t want_done = ISC_FALSE;
02560 isc_boolean_t bucket_empty = ISC_FALSE;
02561 unsigned int bucketnum;
02562 isc_boolean_t dodestroy = ISC_FALSE;
02563
02564 find = event->ev_sender;
02565 fctx = event->ev_arg;
02566 REQUIRE(VALID_FCTX(fctx));
02567 res = fctx->res;
02568
02569 UNUSED(task);
02570
02571 FCTXTRACE("finddone");
02572
02573 bucketnum = fctx->bucketnum;
02574 LOCK(&res->buckets[bucketnum].lock);
02575
02576 INSIST(fctx->pending > 0);
02577 fctx->pending--;
02578
02579 if (ADDRWAIT(fctx)) {
02580
02581
02582
02583 INSIST(!SHUTTINGDOWN(fctx));
02584 fctx->attributes &= ~FCTX_ATTR_ADDRWAIT;
02585 if (event->ev_type == DNS_EVENT_ADBMOREADDRESSES) {
02586 want_try = ISC_TRUE;
02587 } else {
02588 fctx->findfail++;
02589 if (fctx->pending == 0) {
02590
02591
02592
02593
02594
02595 want_done = ISC_TRUE;
02596 }
02597 }
02598 } else if (SHUTTINGDOWN(fctx) && fctx->pending == 0 &&
02599 fctx->nqueries == 0 && ISC_LIST_EMPTY(fctx->validators)) {
02600
02601 if (fctx->references == 0) {
02602 bucket_empty = fctx_unlink(fctx);
02603 dodestroy = ISC_TRUE;
02604 }
02605 }
02606 UNLOCK(&res->buckets[bucketnum].lock);
02607
02608 isc_event_free(&event);
02609 dns_adb_destroyfind(&find);
02610
02611 if (want_try) {
02612 fctx_try(fctx, ISC_TRUE, ISC_FALSE);
02613 } else if (want_done) {
02614 FCTXTRACE("fetch failed in finddone(); return ISC_R_FAILURE");
02615 fctx_done(fctx, ISC_R_FAILURE, __LINE__);
02616 } else if (dodestroy) {
02617 fctx_destroy(fctx);
02618 if (bucket_empty)
02619 empty_bucket(res);
02620 }
02621 }
02622
02623
02624 static inline isc_boolean_t
02625 bad_server(fetchctx_t *fctx, isc_sockaddr_t *address) {
02626 isc_sockaddr_t *sa;
02627
02628 for (sa = ISC_LIST_HEAD(fctx->bad);
02629 sa != NULL;
02630 sa = ISC_LIST_NEXT(sa, link)) {
02631 if (isc_sockaddr_equal(sa, address))
02632 return (ISC_TRUE);
02633 }
02634
02635 return (ISC_FALSE);
02636 }
02637
02638 static inline isc_boolean_t
02639 mark_bad(fetchctx_t *fctx) {
02640 dns_adbfind_t *curr;
02641 dns_adbaddrinfo_t *addrinfo;
02642 isc_boolean_t all_bad = ISC_TRUE;
02643
02644
02645
02646
02647
02648
02649
02650
02651
02652 for (curr = ISC_LIST_HEAD(fctx->finds);
02653 curr != NULL;
02654 curr = ISC_LIST_NEXT(curr, publink)) {
02655 for (addrinfo = ISC_LIST_HEAD(curr->list);
02656 addrinfo != NULL;
02657 addrinfo = ISC_LIST_NEXT(addrinfo, publink)) {
02658 if (bad_server(fctx, &addrinfo->sockaddr))
02659 addrinfo->flags |= FCTX_ADDRINFO_MARK;
02660 else
02661 all_bad = ISC_FALSE;
02662 }
02663 }
02664
02665
02666
02667
02668 for (addrinfo = ISC_LIST_HEAD(fctx->forwaddrs);
02669 addrinfo != NULL;
02670 addrinfo = ISC_LIST_NEXT(addrinfo, publink)) {
02671 if (bad_server(fctx, &addrinfo->sockaddr))
02672 addrinfo->flags |= FCTX_ADDRINFO_MARK;
02673 else
02674 all_bad = ISC_FALSE;
02675 }
02676
02677
02678
02679
02680 for (curr = ISC_LIST_HEAD(fctx->altfinds);
02681 curr != NULL;
02682 curr = ISC_LIST_NEXT(curr, publink)) {
02683 for (addrinfo = ISC_LIST_HEAD(curr->list);
02684 addrinfo != NULL;
02685 addrinfo = ISC_LIST_NEXT(addrinfo, publink)) {
02686 if (bad_server(fctx, &addrinfo->sockaddr))
02687 addrinfo->flags |= FCTX_ADDRINFO_MARK;
02688 else
02689 all_bad = ISC_FALSE;
02690 }
02691 }
02692
02693 for (addrinfo = ISC_LIST_HEAD(fctx->altaddrs);
02694 addrinfo != NULL;
02695 addrinfo = ISC_LIST_NEXT(addrinfo, publink)) {
02696 if (bad_server(fctx, &addrinfo->sockaddr))
02697 addrinfo->flags |= FCTX_ADDRINFO_MARK;
02698 else
02699 all_bad = ISC_FALSE;
02700 }
02701
02702 return (all_bad);
02703 }
02704
02705 static void
02706 add_bad(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo, isc_result_t reason,
02707 badnstype_t badtype)
02708 {
02709 char namebuf[DNS_NAME_FORMATSIZE];
02710 char addrbuf[ISC_SOCKADDR_FORMATSIZE];
02711 char classbuf[64];
02712 char typebuf[64];
02713 char code[64];
02714 isc_buffer_t b;
02715 isc_sockaddr_t *sa;
02716 const char *spc = "";
02717 isc_sockaddr_t *address = &addrinfo->sockaddr;
02718
02719 if (reason == DNS_R_LAME)
02720 fctx->lamecount++;
02721 else {
02722 switch (badtype) {
02723 case badns_unreachable:
02724 fctx->neterr++;
02725 break;
02726 case badns_response:
02727 fctx->badresp++;
02728 break;
02729 case badns_validation:
02730 break;
02731 }
02732 }
02733
02734 if (bad_server(fctx, address)) {
02735
02736
02737
02738 return;
02739 }
02740
02741 FCTXTRACE("add_bad");
02742
02743 sa = isc_mem_get(fctx->mctx, sizeof(*sa));
02744 if (sa == NULL)
02745 return;
02746 *sa = *address;
02747 ISC_LIST_INITANDAPPEND(fctx->bad, sa, link);
02748
02749 if (reason == DNS_R_LAME)
02750 return;
02751
02752 if (reason == DNS_R_UNEXPECTEDRCODE &&
02753 fctx->rmessage->rcode == dns_rcode_servfail &&
02754 ISFORWARDER(addrinfo))
02755 return;
02756
02757 if (reason == DNS_R_UNEXPECTEDRCODE) {
02758 isc_buffer_init(&b, code, sizeof(code) - 1);
02759 dns_rcode_totext(fctx->rmessage->rcode, &b);
02760 code[isc_buffer_usedlength(&b)] = '\0';
02761 spc = " ";
02762 } else if (reason == DNS_R_UNEXPECTEDOPCODE) {
02763 isc_buffer_init(&b, code, sizeof(code) - 1);
02764 dns_opcode_totext((dns_opcode_t)fctx->rmessage->opcode, &b);
02765 code[isc_buffer_usedlength(&b)] = '\0';
02766 spc = " ";
02767 } else {
02768 code[0] = '\0';
02769 }
02770 dns_name_format(&fctx->name, namebuf, sizeof(namebuf));
02771 dns_rdatatype_format(fctx->type, typebuf, sizeof(typebuf));
02772 dns_rdataclass_format(fctx->res->rdclass, classbuf, sizeof(classbuf));
02773 isc_sockaddr_format(address, addrbuf, sizeof(addrbuf));
02774 isc_log_write(dns_lctx, DNS_LOGCATEGORY_LAME_SERVERS,
02775 DNS_LOGMODULE_RESOLVER, ISC_LOG_INFO,
02776 "%s%s%s resolving '%s/%s/%s': %s",
02777 code, spc, dns_result_totext(reason),
02778 namebuf, typebuf, classbuf, addrbuf);
02779 }
02780
02781
02782
02783
02784 static void
02785 sort_adbfind(dns_adbfind_t *find) {
02786 dns_adbaddrinfo_t *best, *curr;
02787 dns_adbaddrinfolist_t sorted;
02788
02789
02790 ISC_LIST_INIT(sorted);
02791 while (!ISC_LIST_EMPTY(find->list)) {
02792 best = ISC_LIST_HEAD(find->list);
02793 curr = ISC_LIST_NEXT(best, publink);
02794 while (curr != NULL) {
02795 if (curr->srtt < best->srtt)
02796 best = curr;
02797 curr = ISC_LIST_NEXT(curr, publink);
02798 }
02799 ISC_LIST_UNLINK(find->list, best, publink);
02800 ISC_LIST_APPEND(sorted, best, publink);
02801 }
02802 find->list = sorted;
02803 }
02804
02805
02806
02807
02808 static void
02809 sort_finds(dns_adbfindlist_t *findlist) {
02810 dns_adbfind_t *best, *curr;
02811 dns_adbfindlist_t sorted;
02812 dns_adbaddrinfo_t *addrinfo, *bestaddrinfo;
02813
02814
02815 for (curr = ISC_LIST_HEAD(*findlist);
02816 curr != NULL;
02817 curr = ISC_LIST_NEXT(curr, publink))
02818 sort_adbfind(curr);
02819
02820
02821 ISC_LIST_INIT(sorted);
02822 while (!ISC_LIST_EMPTY(*findlist)) {
02823 best = ISC_LIST_HEAD(*findlist);
02824 bestaddrinfo = ISC_LIST_HEAD(best->list);
02825 INSIST(bestaddrinfo != NULL);
02826 curr = ISC_LIST_NEXT(best, publink);
02827 while (curr != NULL) {
02828 addrinfo = ISC_LIST_HEAD(curr->list);
02829 INSIST(addrinfo != NULL);
02830 if (addrinfo->srtt < bestaddrinfo->srtt) {
02831 best = curr;
02832 bestaddrinfo = addrinfo;
02833 }
02834 curr = ISC_LIST_NEXT(curr, publink);
02835 }
02836 ISC_LIST_UNLINK(*findlist, best, publink);
02837 ISC_LIST_APPEND(sorted, best, publink);
02838 }
02839 *findlist = sorted;
02840 }
02841
02842 static void
02843 findname(fetchctx_t *fctx, dns_name_t *name, in_port_t port,
02844 unsigned int options, unsigned int flags, isc_stdtime_t now,
02845 isc_boolean_t *need_alternate)
02846 {
02847 dns_adbaddrinfo_t *ai;
02848 dns_adbfind_t *find;
02849 dns_resolver_t *res;
02850 isc_boolean_t unshared;
02851 isc_result_t result;
02852
02853 res = fctx->res;
02854 unshared = ISC_TF((fctx->options & DNS_FETCHOPT_UNSHARED) != 0);
02855
02856
02857
02858
02859
02860
02861
02862 if (dns_name_issubdomain(name, &fctx->domain))
02863 options |= DNS_ADBFIND_STARTATZONE;
02864 options |= DNS_ADBFIND_GLUEOK;
02865 options |= DNS_ADBFIND_HINTOK;
02866
02867
02868
02869
02870 find = NULL;
02871 result = dns_adb_createfind2(fctx->adb,
02872 res->buckets[fctx->bucketnum].task,
02873 fctx_finddone, fctx, name,
02874 &fctx->name, fctx->type,
02875 options, now, NULL,
02876 res->view->dstport,
02877 fctx->depth + 1, fctx->qc, &find);
02878 if (result != ISC_R_SUCCESS) {
02879 if (result == DNS_R_ALIAS) {
02880 char namebuf[DNS_NAME_FORMATSIZE];
02881
02882
02883
02884
02885 dns_adb_destroyfind(&find);
02886 fctx->adberr++;
02887 dns_name_format(name, namebuf, sizeof(namebuf));
02888 isc_log_write(dns_lctx, DNS_LOGCATEGORY_CNAME,
02889 DNS_LOGMODULE_RESOLVER, ISC_LOG_INFO,
02890 "skipping nameserver '%s' because it "
02891 "is a CNAME, while resolving '%s'",
02892 namebuf, fctx->info);
02893 }
02894 } else if (!ISC_LIST_EMPTY(find->list)) {
02895
02896
02897
02898
02899 INSIST((find->options & DNS_ADBFIND_WANTEVENT) == 0);
02900 if (flags != 0 || port != 0) {
02901 for (ai = ISC_LIST_HEAD(find->list);
02902 ai != NULL;
02903 ai = ISC_LIST_NEXT(ai, publink)) {
02904 ai->flags |= flags;
02905 if (port != 0)
02906 isc_sockaddr_setport(&ai->sockaddr,
02907 port);
02908 }
02909 }
02910 if ((flags & FCTX_ADDRINFO_FORWARDER) != 0)
02911 ISC_LIST_APPEND(fctx->altfinds, find, publink);
02912 else
02913 ISC_LIST_APPEND(fctx->finds, find, publink);
02914 } else {
02915
02916
02917
02918
02919 if ((find->options & DNS_ADBFIND_WANTEVENT) != 0) {
02920
02921
02922
02923
02924 fctx->pending++;
02925
02926
02927
02928 if (need_alternate != NULL &&
02929 !*need_alternate && unshared &&
02930 ((res->dispatches4 == NULL &&
02931 find->result_v6 != DNS_R_NXDOMAIN) ||
02932 (res->dispatches6 == NULL &&
02933 find->result_v4 != DNS_R_NXDOMAIN)))
02934 *need_alternate = ISC_TRUE;
02935 } else {
02936 if ((find->options & DNS_ADBFIND_LAMEPRUNED) != 0)
02937 fctx->lamecount++;
02938 else
02939 fctx->adberr++;
02940
02941
02942
02943
02944
02945
02946 if (need_alternate != NULL && !*need_alternate &&
02947 ((res->dispatches4 == NULL &&
02948 find->result_v6 == DNS_R_NXRRSET) ||
02949 (res->dispatches6 == NULL &&
02950 find->result_v4 == DNS_R_NXRRSET)))
02951 *need_alternate = ISC_TRUE;
02952 dns_adb_destroyfind(&find);
02953 }
02954 }
02955 }
02956
02957 static isc_boolean_t
02958 isstrictsubdomain(dns_name_t *name1, dns_name_t *name2) {
02959 int order;
02960 unsigned int nlabels;
02961 dns_namereln_t namereln;
02962
02963 namereln = dns_name_fullcompare(name1, name2, &order, &nlabels);
02964 return (ISC_TF(namereln == dns_namereln_subdomain));
02965 }
02966
02967 static isc_result_t
02968 fctx_getaddresses(fetchctx_t *fctx, isc_boolean_t badcache) {
02969 dns_rdata_t rdata = DNS_RDATA_INIT;
02970 isc_result_t result;
02971 dns_resolver_t *res;
02972 isc_stdtime_t now;
02973 unsigned int stdoptions = 0;
02974 dns_forwarder_t *fwd;
02975 dns_adbaddrinfo_t *ai;
02976 isc_boolean_t all_bad;
02977 dns_rdata_ns_t ns;
02978 isc_boolean_t need_alternate = ISC_FALSE;
02979
02980 FCTXTRACE("getaddresses");
02981
02982
02983
02984
02985 fctx->restarts++;
02986 if (fctx->restarts > 100) {
02987 FCTXTRACE("too many restarts");
02988 return (DNS_R_SERVFAIL);
02989 }
02990
02991 res = fctx->res;
02992
02993 if (fctx->depth > res->maxdepth) {
02994 isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER,
02995 DNS_LOGMODULE_RESOLVER, ISC_LOG_DEBUG(3),
02996 "too much NS indirection resolving '%s'",
02997 fctx->info);
02998 return (DNS_R_SERVFAIL);
02999 }
03000
03001
03002
03003
03004
03005 INSIST(ISC_LIST_EMPTY(fctx->forwaddrs));
03006 INSIST(ISC_LIST_EMPTY(fctx->altaddrs));
03007
03008
03009
03010
03011
03012
03013 fwd = ISC_LIST_HEAD(fctx->forwarders);
03014 if (fwd == NULL) {
03015 dns_forwarders_t *forwarders = NULL;
03016 dns_name_t *name = &fctx->name;
03017 dns_name_t suffix;
03018 unsigned int labels;
03019 dns_fixedname_t fixed;
03020 dns_name_t *domain;
03021
03022
03023
03024
03025
03026 if (dns_rdatatype_atparent(fctx->type) &&
03027 dns_name_countlabels(name) > 1) {
03028 dns_name_init(&suffix, NULL);
03029 labels = dns_name_countlabels(name);
03030 dns_name_getlabelsequence(name, 1, labels - 1, &suffix);
03031 name = &suffix;
03032 }
03033
03034 dns_fixedname_init(&fixed);
03035 domain = dns_fixedname_name(&fixed);
03036 result = dns_fwdtable_find2(fctx->res->view->fwdtable, name,
03037 domain, &forwarders);
03038 if (result == ISC_R_SUCCESS) {
03039 fwd = ISC_LIST_HEAD(forwarders->fwdrs);
03040 fctx->fwdpolicy = forwarders->fwdpolicy;
03041 if (fctx->fwdpolicy == dns_fwdpolicy_only &&
03042 isstrictsubdomain(domain, &fctx->domain)) {
03043 dns_name_free(&fctx->domain, fctx->mctx);
03044 dns_name_init(&fctx->domain, NULL);
03045 result = dns_name_dup(domain, fctx->mctx,
03046 &fctx->domain);
03047 if (result != ISC_R_SUCCESS)
03048 return (result);
03049 }
03050 }
03051 }
03052
03053 while (fwd != NULL) {
03054 if ((isc_sockaddr_pf(&fwd->addr) == AF_INET &&
03055 fctx->res->dispatches4 == NULL) ||
03056 (isc_sockaddr_pf(&fwd->addr) == AF_INET6 &&
03057 fctx->res->dispatches6 == NULL)) {
03058 fwd = ISC_LIST_NEXT(fwd, link);
03059 continue;
03060 }
03061 ai = NULL;
03062 result = dns_adb_findaddrinfo(fctx->adb, &fwd->addr, &ai, 0);
03063 if (result == ISC_R_SUCCESS) {
03064 dns_adbaddrinfo_t *cur;
03065 ai->flags |= FCTX_ADDRINFO_FORWARDER;
03066 ai->dscp = fwd->dscp;
03067 cur = ISC_LIST_HEAD(fctx->forwaddrs);
03068 while (cur != NULL && cur->srtt < ai->srtt)
03069 cur = ISC_LIST_NEXT(cur, publink);
03070 if (cur != NULL)
03071 ISC_LIST_INSERTBEFORE(fctx->forwaddrs, cur,
03072 ai, publink);
03073 else
03074 ISC_LIST_APPEND(fctx->forwaddrs, ai, publink);
03075 }
03076 fwd = ISC_LIST_NEXT(fwd, link);
03077 }
03078
03079
03080
03081
03082
03083 if (fctx->fwdpolicy == dns_fwdpolicy_only)
03084 goto out;
03085
03086
03087
03088
03089
03090 stdoptions = DNS_ADBFIND_WANTEVENT | DNS_ADBFIND_EMPTYEVENT;
03091 if (fctx->restarts == 1) {
03092
03093
03094
03095
03096
03097
03098
03099
03100
03101
03102
03103 stdoptions |= DNS_ADBFIND_AVOIDFETCHES;
03104 }
03105 if (res->dispatches4 != NULL)
03106 stdoptions |= DNS_ADBFIND_INET;
03107 if (res->dispatches6 != NULL)
03108 stdoptions |= DNS_ADBFIND_INET6;
03109
03110 if ((stdoptions & DNS_ADBFIND_ADDRESSMASK) == 0)
03111 return (DNS_R_SERVFAIL);
03112
03113 isc_stdtime_get(&now);
03114
03115 INSIST(ISC_LIST_EMPTY(fctx->finds));
03116 INSIST(ISC_LIST_EMPTY(fctx->altfinds));
03117
03118 for (result = dns_rdataset_first(&fctx->nameservers);
03119 result == ISC_R_SUCCESS;
03120 result = dns_rdataset_next(&fctx->nameservers))
03121 {
03122 dns_rdataset_current(&fctx->nameservers, &rdata);
03123
03124
03125
03126 result = dns_rdata_tostruct(&rdata, &ns, NULL);
03127 if (result != ISC_R_SUCCESS)
03128 continue;
03129
03130 findname(fctx, &ns.name, 0, stdoptions, 0, now,
03131 &need_alternate);
03132 dns_rdata_reset(&rdata);
03133 dns_rdata_freestruct(&ns);
03134 }
03135 if (result != ISC_R_NOMORE)
03136 return (result);
03137
03138
03139
03140
03141 if (need_alternate) {
03142 int family;
03143 alternate_t *a;
03144 family = (res->dispatches6 != NULL) ? AF_INET6 : AF_INET;
03145 for (a = ISC_LIST_HEAD(fctx->res->alternates);
03146 a != NULL;
03147 a = ISC_LIST_NEXT(a, link)) {
03148 if (!a->isaddress) {
03149 findname(fctx, &a->_u._n.name, a->_u._n.port,
03150 stdoptions, FCTX_ADDRINFO_FORWARDER,
03151 now, NULL);
03152 continue;
03153 }
03154 if (isc_sockaddr_pf(&a->_u.addr) != family)
03155 continue;
03156 ai = NULL;
03157 result = dns_adb_findaddrinfo(fctx->adb, &a->_u.addr,
03158 &ai, 0);
03159 if (result == ISC_R_SUCCESS) {
03160 dns_adbaddrinfo_t *cur;
03161 ai->flags |= FCTX_ADDRINFO_FORWARDER;
03162 cur = ISC_LIST_HEAD(fctx->altaddrs);
03163 while (cur != NULL && cur->srtt < ai->srtt)
03164 cur = ISC_LIST_NEXT(cur, publink);
03165 if (cur != NULL)
03166 ISC_LIST_INSERTBEFORE(fctx->altaddrs,
03167 cur, ai, publink);
03168 else
03169 ISC_LIST_APPEND(fctx->altaddrs, ai,
03170 publink);
03171 }
03172 }
03173 }
03174
03175 out:
03176
03177
03178
03179 all_bad = mark_bad(fctx);
03180
03181
03182
03183
03184 if (all_bad) {
03185
03186
03187
03188 if (fctx->pending > 0) {
03189
03190
03191
03192
03193 result = DNS_R_WAIT;
03194 } else {
03195 isc_time_t expire;
03196 isc_interval_t i;
03197
03198
03199
03200
03201
03202 FCTXTRACE("no addresses");
03203 isc_interval_set(&i, DNS_RESOLVER_BADCACHETTL(fctx), 0);
03204 result = isc_time_nowplusinterval(&expire, &i);
03205 if (badcache &&
03206 (fctx->type == dns_rdatatype_dnskey ||
03207 fctx->type == dns_rdatatype_dlv ||
03208 fctx->type == dns_rdatatype_ds) &&
03209 result == ISC_R_SUCCESS)
03210 dns_resolver_addbadcache(fctx->res,
03211 &fctx->name,
03212 fctx->type, &expire);
03213 result = ISC_R_FAILURE;
03214 }
03215 } else {
03216
03217
03218
03219
03220 sort_finds(&fctx->finds);
03221 sort_finds(&fctx->altfinds);
03222 result = ISC_R_SUCCESS;
03223 }
03224
03225 return (result);
03226 }
03227
03228 static inline void
03229 possibly_mark(fetchctx_t *fctx, dns_adbaddrinfo_t *addr) {
03230 isc_netaddr_t na;
03231 char buf[ISC_NETADDR_FORMATSIZE];
03232 isc_sockaddr_t *sa;
03233 isc_boolean_t aborted = ISC_FALSE;
03234 isc_boolean_t bogus;
03235 dns_acl_t *blackhole;
03236 isc_netaddr_t ipaddr;
03237 dns_peer_t *peer = NULL;
03238 dns_resolver_t *res;
03239 const char *msg = NULL;
03240
03241 sa = &addr->sockaddr;
03242
03243 res = fctx->res;
03244 isc_netaddr_fromsockaddr(&ipaddr, sa);
03245 blackhole = dns_dispatchmgr_getblackhole(res->dispatchmgr);
03246 (void) dns_peerlist_peerbyaddr(res->view->peers, &ipaddr, &peer);
03247
03248 if (blackhole != NULL) {
03249 int match;
03250
03251 if (dns_acl_match(&ipaddr, NULL, blackhole,
03252 &res->view->aclenv,
03253 &match, NULL) == ISC_R_SUCCESS &&
03254 match > 0)
03255 aborted = ISC_TRUE;
03256 }
03257
03258 if (peer != NULL &&
03259 dns_peer_getbogus(peer, &bogus) == ISC_R_SUCCESS &&
03260 bogus)
03261 aborted = ISC_TRUE;
03262
03263 if (!isc_log_wouldlog(dns_lctx, ISC_LOG_DEBUG(3)))
03264 return;
03265
03266 if (aborted) {
03267 addr->flags |= FCTX_ADDRINFO_MARK;
03268 msg = "ignoring blackholed / bogus server: ";
03269 } else if (isc_sockaddr_ismulticast(sa)) {
03270 addr->flags |= FCTX_ADDRINFO_MARK;
03271 msg = "ignoring multicast address: ";
03272 } else if (isc_sockaddr_isexperimental(sa)) {
03273 addr->flags |= FCTX_ADDRINFO_MARK;
03274 msg = "ignoring experimental address: ";
03275 } else if (sa->type.sa.sa_family != AF_INET6) {
03276 return;
03277 } else if (IN6_IS_ADDR_V4MAPPED(&sa->type.sin6.sin6_addr)) {
03278 addr->flags |= FCTX_ADDRINFO_MARK;
03279 msg = "ignoring IPv6 mapped IPV4 address: ";
03280 } else if (IN6_IS_ADDR_V4COMPAT(&sa->type.sin6.sin6_addr)) {
03281 addr->flags |= FCTX_ADDRINFO_MARK;
03282 msg = "ignoring IPv6 compatibility IPV4 address: ";
03283 } else
03284 return;
03285
03286 isc_netaddr_fromsockaddr(&na, sa);
03287 isc_netaddr_format(&na, buf, sizeof(buf));
03288 FCTXTRACE2(msg, buf);
03289 }
03290
03291 static inline dns_adbaddrinfo_t *
03292 fctx_nextaddress(fetchctx_t *fctx) {
03293 dns_adbfind_t *find, *start;
03294 dns_adbaddrinfo_t *addrinfo;
03295 dns_adbaddrinfo_t *faddrinfo;
03296
03297
03298
03299
03300
03301
03302
03303
03304 for (addrinfo = ISC_LIST_HEAD(fctx->forwaddrs);
03305 addrinfo != NULL;
03306 addrinfo = ISC_LIST_NEXT(addrinfo, publink)) {
03307 if (!UNMARKED(addrinfo))
03308 continue;
03309 possibly_mark(fctx, addrinfo);
03310 if (UNMARKED(addrinfo)) {
03311 addrinfo->flags |= FCTX_ADDRINFO_MARK;
03312 fctx->find = NULL;
03313 return (addrinfo);
03314 }
03315 }
03316
03317
03318
03319
03320
03321 fctx->attributes |= FCTX_ATTR_TRIEDFIND;
03322
03323 find = fctx->find;
03324 if (find == NULL)
03325 find = ISC_LIST_HEAD(fctx->finds);
03326 else {
03327 find = ISC_LIST_NEXT(find, publink);
03328 if (find == NULL)
03329 find = ISC_LIST_HEAD(fctx->finds);
03330 }
03331
03332
03333
03334
03335 addrinfo = NULL;
03336 if (find != NULL) {
03337 start = find;
03338 do {
03339 for (addrinfo = ISC_LIST_HEAD(find->list);
03340 addrinfo != NULL;
03341 addrinfo = ISC_LIST_NEXT(addrinfo, publink)) {
03342 if (!UNMARKED(addrinfo))
03343 continue;
03344 possibly_mark(fctx, addrinfo);
03345 if (UNMARKED(addrinfo)) {
03346 addrinfo->flags |= FCTX_ADDRINFO_MARK;
03347 break;
03348 }
03349 }
03350 if (addrinfo != NULL)
03351 break;
03352 find = ISC_LIST_NEXT(find, publink);
03353 if (find == NULL)
03354 find = ISC_LIST_HEAD(fctx->finds);
03355 } while (find != start);
03356 }
03357
03358 fctx->find = find;
03359 if (addrinfo != NULL)
03360 return (addrinfo);
03361
03362
03363
03364
03365
03366 fctx->attributes |= FCTX_ATTR_TRIEDALT;
03367
03368 find = fctx->altfind;
03369 if (find == NULL)
03370 find = ISC_LIST_HEAD(fctx->altfinds);
03371 else {
03372 find = ISC_LIST_NEXT(find, publink);
03373 if (find == NULL)
03374 find = ISC_LIST_HEAD(fctx->altfinds);
03375 }
03376
03377
03378
03379
03380 addrinfo = NULL;
03381 if (find != NULL) {
03382 start = find;
03383 do {
03384 for (addrinfo = ISC_LIST_HEAD(find->list);
03385 addrinfo != NULL;
03386 addrinfo = ISC_LIST_NEXT(addrinfo, publink)) {
03387 if (!UNMARKED(addrinfo))
03388 continue;
03389 possibly_mark(fctx, addrinfo);
03390 if (UNMARKED(addrinfo)) {
03391 addrinfo->flags |= FCTX_ADDRINFO_MARK;
03392 break;
03393 }
03394 }
03395 if (addrinfo != NULL)
03396 break;
03397 find = ISC_LIST_NEXT(find, publink);
03398 if (find == NULL)
03399 find = ISC_LIST_HEAD(fctx->altfinds);
03400 } while (find != start);
03401 }
03402
03403 faddrinfo = addrinfo;
03404
03405
03406
03407
03408
03409 for (addrinfo = ISC_LIST_HEAD(fctx->altaddrs);
03410 addrinfo != NULL;
03411 addrinfo = ISC_LIST_NEXT(addrinfo, publink)) {
03412 if (!UNMARKED(addrinfo))
03413 continue;
03414 possibly_mark(fctx, addrinfo);
03415 if (UNMARKED(addrinfo) &&
03416 (faddrinfo == NULL ||
03417 addrinfo->srtt < faddrinfo->srtt)) {
03418 if (faddrinfo != NULL)
03419 faddrinfo->flags &= ~FCTX_ADDRINFO_MARK;
03420 addrinfo->flags |= FCTX_ADDRINFO_MARK;
03421 break;
03422 }
03423 }
03424
03425 if (addrinfo == NULL) {
03426 addrinfo = faddrinfo;
03427 fctx->altfind = find;
03428 }
03429
03430 return (addrinfo);
03431 }
03432
03433 static void
03434 fctx_try(fetchctx_t *fctx, isc_boolean_t retrying, isc_boolean_t badcache) {
03435 isc_result_t result;
03436 dns_adbaddrinfo_t *addrinfo;
03437
03438 FCTXTRACE("try");
03439
03440 REQUIRE(!ADDRWAIT(fctx));
03441
03442
03443 if (isc_counter_used(fctx->qc) > fctx->res->maxqueries) {
03444 isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER,
03445 DNS_LOGMODULE_RESOLVER, ISC_LOG_DEBUG(3),
03446 "exceeded max queries resolving '%s'",
03447 fctx->info);
03448 fctx_done(fctx, DNS_R_SERVFAIL, __LINE__);
03449 return;
03450 }
03451
03452 addrinfo = fctx_nextaddress(fctx);
03453 if (addrinfo == NULL) {
03454
03455
03456
03457 fctx_cancelqueries(fctx, ISC_TRUE);
03458 fctx_cleanupfinds(fctx);
03459 fctx_cleanupaltfinds(fctx);
03460 fctx_cleanupforwaddrs(fctx);
03461 fctx_cleanupaltaddrs(fctx);
03462 result = fctx_getaddresses(fctx, badcache);
03463 if (result == DNS_R_WAIT) {
03464
03465
03466
03467 FCTXTRACE("addrwait");
03468 fctx->attributes |= FCTX_ATTR_ADDRWAIT;
03469 return;
03470 } else if (result != ISC_R_SUCCESS) {
03471
03472
03473
03474 fctx_done(fctx, result, __LINE__);
03475 return;
03476 }
03477
03478 addrinfo = fctx_nextaddress(fctx);
03479
03480
03481
03482
03483 if (addrinfo == NULL) {
03484 fctx_done(fctx, DNS_R_SERVFAIL, __LINE__);
03485 return;
03486 }
03487 }
03488
03489 if (dns_name_countlabels(&fctx->domain) > 2) {
03490 result = isc_counter_increment(fctx->qc);
03491 if (result != ISC_R_SUCCESS) {
03492 isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER,
03493 DNS_LOGMODULE_RESOLVER, ISC_LOG_DEBUG(3),
03494 "exceeded max queries resolving '%s'",
03495 fctx->info);
03496 fctx_done(fctx, DNS_R_SERVFAIL, __LINE__);
03497 return;
03498 }
03499 }
03500
03501 result = fctx_query(fctx, addrinfo, fctx->options);
03502 if (result != ISC_R_SUCCESS)
03503 fctx_done(fctx, result, __LINE__);
03504 else if (retrying)
03505 inc_stats(fctx->res, dns_resstatscounter_retry);
03506 }
03507
03508 static isc_boolean_t
03509 fctx_unlink(fetchctx_t *fctx) {
03510 dns_resolver_t *res;
03511 unsigned int bucketnum;
03512
03513
03514
03515
03516
03517 REQUIRE(VALID_FCTX(fctx));
03518 REQUIRE(fctx->state == fetchstate_done ||
03519 fctx->state == fetchstate_init);
03520 REQUIRE(ISC_LIST_EMPTY(fctx->events));
03521 REQUIRE(ISC_LIST_EMPTY(fctx->queries));
03522 REQUIRE(ISC_LIST_EMPTY(fctx->finds));
03523 REQUIRE(ISC_LIST_EMPTY(fctx->altfinds));
03524 REQUIRE(fctx->pending == 0);
03525 REQUIRE(fctx->references == 0);
03526 REQUIRE(ISC_LIST_EMPTY(fctx->validators));
03527
03528 FCTXTRACE("unlink");
03529
03530 res = fctx->res;
03531 bucketnum = fctx->bucketnum;
03532
03533 ISC_LIST_UNLINK(res->buckets[bucketnum].fctxs, fctx, link);
03534
03535 LOCK(&res->nlock);
03536 res->nfctx--;
03537 UNLOCK(&res->nlock);
03538 dec_stats(res, dns_resstatscounter_nfetch);
03539
03540 if (res->buckets[bucketnum].exiting &&
03541 ISC_LIST_EMPTY(res->buckets[bucketnum].fctxs))
03542 return (ISC_TRUE);
03543
03544 return (ISC_FALSE);
03545 }
03546
03547 static void
03548 fctx_destroy(fetchctx_t *fctx) {
03549 isc_sockaddr_t *sa, *next_sa;
03550 struct tried *tried;
03551
03552 REQUIRE(VALID_FCTX(fctx));
03553 REQUIRE(fctx->state == fetchstate_done ||
03554 fctx->state == fetchstate_init);
03555 REQUIRE(ISC_LIST_EMPTY(fctx->events));
03556 REQUIRE(ISC_LIST_EMPTY(fctx->queries));
03557 REQUIRE(ISC_LIST_EMPTY(fctx->finds));
03558 REQUIRE(ISC_LIST_EMPTY(fctx->altfinds));
03559 REQUIRE(fctx->pending == 0);
03560 REQUIRE(fctx->references == 0);
03561 REQUIRE(ISC_LIST_EMPTY(fctx->validators));
03562 REQUIRE(!ISC_LINK_LINKED(fctx, link));
03563
03564 FCTXTRACE("destroy");
03565
03566
03567
03568
03569 for (sa = ISC_LIST_HEAD(fctx->bad);
03570 sa != NULL;
03571 sa = next_sa) {
03572 next_sa = ISC_LIST_NEXT(sa, link);
03573 ISC_LIST_UNLINK(fctx->bad, sa, link);
03574 isc_mem_put(fctx->mctx, sa, sizeof(*sa));
03575 }
03576
03577 for (tried = ISC_LIST_HEAD(fctx->edns);
03578 tried != NULL;
03579 tried = ISC_LIST_HEAD(fctx->edns)) {
03580 ISC_LIST_UNLINK(fctx->edns, tried, link);
03581 isc_mem_put(fctx->mctx, tried, sizeof(*tried));
03582 }
03583
03584 for (tried = ISC_LIST_HEAD(fctx->edns512);
03585 tried != NULL;
03586 tried = ISC_LIST_HEAD(fctx->edns512)) {
03587 ISC_LIST_UNLINK(fctx->edns512, tried, link);
03588 isc_mem_put(fctx->mctx, tried, sizeof(*tried));
03589 }
03590
03591 for (sa = ISC_LIST_HEAD(fctx->bad_edns);
03592 sa != NULL;
03593 sa = next_sa) {
03594 next_sa = ISC_LIST_NEXT(sa, link);
03595 ISC_LIST_UNLINK(fctx->bad_edns, sa, link);
03596 isc_mem_put(fctx->mctx, sa, sizeof(*sa));
03597 }
03598
03599 isc_counter_detach(&fctx->qc);
03600 isc_timer_detach(&fctx->timer);
03601 dns_message_destroy(&fctx->rmessage);
03602 dns_message_destroy(&fctx->qmessage);
03603 if (dns_name_countlabels(&fctx->domain) > 0)
03604 dns_name_free(&fctx->domain, fctx->mctx);
03605 if (dns_rdataset_isassociated(&fctx->nameservers))
03606 dns_rdataset_disassociate(&fctx->nameservers);
03607 dns_name_free(&fctx->name, fctx->mctx);
03608 dns_db_detach(&fctx->cache);
03609 dns_adb_detach(&fctx->adb);
03610 isc_mem_free(fctx->mctx, fctx->info);
03611 isc_mem_putanddetach(&fctx->mctx, fctx, sizeof(*fctx));
03612 }
03613
03614
03615
03616
03617
03618 static void
03619 fctx_timeout(isc_task_t *task, isc_event_t *event) {
03620 fetchctx_t *fctx = event->ev_arg;
03621 isc_timerevent_t *tevent = (isc_timerevent_t *)event;
03622 resquery_t *query;
03623
03624 REQUIRE(VALID_FCTX(fctx));
03625
03626 UNUSED(task);
03627
03628 FCTXTRACE("timeout");
03629
03630 inc_stats(fctx->res, dns_resstatscounter_querytimeout);
03631
03632 if (event->ev_type == ISC_TIMEREVENT_LIFE) {
03633 fctx->reason = NULL;
03634 fctx_done(fctx, ISC_R_TIMEDOUT, __LINE__);
03635 } else {
03636 isc_result_t result;
03637
03638 fctx->timeouts++;
03639 fctx->timeout = ISC_TRUE;
03640
03641
03642
03643
03644
03645
03646
03647
03648
03649
03650 query = ISC_LIST_HEAD(fctx->queries);
03651 if (query != NULL &&
03652 isc_time_compare(&tevent->due, &query->start) >= 0)
03653 {
03654 FCTXTRACE("query timed out; no response");
03655 fctx_cancelquery(&query, NULL, NULL, ISC_TRUE);
03656 }
03657 fctx->attributes &= ~FCTX_ATTR_ADDRWAIT;
03658
03659
03660
03661
03662
03663 result = fctx_starttimer(fctx);
03664 if (result != ISC_R_SUCCESS)
03665 fctx_done(fctx, result, __LINE__);
03666 else
03667
03668
03669
03670 fctx_try(fctx, ISC_TRUE, ISC_FALSE);
03671 }
03672
03673 isc_event_free(&event);
03674 }
03675
03676 static void
03677 fctx_shutdown(fetchctx_t *fctx) {
03678 isc_event_t *cevent;
03679
03680
03681
03682
03683
03684 FCTXTRACE("shutdown");
03685
03686
03687
03688
03689
03690 if (fctx->want_shutdown)
03691 return;
03692
03693 fctx->want_shutdown = ISC_TRUE;
03694
03695
03696
03697
03698
03699
03700
03701 if (fctx->state != fetchstate_init) {
03702 cevent = &fctx->control_event;
03703 isc_task_send(fctx->res->buckets[fctx->bucketnum].task,
03704 &cevent);
03705 }
03706 }
03707
03708 static void
03709 fctx_doshutdown(isc_task_t *task, isc_event_t *event) {
03710 fetchctx_t *fctx = event->ev_arg;
03711 isc_boolean_t bucket_empty = ISC_FALSE;
03712 dns_resolver_t *res;
03713 unsigned int bucketnum;
03714 dns_validator_t *validator;
03715 isc_boolean_t dodestroy = ISC_FALSE;
03716
03717 REQUIRE(VALID_FCTX(fctx));
03718
03719 UNUSED(task);
03720
03721 res = fctx->res;
03722 bucketnum = fctx->bucketnum;
03723
03724 FCTXTRACE("doshutdown");
03725
03726
03727
03728
03729 fctx->attributes &= ~FCTX_ATTR_ADDRWAIT;
03730
03731
03732
03733
03734
03735 validator = ISC_LIST_HEAD(fctx->validators);
03736 while (validator != NULL) {
03737 dns_validator_cancel(validator);
03738 validator = ISC_LIST_NEXT(validator, link);
03739 }
03740
03741 if (fctx->nsfetch != NULL)
03742 dns_resolver_cancelfetch(fctx->nsfetch);
03743
03744
03745
03746
03747
03748
03749 fctx_stopeverything(fctx, ISC_FALSE);
03750
03751 LOCK(&res->buckets[bucketnum].lock);
03752
03753 fctx->attributes |= FCTX_ATTR_SHUTTINGDOWN;
03754
03755 INSIST(fctx->state == fetchstate_active ||
03756 fctx->state == fetchstate_done);
03757 INSIST(fctx->want_shutdown);
03758
03759 if (fctx->state != fetchstate_done) {
03760 fctx->state = fetchstate_done;
03761 fctx_sendevents(fctx, ISC_R_CANCELED, __LINE__);
03762 }
03763
03764 if (fctx->references == 0 && fctx->pending == 0 &&
03765 fctx->nqueries == 0 && ISC_LIST_EMPTY(fctx->validators)) {
03766 bucket_empty = fctx_unlink(fctx);
03767 dodestroy = ISC_TRUE;
03768 }
03769
03770 UNLOCK(&res->buckets[bucketnum].lock);
03771
03772 if (dodestroy) {
03773 fctx_destroy(fctx);
03774 if (bucket_empty)
03775 empty_bucket(res);
03776 }
03777 }
03778
03779 static void
03780 fctx_start(isc_task_t *task, isc_event_t *event) {
03781 fetchctx_t *fctx = event->ev_arg;
03782 isc_boolean_t done = ISC_FALSE, bucket_empty = ISC_FALSE;
03783 dns_resolver_t *res;
03784 unsigned int bucketnum;
03785 isc_boolean_t dodestroy = ISC_FALSE;
03786
03787 REQUIRE(VALID_FCTX(fctx));
03788
03789 UNUSED(task);
03790
03791 res = fctx->res;
03792 bucketnum = fctx->bucketnum;
03793
03794 FCTXTRACE("start");
03795
03796 LOCK(&res->buckets[bucketnum].lock);
03797
03798 INSIST(fctx->state == fetchstate_init);
03799 if (fctx->want_shutdown) {
03800
03801
03802
03803
03804 fctx->attributes |= FCTX_ATTR_SHUTTINGDOWN;
03805 fctx->state = fetchstate_done;
03806 fctx_sendevents(fctx, ISC_R_CANCELED, __LINE__);
03807
03808
03809
03810
03811 INSIST(fctx->pending == 0);
03812 INSIST(fctx->nqueries == 0);
03813 INSIST(ISC_LIST_EMPTY(fctx->validators));
03814 if (fctx->references == 0) {
03815
03816
03817
03818 bucket_empty = fctx_unlink(fctx);
03819 dodestroy = ISC_TRUE;
03820 }
03821 done = ISC_TRUE;
03822 } else {
03823
03824
03825
03826 fctx->state = fetchstate_active;
03827
03828
03829
03830
03831 ISC_EVENT_INIT(event, sizeof(*event), 0, NULL,
03832 DNS_EVENT_FETCHCONTROL, fctx_doshutdown, fctx,
03833 NULL, NULL, NULL);
03834 }
03835
03836 UNLOCK(&res->buckets[bucketnum].lock);
03837
03838 if (!done) {
03839 isc_result_t result;
03840
03841 INSIST(!dodestroy);
03842
03843
03844
03845
03846 result = fctx_starttimer(fctx);
03847 if (result != ISC_R_SUCCESS)
03848 fctx_done(fctx, result, __LINE__);
03849 else
03850 fctx_try(fctx, ISC_FALSE, ISC_FALSE);
03851 } else if (dodestroy) {
03852 fctx_destroy(fctx);
03853 if (bucket_empty)
03854 empty_bucket(res);
03855 }
03856 }
03857
03858
03859
03860
03861
03862 static inline isc_result_t
03863 fctx_join(fetchctx_t *fctx, isc_task_t *task, isc_sockaddr_t *client,
03864 dns_messageid_t id, isc_taskaction_t action, void *arg,
03865 dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset,
03866 dns_fetch_t *fetch)
03867 {
03868 isc_task_t *clone;
03869 dns_fetchevent_t *event;
03870
03871 FCTXTRACE("join");
03872
03873
03874
03875
03876
03877
03878 clone = NULL;
03879 isc_task_attach(task, &clone);
03880 event = (dns_fetchevent_t *)
03881 isc_event_allocate(fctx->res->mctx, clone, DNS_EVENT_FETCHDONE,
03882 action, arg, sizeof(*event));
03883 if (event == NULL) {
03884 isc_task_detach(&clone);
03885 return (ISC_R_NOMEMORY);
03886 }
03887 event->result = DNS_R_SERVFAIL;
03888 event->qtype = fctx->type;
03889 event->db = NULL;
03890 event->node = NULL;
03891 event->rdataset = rdataset;
03892 event->sigrdataset = sigrdataset;
03893 event->fetch = fetch;
03894 event->client = client;
03895 event->id = id;
03896 dns_fixedname_init(&event->foundname);
03897
03898
03899
03900
03901
03902 if (event->sigrdataset != NULL)
03903 ISC_LIST_PREPEND(fctx->events, event, ev_link);
03904 else
03905 ISC_LIST_APPEND(fctx->events, event, ev_link);
03906 fctx->references++;
03907 fctx->client = client;
03908
03909 fetch->magic = DNS_FETCH_MAGIC;
03910 fetch->private = fctx;
03911
03912 return (ISC_R_SUCCESS);
03913 }
03914
03915 static inline void
03916 log_ns_ttl(fetchctx_t *fctx, const char *where) {
03917 char namebuf[DNS_NAME_FORMATSIZE];
03918 char domainbuf[DNS_NAME_FORMATSIZE];
03919
03920 dns_name_format(&fctx->name, namebuf, sizeof(namebuf));
03921 dns_name_format(&fctx->domain, domainbuf, sizeof(domainbuf));
03922 isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER,
03923 DNS_LOGMODULE_RESOLVER, ISC_LOG_DEBUG(10),
03924 "log_ns_ttl: fctx %p: %s: %s (in '%s'?): %u %u",
03925 fctx, where, namebuf, domainbuf,
03926 fctx->ns_ttl_ok, fctx->ns_ttl);
03927 }
03928
03929 static isc_result_t
03930 fctx_create(dns_resolver_t *res, dns_name_t *name, dns_rdatatype_t type,
03931 dns_name_t *domain, dns_rdataset_t *nameservers,
03932 unsigned int options, unsigned int bucketnum, unsigned int depth,
03933 isc_counter_t *qc, fetchctx_t **fctxp)
03934 {
03935 fetchctx_t *fctx;
03936 isc_result_t result;
03937 isc_result_t iresult;
03938 isc_interval_t interval;
03939 dns_fixedname_t fixed;
03940 unsigned int findoptions = 0;
03941 char buf[DNS_NAME_FORMATSIZE + DNS_RDATATYPE_FORMATSIZE];
03942 char typebuf[DNS_RDATATYPE_FORMATSIZE];
03943 isc_mem_t *mctx;
03944
03945
03946
03947
03948 REQUIRE(fctxp != NULL && *fctxp == NULL);
03949
03950 mctx = res->buckets[bucketnum].mctx;
03951 fctx = isc_mem_get(mctx, sizeof(*fctx));
03952 if (fctx == NULL)
03953 return (ISC_R_NOMEMORY);
03954
03955 fctx->qc = NULL;
03956 if (qc != NULL) {
03957 isc_counter_attach(qc, &fctx->qc);
03958 } else {
03959 result = isc_counter_create(res->mctx,
03960 res->maxqueries, &fctx->qc);
03961 if (result != ISC_R_SUCCESS)
03962 goto cleanup_fetch;
03963 }
03964
03965
03966
03967
03968
03969 dns_name_format(name, buf, sizeof(buf));
03970 dns_rdatatype_format(type, typebuf, sizeof(typebuf));
03971 strcat(buf, "/");
03972 strcat(buf, typebuf);
03973 fctx->info = isc_mem_strdup(mctx, buf);
03974 if (fctx->info == NULL) {
03975 result = ISC_R_NOMEMORY;
03976 goto cleanup_counter;
03977 }
03978
03979 FCTXTRACE("create");
03980 dns_name_init(&fctx->name, NULL);
03981 result = dns_name_dup(name, mctx, &fctx->name);
03982 if (result != ISC_R_SUCCESS)
03983 goto cleanup_info;
03984 dns_name_init(&fctx->domain, NULL);
03985 dns_rdataset_init(&fctx->nameservers);
03986
03987 fctx->type = type;
03988 fctx->options = options;
03989
03990
03991
03992
03993
03994 fctx->res = res;
03995 fctx->references = 0;
03996 fctx->bucketnum = bucketnum;
03997 fctx->state = fetchstate_init;
03998 fctx->want_shutdown = ISC_FALSE;
03999 fctx->cloned = ISC_FALSE;
04000 fctx->depth = depth;
04001 ISC_LIST_INIT(fctx->queries);
04002 ISC_LIST_INIT(fctx->finds);
04003 ISC_LIST_INIT(fctx->altfinds);
04004 ISC_LIST_INIT(fctx->forwaddrs);
04005 ISC_LIST_INIT(fctx->altaddrs);
04006 ISC_LIST_INIT(fctx->forwarders);
04007 fctx->fwdpolicy = dns_fwdpolicy_none;
04008 ISC_LIST_INIT(fctx->bad);
04009 ISC_LIST_INIT(fctx->edns);
04010 ISC_LIST_INIT(fctx->edns512);
04011 ISC_LIST_INIT(fctx->bad_edns);
04012 ISC_LIST_INIT(fctx->validators);
04013 fctx->validator = NULL;
04014 fctx->find = NULL;
04015 fctx->altfind = NULL;
04016 fctx->pending = 0;
04017 fctx->restarts = 0;
04018 fctx->querysent = 0;
04019 fctx->referrals = 0;
04020 TIME_NOW(&fctx->start);
04021 fctx->timeouts = 0;
04022 fctx->lamecount = 0;
04023 fctx->adberr = 0;
04024 fctx->neterr = 0;
04025 fctx->badresp = 0;
04026 fctx->findfail = 0;
04027 fctx->valfail = 0;
04028 fctx->result = ISC_R_FAILURE;
04029 fctx->vresult = ISC_R_SUCCESS;
04030 fctx->exitline = -1;
04031 fctx->logged = ISC_FALSE;
04032 fctx->attributes = 0;
04033 fctx->spilled = ISC_FALSE;
04034 fctx->nqueries = 0;
04035 fctx->reason = NULL;
04036 fctx->rand_buf = 0;
04037 fctx->rand_bits = 0;
04038 fctx->timeout = ISC_FALSE;
04039 fctx->addrinfo = NULL;
04040 fctx->client = NULL;
04041 fctx->ns_ttl = 0;
04042 fctx->ns_ttl_ok = ISC_FALSE;
04043
04044 dns_name_init(&fctx->nsname, NULL);
04045 fctx->nsfetch = NULL;
04046 dns_rdataset_init(&fctx->nsrrset);
04047
04048 if (domain == NULL) {
04049 dns_forwarders_t *forwarders = NULL;
04050 unsigned int labels;
04051 dns_name_t *fwdname = name;
04052 dns_name_t suffix;
04053
04054
04055
04056
04057
04058
04059 if (dns_rdatatype_atparent(fctx->type) &&
04060 dns_name_countlabels(name) > 1) {
04061 dns_name_init(&suffix, NULL);
04062 labels = dns_name_countlabels(name);
04063 dns_name_getlabelsequence(name, 1, labels - 1, &suffix);
04064 fwdname = &suffix;
04065 }
04066
04067
04068 dns_fixedname_init(&fixed);
04069 domain = dns_fixedname_name(&fixed);
04070 result = dns_fwdtable_find2(fctx->res->view->fwdtable, fwdname,
04071 domain, &forwarders);
04072 if (result == ISC_R_SUCCESS)
04073 fctx->fwdpolicy = forwarders->fwdpolicy;
04074
04075 if (fctx->fwdpolicy != dns_fwdpolicy_only) {
04076
04077
04078
04079
04080
04081 if (dns_rdatatype_atparent(fctx->type))
04082 findoptions |= DNS_DBFIND_NOEXACT;
04083 result = dns_view_findzonecut(res->view, name,
04084 domain, 0, findoptions,
04085 ISC_TRUE,
04086 &fctx->nameservers,
04087 NULL);
04088 if (result != ISC_R_SUCCESS)
04089 goto cleanup_name;
04090
04091 result = dns_name_dup(domain, mctx, &fctx->domain);
04092 if (result != ISC_R_SUCCESS) {
04093 dns_rdataset_disassociate(&fctx->nameservers);
04094 goto cleanup_name;
04095 }
04096 fctx->ns_ttl = fctx->nameservers.ttl;
04097 fctx->ns_ttl_ok = ISC_TRUE;
04098 } else {
04099
04100
04101
04102 result = dns_name_dup(domain, mctx, &fctx->domain);
04103 if (result != ISC_R_SUCCESS)
04104 goto cleanup_name;
04105 }
04106 } else {
04107 result = dns_name_dup(domain, mctx, &fctx->domain);
04108 if (result != ISC_R_SUCCESS)
04109 goto cleanup_name;
04110 dns_rdataset_clone(nameservers, &fctx->nameservers);
04111 fctx->ns_ttl = fctx->nameservers.ttl;
04112 fctx->ns_ttl_ok = ISC_TRUE;
04113 }
04114
04115 log_ns_ttl(fctx, "fctx_create");
04116
04117 INSIST(dns_name_issubdomain(&fctx->name, &fctx->domain));
04118
04119 fctx->qmessage = NULL;
04120 result = dns_message_create(mctx, DNS_MESSAGE_INTENTRENDER,
04121 &fctx->qmessage);
04122
04123 if (result != ISC_R_SUCCESS)
04124 goto cleanup_domain;
04125
04126 fctx->rmessage = NULL;
04127 result = dns_message_create(mctx, DNS_MESSAGE_INTENTPARSE,
04128 &fctx->rmessage);
04129
04130 if (result != ISC_R_SUCCESS)
04131 goto cleanup_qmessage;
04132
04133
04134
04135
04136 isc_interval_set(&interval, res->query_timeout, 0);
04137 iresult = isc_time_nowplusinterval(&fctx->expires, &interval);
04138 if (iresult != ISC_R_SUCCESS) {
04139 UNEXPECTED_ERROR(__FILE__, __LINE__,
04140 "isc_time_nowplusinterval: %s",
04141 isc_result_totext(iresult));
04142 result = ISC_R_UNEXPECTED;
04143 goto cleanup_rmessage;
04144 }
04145
04146
04147
04148
04149
04150
04151 isc_interval_set(&fctx->interval, 2, 0);
04152
04153
04154
04155
04156
04157 fctx->timer = NULL;
04158 iresult = isc_timer_create(res->timermgr, isc_timertype_inactive,
04159 NULL, NULL,
04160 res->buckets[bucketnum].task, fctx_timeout,
04161 fctx, &fctx->timer);
04162 if (iresult != ISC_R_SUCCESS) {
04163 UNEXPECTED_ERROR(__FILE__, __LINE__,
04164 "isc_timer_create: %s",
04165 isc_result_totext(iresult));
04166 result = ISC_R_UNEXPECTED;
04167 goto cleanup_rmessage;
04168 }
04169
04170
04171
04172
04173 fctx->cache = NULL;
04174 dns_db_attach(res->view->cachedb, &fctx->cache);
04175 fctx->adb = NULL;
04176 dns_adb_attach(res->view->adb, &fctx->adb);
04177 fctx->mctx = NULL;
04178 isc_mem_attach(mctx, &fctx->mctx);
04179
04180 ISC_LIST_INIT(fctx->events);
04181 ISC_LINK_INIT(fctx, link);
04182 fctx->magic = FCTX_MAGIC;
04183
04184 ISC_LIST_APPEND(res->buckets[bucketnum].fctxs, fctx, link);
04185
04186 LOCK(&res->nlock);
04187 res->nfctx++;
04188 UNLOCK(&res->nlock);
04189 inc_stats(res, dns_resstatscounter_nfetch);
04190
04191 *fctxp = fctx;
04192
04193 return (ISC_R_SUCCESS);
04194
04195 cleanup_rmessage:
04196 dns_message_destroy(&fctx->rmessage);
04197
04198 cleanup_qmessage:
04199 dns_message_destroy(&fctx->qmessage);
04200
04201 cleanup_domain:
04202 if (dns_name_countlabels(&fctx->domain) > 0)
04203 dns_name_free(&fctx->domain, mctx);
04204 if (dns_rdataset_isassociated(&fctx->nameservers))
04205 dns_rdataset_disassociate(&fctx->nameservers);
04206
04207 cleanup_name:
04208 dns_name_free(&fctx->name, mctx);
04209
04210 cleanup_info:
04211 isc_mem_free(mctx, fctx->info);
04212
04213 cleanup_counter:
04214 isc_counter_detach(&fctx->qc);
04215
04216 cleanup_fetch:
04217 isc_mem_put(mctx, fctx, sizeof(*fctx));
04218
04219 return (result);
04220 }
04221
04222
04223
04224
04225 static inline isc_boolean_t
04226 is_lame(fetchctx_t *fctx) {
04227 dns_message_t *message = fctx->rmessage;
04228 dns_name_t *name;
04229 dns_rdataset_t *rdataset;
04230 isc_result_t result;
04231
04232 if (message->rcode != dns_rcode_noerror &&
04233 message->rcode != dns_rcode_nxdomain)
04234 return (ISC_FALSE);
04235
04236 if (message->counts[DNS_SECTION_ANSWER] != 0)
04237 return (ISC_FALSE);
04238
04239 if (message->counts[DNS_SECTION_AUTHORITY] == 0)
04240 return (ISC_FALSE);
04241
04242 result = dns_message_firstname(message, DNS_SECTION_AUTHORITY);
04243 while (result == ISC_R_SUCCESS) {
04244 name = NULL;
04245 dns_message_currentname(message, DNS_SECTION_AUTHORITY, &name);
04246 for (rdataset = ISC_LIST_HEAD(name->list);
04247 rdataset != NULL;
04248 rdataset = ISC_LIST_NEXT(rdataset, link)) {
04249 dns_namereln_t namereln;
04250 int order;
04251 unsigned int labels;
04252 if (rdataset->type != dns_rdatatype_ns)
04253 continue;
04254 namereln = dns_name_fullcompare(name, &fctx->domain,
04255 &order, &labels);
04256 if (namereln == dns_namereln_equal &&
04257 (message->flags & DNS_MESSAGEFLAG_AA) != 0)
04258 return (ISC_FALSE);
04259 if (namereln == dns_namereln_subdomain)
04260 return (ISC_FALSE);
04261 return (ISC_TRUE);
04262 }
04263 result = dns_message_nextname(message, DNS_SECTION_AUTHORITY);
04264 }
04265
04266 return (ISC_FALSE);
04267 }
04268
04269 static inline void
04270 log_lame(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo) {
04271 char namebuf[DNS_NAME_FORMATSIZE];
04272 char domainbuf[DNS_NAME_FORMATSIZE];
04273 char addrbuf[ISC_SOCKADDR_FORMATSIZE];
04274
04275 dns_name_format(&fctx->name, namebuf, sizeof(namebuf));
04276 dns_name_format(&fctx->domain, domainbuf, sizeof(domainbuf));
04277 isc_sockaddr_format(&addrinfo->sockaddr, addrbuf, sizeof(addrbuf));
04278 isc_log_write(dns_lctx, DNS_LOGCATEGORY_LAME_SERVERS,
04279 DNS_LOGMODULE_RESOLVER, ISC_LOG_INFO,
04280 "lame server resolving '%s' (in '%s'?): %s",
04281 namebuf, domainbuf, addrbuf);
04282 }
04283
04284 static inline void
04285 log_formerr(fetchctx_t *fctx, const char *format, ...) {
04286 char nsbuf[ISC_SOCKADDR_FORMATSIZE];
04287 char clbuf[ISC_SOCKADDR_FORMATSIZE];
04288 const char *clmsg = "";
04289 char msgbuf[2048];
04290 va_list args;
04291
04292 va_start(args, format);
04293 vsnprintf(msgbuf, sizeof(msgbuf), format, args);
04294 va_end(args);
04295
04296 isc_sockaddr_format(&fctx->addrinfo->sockaddr, nsbuf, sizeof(nsbuf));
04297
04298 if (fctx->client != NULL) {
04299 clmsg = " for client ";
04300 isc_sockaddr_format(fctx->client, clbuf, sizeof(clbuf));
04301 } else {
04302 clbuf[0] = '\0';
04303 }
04304
04305 isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER,
04306 DNS_LOGMODULE_RESOLVER, ISC_LOG_NOTICE,
04307 "DNS format error from %s resolving %s%s%s: %s",
04308 nsbuf, fctx->info, clmsg, clbuf, msgbuf);
04309 }
04310
04311 static inline isc_result_t
04312 same_question(fetchctx_t *fctx) {
04313 isc_result_t result;
04314 dns_message_t *message = fctx->rmessage;
04315 dns_name_t *name;
04316 dns_rdataset_t *rdataset;
04317
04318
04319
04320
04321
04322
04323
04324
04325 if (message->counts[DNS_SECTION_QUESTION] != 1) {
04326 log_formerr(fctx, "too many questions");
04327 return (DNS_R_FORMERR);
04328 }
04329
04330 result = dns_message_firstname(message, DNS_SECTION_QUESTION);
04331 if (result != ISC_R_SUCCESS)
04332 return (result);
04333 name = NULL;
04334 dns_message_currentname(message, DNS_SECTION_QUESTION, &name);
04335 rdataset = ISC_LIST_HEAD(name->list);
04336 INSIST(rdataset != NULL);
04337 INSIST(ISC_LIST_NEXT(rdataset, link) == NULL);
04338
04339 if (fctx->type != rdataset->type ||
04340 fctx->res->rdclass != rdataset->rdclass ||
04341 !dns_name_equal(&fctx->name, name)) {
04342 char namebuf[DNS_NAME_FORMATSIZE];
04343 char class[DNS_RDATACLASS_FORMATSIZE];
04344 char type[DNS_RDATATYPE_FORMATSIZE];
04345
04346 dns_name_format(name, namebuf, sizeof(namebuf));
04347 dns_rdataclass_format(rdataset->rdclass, class, sizeof(class));
04348 dns_rdatatype_format(rdataset->type, type, sizeof(type));
04349 log_formerr(fctx, "question section mismatch: got %s/%s/%s",
04350 namebuf, class, type);
04351 return (DNS_R_FORMERR);
04352 }
04353
04354 return (ISC_R_SUCCESS);
04355 }
04356
04357 static void
04358 clone_results(fetchctx_t *fctx) {
04359 dns_fetchevent_t *event, *hevent;
04360 isc_result_t result;
04361 dns_name_t *name, *hname;
04362
04363 FCTXTRACE("clone_results");
04364
04365
04366
04367
04368
04369
04370
04371
04372 fctx->cloned = ISC_TRUE;
04373 hevent = ISC_LIST_HEAD(fctx->events);
04374 if (hevent == NULL)
04375 return;
04376 hname = dns_fixedname_name(&hevent->foundname);
04377 for (event = ISC_LIST_NEXT(hevent, ev_link);
04378 event != NULL;
04379 event = ISC_LIST_NEXT(event, ev_link)) {
04380 name = dns_fixedname_name(&event->foundname);
04381 result = dns_name_copy(hname, name, NULL);
04382 if (result != ISC_R_SUCCESS)
04383 event->result = result;
04384 else
04385 event->result = hevent->result;
04386 dns_db_attach(hevent->db, &event->db);
04387 dns_db_attachnode(hevent->db, hevent->node, &event->node);
04388 INSIST(hevent->rdataset != NULL);
04389 INSIST(event->rdataset != NULL);
04390 if (dns_rdataset_isassociated(hevent->rdataset))
04391 dns_rdataset_clone(hevent->rdataset, event->rdataset);
04392 INSIST(! (hevent->sigrdataset == NULL &&
04393 event->sigrdataset != NULL));
04394 if (hevent->sigrdataset != NULL &&
04395 dns_rdataset_isassociated(hevent->sigrdataset) &&
04396 event->sigrdataset != NULL)
04397 dns_rdataset_clone(hevent->sigrdataset,
04398 event->sigrdataset);
04399 }
04400 }
04401
04402 #define CACHE(r) (((r)->attributes & DNS_RDATASETATTR_CACHE) != 0)
04403 #define ANSWER(r) (((r)->attributes & DNS_RDATASETATTR_ANSWER) != 0)
04404 #define ANSWERSIG(r) (((r)->attributes & DNS_RDATASETATTR_ANSWERSIG) != 0)
04405 #define EXTERNAL(r) (((r)->attributes & DNS_RDATASETATTR_EXTERNAL) != 0)
04406 #define CHAINING(r) (((r)->attributes & DNS_RDATASETATTR_CHAINING) != 0)
04407 #define CHASE(r) (((r)->attributes & DNS_RDATASETATTR_CHASE) != 0)
04408 #define CHECKNAMES(r) (((r)->attributes & DNS_RDATASETATTR_CHECKNAMES) != 0)
04409
04410
04411
04412
04413
04414
04415
04416
04417
04418
04419
04420
04421 static isc_boolean_t
04422 maybe_destroy(fetchctx_t *fctx, isc_boolean_t locked) {
04423 unsigned int bucketnum;
04424 isc_boolean_t bucket_empty = ISC_FALSE;
04425 dns_resolver_t *res = fctx->res;
04426 dns_validator_t *validator, *next_validator;
04427 isc_boolean_t dodestroy = ISC_FALSE;
04428
04429 REQUIRE(SHUTTINGDOWN(fctx));
04430
04431 bucketnum = fctx->bucketnum;
04432 if (!locked)
04433 LOCK(&res->buckets[bucketnum].lock);
04434 if (fctx->pending != 0 || fctx->nqueries != 0)
04435 goto unlock;
04436
04437 for (validator = ISC_LIST_HEAD(fctx->validators);
04438 validator != NULL; validator = next_validator) {
04439 next_validator = ISC_LIST_NEXT(validator, link);
04440 dns_validator_cancel(validator);
04441 }
04442
04443 if (fctx->references == 0 && ISC_LIST_EMPTY(fctx->validators)) {
04444 bucket_empty = fctx_unlink(fctx);
04445 dodestroy = ISC_TRUE;
04446 }
04447 unlock:
04448 if (!locked)
04449 UNLOCK(&res->buckets[bucketnum].lock);
04450 if (dodestroy)
04451 fctx_destroy(fctx);
04452 return (bucket_empty);
04453 }
04454
04455
04456
04457
04458 static void
04459 validated(isc_task_t *task, isc_event_t *event) {
04460 dns_adbaddrinfo_t *addrinfo;
04461 dns_dbnode_t *node = NULL;
04462 dns_dbnode_t *nsnode = NULL;
04463 dns_fetchevent_t *hevent;
04464 dns_name_t *name;
04465 dns_rdataset_t *ardataset = NULL;
04466 dns_rdataset_t *asigrdataset = NULL;
04467 dns_rdataset_t *rdataset;
04468 dns_rdataset_t *sigrdataset;
04469 dns_resolver_t *res;
04470 dns_valarg_t *valarg;
04471 dns_validatorevent_t *vevent;
04472 fetchctx_t *fctx;
04473 isc_boolean_t chaining;
04474 isc_boolean_t negative;
04475 isc_boolean_t sentresponse;
04476 isc_result_t eresult = ISC_R_SUCCESS;
04477 isc_result_t result = ISC_R_SUCCESS;
04478 isc_stdtime_t now;
04479 isc_uint32_t ttl;
04480 unsigned options;
04481 isc_uint32_t bucketnum;
04482
04483 UNUSED(task);
04484
04485 REQUIRE(event->ev_type == DNS_EVENT_VALIDATORDONE);
04486 valarg = event->ev_arg;
04487 fctx = valarg->fctx;
04488 res = fctx->res;
04489 addrinfo = valarg->addrinfo;
04490 REQUIRE(VALID_FCTX(fctx));
04491 REQUIRE(!ISC_LIST_EMPTY(fctx->validators));
04492
04493 vevent = (dns_validatorevent_t *)event;
04494 fctx->vresult = vevent->result;
04495
04496 FCTXTRACE("received validation completion event");
04497
04498 bucketnum = fctx->bucketnum;
04499 LOCK(&res->buckets[bucketnum].lock);
04500
04501 ISC_LIST_UNLINK(fctx->validators, vevent->validator, link);
04502 fctx->validator = NULL;
04503
04504
04505
04506
04507
04508 dns_validator_destroy(&vevent->validator);
04509 isc_mem_put(fctx->mctx, valarg, sizeof(*valarg));
04510
04511 negative = ISC_TF(vevent->rdataset == NULL);
04512
04513 sentresponse = ISC_TF((fctx->options & DNS_FETCHOPT_NOVALIDATE) != 0);
04514
04515
04516
04517
04518
04519
04520 if (SHUTTINGDOWN(fctx) && !sentresponse) {
04521 isc_boolean_t bucket_empty;
04522 bucket_empty = maybe_destroy(fctx, ISC_TRUE);
04523 UNLOCK(&res->buckets[bucketnum].lock);
04524 if (bucket_empty)
04525 empty_bucket(res);
04526 goto cleanup_event;
04527 }
04528
04529 isc_stdtime_get(&now);
04530
04531
04532
04533
04534
04535 if (vevent->result == ISC_R_SUCCESS &&
04536 !negative &&
04537 vevent->rdataset != NULL &&
04538 CHAINING(vevent->rdataset))
04539 {
04540 if (vevent->rdataset->type == dns_rdatatype_cname)
04541 eresult = DNS_R_CNAME;
04542 else {
04543 INSIST(vevent->rdataset->type == dns_rdatatype_dname);
04544 eresult = DNS_R_DNAME;
04545 }
04546 chaining = ISC_TRUE;
04547 } else
04548 chaining = ISC_FALSE;
04549
04550
04551
04552
04553
04554
04555
04556 hevent = ISC_LIST_HEAD(fctx->events);
04557 if (hevent != NULL) {
04558 if (!negative && !chaining &&
04559 (fctx->type == dns_rdatatype_any ||
04560 fctx->type == dns_rdatatype_rrsig ||
04561 fctx->type == dns_rdatatype_sig)) {
04562
04563
04564
04565
04566 } else {
04567 ardataset = hevent->rdataset;
04568 asigrdataset = hevent->sigrdataset;
04569 }
04570 }
04571
04572 if (vevent->result != ISC_R_SUCCESS) {
04573 FCTXTRACE("validation failed");
04574 inc_stats(res, dns_resstatscounter_valfail);
04575 fctx->valfail++;
04576 fctx->vresult = vevent->result;
04577 if (fctx->vresult != DNS_R_BROKENCHAIN) {
04578 result = ISC_R_NOTFOUND;
04579 if (vevent->rdataset != NULL)
04580 result = dns_db_findnode(fctx->cache,
04581 vevent->name,
04582 ISC_TRUE, &node);
04583 if (result == ISC_R_SUCCESS)
04584 (void)dns_db_deleterdataset(fctx->cache, node,
04585 NULL,
04586 vevent->type, 0);
04587 if (result == ISC_R_SUCCESS &&
04588 vevent->sigrdataset != NULL)
04589 (void)dns_db_deleterdataset(fctx->cache, node,
04590 NULL,
04591 dns_rdatatype_rrsig,
04592 vevent->type);
04593 if (result == ISC_R_SUCCESS)
04594 dns_db_detachnode(fctx->cache, &node);
04595 }
04596 if (fctx->vresult == DNS_R_BROKENCHAIN && !negative) {
04597
04598
04599
04600 result = ISC_R_NOTFOUND;
04601 if (vevent->rdataset != NULL)
04602 result = dns_db_findnode(fctx->cache,
04603 vevent->name,
04604 ISC_TRUE, &node);
04605 if (result == ISC_R_SUCCESS) {
04606 (void)dns_db_addrdataset(fctx->cache, node,
04607 NULL, now,
04608 vevent->rdataset, 0,
04609 NULL);
04610 }
04611 if (result == ISC_R_SUCCESS &&
04612 vevent->sigrdataset != NULL)
04613 (void)dns_db_addrdataset(fctx->cache, node,
04614 NULL, now,
04615 vevent->sigrdataset,
04616 0, NULL);
04617 if (result == ISC_R_SUCCESS)
04618 dns_db_detachnode(fctx->cache, &node);
04619 }
04620 result = fctx->vresult;
04621 add_bad(fctx, addrinfo, result, badns_validation);
04622 isc_event_free(&event);
04623 UNLOCK(&res->buckets[bucketnum].lock);
04624 INSIST(fctx->validator == NULL);
04625 fctx->validator = ISC_LIST_HEAD(fctx->validators);
04626 if (fctx->validator != NULL)
04627 dns_validator_send(fctx->validator);
04628 else if (sentresponse)
04629 fctx_done(fctx, result, __LINE__);
04630 else if (result == DNS_R_BROKENCHAIN) {
04631 isc_result_t tresult;
04632 isc_time_t expire;
04633 isc_interval_t i;
04634
04635 isc_interval_set(&i, DNS_RESOLVER_BADCACHETTL(fctx), 0);
04636 tresult = isc_time_nowplusinterval(&expire, &i);
04637 if (negative &&
04638 (fctx->type == dns_rdatatype_dnskey ||
04639 fctx->type == dns_rdatatype_dlv ||
04640 fctx->type == dns_rdatatype_ds) &&
04641 tresult == ISC_R_SUCCESS)
04642 dns_resolver_addbadcache(res, &fctx->name,
04643 fctx->type, &expire);
04644 fctx_done(fctx, result, __LINE__);
04645 } else
04646 fctx_try(fctx, ISC_TRUE, ISC_TRUE);
04647 return;
04648 }
04649
04650
04651 if (negative) {
04652 dns_rdatatype_t covers;
04653 FCTXTRACE("nonexistence validation OK");
04654
04655 inc_stats(res, dns_resstatscounter_valnegsuccess);
04656
04657
04658
04659
04660 if (fctx->rmessage->rcode == dns_rcode_nxdomain &&
04661 fctx->type != dns_rdatatype_ds)
04662 covers = dns_rdatatype_any;
04663 else
04664 covers = fctx->type;
04665
04666 result = dns_db_findnode(fctx->cache, vevent->name, ISC_TRUE,
04667 &node);
04668 if (result != ISC_R_SUCCESS)
04669 goto noanswer_response;
04670
04671
04672
04673
04674
04675
04676 ttl = res->view->maxncachettl;
04677 if (fctx->type == dns_rdatatype_soa &&
04678 covers == dns_rdatatype_any && res->zero_no_soa_ttl)
04679 ttl = 0;
04680
04681 result = ncache_adderesult(fctx->rmessage, fctx->cache, node,
04682 covers, now, ttl, vevent->optout,
04683 vevent->secure, ardataset, &eresult);
04684 if (result != ISC_R_SUCCESS)
04685 goto noanswer_response;
04686 goto answer_response;
04687 } else
04688 inc_stats(res, dns_resstatscounter_valsuccess);
04689
04690 FCTXTRACE("validation OK");
04691
04692 if (vevent->proofs[DNS_VALIDATOR_NOQNAMEPROOF] != NULL) {
04693 result = dns_rdataset_addnoqname(vevent->rdataset,
04694 vevent->proofs[DNS_VALIDATOR_NOQNAMEPROOF]);
04695 RUNTIME_CHECK(result == ISC_R_SUCCESS);
04696 INSIST(vevent->sigrdataset != NULL);
04697 vevent->sigrdataset->ttl = vevent->rdataset->ttl;
04698 if (vevent->proofs[DNS_VALIDATOR_CLOSESTENCLOSER] != NULL) {
04699 result = dns_rdataset_addclosest(vevent->rdataset,
04700 vevent->proofs[DNS_VALIDATOR_CLOSESTENCLOSER]);
04701 RUNTIME_CHECK(result == ISC_R_SUCCESS);
04702 }
04703 } else if (vevent->rdataset->trust == dns_trust_answer &&
04704 vevent->rdataset->type != dns_rdatatype_rrsig)
04705 {
04706 isc_result_t tresult;
04707 dns_name_t *noqname = NULL;
04708 tresult = findnoqname(fctx, vevent->name,
04709 vevent->rdataset->type, &noqname);
04710 if (tresult == ISC_R_SUCCESS && noqname != NULL) {
04711 tresult = dns_rdataset_addnoqname(vevent->rdataset,
04712 noqname);
04713 RUNTIME_CHECK(tresult == ISC_R_SUCCESS);
04714 }
04715 }
04716
04717
04718
04719
04720
04721
04722
04723 result = dns_db_findnode(fctx->cache, vevent->name, ISC_TRUE, &node);
04724 if (result != ISC_R_SUCCESS)
04725 goto noanswer_response;
04726
04727 options = 0;
04728 if ((fctx->options & DNS_FETCHOPT_PREFETCH) != 0)
04729 options = DNS_DBADD_PREFETCH;
04730 result = dns_db_addrdataset(fctx->cache, node, NULL, now,
04731 vevent->rdataset, options, ardataset);
04732 if (result != ISC_R_SUCCESS &&
04733 result != DNS_R_UNCHANGED)
04734 goto noanswer_response;
04735 if (ardataset != NULL && NEGATIVE(ardataset)) {
04736 if (NXDOMAIN(ardataset))
04737 eresult = DNS_R_NCACHENXDOMAIN;
04738 else
04739 eresult = DNS_R_NCACHENXRRSET;
04740 } else if (vevent->sigrdataset != NULL) {
04741 result = dns_db_addrdataset(fctx->cache, node, NULL, now,
04742 vevent->sigrdataset, 0,
04743 asigrdataset);
04744 if (result != ISC_R_SUCCESS &&
04745 result != DNS_R_UNCHANGED)
04746 goto noanswer_response;
04747 }
04748
04749 if (sentresponse) {
04750 isc_boolean_t bucket_empty = ISC_FALSE;
04751
04752
04753
04754
04755 dns_db_detachnode(fctx->cache, &node);
04756 if (SHUTTINGDOWN(fctx))
04757 bucket_empty = maybe_destroy(fctx, ISC_TRUE);
04758 UNLOCK(&res->buckets[bucketnum].lock);
04759 if (bucket_empty)
04760 empty_bucket(res);
04761 goto cleanup_event;
04762 }
04763
04764 if (!ISC_LIST_EMPTY(fctx->validators)) {
04765 INSIST(!negative);
04766 INSIST(fctx->type == dns_rdatatype_any ||
04767 fctx->type == dns_rdatatype_rrsig ||
04768 fctx->type == dns_rdatatype_sig);
04769
04770
04771
04772
04773
04774 dns_db_detachnode(fctx->cache, &node);
04775 UNLOCK(&res->buckets[bucketnum].lock);
04776 dns_validator_send(ISC_LIST_HEAD(fctx->validators));
04777 goto cleanup_event;
04778 }
04779
04780 answer_response:
04781
04782
04783
04784 result = dns_message_firstname(fctx->rmessage, DNS_SECTION_AUTHORITY);
04785 while (result == ISC_R_SUCCESS) {
04786 name = NULL;
04787 dns_message_currentname(fctx->rmessage, DNS_SECTION_AUTHORITY,
04788 &name);
04789 for (rdataset = ISC_LIST_HEAD(name->list);
04790 rdataset != NULL;
04791 rdataset = ISC_LIST_NEXT(rdataset, link)) {
04792 if ((rdataset->type != dns_rdatatype_ns &&
04793 rdataset->type != dns_rdatatype_nsec) ||
04794 rdataset->trust != dns_trust_secure)
04795 continue;
04796 for (sigrdataset = ISC_LIST_HEAD(name->list);
04797 sigrdataset != NULL;
04798 sigrdataset = ISC_LIST_NEXT(sigrdataset, link)) {
04799 if (sigrdataset->type != dns_rdatatype_rrsig ||
04800 sigrdataset->covers != rdataset->type)
04801 continue;
04802 break;
04803 }
04804 if (sigrdataset == NULL ||
04805 sigrdataset->trust != dns_trust_secure)
04806 continue;
04807 result = dns_db_findnode(fctx->cache, name, ISC_TRUE,
04808 &nsnode);
04809 if (result != ISC_R_SUCCESS)
04810 continue;
04811
04812 result = dns_db_addrdataset(fctx->cache, nsnode, NULL,
04813 now, rdataset, 0, NULL);
04814 if (result == ISC_R_SUCCESS)
04815 result = dns_db_addrdataset(fctx->cache, nsnode,
04816 NULL, now,
04817 sigrdataset, 0,
04818 NULL);
04819 dns_db_detachnode(fctx->cache, &nsnode);
04820 if (result != ISC_R_SUCCESS)
04821 continue;
04822 }
04823 result = dns_message_nextname(fctx->rmessage,
04824 DNS_SECTION_AUTHORITY);
04825 }
04826
04827 result = ISC_R_SUCCESS;
04828
04829
04830
04831
04832
04833
04834 fctx->attributes |= FCTX_ATTR_HAVEANSWER;
04835
04836 if (hevent != NULL) {
04837
04838
04839
04840 if (dns_rdataset_isassociated(hevent->rdataset) &&
04841 NEGATIVE(hevent->rdataset)) {
04842 INSIST(eresult == DNS_R_NCACHENXDOMAIN ||
04843 eresult == DNS_R_NCACHENXRRSET);
04844 }
04845 hevent->result = eresult;
04846 RUNTIME_CHECK(dns_name_copy(vevent->name,
04847 dns_fixedname_name(&hevent->foundname), NULL)
04848 == ISC_R_SUCCESS);
04849 dns_db_attach(fctx->cache, &hevent->db);
04850 dns_db_transfernode(fctx->cache, &node, &hevent->node);
04851 clone_results(fctx);
04852 }
04853
04854 noanswer_response:
04855 if (node != NULL)
04856 dns_db_detachnode(fctx->cache, &node);
04857
04858 UNLOCK(&res->buckets[bucketnum].lock);
04859 fctx_done(fctx, result, __LINE__);
04860
04861 cleanup_event:
04862 INSIST(node == NULL);
04863 isc_event_free(&event);
04864 }
04865
04866 static void
04867 fctx_log(void *arg, int level, const char *fmt, ...) {
04868 char msgbuf[2048];
04869 va_list args;
04870 fetchctx_t *fctx = arg;
04871
04872 va_start(args, fmt);
04873 vsnprintf(msgbuf, sizeof(msgbuf), fmt, args);
04874 va_end(args);
04875
04876 isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER,
04877 DNS_LOGMODULE_RESOLVER, level,
04878 "fctx %p(%s): %s", fctx, fctx->info, msgbuf);
04879 }
04880
04881 static inline isc_result_t
04882 findnoqname(fetchctx_t *fctx, dns_name_t *name, dns_rdatatype_t type,
04883 dns_name_t **noqnamep)
04884 {
04885 dns_rdataset_t *nrdataset, *next, *sigrdataset;
04886 dns_rdata_rrsig_t rrsig;
04887 isc_result_t result;
04888 unsigned int labels;
04889 dns_section_t section;
04890 dns_name_t *zonename;
04891 dns_fixedname_t fzonename;
04892 dns_name_t *closest;
04893 dns_fixedname_t fclosest;
04894 dns_name_t *nearest;
04895 dns_fixedname_t fnearest;
04896 dns_rdatatype_t found = dns_rdatatype_none;
04897 dns_name_t *noqname = NULL;
04898
04899 FCTXTRACE("findnoqname");
04900
04901 REQUIRE(noqnamep != NULL && *noqnamep == NULL);
04902
04903
04904
04905
04906 for (sigrdataset = ISC_LIST_HEAD(name->list);
04907 sigrdataset != NULL;
04908 sigrdataset = ISC_LIST_NEXT(sigrdataset, link)) {
04909 if (sigrdataset->type == dns_rdatatype_rrsig &&
04910 sigrdataset->covers == type)
04911 break;
04912 }
04913
04914 if (sigrdataset == NULL)
04915 return (ISC_R_NOTFOUND);
04916
04917 labels = dns_name_countlabels(name);
04918
04919 for (result = dns_rdataset_first(sigrdataset);
04920 result == ISC_R_SUCCESS;
04921 result = dns_rdataset_next(sigrdataset)) {
04922 dns_rdata_t rdata = DNS_RDATA_INIT;
04923 dns_rdataset_current(sigrdataset, &rdata);
04924 result = dns_rdata_tostruct(&rdata, &rrsig, NULL);
04925 RUNTIME_CHECK(result == ISC_R_SUCCESS);
04926
04927 if (rrsig.labels + 1U >= labels)
04928 continue;
04929 break;
04930 }
04931
04932 if (result == ISC_R_NOMORE)
04933 return (ISC_R_NOTFOUND);
04934 if (result != ISC_R_SUCCESS)
04935 return (result);
04936
04937 dns_fixedname_init(&fzonename);
04938 zonename = dns_fixedname_name(&fzonename);
04939 dns_fixedname_init(&fclosest);
04940 closest = dns_fixedname_name(&fclosest);
04941 dns_fixedname_init(&fnearest);
04942 nearest = dns_fixedname_name(&fnearest);
04943
04944 #define NXND(x) ((x) == ISC_R_SUCCESS)
04945
04946 section = DNS_SECTION_AUTHORITY;
04947 for (result = dns_message_firstname(fctx->rmessage, section);
04948 result == ISC_R_SUCCESS;
04949 result = dns_message_nextname(fctx->rmessage, section)) {
04950 dns_name_t *nsec = NULL;
04951 dns_message_currentname(fctx->rmessage, section, &nsec);
04952 for (nrdataset = ISC_LIST_HEAD(nsec->list);
04953 nrdataset != NULL; nrdataset = next) {
04954 isc_boolean_t data = ISC_FALSE, exists = ISC_FALSE;
04955 isc_boolean_t optout = ISC_FALSE, unknown = ISC_FALSE;
04956 isc_boolean_t setclosest = ISC_FALSE;
04957 isc_boolean_t setnearest = ISC_FALSE;
04958
04959 next = ISC_LIST_NEXT(nrdataset, link);
04960 if (nrdataset->type != dns_rdatatype_nsec &&
04961 nrdataset->type != dns_rdatatype_nsec3)
04962 continue;
04963
04964 if (nrdataset->type == dns_rdatatype_nsec &&
04965 NXND(dns_nsec_noexistnodata(type, name, nsec,
04966 nrdataset, &exists,
04967 &data, NULL, fctx_log,
04968 fctx)))
04969 {
04970 if (!exists) {
04971 noqname = nsec;
04972 found = dns_rdatatype_nsec;
04973 }
04974 }
04975
04976 if (nrdataset->type == dns_rdatatype_nsec3 &&
04977 NXND(dns_nsec3_noexistnodata(type, name, nsec,
04978 nrdataset, zonename,
04979 &exists, &data,
04980 &optout, &unknown,
04981 &setclosest,
04982 &setnearest,
04983 closest, nearest,
04984 fctx_log, fctx)))
04985 {
04986 if (!exists && setnearest) {
04987 noqname = nsec;
04988 found = dns_rdatatype_nsec3;
04989 }
04990 }
04991 }
04992 }
04993 if (result == ISC_R_NOMORE)
04994 result = ISC_R_SUCCESS;
04995 if (noqname != NULL) {
04996 for (sigrdataset = ISC_LIST_HEAD(noqname->list);
04997 sigrdataset != NULL;
04998 sigrdataset = ISC_LIST_NEXT(sigrdataset, link)) {
04999 if (sigrdataset->type == dns_rdatatype_rrsig &&
05000 sigrdataset->covers == found)
05001 break;
05002 }
05003 if (sigrdataset != NULL)
05004 *noqnamep = noqname;
05005 }
05006 return (result);
05007 }
05008
05009 static inline isc_result_t
05010 cache_name(fetchctx_t *fctx, dns_name_t *name, dns_adbaddrinfo_t *addrinfo,
05011 isc_stdtime_t now)
05012 {
05013 dns_rdataset_t *rdataset, *sigrdataset;
05014 dns_rdataset_t *addedrdataset, *ardataset, *asigrdataset;
05015 dns_rdataset_t *valrdataset = NULL, *valsigrdataset = NULL;
05016 dns_dbnode_t *node, **anodep;
05017 dns_db_t **adbp;
05018 dns_name_t *aname;
05019 dns_resolver_t *res;
05020 isc_boolean_t need_validation, secure_domain, have_answer;
05021 isc_result_t result, eresult;
05022 dns_fetchevent_t *event;
05023 unsigned int options;
05024 isc_task_t *task;
05025 isc_boolean_t fail;
05026 unsigned int valoptions = 0;
05027 isc_boolean_t checknta = ISC_TRUE;
05028
05029
05030
05031
05032
05033 res = fctx->res;
05034 need_validation = ISC_FALSE;
05035 POST(need_validation);
05036 secure_domain = ISC_FALSE;
05037 have_answer = ISC_FALSE;
05038 eresult = ISC_R_SUCCESS;
05039 task = res->buckets[fctx->bucketnum].task;
05040
05041
05042
05043
05044 if ((fctx->options & DNS_FETCHOPT_NONTA) != 0) {
05045 valoptions |= DNS_VALIDATOR_NONTA;
05046 checknta = ISC_FALSE;
05047 }
05048
05049 if (res->view->enablevalidation) {
05050 result = issecuredomain(res->view, name, fctx->type,
05051 now, checknta, &secure_domain);
05052 if (result != ISC_R_SUCCESS)
05053 return (result);
05054
05055 if (!secure_domain && res->view->dlv != NULL) {
05056 valoptions |= DNS_VALIDATOR_DLV;
05057 secure_domain = ISC_TRUE;
05058 }
05059 }
05060
05061 if ((fctx->options & DNS_FETCHOPT_NOCDFLAG) != 0)
05062 valoptions |= DNS_VALIDATOR_NOCDFLAG;
05063
05064 if ((fctx->options & DNS_FETCHOPT_NOVALIDATE) != 0)
05065 need_validation = ISC_FALSE;
05066 else
05067 need_validation = secure_domain;
05068
05069 adbp = NULL;
05070 aname = NULL;
05071 anodep = NULL;
05072 ardataset = NULL;
05073 asigrdataset = NULL;
05074 event = NULL;
05075 if ((name->attributes & DNS_NAMEATTR_ANSWER) != 0 &&
05076 !need_validation) {
05077 have_answer = ISC_TRUE;
05078 event = ISC_LIST_HEAD(fctx->events);
05079 if (event != NULL) {
05080 adbp = &event->db;
05081 aname = dns_fixedname_name(&event->foundname);
05082 result = dns_name_copy(name, aname, NULL);
05083 if (result != ISC_R_SUCCESS)
05084 return (result);
05085 anodep = &event->node;
05086
05087
05088
05089
05090
05091
05092
05093 if ((fctx->type != dns_rdatatype_any &&
05094 fctx->type != dns_rdatatype_rrsig &&
05095 fctx->type != dns_rdatatype_sig) ||
05096 (name->attributes & DNS_NAMEATTR_CHAINING) != 0) {
05097 ardataset = event->rdataset;
05098 asigrdataset = event->sigrdataset;
05099 }
05100 }
05101 }
05102
05103
05104
05105
05106 node = NULL;
05107 result = dns_db_findnode(fctx->cache, name, ISC_TRUE, &node);
05108 if (result != ISC_R_SUCCESS)
05109 return (result);
05110
05111
05112
05113
05114 fail = ISC_TF((fctx->res->options & DNS_RESOLVER_CHECKNAMESFAIL) != 0);
05115 for (rdataset = ISC_LIST_HEAD(name->list);
05116 rdataset != NULL;
05117 rdataset = ISC_LIST_NEXT(rdataset, link)) {
05118 if (!CACHE(rdataset))
05119 continue;
05120 if (CHECKNAMES(rdataset)) {
05121 char namebuf[DNS_NAME_FORMATSIZE];
05122 char typebuf[DNS_RDATATYPE_FORMATSIZE];
05123 char classbuf[DNS_RDATATYPE_FORMATSIZE];
05124
05125 dns_name_format(name, namebuf, sizeof(namebuf));
05126 dns_rdatatype_format(rdataset->type, typebuf,
05127 sizeof(typebuf));
05128 dns_rdataclass_format(rdataset->rdclass, classbuf,
05129 sizeof(classbuf));
05130 isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER,
05131 DNS_LOGMODULE_RESOLVER, ISC_LOG_NOTICE,
05132 "check-names %s %s/%s/%s",
05133 fail ? "failure" : "warning",
05134 namebuf, typebuf, classbuf);
05135 if (fail) {
05136 if (ANSWER(rdataset)) {
05137 dns_db_detachnode(fctx->cache, &node);
05138 return (DNS_R_BADNAME);
05139 }
05140 continue;
05141 }
05142 }
05143
05144
05145
05146
05147 if (rdataset->ttl > res->view->maxcachettl)
05148 rdataset->ttl = res->view->maxcachettl;
05149
05150
05151
05152
05153 if (rdataset->ttl > fctx->res->view->prefetch_eligible)
05154 rdataset->attributes |= DNS_RDATASETATTR_PREFETCH;
05155
05156
05157
05158
05159 for (sigrdataset = ISC_LIST_HEAD(name->list);
05160 sigrdataset != NULL;
05161 sigrdataset = ISC_LIST_NEXT(sigrdataset, link)) {
05162 if (sigrdataset->type == dns_rdatatype_rrsig &&
05163 sigrdataset->covers == rdataset->type)
05164 break;
05165 }
05166
05167
05168
05169
05170
05171
05172
05173
05174
05175
05176
05177 if (secure_domain && rdataset->trust != dns_trust_glue &&
05178 !EXTERNAL(rdataset)) {
05179 dns_trust_t trust;
05180
05181
05182
05183
05184
05185 if (rdataset->type == dns_rdatatype_rrsig)
05186 continue;
05187
05188 if (sigrdataset == NULL) {
05189 if (!ANSWER(rdataset) && need_validation) {
05190
05191
05192
05193
05194 continue;
05195 }
05196 }
05197
05198
05199
05200
05201 if (sigrdataset != NULL) {
05202 rdataset->ttl = ISC_MIN(rdataset->ttl,
05203 sigrdataset->ttl);
05204 sigrdataset->ttl = rdataset->ttl;
05205 }
05206
05207
05208
05209
05210 if (rdataset->ttl > fctx->res->view->prefetch_eligible)
05211 rdataset->attributes |= DNS_RDATASETATTR_PREFETCH;
05212
05213
05214
05215
05216
05217
05218
05219 if (rdataset->trust == dns_trust_additional)
05220 trust = dns_trust_pending_additional;
05221 else
05222 trust = dns_trust_pending_answer;
05223
05224 rdataset->trust = trust;
05225 if (sigrdataset != NULL)
05226 sigrdataset->trust = trust;
05227 if (!need_validation || !ANSWER(rdataset)) {
05228 options = 0;
05229 if (ANSWER(rdataset) &&
05230 rdataset->type != dns_rdatatype_rrsig) {
05231 isc_result_t tresult;
05232 dns_name_t *noqname = NULL;
05233 tresult = findnoqname(fctx, name,
05234 rdataset->type,
05235 &noqname);
05236 if (tresult == ISC_R_SUCCESS &&
05237 noqname != NULL) {
05238 tresult =
05239 dns_rdataset_addnoqname(
05240 rdataset, noqname);
05241 RUNTIME_CHECK(tresult ==
05242 ISC_R_SUCCESS);
05243 }
05244 }
05245 if ((fctx->options & DNS_FETCHOPT_PREFETCH) != 0)
05246 options = DNS_DBADD_PREFETCH;
05247 addedrdataset = ardataset;
05248 result = dns_db_addrdataset(fctx->cache, node,
05249 NULL, now, rdataset,
05250 options,
05251 addedrdataset);
05252 if (result == DNS_R_UNCHANGED) {
05253 result = ISC_R_SUCCESS;
05254 if (!need_validation &&
05255 ardataset != NULL &&
05256 NEGATIVE(ardataset)) {
05257
05258
05259
05260
05261
05262
05263
05264 if (NXDOMAIN(ardataset))
05265 eresult =
05266 DNS_R_NCACHENXDOMAIN;
05267 else
05268 eresult =
05269 DNS_R_NCACHENXRRSET;
05270
05271
05272
05273
05274
05275
05276 continue;
05277 }
05278 }
05279 if (result != ISC_R_SUCCESS)
05280 break;
05281 if (sigrdataset != NULL) {
05282 addedrdataset = asigrdataset;
05283 result = dns_db_addrdataset(fctx->cache,
05284 node, NULL, now,
05285 sigrdataset,
05286 options,
05287 addedrdataset);
05288 if (result == DNS_R_UNCHANGED)
05289 result = ISC_R_SUCCESS;
05290 if (result != ISC_R_SUCCESS)
05291 break;
05292 } else if (!ANSWER(rdataset))
05293 continue;
05294 }
05295
05296 if (ANSWER(rdataset) && need_validation) {
05297 if (fctx->type != dns_rdatatype_any &&
05298 fctx->type != dns_rdatatype_rrsig &&
05299 fctx->type != dns_rdatatype_sig) {
05300
05301
05302
05303
05304
05305
05306 INSIST(valrdataset == NULL &&
05307 valsigrdataset == NULL);
05308 valrdataset = rdataset;
05309 valsigrdataset = sigrdataset;
05310 } else {
05311
05312
05313
05314
05315
05316
05317
05318
05319
05320
05321 result = valcreate(fctx, addrinfo,
05322 name, rdataset->type,
05323 rdataset,
05324 sigrdataset,
05325 valoptions, task);
05326
05327
05328
05329
05330
05331
05332 valoptions |= DNS_VALIDATOR_DEFER;
05333 }
05334 } else if (CHAINING(rdataset)) {
05335 if (rdataset->type == dns_rdatatype_cname)
05336 eresult = DNS_R_CNAME;
05337 else {
05338 INSIST(rdataset->type ==
05339 dns_rdatatype_dname);
05340 eresult = DNS_R_DNAME;
05341 }
05342 }
05343 } else if (!EXTERNAL(rdataset)) {
05344
05345
05346
05347 if (ANSWER(rdataset))
05348 addedrdataset = ardataset;
05349 else if (ANSWERSIG(rdataset))
05350 addedrdataset = asigrdataset;
05351 else
05352 addedrdataset = NULL;
05353 if (CHAINING(rdataset)) {
05354 if (rdataset->type == dns_rdatatype_cname)
05355 eresult = DNS_R_CNAME;
05356 else {
05357 INSIST(rdataset->type ==
05358 dns_rdatatype_dname);
05359 eresult = DNS_R_DNAME;
05360 }
05361 }
05362 if (rdataset->trust == dns_trust_glue &&
05363 (rdataset->type == dns_rdatatype_ns ||
05364 (rdataset->type == dns_rdatatype_rrsig &&
05365 rdataset->covers == dns_rdatatype_ns))) {
05366
05367
05368
05369
05370
05371
05372
05373 options = DNS_DBADD_FORCE;
05374 } else if ((fctx->options & DNS_FETCHOPT_PREFETCH) != 0)
05375 options = DNS_DBADD_PREFETCH;
05376 else
05377 options = 0;
05378
05379 if (ANSWER(rdataset) &&
05380 rdataset->type != dns_rdatatype_rrsig) {
05381 isc_result_t tresult;
05382 dns_name_t *noqname = NULL;
05383 tresult = findnoqname(fctx, name,
05384 rdataset->type, &noqname);
05385 if (tresult == ISC_R_SUCCESS &&
05386 noqname != NULL) {
05387 tresult = dns_rdataset_addnoqname(
05388 rdataset, noqname);
05389 RUNTIME_CHECK(tresult == ISC_R_SUCCESS);
05390 }
05391 }
05392
05393
05394
05395
05396 result = dns_db_addrdataset(fctx->cache,
05397 node, NULL, now,
05398 rdataset,
05399 options,
05400 addedrdataset);
05401
05402 if (result == DNS_R_UNCHANGED) {
05403 if (ANSWER(rdataset) &&
05404 ardataset != NULL &&
05405 NEGATIVE(ardataset)) {
05406
05407
05408
05409
05410
05411
05412 if (NXDOMAIN(ardataset))
05413 eresult = DNS_R_NCACHENXDOMAIN;
05414 else
05415 eresult = DNS_R_NCACHENXRRSET;
05416 }
05417 result = ISC_R_SUCCESS;
05418 } else if (result != ISC_R_SUCCESS)
05419 break;
05420 }
05421 }
05422
05423 if (valrdataset != NULL) {
05424 dns_rdatatype_t vtype = fctx->type;
05425 if (CHAINING(valrdataset)) {
05426 if (valrdataset->type == dns_rdatatype_cname)
05427 vtype = dns_rdatatype_cname;
05428 else
05429 vtype = dns_rdatatype_dname;
05430 }
05431 result = valcreate(fctx, addrinfo, name, vtype, valrdataset,
05432 valsigrdataset, valoptions, task);
05433 }
05434
05435 if (result == ISC_R_SUCCESS && have_answer) {
05436 fctx->attributes |= FCTX_ATTR_HAVEANSWER;
05437 if (event != NULL) {
05438
05439
05440
05441 if (dns_rdataset_isassociated(event->rdataset) &&
05442 NEGATIVE(event->rdataset)) {
05443 INSIST(eresult == DNS_R_NCACHENXDOMAIN ||
05444 eresult == DNS_R_NCACHENXRRSET);
05445 }
05446 event->result = eresult;
05447 dns_db_attach(fctx->cache, adbp);
05448 dns_db_transfernode(fctx->cache, &node, anodep);
05449 clone_results(fctx);
05450 }
05451 }
05452
05453 if (node != NULL)
05454 dns_db_detachnode(fctx->cache, &node);
05455
05456 return (result);
05457 }
05458
05459 static inline isc_result_t
05460 cache_message(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo, isc_stdtime_t now)
05461 {
05462 isc_result_t result;
05463 dns_section_t section;
05464 dns_name_t *name;
05465
05466 FCTXTRACE("cache_message");
05467
05468 fctx->attributes &= ~FCTX_ATTR_WANTCACHE;
05469
05470 LOCK(&fctx->res->buckets[fctx->bucketnum].lock);
05471
05472 for (section = DNS_SECTION_ANSWER;
05473 section <= DNS_SECTION_ADDITIONAL;
05474 section++) {
05475 result = dns_message_firstname(fctx->rmessage, section);
05476 while (result == ISC_R_SUCCESS) {
05477 name = NULL;
05478 dns_message_currentname(fctx->rmessage, section,
05479 &name);
05480 if ((name->attributes & DNS_NAMEATTR_CACHE) != 0) {
05481 result = cache_name(fctx, name, addrinfo, now);
05482 if (result != ISC_R_SUCCESS)
05483 break;
05484 }
05485 result = dns_message_nextname(fctx->rmessage, section);
05486 }
05487 if (result != ISC_R_NOMORE)
05488 break;
05489 }
05490 if (result == ISC_R_NOMORE)
05491 result = ISC_R_SUCCESS;
05492
05493 UNLOCK(&fctx->res->buckets[fctx->bucketnum].lock);
05494
05495 return (result);
05496 }
05497
05498
05499
05500
05501 static isc_result_t
05502 ncache_adderesult(dns_message_t *message, dns_db_t *cache, dns_dbnode_t *node,
05503 dns_rdatatype_t covers, isc_stdtime_t now, dns_ttl_t maxttl,
05504 isc_boolean_t optout, isc_boolean_t secure,
05505 dns_rdataset_t *ardataset, isc_result_t *eresultp)
05506 {
05507 isc_result_t result;
05508 dns_rdataset_t rdataset;
05509
05510 if (ardataset == NULL) {
05511 dns_rdataset_init(&rdataset);
05512 ardataset = &rdataset;
05513 }
05514 if (secure)
05515 result = dns_ncache_addoptout(message, cache, node, covers,
05516 now, maxttl, optout, ardataset);
05517 else
05518 result = dns_ncache_add(message, cache, node, covers, now,
05519 maxttl, ardataset);
05520 if (result == DNS_R_UNCHANGED || result == ISC_R_SUCCESS) {
05521
05522
05523
05524
05525
05526 if (NEGATIVE(ardataset)) {
05527
05528
05529
05530 if (NXDOMAIN(ardataset))
05531 *eresultp = DNS_R_NCACHENXDOMAIN;
05532 else
05533 *eresultp = DNS_R_NCACHENXRRSET;
05534 } else {
05535
05536
05537
05538
05539
05540
05541
05542
05543
05544 *eresultp = ISC_R_SUCCESS;
05545 }
05546 result = ISC_R_SUCCESS;
05547 }
05548 if (ardataset == &rdataset && dns_rdataset_isassociated(ardataset))
05549 dns_rdataset_disassociate(ardataset);
05550
05551 return (result);
05552 }
05553
05554 static inline isc_result_t
05555 ncache_message(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo,
05556 dns_rdatatype_t covers, isc_stdtime_t now)
05557 {
05558 isc_result_t result, eresult;
05559 dns_name_t *name;
05560 dns_resolver_t *res;
05561 dns_db_t **adbp;
05562 dns_dbnode_t *node, **anodep;
05563 dns_rdataset_t *ardataset;
05564 isc_boolean_t need_validation, secure_domain;
05565 dns_name_t *aname;
05566 dns_fetchevent_t *event;
05567 isc_uint32_t ttl;
05568 unsigned int valoptions = 0;
05569 isc_boolean_t checknta = ISC_TRUE;
05570
05571 FCTXTRACE("ncache_message");
05572
05573 fctx->attributes &= ~FCTX_ATTR_WANTNCACHE;
05574
05575 res = fctx->res;
05576 need_validation = ISC_FALSE;
05577 POST(need_validation);
05578 secure_domain = ISC_FALSE;
05579 eresult = ISC_R_SUCCESS;
05580 name = &fctx->name;
05581 node = NULL;
05582
05583
05584
05585
05586
05587 INSIST(fctx->rmessage->counts[DNS_SECTION_ANSWER] == 0);
05588
05589
05590
05591
05592 if ((fctx->options & DNS_FETCHOPT_NONTA) != 0) {
05593 valoptions |= DNS_VALIDATOR_NONTA;
05594 checknta = ISC_FALSE;
05595 }
05596
05597 if (fctx->res->view->enablevalidation) {
05598 result = issecuredomain(res->view, name, fctx->type,
05599 now, checknta, &secure_domain);
05600 if (result != ISC_R_SUCCESS)
05601 return (result);
05602
05603 if (!secure_domain && res->view->dlv != NULL) {
05604 valoptions |= DNS_VALIDATOR_DLV;
05605 secure_domain = ISC_TRUE;
05606 }
05607 }
05608
05609 if ((fctx->options & DNS_FETCHOPT_NOCDFLAG) != 0)
05610 valoptions |= DNS_VALIDATOR_NOCDFLAG;
05611
05612 if ((fctx->options & DNS_FETCHOPT_NOVALIDATE) != 0)
05613 need_validation = ISC_FALSE;
05614 else
05615 need_validation = secure_domain;
05616
05617 if (secure_domain) {
05618
05619
05620
05621 dns_rdataset_t *trdataset;
05622 dns_name_t *tname;
05623
05624 result = dns_message_firstname(fctx->rmessage,
05625 DNS_SECTION_AUTHORITY);
05626 while (result == ISC_R_SUCCESS) {
05627 tname = NULL;
05628 dns_message_currentname(fctx->rmessage,
05629 DNS_SECTION_AUTHORITY,
05630 &tname);
05631 for (trdataset = ISC_LIST_HEAD(tname->list);
05632 trdataset != NULL;
05633 trdataset = ISC_LIST_NEXT(trdataset, link))
05634 trdataset->trust = dns_trust_pending_answer;
05635 result = dns_message_nextname(fctx->rmessage,
05636 DNS_SECTION_AUTHORITY);
05637 }
05638 if (result != ISC_R_NOMORE)
05639 return (result);
05640
05641 }
05642
05643 if (need_validation) {
05644
05645
05646
05647 result = valcreate(fctx, addrinfo, name, fctx->type,
05648 NULL, NULL, valoptions,
05649 res->buckets[fctx->bucketnum].task);
05650
05651
05652
05653
05654
05655 return (result);
05656 }
05657
05658 LOCK(&res->buckets[fctx->bucketnum].lock);
05659
05660 adbp = NULL;
05661 aname = NULL;
05662 anodep = NULL;
05663 ardataset = NULL;
05664 if (!HAVE_ANSWER(fctx)) {
05665 event = ISC_LIST_HEAD(fctx->events);
05666 if (event != NULL) {
05667 adbp = &event->db;
05668 aname = dns_fixedname_name(&event->foundname);
05669 result = dns_name_copy(name, aname, NULL);
05670 if (result != ISC_R_SUCCESS)
05671 goto unlock;
05672 anodep = &event->node;
05673 ardataset = event->rdataset;
05674 }
05675 } else
05676 event = NULL;
05677
05678 result = dns_db_findnode(fctx->cache, name, ISC_TRUE, &node);
05679 if (result != ISC_R_SUCCESS)
05680 goto unlock;
05681
05682
05683
05684
05685
05686
05687 ttl = fctx->res->view->maxncachettl;
05688 if (fctx->type == dns_rdatatype_soa &&
05689 covers == dns_rdatatype_any &&
05690 fctx->res->zero_no_soa_ttl)
05691 ttl = 0;
05692
05693 result = ncache_adderesult(fctx->rmessage, fctx->cache, node,
05694 covers, now, ttl, ISC_FALSE,
05695 ISC_FALSE, ardataset, &eresult);
05696 if (result != ISC_R_SUCCESS)
05697 goto unlock;
05698
05699 if (!HAVE_ANSWER(fctx)) {
05700 fctx->attributes |= FCTX_ATTR_HAVEANSWER;
05701 if (event != NULL) {
05702 event->result = eresult;
05703 dns_db_attach(fctx->cache, adbp);
05704 dns_db_transfernode(fctx->cache, &node, anodep);
05705 clone_results(fctx);
05706 }
05707 }
05708
05709 unlock:
05710 UNLOCK(&res->buckets[fctx->bucketnum].lock);
05711
05712 if (node != NULL)
05713 dns_db_detachnode(fctx->cache, &node);
05714
05715 return (result);
05716 }
05717
05718 static inline void
05719 mark_related(dns_name_t *name, dns_rdataset_t *rdataset,
05720 isc_boolean_t external, isc_boolean_t gluing)
05721 {
05722 name->attributes |= DNS_NAMEATTR_CACHE;
05723 if (gluing) {
05724 rdataset->trust = dns_trust_glue;
05725
05726
05727
05728
05729 if (rdataset->ttl == 0)
05730 rdataset->ttl = 1;
05731 } else
05732 rdataset->trust = dns_trust_additional;
05733
05734
05735
05736 if (!CACHE(rdataset)) {
05737 name->attributes |= DNS_NAMEATTR_CHASE;
05738 rdataset->attributes |= DNS_RDATASETATTR_CHASE;
05739 }
05740 rdataset->attributes |= DNS_RDATASETATTR_CACHE;
05741 if (external)
05742 rdataset->attributes |= DNS_RDATASETATTR_EXTERNAL;
05743 }
05744
05745 static isc_result_t
05746 check_section(void *arg, dns_name_t *addname, dns_rdatatype_t type,
05747 dns_section_t section)
05748 {
05749 fetchctx_t *fctx = arg;
05750 isc_result_t result;
05751 dns_name_t *name;
05752 dns_rdataset_t *rdataset;
05753 isc_boolean_t external;
05754 dns_rdatatype_t rtype;
05755 isc_boolean_t gluing;
05756
05757 REQUIRE(VALID_FCTX(fctx));
05758
05759 #if CHECK_FOR_GLUE_IN_ANSWER
05760 if (section == DNS_SECTION_ANSWER && type != dns_rdatatype_a)
05761 return (ISC_R_SUCCESS);
05762 #endif
05763
05764 if (GLUING(fctx))
05765 gluing = ISC_TRUE;
05766 else
05767 gluing = ISC_FALSE;
05768 name = NULL;
05769 rdataset = NULL;
05770 result = dns_message_findname(fctx->rmessage, section, addname,
05771 dns_rdatatype_any, 0, &name, NULL);
05772 if (result == ISC_R_SUCCESS) {
05773 external = ISC_TF(!dns_name_issubdomain(name, &fctx->domain));
05774 if (type == dns_rdatatype_a) {
05775 for (rdataset = ISC_LIST_HEAD(name->list);
05776 rdataset != NULL;
05777 rdataset = ISC_LIST_NEXT(rdataset, link)) {
05778 if (rdataset->type == dns_rdatatype_rrsig)
05779 rtype = rdataset->covers;
05780 else
05781 rtype = rdataset->type;
05782 if (rtype == dns_rdatatype_a ||
05783 rtype == dns_rdatatype_aaaa)
05784 mark_related(name, rdataset, external,
05785 gluing);
05786 }
05787 } else {
05788 result = dns_message_findtype(name, type, 0,
05789 &rdataset);
05790 if (result == ISC_R_SUCCESS) {
05791 mark_related(name, rdataset, external, gluing);
05792
05793
05794
05795 rdataset = NULL;
05796 result = dns_message_findtype(name,
05797 dns_rdatatype_rrsig,
05798 type, &rdataset);
05799 if (result == ISC_R_SUCCESS)
05800 mark_related(name, rdataset, external,
05801 gluing);
05802 }
05803 }
05804 }
05805
05806 return (ISC_R_SUCCESS);
05807 }
05808
05809 static isc_result_t
05810 check_related(void *arg, dns_name_t *addname, dns_rdatatype_t type) {
05811 return (check_section(arg, addname, type, DNS_SECTION_ADDITIONAL));
05812 }
05813
05814 #ifndef CHECK_FOR_GLUE_IN_ANSWER
05815 #define CHECK_FOR_GLUE_IN_ANSWER 0
05816 #endif
05817 #if CHECK_FOR_GLUE_IN_ANSWER
05818 static isc_result_t
05819 check_answer(void *arg, dns_name_t *addname, dns_rdatatype_t type) {
05820 return (check_section(arg, addname, type, DNS_SECTION_ANSWER));
05821 }
05822 #endif
05823
05824 static void
05825 chase_additional(fetchctx_t *fctx) {
05826 isc_boolean_t rescan;
05827 dns_section_t section = DNS_SECTION_ADDITIONAL;
05828 isc_result_t result;
05829
05830 again:
05831 rescan = ISC_FALSE;
05832
05833 for (result = dns_message_firstname(fctx->rmessage, section);
05834 result == ISC_R_SUCCESS;
05835 result = dns_message_nextname(fctx->rmessage, section)) {
05836 dns_name_t *name = NULL;
05837 dns_rdataset_t *rdataset;
05838 dns_message_currentname(fctx->rmessage, DNS_SECTION_ADDITIONAL,
05839 &name);
05840 if ((name->attributes & DNS_NAMEATTR_CHASE) == 0)
05841 continue;
05842 name->attributes &= ~DNS_NAMEATTR_CHASE;
05843 for (rdataset = ISC_LIST_HEAD(name->list);
05844 rdataset != NULL;
05845 rdataset = ISC_LIST_NEXT(rdataset, link)) {
05846 if (CHASE(rdataset)) {
05847 rdataset->attributes &= ~DNS_RDATASETATTR_CHASE;
05848 (void)dns_rdataset_additionaldata(rdataset,
05849 check_related,
05850 fctx);
05851 rescan = ISC_TRUE;
05852 }
05853 }
05854 }
05855 if (rescan)
05856 goto again;
05857 }
05858
05859 static inline isc_result_t
05860 cname_target(dns_rdataset_t *rdataset, dns_name_t *tname) {
05861 isc_result_t result;
05862 dns_rdata_t rdata = DNS_RDATA_INIT;
05863 dns_rdata_cname_t cname;
05864
05865 result = dns_rdataset_first(rdataset);
05866 if (result != ISC_R_SUCCESS)
05867 return (result);
05868 dns_rdataset_current(rdataset, &rdata);
05869 result = dns_rdata_tostruct(&rdata, &cname, NULL);
05870 if (result != ISC_R_SUCCESS)
05871 return (result);
05872 dns_name_init(tname, NULL);
05873 dns_name_clone(&cname.cname, tname);
05874 dns_rdata_freestruct(&cname);
05875
05876 return (ISC_R_SUCCESS);
05877 }
05878
05879 static inline isc_result_t
05880 dname_target(fetchctx_t *fctx, dns_rdataset_t *rdataset, dns_name_t *qname,
05881 dns_name_t *oname, dns_fixedname_t *fixeddname)
05882 {
05883 isc_result_t result;
05884 dns_rdata_t rdata = DNS_RDATA_INIT;
05885 unsigned int nlabels;
05886 int order;
05887 dns_namereln_t namereln;
05888 dns_rdata_dname_t dname;
05889 dns_fixedname_t prefix;
05890
05891
05892
05893
05894 result = dns_rdataset_first(rdataset);
05895 if (result != ISC_R_SUCCESS)
05896 return (result);
05897 dns_rdataset_current(rdataset, &rdata);
05898 result = dns_rdata_tostruct(&rdata, &dname, NULL);
05899 if (result != ISC_R_SUCCESS)
05900 return (result);
05901
05902
05903
05904
05905 namereln = dns_name_fullcompare(qname, oname, &order, &nlabels);
05906 if (namereln != dns_namereln_subdomain) {
05907 char qbuf[DNS_NAME_FORMATSIZE];
05908 char obuf[DNS_NAME_FORMATSIZE];
05909
05910 dns_rdata_freestruct(&dname);
05911 dns_name_format(qname, qbuf, sizeof(qbuf));
05912 dns_name_format(oname, obuf, sizeof(obuf));
05913 log_formerr(fctx, "unrelated DNAME in answer: "
05914 "%s is not in %s", qbuf, obuf);
05915 return (DNS_R_FORMERR);
05916 }
05917 dns_fixedname_init(&prefix);
05918 dns_name_split(qname, nlabels, dns_fixedname_name(&prefix), NULL);
05919 dns_fixedname_init(fixeddname);
05920 result = dns_name_concatenate(dns_fixedname_name(&prefix),
05921 &dname.dname,
05922 dns_fixedname_name(fixeddname), NULL);
05923 dns_rdata_freestruct(&dname);
05924 return (result);
05925 }
05926
05927 static isc_boolean_t
05928 is_answeraddress_allowed(dns_view_t *view, dns_name_t *name,
05929 dns_rdataset_t *rdataset)
05930 {
05931 isc_result_t result;
05932 dns_rdata_t rdata = DNS_RDATA_INIT;
05933 struct in_addr ina;
05934 struct in6_addr in6a;
05935 isc_netaddr_t netaddr;
05936 char addrbuf[ISC_NETADDR_FORMATSIZE];
05937 char namebuf[DNS_NAME_FORMATSIZE];
05938 char classbuf[64];
05939 char typebuf[64];
05940 int match;
05941
05942
05943 if (view->denyansweracl == NULL)
05944 return (ISC_TRUE);
05945
05946
05947
05948
05949
05950 if (view->answeracl_exclude != NULL) {
05951 dns_rbtnode_t *node = NULL;
05952
05953 result = dns_rbt_findnode(view->answeracl_exclude, name, NULL,
05954 &node, NULL, 0, NULL, NULL);
05955
05956 if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH)
05957 return (ISC_TRUE);
05958 }
05959
05960
05961
05962
05963
05964
05965 for (result = dns_rdataset_first(rdataset);
05966 result == ISC_R_SUCCESS;
05967 result = dns_rdataset_next(rdataset)) {
05968 dns_rdata_reset(&rdata);
05969 dns_rdataset_current(rdataset, &rdata);
05970 if (rdataset->type == dns_rdatatype_a) {
05971 INSIST(rdata.length == sizeof(ina.s_addr));
05972 memmove(&ina.s_addr, rdata.data, sizeof(ina.s_addr));
05973 isc_netaddr_fromin(&netaddr, &ina);
05974 } else {
05975 INSIST(rdata.length == sizeof(in6a.s6_addr));
05976 memmove(in6a.s6_addr, rdata.data, sizeof(in6a.s6_addr));
05977 isc_netaddr_fromin6(&netaddr, &in6a);
05978 }
05979
05980 result = dns_acl_match(&netaddr, NULL, view->denyansweracl,
05981 &view->aclenv, &match, NULL);
05982
05983 if (result == ISC_R_SUCCESS && match > 0) {
05984 isc_netaddr_format(&netaddr, addrbuf, sizeof(addrbuf));
05985 dns_name_format(name, namebuf, sizeof(namebuf));
05986 dns_rdatatype_format(rdataset->type, typebuf,
05987 sizeof(typebuf));
05988 dns_rdataclass_format(rdataset->rdclass, classbuf,
05989 sizeof(classbuf));
05990 isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER,
05991 DNS_LOGMODULE_RESOLVER, ISC_LOG_NOTICE,
05992 "answer address %s denied for %s/%s/%s",
05993 addrbuf, namebuf, typebuf, classbuf);
05994 return (ISC_FALSE);
05995 }
05996 }
05997
05998 return (ISC_TRUE);
05999 }
06000
06001 static isc_boolean_t
06002 is_answertarget_allowed(dns_view_t *view, dns_name_t *name,
06003 dns_rdatatype_t type, dns_name_t *tname,
06004 dns_name_t *domain)
06005 {
06006 isc_result_t result;
06007 dns_rbtnode_t *node = NULL;
06008 char qnamebuf[DNS_NAME_FORMATSIZE];
06009 char tnamebuf[DNS_NAME_FORMATSIZE];
06010 char classbuf[64];
06011 char typebuf[64];
06012
06013
06014 if (view->denyanswernames == NULL)
06015 return (ISC_TRUE);
06016
06017
06018
06019
06020
06021 if (view->answernames_exclude != NULL) {
06022 result = dns_rbt_findnode(view->answernames_exclude, name, NULL,
06023 &node, NULL, 0, NULL, NULL);
06024 if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH)
06025 return (ISC_TRUE);
06026 }
06027
06028
06029
06030
06031 if (dns_name_issubdomain(tname, domain))
06032 return (ISC_TRUE);
06033
06034
06035
06036
06037 result = dns_rbt_findnode(view->denyanswernames, tname, NULL, &node,
06038 NULL, 0, NULL, NULL);
06039 if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH) {
06040 dns_name_format(name, qnamebuf, sizeof(qnamebuf));
06041 dns_name_format(tname, tnamebuf, sizeof(tnamebuf));
06042 dns_rdatatype_format(type, typebuf, sizeof(typebuf));
06043 dns_rdataclass_format(view->rdclass, classbuf,
06044 sizeof(classbuf));
06045 isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER,
06046 DNS_LOGMODULE_RESOLVER, ISC_LOG_NOTICE,
06047 "%s target %s denied for %s/%s",
06048 typebuf, tnamebuf, qnamebuf, classbuf);
06049 return (ISC_FALSE);
06050 }
06051
06052 return (ISC_TRUE);
06053 }
06054
06055 static void
06056 trim_ns_ttl(fetchctx_t *fctx, dns_name_t *name, dns_rdataset_t *rdataset) {
06057 char ns_namebuf[DNS_NAME_FORMATSIZE];
06058 char namebuf[DNS_NAME_FORMATSIZE];
06059 char tbuf[DNS_RDATATYPE_FORMATSIZE];
06060
06061 if (fctx->ns_ttl_ok && rdataset->ttl > fctx->ns_ttl) {
06062 dns_name_format(name, ns_namebuf, sizeof(ns_namebuf));
06063 dns_name_format(&fctx->name, namebuf, sizeof(namebuf));
06064 dns_rdatatype_format(fctx->type, tbuf, sizeof(tbuf));
06065
06066 isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER,
06067 DNS_LOGMODULE_RESOLVER, ISC_LOG_DEBUG(10),
06068 "fctx %p: trimming ttl of %s/NS for %s/%s: "
06069 "%u -> %u", fctx, ns_namebuf, namebuf, tbuf,
06070 rdataset->ttl, fctx->ns_ttl);
06071 rdataset->ttl = fctx->ns_ttl;
06072 }
06073 }
06074
06075
06076
06077
06078
06079
06080
06081
06082 #define LOOK_FOR_NS_IN_ANSWER 0x1
06083 #define LOOK_FOR_GLUE_IN_ANSWER 0x2
06084
06085 static isc_result_t
06086 noanswer_response(fetchctx_t *fctx, dns_name_t *oqname,
06087 unsigned int look_in_options)
06088 {
06089 isc_result_t result;
06090 dns_message_t *message;
06091 dns_name_t *name, *qname, *ns_name, *soa_name, *ds_name, *save_name;
06092 dns_rdataset_t *rdataset, *ns_rdataset;
06093 isc_boolean_t aa, negative_response;
06094 dns_rdatatype_t type, save_type;
06095 dns_section_t section;
06096
06097 FCTXTRACE("noanswer_response");
06098
06099 if ((look_in_options & LOOK_FOR_NS_IN_ANSWER) != 0) {
06100 INSIST(fctx->type == dns_rdatatype_ns);
06101 section = DNS_SECTION_ANSWER;
06102 } else
06103 section = DNS_SECTION_AUTHORITY;
06104
06105 message = fctx->rmessage;
06106
06107
06108
06109
06110 if (oqname == NULL) {
06111
06112
06113
06114
06115 if ((message->flags & DNS_MESSAGEFLAG_AA) != 0)
06116 aa = ISC_TRUE;
06117 else
06118 aa = ISC_FALSE;
06119 qname = &fctx->name;
06120 } else {
06121
06122
06123
06124
06125 qname = oqname;
06126 aa = ISC_FALSE;
06127
06128
06129
06130
06131
06132
06133
06134
06135 if (!dns_name_issubdomain(qname, &fctx->domain))
06136 return (ISC_R_SUCCESS);
06137 }
06138
06139
06140
06141
06142
06143
06144
06145
06146
06147
06148 negative_response = ISC_FALSE;
06149 if (message->rcode == dns_rcode_nxdomain ||
06150 (message->counts[DNS_SECTION_ANSWER] == 0 &&
06151 message->counts[DNS_SECTION_AUTHORITY] == 0))
06152 negative_response = ISC_TRUE;
06153
06154
06155
06156
06157 ns_name = NULL;
06158 ns_rdataset = NULL;
06159 soa_name = NULL;
06160 ds_name = NULL;
06161 save_name = NULL;
06162 save_type = dns_rdatatype_none;
06163 result = dns_message_firstname(message, section);
06164 while (result == ISC_R_SUCCESS) {
06165 name = NULL;
06166 dns_message_currentname(message, section, &name);
06167 if (dns_name_issubdomain(name, &fctx->domain)) {
06168
06169
06170
06171 for (rdataset = ISC_LIST_HEAD(name->list);
06172 rdataset != NULL;
06173 rdataset = ISC_LIST_NEXT(rdataset, link)) {
06174 type = rdataset->type;
06175 if (type == dns_rdatatype_rrsig)
06176 type = rdataset->covers;
06177 if (((type == dns_rdatatype_ns ||
06178 type == dns_rdatatype_soa) &&
06179 !dns_name_issubdomain(qname, name))) {
06180 char qbuf[DNS_NAME_FORMATSIZE];
06181 char nbuf[DNS_NAME_FORMATSIZE];
06182 char tbuf[DNS_RDATATYPE_FORMATSIZE];
06183 dns_rdatatype_format(type, tbuf,
06184 sizeof(tbuf));
06185 dns_name_format(name, nbuf,
06186 sizeof(nbuf));
06187 dns_name_format(qname, qbuf,
06188 sizeof(qbuf));
06189 log_formerr(fctx,
06190 "unrelated %s %s in "
06191 "%s authority section",
06192 tbuf, nbuf, qbuf);
06193 goto nextname;
06194 }
06195 if (type == dns_rdatatype_ns) {
06196
06197
06198
06199
06200
06201 if (rdataset->type ==
06202 dns_rdatatype_ns) {
06203 if (ns_name != NULL &&
06204 name != ns_name) {
06205 log_formerr(fctx,
06206 "multiple NS "
06207 "RRsets in "
06208 "authority "
06209 "section");
06210 return (DNS_R_FORMERR);
06211 }
06212 ns_name = name;
06213 ns_rdataset = rdataset;
06214 }
06215 name->attributes |=
06216 DNS_NAMEATTR_CACHE;
06217 rdataset->attributes |=
06218 DNS_RDATASETATTR_CACHE;
06219 rdataset->trust = dns_trust_glue;
06220 }
06221 if (type == dns_rdatatype_soa) {
06222
06223
06224
06225
06226
06227 if (rdataset->type ==
06228 dns_rdatatype_soa) {
06229 if (soa_name != NULL &&
06230 name != soa_name) {
06231 log_formerr(fctx,
06232 "multiple SOA "
06233 "RRs in "
06234 "authority "
06235 "section");
06236 return (DNS_R_FORMERR);
06237 }
06238 soa_name = name;
06239 }
06240 name->attributes |=
06241 DNS_NAMEATTR_NCACHE;
06242 rdataset->attributes |=
06243 DNS_RDATASETATTR_NCACHE;
06244 if (aa)
06245 rdataset->trust =
06246 dns_trust_authauthority;
06247 else if (ISFORWARDER(fctx->addrinfo))
06248 rdataset->trust =
06249 dns_trust_answer;
06250 else
06251 rdataset->trust =
06252 dns_trust_additional;
06253 }
06254 }
06255 }
06256 nextname:
06257 result = dns_message_nextname(message, section);
06258 if (result == ISC_R_NOMORE)
06259 break;
06260 else if (result != ISC_R_SUCCESS)
06261 return (result);
06262 }
06263
06264 log_ns_ttl(fctx, "noanswer_response");
06265
06266 if (ns_rdataset != NULL && dns_name_equal(&fctx->domain, ns_name) &&
06267 !dns_name_equal(ns_name, dns_rootname))
06268 trim_ns_ttl(fctx, ns_name, ns_rdataset);
06269
06270
06271
06272
06273
06274
06275
06276
06277 if (soa_name != NULL)
06278 negative_response = ISC_TRUE;
06279
06280 result = dns_message_firstname(message, section);
06281 while (result == ISC_R_SUCCESS) {
06282 name = NULL;
06283 dns_message_currentname(message, section, &name);
06284 if (dns_name_issubdomain(name, &fctx->domain)) {
06285 for (rdataset = ISC_LIST_HEAD(name->list);
06286 rdataset != NULL;
06287 rdataset = ISC_LIST_NEXT(rdataset, link)) {
06288 type = rdataset->type;
06289 if (type == dns_rdatatype_rrsig)
06290 type = rdataset->covers;
06291 if (type == dns_rdatatype_nsec ||
06292 type == dns_rdatatype_nsec3) {
06293
06294
06295
06296 if (negative_response) {
06297 name->attributes |=
06298 DNS_NAMEATTR_NCACHE;
06299 rdataset->attributes |=
06300 DNS_RDATASETATTR_NCACHE;
06301 } else if (type == dns_rdatatype_nsec) {
06302 name->attributes |=
06303 DNS_NAMEATTR_CACHE;
06304 rdataset->attributes |=
06305 DNS_RDATASETATTR_CACHE;
06306 }
06307 if (aa)
06308 rdataset->trust =
06309 dns_trust_authauthority;
06310 else if (ISFORWARDER(fctx->addrinfo))
06311 rdataset->trust =
06312 dns_trust_answer;
06313 else
06314 rdataset->trust =
06315 dns_trust_additional;
06316
06317
06318
06319
06320 } else if (type == dns_rdatatype_ds) {
06321
06322
06323
06324
06325
06326
06327
06328 if (ns_name == NULL) {
06329 log_formerr(fctx,
06330 "DS with no "
06331 "referral");
06332 return (DNS_R_FORMERR);
06333 }
06334 if (rdataset->type ==
06335 dns_rdatatype_ds) {
06336 if (ds_name != NULL &&
06337 name != ds_name) {
06338 log_formerr(fctx,
06339 "DS doesn't "
06340 "match "
06341 "referral "
06342 "(NS)");
06343 return (DNS_R_FORMERR);
06344 }
06345 ds_name = name;
06346 }
06347 name->attributes |=
06348 DNS_NAMEATTR_CACHE;
06349 rdataset->attributes |=
06350 DNS_RDATASETATTR_CACHE;
06351 if (aa)
06352 rdataset->trust =
06353 dns_trust_authauthority;
06354 else if (ISFORWARDER(fctx->addrinfo))
06355 rdataset->trust =
06356 dns_trust_answer;
06357 else
06358 rdataset->trust =
06359 dns_trust_additional;
06360 }
06361 }
06362 } else {
06363 save_name = name;
06364 save_type = ISC_LIST_HEAD(name->list)->type;
06365 }
06366 result = dns_message_nextname(message, section);
06367 if (result == ISC_R_NOMORE)
06368 break;
06369 else if (result != ISC_R_SUCCESS)
06370 return (result);
06371 }
06372
06373
06374
06375
06376 if (negative_response && message->rcode == dns_rcode_noerror &&
06377 fctx->type == dns_rdatatype_ds && soa_name != NULL &&
06378 dns_name_equal(soa_name, qname) &&
06379 !dns_name_equal(qname, dns_rootname))
06380 return (DNS_R_CHASEDSSERVERS);
06381
06382
06383
06384
06385 if (!negative_response && ns_name == NULL) {
06386
06387
06388
06389 if (oqname != NULL) {
06390
06391
06392
06393
06394
06395 return (ISC_R_SUCCESS);
06396 } else {
06397
06398
06399
06400 if (save_name == NULL) {
06401 log_formerr(fctx, "invalid response");
06402 return (DNS_R_FORMERR);
06403 }
06404 if (!dns_name_issubdomain(save_name, &fctx->domain)) {
06405 char nbuf[DNS_NAME_FORMATSIZE];
06406 char dbuf[DNS_NAME_FORMATSIZE];
06407 char tbuf[DNS_RDATATYPE_FORMATSIZE];
06408
06409 dns_rdatatype_format(save_type, tbuf,
06410 sizeof(tbuf));
06411 dns_name_format(save_name, nbuf, sizeof(nbuf));
06412 dns_name_format(&fctx->domain, dbuf,
06413 sizeof(dbuf));
06414
06415 log_formerr(fctx, "Name %s (%s) not subdomain"
06416 " of zone %s -- invalid response",
06417 nbuf, tbuf, dbuf);
06418 } else {
06419 log_formerr(fctx, "invalid response");
06420 }
06421 return (DNS_R_FORMERR);
06422 }
06423 }
06424
06425
06426
06427
06428 if (ns_name != NULL && soa_name != NULL && ns_name != soa_name) {
06429 log_formerr(fctx, "NS/SOA mismatch");
06430 return (DNS_R_FORMERR);
06431 }
06432
06433
06434
06435
06436
06437 if (!negative_response && ns_name != NULL && oqname == NULL) {
06438
06439
06440
06441
06442
06443
06444 if (dns_name_equal(ns_name, &fctx->domain)) {
06445 log_formerr(fctx, "non-improving referral");
06446 return (DNS_R_FORMERR);
06447 }
06448
06449
06450
06451
06452
06453 if (! dns_name_issubdomain(&fctx->name, ns_name)) {
06454
06455 log_formerr(fctx, "referral to non-parent");
06456 FCTXTRACE("referral to non-parent");
06457 return (DNS_R_FORMERR);
06458 }
06459
06460
06461
06462
06463
06464
06465 INSIST(ns_rdataset != NULL);
06466 fctx->attributes |= FCTX_ATTR_GLUING;
06467 (void)dns_rdataset_additionaldata(ns_rdataset, check_related,
06468 fctx);
06469 #if CHECK_FOR_GLUE_IN_ANSWER
06470
06471
06472
06473
06474
06475
06476
06477 if ((look_in_options & LOOK_FOR_GLUE_IN_ANSWER) != 0 &&
06478 (fctx->type == dns_rdatatype_aaaa ||
06479 fctx->type == dns_rdatatype_a))
06480 (void)dns_rdataset_additionaldata(ns_rdataset,
06481 check_answer, fctx);
06482 #endif
06483 fctx->attributes &= ~FCTX_ATTR_GLUING;
06484
06485
06486
06487
06488
06489
06490
06491 if (ns_rdataset->ttl == 0)
06492 ns_rdataset->ttl = 1;
06493
06494
06495
06496
06497
06498
06499 INSIST(dns_name_countlabels(&fctx->domain) > 0);
06500 dns_name_free(&fctx->domain, fctx->mctx);
06501 if (dns_rdataset_isassociated(&fctx->nameservers))
06502 dns_rdataset_disassociate(&fctx->nameservers);
06503 dns_name_init(&fctx->domain, NULL);
06504 result = dns_name_dup(ns_name, fctx->mctx, &fctx->domain);
06505 if (result != ISC_R_SUCCESS)
06506 return (result);
06507 fctx->attributes |= FCTX_ATTR_WANTCACHE;
06508 fctx->ns_ttl_ok = ISC_FALSE;
06509 log_ns_ttl(fctx, "DELEGATION");
06510 return (DNS_R_DELEGATION);
06511 }
06512
06513
06514
06515
06516
06517 if (ns_name != NULL)
06518 ns_name->attributes &= ~DNS_NAMEATTR_CACHE;
06519
06520 if (negative_response && oqname == NULL)
06521 fctx->attributes |= FCTX_ATTR_WANTNCACHE;
06522
06523 return (ISC_R_SUCCESS);
06524 }
06525
06526 static isc_result_t
06527 answer_response(fetchctx_t *fctx) {
06528 isc_result_t result;
06529 dns_message_t *message;
06530 dns_name_t *name, *qname, tname, *ns_name;
06531 dns_rdataset_t *rdataset, *ns_rdataset;
06532 isc_boolean_t done, external, chaining, aa, found, want_chaining;
06533 isc_boolean_t have_answer, found_cname, found_type, wanted_chaining;
06534 unsigned int aflag;
06535 dns_rdatatype_t type;
06536 dns_fixedname_t dname, fqname;
06537 dns_view_t *view;
06538
06539 FCTXTRACE("answer_response");
06540
06541 message = fctx->rmessage;
06542
06543
06544
06545
06546
06547
06548 done = ISC_FALSE;
06549 found_cname = ISC_FALSE;
06550 found_type = ISC_FALSE;
06551 chaining = ISC_FALSE;
06552 have_answer = ISC_FALSE;
06553 want_chaining = ISC_FALSE;
06554 POST(want_chaining);
06555 if ((message->flags & DNS_MESSAGEFLAG_AA) != 0)
06556 aa = ISC_TRUE;
06557 else
06558 aa = ISC_FALSE;
06559 qname = &fctx->name;
06560 type = fctx->type;
06561 view = fctx->res->view;
06562 result = dns_message_firstname(message, DNS_SECTION_ANSWER);
06563 while (!done && result == ISC_R_SUCCESS) {
06564 name = NULL;
06565 dns_message_currentname(message, DNS_SECTION_ANSWER, &name);
06566 external = ISC_TF(!dns_name_issubdomain(name, &fctx->domain));
06567 if (dns_name_equal(name, qname)) {
06568 wanted_chaining = ISC_FALSE;
06569 for (rdataset = ISC_LIST_HEAD(name->list);
06570 rdataset != NULL;
06571 rdataset = ISC_LIST_NEXT(rdataset, link)) {
06572 found = ISC_FALSE;
06573 want_chaining = ISC_FALSE;
06574 aflag = 0;
06575 if (rdataset->type == dns_rdatatype_nsec3) {
06576
06577
06578
06579
06580 log_formerr(fctx, "NSEC3 in answer");
06581 return (DNS_R_FORMERR);
06582 }
06583
06584
06585
06586
06587
06588 if ((rdataset->type == dns_rdatatype_a ||
06589 rdataset->type == dns_rdatatype_aaaa) &&
06590 !is_answeraddress_allowed(view, name,
06591 rdataset)) {
06592 return (DNS_R_SERVFAIL);
06593 }
06594
06595 if (rdataset->type == type && !found_cname) {
06596
06597
06598
06599 found = ISC_TRUE;
06600 found_type = ISC_TRUE;
06601 done = ISC_TRUE;
06602 aflag = DNS_RDATASETATTR_ANSWER;
06603 } else if (type == dns_rdatatype_any) {
06604
06605
06606
06607
06608
06609 found = ISC_TRUE;
06610 aflag = DNS_RDATASETATTR_ANSWER;
06611 } else if (rdataset->type == dns_rdatatype_rrsig
06612 && rdataset->covers == type
06613 && !found_cname) {
06614
06615
06616
06617
06618 found = ISC_TRUE;
06619 found_type = ISC_TRUE;
06620 aflag = DNS_RDATASETATTR_ANSWERSIG;
06621 } else if (rdataset->type ==
06622 dns_rdatatype_cname
06623 && !found_type) {
06624
06625
06626
06627
06628
06629
06630
06631
06632 if (type == dns_rdatatype_rrsig ||
06633 type == dns_rdatatype_key ||
06634 type == dns_rdatatype_nsec) {
06635 char buf[DNS_RDATATYPE_FORMATSIZE];
06636 dns_rdatatype_format(fctx->type,
06637 buf, sizeof(buf));
06638 log_formerr(fctx,
06639 "CNAME response "
06640 "for %s RR", buf);
06641 return (DNS_R_FORMERR);
06642 }
06643 found = ISC_TRUE;
06644 found_cname = ISC_TRUE;
06645 want_chaining = ISC_TRUE;
06646 aflag = DNS_RDATASETATTR_ANSWER;
06647 result = cname_target(rdataset,
06648 &tname);
06649 if (result != ISC_R_SUCCESS)
06650 return (result);
06651
06652 if (!is_answertarget_allowed(view,
06653 name,
06654 rdataset->type,
06655 &tname,
06656 &fctx->domain)) {
06657 return (DNS_R_SERVFAIL);
06658 }
06659 } else if (rdataset->type == dns_rdatatype_rrsig
06660 && rdataset->covers ==
06661 dns_rdatatype_cname
06662 && !found_type) {
06663
06664
06665
06666
06667 found = ISC_TRUE;
06668 found_cname = ISC_TRUE;
06669 aflag = DNS_RDATASETATTR_ANSWERSIG;
06670 }
06671
06672 if (found) {
06673
06674
06675
06676
06677 name->attributes |=
06678 DNS_NAMEATTR_CACHE;
06679 rdataset->attributes |=
06680 DNS_RDATASETATTR_CACHE;
06681 rdataset->trust = dns_trust_answer;
06682 if (!chaining) {
06683
06684
06685
06686
06687
06688
06689
06690 INSIST(!external);
06691 if (aflag ==
06692 DNS_RDATASETATTR_ANSWER)
06693 have_answer = ISC_TRUE;
06694 name->attributes |=
06695 DNS_NAMEATTR_ANSWER;
06696 rdataset->attributes |= aflag;
06697 if (aa)
06698 rdataset->trust =
06699 dns_trust_authanswer;
06700 } else if (external) {
06701
06702
06703
06704
06705
06706 rdataset->attributes |=
06707 DNS_RDATASETATTR_EXTERNAL;
06708 }
06709
06710
06711
06712
06713
06714 (void)dns_rdataset_additionaldata(
06715 rdataset,
06716 check_related,
06717 fctx);
06718
06719
06720
06721
06722 if (want_chaining) {
06723 wanted_chaining = ISC_TRUE;
06724 name->attributes |=
06725 DNS_NAMEATTR_CHAINING;
06726 rdataset->attributes |=
06727 DNS_RDATASETATTR_CHAINING;
06728 qname = &tname;
06729 }
06730 }
06731
06732
06733
06734
06735 }
06736
06737
06738
06739
06740
06741
06742
06743
06744
06745
06746
06747 if (wanted_chaining)
06748 chaining = ISC_TRUE;
06749 } else {
06750
06751
06752
06753
06754 wanted_chaining = ISC_FALSE;
06755 for (rdataset = ISC_LIST_HEAD(name->list);
06756 rdataset != NULL;
06757 rdataset = ISC_LIST_NEXT(rdataset, link)) {
06758 isc_boolean_t found_dname = ISC_FALSE;
06759 dns_name_t *dname_name;
06760
06761 found = ISC_FALSE;
06762 aflag = 0;
06763 if (rdataset->type == dns_rdatatype_dname) {
06764
06765
06766
06767
06768
06769
06770
06771 if (!chaining && external) {
06772 log_formerr(fctx,
06773 "external DNAME");
06774 return (DNS_R_FORMERR);
06775 }
06776 found = ISC_TRUE;
06777 want_chaining = ISC_TRUE;
06778 POST(want_chaining);
06779 aflag = DNS_RDATASETATTR_ANSWER;
06780 result = dname_target(fctx, rdataset,
06781 qname, name,
06782 &dname);
06783 if (result == ISC_R_NOSPACE) {
06784
06785
06786
06787
06788
06789 want_chaining = ISC_FALSE;
06790 POST(want_chaining);
06791 } else if (result != ISC_R_SUCCESS)
06792 return (result);
06793 else
06794 found_dname = ISC_TRUE;
06795
06796 dname_name = dns_fixedname_name(&dname);
06797 if (!is_answertarget_allowed(view,
06798 qname,
06799 rdataset->type,
06800 dname_name,
06801 &fctx->domain)) {
06802 return (DNS_R_SERVFAIL);
06803 }
06804 } else if (rdataset->type == dns_rdatatype_rrsig
06805 && rdataset->covers ==
06806 dns_rdatatype_dname) {
06807
06808
06809
06810
06811 found = ISC_TRUE;
06812 aflag = DNS_RDATASETATTR_ANSWERSIG;
06813 }
06814
06815 if (found) {
06816
06817
06818
06819
06820 name->attributes |=
06821 DNS_NAMEATTR_CACHE;
06822 rdataset->attributes |=
06823 DNS_RDATASETATTR_CACHE;
06824 rdataset->trust = dns_trust_answer;
06825 if (!chaining) {
06826
06827
06828
06829
06830
06831 INSIST(!external);
06832 if (aflag ==
06833 DNS_RDATASETATTR_ANSWER)
06834 have_answer = ISC_TRUE;
06835 name->attributes |=
06836 DNS_NAMEATTR_ANSWER;
06837 rdataset->attributes |= aflag;
06838 if (aa)
06839 rdataset->trust =
06840 dns_trust_authanswer;
06841 } else if (external) {
06842 rdataset->attributes |=
06843 DNS_RDATASETATTR_EXTERNAL;
06844 }
06845
06846
06847
06848
06849 if (found_dname) {
06850
06851
06852
06853
06854
06855
06856
06857
06858
06859
06860
06861 dns_fixedname_init(&fqname);
06862 result = dns_name_copy(
06863 dns_fixedname_name(&dname),
06864 dns_fixedname_name(&fqname),
06865 NULL);
06866 if (result != ISC_R_SUCCESS)
06867 return (result);
06868 wanted_chaining = ISC_TRUE;
06869 name->attributes |=
06870 DNS_NAMEATTR_CHAINING;
06871 rdataset->attributes |=
06872 DNS_RDATASETATTR_CHAINING;
06873 qname = dns_fixedname_name(
06874 &fqname);
06875 }
06876 }
06877 }
06878 if (wanted_chaining)
06879 chaining = ISC_TRUE;
06880 }
06881 result = dns_message_nextname(message, DNS_SECTION_ANSWER);
06882 }
06883 if (result == ISC_R_NOMORE)
06884 result = ISC_R_SUCCESS;
06885 if (result != ISC_R_SUCCESS)
06886 return (result);
06887
06888
06889
06890
06891 if (!have_answer) {
06892 log_formerr(fctx, "reply has no answer");
06893 return (DNS_R_FORMERR);
06894 }
06895
06896
06897
06898
06899 fctx->attributes |= FCTX_ATTR_WANTCACHE;
06900
06901
06902
06903
06904 if (chaining) {
06905
06906
06907
06908
06909
06910
06911 return (noanswer_response(fctx, qname, 0));
06912 }
06913
06914
06915
06916
06917
06918 if (message->rcode != dns_rcode_noerror) {
06919 log_formerr(fctx, "CNAME/DNAME chain complete, but RCODE "
06920 "indicates error");
06921 return (DNS_R_FORMERR);
06922 }
06923
06924
06925
06926
06927
06928
06929
06930 done = ISC_FALSE;
06931 ns_name = NULL;
06932 ns_rdataset = NULL;
06933 result = dns_message_firstname(message, DNS_SECTION_AUTHORITY);
06934 while (!done && result == ISC_R_SUCCESS) {
06935 name = NULL;
06936 dns_message_currentname(message, DNS_SECTION_AUTHORITY, &name);
06937 external = ISC_TF(!dns_name_issubdomain(name, &fctx->domain));
06938 if (!external) {
06939
06940
06941
06942
06943 for (rdataset = ISC_LIST_HEAD(name->list);
06944 rdataset != NULL;
06945 rdataset = ISC_LIST_NEXT(rdataset, link)) {
06946 if (rdataset->type == dns_rdatatype_ns ||
06947 (rdataset->type == dns_rdatatype_rrsig &&
06948 rdataset->covers == dns_rdatatype_ns)) {
06949 name->attributes |=
06950 DNS_NAMEATTR_CACHE;
06951 rdataset->attributes |=
06952 DNS_RDATASETATTR_CACHE;
06953 if (aa && !chaining)
06954 rdataset->trust =
06955 dns_trust_authauthority;
06956 else
06957 rdataset->trust =
06958 dns_trust_additional;
06959
06960 if (rdataset->type == dns_rdatatype_ns) {
06961 ns_name = name;
06962 ns_rdataset = rdataset;
06963 }
06964
06965
06966
06967
06968 (void)dns_rdataset_additionaldata(
06969 rdataset,
06970 check_related,
06971 fctx);
06972 done = ISC_TRUE;
06973 }
06974 }
06975 }
06976 result = dns_message_nextname(message, DNS_SECTION_AUTHORITY);
06977 }
06978 if (result == ISC_R_NOMORE)
06979 result = ISC_R_SUCCESS;
06980
06981 log_ns_ttl(fctx, "answer_response");
06982
06983 if (ns_rdataset != NULL && dns_name_equal(&fctx->domain, ns_name) &&
06984 !dns_name_equal(ns_name, dns_rootname))
06985 trim_ns_ttl(fctx, ns_name, ns_rdataset);
06986
06987 return (result);
06988 }
06989
06990 static void
06991 fctx_increference(fetchctx_t *fctx) {
06992 REQUIRE(VALID_FCTX(fctx));
06993
06994 LOCK(&fctx->res->buckets[fctx->bucketnum].lock);
06995 fctx->references++;
06996 UNLOCK(&fctx->res->buckets[fctx->bucketnum].lock);
06997 }
06998
06999 static isc_boolean_t
07000 fctx_decreference(fetchctx_t *fctx) {
07001 isc_boolean_t bucket_empty = ISC_FALSE;
07002
07003 REQUIRE(VALID_FCTX(fctx));
07004
07005 INSIST(fctx->references > 0);
07006 fctx->references--;
07007 if (fctx->references == 0) {
07008
07009
07010
07011 if (fctx->pending == 0 && fctx->nqueries == 0 &&
07012 ISC_LIST_EMPTY(fctx->validators) && SHUTTINGDOWN(fctx)) {
07013
07014
07015
07016
07017 bucket_empty = fctx_unlink(fctx);
07018 fctx_destroy(fctx);
07019 } else {
07020
07021
07022
07023 fctx_shutdown(fctx);
07024 }
07025 }
07026 return (bucket_empty);
07027 }
07028
07029 static void
07030 resume_dslookup(isc_task_t *task, isc_event_t *event) {
07031 dns_fetchevent_t *fevent;
07032 dns_resolver_t *res;
07033 fetchctx_t *fctx;
07034 isc_result_t result;
07035 isc_boolean_t bucket_empty;
07036 isc_boolean_t locked = ISC_FALSE;
07037 unsigned int bucketnum;
07038 dns_rdataset_t nameservers;
07039 dns_fixedname_t fixed;
07040 dns_name_t *domain;
07041
07042 REQUIRE(event->ev_type == DNS_EVENT_FETCHDONE);
07043 fevent = (dns_fetchevent_t *)event;
07044 fctx = event->ev_arg;
07045 REQUIRE(VALID_FCTX(fctx));
07046 res = fctx->res;
07047
07048 UNUSED(task);
07049 FCTXTRACE("resume_dslookup");
07050
07051 if (fevent->node != NULL)
07052 dns_db_detachnode(fevent->db, &fevent->node);
07053 if (fevent->db != NULL)
07054 dns_db_detach(&fevent->db);
07055
07056 dns_rdataset_init(&nameservers);
07057
07058 bucketnum = fctx->bucketnum;
07059 if (fevent->result == ISC_R_CANCELED) {
07060 dns_resolver_destroyfetch(&fctx->nsfetch);
07061 fctx_done(fctx, ISC_R_CANCELED, __LINE__);
07062 } else if (fevent->result == ISC_R_SUCCESS) {
07063
07064 FCTXTRACE("resuming DS lookup");
07065
07066 dns_resolver_destroyfetch(&fctx->nsfetch);
07067 if (dns_rdataset_isassociated(&fctx->nameservers))
07068 dns_rdataset_disassociate(&fctx->nameservers);
07069 dns_rdataset_clone(fevent->rdataset, &fctx->nameservers);
07070 fctx->ns_ttl = fctx->nameservers.ttl;
07071 fctx->ns_ttl_ok = ISC_TRUE;
07072 log_ns_ttl(fctx, "resume_dslookup");
07073 dns_name_free(&fctx->domain, fctx->mctx);
07074 dns_name_init(&fctx->domain, NULL);
07075 result = dns_name_dup(&fctx->nsname, fctx->mctx, &fctx->domain);
07076 if (result != ISC_R_SUCCESS) {
07077 fctx_done(fctx, DNS_R_SERVFAIL, __LINE__);
07078 goto cleanup;
07079 }
07080
07081
07082
07083 fctx_try(fctx, ISC_TRUE, ISC_FALSE);
07084 } else {
07085 unsigned int n;
07086 dns_rdataset_t *nsrdataset = NULL;
07087
07088
07089
07090
07091 dns_fixedname_init(&fixed);
07092 domain = dns_fixedname_name(&fixed);
07093 dns_name_copy(&fctx->nsfetch->private->domain, domain, NULL);
07094 if (dns_name_equal(&fctx->nsname, domain)) {
07095 fctx_done(fctx, DNS_R_SERVFAIL, __LINE__);
07096 dns_resolver_destroyfetch(&fctx->nsfetch);
07097 goto cleanup;
07098 }
07099 if (dns_rdataset_isassociated(
07100 &fctx->nsfetch->private->nameservers)) {
07101 dns_rdataset_clone(
07102 &fctx->nsfetch->private->nameservers,
07103 &nameservers);
07104 nsrdataset = &nameservers;
07105 } else
07106 domain = NULL;
07107 dns_resolver_destroyfetch(&fctx->nsfetch);
07108 n = dns_name_countlabels(&fctx->nsname);
07109 dns_name_getlabelsequence(&fctx->nsname, 1, n - 1,
07110 &fctx->nsname);
07111
07112 if (dns_rdataset_isassociated(fevent->rdataset))
07113 dns_rdataset_disassociate(fevent->rdataset);
07114 FCTXTRACE("continuing to look for parent's NS records");
07115 result = dns_resolver_createfetch(fctx->res, &fctx->nsname,
07116 dns_rdatatype_ns, domain,
07117 nsrdataset, NULL,
07118 fctx->options, task,
07119 resume_dslookup, fctx,
07120 &fctx->nsrrset, NULL,
07121 &fctx->nsfetch);
07122 if (result != ISC_R_SUCCESS)
07123 fctx_done(fctx, result, __LINE__);
07124 else {
07125 LOCK(&res->buckets[bucketnum].lock);
07126 locked = ISC_TRUE;
07127 fctx->references++;
07128 }
07129 }
07130
07131 cleanup:
07132 if (dns_rdataset_isassociated(&nameservers))
07133 dns_rdataset_disassociate(&nameservers);
07134 if (dns_rdataset_isassociated(fevent->rdataset))
07135 dns_rdataset_disassociate(fevent->rdataset);
07136 INSIST(fevent->sigrdataset == NULL);
07137 isc_event_free(&event);
07138 if (!locked)
07139 LOCK(&res->buckets[bucketnum].lock);
07140 bucket_empty = fctx_decreference(fctx);
07141 UNLOCK(&res->buckets[bucketnum].lock);
07142 if (bucket_empty)
07143 empty_bucket(res);
07144 }
07145
07146 static inline void
07147 checknamessection(dns_message_t *message, dns_section_t section) {
07148 isc_result_t result;
07149 dns_name_t *name;
07150 dns_rdata_t rdata = DNS_RDATA_INIT;
07151 dns_rdataset_t *rdataset;
07152
07153 for (result = dns_message_firstname(message, section);
07154 result == ISC_R_SUCCESS;
07155 result = dns_message_nextname(message, section))
07156 {
07157 name = NULL;
07158 dns_message_currentname(message, section, &name);
07159 for (rdataset = ISC_LIST_HEAD(name->list);
07160 rdataset != NULL;
07161 rdataset = ISC_LIST_NEXT(rdataset, link)) {
07162 for (result = dns_rdataset_first(rdataset);
07163 result == ISC_R_SUCCESS;
07164 result = dns_rdataset_next(rdataset)) {
07165 dns_rdataset_current(rdataset, &rdata);
07166 if (!dns_rdata_checkowner(name, rdata.rdclass,
07167 rdata.type,
07168 ISC_FALSE) ||
07169 !dns_rdata_checknames(&rdata, name, NULL))
07170 {
07171 rdataset->attributes |=
07172 DNS_RDATASETATTR_CHECKNAMES;
07173 }
07174 dns_rdata_reset(&rdata);
07175 }
07176 }
07177 }
07178 }
07179
07180 static void
07181 checknames(dns_message_t *message) {
07182
07183 checknamessection(message, DNS_SECTION_ANSWER);
07184 checknamessection(message, DNS_SECTION_AUTHORITY);
07185 checknamessection(message, DNS_SECTION_ADDITIONAL);
07186 }
07187
07188
07189
07190
07191 static void
07192 log_nsid(isc_buffer_t *opt, size_t nsid_len, resquery_t *query,
07193 int level, isc_mem_t *mctx)
07194 {
07195 static const char hex[17] = "0123456789abcdef";
07196 char addrbuf[ISC_SOCKADDR_FORMATSIZE];
07197 isc_uint16_t buflen, i;
07198 unsigned char *p, *nsid;
07199 unsigned char *buf = NULL, *pbuf = NULL;
07200
07201
07202 buflen = (isc_uint16_t)nsid_len * 2 + 1;
07203 buf = isc_mem_get(mctx, buflen);
07204 if (buf == NULL)
07205 goto cleanup;
07206 pbuf = isc_mem_get(mctx, nsid_len + 1);
07207 if (pbuf == NULL)
07208 goto cleanup;
07209
07210
07211 p = buf;
07212 nsid = isc_buffer_current(opt);
07213 for (i = 0; i < nsid_len; i++) {
07214 *p++ = hex[(nsid[i] >> 4) & 0xf];
07215 *p++ = hex[nsid[i] & 0xf];
07216 }
07217 *p = '\0';
07218
07219
07220 p = pbuf;
07221 for (i = 0; i < nsid_len; i++) {
07222 if (isprint(nsid[i]))
07223 *p++ = nsid[i];
07224 else
07225 *p++ = '.';
07226 }
07227 *p = '\0';
07228
07229 isc_sockaddr_format(&query->addrinfo->sockaddr, addrbuf,
07230 sizeof(addrbuf));
07231 isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER,
07232 DNS_LOGMODULE_RESOLVER, level,
07233 "received NSID %s (\"%s\") from %s", buf, pbuf, addrbuf);
07234 cleanup:
07235 if (pbuf != NULL)
07236 isc_mem_put(mctx, pbuf, nsid_len + 1);
07237 if (buf != NULL)
07238 isc_mem_put(mctx, buf, buflen);
07239 }
07240
07241 static isc_boolean_t
07242 iscname(fetchctx_t *fctx) {
07243 isc_result_t result;
07244
07245 result = dns_message_findname(fctx->rmessage, DNS_SECTION_ANSWER,
07246 &fctx->name, dns_rdatatype_cname, 0,
07247 NULL, NULL);
07248 return (result == ISC_R_SUCCESS ? ISC_TRUE : ISC_FALSE);
07249 }
07250
07251 static isc_boolean_t
07252 betterreferral(fetchctx_t *fctx) {
07253 isc_result_t result;
07254 dns_name_t *name;
07255 dns_rdataset_t *rdataset;
07256 dns_message_t *message = fctx->rmessage;
07257
07258 for (result = dns_message_firstname(message, DNS_SECTION_AUTHORITY);
07259 result == ISC_R_SUCCESS;
07260 result = dns_message_nextname(message, DNS_SECTION_AUTHORITY)) {
07261 name = NULL;
07262 dns_message_currentname(message, DNS_SECTION_AUTHORITY, &name);
07263 if (!isstrictsubdomain(name, &fctx->domain))
07264 continue;
07265 for (rdataset = ISC_LIST_HEAD(name->list);
07266 rdataset != NULL;
07267 rdataset = ISC_LIST_NEXT(rdataset, link))
07268 if (rdataset->type == dns_rdatatype_ns)
07269 return (ISC_TRUE);
07270 }
07271 return (ISC_FALSE);
07272 }
07273
07274 static void
07275 process_opt(resquery_t *query, dns_rdataset_t *opt) {
07276 dns_rdata_t rdata;
07277 isc_buffer_t optbuf;
07278 isc_result_t result;
07279 isc_uint16_t optcode;
07280 isc_uint16_t optlen;
07281 #ifdef ISC_PLATFORM_USESIT
07282 unsigned char *sit;
07283 dns_adbaddrinfo_t *addrinfo;
07284 unsigned char cookie[8];
07285 #endif
07286
07287 result = dns_rdataset_first(opt);
07288 if (result == ISC_R_SUCCESS) {
07289 dns_rdata_init(&rdata);
07290 dns_rdataset_current(opt, &rdata);
07291 isc_buffer_init(&optbuf, rdata.data, rdata.length);
07292 isc_buffer_add(&optbuf, rdata.length);
07293 while (isc_buffer_remaininglength(&optbuf) >= 4) {
07294 optcode = isc_buffer_getuint16(&optbuf);
07295 optlen = isc_buffer_getuint16(&optbuf);
07296 INSIST(optlen <= isc_buffer_remaininglength(&optbuf));
07297 switch (optcode) {
07298 case DNS_OPT_NSID:
07299 if (query->options & DNS_FETCHOPT_WANTNSID)
07300 log_nsid(&optbuf, optlen, query,
07301 ISC_LOG_DEBUG(3),
07302 query->fctx->res->mctx);
07303 isc_buffer_forward(&optbuf, optlen);
07304 break;
07305 #ifdef ISC_PLATFORM_USESIT
07306 case DNS_OPT_SIT:
07307 sit = isc_buffer_current(&optbuf);
07308 compute_cc(query, cookie, sizeof(cookie));
07309 INSIST(query->fctx->rmessage->sitbad == 0 &&
07310 query->fctx->rmessage->sitok == 0);
07311 if (optlen >= 8U &&
07312 memcmp(cookie, sit, 8) == 0) {
07313 query->fctx->rmessage->sitok = 1;
07314 inc_stats(query->fctx->res,
07315 dns_resstatscounter_sitok);
07316 addrinfo = query->addrinfo;
07317 dns_adb_setsit(query->fctx->adb,
07318 addrinfo, sit, optlen);
07319 } else
07320 query->fctx->rmessage->sitbad = 1;
07321 isc_buffer_forward(&optbuf, optlen);
07322 inc_stats(query->fctx->res,
07323 dns_resstatscounter_sitin);
07324 break;
07325 #endif
07326 default:
07327 isc_buffer_forward(&optbuf, optlen);
07328 break;
07329 }
07330 }
07331 INSIST(isc_buffer_remaininglength(&optbuf) == 0U);
07332 }
07333 }
07334
07335 static void
07336 resquery_response(isc_task_t *task, isc_event_t *event) {
07337 isc_result_t result = ISC_R_SUCCESS;
07338 resquery_t *query = event->ev_arg;
07339 dns_dispatchevent_t *devent = (dns_dispatchevent_t *)event;
07340 isc_boolean_t keep_trying, get_nameservers, resend;
07341 isc_boolean_t truncated;
07342 dns_message_t *message;
07343 dns_rdataset_t *opt;
07344 fetchctx_t *fctx;
07345 dns_name_t *fname;
07346 dns_fixedname_t foundname;
07347 isc_stdtime_t now;
07348 isc_time_t tnow, *finish;
07349 dns_adbaddrinfo_t *addrinfo;
07350 unsigned int options;
07351 unsigned int findoptions;
07352 isc_result_t broken_server;
07353 badnstype_t broken_type = badns_response;
07354 isc_boolean_t no_response;
07355
07356 REQUIRE(VALID_QUERY(query));
07357 fctx = query->fctx;
07358 options = query->options;
07359 REQUIRE(VALID_FCTX(fctx));
07360 REQUIRE(event->ev_type == DNS_EVENT_DISPATCH);
07361
07362 QTRACE("response");
07363
07364 if (isc_sockaddr_pf(&query->addrinfo->sockaddr) == PF_INET)
07365 inc_stats(fctx->res, dns_resstatscounter_responsev4);
07366 else
07367 inc_stats(fctx->res, dns_resstatscounter_responsev6);
07368
07369 (void)isc_timer_touch(fctx->timer);
07370
07371 keep_trying = ISC_FALSE;
07372 broken_server = ISC_R_SUCCESS;
07373 get_nameservers = ISC_FALSE;
07374 resend = ISC_FALSE;
07375 truncated = ISC_FALSE;
07376 finish = NULL;
07377 no_response = ISC_FALSE;
07378
07379 if (fctx->res->exiting) {
07380 result = ISC_R_SHUTTINGDOWN;
07381 FCTXTRACE("resolver shutting down");
07382 goto done;
07383 }
07384
07385 fctx->timeouts = 0;
07386 fctx->timeout = ISC_FALSE;
07387 fctx->addrinfo = query->addrinfo;
07388
07389
07390
07391
07392
07393
07394 TIME_NOW(&tnow);
07395 finish = &tnow;
07396 isc_stdtime_get(&now);
07397
07398
07399
07400
07401 if (devent->result != ISC_R_SUCCESS) {
07402 if (devent->result == ISC_R_EOF &&
07403 (query->options & DNS_FETCHOPT_NOEDNS0) == 0) {
07404
07405
07406
07407
07408
07409 options |= DNS_FETCHOPT_NOEDNS0;
07410 resend = ISC_TRUE;
07411 add_bad_edns(fctx, &query->addrinfo->sockaddr);
07412 } else {
07413
07414
07415
07416 keep_trying = ISC_TRUE;
07417
07418
07419
07420
07421
07422
07423
07424
07425 if (query->exclusivesocket &&
07426 (devent->result == ISC_R_HOSTUNREACH ||
07427 devent->result == ISC_R_NETUNREACH ||
07428 devent->result == ISC_R_CONNREFUSED ||
07429 devent->result == ISC_R_CANCELED)) {
07430 broken_server = devent->result;
07431 broken_type = badns_unreachable;
07432 finish = NULL;
07433 no_response = ISC_TRUE;
07434 }
07435 }
07436 FCTXTRACE3("dispatcher failure", devent->result);
07437 goto done;
07438 }
07439
07440 message = fctx->rmessage;
07441
07442 if (query->tsig != NULL) {
07443 result = dns_message_setquerytsig(message, query->tsig);
07444 if (result != ISC_R_SUCCESS) {
07445 FCTXTRACE3("unable to set query tsig", result);
07446 goto done;
07447 }
07448 }
07449
07450 if (query->tsigkey) {
07451 result = dns_message_settsigkey(message, query->tsigkey);
07452 if (result != ISC_R_SUCCESS) {
07453 FCTXTRACE3("unable to set tsig key", result);
07454 goto done;
07455 }
07456 }
07457
07458 if ((options & DNS_FETCHOPT_TCP) == 0) {
07459 if ((options & DNS_FETCHOPT_NOEDNS0) == 0)
07460 dns_adb_setudpsize(fctx->adb, query->addrinfo,
07461 isc_buffer_usedlength(&devent->buffer));
07462 else
07463 dns_adb_plainresponse(fctx->adb, query->addrinfo);
07464 }
07465 result = dns_message_parse(message, &devent->buffer, 0);
07466 if (result != ISC_R_SUCCESS) {
07467 FCTXTRACE3("message failed to parse", result);
07468 switch (result) {
07469 case ISC_R_UNEXPECTEDEND:
07470 if (!message->question_ok ||
07471 (message->flags & DNS_MESSAGEFLAG_TC) == 0 ||
07472 (options & DNS_FETCHOPT_TCP) != 0) {
07473
07474
07475
07476
07477
07478
07479
07480
07481
07482 if ((query->options & DNS_FETCHOPT_NOEDNS0)
07483 == 0) {
07484
07485
07486
07487
07488
07489 options |= DNS_FETCHOPT_NOEDNS0;
07490 resend = ISC_TRUE;
07491 add_bad_edns(fctx,
07492 &query->addrinfo->sockaddr);
07493 inc_stats(fctx->res,
07494 dns_resstatscounter_edns0fail);
07495 } else {
07496 broken_server = result;
07497 keep_trying = ISC_TRUE;
07498 }
07499 goto done;
07500 }
07501
07502
07503
07504
07505 truncated = ISC_TRUE;
07506 break;
07507 case DNS_R_FORMERR:
07508 if ((query->options & DNS_FETCHOPT_NOEDNS0) == 0) {
07509
07510
07511
07512
07513
07514 options |= DNS_FETCHOPT_NOEDNS0;
07515 resend = ISC_TRUE;
07516 add_bad_edns(fctx, &query->addrinfo->sockaddr);
07517 inc_stats(fctx->res,
07518 dns_resstatscounter_edns0fail);
07519 } else {
07520 broken_server = DNS_R_UNEXPECTEDRCODE;
07521 keep_trying = ISC_TRUE;
07522 }
07523 goto done;
07524 default:
07525
07526
07527
07528 goto done;
07529 }
07530 }
07531
07532
07533
07534
07535 dns_message_logfmtpacket2(message, "received packet from",
07536 &query->addrinfo->sockaddr,
07537 DNS_LOGCATEGORY_RESOLVER,
07538 DNS_LOGMODULE_PACKETS,
07539 &dns_master_style_comment,
07540 ISC_LOG_DEBUG(10),
07541 fctx->res->mctx);
07542
07543
07544
07545 opt = dns_message_getopt(message);
07546 if (opt != NULL)
07547 process_opt(query, opt);
07548
07549 #ifdef notyet
07550 #ifdef ISC_PLATFORM_USESIT
07551 if (message->sitbad) {
07552
07553
07554
07555 resend = ISC_TRUE;
07556
07557 FCTXTRACE("bad sit");
07558 goto done;
07559 }
07560 #endif
07561 #endif
07562
07563
07564
07565
07566
07567 result = dns_message_checksig(message, fctx->res->view);
07568 if (result != ISC_R_SUCCESS) {
07569 FCTXTRACE3("signature check failed", result);
07570 goto done;
07571 }
07572
07573
07574
07575
07576 INSIST((message->flags & DNS_MESSAGEFLAG_QR) != 0);
07577
07578
07579
07580
07581
07582
07583
07584
07585
07586
07587
07588
07589
07590
07591 if (opt == NULL && !EDNSOK(query->addrinfo) &&
07592 (message->rcode == dns_rcode_noerror ||
07593 message->rcode == dns_rcode_nxdomain ||
07594 message->rcode == dns_rcode_refused ||
07595 message->rcode == dns_rcode_yxdomain) &&
07596 bad_edns(fctx, &query->addrinfo->sockaddr)) {
07597 dns_message_logpacket2(message,
07598 "received packet (bad edns) from",
07599 &query->addrinfo->sockaddr,
07600 DNS_LOGCATEGORY_RESOLVER,
07601 DNS_LOGMODULE_RESOLVER,
07602 ISC_LOG_DEBUG(3),
07603 fctx->res->mctx);
07604 dns_adb_changeflags(fctx->adb, query->addrinfo,
07605 DNS_FETCHOPT_NOEDNS0,
07606 DNS_FETCHOPT_NOEDNS0);
07607 } else if (opt == NULL && (message->flags & DNS_MESSAGEFLAG_TC) == 0 &&
07608 !EDNSOK(query->addrinfo) &&
07609 (message->rcode == dns_rcode_noerror ||
07610 message->rcode == dns_rcode_nxdomain) &&
07611 (query->options & DNS_FETCHOPT_NOEDNS0) == 0) {
07612
07613
07614
07615
07616
07617
07618
07619
07620
07621
07622
07623 dns_message_logpacket2(message, "received packet (no opt) from",
07624 &query->addrinfo->sockaddr,
07625 DNS_LOGCATEGORY_RESOLVER,
07626 DNS_LOGMODULE_RESOLVER,
07627 ISC_LOG_DEBUG(3),
07628 fctx->res->mctx);
07629 dns_adb_changeflags(fctx->adb, query->addrinfo,
07630 DNS_FETCHOPT_NOEDNS0,
07631 DNS_FETCHOPT_NOEDNS0);
07632 }
07633
07634
07635
07636
07637
07638 if (opt != NULL && !EDNSOK(query->addrinfo) &&
07639 (query->options & DNS_FETCHOPT_NOEDNS0) == 0 &&
07640 (message->rcode == dns_rcode_noerror ||
07641 message->rcode == dns_rcode_nxdomain ||
07642 message->rcode == dns_rcode_refused ||
07643 message->rcode == dns_rcode_yxdomain)) {
07644 dns_adb_changeflags(fctx->adb, query->addrinfo,
07645 FCTX_ADDRINFO_EDNSOK,
07646 FCTX_ADDRINFO_EDNSOK);
07647 }
07648
07649
07650
07651
07652 if ((message->flags & DNS_MESSAGEFLAG_TC) != 0)
07653 truncated = ISC_TRUE;
07654
07655 if (truncated) {
07656 inc_stats(fctx->res, dns_resstatscounter_truncated);
07657 if ((options & DNS_FETCHOPT_TCP) != 0) {
07658 broken_server = DNS_R_TRUNCATEDTCP;
07659 keep_trying = ISC_TRUE;
07660 } else {
07661 options |= DNS_FETCHOPT_TCP;
07662 resend = ISC_TRUE;
07663 }
07664 FCTXTRACE3("message truncated", result);
07665 goto done;
07666 }
07667
07668
07669
07670
07671 if (message->opcode != dns_opcode_query) {
07672
07673 broken_server = DNS_R_UNEXPECTEDOPCODE;
07674 keep_trying = ISC_TRUE;
07675 FCTXTRACE("invalid message opcode");
07676 goto done;
07677 }
07678
07679
07680
07681
07682 if (message->rcode != dns_rcode_noerror) {
07683 switch (message->rcode) {
07684 case dns_rcode_nxdomain:
07685 inc_stats(fctx->res, dns_resstatscounter_nxdomain);
07686 break;
07687 case dns_rcode_servfail:
07688 inc_stats(fctx->res, dns_resstatscounter_servfail);
07689 break;
07690 case dns_rcode_formerr:
07691 inc_stats(fctx->res, dns_resstatscounter_formerr);
07692 break;
07693 case dns_rcode_refused:
07694 inc_stats(fctx->res, dns_resstatscounter_refused);
07695 break;
07696 case dns_rcode_badvers:
07697 inc_stats(fctx->res, dns_resstatscounter_badvers);
07698 break;
07699 default:
07700 inc_stats(fctx->res, dns_resstatscounter_othererror);
07701 break;
07702 }
07703 }
07704
07705
07706
07707
07708 if (message->rcode != dns_rcode_noerror &&
07709 message->rcode != dns_rcode_nxdomain) {
07710 isc_buffer_t b;
07711 char code[64];
07712 #ifdef ISC_PLATFORM_USESIT
07713 unsigned char sit[64];
07714
07715
07716
07717
07718 if (!NOSIT(query->addrinfo) &&
07719 (message->rcode == dns_rcode_formerr ||
07720 message->rcode == dns_rcode_notimp ||
07721 message->rcode == dns_rcode_refused) &&
07722 dns_adb_getsit(fctx->adb, query->addrinfo,
07723 sit, sizeof(sit)) == 0U) {
07724 dns_adb_changeflags(fctx->adb, query->addrinfo,
07725 FCTX_ADDRINFO_NOSIT,
07726 FCTX_ADDRINFO_NOSIT);
07727 resend = ISC_TRUE;
07728 } else
07729 #endif
07730 if (((message->rcode == dns_rcode_formerr ||
07731 message->rcode == dns_rcode_notimp) ||
07732 (message->rcode == dns_rcode_servfail &&
07733 dns_message_getopt(message) == NULL)) &&
07734 (query->options & DNS_FETCHOPT_NOEDNS0) == 0) {
07735
07736
07737
07738
07739
07740
07741
07742
07743
07744
07745
07746 options |= DNS_FETCHOPT_NOEDNS0;
07747 resend = ISC_TRUE;
07748
07749
07750
07751 add_bad_edns(fctx, &query->addrinfo->sockaddr);
07752 inc_stats(fctx->res, dns_resstatscounter_edns0fail);
07753 } else if (message->rcode == dns_rcode_formerr) {
07754 if (ISFORWARDER(query->addrinfo)) {
07755
07756
07757
07758
07759 broken_server = DNS_R_REMOTEFORMERR;
07760 keep_trying = ISC_TRUE;
07761 } else {
07762
07763
07764
07765
07766
07767
07768
07769
07770 log_formerr(fctx, "server sent FORMERR");
07771 result = DNS_R_FORMERR;
07772 }
07773 } else if (message->rcode == dns_rcode_yxdomain) {
07774
07775
07776
07777
07778
07779 result = DNS_R_YXDOMAIN;
07780 } else if (message->rcode == dns_rcode_badvers) {
07781 unsigned int flags, mask;
07782 unsigned int version;
07783 #if defined(ISC_PLATFORM_USESIT) && DNS_EDNS_VERSION == 0
07784
07785
07786
07787
07788
07789
07790
07791 if (dns_adb_getsit(fctx->adb, query->addrinfo,
07792 sit, sizeof(sit)) == 0U) {
07793 dns_adb_changeflags(fctx->adb, query->addrinfo,
07794 FCTX_ADDRINFO_NOSIT,
07795 FCTX_ADDRINFO_NOSIT);
07796 }
07797 #endif
07798
07799 resend = ISC_TRUE;
07800 INSIST(opt != NULL);
07801 version = (opt->ttl >> 16) & 0xff;
07802 flags = (version << DNS_FETCHOPT_EDNSVERSIONSHIFT) |
07803 DNS_FETCHOPT_EDNSVERSIONSET;
07804 mask = DNS_FETCHOPT_EDNSVERSIONMASK |
07805 DNS_FETCHOPT_EDNSVERSIONSET;
07806
07807
07808
07809 if (query->ednsversion > (int)version &&
07810 !EDNSOK(query->addrinfo)) {
07811 dns_adb_changeflags(fctx->adb, query->addrinfo,
07812 FCTX_ADDRINFO_EDNSOK,
07813 FCTX_ADDRINFO_EDNSOK);
07814 }
07815
07816
07817
07818
07819
07820
07821
07822
07823
07824
07825 #if DNS_EDNS_VERSION == 0
07826
07827 if (version <= DNS_EDNS_VERSION)
07828 #else
07829 if (version < DNS_EDNS_VERSION)
07830 #endif
07831 {
07832 dns_adb_changeflags(fctx->adb, query->addrinfo,
07833 flags, mask);
07834 } else {
07835 broken_server = DNS_R_BADVERS;
07836 keep_trying = ISC_TRUE;
07837 }
07838 } else {
07839
07840
07841
07842 broken_server = DNS_R_UNEXPECTEDRCODE;
07843 INSIST(broken_server != ISC_R_SUCCESS);
07844 keep_trying = ISC_TRUE;
07845 }
07846
07847 isc_buffer_init(&b, code, sizeof(code) - 1);
07848 dns_rcode_totext(fctx->rmessage->rcode, &b);
07849 code[isc_buffer_usedlength(&b)] = '\0';
07850 FCTXTRACE2("remote server broken: returned ", code);
07851 goto done;
07852 }
07853
07854
07855
07856
07857 result = same_question(fctx);
07858 if (result != ISC_R_SUCCESS) {
07859
07860 if (result == DNS_R_FORMERR)
07861 keep_trying = ISC_TRUE;
07862 FCTXTRACE3("response did not match question", result);
07863 goto done;
07864 }
07865
07866
07867
07868
07869 if (fctx->res->lame_ttl != 0 && !ISFORWARDER(query->addrinfo) &&
07870 is_lame(fctx)) {
07871 inc_stats(fctx->res, dns_resstatscounter_lame);
07872 log_lame(fctx, query->addrinfo);
07873 result = dns_adb_marklame(fctx->adb, query->addrinfo,
07874 &fctx->name, fctx->type,
07875 now + fctx->res->lame_ttl);
07876 if (result != ISC_R_SUCCESS)
07877 isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER,
07878 DNS_LOGMODULE_RESOLVER, ISC_LOG_ERROR,
07879 "could not mark server as lame: %s",
07880 isc_result_totext(result));
07881 broken_server = DNS_R_LAME;
07882 keep_trying = ISC_TRUE;
07883 FCTXTRACE("lame server");
07884 goto done;
07885 }
07886
07887
07888
07889
07890 if (!ISFORWARDER(query->addrinfo) &&
07891 dns_view_isdelegationonly(fctx->res->view, &fctx->domain) &&
07892 !dns_name_equal(&fctx->domain, &fctx->name) &&
07893 fix_mustbedelegationornxdomain(message, fctx)) {
07894 char namebuf[DNS_NAME_FORMATSIZE];
07895 char domainbuf[DNS_NAME_FORMATSIZE];
07896 char addrbuf[ISC_SOCKADDR_FORMATSIZE];
07897 char classbuf[64];
07898 char typebuf[64];
07899
07900 dns_name_format(&fctx->name, namebuf, sizeof(namebuf));
07901 dns_name_format(&fctx->domain, domainbuf, sizeof(domainbuf));
07902 dns_rdatatype_format(fctx->type, typebuf, sizeof(typebuf));
07903 dns_rdataclass_format(fctx->res->rdclass, classbuf,
07904 sizeof(classbuf));
07905 isc_sockaddr_format(&query->addrinfo->sockaddr, addrbuf,
07906 sizeof(addrbuf));
07907
07908 isc_log_write(dns_lctx, DNS_LOGCATEGORY_DELEGATION_ONLY,
07909 DNS_LOGMODULE_RESOLVER, ISC_LOG_NOTICE,
07910 "enforced delegation-only for '%s' (%s/%s/%s) "
07911 "from %s",
07912 domainbuf, namebuf, typebuf, classbuf, addrbuf);
07913 }
07914
07915 if ((fctx->res->options & DNS_RESOLVER_CHECKNAMES) != 0)
07916 checknames(message);
07917
07918
07919
07920
07921 fctx->attributes &= ~(FCTX_ATTR_WANTNCACHE | FCTX_ATTR_WANTCACHE);
07922
07923
07924
07925
07926 if (message->counts[DNS_SECTION_ANSWER] > 0 &&
07927 (message->rcode == dns_rcode_noerror ||
07928 message->rcode == dns_rcode_nxdomain)) {
07929
07930
07931
07932
07933
07934 if ((message->flags & DNS_MESSAGEFLAG_AA) != 0 ||
07935 ISFORWARDER(query->addrinfo))
07936 {
07937 result = answer_response(fctx);
07938 if (result != ISC_R_SUCCESS)
07939 FCTXTRACE3("answer_response (AA/fwd)", result);
07940 } else if (iscname(fctx) &&
07941 fctx->type != dns_rdatatype_any &&
07942 fctx->type != dns_rdatatype_cname)
07943 {
07944
07945
07946
07947
07948
07949 result = answer_response(fctx);
07950 if (result != ISC_R_SUCCESS)
07951 FCTXTRACE3("answer_response (!ANY/!CNAME)",
07952 result);
07953 } else if (fctx->type != dns_rdatatype_ns &&
07954 !betterreferral(fctx)) {
07955
07956
07957
07958 result = answer_response(fctx);
07959 if (result != ISC_R_SUCCESS)
07960 FCTXTRACE3("answer_response (!NS)", result);
07961 } else {
07962 if (fctx->type == dns_rdatatype_ns) {
07963
07964
07965
07966
07967
07968
07969
07970
07971 result = noanswer_response(fctx, NULL,
07972 LOOK_FOR_NS_IN_ANSWER);
07973 if (result != ISC_R_SUCCESS)
07974 FCTXTRACE3("noanswer_response (NS)",
07975 result);
07976 } else {
07977
07978
07979
07980
07981
07982
07983
07984
07985
07986
07987
07988
07989 result = noanswer_response(fctx, NULL,
07990 LOOK_FOR_GLUE_IN_ANSWER);
07991 if (result != ISC_R_SUCCESS)
07992 FCTXTRACE3("noanswer_response", result);
07993 }
07994 if (result != DNS_R_DELEGATION) {
07995
07996
07997
07998
07999
08000
08001
08002 broken_server = DNS_R_LAME;
08003 keep_trying = ISC_TRUE;
08004 goto done;
08005 }
08006 goto force_referral;
08007 }
08008 if (result != ISC_R_SUCCESS) {
08009 if (result == DNS_R_FORMERR)
08010 keep_trying = ISC_TRUE;
08011 goto done;
08012 }
08013 } else if (message->counts[DNS_SECTION_AUTHORITY] > 0 ||
08014 message->rcode == dns_rcode_noerror ||
08015 message->rcode == dns_rcode_nxdomain) {
08016
08017
08018
08019 result = noanswer_response(fctx, NULL, 0);
08020 switch (result) {
08021 case ISC_R_SUCCESS:
08022 case DNS_R_CHASEDSSERVERS:
08023 break;
08024 case DNS_R_DELEGATION:
08025 force_referral:
08026
08027
08028
08029
08030 get_nameservers = ISC_TRUE;
08031 keep_trying = ISC_TRUE;
08032
08033
08034
08035
08036 fctx->restarts = 0;
08037
08038
08039
08040
08041
08042 fctx->referrals++;
08043 fctx->querysent = 0;
08044 fctx->lamecount = 0;
08045 fctx->neterr = 0;
08046 fctx->badresp = 0;
08047 fctx->adberr = 0;
08048
08049 result = ISC_R_SUCCESS;
08050 break;
08051 default:
08052
08053
08054
08055 if (result == DNS_R_FORMERR)
08056 keep_trying = ISC_TRUE;
08057 FCTXTRACE3("noanswer_response", result);
08058 goto done;
08059 }
08060 } else {
08061
08062
08063
08064
08065 broken_server = DNS_R_UNEXPECTEDRCODE;
08066 keep_trying = ISC_TRUE;
08067 FCTXTRACE("broken server: unexpected rcode");
08068 goto done;
08069 }
08070
08071
08072
08073
08074 chase_additional(fctx);
08075
08076
08077
08078
08079
08080 if (WANTCACHE(fctx)) {
08081 result = cache_message(fctx, query->addrinfo, now);
08082 if (result != ISC_R_SUCCESS) {
08083 FCTXTRACE3("cache_message complete", result);
08084 goto done;
08085 }
08086 }
08087
08088
08089
08090
08091
08092 if (WANTNCACHE(fctx)) {
08093 dns_rdatatype_t covers;
08094
08095
08096
08097
08098 if (message->rcode == dns_rcode_nxdomain &&
08099 fctx->type != dns_rdatatype_ds)
08100 covers = dns_rdatatype_any;
08101 else
08102 covers = fctx->type;
08103
08104
08105
08106
08107 result = ncache_message(fctx, query->addrinfo, covers, now);
08108 if (result != ISC_R_SUCCESS)
08109 FCTXTRACE3("ncache_message complete", result);
08110 }
08111
08112 done:
08113
08114
08115
08116
08117 addrinfo = query->addrinfo;
08118
08119 FCTXTRACE4("query canceled in response(); ",
08120 no_response ? "no response" : "responding",
08121 result);
08122
08123
08124
08125
08126
08127
08128 fctx_cancelquery(&query, &devent, finish, no_response);
08129
08130 if (keep_trying) {
08131 if (result == DNS_R_FORMERR)
08132 broken_server = DNS_R_FORMERR;
08133 if (broken_server != ISC_R_SUCCESS) {
08134
08135
08136
08137
08138 add_bad(fctx, addrinfo, broken_server, broken_type);
08139 }
08140
08141 if (get_nameservers) {
08142 dns_name_t *name;
08143 dns_fixedname_init(&foundname);
08144 fname = dns_fixedname_name(&foundname);
08145 if (result != ISC_R_SUCCESS) {
08146 fctx_done(fctx, DNS_R_SERVFAIL, __LINE__);
08147 return;
08148 }
08149 findoptions = 0;
08150 if (dns_rdatatype_atparent(fctx->type))
08151 findoptions |= DNS_DBFIND_NOEXACT;
08152 if ((options & DNS_FETCHOPT_UNSHARED) == 0)
08153 name = &fctx->name;
08154 else
08155 name = &fctx->domain;
08156 result = dns_view_findzonecut(fctx->res->view,
08157 name, fname,
08158 now, findoptions,
08159 ISC_TRUE,
08160 &fctx->nameservers,
08161 NULL);
08162 if (result != ISC_R_SUCCESS) {
08163 FCTXTRACE("couldn't find a zonecut");
08164 fctx_done(fctx, DNS_R_SERVFAIL, __LINE__);
08165 return;
08166 }
08167 if (!dns_name_issubdomain(fname, &fctx->domain)) {
08168
08169
08170
08171
08172 FCTXTRACE("nameservers now above QDOMAIN");
08173 fctx_done(fctx, DNS_R_SERVFAIL, __LINE__);
08174 return;
08175 }
08176 dns_name_free(&fctx->domain, fctx->mctx);
08177 dns_name_init(&fctx->domain, NULL);
08178 result = dns_name_dup(fname, fctx->mctx, &fctx->domain);
08179 if (result != ISC_R_SUCCESS) {
08180 fctx_done(fctx, DNS_R_SERVFAIL, __LINE__);
08181 return;
08182 }
08183 fctx->ns_ttl = fctx->nameservers.ttl;
08184 fctx->ns_ttl_ok = ISC_TRUE;
08185 fctx_cancelqueries(fctx, ISC_TRUE);
08186 fctx_cleanupfinds(fctx);
08187 fctx_cleanupaltfinds(fctx);
08188 fctx_cleanupforwaddrs(fctx);
08189 fctx_cleanupaltaddrs(fctx);
08190 }
08191
08192
08193
08194 fctx_try(fctx, !get_nameservers, ISC_FALSE);
08195 } else if (resend) {
08196
08197
08198
08199 FCTXTRACE("resend");
08200 inc_stats(fctx->res, dns_resstatscounter_retry);
08201 result = fctx_query(fctx, addrinfo, options);
08202 if (result != ISC_R_SUCCESS)
08203 fctx_done(fctx, result, __LINE__);
08204 } else if (result == ISC_R_SUCCESS && !HAVE_ANSWER(fctx)) {
08205
08206
08207
08208
08209 FCTXTRACE("wait for validator");
08210 fctx_cancelqueries(fctx, ISC_TRUE);
08211
08212
08213
08214
08215 result = fctx_stopidletimer(fctx);
08216 if (result != ISC_R_SUCCESS)
08217 fctx_done(fctx, result, __LINE__);
08218 } else if (result == DNS_R_CHASEDSSERVERS) {
08219 unsigned int n;
08220 add_bad(fctx, addrinfo, result, broken_type);
08221 fctx_cancelqueries(fctx, ISC_TRUE);
08222 fctx_cleanupfinds(fctx);
08223 fctx_cleanupforwaddrs(fctx);
08224
08225 n = dns_name_countlabels(&fctx->name);
08226 dns_name_getlabelsequence(&fctx->name, 1, n - 1, &fctx->nsname);
08227
08228 FCTXTRACE("suspending DS lookup to find parent's NS records");
08229
08230 result = dns_resolver_createfetch(fctx->res, &fctx->nsname,
08231 dns_rdatatype_ns,
08232 NULL, NULL, NULL,
08233 fctx->options, task,
08234 resume_dslookup, fctx,
08235 &fctx->nsrrset, NULL,
08236 &fctx->nsfetch);
08237 if (result != ISC_R_SUCCESS)
08238 fctx_done(fctx, result, __LINE__);
08239 else {
08240 fctx_increference(fctx);
08241 result = fctx_stopidletimer(fctx);
08242 if (result != ISC_R_SUCCESS)
08243 fctx_done(fctx, result, __LINE__);
08244 }
08245 } else {
08246
08247
08248
08249 fctx_done(fctx, result, __LINE__);
08250 }
08251 }
08252
08253
08254
08255
08256
08257 static void
08258 destroy(dns_resolver_t *res) {
08259 unsigned int i;
08260 alternate_t *a;
08261
08262 REQUIRE(res->references == 0);
08263 REQUIRE(!res->priming);
08264 REQUIRE(res->primefetch == NULL);
08265
08266 RTRACE("destroy");
08267
08268 INSIST(res->nfctx == 0);
08269
08270 DESTROYLOCK(&res->primelock);
08271 DESTROYLOCK(&res->nlock);
08272 DESTROYLOCK(&res->lock);
08273 for (i = 0; i < res->nbuckets; i++) {
08274 INSIST(ISC_LIST_EMPTY(res->buckets[i].fctxs));
08275 isc_task_shutdown(res->buckets[i].task);
08276 isc_task_detach(&res->buckets[i].task);
08277 DESTROYLOCK(&res->buckets[i].lock);
08278 isc_mem_detach(&res->buckets[i].mctx);
08279 }
08280 isc_mem_put(res->mctx, res->buckets,
08281 res->nbuckets * sizeof(fctxbucket_t));
08282 if (res->dispatches4 != NULL)
08283 dns_dispatchset_destroy(&res->dispatches4);
08284 if (res->dispatches6 != NULL)
08285 dns_dispatchset_destroy(&res->dispatches6);
08286 while ((a = ISC_LIST_HEAD(res->alternates)) != NULL) {
08287 ISC_LIST_UNLINK(res->alternates, a, link);
08288 if (!a->isaddress)
08289 dns_name_free(&a->_u._n.name, res->mctx);
08290 isc_mem_put(res->mctx, a, sizeof(*a));
08291 }
08292 dns_resolver_reset_algorithms(res);
08293 dns_resolver_reset_ds_digests(res);
08294 dns_badcache_destroy(&res->badcache);
08295 dns_resolver_resetmustbesecure(res);
08296 #if USE_ALGLOCK
08297 isc_rwlock_destroy(&res->alglock);
08298 #endif
08299 #if USE_MBSLOCK
08300 isc_rwlock_destroy(&res->mbslock);
08301 #endif
08302 isc_timer_detach(&res->spillattimer);
08303 res->magic = 0;
08304 isc_mem_put(res->mctx, res, sizeof(*res));
08305 }
08306
08307 static void
08308 send_shutdown_events(dns_resolver_t *res) {
08309 isc_event_t *event, *next_event;
08310 isc_task_t *etask;
08311
08312
08313
08314
08315
08316 for (event = ISC_LIST_HEAD(res->whenshutdown);
08317 event != NULL;
08318 event = next_event) {
08319 next_event = ISC_LIST_NEXT(event, ev_link);
08320 ISC_LIST_UNLINK(res->whenshutdown, event, ev_link);
08321 etask = event->ev_sender;
08322 event->ev_sender = res;
08323 isc_task_sendanddetach(&etask, &event);
08324 }
08325 }
08326
08327 static void
08328 empty_bucket(dns_resolver_t *res) {
08329 RTRACE("empty_bucket");
08330
08331 LOCK(&res->lock);
08332
08333 INSIST(res->activebuckets > 0);
08334 res->activebuckets--;
08335 if (res->activebuckets == 0)
08336 send_shutdown_events(res);
08337
08338 UNLOCK(&res->lock);
08339 }
08340
08341 static void
08342 spillattimer_countdown(isc_task_t *task, isc_event_t *event) {
08343 dns_resolver_t *res = event->ev_arg;
08344 isc_result_t result;
08345 unsigned int count;
08346 isc_boolean_t logit = ISC_FALSE;
08347
08348 REQUIRE(VALID_RESOLVER(res));
08349
08350 UNUSED(task);
08351
08352 LOCK(&res->lock);
08353 INSIST(!res->exiting);
08354 if (res->spillat > res->spillatmin) {
08355 res->spillat--;
08356 logit = ISC_TRUE;
08357 }
08358 if (res->spillat <= res->spillatmin) {
08359 result = isc_timer_reset(res->spillattimer,
08360 isc_timertype_inactive, NULL,
08361 NULL, ISC_TRUE);
08362 RUNTIME_CHECK(result == ISC_R_SUCCESS);
08363 }
08364 count = res->spillat;
08365 UNLOCK(&res->lock);
08366 if (logit)
08367 isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER,
08368 DNS_LOGMODULE_RESOLVER, ISC_LOG_NOTICE,
08369 "clients-per-query decreased to %u", count);
08370
08371 isc_event_free(&event);
08372 }
08373
08374 isc_result_t
08375 dns_resolver_create(dns_view_t *view,
08376 isc_taskmgr_t *taskmgr,
08377 unsigned int ntasks, unsigned int ndisp,
08378 isc_socketmgr_t *socketmgr,
08379 isc_timermgr_t *timermgr,
08380 unsigned int options,
08381 dns_dispatchmgr_t *dispatchmgr,
08382 dns_dispatch_t *dispatchv4,
08383 dns_dispatch_t *dispatchv6,
08384 dns_resolver_t **resp)
08385 {
08386 dns_resolver_t *res;
08387 isc_result_t result = ISC_R_SUCCESS;
08388 unsigned int i, buckets_created = 0;
08389 isc_task_t *task = NULL;
08390 char name[16];
08391 unsigned dispattr;
08392
08393
08394
08395
08396
08397 REQUIRE(DNS_VIEW_VALID(view));
08398 REQUIRE(ntasks > 0);
08399 REQUIRE(ndisp > 0);
08400 REQUIRE(resp != NULL && *resp == NULL);
08401 REQUIRE(dispatchmgr != NULL);
08402 REQUIRE(dispatchv4 != NULL || dispatchv6 != NULL);
08403
08404 res = isc_mem_get(view->mctx, sizeof(*res));
08405 if (res == NULL)
08406 return (ISC_R_NOMEMORY);
08407 RTRACE("create");
08408 res->mctx = view->mctx;
08409 res->rdclass = view->rdclass;
08410 res->socketmgr = socketmgr;
08411 res->timermgr = timermgr;
08412 res->taskmgr = taskmgr;
08413 res->dispatchmgr = dispatchmgr;
08414 res->view = view;
08415 res->options = options;
08416 res->lame_ttl = 0;
08417 ISC_LIST_INIT(res->alternates);
08418 res->udpsize = RECV_BUFFER_SIZE;
08419 res->algorithms = NULL;
08420 res->digests = NULL;
08421 res->badcache = NULL;
08422 dns_badcache_init(res->mctx, DNS_RESOLVER_BADCACHESIZE,
08423 &res->badcache);
08424 res->mustbesecure = NULL;
08425 res->spillatmin = res->spillat = 10;
08426 res->spillatmax = 100;
08427 res->spillattimer = NULL;
08428 res->zero_no_soa_ttl = ISC_FALSE;
08429 res->query_timeout = DEFAULT_QUERY_TIMEOUT;
08430 res->maxdepth = DEFAULT_RECURSION_DEPTH;
08431 res->maxqueries = DEFAULT_MAX_QUERIES;
08432 res->nbuckets = ntasks;
08433 if (view->resstats != NULL)
08434 isc_stats_set(view->resstats, ntasks,
08435 dns_resstatscounter_buckets);
08436 res->activebuckets = ntasks;
08437 res->buckets = isc_mem_get(view->mctx,
08438 ntasks * sizeof(fctxbucket_t));
08439 if (res->buckets == NULL) {
08440 result = ISC_R_NOMEMORY;
08441 goto cleanup_res;
08442 }
08443 for (i = 0; i < ntasks; i++) {
08444 result = isc_mutex_init(&res->buckets[i].lock);
08445 if (result != ISC_R_SUCCESS)
08446 goto cleanup_buckets;
08447 res->buckets[i].task = NULL;
08448 result = isc_task_create(taskmgr, 0, &res->buckets[i].task);
08449 if (result != ISC_R_SUCCESS) {
08450 DESTROYLOCK(&res->buckets[i].lock);
08451 goto cleanup_buckets;
08452 }
08453 res->buckets[i].mctx = NULL;
08454 snprintf(name, sizeof(name), "res%u", i);
08455 #ifdef ISC_PLATFORM_USETHREADS
08456
08457
08458
08459
08460
08461 result = isc_mem_create(0, 0, &res->buckets[i].mctx);
08462 if (result != ISC_R_SUCCESS) {
08463 isc_task_detach(&res->buckets[i].task);
08464 DESTROYLOCK(&res->buckets[i].lock);
08465 goto cleanup_buckets;
08466 }
08467 isc_mem_setname(res->buckets[i].mctx, name, NULL);
08468 #else
08469 isc_mem_attach(view->mctx, &res->buckets[i].mctx);
08470 #endif
08471 isc_task_setname(res->buckets[i].task, name, res);
08472 ISC_LIST_INIT(res->buckets[i].fctxs);
08473 res->buckets[i].exiting = ISC_FALSE;
08474 buckets_created++;
08475 }
08476
08477 res->dispatches4 = NULL;
08478 if (dispatchv4 != NULL) {
08479 dns_dispatchset_create(view->mctx, socketmgr, taskmgr,
08480 dispatchv4, &res->dispatches4, ndisp);
08481 dispattr = dns_dispatch_getattributes(dispatchv4);
08482 res->exclusivev4 =
08483 ISC_TF((dispattr & DNS_DISPATCHATTR_EXCLUSIVE) != 0);
08484 }
08485
08486 res->dispatches6 = NULL;
08487 if (dispatchv6 != NULL) {
08488 dns_dispatchset_create(view->mctx, socketmgr, taskmgr,
08489 dispatchv6, &res->dispatches6, ndisp);
08490 dispattr = dns_dispatch_getattributes(dispatchv6);
08491 res->exclusivev6 =
08492 ISC_TF((dispattr & DNS_DISPATCHATTR_EXCLUSIVE) != 0);
08493 }
08494
08495 res->querydscp4 = -1;
08496 res->querydscp6 = -1;
08497 res->references = 1;
08498 res->exiting = ISC_FALSE;
08499 res->frozen = ISC_FALSE;
08500 ISC_LIST_INIT(res->whenshutdown);
08501 res->priming = ISC_FALSE;
08502 res->primefetch = NULL;
08503 res->nfctx = 0;
08504
08505 result = isc_mutex_init(&res->lock);
08506 if (result != ISC_R_SUCCESS)
08507 goto cleanup_dispatches;
08508
08509 result = isc_mutex_init(&res->nlock);
08510 if (result != ISC_R_SUCCESS)
08511 goto cleanup_lock;
08512
08513 result = isc_mutex_init(&res->primelock);
08514 if (result != ISC_R_SUCCESS)
08515 goto cleanup_nlock;
08516
08517 task = NULL;
08518 result = isc_task_create(taskmgr, 0, &task);
08519 if (result != ISC_R_SUCCESS)
08520 goto cleanup_primelock;
08521 isc_task_setname(task, "resolver_task", NULL);
08522
08523 result = isc_timer_create(timermgr, isc_timertype_inactive, NULL, NULL,
08524 task, spillattimer_countdown, res,
08525 &res->spillattimer);
08526 isc_task_detach(&task);
08527 if (result != ISC_R_SUCCESS)
08528 goto cleanup_primelock;
08529
08530 #if USE_ALGLOCK
08531 result = isc_rwlock_init(&res->alglock, 0, 0);
08532 if (result != ISC_R_SUCCESS)
08533 goto cleanup_spillattimer;
08534 #endif
08535 #if USE_MBSLOCK
08536 result = isc_rwlock_init(&res->mbslock, 0, 0);
08537 if (result != ISC_R_SUCCESS)
08538 goto cleanup_alglock;
08539 #endif
08540
08541 res->magic = RES_MAGIC;
08542
08543 *resp = res;
08544
08545 return (ISC_R_SUCCESS);
08546
08547 #if USE_MBSLOCK
08548 cleanup_alglock:
08549 #if USE_ALGLOCK
08550 isc_rwlock_destroy(&res->alglock);
08551 #endif
08552 #endif
08553 #if USE_ALGLOCK || USE_MBSLOCK
08554 cleanup_spillattimer:
08555 isc_timer_detach(&res->spillattimer);
08556 #endif
08557
08558 cleanup_primelock:
08559 DESTROYLOCK(&res->primelock);
08560
08561 cleanup_nlock:
08562 DESTROYLOCK(&res->nlock);
08563
08564 cleanup_lock:
08565 DESTROYLOCK(&res->lock);
08566
08567 cleanup_dispatches:
08568 if (res->dispatches6 != NULL)
08569 dns_dispatchset_destroy(&res->dispatches6);
08570 if (res->dispatches4 != NULL)
08571 dns_dispatchset_destroy(&res->dispatches4);
08572
08573 cleanup_buckets:
08574 for (i = 0; i < buckets_created; i++) {
08575 isc_mem_detach(&res->buckets[i].mctx);
08576 DESTROYLOCK(&res->buckets[i].lock);
08577 isc_task_shutdown(res->buckets[i].task);
08578 isc_task_detach(&res->buckets[i].task);
08579 }
08580 isc_mem_put(view->mctx, res->buckets,
08581 res->nbuckets * sizeof(fctxbucket_t));
08582
08583 cleanup_res:
08584 isc_mem_put(view->mctx, res, sizeof(*res));
08585
08586 return (result);
08587 }
08588
08589 static void
08590 prime_done(isc_task_t *task, isc_event_t *event) {
08591 dns_resolver_t *res;
08592 dns_fetchevent_t *fevent;
08593 dns_fetch_t *fetch;
08594 dns_db_t *db = NULL;
08595
08596 REQUIRE(event->ev_type == DNS_EVENT_FETCHDONE);
08597 fevent = (dns_fetchevent_t *)event;
08598 res = event->ev_arg;
08599 REQUIRE(VALID_RESOLVER(res));
08600
08601 UNUSED(task);
08602
08603 LOCK(&res->lock);
08604
08605 INSIST(res->priming);
08606 res->priming = ISC_FALSE;
08607 LOCK(&res->primelock);
08608 fetch = res->primefetch;
08609 res->primefetch = NULL;
08610 UNLOCK(&res->primelock);
08611
08612 UNLOCK(&res->lock);
08613
08614 if (fevent->result == ISC_R_SUCCESS &&
08615 res->view->cache != NULL && res->view->hints != NULL) {
08616 dns_cache_attachdb(res->view->cache, &db);
08617 dns_root_checkhints(res->view, res->view->hints, db);
08618 dns_db_detach(&db);
08619 }
08620
08621 if (fevent->node != NULL)
08622 dns_db_detachnode(fevent->db, &fevent->node);
08623 if (fevent->db != NULL)
08624 dns_db_detach(&fevent->db);
08625 if (dns_rdataset_isassociated(fevent->rdataset))
08626 dns_rdataset_disassociate(fevent->rdataset);
08627 INSIST(fevent->sigrdataset == NULL);
08628
08629 isc_mem_put(res->mctx, fevent->rdataset, sizeof(*fevent->rdataset));
08630
08631 isc_event_free(&event);
08632 dns_resolver_destroyfetch(&fetch);
08633 }
08634
08635 void
08636 dns_resolver_prime(dns_resolver_t *res) {
08637 isc_boolean_t want_priming = ISC_FALSE;
08638 dns_rdataset_t *rdataset;
08639 isc_result_t result;
08640
08641 REQUIRE(VALID_RESOLVER(res));
08642 REQUIRE(res->frozen);
08643
08644 RTRACE("dns_resolver_prime");
08645
08646 LOCK(&res->lock);
08647
08648 if (!res->exiting && !res->priming) {
08649 INSIST(res->primefetch == NULL);
08650 res->priming = ISC_TRUE;
08651 want_priming = ISC_TRUE;
08652 }
08653
08654 UNLOCK(&res->lock);
08655
08656 if (want_priming) {
08657
08658
08659
08660
08661
08662
08663
08664
08665
08666 RTRACE("priming");
08667 rdataset = isc_mem_get(res->mctx, sizeof(*rdataset));
08668 if (rdataset == NULL) {
08669 LOCK(&res->lock);
08670 INSIST(res->priming);
08671 INSIST(res->primefetch == NULL);
08672 res->priming = ISC_FALSE;
08673 UNLOCK(&res->lock);
08674 return;
08675 }
08676 dns_rdataset_init(rdataset);
08677 LOCK(&res->primelock);
08678 result = dns_resolver_createfetch(res, dns_rootname,
08679 dns_rdatatype_ns,
08680 NULL, NULL, NULL, 0,
08681 res->buckets[0].task,
08682 prime_done,
08683 res, rdataset, NULL,
08684 &res->primefetch);
08685 UNLOCK(&res->primelock);
08686 if (result != ISC_R_SUCCESS) {
08687 LOCK(&res->lock);
08688 INSIST(res->priming);
08689 res->priming = ISC_FALSE;
08690 UNLOCK(&res->lock);
08691 }
08692 }
08693 }
08694
08695 void
08696 dns_resolver_freeze(dns_resolver_t *res) {
08697
08698
08699
08700
08701 REQUIRE(VALID_RESOLVER(res));
08702
08703 res->frozen = ISC_TRUE;
08704 }
08705
08706 void
08707 dns_resolver_attach(dns_resolver_t *source, dns_resolver_t **targetp) {
08708 REQUIRE(VALID_RESOLVER(source));
08709 REQUIRE(targetp != NULL && *targetp == NULL);
08710
08711 RRTRACE(source, "attach");
08712 LOCK(&source->lock);
08713 REQUIRE(!source->exiting);
08714
08715 INSIST(source->references > 0);
08716 source->references++;
08717 INSIST(source->references != 0);
08718 UNLOCK(&source->lock);
08719
08720 *targetp = source;
08721 }
08722
08723 void
08724 dns_resolver_whenshutdown(dns_resolver_t *res, isc_task_t *task,
08725 isc_event_t **eventp)
08726 {
08727 isc_task_t *clone;
08728 isc_event_t *event;
08729
08730 REQUIRE(VALID_RESOLVER(res));
08731 REQUIRE(eventp != NULL);
08732
08733 event = *eventp;
08734 *eventp = NULL;
08735
08736 LOCK(&res->lock);
08737
08738 if (res->exiting && res->activebuckets == 0) {
08739
08740
08741
08742 event->ev_sender = res;
08743 isc_task_send(task, &event);
08744 } else {
08745 clone = NULL;
08746 isc_task_attach(task, &clone);
08747 event->ev_sender = clone;
08748 ISC_LIST_APPEND(res->whenshutdown, event, ev_link);
08749 }
08750
08751 UNLOCK(&res->lock);
08752 }
08753
08754 void
08755 dns_resolver_shutdown(dns_resolver_t *res) {
08756 unsigned int i;
08757 fetchctx_t *fctx;
08758 isc_result_t result;
08759
08760 REQUIRE(VALID_RESOLVER(res));
08761
08762 RTRACE("shutdown");
08763
08764 LOCK(&res->lock);
08765
08766 if (!res->exiting) {
08767 RTRACE("exiting");
08768 res->exiting = ISC_TRUE;
08769
08770 for (i = 0; i < res->nbuckets; i++) {
08771 LOCK(&res->buckets[i].lock);
08772 for (fctx = ISC_LIST_HEAD(res->buckets[i].fctxs);
08773 fctx != NULL;
08774 fctx = ISC_LIST_NEXT(fctx, link))
08775 fctx_shutdown(fctx);
08776 if (res->dispatches4 != NULL && !res->exclusivev4) {
08777 dns_dispatchset_cancelall(res->dispatches4,
08778 res->buckets[i].task);
08779 }
08780 if (res->dispatches6 != NULL && !res->exclusivev6) {
08781 dns_dispatchset_cancelall(res->dispatches6,
08782 res->buckets[i].task);
08783 }
08784 res->buckets[i].exiting = ISC_TRUE;
08785 if (ISC_LIST_EMPTY(res->buckets[i].fctxs)) {
08786 INSIST(res->activebuckets > 0);
08787 res->activebuckets--;
08788 }
08789 UNLOCK(&res->buckets[i].lock);
08790 }
08791 if (res->activebuckets == 0)
08792 send_shutdown_events(res);
08793 result = isc_timer_reset(res->spillattimer,
08794 isc_timertype_inactive, NULL,
08795 NULL, ISC_TRUE);
08796 RUNTIME_CHECK(result == ISC_R_SUCCESS);
08797 }
08798
08799 UNLOCK(&res->lock);
08800 }
08801
08802 void
08803 dns_resolver_detach(dns_resolver_t **resp) {
08804 dns_resolver_t *res;
08805 isc_boolean_t need_destroy = ISC_FALSE;
08806
08807 REQUIRE(resp != NULL);
08808 res = *resp;
08809 REQUIRE(VALID_RESOLVER(res));
08810
08811 RTRACE("detach");
08812
08813 LOCK(&res->lock);
08814
08815 INSIST(res->references > 0);
08816 res->references--;
08817 if (res->references == 0) {
08818 INSIST(res->exiting && res->activebuckets == 0);
08819 need_destroy = ISC_TRUE;
08820 }
08821
08822 UNLOCK(&res->lock);
08823
08824 if (need_destroy)
08825 destroy(res);
08826
08827 *resp = NULL;
08828 }
08829
08830 static inline isc_boolean_t
08831 fctx_match(fetchctx_t *fctx, dns_name_t *name, dns_rdatatype_t type,
08832 unsigned int options)
08833 {
08834
08835
08836
08837 if (fctx->cloned || fctx->state == fetchstate_done ||
08838 ISC_LIST_EMPTY(fctx->events))
08839 return (ISC_FALSE);
08840
08841 if (fctx->type != type || fctx->options != options)
08842 return (ISC_FALSE);
08843 return (dns_name_equal(&fctx->name, name));
08844 }
08845
08846 static inline void
08847 log_fetch(dns_name_t *name, dns_rdatatype_t type) {
08848 char namebuf[DNS_NAME_FORMATSIZE];
08849 char typebuf[DNS_RDATATYPE_FORMATSIZE];
08850 int level = ISC_LOG_DEBUG(1);
08851
08852
08853
08854
08855
08856 if (! isc_log_wouldlog(dns_lctx, level))
08857 return;
08858
08859 dns_name_format(name, namebuf, sizeof(namebuf));
08860 dns_rdatatype_format(type, typebuf, sizeof(typebuf));
08861
08862 isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER,
08863 DNS_LOGMODULE_RESOLVER, level,
08864 "fetch: %s/%s", namebuf, typebuf);
08865 }
08866
08867 isc_result_t
08868 dns_resolver_createfetch(dns_resolver_t *res, dns_name_t *name,
08869 dns_rdatatype_t type,
08870 dns_name_t *domain, dns_rdataset_t *nameservers,
08871 dns_forwarders_t *forwarders,
08872 unsigned int options, isc_task_t *task,
08873 isc_taskaction_t action, void *arg,
08874 dns_rdataset_t *rdataset,
08875 dns_rdataset_t *sigrdataset,
08876 dns_fetch_t **fetchp)
08877 {
08878 return (dns_resolver_createfetch3(res, name, type, domain,
08879 nameservers, forwarders, NULL, 0,
08880 options, 0, NULL, task, action, arg,
08881 rdataset, sigrdataset, fetchp));
08882 }
08883
08884 isc_result_t
08885 dns_resolver_createfetch2(dns_resolver_t *res, dns_name_t *name,
08886 dns_rdatatype_t type,
08887 dns_name_t *domain, dns_rdataset_t *nameservers,
08888 dns_forwarders_t *forwarders,
08889 isc_sockaddr_t *client, dns_messageid_t id,
08890 unsigned int options, isc_task_t *task,
08891 isc_taskaction_t action, void *arg,
08892 dns_rdataset_t *rdataset,
08893 dns_rdataset_t *sigrdataset,
08894 dns_fetch_t **fetchp)
08895 {
08896 return (dns_resolver_createfetch3(res, name, type, domain,
08897 nameservers, forwarders, client, id,
08898 options, 0, NULL, task, action, arg,
08899 rdataset, sigrdataset, fetchp));
08900 }
08901
08902 isc_result_t
08903 dns_resolver_createfetch3(dns_resolver_t *res, dns_name_t *name,
08904 dns_rdatatype_t type,
08905 dns_name_t *domain, dns_rdataset_t *nameservers,
08906 dns_forwarders_t *forwarders,
08907 isc_sockaddr_t *client, dns_messageid_t id,
08908 unsigned int options, unsigned int depth,
08909 isc_counter_t *qc, isc_task_t *task,
08910 isc_taskaction_t action, void *arg,
08911 dns_rdataset_t *rdataset,
08912 dns_rdataset_t *sigrdataset,
08913 dns_fetch_t **fetchp)
08914 {
08915 dns_fetch_t *fetch;
08916 fetchctx_t *fctx = NULL;
08917 isc_result_t result = ISC_R_SUCCESS;
08918 unsigned int bucketnum;
08919 isc_boolean_t new_fctx = ISC_FALSE;
08920 isc_event_t *event;
08921 unsigned int count = 0;
08922 unsigned int spillat;
08923 unsigned int spillatmin;
08924 isc_boolean_t dodestroy = ISC_FALSE;
08925
08926 UNUSED(forwarders);
08927
08928 REQUIRE(VALID_RESOLVER(res));
08929 REQUIRE(res->frozen);
08930
08931 if (domain != NULL) {
08932 REQUIRE(DNS_RDATASET_VALID(nameservers));
08933 REQUIRE(nameservers->type == dns_rdatatype_ns);
08934 } else
08935 REQUIRE(nameservers == NULL);
08936 REQUIRE(forwarders == NULL);
08937 REQUIRE(!dns_rdataset_isassociated(rdataset));
08938 REQUIRE(sigrdataset == NULL ||
08939 !dns_rdataset_isassociated(sigrdataset));
08940 REQUIRE(fetchp != NULL && *fetchp == NULL);
08941
08942 log_fetch(name, type);
08943
08944
08945
08946
08947 fetch = isc_mem_get(res->mctx, sizeof(*fetch));
08948 if (fetch == NULL)
08949 return (ISC_R_NOMEMORY);
08950 fetch->mctx = NULL;
08951 isc_mem_attach(res->mctx, &fetch->mctx);
08952
08953 bucketnum = dns_name_fullhash(name, ISC_FALSE) % res->nbuckets;
08954
08955 LOCK(&res->lock);
08956 spillat = res->spillat;
08957 spillatmin = res->spillatmin;
08958 UNLOCK(&res->lock);
08959 LOCK(&res->buckets[bucketnum].lock);
08960
08961 if (res->buckets[bucketnum].exiting) {
08962 result = ISC_R_SHUTTINGDOWN;
08963 goto unlock;
08964 }
08965
08966 if ((options & DNS_FETCHOPT_UNSHARED) == 0) {
08967 for (fctx = ISC_LIST_HEAD(res->buckets[bucketnum].fctxs);
08968 fctx != NULL;
08969 fctx = ISC_LIST_NEXT(fctx, link)) {
08970 if (fctx_match(fctx, name, type, options))
08971 break;
08972 }
08973 }
08974
08975
08976
08977
08978 if (fctx != NULL && client != NULL) {
08979 dns_fetchevent_t *fevent;
08980 for (fevent = ISC_LIST_HEAD(fctx->events);
08981 fevent != NULL;
08982 fevent = ISC_LIST_NEXT(fevent, ev_link)) {
08983 if (fevent->client != NULL && fevent->id == id &&
08984 isc_sockaddr_equal(fevent->client, client)) {
08985 result = DNS_R_DUPLICATE;
08986 goto unlock;
08987 }
08988 count++;
08989 }
08990 }
08991 if (count >= spillatmin && spillatmin != 0) {
08992 INSIST(fctx != NULL);
08993 if (count >= spillat)
08994 fctx->spilled = ISC_TRUE;
08995 if (fctx->spilled) {
08996 result = DNS_R_DROP;
08997 goto unlock;
08998 }
08999 }
09000
09001 if (fctx == NULL) {
09002 result = fctx_create(res, name, type, domain, nameservers,
09003 options, bucketnum, depth, qc, &fctx);
09004 if (result != ISC_R_SUCCESS)
09005 goto unlock;
09006 new_fctx = ISC_TRUE;
09007 } else if (fctx->depth > depth)
09008 fctx->depth = depth;
09009
09010 result = fctx_join(fctx, task, client, id, action, arg,
09011 rdataset, sigrdataset, fetch);
09012 if (new_fctx) {
09013 if (result == ISC_R_SUCCESS) {
09014
09015
09016
09017 event = &fctx->control_event;
09018 ISC_EVENT_INIT(event, sizeof(*event), 0, NULL,
09019 DNS_EVENT_FETCHCONTROL,
09020 fctx_start, fctx, NULL,
09021 NULL, NULL);
09022 isc_task_send(res->buckets[bucketnum].task, &event);
09023 } else {
09024
09025
09026
09027
09028 (void)fctx_unlink(fctx);
09029 dodestroy = ISC_TRUE;
09030 }
09031 }
09032
09033 unlock:
09034 UNLOCK(&res->buckets[bucketnum].lock);
09035
09036 if (dodestroy)
09037 fctx_destroy(fctx);
09038
09039 if (result == ISC_R_SUCCESS) {
09040 FTRACE("created");
09041 *fetchp = fetch;
09042 } else
09043 isc_mem_putanddetach(&fetch->mctx, fetch, sizeof(*fetch));
09044
09045 return (result);
09046 }
09047
09048 void
09049 dns_resolver_cancelfetch(dns_fetch_t *fetch) {
09050 fetchctx_t *fctx;
09051 dns_resolver_t *res;
09052 dns_fetchevent_t *event, *next_event;
09053 isc_task_t *etask;
09054
09055 REQUIRE(DNS_FETCH_VALID(fetch));
09056 fctx = fetch->private;
09057 REQUIRE(VALID_FCTX(fctx));
09058 res = fctx->res;
09059
09060 FTRACE("cancelfetch");
09061
09062 LOCK(&res->buckets[fctx->bucketnum].lock);
09063
09064
09065
09066
09067
09068
09069 event = NULL;
09070 if (fctx->state != fetchstate_done) {
09071 for (event = ISC_LIST_HEAD(fctx->events);
09072 event != NULL;
09073 event = next_event) {
09074 next_event = ISC_LIST_NEXT(event, ev_link);
09075 if (event->fetch == fetch) {
09076 ISC_LIST_UNLINK(fctx->events, event, ev_link);
09077 break;
09078 }
09079 }
09080 }
09081 if (event != NULL) {
09082 etask = event->ev_sender;
09083 event->ev_sender = fctx;
09084 event->result = ISC_R_CANCELED;
09085 isc_task_sendanddetach(&etask, ISC_EVENT_PTR(&event));
09086 }
09087
09088
09089
09090
09091
09092 UNLOCK(&res->buckets[fctx->bucketnum].lock);
09093 }
09094
09095 void
09096 dns_resolver_destroyfetch(dns_fetch_t **fetchp) {
09097 dns_fetch_t *fetch;
09098 dns_resolver_t *res;
09099 dns_fetchevent_t *event, *next_event;
09100 fetchctx_t *fctx;
09101 unsigned int bucketnum;
09102 isc_boolean_t bucket_empty;
09103
09104 REQUIRE(fetchp != NULL);
09105 fetch = *fetchp;
09106 REQUIRE(DNS_FETCH_VALID(fetch));
09107 fctx = fetch->private;
09108 REQUIRE(VALID_FCTX(fctx));
09109 res = fctx->res;
09110
09111 FTRACE("destroyfetch");
09112
09113 bucketnum = fctx->bucketnum;
09114 LOCK(&res->buckets[bucketnum].lock);
09115
09116
09117
09118
09119
09120 event = NULL;
09121 if (fctx->state != fetchstate_done) {
09122 for (event = ISC_LIST_HEAD(fctx->events);
09123 event != NULL;
09124 event = next_event) {
09125 next_event = ISC_LIST_NEXT(event, ev_link);
09126 RUNTIME_CHECK(event->fetch != fetch);
09127 }
09128 }
09129
09130 bucket_empty = fctx_decreference(fctx);
09131
09132 UNLOCK(&res->buckets[bucketnum].lock);
09133
09134 isc_mem_putanddetach(&fetch->mctx, fetch, sizeof(*fetch));
09135 *fetchp = NULL;
09136
09137 if (bucket_empty)
09138 empty_bucket(res);
09139 }
09140
09141 void
09142 dns_resolver_logfetch(dns_fetch_t *fetch, isc_log_t *lctx,
09143 isc_logcategory_t *category, isc_logmodule_t *module,
09144 int level, isc_boolean_t duplicateok)
09145 {
09146 fetchctx_t *fctx;
09147 dns_resolver_t *res;
09148 char domainbuf[DNS_NAME_FORMATSIZE];
09149
09150 REQUIRE(DNS_FETCH_VALID(fetch));
09151 fctx = fetch->private;
09152 REQUIRE(VALID_FCTX(fctx));
09153 res = fctx->res;
09154
09155 LOCK(&res->buckets[fctx->bucketnum].lock);
09156
09157 INSIST(fctx->exitline >= 0);
09158 if (!fctx->logged || duplicateok) {
09159 dns_name_format(&fctx->domain, domainbuf, sizeof(domainbuf));
09160 isc_log_write(lctx, category, module, level,
09161 "fetch completed at %s:%d for %s in "
09162 "%" ISC_PRINT_QUADFORMAT "u."
09163 "%06" ISC_PRINT_QUADFORMAT "u: %s/%s "
09164 "[domain:%s,referral:%u,restart:%u,qrysent:%u,"
09165 "timeout:%u,lame:%u,neterr:%u,badresp:%u,"
09166 "adberr:%u,findfail:%u,valfail:%u]",
09167 __FILE__, fctx->exitline, fctx->info,
09168 fctx->duration / US_PER_SEC,
09169 fctx->duration % US_PER_SEC,
09170 isc_result_totext(fctx->result),
09171 isc_result_totext(fctx->vresult), domainbuf,
09172 fctx->referrals, fctx->restarts,
09173 fctx->querysent, fctx->timeouts, fctx->lamecount,
09174 fctx->neterr, fctx->badresp, fctx->adberr,
09175 fctx->findfail, fctx->valfail);
09176 fctx->logged = ISC_TRUE;
09177 }
09178
09179 UNLOCK(&res->buckets[fctx->bucketnum].lock);
09180 }
09181
09182 dns_dispatchmgr_t *
09183 dns_resolver_dispatchmgr(dns_resolver_t *resolver) {
09184 REQUIRE(VALID_RESOLVER(resolver));
09185 return (resolver->dispatchmgr);
09186 }
09187
09188 dns_dispatch_t *
09189 dns_resolver_dispatchv4(dns_resolver_t *resolver) {
09190 REQUIRE(VALID_RESOLVER(resolver));
09191 return (dns_dispatchset_get(resolver->dispatches4));
09192 }
09193
09194 dns_dispatch_t *
09195 dns_resolver_dispatchv6(dns_resolver_t *resolver) {
09196 REQUIRE(VALID_RESOLVER(resolver));
09197 return (dns_dispatchset_get(resolver->dispatches6));
09198 }
09199
09200 isc_socketmgr_t *
09201 dns_resolver_socketmgr(dns_resolver_t *resolver) {
09202 REQUIRE(VALID_RESOLVER(resolver));
09203 return (resolver->socketmgr);
09204 }
09205
09206 isc_taskmgr_t *
09207 dns_resolver_taskmgr(dns_resolver_t *resolver) {
09208 REQUIRE(VALID_RESOLVER(resolver));
09209 return (resolver->taskmgr);
09210 }
09211
09212 isc_uint32_t
09213 dns_resolver_getlamettl(dns_resolver_t *resolver) {
09214 REQUIRE(VALID_RESOLVER(resolver));
09215 return (resolver->lame_ttl);
09216 }
09217
09218 void
09219 dns_resolver_setlamettl(dns_resolver_t *resolver, isc_uint32_t lame_ttl) {
09220 REQUIRE(VALID_RESOLVER(resolver));
09221 resolver->lame_ttl = lame_ttl;
09222 }
09223
09224 unsigned int
09225 dns_resolver_nrunning(dns_resolver_t *resolver) {
09226 unsigned int n;
09227 LOCK(&resolver->nlock);
09228 n = resolver->nfctx;
09229 UNLOCK(&resolver->nlock);
09230 return (n);
09231 }
09232
09233 isc_result_t
09234 dns_resolver_addalternate(dns_resolver_t *resolver, isc_sockaddr_t *alt,
09235 dns_name_t *name, in_port_t port) {
09236 alternate_t *a;
09237 isc_result_t result;
09238
09239 REQUIRE(VALID_RESOLVER(resolver));
09240 REQUIRE(!resolver->frozen);
09241 REQUIRE((alt == NULL) ^ (name == NULL));
09242
09243 a = isc_mem_get(resolver->mctx, sizeof(*a));
09244 if (a == NULL)
09245 return (ISC_R_NOMEMORY);
09246 if (alt != NULL) {
09247 a->isaddress = ISC_TRUE;
09248 a->_u.addr = *alt;
09249 } else {
09250 a->isaddress = ISC_FALSE;
09251 a->_u._n.port = port;
09252 dns_name_init(&a->_u._n.name, NULL);
09253 result = dns_name_dup(name, resolver->mctx, &a->_u._n.name);
09254 if (result != ISC_R_SUCCESS) {
09255 isc_mem_put(resolver->mctx, a, sizeof(*a));
09256 return (result);
09257 }
09258 }
09259 ISC_LINK_INIT(a, link);
09260 ISC_LIST_APPEND(resolver->alternates, a, link);
09261
09262 return (ISC_R_SUCCESS);
09263 }
09264
09265 void
09266 dns_resolver_setudpsize(dns_resolver_t *resolver, isc_uint16_t udpsize) {
09267 REQUIRE(VALID_RESOLVER(resolver));
09268 resolver->udpsize = udpsize;
09269 }
09270
09271 isc_uint16_t
09272 dns_resolver_getudpsize(dns_resolver_t *resolver) {
09273 REQUIRE(VALID_RESOLVER(resolver));
09274 return (resolver->udpsize);
09275 }
09276
09277 void
09278 dns_resolver_flushbadcache(dns_resolver_t *resolver, dns_name_t *name) {
09279 if (name != NULL)
09280 dns_badcache_flushname(resolver->badcache, name);
09281 else
09282 dns_badcache_flush(resolver->badcache);
09283 }
09284
09285 void
09286 dns_resolver_flushbadnames(dns_resolver_t *resolver, dns_name_t *name) {
09287 dns_badcache_flushtree(resolver->badcache, name);
09288 }
09289
09290 void
09291 dns_resolver_addbadcache(dns_resolver_t *resolver, dns_name_t *name,
09292 dns_rdatatype_t type, isc_time_t *expire)
09293 {
09294 (void) dns_badcache_add(resolver->badcache, name, type,
09295 ISC_FALSE, 0, expire);
09296 }
09297
09298 isc_boolean_t
09299 dns_resolver_getbadcache(dns_resolver_t *resolver, dns_name_t *name,
09300 dns_rdatatype_t type, isc_time_t *now)
09301 {
09302 return (dns_badcache_find(resolver->badcache, name, type, NULL, now));
09303 }
09304
09305 void
09306 dns_resolver_printbadcache(dns_resolver_t *resolver, FILE *fp) {
09307 (void) dns_badcache_print(resolver->badcache, "Bad cache", fp);
09308 }
09309
09310 static void
09311 free_algorithm(void *node, void *arg) {
09312 unsigned char *algorithms = node;
09313 isc_mem_t *mctx = arg;
09314
09315 isc_mem_put(mctx, algorithms, *algorithms);
09316 }
09317
09318 void
09319 dns_resolver_reset_algorithms(dns_resolver_t *resolver) {
09320
09321 REQUIRE(VALID_RESOLVER(resolver));
09322
09323 #if USE_ALGLOCK
09324 RWLOCK(&resolver->alglock, isc_rwlocktype_write);
09325 #endif
09326 if (resolver->algorithms != NULL)
09327 dns_rbt_destroy(&resolver->algorithms);
09328 #if USE_ALGLOCK
09329 RWUNLOCK(&resolver->alglock, isc_rwlocktype_write);
09330 #endif
09331 }
09332
09333 isc_result_t
09334 dns_resolver_disable_algorithm(dns_resolver_t *resolver, dns_name_t *name,
09335 unsigned int alg)
09336 {
09337 unsigned int len, mask;
09338 unsigned char *new;
09339 unsigned char *algorithms;
09340 isc_result_t result;
09341 dns_rbtnode_t *node = NULL;
09342
09343
09344
09345
09346
09347
09348
09349 REQUIRE(VALID_RESOLVER(resolver));
09350 if (alg > 255)
09351 return (ISC_R_RANGE);
09352
09353 #if USE_ALGLOCK
09354 RWLOCK(&resolver->alglock, isc_rwlocktype_write);
09355 #endif
09356 if (resolver->algorithms == NULL) {
09357 result = dns_rbt_create(resolver->mctx, free_algorithm,
09358 resolver->mctx, &resolver->algorithms);
09359 if (result != ISC_R_SUCCESS)
09360 goto cleanup;
09361 }
09362
09363 len = alg/8 + 2;
09364 mask = 1 << (alg%8);
09365
09366 result = dns_rbt_addnode(resolver->algorithms, name, &node);
09367
09368 if (result == ISC_R_SUCCESS || result == ISC_R_EXISTS) {
09369 algorithms = node->data;
09370
09371
09372
09373
09374 if (algorithms == NULL || len > *algorithms) {
09375
09376
09377
09378
09379
09380
09381 new = isc_mem_get(resolver->mctx, len);
09382 if (new == NULL) {
09383 result = ISC_R_NOMEMORY;
09384 goto cleanup;
09385 }
09386 memset(new, 0, len);
09387 if (algorithms != NULL)
09388 memmove(new, algorithms, *algorithms);
09389 new[len-1] |= mask;
09390
09391 *new = len;
09392 node->data = new;
09393
09394 if (algorithms != NULL)
09395 isc_mem_put(resolver->mctx, algorithms,
09396 *algorithms);
09397 } else
09398 algorithms[len-1] |= mask;
09399 }
09400 result = ISC_R_SUCCESS;
09401 cleanup:
09402 #if USE_ALGLOCK
09403 RWUNLOCK(&resolver->alglock, isc_rwlocktype_write);
09404 #endif
09405 return (result);
09406 }
09407
09408 isc_boolean_t
09409 dns_resolver_algorithm_supported(dns_resolver_t *resolver, dns_name_t *name,
09410 unsigned int alg)
09411 {
09412 unsigned int len, mask;
09413 unsigned char *algorithms;
09414 void *data = NULL;
09415 isc_result_t result;
09416 isc_boolean_t found = ISC_FALSE;
09417
09418 REQUIRE(VALID_RESOLVER(resolver));
09419
09420 #if USE_ALGLOCK
09421 RWLOCK(&resolver->alglock, isc_rwlocktype_read);
09422 #endif
09423 if (resolver->algorithms == NULL)
09424 goto unlock;
09425 result = dns_rbt_findname(resolver->algorithms, name, 0, NULL, &data);
09426 if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH) {
09427 len = alg/8 + 2;
09428 mask = 1 << (alg%8);
09429 algorithms = data;
09430 if (len <= *algorithms && (algorithms[len-1] & mask) != 0)
09431 found = ISC_TRUE;
09432 }
09433 unlock:
09434 #if USE_ALGLOCK
09435 RWUNLOCK(&resolver->alglock, isc_rwlocktype_read);
09436 #endif
09437 if (found)
09438 return (ISC_FALSE);
09439 return (dst_algorithm_supported(alg));
09440 }
09441
09442 static void
09443 free_digest(void *node, void *arg) {
09444 unsigned char *digests = node;
09445 isc_mem_t *mctx = arg;
09446
09447 isc_mem_put(mctx, digests, *digests);
09448 }
09449
09450 void
09451 dns_resolver_reset_ds_digests(dns_resolver_t *resolver) {
09452
09453 REQUIRE(VALID_RESOLVER(resolver));
09454
09455 #if USE_ALGLOCK
09456 RWLOCK(&resolver->alglock, isc_rwlocktype_write);
09457 #endif
09458 if (resolver->digests != NULL)
09459 dns_rbt_destroy(&resolver->digests);
09460 #if USE_ALGLOCK
09461 RWUNLOCK(&resolver->alglock, isc_rwlocktype_write);
09462 #endif
09463 }
09464
09465 isc_result_t
09466 dns_resolver_disable_ds_digest(dns_resolver_t *resolver, dns_name_t *name,
09467 unsigned int digest_type)
09468 {
09469 unsigned int len, mask;
09470 unsigned char *new;
09471 unsigned char *digests;
09472 isc_result_t result;
09473 dns_rbtnode_t *node = NULL;
09474
09475
09476
09477
09478
09479
09480 REQUIRE(VALID_RESOLVER(resolver));
09481 if (digest_type > 255)
09482 return (ISC_R_RANGE);
09483
09484 #if USE_ALGLOCK
09485 RWLOCK(&resolver->alglock, isc_rwlocktype_write);
09486 #endif
09487 if (resolver->digests == NULL) {
09488 result = dns_rbt_create(resolver->mctx, free_digest,
09489 resolver->mctx, &resolver->digests);
09490 if (result != ISC_R_SUCCESS)
09491 goto cleanup;
09492 }
09493
09494 len = digest_type/8 + 2;
09495 mask = 1 << (digest_type%8);
09496
09497 result = dns_rbt_addnode(resolver->digests, name, &node);
09498
09499 if (result == ISC_R_SUCCESS || result == ISC_R_EXISTS) {
09500 digests = node->data;
09501
09502 if (digests == NULL || len > *digests) {
09503
09504
09505
09506
09507
09508
09509 new = isc_mem_get(resolver->mctx, len);
09510 if (new == NULL) {
09511 result = ISC_R_NOMEMORY;
09512 goto cleanup;
09513 }
09514 memset(new, 0, len);
09515 if (digests != NULL)
09516 memmove(new, digests, *digests);
09517 new[len-1] |= mask;
09518
09519 *new = len;
09520 node->data = new;
09521
09522 if (digests != NULL)
09523 isc_mem_put(resolver->mctx, digests,
09524 *digests);
09525 } else
09526 digests[len-1] |= mask;
09527 }
09528 result = ISC_R_SUCCESS;
09529 cleanup:
09530 #if USE_ALGLOCK
09531 RWUNLOCK(&resolver->alglock, isc_rwlocktype_write);
09532 #endif
09533 return (result);
09534 }
09535
09536 isc_boolean_t
09537 dns_resolver_ds_digest_supported(dns_resolver_t *resolver, dns_name_t *name,
09538 unsigned int digest_type)
09539 {
09540 unsigned int len, mask;
09541 unsigned char *digests;
09542 void *data = NULL;
09543 isc_result_t result;
09544 isc_boolean_t found = ISC_FALSE;
09545
09546 REQUIRE(VALID_RESOLVER(resolver));
09547
09548 #if USE_ALGLOCK
09549 RWLOCK(&resolver->alglock, isc_rwlocktype_read);
09550 #endif
09551 if (resolver->digests == NULL)
09552 goto unlock;
09553 result = dns_rbt_findname(resolver->digests, name, 0, NULL, &data);
09554 if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH) {
09555 len = digest_type/8 + 2;
09556 mask = 1 << (digest_type%8);
09557 digests = data;
09558 if (len <= *digests && (digests[len-1] & mask) != 0)
09559 found = ISC_TRUE;
09560 }
09561 unlock:
09562 #if USE_ALGLOCK
09563 RWUNLOCK(&resolver->alglock, isc_rwlocktype_read);
09564 #endif
09565 if (found)
09566 return (ISC_FALSE);
09567 return (dst_ds_digest_supported(digest_type));
09568 }
09569
09570 void
09571 dns_resolver_resetmustbesecure(dns_resolver_t *resolver) {
09572
09573 REQUIRE(VALID_RESOLVER(resolver));
09574
09575 #if USE_MBSLOCK
09576 RWLOCK(&resolver->mbslock, isc_rwlocktype_write);
09577 #endif
09578 if (resolver->mustbesecure != NULL)
09579 dns_rbt_destroy(&resolver->mustbesecure);
09580 #if USE_MBSLOCK
09581 RWUNLOCK(&resolver->mbslock, isc_rwlocktype_write);
09582 #endif
09583 }
09584
09585 static isc_boolean_t yes = ISC_TRUE, no = ISC_FALSE;
09586
09587 isc_result_t
09588 dns_resolver_setmustbesecure(dns_resolver_t *resolver, dns_name_t *name,
09589 isc_boolean_t value)
09590 {
09591 isc_result_t result;
09592
09593 REQUIRE(VALID_RESOLVER(resolver));
09594
09595 #if USE_MBSLOCK
09596 RWLOCK(&resolver->mbslock, isc_rwlocktype_write);
09597 #endif
09598 if (resolver->mustbesecure == NULL) {
09599 result = dns_rbt_create(resolver->mctx, NULL, NULL,
09600 &resolver->mustbesecure);
09601 if (result != ISC_R_SUCCESS)
09602 goto cleanup;
09603 }
09604 result = dns_rbt_addname(resolver->mustbesecure, name,
09605 value ? &yes : &no);
09606 cleanup:
09607 #if USE_MBSLOCK
09608 RWUNLOCK(&resolver->mbslock, isc_rwlocktype_write);
09609 #endif
09610 return (result);
09611 }
09612
09613 isc_boolean_t
09614 dns_resolver_getmustbesecure(dns_resolver_t *resolver, dns_name_t *name) {
09615 void *data = NULL;
09616 isc_boolean_t value = ISC_FALSE;
09617 isc_result_t result;
09618
09619 REQUIRE(VALID_RESOLVER(resolver));
09620
09621 #if USE_MBSLOCK
09622 RWLOCK(&resolver->mbslock, isc_rwlocktype_read);
09623 #endif
09624 if (resolver->mustbesecure == NULL)
09625 goto unlock;
09626 result = dns_rbt_findname(resolver->mustbesecure, name, 0, NULL, &data);
09627 if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH)
09628 value = *(isc_boolean_t*)data;
09629 unlock:
09630 #if USE_MBSLOCK
09631 RWUNLOCK(&resolver->mbslock, isc_rwlocktype_read);
09632 #endif
09633 return (value);
09634 }
09635
09636 void
09637 dns_resolver_getclientsperquery(dns_resolver_t *resolver, isc_uint32_t *cur,
09638 isc_uint32_t *min, isc_uint32_t *max)
09639 {
09640 REQUIRE(VALID_RESOLVER(resolver));
09641
09642 LOCK(&resolver->lock);
09643 if (cur != NULL)
09644 *cur = resolver->spillat;
09645 if (min != NULL)
09646 *min = resolver->spillatmin;
09647 if (max != NULL)
09648 *max = resolver->spillatmax;
09649 UNLOCK(&resolver->lock);
09650 }
09651
09652 void
09653 dns_resolver_setclientsperquery(dns_resolver_t *resolver, isc_uint32_t min,
09654 isc_uint32_t max)
09655 {
09656 REQUIRE(VALID_RESOLVER(resolver));
09657
09658 LOCK(&resolver->lock);
09659 resolver->spillatmin = resolver->spillat = min;
09660 resolver->spillatmax = max;
09661 UNLOCK(&resolver->lock);
09662 }
09663
09664 isc_boolean_t
09665 dns_resolver_getzeronosoattl(dns_resolver_t *resolver) {
09666 REQUIRE(VALID_RESOLVER(resolver));
09667
09668 return (resolver->zero_no_soa_ttl);
09669 }
09670
09671 void
09672 dns_resolver_setzeronosoattl(dns_resolver_t *resolver, isc_boolean_t state) {
09673 REQUIRE(VALID_RESOLVER(resolver));
09674
09675 resolver->zero_no_soa_ttl = state;
09676 }
09677
09678 unsigned int
09679 dns_resolver_getoptions(dns_resolver_t *resolver) {
09680 REQUIRE(VALID_RESOLVER(resolver));
09681
09682 return (resolver->options);
09683 }
09684
09685 unsigned int
09686 dns_resolver_gettimeout(dns_resolver_t *resolver) {
09687 REQUIRE(VALID_RESOLVER(resolver));
09688
09689 return (resolver->query_timeout);
09690 }
09691
09692 void
09693 dns_resolver_settimeout(dns_resolver_t *resolver, unsigned int seconds) {
09694 REQUIRE(VALID_RESOLVER(resolver));
09695
09696 if (seconds == 0)
09697 seconds = DEFAULT_QUERY_TIMEOUT;
09698 if (seconds > MAXIMUM_QUERY_TIMEOUT)
09699 seconds = MAXIMUM_QUERY_TIMEOUT;
09700 if (seconds < MINIMUM_QUERY_TIMEOUT)
09701 seconds = MINIMUM_QUERY_TIMEOUT;
09702
09703 resolver->query_timeout = seconds;
09704 }
09705
09706 void
09707 dns_resolver_setquerydscp4(dns_resolver_t *resolver, isc_dscp_t dscp) {
09708 REQUIRE(VALID_RESOLVER(resolver));
09709
09710 resolver->querydscp4 = dscp;
09711 }
09712
09713 isc_dscp_t
09714 dns_resolver_getquerydscp4(dns_resolver_t *resolver) {
09715 REQUIRE(VALID_RESOLVER(resolver));
09716 return (resolver->querydscp4);
09717 }
09718
09719 void
09720 dns_resolver_setquerydscp6(dns_resolver_t *resolver, isc_dscp_t dscp) {
09721 REQUIRE(VALID_RESOLVER(resolver));
09722
09723 resolver->querydscp6 = dscp;
09724 }
09725
09726 isc_dscp_t
09727 dns_resolver_getquerydscp6(dns_resolver_t *resolver) {
09728 REQUIRE(VALID_RESOLVER(resolver));
09729 return (resolver->querydscp6);
09730 }
09731
09732 void
09733 dns_resolver_setmaxdepth(dns_resolver_t *resolver, unsigned int maxdepth) {
09734 REQUIRE(VALID_RESOLVER(resolver));
09735 resolver->maxdepth = maxdepth;
09736 }
09737
09738 unsigned int
09739 dns_resolver_getmaxdepth(dns_resolver_t *resolver) {
09740 REQUIRE(VALID_RESOLVER(resolver));
09741 return (resolver->maxdepth);
09742 }
09743
09744 void
09745 dns_resolver_setmaxqueries(dns_resolver_t *resolver, unsigned int queries) {
09746 REQUIRE(VALID_RESOLVER(resolver));
09747 resolver->maxqueries = queries;
09748 }
09749
09750 unsigned int
09751 dns_resolver_getmaxqueries(dns_resolver_t *resolver) {
09752 REQUIRE(VALID_RESOLVER(resolver));
09753 return (resolver->maxqueries);
09754 }
09755