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

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