[BACK]Return to dighost.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / dig

Annotation of src/usr.bin/dig/dighost.c, Revision 1.33

1.1       florian     1: /*
                      2:  * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
                      3:  *
                      4:  * Permission to use, copy, modify, and/or distribute this software for any
                      5:  * purpose with or without fee is hereby granted, provided that the above
                      6:  * copyright notice and this permission notice appear in all copies.
                      7:  *
                      8:  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
                      9:  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
                     10:  * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
                     11:  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
                     12:  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
                     13:  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
                     14:  * PERFORMANCE OF THIS SOFTWARE.
                     15:  */
                     16:
1.33    ! florian    17: /* $Id: dighost.c,v 1.32 2020/09/15 08:19:29 florian Exp $ */
1.1       florian    18:
                     19: /*! \file
                     20:  *  \note
                     21:  * Notice to programmers:  Do not use this code as an example of how to
                     22:  * use the ISC library to perform DNS lookups.  Dig and Host both operate
                     23:  * on the request level, since they allow fine-tuning of output and are
                     24:  * intended as debugging tools.  As a result, they perform many of the
                     25:  * functions which could be better handled using the dns_resolver
                     26:  * functions in most applications.
                     27:  */
                     28:
                     29: #include <sys/socket.h>
1.27      florian    30: #include <sys/time.h>
1.1       florian    31: #include <limits.h>
                     32: #include <locale.h>
                     33: #include <netdb.h>
1.6       florian    34: #include <resolv.h>
1.1       florian    35: #include <stdlib.h>
                     36: #include <string.h>
1.18      jsg        37: #include <time.h>
                     38: #include <stdint.h>
1.1       florian    39:
                     40: #include <dns/fixedname.h>
                     41: #include <dns/log.h>
                     42: #include <dns/message.h>
                     43: #include <dns/name.h>
                     44: #include <dns/rdata.h>
                     45: #include <dns/rdataclass.h>
                     46: #include <dns/rdatalist.h>
                     47: #include <dns/rdataset.h>
                     48: #include <dns/rdatatype.h>
                     49: #include <dns/result.h>
                     50: #include <dns/tsig.h>
                     51:
                     52: #include <dst/dst.h>
                     53: #include <dst/result.h>
                     54:
                     55: #include <isc/base64.h>
                     56: #include <isc/hex.h>
                     57: #include <isc/log.h>
                     58: #include <isc/result.h>
                     59: #include <isc/serial.h>
                     60: #include <isc/sockaddr.h>
                     61: #include <isc/task.h>
                     62: #include <isc/timer.h>
                     63: #include <isc/types.h>
                     64: #include <isc/util.h>
                     65:
                     66: #include <isccfg/namedconf.h>
                     67: #include <lwres/lwres.h>
                     68:
                     69: #include "dig.h"
                     70:
                     71: static lwres_conf_t  lwconfdata;
                     72: static lwres_conf_t *lwconf = &lwconfdata;
                     73:
                     74: dig_lookuplist_t lookup_list;
                     75: dig_serverlist_t server_list;
1.5       florian    76: dig_serverlist_t root_hints_server_list;
1.1       florian    77: dig_searchlistlist_t search_list;
                     78:
1.29      florian    79: int
                     80:        check_ra = 0,
                     81:        have_ipv4 = 1,
                     82:        have_ipv6 = 1,
                     83:        specified_source = 0,
                     84:        free_now = 0,
                     85:        cancel_now = 0,
                     86:        usesearch = 0,
                     87:        showsearch = 0,
                     88:        qr = 0,
                     89:        is_dst_up = 0,
                     90:        keep_open = 0;
1.1       florian    91: in_port_t port = 53;
                     92: unsigned int timeout = 0;
                     93: unsigned int extrabytes;
                     94: isc_log_t *lctx = NULL;
                     95: isc_taskmgr_t *taskmgr = NULL;
                     96: isc_task_t *global_task = NULL;
                     97: isc_timermgr_t *timermgr = NULL;
                     98: isc_socketmgr_t *socketmgr = NULL;
                     99: isc_sockaddr_t bind_address;
                    100: isc_sockaddr_t bind_any;
                    101: int sendcount = 0;
                    102: int recvcount = 0;
                    103: int sockcount = 0;
                    104: int ndots = -1;
                    105: int tries = 3;
                    106: int lookup_counter = 0;
                    107:
                    108: static char sitvalue[256];
                    109:
                    110: isc_socket_t *keep = NULL;
                    111: isc_sockaddr_t keepaddr;
                    112:
1.5       florian   113: static const struct {
                    114:        const char *ns;
                    115:        const int af;
                    116: } root_hints[] = {
                    117:        { "198.41.0.4", AF_INET },              /*  a.root-servers.net  */
                    118:        { "2001:503:ba3e::2:30", AF_INET6 },    /*  a.root-servers.net  */
                    119:        { "199.9.14.201", AF_INET },            /*  b.root-servers.net  */
                    120:        { "2001:500:200::b", AF_INET6 },        /*  b.root-servers.net  */
                    121:        { "192.33.4.12", AF_INET },             /*  c.root-servers.net  */
                    122:        { "2001:500:2::c", AF_INET6 },          /*  c.root-servers.net  */
                    123:        { "199.7.91.13", AF_INET },             /*  d.root-servers.net  */
                    124:        { "2001:500:2d::d", AF_INET6 },         /*  d.root-servers.net  */
                    125:        { "192.203.230.10", AF_INET },          /*  e.root-servers.net  */
                    126:        { "2001:500:a8::e", AF_INET6 },         /*  e.root-servers.net  */
                    127:        { "192.5.5.241", AF_INET },             /*  f.root-servers.net  */
                    128:        { "2001:500:2f::f", AF_INET6 },         /*  f.root-servers.net  */
                    129:        { "192.112.36.4", AF_INET },            /*  g.root-servers.net  */
                    130:        { "2001:500:12::d0d", AF_INET6 },       /*  g.root-servers.net  */
                    131:        { "198.97.190.53", AF_INET },           /*  h.root-servers.net  */
                    132:        { "2001:500:1::53", AF_INET6 },         /*  h.root-servers.net */
                    133:        { "192.36.148.17", AF_INET },           /*  i.root-servers.net  */
                    134:        { "2001:7fe::53", AF_INET6 },           /*  i.root-servers.net  */
                    135:        { "192.58.128.30", AF_INET },           /*  j.root-servers.net  */
                    136:        { "2001:503:c27::2:30", AF_INET6 },     /*  j.root-servers.net  */
                    137:        { "193.0.14.129", AF_INET },            /*  k.root-servers.net  */
                    138:        { "2001:7fd::1", AF_INET6 },            /*  k.root-servers.net  */
                    139:        { "199.7.83.42", AF_INET },             /*  l.root-servers.net  */
                    140:        { "2001:500:9f::42", AF_INET6 },        /*  l.root-servers.net  */
                    141:        { "202.12.27.33", AF_INET },            /*  m.root-servers.net  */
                    142:        { "2001:dc3::35", AF_INET6 }            /*  m.root-servers.net  */
                    143: };
                    144:
1.1       florian   145: /*%
                    146:  * Exit Codes:
                    147:  *
                    148:  *\li  0   Everything went well, including things like NXDOMAIN
                    149:  *\li  1   Usage error
                    150:  *\li  7   Got too many RR's or Names
                    151:  *\li  8   Couldn't open batch file
                    152:  *\li  9   No reply from server
                    153:  *\li  10  Internal error
                    154:  */
                    155: int exitcode = 0;
                    156: int fatalexit = 0;
                    157: char keynametext[MXNAME];
                    158: char keyfile[MXNAME] = "";
                    159: char keysecret[MXNAME] = "";
                    160: unsigned char cookie_secret[33];
                    161: unsigned char cookie[8];
                    162: dns_name_t *hmacname = NULL;
                    163: unsigned int digestbits = 0;
                    164: isc_buffer_t *namebuf = NULL;
                    165: dns_tsigkey_t *tsigkey = NULL;
1.29      florian   166: int validated = 1;
                    167: int debugging = 0;
                    168: int debugtiming = 0;
1.1       florian   169: char *progname = NULL;
                    170: dig_lookup_t *current_lookup = NULL;
                    171:
                    172: #define DIG_MAX_ADDRESSES 20
                    173:
                    174: /* dynamic callbacks */
                    175:
                    176: isc_result_t
                    177: (*dighost_printmessage)(dig_query_t *query, dns_message_t *msg,
1.29      florian   178:        int headers);
1.1       florian   179:
                    180: void
                    181: (*dighost_received)(unsigned int bytes, isc_sockaddr_t *from, dig_query_t *query);
                    182:
                    183: void
                    184: (*dighost_trying)(char *frm, dig_lookup_t *lookup);
                    185:
                    186: void
                    187: (*dighost_shutdown)(void);
                    188:
                    189: /* forward declarations */
                    190:
                    191: static void
                    192: cancel_lookup(dig_lookup_t *lookup);
                    193:
                    194: static void
                    195: recv_done(isc_task_t *task, isc_event_t *event);
                    196:
                    197: static void
                    198: send_udp(dig_query_t *query);
                    199:
                    200: static void
                    201: connect_timeout(isc_task_t *task, isc_event_t *event);
                    202:
                    203: static void
1.29      florian   204: launch_next_query(dig_query_t *query, int include_question);
1.1       florian   205:
                    206: static void
                    207: check_next_lookup(dig_lookup_t *lookup);
                    208:
1.29      florian   209: static int
1.1       florian   210: next_origin(dig_lookup_t *oldlookup);
                    211:
                    212: char *
                    213: next_token(char **stringp, const char *delim) {
                    214:        char *res;
                    215:
                    216:        do {
                    217:                res = strsep(stringp, delim);
                    218:                if (res == NULL)
                    219:                        break;
                    220:        } while (*res == '\0');
                    221:        return (res);
                    222: }
                    223:
                    224: static int
                    225: count_dots(char *string) {
                    226:        char *s;
                    227:        int i = 0;
                    228:
                    229:        s = string;
                    230:        while (*s != '\0') {
                    231:                if (*s == '.')
                    232:                        i++;
                    233:                s++;
                    234:        }
                    235:        return (i);
                    236: }
                    237:
                    238: static void
                    239: hex_dump(isc_buffer_t *b) {
                    240:        unsigned int len, i;
                    241:        isc_region_t r;
                    242:
                    243:        isc_buffer_usedregion(b, &r);
                    244:
                    245:        printf("%u bytes\n", r.length);
                    246:        for (len = 0; len < r.length; len++) {
                    247:                printf("%02x ", r.base[len]);
                    248:                if (len % 16 == 15) {
                    249:                        fputs("         ", stdout);
                    250:                        for (i = len - 15; i <= len; i++) {
                    251:                                if (r.base[i] >= '!' && r.base[i] <= '}')
                    252:                                        putchar(r.base[i]);
                    253:                                else
                    254:                                        putchar('.');
                    255:                        }
                    256:                        printf("\n");
                    257:                }
                    258:        }
                    259:        if (len % 16 != 0) {
                    260:                for (i = len; (i % 16) != 0; i++)
                    261:                        fputs("   ", stdout);
                    262:                fputs("         ", stdout);
                    263:                for (i = ((len>>4)<<4); i < len; i++) {
                    264:                        if (r.base[i] >= '!' && r.base[i] <= '}')
                    265:                                putchar(r.base[i]);
                    266:                        else
                    267:                                putchar('.');
                    268:                }
                    269:                printf("\n");
                    270:        }
                    271: }
                    272:
                    273: /*%
                    274:  * Append 'len' bytes of 'text' at '*p', failing with
                    275:  * ISC_R_NOSPACE if that would advance p past 'end'.
                    276:  */
                    277: static isc_result_t
                    278: append(const char *text, size_t len, char **p, char *end) {
                    279:        if (*p + len > end)
                    280:                return (ISC_R_NOSPACE);
                    281:        memmove(*p, text, len);
                    282:        *p += len;
                    283:        return (ISC_R_SUCCESS);
                    284: }
                    285:
                    286: static isc_result_t
                    287: reverse_octets(const char *in, char **p, char *end) {
                    288:        const char *dot = strchr(in, '.');
                    289:        size_t len;
                    290:        if (dot != NULL) {
                    291:                isc_result_t result;
                    292:                result = reverse_octets(dot + 1, p, end);
                    293:                if (result != ISC_R_SUCCESS)
                    294:                        return (result);
                    295:                result = append(".", 1, p, end);
                    296:                if (result != ISC_R_SUCCESS)
                    297:                        return (result);
                    298:                len = (int) (dot - in);
                    299:        } else {
                    300:                len = (int) strlen(in);
                    301:        }
                    302:        return (append(in, len, p, end));
                    303: }
                    304:
                    305: isc_result_t
1.29      florian   306: get_reverse(char *reverse, size_t len, char *value, int ip6_int,
                    307:            int strict)
1.1       florian   308: {
                    309:        int r;
1.31      florian   310:        struct in_addr in;
                    311:        struct in6_addr in6;
1.1       florian   312:        isc_result_t result;
                    313:
1.31      florian   314:        r = inet_pton(AF_INET6, value, &in6);
1.1       florian   315:        if (r > 0) {
                    316:                /* This is a valid IPv6 address. */
1.31      florian   317:                static char hex_digits[] = {
                    318:                        '0', '1', '2', '3', '4', '5', '6', '7',
                    319:                        '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
                    320:                };
                    321:                int i;
                    322:                unsigned char *bytes = (unsigned char *)&in6;
                    323:                char* cp;
                    324:
                    325:                if (len <= 15 * 4 + sizeof("ip6.int"))
                    326:                        return (ISC_R_NOMEMORY);
                    327:
                    328:                cp = reverse;
                    329:                for (i = 15; i >= 0; i--) {
                    330:                        *cp++ = hex_digits[bytes[i] & 0x0f];
                    331:                        *cp++ = '.';
                    332:                        *cp++ = hex_digits[(bytes[i] >> 4) & 0x0f];
                    333:                        *cp++ = '.';
                    334:                }
                    335:                *cp = '\0';
                    336:                if (strlcat(reverse, ip6_int ? "ip6.int" : "ip6.arpa", len)
                    337:                    >= len)
                    338:                        return (ISC_R_NOSPACE);
1.1       florian   339:                return (ISC_R_SUCCESS);
                    340:        } else {
                    341:                /*
                    342:                 * Not a valid IPv6 address.  Assume IPv4.
                    343:                 * If 'strict' is not set, construct the
                    344:                 * in-addr.arpa name by blindly reversing
                    345:                 * octets whether or not they look like integers,
                    346:                 * so that this can be used for RFC2317 names
                    347:                 * and such.
                    348:                 */
                    349:                char *p = reverse;
                    350:                char *end = reverse + len;
1.31      florian   351:                if (strict && inet_pton(AF_INET, value, &in) != 1)
1.1       florian   352:                        return (DNS_R_BADDOTTEDQUAD);
                    353:                result = reverse_octets(value, &p, end);
                    354:                if (result != ISC_R_SUCCESS)
                    355:                        return (result);
                    356:                /* Append .in-addr.arpa. and a terminating NUL. */
                    357:                result = append(".in-addr.arpa.", 15, &p, end);
1.31      florian   358:                return (result);
1.1       florian   359:        }
                    360: }
                    361:
                    362: void
                    363: fatal(const char *format, ...) {
                    364:        va_list args;
                    365:
                    366:        fflush(stdout);
                    367:        fprintf(stderr, "%s: ", progname);
                    368:        va_start(args, format);
                    369:        vfprintf(stderr, format, args);
                    370:        va_end(args);
                    371:        fprintf(stderr, "\n");
                    372:        if (exitcode < 10)
                    373:                exitcode = 10;
                    374:        if (fatalexit != 0)
                    375:                exitcode = fatalexit;
                    376:        exit(exitcode);
                    377: }
                    378:
                    379: void
                    380: debug(const char *format, ...) {
                    381:        va_list args;
1.8       florian   382:        struct timespec t;
1.1       florian   383:
                    384:        if (debugging) {
                    385:                fflush(stdout);
                    386:                if (debugtiming) {
1.13      florian   387:                        clock_gettime(CLOCK_MONOTONIC, &t);
1.8       florian   388:                        fprintf(stderr, "%lld.%06ld: ", t.tv_sec, t.tv_nsec /
                    389:                            1000);
1.1       florian   390:                }
                    391:                va_start(args, format);
                    392:                vfprintf(stderr, format, args);
                    393:                va_end(args);
                    394:                fprintf(stderr, "\n");
                    395:        }
                    396: }
                    397:
                    398: void
                    399: check_result(isc_result_t result, const char *msg) {
                    400:        if (result != ISC_R_SUCCESS) {
                    401:                fatal("%s: %s", msg, isc_result_totext(result));
                    402:        }
                    403: }
                    404:
                    405: /*%
                    406:  * Create a server structure, which is part of the lookup structure.
                    407:  * This is little more than a linked list of servers to query in hopes
                    408:  * of finding the answer the user is looking for
                    409:  */
                    410: dig_server_t *
                    411: make_server(const char *servname, const char *userarg) {
                    412:        dig_server_t *srv;
                    413:
                    414:        REQUIRE(servname != NULL);
                    415:
                    416:        debug("make_server(%s)", servname);
                    417:        srv = malloc(sizeof(struct dig_server));
                    418:        if (srv == NULL)
                    419:                fatal("memory allocation failure in %s:%d",
                    420:                      __FILE__, __LINE__);
                    421:        strlcpy(srv->servername, servname, MXNAME);
                    422:        strlcpy(srv->userarg, userarg, MXNAME);
                    423:        ISC_LINK_INIT(srv, link);
                    424:        return (srv);
                    425: }
                    426:
                    427: static int
                    428: addr2af(int lwresaddrtype)
                    429: {
                    430:        int af = 0;
                    431:
                    432:        switch (lwresaddrtype) {
                    433:        case LWRES_ADDRTYPE_V4:
                    434:                af = AF_INET;
                    435:                break;
                    436:
                    437:        case LWRES_ADDRTYPE_V6:
                    438:                af = AF_INET6;
                    439:                break;
                    440:        }
                    441:
                    442:        return (af);
                    443: }
                    444:
                    445: /*%
                    446:  * Create a copy of the server list from the lwres configuration structure.
                    447:  * The dest list must have already had ISC_LIST_INIT applied.
                    448:  */
                    449: static void
                    450: copy_server_list(lwres_conf_t *confdata, dig_serverlist_t *dest) {
                    451:        dig_server_t *newsrv;
                    452:        char tmp[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255") +
                    453:                 sizeof("%4000000000")];
                    454:        int af;
                    455:        int i;
                    456:
                    457:        debug("copy_server_list()");
                    458:        for (i = 0; i < confdata->nsnext; i++) {
                    459:                af = addr2af(confdata->nameservers[i].family);
                    460:
                    461:                if (af == AF_INET && !have_ipv4)
                    462:                        continue;
                    463:                if (af == AF_INET6 && !have_ipv6)
                    464:                        continue;
                    465:
                    466:                inet_ntop(af, confdata->nameservers[i].address,
                    467:                                   tmp, sizeof(tmp));
                    468:                if (af == AF_INET6 && confdata->nameservers[i].zone != 0) {
                    469:                        char buf[sizeof("%4000000000")];
                    470:                        snprintf(buf, sizeof(buf), "%%%u",
                    471:                                 confdata->nameservers[i].zone);
                    472:                        strlcat(tmp, buf, sizeof(tmp));
                    473:                }
                    474:                newsrv = make_server(tmp, tmp);
                    475:                ISC_LINK_INIT(newsrv, link);
                    476:                ISC_LIST_ENQUEUE(*dest, newsrv, link);
                    477:        }
                    478: }
                    479:
                    480: void
                    481: flush_server_list(void) {
                    482:        dig_server_t *s, *ps;
                    483:
                    484:        debug("flush_server_list()");
                    485:        s = ISC_LIST_HEAD(server_list);
                    486:        while (s != NULL) {
                    487:                ps = s;
                    488:                s = ISC_LIST_NEXT(s, link);
                    489:                ISC_LIST_DEQUEUE(server_list, ps, link);
                    490:                free(ps);
                    491:        }
                    492: }
                    493:
                    494: /* this used to be bind9_getaddresses from lib/bind9 */
                    495: static isc_result_t
                    496: get_addresses(const char *hostname, in_port_t dstport,
                    497:                   isc_sockaddr_t *addrs, int addrsize, int *addrcount)
                    498: {
                    499:        struct addrinfo *ai = NULL, *tmpai, hints;
                    500:        int result, i;
                    501:
                    502:        REQUIRE(hostname != NULL);
                    503:        REQUIRE(addrs != NULL);
                    504:        REQUIRE(addrcount != NULL);
                    505:        REQUIRE(addrsize > 0);
                    506:
                    507:        memset(&hints, 0, sizeof(hints));
                    508:        if (!have_ipv6)
                    509:                hints.ai_family = PF_INET;
                    510:        else if (!have_ipv4)
                    511:                hints.ai_family = PF_INET6;
                    512:        else {
                    513:                hints.ai_family = PF_UNSPEC;
                    514:                hints.ai_flags = AI_ADDRCONFIG;
                    515:        }
                    516:        hints.ai_socktype = SOCK_STREAM;
                    517:
                    518:        result = getaddrinfo(hostname, NULL, &hints, &ai);
                    519:        switch (result) {
                    520:        case 0:
                    521:                break;
                    522:        case EAI_NONAME:
                    523:        case EAI_NODATA:
                    524:                return (ISC_R_NOTFOUND);
                    525:        default:
                    526:                return (ISC_R_FAILURE);
                    527:        }
                    528:        for (tmpai = ai, i = 0;
                    529:             tmpai != NULL && i < addrsize;
                    530:             tmpai = tmpai->ai_next)
                    531:        {
                    532:                if (tmpai->ai_family != AF_INET &&
                    533:                    tmpai->ai_family != AF_INET6)
                    534:                        continue;
                    535:                if (tmpai->ai_family == AF_INET) {
                    536:                        struct sockaddr_in *sin;
                    537:                        sin = (struct sockaddr_in *)tmpai->ai_addr;
                    538:                        isc_sockaddr_fromin(&addrs[i], &sin->sin_addr, dstport);
                    539:                } else {
                    540:                        struct sockaddr_in6 *sin6;
                    541:                        sin6 = (struct sockaddr_in6 *)tmpai->ai_addr;
                    542:                        isc_sockaddr_fromin6(&addrs[i], &sin6->sin6_addr,
                    543:                                             dstport);
                    544:                }
                    545:                i++;
                    546:
                    547:        }
                    548:        freeaddrinfo(ai);
                    549:        *addrcount = i;
                    550:        if (*addrcount == 0)
                    551:                return (ISC_R_NOTFOUND);
                    552:        else
                    553:                return (ISC_R_SUCCESS);
                    554: }
                    555:
1.24      deraadt   556: isc_result_t
1.1       florian   557: set_nameserver(char *opt) {
                    558:        isc_result_t result;
                    559:        isc_sockaddr_t sockaddrs[DIG_MAX_ADDRESSES];
                    560:        int count, i;
                    561:        dig_server_t *srv;
1.32      florian   562:        char tmp[NI_MAXHOST];
1.1       florian   563:
                    564:        if (opt == NULL)
1.24      deraadt   565:                return ISC_R_NOTFOUND;
1.1       florian   566:
                    567:        result = get_addresses(opt, 0, sockaddrs,
                    568:                                    DIG_MAX_ADDRESSES, &count);
                    569:        if (result != ISC_R_SUCCESS)
1.24      deraadt   570:                return (result);
1.1       florian   571:
                    572:        flush_server_list();
                    573:
                    574:        for (i = 0; i < count; i++) {
1.32      florian   575:                int error;
                    576:                error = getnameinfo(&sockaddrs[i].type.sa,
                    577:                    sockaddrs[i].type.sa.sa_len, tmp, sizeof(tmp), NULL, 0,
                    578:                    NI_NUMERICHOST | NI_NUMERICSERV);
                    579:                if (error)
                    580:                        fatal("%s", gai_strerror(error));
1.1       florian   581:                srv = make_server(tmp, opt);
                    582:                if (srv == NULL)
                    583:                        fatal("memory allocation failure");
                    584:                ISC_LIST_APPEND(server_list, srv, link);
                    585:        }
1.24      deraadt   586:        return (ISC_R_SUCCESS);
1.1       florian   587: }
                    588:
                    589: static isc_result_t
                    590: add_nameserver(lwres_conf_t *confdata, const char *addr, int af) {
                    591:
                    592:        int i = confdata->nsnext;
                    593:
                    594:        if (confdata->nsnext >= LWRES_CONFMAXNAMESERVERS)
                    595:                return (ISC_R_FAILURE);
                    596:
                    597:        switch (af) {
                    598:        case AF_INET:
                    599:                confdata->nameservers[i].family = LWRES_ADDRTYPE_V4;
1.3       florian   600:                confdata->nameservers[i].length = sizeof(struct in_addr);
1.1       florian   601:                break;
                    602:        case AF_INET6:
                    603:                confdata->nameservers[i].family = LWRES_ADDRTYPE_V6;
1.3       florian   604:                confdata->nameservers[i].length = sizeof(struct in6_addr);
1.1       florian   605:                break;
                    606:        default:
                    607:                return (ISC_R_FAILURE);
                    608:        }
                    609:
                    610:        if (inet_pton(af, addr, &confdata->nameservers[i].address) == 1) {
                    611:                confdata->nsnext++;
                    612:                return (ISC_R_SUCCESS);
                    613:        }
                    614:        return (ISC_R_FAILURE);
                    615: }
                    616:
                    617: /*%
                    618:  * Produce a cloned server list.  The dest list must have already had
                    619:  * ISC_LIST_INIT applied.
                    620:  */
                    621: void
                    622: clone_server_list(dig_serverlist_t src, dig_serverlist_t *dest) {
                    623:        dig_server_t *srv, *newsrv;
                    624:
                    625:        debug("clone_server_list()");
                    626:        srv = ISC_LIST_HEAD(src);
                    627:        while (srv != NULL) {
                    628:                newsrv = make_server(srv->servername, srv->userarg);
                    629:                ISC_LINK_INIT(newsrv, link);
                    630:                ISC_LIST_ENQUEUE(*dest, newsrv, link);
                    631:                srv = ISC_LIST_NEXT(srv, link);
                    632:        }
                    633: }
                    634:
                    635: /*%
                    636:  * Create an empty lookup structure, which holds all the information needed
                    637:  * to get an answer to a user's question.  This structure contains two
                    638:  * linked lists: the server list (servers to query) and the query list
                    639:  * (outstanding queries which have been made to the listed servers).
                    640:  */
                    641: dig_lookup_t *
                    642: make_empty_lookup(void) {
                    643:        dig_lookup_t *looknew;
                    644:
                    645:        debug("make_empty_lookup()");
                    646:
                    647:        INSIST(!free_now);
                    648:
                    649:        looknew = malloc(sizeof(struct dig_lookup));
                    650:        if (looknew == NULL)
                    651:                fatal("memory allocation failure in %s:%d",
                    652:                       __FILE__, __LINE__);
1.29      florian   653:        looknew->pending = 1;
1.1       florian   654:        looknew->textname[0] = 0;
                    655:        looknew->cmdline[0] = 0;
                    656:        looknew->rdtype = dns_rdatatype_a;
                    657:        looknew->qrdtype = dns_rdatatype_a;
                    658:        looknew->rdclass = dns_rdataclass_in;
1.29      florian   659:        looknew->rdtypeset = 0;
                    660:        looknew->rdclassset = 0;
1.1       florian   661:        looknew->sendspace = NULL;
                    662:        looknew->sendmsg = NULL;
                    663:        looknew->name = NULL;
                    664:        looknew->oname = NULL;
                    665:        looknew->xfr_q = NULL;
                    666:        looknew->current_query = NULL;
1.29      florian   667:        looknew->doing_xfr = 0;
1.1       florian   668:        looknew->ixfr_serial = 0;
1.29      florian   669:        looknew->trace = 0;
                    670:        looknew->trace_root = 0;
                    671:        looknew->identify = 0;
                    672:        looknew->identify_previous_line = 0;
                    673:        looknew->ignore = 0;
                    674:        looknew->servfail_stops = 1;
                    675:        looknew->besteffort = 1;
                    676:        looknew->dnssec = 0;
1.1       florian   677:        looknew->ednsflags = 0;
                    678:        looknew->opcode = dns_opcode_query;
1.29      florian   679:        looknew->expire = 0;
                    680:        looknew->nsid = 0;
                    681:        looknew->idnout = 0;
                    682:        looknew->sit = 0;
1.1       florian   683:        looknew->udpsize = 0;
                    684:        looknew->edns = -1;
1.29      florian   685:        looknew->recurse = 1;
                    686:        looknew->aaonly = 0;
                    687:        looknew->adflag = 0;
                    688:        looknew->cdflag = 0;
                    689:        looknew->ns_search_only = 0;
1.1       florian   690:        looknew->origin = NULL;
                    691:        looknew->tsigctx = NULL;
                    692:        looknew->querysig = NULL;
                    693:        looknew->retries = tries;
                    694:        looknew->nsfound = 0;
1.29      florian   695:        looknew->tcp_mode = 0;
                    696:        looknew->tcp_mode_set = 0;
                    697:        looknew->ip6_int = 0;
                    698:        looknew->comments = 1;
                    699:        looknew->stats = 1;
                    700:        looknew->section_question = 1;
                    701:        looknew->section_answer = 1;
                    702:        looknew->section_authority = 1;
                    703:        looknew->section_additional = 1;
                    704:        looknew->new_search = 0;
                    705:        looknew->done_as_is = 0;
                    706:        looknew->need_search = 0;
1.1       florian   707:        looknew->ecs_addr = NULL;
                    708:        looknew->sitvalue = NULL;
                    709:        looknew->ednsopts = NULL;
                    710:        looknew->ednsoptscnt = 0;
1.29      florian   711:        looknew->ednsneg = 0;
1.1       florian   712:        looknew->eoferr = 0;
                    713:        dns_fixedname_init(&looknew->fdomain);
                    714:        ISC_LINK_INIT(looknew, link);
                    715:        ISC_LIST_INIT(looknew->q);
                    716:        ISC_LIST_INIT(looknew->connecting);
                    717:        ISC_LIST_INIT(looknew->my_server_list);
                    718:        return (looknew);
                    719: }
                    720:
                    721: #define EDNSOPT_OPTIONS 100U
                    722:
                    723: static void
                    724: cloneopts(dig_lookup_t *looknew, dig_lookup_t *lookold) {
                    725:        size_t len = sizeof(looknew->ednsopts[0]) * EDNSOPT_OPTIONS;
                    726:        size_t i;
                    727:        looknew->ednsopts = malloc(len);
                    728:        if (looknew->ednsopts == NULL)
                    729:                fatal("out of memory");
                    730:        for (i = 0; i < EDNSOPT_OPTIONS; i++) {
                    731:                looknew->ednsopts[i].code = 0;
                    732:                looknew->ednsopts[i].length = 0;
                    733:                looknew->ednsopts[i].value = NULL;
                    734:        }
                    735:        looknew->ednsoptscnt = 0;
                    736:        if (lookold == NULL || lookold->ednsopts == NULL)
                    737:                return;
                    738:
                    739:        for (i = 0; i < lookold->ednsoptscnt; i++) {
                    740:                len = lookold->ednsopts[i].length;
                    741:                if (len != 0) {
                    742:                        INSIST(lookold->ednsopts[i].value != NULL);
                    743:                        looknew->ednsopts[i].value =
                    744:                                 malloc(len);
                    745:                        if (looknew->ednsopts[i].value == NULL)
                    746:                                fatal("out of memory");
                    747:                        memmove(looknew->ednsopts[i].value,
                    748:                                lookold->ednsopts[i].value, len);
                    749:                }
                    750:                looknew->ednsopts[i].code = lookold->ednsopts[i].code;
                    751:                looknew->ednsopts[i].length = len;
                    752:        }
                    753:        looknew->ednsoptscnt = lookold->ednsoptscnt;
                    754: }
                    755:
                    756: /*%
                    757:  * Clone a lookup, perhaps copying the server list.  This does not clone
                    758:  * the query list, since it will be regenerated by the setup_lookup()
                    759:  * function, nor does it queue up the new lookup for processing.
                    760:  * Caution: If you don't clone the servers, you MUST clone the server
                    761:  * list separately from somewhere else, or construct it by hand.
                    762:  */
                    763: dig_lookup_t *
1.29      florian   764: clone_lookup(dig_lookup_t *lookold, int servers) {
1.1       florian   765:        dig_lookup_t *looknew;
                    766:
                    767:        debug("clone_lookup()");
                    768:
                    769:        INSIST(!free_now);
                    770:
                    771:        looknew = make_empty_lookup();
                    772:        INSIST(looknew != NULL);
                    773:        strlcpy(looknew->textname, lookold->textname, MXNAME);
                    774:        strlcpy(looknew->cmdline, lookold->cmdline, MXNAME);
                    775:        looknew->textname[MXNAME-1] = 0;
                    776:        looknew->rdtype = lookold->rdtype;
                    777:        looknew->qrdtype = lookold->qrdtype;
                    778:        looknew->rdclass = lookold->rdclass;
                    779:        looknew->rdtypeset = lookold->rdtypeset;
                    780:        looknew->rdclassset = lookold->rdclassset;
                    781:        looknew->doing_xfr = lookold->doing_xfr;
                    782:        looknew->ixfr_serial = lookold->ixfr_serial;
                    783:        looknew->trace = lookold->trace;
                    784:        looknew->trace_root = lookold->trace_root;
                    785:        looknew->identify = lookold->identify;
                    786:        looknew->identify_previous_line = lookold->identify_previous_line;
                    787:        looknew->ignore = lookold->ignore;
                    788:        looknew->servfail_stops = lookold->servfail_stops;
                    789:        looknew->besteffort = lookold->besteffort;
                    790:        looknew->dnssec = lookold->dnssec;
                    791:        looknew->ednsflags = lookold->ednsflags;
                    792:        looknew->opcode = lookold->opcode;
                    793:        looknew->expire = lookold->expire;
                    794:        looknew->nsid = lookold->nsid;
                    795:        looknew->sit = lookold->sit;
                    796:        looknew->sitvalue = lookold->sitvalue;
                    797:        if (lookold->ednsopts != NULL) {
                    798:                cloneopts(looknew, lookold);
                    799:        } else {
                    800:                looknew->ednsopts = NULL;
                    801:                looknew->ednsoptscnt = 0;
                    802:        }
                    803:        looknew->ednsneg = lookold->ednsneg;
                    804:        looknew->idnout = lookold->idnout;
                    805:        looknew->udpsize = lookold->udpsize;
                    806:        looknew->edns = lookold->edns;
                    807:        looknew->recurse = lookold->recurse;
                    808:        looknew->aaonly = lookold->aaonly;
                    809:        looknew->adflag = lookold->adflag;
                    810:        looknew->cdflag = lookold->cdflag;
                    811:        looknew->ns_search_only = lookold->ns_search_only;
                    812:        looknew->tcp_mode = lookold->tcp_mode;
                    813:        looknew->tcp_mode_set = lookold->tcp_mode_set;
                    814:        looknew->comments = lookold->comments;
                    815:        looknew->stats = lookold->stats;
                    816:        looknew->section_question = lookold->section_question;
                    817:        looknew->section_answer = lookold->section_answer;
                    818:        looknew->section_authority = lookold->section_authority;
                    819:        looknew->section_additional = lookold->section_additional;
                    820:        looknew->origin = lookold->origin;
                    821:        looknew->retries = lookold->retries;
                    822:        looknew->tsigctx = NULL;
                    823:        looknew->need_search = lookold->need_search;
                    824:        looknew->done_as_is = lookold->done_as_is;
                    825:        looknew->eoferr = lookold->eoferr;
                    826:
                    827:        if (lookold->ecs_addr != NULL) {
                    828:                size_t len = sizeof(isc_sockaddr_t);
                    829:                looknew->ecs_addr = malloc(len);
                    830:                if (looknew->ecs_addr == NULL)
                    831:                        fatal("out of memory");
                    832:                memmove(looknew->ecs_addr, lookold->ecs_addr, len);
                    833:        }
                    834:
                    835:        dns_name_copy(dns_fixedname_name(&lookold->fdomain),
                    836:                      dns_fixedname_name(&looknew->fdomain), NULL);
                    837:
                    838:        if (servers)
                    839:                clone_server_list(lookold->my_server_list,
                    840:                                  &looknew->my_server_list);
                    841:        return (looknew);
                    842: }
                    843:
                    844: /*%
                    845:  * Requeue a lookup for further processing, perhaps copying the server
                    846:  * list.  The new lookup structure is returned to the caller, and is
                    847:  * queued for processing.  If servers are not cloned in the requeue, they
                    848:  * must be added before allowing the current event to complete, since the
                    849:  * completion of the event may result in the next entry on the lookup
                    850:  * queue getting run.
                    851:  */
                    852: dig_lookup_t *
1.29      florian   853: requeue_lookup(dig_lookup_t *lookold, int servers) {
1.1       florian   854:        dig_lookup_t *looknew;
                    855:
                    856:        debug("requeue_lookup()");
                    857:
                    858:        lookup_counter++;
                    859:        if (lookup_counter > LOOKUP_LIMIT)
                    860:                fatal("too many lookups");
                    861:
                    862:        looknew = clone_lookup(lookold, servers);
                    863:        INSIST(looknew != NULL);
                    864:
                    865:        debug("before insertion, init@%p -> %p, new@%p -> %p",
                    866:              lookold, lookold->link.next, looknew, looknew->link.next);
                    867:        ISC_LIST_PREPEND(lookup_list, looknew, link);
                    868:        debug("after insertion, init -> %p, new = %p, new -> %p",
                    869:              lookold, looknew, looknew->link.next);
                    870:        return (looknew);
                    871: }
                    872:
                    873: void
                    874: setup_text_key(void) {
                    875:        isc_result_t result;
                    876:        dns_name_t keyname;
                    877:        isc_buffer_t secretbuf;
                    878:        unsigned int secretsize;
                    879:        unsigned char *secretstore;
                    880:
                    881:        debug("setup_text_key()");
                    882:        result = isc_buffer_allocate(&namebuf, MXNAME);
                    883:        check_result(result, "isc_buffer_allocate");
                    884:        dns_name_init(&keyname, NULL);
                    885:        check_result(result, "dns_name_init");
                    886:        isc_buffer_putstr(namebuf, keynametext);
                    887:        secretsize = (unsigned int) strlen(keysecret) * 3 / 4;
                    888:        secretstore = malloc(secretsize);
                    889:        if (secretstore == NULL)
                    890:                fatal("memory allocation failure in %s:%d",
                    891:                      __FILE__, __LINE__);
                    892:        isc_buffer_init(&secretbuf, secretstore, secretsize);
                    893:        result = isc_base64_decodestring(keysecret, &secretbuf);
                    894:        if (result != ISC_R_SUCCESS)
                    895:                goto failure;
                    896:
                    897:        secretsize = isc_buffer_usedlength(&secretbuf);
                    898:
                    899:        if (hmacname == NULL) {
                    900:                result = DST_R_UNSUPPORTEDALG;
                    901:                goto failure;
                    902:        }
                    903:
                    904:        result = dns_name_fromtext(&keyname, namebuf, dns_rootname, 0, namebuf);
                    905:        if (result != ISC_R_SUCCESS)
                    906:                goto failure;
                    907:
                    908:        result = dns_tsigkey_create(&keyname, hmacname, secretstore,
1.29      florian   909:                                    (int)secretsize, 0, NULL, 0, 0,
1.1       florian   910:                                    &tsigkey);
                    911:  failure:
                    912:        if (result != ISC_R_SUCCESS)
                    913:                printf(";; Couldn't create key %s: %s\n",
                    914:                       keynametext, isc_result_totext(result));
                    915:        else
                    916:                dst_key_setbits(tsigkey->key, digestbits);
                    917:
                    918:        free(secretstore);
                    919:        dns_name_invalidate(&keyname);
                    920:        isc_buffer_free(&namebuf);
                    921: }
                    922:
                    923: static uint32_t
1.26      florian   924: parse_bits(char *arg, uint32_t max) {
1.1       florian   925:        uint32_t tmp;
1.26      florian   926:        const char *errstr;
1.1       florian   927:
1.26      florian   928:        tmp = strtonum(arg, 0, max, &errstr);
                    929:        if (errstr != NULL)
                    930:                fatal("digest bits is %s: '%s'", errstr, arg);
1.1       florian   931:        tmp = (tmp + 7) & ~0x7U;
                    932:        return (tmp);
                    933: }
                    934:
                    935: isc_result_t
1.33    ! florian   936: parse_netprefix(isc_sockaddr_t **sap, int *plen, const char *value) {
1.1       florian   937:        isc_sockaddr_t *sa = NULL;
                    938:        struct in_addr in4;
                    939:        struct in6_addr in6;
                    940:        uint32_t prefix_length = 0xffffffff;
                    941:        char *slash = NULL;
1.29      florian   942:        int parsed = 0;
                    943:        int prefix_parsed = 0;
1.1       florian   944:        char buf[sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:XXX.XXX.XXX.XXX/128")];
1.26      florian   945:        const char *errstr;
1.1       florian   946:
                    947:        REQUIRE(sap != NULL && *sap == NULL);
                    948:
                    949:        if (strlcpy(buf, value, sizeof(buf)) >= sizeof(buf))
                    950:                fatal("invalid prefix '%s'\n", value);
                    951:
                    952:        sa = malloc(sizeof(*sa));
                    953:        if (sa == NULL)
                    954:                fatal("out of memory");
                    955:        memset(sa, 0, sizeof(*sa));
                    956:
                    957:        if (strcmp(buf, "0") == 0) {
                    958:                sa->type.sa.sa_family = AF_UNSPEC;
                    959:                prefix_length = 0;
                    960:                goto done;
                    961:        }
                    962:
                    963:        slash = strchr(buf, '/');
                    964:        if (slash != NULL) {
                    965:                *slash = '\0';
1.30      florian   966:                prefix_length = strtonum(slash + 1, 0, 128, &errstr);
1.26      florian   967:                if (errstr != NULL) {
                    968:                        fatal("prefix length is %s: '%s'", errstr, value);
1.1       florian   969:                }
1.29      florian   970:                prefix_parsed = 1;
1.1       florian   971:        }
                    972:
                    973:        if (inet_pton(AF_INET6, buf, &in6) == 1) {
1.29      florian   974:                parsed = 1;
1.1       florian   975:                isc_sockaddr_fromin6(sa, &in6, 0);
                    976:                if (prefix_length > 128)
                    977:                        prefix_length = 128;
                    978:        } else if (inet_pton(AF_INET, buf, &in4) == 1) {
1.29      florian   979:                parsed = 1;
1.1       florian   980:                isc_sockaddr_fromin(sa, &in4, 0);
                    981:                if (prefix_length > 32)
                    982:                        prefix_length = 32;
                    983:        } else if (prefix_parsed) {
                    984:                int i;
                    985:
                    986:                for (i = 0; i < 3 && strlen(buf) < sizeof(buf) - 2; i++) {
                    987:                        strlcat(buf, ".0", sizeof(buf));
                    988:                        if (inet_pton(AF_INET, buf, &in4) == 1) {
1.29      florian   989:                                parsed = 1;
1.1       florian   990:                                isc_sockaddr_fromin(sa, &in4, 0);
                    991:                                break;
                    992:                        }
                    993:                }
                    994:
                    995:                if (prefix_length > 32)
                    996:                        prefix_length = 32;
                    997:        }
                    998:
                    999:        if (!parsed)
                   1000:                fatal("invalid address '%s'", value);
                   1001:
                   1002: done:
1.33    ! florian  1003:        *plen = prefix_length;
1.1       florian  1004:        *sap = sa;
                   1005:
                   1006:        return (ISC_R_SUCCESS);
                   1007: }
                   1008:
                   1009: /*
                   1010:  * Parse HMAC algorithm specification
                   1011:  */
                   1012: void
                   1013: parse_hmac(const char *hmac) {
                   1014:        char buf[20];
                   1015:        size_t len;
                   1016:
                   1017:        REQUIRE(hmac != NULL);
                   1018:
                   1019:        len = strlen(hmac);
                   1020:        if (len >= sizeof(buf))
                   1021:                fatal("unknown key type '%.*s'", (int)len, hmac);
                   1022:        strlcpy(buf, hmac, sizeof(buf));
                   1023:
                   1024:        digestbits = 0;
                   1025:
                   1026:        if (strcasecmp(buf, "hmac-sha1") == 0) {
                   1027:                hmacname = DNS_TSIG_HMACSHA1_NAME;
                   1028:                digestbits = 0;
                   1029:        } else if (strncasecmp(buf, "hmac-sha1-", 10) == 0) {
                   1030:                hmacname = DNS_TSIG_HMACSHA1_NAME;
1.26      florian  1031:                digestbits = parse_bits(&buf[10], 160);
1.1       florian  1032:        } else if (strcasecmp(buf, "hmac-sha224") == 0) {
                   1033:                hmacname = DNS_TSIG_HMACSHA224_NAME;
                   1034:        } else if (strncasecmp(buf, "hmac-sha224-", 12) == 0) {
                   1035:                hmacname = DNS_TSIG_HMACSHA224_NAME;
1.26      florian  1036:                digestbits = parse_bits(&buf[12], 224);
1.1       florian  1037:        } else if (strcasecmp(buf, "hmac-sha256") == 0) {
                   1038:                hmacname = DNS_TSIG_HMACSHA256_NAME;
                   1039:        } else if (strncasecmp(buf, "hmac-sha256-", 12) == 0) {
                   1040:                hmacname = DNS_TSIG_HMACSHA256_NAME;
1.26      florian  1041:                digestbits = parse_bits(&buf[12], 256);
1.1       florian  1042:        } else if (strcasecmp(buf, "hmac-sha384") == 0) {
                   1043:                hmacname = DNS_TSIG_HMACSHA384_NAME;
                   1044:        } else if (strncasecmp(buf, "hmac-sha384-", 12) == 0) {
                   1045:                hmacname = DNS_TSIG_HMACSHA384_NAME;
1.26      florian  1046:                digestbits = parse_bits(&buf[12], 384);
1.1       florian  1047:        } else if (strcasecmp(buf, "hmac-sha512") == 0) {
                   1048:                hmacname = DNS_TSIG_HMACSHA512_NAME;
                   1049:        } else if (strncasecmp(buf, "hmac-sha512-", 12) == 0) {
                   1050:                hmacname = DNS_TSIG_HMACSHA512_NAME;
1.26      florian  1051:                digestbits = parse_bits(&buf[12], 512);
1.1       florian  1052:        } else {
                   1053:                fprintf(stderr, ";; Warning, ignoring "
                   1054:                        "invalid TSIG algorithm %s\n", buf);
                   1055:        }
                   1056: }
                   1057:
                   1058: /*
                   1059:  * Get a key from a named.conf format keyfile
                   1060:  */
                   1061: static isc_result_t
                   1062: read_confkey(void) {
                   1063:        cfg_parser_t *pctx = NULL;
                   1064:        cfg_obj_t *file = NULL;
                   1065:        const cfg_obj_t *keyobj = NULL;
                   1066:        const cfg_obj_t *secretobj = NULL;
                   1067:        const cfg_obj_t *algorithmobj = NULL;
                   1068:        const char *keyname;
                   1069:        const char *secretstr;
                   1070:        const char *algorithm;
                   1071:        isc_result_t result;
                   1072:
                   1073:        result = cfg_parser_create(NULL, &pctx);
                   1074:        if (result != ISC_R_SUCCESS)
                   1075:                goto cleanup;
                   1076:
                   1077:        result = cfg_parse_file(pctx, keyfile, &cfg_type_sessionkey,
                   1078:                                &file);
                   1079:        if (result != ISC_R_SUCCESS)
                   1080:                goto cleanup;
                   1081:
                   1082:        result = cfg_map_get(file, "key", &keyobj);
                   1083:        if (result != ISC_R_SUCCESS)
                   1084:                goto cleanup;
                   1085:
                   1086:        (void) cfg_map_get(keyobj, "secret", &secretobj);
                   1087:        (void) cfg_map_get(keyobj, "algorithm", &algorithmobj);
                   1088:        if (secretobj == NULL || algorithmobj == NULL)
                   1089:                fatal("key must have algorithm and secret");
                   1090:
                   1091:        keyname = cfg_obj_asstring(cfg_map_getname(keyobj));
                   1092:        secretstr = cfg_obj_asstring(secretobj);
                   1093:        algorithm = cfg_obj_asstring(algorithmobj);
                   1094:
                   1095:        strlcpy(keynametext, keyname, sizeof(keynametext));
                   1096:        strlcpy(keysecret, secretstr, sizeof(keysecret));
                   1097:        parse_hmac(algorithm);
                   1098:        setup_text_key();
                   1099:
                   1100:  cleanup:
                   1101:        if (pctx != NULL) {
                   1102:                if (file != NULL)
                   1103:                        cfg_obj_destroy(pctx, &file);
                   1104:                cfg_parser_destroy(&pctx);
                   1105:        }
                   1106:
                   1107:        return (result);
                   1108: }
                   1109:
                   1110: void
                   1111: setup_file_key(void) {
                   1112:        isc_result_t result;
                   1113:
                   1114:        debug("setup_file_key()");
                   1115:
1.12      florian  1116:        /* Try reading the key as a session.key keyfile */
                   1117:        result = read_confkey();
1.1       florian  1118:
1.12      florian  1119:        if (result != ISC_R_SUCCESS)
1.1       florian  1120:                fprintf(stderr, "Couldn't read key from %s: %s\n",
                   1121:                        keyfile, isc_result_totext(result));
                   1122: }
                   1123:
                   1124: static dig_searchlist_t *
                   1125: make_searchlist_entry(char *domain) {
                   1126:        dig_searchlist_t *search;
                   1127:        search = malloc(sizeof(*search));
                   1128:        if (search == NULL)
                   1129:                fatal("memory allocation failure in %s:%d",
                   1130:                      __FILE__, __LINE__);
                   1131:        strlcpy(search->origin, domain, MXNAME);
                   1132:        search->origin[MXNAME-1] = 0;
                   1133:        ISC_LINK_INIT(search, link);
                   1134:        return (search);
                   1135: }
                   1136:
                   1137: static void
                   1138: clear_searchlist(void) {
                   1139:        dig_searchlist_t *search;
                   1140:        while ((search = ISC_LIST_HEAD(search_list)) != NULL) {
                   1141:                ISC_LIST_UNLINK(search_list, search, link);
                   1142:                free(search);
                   1143:        }
                   1144: }
                   1145:
                   1146: static void
                   1147: create_search_list(lwres_conf_t *confdata) {
                   1148:        int i;
                   1149:        dig_searchlist_t *search;
                   1150:
                   1151:        debug("create_search_list()");
                   1152:        clear_searchlist();
                   1153:
                   1154:        for (i = 0; i < confdata->searchnxt; i++) {
                   1155:                search = make_searchlist_entry(confdata->search[i]);
                   1156:                ISC_LIST_APPEND(search_list, search, link);
                   1157:        }
                   1158: }
                   1159:
                   1160: /*%
                   1161:  * Setup the system as a whole, reading key information and resolv.conf
                   1162:  * settings.
                   1163:  */
                   1164: void
1.29      florian  1165: setup_system(int ipv4only, int ipv6only) {
1.1       florian  1166:        dig_searchlist_t *domain = NULL;
                   1167:        lwres_result_t lwresult;
                   1168:        int lwresflags = 0;
                   1169:
                   1170:        debug("setup_system()");
                   1171:
                   1172:        if (ipv4only) {
1.28      florian  1173:                if (have_ipv4)
1.29      florian  1174:                        have_ipv6 = 0;
1.28      florian  1175:                else
1.1       florian  1176:                        fatal("can't find IPv4 networking");
                   1177:        }
                   1178:
                   1179:        if (ipv6only) {
1.28      florian  1180:                if (have_ipv6)
1.29      florian  1181:                        have_ipv4 = 0;
1.28      florian  1182:                else
1.1       florian  1183:                        fatal("can't find IPv6 networking");
                   1184:        }
                   1185:
                   1186:        if (have_ipv4)
                   1187:                lwresflags |= LWRES_USEIPV4;
                   1188:        if (have_ipv6)
                   1189:                lwresflags |= LWRES_USEIPV6;
                   1190:        lwres_conf_init(lwconf, lwresflags);
                   1191:
1.6       florian  1192:        lwresult = lwres_conf_parse(lwconf, _PATH_RESCONF);
1.1       florian  1193:        if (lwresult != LWRES_R_SUCCESS && lwresult != LWRES_R_NOTFOUND)
1.6       florian  1194:                fatal("parse of %s failed", _PATH_RESCONF);
1.1       florian  1195:
                   1196:        /* Make the search list */
                   1197:        if (lwconf->searchnxt > 0)
                   1198:                create_search_list(lwconf);
                   1199:        else { /* No search list. Use the domain name if any */
                   1200:                if (lwconf->domainname != NULL) {
                   1201:                        domain = make_searchlist_entry(lwconf->domainname);
                   1202:                        ISC_LIST_APPEND(search_list, domain, link);
                   1203:                        domain  = NULL;
                   1204:                }
                   1205:        }
                   1206:
                   1207:        if (ndots == -1) {
                   1208:                ndots = lwconf->ndots;
                   1209:                debug("ndots is %d.", ndots);
                   1210:        }
                   1211:
                   1212:        /* If user doesn't specify server use nameservers from resolv.conf. */
                   1213:        if (ISC_LIST_EMPTY(server_list))
                   1214:                copy_server_list(lwconf, &server_list);
                   1215:
                   1216:        /* If we don't find a nameserver fall back to localhost */
                   1217:        if (ISC_LIST_EMPTY(server_list)) {
                   1218:                if (have_ipv4) {
                   1219:                        lwresult = add_nameserver(lwconf, "127.0.0.1", AF_INET);
                   1220:                        if (lwresult != ISC_R_SUCCESS)
                   1221:                                fatal("add_nameserver failed");
                   1222:                }
                   1223:                if (have_ipv6) {
                   1224:                        lwresult = add_nameserver(lwconf, "::1", AF_INET6);
                   1225:                        if (lwresult != ISC_R_SUCCESS)
                   1226:                                fatal("add_nameserver failed");
                   1227:                }
                   1228:
                   1229:                copy_server_list(lwconf, &server_list);
                   1230:        }
                   1231:
                   1232:        if (keyfile[0] != 0)
                   1233:                setup_file_key();
                   1234:        else if (keysecret[0] != 0)
                   1235:                setup_text_key();
                   1236:        arc4random_buf(cookie_secret, sizeof(cookie_secret));
                   1237: }
                   1238:
                   1239: /*%
                   1240:  * Override the search list derived from resolv.conf by 'domain'.
                   1241:  */
                   1242: void
                   1243: set_search_domain(char *domain) {
                   1244:        dig_searchlist_t *search;
                   1245:
                   1246:        clear_searchlist();
                   1247:        search = make_searchlist_entry(domain);
                   1248:        ISC_LIST_APPEND(search_list, search, link);
                   1249: }
                   1250:
                   1251: /*%
                   1252:  * Setup the ISC and DNS libraries for use by the system.
                   1253:  */
                   1254: void
                   1255: setup_libs(void) {
                   1256:        isc_result_t result;
                   1257:        isc_logconfig_t *logconfig = NULL;
                   1258:
                   1259:        debug("setup_libs()");
                   1260:
                   1261:        dns_result_register();
                   1262:
                   1263:        result = isc_log_create(&lctx, &logconfig);
                   1264:        check_result(result, "isc_log_create");
                   1265:
                   1266:        isc_log_setcontext(lctx);
                   1267:        dns_log_init(lctx);
                   1268:        dns_log_setcontext(lctx);
                   1269:
                   1270:        result = isc_log_usechannel(logconfig, "default_debug", NULL, NULL);
                   1271:        check_result(result, "isc_log_usechannel");
                   1272:
                   1273:        isc_log_setdebuglevel(lctx, 0);
                   1274:
                   1275:        result = isc_taskmgr_create(1, 0, &taskmgr);
                   1276:        check_result(result, "isc_taskmgr_create");
                   1277:
                   1278:        result = isc_task_create(taskmgr, 0, &global_task);
                   1279:        check_result(result, "isc_task_create");
                   1280:        isc_task_setname(global_task, "dig", NULL);
                   1281:
                   1282:        result = isc_timermgr_create(&timermgr);
                   1283:        check_result(result, "isc_timermgr_create");
                   1284:
                   1285:        result = isc_socketmgr_create(&socketmgr);
                   1286:        check_result(result, "isc_socketmgr_create");
                   1287:
                   1288:        check_result(result, "isc_entropy_create");
                   1289:
                   1290:        result = dst_lib_init();
                   1291:        check_result(result, "dst_lib_init");
1.29      florian  1292:        is_dst_up = 1;
1.1       florian  1293: }
                   1294:
                   1295: typedef struct dig_ednsoptname {
                   1296:        uint32_t code;
                   1297:        const char  *name;
                   1298: } dig_ednsoptname_t;
                   1299:
                   1300: dig_ednsoptname_t optnames[] = {
                   1301:        { 3, "NSID" },          /* RFC 5001 */
                   1302:        { 5, "DAU" },           /* RFC 6975 */
                   1303:        { 6, "DHU" },           /* RFC 6975 */
                   1304:        { 7, "N3U" },           /* RFC 6975 */
                   1305:        { 8, "ECS" },           /* RFC 7871 */
                   1306:        { 9, "EXPIRE" },        /* RFC 7314 */
                   1307:        { 10, "COOKIE" },       /* RFC 7873 */
                   1308:        { 11, "KEEPALIVE" },    /* RFC 7828 */
                   1309:        { 12, "PADDING" },      /* RFC 7830 */
                   1310:        { 12, "PAD" },          /* shorthand */
                   1311:        { 13, "CHAIN" },        /* RFC 7901 */
                   1312:        { 14, "KEY-TAG" },      /* RFC 8145 */
                   1313:        { 26946, "DEVICEID" },  /* Brian Hartvigsen */
                   1314: };
                   1315:
                   1316: #define N_EDNS_OPTNAMES  (sizeof(optnames) / sizeof(optnames[0]))
                   1317:
                   1318: void
                   1319: save_opt(dig_lookup_t *lookup, char *code, char *value) {
                   1320:        isc_result_t result;
                   1321:        uint32_t num = 0;
                   1322:        isc_buffer_t b;
1.29      florian  1323:        int found = 0;
1.1       florian  1324:        unsigned int i;
1.26      florian  1325:        const char *errstr;
1.1       florian  1326:
                   1327:        if (lookup->ednsoptscnt >= EDNSOPT_OPTIONS)
                   1328:                fatal("too many ednsopts");
                   1329:
                   1330:        for (i = 0; i < N_EDNS_OPTNAMES; i++) {
                   1331:                if (strcasecmp(code, optnames[i].name) == 0) {
                   1332:                        num = optnames[i].code;
1.29      florian  1333:                        found = 1;
1.1       florian  1334:                        break;
                   1335:                }
                   1336:        }
                   1337:
                   1338:        if (!found) {
1.26      florian  1339:                num = strtonum(code, 0, 65535, &errstr);
                   1340:                if (errstr != NULL)
                   1341:                        fatal("edns code point is %s: '%s'", errstr, code);
1.1       florian  1342:        }
                   1343:
                   1344:        if (lookup->ednsopts == NULL) {
                   1345:                cloneopts(lookup, NULL);
                   1346:        }
                   1347:
                   1348:        if (lookup->ednsopts[lookup->ednsoptscnt].value != NULL)
                   1349:                free(lookup->ednsopts[lookup->ednsoptscnt].value);
                   1350:
                   1351:        lookup->ednsopts[lookup->ednsoptscnt].code = num;
                   1352:        lookup->ednsopts[lookup->ednsoptscnt].length = 0;
                   1353:        lookup->ednsopts[lookup->ednsoptscnt].value = NULL;
                   1354:
                   1355:        if (value != NULL) {
                   1356:                char *buf;
                   1357:                buf = malloc(strlen(value)/2 + 1);
                   1358:                if (buf == NULL)
                   1359:                        fatal("out of memory");
                   1360:                isc_buffer_init(&b, buf, (unsigned int) strlen(value)/2 + 1);
                   1361:                result = isc_hex_decodestring(value, &b);
                   1362:                check_result(result, "isc_hex_decodestring");
                   1363:                lookup->ednsopts[lookup->ednsoptscnt].value =
                   1364:                                                 isc_buffer_base(&b);
                   1365:                lookup->ednsopts[lookup->ednsoptscnt].length =
                   1366:                                                 isc_buffer_usedlength(&b);
                   1367:        }
                   1368:
                   1369:        lookup->ednsoptscnt++;
                   1370: }
                   1371:
                   1372: /*%
                   1373:  * Add EDNS0 option record to a message.  Currently, the only supported
                   1374:  * options are UDP buffer size, the DO bit, and EDNS options
                   1375:  * (e.g., NSID, SIT, client-subnet)
                   1376:  */
                   1377: static void
                   1378: add_opt(dns_message_t *msg, uint16_t udpsize, uint16_t edns,
                   1379:        unsigned int flags, dns_ednsopt_t *opts, size_t count)
                   1380: {
                   1381:        dns_rdataset_t *rdataset = NULL;
                   1382:        isc_result_t result;
                   1383:
                   1384:        debug("add_opt()");
                   1385:        result = dns_message_buildopt(msg, &rdataset, edns, udpsize, flags,
                   1386:                                      opts, count);
                   1387:        check_result(result, "dns_message_buildopt");
                   1388:        result = dns_message_setopt(msg, rdataset);
                   1389:        check_result(result, "dns_message_setopt");
                   1390: }
                   1391:
                   1392: /*%
                   1393:  * Add a question section to a message, asking for the specified name,
                   1394:  * type, and class.
                   1395:  */
                   1396: static void
                   1397: add_question(dns_message_t *message, dns_name_t *name,
                   1398:             dns_rdataclass_t rdclass, dns_rdatatype_t rdtype)
                   1399: {
                   1400:        dns_rdataset_t *rdataset;
                   1401:        isc_result_t result;
                   1402:
                   1403:        debug("add_question()");
                   1404:        rdataset = NULL;
                   1405:        result = dns_message_gettemprdataset(message, &rdataset);
                   1406:        check_result(result, "dns_message_gettemprdataset()");
                   1407:        dns_rdataset_makequestion(rdataset, rdclass, rdtype);
                   1408:        ISC_LIST_APPEND(name->list, rdataset, link);
                   1409: }
                   1410:
                   1411: /*%
                   1412:  * Check if we're done with all the queued lookups, which is true iff
                   1413:  * all sockets, sends, and recvs are accounted for (counters == 0),
                   1414:  * and the lookup list is empty.
                   1415:  * If we are done, pass control back out to dighost_shutdown() (which is
                   1416:  * part of dig.c, host.c, or nslookup.c) to either shutdown the system as
                   1417:  * a whole or reseed the lookup list.
                   1418:  */
                   1419: static void
                   1420: check_if_done(void) {
                   1421:        debug("check_if_done()");
                   1422:        debug("list %s", ISC_LIST_EMPTY(lookup_list) ? "empty" : "full");
                   1423:        if (ISC_LIST_EMPTY(lookup_list) && current_lookup == NULL &&
                   1424:            sendcount == 0) {
                   1425:                INSIST(sockcount == 0);
                   1426:                INSIST(recvcount == 0);
                   1427:                debug("shutting down");
                   1428:                dighost_shutdown();
                   1429:        }
                   1430: }
                   1431:
                   1432: /*%
                   1433:  * Clear out a query when we're done with it.  WARNING: This routine
                   1434:  * WILL invalidate the query pointer.
                   1435:  */
                   1436: static void
                   1437: clear_query(dig_query_t *query) {
                   1438:        dig_lookup_t *lookup;
                   1439:
                   1440:        REQUIRE(query != NULL);
                   1441:
                   1442:        debug("clear_query(%p)", query);
                   1443:
                   1444:        if (query->timer != NULL)
                   1445:                isc_timer_detach(&query->timer);
                   1446:        lookup = query->lookup;
                   1447:
                   1448:        if (lookup->current_query == query)
                   1449:                lookup->current_query = NULL;
                   1450:
                   1451:        if (ISC_LINK_LINKED(query, link))
                   1452:                ISC_LIST_UNLINK(lookup->q, query, link);
                   1453:        if (ISC_LINK_LINKED(query, clink))
                   1454:                ISC_LIST_UNLINK(lookup->connecting, query, clink);
                   1455:        if (ISC_LINK_LINKED(&query->recvbuf, link))
                   1456:                ISC_LIST_DEQUEUE(query->recvlist, &query->recvbuf,
                   1457:                                 link);
                   1458:        if (ISC_LINK_LINKED(&query->lengthbuf, link))
                   1459:                ISC_LIST_DEQUEUE(query->lengthlist, &query->lengthbuf,
                   1460:                                 link);
                   1461:        INSIST(query->recvspace != NULL);
                   1462:
                   1463:        if (query->sock != NULL) {
                   1464:                isc_socket_detach(&query->sock);
                   1465:                sockcount--;
                   1466:                debug("sockcount=%d", sockcount);
                   1467:        }
                   1468:        free(query->recvspace);
                   1469:        isc_buffer_invalidate(&query->recvbuf);
                   1470:        isc_buffer_invalidate(&query->lengthbuf);
                   1471:        if (query->waiting_senddone)
1.29      florian  1472:                query->pending_free = 1;
1.1       florian  1473:        else
                   1474:                free(query);
                   1475: }
                   1476:
                   1477: /*%
1.29      florian  1478:  * Try and clear out a lookup if we're done with it.  Return 1 if
                   1479:  * the lookup was successfully cleared.  If 1 is returned, the
1.1       florian  1480:  * lookup pointer has been invalidated.
                   1481:  */
1.29      florian  1482: static int
1.1       florian  1483: try_clear_lookup(dig_lookup_t *lookup) {
                   1484:        dig_query_t *q;
                   1485:
                   1486:        REQUIRE(lookup != NULL);
                   1487:
                   1488:        debug("try_clear_lookup(%p)", lookup);
                   1489:
                   1490:        if (ISC_LIST_HEAD(lookup->q) != NULL ||
                   1491:            ISC_LIST_HEAD(lookup->connecting) != NULL)
                   1492:        {
                   1493:                if (debugging) {
                   1494:                        q = ISC_LIST_HEAD(lookup->q);
                   1495:                        while (q != NULL) {
                   1496:                                debug("query to %s still pending", q->servname);
                   1497:                                q = ISC_LIST_NEXT(q, link);
                   1498:                        }
                   1499:
                   1500:                        q = ISC_LIST_HEAD(lookup->connecting);
                   1501:                        while (q != NULL) {
                   1502:                                debug("query to %s still connecting",
                   1503:                                      q->servname);
                   1504:                                q = ISC_LIST_NEXT(q, clink);
                   1505:                        }
                   1506:                }
1.29      florian  1507:                return (0);
1.1       florian  1508:        }
                   1509:
                   1510:        /*
                   1511:         * At this point, we know there are no queries on the lookup,
                   1512:         * so can make it go away also.
                   1513:         */
                   1514:        destroy_lookup(lookup);
1.29      florian  1515:        return (1);
1.1       florian  1516: }
                   1517:
                   1518: void
                   1519: destroy_lookup(dig_lookup_t *lookup) {
                   1520:        dig_server_t *s;
                   1521:        void *ptr;
                   1522:
                   1523:        debug("destroy");
                   1524:        s = ISC_LIST_HEAD(lookup->my_server_list);
                   1525:        while (s != NULL) {
                   1526:                debug("freeing server %p belonging to %p", s, lookup);
                   1527:                ptr = s;
                   1528:                s = ISC_LIST_NEXT(s, link);
                   1529:                ISC_LIST_DEQUEUE(lookup->my_server_list,
                   1530:                                 (dig_server_t *)ptr, link);
                   1531:                free(ptr);
                   1532:        }
                   1533:        if (lookup->sendmsg != NULL)
                   1534:                dns_message_destroy(&lookup->sendmsg);
                   1535:        if (lookup->querysig != NULL) {
                   1536:                debug("freeing buffer %p", lookup->querysig);
                   1537:                isc_buffer_free(&lookup->querysig);
                   1538:        }
                   1539:        if (lookup->sendspace != NULL)
                   1540:                free(lookup->sendspace);
                   1541:
                   1542:        if (lookup->tsigctx != NULL)
                   1543:                dst_context_destroy(&lookup->tsigctx);
                   1544:
                   1545:        if (lookup->ecs_addr != NULL)
                   1546:                free(lookup->ecs_addr);
                   1547:
                   1548:        if (lookup->ednsopts != NULL) {
                   1549:                size_t i;
                   1550:                for (i = 0; i < EDNSOPT_OPTIONS; i++) {
                   1551:                        if (lookup->ednsopts[i].value != NULL)
                   1552:                                free(lookup->ednsopts[i].value);
                   1553:                }
                   1554:                free(lookup->ednsopts);
                   1555:        }
                   1556:
                   1557:        free(lookup);
                   1558: }
                   1559:
                   1560: /*%
                   1561:  * If we can, start the next lookup in the queue running.
                   1562:  * This assumes that the lookup on the head of the queue hasn't been
                   1563:  * started yet.  It also removes the lookup from the head of the queue,
                   1564:  * setting the current_lookup pointer pointing to it.
                   1565:  */
                   1566: void
                   1567: start_lookup(void) {
                   1568:        debug("start_lookup()");
                   1569:        if (cancel_now)
                   1570:                return;
                   1571:
                   1572:        /*
                   1573:         * If there's a current lookup running, we really shouldn't get
                   1574:         * here.
                   1575:         */
                   1576:        INSIST(current_lookup == NULL);
                   1577:
                   1578:        current_lookup = ISC_LIST_HEAD(lookup_list);
                   1579:        /*
                   1580:         * Put the current lookup somewhere so cancel_all can find it
                   1581:         */
                   1582:        if (current_lookup != NULL) {
                   1583:                ISC_LIST_DEQUEUE(lookup_list, current_lookup, link);
                   1584:                if (setup_lookup(current_lookup))
                   1585:                        do_lookup(current_lookup);
                   1586:                else if (next_origin(current_lookup))
                   1587:                        check_next_lookup(current_lookup);
                   1588:        } else {
                   1589:                check_if_done();
                   1590:        }
                   1591: }
                   1592:
                   1593: /*%
                   1594:  * If we can, clear the current lookup and start the next one running.
                   1595:  * This calls try_clear_lookup, so may invalidate the lookup pointer.
                   1596:  */
                   1597: static void
                   1598: check_next_lookup(dig_lookup_t *lookup) {
                   1599:
                   1600:        INSIST(!free_now);
                   1601:
                   1602:        debug("check_next_lookup(%p)", lookup);
                   1603:
                   1604:        if (ISC_LIST_HEAD(lookup->q) != NULL) {
                   1605:                debug("still have a worker");
                   1606:                return;
                   1607:        }
                   1608:        if (try_clear_lookup(lookup)) {
                   1609:                current_lookup = NULL;
                   1610:                start_lookup();
                   1611:        }
                   1612: }
                   1613:
                   1614: /*%
                   1615:  * Create and queue a new lookup as a followup to the current lookup,
                   1616:  * based on the supplied message and section.  This is used in trace and
                   1617:  * name server search modes to start a new lookup using servers from
                   1618:  * NS records in a reply. Returns the number of followup lookups made.
                   1619:  */
                   1620: static int
                   1621: followup_lookup(dns_message_t *msg, dig_query_t *query, dns_section_t section)
                   1622: {
                   1623:        dig_lookup_t *lookup = NULL;
                   1624:        dig_server_t *srv = NULL;
                   1625:        dns_rdataset_t *rdataset = NULL;
                   1626:        dns_rdata_t rdata = DNS_RDATA_INIT;
                   1627:        dns_name_t *name = NULL;
                   1628:        isc_result_t result;
1.29      florian  1629:        int success = 0;
1.1       florian  1630:        int numLookups = 0;
                   1631:        int num;
                   1632:        isc_result_t lresult, addresses_result;
                   1633:        char bad_namestr[DNS_NAME_FORMATSIZE];
                   1634:        dns_name_t *domain;
1.29      florian  1635:        int horizontal = 0, bad = 0;
1.1       florian  1636:
                   1637:        INSIST(!free_now);
                   1638:
                   1639:        debug("following up %s", query->lookup->textname);
                   1640:
                   1641:        addresses_result = ISC_R_SUCCESS;
                   1642:        bad_namestr[0] = '\0';
                   1643:        for (result = dns_message_firstname(msg, section);
                   1644:             result == ISC_R_SUCCESS;
                   1645:             result = dns_message_nextname(msg, section)) {
                   1646:                name = NULL;
                   1647:                dns_message_currentname(msg, section, &name);
                   1648:
                   1649:                if (section == DNS_SECTION_AUTHORITY) {
                   1650:                        rdataset = NULL;
                   1651:                        result = dns_message_findtype(name, dns_rdatatype_soa,
                   1652:                                                      0, &rdataset);
                   1653:                        if (result == ISC_R_SUCCESS)
                   1654:                                return (0);
                   1655:                }
                   1656:                rdataset = NULL;
                   1657:                result = dns_message_findtype(name, dns_rdatatype_ns, 0,
                   1658:                                              &rdataset);
                   1659:                if (result != ISC_R_SUCCESS)
                   1660:                        continue;
                   1661:
                   1662:                debug("found NS set");
                   1663:
                   1664:                if (query->lookup->trace && !query->lookup->trace_root) {
                   1665:                        dns_namereln_t namereln;
                   1666:                        unsigned int nlabels;
                   1667:                        int order;
                   1668:
                   1669:                        domain = dns_fixedname_name(&query->lookup->fdomain);
                   1670:                        namereln = dns_name_fullcompare(name, domain,
                   1671:                                                        &order, &nlabels);
                   1672:                        if (namereln == dns_namereln_equal) {
                   1673:                                if (!horizontal)
                   1674:                                        printf(";; BAD (HORIZONTAL) REFERRAL\n");
1.29      florian  1675:                                horizontal = 1;
1.1       florian  1676:                        } else if (namereln != dns_namereln_subdomain) {
                   1677:                                if (!bad)
                   1678:                                        printf(";; BAD REFERRAL\n");
1.29      florian  1679:                                bad = 1;
1.1       florian  1680:                                continue;
                   1681:                        }
                   1682:                }
                   1683:
                   1684:                for (result = dns_rdataset_first(rdataset);
                   1685:                     result == ISC_R_SUCCESS;
                   1686:                     result = dns_rdataset_next(rdataset)) {
                   1687:                        char namestr[DNS_NAME_FORMATSIZE];
                   1688:                        dns_rdata_ns_t ns;
                   1689:
                   1690:                        if (query->lookup->trace_root &&
                   1691:                            query->lookup->nsfound >= MXSERV)
                   1692:                                break;
                   1693:
                   1694:                        dns_rdataset_current(rdataset, &rdata);
                   1695:
                   1696:                        query->lookup->nsfound++;
1.21      florian  1697:                        result = dns_rdata_tostruct_ns(&rdata, &ns);
                   1698:                        check_result(result, "dns_rdata_tostruct_ns");
1.1       florian  1699:                        dns_name_format(&ns.name, namestr, sizeof(namestr));
1.19      florian  1700:                        dns_rdata_freestruct_ns(&ns);
1.1       florian  1701:
                   1702:                        /* Initialize lookup if we've not yet */
                   1703:                        debug("found NS %s", namestr);
                   1704:                        if (!success) {
1.29      florian  1705:                                success = 1;
1.1       florian  1706:                                lookup_counter++;
                   1707:                                lookup = requeue_lookup(query->lookup,
1.29      florian  1708:                                                        0);
1.1       florian  1709:                                cancel_lookup(query->lookup);
1.29      florian  1710:                                lookup->doing_xfr = 0;
1.1       florian  1711:                                if (!lookup->trace_root &&
                   1712:                                    section == DNS_SECTION_ANSWER)
1.29      florian  1713:                                        lookup->trace = 0;
1.1       florian  1714:                                else
                   1715:                                        lookup->trace = query->lookup->trace;
                   1716:                                lookup->ns_search_only =
                   1717:                                        query->lookup->ns_search_only;
1.29      florian  1718:                                lookup->trace_root = 0;
1.1       florian  1719:                                if (lookup->ns_search_only)
1.29      florian  1720:                                        lookup->recurse = 0;
1.1       florian  1721:                                domain = dns_fixedname_name(&lookup->fdomain);
                   1722:                                dns_name_copy(name, domain, NULL);
                   1723:                        }
                   1724:                        debug("adding server %s", namestr);
                   1725:                        num = getaddresses(lookup, namestr, &lresult);
                   1726:                        if (lresult != ISC_R_SUCCESS) {
                   1727:                                printf("couldn't get address for '%s': %s\n",
                   1728:                                       namestr, isc_result_totext(lresult));
                   1729:                                if (addresses_result == ISC_R_SUCCESS) {
                   1730:                                        addresses_result = lresult;
                   1731:                                        strlcpy(bad_namestr, namestr,
                   1732:                                                sizeof(bad_namestr));
                   1733:                                }
                   1734:                        }
                   1735:                        numLookups += num;
                   1736:                        dns_rdata_reset(&rdata);
                   1737:                }
                   1738:        }
                   1739:        if (numLookups == 0 && addresses_result != ISC_R_SUCCESS) {
                   1740:                fatal("couldn't get address for '%s': %s",
                   1741:                      bad_namestr, isc_result_totext(result));
                   1742:        }
                   1743:
                   1744:        if (lookup == NULL &&
                   1745:            section == DNS_SECTION_ANSWER &&
                   1746:            (query->lookup->trace || query->lookup->ns_search_only))
                   1747:                return (followup_lookup(msg, query, DNS_SECTION_AUTHORITY));
                   1748:
                   1749:        /*
                   1750:         * Randomize the order the nameserver will be tried.
                   1751:         */
                   1752:        if (numLookups > 1) {
                   1753:                uint32_t i, j;
                   1754:                dig_serverlist_t my_server_list;
                   1755:                dig_server_t *next;
                   1756:
                   1757:                ISC_LIST_INIT(my_server_list);
                   1758:
                   1759:                i = numLookups;
                   1760:                for (srv = ISC_LIST_HEAD(lookup->my_server_list);
                   1761:                     srv != NULL;
                   1762:                     srv = ISC_LIST_HEAD(lookup->my_server_list)) {
                   1763:                        INSIST(i > 0);
                   1764:                        j = arc4random_uniform(i);
                   1765:                        next = ISC_LIST_NEXT(srv, link);
                   1766:                        while (j-- > 0 && next != NULL) {
                   1767:                                srv = next;
                   1768:                                next = ISC_LIST_NEXT(srv, link);
                   1769:                        }
                   1770:                        ISC_LIST_DEQUEUE(lookup->my_server_list, srv, link);
                   1771:                        ISC_LIST_APPEND(my_server_list, srv, link);
                   1772:                        i--;
                   1773:                }
                   1774:                ISC_LIST_APPENDLIST(lookup->my_server_list,
                   1775:                                    my_server_list, link);
                   1776:        }
                   1777:
                   1778:        return (numLookups);
                   1779: }
                   1780:
                   1781: /*%
                   1782:  * Create and queue a new lookup using the next origin from the search
                   1783:  * list, read in setup_system().
                   1784:  *
1.29      florian  1785:  * Return 1 iff there was another searchlist entry.
1.1       florian  1786:  */
1.29      florian  1787: static int
1.1       florian  1788: next_origin(dig_lookup_t *oldlookup) {
                   1789:        dig_lookup_t *newlookup;
                   1790:        dig_searchlist_t *search;
                   1791:        dns_fixedname_t fixed;
                   1792:        dns_name_t *name;
                   1793:        isc_result_t result;
                   1794:
                   1795:        INSIST(!free_now);
                   1796:
                   1797:        debug("next_origin()");
                   1798:        debug("following up %s", oldlookup->textname);
                   1799:
                   1800:        if (!usesearch)
                   1801:                /*
                   1802:                 * We're not using a search list, so don't even think
                   1803:                 * about finding the next entry.
                   1804:                 */
1.29      florian  1805:                return (0);
1.1       florian  1806:
                   1807:        /*
                   1808:         * Check for a absolute name or ndots being met.
                   1809:         */
                   1810:        dns_fixedname_init(&fixed);
                   1811:        name = dns_fixedname_name(&fixed);
                   1812:        result = dns_name_fromstring2(name, oldlookup->textname, NULL, 0);
                   1813:        if (result == ISC_R_SUCCESS &&
                   1814:            (dns_name_isabsolute(name) ||
                   1815:             (int)dns_name_countlabels(name) > ndots))
1.29      florian  1816:                return (0);
1.1       florian  1817:
                   1818:        if (oldlookup->origin == NULL && !oldlookup->need_search)
                   1819:                /*
                   1820:                 * Then we just did rootorg; there's nothing left.
                   1821:                 */
1.29      florian  1822:                return (0);
1.1       florian  1823:        if (oldlookup->origin == NULL && oldlookup->need_search) {
1.29      florian  1824:                newlookup = requeue_lookup(oldlookup, 1);
1.1       florian  1825:                newlookup->origin = ISC_LIST_HEAD(search_list);
1.29      florian  1826:                newlookup->need_search = 0;
1.1       florian  1827:        } else {
                   1828:                search = ISC_LIST_NEXT(oldlookup->origin, link);
                   1829:                if (search == NULL && oldlookup->done_as_is)
1.29      florian  1830:                        return (0);
                   1831:                newlookup = requeue_lookup(oldlookup, 1);
1.1       florian  1832:                newlookup->origin = search;
                   1833:        }
                   1834:        cancel_lookup(oldlookup);
1.29      florian  1835:        return (1);
1.1       florian  1836: }
                   1837:
                   1838: /*%
                   1839:  * Insert an SOA record into the sendmessage in a lookup.  Used for
                   1840:  * creating IXFR queries.
                   1841:  */
                   1842: static void
                   1843: insert_soa(dig_lookup_t *lookup) {
                   1844:        isc_result_t result;
                   1845:        dns_rdata_soa_t soa;
                   1846:        dns_rdata_t *rdata = NULL;
                   1847:        dns_rdatalist_t *rdatalist = NULL;
                   1848:        dns_rdataset_t *rdataset = NULL;
                   1849:        dns_name_t *soaname = NULL;
                   1850:
                   1851:        debug("insert_soa()");
                   1852:        soa.serial = lookup->ixfr_serial;
                   1853:        soa.refresh = 0;
                   1854:        soa.retry = 0;
                   1855:        soa.expire = 0;
                   1856:        soa.minimum = 0;
                   1857:        soa.common.rdclass = lookup->rdclass;
                   1858:        soa.common.rdtype = dns_rdatatype_soa;
                   1859:
                   1860:        dns_name_init(&soa.origin, NULL);
                   1861:        dns_name_init(&soa.contact, NULL);
                   1862:
                   1863:        dns_name_clone(dns_rootname, &soa.origin);
                   1864:        dns_name_clone(dns_rootname, &soa.contact);
                   1865:
                   1866:        isc_buffer_init(&lookup->rdatabuf, lookup->rdatastore,
                   1867:                        sizeof(lookup->rdatastore));
                   1868:
                   1869:        result = dns_message_gettemprdata(lookup->sendmsg, &rdata);
                   1870:        check_result(result, "dns_message_gettemprdata");
                   1871:
1.20      florian  1872:        result = dns_rdata_fromstruct_soa(rdata, lookup->rdclass,
1.1       florian  1873:                                      dns_rdatatype_soa, &soa,
                   1874:                                      &lookup->rdatabuf);
1.20      florian  1875:        check_result(result, "isc_rdata_fromstruct_soa");
1.1       florian  1876:
                   1877:        result = dns_message_gettemprdatalist(lookup->sendmsg, &rdatalist);
                   1878:        check_result(result, "dns_message_gettemprdatalist");
                   1879:
                   1880:        result = dns_message_gettemprdataset(lookup->sendmsg, &rdataset);
                   1881:        check_result(result, "dns_message_gettemprdataset");
                   1882:
                   1883:        dns_rdatalist_init(rdatalist);
                   1884:        rdatalist->type = dns_rdatatype_soa;
                   1885:        rdatalist->rdclass = lookup->rdclass;
                   1886:        ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
                   1887:
                   1888:        dns_rdatalist_tordataset(rdatalist, rdataset);
                   1889:
                   1890:        result = dns_message_gettempname(lookup->sendmsg, &soaname);
                   1891:        check_result(result, "dns_message_gettempname");
                   1892:        dns_name_init(soaname, NULL);
                   1893:        dns_name_clone(lookup->name, soaname);
                   1894:        ISC_LIST_INIT(soaname->list);
                   1895:        ISC_LIST_APPEND(soaname->list, rdataset, link);
                   1896:        dns_message_addname(lookup->sendmsg, soaname, DNS_SECTION_AUTHORITY);
                   1897: }
                   1898:
                   1899: static void
                   1900: compute_cookie(unsigned char *clientcookie, size_t len) {
                   1901:        /* XXXMPA need to fix, should be per server. */
                   1902:        INSIST(len >= 8U);
                   1903:        memmove(clientcookie, cookie_secret, 8);
                   1904: }
                   1905:
1.5       florian  1906: #define nitems(_a) (sizeof((_a)) / sizeof((_a)[0]))
                   1907: static void
1.14      jung     1908: populate_root_hints(void)
1.5       florian  1909: {
                   1910:        dig_server_t *newsrv;
                   1911:        size_t i;
                   1912:
                   1913:        if (!ISC_LIST_EMPTY(root_hints_server_list))
                   1914:                return;
                   1915:
                   1916:        for (i = 0; i < nitems(root_hints); i++) {
                   1917:                if (!have_ipv4 && root_hints[i].af == AF_INET)
                   1918:                        continue;
                   1919:                if (!have_ipv6 && root_hints[i].af == AF_INET6)
                   1920:                        continue;
                   1921:                newsrv = make_server(root_hints[i].ns, root_hints[i].ns);
                   1922:                ISC_LINK_INIT(newsrv, link);
                   1923:                ISC_LIST_ENQUEUE(root_hints_server_list, newsrv, link);
                   1924:        }
                   1925: }
                   1926: #undef nitems
                   1927:
1.1       florian  1928: /*%
                   1929:  * Setup the supplied lookup structure, making it ready to start sending
                   1930:  * queries to servers.  Create and initialize the message to be sent as
                   1931:  * well as the query structures and buffer space for the replies.  If the
                   1932:  * server list is empty, clone it from the system default list.
                   1933:  */
1.29      florian  1934: int
1.1       florian  1935: setup_lookup(dig_lookup_t *lookup) {
                   1936:        isc_result_t result;
                   1937:        uint32_t id;
                   1938:        unsigned int len;
                   1939:        dig_server_t *serv;
                   1940:        dig_query_t *query;
                   1941:        isc_buffer_t b;
                   1942:        dns_compress_t cctx;
                   1943:        char store[MXNAME];
                   1944:        char ecsbuf[20];
                   1945:        char sitbuf[256];
                   1946:
                   1947:        REQUIRE(lookup != NULL);
                   1948:        INSIST(!free_now);
                   1949:
                   1950:        debug("setup_lookup(%p)", lookup);
                   1951:
                   1952:        result = dns_message_create(DNS_MESSAGE_INTENTRENDER,
                   1953:                                    &lookup->sendmsg);
                   1954:        check_result(result, "dns_message_create");
                   1955:
                   1956:        if (lookup->new_search) {
                   1957:                debug("resetting lookup counter.");
                   1958:                lookup_counter = 0;
                   1959:        }
                   1960:
                   1961:        if (ISC_LIST_EMPTY(lookup->my_server_list)) {
1.5       florian  1962:                if (lookup->trace && lookup->trace_root) {
                   1963:                        populate_root_hints();
                   1964:                        clone_server_list(root_hints_server_list,
                   1965:                            &lookup->my_server_list);
                   1966:                } else {
                   1967:                        debug("cloning server list");
                   1968:                        clone_server_list(server_list,
                   1969:                            &lookup->my_server_list);
                   1970:                }
1.1       florian  1971:        }
                   1972:        result = dns_message_gettempname(lookup->sendmsg, &lookup->name);
                   1973:        check_result(result, "dns_message_gettempname");
                   1974:        dns_name_init(lookup->name, NULL);
                   1975:
                   1976:        isc_buffer_init(&lookup->namebuf, lookup->name_space,
                   1977:                        sizeof(lookup->name_space));
                   1978:        isc_buffer_init(&lookup->onamebuf, lookup->oname_space,
                   1979:                        sizeof(lookup->oname_space));
                   1980:
                   1981:        /*
                   1982:         * If the name has too many dots, force the origin to be NULL
                   1983:         * (which produces an absolute lookup).  Otherwise, take the origin
                   1984:         * we have if there's one in the struct already.  If it's NULL,
                   1985:         * take the first entry in the searchlist iff either usesearch
                   1986:         * is TRUE or we got a domain line in the resolv.conf file.
                   1987:         */
                   1988:        if (lookup->new_search) {
                   1989:                if ((count_dots(lookup->textname) >= ndots) || !usesearch) {
                   1990:                        lookup->origin = NULL; /* Force abs lookup */
1.29      florian  1991:                        lookup->done_as_is = 1;
1.1       florian  1992:                        lookup->need_search = usesearch;
                   1993:                } else if (lookup->origin == NULL && usesearch) {
                   1994:                        lookup->origin = ISC_LIST_HEAD(search_list);
1.29      florian  1995:                        lookup->need_search = 0;
1.1       florian  1996:                }
                   1997:        }
                   1998:
                   1999:        if (lookup->origin != NULL) {
                   2000:                debug("trying origin %s", lookup->origin->origin);
                   2001:                result = dns_message_gettempname(lookup->sendmsg,
                   2002:                                                 &lookup->oname);
                   2003:                check_result(result, "dns_message_gettempname");
                   2004:                dns_name_init(lookup->oname, NULL);
                   2005:                /* XXX Helper funct to conv char* to name? */
                   2006:                len = (unsigned int) strlen(lookup->origin->origin);
                   2007:                isc_buffer_init(&b, lookup->origin->origin, len);
                   2008:                isc_buffer_add(&b, len);
                   2009:                result = dns_name_fromtext(lookup->oname, &b, dns_rootname,
                   2010:                                           0, &lookup->onamebuf);
                   2011:                if (result != ISC_R_SUCCESS) {
                   2012:                        dns_message_puttempname(lookup->sendmsg,
                   2013:                                                &lookup->name);
                   2014:                        dns_message_puttempname(lookup->sendmsg,
                   2015:                                                &lookup->oname);
                   2016:                        fatal("'%s' is not in legal name syntax (%s)",
                   2017:                              lookup->origin->origin,
                   2018:                              isc_result_totext(result));
                   2019:                }
                   2020:                if (lookup->trace && lookup->trace_root) {
                   2021:                        dns_name_clone(dns_rootname, lookup->name);
                   2022:                } else {
                   2023:                        dns_fixedname_t fixed;
                   2024:                        dns_name_t *name;
                   2025:
                   2026:                        dns_fixedname_init(&fixed);
                   2027:                        name = dns_fixedname_name(&fixed);
                   2028:                        len = (unsigned int) strlen(lookup->textname);
                   2029:                        isc_buffer_init(&b, lookup->textname, len);
                   2030:                        isc_buffer_add(&b, len);
                   2031:                        result = dns_name_fromtext(name, &b, NULL, 0, NULL);
                   2032:                        if (result == ISC_R_SUCCESS &&
                   2033:                            !dns_name_isabsolute(name))
                   2034:                                result = dns_name_concatenate(name,
                   2035:                                                              lookup->oname,
                   2036:                                                              lookup->name,
                   2037:                                                              &lookup->namebuf);
                   2038:                        else if (result == ISC_R_SUCCESS)
                   2039:                                result = dns_name_copy(name, lookup->name,
                   2040:                                                       &lookup->namebuf);
                   2041:                        if (result != ISC_R_SUCCESS) {
                   2042:                                dns_message_puttempname(lookup->sendmsg,
                   2043:                                                        &lookup->name);
                   2044:                                dns_message_puttempname(lookup->sendmsg,
                   2045:                                                        &lookup->oname);
                   2046:                                if (result == DNS_R_NAMETOOLONG)
1.29      florian  2047:                                        return (0);
1.1       florian  2048:                                fatal("'%s' is not in legal name syntax (%s)",
                   2049:                                      lookup->textname,
                   2050:                                      isc_result_totext(result));
                   2051:                        }
                   2052:                }
                   2053:                dns_message_puttempname(lookup->sendmsg, &lookup->oname);
                   2054:        } else
                   2055:        {
                   2056:                debug("using root origin");
                   2057:                if (lookup->trace && lookup->trace_root)
                   2058:                        dns_name_clone(dns_rootname, lookup->name);
                   2059:                else {
                   2060:                        len = (unsigned int) strlen(lookup->textname);
                   2061:                        isc_buffer_init(&b, lookup->textname, len);
                   2062:                        isc_buffer_add(&b, len);
                   2063:                        result = dns_name_fromtext(lookup->name, &b,
                   2064:                                                   dns_rootname, 0,
                   2065:                                                   &lookup->namebuf);
                   2066:                }
                   2067:                if (result != ISC_R_SUCCESS) {
                   2068:                        dns_message_puttempname(lookup->sendmsg,
                   2069:                                                &lookup->name);
                   2070:                        fatal("'%s' is not a legal name "
                   2071:                              "(%s)", lookup->textname,
                   2072:                              isc_result_totext(result));
                   2073:                }
                   2074:        }
                   2075:        dns_name_format(lookup->name, store, sizeof(store));
                   2076:        dighost_trying(store, lookup);
                   2077:        INSIST(dns_name_isabsolute(lookup->name));
                   2078:
                   2079:        id = arc4random();
                   2080:        lookup->sendmsg->id = (unsigned short)id & 0xFFFF;
                   2081:        lookup->sendmsg->opcode = lookup->opcode;
                   2082:        lookup->msgcounter = 0;
                   2083:        /*
                   2084:         * If this is a trace request, completely disallow recursion, since
                   2085:         * it's meaningless for traces.
                   2086:         */
                   2087:        if (lookup->trace || (lookup->ns_search_only && !lookup->trace_root))
1.29      florian  2088:                lookup->recurse = 0;
1.1       florian  2089:
                   2090:        if (lookup->recurse &&
                   2091:            lookup->rdtype != dns_rdatatype_axfr &&
                   2092:            lookup->rdtype != dns_rdatatype_ixfr) {
                   2093:                debug("recursive query");
                   2094:                lookup->sendmsg->flags |= DNS_MESSAGEFLAG_RD;
                   2095:        }
                   2096:
                   2097:        /* XXX aaflag */
                   2098:        if (lookup->aaonly) {
                   2099:                debug("AA query");
                   2100:                lookup->sendmsg->flags |= DNS_MESSAGEFLAG_AA;
                   2101:        }
                   2102:
                   2103:        if (lookup->adflag) {
                   2104:                debug("AD query");
                   2105:                lookup->sendmsg->flags |= DNS_MESSAGEFLAG_AD;
                   2106:        }
                   2107:
                   2108:        if (lookup->cdflag) {
                   2109:                debug("CD query");
                   2110:                lookup->sendmsg->flags |= DNS_MESSAGEFLAG_CD;
                   2111:        }
                   2112:
                   2113:        dns_message_addname(lookup->sendmsg, lookup->name,
                   2114:                            DNS_SECTION_QUESTION);
                   2115:
                   2116:        if (lookup->trace && lookup->trace_root) {
                   2117:                lookup->qrdtype = lookup->rdtype;
                   2118:                lookup->rdtype = dns_rdatatype_ns;
                   2119:        }
                   2120:
                   2121:        if ((lookup->rdtype == dns_rdatatype_axfr) ||
                   2122:            (lookup->rdtype == dns_rdatatype_ixfr)) {
                   2123:                /*
                   2124:                 * Force TCP mode if we're doing an axfr.
                   2125:                 */
                   2126:                if (lookup->rdtype == dns_rdatatype_axfr) {
1.29      florian  2127:                        lookup->doing_xfr = 1;
                   2128:                        lookup->tcp_mode = 1;
1.1       florian  2129:                } else if (lookup->tcp_mode) {
1.29      florian  2130:                        lookup->doing_xfr = 1;
1.1       florian  2131:                }
                   2132:        }
                   2133:
                   2134:        add_question(lookup->sendmsg, lookup->name, lookup->rdclass,
                   2135:                     lookup->rdtype);
                   2136:
                   2137:        /* add_soa */
                   2138:        if (lookup->rdtype == dns_rdatatype_ixfr)
                   2139:                insert_soa(lookup);
                   2140:
                   2141:        /* XXX Insist this? */
                   2142:        lookup->tsigctx = NULL;
                   2143:        lookup->querysig = NULL;
                   2144:        if (tsigkey != NULL) {
                   2145:                debug("initializing keys");
                   2146:                result = dns_message_settsigkey(lookup->sendmsg, tsigkey);
                   2147:                check_result(result, "dns_message_settsigkey");
                   2148:        }
                   2149:
                   2150:        lookup->sendspace = malloc(COMMSIZE);
                   2151:        if (lookup->sendspace == NULL)
                   2152:                fatal("memory allocation failure");
                   2153:
                   2154:        result = dns_compress_init(&cctx, -1);
                   2155:        check_result(result, "dns_compress_init");
                   2156:
                   2157:        debug("starting to render the message");
                   2158:        isc_buffer_init(&lookup->renderbuf, lookup->sendspace, COMMSIZE);
                   2159:        result = dns_message_renderbegin(lookup->sendmsg, &cctx,
                   2160:                                         &lookup->renderbuf);
                   2161:        check_result(result, "dns_message_renderbegin");
                   2162:        if (lookup->udpsize > 0 || lookup->dnssec ||
                   2163:            lookup->edns > -1 || lookup->ecs_addr != NULL)
                   2164:        {
                   2165: #define MAXOPTS (EDNSOPT_OPTIONS + DNS_EDNSOPTIONS)
                   2166:                dns_ednsopt_t opts[MAXOPTS];
                   2167:                unsigned int flags;
                   2168:                unsigned int i = 0;
                   2169:
                   2170:                if (lookup->udpsize == 0)
                   2171:                        lookup->udpsize = 4096;
                   2172:                if (lookup->edns < 0)
                   2173:                        lookup->edns = 0;
                   2174:
                   2175:                if (lookup->nsid) {
                   2176:                        INSIST(i < MAXOPTS);
                   2177:                        opts[i].code = DNS_OPT_NSID;
                   2178:                        opts[i].length = 0;
                   2179:                        opts[i].value = NULL;
                   2180:                        i++;
                   2181:                }
                   2182:
                   2183:                if (lookup->ecs_addr != NULL) {
                   2184:                        uint8_t addr[16];
                   2185:                        uint16_t family;
                   2186:                        uint32_t plen;
                   2187:                        struct sockaddr *sa;
                   2188:                        struct sockaddr_in *sin;
                   2189:                        struct sockaddr_in6 *sin6;
                   2190:                        size_t addrl;
                   2191:
                   2192:                        sa = &lookup->ecs_addr->type.sa;
1.33    ! florian  2193:                        plen = lookup->ecs_plen;
1.1       florian  2194:
                   2195:                        /* Round up prefix len to a multiple of 8 */
                   2196:                        addrl = (plen + 7) / 8;
                   2197:
                   2198:                        INSIST(i < MAXOPTS);
                   2199:                        opts[i].code = DNS_OPT_CLIENT_SUBNET;
                   2200:                        opts[i].length = (uint16_t) addrl + 4;
                   2201:                        check_result(result, "isc_buffer_allocate");
                   2202:
                   2203:                        /*
                   2204:                         * XXXMUKS: According to RFC7871, "If there is
                   2205:                         * no ADDRESS set, i.e., SOURCE PREFIX-LENGTH is
                   2206:                         * set to 0, then FAMILY SHOULD be set to the
                   2207:                         * transport over which the query is sent."
                   2208:                         *
                   2209:                         * However, at this point we don't know what
                   2210:                         * transport(s) we'll be using, so we can't
                   2211:                         * set the value now. For now, we're using
                   2212:                         * IPv4 as the default the +subnet option
                   2213:                         * used an IPv4 prefix, or for +subnet=0,
                   2214:                         * and IPv6 if the +subnet option used an
                   2215:                         * IPv6 prefix.
                   2216:                         *
                   2217:                         * (For future work: preserve the offset into
                   2218:                         * the buffer where the family field is;
                   2219:                         * that way we can update it in send_udp()
                   2220:                         * or send_tcp_connect() once we know
                   2221:                         * what it outght to be.)
                   2222:                         */
                   2223:                        switch (sa->sa_family) {
                   2224:                        case AF_UNSPEC:
                   2225:                                INSIST(plen == 0);
                   2226:                                family = 1;
                   2227:                                break;
                   2228:                        case AF_INET:
                   2229:                                INSIST(plen <= 32);
                   2230:                                family = 1;
                   2231:                                sin = (struct sockaddr_in *) sa;
                   2232:                                memmove(addr, &sin->sin_addr, addrl);
                   2233:                                break;
                   2234:                        case AF_INET6:
                   2235:                                INSIST(plen <= 128);
                   2236:                                family = 2;
                   2237:                                sin6 = (struct sockaddr_in6 *) sa;
                   2238:                                memmove(addr, &sin6->sin6_addr, addrl);
                   2239:                                break;
                   2240:                        default:
                   2241:                                INSIST(0);
                   2242:                        }
                   2243:
                   2244:                        isc_buffer_init(&b, ecsbuf, sizeof(ecsbuf));
                   2245:                        /* family */
                   2246:                        isc_buffer_putuint16(&b, family);
                   2247:                        /* source prefix-length */
                   2248:                        isc_buffer_putuint8(&b, plen);
                   2249:                        /* scope prefix-length */
                   2250:                        isc_buffer_putuint8(&b, 0);
                   2251:
                   2252:                        /* address */
                   2253:                        if (addrl > 0) {
                   2254:                                /* Mask off last address byte */
                   2255:                                if ((plen % 8) != 0)
                   2256:                                        addr[addrl - 1] &=
                   2257:                                                ~0U << (8 - (plen % 8));
                   2258:                                isc_buffer_putmem(&b, addr,
                   2259:                                                  (unsigned)addrl);
                   2260:                        }
                   2261:
                   2262:                        opts[i].value = (uint8_t *) ecsbuf;
                   2263:                        i++;
                   2264:                }
                   2265:
                   2266:                if (lookup->sit) {
                   2267:                        INSIST(i < MAXOPTS);
                   2268:                        opts[i].code = DNS_OPT_COOKIE;
                   2269:                        if (lookup->sitvalue != NULL) {
                   2270:                                isc_buffer_init(&b, sitbuf, sizeof(sitbuf));
                   2271:                                result = isc_hex_decodestring(lookup->sitvalue,
                   2272:                                                              &b);
                   2273:                                check_result(result, "isc_hex_decodestring");
                   2274:                                opts[i].value = isc_buffer_base(&b);
                   2275:                                opts[i].length = isc_buffer_usedlength(&b);
                   2276:                        } else {
                   2277:                                compute_cookie(cookie, sizeof(cookie));
                   2278:                                opts[i].length = 8;
                   2279:                                opts[i].value = cookie;
                   2280:                        }
                   2281:                        i++;
                   2282:                }
                   2283:
                   2284:                if (lookup->expire) {
                   2285:                        INSIST(i < MAXOPTS);
                   2286:                        opts[i].code = DNS_OPT_EXPIRE;
                   2287:                        opts[i].length = 0;
                   2288:                        opts[i].value = NULL;
                   2289:                        i++;
                   2290:                }
                   2291:
                   2292:                if (lookup->ednsoptscnt != 0) {
                   2293:                        INSIST(i + lookup->ednsoptscnt <= MAXOPTS);
                   2294:                        memmove(&opts[i], lookup->ednsopts,
                   2295:                                sizeof(dns_ednsopt_t) * lookup->ednsoptscnt);
                   2296:                        i += lookup->ednsoptscnt;
                   2297:                }
                   2298:
                   2299:                flags = lookup->ednsflags;
                   2300:                flags &= ~DNS_MESSAGEEXTFLAG_DO;
                   2301:                if (lookup->dnssec)
                   2302:                        flags |= DNS_MESSAGEEXTFLAG_DO;
                   2303:                add_opt(lookup->sendmsg, lookup->udpsize,
                   2304:                        lookup->edns, flags, opts, i);
                   2305:        }
                   2306:
                   2307:        result = dns_message_rendersection(lookup->sendmsg,
1.15      florian  2308:                                           DNS_SECTION_QUESTION);
1.1       florian  2309:        check_result(result, "dns_message_rendersection");
                   2310:        result = dns_message_rendersection(lookup->sendmsg,
1.15      florian  2311:                                           DNS_SECTION_AUTHORITY);
1.1       florian  2312:        check_result(result, "dns_message_rendersection");
                   2313:        result = dns_message_renderend(lookup->sendmsg);
                   2314:        check_result(result, "dns_message_renderend");
                   2315:        debug("done rendering");
                   2316:
                   2317:        dns_compress_invalidate(&cctx);
                   2318:
                   2319:        /*
                   2320:         * Force TCP mode if the request is larger than 512 bytes.
                   2321:         */
                   2322:        if (isc_buffer_usedlength(&lookup->renderbuf) > 512)
1.29      florian  2323:                lookup->tcp_mode = 1;
1.1       florian  2324:
1.29      florian  2325:        lookup->pending = 0;
1.1       florian  2326:
                   2327:        for (serv = ISC_LIST_HEAD(lookup->my_server_list);
                   2328:             serv != NULL;
                   2329:             serv = ISC_LIST_NEXT(serv, link)) {
                   2330:                query = malloc(sizeof(dig_query_t));
                   2331:                if (query == NULL)
                   2332:                        fatal("memory allocation failure in %s:%d",
                   2333:                              __FILE__, __LINE__);
                   2334:                debug("create query %p linked to lookup %p",
                   2335:                       query, lookup);
                   2336:                query->lookup = lookup;
                   2337:                query->timer = NULL;
1.29      florian  2338:                query->waiting_connect = 0;
                   2339:                query->waiting_senddone = 0;
                   2340:                query->pending_free = 0;
                   2341:                query->recv_made = 0;
                   2342:                query->first_pass = 1;
                   2343:                query->first_soa_rcvd = 0;
                   2344:                query->second_rr_rcvd = 0;
                   2345:                query->first_repeat_rcvd = 0;
                   2346:                query->warn_id = 1;
                   2347:                query->timedout = 0;
1.1       florian  2348:                query->first_rr_serial = 0;
                   2349:                query->second_rr_serial = 0;
                   2350:                query->servname = serv->servername;
                   2351:                query->userarg = serv->userarg;
                   2352:                query->rr_count = 0;
                   2353:                query->msg_count = 0;
                   2354:                query->byte_count = 0;
1.29      florian  2355:                query->ixfr_axfr = 0;
1.1       florian  2356:                ISC_LIST_INIT(query->recvlist);
                   2357:                ISC_LIST_INIT(query->lengthlist);
                   2358:                query->sock = NULL;
                   2359:                query->recvspace = malloc(COMMSIZE);
                   2360:                if (query->recvspace == NULL)
                   2361:                        fatal("memory allocation failure");
                   2362:
                   2363:                isc_buffer_init(&query->recvbuf, query->recvspace, COMMSIZE);
                   2364:                isc_buffer_init(&query->lengthbuf, query->lengthspace, 2);
                   2365:                isc_buffer_init(&query->slbuf, query->slspace, 2);
                   2366:                query->sendbuf = lookup->renderbuf;
                   2367:
                   2368:                ISC_LINK_INIT(query, clink);
                   2369:                ISC_LINK_INIT(query, link);
                   2370:                ISC_LIST_ENQUEUE(lookup->q, query, link);
                   2371:        }
                   2372:
                   2373:        /* XXX qrflag, print_query, etc... */
                   2374:        if (!ISC_LIST_EMPTY(lookup->q) && qr) {
                   2375:                extrabytes = 0;
                   2376:                dighost_printmessage(ISC_LIST_HEAD(lookup->q), lookup->sendmsg,
1.29      florian  2377:                             1);
1.1       florian  2378:        }
1.29      florian  2379:        return (1);
1.1       florian  2380: }
                   2381:
                   2382: /*%
                   2383:  * Event handler for send completion.  Track send counter, and clear out
                   2384:  * the query if the send was canceled.
                   2385:  */
                   2386: static void
                   2387: send_done(isc_task_t *_task, isc_event_t *event) {
                   2388:        isc_socketevent_t *sevent = (isc_socketevent_t *)event;
                   2389:        isc_buffer_t *b = NULL;
                   2390:        dig_query_t *query, *next;
                   2391:        dig_lookup_t *l;
                   2392:
                   2393:        REQUIRE(event->ev_type == ISC_SOCKEVENT_SENDDONE);
                   2394:
                   2395:        UNUSED(_task);
                   2396:
                   2397:        debug("send_done()");
                   2398:        sendcount--;
                   2399:        debug("sendcount=%d", sendcount);
                   2400:        INSIST(sendcount >= 0);
                   2401:
                   2402:        for  (b = ISC_LIST_HEAD(sevent->bufferlist);
                   2403:              b != NULL;
                   2404:              b = ISC_LIST_HEAD(sevent->bufferlist)) {
                   2405:                ISC_LIST_DEQUEUE(sevent->bufferlist, b, link);
                   2406:                free(b);
                   2407:        }
                   2408:
                   2409:        query = event->ev_arg;
1.29      florian  2410:        query->waiting_senddone = 0;
1.1       florian  2411:        l = query->lookup;
                   2412:
                   2413:        if (l->ns_search_only && !l->trace_root && !l->tcp_mode) {
                   2414:                debug("sending next, since searching");
                   2415:                next = ISC_LIST_NEXT(query, link);
                   2416:                if (next != NULL)
                   2417:                        send_udp(next);
                   2418:        }
                   2419:
                   2420:        isc_event_free(&event);
                   2421:
                   2422:        if (query->pending_free)
                   2423:                free(query);
                   2424:
                   2425:        check_if_done();
                   2426: }
                   2427:
                   2428: /*%
                   2429:  * Cancel a lookup, sending isc_socket_cancel() requests to all outstanding
                   2430:  * IO sockets.  The cancel handlers should take care of cleaning up the
                   2431:  * query and lookup structures
                   2432:  */
                   2433: static void
                   2434: cancel_lookup(dig_lookup_t *lookup) {
                   2435:        dig_query_t *query, *next;
                   2436:
                   2437:        debug("cancel_lookup()");
                   2438:        query = ISC_LIST_HEAD(lookup->q);
                   2439:        while (query != NULL) {
                   2440:                next = ISC_LIST_NEXT(query, link);
                   2441:                if (query->sock != NULL) {
                   2442:                        isc_socket_cancel(query->sock, global_task,
                   2443:                                          ISC_SOCKCANCEL_ALL);
                   2444:                        check_if_done();
                   2445:                } else {
                   2446:                        clear_query(query);
                   2447:                }
                   2448:                query = next;
                   2449:        }
1.29      florian  2450:        lookup->pending = 0;
1.1       florian  2451:        lookup->retries = 0;
                   2452: }
                   2453:
                   2454: static void
                   2455: bringup_timer(dig_query_t *query, unsigned int default_timeout) {
                   2456:        dig_lookup_t *l;
                   2457:        unsigned int local_timeout;
                   2458:        isc_result_t result;
                   2459:
                   2460:        debug("bringup_timer()");
                   2461:        /*
                   2462:         * If the timer already exists, that means we're calling this
                   2463:         * a second time (for a retry).  Don't need to recreate it,
                   2464:         * just reset it.
                   2465:         */
                   2466:        l = query->lookup;
                   2467:        if (ISC_LINK_LINKED(query, link) && ISC_LIST_NEXT(query, link) != NULL)
                   2468:                local_timeout = SERVER_TIMEOUT;
                   2469:        else {
                   2470:                if (timeout == 0)
                   2471:                        local_timeout = default_timeout;
                   2472:                else
                   2473:                        local_timeout = timeout;
                   2474:        }
                   2475:        debug("have local timeout of %d", local_timeout);
1.9       florian  2476:        l->interval.tv_sec = local_timeout;
                   2477:        l->interval.tv_nsec = 0;
1.1       florian  2478:        if (query->timer != NULL)
                   2479:                isc_timer_detach(&query->timer);
1.7       florian  2480:        result = isc_timer_create(timermgr,
1.1       florian  2481:                                  &l->interval, global_task, connect_timeout,
                   2482:                                  query, &query->timer);
                   2483:        check_result(result, "isc_timer_create");
                   2484: }
                   2485:
                   2486: static void
                   2487: force_timeout(dig_query_t *query) {
                   2488:        isc_event_t *event;
                   2489:
                   2490:        debug("force_timeout ()");
                   2491:        event = isc_event_allocate(query, ISC_TIMEREVENT_IDLE,
                   2492:                                   connect_timeout, query,
                   2493:                                   sizeof(isc_event_t));
                   2494:        if (event == NULL) {
                   2495:                fatal("isc_event_allocate: %s",
                   2496:                      isc_result_totext(ISC_R_NOMEMORY));
                   2497:        }
                   2498:        isc_task_send(global_task, &event);
                   2499:
                   2500:        /*
                   2501:         * The timer may have expired if, for example, get_address() takes
                   2502:         * long time and the timer was running on a different thread.
                   2503:         * We need to cancel the possible timeout event not to confuse
                   2504:         * ourselves due to the duplicate events.
                   2505:         */
                   2506:        if (query->timer != NULL)
                   2507:                isc_timer_detach(&query->timer);
                   2508: }
                   2509:
                   2510: static void
                   2511: connect_done(isc_task_t *task, isc_event_t *event);
                   2512:
                   2513: /*%
                   2514:  * Unlike send_udp, this can't be called multiple times with the same
                   2515:  * query.  When we retry TCP, we requeue the whole lookup, which should
                   2516:  * start anew.
                   2517:  */
                   2518: static void
                   2519: send_tcp_connect(dig_query_t *query) {
                   2520:        isc_result_t result;
                   2521:        dig_query_t *next;
                   2522:        dig_lookup_t *l;
                   2523:
                   2524:        debug("send_tcp_connect(%p)", query);
                   2525:
                   2526:        l = query->lookup;
1.29      florian  2527:        query->waiting_connect = 1;
1.1       florian  2528:        query->lookup->current_query = query;
                   2529:        result = get_address(query->servname, port, &query->sockaddr);
                   2530:        if (result != ISC_R_SUCCESS) {
                   2531:                /*
                   2532:                 * This servname doesn't have an address.  Try the next server
                   2533:                 * by triggering an immediate 'timeout' (we lie, but the effect
                   2534:                 * is the same).
                   2535:                 */
                   2536:                force_timeout(query);
                   2537:                return;
                   2538:        }
                   2539:
                   2540:        if (specified_source &&
                   2541:            (isc_sockaddr_pf(&query->sockaddr) !=
                   2542:             isc_sockaddr_pf(&bind_address))) {
                   2543:                printf(";; Skipping server %s, incompatible "
                   2544:                       "address family\n", query->servname);
1.29      florian  2545:                query->waiting_connect = 0;
1.1       florian  2546:                if (ISC_LINK_LINKED(query, link))
                   2547:                        next = ISC_LIST_NEXT(query, link);
                   2548:                else
                   2549:                        next = NULL;
                   2550:                l = query->lookup;
                   2551:                clear_query(query);
                   2552:                if (next == NULL) {
                   2553:                        printf(";; No acceptable nameservers\n");
                   2554:                        check_next_lookup(l);
                   2555:                        return;
                   2556:                }
                   2557:                send_tcp_connect(next);
                   2558:                return;
                   2559:        }
                   2560:
                   2561:        INSIST(query->sock == NULL);
                   2562:
                   2563:        if (keep != NULL && isc_sockaddr_equal(&keepaddr, &query->sockaddr)) {
                   2564:                sockcount++;
                   2565:                isc_socket_attach(keep, &query->sock);
1.29      florian  2566:                query->waiting_connect = 0;
                   2567:                launch_next_query(query, 1);
1.1       florian  2568:                goto search;
                   2569:        }
                   2570:
                   2571:        result = isc_socket_create(socketmgr,
                   2572:                                   isc_sockaddr_pf(&query->sockaddr),
                   2573:                                   isc_sockettype_tcp, &query->sock);
                   2574:        check_result(result, "isc_socket_create");
                   2575:        sockcount++;
                   2576:        debug("sockcount=%d", sockcount);
                   2577:        if (specified_source)
                   2578:                result = isc_socket_bind(query->sock, &bind_address,
                   2579:                                         ISC_SOCKET_REUSEADDRESS);
                   2580:        else {
                   2581:                if ((isc_sockaddr_pf(&query->sockaddr) == AF_INET) &&
                   2582:                    have_ipv4)
                   2583:                        isc_sockaddr_any(&bind_any);
                   2584:                else
                   2585:                        isc_sockaddr_any6(&bind_any);
                   2586:                result = isc_socket_bind(query->sock, &bind_any, 0);
                   2587:        }
                   2588:        check_result(result, "isc_socket_bind");
                   2589:        bringup_timer(query, TCP_TIMEOUT);
                   2590:        result = isc_socket_connect(query->sock, &query->sockaddr,
                   2591:                                    global_task, connect_done, query);
                   2592:        check_result(result, "isc_socket_connect");
                   2593:  search:
                   2594:        /*
                   2595:         * If we're at the endgame of a nameserver search, we need to
                   2596:         * immediately bring up all the queries.  Do it here.
                   2597:         */
                   2598:        if (l->ns_search_only && !l->trace_root) {
                   2599:                debug("sending next, since searching");
                   2600:                if (ISC_LINK_LINKED(query, link)) {
                   2601:                        next = ISC_LIST_NEXT(query, link);
                   2602:                        ISC_LIST_DEQUEUE(l->q, query, link);
                   2603:                } else
                   2604:                        next = NULL;
                   2605:                ISC_LIST_ENQUEUE(l->connecting, query, clink);
                   2606:                if (next != NULL)
                   2607:                        send_tcp_connect(next);
                   2608:        }
                   2609: }
                   2610:
                   2611: static isc_buffer_t *
                   2612: clone_buffer(isc_buffer_t *source) {
                   2613:        isc_buffer_t *buffer;
                   2614:        buffer = malloc(sizeof(*buffer));
                   2615:        if (buffer == NULL)
                   2616:                fatal("memory allocation failure in %s:%d",
                   2617:                      __FILE__, __LINE__);
                   2618:        *buffer = *source;
                   2619:        return (buffer);
                   2620: }
                   2621:
                   2622: /*%
                   2623:  * Send a UDP packet to the remote nameserver, possible starting the
                   2624:  * recv action as well.  Also make sure that the timer is running and
                   2625:  * is properly reset.
                   2626:  */
                   2627: static void
                   2628: send_udp(dig_query_t *query) {
                   2629:        dig_lookup_t *l = NULL;
                   2630:        isc_result_t result;
                   2631:        isc_buffer_t *sendbuf;
                   2632:
                   2633:        debug("send_udp(%p)", query);
                   2634:
                   2635:        l = query->lookup;
                   2636:        bringup_timer(query, UDP_TIMEOUT);
                   2637:        l->current_query = query;
                   2638:        debug("working on lookup %p, query %p", query->lookup, query);
                   2639:        if (!query->recv_made) {
                   2640:                /* XXX Check the sense of this, need assertion? */
1.29      florian  2641:                query->waiting_connect = 0;
1.1       florian  2642:                result = get_address(query->servname, port, &query->sockaddr);
                   2643:                if (result != ISC_R_SUCCESS) {
                   2644:                        /* This servname doesn't have an address. */
                   2645:                        force_timeout(query);
                   2646:                        return;
                   2647:                }
                   2648:
                   2649:                result = isc_socket_create(socketmgr,
                   2650:                                           isc_sockaddr_pf(&query->sockaddr),
                   2651:                                           isc_sockettype_udp, &query->sock);
                   2652:                check_result(result, "isc_socket_create");
                   2653:                sockcount++;
                   2654:                debug("sockcount=%d", sockcount);
                   2655:                if (specified_source) {
                   2656:                        result = isc_socket_bind(query->sock, &bind_address,
                   2657:                                                 ISC_SOCKET_REUSEADDRESS);
                   2658:                } else {
                   2659:                        isc_sockaddr_anyofpf(&bind_any,
                   2660:                                        isc_sockaddr_pf(&query->sockaddr));
                   2661:                        result = isc_socket_bind(query->sock, &bind_any, 0);
                   2662:                }
                   2663:                check_result(result, "isc_socket_bind");
                   2664:
1.29      florian  2665:                query->recv_made = 1;
1.1       florian  2666:                ISC_LINK_INIT(&query->recvbuf, link);
                   2667:                ISC_LIST_ENQUEUE(query->recvlist, &query->recvbuf,
                   2668:                                 link);
                   2669:                debug("recving with lookup=%p, query=%p, sock=%p",
                   2670:                      query->lookup, query, query->sock);
                   2671:                result = isc_socket_recvv(query->sock, &query->recvlist, 1,
                   2672:                                          global_task, recv_done, query);
                   2673:                check_result(result, "isc_socket_recvv");
                   2674:                recvcount++;
                   2675:                debug("recvcount=%d", recvcount);
                   2676:        }
                   2677:        ISC_LIST_INIT(query->sendlist);
                   2678:        sendbuf = clone_buffer(&query->sendbuf);
                   2679:        ISC_LIST_ENQUEUE(query->sendlist, sendbuf, link);
                   2680:        debug("sending a request");
1.13      florian  2681:        clock_gettime(CLOCK_MONOTONIC, &query->time_sent);
1.1       florian  2682:        INSIST(query->sock != NULL);
1.29      florian  2683:        query->waiting_senddone = 1;
1.1       florian  2684:        result = isc_socket_sendtov2(query->sock, &query->sendlist,
                   2685:                                     global_task, send_done, query,
                   2686:                                     &query->sockaddr, NULL,
                   2687:                                     ISC_SOCKFLAG_NORETRY);
                   2688:        check_result(result, "isc_socket_sendtov");
                   2689:        sendcount++;
                   2690: }
                   2691:
                   2692: /*%
                   2693:  * IO timeout handler, used for both connect and recv timeouts.  If
                   2694:  * retries are still allowed, either resend the UDP packet or queue a
                   2695:  * new TCP lookup.  Otherwise, cancel the lookup.
                   2696:  */
                   2697: static void
                   2698: connect_timeout(isc_task_t *task, isc_event_t *event) {
                   2699:        dig_lookup_t *l = NULL;
                   2700:        dig_query_t *query = NULL, *cq;
                   2701:
                   2702:        UNUSED(task);
                   2703:        REQUIRE(event->ev_type == ISC_TIMEREVENT_IDLE);
                   2704:
                   2705:        debug("connect_timeout()");
                   2706:
                   2707:        query = event->ev_arg;
                   2708:        l = query->lookup;
                   2709:        isc_event_free(&event);
                   2710:
                   2711:        INSIST(!free_now);
                   2712:
                   2713:        if ((query != NULL) && (query->lookup->current_query != NULL) &&
                   2714:            ISC_LINK_LINKED(query->lookup->current_query, link) &&
                   2715:            (ISC_LIST_NEXT(query->lookup->current_query, link) != NULL)) {
                   2716:                debug("trying next server...");
                   2717:                cq = query->lookup->current_query;
                   2718:                if (!l->tcp_mode)
                   2719:                        send_udp(ISC_LIST_NEXT(cq, link));
                   2720:                else {
                   2721:                        if (query->sock != NULL)
                   2722:                                isc_socket_cancel(query->sock, NULL,
                   2723:                                                  ISC_SOCKCANCEL_ALL);
                   2724:                        send_tcp_connect(ISC_LIST_NEXT(cq, link));
                   2725:                }
                   2726:                return;
                   2727:        }
                   2728:
                   2729:        if (l->tcp_mode && query->sock != NULL) {
1.29      florian  2730:                query->timedout = 1;
1.1       florian  2731:                isc_socket_cancel(query->sock, NULL, ISC_SOCKCANCEL_ALL);
                   2732:        }
                   2733:
                   2734:        if (l->retries > 1) {
                   2735:                if (!l->tcp_mode) {
                   2736:                        l->retries--;
                   2737:                        debug("resending UDP request to first server");
                   2738:                        send_udp(ISC_LIST_HEAD(l->q));
                   2739:                } else {
                   2740:                        debug("making new TCP request, %d tries left",
                   2741:                              l->retries);
                   2742:                        l->retries--;
1.29      florian  2743:                        requeue_lookup(l, 1);
1.1       florian  2744:                        cancel_lookup(l);
                   2745:                        check_next_lookup(l);
                   2746:                }
                   2747:        } else {
                   2748:                if (!l->ns_search_only) {
                   2749:                        fputs(l->cmdline, stdout);
                   2750:                        printf(";; connection timed out; no servers could be "
                   2751:                               "reached\n");
                   2752:                }
                   2753:                cancel_lookup(l);
                   2754:                check_next_lookup(l);
                   2755:                if (exitcode < 9)
                   2756:                        exitcode = 9;
                   2757:        }
                   2758: }
                   2759:
                   2760: /*%
                   2761:  * Event handler for the TCP recv which gets the length header of TCP
                   2762:  * packets.  Start the next recv of length bytes.
                   2763:  */
                   2764: static void
                   2765: tcp_length_done(isc_task_t *task, isc_event_t *event) {
                   2766:        isc_socketevent_t *sevent;
                   2767:        isc_buffer_t *b = NULL;
                   2768:        isc_result_t result;
                   2769:        dig_query_t *query = NULL;
                   2770:        dig_lookup_t *l, *n;
                   2771:        uint16_t length;
                   2772:
                   2773:        REQUIRE(event->ev_type == ISC_SOCKEVENT_RECVDONE);
                   2774:        INSIST(!free_now);
                   2775:
                   2776:        UNUSED(task);
                   2777:
                   2778:        debug("tcp_length_done()");
                   2779:
                   2780:        sevent = (isc_socketevent_t *)event;
                   2781:        query = event->ev_arg;
                   2782:
                   2783:        recvcount--;
                   2784:        INSIST(recvcount >= 0);
                   2785:
                   2786:        b = ISC_LIST_HEAD(sevent->bufferlist);
                   2787:        INSIST(b ==  &query->lengthbuf);
                   2788:        ISC_LIST_DEQUEUE(sevent->bufferlist, b, link);
                   2789:
                   2790:        if (sevent->result == ISC_R_CANCELED) {
                   2791:                isc_event_free(&event);
                   2792:                l = query->lookup;
                   2793:                clear_query(query);
                   2794:                check_next_lookup(l);
                   2795:                return;
                   2796:        }
                   2797:        if (sevent->result != ISC_R_SUCCESS) {
                   2798:                char sockstr[ISC_SOCKADDR_FORMATSIZE];
                   2799:                isc_sockaddr_format(&query->sockaddr, sockstr,
                   2800:                                    sizeof(sockstr));
                   2801:                printf(";; communications error to %s: %s\n",
                   2802:                       sockstr, isc_result_totext(sevent->result));
                   2803:                if (keep != NULL)
                   2804:                        isc_socket_detach(&keep);
                   2805:                l = query->lookup;
                   2806:                isc_socket_detach(&query->sock);
                   2807:                sockcount--;
                   2808:                debug("sockcount=%d", sockcount);
                   2809:                INSIST(sockcount >= 0);
                   2810:                if (sevent->result == ISC_R_EOF && l->eoferr == 0U) {
1.29      florian  2811:                        n = requeue_lookup(l, 1);
1.1       florian  2812:                        n->eoferr++;
                   2813:                }
                   2814:                isc_event_free(&event);
                   2815:                clear_query(query);
                   2816:                cancel_lookup(l);
                   2817:                check_next_lookup(l);
                   2818:                return;
                   2819:        }
                   2820:        length = isc_buffer_getuint16(b);
                   2821:        if (length == 0) {
                   2822:                isc_event_free(&event);
1.29      florian  2823:                launch_next_query(query, 0);
1.1       florian  2824:                return;
                   2825:        }
                   2826:
                   2827:        /*
                   2828:         * Even though the buffer was already init'ed, we need
                   2829:         * to redo it now, to force the length we want.
                   2830:         */
                   2831:        isc_buffer_invalidate(&query->recvbuf);
                   2832:        isc_buffer_init(&query->recvbuf, query->recvspace, length);
                   2833:        ENSURE(ISC_LIST_EMPTY(query->recvlist));
                   2834:        ISC_LINK_INIT(&query->recvbuf, link);
                   2835:        ISC_LIST_ENQUEUE(query->recvlist, &query->recvbuf, link);
                   2836:        debug("recving with lookup=%p, query=%p", query->lookup, query);
                   2837:        result = isc_socket_recvv(query->sock, &query->recvlist, length, task,
                   2838:                                  recv_done, query);
                   2839:        check_result(result, "isc_socket_recvv");
                   2840:        recvcount++;
                   2841:        debug("resubmitted recv request with length %d, recvcount=%d",
                   2842:              length, recvcount);
                   2843:        isc_event_free(&event);
                   2844: }
                   2845:
                   2846: /*%
                   2847:  * For transfers that involve multiple recvs (XFR's in particular),
                   2848:  * launch the next recv.
                   2849:  */
                   2850: static void
1.29      florian  2851: launch_next_query(dig_query_t *query, int include_question) {
1.1       florian  2852:        isc_result_t result;
                   2853:        dig_lookup_t *l;
                   2854:        isc_buffer_t *buffer;
                   2855:
                   2856:        INSIST(!free_now);
                   2857:
                   2858:        debug("launch_next_query()");
                   2859:
                   2860:        if (!query->lookup->pending) {
                   2861:                debug("ignoring launch_next_query because !pending");
                   2862:                isc_socket_detach(&query->sock);
                   2863:                sockcount--;
                   2864:                debug("sockcount=%d", sockcount);
                   2865:                INSIST(sockcount >= 0);
1.29      florian  2866:                query->waiting_connect = 0;
1.1       florian  2867:                l = query->lookup;
                   2868:                clear_query(query);
                   2869:                check_next_lookup(l);
                   2870:                return;
                   2871:        }
                   2872:
                   2873:        isc_buffer_clear(&query->slbuf);
                   2874:        isc_buffer_clear(&query->lengthbuf);
                   2875:        isc_buffer_putuint16(&query->slbuf, (uint16_t) query->sendbuf.used);
                   2876:        ISC_LIST_INIT(query->sendlist);
                   2877:        ISC_LINK_INIT(&query->slbuf, link);
                   2878:        if (!query->first_soa_rcvd) {
                   2879:                buffer = clone_buffer(&query->slbuf);
                   2880:                ISC_LIST_ENQUEUE(query->sendlist, buffer, link);
                   2881:                if (include_question) {
                   2882:                        buffer = clone_buffer(&query->sendbuf);
                   2883:                        ISC_LIST_ENQUEUE(query->sendlist, buffer, link);
                   2884:                }
                   2885:        }
                   2886:
                   2887:        ISC_LINK_INIT(&query->lengthbuf, link);
                   2888:        ISC_LIST_ENQUEUE(query->lengthlist, &query->lengthbuf, link);
                   2889:
                   2890:        result = isc_socket_recvv(query->sock, &query->lengthlist, 0,
                   2891:                                  global_task, tcp_length_done, query);
                   2892:        check_result(result, "isc_socket_recvv");
                   2893:        recvcount++;
                   2894:        debug("recvcount=%d", recvcount);
                   2895:        if (!query->first_soa_rcvd) {
                   2896:                debug("sending a request in launch_next_query");
1.13      florian  2897:                clock_gettime(CLOCK_MONOTONIC, &query->time_sent);
1.29      florian  2898:                query->waiting_senddone = 1;
1.1       florian  2899:                result = isc_socket_sendv(query->sock, &query->sendlist,
                   2900:                                          global_task, send_done, query);
                   2901:                check_result(result, "isc_socket_sendv");
                   2902:                sendcount++;
                   2903:                debug("sendcount=%d", sendcount);
                   2904:        }
1.29      florian  2905:        query->waiting_connect = 0;
1.1       florian  2906:        return;
                   2907: }
                   2908:
                   2909: /*%
                   2910:  * Event handler for TCP connect complete.  Make sure the connection was
                   2911:  * successful, then pass into launch_next_query to actually send the
                   2912:  * question.
                   2913:  */
                   2914: static void
                   2915: connect_done(isc_task_t *task, isc_event_t *event) {
                   2916:        char sockstr[ISC_SOCKADDR_FORMATSIZE];
                   2917:        isc_socketevent_t *sevent = NULL;
                   2918:        dig_query_t *query = NULL, *next;
                   2919:        dig_lookup_t *l;
                   2920:
                   2921:        UNUSED(task);
                   2922:
                   2923:        REQUIRE(event->ev_type == ISC_SOCKEVENT_CONNECT);
                   2924:        INSIST(!free_now);
                   2925:
                   2926:        debug("connect_done()");
                   2927:
                   2928:        sevent = (isc_socketevent_t *)event;
                   2929:        query = sevent->ev_arg;
                   2930:
                   2931:        INSIST(query->waiting_connect);
                   2932:
1.29      florian  2933:        query->waiting_connect = 0;
1.1       florian  2934:
                   2935:        if (sevent->result == ISC_R_CANCELED) {
                   2936:                debug("in cancel handler");
                   2937:                isc_sockaddr_format(&query->sockaddr, sockstr, sizeof(sockstr));
                   2938:                if (query->timedout)
                   2939:                        printf(";; Connection to %s(%s) for %s failed: %s.\n",
                   2940:                               sockstr, query->servname,
                   2941:                               query->lookup->textname,
                   2942:                               isc_result_totext(ISC_R_TIMEDOUT));
                   2943:                isc_socket_detach(&query->sock);
                   2944:                INSIST(sockcount > 0);
                   2945:                sockcount--;
                   2946:                debug("sockcount=%d", sockcount);
1.29      florian  2947:                query->waiting_connect = 0;
1.1       florian  2948:                isc_event_free(&event);
                   2949:                l = query->lookup;
                   2950:                clear_query(query);
                   2951:                check_next_lookup(l);
                   2952:                return;
                   2953:        }
                   2954:        if (sevent->result != ISC_R_SUCCESS) {
                   2955:
                   2956:                debug("unsuccessful connection: %s",
                   2957:                      isc_result_totext(sevent->result));
                   2958:                isc_sockaddr_format(&query->sockaddr, sockstr, sizeof(sockstr));
                   2959:                if (sevent->result != ISC_R_CANCELED)
                   2960:                        printf(";; Connection to %s(%s) for %s failed: "
                   2961:                               "%s.\n", sockstr,
                   2962:                               query->servname, query->lookup->textname,
                   2963:                               isc_result_totext(sevent->result));
                   2964:                isc_socket_detach(&query->sock);
                   2965:                INSIST(sockcount > 0);
                   2966:                sockcount--;
                   2967:                /* XXX Clean up exitcodes */
                   2968:                if (exitcode < 9)
                   2969:                        exitcode = 9;
                   2970:                debug("sockcount=%d", sockcount);
1.29      florian  2971:                query->waiting_connect = 0;
1.1       florian  2972:                isc_event_free(&event);
                   2973:                l = query->lookup;
                   2974:                if ((l->current_query != NULL) &&
                   2975:                    (ISC_LINK_LINKED(l->current_query, link)))
                   2976:                        next = ISC_LIST_NEXT(l->current_query, link);
                   2977:                else
                   2978:                        next = NULL;
                   2979:                clear_query(query);
                   2980:                if (next != NULL) {
                   2981:                        bringup_timer(next, TCP_TIMEOUT);
                   2982:                        send_tcp_connect(next);
                   2983:                } else
                   2984:                        check_next_lookup(l);
                   2985:                return;
                   2986:        }
                   2987:        if (keep_open) {
                   2988:                if (keep != NULL)
                   2989:                        isc_socket_detach(&keep);
                   2990:                isc_socket_attach(query->sock, &keep);
                   2991:                keepaddr = query->sockaddr;
                   2992:        }
1.29      florian  2993:        launch_next_query(query, 1);
1.1       florian  2994:        isc_event_free(&event);
                   2995: }
                   2996:
                   2997: /*%
                   2998:  * Check if the ongoing XFR needs more data before it's complete, using
                   2999:  * the semantics of IXFR and AXFR protocols.  Much of the complexity of
                   3000:  * this routine comes from determining when an IXFR is complete.
1.29      florian  3001:  * 0 means more data is on the way, and the recv has been issued.
1.1       florian  3002:  */
1.29      florian  3003: static int
1.1       florian  3004: check_for_more_data(dig_query_t *query, dns_message_t *msg,
                   3005:                    isc_socketevent_t *sevent)
                   3006: {
                   3007:        dns_rdataset_t *rdataset = NULL;
                   3008:        dns_rdata_t rdata = DNS_RDATA_INIT;
                   3009:        dns_rdata_soa_t soa;
                   3010:        uint32_t ixfr_serial = query->lookup->ixfr_serial, serial;
                   3011:        isc_result_t result;
1.29      florian  3012:        int ixfr = query->lookup->rdtype == dns_rdatatype_ixfr;
                   3013:        int axfr = query->lookup->rdtype == dns_rdatatype_axfr;
1.1       florian  3014:
                   3015:        if (ixfr)
                   3016:                axfr = query->ixfr_axfr;
                   3017:
                   3018:        debug("check_for_more_data()");
                   3019:
                   3020:        /*
                   3021:         * By the time we're in this routine, we know we're doing
                   3022:         * either an AXFR or IXFR.  If there's no second_rr_type,
                   3023:         * then we don't yet know which kind of answer we got back
                   3024:         * from the server.  Here, we're going to walk through the
                   3025:         * rr's in the message, acting as necessary whenever we hit
                   3026:         * an SOA rr.
                   3027:         */
                   3028:
                   3029:        query->msg_count++;
                   3030:        query->byte_count += sevent->n;
                   3031:        result = dns_message_firstname(msg, DNS_SECTION_ANSWER);
                   3032:        if (result != ISC_R_SUCCESS) {
                   3033:                puts("; Transfer failed.");
1.29      florian  3034:                return (1);
1.1       florian  3035:        }
                   3036:        do {
                   3037:                dns_name_t *name;
                   3038:                name = NULL;
                   3039:                dns_message_currentname(msg, DNS_SECTION_ANSWER,
                   3040:                                        &name);
                   3041:                for (rdataset = ISC_LIST_HEAD(name->list);
                   3042:                     rdataset != NULL;
                   3043:                     rdataset = ISC_LIST_NEXT(rdataset, link)) {
                   3044:                        result = dns_rdataset_first(rdataset);
                   3045:                        if (result != ISC_R_SUCCESS)
                   3046:                                continue;
                   3047:                        do {
                   3048:                                query->rr_count++;
                   3049:                                dns_rdata_reset(&rdata);
                   3050:                                dns_rdataset_current(rdataset, &rdata);
                   3051:                                /*
                   3052:                                 * If this is the first rr, make sure
                   3053:                                 * it's an SOA
                   3054:                                 */
                   3055:                                if ((!query->first_soa_rcvd) &&
                   3056:                                    (rdata.type != dns_rdatatype_soa)) {
                   3057:                                        puts("; Transfer failed.  "
                   3058:                                             "Didn't start with SOA answer.");
1.29      florian  3059:                                        return (1);
1.1       florian  3060:                                }
                   3061:                                if ((!query->second_rr_rcvd) &&
                   3062:                                    (rdata.type != dns_rdatatype_soa)) {
1.29      florian  3063:                                        query->second_rr_rcvd = 1;
1.1       florian  3064:                                        query->second_rr_serial = 0;
                   3065:                                        debug("got the second rr as nonsoa");
1.29      florian  3066:                                        axfr = query->ixfr_axfr = 1;
1.1       florian  3067:                                        goto next_rdata;
                   3068:                                }
                   3069:
                   3070:                                /*
                   3071:                                 * If the record is anything except an SOA
                   3072:                                 * now, just continue on...
                   3073:                                 */
                   3074:                                if (rdata.type != dns_rdatatype_soa)
                   3075:                                        goto next_rdata;
                   3076:
                   3077:                                /* Now we have an SOA.  Work with it. */
                   3078:                                debug("got an SOA");
1.21      florian  3079:                                result = dns_rdata_tostruct_soa(&rdata, &soa);
                   3080:                                check_result(result, "dns_rdata_tostruct_soa");
1.1       florian  3081:                                serial = soa.serial;
1.19      florian  3082:                                dns_rdata_freestruct_soa(&soa);
1.1       florian  3083:                                if (!query->first_soa_rcvd) {
1.29      florian  3084:                                        query->first_soa_rcvd = 1;
1.1       florian  3085:                                        query->first_rr_serial = serial;
                   3086:                                        debug("this is the first serial %u",
                   3087:                                              serial);
                   3088:                                        if (ixfr && isc_serial_ge(ixfr_serial,
                   3089:                                                                  serial)) {
                   3090:                                                debug("got up to date "
                   3091:                                                      "response");
                   3092:                                                goto doexit;
                   3093:                                        }
                   3094:                                        goto next_rdata;
                   3095:                                }
                   3096:                                if (axfr) {
                   3097:                                        debug("doing axfr, got second SOA");
                   3098:                                        goto doexit;
                   3099:                                }
                   3100:                                if (!query->second_rr_rcvd) {
                   3101:                                        if (query->first_rr_serial == serial) {
                   3102:                                                debug("doing ixfr, got "
                   3103:                                                      "empty zone");
                   3104:                                                goto doexit;
                   3105:                                        }
                   3106:                                        debug("this is the second serial %u",
                   3107:                                              serial);
1.29      florian  3108:                                        query->second_rr_rcvd = 1;
1.1       florian  3109:                                        query->second_rr_serial = serial;
                   3110:                                        goto next_rdata;
                   3111:                                }
                   3112:                                /*
                   3113:                                 * If we get to this point, we're doing an
                   3114:                                 * IXFR and have to start really looking
                   3115:                                 * at serial numbers.
                   3116:                                 */
                   3117:                                if (query->first_rr_serial == serial) {
                   3118:                                        debug("got a match for ixfr");
                   3119:                                        if (!query->first_repeat_rcvd) {
                   3120:                                                query->first_repeat_rcvd =
1.29      florian  3121:                                                        1;
1.1       florian  3122:                                                goto next_rdata;
                   3123:                                        }
                   3124:                                        debug("done with ixfr");
                   3125:                                        goto doexit;
                   3126:                                }
                   3127:                                debug("meaningless soa %u", serial);
                   3128:                        next_rdata:
                   3129:                                result = dns_rdataset_next(rdataset);
                   3130:                        } while (result == ISC_R_SUCCESS);
                   3131:                }
                   3132:                result = dns_message_nextname(msg, DNS_SECTION_ANSWER);
                   3133:        } while (result == ISC_R_SUCCESS);
1.29      florian  3134:        launch_next_query(query, 0);
                   3135:        return (0);
1.1       florian  3136:  doexit:
                   3137:        dighost_received(sevent->n, &sevent->address, query);
1.29      florian  3138:        return (1);
1.1       florian  3139: }
                   3140:
                   3141: static void
                   3142: process_sit(dig_lookup_t *l, dns_message_t *msg,
                   3143:            isc_buffer_t *optbuf, size_t optlen)
                   3144: {
                   3145:        char bb[256];
                   3146:        isc_buffer_t hexbuf;
                   3147:        size_t len;
                   3148:        const unsigned char *sit;
1.29      florian  3149:        int copysit;
1.1       florian  3150:        isc_result_t result;
                   3151:
                   3152:        if (l->sitvalue != NULL) {
                   3153:                isc_buffer_init(&hexbuf, bb, sizeof(bb));
                   3154:                result = isc_hex_decodestring(l->sitvalue, &hexbuf);
                   3155:                check_result(result, "isc_hex_decodestring");
                   3156:                sit = isc_buffer_base(&hexbuf);
                   3157:                len = isc_buffer_usedlength(&hexbuf);
1.29      florian  3158:                copysit = 0;
1.1       florian  3159:        } else {
                   3160:                sit = cookie;
                   3161:                len = sizeof(cookie);
1.29      florian  3162:                copysit = 1;
1.1       florian  3163:        }
                   3164:
                   3165:        INSIST(msg->sitok == 0 && msg->sitbad == 0);
                   3166:        if (optlen >= len && optlen >= 8U) {
1.25      florian  3167:                if (timingsafe_bcmp(isc_buffer_current(optbuf), sit, 8) == 0) {
1.1       florian  3168:                        msg->sitok = 1;
                   3169:                } else {
                   3170:                        printf(";; Warning: SIT client cookie mismatch\n");
                   3171:                        msg->sitbad = 1;
1.29      florian  3172:                        copysit = 0;
1.1       florian  3173:                }
                   3174:        } else {
                   3175:                printf(";; Warning: SIT bad token (too short)\n");
                   3176:                msg->sitbad = 1;
1.29      florian  3177:                copysit = 0;
1.1       florian  3178:        }
                   3179:        if (copysit) {
                   3180:                isc_region_t r;
                   3181:
                   3182:                r.base = isc_buffer_current(optbuf);
                   3183:                r.length = (unsigned int)optlen;
                   3184:                isc_buffer_init(&hexbuf, sitvalue, sizeof(sitvalue));
                   3185:                result = isc_hex_totext(&r, 2, "", &hexbuf);
                   3186:                check_result(result, "isc_hex_totext");
                   3187:                if (isc_buffer_availablelength(&hexbuf) > 0) {
                   3188:                        isc_buffer_putuint8(&hexbuf, 0);
                   3189:                        l->sitvalue = sitvalue;
                   3190:                }
                   3191:        }
                   3192:        isc_buffer_forward(optbuf, (unsigned int)optlen);
                   3193: }
                   3194:
                   3195: static void
                   3196: process_opt(dig_lookup_t *l, dns_message_t *msg) {
                   3197:        dns_rdata_t rdata;
                   3198:        isc_result_t result;
                   3199:        isc_buffer_t optbuf;
                   3200:        uint16_t optcode, optlen;
                   3201:        dns_rdataset_t *opt = msg->opt;
1.29      florian  3202:        int seen_cookie = 0;
1.1       florian  3203:
                   3204:        result = dns_rdataset_first(opt);
                   3205:        if (result == ISC_R_SUCCESS) {
                   3206:                dns_rdata_init(&rdata);
                   3207:                dns_rdataset_current(opt, &rdata);
                   3208:                isc_buffer_init(&optbuf, rdata.data, rdata.length);
                   3209:                isc_buffer_add(&optbuf, rdata.length);
                   3210:                while (isc_buffer_remaininglength(&optbuf) >= 4) {
                   3211:                        optcode = isc_buffer_getuint16(&optbuf);
                   3212:                        optlen = isc_buffer_getuint16(&optbuf);
                   3213:                        switch (optcode) {
                   3214:                        case DNS_OPT_COOKIE:
                   3215:                                /*
                   3216:                                 * Only process the first cookie option.
                   3217:                                 */
                   3218:                                if (seen_cookie) {
                   3219:                                        isc_buffer_forward(&optbuf, optlen);
                   3220:                                        break;
                   3221:                                }
                   3222:                                process_sit(l, msg, &optbuf, optlen);
1.29      florian  3223:                                seen_cookie = 1;
1.1       florian  3224:                                break;
                   3225:                        default:
                   3226:                                isc_buffer_forward(&optbuf, optlen);
                   3227:                                break;
                   3228:                        }
                   3229:                }
                   3230:        }
                   3231: }
                   3232:
                   3233: static int
                   3234: ednsvers(dns_rdataset_t *opt) {
                   3235:        return ((opt->ttl >> 16) & 0xff);
                   3236: }
                   3237:
                   3238: /*%
                   3239:  * Event handler for recv complete.  Perform whatever actions are necessary,
                   3240:  * based on the specifics of the user's request.
                   3241:  */
                   3242: static void
                   3243: recv_done(isc_task_t *task, isc_event_t *event) {
                   3244:        isc_socketevent_t *sevent = NULL;
                   3245:        dig_query_t *query = NULL;
                   3246:        isc_buffer_t *b = NULL;
                   3247:        dns_message_t *msg = NULL;
                   3248:        isc_result_t result;
                   3249:        dig_lookup_t *n, *l;
1.29      florian  3250:        int docancel = 0;
                   3251:        int match = 1;
1.1       florian  3252:        unsigned int parseflags;
                   3253:        dns_messageid_t id;
                   3254:        unsigned int msgflags;
                   3255:        int newedns;
                   3256:
                   3257:        UNUSED(task);
                   3258:        INSIST(!free_now);
                   3259:
                   3260:        debug("recv_done()");
                   3261:
                   3262:        recvcount--;
                   3263:        debug("recvcount=%d", recvcount);
                   3264:        INSIST(recvcount >= 0);
                   3265:
                   3266:        query = event->ev_arg;
1.13      florian  3267:        clock_gettime(CLOCK_MONOTONIC, &query->time_recv);
1.1       florian  3268:        debug("lookup=%p, query=%p", query->lookup, query);
                   3269:
                   3270:        l = query->lookup;
                   3271:
                   3272:        REQUIRE(event->ev_type == ISC_SOCKEVENT_RECVDONE);
                   3273:        sevent = (isc_socketevent_t *)event;
                   3274:
                   3275:        b = ISC_LIST_HEAD(sevent->bufferlist);
                   3276:        INSIST(b == &query->recvbuf);
                   3277:        ISC_LIST_DEQUEUE(sevent->bufferlist, &query->recvbuf, link);
                   3278:
                   3279:        if ((l->tcp_mode) && (query->timer != NULL))
                   3280:                isc_timer_touch(query->timer);
                   3281:        if ((!l->pending && !l->ns_search_only) || cancel_now) {
                   3282:                debug("no longer pending.  Got %s",
                   3283:                        isc_result_totext(sevent->result));
1.29      florian  3284:                query->waiting_connect = 0;
1.1       florian  3285:
                   3286:                isc_event_free(&event);
                   3287:                clear_query(query);
                   3288:                check_next_lookup(l);
                   3289:                return;
                   3290:        }
                   3291:
                   3292:        if (sevent->result != ISC_R_SUCCESS) {
                   3293:                if (sevent->result == ISC_R_CANCELED) {
                   3294:                        debug("in recv cancel handler");
1.29      florian  3295:                        query->waiting_connect = 0;
1.1       florian  3296:                } else {
                   3297:                        printf(";; communications error: %s\n",
                   3298:                               isc_result_totext(sevent->result));
                   3299:                        if (keep != NULL)
                   3300:                                isc_socket_detach(&keep);
                   3301:                        isc_socket_detach(&query->sock);
                   3302:                        sockcount--;
                   3303:                        debug("sockcount=%d", sockcount);
                   3304:                        INSIST(sockcount >= 0);
                   3305:                }
                   3306:                if (sevent->result == ISC_R_EOF && l->eoferr == 0U) {
1.29      florian  3307:                        n = requeue_lookup(l, 1);
1.1       florian  3308:                        n->eoferr++;
                   3309:                }
                   3310:                isc_event_free(&event);
                   3311:                clear_query(query);
                   3312:                cancel_lookup(l);
                   3313:                check_next_lookup(l);
                   3314:                return;
                   3315:        }
                   3316:
                   3317:        if (!l->tcp_mode &&
                   3318:            !isc_sockaddr_compare(&sevent->address, &query->sockaddr,
                   3319:                                  ISC_SOCKADDR_CMPADDR|
                   3320:                                  ISC_SOCKADDR_CMPPORT|
                   3321:                                  ISC_SOCKADDR_CMPSCOPE|
                   3322:                                  ISC_SOCKADDR_CMPSCOPEZERO)) {
                   3323:                char buf1[ISC_SOCKADDR_FORMATSIZE];
                   3324:                char buf2[ISC_SOCKADDR_FORMATSIZE];
                   3325:                isc_sockaddr_t any;
                   3326:
                   3327:                if (isc_sockaddr_pf(&query->sockaddr) == AF_INET)
                   3328:                        isc_sockaddr_any(&any);
                   3329:                else
                   3330:                        isc_sockaddr_any6(&any);
                   3331:
                   3332:                /*
                   3333:                * We don't expect a match when the packet is
                   3334:                * sent to 0.0.0.0, :: or to a multicast addresses.
                   3335:                * XXXMPA broadcast needs to be handled here as well.
                   3336:                */
                   3337:                if ((!isc_sockaddr_eqaddr(&query->sockaddr, &any) &&
                   3338:                     !isc_sockaddr_ismulticast(&query->sockaddr)) ||
                   3339:                    isc_sockaddr_getport(&query->sockaddr) !=
                   3340:                    isc_sockaddr_getport(&sevent->address)) {
                   3341:                        isc_sockaddr_format(&sevent->address, buf1,
                   3342:                        sizeof(buf1));
                   3343:                        isc_sockaddr_format(&query->sockaddr, buf2,
                   3344:                        sizeof(buf2));
                   3345:                        printf(";; reply from unexpected source: %s,"
                   3346:                        " expected %s\n", buf1, buf2);
1.29      florian  3347:                        match = 0;
1.1       florian  3348:                }
                   3349:        }
                   3350:
                   3351:        result = dns_message_peekheader(b, &id, &msgflags);
                   3352:        if (result != ISC_R_SUCCESS || l->sendmsg->id != id) {
1.29      florian  3353:                match = 0;
1.1       florian  3354:                if (l->tcp_mode) {
1.29      florian  3355:                        int fail = 1;
1.1       florian  3356:                        if (result == ISC_R_SUCCESS) {
                   3357:                                if (!query->first_soa_rcvd ||
                   3358:                                     query->warn_id)
                   3359:                                        printf(";; %s: ID mismatch: "
                   3360:                                               "expected ID %u, got %u\n",
                   3361:                                               query->first_soa_rcvd ?
                   3362:                                               "WARNING" : "ERROR",
                   3363:                                               l->sendmsg->id, id);
                   3364:                                if (query->first_soa_rcvd)
1.29      florian  3365:                                        fail = 0;
                   3366:                                query->warn_id = 0;
1.1       florian  3367:                        } else
                   3368:                                printf(";; ERROR: short "
                   3369:                                       "(< header size) message\n");
                   3370:                        if (fail) {
                   3371:                                isc_event_free(&event);
                   3372:                                clear_query(query);
                   3373:                                cancel_lookup(l);
                   3374:                                check_next_lookup(l);
                   3375:                                return;
                   3376:                        }
1.29      florian  3377:                        match = 1;
1.1       florian  3378:                } else if (result == ISC_R_SUCCESS)
                   3379:                        printf(";; Warning: ID mismatch: "
                   3380:                               "expected ID %u, got %u\n", l->sendmsg->id, id);
                   3381:                else
                   3382:                        printf(";; Warning: short "
                   3383:                               "(< header size) message received\n");
                   3384:        }
                   3385:
                   3386:        if (result == ISC_R_SUCCESS && (msgflags & DNS_MESSAGEFLAG_QR) == 0)
                   3387:                printf(";; Warning: query response not set\n");
                   3388:
                   3389:        if (!match)
                   3390:                goto udp_mismatch;
                   3391:
                   3392:        result = dns_message_create(DNS_MESSAGE_INTENTPARSE, &msg);
                   3393:        check_result(result, "dns_message_create");
                   3394:
                   3395:        if (tsigkey != NULL) {
                   3396:                if (l->querysig == NULL) {
                   3397:                        debug("getting initial querysig");
                   3398:                        result = dns_message_getquerytsig(l->sendmsg,
                   3399:                                                          &l->querysig);
                   3400:                        check_result(result, "dns_message_getquerytsig");
                   3401:                }
                   3402:                result = dns_message_setquerytsig(msg, l->querysig);
                   3403:                check_result(result, "dns_message_setquerytsig");
                   3404:                result = dns_message_settsigkey(msg, tsigkey);
                   3405:                check_result(result, "dns_message_settsigkey");
                   3406:                msg->tsigctx = l->tsigctx;
                   3407:                l->tsigctx = NULL;
                   3408:                if (l->msgcounter != 0)
                   3409:                        msg->tcp_continuation = 1;
                   3410:                l->msgcounter++;
                   3411:        }
                   3412:
                   3413:        debug("before parse starts");
1.17      florian  3414:        parseflags = 0;
1.1       florian  3415:        if (l->besteffort) {
                   3416:                parseflags |= DNS_MESSAGEPARSE_BESTEFFORT;
                   3417:                parseflags |= DNS_MESSAGEPARSE_IGNORETRUNCATION;
                   3418:        }
                   3419:        result = dns_message_parse(msg, b, parseflags);
                   3420:        if (result == DNS_R_RECOVERABLE) {
                   3421:                printf(";; Warning: Message parser reports malformed "
                   3422:                       "message packet.\n");
                   3423:                result = ISC_R_SUCCESS;
                   3424:        }
                   3425:        if (result != ISC_R_SUCCESS) {
                   3426:                printf(";; Got bad packet: %s\n", isc_result_totext(result));
                   3427:                hex_dump(b);
1.29      florian  3428:                query->waiting_connect = 0;
1.1       florian  3429:                dns_message_destroy(&msg);
                   3430:                isc_event_free(&event);
                   3431:                clear_query(query);
                   3432:                cancel_lookup(l);
                   3433:                check_next_lookup(l);
                   3434:                return;
                   3435:        }
                   3436:        if (msg->counts[DNS_SECTION_QUESTION] != 0) {
1.29      florian  3437:                match = 1;
1.1       florian  3438:                for (result = dns_message_firstname(msg, DNS_SECTION_QUESTION);
                   3439:                     result == ISC_R_SUCCESS && match;
                   3440:                     result = dns_message_nextname(msg, DNS_SECTION_QUESTION)) {
                   3441:                        dns_name_t *name = NULL;
                   3442:                        dns_rdataset_t *rdataset;
                   3443:
                   3444:                        dns_message_currentname(msg, DNS_SECTION_QUESTION,
                   3445:                                                &name);
                   3446:                        for (rdataset = ISC_LIST_HEAD(name->list);
                   3447:                             rdataset != NULL;
                   3448:                             rdataset = ISC_LIST_NEXT(rdataset, link)) {
                   3449:                                if (l->rdtype != rdataset->type ||
                   3450:                                    l->rdclass != rdataset->rdclass ||
                   3451:                                    !dns_name_equal(l->name, name)) {
                   3452:                                        char namestr[DNS_NAME_FORMATSIZE];
                   3453:                                        char typebuf[DNS_RDATATYPE_FORMATSIZE];
                   3454:                                        char classbuf[DNS_RDATACLASS_FORMATSIZE];
                   3455:                                        dns_name_format(name, namestr,
                   3456:                                                        sizeof(namestr));
                   3457:                                        dns_rdatatype_format(rdataset->type,
                   3458:                                                             typebuf,
                   3459:                                                             sizeof(typebuf));
                   3460:                                        dns_rdataclass_format(rdataset->rdclass,
                   3461:                                                              classbuf,
                   3462:                                                              sizeof(classbuf));
                   3463:                                        printf(";; Question section mismatch: "
                   3464:                                               "got %s/%s/%s\n",
                   3465:                                               namestr, typebuf, classbuf);
1.29      florian  3466:                                        match = 0;
1.1       florian  3467:                                }
                   3468:                        }
                   3469:                }
                   3470:                if (!match) {
                   3471:                        dns_message_destroy(&msg);
                   3472:                        if (l->tcp_mode) {
                   3473:                                isc_event_free(&event);
                   3474:                                clear_query(query);
                   3475:                                cancel_lookup(l);
                   3476:                                check_next_lookup(l);
                   3477:                                return;
                   3478:                        } else
                   3479:                                goto udp_mismatch;
                   3480:                }
                   3481:        }
                   3482:        if (msg->rcode == dns_rcode_badvers && msg->opt != NULL &&
                   3483:            (newedns = ednsvers(msg->opt)) < l->edns && l->ednsneg) {
                   3484:                /*
                   3485:                 * Add minimum EDNS version required checks here if needed.
                   3486:                 */
                   3487:                if (l->comments)
                   3488:                        printf(";; BADVERS, retrying with EDNS version %u.\n",
                   3489:                               (unsigned int)newedns);
                   3490:                l->edns = newedns;
1.29      florian  3491:                n = requeue_lookup(l, 1);
1.1       florian  3492:                if (l->trace && l->trace_root)
                   3493:                        n->rdtype = l->qrdtype;
                   3494:                dns_message_destroy(&msg);
                   3495:                isc_event_free(&event);
                   3496:                clear_query(query);
                   3497:                cancel_lookup(l);
                   3498:                check_next_lookup(l);
                   3499:                return;
                   3500:        }
                   3501:        if ((msg->flags & DNS_MESSAGEFLAG_TC) != 0 &&
                   3502:            !l->ignore && !l->tcp_mode) {
                   3503:                if (l->sitvalue == NULL && l->sit && msg->opt != NULL)
                   3504:                        process_opt(l, msg);
                   3505:                if (l->comments)
                   3506:                        printf(";; Truncated, retrying in TCP mode.\n");
1.29      florian  3507:                n = requeue_lookup(l, 1);
                   3508:                n->tcp_mode = 1;
1.1       florian  3509:                if (l->trace && l->trace_root)
                   3510:                        n->rdtype = l->qrdtype;
                   3511:                dns_message_destroy(&msg);
                   3512:                isc_event_free(&event);
                   3513:                clear_query(query);
                   3514:                cancel_lookup(l);
                   3515:                check_next_lookup(l);
                   3516:                return;
                   3517:        }
                   3518:        if ((msg->rcode == dns_rcode_servfail && !l->servfail_stops) ||
                   3519:            (check_ra && (msg->flags & DNS_MESSAGEFLAG_RA) == 0 && l->recurse))
                   3520:        {
                   3521:                dig_query_t *next = ISC_LIST_NEXT(query, link);
                   3522:                if (l->current_query == query)
                   3523:                        l->current_query = NULL;
                   3524:                if (next != NULL) {
                   3525:                        debug("sending query %p\n", next);
                   3526:                        if (l->tcp_mode)
                   3527:                                send_tcp_connect(next);
                   3528:                        else
                   3529:                                send_udp(next);
                   3530:                }
                   3531:                /*
                   3532:                 * If our query is at the head of the list and there
                   3533:                 * is no next, we're the only one left, so fall
                   3534:                 * through to print the message.
                   3535:                 */
                   3536:                if ((ISC_LIST_HEAD(l->q) != query) ||
                   3537:                    (ISC_LIST_NEXT(query, link) != NULL)) {
                   3538:                        if (l->comments)
                   3539:                                printf(";; Got %s from %s, "
                   3540:                                       "trying next server\n",
                   3541:                                       msg->rcode == dns_rcode_servfail ?
                   3542:                                       "SERVFAIL reply" :
                   3543:                                       "recursion not available",
                   3544:                                       query->servname);
                   3545:                        clear_query(query);
                   3546:                        check_next_lookup(l);
                   3547:                        dns_message_destroy(&msg);
                   3548:                        isc_event_free(&event);
                   3549:                        return;
                   3550:                }
                   3551:        }
                   3552:
                   3553:        if (tsigkey != NULL) {
                   3554:                result = dns_tsig_verify(&query->recvbuf, msg);
                   3555:                if (result != ISC_R_SUCCESS) {
                   3556:                        printf(";; Couldn't verify signature: %s\n",
                   3557:                               isc_result_totext(result));
1.29      florian  3558:                        validated = 0;
1.1       florian  3559:                }
                   3560:                l->tsigctx = msg->tsigctx;
                   3561:                msg->tsigctx = NULL;
                   3562:                if (l->querysig != NULL) {
                   3563:                        debug("freeing querysig buffer %p", l->querysig);
                   3564:                        isc_buffer_free(&l->querysig);
                   3565:                }
                   3566:                result = dns_message_getquerytsig(msg, &l->querysig);
                   3567:                check_result(result,"dns_message_getquerytsig");
                   3568:        }
                   3569:
                   3570:        extrabytes = isc_buffer_remaininglength(b);
                   3571:
                   3572:        debug("after parse");
                   3573:        if (l->doing_xfr && l->xfr_q == NULL) {
                   3574:                l->xfr_q = query;
                   3575:                /*
                   3576:                 * Once we are in the XFR message, increase
                   3577:                 * the timeout to much longer, so brief network
                   3578:                 * outages won't cause the XFR to abort
                   3579:                 */
                   3580:                if (timeout != INT_MAX && query->timer != NULL) {
                   3581:                        unsigned int local_timeout;
                   3582:
                   3583:                        if (timeout == 0) {
                   3584:                                if (l->tcp_mode)
                   3585:                                        local_timeout = TCP_TIMEOUT * 4;
                   3586:                                else
                   3587:                                        local_timeout = UDP_TIMEOUT * 4;
                   3588:                        } else {
                   3589:                                if (timeout < (INT_MAX / 4))
                   3590:                                        local_timeout = timeout * 4;
                   3591:                                else
                   3592:                                        local_timeout = INT_MAX;
                   3593:                        }
                   3594:                        debug("have local timeout of %d", local_timeout);
1.9       florian  3595:                        l->interval.tv_sec = local_timeout;
                   3596:                        l->interval.tv_nsec = 0;
1.1       florian  3597:                        result = isc_timer_reset(query->timer,
                   3598:                                                 &l->interval,
1.29      florian  3599:                                                 0);
1.1       florian  3600:                        check_result(result, "isc_timer_reset");
                   3601:                }
                   3602:        }
                   3603:
                   3604:        if (l->sitvalue != NULL) {
                   3605:                if (msg->opt == NULL)
                   3606:                        printf(";; expected opt record in response\n");
                   3607:                else
                   3608:                        process_opt(l, msg);
                   3609:        } else if (l->sit && msg->opt != NULL)
                   3610:                process_opt(l, msg);
                   3611:
                   3612:        if (!l->doing_xfr || l->xfr_q == query) {
                   3613:                if (msg->rcode == dns_rcode_nxdomain &&
                   3614:                    (l->origin != NULL || l->need_search)) {
                   3615:                        if (!next_origin(query->lookup) || showsearch) {
1.29      florian  3616:                                dighost_printmessage(query, msg, 1);
1.1       florian  3617:                                dighost_received(b->used, &sevent->address, query);
                   3618:                        }
                   3619:                } else if (!l->trace && !l->ns_search_only) {
1.29      florian  3620:                                dighost_printmessage(query, msg, 1);
1.1       florian  3621:                } else if (l->trace) {
                   3622:                        int nl = 0;
                   3623:                        int count = msg->counts[DNS_SECTION_ANSWER];
                   3624:
                   3625:                        debug("in TRACE code");
                   3626:                        if (!l->ns_search_only)
1.29      florian  3627:                                dighost_printmessage(query, msg, 1);
1.1       florian  3628:
                   3629:                        l->rdtype = l->qrdtype;
                   3630:                        if (l->trace_root || (l->ns_search_only && count > 0)) {
                   3631:                                if (!l->trace_root)
                   3632:                                        l->rdtype = dns_rdatatype_soa;
                   3633:                                nl = followup_lookup(msg, query,
                   3634:                                                     DNS_SECTION_ANSWER);
1.29      florian  3635:                                l->trace_root = 0;
1.1       florian  3636:                        } else if (count == 0)
                   3637:                                nl = followup_lookup(msg, query,
                   3638:                                                     DNS_SECTION_AUTHORITY);
                   3639:                        if (nl == 0)
1.29      florian  3640:                                docancel = 1;
1.1       florian  3641:                } else {
                   3642:                        debug("in NSSEARCH code");
                   3643:
                   3644:                        if (l->trace_root) {
                   3645:                                /*
                   3646:                                 * This is the initial NS query.
                   3647:                                 */
                   3648:                                int nl;
                   3649:
                   3650:                                l->rdtype = dns_rdatatype_soa;
                   3651:                                nl = followup_lookup(msg, query,
                   3652:                                                     DNS_SECTION_ANSWER);
                   3653:                                if (nl == 0)
1.29      florian  3654:                                        docancel = 1;
                   3655:                                l->trace_root = 0;
                   3656:                                usesearch = 0;
1.1       florian  3657:                        } else
1.29      florian  3658:                                dighost_printmessage(query, msg, 1);
1.1       florian  3659:                }
                   3660:        }
                   3661:
                   3662:        if (l->pending)
                   3663:                debug("still pending.");
                   3664:        if (l->doing_xfr) {
                   3665:                if (query != l->xfr_q) {
                   3666:                        dns_message_destroy(&msg);
                   3667:                        isc_event_free(&event);
1.29      florian  3668:                        query->waiting_connect = 0;
1.1       florian  3669:                        return;
                   3670:                }
                   3671:                if (!docancel)
                   3672:                        docancel = check_for_more_data(query, msg, sevent);
                   3673:                if (docancel) {
                   3674:                        dns_message_destroy(&msg);
                   3675:                        clear_query(query);
                   3676:                        cancel_lookup(l);
                   3677:                        check_next_lookup(l);
                   3678:                }
                   3679:        } else {
                   3680:
                   3681:                if (msg->rcode == dns_rcode_noerror || l->origin == NULL) {
                   3682:
                   3683:                                dighost_received(b->used, &sevent->address, query);
                   3684:                }
                   3685:
                   3686:                if (!query->lookup->ns_search_only)
1.29      florian  3687:                        query->lookup->pending = 0;
1.1       florian  3688:                if (!query->lookup->ns_search_only ||
                   3689:                    query->lookup->trace_root || docancel) {
                   3690:                                dns_message_destroy(&msg);
                   3691:
                   3692:                        cancel_lookup(l);
                   3693:                }
                   3694:                clear_query(query);
                   3695:                check_next_lookup(l);
                   3696:        }
                   3697:        if (msg != NULL) {
                   3698:                        dns_message_destroy(&msg);
                   3699:        }
                   3700:        isc_event_free(&event);
                   3701:        return;
                   3702:
                   3703:  udp_mismatch:
                   3704:        isc_buffer_invalidate(&query->recvbuf);
                   3705:        isc_buffer_init(&query->recvbuf, query->recvspace, COMMSIZE);
                   3706:        ISC_LIST_ENQUEUE(query->recvlist, &query->recvbuf, link);
                   3707:        result = isc_socket_recvv(query->sock, &query->recvlist, 1,
                   3708:                                  global_task, recv_done, query);
                   3709:        check_result(result, "isc_socket_recvv");
                   3710:        recvcount++;
                   3711:        isc_event_free(&event);
                   3712:        return;
                   3713: }
                   3714:
                   3715: /*%
                   3716:  * Turn a name into an address, using system-supplied routines.  This is
                   3717:  * used in looking up server names, etc... and needs to use system-supplied
                   3718:  * routines, since they may be using a non-DNS system for these lookups.
                   3719:  */
                   3720: isc_result_t
                   3721: get_address(char *host, in_port_t myport, isc_sockaddr_t *sockaddr) {
                   3722:        int count;
                   3723:        isc_result_t result;
                   3724:
                   3725:        result = get_addresses(host, myport, sockaddr, 1, &count);
                   3726:        if (result != ISC_R_SUCCESS)
                   3727:                return (result);
                   3728:
                   3729:        INSIST(count == 1);
                   3730:
                   3731:        return (ISC_R_SUCCESS);
                   3732: }
                   3733:
                   3734: int
                   3735: getaddresses(dig_lookup_t *lookup, const char *host, isc_result_t *resultp) {
                   3736:        isc_result_t result;
                   3737:        isc_sockaddr_t sockaddrs[DIG_MAX_ADDRESSES];
                   3738:        int count, i;
                   3739:        dig_server_t *srv;
1.32      florian  3740:        char tmp[NI_MAXHOST];
1.1       florian  3741:
                   3742:        result = get_addresses(host, 0, sockaddrs,
                   3743:                                    DIG_MAX_ADDRESSES, &count);
                   3744:        if (resultp != NULL)
                   3745:                *resultp = result;
                   3746:        if (result != ISC_R_SUCCESS) {
                   3747:                if (resultp == NULL)
                   3748:                        fatal("couldn't get address for '%s': %s",
                   3749:                              host, isc_result_totext(result));
                   3750:                return (0);
                   3751:        }
                   3752:
                   3753:        for (i = 0; i < count; i++) {
1.32      florian  3754:                int error;
                   3755:                error = getnameinfo(&sockaddrs[i].type.sa,
                   3756:                    sockaddrs[i].type.sa.sa_len, tmp, sizeof(tmp), NULL, 0,
                   3757:                    NI_NUMERICHOST | NI_NUMERICSERV);
                   3758:                if (error)
                   3759:                        fatal("%s", gai_strerror(error));
                   3760:
1.1       florian  3761:                srv = make_server(tmp, host);
                   3762:                ISC_LIST_APPEND(lookup->my_server_list, srv, link);
                   3763:        }
                   3764:
                   3765:        return (count);
                   3766: }
                   3767:
                   3768: /*%
                   3769:  * Initiate either a TCP or UDP lookup
                   3770:  */
                   3771: void
                   3772: do_lookup(dig_lookup_t *lookup) {
                   3773:        dig_query_t *query;
                   3774:
                   3775:        REQUIRE(lookup != NULL);
                   3776:
                   3777:        debug("do_lookup()");
1.29      florian  3778:        lookup->pending = 1;
1.1       florian  3779:        query = ISC_LIST_HEAD(lookup->q);
                   3780:        if (query != NULL) {
                   3781:                if (lookup->tcp_mode)
                   3782:                        send_tcp_connect(query);
                   3783:                else
                   3784:                        send_udp(query);
                   3785:        }
                   3786: }
                   3787:
                   3788: /*%
                   3789:  * Start everything in action upon task startup.
                   3790:  */
                   3791: void
                   3792: onrun_callback(isc_task_t *task, isc_event_t *event) {
                   3793:        UNUSED(task);
                   3794:
                   3795:        isc_event_free(&event);
                   3796:        start_lookup();
                   3797: }
                   3798:
                   3799: /*%
                   3800:  * Make everything on the lookup queue go away.  Mainly used by the
                   3801:  * SIGINT handler.
                   3802:  */
                   3803: void
                   3804: cancel_all(void) {
                   3805:        dig_lookup_t *l, *n;
                   3806:        dig_query_t *q, *nq;
                   3807:
                   3808:        debug("cancel_all()");
                   3809:
                   3810:        if (free_now) {
                   3811:                return;
                   3812:        }
1.29      florian  3813:        cancel_now = 1;
1.1       florian  3814:        if (current_lookup != NULL) {
                   3815:                for (q = ISC_LIST_HEAD(current_lookup->q);
                   3816:                     q != NULL;
                   3817:                     q = nq)
                   3818:                {
                   3819:                        nq = ISC_LIST_NEXT(q, link);
                   3820:                        debug("canceling pending query %p, belonging to %p",
                   3821:                              q, current_lookup);
                   3822:                        if (q->sock != NULL)
                   3823:                                isc_socket_cancel(q->sock, NULL,
                   3824:                                                  ISC_SOCKCANCEL_ALL);
                   3825:                        else
                   3826:                                clear_query(q);
                   3827:                }
                   3828:                for (q = ISC_LIST_HEAD(current_lookup->connecting);
                   3829:                     q != NULL;
                   3830:                     q = nq)
                   3831:                {
                   3832:                        nq = ISC_LIST_NEXT(q, clink);
                   3833:                        debug("canceling connecting query %p, belonging to %p",
                   3834:                              q, current_lookup);
                   3835:                        if (q->sock != NULL)
                   3836:                                isc_socket_cancel(q->sock, NULL,
                   3837:                                                  ISC_SOCKCANCEL_ALL);
                   3838:                        else
                   3839:                                clear_query(q);
                   3840:                }
                   3841:        }
                   3842:        l = ISC_LIST_HEAD(lookup_list);
                   3843:        while (l != NULL) {
                   3844:                n = ISC_LIST_NEXT(l, link);
                   3845:                ISC_LIST_DEQUEUE(lookup_list, l, link);
                   3846:                try_clear_lookup(l);
                   3847:                l = n;
                   3848:        }
                   3849: }
                   3850:
                   3851: /*%
                   3852:  * Destroy all of the libs we are using, and get everything ready for a
                   3853:  * clean shutdown.
                   3854:  */
                   3855: void
                   3856: destroy_libs(void) {
                   3857:
                   3858:        if (keep != NULL)
                   3859:                isc_socket_detach(&keep);
                   3860:        debug("destroy_libs()");
                   3861:        if (global_task != NULL) {
                   3862:                debug("freeing task");
                   3863:                isc_task_detach(&global_task);
                   3864:        }
                   3865:        /*
                   3866:         * The taskmgr_destroy() call blocks until all events are cleared
                   3867:         * from the task.
                   3868:         */
                   3869:        if (taskmgr != NULL) {
                   3870:                debug("freeing taskmgr");
                   3871:                isc_taskmgr_destroy(&taskmgr);
                   3872:        }
                   3873:        REQUIRE(sockcount == 0);
                   3874:        REQUIRE(recvcount == 0);
                   3875:        REQUIRE(sendcount == 0);
                   3876:
                   3877:        INSIST(ISC_LIST_HEAD(lookup_list) == NULL);
                   3878:        INSIST(current_lookup == NULL);
                   3879:        INSIST(!free_now);
                   3880:
1.29      florian  3881:        free_now = 1;
1.1       florian  3882:
                   3883:        lwres_conf_clear(lwconf);
                   3884:
                   3885:        flush_server_list();
                   3886:
                   3887:        clear_searchlist();
                   3888:
                   3889:        if (socketmgr != NULL) {
                   3890:                debug("freeing socketmgr");
                   3891:                isc_socketmgr_destroy(&socketmgr);
                   3892:        }
                   3893:        if (timermgr != NULL) {
                   3894:                debug("freeing timermgr");
                   3895:                isc_timermgr_destroy(&timermgr);
                   3896:        }
                   3897:        if (tsigkey != NULL) {
                   3898:                debug("freeing key %p", tsigkey);
                   3899:                dns_tsigkey_detach(&tsigkey);
                   3900:        }
                   3901:        if (namebuf != NULL)
                   3902:                isc_buffer_free(&namebuf);
                   3903:
                   3904:        if (is_dst_up) {
                   3905:                debug("destroy DST lib");
                   3906:                dst_lib_destroy();
1.29      florian  3907:                is_dst_up = 0;
1.1       florian  3908:        }
                   3909:
                   3910:        debug("Removing log context");
                   3911:        isc_log_destroy(&lctx);
                   3912:
                   3913: }
                   3914:
1.27      florian  3915: int64_t
                   3916: uelapsed(const struct timespec *t1, const struct timespec *t2)
                   3917: {
                   3918:        struct timespec  diff, zero = {0, 0};
                   3919:        struct timeval   tv;
                   3920:
                   3921:        timespecsub(t1, t2, &diff);
                   3922:
                   3923:        if (timespeccmp(&diff, &zero, <=))
                   3924:                return 0;
                   3925:
                   3926:        TIMESPEC_TO_TIMEVAL(&tv, &diff);
                   3927:
                   3928:        return (tv.tv_sec * 1000000 + tv.tv_usec);
                   3929: }