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