1 /* 2 * linux/fs/nfsd/nfsxdr.c 3 * 4 * XDR support for nfsd 5 * 6 * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de> 7 */ 8 9 #include <linux/types.h> 10 #include <linux/time.h> 11 #include <linux/nfs.h> 12 #include <linux/vfs.h> 13 #include <linux/sunrpc/xdr.h> 14 #include <linux/sunrpc/svc.h> 15 #include <linux/nfsd/nfsd.h> 16 #include <linux/nfsd/xdr.h> 17 #include <linux/mm.h> 18 #include "auth.h" 19 20 #define NFSDDBG_FACILITY NFSDDBG_XDR 21 22 /* 23 * Mapping of S_IF* types to NFS file types 24 */ 25 static u32 nfs_ftypes[] = { 26 NFNON, NFCHR, NFCHR, NFBAD, 27 NFDIR, NFBAD, NFBLK, NFBAD, 28 NFREG, NFBAD, NFLNK, NFBAD, 29 NFSOCK, NFBAD, NFLNK, NFBAD, 30 }; 31 32 33 /* 34 * XDR functions for basic NFS types 35 */ 36 static __be32 * 37 decode_fh(__be32 *p, struct svc_fh *fhp) 38 { 39 fh_init(fhp, NFS_FHSIZE); 40 memcpy(&fhp->fh_handle.fh_base, p, NFS_FHSIZE); 41 fhp->fh_handle.fh_size = NFS_FHSIZE; 42 43 /* FIXME: Look up export pointer here and verify 44 * Sun Secure RPC if requested */ 45 return p + (NFS_FHSIZE >> 2); 46 } 47 48 /* Helper function for NFSv2 ACL code */ 49 __be32 *nfs2svc_decode_fh(__be32 *p, struct svc_fh *fhp) 50 { 51 return decode_fh(p, fhp); 52 } 53 54 static __be32 * 55 encode_fh(__be32 *p, struct svc_fh *fhp) 56 { 57 memcpy(p, &fhp->fh_handle.fh_base, NFS_FHSIZE); 58 return p + (NFS_FHSIZE>> 2); 59 } 60 61 /* 62 * Decode a file name and make sure that the path contains 63 * no slashes or null bytes. 64 */ 65 static __be32 * 66 decode_filename(__be32 *p, char **namp, unsigned int *lenp) 67 { 68 char *name; 69 unsigned int i; 70 71 if ((p = xdr_decode_string_inplace(p, namp, lenp, NFS_MAXNAMLEN)) != NULL) { 72 for (i = 0, name = *namp; i < *lenp; i++, name++) { 73 if (*name == '\0' || *name == '/') 74 return NULL; 75 } 76 } 77 78 return p; 79 } 80 81 static __be32 * 82 decode_pathname(__be32 *p, char **namp, unsigned int *lenp) 83 { 84 char *name; 85 unsigned int i; 86 87 if ((p = xdr_decode_string_inplace(p, namp, lenp, NFS_MAXPATHLEN)) != NULL) { 88 for (i = 0, name = *namp; i < *lenp; i++, name++) { 89 if (*name == '\0') 90 return NULL; 91 } 92 } 93 94 return p; 95 } 96 97 static __be32 * 98 decode_sattr(__be32 *p, struct iattr *iap) 99 { 100 u32 tmp, tmp1; 101 102 iap->ia_valid = 0; 103 104 /* Sun client bug compatibility check: some sun clients seem to 105 * put 0xffff in the mode field when they mean 0xffffffff. 106 * Quoting the 4.4BSD nfs server code: Nah nah nah nah na nah. 107 */ 108 if ((tmp = ntohl(*p++)) != (u32)-1 && tmp != 0xffff) { 109 iap->ia_valid |= ATTR_MODE; 110 iap->ia_mode = tmp; 111 } 112 if ((tmp = ntohl(*p++)) != (u32)-1) { 113 iap->ia_valid |= ATTR_UID; 114 iap->ia_uid = tmp; 115 } 116 if ((tmp = ntohl(*p++)) != (u32)-1) { 117 iap->ia_valid |= ATTR_GID; 118 iap->ia_gid = tmp; 119 } 120 if ((tmp = ntohl(*p++)) != (u32)-1) { 121 iap->ia_valid |= ATTR_SIZE; 122 iap->ia_size = tmp; 123 } 124 tmp = ntohl(*p++); tmp1 = ntohl(*p++); 125 if (tmp != (u32)-1 && tmp1 != (u32)-1) { 126 iap->ia_valid |= ATTR_ATIME | ATTR_ATIME_SET; 127 iap->ia_atime.tv_sec = tmp; 128 iap->ia_atime.tv_nsec = tmp1 * 1000; 129 } 130 tmp = ntohl(*p++); tmp1 = ntohl(*p++); 131 if (tmp != (u32)-1 && tmp1 != (u32)-1) { 132 iap->ia_valid |= ATTR_MTIME | ATTR_MTIME_SET; 133 iap->ia_mtime.tv_sec = tmp; 134 iap->ia_mtime.tv_nsec = tmp1 * 1000; 135 /* 136 * Passing the invalid value useconds=1000000 for mtime 137 * is a Sun convention for "set both mtime and atime to 138 * current server time". It's needed to make permissions 139 * checks for the "touch" program across v2 mounts to 140 * Solaris and Irix boxes work correctly. See description of 141 * sattr in section 6.1 of "NFS Illustrated" by 142 * Brent Callaghan, Addison-Wesley, ISBN 0-201-32750-5 143 */ 144 if (tmp1 == 1000000) 145 iap->ia_valid &= ~(ATTR_ATIME_SET|ATTR_MTIME_SET); 146 } 147 return p; 148 } 149 150 static __be32 * 151 encode_fattr(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *fhp, 152 struct kstat *stat) 153 { 154 struct dentry *dentry = fhp->fh_dentry; 155 int type; 156 struct timespec time; 157 u32 f; 158 159 type = (stat->mode & S_IFMT); 160 161 *p++ = htonl(nfs_ftypes[type >> 12]); 162 *p++ = htonl((u32) stat->mode); 163 *p++ = htonl((u32) stat->nlink); 164 *p++ = htonl((u32) nfsd_ruid(rqstp, stat->uid)); 165 *p++ = htonl((u32) nfsd_rgid(rqstp, stat->gid)); 166 167 if (S_ISLNK(type) && stat->size > NFS_MAXPATHLEN) { 168 *p++ = htonl(NFS_MAXPATHLEN); 169 } else { 170 *p++ = htonl((u32) stat->size); 171 } 172 *p++ = htonl((u32) stat->blksize); 173 if (S_ISCHR(type) || S_ISBLK(type)) 174 *p++ = htonl(new_encode_dev(stat->rdev)); 175 else 176 *p++ = htonl(0xffffffff); 177 *p++ = htonl((u32) stat->blocks); 178 switch (fsid_source(fhp)) { 179 default: 180 case FSIDSOURCE_DEV: 181 *p++ = htonl(new_encode_dev(stat->dev)); 182 break; 183 case FSIDSOURCE_FSID: 184 *p++ = htonl((u32) fhp->fh_export->ex_fsid); 185 break; 186 case FSIDSOURCE_UUID: 187 f = ((u32*)fhp->fh_export->ex_uuid)[0]; 188 f ^= ((u32*)fhp->fh_export->ex_uuid)[1]; 189 f ^= ((u32*)fhp->fh_export->ex_uuid)[2]; 190 f ^= ((u32*)fhp->fh_export->ex_uuid)[3]; 191 *p++ = htonl(f); 192 break; 193 } 194 *p++ = htonl((u32) stat->ino); 195 *p++ = htonl((u32) stat->atime.tv_sec); 196 *p++ = htonl(stat->atime.tv_nsec ? stat->atime.tv_nsec / 1000 : 0); 197 lease_get_mtime(dentry->d_inode, &time); 198 *p++ = htonl((u32) time.tv_sec); 199 *p++ = htonl(time.tv_nsec ? time.tv_nsec / 1000 : 0); 200 *p++ = htonl((u32) stat->ctime.tv_sec); 201 *p++ = htonl(stat->ctime.tv_nsec ? stat->ctime.tv_nsec / 1000 : 0); 202 203 return p; 204 } 205 206 /* Helper function for NFSv2 ACL code */ 207 __be32 *nfs2svc_encode_fattr(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *fhp) 208 { 209 struct kstat stat; 210 vfs_getattr(fhp->fh_export->ex_path.mnt, fhp->fh_dentry, &stat); 211 return encode_fattr(rqstp, p, fhp, &stat); 212 } 213 214 /* 215 * XDR decode functions 216 */ 217 int 218 nfssvc_decode_void(struct svc_rqst *rqstp, __be32 *p, void *dummy) 219 { 220 return xdr_argsize_check(rqstp, p); 221 } 222 223 int 224 nfssvc_decode_fhandle(struct svc_rqst *rqstp, __be32 *p, struct nfsd_fhandle *args) 225 { 226 if (!(p = decode_fh(p, &args->fh))) 227 return 0; 228 return xdr_argsize_check(rqstp, p); 229 } 230 231 int 232 nfssvc_decode_sattrargs(struct svc_rqst *rqstp, __be32 *p, 233 struct nfsd_sattrargs *args) 234 { 235 p = decode_fh(p, &args->fh); 236 if (!p) 237 return 0; 238 p = decode_sattr(p, &args->attrs); 239 240 return xdr_argsize_check(rqstp, p); 241 } 242 243 int 244 nfssvc_decode_diropargs(struct svc_rqst *rqstp, __be32 *p, 245 struct nfsd_diropargs *args) 246 { 247 if (!(p = decode_fh(p, &args->fh)) 248 || !(p = decode_filename(p, &args->name, &args->len))) 249 return 0; 250 251 return xdr_argsize_check(rqstp, p); 252 } 253 254 int 255 nfssvc_decode_readargs(struct svc_rqst *rqstp, __be32 *p, 256 struct nfsd_readargs *args) 257 { 258 unsigned int len; 259 int v,pn; 260 if (!(p = decode_fh(p, &args->fh))) 261 return 0; 262 263 args->offset = ntohl(*p++); 264 len = args->count = ntohl(*p++); 265 p++; /* totalcount - unused */ 266 267 if (len > NFSSVC_MAXBLKSIZE_V2) 268 len = NFSSVC_MAXBLKSIZE_V2; 269 270 /* set up somewhere to store response. 271 * We take pages, put them on reslist and include in iovec 272 */ 273 v=0; 274 while (len > 0) { 275 pn = rqstp->rq_resused++; 276 rqstp->rq_vec[v].iov_base = page_address(rqstp->rq_respages[pn]); 277 rqstp->rq_vec[v].iov_len = len < PAGE_SIZE?len:PAGE_SIZE; 278 len -= rqstp->rq_vec[v].iov_len; 279 v++; 280 } 281 args->vlen = v; 282 return xdr_argsize_check(rqstp, p); 283 } 284 285 int 286 nfssvc_decode_writeargs(struct svc_rqst *rqstp, __be32 *p, 287 struct nfsd_writeargs *args) 288 { 289 unsigned int len, hdr, dlen; 290 int v; 291 292 if (!(p = decode_fh(p, &args->fh))) 293 return 0; 294 295 p++; /* beginoffset */ 296 args->offset = ntohl(*p++); /* offset */ 297 p++; /* totalcount */ 298 len = args->len = ntohl(*p++); 299 /* 300 * The protocol specifies a maximum of 8192 bytes. 301 */ 302 if (len > NFSSVC_MAXBLKSIZE_V2) 303 return 0; 304 305 /* 306 * Check to make sure that we got the right number of 307 * bytes. 308 */ 309 hdr = (void*)p - rqstp->rq_arg.head[0].iov_base; 310 dlen = rqstp->rq_arg.head[0].iov_len + rqstp->rq_arg.page_len 311 - hdr; 312 313 /* 314 * Round the length of the data which was specified up to 315 * the next multiple of XDR units and then compare that 316 * against the length which was actually received. 317 * Note that when RPCSEC/GSS (for example) is used, the 318 * data buffer can be padded so dlen might be larger 319 * than required. It must never be smaller. 320 */ 321 if (dlen < XDR_QUADLEN(len)*4) 322 return 0; 323 324 rqstp->rq_vec[0].iov_base = (void*)p; 325 rqstp->rq_vec[0].iov_len = rqstp->rq_arg.head[0].iov_len - hdr; 326 v = 0; 327 while (len > rqstp->rq_vec[v].iov_len) { 328 len -= rqstp->rq_vec[v].iov_len; 329 v++; 330 rqstp->rq_vec[v].iov_base = page_address(rqstp->rq_pages[v]); 331 rqstp->rq_vec[v].iov_len = PAGE_SIZE; 332 } 333 rqstp->rq_vec[v].iov_len = len; 334 args->vlen = v + 1; 335 return 1; 336 } 337 338 int 339 nfssvc_decode_createargs(struct svc_rqst *rqstp, __be32 *p, 340 struct nfsd_createargs *args) 341 { 342 if ( !(p = decode_fh(p, &args->fh)) 343 || !(p = decode_filename(p, &args->name, &args->len))) 344 return 0; 345 p = decode_sattr(p, &args->attrs); 346 347 return xdr_argsize_check(rqstp, p); 348 } 349 350 int 351 nfssvc_decode_renameargs(struct svc_rqst *rqstp, __be32 *p, 352 struct nfsd_renameargs *args) 353 { 354 if (!(p = decode_fh(p, &args->ffh)) 355 || !(p = decode_filename(p, &args->fname, &args->flen)) 356 || !(p = decode_fh(p, &args->tfh)) 357 || !(p = decode_filename(p, &args->tname, &args->tlen))) 358 return 0; 359 360 return xdr_argsize_check(rqstp, p); 361 } 362 363 int 364 nfssvc_decode_readlinkargs(struct svc_rqst *rqstp, __be32 *p, struct nfsd_readlinkargs *args) 365 { 366 if (!(p = decode_fh(p, &args->fh))) 367 return 0; 368 args->buffer = page_address(rqstp->rq_respages[rqstp->rq_resused++]); 369 370 return xdr_argsize_check(rqstp, p); 371 } 372 373 int 374 nfssvc_decode_linkargs(struct svc_rqst *rqstp, __be32 *p, 375 struct nfsd_linkargs *args) 376 { 377 if (!(p = decode_fh(p, &args->ffh)) 378 || !(p = decode_fh(p, &args->tfh)) 379 || !(p = decode_filename(p, &args->tname, &args->tlen))) 380 return 0; 381 382 return xdr_argsize_check(rqstp, p); 383 } 384 385 int 386 nfssvc_decode_symlinkargs(struct svc_rqst *rqstp, __be32 *p, 387 struct nfsd_symlinkargs *args) 388 { 389 if ( !(p = decode_fh(p, &args->ffh)) 390 || !(p = decode_filename(p, &args->fname, &args->flen)) 391 || !(p = decode_pathname(p, &args->tname, &args->tlen))) 392 return 0; 393 p = decode_sattr(p, &args->attrs); 394 395 return xdr_argsize_check(rqstp, p); 396 } 397 398 int 399 nfssvc_decode_readdirargs(struct svc_rqst *rqstp, __be32 *p, 400 struct nfsd_readdirargs *args) 401 { 402 if (!(p = decode_fh(p, &args->fh))) 403 return 0; 404 args->cookie = ntohl(*p++); 405 args->count = ntohl(*p++); 406 if (args->count > PAGE_SIZE) 407 args->count = PAGE_SIZE; 408 409 args->buffer = page_address(rqstp->rq_respages[rqstp->rq_resused++]); 410 411 return xdr_argsize_check(rqstp, p); 412 } 413 414 /* 415 * XDR encode functions 416 */ 417 int 418 nfssvc_encode_void(struct svc_rqst *rqstp, __be32 *p, void *dummy) 419 { 420 return xdr_ressize_check(rqstp, p); 421 } 422 423 int 424 nfssvc_encode_attrstat(struct svc_rqst *rqstp, __be32 *p, 425 struct nfsd_attrstat *resp) 426 { 427 p = encode_fattr(rqstp, p, &resp->fh, &resp->stat); 428 return xdr_ressize_check(rqstp, p); 429 } 430 431 int 432 nfssvc_encode_diropres(struct svc_rqst *rqstp, __be32 *p, 433 struct nfsd_diropres *resp) 434 { 435 p = encode_fh(p, &resp->fh); 436 p = encode_fattr(rqstp, p, &resp->fh, &resp->stat); 437 return xdr_ressize_check(rqstp, p); 438 } 439 440 int 441 nfssvc_encode_readlinkres(struct svc_rqst *rqstp, __be32 *p, 442 struct nfsd_readlinkres *resp) 443 { 444 *p++ = htonl(resp->len); 445 xdr_ressize_check(rqstp, p); 446 rqstp->rq_res.page_len = resp->len; 447 if (resp->len & 3) { 448 /* need to pad the tail */ 449 rqstp->rq_res.tail[0].iov_base = p; 450 *p = 0; 451 rqstp->rq_res.tail[0].iov_len = 4 - (resp->len&3); 452 } 453 return 1; 454 } 455 456 int 457 nfssvc_encode_readres(struct svc_rqst *rqstp, __be32 *p, 458 struct nfsd_readres *resp) 459 { 460 p = encode_fattr(rqstp, p, &resp->fh, &resp->stat); 461 *p++ = htonl(resp->count); 462 xdr_ressize_check(rqstp, p); 463 464 /* now update rqstp->rq_res to reflect data aswell */ 465 rqstp->rq_res.page_len = resp->count; 466 if (resp->count & 3) { 467 /* need to pad the tail */ 468 rqstp->rq_res.tail[0].iov_base = p; 469 *p = 0; 470 rqstp->rq_res.tail[0].iov_len = 4 - (resp->count&3); 471 } 472 return 1; 473 } 474 475 int 476 nfssvc_encode_readdirres(struct svc_rqst *rqstp, __be32 *p, 477 struct nfsd_readdirres *resp) 478 { 479 xdr_ressize_check(rqstp, p); 480 p = resp->buffer; 481 *p++ = 0; /* no more entries */ 482 *p++ = htonl((resp->common.err == nfserr_eof)); 483 rqstp->rq_res.page_len = (((unsigned long)p-1) & ~PAGE_MASK)+1; 484 485 return 1; 486 } 487 488 int 489 nfssvc_encode_statfsres(struct svc_rqst *rqstp, __be32 *p, 490 struct nfsd_statfsres *resp) 491 { 492 struct kstatfs *stat = &resp->stats; 493 494 *p++ = htonl(NFSSVC_MAXBLKSIZE_V2); /* max transfer size */ 495 *p++ = htonl(stat->f_bsize); 496 *p++ = htonl(stat->f_blocks); 497 *p++ = htonl(stat->f_bfree); 498 *p++ = htonl(stat->f_bavail); 499 return xdr_ressize_check(rqstp, p); 500 } 501 502 int 503 nfssvc_encode_entry(void *ccdv, const char *name, 504 int namlen, loff_t offset, u64 ino, unsigned int d_type) 505 { 506 struct readdir_cd *ccd = ccdv; 507 struct nfsd_readdirres *cd = container_of(ccd, struct nfsd_readdirres, common); 508 __be32 *p = cd->buffer; 509 int buflen, slen; 510 511 /* 512 dprintk("nfsd: entry(%.*s off %ld ino %ld)\n", 513 namlen, name, offset, ino); 514 */ 515 516 if (offset > ~((u32) 0)) { 517 cd->common.err = nfserr_fbig; 518 return -EINVAL; 519 } 520 if (cd->offset) 521 *cd->offset = htonl(offset); 522 if (namlen > NFS2_MAXNAMLEN) 523 namlen = NFS2_MAXNAMLEN;/* truncate filename */ 524 525 slen = XDR_QUADLEN(namlen); 526 if ((buflen = cd->buflen - slen - 4) < 0) { 527 cd->common.err = nfserr_toosmall; 528 return -EINVAL; 529 } 530 if (ino > ~((u32) 0)) { 531 cd->common.err = nfserr_fbig; 532 return -EINVAL; 533 } 534 *p++ = xdr_one; /* mark entry present */ 535 *p++ = htonl((u32) ino); /* file id */ 536 p = xdr_encode_array(p, name, namlen);/* name length & name */ 537 cd->offset = p; /* remember pointer */ 538 *p++ = htonl(~0U); /* offset of next entry */ 539 540 cd->buflen = buflen; 541 cd->buffer = p; 542 cd->common.err = nfs_ok; 543 return 0; 544 } 545 546 /* 547 * XDR release functions 548 */ 549 int 550 nfssvc_release_fhandle(struct svc_rqst *rqstp, __be32 *p, 551 struct nfsd_fhandle *resp) 552 { 553 fh_put(&resp->fh); 554 return 1; 555 } 556