xref: /plan9/sys/src/cmd/ndb/dnstcp.c (revision e02f7f02bd837384880240d3ead0b1c0930eacbe)
14f8f669cSDavid du Colombier /*
24f8f669cSDavid du Colombier  * dnstcp - serve dns via tcp
34f8f669cSDavid du Colombier  */
47dd7cddfSDavid du Colombier #include <u.h>
57dd7cddfSDavid du Colombier #include <libc.h>
67dd7cddfSDavid du Colombier #include <ip.h>
77dd7cddfSDavid du Colombier #include "dns.h"
87dd7cddfSDavid du Colombier 
94f8f669cSDavid du Colombier Cfg cfg;
107ad596ffSDavid du Colombier 
114f8f669cSDavid du Colombier char	*caller = "";
127dd7cddfSDavid du Colombier char	*dbfile;
137dd7cddfSDavid du Colombier int	debug;
144f8f669cSDavid du Colombier uchar	ipaddr[IPaddrlen];	/* my ip address */
154f8f669cSDavid du Colombier char	*logfile = "dns";
164f8f669cSDavid du Colombier int	maxage = 60*60;
174f8f669cSDavid du Colombier char	mntpt[Maxpath];
184f8f669cSDavid du Colombier int	needrefresh;
194f8f669cSDavid du Colombier ulong	now;
20a41547ffSDavid du Colombier vlong	nowns;
217dd7cddfSDavid du Colombier int	testing;
2267031067SDavid du Colombier int	traceactivity;
230103620dSDavid du Colombier char	*zonerefreshprogram;
247dd7cddfSDavid du Colombier 
257dd7cddfSDavid du Colombier static int	readmsg(int, uchar*, int);
267dd7cddfSDavid du Colombier static void	reply(int, DNSmsg*, Request*);
277dd7cddfSDavid du Colombier static void	dnzone(DNSmsg*, DNSmsg*, Request*);
287dd7cddfSDavid du Colombier static void	getcaller(char*);
297dd7cddfSDavid du Colombier static void	refreshmain(char*);
307dd7cddfSDavid du Colombier 
317dd7cddfSDavid du Colombier void
usage(void)32b4b9fc2fSDavid du Colombier usage(void)
33b4b9fc2fSDavid du Colombier {
34830cad64SDavid du Colombier 	fprint(2, "usage: %s [-rR] [-f ndb-file] [-x netmtpt] [conndir]\n", argv0);
35b4b9fc2fSDavid du Colombier 	exits("usage");
36b4b9fc2fSDavid du Colombier }
37b4b9fc2fSDavid du Colombier 
38b4b9fc2fSDavid du Colombier void
main(int argc,char * argv[])397dd7cddfSDavid du Colombier main(int argc, char *argv[])
407dd7cddfSDavid du Colombier {
41225077b0SDavid du Colombier 	volatile int len, rcode;
42225077b0SDavid du Colombier 	volatile char tname[32];
43225077b0SDavid du Colombier 	char *volatile err, *volatile ext = "";
44225077b0SDavid du Colombier 	volatile uchar buf[64*1024], callip[IPaddrlen];
45225077b0SDavid du Colombier 	volatile DNSmsg reqmsg, repmsg;
46225077b0SDavid du Colombier 	volatile Request req;
477dd7cddfSDavid du Colombier 
48a41547ffSDavid du Colombier 	alarm(2*60*1000);
494f8f669cSDavid du Colombier 	cfg.cachedb = 1;
507dd7cddfSDavid du Colombier 	ARGBEGIN{
517dd7cddfSDavid du Colombier 	case 'd':
5259cc4ca5SDavid du Colombier 		debug++;
537dd7cddfSDavid du Colombier 		break;
547dd7cddfSDavid du Colombier 	case 'f':
55b4b9fc2fSDavid du Colombier 		dbfile = EARGF(usage());
567dd7cddfSDavid du Colombier 		break;
577dd7cddfSDavid du Colombier 	case 'r':
584f8f669cSDavid du Colombier 		cfg.resolver = 1;
594f8f669cSDavid du Colombier 		break;
604f8f669cSDavid du Colombier 	case 'R':
614f8f669cSDavid du Colombier 		norecursion = 1;
627dd7cddfSDavid du Colombier 		break;
637dd7cddfSDavid du Colombier 	case 'x':
64b4b9fc2fSDavid du Colombier 		ext = EARGF(usage());
65b4b9fc2fSDavid du Colombier 		break;
66b4b9fc2fSDavid du Colombier 	default:
67b4b9fc2fSDavid du Colombier 		usage();
687dd7cddfSDavid du Colombier 		break;
697dd7cddfSDavid du Colombier 	}ARGEND
707dd7cddfSDavid du Colombier 
7159cc4ca5SDavid du Colombier 	if(debug < 2)
7259cc4ca5SDavid du Colombier 		debug = 0;
7359cc4ca5SDavid du Colombier 
747dd7cddfSDavid du Colombier 	if(argc > 0)
757dd7cddfSDavid du Colombier 		getcaller(argv[0]);
767dd7cddfSDavid du Colombier 
774f8f669cSDavid du Colombier 	cfg.inside = 1;
7859cc4ca5SDavid du Colombier 	dninit();
797dd7cddfSDavid du Colombier 
804f8f669cSDavid du Colombier 	snprint(mntpt, sizeof mntpt, "/net%s", ext);
819a747e4fSDavid du Colombier 	if(myipaddr(ipaddr, mntpt) < 0)
827dd7cddfSDavid du Colombier 		sysfatal("can't read my ip address");
834f8f669cSDavid du Colombier 	dnslog("dnstcp call from %s to %I", caller, ipaddr);
84d3907fe5SDavid du Colombier 	memset(callip, 0, sizeof callip);
85d3907fe5SDavid du Colombier 	parseip(callip, caller);
8659cc4ca5SDavid du Colombier 
877dd7cddfSDavid du Colombier 	db2cache(1);
887dd7cddfSDavid du Colombier 
894f8f669cSDavid du Colombier 	memset(&req, 0, sizeof req);
907dd7cddfSDavid du Colombier 	setjmp(req.mret);
917dd7cddfSDavid du Colombier 	req.isslave = 0;
924f8f669cSDavid du Colombier 	procsetname("main loop");
937dd7cddfSDavid du Colombier 
947dd7cddfSDavid du Colombier 	/* loop on requests */
95b4b9fc2fSDavid du Colombier 	for(;; putactivity(0)){
964f8f669cSDavid du Colombier 		now = time(nil);
974f8f669cSDavid du Colombier 		memset(&repmsg, 0, sizeof repmsg);
984f8f669cSDavid du Colombier 		len = readmsg(0, buf, sizeof buf);
997dd7cddfSDavid du Colombier 		if(len <= 0)
1007dd7cddfSDavid du Colombier 			break;
101a41547ffSDavid du Colombier 
102b4b9fc2fSDavid du Colombier 		getactivity(&req, 0);
103*e02f7f02SDavid du Colombier 		req.aborttime = timems() + S2MS(15*Min);
1044f8f669cSDavid du Colombier 		rcode = 0;
1054f8f669cSDavid du Colombier 		memset(&reqmsg, 0, sizeof reqmsg);
1064f8f669cSDavid du Colombier 		err = convM2DNS(buf, len, &reqmsg, &rcode);
1077dd7cddfSDavid du Colombier 		if(err){
108d3907fe5SDavid du Colombier 			dnslog("server: input error: %s from %s", err, caller);
109186d659cSDavid du Colombier 			free(err);
1107dd7cddfSDavid du Colombier 			break;
1117dd7cddfSDavid du Colombier 		}
1124f8f669cSDavid du Colombier 		if (rcode == 0)
1137dd7cddfSDavid du Colombier 			if(reqmsg.qdcount < 1){
114d3907fe5SDavid du Colombier 				dnslog("server: no questions from %s", caller);
1154f8f669cSDavid du Colombier 				break;
1164f8f669cSDavid du Colombier 			} else if(reqmsg.flags & Fresp){
117d3907fe5SDavid du Colombier 				dnslog("server: reply not request from %s",
118d3907fe5SDavid du Colombier 					caller);
1194f8f669cSDavid du Colombier 				break;
1204f8f669cSDavid du Colombier 			} else if((reqmsg.flags & Omask) != Oquery){
121d3907fe5SDavid du Colombier 				dnslog("server: op %d from %s",
122d3907fe5SDavid du Colombier 					reqmsg.flags & Omask, caller);
1237dd7cddfSDavid du Colombier 				break;
1247dd7cddfSDavid du Colombier 			}
1257dd7cddfSDavid du Colombier 		if(debug)
1264f8f669cSDavid du Colombier 			dnslog("[%d] %d: serve (%s) %d %s %s",
1274f8f669cSDavid du Colombier 				getpid(), req.id, caller,
1284f8f669cSDavid du Colombier 				reqmsg.id, reqmsg.qd->owner->name,
1299a747e4fSDavid du Colombier 				rrname(reqmsg.qd->type, tname, sizeof tname));
1307dd7cddfSDavid du Colombier 
1317dd7cddfSDavid du Colombier 		/* loop through each question */
1324f8f669cSDavid du Colombier 		while(reqmsg.qd)
1334f8f669cSDavid du Colombier 			if(reqmsg.qd->type == Taxfr)
1347dd7cddfSDavid du Colombier 				dnzone(&reqmsg, &repmsg, &req);
1354f8f669cSDavid du Colombier 			else {
136d3907fe5SDavid du Colombier 				dnserver(&reqmsg, &repmsg, &req, callip, rcode);
1377dd7cddfSDavid du Colombier 				reply(1, &repmsg, &req);
1387dd7cddfSDavid du Colombier 				rrfreelist(repmsg.qd);
1397dd7cddfSDavid du Colombier 				rrfreelist(repmsg.an);
1407dd7cddfSDavid du Colombier 				rrfreelist(repmsg.ns);
1417dd7cddfSDavid du Colombier 				rrfreelist(repmsg.ar);
1427dd7cddfSDavid du Colombier 			}
1436aaebd7dSDavid du Colombier 		rrfreelist(reqmsg.qd);		/* qd will be nil */
1447dd7cddfSDavid du Colombier 		rrfreelist(reqmsg.an);
1457dd7cddfSDavid du Colombier 		rrfreelist(reqmsg.ns);
1467dd7cddfSDavid du Colombier 		rrfreelist(reqmsg.ar);
1477dd7cddfSDavid du Colombier 
1487dd7cddfSDavid du Colombier 		if(req.isslave){
149b4b9fc2fSDavid du Colombier 			putactivity(0);
1507dd7cddfSDavid du Colombier 			_exits(0);
1517dd7cddfSDavid du Colombier 		}
1527dd7cddfSDavid du Colombier 	}
1537dd7cddfSDavid du Colombier 	refreshmain(mntpt);
1547dd7cddfSDavid du Colombier }
1557dd7cddfSDavid du Colombier 
1567dd7cddfSDavid du Colombier static int
readmsg(int fd,uchar * buf,int max)1577dd7cddfSDavid du Colombier readmsg(int fd, uchar *buf, int max)
1587dd7cddfSDavid du Colombier {
1597dd7cddfSDavid du Colombier 	int n;
1607dd7cddfSDavid du Colombier 	uchar x[2];
1617dd7cddfSDavid du Colombier 
1627dd7cddfSDavid du Colombier 	if(readn(fd, x, 2) != 2)
1637dd7cddfSDavid du Colombier 		return -1;
1644f8f669cSDavid du Colombier 	n = x[0]<<8 | x[1];
1657dd7cddfSDavid du Colombier 	if(n > max)
1667dd7cddfSDavid du Colombier 		return -1;
1677dd7cddfSDavid du Colombier 	if(readn(fd, buf, n) != n)
1687dd7cddfSDavid du Colombier 		return -1;
1697dd7cddfSDavid du Colombier 	return n;
1707dd7cddfSDavid du Colombier }
1717dd7cddfSDavid du Colombier 
1727dd7cddfSDavid du Colombier static void
reply(int fd,DNSmsg * rep,Request * req)1737dd7cddfSDavid du Colombier reply(int fd, DNSmsg *rep, Request *req)
1747dd7cddfSDavid du Colombier {
1757dd7cddfSDavid du Colombier 	int len, rv;
1767dd7cddfSDavid du Colombier 	char tname[32];
17776783259SDavid du Colombier 	uchar buf[64*1024];
1787dd7cddfSDavid du Colombier 	RR *rp;
1797dd7cddfSDavid du Colombier 
1807dd7cddfSDavid du Colombier 	if(debug){
1814f8f669cSDavid du Colombier 		dnslog("%d: reply (%s) %s %s %ux",
1827dd7cddfSDavid du Colombier 			req->id, caller,
1837dd7cddfSDavid du Colombier 			rep->qd->owner->name,
1849a747e4fSDavid du Colombier 			rrname(rep->qd->type, tname, sizeof tname),
1857dd7cddfSDavid du Colombier 			rep->flags);
1867dd7cddfSDavid du Colombier 		for(rp = rep->an; rp; rp = rp->next)
1874f8f669cSDavid du Colombier 			dnslog("an %R", rp);
1887dd7cddfSDavid du Colombier 		for(rp = rep->ns; rp; rp = rp->next)
1894f8f669cSDavid du Colombier 			dnslog("ns %R", rp);
1907dd7cddfSDavid du Colombier 		for(rp = rep->ar; rp; rp = rp->next)
1914f8f669cSDavid du Colombier 			dnslog("ar %R", rp);
1927dd7cddfSDavid du Colombier 	}
1937dd7cddfSDavid du Colombier 
1947dd7cddfSDavid du Colombier 
1957dd7cddfSDavid du Colombier 	len = convDNS2M(rep, buf+2, sizeof(buf) - 2);
1967dd7cddfSDavid du Colombier 	buf[0] = len>>8;
1977dd7cddfSDavid du Colombier 	buf[1] = len;
1987dd7cddfSDavid du Colombier 	rv = write(fd, buf, len+2);
1997dd7cddfSDavid du Colombier 	if(rv != len+2){
200d6d99297SDavid du Colombier 		dnslog("[%d] sending reply: %d instead of %d", getpid(), rv,
201d6d99297SDavid du Colombier 			len+2);
2027dd7cddfSDavid du Colombier 		exits(0);
2037dd7cddfSDavid du Colombier 	}
2047dd7cddfSDavid du Colombier }
2057dd7cddfSDavid du Colombier 
2067dd7cddfSDavid du Colombier /*
2077dd7cddfSDavid du Colombier  *  Hash table for domain names.  The hash is based only on the
2087dd7cddfSDavid du Colombier  *  first element of the domain name.
2097dd7cddfSDavid du Colombier  */
2107dd7cddfSDavid du Colombier extern DN	*ht[HTLEN];
2117dd7cddfSDavid du Colombier 
2127dd7cddfSDavid du Colombier static int
numelem(char * name)2137dd7cddfSDavid du Colombier numelem(char *name)
2147dd7cddfSDavid du Colombier {
2157dd7cddfSDavid du Colombier 	int i;
2167dd7cddfSDavid du Colombier 
2177dd7cddfSDavid du Colombier 	i = 1;
2187dd7cddfSDavid du Colombier 	for(; *name; name++)
2197dd7cddfSDavid du Colombier 		if(*name == '.')
2207dd7cddfSDavid du Colombier 			i++;
2217dd7cddfSDavid du Colombier 	return i;
2227dd7cddfSDavid du Colombier }
2237dd7cddfSDavid du Colombier 
2247dd7cddfSDavid du Colombier int
inzone(DN * dp,char * name,int namelen,int depth)2257dd7cddfSDavid du Colombier inzone(DN *dp, char *name, int namelen, int depth)
2267dd7cddfSDavid du Colombier {
2277dd7cddfSDavid du Colombier 	int n;
2287dd7cddfSDavid du Colombier 
2294f8f669cSDavid du Colombier 	if(dp->name == nil)
2307dd7cddfSDavid du Colombier 		return 0;
2317dd7cddfSDavid du Colombier 	if(numelem(dp->name) != depth)
2327dd7cddfSDavid du Colombier 		return 0;
2337dd7cddfSDavid du Colombier 	n = strlen(dp->name);
2347dd7cddfSDavid du Colombier 	if(n < namelen)
2357dd7cddfSDavid du Colombier 		return 0;
2367dd7cddfSDavid du Colombier 	if(strcmp(name, dp->name + n - namelen) != 0)
2377dd7cddfSDavid du Colombier 		return 0;
2387dd7cddfSDavid du Colombier 	if(n > namelen && dp->name[n - namelen - 1] != '.')
2397dd7cddfSDavid du Colombier 		return 0;
2407dd7cddfSDavid du Colombier 	return 1;
2417dd7cddfSDavid du Colombier }
2427dd7cddfSDavid du Colombier 
2437dd7cddfSDavid du Colombier static void
dnzone(DNSmsg * reqp,DNSmsg * repp,Request * req)2447dd7cddfSDavid du Colombier dnzone(DNSmsg *reqp, DNSmsg *repp, Request *req)
2457dd7cddfSDavid du Colombier {
2463ff48bf5SDavid du Colombier 	DN *dp, *ndp;
2473ff48bf5SDavid du Colombier 	RR r, *rp;
2483ff48bf5SDavid du Colombier 	int h, depth, found, nlen;
2497dd7cddfSDavid du Colombier 
2507dd7cddfSDavid du Colombier 	memset(repp, 0, sizeof(*repp));
2517dd7cddfSDavid du Colombier 	repp->id = reqp->id;
2527dd7cddfSDavid du Colombier 	repp->qd = reqp->qd;
2537dd7cddfSDavid du Colombier 	reqp->qd = reqp->qd->next;
2547dd7cddfSDavid du Colombier 	repp->qd->next = 0;
255b4b9fc2fSDavid du Colombier 	repp->flags = Fauth | Fresp | Oquery;
256b4b9fc2fSDavid du Colombier 	if(!norecursion)
257b4b9fc2fSDavid du Colombier 		repp->flags |= Fcanrec;
2587dd7cddfSDavid du Colombier 	dp = repp->qd->owner;
2597dd7cddfSDavid du Colombier 
2607dd7cddfSDavid du Colombier 	/* send the soa */
2617dd7cddfSDavid du Colombier 	repp->an = rrlookup(dp, Tsoa, NOneg);
2627dd7cddfSDavid du Colombier 	reply(1, repp, req);
2637dd7cddfSDavid du Colombier 	if(repp->an == 0)
2647dd7cddfSDavid du Colombier 		goto out;
2657dd7cddfSDavid du Colombier 	rrfreelist(repp->an);
2664f8f669cSDavid du Colombier 	repp->an = nil;
2677dd7cddfSDavid du Colombier 
2683ff48bf5SDavid du Colombier 	nlen = strlen(dp->name);
2697dd7cddfSDavid du Colombier 
2704f8f669cSDavid du Colombier 	/* construct a breadth-first search of the name space (hard with a hash) */
2713ff48bf5SDavid du Colombier 	repp->an = &r;
2723ff48bf5SDavid du Colombier 	for(depth = numelem(dp->name); ; depth++){
2733ff48bf5SDavid du Colombier 		found = 0;
2743ff48bf5SDavid du Colombier 		for(h = 0; h < HTLEN; h++)
2753ff48bf5SDavid du Colombier 			for(ndp = ht[h]; ndp; ndp = ndp->next)
2763ff48bf5SDavid du Colombier 				if(inzone(ndp, dp->name, nlen, depth)){
2773ff48bf5SDavid du Colombier 					for(rp = ndp->rr; rp; rp = rp->next){
2784f8f669cSDavid du Colombier 						/*
2794f8f669cSDavid du Colombier 						 * there shouldn't be negatives,
2804f8f669cSDavid du Colombier 						 * but just in case.
2814f8f669cSDavid du Colombier 						 * don't send any soa's,
2824f8f669cSDavid du Colombier 						 * ns's are enough.
2834f8f669cSDavid du Colombier 						 */
2844f8f669cSDavid du Colombier 						if (rp->negative ||
2854f8f669cSDavid du Colombier 						    rp->type == Tsoa)
2863ff48bf5SDavid du Colombier 							continue;
2873ff48bf5SDavid du Colombier 						r = *rp;
2883ff48bf5SDavid du Colombier 						r.next = 0;
2893ff48bf5SDavid du Colombier 						reply(1, repp, req);
2903ff48bf5SDavid du Colombier 					}
2913ff48bf5SDavid du Colombier 					found = 1;
2923ff48bf5SDavid du Colombier 				}
2933ff48bf5SDavid du Colombier 		if(!found)
2943ff48bf5SDavid du Colombier 			break;
2957dd7cddfSDavid du Colombier 	}
2967dd7cddfSDavid du Colombier 
2977dd7cddfSDavid du Colombier 	/* resend the soa */
2987dd7cddfSDavid du Colombier 	repp->an = rrlookup(dp, Tsoa, NOneg);
2997dd7cddfSDavid du Colombier 	reply(1, repp, req);
3007dd7cddfSDavid du Colombier 	rrfreelist(repp->an);
3014f8f669cSDavid du Colombier 	repp->an = nil;
3027dd7cddfSDavid du Colombier out:
3037dd7cddfSDavid du Colombier 	rrfree(repp->qd);
3044f8f669cSDavid du Colombier 	repp->qd = nil;
3057dd7cddfSDavid du Colombier }
3067dd7cddfSDavid du Colombier 
3077dd7cddfSDavid du Colombier static void
getcaller(char * dir)3087dd7cddfSDavid du Colombier getcaller(char *dir)
3097dd7cddfSDavid du Colombier {
3107dd7cddfSDavid du Colombier 	int fd, n;
3117dd7cddfSDavid du Colombier 	static char remote[128];
3127dd7cddfSDavid du Colombier 
3137dd7cddfSDavid du Colombier 	snprint(remote, sizeof(remote), "%s/remote", dir);
3147dd7cddfSDavid du Colombier 	fd = open(remote, OREAD);
3157dd7cddfSDavid du Colombier 	if(fd < 0)
3167dd7cddfSDavid du Colombier 		return;
3174f8f669cSDavid du Colombier 	n = read(fd, remote, sizeof remote - 1);
3187dd7cddfSDavid du Colombier 	close(fd);
3197dd7cddfSDavid du Colombier 	if(n <= 0)
3207dd7cddfSDavid du Colombier 		return;
3217dd7cddfSDavid du Colombier 	if(remote[n-1] == '\n')
3227dd7cddfSDavid du Colombier 		n--;
3237dd7cddfSDavid du Colombier 	remote[n] = 0;
3247dd7cddfSDavid du Colombier 	caller = remote;
3257dd7cddfSDavid du Colombier }
3267dd7cddfSDavid du Colombier 
3277dd7cddfSDavid du Colombier static void
refreshmain(char * net)3287dd7cddfSDavid du Colombier refreshmain(char *net)
3297dd7cddfSDavid du Colombier {
3307dd7cddfSDavid du Colombier 	int fd;
3317dd7cddfSDavid du Colombier 	char file[128];
3327dd7cddfSDavid du Colombier 
3337dd7cddfSDavid du Colombier 	snprint(file, sizeof(file), "%s/dns", net);
3347dd7cddfSDavid du Colombier 	if(debug)
3354f8f669cSDavid du Colombier 		dnslog("refreshing %s", file);
3367dd7cddfSDavid du Colombier 	fd = open(file, ORDWR);
3374f8f669cSDavid du Colombier 	if(fd < 0)
3384f8f669cSDavid du Colombier 		dnslog("can't refresh %s", file);
3394f8f669cSDavid du Colombier 	else {
3407dd7cddfSDavid du Colombier 		fprint(fd, "refresh");
3417dd7cddfSDavid du Colombier 		close(fd);
3427dd7cddfSDavid du Colombier 	}
3434f8f669cSDavid du Colombier }
3447dd7cddfSDavid du Colombier 
3457dd7cddfSDavid du Colombier /*
3467dd7cddfSDavid du Colombier  *  the following varies between dnsdebug and dns
3477dd7cddfSDavid du Colombier  */
3487dd7cddfSDavid du Colombier void
logreply(int id,uchar * addr,DNSmsg * mp)3497dd7cddfSDavid du Colombier logreply(int id, uchar *addr, DNSmsg *mp)
3507dd7cddfSDavid du Colombier {
3517dd7cddfSDavid du Colombier 	RR *rp;
3527dd7cddfSDavid du Colombier 
3534f8f669cSDavid du Colombier 	dnslog("%d: rcvd %I flags:%s%s%s%s%s", id, addr,
3547dd7cddfSDavid du Colombier 		mp->flags & Fauth? " auth": "",
3557dd7cddfSDavid du Colombier 		mp->flags & Ftrunc? " trunc": "",
3567dd7cddfSDavid du Colombier 		mp->flags & Frecurse? " rd": "",
3577dd7cddfSDavid du Colombier 		mp->flags & Fcanrec? " ra": "",
3584f8f669cSDavid du Colombier 		(mp->flags & (Fauth|Rmask)) == (Fauth|Rname)? " nx": "");
3597dd7cddfSDavid du Colombier 	for(rp = mp->qd; rp != nil; rp = rp->next)
3604f8f669cSDavid du Colombier 		dnslog("%d: rcvd %I qd %s", id, addr, rp->owner->name);
3617dd7cddfSDavid du Colombier 	for(rp = mp->an; rp != nil; rp = rp->next)
3624f8f669cSDavid du Colombier 		dnslog("%d: rcvd %I an %R", id, addr, rp);
3637dd7cddfSDavid du Colombier 	for(rp = mp->ns; rp != nil; rp = rp->next)
3644f8f669cSDavid du Colombier 		dnslog("%d: rcvd %I ns %R", id, addr, rp);
3657dd7cddfSDavid du Colombier 	for(rp = mp->ar; rp != nil; rp = rp->next)
3664f8f669cSDavid du Colombier 		dnslog("%d: rcvd %I ar %R", id, addr, rp);
3677dd7cddfSDavid du Colombier }
3687dd7cddfSDavid du Colombier 
3697dd7cddfSDavid du Colombier void
logsend(int id,int subid,uchar * addr,char * sname,char * rname,int type)3707dd7cddfSDavid du Colombier logsend(int id, int subid, uchar *addr, char *sname, char *rname, int type)
3717dd7cddfSDavid du Colombier {
3727dd7cddfSDavid du Colombier 	char buf[12];
3737dd7cddfSDavid du Colombier 
3744f8f669cSDavid du Colombier 	dnslog("%d.%d: sending to %I/%s %s %s",
3759a747e4fSDavid du Colombier 		id, subid, addr, sname, rname, rrname(type, buf, sizeof buf));
3767dd7cddfSDavid du Colombier }
3777dd7cddfSDavid du Colombier 
3787dd7cddfSDavid du Colombier RR*
getdnsservers(int class)3797dd7cddfSDavid du Colombier getdnsservers(int class)
3807dd7cddfSDavid du Colombier {
3817dd7cddfSDavid du Colombier 	return dnsservers(class);
3827dd7cddfSDavid du Colombier }
383