root/fs/lockd/clntxdr.c

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

DEFINITIONS

This source file includes following definitions.
  1. loff_t_to_s32
  2. nlm_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_nlm_stat
  11. decode_nlm_stat
  12. encode_nlm_holder
  13. decode_nlm_holder
  14. encode_caller_name
  15. encode_nlm_lock
  16. nlm_xdr_enc_testargs
  17. nlm_xdr_enc_lockargs
  18. nlm_xdr_enc_cancargs
  19. nlm_xdr_enc_unlockargs
  20. nlm_xdr_enc_res
  21. encode_nlm_testrply
  22. nlm_xdr_enc_testres
  23. decode_nlm_testrply
  24. nlm_xdr_dec_testres
  25. nlm_xdr_dec_res

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

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