forked from Qortal/Brooklyn
04c1822c0a
Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey!
363 lines
7.7 KiB
C
363 lines
7.7 KiB
C
// SPDX-License-Identifier: GPL-2.0
|
|
/*
|
|
* linux/fs/lockd/xdr4.c
|
|
*
|
|
* XDR support for lockd and the lock client.
|
|
*
|
|
* Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de>
|
|
* Copyright (C) 1999, Trond Myklebust <trond.myklebust@fys.uio.no>
|
|
*/
|
|
|
|
#include <linux/types.h>
|
|
#include <linux/sched.h>
|
|
#include <linux/nfs.h>
|
|
|
|
#include <linux/sunrpc/xdr.h>
|
|
#include <linux/sunrpc/clnt.h>
|
|
#include <linux/sunrpc/svc.h>
|
|
#include <linux/sunrpc/stats.h>
|
|
#include <linux/lockd/lockd.h>
|
|
|
|
#include "svcxdr.h"
|
|
|
|
static inline loff_t
|
|
s64_to_loff_t(__s64 offset)
|
|
{
|
|
return (loff_t)offset;
|
|
}
|
|
|
|
|
|
static inline s64
|
|
loff_t_to_s64(loff_t offset)
|
|
{
|
|
s64 res;
|
|
if (offset > NLM4_OFFSET_MAX)
|
|
res = NLM4_OFFSET_MAX;
|
|
else if (offset < -NLM4_OFFSET_MAX)
|
|
res = -NLM4_OFFSET_MAX;
|
|
else
|
|
res = offset;
|
|
return res;
|
|
}
|
|
|
|
/*
|
|
* NLM file handles are defined by specification to be a variable-length
|
|
* XDR opaque no longer than 1024 bytes. However, this implementation
|
|
* limits their length to the size of an NFSv3 file handle.
|
|
*/
|
|
static bool
|
|
svcxdr_decode_fhandle(struct xdr_stream *xdr, struct nfs_fh *fh)
|
|
{
|
|
__be32 *p;
|
|
u32 len;
|
|
|
|
if (xdr_stream_decode_u32(xdr, &len) < 0)
|
|
return false;
|
|
if (len > NFS_MAXFHSIZE)
|
|
return false;
|
|
|
|
p = xdr_inline_decode(xdr, len);
|
|
if (!p)
|
|
return false;
|
|
fh->size = len;
|
|
memcpy(fh->data, p, len);
|
|
memset(fh->data + len, 0, sizeof(fh->data) - len);
|
|
|
|
return true;
|
|
}
|
|
|
|
static bool
|
|
svcxdr_decode_lock(struct xdr_stream *xdr, struct nlm_lock *lock)
|
|
{
|
|
struct file_lock *fl = &lock->fl;
|
|
u64 len, start;
|
|
s64 end;
|
|
|
|
if (!svcxdr_decode_string(xdr, &lock->caller, &lock->len))
|
|
return false;
|
|
if (!svcxdr_decode_fhandle(xdr, &lock->fh))
|
|
return false;
|
|
if (!svcxdr_decode_owner(xdr, &lock->oh))
|
|
return false;
|
|
if (xdr_stream_decode_u32(xdr, &lock->svid) < 0)
|
|
return false;
|
|
if (xdr_stream_decode_u64(xdr, &start) < 0)
|
|
return false;
|
|
if (xdr_stream_decode_u64(xdr, &len) < 0)
|
|
return false;
|
|
|
|
locks_init_lock(fl);
|
|
fl->fl_flags = FL_POSIX;
|
|
fl->fl_type = F_RDLCK;
|
|
end = start + len - 1;
|
|
fl->fl_start = s64_to_loff_t(start);
|
|
if (len == 0 || end < 0)
|
|
fl->fl_end = OFFSET_MAX;
|
|
else
|
|
fl->fl_end = s64_to_loff_t(end);
|
|
|
|
return true;
|
|
}
|
|
|
|
static bool
|
|
svcxdr_encode_holder(struct xdr_stream *xdr, const struct nlm_lock *lock)
|
|
{
|
|
const struct file_lock *fl = &lock->fl;
|
|
s64 start, len;
|
|
|
|
/* exclusive */
|
|
if (xdr_stream_encode_bool(xdr, fl->fl_type != F_RDLCK) < 0)
|
|
return false;
|
|
if (xdr_stream_encode_u32(xdr, lock->svid) < 0)
|
|
return false;
|
|
if (!svcxdr_encode_owner(xdr, &lock->oh))
|
|
return false;
|
|
start = loff_t_to_s64(fl->fl_start);
|
|
if (fl->fl_end == OFFSET_MAX)
|
|
len = 0;
|
|
else
|
|
len = loff_t_to_s64(fl->fl_end - fl->fl_start + 1);
|
|
if (xdr_stream_encode_u64(xdr, start) < 0)
|
|
return false;
|
|
if (xdr_stream_encode_u64(xdr, len) < 0)
|
|
return false;
|
|
|
|
return true;
|
|
}
|
|
|
|
static bool
|
|
svcxdr_encode_testrply(struct xdr_stream *xdr, const struct nlm_res *resp)
|
|
{
|
|
if (!svcxdr_encode_stats(xdr, resp->status))
|
|
return false;
|
|
switch (resp->status) {
|
|
case nlm_lck_denied:
|
|
if (!svcxdr_encode_holder(xdr, &resp->lock))
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
/*
|
|
* Decode Call arguments
|
|
*/
|
|
|
|
int
|
|
nlm4svc_decode_void(struct svc_rqst *rqstp, __be32 *p)
|
|
{
|
|
return 1;
|
|
}
|
|
|
|
int
|
|
nlm4svc_decode_testargs(struct svc_rqst *rqstp, __be32 *p)
|
|
{
|
|
struct xdr_stream *xdr = &rqstp->rq_arg_stream;
|
|
struct nlm_args *argp = rqstp->rq_argp;
|
|
u32 exclusive;
|
|
|
|
if (!svcxdr_decode_cookie(xdr, &argp->cookie))
|
|
return 0;
|
|
if (xdr_stream_decode_bool(xdr, &exclusive) < 0)
|
|
return 0;
|
|
if (!svcxdr_decode_lock(xdr, &argp->lock))
|
|
return 0;
|
|
if (exclusive)
|
|
argp->lock.fl.fl_type = F_WRLCK;
|
|
|
|
return 1;
|
|
}
|
|
|
|
int
|
|
nlm4svc_decode_lockargs(struct svc_rqst *rqstp, __be32 *p)
|
|
{
|
|
struct xdr_stream *xdr = &rqstp->rq_arg_stream;
|
|
struct nlm_args *argp = rqstp->rq_argp;
|
|
u32 exclusive;
|
|
|
|
if (!svcxdr_decode_cookie(xdr, &argp->cookie))
|
|
return 0;
|
|
if (xdr_stream_decode_bool(xdr, &argp->block) < 0)
|
|
return 0;
|
|
if (xdr_stream_decode_bool(xdr, &exclusive) < 0)
|
|
return 0;
|
|
if (!svcxdr_decode_lock(xdr, &argp->lock))
|
|
return 0;
|
|
if (exclusive)
|
|
argp->lock.fl.fl_type = F_WRLCK;
|
|
if (xdr_stream_decode_bool(xdr, &argp->reclaim) < 0)
|
|
return 0;
|
|
if (xdr_stream_decode_u32(xdr, &argp->state) < 0)
|
|
return 0;
|
|
argp->monitor = 1; /* monitor client by default */
|
|
|
|
return 1;
|
|
}
|
|
|
|
int
|
|
nlm4svc_decode_cancargs(struct svc_rqst *rqstp, __be32 *p)
|
|
{
|
|
struct xdr_stream *xdr = &rqstp->rq_arg_stream;
|
|
struct nlm_args *argp = rqstp->rq_argp;
|
|
u32 exclusive;
|
|
|
|
if (!svcxdr_decode_cookie(xdr, &argp->cookie))
|
|
return 0;
|
|
if (xdr_stream_decode_bool(xdr, &argp->block) < 0)
|
|
return 0;
|
|
if (xdr_stream_decode_bool(xdr, &exclusive) < 0)
|
|
return 0;
|
|
if (!svcxdr_decode_lock(xdr, &argp->lock))
|
|
return 0;
|
|
if (exclusive)
|
|
argp->lock.fl.fl_type = F_WRLCK;
|
|
return 1;
|
|
}
|
|
|
|
int
|
|
nlm4svc_decode_unlockargs(struct svc_rqst *rqstp, __be32 *p)
|
|
{
|
|
struct xdr_stream *xdr = &rqstp->rq_arg_stream;
|
|
struct nlm_args *argp = rqstp->rq_argp;
|
|
|
|
if (!svcxdr_decode_cookie(xdr, &argp->cookie))
|
|
return 0;
|
|
if (!svcxdr_decode_lock(xdr, &argp->lock))
|
|
return 0;
|
|
argp->lock.fl.fl_type = F_UNLCK;
|
|
|
|
return 1;
|
|
}
|
|
|
|
int
|
|
nlm4svc_decode_res(struct svc_rqst *rqstp, __be32 *p)
|
|
{
|
|
struct xdr_stream *xdr = &rqstp->rq_arg_stream;
|
|
struct nlm_res *resp = rqstp->rq_argp;
|
|
|
|
if (!svcxdr_decode_cookie(xdr, &resp->cookie))
|
|
return 0;
|
|
if (!svcxdr_decode_stats(xdr, &resp->status))
|
|
return 0;
|
|
|
|
return 1;
|
|
}
|
|
|
|
int
|
|
nlm4svc_decode_reboot(struct svc_rqst *rqstp, __be32 *p)
|
|
{
|
|
struct xdr_stream *xdr = &rqstp->rq_arg_stream;
|
|
struct nlm_reboot *argp = rqstp->rq_argp;
|
|
u32 len;
|
|
|
|
if (xdr_stream_decode_u32(xdr, &len) < 0)
|
|
return 0;
|
|
if (len > SM_MAXSTRLEN)
|
|
return 0;
|
|
p = xdr_inline_decode(xdr, len);
|
|
if (!p)
|
|
return 0;
|
|
argp->len = len;
|
|
argp->mon = (char *)p;
|
|
if (xdr_stream_decode_u32(xdr, &argp->state) < 0)
|
|
return 0;
|
|
p = xdr_inline_decode(xdr, SM_PRIV_SIZE);
|
|
if (!p)
|
|
return 0;
|
|
memcpy(&argp->priv.data, p, sizeof(argp->priv.data));
|
|
|
|
return 1;
|
|
}
|
|
|
|
int
|
|
nlm4svc_decode_shareargs(struct svc_rqst *rqstp, __be32 *p)
|
|
{
|
|
struct xdr_stream *xdr = &rqstp->rq_arg_stream;
|
|
struct nlm_args *argp = rqstp->rq_argp;
|
|
struct nlm_lock *lock = &argp->lock;
|
|
|
|
memset(lock, 0, sizeof(*lock));
|
|
locks_init_lock(&lock->fl);
|
|
lock->svid = ~(u32)0;
|
|
|
|
if (!svcxdr_decode_cookie(xdr, &argp->cookie))
|
|
return 0;
|
|
if (!svcxdr_decode_string(xdr, &lock->caller, &lock->len))
|
|
return 0;
|
|
if (!svcxdr_decode_fhandle(xdr, &lock->fh))
|
|
return 0;
|
|
if (!svcxdr_decode_owner(xdr, &lock->oh))
|
|
return 0;
|
|
/* XXX: Range checks are missing in the original code */
|
|
if (xdr_stream_decode_u32(xdr, &argp->fsm_mode) < 0)
|
|
return 0;
|
|
if (xdr_stream_decode_u32(xdr, &argp->fsm_access) < 0)
|
|
return 0;
|
|
|
|
return 1;
|
|
}
|
|
|
|
int
|
|
nlm4svc_decode_notify(struct svc_rqst *rqstp, __be32 *p)
|
|
{
|
|
struct xdr_stream *xdr = &rqstp->rq_arg_stream;
|
|
struct nlm_args *argp = rqstp->rq_argp;
|
|
struct nlm_lock *lock = &argp->lock;
|
|
|
|
if (!svcxdr_decode_string(xdr, &lock->caller, &lock->len))
|
|
return 0;
|
|
if (xdr_stream_decode_u32(xdr, &argp->state) < 0)
|
|
return 0;
|
|
|
|
return 1;
|
|
}
|
|
|
|
|
|
/*
|
|
* Encode Reply results
|
|
*/
|
|
|
|
int
|
|
nlm4svc_encode_void(struct svc_rqst *rqstp, __be32 *p)
|
|
{
|
|
return 1;
|
|
}
|
|
|
|
int
|
|
nlm4svc_encode_testres(struct svc_rqst *rqstp, __be32 *p)
|
|
{
|
|
struct xdr_stream *xdr = &rqstp->rq_res_stream;
|
|
struct nlm_res *resp = rqstp->rq_resp;
|
|
|
|
return svcxdr_encode_cookie(xdr, &resp->cookie) &&
|
|
svcxdr_encode_testrply(xdr, resp);
|
|
}
|
|
|
|
int
|
|
nlm4svc_encode_res(struct svc_rqst *rqstp, __be32 *p)
|
|
{
|
|
struct xdr_stream *xdr = &rqstp->rq_res_stream;
|
|
struct nlm_res *resp = rqstp->rq_resp;
|
|
|
|
return svcxdr_encode_cookie(xdr, &resp->cookie) &&
|
|
svcxdr_encode_stats(xdr, resp->status);
|
|
}
|
|
|
|
int
|
|
nlm4svc_encode_shareres(struct svc_rqst *rqstp, __be32 *p)
|
|
{
|
|
struct xdr_stream *xdr = &rqstp->rq_res_stream;
|
|
struct nlm_res *resp = rqstp->rq_resp;
|
|
|
|
if (!svcxdr_encode_cookie(xdr, &resp->cookie))
|
|
return 0;
|
|
if (!svcxdr_encode_stats(xdr, resp->status))
|
|
return 0;
|
|
/* sequence */
|
|
if (xdr_stream_encode_u32(xdr, 0) < 0)
|
|
return 0;
|
|
|
|
return 1;
|
|
}
|