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