nfs3srv.c (7555B)
1 /* 2 * Simple read-only NFS v3 server. 3 * Runs every request in its own thread. 4 * Expects client to provide the fsxxx routines in nfs3srv.h. 5 */ 6 #include <u.h> 7 #include <libc.h> 8 #include <thread.h> 9 #include <sunrpc.h> 10 #include <nfs3.h> 11 #include "nfs3srv.h" 12 13 int insecure = 0; 14 15 static SunStatus 16 authunixunpack(SunRpc *rpc, SunAuthUnix *au) 17 { 18 uchar *p, *ep; 19 SunAuthInfo *ai; 20 21 ai = &rpc->cred; 22 if(ai->flavor != SunAuthSys) 23 return SunAuthTooWeak; 24 p = ai->data; 25 ep = p+ai->ndata; 26 if(sunauthunixunpack(p, ep, &p, au) < 0) 27 return SunGarbageArgs; 28 if(!insecure){ 29 if(au->uid == 0) 30 au->uid = -1; 31 if(au->gid == 0) 32 au->gid = -1; 33 } 34 35 return SunSuccess; 36 } 37 38 static int 39 rnull(SunMsg *m) 40 { 41 NfsMount3RNull rx; 42 43 memset(&rx, 0, sizeof rx); 44 return sunmsgreply(m, &rx.call); 45 } 46 47 static int 48 rmnt(SunMsg *m) 49 { 50 Nfs3Handle nh; 51 NfsMount3RMnt rx; 52 SunAuthUnix au; 53 int ok; 54 55 if((ok = authunixunpack(&m->rpc, &au)) != SunSuccess) 56 return sunmsgreplyerror(m, ok); 57 58 /* ignore file system path and return the dump tree */ 59 60 memset(&rx, 0, sizeof rx); 61 rx.nauth = 0; 62 rx.status = 0; 63 memset(&nh, 0, sizeof nh); 64 fsgetroot(&nh); 65 rx.handle = nh.h; 66 rx.len = nh.len; 67 68 return sunmsgreply(m, &rx.call); 69 } 70 71 static int 72 rumnt(SunMsg *m) 73 { 74 NfsMount3RUmnt rx; 75 76 /* ignore */ 77 78 memset(&rx, 0, sizeof rx); 79 return sunmsgreply(m, &rx.call); 80 } 81 82 static int 83 rumntall(SunMsg *m) 84 { 85 NfsMount3RUmntall rx; 86 87 /* ignore */ 88 89 memset(&rx, 0, sizeof rx); 90 return sunmsgreply(m, &rx.call); 91 } 92 93 static int 94 rexport(SunMsg *m) 95 { 96 NfsMount3RExport rx; 97 98 /* ignore */ 99 100 memset(&rx, 0, sizeof rx); 101 rx.count = 0; 102 return sunmsgreply(m, &rx.call); 103 } 104 105 static void 106 rmount3(void *v) 107 { 108 SunMsg *m; 109 110 m = v; 111 switch(m->call->type){ 112 default: 113 sunmsgreplyerror(m, SunProcUnavail); 114 case NfsMount3CallTNull: 115 rnull(m); 116 break; 117 case NfsMount3CallTMnt: 118 rmnt(m); 119 break; 120 case NfsMount3CallTDump: 121 rmnt(m); 122 break; 123 case NfsMount3CallTUmnt: 124 rumnt(m); 125 break; 126 case NfsMount3CallTUmntall: 127 rumntall(m); 128 break; 129 case NfsMount3CallTExport: 130 rexport(m); 131 break; 132 } 133 } 134 135 void 136 mount3proc(void *v) 137 { 138 Channel *c; 139 SunMsg *m; 140 141 threadsetname("mount1"); 142 c = v; 143 while((m=recvp(c)) != nil) 144 threadcreate(rmount3, m, SunStackSize); 145 } 146 147 static int 148 senderror(SunMsg *m, SunCall *rc, Nfs3Status status) 149 { 150 /* knows that status is first field in all replies */ 151 ((Nfs3RGetattr*)rc)->status = status; 152 return sunmsgreply(m, rc); 153 } 154 155 static int 156 rnull0(SunMsg *m) 157 { 158 Nfs3RNull rx; 159 160 memset(&rx, 0, sizeof rx); 161 return sunmsgreply(m, &rx.call); 162 } 163 164 static int 165 rgetattr(SunMsg *m) 166 { 167 Nfs3TGetattr *tx = (Nfs3TGetattr*)m->call; 168 Nfs3RGetattr rx; 169 SunAuthUnix au; 170 int ok; 171 172 if((ok = authunixunpack(&m->rpc, &au)) != SunSuccess) 173 return sunmsgreplyerror(m, ok); 174 175 memset(&rx, 0, sizeof rx); 176 rx.status = fsgetattr(&au, &tx->handle, &rx.attr); 177 return sunmsgreply(m, &rx.call); 178 } 179 180 static int 181 rlookup(SunMsg *m) 182 { 183 Nfs3TLookup *tx = (Nfs3TLookup*)m->call; 184 Nfs3RLookup rx; 185 SunAuthUnix au; 186 int ok; 187 188 if((ok = authunixunpack(&m->rpc, &au)) != SunSuccess) 189 return sunmsgreplyerror(m, ok); 190 191 memset(&rx, 0, sizeof rx); 192 rx.status = fsgetattr(&au, &tx->handle, &rx.dirAttr); 193 if(rx.status != Nfs3Ok) 194 return sunmsgreply(m, &rx.call); 195 rx.haveDirAttr = 1; 196 rx.status = fslookup(&au, &tx->handle, tx->name, &rx.handle); 197 if(rx.status != Nfs3Ok) 198 return sunmsgreply(m, &rx.call); 199 rx.status = fsgetattr(&au, &rx.handle, &rx.attr); 200 if(rx.status != Nfs3Ok) 201 return sunmsgreply(m, &rx.call); 202 rx.haveAttr = 1; 203 return sunmsgreply(m, &rx.call); 204 } 205 206 static int 207 raccess(SunMsg *m) 208 { 209 Nfs3TAccess *tx = (Nfs3TAccess*)m->call; 210 Nfs3RAccess rx; 211 SunAuthUnix au; 212 int ok; 213 214 if((ok = authunixunpack(&m->rpc, &au)) != SunSuccess) 215 return sunmsgreplyerror(m, ok); 216 217 memset(&rx, 0, sizeof rx); 218 rx.haveAttr = 1; 219 rx.status = fsaccess(&au, &tx->handle, tx->access, &rx.access, &rx.attr); 220 return sunmsgreply(m, &rx.call); 221 } 222 223 static int 224 rreadlink(SunMsg *m) 225 { 226 Nfs3RReadlink rx; 227 Nfs3TReadlink *tx = (Nfs3TReadlink*)m->call; 228 SunAuthUnix au; 229 int ok; 230 231 if((ok = authunixunpack(&m->rpc, &au)) != SunSuccess) 232 return sunmsgreplyerror(m, ok); 233 234 memset(&rx, 0, sizeof rx); 235 rx.haveAttr = 0; 236 rx.data = nil; 237 rx.status = fsreadlink(&au, &tx->handle, &rx.data); 238 sunmsgreply(m, &rx.call); 239 free(rx.data); 240 return 0; 241 } 242 243 static int 244 rread(SunMsg *m) 245 { 246 Nfs3TRead *tx = (Nfs3TRead*)m->call; 247 Nfs3RRead rx; 248 SunAuthUnix au; 249 int ok; 250 251 if((ok = authunixunpack(&m->rpc, &au)) != SunSuccess) 252 return sunmsgreplyerror(m, ok); 253 254 memset(&rx, 0, sizeof rx); 255 rx.haveAttr = 0; 256 rx.data = nil; 257 rx.status = fsreadfile(&au, &tx->handle, tx->count, tx->offset, &rx.data, &rx.count, &rx.eof); 258 if(rx.status == Nfs3Ok) 259 rx.ndata = rx.count; 260 261 sunmsgreply(m, &rx.call); 262 free(rx.data); 263 return 0; 264 } 265 266 static int 267 rreaddir(SunMsg *m) 268 { 269 Nfs3TReadDir *tx = (Nfs3TReadDir*)m->call; 270 Nfs3RReadDir rx; 271 SunAuthUnix au; 272 int ok; 273 274 if((ok = authunixunpack(&m->rpc, &au)) != SunSuccess) 275 return sunmsgreplyerror(m, ok); 276 277 memset(&rx, 0, sizeof rx); 278 rx.status = fsreaddir(&au, &tx->handle, tx->count, tx->cookie, &rx.data, &rx.count, &rx.eof); 279 sunmsgreply(m, &rx.call); 280 free(rx.data); 281 return 0; 282 } 283 284 static int 285 rreaddirplus(SunMsg *m) 286 { 287 Nfs3RReadDirPlus rx; 288 289 memset(&rx, 0, sizeof rx); 290 rx.status = Nfs3ErrNotSupp; 291 sunmsgreply(m, &rx.call); 292 return 0; 293 } 294 295 static int 296 rfsstat(SunMsg *m) 297 { 298 Nfs3RFsStat rx; 299 300 /* just make something up */ 301 memset(&rx, 0, sizeof rx); 302 rx.status = Nfs3Ok; 303 rx.haveAttr = 0; 304 rx.totalBytes = 1000000000; 305 rx.freeBytes = 0; 306 rx.availBytes = 0; 307 rx.totalFiles = 100000; 308 rx.freeFiles = 0; 309 rx.availFiles = 0; 310 rx.invarSec = 0; 311 return sunmsgreply(m, &rx.call); 312 } 313 314 static int 315 rfsinfo(SunMsg *m) 316 { 317 Nfs3RFsInfo rx; 318 319 /* just make something up */ 320 memset(&rx, 0, sizeof rx); 321 rx.status = Nfs3Ok; 322 rx.haveAttr = 0; 323 rx.readMax = MaxDataSize; 324 rx.readPref = MaxDataSize; 325 rx.readMult = MaxDataSize; 326 rx.writeMax = MaxDataSize; 327 rx.writePref = MaxDataSize; 328 rx.writeMult = MaxDataSize; 329 rx.readDirPref = MaxDataSize; 330 rx.maxFileSize = 1LL<<60; 331 rx.timePrec.sec = 1; 332 rx.timePrec.nsec = 0; 333 rx.flags = Nfs3FsHomogeneous|Nfs3FsCanSetTime; 334 return sunmsgreply(m, &rx.call); 335 } 336 337 static int 338 rpathconf(SunMsg *m) 339 { 340 Nfs3RPathconf rx; 341 342 memset(&rx, 0, sizeof rx); 343 rx.status = Nfs3Ok; 344 rx.haveAttr = 0; 345 rx.maxLink = 1; 346 rx.maxName = 1024; 347 rx.noTrunc = 1; 348 rx.chownRestricted = 0; 349 rx.caseInsensitive = 0; 350 rx.casePreserving = 1; 351 return sunmsgreply(m, &rx.call); 352 } 353 354 static int 355 rrofs(SunMsg *m) 356 { 357 uchar buf[512]; /* clumsy hack*/ 358 359 memset(buf, 0, sizeof buf); 360 return senderror(m, (SunCall*)buf, Nfs3ErrRoFs); 361 } 362 363 364 static void 365 rnfs3(void *v) 366 { 367 SunMsg *m; 368 369 m = v; 370 switch(m->call->type){ 371 default: 372 abort(); 373 case Nfs3CallTNull: 374 rnull0(m); 375 break; 376 case Nfs3CallTGetattr: 377 rgetattr(m); 378 break; 379 case Nfs3CallTLookup: 380 rlookup(m); 381 break; 382 case Nfs3CallTAccess: 383 raccess(m); 384 break; 385 case Nfs3CallTReadlink: 386 rreadlink(m); 387 break; 388 case Nfs3CallTRead: 389 rread(m); 390 break; 391 case Nfs3CallTReadDir: 392 rreaddir(m); 393 break; 394 case Nfs3CallTReadDirPlus: 395 rreaddirplus(m); 396 break; 397 case Nfs3CallTFsStat: 398 rfsstat(m); 399 break; 400 case Nfs3CallTFsInfo: 401 rfsinfo(m); 402 break; 403 case Nfs3CallTPathconf: 404 rpathconf(m); 405 break; 406 case Nfs3CallTSetattr: 407 case Nfs3CallTWrite: 408 case Nfs3CallTCreate: 409 case Nfs3CallTMkdir: 410 case Nfs3CallTSymlink: 411 case Nfs3CallTMknod: 412 case Nfs3CallTRemove: 413 case Nfs3CallTRmdir: 414 case Nfs3CallTLink: 415 case Nfs3CallTCommit: 416 rrofs(m); 417 break; 418 } 419 } 420 421 void 422 nfs3proc(void *v) 423 { 424 Channel *c; 425 SunMsg *m; 426 427 c = v; 428 threadsetname("nfs3"); 429 while((m = recvp(c)) != nil) 430 threadcreate(rnfs3, m, SunStackSize); 431 }