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