]> Git Repo - linux.git/blame - fs/lockd/xdr.c
lockd: Update the NLMv1 TEST arguments decoder to use struct xdr_stream
[linux.git] / fs / lockd / xdr.c
CommitLineData
b2441318 1// SPDX-License-Identifier: GPL-2.0
1da177e4
LT
2/*
3 * linux/fs/lockd/xdr.c
4 *
5 * XDR support for lockd and the lock client.
6 *
7 * Copyright (C) 1995, 1996 Olaf Kirch <[email protected]>
8 */
9
1da177e4
LT
10#include <linux/types.h>
11#include <linux/sched.h>
1da177e4
LT
12#include <linux/nfs.h>
13
14#include <linux/sunrpc/xdr.h>
15#include <linux/sunrpc/clnt.h>
16#include <linux/sunrpc/svc.h>
17#include <linux/sunrpc/stats.h>
18#include <linux/lockd/lockd.h>
1da177e4 19
9c69de4c
CH
20#include <uapi/linux/nfs2.h>
21
cc1029b5
CL
22#include "svcxdr.h"
23
1da177e4
LT
24#define NLMDBG_FACILITY NLMDBG_XDR
25
26
27static inline loff_t
28s32_to_loff_t(__s32 offset)
29{
30 return (loff_t)offset;
31}
32
33static inline __s32
34loff_t_to_s32(loff_t offset)
35{
36 __s32 res;
37 if (offset >= NLM_OFFSET_MAX)
38 res = NLM_OFFSET_MAX;
39 else if (offset <= -NLM_OFFSET_MAX)
40 res = -NLM_OFFSET_MAX;
41 else
42 res = offset;
43 return res;
44}
45
46/*
47 * XDR functions for basic NLM types
48 */
52921e02 49static __be32 *nlm_decode_cookie(__be32 *p, struct nlm_cookie *c)
1da177e4
LT
50{
51 unsigned int len;
52
53 len = ntohl(*p++);
54
55 if(len==0)
56 {
57 c->len=4;
58 memset(c->data, 0, 4); /* hockeypux brain damage */
59 }
60 else if(len<=NLM_MAXCOOKIELEN)
61 {
62 c->len=len;
63 memcpy(c->data, p, len);
64 p+=XDR_QUADLEN(len);
65 }
66 else
67 {
e159a08b
CL
68 dprintk("lockd: bad cookie size %d (only cookies under "
69 "%d bytes are supported.)\n",
70 len, NLM_MAXCOOKIELEN);
1da177e4
LT
71 return NULL;
72 }
73 return p;
74}
75
52921e02
AV
76static inline __be32 *
77nlm_encode_cookie(__be32 *p, struct nlm_cookie *c)
1da177e4
LT
78{
79 *p++ = htonl(c->len);
80 memcpy(p, c->data, c->len);
81 p+=XDR_QUADLEN(c->len);
82 return p;
83}
84
52921e02
AV
85static __be32 *
86nlm_decode_fh(__be32 *p, struct nfs_fh *f)
1da177e4
LT
87{
88 unsigned int len;
89
90 if ((len = ntohl(*p++)) != NFS2_FHSIZE) {
e159a08b 91 dprintk("lockd: bad fhandle size %d (should be %d)\n",
1da177e4
LT
92 len, NFS2_FHSIZE);
93 return NULL;
94 }
95 f->size = NFS2_FHSIZE;
96 memset(f->data, 0, sizeof(f->data));
97 memcpy(f->data, p, NFS2_FHSIZE);
98 return p + XDR_QUADLEN(NFS2_FHSIZE);
99}
100
2fd0c67a
CL
101/*
102 * NLM file handles are defined by specification to be a variable-length
103 * XDR opaque no longer than 1024 bytes. However, this implementation
104 * constrains their length to exactly the length of an NFSv2 file
105 * handle.
106 */
107static bool
108svcxdr_decode_fhandle(struct xdr_stream *xdr, struct nfs_fh *fh)
109{
110 __be32 *p;
111 u32 len;
112
113 if (xdr_stream_decode_u32(xdr, &len) < 0)
114 return false;
115 if (len != NFS2_FHSIZE)
116 return false;
117
118 p = xdr_inline_decode(xdr, len);
119 if (!p)
120 return false;
121 fh->size = NFS2_FHSIZE;
122 memcpy(fh->data, p, len);
123 memset(fh->data + NFS2_FHSIZE, 0, sizeof(fh->data) - NFS2_FHSIZE);
124
125 return true;
126}
127
1da177e4
LT
128/*
129 * Encode and decode owner handle
130 */
52921e02
AV
131static inline __be32 *
132nlm_decode_oh(__be32 *p, struct xdr_netobj *oh)
1da177e4
LT
133{
134 return xdr_decode_netobj(p, oh);
135}
136
52921e02
AV
137static inline __be32 *
138nlm_encode_oh(__be32 *p, struct xdr_netobj *oh)
1da177e4
LT
139{
140 return xdr_encode_netobj(p, oh);
141}
142
52921e02
AV
143static __be32 *
144nlm_decode_lock(__be32 *p, struct nlm_lock *lock)
1da177e4
LT
145{
146 struct file_lock *fl = &lock->fl;
147 s32 start, len, end;
148
149 if (!(p = xdr_decode_string_inplace(p, &lock->caller,
150 &lock->len,
151 NLM_MAXSTRLEN))
152 || !(p = nlm_decode_fh(p, &lock->fh))
153 || !(p = nlm_decode_oh(p, &lock->oh)))
154 return NULL;
7bab377f 155 lock->svid = ntohl(*p++);
1da177e4
LT
156
157 locks_init_lock(fl);
1da177e4
LT
158 fl->fl_flags = FL_POSIX;
159 fl->fl_type = F_RDLCK; /* as good as anything else */
160 start = ntohl(*p++);
161 len = ntohl(*p++);
162 end = start + len - 1;
163
164 fl->fl_start = s32_to_loff_t(start);
165
166 if (len == 0 || end < 0)
167 fl->fl_end = OFFSET_MAX;
168 else
169 fl->fl_end = s32_to_loff_t(end);
170 return p;
171}
172
2fd0c67a
CL
173static bool
174svcxdr_decode_lock(struct xdr_stream *xdr, struct nlm_lock *lock)
175{
176 struct file_lock *fl = &lock->fl;
177 s32 start, len, end;
178
179 if (!svcxdr_decode_string(xdr, &lock->caller, &lock->len))
180 return false;
181 if (!svcxdr_decode_fhandle(xdr, &lock->fh))
182 return false;
183 if (!svcxdr_decode_owner(xdr, &lock->oh))
184 return false;
185 if (xdr_stream_decode_u32(xdr, &lock->svid) < 0)
186 return false;
187 if (xdr_stream_decode_u32(xdr, &start) < 0)
188 return false;
189 if (xdr_stream_decode_u32(xdr, &len) < 0)
190 return false;
191
192 locks_init_lock(fl);
193 fl->fl_flags = FL_POSIX;
194 fl->fl_type = F_RDLCK;
195 end = start + len - 1;
196 fl->fl_start = s32_to_loff_t(start);
197 if (len == 0 || end < 0)
198 fl->fl_end = OFFSET_MAX;
199 else
200 fl->fl_end = s32_to_loff_t(end);
201
202 return true;
203}
204
1da177e4
LT
205/*
206 * Encode result of a TEST/TEST_MSG call
207 */
52921e02
AV
208static __be32 *
209nlm_encode_testres(__be32 *p, struct nlm_res *resp)
1da177e4
LT
210{
211 s32 start, len;
212
213 if (!(p = nlm_encode_cookie(p, &resp->cookie)))
214 return NULL;
215 *p++ = resp->status;
216
217 if (resp->status == nlm_lck_denied) {
218 struct file_lock *fl = &resp->lock.fl;
219
220 *p++ = (fl->fl_type == F_RDLCK)? xdr_zero : xdr_one;
7bab377f 221 *p++ = htonl(resp->lock.svid);
1da177e4
LT
222
223 /* Encode owner handle. */
224 if (!(p = xdr_encode_netobj(p, &resp->lock.oh)))
225 return NULL;
226
227 start = loff_t_to_s32(fl->fl_start);
228 if (fl->fl_end == OFFSET_MAX)
229 len = 0;
230 else
231 len = loff_t_to_s32(fl->fl_end - fl->fl_start + 1);
232
233 *p++ = htonl(start);
234 *p++ = htonl(len);
235 }
236
237 return p;
238}
239
240
241/*
cc1029b5 242 * Decode Call arguments
1da177e4 243 */
cc1029b5
CL
244
245int
246nlmsvc_decode_void(struct svc_rqst *rqstp, __be32 *p)
247{
248 return 1;
249}
250
1da177e4 251int
026fec7e 252nlmsvc_decode_testargs(struct svc_rqst *rqstp, __be32 *p)
1da177e4 253{
2fd0c67a 254 struct xdr_stream *xdr = &rqstp->rq_arg_stream;
026fec7e 255 struct nlm_args *argp = rqstp->rq_argp;
2fd0c67a 256 u32 exclusive;
1da177e4 257
2fd0c67a 258 if (!svcxdr_decode_cookie(xdr, &argp->cookie))
1da177e4 259 return 0;
2fd0c67a
CL
260 if (xdr_stream_decode_bool(xdr, &exclusive) < 0)
261 return 0;
262 if (!svcxdr_decode_lock(xdr, &argp->lock))
1da177e4
LT
263 return 0;
264 if (exclusive)
265 argp->lock.fl.fl_type = F_WRLCK;
266
2fd0c67a 267 return 1;
1da177e4
LT
268}
269
270int
63f8de37 271nlmsvc_encode_testres(struct svc_rqst *rqstp, __be32 *p)
1da177e4 272{
63f8de37
CH
273 struct nlm_res *resp = rqstp->rq_resp;
274
1da177e4
LT
275 if (!(p = nlm_encode_testres(p, resp)))
276 return 0;
277 return xdr_ressize_check(rqstp, p);
278}
279
280int
026fec7e 281nlmsvc_decode_lockargs(struct svc_rqst *rqstp, __be32 *p)
1da177e4 282{
026fec7e 283 struct nlm_args *argp = rqstp->rq_argp;
1da177e4
LT
284 u32 exclusive;
285
286 if (!(p = nlm_decode_cookie(p, &argp->cookie)))
287 return 0;
288 argp->block = ntohl(*p++);
289 exclusive = ntohl(*p++);
290 if (!(p = nlm_decode_lock(p, &argp->lock)))
291 return 0;
292 if (exclusive)
293 argp->lock.fl.fl_type = F_WRLCK;
294 argp->reclaim = ntohl(*p++);
295 argp->state = ntohl(*p++);
296 argp->monitor = 1; /* monitor client by default */
297
298 return xdr_argsize_check(rqstp, p);
299}
300
301int
026fec7e 302nlmsvc_decode_cancargs(struct svc_rqst *rqstp, __be32 *p)
1da177e4 303{
026fec7e 304 struct nlm_args *argp = rqstp->rq_argp;
1da177e4
LT
305 u32 exclusive;
306
307 if (!(p = nlm_decode_cookie(p, &argp->cookie)))
308 return 0;
309 argp->block = ntohl(*p++);
310 exclusive = ntohl(*p++);
311 if (!(p = nlm_decode_lock(p, &argp->lock)))
312 return 0;
313 if (exclusive)
314 argp->lock.fl.fl_type = F_WRLCK;
315 return xdr_argsize_check(rqstp, p);
316}
317
318int
026fec7e 319nlmsvc_decode_unlockargs(struct svc_rqst *rqstp, __be32 *p)
1da177e4 320{
026fec7e
CH
321 struct nlm_args *argp = rqstp->rq_argp;
322
1da177e4
LT
323 if (!(p = nlm_decode_cookie(p, &argp->cookie))
324 || !(p = nlm_decode_lock(p, &argp->lock)))
325 return 0;
326 argp->lock.fl.fl_type = F_UNLCK;
327 return xdr_argsize_check(rqstp, p);
328}
329
330int
026fec7e 331nlmsvc_decode_shareargs(struct svc_rqst *rqstp, __be32 *p)
1da177e4 332{
026fec7e 333 struct nlm_args *argp = rqstp->rq_argp;
1da177e4
LT
334 struct nlm_lock *lock = &argp->lock;
335
336 memset(lock, 0, sizeof(*lock));
337 locks_init_lock(&lock->fl);
7bab377f 338 lock->svid = ~(u32) 0;
1da177e4
LT
339
340 if (!(p = nlm_decode_cookie(p, &argp->cookie))
341 || !(p = xdr_decode_string_inplace(p, &lock->caller,
342 &lock->len, NLM_MAXSTRLEN))
343 || !(p = nlm_decode_fh(p, &lock->fh))
344 || !(p = nlm_decode_oh(p, &lock->oh)))
345 return 0;
346 argp->fsm_mode = ntohl(*p++);
347 argp->fsm_access = ntohl(*p++);
348 return xdr_argsize_check(rqstp, p);
349}
350
351int
63f8de37 352nlmsvc_encode_shareres(struct svc_rqst *rqstp, __be32 *p)
1da177e4 353{
63f8de37
CH
354 struct nlm_res *resp = rqstp->rq_resp;
355
1da177e4
LT
356 if (!(p = nlm_encode_cookie(p, &resp->cookie)))
357 return 0;
358 *p++ = resp->status;
359 *p++ = xdr_zero; /* sequence argument */
360 return xdr_ressize_check(rqstp, p);
361}
362
363int
63f8de37 364nlmsvc_encode_res(struct svc_rqst *rqstp, __be32 *p)
1da177e4 365{
63f8de37
CH
366 struct nlm_res *resp = rqstp->rq_resp;
367
1da177e4
LT
368 if (!(p = nlm_encode_cookie(p, &resp->cookie)))
369 return 0;
370 *p++ = resp->status;
371 return xdr_ressize_check(rqstp, p);
372}
373
374int
026fec7e 375nlmsvc_decode_notify(struct svc_rqst *rqstp, __be32 *p)
1da177e4 376{
026fec7e 377 struct nlm_args *argp = rqstp->rq_argp;
1da177e4
LT
378 struct nlm_lock *lock = &argp->lock;
379
380 if (!(p = xdr_decode_string_inplace(p, &lock->caller,
381 &lock->len, NLM_MAXSTRLEN)))
382 return 0;
383 argp->state = ntohl(*p++);
384 return xdr_argsize_check(rqstp, p);
385}
386
387int
026fec7e 388nlmsvc_decode_reboot(struct svc_rqst *rqstp, __be32 *p)
1da177e4 389{
026fec7e
CH
390 struct nlm_reboot *argp = rqstp->rq_argp;
391
1da177e4
LT
392 if (!(p = xdr_decode_string_inplace(p, &argp->mon, &argp->len, SM_MAXSTRLEN)))
393 return 0;
394 argp->state = ntohl(*p++);
576df463
CL
395 memcpy(&argp->priv.data, p, sizeof(argp->priv.data));
396 p += XDR_QUADLEN(SM_PRIV_SIZE);
1da177e4
LT
397 return xdr_argsize_check(rqstp, p);
398}
399
400int
026fec7e 401nlmsvc_decode_res(struct svc_rqst *rqstp, __be32 *p)
1da177e4 402{
026fec7e
CH
403 struct nlm_res *resp = rqstp->rq_argp;
404
1da177e4
LT
405 if (!(p = nlm_decode_cookie(p, &resp->cookie)))
406 return 0;
e8c5c045 407 resp->status = *p++;
1da177e4
LT
408 return xdr_argsize_check(rqstp, p);
409}
410
1da177e4 411int
63f8de37 412nlmsvc_encode_void(struct svc_rqst *rqstp, __be32 *p)
1da177e4
LT
413{
414 return xdr_ressize_check(rqstp, p);
415}
This page took 1.083968 seconds and 4 git commands to generate.