xref: /openbmc/linux/fs/lockd/clnt4xdr.c (revision 2c684d89)
1 /*
2  * linux/fs/lockd/clnt4xdr.c
3  *
4  * XDR functions to encode/decode NLM version 4 RPC arguments and results.
5  *
6  * NLM client-side only.
7  *
8  * Copyright (C) 2010, Oracle.  All rights reserved.
9  */
10 
11 #include <linux/types.h>
12 #include <linux/sunrpc/xdr.h>
13 #include <linux/sunrpc/clnt.h>
14 #include <linux/sunrpc/stats.h>
15 #include <linux/lockd/lockd.h>
16 
17 #include <uapi/linux/nfs3.h>
18 
19 #define NLMDBG_FACILITY		NLMDBG_XDR
20 
21 #if (NLMCLNT_OHSIZE > XDR_MAX_NETOBJ)
22 #  error "NLM host name cannot be larger than XDR_MAX_NETOBJ!"
23 #endif
24 
25 #if (NLMCLNT_OHSIZE > NLM_MAXSTRLEN)
26 #  error "NLM host name cannot be larger than NLM's maximum string length!"
27 #endif
28 
29 /*
30  * Declare the space requirements for NLM arguments and replies as
31  * number of 32bit-words
32  */
33 #define NLM4_void_sz		(0)
34 #define NLM4_cookie_sz		(1+(NLM_MAXCOOKIELEN>>2))
35 #define NLM4_caller_sz		(1+(NLMCLNT_OHSIZE>>2))
36 #define NLM4_owner_sz		(1+(NLMCLNT_OHSIZE>>2))
37 #define NLM4_fhandle_sz		(1+(NFS3_FHSIZE>>2))
38 #define NLM4_lock_sz		(5+NLM4_caller_sz+NLM4_owner_sz+NLM4_fhandle_sz)
39 #define NLM4_holder_sz		(6+NLM4_owner_sz)
40 
41 #define NLM4_testargs_sz	(NLM4_cookie_sz+1+NLM4_lock_sz)
42 #define NLM4_lockargs_sz	(NLM4_cookie_sz+4+NLM4_lock_sz)
43 #define NLM4_cancargs_sz	(NLM4_cookie_sz+2+NLM4_lock_sz)
44 #define NLM4_unlockargs_sz	(NLM4_cookie_sz+NLM4_lock_sz)
45 
46 #define NLM4_testres_sz		(NLM4_cookie_sz+1+NLM4_holder_sz)
47 #define NLM4_res_sz		(NLM4_cookie_sz+1)
48 #define NLM4_norep_sz		(0)
49 
50 
51 static s64 loff_t_to_s64(loff_t offset)
52 {
53 	s64 res;
54 
55 	if (offset >= NLM4_OFFSET_MAX)
56 		res = NLM4_OFFSET_MAX;
57 	else if (offset <= -NLM4_OFFSET_MAX)
58 		res = -NLM4_OFFSET_MAX;
59 	else
60 		res = offset;
61 	return res;
62 }
63 
64 static void nlm4_compute_offsets(const struct nlm_lock *lock,
65 				 u64 *l_offset, u64 *l_len)
66 {
67 	const struct file_lock *fl = &lock->fl;
68 
69 	*l_offset = loff_t_to_s64(fl->fl_start);
70 	if (fl->fl_end == OFFSET_MAX)
71 		*l_len = 0;
72 	else
73 		*l_len = loff_t_to_s64(fl->fl_end - fl->fl_start + 1);
74 }
75 
76 /*
77  * Handle decode buffer overflows out-of-line.
78  */
79 static void print_overflow_msg(const char *func, const struct xdr_stream *xdr)
80 {
81 	dprintk("lockd: %s prematurely hit the end of our receive buffer. "
82 		"Remaining buffer length is %tu words.\n",
83 		func, xdr->end - xdr->p);
84 }
85 
86 
87 /*
88  * Encode/decode NLMv4 basic data types
89  *
90  * Basic NLMv4 data types are defined in Appendix II, section 6.1.4
91  * of RFC 1813: "NFS Version 3 Protocol Specification" and in Chapter
92  * 10 of X/Open's "Protocols for Interworking: XNFS, Version 3W".
93  *
94  * Not all basic data types have their own encoding and decoding
95  * functions.  For run-time efficiency, some data types are encoded
96  * or decoded inline.
97  */
98 
99 static void encode_bool(struct xdr_stream *xdr, const int value)
100 {
101 	__be32 *p;
102 
103 	p = xdr_reserve_space(xdr, 4);
104 	*p = value ? xdr_one : xdr_zero;
105 }
106 
107 static void encode_int32(struct xdr_stream *xdr, const s32 value)
108 {
109 	__be32 *p;
110 
111 	p = xdr_reserve_space(xdr, 4);
112 	*p = cpu_to_be32(value);
113 }
114 
115 /*
116  *	typedef opaque netobj<MAXNETOBJ_SZ>
117  */
118 static void encode_netobj(struct xdr_stream *xdr,
119 			  const u8 *data, const unsigned int length)
120 {
121 	__be32 *p;
122 
123 	p = xdr_reserve_space(xdr, 4 + length);
124 	xdr_encode_opaque(p, data, length);
125 }
126 
127 static int decode_netobj(struct xdr_stream *xdr,
128 			 struct xdr_netobj *obj)
129 {
130 	u32 length;
131 	__be32 *p;
132 
133 	p = xdr_inline_decode(xdr, 4);
134 	if (unlikely(p == NULL))
135 		goto out_overflow;
136 	length = be32_to_cpup(p++);
137 	if (unlikely(length > XDR_MAX_NETOBJ))
138 		goto out_size;
139 	obj->len = length;
140 	obj->data = (u8 *)p;
141 	return 0;
142 out_size:
143 	dprintk("NFS: returned netobj was too long: %u\n", length);
144 	return -EIO;
145 out_overflow:
146 	print_overflow_msg(__func__, xdr);
147 	return -EIO;
148 }
149 
150 /*
151  *	netobj cookie;
152  */
153 static void encode_cookie(struct xdr_stream *xdr,
154 			  const struct nlm_cookie *cookie)
155 {
156 	encode_netobj(xdr, (u8 *)&cookie->data, cookie->len);
157 }
158 
159 static int decode_cookie(struct xdr_stream *xdr,
160 			     struct nlm_cookie *cookie)
161 {
162 	u32 length;
163 	__be32 *p;
164 
165 	p = xdr_inline_decode(xdr, 4);
166 	if (unlikely(p == NULL))
167 		goto out_overflow;
168 	length = be32_to_cpup(p++);
169 	/* apparently HPUX can return empty cookies */
170 	if (length == 0)
171 		goto out_hpux;
172 	if (length > NLM_MAXCOOKIELEN)
173 		goto out_size;
174 	p = xdr_inline_decode(xdr, length);
175 	if (unlikely(p == NULL))
176 		goto out_overflow;
177 	cookie->len = length;
178 	memcpy(cookie->data, p, length);
179 	return 0;
180 out_hpux:
181 	cookie->len = 4;
182 	memset(cookie->data, 0, 4);
183 	return 0;
184 out_size:
185 	dprintk("NFS: returned cookie was too long: %u\n", length);
186 	return -EIO;
187 out_overflow:
188 	print_overflow_msg(__func__, xdr);
189 	return -EIO;
190 }
191 
192 /*
193  *	netobj fh;
194  */
195 static void encode_fh(struct xdr_stream *xdr, const struct nfs_fh *fh)
196 {
197 	encode_netobj(xdr, (u8 *)&fh->data, fh->size);
198 }
199 
200 /*
201  *	enum nlm4_stats {
202  *		NLM4_GRANTED = 0,
203  *		NLM4_DENIED = 1,
204  *		NLM4_DENIED_NOLOCKS = 2,
205  *		NLM4_BLOCKED = 3,
206  *		NLM4_DENIED_GRACE_PERIOD = 4,
207  *		NLM4_DEADLCK = 5,
208  *		NLM4_ROFS = 6,
209  *		NLM4_STALE_FH = 7,
210  *		NLM4_FBIG = 8,
211  *		NLM4_FAILED = 9
212  *	};
213  *
214  *	struct nlm4_stat {
215  *		nlm4_stats stat;
216  *	};
217  *
218  * NB: we don't swap bytes for the NLM status values.  The upper
219  * layers deal directly with the status value in network byte
220  * order.
221  */
222 static void encode_nlm4_stat(struct xdr_stream *xdr,
223 			     const __be32 stat)
224 {
225 	__be32 *p;
226 
227 	BUG_ON(be32_to_cpu(stat) > NLM_FAILED);
228 	p = xdr_reserve_space(xdr, 4);
229 	*p = stat;
230 }
231 
232 static int decode_nlm4_stat(struct xdr_stream *xdr, __be32 *stat)
233 {
234 	__be32 *p;
235 
236 	p = xdr_inline_decode(xdr, 4);
237 	if (unlikely(p == NULL))
238 		goto out_overflow;
239 	if (unlikely(ntohl(*p) > ntohl(nlm4_failed)))
240 		goto out_bad_xdr;
241 	*stat = *p;
242 	return 0;
243 out_bad_xdr:
244 	dprintk("%s: server returned invalid nlm4_stats value: %u\n",
245 			__func__, be32_to_cpup(p));
246 	return -EIO;
247 out_overflow:
248 	print_overflow_msg(__func__, xdr);
249 	return -EIO;
250 }
251 
252 /*
253  *	struct nlm4_holder {
254  *		bool	exclusive;
255  *		int32	svid;
256  *		netobj	oh;
257  *		uint64	l_offset;
258  *		uint64	l_len;
259  *	};
260  */
261 static void encode_nlm4_holder(struct xdr_stream *xdr,
262 			       const struct nlm_res *result)
263 {
264 	const struct nlm_lock *lock = &result->lock;
265 	u64 l_offset, l_len;
266 	__be32 *p;
267 
268 	encode_bool(xdr, lock->fl.fl_type == F_RDLCK);
269 	encode_int32(xdr, lock->svid);
270 	encode_netobj(xdr, lock->oh.data, lock->oh.len);
271 
272 	p = xdr_reserve_space(xdr, 4 + 4);
273 	nlm4_compute_offsets(lock, &l_offset, &l_len);
274 	p = xdr_encode_hyper(p, l_offset);
275 	xdr_encode_hyper(p, l_len);
276 }
277 
278 static int decode_nlm4_holder(struct xdr_stream *xdr, struct nlm_res *result)
279 {
280 	struct nlm_lock *lock = &result->lock;
281 	struct file_lock *fl = &lock->fl;
282 	u64 l_offset, l_len;
283 	u32 exclusive;
284 	int error;
285 	__be32 *p;
286 	s32 end;
287 
288 	memset(lock, 0, sizeof(*lock));
289 	locks_init_lock(fl);
290 
291 	p = xdr_inline_decode(xdr, 4 + 4);
292 	if (unlikely(p == NULL))
293 		goto out_overflow;
294 	exclusive = be32_to_cpup(p++);
295 	lock->svid = be32_to_cpup(p);
296 	fl->fl_pid = (pid_t)lock->svid;
297 
298 	error = decode_netobj(xdr, &lock->oh);
299 	if (unlikely(error))
300 		goto out;
301 
302 	p = xdr_inline_decode(xdr, 8 + 8);
303 	if (unlikely(p == NULL))
304 		goto out_overflow;
305 
306 	fl->fl_flags = FL_POSIX;
307 	fl->fl_type  = exclusive != 0 ? F_WRLCK : F_RDLCK;
308 	p = xdr_decode_hyper(p, &l_offset);
309 	xdr_decode_hyper(p, &l_len);
310 	end = l_offset + l_len - 1;
311 
312 	fl->fl_start = (loff_t)l_offset;
313 	if (l_len == 0 || end < 0)
314 		fl->fl_end = OFFSET_MAX;
315 	else
316 		fl->fl_end = (loff_t)end;
317 	error = 0;
318 out:
319 	return error;
320 out_overflow:
321 	print_overflow_msg(__func__, xdr);
322 	return -EIO;
323 }
324 
325 /*
326  *	string caller_name<LM_MAXSTRLEN>;
327  */
328 static void encode_caller_name(struct xdr_stream *xdr, const char *name)
329 {
330 	/* NB: client-side does not set lock->len */
331 	u32 length = strlen(name);
332 	__be32 *p;
333 
334 	p = xdr_reserve_space(xdr, 4 + length);
335 	xdr_encode_opaque(p, name, length);
336 }
337 
338 /*
339  *	struct nlm4_lock {
340  *		string	caller_name<LM_MAXSTRLEN>;
341  *		netobj	fh;
342  *		netobj	oh;
343  *		int32	svid;
344  *		uint64	l_offset;
345  *		uint64	l_len;
346  *	};
347  */
348 static void encode_nlm4_lock(struct xdr_stream *xdr,
349 			     const struct nlm_lock *lock)
350 {
351 	u64 l_offset, l_len;
352 	__be32 *p;
353 
354 	encode_caller_name(xdr, lock->caller);
355 	encode_fh(xdr, &lock->fh);
356 	encode_netobj(xdr, lock->oh.data, lock->oh.len);
357 
358 	p = xdr_reserve_space(xdr, 4 + 8 + 8);
359 	*p++ = cpu_to_be32(lock->svid);
360 
361 	nlm4_compute_offsets(lock, &l_offset, &l_len);
362 	p = xdr_encode_hyper(p, l_offset);
363 	xdr_encode_hyper(p, l_len);
364 }
365 
366 
367 /*
368  * NLMv4 XDR encode functions
369  *
370  * NLMv4 argument types are defined in Appendix II of RFC 1813:
371  * "NFS Version 3 Protocol Specification" and Chapter 10 of X/Open's
372  * "Protocols for Interworking: XNFS, Version 3W".
373  */
374 
375 /*
376  *	struct nlm4_testargs {
377  *		netobj cookie;
378  *		bool exclusive;
379  *		struct nlm4_lock alock;
380  *	};
381  */
382 static void nlm4_xdr_enc_testargs(struct rpc_rqst *req,
383 				  struct xdr_stream *xdr,
384 				  const struct nlm_args *args)
385 {
386 	const struct nlm_lock *lock = &args->lock;
387 
388 	encode_cookie(xdr, &args->cookie);
389 	encode_bool(xdr, lock->fl.fl_type == F_WRLCK);
390 	encode_nlm4_lock(xdr, lock);
391 }
392 
393 /*
394  *	struct nlm4_lockargs {
395  *		netobj cookie;
396  *		bool block;
397  *		bool exclusive;
398  *		struct nlm4_lock alock;
399  *		bool reclaim;
400  *		int state;
401  *	};
402  */
403 static void nlm4_xdr_enc_lockargs(struct rpc_rqst *req,
404 				  struct xdr_stream *xdr,
405 				  const struct nlm_args *args)
406 {
407 	const struct nlm_lock *lock = &args->lock;
408 
409 	encode_cookie(xdr, &args->cookie);
410 	encode_bool(xdr, args->block);
411 	encode_bool(xdr, lock->fl.fl_type == F_WRLCK);
412 	encode_nlm4_lock(xdr, lock);
413 	encode_bool(xdr, args->reclaim);
414 	encode_int32(xdr, args->state);
415 }
416 
417 /*
418  *	struct nlm4_cancargs {
419  *		netobj cookie;
420  *		bool block;
421  *		bool exclusive;
422  *		struct nlm4_lock alock;
423  *	};
424  */
425 static void nlm4_xdr_enc_cancargs(struct rpc_rqst *req,
426 				  struct xdr_stream *xdr,
427 				  const struct nlm_args *args)
428 {
429 	const struct nlm_lock *lock = &args->lock;
430 
431 	encode_cookie(xdr, &args->cookie);
432 	encode_bool(xdr, args->block);
433 	encode_bool(xdr, lock->fl.fl_type == F_WRLCK);
434 	encode_nlm4_lock(xdr, lock);
435 }
436 
437 /*
438  *	struct nlm4_unlockargs {
439  *		netobj cookie;
440  *		struct nlm4_lock alock;
441  *	};
442  */
443 static void nlm4_xdr_enc_unlockargs(struct rpc_rqst *req,
444 				    struct xdr_stream *xdr,
445 				    const struct nlm_args *args)
446 {
447 	const struct nlm_lock *lock = &args->lock;
448 
449 	encode_cookie(xdr, &args->cookie);
450 	encode_nlm4_lock(xdr, lock);
451 }
452 
453 /*
454  *	struct nlm4_res {
455  *		netobj cookie;
456  *		nlm4_stat stat;
457  *	};
458  */
459 static void nlm4_xdr_enc_res(struct rpc_rqst *req,
460 			     struct xdr_stream *xdr,
461 			     const struct nlm_res *result)
462 {
463 	encode_cookie(xdr, &result->cookie);
464 	encode_nlm4_stat(xdr, result->status);
465 }
466 
467 /*
468  *	union nlm4_testrply switch (nlm4_stats stat) {
469  *	case NLM4_DENIED:
470  *		struct nlm4_holder holder;
471  *	default:
472  *		void;
473  *	};
474  *
475  *	struct nlm4_testres {
476  *		netobj cookie;
477  *		nlm4_testrply test_stat;
478  *	};
479  */
480 static void nlm4_xdr_enc_testres(struct rpc_rqst *req,
481 				 struct xdr_stream *xdr,
482 				 const struct nlm_res *result)
483 {
484 	encode_cookie(xdr, &result->cookie);
485 	encode_nlm4_stat(xdr, result->status);
486 	if (result->status == nlm_lck_denied)
487 		encode_nlm4_holder(xdr, result);
488 }
489 
490 
491 /*
492  * NLMv4 XDR decode functions
493  *
494  * NLMv4 argument types are defined in Appendix II of RFC 1813:
495  * "NFS Version 3 Protocol Specification" and Chapter 10 of X/Open's
496  * "Protocols for Interworking: XNFS, Version 3W".
497  */
498 
499 /*
500  *	union nlm4_testrply switch (nlm4_stats stat) {
501  *	case NLM4_DENIED:
502  *		struct nlm4_holder holder;
503  *	default:
504  *		void;
505  *	};
506  *
507  *	struct nlm4_testres {
508  *		netobj cookie;
509  *		nlm4_testrply test_stat;
510  *	};
511  */
512 static int decode_nlm4_testrply(struct xdr_stream *xdr,
513 				struct nlm_res *result)
514 {
515 	int error;
516 
517 	error = decode_nlm4_stat(xdr, &result->status);
518 	if (unlikely(error))
519 		goto out;
520 	if (result->status == nlm_lck_denied)
521 		error = decode_nlm4_holder(xdr, result);
522 out:
523 	return error;
524 }
525 
526 static int nlm4_xdr_dec_testres(struct rpc_rqst *req,
527 				struct xdr_stream *xdr,
528 				struct nlm_res *result)
529 {
530 	int error;
531 
532 	error = decode_cookie(xdr, &result->cookie);
533 	if (unlikely(error))
534 		goto out;
535 	error = decode_nlm4_testrply(xdr, result);
536 out:
537 	return error;
538 }
539 
540 /*
541  *	struct nlm4_res {
542  *		netobj cookie;
543  *		nlm4_stat stat;
544  *	};
545  */
546 static int nlm4_xdr_dec_res(struct rpc_rqst *req,
547 			    struct xdr_stream *xdr,
548 			    struct nlm_res *result)
549 {
550 	int error;
551 
552 	error = decode_cookie(xdr, &result->cookie);
553 	if (unlikely(error))
554 		goto out;
555 	error = decode_nlm4_stat(xdr, &result->status);
556 out:
557 	return error;
558 }
559 
560 
561 /*
562  * For NLM, a void procedure really returns nothing
563  */
564 #define nlm4_xdr_dec_norep	NULL
565 
566 #define PROC(proc, argtype, restype)					\
567 [NLMPROC_##proc] = {							\
568 	.p_proc      = NLMPROC_##proc,					\
569 	.p_encode    = (kxdreproc_t)nlm4_xdr_enc_##argtype,		\
570 	.p_decode    = (kxdrdproc_t)nlm4_xdr_dec_##restype,		\
571 	.p_arglen    = NLM4_##argtype##_sz,				\
572 	.p_replen    = NLM4_##restype##_sz,				\
573 	.p_statidx   = NLMPROC_##proc,					\
574 	.p_name      = #proc,						\
575 	}
576 
577 static struct rpc_procinfo	nlm4_procedures[] = {
578 	PROC(TEST,		testargs,	testres),
579 	PROC(LOCK,		lockargs,	res),
580 	PROC(CANCEL,		cancargs,	res),
581 	PROC(UNLOCK,		unlockargs,	res),
582 	PROC(GRANTED,		testargs,	res),
583 	PROC(TEST_MSG,		testargs,	norep),
584 	PROC(LOCK_MSG,		lockargs,	norep),
585 	PROC(CANCEL_MSG,	cancargs,	norep),
586 	PROC(UNLOCK_MSG,	unlockargs,	norep),
587 	PROC(GRANTED_MSG,	testargs,	norep),
588 	PROC(TEST_RES,		testres,	norep),
589 	PROC(LOCK_RES,		res,		norep),
590 	PROC(CANCEL_RES,	res,		norep),
591 	PROC(UNLOCK_RES,	res,		norep),
592 	PROC(GRANTED_RES,	res,		norep),
593 };
594 
595 const struct rpc_version nlm_version4 = {
596 	.number		= 4,
597 	.nrprocs	= ARRAY_SIZE(nlm4_procedures),
598 	.procs		= nlm4_procedures,
599 };
600