xref: /plan9/sys/src/cmd/ndb/dns.c (revision 3ff48bf5ed603850fcd251ddf13025d23d693782)
13e12c5d1SDavid du Colombier #include <u.h>
23e12c5d1SDavid du Colombier #include <libc.h>
3219b2ee8SDavid du Colombier #include <auth.h>
43e12c5d1SDavid du Colombier #include <fcall.h>
53e12c5d1SDavid du Colombier #include <bio.h>
63e12c5d1SDavid du Colombier #include <ctype.h>
77dd7cddfSDavid du Colombier #include <ip.h>
89a747e4fSDavid du Colombier #include <pool.h>
93e12c5d1SDavid du Colombier #include "dns.h"
103e12c5d1SDavid du Colombier 
113e12c5d1SDavid du Colombier enum
123e12c5d1SDavid du Colombier {
139a747e4fSDavid du Colombier 	Maxrequest=		1024,
143e12c5d1SDavid du Colombier 	Ncache=			8,
157dd7cddfSDavid du Colombier 	Maxpath=		128,
167dd7cddfSDavid du Colombier 	Maxreply=		512,
177dd7cddfSDavid du Colombier 	Maxrrr=			16,
189a747e4fSDavid du Colombier 	Maxfdata=		8192,
193e12c5d1SDavid du Colombier 
209a747e4fSDavid du Colombier 	Qdir=			0,
213e12c5d1SDavid du Colombier 	Qdns=			1,
223e12c5d1SDavid du Colombier };
233e12c5d1SDavid du Colombier 
243e12c5d1SDavid du Colombier typedef struct Mfile	Mfile;
257dd7cddfSDavid du Colombier typedef struct Job	Job;
263e12c5d1SDavid du Colombier typedef struct Network	Network;
273e12c5d1SDavid du Colombier 
283e12c5d1SDavid du Colombier int vers;		/* incremented each clone/attach */
293e12c5d1SDavid du Colombier 
303e12c5d1SDavid du Colombier struct Mfile
313e12c5d1SDavid du Colombier {
327dd7cddfSDavid du Colombier 	Mfile		*next;		/* next free mfile */
339a747e4fSDavid du Colombier 	int		ref;
347dd7cddfSDavid du Colombier 
359a747e4fSDavid du Colombier 	char		*user;
363e12c5d1SDavid du Colombier 	Qid		qid;
373e12c5d1SDavid du Colombier 	int		fid;
383e12c5d1SDavid du Colombier 
393e12c5d1SDavid du Colombier 	int		type;		/* reply type */
407dd7cddfSDavid du Colombier 	char		reply[Maxreply];
417dd7cddfSDavid du Colombier 	ushort		rr[Maxrrr];	/* offset of rr's */
427dd7cddfSDavid du Colombier 	ushort		nrr;		/* number of rr's */
433e12c5d1SDavid du Colombier };
443e12c5d1SDavid du Colombier 
457dd7cddfSDavid du Colombier //
467dd7cddfSDavid du Colombier //  active local requests
477dd7cddfSDavid du Colombier //
487dd7cddfSDavid du Colombier struct Job
497dd7cddfSDavid du Colombier {
507dd7cddfSDavid du Colombier 	Job	*next;
517dd7cddfSDavid du Colombier 	int	flushed;
527dd7cddfSDavid du Colombier 	Fcall	request;
537dd7cddfSDavid du Colombier 	Fcall	reply;
547dd7cddfSDavid du Colombier };
557dd7cddfSDavid du Colombier Lock	joblock;
567dd7cddfSDavid du Colombier Job	*joblist;
577dd7cddfSDavid du Colombier 
587dd7cddfSDavid du Colombier struct {
597dd7cddfSDavid du Colombier 	Lock;
607dd7cddfSDavid du Colombier 	Mfile	*inuse;		/* active mfile's */
617dd7cddfSDavid du Colombier } mfalloc;
627dd7cddfSDavid du Colombier 
633e12c5d1SDavid du Colombier int	mfd[2];
643e12c5d1SDavid du Colombier int	debug;
657dd7cddfSDavid du Colombier int	cachedb;
667dd7cddfSDavid du Colombier ulong	now;
677dd7cddfSDavid du Colombier int	testing;
687dd7cddfSDavid du Colombier char	*trace;
697dd7cddfSDavid du Colombier int	needrefresh;
707dd7cddfSDavid du Colombier int	resolver;
717dd7cddfSDavid du Colombier uchar	ipaddr[IPaddrlen];	/* my ip address */
727dd7cddfSDavid du Colombier int	maxage;
733e12c5d1SDavid du Colombier 
749a747e4fSDavid du Colombier void	rversion(Job*);
759a747e4fSDavid du Colombier void	rauth(Job*);
767dd7cddfSDavid du Colombier void	rflush(Job*);
777dd7cddfSDavid du Colombier void	rattach(Job*, Mfile*);
787dd7cddfSDavid du Colombier char*	rwalk(Job*, Mfile*);
797dd7cddfSDavid du Colombier void	ropen(Job*, Mfile*);
807dd7cddfSDavid du Colombier void	rcreate(Job*, Mfile*);
817dd7cddfSDavid du Colombier void	rread(Job*, Mfile*);
827dd7cddfSDavid du Colombier void	rwrite(Job*, Mfile*, Request*);
837dd7cddfSDavid du Colombier void	rclunk(Job*, Mfile*);
847dd7cddfSDavid du Colombier void	rremove(Job*, Mfile*);
857dd7cddfSDavid du Colombier void	rstat(Job*, Mfile*);
867dd7cddfSDavid du Colombier void	rwstat(Job*, Mfile*);
877dd7cddfSDavid du Colombier void	sendmsg(Job*, char*);
887dd7cddfSDavid du Colombier void	mountinit(char*, char*);
893e12c5d1SDavid du Colombier void	io(void);
903e12c5d1SDavid du Colombier int	fillreply(Mfile*, int);
917dd7cddfSDavid du Colombier Job*	newjob(void);
927dd7cddfSDavid du Colombier void	freejob(Job*);
937dd7cddfSDavid du Colombier void	setext(char*, int, char*);
943e12c5d1SDavid du Colombier 
95219b2ee8SDavid du Colombier char	*logfile = "dns";
96219b2ee8SDavid du Colombier char	*dbfile;
977dd7cddfSDavid du Colombier char	mntpt[Maxpath];
987dd7cddfSDavid du Colombier char	*LOG;
997dd7cddfSDavid du Colombier 
1007dd7cddfSDavid du Colombier void
1017dd7cddfSDavid du Colombier usage(void)
1027dd7cddfSDavid du Colombier {
1037dd7cddfSDavid du Colombier 	fprint(2, "usage: %s [-rs] [-f ndb-file] [-x netmtpt]\n", argv0);
1047dd7cddfSDavid du Colombier 	exits("usage");
1057dd7cddfSDavid du Colombier }
106219b2ee8SDavid du Colombier 
1073e12c5d1SDavid du Colombier void
1083e12c5d1SDavid du Colombier main(int argc, char *argv[])
1093e12c5d1SDavid du Colombier {
1103e12c5d1SDavid du Colombier 	int	serve;
1117dd7cddfSDavid du Colombier 	char	servefile[Maxpath];
1127dd7cddfSDavid du Colombier 	char	ext[Maxpath];
1137dd7cddfSDavid du Colombier 	char	*p;
114219b2ee8SDavid du Colombier 
1153e12c5d1SDavid du Colombier 	serve = 0;
1167dd7cddfSDavid du Colombier 	setnetmtpt(mntpt, sizeof(mntpt), nil);
1177dd7cddfSDavid du Colombier 	ext[0] = 0;
1183e12c5d1SDavid du Colombier 	ARGBEGIN{
1193e12c5d1SDavid du Colombier 	case 'd':
1203e12c5d1SDavid du Colombier 		debug = 1;
1213e12c5d1SDavid du Colombier 		break;
122219b2ee8SDavid du Colombier 	case 'f':
1237dd7cddfSDavid du Colombier 		p = ARGF();
1247dd7cddfSDavid du Colombier 		if(p == nil)
1257dd7cddfSDavid du Colombier 			usage();
1267dd7cddfSDavid du Colombier 		dbfile = p;
1277dd7cddfSDavid du Colombier 		break;
1287dd7cddfSDavid du Colombier 	case 'x':
1297dd7cddfSDavid du Colombier 		p = ARGF();
1307dd7cddfSDavid du Colombier 		if(p == nil)
1317dd7cddfSDavid du Colombier 			usage();
1327dd7cddfSDavid du Colombier 		setnetmtpt(mntpt, sizeof(mntpt), p);
1337dd7cddfSDavid du Colombier 		setext(ext, sizeof(ext), mntpt);
1347dd7cddfSDavid du Colombier 		break;
1357dd7cddfSDavid du Colombier 	case 'r':
1367dd7cddfSDavid du Colombier 		resolver = 1;
137219b2ee8SDavid du Colombier 		break;
1383e12c5d1SDavid du Colombier 	case 's':
1393e12c5d1SDavid du Colombier 		serve = 1;	/* serve network */
1407dd7cddfSDavid du Colombier 		cachedb = 1;
1417dd7cddfSDavid du Colombier 		break;
1427dd7cddfSDavid du Colombier 	case 'a':
1437dd7cddfSDavid du Colombier 		p = ARGF();
1447dd7cddfSDavid du Colombier 		if(p == nil)
1457dd7cddfSDavid du Colombier 			usage();
1467dd7cddfSDavid du Colombier 		maxage = atoi(p);
1477dd7cddfSDavid du Colombier 		break;
1487dd7cddfSDavid du Colombier 	case 't':
1497dd7cddfSDavid du Colombier 		testing = 1;
1503e12c5d1SDavid du Colombier 		break;
1513e12c5d1SDavid du Colombier 	}ARGEND
1523e12c5d1SDavid du Colombier 	USED(argc);
1533e12c5d1SDavid du Colombier 	USED(argv);
1543e12c5d1SDavid du Colombier 
1559a747e4fSDavid du Colombier if(testing) mainmem->flags |= POOL_NOREUSE;
1567dd7cddfSDavid du Colombier 	rfork(RFREND|RFNOTEG);
1573e12c5d1SDavid du Colombier 
1587dd7cddfSDavid du Colombier 	/* start syslog before we fork */
1599a747e4fSDavid du Colombier 	fmtinstall('F', fcallfmt);
160219b2ee8SDavid du Colombier 	dninit();
1619a747e4fSDavid du Colombier 	if(myipaddr(ipaddr, mntpt) < 0)
1627dd7cddfSDavid du Colombier 		sysfatal("can't read my ip address");
163219b2ee8SDavid du Colombier 
1647dd7cddfSDavid du Colombier 	syslog(0, logfile, "starting dns on %I", ipaddr);
1657dd7cddfSDavid du Colombier 
1667dd7cddfSDavid du Colombier 	opendatabase();
1677dd7cddfSDavid du Colombier 
1687dd7cddfSDavid du Colombier 	snprint(servefile, sizeof(servefile), "#s/dns%s", ext);
1697dd7cddfSDavid du Colombier 	unmount(servefile, mntpt);
1707dd7cddfSDavid du Colombier 	remove(servefile);
1717dd7cddfSDavid du Colombier 	mountinit(servefile, mntpt);
1727dd7cddfSDavid du Colombier 
1737dd7cddfSDavid du Colombier 	now = time(0);
1747dd7cddfSDavid du Colombier 	srand(now*getpid());
1757dd7cddfSDavid du Colombier 	db2cache(1);
1767dd7cddfSDavid du Colombier 
177bd389b36SDavid du Colombier 	if(serve)
1787dd7cddfSDavid du Colombier 		dnudpserver(mntpt);
1793e12c5d1SDavid du Colombier 	io();
1807dd7cddfSDavid du Colombier 	syslog(0, logfile, "io returned, exiting");
1813e12c5d1SDavid du Colombier 	exits(0);
1823e12c5d1SDavid du Colombier }
1833e12c5d1SDavid du Colombier 
1847dd7cddfSDavid du Colombier /*
1857dd7cddfSDavid du Colombier  *  if a mount point is specified, set the cs extention to be the mount point
1867dd7cddfSDavid du Colombier  *  with '_'s replacing '/'s
1877dd7cddfSDavid du Colombier  */
1883e12c5d1SDavid du Colombier void
1897dd7cddfSDavid du Colombier setext(char *ext, int n, char *p)
1907dd7cddfSDavid du Colombier {
1917dd7cddfSDavid du Colombier 	int i, c;
1927dd7cddfSDavid du Colombier 
1937dd7cddfSDavid du Colombier 	n--;
1947dd7cddfSDavid du Colombier 	for(i = 0; i < n; i++){
1957dd7cddfSDavid du Colombier 		c = p[i];
1967dd7cddfSDavid du Colombier 		if(c == 0)
1977dd7cddfSDavid du Colombier 			break;
1987dd7cddfSDavid du Colombier 		if(c == '/')
1997dd7cddfSDavid du Colombier 			c = '_';
2007dd7cddfSDavid du Colombier 		ext[i] = c;
2017dd7cddfSDavid du Colombier 	}
2027dd7cddfSDavid du Colombier 	ext[i] = 0;
2037dd7cddfSDavid du Colombier }
2047dd7cddfSDavid du Colombier 
2057dd7cddfSDavid du Colombier void
2067dd7cddfSDavid du Colombier mountinit(char *service, char *mntpt)
2073e12c5d1SDavid du Colombier {
2083e12c5d1SDavid du Colombier 	int f;
2093e12c5d1SDavid du Colombier 	int p[2];
2103e12c5d1SDavid du Colombier 	char buf[32];
2113e12c5d1SDavid du Colombier 
2123e12c5d1SDavid du Colombier 	if(pipe(p) < 0)
2137dd7cddfSDavid du Colombier 		abort(); /* "pipe failed" */;
214219b2ee8SDavid du Colombier 	switch(rfork(RFFDG|RFPROC|RFNAMEG)){
2153e12c5d1SDavid du Colombier 	case 0:
216219b2ee8SDavid du Colombier 		close(p[1]);
2173e12c5d1SDavid du Colombier 		break;
2183e12c5d1SDavid du Colombier 	case -1:
2197dd7cddfSDavid du Colombier 		abort(); /* "fork failed\n" */;
2203e12c5d1SDavid du Colombier 	default:
221219b2ee8SDavid du Colombier 		close(p[0]);
222219b2ee8SDavid du Colombier 
2233e12c5d1SDavid du Colombier 		/*
2243e12c5d1SDavid du Colombier 		 *  make a /srv/dns
2253e12c5d1SDavid du Colombier 		 */
2263e12c5d1SDavid du Colombier 		f = create(service, 1, 0666);
2273e12c5d1SDavid du Colombier 		if(f < 0)
2287dd7cddfSDavid du Colombier 			abort(); /* service */;
229bd389b36SDavid du Colombier 		snprint(buf, sizeof(buf), "%d", p[1]);
2303e12c5d1SDavid du Colombier 		if(write(f, buf, strlen(buf)) != strlen(buf))
2317dd7cddfSDavid du Colombier 			abort(); /* "write %s", service */;
2323e12c5d1SDavid du Colombier 		close(f);
2333e12c5d1SDavid du Colombier 
2343e12c5d1SDavid du Colombier 		/*
2353e12c5d1SDavid du Colombier 		 *  put ourselves into the file system
2363e12c5d1SDavid du Colombier 		 */
2379a747e4fSDavid du Colombier 		if(mount(p[1], -1, mntpt, MAFTER, "") < 0)
2389a747e4fSDavid du Colombier 			fprint(2, "dns mount failed: %r\n");
239219b2ee8SDavid du Colombier 		_exits(0);
2403e12c5d1SDavid du Colombier 	}
2413e12c5d1SDavid du Colombier 	mfd[0] = mfd[1] = p[0];
2423e12c5d1SDavid du Colombier }
2433e12c5d1SDavid du Colombier 
2443e12c5d1SDavid du Colombier Mfile*
2457dd7cddfSDavid du Colombier newfid(int fid, int needunused)
2463e12c5d1SDavid du Colombier {
2473e12c5d1SDavid du Colombier 	Mfile *mf;
2483e12c5d1SDavid du Colombier 
2497dd7cddfSDavid du Colombier 	lock(&mfalloc);
2507dd7cddfSDavid du Colombier 	for(mf = mfalloc.inuse; mf != nil; mf = mf->next){
2517dd7cddfSDavid du Colombier 		if(mf->fid == fid){
2527dd7cddfSDavid du Colombier 			unlock(&mfalloc);
2537dd7cddfSDavid du Colombier 			if(needunused)
2547dd7cddfSDavid du Colombier 				return nil;
2553e12c5d1SDavid du Colombier 			return mf;
2563e12c5d1SDavid du Colombier 		}
2573e12c5d1SDavid du Colombier 	}
2589a747e4fSDavid du Colombier 	mf = emalloc(sizeof(*mf));
2597dd7cddfSDavid du Colombier 	if(mf == nil)
2607dd7cddfSDavid du Colombier 		sysfatal("out of memory");
2613e12c5d1SDavid du Colombier 	mf->fid = fid;
2627dd7cddfSDavid du Colombier 	mf->next = mfalloc.inuse;
2637dd7cddfSDavid du Colombier 	mfalloc.inuse = mf;
2647dd7cddfSDavid du Colombier 	unlock(&mfalloc);
2653e12c5d1SDavid du Colombier 	return mf;
2663e12c5d1SDavid du Colombier }
2673e12c5d1SDavid du Colombier 
2683e12c5d1SDavid du Colombier void
2697dd7cddfSDavid du Colombier freefid(Mfile *mf)
2707dd7cddfSDavid du Colombier {
2717dd7cddfSDavid du Colombier 	Mfile **l;
2727dd7cddfSDavid du Colombier 
2737dd7cddfSDavid du Colombier 	lock(&mfalloc);
2747dd7cddfSDavid du Colombier 	for(l = &mfalloc.inuse; *l != nil; l = &(*l)->next){
2757dd7cddfSDavid du Colombier 		if(*l == mf){
2767dd7cddfSDavid du Colombier 			*l = mf->next;
2779a747e4fSDavid du Colombier 			if(mf->user)
2789a747e4fSDavid du Colombier 				free(mf->user);
2797dd7cddfSDavid du Colombier 			free(mf);
2807dd7cddfSDavid du Colombier 			unlock(&mfalloc);
2817dd7cddfSDavid du Colombier 			return;
2827dd7cddfSDavid du Colombier 		}
2837dd7cddfSDavid du Colombier 	}
2847dd7cddfSDavid du Colombier 	sysfatal("freeing unused fid");
2857dd7cddfSDavid du Colombier }
2867dd7cddfSDavid du Colombier 
2877dd7cddfSDavid du Colombier Mfile*
2887dd7cddfSDavid du Colombier copyfid(Mfile *mf, int fid)
2897dd7cddfSDavid du Colombier {
2907dd7cddfSDavid du Colombier 	Mfile *nmf;
2917dd7cddfSDavid du Colombier 
2927dd7cddfSDavid du Colombier 	nmf = newfid(fid, 1);
2937dd7cddfSDavid du Colombier 	if(nmf == nil)
2947dd7cddfSDavid du Colombier 		return nil;
2957dd7cddfSDavid du Colombier 	nmf->fid = fid;
2969a747e4fSDavid du Colombier 	nmf->user = estrdup(mf->user);
2979a747e4fSDavid du Colombier 	nmf->qid.type = mf->qid.type;
2987dd7cddfSDavid du Colombier 	nmf->qid.path = mf->qid.path;
2997dd7cddfSDavid du Colombier 	nmf->qid.vers = vers++;
3007dd7cddfSDavid du Colombier 	return nmf;
3017dd7cddfSDavid du Colombier }
3027dd7cddfSDavid du Colombier 
3037dd7cddfSDavid du Colombier Job*
3047dd7cddfSDavid du Colombier newjob(void)
3057dd7cddfSDavid du Colombier {
3067dd7cddfSDavid du Colombier 	Job *job;
3077dd7cddfSDavid du Colombier 
3089a747e4fSDavid du Colombier 	job = emalloc(sizeof(*job));
3097dd7cddfSDavid du Colombier 	lock(&joblock);
3107dd7cddfSDavid du Colombier 	job->next = joblist;
3117dd7cddfSDavid du Colombier 	joblist = job;
3127dd7cddfSDavid du Colombier 	job->request.tag = -1;
3137dd7cddfSDavid du Colombier 	unlock(&joblock);
3147dd7cddfSDavid du Colombier 	return job;
3157dd7cddfSDavid du Colombier }
3167dd7cddfSDavid du Colombier 
3177dd7cddfSDavid du Colombier void
3187dd7cddfSDavid du Colombier freejob(Job *job)
3197dd7cddfSDavid du Colombier {
3207dd7cddfSDavid du Colombier 	Job **l;
3217dd7cddfSDavid du Colombier 
3227dd7cddfSDavid du Colombier 	lock(&joblock);
3237dd7cddfSDavid du Colombier 	for(l = &joblist; *l; l = &(*l)->next){
3247dd7cddfSDavid du Colombier 		if((*l) == job){
3257dd7cddfSDavid du Colombier 			*l = job->next;
3267dd7cddfSDavid du Colombier 			free(job);
3277dd7cddfSDavid du Colombier 			break;
3287dd7cddfSDavid du Colombier 		}
3297dd7cddfSDavid du Colombier 	}
3307dd7cddfSDavid du Colombier 	unlock(&joblock);
3317dd7cddfSDavid du Colombier }
3327dd7cddfSDavid du Colombier 
3337dd7cddfSDavid du Colombier void
3347dd7cddfSDavid du Colombier flushjob(int tag)
3357dd7cddfSDavid du Colombier {
3367dd7cddfSDavid du Colombier 	Job *job;
3377dd7cddfSDavid du Colombier 
3387dd7cddfSDavid du Colombier 	lock(&joblock);
3397dd7cddfSDavid du Colombier 	for(job = joblist; job; job = job->next){
3407dd7cddfSDavid du Colombier 		if(job->request.tag == tag && job->request.type != Tflush){
3417dd7cddfSDavid du Colombier 			job->flushed = 1;
3427dd7cddfSDavid du Colombier 			break;
3437dd7cddfSDavid du Colombier 		}
3447dd7cddfSDavid du Colombier 	}
3457dd7cddfSDavid du Colombier 	unlock(&joblock);
3467dd7cddfSDavid du Colombier }
3477dd7cddfSDavid du Colombier 
3487dd7cddfSDavid du Colombier void
3493e12c5d1SDavid du Colombier io(void)
3503e12c5d1SDavid du Colombier {
3513e12c5d1SDavid du Colombier 	long n;
3523e12c5d1SDavid du Colombier 	Mfile *mf;
3539a747e4fSDavid du Colombier 	uchar mdata[IOHDRSZ + Maxfdata];
3543e12c5d1SDavid du Colombier 	Request req;
3557dd7cddfSDavid du Colombier 	Job *job;
3563e12c5d1SDavid du Colombier 
3573e12c5d1SDavid du Colombier 	/*
3583e12c5d1SDavid du Colombier 	 *  a slave process is sometimes forked to wait for replies from other
3593e12c5d1SDavid du Colombier 	 *  servers.  The master process returns immediately via a longjmp
360219b2ee8SDavid du Colombier 	 *  through 'mret'.
3613e12c5d1SDavid du Colombier 	 */
3627dd7cddfSDavid du Colombier 	if(setjmp(req.mret))
3637dd7cddfSDavid du Colombier 		putactivity();
3643e12c5d1SDavid du Colombier 	req.isslave = 0;
3657dd7cddfSDavid du Colombier 	for(;;){
3669a747e4fSDavid du Colombier 		n = read9pmsg(mfd[0], mdata, sizeof mdata);
3677dd7cddfSDavid du Colombier 		if(n<=0){
3687dd7cddfSDavid du Colombier 			syslog(0, logfile, "error reading mntpt: %r");
3697dd7cddfSDavid du Colombier 			exits(0);
3707dd7cddfSDavid du Colombier 		}
3717dd7cddfSDavid du Colombier 		job = newjob();
3729a747e4fSDavid du Colombier 		if(convM2S(mdata, n, &job->request) != n){
3737dd7cddfSDavid du Colombier 			freejob(job);
3747dd7cddfSDavid du Colombier 			continue;
3757dd7cddfSDavid du Colombier 		}
3767dd7cddfSDavid du Colombier 		mf = newfid(job->request.fid, 0);
377219b2ee8SDavid du Colombier 		if(debug)
3787dd7cddfSDavid du Colombier 			syslog(0, logfile, "%F", &job->request);
3797dd7cddfSDavid du Colombier 
3807dd7cddfSDavid du Colombier 		getactivity(&req);
3817dd7cddfSDavid du Colombier 		req.aborttime = now + 60;	/* don't spend more than 60 seconds */
3827dd7cddfSDavid du Colombier 
3837dd7cddfSDavid du Colombier 		switch(job->request.type){
3843e12c5d1SDavid du Colombier 		default:
3859a747e4fSDavid du Colombier 			syslog(1, logfile, "unknown request type %d", job->request.type);
3863e12c5d1SDavid du Colombier 			break;
3879a747e4fSDavid du Colombier 		case Tversion:
3889a747e4fSDavid du Colombier 			rversion(job);
3893e12c5d1SDavid du Colombier 			break;
3909a747e4fSDavid du Colombier 		case Tauth:
3919a747e4fSDavid du Colombier 			rauth(job);
3923e12c5d1SDavid du Colombier 			break;
3933e12c5d1SDavid du Colombier 		case Tflush:
3947dd7cddfSDavid du Colombier 			rflush(job);
3953e12c5d1SDavid du Colombier 			break;
3963e12c5d1SDavid du Colombier 		case Tattach:
3977dd7cddfSDavid du Colombier 			rattach(job, mf);
3983e12c5d1SDavid du Colombier 			break;
3993e12c5d1SDavid du Colombier 		case Twalk:
4007dd7cddfSDavid du Colombier 			rwalk(job, mf);
4013e12c5d1SDavid du Colombier 			break;
4023e12c5d1SDavid du Colombier 		case Topen:
4037dd7cddfSDavid du Colombier 			ropen(job, mf);
4043e12c5d1SDavid du Colombier 			break;
4053e12c5d1SDavid du Colombier 		case Tcreate:
4067dd7cddfSDavid du Colombier 			rcreate(job, mf);
4073e12c5d1SDavid du Colombier 			break;
4083e12c5d1SDavid du Colombier 		case Tread:
4097dd7cddfSDavid du Colombier 			rread(job, mf);
4103e12c5d1SDavid du Colombier 			break;
4113e12c5d1SDavid du Colombier 		case Twrite:
4127dd7cddfSDavid du Colombier 			rwrite(job, mf, &req);
4133e12c5d1SDavid du Colombier 			break;
4143e12c5d1SDavid du Colombier 		case Tclunk:
4157dd7cddfSDavid du Colombier 			rclunk(job, mf);
4163e12c5d1SDavid du Colombier 			break;
4173e12c5d1SDavid du Colombier 		case Tremove:
4187dd7cddfSDavid du Colombier 			rremove(job, mf);
4193e12c5d1SDavid du Colombier 			break;
4203e12c5d1SDavid du Colombier 		case Tstat:
4217dd7cddfSDavid du Colombier 			rstat(job, mf);
4223e12c5d1SDavid du Colombier 			break;
4233e12c5d1SDavid du Colombier 		case Twstat:
4247dd7cddfSDavid du Colombier 			rwstat(job, mf);
4253e12c5d1SDavid du Colombier 			break;
4263e12c5d1SDavid du Colombier 		}
4277dd7cddfSDavid du Colombier 
4287dd7cddfSDavid du Colombier 		freejob(job);
4297dd7cddfSDavid du Colombier 
4303e12c5d1SDavid du Colombier 		/*
4313e12c5d1SDavid du Colombier 		 *  slave processes die after replying
4323e12c5d1SDavid du Colombier 		 */
4337dd7cddfSDavid du Colombier 		if(req.isslave){
4347dd7cddfSDavid du Colombier 			putactivity();
4353e12c5d1SDavid du Colombier 			_exits(0);
4367dd7cddfSDavid du Colombier 		}
4377dd7cddfSDavid du Colombier 
4387dd7cddfSDavid du Colombier 		putactivity();
4397dd7cddfSDavid du Colombier 	}
4403e12c5d1SDavid du Colombier }
4413e12c5d1SDavid du Colombier 
4423e12c5d1SDavid du Colombier void
4439a747e4fSDavid du Colombier rversion(Job *job)
444219b2ee8SDavid du Colombier {
4459a747e4fSDavid du Colombier 	if(job->request.msize > IOHDRSZ + Maxfdata)
4469a747e4fSDavid du Colombier 		job->reply.msize = IOHDRSZ + Maxfdata;
4479a747e4fSDavid du Colombier 	else
4489a747e4fSDavid du Colombier 		job->reply.msize = job->request.msize;
4499a747e4fSDavid du Colombier 	if(strncmp(job->request.version, "9P2000", 6) != 0)
4509a747e4fSDavid du Colombier 		sendmsg(job, "unknown 9P version");
4519a747e4fSDavid du Colombier 	else{
4529a747e4fSDavid du Colombier 		job->reply.version = "9P2000";
4537dd7cddfSDavid du Colombier 		sendmsg(job, 0);
454219b2ee8SDavid du Colombier 	}
4559a747e4fSDavid du Colombier }
456219b2ee8SDavid du Colombier 
457219b2ee8SDavid du Colombier void
4589a747e4fSDavid du Colombier rauth(Job *job)
4593e12c5d1SDavid du Colombier {
460*3ff48bf5SDavid du Colombier 	sendmsg(job, "dns: authentication not required");
4617dd7cddfSDavid du Colombier }
4627dd7cddfSDavid du Colombier 
4639a747e4fSDavid du Colombier /*
4649a747e4fSDavid du Colombier  *  don't flush till all the slaves are done
4659a747e4fSDavid du Colombier  */
4667dd7cddfSDavid du Colombier void
4677dd7cddfSDavid du Colombier rflush(Job *job)
4687dd7cddfSDavid du Colombier {
4697dd7cddfSDavid du Colombier 	flushjob(job->request.oldtag);
4707dd7cddfSDavid du Colombier 	sendmsg(job, 0);
4713e12c5d1SDavid du Colombier }
4723e12c5d1SDavid du Colombier 
4733e12c5d1SDavid du Colombier void
4747dd7cddfSDavid du Colombier rattach(Job *job, Mfile *mf)
4753e12c5d1SDavid du Colombier {
4769a747e4fSDavid du Colombier 	if(mf->user != nil)
4779a747e4fSDavid du Colombier 		free(mf->user);
4789a747e4fSDavid du Colombier 	mf->user = estrdup(job->request.uname);
4793e12c5d1SDavid du Colombier 	mf->qid.vers = vers++;
4809a747e4fSDavid du Colombier 	mf->qid.type = QTDIR;
4819a747e4fSDavid du Colombier 	mf->qid.path = 0LL;
4827dd7cddfSDavid du Colombier 	job->reply.qid = mf->qid;
4837dd7cddfSDavid du Colombier 	sendmsg(job, 0);
4843e12c5d1SDavid du Colombier }
4853e12c5d1SDavid du Colombier 
4863e12c5d1SDavid du Colombier char*
4877dd7cddfSDavid du Colombier rwalk(Job *job, Mfile *mf)
4883e12c5d1SDavid du Colombier {
4893e12c5d1SDavid du Colombier 	char *err;
4909a747e4fSDavid du Colombier 	char **elems;
4919a747e4fSDavid du Colombier 	int nelems;
4929a747e4fSDavid du Colombier 	int i;
4939a747e4fSDavid du Colombier 	Mfile *nmf;
4949a747e4fSDavid du Colombier 	Qid qid;
4953e12c5d1SDavid du Colombier 
4963e12c5d1SDavid du Colombier 	err = 0;
4979a747e4fSDavid du Colombier 	nmf = nil;
4989a747e4fSDavid du Colombier 	elems = job->request.wname;
4999a747e4fSDavid du Colombier 	nelems = job->request.nwname;
5009a747e4fSDavid du Colombier 	job->reply.nwqid = 0;
5019a747e4fSDavid du Colombier 
5029a747e4fSDavid du Colombier 	if(job->request.newfid != job->request.fid){
5039a747e4fSDavid du Colombier 		/* clone fid */
5049a747e4fSDavid du Colombier 		if(job->request.newfid<0){
5059a747e4fSDavid du Colombier 			err = "clone newfid out of range";
5069a747e4fSDavid du Colombier 			goto send;
5079a747e4fSDavid du Colombier 		}
5089a747e4fSDavid du Colombier 		nmf = copyfid(mf, job->request.newfid);
5099a747e4fSDavid du Colombier 		if(nmf == nil){
5109a747e4fSDavid du Colombier 			err = "clone bad newfid";
5119a747e4fSDavid du Colombier 			goto send;
5129a747e4fSDavid du Colombier 		}
5139a747e4fSDavid du Colombier 		mf = nmf;
5149a747e4fSDavid du Colombier 	}
5159a747e4fSDavid du Colombier 	/* else nmf will be nil */
5169a747e4fSDavid du Colombier 
5179a747e4fSDavid du Colombier 	qid = mf->qid;
5189a747e4fSDavid du Colombier 	if(nelems > 0){
5199a747e4fSDavid du Colombier 		/* walk fid */
5209a747e4fSDavid du Colombier 		for(i=0; i<nelems && i<MAXWELEM; i++){
5219a747e4fSDavid du Colombier 			if((qid.type & QTDIR) == 0){
5223e12c5d1SDavid du Colombier 				err = "not a directory";
5239a747e4fSDavid du Colombier 				break;
5243e12c5d1SDavid du Colombier 			}
5259a747e4fSDavid du Colombier 			if(strcmp(elems[i], "..") == 0 || strcmp(elems[i], ".") == 0){
5269a747e4fSDavid du Colombier 				qid.type = QTDIR;
5279a747e4fSDavid du Colombier 				qid.path = Qdir;
5289a747e4fSDavid du Colombier     Found:
5299a747e4fSDavid du Colombier 				job->reply.wqid[i] = qid;
5309a747e4fSDavid du Colombier 				job->reply.nwqid++;
5319a747e4fSDavid du Colombier 				continue;
5323e12c5d1SDavid du Colombier 			}
5339a747e4fSDavid du Colombier 			if(strcmp(elems[i], "dns") == 0){
5349a747e4fSDavid du Colombier 				qid.type = QTFILE;
5359a747e4fSDavid du Colombier 				qid.path = Qdns;
5369a747e4fSDavid du Colombier 				goto Found;
5373e12c5d1SDavid du Colombier 			}
5389a747e4fSDavid du Colombier 			err = "file does not exist";
5399a747e4fSDavid du Colombier 			break;
5409a747e4fSDavid du Colombier 		}
5419a747e4fSDavid du Colombier 	}
5429a747e4fSDavid du Colombier 
5433e12c5d1SDavid du Colombier     send:
5449a747e4fSDavid du Colombier 	if(nmf != nil && (err!=nil || job->reply.nwqid<nelems))
5459a747e4fSDavid du Colombier 		freefid(nmf);
5469a747e4fSDavid du Colombier 	if(err == nil)
5479a747e4fSDavid du Colombier 		mf->qid = qid;
5487dd7cddfSDavid du Colombier 	sendmsg(job, err);
5493e12c5d1SDavid du Colombier 	return err;
5503e12c5d1SDavid du Colombier }
5513e12c5d1SDavid du Colombier 
5523e12c5d1SDavid du Colombier void
5537dd7cddfSDavid du Colombier ropen(Job *job, Mfile *mf)
5543e12c5d1SDavid du Colombier {
5553e12c5d1SDavid du Colombier 	int mode;
5563e12c5d1SDavid du Colombier 	char *err;
5573e12c5d1SDavid du Colombier 
5583e12c5d1SDavid du Colombier 	err = 0;
5597dd7cddfSDavid du Colombier 	mode = job->request.mode;
5609a747e4fSDavid du Colombier 	if(mf->qid.type & QTDIR){
5613e12c5d1SDavid du Colombier 		if(mode)
5623e12c5d1SDavid du Colombier 			err = "permission denied";
5633e12c5d1SDavid du Colombier 	}
5647dd7cddfSDavid du Colombier 	job->reply.qid = mf->qid;
5659a747e4fSDavid du Colombier 	job->reply.iounit = 0;
5667dd7cddfSDavid du Colombier 	sendmsg(job, err);
5673e12c5d1SDavid du Colombier }
5683e12c5d1SDavid du Colombier 
5693e12c5d1SDavid du Colombier void
5707dd7cddfSDavid du Colombier rcreate(Job *job, Mfile *mf)
5713e12c5d1SDavid du Colombier {
5723e12c5d1SDavid du Colombier 	USED(mf);
5737dd7cddfSDavid du Colombier 	sendmsg(job, "creation permission denied");
5743e12c5d1SDavid du Colombier }
5753e12c5d1SDavid du Colombier 
5763e12c5d1SDavid du Colombier void
5777dd7cddfSDavid du Colombier rread(Job *job, Mfile *mf)
5783e12c5d1SDavid du Colombier {
5797dd7cddfSDavid du Colombier 	int i, n, cnt;
5807dd7cddfSDavid du Colombier 	long off;
5813e12c5d1SDavid du Colombier 	Dir dir;
5829a747e4fSDavid du Colombier 	uchar buf[Maxfdata];
5833e12c5d1SDavid du Colombier 	char *err;
5849a747e4fSDavid du Colombier 	long clock;
5853e12c5d1SDavid du Colombier 
5863e12c5d1SDavid du Colombier 	n = 0;
5873e12c5d1SDavid du Colombier 	err = 0;
5887dd7cddfSDavid du Colombier 	off = job->request.offset;
5897dd7cddfSDavid du Colombier 	cnt = job->request.count;
5909a747e4fSDavid du Colombier 	if(mf->qid.type & QTDIR){
5919a747e4fSDavid du Colombier 		clock = time(0);
5923e12c5d1SDavid du Colombier 		if(off == 0){
5939a747e4fSDavid du Colombier 			dir.name = "dns";
5949a747e4fSDavid du Colombier 			dir.qid.type = QTFILE;
5953e12c5d1SDavid du Colombier 			dir.qid.vers = vers;
5963e12c5d1SDavid du Colombier 			dir.qid.path = Qdns;
5973e12c5d1SDavid du Colombier 			dir.mode = 0666;
5983e12c5d1SDavid du Colombier 			dir.length = 0;
5999a747e4fSDavid du Colombier 			dir.uid = mf->user;
6009a747e4fSDavid du Colombier 			dir.gid = mf->user;
6019a747e4fSDavid du Colombier 			dir.muid = mf->user;
6029a747e4fSDavid du Colombier 			dir.atime = clock;	/* wrong */
6039a747e4fSDavid du Colombier 			dir.mtime = clock;	/* wrong */
6049a747e4fSDavid du Colombier 			n = convD2M(&dir, buf, sizeof buf);
6053e12c5d1SDavid du Colombier 		}
6069a747e4fSDavid du Colombier 		job->reply.data = (char*)buf;
6073e12c5d1SDavid du Colombier 	} else {
6087dd7cddfSDavid du Colombier 		for(i = 1; i <= mf->nrr; i++)
6097dd7cddfSDavid du Colombier 			if(mf->rr[i] > off)
6103e12c5d1SDavid du Colombier 				break;
6117dd7cddfSDavid du Colombier 		if(i > mf->nrr)
6127dd7cddfSDavid du Colombier 			goto send;
6137dd7cddfSDavid du Colombier 		if(off + cnt > mf->rr[i])
6147dd7cddfSDavid du Colombier 			n = mf->rr[i] - off;
6157dd7cddfSDavid du Colombier 		else
6167dd7cddfSDavid du Colombier 			n = cnt;
6177dd7cddfSDavid du Colombier 		job->reply.data = mf->reply + off;
6183e12c5d1SDavid du Colombier 	}
6193e12c5d1SDavid du Colombier send:
6207dd7cddfSDavid du Colombier 	job->reply.count = n;
6217dd7cddfSDavid du Colombier 	sendmsg(job, err);
6223e12c5d1SDavid du Colombier }
6233e12c5d1SDavid du Colombier 
6243e12c5d1SDavid du Colombier void
6257dd7cddfSDavid du Colombier rwrite(Job *job, Mfile *mf, Request *req)
6263e12c5d1SDavid du Colombier {
6277dd7cddfSDavid du Colombier 	int cnt, rooted, status;
6287dd7cddfSDavid du Colombier 	long n;
6297dd7cddfSDavid du Colombier 	char *err, *p, *atype;
6307dd7cddfSDavid du Colombier 	RR *rp, *tp, *neg;
6317dd7cddfSDavid du Colombier 	int wantsav;
6323e12c5d1SDavid du Colombier 
6333e12c5d1SDavid du Colombier 	err = 0;
6347dd7cddfSDavid du Colombier 	cnt = job->request.count;
6359a747e4fSDavid du Colombier 	if(mf->qid.type & QTDIR){
6363e12c5d1SDavid du Colombier 		err = "can't write directory";
6373e12c5d1SDavid du Colombier 		goto send;
6383e12c5d1SDavid du Colombier 	}
6393e12c5d1SDavid du Colombier 	if(cnt >= Maxrequest){
6403e12c5d1SDavid du Colombier 		err = "request too long";
6413e12c5d1SDavid du Colombier 		goto send;
6423e12c5d1SDavid du Colombier 	}
6437dd7cddfSDavid du Colombier 	job->request.data[cnt] = 0;
6447dd7cddfSDavid du Colombier 	if(cnt > 0 && job->request.data[cnt-1] == '\n')
6457dd7cddfSDavid du Colombier 		job->request.data[cnt-1] = 0;
6463e12c5d1SDavid du Colombier 
6473e12c5d1SDavid du Colombier 	/*
6487dd7cddfSDavid du Colombier 	 *  special commands
649219b2ee8SDavid du Colombier 	 */
6507dd7cddfSDavid du Colombier 	if(strncmp(job->request.data, "debug", 5)==0 && job->request.data[5] == 0){
651219b2ee8SDavid du Colombier 		debug ^= 1;
652219b2ee8SDavid du Colombier 		goto send;
6537dd7cddfSDavid du Colombier 	} else if(strncmp(job->request.data, "dump", 4)==0 && job->request.data[4] == 0){
654219b2ee8SDavid du Colombier 		dndump("/lib/ndb/dnsdump");
655219b2ee8SDavid du Colombier 		goto send;
6567dd7cddfSDavid du Colombier 	} else if(strncmp(job->request.data, "refresh", 7)==0 && job->request.data[7] == 0){
6577dd7cddfSDavid du Colombier 		needrefresh = 1;
6587dd7cddfSDavid du Colombier 		goto send;
6599a747e4fSDavid du Colombier 	} else if(strncmp(job->request.data, "poolcheck", 9)==0 && job->request.data[9] == 0){
6609a747e4fSDavid du Colombier 		poolcheck(mainmem);
6619a747e4fSDavid du Colombier 		goto send;
662219b2ee8SDavid du Colombier 	}
663219b2ee8SDavid du Colombier 
664219b2ee8SDavid du Colombier 	/*
6657dd7cddfSDavid du Colombier 	 *  kill previous reply
6667dd7cddfSDavid du Colombier 	 */
6677dd7cddfSDavid du Colombier 	mf->nrr = 0;
6687dd7cddfSDavid du Colombier 	mf->rr[0] = 0;
6697dd7cddfSDavid du Colombier 
6707dd7cddfSDavid du Colombier 	/*
6713e12c5d1SDavid du Colombier 	 *  break up request (into a name and a type)
6723e12c5d1SDavid du Colombier 	 */
6737dd7cddfSDavid du Colombier 	atype = strchr(job->request.data, ' ');
6743e12c5d1SDavid du Colombier 	if(atype == 0){
6753e12c5d1SDavid du Colombier 		err = "illegal request";
6763e12c5d1SDavid du Colombier 		goto send;
6773e12c5d1SDavid du Colombier 	} else
6783e12c5d1SDavid du Colombier 		*atype++ = 0;
6793e12c5d1SDavid du Colombier 
6807dd7cddfSDavid du Colombier 	/*
6817dd7cddfSDavid du Colombier 	 *  tracing request
6827dd7cddfSDavid du Colombier 	 */
6837dd7cddfSDavid du Colombier 	if(strcmp(atype, "trace") == 0){
6847dd7cddfSDavid du Colombier 		if(trace)
6857dd7cddfSDavid du Colombier 			free(trace);
6867dd7cddfSDavid du Colombier 		if(*job->request.data)
6879a747e4fSDavid du Colombier 			trace = estrdup(job->request.data);
6887dd7cddfSDavid du Colombier 		else
6897dd7cddfSDavid du Colombier 			trace = 0;
6907dd7cddfSDavid du Colombier 		goto send;
6917dd7cddfSDavid du Colombier 	}
6927dd7cddfSDavid du Colombier 
6933e12c5d1SDavid du Colombier 	mf->type = rrtype(atype);
6943e12c5d1SDavid du Colombier 	if(mf->type < 0){
6953e12c5d1SDavid du Colombier 		err = "unknown type";
6963e12c5d1SDavid du Colombier 		goto send;
6973e12c5d1SDavid du Colombier 	}
6983e12c5d1SDavid du Colombier 
6997dd7cddfSDavid du Colombier 	p = atype - 2;
7007dd7cddfSDavid du Colombier 	if(p >= job->request.data && *p == '.'){
7017dd7cddfSDavid du Colombier 		rooted = 1;
7027dd7cddfSDavid du Colombier 		*p = 0;
7037dd7cddfSDavid du Colombier 	} else
7047dd7cddfSDavid du Colombier 		rooted = 0;
7053e12c5d1SDavid du Colombier 
7067dd7cddfSDavid du Colombier 	p = job->request.data;
7077dd7cddfSDavid du Colombier 	if(*p == '!'){
7087dd7cddfSDavid du Colombier 		wantsav = 1;
7097dd7cddfSDavid du Colombier 		p++;
7107dd7cddfSDavid du Colombier 	} else
7117dd7cddfSDavid du Colombier 		wantsav = 0;
7129a747e4fSDavid du Colombier 	dncheck(0, 1);
7137dd7cddfSDavid du Colombier 	rp = dnresolve(p, Cin, mf->type, req, 0, 0, Recurse, rooted, &status);
7149a747e4fSDavid du Colombier 	dncheck(0, 1);
7157dd7cddfSDavid du Colombier 	neg = rrremneg(&rp);
7167dd7cddfSDavid du Colombier 	if(neg){
7177dd7cddfSDavid du Colombier 		status = neg->negrcode;
7187dd7cddfSDavid du Colombier 		rrfreelist(neg);
7197dd7cddfSDavid du Colombier 	}
7207dd7cddfSDavid du Colombier 	if(rp == 0){
7217dd7cddfSDavid du Colombier 		if(status == Rname)
7227dd7cddfSDavid du Colombier 			err = "name does not exist";
7237dd7cddfSDavid du Colombier 		else
7247dd7cddfSDavid du Colombier 			err = "no translation found";
7257dd7cddfSDavid du Colombier 	} else {
7267dd7cddfSDavid du Colombier 		/* format data to be read later */
7277dd7cddfSDavid du Colombier 		n = 0;
7287dd7cddfSDavid du Colombier 		mf->nrr = 0;
7297dd7cddfSDavid du Colombier 		for(tp = rp; mf->nrr < Maxrrr-1 && n < Maxreply && tp &&
7307dd7cddfSDavid du Colombier 				tsame(mf->type, tp->type); tp = tp->next){
7317dd7cddfSDavid du Colombier 			mf->rr[mf->nrr++] = n;
7327dd7cddfSDavid du Colombier 			if(wantsav)
7337dd7cddfSDavid du Colombier 				n += snprint(mf->reply+n, Maxreply-n, "%Q", tp);
7347dd7cddfSDavid du Colombier 			else
7357dd7cddfSDavid du Colombier 				n += snprint(mf->reply+n, Maxreply-n, "%R", tp);
7367dd7cddfSDavid du Colombier 		}
7377dd7cddfSDavid du Colombier 		mf->rr[mf->nrr] = n;
7387dd7cddfSDavid du Colombier 		rrfreelist(rp);
7397dd7cddfSDavid du Colombier 	}
7403e12c5d1SDavid du Colombier 
7413e12c5d1SDavid du Colombier     send:
7429a747e4fSDavid du Colombier 	dncheck(0, 1);
7437dd7cddfSDavid du Colombier 	job->reply.count = cnt;
7447dd7cddfSDavid du Colombier 	sendmsg(job, err);
7453e12c5d1SDavid du Colombier }
7463e12c5d1SDavid du Colombier 
7473e12c5d1SDavid du Colombier void
7487dd7cddfSDavid du Colombier rclunk(Job *job, Mfile *mf)
7493e12c5d1SDavid du Colombier {
7507dd7cddfSDavid du Colombier 	freefid(mf);
7517dd7cddfSDavid du Colombier 	sendmsg(job, 0);
7523e12c5d1SDavid du Colombier }
7533e12c5d1SDavid du Colombier 
7543e12c5d1SDavid du Colombier void
7557dd7cddfSDavid du Colombier rremove(Job *job, Mfile *mf)
7563e12c5d1SDavid du Colombier {
7573e12c5d1SDavid du Colombier 	USED(mf);
7587dd7cddfSDavid du Colombier 	sendmsg(job, "remove permission denied");
7593e12c5d1SDavid du Colombier }
7603e12c5d1SDavid du Colombier 
7613e12c5d1SDavid du Colombier void
7627dd7cddfSDavid du Colombier rstat(Job *job, Mfile *mf)
7633e12c5d1SDavid du Colombier {
7643e12c5d1SDavid du Colombier 	Dir dir;
7659a747e4fSDavid du Colombier 	uchar buf[IOHDRSZ+Maxfdata];
7663e12c5d1SDavid du Colombier 
7679a747e4fSDavid du Colombier 	if(mf->qid.type & QTDIR){
7689a747e4fSDavid du Colombier 		dir.name = ".";
7699a747e4fSDavid du Colombier 		dir.mode = DMDIR|0555;
770219b2ee8SDavid du Colombier 	} else {
7719a747e4fSDavid du Colombier 		dir.name = "dns";
7723e12c5d1SDavid du Colombier 		dir.mode = 0666;
773219b2ee8SDavid du Colombier 	}
774219b2ee8SDavid du Colombier 	dir.qid = mf->qid;
7753e12c5d1SDavid du Colombier 	dir.length = 0;
7769a747e4fSDavid du Colombier 	dir.uid = mf->user;
7779a747e4fSDavid du Colombier 	dir.gid = mf->user;
7789a747e4fSDavid du Colombier 	dir.muid = mf->user;
7793e12c5d1SDavid du Colombier 	dir.atime = dir.mtime = time(0);
7809a747e4fSDavid du Colombier 	job->reply.nstat = convD2M(&dir, buf, sizeof buf);
7819a747e4fSDavid du Colombier 	job->reply.stat = buf;
7827dd7cddfSDavid du Colombier 	sendmsg(job, 0);
7833e12c5d1SDavid du Colombier }
7843e12c5d1SDavid du Colombier 
7853e12c5d1SDavid du Colombier void
7867dd7cddfSDavid du Colombier rwstat(Job *job, Mfile *mf)
7873e12c5d1SDavid du Colombier {
7883e12c5d1SDavid du Colombier 	USED(mf);
7897dd7cddfSDavid du Colombier 	sendmsg(job, "wstat permission denied");
7903e12c5d1SDavid du Colombier }
7913e12c5d1SDavid du Colombier 
7923e12c5d1SDavid du Colombier void
7937dd7cddfSDavid du Colombier sendmsg(Job *job, char *err)
7943e12c5d1SDavid du Colombier {
7953e12c5d1SDavid du Colombier 	int n;
7969a747e4fSDavid du Colombier 	uchar mdata[IOHDRSZ + Maxfdata];
7979a747e4fSDavid du Colombier 	char ename[ERRMAX];
7983e12c5d1SDavid du Colombier 
7993e12c5d1SDavid du Colombier 	if(err){
8007dd7cddfSDavid du Colombier 		job->reply.type = Rerror;
8019a747e4fSDavid du Colombier 		snprint(ename, sizeof(ename), "dns: %s", err);
8029a747e4fSDavid du Colombier 		job->reply.ename = ename;
8033e12c5d1SDavid du Colombier 	}else{
8047dd7cddfSDavid du Colombier 		job->reply.type = job->request.type+1;
8053e12c5d1SDavid du Colombier 	}
8067dd7cddfSDavid du Colombier 	job->reply.tag = job->request.tag;
8079a747e4fSDavid du Colombier 	n = convS2M(&job->reply, mdata, sizeof mdata);
8089a747e4fSDavid du Colombier 	if(n == 0){
8099a747e4fSDavid du Colombier 		syslog(1, logfile, "sendmsg convS2M of %F returns 0", &job->reply);
8109a747e4fSDavid du Colombier 		abort();
8113e12c5d1SDavid du Colombier 	}
8129a747e4fSDavid du Colombier 	lock(&joblock);
8139a747e4fSDavid du Colombier 	if(job->flushed == 0)
8149a747e4fSDavid du Colombier 		if(write(mfd[1], mdata, n)!=n)
8159a747e4fSDavid du Colombier 			sysfatal("mount write");
8167dd7cddfSDavid du Colombier 	unlock(&joblock);
8179a747e4fSDavid du Colombier 	if(debug)
8189a747e4fSDavid du Colombier 		syslog(0, logfile, "%F %d", &job->reply, n);
8193e12c5d1SDavid du Colombier }
8203e12c5d1SDavid du Colombier 
8213e12c5d1SDavid du Colombier /*
8227dd7cddfSDavid du Colombier  *  the following varies between dnsdebug and dns
8233e12c5d1SDavid du Colombier  */
8243e12c5d1SDavid du Colombier void
8257dd7cddfSDavid du Colombier logreply(int id, uchar *addr, DNSmsg *mp)
8263e12c5d1SDavid du Colombier {
8277dd7cddfSDavid du Colombier 	RR *rp;
8283e12c5d1SDavid du Colombier 
8297dd7cddfSDavid du Colombier 	syslog(0, LOG, "%d: rcvd %I flags:%s%s%s%s%s", id, addr,
8307dd7cddfSDavid du Colombier 		mp->flags & Fauth ? " auth" : "",
8317dd7cddfSDavid du Colombier 		mp->flags & Ftrunc ? " trunc" : "",
8327dd7cddfSDavid du Colombier 		mp->flags & Frecurse ? " rd" : "",
8337dd7cddfSDavid du Colombier 		mp->flags & Fcanrec ? " ra" : "",
8347dd7cddfSDavid du Colombier 		mp->flags & (Fauth|Rname) == (Fauth|Rname) ?
8357dd7cddfSDavid du Colombier 		" nx" : "");
8367dd7cddfSDavid du Colombier 	for(rp = mp->qd; rp != nil; rp = rp->next)
8377dd7cddfSDavid du Colombier 		syslog(0, LOG, "%d: rcvd %I qd %s", id, addr, rp->owner->name);
8387dd7cddfSDavid du Colombier 	for(rp = mp->an; rp != nil; rp = rp->next)
8397dd7cddfSDavid du Colombier 		syslog(0, LOG, "%d: rcvd %I an %R", id, addr, rp);
8407dd7cddfSDavid du Colombier 	for(rp = mp->ns; rp != nil; rp = rp->next)
8417dd7cddfSDavid du Colombier 		syslog(0, LOG, "%d: rcvd %I ns %R", id, addr, rp);
8427dd7cddfSDavid du Colombier 	for(rp = mp->ar; rp != nil; rp = rp->next)
8437dd7cddfSDavid du Colombier 		syslog(0, LOG, "%d: rcvd %I ar %R", id, addr, rp);
8443e12c5d1SDavid du Colombier }
8457dd7cddfSDavid du Colombier 
8467dd7cddfSDavid du Colombier void
8477dd7cddfSDavid du Colombier logsend(int id, int subid, uchar *addr, char *sname, char *rname, int type)
8487dd7cddfSDavid du Colombier {
8497dd7cddfSDavid du Colombier 	char buf[12];
8507dd7cddfSDavid du Colombier 
8517dd7cddfSDavid du Colombier 	syslog(0, LOG, "%d.%d: sending to %I/%s %s %s",
8529a747e4fSDavid du Colombier 		id, subid, addr, sname, rname, rrname(type, buf, sizeof buf));
8537dd7cddfSDavid du Colombier }
8547dd7cddfSDavid du Colombier 
8557dd7cddfSDavid du Colombier RR*
8567dd7cddfSDavid du Colombier getdnsservers(int class)
8577dd7cddfSDavid du Colombier {
8587dd7cddfSDavid du Colombier 	return dnsservers(class);
8593e12c5d1SDavid du Colombier }
860