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

Annotation of src/usr.bin/dig/nslookup.c, Revision 1.12

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: #include <limits.h>
                     18: #include <stdlib.h>
                     19: #include <string.h>
                     20: #include <unistd.h>
                     21:
                     22: #include <isc/app.h>
                     23: #include <isc/buffer.h>
                     24: #include <isc/event.h>
                     25: #include <isc/util.h>
                     26: #include <isc/task.h>
                     27:
                     28: #include <dns/message.h>
                     29: #include <dns/name.h>
                     30: #include <dns/fixedname.h>
                     31: #include <dns/rdata.h>
                     32: #include <dns/rdataclass.h>
                     33: #include <dns/rdataset.h>
                     34: #include <dns/rdatatype.h>
                     35:
                     36: #include "dig.h"
                     37:
1.12    ! florian    38: static int short_form = 1,
        !            39:        tcpmode = 0,
        !            40:        identify = 0, stats = 1,
        !            41:        comments = 1, section_question = 1,
        !            42:        section_answer = 1, section_authority = 1,
        !            43:        section_additional = 1, recurse = 1,
        !            44:        aaonly = 0, nofail = 1;
1.1       florian    45:
1.12    ! florian    46: static int interactive;
1.1       florian    47:
1.12    ! florian    48: static int in_use = 0;
1.1       florian    49: static char defclass[MXRD] = "IN";
                     50: static char deftype[MXRD] = "A";
                     51: static isc_event_t *global_event = NULL;
                     52: static int query_error = 1, print_error = 0;
                     53:
                     54: static char domainopt[DNS_NAME_MAXTEXT];
                     55:
                     56: static const char *rcodetext[] = {
                     57:        "NOERROR",
                     58:        "FORMERR",
                     59:        "SERVFAIL",
                     60:        "NXDOMAIN",
                     61:        "NOTIMP",
                     62:        "REFUSED",
                     63:        "YXDOMAIN",
                     64:        "YXRRSET",
                     65:        "NXRRSET",
                     66:        "NOTAUTH",
                     67:        "NOTZONE",
                     68:        "RESERVED11",
                     69:        "RESERVED12",
                     70:        "RESERVED13",
                     71:        "RESERVED14",
                     72:        "RESERVED15",
                     73:        "BADVERS"
                     74: };
                     75:
                     76: static const char *rtypetext[] = {
                     77:        "rtype_0 = ",                   /* 0 */
                     78:        "internet address = ",          /* 1 */
                     79:        "nameserver = ",                /* 2 */
                     80:        "md = ",                        /* 3 */
                     81:        "mf = ",                        /* 4 */
                     82:        "canonical name = ",            /* 5 */
                     83:        "soa = ",                       /* 6 */
                     84:        "mb = ",                        /* 7 */
                     85:        "mg = ",                        /* 8 */
                     86:        "mr = ",                        /* 9 */
                     87:        "rtype_10 = ",                  /* 10 */
                     88:        "protocol = ",                  /* 11 */
                     89:        "name = ",                      /* 12 */
                     90:        "hinfo = ",                     /* 13 */
                     91:        "minfo = ",                     /* 14 */
                     92:        "mail exchanger = ",            /* 15 */
                     93:        "text = ",                      /* 16 */
                     94:        "rp = ",                        /* 17 */
                     95:        "afsdb = ",                     /* 18 */
                     96:        "x25 address = ",               /* 19 */
                     97:        "isdn address = ",              /* 20 */
                     98:        "rt = ",                        /* 21 */
                     99:        "nsap = ",                      /* 22 */
                    100:        "nsap_ptr = ",                  /* 23 */
                    101:        "signature = ",                 /* 24 */
                    102:        "key = ",                       /* 25 */
                    103:        "px = ",                        /* 26 */
                    104:        "gpos = ",                      /* 27 */
                    105:        "has AAAA address ",            /* 28 */
                    106:        "loc = ",                       /* 29 */
                    107:        "next = ",                      /* 30 */
                    108:        "rtype_31 = ",                  /* 31 */
                    109:        "rtype_32 = ",                  /* 32 */
                    110:        "service = ",                   /* 33 */
                    111:        "rtype_34 = ",                  /* 34 */
                    112:        "naptr = ",                     /* 35 */
                    113:        "kx = ",                        /* 36 */
                    114:        "cert = ",                      /* 37 */
                    115:        "v6 address = ",                /* 38 */
                    116:        "dname = ",                     /* 39 */
                    117:        "rtype_40 = ",                  /* 40 */
                    118:        "optional = "                   /* 41 */
                    119: };
                    120:
                    121: #define N_KNOWN_RRTYPES (sizeof(rtypetext) / sizeof(rtypetext[0]))
                    122:
                    123: static void flush_lookup_list(void);
                    124: static void getinput(isc_task_t *task, isc_event_t *event);
                    125:
                    126: static char *
                    127: rcode_totext(dns_rcode_t rcode)
                    128: {
                    129:        static char buf[sizeof("?65535")];
                    130:        union {
                    131:                const char *consttext;
                    132:                char *deconsttext;
                    133:        } totext;
                    134:
                    135:        if (rcode >= (sizeof(rcodetext)/sizeof(rcodetext[0]))) {
                    136:                snprintf(buf, sizeof(buf), "?%u", rcode);
                    137:                totext.deconsttext = buf;
                    138:        } else
                    139:                totext.consttext = rcodetext[rcode];
                    140:        return totext.deconsttext;
                    141: }
                    142:
                    143: static void
                    144: query_finished(void) {
                    145:        isc_event_t *event = global_event;
                    146:
                    147:        flush_lookup_list();
                    148:        debug("dighost_shutdown()");
                    149:
                    150:        if (!in_use) {
                    151:                isc_app_shutdown();
                    152:                return;
                    153:        }
                    154:
                    155:        isc_task_send(global_task, &event);
                    156: }
                    157:
                    158: static void
                    159: printsoa(dns_rdata_t *rdata) {
                    160:        dns_rdata_soa_t soa;
                    161:        isc_result_t result;
                    162:        char namebuf[DNS_NAME_FORMATSIZE];
                    163:
1.7       florian   164:        result = dns_rdata_tostruct_soa(rdata, &soa);
                    165:        check_result(result, "dns_rdata_tostruct_soa");
1.1       florian   166:
                    167:        dns_name_format(&soa.origin, namebuf, sizeof(namebuf));
                    168:        printf("\torigin = %s\n", namebuf);
                    169:        dns_name_format(&soa.contact, namebuf, sizeof(namebuf));
                    170:        printf("\tmail addr = %s\n", namebuf);
                    171:        printf("\tserial = %u\n", soa.serial);
                    172:        printf("\trefresh = %u\n", soa.refresh);
                    173:        printf("\tretry = %u\n", soa.retry);
                    174:        printf("\texpire = %u\n", soa.expire);
                    175:        printf("\tminimum = %u\n", soa.minimum);
1.6       florian   176:        dns_rdata_freestruct_soa(&soa);
1.1       florian   177: }
                    178:
                    179: static void
                    180: printa(dns_rdata_t *rdata) {
                    181:        isc_result_t result;
                    182:        char text[sizeof("255.255.255.255")];
                    183:        isc_buffer_t b;
                    184:
                    185:        isc_buffer_init(&b, text, sizeof(text));
                    186:        result = dns_rdata_totext(rdata, NULL, &b);
                    187:        check_result(result, "dns_rdata_totext");
                    188:        printf("Address: %.*s\n", (int)isc_buffer_usedlength(&b),
                    189:               (char *)isc_buffer_base(&b));
                    190: }
                    191: static void
                    192: printrdata(dns_rdata_t *rdata) {
                    193:        isc_result_t result;
                    194:        isc_buffer_t *b = NULL;
                    195:        unsigned int size = 1024;
1.12    ! florian   196:        int done = 0;
1.1       florian   197:
                    198:        if (rdata->type < N_KNOWN_RRTYPES)
                    199:                printf("%s", rtypetext[rdata->type]);
                    200:        else
                    201:                printf("rdata_%d = ", rdata->type);
                    202:
                    203:        while (!done) {
                    204:                result = isc_buffer_allocate(&b, size);
                    205:                if (result != ISC_R_SUCCESS)
                    206:                        check_result(result, "isc_buffer_allocate");
                    207:                result = dns_rdata_totext(rdata, NULL, b);
                    208:                if (result == ISC_R_SUCCESS) {
                    209:                        printf("%.*s\n", (int)isc_buffer_usedlength(b),
                    210:                               (char *)isc_buffer_base(b));
1.12    ! florian   211:                        done = 1;
1.1       florian   212:                } else if (result != ISC_R_NOSPACE)
                    213:                        check_result(result, "dns_rdata_totext");
                    214:                isc_buffer_free(&b);
                    215:                size *= 2;
                    216:        }
                    217: }
                    218:
                    219: static isc_result_t
1.12    ! florian   220: printsection(dig_query_t *query, dns_message_t *msg, int headers,
1.1       florian   221:             dns_section_t section) {
                    222:        isc_result_t result, loopresult;
                    223:        dns_name_t *name;
                    224:        dns_rdataset_t *rdataset = NULL;
                    225:        dns_rdata_t rdata = DNS_RDATA_INIT;
                    226:        char namebuf[DNS_NAME_FORMATSIZE];
                    227:
                    228:        UNUSED(query);
                    229:        UNUSED(headers);
                    230:
                    231:        debug("printsection()");
                    232:
                    233:        result = dns_message_firstname(msg, section);
                    234:        if (result == ISC_R_NOMORE)
                    235:                return (ISC_R_SUCCESS);
                    236:        else if (result != ISC_R_SUCCESS)
                    237:                return (result);
                    238:        for (;;) {
                    239:                name = NULL;
                    240:                dns_message_currentname(msg, section,
                    241:                                        &name);
                    242:                for (rdataset = ISC_LIST_HEAD(name->list);
                    243:                     rdataset != NULL;
                    244:                     rdataset = ISC_LIST_NEXT(rdataset, link)) {
                    245:                        loopresult = dns_rdataset_first(rdataset);
                    246:                        while (loopresult == ISC_R_SUCCESS) {
                    247:                                dns_rdataset_current(rdataset, &rdata);
                    248:                                switch (rdata.type) {
                    249:                                case dns_rdatatype_a:
                    250:                                        if (section != DNS_SECTION_ANSWER)
                    251:                                                goto def_short_section;
                    252:                                        dns_name_format(name, namebuf,
                    253:                                                        sizeof(namebuf));
                    254:                                        printf("Name:\t%s\n", namebuf);
                    255:                                        printa(&rdata);
                    256:                                        break;
                    257:                                case dns_rdatatype_soa:
                    258:                                        dns_name_format(name, namebuf,
                    259:                                                        sizeof(namebuf));
                    260:                                        printf("%s\n", namebuf);
                    261:                                        printsoa(&rdata);
                    262:                                        break;
                    263:                                default:
                    264:                                def_short_section:
                    265:                                        dns_name_format(name, namebuf,
                    266:                                                        sizeof(namebuf));
                    267:                                        printf("%s\t", namebuf);
                    268:                                        printrdata(&rdata);
                    269:                                        break;
                    270:                                }
                    271:                                dns_rdata_reset(&rdata);
                    272:                                loopresult = dns_rdataset_next(rdataset);
                    273:                        }
                    274:                }
                    275:                result = dns_message_nextname(msg, section);
                    276:                if (result == ISC_R_NOMORE)
                    277:                        break;
                    278:                else if (result != ISC_R_SUCCESS) {
                    279:                        return (result);
                    280:                }
                    281:        }
                    282:        return (ISC_R_SUCCESS);
                    283: }
                    284:
                    285: static isc_result_t
1.12    ! florian   286: detailsection(dig_query_t *query, dns_message_t *msg, int headers,
1.1       florian   287:             dns_section_t section) {
                    288:        isc_result_t result, loopresult;
                    289:        dns_name_t *name;
                    290:        dns_rdataset_t *rdataset = NULL;
                    291:        dns_rdata_t rdata = DNS_RDATA_INIT;
                    292:        char namebuf[DNS_NAME_FORMATSIZE];
                    293:
                    294:        UNUSED(query);
                    295:
                    296:        debug("detailsection()");
                    297:
                    298:        if (headers) {
                    299:                switch (section) {
                    300:                case DNS_SECTION_QUESTION:
                    301:                        puts("    QUESTIONS:");
                    302:                        break;
                    303:                case DNS_SECTION_ANSWER:
                    304:                        puts("    ANSWERS:");
                    305:                        break;
                    306:                case DNS_SECTION_AUTHORITY:
                    307:                        puts("    AUTHORITY RECORDS:");
                    308:                        break;
                    309:                case DNS_SECTION_ADDITIONAL:
                    310:                        puts("    ADDITIONAL RECORDS:");
                    311:                        break;
                    312:                }
                    313:        }
                    314:
                    315:        result = dns_message_firstname(msg, section);
                    316:        if (result == ISC_R_NOMORE)
                    317:                return (ISC_R_SUCCESS);
                    318:        else if (result != ISC_R_SUCCESS)
                    319:                return (result);
                    320:        for (;;) {
                    321:                name = NULL;
                    322:                dns_message_currentname(msg, section,
                    323:                                        &name);
                    324:                for (rdataset = ISC_LIST_HEAD(name->list);
                    325:                     rdataset != NULL;
                    326:                     rdataset = ISC_LIST_NEXT(rdataset, link)) {
                    327:                        if (section == DNS_SECTION_QUESTION) {
                    328:                                dns_name_format(name, namebuf,
                    329:                                                sizeof(namebuf));
                    330:                                printf("\t%s, ", namebuf);
                    331:                                dns_rdatatype_format(rdataset->type,
                    332:                                                     namebuf,
                    333:                                                     sizeof(namebuf));
                    334:                                printf("type = %s, ", namebuf);
                    335:                                dns_rdataclass_format(rdataset->rdclass,
                    336:                                                      namebuf,
                    337:                                                      sizeof(namebuf));
                    338:                                printf("class = %s\n", namebuf);
                    339:                        }
                    340:                        loopresult = dns_rdataset_first(rdataset);
                    341:                        while (loopresult == ISC_R_SUCCESS) {
                    342:                                dns_rdataset_current(rdataset, &rdata);
                    343:
                    344:                                dns_name_format(name, namebuf,
                    345:                                                sizeof(namebuf));
                    346:                                printf("    ->  %s\n", namebuf);
                    347:
                    348:                                switch (rdata.type) {
                    349:                                case dns_rdatatype_soa:
                    350:                                        printsoa(&rdata);
                    351:                                        break;
                    352:                                default:
                    353:                                        printf("\t");
                    354:                                        printrdata(&rdata);
                    355:                                }
                    356:                                dns_rdata_reset(&rdata);
                    357:                                printf("\tttl = %u\n", rdataset->ttl);
                    358:                                loopresult = dns_rdataset_next(rdataset);
                    359:                        }
                    360:                }
                    361:                result = dns_message_nextname(msg, section);
                    362:                if (result == ISC_R_NOMORE)
                    363:                        break;
                    364:                else if (result != ISC_R_SUCCESS) {
                    365:                        return (result);
                    366:                }
                    367:        }
                    368:        return (ISC_R_SUCCESS);
                    369: }
                    370:
                    371: static void
                    372: received(unsigned int bytes, isc_sockaddr_t *from, dig_query_t *query)
                    373: {
                    374:        UNUSED(bytes);
                    375:        UNUSED(from);
                    376:        UNUSED(query);
                    377: }
                    378:
                    379: static void
                    380: trying(char *frm, dig_lookup_t *lookup) {
                    381:        UNUSED(frm);
                    382:        UNUSED(lookup);
                    383: }
                    384:
                    385: static isc_result_t
1.12    ! florian   386: printmessage(dig_query_t *query, dns_message_t *msg, int headers) {
1.1       florian   387:        char servtext[ISC_SOCKADDR_FORMATSIZE];
                    388:
                    389:        /* I've we've gotten this far, we've reached a server. */
                    390:        query_error = 0;
                    391:
                    392:        debug("printmessage()");
                    393:
                    394:        isc_sockaddr_format(&query->sockaddr, servtext, sizeof(servtext));
                    395:        printf("Server:\t\t%s\n", query->userarg);
                    396:        printf("Address:\t%s\n", servtext);
                    397:
                    398:        puts("");
                    399:
                    400:        if (!short_form) {
                    401:                puts("------------");
                    402:                /*              detailheader(query, msg);*/
1.12    ! florian   403:                detailsection(query, msg, 1, DNS_SECTION_QUESTION);
        !           404:                detailsection(query, msg, 1, DNS_SECTION_ANSWER);
        !           405:                detailsection(query, msg, 1, DNS_SECTION_AUTHORITY);
        !           406:                detailsection(query, msg, 1, DNS_SECTION_ADDITIONAL);
1.1       florian   407:                puts("------------");
                    408:        }
                    409:
                    410:        if (msg->rcode != 0) {
                    411:                char nametext[DNS_NAME_FORMATSIZE];
                    412:                dns_name_format(query->lookup->name,
                    413:                                nametext, sizeof(nametext));
                    414:                printf("** server can't find %s: %s\n",
                    415:                       nametext, rcode_totext(msg->rcode));
                    416:                debug("returning with rcode == 0");
                    417:
                    418:                /* the lookup failed */
                    419:                print_error |= 1;
                    420:                return (ISC_R_SUCCESS);
                    421:        }
                    422:
                    423:        if ((msg->flags & DNS_MESSAGEFLAG_AA) == 0)
                    424:                puts("Non-authoritative answer:");
                    425:        if (!ISC_LIST_EMPTY(msg->sections[DNS_SECTION_ANSWER]))
                    426:                printsection(query, msg, headers, DNS_SECTION_ANSWER);
                    427:        else
                    428:                printf("*** Can't find %s: No answer\n",
                    429:                       query->lookup->textname);
                    430:
                    431:        if (((msg->flags & DNS_MESSAGEFLAG_AA) == 0) &&
                    432:            (query->lookup->rdtype != dns_rdatatype_a)) {
                    433:                puts("\nAuthoritative answers can be found from:");
                    434:                printsection(query, msg, headers,
                    435:                             DNS_SECTION_AUTHORITY);
                    436:                printsection(query, msg, headers,
                    437:                             DNS_SECTION_ADDITIONAL);
                    438:        }
                    439:        return (ISC_R_SUCCESS);
                    440: }
                    441:
                    442: static void
1.12    ! florian   443: show_settings(int full, int serv_only) {
1.1       florian   444:        dig_server_t *srv;
                    445:        isc_sockaddr_t sockaddr;
                    446:        dig_searchlist_t *listent;
                    447:        isc_result_t result;
                    448:
                    449:        srv = ISC_LIST_HEAD(server_list);
                    450:
                    451:        while (srv != NULL) {
                    452:                char sockstr[ISC_SOCKADDR_FORMATSIZE];
                    453:
                    454:                result = get_address(srv->servername, port, &sockaddr);
                    455:                check_result(result, "get_address");
                    456:
                    457:                isc_sockaddr_format(&sockaddr, sockstr, sizeof(sockstr));
                    458:                printf("Default server: %s\nAddress: %s\n",
                    459:                        srv->userarg, sockstr);
                    460:                if (!full)
                    461:                        return;
                    462:                srv = ISC_LIST_NEXT(srv, link);
                    463:        }
                    464:        if (serv_only)
                    465:                return;
                    466:        printf("\nSet options:\n");
                    467:        printf("  %s\t\t\t%s\t\t%s\n",
                    468:               tcpmode ? "vc" : "novc",
                    469:               short_form ? "nodebug" : "debug",
                    470:               debugging ? "d2" : "nod2");
                    471:        printf("  %s\t\t%s\n",
                    472:               usesearch ? "search" : "nosearch",
                    473:               recurse ? "recurse" : "norecurse");
                    474:        printf("  timeout = %u\t\tretry = %d\tport = %u\tndots = %d\n",
                    475:               timeout, tries, port, ndots);
                    476:        printf("  querytype = %-8s\tclass = %s\n", deftype, defclass);
                    477:        printf("  srchlist = ");
                    478:        for (listent = ISC_LIST_HEAD(search_list);
                    479:             listent != NULL;
                    480:             listent = ISC_LIST_NEXT(listent, link)) {
                    481:                     printf("%s", listent->origin);
                    482:                     if (ISC_LIST_NEXT(listent, link) != NULL)
                    483:                             printf("/");
                    484:        }
                    485:        printf("\n");
                    486: }
                    487:
1.12    ! florian   488: static int
1.1       florian   489: testtype(char *typetext) {
                    490:        isc_result_t result;
                    491:        isc_textregion_t tr;
                    492:        dns_rdatatype_t rdtype;
                    493:
                    494:        tr.base = typetext;
                    495:        tr.length = strlen(typetext);
                    496:        result = dns_rdatatype_fromtext(&rdtype, &tr);
                    497:        if (result == ISC_R_SUCCESS)
1.12    ! florian   498:                return (1);
1.1       florian   499:        else {
                    500:                printf("unknown query type: %s\n", typetext);
1.12    ! florian   501:                return (0);
1.1       florian   502:        }
                    503: }
                    504:
1.12    ! florian   505: static int
1.1       florian   506: testclass(char *typetext) {
                    507:        isc_result_t result;
                    508:        isc_textregion_t tr;
                    509:        dns_rdataclass_t rdclass;
                    510:
                    511:        tr.base = typetext;
                    512:        tr.length = strlen(typetext);
                    513:        result = dns_rdataclass_fromtext(&rdclass, &tr);
                    514:        if (result == ISC_R_SUCCESS)
1.12    ! florian   515:                return (1);
1.1       florian   516:        else {
                    517:                printf("unknown query class: %s\n", typetext);
1.12    ! florian   518:                return (0);
1.1       florian   519:        }
                    520: }
                    521:
                    522: static void
                    523: set_port(const char *value) {
                    524:        uint32_t n;
1.11      florian   525:        const char *errstr;
                    526:
                    527:        n = strtonum(value, 0, 65535, &errstr);
                    528:        if (errstr == NULL)
1.1       florian   529:                port = (uint16_t) n;
1.11      florian   530:        else
                    531:                printf("port is %s: '%s'\n", errstr, value);
1.1       florian   532: }
                    533:
                    534: static void
                    535: set_timeout(const char *value) {
                    536:        uint32_t n;
1.11      florian   537:        const char *errstr;
                    538:
                    539:        n = strtonum(value, 0, UINT_MAX, &errstr);
                    540:        if (errstr == NULL)
1.1       florian   541:                timeout = n;
1.11      florian   542:        else
                    543:                printf("timeout is %s: '%s'\n", errstr, value);
1.1       florian   544: }
                    545:
                    546: static void
                    547: set_tries(const char *value) {
                    548:        uint32_t n;
1.11      florian   549:        const char *errstr;
                    550:
                    551:        n = strtonum(value, 0, INT_MAX, &errstr);
                    552:        if (errstr == NULL)
1.1       florian   553:                tries = n;
1.11      florian   554:        else
                    555:                printf("tries is %s: '%s'\n", errstr, value);
1.1       florian   556: }
                    557:
                    558: static void
                    559: set_ndots(const char *value) {
                    560:        uint32_t n;
1.11      florian   561:        const char *errstr;
                    562:
                    563:        n = strtonum(value, 0, 128, &errstr);
                    564:        if (errstr == NULL)
1.1       florian   565:                ndots = n;
1.11      florian   566:        else
                    567:                printf("ndots is %s: '%s'\n", errstr, value);
1.1       florian   568: }
                    569:
                    570: static void
                    571: version(void) {
                    572:        fputs("nslookup " VERSION "\n", stderr);
                    573: }
                    574:
                    575: static void
                    576: setoption(char *opt) {
                    577:        size_t l = strlen(opt);
                    578:
                    579: #define CHECKOPT(A, N) \
                    580:        ((l >= N) && (l < sizeof(A)) && (strncasecmp(opt, A, l) == 0))
                    581:
                    582:        if (CHECKOPT("all", 3)) {
1.12    ! florian   583:                show_settings(1, 0);
1.1       florian   584:        } else if (strncasecmp(opt, "class=", 6) == 0) {
                    585:                if (testclass(&opt[6]))
                    586:                        strlcpy(defclass, &opt[6], sizeof(defclass));
                    587:        } else if (strncasecmp(opt, "cl=", 3) == 0) {
                    588:                if (testclass(&opt[3]))
                    589:                        strlcpy(defclass, &opt[3], sizeof(defclass));
                    590:        } else if (strncasecmp(opt, "type=", 5) == 0) {
                    591:                if (testtype(&opt[5]))
                    592:                        strlcpy(deftype, &opt[5], sizeof(deftype));
                    593:        } else if (strncasecmp(opt, "ty=", 3) == 0) {
                    594:                if (testtype(&opt[3]))
                    595:                        strlcpy(deftype, &opt[3], sizeof(deftype));
                    596:        } else if (strncasecmp(opt, "querytype=", 10) == 0) {
                    597:                if (testtype(&opt[10]))
                    598:                        strlcpy(deftype, &opt[10], sizeof(deftype));
                    599:        } else if (strncasecmp(opt, "query=", 6) == 0) {
                    600:                if (testtype(&opt[6]))
                    601:                        strlcpy(deftype, &opt[6], sizeof(deftype));
                    602:        } else if (strncasecmp(opt, "qu=", 3) == 0) {
                    603:                if (testtype(&opt[3]))
                    604:                        strlcpy(deftype, &opt[3], sizeof(deftype));
                    605:        } else if (strncasecmp(opt, "q=", 2) == 0) {
                    606:                if (testtype(&opt[2]))
                    607:                        strlcpy(deftype, &opt[2], sizeof(deftype));
                    608:        } else if (strncasecmp(opt, "domain=", 7) == 0) {
                    609:                strlcpy(domainopt, &opt[7], sizeof(domainopt));
                    610:                set_search_domain(domainopt);
1.12    ! florian   611:                usesearch = 1;
1.1       florian   612:        } else if (strncasecmp(opt, "do=", 3) == 0) {
                    613:                strlcpy(domainopt, &opt[3], sizeof(domainopt));
                    614:                set_search_domain(domainopt);
1.12    ! florian   615:                usesearch = 1;
1.1       florian   616:        } else if (strncasecmp(opt, "port=", 5) == 0) {
                    617:                set_port(&opt[5]);
                    618:        } else if (strncasecmp(opt, "po=", 3) == 0) {
                    619:                set_port(&opt[3]);
                    620:        } else if (strncasecmp(opt, "timeout=", 8) == 0) {
                    621:                set_timeout(&opt[8]);
                    622:        } else if (strncasecmp(opt, "t=", 2) == 0) {
                    623:                set_timeout(&opt[2]);
                    624:        } else if (CHECKOPT("recurse", 3)) {
1.12    ! florian   625:                recurse = 1;
1.1       florian   626:        } else if (CHECKOPT("norecurse", 5)) {
1.12    ! florian   627:                recurse = 0;
1.1       florian   628:        } else if (strncasecmp(opt, "retry=", 6) == 0) {
                    629:                set_tries(&opt[6]);
                    630:        } else if (strncasecmp(opt, "ret=", 4) == 0) {
                    631:                set_tries(&opt[4]);
                    632:        } else if (CHECKOPT("defname", 3)) {
1.12    ! florian   633:                usesearch = 1;
1.1       florian   634:        } else if (CHECKOPT("nodefname", 5)) {
1.12    ! florian   635:                usesearch = 0;
1.1       florian   636:        } else if (CHECKOPT("vc", 2) == 0) {
1.12    ! florian   637:                tcpmode = 1;
1.1       florian   638:        } else if (CHECKOPT("novc", 4) == 0) {
1.12    ! florian   639:                tcpmode = 0;
1.1       florian   640:        } else if (CHECKOPT("debug", 3) == 0) {
1.12    ! florian   641:                short_form = 0;
        !           642:                showsearch = 1;
1.1       florian   643:        } else if (CHECKOPT("nodebug", 5) == 0) {
1.12    ! florian   644:                short_form = 1;
        !           645:                showsearch = 0;
1.1       florian   646:        } else if (CHECKOPT("d2", 2) == 0) {
1.12    ! florian   647:                debugging = 1;
1.1       florian   648:        } else if (CHECKOPT("nod2", 4) == 0) {
1.12    ! florian   649:                debugging = 0;
1.1       florian   650:        } else if (CHECKOPT("search", 3) == 0) {
1.12    ! florian   651:                usesearch = 1;
1.1       florian   652:        } else if (CHECKOPT("nosearch", 5) == 0) {
1.12    ! florian   653:                usesearch = 0;
1.1       florian   654:        } else if (CHECKOPT("sil", 3) == 0) {
1.12    ! florian   655:                /* deprecation_msg = 0; */
1.1       florian   656:        } else if (CHECKOPT("fail", 3) == 0) {
1.12    ! florian   657:                nofail=0;
1.1       florian   658:        } else if (CHECKOPT("nofail", 5) == 0) {
1.12    ! florian   659:                nofail=1;
1.1       florian   660:        } else if (strncasecmp(opt, "ndots=", 6) == 0) {
                    661:                set_ndots(&opt[6]);
                    662:        } else {
                    663:                printf("*** Invalid option: %s\n", opt);
                    664:        }
                    665: }
                    666:
                    667: static void
                    668: addlookup(char *opt) {
                    669:        dig_lookup_t *lookup;
                    670:        isc_result_t result;
                    671:        isc_textregion_t tr;
                    672:        dns_rdatatype_t rdtype;
                    673:        dns_rdataclass_t rdclass;
                    674:        char store[MXNAME];
                    675:
                    676:        debug("addlookup()");
                    677:        tr.base = deftype;
                    678:        tr.length = strlen(deftype);
                    679:        result = dns_rdatatype_fromtext(&rdtype, &tr);
                    680:        if (result != ISC_R_SUCCESS) {
                    681:                printf("unknown query type: %s\n", deftype);
                    682:                rdclass = dns_rdatatype_a;
                    683:        }
                    684:        tr.base = defclass;
                    685:        tr.length = strlen(defclass);
                    686:        result = dns_rdataclass_fromtext(&rdclass, &tr);
                    687:        if (result != ISC_R_SUCCESS) {
                    688:                printf("unknown query class: %s\n", defclass);
                    689:                rdclass = dns_rdataclass_in;
                    690:        }
                    691:        lookup = make_empty_lookup();
1.12    ! florian   692:        if (get_reverse(store, sizeof(store), opt, lookup->ip6_int, 1)
1.1       florian   693:            == ISC_R_SUCCESS) {
                    694:                strlcpy(lookup->textname, store, sizeof(lookup->textname));
                    695:                lookup->rdtype = dns_rdatatype_ptr;
1.12    ! florian   696:                lookup->rdtypeset = 1;
1.1       florian   697:        } else {
                    698:                strlcpy(lookup->textname, opt, sizeof(lookup->textname));
                    699:                lookup->rdtype = rdtype;
1.12    ! florian   700:                lookup->rdtypeset = 1;
1.1       florian   701:        }
                    702:        lookup->rdclass = rdclass;
1.12    ! florian   703:        lookup->rdclassset = 1;
        !           704:        lookup->trace = 0;
1.1       florian   705:        lookup->trace_root = lookup->trace;
1.12    ! florian   706:        lookup->ns_search_only = 0;
1.1       florian   707:        lookup->identify = identify;
                    708:        lookup->recurse = recurse;
                    709:        lookup->aaonly = aaonly;
                    710:        lookup->retries = tries;
                    711:        lookup->udpsize = 0;
                    712:        lookup->comments = comments;
                    713:        lookup->tcp_mode = tcpmode;
                    714:        lookup->stats = stats;
                    715:        lookup->section_question = section_question;
                    716:        lookup->section_answer = section_answer;
                    717:        lookup->section_authority = section_authority;
                    718:        lookup->section_additional = section_additional;
1.12    ! florian   719:        lookup->new_search = 1;
1.1       florian   720:        if (nofail)
1.12    ! florian   721:                lookup->servfail_stops = 0;
1.1       florian   722:        ISC_LIST_INIT(lookup->q);
                    723:        ISC_LINK_INIT(lookup, link);
                    724:        ISC_LIST_APPEND(lookup_list, lookup, link);
                    725:        lookup->origin = NULL;
                    726:        ISC_LIST_INIT(lookup->my_server_list);
                    727:        debug("looking up %s", lookup->textname);
                    728: }
                    729:
                    730: static void
                    731: do_next_command(char *input) {
                    732:        char *ptr, *arg;
                    733:
                    734:        ptr = next_token(&input, " \t\r\n");
                    735:        if (ptr == NULL)
                    736:                return;
                    737:        arg = next_token(&input, " \t\r\n");
1.10      deraadt   738:        if (strcasecmp(ptr, "set") == 0) {
                    739:                if (arg == NULL)
                    740:                        printf("Usage: set keyword=value, or set all\n");
                    741:                else
                    742:                        setoption(arg);
                    743:        } else if ((strcasecmp(ptr, "server") == 0) ||
1.1       florian   744:                 (strcasecmp(ptr, "lserver") == 0)) {
1.9       deraadt   745:                isc_result_t res;
                    746:
                    747:                if (arg == NULL)
                    748:                        printf("usage: server hostname\n");
                    749:                else if ((res = set_nameserver(arg))) {
                    750:                        printf("couldn't get address for '%s': %s\n",
                    751:                            arg, isc_result_totext(res));
                    752:                } else {
1.12    ! florian   753:                        check_ra = 0;
        !           754:                        show_settings(1, 1);
1.9       deraadt   755:                }
1.1       florian   756:        } else if (strcasecmp(ptr, "exit") == 0) {
1.12    ! florian   757:                in_use = 0;
1.1       florian   758:        } else if (strcasecmp(ptr, "help") == 0 ||
                    759:                   strcasecmp(ptr, "?") == 0) {
                    760:                printf("The '%s' command is not yet implemented.\n", ptr);
                    761:        } else if (strcasecmp(ptr, "finger") == 0 ||
                    762:                   strcasecmp(ptr, "root") == 0 ||
                    763:                   strcasecmp(ptr, "ls") == 0 ||
                    764:                   strcasecmp(ptr, "view") == 0) {
                    765:                printf("The '%s' command is not implemented.\n", ptr);
                    766:        } else
                    767:                addlookup(ptr);
                    768: }
                    769:
                    770: static void
                    771: get_next_command(void) {
                    772:        char *buf;
                    773:        char *ptr;
                    774:
                    775:        fflush(stdout);
                    776:        buf = malloc(COMMSIZE);
                    777:        if (buf == NULL)
                    778:                fatal("memory allocation failure");
                    779:        if (interactive) {
                    780:                fputs("> ", stderr);
                    781:                fflush(stderr);
                    782:                ptr = fgets(buf, COMMSIZE, stdin);
                    783:        } else
                    784:                ptr = fgets(buf, COMMSIZE, stdin);
                    785:        if (ptr == NULL) {
1.12    ! florian   786:                in_use = 0;
1.1       florian   787:        } else
                    788:                do_next_command(ptr);
                    789:        free(buf);
                    790: }
                    791:
                    792: static void
                    793: parse_args(int argc, char **argv) {
1.12    ! florian   794:        int have_lookup = 0;
1.1       florian   795:
1.12    ! florian   796:        usesearch = 1;
1.1       florian   797:        for (argc--, argv++; argc > 0; argc--, argv++) {
                    798:                debug("main parsing %s", argv[0]);
                    799:                if (argv[0][0] == '-') {
                    800:                        if (strncasecmp(argv[0], "-ver", 4) == 0) {
                    801:                                version();
                    802:                                exit(0);
                    803:                        } else if (argv[0][1] != 0) {
                    804:                                setoption(&argv[0][1]);
                    805:                        } else
1.12    ! florian   806:                                have_lookup = 1;
1.1       florian   807:                } else {
                    808:                        if (!have_lookup) {
1.12    ! florian   809:                                have_lookup = 1;
        !           810:                                in_use = 1;
1.1       florian   811:                                addlookup(argv[0]);
                    812:                        } else {
1.9       deraadt   813:                                isc_result_t res;
                    814:
                    815:                                if ((res = set_nameserver(argv[0])))
                    816:                                        fatal("couldn't get address for '%s': %s",
                    817:                                            argv[0], isc_result_totext(res));
1.12    ! florian   818:                                check_ra = 0;
1.1       florian   819:                        }
                    820:                }
                    821:        }
                    822: }
                    823:
                    824: static void
                    825: flush_lookup_list(void) {
                    826:        dig_lookup_t *l, *lp;
                    827:        dig_query_t *q, *qp;
                    828:        dig_server_t *s, *sp;
                    829:
                    830:        lookup_counter = 0;
                    831:        l = ISC_LIST_HEAD(lookup_list);
                    832:        while (l != NULL) {
                    833:                q = ISC_LIST_HEAD(l->q);
                    834:                while (q != NULL) {
                    835:                        if (q->sock != NULL) {
                    836:                                isc_socket_cancel(q->sock, NULL,
                    837:                                                  ISC_SOCKCANCEL_ALL);
                    838:                                isc_socket_detach(&q->sock);
                    839:                        }
                    840:                        if (ISC_LINK_LINKED(&q->recvbuf, link))
                    841:                                ISC_LIST_DEQUEUE(q->recvlist, &q->recvbuf,
                    842:                                                 link);
                    843:                        if (ISC_LINK_LINKED(&q->lengthbuf, link))
                    844:                                ISC_LIST_DEQUEUE(q->lengthlist, &q->lengthbuf,
                    845:                                                 link);
                    846:                        isc_buffer_invalidate(&q->recvbuf);
                    847:                        isc_buffer_invalidate(&q->lengthbuf);
                    848:                        qp = q;
                    849:                        q = ISC_LIST_NEXT(q, link);
                    850:                        ISC_LIST_DEQUEUE(l->q, qp, link);
                    851:                        free(qp);
                    852:                }
                    853:                s = ISC_LIST_HEAD(l->my_server_list);
                    854:                while (s != NULL) {
                    855:                        sp = s;
                    856:                        s = ISC_LIST_NEXT(s, link);
                    857:                        ISC_LIST_DEQUEUE(l->my_server_list, sp, link);
                    858:                        free(sp);
                    859:
                    860:                }
                    861:                if (l->sendmsg != NULL)
                    862:                        dns_message_destroy(&l->sendmsg);
                    863:                lp = l;
                    864:                l = ISC_LIST_NEXT(l, link);
                    865:                ISC_LIST_DEQUEUE(lookup_list, lp, link);
                    866:                free(lp);
                    867:        }
                    868: }
                    869:
                    870: static void
                    871: getinput(isc_task_t *task, isc_event_t *event) {
                    872:        UNUSED(task);
                    873:        if (global_event == NULL)
                    874:                global_event = event;
                    875:        while (in_use) {
                    876:                get_next_command();
                    877:                if (ISC_LIST_HEAD(lookup_list) != NULL) {
                    878:                        start_lookup();
                    879:                        return;
                    880:                }
                    881:        }
                    882:        isc_app_shutdown();
                    883: }
                    884:
                    885: int
                    886: nslookup_main(int argc, char **argv) {
                    887:        isc_result_t result;
                    888:
1.12    ! florian   889:        interactive = isatty(0);
1.1       florian   890:
                    891:        ISC_LIST_INIT(lookup_list);
                    892:        ISC_LIST_INIT(server_list);
1.3       florian   893:        ISC_LIST_INIT(root_hints_server_list);
1.1       florian   894:        ISC_LIST_INIT(search_list);
                    895:
1.12    ! florian   896:        check_ra = 1;
1.1       florian   897:
                    898:        /* setup dighost callbacks */
                    899:        dighost_printmessage = printmessage;
                    900:        dighost_received = received;
                    901:        dighost_trying = trying;
                    902:        dighost_shutdown = query_finished;
                    903:
                    904:        result = isc_app_start();
                    905:        check_result(result, "isc_app_start");
                    906:
                    907:        if (pledge("stdio rpath inet dns", NULL) == -1) {
                    908:                perror("pledge");
                    909:                exit(1);
                    910:        }
                    911:
                    912:        setup_libs();
                    913:        progname = argv[0];
                    914:
                    915:        if (pledge("stdio inet dns", NULL) == -1) {
                    916:                perror("pledge");
                    917:                exit(1);
                    918:        }
                    919:
                    920:        parse_args(argc, argv);
                    921:
1.12    ! florian   922:        setup_system(0, 0);
1.1       florian   923:        if (domainopt[0] != '\0')
                    924:                set_search_domain(domainopt);
                    925:        if (in_use)
                    926:                result = isc_app_onrun(global_task, onrun_callback,
                    927:                                       NULL);
                    928:        else
                    929:                result = isc_app_onrun(global_task, getinput, NULL);
                    930:        check_result(result, "isc_app_onrun");
1.12    ! florian   931:        in_use = !in_use;
1.1       florian   932:
                    933:        (void)isc_app_run();
                    934:
                    935:        puts("");
                    936:        debug("done, and starting to shut down");
                    937:        if (global_event != NULL)
                    938:                isc_event_free(&global_event);
                    939:        cancel_all();
                    940:        destroy_libs();
                    941:
                    942:        return (query_error | print_error);
                    943: }