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