linux/fs/lockd/xdr.c
<<
>>
Prefs
   1/*
   2 * linux/fs/lockd/xdr.c
   3 *
   4 * XDR support for lockd and the lock client.
   5 *
   6 * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de>
   7 */
   8
   9#include <linux/types.h>
  10#include <linux/sched.h>
  11#include <linux/nfs.h>
  12
  13#include <linux/sunrpc/xdr.h>
  14#include <linux/sunrpc/clnt.h>
  15#include <linux/sunrpc/svc.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
  24static inline loff_t
  25s32_to_loff_t(__s32 offset)
  26{
  27        return (loff_t)offset;
  28}
  29
  30static inline __s32
  31loff_t_to_s32(loff_t offset)
  32{
  33        __s32 res;
  34        if (offset >= NLM_OFFSET_MAX)
  35                res = NLM_OFFSET_MAX;
  36        else if (offset <= -NLM_OFFSET_MAX)
  37                res = -NLM_OFFSET_MAX;
  38        else
  39                res = offset;
  40        return res;
  41}
  42
  43/*
  44 * XDR functions for basic NLM types
  45 */
  46static __be32 *nlm_decode_cookie(__be32 *p, struct nlm_cookie *c)
  47{
  48        unsigned int    len;
  49
  50        len = ntohl(*p++);
  51        
  52        if(len==0)
  53        {
  54                c->len=4;
  55                memset(c->data, 0, 4);  /* hockeypux brain damage */
  56        }
  57        else if(len<=NLM_MAXCOOKIELEN)
  58        {
  59                c->len=len;
  60                memcpy(c->data, p, len);
  61                p+=XDR_QUADLEN(len);
  62        }
  63        else 
  64        {
  65                dprintk("lockd: bad cookie size %d (only cookies under "
  66                        "%d bytes are supported.)\n",
  67                                len, NLM_MAXCOOKIELEN);
  68                return NULL;
  69        }
  70        return p;
  71}
  72
  73static inline __be32 *
  74nlm_encode_cookie(__be32 *p, struct nlm_cookie *c)
  75{
  76        *p++ = htonl(c->len);
  77        memcpy(p, c->data, c->len);
  78        p+=XDR_QUADLEN(c->len);
  79        return p;
  80}
  81
  82static __be32 *
  83nlm_decode_fh(__be32 *p, struct nfs_fh *f)
  84{
  85        unsigned int    len;
  86
  87        if ((len = ntohl(*p++)) != NFS2_FHSIZE) {
  88                dprintk("lockd: bad fhandle size %d (should be %d)\n",
  89                        len, NFS2_FHSIZE);
  90                return NULL;
  91        }
  92        f->size = NFS2_FHSIZE;
  93        memset(f->data, 0, sizeof(f->data));
  94        memcpy(f->data, p, NFS2_FHSIZE);
  95        return p + XDR_QUADLEN(NFS2_FHSIZE);
  96}
  97
  98static inline __be32 *
  99nlm_encode_fh(__be32 *p, struct nfs_fh *f)
 100{
 101        *p++ = htonl(NFS2_FHSIZE);
 102        memcpy(p, f->data, NFS2_FHSIZE);
 103        return p + XDR_QUADLEN(NFS2_FHSIZE);
 104}
 105
 106/*
 107 * Encode and decode owner handle
 108 */
 109static inline __be32 *
 110nlm_decode_oh(__be32 *p, struct xdr_netobj *oh)
 111{
 112        return xdr_decode_netobj(p, oh);
 113}
 114
 115static inline __be32 *
 116nlm_encode_oh(__be32 *p, struct xdr_netobj *oh)
 117{
 118        return xdr_encode_netobj(p, oh);
 119}
 120
 121static __be32 *
 122nlm_decode_lock(__be32 *p, struct nlm_lock *lock)
 123{
 124        struct file_lock        *fl = &lock->fl;
 125        s32                     start, len, end;
 126
 127        if (!(p = xdr_decode_string_inplace(p, &lock->caller,
 128                                            &lock->len,
 129                                            NLM_MAXSTRLEN))
 130         || !(p = nlm_decode_fh(p, &lock->fh))
 131         || !(p = nlm_decode_oh(p, &lock->oh)))
 132                return NULL;
 133        lock->svid  = ntohl(*p++);
 134
 135        locks_init_lock(fl);
 136        fl->fl_owner = current->files;
 137        fl->fl_pid   = (pid_t)lock->svid;
 138        fl->fl_flags = FL_POSIX;
 139        fl->fl_type  = F_RDLCK;         /* as good as anything else */
 140        start = ntohl(*p++);
 141        len = ntohl(*p++);
 142        end = start + len - 1;
 143
 144        fl->fl_start = s32_to_loff_t(start);
 145
 146        if (len == 0 || end < 0)
 147                fl->fl_end = OFFSET_MAX;
 148        else
 149                fl->fl_end = s32_to_loff_t(end);
 150        return p;
 151}
 152
 153/*
 154 * Encode result of a TEST/TEST_MSG call
 155 */
 156static __be32 *
 157nlm_encode_testres(__be32 *p, struct nlm_res *resp)
 158{
 159        s32             start, len;
 160
 161        if (!(p = nlm_encode_cookie(p, &resp->cookie)))
 162                return NULL;
 163        *p++ = resp->status;
 164
 165        if (resp->status == nlm_lck_denied) {
 166                struct file_lock        *fl = &resp->lock.fl;
 167
 168                *p++ = (fl->fl_type == F_RDLCK)? xdr_zero : xdr_one;
 169                *p++ = htonl(resp->lock.svid);
 170
 171                /* Encode owner handle. */
 172                if (!(p = xdr_encode_netobj(p, &resp->lock.oh)))
 173                        return NULL;
 174
 175                start = loff_t_to_s32(fl->fl_start);
 176                if (fl->fl_end == OFFSET_MAX)
 177                        len = 0;
 178                else
 179                        len = loff_t_to_s32(fl->fl_end - fl->fl_start + 1);
 180
 181                *p++ = htonl(start);
 182                *p++ = htonl(len);
 183        }
 184
 185        return p;
 186}
 187
 188
 189/*
 190 * First, the server side XDR functions
 191 */
 192int
 193nlmsvc_decode_testargs(struct svc_rqst *rqstp, __be32 *p, nlm_args *argp)
 194{
 195        u32     exclusive;
 196
 197        if (!(p = nlm_decode_cookie(p, &argp->cookie)))
 198                return 0;
 199
 200        exclusive = ntohl(*p++);
 201        if (!(p = nlm_decode_lock(p, &argp->lock)))
 202                return 0;
 203        if (exclusive)
 204                argp->lock.fl.fl_type = F_WRLCK;
 205
 206        return xdr_argsize_check(rqstp, p);
 207}
 208
 209int
 210nlmsvc_encode_testres(struct svc_rqst *rqstp, __be32 *p, struct nlm_res *resp)
 211{
 212        if (!(p = nlm_encode_testres(p, resp)))
 213                return 0;
 214        return xdr_ressize_check(rqstp, p);
 215}
 216
 217int
 218nlmsvc_decode_lockargs(struct svc_rqst *rqstp, __be32 *p, nlm_args *argp)
 219{
 220        u32     exclusive;
 221
 222        if (!(p = nlm_decode_cookie(p, &argp->cookie)))
 223                return 0;
 224        argp->block  = ntohl(*p++);
 225        exclusive    = ntohl(*p++);
 226        if (!(p = nlm_decode_lock(p, &argp->lock)))
 227                return 0;
 228        if (exclusive)
 229                argp->lock.fl.fl_type = F_WRLCK;
 230        argp->reclaim = ntohl(*p++);
 231        argp->state   = ntohl(*p++);
 232        argp->monitor = 1;              /* monitor client by default */
 233
 234        return xdr_argsize_check(rqstp, p);
 235}
 236
 237int
 238nlmsvc_decode_cancargs(struct svc_rqst *rqstp, __be32 *p, nlm_args *argp)
 239{
 240        u32     exclusive;
 241
 242        if (!(p = nlm_decode_cookie(p, &argp->cookie)))
 243                return 0;
 244        argp->block = ntohl(*p++);
 245        exclusive = ntohl(*p++);
 246        if (!(p = nlm_decode_lock(p, &argp->lock)))
 247                return 0;
 248        if (exclusive)
 249                argp->lock.fl.fl_type = F_WRLCK;
 250        return xdr_argsize_check(rqstp, p);
 251}
 252
 253int
 254nlmsvc_decode_unlockargs(struct svc_rqst *rqstp, __be32 *p, nlm_args *argp)
 255{
 256        if (!(p = nlm_decode_cookie(p, &argp->cookie))
 257         || !(p = nlm_decode_lock(p, &argp->lock)))
 258                return 0;
 259        argp->lock.fl.fl_type = F_UNLCK;
 260        return xdr_argsize_check(rqstp, p);
 261}
 262
 263int
 264nlmsvc_decode_shareargs(struct svc_rqst *rqstp, __be32 *p, nlm_args *argp)
 265{
 266        struct nlm_lock *lock = &argp->lock;
 267
 268        memset(lock, 0, sizeof(*lock));
 269        locks_init_lock(&lock->fl);
 270        lock->svid = ~(u32) 0;
 271        lock->fl.fl_pid = (pid_t)lock->svid;
 272
 273        if (!(p = nlm_decode_cookie(p, &argp->cookie))
 274         || !(p = xdr_decode_string_inplace(p, &lock->caller,
 275                                            &lock->len, NLM_MAXSTRLEN))
 276         || !(p = nlm_decode_fh(p, &lock->fh))
 277         || !(p = nlm_decode_oh(p, &lock->oh)))
 278                return 0;
 279        argp->fsm_mode = ntohl(*p++);
 280        argp->fsm_access = ntohl(*p++);
 281        return xdr_argsize_check(rqstp, p);
 282}
 283
 284int
 285nlmsvc_encode_shareres(struct svc_rqst *rqstp, __be32 *p, struct nlm_res *resp)
 286{
 287        if (!(p = nlm_encode_cookie(p, &resp->cookie)))
 288                return 0;
 289        *p++ = resp->status;
 290        *p++ = xdr_zero;                /* sequence argument */
 291        return xdr_ressize_check(rqstp, p);
 292}
 293
 294int
 295nlmsvc_encode_res(struct svc_rqst *rqstp, __be32 *p, struct nlm_res *resp)
 296{
 297        if (!(p = nlm_encode_cookie(p, &resp->cookie)))
 298                return 0;
 299        *p++ = resp->status;
 300        return xdr_ressize_check(rqstp, p);
 301}
 302
 303int
 304nlmsvc_decode_notify(struct svc_rqst *rqstp, __be32 *p, struct nlm_args *argp)
 305{
 306        struct nlm_lock *lock = &argp->lock;
 307
 308        if (!(p = xdr_decode_string_inplace(p, &lock->caller,
 309                                            &lock->len, NLM_MAXSTRLEN)))
 310                return 0;
 311        argp->state = ntohl(*p++);
 312        return xdr_argsize_check(rqstp, p);
 313}
 314
 315int
 316nlmsvc_decode_reboot(struct svc_rqst *rqstp, __be32 *p, struct nlm_reboot *argp)
 317{
 318        if (!(p = xdr_decode_string_inplace(p, &argp->mon, &argp->len, SM_MAXSTRLEN)))
 319                return 0;
 320        argp->state = ntohl(*p++);
 321        memcpy(&argp->priv.data, p, sizeof(argp->priv.data));
 322        p += XDR_QUADLEN(SM_PRIV_SIZE);
 323        return xdr_argsize_check(rqstp, p);
 324}
 325
 326int
 327nlmsvc_decode_res(struct svc_rqst *rqstp, __be32 *p, struct nlm_res *resp)
 328{
 329        if (!(p = nlm_decode_cookie(p, &resp->cookie)))
 330                return 0;
 331        resp->status = *p++;
 332        return xdr_argsize_check(rqstp, p);
 333}
 334
 335int
 336nlmsvc_decode_void(struct svc_rqst *rqstp, __be32 *p, void *dummy)
 337{
 338        return xdr_argsize_check(rqstp, p);
 339}
 340
 341int
 342nlmsvc_encode_void(struct svc_rqst *rqstp, __be32 *p, void *dummy)
 343{
 344        return xdr_ressize_check(rqstp, p);
 345}
 346