1 /*
2  * linux/fs/nfs/nfs2xdr.c
3  *
4  * XDR functions to encode/decode NFS RPC arguments and results.
5  *
6  * Copyright (C) 1992, 1993, 1994  Rick Sladkey
7  * Copyright (C) 1996 Olaf Kirch
8  * 04 Aug 1998  Ion Badulescu <ionut@cs.columbia.edu>
9  * 		FIFO's need special handling in NFSv2
10  */
11 
12 #include <linux/param.h>
13 #include <linux/sched.h>
14 #include <linux/mm.h>
15 #include <linux/slab.h>
16 #include <linux/utsname.h>
17 #include <linux/errno.h>
18 #include <linux/string.h>
19 #include <linux/in.h>
20 #include <linux/pagemap.h>
21 #include <linux/proc_fs.h>
22 #include <linux/sunrpc/clnt.h>
23 #include <linux/nfs.h>
24 #include <linux/nfs2.h>
25 #include <linux/nfs_fs.h>
26 
27 #define NFSDBG_FACILITY		NFSDBG_XDR
28 /* #define NFS_PARANOIA 1 */
29 
30 extern int			nfs_stat_to_errno(int stat);
31 
32 /* Mapping from NFS error code to "errno" error code. */
33 #define errno_NFSERR_IO		EIO
34 
35 /*
36  * Declare the space requirements for NFS arguments and replies as
37  * number of 32bit-words
38  */
39 #define NFS_fhandle_sz		8
40 #define NFS_sattr_sz		8
41 #define NFS_filename_sz		1+(NFS2_MAXNAMLEN>>2)
42 #define NFS_path_sz		1+(NFS2_MAXPATHLEN>>2)
43 #define NFS_fattr_sz		17
44 #define NFS_info_sz		5
45 #define NFS_entry_sz		NFS_filename_sz+3
46 
47 #define NFS_enc_void_sz		0
48 #define NFS_diropargs_sz	NFS_fhandle_sz+NFS_filename_sz
49 #define NFS_sattrargs_sz	NFS_fhandle_sz+NFS_sattr_sz
50 #define NFS_readlinkargs_sz	NFS_fhandle_sz
51 #define NFS_readargs_sz		NFS_fhandle_sz+3
52 #define NFS_writeargs_sz	NFS_fhandle_sz+4
53 #define NFS_createargs_sz	NFS_diropargs_sz+NFS_sattr_sz
54 #define NFS_renameargs_sz	NFS_diropargs_sz+NFS_diropargs_sz
55 #define NFS_linkargs_sz		NFS_fhandle_sz+NFS_diropargs_sz
56 #define NFS_symlinkargs_sz	NFS_diropargs_sz+NFS_path_sz+NFS_sattr_sz
57 #define NFS_readdirargs_sz	NFS_fhandle_sz+2
58 
59 #define NFS_dec_void_sz		0
60 #define NFS_attrstat_sz		1+NFS_fattr_sz
61 #define NFS_diropres_sz		1+NFS_fhandle_sz+NFS_fattr_sz
62 #define NFS_readlinkres_sz	1
63 #define NFS_readres_sz		1+NFS_fattr_sz+1
64 #define NFS_writeres_sz         NFS_attrstat_sz
65 #define NFS_stat_sz		1
66 #define NFS_readdirres_sz	1
67 #define NFS_statfsres_sz	1+NFS_info_sz
68 
69 /*
70  * Common NFS XDR functions as inlines
71  */
72 static inline u32 *
xdr_encode_fhandle(u32 * p,struct nfs_fh * fhandle)73 xdr_encode_fhandle(u32 *p, struct nfs_fh *fhandle)
74 {
75 	memcpy(p, fhandle->data, NFS2_FHSIZE);
76 	return p + XDR_QUADLEN(NFS2_FHSIZE);
77 }
78 
79 static inline u32 *
xdr_decode_fhandle(u32 * p,struct nfs_fh * fhandle)80 xdr_decode_fhandle(u32 *p, struct nfs_fh *fhandle)
81 {
82 	/* Zero handle first to allow comparisons */
83 	memset(fhandle, 0, sizeof(*fhandle));
84 	/* NFSv2 handles have a fixed length */
85 	fhandle->size = NFS2_FHSIZE;
86 	memcpy(fhandle->data, p, NFS2_FHSIZE);
87 	return p + XDR_QUADLEN(NFS2_FHSIZE);
88 }
89 
90 static inline u32*
xdr_decode_time(u32 * p,u64 * timep)91 xdr_decode_time(u32 *p, u64 *timep)
92 {
93 	u64 tmp = (u64)ntohl(*p++) << 32;
94 	*timep = tmp + (u64)ntohl(*p++);
95 	return p;
96 }
97 
98 static u32 *
xdr_decode_fattr(u32 * p,struct nfs_fattr * fattr)99 xdr_decode_fattr(u32 *p, struct nfs_fattr *fattr)
100 {
101 	fattr->type = (enum nfs_ftype) ntohl(*p++);
102 	fattr->mode = ntohl(*p++);
103 	fattr->nlink = ntohl(*p++);
104 	fattr->uid = ntohl(*p++);
105 	fattr->gid = ntohl(*p++);
106 	fattr->size = ntohl(*p++);
107 	fattr->du.nfs2.blocksize = ntohl(*p++);
108 	fattr->rdev = ntohl(*p++);
109 	fattr->du.nfs2.blocks = ntohl(*p++);
110 	fattr->fsid = ntohl(*p++);
111 	fattr->fileid = ntohl(*p++);
112 	p = xdr_decode_time(p, &fattr->atime);
113 	p = xdr_decode_time(p, &fattr->mtime);
114 	p = xdr_decode_time(p, &fattr->ctime);
115 	fattr->valid |= NFS_ATTR_FATTR;
116 	if (fattr->type == NFCHR && fattr->rdev == NFS2_FIFO_DEV) {
117 		fattr->type = NFFIFO;
118 		fattr->mode = (fattr->mode & ~S_IFMT) | S_IFIFO;
119 		fattr->rdev = 0;
120 	}
121 	return p;
122 }
123 
124 #define SATTR(p, attr, flag, field) \
125         *p++ = (attr->ia_valid & flag) ? htonl(attr->field) : ~(u32) 0
126 static inline u32 *
xdr_encode_sattr(u32 * p,struct iattr * attr)127 xdr_encode_sattr(u32 *p, struct iattr *attr)
128 {
129 	SATTR(p, attr, ATTR_MODE, ia_mode);
130 	SATTR(p, attr, ATTR_UID, ia_uid);
131 	SATTR(p, attr, ATTR_GID, ia_gid);
132 	SATTR(p, attr, ATTR_SIZE, ia_size);
133 
134 	if (attr->ia_valid & (ATTR_ATIME|ATTR_ATIME_SET)) {
135 		*p++ = htonl(attr->ia_atime);
136 		*p++ = 0;
137 	} else {
138 		*p++ = ~(u32) 0;
139 		*p++ = ~(u32) 0;
140 	}
141 
142 	if (attr->ia_valid & (ATTR_MTIME|ATTR_MTIME_SET)) {
143 		*p++ = htonl(attr->ia_mtime);
144 		*p++ = 0;
145 	} else {
146 		*p++ = ~(u32) 0;
147 		*p++ = ~(u32) 0;
148 	}
149   	return p;
150 }
151 #undef SATTR
152 
153 /*
154  * NFS encode functions
155  */
156 /*
157  * Encode void argument
158  */
159 static int
nfs_xdr_enc_void(struct rpc_rqst * req,u32 * p,void * dummy)160 nfs_xdr_enc_void(struct rpc_rqst *req, u32 *p, void *dummy)
161 {
162 	req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
163 	return 0;
164 }
165 
166 /*
167  * Encode file handle argument
168  * GETATTR, READLINK, STATFS
169  */
170 static int
nfs_xdr_fhandle(struct rpc_rqst * req,u32 * p,struct nfs_fh * fh)171 nfs_xdr_fhandle(struct rpc_rqst *req, u32 *p, struct nfs_fh *fh)
172 {
173 	p = xdr_encode_fhandle(p, fh);
174 	req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
175 	return 0;
176 }
177 
178 /*
179  * Encode SETATTR arguments
180  */
181 static int
nfs_xdr_sattrargs(struct rpc_rqst * req,u32 * p,struct nfs_sattrargs * args)182 nfs_xdr_sattrargs(struct rpc_rqst *req, u32 *p, struct nfs_sattrargs *args)
183 {
184 	p = xdr_encode_fhandle(p, args->fh);
185 	p = xdr_encode_sattr(p, args->sattr);
186 	req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
187 	return 0;
188 }
189 
190 /*
191  * Encode directory ops argument
192  * LOOKUP, REMOVE, RMDIR
193  */
194 static int
nfs_xdr_diropargs(struct rpc_rqst * req,u32 * p,struct nfs_diropargs * args)195 nfs_xdr_diropargs(struct rpc_rqst *req, u32 *p, struct nfs_diropargs *args)
196 {
197 	p = xdr_encode_fhandle(p, args->fh);
198 	p = xdr_encode_array(p, args->name, args->len);
199 	req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
200 	return 0;
201 }
202 
203 /*
204  * Arguments to a READ call. Since we read data directly into the page
205  * cache, we also set up the reply iovec here so that iov[1] points
206  * exactly to the page we want to fetch.
207  */
208 static int
nfs_xdr_readargs(struct rpc_rqst * req,u32 * p,struct nfs_readargs * args)209 nfs_xdr_readargs(struct rpc_rqst *req, u32 *p, struct nfs_readargs *args)
210 {
211 	struct rpc_auth	*auth = req->rq_task->tk_auth;
212 	unsigned int replen;
213 	u32 offset = (u32)args->offset;
214 	u32 count = args->count;
215 
216 	p = xdr_encode_fhandle(p, args->fh);
217 	*p++ = htonl(offset);
218 	*p++ = htonl(count);
219 	*p++ = htonl(count);
220 	req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
221 
222 	/* Inline the page array */
223 	replen = (RPC_REPHDRSIZE + auth->au_rslack + NFS_readres_sz) << 2;
224 	xdr_inline_pages(&req->rq_rcv_buf, replen,
225 			 args->pages, args->pgbase, count);
226 	return 0;
227 }
228 
229 /*
230  * Decode READ reply
231  */
232 static int
nfs_xdr_readres(struct rpc_rqst * req,u32 * p,struct nfs_readres * res)233 nfs_xdr_readres(struct rpc_rqst *req, u32 *p, struct nfs_readres *res)
234 {
235 	struct xdr_buf *rcvbuf = &req->rq_rcv_buf;
236 	struct iovec *iov = req->rq_rvec;
237 	int	status, count, recvd, hdrlen;
238 
239 	if ((status = ntohl(*p++)))
240 		return -nfs_stat_to_errno(status);
241 	p = xdr_decode_fattr(p, res->fattr);
242 
243 	count = ntohl(*p++);
244 	res->eof = 0;
245 	if (rcvbuf->page_len) {
246 		u32 end = page_offset(rcvbuf->pages[0]) + rcvbuf->page_base + count;
247 		if (end >= res->fattr->size)
248 			res->eof = 1;
249 	}
250 	hdrlen = (u8 *) p - (u8 *) iov->iov_base;
251 	if (iov->iov_len < hdrlen) {
252 		printk(KERN_WARNING "NFS: READ reply header overflowed:"
253 				"length %d > %Zu\n", hdrlen, iov->iov_len);
254 		return -errno_NFSERR_IO;
255 	} else if (iov->iov_len != hdrlen) {
256 		dprintk("NFS: READ header is short. iovec will be shifted.\n");
257 		xdr_shift_buf(&req->rq_rcv_buf, iov->iov_len - hdrlen);
258 	}
259 
260 	recvd = req->rq_received - hdrlen;
261 	if (count > recvd) {
262 		printk(KERN_WARNING "NFS: server cheating in read reply: "
263 			"count %d > recvd %d\n", count, recvd);
264 		count = recvd;
265 		res->eof = 0;
266 	}
267 
268 	dprintk("RPC:      readres OK count %d\n", count);
269 	if (count < res->count)
270 		res->count = count;
271 
272 	return count;
273 }
274 
275 
276 /*
277  * Write arguments. Splice the buffer to be written into the iovec.
278  */
279 static int
nfs_xdr_writeargs(struct rpc_rqst * req,u32 * p,struct nfs_writeargs * args)280 nfs_xdr_writeargs(struct rpc_rqst *req, u32 *p, struct nfs_writeargs *args)
281 {
282 	struct xdr_buf *sndbuf = &req->rq_snd_buf;
283 	u32 offset = (u32)args->offset;
284 	u32 count = args->count;
285 
286 	p = xdr_encode_fhandle(p, args->fh);
287 	*p++ = htonl(offset);
288 	*p++ = htonl(offset);
289 	*p++ = htonl(count);
290 	*p++ = htonl(count);
291 	sndbuf->len = xdr_adjust_iovec(sndbuf->head, p);
292 
293 	/* Copy the page array */
294 	xdr_encode_pages(sndbuf, args->pages, args->pgbase, count);
295 	return 0;
296 }
297 
298 /*
299  * Encode create arguments
300  * CREATE, MKDIR
301  */
302 static int
nfs_xdr_createargs(struct rpc_rqst * req,u32 * p,struct nfs_createargs * args)303 nfs_xdr_createargs(struct rpc_rqst *req, u32 *p, struct nfs_createargs *args)
304 {
305 	p = xdr_encode_fhandle(p, args->fh);
306 	p = xdr_encode_array(p, args->name, args->len);
307 	p = xdr_encode_sattr(p, args->sattr);
308 	req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
309 	return 0;
310 }
311 
312 /*
313  * Encode RENAME arguments
314  */
315 static int
nfs_xdr_renameargs(struct rpc_rqst * req,u32 * p,struct nfs_renameargs * args)316 nfs_xdr_renameargs(struct rpc_rqst *req, u32 *p, struct nfs_renameargs *args)
317 {
318 	p = xdr_encode_fhandle(p, args->fromfh);
319 	p = xdr_encode_array(p, args->fromname, args->fromlen);
320 	p = xdr_encode_fhandle(p, args->tofh);
321 	p = xdr_encode_array(p, args->toname, args->tolen);
322 	req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
323 	return 0;
324 }
325 
326 /*
327  * Encode LINK arguments
328  */
329 static int
nfs_xdr_linkargs(struct rpc_rqst * req,u32 * p,struct nfs_linkargs * args)330 nfs_xdr_linkargs(struct rpc_rqst *req, u32 *p, struct nfs_linkargs *args)
331 {
332 	p = xdr_encode_fhandle(p, args->fromfh);
333 	p = xdr_encode_fhandle(p, args->tofh);
334 	p = xdr_encode_array(p, args->toname, args->tolen);
335 	req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
336 	return 0;
337 }
338 
339 /*
340  * Encode SYMLINK arguments
341  */
342 static int
nfs_xdr_symlinkargs(struct rpc_rqst * req,u32 * p,struct nfs_symlinkargs * args)343 nfs_xdr_symlinkargs(struct rpc_rqst *req, u32 *p, struct nfs_symlinkargs *args)
344 {
345 	p = xdr_encode_fhandle(p, args->fromfh);
346 	p = xdr_encode_array(p, args->fromname, args->fromlen);
347 	p = xdr_encode_array(p, args->topath, args->tolen);
348 	p = xdr_encode_sattr(p, args->sattr);
349 	req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
350 	return 0;
351 }
352 
353 /*
354  * Encode arguments to readdir call
355  */
356 static int
nfs_xdr_readdirargs(struct rpc_rqst * req,u32 * p,struct nfs_readdirargs * args)357 nfs_xdr_readdirargs(struct rpc_rqst *req, u32 *p, struct nfs_readdirargs *args)
358 {
359 	struct rpc_task	*task = req->rq_task;
360 	struct rpc_auth	*auth = task->tk_auth;
361 	unsigned int replen;
362 	u32 count = args->count;
363 
364 	/*
365 	 * Some servers (e.g. HP OS 9.5) seem to expect the buffer size
366 	 * to be in longwords ... check whether to convert the size.
367 	 */
368 	if (task->tk_client->cl_flags & NFS_CLNTF_BUFSIZE)
369 		count = count >> 2;
370 
371 	p = xdr_encode_fhandle(p, args->fh);
372 	*p++ = htonl(args->cookie);
373 	*p++ = htonl(count); /* see above */
374 	req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
375 
376 	/* Inline the page array */
377 	replen = (RPC_REPHDRSIZE + auth->au_rslack + NFS_readdirres_sz) << 2;
378 	xdr_inline_pages(&req->rq_rcv_buf, replen, args->pages, 0, count);
379 	return 0;
380 }
381 
382 /*
383  * Decode the result of a readdir call.
384  * We're not really decoding anymore, we just leave the buffer untouched
385  * and only check that it is syntactically correct.
386  * The real decoding happens in nfs_decode_entry below, called directly
387  * from nfs_readdir for each entry.
388  */
389 static int
nfs_xdr_readdirres(struct rpc_rqst * req,u32 * p,void * dummy)390 nfs_xdr_readdirres(struct rpc_rqst *req, u32 *p, void *dummy)
391 {
392 	struct xdr_buf *rcvbuf = &req->rq_rcv_buf;
393 	struct iovec *iov = rcvbuf->head;
394 	struct page **page;
395 	int hdrlen, recvd;
396 	int status, nr;
397 	unsigned int len, pglen;
398 	u32 *end, *entry;
399 
400 	if ((status = ntohl(*p++)))
401 		return -nfs_stat_to_errno(status);
402 
403 	hdrlen = (u8 *) p - (u8 *) iov->iov_base;
404 	if (iov->iov_len < hdrlen) {
405 		printk(KERN_WARNING "NFS: READDIR reply header overflowed:"
406 				"length %d > %Zu\n", hdrlen, iov->iov_len);
407 		return -errno_NFSERR_IO;
408 	} else if (iov->iov_len != hdrlen) {
409 		dprintk("NFS: READDIR header is short. iovec will be shifted.\n");
410 		xdr_shift_buf(rcvbuf, iov->iov_len - hdrlen);
411 	}
412 
413 	pglen = rcvbuf->page_len;
414 	recvd = req->rq_received - hdrlen;
415 	if (pglen > recvd)
416 		pglen = recvd;
417 	page = rcvbuf->pages;
418 	p = kmap(*page);
419 	entry = p;
420 	end = (u32 *)((char *)p + pglen);
421 	for (nr = 0; *p++; nr++) {
422 		if (p + 2 > end)
423 			goto short_pkt;
424 		p++; /* fileid */
425 		len = ntohl(*p++);
426 		p += XDR_QUADLEN(len) + 1;	/* name plus cookie */
427 		if (len > NFS2_MAXNAMLEN) {
428 			printk(KERN_WARNING "NFS: giant filename in readdir (len 0x%x)!\n",
429 						len);
430 			goto err_unmap;
431 		}
432 		if (p + 2 > end)
433 			goto short_pkt;
434 		entry = p;
435 	}
436 	if (!nr && (entry[0] != 0 || entry[1] == 0))
437 		goto short_pkt;
438  out:
439 	kunmap(*page);
440 	return nr;
441  short_pkt:
442 	entry[0] = entry[1] = 0;
443 	/* truncate listing ? */
444 	if (!nr) {
445 		printk(KERN_NOTICE "NFS: readdir reply truncated!\n");
446 		entry[1] = 1;
447 	}
448 	goto out;
449 err_unmap:
450 	kunmap(*page);
451 	return -errno_NFSERR_IO;
452 }
453 
454 u32 *
nfs_decode_dirent(u32 * p,struct nfs_entry * entry,int plus)455 nfs_decode_dirent(u32 *p, struct nfs_entry *entry, int plus)
456 {
457 	if (!*p++) {
458 		if (!*p)
459 			return ERR_PTR(-EAGAIN);
460 		entry->eof = 1;
461 		return ERR_PTR(-EBADCOOKIE);
462 	}
463 
464 	entry->ino	  = ntohl(*p++);
465 	entry->len	  = ntohl(*p++);
466 	entry->name	  = (const char *) p;
467 	p		 += XDR_QUADLEN(entry->len);
468 	entry->prev_cookie	  = entry->cookie;
469 	entry->cookie	  = ntohl(*p++);
470 	entry->eof	  = !p[0] && p[1];
471 
472 	return p;
473 }
474 
475 /*
476  * NFS XDR decode functions
477  */
478 /*
479  * Decode void reply
480  */
481 static int
nfs_xdr_dec_void(struct rpc_rqst * req,u32 * p,void * dummy)482 nfs_xdr_dec_void(struct rpc_rqst *req, u32 *p, void *dummy)
483 {
484 	return 0;
485 }
486 
487 /*
488  * Decode simple status reply
489  */
490 static int
nfs_xdr_stat(struct rpc_rqst * req,u32 * p,void * dummy)491 nfs_xdr_stat(struct rpc_rqst *req, u32 *p, void *dummy)
492 {
493 	int	status;
494 
495 	if ((status = ntohl(*p++)) != 0)
496 		status = -nfs_stat_to_errno(status);
497 	return status;
498 }
499 
500 /*
501  * Decode attrstat reply
502  * GETATTR, SETATTR, WRITE
503  */
504 static int
nfs_xdr_attrstat(struct rpc_rqst * req,u32 * p,struct nfs_fattr * fattr)505 nfs_xdr_attrstat(struct rpc_rqst *req, u32 *p, struct nfs_fattr *fattr)
506 {
507 	int	status;
508 
509 	if ((status = ntohl(*p++)))
510 		return -nfs_stat_to_errno(status);
511 	xdr_decode_fattr(p, fattr);
512 	return 0;
513 }
514 
515 /*
516  * Decode diropres reply
517  * LOOKUP, CREATE, MKDIR
518  */
519 static int
nfs_xdr_diropres(struct rpc_rqst * req,u32 * p,struct nfs_diropok * res)520 nfs_xdr_diropres(struct rpc_rqst *req, u32 *p, struct nfs_diropok *res)
521 {
522 	int	status;
523 
524 	if ((status = ntohl(*p++)))
525 		return -nfs_stat_to_errno(status);
526 	p = xdr_decode_fhandle(p, res->fh);
527 	xdr_decode_fattr(p, res->fattr);
528 	return 0;
529 }
530 
531 /*
532  * Encode READLINK args
533  */
534 static int
nfs_xdr_readlinkargs(struct rpc_rqst * req,u32 * p,struct nfs_readlinkargs * args)535 nfs_xdr_readlinkargs(struct rpc_rqst *req, u32 *p, struct nfs_readlinkargs *args)
536 {
537 	struct rpc_auth *auth = req->rq_task->tk_auth;
538 	unsigned int replen;
539 	u32 count = args->count - 4;
540 
541 	p = xdr_encode_fhandle(p, args->fh);
542 	req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
543 
544 	/* Inline the page array */
545 	replen = (RPC_REPHDRSIZE + auth->au_rslack + NFS_readlinkres_sz) << 2;
546 	xdr_inline_pages(&req->rq_rcv_buf, replen, args->pages, 0, count);
547 	return 0;
548 }
549 
550 /*
551  * Decode READLINK reply
552  */
553 static int
nfs_xdr_readlinkres(struct rpc_rqst * req,u32 * p,void * dummy)554 nfs_xdr_readlinkres(struct rpc_rqst *req, u32 *p, void *dummy)
555 {
556 	struct xdr_buf *rcvbuf = &req->rq_rcv_buf;
557 	struct iovec *iov = rcvbuf->head;
558 	unsigned int hdrlen;
559 	u32	*strlen, len;
560 	char	*string;
561 	int	status;
562 
563 	if ((status = ntohl(*p++)))
564 		return -nfs_stat_to_errno(status);
565 	hdrlen = (u8 *) p - (u8 *) iov->iov_base;
566 	if (iov->iov_len > hdrlen) {
567 		dprintk("NFS: READLINK header is short. iovec will be shifted.\n");
568 		xdr_shift_buf(rcvbuf, iov->iov_len - hdrlen);
569 	}
570 
571 	strlen = (u32*)kmap(rcvbuf->pages[0]);
572 	/* Convert length of symlink */
573 	len = ntohl(*strlen);
574 	if (len >= rcvbuf->page_len - sizeof(u32) || len > NFS2_MAXPATHLEN) {
575 		dprintk("NFS: server returned giant symlink!\n");
576 		kunmap(rcvbuf->pages[0]);
577 		return -ENAMETOOLONG;
578         }
579 	*strlen = len;
580 	/* NULL terminate the string we got */
581 	string = (char *)(strlen + 1);
582 	string[len] = 0;
583 	kunmap(rcvbuf->pages[0]);
584 	return 0;
585 }
586 
587 /*
588  * Decode WRITE reply
589  */
590 static int
nfs_xdr_writeres(struct rpc_rqst * req,u32 * p,struct nfs_writeres * res)591 nfs_xdr_writeres(struct rpc_rqst *req, u32 *p, struct nfs_writeres *res)
592 {
593 	res->verf->committed = NFS_FILE_SYNC;
594 	return nfs_xdr_attrstat(req, p, res->fattr);
595 }
596 
597 /*
598  * Decode STATFS reply
599  */
600 static int
nfs_xdr_statfsres(struct rpc_rqst * req,u32 * p,struct nfs_fsinfo * res)601 nfs_xdr_statfsres(struct rpc_rqst *req, u32 *p, struct nfs_fsinfo *res)
602 {
603 	int	status;
604 	u32	xfer_size;
605 
606 	if ((status = ntohl(*p++)))
607 		return -nfs_stat_to_errno(status);
608 
609 	/* For NFSv2, we more or less have to guess the preferred
610 	 * read/write/readdir sizes from the single 'transfer size'
611 	 * value.
612 	 */
613 	xfer_size = ntohl(*p++);	/* tsize */
614 	res->rtmax  = 8 * 1024;
615 	res->rtpref = xfer_size;
616 	res->rtmult = xfer_size;
617 	res->wtmax  = 8 * 1024;
618 	res->wtpref = xfer_size;
619 	res->wtmult = xfer_size;
620 	res->dtpref = PAGE_CACHE_SIZE;
621 	res->maxfilesize = 0x7FFFFFFF;	/* just a guess */
622 	res->bsize  = ntohl(*p++);
623 
624 	res->tbytes = ntohl(*p++) * res->bsize;
625 	res->fbytes = ntohl(*p++) * res->bsize;
626 	res->abytes = ntohl(*p++) * res->bsize;
627 	res->tfiles = 0;
628 	res->ffiles = 0;
629 	res->afiles = 0;
630 	res->namelen = 0;
631 
632 	return 0;
633 }
634 
635 /*
636  * We need to translate between nfs status return values and
637  * the local errno values which may not be the same.
638  */
639 static struct {
640 	int stat;
641 	int errno;
642 } nfs_errtbl[] = {
643 	{ NFS_OK,		0		},
644 	{ NFSERR_PERM,		EPERM		},
645 	{ NFSERR_NOENT,		ENOENT		},
646 	{ NFSERR_IO,		errno_NFSERR_IO	},
647 	{ NFSERR_NXIO,		ENXIO		},
648 /*	{ NFSERR_EAGAIN,	EAGAIN		}, */
649 	{ NFSERR_ACCES,		EACCES		},
650 	{ NFSERR_EXIST,		EEXIST		},
651 	{ NFSERR_XDEV,		EXDEV		},
652 	{ NFSERR_NODEV,		ENODEV		},
653 	{ NFSERR_NOTDIR,	ENOTDIR		},
654 	{ NFSERR_ISDIR,		EISDIR		},
655 	{ NFSERR_INVAL,		EINVAL		},
656 	{ NFSERR_FBIG,		EFBIG		},
657 	{ NFSERR_NOSPC,		ENOSPC		},
658 	{ NFSERR_ROFS,		EROFS		},
659 	{ NFSERR_MLINK,		EMLINK		},
660 	{ NFSERR_NAMETOOLONG,	ENAMETOOLONG	},
661 	{ NFSERR_NOTEMPTY,	ENOTEMPTY	},
662 	{ NFSERR_DQUOT,		EDQUOT		},
663 	{ NFSERR_STALE,		ESTALE		},
664 	{ NFSERR_REMOTE,	EREMOTE		},
665 #ifdef EWFLUSH
666 	{ NFSERR_WFLUSH,	EWFLUSH		},
667 #endif
668 	{ NFSERR_BADHANDLE,	EBADHANDLE	},
669 	{ NFSERR_NOT_SYNC,	ENOTSYNC	},
670 	{ NFSERR_BAD_COOKIE,	EBADCOOKIE	},
671 	{ NFSERR_NOTSUPP,	ENOTSUPP	},
672 	{ NFSERR_TOOSMALL,	ETOOSMALL	},
673 	{ NFSERR_SERVERFAULT,	ESERVERFAULT	},
674 	{ NFSERR_BADTYPE,	EBADTYPE	},
675 	{ NFSERR_JUKEBOX,	EJUKEBOX	},
676 	{ -1,			EIO		}
677 };
678 
679 /*
680  * Convert an NFS error code to a local one.
681  * This one is used jointly by NFSv2 and NFSv3.
682  */
683 int
nfs_stat_to_errno(int stat)684 nfs_stat_to_errno(int stat)
685 {
686 	int i;
687 
688 	for (i = 0; nfs_errtbl[i].stat != -1; i++) {
689 		if (nfs_errtbl[i].stat == stat)
690 			return nfs_errtbl[i].errno;
691 	}
692 	printk(KERN_ERR "nfs_stat_to_errno: bad nfs status return value: %d\n", stat);
693 	return nfs_errtbl[i].errno;
694 }
695 
696 #ifndef MAX
697 # define MAX(a, b)	(((a) > (b))? (a) : (b))
698 #endif
699 
700 #define PROC(proc, argtype, restype, timer)				\
701     { .p_procname =  "nfs_" #proc,					\
702       .p_encode   =  (kxdrproc_t) nfs_xdr_##argtype,			\
703       .p_decode   =  (kxdrproc_t) nfs_xdr_##restype,			\
704       .p_bufsiz   =  MAX(NFS_##argtype##_sz,NFS_##restype##_sz) << 2,	\
705       .p_timer    =  timer						\
706     }
707 static struct rpc_procinfo	nfs_procedures[18] = {
708     PROC(null,		enc_void,	dec_void, 0),
709     PROC(getattr,	fhandle,	attrstat, 1),
710     PROC(setattr,	sattrargs,	attrstat, 0),
711     PROC(root,		enc_void,	dec_void, 0),
712     PROC(lookup,	diropargs,	diropres, 2),
713     PROC(readlink,	readlinkargs,	readlinkres, 3),
714     PROC(read,		readargs,	readres, 3),
715     PROC(writecache,	enc_void,	dec_void, 0),
716     PROC(write,		writeargs,	writeres, 4),
717     PROC(create,	createargs,	diropres, 0),
718     PROC(remove,	diropargs,	stat, 0),
719     PROC(rename,	renameargs,	stat, 0),
720     PROC(link,		linkargs,	stat, 0),
721     PROC(symlink,	symlinkargs,	stat, 0),
722     PROC(mkdir,		createargs,	diropres, 0),
723     PROC(rmdir,		diropargs,	stat, 0),
724     PROC(readdir,	readdirargs,	readdirres, 3),
725     PROC(statfs,	fhandle,	statfsres, 0),
726 };
727 
728 struct rpc_version		nfs_version2 = {
729 	2,
730 	sizeof(nfs_procedures)/sizeof(nfs_procedures[0]),
731 	nfs_procedures
732 };
733