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
, NFFIFO
, 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(p
, namp
, lenp
, NFS_MAXNAMLEN
)) != NULL
) {
69 for (i
= 0, name
= *namp
; i
< *lenp
; i
++, name
++) {
70 if (*name
== '\0' || *name
== '/')
80 decode_pathname(u32
*p
, char **namp
, int *lenp
)
85 if ((p
= xdr_decode_string(p
, namp
, lenp
, NFS_MAXPATHLEN
)) != NULL
) {
86 for (i
= 0, name
= *namp
; i
< *lenp
; i
++, name
++) {
97 decode_sattr(u32
*p
, struct iattr
*iap
)
103 /* Sun client bug compatibility check: some sun clients seem to
104 * put 0xffff in the mode field when they mean 0xffffffff.
105 * Quoting the 4.4BSD nfs server code: Nah nah nah nah na nah.
107 if ((tmp
= ntohl(*p
++)) != (u32
)-1 && tmp
!= 0xffff) {
108 iap
->ia_valid
|= ATTR_MODE
;
111 if ((tmp
= ntohl(*p
++)) != (u32
)-1) {
112 iap
->ia_valid
|= ATTR_UID
;
115 if ((tmp
= ntohl(*p
++)) != (u32
)-1) {
116 iap
->ia_valid
|= ATTR_GID
;
119 if ((tmp
= ntohl(*p
++)) != (u32
)-1) {
120 iap
->ia_valid
|= ATTR_SIZE
;
123 tmp
= ntohl(*p
++); tmp1
= ntohl(*p
++);
124 if (tmp
!= (u32
)-1 && tmp1
!= (u32
)-1) {
125 iap
->ia_valid
|= ATTR_ATIME
| ATTR_ATIME_SET
;
128 tmp
= ntohl(*p
++); tmp1
= ntohl(*p
++);
129 if (tmp
!= (u32
)-1 && tmp1
!= (u32
)-1) {
130 iap
->ia_valid
|= ATTR_MTIME
| ATTR_MTIME_SET
;
137 encode_fattr(struct svc_rqst
*rqstp
, u32
*p
, struct inode
*inode
)
141 *p
++ = htonl(nfs_ftypes
[(inode
->i_mode
& S_IFMT
) >> 12]);
142 *p
++ = htonl((u32
) inode
->i_mode
);
143 *p
++ = htonl((u32
) inode
->i_nlink
);
144 *p
++ = htonl((u32
) nfsd_ruid(rqstp
, inode
->i_uid
));
145 *p
++ = htonl((u32
) nfsd_rgid(rqstp
, inode
->i_gid
));
146 if (S_ISLNK(inode
->i_mode
) && 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 *p
++ = htonl((u32
) inode
->i_rdev
);
153 *p
++ = htonl((u32
) inode
->i_blocks
);
154 *p
++ = htonl((u32
) inode
->i_dev
);
155 *p
++ = htonl((u32
) inode
->i_ino
);
156 *p
++ = htonl((u32
) inode
->i_atime
);
158 *p
++ = htonl((u32
) inode
->i_mtime
);
160 *p
++ = htonl((u32
) inode
->i_ctime
);
167 * Check buffer bounds after decoding arguments
170 xdr_argsize_check(struct svc_rqst
*rqstp
, u32
*p
)
172 struct svc_buf
*buf
= &rqstp
->rq_argbuf
;
174 return p
- buf
->base
<= buf
->buflen
;
178 xdr_ressize_check(struct svc_rqst
*rqstp
, u32
*p
)
180 struct svc_buf
*buf
= &rqstp
->rq_resbuf
;
182 buf
->len
= p
- buf
->base
;
183 dprintk("nfsd: ressize_check p %p base %p len %d\n",
184 p
, buf
->base
, buf
->buflen
);
185 return (buf
->len
<= buf
->buflen
);
189 * XDR decode functions
192 nfssvc_decode_void(struct svc_rqst
*rqstp
, u32
*p
, void *dummy
)
194 return xdr_argsize_check(rqstp
, p
);
198 nfssvc_decode_fhandle(struct svc_rqst
*rqstp
, u32
*p
, struct svc_fh
*fhp
)
200 if (!(p
= decode_fh(p
, fhp
)))
202 return xdr_argsize_check(rqstp
, p
);
206 nfssvc_decode_sattrargs(struct svc_rqst
*rqstp
, u32
*p
,
207 struct nfsd_sattrargs
*args
)
209 if (!(p
= decode_fh(p
, &args
->fh
))
210 || !(p
= decode_sattr(p
, &args
->attrs
)))
213 return xdr_argsize_check(rqstp
, p
);
217 nfssvc_decode_diropargs(struct svc_rqst
*rqstp
, u32
*p
,
218 struct nfsd_diropargs
*args
)
220 if (!(p
= decode_fh(p
, &args
->fh
))
221 || !(p
= decode_filename(p
, &args
->name
, &args
->len
)))
224 return xdr_argsize_check(rqstp
, p
);
228 nfssvc_decode_readargs(struct svc_rqst
*rqstp
, u32
*p
,
229 struct nfsd_readargs
*args
)
231 if (!(p
= decode_fh(p
, &args
->fh
)))
234 args
->offset
= ntohl(*p
++);
235 args
->count
= ntohl(*p
++);
236 args
->totalsize
= ntohl(*p
++);
238 return xdr_argsize_check(rqstp
, p
);
242 nfssvc_decode_writeargs(struct svc_rqst
*rqstp
, u32
*p
,
243 struct nfsd_writeargs
*args
)
245 if (!(p
= decode_fh(p
, &args
->fh
)))
248 p
++; /* beginoffset */
249 args
->offset
= ntohl(*p
++); /* offset */
250 p
++; /* totalcount */
251 args
->len
= ntohl(*p
++);
252 args
->data
= (char *) p
;
253 p
+= XDR_QUADLEN(args
->len
);
255 return xdr_argsize_check(rqstp
, p
);
259 nfssvc_decode_createargs(struct svc_rqst
*rqstp
, u32
*p
,
260 struct nfsd_createargs
*args
)
262 if (!(p
= decode_fh(p
, &args
->fh
))
263 || !(p
= decode_filename(p
, &args
->name
, &args
->len
))
264 || !(p
= decode_sattr(p
, &args
->attrs
)))
267 return xdr_argsize_check(rqstp
, p
);
271 nfssvc_decode_renameargs(struct svc_rqst
*rqstp
, u32
*p
,
272 struct nfsd_renameargs
*args
)
274 if (!(p
= decode_fh(p
, &args
->ffh
))
275 || !(p
= decode_filename(p
, &args
->fname
, &args
->flen
))
276 || !(p
= decode_fh(p
, &args
->tfh
))
277 || !(p
= decode_filename(p
, &args
->tname
, &args
->tlen
)))
280 return xdr_argsize_check(rqstp
, p
);
284 nfssvc_decode_linkargs(struct svc_rqst
*rqstp
, u32
*p
,
285 struct nfsd_linkargs
*args
)
287 if (!(p
= decode_fh(p
, &args
->ffh
))
288 || !(p
= decode_fh(p
, &args
->tfh
))
289 || !(p
= decode_filename(p
, &args
->tname
, &args
->tlen
)))
292 return xdr_argsize_check(rqstp
, p
);
296 nfssvc_decode_symlinkargs(struct svc_rqst
*rqstp
, u32
*p
,
297 struct nfsd_symlinkargs
*args
)
299 if (!(p
= decode_fh(p
, &args
->ffh
))
300 || !(p
= decode_filename(p
, &args
->fname
, &args
->flen
))
301 || !(p
= decode_pathname(p
, &args
->tname
, &args
->tlen
))
302 || !(p
= decode_sattr(p
, &args
->attrs
)))
305 return xdr_argsize_check(rqstp
, p
);
309 nfssvc_decode_readdirargs(struct svc_rqst
*rqstp
, u32
*p
,
310 struct nfsd_readdirargs
*args
)
312 if (!(p
= decode_fh(p
, &args
->fh
)))
314 args
->cookie
= ntohl(*p
++);
315 args
->count
= ntohl(*p
++);
317 return xdr_argsize_check(rqstp
, p
);
321 * XDR encode functions
324 nfssvc_encode_void(struct svc_rqst
*rqstp
, u32
*p
, void *dummy
)
326 return xdr_ressize_check(rqstp
, p
);
330 nfssvc_encode_attrstat(struct svc_rqst
*rqstp
, u32
*p
,
331 struct nfsd_attrstat
*resp
)
333 if (!(p
= encode_fattr(rqstp
, p
, resp
->fh
.fh_dentry
->d_inode
)))
335 return xdr_ressize_check(rqstp
, p
);
339 nfssvc_encode_diropres(struct svc_rqst
*rqstp
, u32
*p
,
340 struct nfsd_diropres
*resp
)
342 if (!(p
= encode_fh(p
, &resp
->fh
))
343 || !(p
= encode_fattr(rqstp
, p
, resp
->fh
.fh_dentry
->d_inode
)))
345 return xdr_ressize_check(rqstp
, p
);
349 nfssvc_encode_readlinkres(struct svc_rqst
*rqstp
, u32
*p
,
350 struct nfsd_readlinkres
*resp
)
352 *p
++ = htonl(resp
->len
);
353 p
+= XDR_QUADLEN(resp
->len
);
354 return xdr_ressize_check(rqstp
, p
);
358 nfssvc_encode_readres(struct svc_rqst
*rqstp
, u32
*p
,
359 struct nfsd_readres
*resp
)
361 if (!(p
= encode_fattr(rqstp
, p
, resp
->fh
.fh_dentry
->d_inode
)))
363 *p
++ = htonl(resp
->count
);
364 p
+= XDR_QUADLEN(resp
->count
);
366 return xdr_ressize_check(rqstp
, p
);
370 nfssvc_encode_readdirres(struct svc_rqst
*rqstp
, u32
*p
,
371 struct nfsd_readdirres
*resp
)
373 p
+= XDR_QUADLEN(resp
->count
);
374 return xdr_ressize_check(rqstp
, p
);
378 nfssvc_encode_statfsres(struct svc_rqst
*rqstp
, u32
*p
,
379 struct nfsd_statfsres
*resp
)
381 struct statfs
*stat
= &resp
->stats
;
383 *p
++ = htonl(8 * 1024); /* max transfer size */
384 *p
++ = htonl(stat
->f_bsize
);
385 *p
++ = htonl(stat
->f_blocks
);
386 *p
++ = htonl(stat
->f_bfree
);
387 *p
++ = htonl(stat
->f_bavail
);
388 return xdr_ressize_check(rqstp
, p
);
392 nfssvc_encode_entry(struct readdir_cd
*cd
, const char *name
,
393 int namlen
, off_t offset
, ino_t ino
)
399 dprintk("nfsd: entry(%.*s off %ld ino %ld)\n",
400 namlen, name, offset, ino);
403 if (offset
> ~((u32
) 0))
406 *cd
->offset
= htonl(offset
);
407 if (namlen
> NFS2_MAXNAMLEN
)
408 namlen
= NFS2_MAXNAMLEN
;/* truncate filename */
410 slen
= XDR_QUADLEN(namlen
);
411 if ((buflen
= cd
->buflen
- slen
- 4) < 0) {
415 *p
++ = xdr_one
; /* mark entry present */
416 *p
++ = htonl((u32
) ino
); /* file id */
417 p
= xdr_encode_array(p
, name
, namlen
);/* name length & name */
418 cd
->offset
= p
; /* remember pointer */
419 *p
++ = ~(u32
) 0; /* offset of next entry */
427 * XDR release functions
430 nfssvc_release_fhandle(struct svc_rqst
*rqstp
, u32
*p
,
431 struct nfsd_fhandle
*resp
)