[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.8

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