xref: /plan9/sys/src/cmd/ndb/dns.c (revision 7dd7cddf99dd7472612f1413b4da293630e6b1bc)
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>
7*7dd7cddfSDavid du Colombier #include <ip.h>
83e12c5d1SDavid du Colombier #include "dns.h"
93e12c5d1SDavid du Colombier 
103e12c5d1SDavid du Colombier enum
113e12c5d1SDavid du Colombier {
123e12c5d1SDavid du Colombier 	Maxrequest=		4*NAMELEN,
133e12c5d1SDavid du Colombier 	Ncache=			8,
14*7dd7cddfSDavid du Colombier 	Maxpath=		128,
15*7dd7cddfSDavid du Colombier 	Maxreply=		512,
16*7dd7cddfSDavid du Colombier 	Maxrrr=			16,
173e12c5d1SDavid du Colombier 
183e12c5d1SDavid du Colombier 	Qdns=			1,
193e12c5d1SDavid du Colombier };
203e12c5d1SDavid du Colombier 
213e12c5d1SDavid du Colombier typedef struct Mfile	Mfile;
22*7dd7cddfSDavid du Colombier typedef struct Job	Job;
233e12c5d1SDavid du Colombier typedef struct Network	Network;
243e12c5d1SDavid du Colombier 
253e12c5d1SDavid du Colombier int vers;		/* incremented each clone/attach */
263e12c5d1SDavid du Colombier 
273e12c5d1SDavid du Colombier struct Mfile
283e12c5d1SDavid du Colombier {
29*7dd7cddfSDavid du Colombier 	Mfile		*next;		/* next free mfile */
30*7dd7cddfSDavid du Colombier 
313e12c5d1SDavid du Colombier 	char		user[NAMELEN];
323e12c5d1SDavid du Colombier 	Qid		qid;
333e12c5d1SDavid du Colombier 	int		fid;
343e12c5d1SDavid du Colombier 
353e12c5d1SDavid du Colombier 	int		type;		/* reply type */
36*7dd7cddfSDavid du Colombier 	char		reply[Maxreply];
37*7dd7cddfSDavid du Colombier 	ushort		rr[Maxrrr];	/* offset of rr's */
38*7dd7cddfSDavid du Colombier 	ushort		nrr;		/* number of rr's */
393e12c5d1SDavid du Colombier };
403e12c5d1SDavid du Colombier 
41*7dd7cddfSDavid du Colombier //
42*7dd7cddfSDavid du Colombier //  active local requests
43*7dd7cddfSDavid du Colombier //
44*7dd7cddfSDavid du Colombier struct Job
45*7dd7cddfSDavid du Colombier {
46*7dd7cddfSDavid du Colombier 	Job	*next;
47*7dd7cddfSDavid du Colombier 	int	flushed;
48*7dd7cddfSDavid du Colombier 	Fcall	request;
49*7dd7cddfSDavid du Colombier 	Fcall	reply;
50*7dd7cddfSDavid du Colombier };
51*7dd7cddfSDavid du Colombier Lock	joblock;
52*7dd7cddfSDavid du Colombier Job	*joblist;
53*7dd7cddfSDavid du Colombier 
54*7dd7cddfSDavid du Colombier struct {
55*7dd7cddfSDavid du Colombier 	Lock;
56*7dd7cddfSDavid du Colombier 	Mfile	*inuse;		/* active mfile's */
57*7dd7cddfSDavid du Colombier } mfalloc;
58*7dd7cddfSDavid du Colombier 
593e12c5d1SDavid du Colombier int	mfd[2];
603e12c5d1SDavid du Colombier char	user[NAMELEN];
613e12c5d1SDavid du Colombier int	debug;
62*7dd7cddfSDavid du Colombier int	cachedb;
63*7dd7cddfSDavid du Colombier ulong	now;
64*7dd7cddfSDavid du Colombier int	testing;
65*7dd7cddfSDavid du Colombier char	*trace;
66*7dd7cddfSDavid du Colombier int	needrefresh;
67*7dd7cddfSDavid du Colombier int	resolver;
68*7dd7cddfSDavid du Colombier uchar	ipaddr[IPaddrlen];	/* my ip address */
69*7dd7cddfSDavid du Colombier int	maxage;
703e12c5d1SDavid du Colombier 
71*7dd7cddfSDavid du Colombier void	rsession(Job*);
72*7dd7cddfSDavid du Colombier void	rsimple(Job*);
73*7dd7cddfSDavid du Colombier void	rflush(Job*);
74*7dd7cddfSDavid du Colombier void	rattach(Job*, Mfile*);
75*7dd7cddfSDavid du Colombier void	rclone(Job*, Mfile*);
76*7dd7cddfSDavid du Colombier char*	rwalk(Job*, Mfile*);
77*7dd7cddfSDavid du Colombier void	rclwalk(Job*, Mfile*);
78*7dd7cddfSDavid du Colombier void	ropen(Job*, Mfile*);
79*7dd7cddfSDavid du Colombier void	rcreate(Job*, Mfile*);
80*7dd7cddfSDavid du Colombier void	rread(Job*, Mfile*);
81*7dd7cddfSDavid du Colombier void	rwrite(Job*, Mfile*, Request*);
82*7dd7cddfSDavid du Colombier void	rclunk(Job*, Mfile*);
83*7dd7cddfSDavid du Colombier void	rremove(Job*, Mfile*);
84*7dd7cddfSDavid du Colombier void	rstat(Job*, Mfile*);
85*7dd7cddfSDavid du Colombier void	rauth(Job*);
86*7dd7cddfSDavid du Colombier void	rwstat(Job*, Mfile*);
87*7dd7cddfSDavid du Colombier void	sendmsg(Job*, char*);
88*7dd7cddfSDavid du Colombier void	mountinit(char*, char*);
893e12c5d1SDavid du Colombier void	io(void);
903e12c5d1SDavid du Colombier int	fillreply(Mfile*, int);
91*7dd7cddfSDavid du Colombier Job*	newjob(void);
92*7dd7cddfSDavid du Colombier void	freejob(Job*);
93*7dd7cddfSDavid du Colombier void	setext(char*, int, char*);
943e12c5d1SDavid du Colombier 
953e12c5d1SDavid du Colombier char *mname[]={
963e12c5d1SDavid du Colombier 	[Tnop]		"Tnop",
973e12c5d1SDavid du Colombier 	[Tsession]	"Tsession",
983e12c5d1SDavid du Colombier 	[Tflush]	"Tflush",
993e12c5d1SDavid du Colombier 	[Tattach]	"Tattach",
1003e12c5d1SDavid du Colombier 	[Tclone]	"Tclone",
1013e12c5d1SDavid du Colombier 	[Twalk]		"Twalk",
1023e12c5d1SDavid du Colombier 	[Topen]		"Topen",
1033e12c5d1SDavid du Colombier 	[Tcreate]	"Tcreate",
1043e12c5d1SDavid du Colombier 	[Tclunk]	"Tclunk",
1053e12c5d1SDavid du Colombier 	[Tread]		"Tread",
1063e12c5d1SDavid du Colombier 	[Twrite]	"Twrite",
1073e12c5d1SDavid du Colombier 	[Tremove]	"Tremove",
1083e12c5d1SDavid du Colombier 	[Tstat]		"Tstat",
1093e12c5d1SDavid du Colombier 	[Twstat]	"Twstat",
1103e12c5d1SDavid du Colombier 			0,
1113e12c5d1SDavid du Colombier };
1123e12c5d1SDavid du Colombier 
113219b2ee8SDavid du Colombier char	*logfile = "dns";
114219b2ee8SDavid du Colombier char	*dbfile;
115*7dd7cddfSDavid du Colombier char	mntpt[Maxpath];
116*7dd7cddfSDavid du Colombier char	*LOG;
117*7dd7cddfSDavid du Colombier 
118*7dd7cddfSDavid du Colombier void
119*7dd7cddfSDavid du Colombier usage(void)
120*7dd7cddfSDavid du Colombier {
121*7dd7cddfSDavid du Colombier 	fprint(2, "usage: %s [-rs] [-f ndb-file] [-x netmtpt]\n", argv0);
122*7dd7cddfSDavid du Colombier 	exits("usage");
123*7dd7cddfSDavid du Colombier }
124219b2ee8SDavid du Colombier 
1253e12c5d1SDavid du Colombier void
1263e12c5d1SDavid du Colombier main(int argc, char *argv[])
1273e12c5d1SDavid du Colombier {
1283e12c5d1SDavid du Colombier 	int	serve;
129*7dd7cddfSDavid du Colombier 	char	servefile[Maxpath];
130*7dd7cddfSDavid du Colombier 	char	buf[Maxpath];
131*7dd7cddfSDavid du Colombier 	char	ext[Maxpath];
132*7dd7cddfSDavid du Colombier 	char	*p;
133219b2ee8SDavid du Colombier 
1343e12c5d1SDavid du Colombier 	serve = 0;
135*7dd7cddfSDavid du Colombier 	setnetmtpt(mntpt, sizeof(mntpt), nil);
136*7dd7cddfSDavid du Colombier 	ext[0] = 0;
1373e12c5d1SDavid du Colombier 	ARGBEGIN{
1383e12c5d1SDavid du Colombier 	case 'd':
1393e12c5d1SDavid du Colombier 		debug = 1;
1403e12c5d1SDavid du Colombier 		break;
141219b2ee8SDavid du Colombier 	case 'f':
142*7dd7cddfSDavid du Colombier 		p = ARGF();
143*7dd7cddfSDavid du Colombier 		if(p == nil)
144*7dd7cddfSDavid du Colombier 			usage();
145*7dd7cddfSDavid du Colombier 		dbfile = p;
146*7dd7cddfSDavid du Colombier 		break;
147*7dd7cddfSDavid du Colombier 	case 'x':
148*7dd7cddfSDavid du Colombier 		p = ARGF();
149*7dd7cddfSDavid du Colombier 		if(p == nil)
150*7dd7cddfSDavid du Colombier 			usage();
151*7dd7cddfSDavid du Colombier 		setnetmtpt(mntpt, sizeof(mntpt), p);
152*7dd7cddfSDavid du Colombier 		setext(ext, sizeof(ext), mntpt);
153*7dd7cddfSDavid du Colombier 		break;
154*7dd7cddfSDavid du Colombier 	case 'r':
155*7dd7cddfSDavid du Colombier 		resolver = 1;
156219b2ee8SDavid du Colombier 		break;
1573e12c5d1SDavid du Colombier 	case 's':
1583e12c5d1SDavid du Colombier 		serve = 1;	/* serve network */
159*7dd7cddfSDavid du Colombier 		cachedb = 1;
160*7dd7cddfSDavid du Colombier 		break;
161*7dd7cddfSDavid du Colombier 	case 'a':
162*7dd7cddfSDavid du Colombier 		p = ARGF();
163*7dd7cddfSDavid du Colombier 		if(p == nil)
164*7dd7cddfSDavid du Colombier 			usage();
165*7dd7cddfSDavid du Colombier 		maxage = atoi(p);
166*7dd7cddfSDavid du Colombier 		break;
167*7dd7cddfSDavid du Colombier 	case 't':
168*7dd7cddfSDavid du Colombier 		testing = 1;
1693e12c5d1SDavid du Colombier 		break;
1703e12c5d1SDavid du Colombier 	}ARGEND
1713e12c5d1SDavid du Colombier 	USED(argc);
1723e12c5d1SDavid du Colombier 	USED(argv);
1733e12c5d1SDavid du Colombier 
174*7dd7cddfSDavid du Colombier 	rfork(RFREND|RFNOTEG);
1753e12c5d1SDavid du Colombier 
176*7dd7cddfSDavid du Colombier 	/* start syslog before we fork */
177219b2ee8SDavid du Colombier 	fmtinstall('F', fcallconv);
178219b2ee8SDavid du Colombier 	dninit();
179*7dd7cddfSDavid du Colombier 	snprint(buf, sizeof(buf), "%s/ipifc", mntpt);
180*7dd7cddfSDavid du Colombier 	if(myipaddr(ipaddr, buf) < 0)
181*7dd7cddfSDavid du Colombier 		sysfatal("can't read my ip address");
182219b2ee8SDavid du Colombier 
183*7dd7cddfSDavid du Colombier 	syslog(0, logfile, "starting dns on %I", ipaddr);
184*7dd7cddfSDavid du Colombier 
185*7dd7cddfSDavid du Colombier 	opendatabase();
186*7dd7cddfSDavid du Colombier 
187*7dd7cddfSDavid du Colombier 	snprint(servefile, sizeof(servefile), "#s/dns%s", ext);
188*7dd7cddfSDavid du Colombier 	unmount(servefile, mntpt);
189*7dd7cddfSDavid du Colombier 	remove(servefile);
190*7dd7cddfSDavid du Colombier 	mountinit(servefile, mntpt);
191*7dd7cddfSDavid du Colombier 
192*7dd7cddfSDavid du Colombier 	now = time(0);
193*7dd7cddfSDavid du Colombier 	srand(now*getpid());
194*7dd7cddfSDavid du Colombier 	db2cache(1);
195*7dd7cddfSDavid du Colombier 
196bd389b36SDavid du Colombier 	if(serve)
197*7dd7cddfSDavid du Colombier 		dnudpserver(mntpt);
1983e12c5d1SDavid du Colombier 	io();
199*7dd7cddfSDavid du Colombier 	syslog(0, logfile, "io returned, exiting");
2003e12c5d1SDavid du Colombier 	exits(0);
2013e12c5d1SDavid du Colombier }
2023e12c5d1SDavid du Colombier 
203*7dd7cddfSDavid du Colombier /*
204*7dd7cddfSDavid du Colombier  *  if a mount point is specified, set the cs extention to be the mount point
205*7dd7cddfSDavid du Colombier  *  with '_'s replacing '/'s
206*7dd7cddfSDavid du Colombier  */
2073e12c5d1SDavid du Colombier void
208*7dd7cddfSDavid du Colombier setext(char *ext, int n, char *p)
209*7dd7cddfSDavid du Colombier {
210*7dd7cddfSDavid du Colombier 	int i, c;
211*7dd7cddfSDavid du Colombier 
212*7dd7cddfSDavid du Colombier 	n--;
213*7dd7cddfSDavid du Colombier 	for(i = 0; i < n; i++){
214*7dd7cddfSDavid du Colombier 		c = p[i];
215*7dd7cddfSDavid du Colombier 		if(c == 0)
216*7dd7cddfSDavid du Colombier 			break;
217*7dd7cddfSDavid du Colombier 		if(c == '/')
218*7dd7cddfSDavid du Colombier 			c = '_';
219*7dd7cddfSDavid du Colombier 		ext[i] = c;
220*7dd7cddfSDavid du Colombier 	}
221*7dd7cddfSDavid du Colombier 	ext[i] = 0;
222*7dd7cddfSDavid du Colombier }
223*7dd7cddfSDavid du Colombier 
224*7dd7cddfSDavid du Colombier void
225*7dd7cddfSDavid du Colombier mountinit(char *service, char *mntpt)
2263e12c5d1SDavid du Colombier {
2273e12c5d1SDavid du Colombier 	int f;
2283e12c5d1SDavid du Colombier 	int p[2];
2293e12c5d1SDavid du Colombier 	char buf[32];
2303e12c5d1SDavid du Colombier 
2313e12c5d1SDavid du Colombier 	if(pipe(p) < 0)
232*7dd7cddfSDavid du Colombier 		abort(); /* "pipe failed" */;
233219b2ee8SDavid du Colombier 	switch(rfork(RFFDG|RFPROC|RFNAMEG)){
2343e12c5d1SDavid du Colombier 	case 0:
235219b2ee8SDavid du Colombier 		close(p[1]);
2363e12c5d1SDavid du Colombier 		break;
2373e12c5d1SDavid du Colombier 	case -1:
238*7dd7cddfSDavid du Colombier 		abort(); /* "fork failed\n" */;
2393e12c5d1SDavid du Colombier 	default:
240219b2ee8SDavid du Colombier 		close(p[0]);
241219b2ee8SDavid du Colombier 
2423e12c5d1SDavid du Colombier 		/*
2433e12c5d1SDavid du Colombier 		 *  make a /srv/dns
2443e12c5d1SDavid du Colombier 		 */
2453e12c5d1SDavid du Colombier 		f = create(service, 1, 0666);
2463e12c5d1SDavid du Colombier 		if(f < 0)
247*7dd7cddfSDavid du Colombier 			abort(); /* service */;
248bd389b36SDavid du Colombier 		snprint(buf, sizeof(buf), "%d", p[1]);
2493e12c5d1SDavid du Colombier 		if(write(f, buf, strlen(buf)) != strlen(buf))
250*7dd7cddfSDavid du Colombier 			abort(); /* "write %s", service */;
2513e12c5d1SDavid du Colombier 		close(f);
2523e12c5d1SDavid du Colombier 
2533e12c5d1SDavid du Colombier 		/*
2543e12c5d1SDavid du Colombier 		 *  put ourselves into the file system
2553e12c5d1SDavid du Colombier 		 */
256*7dd7cddfSDavid du Colombier 		if(mount(p[1], mntpt, MAFTER, "") < 0)
257*7dd7cddfSDavid du Colombier 			abort(); /* "mount failed\n" */;
258219b2ee8SDavid du Colombier 		_exits(0);
2593e12c5d1SDavid du Colombier 	}
2603e12c5d1SDavid du Colombier 	mfd[0] = mfd[1] = p[0];
2613e12c5d1SDavid du Colombier }
2623e12c5d1SDavid du Colombier 
2633e12c5d1SDavid du Colombier #define INC 4
2643e12c5d1SDavid du Colombier Mfile*
265*7dd7cddfSDavid du Colombier newfid(int fid, int needunused)
2663e12c5d1SDavid du Colombier {
2673e12c5d1SDavid du Colombier 	Mfile *mf;
2683e12c5d1SDavid du Colombier 
269*7dd7cddfSDavid du Colombier 	lock(&mfalloc);
270*7dd7cddfSDavid du Colombier 	for(mf = mfalloc.inuse; mf != nil; mf = mf->next){
271*7dd7cddfSDavid du Colombier 		if(mf->fid == fid){
272*7dd7cddfSDavid du Colombier 			unlock(&mfalloc);
273*7dd7cddfSDavid du Colombier 			if(needunused)
274*7dd7cddfSDavid du Colombier 				return nil;
2753e12c5d1SDavid du Colombier 			return mf;
2763e12c5d1SDavid du Colombier 		}
2773e12c5d1SDavid du Colombier 	}
278*7dd7cddfSDavid du Colombier 	mf = mallocz(sizeof(*mf), 1);
279*7dd7cddfSDavid du Colombier 	if(mf == nil)
280*7dd7cddfSDavid du Colombier 		sysfatal("out of memory");
2813e12c5d1SDavid du Colombier 	mf->fid = fid;
282*7dd7cddfSDavid du Colombier 	mf->next = mfalloc.inuse;
283*7dd7cddfSDavid du Colombier 	mfalloc.inuse = mf;
284*7dd7cddfSDavid du Colombier 	unlock(&mfalloc);
2853e12c5d1SDavid du Colombier 	return mf;
2863e12c5d1SDavid du Colombier }
2873e12c5d1SDavid du Colombier 
2883e12c5d1SDavid du Colombier void
289*7dd7cddfSDavid du Colombier freefid(Mfile *mf)
290*7dd7cddfSDavid du Colombier {
291*7dd7cddfSDavid du Colombier 	Mfile **l;
292*7dd7cddfSDavid du Colombier 
293*7dd7cddfSDavid du Colombier 	lock(&mfalloc);
294*7dd7cddfSDavid du Colombier 	for(l = &mfalloc.inuse; *l != nil; l = &(*l)->next){
295*7dd7cddfSDavid du Colombier 		if(*l == mf){
296*7dd7cddfSDavid du Colombier 			*l = mf->next;
297*7dd7cddfSDavid du Colombier 			free(mf);
298*7dd7cddfSDavid du Colombier 			unlock(&mfalloc);
299*7dd7cddfSDavid du Colombier 			return;
300*7dd7cddfSDavid du Colombier 		}
301*7dd7cddfSDavid du Colombier 	}
302*7dd7cddfSDavid du Colombier 	sysfatal("freeing unused fid");
303*7dd7cddfSDavid du Colombier }
304*7dd7cddfSDavid du Colombier 
305*7dd7cddfSDavid du Colombier Mfile*
306*7dd7cddfSDavid du Colombier copyfid(Mfile *mf, int fid)
307*7dd7cddfSDavid du Colombier {
308*7dd7cddfSDavid du Colombier 	Mfile *nmf;
309*7dd7cddfSDavid du Colombier 
310*7dd7cddfSDavid du Colombier 	nmf = newfid(fid, 1);
311*7dd7cddfSDavid du Colombier 	if(nmf == nil)
312*7dd7cddfSDavid du Colombier 		return nil;
313*7dd7cddfSDavid du Colombier 	nmf->fid = fid;
314*7dd7cddfSDavid du Colombier 	strncpy(nmf->user, mf->user, sizeof(mf->user));
315*7dd7cddfSDavid du Colombier 	nmf->qid.path = mf->qid.path;
316*7dd7cddfSDavid du Colombier 	nmf->qid.vers = vers++;
317*7dd7cddfSDavid du Colombier 	return nmf;
318*7dd7cddfSDavid du Colombier }
319*7dd7cddfSDavid du Colombier 
320*7dd7cddfSDavid du Colombier Job*
321*7dd7cddfSDavid du Colombier newjob(void)
322*7dd7cddfSDavid du Colombier {
323*7dd7cddfSDavid du Colombier 	Job *job;
324*7dd7cddfSDavid du Colombier 
325*7dd7cddfSDavid du Colombier 	job = mallocz(sizeof(Job), 1);
326*7dd7cddfSDavid du Colombier 	lock(&joblock);
327*7dd7cddfSDavid du Colombier 	job->next = joblist;
328*7dd7cddfSDavid du Colombier 	joblist = job;
329*7dd7cddfSDavid du Colombier 	job->request.tag = -1;
330*7dd7cddfSDavid du Colombier 	unlock(&joblock);
331*7dd7cddfSDavid du Colombier 	return job;
332*7dd7cddfSDavid du Colombier }
333*7dd7cddfSDavid du Colombier 
334*7dd7cddfSDavid du Colombier void
335*7dd7cddfSDavid du Colombier freejob(Job *job)
336*7dd7cddfSDavid du Colombier {
337*7dd7cddfSDavid du Colombier 	Job **l;
338*7dd7cddfSDavid du Colombier 
339*7dd7cddfSDavid du Colombier 	lock(&joblock);
340*7dd7cddfSDavid du Colombier 	for(l = &joblist; *l; l = &(*l)->next){
341*7dd7cddfSDavid du Colombier 		if((*l) == job){
342*7dd7cddfSDavid du Colombier 			*l = job->next;
343*7dd7cddfSDavid du Colombier 			free(job);
344*7dd7cddfSDavid du Colombier 			break;
345*7dd7cddfSDavid du Colombier 		}
346*7dd7cddfSDavid du Colombier 	}
347*7dd7cddfSDavid du Colombier 	unlock(&joblock);
348*7dd7cddfSDavid du Colombier }
349*7dd7cddfSDavid du Colombier 
350*7dd7cddfSDavid du Colombier void
351*7dd7cddfSDavid du Colombier flushjob(int tag)
352*7dd7cddfSDavid du Colombier {
353*7dd7cddfSDavid du Colombier 	Job *job;
354*7dd7cddfSDavid du Colombier 
355*7dd7cddfSDavid du Colombier 	lock(&joblock);
356*7dd7cddfSDavid du Colombier 	for(job = joblist; job; job = job->next){
357*7dd7cddfSDavid du Colombier 		if(job->request.tag == tag && job->request.type != Tflush){
358*7dd7cddfSDavid du Colombier 			job->flushed = 1;
359*7dd7cddfSDavid du Colombier 			break;
360*7dd7cddfSDavid du Colombier 		}
361*7dd7cddfSDavid du Colombier 	}
362*7dd7cddfSDavid du Colombier 	unlock(&joblock);
363*7dd7cddfSDavid du Colombier }
364*7dd7cddfSDavid du Colombier 
365*7dd7cddfSDavid du Colombier void
3663e12c5d1SDavid du Colombier io(void)
3673e12c5d1SDavid du Colombier {
3683e12c5d1SDavid du Colombier 	long n;
3693e12c5d1SDavid du Colombier 	Mfile *mf;
3703e12c5d1SDavid du Colombier 	char mdata[MAXFDATA + MAXMSG];
3713e12c5d1SDavid du Colombier 	Request req;
372*7dd7cddfSDavid du Colombier 	Job *job;
3733e12c5d1SDavid du Colombier 
3743e12c5d1SDavid du Colombier 	/*
3753e12c5d1SDavid du Colombier 	 *  a slave process is sometimes forked to wait for replies from other
3763e12c5d1SDavid du Colombier 	 *  servers.  The master process returns immediately via a longjmp
377219b2ee8SDavid du Colombier 	 *  through 'mret'.
3783e12c5d1SDavid du Colombier 	 */
379*7dd7cddfSDavid du Colombier 	if(setjmp(req.mret))
380*7dd7cddfSDavid du Colombier 		putactivity();
3813e12c5d1SDavid du Colombier 	req.isslave = 0;
382*7dd7cddfSDavid du Colombier 	for(;;){
3833e12c5d1SDavid du Colombier 		n = read(mfd[0], mdata, sizeof mdata);
384*7dd7cddfSDavid du Colombier 		if(n<=0){
385*7dd7cddfSDavid du Colombier 			syslog(0, logfile, "error reading mntpt: %r");
386*7dd7cddfSDavid du Colombier 			exits(0);
387*7dd7cddfSDavid du Colombier 		}
388*7dd7cddfSDavid du Colombier 		job = newjob();
389*7dd7cddfSDavid du Colombier 		if(convM2S(mdata, &job->request, n) == 0){
390*7dd7cddfSDavid du Colombier 			freejob(job);
391*7dd7cddfSDavid du Colombier 			continue;
392*7dd7cddfSDavid du Colombier 		}
393*7dd7cddfSDavid du Colombier 		mf = newfid(job->request.fid, 0);
394219b2ee8SDavid du Colombier 		if(debug)
395*7dd7cddfSDavid du Colombier 			syslog(0, logfile, "%F", &job->request);
396*7dd7cddfSDavid du Colombier 
397*7dd7cddfSDavid du Colombier 		getactivity(&req);
398*7dd7cddfSDavid du Colombier 		req.aborttime = now + 60;	/* don't spend more than 60 seconds */
399*7dd7cddfSDavid du Colombier 
400*7dd7cddfSDavid du Colombier 		switch(job->request.type){
4013e12c5d1SDavid du Colombier 		default:
402*7dd7cddfSDavid du Colombier 			abort(); /* "type" */;
4033e12c5d1SDavid du Colombier 			break;
4043e12c5d1SDavid du Colombier 		case Tsession:
405*7dd7cddfSDavid du Colombier 			rsession(job);
4063e12c5d1SDavid du Colombier 			break;
4073e12c5d1SDavid du Colombier 		case Tnop:
408*7dd7cddfSDavid du Colombier 			rsimple(job);
4093e12c5d1SDavid du Colombier 			break;
4103e12c5d1SDavid du Colombier 		case Tflush:
411*7dd7cddfSDavid du Colombier 			rflush(job);
4123e12c5d1SDavid du Colombier 			break;
4133e12c5d1SDavid du Colombier 		case Tattach:
414*7dd7cddfSDavid du Colombier 			rattach(job, mf);
4153e12c5d1SDavid du Colombier 			break;
4163e12c5d1SDavid du Colombier 		case Tclone:
417*7dd7cddfSDavid du Colombier 			rclone(job, mf);
4183e12c5d1SDavid du Colombier 			break;
4193e12c5d1SDavid du Colombier 		case Twalk:
420*7dd7cddfSDavid du Colombier 			rwalk(job, mf);
4213e12c5d1SDavid du Colombier 			break;
4223e12c5d1SDavid du Colombier 		case Tclwalk:
423*7dd7cddfSDavid du Colombier 			rclwalk(job, mf);
4243e12c5d1SDavid du Colombier 			break;
4253e12c5d1SDavid du Colombier 		case Topen:
426*7dd7cddfSDavid du Colombier 			ropen(job, mf);
4273e12c5d1SDavid du Colombier 			break;
4283e12c5d1SDavid du Colombier 		case Tcreate:
429*7dd7cddfSDavid du Colombier 			rcreate(job, mf);
4303e12c5d1SDavid du Colombier 			break;
4313e12c5d1SDavid du Colombier 		case Tread:
432*7dd7cddfSDavid du Colombier 			rread(job, mf);
4333e12c5d1SDavid du Colombier 			break;
4343e12c5d1SDavid du Colombier 		case Twrite:
435*7dd7cddfSDavid du Colombier 			rwrite(job, mf, &req);
4363e12c5d1SDavid du Colombier 			break;
4373e12c5d1SDavid du Colombier 		case Tclunk:
438*7dd7cddfSDavid du Colombier 			rclunk(job, mf);
4393e12c5d1SDavid du Colombier 			break;
4403e12c5d1SDavid du Colombier 		case Tremove:
441*7dd7cddfSDavid du Colombier 			rremove(job, mf);
4423e12c5d1SDavid du Colombier 			break;
4433e12c5d1SDavid du Colombier 		case Tstat:
444*7dd7cddfSDavid du Colombier 			rstat(job, mf);
4453e12c5d1SDavid du Colombier 			break;
4463e12c5d1SDavid du Colombier 		case Twstat:
447*7dd7cddfSDavid du Colombier 			rwstat(job, mf);
4483e12c5d1SDavid du Colombier 			break;
4493e12c5d1SDavid du Colombier 		}
450*7dd7cddfSDavid du Colombier 
451*7dd7cddfSDavid du Colombier 		freejob(job);
452*7dd7cddfSDavid du Colombier 
4533e12c5d1SDavid du Colombier 		/*
4543e12c5d1SDavid du Colombier 		 *  slave processes die after replying
4553e12c5d1SDavid du Colombier 		 */
456*7dd7cddfSDavid du Colombier 		if(req.isslave){
457*7dd7cddfSDavid du Colombier 			putactivity();
4583e12c5d1SDavid du Colombier 			_exits(0);
459*7dd7cddfSDavid du Colombier 		}
460*7dd7cddfSDavid du Colombier 
461*7dd7cddfSDavid du Colombier 		putactivity();
462*7dd7cddfSDavid du Colombier 	}
4633e12c5d1SDavid du Colombier }
4643e12c5d1SDavid du Colombier 
4653e12c5d1SDavid du Colombier void
466*7dd7cddfSDavid du Colombier rsession(Job *job)
467219b2ee8SDavid du Colombier {
468*7dd7cddfSDavid du Colombier 	memset(job->reply.authid, 0, sizeof(job->reply.authid));
469*7dd7cddfSDavid du Colombier 	memset(job->reply.authdom, 0, sizeof(job->reply.authdom));
470*7dd7cddfSDavid du Colombier 	memset(job->reply.chal, 0, sizeof(job->reply.chal));
471*7dd7cddfSDavid du Colombier 	sendmsg(job, 0);
472219b2ee8SDavid du Colombier }
473219b2ee8SDavid du Colombier 
474219b2ee8SDavid du Colombier void
475*7dd7cddfSDavid du Colombier rsimple(Job *job)
4763e12c5d1SDavid du Colombier {
477*7dd7cddfSDavid du Colombier 	sendmsg(job, 0);
478*7dd7cddfSDavid du Colombier }
479*7dd7cddfSDavid du Colombier 
480*7dd7cddfSDavid du Colombier /* ignore flushes since the operation will time out */
481*7dd7cddfSDavid du Colombier void
482*7dd7cddfSDavid du Colombier rflush(Job *job)
483*7dd7cddfSDavid du Colombier {
484*7dd7cddfSDavid du Colombier 	flushjob(job->request.oldtag);
485*7dd7cddfSDavid du Colombier 	sendmsg(job, 0);
4863e12c5d1SDavid du Colombier }
4873e12c5d1SDavid du Colombier 
4883e12c5d1SDavid du Colombier void
489*7dd7cddfSDavid du Colombier rauth(Job *job)
4903e12c5d1SDavid du Colombier {
491*7dd7cddfSDavid du Colombier 	sendmsg(job, "Authentication failed");
4923e12c5d1SDavid du Colombier }
4933e12c5d1SDavid du Colombier 
4943e12c5d1SDavid du Colombier void
495*7dd7cddfSDavid du Colombier rattach(Job *job, Mfile *mf)
4963e12c5d1SDavid du Colombier {
497*7dd7cddfSDavid du Colombier 	strcpy(mf->user, job->request.uname);
4983e12c5d1SDavid du Colombier 	mf->qid.vers = vers++;
4993e12c5d1SDavid du Colombier 	mf->qid.path = CHDIR;
500*7dd7cddfSDavid du Colombier 	job->reply.qid = mf->qid;
501*7dd7cddfSDavid du Colombier 	sendmsg(job, 0);
5023e12c5d1SDavid du Colombier }
5033e12c5d1SDavid du Colombier 
504*7dd7cddfSDavid du Colombier char *Eused;
505*7dd7cddfSDavid du Colombier 
5063e12c5d1SDavid du Colombier void
507*7dd7cddfSDavid du Colombier rclone(Job *job, Mfile *mf)
5083e12c5d1SDavid du Colombier {
5093e12c5d1SDavid du Colombier 	Mfile *nmf;
5103e12c5d1SDavid du Colombier 	char *err=0;
5113e12c5d1SDavid du Colombier 
512*7dd7cddfSDavid du Colombier 	nmf = copyfid(mf, job->request.newfid);
513*7dd7cddfSDavid du Colombier 	if(nmf == nil)
514*7dd7cddfSDavid du Colombier 		err = Eused;
515*7dd7cddfSDavid du Colombier 	sendmsg(job, err);
5163e12c5d1SDavid du Colombier }
5173e12c5d1SDavid du Colombier 
5183e12c5d1SDavid du Colombier void
519*7dd7cddfSDavid du Colombier rclwalk(Job *job, Mfile *mf)
5203e12c5d1SDavid du Colombier {
5213e12c5d1SDavid du Colombier 	Mfile *nmf;
5223e12c5d1SDavid du Colombier 
523*7dd7cddfSDavid du Colombier 	nmf = copyfid(mf, job->request.newfid);
524*7dd7cddfSDavid du Colombier 	if(nmf == nil){
525*7dd7cddfSDavid du Colombier 		sendmsg(job, Eused);
5263e12c5d1SDavid du Colombier 		return;
5273e12c5d1SDavid du Colombier 	}
528*7dd7cddfSDavid du Colombier 	job->request.fid = job->request.newfid;
529*7dd7cddfSDavid du Colombier 	if(rwalk(job, nmf) != nil)
530*7dd7cddfSDavid du Colombier 		freefid(nmf);
5313e12c5d1SDavid du Colombier }
5323e12c5d1SDavid du Colombier 
5333e12c5d1SDavid du Colombier char*
534*7dd7cddfSDavid du Colombier rwalk(Job *job, Mfile *mf)
5353e12c5d1SDavid du Colombier {
5363e12c5d1SDavid du Colombier 	char *err;
5373e12c5d1SDavid du Colombier 	char *name;
5383e12c5d1SDavid du Colombier 
5393e12c5d1SDavid du Colombier 	err = 0;
540*7dd7cddfSDavid du Colombier 	name = job->request.name;
5413e12c5d1SDavid du Colombier 	if((mf->qid.path & CHDIR) == 0){
5423e12c5d1SDavid du Colombier 		err = "not a directory";
5433e12c5d1SDavid du Colombier 		goto send;
5443e12c5d1SDavid du Colombier 	}
5453e12c5d1SDavid du Colombier 	if(strcmp(name, ".") == 0){
5463e12c5d1SDavid du Colombier 		mf->qid.path = CHDIR;
5473e12c5d1SDavid du Colombier 		goto send;
5483e12c5d1SDavid du Colombier 	}
5493e12c5d1SDavid du Colombier 	if(strcmp(name, "dns") == 0){
5503e12c5d1SDavid du Colombier 		mf->qid.path = Qdns;
5513e12c5d1SDavid du Colombier 		goto send;
5523e12c5d1SDavid du Colombier 	}
5533e12c5d1SDavid du Colombier 	err = "nonexistent file";
5543e12c5d1SDavid du Colombier     send:
555*7dd7cddfSDavid du Colombier 	job->reply.qid = mf->qid;
556*7dd7cddfSDavid du Colombier 	sendmsg(job, err);
5573e12c5d1SDavid du Colombier 	return err;
5583e12c5d1SDavid du Colombier }
5593e12c5d1SDavid du Colombier 
5603e12c5d1SDavid du Colombier void
561*7dd7cddfSDavid du Colombier ropen(Job *job, Mfile *mf)
5623e12c5d1SDavid du Colombier {
5633e12c5d1SDavid du Colombier 	int mode;
5643e12c5d1SDavid du Colombier 	char *err;
5653e12c5d1SDavid du Colombier 
5663e12c5d1SDavid du Colombier 	err = 0;
567*7dd7cddfSDavid du Colombier 	mode = job->request.mode;
5683e12c5d1SDavid du Colombier 	if(mf->qid.path & CHDIR){
5693e12c5d1SDavid du Colombier 		if(mode)
5703e12c5d1SDavid du Colombier 			err = "permission denied";
5713e12c5d1SDavid du Colombier 	}
572*7dd7cddfSDavid du Colombier 	job->reply.qid = mf->qid;
573*7dd7cddfSDavid du Colombier 	sendmsg(job, err);
5743e12c5d1SDavid du Colombier }
5753e12c5d1SDavid du Colombier 
5763e12c5d1SDavid du Colombier void
577*7dd7cddfSDavid du Colombier rcreate(Job *job, Mfile *mf)
5783e12c5d1SDavid du Colombier {
5793e12c5d1SDavid du Colombier 	USED(mf);
580*7dd7cddfSDavid du Colombier 	sendmsg(job, "creation permission denied");
5813e12c5d1SDavid du Colombier }
5823e12c5d1SDavid du Colombier 
5833e12c5d1SDavid du Colombier void
584*7dd7cddfSDavid du Colombier rread(Job *job, Mfile *mf)
5853e12c5d1SDavid du Colombier {
586*7dd7cddfSDavid du Colombier 	int i, n, cnt;
587*7dd7cddfSDavid du Colombier 	long off;
5883e12c5d1SDavid du Colombier 	Dir dir;
5893e12c5d1SDavid du Colombier 	char buf[MAXFDATA];
5903e12c5d1SDavid du Colombier 	char *err;
5913e12c5d1SDavid du Colombier 
5923e12c5d1SDavid du Colombier 	n = 0;
5933e12c5d1SDavid du Colombier 	err = 0;
594*7dd7cddfSDavid du Colombier 	off = job->request.offset;
595*7dd7cddfSDavid du Colombier 	cnt = job->request.count;
5963e12c5d1SDavid du Colombier 	if(mf->qid.path & CHDIR){
5973e12c5d1SDavid du Colombier 		if(off%DIRLEN || cnt%DIRLEN){
5983e12c5d1SDavid du Colombier 			err = "bad offset";
5993e12c5d1SDavid du Colombier 			goto send;
6003e12c5d1SDavid du Colombier 		}
6013e12c5d1SDavid du Colombier 		if(off == 0){
6023e12c5d1SDavid du Colombier 			memmove(dir.name, "dns", NAMELEN);
6033e12c5d1SDavid du Colombier 			dir.qid.vers = vers;
6043e12c5d1SDavid du Colombier 			dir.qid.path = Qdns;
6053e12c5d1SDavid du Colombier 			dir.mode = 0666;
6063e12c5d1SDavid du Colombier 			dir.length = 0;
6073e12c5d1SDavid du Colombier 			strcpy(dir.uid, mf->user);
6083e12c5d1SDavid du Colombier 			strcpy(dir.gid, mf->user);
609*7dd7cddfSDavid du Colombier 			dir.atime = now;
610*7dd7cddfSDavid du Colombier 			dir.mtime = now;
6113e12c5d1SDavid du Colombier 			convD2M(&dir, buf+n);
6123e12c5d1SDavid du Colombier 			n += DIRLEN;
6133e12c5d1SDavid du Colombier 		}
614*7dd7cddfSDavid du Colombier 		job->reply.data = buf;
6153e12c5d1SDavid du Colombier 	} else {
616*7dd7cddfSDavid du Colombier 		for(i = 1; i <= mf->nrr; i++)
617*7dd7cddfSDavid du Colombier 			if(mf->rr[i] > off)
6183e12c5d1SDavid du Colombier 				break;
619*7dd7cddfSDavid du Colombier 		if(i > mf->nrr)
620*7dd7cddfSDavid du Colombier 			goto send;
621*7dd7cddfSDavid du Colombier 		if(off + cnt > mf->rr[i])
622*7dd7cddfSDavid du Colombier 			n = mf->rr[i] - off;
623*7dd7cddfSDavid du Colombier 		else
624*7dd7cddfSDavid du Colombier 			n = cnt;
625*7dd7cddfSDavid du Colombier 		job->reply.data = mf->reply + off;
6263e12c5d1SDavid du Colombier 	}
6273e12c5d1SDavid du Colombier send:
628*7dd7cddfSDavid du Colombier 	job->reply.count = n;
629*7dd7cddfSDavid du Colombier 	sendmsg(job, err);
6303e12c5d1SDavid du Colombier }
6313e12c5d1SDavid du Colombier 
6323e12c5d1SDavid du Colombier void
633*7dd7cddfSDavid du Colombier rwrite(Job *job, Mfile *mf, Request *req)
6343e12c5d1SDavid du Colombier {
635*7dd7cddfSDavid du Colombier 	int cnt, rooted, status;
636*7dd7cddfSDavid du Colombier 	long n;
637*7dd7cddfSDavid du Colombier 	char *err, *p, *atype;
638*7dd7cddfSDavid du Colombier 	RR *rp, *tp, *neg;
639*7dd7cddfSDavid du Colombier 	int wantsav;
6403e12c5d1SDavid du Colombier 
6413e12c5d1SDavid du Colombier 	err = 0;
642*7dd7cddfSDavid du Colombier 	cnt = job->request.count;
6433e12c5d1SDavid du Colombier 	if(mf->qid.path & CHDIR){
6443e12c5d1SDavid du Colombier 		err = "can't write directory";
6453e12c5d1SDavid du Colombier 		goto send;
6463e12c5d1SDavid du Colombier 	}
6473e12c5d1SDavid du Colombier 	if(cnt >= Maxrequest){
6483e12c5d1SDavid du Colombier 		err = "request too long";
6493e12c5d1SDavid du Colombier 		goto send;
6503e12c5d1SDavid du Colombier 	}
651*7dd7cddfSDavid du Colombier 	job->request.data[cnt] = 0;
652*7dd7cddfSDavid du Colombier 	if(cnt > 0 && job->request.data[cnt-1] == '\n')
653*7dd7cddfSDavid du Colombier 		job->request.data[cnt-1] = 0;
6543e12c5d1SDavid du Colombier 
6553e12c5d1SDavid du Colombier 	/*
656*7dd7cddfSDavid du Colombier 	 *  special commands
657219b2ee8SDavid du Colombier 	 */
658*7dd7cddfSDavid du Colombier 	if(strncmp(job->request.data, "debug", 5)==0 && job->request.data[5] == 0){
659219b2ee8SDavid du Colombier 		debug ^= 1;
660219b2ee8SDavid du Colombier 		goto send;
661*7dd7cddfSDavid du Colombier 	} else if(strncmp(job->request.data, "dump", 4)==0 && job->request.data[4] == 0){
662219b2ee8SDavid du Colombier 		dndump("/lib/ndb/dnsdump");
663219b2ee8SDavid du Colombier 		goto send;
664*7dd7cddfSDavid du Colombier 	} else if(strncmp(job->request.data, "refresh", 7)==0 && job->request.data[7] == 0){
665*7dd7cddfSDavid du Colombier 		needrefresh = 1;
666*7dd7cddfSDavid du Colombier 		goto send;
667219b2ee8SDavid du Colombier 	}
668219b2ee8SDavid du Colombier 
669219b2ee8SDavid du Colombier 	/*
670*7dd7cddfSDavid du Colombier 	 *  kill previous reply
671*7dd7cddfSDavid du Colombier 	 */
672*7dd7cddfSDavid du Colombier 	mf->nrr = 0;
673*7dd7cddfSDavid du Colombier 	mf->rr[0] = 0;
674*7dd7cddfSDavid du Colombier 
675*7dd7cddfSDavid du Colombier 	/*
6763e12c5d1SDavid du Colombier 	 *  break up request (into a name and a type)
6773e12c5d1SDavid du Colombier 	 */
678*7dd7cddfSDavid du Colombier 	atype = strchr(job->request.data, ' ');
6793e12c5d1SDavid du Colombier 	if(atype == 0){
6803e12c5d1SDavid du Colombier 		err = "illegal request";
6813e12c5d1SDavid du Colombier 		goto send;
6823e12c5d1SDavid du Colombier 	} else
6833e12c5d1SDavid du Colombier 		*atype++ = 0;
6843e12c5d1SDavid du Colombier 
685*7dd7cddfSDavid du Colombier 	/*
686*7dd7cddfSDavid du Colombier 	 *  tracing request
687*7dd7cddfSDavid du Colombier 	 */
688*7dd7cddfSDavid du Colombier 	if(strcmp(atype, "trace") == 0){
689*7dd7cddfSDavid du Colombier 		if(trace)
690*7dd7cddfSDavid du Colombier 			free(trace);
691*7dd7cddfSDavid du Colombier 		if(*job->request.data)
692*7dd7cddfSDavid du Colombier 			trace = strdup(job->request.data);
693*7dd7cddfSDavid du Colombier 		else
694*7dd7cddfSDavid du Colombier 			trace = 0;
695*7dd7cddfSDavid du Colombier 		goto send;
696*7dd7cddfSDavid du Colombier 	}
697*7dd7cddfSDavid du Colombier 
6983e12c5d1SDavid du Colombier 	mf->type = rrtype(atype);
6993e12c5d1SDavid du Colombier 	if(mf->type < 0){
7003e12c5d1SDavid du Colombier 		err = "unknown type";
7013e12c5d1SDavid du Colombier 		goto send;
7023e12c5d1SDavid du Colombier 	}
7033e12c5d1SDavid du Colombier 
704*7dd7cddfSDavid du Colombier 	p = atype - 2;
705*7dd7cddfSDavid du Colombier 	if(p >= job->request.data && *p == '.'){
706*7dd7cddfSDavid du Colombier 		rooted = 1;
707*7dd7cddfSDavid du Colombier 		*p = 0;
708*7dd7cddfSDavid du Colombier 	} else
709*7dd7cddfSDavid du Colombier 		rooted = 0;
7103e12c5d1SDavid du Colombier 
711*7dd7cddfSDavid du Colombier 	p = job->request.data;
712*7dd7cddfSDavid du Colombier 	if(*p == '!'){
713*7dd7cddfSDavid du Colombier 		wantsav = 1;
714*7dd7cddfSDavid du Colombier 		p++;
715*7dd7cddfSDavid du Colombier 	} else
716*7dd7cddfSDavid du Colombier 		wantsav = 0;
717*7dd7cddfSDavid du Colombier 	rp = dnresolve(p, Cin, mf->type, req, 0, 0, Recurse, rooted, &status);
718*7dd7cddfSDavid du Colombier 	neg = rrremneg(&rp);
719*7dd7cddfSDavid du Colombier 	if(neg){
720*7dd7cddfSDavid du Colombier 		status = neg->negrcode;
721*7dd7cddfSDavid du Colombier 		rrfreelist(neg);
722*7dd7cddfSDavid du Colombier 	}
723*7dd7cddfSDavid du Colombier 	if(rp == 0){
724*7dd7cddfSDavid du Colombier 		if(status == Rname)
725*7dd7cddfSDavid du Colombier 			err = "name does not exist";
726*7dd7cddfSDavid du Colombier 		else
727*7dd7cddfSDavid du Colombier 			err = "no translation found";
728*7dd7cddfSDavid du Colombier 	} else {
729*7dd7cddfSDavid du Colombier 		/* format data to be read later */
730*7dd7cddfSDavid du Colombier 		n = 0;
731*7dd7cddfSDavid du Colombier 		mf->nrr = 0;
732*7dd7cddfSDavid du Colombier 		for(tp = rp; mf->nrr < Maxrrr-1 && n < Maxreply && tp &&
733*7dd7cddfSDavid du Colombier 				tsame(mf->type, tp->type); tp = tp->next){
734*7dd7cddfSDavid du Colombier 			mf->rr[mf->nrr++] = n;
735*7dd7cddfSDavid du Colombier 			if(wantsav)
736*7dd7cddfSDavid du Colombier 				n += snprint(mf->reply+n, Maxreply-n, "%Q", tp);
737*7dd7cddfSDavid du Colombier 			else
738*7dd7cddfSDavid du Colombier 				n += snprint(mf->reply+n, Maxreply-n, "%R", tp);
739*7dd7cddfSDavid du Colombier 		}
740*7dd7cddfSDavid du Colombier 		mf->rr[mf->nrr] = n;
741*7dd7cddfSDavid du Colombier 		rrfreelist(rp);
742*7dd7cddfSDavid du Colombier 	}
7433e12c5d1SDavid du Colombier 
7443e12c5d1SDavid du Colombier     send:
745*7dd7cddfSDavid du Colombier 	job->reply.count = cnt;
746*7dd7cddfSDavid du Colombier 	sendmsg(job, err);
7473e12c5d1SDavid du Colombier }
7483e12c5d1SDavid du Colombier 
7493e12c5d1SDavid du Colombier void
750*7dd7cddfSDavid du Colombier rclunk(Job *job, Mfile *mf)
7513e12c5d1SDavid du Colombier {
752*7dd7cddfSDavid du Colombier 	freefid(mf);
753*7dd7cddfSDavid du Colombier 	sendmsg(job, 0);
7543e12c5d1SDavid du Colombier }
7553e12c5d1SDavid du Colombier 
7563e12c5d1SDavid du Colombier void
757*7dd7cddfSDavid du Colombier rremove(Job *job, Mfile *mf)
7583e12c5d1SDavid du Colombier {
7593e12c5d1SDavid du Colombier 	USED(mf);
760*7dd7cddfSDavid du Colombier 	sendmsg(job, "remove permission denied");
7613e12c5d1SDavid du Colombier }
7623e12c5d1SDavid du Colombier 
7633e12c5d1SDavid du Colombier void
764*7dd7cddfSDavid du Colombier rstat(Job *job, Mfile *mf)
7653e12c5d1SDavid du Colombier {
7663e12c5d1SDavid du Colombier 	Dir dir;
7673e12c5d1SDavid du Colombier 
768219b2ee8SDavid du Colombier 	if(mf->qid.path & CHDIR){
769219b2ee8SDavid du Colombier 		strcpy(dir.name, ".");
770219b2ee8SDavid du Colombier 		dir.mode = CHDIR|0555;
771219b2ee8SDavid du Colombier 	} else {
772219b2ee8SDavid du Colombier 		strcpy(dir.name, "dns");
7733e12c5d1SDavid du Colombier 		dir.mode = 0666;
774219b2ee8SDavid du Colombier 	}
775219b2ee8SDavid du Colombier 	dir.qid = mf->qid;
7763e12c5d1SDavid du Colombier 	dir.length = 0;
7773e12c5d1SDavid du Colombier 	strcpy(dir.uid, mf->user);
7783e12c5d1SDavid du Colombier 	strcpy(dir.gid, mf->user);
7793e12c5d1SDavid du Colombier 	dir.atime = dir.mtime = time(0);
780*7dd7cddfSDavid du Colombier 	convD2M(&dir, (char*)job->reply.stat);
781*7dd7cddfSDavid du Colombier 	sendmsg(job, 0);
7823e12c5d1SDavid du Colombier }
7833e12c5d1SDavid du Colombier 
7843e12c5d1SDavid du Colombier void
785*7dd7cddfSDavid du Colombier rwstat(Job *job, Mfile *mf)
7863e12c5d1SDavid du Colombier {
7873e12c5d1SDavid du Colombier 	USED(mf);
788*7dd7cddfSDavid du Colombier 	sendmsg(job, "wstat permission denied");
7893e12c5d1SDavid du Colombier }
7903e12c5d1SDavid du Colombier 
7913e12c5d1SDavid du Colombier void
792*7dd7cddfSDavid du Colombier sendmsg(Job *job, char *err)
7933e12c5d1SDavid du Colombier {
7943e12c5d1SDavid du Colombier 	int n;
7953e12c5d1SDavid du Colombier 	char mdata[MAXFDATA + MAXMSG];
7963e12c5d1SDavid du Colombier 
7973e12c5d1SDavid du Colombier 	if(err){
798*7dd7cddfSDavid du Colombier 		job->reply.type = Rerror;
799*7dd7cddfSDavid du Colombier 		snprint(job->reply.ename, sizeof(job->reply.ename), "dns: %s", err);
8003e12c5d1SDavid du Colombier 	}else{
801*7dd7cddfSDavid du Colombier 		job->reply.type = job->request.type+1;
802*7dd7cddfSDavid du Colombier 		job->reply.fid = job->request.fid;
8033e12c5d1SDavid du Colombier 	}
804*7dd7cddfSDavid du Colombier 	job->reply.tag = job->request.tag;
805219b2ee8SDavid du Colombier 	if(debug)
806*7dd7cddfSDavid du Colombier 		syslog(0, logfile, "%F", &job->reply);
807*7dd7cddfSDavid du Colombier 	n = convS2M(&job->reply, mdata);
808*7dd7cddfSDavid du Colombier 	lock(&joblock);
809*7dd7cddfSDavid du Colombier 	if(job->flushed == 0){
8103e12c5d1SDavid du Colombier 		if(write(mfd[1], mdata, n)!=n)
811*7dd7cddfSDavid du Colombier 			abort(); /* "mount write" */;
8123e12c5d1SDavid du Colombier 	}
813*7dd7cddfSDavid du Colombier 	unlock(&joblock);
8143e12c5d1SDavid du Colombier }
8153e12c5d1SDavid du Colombier 
8163e12c5d1SDavid du Colombier /*
817*7dd7cddfSDavid du Colombier  *  the following varies between dnsdebug and dns
8183e12c5d1SDavid du Colombier  */
8193e12c5d1SDavid du Colombier void
820*7dd7cddfSDavid du Colombier logreply(int id, uchar *addr, DNSmsg *mp)
8213e12c5d1SDavid du Colombier {
822*7dd7cddfSDavid du Colombier 	RR *rp;
8233e12c5d1SDavid du Colombier 
824*7dd7cddfSDavid du Colombier 	syslog(0, LOG, "%d: rcvd %I flags:%s%s%s%s%s", id, addr,
825*7dd7cddfSDavid du Colombier 		mp->flags & Fauth ? " auth" : "",
826*7dd7cddfSDavid du Colombier 		mp->flags & Ftrunc ? " trunc" : "",
827*7dd7cddfSDavid du Colombier 		mp->flags & Frecurse ? " rd" : "",
828*7dd7cddfSDavid du Colombier 		mp->flags & Fcanrec ? " ra" : "",
829*7dd7cddfSDavid du Colombier 		mp->flags & (Fauth|Rname) == (Fauth|Rname) ?
830*7dd7cddfSDavid du Colombier 		" nx" : "");
831*7dd7cddfSDavid du Colombier 	for(rp = mp->qd; rp != nil; rp = rp->next)
832*7dd7cddfSDavid du Colombier 		syslog(0, LOG, "%d: rcvd %I qd %s", id, addr, rp->owner->name);
833*7dd7cddfSDavid du Colombier 	for(rp = mp->an; rp != nil; rp = rp->next)
834*7dd7cddfSDavid du Colombier 		syslog(0, LOG, "%d: rcvd %I an %R", id, addr, rp);
835*7dd7cddfSDavid du Colombier 	for(rp = mp->ns; rp != nil; rp = rp->next)
836*7dd7cddfSDavid du Colombier 		syslog(0, LOG, "%d: rcvd %I ns %R", id, addr, rp);
837*7dd7cddfSDavid du Colombier 	for(rp = mp->ar; rp != nil; rp = rp->next)
838*7dd7cddfSDavid du Colombier 		syslog(0, LOG, "%d: rcvd %I ar %R", id, addr, rp);
8393e12c5d1SDavid du Colombier }
840*7dd7cddfSDavid du Colombier 
841*7dd7cddfSDavid du Colombier void
842*7dd7cddfSDavid du Colombier logsend(int id, int subid, uchar *addr, char *sname, char *rname, int type)
843*7dd7cddfSDavid du Colombier {
844*7dd7cddfSDavid du Colombier 	char buf[12];
845*7dd7cddfSDavid du Colombier 
846*7dd7cddfSDavid du Colombier 	syslog(0, LOG, "%d.%d: sending to %I/%s %s %s",
847*7dd7cddfSDavid du Colombier 		id, subid, addr, sname, rname, rrname(type, buf));
848*7dd7cddfSDavid du Colombier }
849*7dd7cddfSDavid du Colombier 
850*7dd7cddfSDavid du Colombier RR*
851*7dd7cddfSDavid du Colombier getdnsservers(int class)
852*7dd7cddfSDavid du Colombier {
853*7dd7cddfSDavid du Colombier 	return dnsservers(class);
8543e12c5d1SDavid du Colombier }
855