Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * linux/fs/lockd/clnt4xdr.c
0004  *
0005  * XDR functions to encode/decode NLM version 4 RPC arguments and results.
0006  *
0007  * NLM client-side only.
0008  *
0009  * Copyright (C) 2010, Oracle.  All rights reserved.
0010  */
0011 
0012 #include <linux/types.h>
0013 #include <linux/sunrpc/xdr.h>
0014 #include <linux/sunrpc/clnt.h>
0015 #include <linux/sunrpc/stats.h>
0016 #include <linux/lockd/lockd.h>
0017 
0018 #include <uapi/linux/nfs3.h>
0019 
0020 #define NLMDBG_FACILITY     NLMDBG_XDR
0021 
0022 #if (NLMCLNT_OHSIZE > XDR_MAX_NETOBJ)
0023 #  error "NLM host name cannot be larger than XDR_MAX_NETOBJ!"
0024 #endif
0025 
0026 #if (NLMCLNT_OHSIZE > NLM_MAXSTRLEN)
0027 #  error "NLM host name cannot be larger than NLM's maximum string length!"
0028 #endif
0029 
0030 /*
0031  * Declare the space requirements for NLM arguments and replies as
0032  * number of 32bit-words
0033  */
0034 #define NLM4_void_sz        (0)
0035 #define NLM4_cookie_sz      (1+(NLM_MAXCOOKIELEN>>2))
0036 #define NLM4_caller_sz      (1+(NLMCLNT_OHSIZE>>2))
0037 #define NLM4_owner_sz       (1+(NLMCLNT_OHSIZE>>2))
0038 #define NLM4_fhandle_sz     (1+(NFS3_FHSIZE>>2))
0039 #define NLM4_lock_sz        (5+NLM4_caller_sz+NLM4_owner_sz+NLM4_fhandle_sz)
0040 #define NLM4_holder_sz      (6+NLM4_owner_sz)
0041 
0042 #define NLM4_testargs_sz    (NLM4_cookie_sz+1+NLM4_lock_sz)
0043 #define NLM4_lockargs_sz    (NLM4_cookie_sz+4+NLM4_lock_sz)
0044 #define NLM4_cancargs_sz    (NLM4_cookie_sz+2+NLM4_lock_sz)
0045 #define NLM4_unlockargs_sz  (NLM4_cookie_sz+NLM4_lock_sz)
0046 
0047 #define NLM4_testres_sz     (NLM4_cookie_sz+1+NLM4_holder_sz)
0048 #define NLM4_res_sz     (NLM4_cookie_sz+1)
0049 #define NLM4_norep_sz       (0)
0050 
0051 
0052 static s64 loff_t_to_s64(loff_t offset)
0053 {
0054     s64 res;
0055 
0056     if (offset >= NLM4_OFFSET_MAX)
0057         res = NLM4_OFFSET_MAX;
0058     else if (offset <= -NLM4_OFFSET_MAX)
0059         res = -NLM4_OFFSET_MAX;
0060     else
0061         res = offset;
0062     return res;
0063 }
0064 
0065 static void nlm4_compute_offsets(const struct nlm_lock *lock,
0066                  u64 *l_offset, u64 *l_len)
0067 {
0068     const struct file_lock *fl = &lock->fl;
0069 
0070     *l_offset = loff_t_to_s64(fl->fl_start);
0071     if (fl->fl_end == OFFSET_MAX)
0072         *l_len = 0;
0073     else
0074         *l_len = loff_t_to_s64(fl->fl_end - fl->fl_start + 1);
0075 }
0076 
0077 /*
0078  * Encode/decode NLMv4 basic data types
0079  *
0080  * Basic NLMv4 data types are defined in Appendix II, section 6.1.4
0081  * of RFC 1813: "NFS Version 3 Protocol Specification" and in Chapter
0082  * 10 of X/Open's "Protocols for Interworking: XNFS, Version 3W".
0083  *
0084  * Not all basic data types have their own encoding and decoding
0085  * functions.  For run-time efficiency, some data types are encoded
0086  * or decoded inline.
0087  */
0088 
0089 static void encode_bool(struct xdr_stream *xdr, const int value)
0090 {
0091     __be32 *p;
0092 
0093     p = xdr_reserve_space(xdr, 4);
0094     *p = value ? xdr_one : xdr_zero;
0095 }
0096 
0097 static void encode_int32(struct xdr_stream *xdr, const s32 value)
0098 {
0099     __be32 *p;
0100 
0101     p = xdr_reserve_space(xdr, 4);
0102     *p = cpu_to_be32(value);
0103 }
0104 
0105 /*
0106  *  typedef opaque netobj<MAXNETOBJ_SZ>
0107  */
0108 static void encode_netobj(struct xdr_stream *xdr,
0109               const u8 *data, const unsigned int length)
0110 {
0111     __be32 *p;
0112 
0113     p = xdr_reserve_space(xdr, 4 + length);
0114     xdr_encode_opaque(p, data, length);
0115 }
0116 
0117 static int decode_netobj(struct xdr_stream *xdr,
0118              struct xdr_netobj *obj)
0119 {
0120     ssize_t ret;
0121 
0122     ret = xdr_stream_decode_opaque_inline(xdr, (void *)&obj->data,
0123                         XDR_MAX_NETOBJ);
0124     if (unlikely(ret < 0))
0125         return -EIO;
0126     obj->len = ret;
0127     return 0;
0128 }
0129 
0130 /*
0131  *  netobj cookie;
0132  */
0133 static void encode_cookie(struct xdr_stream *xdr,
0134               const struct nlm_cookie *cookie)
0135 {
0136     encode_netobj(xdr, (u8 *)&cookie->data, cookie->len);
0137 }
0138 
0139 static int decode_cookie(struct xdr_stream *xdr,
0140                  struct nlm_cookie *cookie)
0141 {
0142     u32 length;
0143     __be32 *p;
0144 
0145     p = xdr_inline_decode(xdr, 4);
0146     if (unlikely(p == NULL))
0147         goto out_overflow;
0148     length = be32_to_cpup(p++);
0149     /* apparently HPUX can return empty cookies */
0150     if (length == 0)
0151         goto out_hpux;
0152     if (length > NLM_MAXCOOKIELEN)
0153         goto out_size;
0154     p = xdr_inline_decode(xdr, length);
0155     if (unlikely(p == NULL))
0156         goto out_overflow;
0157     cookie->len = length;
0158     memcpy(cookie->data, p, length);
0159     return 0;
0160 out_hpux:
0161     cookie->len = 4;
0162     memset(cookie->data, 0, 4);
0163     return 0;
0164 out_size:
0165     dprintk("NFS: returned cookie was too long: %u\n", length);
0166     return -EIO;
0167 out_overflow:
0168     return -EIO;
0169 }
0170 
0171 /*
0172  *  netobj fh;
0173  */
0174 static void encode_fh(struct xdr_stream *xdr, const struct nfs_fh *fh)
0175 {
0176     encode_netobj(xdr, (u8 *)&fh->data, fh->size);
0177 }
0178 
0179 /*
0180  *  enum nlm4_stats {
0181  *      NLM4_GRANTED = 0,
0182  *      NLM4_DENIED = 1,
0183  *      NLM4_DENIED_NOLOCKS = 2,
0184  *      NLM4_BLOCKED = 3,
0185  *      NLM4_DENIED_GRACE_PERIOD = 4,
0186  *      NLM4_DEADLCK = 5,
0187  *      NLM4_ROFS = 6,
0188  *      NLM4_STALE_FH = 7,
0189  *      NLM4_FBIG = 8,
0190  *      NLM4_FAILED = 9
0191  *  };
0192  *
0193  *  struct nlm4_stat {
0194  *      nlm4_stats stat;
0195  *  };
0196  *
0197  * NB: we don't swap bytes for the NLM status values.  The upper
0198  * layers deal directly with the status value in network byte
0199  * order.
0200  */
0201 static void encode_nlm4_stat(struct xdr_stream *xdr,
0202                  const __be32 stat)
0203 {
0204     __be32 *p;
0205 
0206     BUG_ON(be32_to_cpu(stat) > NLM_FAILED);
0207     p = xdr_reserve_space(xdr, 4);
0208     *p = stat;
0209 }
0210 
0211 static int decode_nlm4_stat(struct xdr_stream *xdr, __be32 *stat)
0212 {
0213     __be32 *p;
0214 
0215     p = xdr_inline_decode(xdr, 4);
0216     if (unlikely(p == NULL))
0217         goto out_overflow;
0218     if (unlikely(ntohl(*p) > ntohl(nlm4_failed)))
0219         goto out_bad_xdr;
0220     *stat = *p;
0221     return 0;
0222 out_bad_xdr:
0223     dprintk("%s: server returned invalid nlm4_stats value: %u\n",
0224             __func__, be32_to_cpup(p));
0225     return -EIO;
0226 out_overflow:
0227     return -EIO;
0228 }
0229 
0230 /*
0231  *  struct nlm4_holder {
0232  *      bool    exclusive;
0233  *      int32   svid;
0234  *      netobj  oh;
0235  *      uint64  l_offset;
0236  *      uint64  l_len;
0237  *  };
0238  */
0239 static void encode_nlm4_holder(struct xdr_stream *xdr,
0240                    const struct nlm_res *result)
0241 {
0242     const struct nlm_lock *lock = &result->lock;
0243     u64 l_offset, l_len;
0244     __be32 *p;
0245 
0246     encode_bool(xdr, lock->fl.fl_type == F_RDLCK);
0247     encode_int32(xdr, lock->svid);
0248     encode_netobj(xdr, lock->oh.data, lock->oh.len);
0249 
0250     p = xdr_reserve_space(xdr, 4 + 4);
0251     nlm4_compute_offsets(lock, &l_offset, &l_len);
0252     p = xdr_encode_hyper(p, l_offset);
0253     xdr_encode_hyper(p, l_len);
0254 }
0255 
0256 static int decode_nlm4_holder(struct xdr_stream *xdr, struct nlm_res *result)
0257 {
0258     struct nlm_lock *lock = &result->lock;
0259     struct file_lock *fl = &lock->fl;
0260     u64 l_offset, l_len;
0261     u32 exclusive;
0262     int error;
0263     __be32 *p;
0264     s32 end;
0265 
0266     memset(lock, 0, sizeof(*lock));
0267     locks_init_lock(fl);
0268 
0269     p = xdr_inline_decode(xdr, 4 + 4);
0270     if (unlikely(p == NULL))
0271         goto out_overflow;
0272     exclusive = be32_to_cpup(p++);
0273     lock->svid = be32_to_cpup(p);
0274     fl->fl_pid = (pid_t)lock->svid;
0275 
0276     error = decode_netobj(xdr, &lock->oh);
0277     if (unlikely(error))
0278         goto out;
0279 
0280     p = xdr_inline_decode(xdr, 8 + 8);
0281     if (unlikely(p == NULL))
0282         goto out_overflow;
0283 
0284     fl->fl_flags = FL_POSIX;
0285     fl->fl_type  = exclusive != 0 ? F_WRLCK : F_RDLCK;
0286     p = xdr_decode_hyper(p, &l_offset);
0287     xdr_decode_hyper(p, &l_len);
0288     end = l_offset + l_len - 1;
0289 
0290     fl->fl_start = (loff_t)l_offset;
0291     if (l_len == 0 || end < 0)
0292         fl->fl_end = OFFSET_MAX;
0293     else
0294         fl->fl_end = (loff_t)end;
0295     error = 0;
0296 out:
0297     return error;
0298 out_overflow:
0299     return -EIO;
0300 }
0301 
0302 /*
0303  *  string caller_name<LM_MAXSTRLEN>;
0304  */
0305 static void encode_caller_name(struct xdr_stream *xdr, const char *name)
0306 {
0307     /* NB: client-side does not set lock->len */
0308     u32 length = strlen(name);
0309     __be32 *p;
0310 
0311     p = xdr_reserve_space(xdr, 4 + length);
0312     xdr_encode_opaque(p, name, length);
0313 }
0314 
0315 /*
0316  *  struct nlm4_lock {
0317  *      string  caller_name<LM_MAXSTRLEN>;
0318  *      netobj  fh;
0319  *      netobj  oh;
0320  *      int32   svid;
0321  *      uint64  l_offset;
0322  *      uint64  l_len;
0323  *  };
0324  */
0325 static void encode_nlm4_lock(struct xdr_stream *xdr,
0326                  const struct nlm_lock *lock)
0327 {
0328     u64 l_offset, l_len;
0329     __be32 *p;
0330 
0331     encode_caller_name(xdr, lock->caller);
0332     encode_fh(xdr, &lock->fh);
0333     encode_netobj(xdr, lock->oh.data, lock->oh.len);
0334 
0335     p = xdr_reserve_space(xdr, 4 + 8 + 8);
0336     *p++ = cpu_to_be32(lock->svid);
0337 
0338     nlm4_compute_offsets(lock, &l_offset, &l_len);
0339     p = xdr_encode_hyper(p, l_offset);
0340     xdr_encode_hyper(p, l_len);
0341 }
0342 
0343 
0344 /*
0345  * NLMv4 XDR encode functions
0346  *
0347  * NLMv4 argument types are defined in Appendix II of RFC 1813:
0348  * "NFS Version 3 Protocol Specification" and Chapter 10 of X/Open's
0349  * "Protocols for Interworking: XNFS, Version 3W".
0350  */
0351 
0352 /*
0353  *  struct nlm4_testargs {
0354  *      netobj cookie;
0355  *      bool exclusive;
0356  *      struct nlm4_lock alock;
0357  *  };
0358  */
0359 static void nlm4_xdr_enc_testargs(struct rpc_rqst *req,
0360                   struct xdr_stream *xdr,
0361                   const void *data)
0362 {
0363     const struct nlm_args *args = data;
0364     const struct nlm_lock *lock = &args->lock;
0365 
0366     encode_cookie(xdr, &args->cookie);
0367     encode_bool(xdr, lock->fl.fl_type == F_WRLCK);
0368     encode_nlm4_lock(xdr, lock);
0369 }
0370 
0371 /*
0372  *  struct nlm4_lockargs {
0373  *      netobj cookie;
0374  *      bool block;
0375  *      bool exclusive;
0376  *      struct nlm4_lock alock;
0377  *      bool reclaim;
0378  *      int state;
0379  *  };
0380  */
0381 static void nlm4_xdr_enc_lockargs(struct rpc_rqst *req,
0382                   struct xdr_stream *xdr,
0383                   const void *data)
0384 {
0385     const struct nlm_args *args = data;
0386     const struct nlm_lock *lock = &args->lock;
0387 
0388     encode_cookie(xdr, &args->cookie);
0389     encode_bool(xdr, args->block);
0390     encode_bool(xdr, lock->fl.fl_type == F_WRLCK);
0391     encode_nlm4_lock(xdr, lock);
0392     encode_bool(xdr, args->reclaim);
0393     encode_int32(xdr, args->state);
0394 }
0395 
0396 /*
0397  *  struct nlm4_cancargs {
0398  *      netobj cookie;
0399  *      bool block;
0400  *      bool exclusive;
0401  *      struct nlm4_lock alock;
0402  *  };
0403  */
0404 static void nlm4_xdr_enc_cancargs(struct rpc_rqst *req,
0405                   struct xdr_stream *xdr,
0406                   const void *data)
0407 {
0408     const struct nlm_args *args = data;
0409     const struct nlm_lock *lock = &args->lock;
0410 
0411     encode_cookie(xdr, &args->cookie);
0412     encode_bool(xdr, args->block);
0413     encode_bool(xdr, lock->fl.fl_type == F_WRLCK);
0414     encode_nlm4_lock(xdr, lock);
0415 }
0416 
0417 /*
0418  *  struct nlm4_unlockargs {
0419  *      netobj cookie;
0420  *      struct nlm4_lock alock;
0421  *  };
0422  */
0423 static void nlm4_xdr_enc_unlockargs(struct rpc_rqst *req,
0424                     struct xdr_stream *xdr,
0425                     const void *data)
0426 {
0427     const struct nlm_args *args = data;
0428     const struct nlm_lock *lock = &args->lock;
0429 
0430     encode_cookie(xdr, &args->cookie);
0431     encode_nlm4_lock(xdr, lock);
0432 }
0433 
0434 /*
0435  *  struct nlm4_res {
0436  *      netobj cookie;
0437  *      nlm4_stat stat;
0438  *  };
0439  */
0440 static void nlm4_xdr_enc_res(struct rpc_rqst *req,
0441                  struct xdr_stream *xdr,
0442                  const void *data)
0443 {
0444     const struct nlm_res *result = data;
0445 
0446     encode_cookie(xdr, &result->cookie);
0447     encode_nlm4_stat(xdr, result->status);
0448 }
0449 
0450 /*
0451  *  union nlm4_testrply switch (nlm4_stats stat) {
0452  *  case NLM4_DENIED:
0453  *      struct nlm4_holder holder;
0454  *  default:
0455  *      void;
0456  *  };
0457  *
0458  *  struct nlm4_testres {
0459  *      netobj cookie;
0460  *      nlm4_testrply test_stat;
0461  *  };
0462  */
0463 static void nlm4_xdr_enc_testres(struct rpc_rqst *req,
0464                  struct xdr_stream *xdr,
0465                  const void *data)
0466 {
0467     const struct nlm_res *result = data;
0468 
0469     encode_cookie(xdr, &result->cookie);
0470     encode_nlm4_stat(xdr, result->status);
0471     if (result->status == nlm_lck_denied)
0472         encode_nlm4_holder(xdr, result);
0473 }
0474 
0475 
0476 /*
0477  * NLMv4 XDR decode functions
0478  *
0479  * NLMv4 argument types are defined in Appendix II of RFC 1813:
0480  * "NFS Version 3 Protocol Specification" and Chapter 10 of X/Open's
0481  * "Protocols for Interworking: XNFS, Version 3W".
0482  */
0483 
0484 /*
0485  *  union nlm4_testrply switch (nlm4_stats stat) {
0486  *  case NLM4_DENIED:
0487  *      struct nlm4_holder holder;
0488  *  default:
0489  *      void;
0490  *  };
0491  *
0492  *  struct nlm4_testres {
0493  *      netobj cookie;
0494  *      nlm4_testrply test_stat;
0495  *  };
0496  */
0497 static int decode_nlm4_testrply(struct xdr_stream *xdr,
0498                 struct nlm_res *result)
0499 {
0500     int error;
0501 
0502     error = decode_nlm4_stat(xdr, &result->status);
0503     if (unlikely(error))
0504         goto out;
0505     if (result->status == nlm_lck_denied)
0506         error = decode_nlm4_holder(xdr, result);
0507 out:
0508     return error;
0509 }
0510 
0511 static int nlm4_xdr_dec_testres(struct rpc_rqst *req,
0512                 struct xdr_stream *xdr,
0513                 void *data)
0514 {
0515     struct nlm_res *result = data;
0516     int error;
0517 
0518     error = decode_cookie(xdr, &result->cookie);
0519     if (unlikely(error))
0520         goto out;
0521     error = decode_nlm4_testrply(xdr, result);
0522 out:
0523     return error;
0524 }
0525 
0526 /*
0527  *  struct nlm4_res {
0528  *      netobj cookie;
0529  *      nlm4_stat stat;
0530  *  };
0531  */
0532 static int nlm4_xdr_dec_res(struct rpc_rqst *req,
0533                 struct xdr_stream *xdr,
0534                 void *data)
0535 {
0536     struct nlm_res *result = data;
0537     int error;
0538 
0539     error = decode_cookie(xdr, &result->cookie);
0540     if (unlikely(error))
0541         goto out;
0542     error = decode_nlm4_stat(xdr, &result->status);
0543 out:
0544     return error;
0545 }
0546 
0547 
0548 /*
0549  * For NLM, a void procedure really returns nothing
0550  */
0551 #define nlm4_xdr_dec_norep  NULL
0552 
0553 #define PROC(proc, argtype, restype)                    \
0554 [NLMPROC_##proc] = {                            \
0555     .p_proc      = NLMPROC_##proc,                  \
0556     .p_encode    = nlm4_xdr_enc_##argtype,              \
0557     .p_decode    = nlm4_xdr_dec_##restype,              \
0558     .p_arglen    = NLM4_##argtype##_sz,             \
0559     .p_replen    = NLM4_##restype##_sz,             \
0560     .p_statidx   = NLMPROC_##proc,                  \
0561     .p_name      = #proc,                       \
0562     }
0563 
0564 static const struct rpc_procinfo nlm4_procedures[] = {
0565     PROC(TEST,      testargs,   testres),
0566     PROC(LOCK,      lockargs,   res),
0567     PROC(CANCEL,        cancargs,   res),
0568     PROC(UNLOCK,        unlockargs, res),
0569     PROC(GRANTED,       testargs,   res),
0570     PROC(TEST_MSG,      testargs,   norep),
0571     PROC(LOCK_MSG,      lockargs,   norep),
0572     PROC(CANCEL_MSG,    cancargs,   norep),
0573     PROC(UNLOCK_MSG,    unlockargs, norep),
0574     PROC(GRANTED_MSG,   testargs,   norep),
0575     PROC(TEST_RES,      testres,    norep),
0576     PROC(LOCK_RES,      res,        norep),
0577     PROC(CANCEL_RES,    res,        norep),
0578     PROC(UNLOCK_RES,    res,        norep),
0579     PROC(GRANTED_RES,   res,        norep),
0580 };
0581 
0582 static unsigned int nlm_version4_counts[ARRAY_SIZE(nlm4_procedures)];
0583 const struct rpc_version nlm_version4 = {
0584     .number     = 4,
0585     .nrprocs    = ARRAY_SIZE(nlm4_procedures),
0586     .procs      = nlm4_procedures,
0587     .counts     = nlm_version4_counts,
0588 };