1 #include "all.h"
2
3 /*
4 * Cf. /lib/rfc/rfc1094
5 */
6
7 static int mntnull(int, Rpccall*, Rpccall*);
8 static int mntmnt(int, Rpccall*, Rpccall*);
9 static int mntdump(int, Rpccall*, Rpccall*);
10 static int mntumnt(int, Rpccall*, Rpccall*);
11 static int mntumntall(int, Rpccall*, Rpccall*);
12 static int mntexport(int, Rpccall*, Rpccall*);
13
14 Procmap mntproc[] = {
15 0, mntnull,
16 1, mntmnt,
17 2, mntdump,
18 3, mntumnt,
19 4, mntumntall,
20 5, mntexport,
21 0, 0
22 };
23
24 long starttime;
25 static int noauth;
26 char * config;
27 Session * head;
28 Session * tail;
29 int staletime = 10*60;
30
31 void
mnttimer(long now)32 mnttimer(long now)
33 {
34 Session *s;
35
36 for(s=head; s; s=s->next)
37 fidtimer(s, now);
38 }
39
40 static void
usage(void)41 usage(void)
42 {
43 sysfatal("usage: %s %s [-ns] [-a dialstring] [-c uidmap] [-f srvfile] "
44 "[-T staletime]", argv0, commonopts);
45 }
46
47 void
mntinit(int argc,char ** argv)48 mntinit(int argc, char **argv)
49 {
50 int tries;
51
52 config = "config";
53 starttime = time(0);
54 clog("nfs mount server init, starttime = %lud\n", starttime);
55 tries = 0;
56 ARGBEGIN{
57 case 'a':
58 ++tries;
59 srvinit(-1, 0, EARGF(usage()));
60 break;
61 case 'c':
62 config = EARGF(usage());
63 break;
64 case 'f':
65 ++tries;
66 srvinit(-1, EARGF(usage()), 0);
67 break;
68 case 'n':
69 ++noauth;
70 break;
71 case 's':
72 ++tries;
73 srvinit(1, 0, 0);
74 break;
75 case 'T':
76 staletime = atoi(EARGF(usage()));
77 break;
78 default:
79 if(argopt(ARGC()) < 0)
80 sysfatal("usage: %s %s [-ns] [-a dialstring] "
81 "[-c uidmap] [-f srvfile] [-T staletime]",
82 argv0, commonopts);
83 break;
84 }ARGEND
85 noauth=1; /* ZZZ */
86 if(tries == 0 && head == 0)
87 srvinit(-1, 0, "tcp!fs");
88 if(head == 0)
89 panic("can't initialize services");
90 readunixidmaps(config);
91 }
92
93 void
srvinit(int fd,char * file,char * addr)94 srvinit(int fd, char *file, char *addr)
95 {
96 char fdservice[16], *naddr;
97 Session *s;
98 Xfile *xp;
99 Xfid *xf;
100 Fid *f;
101
102 s = calloc(1, sizeof(Session));
103 s->spec = "";
104 s->fd = -1;
105 if(fd >= 0){
106 s->fd = fd;
107 sprint(fdservice, "/fd/%d", s->fd);
108 s->service = strstore(fdservice);
109 chat("fd = %d\n", s->fd);
110 }else if(file){
111 chat("file = \"%s\"\n", file);
112 s->service = file;
113 s->fd = open(file, ORDWR);
114 if(s->fd < 0){
115 clog("can't open %s: %r\n", file);
116 goto error;
117 }
118 }else if(addr){
119 chat("addr = \"%s\"\n", addr);
120 naddr = netmkaddr(addr, 0, "9fs");
121 s->service = addr;
122 s->fd = dial(naddr, 0, 0, 0);
123 if(s->fd < 0){
124 clog("can't dial %s: %r\n", naddr);
125 goto error;
126 }
127 }
128
129 chat("version...");
130 s->tag = NOTAG-1;
131 s->f.msize = Maxfdata+IOHDRSZ;
132 s->f.version = "9P2000";
133 xmesg(s, Tversion);
134 messagesize = IOHDRSZ+s->f.msize;
135 chat("version spec %s size %d\n", s->f.version, s->f.msize);
136
137 s->tag = 0;
138
139 chat("authenticate...");
140 if(authhostowner(s) < 0){
141 clog("auth failed %r\n");
142 goto error;
143 }
144
145 chat("attach as none...");
146 f = newfid(s);
147 s->f.fid = f - s->fids;
148 s->f.afid = ~0x0UL;
149 s->f.uname = "none";
150 s->f.aname = s->spec;
151 if(xmesg(s, Tattach)){
152 clog("attach failed\n");
153 goto error;
154 }
155
156 xp = xfile(&s->f.qid, s, 1);
157 s->root = xp;
158 xp->parent = xp;
159 xp->name = "/";
160 xf = xfid("none", xp, 1);
161 xf->urfid = f;
162 clog("service=%s uid=%s fid=%ld\n",
163 s->service, xf->uid, xf->urfid - s->fids);
164 if(tail)
165 tail->next = s;
166 else
167 head = s;
168 tail = s;
169 return;
170
171 error:
172 if(s->fd >= 0)
173 close(s->fd);
174 free(s);
175 }
176
177 static int
mntnull(int n,Rpccall * cmd,Rpccall * reply)178 mntnull(int n, Rpccall *cmd, Rpccall *reply)
179 {
180 USED(n, cmd, reply);
181 chat("mntnull\n");
182 return 0;
183 }
184
185 static char*
Str2str(String s,char * buf,int nbuf)186 Str2str(String s, char *buf, int nbuf)
187 {
188 int i;
189 i = s.n;
190 if(i >= nbuf)
191 i = nbuf-1;
192 memmove(buf, s.s, i);
193 buf[i] = 0;
194 return buf;
195 }
196
197 static int
mntmnt(int n,Rpccall * cmd,Rpccall * reply)198 mntmnt(int n, Rpccall *cmd, Rpccall *reply)
199 {
200 int i;
201 char dom[64];
202 uchar *argptr = cmd->args;
203 uchar *dataptr = reply->results;
204 Authunix au;
205 Xfile *xp;
206 String root;
207
208 chat("mntmnt...\n");
209 if(n < 8)
210 return garbage(reply, "n too small");
211 argptr += string2S(argptr, &root);
212 if(argptr != &((uchar *)cmd->args)[n])
213 return garbage(reply, "bad count");
214 clog("host=%I, port=%ld, root=\"%.*s\"...",
215 cmd->host, cmd->port, utfnlen(root.s, root.n), root.s);
216 if(auth2unix(&cmd->cred, &au) != 0){
217 chat("auth flavor=%ld, count=%ld\n",
218 cmd->cred.flavor, cmd->cred.count);
219 for(i=0; i<cmd->cred.count; i++)
220 chat(" %.2ux", ((uchar *)cmd->cred.data)[i]);
221 chat("\n");
222 clog("auth: bad credentials");
223 return error(reply, 1);
224 }
225 clog("auth: %ld %.*s u=%ld g=%ld",
226 au.stamp, utfnlen(au.mach.s, au.mach.n), au.mach.s, au.uid, au.gid);
227 for(i=0; i<au.gidlen; i++)
228 chat(", %ld", au.gids[i]);
229 chat("...");
230 if(getdom(cmd->host, dom, sizeof(dom))<0){
231 clog("auth: unknown ip address");
232 return error(reply, 1);
233 }
234 chat("dom=%s...", dom);
235 xp = xfroot(root.s, root.n);
236 if(xp == 0){
237 chat("xp=0...");
238 clog("mntmnt: no fs");
239 return error(reply, 3);
240 }
241
242 PLONG(0);
243 dataptr += xp2fhandle(xp, dataptr);
244 chat("OK\n");
245 return dataptr - (uchar *)reply->results;
246 }
247
248 static int
mntdump(int n,Rpccall * cmd,Rpccall * reply)249 mntdump(int n, Rpccall *cmd, Rpccall *reply)
250 {
251 if(n != 0)
252 return garbage(reply, "mntdump");
253 USED(cmd);
254 chat("mntdump...");
255 return error(reply, FALSE);
256 }
257
258 static int
mntumnt(int n,Rpccall * cmd,Rpccall * reply)259 mntumnt(int n, Rpccall *cmd, Rpccall *reply)
260 {
261 if(n <= 0)
262 return garbage(reply, "mntumnt");
263 USED(cmd);
264 chat("mntumnt\n");
265 return 0;
266 }
267
268 static int
mntumntall(int n,Rpccall * cmd,Rpccall * reply)269 mntumntall(int n, Rpccall *cmd, Rpccall *reply)
270 {
271 if(n != 0)
272 return garbage(reply, "mntumntall");
273 USED(cmd);
274 chat("mntumntall\n");
275 return 0;
276 }
277
278 static int
mntexport(int n,Rpccall * cmd,Rpccall * reply)279 mntexport(int n, Rpccall *cmd, Rpccall *reply)
280 {
281 uchar *dataptr = reply->results;
282 Authunix au;
283 int i;
284
285 chat("mntexport...");
286 if(n != 0)
287 return garbage(reply, "mntexport");
288 if(auth2unix(&cmd->cred, &au) != 0){
289 chat("auth flavor=%ld, count=%ld\n",
290 cmd->cred.flavor, cmd->cred.count);
291 for(i=0; i<cmd->cred.count; i++)
292 chat(" %.2ux", ((uchar *)cmd->cred.data)[i]);
293 chat("...");
294 au.mach.n = 0;
295 }else
296 chat("%ld@%.*s...", au.uid, utfnlen(au.mach.s, au.mach.n), au.mach.s);
297 PLONG(TRUE);
298 PLONG(1);
299 PPTR("/", 1);
300 if(au.mach.n > 0){
301 PLONG(TRUE);
302 PLONG(au.mach.n);
303 PPTR(au.mach.s, au.mach.n);
304 }
305 PLONG(FALSE);
306 PLONG(FALSE);
307 chat("OK\n");
308 return dataptr - (uchar *)reply->results;
309 }
310
311 Xfile *
xfroot(char * name,int n)312 xfroot(char *name, int n)
313 {
314 Session *s;
315 char *p;
316
317 if(n <= 0)
318 n = strlen(name);
319 chat("xfroot: %.*s...", utfnlen(name, n), name);
320 if(n == 1 && name[0] == '/')
321 return head->root;
322 for(s=head; s; s=s->next){
323 if(strncmp(name, s->service, n) == 0)
324 return s->root;
325 p = strrchr(s->service, '!'); /* for -a tcp!foo */
326 if(p && strncmp(name, p+1, n) == 0)
327 return s->root;
328 p = strrchr(s->service, '/'); /* for -f /srv/foo */
329 if(p && strncmp(name, p+1, n) == 0)
330 return s->root;
331 }
332 return 0;
333 }
334