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 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 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 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 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 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* 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 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 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 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 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 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 * 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