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

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