6 * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de>
9 #include <linux/types.h>
10 #include <linux/sched.h>
11 #include <linux/nfs.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>
18 #define NFSDDBG_FACILITY NFSDDBG_XDR
21 #ifdef NFSD_OPTIMIZE_SPACE
26 * Mapping of S_IF* types to NFS file types
28 static u32 nfs_ftypes[] = {
29 NFNON, NFCHR, NFCHR, NFBAD,
30 NFDIR, NFBAD, NFBLK, NFBAD,
31 NFREG, NFBAD, NFLNK, NFBAD,
32 NFSOCK, NFBAD, NFLNK, NFBAD,
37 * XDR functions for basic NFS types
40 decode_fh(u32 *p, struct svc_fh *fhp)
42 fh_init(fhp, NFS_FHSIZE);
43 memcpy(&fhp->fh_handle.fh_base, p, NFS_FHSIZE);
44 fhp->fh_handle.fh_size = NFS_FHSIZE;
46 /* FIXME: Look up export pointer here and verify
47 * Sun Secure RPC if requested */
48 return p + (NFS_FHSIZE >> 2);
52 encode_fh(u32 *p, struct svc_fh *fhp)
54 memcpy(p, &fhp->fh_handle.fh_base, NFS_FHSIZE);
55 return p + (NFS_FHSIZE>> 2);
59 * Decode a file name and make sure that the path contains
60 * no slashes or null bytes.
63 decode_filename(u32 *p, char **namp, int *lenp)
68 if ((p = xdr_decode_string_inplace(p, namp, lenp, NFS_MAXNAMLEN)) != NULL) {
69 for (i = 0, name = *namp; i < *lenp; i++, name++) {
70 if (*name == '\0' || *name == '/')
79 decode_pathname(u32 *p, char **namp, int *lenp)
84 if ((p = xdr_decode_string(p, namp, lenp, NFS_MAXPATHLEN)) != NULL) {
85 for (i = 0, name = *namp; i < *lenp; i++, name++) {
95 decode_sattr(u32 *p, struct iattr *iap)
101 /* Sun client bug compatibility check: some sun clients seem to
102 * put 0xffff in the mode field when they mean 0xffffffff.
103 * Quoting the 4.4BSD nfs server code: Nah nah nah nah na nah.
105 if ((tmp = ntohl(*p++)) != (u32)-1 && tmp != 0xffff) {
106 iap->ia_valid |= ATTR_MODE;
109 if ((tmp = ntohl(*p++)) != (u32)-1) {
110 iap->ia_valid |= ATTR_UID;
113 if ((tmp = ntohl(*p++)) != (u32)-1) {
114 iap->ia_valid |= ATTR_GID;
117 if ((tmp = ntohl(*p++)) != (u32)-1) {
118 iap->ia_valid |= ATTR_SIZE;
121 tmp = ntohl(*p++); tmp1 = ntohl(*p++);
122 if (tmp != (u32)-1 && tmp1 != (u32)-1) {
123 iap->ia_valid |= ATTR_ATIME | ATTR_ATIME_SET;
126 tmp = ntohl(*p++); tmp1 = ntohl(*p++);
127 if (tmp != (u32)-1 && tmp1 != (u32)-1) {
128 iap->ia_valid |= ATTR_MTIME | ATTR_MTIME_SET;
135 encode_fattr(struct svc_rqst *rqstp, u32 *p, struct svc_fh *fhp)
137 struct inode *inode = fhp->fh_dentry->d_inode;
138 int type = (inode->i_mode & S_IFMT);
140 *p++ = htonl(nfs_ftypes[type >> 12]);
141 *p++ = htonl((u32) inode->i_mode);
142 *p++ = htonl((u32) inode->i_nlink);
143 *p++ = htonl((u32) nfsd_ruid(rqstp, inode->i_uid));
144 *p++ = htonl((u32) nfsd_rgid(rqstp, inode->i_gid));
146 if (S_ISLNK(type) && inode->i_size > NFS_MAXPATHLEN) {
147 *p++ = htonl(NFS_MAXPATHLEN);
149 *p++ = htonl((u32) inode->i_size);
151 *p++ = htonl((u32) inode->i_blksize);
152 if (S_ISCHR(type) || S_ISBLK(type))
153 *p++ = htonl((u32) inode->i_rdev);
155 *p++ = htonl(0xffffffff);
156 *p++ = htonl((u32) inode->i_blocks);
157 if (rqstp->rq_reffh->fh_version == 1
158 && rqstp->rq_reffh->fh_fsid_type == 1
159 && (fhp->fh_export->ex_flags & NFSEXP_FSID))
160 *p++ = htonl((u32) fhp->fh_export->ex_fsid);
162 *p++ = htonl((u32) inode->i_dev);
163 *p++ = htonl((u32) inode->i_ino);
164 *p++ = htonl((u32) inode->i_atime);
166 *p++ = htonl((u32) lease_get_mtime(inode));
168 *p++ = htonl((u32) inode->i_ctime);
175 * Check buffer bounds after decoding arguments
178 xdr_argsize_check(struct svc_rqst *rqstp, u32 *p)
180 struct svc_buf *buf = &rqstp->rq_argbuf;
182 return p - buf->base <= buf->buflen;
186 xdr_ressize_check(struct svc_rqst *rqstp, u32 *p)
188 struct svc_buf *buf = &rqstp->rq_resbuf;
190 buf->len = p - buf->base;
191 dprintk("nfsd: ressize_check p %p base %p len %d\n",
192 p, buf->base, buf->buflen);
193 return (buf->len <= buf->buflen);
197 * XDR decode functions
200 nfssvc_decode_void(struct svc_rqst *rqstp, u32 *p, void *dummy)
202 return xdr_argsize_check(rqstp, p);
206 nfssvc_decode_fhandle(struct svc_rqst *rqstp, u32 *p, struct svc_fh *fhp)
208 if (!(p = decode_fh(p, fhp)))
210 return xdr_argsize_check(rqstp, p);
214 nfssvc_decode_sattrargs(struct svc_rqst *rqstp, u32 *p,
215 struct nfsd_sattrargs *args)
217 if (!(p = decode_fh(p, &args->fh))
218 || !(p = decode_sattr(p, &args->attrs)))
221 return xdr_argsize_check(rqstp, p);
225 nfssvc_decode_diropargs(struct svc_rqst *rqstp, u32 *p,
226 struct nfsd_diropargs *args)
228 if (!(p = decode_fh(p, &args->fh))
229 || !(p = decode_filename(p, &args->name, &args->len)))
232 return xdr_argsize_check(rqstp, p);
236 nfssvc_decode_readargs(struct svc_rqst *rqstp, u32 *p,
237 struct nfsd_readargs *args)
239 if (!(p = decode_fh(p, &args->fh)))
242 args->offset = ntohl(*p++);
243 args->count = ntohl(*p++);
244 args->totalsize = ntohl(*p++);
246 return xdr_argsize_check(rqstp, p);
250 nfssvc_decode_writeargs(struct svc_rqst *rqstp, u32 *p,
251 struct nfsd_writeargs *args)
253 if (!(p = decode_fh(p, &args->fh)))
256 p++; /* beginoffset */
257 args->offset = ntohl(*p++); /* offset */
258 p++; /* totalcount */
259 args->len = ntohl(*p++);
260 args->data = (char *) p;
261 p += XDR_QUADLEN(args->len);
263 return xdr_argsize_check(rqstp, p);
267 nfssvc_decode_createargs(struct svc_rqst *rqstp, u32 *p,
268 struct nfsd_createargs *args)
270 if (!(p = decode_fh(p, &args->fh))
271 || !(p = decode_filename(p, &args->name, &args->len))
272 || !(p = decode_sattr(p, &args->attrs)))
275 return xdr_argsize_check(rqstp, p);
279 nfssvc_decode_renameargs(struct svc_rqst *rqstp, u32 *p,
280 struct nfsd_renameargs *args)
282 if (!(p = decode_fh(p, &args->ffh))
283 || !(p = decode_filename(p, &args->fname, &args->flen))
284 || !(p = decode_fh(p, &args->tfh))
285 || !(p = decode_filename(p, &args->tname, &args->tlen)))
288 return xdr_argsize_check(rqstp, p);
292 nfssvc_decode_linkargs(struct svc_rqst *rqstp, u32 *p,
293 struct nfsd_linkargs *args)
295 if (!(p = decode_fh(p, &args->ffh))
296 || !(p = decode_fh(p, &args->tfh))
297 || !(p = decode_filename(p, &args->tname, &args->tlen)))
300 return xdr_argsize_check(rqstp, p);
304 nfssvc_decode_symlinkargs(struct svc_rqst *rqstp, u32 *p,
305 struct nfsd_symlinkargs *args)
307 if (!(p = decode_fh(p, &args->ffh))
308 || !(p = decode_filename(p, &args->fname, &args->flen))
309 || !(p = decode_pathname(p, &args->tname, &args->tlen))
310 || !(p = decode_sattr(p, &args->attrs)))
313 return xdr_argsize_check(rqstp, p);
317 nfssvc_decode_readdirargs(struct svc_rqst *rqstp, u32 *p,
318 struct nfsd_readdirargs *args)
320 if (!(p = decode_fh(p, &args->fh)))
322 args->cookie = ntohl(*p++);
323 args->count = ntohl(*p++);
325 return xdr_argsize_check(rqstp, p);
329 * XDR encode functions
332 nfssvc_encode_void(struct svc_rqst *rqstp, u32 *p, void *dummy)
334 return xdr_ressize_check(rqstp, p);
338 nfssvc_encode_attrstat(struct svc_rqst *rqstp, u32 *p,
339 struct nfsd_attrstat *resp)
341 p = encode_fattr(rqstp, p, &resp->fh);
342 return xdr_ressize_check(rqstp, p);
346 nfssvc_encode_diropres(struct svc_rqst *rqstp, u32 *p,
347 struct nfsd_diropres *resp)
349 p = encode_fh(p, &resp->fh);
350 p = encode_fattr(rqstp, p, &resp->fh);
351 return xdr_ressize_check(rqstp, p);
355 nfssvc_encode_readlinkres(struct svc_rqst *rqstp, u32 *p,
356 struct nfsd_readlinkres *resp)
358 *p++ = htonl(resp->len);
359 p += XDR_QUADLEN(resp->len);
360 return xdr_ressize_check(rqstp, p);
364 nfssvc_encode_readres(struct svc_rqst *rqstp, u32 *p,
365 struct nfsd_readres *resp)
367 p = encode_fattr(rqstp, p, &resp->fh);
368 *p++ = htonl(resp->count);
369 p += XDR_QUADLEN(resp->count);
371 return xdr_ressize_check(rqstp, p);
375 nfssvc_encode_readdirres(struct svc_rqst *rqstp, u32 *p,
376 struct nfsd_readdirres *resp)
378 p += XDR_QUADLEN(resp->count);
379 return xdr_ressize_check(rqstp, p);
383 nfssvc_encode_statfsres(struct svc_rqst *rqstp, u32 *p,
384 struct nfsd_statfsres *resp)
386 struct statfs *stat = &resp->stats;
388 *p++ = htonl(NFSSVC_MAXBLKSIZE); /* max transfer size */
389 *p++ = htonl(stat->f_bsize);
390 *p++ = htonl(stat->f_blocks);
391 *p++ = htonl(stat->f_bfree);
392 *p++ = htonl(stat->f_bavail);
393 return xdr_ressize_check(rqstp, p);
397 nfssvc_encode_entry(struct readdir_cd *cd, const char *name,
398 int namlen, loff_t offset, ino_t ino, unsigned int d_type)
404 dprintk("nfsd: entry(%.*s off %ld ino %ld)\n",
405 namlen, name, offset, ino);
408 if (offset > ~((u32) 0))
411 *cd->offset = htonl(offset);
412 if (namlen > NFS2_MAXNAMLEN)
413 namlen = NFS2_MAXNAMLEN;/* truncate filename */
415 slen = XDR_QUADLEN(namlen);
416 if ((buflen = cd->buflen - slen - 4) < 0) {
420 *p++ = xdr_one; /* mark entry present */
421 *p++ = htonl((u32) ino); /* file id */
422 p = xdr_encode_array(p, name, namlen);/* name length & name */
423 cd->offset = p; /* remember pointer */
424 *p++ = ~(u32) 0; /* offset of next entry */
432 * XDR release functions
435 nfssvc_release_fhandle(struct svc_rqst *rqstp, u32 *p,
436 struct nfsd_fhandle *resp)