dighost.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2004-2015  Internet Systems Consortium, Inc. ("ISC")
00003  * Copyright (C) 2000-2003  Internet Software Consortium.
00004  *
00005  * Permission to use, copy, modify, and/or distribute this software for any
00006  * purpose with or without fee is hereby granted, provided that the above
00007  * copyright notice and this permission notice appear in all copies.
00008  *
00009  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
00010  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
00011  * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
00012  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
00013  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
00014  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
00015  * PERFORMANCE OF THIS SOFTWARE.
00016  */
00017 
00018 /*! \file
00019  *  \note
00020  * Notice to programmers:  Do not use this code as an example of how to
00021  * use the ISC library to perform DNS lookups.  Dig and Host both operate
00022  * on the request level, since they allow fine-tuning of output and are
00023  * intended as debugging tools.  As a result, they perform many of the
00024  * functions which could be better handled using the dns_resolver
00025  * functions in most applications.
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  * Exit Codes:
00174  *
00175  *\li   0   Everything went well, including things like NXDOMAIN
00176  *\li   1   Usage error
00177  *\li   7   Got too many RR's or Names
00178  *\li   8   Couldn't open batch file
00179  *\li   9   No reply from server
00180  *\li   10  Internal error
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; /* the query name */
00300 #if DIG_SIGCHASE_TD
00301 /*
00302  * the current name is the parent name when we follow delegation
00303  */
00304 dns_name_t chase_current_name;
00305 /*
00306  * the child name is used for delegation (NS DS responses in AUTHORITY section)
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  * Apply and clear locks at the event level in global task.
00353  * Can I get rid of these using shutdown events?  XXX
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  * Append 'len' bytes of 'text' at '*p', failing with
00460  * ISC_R_NOSPACE if that would advance p past 'end'.
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                 /* This is a valid IPv6 address. */
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                  * Not a valid IPv6 address.  Assume IPv4.
00518                  * If 'strict' is not set, construct the
00519                  * in-addr.arpa name by blindly reversing
00520                  * octets whether or not they look like integers,
00521                  * so that this can be used for RFC2317 names
00522                  * and such.
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                 /* Append .in-addr.arpa. and a terminating NUL. */
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  * Create a server structure, which is part of the lookup structure.
00584  * This is little more than a linked list of servers to query in hopes
00585  * of finding the answer the user is looking for
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  * Create a copy of the server list from the lwres configuration structure.
00624  * The dest list must have already had ISC_LIST_INIT applied.
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  * Produce a cloned server list.  The dest list must have already had
00731  * ISC_LIST_INIT applied.
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  * Create an empty lookup structure, which holds all the information needed
00749  * to get an answer to a user's question.  This structure contains two
00750  * linked lists: the server list (servers to query) and the query list
00751  * (outstanding queries which have been made to the listed servers).
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  * Clone a lookup, perhaps copying the server list.  This does not clone
00852  * the query list, since it will be regenerated by the setup_lookup()
00853  * function, nor does it queue up the new lookup for processing.
00854  * Caution: If you don't clone the servers, you MUST clone the server
00855  * list separately from somewhere else, or construct it by hand.
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  * Requeue a lookup for further processing, perhaps copying the server
00952  * list.  The new lookup structure is returned to the caller, and is
00953  * queued for processing.  If servers are not cloned in the requeue, they
00954  * must be added before allowing the current event to complete, since the
00955  * completion of the event may result in the next entry on the lookup
00956  * queue getting run.
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  * Parse HMAC algorithm specification
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  * Get a key from a named.conf format keyfile
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         /* Try reading the key from a K* pair */
01249         result = dst_key_fromnamedfile(keyfile, NULL,
01250                                        DST_TYPE_PRIVATE | DST_TYPE_KEY, mctx,
01251                                        &dstkey);
01252 
01253         /* If that didn't work, try reading it as a session.key keyfile */
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  * Setup the system as a whole, reading key information and resolv.conf
01341  * settings.
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         /* Make the search list */
01370         if (lwconf->searchnxt > 0)
01371                 create_search_list(lwconf);
01372         else { /* No search list. Use the domain name if any */
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         /* If user doesn't specify server use nameservers from resolv.conf. */
01400         if (ISC_LIST_EMPTY(server_list))
01401                 copy_server_list(lwconf, &server_list);
01402 
01403         /* If we don't find a nameserver fall back to localhost */
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         /* Setup the list of messages for +sigchase */
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  * Override the search list derived from resolv.conf by 'domain'.
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  * Setup the ISC and DNS libraries for use by the system.
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          * 6 and 2 set as reasonable parameters for 3 or 4 nameserver
01525          * systems.
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  * Add EDNS0 option record to a message.  Currently, the only supported
01575  * options are UDP buffer size, the DO bit, and EDNS options
01576  * (e.g., NSID, SIT, client-subnet)
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  * Add a question section to a message, asking for the specified name,
01595  * type, and class.
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  * Check if we're done with all the queued lookups, which is true iff
01615  * all sockets, sends, and recvs are accounted for (counters == 0),
01616  * and the lookup list is empty.
01617  * If we are done, pass control back out to dighost_shutdown() (which is
01618  * part of dig.c, host.c, or nslookup.c) to either shutdown the system as
01619  * a whole or reseed the lookup list.
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  * Clear out a query when we're done with it.  WARNING: This routine
01636  * WILL invalidate the query pointer.
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  * Try and clear out a lookup if we're done with it.  Return ISC_TRUE if
01679  * the lookup was successfully cleared.  If ISC_TRUE is returned, the
01680  * lookup pointer has been invalidated.
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          * At this point, we know there are no queries on the lookup,
01712          * so can make it go away also.
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  * If we can, start the next lookup in the queue running.
01755  * This assumes that the lookup on the head of the queue hasn't been
01756  * started yet.  It also removes the lookup from the head of the queue,
01757  * setting the current_lookup pointer pointing to it.
01758  */
01759 void
01760 start_lookup(void) {
01761         debug("start_lookup()");
01762         if (cancel_now)
01763                 return;
01764 
01765         /*
01766          * If there's a current lookup running, we really shouldn't get
01767          * here.
01768          */
01769         INSIST(current_lookup == NULL);
01770 
01771         current_lookup = ISC_LIST_HEAD(lookup_list);
01772         /*
01773          * Put the current lookup somewhere so cancel_all can find it
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                                  * Verify temp is really the lowest
01806                                  * WARNING
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  * If we can, clear the current lookup and start the next one running.
01870  * This calls try_clear_lookup, so may invalidate the lookup pointer.
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  * Create and queue a new lookup as a followup to the current lookup,
01891  * based on the supplied message and section.  This is used in trace and
01892  * name server search modes to start a new lookup using servers from
01893  * NS records in a reply. Returns the number of followup lookups made.
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                         /* Initialize lookup if we've not yet */
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          * Randomize the order the nameserver will be tried.
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  * Create and queue a new lookup using the next origin from the search
02058  * list, read in setup_system().
02059  *
02060  * Return ISC_TRUE iff there was another searchlist entry.
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                  * We're not using a search list, so don't even think
02078                  * about finding the next entry.
02079                  */
02080                 return (ISC_FALSE);
02081 
02082         /*
02083          * Check for a absolute name or ndots being met.
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                  * Then we just did rootorg; there's nothing left.
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  * Insert an SOA record into the sendmessage in a lookup.  Used for
02116  * creating IXFR queries.
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         /* XXXMPA need to fix, should be per server. */
02181         INSIST(len >= 8U);
02182         memmove(clientcookie, cookie_secret, 8);
02183 }
02184 #endif
02185 
02186 /*%
02187  * Setup the supplied lookup structure, making it ready to start sending
02188  * queries to servers.  Create and initialize the message to be sent as
02189  * well as the query structures and buffer space for the replies.  If the
02190  * server list is empty, clone it from the system default list.
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          * We cannot convert `textname' and `origin' separately.
02246          * `textname' doesn't contain TLD, but local mapping needs
02247          * TLD.
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          * If the name has too many dots, force the origin to be NULL
02256          * (which produces an absolute lookup).  Otherwise, take the origin
02257          * we have if there's one in the struct already.  If it's NULL,
02258          * take the first entry in the searchlist iff either usesearch
02259          * is TRUE or we got a domain line in the resolv.conf file.
02260          */
02261         if (lookup->new_search) {
02262 #ifdef WITH_IDN
02263                 if ((count_dots(utf8_textname) >= ndots) || !usesearch) {
02264                         lookup->origin = NULL; /* Force abs lookup */
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; /* Force abs lookup */
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                 /* XXX Helper funct to conv char* to name? */
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          * If this is a trace request, completely disallow recursion, since
02394          * it's meaningless for traces.
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         /* XXX aaflag */
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                  * Force TCP mode if we're doing an axfr.
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         /* add_soa */
02453         if (lookup->rdtype == dns_rdatatype_ixfr)
02454                 insert_soa(lookup);
02455 
02456         /* XXX Insist this? */
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                         /* Round up prefix len to a multiple of 8 */
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          * Force TCP mode if the request is larger than 512 bytes.
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         /* XXX qrflag, print_query, etc... */
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  * Event handler for send completion.  Track send counter, and clear out
02657  * the query if the send was canceled.
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  * Cancel a lookup, sending isc_socket_cancel() requests to all outstanding
02706  * IO sockets.  The cancel handlers should take care of cleaning up the
02707  * query and lookup structures
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          * If the timer already exists, that means we're calling this
02741          * a second time (for a retry).  Don't need to recreate it,
02742          * just reset it.
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          * The timer may have expired if, for example, get_address() takes
02779          * long time and the timer was running on a different thread.
02780          * We need to cancel the possible timeout event not to confuse
02781          * ourselves due to the duplicate events.
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  * Unlike send_udp, this can't be called multiple times with the same
02793  * query.  When we retry TCP, we requeue the whole lookup, which should
02794  * start anew.
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                  * This servname doesn't have an address.  Try the next server
02811                  * by triggering an immediate 'timeout' (we lie, but the effect
02812                  * is the same).
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          * If we're at the endgame of a nameserver search, we need to
02873          * immediately bring up all the queries.  Do it here.
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  * Send a UDP packet to the remote nameserver, possible starting the
02899  * recv action as well.  Also make sure that the timer is running and
02900  * is properly reset.
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                 /* XXX Check the sense of this, need assertion? */
02916                 query->waiting_connect = ISC_FALSE;
02917                 result = get_address(query->servname, port, &query->sockaddr);
02918                 if (result != ISC_R_SUCCESS) {
02919                         /* This servname doesn't have an address. */
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  * IO timeout handler, used for both connect and recv timeouts.  If
02971  * retries are still allowed, either resend the UDP packet or queue a
02972  * new TCP lookup.  Otherwise, cancel the lookup.
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  * Event handler for the TCP recv which gets the length header of TCP
03036  * packets.  Start the next recv of length bytes.
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          * Even though the buffer was already init'ed, we need
03100          * to redo it now, to force the length we want.
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  * For transfers that involve multiple recvs (XFR's in particular),
03120  * launch the next recv.
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  * Event handler for TCP connect complete.  Make sure the connection was
03186  * successful, then pass into launch_next_query to actually send the
03187  * question.
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                 /* XXX Clean up exitcodes */
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  * Check if the ongoing XFR needs more data before it's complete, using
03272  * the semantics of IXFR and AXFR protocols.  Much of the complexity of
03273  * this routine comes from determining when an IXFR is complete.
03274  * ISC_FALSE means more data is on the way, and the recv has been issued.
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          * By the time we're in this routine, we know we're doing
03295          * either an AXFR or IXFR.  If there's no second_rr_type,
03296          * then we don't yet know which kind of answer we got back
03297          * from the server.  Here, we're going to walk through the
03298          * rr's in the message, acting as necessary whenever we hit
03299          * an SOA rr.
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                                  * If this is the first rr, make sure
03326                                  * it's an SOA
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                                  * If the record is anything except an SOA
03345                                  * now, just continue on...
03346                                  */
03347                                 if (rdata.type != dns_rdatatype_soa)
03348                                         goto next_rdata;
03349 
03350                                 /* Now we have an SOA.  Work with it. */
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                                  * If we get to this point, we're doing an
03387                                  * IXFR and have to start really looking
03388                                  * at serial numbers.
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  * Event handler for recv complete.  Perform whatever actions are necessary,
03506  * based on the specifics of the user's request.
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                 * We don't expect a match when the packet is
03607                 * sent to 0.0.0.0, :: or to a multicast addresses.
03608                 * XXXMPA broadcast needs to be handled here as well.
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                  * Add minimum EDNS version required checks here if needed.
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                  * If our query is at the head of the list and there
03817                  * is no next, we're the only one left, so fall
03818                  * through to print the message.
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                  * Once we are in the XFR message, increase
03862                  * the timeout to much longer, so brief network
03863                  * outages won't cause the XFR to abort
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                                  * This is the initial NS query.
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  * Turn a name into an address, using system-supplied routines.  This is
04070  * used in looking up server names, etc... and needs to use system-supplied
04071  * routines, since they may be using a non-DNS system for these lookups.
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  * Initiate either a TCP or UDP lookup
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  * Start everything in action upon task startup.
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  * Make everything on the lookup queue go away.  Mainly used by the
04158  * SIGINT handler.
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(&current_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  * Destroy all of the libs we are using, and get everything ready for a
04215  * clean shutdown.
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          * The taskmgr_destroy() call blocks until all events are cleared
04236          * from the task.
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         /* Destroy the messages kept for sigchase */
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         /* Set locale */
04358         (void)setlocale(LC_ALL, "");
04359 #endif
04360         /* Create configuration context. */
04361         r = idn_nameinit(1);
04362         if (r != idn_success)
04363                 fatal("idn api initialization failed: %s",
04364                       idn_result_tostring(r));
04365 
04366         /* Set domain name -> text post-conversion filter. */
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          * Copy contents of 'buffer' to 'tmp1', supply trailing dot
04381          * if 'absolute' is true, and terminate with NUL.
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          * Convert contents of 'tmp1' to local encoding.
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          * Copy the converted contents in 'tmp1' back to 'buffer'.
04405          * If we have appended trailing dot, remove it.
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         /* Already absolute? */
04427         if (namelen > 0 && name[namelen - 1] == '.')
04428                 return idn_success;
04429 
04430         /* Append dot and origin */
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 /* WITH_IDN */
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  * take a DNSKEY RRset and the RRSIG RRset corresponding in parameter
05063  * return ISC_R_SUCCESS if the DNSKEY RRset contains a trusted_key
05064  *                      and the RRset is valid
05065  * return ISC_R_NOTFOUND if not contains trusted key
05066                         or if the RRset isn't valid
05067  * return ISC_R_FAILURE if problem
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                  * Test if the id of the DNSKEY is
05197                  * the id of the DNSKEY signer's
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                          * Test if the id of the DNSKEY is the
05270                          * id of DNSKEY referenced by the DS
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  * take a pointer on a rdataset in parameter and try to resolv it.
05325  * the searched rrset is a rrset on 'name' with type 'type'
05326  * (and if the type is a rrsig the signature cover 'covers').
05327  * the lookedup is to known if you have already done the query on the net.
05328  * ISC_R_SUCCESS: if we found the rrset
05329  * ISC_R_NOTFOUND: we do not found the rrset in cache
05330  * and we do a query on the net
05331  * ISC_R_FAILURE: rrset not found
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                 /* test if it's a grand father case */
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                   printf("RRset:\n");
05699                   print_rdataset(&chase_name , chase_rdataset, mctx);
05700                   printf("DNSKEYset:\n");
05701                   print_rdataset(&chase_name , chase_keyrdataset, mctx);
05702                   printf("RRSIG of RRset:\n");
05703                   print_rdataset(&chase_name , chase_sigrdataset, mctx);
05704                   printf("\n");
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         /* What do we chase? */
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         /* first find the DNSKEY name */
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         /* Do we have a key?  */
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                  * if there is no RRSIG of DS,
05859                  * we don't want to search on the network
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                          * We continue even the DS couldn't be validated,
05870                          * because the DNSKEY could be a Trusted Key.
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                 /* We have no response */
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  * return 1  if name1  <  name2
06041  *        0  if name1  == name2
06042  *        -1 if name1  >  name2
06043  *    and -2 if problem
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         /* Never get here */
06257 }
06258 #endif

Generated on Tue Apr 28 17:40:53 2015 by Doxygen 1.5.4 for BIND9 Internals 9.11.0pre-alpha