xref: /plan9-contrib/sys/src/cmd/ndb/dns.c (revision 219b2ee8daee37f4aad58d63f21287faa8e4ffdc)
13e12c5d1SDavid du Colombier #include <u.h>
23e12c5d1SDavid du Colombier #include <libc.h>
3*219b2ee8SDavid du Colombier #include <auth.h>
43e12c5d1SDavid du Colombier #include <fcall.h>
53e12c5d1SDavid du Colombier #include <bio.h>
63e12c5d1SDavid du Colombier #include <ctype.h>
73e12c5d1SDavid du Colombier #include "dns.h"
83e12c5d1SDavid du Colombier 
93e12c5d1SDavid du Colombier enum
103e12c5d1SDavid du Colombier {
113e12c5d1SDavid du Colombier 	Maxrequest=		4*NAMELEN,
123e12c5d1SDavid du Colombier 	Ncache=			8,
133e12c5d1SDavid du Colombier 
143e12c5d1SDavid du Colombier 	Qdns=			1,
153e12c5d1SDavid du Colombier };
163e12c5d1SDavid du Colombier 
173e12c5d1SDavid du Colombier typedef struct Mfile	Mfile;
183e12c5d1SDavid du Colombier typedef struct Network	Network;
193e12c5d1SDavid du Colombier 
203e12c5d1SDavid du Colombier int vers;		/* incremented each clone/attach */
213e12c5d1SDavid du Colombier 
223e12c5d1SDavid du Colombier struct Mfile
233e12c5d1SDavid du Colombier {
243e12c5d1SDavid du Colombier 	int		busy;
253e12c5d1SDavid du Colombier 	char		user[NAMELEN];
263e12c5d1SDavid du Colombier 	Qid		qid;
273e12c5d1SDavid du Colombier 	int		fid;
283e12c5d1SDavid du Colombier 
293e12c5d1SDavid du Colombier 	int		tag;		/* tag of current request */
303e12c5d1SDavid du Colombier 	RR		*rp;		/* start of reply */
313e12c5d1SDavid du Colombier 	int		type;		/* reply type */
323e12c5d1SDavid du Colombier };
333e12c5d1SDavid du Colombier 
343e12c5d1SDavid du Colombier Mfile	*mfile;
353e12c5d1SDavid du Colombier int	nmfile = 0;
363e12c5d1SDavid du Colombier int	mfd[2];
373e12c5d1SDavid du Colombier char	user[NAMELEN];
383e12c5d1SDavid du Colombier Fcall	*rhp;
393e12c5d1SDavid du Colombier Fcall	*thp;
403e12c5d1SDavid du Colombier int	debug;
413e12c5d1SDavid du Colombier 
42*219b2ee8SDavid du Colombier void	rsession(void);
433e12c5d1SDavid du Colombier void	rsimple(void);
443e12c5d1SDavid du Colombier void	rflush(int tag);
453e12c5d1SDavid du Colombier void	rattach(Mfile*);
463e12c5d1SDavid du Colombier void	rclone(Mfile*);
473e12c5d1SDavid du Colombier char*	rwalk(Mfile*);
483e12c5d1SDavid du Colombier void	rclwalk(Mfile*);
493e12c5d1SDavid du Colombier void	ropen(Mfile*);
503e12c5d1SDavid du Colombier void	rcreate(Mfile*);
513e12c5d1SDavid du Colombier void	rread(Mfile*);
523e12c5d1SDavid du Colombier void	rwrite(Mfile*, Request*);
533e12c5d1SDavid du Colombier void	rclunk(Mfile*);
543e12c5d1SDavid du Colombier void	rremove(Mfile*);
553e12c5d1SDavid du Colombier void	rstat(Mfile*);
563e12c5d1SDavid du Colombier void	rauth(void);
573e12c5d1SDavid du Colombier void	rwstat(Mfile*);
583e12c5d1SDavid du Colombier void	sendmsg(char*);
593e12c5d1SDavid du Colombier void	mountinit(char*);
603e12c5d1SDavid du Colombier void	io(void);
613e12c5d1SDavid du Colombier int	lookup(Mfile*, char*, char*, char*);
623e12c5d1SDavid du Colombier int	fillreply(Mfile*, int);
633e12c5d1SDavid du Colombier int	mygetfields(char*, char**, int, char);
643e12c5d1SDavid du Colombier 
653e12c5d1SDavid du Colombier char *mname[]={
663e12c5d1SDavid du Colombier 	[Tnop]		"Tnop",
673e12c5d1SDavid du Colombier 	[Tsession]	"Tsession",
683e12c5d1SDavid du Colombier 	[Tflush]	"Tflush",
693e12c5d1SDavid du Colombier 	[Tattach]	"Tattach",
703e12c5d1SDavid du Colombier 	[Tclone]	"Tclone",
713e12c5d1SDavid du Colombier 	[Twalk]		"Twalk",
723e12c5d1SDavid du Colombier 	[Topen]		"Topen",
733e12c5d1SDavid du Colombier 	[Tcreate]	"Tcreate",
743e12c5d1SDavid du Colombier 	[Tclunk]	"Tclunk",
753e12c5d1SDavid du Colombier 	[Tread]		"Tread",
763e12c5d1SDavid du Colombier 	[Twrite]	"Twrite",
773e12c5d1SDavid du Colombier 	[Tremove]	"Tremove",
783e12c5d1SDavid du Colombier 	[Tstat]		"Tstat",
793e12c5d1SDavid du Colombier 	[Twstat]	"Twstat",
803e12c5d1SDavid du Colombier 			0,
813e12c5d1SDavid du Colombier };
823e12c5d1SDavid du Colombier 
83*219b2ee8SDavid du Colombier char *logfile = "dns";
84*219b2ee8SDavid du Colombier char *dbfile;
85*219b2ee8SDavid du Colombier 
863e12c5d1SDavid du Colombier void
873e12c5d1SDavid du Colombier main(int argc, char *argv[])
883e12c5d1SDavid du Colombier {
893e12c5d1SDavid du Colombier 	Fcall	rhdr;
903e12c5d1SDavid du Colombier 	Fcall	thdr;
913e12c5d1SDavid du Colombier 	int	serve;
923e12c5d1SDavid du Colombier 
93*219b2ee8SDavid du Colombier 
943e12c5d1SDavid du Colombier 	serve = 0;
953e12c5d1SDavid du Colombier 	rhp = &rhdr;
963e12c5d1SDavid du Colombier 	thp = &thdr;
973e12c5d1SDavid du Colombier 	ARGBEGIN{
983e12c5d1SDavid du Colombier 	case 'd':
993e12c5d1SDavid du Colombier 		debug = 1;
1003e12c5d1SDavid du Colombier 		break;
101*219b2ee8SDavid du Colombier 	case 'f':
102*219b2ee8SDavid du Colombier 		dbfile = ARGF();
103*219b2ee8SDavid du Colombier 		break;
1043e12c5d1SDavid du Colombier 	case 's':
1053e12c5d1SDavid du Colombier 		serve = 1;	/* serve network */
1063e12c5d1SDavid du Colombier 		break;
1073e12c5d1SDavid du Colombier 	}ARGEND
1083e12c5d1SDavid du Colombier 	USED(argc);
1093e12c5d1SDavid du Colombier 	USED(argv);
1103e12c5d1SDavid du Colombier 
111*219b2ee8SDavid du Colombier 	remove("#s/dns");
1123e12c5d1SDavid du Colombier 	unmount("/net/dns", "/net");
1133e12c5d1SDavid du Colombier 	mountinit("#s/dns");
1143e12c5d1SDavid du Colombier 
115*219b2ee8SDavid du Colombier 	fmtinstall('F', fcallconv);
116*219b2ee8SDavid du Colombier 	dninit();
117*219b2ee8SDavid du Colombier 
118*219b2ee8SDavid du Colombier 	syslog(1, logfile, "started%s%s", serve?" serving":"",
119bd389b36SDavid du Colombier 		debug?" debuging":"");
120bd389b36SDavid du Colombier 	if(serve)
121bd389b36SDavid du Colombier 		dnserver();
1223e12c5d1SDavid du Colombier 	io();
1233e12c5d1SDavid du Colombier 	exits(0);
1243e12c5d1SDavid du Colombier }
1253e12c5d1SDavid du Colombier 
1263e12c5d1SDavid du Colombier void
1273e12c5d1SDavid du Colombier mountinit(char *service)
1283e12c5d1SDavid du Colombier {
1293e12c5d1SDavid du Colombier 	int f;
1303e12c5d1SDavid du Colombier 	int p[2];
1313e12c5d1SDavid du Colombier 	char buf[32];
1323e12c5d1SDavid du Colombier 
1333e12c5d1SDavid du Colombier 	if(pipe(p) < 0)
1343e12c5d1SDavid du Colombier 		fatal("pipe failed");
135*219b2ee8SDavid du Colombier 	switch(rfork(RFFDG|RFPROC|RFNAMEG)){
1363e12c5d1SDavid du Colombier 	case 0:
137*219b2ee8SDavid du Colombier 		close(p[1]);
1383e12c5d1SDavid du Colombier 		break;
1393e12c5d1SDavid du Colombier 	case -1:
1403e12c5d1SDavid du Colombier 		fatal("fork failed\n");
1413e12c5d1SDavid du Colombier 	default:
142*219b2ee8SDavid du Colombier 		close(p[0]);
143*219b2ee8SDavid du Colombier 
1443e12c5d1SDavid du Colombier 		/*
1453e12c5d1SDavid du Colombier 		 *  make a /srv/dns
1463e12c5d1SDavid du Colombier 		 */
1473e12c5d1SDavid du Colombier 		f = create(service, 1, 0666);
1483e12c5d1SDavid du Colombier 		if(f < 0)
1493e12c5d1SDavid du Colombier 			fatal(service);
150bd389b36SDavid du Colombier 		snprint(buf, sizeof(buf), "%d", p[1]);
1513e12c5d1SDavid du Colombier 		if(write(f, buf, strlen(buf)) != strlen(buf))
1523e12c5d1SDavid du Colombier 			fatal("write %s", service);
1533e12c5d1SDavid du Colombier 		close(f);
1543e12c5d1SDavid du Colombier 
1553e12c5d1SDavid du Colombier 		/*
1563e12c5d1SDavid du Colombier 		 *  put ourselves into the file system
1573e12c5d1SDavid du Colombier 		 */
158*219b2ee8SDavid du Colombier 		if(mount(p[1], "/net", MAFTER, "") < 0)
1593e12c5d1SDavid du Colombier 			fatal("mount failed\n");
160*219b2ee8SDavid du Colombier 		_exits(0);
1613e12c5d1SDavid du Colombier 	}
1623e12c5d1SDavid du Colombier 	mfd[0] = mfd[1] = p[0];
1633e12c5d1SDavid du Colombier }
1643e12c5d1SDavid du Colombier 
1653e12c5d1SDavid du Colombier #define INC 4
1663e12c5d1SDavid du Colombier Mfile*
1673e12c5d1SDavid du Colombier newfid(int fid)
1683e12c5d1SDavid du Colombier {
1693e12c5d1SDavid du Colombier 	Mfile *mf;
1703e12c5d1SDavid du Colombier 	Mfile *freemf;
1713e12c5d1SDavid du Colombier 	int old;
1723e12c5d1SDavid du Colombier 	Mfile *o;
1733e12c5d1SDavid du Colombier 
1743e12c5d1SDavid du Colombier 	freemf = 0;
1753e12c5d1SDavid du Colombier 	for(mf = mfile; mf < &mfile[nmfile]; mf++){
1763e12c5d1SDavid du Colombier 		if(mf->fid==fid)
1773e12c5d1SDavid du Colombier 			return mf;
1783e12c5d1SDavid du Colombier 		if(mf->busy == 0)
1793e12c5d1SDavid du Colombier 			freemf = mf;
1803e12c5d1SDavid du Colombier 	}
1813e12c5d1SDavid du Colombier 	if(freemf == 0){
1823e12c5d1SDavid du Colombier 		old = nmfile;
1833e12c5d1SDavid du Colombier 		nmfile += INC;
1843e12c5d1SDavid du Colombier 		o = mfile;
1853e12c5d1SDavid du Colombier 		mfile = realloc(mfile, nmfile*sizeof(Mfile));
1863e12c5d1SDavid du Colombier 		if(mfile == 0){
1873e12c5d1SDavid du Colombier 			fprint(2, "dns: realloc(0x%lux, %d)\n", o, nmfile*sizeof(Mfile));
1883e12c5d1SDavid du Colombier 			fatal("realloc failure");
1893e12c5d1SDavid du Colombier 		}
1903e12c5d1SDavid du Colombier 		mf = &mfile[old];
1913e12c5d1SDavid du Colombier 		memset(mf, 0, INC*sizeof(Mfile));
1923e12c5d1SDavid du Colombier 	} else
1933e12c5d1SDavid du Colombier 		mf = freemf;
1943e12c5d1SDavid du Colombier 
1953e12c5d1SDavid du Colombier 	memset(mf, 0, sizeof mfile[0]);
1963e12c5d1SDavid du Colombier 	mf->fid = fid;
1973e12c5d1SDavid du Colombier 	return mf;
1983e12c5d1SDavid du Colombier }
1993e12c5d1SDavid du Colombier 
2003e12c5d1SDavid du Colombier void
2013e12c5d1SDavid du Colombier io(void)
2023e12c5d1SDavid du Colombier {
2033e12c5d1SDavid du Colombier 	long n;
2043e12c5d1SDavid du Colombier 	Mfile *mf;
2053e12c5d1SDavid du Colombier 	char mdata[MAXFDATA + MAXMSG];
2063e12c5d1SDavid du Colombier 	Request req;
2073e12c5d1SDavid du Colombier 
2083e12c5d1SDavid du Colombier 	/*
2093e12c5d1SDavid du Colombier 	 *  a slave process is sometimes forked to wait for replies from other
2103e12c5d1SDavid du Colombier 	 *  servers.  The master process returns immediately via a longjmp
211*219b2ee8SDavid du Colombier 	 *  through 'mret'.
2123e12c5d1SDavid du Colombier 	 */
2133e12c5d1SDavid du Colombier 	setjmp(req.mret);
2143e12c5d1SDavid du Colombier 	req.isslave = 0;
2153e12c5d1SDavid du Colombier     loop:
2163e12c5d1SDavid du Colombier 	n = read(mfd[0], mdata, sizeof mdata);
2173e12c5d1SDavid du Colombier 	if(n<=0)
2183e12c5d1SDavid du Colombier 		fatal("mount read");
2193e12c5d1SDavid du Colombier 	if(convM2S(mdata, rhp, n) == 0)
2203e12c5d1SDavid du Colombier 		goto loop;
2213e12c5d1SDavid du Colombier 	if(rhp->fid<0)
2223e12c5d1SDavid du Colombier 		fatal("fid out of range");
2233e12c5d1SDavid du Colombier 	mf = newfid(rhp->fid);
224*219b2ee8SDavid du Colombier 	if(debug)
225*219b2ee8SDavid du Colombier 		syslog(0, logfile, "%F", rhp);
2263e12c5d1SDavid du Colombier 	mf->tag = rhp->tag;
2273e12c5d1SDavid du Colombier 	switch(rhp->type){
2283e12c5d1SDavid du Colombier 	default:
2293e12c5d1SDavid du Colombier 		fatal("type");
2303e12c5d1SDavid du Colombier 		break;
2313e12c5d1SDavid du Colombier 	case Tsession:
232*219b2ee8SDavid du Colombier 		rsession();
2333e12c5d1SDavid du Colombier 		break;
2343e12c5d1SDavid du Colombier 	case Tnop:
2353e12c5d1SDavid du Colombier 		rsimple();
2363e12c5d1SDavid du Colombier 		break;
2373e12c5d1SDavid du Colombier 	case Tflush:
2383e12c5d1SDavid du Colombier 		rflush(rhp->tag);
2393e12c5d1SDavid du Colombier 		break;
2403e12c5d1SDavid du Colombier 	case Tattach:
2413e12c5d1SDavid du Colombier 		rattach(mf);
2423e12c5d1SDavid du Colombier 		break;
2433e12c5d1SDavid du Colombier 	case Tclone:
2443e12c5d1SDavid du Colombier 		rclone(mf);
2453e12c5d1SDavid du Colombier 		break;
2463e12c5d1SDavid du Colombier 	case Twalk:
2473e12c5d1SDavid du Colombier 		rwalk(mf);
2483e12c5d1SDavid du Colombier 		break;
2493e12c5d1SDavid du Colombier 	case Tclwalk:
2503e12c5d1SDavid du Colombier 		rclwalk(mf);
2513e12c5d1SDavid du Colombier 		break;
2523e12c5d1SDavid du Colombier 	case Topen:
2533e12c5d1SDavid du Colombier 		ropen(mf);
2543e12c5d1SDavid du Colombier 		break;
2553e12c5d1SDavid du Colombier 	case Tcreate:
2563e12c5d1SDavid du Colombier 		rcreate(mf);
2573e12c5d1SDavid du Colombier 		break;
2583e12c5d1SDavid du Colombier 	case Tread:
2593e12c5d1SDavid du Colombier 		rread(mf);
2603e12c5d1SDavid du Colombier 		break;
2613e12c5d1SDavid du Colombier 	case Twrite:
2623e12c5d1SDavid du Colombier 		rwrite(mf, &req);
2633e12c5d1SDavid du Colombier 		break;
2643e12c5d1SDavid du Colombier 	case Tclunk:
2653e12c5d1SDavid du Colombier 		rclunk(mf);
2663e12c5d1SDavid du Colombier 		break;
2673e12c5d1SDavid du Colombier 	case Tremove:
2683e12c5d1SDavid du Colombier 		rremove(mf);
2693e12c5d1SDavid du Colombier 		break;
2703e12c5d1SDavid du Colombier 	case Tstat:
2713e12c5d1SDavid du Colombier 		rstat(mf);
2723e12c5d1SDavid du Colombier 		break;
2733e12c5d1SDavid du Colombier 	case Twstat:
2743e12c5d1SDavid du Colombier 		rwstat(mf);
2753e12c5d1SDavid du Colombier 		break;
2763e12c5d1SDavid du Colombier 	}
2773e12c5d1SDavid du Colombier 	/*
2783e12c5d1SDavid du Colombier 	 *  slave processes die after replying
2793e12c5d1SDavid du Colombier 	 */
2803e12c5d1SDavid du Colombier 	if(req.isslave)
2813e12c5d1SDavid du Colombier 		_exits(0);
2823e12c5d1SDavid du Colombier 	goto loop;
2833e12c5d1SDavid du Colombier }
2843e12c5d1SDavid du Colombier 
2853e12c5d1SDavid du Colombier void
286*219b2ee8SDavid du Colombier rsession(void)
287*219b2ee8SDavid du Colombier {
288*219b2ee8SDavid du Colombier 	memset(thp->authid, 0, sizeof(thp->authid));
289*219b2ee8SDavid du Colombier 	memset(thp->authdom, 0, sizeof(thp->authdom));
290*219b2ee8SDavid du Colombier 	memset(thp->chal, 0, sizeof(thp->chal));
291*219b2ee8SDavid du Colombier 	sendmsg(0);
292*219b2ee8SDavid du Colombier }
293*219b2ee8SDavid du Colombier 
294*219b2ee8SDavid du Colombier void
2953e12c5d1SDavid du Colombier rsimple(void)
2963e12c5d1SDavid du Colombier {
2973e12c5d1SDavid du Colombier 	sendmsg(0);
2983e12c5d1SDavid du Colombier }
2993e12c5d1SDavid du Colombier 
3003e12c5d1SDavid du Colombier void
3013e12c5d1SDavid du Colombier rflush(int tag)
3023e12c5d1SDavid du Colombier {
3033e12c5d1SDavid du Colombier 	Mfile *mf;
3043e12c5d1SDavid du Colombier 
3053e12c5d1SDavid du Colombier 	for(mf = mfile; mf < &mfile[nmfile]; mf++){
3063e12c5d1SDavid du Colombier 		if(mf->busy == 0)
3073e12c5d1SDavid du Colombier 			continue;
3083e12c5d1SDavid du Colombier 		if(mf->tag == tag){
3093e12c5d1SDavid du Colombier 			mf->tag = -1;
3103e12c5d1SDavid du Colombier 			break;
3113e12c5d1SDavid du Colombier 		}
3123e12c5d1SDavid du Colombier 	}
3133e12c5d1SDavid du Colombier 	sendmsg(0);
3143e12c5d1SDavid du Colombier }
3153e12c5d1SDavid du Colombier 
3163e12c5d1SDavid du Colombier void
3173e12c5d1SDavid du Colombier rauth(void)
3183e12c5d1SDavid du Colombier {
3193e12c5d1SDavid du Colombier 	sendmsg("Authentication failed");
3203e12c5d1SDavid du Colombier }
3213e12c5d1SDavid du Colombier 
3223e12c5d1SDavid du Colombier void
3233e12c5d1SDavid du Colombier rattach(Mfile *mf)
3243e12c5d1SDavid du Colombier {
3253e12c5d1SDavid du Colombier 	if(mf->busy == 0){
3263e12c5d1SDavid du Colombier 		mf->busy = 1;
3273e12c5d1SDavid du Colombier 		strcpy(mf->user, rhp->uname);
3283e12c5d1SDavid du Colombier 	}
3293e12c5d1SDavid du Colombier 	mf->qid.vers = vers++;
3303e12c5d1SDavid du Colombier 	mf->qid.path = CHDIR;
3313e12c5d1SDavid du Colombier 	thp->qid = mf->qid;
3323e12c5d1SDavid du Colombier 	sendmsg(0);
3333e12c5d1SDavid du Colombier }
3343e12c5d1SDavid du Colombier 
3353e12c5d1SDavid du Colombier void
3363e12c5d1SDavid du Colombier rclone(Mfile *mf)
3373e12c5d1SDavid du Colombier {
3383e12c5d1SDavid du Colombier 	Mfile *nmf;
3393e12c5d1SDavid du Colombier 	char *err=0;
3403e12c5d1SDavid du Colombier 
3413e12c5d1SDavid du Colombier 	if(rhp->newfid<0){
3423e12c5d1SDavid du Colombier 		err = "clone nfid out of range";
3433e12c5d1SDavid du Colombier 		goto send;
3443e12c5d1SDavid du Colombier 	}
3453e12c5d1SDavid du Colombier 	nmf = newfid(rhp->newfid);
3463e12c5d1SDavid du Colombier 	if(nmf->busy){
3473e12c5d1SDavid du Colombier 		err = "clone to used channel";
3483e12c5d1SDavid du Colombier 		goto send;
3493e12c5d1SDavid du Colombier 	}
3503e12c5d1SDavid du Colombier 	*nmf = *mf;
3513e12c5d1SDavid du Colombier 	nmf->fid = rhp->newfid;
3523e12c5d1SDavid du Colombier 	nmf->qid.vers = vers++;
3533e12c5d1SDavid du Colombier     send:
3543e12c5d1SDavid du Colombier 	sendmsg(err);
3553e12c5d1SDavid du Colombier }
3563e12c5d1SDavid du Colombier 
3573e12c5d1SDavid du Colombier void
3583e12c5d1SDavid du Colombier rclwalk(Mfile *mf)
3593e12c5d1SDavid du Colombier {
3603e12c5d1SDavid du Colombier 	Mfile *nmf;
3613e12c5d1SDavid du Colombier 
3623e12c5d1SDavid du Colombier 	if(rhp->newfid<0){
3633e12c5d1SDavid du Colombier 		sendmsg("clone nfid out of range");
3643e12c5d1SDavid du Colombier 		return;
3653e12c5d1SDavid du Colombier 	}
3663e12c5d1SDavid du Colombier 	nmf = newfid(rhp->newfid);
3673e12c5d1SDavid du Colombier 	if(nmf->busy){
3683e12c5d1SDavid du Colombier 		sendmsg("clone to used channel");
3693e12c5d1SDavid du Colombier 		return;
3703e12c5d1SDavid du Colombier 	}
3713e12c5d1SDavid du Colombier 	*nmf = *mf;
3723e12c5d1SDavid du Colombier 	nmf->fid = rhp->newfid;
3733e12c5d1SDavid du Colombier 	rhp->fid = rhp->newfid;
3743e12c5d1SDavid du Colombier 	nmf->qid.vers = vers++;
3753e12c5d1SDavid du Colombier 	if(rwalk(nmf))
3763e12c5d1SDavid du Colombier 		nmf->busy = 0;
3773e12c5d1SDavid du Colombier }
3783e12c5d1SDavid du Colombier 
3793e12c5d1SDavid du Colombier char*
3803e12c5d1SDavid du Colombier rwalk(Mfile *mf)
3813e12c5d1SDavid du Colombier {
3823e12c5d1SDavid du Colombier 	char *err;
3833e12c5d1SDavid du Colombier 	char *name;
3843e12c5d1SDavid du Colombier 
3853e12c5d1SDavid du Colombier 	err = 0;
3863e12c5d1SDavid du Colombier 	name = rhp->name;
3873e12c5d1SDavid du Colombier 	if((mf->qid.path & CHDIR) == 0){
3883e12c5d1SDavid du Colombier 		err = "not a directory";
3893e12c5d1SDavid du Colombier 		goto send;
3903e12c5d1SDavid du Colombier 	}
3913e12c5d1SDavid du Colombier 	if(strcmp(name, ".") == 0){
3923e12c5d1SDavid du Colombier 		mf->qid.path = CHDIR;
3933e12c5d1SDavid du Colombier 		goto send;
3943e12c5d1SDavid du Colombier 	}
3953e12c5d1SDavid du Colombier 	if(strcmp(name, "dns") == 0){
3963e12c5d1SDavid du Colombier 		mf->qid.path = Qdns;
3973e12c5d1SDavid du Colombier 		goto send;
3983e12c5d1SDavid du Colombier 	}
3993e12c5d1SDavid du Colombier 	err = "nonexistent file";
4003e12c5d1SDavid du Colombier     send:
4013e12c5d1SDavid du Colombier 	thp->qid = mf->qid;
4023e12c5d1SDavid du Colombier 	sendmsg(err);
4033e12c5d1SDavid du Colombier 	return err;
4043e12c5d1SDavid du Colombier }
4053e12c5d1SDavid du Colombier 
4063e12c5d1SDavid du Colombier void
4073e12c5d1SDavid du Colombier ropen(Mfile *mf)
4083e12c5d1SDavid du Colombier {
4093e12c5d1SDavid du Colombier 	int mode;
4103e12c5d1SDavid du Colombier 	char *err;
4113e12c5d1SDavid du Colombier 
4123e12c5d1SDavid du Colombier 	err = 0;
4133e12c5d1SDavid du Colombier 	mode = rhp->mode;
4143e12c5d1SDavid du Colombier 	if(mf->qid.path & CHDIR){
4153e12c5d1SDavid du Colombier 		if(mode)
4163e12c5d1SDavid du Colombier 			err = "permission denied";
4173e12c5d1SDavid du Colombier 	}
4183e12c5d1SDavid du Colombier     send:
4193e12c5d1SDavid du Colombier 	thp->qid = mf->qid;
4203e12c5d1SDavid du Colombier 	sendmsg(err);
4213e12c5d1SDavid du Colombier }
4223e12c5d1SDavid du Colombier 
4233e12c5d1SDavid du Colombier void
4243e12c5d1SDavid du Colombier rcreate(Mfile *mf)
4253e12c5d1SDavid du Colombier {
4263e12c5d1SDavid du Colombier 	USED(mf);
4273e12c5d1SDavid du Colombier 	sendmsg("creation permission denied");
4283e12c5d1SDavid du Colombier }
4293e12c5d1SDavid du Colombier 
4303e12c5d1SDavid du Colombier void
4313e12c5d1SDavid du Colombier rread(Mfile *mf)
4323e12c5d1SDavid du Colombier {
4333e12c5d1SDavid du Colombier 	int n, cnt, len;
4343e12c5d1SDavid du Colombier 	long toff, off, clock;
4353e12c5d1SDavid du Colombier 	Dir dir;
4363e12c5d1SDavid du Colombier 	char buf[MAXFDATA];
4373e12c5d1SDavid du Colombier 	char *err;
4383e12c5d1SDavid du Colombier 	RR *rp;
4393e12c5d1SDavid du Colombier 
4403e12c5d1SDavid du Colombier 	n = 0;
4413e12c5d1SDavid du Colombier 	err = 0;
4423e12c5d1SDavid du Colombier 	off = rhp->offset;
4433e12c5d1SDavid du Colombier 	cnt = rhp->count;
4443e12c5d1SDavid du Colombier 	if(mf->qid.path & CHDIR){
4453e12c5d1SDavid du Colombier 		if(off%DIRLEN || cnt%DIRLEN){
4463e12c5d1SDavid du Colombier 			err = "bad offset";
4473e12c5d1SDavid du Colombier 			goto send;
4483e12c5d1SDavid du Colombier 		}
4493e12c5d1SDavid du Colombier 		clock = time(0);
4503e12c5d1SDavid du Colombier 		if(off == 0){
4513e12c5d1SDavid du Colombier 			memmove(dir.name, "dns", NAMELEN);
4523e12c5d1SDavid du Colombier 			dir.qid.vers = vers;
4533e12c5d1SDavid du Colombier 			dir.qid.path = Qdns;
4543e12c5d1SDavid du Colombier 			dir.mode = 0666;
4553e12c5d1SDavid du Colombier 			dir.length = 0;
4563e12c5d1SDavid du Colombier 			dir.hlength = 0;
4573e12c5d1SDavid du Colombier 			strcpy(dir.uid, mf->user);
4583e12c5d1SDavid du Colombier 			strcpy(dir.gid, mf->user);
4593e12c5d1SDavid du Colombier 			dir.atime = clock;	/* wrong */
4603e12c5d1SDavid du Colombier 			dir.mtime = clock;	/* wrong */
4613e12c5d1SDavid du Colombier 			convD2M(&dir, buf+n);
4623e12c5d1SDavid du Colombier 			n += DIRLEN;
4633e12c5d1SDavid du Colombier 		}
4643e12c5d1SDavid du Colombier 		thp->data = buf;
4653e12c5d1SDavid du Colombier 	} else {
4663e12c5d1SDavid du Colombier 		toff = 0;
4673e12c5d1SDavid du Colombier 		n = 0;
4683e12c5d1SDavid du Colombier 		thp->data = buf;
469*219b2ee8SDavid du Colombier 		for(rp = mf->rp; rp && tsame(mf->type, rp->type); rp = rp->next){
470bd389b36SDavid du Colombier 			len = snprint(buf, sizeof(buf), "%R", rp);
4713e12c5d1SDavid du Colombier 			if(toff + len > off){
4723e12c5d1SDavid du Colombier 				toff = off - toff;
4733e12c5d1SDavid du Colombier 				if(cnt > len - toff)
4743e12c5d1SDavid du Colombier 					cnt = len - toff;
4753e12c5d1SDavid du Colombier 				thp->data = buf + toff;
4763e12c5d1SDavid du Colombier 				n = cnt;
4773e12c5d1SDavid du Colombier 				break;
4783e12c5d1SDavid du Colombier 			}
4793e12c5d1SDavid du Colombier 			toff += len;
4803e12c5d1SDavid du Colombier 		}
4813e12c5d1SDavid du Colombier 	}
4823e12c5d1SDavid du Colombier send:
4833e12c5d1SDavid du Colombier 	thp->count = n;
4843e12c5d1SDavid du Colombier 	sendmsg(err);
4853e12c5d1SDavid du Colombier }
4863e12c5d1SDavid du Colombier 
4873e12c5d1SDavid du Colombier void
4883e12c5d1SDavid du Colombier rwrite(Mfile *mf, Request *req)
4893e12c5d1SDavid du Colombier {
4903e12c5d1SDavid du Colombier 	int cnt;
4913e12c5d1SDavid du Colombier 	char *err;
4923e12c5d1SDavid du Colombier 	char *atype;
4933e12c5d1SDavid du Colombier 
4943e12c5d1SDavid du Colombier 	err = 0;
4953e12c5d1SDavid du Colombier 	cnt = rhp->count;
4963e12c5d1SDavid du Colombier 	if(mf->qid.path & CHDIR){
4973e12c5d1SDavid du Colombier 		err = "can't write directory";
4983e12c5d1SDavid du Colombier 		goto send;
4993e12c5d1SDavid du Colombier 	}
5003e12c5d1SDavid du Colombier 	if(cnt >= Maxrequest){
5013e12c5d1SDavid du Colombier 		err = "request too long";
5023e12c5d1SDavid du Colombier 		goto send;
5033e12c5d1SDavid du Colombier 	}
5043e12c5d1SDavid du Colombier 	rhp->data[cnt] = 0;
5053e12c5d1SDavid du Colombier 
5063e12c5d1SDavid du Colombier 	/*
507*219b2ee8SDavid du Colombier 	 *  toggle debugging
508*219b2ee8SDavid du Colombier 	 */
509*219b2ee8SDavid du Colombier 	if(strncmp(rhp->data, "debug", 5)==0){
510*219b2ee8SDavid du Colombier 		debug ^= 1;
511*219b2ee8SDavid du Colombier 		goto send;
512*219b2ee8SDavid du Colombier 	} else if(strncmp(rhp->data, "dump", 4)==0){
513*219b2ee8SDavid du Colombier 		dndump("/lib/ndb/dnsdump");
514*219b2ee8SDavid du Colombier 		goto send;
515*219b2ee8SDavid du Colombier 	}
516*219b2ee8SDavid du Colombier 
517*219b2ee8SDavid du Colombier 	/*
5183e12c5d1SDavid du Colombier 	 *  break up request (into a name and a type)
5193e12c5d1SDavid du Colombier 	 */
5203e12c5d1SDavid du Colombier 	atype = strchr(rhp->data, ' ');
5213e12c5d1SDavid du Colombier 	if(atype == 0){
5223e12c5d1SDavid du Colombier 		err = "illegal request";
5233e12c5d1SDavid du Colombier 		goto send;
5243e12c5d1SDavid du Colombier 	} else
5253e12c5d1SDavid du Colombier 		*atype++ = 0;
5263e12c5d1SDavid du Colombier 
5273e12c5d1SDavid du Colombier 	mf->type = rrtype(atype);
5283e12c5d1SDavid du Colombier 	if(mf->type < 0){
5293e12c5d1SDavid du Colombier 		err = "unknown type";
5303e12c5d1SDavid du Colombier 		goto send;
5313e12c5d1SDavid du Colombier 	}
5323e12c5d1SDavid du Colombier 
5333e12c5d1SDavid du Colombier 	mf->rp = dnresolve(rhp->data, Cin, mf->type, req, 0);
5343e12c5d1SDavid du Colombier 	if(mf->rp == 0){
5353e12c5d1SDavid du Colombier 		err = "not found";
536*219b2ee8SDavid du Colombier 	}
5373e12c5d1SDavid du Colombier 
5383e12c5d1SDavid du Colombier 	/* don't reply if the request was flushed */
5393e12c5d1SDavid du Colombier 	if(mf->tag < 0)
5403e12c5d1SDavid du Colombier 		return;
5413e12c5d1SDavid du Colombier 
5423e12c5d1SDavid du Colombier     send:
5433e12c5d1SDavid du Colombier 	thp->count = cnt;
5443e12c5d1SDavid du Colombier 	sendmsg(err);
5453e12c5d1SDavid du Colombier }
5463e12c5d1SDavid du Colombier 
5473e12c5d1SDavid du Colombier void
5483e12c5d1SDavid du Colombier rclunk(Mfile *mf)
5493e12c5d1SDavid du Colombier {
5503e12c5d1SDavid du Colombier 	if(mf->rp){
5513e12c5d1SDavid du Colombier 		/* free resource records from the database */
5523e12c5d1SDavid du Colombier 		if(mf->rp->db)
5533e12c5d1SDavid du Colombier 			rrfreelist(mf->rp);
5543e12c5d1SDavid du Colombier 		mf->rp = 0;
5553e12c5d1SDavid du Colombier 	}
5563e12c5d1SDavid du Colombier 	mf->busy = 0;
5573e12c5d1SDavid du Colombier 	mf->fid = 0;
5583e12c5d1SDavid du Colombier 	sendmsg(0);
5593e12c5d1SDavid du Colombier }
5603e12c5d1SDavid du Colombier 
5613e12c5d1SDavid du Colombier void
5623e12c5d1SDavid du Colombier rremove(Mfile *mf)
5633e12c5d1SDavid du Colombier {
5643e12c5d1SDavid du Colombier 	USED(mf);
5653e12c5d1SDavid du Colombier 	sendmsg("remove permission denied");
5663e12c5d1SDavid du Colombier }
5673e12c5d1SDavid du Colombier 
5683e12c5d1SDavid du Colombier void
5693e12c5d1SDavid du Colombier rstat(Mfile *mf)
5703e12c5d1SDavid du Colombier {
5713e12c5d1SDavid du Colombier 	Dir dir;
5723e12c5d1SDavid du Colombier 
573*219b2ee8SDavid du Colombier 	if(mf->qid.path & CHDIR){
574*219b2ee8SDavid du Colombier 		strcpy(dir.name, ".");
575*219b2ee8SDavid du Colombier 		dir.mode = CHDIR|0555;
576*219b2ee8SDavid du Colombier 	} else {
577*219b2ee8SDavid du Colombier 		strcpy(dir.name, "dns");
5783e12c5d1SDavid du Colombier 		dir.mode = 0666;
579*219b2ee8SDavid du Colombier 	}
580*219b2ee8SDavid du Colombier 	dir.qid = mf->qid;
5813e12c5d1SDavid du Colombier 	dir.length = 0;
5823e12c5d1SDavid du Colombier 	dir.hlength = 0;
5833e12c5d1SDavid du Colombier 	strcpy(dir.uid, mf->user);
5843e12c5d1SDavid du Colombier 	strcpy(dir.gid, mf->user);
5853e12c5d1SDavid du Colombier 	dir.atime = dir.mtime = time(0);
5863e12c5d1SDavid du Colombier 	convD2M(&dir, (char*)thp->stat);
5873e12c5d1SDavid du Colombier 	sendmsg(0);
5883e12c5d1SDavid du Colombier }
5893e12c5d1SDavid du Colombier 
5903e12c5d1SDavid du Colombier void
5913e12c5d1SDavid du Colombier rwstat(Mfile *mf)
5923e12c5d1SDavid du Colombier {
5933e12c5d1SDavid du Colombier 	USED(mf);
5943e12c5d1SDavid du Colombier 	sendmsg("wstat permission denied");
5953e12c5d1SDavid du Colombier }
5963e12c5d1SDavid du Colombier 
5973e12c5d1SDavid du Colombier void
5983e12c5d1SDavid du Colombier sendmsg(char *err)
5993e12c5d1SDavid du Colombier {
6003e12c5d1SDavid du Colombier 	int n;
6013e12c5d1SDavid du Colombier 	char mdata[MAXFDATA + MAXMSG];
6023e12c5d1SDavid du Colombier 
6033e12c5d1SDavid du Colombier 	if(err){
6043e12c5d1SDavid du Colombier 		thp->type = Rerror;
605bd389b36SDavid du Colombier 		snprint(thp->ename, sizeof(thp->ename), "dns: %s", err);
6063e12c5d1SDavid du Colombier 	}else{
6073e12c5d1SDavid du Colombier 		thp->type = rhp->type+1;
6083e12c5d1SDavid du Colombier 		thp->fid = rhp->fid;
6093e12c5d1SDavid du Colombier 	}
6103e12c5d1SDavid du Colombier 	thp->tag = rhp->tag;
611*219b2ee8SDavid du Colombier 	if(debug)
612*219b2ee8SDavid du Colombier 		syslog(0, logfile, "%F", thp);
6133e12c5d1SDavid du Colombier 	n = convS2M(thp, mdata);
6143e12c5d1SDavid du Colombier 	if(write(mfd[1], mdata, n)!=n)
6153e12c5d1SDavid du Colombier 		fatal("mount write");
6163e12c5d1SDavid du Colombier }
6173e12c5d1SDavid du Colombier 
6183e12c5d1SDavid du Colombier int
6193e12c5d1SDavid du Colombier mygetfields(char *lp, char **fields, int n, char sep)
6203e12c5d1SDavid du Colombier {
6213e12c5d1SDavid du Colombier 	int i;
6223e12c5d1SDavid du Colombier 	char sep2=0;
6233e12c5d1SDavid du Colombier 
6243e12c5d1SDavid du Colombier 	if(sep == ' ')
6253e12c5d1SDavid du Colombier 		sep2 = '\t';
6263e12c5d1SDavid du Colombier 	for(i=0; lp && *lp && i<n; i++){
6273e12c5d1SDavid du Colombier 		if(*lp==sep || *lp==sep2)
6283e12c5d1SDavid du Colombier 			*lp++=0;
6293e12c5d1SDavid du Colombier 		if(*lp == 0)
6303e12c5d1SDavid du Colombier 			break;
6313e12c5d1SDavid du Colombier 		fields[i]=lp;
6323e12c5d1SDavid du Colombier 		while(*lp && *lp!=sep && *lp!=sep2)
6333e12c5d1SDavid du Colombier 			lp++;
6343e12c5d1SDavid du Colombier 	}
6353e12c5d1SDavid du Colombier 	return i;
6363e12c5d1SDavid du Colombier }
6373e12c5d1SDavid du Colombier 
6383e12c5d1SDavid du Colombier void
639bd389b36SDavid du Colombier warning(char *fmt, ...)
640bd389b36SDavid du Colombier {
641bd389b36SDavid du Colombier 	int n;
642bd389b36SDavid du Colombier 	char dnserr[128];
643bd389b36SDavid du Colombier 
644bd389b36SDavid du Colombier 	n = doprint(dnserr, dnserr+sizeof(dnserr), fmt, &fmt+1) - dnserr;
645bd389b36SDavid du Colombier 	dnserr[n] = 0;
646bd389b36SDavid du Colombier 	syslog(1, "dns", dnserr);
647bd389b36SDavid du Colombier }
648bd389b36SDavid du Colombier 
649bd389b36SDavid du Colombier void
6503e12c5d1SDavid du Colombier fatal(char *fmt, ...)
6513e12c5d1SDavid du Colombier {
6523e12c5d1SDavid du Colombier 	int n;
6533e12c5d1SDavid du Colombier 	char dnserr[128];
6543e12c5d1SDavid du Colombier 
6553e12c5d1SDavid du Colombier 	n = doprint(dnserr, dnserr+sizeof(dnserr), fmt, &fmt+1) - dnserr;
6563e12c5d1SDavid du Colombier 	dnserr[n] = 0;
6573e12c5d1SDavid du Colombier 	syslog(1, "dns", dnserr);
6583e12c5d1SDavid du Colombier 	abort();
6593e12c5d1SDavid du Colombier }
6603e12c5d1SDavid du Colombier 
6613e12c5d1SDavid du Colombier /*
6623e12c5d1SDavid du Colombier  *  create a slave process to handle a request to avoid one request blocking
6633e12c5d1SDavid du Colombier  *  another
6643e12c5d1SDavid du Colombier  */
6653e12c5d1SDavid du Colombier void
6663e12c5d1SDavid du Colombier slave(Request *req)
6673e12c5d1SDavid du Colombier {
6683e12c5d1SDavid du Colombier 	if(req->isslave)
6693e12c5d1SDavid du Colombier 		return;		/* we're already a slave process */
6703e12c5d1SDavid du Colombier 
6713e12c5d1SDavid du Colombier 	switch(rfork(RFPROC|RFNOTEG|RFMEM|RFNOWAIT)){
6723e12c5d1SDavid du Colombier 	case -1:
6733e12c5d1SDavid du Colombier 		break;
6743e12c5d1SDavid du Colombier 	case 0:
6753e12c5d1SDavid du Colombier 		req->isslave = 1;
6763e12c5d1SDavid du Colombier 		break;
6773e12c5d1SDavid du Colombier 	default:
6783e12c5d1SDavid du Colombier 		longjmp(req->mret, 1);
6793e12c5d1SDavid du Colombier 	}
6803e12c5d1SDavid du Colombier }
681