linux-old/fs/lockd/xdr4.c
<<
>>
Prefs
   1/*
   2 * linux/fs/lockd/xdr4.c
   3 *
   4 * XDR support for lockd and the lock client.
   5 *
   6 * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de>
   7 * Copyright (C) 1999, Trond Myklebust <trond.myklebust@fys.uio.no>
   8 */
   9
  10#include <linux/types.h>
  11#include <linux/sched.h>
  12#include <linux/utsname.h>
  13#include <linux/nfs.h>
  14
  15#include <linux/sunrpc/xdr.h>
  16#include <linux/sunrpc/clnt.h>
  17#include <linux/sunrpc/svc.h>
  18#include <linux/sunrpc/stats.h>
  19#include <linux/lockd/lockd.h>
  20#include <linux/lockd/sm_inter.h>
  21
  22#define NLMDBG_FACILITY         NLMDBG_XDR
  23
  24static inline loff_t
  25s64_to_loff_t(__s64 offset)
  26{
  27        return (loff_t)offset;
  28}
  29
  30
  31static inline s64
  32loff_t_to_s64(loff_t offset)
  33{
  34        s64 res;
  35        if (offset > NLM4_OFFSET_MAX)
  36                res = NLM4_OFFSET_MAX;
  37        else if (offset < -NLM4_OFFSET_MAX)
  38                res = -NLM4_OFFSET_MAX;
  39        else
  40                res = offset;
  41        return res;
  42}
  43
  44/*
  45 * XDR functions for basic NLM types
  46 */
  47static u32 *
  48nlm4_decode_cookie(u32 *p, struct nlm_cookie *c)
  49{
  50        unsigned int    len;
  51
  52        len = ntohl(*p++);
  53        
  54        if(len==0)
  55        {
  56                c->len=4;
  57                memset(c->data, 0, 4);  /* hockeypux brain damage */
  58        }
  59        else if(len<=NLM_MAXCOOKIELEN)
  60        {
  61                c->len=len;
  62                memcpy(c->data, p, len);
  63                p+=(len+3)>>2;
  64        }
  65        else 
  66        {
  67                printk(KERN_NOTICE
  68                        "lockd: bad cookie size %d (only cookies under %d bytes are supported.)\n", len, NLM_MAXCOOKIELEN);
  69                return NULL;
  70        }
  71        return p;
  72}
  73
  74static u32 *
  75nlm4_encode_cookie(u32 *p, struct nlm_cookie *c)
  76{
  77        *p++ = htonl(c->len);
  78        memcpy(p, c->data, c->len);
  79        p+=(c->len+3)>>2;
  80        return p;
  81}
  82
  83static u32 *
  84nlm4_decode_fh(u32 *p, struct nfs_fh *f)
  85{
  86        memset(f->data, 0, sizeof(f->data));
  87        f->size = ntohl(*p++);
  88        if (f->size > NFS_MAXFHSIZE) {
  89                printk(KERN_NOTICE
  90                        "lockd: bad fhandle size %d (should be <=%d)\n",
  91                        f->size, NFS_MAXFHSIZE);
  92                return NULL;
  93        }
  94        memcpy(f->data, p, f->size);
  95        return p + XDR_QUADLEN(f->size);
  96}
  97
  98static u32 *
  99nlm4_encode_fh(u32 *p, struct nfs_fh *f)
 100{
 101        *p++ = htonl(f->size);
 102        if (f->size) p[XDR_QUADLEN(f->size)-1] = 0; /* don't leak anything */
 103        memcpy(p, f->data, f->size);
 104        return p + XDR_QUADLEN(f->size);
 105}
 106
 107/*
 108 * Encode and decode owner handle
 109 */
 110static u32 *
 111nlm4_decode_oh(u32 *p, struct xdr_netobj *oh)
 112{
 113        return xdr_decode_netobj(p, oh);
 114}
 115
 116static u32 *
 117nlm4_encode_oh(u32 *p, struct xdr_netobj *oh)
 118{
 119        return xdr_encode_netobj(p, oh);
 120}
 121
 122static u32 *
 123nlm4_decode_lock(u32 *p, struct nlm_lock *lock)
 124{
 125        struct file_lock        *fl = &lock->fl;
 126        __s64                   len, start, end;
 127
 128        if (!(p = xdr_decode_string_inplace(p, &lock->caller,
 129                                            &lock->len, NLM_MAXSTRLEN))
 130         || !(p = nlm4_decode_fh(p, &lock->fh))
 131         || !(p = nlm4_decode_oh(p, &lock->oh)))
 132                return NULL;
 133
 134        locks_init_lock(fl);
 135        fl->fl_owner = current->files;
 136        fl->fl_pid   = ntohl(*p++);
 137        fl->fl_flags = FL_POSIX;
 138        fl->fl_type  = F_RDLCK;         /* as good as anything else */
 139        p = xdr_decode_hyper(p, &start);
 140        p = xdr_decode_hyper(p, &len);
 141        end = start + len - 1;
 142
 143        fl->fl_start = s64_to_loff_t(start);
 144
 145        if (len == 0 || end < 0)
 146                fl->fl_end = OFFSET_MAX;
 147        else
 148                fl->fl_end = s64_to_loff_t(end);
 149        return p;
 150}
 151
 152/*
 153 * Encode a lock as part of an NLM call
 154 */
 155static u32 *
 156nlm4_encode_lock(u32 *p, struct nlm_lock *lock)
 157{
 158        struct file_lock        *fl = &lock->fl;
 159        __s64                   start, len;
 160
 161        if (!(p = xdr_encode_string(p, lock->caller))
 162         || !(p = nlm4_encode_fh(p, &lock->fh))
 163         || !(p = nlm4_encode_oh(p, &lock->oh)))
 164                return NULL;
 165
 166        if (fl->fl_start > NLM4_OFFSET_MAX
 167         || (fl->fl_end > NLM4_OFFSET_MAX && fl->fl_end != OFFSET_MAX))
 168                return NULL;
 169
 170        *p++ = htonl(fl->fl_pid);
 171
 172        start = loff_t_to_s64(fl->fl_start);
 173        if (fl->fl_end == OFFSET_MAX)
 174                len = 0;
 175        else
 176                len = loff_t_to_s64(fl->fl_end - fl->fl_start + 1);
 177
 178        p = xdr_encode_hyper(p, start);
 179        p = xdr_encode_hyper(p, len);
 180
 181        return p;
 182}
 183
 184/*
 185 * Encode result of a TEST/TEST_MSG call
 186 */
 187static u32 *
 188nlm4_encode_testres(u32 *p, struct nlm_res *resp)
 189{
 190        s64             start, len;
 191
 192        dprintk("xdr: before encode_testres (p %p resp %p)\n", p, resp);
 193        if (!(p = nlm4_encode_cookie(p, &resp->cookie)))
 194                return 0;
 195        *p++ = resp->status;
 196
 197        if (resp->status == nlm_lck_denied) {
 198                struct file_lock        *fl = &resp->lock.fl;
 199
 200                *p++ = (fl->fl_type == F_RDLCK)? xdr_zero : xdr_one;
 201                *p++ = htonl(fl->fl_pid);
 202
 203                /* Encode owner handle. */
 204                if (!(p = xdr_encode_netobj(p, &resp->lock.oh)))
 205                        return 0;
 206
 207                start = loff_t_to_s64(fl->fl_start);
 208                if (fl->fl_end == OFFSET_MAX)
 209                        len = 0;
 210                else
 211                        len = loff_t_to_s64(fl->fl_end - fl->fl_start + 1);
 212                
 213                p = xdr_encode_hyper(p, start);
 214                p = xdr_encode_hyper(p, len);
 215                dprintk("xdr: encode_testres (status %d pid %d type %d start %Ld end %Ld)\n",
 216                        resp->status, fl->fl_pid, fl->fl_type,
 217                        (long long)fl->fl_start,  (long long)fl->fl_end);
 218        }
 219
 220        dprintk("xdr: after encode_testres (p %p resp %p)\n", p, resp);
 221        return p;
 222}
 223
 224
 225/*
 226 * Check buffer bounds after decoding arguments
 227 */
 228static int
 229xdr_argsize_check(struct svc_rqst *rqstp, u32 *p)
 230{
 231        struct svc_buf  *buf = &rqstp->rq_argbuf;
 232
 233        return p - buf->base <= buf->buflen;
 234}
 235
 236static int
 237xdr_ressize_check(struct svc_rqst *rqstp, u32 *p)
 238{
 239        struct svc_buf  *buf = &rqstp->rq_resbuf;
 240
 241        buf->len = p - buf->base;
 242        return (buf->len <= buf->buflen);
 243}
 244
 245/*
 246 * First, the server side XDR functions
 247 */
 248int
 249nlm4svc_decode_testargs(struct svc_rqst *rqstp, u32 *p, nlm_args *argp)
 250{
 251        u32     exclusive;
 252
 253        if (!(p = nlm4_decode_cookie(p, &argp->cookie)))
 254                return 0;
 255
 256        exclusive = ntohl(*p++);
 257        if (!(p = nlm4_decode_lock(p, &argp->lock)))
 258                return 0;
 259        if (exclusive)
 260                argp->lock.fl.fl_type = F_WRLCK;
 261
 262        return xdr_argsize_check(rqstp, p);
 263}
 264
 265int
 266nlm4svc_encode_testres(struct svc_rqst *rqstp, u32 *p, struct nlm_res *resp)
 267{
 268        if (!(p = nlm4_encode_testres(p, resp)))
 269                return 0;
 270        return xdr_ressize_check(rqstp, p);
 271}
 272
 273int
 274nlm4svc_decode_lockargs(struct svc_rqst *rqstp, u32 *p, nlm_args *argp)
 275{
 276        u32     exclusive;
 277
 278        if (!(p = nlm4_decode_cookie(p, &argp->cookie)))
 279                return 0;
 280        argp->block  = ntohl(*p++);
 281        exclusive    = ntohl(*p++);
 282        if (!(p = nlm4_decode_lock(p, &argp->lock)))
 283                return 0;
 284        if (exclusive)
 285                argp->lock.fl.fl_type = F_WRLCK;
 286        argp->reclaim = ntohl(*p++);
 287        argp->state   = ntohl(*p++);
 288        argp->monitor = 1;              /* monitor client by default */
 289
 290        return xdr_argsize_check(rqstp, p);
 291}
 292
 293int
 294nlm4svc_decode_cancargs(struct svc_rqst *rqstp, u32 *p, nlm_args *argp)
 295{
 296        u32     exclusive;
 297
 298        if (!(p = nlm4_decode_cookie(p, &argp->cookie)))
 299                return 0;
 300        argp->block = ntohl(*p++);
 301        exclusive = ntohl(*p++);
 302        if (!(p = nlm4_decode_lock(p, &argp->lock)))
 303                return 0;
 304        if (exclusive)
 305                argp->lock.fl.fl_type = F_WRLCK;
 306        return xdr_argsize_check(rqstp, p);
 307}
 308
 309int
 310nlm4svc_decode_unlockargs(struct svc_rqst *rqstp, u32 *p, nlm_args *argp)
 311{
 312        if (!(p = nlm4_decode_cookie(p, &argp->cookie))
 313         || !(p = nlm4_decode_lock(p, &argp->lock)))
 314                return 0;
 315        argp->lock.fl.fl_type = F_UNLCK;
 316        return xdr_argsize_check(rqstp, p);
 317}
 318
 319int
 320nlm4svc_decode_shareargs(struct svc_rqst *rqstp, u32 *p, nlm_args *argp)
 321{
 322        struct nlm_lock *lock = &argp->lock;
 323
 324        memset(lock, 0, sizeof(*lock));
 325        locks_init_lock(&lock->fl);
 326        lock->fl.fl_pid = ~(u32) 0;
 327
 328        if (!(p = nlm4_decode_cookie(p, &argp->cookie))
 329         || !(p = xdr_decode_string_inplace(p, &lock->caller,
 330                                            &lock->len, NLM_MAXSTRLEN))
 331         || !(p = nlm4_decode_fh(p, &lock->fh))
 332         || !(p = nlm4_decode_oh(p, &lock->oh)))
 333                return 0;
 334        argp->fsm_mode = ntohl(*p++);
 335        argp->fsm_access = ntohl(*p++);
 336        return xdr_argsize_check(rqstp, p);
 337}
 338
 339int
 340nlm4svc_encode_shareres(struct svc_rqst *rqstp, u32 *p, struct nlm_res *resp)
 341{
 342        if (!(p = nlm4_encode_cookie(p, &resp->cookie)))
 343                return 0;
 344        *p++ = resp->status;
 345        *p++ = xdr_zero;                /* sequence argument */
 346        return xdr_ressize_check(rqstp, p);
 347}
 348
 349int
 350nlm4svc_encode_res(struct svc_rqst *rqstp, u32 *p, struct nlm_res *resp)
 351{
 352        if (!(p = nlm4_encode_cookie(p, &resp->cookie)))
 353                return 0;
 354        *p++ = resp->status;
 355        return xdr_ressize_check(rqstp, p);
 356}
 357
 358int
 359nlm4svc_decode_notify(struct svc_rqst *rqstp, u32 *p, struct nlm_args *argp)
 360{
 361        struct nlm_lock *lock = &argp->lock;
 362
 363        if (!(p = xdr_decode_string_inplace(p, &lock->caller,
 364                                            &lock->len, NLM_MAXSTRLEN)))
 365                return 0;
 366        argp->state = ntohl(*p++);
 367        return xdr_argsize_check(rqstp, p);
 368}
 369
 370int
 371nlm4svc_decode_reboot(struct svc_rqst *rqstp, u32 *p, struct nlm_reboot *argp)
 372{
 373        if (!(p = xdr_decode_string_inplace(p, &argp->mon, &argp->len, SM_MAXSTRLEN)))
 374                return 0;
 375        argp->state = ntohl(*p++);
 376        /* Preserve the address in network byte order */
 377        argp->addr = *p++;
 378        return xdr_argsize_check(rqstp, p);
 379}
 380
 381int
 382nlm4svc_decode_res(struct svc_rqst *rqstp, u32 *p, struct nlm_res *resp)
 383{
 384        if (!(p = nlm4_decode_cookie(p, &resp->cookie)))
 385                return 0;
 386        resp->status = ntohl(*p++);
 387        return xdr_argsize_check(rqstp, p);
 388}
 389
 390int
 391nlm4svc_decode_void(struct svc_rqst *rqstp, u32 *p, void *dummy)
 392{
 393        return xdr_argsize_check(rqstp, p);
 394}
 395
 396int
 397nlm4svc_encode_void(struct svc_rqst *rqstp, u32 *p, void *dummy)
 398{
 399        return xdr_ressize_check(rqstp, p);
 400}
 401
 402/*
 403 * Now, the client side XDR functions
 404 */
 405static int
 406nlm4clt_encode_void(struct rpc_rqst *req, u32 *p, void *ptr)
 407{
 408        req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
 409        return 0;
 410}
 411
 412static int
 413nlm4clt_decode_void(struct rpc_rqst *req, u32 *p, void *ptr)
 414{
 415        return 0;
 416}
 417
 418static int
 419nlm4clt_encode_testargs(struct rpc_rqst *req, u32 *p, nlm_args *argp)
 420{
 421        struct nlm_lock *lock = &argp->lock;
 422
 423        if (!(p = nlm4_encode_cookie(p, &argp->cookie)))
 424                return -EIO;
 425        *p++ = (lock->fl.fl_type == F_WRLCK)? xdr_one : xdr_zero;
 426        if (!(p = nlm4_encode_lock(p, lock)))
 427                return -EIO;
 428        req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
 429        return 0;
 430}
 431
 432static int
 433nlm4clt_decode_testres(struct rpc_rqst *req, u32 *p, struct nlm_res *resp)
 434{
 435        if (!(p = nlm4_decode_cookie(p, &resp->cookie)))
 436                return -EIO;
 437        resp->status = ntohl(*p++);
 438        if (resp->status == NLM_LCK_DENIED) {
 439                struct file_lock        *fl = &resp->lock.fl;
 440                u32                     excl;
 441                s64                     start, end, len;
 442
 443                memset(&resp->lock, 0, sizeof(resp->lock));
 444                locks_init_lock(fl);
 445                excl = ntohl(*p++);
 446                fl->fl_pid = ntohl(*p++);
 447                if (!(p = nlm4_decode_oh(p, &resp->lock.oh)))
 448                        return -EIO;
 449
 450                fl->fl_flags = FL_POSIX;
 451                fl->fl_type  = excl? F_WRLCK : F_RDLCK;
 452                p = xdr_decode_hyper(p, &start);
 453                p = xdr_decode_hyper(p, &len);
 454                end = start + len - 1;
 455
 456                fl->fl_start = s64_to_loff_t(start);
 457                if (len == 0 || end < 0)
 458                        fl->fl_end = OFFSET_MAX;
 459                else
 460                        fl->fl_end = s64_to_loff_t(end);
 461        }
 462        return 0;
 463}
 464
 465
 466static int
 467nlm4clt_encode_lockargs(struct rpc_rqst *req, u32 *p, nlm_args *argp)
 468{
 469        struct nlm_lock *lock = &argp->lock;
 470
 471        if (!(p = nlm4_encode_cookie(p, &argp->cookie)))
 472                return -EIO;
 473        *p++ = argp->block? xdr_one : xdr_zero;
 474        *p++ = (lock->fl.fl_type == F_WRLCK)? xdr_one : xdr_zero;
 475        if (!(p = nlm4_encode_lock(p, lock)))
 476                return -EIO;
 477        *p++ = argp->reclaim? xdr_one : xdr_zero;
 478        *p++ = htonl(argp->state);
 479        req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
 480        return 0;
 481}
 482
 483static int
 484nlm4clt_encode_cancargs(struct rpc_rqst *req, u32 *p, nlm_args *argp)
 485{
 486        struct nlm_lock *lock = &argp->lock;
 487
 488        if (!(p = nlm4_encode_cookie(p, &argp->cookie)))
 489                return -EIO;
 490        *p++ = argp->block? xdr_one : xdr_zero;
 491        *p++ = (lock->fl.fl_type == F_WRLCK)? xdr_one : xdr_zero;
 492        if (!(p = nlm4_encode_lock(p, lock)))
 493                return -EIO;
 494        req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
 495        return 0;
 496}
 497
 498static int
 499nlm4clt_encode_unlockargs(struct rpc_rqst *req, u32 *p, nlm_args *argp)
 500{
 501        struct nlm_lock *lock = &argp->lock;
 502
 503        if (!(p = nlm4_encode_cookie(p, &argp->cookie)))
 504                return -EIO;
 505        if (!(p = nlm4_encode_lock(p, lock)))
 506                return -EIO;
 507        req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
 508        return 0;
 509}
 510
 511static int
 512nlm4clt_encode_res(struct rpc_rqst *req, u32 *p, struct nlm_res *resp)
 513{
 514        if (!(p = nlm4_encode_cookie(p, &resp->cookie)))
 515                return -EIO;
 516        *p++ = resp->status;
 517        req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
 518        return 0;
 519}
 520
 521static int
 522nlm4clt_encode_testres(struct rpc_rqst *req, u32 *p, struct nlm_res *resp)
 523{
 524        if (!(p = nlm4_encode_testres(p, resp)))
 525                return -EIO;
 526        req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
 527        return 0;
 528}
 529
 530static int
 531nlm4clt_decode_res(struct rpc_rqst *req, u32 *p, struct nlm_res *resp)
 532{
 533        if (!(p = nlm4_decode_cookie(p, &resp->cookie)))
 534                return -EIO;
 535        resp->status = ntohl(*p++);
 536        return 0;
 537}
 538
 539/*
 540 * Buffer requirements for NLM
 541 */
 542#define NLM4_void_sz            0
 543#define NLM4_cookie_sz          1+XDR_QUADLEN(NLM_MAXCOOKIELEN)
 544#define NLM4_caller_sz          1+XDR_QUADLEN(NLM_MAXSTRLEN)
 545#define NLM4_netobj_sz          1+XDR_QUADLEN(XDR_MAX_NETOBJ)
 546/* #define NLM4_owner_sz                1+XDR_QUADLEN(NLM4_MAXOWNER) */
 547#define NLM4_fhandle_sz         1+XDR_QUADLEN(NFS3_FHSIZE)
 548#define NLM4_lock_sz            5+NLM4_caller_sz+NLM4_netobj_sz+NLM4_fhandle_sz
 549#define NLM4_holder_sz          6+NLM4_netobj_sz
 550
 551#define NLM4_testargs_sz        NLM4_cookie_sz+1+NLM4_lock_sz
 552#define NLM4_lockargs_sz        NLM4_cookie_sz+4+NLM4_lock_sz
 553#define NLM4_cancargs_sz        NLM4_cookie_sz+2+NLM4_lock_sz
 554#define NLM4_unlockargs_sz      NLM4_cookie_sz+NLM4_lock_sz
 555
 556#define NLM4_testres_sz         NLM4_cookie_sz+1+NLM4_holder_sz
 557#define NLM4_res_sz             NLM4_cookie_sz+1
 558#define NLM4_norep_sz           0
 559
 560#ifndef MAX
 561# define MAX(a,b)               (((a) > (b))? (a) : (b))
 562#endif
 563
 564/*
 565 * For NLM, a void procedure really returns nothing
 566 */
 567#define nlm4clt_decode_norep    NULL
 568
 569#define PROC(proc, argtype, restype)                                    \
 570    { .p_procname  = "nlm4_" #proc,                                     \
 571      .p_encode    = (kxdrproc_t) nlm4clt_encode_##argtype,             \
 572      .p_decode    = (kxdrproc_t) nlm4clt_decode_##restype,             \
 573      .p_bufsiz    = MAX(NLM4_##argtype##_sz, NLM4_##restype##_sz) << 2 \
 574    }
 575
 576static struct rpc_procinfo      nlm4_procedures[] = {
 577    PROC(null,          void,           void),
 578    PROC(test,          testargs,       testres),
 579    PROC(lock,          lockargs,       res),
 580    PROC(canc,          cancargs,       res),
 581    PROC(unlock,        unlockargs,     res),
 582    PROC(granted,       testargs,       res),
 583    PROC(test_msg,      testargs,       norep),
 584    PROC(lock_msg,      lockargs,       norep),
 585    PROC(canc_msg,      cancargs,       norep),
 586    PROC(unlock_msg,    unlockargs,     norep),
 587    PROC(granted_msg,   testargs,       norep),
 588    PROC(test_res,      testres,        norep),
 589    PROC(lock_res,      res,            norep),
 590    PROC(canc_res,      res,            norep),
 591    PROC(unlock_res,    res,            norep),
 592    PROC(granted_res,   res,            norep),
 593    PROC(undef,         void,           void),
 594    PROC(undef,         void,           void),
 595    PROC(undef,         void,           void),
 596    PROC(undef,         void,           void),
 597#ifdef NLMCLNT_SUPPORT_SHARES
 598    PROC(share,         shareargs,      shareres),
 599    PROC(unshare,       shareargs,      shareres),
 600    PROC(nm_lock,       lockargs,       res),
 601    PROC(free_all,      notify,         void),
 602#else
 603    PROC(undef,         void,           void),
 604    PROC(undef,         void,           void),
 605    PROC(undef,         void,           void),
 606    PROC(undef,         void,           void),
 607#endif
 608};
 609
 610struct rpc_version      nlm_version4 = {
 611        4, 24, nlm4_procedures,
 612};
 613
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.