xref: /plan9/sys/src/cmd/ndb/cs.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 <ndb.h>
83e12c5d1SDavid du Colombier #include <ip.h>
9*219b2ee8SDavid du Colombier #include <lock.h>
103e12c5d1SDavid du Colombier 
113e12c5d1SDavid du Colombier enum
123e12c5d1SDavid du Colombier {
13*219b2ee8SDavid du Colombier 	Nreply=			8,
143e12c5d1SDavid du Colombier 	Maxreply=		256,
153e12c5d1SDavid du Colombier 	Maxrequest=		4*NAMELEN,
163e12c5d1SDavid du Colombier 	Ncache=			8,
173e12c5d1SDavid du Colombier 
183e12c5d1SDavid du Colombier 	Qcs=			1,
193e12c5d1SDavid du Colombier };
203e12c5d1SDavid du Colombier 
213e12c5d1SDavid du Colombier typedef struct Mfile	Mfile;
22*219b2ee8SDavid du Colombier typedef struct Mlist	Mlist;
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 {
293e12c5d1SDavid du Colombier 	int		busy;
30*219b2ee8SDavid du Colombier 
313e12c5d1SDavid du Colombier 	char		user[NAMELEN];
323e12c5d1SDavid du Colombier 	Qid		qid;
333e12c5d1SDavid du Colombier 	int		fid;
343e12c5d1SDavid du Colombier 
35*219b2ee8SDavid du Colombier 	int		nreply;
36*219b2ee8SDavid du Colombier 	char		*reply[Nreply];
37*219b2ee8SDavid du Colombier 	int		replylen[Nreply];
38*219b2ee8SDavid du Colombier };
39*219b2ee8SDavid du Colombier 
40*219b2ee8SDavid du Colombier struct Mlist
41*219b2ee8SDavid du Colombier {
42*219b2ee8SDavid du Colombier 	Mlist	*next;
43*219b2ee8SDavid du Colombier 	Mfile	mf;
443e12c5d1SDavid du Colombier };
453e12c5d1SDavid du Colombier 
463e12c5d1SDavid du Colombier Fcall	*rhp;
473e12c5d1SDavid du Colombier Fcall	*thp;
48*219b2ee8SDavid du Colombier Mlist	*mlist;
493e12c5d1SDavid du Colombier int	mfd[2];
503e12c5d1SDavid du Colombier char	user[NAMELEN];
513e12c5d1SDavid du Colombier int	debug;
523e12c5d1SDavid du Colombier jmp_buf	masterjmp;	/* return through here after a slave process has been created */
533e12c5d1SDavid du Colombier int	*isslave;	/* *isslave non-zero means this is a slave process */
54bd389b36SDavid du Colombier char	*dbfile;
553e12c5d1SDavid du Colombier 
56*219b2ee8SDavid du Colombier void	rsession(void);
573e12c5d1SDavid du Colombier void	rflush(void);
583e12c5d1SDavid du Colombier void	rattach(Mfile *);
593e12c5d1SDavid du Colombier void	rclone(Mfile *);
603e12c5d1SDavid du Colombier char*	rwalk(Mfile *);
613e12c5d1SDavid du Colombier void	rclwalk(Mfile *);
623e12c5d1SDavid du Colombier void	ropen(Mfile *);
633e12c5d1SDavid du Colombier void	rcreate(Mfile *);
643e12c5d1SDavid du Colombier void	rread(Mfile *);
653e12c5d1SDavid du Colombier void	rwrite(Mfile *);
663e12c5d1SDavid du Colombier void	rclunk(Mfile *);
673e12c5d1SDavid du Colombier void	rremove(Mfile *);
683e12c5d1SDavid du Colombier void	rstat(Mfile *);
693e12c5d1SDavid du Colombier void	rauth(void);
703e12c5d1SDavid du Colombier void	rwstat(Mfile *);
713e12c5d1SDavid du Colombier void	sendmsg(char*);
723e12c5d1SDavid du Colombier void	error(char*);
73*219b2ee8SDavid du Colombier void	mountinit(char*, ulong);
743e12c5d1SDavid du Colombier void	io(void);
753e12c5d1SDavid du Colombier void	netinit(void);
763e12c5d1SDavid du Colombier void	netadd(char*);
773e12c5d1SDavid du Colombier int	lookup(Mfile*, char*, char*, char*);
78*219b2ee8SDavid du Colombier char	*genquery(Mfile*, char*);
793e12c5d1SDavid du Colombier int	mygetfields(char*, char**, int, char);
80bd389b36SDavid du Colombier int	needproto(Network*, Ndbtuple*);
813e12c5d1SDavid du Colombier Ndbtuple*	lookval(Ndbtuple*, Ndbtuple*, char*, char*);
823e12c5d1SDavid du Colombier Ndbtuple*	reorder(Ndbtuple*, Ndbtuple*);
833e12c5d1SDavid du Colombier 
84bd389b36SDavid du Colombier extern void	paralloc(void);
85bd389b36SDavid du Colombier 
863e12c5d1SDavid du Colombier char *mname[]={
873e12c5d1SDavid du Colombier 	[Tnop]		"Tnop",
883e12c5d1SDavid du Colombier 	[Tsession]	"Tsession",
893e12c5d1SDavid du Colombier 	[Tflush]	"Tflush",
903e12c5d1SDavid du Colombier 	[Tattach]	"Tattach",
913e12c5d1SDavid du Colombier 	[Tclone]	"Tclone",
923e12c5d1SDavid du Colombier 	[Twalk]		"Twalk",
933e12c5d1SDavid du Colombier 	[Topen]		"Topen",
943e12c5d1SDavid du Colombier 	[Tcreate]	"Tcreate",
953e12c5d1SDavid du Colombier 	[Tclunk]	"Tclunk",
963e12c5d1SDavid du Colombier 	[Tread]		"Tread",
973e12c5d1SDavid du Colombier 	[Twrite]	"Twrite",
983e12c5d1SDavid du Colombier 	[Tremove]	"Tremove",
993e12c5d1SDavid du Colombier 	[Tstat]		"Tstat",
1003e12c5d1SDavid du Colombier 	[Twstat]	"Twstat",
1013e12c5d1SDavid du Colombier 			0,
1023e12c5d1SDavid du Colombier };
1033e12c5d1SDavid du Colombier 
104bd389b36SDavid du Colombier Lock	dblock;		/* mutex on database operations */
105bd389b36SDavid du Colombier 
106*219b2ee8SDavid du Colombier char *logfile = "cs";
107*219b2ee8SDavid du Colombier 
108*219b2ee8SDavid du Colombier 
1093e12c5d1SDavid du Colombier void
1103e12c5d1SDavid du Colombier main(int argc, char *argv[])
1113e12c5d1SDavid du Colombier {
1123e12c5d1SDavid du Colombier 	Fcall	rhdr;
1133e12c5d1SDavid du Colombier 	Fcall	thdr;
114*219b2ee8SDavid du Colombier 	char	*service = "#s/cs";
115*219b2ee8SDavid du Colombier 	int	justsetname;
1163e12c5d1SDavid du Colombier 
117*219b2ee8SDavid du Colombier 	justsetname = 0;
1183e12c5d1SDavid du Colombier 	rhp = &rhdr;
1193e12c5d1SDavid du Colombier 	thp = &thdr;
1203e12c5d1SDavid du Colombier 	ARGBEGIN{
1213e12c5d1SDavid du Colombier 	case 'd':
1223e12c5d1SDavid du Colombier 		debug = 1;
123*219b2ee8SDavid du Colombier 		service = "#s/dcs";
1243e12c5d1SDavid du Colombier 		break;
125bd389b36SDavid du Colombier 	case 'f':
126bd389b36SDavid du Colombier 		dbfile = ARGF();
127bd389b36SDavid du Colombier 		break;
128*219b2ee8SDavid du Colombier 	case 'n':
129*219b2ee8SDavid du Colombier 		justsetname = 1;
130*219b2ee8SDavid du Colombier 		break;
1313e12c5d1SDavid du Colombier 	}ARGEND
1323e12c5d1SDavid du Colombier 	USED(argc);
1333e12c5d1SDavid du Colombier 	USED(argv);
1343e12c5d1SDavid du Colombier 
135*219b2ee8SDavid du Colombier 	if(justsetname){
136*219b2ee8SDavid du Colombier 		netinit();
137*219b2ee8SDavid du Colombier 		exits(0);
138*219b2ee8SDavid du Colombier 	}
139*219b2ee8SDavid du Colombier 	unmount(service, "/net");
140*219b2ee8SDavid du Colombier 	remove(service);
141*219b2ee8SDavid du Colombier 	mountinit(service, MAFTER);
142*219b2ee8SDavid du Colombier 
143*219b2ee8SDavid du Colombier 	lockinit();
144*219b2ee8SDavid du Colombier 	fmtinstall('F', fcallconv);
1453e12c5d1SDavid du Colombier 	netinit();
1463e12c5d1SDavid du Colombier 
1473e12c5d1SDavid du Colombier 	io();
148*219b2ee8SDavid du Colombier 	exits(0);
1493e12c5d1SDavid du Colombier }
1503e12c5d1SDavid du Colombier 
1513e12c5d1SDavid du Colombier void
152*219b2ee8SDavid du Colombier mountinit(char *service, ulong flags)
1533e12c5d1SDavid du Colombier {
1543e12c5d1SDavid du Colombier 	int f;
1553e12c5d1SDavid du Colombier 	int p[2];
1563e12c5d1SDavid du Colombier 	char buf[32];
1573e12c5d1SDavid du Colombier 
1583e12c5d1SDavid du Colombier 	if(pipe(p) < 0)
1593e12c5d1SDavid du Colombier 		error("pipe failed");
160*219b2ee8SDavid du Colombier 	switch(rfork(RFFDG|RFPROC|RFNAMEG)){
1613e12c5d1SDavid du Colombier 	case 0:
162*219b2ee8SDavid du Colombier 		close(p[1]);
1633e12c5d1SDavid du Colombier 		break;
1643e12c5d1SDavid du Colombier 	case -1:
1653e12c5d1SDavid du Colombier 		error("fork failed\n");
1663e12c5d1SDavid du Colombier 	default:
1673e12c5d1SDavid du Colombier 		/*
1683e12c5d1SDavid du Colombier 		 *  make a /srv/cs
1693e12c5d1SDavid du Colombier 		 */
1703e12c5d1SDavid du Colombier 		f = create(service, 1, 0666);
1713e12c5d1SDavid du Colombier 		if(f < 0)
1723e12c5d1SDavid du Colombier 			error(service);
173bd389b36SDavid du Colombier 		snprint(buf, sizeof(buf), "%d", p[1]);
1743e12c5d1SDavid du Colombier 		if(write(f, buf, strlen(buf)) != strlen(buf))
175*219b2ee8SDavid du Colombier 			error("write /srv/cs");
1763e12c5d1SDavid du Colombier 		close(f);
1773e12c5d1SDavid du Colombier 
1783e12c5d1SDavid du Colombier 		/*
1793e12c5d1SDavid du Colombier 		 *  put ourselves into the file system
1803e12c5d1SDavid du Colombier 		 */
181*219b2ee8SDavid du Colombier 		close(p[0]);
182*219b2ee8SDavid du Colombier 		if(mount(p[1], "/net", flags, "") < 0)
1833e12c5d1SDavid du Colombier 			error("mount failed\n");
184*219b2ee8SDavid du Colombier 		_exits(0);
1853e12c5d1SDavid du Colombier 	}
1863e12c5d1SDavid du Colombier 	mfd[0] = mfd[1] = p[0];
1873e12c5d1SDavid du Colombier }
1883e12c5d1SDavid du Colombier 
1893e12c5d1SDavid du Colombier Mfile*
1903e12c5d1SDavid du Colombier newfid(int fid)
1913e12c5d1SDavid du Colombier {
192*219b2ee8SDavid du Colombier 	Mlist *f, *ff;
1933e12c5d1SDavid du Colombier 	Mfile *mf;
1943e12c5d1SDavid du Colombier 
195*219b2ee8SDavid du Colombier 	ff = 0;
196*219b2ee8SDavid du Colombier 	for(f = mlist; f; f = f->next)
197*219b2ee8SDavid du Colombier 		if(f->mf.busy && f->mf.fid == fid)
198*219b2ee8SDavid du Colombier 			return &f->mf;
199*219b2ee8SDavid du Colombier 		else if(!ff && !f->mf.busy)
200*219b2ee8SDavid du Colombier 			ff = f;
201*219b2ee8SDavid du Colombier 	if(ff == 0){
202*219b2ee8SDavid du Colombier 		ff = malloc(sizeof *f);
203*219b2ee8SDavid du Colombier 		if(ff == 0){
204*219b2ee8SDavid du Colombier 			fprint(2, "cs: malloc(%d)\n", sizeof *ff);
205*219b2ee8SDavid du Colombier 			error("malloc failure");
2063e12c5d1SDavid du Colombier 		}
207*219b2ee8SDavid du Colombier 		ff->next = mlist;
208*219b2ee8SDavid du Colombier 		mlist = ff;
2093e12c5d1SDavid du Colombier 	}
210*219b2ee8SDavid du Colombier 	mf = &ff->mf;
211*219b2ee8SDavid du Colombier 	memset(mf, 0, sizeof *mf);
2123e12c5d1SDavid du Colombier 	mf->fid = fid;
2133e12c5d1SDavid du Colombier 	return mf;
2143e12c5d1SDavid du Colombier }
2153e12c5d1SDavid du Colombier 
2163e12c5d1SDavid du Colombier void
2173e12c5d1SDavid du Colombier io(void)
2183e12c5d1SDavid du Colombier {
2193e12c5d1SDavid du Colombier 	long n;
2203e12c5d1SDavid du Colombier 	Mfile *mf;
2213e12c5d1SDavid du Colombier 	int slaveflag;
2223e12c5d1SDavid du Colombier 	char mdata[MAXFDATA + MAXMSG];
2233e12c5d1SDavid du Colombier 
2243e12c5d1SDavid du Colombier 	/*
2253e12c5d1SDavid du Colombier 	 *  if we ask dns to fulfill requests,
2263e12c5d1SDavid du Colombier 	 *  a slave process is created to wait for replies.  The
2273e12c5d1SDavid du Colombier 	 *  master process returns immediately via a longjmp's
2283e12c5d1SDavid du Colombier 	 *  through 'masterjmp'.
2293e12c5d1SDavid du Colombier 	 *
2303e12c5d1SDavid du Colombier 	 *  *isslave is a pointer into the call stack to a variable
2313e12c5d1SDavid du Colombier 	 *  that tells whether or not the current process is a slave.
2323e12c5d1SDavid du Colombier 	 */
2333e12c5d1SDavid du Colombier 	slaveflag = 0;		/* init slave variable */
2343e12c5d1SDavid du Colombier 	isslave = &slaveflag;
2353e12c5d1SDavid du Colombier 	setjmp(masterjmp);
2363e12c5d1SDavid du Colombier 
2373e12c5d1SDavid du Colombier 	for(;;){
238*219b2ee8SDavid du Colombier 		n = read9p(mfd[0], mdata, sizeof mdata);
2393e12c5d1SDavid du Colombier 		if(n<=0)
2403e12c5d1SDavid du Colombier 			error("mount read");
2413e12c5d1SDavid du Colombier 		if(convM2S(mdata, rhp, n) == 0){
242*219b2ee8SDavid du Colombier 			syslog(1, logfile, "format error %ux %ux %ux %ux %ux", mdata[0], mdata[1], mdata[2], mdata[3], mdata[4]);
2433e12c5d1SDavid du Colombier 			continue;
2443e12c5d1SDavid du Colombier 		}
2453e12c5d1SDavid du Colombier 		if(rhp->fid<0)
2463e12c5d1SDavid du Colombier 			error("fid out of range");
247bd389b36SDavid du Colombier 		lock(&dblock);
2483e12c5d1SDavid du Colombier 		mf = newfid(rhp->fid);
249*219b2ee8SDavid du Colombier 		if(debug)
250*219b2ee8SDavid du Colombier 			syslog(0, logfile, "%F", rhp);
2513e12c5d1SDavid du Colombier 
2523e12c5d1SDavid du Colombier 
2533e12c5d1SDavid du Colombier 		switch(rhp->type){
2543e12c5d1SDavid du Colombier 		default:
255*219b2ee8SDavid du Colombier 			syslog(1, logfile, "unknown request type %d", rhp->type);
2563e12c5d1SDavid du Colombier 			break;
2573e12c5d1SDavid du Colombier 		case Tsession:
258*219b2ee8SDavid du Colombier 			rsession();
2593e12c5d1SDavid du Colombier 			break;
2603e12c5d1SDavid du Colombier 		case Tnop:
2613e12c5d1SDavid du Colombier 			rflush();
2623e12c5d1SDavid du Colombier 			break;
2633e12c5d1SDavid du Colombier 		case Tflush:
2643e12c5d1SDavid du Colombier 			rflush();
2653e12c5d1SDavid du Colombier 			break;
2663e12c5d1SDavid du Colombier 		case Tattach:
2673e12c5d1SDavid du Colombier 			rattach(mf);
2683e12c5d1SDavid du Colombier 			break;
2693e12c5d1SDavid du Colombier 		case Tclone:
2703e12c5d1SDavid du Colombier 			rclone(mf);
2713e12c5d1SDavid du Colombier 			break;
2723e12c5d1SDavid du Colombier 		case Twalk:
2733e12c5d1SDavid du Colombier 			rwalk(mf);
2743e12c5d1SDavid du Colombier 			break;
2753e12c5d1SDavid du Colombier 		case Tclwalk:
2763e12c5d1SDavid du Colombier 			rclwalk(mf);
2773e12c5d1SDavid du Colombier 			break;
2783e12c5d1SDavid du Colombier 		case Topen:
2793e12c5d1SDavid du Colombier 			ropen(mf);
2803e12c5d1SDavid du Colombier 			break;
2813e12c5d1SDavid du Colombier 		case Tcreate:
2823e12c5d1SDavid du Colombier 			rcreate(mf);
2833e12c5d1SDavid du Colombier 			break;
2843e12c5d1SDavid du Colombier 		case Tread:
2853e12c5d1SDavid du Colombier 			rread(mf);
2863e12c5d1SDavid du Colombier 			break;
2873e12c5d1SDavid du Colombier 		case Twrite:
2883e12c5d1SDavid du Colombier 			rwrite(mf);
2893e12c5d1SDavid du Colombier 			break;
2903e12c5d1SDavid du Colombier 		case Tclunk:
2913e12c5d1SDavid du Colombier 			rclunk(mf);
2923e12c5d1SDavid du Colombier 			break;
2933e12c5d1SDavid du Colombier 		case Tremove:
2943e12c5d1SDavid du Colombier 			rremove(mf);
2953e12c5d1SDavid du Colombier 			break;
2963e12c5d1SDavid du Colombier 		case Tstat:
2973e12c5d1SDavid du Colombier 			rstat(mf);
2983e12c5d1SDavid du Colombier 			break;
2993e12c5d1SDavid du Colombier 		case Twstat:
3003e12c5d1SDavid du Colombier 			rwstat(mf);
3013e12c5d1SDavid du Colombier 			break;
3023e12c5d1SDavid du Colombier 		}
303bd389b36SDavid du Colombier 		unlock(&dblock);
3043e12c5d1SDavid du Colombier 		/*
3053e12c5d1SDavid du Colombier 		 *  slave processes die after replying
3063e12c5d1SDavid du Colombier 		 */
307*219b2ee8SDavid du Colombier 		if(*isslave){
308*219b2ee8SDavid du Colombier 			if(debug)
309*219b2ee8SDavid du Colombier 				syslog(0, logfile, "slave death %d", getpid());
3103e12c5d1SDavid du Colombier 			_exits(0);
3113e12c5d1SDavid du Colombier 		}
3123e12c5d1SDavid du Colombier 	}
313*219b2ee8SDavid du Colombier }
314*219b2ee8SDavid du Colombier 
315*219b2ee8SDavid du Colombier void
316*219b2ee8SDavid du Colombier rsession(void)
317*219b2ee8SDavid du Colombier {
318*219b2ee8SDavid du Colombier 	memset(thp->authid, 0, sizeof(thp->authid));
319*219b2ee8SDavid du Colombier 	memset(thp->authdom, 0, sizeof(thp->authdom));
320*219b2ee8SDavid du Colombier 	memset(thp->chal, 0, sizeof(thp->chal));
321*219b2ee8SDavid du Colombier 	sendmsg(0);
322*219b2ee8SDavid du Colombier }
3233e12c5d1SDavid du Colombier 
3243e12c5d1SDavid du Colombier void
3253e12c5d1SDavid du Colombier rflush(void)		/* synchronous so easy */
3263e12c5d1SDavid du Colombier {
3273e12c5d1SDavid du Colombier 	sendmsg(0);
3283e12c5d1SDavid du Colombier }
3293e12c5d1SDavid du Colombier 
3303e12c5d1SDavid du Colombier void
3313e12c5d1SDavid du Colombier rattach(Mfile *mf)
3323e12c5d1SDavid du Colombier {
3333e12c5d1SDavid du Colombier 	if(mf->busy == 0){
3343e12c5d1SDavid du Colombier 		mf->busy = 1;
3353e12c5d1SDavid du Colombier 		strcpy(mf->user, rhp->uname);
3363e12c5d1SDavid du Colombier 	}
3373e12c5d1SDavid du Colombier 	mf->qid.vers = vers++;
3383e12c5d1SDavid du Colombier 	mf->qid.path = CHDIR;
3393e12c5d1SDavid du Colombier 	thp->qid = mf->qid;
3403e12c5d1SDavid du Colombier 	sendmsg(0);
3413e12c5d1SDavid du Colombier }
3423e12c5d1SDavid du Colombier 
3433e12c5d1SDavid du Colombier void
3443e12c5d1SDavid du Colombier rclone(Mfile *mf)
3453e12c5d1SDavid du Colombier {
3463e12c5d1SDavid du Colombier 	Mfile *nmf;
3473e12c5d1SDavid du Colombier 	char *err=0;
3483e12c5d1SDavid du Colombier 
3493e12c5d1SDavid du Colombier 	if(rhp->newfid<0){
3503e12c5d1SDavid du Colombier 		err = "clone nfid out of range";
3513e12c5d1SDavid du Colombier 		goto send;
3523e12c5d1SDavid du Colombier 	}
3533e12c5d1SDavid du Colombier 	nmf = newfid(rhp->newfid);
3543e12c5d1SDavid du Colombier 	if(nmf->busy){
3553e12c5d1SDavid du Colombier 		err = "clone to used channel";
3563e12c5d1SDavid du Colombier 		goto send;
3573e12c5d1SDavid du Colombier 	}
3583e12c5d1SDavid du Colombier 	*nmf = *mf;
3593e12c5d1SDavid du Colombier 	nmf->fid = rhp->newfid;
3603e12c5d1SDavid du Colombier 	nmf->qid.vers = vers++;
3613e12c5d1SDavid du Colombier     send:
3623e12c5d1SDavid du Colombier 	sendmsg(err);
3633e12c5d1SDavid du Colombier }
3643e12c5d1SDavid du Colombier 
3653e12c5d1SDavid du Colombier void
3663e12c5d1SDavid du Colombier rclwalk(Mfile *mf)
3673e12c5d1SDavid du Colombier {
3683e12c5d1SDavid du Colombier 	Mfile *nmf;
3693e12c5d1SDavid du Colombier 
3703e12c5d1SDavid du Colombier 	if(rhp->newfid<0){
3713e12c5d1SDavid du Colombier 		sendmsg("clone nfid out of range");
3723e12c5d1SDavid du Colombier 		return;
3733e12c5d1SDavid du Colombier 	}
3743e12c5d1SDavid du Colombier 	nmf = newfid(rhp->newfid);
3753e12c5d1SDavid du Colombier 	if(nmf->busy){
3763e12c5d1SDavid du Colombier 		sendmsg("clone to used channel");
3773e12c5d1SDavid du Colombier 		return;
3783e12c5d1SDavid du Colombier 	}
3793e12c5d1SDavid du Colombier 	*nmf = *mf;
3803e12c5d1SDavid du Colombier 	nmf->fid = rhp->newfid;
3813e12c5d1SDavid du Colombier 	rhp->fid = rhp->newfid;
3823e12c5d1SDavid du Colombier 	nmf->qid.vers = vers++;
3833e12c5d1SDavid du Colombier 	if(rwalk(nmf))
3843e12c5d1SDavid du Colombier 		nmf->busy = 0;
3853e12c5d1SDavid du Colombier }
3863e12c5d1SDavid du Colombier 
3873e12c5d1SDavid du Colombier char*
3883e12c5d1SDavid du Colombier rwalk(Mfile *mf)
3893e12c5d1SDavid du Colombier {
3903e12c5d1SDavid du Colombier 	char *err;
3913e12c5d1SDavid du Colombier 	char *name;
3923e12c5d1SDavid du Colombier 
3933e12c5d1SDavid du Colombier 	err = 0;
3943e12c5d1SDavid du Colombier 	name = rhp->name;
3953e12c5d1SDavid du Colombier 	if((mf->qid.path & CHDIR) == 0){
3963e12c5d1SDavid du Colombier 		err = "not a directory";
3973e12c5d1SDavid du Colombier 		goto send;
3983e12c5d1SDavid du Colombier 	}
3993e12c5d1SDavid du Colombier 	if(strcmp(name, ".") == 0){
4003e12c5d1SDavid du Colombier 		mf->qid.path = CHDIR;
4013e12c5d1SDavid du Colombier 		goto send;
4023e12c5d1SDavid du Colombier 	}
4033e12c5d1SDavid du Colombier 	if(strcmp(name, "cs") == 0){
4043e12c5d1SDavid du Colombier 		mf->qid.path = Qcs;
4053e12c5d1SDavid du Colombier 		goto send;
4063e12c5d1SDavid du Colombier 	}
4073e12c5d1SDavid du Colombier 	err = "nonexistent file";
4083e12c5d1SDavid du Colombier     send:
4093e12c5d1SDavid du Colombier 	thp->qid = mf->qid;
4103e12c5d1SDavid du Colombier 	sendmsg(err);
4113e12c5d1SDavid du Colombier 	return err;
4123e12c5d1SDavid du Colombier }
4133e12c5d1SDavid du Colombier 
4143e12c5d1SDavid du Colombier void
4153e12c5d1SDavid du Colombier ropen(Mfile *mf)
4163e12c5d1SDavid du Colombier {
4173e12c5d1SDavid du Colombier 	int mode;
4183e12c5d1SDavid du Colombier 	char *err;
4193e12c5d1SDavid du Colombier 
4203e12c5d1SDavid du Colombier 	err = 0;
4213e12c5d1SDavid du Colombier 	mode = rhp->mode;
4223e12c5d1SDavid du Colombier 	if(mf->qid.path & CHDIR){
4233e12c5d1SDavid du Colombier 		if(mode)
4243e12c5d1SDavid du Colombier 			err = "permission denied";
4253e12c5d1SDavid du Colombier 	}
4263e12c5d1SDavid du Colombier     send:
4273e12c5d1SDavid du Colombier 	thp->qid = mf->qid;
4283e12c5d1SDavid du Colombier 	sendmsg(err);
4293e12c5d1SDavid du Colombier }
4303e12c5d1SDavid du Colombier 
4313e12c5d1SDavid du Colombier void
4323e12c5d1SDavid du Colombier rcreate(Mfile *mf)
4333e12c5d1SDavid du Colombier {
4343e12c5d1SDavid du Colombier 	USED(mf);
4353e12c5d1SDavid du Colombier 	sendmsg("creation permission denied");
4363e12c5d1SDavid du Colombier }
4373e12c5d1SDavid du Colombier 
4383e12c5d1SDavid du Colombier void
4393e12c5d1SDavid du Colombier rread(Mfile *mf)
4403e12c5d1SDavid du Colombier {
441*219b2ee8SDavid du Colombier 	int i, n, cnt;
442*219b2ee8SDavid du Colombier 	long off, toff, clock;
4433e12c5d1SDavid du Colombier 	Dir dir;
4443e12c5d1SDavid du Colombier 	char buf[MAXFDATA];
4453e12c5d1SDavid du Colombier 	char *err;
4463e12c5d1SDavid du Colombier 
4473e12c5d1SDavid du Colombier 	n = 0;
4483e12c5d1SDavid du Colombier 	err = 0;
4493e12c5d1SDavid du Colombier 	off = rhp->offset;
4503e12c5d1SDavid du Colombier 	cnt = rhp->count;
4513e12c5d1SDavid du Colombier 	if(mf->qid.path & CHDIR){
4523e12c5d1SDavid du Colombier 		if(off%DIRLEN || cnt%DIRLEN){
4533e12c5d1SDavid du Colombier 			err = "bad offset";
4543e12c5d1SDavid du Colombier 			goto send;
4553e12c5d1SDavid du Colombier 		}
4563e12c5d1SDavid du Colombier 		clock = time(0);
4573e12c5d1SDavid du Colombier 		if(off == 0){
4583e12c5d1SDavid du Colombier 			memmove(dir.name, "cs", NAMELEN);
4593e12c5d1SDavid du Colombier 			dir.qid.vers = vers;
4603e12c5d1SDavid du Colombier 			dir.qid.path = Qcs;
4613e12c5d1SDavid du Colombier 			dir.mode = 0666;
4623e12c5d1SDavid du Colombier 			dir.length = 0;
4633e12c5d1SDavid du Colombier 			dir.hlength = 0;
4643e12c5d1SDavid du Colombier 			strcpy(dir.uid, mf->user);
4653e12c5d1SDavid du Colombier 			strcpy(dir.gid, mf->user);
4663e12c5d1SDavid du Colombier 			dir.atime = clock;	/* wrong */
4673e12c5d1SDavid du Colombier 			dir.mtime = clock;	/* wrong */
4683e12c5d1SDavid du Colombier 			convD2M(&dir, buf+n);
4693e12c5d1SDavid du Colombier 			n += DIRLEN;
4703e12c5d1SDavid du Colombier 		}
4713e12c5d1SDavid du Colombier 		thp->data = buf;
4723e12c5d1SDavid du Colombier 	} else {
473*219b2ee8SDavid du Colombier 		toff = 0;
474*219b2ee8SDavid du Colombier 		for(i = 0; mf->reply[i] && i < mf->nreply; i++){
475*219b2ee8SDavid du Colombier 			n = mf->replylen[i];
476*219b2ee8SDavid du Colombier 			if(off < toff + n)
477*219b2ee8SDavid du Colombier 				break;
478*219b2ee8SDavid du Colombier 			toff += n;
4793e12c5d1SDavid du Colombier 		}
480*219b2ee8SDavid du Colombier 		if(i >= mf->nreply){
481*219b2ee8SDavid du Colombier 			n = 0;
482*219b2ee8SDavid du Colombier 			goto send;
483*219b2ee8SDavid du Colombier 		}
484*219b2ee8SDavid du Colombier 		thp->data = mf->reply[i] + (off - toff);
485*219b2ee8SDavid du Colombier 		if(cnt > toff - off + n)
486*219b2ee8SDavid du Colombier 			n = toff - off + n;
487*219b2ee8SDavid du Colombier 		else
488*219b2ee8SDavid du Colombier 			n = cnt;
4893e12c5d1SDavid du Colombier 	}
4903e12c5d1SDavid du Colombier send:
4913e12c5d1SDavid du Colombier 	thp->count = n;
4923e12c5d1SDavid du Colombier 	sendmsg(err);
4933e12c5d1SDavid du Colombier }
4943e12c5d1SDavid du Colombier 
4953e12c5d1SDavid du Colombier void
4963e12c5d1SDavid du Colombier rwrite(Mfile *mf)
4973e12c5d1SDavid du Colombier {
4983e12c5d1SDavid du Colombier 	int cnt, n;
4993e12c5d1SDavid du Colombier 	char *err;
5003e12c5d1SDavid du Colombier 	char *field[3];
5013e12c5d1SDavid du Colombier 	int rv;
5023e12c5d1SDavid du Colombier 
5033e12c5d1SDavid du Colombier 	err = 0;
5043e12c5d1SDavid du Colombier 	cnt = rhp->count;
5053e12c5d1SDavid du Colombier 	if(mf->qid.path & CHDIR){
5063e12c5d1SDavid du Colombier 		err = "can't write directory";
5073e12c5d1SDavid du Colombier 		goto send;
5083e12c5d1SDavid du Colombier 	}
5093e12c5d1SDavid du Colombier 	if(cnt >= Maxrequest){
5103e12c5d1SDavid du Colombier 		err = "request too long";
5113e12c5d1SDavid du Colombier 		goto send;
5123e12c5d1SDavid du Colombier 	}
5133e12c5d1SDavid du Colombier 	rhp->data[cnt] = 0;
5143e12c5d1SDavid du Colombier 
5153e12c5d1SDavid du Colombier 	/*
516*219b2ee8SDavid du Colombier 	 *  toggle debugging
517*219b2ee8SDavid du Colombier 	 */
518*219b2ee8SDavid du Colombier 	if(strncmp(rhp->data, "debug", 5)==0){
519*219b2ee8SDavid du Colombier 		debug ^= 1;
520*219b2ee8SDavid du Colombier 		syslog(1, logfile, "debug %d", debug);
521*219b2ee8SDavid du Colombier 		goto send;
522*219b2ee8SDavid du Colombier 	}
523*219b2ee8SDavid du Colombier 
524*219b2ee8SDavid du Colombier 	/*
5253e12c5d1SDavid du Colombier 	 *  add networks to the default list
5263e12c5d1SDavid du Colombier 	 */
5273e12c5d1SDavid du Colombier 	if(strncmp(rhp->data, "add ", 4)==0){
5283e12c5d1SDavid du Colombier 		if(rhp->data[cnt-1] == '\n')
5293e12c5d1SDavid du Colombier 			rhp->data[cnt-1] = 0;
5303e12c5d1SDavid du Colombier 		netadd(rhp->data+4);
5313e12c5d1SDavid du Colombier 		goto send;
5323e12c5d1SDavid du Colombier 	}
5333e12c5d1SDavid du Colombier 
5343e12c5d1SDavid du Colombier 	/*
535*219b2ee8SDavid du Colombier 	 *  look for a general query
536*219b2ee8SDavid du Colombier 	 */
537*219b2ee8SDavid du Colombier 	if(*rhp->data == '!'){
538*219b2ee8SDavid du Colombier 		err = genquery(mf, rhp->data+1);
539*219b2ee8SDavid du Colombier 		goto send;
540*219b2ee8SDavid du Colombier 	}
541*219b2ee8SDavid du Colombier 
542*219b2ee8SDavid du Colombier 	/*
5433e12c5d1SDavid du Colombier 	 *  break up name
5443e12c5d1SDavid du Colombier 	 */
5453e12c5d1SDavid du Colombier 	if(debug)
546*219b2ee8SDavid du Colombier 		syslog(0, logfile, "write %s", rhp->data);
5473e12c5d1SDavid du Colombier 
5483e12c5d1SDavid du Colombier 	n = mygetfields(rhp->data, field, 3, '!');
5493e12c5d1SDavid du Colombier 	rv = -1;
5503e12c5d1SDavid du Colombier 	switch(n){
5513e12c5d1SDavid du Colombier 	case 1:
5523e12c5d1SDavid du Colombier 		rv = lookup(mf, "net", field[0], 0);
5533e12c5d1SDavid du Colombier 		break;
5543e12c5d1SDavid du Colombier 	case 2:
5553e12c5d1SDavid du Colombier 		rv = lookup(mf, field[0], field[1], 0);
5563e12c5d1SDavid du Colombier 		break;
5573e12c5d1SDavid du Colombier 	case 3:
5583e12c5d1SDavid du Colombier 		rv = lookup(mf, field[0], field[1], field[2]);
5593e12c5d1SDavid du Colombier 		break;
5603e12c5d1SDavid du Colombier 	}
5613e12c5d1SDavid du Colombier 
5623e12c5d1SDavid du Colombier 	if(rv < 0)
5633e12c5d1SDavid du Colombier 		err = "can't translate address";
5643e12c5d1SDavid du Colombier 
5653e12c5d1SDavid du Colombier     send:
5663e12c5d1SDavid du Colombier 	thp->count = cnt;
5673e12c5d1SDavid du Colombier 	sendmsg(err);
5683e12c5d1SDavid du Colombier }
5693e12c5d1SDavid du Colombier 
5703e12c5d1SDavid du Colombier void
5713e12c5d1SDavid du Colombier rclunk(Mfile *mf)
5723e12c5d1SDavid du Colombier {
573*219b2ee8SDavid du Colombier 	int i;
574*219b2ee8SDavid du Colombier 
575*219b2ee8SDavid du Colombier 	for(i = 0; i < mf->nreply; i++)
576*219b2ee8SDavid du Colombier 		free(mf->reply[i]);
5773e12c5d1SDavid du Colombier 	mf->busy = 0;
5783e12c5d1SDavid du Colombier 	mf->fid = 0;
5793e12c5d1SDavid du Colombier 	sendmsg(0);
5803e12c5d1SDavid du Colombier }
5813e12c5d1SDavid du Colombier 
5823e12c5d1SDavid du Colombier void
5833e12c5d1SDavid du Colombier rremove(Mfile *mf)
5843e12c5d1SDavid du Colombier {
5853e12c5d1SDavid du Colombier 	USED(mf);
5863e12c5d1SDavid du Colombier 	sendmsg("remove permission denied");
5873e12c5d1SDavid du Colombier }
5883e12c5d1SDavid du Colombier 
5893e12c5d1SDavid du Colombier void
5903e12c5d1SDavid du Colombier rstat(Mfile *mf)
5913e12c5d1SDavid du Colombier {
5923e12c5d1SDavid du Colombier 	Dir dir;
5933e12c5d1SDavid du Colombier 
594*219b2ee8SDavid du Colombier 	if(mf->qid.path & CHDIR){
595*219b2ee8SDavid du Colombier 		strcpy(dir.name, ".");
596*219b2ee8SDavid du Colombier 		dir.mode = CHDIR|0555;
597*219b2ee8SDavid du Colombier 	} else {
598*219b2ee8SDavid du Colombier 		strcpy(dir.name, "cs");
5993e12c5d1SDavid du Colombier 		dir.mode = 0666;
600*219b2ee8SDavid du Colombier 	}
601*219b2ee8SDavid du Colombier 	dir.qid = mf->qid;
6023e12c5d1SDavid du Colombier 	dir.length = 0;
6033e12c5d1SDavid du Colombier 	dir.hlength = 0;
6043e12c5d1SDavid du Colombier 	strcpy(dir.uid, mf->user);
6053e12c5d1SDavid du Colombier 	strcpy(dir.gid, mf->user);
6063e12c5d1SDavid du Colombier 	dir.atime = dir.mtime = time(0);
6073e12c5d1SDavid du Colombier 	convD2M(&dir, (char*)thp->stat);
6083e12c5d1SDavid du Colombier 	sendmsg(0);
6093e12c5d1SDavid du Colombier }
6103e12c5d1SDavid du Colombier 
6113e12c5d1SDavid du Colombier void
6123e12c5d1SDavid du Colombier rwstat(Mfile *mf)
6133e12c5d1SDavid du Colombier {
6143e12c5d1SDavid du Colombier 	USED(mf);
6153e12c5d1SDavid du Colombier 	sendmsg("wstat permission denied");
6163e12c5d1SDavid du Colombier }
6173e12c5d1SDavid du Colombier 
6183e12c5d1SDavid du Colombier void
6193e12c5d1SDavid du Colombier sendmsg(char *err)
6203e12c5d1SDavid du Colombier {
6213e12c5d1SDavid du Colombier 	int n;
6223e12c5d1SDavid du Colombier 	char mdata[MAXFDATA + MAXMSG];
6233e12c5d1SDavid du Colombier 
6243e12c5d1SDavid du Colombier 	if(err){
6253e12c5d1SDavid du Colombier 		thp->type = Rerror;
626bd389b36SDavid du Colombier 		snprint(thp->ename, sizeof(thp->ename), "cs: %s", err);
6273e12c5d1SDavid du Colombier 	}else{
6283e12c5d1SDavid du Colombier 		thp->type = rhp->type+1;
6293e12c5d1SDavid du Colombier 		thp->fid = rhp->fid;
6303e12c5d1SDavid du Colombier 	}
6313e12c5d1SDavid du Colombier 	thp->tag = rhp->tag;
6323e12c5d1SDavid du Colombier 	n = convS2M(thp, mdata);
633*219b2ee8SDavid du Colombier 	if(n == 0){
634*219b2ee8SDavid du Colombier 		syslog(1, logfile, "sendmsg convS2M of %F returns 0", thp);
635*219b2ee8SDavid du Colombier 		abort();
636*219b2ee8SDavid du Colombier 	}
637*219b2ee8SDavid du Colombier 	if(write9p(mfd[1], mdata, n)!=n)
6383e12c5d1SDavid du Colombier 		error("mount write");
639*219b2ee8SDavid du Colombier 	if(debug)
640*219b2ee8SDavid du Colombier 		syslog(0, logfile, "%F %d", thp, n);
6413e12c5d1SDavid du Colombier }
6423e12c5d1SDavid du Colombier 
6433e12c5d1SDavid du Colombier void
6443e12c5d1SDavid du Colombier error(char *s)
6453e12c5d1SDavid du Colombier {
646bd389b36SDavid du Colombier 	syslog(1, "cs", "%s: %r", s);
647bd389b36SDavid du Colombier 	_exits(0);
6483e12c5d1SDavid du Colombier }
6493e12c5d1SDavid du Colombier 
6503e12c5d1SDavid du Colombier /*
6513e12c5d1SDavid du Colombier  *  Network specific translators
6523e12c5d1SDavid du Colombier  */
653*219b2ee8SDavid du Colombier Ndbtuple*	iplookup(Network*, char*, char*, int);
654*219b2ee8SDavid du Colombier char*		iptrans(Ndbtuple*, Network*, char*);
655*219b2ee8SDavid du Colombier Ndbtuple*	dklookup(Network*, char*, char*, int);
656*219b2ee8SDavid du Colombier char*		dktrans(Ndbtuple*, Network*, char*);
657*219b2ee8SDavid du Colombier Ndbtuple*	telcolookup(Network*, char*, char*, int);
658*219b2ee8SDavid du Colombier char*		telcotrans(Ndbtuple*, Network*, char*);
6593e12c5d1SDavid du Colombier Ndbtuple*	dnsiplookup(char*, Ndbs*, char*);
6603e12c5d1SDavid du Colombier 
6613e12c5d1SDavid du Colombier struct Network
6623e12c5d1SDavid du Colombier {
6633e12c5d1SDavid du Colombier 	char		*net;
6643e12c5d1SDavid du Colombier 	int		nolookup;
665*219b2ee8SDavid du Colombier 	Ndbtuple	*(*lookup)(Network*, char*, char*, int);
666*219b2ee8SDavid du Colombier 	char		*(*trans)(Ndbtuple*, Network*, char*);
6673e12c5d1SDavid du Colombier 	int		needproto;
6683e12c5d1SDavid du Colombier 	Network		*next;
6693e12c5d1SDavid du Colombier 	int		def;
6703e12c5d1SDavid du Colombier };
6713e12c5d1SDavid du Colombier 
6723e12c5d1SDavid du Colombier Network network[] = {
6733e12c5d1SDavid du Colombier 	{ "il",		0,	iplookup,	iptrans,	1, },
674*219b2ee8SDavid du Colombier 	{ "fil",	0,	iplookup,	iptrans,	1, },
6753e12c5d1SDavid du Colombier 	{ "tcp",	0,	iplookup,	iptrans,	0, },
6763e12c5d1SDavid du Colombier 	{ "udp",	0,	iplookup,	iptrans,	0, },
6773e12c5d1SDavid du Colombier 	{ "dk",		1,	dklookup,	dktrans,	0, },
678*219b2ee8SDavid du Colombier 	{ "telco",	0,	telcolookup,	telcotrans,	0, },
6793e12c5d1SDavid du Colombier 	{ 0,		0, 	0,		0,		0, },
6803e12c5d1SDavid du Colombier };
6813e12c5d1SDavid du Colombier 
6823e12c5d1SDavid du Colombier char	eaddr[Ndbvlen];		/* ascii ethernet address */
6833e12c5d1SDavid du Colombier char	ipaddr[Ndbvlen];	/* ascii internet address */
6843e12c5d1SDavid du Colombier char	dknet[Ndbvlen];		/* ascii datakit network name */
6853e12c5d1SDavid du Colombier uchar	ipa[4];			/* binary internet address */
6863e12c5d1SDavid du Colombier char	sysname[Ndbvlen];
6873e12c5d1SDavid du Colombier int	isdk;
6883e12c5d1SDavid du Colombier 
6893e12c5d1SDavid du Colombier Network *netlist;		/* networks ordered by preference */
6903e12c5d1SDavid du Colombier Network *last;
6913e12c5d1SDavid du Colombier 
6923e12c5d1SDavid du Colombier static Ndb *db;
6933e12c5d1SDavid du Colombier 
6943e12c5d1SDavid du Colombier 
6953e12c5d1SDavid du Colombier /*
6963e12c5d1SDavid du Colombier  *  get ip address and system name
6973e12c5d1SDavid du Colombier  */
6983e12c5d1SDavid du Colombier void
6993e12c5d1SDavid du Colombier ipid(void)
7003e12c5d1SDavid du Colombier {
7013e12c5d1SDavid du Colombier 	uchar addr[6];
7023e12c5d1SDavid du Colombier 	Ndbtuple *t;
703*219b2ee8SDavid du Colombier 	char *p, *attr;
7043e12c5d1SDavid du Colombier 	Ndbs s;
7053e12c5d1SDavid du Colombier 	int f;
7063e12c5d1SDavid du Colombier 	static int isether;
7073e12c5d1SDavid du Colombier 
7083e12c5d1SDavid du Colombier 	/* grab ether addr from the device */
7093e12c5d1SDavid du Colombier 	if(isether == 0){
7103e12c5d1SDavid du Colombier 		if(myetheraddr(addr, "/net/ether") >= 0){
711bd389b36SDavid du Colombier 			snprint(eaddr, sizeof(eaddr), "%E", addr);
7123e12c5d1SDavid du Colombier 			isether = 1;
7133e12c5d1SDavid du Colombier 		}
7143e12c5d1SDavid du Colombier 	}
7153e12c5d1SDavid du Colombier 
7163e12c5d1SDavid du Colombier 	/* grab ip addr from the device */
7173e12c5d1SDavid du Colombier 	if(*ipa == 0){
7183e12c5d1SDavid du Colombier 		if(myipaddr(ipa, "/net/tcp") >= 0){
7193e12c5d1SDavid du Colombier 			if(*ipa)
720bd389b36SDavid du Colombier 				snprint(ipaddr, sizeof(ipaddr), "%I", ipa);
7213e12c5d1SDavid du Colombier 		}
7223e12c5d1SDavid du Colombier 	}
7233e12c5d1SDavid du Colombier 
7243e12c5d1SDavid du Colombier 	/* use ether addr plus db to get ipaddr */
7253e12c5d1SDavid du Colombier 	if(*ipa == 0 && isether){
7263e12c5d1SDavid du Colombier 		t = ndbgetval(db, &s, "ether", eaddr, "ip", ipaddr);
7273e12c5d1SDavid du Colombier 		if(t){
7283e12c5d1SDavid du Colombier 			ndbfree(t);
7293e12c5d1SDavid du Colombier 			parseip(ipa, ipaddr);
7303e12c5d1SDavid du Colombier 		}
7313e12c5d1SDavid du Colombier 	}
7323e12c5d1SDavid du Colombier 
733*219b2ee8SDavid du Colombier 	/* use environment, ether addr, or ipaddr to get system name */
7343e12c5d1SDavid du Colombier 	if(*sysname == 0){
735*219b2ee8SDavid du Colombier 		/* environment has priority */
736*219b2ee8SDavid du Colombier 		p = getenv("sysname");
737*219b2ee8SDavid du Colombier 		if(p ){
738*219b2ee8SDavid du Colombier 			attr = ipattr(p);
739*219b2ee8SDavid du Colombier 			if(strcmp(attr, "ip") != 0)
740*219b2ee8SDavid du Colombier 				strcpy(sysname, p);
741*219b2ee8SDavid du Colombier 		}
742*219b2ee8SDavid du Colombier 
743*219b2ee8SDavid du Colombier 		/* next use ether and ip addresses to find system name */
744*219b2ee8SDavid du Colombier 		if(*sysname == 0){
7453e12c5d1SDavid du Colombier 			t = 0;
7463e12c5d1SDavid du Colombier 			if(isether)
7473e12c5d1SDavid du Colombier 				t = ndbgetval(db, &s, "ether", eaddr, "sys", sysname);
7483e12c5d1SDavid du Colombier 			if(t == 0 && *ipa)
7493e12c5d1SDavid du Colombier 				t = ndbgetval(db, &s, "ip", ipaddr, "sys", sysname);
750*219b2ee8SDavid du Colombier 			if(t)
751*219b2ee8SDavid du Colombier 				ndbfree(t);
752*219b2ee8SDavid du Colombier 		}
7533e12c5d1SDavid du Colombier 
7543e12c5d1SDavid du Colombier 		/* set /dev/sysname if we now know it */
755*219b2ee8SDavid du Colombier 		if(*sysname){
7563e12c5d1SDavid du Colombier 			f = open("/dev/sysname", OWRITE);
7573e12c5d1SDavid du Colombier 			if(f >= 0){
7583e12c5d1SDavid du Colombier 				write(f, sysname, strlen(sysname));
7593e12c5d1SDavid du Colombier 				close(f);
7603e12c5d1SDavid du Colombier 			}
7613e12c5d1SDavid du Colombier 		}
7623e12c5d1SDavid du Colombier 	}
7633e12c5d1SDavid du Colombier }
7643e12c5d1SDavid du Colombier 
7653e12c5d1SDavid du Colombier /*
7663e12c5d1SDavid du Colombier  *  set the datakit network name from a datakit network address
7673e12c5d1SDavid du Colombier  */
7683e12c5d1SDavid du Colombier int
7693e12c5d1SDavid du Colombier setdknet(char *x)
7703e12c5d1SDavid du Colombier {
7713e12c5d1SDavid du Colombier 	char *p;
7723e12c5d1SDavid du Colombier 
7733e12c5d1SDavid du Colombier 	strncpy(dknet, x, sizeof(dknet)-2);
7743e12c5d1SDavid du Colombier 	p = strrchr(dknet, '/');
7753e12c5d1SDavid du Colombier 	if(p == 0 || p == strchr(dknet, '/')){
7763e12c5d1SDavid du Colombier 		*dknet = 0;
7773e12c5d1SDavid du Colombier 		return 0;
7783e12c5d1SDavid du Colombier 	}
7793e12c5d1SDavid du Colombier 	*++p = '*';
7803e12c5d1SDavid du Colombier 	*(p+1) = 0;
7813e12c5d1SDavid du Colombier 	return 1;
7823e12c5d1SDavid du Colombier }
7833e12c5d1SDavid du Colombier 
7843e12c5d1SDavid du Colombier /*
7853e12c5d1SDavid du Colombier  *  get datakit address
7863e12c5d1SDavid du Colombier  */
7873e12c5d1SDavid du Colombier void
7883e12c5d1SDavid du Colombier dkid(void)
7893e12c5d1SDavid du Colombier {
7903e12c5d1SDavid du Colombier 	Ndbtuple *t;
7913e12c5d1SDavid du Colombier 	Ndbs s;
7923e12c5d1SDavid du Colombier 	char dkname[Ndbvlen];
7933e12c5d1SDavid du Colombier 	char raddr[Ndbvlen];
7943e12c5d1SDavid du Colombier 	int i, f, n;
7953e12c5d1SDavid du Colombier 	static int isdknet;
7963e12c5d1SDavid du Colombier 
7973e12c5d1SDavid du Colombier 	/* try for a datakit network name in the database */
7983e12c5d1SDavid du Colombier 	if(isdknet == 0){
7993e12c5d1SDavid du Colombier 		/* use ether and ip addresses to find dk name */
8003e12c5d1SDavid du Colombier 		t = 0;
8013e12c5d1SDavid du Colombier 		if(t == 0 && *ipa)
8023e12c5d1SDavid du Colombier 			t = ndbgetval(db, &s, "ip", ipaddr, "dk", dkname);
8033e12c5d1SDavid du Colombier 		if(t == 0 && *sysname)
8043e12c5d1SDavid du Colombier 			t = ndbgetval(db, &s, "sys", sysname, "dk", dkname);
8053e12c5d1SDavid du Colombier 		if(t){
8063e12c5d1SDavid du Colombier 			ndbfree(t);
8073e12c5d1SDavid du Colombier 			isdknet = setdknet(dkname);
8083e12c5d1SDavid du Colombier 		}
8093e12c5d1SDavid du Colombier 	}
8103e12c5d1SDavid du Colombier 
8113e12c5d1SDavid du Colombier 	/* try for a datakit network name from a system we've connected to */
8123e12c5d1SDavid du Colombier 	if(isdknet == 0){
8133e12c5d1SDavid du Colombier 		for(i = 0; isdknet == 0 && i < 7; i++){
814bd389b36SDavid du Colombier 			snprint(raddr, sizeof(raddr), "/net/dk/%d/remote", i);
8153e12c5d1SDavid du Colombier 			f = open(raddr, OREAD);
8163e12c5d1SDavid du Colombier 			if(f < 0){
8173e12c5d1SDavid du Colombier 				isdknet = -1;
8183e12c5d1SDavid du Colombier 				break;
8193e12c5d1SDavid du Colombier 			}
8203e12c5d1SDavid du Colombier 			n = read(f, raddr, sizeof(raddr)-1);
8213e12c5d1SDavid du Colombier 			close(f);
8223e12c5d1SDavid du Colombier 			if(n > 0){
8233e12c5d1SDavid du Colombier 				raddr[n] = 0;
8243e12c5d1SDavid du Colombier 				isdknet = setdknet(raddr);
8253e12c5d1SDavid du Colombier 			}
8263e12c5d1SDavid du Colombier 		}
8273e12c5d1SDavid du Colombier 	}
828*219b2ee8SDavid du Colombier 	/* hack for gnots */
829*219b2ee8SDavid du Colombier 	if(isdknet <= 0)
830*219b2ee8SDavid du Colombier 		isdknet = setdknet("nj/astro/Nfs");
8313e12c5d1SDavid du Colombier }
8323e12c5d1SDavid du Colombier 
8333e12c5d1SDavid du Colombier /*
8343e12c5d1SDavid du Colombier  *  Set up a list of default networks by looking for
8353e12c5d1SDavid du Colombier  *  /net/ * /clone.
8363e12c5d1SDavid du Colombier  */
8373e12c5d1SDavid du Colombier void
8383e12c5d1SDavid du Colombier netinit(void)
8393e12c5d1SDavid du Colombier {
8403e12c5d1SDavid du Colombier 	char clone[256];
8413e12c5d1SDavid du Colombier 	Dir d;
8423e12c5d1SDavid du Colombier 	Network *np;
8433e12c5d1SDavid du Colombier 
8443e12c5d1SDavid du Colombier 	/* add the mounted networks to the default list */
8453e12c5d1SDavid du Colombier 	for(np = network; np->net; np++){
846bd389b36SDavid du Colombier 		snprint(clone, sizeof(clone), "/net/%s/clone", np->net);
8473e12c5d1SDavid du Colombier 		if(dirstat(clone, &d) < 0)
8483e12c5d1SDavid du Colombier 			continue;
8493e12c5d1SDavid du Colombier 		if(netlist)
8503e12c5d1SDavid du Colombier 			last->next = np;
8513e12c5d1SDavid du Colombier 		else
8523e12c5d1SDavid du Colombier 			netlist = np;
8533e12c5d1SDavid du Colombier 		last = np;
8543e12c5d1SDavid du Colombier 		np->next = 0;
8553e12c5d1SDavid du Colombier 		np->def = 1;
8563e12c5d1SDavid du Colombier 	}
8573e12c5d1SDavid du Colombier 
8583e12c5d1SDavid du Colombier 	fmtinstall('E', eipconv);
8593e12c5d1SDavid du Colombier 	fmtinstall('I', eipconv);
8603e12c5d1SDavid du Colombier 
861bd389b36SDavid du Colombier 	db = ndbopen(dbfile);
8623e12c5d1SDavid du Colombier 	ipid();
8633e12c5d1SDavid du Colombier 	dkid();
8643e12c5d1SDavid du Colombier 
865*219b2ee8SDavid du Colombier 	if(debug)
866*219b2ee8SDavid du Colombier 		syslog(0, logfile, "sysname %s dknet %s eaddr %s ipaddr %s ipa %I\n",
8673e12c5d1SDavid du Colombier 			sysname, dknet, eaddr, ipaddr, ipa);
8683e12c5d1SDavid du Colombier }
8693e12c5d1SDavid du Colombier 
8703e12c5d1SDavid du Colombier /*
8713e12c5d1SDavid du Colombier  *  add networks to the standard list
8723e12c5d1SDavid du Colombier  */
8733e12c5d1SDavid du Colombier void
8743e12c5d1SDavid du Colombier netadd(char *p)
8753e12c5d1SDavid du Colombier {
8763e12c5d1SDavid du Colombier 	Network *np;
8773e12c5d1SDavid du Colombier 	char *field[12];
8783e12c5d1SDavid du Colombier 	int i, n;
8793e12c5d1SDavid du Colombier 
8803e12c5d1SDavid du Colombier 	n = mygetfields(p, field, 12, ' ');
8813e12c5d1SDavid du Colombier 	for(i = 0; i < n; i++){
8823e12c5d1SDavid du Colombier 		for(np = network; np->net; np++){
8833e12c5d1SDavid du Colombier 			if(strcmp(field[i], np->net) != 0)
8843e12c5d1SDavid du Colombier 				continue;
8853e12c5d1SDavid du Colombier 			if(np->def)
8863e12c5d1SDavid du Colombier 				break;
8873e12c5d1SDavid du Colombier 			if(netlist)
8883e12c5d1SDavid du Colombier 				last->next = np;
8893e12c5d1SDavid du Colombier 			else
8903e12c5d1SDavid du Colombier 				netlist = np;
8913e12c5d1SDavid du Colombier 			last = np;
8923e12c5d1SDavid du Colombier 			np->next = 0;
8933e12c5d1SDavid du Colombier 			np->def = 1;
8943e12c5d1SDavid du Colombier 		}
8953e12c5d1SDavid du Colombier 	}
8963e12c5d1SDavid du Colombier }
8973e12c5d1SDavid du Colombier 
8983e12c5d1SDavid du Colombier /*
899*219b2ee8SDavid du Colombier  *  make a tuple
900*219b2ee8SDavid du Colombier  */
901*219b2ee8SDavid du Colombier Ndbtuple*
902*219b2ee8SDavid du Colombier mktuple(char *attr, char *val)
903*219b2ee8SDavid du Colombier {
904*219b2ee8SDavid du Colombier 	Ndbtuple *t;
905*219b2ee8SDavid du Colombier 
906*219b2ee8SDavid du Colombier 	t = malloc(sizeof(Ndbtuple));
907*219b2ee8SDavid du Colombier 	strcpy(t->attr, attr);
908*219b2ee8SDavid du Colombier 	strncpy(t->val, val, sizeof(t->val));
909*219b2ee8SDavid du Colombier 	t->val[sizeof(t->val)-1] = 0;
910*219b2ee8SDavid du Colombier 	t->line = t;
911*219b2ee8SDavid du Colombier 	t->entry = 0;
912*219b2ee8SDavid du Colombier 	return t;
913*219b2ee8SDavid du Colombier }
914*219b2ee8SDavid du Colombier 
915*219b2ee8SDavid du Colombier /*
9163e12c5d1SDavid du Colombier  *  lookup a request.  the network "net" means we should pick the
9173e12c5d1SDavid du Colombier  *  best network to get there.
9183e12c5d1SDavid du Colombier  */
9193e12c5d1SDavid du Colombier int
9203e12c5d1SDavid du Colombier lookup(Mfile *mf, char *net, char *host, char *serv)
9213e12c5d1SDavid du Colombier {
922*219b2ee8SDavid du Colombier 	Network *np, *p;
923*219b2ee8SDavid du Colombier 	char *cp;
924*219b2ee8SDavid du Colombier 	Ndbtuple *nt, *t;
925*219b2ee8SDavid du Colombier 	int i;
926*219b2ee8SDavid du Colombier 	char reply[Maxreply];
9273e12c5d1SDavid du Colombier 
9283e12c5d1SDavid du Colombier 	/* start transaction with a clean slate */
929*219b2ee8SDavid du Colombier 	for(i = 0; i < Nreply; i++){
930*219b2ee8SDavid du Colombier 		if(mf->reply[i])
931*219b2ee8SDavid du Colombier 			free(mf->reply[i]);
932*219b2ee8SDavid du Colombier 		mf->reply[i] = 0;
933*219b2ee8SDavid du Colombier 		mf->replylen[i] = 0;
9343e12c5d1SDavid du Colombier 	}
935*219b2ee8SDavid du Colombier 	mf->nreply = 0;
9363e12c5d1SDavid du Colombier 
9373e12c5d1SDavid du Colombier 	/* open up the standard db files */
9383e12c5d1SDavid du Colombier 	if(db == 0)
939bd389b36SDavid du Colombier 		db = ndbopen(dbfile);
9403e12c5d1SDavid du Colombier 	if(db == 0)
9413e12c5d1SDavid du Colombier 		error("can't open network database\n");
9423e12c5d1SDavid du Colombier 
943*219b2ee8SDavid du Colombier 	nt = 0;
9443e12c5d1SDavid du Colombier 	if(strcmp(net, "net") == 0){
9453e12c5d1SDavid du Colombier 		/*
9463e12c5d1SDavid du Colombier 		 *  go through set of default nets
9473e12c5d1SDavid du Colombier 		 */
9483e12c5d1SDavid du Colombier 		for(np = netlist; np; np = np->next){
949*219b2ee8SDavid du Colombier 			nt = (*np->lookup)(np, host, serv, 0);
950*219b2ee8SDavid du Colombier 			if(nt){
951*219b2ee8SDavid du Colombier 				if(needproto(np, nt) == 0)
952*219b2ee8SDavid du Colombier 					break;
953*219b2ee8SDavid du Colombier 				ndbfree(nt);
954*219b2ee8SDavid du Colombier 				nt = 0;
955bd389b36SDavid du Colombier 			}
9563e12c5d1SDavid du Colombier 		}
9573e12c5d1SDavid du Colombier 
9583e12c5d1SDavid du Colombier 		/*
9593e12c5d1SDavid du Colombier 		 *   try first net that requires no table lookup
9603e12c5d1SDavid du Colombier 		 */
961*219b2ee8SDavid du Colombier 		if(nt == 0)
9623e12c5d1SDavid du Colombier 			for(np = netlist; np; np = np->next){
9633e12c5d1SDavid du Colombier 				if(np->nolookup && *host != '$'){
964*219b2ee8SDavid du Colombier 					nt = (*np->lookup)(np, host, serv, 1);
965*219b2ee8SDavid du Colombier 					if(nt)
9663e12c5d1SDavid du Colombier 						break;
9673e12c5d1SDavid du Colombier 				}
9683e12c5d1SDavid du Colombier 			}
9693e12c5d1SDavid du Colombier 
970*219b2ee8SDavid du Colombier 		if(nt == 0)
9713e12c5d1SDavid du Colombier 			return -1;
972*219b2ee8SDavid du Colombier 
973*219b2ee8SDavid du Colombier 		/*
974*219b2ee8SDavid du Colombier 		 *  create replies
975*219b2ee8SDavid du Colombier 		 */
976*219b2ee8SDavid du Colombier 		for(p = np; p; p = p->next){
977*219b2ee8SDavid du Colombier 			for(t = nt; mf->nreply < Nreply && t; t = t->entry){
978*219b2ee8SDavid du Colombier 				if(needproto(p, nt) < 0)
979*219b2ee8SDavid du Colombier 					continue;
980*219b2ee8SDavid du Colombier 				cp = (*p->trans)(t, p, serv);
981*219b2ee8SDavid du Colombier 				if(cp){
982*219b2ee8SDavid du Colombier 					mf->replylen[mf->nreply] = strlen(cp);
983*219b2ee8SDavid du Colombier 					mf->reply[mf->nreply++] = cp;
984*219b2ee8SDavid du Colombier 				}
985*219b2ee8SDavid du Colombier 			}
986*219b2ee8SDavid du Colombier 		}
987*219b2ee8SDavid du Colombier 		for(p = netlist; mf->nreply < Nreply && p != np; p = p->next){
988*219b2ee8SDavid du Colombier 			for(t = nt; mf->nreply < Nreply && t; t = t->entry){
989*219b2ee8SDavid du Colombier 				if(needproto(p, nt) < 0)
990*219b2ee8SDavid du Colombier 					continue;
991*219b2ee8SDavid du Colombier 				cp = (*p->trans)(t, p, serv);
992*219b2ee8SDavid du Colombier 				if(cp){
993*219b2ee8SDavid du Colombier 					mf->replylen[mf->nreply] = strlen(cp);
994*219b2ee8SDavid du Colombier 					mf->reply[mf->nreply++] = cp;
995*219b2ee8SDavid du Colombier 				}
996*219b2ee8SDavid du Colombier 			}
997*219b2ee8SDavid du Colombier 		}
998*219b2ee8SDavid du Colombier 		ndbfree(nt);
999*219b2ee8SDavid du Colombier 		return 0;
10003e12c5d1SDavid du Colombier 	} else {
10013e12c5d1SDavid du Colombier 		/*
10023e12c5d1SDavid du Colombier 		 *  look on a specific network
10033e12c5d1SDavid du Colombier 		 */
1004*219b2ee8SDavid du Colombier 		for(p = network; p->net; p++){
1005*219b2ee8SDavid du Colombier 			if(strcmp(p->net, net) == 0){
1006*219b2ee8SDavid du Colombier 				nt = (*p->lookup)(p, host, serv, 1);
1007*219b2ee8SDavid du Colombier 				if (nt == 0)
1008*219b2ee8SDavid du Colombier 					return -1;
1009*219b2ee8SDavid du Colombier 
1010*219b2ee8SDavid du Colombier 				/* create replies */
1011*219b2ee8SDavid du Colombier 				for(t = nt; mf->nreply < Nreply && t; t = t->entry){
1012*219b2ee8SDavid du Colombier 					cp = (*p->trans)(t, p, serv);
1013*219b2ee8SDavid du Colombier 					if(cp){
1014*219b2ee8SDavid du Colombier 						mf->replylen[mf->nreply] = strlen(cp);
1015*219b2ee8SDavid du Colombier 						mf->reply[mf->nreply++] = cp;
1016*219b2ee8SDavid du Colombier 					}
1017*219b2ee8SDavid du Colombier 				}
1018*219b2ee8SDavid du Colombier 				ndbfree(nt);
1019*219b2ee8SDavid du Colombier 				return 0;
10203e12c5d1SDavid du Colombier 			}
10213e12c5d1SDavid du Colombier 		}
10223e12c5d1SDavid du Colombier 	}
10233e12c5d1SDavid du Colombier 
10243e12c5d1SDavid du Colombier 	/*
1025*219b2ee8SDavid du Colombier 	 *  not a known network, don't translate host or service
10263e12c5d1SDavid du Colombier 	 */
10273e12c5d1SDavid du Colombier 	if(serv)
1028*219b2ee8SDavid du Colombier 		snprint(reply, sizeof(reply), "/net/%s/clone %s!%s",
1029bd389b36SDavid du Colombier 			net, host, serv);
1030bd389b36SDavid du Colombier 	else
1031*219b2ee8SDavid du Colombier 		snprint(reply, sizeof(reply), "/net/%s/clone %s",
1032bd389b36SDavid du Colombier 			net, host);
1033*219b2ee8SDavid du Colombier 	mf->reply[0] = strdup(reply);
1034*219b2ee8SDavid du Colombier 	mf->replylen[0] = strlen(reply);
1035*219b2ee8SDavid du Colombier 	mf->nreply = 1;
10363e12c5d1SDavid du Colombier 	return 0;
10373e12c5d1SDavid du Colombier }
10383e12c5d1SDavid du Colombier 
10393e12c5d1SDavid du Colombier /*
10403e12c5d1SDavid du Colombier  *  see if we can use this protocol
10413e12c5d1SDavid du Colombier  */
10423e12c5d1SDavid du Colombier int
10433e12c5d1SDavid du Colombier needproto(Network *np, Ndbtuple *t)
10443e12c5d1SDavid du Colombier {
10453e12c5d1SDavid du Colombier 	if(np->needproto == 0)
10463e12c5d1SDavid du Colombier 		return 0;
10473e12c5d1SDavid du Colombier 	for(; t; t = t->entry)
10483e12c5d1SDavid du Colombier 		if(strcmp(t->attr, "proto")==0 && strcmp(t->val, np->net)==0)
10493e12c5d1SDavid du Colombier 			return 0;
10503e12c5d1SDavid du Colombier 	return -1;
10513e12c5d1SDavid du Colombier }
10523e12c5d1SDavid du Colombier 
10533e12c5d1SDavid du Colombier /*
10543e12c5d1SDavid du Colombier  *  translate an ip service name into a port number.  If it's a numeric port
10553e12c5d1SDavid du Colombier  *  number, look for restricted access.
10563e12c5d1SDavid du Colombier  *
10573e12c5d1SDavid du Colombier  *  the service '*' needs no translation.
10583e12c5d1SDavid du Colombier  */
10593e12c5d1SDavid du Colombier char*
10603e12c5d1SDavid du Colombier ipserv(Network *np, char *name, char *buf)
10613e12c5d1SDavid du Colombier {
10623e12c5d1SDavid du Colombier 	char *p;
10633e12c5d1SDavid du Colombier 	int alpha = 0;
10643e12c5d1SDavid du Colombier 	int restr = 0;
10653e12c5d1SDavid du Colombier 	char port[Ndbvlen];
10663e12c5d1SDavid du Colombier 	Ndbtuple *t, *nt;
10673e12c5d1SDavid du Colombier 	Ndbs s;
10683e12c5d1SDavid du Colombier 
10693e12c5d1SDavid du Colombier 	/* '*' means any service */
10703e12c5d1SDavid du Colombier 	if(strcmp(name, "*")==0){
10713e12c5d1SDavid du Colombier 		strcpy(buf, name);
10723e12c5d1SDavid du Colombier 		return buf;
10733e12c5d1SDavid du Colombier 	}
10743e12c5d1SDavid du Colombier 
10753e12c5d1SDavid du Colombier 	/*  see if it's numeric or symbolic */
10763e12c5d1SDavid du Colombier 	port[0] = 0;
10773e12c5d1SDavid du Colombier 	for(p = name; *p; p++){
10783e12c5d1SDavid du Colombier 		if(isdigit(*p))
10793e12c5d1SDavid du Colombier 			;
10803e12c5d1SDavid du Colombier 		else if(isalpha(*p) || *p == '-' || *p == '$')
10813e12c5d1SDavid du Colombier 			alpha = 1;
10823e12c5d1SDavid du Colombier 		else
10833e12c5d1SDavid du Colombier 			return 0;
10843e12c5d1SDavid du Colombier 	}
10853e12c5d1SDavid du Colombier 	if(alpha){
10863e12c5d1SDavid du Colombier 		t = ndbgetval(db, &s, np->net, name, "port", port);
10873e12c5d1SDavid du Colombier 		if(t == 0)
10883e12c5d1SDavid du Colombier 			return 0;
10893e12c5d1SDavid du Colombier 	} else {
10903e12c5d1SDavid du Colombier 		t = ndbgetval(db, &s, "port", name, "port", port);
10913e12c5d1SDavid du Colombier 		if(t == 0){
10923e12c5d1SDavid du Colombier 			strncpy(port, name, sizeof(port));
10933e12c5d1SDavid du Colombier 			port[sizeof(port)-1] = 0;
10943e12c5d1SDavid du Colombier 		}
10953e12c5d1SDavid du Colombier 	}
10963e12c5d1SDavid du Colombier 
10973e12c5d1SDavid du Colombier 	if(t){
10983e12c5d1SDavid du Colombier 		for(nt = t; nt; nt = nt->entry)
10993e12c5d1SDavid du Colombier 			if(strcmp(nt->attr, "restricted") == 0)
11003e12c5d1SDavid du Colombier 				restr = 1;
11013e12c5d1SDavid du Colombier 		ndbfree(t);
11023e12c5d1SDavid du Colombier 	}
11033e12c5d1SDavid du Colombier 	sprint(buf, "%s%s", port, restr ? "!r" : "");
11043e12c5d1SDavid du Colombier 	return buf;
11053e12c5d1SDavid du Colombier }
11063e12c5d1SDavid du Colombier 
11073e12c5d1SDavid du Colombier /*
11083e12c5d1SDavid du Colombier  *  look for the value associated with this attribute for our system.
11093e12c5d1SDavid du Colombier  *  the precedence is highest to lowest:
11103e12c5d1SDavid du Colombier  *	- an attr/value pair in this system's entry
11113e12c5d1SDavid du Colombier  *	- an attr/value pair in this system's subnet entry
11123e12c5d1SDavid du Colombier  *	- an attr/value pair in this system's net entry
11133e12c5d1SDavid du Colombier  */
11143e12c5d1SDavid du Colombier void
11153e12c5d1SDavid du Colombier ipattrlookup(char *attr, char *buf)
11163e12c5d1SDavid du Colombier {
11173e12c5d1SDavid du Colombier 	Ndbtuple *t, *st;
11183e12c5d1SDavid du Colombier 	Ndbs s, ss;
11193e12c5d1SDavid du Colombier 	char ip[Ndbvlen+1];
11203e12c5d1SDavid du Colombier 	uchar net[4];
11213e12c5d1SDavid du Colombier 	uchar mask[4];
11223e12c5d1SDavid du Colombier 
11233e12c5d1SDavid du Colombier 	*buf = 0;
11243e12c5d1SDavid du Colombier 
11253e12c5d1SDavid du Colombier 	/*
11263e12c5d1SDavid du Colombier 	 *  look for an entry for this system
11273e12c5d1SDavid du Colombier 	 */
11283e12c5d1SDavid du Colombier 	ipid();
11293e12c5d1SDavid du Colombier 	if(*ipa == 0)
11303e12c5d1SDavid du Colombier 		return;
11313e12c5d1SDavid du Colombier 	t = ndbsearch(db, &s, "ip", ipaddr);
1132*219b2ee8SDavid du Colombier 	if(t){
11333e12c5d1SDavid du Colombier 		/*
11343e12c5d1SDavid du Colombier 		 *  look for a closely bound attribute
11353e12c5d1SDavid du Colombier 		 */
11363e12c5d1SDavid du Colombier 		lookval(t, s.t, attr, buf);
11373e12c5d1SDavid du Colombier 		ndbfree(t);
11383e12c5d1SDavid du Colombier 		if(*buf)
11393e12c5d1SDavid du Colombier 			return;
1140*219b2ee8SDavid du Colombier 	}
11413e12c5d1SDavid du Colombier 
11423e12c5d1SDavid du Colombier 	/*
11433e12c5d1SDavid du Colombier 	 *  Look up the client's network and find a subnet mask for it.
11443e12c5d1SDavid du Colombier 	 *  Fill in from the subnet (or net) entry anything we can't figure
11453e12c5d1SDavid du Colombier 	 *  out from the client record.
11463e12c5d1SDavid du Colombier 	 */
11473e12c5d1SDavid du Colombier 	maskip(ipa, classmask[CLASS(ipa)], net);
1148bd389b36SDavid du Colombier 	snprint(ip, sizeof(ip), "%I", net);
11493e12c5d1SDavid du Colombier 	t = ndbsearch(db, &s, "ip", ip);
11503e12c5d1SDavid du Colombier 	if(t){
11513e12c5d1SDavid du Colombier 		/* got a net, look for a subnet */
11523e12c5d1SDavid du Colombier 		if(lookval(t, s.t, "ipmask", ip)){
11533e12c5d1SDavid du Colombier 			parseip(mask, ip);
11543e12c5d1SDavid du Colombier 			maskip(ipa, mask, net);
1155bd389b36SDavid du Colombier 			snprint(ip, sizeof(ip), "%I", net);
11563e12c5d1SDavid du Colombier 			st = ndbsearch(db, &ss, "ip", ip);
11573e12c5d1SDavid du Colombier 			if(st){
11583e12c5d1SDavid du Colombier 				lookval(st, ss.t, attr, buf);
11593e12c5d1SDavid du Colombier 				ndbfree(st);
11603e12c5d1SDavid du Colombier 			}
11613e12c5d1SDavid du Colombier 		}
11623e12c5d1SDavid du Colombier 
11633e12c5d1SDavid du Colombier 
11643e12c5d1SDavid du Colombier 		/* fill in what the client and subnet entries didn't have */
11653e12c5d1SDavid du Colombier 		if(*buf == 0)
11663e12c5d1SDavid du Colombier 			lookval(t, s.t, attr, buf);
11673e12c5d1SDavid du Colombier 		ndbfree(t);
11683e12c5d1SDavid du Colombier 	}
11693e12c5d1SDavid du Colombier }
11703e12c5d1SDavid du Colombier 
11713e12c5d1SDavid du Colombier /*
11723e12c5d1SDavid du Colombier  *  lookup (and translate) an ip destination
11733e12c5d1SDavid du Colombier  */
1174*219b2ee8SDavid du Colombier Ndbtuple*
1175*219b2ee8SDavid du Colombier iplookup(Network *np, char *host, char *serv, int nolookup)
11763e12c5d1SDavid du Colombier {
11773e12c5d1SDavid du Colombier 	char *attr;
11783e12c5d1SDavid du Colombier 	Ndbtuple *t;
11793e12c5d1SDavid du Colombier 	Ndbs s;
11803e12c5d1SDavid du Colombier 	char ts[Ndbvlen+1];
11813e12c5d1SDavid du Colombier 	char th[Ndbvlen+1];
11823e12c5d1SDavid du Colombier 	char dollar[Ndbvlen+1];
11833e12c5d1SDavid du Colombier 
1184*219b2ee8SDavid du Colombier 	USED(nolookup);
1185*219b2ee8SDavid du Colombier 
11863e12c5d1SDavid du Colombier 	/*
11873e12c5d1SDavid du Colombier 	 *  start with the service since it's the most likely to fail
11883e12c5d1SDavid du Colombier 	 *  and costs the least
11893e12c5d1SDavid du Colombier 	 */
11903e12c5d1SDavid du Colombier 	if(serv==0 || ipserv(np, serv, ts) == 0)
1191*219b2ee8SDavid du Colombier 		return 0;
11923e12c5d1SDavid du Colombier 
11933e12c5d1SDavid du Colombier 	/* for dial strings with no host */
1194*219b2ee8SDavid du Colombier 	if(strcmp(host, "*") == 0)
1195*219b2ee8SDavid du Colombier 		return mktuple("ip", "*");
11963e12c5d1SDavid du Colombier 
11973e12c5d1SDavid du Colombier 	/*
11983e12c5d1SDavid du Colombier 	 *  '$' means the rest of the name is an attribute that we
11993e12c5d1SDavid du Colombier 	 *  need to search for
12003e12c5d1SDavid du Colombier 	 */
12013e12c5d1SDavid du Colombier 	if(*host == '$'){
12023e12c5d1SDavid du Colombier 		ipattrlookup(host+1, dollar);
12033e12c5d1SDavid du Colombier 		if(*dollar)
12043e12c5d1SDavid du Colombier 			host = dollar;
12053e12c5d1SDavid du Colombier 	}
12063e12c5d1SDavid du Colombier 
12073e12c5d1SDavid du Colombier 	/*
12083e12c5d1SDavid du Colombier 	 *  just accept addresses
12093e12c5d1SDavid du Colombier 	 */
1210*219b2ee8SDavid du Colombier 	attr = ipattr(host);
1211*219b2ee8SDavid du Colombier 	if(strcmp(attr, "ip") == 0)
1212*219b2ee8SDavid du Colombier 		return mktuple("ip", host);
12133e12c5d1SDavid du Colombier 
12143e12c5d1SDavid du Colombier 	/*
12153e12c5d1SDavid du Colombier 	 *  give the domain name server the first opportunity to
1216bd389b36SDavid du Colombier 	 *  resolve domain names.  if that fails try the database.
12173e12c5d1SDavid du Colombier 	 */
12183e12c5d1SDavid du Colombier 	t = 0;
12193e12c5d1SDavid du Colombier 	if(strcmp(attr, "dom") == 0)
12203e12c5d1SDavid du Colombier 		t = dnsiplookup(host, &s, th);
12213e12c5d1SDavid du Colombier 	if(t == 0)
12223e12c5d1SDavid du Colombier 		t = ndbgetval(db, &s, attr, host, "ip", th);
12233e12c5d1SDavid du Colombier 	if(t == 0)
1224*219b2ee8SDavid du Colombier 		return 0;
1225bd389b36SDavid du Colombier 
1226bd389b36SDavid du Colombier 	/*
1227bd389b36SDavid du Colombier 	 *  reorder the tuple to have the matched line first and
1228bd389b36SDavid du Colombier 	 *  save that in the request structure.
1229bd389b36SDavid du Colombier 	 */
1230*219b2ee8SDavid du Colombier 	return reorder(t, s.t);
12313e12c5d1SDavid du Colombier }
12323e12c5d1SDavid du Colombier 
12333e12c5d1SDavid du Colombier /*
12343e12c5d1SDavid du Colombier  *  translate an ip address
12353e12c5d1SDavid du Colombier  */
1236*219b2ee8SDavid du Colombier char*
1237*219b2ee8SDavid du Colombier iptrans(Ndbtuple *t, Network *np, char *serv)
12383e12c5d1SDavid du Colombier {
12393e12c5d1SDavid du Colombier 	char ts[Ndbvlen+1];
1240*219b2ee8SDavid du Colombier 	char reply[Maxreply];
12413e12c5d1SDavid du Colombier 
1242*219b2ee8SDavid du Colombier 	if(strcmp(t->attr, "ip") != 0)
12433e12c5d1SDavid du Colombier 		return 0;
1244*219b2ee8SDavid du Colombier 
1245*219b2ee8SDavid du Colombier 	if(serv == 0 || ipserv(np, serv, ts) == 0)
1246*219b2ee8SDavid du Colombier 		return 0;
1247*219b2ee8SDavid du Colombier 
1248*219b2ee8SDavid du Colombier 	if(*t->val == '*')
1249*219b2ee8SDavid du Colombier 		snprint(reply, sizeof(reply), "/net/%s/clone %s",
1250*219b2ee8SDavid du Colombier 			np->net, ts);
1251*219b2ee8SDavid du Colombier 	else
1252*219b2ee8SDavid du Colombier 		snprint(reply, sizeof(reply), "/net/%s/clone %s!%s",
1253*219b2ee8SDavid du Colombier 			np->net, t->val, ts);
1254*219b2ee8SDavid du Colombier 
1255*219b2ee8SDavid du Colombier 	return strdup(reply);
12563e12c5d1SDavid du Colombier }
12573e12c5d1SDavid du Colombier 
12583e12c5d1SDavid du Colombier /*
12593e12c5d1SDavid du Colombier  *  look for the value associated with this attribute for our system.
12603e12c5d1SDavid du Colombier  *  the precedence is highest to lowest:
12613e12c5d1SDavid du Colombier  *	- an attr/value pair in this system's entry
12623e12c5d1SDavid du Colombier  *	- an attr/value pair in this system's net entry
12633e12c5d1SDavid du Colombier  */
12643e12c5d1SDavid du Colombier void
12653e12c5d1SDavid du Colombier dkattrlookup(char *attr, char *buf)
12663e12c5d1SDavid du Colombier {
12673e12c5d1SDavid du Colombier 	Ndbtuple *t;
12683e12c5d1SDavid du Colombier 	Ndbs s;
12693e12c5d1SDavid du Colombier 
12703e12c5d1SDavid du Colombier 	*buf = 0;
12713e12c5d1SDavid du Colombier 
12723e12c5d1SDavid du Colombier 	dkid();
12733e12c5d1SDavid du Colombier 	if(*dknet == 0)
12743e12c5d1SDavid du Colombier 		return;
12753e12c5d1SDavid du Colombier 	t = ndbsearch(db, &s, "dk", dknet);
12763e12c5d1SDavid du Colombier 	if(t){
12773e12c5d1SDavid du Colombier 		lookval(t, s.t, attr, buf);
12783e12c5d1SDavid du Colombier 		ndbfree(t);
12793e12c5d1SDavid du Colombier 	}
12803e12c5d1SDavid du Colombier }
12813e12c5d1SDavid du Colombier 
12823e12c5d1SDavid du Colombier /*
12833e12c5d1SDavid du Colombier  *  lookup (and translate) a datakit destination
12843e12c5d1SDavid du Colombier  */
1285*219b2ee8SDavid du Colombier Ndbtuple*
1286*219b2ee8SDavid du Colombier dklookup(Network *np, char *host, char *serv, int nolookup)
12873e12c5d1SDavid du Colombier {
12883e12c5d1SDavid du Colombier 	char *p;
1289*219b2ee8SDavid du Colombier 	int slash = 0;
12903e12c5d1SDavid du Colombier 	Ndbtuple *t, *nt;
12913e12c5d1SDavid du Colombier 	Ndbs s;
12923e12c5d1SDavid du Colombier 	char th[Ndbvlen+1];
12933e12c5d1SDavid du Colombier 	char dollar[Ndbvlen+1];
1294*219b2ee8SDavid du Colombier 	char *attr;
12953e12c5d1SDavid du Colombier 
12963e12c5d1SDavid du Colombier 	USED(np);
12973e12c5d1SDavid du Colombier 
12983e12c5d1SDavid du Colombier 	/*
12993e12c5d1SDavid du Colombier 	 *  '$' means the rest of the name is an attribute that we
13003e12c5d1SDavid du Colombier 	 *  need to search for
13013e12c5d1SDavid du Colombier 	 */
13023e12c5d1SDavid du Colombier 	if(*host == '$'){
13033e12c5d1SDavid du Colombier 		dkattrlookup(host+1, dollar);
13043e12c5d1SDavid du Colombier 		if(*dollar)
13053e12c5d1SDavid du Colombier 			host = dollar;
13063e12c5d1SDavid du Colombier 	}
13073e12c5d1SDavid du Colombier 
13083e12c5d1SDavid du Colombier 	for(p = host; *p; p++){
1309*219b2ee8SDavid du Colombier 		if(isalnum(*p) || *p == '-' || *p == '.')
13103e12c5d1SDavid du Colombier 			;
13113e12c5d1SDavid du Colombier 		else if(*p == '/')
13123e12c5d1SDavid du Colombier 			slash = 1;
13133e12c5d1SDavid du Colombier 		else
13143e12c5d1SDavid du Colombier 			return 0;
13153e12c5d1SDavid du Colombier 	}
13163e12c5d1SDavid du Colombier 
1317*219b2ee8SDavid du Colombier 	/* hack for announcements */
1318*219b2ee8SDavid du Colombier 	if(nolookup && serv == 0)
1319*219b2ee8SDavid du Colombier 		return mktuple("dk", host);
1320*219b2ee8SDavid du Colombier 
1321*219b2ee8SDavid du Colombier 	/* let dk addresses be domain names */
1322*219b2ee8SDavid du Colombier 	attr = ipattr(host);
1323*219b2ee8SDavid du Colombier 
13243e12c5d1SDavid du Colombier 	/* don't translate paths, just believe the user */
1325*219b2ee8SDavid du Colombier 	if(slash)
1326*219b2ee8SDavid du Colombier 		return mktuple("dk", host);
1327*219b2ee8SDavid du Colombier 
1328*219b2ee8SDavid du Colombier 	t = ndbgetval(db, &s, attr, host, "dk", th);
1329*219b2ee8SDavid du Colombier 	if(t == 0){
1330*219b2ee8SDavid du Colombier 		if(nolookup)
1331*219b2ee8SDavid du Colombier 			return mktuple("dk", host);
1332*219b2ee8SDavid du Colombier 		return 0;
1333*219b2ee8SDavid du Colombier 	}
13343e12c5d1SDavid du Colombier 
13353e12c5d1SDavid du Colombier 	/* don't allow services in calls to consoles */
13363e12c5d1SDavid du Colombier 	for(nt = t; nt; nt = nt->entry)
13373e12c5d1SDavid du Colombier 		if(strcmp("flavor", nt->attr)==0
13383e12c5d1SDavid du Colombier 		&& strcmp("console", nt->val)==0
13393e12c5d1SDavid du Colombier 		&& serv && *serv){
13403e12c5d1SDavid du Colombier 			ndbfree(t);
13413e12c5d1SDavid du Colombier 			return 0;
13423e12c5d1SDavid du Colombier 		}
13433e12c5d1SDavid du Colombier 
1344*219b2ee8SDavid du Colombier 	return reorder(t, s.t);
13453e12c5d1SDavid du Colombier }
13463e12c5d1SDavid du Colombier 
13473e12c5d1SDavid du Colombier /*
13483e12c5d1SDavid du Colombier  *  translate a datakit address
13493e12c5d1SDavid du Colombier  */
1350*219b2ee8SDavid du Colombier char*
1351*219b2ee8SDavid du Colombier dktrans(Ndbtuple *t, Network *np, char *serv)
13523e12c5d1SDavid du Colombier {
1353*219b2ee8SDavid du Colombier 	char reply[Maxreply];
13543e12c5d1SDavid du Colombier 
1355*219b2ee8SDavid du Colombier 	if(strcmp(t->attr, "dk") != 0)
13563e12c5d1SDavid du Colombier 		return 0;
1357*219b2ee8SDavid du Colombier 
1358*219b2ee8SDavid du Colombier 	if(serv)
1359*219b2ee8SDavid du Colombier 		snprint(reply, sizeof(reply), "/net/%s/clone %s!%s", np->net,
1360*219b2ee8SDavid du Colombier 			t->val, serv);
1361*219b2ee8SDavid du Colombier 	else
1362*219b2ee8SDavid du Colombier 		snprint(reply, sizeof(reply), "/net/%s/clone %s", np->net,
1363*219b2ee8SDavid du Colombier 			t->val);
1364*219b2ee8SDavid du Colombier 	return strdup(reply);
13653e12c5d1SDavid du Colombier }
13663e12c5d1SDavid du Colombier 
1367*219b2ee8SDavid du Colombier /*
1368*219b2ee8SDavid du Colombier  *  lookup a telephone number
1369*219b2ee8SDavid du Colombier  */
1370*219b2ee8SDavid du Colombier Ndbtuple*
1371*219b2ee8SDavid du Colombier telcolookup(Network *np, char *host, char *serv, int nolookup)
1372*219b2ee8SDavid du Colombier {
1373*219b2ee8SDavid du Colombier 	Ndbtuple *t;
1374*219b2ee8SDavid du Colombier 	Ndbs s;
1375*219b2ee8SDavid du Colombier 	char th[Ndbvlen+1];
1376*219b2ee8SDavid du Colombier 
1377*219b2ee8SDavid du Colombier 	USED(np, nolookup, serv);
1378*219b2ee8SDavid du Colombier 
1379*219b2ee8SDavid du Colombier 	t = ndbgetval(db, &s, "sys", host, "telco", th);
1380*219b2ee8SDavid du Colombier 	if(t == 0)
1381*219b2ee8SDavid du Colombier 		return mktuple("telco", host);
1382*219b2ee8SDavid du Colombier 
1383*219b2ee8SDavid du Colombier 	return reorder(t, s.t);
1384*219b2ee8SDavid du Colombier }
1385*219b2ee8SDavid du Colombier 
1386*219b2ee8SDavid du Colombier /*
1387*219b2ee8SDavid du Colombier  *  translate a telephone address
1388*219b2ee8SDavid du Colombier  */
1389*219b2ee8SDavid du Colombier char*
1390*219b2ee8SDavid du Colombier telcotrans(Ndbtuple *t, Network *np, char *serv)
1391*219b2ee8SDavid du Colombier {
1392*219b2ee8SDavid du Colombier 	char reply[Maxreply];
1393*219b2ee8SDavid du Colombier 
1394*219b2ee8SDavid du Colombier 	if(strcmp(t->attr, "telco") != 0)
1395*219b2ee8SDavid du Colombier 		return 0;
1396*219b2ee8SDavid du Colombier 
1397*219b2ee8SDavid du Colombier 	if(serv)
1398*219b2ee8SDavid du Colombier 		snprint(reply, sizeof(reply), "/net/%s/clone %s!%s", np->net,
1399*219b2ee8SDavid du Colombier 			t->val, serv);
1400*219b2ee8SDavid du Colombier 	else
1401*219b2ee8SDavid du Colombier 		snprint(reply, sizeof(reply), "/net/%s/clone %s", np->net,
1402*219b2ee8SDavid du Colombier 			t->val);
1403*219b2ee8SDavid du Colombier 	return strdup(reply);
1404*219b2ee8SDavid du Colombier }
14053e12c5d1SDavid du Colombier int
14063e12c5d1SDavid du Colombier mygetfields(char *lp, char **fields, int n, char sep)
14073e12c5d1SDavid du Colombier {
14083e12c5d1SDavid du Colombier 	int i;
14093e12c5d1SDavid du Colombier 	char sep2=0;
14103e12c5d1SDavid du Colombier 
14113e12c5d1SDavid du Colombier 	if(sep == ' ')
14123e12c5d1SDavid du Colombier 		sep2 = '\t';
14133e12c5d1SDavid du Colombier 	for(i=0; lp && *lp && i<n; i++){
14143e12c5d1SDavid du Colombier 		if(*lp==sep || *lp==sep2)
14153e12c5d1SDavid du Colombier 			*lp++ = 0;
14163e12c5d1SDavid du Colombier 		if(*lp == 0)
14173e12c5d1SDavid du Colombier 			break;
14183e12c5d1SDavid du Colombier 		fields[i] = lp;
14193e12c5d1SDavid du Colombier 		while(*lp && *lp!=sep && *lp!=sep2)
14203e12c5d1SDavid du Colombier 			lp++;
14213e12c5d1SDavid du Colombier 	}
14223e12c5d1SDavid du Colombier 	return i;
14233e12c5d1SDavid du Colombier }
14243e12c5d1SDavid du Colombier 
14253e12c5d1SDavid du Colombier /*
14263e12c5d1SDavid du Colombier  *  Look for a pair with the given attribute.  look first on the same line,
14273e12c5d1SDavid du Colombier  *  then in the whole entry.
14283e12c5d1SDavid du Colombier  */
14293e12c5d1SDavid du Colombier Ndbtuple*
14303e12c5d1SDavid du Colombier lookval(Ndbtuple *entry, Ndbtuple *line, char *attr, char *to)
14313e12c5d1SDavid du Colombier {
14323e12c5d1SDavid du Colombier 	Ndbtuple *nt;
14333e12c5d1SDavid du Colombier 
14343e12c5d1SDavid du Colombier 	/* first look on same line (closer binding) */
14353e12c5d1SDavid du Colombier 	for(nt = line;;){
14363e12c5d1SDavid du Colombier 		if(strcmp(attr, nt->attr) == 0){
14373e12c5d1SDavid du Colombier 			strncpy(to, nt->val, Ndbvlen);
14383e12c5d1SDavid du Colombier 			return nt;
14393e12c5d1SDavid du Colombier 		}
14403e12c5d1SDavid du Colombier 		nt = nt->line;
14413e12c5d1SDavid du Colombier 		if(nt == line)
14423e12c5d1SDavid du Colombier 			break;
14433e12c5d1SDavid du Colombier 	}
14443e12c5d1SDavid du Colombier 	/* search whole tuple */
14453e12c5d1SDavid du Colombier 	for(nt = entry; nt; nt = nt->entry)
14463e12c5d1SDavid du Colombier 		if(strcmp(attr, nt->attr) == 0){
14473e12c5d1SDavid du Colombier 			strncpy(to, nt->val, Ndbvlen);
14483e12c5d1SDavid du Colombier 			return nt;
14493e12c5d1SDavid du Colombier 		}
14503e12c5d1SDavid du Colombier 	return 0;
14513e12c5d1SDavid du Colombier }
14523e12c5d1SDavid du Colombier 
14533e12c5d1SDavid du Colombier /*
14543e12c5d1SDavid du Colombier  *  reorder the tuple to put x's line first in the entry
14553e12c5d1SDavid du Colombier  */
14563e12c5d1SDavid du Colombier Ndbtuple*
14573e12c5d1SDavid du Colombier reorder(Ndbtuple *t, Ndbtuple *x)
14583e12c5d1SDavid du Colombier {
14593e12c5d1SDavid du Colombier 	Ndbtuple *nt;
14603e12c5d1SDavid du Colombier 	Ndbtuple *line;
14613e12c5d1SDavid du Colombier 
1462*219b2ee8SDavid du Colombier 	/* find start of this entry's line */
1463*219b2ee8SDavid du Colombier 	for(line = x; line->entry == line->line; line = line->line)
14643e12c5d1SDavid du Colombier 		;
1465*219b2ee8SDavid du Colombier 	line = line->line;
1466*219b2ee8SDavid du Colombier 	if(line == t)
1467*219b2ee8SDavid du Colombier 		return t;	/* already the first line */
14683e12c5d1SDavid du Colombier 
1469*219b2ee8SDavid du Colombier 	/* remove this line and everything after it from the entry */
1470*219b2ee8SDavid du Colombier 	for(nt = t; nt->entry != line; nt = nt->entry)
1471*219b2ee8SDavid du Colombier 		;
1472*219b2ee8SDavid du Colombier 	nt->entry = 0;
14733e12c5d1SDavid du Colombier 
1474*219b2ee8SDavid du Colombier 	/* make that the start of the entry */
1475*219b2ee8SDavid du Colombier 	for(nt = line; nt->entry; nt = nt->entry)
1476*219b2ee8SDavid du Colombier 		;
14773e12c5d1SDavid du Colombier 	nt->entry = t;
14783e12c5d1SDavid du Colombier 	return line;
14793e12c5d1SDavid du Colombier }
14803e12c5d1SDavid du Colombier 
14813e12c5d1SDavid du Colombier /*
14823e12c5d1SDavid du Colombier  *  create a slave process to handle a request to avoid one request blocking
14833e12c5d1SDavid du Colombier  *  another
14843e12c5d1SDavid du Colombier  */
14853e12c5d1SDavid du Colombier void
14863e12c5d1SDavid du Colombier slave(void)
14873e12c5d1SDavid du Colombier {
14883e12c5d1SDavid du Colombier 	if(*isslave)
14893e12c5d1SDavid du Colombier 		return;		/* we're already a slave process */
14903e12c5d1SDavid du Colombier 
14913e12c5d1SDavid du Colombier 	switch(rfork(RFPROC|RFNOTEG|RFMEM|RFNOWAIT)){
14923e12c5d1SDavid du Colombier 	case -1:
14933e12c5d1SDavid du Colombier 		break;
14943e12c5d1SDavid du Colombier 	case 0:
1495*219b2ee8SDavid du Colombier 		if(debug)
1496*219b2ee8SDavid du Colombier 			syslog(0, logfile, "slave %d", getpid());
14973e12c5d1SDavid du Colombier 		*isslave = 1;
14983e12c5d1SDavid du Colombier 		break;
14993e12c5d1SDavid du Colombier 	default:
15003e12c5d1SDavid du Colombier 		longjmp(masterjmp, 1);
15013e12c5d1SDavid du Colombier 	}
15023e12c5d1SDavid du Colombier }
15033e12c5d1SDavid du Colombier 
1504*219b2ee8SDavid du Colombier int
1505*219b2ee8SDavid du Colombier dnsmount(void)
1506*219b2ee8SDavid du Colombier {
1507*219b2ee8SDavid du Colombier 	int fd;
1508*219b2ee8SDavid du Colombier 
1509*219b2ee8SDavid du Colombier 	fd = open("#s/dns", ORDWR);
1510*219b2ee8SDavid du Colombier 	if(fd < 0)
1511*219b2ee8SDavid du Colombier 		return -1;
1512*219b2ee8SDavid du Colombier 	if(mount(fd, "/net", MAFTER, "") < 0){
1513*219b2ee8SDavid du Colombier 		close(fd);
1514*219b2ee8SDavid du Colombier 		return -1;
1515*219b2ee8SDavid du Colombier 	}
1516*219b2ee8SDavid du Colombier 	close(fd);
1517*219b2ee8SDavid du Colombier 	return 0;
1518*219b2ee8SDavid du Colombier }
1519*219b2ee8SDavid du Colombier 
15203e12c5d1SDavid du Colombier /*
15213e12c5d1SDavid du Colombier  *  call the dns process and have it try to translate a name
15223e12c5d1SDavid du Colombier  */
15233e12c5d1SDavid du Colombier Ndbtuple*
15243e12c5d1SDavid du Colombier dnsiplookup(char *host, Ndbs *s, char *ht)
15253e12c5d1SDavid du Colombier {
15263e12c5d1SDavid du Colombier 	int fd, n;
15273e12c5d1SDavid du Colombier 	char buf[Ndbvlen + 4];
15283e12c5d1SDavid du Colombier 	Ndbtuple *t, *nt, **le, **ll;
15293e12c5d1SDavid du Colombier 	char *fields[4];
15303e12c5d1SDavid du Colombier 
1531bd389b36SDavid du Colombier 	unlock(&dblock);
1532bd389b36SDavid du Colombier 
15333e12c5d1SDavid du Colombier 	/* save the name before starting a slave */
1534bd389b36SDavid du Colombier 	snprint(buf, sizeof(buf), "%s ip", host);
15353e12c5d1SDavid du Colombier 
15363e12c5d1SDavid du Colombier 	slave();
15373e12c5d1SDavid du Colombier 
15383e12c5d1SDavid du Colombier 	fd = open("/net/dns", ORDWR);
1539*219b2ee8SDavid du Colombier 	if(fd < 0 && dnsmount() == 0)
1540*219b2ee8SDavid du Colombier 		fd = open("/net/dns", ORDWR);
1541bd389b36SDavid du Colombier 	if(fd < 0){
1542bd389b36SDavid du Colombier 		lock(&dblock);
15433e12c5d1SDavid du Colombier 		return 0;
1544bd389b36SDavid du Colombier 	}
15453e12c5d1SDavid du Colombier 
15463e12c5d1SDavid du Colombier 	t = 0;
1547*219b2ee8SDavid du Colombier 	ll = le = 0;
15483e12c5d1SDavid du Colombier 	if(write(fd, buf, strlen(buf)) >= 0){
15493e12c5d1SDavid du Colombier 		seek(fd, 0, 0);
15503e12c5d1SDavid du Colombier 		ll = &t;
15513e12c5d1SDavid du Colombier 		le = &t;
15523e12c5d1SDavid du Colombier 		while((n = read(fd, buf, sizeof(buf)-1)) > 0){
15533e12c5d1SDavid du Colombier 			buf[n] = 0;
15543e12c5d1SDavid du Colombier 			n = mygetfields(buf, fields, 4, ' ');
15553e12c5d1SDavid du Colombier 			if(n < 3)
15563e12c5d1SDavid du Colombier 				continue;
15573e12c5d1SDavid du Colombier 			nt = malloc(sizeof(Ndbtuple));
15583e12c5d1SDavid du Colombier 			strcpy(nt->attr, "ip");
15593e12c5d1SDavid du Colombier 			strncpy(nt->val, fields[2], Ndbvlen-1);
15603e12c5d1SDavid du Colombier 			*ll = nt;
15613e12c5d1SDavid du Colombier 			*le = nt;
15623e12c5d1SDavid du Colombier 			ll = &nt->line;
15633e12c5d1SDavid du Colombier 			le = &nt->entry;
15643e12c5d1SDavid du Colombier 			nt->line = t;
15653e12c5d1SDavid du Colombier 		}
15663e12c5d1SDavid du Colombier 	}
1567*219b2ee8SDavid du Colombier 	if(t){
15683e12c5d1SDavid du Colombier 		strcpy(ht, t->val);
1569*219b2ee8SDavid du Colombier 
1570*219b2ee8SDavid du Colombier 		/* add in domain name */
1571*219b2ee8SDavid du Colombier 		nt = malloc(sizeof(Ndbtuple));
1572*219b2ee8SDavid du Colombier 		strcpy(nt->attr, "dom");
1573*219b2ee8SDavid du Colombier 		strcpy(nt->val, host);
1574*219b2ee8SDavid du Colombier 		*ll = nt;
1575*219b2ee8SDavid du Colombier 		*le = nt;
1576*219b2ee8SDavid du Colombier 		nt->line = t;
1577*219b2ee8SDavid du Colombier 	}
15783e12c5d1SDavid du Colombier 	close(fd);
15793e12c5d1SDavid du Colombier 	s->t = t;
1580bd389b36SDavid du Colombier 	lock(&dblock);
15813e12c5d1SDavid du Colombier 	return t;
15823e12c5d1SDavid du Colombier }
1583*219b2ee8SDavid du Colombier 
1584*219b2ee8SDavid du Colombier int
1585*219b2ee8SDavid du Colombier qmatch(Ndbtuple *t, char **attr, char **val, int n)
1586*219b2ee8SDavid du Colombier {
1587*219b2ee8SDavid du Colombier 	int i, found;
1588*219b2ee8SDavid du Colombier 	Ndbtuple *nt;
1589*219b2ee8SDavid du Colombier 
1590*219b2ee8SDavid du Colombier 	for(i = 1; i < n; i++){
1591*219b2ee8SDavid du Colombier 		found = 0;
1592*219b2ee8SDavid du Colombier 		for(nt = t; nt; nt = nt->entry)
1593*219b2ee8SDavid du Colombier 			if(strcmp(attr[i], nt->attr) == 0)
1594*219b2ee8SDavid du Colombier 				if(strcmp(val[i], "*") == 0
1595*219b2ee8SDavid du Colombier 				|| strcmp(val[i], nt->val) == 0){
1596*219b2ee8SDavid du Colombier 					found = 1;
1597*219b2ee8SDavid du Colombier 					break;
1598*219b2ee8SDavid du Colombier 				}
1599*219b2ee8SDavid du Colombier 		if(found == 0)
1600*219b2ee8SDavid du Colombier 			break;
1601*219b2ee8SDavid du Colombier 	}
1602*219b2ee8SDavid du Colombier 	return i == n;
1603*219b2ee8SDavid du Colombier }
1604*219b2ee8SDavid du Colombier 
1605*219b2ee8SDavid du Colombier void
1606*219b2ee8SDavid du Colombier qreply(Mfile *mf, Ndbtuple *t)
1607*219b2ee8SDavid du Colombier {
1608*219b2ee8SDavid du Colombier 	int i;
1609*219b2ee8SDavid du Colombier 	Ndbtuple *nt;
1610*219b2ee8SDavid du Colombier 	char buf[512];
1611*219b2ee8SDavid du Colombier 
1612*219b2ee8SDavid du Colombier 	buf[0] = 0;
1613*219b2ee8SDavid du Colombier 	for(nt = t; mf->nreply < Nreply && nt; nt = nt->entry){
1614*219b2ee8SDavid du Colombier 		strcat(buf, nt->attr);
1615*219b2ee8SDavid du Colombier 		strcat(buf, "=");
1616*219b2ee8SDavid du Colombier 		strcat(buf, nt->val);
1617*219b2ee8SDavid du Colombier 		i = strlen(buf);
1618*219b2ee8SDavid du Colombier 		if(nt->line != nt->entry || sizeof(buf) - i < 2*Ndbvlen+2){
1619*219b2ee8SDavid du Colombier 			mf->replylen[mf->nreply] = strlen(buf);
1620*219b2ee8SDavid du Colombier 			mf->reply[mf->nreply++] = strdup(buf);
1621*219b2ee8SDavid du Colombier 			buf[0] = 0;
1622*219b2ee8SDavid du Colombier 		} else
1623*219b2ee8SDavid du Colombier 			strcat(buf, " ");
1624*219b2ee8SDavid du Colombier 	}
1625*219b2ee8SDavid du Colombier }
1626*219b2ee8SDavid du Colombier 
1627*219b2ee8SDavid du Colombier /*
1628*219b2ee8SDavid du Colombier  *  generic query lookup.
1629*219b2ee8SDavid du Colombier  */
1630*219b2ee8SDavid du Colombier char*
1631*219b2ee8SDavid du Colombier genquery(Mfile *mf, char *query)
1632*219b2ee8SDavid du Colombier {
1633*219b2ee8SDavid du Colombier 	int i, n;
1634*219b2ee8SDavid du Colombier 	char *p;
1635*219b2ee8SDavid du Colombier 	char *attr[32];
1636*219b2ee8SDavid du Colombier 	char *val[32];
1637*219b2ee8SDavid du Colombier 	char ip[Ndbvlen];
1638*219b2ee8SDavid du Colombier 	Ndbtuple *t;
1639*219b2ee8SDavid du Colombier 	Ndbs s;
1640*219b2ee8SDavid du Colombier 
1641*219b2ee8SDavid du Colombier 	n = mygetfields(query, attr, 32, ' ');
1642*219b2ee8SDavid du Colombier 	if(n == 0)
1643*219b2ee8SDavid du Colombier 		return "bad query";
1644*219b2ee8SDavid du Colombier 
1645*219b2ee8SDavid du Colombier 	/* parse pairs */
1646*219b2ee8SDavid du Colombier 	for(i = 0; i < n; i++){
1647*219b2ee8SDavid du Colombier 		p = strchr(attr[i], '=');
1648*219b2ee8SDavid du Colombier 		if(p == 0)
1649*219b2ee8SDavid du Colombier 			return "bad query";
1650*219b2ee8SDavid du Colombier 		*p++ = 0;
1651*219b2ee8SDavid du Colombier 		val[i] = p;
1652*219b2ee8SDavid du Colombier 	}
1653*219b2ee8SDavid du Colombier 
1654*219b2ee8SDavid du Colombier 	/* give dns a chance */
1655*219b2ee8SDavid du Colombier 	if((strcmp(attr[0], "dom") == 0 || strcmp(attr[0], "ip") == 0) && val[0]){
1656*219b2ee8SDavid du Colombier 		t = dnsiplookup(val[0], &s, ip);
1657*219b2ee8SDavid du Colombier 		if(t){
1658*219b2ee8SDavid du Colombier 			if(qmatch(t, attr, val, n)){
1659*219b2ee8SDavid du Colombier 				qreply(mf, t);
1660*219b2ee8SDavid du Colombier 				ndbfree(t);
1661*219b2ee8SDavid du Colombier 				return 0;
1662*219b2ee8SDavid du Colombier 			}
1663*219b2ee8SDavid du Colombier 			ndbfree(t);
1664*219b2ee8SDavid du Colombier 		}
1665*219b2ee8SDavid du Colombier 	}
1666*219b2ee8SDavid du Colombier 
1667*219b2ee8SDavid du Colombier 	/* first pair is always the key.  It can't be a '*' */
1668*219b2ee8SDavid du Colombier 	t = ndbsearch(db, &s, attr[0], val[0]);
1669*219b2ee8SDavid du Colombier 
1670*219b2ee8SDavid du Colombier 	/* search is the and of all the pairs */
1671*219b2ee8SDavid du Colombier 	while(t){
1672*219b2ee8SDavid du Colombier 		if(qmatch(t, attr, val, n)){
1673*219b2ee8SDavid du Colombier 			qreply(mf, t);
1674*219b2ee8SDavid du Colombier 			ndbfree(t);
1675*219b2ee8SDavid du Colombier 			return 0;
1676*219b2ee8SDavid du Colombier 		}
1677*219b2ee8SDavid du Colombier 
1678*219b2ee8SDavid du Colombier 		ndbfree(t);
1679*219b2ee8SDavid du Colombier 		t = ndbsnext(&s, attr[0], val[0]);
1680*219b2ee8SDavid du Colombier 	}
1681*219b2ee8SDavid du Colombier 
1682*219b2ee8SDavid du Colombier 	return "no match";
1683*219b2ee8SDavid du Colombier }
1684