15185a700Sflorian /* 25185a700Sflorian * Copyright (C) Internet Systems Consortium, Inc. ("ISC") 35185a700Sflorian * 45185a700Sflorian * Permission to use, copy, modify, and/or distribute this software for any 55185a700Sflorian * purpose with or without fee is hereby granted, provided that the above 65185a700Sflorian * copyright notice and this permission notice appear in all copies. 75185a700Sflorian * 85185a700Sflorian * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH 95185a700Sflorian * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 105185a700Sflorian * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, 115185a700Sflorian * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 125185a700Sflorian * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 135185a700Sflorian * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 145185a700Sflorian * PERFORMANCE OF THIS SOFTWARE. 155185a700Sflorian */ 165185a700Sflorian 17*9835a5e1Sflorian /* $Id: dig.c,v 1.21 2024/12/27 09:04:48 florian Exp $ */ 185185a700Sflorian 195185a700Sflorian /*! \file */ 2033e1be9eSflorian #include <sys/types.h> 2133e1be9eSflorian #include <sys/socket.h> 2233e1be9eSflorian 2333e1be9eSflorian #include <netdb.h> 245185a700Sflorian 25c49c5f05Sflorian #include <errno.h> 265185a700Sflorian #include <stdlib.h> 275185a700Sflorian #include <time.h> 285185a700Sflorian #include <unistd.h> 295185a700Sflorian 305185a700Sflorian #include <isc/app.h> 315185a700Sflorian 325185a700Sflorian #include <string.h> 335185a700Sflorian #include <isc/util.h> 345185a700Sflorian 355185a700Sflorian #include <dns/fixedname.h> 365185a700Sflorian #include <dns/masterdump.h> 375185a700Sflorian #include <dns/message.h> 385185a700Sflorian #include <dns/name.h> 395185a700Sflorian #include <dns/rdata.h> 405185a700Sflorian #include <dns/rdataset.h> 415185a700Sflorian #include <dns/rdatatype.h> 425185a700Sflorian #include <dns/rdataclass.h> 435185a700Sflorian #include <dns/result.h> 445185a700Sflorian #include <dns/tsig.h> 455185a700Sflorian 465185a700Sflorian #include "dig.h" 475185a700Sflorian 485185a700Sflorian #define ADD_STRING(b, s) { \ 495185a700Sflorian if (strlen(s) >= isc_buffer_availablelength(b)) \ 505185a700Sflorian return (ISC_R_NOSPACE); \ 515185a700Sflorian else \ 525185a700Sflorian isc_buffer_putstr(b, s); \ 535185a700Sflorian } 545185a700Sflorian 555185a700Sflorian dig_lookup_t *default_lookup = NULL; 565185a700Sflorian 575185a700Sflorian static char *batchname = NULL; 585185a700Sflorian static FILE *batchfp = NULL; 595185a700Sflorian static char *argv0; 605185a700Sflorian static int addresscount = 0; 615185a700Sflorian 625185a700Sflorian static char domainopt[DNS_NAME_MAXTEXT]; 635185a700Sflorian static char sitvalue[256]; 645185a700Sflorian 651fb015a8Sflorian static int short_form = 0, printcmd = 1, 661fb015a8Sflorian ip6_int = 0, plusquest = 0, pluscomm = 0, 671fb015a8Sflorian multiline = 0, nottl = 0, noclass = 0, 681fb015a8Sflorian onesoa = 0, use_usec = 0, nocrypto = 0, 691fb015a8Sflorian ipv4only = 0, ipv6only = 0; 705185a700Sflorian static uint32_t splitwidth = 0xffffffff; 715185a700Sflorian 725185a700Sflorian /*% rrcomments are neither explicitly enabled nor disabled by default */ 735185a700Sflorian static int rrcomments = 0; 745185a700Sflorian 755185a700Sflorian /*% opcode text */ 765185a700Sflorian static const char * const opcodetext[] = { 775185a700Sflorian "QUERY", 785185a700Sflorian "IQUERY", 795185a700Sflorian "STATUS", 805185a700Sflorian "RESERVED3", 815185a700Sflorian "NOTIFY", 825185a700Sflorian "UPDATE", 835185a700Sflorian "RESERVED6", 845185a700Sflorian "RESERVED7", 855185a700Sflorian "RESERVED8", 865185a700Sflorian "RESERVED9", 875185a700Sflorian "RESERVED10", 885185a700Sflorian "RESERVED11", 895185a700Sflorian "RESERVED12", 905185a700Sflorian "RESERVED13", 915185a700Sflorian "RESERVED14", 925185a700Sflorian "RESERVED15" 935185a700Sflorian }; 945185a700Sflorian 955185a700Sflorian /*% return code text */ 965185a700Sflorian static const char * const rcodetext[] = { 975185a700Sflorian "NOERROR", 985185a700Sflorian "FORMERR", 995185a700Sflorian "SERVFAIL", 1005185a700Sflorian "NXDOMAIN", 1015185a700Sflorian "NOTIMP", 1025185a700Sflorian "REFUSED", 1035185a700Sflorian "YXDOMAIN", 1045185a700Sflorian "YXRRSET", 1055185a700Sflorian "NXRRSET", 1065185a700Sflorian "NOTAUTH", 1075185a700Sflorian "NOTZONE", 1085185a700Sflorian "RESERVED11", 1095185a700Sflorian "RESERVED12", 1105185a700Sflorian "RESERVED13", 1115185a700Sflorian "RESERVED14", 1125185a700Sflorian "RESERVED15", 1135185a700Sflorian "BADVERS" 1145185a700Sflorian }; 1155185a700Sflorian 1165185a700Sflorian /*% safe rcodetext[] */ 1175185a700Sflorian static const char * 1185185a700Sflorian rcode_totext(dns_rcode_t rcode) 1195185a700Sflorian { 1205185a700Sflorian static char buf[sizeof("?65535")]; 1215185a700Sflorian 1225185a700Sflorian if (rcode == dns_rcode_badcookie) 1235185a700Sflorian return ("BADCOOKIE"); 1245185a700Sflorian if (rcode >= (sizeof(rcodetext)/sizeof(rcodetext[0]))) { 1255185a700Sflorian snprintf(buf, sizeof(buf), "?%u", rcode); 1265185a700Sflorian return (buf); 1275185a700Sflorian } 1285185a700Sflorian return (rcodetext[rcode]); 1295185a700Sflorian } 1305185a700Sflorian 1315185a700Sflorian /*% print usage */ 1325185a700Sflorian static void 1335185a700Sflorian print_usage(FILE *fp) { 1345185a700Sflorian fputs( 13565e34726Sschwarze "usage: dig [@server] [-46hiuv] [-b sourceaddr[#port]] [-c class] [-f file]\n" 1365185a700Sflorian " [-k keyfile] [-p port] [-q name] [-t type] [-x addr]\n" 1375185a700Sflorian " [-y [hmac:]name:key] [name] [type] [class]\n" 1385185a700Sflorian " +[no]aaonly +[no]additional +[no]adflag +[no]all +[no]answer\n" 1395185a700Sflorian " +[no]authority +[no]besteffort +bufsize=# +[no]cdflag +[no]class\n" 1405185a700Sflorian " +[no]cmd +[no]comments +[no]cookie[=value] +[no]crypto +[no]dnssec\n" 1415185a700Sflorian " +domain=name +[no]edns[=#] +ednsflags[=#] +[no]ednsnegotiation\n" 1425185a700Sflorian " +[no]ednsopt[=code[:value]] +[no]expire +[no]fail +[no]identify\n" 1435185a700Sflorian " +[no]ignore +[no]keepopen +[no]multiline +ndots=# +[no]nsid\n" 1445185a700Sflorian " +[no]nssearch +[no]onesoa +[no]opcode=# +[no]qr +[no]question\n" 1455185a700Sflorian " +[no]recurse +retry=# +[no]rrcomments +[no]search +[no]short\n" 1465185a700Sflorian " +[no]showsearch +[no]split=# +[no]stats +[no]subnet=addr[/prefix]\n" 1475185a700Sflorian " +[no]tcp +timeout=# +[no]trace +tries=# +[no]ttlid +[no]vc\n", fp); 1485185a700Sflorian } 1495185a700Sflorian 1505185a700Sflorian static __dead void 1515185a700Sflorian usage(void); 1525185a700Sflorian 1535185a700Sflorian static void 1545185a700Sflorian usage(void) { 1555185a700Sflorian print_usage(stderr); 1565185a700Sflorian exit(1); 1575185a700Sflorian } 1585185a700Sflorian 1595185a700Sflorian /*% version */ 1605185a700Sflorian static void 1615185a700Sflorian version(void) { 1625185a700Sflorian fputs("dig " VERSION "\n", stderr); 1635185a700Sflorian } 1645185a700Sflorian 1655185a700Sflorian /*% help */ 1665185a700Sflorian static void 1675185a700Sflorian help(void) { 1685185a700Sflorian print_usage(stdout); 1695185a700Sflorian } 1705185a700Sflorian 1715185a700Sflorian /*% 1725185a700Sflorian * Callback from dighost.c to print the received message. 1735185a700Sflorian */ 1745185a700Sflorian static void 175b1a294b5Sflorian received(unsigned int bytes, struct sockaddr_storage *from, dig_query_t *query) { 1765185a700Sflorian time_t tnow; 1775185a700Sflorian struct tm tmnow; 1785185a700Sflorian char time_str[100]; 1795185a700Sflorian char fromtext[ISC_SOCKADDR_FORMATSIZE]; 1805185a700Sflorian 1815185a700Sflorian isc_sockaddr_format(from, fromtext, sizeof(fromtext)); 1825185a700Sflorian 1835185a700Sflorian if (query->lookup->stats && !short_form) { 1845185a700Sflorian if (use_usec) 185427f8978Sflorian printf(";; Query time: %lld usec\n", 186427f8978Sflorian uelapsed(&query->time_recv, &query->time_sent)); 1875185a700Sflorian else 188427f8978Sflorian printf(";; Query time: %lld msec\n", 189427f8978Sflorian uelapsed(&query->time_recv, &query->time_sent) / 190427f8978Sflorian 1000); 1915185a700Sflorian printf(";; SERVER: %s(%s)\n", fromtext, query->servname); 1925185a700Sflorian time(&tnow); 1935185a700Sflorian tmnow = *localtime(&tnow); 1945185a700Sflorian 1955185a700Sflorian if (strftime(time_str, sizeof(time_str), 1965185a700Sflorian "%a %b %d %H:%M:%S %Z %Y", &tmnow) > 0U) 1975185a700Sflorian printf(";; WHEN: %s\n", time_str); 1985185a700Sflorian if (query->lookup->doing_xfr) { 1995185a700Sflorian printf(";; XFR size: %u records (messages %u, " 2005185a700Sflorian "bytes %llu)\n", 2015185a700Sflorian query->rr_count, query->msg_count, 2025185a700Sflorian query->byte_count); 2035185a700Sflorian } else { 2045185a700Sflorian printf(";; MSG SIZE rcvd: %u\n", bytes); 2055185a700Sflorian } 2065185a700Sflorian if (tsigkey != NULL) { 2075185a700Sflorian if (!validated) 2085185a700Sflorian puts(";; WARNING -- Some TSIG could not " 2095185a700Sflorian "be validated"); 2105185a700Sflorian } 2115185a700Sflorian if ((tsigkey == NULL) && (keysecret[0] != 0)) { 2125185a700Sflorian puts(";; WARNING -- TSIG key was not used."); 2135185a700Sflorian } 2145185a700Sflorian puts(""); 2155185a700Sflorian } else if (query->lookup->identify && !short_form) { 2165185a700Sflorian if (use_usec) 2175185a700Sflorian printf(";; Received %llu bytes " 218427f8978Sflorian "from %s(%s) in %lld us\n\n", 2195185a700Sflorian query->lookup->doing_xfr 2205185a700Sflorian ? query->byte_count 2215185a700Sflorian : (uint64_t)bytes, 222427f8978Sflorian fromtext, query->userarg, 223427f8978Sflorian uelapsed(&query->time_recv, &query->time_sent)); 2245185a700Sflorian else 2255185a700Sflorian printf(";; Received %llu bytes " 226427f8978Sflorian "from %s(%s) in %lld ms\n\n", 2275185a700Sflorian query->lookup->doing_xfr 2285185a700Sflorian ? query->byte_count 2295185a700Sflorian : (uint64_t)bytes, 230427f8978Sflorian fromtext, query->userarg, 231427f8978Sflorian uelapsed(&query->time_recv, &query->time_sent) / 232427f8978Sflorian 1000); 2335185a700Sflorian } 2345185a700Sflorian } 2355185a700Sflorian 2365185a700Sflorian /* 2375185a700Sflorian * Callback from dighost.c to print that it is trying a server. 2385185a700Sflorian * Not used in dig. 2395185a700Sflorian * XXX print_trying 2405185a700Sflorian */ 2415185a700Sflorian static void 2425185a700Sflorian trying(char *frm, dig_lookup_t *lookup) { 2435185a700Sflorian UNUSED(frm); 2445185a700Sflorian UNUSED(lookup); 2455185a700Sflorian } 2465185a700Sflorian 2475185a700Sflorian /*% 2485185a700Sflorian * Internal print routine used to print short form replies. 2495185a700Sflorian */ 2505185a700Sflorian static isc_result_t 2515185a700Sflorian say_message(dns_rdata_t *rdata, dig_query_t *query, isc_buffer_t *buf) { 2525185a700Sflorian isc_result_t result; 2535185a700Sflorian char store[sizeof(" in 18446744073709551616 us.")]; 2545185a700Sflorian unsigned int styleflags = 0; 2555185a700Sflorian 2565185a700Sflorian if (query->lookup->trace || query->lookup->ns_search_only) { 2575185a700Sflorian result = dns_rdatatype_totext(rdata->type, buf); 2585185a700Sflorian if (result != ISC_R_SUCCESS) 2595185a700Sflorian return (result); 2605185a700Sflorian ADD_STRING(buf, " "); 2615185a700Sflorian } 2625185a700Sflorian 2635185a700Sflorian /* Turn on rrcomments if explicitly enabled */ 2645185a700Sflorian if (rrcomments > 0) 2655185a700Sflorian styleflags |= DNS_STYLEFLAG_RRCOMMENT; 2665185a700Sflorian if (nocrypto) 2675185a700Sflorian styleflags |= DNS_STYLEFLAG_NOCRYPTO; 2685185a700Sflorian result = dns_rdata_tofmttext(rdata, NULL, styleflags, 0, 2695185a700Sflorian splitwidth, " ", buf); 2705185a700Sflorian if (result == ISC_R_NOSPACE) 2715185a700Sflorian return (result); 2725185a700Sflorian check_result(result, "dns_rdata_totext"); 2735185a700Sflorian if (query->lookup->identify) { 2745185a700Sflorian ADD_STRING(buf, " from server "); 2755185a700Sflorian ADD_STRING(buf, query->servname); 2765185a700Sflorian if (use_usec) 277427f8978Sflorian snprintf(store, sizeof(store), " in %lld us.", 278427f8978Sflorian uelapsed(&query->time_recv, &query->time_sent)); 2795185a700Sflorian else 280427f8978Sflorian snprintf(store, sizeof(store), " in %lld ms.", 281427f8978Sflorian uelapsed(&query->time_recv, &query->time_sent) / 282427f8978Sflorian 1000); 2835185a700Sflorian ADD_STRING(buf, store); 2845185a700Sflorian } 2855185a700Sflorian ADD_STRING(buf, "\n"); 2865185a700Sflorian return (ISC_R_SUCCESS); 2875185a700Sflorian } 2885185a700Sflorian 2895185a700Sflorian /*% 2905185a700Sflorian * short_form message print handler. Calls above say_message() 2915185a700Sflorian */ 2925185a700Sflorian static isc_result_t 2935185a700Sflorian short_answer(dns_message_t *msg, dns_messagetextflag_t flags, 2945185a700Sflorian isc_buffer_t *buf, dig_query_t *query) 2955185a700Sflorian { 2965185a700Sflorian dns_name_t *name; 2975185a700Sflorian dns_rdataset_t *rdataset; 2985185a700Sflorian isc_result_t result, loopresult; 2995185a700Sflorian dns_name_t empty_name; 3005185a700Sflorian dns_rdata_t rdata = DNS_RDATA_INIT; 3015185a700Sflorian 3025185a700Sflorian UNUSED(flags); 3035185a700Sflorian 3045185a700Sflorian dns_name_init(&empty_name, NULL); 3055185a700Sflorian result = dns_message_firstname(msg, DNS_SECTION_ANSWER); 3065185a700Sflorian if (result == ISC_R_NOMORE) 3075185a700Sflorian return (ISC_R_SUCCESS); 3085185a700Sflorian else if (result != ISC_R_SUCCESS) 3095185a700Sflorian return (result); 3105185a700Sflorian 3115185a700Sflorian for (;;) { 3125185a700Sflorian name = NULL; 3135185a700Sflorian dns_message_currentname(msg, DNS_SECTION_ANSWER, &name); 3145185a700Sflorian 3155185a700Sflorian for (rdataset = ISC_LIST_HEAD(name->list); 3165185a700Sflorian rdataset != NULL; 3175185a700Sflorian rdataset = ISC_LIST_NEXT(rdataset, link)) { 3185185a700Sflorian loopresult = dns_rdataset_first(rdataset); 3195185a700Sflorian while (loopresult == ISC_R_SUCCESS) { 3205185a700Sflorian dns_rdataset_current(rdataset, &rdata); 3215185a700Sflorian result = say_message(&rdata, query, 3225185a700Sflorian buf); 3235185a700Sflorian if (result == ISC_R_NOSPACE) 3245185a700Sflorian return (result); 3255185a700Sflorian check_result(result, "say_message"); 3265185a700Sflorian loopresult = dns_rdataset_next(rdataset); 3275185a700Sflorian dns_rdata_reset(&rdata); 3285185a700Sflorian } 3295185a700Sflorian } 3305185a700Sflorian result = dns_message_nextname(msg, DNS_SECTION_ANSWER); 3315185a700Sflorian if (result == ISC_R_NOMORE) 3325185a700Sflorian break; 3335185a700Sflorian else if (result != ISC_R_SUCCESS) 3345185a700Sflorian return (result); 3355185a700Sflorian } 3365185a700Sflorian 3375185a700Sflorian return (ISC_R_SUCCESS); 3385185a700Sflorian } 3395185a700Sflorian 3401fb015a8Sflorian static int 3415185a700Sflorian isdotlocal(dns_message_t *msg) { 3425185a700Sflorian isc_result_t result; 3435185a700Sflorian static unsigned char local_ndata[] = { "\005local\0" }; 3445185a700Sflorian static unsigned char local_offsets[] = { 0, 6 }; 3455185a700Sflorian static dns_name_t local = 3465185a700Sflorian DNS_NAME_INITABSOLUTE(local_ndata, local_offsets); 3475185a700Sflorian 3485185a700Sflorian for (result = dns_message_firstname(msg, DNS_SECTION_QUESTION); 3495185a700Sflorian result == ISC_R_SUCCESS; 3505185a700Sflorian result = dns_message_nextname(msg, DNS_SECTION_QUESTION)) 3515185a700Sflorian { 3525185a700Sflorian dns_name_t *name = NULL; 3535185a700Sflorian dns_message_currentname(msg, DNS_SECTION_QUESTION, &name); 3545185a700Sflorian if (dns_name_issubdomain(name, &local)) 3551fb015a8Sflorian return (1); 3565185a700Sflorian } 3571fb015a8Sflorian return (0); 3585185a700Sflorian } 3595185a700Sflorian 3605185a700Sflorian /* 3615185a700Sflorian * Callback from dighost.c to print the reply from a server 3625185a700Sflorian */ 3635185a700Sflorian static isc_result_t 3641fb015a8Sflorian printmessage(dig_query_t *query, dns_message_t *msg, int headers) { 3655185a700Sflorian isc_result_t result; 3665185a700Sflorian dns_messagetextflag_t flags; 3675185a700Sflorian isc_buffer_t *buf = NULL; 3685185a700Sflorian unsigned int len = OUTPUTBUF; 3695185a700Sflorian dns_master_style_t *style = NULL; 3705185a700Sflorian unsigned int styleflags = 0; 3715185a700Sflorian 3725185a700Sflorian styleflags |= DNS_STYLEFLAG_REL_OWNER; 3735185a700Sflorian if (query->lookup->comments) 3745185a700Sflorian styleflags |= DNS_STYLEFLAG_COMMENT; 3755185a700Sflorian /* Turn on rrcomments if explicitly enabled */ 3765185a700Sflorian if (rrcomments > 0) 3775185a700Sflorian styleflags |= DNS_STYLEFLAG_RRCOMMENT; 3785185a700Sflorian if (nottl) 3795185a700Sflorian styleflags |= DNS_STYLEFLAG_NO_TTL; 3805185a700Sflorian if (noclass) 3815185a700Sflorian styleflags |= DNS_STYLEFLAG_NO_CLASS; 3825185a700Sflorian if (nocrypto) 3835185a700Sflorian styleflags |= DNS_STYLEFLAG_NOCRYPTO; 3845185a700Sflorian if (multiline) { 3855185a700Sflorian styleflags |= DNS_STYLEFLAG_OMIT_OWNER; 3865185a700Sflorian styleflags |= DNS_STYLEFLAG_OMIT_CLASS; 3875185a700Sflorian styleflags |= DNS_STYLEFLAG_REL_DATA; 3885185a700Sflorian styleflags |= DNS_STYLEFLAG_OMIT_TTL; 3895185a700Sflorian styleflags |= DNS_STYLEFLAG_TTL; 3905185a700Sflorian styleflags |= DNS_STYLEFLAG_MULTILINE; 3915185a700Sflorian /* Turn on rrcomments unless explicitly disabled */ 3925185a700Sflorian if (rrcomments >= 0) 3935185a700Sflorian styleflags |= DNS_STYLEFLAG_RRCOMMENT; 3945185a700Sflorian } 3955185a700Sflorian if (multiline || (nottl && noclass)) 3965185a700Sflorian result = dns_master_stylecreate2(&style, styleflags, 3975185a700Sflorian 24, 24, 24, 32, 80, 8, 3985185a700Sflorian splitwidth); 3995185a700Sflorian else if (nottl || noclass) 4005185a700Sflorian result = dns_master_stylecreate2(&style, styleflags, 4015185a700Sflorian 24, 24, 32, 40, 80, 8, 4025185a700Sflorian splitwidth); 4035185a700Sflorian else 4045185a700Sflorian result = dns_master_stylecreate2(&style, styleflags, 4055185a700Sflorian 24, 32, 40, 48, 80, 8, 4065185a700Sflorian splitwidth); 4075185a700Sflorian check_result(result, "dns_master_stylecreate"); 4085185a700Sflorian 4095185a700Sflorian if (query->lookup->cmdline[0] != 0) { 4105185a700Sflorian if (!short_form) 4115185a700Sflorian fputs(query->lookup->cmdline, stdout); 4125185a700Sflorian query->lookup->cmdline[0]=0; 4135185a700Sflorian } 4145185a700Sflorian debug("printmessage(%s %s %s)", headers ? "headers" : "noheaders", 4155185a700Sflorian query->lookup->comments ? "comments" : "nocomments", 4165185a700Sflorian short_form ? "short_form" : "long_form"); 4175185a700Sflorian 4185185a700Sflorian flags = 0; 4195185a700Sflorian if (!headers) { 4205185a700Sflorian flags |= DNS_MESSAGETEXTFLAG_NOHEADERS; 4215185a700Sflorian flags |= DNS_MESSAGETEXTFLAG_NOCOMMENTS; 4225185a700Sflorian } 4235185a700Sflorian if (onesoa && query->lookup->rdtype == dns_rdatatype_axfr) 4245185a700Sflorian flags |= (query->msg_count == 0) ? DNS_MESSAGETEXTFLAG_ONESOA : 4255185a700Sflorian DNS_MESSAGETEXTFLAG_OMITSOA; 4265185a700Sflorian if (!query->lookup->comments) 4275185a700Sflorian flags |= DNS_MESSAGETEXTFLAG_NOCOMMENTS; 4285185a700Sflorian 4295185a700Sflorian result = isc_buffer_allocate(&buf, len); 4305185a700Sflorian check_result(result, "isc_buffer_allocate"); 4315185a700Sflorian 4325185a700Sflorian if (query->lookup->comments && !short_form) { 4335185a700Sflorian if (query->lookup->cmdline[0] != 0) 4345185a700Sflorian printf("; %s\n", query->lookup->cmdline); 4355185a700Sflorian if (msg == query->lookup->sendmsg) 4365185a700Sflorian printf(";; Sending:\n"); 4375185a700Sflorian else 4385185a700Sflorian printf(";; Got answer:\n"); 4395185a700Sflorian 4405185a700Sflorian if (headers) { 4415185a700Sflorian if (isdotlocal(msg)) { 4425185a700Sflorian printf(";; WARNING: .local is reserved for " 4435185a700Sflorian "Multicast DNS\n;; You are currently " 4445185a700Sflorian "testing what happens when an mDNS " 4455185a700Sflorian "query is leaked to DNS\n"); 4465185a700Sflorian } 4475185a700Sflorian printf(";; ->>HEADER<<- opcode: %s, status: %s, " 4485185a700Sflorian "id: %u\n", 4495185a700Sflorian opcodetext[msg->opcode], 4505185a700Sflorian rcode_totext(msg->rcode), 4515185a700Sflorian msg->id); 4525185a700Sflorian printf(";; flags:"); 4535185a700Sflorian if ((msg->flags & DNS_MESSAGEFLAG_QR) != 0) 4545185a700Sflorian printf(" qr"); 4555185a700Sflorian if ((msg->flags & DNS_MESSAGEFLAG_AA) != 0) 4565185a700Sflorian printf(" aa"); 4575185a700Sflorian if ((msg->flags & DNS_MESSAGEFLAG_TC) != 0) 4585185a700Sflorian printf(" tc"); 4595185a700Sflorian if ((msg->flags & DNS_MESSAGEFLAG_RD) != 0) 4605185a700Sflorian printf(" rd"); 4615185a700Sflorian if ((msg->flags & DNS_MESSAGEFLAG_RA) != 0) 4625185a700Sflorian printf(" ra"); 4635185a700Sflorian if ((msg->flags & DNS_MESSAGEFLAG_AD) != 0) 4645185a700Sflorian printf(" ad"); 4655185a700Sflorian if ((msg->flags & DNS_MESSAGEFLAG_CD) != 0) 4665185a700Sflorian printf(" cd"); 4675185a700Sflorian if ((msg->flags & 0x0040U) != 0) 4685185a700Sflorian printf("; MBZ: 0x4"); 4695185a700Sflorian 4705185a700Sflorian printf("; QUERY: %u, ANSWER: %u, " 4715185a700Sflorian "AUTHORITY: %u, ADDITIONAL: %u\n", 4725185a700Sflorian msg->counts[DNS_SECTION_QUESTION], 4735185a700Sflorian msg->counts[DNS_SECTION_ANSWER], 4745185a700Sflorian msg->counts[DNS_SECTION_AUTHORITY], 4755185a700Sflorian msg->counts[DNS_SECTION_ADDITIONAL]); 4765185a700Sflorian 4775185a700Sflorian if (msg != query->lookup->sendmsg && 4785185a700Sflorian (msg->flags & DNS_MESSAGEFLAG_RD) != 0 && 4795185a700Sflorian (msg->flags & DNS_MESSAGEFLAG_RA) == 0) 4805185a700Sflorian printf(";; WARNING: recursion requested " 4815185a700Sflorian "but not available\n"); 4825185a700Sflorian } 4835185a700Sflorian if (msg != query->lookup->sendmsg && 4845185a700Sflorian query->lookup->edns != -1 && msg->opt == NULL && 4855185a700Sflorian (msg->rcode == dns_rcode_formerr || 4865185a700Sflorian msg->rcode == dns_rcode_notimp)) 4875185a700Sflorian printf("\n;; WARNING: EDNS query returned status " 4885185a700Sflorian "%s - retry with '%s+noedns'\n", 4895185a700Sflorian rcode_totext(msg->rcode), 4905185a700Sflorian query->lookup->dnssec ? "+nodnssec ": ""); 4915185a700Sflorian if (msg != query->lookup->sendmsg && extrabytes != 0U) 4925185a700Sflorian printf(";; WARNING: Message has %u extra byte%s at " 4935185a700Sflorian "end\n", extrabytes, extrabytes != 0 ? "s" : ""); 4945185a700Sflorian } 4955185a700Sflorian 4965185a700Sflorian repopulate_buffer: 4975185a700Sflorian 4985185a700Sflorian if (query->lookup->comments && headers && !short_form) { 4995185a700Sflorian result = dns_message_pseudosectiontotext(msg, 5005185a700Sflorian DNS_PSEUDOSECTION_OPT, 501*9835a5e1Sflorian style, flags, query->lookup->textname, buf); 5025185a700Sflorian if (result == ISC_R_NOSPACE) { 5035185a700Sflorian buftoosmall: 5045185a700Sflorian len += OUTPUTBUF; 5055185a700Sflorian isc_buffer_free(&buf); 5065185a700Sflorian result = isc_buffer_allocate(&buf, len); 5075185a700Sflorian if (result == ISC_R_SUCCESS) 5085185a700Sflorian goto repopulate_buffer; 5095185a700Sflorian else 5105185a700Sflorian goto cleanup; 5115185a700Sflorian } 5125185a700Sflorian check_result(result, 5135185a700Sflorian "dns_message_pseudosectiontotext"); 5145185a700Sflorian } 5155185a700Sflorian 5165185a700Sflorian if (query->lookup->section_question && headers) { 5175185a700Sflorian if (!short_form) { 5185185a700Sflorian result = dns_message_sectiontotext(msg, 5195185a700Sflorian DNS_SECTION_QUESTION, 5205185a700Sflorian style, flags, buf); 5215185a700Sflorian if (result == ISC_R_NOSPACE) 5225185a700Sflorian goto buftoosmall; 5235185a700Sflorian check_result(result, "dns_message_sectiontotext"); 5245185a700Sflorian } 5255185a700Sflorian } 5265185a700Sflorian if (query->lookup->section_answer) { 5275185a700Sflorian if (!short_form) { 5285185a700Sflorian result = dns_message_sectiontotext(msg, 5295185a700Sflorian DNS_SECTION_ANSWER, 5305185a700Sflorian style, flags, buf); 5315185a700Sflorian if (result == ISC_R_NOSPACE) 5325185a700Sflorian goto buftoosmall; 5335185a700Sflorian check_result(result, "dns_message_sectiontotext"); 5345185a700Sflorian } else { 5355185a700Sflorian result = short_answer(msg, flags, buf, query); 5365185a700Sflorian if (result == ISC_R_NOSPACE) 5375185a700Sflorian goto buftoosmall; 5385185a700Sflorian check_result(result, "short_answer"); 5395185a700Sflorian } 5405185a700Sflorian } 5415185a700Sflorian if (query->lookup->section_authority) { 5425185a700Sflorian if (!short_form) { 5435185a700Sflorian result = dns_message_sectiontotext(msg, 5445185a700Sflorian DNS_SECTION_AUTHORITY, 5455185a700Sflorian style, flags, buf); 5465185a700Sflorian if (result == ISC_R_NOSPACE) 5475185a700Sflorian goto buftoosmall; 5485185a700Sflorian check_result(result, "dns_message_sectiontotext"); 5495185a700Sflorian } 5505185a700Sflorian } 5515185a700Sflorian if (query->lookup->section_additional) { 5525185a700Sflorian if (!short_form) { 5535185a700Sflorian result = dns_message_sectiontotext(msg, 5545185a700Sflorian DNS_SECTION_ADDITIONAL, 5555185a700Sflorian style, flags, buf); 5565185a700Sflorian if (result == ISC_R_NOSPACE) 5575185a700Sflorian goto buftoosmall; 5585185a700Sflorian check_result(result, "dns_message_sectiontotext"); 5595185a700Sflorian /* 5605185a700Sflorian * Only print the signature on the first record. 5615185a700Sflorian */ 5625185a700Sflorian if (headers) { 5635185a700Sflorian result = dns_message_pseudosectiontotext( 5645185a700Sflorian msg, 5655185a700Sflorian DNS_PSEUDOSECTION_TSIG, 566*9835a5e1Sflorian style, flags, 567*9835a5e1Sflorian query->lookup->textname, 568*9835a5e1Sflorian buf); 5695185a700Sflorian if (result == ISC_R_NOSPACE) 5705185a700Sflorian goto buftoosmall; 5715185a700Sflorian check_result(result, 5725185a700Sflorian "dns_message_pseudosectiontotext"); 5735185a700Sflorian result = dns_message_pseudosectiontotext( 5745185a700Sflorian msg, 5755185a700Sflorian DNS_PSEUDOSECTION_SIG0, 576*9835a5e1Sflorian style, flags, 577*9835a5e1Sflorian query->lookup->textname, 578*9835a5e1Sflorian buf); 5795185a700Sflorian if (result == ISC_R_NOSPACE) 5805185a700Sflorian goto buftoosmall; 5815185a700Sflorian check_result(result, 5825185a700Sflorian "dns_message_pseudosectiontotext"); 5835185a700Sflorian } 5845185a700Sflorian } 5855185a700Sflorian } 5865185a700Sflorian 5875185a700Sflorian if (headers && query->lookup->comments && !short_form) 5885185a700Sflorian printf("\n"); 5895185a700Sflorian 5905185a700Sflorian printf("%.*s", (int)isc_buffer_usedlength(buf), 5915185a700Sflorian (char *)isc_buffer_base(buf)); 5925185a700Sflorian isc_buffer_free(&buf); 5935185a700Sflorian 5945185a700Sflorian cleanup: 5955185a700Sflorian if (style != NULL) 5965185a700Sflorian dns_master_styledestroy(&style); 5975185a700Sflorian return (result); 5985185a700Sflorian } 5995185a700Sflorian 6005185a700Sflorian /*% 6015185a700Sflorian * print the greeting message when the program first starts up. 6025185a700Sflorian */ 6035185a700Sflorian static void 6045185a700Sflorian printgreeting(int argc, char **argv, dig_lookup_t *lookup) { 6055185a700Sflorian int i; 6061fb015a8Sflorian static int first = 1; 6075185a700Sflorian char append[MXNAME]; 6085185a700Sflorian 6095185a700Sflorian if (printcmd) { 6105185a700Sflorian snprintf(lookup->cmdline, sizeof(lookup->cmdline), 6115185a700Sflorian "%s; <<>> dig " VERSION " <<>>", 6125185a700Sflorian first?"\n":""); 6135185a700Sflorian i = 1; 6145185a700Sflorian while (i < argc) { 6155185a700Sflorian snprintf(append, sizeof(append), " %s", argv[i++]); 6165185a700Sflorian strlcat(lookup->cmdline, append, 6175185a700Sflorian sizeof(lookup->cmdline)); 6185185a700Sflorian } 6195185a700Sflorian strlcat(lookup->cmdline, "\n", sizeof(lookup->cmdline)); 6205185a700Sflorian if (first && addresscount != 0) { 6215185a700Sflorian snprintf(append, sizeof(append), 6225185a700Sflorian "; (%d server%s found)\n", 6235185a700Sflorian addresscount, 6245185a700Sflorian addresscount > 1 ? "s" : ""); 6255185a700Sflorian strlcat(lookup->cmdline, append, 6265185a700Sflorian sizeof(lookup->cmdline)); 6275185a700Sflorian } 6285185a700Sflorian if (first) { 6295185a700Sflorian snprintf(append, sizeof(append), 6305185a700Sflorian ";; global options:%s%s\n", 6315185a700Sflorian short_form ? " +short" : "", 6325185a700Sflorian printcmd ? " +cmd" : ""); 6331fb015a8Sflorian first = 0; 6345185a700Sflorian strlcat(lookup->cmdline, append, 6355185a700Sflorian sizeof(lookup->cmdline)); 6365185a700Sflorian } 6375185a700Sflorian } 6385185a700Sflorian } 6395185a700Sflorian 6405185a700Sflorian static void 6411fb015a8Sflorian plus_option(const char *option, int is_batchfile, 6425185a700Sflorian dig_lookup_t *lookup) 6435185a700Sflorian { 6445185a700Sflorian isc_result_t result; 6455185a700Sflorian char option_store[256]; 646c49c5f05Sflorian char *cmd, *value, *ptr, *code, *ep; 647c49c5f05Sflorian const char *errstr; 648c49c5f05Sflorian long lval; 6495185a700Sflorian uint32_t num; 6501fb015a8Sflorian int state = 1; 6515185a700Sflorian size_t n; 6525185a700Sflorian 6535185a700Sflorian strlcpy(option_store, option, sizeof(option_store)); 6545185a700Sflorian ptr = option_store; 6555185a700Sflorian cmd = next_token(&ptr, "="); 6565185a700Sflorian if (cmd == NULL) { 6575185a700Sflorian printf(";; Invalid option %s\n", option_store); 6585185a700Sflorian return; 6595185a700Sflorian } 6605185a700Sflorian value = ptr; 6615185a700Sflorian if (strncasecmp(cmd, "no", 2)==0) { 6625185a700Sflorian cmd += 2; 6631fb015a8Sflorian state = 0; 6645185a700Sflorian } 6655185a700Sflorian 6665185a700Sflorian #define FULLCHECK(A) \ 6675185a700Sflorian do { \ 6685185a700Sflorian size_t _l = strlen(cmd); \ 6695185a700Sflorian if (_l >= sizeof(A) || strncasecmp(cmd, A, _l) != 0) \ 6705185a700Sflorian goto invalid_option; \ 6715185a700Sflorian } while (0) 6725185a700Sflorian #define FULLCHECK2(A, B) \ 6735185a700Sflorian do { \ 6745185a700Sflorian size_t _l = strlen(cmd); \ 6755185a700Sflorian if ((_l >= sizeof(A) || strncasecmp(cmd, A, _l) != 0) && \ 6765185a700Sflorian (_l >= sizeof(B) || strncasecmp(cmd, B, _l) != 0)) \ 6775185a700Sflorian goto invalid_option; \ 6785185a700Sflorian } while (0) 6795185a700Sflorian 6805185a700Sflorian switch (cmd[0]) { 6815185a700Sflorian case 'a': 6825185a700Sflorian switch (cmd[1]) { 6835185a700Sflorian case 'a': /* aaonly / aaflag */ 6845185a700Sflorian FULLCHECK2("aaonly", "aaflag"); 6855185a700Sflorian lookup->aaonly = state; 6865185a700Sflorian break; 6875185a700Sflorian case 'd': 6885185a700Sflorian switch (cmd[2]) { 6895185a700Sflorian case 'd': /* additional */ 6905185a700Sflorian FULLCHECK("additional"); 6915185a700Sflorian lookup->section_additional = state; 6925185a700Sflorian break; 6935185a700Sflorian case 'f': /* adflag */ 6945185a700Sflorian case '\0': /* +ad is a synonym for +adflag */ 6955185a700Sflorian FULLCHECK("adflag"); 6965185a700Sflorian lookup->adflag = state; 6975185a700Sflorian break; 6985185a700Sflorian default: 6995185a700Sflorian goto invalid_option; 7005185a700Sflorian } 7015185a700Sflorian break; 7025185a700Sflorian case 'l': /* all */ 7035185a700Sflorian FULLCHECK("all"); 7045185a700Sflorian lookup->section_question = state; 7055185a700Sflorian lookup->section_authority = state; 7065185a700Sflorian lookup->section_answer = state; 7075185a700Sflorian lookup->section_additional = state; 7085185a700Sflorian lookup->comments = state; 7095185a700Sflorian lookup->stats = state; 7105185a700Sflorian printcmd = state; 7115185a700Sflorian break; 7125185a700Sflorian case 'n': /* answer */ 7135185a700Sflorian FULLCHECK("answer"); 7145185a700Sflorian lookup->section_answer = state; 7155185a700Sflorian break; 7165185a700Sflorian case 'u': /* authority */ 7175185a700Sflorian FULLCHECK("authority"); 7185185a700Sflorian lookup->section_authority = state; 7195185a700Sflorian break; 7205185a700Sflorian default: 7215185a700Sflorian goto invalid_option; 7225185a700Sflorian } 7235185a700Sflorian break; 7245185a700Sflorian case 'b': 7255185a700Sflorian switch (cmd[1]) { 7265185a700Sflorian case 'e':/* besteffort */ 7275185a700Sflorian FULLCHECK("besteffort"); 7285185a700Sflorian lookup->besteffort = state; 7295185a700Sflorian break; 7305185a700Sflorian case 'u':/* bufsize */ 7315185a700Sflorian FULLCHECK("bufsize"); 7325185a700Sflorian if (value == NULL) 7335185a700Sflorian goto need_value; 7345185a700Sflorian if (!state) 7355185a700Sflorian goto invalid_option; 736c49c5f05Sflorian num = strtonum(value, 0, COMMSIZE, &errstr); 737c49c5f05Sflorian if (errstr != NULL) 738c49c5f05Sflorian fatal("buffer size is %s: '%s'", errstr, value); 7395185a700Sflorian lookup->udpsize = num; 7405185a700Sflorian break; 7415185a700Sflorian default: 7425185a700Sflorian goto invalid_option; 7435185a700Sflorian } 7445185a700Sflorian break; 7455185a700Sflorian case 'c': 7465185a700Sflorian switch (cmd[1]) { 7475185a700Sflorian case 'd':/* cdflag */ 7485185a700Sflorian switch (cmd[2]) { 7495185a700Sflorian case 'f': /* cdflag */ 7505185a700Sflorian case '\0': /* +cd is a synonym for +cdflag */ 7515185a700Sflorian FULLCHECK("cdflag"); 7525185a700Sflorian lookup->cdflag = state; 7535185a700Sflorian break; 7545185a700Sflorian default: 7555185a700Sflorian goto invalid_option; 7565185a700Sflorian } 7575185a700Sflorian break; 7585185a700Sflorian case 'l': /* class */ 7595185a700Sflorian /* keep +cl for backwards compatibility */ 7605185a700Sflorian FULLCHECK2("cl", "class"); 7611fb015a8Sflorian noclass = !state; 7625185a700Sflorian break; 7635185a700Sflorian case 'm': /* cmd */ 7645185a700Sflorian FULLCHECK("cmd"); 7655185a700Sflorian printcmd = state; 7665185a700Sflorian break; 7675185a700Sflorian case 'o': /* comments */ 7685185a700Sflorian switch (cmd[2]) { 7695185a700Sflorian case 'o': 7705185a700Sflorian FULLCHECK("cookie"); 7715185a700Sflorian goto sit; 7725185a700Sflorian case 'm': 7735185a700Sflorian FULLCHECK("comments"); 7745185a700Sflorian lookup->comments = state; 7755185a700Sflorian if (lookup == default_lookup) 7765185a700Sflorian pluscomm = state; 7775185a700Sflorian break; 7785185a700Sflorian default: 7795185a700Sflorian goto invalid_option; 7805185a700Sflorian } 7815185a700Sflorian break; 7825185a700Sflorian case 'r': 7835185a700Sflorian FULLCHECK("crypto"); 7841fb015a8Sflorian nocrypto = !state; 7855185a700Sflorian break; 7865185a700Sflorian default: 7875185a700Sflorian goto invalid_option; 7885185a700Sflorian } 7895185a700Sflorian break; 7905185a700Sflorian case 'd': 7915185a700Sflorian switch (cmd[1]) { 7925185a700Sflorian case 'e': /* defname */ 7935185a700Sflorian FULLCHECK("defname"); 7945185a700Sflorian if (!lookup->trace) { 7955185a700Sflorian usesearch = state; 7965185a700Sflorian } 7975185a700Sflorian break; 7985185a700Sflorian case 'n': /* dnssec */ 7995185a700Sflorian FULLCHECK("dnssec"); 8005185a700Sflorian if (state && lookup->edns == -1) 8015185a700Sflorian lookup->edns = 0; 8025185a700Sflorian lookup->dnssec = state; 8035185a700Sflorian break; 8045185a700Sflorian case 'o': /* domain */ 8055185a700Sflorian FULLCHECK("domain"); 8065185a700Sflorian if (value == NULL) 8075185a700Sflorian goto need_value; 8085185a700Sflorian if (!state) 8095185a700Sflorian goto invalid_option; 8105185a700Sflorian strlcpy(domainopt, value, sizeof(domainopt)); 8115185a700Sflorian break; 8125185a700Sflorian default: 8135185a700Sflorian goto invalid_option; 8145185a700Sflorian } 8155185a700Sflorian break; 8165185a700Sflorian case 'e': 8175185a700Sflorian switch (cmd[1]) { 8185185a700Sflorian case 'd': 8195185a700Sflorian switch(cmd[2]) { 8205185a700Sflorian case 'n': 8215185a700Sflorian switch (cmd[3]) { 8225185a700Sflorian case 's': 8235185a700Sflorian switch (cmd[4]) { 8245185a700Sflorian case 0: 8255185a700Sflorian FULLCHECK("edns"); 8265185a700Sflorian if (!state) { 8275185a700Sflorian lookup->edns = -1; 8285185a700Sflorian break; 8295185a700Sflorian } 8305185a700Sflorian if (value == NULL) { 8315185a700Sflorian lookup->edns = 0; 8325185a700Sflorian break; 8335185a700Sflorian } 834c49c5f05Sflorian num = strtonum(value, 0, 255, 835c49c5f05Sflorian &errstr); 836c49c5f05Sflorian if (errstr != NULL) 837c49c5f05Sflorian fatal("edns is %s: " 838c49c5f05Sflorian "'%s'", errstr, 839c49c5f05Sflorian value); 8405185a700Sflorian lookup->edns = num; 8415185a700Sflorian break; 8425185a700Sflorian case 'f': 8435185a700Sflorian FULLCHECK("ednsflags"); 8445185a700Sflorian if (!state) { 8455185a700Sflorian lookup->ednsflags = 0; 8465185a700Sflorian break; 8475185a700Sflorian } 8485185a700Sflorian if (value == NULL) { 8495185a700Sflorian lookup->ednsflags = 0; 8505185a700Sflorian break; 8515185a700Sflorian } 852c49c5f05Sflorian errno = 0; 853c49c5f05Sflorian lval = strtol(value, &ep, 0); 854c49c5f05Sflorian if (value[0] == '\0' || *ep != 855c49c5f05Sflorian '\0' || lval < 0 || lval > 856c49c5f05Sflorian 0xffff || errno != 0) 8575185a700Sflorian fatal("Couldn't parse " 8585185a700Sflorian "ednsflags"); 859c49c5f05Sflorian lookup->ednsflags = lval; 8605185a700Sflorian break; 8615185a700Sflorian case 'n': 8625185a700Sflorian FULLCHECK("ednsnegotiation"); 8635185a700Sflorian lookup->ednsneg = state; 8645185a700Sflorian break; 8655185a700Sflorian case 'o': 8665185a700Sflorian FULLCHECK("ednsopt"); 8675185a700Sflorian if (!state) { 8685185a700Sflorian lookup->ednsoptscnt = 0; 8695185a700Sflorian break; 8705185a700Sflorian } 8715185a700Sflorian if (value == NULL) 8725185a700Sflorian fatal("ednsopt no " 8735185a700Sflorian "code point " 8745185a700Sflorian "specified"); 8755185a700Sflorian code = next_token(&value, ":"); 8765185a700Sflorian save_opt(lookup, code, value); 8775185a700Sflorian break; 8785185a700Sflorian default: 8795185a700Sflorian goto invalid_option; 8805185a700Sflorian } 8815185a700Sflorian break; 8825185a700Sflorian default: 8835185a700Sflorian goto invalid_option; 8845185a700Sflorian } 8855185a700Sflorian break; 8865185a700Sflorian default: 8875185a700Sflorian goto invalid_option; 8885185a700Sflorian } 8895185a700Sflorian break; 8905185a700Sflorian case 'x': 8915185a700Sflorian FULLCHECK("expire"); 8925185a700Sflorian lookup->expire = state; 8935185a700Sflorian break; 8945185a700Sflorian default: 8955185a700Sflorian goto invalid_option; 8965185a700Sflorian } 8975185a700Sflorian break; 8985185a700Sflorian case 'f': /* fail */ 8995185a700Sflorian FULLCHECK("fail"); 9005185a700Sflorian lookup->servfail_stops = state; 9015185a700Sflorian break; 9025185a700Sflorian case 'i': 9035185a700Sflorian switch (cmd[1]) { 9045185a700Sflorian case 'd': /* identify */ 9055185a700Sflorian switch (cmd[2]) { 9065185a700Sflorian case 'e': 9075185a700Sflorian FULLCHECK("identify"); 9085185a700Sflorian lookup->identify = state; 9095185a700Sflorian break; 9105185a700Sflorian case 'n': 9115185a700Sflorian FULLCHECK("idnout"); 9125185a700Sflorian fprintf(stderr, ";; IDN support not enabled\n"); 9135185a700Sflorian break; 9145185a700Sflorian default: 9155185a700Sflorian goto invalid_option; 9165185a700Sflorian } 9175185a700Sflorian break; 9185185a700Sflorian case 'g': /* ignore */ 9195185a700Sflorian default: /* 9205185a700Sflorian * Inherits default for compatibility (+[no]i*). 9215185a700Sflorian */ 9225185a700Sflorian FULLCHECK("ignore"); 9235185a700Sflorian lookup->ignore = state; 9245185a700Sflorian } 9255185a700Sflorian break; 9265185a700Sflorian case 'k': 9275185a700Sflorian FULLCHECK("keepopen"); 9285185a700Sflorian keep_open = state; 9295185a700Sflorian break; 9305185a700Sflorian case 'm': /* multiline */ 9315185a700Sflorian FULLCHECK("multiline"); 9325185a700Sflorian multiline = state; 9335185a700Sflorian break; 9345185a700Sflorian case 'n': 9355185a700Sflorian switch (cmd[1]) { 9365185a700Sflorian case 'd': /* ndots */ 9375185a700Sflorian FULLCHECK("ndots"); 9385185a700Sflorian if (value == NULL) 9395185a700Sflorian goto need_value; 9405185a700Sflorian if (!state) 9415185a700Sflorian goto invalid_option; 942c49c5f05Sflorian num = strtonum(value, 0, MAXNDOTS, &errstr); 943c49c5f05Sflorian if (errstr != NULL) 944c49c5f05Sflorian fatal("ndots is %s: '%s'", errstr, value); 9455185a700Sflorian ndots = num; 9465185a700Sflorian break; 9475185a700Sflorian case 's': 9485185a700Sflorian switch (cmd[2]) { 9495185a700Sflorian case 'i': /* nsid */ 9505185a700Sflorian FULLCHECK("nsid"); 9515185a700Sflorian if (state && lookup->edns == -1) 9525185a700Sflorian lookup->edns = 0; 9535185a700Sflorian lookup->nsid = state; 9545185a700Sflorian break; 9555185a700Sflorian case 's': /* nssearch */ 9565185a700Sflorian FULLCHECK("nssearch"); 9575185a700Sflorian lookup->ns_search_only = state; 9585185a700Sflorian if (state) { 9591fb015a8Sflorian lookup->trace_root = 1; 9601fb015a8Sflorian lookup->recurse = 1; 9611fb015a8Sflorian lookup->identify = 1; 9621fb015a8Sflorian lookup->stats = 0; 9631fb015a8Sflorian lookup->comments = 0; 9641fb015a8Sflorian lookup->section_additional = 0; 9651fb015a8Sflorian lookup->section_authority = 0; 9661fb015a8Sflorian lookup->section_question = 0; 9675185a700Sflorian lookup->rdtype = dns_rdatatype_ns; 9681fb015a8Sflorian lookup->rdtypeset = 1; 9691fb015a8Sflorian short_form = 1; 9705185a700Sflorian rrcomments = 0; 9715185a700Sflorian } 9725185a700Sflorian break; 9735185a700Sflorian default: 9745185a700Sflorian goto invalid_option; 9755185a700Sflorian } 9765185a700Sflorian break; 9775185a700Sflorian default: 9785185a700Sflorian goto invalid_option; 9795185a700Sflorian } 9805185a700Sflorian break; 9815185a700Sflorian case 'o': 9825185a700Sflorian switch (cmd[1]) { 9835185a700Sflorian case 'n': 9845185a700Sflorian FULLCHECK("onesoa"); 9855185a700Sflorian onesoa = state; 9865185a700Sflorian break; 9875185a700Sflorian case 'p': 9885185a700Sflorian FULLCHECK("opcode"); 9895185a700Sflorian if (!state) { 9905185a700Sflorian lookup->opcode = 0; /* default - query */ 9915185a700Sflorian break; 9925185a700Sflorian } 9935185a700Sflorian if (value == NULL) 9945185a700Sflorian goto need_value; 9955185a700Sflorian for (num = 0; 9965185a700Sflorian num < sizeof(opcodetext)/sizeof(opcodetext[0]); 9975185a700Sflorian num++) { 9985185a700Sflorian if (strcasecmp(opcodetext[num], value) == 0) 9995185a700Sflorian break; 10005185a700Sflorian } 10015185a700Sflorian if (num < 16) { 10025185a700Sflorian lookup->opcode = (dns_opcode_t)num; 10035185a700Sflorian break; 10045185a700Sflorian } 1005c49c5f05Sflorian num = strtonum(value, 0, 15, &errstr); 1006c49c5f05Sflorian if (errstr != NULL) 1007c49c5f05Sflorian fatal("opcode is %s: '%s'", errstr, value); 10085185a700Sflorian lookup->opcode = (dns_opcode_t)num; 10095185a700Sflorian break; 10105185a700Sflorian default: 10115185a700Sflorian goto invalid_option; 10125185a700Sflorian } 10135185a700Sflorian break; 10145185a700Sflorian case 'q': 10155185a700Sflorian switch (cmd[1]) { 10165185a700Sflorian case 'r': /* qr */ 10175185a700Sflorian FULLCHECK("qr"); 10185185a700Sflorian qr = state; 10195185a700Sflorian break; 10205185a700Sflorian case 'u': /* question */ 10215185a700Sflorian FULLCHECK("question"); 10225185a700Sflorian lookup->section_question = state; 10235185a700Sflorian if (lookup == default_lookup) 10245185a700Sflorian plusquest = state; 10255185a700Sflorian break; 10265185a700Sflorian default: 10275185a700Sflorian goto invalid_option; 10285185a700Sflorian } 10295185a700Sflorian break; 10305185a700Sflorian case 'r': 10315185a700Sflorian switch (cmd[1]) { 10325185a700Sflorian case 'd': /* rdflag */ 10335185a700Sflorian FULLCHECK("rdflag"); 10345185a700Sflorian lookup->recurse = state; 10355185a700Sflorian break; 10365185a700Sflorian case 'e': 10375185a700Sflorian switch (cmd[2]) { 10385185a700Sflorian case 'c': /* recurse */ 10395185a700Sflorian FULLCHECK("recurse"); 10405185a700Sflorian lookup->recurse = state; 10415185a700Sflorian break; 10425185a700Sflorian case 't': /* retry / retries */ 10435185a700Sflorian FULLCHECK2("retry", "retries"); 10445185a700Sflorian if (value == NULL) 10455185a700Sflorian goto need_value; 10465185a700Sflorian if (!state) 10475185a700Sflorian goto invalid_option; 1048c49c5f05Sflorian lookup->retries = strtonum(value, 0, 1049c49c5f05Sflorian MAXTRIES - 1, &errstr); 1050c49c5f05Sflorian if (errstr != NULL) 1051c49c5f05Sflorian fatal("retries is %s: '%s'", errstr, 1052c49c5f05Sflorian value); 10535185a700Sflorian lookup->retries++; 10545185a700Sflorian break; 10555185a700Sflorian default: 10565185a700Sflorian goto invalid_option; 10575185a700Sflorian } 10585185a700Sflorian break; 10595185a700Sflorian case 'r': /* rrcomments */ 10605185a700Sflorian FULLCHECK("rrcomments"); 10615185a700Sflorian rrcomments = state ? 1 : -1; 10625185a700Sflorian break; 10635185a700Sflorian default: 10645185a700Sflorian goto invalid_option; 10655185a700Sflorian } 10665185a700Sflorian break; 10675185a700Sflorian case 's': 10685185a700Sflorian switch (cmd[1]) { 10695185a700Sflorian case 'e': /* search */ 10705185a700Sflorian FULLCHECK("search"); 10715185a700Sflorian if (!lookup->trace) { 10725185a700Sflorian usesearch = state; 10735185a700Sflorian } 10745185a700Sflorian break; 10755185a700Sflorian case 'h': 10765185a700Sflorian if (cmd[2] != 'o') 10775185a700Sflorian goto invalid_option; 10785185a700Sflorian switch (cmd[3]) { 10795185a700Sflorian case 'r': /* short */ 10805185a700Sflorian FULLCHECK("short"); 10815185a700Sflorian short_form = state; 10825185a700Sflorian if (state) { 10831fb015a8Sflorian printcmd = 0; 10841fb015a8Sflorian lookup->section_additional = 0; 10851fb015a8Sflorian lookup->section_answer = 1; 10861fb015a8Sflorian lookup->section_authority = 0; 10871fb015a8Sflorian lookup->section_question = 0; 10881fb015a8Sflorian lookup->comments = 0; 10891fb015a8Sflorian lookup->stats = 0; 10905185a700Sflorian rrcomments = -1; 10915185a700Sflorian } 10925185a700Sflorian break; 10935185a700Sflorian case 'w': /* showsearch */ 10945185a700Sflorian FULLCHECK("showsearch"); 10955185a700Sflorian if (!lookup->trace) { 10965185a700Sflorian showsearch = state; 10975185a700Sflorian usesearch = state; 10985185a700Sflorian } 10995185a700Sflorian break; 11005185a700Sflorian default: 11015185a700Sflorian goto invalid_option; 11025185a700Sflorian } 11035185a700Sflorian break; 11045185a700Sflorian case 'i': 11055185a700Sflorian switch (cmd[2]) { 11065185a700Sflorian case 't': /* sit */ 11075185a700Sflorian FULLCHECK("sit"); 11085185a700Sflorian sit: 11095185a700Sflorian if (state && lookup->edns == -1) 11105185a700Sflorian lookup->edns = 0; 11115185a700Sflorian lookup->sit = state; 11125185a700Sflorian if (value != NULL) { 11135185a700Sflorian n = strlcpy(sitvalue, value, 11145185a700Sflorian sizeof(sitvalue)); 11155185a700Sflorian if (n >= sizeof(sitvalue)) 11165185a700Sflorian fatal("SIT data too large"); 11175185a700Sflorian lookup->sitvalue = sitvalue; 11185185a700Sflorian } else 11195185a700Sflorian lookup->sitvalue = NULL; 11205185a700Sflorian break; 11215185a700Sflorian default: 11225185a700Sflorian goto invalid_option; 11235185a700Sflorian } 11245185a700Sflorian break; 11255185a700Sflorian case 'p': /* split */ 11265185a700Sflorian FULLCHECK("split"); 11275185a700Sflorian if (value != NULL && !state) 11285185a700Sflorian goto invalid_option; 11295185a700Sflorian if (!state) { 11305185a700Sflorian splitwidth = 0; 11315185a700Sflorian break; 11325185a700Sflorian } else if (value == NULL) 11335185a700Sflorian break; 11345185a700Sflorian 1135c49c5f05Sflorian splitwidth = strtonum(value, 0, 1023, &errstr); 1136c49c5f05Sflorian if (errstr != NULL) 1137c49c5f05Sflorian fatal("split is %s: '%s'", errstr, value); 11385185a700Sflorian if ((splitwidth % 4) != 0U) { 11395185a700Sflorian splitwidth = ((splitwidth + 3) / 4) * 4; 11405185a700Sflorian fprintf(stderr, ";; Warning, split must be " 11415185a700Sflorian "a multiple of 4; adjusting " 11425185a700Sflorian "to %u\n", splitwidth); 11435185a700Sflorian } 11445185a700Sflorian /* 11455185a700Sflorian * There is an adjustment done in the 11465185a700Sflorian * totext_<rrtype>() functions which causes 11475185a700Sflorian * splitwidth to shrink. This is okay when we're 11485185a700Sflorian * using the default width but incorrect in this 11495185a700Sflorian * case, so we correct for it 11505185a700Sflorian */ 11515185a700Sflorian if (splitwidth) 11525185a700Sflorian splitwidth += 3; 11535185a700Sflorian break; 11545185a700Sflorian case 't': /* stats */ 11555185a700Sflorian FULLCHECK("stats"); 11565185a700Sflorian lookup->stats = state; 11575185a700Sflorian break; 11585185a700Sflorian case 'u': /* subnet */ 11595185a700Sflorian FULLCHECK("subnet"); 11605185a700Sflorian if (state && value == NULL) 11615185a700Sflorian goto need_value; 11625185a700Sflorian if (!state) { 11635185a700Sflorian if (lookup->ecs_addr != NULL) { 11645185a700Sflorian free(lookup->ecs_addr); 11655185a700Sflorian lookup->ecs_addr = NULL; 11665185a700Sflorian } 11675185a700Sflorian break; 11685185a700Sflorian } 11695185a700Sflorian if (lookup->edns == -1) 11705185a700Sflorian lookup->edns = 0; 11715185a700Sflorian if (lookup->ecs_addr != NULL) { 11725185a700Sflorian free(lookup->ecs_addr); 11735185a700Sflorian lookup->ecs_addr = NULL; 11745185a700Sflorian } 11758c9fac11Sflorian result = parse_netprefix(&lookup->ecs_addr, 11768c9fac11Sflorian &lookup->ecs_plen, value); 11775185a700Sflorian if (result != ISC_R_SUCCESS) 11785185a700Sflorian fatal("Couldn't parse client"); 11795185a700Sflorian break; 11805185a700Sflorian default: 11815185a700Sflorian goto invalid_option; 11825185a700Sflorian } 11835185a700Sflorian break; 11845185a700Sflorian case 't': 11855185a700Sflorian switch (cmd[1]) { 11865185a700Sflorian case 'c': /* tcp */ 11875185a700Sflorian FULLCHECK("tcp"); 11885185a700Sflorian if (!is_batchfile) { 11895185a700Sflorian lookup->tcp_mode = state; 11901fb015a8Sflorian lookup->tcp_mode_set = 1; 11915185a700Sflorian } 11925185a700Sflorian break; 11935185a700Sflorian case 'i': /* timeout */ 11945185a700Sflorian FULLCHECK("timeout"); 11955185a700Sflorian if (value == NULL) 11965185a700Sflorian goto need_value; 11975185a700Sflorian if (!state) 11985185a700Sflorian goto invalid_option; 1199c49c5f05Sflorian timeout = strtonum(value, 0, MAXTIMEOUT, &errstr); 1200c49c5f05Sflorian if (errstr != NULL) 1201c49c5f05Sflorian fatal("timeout is %s: '%s'", errstr, value); 12025185a700Sflorian if (timeout == 0) 12035185a700Sflorian timeout = 1; 12045185a700Sflorian break; 12055185a700Sflorian case 'r': 12065185a700Sflorian switch (cmd[2]) { 12075185a700Sflorian case 'a': /* trace */ 12085185a700Sflorian FULLCHECK("trace"); 12095185a700Sflorian lookup->trace = state; 12105185a700Sflorian lookup->trace_root = state; 12115185a700Sflorian if (state) { 12121fb015a8Sflorian lookup->recurse = 0; 12131fb015a8Sflorian lookup->identify = 1; 12141fb015a8Sflorian lookup->comments = 0; 12155185a700Sflorian rrcomments = 0; 12161fb015a8Sflorian lookup->stats = 0; 12171fb015a8Sflorian lookup->section_additional = 0; 12181fb015a8Sflorian lookup->section_authority = 1; 12191fb015a8Sflorian lookup->section_question = 0; 12201fb015a8Sflorian lookup->dnssec = 1; 12211fb015a8Sflorian usesearch = 0; 12225185a700Sflorian } 12235185a700Sflorian break; 12245185a700Sflorian case 'i': /* tries */ 12255185a700Sflorian FULLCHECK("tries"); 12265185a700Sflorian if (value == NULL) 12275185a700Sflorian goto need_value; 12285185a700Sflorian if (!state) 12295185a700Sflorian goto invalid_option; 1230c49c5f05Sflorian lookup->retries = strtonum(value, 0, MAXTRIES, 1231c49c5f05Sflorian &errstr); 1232c49c5f05Sflorian if (errstr != NULL) 1233c49c5f05Sflorian fatal("tries is %s: '%s'", errstr, 1234c49c5f05Sflorian value); 12355185a700Sflorian if (lookup->retries == 0) 12365185a700Sflorian lookup->retries = 1; 12375185a700Sflorian break; 12385185a700Sflorian default: 12395185a700Sflorian goto invalid_option; 12405185a700Sflorian } 12415185a700Sflorian break; 12425185a700Sflorian case 't': /* ttlid */ 12435185a700Sflorian FULLCHECK("ttlid"); 12441fb015a8Sflorian nottl = !state; 12455185a700Sflorian break; 12465185a700Sflorian default: 12475185a700Sflorian goto invalid_option; 12485185a700Sflorian } 12495185a700Sflorian break; 12505185a700Sflorian case 'v': 12515185a700Sflorian FULLCHECK("vc"); 12525185a700Sflorian if (!is_batchfile) { 12535185a700Sflorian lookup->tcp_mode = state; 12541fb015a8Sflorian lookup->tcp_mode_set = 1; 12555185a700Sflorian } 12565185a700Sflorian break; 1257*9835a5e1Sflorian case 'z': 1258*9835a5e1Sflorian FULLCHECK("zoneversion"); 1259*9835a5e1Sflorian if (!state) 1260*9835a5e1Sflorian break; 1261*9835a5e1Sflorian save_opt(lookup, "zoneversion", NULL); 1262*9835a5e1Sflorian break; 12635185a700Sflorian default: 12645185a700Sflorian invalid_option: 12655185a700Sflorian need_value: 12665185a700Sflorian fprintf(stderr, "Invalid option: +%s\n", 12675185a700Sflorian option); 12685185a700Sflorian usage(); 12695185a700Sflorian } 12705185a700Sflorian return; 12715185a700Sflorian } 12725185a700Sflorian 12735185a700Sflorian /*% 12741fb015a8Sflorian * #1 returned if value was used 12755185a700Sflorian */ 12765185a700Sflorian static const char *single_dash_opts = "46dhinuv"; 12775185a700Sflorian static const char *dash_opts = "46bcdfhikmnptvyx"; 12781fb015a8Sflorian static int 12795185a700Sflorian dash_option(char *option, char *next, dig_lookup_t **lookup, 12801fb015a8Sflorian int *open_type_class, int *need_clone, 12811fb015a8Sflorian int config_only, int argc, char **argv, 12821fb015a8Sflorian int *firstarg) 12835185a700Sflorian { 12845185a700Sflorian char opt, *value, *ptr, *ptr2, *ptr3; 12855185a700Sflorian isc_result_t result; 12861fb015a8Sflorian int value_from_next; 12875185a700Sflorian isc_textregion_t tr; 12885185a700Sflorian dns_rdatatype_t rdtype; 12895185a700Sflorian dns_rdataclass_t rdclass; 12905185a700Sflorian char textname[MXNAME]; 129133e1be9eSflorian char *cmd; 12925185a700Sflorian uint32_t num; 1293c49c5f05Sflorian const char *errstr; 12945185a700Sflorian 12955185a700Sflorian while (strpbrk(option, single_dash_opts) == &option[0]) { 12965185a700Sflorian /* 12975185a700Sflorian * Since the -[46dhinuv] options do not take an argument, 12985185a700Sflorian * account for them (in any number and/or combination) 12995185a700Sflorian * if they appear as the first character(s) of a q-opt. 13005185a700Sflorian */ 13015185a700Sflorian opt = option[0]; 13025185a700Sflorian switch (opt) { 13035185a700Sflorian case '4': 13041bf56eb0Sflorian if (have_ipv4) 13051fb015a8Sflorian have_ipv6 = 0; 13061bf56eb0Sflorian else 13075185a700Sflorian fatal("can't find IPv4 networking"); 13085185a700Sflorian break; 13095185a700Sflorian case '6': 13101bf56eb0Sflorian if (have_ipv6) 13111fb015a8Sflorian have_ipv4 = 0; 13121bf56eb0Sflorian else 13135185a700Sflorian fatal("can't find IPv6 networking"); 13145185a700Sflorian break; 13155185a700Sflorian case 'd': 13165185a700Sflorian ptr = strpbrk(&option[1], dash_opts); 13175185a700Sflorian if (ptr != &option[1]) { 13185185a700Sflorian cmd = option; 13195185a700Sflorian FULLCHECK("debug"); 13201fb015a8Sflorian debugging = 1; 13211fb015a8Sflorian return (0); 13225185a700Sflorian } else 13231fb015a8Sflorian debugging = 1; 13245185a700Sflorian break; 13255185a700Sflorian case 'h': 13265185a700Sflorian help(); 13275185a700Sflorian exit(0); 13285185a700Sflorian break; 13295185a700Sflorian case 'i': 13301fb015a8Sflorian ip6_int = 1; 13315185a700Sflorian break; 13325185a700Sflorian case 'n': 13335185a700Sflorian /* deprecated */ 13345185a700Sflorian break; 13355185a700Sflorian case 'u': 13361fb015a8Sflorian use_usec = 1; 13375185a700Sflorian break; 13385185a700Sflorian case 'v': 13395185a700Sflorian version(); 13405185a700Sflorian exit(0); 13415185a700Sflorian break; 13425185a700Sflorian } 13435185a700Sflorian if (strlen(option) > 1U) 13445185a700Sflorian option = &option[1]; 13455185a700Sflorian else 13461fb015a8Sflorian return (0); 13475185a700Sflorian } 13485185a700Sflorian opt = option[0]; 13495185a700Sflorian if (strlen(option) > 1U) { 13501fb015a8Sflorian value_from_next = 0; 13515185a700Sflorian value = &option[1]; 13525185a700Sflorian } else { 13531fb015a8Sflorian value_from_next = 1; 13545185a700Sflorian value = next; 13555185a700Sflorian } 13565185a700Sflorian if (value == NULL) 13575185a700Sflorian goto invalid_option; 13585185a700Sflorian switch (opt) { 135933e1be9eSflorian case 'b': { 136033e1be9eSflorian struct addrinfo *ai = NULL, hints; 136133e1be9eSflorian int error; 136233e1be9eSflorian char *hash; 136333e1be9eSflorian 136433e1be9eSflorian memset(&hints, 0, sizeof(hints)); 136533e1be9eSflorian hints.ai_flags = AI_NUMERICHOST; 136633e1be9eSflorian hints.ai_socktype = SOCK_DGRAM; 136733e1be9eSflorian 13685185a700Sflorian hash = strchr(value, '#'); 13695185a700Sflorian if (hash != NULL) { 13705185a700Sflorian *hash = '\0'; 137133e1be9eSflorian error = getaddrinfo(value, hash + 1, &hints, &ai); 13725185a700Sflorian *hash = '#'; 137333e1be9eSflorian } else 137433e1be9eSflorian error = getaddrinfo(value, NULL, &hints, &ai); 137533e1be9eSflorian 137633e1be9eSflorian if (error) 137733e1be9eSflorian fatal("invalid address %s: %s", value, 137833e1be9eSflorian gai_strerror(error)); 137933e1be9eSflorian if (ai == NULL || ai->ai_addrlen > sizeof(bind_address)) 138033e1be9eSflorian fatal("invalid address %s", value); 138133e1be9eSflorian if (!have_ipv4 && ai->ai_family == AF_INET) 138233e1be9eSflorian fatal("%s: wrong address family", value); 138333e1be9eSflorian if (!have_ipv6 && ai->ai_family == AF_INET6) 138433e1be9eSflorian fatal("%s: wrong address family", value); 138533e1be9eSflorian 138633e1be9eSflorian memset(&bind_address, 0, sizeof(bind_address)); 138733e1be9eSflorian memcpy(&bind_address, ai->ai_addr, ai->ai_addrlen); 138833e1be9eSflorian 13891fb015a8Sflorian specified_source = 1; 13905185a700Sflorian return (value_from_next); 139133e1be9eSflorian } 13925185a700Sflorian case 'c': 13935185a700Sflorian if ((*lookup)->rdclassset) { 13945185a700Sflorian fprintf(stderr, ";; Warning, extra class option\n"); 13955185a700Sflorian } 13961fb015a8Sflorian *open_type_class = 0; 13975185a700Sflorian tr.base = value; 13985185a700Sflorian tr.length = (unsigned int) strlen(value); 13995185a700Sflorian result = dns_rdataclass_fromtext(&rdclass, 14005185a700Sflorian (isc_textregion_t *)&tr); 14015185a700Sflorian if (result == ISC_R_SUCCESS) { 14025185a700Sflorian (*lookup)->rdclass = rdclass; 14031fb015a8Sflorian (*lookup)->rdclassset = 1; 14045185a700Sflorian } else 14055185a700Sflorian fprintf(stderr, ";; Warning, ignoring " 14065185a700Sflorian "invalid class %s\n", 14075185a700Sflorian value); 14085185a700Sflorian return (value_from_next); 14095185a700Sflorian case 'f': 14105185a700Sflorian batchname = value; 14115185a700Sflorian return (value_from_next); 14125185a700Sflorian case 'k': 14135185a700Sflorian strlcpy(keyfile, value, sizeof(keyfile)); 14145185a700Sflorian return (value_from_next); 14155185a700Sflorian case 'p': 1416c49c5f05Sflorian num = strtonum(value, 0, MAXPORT, &errstr); 1417c49c5f05Sflorian if (errstr != NULL) 1418c49c5f05Sflorian fatal("port number is %s: '%s'", errstr, value); 14195185a700Sflorian port = num; 14205185a700Sflorian return (value_from_next); 14215185a700Sflorian case 'q': 14225185a700Sflorian if (!config_only) { 14235185a700Sflorian if (*need_clone) 14245185a700Sflorian (*lookup) = clone_lookup(default_lookup, 14251fb015a8Sflorian 1); 14261fb015a8Sflorian *need_clone = 1; 14275185a700Sflorian strlcpy((*lookup)->textname, value, 14285185a700Sflorian sizeof((*lookup)->textname)); 14291fb015a8Sflorian (*lookup)->trace_root = (*lookup)->trace || 14301fb015a8Sflorian (*lookup)->ns_search_only; 14311fb015a8Sflorian (*lookup)->new_search = 1; 14325185a700Sflorian if (*firstarg) { 14335185a700Sflorian printgreeting(argc, argv, *lookup); 14341fb015a8Sflorian *firstarg = 0; 14355185a700Sflorian } 14365185a700Sflorian ISC_LIST_APPEND(lookup_list, (*lookup), link); 14375185a700Sflorian debug("looking up %s", (*lookup)->textname); 14385185a700Sflorian } 14395185a700Sflorian return (value_from_next); 14405185a700Sflorian case 't': 14411fb015a8Sflorian *open_type_class = 0; 14425185a700Sflorian if (strncasecmp(value, "ixfr=", 5) == 0) { 14435185a700Sflorian rdtype = dns_rdatatype_ixfr; 14445185a700Sflorian result = ISC_R_SUCCESS; 14455185a700Sflorian } else { 14465185a700Sflorian tr.base = value; 14475185a700Sflorian tr.length = (unsigned int) strlen(value); 14485185a700Sflorian result = dns_rdatatype_fromtext(&rdtype, 14495185a700Sflorian (isc_textregion_t *)&tr); 14505185a700Sflorian if (result == ISC_R_SUCCESS && 14515185a700Sflorian rdtype == dns_rdatatype_ixfr) { 14525185a700Sflorian result = DNS_R_UNKNOWN; 14535185a700Sflorian } 14545185a700Sflorian } 14555185a700Sflorian if (result == ISC_R_SUCCESS) { 14565185a700Sflorian if ((*lookup)->rdtypeset) { 14575185a700Sflorian fprintf(stderr, ";; Warning, " 14585185a700Sflorian "extra type option\n"); 14595185a700Sflorian } 14605185a700Sflorian if (rdtype == dns_rdatatype_ixfr) { 14615185a700Sflorian uint32_t serial; 14625185a700Sflorian (*lookup)->rdtype = dns_rdatatype_ixfr; 14631fb015a8Sflorian (*lookup)->rdtypeset = 1; 1464c49c5f05Sflorian serial = strtonum(&value[5], 0, MAXSERIAL, 1465c49c5f05Sflorian &errstr); 1466c49c5f05Sflorian if (errstr != NULL) 1467c49c5f05Sflorian fatal("serial number is %s: '%s'", 1468c49c5f05Sflorian errstr, &value[5]); 14695185a700Sflorian (*lookup)->ixfr_serial = serial; 14705185a700Sflorian (*lookup)->section_question = plusquest; 14715185a700Sflorian (*lookup)->comments = pluscomm; 14725185a700Sflorian if (!(*lookup)->tcp_mode_set) 14731fb015a8Sflorian (*lookup)->tcp_mode = 1; 14745185a700Sflorian } else { 14755185a700Sflorian (*lookup)->rdtype = rdtype; 14765185a700Sflorian if (!config_only) 14771fb015a8Sflorian (*lookup)->rdtypeset = 1; 14785185a700Sflorian if (rdtype == dns_rdatatype_axfr) { 14795185a700Sflorian (*lookup)->section_question = plusquest; 14805185a700Sflorian (*lookup)->comments = pluscomm; 14815185a700Sflorian } 14821fb015a8Sflorian (*lookup)->ixfr_serial = 0; 14835185a700Sflorian } 14845185a700Sflorian } else 14855185a700Sflorian fprintf(stderr, ";; Warning, ignoring " 14865185a700Sflorian "invalid type %s\n", 14875185a700Sflorian value); 14885185a700Sflorian return (value_from_next); 14895185a700Sflorian case 'y': 14905185a700Sflorian ptr = next_token(&value, ":"); /* hmac type or name */ 14915185a700Sflorian if (ptr == NULL) { 14925185a700Sflorian usage(); 14935185a700Sflorian } 14945185a700Sflorian ptr2 = next_token(&value, ":"); /* name or secret */ 14955185a700Sflorian if (ptr2 == NULL) 14965185a700Sflorian usage(); 14975185a700Sflorian ptr3 = next_token(&value, ":"); /* secret or NULL */ 14985185a700Sflorian if (ptr3 != NULL) { 14995185a700Sflorian parse_hmac(ptr); 15005185a700Sflorian ptr = ptr2; 15015185a700Sflorian ptr2 = ptr3; 15025185a700Sflorian } else { 15035185a700Sflorian hmacname = DNS_TSIG_HMACSHA256_NAME; 15045185a700Sflorian digestbits = 0; 15055185a700Sflorian } 15065185a700Sflorian strlcpy(keynametext, ptr, sizeof(keynametext)); 15075185a700Sflorian strlcpy(keysecret, ptr2, sizeof(keysecret)); 15085185a700Sflorian return (value_from_next); 15095185a700Sflorian case 'x': 15105185a700Sflorian if (*need_clone) 15111fb015a8Sflorian *lookup = clone_lookup(default_lookup, 1); 15121fb015a8Sflorian *need_clone = 1; 15135185a700Sflorian if (get_reverse(textname, sizeof(textname), value, 15141fb015a8Sflorian ip6_int, 0) == ISC_R_SUCCESS) { 15155185a700Sflorian strlcpy((*lookup)->textname, textname, 15165185a700Sflorian sizeof((*lookup)->textname)); 15175185a700Sflorian debug("looking up %s", (*lookup)->textname); 15181fb015a8Sflorian (*lookup)->trace_root = (*lookup)->trace || 15191fb015a8Sflorian (*lookup)->ns_search_only; 15205185a700Sflorian (*lookup)->ip6_int = ip6_int; 15215185a700Sflorian if (!(*lookup)->rdtypeset) 15225185a700Sflorian (*lookup)->rdtype = dns_rdatatype_ptr; 15235185a700Sflorian if (!(*lookup)->rdclassset) 15245185a700Sflorian (*lookup)->rdclass = dns_rdataclass_in; 15251fb015a8Sflorian (*lookup)->new_search = 1; 15265185a700Sflorian if (*firstarg) { 15275185a700Sflorian printgreeting(argc, argv, *lookup); 15281fb015a8Sflorian *firstarg = 0; 15295185a700Sflorian } 15305185a700Sflorian ISC_LIST_APPEND(lookup_list, *lookup, link); 15315185a700Sflorian } else { 15325185a700Sflorian fprintf(stderr, "Invalid IP address %s\n", value); 15335185a700Sflorian exit(1); 15345185a700Sflorian } 15355185a700Sflorian return (value_from_next); 15365185a700Sflorian invalid_option: 15375185a700Sflorian default: 15385185a700Sflorian fprintf(stderr, "Invalid option: -%s\n", option); 15395185a700Sflorian usage(); 15405185a700Sflorian } 15415185a700Sflorian /* NOTREACHED */ 15421fb015a8Sflorian return (0); 15435185a700Sflorian } 15445185a700Sflorian 15455185a700Sflorian /*% 15465185a700Sflorian * Because we may be trying to do memory allocation recording, we're going 15475185a700Sflorian * to need to parse the arguments for the -m *before* we start the main 15485185a700Sflorian * argument parsing routine. 15495185a700Sflorian * 15505185a700Sflorian * I'd prefer not to have to do this, but I am not quite sure how else to 15515185a700Sflorian * fix the problem. Argument parsing in dig involves memory allocation 15525185a700Sflorian * by its nature, so it can't be done in the main argument parser. 15535185a700Sflorian */ 15545185a700Sflorian static void 15555185a700Sflorian preparse_args(int argc, char **argv) { 15565185a700Sflorian int rc; 15575185a700Sflorian char **rv; 15585185a700Sflorian char *option; 15595185a700Sflorian 15605185a700Sflorian rc = argc; 15615185a700Sflorian rv = argv; 15625185a700Sflorian for (rc--, rv++; rc > 0; rc--, rv++) { 15635185a700Sflorian if (rv[0][0] != '-') 15645185a700Sflorian continue; 15655185a700Sflorian option = &rv[0][1]; 15665185a700Sflorian while (strpbrk(option, single_dash_opts) == &option[0]) { 15675185a700Sflorian switch (option[0]) { 15685185a700Sflorian case '4': 15695185a700Sflorian if (ipv6only) 15705185a700Sflorian fatal("only one of -4 and -6 allowed"); 15711fb015a8Sflorian ipv4only = 1; 15725185a700Sflorian break; 15735185a700Sflorian case '6': 15745185a700Sflorian if (ipv4only) 15755185a700Sflorian fatal("only one of -4 and -6 allowed"); 15761fb015a8Sflorian ipv6only = 1; 15775185a700Sflorian break; 15785185a700Sflorian } 15795185a700Sflorian option = &option[1]; 15805185a700Sflorian } 15815185a700Sflorian } 15825185a700Sflorian } 15835185a700Sflorian 15845185a700Sflorian static void 15851fb015a8Sflorian parse_args(int is_batchfile, int config_only, 15865185a700Sflorian int argc, char **argv) 15875185a700Sflorian { 15885185a700Sflorian isc_result_t result; 15895185a700Sflorian isc_textregion_t tr; 15901fb015a8Sflorian int firstarg = 1; 15915185a700Sflorian dig_lookup_t *lookup = NULL; 15925185a700Sflorian dns_rdatatype_t rdtype; 15935185a700Sflorian dns_rdataclass_t rdclass; 15941fb015a8Sflorian int open_type_class = 1; 15955185a700Sflorian char batchline[MXNAME]; 15965185a700Sflorian int bargc; 15975185a700Sflorian char *bargv[64]; 15985185a700Sflorian int rc; 15995185a700Sflorian char **rv; 16005185a700Sflorian char *input; 16015185a700Sflorian int i; 16021fb015a8Sflorian int need_clone = 1; 1603c49c5f05Sflorian const char *errstr; 16045185a700Sflorian 16055185a700Sflorian /* 16065185a700Sflorian * The semantics for parsing the args is a bit complex; if 16075185a700Sflorian * we don't have a host yet, make the arg apply globally, 16085185a700Sflorian * otherwise make it apply to the latest host. This is 16095185a700Sflorian * a bit different than the previous versions, but should 16105185a700Sflorian * form a consistent user interface. 16115185a700Sflorian * 16125185a700Sflorian * First, create a "default lookup" which won't actually be used 16135185a700Sflorian * anywhere, except for cloning into new lookups 16145185a700Sflorian */ 16155185a700Sflorian 16165185a700Sflorian debug("parse_args()"); 16175185a700Sflorian if (!is_batchfile) { 16185185a700Sflorian debug("making new lookup"); 16195185a700Sflorian default_lookup = make_empty_lookup(); 16201fb015a8Sflorian default_lookup->adflag = 1; 16215185a700Sflorian default_lookup->edns = 0; 16225185a700Sflorian } 16235185a700Sflorian 16245185a700Sflorian if (is_batchfile && !config_only) { 16255185a700Sflorian /* Processing '-f batchfile'. */ 16261fb015a8Sflorian lookup = clone_lookup(default_lookup, 1); 16271fb015a8Sflorian need_clone = 0; 16285185a700Sflorian } else 16295185a700Sflorian lookup = default_lookup; 16305185a700Sflorian 16315185a700Sflorian rc = argc; 16325185a700Sflorian rv = argv; 16335185a700Sflorian for (rc--, rv++; rc > 0; rc--, rv++) { 16345185a700Sflorian debug("main parsing %s", rv[0]); 16355185a700Sflorian if (strncmp(rv[0], "%", 1) == 0) 16365185a700Sflorian break; 16375185a700Sflorian if (rv[0][0] == '@') { 16385185a700Sflorian 16395185a700Sflorian if (is_batchfile && !config_only) { 16405185a700Sflorian addresscount = getaddresses(lookup, &rv[0][1], 16415185a700Sflorian &result); 16425185a700Sflorian if (result != ISC_R_SUCCESS) { 16435185a700Sflorian fprintf(stderr, "couldn't get address " 16445185a700Sflorian "for '%s': %s: skipping " 16455185a700Sflorian "lookup\n", &rv[0][1], 16465185a700Sflorian isc_result_totext(result)); 16475185a700Sflorian if (ISC_LINK_LINKED(lookup, link)) 16485185a700Sflorian ISC_LIST_DEQUEUE(lookup_list, 16495185a700Sflorian lookup, link); 16505185a700Sflorian destroy_lookup(lookup); 16515185a700Sflorian return; 16525185a700Sflorian } 16535185a700Sflorian } else 16545185a700Sflorian addresscount = getaddresses(lookup, &rv[0][1], 16555185a700Sflorian NULL); 16565185a700Sflorian } else if (rv[0][0] == '+') { 16575185a700Sflorian plus_option(&rv[0][1], is_batchfile, 16585185a700Sflorian lookup); 16595185a700Sflorian } else if (rv[0][0] == '-') { 16605185a700Sflorian if (rc <= 1) { 16615185a700Sflorian if (dash_option(&rv[0][1], NULL, 16625185a700Sflorian &lookup, &open_type_class, 16635185a700Sflorian &need_clone, config_only, 16645185a700Sflorian argc, argv, &firstarg)) { 16655185a700Sflorian rc--; 16665185a700Sflorian rv++; 16675185a700Sflorian } 16685185a700Sflorian } else { 16695185a700Sflorian if (dash_option(&rv[0][1], rv[1], 16705185a700Sflorian &lookup, &open_type_class, 16715185a700Sflorian &need_clone, config_only, 16725185a700Sflorian argc, argv, &firstarg)) { 16735185a700Sflorian rc--; 16745185a700Sflorian rv++; 16755185a700Sflorian } 16765185a700Sflorian } 16775185a700Sflorian } else { 16785185a700Sflorian /* 16795185a700Sflorian * Anything which isn't an option 16805185a700Sflorian */ 16815185a700Sflorian if (open_type_class) { 16825185a700Sflorian if (strncasecmp(rv[0], "ixfr=", 5) == 0) { 16835185a700Sflorian rdtype = dns_rdatatype_ixfr; 16845185a700Sflorian result = ISC_R_SUCCESS; 16855185a700Sflorian } else { 16865185a700Sflorian tr.base = rv[0]; 16875185a700Sflorian tr.length = 16885185a700Sflorian (unsigned int) strlen(rv[0]); 16895185a700Sflorian result = dns_rdatatype_fromtext(&rdtype, 16905185a700Sflorian (isc_textregion_t *)&tr); 16915185a700Sflorian if (result == ISC_R_SUCCESS && 16925185a700Sflorian rdtype == dns_rdatatype_ixfr) { 16935185a700Sflorian fprintf(stderr, ";; Warning, " 16945185a700Sflorian "ixfr requires a " 16955185a700Sflorian "serial number\n"); 16965185a700Sflorian continue; 16975185a700Sflorian } 16985185a700Sflorian } 16995185a700Sflorian if (result == ISC_R_SUCCESS) { 17005185a700Sflorian if (lookup->rdtypeset) { 17015185a700Sflorian fprintf(stderr, ";; Warning, " 17025185a700Sflorian "extra type option\n"); 17035185a700Sflorian } 17045185a700Sflorian if (rdtype == dns_rdatatype_ixfr) { 17055185a700Sflorian uint32_t serial; 17065185a700Sflorian lookup->rdtype = 17075185a700Sflorian dns_rdatatype_ixfr; 17081fb015a8Sflorian lookup->rdtypeset = 1; 1709c49c5f05Sflorian serial = strtonum(&rv[0][5], 0, 1710c49c5f05Sflorian MAXSERIAL, &errstr); 1711c49c5f05Sflorian if (errstr != NULL) 1712c49c5f05Sflorian fatal("serial number " 1713c49c5f05Sflorian "is %s: '%s'", 1714c49c5f05Sflorian errstr, &rv[0][5]); 17155185a700Sflorian lookup->ixfr_serial = serial; 17165185a700Sflorian lookup->section_question = 17175185a700Sflorian plusquest; 17185185a700Sflorian lookup->comments = pluscomm; 17195185a700Sflorian if (!lookup->tcp_mode_set) 17201fb015a8Sflorian lookup->tcp_mode = 1; 17215185a700Sflorian } else { 17225185a700Sflorian lookup->rdtype = rdtype; 17231fb015a8Sflorian lookup->rdtypeset = 1; 17245185a700Sflorian if (rdtype == 17255185a700Sflorian dns_rdatatype_axfr) { 17265185a700Sflorian lookup->section_question = 17275185a700Sflorian plusquest; 17285185a700Sflorian lookup->comments = pluscomm; 17295185a700Sflorian } 17301fb015a8Sflorian lookup->ixfr_serial = 0; 17315185a700Sflorian } 17325185a700Sflorian continue; 17335185a700Sflorian } 17345185a700Sflorian result = dns_rdataclass_fromtext(&rdclass, 17355185a700Sflorian (isc_textregion_t *)&tr); 17365185a700Sflorian if (result == ISC_R_SUCCESS) { 17375185a700Sflorian if (lookup->rdclassset) { 17385185a700Sflorian fprintf(stderr, ";; Warning, " 17395185a700Sflorian "extra class option\n"); 17405185a700Sflorian } 17415185a700Sflorian lookup->rdclass = rdclass; 17421fb015a8Sflorian lookup->rdclassset = 1; 17435185a700Sflorian continue; 17445185a700Sflorian } 17455185a700Sflorian } 17465185a700Sflorian 17475185a700Sflorian if (!config_only) { 17485185a700Sflorian if (need_clone) 17495185a700Sflorian lookup = clone_lookup(default_lookup, 17501fb015a8Sflorian 1); 17511fb015a8Sflorian need_clone = 1; 17525185a700Sflorian strlcpy(lookup->textname, rv[0], 17535185a700Sflorian sizeof(lookup->textname)); 17541fb015a8Sflorian lookup->trace_root = lookup->trace || 17551fb015a8Sflorian lookup->ns_search_only; 17561fb015a8Sflorian lookup->new_search = 1; 17575185a700Sflorian if (firstarg) { 17585185a700Sflorian printgreeting(argc, argv, lookup); 17591fb015a8Sflorian firstarg = 0; 17605185a700Sflorian } 17615185a700Sflorian ISC_LIST_APPEND(lookup_list, lookup, link); 17625185a700Sflorian debug("looking up %s", lookup->textname); 17635185a700Sflorian } 17645185a700Sflorian /* XXX Error message */ 17655185a700Sflorian } 17665185a700Sflorian } 17675185a700Sflorian 17685185a700Sflorian /* 17695185a700Sflorian * If we have a batchfile, seed the lookup list with the 17705185a700Sflorian * first entry, then trust the callback in dighost_shutdown 17715185a700Sflorian * to get the rest 17725185a700Sflorian */ 17735185a700Sflorian if ((batchname != NULL) && !(is_batchfile)) { 17745185a700Sflorian if (strcmp(batchname, "-") == 0) 17755185a700Sflorian batchfp = stdin; 17765185a700Sflorian else 17775185a700Sflorian batchfp = fopen(batchname, "r"); 17785185a700Sflorian if (batchfp == NULL) { 17795185a700Sflorian perror(batchname); 17805185a700Sflorian if (exitcode < 8) 17815185a700Sflorian exitcode = 8; 17825185a700Sflorian fatal("couldn't open specified batch file"); 17835185a700Sflorian } 17845185a700Sflorian /* XXX Remove code dup from shutdown code */ 17855185a700Sflorian next_line: 1786267a2de3Sjsg if (fgets(batchline, sizeof(batchline), batchfp) != NULL) { 17875185a700Sflorian bargc = 1; 17885185a700Sflorian debug("batch line %s", batchline); 17895185a700Sflorian if (batchline[0] == '\r' || batchline[0] == '\n' 17905185a700Sflorian || batchline[0] == '#' || batchline[0] == ';') 17915185a700Sflorian goto next_line; 17925185a700Sflorian input = batchline; 17935185a700Sflorian bargv[bargc] = next_token(&input, " \t\r\n"); 17945185a700Sflorian while ((bargc < 14) && (bargv[bargc] != NULL)) { 17955185a700Sflorian bargc++; 17965185a700Sflorian bargv[bargc] = next_token(&input, " \t\r\n"); 17975185a700Sflorian } 17985185a700Sflorian 17995185a700Sflorian bargv[0] = argv[0]; 18005185a700Sflorian argv0 = argv[0]; 18015185a700Sflorian 18025185a700Sflorian for(i = 0; i < bargc; i++) 18035185a700Sflorian debug("batch argv %d: %s", i, bargv[i]); 18041fb015a8Sflorian parse_args(1, 0, bargc, (char **)bargv); 18055185a700Sflorian return; 18065185a700Sflorian } 18075185a700Sflorian return; 18085185a700Sflorian } 18095185a700Sflorian /* 18105185a700Sflorian * If no lookup specified, search for root 18115185a700Sflorian */ 18125185a700Sflorian if ((lookup_list.head == NULL) && !config_only) { 18135185a700Sflorian if (need_clone) 18141fb015a8Sflorian lookup = clone_lookup(default_lookup, 1); 18151fb015a8Sflorian need_clone = 1; 18161fb015a8Sflorian lookup->trace_root = lookup->trace || lookup->ns_search_only; 18171fb015a8Sflorian lookup->new_search = 1; 18185185a700Sflorian strlcpy(lookup->textname, ".", sizeof(lookup->textname)); 18195185a700Sflorian lookup->rdtype = dns_rdatatype_ns; 18201fb015a8Sflorian lookup->rdtypeset = 1; 18215185a700Sflorian if (firstarg) { 18225185a700Sflorian printgreeting(argc, argv, lookup); 18231fb015a8Sflorian firstarg = 0; 18245185a700Sflorian } 18255185a700Sflorian ISC_LIST_APPEND(lookup_list, lookup, link); 18265185a700Sflorian } 18275185a700Sflorian if (!need_clone) 18285185a700Sflorian destroy_lookup(lookup); 18295185a700Sflorian } 18305185a700Sflorian 18315185a700Sflorian /* 18325185a700Sflorian * Callback from dighost.c to allow program-specific shutdown code. 18335185a700Sflorian * Here, we're possibly reading from a batch file, then shutting down 18345185a700Sflorian * for real if there's nothing in the batch file to read. 18355185a700Sflorian */ 18365185a700Sflorian static void 18375185a700Sflorian query_finished(void) { 18385185a700Sflorian char batchline[MXNAME]; 18395185a700Sflorian int bargc; 18405185a700Sflorian char *bargv[16]; 18415185a700Sflorian char *input; 18425185a700Sflorian int i; 18435185a700Sflorian 18445185a700Sflorian if (batchname == NULL) { 18455185a700Sflorian isc_app_shutdown(); 18465185a700Sflorian return; 18475185a700Sflorian } 18485185a700Sflorian 18495185a700Sflorian fflush(stdout); 18505185a700Sflorian if (feof(batchfp)) { 18515185a700Sflorian batchname = NULL; 18525185a700Sflorian isc_app_shutdown(); 18535185a700Sflorian if (batchfp != stdin) 18545185a700Sflorian fclose(batchfp); 18555185a700Sflorian return; 18565185a700Sflorian } 18575185a700Sflorian 1858267a2de3Sjsg if (fgets(batchline, sizeof(batchline), batchfp) != NULL) { 18595185a700Sflorian debug("batch line %s", batchline); 18605185a700Sflorian bargc = 1; 18615185a700Sflorian input = batchline; 18625185a700Sflorian bargv[bargc] = next_token(&input, " \t\r\n"); 18635185a700Sflorian while ((bargc < 14) && (bargv[bargc] != NULL)) { 18645185a700Sflorian bargc++; 18655185a700Sflorian bargv[bargc] = next_token(&input, " \t\r\n"); 18665185a700Sflorian } 18675185a700Sflorian 18685185a700Sflorian bargv[0] = argv0; 18695185a700Sflorian 18705185a700Sflorian for(i = 0; i < bargc; i++) 18715185a700Sflorian debug("batch argv %d: %s", i, bargv[i]); 18721fb015a8Sflorian parse_args(1, 0, bargc, (char **)bargv); 18735185a700Sflorian start_lookup(); 18745185a700Sflorian } else { 18755185a700Sflorian batchname = NULL; 18765185a700Sflorian if (batchfp != stdin) 18775185a700Sflorian fclose(batchfp); 18785185a700Sflorian isc_app_shutdown(); 18795185a700Sflorian return; 18805185a700Sflorian } 18815185a700Sflorian } 18825185a700Sflorian 18835185a700Sflorian void dig_setup(int argc, char **argv) 18845185a700Sflorian { 18855185a700Sflorian isc_result_t result; 18865185a700Sflorian 18875185a700Sflorian ISC_LIST_INIT(lookup_list); 18885185a700Sflorian ISC_LIST_INIT(server_list); 1889927deb69Sflorian ISC_LIST_INIT(root_hints_server_list); 18905185a700Sflorian ISC_LIST_INIT(search_list); 18915185a700Sflorian 18925185a700Sflorian if (pledge("stdio rpath inet dns", NULL) == -1) { 18935185a700Sflorian perror("pledge"); 18945185a700Sflorian exit(1); 18955185a700Sflorian } 18965185a700Sflorian 18975185a700Sflorian debug("dig_setup()"); 18985185a700Sflorian 18995185a700Sflorian /* setup dighost callbacks */ 19005185a700Sflorian dighost_printmessage = printmessage; 19015185a700Sflorian dighost_received = received; 19025185a700Sflorian dighost_trying = trying; 19035185a700Sflorian dighost_shutdown = query_finished; 19045185a700Sflorian 19055185a700Sflorian progname = argv[0]; 19065185a700Sflorian preparse_args(argc, argv); 19075185a700Sflorian 19085185a700Sflorian result = isc_app_start(); 19095185a700Sflorian check_result(result, "isc_app_start"); 19105185a700Sflorian 19115185a700Sflorian setup_libs(); 19125185a700Sflorian setup_system(ipv4only, ipv6only); 19135185a700Sflorian } 19145185a700Sflorian 19151fb015a8Sflorian void dig_query_setup(int is_batchfile, int config_only, 19165185a700Sflorian int argc, char **argv) 19175185a700Sflorian { 19185185a700Sflorian debug("dig_query_setup"); 19195185a700Sflorian 19205185a700Sflorian parse_args(is_batchfile, config_only, argc, argv); 19215185a700Sflorian if (keyfile[0] != 0) 19225185a700Sflorian setup_file_key(); 19235185a700Sflorian else if (keysecret[0] != 0) 19245185a700Sflorian setup_text_key(); 19255185a700Sflorian 19265185a700Sflorian if (pledge("stdio inet dns", NULL) == -1) { 19275185a700Sflorian perror("pledge"); 19285185a700Sflorian exit(1); 19295185a700Sflorian } 19305185a700Sflorian 19315185a700Sflorian if (domainopt[0] != '\0') { 19325185a700Sflorian set_search_domain(domainopt); 19331fb015a8Sflorian usesearch = 1; 19345185a700Sflorian } 19355185a700Sflorian } 19365185a700Sflorian 1937a83f8be2Sjsg void dig_startup(void) { 19385185a700Sflorian isc_result_t result; 19395185a700Sflorian 19405185a700Sflorian debug("dig_startup()"); 19415185a700Sflorian 19425185a700Sflorian result = isc_app_onrun(global_task, onrun_callback, NULL); 19435185a700Sflorian check_result(result, "isc_app_onrun"); 19445185a700Sflorian isc_app_run(); 19455185a700Sflorian } 19465185a700Sflorian 19475185a700Sflorian void 1948a83f8be2Sjsg dig_shutdown(void) { 19495185a700Sflorian destroy_lookup(default_lookup); 19505185a700Sflorian if (batchname != NULL) { 19515185a700Sflorian if (batchfp != stdin) 19525185a700Sflorian fclose(batchfp); 19535185a700Sflorian batchname = NULL; 19545185a700Sflorian } 19555185a700Sflorian 19565185a700Sflorian cancel_all(); 19575185a700Sflorian destroy_libs(); 19585185a700Sflorian } 19595185a700Sflorian 19605185a700Sflorian /*% Main processing routine for dig */ 19615185a700Sflorian int 19625185a700Sflorian main(int argc, char **argv) { 19635185a700Sflorian extern char *__progname; 19645185a700Sflorian 19655185a700Sflorian if (strcmp("host", __progname) == 0) 19665185a700Sflorian return host_main(argc, argv); 19675185a700Sflorian if (strcmp("nslookup", __progname) == 0) 19685185a700Sflorian return nslookup_main(argc, argv); 19695185a700Sflorian 19705185a700Sflorian dig_setup(argc, argv); 19711fb015a8Sflorian dig_query_setup(0, 0, argc, argv); 19725185a700Sflorian dig_startup(); 19735185a700Sflorian dig_shutdown(); 19745185a700Sflorian 19755185a700Sflorian return (exitcode); 19765185a700Sflorian } 1977