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