~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Linux Cross Reference
Linux/fs/nfsd/nfsxdr.c

Version: ~ [ 2.4.0 ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /*
  2  * linux/fs/nfsd/xdr.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/sched.h>
 11 #include <linux/nfs.h>
 12 
 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 
 18 #define NFSDDBG_FACILITY                NFSDDBG_XDR
 19 
 20 
 21 #ifdef NFSD_OPTIMIZE_SPACE
 22 # define inline
 23 #endif
 24 
 25 /*
 26  * Mapping of S_IF* types to NFS file types
 27  */
 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,
 33 };
 34 
 35 
 36 /*
 37  * XDR functions for basic NFS types
 38  */
 39 static inline u32 *
 40 decode_fh(u32 *p, struct svc_fh *fhp)
 41 {
 42         fh_init(fhp, NFS_FHSIZE);
 43         memcpy(&fhp->fh_handle.fh_base, p, NFS_FHSIZE);
 44         fhp->fh_handle.fh_size = NFS_FHSIZE;
 45 
 46         /* FIXME: Look up export pointer here and verify
 47          * Sun Secure RPC if requested */
 48         return p + (NFS_FHSIZE >> 2);
 49 }
 50 
 51 static inline u32 *
 52 encode_fh(u32 *p, struct svc_fh *fhp)
 53 {
 54         memcpy(p, &fhp->fh_handle.fh_base, NFS_FHSIZE);
 55         return p + (NFS_FHSIZE>> 2);
 56 }
 57 
 58 /*
 59  * Decode a file name and make sure that the path contains
 60  * no slashes or null bytes.
 61  */
 62 static inline u32 *
 63 decode_filename(u32 *p, char **namp, int *lenp)
 64 {
 65         char            *name;
 66         int             i;
 67 
 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 == '/')
 71                                 return NULL;
 72                 }
 73                 *name = '\0';
 74         }
 75 
 76         return p;
 77 }
 78 
 79 static inline u32 *
 80 decode_pathname(u32 *p, char **namp, int *lenp)
 81 {
 82         char            *name;
 83         int             i;
 84 
 85         if ((p = xdr_decode_string(p, namp, lenp, NFS_MAXPATHLEN)) != NULL) {
 86                 for (i = 0, name = *namp; i < *lenp; i++, name++) {
 87                         if (*name == '\0')
 88                                 return NULL;
 89                 }
 90                 *name = '\0';
 91         }
 92 
 93         return p;
 94 }
 95 
 96 static inline u32 *
 97 decode_sattr(u32 *p, struct iattr *iap)
 98 {
 99         u32     tmp, tmp1;
100 
101         iap->ia_valid = 0;
102 
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.
106          */
107         if ((tmp = ntohl(*p++)) != (u32)-1 && tmp != 0xffff) {
108                 iap->ia_valid |= ATTR_MODE;
109                 iap->ia_mode = tmp;
110         }
111         if ((tmp = ntohl(*p++)) != (u32)-1) {
112                 iap->ia_valid |= ATTR_UID;
113                 iap->ia_uid = tmp;
114         }
115         if ((tmp = ntohl(*p++)) != (u32)-1) {
116                 iap->ia_valid |= ATTR_GID;
117                 iap->ia_gid = tmp;
118         }
119         if ((tmp = ntohl(*p++)) != (u32)-1) {
120                 iap->ia_valid |= ATTR_SIZE;
121                 iap->ia_size = tmp;
122         }
123         tmp  = ntohl(*p++); tmp1 = ntohl(*p++);
124         if (tmp != (u32)-1 && tmp1 != (u32)-1) {
125                 iap->ia_valid |= ATTR_ATIME | ATTR_ATIME_SET;
126                 iap->ia_atime = tmp;
127         }
128         tmp  = ntohl(*p++); tmp1 = ntohl(*p++);
129         if (tmp != (u32)-1 && tmp1 != (u32)-1) {
130                 iap->ia_valid |= ATTR_MTIME | ATTR_MTIME_SET;
131                 iap->ia_mtime = tmp;
132         }
133         return p;
134 }
135 
136 static inline u32 *
137 encode_fattr(struct svc_rqst *rqstp, u32 *p, struct inode *inode)
138 {
139         if (!inode)
140                 return 0;
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);
148         } else {
149                 *p++ = htonl((u32) inode->i_size);
150         }
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);
157         *p++ = 0;
158         *p++ = htonl((u32) lease_get_mtime(inode));
159         *p++ = 0;
160         *p++ = htonl((u32) inode->i_ctime);
161         *p++ = 0;
162 
163         return p;
164 }
165 
166 /*
167  * Check buffer bounds after decoding arguments
168  */
169 static inline int
170 xdr_argsize_check(struct svc_rqst *rqstp, u32 *p)
171 {
172         struct svc_buf  *buf = &rqstp->rq_argbuf;
173 
174         return p - buf->base <= buf->buflen;
175 }
176 
177 static inline int
178 xdr_ressize_check(struct svc_rqst *rqstp, u32 *p)
179 {
180         struct svc_buf  *buf = &rqstp->rq_resbuf;
181 
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);
186 }
187 
188 /*
189  * XDR decode functions
190  */
191 int
192 nfssvc_decode_void(struct svc_rqst *rqstp, u32 *p, void *dummy)
193 {
194         return xdr_argsize_check(rqstp, p);
195 }
196 
197 int
198 nfssvc_decode_fhandle(struct svc_rqst *rqstp, u32 *p, struct svc_fh *fhp)
199 {
200         if (!(p = decode_fh(p, fhp)))
201                 return 0;
202         return xdr_argsize_check(rqstp, p);
203 }
204 
205 int
206 nfssvc_decode_sattrargs(struct svc_rqst *rqstp, u32 *p,
207                                         struct nfsd_sattrargs *args)
208 {
209         if (!(p = decode_fh(p, &args->fh))
210          || !(p = decode_sattr(p, &args->attrs)))
211                 return 0;
212 
213         return xdr_argsize_check(rqstp, p);
214 }
215 
216 int
217 nfssvc_decode_diropargs(struct svc_rqst *rqstp, u32 *p,
218                                         struct nfsd_diropargs *args)
219 {
220         if (!(p = decode_fh(p, &args->fh))
221          || !(p = decode_filename(p, &args->name, &args->len)))
222                 return 0;
223 
224          return xdr_argsize_check(rqstp, p);
225 }
226 
227 int
228 nfssvc_decode_readargs(struct svc_rqst *rqstp, u32 *p,
229                                         struct nfsd_readargs *args)
230 {
231         if (!(p = decode_fh(p, &args->fh)))
232                 return 0;
233 
234         args->offset    = ntohl(*p++);
235         args->count     = ntohl(*p++);
236         args->totalsize = ntohl(*p++);
237 
238         return xdr_argsize_check(rqstp, p);
239 }
240 
241 int
242 nfssvc_decode_writeargs(struct svc_rqst *rqstp, u32 *p,
243                                         struct nfsd_writeargs *args)
244 {
245         if (!(p = decode_fh(p, &args->fh)))
246                 return 0;
247 
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);
254 
255         return xdr_argsize_check(rqstp, p);
256 }
257 
258 int
259 nfssvc_decode_createargs(struct svc_rqst *rqstp, u32 *p,
260                                         struct nfsd_createargs *args)
261 {
262         if (!(p = decode_fh(p, &args->fh))
263          || !(p = decode_filename(p, &args->name, &args->len))
264          || !(p = decode_sattr(p, &args->attrs)))
265                 return 0;
266 
267         return xdr_argsize_check(rqstp, p);
268 }
269 
270 int
271 nfssvc_decode_renameargs(struct svc_rqst *rqstp, u32 *p,
272                                         struct nfsd_renameargs *args)
273 {
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)))
278                 return 0;
279 
280         return xdr_argsize_check(rqstp, p);
281 }
282 
283 int
284 nfssvc_decode_linkargs(struct svc_rqst *rqstp, u32 *p,
285                                         struct nfsd_linkargs *args)
286 {
287         if (!(p = decode_fh(p, &args->ffh))
288          || !(p = decode_fh(p, &args->tfh))
289          || !(p = decode_filename(p, &args->tname, &args->tlen)))
290                 return 0;
291 
292         return xdr_argsize_check(rqstp, p);
293 }
294 
295 int
296 nfssvc_decode_symlinkargs(struct svc_rqst *rqstp, u32 *p,
297                                         struct nfsd_symlinkargs *args)
298 {
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)))
303                 return 0;
304 
305         return xdr_argsize_check(rqstp, p);
306 }
307 
308 int
309 nfssvc_decode_readdirargs(struct svc_rqst *rqstp, u32 *p,
310                                         struct nfsd_readdirargs *args)
311 {
312         if (!(p = decode_fh(p, &args->fh)))
313                 return 0;
314         args->cookie = ntohl(*p++);
315         args->count  = ntohl(*p++);
316 
317         return xdr_argsize_check(rqstp, p);
318 }
319 
320 /*
321  * XDR encode functions
322  */
323 int
324 nfssvc_encode_void(struct svc_rqst *rqstp, u32 *p, void *dummy)
325 {
326         return xdr_ressize_check(rqstp, p);
327 }
328 
329 int
330 nfssvc_encode_attrstat(struct svc_rqst *rqstp, u32 *p,
331                                         struct nfsd_attrstat *resp)
332 {
333         if (!(p = encode_fattr(rqstp, p, resp->fh.fh_dentry->d_inode)))
334                 return 0;
335         return xdr_ressize_check(rqstp, p);
336 }
337 
338 int
339 nfssvc_encode_diropres(struct svc_rqst *rqstp, u32 *p,
340                                         struct nfsd_diropres *resp)
341 {
342         if (!(p = encode_fh(p, &resp->fh))
343          || !(p = encode_fattr(rqstp, p, resp->fh.fh_dentry->d_inode)))
344                 return 0;
345         return xdr_ressize_check(rqstp, p);
346 }
347 
348 int
349 nfssvc_encode_readlinkres(struct svc_rqst *rqstp, u32 *p,
350                                         struct nfsd_readlinkres *resp)
351 {
352         *p++ = htonl(resp->len);
353         p += XDR_QUADLEN(resp->len);
354         return xdr_ressize_check(rqstp, p);
355 }
356 
357 int
358 nfssvc_encode_readres(struct svc_rqst *rqstp, u32 *p,
359                                         struct nfsd_readres *resp)
360 {
361         if (!(p = encode_fattr(rqstp, p, resp->fh.fh_dentry->d_inode)))
362                 return 0;
363         *p++ = htonl(resp->count);
364         p += XDR_QUADLEN(resp->count);
365 
366         return xdr_ressize_check(rqstp, p);
367 }
368 
369 int
370 nfssvc_encode_readdirres(struct svc_rqst *rqstp, u32 *p,
371                                         struct nfsd_readdirres *resp)
372 {
373         p += XDR_QUADLEN(resp->count);
374         return xdr_ressize_check(rqstp, p);
375 }
376 
377 int
378 nfssvc_encode_statfsres(struct svc_rqst *rqstp, u32 *p,
379                                         struct nfsd_statfsres *resp)
380 {
381         struct statfs   *stat = &resp->stats;
382 
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);
389 }
390 
391 int
392 nfssvc_encode_entry(struct readdir_cd *cd, const char *name,
393                     int namlen, off_t offset, ino_t ino, unsigned int d_type)
394 {
395         u32     *p = cd->buffer;
396         int     buflen, slen;
397 
398         /*
399         dprintk("nfsd: entry(%.*s off %ld ino %ld)\n",
400                         namlen, name, offset, ino);
401          */
402 
403         if (offset > ~((u32) 0))
404                 return -EINVAL;
405         if (cd->offset)
406                 *cd->offset = htonl(offset);
407         if (namlen > NFS2_MAXNAMLEN)
408                 namlen = NFS2_MAXNAMLEN;/* truncate filename */
409 
410         slen = XDR_QUADLEN(namlen);
411         if ((buflen = cd->buflen - slen - 4) < 0) {
412                 cd->eob = 1;
413                 return -EINVAL;
414         }
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 */
420 
421         cd->buflen = buflen;
422         cd->buffer = p;
423         return 0;
424 }
425 
426 /*
427  * XDR release functions
428  */
429 int
430 nfssvc_release_fhandle(struct svc_rqst *rqstp, u32 *p,
431                                         struct nfsd_fhandle *resp)
432 {
433         fh_put(&resp->fh);
434         return 1;
435 }
436 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.