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