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