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