]> git.ipfire.org Git - people/ms/linux.git/blame - fs/lockd/xdr4.c
Merge branch 'for-6.0/dax' into libnvdimm-fixes
[people/ms/linux.git] / fs / lockd / xdr4.c
CommitLineData
b2441318 1// SPDX-License-Identifier: GPL-2.0
1da177e4
LT
2/*
3 * linux/fs/lockd/xdr4.c
4 *
5 * XDR support for lockd and the lock client.
6 *
7 * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de>
8 * Copyright (C) 1999, Trond Myklebust <trond.myklebust@fys.uio.no>
9 */
10
11#include <linux/types.h>
12#include <linux/sched.h>
1da177e4
LT
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>
1da177e4 20
7956521a
CL
21#include "svcxdr.h"
22
1da177e4
LT
23static inline s64
24loff_t_to_s64(loff_t offset)
25{
26 s64 res;
27 if (offset > NLM4_OFFSET_MAX)
28 res = NLM4_OFFSET_MAX;
29 else if (offset < -NLM4_OFFSET_MAX)
30 res = -NLM4_OFFSET_MAX;
31 else
32 res = offset;
33 return res;
34}
35
345b4159
CL
36/*
37 * NLM file handles are defined by specification to be a variable-length
38 * XDR opaque no longer than 1024 bytes. However, this implementation
39 * limits their length to the size of an NFSv3 file handle.
40 */
41static bool
42svcxdr_decode_fhandle(struct xdr_stream *xdr, struct nfs_fh *fh)
43{
44 __be32 *p;
45 u32 len;
46
47 if (xdr_stream_decode_u32(xdr, &len) < 0)
48 return false;
49 if (len > NFS_MAXFHSIZE)
50 return false;
51
52 p = xdr_inline_decode(xdr, len);
53 if (!p)
54 return false;
55 fh->size = len;
56 memcpy(fh->data, p, len);
57 memset(fh->data + len, 0, sizeof(fh->data) - len);
58
59 return true;
60}
61
345b4159
CL
62static bool
63svcxdr_decode_lock(struct xdr_stream *xdr, struct nlm_lock *lock)
64{
65 struct file_lock *fl = &lock->fl;
345b4159
CL
66
67 if (!svcxdr_decode_string(xdr, &lock->caller, &lock->len))
68 return false;
69 if (!svcxdr_decode_fhandle(xdr, &lock->fh))
70 return false;
71 if (!svcxdr_decode_owner(xdr, &lock->oh))
72 return false;
73 if (xdr_stream_decode_u32(xdr, &lock->svid) < 0)
74 return false;
6930bcbf 75 if (xdr_stream_decode_u64(xdr, &lock->lock_start) < 0)
345b4159 76 return false;
6930bcbf 77 if (xdr_stream_decode_u64(xdr, &lock->lock_len) < 0)
345b4159
CL
78 return false;
79
80 locks_init_lock(fl);
81 fl->fl_flags = FL_POSIX;
82 fl->fl_type = F_RDLCK;
345b4159
CL
83
84 return true;
85}
86
1beef147
CL
87static bool
88svcxdr_encode_holder(struct xdr_stream *xdr, const struct nlm_lock *lock)
1da177e4 89{
1beef147
CL
90 const struct file_lock *fl = &lock->fl;
91 s64 start, len;
1da177e4 92
1beef147
CL
93 /* exclusive */
94 if (xdr_stream_encode_bool(xdr, fl->fl_type != F_RDLCK) < 0)
95 return false;
96 if (xdr_stream_encode_u32(xdr, lock->svid) < 0)
97 return false;
98 if (!svcxdr_encode_owner(xdr, &lock->oh))
99 return false;
100 start = loff_t_to_s64(fl->fl_start);
101 if (fl->fl_end == OFFSET_MAX)
102 len = 0;
103 else
104 len = loff_t_to_s64(fl->fl_end - fl->fl_start + 1);
105 if (xdr_stream_encode_u64(xdr, start) < 0)
106 return false;
107 if (xdr_stream_encode_u64(xdr, len) < 0)
108 return false;
109
110 return true;
111}
1da177e4 112
1beef147
CL
113static bool
114svcxdr_encode_testrply(struct xdr_stream *xdr, const struct nlm_res *resp)
115{
116 if (!svcxdr_encode_stats(xdr, resp->status))
117 return false;
118 switch (resp->status) {
119 case nlm_lck_denied:
120 if (!svcxdr_encode_holder(xdr, &resp->lock))
121 return false;
1da177e4
LT
122 }
123
1beef147 124 return true;
1da177e4
LT
125}
126
127
128/*
7956521a 129 * Decode Call arguments
1da177e4 130 */
7956521a 131
c44b31c2 132bool
16c66364 133nlm4svc_decode_void(struct svc_rqst *rqstp, struct xdr_stream *xdr)
7956521a 134{
c44b31c2 135 return true;
7956521a
CL
136}
137
c44b31c2 138bool
16c66364 139nlm4svc_decode_testargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
1da177e4 140{
026fec7e 141 struct nlm_args *argp = rqstp->rq_argp;
345b4159 142 u32 exclusive;
1da177e4 143
345b4159 144 if (!svcxdr_decode_cookie(xdr, &argp->cookie))
c44b31c2 145 return false;
345b4159 146 if (xdr_stream_decode_bool(xdr, &exclusive) < 0)
c44b31c2 147 return false;
345b4159 148 if (!svcxdr_decode_lock(xdr, &argp->lock))
c44b31c2 149 return false;
1da177e4
LT
150 if (exclusive)
151 argp->lock.fl.fl_type = F_WRLCK;
152
c44b31c2 153 return true;
1da177e4
LT
154}
155
c44b31c2 156bool
16c66364 157nlm4svc_decode_lockargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
1da177e4 158{
026fec7e 159 struct nlm_args *argp = rqstp->rq_argp;
0e5977af 160 u32 exclusive;
1da177e4 161
0e5977af 162 if (!svcxdr_decode_cookie(xdr, &argp->cookie))
c44b31c2 163 return false;
0e5977af 164 if (xdr_stream_decode_bool(xdr, &argp->block) < 0)
c44b31c2 165 return false;
0e5977af 166 if (xdr_stream_decode_bool(xdr, &exclusive) < 0)
c44b31c2 167 return false;
0e5977af 168 if (!svcxdr_decode_lock(xdr, &argp->lock))
c44b31c2 169 return false;
1da177e4
LT
170 if (exclusive)
171 argp->lock.fl.fl_type = F_WRLCK;
0e5977af 172 if (xdr_stream_decode_bool(xdr, &argp->reclaim) < 0)
c44b31c2 173 return false;
0e5977af 174 if (xdr_stream_decode_u32(xdr, &argp->state) < 0)
c44b31c2 175 return false;
1da177e4
LT
176 argp->monitor = 1; /* monitor client by default */
177
c44b31c2 178 return true;
0e5977af
CL
179}
180
c44b31c2 181bool
16c66364 182nlm4svc_decode_cancargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
0e5977af 183{
1e1f38dc
CL
184 struct nlm_args *argp = rqstp->rq_argp;
185 u32 exclusive;
0e5977af 186
1e1f38dc 187 if (!svcxdr_decode_cookie(xdr, &argp->cookie))
c44b31c2 188 return false;
1e1f38dc 189 if (xdr_stream_decode_bool(xdr, &argp->block) < 0)
c44b31c2 190 return false;
1e1f38dc 191 if (xdr_stream_decode_bool(xdr, &exclusive) < 0)
c44b31c2 192 return false;
1e1f38dc 193 if (!svcxdr_decode_lock(xdr, &argp->lock))
c44b31c2 194 return false;
1e1f38dc
CL
195 if (exclusive)
196 argp->lock.fl.fl_type = F_WRLCK;
c44b31c2
CL
197
198 return true;
1da177e4
LT
199}
200
c44b31c2 201bool
16c66364 202nlm4svc_decode_unlockargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
1da177e4 203{
d76d8c25 204 struct nlm_args *argp = rqstp->rq_argp;
1da177e4 205
d76d8c25 206 if (!svcxdr_decode_cookie(xdr, &argp->cookie))
c44b31c2 207 return false;
d76d8c25 208 if (!svcxdr_decode_lock(xdr, &argp->lock))
c44b31c2 209 return false;
d76d8c25
CL
210 argp->lock.fl.fl_type = F_UNLCK;
211
c44b31c2 212 return true;
1da177e4
LT
213}
214
c44b31c2 215bool
16c66364 216nlm4svc_decode_res(struct svc_rqst *rqstp, struct xdr_stream *xdr)
b4c24b5a 217{
b4c24b5a
CL
218 struct nlm_res *resp = rqstp->rq_argp;
219
220 if (!svcxdr_decode_cookie(xdr, &resp->cookie))
c44b31c2 221 return false;
b4c24b5a 222 if (!svcxdr_decode_stats(xdr, &resp->status))
c44b31c2 223 return false;
b4c24b5a 224
c44b31c2 225 return true;
b4c24b5a
CL
226}
227
c44b31c2 228bool
16c66364 229nlm4svc_decode_reboot(struct svc_rqst *rqstp, struct xdr_stream *xdr)
bc3665fd 230{
bc3665fd 231 struct nlm_reboot *argp = rqstp->rq_argp;
16c66364 232 __be32 *p;
bc3665fd
CL
233 u32 len;
234
235 if (xdr_stream_decode_u32(xdr, &len) < 0)
c44b31c2 236 return false;
bc3665fd 237 if (len > SM_MAXSTRLEN)
c44b31c2 238 return false;
bc3665fd
CL
239 p = xdr_inline_decode(xdr, len);
240 if (!p)
c44b31c2 241 return false;
bc3665fd
CL
242 argp->len = len;
243 argp->mon = (char *)p;
244 if (xdr_stream_decode_u32(xdr, &argp->state) < 0)
c44b31c2 245 return false;
bc3665fd
CL
246 p = xdr_inline_decode(xdr, SM_PRIV_SIZE);
247 if (!p)
c44b31c2 248 return false;
bc3665fd
CL
249 memcpy(&argp->priv.data, p, sizeof(argp->priv.data));
250
c44b31c2 251 return true;
bc3665fd
CL
252}
253
c44b31c2 254bool
16c66364 255nlm4svc_decode_shareargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
1da177e4 256{
026fec7e 257 struct nlm_args *argp = rqstp->rq_argp;
1da177e4
LT
258 struct nlm_lock *lock = &argp->lock;
259
260 memset(lock, 0, sizeof(*lock));
261 locks_init_lock(&lock->fl);
7cf96b6d 262 lock->svid = ~(u32)0;
1da177e4 263
7cf96b6d 264 if (!svcxdr_decode_cookie(xdr, &argp->cookie))
c44b31c2 265 return false;
7cf96b6d 266 if (!svcxdr_decode_string(xdr, &lock->caller, &lock->len))
c44b31c2 267 return false;
7cf96b6d 268 if (!svcxdr_decode_fhandle(xdr, &lock->fh))
c44b31c2 269 return false;
7cf96b6d 270 if (!svcxdr_decode_owner(xdr, &lock->oh))
c44b31c2 271 return false;
7cf96b6d
CL
272 /* XXX: Range checks are missing in the original code */
273 if (xdr_stream_decode_u32(xdr, &argp->fsm_mode) < 0)
c44b31c2 274 return false;
7cf96b6d 275 if (xdr_stream_decode_u32(xdr, &argp->fsm_access) < 0)
c44b31c2 276 return false;
7cf96b6d 277
c44b31c2 278 return true;
7cf96b6d
CL
279}
280
c44b31c2 281bool
16c66364 282nlm4svc_decode_notify(struct svc_rqst *rqstp, struct xdr_stream *xdr)
3049e974 283{
3049e974
CL
284 struct nlm_args *argp = rqstp->rq_argp;
285 struct nlm_lock *lock = &argp->lock;
286
287 if (!svcxdr_decode_string(xdr, &lock->caller, &lock->len))
c44b31c2 288 return false;
3049e974 289 if (xdr_stream_decode_u32(xdr, &argp->state) < 0)
c44b31c2 290 return false;
3049e974 291
c44b31c2 292 return true;
3049e974
CL
293}
294
ec757e42
CL
295
296/*
297 * Encode Reply results
298 */
299
130e2054 300bool
fda49441 301nlm4svc_encode_void(struct svc_rqst *rqstp, struct xdr_stream *xdr)
ec757e42 302{
130e2054 303 return true;
ec757e42
CL
304}
305
130e2054 306bool
fda49441 307nlm4svc_encode_testres(struct svc_rqst *rqstp, struct xdr_stream *xdr)
7cf96b6d
CL
308{
309 struct nlm_res *resp = rqstp->rq_resp;
310
1beef147
CL
311 return svcxdr_encode_cookie(xdr, &resp->cookie) &&
312 svcxdr_encode_testrply(xdr, resp);
1da177e4
LT
313}
314
130e2054 315bool
fda49441 316nlm4svc_encode_res(struct svc_rqst *rqstp, struct xdr_stream *xdr)
1da177e4 317{
63f8de37
CH
318 struct nlm_res *resp = rqstp->rq_resp;
319
447c14d4
CL
320 return svcxdr_encode_cookie(xdr, &resp->cookie) &&
321 svcxdr_encode_stats(xdr, resp->status);
1da177e4
LT
322}
323
130e2054 324bool
fda49441 325nlm4svc_encode_shareres(struct svc_rqst *rqstp, struct xdr_stream *xdr)
1da177e4 326{
63f8de37
CH
327 struct nlm_res *resp = rqstp->rq_resp;
328
0ff5b50a 329 if (!svcxdr_encode_cookie(xdr, &resp->cookie))
130e2054 330 return false;
0ff5b50a 331 if (!svcxdr_encode_stats(xdr, resp->status))
130e2054 332 return false;
0ff5b50a
CL
333 /* sequence */
334 if (xdr_stream_encode_u32(xdr, 0) < 0)
130e2054 335 return false;
0ff5b50a 336
130e2054 337 return true;
1da177e4 338}