xref: /plan9/sys/src/cmd/ndb/dnsdebug.c (revision b2ebcd4d1aeacb3fc8c3d85492d03278b32bed3f)
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 
94f8f669cSDavid du Colombier enum {
109a747e4fSDavid du Colombier 	Maxrequest=		128,
117dd7cddfSDavid du Colombier };
127dd7cddfSDavid du Colombier 
134f8f669cSDavid du Colombier Cfg cfg;
144f8f669cSDavid du Colombier 
157dd7cddfSDavid du Colombier static char *servername;
167dd7cddfSDavid du Colombier static RR *serverrr;
177dd7cddfSDavid du Colombier static RR *serveraddrs;
187dd7cddfSDavid du Colombier 
194f8f669cSDavid du Colombier char	*dbfile;
205aa528faSDavid du Colombier int	debug;
214f8f669cSDavid du Colombier uchar	ipaddr[IPaddrlen];	/* my ip address */
224f8f669cSDavid du Colombier char	*logfile = "dnsdebug";
234f8f669cSDavid du Colombier int	maxage  = 60*60;
244f8f669cSDavid du Colombier char	mntpt[Maxpath];
254f8f669cSDavid du Colombier int	needrefresh;
265aa528faSDavid du Colombier ulong	now;
27a41547ffSDavid du Colombier vlong	nowns;
285aa528faSDavid du Colombier int	testing;
296b0d5c8bSDavid du Colombier char	*trace;
304f8f669cSDavid du Colombier int	traceactivity;
31dc5a79c1SDavid du Colombier char	*zonerefreshprogram;
327dd7cddfSDavid du Colombier 
336b0d5c8bSDavid du Colombier void	docmd(int, char**);
344f8f669cSDavid du Colombier void	doquery(char*, char*);
354f8f669cSDavid du Colombier void	preloadserveraddrs(void);
364f8f669cSDavid du Colombier int	prettyrrfmt(Fmt*);
374f8f669cSDavid du Colombier int	setserver(char*);
384f8f669cSDavid du Colombier void	squirrelserveraddrs(void);
394f8f669cSDavid du Colombier 
404f8f669cSDavid du Colombier void
usage(void)414f8f669cSDavid du Colombier usage(void)
424f8f669cSDavid du Colombier {
43d9924332SDavid du Colombier 	fprint(2, "%s: [-rx] [-f db-file] [[@server] domain [type]]\n", argv0);
444f8f669cSDavid du Colombier 	exits("usage");
454f8f669cSDavid du Colombier }
467dd7cddfSDavid du Colombier 
477dd7cddfSDavid du Colombier void
main(int argc,char * argv[])487dd7cddfSDavid du Colombier main(int argc, char *argv[])
497dd7cddfSDavid du Colombier {
507dd7cddfSDavid du Colombier 	int n;
517dd7cddfSDavid du Colombier 	Biobuf in;
5280ee5cbfSDavid du Colombier 	char *p;
537dd7cddfSDavid du Colombier 	char *f[4];
547dd7cddfSDavid du Colombier 
557dd7cddfSDavid du Colombier 	strcpy(mntpt, "/net");
564f8f669cSDavid du Colombier 	cfg.inside = 1;
577dd7cddfSDavid du Colombier 
587dd7cddfSDavid du Colombier 	ARGBEGIN{
594f8f669cSDavid du Colombier 	case 'f':
604f8f669cSDavid du Colombier 		dbfile = EARGF(usage());
614f8f669cSDavid du Colombier 		break;
627dd7cddfSDavid du Colombier 	case 'r':
634f8f669cSDavid du Colombier 		cfg.resolver = 1;
647dd7cddfSDavid du Colombier 		break;
657dd7cddfSDavid du Colombier 	case 'x':
667dd7cddfSDavid du Colombier 		dbfile = "/lib/ndb/external";
677dd7cddfSDavid du Colombier 		strcpy(mntpt, "/net.alt");
687dd7cddfSDavid du Colombier 		break;
694f8f669cSDavid du Colombier 	default:
704f8f669cSDavid du Colombier 		usage();
717dd7cddfSDavid du Colombier 	}ARGEND
727dd7cddfSDavid du Colombier 
734f8f669cSDavid du Colombier 	now = time(nil);
74e02f7f02SDavid du Colombier 	nowns = nsec();
757dd7cddfSDavid du Colombier 	dninit();
769a747e4fSDavid du Colombier 	fmtinstall('R', prettyrrfmt);
779a747e4fSDavid du Colombier 	if(myipaddr(ipaddr, mntpt) < 0)
787dd7cddfSDavid du Colombier 		sysfatal("can't read my ip address");
797dd7cddfSDavid du Colombier 	opendatabase();
807dd7cddfSDavid du Colombier 
814f8f669cSDavid du Colombier 	if(cfg.resolver)
827dd7cddfSDavid du Colombier 		squirrelserveraddrs();
837dd7cddfSDavid du Colombier 
847dd7cddfSDavid du Colombier 	debug = 1;
857dd7cddfSDavid du Colombier 
867dd7cddfSDavid du Colombier 	if(argc > 0){
877dd7cddfSDavid du Colombier 		docmd(argc, argv);
887dd7cddfSDavid du Colombier 		exits(0);
897dd7cddfSDavid du Colombier 	}
907dd7cddfSDavid du Colombier 
917dd7cddfSDavid du Colombier 	Binit(&in, 0, OREAD);
927dd7cddfSDavid du Colombier 	for(print("> "); p = Brdline(&in, '\n'); print("> ")){
937dd7cddfSDavid du Colombier 		p[Blinelen(&in)-1] = 0;
947dd7cddfSDavid du Colombier 		n = tokenize(p, f, 3);
954f8f669cSDavid du Colombier 		if(n>=1) {
964f8f669cSDavid du Colombier 			dnpurge();		/* flush the cache */
977dd7cddfSDavid du Colombier 			docmd(n, f);
984f8f669cSDavid du Colombier 		}
997dd7cddfSDavid du Colombier 	}
1007dd7cddfSDavid du Colombier 	exits(0);
1017dd7cddfSDavid du Colombier }
1027dd7cddfSDavid du Colombier 
1037dd7cddfSDavid du Colombier static char*
longtime(long t)1047dd7cddfSDavid du Colombier longtime(long t)
1057dd7cddfSDavid du Colombier {
1067dd7cddfSDavid du Colombier 	int d, h, m, n;
1077dd7cddfSDavid du Colombier 	static char x[128];
1087dd7cddfSDavid du Colombier 
1097dd7cddfSDavid du Colombier 	for(d = 0; t >= 24*60*60; t -= 24*60*60)
1107dd7cddfSDavid du Colombier 		d++;
1117dd7cddfSDavid du Colombier 	for(h = 0; t >= 60*60; t -= 60*60)
1127dd7cddfSDavid du Colombier 		h++;
1137dd7cddfSDavid du Colombier 	for(m = 0; t >= 60; t -= 60)
1147dd7cddfSDavid du Colombier 		m++;
1157dd7cddfSDavid du Colombier 	n = 0;
1167dd7cddfSDavid du Colombier 	if(d)
1177dd7cddfSDavid du Colombier 		n += sprint(x, "%d day ", d);
1187dd7cddfSDavid du Colombier 	if(h)
1197dd7cddfSDavid du Colombier 		n += sprint(x+n, "%d hr ", h);
1207dd7cddfSDavid du Colombier 	if(m)
1217dd7cddfSDavid du Colombier 		n += sprint(x+n, "%d min ", m);
1227dd7cddfSDavid du Colombier 	if(t || n == 0)
1237dd7cddfSDavid du Colombier 		sprint(x+n, "%ld sec", t);
1247dd7cddfSDavid du Colombier 	return x;
1257dd7cddfSDavid du Colombier }
1267dd7cddfSDavid du Colombier 
1277dd7cddfSDavid du Colombier int
prettyrrfmt(Fmt * f)1289a747e4fSDavid du Colombier prettyrrfmt(Fmt *f)
1297dd7cddfSDavid du Colombier {
1307dd7cddfSDavid du Colombier 	RR *rp;
1317dd7cddfSDavid du Colombier 	char buf[3*Domlen];
1327dd7cddfSDavid du Colombier 	char *p, *e;
1338754a1dfSDavid du Colombier 	Txt *t;
1347dd7cddfSDavid du Colombier 
1359a747e4fSDavid du Colombier 	rp = va_arg(f->args, RR*);
1367dd7cddfSDavid du Colombier 	if(rp == 0){
1377dd7cddfSDavid du Colombier 		strcpy(buf, "<null>");
1387dd7cddfSDavid du Colombier 		goto out;
1397dd7cddfSDavid du Colombier 	}
1407dd7cddfSDavid du Colombier 
1417dd7cddfSDavid du Colombier 	p = buf;
1427dd7cddfSDavid du Colombier 	e = buf + sizeof(buf);
1437dd7cddfSDavid du Colombier 	p = seprint(p, e, "%-32.32s %-15.15s %-5.5s", rp->owner->name,
1447dd7cddfSDavid du Colombier 		longtime(rp->db? rp->ttl: (rp->ttl - now)),
1459a747e4fSDavid du Colombier 		rrname(rp->type, buf, sizeof buf));
1467dd7cddfSDavid du Colombier 
1477dd7cddfSDavid du Colombier 	if(rp->negative){
14872061b92SDavid du Colombier 		seprint(p, e, "negative rcode %d", rp->negrcode);
1497dd7cddfSDavid du Colombier 		goto out;
1507dd7cddfSDavid du Colombier 	}
1517dd7cddfSDavid du Colombier 
1527dd7cddfSDavid du Colombier 	switch(rp->type){
1537dd7cddfSDavid du Colombier 	case Thinfo:
1547dd7cddfSDavid du Colombier 		seprint(p, e, "\t%s %s", rp->cpu->name, rp->os->name);
1557dd7cddfSDavid du Colombier 		break;
1567dd7cddfSDavid du Colombier 	case Tcname:
1577dd7cddfSDavid du Colombier 	case Tmb:
1587dd7cddfSDavid du Colombier 	case Tmd:
1597dd7cddfSDavid du Colombier 	case Tmf:
1607dd7cddfSDavid du Colombier 	case Tns:
1614f8f669cSDavid du Colombier 		seprint(p, e, "\t%s", (rp->host? rp->host->name: ""));
1627dd7cddfSDavid du Colombier 		break;
1637dd7cddfSDavid du Colombier 	case Tmg:
1647dd7cddfSDavid du Colombier 	case Tmr:
1654f8f669cSDavid du Colombier 		seprint(p, e, "\t%s", (rp->mb? rp->mb->name: ""));
1667dd7cddfSDavid du Colombier 		break;
1677dd7cddfSDavid du Colombier 	case Tminfo:
1684f8f669cSDavid du Colombier 		seprint(p, e, "\t%s %s", (rp->mb? rp->mb->name: ""),
1694f8f669cSDavid du Colombier 			(rp->rmb? rp->rmb->name: ""));
1707dd7cddfSDavid du Colombier 		break;
1717dd7cddfSDavid du Colombier 	case Tmx:
1724f8f669cSDavid du Colombier 		seprint(p, e, "\t%lud %s", rp->pref,
1734f8f669cSDavid du Colombier 			(rp->host? rp->host->name: ""));
1747dd7cddfSDavid du Colombier 		break;
1757dd7cddfSDavid du Colombier 	case Ta:
1765d459b5aSDavid du Colombier 	case Taaaa:
1774f8f669cSDavid du Colombier 		seprint(p, e, "\t%s", (rp->ip? rp->ip->name: ""));
1787dd7cddfSDavid du Colombier 		break;
1797dd7cddfSDavid du Colombier 	case Tptr:
1804f8f669cSDavid du Colombier 		seprint(p, e, "\t%s", (rp->ptr? rp->ptr->name: ""));
1817dd7cddfSDavid du Colombier 		break;
1827dd7cddfSDavid du Colombier 	case Tsoa:
1834f8f669cSDavid du Colombier 		seprint(p, e, "\t%s %s %lud %lud %lud %lud %lud",
1844f8f669cSDavid du Colombier 			rp->host->name, rp->rmb->name, rp->soa->serial,
1854f8f669cSDavid du Colombier 			rp->soa->refresh, rp->soa->retry,
1867dd7cddfSDavid du Colombier 			rp->soa->expire, rp->soa->minttl);
1877dd7cddfSDavid du Colombier 		break;
1884f8f669cSDavid du Colombier 	case Tsrv:
1894f8f669cSDavid du Colombier 		seprint(p, e, "\t%ud %ud %ud %s",
190225077b0SDavid du Colombier 			rp->srv->pri, rp->srv->weight, rp->port, rp->host->name);
1914f8f669cSDavid du Colombier 		break;
1929a747e4fSDavid du Colombier 	case Tnull:
1939a747e4fSDavid du Colombier 		seprint(p, e, "\t%.*H", rp->null->dlen, rp->null->data);
1949a747e4fSDavid du Colombier 		break;
1957dd7cddfSDavid du Colombier 	case Ttxt:
1968754a1dfSDavid du Colombier 		p = seprint(p, e, "\t");
1978754a1dfSDavid du Colombier 		for(t = rp->txt; t != nil; t = t->next)
1988754a1dfSDavid du Colombier 			p = seprint(p, e, "%s", t->p);
1997dd7cddfSDavid du Colombier 		break;
2007dd7cddfSDavid du Colombier 	case Trp:
2018754a1dfSDavid du Colombier 		seprint(p, e, "\t%s %s", rp->rmb->name, rp->rp->name);
2027dd7cddfSDavid du Colombier 		break;
2037dd7cddfSDavid du Colombier 	case Tkey:
2047dd7cddfSDavid du Colombier 		seprint(p, e, "\t%d %d %d", rp->key->flags, rp->key->proto,
2057dd7cddfSDavid du Colombier 			rp->key->alg);
2067dd7cddfSDavid du Colombier 		break;
2077dd7cddfSDavid du Colombier 	case Tsig:
2087dd7cddfSDavid du Colombier 		seprint(p, e, "\t%d %d %d %lud %lud %lud %d %s",
2094f8f669cSDavid du Colombier 			rp->sig->type, rp->sig->alg, rp->sig->labels,
2104f8f669cSDavid du Colombier 			rp->sig->ttl, rp->sig->exp, rp->sig->incep,
2114f8f669cSDavid du Colombier 			rp->sig->tag, rp->sig->signer->name);
2127dd7cddfSDavid du Colombier 		break;
2137dd7cddfSDavid du Colombier 	case Tcert:
2147dd7cddfSDavid du Colombier 		seprint(p, e, "\t%d %d %d",
2157dd7cddfSDavid du Colombier 			rp->sig->type, rp->sig->tag, rp->sig->alg);
2167dd7cddfSDavid du Colombier 		break;
2177dd7cddfSDavid du Colombier 	}
2187dd7cddfSDavid du Colombier out:
2199a747e4fSDavid du Colombier 	return fmtstrcpy(f, buf);
2207dd7cddfSDavid du Colombier }
2217dd7cddfSDavid du Colombier 
2227dd7cddfSDavid du Colombier void
logsection(char * flag,RR * rp)2237dd7cddfSDavid du Colombier logsection(char *flag, RR *rp)
2247dd7cddfSDavid du Colombier {
2257dd7cddfSDavid du Colombier 	if(rp == nil)
2267dd7cddfSDavid du Colombier 		return;
2277dd7cddfSDavid du Colombier 	print("\t%s%R\n", flag, rp);
2287dd7cddfSDavid du Colombier 	for(rp = rp->next; rp != nil; rp = rp->next)
2297dd7cddfSDavid du Colombier 		print("\t      %R\n", rp);
2307dd7cddfSDavid du Colombier }
2317dd7cddfSDavid du Colombier 
2327dd7cddfSDavid du Colombier void
logreply(int id,uchar * addr,DNSmsg * mp)2337dd7cddfSDavid du Colombier logreply(int id, uchar *addr, DNSmsg *mp)
2347dd7cddfSDavid du Colombier {
2357dd7cddfSDavid du Colombier 	RR *rp;
2364f8f669cSDavid du Colombier 	char buf[12], resp[32];
2377dd7cddfSDavid du Colombier 
2387dd7cddfSDavid du Colombier 	switch(mp->flags & Rmask){
2397dd7cddfSDavid du Colombier 	case Rok:
2407dd7cddfSDavid du Colombier 		strcpy(resp, "OK");
2417dd7cddfSDavid du Colombier 		break;
2427dd7cddfSDavid du Colombier 	case Rformat:
2437dd7cddfSDavid du Colombier 		strcpy(resp, "Format error");
2447dd7cddfSDavid du Colombier 		break;
2457dd7cddfSDavid du Colombier 	case Rserver:
2467dd7cddfSDavid du Colombier 		strcpy(resp, "Server failed");
2477dd7cddfSDavid du Colombier 		break;
2487dd7cddfSDavid du Colombier 	case Rname:
2497dd7cddfSDavid du Colombier 		strcpy(resp, "Nonexistent");
2507dd7cddfSDavid du Colombier 		break;
2517dd7cddfSDavid du Colombier 	case Runimplimented:
2527dd7cddfSDavid du Colombier 		strcpy(resp, "Unimplemented");
2537dd7cddfSDavid du Colombier 		break;
2547dd7cddfSDavid du Colombier 	case Rrefused:
2557dd7cddfSDavid du Colombier 		strcpy(resp, "Refused");
2567dd7cddfSDavid du Colombier 		break;
2577dd7cddfSDavid du Colombier 	default:
2587dd7cddfSDavid du Colombier 		sprint(resp, "%d", mp->flags & Rmask);
2597dd7cddfSDavid du Colombier 		break;
2607dd7cddfSDavid du Colombier 	}
2617dd7cddfSDavid du Colombier 
2627dd7cddfSDavid du Colombier 	print("%d: rcvd %s from %I (%s%s%s%s%s)\n", id, resp, addr,
2637dd7cddfSDavid du Colombier 		mp->flags & Fauth? "authoritative": "",
2647dd7cddfSDavid du Colombier 		mp->flags & Ftrunc? " truncated": "",
2657dd7cddfSDavid du Colombier 		mp->flags & Frecurse? " recurse": "",
2667dd7cddfSDavid du Colombier 		mp->flags & Fcanrec? " can_recurse": "",
2674f8f669cSDavid du Colombier 		(mp->flags & (Fauth|Rmask)) == (Fauth|Rname)? " nx": "");
2687dd7cddfSDavid du Colombier 	for(rp = mp->qd; rp != nil; rp = rp->next)
2694f8f669cSDavid du Colombier 		print("\tQ:    %s %s\n", rp->owner->name,
2704f8f669cSDavid du Colombier 			rrname(rp->type, buf, sizeof buf));
2717dd7cddfSDavid du Colombier 	logsection("Ans:  ", mp->an);
2727dd7cddfSDavid du Colombier 	logsection("Auth: ", mp->ns);
2737dd7cddfSDavid du Colombier 	logsection("Hint: ", mp->ar);
2747dd7cddfSDavid du Colombier }
2757dd7cddfSDavid du Colombier 
2767dd7cddfSDavid du Colombier void
logsend(int id,int subid,uchar * addr,char * sname,char * rname,int type)2777dd7cddfSDavid du Colombier logsend(int id, int subid, uchar *addr, char *sname, char *rname, int type)
2787dd7cddfSDavid du Colombier {
2797dd7cddfSDavid du Colombier 	char buf[12];
2807dd7cddfSDavid du Colombier 
2817dd7cddfSDavid du Colombier 	print("%d.%d: sending to %I/%s %s %s\n", id, subid,
2829a747e4fSDavid du Colombier 		addr, sname, rname, rrname(type, buf, sizeof buf));
2837dd7cddfSDavid du Colombier }
2847dd7cddfSDavid du Colombier 
2857dd7cddfSDavid du Colombier RR*
getdnsservers(int class)2867dd7cddfSDavid du Colombier getdnsservers(int class)
2877dd7cddfSDavid du Colombier {
2887dd7cddfSDavid du Colombier 	RR *rr;
2897dd7cddfSDavid du Colombier 
2907dd7cddfSDavid du Colombier 	if(servername == nil)
2917dd7cddfSDavid du Colombier 		return dnsservers(class);
2927dd7cddfSDavid du Colombier 
2937dd7cddfSDavid du Colombier 	rr = rralloc(Tns);
2947dd7cddfSDavid du Colombier 	rr->owner = dnlookup("local#dns#servers", class, 1);
2957dd7cddfSDavid du Colombier 	rr->host = dnlookup(servername, class, 1);
2967dd7cddfSDavid du Colombier 
2977dd7cddfSDavid du Colombier 	return rr;
2987dd7cddfSDavid du Colombier }
2997dd7cddfSDavid du Colombier 
3007dd7cddfSDavid du Colombier void
squirrelserveraddrs(void)3017dd7cddfSDavid du Colombier squirrelserveraddrs(void)
3027dd7cddfSDavid du Colombier {
303d9924332SDavid du Colombier 	int v4;
304d9924332SDavid du Colombier 	char *attr;
3057dd7cddfSDavid du Colombier 	RR *rr, *rp, **l;
3067dd7cddfSDavid du Colombier 	Request req;
3077dd7cddfSDavid du Colombier 
3087dd7cddfSDavid du Colombier 	/* look up the resolver address first */
3094f8f669cSDavid du Colombier 	cfg.resolver = 0;
3107dd7cddfSDavid du Colombier 	debug = 0;
3117dd7cddfSDavid du Colombier 	if(serveraddrs)
3127dd7cddfSDavid du Colombier 		rrfreelist(serveraddrs);
3137dd7cddfSDavid du Colombier 	serveraddrs = nil;
3147dd7cddfSDavid du Colombier 	rr = getdnsservers(Cin);
3157dd7cddfSDavid du Colombier 	l = &serveraddrs;
3167dd7cddfSDavid du Colombier 	for(rp = rr; rp != nil; rp = rp->next){
317d9924332SDavid du Colombier 		attr = ipattr(rp->host->name);
318d9924332SDavid du Colombier 		v4 = strcmp(attr, "ip") == 0;
319d9924332SDavid du Colombier 		if(v4 || strcmp(attr, "ipv6") == 0){
320d9924332SDavid du Colombier 			*l = rralloc(v4? Ta: Taaaa);
3217dd7cddfSDavid du Colombier 			(*l)->owner = rp->host;
3227dd7cddfSDavid du Colombier 			(*l)->ip = rp->host;
3237dd7cddfSDavid du Colombier 			l = &(*l)->next;
3247dd7cddfSDavid du Colombier 			continue;
3257dd7cddfSDavid du Colombier 		}
326*b2ebcd4dSDavid du Colombier 		memset(&req, 0, sizeof req);
3277dd7cddfSDavid du Colombier 		req.isslave = 1;
328e02f7f02SDavid du Colombier 		req.aborttime = NS2MS(nowns) + Maxreqtm;
329271b8d73SDavid du Colombier 		*l = dnresolve(rp->host->name, Cin, Ta, &req, 0, 0, Recurse, 0, 0);
330d9924332SDavid du Colombier 		if(*l == nil)
331d9924332SDavid du Colombier 			*l = dnresolve(rp->host->name, Cin, Taaaa, &req,
332d9924332SDavid du Colombier 				0, 0, Recurse, 0, 0);
3337dd7cddfSDavid du Colombier 		while(*l != nil)
3347dd7cddfSDavid du Colombier 			l = &(*l)->next;
3357dd7cddfSDavid du Colombier 	}
3364f8f669cSDavid du Colombier 	cfg.resolver = 1;
3377dd7cddfSDavid du Colombier 	debug = 1;
3387dd7cddfSDavid du Colombier }
3397dd7cddfSDavid du Colombier 
3407dd7cddfSDavid du Colombier void
preloadserveraddrs(void)3417dd7cddfSDavid du Colombier preloadserveraddrs(void)
3427dd7cddfSDavid du Colombier {
3437dd7cddfSDavid du Colombier 	RR *rp, **l, *first;
3447dd7cddfSDavid du Colombier 
3457dd7cddfSDavid du Colombier 	l = &first;
3467dd7cddfSDavid du Colombier 	for(rp = serveraddrs; rp != nil; rp = rp->next){
3474faf7596SDavid du Colombier 		lock(&dnlock);
3487dd7cddfSDavid du Colombier 		rrcopy(rp, l);
3494faf7596SDavid du Colombier 		unlock(&dnlock);
3506dc4800dSDavid du Colombier 		rrattach(first, Authoritative);
3517dd7cddfSDavid du Colombier 	}
3527dd7cddfSDavid du Colombier }
3537dd7cddfSDavid du Colombier 
3547dd7cddfSDavid du Colombier int
setserver(char * server)3557dd7cddfSDavid du Colombier setserver(char *server)
3567dd7cddfSDavid du Colombier {
3577dd7cddfSDavid du Colombier 	if(servername != nil){
3587dd7cddfSDavid du Colombier 		free(servername);
3597dd7cddfSDavid du Colombier 		servername = nil;
3604f8f669cSDavid du Colombier 		cfg.resolver = 0;
3617dd7cddfSDavid du Colombier 	}
3627dd7cddfSDavid du Colombier 	if(server == nil || *server == 0)
3637dd7cddfSDavid du Colombier 		return 0;
3647dd7cddfSDavid du Colombier 	servername = strdup(server);
3657dd7cddfSDavid du Colombier 	squirrelserveraddrs();
3667dd7cddfSDavid du Colombier 	if(serveraddrs == nil){
3677dd7cddfSDavid du Colombier 		print("can't resolve %s\n", servername);
3684f8f669cSDavid du Colombier 		cfg.resolver = 0;
3694f8f669cSDavid du Colombier 	} else
3704f8f669cSDavid du Colombier 		cfg.resolver = 1;
3714f8f669cSDavid du Colombier 	return cfg.resolver? 0: -1;
3727dd7cddfSDavid du Colombier }
3737dd7cddfSDavid du Colombier 
3747dd7cddfSDavid du Colombier void
doquery(char * name,char * tstr)3757dd7cddfSDavid du Colombier doquery(char *name, char *tstr)
3767dd7cddfSDavid du Colombier {
3774f8f669cSDavid du Colombier 	int len, type, rooted;
3786b0d5c8bSDavid du Colombier 	char *p, *np;
3796b0d5c8bSDavid du Colombier 	char buf[1024];
3804f8f669cSDavid du Colombier 	RR *rr, *rp;
3814f8f669cSDavid du Colombier 	Request req;
3827dd7cddfSDavid du Colombier 
3834f8f669cSDavid du Colombier 	if(cfg.resolver)
3847dd7cddfSDavid du Colombier 		preloadserveraddrs();
3857dd7cddfSDavid du Colombier 
3867dd7cddfSDavid du Colombier 	/* default to an "ip" request if alpha, "ptr" if numeric */
3874f8f669cSDavid du Colombier 	if(tstr == nil || *tstr == 0)
3887dd7cddfSDavid du Colombier 		if(strcmp(ipattr(name), "ip") == 0)
3897dd7cddfSDavid du Colombier 			tstr = "ptr";
3907dd7cddfSDavid du Colombier 		else
3917dd7cddfSDavid du Colombier 			tstr = "ip";
3927dd7cddfSDavid du Colombier 
3937dd7cddfSDavid du Colombier 	/* if name end in '.', remove it */
3947dd7cddfSDavid du Colombier 	len = strlen(name);
395271b8d73SDavid du Colombier 	if(len > 0 && name[len-1] == '.'){
396271b8d73SDavid du Colombier 		rooted = 1;
3977dd7cddfSDavid du Colombier 		name[len-1] = 0;
398271b8d73SDavid du Colombier 	} else
399271b8d73SDavid du Colombier 		rooted = 0;
4007dd7cddfSDavid du Colombier 
4017dd7cddfSDavid du Colombier 	/* inverse queries may need to be permuted */
4029a747e4fSDavid du Colombier 	strncpy(buf, name, sizeof buf);
40353874d13SDavid du Colombier 	if(strcmp("ptr", tstr) == 0 && cistrstr(name, ".arpa") == nil){
40453874d13SDavid du Colombier 		/* TODO: reversing v6 addrs is harder */
4057dd7cddfSDavid du Colombier 		for(p = name; *p; p++)
4067dd7cddfSDavid du Colombier 			;
4077dd7cddfSDavid du Colombier 		*p = '.';
4087dd7cddfSDavid du Colombier 		np = buf;
4097dd7cddfSDavid du Colombier 		len = 0;
4107dd7cddfSDavid du Colombier 		while(p >= name){
4117dd7cddfSDavid du Colombier 			len++;
4127dd7cddfSDavid du Colombier 			p--;
4137dd7cddfSDavid du Colombier 			if(*p == '.'){
4147dd7cddfSDavid du Colombier 				memmove(np, p+1, len);
4157dd7cddfSDavid du Colombier 				np += len;
4167dd7cddfSDavid du Colombier 				len = 0;
4177dd7cddfSDavid du Colombier 			}
4187dd7cddfSDavid du Colombier 		}
4197dd7cddfSDavid du Colombier 		memmove(np, p+1, len);
4207dd7cddfSDavid du Colombier 		np += len;
42153874d13SDavid du Colombier 		strcpy(np, "in-addr.arpa");	/* TODO: ip6.arpa for v6 */
4227dd7cddfSDavid du Colombier 	}
4237dd7cddfSDavid du Colombier 
4247dd7cddfSDavid du Colombier 	/* look it up */
4257dd7cddfSDavid du Colombier 	type = rrtype(tstr);
4267dd7cddfSDavid du Colombier 	if(type < 0){
4277dd7cddfSDavid du Colombier 		print("!unknown type %s\n", tstr);
4287dd7cddfSDavid du Colombier 		return;
4297dd7cddfSDavid du Colombier 	}
4307dd7cddfSDavid du Colombier 
4314f8f669cSDavid du Colombier 	memset(&req, 0, sizeof req);
432b4b9fc2fSDavid du Colombier 	getactivity(&req, 0);
4337dd7cddfSDavid du Colombier 	req.isslave = 1;
434e02f7f02SDavid du Colombier 	req.aborttime = NS2MS(nowns) + Maxreqtm;
435271b8d73SDavid du Colombier 	rr = dnresolve(buf, Cin, type, &req, 0, 0, Recurse, rooted, 0);
4367dd7cddfSDavid du Colombier 	if(rr){
4377dd7cddfSDavid du Colombier 		print("----------------------------\n");
4387dd7cddfSDavid du Colombier 		for(rp = rr; rp; rp = rp->next)
4397dd7cddfSDavid du Colombier 			print("answer %R\n", rp);
4407dd7cddfSDavid du Colombier 		print("----------------------------\n");
4417dd7cddfSDavid du Colombier 	}
4427dd7cddfSDavid du Colombier 	rrfreelist(rr);
4437dd7cddfSDavid du Colombier 
444b4b9fc2fSDavid du Colombier 	putactivity(0);
4457dd7cddfSDavid du Colombier }
4467dd7cddfSDavid du Colombier 
4477dd7cddfSDavid du Colombier void
docmd(int n,char ** f)4487dd7cddfSDavid du Colombier docmd(int n, char **f)
4497dd7cddfSDavid du Colombier {
4507dd7cddfSDavid du Colombier 	int tmpsrv;
4517dd7cddfSDavid du Colombier 	char *name, *type;
4527dd7cddfSDavid du Colombier 
4534f8f669cSDavid du Colombier 	name = type = nil;
4547dd7cddfSDavid du Colombier 	tmpsrv = 0;
4557dd7cddfSDavid du Colombier 
4567dd7cddfSDavid du Colombier 	if(*f[0] == '@') {
4577dd7cddfSDavid du Colombier 		if(setserver(f[0]+1) < 0)
4587dd7cddfSDavid du Colombier 			return;
4597dd7cddfSDavid du Colombier 
4607dd7cddfSDavid du Colombier 		switch(n){
4617dd7cddfSDavid du Colombier 		case 3:
4627dd7cddfSDavid du Colombier 			type = f[2];
4637dd7cddfSDavid du Colombier 			/* fall through */
4647dd7cddfSDavid du Colombier 		case 2:
4657dd7cddfSDavid du Colombier 			name = f[1];
4667dd7cddfSDavid du Colombier 			tmpsrv = 1;
4677dd7cddfSDavid du Colombier 			break;
4687dd7cddfSDavid du Colombier 		}
4694f8f669cSDavid du Colombier 	} else
4707dd7cddfSDavid du Colombier 		switch(n){
4717dd7cddfSDavid du Colombier 		case 2:
4727dd7cddfSDavid du Colombier 			type = f[1];
4737dd7cddfSDavid du Colombier 			/* fall through */
4747dd7cddfSDavid du Colombier 		case 1:
4757dd7cddfSDavid du Colombier 			name = f[0];
4767dd7cddfSDavid du Colombier 			break;
4777dd7cddfSDavid du Colombier 		}
4787dd7cddfSDavid du Colombier 
4797dd7cddfSDavid du Colombier 	if(name == nil)
4807dd7cddfSDavid du Colombier 		return;
4817dd7cddfSDavid du Colombier 
4827dd7cddfSDavid du Colombier 	doquery(name, type);
4837dd7cddfSDavid du Colombier 
4847dd7cddfSDavid du Colombier 	if(tmpsrv)
4857dd7cddfSDavid du Colombier 		setserver("");
4867dd7cddfSDavid du Colombier }
487