xref: /plan9/sys/src/cmd/ndb/dnsdebug.c (revision 7dd7cddf99dd7472612f1413b4da293630e6b1bc)
1*7dd7cddfSDavid du Colombier #include <u.h>
2*7dd7cddfSDavid du Colombier #include <libc.h>
3*7dd7cddfSDavid du Colombier #include <bio.h>
4*7dd7cddfSDavid du Colombier #include <ctype.h>
5*7dd7cddfSDavid du Colombier #include <ip.h>
6*7dd7cddfSDavid du Colombier #include <ndb.h>
7*7dd7cddfSDavid du Colombier #include "dns.h"
8*7dd7cddfSDavid du Colombier 
9*7dd7cddfSDavid du Colombier enum
10*7dd7cddfSDavid du Colombier {
11*7dd7cddfSDavid du Colombier 	Maxrequest=		4*NAMELEN,
12*7dd7cddfSDavid du Colombier 	Ncache=			8,
13*7dd7cddfSDavid du Colombier 	Maxpath=		128,
14*7dd7cddfSDavid du Colombier 	Maxreply=		512,
15*7dd7cddfSDavid du Colombier 	Maxrrr=			16,
16*7dd7cddfSDavid du Colombier };
17*7dd7cddfSDavid du Colombier 
18*7dd7cddfSDavid du Colombier static char *servername;
19*7dd7cddfSDavid du Colombier static RR *serverrr;
20*7dd7cddfSDavid du Colombier static RR *serveraddrs;
21*7dd7cddfSDavid du Colombier 
22*7dd7cddfSDavid du Colombier int	debug;
23*7dd7cddfSDavid du Colombier int	cachedb;
24*7dd7cddfSDavid du Colombier ulong	now;
25*7dd7cddfSDavid du Colombier int	testing;
26*7dd7cddfSDavid du Colombier char	*trace;
27*7dd7cddfSDavid du Colombier int	needrefresh;
28*7dd7cddfSDavid du Colombier int	resolver;
29*7dd7cddfSDavid du Colombier uchar	ipaddr[IPaddrlen];	/* my ip address */
30*7dd7cddfSDavid du Colombier int	maxage;
31*7dd7cddfSDavid du Colombier char	*logfile = "dns";
32*7dd7cddfSDavid du Colombier char	*dbfile;
33*7dd7cddfSDavid du Colombier char	mntpt[Maxpath];
34*7dd7cddfSDavid du Colombier 
35*7dd7cddfSDavid du Colombier int prettyrrconv(va_list*, Fconv*);
36*7dd7cddfSDavid du Colombier void preloadserveraddrs(void);
37*7dd7cddfSDavid du Colombier void squirrelserveraddrs(void);
38*7dd7cddfSDavid du Colombier int setserver(char*);
39*7dd7cddfSDavid du Colombier void doquery(char*, char*);
40*7dd7cddfSDavid du Colombier void docmd(int, char**);
41*7dd7cddfSDavid du Colombier 
42*7dd7cddfSDavid du Colombier void
43*7dd7cddfSDavid du Colombier main(int argc, char *argv[])
44*7dd7cddfSDavid du Colombier {
45*7dd7cddfSDavid du Colombier 	int n;
46*7dd7cddfSDavid du Colombier 	Biobuf in;
47*7dd7cddfSDavid du Colombier 	char buf[1024], *p;
48*7dd7cddfSDavid du Colombier 	char *f[4];
49*7dd7cddfSDavid du Colombier 
50*7dd7cddfSDavid du Colombier 	strcpy(mntpt, "/net");
51*7dd7cddfSDavid du Colombier 
52*7dd7cddfSDavid du Colombier 	ARGBEGIN{
53*7dd7cddfSDavid du Colombier 	case 'r':
54*7dd7cddfSDavid du Colombier 		resolver = 1;
55*7dd7cddfSDavid du Colombier 		break;
56*7dd7cddfSDavid du Colombier 	case 'x':
57*7dd7cddfSDavid du Colombier 		dbfile = "/lib/ndb/external";
58*7dd7cddfSDavid du Colombier 		strcpy(mntpt, "/net.alt");
59*7dd7cddfSDavid du Colombier 		break;
60*7dd7cddfSDavid du Colombier 	}ARGEND
61*7dd7cddfSDavid du Colombier 
62*7dd7cddfSDavid du Colombier 	now = time(0);
63*7dd7cddfSDavid du Colombier 	dninit();
64*7dd7cddfSDavid du Colombier 	fmtinstall('R', prettyrrconv);
65*7dd7cddfSDavid du Colombier 	snprint(buf, sizeof(buf), "%s/ipifc", mntpt);
66*7dd7cddfSDavid du Colombier 	if(myipaddr(ipaddr, buf) < 0)
67*7dd7cddfSDavid du Colombier 		sysfatal("can't read my ip address");
68*7dd7cddfSDavid du Colombier 	opendatabase();
69*7dd7cddfSDavid du Colombier 
70*7dd7cddfSDavid du Colombier 	if(resolver)
71*7dd7cddfSDavid du Colombier 		squirrelserveraddrs();
72*7dd7cddfSDavid du Colombier 
73*7dd7cddfSDavid du Colombier 	debug = 1;
74*7dd7cddfSDavid du Colombier 
75*7dd7cddfSDavid du Colombier 	if(argc > 0){
76*7dd7cddfSDavid du Colombier 		docmd(argc, argv);
77*7dd7cddfSDavid du Colombier 		exits(0);
78*7dd7cddfSDavid du Colombier 	}
79*7dd7cddfSDavid du Colombier 
80*7dd7cddfSDavid du Colombier 	Binit(&in, 0, OREAD);
81*7dd7cddfSDavid du Colombier 	for(print("> "); p = Brdline(&in, '\n'); print("> ")){
82*7dd7cddfSDavid du Colombier 		p[Blinelen(&in)-1] = 0;
83*7dd7cddfSDavid du Colombier 		n = tokenize(p, f, 3);
84*7dd7cddfSDavid du Colombier 		if(n<1)
85*7dd7cddfSDavid du Colombier 			continue;
86*7dd7cddfSDavid du Colombier 
87*7dd7cddfSDavid du Colombier 		/* flush the cache */
88*7dd7cddfSDavid du Colombier 		dnpurge();
89*7dd7cddfSDavid du Colombier 
90*7dd7cddfSDavid du Colombier 		docmd(n, f);
91*7dd7cddfSDavid du Colombier 
92*7dd7cddfSDavid du Colombier 	}
93*7dd7cddfSDavid du Colombier 	exits(0);
94*7dd7cddfSDavid du Colombier }
95*7dd7cddfSDavid du Colombier 
96*7dd7cddfSDavid du Colombier static char*
97*7dd7cddfSDavid du Colombier longtime(long t)
98*7dd7cddfSDavid du Colombier {
99*7dd7cddfSDavid du Colombier 	int d, h, m, n;
100*7dd7cddfSDavid du Colombier 	static char x[128];
101*7dd7cddfSDavid du Colombier 
102*7dd7cddfSDavid du Colombier 	for(d = 0; t >= 24*60*60; t -= 24*60*60)
103*7dd7cddfSDavid du Colombier 		d++;
104*7dd7cddfSDavid du Colombier 	for(h = 0; t >= 60*60; t -= 60*60)
105*7dd7cddfSDavid du Colombier 		h++;
106*7dd7cddfSDavid du Colombier 	for(m = 0; t >= 60; t -= 60)
107*7dd7cddfSDavid du Colombier 		m++;
108*7dd7cddfSDavid du Colombier 	n = 0;
109*7dd7cddfSDavid du Colombier 	if(d)
110*7dd7cddfSDavid du Colombier 		n += sprint(x, "%d day ", d);
111*7dd7cddfSDavid du Colombier 	if(h)
112*7dd7cddfSDavid du Colombier 		n += sprint(x+n, "%d hr ", h);
113*7dd7cddfSDavid du Colombier 	if(m)
114*7dd7cddfSDavid du Colombier 		n += sprint(x+n, "%d min ", m);
115*7dd7cddfSDavid du Colombier 	if(t || n == 0)
116*7dd7cddfSDavid du Colombier 		sprint(x+n, "%ld sec", t);
117*7dd7cddfSDavid du Colombier 	return x;
118*7dd7cddfSDavid du Colombier }
119*7dd7cddfSDavid du Colombier 
120*7dd7cddfSDavid du Colombier int
121*7dd7cddfSDavid du Colombier prettyrrconv(va_list *arg, Fconv *f)
122*7dd7cddfSDavid du Colombier {
123*7dd7cddfSDavid du Colombier 	RR *rp;
124*7dd7cddfSDavid du Colombier 	char buf[3*Domlen];
125*7dd7cddfSDavid du Colombier 	char *p, *e;
126*7dd7cddfSDavid du Colombier 
127*7dd7cddfSDavid du Colombier 	rp = va_arg(*arg, RR*);
128*7dd7cddfSDavid du Colombier 	if(rp == 0){
129*7dd7cddfSDavid du Colombier 		strcpy(buf, "<null>");
130*7dd7cddfSDavid du Colombier 		goto out;
131*7dd7cddfSDavid du Colombier 	}
132*7dd7cddfSDavid du Colombier 
133*7dd7cddfSDavid du Colombier 	p = buf;
134*7dd7cddfSDavid du Colombier 	e = buf + sizeof(buf);
135*7dd7cddfSDavid du Colombier 	p = seprint(p, e, "%-32.32s %-15.15s %-5.5s", rp->owner->name,
136*7dd7cddfSDavid du Colombier 		longtime(rp->db ? rp->ttl : (rp->ttl-now)),
137*7dd7cddfSDavid du Colombier 		rrname(rp->type, buf));
138*7dd7cddfSDavid du Colombier 
139*7dd7cddfSDavid du Colombier 	if(rp->negative){
140*7dd7cddfSDavid du Colombier 		seprint(p, e, "negative rcode %d\n", rp->negrcode);
141*7dd7cddfSDavid du Colombier 		goto out;
142*7dd7cddfSDavid du Colombier 	}
143*7dd7cddfSDavid du Colombier 
144*7dd7cddfSDavid du Colombier 	switch(rp->type){
145*7dd7cddfSDavid du Colombier 	case Thinfo:
146*7dd7cddfSDavid du Colombier 		seprint(p, e, "\t%s %s", rp->cpu->name, rp->os->name);
147*7dd7cddfSDavid du Colombier 		break;
148*7dd7cddfSDavid du Colombier 	case Tcname:
149*7dd7cddfSDavid du Colombier 	case Tmb:
150*7dd7cddfSDavid du Colombier 	case Tmd:
151*7dd7cddfSDavid du Colombier 	case Tmf:
152*7dd7cddfSDavid du Colombier 	case Tns:
153*7dd7cddfSDavid du Colombier 		seprint(p, e, "\t%s", rp->host->name);
154*7dd7cddfSDavid du Colombier 		break;
155*7dd7cddfSDavid du Colombier 	case Tmg:
156*7dd7cddfSDavid du Colombier 	case Tmr:
157*7dd7cddfSDavid du Colombier 		seprint(p, e, "\t%s", rp->mb->name);
158*7dd7cddfSDavid du Colombier 		break;
159*7dd7cddfSDavid du Colombier 	case Tminfo:
160*7dd7cddfSDavid du Colombier 		seprint(p, e, "\t%s %s", rp->mb->name, rp->rmb->name);
161*7dd7cddfSDavid du Colombier 		break;
162*7dd7cddfSDavid du Colombier 	case Tmx:
163*7dd7cddfSDavid du Colombier 		seprint(p, e, "\t%lud %s", rp->pref, rp->host->name);
164*7dd7cddfSDavid du Colombier 		break;
165*7dd7cddfSDavid du Colombier 	case Ta:
166*7dd7cddfSDavid du Colombier 		seprint(p, e, "\t%s", rp->ip->name);
167*7dd7cddfSDavid du Colombier 		break;
168*7dd7cddfSDavid du Colombier 	case Tptr:
169*7dd7cddfSDavid du Colombier 		seprint(p, e, "\t%s", rp->ptr->name);
170*7dd7cddfSDavid du Colombier 		break;
171*7dd7cddfSDavid du Colombier 	case Tsoa:
172*7dd7cddfSDavid du Colombier 		seprint(p, e, "\t%s %s %lud %lud %lud %lud %lud", rp->host->name,
173*7dd7cddfSDavid du Colombier 			rp->rmb->name, rp->soa->serial, rp->soa->refresh, rp->soa->retry,
174*7dd7cddfSDavid du Colombier 			rp->soa->expire, rp->soa->minttl);
175*7dd7cddfSDavid du Colombier 		break;
176*7dd7cddfSDavid du Colombier 	case Ttxt:
177*7dd7cddfSDavid du Colombier 		seprint(p, e, "\t%s", rp->txt->name);
178*7dd7cddfSDavid du Colombier 		break;
179*7dd7cddfSDavid du Colombier 	case Trp:
180*7dd7cddfSDavid du Colombier 		seprint(p, e, "\t%s %s", rp->rmb->name, rp->txt->name);
181*7dd7cddfSDavid du Colombier 		break;
182*7dd7cddfSDavid du Colombier 	case Tkey:
183*7dd7cddfSDavid du Colombier 		seprint(p, e, "\t%d %d %d", rp->key->flags, rp->key->proto,
184*7dd7cddfSDavid du Colombier 			rp->key->alg);
185*7dd7cddfSDavid du Colombier 		break;
186*7dd7cddfSDavid du Colombier 	case Tsig:
187*7dd7cddfSDavid du Colombier 		seprint(p, e, "\t%d %d %d %lud %lud %lud %d %s",
188*7dd7cddfSDavid du Colombier 			rp->sig->type, rp->sig->alg, rp->sig->labels, rp->sig->ttl,
189*7dd7cddfSDavid du Colombier 			rp->sig->exp, rp->sig->incep, rp->sig->tag, rp->sig->signer->name);
190*7dd7cddfSDavid du Colombier 		break;
191*7dd7cddfSDavid du Colombier 	case Tcert:
192*7dd7cddfSDavid du Colombier 		seprint(p, e, "\t%d %d %d",
193*7dd7cddfSDavid du Colombier 			rp->sig->type, rp->sig->tag, rp->sig->alg);
194*7dd7cddfSDavid du Colombier 		break;
195*7dd7cddfSDavid du Colombier 	default:
196*7dd7cddfSDavid du Colombier 		break;
197*7dd7cddfSDavid du Colombier 	}
198*7dd7cddfSDavid du Colombier out:
199*7dd7cddfSDavid du Colombier 	strconv(buf, f);
200*7dd7cddfSDavid du Colombier 	return sizeof(RR*);
201*7dd7cddfSDavid du Colombier }
202*7dd7cddfSDavid du Colombier 
203*7dd7cddfSDavid du Colombier void
204*7dd7cddfSDavid du Colombier logsection(char *flag, RR *rp)
205*7dd7cddfSDavid du Colombier {
206*7dd7cddfSDavid du Colombier 	if(rp == nil)
207*7dd7cddfSDavid du Colombier 		return;
208*7dd7cddfSDavid du Colombier 	print("\t%s%R\n", flag, rp);
209*7dd7cddfSDavid du Colombier 	for(rp = rp->next; rp != nil; rp = rp->next)
210*7dd7cddfSDavid du Colombier 		print("\t      %R\n", rp);
211*7dd7cddfSDavid du Colombier }
212*7dd7cddfSDavid du Colombier 
213*7dd7cddfSDavid du Colombier void
214*7dd7cddfSDavid du Colombier logreply(int id, uchar *addr, DNSmsg *mp)
215*7dd7cddfSDavid du Colombier {
216*7dd7cddfSDavid du Colombier 	RR *rp;
217*7dd7cddfSDavid du Colombier 	char buf[12];
218*7dd7cddfSDavid du Colombier 	char resp[32];
219*7dd7cddfSDavid du Colombier 
220*7dd7cddfSDavid du Colombier 	switch(mp->flags & Rmask){
221*7dd7cddfSDavid du Colombier 	case Rok:
222*7dd7cddfSDavid du Colombier 		strcpy(resp, "OK");
223*7dd7cddfSDavid du Colombier 		break;
224*7dd7cddfSDavid du Colombier 	case Rformat:
225*7dd7cddfSDavid du Colombier 		strcpy(resp, "Format error");
226*7dd7cddfSDavid du Colombier 		break;
227*7dd7cddfSDavid du Colombier 	case Rserver:
228*7dd7cddfSDavid du Colombier 		strcpy(resp, "Server failed");
229*7dd7cddfSDavid du Colombier 		break;
230*7dd7cddfSDavid du Colombier 	case Rname:
231*7dd7cddfSDavid du Colombier 		strcpy(resp, "Nonexistent");
232*7dd7cddfSDavid du Colombier 		break;
233*7dd7cddfSDavid du Colombier 	case Runimplimented:
234*7dd7cddfSDavid du Colombier 		strcpy(resp, "Unimplemented");
235*7dd7cddfSDavid du Colombier 		break;
236*7dd7cddfSDavid du Colombier 	case Rrefused:
237*7dd7cddfSDavid du Colombier 		strcpy(resp, "Refused");
238*7dd7cddfSDavid du Colombier 		break;
239*7dd7cddfSDavid du Colombier 	default:
240*7dd7cddfSDavid du Colombier 		sprint(resp, "%d", mp->flags & Rmask);
241*7dd7cddfSDavid du Colombier 		break;
242*7dd7cddfSDavid du Colombier 	}
243*7dd7cddfSDavid du Colombier 
244*7dd7cddfSDavid du Colombier 	print("%d: rcvd %s from %I (%s%s%s%s%s)\n", id, resp, addr,
245*7dd7cddfSDavid du Colombier 		mp->flags & Fauth ? "authoritative" : "",
246*7dd7cddfSDavid du Colombier 		mp->flags & Ftrunc ? " truncated" : "",
247*7dd7cddfSDavid du Colombier 		mp->flags & Frecurse ? " recurse" : "",
248*7dd7cddfSDavid du Colombier 		mp->flags & Fcanrec ? " can_recurse" : "",
249*7dd7cddfSDavid du Colombier 		mp->flags & (Fauth|Rname) == (Fauth|Rname) ?
250*7dd7cddfSDavid du Colombier 		" nx" : "");
251*7dd7cddfSDavid du Colombier 	for(rp = mp->qd; rp != nil; rp = rp->next)
252*7dd7cddfSDavid du Colombier 		print("\tQ:    %s %s\n", rp->owner->name, rrname(rp->type, buf));
253*7dd7cddfSDavid du Colombier 	logsection("Ans:  ", mp->an);
254*7dd7cddfSDavid du Colombier 	logsection("Auth: ", mp->ns);
255*7dd7cddfSDavid du Colombier 	logsection("Hint: ", mp->ar);
256*7dd7cddfSDavid du Colombier }
257*7dd7cddfSDavid du Colombier 
258*7dd7cddfSDavid du Colombier void
259*7dd7cddfSDavid du Colombier logsend(int id, int subid, uchar *addr, char *sname, char *rname, int type)
260*7dd7cddfSDavid du Colombier {
261*7dd7cddfSDavid du Colombier 	char buf[12];
262*7dd7cddfSDavid du Colombier 
263*7dd7cddfSDavid du Colombier 	print("%d.%d: sending to %I/%s %s %s\n", id, subid,
264*7dd7cddfSDavid du Colombier 		addr, sname, rname, rrname(type, buf));
265*7dd7cddfSDavid du Colombier }
266*7dd7cddfSDavid du Colombier 
267*7dd7cddfSDavid du Colombier RR*
268*7dd7cddfSDavid du Colombier getdnsservers(int class)
269*7dd7cddfSDavid du Colombier {
270*7dd7cddfSDavid du Colombier 	RR *rr;
271*7dd7cddfSDavid du Colombier 
272*7dd7cddfSDavid du Colombier 	if(servername == nil)
273*7dd7cddfSDavid du Colombier 		return dnsservers(class);
274*7dd7cddfSDavid du Colombier 
275*7dd7cddfSDavid du Colombier 	rr = rralloc(Tns);
276*7dd7cddfSDavid du Colombier 	rr->owner = dnlookup("local#dns#servers", class, 1);
277*7dd7cddfSDavid du Colombier 	rr->host = dnlookup(servername, class, 1);
278*7dd7cddfSDavid du Colombier 
279*7dd7cddfSDavid du Colombier 	return rr;
280*7dd7cddfSDavid du Colombier }
281*7dd7cddfSDavid du Colombier 
282*7dd7cddfSDavid du Colombier void
283*7dd7cddfSDavid du Colombier squirrelserveraddrs(void)
284*7dd7cddfSDavid du Colombier {
285*7dd7cddfSDavid du Colombier 	RR *rr, *rp, **l;
286*7dd7cddfSDavid du Colombier 	Request req;
287*7dd7cddfSDavid du Colombier 
288*7dd7cddfSDavid du Colombier 	/* look up the resolver address first */
289*7dd7cddfSDavid du Colombier 	resolver = 0;
290*7dd7cddfSDavid du Colombier 	debug = 0;
291*7dd7cddfSDavid du Colombier 	if(serveraddrs)
292*7dd7cddfSDavid du Colombier 		rrfreelist(serveraddrs);
293*7dd7cddfSDavid du Colombier 	serveraddrs = nil;
294*7dd7cddfSDavid du Colombier 	rr = getdnsservers(Cin);
295*7dd7cddfSDavid du Colombier 	l = &serveraddrs;
296*7dd7cddfSDavid du Colombier 	for(rp = rr; rp != nil; rp = rp->next){
297*7dd7cddfSDavid du Colombier 		if(strcmp(ipattr(rp->host->name), "ip") == 0){
298*7dd7cddfSDavid du Colombier 			*l = rralloc(Ta);
299*7dd7cddfSDavid du Colombier 			(*l)->owner = rp->host;
300*7dd7cddfSDavid du Colombier 			(*l)->ip = rp->host;
301*7dd7cddfSDavid du Colombier 			l = &(*l)->next;
302*7dd7cddfSDavid du Colombier 			continue;
303*7dd7cddfSDavid du Colombier 		}
304*7dd7cddfSDavid du Colombier 		req.isslave = 1;
305*7dd7cddfSDavid du Colombier 		req.aborttime = now + 60;	/* don't spend more than 60 seconds */
306*7dd7cddfSDavid du Colombier 		*l = dnresolve(rp->host->name, Cin, Ta, &req, 0, 0, Recurse, 1, 0);
307*7dd7cddfSDavid du Colombier 		while(*l != nil)
308*7dd7cddfSDavid du Colombier 			l = &(*l)->next;
309*7dd7cddfSDavid du Colombier 	}
310*7dd7cddfSDavid du Colombier 	resolver = 1;
311*7dd7cddfSDavid du Colombier 	debug = 1;
312*7dd7cddfSDavid du Colombier }
313*7dd7cddfSDavid du Colombier 
314*7dd7cddfSDavid du Colombier void
315*7dd7cddfSDavid du Colombier preloadserveraddrs(void)
316*7dd7cddfSDavid du Colombier {
317*7dd7cddfSDavid du Colombier 	RR *rp, **l, *first;
318*7dd7cddfSDavid du Colombier 
319*7dd7cddfSDavid du Colombier 	l = &first;
320*7dd7cddfSDavid du Colombier 	for(rp = serveraddrs; rp != nil; rp = rp->next){
321*7dd7cddfSDavid du Colombier 		rrcopy(rp, l);
322*7dd7cddfSDavid du Colombier 		rrattach(first, 1);
323*7dd7cddfSDavid du Colombier 	}
324*7dd7cddfSDavid du Colombier }
325*7dd7cddfSDavid du Colombier 
326*7dd7cddfSDavid du Colombier int
327*7dd7cddfSDavid du Colombier setserver(char *server)
328*7dd7cddfSDavid du Colombier {
329*7dd7cddfSDavid du Colombier 	if(servername != nil){
330*7dd7cddfSDavid du Colombier 		free(servername);
331*7dd7cddfSDavid du Colombier 		servername = nil;
332*7dd7cddfSDavid du Colombier 		resolver = 0;
333*7dd7cddfSDavid du Colombier 	}
334*7dd7cddfSDavid du Colombier 	if(server == nil || *server == 0)
335*7dd7cddfSDavid du Colombier 		return 0;
336*7dd7cddfSDavid du Colombier 	servername = strdup(server);
337*7dd7cddfSDavid du Colombier 	squirrelserveraddrs();
338*7dd7cddfSDavid du Colombier 	if(serveraddrs == nil){
339*7dd7cddfSDavid du Colombier 		print("can't resolve %s\n", servername);
340*7dd7cddfSDavid du Colombier 		resolver = 0;
341*7dd7cddfSDavid du Colombier 	} else {
342*7dd7cddfSDavid du Colombier 		resolver = 1;
343*7dd7cddfSDavid du Colombier 	}
344*7dd7cddfSDavid du Colombier 	return resolver ? 0 : -1;
345*7dd7cddfSDavid du Colombier }
346*7dd7cddfSDavid du Colombier 
347*7dd7cddfSDavid du Colombier void
348*7dd7cddfSDavid du Colombier doquery(char *name, char *tstr)
349*7dd7cddfSDavid du Colombier {
350*7dd7cddfSDavid du Colombier 	Request req;
351*7dd7cddfSDavid du Colombier 	RR *rr, *rp;
352*7dd7cddfSDavid du Colombier 	int len, type;
353*7dd7cddfSDavid du Colombier 	char *p, *np;
354*7dd7cddfSDavid du Colombier 	char buf[1024];
355*7dd7cddfSDavid du Colombier 
356*7dd7cddfSDavid du Colombier 	if(resolver)
357*7dd7cddfSDavid du Colombier 		preloadserveraddrs();
358*7dd7cddfSDavid du Colombier 
359*7dd7cddfSDavid du Colombier 	/* default to an "ip" request if alpha, "ptr" if numeric */
360*7dd7cddfSDavid du Colombier 	if(tstr == nil || *tstr == 0) {
361*7dd7cddfSDavid du Colombier 		if(strcmp(ipattr(name), "ip") == 0)
362*7dd7cddfSDavid du Colombier 			tstr = "ptr";
363*7dd7cddfSDavid du Colombier 		else
364*7dd7cddfSDavid du Colombier 			tstr = "ip";
365*7dd7cddfSDavid du Colombier 	}
366*7dd7cddfSDavid du Colombier 
367*7dd7cddfSDavid du Colombier 	/* if name end in '.', remove it */
368*7dd7cddfSDavid du Colombier 	len = strlen(name);
369*7dd7cddfSDavid du Colombier 	if(len > 0 && name[len-1] == '.')
370*7dd7cddfSDavid du Colombier 		name[len-1] = 0;
371*7dd7cddfSDavid du Colombier 
372*7dd7cddfSDavid du Colombier 	/* inverse queries may need to be permuted */
373*7dd7cddfSDavid du Colombier 	if(strcmp("ptr", tstr) == 0
374*7dd7cddfSDavid du Colombier 	&& strstr(name, "IN-ADDR") == 0
375*7dd7cddfSDavid du Colombier 	&& strstr(name, "in-addr") == 0){
376*7dd7cddfSDavid du Colombier 		for(p = name; *p; p++)
377*7dd7cddfSDavid du Colombier 			;
378*7dd7cddfSDavid du Colombier 		*p = '.';
379*7dd7cddfSDavid du Colombier 		np = buf;
380*7dd7cddfSDavid du Colombier 		len = 0;
381*7dd7cddfSDavid du Colombier 		while(p >= name){
382*7dd7cddfSDavid du Colombier 			len++;
383*7dd7cddfSDavid du Colombier 			p--;
384*7dd7cddfSDavid du Colombier 			if(*p == '.'){
385*7dd7cddfSDavid du Colombier 				memmove(np, p+1, len);
386*7dd7cddfSDavid du Colombier 				np += len;
387*7dd7cddfSDavid du Colombier 				len = 0;
388*7dd7cddfSDavid du Colombier 			}
389*7dd7cddfSDavid du Colombier 		}
390*7dd7cddfSDavid du Colombier 		memmove(np, p+1, len);
391*7dd7cddfSDavid du Colombier 		np += len;
392*7dd7cddfSDavid du Colombier 		strcpy(np, "in-addr.arpa");
393*7dd7cddfSDavid du Colombier 		strcpy(name, buf);
394*7dd7cddfSDavid du Colombier 	}
395*7dd7cddfSDavid du Colombier 
396*7dd7cddfSDavid du Colombier 	/* look it up */
397*7dd7cddfSDavid du Colombier 	type = rrtype(tstr);
398*7dd7cddfSDavid du Colombier 	if(type < 0){
399*7dd7cddfSDavid du Colombier 		print("!unknown type %s\n", tstr);
400*7dd7cddfSDavid du Colombier 		return;
401*7dd7cddfSDavid du Colombier 	}
402*7dd7cddfSDavid du Colombier 
403*7dd7cddfSDavid du Colombier 	getactivity(&req);
404*7dd7cddfSDavid du Colombier 	req.isslave = 1;
405*7dd7cddfSDavid du Colombier 	req.aborttime = now + 60;	/* don't spend more than 60 seconds */
406*7dd7cddfSDavid du Colombier 	rr = dnresolve(name, Cin, type, &req, 0, 0, Recurse, 1, 0);
407*7dd7cddfSDavid du Colombier 	if(rr){
408*7dd7cddfSDavid du Colombier 		print("----------------------------\n");
409*7dd7cddfSDavid du Colombier 		for(rp = rr; rp; rp = rp->next)
410*7dd7cddfSDavid du Colombier 			print("answer %R\n", rp);
411*7dd7cddfSDavid du Colombier 		print("----------------------------\n");
412*7dd7cddfSDavid du Colombier 	}
413*7dd7cddfSDavid du Colombier 	rrfreelist(rr);
414*7dd7cddfSDavid du Colombier 
415*7dd7cddfSDavid du Colombier 	putactivity();
416*7dd7cddfSDavid du Colombier }
417*7dd7cddfSDavid du Colombier 
418*7dd7cddfSDavid du Colombier void
419*7dd7cddfSDavid du Colombier docmd(int n, char **f)
420*7dd7cddfSDavid du Colombier {
421*7dd7cddfSDavid du Colombier 	int tmpsrv;
422*7dd7cddfSDavid du Colombier 	char *name, *type;
423*7dd7cddfSDavid du Colombier 
424*7dd7cddfSDavid du Colombier 	name = nil;
425*7dd7cddfSDavid du Colombier 	type = nil;
426*7dd7cddfSDavid du Colombier 	tmpsrv = 0;
427*7dd7cddfSDavid du Colombier 
428*7dd7cddfSDavid du Colombier 	if(*f[0] == '@') {
429*7dd7cddfSDavid du Colombier 		if(setserver(f[0]+1) < 0)
430*7dd7cddfSDavid du Colombier 			return;
431*7dd7cddfSDavid du Colombier 
432*7dd7cddfSDavid du Colombier 		switch(n){
433*7dd7cddfSDavid du Colombier 		case 3:
434*7dd7cddfSDavid du Colombier 			type = f[2];
435*7dd7cddfSDavid du Colombier 			/* fall through */
436*7dd7cddfSDavid du Colombier 		case 2:
437*7dd7cddfSDavid du Colombier 			name = f[1];
438*7dd7cddfSDavid du Colombier 			tmpsrv = 1;
439*7dd7cddfSDavid du Colombier 			break;
440*7dd7cddfSDavid du Colombier 		}
441*7dd7cddfSDavid du Colombier 	} else {
442*7dd7cddfSDavid du Colombier 		switch(n){
443*7dd7cddfSDavid du Colombier 		case 2:
444*7dd7cddfSDavid du Colombier 			type = f[1];
445*7dd7cddfSDavid du Colombier 			/* fall through */
446*7dd7cddfSDavid du Colombier 		case 1:
447*7dd7cddfSDavid du Colombier 			name = f[0];
448*7dd7cddfSDavid du Colombier 			break;
449*7dd7cddfSDavid du Colombier 		}
450*7dd7cddfSDavid du Colombier 	}
451*7dd7cddfSDavid du Colombier 
452*7dd7cddfSDavid du Colombier 	if(name == nil)
453*7dd7cddfSDavid du Colombier 		return;
454*7dd7cddfSDavid du Colombier 
455*7dd7cddfSDavid du Colombier 	doquery(name, type);
456*7dd7cddfSDavid du Colombier 
457*7dd7cddfSDavid du Colombier 	if(tmpsrv)
458*7dd7cddfSDavid du Colombier 		setserver("");
459*7dd7cddfSDavid du Colombier }
460