4 * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de>
11 #define NFSDDBG_FACILITY NFSDDBG_XDR
14 * Mapping of S_IF* types to NFS file types
16 static u32 nfs_ftypes
[] = {
17 NFNON
, NFCHR
, NFCHR
, NFBAD
,
18 NFDIR
, NFBAD
, NFBLK
, NFBAD
,
19 NFREG
, NFBAD
, NFLNK
, NFBAD
,
20 NFSOCK
, NFBAD
, NFLNK
, NFBAD
,
25 * XDR functions for basic NFS types
28 decode_fh(__be32
*p
, struct svc_fh
*fhp
)
30 fh_init(fhp
, NFS_FHSIZE
);
31 memcpy(&fhp
->fh_handle
.fh_base
, p
, NFS_FHSIZE
);
32 fhp
->fh_handle
.fh_size
= NFS_FHSIZE
;
34 /* FIXME: Look up export pointer here and verify
35 * Sun Secure RPC if requested */
36 return p
+ (NFS_FHSIZE
>> 2);
39 /* Helper function for NFSv2 ACL code */
40 __be32
*nfs2svc_decode_fh(__be32
*p
, struct svc_fh
*fhp
)
42 return decode_fh(p
, fhp
);
46 encode_fh(__be32
*p
, struct svc_fh
*fhp
)
48 memcpy(p
, &fhp
->fh_handle
.fh_base
, NFS_FHSIZE
);
49 return p
+ (NFS_FHSIZE
>> 2);
53 * Decode a file name and make sure that the path contains
54 * no slashes or null bytes.
57 decode_filename(__be32
*p
, char **namp
, unsigned int *lenp
)
62 if ((p
= xdr_decode_string_inplace(p
, namp
, lenp
, NFS_MAXNAMLEN
)) != NULL
) {
63 for (i
= 0, name
= *namp
; i
< *lenp
; i
++, name
++) {
64 if (*name
== '\0' || *name
== '/')
73 decode_pathname(__be32
*p
, char **namp
, unsigned int *lenp
)
78 if ((p
= xdr_decode_string_inplace(p
, namp
, lenp
, NFS_MAXPATHLEN
)) != NULL
) {
79 for (i
= 0, name
= *namp
; i
< *lenp
; i
++, name
++) {
89 decode_sattr(__be32
*p
, struct iattr
*iap
)
95 /* Sun client bug compatibility check: some sun clients seem to
96 * put 0xffff in the mode field when they mean 0xffffffff.
97 * Quoting the 4.4BSD nfs server code: Nah nah nah nah na nah.
99 if ((tmp
= ntohl(*p
++)) != (u32
)-1 && tmp
!= 0xffff) {
100 iap
->ia_valid
|= ATTR_MODE
;
103 if ((tmp
= ntohl(*p
++)) != (u32
)-1) {
104 iap
->ia_uid
= make_kuid(&init_user_ns
, tmp
);
105 if (uid_valid(iap
->ia_uid
))
106 iap
->ia_valid
|= ATTR_UID
;
108 if ((tmp
= ntohl(*p
++)) != (u32
)-1) {
109 iap
->ia_gid
= make_kgid(&init_user_ns
, tmp
);
110 if (gid_valid(iap
->ia_gid
))
111 iap
->ia_valid
|= ATTR_GID
;
113 if ((tmp
= ntohl(*p
++)) != (u32
)-1) {
114 iap
->ia_valid
|= ATTR_SIZE
;
117 tmp
= ntohl(*p
++); tmp1
= ntohl(*p
++);
118 if (tmp
!= (u32
)-1 && tmp1
!= (u32
)-1) {
119 iap
->ia_valid
|= ATTR_ATIME
| ATTR_ATIME_SET
;
120 iap
->ia_atime
.tv_sec
= tmp
;
121 iap
->ia_atime
.tv_nsec
= tmp1
* 1000;
123 tmp
= ntohl(*p
++); tmp1
= ntohl(*p
++);
124 if (tmp
!= (u32
)-1 && tmp1
!= (u32
)-1) {
125 iap
->ia_valid
|= ATTR_MTIME
| ATTR_MTIME_SET
;
126 iap
->ia_mtime
.tv_sec
= tmp
;
127 iap
->ia_mtime
.tv_nsec
= tmp1
* 1000;
129 * Passing the invalid value useconds=1000000 for mtime
130 * is a Sun convention for "set both mtime and atime to
131 * current server time". It's needed to make permissions
132 * checks for the "touch" program across v2 mounts to
133 * Solaris and Irix boxes work correctly. See description of
134 * sattr in section 6.1 of "NFS Illustrated" by
135 * Brent Callaghan, Addison-Wesley, ISBN 0-201-32750-5
138 iap
->ia_valid
&= ~(ATTR_ATIME_SET
|ATTR_MTIME_SET
);
144 encode_fattr(struct svc_rqst
*rqstp
, __be32
*p
, struct svc_fh
*fhp
,
147 struct dentry
*dentry
= fhp
->fh_dentry
;
149 struct timespec time
;
152 type
= (stat
->mode
& S_IFMT
);
154 *p
++ = htonl(nfs_ftypes
[type
>> 12]);
155 *p
++ = htonl((u32
) stat
->mode
);
156 *p
++ = htonl((u32
) stat
->nlink
);
157 *p
++ = htonl((u32
) from_kuid(&init_user_ns
, stat
->uid
));
158 *p
++ = htonl((u32
) from_kgid(&init_user_ns
, stat
->gid
));
160 if (S_ISLNK(type
) && stat
->size
> NFS_MAXPATHLEN
) {
161 *p
++ = htonl(NFS_MAXPATHLEN
);
163 *p
++ = htonl((u32
) stat
->size
);
165 *p
++ = htonl((u32
) stat
->blksize
);
166 if (S_ISCHR(type
) || S_ISBLK(type
))
167 *p
++ = htonl(new_encode_dev(stat
->rdev
));
169 *p
++ = htonl(0xffffffff);
170 *p
++ = htonl((u32
) stat
->blocks
);
171 switch (fsid_source(fhp
)) {
174 *p
++ = htonl(new_encode_dev(stat
->dev
));
176 case FSIDSOURCE_FSID
:
177 *p
++ = htonl((u32
) fhp
->fh_export
->ex_fsid
);
179 case FSIDSOURCE_UUID
:
180 f
= ((u32
*)fhp
->fh_export
->ex_uuid
)[0];
181 f
^= ((u32
*)fhp
->fh_export
->ex_uuid
)[1];
182 f
^= ((u32
*)fhp
->fh_export
->ex_uuid
)[2];
183 f
^= ((u32
*)fhp
->fh_export
->ex_uuid
)[3];
187 *p
++ = htonl((u32
) stat
->ino
);
188 *p
++ = htonl((u32
) stat
->atime
.tv_sec
);
189 *p
++ = htonl(stat
->atime
.tv_nsec
? stat
->atime
.tv_nsec
/ 1000 : 0);
190 lease_get_mtime(d_inode(dentry
), &time
);
191 *p
++ = htonl((u32
) time
.tv_sec
);
192 *p
++ = htonl(time
.tv_nsec
? time
.tv_nsec
/ 1000 : 0);
193 *p
++ = htonl((u32
) stat
->ctime
.tv_sec
);
194 *p
++ = htonl(stat
->ctime
.tv_nsec
? stat
->ctime
.tv_nsec
/ 1000 : 0);
199 /* Helper function for NFSv2 ACL code */
200 __be32
*nfs2svc_encode_fattr(struct svc_rqst
*rqstp
, __be32
*p
, struct svc_fh
*fhp
, struct kstat
*stat
)
202 return encode_fattr(rqstp
, p
, fhp
, stat
);
206 * XDR decode functions
209 nfssvc_decode_void(struct svc_rqst
*rqstp
, __be32
*p
, void *dummy
)
211 return xdr_argsize_check(rqstp
, p
);
215 nfssvc_decode_fhandle(struct svc_rqst
*rqstp
, __be32
*p
, struct nfsd_fhandle
*args
)
217 p
= decode_fh(p
, &args
->fh
);
220 return xdr_argsize_check(rqstp
, p
);
224 nfssvc_decode_sattrargs(struct svc_rqst
*rqstp
, __be32
*p
,
225 struct nfsd_sattrargs
*args
)
227 p
= decode_fh(p
, &args
->fh
);
230 p
= decode_sattr(p
, &args
->attrs
);
232 return xdr_argsize_check(rqstp
, p
);
236 nfssvc_decode_diropargs(struct svc_rqst
*rqstp
, __be32
*p
,
237 struct nfsd_diropargs
*args
)
239 if (!(p
= decode_fh(p
, &args
->fh
))
240 || !(p
= decode_filename(p
, &args
->name
, &args
->len
)))
243 return xdr_argsize_check(rqstp
, p
);
247 nfssvc_decode_readargs(struct svc_rqst
*rqstp
, __be32
*p
,
248 struct nfsd_readargs
*args
)
252 p
= decode_fh(p
, &args
->fh
);
256 args
->offset
= ntohl(*p
++);
257 len
= args
->count
= ntohl(*p
++);
258 p
++; /* totalcount - unused */
260 len
= min_t(unsigned int, len
, NFSSVC_MAXBLKSIZE_V2
);
262 /* set up somewhere to store response.
263 * We take pages, put them on reslist and include in iovec
267 struct page
*p
= *(rqstp
->rq_next_page
++);
269 rqstp
->rq_vec
[v
].iov_base
= page_address(p
);
270 rqstp
->rq_vec
[v
].iov_len
= min_t(unsigned int, len
, PAGE_SIZE
);
271 len
-= rqstp
->rq_vec
[v
].iov_len
;
275 return xdr_argsize_check(rqstp
, p
);
279 nfssvc_decode_writeargs(struct svc_rqst
*rqstp
, __be32
*p
,
280 struct nfsd_writeargs
*args
)
282 unsigned int len
, hdr
, dlen
;
283 struct kvec
*head
= rqstp
->rq_arg
.head
;
286 p
= decode_fh(p
, &args
->fh
);
290 p
++; /* beginoffset */
291 args
->offset
= ntohl(*p
++); /* offset */
292 p
++; /* totalcount */
293 len
= args
->len
= ntohl(*p
++);
295 * The protocol specifies a maximum of 8192 bytes.
297 if (len
> NFSSVC_MAXBLKSIZE_V2
)
301 * Check to make sure that we got the right number of
304 hdr
= (void*)p
- head
->iov_base
;
305 if (hdr
> head
->iov_len
)
307 dlen
= head
->iov_len
+ rqstp
->rq_arg
.page_len
- hdr
;
310 * Round the length of the data which was specified up to
311 * the next multiple of XDR units and then compare that
312 * against the length which was actually received.
313 * Note that when RPCSEC/GSS (for example) is used, the
314 * data buffer can be padded so dlen might be larger
315 * than required. It must never be smaller.
317 if (dlen
< XDR_QUADLEN(len
)*4)
320 rqstp
->rq_vec
[0].iov_base
= (void*)p
;
321 rqstp
->rq_vec
[0].iov_len
= head
->iov_len
- hdr
;
323 while (len
> rqstp
->rq_vec
[v
].iov_len
) {
324 len
-= rqstp
->rq_vec
[v
].iov_len
;
326 rqstp
->rq_vec
[v
].iov_base
= page_address(rqstp
->rq_pages
[v
]);
327 rqstp
->rq_vec
[v
].iov_len
= PAGE_SIZE
;
329 rqstp
->rq_vec
[v
].iov_len
= len
;
335 nfssvc_decode_createargs(struct svc_rqst
*rqstp
, __be32
*p
,
336 struct nfsd_createargs
*args
)
338 if ( !(p
= decode_fh(p
, &args
->fh
))
339 || !(p
= decode_filename(p
, &args
->name
, &args
->len
)))
341 p
= decode_sattr(p
, &args
->attrs
);
343 return xdr_argsize_check(rqstp
, p
);
347 nfssvc_decode_renameargs(struct svc_rqst
*rqstp
, __be32
*p
,
348 struct nfsd_renameargs
*args
)
350 if (!(p
= decode_fh(p
, &args
->ffh
))
351 || !(p
= decode_filename(p
, &args
->fname
, &args
->flen
))
352 || !(p
= decode_fh(p
, &args
->tfh
))
353 || !(p
= decode_filename(p
, &args
->tname
, &args
->tlen
)))
356 return xdr_argsize_check(rqstp
, p
);
360 nfssvc_decode_readlinkargs(struct svc_rqst
*rqstp
, __be32
*p
, struct nfsd_readlinkargs
*args
)
362 p
= decode_fh(p
, &args
->fh
);
365 args
->buffer
= page_address(*(rqstp
->rq_next_page
++));
367 return xdr_argsize_check(rqstp
, p
);
371 nfssvc_decode_linkargs(struct svc_rqst
*rqstp
, __be32
*p
,
372 struct nfsd_linkargs
*args
)
374 if (!(p
= decode_fh(p
, &args
->ffh
))
375 || !(p
= decode_fh(p
, &args
->tfh
))
376 || !(p
= decode_filename(p
, &args
->tname
, &args
->tlen
)))
379 return xdr_argsize_check(rqstp
, p
);
383 nfssvc_decode_symlinkargs(struct svc_rqst
*rqstp
, __be32
*p
,
384 struct nfsd_symlinkargs
*args
)
386 if ( !(p
= decode_fh(p
, &args
->ffh
))
387 || !(p
= decode_filename(p
, &args
->fname
, &args
->flen
))
388 || !(p
= decode_pathname(p
, &args
->tname
, &args
->tlen
)))
390 p
= decode_sattr(p
, &args
->attrs
);
392 return xdr_argsize_check(rqstp
, p
);
396 nfssvc_decode_readdirargs(struct svc_rqst
*rqstp
, __be32
*p
,
397 struct nfsd_readdirargs
*args
)
399 p
= decode_fh(p
, &args
->fh
);
402 args
->cookie
= ntohl(*p
++);
403 args
->count
= ntohl(*p
++);
404 args
->count
= min_t(u32
, args
->count
, PAGE_SIZE
);
405 args
->buffer
= page_address(*(rqstp
->rq_next_page
++));
407 return xdr_argsize_check(rqstp
, p
);
411 * XDR encode functions
414 nfssvc_encode_void(struct svc_rqst
*rqstp
, __be32
*p
, void *dummy
)
416 return xdr_ressize_check(rqstp
, p
);
420 nfssvc_encode_attrstat(struct svc_rqst
*rqstp
, __be32
*p
,
421 struct nfsd_attrstat
*resp
)
423 p
= encode_fattr(rqstp
, p
, &resp
->fh
, &resp
->stat
);
424 return xdr_ressize_check(rqstp
, p
);
428 nfssvc_encode_diropres(struct svc_rqst
*rqstp
, __be32
*p
,
429 struct nfsd_diropres
*resp
)
431 p
= encode_fh(p
, &resp
->fh
);
432 p
= encode_fattr(rqstp
, p
, &resp
->fh
, &resp
->stat
);
433 return xdr_ressize_check(rqstp
, p
);
437 nfssvc_encode_readlinkres(struct svc_rqst
*rqstp
, __be32
*p
,
438 struct nfsd_readlinkres
*resp
)
440 *p
++ = htonl(resp
->len
);
441 xdr_ressize_check(rqstp
, p
);
442 rqstp
->rq_res
.page_len
= resp
->len
;
444 /* need to pad the tail */
445 rqstp
->rq_res
.tail
[0].iov_base
= p
;
447 rqstp
->rq_res
.tail
[0].iov_len
= 4 - (resp
->len
&3);
453 nfssvc_encode_readres(struct svc_rqst
*rqstp
, __be32
*p
,
454 struct nfsd_readres
*resp
)
456 p
= encode_fattr(rqstp
, p
, &resp
->fh
, &resp
->stat
);
457 *p
++ = htonl(resp
->count
);
458 xdr_ressize_check(rqstp
, p
);
460 /* now update rqstp->rq_res to reflect data as well */
461 rqstp
->rq_res
.page_len
= resp
->count
;
462 if (resp
->count
& 3) {
463 /* need to pad the tail */
464 rqstp
->rq_res
.tail
[0].iov_base
= p
;
466 rqstp
->rq_res
.tail
[0].iov_len
= 4 - (resp
->count
&3);
472 nfssvc_encode_readdirres(struct svc_rqst
*rqstp
, __be32
*p
,
473 struct nfsd_readdirres
*resp
)
475 xdr_ressize_check(rqstp
, p
);
477 *p
++ = 0; /* no more entries */
478 *p
++ = htonl((resp
->common
.err
== nfserr_eof
));
479 rqstp
->rq_res
.page_len
= (((unsigned long)p
-1) & ~PAGE_MASK
)+1;
485 nfssvc_encode_statfsres(struct svc_rqst
*rqstp
, __be32
*p
,
486 struct nfsd_statfsres
*resp
)
488 struct kstatfs
*stat
= &resp
->stats
;
490 *p
++ = htonl(NFSSVC_MAXBLKSIZE_V2
); /* max transfer size */
491 *p
++ = htonl(stat
->f_bsize
);
492 *p
++ = htonl(stat
->f_blocks
);
493 *p
++ = htonl(stat
->f_bfree
);
494 *p
++ = htonl(stat
->f_bavail
);
495 return xdr_ressize_check(rqstp
, p
);
499 nfssvc_encode_entry(void *ccdv
, const char *name
,
500 int namlen
, loff_t offset
, u64 ino
, unsigned int d_type
)
502 struct readdir_cd
*ccd
= ccdv
;
503 struct nfsd_readdirres
*cd
= container_of(ccd
, struct nfsd_readdirres
, common
);
504 __be32
*p
= cd
->buffer
;
508 dprintk("nfsd: entry(%.*s off %ld ino %ld)\n",
509 namlen, name, offset, ino);
512 if (offset
> ~((u32
) 0)) {
513 cd
->common
.err
= nfserr_fbig
;
517 *cd
->offset
= htonl(offset
);
519 /* truncate filename */
520 namlen
= min(namlen
, NFS2_MAXNAMLEN
);
521 slen
= XDR_QUADLEN(namlen
);
523 if ((buflen
= cd
->buflen
- slen
- 4) < 0) {
524 cd
->common
.err
= nfserr_toosmall
;
527 if (ino
> ~((u32
) 0)) {
528 cd
->common
.err
= nfserr_fbig
;
531 *p
++ = xdr_one
; /* mark entry present */
532 *p
++ = htonl((u32
) ino
); /* file id */
533 p
= xdr_encode_array(p
, name
, namlen
);/* name length & name */
534 cd
->offset
= p
; /* remember pointer */
535 *p
++ = htonl(~0U); /* offset of next entry */
539 cd
->common
.err
= nfs_ok
;
544 * XDR release functions
547 nfssvc_release_fhandle(struct svc_rqst
*rqstp
, __be32
*p
,
548 struct nfsd_fhandle
*resp
)