00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #include <config.h>
00029 #include <stdlib.h>
00030 #include <unistd.h>
00031 #include <string.h>
00032 #include <limits.h>
00033
00034 #ifdef HAVE_LOCALE_H
00035 #include <locale.h>
00036 #endif
00037
00038 #ifdef WITH_IDN
00039 #include <idn/result.h>
00040 #include <idn/log.h>
00041 #include <idn/resconf.h>
00042 #include <idn/api.h>
00043 #endif
00044
00045 #include <dns/byaddr.h>
00046 #ifdef DIG_SIGCHASE
00047 #include <dns/callbacks.h>
00048 #include <dns/dnssec.h>
00049 #include <dns/ds.h>
00050 #include <dns/master.h>
00051 #include <dns/nsec.h>
00052 #include <isc/random.h>
00053 #include <ctype.h>
00054 #endif
00055 #include <dns/fixedname.h>
00056 #include <dns/log.h>
00057 #include <dns/message.h>
00058 #include <dns/name.h>
00059 #include <dns/rcode.h>
00060 #include <dns/rdata.h>
00061 #include <dns/rdataclass.h>
00062 #include <dns/rdatalist.h>
00063 #include <dns/rdataset.h>
00064 #include <dns/rdatastruct.h>
00065 #include <dns/rdatatype.h>
00066 #include <dns/result.h>
00067 #include <dns/tsig.h>
00068
00069 #include <dst/dst.h>
00070 #include <dst/result.h>
00071
00072 #include <isc/app.h>
00073 #include <isc/base64.h>
00074 #include <isc/entropy.h>
00075 #include <isc/file.h>
00076 #include <isc/hex.h>
00077 #include <isc/lang.h>
00078 #include <isc/log.h>
00079 #include <isc/netaddr.h>
00080 #include <isc/netdb.h>
00081 #include <isc/parseint.h>
00082 #include <isc/print.h>
00083 #include <isc/random.h>
00084 #include <isc/result.h>
00085 #include <isc/serial.h>
00086 #include <isc/sockaddr.h>
00087 #include <isc/string.h>
00088 #include <isc/task.h>
00089 #include <isc/timer.h>
00090 #include <isc/types.h>
00091 #include <isc/util.h>
00092
00093 #include <isccfg/namedconf.h>
00094
00095 #include <lwres/lwres.h>
00096 #include <lwres/net.h>
00097
00098 #include <bind9/getaddresses.h>
00099
00100 #include <dig/dig.h>
00101
00102 #ifdef PKCS11CRYPTO
00103 #include <pk11/result.h>
00104 #endif
00105
00106 #if ! defined(NS_INADDRSZ)
00107 #define NS_INADDRSZ 4
00108 #endif
00109
00110 #if ! defined(NS_IN6ADDRSZ)
00111 #define NS_IN6ADDRSZ 16
00112 #endif
00113
00114 static lwres_context_t *lwctx = NULL;
00115 static lwres_conf_t *lwconf;
00116
00117 dig_lookuplist_t lookup_list;
00118 dig_serverlist_t server_list;
00119 dig_searchlistlist_t search_list;
00120
00121 isc_boolean_t
00122 check_ra = ISC_FALSE,
00123 have_ipv4 = ISC_FALSE,
00124 have_ipv6 = ISC_FALSE,
00125 specified_source = ISC_FALSE,
00126 free_now = ISC_FALSE,
00127 cancel_now = ISC_FALSE,
00128 usesearch = ISC_FALSE,
00129 showsearch = ISC_FALSE,
00130 qr = ISC_FALSE,
00131 is_dst_up = ISC_FALSE,
00132 keep_open = ISC_FALSE,
00133 verbose = ISC_FALSE;
00134 in_port_t port = 53;
00135 unsigned int timeout = 0;
00136 unsigned int extrabytes;
00137 isc_mem_t *mctx = NULL;
00138 isc_log_t *lctx = NULL;
00139 isc_taskmgr_t *taskmgr = NULL;
00140 isc_task_t *global_task = NULL;
00141 isc_timermgr_t *timermgr = NULL;
00142 isc_socketmgr_t *socketmgr = NULL;
00143 isc_sockaddr_t bind_address;
00144 isc_sockaddr_t bind_any;
00145 int sendcount = 0;
00146 int recvcount = 0;
00147 int sockcount = 0;
00148 int ndots = -1;
00149 int tries = 3;
00150 int lookup_counter = 0;
00151
00152 #ifdef ISC_PLATFORM_USESIT
00153 static char sitvalue[256];
00154 #endif
00155
00156 #ifdef WITH_IDN
00157 static void initialize_idn(void);
00158 static isc_result_t output_filter(isc_buffer_t *buffer,
00159 unsigned int used_org,
00160 isc_boolean_t absolute);
00161 static idn_result_t append_textname(char *name, const char *origin,
00162 size_t namesize);
00163 static void idn_check_result(idn_result_t r, const char *msg);
00164
00165 #define MAXDLEN 256
00166 int idnoptions = 0;
00167 #endif
00168
00169 isc_socket_t *keep = NULL;
00170 isc_sockaddr_t keepaddr;
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182 int exitcode = 0;
00183 int fatalexit = 0;
00184 char keynametext[MXNAME];
00185 char keyfile[MXNAME] = "";
00186 char keysecret[MXNAME] = "";
00187 unsigned char cookie_secret[33];
00188 unsigned char cookie[8];
00189 dns_name_t *hmacname = NULL;
00190 unsigned int digestbits = 0;
00191 isc_buffer_t *namebuf = NULL;
00192 dns_tsigkey_t *key = NULL;
00193 isc_boolean_t validated = ISC_TRUE;
00194 isc_entropy_t *entp = NULL;
00195 isc_mempool_t *commctx = NULL;
00196 isc_boolean_t debugging = ISC_FALSE;
00197 isc_boolean_t debugtiming = ISC_FALSE;
00198 isc_boolean_t memdebugging = ISC_FALSE;
00199 char *progname = NULL;
00200 isc_mutex_t lookup_lock;
00201 dig_lookup_t *current_lookup = NULL;
00202
00203 #ifdef DIG_SIGCHASE
00204
00205 isc_result_t get_trusted_key(isc_mem_t *mctx);
00206 dns_rdataset_t * sigchase_scanname(dns_rdatatype_t type,
00207 dns_rdatatype_t covers,
00208 isc_boolean_t *lookedup,
00209 dns_name_t *rdata_name);
00210 dns_rdataset_t * chase_scanname_section(dns_message_t *msg,
00211 dns_name_t *name,
00212 dns_rdatatype_t type,
00213 dns_rdatatype_t covers,
00214 int section);
00215 isc_result_t advanced_rrsearch(dns_rdataset_t **rdataset,
00216 dns_name_t *name,
00217 dns_rdatatype_t type,
00218 dns_rdatatype_t covers,
00219 isc_boolean_t *lookedup);
00220 isc_result_t sigchase_verify_sig_key(dns_name_t *name,
00221 dns_rdataset_t *rdataset,
00222 dst_key_t* dnsseckey,
00223 dns_rdataset_t *sigrdataset,
00224 isc_mem_t *mctx);
00225 isc_result_t sigchase_verify_sig(dns_name_t *name,
00226 dns_rdataset_t *rdataset,
00227 dns_rdataset_t *keyrdataset,
00228 dns_rdataset_t *sigrdataset,
00229 isc_mem_t *mctx);
00230 isc_result_t sigchase_verify_ds(dns_name_t *name,
00231 dns_rdataset_t *keyrdataset,
00232 dns_rdataset_t *dsrdataset,
00233 isc_mem_t *mctx);
00234 void sigchase(dns_message_t *msg);
00235 void print_rdata(dns_rdata_t *rdata, isc_mem_t *mctx);
00236 void print_rdataset(dns_name_t *name,
00237 dns_rdataset_t *rdataset, isc_mem_t *mctx);
00238 void dup_name(dns_name_t *source, dns_name_t* target,
00239 isc_mem_t *mctx);
00240 void free_name(dns_name_t *name, isc_mem_t *mctx);
00241 void dump_database(void);
00242 void dump_database_section(dns_message_t *msg, int section);
00243 dns_rdataset_t * search_type(dns_name_t *name, dns_rdatatype_t type,
00244 dns_rdatatype_t covers);
00245 isc_result_t contains_trusted_key(dns_name_t *name,
00246 dns_rdataset_t *rdataset,
00247 dns_rdataset_t *sigrdataset,
00248 isc_mem_t *mctx);
00249 void print_type(dns_rdatatype_t type);
00250 isc_result_t prove_nx_domain(dns_message_t * msg,
00251 dns_name_t * name,
00252 dns_name_t * rdata_name,
00253 dns_rdataset_t ** rdataset,
00254 dns_rdataset_t ** sigrdataset);
00255 isc_result_t prove_nx_type(dns_message_t * msg, dns_name_t *name,
00256 dns_rdataset_t *nsec,
00257 dns_rdataclass_t class,
00258 dns_rdatatype_t type,
00259 dns_name_t * rdata_name,
00260 dns_rdataset_t ** rdataset,
00261 dns_rdataset_t ** sigrdataset);
00262 isc_result_t prove_nx(dns_message_t * msg, dns_name_t * name,
00263 dns_rdataclass_t class,
00264 dns_rdatatype_t type,
00265 dns_name_t * rdata_name,
00266 dns_rdataset_t ** rdataset,
00267 dns_rdataset_t ** sigrdataset);
00268 static void nameFromString(const char *str, dns_name_t *p_ret);
00269 int inf_name(dns_name_t * name1, dns_name_t * name2);
00270 isc_result_t removetmpkey(isc_mem_t *mctx, const char *file);
00271 void clean_trustedkey(void);
00272 isc_result_t insert_trustedkey(void *arg, dns_name_t *name,
00273 dns_rdataset_t *rdataset);
00274 #if DIG_SIGCHASE_BU
00275 isc_result_t getneededrr(dns_message_t *msg);
00276 void sigchase_bottom_up(dns_message_t *msg);
00277 void sigchase_bu(dns_message_t *msg);
00278 #endif
00279 #if DIG_SIGCHASE_TD
00280 isc_result_t initialization(dns_name_t *name);
00281 isc_result_t prepare_lookup(dns_name_t *name);
00282 isc_result_t grandfather_pb_test(dns_name_t * zone_name,
00283 dns_rdataset_t *sigrdataset);
00284 isc_result_t child_of_zone(dns_name_t *name,
00285 dns_name_t *zone_name,
00286 dns_name_t *child_name);
00287 void sigchase_td(dns_message_t *msg);
00288 #endif
00289 char trustedkey[MXNAME] = "";
00290
00291 dns_rdataset_t *chase_rdataset = NULL;
00292 dns_rdataset_t *chase_sigrdataset = NULL;
00293 dns_rdataset_t *chase_dsrdataset = NULL;
00294 dns_rdataset_t *chase_sigdsrdataset = NULL;
00295 dns_rdataset_t *chase_keyrdataset = NULL;
00296 dns_rdataset_t *chase_sigkeyrdataset = NULL;
00297 dns_rdataset_t *chase_nsrdataset = NULL;
00298
00299 dns_name_t chase_name;
00300 #if DIG_SIGCHASE_TD
00301
00302
00303
00304 dns_name_t chase_current_name;
00305
00306
00307
00308 dns_name_t chase_authority_name;
00309 #endif
00310 #if DIG_SIGCHASE_BU
00311 dns_name_t chase_signame;
00312 #endif
00313
00314
00315 isc_boolean_t chase_siglookedup = ISC_FALSE;
00316 isc_boolean_t chase_keylookedup = ISC_FALSE;
00317 isc_boolean_t chase_sigkeylookedup = ISC_FALSE;
00318 isc_boolean_t chase_dslookedup = ISC_FALSE;
00319 isc_boolean_t chase_sigdslookedup = ISC_FALSE;
00320 #if DIG_SIGCHASE_TD
00321 isc_boolean_t chase_nslookedup = ISC_FALSE;
00322 isc_boolean_t chase_lookedup = ISC_FALSE;
00323
00324
00325 isc_boolean_t delegation_follow = ISC_FALSE;
00326 isc_boolean_t grandfather_pb = ISC_FALSE;
00327 isc_boolean_t have_response = ISC_FALSE;
00328 isc_boolean_t have_delegation_ns = ISC_FALSE;
00329 dns_message_t * error_message = NULL;
00330 #endif
00331
00332 isc_boolean_t dsvalidating = ISC_FALSE;
00333 isc_boolean_t chase_name_dup = ISC_FALSE;
00334
00335 ISC_LIST(dig_message_t) chase_message_list;
00336 ISC_LIST(dig_message_t) chase_message_list2;
00337
00338
00339 #define MAX_TRUSTED_KEY 5
00340 typedef struct struct_trusted_key_list {
00341 dst_key_t * key[MAX_TRUSTED_KEY];
00342 int nb_tk;
00343 } struct_tk_list;
00344
00345 struct_tk_list tk_list = { {NULL, NULL, NULL, NULL, NULL}, 0};
00346
00347 #endif
00348
00349 #define DIG_MAX_ADDRESSES 20
00350
00351
00352
00353
00354
00355 #define LOCK_LOOKUP {\
00356 debug("lock_lookup %s:%d", __FILE__, __LINE__);\
00357 check_result(isc_mutex_lock((&lookup_lock)), "isc_mutex_lock");\
00358 debug("success");\
00359 }
00360 #define UNLOCK_LOOKUP {\
00361 debug("unlock_lookup %s:%d", __FILE__, __LINE__);\
00362 check_result(isc_mutex_unlock((&lookup_lock)),\
00363 "isc_mutex_unlock");\
00364 }
00365
00366 static void
00367 cancel_lookup(dig_lookup_t *lookup);
00368
00369 static void
00370 recv_done(isc_task_t *task, isc_event_t *event);
00371
00372 static void
00373 send_udp(dig_query_t *query);
00374
00375 static void
00376 connect_timeout(isc_task_t *task, isc_event_t *event);
00377
00378 static void
00379 launch_next_query(dig_query_t *query, isc_boolean_t include_question);
00380
00381 static void
00382 check_next_lookup(dig_lookup_t *lookup);
00383
00384 static isc_boolean_t
00385 next_origin(dig_lookup_t *oldlookup);
00386
00387 static void *
00388 mem_alloc(void *arg, size_t size) {
00389 return (isc_mem_get(arg, size));
00390 }
00391
00392 static void
00393 mem_free(void *arg, void *mem, size_t size) {
00394 isc_mem_put(arg, mem, size);
00395 }
00396
00397 char *
00398 next_token(char **stringp, const char *delim) {
00399 char *res;
00400
00401 do {
00402 res = strsep(stringp, delim);
00403 if (res == NULL)
00404 break;
00405 } while (*res == '\0');
00406 return (res);
00407 }
00408
00409 static int
00410 count_dots(char *string) {
00411 char *s;
00412 int i = 0;
00413
00414 s = string;
00415 while (*s != '\0') {
00416 if (*s == '.')
00417 i++;
00418 s++;
00419 }
00420 return (i);
00421 }
00422
00423 static void
00424 hex_dump(isc_buffer_t *b) {
00425 unsigned int len, i;
00426 isc_region_t r;
00427
00428 isc_buffer_usedregion(b, &r);
00429
00430 printf("%d bytes\n", r.length);
00431 for (len = 0; len < r.length; len++) {
00432 printf("%02x ", r.base[len]);
00433 if (len % 16 == 15) {
00434 fputs(" ", stdout);
00435 for (i = len - 15; i <= len; i++) {
00436 if (r.base[i] >= '!' && r.base[i] <= '}')
00437 putchar(r.base[i]);
00438 else
00439 putchar('.');
00440 }
00441 printf("\n");
00442 }
00443 }
00444 if (len % 16 != 0) {
00445 for (i = len; (i % 16) != 0; i++)
00446 fputs(" ", stdout);
00447 fputs(" ", stdout);
00448 for (i = ((len>>4)<<4); i < len; i++) {
00449 if (r.base[i] >= '!' && r.base[i] <= '}')
00450 putchar(r.base[i]);
00451 else
00452 putchar('.');
00453 }
00454 printf("\n");
00455 }
00456 }
00457
00458
00459
00460
00461
00462 static isc_result_t
00463 append(const char *text, int len, char **p, char *end) {
00464 if (len > end - *p)
00465 return (ISC_R_NOSPACE);
00466 memmove(*p, text, len);
00467 *p += len;
00468 return (ISC_R_SUCCESS);
00469 }
00470
00471 static isc_result_t
00472 reverse_octets(const char *in, char **p, char *end) {
00473 char *dot = strchr(in, '.');
00474 int len;
00475 if (dot != NULL) {
00476 isc_result_t result;
00477 result = reverse_octets(dot + 1, p, end);
00478 if (result != ISC_R_SUCCESS)
00479 return (result);
00480 result = append(".", 1, p, end);
00481 if (result != ISC_R_SUCCESS)
00482 return (result);
00483 len = (int)(dot - in);
00484 } else {
00485 len = strlen(in);
00486 }
00487 return (append(in, len, p, end));
00488 }
00489
00490 isc_result_t
00491 get_reverse(char *reverse, size_t len, char *value, isc_boolean_t ip6_int,
00492 isc_boolean_t strict)
00493 {
00494 int r;
00495 isc_result_t result;
00496 isc_netaddr_t addr;
00497
00498 addr.family = AF_INET6;
00499 r = inet_pton(AF_INET6, value, &addr.type.in6);
00500 if (r > 0) {
00501
00502 dns_fixedname_t fname;
00503 dns_name_t *name;
00504 unsigned int options = 0;
00505
00506 if (ip6_int)
00507 options |= DNS_BYADDROPT_IPV6INT;
00508 dns_fixedname_init(&fname);
00509 name = dns_fixedname_name(&fname);
00510 result = dns_byaddr_createptrname2(&addr, options, name);
00511 if (result != ISC_R_SUCCESS)
00512 return (result);
00513 dns_name_format(name, reverse, (unsigned int)len);
00514 return (ISC_R_SUCCESS);
00515 } else {
00516
00517
00518
00519
00520
00521
00522
00523
00524 char *p = reverse;
00525 char *end = reverse + len;
00526 if (strict && inet_pton(AF_INET, value, &addr.type.in) != 1)
00527 return (DNS_R_BADDOTTEDQUAD);
00528 result = reverse_octets(value, &p, end);
00529 if (result != ISC_R_SUCCESS)
00530 return (result);
00531
00532 result = append(".in-addr.arpa.", 15, &p, end);
00533 if (result != ISC_R_SUCCESS)
00534 return (result);
00535 return (ISC_R_SUCCESS);
00536 }
00537 }
00538
00539 void
00540 fatal(const char *format, ...) {
00541 va_list args;
00542
00543 fflush(stdout);
00544 fprintf(stderr, "%s: ", progname);
00545 va_start(args, format);
00546 vfprintf(stderr, format, args);
00547 va_end(args);
00548 fprintf(stderr, "\n");
00549 if (exitcode < 10)
00550 exitcode = 10;
00551 if (fatalexit != 0)
00552 exitcode = fatalexit;
00553 exit(exitcode);
00554 }
00555
00556 void
00557 debug(const char *format, ...) {
00558 va_list args;
00559 isc_time_t t;
00560
00561 if (debugging) {
00562 fflush(stdout);
00563 if (debugtiming) {
00564 TIME_NOW(&t);
00565 fprintf(stderr, "%d.%06d: ", isc_time_seconds(&t),
00566 isc_time_nanoseconds(&t) / 1000);
00567 }
00568 va_start(args, format);
00569 vfprintf(stderr, format, args);
00570 va_end(args);
00571 fprintf(stderr, "\n");
00572 }
00573 }
00574
00575 void
00576 check_result(isc_result_t result, const char *msg) {
00577 if (result != ISC_R_SUCCESS) {
00578 fatal("%s: %s", msg, isc_result_totext(result));
00579 }
00580 }
00581
00582
00583
00584
00585
00586
00587 dig_server_t *
00588 make_server(const char *servname, const char *userarg) {
00589 dig_server_t *srv;
00590
00591 REQUIRE(servname != NULL);
00592
00593 debug("make_server(%s)", servname);
00594 srv = isc_mem_allocate(mctx, sizeof(struct dig_server));
00595 if (srv == NULL)
00596 fatal("memory allocation failure in %s:%d",
00597 __FILE__, __LINE__);
00598 strlcpy(srv->servername, servname, MXNAME);
00599 strlcpy(srv->userarg, userarg, MXNAME);
00600 ISC_LINK_INIT(srv, link);
00601 return (srv);
00602 }
00603
00604 static int
00605 addr2af(int lwresaddrtype)
00606 {
00607 int af = 0;
00608
00609 switch (lwresaddrtype) {
00610 case LWRES_ADDRTYPE_V4:
00611 af = AF_INET;
00612 break;
00613
00614 case LWRES_ADDRTYPE_V6:
00615 af = AF_INET6;
00616 break;
00617 }
00618
00619 return (af);
00620 }
00621
00622
00623
00624
00625
00626 static void
00627 copy_server_list(lwres_conf_t *confdata, dig_serverlist_t *dest) {
00628 dig_server_t *newsrv;
00629 char tmp[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255") +
00630 sizeof("%4000000000")];
00631 int af;
00632 int i;
00633
00634 debug("copy_server_list()");
00635 for (i = 0; i < confdata->nsnext; i++) {
00636 af = addr2af(confdata->nameservers[i].family);
00637
00638 if (af == AF_INET && !have_ipv4)
00639 continue;
00640 if (af == AF_INET6 && !have_ipv6)
00641 continue;
00642
00643 lwres_net_ntop(af, confdata->nameservers[i].address,
00644 tmp, sizeof(tmp));
00645 if (af == AF_INET6 && confdata->nameservers[i].zone != 0) {
00646 char buf[sizeof("%4000000000")];
00647 snprintf(buf, sizeof(buf), "%%%u",
00648 confdata->nameservers[i].zone);
00649 strlcat(tmp, buf, sizeof(tmp));
00650 }
00651 newsrv = make_server(tmp, tmp);
00652 ISC_LINK_INIT(newsrv, link);
00653 ISC_LIST_ENQUEUE(*dest, newsrv, link);
00654 }
00655 }
00656
00657 void
00658 flush_server_list(void) {
00659 dig_server_t *s, *ps;
00660
00661 debug("flush_server_list()");
00662 s = ISC_LIST_HEAD(server_list);
00663 while (s != NULL) {
00664 ps = s;
00665 s = ISC_LIST_NEXT(s, link);
00666 ISC_LIST_DEQUEUE(server_list, ps, link);
00667 isc_mem_free(mctx, ps);
00668 }
00669 }
00670
00671 void
00672 set_nameserver(char *opt) {
00673 isc_result_t result;
00674 isc_sockaddr_t sockaddrs[DIG_MAX_ADDRESSES];
00675 isc_netaddr_t netaddr;
00676 int count, i;
00677 dig_server_t *srv;
00678 char tmp[ISC_NETADDR_FORMATSIZE];
00679
00680 if (opt == NULL)
00681 return;
00682
00683 result = bind9_getaddresses(opt, 0, sockaddrs,
00684 DIG_MAX_ADDRESSES, &count);
00685 if (result != ISC_R_SUCCESS)
00686 fatal("couldn't get address for '%s': %s",
00687 opt, isc_result_totext(result));
00688
00689 flush_server_list();
00690
00691 for (i = 0; i < count; i++) {
00692 isc_netaddr_fromsockaddr(&netaddr, &sockaddrs[i]);
00693 isc_netaddr_format(&netaddr, tmp, sizeof(tmp));
00694 srv = make_server(tmp, opt);
00695 if (srv == NULL)
00696 fatal("memory allocation failure");
00697 ISC_LIST_APPEND(server_list, srv, link);
00698 }
00699 }
00700
00701 static isc_result_t
00702 add_nameserver(lwres_conf_t *confdata, const char *addr, int af) {
00703
00704 int i = confdata->nsnext;
00705
00706 if (confdata->nsnext >= LWRES_CONFMAXNAMESERVERS)
00707 return (ISC_R_FAILURE);
00708
00709 switch (af) {
00710 case AF_INET:
00711 confdata->nameservers[i].family = LWRES_ADDRTYPE_V4;
00712 confdata->nameservers[i].length = NS_INADDRSZ;
00713 break;
00714 case AF_INET6:
00715 confdata->nameservers[i].family = LWRES_ADDRTYPE_V6;
00716 confdata->nameservers[i].length = NS_IN6ADDRSZ;
00717 break;
00718 default:
00719 return (ISC_R_FAILURE);
00720 }
00721
00722 if (lwres_net_pton(af, addr, &confdata->nameservers[i].address) == 1) {
00723 confdata->nsnext++;
00724 return (ISC_R_SUCCESS);
00725 }
00726 return (ISC_R_FAILURE);
00727 }
00728
00729
00730
00731
00732
00733 void
00734 clone_server_list(dig_serverlist_t src, dig_serverlist_t *dest) {
00735 dig_server_t *srv, *newsrv;
00736
00737 debug("clone_server_list()");
00738 srv = ISC_LIST_HEAD(src);
00739 while (srv != NULL) {
00740 newsrv = make_server(srv->servername, srv->userarg);
00741 ISC_LINK_INIT(newsrv, link);
00742 ISC_LIST_ENQUEUE(*dest, newsrv, link);
00743 srv = ISC_LIST_NEXT(srv, link);
00744 }
00745 }
00746
00747
00748
00749
00750
00751
00752
00753 dig_lookup_t *
00754 make_empty_lookup(void) {
00755 dig_lookup_t *looknew;
00756
00757 debug("make_empty_lookup()");
00758
00759 INSIST(!free_now);
00760
00761 looknew = isc_mem_allocate(mctx, sizeof(struct dig_lookup));
00762 if (looknew == NULL)
00763 fatal("memory allocation failure in %s:%d",
00764 __FILE__, __LINE__);
00765 looknew->pending = ISC_TRUE;
00766 looknew->textname[0] = 0;
00767 looknew->cmdline[0] = 0;
00768 looknew->rdtype = dns_rdatatype_a;
00769 looknew->qrdtype = dns_rdatatype_a;
00770 looknew->rdclass = dns_rdataclass_in;
00771 looknew->rdtypeset = ISC_FALSE;
00772 looknew->rdclassset = ISC_FALSE;
00773 looknew->sendspace = NULL;
00774 looknew->sendmsg = NULL;
00775 looknew->name = NULL;
00776 looknew->oname = NULL;
00777 looknew->timer = NULL;
00778 looknew->xfr_q = NULL;
00779 looknew->current_query = NULL;
00780 looknew->doing_xfr = ISC_FALSE;
00781 looknew->ixfr_serial = 0;
00782 looknew->trace = ISC_FALSE;
00783 looknew->trace_root = ISC_FALSE;
00784 looknew->identify = ISC_FALSE;
00785 looknew->identify_previous_line = ISC_FALSE;
00786 looknew->ignore = ISC_FALSE;
00787 looknew->servfail_stops = ISC_TRUE;
00788 looknew->besteffort = ISC_TRUE;
00789 looknew->dnssec = ISC_FALSE;
00790 looknew->ednsflags = 0;
00791 looknew->expire = ISC_FALSE;
00792 looknew->nsid = ISC_FALSE;
00793 looknew->header_only = ISC_FALSE;
00794 #ifdef ISC_PLATFORM_USESIT
00795 looknew->sit = ISC_FALSE;
00796 #endif
00797 #ifdef DIG_SIGCHASE
00798 looknew->sigchase = ISC_FALSE;
00799 #if DIG_SIGCHASE_TD
00800 looknew->do_topdown = ISC_FALSE;
00801 looknew->trace_root_sigchase = ISC_FALSE;
00802 looknew->rdtype_sigchaseset = ISC_FALSE;
00803 looknew->rdtype_sigchase = dns_rdatatype_any;
00804 looknew->qrdtype_sigchase = dns_rdatatype_any;
00805 looknew->rdclass_sigchase = dns_rdataclass_in;
00806 looknew->rdclass_sigchaseset = ISC_FALSE;
00807 #endif
00808 #endif
00809 looknew->udpsize = 0;
00810 looknew->edns = -1;
00811 looknew->recurse = ISC_TRUE;
00812 looknew->aaonly = ISC_FALSE;
00813 looknew->adflag = ISC_FALSE;
00814 looknew->cdflag = ISC_FALSE;
00815 looknew->zflag = ISC_FALSE;
00816 looknew->ns_search_only = ISC_FALSE;
00817 looknew->origin = NULL;
00818 looknew->tsigctx = NULL;
00819 looknew->querysig = NULL;
00820 looknew->retries = tries;
00821 looknew->nsfound = 0;
00822 looknew->tcp_mode = ISC_FALSE;
00823 looknew->tcp_mode_set = ISC_FALSE;
00824 looknew->ip6_int = ISC_FALSE;
00825 looknew->comments = ISC_TRUE;
00826 looknew->stats = ISC_TRUE;
00827 looknew->section_question = ISC_TRUE;
00828 looknew->section_answer = ISC_TRUE;
00829 looknew->section_authority = ISC_TRUE;
00830 looknew->section_additional = ISC_TRUE;
00831 looknew->new_search = ISC_FALSE;
00832 looknew->done_as_is = ISC_FALSE;
00833 looknew->need_search = ISC_FALSE;
00834 looknew->ecs_addr = NULL;
00835 #ifdef ISC_PLATFORM_USESIT
00836 looknew->sitvalue = NULL;
00837 #endif
00838 looknew->ednsopts = NULL;
00839 looknew->ednsoptscnt = 0;
00840 looknew->ednsneg = ISC_TRUE;
00841 looknew->dscp = -1;
00842 dns_fixedname_init(&looknew->fdomain);
00843 ISC_LINK_INIT(looknew, link);
00844 ISC_LIST_INIT(looknew->q);
00845 ISC_LIST_INIT(looknew->connecting);
00846 ISC_LIST_INIT(looknew->my_server_list);
00847 return (looknew);
00848 }
00849
00850
00851
00852
00853
00854
00855
00856
00857 dig_lookup_t *
00858 clone_lookup(dig_lookup_t *lookold, isc_boolean_t servers) {
00859 dig_lookup_t *looknew;
00860
00861 debug("clone_lookup()");
00862
00863 INSIST(!free_now);
00864
00865 looknew = make_empty_lookup();
00866 INSIST(looknew != NULL);
00867 strlcpy(looknew->textname, lookold->textname, MXNAME);
00868 #if DIG_SIGCHASE_TD
00869 strlcpy(looknew->textnamesigchase, lookold->textnamesigchase, MXNAME);
00870 #endif
00871 strlcpy(looknew->cmdline, lookold->cmdline, MXNAME);
00872 looknew->textname[MXNAME-1] = 0;
00873 looknew->rdtype = lookold->rdtype;
00874 looknew->qrdtype = lookold->qrdtype;
00875 looknew->rdclass = lookold->rdclass;
00876 looknew->rdtypeset = lookold->rdtypeset;
00877 looknew->rdclassset = lookold->rdclassset;
00878 looknew->doing_xfr = lookold->doing_xfr;
00879 looknew->ixfr_serial = lookold->ixfr_serial;
00880 looknew->trace = lookold->trace;
00881 looknew->trace_root = lookold->trace_root;
00882 looknew->identify = lookold->identify;
00883 looknew->identify_previous_line = lookold->identify_previous_line;
00884 looknew->ignore = lookold->ignore;
00885 looknew->servfail_stops = lookold->servfail_stops;
00886 looknew->besteffort = lookold->besteffort;
00887 looknew->dnssec = lookold->dnssec;
00888 looknew->ednsflags = lookold->ednsflags;
00889 looknew->expire = lookold->expire;
00890 looknew->nsid = lookold->nsid;
00891 looknew->header_only = lookold->header_only;
00892 #ifdef ISC_PLATFORM_USESIT
00893 looknew->sit = lookold->sit;
00894 looknew->sitvalue = lookold->sitvalue;
00895 #endif
00896 looknew->ednsopts = lookold->ednsopts;
00897 looknew->ednsoptscnt = lookold->ednsoptscnt;
00898 looknew->ednsneg = lookold->ednsneg;
00899 #ifdef DIG_SIGCHASE
00900 looknew->sigchase = lookold->sigchase;
00901 #if DIG_SIGCHASE_TD
00902 looknew->do_topdown = lookold->do_topdown;
00903 looknew->trace_root_sigchase = lookold->trace_root_sigchase;
00904 looknew->rdtype_sigchaseset = lookold->rdtype_sigchaseset;
00905 looknew->rdtype_sigchase = lookold->rdtype_sigchase;
00906 looknew->qrdtype_sigchase = lookold->qrdtype_sigchase;
00907 looknew->rdclass_sigchase = lookold->rdclass_sigchase;
00908 looknew->rdclass_sigchaseset = lookold->rdclass_sigchaseset;
00909 #endif
00910 #endif
00911 looknew->udpsize = lookold->udpsize;
00912 looknew->edns = lookold->edns;
00913 looknew->recurse = lookold->recurse;
00914 looknew->aaonly = lookold->aaonly;
00915 looknew->adflag = lookold->adflag;
00916 looknew->cdflag = lookold->cdflag;
00917 looknew->zflag = lookold->zflag;
00918 looknew->ns_search_only = lookold->ns_search_only;
00919 looknew->tcp_mode = lookold->tcp_mode;
00920 looknew->tcp_mode_set = lookold->tcp_mode_set;
00921 looknew->comments = lookold->comments;
00922 looknew->stats = lookold->stats;
00923 looknew->section_question = lookold->section_question;
00924 looknew->section_answer = lookold->section_answer;
00925 looknew->section_authority = lookold->section_authority;
00926 looknew->section_additional = lookold->section_additional;
00927 looknew->retries = lookold->retries;
00928 looknew->tsigctx = NULL;
00929 looknew->need_search = lookold->need_search;
00930 looknew->done_as_is = lookold->done_as_is;
00931 looknew->dscp = lookold->dscp;
00932
00933 if (lookold->ecs_addr != NULL) {
00934 size_t len = sizeof(isc_sockaddr_t);
00935 looknew->ecs_addr = isc_mem_allocate(mctx, len);
00936 if (looknew->ecs_addr == NULL)
00937 fatal("out of memory");
00938 memmove(looknew->ecs_addr, lookold->ecs_addr, len);
00939 }
00940
00941 dns_name_copy(dns_fixedname_name(&lookold->fdomain),
00942 dns_fixedname_name(&looknew->fdomain), NULL);
00943
00944 if (servers)
00945 clone_server_list(lookold->my_server_list,
00946 &looknew->my_server_list);
00947 return (looknew);
00948 }
00949
00950
00951
00952
00953
00954
00955
00956
00957
00958 dig_lookup_t *
00959 requeue_lookup(dig_lookup_t *lookold, isc_boolean_t servers) {
00960 dig_lookup_t *looknew;
00961
00962 debug("requeue_lookup()");
00963
00964 lookup_counter++;
00965 if (lookup_counter > LOOKUP_LIMIT)
00966 fatal("too many lookups");
00967
00968 looknew = clone_lookup(lookold, servers);
00969 INSIST(looknew != NULL);
00970
00971 debug("before insertion, init@%p -> %p, new@%p -> %p",
00972 lookold, lookold->link.next, looknew, looknew->link.next);
00973 ISC_LIST_PREPEND(lookup_list, looknew, link);
00974 debug("after insertion, init -> %p, new = %p, new -> %p",
00975 lookold, looknew, looknew->link.next);
00976 return (looknew);
00977 }
00978
00979
00980 void
00981 setup_text_key(void) {
00982 isc_result_t result;
00983 dns_name_t keyname;
00984 isc_buffer_t secretbuf;
00985 int secretsize;
00986 unsigned char *secretstore;
00987
00988 debug("setup_text_key()");
00989 result = isc_buffer_allocate(mctx, &namebuf, MXNAME);
00990 check_result(result, "isc_buffer_allocate");
00991 dns_name_init(&keyname, NULL);
00992 check_result(result, "dns_name_init");
00993 isc_buffer_putstr(namebuf, keynametext);
00994 secretsize = strlen(keysecret) * 3 / 4;
00995 secretstore = isc_mem_allocate(mctx, secretsize);
00996 if (secretstore == NULL)
00997 fatal("memory allocation failure in %s:%d",
00998 __FILE__, __LINE__);
00999 isc_buffer_init(&secretbuf, secretstore, secretsize);
01000 result = isc_base64_decodestring(keysecret, &secretbuf);
01001 if (result != ISC_R_SUCCESS)
01002 goto failure;
01003
01004 secretsize = isc_buffer_usedlength(&secretbuf);
01005
01006 if (hmacname == NULL) {
01007 result = DST_R_UNSUPPORTEDALG;
01008 goto failure;
01009 }
01010
01011 result = dns_name_fromtext(&keyname, namebuf, dns_rootname, 0, namebuf);
01012 if (result != ISC_R_SUCCESS)
01013 goto failure;
01014
01015 result = dns_tsigkey_create(&keyname, hmacname, secretstore,
01016 secretsize, ISC_FALSE, NULL, 0, 0, mctx,
01017 NULL, &key);
01018 failure:
01019 if (result != ISC_R_SUCCESS)
01020 printf(";; Couldn't create key %s: %s\n",
01021 keynametext, isc_result_totext(result));
01022 else
01023 dst_key_setbits(key->key, digestbits);
01024
01025 isc_mem_free(mctx, secretstore);
01026 dns_name_invalidate(&keyname);
01027 isc_buffer_free(&namebuf);
01028 }
01029
01030 static isc_result_t
01031 parse_uint_helper(isc_uint32_t *uip, const char *value, isc_uint32_t max,
01032 const char *desc, int base) {
01033 isc_uint32_t n;
01034 isc_result_t result = isc_parse_uint32(&n, value, base);
01035 if (result == ISC_R_SUCCESS && n > max)
01036 result = ISC_R_RANGE;
01037 if (result != ISC_R_SUCCESS) {
01038 printf("invalid %s '%s': %s\n", desc,
01039 value, isc_result_totext(result));
01040 return (result);
01041 }
01042 *uip = n;
01043 return (ISC_R_SUCCESS);
01044 }
01045
01046 isc_result_t
01047 parse_uint(isc_uint32_t *uip, const char *value, isc_uint32_t max,
01048 const char *desc) {
01049 return (parse_uint_helper(uip, value, max, desc, 10));
01050 }
01051
01052 isc_result_t
01053 parse_xint(isc_uint32_t *uip, const char *value, isc_uint32_t max,
01054 const char *desc) {
01055 return (parse_uint_helper(uip, value, max, desc, 0));
01056 }
01057
01058 static isc_uint32_t
01059 parse_bits(char *arg, const char *desc, isc_uint32_t max) {
01060 isc_result_t result;
01061 isc_uint32_t tmp;
01062
01063 result = parse_uint(&tmp, arg, max, desc);
01064 if (result != ISC_R_SUCCESS)
01065 fatal("couldn't parse digest bits");
01066 tmp = (tmp + 7) & ~0x7U;
01067 return (tmp);
01068 }
01069
01070 isc_result_t
01071 parse_netprefix(isc_sockaddr_t **sap, const char *value) {
01072 isc_result_t result = ISC_R_SUCCESS;
01073 isc_sockaddr_t *sa = NULL;
01074 struct in_addr in4;
01075 struct in6_addr in6;
01076 isc_uint32_t netmask = 0;
01077 char *slash = NULL;
01078 isc_boolean_t parsed = ISC_FALSE;
01079
01080 if ((slash = strchr(value, '/'))) {
01081 *slash = '\0';
01082 result = isc_parse_uint32(&netmask, slash + 1, 10);
01083 if (result != ISC_R_SUCCESS) {
01084 *slash = '/';
01085 fatal("invalid prefix length '%s': %s\n",
01086 value, isc_result_totext(result));
01087 }
01088 }
01089
01090 sa = isc_mem_allocate(mctx, sizeof(*sa));
01091 if (sa == NULL)
01092 fatal("out of memory");
01093 if (inet_pton(AF_INET6, value, &in6) == 1) {
01094 isc_sockaddr_fromin6(sa, &in6, 0);
01095 parsed = ISC_TRUE;
01096 if (netmask == 0 || netmask > 128)
01097 netmask = 128;
01098 } else if (inet_pton(AF_INET, value, &in4) == 1) {
01099 parsed = ISC_TRUE;
01100 isc_sockaddr_fromin(sa, &in4, 0);
01101 if (netmask == 0 || netmask > 32)
01102 netmask = 32;
01103 } else if (netmask != 0) {
01104 char buf[64];
01105 int i;
01106
01107 strlcpy(buf, value, sizeof(buf));
01108 for (i = 0; i < 3; i++) {
01109 strlcat(buf, ".0", sizeof(buf));
01110 if (inet_pton(AF_INET, buf, &in4) == 1) {
01111 parsed = ISC_TRUE;
01112 isc_sockaddr_fromin(sa, &in4, 0);
01113 break;
01114 }
01115 }
01116
01117 }
01118
01119 if (slash != NULL)
01120 *slash = '/';
01121
01122 if (!parsed)
01123 fatal("invalid address '%s'", value);
01124
01125 sa->length = netmask;
01126 *sap = sa;
01127
01128 return (ISC_R_SUCCESS);
01129 }
01130
01131
01132
01133
01134
01135 void
01136 parse_hmac(const char *hmac) {
01137 char buf[20];
01138 int len;
01139
01140 REQUIRE(hmac != NULL);
01141
01142 len = strlen(hmac);
01143 if (len >= (int) sizeof(buf))
01144 fatal("unknown key type '%.*s'", len, hmac);
01145 strlcpy(buf, hmac, sizeof(buf));
01146
01147 digestbits = 0;
01148
01149 if (strcasecmp(buf, "hmac-md5") == 0) {
01150 hmacname = DNS_TSIG_HMACMD5_NAME;
01151 } else if (strncasecmp(buf, "hmac-md5-", 9) == 0) {
01152 hmacname = DNS_TSIG_HMACMD5_NAME;
01153 digestbits = parse_bits(&buf[9], "digest-bits [0..128]", 128);
01154 } else if (strcasecmp(buf, "hmac-sha1") == 0) {
01155 hmacname = DNS_TSIG_HMACSHA1_NAME;
01156 digestbits = 0;
01157 } else if (strncasecmp(buf, "hmac-sha1-", 10) == 0) {
01158 hmacname = DNS_TSIG_HMACSHA1_NAME;
01159 digestbits = parse_bits(&buf[10], "digest-bits [0..160]", 160);
01160 } else if (strcasecmp(buf, "hmac-sha224") == 0) {
01161 hmacname = DNS_TSIG_HMACSHA224_NAME;
01162 } else if (strncasecmp(buf, "hmac-sha224-", 12) == 0) {
01163 hmacname = DNS_TSIG_HMACSHA224_NAME;
01164 digestbits = parse_bits(&buf[12], "digest-bits [0..224]", 224);
01165 } else if (strcasecmp(buf, "hmac-sha256") == 0) {
01166 hmacname = DNS_TSIG_HMACSHA256_NAME;
01167 } else if (strncasecmp(buf, "hmac-sha256-", 12) == 0) {
01168 hmacname = DNS_TSIG_HMACSHA256_NAME;
01169 digestbits = parse_bits(&buf[12], "digest-bits [0..256]", 256);
01170 } else if (strcasecmp(buf, "hmac-sha384") == 0) {
01171 hmacname = DNS_TSIG_HMACSHA384_NAME;
01172 } else if (strncasecmp(buf, "hmac-sha384-", 12) == 0) {
01173 hmacname = DNS_TSIG_HMACSHA384_NAME;
01174 digestbits = parse_bits(&buf[12], "digest-bits [0..384]", 384);
01175 } else if (strcasecmp(buf, "hmac-sha512") == 0) {
01176 hmacname = DNS_TSIG_HMACSHA512_NAME;
01177 } else if (strncasecmp(buf, "hmac-sha512-", 12) == 0) {
01178 hmacname = DNS_TSIG_HMACSHA512_NAME;
01179 digestbits = parse_bits(&buf[12], "digest-bits [0..512]", 512);
01180 } else {
01181 fprintf(stderr, ";; Warning, ignoring "
01182 "invalid TSIG algorithm %s\n", buf);
01183 }
01184 }
01185
01186
01187
01188
01189 static isc_result_t
01190 read_confkey(void) {
01191 cfg_parser_t *pctx = NULL;
01192 cfg_obj_t *file = NULL;
01193 const cfg_obj_t *keyobj = NULL;
01194 const cfg_obj_t *secretobj = NULL;
01195 const cfg_obj_t *algorithmobj = NULL;
01196 const char *keyname;
01197 const char *secretstr;
01198 const char *algorithm;
01199 isc_result_t result;
01200
01201 if (! isc_file_exists(keyfile))
01202 return (ISC_R_FILENOTFOUND);
01203
01204 result = cfg_parser_create(mctx, NULL, &pctx);
01205 if (result != ISC_R_SUCCESS)
01206 goto cleanup;
01207
01208 result = cfg_parse_file(pctx, keyfile, &cfg_type_sessionkey,
01209 &file);
01210 if (result != ISC_R_SUCCESS)
01211 goto cleanup;
01212
01213 result = cfg_map_get(file, "key", &keyobj);
01214 if (result != ISC_R_SUCCESS)
01215 goto cleanup;
01216
01217 (void) cfg_map_get(keyobj, "secret", &secretobj);
01218 (void) cfg_map_get(keyobj, "algorithm", &algorithmobj);
01219 if (secretobj == NULL || algorithmobj == NULL)
01220 fatal("key must have algorithm and secret");
01221
01222 keyname = cfg_obj_asstring(cfg_map_getname(keyobj));
01223 secretstr = cfg_obj_asstring(secretobj);
01224 algorithm = cfg_obj_asstring(algorithmobj);
01225
01226 strlcpy(keynametext, keyname, sizeof(keynametext));
01227 strlcpy(keysecret, secretstr, sizeof(keysecret));
01228 parse_hmac(algorithm);
01229 setup_text_key();
01230
01231 cleanup:
01232 if (pctx != NULL) {
01233 if (file != NULL)
01234 cfg_obj_destroy(pctx, &file);
01235 cfg_parser_destroy(&pctx);
01236 }
01237
01238 return (result);
01239 }
01240
01241 void
01242 setup_file_key(void) {
01243 isc_result_t result;
01244 dst_key_t *dstkey = NULL;
01245
01246 debug("setup_file_key()");
01247
01248
01249 result = dst_key_fromnamedfile(keyfile, NULL,
01250 DST_TYPE_PRIVATE | DST_TYPE_KEY, mctx,
01251 &dstkey);
01252
01253
01254 if (result != ISC_R_SUCCESS) {
01255 result = read_confkey();
01256 if (result == ISC_R_SUCCESS)
01257 return;
01258 }
01259
01260 if (result != ISC_R_SUCCESS) {
01261 fprintf(stderr, "Couldn't read key from %s: %s\n",
01262 keyfile, isc_result_totext(result));
01263 goto failure;
01264 }
01265
01266 switch (dst_key_alg(dstkey)) {
01267 case DST_ALG_HMACMD5:
01268 hmacname = DNS_TSIG_HMACMD5_NAME;
01269 break;
01270 case DST_ALG_HMACSHA1:
01271 hmacname = DNS_TSIG_HMACSHA1_NAME;
01272 break;
01273 case DST_ALG_HMACSHA224:
01274 hmacname = DNS_TSIG_HMACSHA224_NAME;
01275 break;
01276 case DST_ALG_HMACSHA256:
01277 hmacname = DNS_TSIG_HMACSHA256_NAME;
01278 break;
01279 case DST_ALG_HMACSHA384:
01280 hmacname = DNS_TSIG_HMACSHA384_NAME;
01281 break;
01282 case DST_ALG_HMACSHA512:
01283 hmacname = DNS_TSIG_HMACSHA512_NAME;
01284 break;
01285 default:
01286 printf(";; Couldn't create key %s: bad algorithm\n",
01287 keynametext);
01288 goto failure;
01289 }
01290 result = dns_tsigkey_createfromkey(dst_key_name(dstkey), hmacname,
01291 dstkey, ISC_FALSE, NULL, 0, 0,
01292 mctx, NULL, &key);
01293 if (result != ISC_R_SUCCESS) {
01294 printf(";; Couldn't create key %s: %s\n",
01295 keynametext, isc_result_totext(result));
01296 goto failure;
01297 }
01298 failure:
01299 if (dstkey != NULL)
01300 dst_key_free(&dstkey);
01301 }
01302
01303 static dig_searchlist_t *
01304 make_searchlist_entry(char *domain) {
01305 dig_searchlist_t *search;
01306 search = isc_mem_allocate(mctx, sizeof(*search));
01307 if (search == NULL)
01308 fatal("memory allocation failure in %s:%d",
01309 __FILE__, __LINE__);
01310 strlcpy(search->origin, domain, MXNAME);
01311 search->origin[MXNAME-1] = 0;
01312 ISC_LINK_INIT(search, link);
01313 return (search);
01314 }
01315
01316 static void
01317 clear_searchlist(void) {
01318 dig_searchlist_t *search;
01319 while ((search = ISC_LIST_HEAD(search_list)) != NULL) {
01320 ISC_LIST_UNLINK(search_list, search, link);
01321 isc_mem_free(mctx, search);
01322 }
01323 }
01324
01325 static void
01326 create_search_list(lwres_conf_t *confdata) {
01327 int i;
01328 dig_searchlist_t *search;
01329
01330 debug("create_search_list()");
01331 clear_searchlist();
01332
01333 for (i = 0; i < confdata->searchnxt; i++) {
01334 search = make_searchlist_entry(confdata->search[i]);
01335 ISC_LIST_APPEND(search_list, search, link);
01336 }
01337 }
01338
01339
01340
01341
01342
01343 void
01344 setup_system(void) {
01345 dig_searchlist_t *domain = NULL;
01346 lwres_result_t lwresult;
01347 unsigned int lwresflags;
01348 isc_result_t result;
01349
01350 debug("setup_system()");
01351
01352 lwresflags = LWRES_CONTEXT_SERVERMODE;
01353 if (have_ipv4)
01354 lwresflags |= LWRES_CONTEXT_USEIPV4;
01355 if (have_ipv6)
01356 lwresflags |= LWRES_CONTEXT_USEIPV6;
01357
01358 lwresult = lwres_context_create(&lwctx, mctx, mem_alloc, mem_free,
01359 lwresflags);
01360 if (lwresult != LWRES_R_SUCCESS)
01361 fatal("lwres_context_create failed");
01362
01363 lwresult = lwres_conf_parse(lwctx, RESOLV_CONF);
01364 if (lwresult != LWRES_R_SUCCESS && lwresult != LWRES_R_NOTFOUND)
01365 fatal("parse of %s failed", RESOLV_CONF);
01366
01367 lwconf = lwres_conf_get(lwctx);
01368
01369
01370 if (lwconf->searchnxt > 0)
01371 create_search_list(lwconf);
01372 else {
01373 if (lwconf->domainname != NULL) {
01374 domain = make_searchlist_entry(lwconf->domainname);
01375 ISC_LIST_APPEND(search_list, domain, link);
01376 domain = NULL;
01377 }
01378 }
01379
01380 if (lwconf->resdebug) {
01381 verbose = ISC_TRUE;
01382 debug("verbose is on");
01383 }
01384 if (ndots == -1) {
01385 ndots = lwconf->ndots;
01386 debug("ndots is %d.", ndots);
01387 }
01388 if (lwconf->attempts) {
01389 tries = lwconf->attempts + 1;
01390 if (tries < 2)
01391 tries = 2;
01392 debug("tries is %d.", tries);
01393 }
01394 if (lwconf->timeout) {
01395 timeout = lwconf->timeout;
01396 debug("timeout is %d.", timeout);
01397 }
01398
01399
01400 if (ISC_LIST_EMPTY(server_list))
01401 copy_server_list(lwconf, &server_list);
01402
01403
01404 if (ISC_LIST_EMPTY(server_list)) {
01405 if (have_ipv4) {
01406 lwresult = add_nameserver(lwconf, "127.0.0.1", AF_INET);
01407 if (lwresult != ISC_R_SUCCESS)
01408 fatal("add_nameserver failed");
01409 }
01410 if (have_ipv6) {
01411 lwresult = add_nameserver(lwconf, "::1", AF_INET6);
01412 if (lwresult != ISC_R_SUCCESS)
01413 fatal("add_nameserver failed");
01414 }
01415
01416 copy_server_list(lwconf, &server_list);
01417 }
01418
01419 #ifdef WITH_IDN
01420 initialize_idn();
01421 #endif
01422
01423 if (keyfile[0] != 0)
01424 setup_file_key();
01425 else if (keysecret[0] != 0)
01426 setup_text_key();
01427 #ifdef DIG_SIGCHASE
01428
01429 ISC_LIST_INIT(chase_message_list);
01430 ISC_LIST_INIT(chase_message_list2);
01431 dns_name_init(&chase_name, NULL);
01432 #if DIG_SIGCHASE_TD
01433 dns_name_init(&chase_current_name, NULL);
01434 dns_name_init(&chase_authority_name, NULL);
01435 #endif
01436 #if DIG_SIGCHASE_BU
01437 dns_name_init(&chase_signame, NULL);
01438 #endif
01439
01440 #endif
01441 result = isc_entropy_getdata(entp, cookie_secret,
01442 sizeof(cookie_secret), NULL, 0);
01443 if (result != ISC_R_SUCCESS)
01444 fatal("unable to generate cookie secret");
01445 }
01446
01447
01448
01449
01450 void
01451 set_search_domain(char *domain) {
01452 dig_searchlist_t *search;
01453
01454 clear_searchlist();
01455 search = make_searchlist_entry(domain);
01456 ISC_LIST_APPEND(search_list, search, link);
01457 }
01458
01459
01460
01461
01462 void
01463 setup_libs(void) {
01464 isc_result_t result;
01465 isc_logconfig_t *logconfig = NULL;
01466
01467 debug("setup_libs()");
01468
01469 #ifdef PKCS11CRYPTO
01470 pk11_result_register();
01471 #endif
01472 dns_result_register();
01473
01474 result = isc_net_probeipv4();
01475 if (result == ISC_R_SUCCESS)
01476 have_ipv4 = ISC_TRUE;
01477
01478 result = isc_net_probeipv6();
01479 if (result == ISC_R_SUCCESS)
01480 have_ipv6 = ISC_TRUE;
01481 if (!have_ipv6 && !have_ipv4)
01482 fatal("can't find either v4 or v6 networking");
01483
01484 result = isc_mem_create(0, 0, &mctx);
01485 check_result(result, "isc_mem_create");
01486 isc_mem_setname(mctx, "dig", NULL);
01487
01488 result = isc_log_create(mctx, &lctx, &logconfig);
01489 check_result(result, "isc_log_create");
01490
01491 isc_log_setcontext(lctx);
01492 dns_log_init(lctx);
01493 dns_log_setcontext(lctx);
01494
01495 result = isc_log_usechannel(logconfig, "default_debug", NULL, NULL);
01496 check_result(result, "isc_log_usechannel");
01497
01498 isc_log_setdebuglevel(lctx, 0);
01499
01500 result = isc_taskmgr_create(mctx, 1, 0, &taskmgr);
01501 check_result(result, "isc_taskmgr_create");
01502
01503 result = isc_task_create(taskmgr, 0, &global_task);
01504 check_result(result, "isc_task_create");
01505 isc_task_setname(global_task, "dig", NULL);
01506
01507 result = isc_timermgr_create(mctx, &timermgr);
01508 check_result(result, "isc_timermgr_create");
01509
01510 result = isc_socketmgr_create(mctx, &socketmgr);
01511 check_result(result, "isc_socketmgr_create");
01512
01513 result = isc_entropy_create(mctx, &entp);
01514 check_result(result, "isc_entropy_create");
01515
01516 result = dst_lib_init(mctx, entp, 0);
01517 check_result(result, "dst_lib_init");
01518 is_dst_up = ISC_TRUE;
01519
01520 result = isc_mempool_create(mctx, COMMSIZE, &commctx);
01521 check_result(result, "isc_mempool_create");
01522 isc_mempool_setname(commctx, "COMMPOOL");
01523
01524
01525
01526
01527 isc_mempool_setfreemax(commctx, 6);
01528 isc_mempool_setfillcount(commctx, 2);
01529
01530 result = isc_mutex_init(&lookup_lock);
01531 check_result(result, "isc_mutex_init");
01532 }
01533
01534 #define EDNSOPTS 100U
01535 static dns_ednsopt_t ednsopts[EDNSOPTS];
01536 static unsigned char ednsoptscnt = 0;
01537
01538 void
01539 save_opt(dig_lookup_t *lookup, char *code, char *value) {
01540 isc_uint32_t num;
01541 isc_buffer_t b;
01542 isc_result_t result;
01543
01544 if (ednsoptscnt == EDNSOPTS)
01545 fatal("too many ednsopts");
01546
01547 result = parse_uint(&num, code, 65535, "ednsopt");
01548 if (result != ISC_R_SUCCESS)
01549 fatal("bad edns code point: %s", code);
01550
01551 ednsopts[ednsoptscnt].code = num;
01552 ednsopts[ednsoptscnt].length = 0;
01553 ednsopts[ednsoptscnt].value = NULL;
01554
01555 if (value != NULL) {
01556 char *buf;
01557 buf = isc_mem_allocate(mctx, strlen(value)/2 + 1);
01558 if (buf == NULL)
01559 fatal("out of memory");
01560 isc_buffer_init(&b, buf, strlen(value)/2 + 1);
01561 result = isc_hex_decodestring(value, &b);
01562 check_result(result, "isc_hex_decodestring");
01563 ednsopts[ednsoptscnt].value = isc_buffer_base(&b);
01564 ednsopts[ednsoptscnt].length = isc_buffer_usedlength(&b);
01565 }
01566
01567 if (lookup->ednsoptscnt == 0)
01568 lookup->ednsopts = &ednsopts[ednsoptscnt];
01569 lookup->ednsoptscnt++;
01570 ednsoptscnt++;
01571 }
01572
01573
01574
01575
01576
01577
01578 static void
01579 add_opt(dns_message_t *msg, isc_uint16_t udpsize, isc_uint16_t edns,
01580 unsigned int flags, dns_ednsopt_t *opts, size_t count)
01581 {
01582 dns_rdataset_t *rdataset = NULL;
01583 isc_result_t result;
01584
01585 debug("add_opt()");
01586 result = dns_message_buildopt(msg, &rdataset, edns, udpsize, flags,
01587 opts, count);
01588 check_result(result, "dns_message_buildopt");
01589 result = dns_message_setopt(msg, rdataset);
01590 check_result(result, "dns_message_setopt");
01591 }
01592
01593
01594
01595
01596
01597 static void
01598 add_question(dns_message_t *message, dns_name_t *name,
01599 dns_rdataclass_t rdclass, dns_rdatatype_t rdtype)
01600 {
01601 dns_rdataset_t *rdataset;
01602 isc_result_t result;
01603
01604 debug("add_question()");
01605 rdataset = NULL;
01606 result = dns_message_gettemprdataset(message, &rdataset);
01607 check_result(result, "dns_message_gettemprdataset()");
01608 dns_rdataset_init(rdataset);
01609 dns_rdataset_makequestion(rdataset, rdclass, rdtype);
01610 ISC_LIST_APPEND(name->list, rdataset, link);
01611 }
01612
01613
01614
01615
01616
01617
01618
01619
01620
01621 static void
01622 check_if_done(void) {
01623 debug("check_if_done()");
01624 debug("list %s", ISC_LIST_EMPTY(lookup_list) ? "empty" : "full");
01625 if (ISC_LIST_EMPTY(lookup_list) && current_lookup == NULL &&
01626 sendcount == 0) {
01627 INSIST(sockcount == 0);
01628 INSIST(recvcount == 0);
01629 debug("shutting down");
01630 dighost_shutdown();
01631 }
01632 }
01633
01634
01635
01636
01637
01638 static void
01639 clear_query(dig_query_t *query) {
01640 dig_lookup_t *lookup;
01641
01642 REQUIRE(query != NULL);
01643
01644 debug("clear_query(%p)", query);
01645
01646 lookup = query->lookup;
01647
01648 if (lookup->current_query == query)
01649 lookup->current_query = NULL;
01650
01651 if (ISC_LINK_LINKED(query, link))
01652 ISC_LIST_UNLINK(lookup->q, query, link);
01653 if (ISC_LINK_LINKED(query, clink))
01654 ISC_LIST_UNLINK(lookup->connecting, query, clink);
01655 if (ISC_LINK_LINKED(&query->recvbuf, link))
01656 ISC_LIST_DEQUEUE(query->recvlist, &query->recvbuf,
01657 link);
01658 if (ISC_LINK_LINKED(&query->lengthbuf, link))
01659 ISC_LIST_DEQUEUE(query->lengthlist, &query->lengthbuf,
01660 link);
01661 INSIST(query->recvspace != NULL);
01662
01663 if (query->sock != NULL) {
01664 isc_socket_detach(&query->sock);
01665 sockcount--;
01666 debug("sockcount=%d", sockcount);
01667 }
01668 isc_mempool_put(commctx, query->recvspace);
01669 isc_buffer_invalidate(&query->recvbuf);
01670 isc_buffer_invalidate(&query->lengthbuf);
01671 if (query->waiting_senddone)
01672 query->pending_free = ISC_TRUE;
01673 else
01674 isc_mem_free(mctx, query);
01675 }
01676
01677
01678
01679
01680
01681
01682 static isc_boolean_t
01683 try_clear_lookup(dig_lookup_t *lookup) {
01684 dig_query_t *q;
01685
01686 REQUIRE(lookup != NULL);
01687
01688 debug("try_clear_lookup(%p)", lookup);
01689
01690 if (ISC_LIST_HEAD(lookup->q) != NULL ||
01691 ISC_LIST_HEAD(lookup->connecting) != NULL)
01692 {
01693 if (debugging) {
01694 q = ISC_LIST_HEAD(lookup->q);
01695 while (q != NULL) {
01696 debug("query to %s still pending", q->servname);
01697 q = ISC_LIST_NEXT(q, link);
01698 }
01699
01700 q = ISC_LIST_HEAD(lookup->connecting);
01701 while (q != NULL) {
01702 debug("query to %s still connecting",
01703 q->servname);
01704 q = ISC_LIST_NEXT(q, clink);
01705 }
01706 }
01707 return (ISC_FALSE);
01708 }
01709
01710
01711
01712
01713
01714 destroy_lookup(lookup);
01715 return (ISC_TRUE);
01716 }
01717
01718 void
01719 destroy_lookup(dig_lookup_t *lookup) {
01720 dig_server_t *s;
01721 void *ptr;
01722
01723 debug("destroy");
01724 s = ISC_LIST_HEAD(lookup->my_server_list);
01725 while (s != NULL) {
01726 debug("freeing server %p belonging to %p", s, lookup);
01727 ptr = s;
01728 s = ISC_LIST_NEXT(s, link);
01729 ISC_LIST_DEQUEUE(lookup->my_server_list,
01730 (dig_server_t *)ptr, link);
01731 isc_mem_free(mctx, ptr);
01732 }
01733 if (lookup->sendmsg != NULL)
01734 dns_message_destroy(&lookup->sendmsg);
01735 if (lookup->querysig != NULL) {
01736 debug("freeing buffer %p", lookup->querysig);
01737 isc_buffer_free(&lookup->querysig);
01738 }
01739 if (lookup->timer != NULL)
01740 isc_timer_detach(&lookup->timer);
01741 if (lookup->sendspace != NULL)
01742 isc_mempool_put(commctx, lookup->sendspace);
01743
01744 if (lookup->tsigctx != NULL)
01745 dst_context_destroy(&lookup->tsigctx);
01746
01747 if (lookup->ecs_addr != NULL)
01748 isc_mem_free(mctx, lookup->ecs_addr);
01749
01750 isc_mem_free(mctx, lookup);
01751 }
01752
01753
01754
01755
01756
01757
01758
01759 void
01760 start_lookup(void) {
01761 debug("start_lookup()");
01762 if (cancel_now)
01763 return;
01764
01765
01766
01767
01768
01769 INSIST(current_lookup == NULL);
01770
01771 current_lookup = ISC_LIST_HEAD(lookup_list);
01772
01773
01774
01775 if (current_lookup != NULL) {
01776 ISC_LIST_DEQUEUE(lookup_list, current_lookup, link);
01777 #if DIG_SIGCHASE_TD
01778 if (current_lookup->do_topdown &&
01779 !current_lookup->rdtype_sigchaseset) {
01780 dst_key_t *trustedkey = NULL;
01781 isc_buffer_t *b = NULL;
01782 isc_region_t r;
01783 isc_result_t result;
01784 dns_name_t query_name;
01785 dns_name_t *key_name;
01786 int i;
01787
01788 result = get_trusted_key(mctx);
01789 if (result != ISC_R_SUCCESS) {
01790 printf("\n;; No trusted key, "
01791 "+sigchase option is disabled\n");
01792 current_lookup->sigchase = ISC_FALSE;
01793 goto novalidation;
01794 }
01795 dns_name_init(&query_name, NULL);
01796 nameFromString(current_lookup->textname, &query_name);
01797
01798 for (i = 0; i < tk_list.nb_tk; i++) {
01799 key_name = dst_key_name(tk_list.key[i]);
01800
01801 if (dns_name_issubdomain(&query_name,
01802 key_name) == ISC_TRUE)
01803 trustedkey = tk_list.key[i];
01804
01805
01806
01807
01808 }
01809 if (trustedkey == NULL) {
01810 printf("\n;; The queried zone: ");
01811 dns_name_print(&query_name, stdout);
01812 printf(" isn't a subdomain of any Trusted Keys"
01813 ": +sigchase option is disable\n");
01814 current_lookup->sigchase = ISC_FALSE;
01815 free_name(&query_name, mctx);
01816 goto novalidation;
01817 }
01818 free_name(&query_name, mctx);
01819
01820 current_lookup->rdtype_sigchase
01821 = current_lookup->rdtype;
01822 current_lookup->rdtype_sigchaseset
01823 = current_lookup->rdtypeset;
01824 current_lookup->rdtype = dns_rdatatype_ns;
01825
01826 current_lookup->qrdtype_sigchase
01827 = current_lookup->qrdtype;
01828 current_lookup->qrdtype = dns_rdatatype_ns;
01829
01830 current_lookup->rdclass_sigchase
01831 = current_lookup->rdclass;
01832 current_lookup->rdclass_sigchaseset
01833 = current_lookup->rdclassset;
01834 current_lookup->rdclass = dns_rdataclass_in;
01835
01836 strlcpy(current_lookup->textnamesigchase,
01837 current_lookup->textname, MXNAME);
01838
01839 current_lookup->trace_root_sigchase = ISC_TRUE;
01840
01841 result = isc_buffer_allocate(mctx, &b, BUFSIZE);
01842 check_result(result, "isc_buffer_allocate");
01843 result = dns_name_totext(dst_key_name(trustedkey),
01844 ISC_FALSE, b);
01845 check_result(result, "dns_name_totext");
01846 isc_buffer_usedregion(b, &r);
01847 r.base[r.length] = '\0';
01848 strlcpy(current_lookup->textname, (char*)r.base,
01849 MXNAME);
01850 isc_buffer_free(&b);
01851
01852 nameFromString(current_lookup->textnamesigchase,
01853 &chase_name);
01854
01855 dns_name_init(&chase_authority_name, NULL);
01856 }
01857 novalidation:
01858 #endif
01859 if (setup_lookup(current_lookup))
01860 do_lookup(current_lookup);
01861 else if (next_origin(current_lookup))
01862 check_next_lookup(current_lookup);
01863 } else {
01864 check_if_done();
01865 }
01866 }
01867
01868
01869
01870
01871
01872 static void
01873 check_next_lookup(dig_lookup_t *lookup) {
01874
01875 INSIST(!free_now);
01876
01877 debug("check_next_lookup(%p)", lookup);
01878
01879 if (ISC_LIST_HEAD(lookup->q) != NULL) {
01880 debug("still have a worker");
01881 return;
01882 }
01883 if (try_clear_lookup(lookup)) {
01884 current_lookup = NULL;
01885 start_lookup();
01886 }
01887 }
01888
01889
01890
01891
01892
01893
01894
01895 static int
01896 followup_lookup(dns_message_t *msg, dig_query_t *query, dns_section_t section)
01897 {
01898 dig_lookup_t *lookup = NULL;
01899 dig_server_t *srv = NULL;
01900 dns_rdataset_t *rdataset = NULL;
01901 dns_rdata_t rdata = DNS_RDATA_INIT;
01902 dns_name_t *name = NULL;
01903 isc_result_t result;
01904 isc_boolean_t success = ISC_FALSE;
01905 int numLookups = 0;
01906 int num;
01907 isc_result_t lresult, addresses_result;
01908 char bad_namestr[DNS_NAME_FORMATSIZE];
01909 dns_name_t *domain;
01910 isc_boolean_t horizontal = ISC_FALSE, bad = ISC_FALSE;
01911
01912 INSIST(!free_now);
01913
01914 debug("following up %s", query->lookup->textname);
01915
01916 addresses_result = ISC_R_SUCCESS;
01917 bad_namestr[0] = '\0';
01918 for (result = dns_message_firstname(msg, section);
01919 result == ISC_R_SUCCESS;
01920 result = dns_message_nextname(msg, section)) {
01921 name = NULL;
01922 dns_message_currentname(msg, section, &name);
01923
01924 if (section == DNS_SECTION_AUTHORITY) {
01925 rdataset = NULL;
01926 result = dns_message_findtype(name, dns_rdatatype_soa,
01927 0, &rdataset);
01928 if (result == ISC_R_SUCCESS)
01929 return (0);
01930 }
01931 rdataset = NULL;
01932 result = dns_message_findtype(name, dns_rdatatype_ns, 0,
01933 &rdataset);
01934 if (result != ISC_R_SUCCESS)
01935 continue;
01936
01937 debug("found NS set");
01938
01939 if (query->lookup->trace && !query->lookup->trace_root) {
01940 dns_namereln_t namereln;
01941 unsigned int nlabels;
01942 int order;
01943
01944 domain = dns_fixedname_name(&query->lookup->fdomain);
01945 namereln = dns_name_fullcompare(name, domain,
01946 &order, &nlabels);
01947 if (namereln == dns_namereln_equal) {
01948 if (!horizontal)
01949 printf(";; BAD (HORIZONTAL) REFERRAL\n");
01950 horizontal = ISC_TRUE;
01951 } else if (namereln != dns_namereln_subdomain) {
01952 if (!bad)
01953 printf(";; BAD REFERRAL\n");
01954 bad = ISC_TRUE;
01955 continue;
01956 }
01957 }
01958
01959 for (result = dns_rdataset_first(rdataset);
01960 result == ISC_R_SUCCESS;
01961 result = dns_rdataset_next(rdataset)) {
01962 char namestr[DNS_NAME_FORMATSIZE];
01963 dns_rdata_ns_t ns;
01964
01965 if (query->lookup->trace_root &&
01966 query->lookup->nsfound >= MXSERV)
01967 break;
01968
01969 dns_rdataset_current(rdataset, &rdata);
01970
01971 query->lookup->nsfound++;
01972 result = dns_rdata_tostruct(&rdata, &ns, NULL);
01973 check_result(result, "dns_rdata_tostruct");
01974 dns_name_format(&ns.name, namestr, sizeof(namestr));
01975 dns_rdata_freestruct(&ns);
01976
01977
01978 debug("found NS %s", namestr);
01979 if (!success) {
01980 success = ISC_TRUE;
01981 lookup_counter++;
01982 lookup = requeue_lookup(query->lookup,
01983 ISC_FALSE);
01984 cancel_lookup(query->lookup);
01985 lookup->doing_xfr = ISC_FALSE;
01986 if (!lookup->trace_root &&
01987 section == DNS_SECTION_ANSWER)
01988 lookup->trace = ISC_FALSE;
01989 else
01990 lookup->trace = query->lookup->trace;
01991 lookup->ns_search_only =
01992 query->lookup->ns_search_only;
01993 lookup->trace_root = ISC_FALSE;
01994 if (lookup->ns_search_only)
01995 lookup->recurse = ISC_FALSE;
01996 domain = dns_fixedname_name(&lookup->fdomain);
01997 dns_name_copy(name, domain, NULL);
01998 }
01999 debug("adding server %s", namestr);
02000 num = getaddresses(lookup, namestr, &lresult);
02001 if (lresult != ISC_R_SUCCESS) {
02002 printf("couldn't get address for '%s': %s\n",
02003 namestr, isc_result_totext(lresult));
02004 if (addresses_result == ISC_R_SUCCESS) {
02005 addresses_result = lresult;
02006 strcpy(bad_namestr, namestr);
02007 }
02008 }
02009 numLookups += num;
02010 dns_rdata_reset(&rdata);
02011 }
02012 }
02013 if (numLookups == 0 && addresses_result != ISC_R_SUCCESS) {
02014 fatal("couldn't get address for '%s': %s",
02015 bad_namestr, isc_result_totext(result));
02016 }
02017
02018 if (lookup == NULL &&
02019 section == DNS_SECTION_ANSWER &&
02020 (query->lookup->trace || query->lookup->ns_search_only))
02021 return (followup_lookup(msg, query, DNS_SECTION_AUTHORITY));
02022
02023
02024
02025
02026 if (numLookups > 1) {
02027 isc_uint32_t i, j;
02028 dig_serverlist_t my_server_list;
02029 dig_server_t *next;
02030
02031 ISC_LIST_INIT(my_server_list);
02032
02033 i = numLookups;
02034 for (srv = ISC_LIST_HEAD(lookup->my_server_list);
02035 srv != NULL;
02036 srv = ISC_LIST_HEAD(lookup->my_server_list)) {
02037 INSIST(i > 0);
02038 isc_random_get(&j);
02039 j %= i;
02040 next = ISC_LIST_NEXT(srv, link);
02041 while (j-- > 0 && next != NULL) {
02042 srv = next;
02043 next = ISC_LIST_NEXT(srv, link);
02044 }
02045 ISC_LIST_DEQUEUE(lookup->my_server_list, srv, link);
02046 ISC_LIST_APPEND(my_server_list, srv, link);
02047 i--;
02048 }
02049 ISC_LIST_APPENDLIST(lookup->my_server_list,
02050 my_server_list, link);
02051 }
02052
02053 return (numLookups);
02054 }
02055
02056
02057
02058
02059
02060
02061
02062 static isc_boolean_t
02063 next_origin(dig_lookup_t *oldlookup) {
02064 dig_lookup_t *newlookup;
02065 dig_searchlist_t *search;
02066 dns_fixedname_t fixed;
02067 dns_name_t *name;
02068 isc_result_t result;
02069
02070 INSIST(!free_now);
02071
02072 debug("next_origin()");
02073 debug("following up %s", oldlookup->textname);
02074
02075 if (!usesearch)
02076
02077
02078
02079
02080 return (ISC_FALSE);
02081
02082
02083
02084
02085 dns_fixedname_init(&fixed);
02086 name = dns_fixedname_name(&fixed);
02087 result = dns_name_fromstring2(name, oldlookup->textname, NULL,
02088 0, NULL);
02089 if (result == ISC_R_SUCCESS &&
02090 (dns_name_isabsolute(name) ||
02091 (int)dns_name_countlabels(name) > ndots))
02092 return (ISC_FALSE);
02093
02094 if (oldlookup->origin == NULL && !oldlookup->need_search)
02095
02096
02097
02098 return (ISC_FALSE);
02099 if (oldlookup->origin == NULL && oldlookup->need_search) {
02100 newlookup = requeue_lookup(oldlookup, ISC_TRUE);
02101 newlookup->origin = ISC_LIST_HEAD(search_list);
02102 newlookup->need_search = ISC_FALSE;
02103 } else {
02104 search = ISC_LIST_NEXT(oldlookup->origin, link);
02105 if (search == NULL && oldlookup->done_as_is)
02106 return (ISC_FALSE);
02107 newlookup = requeue_lookup(oldlookup, ISC_TRUE);
02108 newlookup->origin = search;
02109 }
02110 cancel_lookup(oldlookup);
02111 return (ISC_TRUE);
02112 }
02113
02114
02115
02116
02117
02118 static void
02119 insert_soa(dig_lookup_t *lookup) {
02120 isc_result_t result;
02121 dns_rdata_soa_t soa;
02122 dns_rdata_t *rdata = NULL;
02123 dns_rdatalist_t *rdatalist = NULL;
02124 dns_rdataset_t *rdataset = NULL;
02125 dns_name_t *soaname = NULL;
02126
02127 debug("insert_soa()");
02128 soa.mctx = mctx;
02129 soa.serial = lookup->ixfr_serial;
02130 soa.refresh = 0;
02131 soa.retry = 0;
02132 soa.expire = 0;
02133 soa.minimum = 0;
02134 soa.common.rdclass = lookup->rdclass;
02135 soa.common.rdtype = dns_rdatatype_soa;
02136
02137 dns_name_init(&soa.origin, NULL);
02138 dns_name_init(&soa.contact, NULL);
02139
02140 dns_name_clone(dns_rootname, &soa.origin);
02141 dns_name_clone(dns_rootname, &soa.contact);
02142
02143 isc_buffer_init(&lookup->rdatabuf, lookup->rdatastore,
02144 sizeof(lookup->rdatastore));
02145
02146 result = dns_message_gettemprdata(lookup->sendmsg, &rdata);
02147 check_result(result, "dns_message_gettemprdata");
02148
02149 result = dns_rdata_fromstruct(rdata, lookup->rdclass,
02150 dns_rdatatype_soa, &soa,
02151 &lookup->rdatabuf);
02152 check_result(result, "isc_rdata_fromstruct");
02153
02154 result = dns_message_gettemprdatalist(lookup->sendmsg, &rdatalist);
02155 check_result(result, "dns_message_gettemprdatalist");
02156
02157 result = dns_message_gettemprdataset(lookup->sendmsg, &rdataset);
02158 check_result(result, "dns_message_gettemprdataset");
02159
02160 dns_rdatalist_init(rdatalist);
02161 rdatalist->type = dns_rdatatype_soa;
02162 rdatalist->rdclass = lookup->rdclass;
02163 ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
02164
02165 dns_rdataset_init(rdataset);
02166 dns_rdatalist_tordataset(rdatalist, rdataset);
02167
02168 result = dns_message_gettempname(lookup->sendmsg, &soaname);
02169 check_result(result, "dns_message_gettempname");
02170 dns_name_init(soaname, NULL);
02171 dns_name_clone(lookup->name, soaname);
02172 ISC_LIST_INIT(soaname->list);
02173 ISC_LIST_APPEND(soaname->list, rdataset, link);
02174 dns_message_addname(lookup->sendmsg, soaname, DNS_SECTION_AUTHORITY);
02175 }
02176
02177 #ifdef ISC_PLATFORM_USESIT
02178 static void
02179 compute_cookie(unsigned char *clientcookie, size_t len) {
02180
02181 INSIST(len >= 8U);
02182 memmove(clientcookie, cookie_secret, 8);
02183 }
02184 #endif
02185
02186
02187
02188
02189
02190
02191
02192 isc_boolean_t
02193 setup_lookup(dig_lookup_t *lookup) {
02194 isc_result_t result;
02195 isc_uint32_t id;
02196 int len;
02197 dig_server_t *serv;
02198 dig_query_t *query;
02199 isc_buffer_t b;
02200 dns_compress_t cctx;
02201 char store[MXNAME];
02202 char ecsbuf[20];
02203 #ifdef ISC_PLATFORM_USESIT
02204 char sitbuf[256];
02205 #endif
02206 #ifdef WITH_IDN
02207 idn_result_t mr;
02208 char utf8_textname[MXNAME], utf8_origin[MXNAME], idn_textname[MXNAME];
02209 #endif
02210
02211 #ifdef WITH_IDN
02212 result = dns_name_settotextfilter(output_filter);
02213 check_result(result, "dns_name_settotextfilter");
02214 #endif
02215
02216 REQUIRE(lookup != NULL);
02217 INSIST(!free_now);
02218
02219 debug("setup_lookup(%p)", lookup);
02220
02221 result = dns_message_create(mctx, DNS_MESSAGE_INTENTRENDER,
02222 &lookup->sendmsg);
02223 check_result(result, "dns_message_create");
02224
02225 if (lookup->new_search) {
02226 debug("resetting lookup counter.");
02227 lookup_counter = 0;
02228 }
02229
02230 if (ISC_LIST_EMPTY(lookup->my_server_list)) {
02231 debug("cloning server list");
02232 clone_server_list(server_list, &lookup->my_server_list);
02233 }
02234 result = dns_message_gettempname(lookup->sendmsg, &lookup->name);
02235 check_result(result, "dns_message_gettempname");
02236 dns_name_init(lookup->name, NULL);
02237
02238 isc_buffer_init(&lookup->namebuf, lookup->namespace,
02239 sizeof(lookup->namespace));
02240 isc_buffer_init(&lookup->onamebuf, lookup->onamespace,
02241 sizeof(lookup->onamespace));
02242
02243 #ifdef WITH_IDN
02244
02245
02246
02247
02248
02249 mr = idn_encodename(IDN_LOCALCONV | IDN_DELIMMAP, lookup->textname,
02250 utf8_textname, sizeof(utf8_textname));
02251 idn_check_result(mr, "convert textname to UTF-8");
02252 #endif
02253
02254
02255
02256
02257
02258
02259
02260
02261 if (lookup->new_search) {
02262 #ifdef WITH_IDN
02263 if ((count_dots(utf8_textname) >= ndots) || !usesearch) {
02264 lookup->origin = NULL;
02265 lookup->done_as_is = ISC_TRUE;
02266 lookup->need_search = usesearch;
02267 } else if (lookup->origin == NULL && usesearch) {
02268 lookup->origin = ISC_LIST_HEAD(search_list);
02269 lookup->need_search = ISC_FALSE;
02270 }
02271 #else
02272 if ((count_dots(lookup->textname) >= ndots) || !usesearch) {
02273 lookup->origin = NULL;
02274 lookup->done_as_is = ISC_TRUE;
02275 lookup->need_search = usesearch;
02276 } else if (lookup->origin == NULL && usesearch) {
02277 lookup->origin = ISC_LIST_HEAD(search_list);
02278 lookup->need_search = ISC_FALSE;
02279 }
02280 #endif
02281 }
02282
02283 #ifdef WITH_IDN
02284 if (lookup->origin != NULL) {
02285 mr = idn_encodename(IDN_LOCALCONV | IDN_DELIMMAP,
02286 lookup->origin->origin, utf8_origin,
02287 sizeof(utf8_origin));
02288 idn_check_result(mr, "convert origin to UTF-8");
02289 mr = append_textname(utf8_textname, utf8_origin,
02290 sizeof(utf8_textname));
02291 idn_check_result(mr, "append origin to textname");
02292 }
02293 mr = idn_encodename(idnoptions | IDN_LOCALMAP | IDN_NAMEPREP |
02294 IDN_IDNCONV | IDN_LENCHECK, utf8_textname,
02295 idn_textname, sizeof(idn_textname));
02296 idn_check_result(mr, "convert UTF-8 textname to IDN encoding");
02297 #else
02298 if (lookup->origin != NULL) {
02299 debug("trying origin %s", lookup->origin->origin);
02300 result = dns_message_gettempname(lookup->sendmsg,
02301 &lookup->oname);
02302 check_result(result, "dns_message_gettempname");
02303 dns_name_init(lookup->oname, NULL);
02304
02305 len = strlen(lookup->origin->origin);
02306 isc_buffer_init(&b, lookup->origin->origin, len);
02307 isc_buffer_add(&b, len);
02308 result = dns_name_fromtext(lookup->oname, &b, dns_rootname,
02309 0, &lookup->onamebuf);
02310 if (result != ISC_R_SUCCESS) {
02311 dns_message_puttempname(lookup->sendmsg,
02312 &lookup->name);
02313 dns_message_puttempname(lookup->sendmsg,
02314 &lookup->oname);
02315 fatal("'%s' is not in legal name syntax (%s)",
02316 lookup->origin->origin,
02317 isc_result_totext(result));
02318 }
02319 if (lookup->trace && lookup->trace_root) {
02320 dns_name_clone(dns_rootname, lookup->name);
02321 } else {
02322 dns_fixedname_t fixed;
02323 dns_name_t *name;
02324
02325 dns_fixedname_init(&fixed);
02326 name = dns_fixedname_name(&fixed);
02327 len = strlen(lookup->textname);
02328 isc_buffer_init(&b, lookup->textname, len);
02329 isc_buffer_add(&b, len);
02330 result = dns_name_fromtext(name, &b, NULL, 0, NULL);
02331 if (result == ISC_R_SUCCESS &&
02332 !dns_name_isabsolute(name))
02333 result = dns_name_concatenate(name,
02334 lookup->oname,
02335 lookup->name,
02336 &lookup->namebuf);
02337 else if (result == ISC_R_SUCCESS)
02338 result = dns_name_copy(name, lookup->name,
02339 &lookup->namebuf);
02340 if (result != ISC_R_SUCCESS) {
02341 dns_message_puttempname(lookup->sendmsg,
02342 &lookup->name);
02343 dns_message_puttempname(lookup->sendmsg,
02344 &lookup->oname);
02345 if (result == DNS_R_NAMETOOLONG)
02346 return (ISC_FALSE);
02347 fatal("'%s' is not in legal name syntax (%s)",
02348 lookup->textname,
02349 isc_result_totext(result));
02350 }
02351 }
02352 dns_message_puttempname(lookup->sendmsg, &lookup->oname);
02353 } else
02354 #endif
02355 {
02356 debug("using root origin");
02357 if (lookup->trace && lookup->trace_root)
02358 dns_name_clone(dns_rootname, lookup->name);
02359 else {
02360 #ifdef WITH_IDN
02361 len = strlen(idn_textname);
02362 isc_buffer_init(&b, idn_textname, len);
02363 isc_buffer_add(&b, len);
02364 result = dns_name_fromtext(lookup->name, &b,
02365 dns_rootname, 0,
02366 &lookup->namebuf);
02367 #else
02368 len = strlen(lookup->textname);
02369 isc_buffer_init(&b, lookup->textname, len);
02370 isc_buffer_add(&b, len);
02371 result = dns_name_fromtext(lookup->name, &b,
02372 dns_rootname, 0,
02373 &lookup->namebuf);
02374 #endif
02375 }
02376 if (result != ISC_R_SUCCESS) {
02377 dns_message_puttempname(lookup->sendmsg,
02378 &lookup->name);
02379 fatal("'%s' is not a legal name "
02380 "(%s)", lookup->textname,
02381 isc_result_totext(result));
02382 }
02383 }
02384 dns_name_format(lookup->name, store, sizeof(store));
02385 trying(store, lookup);
02386 INSIST(dns_name_isabsolute(lookup->name));
02387
02388 isc_random_get(&id);
02389 lookup->sendmsg->id = (unsigned short)id & 0xFFFF;
02390 lookup->sendmsg->opcode = dns_opcode_query;
02391 lookup->msgcounter = 0;
02392
02393
02394
02395
02396 if (lookup->trace || (lookup->ns_search_only && !lookup->trace_root))
02397 lookup->recurse = ISC_FALSE;
02398
02399 if (lookup->recurse &&
02400 lookup->rdtype != dns_rdatatype_axfr &&
02401 lookup->rdtype != dns_rdatatype_ixfr) {
02402 debug("recursive query");
02403 lookup->sendmsg->flags |= DNS_MESSAGEFLAG_RD;
02404 }
02405
02406
02407 if (lookup->aaonly) {
02408 debug("AA query");
02409 lookup->sendmsg->flags |= DNS_MESSAGEFLAG_AA;
02410 }
02411
02412 if (lookup->adflag) {
02413 debug("AD query");
02414 lookup->sendmsg->flags |= DNS_MESSAGEFLAG_AD;
02415 }
02416
02417 if (lookup->cdflag) {
02418 debug("CD query");
02419 lookup->sendmsg->flags |= DNS_MESSAGEFLAG_CD;
02420 }
02421
02422 if (lookup->zflag) {
02423 debug("Z query");
02424 lookup->sendmsg->flags |= 0x0040U;
02425 }
02426
02427 dns_message_addname(lookup->sendmsg, lookup->name,
02428 DNS_SECTION_QUESTION);
02429
02430 if (lookup->trace && lookup->trace_root) {
02431 lookup->qrdtype = lookup->rdtype;
02432 lookup->rdtype = dns_rdatatype_ns;
02433 }
02434
02435 if ((lookup->rdtype == dns_rdatatype_axfr) ||
02436 (lookup->rdtype == dns_rdatatype_ixfr)) {
02437
02438
02439
02440 if (lookup->rdtype == dns_rdatatype_axfr) {
02441 lookup->doing_xfr = ISC_TRUE;
02442 lookup->tcp_mode = ISC_TRUE;
02443 } else if (lookup->tcp_mode) {
02444 lookup->doing_xfr = ISC_TRUE;
02445 }
02446 }
02447
02448 if (!lookup->header_only)
02449 add_question(lookup->sendmsg, lookup->name, lookup->rdclass,
02450 lookup->rdtype);
02451
02452
02453 if (lookup->rdtype == dns_rdatatype_ixfr)
02454 insert_soa(lookup);
02455
02456
02457 lookup->tsigctx = NULL;
02458 lookup->querysig = NULL;
02459 if (key != NULL) {
02460 debug("initializing keys");
02461 result = dns_message_settsigkey(lookup->sendmsg, key);
02462 check_result(result, "dns_message_settsigkey");
02463 }
02464
02465 lookup->sendspace = isc_mempool_get(commctx);
02466 if (lookup->sendspace == NULL)
02467 fatal("memory allocation failure");
02468
02469 result = dns_compress_init(&cctx, -1, mctx);
02470 check_result(result, "dns_compress_init");
02471
02472 debug("starting to render the message");
02473 isc_buffer_init(&lookup->renderbuf, lookup->sendspace, COMMSIZE);
02474 result = dns_message_renderbegin(lookup->sendmsg, &cctx,
02475 &lookup->renderbuf);
02476 check_result(result, "dns_message_renderbegin");
02477 if (lookup->udpsize > 0 || lookup->dnssec ||
02478 lookup->edns > -1 || lookup->ecs_addr != NULL)
02479 {
02480 dns_ednsopt_t opts[EDNSOPTS + DNS_EDNSOPTIONS];
02481 unsigned int flags;
02482 int i = 0;
02483
02484 if (lookup->udpsize == 0)
02485 lookup->udpsize = 4096;
02486 if (lookup->edns < 0)
02487 lookup->edns = 0;
02488
02489 if (lookup->nsid) {
02490 INSIST(i < DNS_EDNSOPTIONS);
02491 opts[i].code = DNS_OPT_NSID;
02492 opts[i].length = 0;
02493 opts[i].value = NULL;
02494 i++;
02495 }
02496
02497 if (lookup->ecs_addr != NULL) {
02498 isc_uint32_t prefixlen;
02499 struct sockaddr *sa;
02500 struct sockaddr_in *sin;
02501 struct sockaddr_in6 *sin6;
02502 size_t addrl;
02503
02504 sa = &lookup->ecs_addr->type.sa;
02505 prefixlen = lookup->ecs_addr->length;
02506
02507
02508 addrl = (prefixlen + 7) / 8;
02509
02510 INSIST(i < DNS_EDNSOPTIONS);
02511 opts[i].code = DNS_OPT_CLIENT_SUBNET;
02512 opts[i].length = (isc_uint16_t) addrl + 4;
02513 check_result(result, "isc_buffer_allocate");
02514 isc_buffer_init(&b, ecsbuf, sizeof(ecsbuf));
02515 if (sa->sa_family == AF_INET) {
02516 sin = (struct sockaddr_in *) sa;
02517 isc_buffer_putuint16(&b, 1);
02518 isc_buffer_putuint8(&b, prefixlen);
02519 isc_buffer_putuint8(&b, 0);
02520 isc_buffer_putmem(&b,
02521 (isc_uint8_t *) &sin->sin_addr,
02522 (unsigned int) addrl);
02523 } else {
02524 sin6 = (struct sockaddr_in6 *) sa;
02525 isc_buffer_putuint16(&b, 2);
02526 isc_buffer_putuint8(&b, prefixlen);
02527 isc_buffer_putuint8(&b, 0);
02528 isc_buffer_putmem(&b,
02529 (isc_uint8_t *) &sin6->sin6_addr,
02530 (unsigned int) addrl);
02531 }
02532
02533 opts[i].value = (isc_uint8_t *) ecsbuf;
02534 i++;
02535 }
02536
02537 #ifdef ISC_PLATFORM_USESIT
02538 if (lookup->sit) {
02539 INSIST(i < DNS_EDNSOPTIONS);
02540 opts[i].code = DNS_OPT_SIT;
02541 if (lookup->sitvalue != NULL) {
02542 isc_buffer_init(&b, sitbuf, sizeof(sitbuf));
02543 result = isc_hex_decodestring(lookup->sitvalue,
02544 &b);
02545 check_result(result, "isc_hex_decodestring");
02546 opts[i].value = isc_buffer_base(&b);
02547 opts[i].length = isc_buffer_usedlength(&b);
02548 } else {
02549 compute_cookie(cookie, sizeof(cookie));
02550 opts[i].length = 8;
02551 opts[i].value = cookie;
02552 }
02553 i++;
02554 }
02555 #endif
02556
02557 if (lookup->expire) {
02558 INSIST(i < DNS_EDNSOPTIONS);
02559 opts[i].code = DNS_OPT_EXPIRE;
02560 opts[i].length = 0;
02561 opts[i].value = NULL;
02562 i++;
02563 }
02564
02565 if (lookup->ednsoptscnt != 0) {
02566 memmove(&opts[i], lookup->ednsopts,
02567 sizeof(dns_ednsopt_t) * lookup->ednsoptscnt);
02568 i += lookup->ednsoptscnt;
02569 }
02570
02571 flags = lookup->ednsflags;
02572 flags &= ~DNS_MESSAGEEXTFLAG_DO;
02573 if (lookup->dnssec)
02574 flags |= DNS_MESSAGEEXTFLAG_DO;
02575 add_opt(lookup->sendmsg, lookup->udpsize,
02576 lookup->edns, flags, opts, i);
02577 }
02578
02579 result = dns_message_rendersection(lookup->sendmsg,
02580 DNS_SECTION_QUESTION, 0);
02581 check_result(result, "dns_message_rendersection");
02582 result = dns_message_rendersection(lookup->sendmsg,
02583 DNS_SECTION_AUTHORITY, 0);
02584 check_result(result, "dns_message_rendersection");
02585 result = dns_message_renderend(lookup->sendmsg);
02586 check_result(result, "dns_message_renderend");
02587 debug("done rendering");
02588
02589 dns_compress_invalidate(&cctx);
02590
02591
02592
02593
02594 if (isc_buffer_usedlength(&lookup->renderbuf) > 512)
02595 lookup->tcp_mode = ISC_TRUE;
02596
02597 lookup->pending = ISC_FALSE;
02598
02599 for (serv = ISC_LIST_HEAD(lookup->my_server_list);
02600 serv != NULL;
02601 serv = ISC_LIST_NEXT(serv, link)) {
02602 query = isc_mem_allocate(mctx, sizeof(dig_query_t));
02603 if (query == NULL)
02604 fatal("memory allocation failure in %s:%d",
02605 __FILE__, __LINE__);
02606 debug("create query %p linked to lookup %p",
02607 query, lookup);
02608 query->lookup = lookup;
02609 query->waiting_connect = ISC_FALSE;
02610 query->waiting_senddone = ISC_FALSE;
02611 query->pending_free = ISC_FALSE;
02612 query->recv_made = ISC_FALSE;
02613 query->first_pass = ISC_TRUE;
02614 query->first_soa_rcvd = ISC_FALSE;
02615 query->second_rr_rcvd = ISC_FALSE;
02616 query->first_repeat_rcvd = ISC_FALSE;
02617 query->warn_id = ISC_TRUE;
02618 query->first_rr_serial = 0;
02619 query->second_rr_serial = 0;
02620 query->servname = serv->servername;
02621 query->userarg = serv->userarg;
02622 query->rr_count = 0;
02623 query->msg_count = 0;
02624 query->byte_count = 0;
02625 query->ixfr_axfr = ISC_FALSE;
02626 ISC_LIST_INIT(query->recvlist);
02627 ISC_LIST_INIT(query->lengthlist);
02628 query->sock = NULL;
02629 query->recvspace = isc_mempool_get(commctx);
02630 if (query->recvspace == NULL)
02631 fatal("memory allocation failure");
02632
02633 isc_buffer_init(&query->recvbuf, query->recvspace, COMMSIZE);
02634 isc_buffer_init(&query->lengthbuf, query->lengthspace, 2);
02635 isc_buffer_init(&query->slbuf, query->slspace, 2);
02636 query->sendbuf = lookup->renderbuf;
02637
02638 ISC_LINK_INIT(query, clink);
02639 ISC_LINK_INIT(query, link);
02640 ISC_LIST_ENQUEUE(lookup->q, query, link);
02641 }
02642
02643
02644 if (!ISC_LIST_EMPTY(lookup->q) && qr) {
02645 extrabytes = 0;
02646 printmessage(ISC_LIST_HEAD(lookup->q), lookup->sendmsg,
02647 ISC_TRUE);
02648 if (lookup->stats)
02649 printf(";; QUERY SIZE: %u\n\n",
02650 isc_buffer_usedlength(&lookup->renderbuf));
02651 }
02652 return (ISC_TRUE);
02653 }
02654
02655
02656
02657
02658
02659 static void
02660 send_done(isc_task_t *_task, isc_event_t *event) {
02661 isc_socketevent_t *sevent = (isc_socketevent_t *)event;
02662 isc_buffer_t *b = NULL;
02663 dig_query_t *query, *next;
02664 dig_lookup_t *l;
02665
02666 REQUIRE(event->ev_type == ISC_SOCKEVENT_SENDDONE);
02667
02668 UNUSED(_task);
02669
02670 LOCK_LOOKUP;
02671
02672 debug("send_done()");
02673 sendcount--;
02674 debug("sendcount=%d", sendcount);
02675 INSIST(sendcount >= 0);
02676
02677 for (b = ISC_LIST_HEAD(sevent->bufferlist);
02678 b != NULL;
02679 b = ISC_LIST_HEAD(sevent->bufferlist)) {
02680 ISC_LIST_DEQUEUE(sevent->bufferlist, b, link);
02681 isc_mem_free(mctx, b);
02682 }
02683
02684 query = event->ev_arg;
02685 query->waiting_senddone = ISC_FALSE;
02686 l = query->lookup;
02687
02688 if (l->ns_search_only && !l->trace_root && !l->tcp_mode) {
02689 debug("sending next, since searching");
02690 next = ISC_LIST_NEXT(query, link);
02691 if (next != NULL)
02692 send_udp(next);
02693 }
02694
02695 isc_event_free(&event);
02696
02697 if (query->pending_free)
02698 isc_mem_free(mctx, query);
02699
02700 check_if_done();
02701 UNLOCK_LOOKUP;
02702 }
02703
02704
02705
02706
02707
02708
02709 static void
02710 cancel_lookup(dig_lookup_t *lookup) {
02711 dig_query_t *query, *next;
02712
02713 debug("cancel_lookup()");
02714 query = ISC_LIST_HEAD(lookup->q);
02715 while (query != NULL) {
02716 next = ISC_LIST_NEXT(query, link);
02717 if (query->sock != NULL) {
02718 isc_socket_cancel(query->sock, global_task,
02719 ISC_SOCKCANCEL_ALL);
02720 check_if_done();
02721 } else {
02722 clear_query(query);
02723 }
02724 query = next;
02725 }
02726 if (lookup->timer != NULL)
02727 isc_timer_detach(&lookup->timer);
02728 lookup->pending = ISC_FALSE;
02729 lookup->retries = 0;
02730 }
02731
02732 static void
02733 bringup_timer(dig_query_t *query, unsigned int default_timeout) {
02734 dig_lookup_t *l;
02735 unsigned int local_timeout;
02736 isc_result_t result;
02737
02738 debug("bringup_timer()");
02739
02740
02741
02742
02743
02744 l = query->lookup;
02745 if (ISC_LIST_NEXT(query, link) != NULL)
02746 local_timeout = SERVER_TIMEOUT;
02747 else {
02748 if (timeout == 0)
02749 local_timeout = default_timeout;
02750 else
02751 local_timeout = timeout;
02752 }
02753 debug("have local timeout of %d", local_timeout);
02754 isc_interval_set(&l->interval, local_timeout, 0);
02755 if (l->timer != NULL)
02756 isc_timer_detach(&l->timer);
02757 result = isc_timer_create(timermgr, isc_timertype_once, NULL,
02758 &l->interval, global_task, connect_timeout,
02759 l, &l->timer);
02760 check_result(result, "isc_timer_create");
02761 }
02762
02763 static void
02764 force_timeout(dig_lookup_t *l, dig_query_t *query) {
02765 isc_event_t *event;
02766
02767 debug("force_timeout ()");
02768 event = isc_event_allocate(mctx, query, ISC_TIMEREVENT_IDLE,
02769 connect_timeout, l,
02770 sizeof(isc_event_t));
02771 if (event == NULL) {
02772 fatal("isc_event_allocate: %s",
02773 isc_result_totext(ISC_R_NOMEMORY));
02774 }
02775 isc_task_send(global_task, &event);
02776
02777
02778
02779
02780
02781
02782
02783 if (l->timer != NULL)
02784 isc_timer_detach(&l->timer);
02785 }
02786
02787
02788 static void
02789 connect_done(isc_task_t *task, isc_event_t *event);
02790
02791
02792
02793
02794
02795
02796 static void
02797 send_tcp_connect(dig_query_t *query) {
02798 isc_result_t result;
02799 dig_query_t *next;
02800 dig_lookup_t *l;
02801
02802 debug("send_tcp_connect(%p)", query);
02803
02804 l = query->lookup;
02805 query->waiting_connect = ISC_TRUE;
02806 query->lookup->current_query = query;
02807 result = get_address(query->servname, port, &query->sockaddr);
02808 if (result != ISC_R_SUCCESS) {
02809
02810
02811
02812
02813
02814 force_timeout(l, query);
02815 return;
02816 }
02817
02818 if (specified_source &&
02819 (isc_sockaddr_pf(&query->sockaddr) !=
02820 isc_sockaddr_pf(&bind_address))) {
02821 printf(";; Skipping server %s, incompatible "
02822 "address family\n", query->servname);
02823 query->waiting_connect = ISC_FALSE;
02824 next = ISC_LIST_NEXT(query, link);
02825 l = query->lookup;
02826 clear_query(query);
02827 if (next == NULL) {
02828 printf(";; No acceptable nameservers\n");
02829 check_next_lookup(l);
02830 return;
02831 }
02832 send_tcp_connect(next);
02833 return;
02834 }
02835
02836 INSIST(query->sock == NULL);
02837
02838 if (keep != NULL && isc_sockaddr_equal(&keepaddr, &query->sockaddr)) {
02839 sockcount++;
02840 isc_socket_attach(keep, &query->sock);
02841 query->waiting_connect = ISC_FALSE;
02842 launch_next_query(query, ISC_TRUE);
02843 goto search;
02844 }
02845
02846 result = isc_socket_create(socketmgr,
02847 isc_sockaddr_pf(&query->sockaddr),
02848 isc_sockettype_tcp, &query->sock);
02849 check_result(result, "isc_socket_create");
02850 sockcount++;
02851 debug("sockcount=%d", sockcount);
02852 if (query->lookup->dscp != -1)
02853 isc_socket_dscp(query->sock, query->lookup->dscp);
02854 if (specified_source)
02855 result = isc_socket_bind(query->sock, &bind_address,
02856 ISC_SOCKET_REUSEADDRESS);
02857 else {
02858 if ((isc_sockaddr_pf(&query->sockaddr) == AF_INET) &&
02859 have_ipv4)
02860 isc_sockaddr_any(&bind_any);
02861 else
02862 isc_sockaddr_any6(&bind_any);
02863 result = isc_socket_bind(query->sock, &bind_any, 0);
02864 }
02865 check_result(result, "isc_socket_bind");
02866 bringup_timer(query, TCP_TIMEOUT);
02867 result = isc_socket_connect(query->sock, &query->sockaddr,
02868 global_task, connect_done, query);
02869 check_result(result, "isc_socket_connect");
02870 search:
02871
02872
02873
02874
02875 if (l->ns_search_only && !l->trace_root) {
02876 debug("sending next, since searching");
02877 next = ISC_LIST_NEXT(query, link);
02878 if (ISC_LINK_LINKED(query, link))
02879 ISC_LIST_DEQUEUE(l->q, query, link);
02880 ISC_LIST_ENQUEUE(l->connecting, query, clink);
02881 if (next != NULL)
02882 send_tcp_connect(next);
02883 }
02884 }
02885
02886 static isc_buffer_t *
02887 clone_buffer(isc_buffer_t *source) {
02888 isc_buffer_t *buffer;
02889 buffer = isc_mem_allocate(mctx, sizeof(*buffer));
02890 if (buffer == NULL)
02891 fatal("memory allocation failure in %s:%d",
02892 __FILE__, __LINE__);
02893 *buffer = *source;
02894 return (buffer);
02895 }
02896
02897
02898
02899
02900
02901
02902 static void
02903 send_udp(dig_query_t *query) {
02904 dig_lookup_t *l = NULL;
02905 isc_result_t result;
02906 isc_buffer_t *sendbuf;
02907
02908 debug("send_udp(%p)", query);
02909
02910 l = query->lookup;
02911 bringup_timer(query, UDP_TIMEOUT);
02912 l->current_query = query;
02913 debug("working on lookup %p, query %p", query->lookup, query);
02914 if (!query->recv_made) {
02915
02916 query->waiting_connect = ISC_FALSE;
02917 result = get_address(query->servname, port, &query->sockaddr);
02918 if (result != ISC_R_SUCCESS) {
02919
02920 force_timeout(l, query);
02921 return;
02922 }
02923
02924 result = isc_socket_create(socketmgr,
02925 isc_sockaddr_pf(&query->sockaddr),
02926 isc_sockettype_udp, &query->sock);
02927 check_result(result, "isc_socket_create");
02928 sockcount++;
02929 debug("sockcount=%d", sockcount);
02930 if (query->lookup->dscp != -1)
02931 isc_socket_dscp(query->sock, query->lookup->dscp);
02932 if (specified_source) {
02933 result = isc_socket_bind(query->sock, &bind_address,
02934 ISC_SOCKET_REUSEADDRESS);
02935 } else {
02936 isc_sockaddr_anyofpf(&bind_any,
02937 isc_sockaddr_pf(&query->sockaddr));
02938 result = isc_socket_bind(query->sock, &bind_any, 0);
02939 }
02940 check_result(result, "isc_socket_bind");
02941
02942 query->recv_made = ISC_TRUE;
02943 ISC_LINK_INIT(&query->recvbuf, link);
02944 ISC_LIST_ENQUEUE(query->recvlist, &query->recvbuf,
02945 link);
02946 debug("recving with lookup=%p, query=%p, sock=%p",
02947 query->lookup, query, query->sock);
02948 result = isc_socket_recvv(query->sock, &query->recvlist, 1,
02949 global_task, recv_done, query);
02950 check_result(result, "isc_socket_recvv");
02951 recvcount++;
02952 debug("recvcount=%d", recvcount);
02953 }
02954 ISC_LIST_INIT(query->sendlist);
02955 sendbuf = clone_buffer(&query->sendbuf);
02956 ISC_LIST_ENQUEUE(query->sendlist, sendbuf, link);
02957 debug("sending a request");
02958 TIME_NOW(&query->time_sent);
02959 INSIST(query->sock != NULL);
02960 query->waiting_senddone = ISC_TRUE;
02961 result = isc_socket_sendtov2(query->sock, &query->sendlist,
02962 global_task, send_done, query,
02963 &query->sockaddr, NULL,
02964 ISC_SOCKFLAG_NORETRY);
02965 check_result(result, "isc_socket_sendtov");
02966 sendcount++;
02967 }
02968
02969
02970
02971
02972
02973
02974 static void
02975 connect_timeout(isc_task_t *task, isc_event_t *event) {
02976 dig_lookup_t *l = NULL;
02977 dig_query_t *query = NULL, *next, *cq;
02978
02979 UNUSED(task);
02980 REQUIRE(event->ev_type == ISC_TIMEREVENT_IDLE);
02981
02982 debug("connect_timeout()");
02983
02984 LOCK_LOOKUP;
02985 l = event->ev_arg;
02986 query = l->current_query;
02987 isc_event_free(&event);
02988
02989 INSIST(!free_now);
02990
02991 if ((query != NULL) && (query->lookup->current_query != NULL) &&
02992 (ISC_LIST_NEXT(query->lookup->current_query, link) != NULL)) {
02993 debug("trying next server...");
02994 cq = query->lookup->current_query;
02995 if (!l->tcp_mode)
02996 send_udp(ISC_LIST_NEXT(cq, link));
02997 else {
02998 if (query->sock != NULL)
02999 isc_socket_cancel(query->sock, NULL,
03000 ISC_SOCKCANCEL_ALL);
03001 next = ISC_LIST_NEXT(cq, link);
03002 if (next != NULL)
03003 send_tcp_connect(next);
03004 }
03005 UNLOCK_LOOKUP;
03006 return;
03007 }
03008
03009 if (l->retries > 1) {
03010 if (!l->tcp_mode) {
03011 l->retries--;
03012 debug("resending UDP request to first server");
03013 send_udp(ISC_LIST_HEAD(l->q));
03014 } else {
03015 debug("making new TCP request, %d tries left",
03016 l->retries);
03017 l->retries--;
03018 requeue_lookup(l, ISC_TRUE);
03019 cancel_lookup(l);
03020 check_next_lookup(l);
03021 }
03022 } else {
03023 fputs(l->cmdline, stdout);
03024 printf(";; connection timed out; no servers could be "
03025 "reached\n");
03026 cancel_lookup(l);
03027 check_next_lookup(l);
03028 if (exitcode < 9)
03029 exitcode = 9;
03030 }
03031 UNLOCK_LOOKUP;
03032 }
03033
03034
03035
03036
03037
03038 static void
03039 tcp_length_done(isc_task_t *task, isc_event_t *event) {
03040 isc_socketevent_t *sevent;
03041 isc_buffer_t *b = NULL;
03042 isc_result_t result;
03043 dig_query_t *query = NULL;
03044 dig_lookup_t *l;
03045 isc_uint16_t length;
03046
03047 REQUIRE(event->ev_type == ISC_SOCKEVENT_RECVDONE);
03048 INSIST(!free_now);
03049
03050 UNUSED(task);
03051
03052 debug("tcp_length_done()");
03053
03054 LOCK_LOOKUP;
03055 sevent = (isc_socketevent_t *)event;
03056 query = event->ev_arg;
03057
03058 recvcount--;
03059 INSIST(recvcount >= 0);
03060
03061 b = ISC_LIST_HEAD(sevent->bufferlist);
03062 INSIST(b == &query->lengthbuf);
03063 ISC_LIST_DEQUEUE(sevent->bufferlist, b, link);
03064
03065 if (sevent->result == ISC_R_CANCELED) {
03066 isc_event_free(&event);
03067 l = query->lookup;
03068 clear_query(query);
03069 check_next_lookup(l);
03070 UNLOCK_LOOKUP;
03071 return;
03072 }
03073 if (sevent->result != ISC_R_SUCCESS) {
03074 char sockstr[ISC_SOCKADDR_FORMATSIZE];
03075 isc_sockaddr_format(&query->sockaddr, sockstr,
03076 sizeof(sockstr));
03077 printf(";; communications error to %s: %s\n",
03078 sockstr, isc_result_totext(sevent->result));
03079 l = query->lookup;
03080 isc_socket_detach(&query->sock);
03081 sockcount--;
03082 debug("sockcount=%d", sockcount);
03083 INSIST(sockcount >= 0);
03084 isc_event_free(&event);
03085 clear_query(query);
03086 check_next_lookup(l);
03087 UNLOCK_LOOKUP;
03088 return;
03089 }
03090 length = isc_buffer_getuint16(b);
03091 if (length == 0) {
03092 isc_event_free(&event);
03093 launch_next_query(query, ISC_FALSE);
03094 UNLOCK_LOOKUP;
03095 return;
03096 }
03097
03098
03099
03100
03101
03102 isc_buffer_invalidate(&query->recvbuf);
03103 isc_buffer_init(&query->recvbuf, query->recvspace, length);
03104 ENSURE(ISC_LIST_EMPTY(query->recvlist));
03105 ISC_LINK_INIT(&query->recvbuf, link);
03106 ISC_LIST_ENQUEUE(query->recvlist, &query->recvbuf, link);
03107 debug("recving with lookup=%p, query=%p", query->lookup, query);
03108 result = isc_socket_recvv(query->sock, &query->recvlist, length, task,
03109 recv_done, query);
03110 check_result(result, "isc_socket_recvv");
03111 recvcount++;
03112 debug("resubmitted recv request with length %d, recvcount=%d",
03113 length, recvcount);
03114 isc_event_free(&event);
03115 UNLOCK_LOOKUP;
03116 }
03117
03118
03119
03120
03121
03122 static void
03123 launch_next_query(dig_query_t *query, isc_boolean_t include_question) {
03124 isc_result_t result;
03125 dig_lookup_t *l;
03126 isc_buffer_t *buffer;
03127
03128 INSIST(!free_now);
03129
03130 debug("launch_next_query()");
03131
03132 if (!query->lookup->pending) {
03133 debug("ignoring launch_next_query because !pending");
03134 isc_socket_detach(&query->sock);
03135 sockcount--;
03136 debug("sockcount=%d", sockcount);
03137 INSIST(sockcount >= 0);
03138 query->waiting_connect = ISC_FALSE;
03139 l = query->lookup;
03140 clear_query(query);
03141 check_next_lookup(l);
03142 return;
03143 }
03144
03145 isc_buffer_clear(&query->slbuf);
03146 isc_buffer_clear(&query->lengthbuf);
03147 isc_buffer_putuint16(&query->slbuf, (isc_uint16_t) query->sendbuf.used);
03148 ISC_LIST_INIT(query->sendlist);
03149 ISC_LINK_INIT(&query->slbuf, link);
03150 if (!query->first_soa_rcvd) {
03151 buffer = clone_buffer(&query->slbuf);
03152 ISC_LIST_ENQUEUE(query->sendlist, buffer, link);
03153 if (include_question) {
03154 buffer = clone_buffer(&query->sendbuf);
03155 ISC_LIST_ENQUEUE(query->sendlist, buffer, link);
03156 }
03157 }
03158
03159 ISC_LINK_INIT(&query->lengthbuf, link);
03160 ISC_LIST_ENQUEUE(query->lengthlist, &query->lengthbuf, link);
03161
03162 result = isc_socket_recvv(query->sock, &query->lengthlist, 0,
03163 global_task, tcp_length_done, query);
03164 check_result(result, "isc_socket_recvv");
03165 recvcount++;
03166 debug("recvcount=%d", recvcount);
03167 if (!query->first_soa_rcvd) {
03168 debug("sending a request in launch_next_query");
03169 TIME_NOW(&query->time_sent);
03170 query->waiting_senddone = ISC_TRUE;
03171 result = isc_socket_sendv(query->sock, &query->sendlist,
03172 global_task, send_done, query);
03173 check_result(result, "isc_socket_sendv");
03174 sendcount++;
03175 debug("sendcount=%d", sendcount);
03176 }
03177 query->waiting_connect = ISC_FALSE;
03178 #if 0
03179 check_next_lookup(query->lookup);
03180 #endif
03181 return;
03182 }
03183
03184
03185
03186
03187
03188
03189 static void
03190 connect_done(isc_task_t *task, isc_event_t *event) {
03191 isc_socketevent_t *sevent = NULL;
03192 dig_query_t *query = NULL, *next;
03193 dig_lookup_t *l;
03194
03195 UNUSED(task);
03196
03197 REQUIRE(event->ev_type == ISC_SOCKEVENT_CONNECT);
03198 INSIST(!free_now);
03199
03200 debug("connect_done()");
03201
03202 LOCK_LOOKUP;
03203 sevent = (isc_socketevent_t *)event;
03204 query = sevent->ev_arg;
03205
03206 INSIST(query->waiting_connect);
03207
03208 query->waiting_connect = ISC_FALSE;
03209
03210 if (sevent->result == ISC_R_CANCELED) {
03211 debug("in cancel handler");
03212 isc_socket_detach(&query->sock);
03213 INSIST(sockcount > 0);
03214 sockcount--;
03215 debug("sockcount=%d", sockcount);
03216 query->waiting_connect = ISC_FALSE;
03217 isc_event_free(&event);
03218 l = query->lookup;
03219 clear_query(query);
03220 check_next_lookup(l);
03221 UNLOCK_LOOKUP;
03222 return;
03223 }
03224 if (sevent->result != ISC_R_SUCCESS) {
03225 char sockstr[ISC_SOCKADDR_FORMATSIZE];
03226
03227 debug("unsuccessful connection: %s",
03228 isc_result_totext(sevent->result));
03229 isc_sockaddr_format(&query->sockaddr, sockstr, sizeof(sockstr));
03230 if (sevent->result != ISC_R_CANCELED)
03231 printf(";; Connection to %s(%s) for %s failed: "
03232 "%s.\n", sockstr,
03233 query->servname, query->lookup->textname,
03234 isc_result_totext(sevent->result));
03235 isc_socket_detach(&query->sock);
03236 sockcount--;
03237 INSIST(sockcount >= 0);
03238
03239 if (exitcode < 9)
03240 exitcode = 9;
03241 debug("sockcount=%d", sockcount);
03242 query->waiting_connect = ISC_FALSE;
03243 isc_event_free(&event);
03244 l = query->lookup;
03245 if ((l->current_query != NULL) &&
03246 (ISC_LINK_LINKED(l->current_query, link)))
03247 next = ISC_LIST_NEXT(l->current_query, link);
03248 else
03249 next = NULL;
03250 clear_query(query);
03251 if (next != NULL) {
03252 bringup_timer(next, TCP_TIMEOUT);
03253 send_tcp_connect(next);
03254 } else
03255 check_next_lookup(l);
03256 UNLOCK_LOOKUP;
03257 return;
03258 }
03259 if (keep_open) {
03260 if (keep != NULL)
03261 isc_socket_detach(&keep);
03262 isc_socket_attach(query->sock, &keep);
03263 keepaddr = query->sockaddr;
03264 }
03265 launch_next_query(query, ISC_TRUE);
03266 isc_event_free(&event);
03267 UNLOCK_LOOKUP;
03268 }
03269
03270
03271
03272
03273
03274
03275
03276 static isc_boolean_t
03277 check_for_more_data(dig_query_t *query, dns_message_t *msg,
03278 isc_socketevent_t *sevent)
03279 {
03280 dns_rdataset_t *rdataset = NULL;
03281 dns_rdata_t rdata = DNS_RDATA_INIT;
03282 dns_rdata_soa_t soa;
03283 isc_uint32_t ixfr_serial = query->lookup->ixfr_serial, serial;
03284 isc_result_t result;
03285 isc_boolean_t ixfr = query->lookup->rdtype == dns_rdatatype_ixfr;
03286 isc_boolean_t axfr = query->lookup->rdtype == dns_rdatatype_axfr;
03287
03288 if (ixfr)
03289 axfr = query->ixfr_axfr;
03290
03291 debug("check_for_more_data()");
03292
03293
03294
03295
03296
03297
03298
03299
03300
03301
03302 query->msg_count++;
03303 query->byte_count += sevent->n;
03304 result = dns_message_firstname(msg, DNS_SECTION_ANSWER);
03305 if (result != ISC_R_SUCCESS) {
03306 puts("; Transfer failed.");
03307 return (ISC_TRUE);
03308 }
03309 do {
03310 dns_name_t *name;
03311 name = NULL;
03312 dns_message_currentname(msg, DNS_SECTION_ANSWER,
03313 &name);
03314 for (rdataset = ISC_LIST_HEAD(name->list);
03315 rdataset != NULL;
03316 rdataset = ISC_LIST_NEXT(rdataset, link)) {
03317 result = dns_rdataset_first(rdataset);
03318 if (result != ISC_R_SUCCESS)
03319 continue;
03320 do {
03321 query->rr_count++;
03322 dns_rdata_reset(&rdata);
03323 dns_rdataset_current(rdataset, &rdata);
03324
03325
03326
03327
03328 if ((!query->first_soa_rcvd) &&
03329 (rdata.type != dns_rdatatype_soa)) {
03330 puts("; Transfer failed. "
03331 "Didn't start with SOA answer.");
03332 return (ISC_TRUE);
03333 }
03334 if ((!query->second_rr_rcvd) &&
03335 (rdata.type != dns_rdatatype_soa)) {
03336 query->second_rr_rcvd = ISC_TRUE;
03337 query->second_rr_serial = 0;
03338 debug("got the second rr as nonsoa");
03339 axfr = query->ixfr_axfr = ISC_TRUE;
03340 goto next_rdata;
03341 }
03342
03343
03344
03345
03346
03347 if (rdata.type != dns_rdatatype_soa)
03348 goto next_rdata;
03349
03350
03351 debug("got an SOA");
03352 result = dns_rdata_tostruct(&rdata, &soa, NULL);
03353 check_result(result, "dns_rdata_tostruct");
03354 serial = soa.serial;
03355 dns_rdata_freestruct(&soa);
03356 if (!query->first_soa_rcvd) {
03357 query->first_soa_rcvd = ISC_TRUE;
03358 query->first_rr_serial = serial;
03359 debug("this is the first serial %u",
03360 serial);
03361 if (ixfr && isc_serial_ge(ixfr_serial,
03362 serial)) {
03363 debug("got up to date "
03364 "response");
03365 goto doexit;
03366 }
03367 goto next_rdata;
03368 }
03369 if (axfr) {
03370 debug("doing axfr, got second SOA");
03371 goto doexit;
03372 }
03373 if (!query->second_rr_rcvd) {
03374 if (query->first_rr_serial == serial) {
03375 debug("doing ixfr, got "
03376 "empty zone");
03377 goto doexit;
03378 }
03379 debug("this is the second serial %u",
03380 serial);
03381 query->second_rr_rcvd = ISC_TRUE;
03382 query->second_rr_serial = serial;
03383 goto next_rdata;
03384 }
03385
03386
03387
03388
03389
03390 if (query->first_rr_serial == serial) {
03391 debug("got a match for ixfr");
03392 if (!query->first_repeat_rcvd) {
03393 query->first_repeat_rcvd =
03394 ISC_TRUE;
03395 goto next_rdata;
03396 }
03397 debug("done with ixfr");
03398 goto doexit;
03399 }
03400 debug("meaningless soa %u", serial);
03401 next_rdata:
03402 result = dns_rdataset_next(rdataset);
03403 } while (result == ISC_R_SUCCESS);
03404 }
03405 result = dns_message_nextname(msg, DNS_SECTION_ANSWER);
03406 } while (result == ISC_R_SUCCESS);
03407 launch_next_query(query, ISC_FALSE);
03408 return (ISC_FALSE);
03409 doexit:
03410 received(sevent->n, &sevent->address, query);
03411 return (ISC_TRUE);
03412 }
03413
03414 #ifdef ISC_PLATFORM_USESIT
03415 static void
03416 process_sit(dig_lookup_t *l, dns_message_t *msg,
03417 isc_buffer_t *optbuf, size_t optlen)
03418 {
03419 char bb[256];
03420 isc_buffer_t hexbuf;
03421 size_t len;
03422 const unsigned char *sit;
03423 isc_boolean_t copysit;
03424 isc_result_t result;
03425
03426 if (l->sitvalue != NULL) {
03427 isc_buffer_init(&hexbuf, bb, sizeof(bb));
03428 result = isc_hex_decodestring(l->sitvalue, &hexbuf);
03429 check_result(result, "isc_hex_decodestring");
03430 sit = isc_buffer_base(&hexbuf);
03431 len = isc_buffer_usedlength(&hexbuf);
03432 copysit = ISC_FALSE;
03433 } else {
03434 sit = cookie;
03435 len = sizeof(cookie);
03436 copysit = ISC_TRUE;
03437 }
03438
03439 INSIST(msg->sitok == 0 && msg->sitbad == 0);
03440 if (optlen >= len && optlen >= 8U) {
03441 if (memcmp(isc_buffer_current(optbuf), sit, 8) == 0) {
03442 msg->sitok = 1;
03443 } else {
03444 printf(";; Warning: SIT client cookie mismatch\n");
03445 msg->sitbad = 1;
03446 copysit = ISC_FALSE;
03447 }
03448 } else {
03449 printf(";; Warning: SIT bad token (too short)\n");
03450 msg->sitbad = 1;
03451 copysit = ISC_FALSE;
03452 }
03453 if (copysit) {
03454 isc_region_t r;
03455
03456 r.base = isc_buffer_current(optbuf);
03457 r.length = (unsigned int)optlen;
03458 isc_buffer_init(&hexbuf, sitvalue, sizeof(sitvalue));
03459 result = isc_hex_totext(&r, 2, "", &hexbuf);
03460 check_result(result, "isc_hex_totext");
03461 if (isc_buffer_availablelength(&hexbuf) > 0) {
03462 isc_buffer_putuint8(&hexbuf, 0);
03463 l->sitvalue = sitvalue;
03464 }
03465 }
03466 isc_buffer_forward(optbuf, (unsigned int)optlen);
03467 }
03468
03469 static void
03470 process_opt(dig_lookup_t *l, dns_message_t *msg) {
03471 dns_rdata_t rdata;
03472 isc_result_t result;
03473 isc_buffer_t optbuf;
03474 isc_uint16_t optcode, optlen;
03475 dns_rdataset_t *opt = msg->opt;
03476
03477 result = dns_rdataset_first(opt);
03478 if (result == ISC_R_SUCCESS) {
03479 dns_rdata_init(&rdata);
03480 dns_rdataset_current(opt, &rdata);
03481 isc_buffer_init(&optbuf, rdata.data, rdata.length);
03482 isc_buffer_add(&optbuf, rdata.length);
03483 while (isc_buffer_remaininglength(&optbuf) >= 4) {
03484 optcode = isc_buffer_getuint16(&optbuf);
03485 optlen = isc_buffer_getuint16(&optbuf);
03486 switch (optcode) {
03487 case DNS_OPT_SIT:
03488 process_sit(l, msg, &optbuf, optlen);
03489 break;
03490 default:
03491 isc_buffer_forward(&optbuf, optlen);
03492 break;
03493 }
03494 }
03495 }
03496 }
03497 #endif
03498
03499 static int
03500 ednsvers(dns_rdataset_t *opt) {
03501 return ((opt->ttl >> 16) & 0xff);
03502 }
03503
03504
03505
03506
03507
03508 static void
03509 recv_done(isc_task_t *task, isc_event_t *event) {
03510 isc_socketevent_t *sevent = NULL;
03511 dig_query_t *query = NULL;
03512 isc_buffer_t *b = NULL;
03513 dns_message_t *msg = NULL;
03514 #ifdef DIG_SIGCHASE
03515 dig_message_t *chase_msg = NULL;
03516 dig_message_t *chase_msg2 = NULL;
03517 #endif
03518 isc_result_t result;
03519 dig_lookup_t *n, *l;
03520 isc_boolean_t docancel = ISC_FALSE;
03521 isc_boolean_t match = ISC_TRUE;
03522 unsigned int parseflags;
03523 dns_messageid_t id;
03524 unsigned int msgflags;
03525 #ifdef DIG_SIGCHASE
03526 isc_result_t do_sigchase = ISC_FALSE;
03527
03528 dns_message_t *msg_temp = NULL;
03529 isc_region_t r;
03530 isc_buffer_t *buf = NULL;
03531 #endif
03532 int newedns;
03533
03534 UNUSED(task);
03535 INSIST(!free_now);
03536
03537 debug("recv_done()");
03538
03539 LOCK_LOOKUP;
03540 recvcount--;
03541 debug("recvcount=%d", recvcount);
03542 INSIST(recvcount >= 0);
03543
03544 query = event->ev_arg;
03545 TIME_NOW(&query->time_recv);
03546 debug("lookup=%p, query=%p", query->lookup, query);
03547
03548 l = query->lookup;
03549
03550 REQUIRE(event->ev_type == ISC_SOCKEVENT_RECVDONE);
03551 sevent = (isc_socketevent_t *)event;
03552
03553 b = ISC_LIST_HEAD(sevent->bufferlist);
03554 INSIST(b == &query->recvbuf);
03555 ISC_LIST_DEQUEUE(sevent->bufferlist, &query->recvbuf, link);
03556
03557 if ((l->tcp_mode) && (l->timer != NULL))
03558 isc_timer_touch(l->timer);
03559 if ((!l->pending && !l->ns_search_only) || cancel_now) {
03560 debug("no longer pending. Got %s",
03561 isc_result_totext(sevent->result));
03562 query->waiting_connect = ISC_FALSE;
03563
03564 isc_event_free(&event);
03565 clear_query(query);
03566 check_next_lookup(l);
03567 UNLOCK_LOOKUP;
03568 return;
03569 }
03570
03571 if (sevent->result != ISC_R_SUCCESS) {
03572 if (sevent->result == ISC_R_CANCELED) {
03573 debug("in recv cancel handler");
03574 query->waiting_connect = ISC_FALSE;
03575 } else {
03576 printf(";; communications error: %s\n",
03577 isc_result_totext(sevent->result));
03578 isc_socket_detach(&query->sock);
03579 sockcount--;
03580 debug("sockcount=%d", sockcount);
03581 INSIST(sockcount >= 0);
03582 }
03583 isc_event_free(&event);
03584 clear_query(query);
03585 check_next_lookup(l);
03586 UNLOCK_LOOKUP;
03587 return;
03588 }
03589
03590 if (!l->tcp_mode &&
03591 !isc_sockaddr_compare(&sevent->address, &query->sockaddr,
03592 ISC_SOCKADDR_CMPADDR|
03593 ISC_SOCKADDR_CMPPORT|
03594 ISC_SOCKADDR_CMPSCOPE|
03595 ISC_SOCKADDR_CMPSCOPEZERO)) {
03596 char buf1[ISC_SOCKADDR_FORMATSIZE];
03597 char buf2[ISC_SOCKADDR_FORMATSIZE];
03598 isc_sockaddr_t any;
03599
03600 if (isc_sockaddr_pf(&query->sockaddr) == AF_INET)
03601 isc_sockaddr_any(&any);
03602 else
03603 isc_sockaddr_any6(&any);
03604
03605
03606
03607
03608
03609
03610 if ((!isc_sockaddr_eqaddr(&query->sockaddr, &any) &&
03611 !isc_sockaddr_ismulticast(&query->sockaddr)) ||
03612 isc_sockaddr_getport(&query->sockaddr) !=
03613 isc_sockaddr_getport(&sevent->address)) {
03614 isc_sockaddr_format(&sevent->address, buf1,
03615 sizeof(buf1));
03616 isc_sockaddr_format(&query->sockaddr, buf2,
03617 sizeof(buf2));
03618 printf(";; reply from unexpected source: %s,"
03619 " expected %s\n", buf1, buf2);
03620 match = ISC_FALSE;
03621 }
03622 }
03623
03624 result = dns_message_peekheader(b, &id, &msgflags);
03625 if (result != ISC_R_SUCCESS || l->sendmsg->id != id) {
03626 match = ISC_FALSE;
03627 if (l->tcp_mode) {
03628 isc_boolean_t fail = ISC_TRUE;
03629 if (result == ISC_R_SUCCESS) {
03630 if (!query->first_soa_rcvd ||
03631 query->warn_id)
03632 printf(";; %s: ID mismatch: "
03633 "expected ID %u, got %u\n",
03634 query->first_soa_rcvd ?
03635 "WARNING" : "ERROR",
03636 l->sendmsg->id, id);
03637 if (query->first_soa_rcvd)
03638 fail = ISC_FALSE;
03639 query->warn_id = ISC_FALSE;
03640 } else
03641 printf(";; ERROR: short "
03642 "(< header size) message\n");
03643 if (fail) {
03644 isc_event_free(&event);
03645 clear_query(query);
03646 check_next_lookup(l);
03647 UNLOCK_LOOKUP;
03648 return;
03649 }
03650 match = ISC_TRUE;
03651 } else if (result == ISC_R_SUCCESS)
03652 printf(";; Warning: ID mismatch: "
03653 "expected ID %u, got %u\n", l->sendmsg->id, id);
03654 else
03655 printf(";; Warning: short "
03656 "(< header size) message received\n");
03657 }
03658
03659 if (result == ISC_R_SUCCESS && (msgflags & DNS_MESSAGEFLAG_QR) == 0)
03660 printf(";; Warning: query response not set\n");
03661
03662 if (!match)
03663 goto udp_mismatch;
03664
03665 result = dns_message_create(mctx, DNS_MESSAGE_INTENTPARSE, &msg);
03666 check_result(result, "dns_message_create");
03667
03668 if (key != NULL) {
03669 if (l->querysig == NULL) {
03670 debug("getting initial querysig");
03671 result = dns_message_getquerytsig(l->sendmsg, mctx,
03672 &l->querysig);
03673 check_result(result, "dns_message_getquerytsig");
03674 }
03675 result = dns_message_setquerytsig(msg, l->querysig);
03676 check_result(result, "dns_message_setquerytsig");
03677 result = dns_message_settsigkey(msg, key);
03678 check_result(result, "dns_message_settsigkey");
03679 msg->tsigctx = l->tsigctx;
03680 l->tsigctx = NULL;
03681 if (l->msgcounter != 0)
03682 msg->tcp_continuation = 1;
03683 l->msgcounter++;
03684 }
03685
03686 debug("before parse starts");
03687 parseflags = DNS_MESSAGEPARSE_PRESERVEORDER;
03688 #ifdef DIG_SIGCHASE
03689 if (!l->sigchase) {
03690 do_sigchase = ISC_FALSE;
03691 } else {
03692 parseflags = 0;
03693 do_sigchase = ISC_TRUE;
03694 }
03695 #endif
03696 if (l->besteffort) {
03697 parseflags |= DNS_MESSAGEPARSE_BESTEFFORT;
03698 parseflags |= DNS_MESSAGEPARSE_IGNORETRUNCATION;
03699 }
03700 result = dns_message_parse(msg, b, parseflags);
03701 if (result == DNS_R_RECOVERABLE) {
03702 printf(";; Warning: Message parser reports malformed "
03703 "message packet.\n");
03704 result = ISC_R_SUCCESS;
03705 }
03706 if (result != ISC_R_SUCCESS) {
03707 printf(";; Got bad packet: %s\n", isc_result_totext(result));
03708 hex_dump(b);
03709 query->waiting_connect = ISC_FALSE;
03710 dns_message_destroy(&msg);
03711 isc_event_free(&event);
03712 clear_query(query);
03713 cancel_lookup(l);
03714 check_next_lookup(l);
03715 UNLOCK_LOOKUP;
03716 return;
03717 }
03718 if (msg->counts[DNS_SECTION_QUESTION] != 0) {
03719 match = ISC_TRUE;
03720 for (result = dns_message_firstname(msg, DNS_SECTION_QUESTION);
03721 result == ISC_R_SUCCESS && match;
03722 result = dns_message_nextname(msg, DNS_SECTION_QUESTION)) {
03723 dns_name_t *name = NULL;
03724 dns_rdataset_t *rdataset;
03725
03726 dns_message_currentname(msg, DNS_SECTION_QUESTION,
03727 &name);
03728 for (rdataset = ISC_LIST_HEAD(name->list);
03729 rdataset != NULL;
03730 rdataset = ISC_LIST_NEXT(rdataset, link)) {
03731 if (l->rdtype != rdataset->type ||
03732 l->rdclass != rdataset->rdclass ||
03733 !dns_name_equal(l->name, name)) {
03734 char namestr[DNS_NAME_FORMATSIZE];
03735 char typebuf[DNS_RDATATYPE_FORMATSIZE];
03736 char classbuf[DNS_RDATACLASS_FORMATSIZE];
03737 dns_name_format(name, namestr,
03738 sizeof(namestr));
03739 dns_rdatatype_format(rdataset->type,
03740 typebuf,
03741 sizeof(typebuf));
03742 dns_rdataclass_format(rdataset->rdclass,
03743 classbuf,
03744 sizeof(classbuf));
03745 printf(";; Question section mismatch: "
03746 "got %s/%s/%s\n",
03747 namestr, typebuf, classbuf);
03748 match = ISC_FALSE;
03749 }
03750 }
03751 }
03752 if (!match) {
03753 dns_message_destroy(&msg);
03754 if (l->tcp_mode) {
03755 isc_event_free(&event);
03756 clear_query(query);
03757 check_next_lookup(l);
03758 UNLOCK_LOOKUP;
03759 return;
03760 } else
03761 goto udp_mismatch;
03762 }
03763 }
03764 if (msg->rcode == dns_rcode_badvers && msg->opt != NULL &&
03765 (newedns = ednsvers(msg->opt)) < l->edns && l->ednsneg) {
03766
03767
03768
03769 if (l->comments)
03770 printf(";; BADVERS, retrying with EDNS version %u.\n",
03771 newedns);
03772 l->edns = newedns;
03773 n = requeue_lookup(l, ISC_TRUE);
03774 n->origin = query->lookup->origin;
03775 dns_message_destroy(&msg);
03776 isc_event_free(&event);
03777 clear_query(query);
03778 cancel_lookup(l);
03779 check_next_lookup(l);
03780 UNLOCK_LOOKUP;
03781 return;
03782 }
03783 if ((msg->flags & DNS_MESSAGEFLAG_TC) != 0 &&
03784 !l->ignore && !l->tcp_mode) {
03785 #ifdef ISC_PLATFORM_USESIT
03786 if (l->sitvalue == NULL && l->sit && msg->opt != NULL)
03787 process_opt(l, msg);
03788 #endif
03789 if (l->comments)
03790 printf(";; Truncated, retrying in TCP mode.\n");
03791 n = requeue_lookup(l, ISC_TRUE);
03792 n->tcp_mode = ISC_TRUE;
03793 n->origin = query->lookup->origin;
03794 dns_message_destroy(&msg);
03795 isc_event_free(&event);
03796 clear_query(query);
03797 cancel_lookup(l);
03798 check_next_lookup(l);
03799 UNLOCK_LOOKUP;
03800 return;
03801 }
03802 if ((msg->rcode == dns_rcode_servfail && !l->servfail_stops) ||
03803 (check_ra && (msg->flags & DNS_MESSAGEFLAG_RA) == 0 && l->recurse))
03804 {
03805 dig_query_t *next = ISC_LIST_NEXT(query, link);
03806 if (l->current_query == query)
03807 l->current_query = NULL;
03808 if (next != NULL) {
03809 debug("sending query %p\n", next);
03810 if (l->tcp_mode)
03811 send_tcp_connect(next);
03812 else
03813 send_udp(next);
03814 }
03815
03816
03817
03818
03819
03820 if ((ISC_LIST_HEAD(l->q) != query) ||
03821 (ISC_LIST_NEXT(query, link) != NULL)) {
03822 if (l->comments)
03823 printf(";; Got %s from %s, "
03824 "trying next server\n",
03825 msg->rcode == dns_rcode_servfail ?
03826 "SERVFAIL reply" :
03827 "recursion not available",
03828 query->servname);
03829 clear_query(query);
03830 check_next_lookup(l);
03831 dns_message_destroy(&msg);
03832 isc_event_free(&event);
03833 UNLOCK_LOOKUP;
03834 return;
03835 }
03836 }
03837
03838 if (key != NULL) {
03839 result = dns_tsig_verify(&query->recvbuf, msg, NULL, NULL);
03840 if (result != ISC_R_SUCCESS) {
03841 printf(";; Couldn't verify signature: %s\n",
03842 isc_result_totext(result));
03843 validated = ISC_FALSE;
03844 }
03845 l->tsigctx = msg->tsigctx;
03846 msg->tsigctx = NULL;
03847 if (l->querysig != NULL) {
03848 debug("freeing querysig buffer %p", l->querysig);
03849 isc_buffer_free(&l->querysig);
03850 }
03851 result = dns_message_getquerytsig(msg, mctx, &l->querysig);
03852 check_result(result,"dns_message_getquerytsig");
03853 }
03854
03855 extrabytes = isc_buffer_remaininglength(b);
03856
03857 debug("after parse");
03858 if (l->doing_xfr && l->xfr_q == NULL) {
03859 l->xfr_q = query;
03860
03861
03862
03863
03864
03865 if (timeout != INT_MAX && l->timer != NULL) {
03866 unsigned int local_timeout;
03867
03868 if (timeout == 0) {
03869 if (l->tcp_mode)
03870 local_timeout = TCP_TIMEOUT * 4;
03871 else
03872 local_timeout = UDP_TIMEOUT * 4;
03873 } else {
03874 if (timeout < (INT_MAX / 4))
03875 local_timeout = timeout * 4;
03876 else
03877 local_timeout = INT_MAX;
03878 }
03879 debug("have local timeout of %d", local_timeout);
03880 isc_interval_set(&l->interval, local_timeout, 0);
03881 result = isc_timer_reset(l->timer,
03882 isc_timertype_once,
03883 NULL,
03884 &l->interval,
03885 ISC_FALSE);
03886 check_result(result, "isc_timer_reset");
03887 }
03888 }
03889
03890 #ifdef ISC_PLATFORM_USESIT
03891 if (l->sitvalue != NULL) {
03892 if (msg->opt == NULL)
03893 printf(";; expected opt record in response\n");
03894 else
03895 process_opt(l, msg);
03896 } else if (l->sit && msg->opt != NULL)
03897 process_opt(l, msg);
03898 #endif
03899
03900 if (!l->doing_xfr || l->xfr_q == query) {
03901 if (msg->rcode == dns_rcode_nxdomain &&
03902 (l->origin != NULL || l->need_search)) {
03903 if (!next_origin(query->lookup) || showsearch) {
03904 printmessage(query, msg, ISC_TRUE);
03905 received(b->used, &sevent->address, query);
03906 }
03907 } else if (!l->trace && !l->ns_search_only) {
03908 #ifdef DIG_SIGCHASE
03909 if (!do_sigchase)
03910 #endif
03911 printmessage(query, msg, ISC_TRUE);
03912 } else if (l->trace) {
03913 int nl = 0;
03914 int count = msg->counts[DNS_SECTION_ANSWER];
03915
03916 debug("in TRACE code");
03917 if (!l->ns_search_only)
03918 printmessage(query, msg, ISC_TRUE);
03919
03920 l->rdtype = l->qrdtype;
03921 if (l->trace_root || (l->ns_search_only && count > 0)) {
03922 if (!l->trace_root)
03923 l->rdtype = dns_rdatatype_soa;
03924 nl = followup_lookup(msg, query,
03925 DNS_SECTION_ANSWER);
03926 l->trace_root = ISC_FALSE;
03927 } else if (count == 0)
03928 nl = followup_lookup(msg, query,
03929 DNS_SECTION_AUTHORITY);
03930 if (nl == 0)
03931 docancel = ISC_TRUE;
03932 } else {
03933 debug("in NSSEARCH code");
03934
03935 if (l->trace_root) {
03936
03937
03938
03939 int nl;
03940
03941 l->rdtype = dns_rdatatype_soa;
03942 nl = followup_lookup(msg, query,
03943 DNS_SECTION_ANSWER);
03944 if (nl == 0)
03945 docancel = ISC_TRUE;
03946 l->trace_root = ISC_FALSE;
03947 usesearch = ISC_FALSE;
03948 } else
03949 #ifdef DIG_SIGCHASE
03950 if (!do_sigchase)
03951 #endif
03952 printmessage(query, msg, ISC_TRUE);
03953 }
03954 #ifdef DIG_SIGCHASE
03955 if (do_sigchase) {
03956 chase_msg = isc_mem_allocate(mctx,
03957 sizeof(dig_message_t));
03958 if (chase_msg == NULL) {
03959 fatal("Memory allocation failure in %s:%d",
03960 __FILE__, __LINE__);
03961 }
03962 ISC_LIST_INITANDAPPEND(chase_message_list, chase_msg,
03963 link);
03964 if (dns_message_create(mctx, DNS_MESSAGE_INTENTPARSE,
03965 &msg_temp) != ISC_R_SUCCESS) {
03966 fatal("dns_message_create in %s:%d",
03967 __FILE__, __LINE__);
03968 }
03969
03970 isc_buffer_usedregion(b, &r);
03971 result = isc_buffer_allocate(mctx, &buf, r.length);
03972
03973 check_result(result, "isc_buffer_allocate");
03974 result = isc_buffer_copyregion(buf, &r);
03975 check_result(result, "isc_buffer_copyregion");
03976
03977 result = dns_message_parse(msg_temp, buf, 0);
03978
03979 isc_buffer_free(&buf);
03980 chase_msg->msg = msg_temp;
03981
03982 chase_msg2 = isc_mem_allocate(mctx,
03983 sizeof(dig_message_t));
03984 if (chase_msg2 == NULL) {
03985 fatal("Memory allocation failure in %s:%d",
03986 __FILE__, __LINE__);
03987 }
03988 ISC_LIST_INITANDAPPEND(chase_message_list2, chase_msg2,
03989 link);
03990 chase_msg2->msg = msg;
03991 }
03992 #endif
03993 }
03994
03995 #ifdef DIG_SIGCHASE
03996 if (l->sigchase && ISC_LIST_EMPTY(lookup_list)) {
03997 sigchase(msg_temp);
03998 }
03999 #endif
04000
04001 if (l->pending)
04002 debug("still pending.");
04003 if (l->doing_xfr) {
04004 if (query != l->xfr_q) {
04005 dns_message_destroy(&msg);
04006 isc_event_free(&event);
04007 query->waiting_connect = ISC_FALSE;
04008 UNLOCK_LOOKUP;
04009 return;
04010 }
04011 if (!docancel)
04012 docancel = check_for_more_data(query, msg, sevent);
04013 if (docancel) {
04014 dns_message_destroy(&msg);
04015 clear_query(query);
04016 cancel_lookup(l);
04017 check_next_lookup(l);
04018 }
04019 } else {
04020
04021 if (msg->rcode == dns_rcode_noerror || l->origin == NULL) {
04022
04023 #ifdef DIG_SIGCHASE
04024 if (!l->sigchase)
04025 #endif
04026 received(b->used, &sevent->address, query);
04027 }
04028
04029 if (!query->lookup->ns_search_only)
04030 query->lookup->pending = ISC_FALSE;
04031 if (!query->lookup->ns_search_only ||
04032 query->lookup->trace_root || docancel) {
04033 #ifdef DIG_SIGCHASE
04034 if (!do_sigchase)
04035 #endif
04036 dns_message_destroy(&msg);
04037
04038 cancel_lookup(l);
04039 }
04040 clear_query(query);
04041 check_next_lookup(l);
04042 }
04043 if (msg != NULL) {
04044 #ifdef DIG_SIGCHASE
04045 if (do_sigchase)
04046 msg = NULL;
04047 else
04048 #endif
04049 dns_message_destroy(&msg);
04050 }
04051 isc_event_free(&event);
04052 UNLOCK_LOOKUP;
04053 return;
04054
04055 udp_mismatch:
04056 isc_buffer_invalidate(&query->recvbuf);
04057 isc_buffer_init(&query->recvbuf, query->recvspace, COMMSIZE);
04058 ISC_LIST_ENQUEUE(query->recvlist, &query->recvbuf, link);
04059 result = isc_socket_recvv(query->sock, &query->recvlist, 1,
04060 global_task, recv_done, query);
04061 check_result(result, "isc_socket_recvv");
04062 recvcount++;
04063 isc_event_free(&event);
04064 UNLOCK_LOOKUP;
04065 return;
04066 }
04067
04068
04069
04070
04071
04072
04073 isc_result_t
04074 get_address(char *host, in_port_t myport, isc_sockaddr_t *sockaddr) {
04075 int count;
04076 isc_result_t result;
04077 isc_boolean_t is_running;
04078
04079 is_running = isc_app_isrunning();
04080 if (is_running)
04081 isc_app_block();
04082 result = bind9_getaddresses(host, myport, sockaddr, 1, &count);
04083 if (is_running)
04084 isc_app_unblock();
04085 if (result != ISC_R_SUCCESS)
04086 return (result);
04087
04088 INSIST(count == 1);
04089
04090 return (ISC_R_SUCCESS);
04091 }
04092
04093 int
04094 getaddresses(dig_lookup_t *lookup, const char *host, isc_result_t *resultp) {
04095 isc_result_t result;
04096 isc_sockaddr_t sockaddrs[DIG_MAX_ADDRESSES];
04097 isc_netaddr_t netaddr;
04098 int count, i;
04099 dig_server_t *srv;
04100 char tmp[ISC_NETADDR_FORMATSIZE];
04101
04102 result = bind9_getaddresses(host, 0, sockaddrs,
04103 DIG_MAX_ADDRESSES, &count);
04104 if (resultp != NULL)
04105 *resultp = result;
04106 if (result != ISC_R_SUCCESS) {
04107 if (resultp == NULL)
04108 fatal("couldn't get address for '%s': %s",
04109 host, isc_result_totext(result));
04110 return 0;
04111 }
04112
04113 for (i = 0; i < count; i++) {
04114 isc_netaddr_fromsockaddr(&netaddr, &sockaddrs[i]);
04115 isc_netaddr_format(&netaddr, tmp, sizeof(tmp));
04116 srv = make_server(tmp, host);
04117 ISC_LIST_APPEND(lookup->my_server_list, srv, link);
04118 }
04119
04120 return count;
04121 }
04122
04123
04124
04125
04126 void
04127 do_lookup(dig_lookup_t *lookup) {
04128 dig_query_t *query;
04129
04130 REQUIRE(lookup != NULL);
04131
04132 debug("do_lookup()");
04133 lookup->pending = ISC_TRUE;
04134 query = ISC_LIST_HEAD(lookup->q);
04135 if (query != NULL) {
04136 if (lookup->tcp_mode)
04137 send_tcp_connect(query);
04138 else
04139 send_udp(query);
04140 }
04141 }
04142
04143
04144
04145
04146 void
04147 onrun_callback(isc_task_t *task, isc_event_t *event) {
04148 UNUSED(task);
04149
04150 isc_event_free(&event);
04151 LOCK_LOOKUP;
04152 start_lookup();
04153 UNLOCK_LOOKUP;
04154 }
04155
04156
04157
04158
04159
04160 void
04161 cancel_all(void) {
04162 dig_lookup_t *l, *n;
04163 dig_query_t *q, *nq;
04164
04165 debug("cancel_all()");
04166
04167 LOCK_LOOKUP;
04168 if (free_now) {
04169 UNLOCK_LOOKUP;
04170 return;
04171 }
04172 cancel_now = ISC_TRUE;
04173 if (current_lookup != NULL) {
04174 if (current_lookup->timer != NULL)
04175 isc_timer_detach(¤t_lookup->timer);
04176 for (q = ISC_LIST_HEAD(current_lookup->q);
04177 q != NULL;
04178 q = nq)
04179 {
04180 nq = ISC_LIST_NEXT(q, link);
04181 debug("canceling pending query %p, belonging to %p",
04182 q, current_lookup);
04183 if (q->sock != NULL)
04184 isc_socket_cancel(q->sock, NULL,
04185 ISC_SOCKCANCEL_ALL);
04186 else
04187 clear_query(q);
04188 }
04189 for (q = ISC_LIST_HEAD(current_lookup->connecting);
04190 q != NULL;
04191 q = nq)
04192 {
04193 nq = ISC_LIST_NEXT(q, clink);
04194 debug("canceling connecting query %p, belonging to %p",
04195 q, current_lookup);
04196 if (q->sock != NULL)
04197 isc_socket_cancel(q->sock, NULL,
04198 ISC_SOCKCANCEL_ALL);
04199 else
04200 clear_query(q);
04201 }
04202 }
04203 l = ISC_LIST_HEAD(lookup_list);
04204 while (l != NULL) {
04205 n = ISC_LIST_NEXT(l, link);
04206 ISC_LIST_DEQUEUE(lookup_list, l, link);
04207 try_clear_lookup(l);
04208 l = n;
04209 }
04210 UNLOCK_LOOKUP;
04211 }
04212
04213
04214
04215
04216
04217 void
04218 destroy_libs(void) {
04219 #ifdef DIG_SIGCHASE
04220 void * ptr;
04221 dig_message_t *chase_msg;
04222 #endif
04223 #ifdef WITH_IDN
04224 isc_result_t result;
04225 #endif
04226
04227 if (keep != NULL)
04228 isc_socket_detach(&keep);
04229 debug("destroy_libs()");
04230 if (global_task != NULL) {
04231 debug("freeing task");
04232 isc_task_detach(&global_task);
04233 }
04234
04235
04236
04237
04238 if (taskmgr != NULL) {
04239 debug("freeing taskmgr");
04240 isc_taskmgr_destroy(&taskmgr);
04241 }
04242 LOCK_LOOKUP;
04243 REQUIRE(sockcount == 0);
04244 REQUIRE(recvcount == 0);
04245 REQUIRE(sendcount == 0);
04246
04247 INSIST(ISC_LIST_HEAD(lookup_list) == NULL);
04248 INSIST(current_lookup == NULL);
04249 INSIST(!free_now);
04250
04251 free_now = ISC_TRUE;
04252
04253 lwres_conf_clear(lwctx);
04254 lwres_context_destroy(&lwctx);
04255
04256 flush_server_list();
04257
04258 clear_searchlist();
04259
04260 #ifdef WITH_IDN
04261 result = dns_name_settotextfilter(NULL);
04262 check_result(result, "dns_name_settotextfilter");
04263 #endif
04264 dns_name_destroy();
04265
04266 if (commctx != NULL) {
04267 debug("freeing commctx");
04268 isc_mempool_destroy(&commctx);
04269 }
04270 if (socketmgr != NULL) {
04271 debug("freeing socketmgr");
04272 isc_socketmgr_destroy(&socketmgr);
04273 }
04274 if (timermgr != NULL) {
04275 debug("freeing timermgr");
04276 isc_timermgr_destroy(&timermgr);
04277 }
04278 if (key != NULL) {
04279 debug("freeing key %p", key);
04280 dns_tsigkey_detach(&key);
04281 }
04282 if (namebuf != NULL)
04283 isc_buffer_free(&namebuf);
04284
04285 if (is_dst_up) {
04286 debug("destroy DST lib");
04287 dst_lib_destroy();
04288 is_dst_up = ISC_FALSE;
04289 }
04290 if (entp != NULL) {
04291 debug("detach from entropy");
04292 isc_entropy_detach(&entp);
04293 }
04294
04295 UNLOCK_LOOKUP;
04296 DESTROYLOCK(&lookup_lock);
04297 #ifdef DIG_SIGCHASE
04298
04299 debug("Destroy the messages kept for sigchase");
04300
04301 chase_msg = ISC_LIST_HEAD(chase_message_list);
04302
04303 while (chase_msg != NULL) {
04304 INSIST(chase_msg->msg != NULL);
04305 dns_message_destroy(&(chase_msg->msg));
04306 ptr = chase_msg;
04307 chase_msg = ISC_LIST_NEXT(chase_msg, link);
04308 isc_mem_free(mctx, ptr);
04309 }
04310
04311 chase_msg = ISC_LIST_HEAD(chase_message_list2);
04312
04313 while (chase_msg != NULL) {
04314 INSIST(chase_msg->msg != NULL);
04315 dns_message_destroy(&(chase_msg->msg));
04316 ptr = chase_msg;
04317 chase_msg = ISC_LIST_NEXT(chase_msg, link);
04318 isc_mem_free(mctx, ptr);
04319 }
04320 if (dns_name_dynamic(&chase_name))
04321 free_name(&chase_name, mctx);
04322 #if DIG_SIGCHASE_TD
04323 if (dns_name_dynamic(&chase_current_name))
04324 free_name(&chase_current_name, mctx);
04325 if (dns_name_dynamic(&chase_authority_name))
04326 free_name(&chase_authority_name, mctx);
04327 #endif
04328 #if DIG_SIGCHASE_BU
04329 if (dns_name_dynamic(&chase_signame))
04330 free_name(&chase_signame, mctx);
04331 #endif
04332
04333 #endif
04334 debug("Removing log context");
04335 isc_log_destroy(&lctx);
04336
04337 while (ednsoptscnt > 0U) {
04338 ednsoptscnt--;
04339 if (ednsopts[ednsoptscnt].value != NULL)
04340 isc_mem_free(mctx, ednsopts[ednsoptscnt].value);
04341 }
04342
04343 debug("Destroy memory");
04344 if (memdebugging != 0)
04345 isc_mem_stats(mctx, stderr);
04346 if (mctx != NULL)
04347 isc_mem_destroy(&mctx);
04348 }
04349
04350 #ifdef WITH_IDN
04351 static void
04352 initialize_idn(void) {
04353 idn_result_t r;
04354 isc_result_t result;
04355
04356 #ifdef HAVE_SETLOCALE
04357
04358 (void)setlocale(LC_ALL, "");
04359 #endif
04360
04361 r = idn_nameinit(1);
04362 if (r != idn_success)
04363 fatal("idn api initialization failed: %s",
04364 idn_result_tostring(r));
04365
04366
04367 result = dns_name_settotextfilter(output_filter);
04368 check_result(result, "dns_name_settotextfilter");
04369 }
04370
04371 static isc_result_t
04372 output_filter(isc_buffer_t *buffer, unsigned int used_org,
04373 isc_boolean_t absolute)
04374 {
04375 char tmp1[MAXDLEN], tmp2[MAXDLEN];
04376 size_t fromlen, tolen;
04377 isc_boolean_t end_with_dot;
04378
04379
04380
04381
04382
04383 fromlen = isc_buffer_usedlength(buffer) - used_org;
04384 if (fromlen >= MAXDLEN)
04385 return (ISC_R_SUCCESS);
04386 memmove(tmp1, (char *)isc_buffer_base(buffer) + used_org, fromlen);
04387 end_with_dot = (tmp1[fromlen - 1] == '.') ? ISC_TRUE : ISC_FALSE;
04388 if (absolute && !end_with_dot) {
04389 fromlen++;
04390 if (fromlen >= MAXDLEN)
04391 return (ISC_R_SUCCESS);
04392 tmp1[fromlen - 1] = '.';
04393 }
04394 tmp1[fromlen] = '\0';
04395
04396
04397
04398
04399 if (idn_decodename(IDN_DECODE_APP, tmp1, tmp2, MAXDLEN) != idn_success)
04400 return (ISC_R_SUCCESS);
04401 strcpy(tmp1, tmp2);
04402
04403
04404
04405
04406
04407 tolen = strlen(tmp1);
04408 if (absolute && !end_with_dot && tmp1[tolen - 1] == '.')
04409 tolen--;
04410
04411 if (isc_buffer_length(buffer) < used_org + tolen)
04412 return (ISC_R_NOSPACE);
04413
04414 isc_buffer_subtract(buffer, isc_buffer_usedlength(buffer) - used_org);
04415 memmove(isc_buffer_used(buffer), tmp1, tolen);
04416 isc_buffer_add(buffer, (unsigned int)tolen);
04417
04418 return (ISC_R_SUCCESS);
04419 }
04420
04421 static idn_result_t
04422 append_textname(char *name, const char *origin, size_t namesize) {
04423 size_t namelen = strlen(name);
04424 size_t originlen = strlen(origin);
04425
04426
04427 if (namelen > 0 && name[namelen - 1] == '.')
04428 return idn_success;
04429
04430
04431
04432 if (namelen + 1 + originlen >= namesize)
04433 return idn_buffer_overflow;
04434
04435 if (*origin != '.')
04436 name[namelen++] = '.';
04437 (void)strcpy(name + namelen, origin);
04438 return idn_success;
04439 }
04440
04441 static void
04442 idn_check_result(idn_result_t r, const char *msg) {
04443 if (r != idn_success) {
04444 exitcode = 1;
04445 fatal("%s: %s", msg, idn_result_tostring(r));
04446 }
04447 }
04448 #endif
04449
04450 #ifdef DIG_SIGCHASE
04451 void
04452 print_type(dns_rdatatype_t type)
04453 {
04454 isc_buffer_t * b = NULL;
04455 isc_result_t result;
04456 isc_region_t r;
04457
04458 result = isc_buffer_allocate(mctx, &b, 4000);
04459 check_result(result, "isc_buffer_allocate");
04460
04461 result = dns_rdatatype_totext(type, b);
04462 check_result(result, "print_type");
04463
04464 isc_buffer_usedregion(b, &r);
04465 r.base[r.length] = '\0';
04466
04467 printf("%s", r.base);
04468
04469 isc_buffer_free(&b);
04470 }
04471
04472 void
04473 dump_database_section(dns_message_t *msg, int section)
04474 {
04475 dns_name_t *msg_name=NULL;
04476
04477 dns_rdataset_t *rdataset;
04478
04479 do {
04480 dns_message_currentname(msg, section, &msg_name);
04481
04482 for (rdataset = ISC_LIST_HEAD(msg_name->list); rdataset != NULL;
04483 rdataset = ISC_LIST_NEXT(rdataset, link)) {
04484 dns_name_print(msg_name, stdout);
04485 printf("\n");
04486 print_rdataset(msg_name, rdataset, mctx);
04487 printf("end\n");
04488 }
04489 msg_name = NULL;
04490 } while (dns_message_nextname(msg, section) == ISC_R_SUCCESS);
04491 }
04492
04493 void
04494 dump_database(void) {
04495 dig_message_t * msg;
04496
04497 for (msg = ISC_LIST_HEAD(chase_message_list); msg != NULL;
04498 msg = ISC_LIST_NEXT(msg, link)) {
04499 if (dns_message_firstname(msg->msg, DNS_SECTION_ANSWER)
04500 == ISC_R_SUCCESS)
04501 dump_database_section(msg->msg, DNS_SECTION_ANSWER);
04502
04503 if (dns_message_firstname(msg->msg, DNS_SECTION_AUTHORITY)
04504 == ISC_R_SUCCESS)
04505 dump_database_section(msg->msg, DNS_SECTION_AUTHORITY);
04506
04507 if (dns_message_firstname(msg->msg, DNS_SECTION_ADDITIONAL)
04508 == ISC_R_SUCCESS)
04509 dump_database_section(msg->msg, DNS_SECTION_ADDITIONAL);
04510 }
04511 }
04512
04513
04514 dns_rdataset_t *
04515 search_type(dns_name_t *name, dns_rdatatype_t type, dns_rdatatype_t covers) {
04516 dns_rdataset_t *rdataset;
04517 dns_rdata_sig_t siginfo;
04518 dns_rdata_t sigrdata = DNS_RDATA_INIT;
04519 isc_result_t result;
04520
04521 for (rdataset = ISC_LIST_HEAD(name->list); rdataset != NULL;
04522 rdataset = ISC_LIST_NEXT(rdataset, link)) {
04523 if (type == dns_rdatatype_any) {
04524 if (rdataset->type != dns_rdatatype_rrsig)
04525 return (rdataset);
04526 } else if ((type == dns_rdatatype_rrsig) &&
04527 (rdataset->type == dns_rdatatype_rrsig)) {
04528 result = dns_rdataset_first(rdataset);
04529 check_result(result, "empty rdataset");
04530 dns_rdataset_current(rdataset, &sigrdata);
04531 result = dns_rdata_tostruct(&sigrdata, &siginfo, NULL);
04532 check_result(result, "sigrdata tostruct siginfo");
04533
04534 if ((siginfo.covered == covers) ||
04535 (covers == dns_rdatatype_any)) {
04536 dns_rdata_reset(&sigrdata);
04537 dns_rdata_freestruct(&siginfo);
04538 return (rdataset);
04539 }
04540 dns_rdata_reset(&sigrdata);
04541 dns_rdata_freestruct(&siginfo);
04542 } else if (rdataset->type == type)
04543 return (rdataset);
04544 }
04545 return (NULL);
04546 }
04547
04548 dns_rdataset_t *
04549 chase_scanname_section(dns_message_t *msg, dns_name_t *name,
04550 dns_rdatatype_t type, dns_rdatatype_t covers,
04551 int section)
04552 {
04553 dns_rdataset_t *rdataset;
04554 dns_name_t *msg_name = NULL;
04555
04556 if (msg->counts[section] == 0)
04557 return (NULL);
04558
04559 do {
04560 dns_message_currentname(msg, section, &msg_name);
04561 if (dns_name_compare(msg_name, name) == 0) {
04562 rdataset = search_type(msg_name, type, covers);
04563 if (rdataset != NULL)
04564 return (rdataset);
04565 }
04566 msg_name = NULL;
04567 } while (dns_message_nextname(msg, section) == ISC_R_SUCCESS);
04568
04569 return (NULL);
04570 }
04571
04572
04573 dns_rdataset_t *
04574 chase_scanname(dns_name_t *name, dns_rdatatype_t type, dns_rdatatype_t covers)
04575 {
04576 dns_rdataset_t *rdataset = NULL;
04577 dig_message_t * msg;
04578
04579 for (msg = ISC_LIST_HEAD(chase_message_list2); msg != NULL;
04580 msg = ISC_LIST_NEXT(msg, link)) {
04581 if (dns_message_firstname(msg->msg, DNS_SECTION_ANSWER)
04582 == ISC_R_SUCCESS)
04583 rdataset = chase_scanname_section(msg->msg, name,
04584 type, covers,
04585 DNS_SECTION_ANSWER);
04586 if (rdataset != NULL)
04587 return (rdataset);
04588 if (dns_message_firstname(msg->msg, DNS_SECTION_AUTHORITY)
04589 == ISC_R_SUCCESS)
04590 rdataset =
04591 chase_scanname_section(msg->msg, name,
04592 type, covers,
04593 DNS_SECTION_AUTHORITY);
04594 if (rdataset != NULL)
04595 return (rdataset);
04596 if (dns_message_firstname(msg->msg, DNS_SECTION_ADDITIONAL)
04597 == ISC_R_SUCCESS)
04598 rdataset =
04599 chase_scanname_section(msg->msg, name, type,
04600 covers,
04601 DNS_SECTION_ADDITIONAL);
04602 if (rdataset != NULL)
04603 return (rdataset);
04604 }
04605
04606 return (NULL);
04607 }
04608
04609 dns_rdataset_t *
04610 sigchase_scanname(dns_rdatatype_t type, dns_rdatatype_t covers,
04611 isc_boolean_t * lookedup, dns_name_t *rdata_name)
04612 {
04613 dig_lookup_t *lookup;
04614 isc_buffer_t *b = NULL;
04615 isc_region_t r;
04616 isc_result_t result;
04617 dns_rdataset_t * temp;
04618 dns_rdatatype_t querytype;
04619
04620 temp = chase_scanname(rdata_name, type, covers);
04621 if (temp != NULL)
04622 return (temp);
04623
04624 if (*lookedup == ISC_TRUE)
04625 return (NULL);
04626
04627 lookup = clone_lookup(current_lookup, ISC_TRUE);
04628 lookup->trace_root = ISC_FALSE;
04629 lookup->new_search = ISC_TRUE;
04630
04631 result = isc_buffer_allocate(mctx, &b, BUFSIZE);
04632 check_result(result, "isc_buffer_allocate");
04633 result = dns_name_totext(rdata_name, ISC_FALSE, b);
04634 check_result(result, "dns_name_totext");
04635 isc_buffer_usedregion(b, &r);
04636 r.base[r.length] = '\0';
04637 strlcpy(lookup->textname, (char*)r.base, sizeof(lookup->textname));
04638 isc_buffer_free(&b);
04639
04640 if (type == dns_rdatatype_rrsig)
04641 querytype = covers;
04642 else
04643 querytype = type;
04644
04645 if (querytype == 0 || querytype == 255) {
04646 printf("Error in the queried type: %d\n", querytype);
04647 return (NULL);
04648 }
04649
04650 lookup->rdtype = querytype;
04651 lookup->rdtypeset = ISC_TRUE;
04652 lookup->qrdtype = querytype;
04653 *lookedup = ISC_TRUE;
04654
04655 ISC_LIST_APPEND(lookup_list, lookup, link);
04656 printf("\n\nLaunch a query to find a RRset of type ");
04657 print_type(type);
04658 printf(" for zone: %s\n", lookup->textname);
04659 return (NULL);
04660 }
04661
04662 isc_result_t
04663 insert_trustedkey(void *arg, dns_name_t *name, dns_rdataset_t *rdataset)
04664 {
04665 isc_result_t result;
04666 dst_key_t *key;
04667
04668 UNUSED(arg);
04669
04670 if (rdataset == NULL || rdataset->type != dns_rdatatype_dnskey)
04671 return (ISC_R_SUCCESS);
04672
04673 for (result = dns_rdataset_first(rdataset);
04674 result == ISC_R_SUCCESS;
04675 result = dns_rdataset_next(rdataset)) {
04676 dns_rdata_t rdata = DNS_RDATA_INIT;
04677 isc_buffer_t b;
04678
04679 dns_rdataset_current(rdataset, &rdata);
04680 isc_buffer_init(&b, rdata.data, rdata.length);
04681 isc_buffer_add(&b, rdata.length);
04682 if (tk_list.nb_tk >= MAX_TRUSTED_KEY)
04683 return (ISC_R_SUCCESS);
04684 key = NULL;
04685 result = dst_key_fromdns(name, rdata.rdclass, &b, mctx, &key);
04686 if (result != ISC_R_SUCCESS)
04687 continue;
04688 tk_list.key[tk_list.nb_tk++] = key;
04689 }
04690 return (ISC_R_SUCCESS);
04691 }
04692
04693 void
04694 clean_trustedkey()
04695 {
04696 int i = 0;
04697
04698 for (i= 0; i < MAX_TRUSTED_KEY; i++) {
04699 if (tk_list.key[i] != NULL) {
04700 dst_key_free(&tk_list.key[i]);
04701 tk_list.key[i] = NULL;
04702 } else
04703 break;
04704 }
04705 tk_list.nb_tk = 0;
04706 return;
04707 }
04708
04709 char alphnum[] =
04710 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
04711
04712 isc_result_t
04713 removetmpkey(isc_mem_t *mctx, const char *file)
04714 {
04715 char *tempnamekey = NULL;
04716 int tempnamekeylen;
04717 isc_result_t result;
04718
04719 tempnamekeylen = strlen(file)+10;
04720
04721 tempnamekey = isc_mem_allocate(mctx, tempnamekeylen);
04722 if (tempnamekey == NULL)
04723 return (ISC_R_NOMEMORY);
04724
04725 memset(tempnamekey, 0, tempnamekeylen);
04726
04727 strcat(tempnamekey, file);
04728 strcat(tempnamekey,".key");
04729 isc_file_remove(tempnamekey);
04730
04731 result = isc_file_remove(tempnamekey);
04732 isc_mem_free(mctx, tempnamekey);
04733 return (result);
04734 }
04735
04736 isc_result_t
04737 get_trusted_key(isc_mem_t *mctx)
04738 {
04739 isc_result_t result;
04740 const char *filename = NULL;
04741 dns_rdatacallbacks_t callbacks;
04742
04743 result = isc_file_exists(trustedkey);
04744 if (result != ISC_TRUE) {
04745 result = isc_file_exists("/etc/trusted-key.key");
04746 if (result != ISC_TRUE) {
04747 result = isc_file_exists("./trusted-key.key");
04748 if (result != ISC_TRUE)
04749 return (ISC_R_FAILURE);
04750 else
04751 filename = "./trusted-key.key";
04752 } else
04753 filename = "/etc/trusted-key.key";
04754 } else
04755 filename = trustedkey;
04756
04757 if (filename == NULL) {
04758 printf("No trusted key\n");
04759 return (ISC_R_FAILURE);
04760 }
04761
04762 dns_rdatacallbacks_init_stdio(&callbacks);
04763 callbacks.add = insert_trustedkey;
04764 return (dns_master_loadfile(filename, dns_rootname, dns_rootname,
04765 current_lookup->rdclass, DNS_MASTER_NOTTL,
04766 &callbacks, mctx));
04767 }
04768
04769
04770 static void
04771 nameFromString(const char *str, dns_name_t *p_ret) {
04772 size_t len = strlen(str);
04773 isc_result_t result;
04774 isc_buffer_t buffer;
04775 dns_fixedname_t fixedname;
04776
04777 REQUIRE(p_ret != NULL);
04778 REQUIRE(str != NULL);
04779
04780 isc_buffer_constinit(&buffer, str, len);
04781 isc_buffer_add(&buffer, len);
04782
04783 dns_fixedname_init(&fixedname);
04784 result = dns_name_fromtext(dns_fixedname_name(&fixedname), &buffer,
04785 dns_rootname, DNS_NAME_DOWNCASE, NULL);
04786 check_result(result, "nameFromString");
04787
04788 if (dns_name_dynamic(p_ret))
04789 free_name(p_ret, mctx);
04790
04791 result = dns_name_dup(dns_fixedname_name(&fixedname), mctx, p_ret);
04792 check_result(result, "nameFromString");
04793 }
04794
04795
04796 #if DIG_SIGCHASE_TD
04797 isc_result_t
04798 prepare_lookup(dns_name_t *name)
04799 {
04800 isc_result_t result;
04801 dig_lookup_t *lookup = NULL;
04802 dig_server_t *s;
04803 void *ptr;
04804
04805 lookup = clone_lookup(current_lookup, ISC_TRUE);
04806 lookup->trace_root = ISC_FALSE;
04807 lookup->new_search = ISC_TRUE;
04808 lookup->trace_root_sigchase = ISC_FALSE;
04809
04810 strlcpy(lookup->textname, lookup->textnamesigchase, MXNAME);
04811
04812 lookup->rdtype = lookup->rdtype_sigchase;
04813 lookup->rdtypeset = ISC_TRUE;
04814 lookup->qrdtype = lookup->qrdtype_sigchase;
04815
04816 s = ISC_LIST_HEAD(lookup->my_server_list);
04817 while (s != NULL) {
04818 debug("freeing server %p belonging to %p",
04819 s, lookup);
04820 ptr = s;
04821 s = ISC_LIST_NEXT(s, link);
04822 ISC_LIST_DEQUEUE(lookup->my_server_list,
04823 (dig_server_t *)ptr, link);
04824 isc_mem_free(mctx, ptr);
04825 }
04826
04827
04828 for (result = dns_rdataset_first(chase_nsrdataset);
04829 result == ISC_R_SUCCESS;
04830 result = dns_rdataset_next(chase_nsrdataset)) {
04831 char namestr[DNS_NAME_FORMATSIZE];
04832 dns_rdata_ns_t ns;
04833 dns_rdata_t rdata = DNS_RDATA_INIT;
04834 dig_server_t * srv = NULL;
04835 #define __FOLLOW_GLUE__
04836 #ifdef __FOLLOW_GLUE__
04837 isc_buffer_t *b = NULL;
04838 isc_result_t result;
04839 isc_region_t r;
04840 dns_rdataset_t *rdataset = NULL;
04841 isc_boolean_t true = ISC_TRUE;
04842 #endif
04843
04844 memset(namestr, 0, DNS_NAME_FORMATSIZE);
04845
04846 dns_rdataset_current(chase_nsrdataset, &rdata);
04847
04848 result = dns_rdata_tostruct(&rdata, &ns, NULL);
04849 check_result(result, "dns_rdata_tostruct");
04850
04851 #ifdef __FOLLOW_GLUE__
04852
04853 result = advanced_rrsearch(&rdataset, &ns.name,
04854 dns_rdatatype_aaaa,
04855 dns_rdatatype_any, &true);
04856 if (result == ISC_R_SUCCESS) {
04857 for (result = dns_rdataset_first(rdataset);
04858 result == ISC_R_SUCCESS;
04859 result = dns_rdataset_next(rdataset)) {
04860 dns_rdata_t aaaa = DNS_RDATA_INIT;
04861 dns_rdataset_current(rdataset, &aaaa);
04862
04863 result = isc_buffer_allocate(mctx, &b, 80);
04864 check_result(result, "isc_buffer_allocate");
04865
04866 dns_rdata_totext(&aaaa, &ns.name, b);
04867 isc_buffer_usedregion(b, &r);
04868 r.base[r.length] = '\0';
04869 strlcpy(namestr, (char*)r.base,
04870 DNS_NAME_FORMATSIZE);
04871 isc_buffer_free(&b);
04872 dns_rdata_reset(&aaaa);
04873
04874
04875 srv = make_server(namestr, namestr);
04876
04877 ISC_LIST_APPEND(lookup->my_server_list,
04878 srv, link);
04879 }
04880 }
04881
04882 rdataset = NULL;
04883 result = advanced_rrsearch(&rdataset, &ns.name, dns_rdatatype_a,
04884 dns_rdatatype_any, &true);
04885 if (result == ISC_R_SUCCESS) {
04886 for (result = dns_rdataset_first(rdataset);
04887 result == ISC_R_SUCCESS;
04888 result = dns_rdataset_next(rdataset)) {
04889 dns_rdata_t a = DNS_RDATA_INIT;
04890 dns_rdataset_current(rdataset, &a);
04891
04892 result = isc_buffer_allocate(mctx, &b, 80);
04893 check_result(result, "isc_buffer_allocate");
04894
04895 dns_rdata_totext(&a, &ns.name, b);
04896 isc_buffer_usedregion(b, &r);
04897 r.base[r.length] = '\0';
04898 strlcpy(namestr, (char*)r.base,
04899 DNS_NAME_FORMATSIZE);
04900 isc_buffer_free(&b);
04901 dns_rdata_reset(&a);
04902 printf("ns name: %s\n", namestr);
04903
04904
04905 srv = make_server(namestr, namestr);
04906
04907 ISC_LIST_APPEND(lookup->my_server_list,
04908 srv, link);
04909 }
04910 }
04911 #else
04912
04913 dns_name_format(&ns.name, namestr, sizeof(namestr));
04914 printf("ns name: ");
04915 dns_name_print(&ns.name, stdout);
04916 printf("\n");
04917 srv = make_server(namestr, namestr);
04918
04919 ISC_LIST_APPEND(lookup->my_server_list, srv, link);
04920
04921 #endif
04922 dns_rdata_freestruct(&ns);
04923 dns_rdata_reset(&rdata);
04924
04925 }
04926
04927 ISC_LIST_APPEND(lookup_list, lookup, link);
04928 printf("\nLaunch a query to find a RRset of type ");
04929 print_type(lookup->rdtype);
04930 printf(" for zone: %s", lookup->textname);
04931 printf(" with nameservers:");
04932 printf("\n");
04933 print_rdataset(name, chase_nsrdataset, mctx);
04934 return (ISC_R_SUCCESS);
04935 }
04936
04937
04938 isc_result_t
04939 child_of_zone(dns_name_t * name, dns_name_t * zone_name,
04940 dns_name_t * child_name)
04941 {
04942 dns_namereln_t name_reln;
04943 int orderp;
04944 unsigned int nlabelsp;
04945
04946 name_reln = dns_name_fullcompare(name, zone_name, &orderp, &nlabelsp);
04947 if (name_reln != dns_namereln_subdomain ||
04948 dns_name_countlabels(name) <= dns_name_countlabels(zone_name) + 1) {
04949 printf("\n;; ERROR : ");
04950 dns_name_print(name, stdout);
04951 printf(" is not a subdomain of: ");
04952 dns_name_print(zone_name, stdout);
04953 printf(" FAILED\n\n");
04954 return (ISC_R_FAILURE);
04955 }
04956
04957 dns_name_getlabelsequence(name,
04958 dns_name_countlabels(name) -
04959 dns_name_countlabels(zone_name) -1,
04960 dns_name_countlabels(zone_name) +1,
04961 child_name);
04962 return (ISC_R_SUCCESS);
04963 }
04964
04965 isc_result_t
04966 grandfather_pb_test(dns_name_t *zone_name, dns_rdataset_t *sigrdataset) {
04967 dns_rdata_sig_t siginfo;
04968 dns_rdataset_t mysigrdataset;
04969 isc_result_t result;
04970
04971 dns_rdataset_init(&mysigrdataset);
04972 dns_rdataset_clone(sigrdataset, &mysigrdataset);
04973
04974 result = dns_rdataset_first(&mysigrdataset);
04975 check_result(result, "empty RRSIG dataset");
04976
04977 do {
04978 dns_rdata_t sigrdata = DNS_RDATA_INIT;
04979
04980 dns_rdataset_current(&mysigrdataset, &sigrdata);
04981
04982 result = dns_rdata_tostruct(&sigrdata, &siginfo, NULL);
04983 check_result(result, "sigrdata tostruct siginfo");
04984
04985 if (dns_name_compare(&siginfo.signer, zone_name) == 0) {
04986 result = ISC_R_SUCCESS;
04987 goto cleanup;
04988 }
04989 } while (dns_rdataset_next(&mysigrdataset) == ISC_R_SUCCESS);
04990
04991 result = ISC_R_FAILURE;
04992 cleanup:
04993 dns_rdataset_disassociate(&mysigrdataset);
04994
04995 return (result);
04996 }
04997
04998
04999 isc_result_t
05000 initialization(dns_name_t *name)
05001 {
05002 isc_result_t result;
05003 isc_boolean_t true = ISC_TRUE;
05004
05005 chase_nsrdataset = NULL;
05006 result = advanced_rrsearch(&chase_nsrdataset, name, dns_rdatatype_ns,
05007 dns_rdatatype_any, &true);
05008 if (result != ISC_R_SUCCESS) {
05009 printf("\n;; NS RRset is missing to continue validation:"
05010 " FAILED\n\n");
05011 return (ISC_R_FAILURE);
05012 }
05013 INSIST(chase_nsrdataset != NULL);
05014 prepare_lookup(name);
05015
05016 dup_name(name, &chase_current_name, mctx);
05017
05018 return (ISC_R_SUCCESS);
05019 }
05020 #endif
05021
05022 void
05023 print_rdataset(dns_name_t *name, dns_rdataset_t *rdataset, isc_mem_t *mctx)
05024 {
05025 isc_buffer_t *b = NULL;
05026 isc_result_t result;
05027 isc_region_t r;
05028
05029 result = isc_buffer_allocate(mctx, &b, 9000);
05030 check_result(result, "isc_buffer_allocate");
05031
05032 printrdataset(name, rdataset, b);
05033
05034 isc_buffer_usedregion(b, &r);
05035 r.base[r.length] = '\0';
05036
05037
05038 printf("%s\n", r.base);
05039
05040 isc_buffer_free(&b);
05041 }
05042
05043
05044 void
05045 dup_name(dns_name_t *source, dns_name_t *target, isc_mem_t *mctx) {
05046 isc_result_t result;
05047
05048 if (dns_name_dynamic(target))
05049 free_name(target, mctx);
05050 result = dns_name_dup(source, mctx, target);
05051 check_result(result, "dns_name_dup");
05052 }
05053
05054 void
05055 free_name(dns_name_t *name, isc_mem_t *mctx) {
05056 dns_name_free(name, mctx);
05057 dns_name_init(name, NULL);
05058 }
05059
05060
05061
05062
05063
05064
05065
05066
05067
05068
05069
05070 isc_result_t
05071 contains_trusted_key(dns_name_t *name, dns_rdataset_t *rdataset,
05072 dns_rdataset_t *sigrdataset,
05073 isc_mem_t *mctx)
05074 {
05075 dns_rdataset_t myrdataset;
05076 dst_key_t *dnsseckey = NULL;
05077 int i;
05078 isc_result_t result;
05079
05080 if (name == NULL || rdataset == NULL)
05081 return (ISC_R_FAILURE);
05082
05083 dns_rdataset_init(&myrdataset);
05084 dns_rdataset_clone(rdataset, &myrdataset);
05085
05086 result = dns_rdataset_first(&myrdataset);
05087 check_result(result, "empty rdataset");
05088
05089 do {
05090 dns_rdata_t rdata = DNS_RDATA_INIT;
05091
05092 dns_rdataset_current(&myrdataset, &rdata);
05093 INSIST(rdata.type == dns_rdatatype_dnskey);
05094
05095 result = dns_dnssec_keyfromrdata(name, &rdata,
05096 mctx, &dnsseckey);
05097 check_result(result, "dns_dnssec_keyfromrdata");
05098
05099 for (i = 0; i < tk_list.nb_tk; i++) {
05100 if (dst_key_compare(tk_list.key[i], dnsseckey)
05101 == ISC_TRUE) {
05102 dns_rdata_reset(&rdata);
05103
05104 printf(";; Ok, find a Trusted Key in the "
05105 "DNSKEY RRset: %d\n",
05106 dst_key_id(dnsseckey));
05107 result = sigchase_verify_sig_key(name, rdataset,
05108 dnsseckey,
05109 sigrdataset,
05110 mctx);
05111 if (result == ISC_R_SUCCESS)
05112 goto cleanup;
05113 }
05114 }
05115 dst_key_free(&dnsseckey);
05116 } while (dns_rdataset_next(&myrdataset) == ISC_R_SUCCESS);
05117
05118 cleanup:
05119 if (dnsseckey != NULL)
05120 dst_key_free(&dnsseckey);
05121 dns_rdataset_disassociate(&myrdataset);
05122
05123 return (ISC_R_NOTFOUND);
05124 }
05125
05126 isc_result_t
05127 sigchase_verify_sig(dns_name_t *name, dns_rdataset_t *rdataset,
05128 dns_rdataset_t *keyrdataset,
05129 dns_rdataset_t *sigrdataset,
05130 isc_mem_t *mctx)
05131 {
05132 dns_rdataset_t mykeyrdataset;
05133 dst_key_t *dnsseckey = NULL;
05134 isc_result_t result;
05135
05136 dns_rdataset_init(&mykeyrdataset);
05137 dns_rdataset_clone(keyrdataset, &mykeyrdataset);
05138
05139 result = dns_rdataset_first(&mykeyrdataset);
05140 check_result(result, "empty DNSKEY dataset");
05141
05142 do {
05143 dns_rdata_t keyrdata = DNS_RDATA_INIT;
05144
05145 dns_rdataset_current(&mykeyrdataset, &keyrdata);
05146 INSIST(keyrdata.type == dns_rdatatype_dnskey);
05147
05148 result = dns_dnssec_keyfromrdata(name, &keyrdata,
05149 mctx, &dnsseckey);
05150 check_result(result, "dns_dnssec_keyfromrdata");
05151
05152 result = sigchase_verify_sig_key(name, rdataset, dnsseckey,
05153 sigrdataset, mctx);
05154 if (result == ISC_R_SUCCESS)
05155 goto cleanup;
05156 dst_key_free(&dnsseckey);
05157 } while (dns_rdataset_next(&mykeyrdataset) == ISC_R_SUCCESS);
05158
05159 result = ISC_R_NOTFOUND;
05160
05161 cleanup:
05162 if (dnsseckey != NULL)
05163 dst_key_free(&dnsseckey);
05164 dns_rdataset_disassociate(&mykeyrdataset);
05165
05166 return (result);
05167 }
05168
05169 isc_result_t
05170 sigchase_verify_sig_key(dns_name_t *name, dns_rdataset_t *rdataset,
05171 dst_key_t *dnsseckey, dns_rdataset_t *sigrdataset,
05172 isc_mem_t *mctx)
05173 {
05174 dns_rdata_sig_t siginfo;
05175 dns_rdataset_t myrdataset;
05176 dns_rdataset_t mysigrdataset;
05177 isc_result_t result;
05178
05179 dns_rdataset_init(&myrdataset);
05180 dns_rdataset_clone(rdataset, &myrdataset);
05181 dns_rdataset_init(&mysigrdataset);
05182 dns_rdataset_clone(sigrdataset, &mysigrdataset);
05183
05184 result = dns_rdataset_first(&mysigrdataset);
05185 check_result(result, "empty RRSIG dataset");
05186
05187 do {
05188 dns_rdata_t sigrdata = DNS_RDATA_INIT;
05189
05190 dns_rdataset_current(&mysigrdataset, &sigrdata);
05191
05192 result = dns_rdata_tostruct(&sigrdata, &siginfo, NULL);
05193 check_result(result, "sigrdata tostruct siginfo");
05194
05195
05196
05197
05198
05199 if (siginfo.keyid == dst_key_id(dnsseckey)) {
05200
05201 result = dns_rdataset_first(&myrdataset);
05202 check_result(result, "empty DS dataset");
05203
05204 result = dns_dnssec_verify(name, &myrdataset, dnsseckey,
05205 ISC_FALSE, mctx, &sigrdata);
05206
05207 printf(";; VERIFYING ");
05208 print_type(rdataset->type);
05209 printf(" RRset for ");
05210 dns_name_print(name, stdout);
05211 printf(" with DNSKEY:%d: %s\n", dst_key_id(dnsseckey),
05212 isc_result_totext(result));
05213
05214 if (result == ISC_R_SUCCESS)
05215 goto cleanup;
05216 }
05217 } while (dns_rdataset_next(&mysigrdataset) == ISC_R_SUCCESS);
05218
05219 result = ISC_R_NOTFOUND;
05220
05221 cleanup:
05222 dns_rdataset_disassociate(&myrdataset);
05223 dns_rdataset_disassociate(&mysigrdataset);
05224
05225 return (result);
05226 }
05227
05228
05229 isc_result_t
05230 sigchase_verify_ds(dns_name_t *name, dns_rdataset_t *keyrdataset,
05231 dns_rdataset_t *dsrdataset, isc_mem_t *mctx)
05232 {
05233 dns_rdata_ds_t dsinfo;
05234 dns_rdataset_t mydsrdataset;
05235 dns_rdataset_t mykeyrdataset;
05236 dst_key_t *dnsseckey = NULL;
05237 isc_result_t result;
05238 unsigned char dsbuf[DNS_DS_BUFFERSIZE];
05239
05240 dns_rdataset_init(&mydsrdataset);
05241 dns_rdataset_clone(dsrdataset, &mydsrdataset);
05242 dns_rdataset_init(&mykeyrdataset);
05243 dns_rdataset_clone(keyrdataset, &mykeyrdataset);
05244
05245 result = dns_rdataset_first(&mydsrdataset);
05246 check_result(result, "empty DSset dataset");
05247 do {
05248 dns_rdata_t dsrdata = DNS_RDATA_INIT;
05249
05250 dns_rdataset_current(&mydsrdataset, &dsrdata);
05251
05252 result = dns_rdata_tostruct(&dsrdata, &dsinfo, NULL);
05253 check_result(result, "dns_rdata_tostruct for DS");
05254
05255 result = dns_rdataset_first(&mykeyrdataset);
05256 check_result(result, "empty KEY dataset");
05257
05258 do {
05259 dns_rdata_t keyrdata = DNS_RDATA_INIT;
05260
05261 dns_rdataset_current(&mykeyrdataset, &keyrdata);
05262 INSIST(keyrdata.type == dns_rdatatype_dnskey);
05263
05264 result = dns_dnssec_keyfromrdata(name, &keyrdata,
05265 mctx, &dnsseckey);
05266 check_result(result, "dns_dnssec_keyfromrdata");
05267
05268
05269
05270
05271
05272 if (dsinfo.key_tag == dst_key_id(dnsseckey)) {
05273 dns_rdata_t newdsrdata = DNS_RDATA_INIT;
05274
05275 result = dns_ds_buildrdata(name, &keyrdata,
05276 dsinfo.digest_type,
05277 dsbuf, &newdsrdata);
05278 dns_rdata_freestruct(&dsinfo);
05279
05280 if (result != ISC_R_SUCCESS) {
05281 printf("Oops: impossible to build"
05282 " new DS rdata\n");
05283 goto cleanup;
05284 }
05285
05286
05287 if (dns_rdata_compare(&dsrdata,
05288 &newdsrdata) == 0) {
05289 printf(";; OK a DS valids a DNSKEY"
05290 " in the RRset\n");
05291 printf(";; Now verify that this"
05292 " DNSKEY validates the "
05293 "DNSKEY RRset\n");
05294
05295 result = sigchase_verify_sig_key(name,
05296 keyrdataset,
05297 dnsseckey,
05298 chase_sigkeyrdataset,
05299 mctx);
05300 if (result == ISC_R_SUCCESS)
05301 goto cleanup;
05302 } else {
05303 printf(";; This DS is NOT the DS for"
05304 " the chasing KEY: FAILED\n");
05305 }
05306 }
05307 dst_key_free(&dnsseckey);
05308 } while (dns_rdataset_next(&mykeyrdataset) == ISC_R_SUCCESS);
05309 } while (dns_rdataset_next(&mydsrdataset) == ISC_R_SUCCESS);
05310
05311 result = ISC_R_NOTFOUND;
05312
05313 cleanup:
05314 if (dnsseckey != NULL)
05315 dst_key_free(&dnsseckey);
05316 dns_rdataset_disassociate(&mydsrdataset);
05317 dns_rdataset_disassociate(&mykeyrdataset);
05318
05319 return (result);
05320 }
05321
05322
05323
05324
05325
05326
05327
05328
05329
05330
05331
05332
05333 isc_result_t
05334 advanced_rrsearch(dns_rdataset_t **rdataset, dns_name_t *name,
05335 dns_rdatatype_t type, dns_rdatatype_t covers,
05336 isc_boolean_t *lookedup)
05337 {
05338 isc_boolean_t tmplookedup;
05339
05340 INSIST(rdataset != NULL);
05341
05342 if (*rdataset != NULL)
05343 return (ISC_R_SUCCESS);
05344
05345 tmplookedup = *lookedup;
05346 if ((*rdataset = sigchase_scanname(type, covers,
05347 lookedup, name)) == NULL) {
05348 if (tmplookedup)
05349 return (ISC_R_FAILURE);
05350 return (ISC_R_NOTFOUND);
05351 }
05352 *lookedup = ISC_FALSE;
05353 return (ISC_R_SUCCESS);
05354 }
05355
05356
05357
05358 #if DIG_SIGCHASE_TD
05359 void
05360 sigchase_td(dns_message_t *msg)
05361 {
05362 isc_result_t result;
05363 dns_name_t *name = NULL;
05364 isc_boolean_t have_answer = ISC_FALSE;
05365 isc_boolean_t true = ISC_TRUE;
05366
05367 if (msg->rcode != dns_rcode_noerror &&
05368 msg->rcode != dns_rcode_nxdomain) {
05369 char buf[20];
05370 isc_buffer_t b;
05371
05372 isc_buffer_init(&b, buf, sizeof(buf));
05373 result = dns_rcode_totext(msg->rcode, &b);
05374 check_result(result, "dns_rcode_totext failed");
05375 printf("error response code %.*s\n",
05376 (int)isc_buffer_usedlength(&b), buf);
05377 error_message = msg;
05378 return;
05379 }
05380
05381 if ((result = dns_message_firstname(msg, DNS_SECTION_ANSWER))
05382 == ISC_R_SUCCESS) {
05383 dns_message_currentname(msg, DNS_SECTION_ANSWER, &name);
05384 if (current_lookup->trace_root_sigchase) {
05385 initialization(name);
05386 return;
05387 }
05388 have_answer = true;
05389 } else {
05390 if (!current_lookup->trace_root_sigchase) {
05391 result = dns_message_firstname(msg,
05392 DNS_SECTION_AUTHORITY);
05393 if (result != ISC_R_SUCCESS) {
05394 printf("no answer or authority section\n");
05395 error_message = msg;
05396 return;
05397 }
05398 dns_message_currentname(msg, DNS_SECTION_AUTHORITY,
05399 &name);
05400 chase_nsrdataset
05401 = chase_scanname_section(msg, name,
05402 dns_rdatatype_ns,
05403 dns_rdatatype_any,
05404 DNS_SECTION_AUTHORITY);
05405 dup_name(name, &chase_authority_name, mctx);
05406 if (chase_nsrdataset != NULL) {
05407 have_delegation_ns = ISC_TRUE;
05408 printf("no response but there is a delegation"
05409 " in authority section: ");
05410 dns_name_print(name, stdout);
05411 printf("\n");
05412 } else {
05413 printf("no response and no delegation in "
05414 "authority section but a reference"
05415 " to: ");
05416 dns_name_print(name, stdout);
05417 printf("\n");
05418 error_message = msg;
05419 }
05420 } else {
05421 printf(";; NO ANSWERS: %s\n",
05422 isc_result_totext(result));
05423 free_name(&chase_name, mctx);
05424 clean_trustedkey();
05425 return;
05426 }
05427 }
05428
05429
05430 if (have_answer) {
05431 chase_rdataset
05432 = chase_scanname_section(msg, &chase_name,
05433 current_lookup
05434 ->rdtype_sigchase,
05435 dns_rdatatype_any,
05436 DNS_SECTION_ANSWER);
05437 if (chase_rdataset != NULL)
05438 have_response = ISC_TRUE;
05439 }
05440
05441 result = advanced_rrsearch(&chase_keyrdataset,
05442 &chase_current_name,
05443 dns_rdatatype_dnskey,
05444 dns_rdatatype_any,
05445 &chase_keylookedup);
05446 if (result == ISC_R_FAILURE) {
05447 printf("\n;; DNSKEY is missing to continue validation:"
05448 " FAILED\n\n");
05449 goto cleanandgo;
05450 }
05451 if (result == ISC_R_NOTFOUND)
05452 return;
05453 INSIST(chase_keyrdataset != NULL);
05454 printf("\n;; DNSKEYset:\n");
05455 print_rdataset(&chase_current_name , chase_keyrdataset, mctx);
05456
05457
05458 result = advanced_rrsearch(&chase_sigkeyrdataset,
05459 &chase_current_name,
05460 dns_rdatatype_rrsig,
05461 dns_rdatatype_dnskey,
05462 &chase_sigkeylookedup);
05463 if (result == ISC_R_FAILURE) {
05464 printf("\n;; RRSIG of DNSKEY is missing to continue validation:"
05465 " FAILED\n\n");
05466 goto cleanandgo;
05467 }
05468 if (result == ISC_R_NOTFOUND)
05469 return;
05470 INSIST(chase_sigkeyrdataset != NULL);
05471 printf("\n;; RRSIG of the DNSKEYset:\n");
05472 print_rdataset(&chase_current_name , chase_sigkeyrdataset, mctx);
05473
05474
05475 if (!chase_dslookedup && !chase_nslookedup) {
05476 if (!delegation_follow) {
05477 result = contains_trusted_key(&chase_current_name,
05478 chase_keyrdataset,
05479 chase_sigkeyrdataset,
05480 mctx);
05481 } else {
05482 INSIST(chase_dsrdataset != NULL);
05483 INSIST(chase_sigdsrdataset != NULL);
05484 result = sigchase_verify_ds(&chase_current_name,
05485 chase_keyrdataset,
05486 chase_dsrdataset,
05487 mctx);
05488 }
05489
05490 if (result != ISC_R_SUCCESS) {
05491 printf("\n;; chain of trust can't be validated:"
05492 " FAILED\n\n");
05493 goto cleanandgo;
05494 } else {
05495 chase_dsrdataset = NULL;
05496 chase_sigdsrdataset = NULL;
05497 }
05498 }
05499
05500 if (have_response || (!have_delegation_ns && !have_response)) {
05501
05502
05503 if (have_response) {
05504 result = advanced_rrsearch(&chase_sigrdataset,
05505 &chase_name,
05506 dns_rdatatype_rrsig,
05507 current_lookup
05508 ->rdtype_sigchase,
05509 &true);
05510 if (result == ISC_R_FAILURE) {
05511 printf("\n;; RRset is missing to continue"
05512 " validation SHOULD NOT APPEND:"
05513 " FAILED\n\n");
05514 goto cleanandgo;
05515 }
05516
05517 } else {
05518 result = advanced_rrsearch(&chase_sigrdataset,
05519 &chase_authority_name,
05520 dns_rdatatype_rrsig,
05521 dns_rdatatype_any,
05522 &true);
05523 if (result == ISC_R_FAILURE) {
05524 printf("\n;; RRSIG is missing to continue"
05525 " validation SHOULD NOT APPEND:"
05526 " FAILED\n\n");
05527 goto cleanandgo;
05528 }
05529 }
05530 result = grandfather_pb_test(&chase_current_name,
05531 chase_sigrdataset);
05532 if (result != ISC_R_SUCCESS) {
05533 dns_name_t tmp_name;
05534
05535 printf("\n;; We are in a Grand Father Problem:"
05536 " See 2.2.1 in RFC 3658\n");
05537 chase_rdataset = NULL;
05538 chase_sigrdataset = NULL;
05539 have_response = ISC_FALSE;
05540 have_delegation_ns = ISC_FALSE;
05541
05542 dns_name_init(&tmp_name, NULL);
05543 result = child_of_zone(&chase_name, &chase_current_name,
05544 &tmp_name);
05545 if (dns_name_dynamic(&chase_authority_name))
05546 free_name(&chase_authority_name, mctx);
05547 dup_name(&tmp_name, &chase_authority_name, mctx);
05548 printf(";; and we try to continue chain of trust"
05549 " validation of the zone: ");
05550 dns_name_print(&chase_authority_name, stdout);
05551 printf("\n");
05552 have_delegation_ns = ISC_TRUE;
05553 } else {
05554 if (have_response)
05555 goto finalstep;
05556 else
05557 chase_sigrdataset = NULL;
05558 }
05559 }
05560
05561 if (have_delegation_ns) {
05562 chase_nsrdataset = NULL;
05563 result = advanced_rrsearch(&chase_nsrdataset,
05564 &chase_authority_name,
05565 dns_rdatatype_ns,
05566 dns_rdatatype_any,
05567 &chase_nslookedup);
05568 if (result == ISC_R_FAILURE) {
05569 printf("\n;;NSset is missing to continue validation:"
05570 " FAILED\n\n");
05571 goto cleanandgo;
05572 }
05573 if (result == ISC_R_NOTFOUND) {
05574 return;
05575 }
05576 INSIST(chase_nsrdataset != NULL);
05577
05578 result = advanced_rrsearch(&chase_dsrdataset,
05579 &chase_authority_name,
05580 dns_rdatatype_ds,
05581 dns_rdatatype_any,
05582 &chase_dslookedup);
05583 if (result == ISC_R_FAILURE) {
05584 printf("\n;; DSset is missing to continue validation:"
05585 " FAILED\n\n");
05586 goto cleanandgo;
05587 }
05588 if (result == ISC_R_NOTFOUND)
05589 return;
05590 INSIST(chase_dsrdataset != NULL);
05591 printf("\n;; DSset:\n");
05592 print_rdataset(&chase_authority_name , chase_dsrdataset, mctx);
05593
05594 result = advanced_rrsearch(&chase_sigdsrdataset,
05595 &chase_authority_name,
05596 dns_rdatatype_rrsig,
05597 dns_rdatatype_ds,
05598 &true);
05599 if (result != ISC_R_SUCCESS) {
05600 printf("\n;; DSset is missing to continue validation:"
05601 " FAILED\n\n");
05602 goto cleanandgo;
05603 }
05604 printf("\n;; RRSIGset of DSset\n");
05605 print_rdataset(&chase_authority_name,
05606 chase_sigdsrdataset, mctx);
05607 INSIST(chase_sigdsrdataset != NULL);
05608
05609 result = sigchase_verify_sig(&chase_authority_name,
05610 chase_dsrdataset,
05611 chase_keyrdataset,
05612 chase_sigdsrdataset, mctx);
05613 if (result != ISC_R_SUCCESS) {
05614 printf("\n;; Impossible to verify the DSset:"
05615 " FAILED\n\n");
05616 goto cleanandgo;
05617 }
05618 chase_keyrdataset = NULL;
05619 chase_sigkeyrdataset = NULL;
05620
05621
05622 prepare_lookup(&chase_authority_name);
05623
05624 have_response = ISC_FALSE;
05625 have_delegation_ns = ISC_FALSE;
05626 delegation_follow = ISC_TRUE;
05627 error_message = NULL;
05628 dup_name(&chase_authority_name, &chase_current_name, mctx);
05629 free_name(&chase_authority_name, mctx);
05630 return;
05631 }
05632
05633
05634 if (error_message != NULL) {
05635 dns_rdataset_t *rdataset;
05636 dns_rdataset_t *sigrdataset;
05637 dns_name_t rdata_name;
05638 isc_result_t ret = ISC_R_FAILURE;
05639
05640 dns_name_init(&rdata_name, NULL);
05641 result = prove_nx(error_message, &chase_name,
05642 current_lookup->rdclass_sigchase,
05643 current_lookup->rdtype_sigchase, &rdata_name,
05644 &rdataset, &sigrdataset);
05645 if (rdataset == NULL || sigrdataset == NULL ||
05646 dns_name_countlabels(&rdata_name) == 0) {
05647 printf("\n;; Impossible to verify the non-existence,"
05648 " the NSEC RRset can't be validated:"
05649 " FAILED\n\n");
05650 goto cleanandgo;
05651 }
05652 ret = sigchase_verify_sig(&rdata_name, rdataset,
05653 chase_keyrdataset,
05654 sigrdataset, mctx);
05655 if (ret != ISC_R_SUCCESS) {
05656 free_name(&rdata_name, mctx);
05657 printf("\n;; Impossible to verify the NSEC RR to prove"
05658 " the non-existence : FAILED\n\n");
05659 goto cleanandgo;
05660 }
05661 free_name(&rdata_name, mctx);
05662 if (result != ISC_R_SUCCESS) {
05663 printf("\n;; Impossible to verify the non-existence:"
05664 " FAILED\n\n");
05665 goto cleanandgo;
05666 } else {
05667 printf("\n;; OK the query doesn't have response but"
05668 " we have validate this fact : SUCCESS\n\n");
05669 goto cleanandgo;
05670 }
05671 }
05672
05673 cleanandgo:
05674 printf(";; cleanandgo \n");
05675 if (dns_name_dynamic(&chase_current_name))
05676 free_name(&chase_current_name, mctx);
05677 if (dns_name_dynamic(&chase_authority_name))
05678 free_name(&chase_authority_name, mctx);
05679 clean_trustedkey();
05680 return;
05681
05682 finalstep :
05683 result = advanced_rrsearch(&chase_rdataset, &chase_name,
05684 current_lookup->rdtype_sigchase,
05685 dns_rdatatype_any ,
05686 &true);
05687 if (result == ISC_R_FAILURE) {
05688 printf("\n;; RRsig of RRset is missing to continue validation"
05689 " SHOULD NOT APPEND: FAILED\n\n");
05690 goto cleanandgo;
05691 }
05692 result = sigchase_verify_sig(&chase_name, chase_rdataset,
05693 chase_keyrdataset,
05694 chase_sigrdataset, mctx);
05695 if (result != ISC_R_SUCCESS) {
05696 printf("\n;; Impossible to verify the RRset : FAILED\n\n");
05697
05698
05699
05700
05701
05702
05703
05704
05705
05706 goto cleanandgo;
05707 } else {
05708 printf("\n;; The Answer:\n");
05709 print_rdataset(&chase_name , chase_rdataset, mctx);
05710
05711 printf("\n;; FINISH : we have validate the DNSSEC chain"
05712 " of trust: SUCCESS\n\n");
05713 goto cleanandgo;
05714 }
05715 }
05716
05717 #endif
05718
05719
05720 #if DIG_SIGCHASE_BU
05721
05722 isc_result_t
05723 getneededrr(dns_message_t *msg)
05724 {
05725 isc_result_t result;
05726 dns_name_t *name = NULL;
05727 dns_rdata_t sigrdata = DNS_RDATA_INIT;
05728 dns_rdata_sig_t siginfo;
05729 isc_boolean_t true = ISC_TRUE;
05730
05731 if ((result = dns_message_firstname(msg, DNS_SECTION_ANSWER))
05732 != ISC_R_SUCCESS) {
05733 printf(";; NO ANSWERS: %s\n", isc_result_totext(result));
05734
05735 if (chase_name.ndata == NULL)
05736 return (ISC_R_ADDRNOTAVAIL);
05737 } else {
05738 dns_message_currentname(msg, DNS_SECTION_ANSWER, &name);
05739 }
05740
05741
05742 if (chase_rdataset == NULL) {
05743 result = advanced_rrsearch(&chase_rdataset, name,
05744 dns_rdatatype_any,
05745 dns_rdatatype_any, &true);
05746 if (result != ISC_R_SUCCESS) {
05747 printf("\n;; No Answers: Validation FAILED\n\n");
05748 return (ISC_R_NOTFOUND);
05749 }
05750 dup_name(name, &chase_name, mctx);
05751 printf(";; RRset to chase:\n");
05752 print_rdataset(&chase_name, chase_rdataset, mctx);
05753 }
05754 INSIST(chase_rdataset != NULL);
05755
05756
05757 if (chase_sigrdataset == NULL) {
05758 result = advanced_rrsearch(&chase_sigrdataset, name,
05759 dns_rdatatype_rrsig,
05760 chase_rdataset->type,
05761 &chase_siglookedup);
05762 if (result == ISC_R_FAILURE) {
05763 printf("\n;; RRSIG is missing for continue validation:"
05764 " FAILED\n\n");
05765 if (dns_name_dynamic(&chase_name))
05766 free_name(&chase_name, mctx);
05767 return (ISC_R_NOTFOUND);
05768 }
05769 if (result == ISC_R_NOTFOUND) {
05770 return (ISC_R_NOTFOUND);
05771 }
05772 printf("\n;; RRSIG of the RRset to chase:\n");
05773 print_rdataset(&chase_name, chase_sigrdataset, mctx);
05774 }
05775 INSIST(chase_sigrdataset != NULL);
05776
05777
05778
05779 result = dns_rdataset_first(chase_sigrdataset);
05780 check_result(result, "empty RRSIG dataset");
05781 dns_rdataset_current(chase_sigrdataset, &sigrdata);
05782 result = dns_rdata_tostruct(&sigrdata, &siginfo, NULL);
05783 check_result(result, "sigrdata tostruct siginfo");
05784 dup_name(&siginfo.signer, &chase_signame, mctx);
05785 dns_rdata_freestruct(&siginfo);
05786 dns_rdata_reset(&sigrdata);
05787
05788
05789 if (chase_keyrdataset == NULL) {
05790 result = advanced_rrsearch(&chase_keyrdataset,
05791 &chase_signame,
05792 dns_rdatatype_dnskey,
05793 dns_rdatatype_any,
05794 &chase_keylookedup);
05795 if (result == ISC_R_FAILURE) {
05796 printf("\n;; DNSKEY is missing to continue validation:"
05797 " FAILED\n\n");
05798 free_name(&chase_signame, mctx);
05799 if (dns_name_dynamic(&chase_name))
05800 free_name(&chase_name, mctx);
05801 return (ISC_R_NOTFOUND);
05802 }
05803 if (result == ISC_R_NOTFOUND) {
05804 free_name(&chase_signame, mctx);
05805 return (ISC_R_NOTFOUND);
05806 }
05807 printf("\n;; DNSKEYset that signs the RRset to chase:\n");
05808 print_rdataset(&chase_signame, chase_keyrdataset, mctx);
05809 }
05810 INSIST(chase_keyrdataset != NULL);
05811
05812 if (chase_sigkeyrdataset == NULL) {
05813 result = advanced_rrsearch(&chase_sigkeyrdataset,
05814 &chase_signame,
05815 dns_rdatatype_rrsig,
05816 dns_rdatatype_dnskey,
05817 &chase_sigkeylookedup);
05818 if (result == ISC_R_FAILURE) {
05819 printf("\n;; RRSIG for DNSKEY is missing to continue"
05820 " validation : FAILED\n\n");
05821 free_name(&chase_signame, mctx);
05822 if (dns_name_dynamic(&chase_name))
05823 free_name(&chase_name, mctx);
05824 return (ISC_R_NOTFOUND);
05825 }
05826 if (result == ISC_R_NOTFOUND) {
05827 free_name(&chase_signame, mctx);
05828 return (ISC_R_NOTFOUND);
05829 }
05830 printf("\n;; RRSIG of the DNSKEYset that signs the "
05831 "RRset to chase:\n");
05832 print_rdataset(&chase_signame, chase_sigkeyrdataset, mctx);
05833 }
05834 INSIST(chase_sigkeyrdataset != NULL);
05835
05836
05837 if (chase_dsrdataset == NULL) {
05838 result = advanced_rrsearch(&chase_dsrdataset, &chase_signame,
05839 dns_rdatatype_ds, dns_rdatatype_any,
05840 &chase_dslookedup);
05841 if (result == ISC_R_FAILURE) {
05842 printf("\n;; WARNING There is no DS for the zone: ");
05843 dns_name_print(&chase_signame, stdout);
05844 printf("\n");
05845 }
05846 if (result == ISC_R_NOTFOUND) {
05847 free_name(&chase_signame, mctx);
05848 return (ISC_R_NOTFOUND);
05849 }
05850 if (chase_dsrdataset != NULL) {
05851 printf("\n;; DSset of the DNSKEYset\n");
05852 print_rdataset(&chase_signame, chase_dsrdataset, mctx);
05853 }
05854 }
05855
05856 if (chase_dsrdataset != NULL) {
05857
05858
05859
05860
05861 result = advanced_rrsearch(&chase_sigdsrdataset,
05862 &chase_signame,
05863 dns_rdatatype_rrsig,
05864 dns_rdatatype_ds, &true);
05865 if (result == ISC_R_FAILURE) {
05866 printf(";; WARNING : NO RRSIG DS : RRSIG DS"
05867 " should come with DS\n");
05868
05869
05870
05871
05872 chase_dsrdataset = NULL;
05873 } else {
05874 printf("\n;; RRSIG of the DSset of the DNSKEYset\n");
05875 print_rdataset(&chase_signame, chase_sigdsrdataset,
05876 mctx);
05877 }
05878 }
05879 return (1);
05880 }
05881
05882
05883
05884 void
05885 sigchase_bu(dns_message_t *msg)
05886 {
05887 isc_result_t result;
05888 int ret;
05889
05890 if (tk_list.nb_tk == 0) {
05891 result = get_trusted_key(mctx);
05892 if (result != ISC_R_SUCCESS) {
05893 printf("No trusted keys present\n");
05894 return;
05895 }
05896 }
05897
05898
05899 ret = getneededrr(msg);
05900 if (ret == ISC_R_NOTFOUND)
05901 return;
05902
05903 if (ret == ISC_R_ADDRNOTAVAIL) {
05904
05905 dns_rdataset_t *rdataset;
05906 dns_rdataset_t *sigrdataset;
05907 dns_name_t rdata_name;
05908 dns_name_t query_name;
05909
05910
05911 dns_name_init(&query_name, NULL);
05912 dns_name_init(&rdata_name, NULL);
05913 nameFromString(current_lookup->textname, &query_name);
05914
05915 result = prove_nx(msg, &query_name, current_lookup->rdclass,
05916 current_lookup->rdtype, &rdata_name,
05917 &rdataset, &sigrdataset);
05918 free_name(&query_name, mctx);
05919 if (rdataset == NULL || sigrdataset == NULL ||
05920 dns_name_countlabels(&rdata_name) == 0) {
05921 printf("\n;; Impossible to verify the Non-existence,"
05922 " the NSEC RRset can't be validated: "
05923 "FAILED\n\n");
05924 clean_trustedkey();
05925 return;
05926 }
05927
05928 if (result != ISC_R_SUCCESS) {
05929 printf("\n No Answers and impossible to prove the"
05930 " unsecurity : Validation FAILED\n\n");
05931 clean_trustedkey();
05932 return;
05933 }
05934 printf(";; An NSEC prove the non-existence of a answers,"
05935 " Now we want validate this NSEC\n");
05936
05937 dup_name(&rdata_name, &chase_name, mctx);
05938 free_name(&rdata_name, mctx);
05939 chase_rdataset = rdataset;
05940 chase_sigrdataset = sigrdataset;
05941 chase_keyrdataset = NULL;
05942 chase_sigkeyrdataset = NULL;
05943 chase_dsrdataset = NULL;
05944 chase_sigdsrdataset = NULL;
05945 chase_siglookedup = ISC_FALSE;
05946 chase_keylookedup = ISC_FALSE;
05947 chase_dslookedup = ISC_FALSE;
05948 chase_sigdslookedup = ISC_FALSE;
05949 sigchase(msg);
05950 clean_trustedkey();
05951 return;
05952 }
05953
05954
05955 printf("\n\n\n;; WE HAVE MATERIAL, WE NOW DO VALIDATION\n");
05956
05957 result = sigchase_verify_sig(&chase_name, chase_rdataset,
05958 chase_keyrdataset,
05959 chase_sigrdataset, mctx);
05960 if (result != ISC_R_SUCCESS) {
05961 free_name(&chase_name, mctx);
05962 free_name(&chase_signame, mctx);
05963 printf(";; No DNSKEY is valid to check the RRSIG"
05964 " of the RRset: FAILED\n");
05965 clean_trustedkey();
05966 return;
05967 }
05968 printf(";; OK We found DNSKEY (or more) to validate the RRset\n");
05969
05970 result = contains_trusted_key(&chase_signame, chase_keyrdataset,
05971 chase_sigkeyrdataset, mctx);
05972 if (result == ISC_R_SUCCESS) {
05973 free_name(&chase_name, mctx);
05974 free_name(&chase_signame, mctx);
05975 printf("\n;; Ok this DNSKEY is a Trusted Key,"
05976 " DNSSEC validation is ok: SUCCESS\n\n");
05977 clean_trustedkey();
05978 return;
05979 }
05980
05981 printf(";; Now, we are going to validate this DNSKEY by the DS\n");
05982
05983 if (chase_dsrdataset == NULL) {
05984 free_name(&chase_name, mctx);
05985 free_name(&chase_signame, mctx);
05986 printf(";; the DNSKEY isn't trusted-key and there isn't"
05987 " DS to validate the DNSKEY: FAILED\n");
05988 clean_trustedkey();
05989 return;
05990 }
05991
05992 result = sigchase_verify_ds(&chase_signame, chase_keyrdataset,
05993 chase_dsrdataset, mctx);
05994 if (result != ISC_R_SUCCESS) {
05995 free_name(&chase_signame, mctx);
05996 free_name(&chase_name, mctx);
05997 printf(";; ERROR no DS validates a DNSKEY in the"
05998 " DNSKEY RRset: FAILED\n");
05999 clean_trustedkey();
06000 return;
06001 } else
06002 printf(";; OK this DNSKEY (validated by the DS) validates"
06003 " the RRset of the DNSKEYs, thus the DNSKEY validates"
06004 " the RRset\n");
06005 INSIST(chase_sigdsrdataset != NULL);
06006
06007 dup_name(&chase_signame, &chase_name, mctx);
06008 free_name(&chase_signame, mctx);
06009 chase_rdataset = chase_dsrdataset;
06010 chase_sigrdataset = chase_sigdsrdataset;
06011 chase_keyrdataset = NULL;
06012 chase_sigkeyrdataset = NULL;
06013 chase_dsrdataset = NULL;
06014 chase_sigdsrdataset = NULL;
06015 chase_siglookedup = chase_keylookedup = ISC_FALSE;
06016 chase_dslookedup = chase_sigdslookedup = ISC_FALSE;
06017
06018 printf(";; Now, we want to validate the DS : recursive call\n");
06019 sigchase(msg);
06020 return;
06021 }
06022 #endif
06023
06024 void
06025 sigchase(dns_message_t *msg) {
06026 #if DIG_SIGCHASE_TD
06027 if (current_lookup->do_topdown) {
06028 sigchase_td(msg);
06029 return;
06030 }
06031 #endif
06032 #if DIG_SIGCHASE_BU
06033 sigchase_bu(msg);
06034 return;
06035 #endif
06036 }
06037
06038
06039
06040
06041
06042
06043
06044
06045 int
06046 inf_name(dns_name_t *name1, dns_name_t *name2)
06047 {
06048 dns_label_t label1;
06049 dns_label_t label2;
06050 unsigned int nblabel1;
06051 unsigned int nblabel2;
06052 int min_lum_label;
06053 int i;
06054 int ret = -2;
06055
06056 nblabel1 = dns_name_countlabels(name1);
06057 nblabel2 = dns_name_countlabels(name2);
06058
06059 if (nblabel1 >= nblabel2)
06060 min_lum_label = nblabel2;
06061 else
06062 min_lum_label = nblabel1;
06063
06064
06065 for (i=1 ; i < min_lum_label; i++) {
06066 dns_name_getlabel(name1, nblabel1 -1 - i, &label1);
06067 dns_name_getlabel(name2, nblabel2 -1 - i, &label2);
06068 if ((ret = isc_region_compare(&label1, &label2)) != 0) {
06069 if (ret < 0)
06070 return (-1);
06071 else if (ret > 0)
06072 return (1);
06073 }
06074 }
06075 if (nblabel1 == nblabel2)
06076 return (0);
06077
06078 if (nblabel1 < nblabel2)
06079 return (-1);
06080 else
06081 return (1);
06082 }
06083
06084
06085
06086
06087
06088
06089 isc_result_t
06090 prove_nx_domain(dns_message_t *msg,
06091 dns_name_t *name,
06092 dns_name_t *rdata_name,
06093 dns_rdataset_t **rdataset,
06094 dns_rdataset_t **sigrdataset)
06095 {
06096 isc_result_t ret = ISC_R_FAILURE;
06097 isc_result_t result = ISC_R_NOTFOUND;
06098 dns_rdataset_t *nsecset = NULL;
06099 dns_rdataset_t *signsecset = NULL ;
06100 dns_rdata_t nsec = DNS_RDATA_INIT;
06101 dns_name_t *nsecname;
06102 dns_rdata_nsec_t nsecstruct;
06103
06104 if ((result = dns_message_firstname(msg, DNS_SECTION_AUTHORITY))
06105 != ISC_R_SUCCESS) {
06106 printf(";; nothing in authority section : impossible to"
06107 " validate the non-existence : FAILED\n");
06108 return (ISC_R_FAILURE);
06109 }
06110
06111 do {
06112 nsecname = NULL;
06113 dns_message_currentname(msg, DNS_SECTION_AUTHORITY, &nsecname);
06114 nsecset = search_type(nsecname, dns_rdatatype_nsec,
06115 dns_rdatatype_any);
06116 if (nsecset == NULL)
06117 continue;
06118
06119 printf("There is a NSEC for this zone in the"
06120 " AUTHORITY section:\n");
06121 print_rdataset(nsecname, nsecset, mctx);
06122
06123 for (result = dns_rdataset_first(nsecset);
06124 result == ISC_R_SUCCESS;
06125 result = dns_rdataset_next(nsecset)) {
06126 dns_rdataset_current(nsecset, &nsec);
06127
06128 signsecset
06129 = chase_scanname_section(msg, nsecname,
06130 dns_rdatatype_rrsig,
06131 dns_rdatatype_nsec,
06132 DNS_SECTION_AUTHORITY);
06133 if (signsecset == NULL) {
06134 printf(";; no RRSIG NSEC in authority section:"
06135 " impossible to validate the "
06136 "non-existence: FAILED\n");
06137 return (ISC_R_FAILURE);
06138 }
06139
06140 ret = dns_rdata_tostruct(&nsec, &nsecstruct, NULL);
06141 check_result(ret,"dns_rdata_tostruct");
06142
06143 if ((inf_name(nsecname, &nsecstruct.next) == 1 &&
06144 inf_name(name, &nsecstruct.next) == 1) ||
06145 (inf_name(name, nsecname) == 1 &&
06146 inf_name(&nsecstruct.next, name) == 1)) {
06147 dns_rdata_freestruct(&nsecstruct);
06148 *rdataset = nsecset;
06149 *sigrdataset = signsecset;
06150 dup_name(nsecname, rdata_name, mctx);
06151
06152 return (ISC_R_SUCCESS);
06153 }
06154
06155 dns_rdata_freestruct(&nsecstruct);
06156 dns_rdata_reset(&nsec);
06157 }
06158 } while (dns_message_nextname(msg, DNS_SECTION_AUTHORITY)
06159 == ISC_R_SUCCESS);
06160
06161 *rdataset = NULL;
06162 *sigrdataset = NULL;
06163 rdata_name = NULL;
06164 return (ISC_R_FAILURE);
06165 }
06166
06167
06168
06169
06170
06171
06172
06173
06174 isc_result_t
06175 prove_nx_type(dns_message_t *msg, dns_name_t *name, dns_rdataset_t *nsecset,
06176 dns_rdataclass_t class, dns_rdatatype_t type,
06177 dns_name_t *rdata_name, dns_rdataset_t **rdataset,
06178 dns_rdataset_t **sigrdataset)
06179 {
06180 isc_result_t ret;
06181 dns_rdataset_t *signsecset;
06182 dns_rdata_t nsec = DNS_RDATA_INIT;
06183
06184 UNUSED(class);
06185
06186 ret = dns_rdataset_first(nsecset);
06187 check_result(ret,"dns_rdataset_first");
06188
06189 dns_rdataset_current(nsecset, &nsec);
06190
06191 ret = dns_nsec_typepresent(&nsec, type);
06192 if (ret == ISC_R_SUCCESS)
06193 printf("OK the NSEC said that the type doesn't exist \n");
06194
06195 signsecset = chase_scanname_section(msg, name,
06196 dns_rdatatype_rrsig,
06197 dns_rdatatype_nsec,
06198 DNS_SECTION_AUTHORITY);
06199 if (signsecset == NULL) {
06200 printf("There isn't RRSIG NSEC for the zone \n");
06201 return (ISC_R_FAILURE);
06202 }
06203 dup_name(name, rdata_name, mctx);
06204 *rdataset = nsecset;
06205 *sigrdataset = signsecset;
06206
06207 return (ret);
06208 }
06209
06210
06211
06212
06213
06214
06215
06216 isc_result_t
06217 prove_nx(dns_message_t *msg, dns_name_t *name, dns_rdataclass_t class,
06218 dns_rdatatype_t type, dns_name_t *rdata_name,
06219 dns_rdataset_t **rdataset, dns_rdataset_t **sigrdataset)
06220 {
06221 isc_result_t ret;
06222 dns_rdataset_t *nsecset = NULL;
06223
06224 printf("We want to prove the non-existence of a type of rdata %d"
06225 " or of the zone: \n", type);
06226
06227 if ((ret = dns_message_firstname(msg, DNS_SECTION_AUTHORITY))
06228 != ISC_R_SUCCESS) {
06229 printf(";; nothing in authority section : impossible to"
06230 " validate the non-existence : FAILED\n");
06231 return (ISC_R_FAILURE);
06232 }
06233
06234 nsecset = chase_scanname_section(msg, name, dns_rdatatype_nsec,
06235 dns_rdatatype_any,
06236 DNS_SECTION_AUTHORITY);
06237 if (nsecset != NULL) {
06238 printf("We have a NSEC for this zone :OK\n");
06239 ret = prove_nx_type(msg, name, nsecset, class,
06240 type, rdata_name, rdataset,
06241 sigrdataset);
06242 if (ret != ISC_R_SUCCESS) {
06243 printf("prove_nx: ERROR type exist\n");
06244 return (ret);
06245 } else {
06246 printf("prove_nx: OK type does not exist\n");
06247 return (ISC_R_SUCCESS);
06248 }
06249 } else {
06250 printf("there is no NSEC for this zone: validating "
06251 "that the zone doesn't exist\n");
06252 ret = prove_nx_domain(msg, name, rdata_name,
06253 rdataset, sigrdataset);
06254 return (ret);
06255 }
06256
06257 }
06258 #endif