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