xref: /plan9/sys/src/cmd/aux/nfsmount.c (revision 34e0422554c8e8bef66509534d2c44f4660bf678)
1*34e04225SDavid du Colombier /* Copyright © 2003 Russ Cox, MIT; see /sys/src/libsunrpc/COPYING */
2*34e04225SDavid du Colombier #include <u.h>
3*34e04225SDavid du Colombier #include <libc.h>
4*34e04225SDavid du Colombier #include <thread.h>
5*34e04225SDavid du Colombier #include <sunrpc.h>
6*34e04225SDavid du Colombier #include <nfs3.h>
7*34e04225SDavid du Colombier 
8*34e04225SDavid du Colombier int chatty;
9*34e04225SDavid du Colombier SunClient *client;
10*34e04225SDavid du Colombier 
11*34e04225SDavid du Colombier void
usage(void)12*34e04225SDavid du Colombier usage(void)
13*34e04225SDavid du Colombier {
14*34e04225SDavid du Colombier 	fprint(2, "usage: nfsmount address [cmd]\n"
15*34e04225SDavid du Colombier 		"cmd is one of:\n"
16*34e04225SDavid du Colombier 		"\tnull\n"
17*34e04225SDavid du Colombier 		"\tmnt path\n"
18*34e04225SDavid du Colombier 		"\tdump\n"
19*34e04225SDavid du Colombier 		"\tumnt path\n"
20*34e04225SDavid du Colombier 		"\tumntall\n"
21*34e04225SDavid du Colombier 		"\texport (default)\n");
22*34e04225SDavid du Colombier 	threadexitsall("usage");
23*34e04225SDavid du Colombier }
24*34e04225SDavid du Colombier 
25*34e04225SDavid du Colombier void
portCall(SunCall * c,PortCallType type)26*34e04225SDavid du Colombier portCall(SunCall *c, PortCallType type)
27*34e04225SDavid du Colombier {
28*34e04225SDavid du Colombier 	c->rpc.prog = PortProgram;
29*34e04225SDavid du Colombier 	c->rpc.vers = PortVersion;
30*34e04225SDavid du Colombier 	c->rpc.proc = type>>1;
31*34e04225SDavid du Colombier 	c->rpc.iscall = !(type&1);
32*34e04225SDavid du Colombier 	c->type = type;
33*34e04225SDavid du Colombier }
34*34e04225SDavid du Colombier 
35*34e04225SDavid du Colombier int
getport(SunClient * client,uint prog,uint vers,uint prot,uint * port)36*34e04225SDavid du Colombier getport(SunClient *client, uint prog, uint vers, uint prot, uint *port)
37*34e04225SDavid du Colombier {
38*34e04225SDavid du Colombier 	PortTGetport tx;
39*34e04225SDavid du Colombier 	PortRGetport rx;
40*34e04225SDavid du Colombier 
41*34e04225SDavid du Colombier 	memset(&tx, 0, sizeof tx);
42*34e04225SDavid du Colombier 	portCall(&tx.call, PortCallTGetport);
43*34e04225SDavid du Colombier 	tx.map.prog = prog;
44*34e04225SDavid du Colombier 	tx.map.vers = vers;
45*34e04225SDavid du Colombier 	tx.map.prot = prot;
46*34e04225SDavid du Colombier 
47*34e04225SDavid du Colombier 	memset(&rx, 0, sizeof rx);
48*34e04225SDavid du Colombier 	portCall(&rx.call, PortCallRGetport);
49*34e04225SDavid du Colombier 
50*34e04225SDavid du Colombier 	if(sunClientRpc(client, 0, &tx.call, &rx.call, nil) < 0)
51*34e04225SDavid du Colombier 		return -1;
52*34e04225SDavid du Colombier 	*port = rx.port;
53*34e04225SDavid du Colombier 	return 0;
54*34e04225SDavid du Colombier }
55*34e04225SDavid du Colombier 
56*34e04225SDavid du Colombier uchar unixauth[] = {
57*34e04225SDavid du Colombier 	0x12, 0x23, 0x34, 0x45,	/* stamp */
58*34e04225SDavid du Colombier 	0x00, 0x00, 0x00, 0x04,	/* gnot */
59*34e04225SDavid du Colombier 	0x67, 0x6e, 0x6f, 0x74,
60*34e04225SDavid du Colombier 	0x00, 0x00, 0x03, 0xE9,	/* 1001 */
61*34e04225SDavid du Colombier 	0x00, 0x00, 0x03, 0xE9,	/* 1001 */
62*34e04225SDavid du Colombier 	0x00, 0x00, 0x00, 0x00,	/* gid list */
63*34e04225SDavid du Colombier };
64*34e04225SDavid du Colombier void
mountCall(SunCall * c,NfsMount3CallType type)65*34e04225SDavid du Colombier mountCall(SunCall *c, NfsMount3CallType type)
66*34e04225SDavid du Colombier {
67*34e04225SDavid du Colombier 	c->rpc.prog = NfsMount3Program;
68*34e04225SDavid du Colombier 	c->rpc.vers = NfsMount3Version;
69*34e04225SDavid du Colombier 	c->rpc.proc = type>>1;
70*34e04225SDavid du Colombier 	c->rpc.iscall = !(type&1);
71*34e04225SDavid du Colombier 	if(c->rpc.iscall){
72*34e04225SDavid du Colombier 		c->rpc.cred.flavor = SunAuthSys;
73*34e04225SDavid du Colombier 		c->rpc.cred.data = unixauth;
74*34e04225SDavid du Colombier 		c->rpc.cred.ndata = sizeof unixauth;
75*34e04225SDavid du Colombier 	}
76*34e04225SDavid du Colombier 	c->type = type;
77*34e04225SDavid du Colombier }
78*34e04225SDavid du Colombier 
79*34e04225SDavid du Colombier void
tnull(char ** argv)80*34e04225SDavid du Colombier tnull(char **argv)
81*34e04225SDavid du Colombier {
82*34e04225SDavid du Colombier 	NfsMount3TNull tx;
83*34e04225SDavid du Colombier 	NfsMount3RNull rx;
84*34e04225SDavid du Colombier 
85*34e04225SDavid du Colombier 	USED(argv);
86*34e04225SDavid du Colombier 
87*34e04225SDavid du Colombier 	memset(&tx, 0, sizeof tx);
88*34e04225SDavid du Colombier 	mountCall(&tx.call, NfsMount3CallTNull);
89*34e04225SDavid du Colombier 
90*34e04225SDavid du Colombier 	memset(&rx, 0, sizeof rx);
91*34e04225SDavid du Colombier 	mountCall(&rx.call, NfsMount3CallRNull);
92*34e04225SDavid du Colombier 
93*34e04225SDavid du Colombier 	if(sunClientRpc(client, 0, &tx.call, &rx.call, nil) < 0)
94*34e04225SDavid du Colombier 		sysfatal("rpc: %r");
95*34e04225SDavid du Colombier }
96*34e04225SDavid du Colombier 
97*34e04225SDavid du Colombier void
tmnt(char ** argv)98*34e04225SDavid du Colombier tmnt(char **argv)
99*34e04225SDavid du Colombier {
100*34e04225SDavid du Colombier 	int i;
101*34e04225SDavid du Colombier 	NfsMount3TMnt tx;
102*34e04225SDavid du Colombier 	NfsMount3RMnt rx;
103*34e04225SDavid du Colombier 
104*34e04225SDavid du Colombier 	memset(&tx, 0, sizeof tx);
105*34e04225SDavid du Colombier 	mountCall(&tx.call, NfsMount3CallTMnt);
106*34e04225SDavid du Colombier 	tx.path = argv[0];
107*34e04225SDavid du Colombier 
108*34e04225SDavid du Colombier 	memset(&rx, 0, sizeof rx);
109*34e04225SDavid du Colombier 	mountCall(&rx.call, NfsMount3CallRMnt);
110*34e04225SDavid du Colombier 
111*34e04225SDavid du Colombier 	if(sunClientRpc(client, 0, &tx.call, &rx.call, nil) < 0)
112*34e04225SDavid du Colombier 		sysfatal("rpc: %r");
113*34e04225SDavid du Colombier 
114*34e04225SDavid du Colombier 	if(rx.status != 0){
115*34e04225SDavid du Colombier 		nfs3Errstr(rx.status);
116*34e04225SDavid du Colombier 		sysfatal("mnt: %r");
117*34e04225SDavid du Colombier 	}
118*34e04225SDavid du Colombier 
119*34e04225SDavid du Colombier 	print("handle %.*H\n", rx.len, rx.handle);
120*34e04225SDavid du Colombier 	print("auth:");
121*34e04225SDavid du Colombier 	for(i=0; i<rx.nauth; i++)
122*34e04225SDavid du Colombier 		print(" %ud", (uint)rx.auth[i]);
123*34e04225SDavid du Colombier 	print("\n");
124*34e04225SDavid du Colombier }
125*34e04225SDavid du Colombier 
126*34e04225SDavid du Colombier void
tdump(char ** argv)127*34e04225SDavid du Colombier tdump(char **argv)
128*34e04225SDavid du Colombier {
129*34e04225SDavid du Colombier 	uchar *p, *ep;
130*34e04225SDavid du Colombier 	NfsMount3TDump tx;
131*34e04225SDavid du Colombier 	NfsMount3RDump rx;
132*34e04225SDavid du Colombier 	NfsMount3Entry e;
133*34e04225SDavid du Colombier 
134*34e04225SDavid du Colombier 	memset(&tx, 0, sizeof tx);
135*34e04225SDavid du Colombier 	mountCall(&tx.call, NfsMount3CallTDump);
136*34e04225SDavid du Colombier 	USED(argv);
137*34e04225SDavid du Colombier 
138*34e04225SDavid du Colombier 	memset(&rx, 0, sizeof rx);
139*34e04225SDavid du Colombier 	mountCall(&rx.call, NfsMount3CallRDump);
140*34e04225SDavid du Colombier 
141*34e04225SDavid du Colombier 	if(sunClientRpc(client, 0, &tx.call, &rx.call, nil) < 0)
142*34e04225SDavid du Colombier 		sysfatal("rpc: %r");
143*34e04225SDavid du Colombier 
144*34e04225SDavid du Colombier 	p = rx.data;
145*34e04225SDavid du Colombier 	ep = p+rx.count;
146*34e04225SDavid du Colombier 	while(p < ep){
147*34e04225SDavid du Colombier 		if(nfsMount3EntryUnpack(p, ep, &p, &e) < 0)
148*34e04225SDavid du Colombier 			sysfatal("unpack entry structure failed");
149*34e04225SDavid du Colombier 		print("%s %s\n", e.host, e.path);
150*34e04225SDavid du Colombier 	}
151*34e04225SDavid du Colombier }
152*34e04225SDavid du Colombier 
153*34e04225SDavid du Colombier void
tumnt(char ** argv)154*34e04225SDavid du Colombier tumnt(char **argv)
155*34e04225SDavid du Colombier {
156*34e04225SDavid du Colombier 	NfsMount3TUmnt tx;
157*34e04225SDavid du Colombier 	NfsMount3RUmnt rx;
158*34e04225SDavid du Colombier 
159*34e04225SDavid du Colombier 	memset(&tx, 0, sizeof tx);
160*34e04225SDavid du Colombier 	mountCall(&tx.call, NfsMount3CallTUmnt);
161*34e04225SDavid du Colombier 	tx.path = argv[0];
162*34e04225SDavid du Colombier 
163*34e04225SDavid du Colombier 	memset(&rx, 0, sizeof rx);
164*34e04225SDavid du Colombier 	mountCall(&rx.call, NfsMount3CallRUmnt);
165*34e04225SDavid du Colombier 
166*34e04225SDavid du Colombier 	if(sunClientRpc(client, 0, &tx.call, &rx.call, nil) < 0)
167*34e04225SDavid du Colombier 		sysfatal("rpc: %r");
168*34e04225SDavid du Colombier 
169*34e04225SDavid du Colombier 	print("\n");
170*34e04225SDavid du Colombier }
171*34e04225SDavid du Colombier 
172*34e04225SDavid du Colombier void
tumntall(char ** argv)173*34e04225SDavid du Colombier tumntall(char **argv)
174*34e04225SDavid du Colombier {
175*34e04225SDavid du Colombier 	NfsMount3TUmntall tx;
176*34e04225SDavid du Colombier 	NfsMount3RUmntall rx;
177*34e04225SDavid du Colombier 
178*34e04225SDavid du Colombier 	memset(&tx, 0, sizeof tx);
179*34e04225SDavid du Colombier 	mountCall(&tx.call, NfsMount3CallTUmntall);
180*34e04225SDavid du Colombier 	USED(argv);
181*34e04225SDavid du Colombier 
182*34e04225SDavid du Colombier 	memset(&rx, 0, sizeof rx);
183*34e04225SDavid du Colombier 	mountCall(&rx.call, NfsMount3CallRUmntall);
184*34e04225SDavid du Colombier 
185*34e04225SDavid du Colombier 	if(sunClientRpc(client, 0, &tx.call, &rx.call, nil) < 0)
186*34e04225SDavid du Colombier 		sysfatal("rpc: %r");
187*34e04225SDavid du Colombier 
188*34e04225SDavid du Colombier 	print("\n");
189*34e04225SDavid du Colombier }
190*34e04225SDavid du Colombier 
191*34e04225SDavid du Colombier void
texport(char ** argv)192*34e04225SDavid du Colombier texport(char **argv)
193*34e04225SDavid du Colombier {
194*34e04225SDavid du Colombier 	uchar *p, *ep, *tofree;
195*34e04225SDavid du Colombier 	char **g, **gg;
196*34e04225SDavid du Colombier 	int ng, i, n;
197*34e04225SDavid du Colombier 	NfsMount3TDump tx;
198*34e04225SDavid du Colombier 	NfsMount3RDump rx;
199*34e04225SDavid du Colombier 	NfsMount3Export e;
200*34e04225SDavid du Colombier 
201*34e04225SDavid du Colombier 	memset(&tx, 0, sizeof tx);
202*34e04225SDavid du Colombier 	mountCall(&tx.call, NfsMount3CallTExport);
203*34e04225SDavid du Colombier 	USED(argv);
204*34e04225SDavid du Colombier 
205*34e04225SDavid du Colombier 	memset(&rx, 0, sizeof rx);
206*34e04225SDavid du Colombier 	mountCall(&rx.call, NfsMount3CallRExport);
207*34e04225SDavid du Colombier 
208*34e04225SDavid du Colombier 	if(sunClientRpc(client, 0, &tx.call, &rx.call, &tofree) < 0)
209*34e04225SDavid du Colombier 		sysfatal("rpc: %r");
210*34e04225SDavid du Colombier 
211*34e04225SDavid du Colombier 	p = rx.data;
212*34e04225SDavid du Colombier 	ep = p+rx.count;
213*34e04225SDavid du Colombier 	g = nil;
214*34e04225SDavid du Colombier 	ng = 0;
215*34e04225SDavid du Colombier 	while(p < ep){
216*34e04225SDavid du Colombier 		n = nfsMount3ExportGroupSize(p);
217*34e04225SDavid du Colombier 		if(n > ng){
218*34e04225SDavid du Colombier 			ng = n;
219*34e04225SDavid du Colombier 			g = erealloc(g, sizeof(g[0])*ng);
220*34e04225SDavid du Colombier 		}
221*34e04225SDavid du Colombier 		if(nfsMount3ExportUnpack(p, ep, &p, g, &gg, &e) < 0)
222*34e04225SDavid du Colombier 			sysfatal("unpack export structure failed");
223*34e04225SDavid du Colombier 		print("%s", e.path);
224*34e04225SDavid du Colombier 		for(i=0; i<e.ng; i++)
225*34e04225SDavid du Colombier 			print(" %s", e.g[i]);
226*34e04225SDavid du Colombier 		print("\n");
227*34e04225SDavid du Colombier 	}
228*34e04225SDavid du Colombier 	free(tofree);
229*34e04225SDavid du Colombier }
230*34e04225SDavid du Colombier 
231*34e04225SDavid du Colombier static struct {
232*34e04225SDavid du Colombier 	char *cmd;
233*34e04225SDavid du Colombier 	int narg;
234*34e04225SDavid du Colombier 	void (*fn)(char**);
235*34e04225SDavid du Colombier } tab[] = {
236*34e04225SDavid du Colombier 	"null",	0,	tnull,
237*34e04225SDavid du Colombier 	"mnt",	1,	tmnt,
238*34e04225SDavid du Colombier 	"dump",	0,	tdump,
239*34e04225SDavid du Colombier 	"umnt",	1,	tumnt,
240*34e04225SDavid du Colombier 	"umntall",	1,	tumntall,
241*34e04225SDavid du Colombier 	"export",	0,	texport,
242*34e04225SDavid du Colombier };
243*34e04225SDavid du Colombier 
244*34e04225SDavid du Colombier char*
netchangeport(char * addr,char * port)245*34e04225SDavid du Colombier netchangeport(char *addr, char *port)
246*34e04225SDavid du Colombier {
247*34e04225SDavid du Colombier 	static char buf[256];
248*34e04225SDavid du Colombier 	char *r;
249*34e04225SDavid du Colombier 
250*34e04225SDavid du Colombier 	strecpy(buf, buf+sizeof buf, addr);
251*34e04225SDavid du Colombier 	r = strrchr(buf, '!');
252*34e04225SDavid du Colombier 	if(r == nil)
253*34e04225SDavid du Colombier 		return nil;
254*34e04225SDavid du Colombier 	r++;
255*34e04225SDavid du Colombier 	strecpy(r, buf+sizeof buf, port);
256*34e04225SDavid du Colombier 	return buf;
257*34e04225SDavid du Colombier }
258*34e04225SDavid du Colombier 
259*34e04225SDavid du Colombier void
threadmain(int argc,char ** argv)260*34e04225SDavid du Colombier threadmain(int argc, char **argv)
261*34e04225SDavid du Colombier {
262*34e04225SDavid du Colombier 	char *dflt[] = { "export", };
263*34e04225SDavid du Colombier 	char *addr, *cmd;
264*34e04225SDavid du Colombier 	int i, proto;
265*34e04225SDavid du Colombier 	uint port;
266*34e04225SDavid du Colombier 	char buf[32];
267*34e04225SDavid du Colombier 	int mapit;
268*34e04225SDavid du Colombier 
269*34e04225SDavid du Colombier 	mapit = 1;
270*34e04225SDavid du Colombier 	ARGBEGIN{
271*34e04225SDavid du Colombier 	case 'R':
272*34e04225SDavid du Colombier 		chatty++;
273*34e04225SDavid du Colombier 		break;
274*34e04225SDavid du Colombier 	case 'm':
275*34e04225SDavid du Colombier 		mapit = 0;
276*34e04225SDavid du Colombier 		break;
277*34e04225SDavid du Colombier 	}ARGEND
278*34e04225SDavid du Colombier 
279*34e04225SDavid du Colombier 	if(argc < 1)
280*34e04225SDavid du Colombier 		usage();
281*34e04225SDavid du Colombier 
282*34e04225SDavid du Colombier 	fmtinstall('B', sunRpcFmt);
283*34e04225SDavid du Colombier 	fmtinstall('C', sunCallFmt);
284*34e04225SDavid du Colombier 	fmtinstall('H', encodefmt);
285*34e04225SDavid du Colombier 	sunFmtInstall(&portProg);
286*34e04225SDavid du Colombier 	sunFmtInstall(&nfsMount3Prog);
287*34e04225SDavid du Colombier 
288*34e04225SDavid du Colombier 	addr = netmkaddr(argv[0], "udp", "portmap");
289*34e04225SDavid du Colombier 	if(mapit){
290*34e04225SDavid du Colombier 		/* translate with port mapper */
291*34e04225SDavid du Colombier 		fprint(2, "connecting to %s\n", addr);
292*34e04225SDavid du Colombier 		if((client = sunDial(addr)) == nil)
293*34e04225SDavid du Colombier 			sysfatal("dial %s: %r", addr);
294*34e04225SDavid du Colombier 		client->chatty = chatty;
295*34e04225SDavid du Colombier 		sunClientProg(client, &portProg);
296*34e04225SDavid du Colombier 		if(strstr(addr, "udp!"))
297*34e04225SDavid du Colombier 			proto = PortProtoUdp;
298*34e04225SDavid du Colombier 		else
299*34e04225SDavid du Colombier 			proto = PortProtoTcp;
300*34e04225SDavid du Colombier 		if(getport(client, NfsMount3Program, NfsMount3Version, proto, &port) < 0)
301*34e04225SDavid du Colombier 			sysfatal("getport: %r");
302*34e04225SDavid du Colombier 		snprint(buf, sizeof buf, "%ud!r", port);
303*34e04225SDavid du Colombier 		addr = netchangeport(addr, buf);
304*34e04225SDavid du Colombier 		sunClientClose(client);
305*34e04225SDavid du Colombier 	}
306*34e04225SDavid du Colombier 
307*34e04225SDavid du Colombier 	fprint(2, "connecting to %s\n", addr);
308*34e04225SDavid du Colombier 	if((client = sunDial(addr)) == nil)
309*34e04225SDavid du Colombier 		sysfatal("dial %s: %r", addr);
310*34e04225SDavid du Colombier 
311*34e04225SDavid du Colombier 	client->chatty = chatty;
312*34e04225SDavid du Colombier 	sunClientProg(client, &nfsMount3Prog);
313*34e04225SDavid du Colombier 
314*34e04225SDavid du Colombier 	argv++;
315*34e04225SDavid du Colombier 	argc--;
316*34e04225SDavid du Colombier 
317*34e04225SDavid du Colombier 	if(argc == 0){
318*34e04225SDavid du Colombier 		argc = 1;
319*34e04225SDavid du Colombier 		argv = dflt;
320*34e04225SDavid du Colombier 	}
321*34e04225SDavid du Colombier 	cmd = argv[0];
322*34e04225SDavid du Colombier 	argv++;
323*34e04225SDavid du Colombier 	argc--;
324*34e04225SDavid du Colombier 
325*34e04225SDavid du Colombier 	for(i=0; i<nelem(tab); i++){
326*34e04225SDavid du Colombier 		if(strcmp(tab[i].cmd, cmd) == 0){
327*34e04225SDavid du Colombier 			if(tab[i].narg != argc)
328*34e04225SDavid du Colombier 				usage();
329*34e04225SDavid du Colombier 			(*tab[i].fn)(argv);
330*34e04225SDavid du Colombier 			threadexitsall(nil);
331*34e04225SDavid du Colombier 		}
332*34e04225SDavid du Colombier 	}
333*34e04225SDavid du Colombier 	usage();
334*34e04225SDavid du Colombier }
335