root/fs/lockd/clnt4xdr.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. loff_t_to_s64
  2. nlm4_compute_offsets
  3. encode_bool
  4. encode_int32
  5. encode_netobj
  6. decode_netobj
  7. encode_cookie
  8. decode_cookie
  9. encode_fh
  10. encode_nlm4_stat
  11. decode_nlm4_stat
  12. encode_nlm4_holder
  13. decode_nlm4_holder
  14. encode_caller_name
  15. encode_nlm4_lock
  16. nlm4_xdr_enc_testargs
  17. nlm4_xdr_enc_lockargs
  18. nlm4_xdr_enc_cancargs
  19. nlm4_xdr_enc_unlockargs
  20. nlm4_xdr_enc_res
  21. nlm4_xdr_enc_testres
  22. decode_nlm4_testrply
  23. nlm4_xdr_dec_testres
  24. nlm4_xdr_dec_res

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

/* [<][>][^][v][top][bottom][index][help] */