linux/fs/lockd/clnt4xdr.c
<<
>>
Prefs
   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
  52static 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
  65static 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
  89static 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
  97static 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 */
 108static 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
 117static 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 */
 133static 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
 139static 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;
 160out_hpux:
 161        cookie->len = 4;
 162        memset(cookie->data, 0, 4);
 163        return 0;
 164out_size:
 165        dprintk("NFS: returned cookie was too long: %u\n", length);
 166        return -EIO;
 167out_overflow:
 168        return -EIO;
 169}
 170
 171/*
 172 *      netobj fh;
 173 */
 174static 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 */
 201static 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
 211static 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;
 222out_bad_xdr:
 223        dprintk("%s: server returned invalid nlm4_stats value: %u\n",
 224                        __func__, be32_to_cpup(p));
 225        return -EIO;
 226out_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 */
 239static 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
 256static 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;
 296out:
 297        return error;
 298out_overflow:
 299        return -EIO;
 300}
 301
 302/*
 303 *      string caller_name<LM_MAXSTRLEN>;
 304 */
 305static 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 */
 325static 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 */
 359static 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 */
 381static 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 */
 404static 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 */
 423static 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 */
 440static 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 */
 463static 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 */
 497static 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);
 507out:
 508        return error;
 509}
 510
 511static 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);
 522out:
 523        return error;
 524}
 525
 526/*
 527 *      struct nlm4_res {
 528 *              netobj cookie;
 529 *              nlm4_stat stat;
 530 *      };
 531 */
 532static 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);
 543out:
 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
 564static 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
 582static unsigned int nlm_version4_counts[ARRAY_SIZE(nlm4_procedures)];
 583const struct rpc_version nlm_version4 = {
 584        .number         = 4,
 585        .nrprocs        = ARRAY_SIZE(nlm4_procedures),
 586        .procs          = nlm4_procedures,
 587        .counts         = nlm_version4_counts,
 588};
 589