xref: /plan9/sys/src/cmd/ndb/dnsdebug.c (revision b4b9fc2f779153b9820efab8812e6c2c09d0221c)
17dd7cddfSDavid du Colombier #include <u.h>
27dd7cddfSDavid du Colombier #include <libc.h>
37dd7cddfSDavid du Colombier #include <bio.h>
47dd7cddfSDavid du Colombier #include <ctype.h>
57dd7cddfSDavid du Colombier #include <ip.h>
67dd7cddfSDavid du Colombier #include <ndb.h>
77dd7cddfSDavid du Colombier #include "dns.h"
87dd7cddfSDavid du Colombier 
97dd7cddfSDavid du Colombier enum
107dd7cddfSDavid du Colombier {
119a747e4fSDavid du Colombier 	Maxrequest=		128,
127dd7cddfSDavid du Colombier 	Ncache=			8,
137dd7cddfSDavid du Colombier 	Maxpath=		128,
147dd7cddfSDavid du Colombier 	Maxreply=		512,
157dd7cddfSDavid du Colombier 	Maxrrr=			16,
167dd7cddfSDavid du Colombier };
177dd7cddfSDavid du Colombier 
187dd7cddfSDavid du Colombier static char *servername;
197dd7cddfSDavid du Colombier static RR *serverrr;
207dd7cddfSDavid du Colombier static RR *serveraddrs;
217dd7cddfSDavid du Colombier 
227dd7cddfSDavid du Colombier int	debug;
237dd7cddfSDavid du Colombier int	cachedb;
247dd7cddfSDavid du Colombier ulong	now;
257dd7cddfSDavid du Colombier int	testing;
2667031067SDavid du Colombier int traceactivity;
277dd7cddfSDavid du Colombier char	*trace;
287dd7cddfSDavid du Colombier int	needrefresh;
297dd7cddfSDavid du Colombier int	resolver;
307dd7cddfSDavid du Colombier uchar	ipaddr[IPaddrlen];	/* my ip address */
317dd7cddfSDavid du Colombier int	maxage;
327dd7cddfSDavid du Colombier char	*logfile = "dns";
337dd7cddfSDavid du Colombier char	*dbfile;
347dd7cddfSDavid du Colombier char	mntpt[Maxpath];
35dc5a79c1SDavid du Colombier char	*zonerefreshprogram;
367dd7cddfSDavid du Colombier 
379a747e4fSDavid du Colombier int prettyrrfmt(Fmt*);
387dd7cddfSDavid du Colombier void preloadserveraddrs(void);
397dd7cddfSDavid du Colombier void squirrelserveraddrs(void);
407dd7cddfSDavid du Colombier int setserver(char*);
417dd7cddfSDavid du Colombier void doquery(char*, char*);
427dd7cddfSDavid du Colombier void docmd(int, char**);
437dd7cddfSDavid du Colombier 
447dd7cddfSDavid du Colombier void
457dd7cddfSDavid du Colombier main(int argc, char *argv[])
467dd7cddfSDavid du Colombier {
477dd7cddfSDavid du Colombier 	int n;
487dd7cddfSDavid du Colombier 	Biobuf in;
4980ee5cbfSDavid du Colombier 	char *p;
507dd7cddfSDavid du Colombier 	char *f[4];
517dd7cddfSDavid du Colombier 
527dd7cddfSDavid du Colombier 	strcpy(mntpt, "/net");
537dd7cddfSDavid du Colombier 
547dd7cddfSDavid du Colombier 	ARGBEGIN{
557dd7cddfSDavid du Colombier 	case 'r':
567dd7cddfSDavid du Colombier 		resolver = 1;
577dd7cddfSDavid du Colombier 		break;
587dd7cddfSDavid du Colombier 	case 'x':
597dd7cddfSDavid du Colombier 		dbfile = "/lib/ndb/external";
607dd7cddfSDavid du Colombier 		strcpy(mntpt, "/net.alt");
617dd7cddfSDavid du Colombier 		break;
6234f77ae3SDavid du Colombier 	case 'f':
6334f77ae3SDavid du Colombier 		dbfile = ARGF();
6434f77ae3SDavid du Colombier 		break;
657dd7cddfSDavid du Colombier 	}ARGEND
667dd7cddfSDavid du Colombier 
677dd7cddfSDavid du Colombier 	now = time(0);
687dd7cddfSDavid du Colombier 	dninit();
699a747e4fSDavid du Colombier 	fmtinstall('R', prettyrrfmt);
709a747e4fSDavid du Colombier 	if(myipaddr(ipaddr, mntpt) < 0)
717dd7cddfSDavid du Colombier 		sysfatal("can't read my ip address");
727dd7cddfSDavid du Colombier 	opendatabase();
737dd7cddfSDavid du Colombier 
747dd7cddfSDavid du Colombier 	if(resolver)
757dd7cddfSDavid du Colombier 		squirrelserveraddrs();
767dd7cddfSDavid du Colombier 
777dd7cddfSDavid du Colombier 	debug = 1;
787dd7cddfSDavid du Colombier 
797dd7cddfSDavid du Colombier 	if(argc > 0){
807dd7cddfSDavid du Colombier 		docmd(argc, argv);
817dd7cddfSDavid du Colombier 		exits(0);
827dd7cddfSDavid du Colombier 	}
837dd7cddfSDavid du Colombier 
847dd7cddfSDavid du Colombier 	Binit(&in, 0, OREAD);
857dd7cddfSDavid du Colombier 	for(print("> "); p = Brdline(&in, '\n'); print("> ")){
867dd7cddfSDavid du Colombier 		p[Blinelen(&in)-1] = 0;
877dd7cddfSDavid du Colombier 		n = tokenize(p, f, 3);
887dd7cddfSDavid du Colombier 		if(n<1)
897dd7cddfSDavid du Colombier 			continue;
907dd7cddfSDavid du Colombier 
917dd7cddfSDavid du Colombier 		/* flush the cache */
927dd7cddfSDavid du Colombier 		dnpurge();
937dd7cddfSDavid du Colombier 
947dd7cddfSDavid du Colombier 		docmd(n, f);
957dd7cddfSDavid du Colombier 
967dd7cddfSDavid du Colombier 	}
977dd7cddfSDavid du Colombier 	exits(0);
987dd7cddfSDavid du Colombier }
997dd7cddfSDavid du Colombier 
1007dd7cddfSDavid du Colombier static char*
1017dd7cddfSDavid du Colombier longtime(long t)
1027dd7cddfSDavid du Colombier {
1037dd7cddfSDavid du Colombier 	int d, h, m, n;
1047dd7cddfSDavid du Colombier 	static char x[128];
1057dd7cddfSDavid du Colombier 
1067dd7cddfSDavid du Colombier 	for(d = 0; t >= 24*60*60; t -= 24*60*60)
1077dd7cddfSDavid du Colombier 		d++;
1087dd7cddfSDavid du Colombier 	for(h = 0; t >= 60*60; t -= 60*60)
1097dd7cddfSDavid du Colombier 		h++;
1107dd7cddfSDavid du Colombier 	for(m = 0; t >= 60; t -= 60)
1117dd7cddfSDavid du Colombier 		m++;
1127dd7cddfSDavid du Colombier 	n = 0;
1137dd7cddfSDavid du Colombier 	if(d)
1147dd7cddfSDavid du Colombier 		n += sprint(x, "%d day ", d);
1157dd7cddfSDavid du Colombier 	if(h)
1167dd7cddfSDavid du Colombier 		n += sprint(x+n, "%d hr ", h);
1177dd7cddfSDavid du Colombier 	if(m)
1187dd7cddfSDavid du Colombier 		n += sprint(x+n, "%d min ", m);
1197dd7cddfSDavid du Colombier 	if(t || n == 0)
1207dd7cddfSDavid du Colombier 		sprint(x+n, "%ld sec", t);
1217dd7cddfSDavid du Colombier 	return x;
1227dd7cddfSDavid du Colombier }
1237dd7cddfSDavid du Colombier 
1247dd7cddfSDavid du Colombier int
1259a747e4fSDavid du Colombier prettyrrfmt(Fmt *f)
1267dd7cddfSDavid du Colombier {
1277dd7cddfSDavid du Colombier 	RR *rp;
1287dd7cddfSDavid du Colombier 	char buf[3*Domlen];
1297dd7cddfSDavid du Colombier 	char *p, *e;
1308754a1dfSDavid du Colombier 	Txt *t;
1317dd7cddfSDavid du Colombier 
1329a747e4fSDavid du Colombier 	rp = va_arg(f->args, RR*);
1337dd7cddfSDavid du Colombier 	if(rp == 0){
1347dd7cddfSDavid du Colombier 		strcpy(buf, "<null>");
1357dd7cddfSDavid du Colombier 		goto out;
1367dd7cddfSDavid du Colombier 	}
1377dd7cddfSDavid du Colombier 
1387dd7cddfSDavid du Colombier 	p = buf;
1397dd7cddfSDavid du Colombier 	e = buf + sizeof(buf);
1407dd7cddfSDavid du Colombier 	p = seprint(p, e, "%-32.32s %-15.15s %-5.5s", rp->owner->name,
1417dd7cddfSDavid du Colombier 		longtime(rp->db ? rp->ttl : (rp->ttl-now)),
1429a747e4fSDavid du Colombier 		rrname(rp->type, buf, sizeof buf));
1437dd7cddfSDavid du Colombier 
1447dd7cddfSDavid du Colombier 	if(rp->negative){
1457dd7cddfSDavid du Colombier 		seprint(p, e, "negative rcode %d\n", rp->negrcode);
1467dd7cddfSDavid du Colombier 		goto out;
1477dd7cddfSDavid du Colombier 	}
1487dd7cddfSDavid du Colombier 
1497dd7cddfSDavid du Colombier 	switch(rp->type){
1507dd7cddfSDavid du Colombier 	case Thinfo:
1517dd7cddfSDavid du Colombier 		seprint(p, e, "\t%s %s", rp->cpu->name, rp->os->name);
1527dd7cddfSDavid du Colombier 		break;
1537dd7cddfSDavid du Colombier 	case Tcname:
1547dd7cddfSDavid du Colombier 	case Tmb:
1557dd7cddfSDavid du Colombier 	case Tmd:
1567dd7cddfSDavid du Colombier 	case Tmf:
1577dd7cddfSDavid du Colombier 	case Tns:
1587dd7cddfSDavid du Colombier 		seprint(p, e, "\t%s", rp->host->name);
1597dd7cddfSDavid du Colombier 		break;
1607dd7cddfSDavid du Colombier 	case Tmg:
1617dd7cddfSDavid du Colombier 	case Tmr:
1627dd7cddfSDavid du Colombier 		seprint(p, e, "\t%s", rp->mb->name);
1637dd7cddfSDavid du Colombier 		break;
1647dd7cddfSDavid du Colombier 	case Tminfo:
1657dd7cddfSDavid du Colombier 		seprint(p, e, "\t%s %s", rp->mb->name, rp->rmb->name);
1667dd7cddfSDavid du Colombier 		break;
1677dd7cddfSDavid du Colombier 	case Tmx:
1687dd7cddfSDavid du Colombier 		seprint(p, e, "\t%lud %s", rp->pref, rp->host->name);
1697dd7cddfSDavid du Colombier 		break;
1707dd7cddfSDavid du Colombier 	case Ta:
1715d459b5aSDavid du Colombier 	case Taaaa:
1727dd7cddfSDavid du Colombier 		seprint(p, e, "\t%s", rp->ip->name);
1737dd7cddfSDavid du Colombier 		break;
1747dd7cddfSDavid du Colombier 	case Tptr:
1757dd7cddfSDavid du Colombier 		seprint(p, e, "\t%s", rp->ptr->name);
1767dd7cddfSDavid du Colombier 		break;
1777dd7cddfSDavid du Colombier 	case Tsoa:
1787dd7cddfSDavid du Colombier 		seprint(p, e, "\t%s %s %lud %lud %lud %lud %lud", rp->host->name,
1797dd7cddfSDavid du Colombier 			rp->rmb->name, rp->soa->serial, rp->soa->refresh, rp->soa->retry,
1807dd7cddfSDavid du Colombier 			rp->soa->expire, rp->soa->minttl);
1817dd7cddfSDavid du Colombier 		break;
1829a747e4fSDavid du Colombier 	case Tnull:
1839a747e4fSDavid du Colombier 		seprint(p, e, "\t%.*H", rp->null->dlen, rp->null->data);
1849a747e4fSDavid du Colombier 		break;
1857dd7cddfSDavid du Colombier 	case Ttxt:
1868754a1dfSDavid du Colombier 		p = seprint(p, e, "\t");
1878754a1dfSDavid du Colombier 		for(t = rp->txt; t != nil; t = t->next)
1888754a1dfSDavid du Colombier 			p = seprint(p, e, "%s", t->p);
1897dd7cddfSDavid du Colombier 		break;
1907dd7cddfSDavid du Colombier 	case Trp:
1918754a1dfSDavid du Colombier 		seprint(p, e, "\t%s %s", rp->rmb->name, rp->rp->name);
1927dd7cddfSDavid du Colombier 		break;
1937dd7cddfSDavid du Colombier 	case Tkey:
1947dd7cddfSDavid du Colombier 		seprint(p, e, "\t%d %d %d", rp->key->flags, rp->key->proto,
1957dd7cddfSDavid du Colombier 			rp->key->alg);
1967dd7cddfSDavid du Colombier 		break;
1977dd7cddfSDavid du Colombier 	case Tsig:
1987dd7cddfSDavid du Colombier 		seprint(p, e, "\t%d %d %d %lud %lud %lud %d %s",
1997dd7cddfSDavid du Colombier 			rp->sig->type, rp->sig->alg, rp->sig->labels, rp->sig->ttl,
2007dd7cddfSDavid du Colombier 			rp->sig->exp, rp->sig->incep, rp->sig->tag, rp->sig->signer->name);
2017dd7cddfSDavid du Colombier 		break;
2027dd7cddfSDavid du Colombier 	case Tcert:
2037dd7cddfSDavid du Colombier 		seprint(p, e, "\t%d %d %d",
2047dd7cddfSDavid du Colombier 			rp->sig->type, rp->sig->tag, rp->sig->alg);
2057dd7cddfSDavid du Colombier 		break;
2067dd7cddfSDavid du Colombier 	default:
2077dd7cddfSDavid du Colombier 		break;
2087dd7cddfSDavid du Colombier 	}
2097dd7cddfSDavid du Colombier out:
2109a747e4fSDavid du Colombier 	return fmtstrcpy(f, buf);
2117dd7cddfSDavid du Colombier }
2127dd7cddfSDavid du Colombier 
2137dd7cddfSDavid du Colombier void
2147dd7cddfSDavid du Colombier logsection(char *flag, RR *rp)
2157dd7cddfSDavid du Colombier {
2167dd7cddfSDavid du Colombier 	if(rp == nil)
2177dd7cddfSDavid du Colombier 		return;
2187dd7cddfSDavid du Colombier 	print("\t%s%R\n", flag, rp);
2197dd7cddfSDavid du Colombier 	for(rp = rp->next; rp != nil; rp = rp->next)
2207dd7cddfSDavid du Colombier 		print("\t      %R\n", rp);
2217dd7cddfSDavid du Colombier }
2227dd7cddfSDavid du Colombier 
2237dd7cddfSDavid du Colombier void
2247dd7cddfSDavid du Colombier logreply(int id, uchar *addr, DNSmsg *mp)
2257dd7cddfSDavid du Colombier {
2267dd7cddfSDavid du Colombier 	RR *rp;
2277dd7cddfSDavid du Colombier 	char buf[12];
2287dd7cddfSDavid du Colombier 	char resp[32];
2297dd7cddfSDavid du Colombier 
2307dd7cddfSDavid du Colombier 	switch(mp->flags & Rmask){
2317dd7cddfSDavid du Colombier 	case Rok:
2327dd7cddfSDavid du Colombier 		strcpy(resp, "OK");
2337dd7cddfSDavid du Colombier 		break;
2347dd7cddfSDavid du Colombier 	case Rformat:
2357dd7cddfSDavid du Colombier 		strcpy(resp, "Format error");
2367dd7cddfSDavid du Colombier 		break;
2377dd7cddfSDavid du Colombier 	case Rserver:
2387dd7cddfSDavid du Colombier 		strcpy(resp, "Server failed");
2397dd7cddfSDavid du Colombier 		break;
2407dd7cddfSDavid du Colombier 	case Rname:
2417dd7cddfSDavid du Colombier 		strcpy(resp, "Nonexistent");
2427dd7cddfSDavid du Colombier 		break;
2437dd7cddfSDavid du Colombier 	case Runimplimented:
2447dd7cddfSDavid du Colombier 		strcpy(resp, "Unimplemented");
2457dd7cddfSDavid du Colombier 		break;
2467dd7cddfSDavid du Colombier 	case Rrefused:
2477dd7cddfSDavid du Colombier 		strcpy(resp, "Refused");
2487dd7cddfSDavid du Colombier 		break;
2497dd7cddfSDavid du Colombier 	default:
2507dd7cddfSDavid du Colombier 		sprint(resp, "%d", mp->flags & Rmask);
2517dd7cddfSDavid du Colombier 		break;
2527dd7cddfSDavid du Colombier 	}
2537dd7cddfSDavid du Colombier 
2547dd7cddfSDavid du Colombier 	print("%d: rcvd %s from %I (%s%s%s%s%s)\n", id, resp, addr,
2557dd7cddfSDavid du Colombier 		mp->flags & Fauth ? "authoritative" : "",
2567dd7cddfSDavid du Colombier 		mp->flags & Ftrunc ? " truncated" : "",
2577dd7cddfSDavid du Colombier 		mp->flags & Frecurse ? " recurse" : "",
2587dd7cddfSDavid du Colombier 		mp->flags & Fcanrec ? " can_recurse" : "",
2597dd7cddfSDavid du Colombier 		mp->flags & (Fauth|Rname) == (Fauth|Rname) ?
2607dd7cddfSDavid du Colombier 		" nx" : "");
2617dd7cddfSDavid du Colombier 	for(rp = mp->qd; rp != nil; rp = rp->next)
2629a747e4fSDavid du Colombier 		print("\tQ:    %s %s\n", rp->owner->name, rrname(rp->type, buf, sizeof buf));
2637dd7cddfSDavid du Colombier 	logsection("Ans:  ", mp->an);
2647dd7cddfSDavid du Colombier 	logsection("Auth: ", mp->ns);
2657dd7cddfSDavid du Colombier 	logsection("Hint: ", mp->ar);
2667dd7cddfSDavid du Colombier }
2677dd7cddfSDavid du Colombier 
2687dd7cddfSDavid du Colombier void
2697dd7cddfSDavid du Colombier logsend(int id, int subid, uchar *addr, char *sname, char *rname, int type)
2707dd7cddfSDavid du Colombier {
2717dd7cddfSDavid du Colombier 	char buf[12];
2727dd7cddfSDavid du Colombier 
2737dd7cddfSDavid du Colombier 	print("%d.%d: sending to %I/%s %s %s\n", id, subid,
2749a747e4fSDavid du Colombier 		addr, sname, rname, rrname(type, buf, sizeof buf));
2757dd7cddfSDavid du Colombier }
2767dd7cddfSDavid du Colombier 
2777dd7cddfSDavid du Colombier RR*
2787dd7cddfSDavid du Colombier getdnsservers(int class)
2797dd7cddfSDavid du Colombier {
2807dd7cddfSDavid du Colombier 	RR *rr;
2817dd7cddfSDavid du Colombier 
2827dd7cddfSDavid du Colombier 	if(servername == nil)
2837dd7cddfSDavid du Colombier 		return dnsservers(class);
2847dd7cddfSDavid du Colombier 
2857dd7cddfSDavid du Colombier 	rr = rralloc(Tns);
2867dd7cddfSDavid du Colombier 	rr->owner = dnlookup("local#dns#servers", class, 1);
2877dd7cddfSDavid du Colombier 	rr->host = dnlookup(servername, class, 1);
2887dd7cddfSDavid du Colombier 
2897dd7cddfSDavid du Colombier 	return rr;
2907dd7cddfSDavid du Colombier }
2917dd7cddfSDavid du Colombier 
2927dd7cddfSDavid du Colombier void
2937dd7cddfSDavid du Colombier squirrelserveraddrs(void)
2947dd7cddfSDavid du Colombier {
2957dd7cddfSDavid du Colombier 	RR *rr, *rp, **l;
2967dd7cddfSDavid du Colombier 	Request req;
2977dd7cddfSDavid du Colombier 
2987dd7cddfSDavid du Colombier 	/* look up the resolver address first */
2997dd7cddfSDavid du Colombier 	resolver = 0;
3007dd7cddfSDavid du Colombier 	debug = 0;
3017dd7cddfSDavid du Colombier 	if(serveraddrs)
3027dd7cddfSDavid du Colombier 		rrfreelist(serveraddrs);
3037dd7cddfSDavid du Colombier 	serveraddrs = nil;
3047dd7cddfSDavid du Colombier 	rr = getdnsservers(Cin);
3057dd7cddfSDavid du Colombier 	l = &serveraddrs;
3067dd7cddfSDavid du Colombier 	for(rp = rr; rp != nil; rp = rp->next){
3077dd7cddfSDavid du Colombier 		if(strcmp(ipattr(rp->host->name), "ip") == 0){
3087dd7cddfSDavid du Colombier 			*l = rralloc(Ta);
3097dd7cddfSDavid du Colombier 			(*l)->owner = rp->host;
3107dd7cddfSDavid du Colombier 			(*l)->ip = rp->host;
3117dd7cddfSDavid du Colombier 			l = &(*l)->next;
3127dd7cddfSDavid du Colombier 			continue;
3137dd7cddfSDavid du Colombier 		}
3147dd7cddfSDavid du Colombier 		req.isslave = 1;
3157dd7cddfSDavid du Colombier 		req.aborttime = now + 60;	/* don't spend more than 60 seconds */
316271b8d73SDavid du Colombier 		*l = dnresolve(rp->host->name, Cin, Ta, &req, 0, 0, Recurse, 0, 0);
3177dd7cddfSDavid du Colombier 		while(*l != nil)
3187dd7cddfSDavid du Colombier 			l = &(*l)->next;
3197dd7cddfSDavid du Colombier 	}
3207dd7cddfSDavid du Colombier 	resolver = 1;
3217dd7cddfSDavid du Colombier 	debug = 1;
3227dd7cddfSDavid du Colombier }
3237dd7cddfSDavid du Colombier 
3247dd7cddfSDavid du Colombier void
3257dd7cddfSDavid du Colombier preloadserveraddrs(void)
3267dd7cddfSDavid du Colombier {
3277dd7cddfSDavid du Colombier 	RR *rp, **l, *first;
3287dd7cddfSDavid du Colombier 
3297dd7cddfSDavid du Colombier 	l = &first;
3307dd7cddfSDavid du Colombier 	for(rp = serveraddrs; rp != nil; rp = rp->next){
3317dd7cddfSDavid du Colombier 		rrcopy(rp, l);
3327dd7cddfSDavid du Colombier 		rrattach(first, 1);
3337dd7cddfSDavid du Colombier 	}
3347dd7cddfSDavid du Colombier }
3357dd7cddfSDavid du Colombier 
3367dd7cddfSDavid du Colombier int
3377dd7cddfSDavid du Colombier setserver(char *server)
3387dd7cddfSDavid du Colombier {
3397dd7cddfSDavid du Colombier 	if(servername != nil){
3407dd7cddfSDavid du Colombier 		free(servername);
3417dd7cddfSDavid du Colombier 		servername = nil;
3427dd7cddfSDavid du Colombier 		resolver = 0;
3437dd7cddfSDavid du Colombier 	}
3447dd7cddfSDavid du Colombier 	if(server == nil || *server == 0)
3457dd7cddfSDavid du Colombier 		return 0;
3467dd7cddfSDavid du Colombier 	servername = strdup(server);
3477dd7cddfSDavid du Colombier 	squirrelserveraddrs();
3487dd7cddfSDavid du Colombier 	if(serveraddrs == nil){
3497dd7cddfSDavid du Colombier 		print("can't resolve %s\n", servername);
3507dd7cddfSDavid du Colombier 		resolver = 0;
3517dd7cddfSDavid du Colombier 	} else {
3527dd7cddfSDavid du Colombier 		resolver = 1;
3537dd7cddfSDavid du Colombier 	}
3547dd7cddfSDavid du Colombier 	return resolver ? 0 : -1;
3557dd7cddfSDavid du Colombier }
3567dd7cddfSDavid du Colombier 
3577dd7cddfSDavid du Colombier void
3587dd7cddfSDavid du Colombier doquery(char *name, char *tstr)
3597dd7cddfSDavid du Colombier {
3607dd7cddfSDavid du Colombier 	Request req;
3617dd7cddfSDavid du Colombier 	RR *rr, *rp;
3627dd7cddfSDavid du Colombier 	int len, type;
3637dd7cddfSDavid du Colombier 	char *p, *np;
364271b8d73SDavid du Colombier 	int rooted;
3657dd7cddfSDavid du Colombier 	char buf[1024];
3667dd7cddfSDavid du Colombier 
3677dd7cddfSDavid du Colombier 	if(resolver)
3687dd7cddfSDavid du Colombier 		preloadserveraddrs();
3697dd7cddfSDavid du Colombier 
3707dd7cddfSDavid du Colombier 	/* default to an "ip" request if alpha, "ptr" if numeric */
3717dd7cddfSDavid du Colombier 	if(tstr == nil || *tstr == 0) {
3727dd7cddfSDavid du Colombier 		if(strcmp(ipattr(name), "ip") == 0)
3737dd7cddfSDavid du Colombier 			tstr = "ptr";
3747dd7cddfSDavid du Colombier 		else
3757dd7cddfSDavid du Colombier 			tstr = "ip";
3767dd7cddfSDavid du Colombier 	}
3777dd7cddfSDavid du Colombier 
3787dd7cddfSDavid du Colombier 	/* if name end in '.', remove it */
3797dd7cddfSDavid du Colombier 	len = strlen(name);
380271b8d73SDavid du Colombier 	if(len > 0 && name[len-1] == '.'){
381271b8d73SDavid du Colombier 		rooted = 1;
3827dd7cddfSDavid du Colombier 		name[len-1] = 0;
383271b8d73SDavid du Colombier 	} else
384271b8d73SDavid du Colombier 		rooted = 0;
3857dd7cddfSDavid du Colombier 
3867dd7cddfSDavid du Colombier 	/* inverse queries may need to be permuted */
3879a747e4fSDavid du Colombier 	strncpy(buf, name, sizeof buf);
3887dd7cddfSDavid du Colombier 	if(strcmp("ptr", tstr) == 0
3897dd7cddfSDavid du Colombier 	&& strstr(name, "IN-ADDR") == 0
3907dd7cddfSDavid du Colombier 	&& strstr(name, "in-addr") == 0){
3917dd7cddfSDavid du Colombier 		for(p = name; *p; p++)
3927dd7cddfSDavid du Colombier 			;
3937dd7cddfSDavid du Colombier 		*p = '.';
3947dd7cddfSDavid du Colombier 		np = buf;
3957dd7cddfSDavid du Colombier 		len = 0;
3967dd7cddfSDavid du Colombier 		while(p >= name){
3977dd7cddfSDavid du Colombier 			len++;
3987dd7cddfSDavid du Colombier 			p--;
3997dd7cddfSDavid du Colombier 			if(*p == '.'){
4007dd7cddfSDavid du Colombier 				memmove(np, p+1, len);
4017dd7cddfSDavid du Colombier 				np += len;
4027dd7cddfSDavid du Colombier 				len = 0;
4037dd7cddfSDavid du Colombier 			}
4047dd7cddfSDavid du Colombier 		}
4057dd7cddfSDavid du Colombier 		memmove(np, p+1, len);
4067dd7cddfSDavid du Colombier 		np += len;
4077dd7cddfSDavid du Colombier 		strcpy(np, "in-addr.arpa");
4087dd7cddfSDavid du Colombier 	}
4097dd7cddfSDavid du Colombier 
4107dd7cddfSDavid du Colombier 	/* look it up */
4117dd7cddfSDavid du Colombier 	type = rrtype(tstr);
4127dd7cddfSDavid du Colombier 	if(type < 0){
4137dd7cddfSDavid du Colombier 		print("!unknown type %s\n", tstr);
4147dd7cddfSDavid du Colombier 		return;
4157dd7cddfSDavid du Colombier 	}
4167dd7cddfSDavid du Colombier 
417*b4b9fc2fSDavid du Colombier 	getactivity(&req, 0);
4187dd7cddfSDavid du Colombier 	req.isslave = 1;
4197dd7cddfSDavid du Colombier 	req.aborttime = now + 60;	/* don't spend more than 60 seconds */
420271b8d73SDavid du Colombier 	rr = dnresolve(buf, Cin, type, &req, 0, 0, Recurse, rooted, 0);
4217dd7cddfSDavid du Colombier 	if(rr){
4227dd7cddfSDavid du Colombier 		print("----------------------------\n");
4237dd7cddfSDavid du Colombier 		for(rp = rr; rp; rp = rp->next)
4247dd7cddfSDavid du Colombier 			print("answer %R\n", rp);
4257dd7cddfSDavid du Colombier 		print("----------------------------\n");
4267dd7cddfSDavid du Colombier 	}
4277dd7cddfSDavid du Colombier 	rrfreelist(rr);
4287dd7cddfSDavid du Colombier 
429*b4b9fc2fSDavid du Colombier 	putactivity(0);
4307dd7cddfSDavid du Colombier }
4317dd7cddfSDavid du Colombier 
4327dd7cddfSDavid du Colombier void
4337dd7cddfSDavid du Colombier docmd(int n, char **f)
4347dd7cddfSDavid du Colombier {
4357dd7cddfSDavid du Colombier 	int tmpsrv;
4367dd7cddfSDavid du Colombier 	char *name, *type;
4377dd7cddfSDavid du Colombier 
4387dd7cddfSDavid du Colombier 	name = nil;
4397dd7cddfSDavid du Colombier 	type = nil;
4407dd7cddfSDavid du Colombier 	tmpsrv = 0;
4417dd7cddfSDavid du Colombier 
4427dd7cddfSDavid du Colombier 	if(*f[0] == '@') {
4437dd7cddfSDavid du Colombier 		if(setserver(f[0]+1) < 0)
4447dd7cddfSDavid du Colombier 			return;
4457dd7cddfSDavid du Colombier 
4467dd7cddfSDavid du Colombier 		switch(n){
4477dd7cddfSDavid du Colombier 		case 3:
4487dd7cddfSDavid du Colombier 			type = f[2];
4497dd7cddfSDavid du Colombier 			/* fall through */
4507dd7cddfSDavid du Colombier 		case 2:
4517dd7cddfSDavid du Colombier 			name = f[1];
4527dd7cddfSDavid du Colombier 			tmpsrv = 1;
4537dd7cddfSDavid du Colombier 			break;
4547dd7cddfSDavid du Colombier 		}
4557dd7cddfSDavid du Colombier 	} else {
4567dd7cddfSDavid du Colombier 		switch(n){
4577dd7cddfSDavid du Colombier 		case 2:
4587dd7cddfSDavid du Colombier 			type = f[1];
4597dd7cddfSDavid du Colombier 			/* fall through */
4607dd7cddfSDavid du Colombier 		case 1:
4617dd7cddfSDavid du Colombier 			name = f[0];
4627dd7cddfSDavid du Colombier 			break;
4637dd7cddfSDavid du Colombier 		}
4647dd7cddfSDavid du Colombier 	}
4657dd7cddfSDavid du Colombier 
4667dd7cddfSDavid du Colombier 	if(name == nil)
4677dd7cddfSDavid du Colombier 		return;
4687dd7cddfSDavid du Colombier 
4697dd7cddfSDavid du Colombier 	doquery(name, type);
4707dd7cddfSDavid du Colombier 
4717dd7cddfSDavid du Colombier 	if(tmpsrv)
4727dd7cddfSDavid du Colombier 		setserver("");
4737dd7cddfSDavid du Colombier }
474