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

Annotation of src/usr.bin/dig/host.c, Revision 1.1

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:
        !            17: /*! \file */
        !            18: #include <sys/cdefs.h>
        !            19:
        !            20: #include <err.h>
        !            21: #include <limits.h>
        !            22: #include <locale.h>
        !            23: #include <stdlib.h>
        !            24: #include <string.h>
        !            25: #include <unistd.h>
        !            26:
        !            27: #include <isc/app.h>
        !            28: #include <isc/netaddr.h>
        !            29: #include <isc/util.h>
        !            30: #include <isc/task.h>
        !            31:
        !            32: #include <dns/byaddr.h>
        !            33: #include <dns/fixedname.h>
        !            34: #include <dns/message.h>
        !            35: #include <dns/name.h>
        !            36: #include <dns/rdata.h>
        !            37: #include <dns/rdataclass.h>
        !            38: #include <dns/rdataset.h>
        !            39: #include <dns/rdatatype.h>
        !            40: #include "rdatastruct.h"
        !            41:
        !            42: #include "dig.h"
        !            43:
        !            44: static isc_boolean_t short_form = ISC_TRUE, listed_server = ISC_FALSE;
        !            45: static isc_boolean_t default_lookups = ISC_TRUE;
        !            46: static int seen_error = -1;
        !            47: static isc_boolean_t list_addresses = ISC_TRUE;
        !            48: static dns_rdatatype_t list_type = dns_rdatatype_a;
        !            49: static isc_boolean_t printed_server = ISC_FALSE;
        !            50: static isc_boolean_t ipv4only = ISC_FALSE, ipv6only = ISC_FALSE;
        !            51:
        !            52: static const char *opcodetext[] = {
        !            53:        "QUERY",
        !            54:        "IQUERY",
        !            55:        "STATUS",
        !            56:        "RESERVED3",
        !            57:        "NOTIFY",
        !            58:        "UPDATE",
        !            59:        "RESERVED6",
        !            60:        "RESERVED7",
        !            61:        "RESERVED8",
        !            62:        "RESERVED9",
        !            63:        "RESERVED10",
        !            64:        "RESERVED11",
        !            65:        "RESERVED12",
        !            66:        "RESERVED13",
        !            67:        "RESERVED14",
        !            68:        "RESERVED15"
        !            69: };
        !            70:
        !            71: static const char *rcodetext[] = {
        !            72:        "NOERROR",
        !            73:        "FORMERR",
        !            74:        "SERVFAIL",
        !            75:        "NXDOMAIN",
        !            76:        "NOTIMP",
        !            77:        "REFUSED",
        !            78:        "YXDOMAIN",
        !            79:        "YXRRSET",
        !            80:        "NXRRSET",
        !            81:        "NOTAUTH",
        !            82:        "NOTZONE",
        !            83:        "RESERVED11",
        !            84:        "RESERVED12",
        !            85:        "RESERVED13",
        !            86:        "RESERVED14",
        !            87:        "RESERVED15",
        !            88:        "BADVERS"
        !            89: };
        !            90:
        !            91: struct rtype {
        !            92:        unsigned int type;
        !            93:        const char *text;
        !            94: };
        !            95:
        !            96: static struct rtype rtypes[] = {
        !            97:        { 1,    "has address" },
        !            98:        { 2,    "name server" },
        !            99:        { 5,    "is an alias for" },
        !           100:        { 11,   "has well known services" },
        !           101:        { 12,   "domain name pointer" },
        !           102:        { 13,   "host information" },
        !           103:        { 15,   "mail is handled by" },
        !           104:        { 16,   "descriptive text" },
        !           105:        { 19,   "x25 address" },
        !           106:        { 20,   "ISDN address" },
        !           107:        { 24,   "has signature" },
        !           108:        { 25,   "has key" },
        !           109:        { 28,   "has IPv6 address" },
        !           110:        { 29,   "location" },
        !           111:        { 0, NULL }
        !           112: };
        !           113:
        !           114: static char *
        !           115: rcode_totext(dns_rcode_t rcode)
        !           116: {
        !           117:        static char buf[sizeof("?65535")];
        !           118:        union {
        !           119:                const char *consttext;
        !           120:                char *deconsttext;
        !           121:        } totext;
        !           122:
        !           123:        if (rcode >= (sizeof(rcodetext)/sizeof(rcodetext[0]))) {
        !           124:                snprintf(buf, sizeof(buf), "?%u", rcode);
        !           125:                totext.deconsttext = buf;
        !           126:        } else
        !           127:                totext.consttext = rcodetext[rcode];
        !           128:        return totext.deconsttext;
        !           129: }
        !           130:
        !           131: static __dead void
        !           132: show_usage(void);
        !           133:
        !           134: static void
        !           135: show_usage(void) {
        !           136:        fputs(
        !           137: "usage: host [-46aCdilrsTVvw] [-c class] [-m flag] [-N ndots] [-R number]\n"
        !           138: "            [-t type] [-W wait] name [server]\n", stderr);
        !           139:        exit(1);
        !           140: }
        !           141:
        !           142: static void
        !           143: host_shutdown(void) {
        !           144:        (void) isc_app_shutdown();
        !           145: }
        !           146:
        !           147: static void
        !           148: received(unsigned int bytes, isc_sockaddr_t *from, dig_query_t *query) {
        !           149:        isc_time_t now;
        !           150:        int diff;
        !           151:
        !           152:        if (!short_form) {
        !           153:                char fromtext[ISC_SOCKADDR_FORMATSIZE];
        !           154:                isc_sockaddr_format(from, fromtext, sizeof(fromtext));
        !           155:                TIME_NOW(&now);
        !           156:                diff = (int) isc_time_microdiff(&now, &query->time_sent);
        !           157:                printf("Received %u bytes from %s in %d ms\n",
        !           158:                       bytes, fromtext, diff/1000);
        !           159:        }
        !           160: }
        !           161:
        !           162: static void
        !           163: trying(char *frm, dig_lookup_t *lookup) {
        !           164:        UNUSED(lookup);
        !           165:
        !           166:        if (!short_form)
        !           167:                printf("Trying \"%s\"\n", frm);
        !           168: }
        !           169:
        !           170: static void
        !           171: say_message(dns_name_t *name, const char *msg, dns_rdata_t *rdata,
        !           172:            dig_query_t *query)
        !           173: {
        !           174:        isc_buffer_t *b = NULL;
        !           175:        char namestr[DNS_NAME_FORMATSIZE];
        !           176:        isc_region_t r;
        !           177:        isc_result_t result;
        !           178:        unsigned int bufsize = BUFSIZ;
        !           179:
        !           180:        dns_name_format(name, namestr, sizeof(namestr));
        !           181:  retry:
        !           182:        result = isc_buffer_allocate(&b, bufsize);
        !           183:        check_result(result, "isc_buffer_allocate");
        !           184:        result = dns_rdata_totext(rdata, NULL, b);
        !           185:        if (result == ISC_R_NOSPACE) {
        !           186:                isc_buffer_free(&b);
        !           187:                bufsize *= 2;
        !           188:                goto retry;
        !           189:        }
        !           190:        check_result(result, "dns_rdata_totext");
        !           191:        isc_buffer_usedregion(b, &r);
        !           192:        if (query->lookup->identify_previous_line) {
        !           193:                printf("Nameserver %s:\n\t",
        !           194:                        query->servname);
        !           195:        }
        !           196:        printf("%s %s %.*s", namestr,
        !           197:               msg, (int)r.length, (char *)r.base);
        !           198:        if (query->lookup->identify) {
        !           199:                printf(" on server %s", query->servname);
        !           200:        }
        !           201:        printf("\n");
        !           202:        isc_buffer_free(&b);
        !           203: }
        !           204: static isc_result_t
        !           205: printsection(dns_message_t *msg, dns_section_t sectionid,
        !           206:             const char *section_name, isc_boolean_t headers,
        !           207:             dig_query_t *query)
        !           208: {
        !           209:        dns_name_t *name, *print_name;
        !           210:        dns_rdataset_t *rdataset;
        !           211:        dns_rdata_t rdata = DNS_RDATA_INIT;
        !           212:        isc_buffer_t target;
        !           213:        isc_result_t result, loopresult;
        !           214:        isc_region_t r;
        !           215:        dns_name_t empty_name;
        !           216:        char tbuf[4096];
        !           217:        isc_boolean_t first;
        !           218:        isc_boolean_t no_rdata;
        !           219:
        !           220:        if (sectionid == DNS_SECTION_QUESTION)
        !           221:                no_rdata = ISC_TRUE;
        !           222:        else
        !           223:                no_rdata = ISC_FALSE;
        !           224:
        !           225:        if (headers)
        !           226:                printf(";; %s SECTION:\n", section_name);
        !           227:
        !           228:        dns_name_init(&empty_name, NULL);
        !           229:
        !           230:        result = dns_message_firstname(msg, sectionid);
        !           231:        if (result == ISC_R_NOMORE)
        !           232:                return (ISC_R_SUCCESS);
        !           233:        else if (result != ISC_R_SUCCESS)
        !           234:                return (result);
        !           235:
        !           236:        for (;;) {
        !           237:                name = NULL;
        !           238:                dns_message_currentname(msg, sectionid, &name);
        !           239:
        !           240:                isc_buffer_init(&target, tbuf, sizeof(tbuf));
        !           241:                first = ISC_TRUE;
        !           242:                print_name = name;
        !           243:
        !           244:                for (rdataset = ISC_LIST_HEAD(name->list);
        !           245:                     rdataset != NULL;
        !           246:                     rdataset = ISC_LIST_NEXT(rdataset, link)) {
        !           247:                        if (query->lookup->rdtype == dns_rdatatype_axfr &&
        !           248:                            !((!list_addresses &&
        !           249:                               (list_type == dns_rdatatype_any ||
        !           250:                                rdataset->type == list_type)) ||
        !           251:                              (list_addresses &&
        !           252:                               (rdataset->type == dns_rdatatype_a ||
        !           253:                                rdataset->type == dns_rdatatype_aaaa ||
        !           254:                                rdataset->type == dns_rdatatype_ns ||
        !           255:                                rdataset->type == dns_rdatatype_ptr))))
        !           256:                                continue;
        !           257:                        if (!short_form) {
        !           258:                                result = dns_rdataset_totext(rdataset,
        !           259:                                                             print_name,
        !           260:                                                             ISC_FALSE,
        !           261:                                                             no_rdata,
        !           262:                                                             &target);
        !           263:                                if (result != ISC_R_SUCCESS)
        !           264:                                        return (result);
        !           265: #ifdef USEINITALWS
        !           266:                                if (first) {
        !           267:                                        print_name = &empty_name;
        !           268:                                        first = ISC_FALSE;
        !           269:                                }
        !           270: #else
        !           271:                                UNUSED(first); /* Shut up compiler. */
        !           272: #endif
        !           273:                        } else {
        !           274:                                loopresult = dns_rdataset_first(rdataset);
        !           275:                                while (loopresult == ISC_R_SUCCESS) {
        !           276:                                        struct rtype *t;
        !           277:                                        const char *rtt;
        !           278:                                        char typebuf[DNS_RDATATYPE_FORMATSIZE];
        !           279:                                        char typebuf2[DNS_RDATATYPE_FORMATSIZE
        !           280:                                                     + 20];
        !           281:                                        dns_rdataset_current(rdataset, &rdata);
        !           282:
        !           283:                                        for (t = rtypes; t->text != NULL; t++) {
        !           284:                                                if (t->type == rdata.type) {
        !           285:                                                        rtt = t->text;
        !           286:                                                        goto found;
        !           287:                                                }
        !           288:                                        }
        !           289:
        !           290:                                        dns_rdatatype_format(rdata.type,
        !           291:                                                             typebuf,
        !           292:                                                             sizeof(typebuf));
        !           293:                                        snprintf(typebuf2, sizeof(typebuf2),
        !           294:                                                 "has %s record", typebuf);
        !           295:                                        rtt = typebuf2;
        !           296:                                found:
        !           297:                                        say_message(print_name, rtt,
        !           298:                                                    &rdata, query);
        !           299:                                        dns_rdata_reset(&rdata);
        !           300:                                        loopresult =
        !           301:                                                dns_rdataset_next(rdataset);
        !           302:                                }
        !           303:                        }
        !           304:                }
        !           305:                if (!short_form) {
        !           306:                        isc_buffer_usedregion(&target, &r);
        !           307:                        if (no_rdata)
        !           308:                                printf(";%.*s", (int)r.length,
        !           309:                                       (char *)r.base);
        !           310:                        else
        !           311:                                printf("%.*s", (int)r.length, (char *)r.base);
        !           312:                }
        !           313:
        !           314:                result = dns_message_nextname(msg, sectionid);
        !           315:                if (result == ISC_R_NOMORE)
        !           316:                        break;
        !           317:                else if (result != ISC_R_SUCCESS)
        !           318:                        return (result);
        !           319:        }
        !           320:
        !           321:        return (ISC_R_SUCCESS);
        !           322: }
        !           323:
        !           324: static isc_result_t
        !           325: printrdata(dns_message_t *msg, dns_rdataset_t *rdataset, dns_name_t *owner,
        !           326:           const char *set_name, isc_boolean_t headers)
        !           327: {
        !           328:        isc_buffer_t target;
        !           329:        isc_result_t result;
        !           330:        isc_region_t r;
        !           331:        char tbuf[4096];
        !           332:
        !           333:        UNUSED(msg);
        !           334:        if (headers)
        !           335:                printf(";; %s SECTION:\n", set_name);
        !           336:
        !           337:        isc_buffer_init(&target, tbuf, sizeof(tbuf));
        !           338:
        !           339:        result = dns_rdataset_totext(rdataset, owner, ISC_FALSE, ISC_FALSE,
        !           340:                                     &target);
        !           341:        if (result != ISC_R_SUCCESS)
        !           342:                return (result);
        !           343:        isc_buffer_usedregion(&target, &r);
        !           344:        printf("%.*s", (int)r.length, (char *)r.base);
        !           345:
        !           346:        return (ISC_R_SUCCESS);
        !           347: }
        !           348:
        !           349: static void
        !           350: chase_cnamechain(dns_message_t *msg, dns_name_t *qname) {
        !           351:        isc_result_t result;
        !           352:        dns_rdataset_t *rdataset;
        !           353:        dns_rdata_cname_t cname;
        !           354:        dns_rdata_t rdata = DNS_RDATA_INIT;
        !           355:        unsigned int i = msg->counts[DNS_SECTION_ANSWER];
        !           356:
        !           357:        while (i-- > 0) {
        !           358:                rdataset = NULL;
        !           359:                result = dns_message_findname(msg, DNS_SECTION_ANSWER, qname,
        !           360:                                              dns_rdatatype_cname, 0, NULL,
        !           361:                                              &rdataset);
        !           362:                if (result != ISC_R_SUCCESS)
        !           363:                        return;
        !           364:                result = dns_rdataset_first(rdataset);
        !           365:                check_result(result, "dns_rdataset_first");
        !           366:                dns_rdata_reset(&rdata);
        !           367:                dns_rdataset_current(rdataset, &rdata);
        !           368:                result = dns_rdata_tostruct(&rdata, &cname);
        !           369:                check_result(result, "dns_rdata_tostruct");
        !           370:                dns_name_copy(&cname.cname, qname, NULL);
        !           371:                dns_rdata_freestruct(&cname);
        !           372:        }
        !           373: }
        !           374:
        !           375: static isc_result_t
        !           376: printmessage(dig_query_t *query, dns_message_t *msg, isc_boolean_t headers) {
        !           377:        isc_boolean_t did_flag = ISC_FALSE;
        !           378:        dns_rdataset_t *opt, *tsig = NULL;
        !           379:        dns_name_t *tsigname;
        !           380:        isc_result_t result = ISC_R_SUCCESS;
        !           381:        int force_error;
        !           382:
        !           383:        UNUSED(headers);
        !           384:
        !           385:        /*
        !           386:         * We get called multiple times.
        !           387:         * Preserve any existing error status.
        !           388:         */
        !           389:        force_error = (seen_error == 1) ? 1 : 0;
        !           390:        seen_error = 1;
        !           391:        if (listed_server && !printed_server) {
        !           392:                char sockstr[ISC_SOCKADDR_FORMATSIZE];
        !           393:
        !           394:                printf("Using domain server:\n");
        !           395:                printf("Name: %s\n", query->userarg);
        !           396:                isc_sockaddr_format(&query->sockaddr, sockstr,
        !           397:                                    sizeof(sockstr));
        !           398:                printf("Address: %s\n", sockstr);
        !           399:                printf("Aliases: \n\n");
        !           400:                printed_server = ISC_TRUE;
        !           401:        }
        !           402:
        !           403:        if (msg->rcode != 0) {
        !           404:                char namestr[DNS_NAME_FORMATSIZE];
        !           405:                dns_name_format(query->lookup->name, namestr, sizeof(namestr));
        !           406:
        !           407:                if (query->lookup->identify_previous_line)
        !           408:                        printf("Nameserver %s:\n\t%s not found: %d(%s)\n",
        !           409:                               query->servname,
        !           410:                               (msg->rcode != dns_rcode_nxdomain) ? namestr :
        !           411:                               query->lookup->textname, msg->rcode,
        !           412:                               rcode_totext(msg->rcode));
        !           413:                else
        !           414:                        printf("Host %s not found: %d(%s)\n",
        !           415:                               (msg->rcode != dns_rcode_nxdomain) ? namestr :
        !           416:                               query->lookup->textname, msg->rcode,
        !           417:                               rcode_totext(msg->rcode));
        !           418:                return (ISC_R_SUCCESS);
        !           419:        }
        !           420:
        !           421:        if (default_lookups && query->lookup->rdtype == dns_rdatatype_a) {
        !           422:                char namestr[DNS_NAME_FORMATSIZE];
        !           423:                dig_lookup_t *lookup;
        !           424:                dns_fixedname_t fixed;
        !           425:                dns_name_t *name;
        !           426:
        !           427:                /* Add AAAA and MX lookups. */
        !           428:                dns_fixedname_init(&fixed);
        !           429:                name = dns_fixedname_name(&fixed);
        !           430:                dns_name_copy(query->lookup->name, name, NULL);
        !           431:                chase_cnamechain(msg, name);
        !           432:                dns_name_format(name, namestr, sizeof(namestr));
        !           433:                lookup = clone_lookup(query->lookup, ISC_FALSE);
        !           434:                if (lookup != NULL) {
        !           435:                        strlcpy(lookup->textname, namestr,
        !           436:                                sizeof(lookup->textname));
        !           437:                        lookup->rdtype = dns_rdatatype_aaaa;
        !           438:                        lookup->rdtypeset = ISC_TRUE;
        !           439:                        lookup->origin = NULL;
        !           440:                        lookup->retries = tries;
        !           441:                        ISC_LIST_APPEND(lookup_list, lookup, link);
        !           442:                }
        !           443:                lookup = clone_lookup(query->lookup, ISC_FALSE);
        !           444:                if (lookup != NULL) {
        !           445:                        strlcpy(lookup->textname, namestr,
        !           446:                                sizeof(lookup->textname));
        !           447:                        lookup->rdtype = dns_rdatatype_mx;
        !           448:                        lookup->rdtypeset = ISC_TRUE;
        !           449:                        lookup->origin = NULL;
        !           450:                        lookup->retries = tries;
        !           451:                        ISC_LIST_APPEND(lookup_list, lookup, link);
        !           452:                }
        !           453:        }
        !           454:
        !           455:        if (!short_form) {
        !           456:                printf(";; ->>HEADER<<- opcode: %s, status: %s, id: %u\n",
        !           457:                       opcodetext[msg->opcode], rcode_totext(msg->rcode),
        !           458:                       msg->id);
        !           459:                printf(";; flags: ");
        !           460:                if ((msg->flags & DNS_MESSAGEFLAG_QR) != 0) {
        !           461:                        printf("qr");
        !           462:                        did_flag = ISC_TRUE;
        !           463:                }
        !           464:                if ((msg->flags & DNS_MESSAGEFLAG_AA) != 0) {
        !           465:                        printf("%saa", did_flag ? " " : "");
        !           466:                        did_flag = ISC_TRUE;
        !           467:                }
        !           468:                if ((msg->flags & DNS_MESSAGEFLAG_TC) != 0) {
        !           469:                        printf("%stc", did_flag ? " " : "");
        !           470:                        did_flag = ISC_TRUE;
        !           471:                }
        !           472:                if ((msg->flags & DNS_MESSAGEFLAG_RD) != 0) {
        !           473:                        printf("%srd", did_flag ? " " : "");
        !           474:                        did_flag = ISC_TRUE;
        !           475:                }
        !           476:                if ((msg->flags & DNS_MESSAGEFLAG_RA) != 0) {
        !           477:                        printf("%sra", did_flag ? " " : "");
        !           478:                        did_flag = ISC_TRUE;
        !           479:                }
        !           480:                if ((msg->flags & DNS_MESSAGEFLAG_AD) != 0) {
        !           481:                        printf("%sad", did_flag ? " " : "");
        !           482:                        did_flag = ISC_TRUE;
        !           483:                }
        !           484:                if ((msg->flags & DNS_MESSAGEFLAG_CD) != 0) {
        !           485:                        printf("%scd", did_flag ? " " : "");
        !           486:                        did_flag = ISC_TRUE;
        !           487:                        POST(did_flag);
        !           488:                }
        !           489:                printf("; QUERY: %u, ANSWER: %u, "
        !           490:                       "AUTHORITY: %u, ADDITIONAL: %u\n",
        !           491:                       msg->counts[DNS_SECTION_QUESTION],
        !           492:                       msg->counts[DNS_SECTION_ANSWER],
        !           493:                       msg->counts[DNS_SECTION_AUTHORITY],
        !           494:                       msg->counts[DNS_SECTION_ADDITIONAL]);
        !           495:                opt = dns_message_getopt(msg);
        !           496:                if (opt != NULL)
        !           497:                        printf(";; EDNS: version: %u, udp=%u\n",
        !           498:                               (unsigned int)((opt->ttl & 0x00ff0000) >> 16),
        !           499:                               (unsigned int)opt->rdclass);
        !           500:                tsigname = NULL;
        !           501:                tsig = dns_message_gettsig(msg, &tsigname);
        !           502:                if (tsig != NULL)
        !           503:                        printf(";; PSEUDOSECTIONS: TSIG\n");
        !           504:        }
        !           505:        if (! ISC_LIST_EMPTY(msg->sections[DNS_SECTION_QUESTION]) &&
        !           506:            !short_form) {
        !           507:                printf("\n");
        !           508:                result = printsection(msg, DNS_SECTION_QUESTION, "QUESTION",
        !           509:                                      ISC_TRUE, query);
        !           510:                if (result != ISC_R_SUCCESS)
        !           511:                        return (result);
        !           512:        }
        !           513:        if (! ISC_LIST_EMPTY(msg->sections[DNS_SECTION_ANSWER])) {
        !           514:                if (!short_form)
        !           515:                        printf("\n");
        !           516:                result = printsection(msg, DNS_SECTION_ANSWER, "ANSWER",
        !           517:                                      ISC_TF(!short_form), query);
        !           518:                if (result != ISC_R_SUCCESS)
        !           519:                        return (result);
        !           520:        }
        !           521:
        !           522:        if (! ISC_LIST_EMPTY(msg->sections[DNS_SECTION_AUTHORITY]) &&
        !           523:            !short_form) {
        !           524:                printf("\n");
        !           525:                result = printsection(msg, DNS_SECTION_AUTHORITY, "AUTHORITY",
        !           526:                                      ISC_TRUE, query);
        !           527:                if (result != ISC_R_SUCCESS)
        !           528:                        return (result);
        !           529:        }
        !           530:        if (! ISC_LIST_EMPTY(msg->sections[DNS_SECTION_ADDITIONAL]) &&
        !           531:            !short_form) {
        !           532:                printf("\n");
        !           533:                result = printsection(msg, DNS_SECTION_ADDITIONAL,
        !           534:                                      "ADDITIONAL", ISC_TRUE, query);
        !           535:                if (result != ISC_R_SUCCESS)
        !           536:                        return (result);
        !           537:        }
        !           538:        if ((tsig != NULL) && !short_form) {
        !           539:                printf("\n");
        !           540:                result = printrdata(msg, tsig, tsigname,
        !           541:                                    "PSEUDOSECTION TSIG", ISC_TRUE);
        !           542:                if (result != ISC_R_SUCCESS)
        !           543:                        return (result);
        !           544:        }
        !           545:        if (!short_form)
        !           546:                printf("\n");
        !           547:
        !           548:        if (short_form && !default_lookups &&
        !           549:            ISC_LIST_EMPTY(msg->sections[DNS_SECTION_ANSWER])) {
        !           550:                char namestr[DNS_NAME_FORMATSIZE];
        !           551:                char typestr[DNS_RDATATYPE_FORMATSIZE];
        !           552:                dns_name_format(query->lookup->name, namestr, sizeof(namestr));
        !           553:                dns_rdatatype_format(query->lookup->rdtype, typestr,
        !           554:                                     sizeof(typestr));
        !           555:                printf("%s has no %s record\n", namestr, typestr);
        !           556:        }
        !           557:        seen_error = force_error;
        !           558:        return (result);
        !           559: }
        !           560:
        !           561: static const char * optstring = "46ac:dilnrst:vVwCDN:R:TW:";
        !           562:
        !           563: /*% version */
        !           564: static void
        !           565: version(void) {
        !           566:        fputs("host " VERSION "\n", stderr);
        !           567: }
        !           568:
        !           569: static void
        !           570: pre_parse_args(int argc, char **argv) {
        !           571:        int c;
        !           572:
        !           573:        while ((c = getopt(argc, argv, optstring)) != -1) {
        !           574:                switch (c) {
        !           575:                case '4':
        !           576:                        if (ipv6only)
        !           577:                                fatal("only one of -4 and -6 allowed");
        !           578:                        ipv4only = ISC_TRUE;
        !           579:                        break;
        !           580:                case '6':
        !           581:                        if (ipv4only)
        !           582:                                fatal("only one of -4 and -6 allowed");
        !           583:                        ipv6only = ISC_TRUE;
        !           584:                        break;
        !           585:                case 'a': break;
        !           586:                case 'c': break;
        !           587:                case 'd': break;
        !           588:                case 'i': break;
        !           589:                case 'l': break;
        !           590:                case 'n': break;
        !           591:                case 'r': break;
        !           592:                case 's': break;
        !           593:                case 't': break;
        !           594:                case 'v': break;
        !           595:                case 'V':
        !           596:                          version();
        !           597:                          exit(0);
        !           598:                          break;
        !           599:                case 'w': break;
        !           600:                case 'C': break;
        !           601:                case 'D':
        !           602:                        if (debugging)
        !           603:                                debugtiming = ISC_TRUE;
        !           604:                        debugging = ISC_TRUE;
        !           605:                        break;
        !           606:                case 'N': break;
        !           607:                case 'R': break;
        !           608:                case 'T': break;
        !           609:                case 'W': break;
        !           610:                default:
        !           611:                        show_usage();
        !           612:                }
        !           613:        }
        !           614:        optind = 1;
        !           615:        optreset = 1;
        !           616: }
        !           617:
        !           618: static void
        !           619: parse_args(int argc, char **argv) {
        !           620:        char hostname[MXNAME];
        !           621:        dig_lookup_t *lookup;
        !           622:        int c;
        !           623:        char store[MXNAME];
        !           624:        isc_textregion_t tr;
        !           625:        isc_result_t result = ISC_R_SUCCESS;
        !           626:        dns_rdatatype_t rdtype;
        !           627:        dns_rdataclass_t rdclass;
        !           628:        uint32_t serial = 0;
        !           629:        const char *errstr;
        !           630:
        !           631:        lookup = make_empty_lookup();
        !           632:
        !           633:        lookup->servfail_stops = ISC_FALSE;
        !           634:        lookup->comments = ISC_FALSE;
        !           635:
        !           636:        while ((c = getopt(argc, argv, optstring)) != -1) {
        !           637:                switch (c) {
        !           638:                case 'l':
        !           639:                        lookup->tcp_mode = ISC_TRUE;
        !           640:                        lookup->rdtype = dns_rdatatype_axfr;
        !           641:                        lookup->rdtypeset = ISC_TRUE;
        !           642:                        fatalexit = 3;
        !           643:                        break;
        !           644:                case 'v':
        !           645:                case 'd':
        !           646:                        short_form = ISC_FALSE;
        !           647:                        break;
        !           648:                case 'r':
        !           649:                        lookup->recurse = ISC_FALSE;
        !           650:                        break;
        !           651:                case 't':
        !           652:                        if (strncasecmp(optarg, "ixfr=", 5) == 0) {
        !           653:                                rdtype = dns_rdatatype_ixfr;
        !           654:                                /* XXXMPA add error checking */
        !           655:                                serial = strtoul(optarg + 5,
        !           656:                                                 NULL, 10);
        !           657:                                result = ISC_R_SUCCESS;
        !           658:                        } else {
        !           659:                                tr.base = optarg;
        !           660:                                tr.length = strlen(optarg);
        !           661:                                result = dns_rdatatype_fromtext(&rdtype,
        !           662:                                                   (isc_textregion_t *)&tr);
        !           663:                        }
        !           664:
        !           665:                        if (result != ISC_R_SUCCESS) {
        !           666:                                fatalexit = 2;
        !           667:                                fatal("invalid type: %s\n", optarg);
        !           668:                        }
        !           669:                        if (!lookup->rdtypeset ||
        !           670:                            lookup->rdtype != dns_rdatatype_axfr)
        !           671:                                lookup->rdtype = rdtype;
        !           672:                        lookup->rdtypeset = ISC_TRUE;
        !           673:                        if (rdtype == dns_rdatatype_axfr) {
        !           674:                                /* -l -t any -v */
        !           675:                                list_type = dns_rdatatype_any;
        !           676:                                short_form = ISC_FALSE;
        !           677:                                lookup->tcp_mode = ISC_TRUE;
        !           678:                        } else if (rdtype == dns_rdatatype_ixfr) {
        !           679:                                lookup->ixfr_serial = serial;
        !           680:                                lookup->tcp_mode = ISC_TRUE;
        !           681:                                list_type = rdtype;
        !           682:                        } else
        !           683:                                list_type = rdtype;
        !           684:                        list_addresses = ISC_FALSE;
        !           685:                        default_lookups = ISC_FALSE;
        !           686:                        break;
        !           687:                case 'c':
        !           688:                        tr.base = optarg;
        !           689:                        tr.length = strlen(optarg);
        !           690:                        result = dns_rdataclass_fromtext(&rdclass,
        !           691:                                                   (isc_textregion_t *)&tr);
        !           692:
        !           693:                        if (result != ISC_R_SUCCESS) {
        !           694:                                fatalexit = 2;
        !           695:                                fatal("invalid class: %s\n", optarg);
        !           696:                        } else {
        !           697:                                lookup->rdclass = rdclass;
        !           698:                                lookup->rdclassset = ISC_TRUE;
        !           699:                        }
        !           700:                        default_lookups = ISC_FALSE;
        !           701:                        break;
        !           702:                case 'a':
        !           703:                        if (!lookup->rdtypeset ||
        !           704:                            lookup->rdtype != dns_rdatatype_axfr)
        !           705:                                lookup->rdtype = dns_rdatatype_any;
        !           706:                        list_type = dns_rdatatype_any;
        !           707:                        list_addresses = ISC_FALSE;
        !           708:                        lookup->rdtypeset = ISC_TRUE;
        !           709:                        short_form = ISC_FALSE;
        !           710:                        default_lookups = ISC_FALSE;
        !           711:                        break;
        !           712:                case 'i':
        !           713:                        lookup->ip6_int = ISC_TRUE;
        !           714:                        break;
        !           715:                case 'n':
        !           716:                        /* deprecated */
        !           717:                        break;
        !           718:                case 'm':
        !           719:                        /* Handled by pre_parse_args(). */
        !           720:                        break;
        !           721:                case 'w':
        !           722:                        /*
        !           723:                         * The timer routines are coded such that
        !           724:                         * timeout==MAXINT doesn't enable the timer
        !           725:                         */
        !           726:                        timeout = INT_MAX;
        !           727:                        break;
        !           728:                case 'W':
        !           729:                        timeout = strtonum(optarg, 0, INT_MAX, &errstr);
        !           730:                        if (errstr != NULL)
        !           731:                                errx(1, "timeout is %s: %s", errstr, optarg);
        !           732:                        if (timeout < 1)
        !           733:                                timeout = 1;
        !           734:                        break;
        !           735:                case 'R':
        !           736:                        tries = strtonum(optarg, INT_MIN, INT_MAX - 1, &errstr);
        !           737:                        if (errstr != NULL)
        !           738:                                errx(1, "retries is %s: %s", errstr, optarg);
        !           739:                        tries++;
        !           740:                        if (tries < 2)
        !           741:                                tries = 2;
        !           742:                        break;
        !           743:                case 'T':
        !           744:                        lookup->tcp_mode = ISC_TRUE;
        !           745:                        break;
        !           746:                case 'C':
        !           747:                        debug("showing all SOAs");
        !           748:                        lookup->rdtype = dns_rdatatype_ns;
        !           749:                        lookup->rdtypeset = ISC_TRUE;
        !           750:                        lookup->rdclass = dns_rdataclass_in;
        !           751:                        lookup->rdclassset = ISC_TRUE;
        !           752:                        lookup->ns_search_only = ISC_TRUE;
        !           753:                        lookup->trace_root = ISC_TRUE;
        !           754:                        lookup->identify_previous_line = ISC_TRUE;
        !           755:                        default_lookups = ISC_FALSE;
        !           756:                        break;
        !           757:                case 'N':
        !           758:                        debug("setting NDOTS to %s", optarg);
        !           759:                        ndots = strtonum(optarg, 0, INT_MAX, &errstr);
        !           760:                        if (errstr != NULL)
        !           761:                                errx(1, "ndots is %s: %s", errstr, optarg);
        !           762:                        break;
        !           763:                case 'D':
        !           764:                        /* Handled by pre_parse_args(). */
        !           765:                        break;
        !           766:                case '4':
        !           767:                        /* Handled by pre_parse_args(). */
        !           768:                        break;
        !           769:                case '6':
        !           770:                        /* Handled by pre_parse_args(). */
        !           771:                        break;
        !           772:                case 's':
        !           773:                        lookup->servfail_stops = ISC_TRUE;
        !           774:                        break;
        !           775:                default:
        !           776:                        show_usage();
        !           777:                }
        !           778:        }
        !           779:
        !           780:        lookup->retries = tries;
        !           781:
        !           782:        argc -= optind;
        !           783:        argv += optind;
        !           784:
        !           785:        if (argc == 0)
        !           786:                show_usage();
        !           787:
        !           788:        strlcpy(hostname, *argv, sizeof(hostname));
        !           789:
        !           790:        if (argc == 2) {
        !           791:                set_nameserver(*argv + 1);
        !           792:                debug("server is %s", *argv + 1);
        !           793:                listed_server = ISC_TRUE;
        !           794:        } else
        !           795:                check_ra = ISC_TRUE;
        !           796:
        !           797:        lookup->pending = ISC_FALSE;
        !           798:        if (get_reverse(store, sizeof(store), hostname,
        !           799:                        lookup->ip6_int, ISC_TRUE) == ISC_R_SUCCESS) {
        !           800:                strlcpy(lookup->textname, store, sizeof(lookup->textname));
        !           801:                lookup->rdtype = dns_rdatatype_ptr;
        !           802:                lookup->rdtypeset = ISC_TRUE;
        !           803:                default_lookups = ISC_FALSE;
        !           804:        } else {
        !           805:                strlcpy(lookup->textname, hostname, sizeof(lookup->textname));
        !           806:                usesearch = ISC_TRUE;
        !           807:        }
        !           808:        lookup->new_search = ISC_TRUE;
        !           809:        ISC_LIST_APPEND(lookup_list, lookup, link);
        !           810: }
        !           811:
        !           812: int
        !           813: host_main(int argc, char **argv) {
        !           814:        isc_result_t result;
        !           815:
        !           816:        tries = 2;
        !           817:
        !           818:        ISC_LIST_INIT(lookup_list);
        !           819:        ISC_LIST_INIT(server_list);
        !           820:        ISC_LIST_INIT(search_list);
        !           821:
        !           822:        fatalexit = 1;
        !           823:
        !           824:        /* setup dighost callbacks */
        !           825:        dighost_printmessage = printmessage;
        !           826:        dighost_received = received;
        !           827:        dighost_trying = trying;
        !           828:        dighost_shutdown = host_shutdown;
        !           829:
        !           830:        debug("main()");
        !           831:        progname = argv[0];
        !           832:        pre_parse_args(argc, argv);
        !           833:        result = isc_app_start();
        !           834:        check_result(result, "isc_app_start");
        !           835:
        !           836:        if (pledge("stdio rpath inet dns", NULL) == -1) {
        !           837:                perror("pledge");
        !           838:                exit(1);
        !           839:        }
        !           840:
        !           841:        setup_libs();
        !           842:
        !           843:        if (pledge("stdio inet dns", NULL) == -1) {
        !           844:                perror("pledge");
        !           845:                exit(1);
        !           846:        }
        !           847:
        !           848:        parse_args(argc, argv);
        !           849:        setup_system(ipv4only, ipv6only);
        !           850:        result = isc_app_onrun(global_task, onrun_callback, NULL);
        !           851:        check_result(result, "isc_app_onrun");
        !           852:        isc_app_run();
        !           853:        cancel_all();
        !           854:        destroy_libs();
        !           855:        isc_app_finish();
        !           856:        return ((seen_error == 0) ? 0 : 1);
        !           857: }