xref: /plan9/sys/src/cmd/9nfs/nfsmount.c (revision 883a8c51bed350ea85a0220461d31e311550db04)
19a747e4fSDavid du Colombier #include "all.h"
29a747e4fSDavid du Colombier 
39a747e4fSDavid du Colombier /*
49a747e4fSDavid du Colombier  *	Cf. /lib/rfc/rfc1094
59a747e4fSDavid du Colombier  */
69a747e4fSDavid du Colombier 
79a747e4fSDavid du Colombier static int	mntnull(int, Rpccall*, Rpccall*);
89a747e4fSDavid du Colombier static int	mntmnt(int, Rpccall*, Rpccall*);
99a747e4fSDavid du Colombier static int	mntdump(int, Rpccall*, Rpccall*);
109a747e4fSDavid du Colombier static int	mntumnt(int, Rpccall*, Rpccall*);
119a747e4fSDavid du Colombier static int	mntumntall(int, Rpccall*, Rpccall*);
129a747e4fSDavid du Colombier static int	mntexport(int, Rpccall*, Rpccall*);
139a747e4fSDavid du Colombier 
149a747e4fSDavid du Colombier Procmap mntproc[] = {
159a747e4fSDavid du Colombier 	0, mntnull,
169a747e4fSDavid du Colombier 	1, mntmnt,
179a747e4fSDavid du Colombier 	2, mntdump,
189a747e4fSDavid du Colombier 	3, mntumnt,
199a747e4fSDavid du Colombier 	4, mntumntall,
209a747e4fSDavid du Colombier 	5, mntexport,
219a747e4fSDavid du Colombier 	0, 0
229a747e4fSDavid du Colombier };
239a747e4fSDavid du Colombier 
249a747e4fSDavid du Colombier long		starttime;
259a747e4fSDavid du Colombier static int	noauth;
269a747e4fSDavid du Colombier char *		config;
279a747e4fSDavid du Colombier Session *	head;
289a747e4fSDavid du Colombier Session *	tail;
299a747e4fSDavid du Colombier int staletime = 10*60;
309a747e4fSDavid du Colombier 
319a747e4fSDavid du Colombier void
mnttimer(long now)329a747e4fSDavid du Colombier mnttimer(long now)
339a747e4fSDavid du Colombier {
349a747e4fSDavid du Colombier 	Session *s;
359a747e4fSDavid du Colombier 
369a747e4fSDavid du Colombier 	for(s=head; s; s=s->next)
379a747e4fSDavid du Colombier 		fidtimer(s, now);
389a747e4fSDavid du Colombier }
399a747e4fSDavid du Colombier 
408c41de82SDavid du Colombier static void
usage(void)418c41de82SDavid du Colombier usage(void)
428c41de82SDavid du Colombier {
438c41de82SDavid du Colombier 	sysfatal("usage: %s %s [-ns] [-a dialstring] [-c uidmap] [-f srvfile] "
448c41de82SDavid du Colombier 		"[-T staletime]", argv0, commonopts);
458c41de82SDavid du Colombier }
468c41de82SDavid du Colombier 
479a747e4fSDavid du Colombier void
mntinit(int argc,char ** argv)489a747e4fSDavid du Colombier mntinit(int argc, char **argv)
499a747e4fSDavid du Colombier {
509a747e4fSDavid du Colombier 	int tries;
519a747e4fSDavid du Colombier 
529a747e4fSDavid du Colombier 	config = "config";
539a747e4fSDavid du Colombier 	starttime = time(0);
549a747e4fSDavid du Colombier 	clog("nfs mount server init, starttime = %lud\n", starttime);
559a747e4fSDavid du Colombier 	tries = 0;
569a747e4fSDavid du Colombier 	ARGBEGIN{
579a747e4fSDavid du Colombier 	case 'a':
589a747e4fSDavid du Colombier 		++tries;
598c41de82SDavid du Colombier 		srvinit(-1, 0, EARGF(usage()));
608c41de82SDavid du Colombier 		break;
618c41de82SDavid du Colombier 	case 'c':
628c41de82SDavid du Colombier 		config = EARGF(usage());
639a747e4fSDavid du Colombier 		break;
649a747e4fSDavid du Colombier 	case 'f':
659a747e4fSDavid du Colombier 		++tries;
668c41de82SDavid du Colombier 		srvinit(-1, EARGF(usage()), 0);
678c41de82SDavid du Colombier 		break;
688c41de82SDavid du Colombier 	case 'n':
698c41de82SDavid du Colombier 		++noauth;
709a747e4fSDavid du Colombier 		break;
719a747e4fSDavid du Colombier 	case 's':
729a747e4fSDavid du Colombier 		++tries;
739a747e4fSDavid du Colombier 		srvinit(1, 0, 0);
749a747e4fSDavid du Colombier 		break;
759a747e4fSDavid du Colombier 	case 'T':
768c41de82SDavid du Colombier 		staletime = atoi(EARGF(usage()));
779a747e4fSDavid du Colombier 		break;
78363b328dSDavid du Colombier 	default:
79363b328dSDavid du Colombier 		if(argopt(ARGC()) < 0)
808c41de82SDavid du Colombier 			sysfatal("usage: %s %s [-ns] [-a dialstring] "
818c41de82SDavid du Colombier 				"[-c uidmap] [-f srvfile] [-T staletime]",
82363b328dSDavid du Colombier 				argv0, commonopts);
83363b328dSDavid du Colombier 		break;
849a747e4fSDavid du Colombier 	}ARGEND
859a747e4fSDavid du Colombier noauth=1;	/* ZZZ */
869a747e4fSDavid du Colombier 	if(tries == 0 && head == 0)
878c41de82SDavid du Colombier 		srvinit(-1, 0, "tcp!fs");
889a747e4fSDavid du Colombier 	if(head == 0)
899a747e4fSDavid du Colombier 		panic("can't initialize services");
909a747e4fSDavid du Colombier 	readunixidmaps(config);
919a747e4fSDavid du Colombier }
929a747e4fSDavid du Colombier 
939a747e4fSDavid du Colombier void
srvinit(int fd,char * file,char * addr)949a747e4fSDavid du Colombier srvinit(int fd, char *file, char *addr)
959a747e4fSDavid du Colombier {
969a747e4fSDavid du Colombier 	char fdservice[16], *naddr;
979a747e4fSDavid du Colombier 	Session *s;
989a747e4fSDavid du Colombier 	Xfile *xp;
999a747e4fSDavid du Colombier 	Xfid *xf;
1009a747e4fSDavid du Colombier 	Fid *f;
1019a747e4fSDavid du Colombier 
1029a747e4fSDavid du Colombier 	s = calloc(1, sizeof(Session));
1039a747e4fSDavid du Colombier 	s->spec = "";
1049a747e4fSDavid du Colombier 	s->fd = -1;
1059a747e4fSDavid du Colombier 	if(fd >= 0){
1069a747e4fSDavid du Colombier 		s->fd = fd;
1079a747e4fSDavid du Colombier 		sprint(fdservice, "/fd/%d", s->fd);
1089a747e4fSDavid du Colombier 		s->service = strstore(fdservice);
1099a747e4fSDavid du Colombier 		chat("fd = %d\n", s->fd);
1109a747e4fSDavid du Colombier 	}else if(file){
1119a747e4fSDavid du Colombier 		chat("file = \"%s\"\n", file);
1129a747e4fSDavid du Colombier 		s->service = file;
1139a747e4fSDavid du Colombier 		s->fd = open(file, ORDWR);
1149a747e4fSDavid du Colombier 		if(s->fd < 0){
1159a747e4fSDavid du Colombier 			clog("can't open %s: %r\n", file);
1169a747e4fSDavid du Colombier 			goto error;
1179a747e4fSDavid du Colombier 		}
1189a747e4fSDavid du Colombier 	}else if(addr){
1199a747e4fSDavid du Colombier 		chat("addr = \"%s\"\n", addr);
1209a747e4fSDavid du Colombier 		naddr = netmkaddr(addr, 0, "9fs");
1219a747e4fSDavid du Colombier 		s->service = addr;
1229a747e4fSDavid du Colombier 		s->fd = dial(naddr, 0, 0, 0);
1239a747e4fSDavid du Colombier 		if(s->fd < 0){
1249a747e4fSDavid du Colombier 			clog("can't dial %s: %r\n", naddr);
1259a747e4fSDavid du Colombier 			goto error;
1269a747e4fSDavid du Colombier 		}
1279a747e4fSDavid du Colombier 	}
1289a747e4fSDavid du Colombier 
1299a747e4fSDavid du Colombier 	chat("version...");
1309a747e4fSDavid du Colombier 	s->tag = NOTAG-1;
1319a747e4fSDavid du Colombier 	s->f.msize = Maxfdata+IOHDRSZ;
1329a747e4fSDavid du Colombier 	s->f.version = "9P2000";
1339a747e4fSDavid du Colombier 	xmesg(s, Tversion);
1349a747e4fSDavid du Colombier 	messagesize = IOHDRSZ+s->f.msize;
1359a747e4fSDavid du Colombier 	chat("version spec %s size %d\n", s->f.version, s->f.msize);
1369a747e4fSDavid du Colombier 
137b985bfb9SDavid du Colombier 	s->tag = 0;
138b985bfb9SDavid du Colombier 
139b985bfb9SDavid du Colombier 	chat("authenticate...");
140b985bfb9SDavid du Colombier 	if(authhostowner(s) < 0){
141b985bfb9SDavid du Colombier 		clog("auth failed %r\n");
1429a747e4fSDavid du Colombier 		goto error;
1439a747e4fSDavid du Colombier 	}
1449a747e4fSDavid du Colombier 
145b985bfb9SDavid du Colombier 	chat("attach as none...");
1469a747e4fSDavid du Colombier 	f = newfid(s);
1479a747e4fSDavid du Colombier 	s->f.fid = f - s->fids;
1489a747e4fSDavid du Colombier 	s->f.afid = ~0x0UL;
1499a747e4fSDavid du Colombier 	s->f.uname = "none";
1509a747e4fSDavid du Colombier 	s->f.aname = s->spec;
1519a747e4fSDavid du Colombier 	if(xmesg(s, Tattach)){
1529a747e4fSDavid du Colombier 		clog("attach failed\n");
1539a747e4fSDavid du Colombier 		goto error;
1549a747e4fSDavid du Colombier 	}
1559a747e4fSDavid du Colombier 
1569a747e4fSDavid du Colombier 	xp = xfile(&s->f.qid, s, 1);
1579a747e4fSDavid du Colombier 	s->root = xp;
1589a747e4fSDavid du Colombier 	xp->parent = xp;
1599a747e4fSDavid du Colombier 	xp->name = "/";
1609a747e4fSDavid du Colombier 	xf = xfid("none", xp, 1);
1619a747e4fSDavid du Colombier 	xf->urfid = f;
1629a747e4fSDavid du Colombier 	clog("service=%s uid=%s fid=%ld\n",
1639a747e4fSDavid du Colombier 		s->service, xf->uid, xf->urfid - s->fids);
1649a747e4fSDavid du Colombier 	if(tail)
1659a747e4fSDavid du Colombier 		tail->next = s;
1669a747e4fSDavid du Colombier 	else
1679a747e4fSDavid du Colombier 		head = s;
1689a747e4fSDavid du Colombier 	tail = s;
1699a747e4fSDavid du Colombier 	return;
1709a747e4fSDavid du Colombier 
1719a747e4fSDavid du Colombier error:
1729a747e4fSDavid du Colombier 	if(s->fd >= 0)
1739a747e4fSDavid du Colombier 		close(s->fd);
1749a747e4fSDavid du Colombier 	free(s);
1759a747e4fSDavid du Colombier }
1769a747e4fSDavid du Colombier 
1779a747e4fSDavid du Colombier static int
mntnull(int n,Rpccall * cmd,Rpccall * reply)1789a747e4fSDavid du Colombier mntnull(int n, Rpccall *cmd, Rpccall *reply)
1799a747e4fSDavid du Colombier {
1809a747e4fSDavid du Colombier 	USED(n, cmd, reply);
1819a747e4fSDavid du Colombier 	chat("mntnull\n");
1829a747e4fSDavid du Colombier 	return 0;
1839a747e4fSDavid du Colombier }
1849a747e4fSDavid du Colombier 
1859a747e4fSDavid du Colombier static char*
Str2str(String s,char * buf,int nbuf)1869a747e4fSDavid du Colombier Str2str(String s, char *buf, int nbuf)
1879a747e4fSDavid du Colombier {
1889a747e4fSDavid du Colombier 	int i;
1899a747e4fSDavid du Colombier 	i = s.n;
1909a747e4fSDavid du Colombier 	if(i >= nbuf)
1919a747e4fSDavid du Colombier 		i = nbuf-1;
1929a747e4fSDavid du Colombier 	memmove(buf, s.s, i);
1939a747e4fSDavid du Colombier 	buf[i] = 0;
1949a747e4fSDavid du Colombier 	return buf;
1959a747e4fSDavid du Colombier }
1969a747e4fSDavid du Colombier 
1979a747e4fSDavid du Colombier static int
mntmnt(int n,Rpccall * cmd,Rpccall * reply)1989a747e4fSDavid du Colombier mntmnt(int n, Rpccall *cmd, Rpccall *reply)
1999a747e4fSDavid du Colombier {
2009a747e4fSDavid du Colombier 	int i;
2019a747e4fSDavid du Colombier 	char dom[64];
2029a747e4fSDavid du Colombier 	uchar *argptr = cmd->args;
2039a747e4fSDavid du Colombier 	uchar *dataptr = reply->results;
2049a747e4fSDavid du Colombier 	Authunix au;
2059a747e4fSDavid du Colombier 	Xfile *xp;
2069a747e4fSDavid du Colombier 	String root;
2079a747e4fSDavid du Colombier 
2089a747e4fSDavid du Colombier 	chat("mntmnt...\n");
2099a747e4fSDavid du Colombier 	if(n < 8)
2109a747e4fSDavid du Colombier 		return garbage(reply, "n too small");
2119a747e4fSDavid du Colombier 	argptr += string2S(argptr, &root);
2129a747e4fSDavid du Colombier 	if(argptr != &((uchar *)cmd->args)[n])
2139a747e4fSDavid du Colombier 		return garbage(reply, "bad count");
2149a747e4fSDavid du Colombier 	clog("host=%I, port=%ld, root=\"%.*s\"...",
2159a747e4fSDavid du Colombier 		cmd->host, cmd->port, utfnlen(root.s, root.n), root.s);
2169a747e4fSDavid du Colombier 	if(auth2unix(&cmd->cred, &au) != 0){
2179a747e4fSDavid du Colombier 		chat("auth flavor=%ld, count=%ld\n",
2189a747e4fSDavid du Colombier 			cmd->cred.flavor, cmd->cred.count);
2199a747e4fSDavid du Colombier 		for(i=0; i<cmd->cred.count; i++)
2209a747e4fSDavid du Colombier 			chat(" %.2ux", ((uchar *)cmd->cred.data)[i]);
2219a747e4fSDavid du Colombier 		chat("\n");
2229a747e4fSDavid du Colombier 		clog("auth: bad credentials");
2239a747e4fSDavid du Colombier 		return error(reply, 1);
2249a747e4fSDavid du Colombier 	}
2259a747e4fSDavid du Colombier 	clog("auth: %ld %.*s u=%ld g=%ld",
2269a747e4fSDavid du Colombier 		au.stamp, utfnlen(au.mach.s, au.mach.n), au.mach.s, au.uid, au.gid);
2279a747e4fSDavid du Colombier 	for(i=0; i<au.gidlen; i++)
2289a747e4fSDavid du Colombier 		chat(", %ld", au.gids[i]);
2299a747e4fSDavid du Colombier 	chat("...");
2309a747e4fSDavid du Colombier 	if(getdom(cmd->host, dom, sizeof(dom))<0){
2319a747e4fSDavid du Colombier 		clog("auth: unknown ip address");
2329a747e4fSDavid du Colombier 		return error(reply, 1);
2339a747e4fSDavid du Colombier 	}
2349a747e4fSDavid du Colombier 	chat("dom=%s...", dom);
2359a747e4fSDavid du Colombier 	xp = xfroot(root.s, root.n);
2369a747e4fSDavid du Colombier 	if(xp == 0){
2379a747e4fSDavid du Colombier 		chat("xp=0...");
2389a747e4fSDavid du Colombier 		clog("mntmnt: no fs");
2399a747e4fSDavid du Colombier 		return error(reply, 3);
2409a747e4fSDavid du Colombier 	}
2419a747e4fSDavid du Colombier 
2429a747e4fSDavid du Colombier 	PLONG(0);
2439a747e4fSDavid du Colombier 	dataptr += xp2fhandle(xp, dataptr);
2449a747e4fSDavid du Colombier 	chat("OK\n");
2459a747e4fSDavid du Colombier 	return dataptr - (uchar *)reply->results;
2469a747e4fSDavid du Colombier }
2479a747e4fSDavid du Colombier 
2489a747e4fSDavid du Colombier static int
mntdump(int n,Rpccall * cmd,Rpccall * reply)2499a747e4fSDavid du Colombier mntdump(int n, Rpccall *cmd, Rpccall *reply)
2509a747e4fSDavid du Colombier {
2519a747e4fSDavid du Colombier 	if(n != 0)
2529a747e4fSDavid du Colombier 		return garbage(reply, "mntdump");
2539a747e4fSDavid du Colombier 	USED(cmd);
2549a747e4fSDavid du Colombier 	chat("mntdump...");
2559a747e4fSDavid du Colombier 	return error(reply, FALSE);
2569a747e4fSDavid du Colombier }
2579a747e4fSDavid du Colombier 
2589a747e4fSDavid du Colombier static int
mntumnt(int n,Rpccall * cmd,Rpccall * reply)2599a747e4fSDavid du Colombier mntumnt(int n, Rpccall *cmd, Rpccall *reply)
2609a747e4fSDavid du Colombier {
2619a747e4fSDavid du Colombier 	if(n <= 0)
2629a747e4fSDavid du Colombier 		return garbage(reply, "mntumnt");
2639a747e4fSDavid du Colombier 	USED(cmd);
2649a747e4fSDavid du Colombier 	chat("mntumnt\n");
2659a747e4fSDavid du Colombier 	return 0;
2669a747e4fSDavid du Colombier }
2679a747e4fSDavid du Colombier 
2689a747e4fSDavid du Colombier static int
mntumntall(int n,Rpccall * cmd,Rpccall * reply)2699a747e4fSDavid du Colombier mntumntall(int n, Rpccall *cmd, Rpccall *reply)
2709a747e4fSDavid du Colombier {
2719a747e4fSDavid du Colombier 	if(n != 0)
2729a747e4fSDavid du Colombier 		return garbage(reply, "mntumntall");
2739a747e4fSDavid du Colombier 	USED(cmd);
2749a747e4fSDavid du Colombier 	chat("mntumntall\n");
2759a747e4fSDavid du Colombier 	return 0;
2769a747e4fSDavid du Colombier }
2779a747e4fSDavid du Colombier 
2789a747e4fSDavid du Colombier static int
mntexport(int n,Rpccall * cmd,Rpccall * reply)2799a747e4fSDavid du Colombier mntexport(int n, Rpccall *cmd, Rpccall *reply)
2809a747e4fSDavid du Colombier {
2819a747e4fSDavid du Colombier 	uchar *dataptr = reply->results;
2829a747e4fSDavid du Colombier 	Authunix au;
2839a747e4fSDavid du Colombier 	int i;
2849a747e4fSDavid du Colombier 
2859a747e4fSDavid du Colombier 	chat("mntexport...");
2869a747e4fSDavid du Colombier 	if(n != 0)
2879a747e4fSDavid du Colombier 		return garbage(reply, "mntexport");
2889a747e4fSDavid du Colombier 	if(auth2unix(&cmd->cred, &au) != 0){
2899a747e4fSDavid du Colombier 		chat("auth flavor=%ld, count=%ld\n",
2909a747e4fSDavid du Colombier 			cmd->cred.flavor, cmd->cred.count);
2919a747e4fSDavid du Colombier 		for(i=0; i<cmd->cred.count; i++)
2929a747e4fSDavid du Colombier 			chat(" %.2ux", ((uchar *)cmd->cred.data)[i]);
2939a747e4fSDavid du Colombier 		chat("...");
2949a747e4fSDavid du Colombier 		au.mach.n = 0;
2959a747e4fSDavid du Colombier 	}else
2969a747e4fSDavid du Colombier 		chat("%ld@%.*s...", au.uid, utfnlen(au.mach.s, au.mach.n), au.mach.s);
2979a747e4fSDavid du Colombier 	PLONG(TRUE);
2989a747e4fSDavid du Colombier 	PLONG(1);
2999a747e4fSDavid du Colombier 	PPTR("/", 1);
3009a747e4fSDavid du Colombier 	if(au.mach.n > 0){
3019a747e4fSDavid du Colombier 		PLONG(TRUE);
3029a747e4fSDavid du Colombier 		PLONG(au.mach.n);
3039a747e4fSDavid du Colombier 		PPTR(au.mach.s, au.mach.n);
3049a747e4fSDavid du Colombier 	}
3059a747e4fSDavid du Colombier 	PLONG(FALSE);
3069a747e4fSDavid du Colombier 	PLONG(FALSE);
3079a747e4fSDavid du Colombier 	chat("OK\n");
3089a747e4fSDavid du Colombier 	return dataptr - (uchar *)reply->results;
3099a747e4fSDavid du Colombier }
3109a747e4fSDavid du Colombier 
3119a747e4fSDavid du Colombier Xfile *
xfroot(char * name,int n)3129a747e4fSDavid du Colombier xfroot(char *name, int n)
3139a747e4fSDavid du Colombier {
3149a747e4fSDavid du Colombier 	Session *s;
3159a747e4fSDavid du Colombier 	char *p;
3169a747e4fSDavid du Colombier 
3179a747e4fSDavid du Colombier 	if(n <= 0)
3189a747e4fSDavid du Colombier 		n = strlen(name);
3199a747e4fSDavid du Colombier 	chat("xfroot: %.*s...", utfnlen(name, n), name);
3209a747e4fSDavid du Colombier 	if(n == 1 && name[0] == '/')
3219a747e4fSDavid du Colombier 		return head->root;
3229a747e4fSDavid du Colombier 	for(s=head; s; s=s->next){
3239a747e4fSDavid du Colombier 		if(strncmp(name, s->service, n) == 0)
3249a747e4fSDavid du Colombier 			return s->root;
3258c41de82SDavid du Colombier 		p = strrchr(s->service, '!');	/* for -a tcp!foo */
326d9306527SDavid du Colombier 		if(p && strncmp(name, p+1, n) == 0)
327d9306527SDavid du Colombier 			return s->root;
328*883a8c51SDavid du Colombier 		p = strrchr(s->service, '/');	/* for -f /srv/foo */
3299a747e4fSDavid du Colombier 		if(p && strncmp(name, p+1, n) == 0)
3309a747e4fSDavid du Colombier 			return s->root;
3319a747e4fSDavid du Colombier 	}
3329a747e4fSDavid du Colombier 	return 0;
3339a747e4fSDavid du Colombier }
334