futex: Clean up stale comments
[linux-2.6-microblaze.git] / fs / lockd / xdr.c
1 // SPDX-License-Identifier: GPL-2.0
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 <okir@monad.swb.de>
8  */
9
10 #include <linux/types.h>
11 #include <linux/sched.h>
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>
19
20 #include <uapi/linux/nfs2.h>
21
22 #include "svcxdr.h"
23
24
25 static inline loff_t
26 s32_to_loff_t(__s32 offset)
27 {
28         return (loff_t)offset;
29 }
30
31 static inline __s32
32 loff_t_to_s32(loff_t offset)
33 {
34         __s32 res;
35         if (offset >= NLM_OFFSET_MAX)
36                 res = NLM_OFFSET_MAX;
37         else if (offset <= -NLM_OFFSET_MAX)
38                 res = -NLM_OFFSET_MAX;
39         else
40                 res = offset;
41         return res;
42 }
43
44 /*
45  * NLM file handles are defined by specification to be a variable-length
46  * XDR opaque no longer than 1024 bytes. However, this implementation
47  * constrains their length to exactly the length of an NFSv2 file
48  * handle.
49  */
50 static bool
51 svcxdr_decode_fhandle(struct xdr_stream *xdr, struct nfs_fh *fh)
52 {
53         __be32 *p;
54         u32 len;
55
56         if (xdr_stream_decode_u32(xdr, &len) < 0)
57                 return false;
58         if (len != NFS2_FHSIZE)
59                 return false;
60
61         p = xdr_inline_decode(xdr, len);
62         if (!p)
63                 return false;
64         fh->size = NFS2_FHSIZE;
65         memcpy(fh->data, p, len);
66         memset(fh->data + NFS2_FHSIZE, 0, sizeof(fh->data) - NFS2_FHSIZE);
67
68         return true;
69 }
70
71 static bool
72 svcxdr_decode_lock(struct xdr_stream *xdr, struct nlm_lock *lock)
73 {
74         struct file_lock *fl = &lock->fl;
75         s32 start, len, end;
76
77         if (!svcxdr_decode_string(xdr, &lock->caller, &lock->len))
78                 return false;
79         if (!svcxdr_decode_fhandle(xdr, &lock->fh))
80                 return false;
81         if (!svcxdr_decode_owner(xdr, &lock->oh))
82                 return false;
83         if (xdr_stream_decode_u32(xdr, &lock->svid) < 0)
84                 return false;
85         if (xdr_stream_decode_u32(xdr, &start) < 0)
86                 return false;
87         if (xdr_stream_decode_u32(xdr, &len) < 0)
88                 return false;
89
90         locks_init_lock(fl);
91         fl->fl_flags = FL_POSIX;
92         fl->fl_type  = F_RDLCK;
93         end = start + len - 1;
94         fl->fl_start = s32_to_loff_t(start);
95         if (len == 0 || end < 0)
96                 fl->fl_end = OFFSET_MAX;
97         else
98                 fl->fl_end = s32_to_loff_t(end);
99
100         return true;
101 }
102
103 static bool
104 svcxdr_encode_holder(struct xdr_stream *xdr, const struct nlm_lock *lock)
105 {
106         const struct file_lock *fl = &lock->fl;
107         s32 start, len;
108
109         /* exclusive */
110         if (xdr_stream_encode_bool(xdr, fl->fl_type != F_RDLCK) < 0)
111                 return false;
112         if (xdr_stream_encode_u32(xdr, lock->svid) < 0)
113                 return false;
114         if (!svcxdr_encode_owner(xdr, &lock->oh))
115                 return false;
116         start = loff_t_to_s32(fl->fl_start);
117         if (fl->fl_end == OFFSET_MAX)
118                 len = 0;
119         else
120                 len = loff_t_to_s32(fl->fl_end - fl->fl_start + 1);
121         if (xdr_stream_encode_u32(xdr, start) < 0)
122                 return false;
123         if (xdr_stream_encode_u32(xdr, len) < 0)
124                 return false;
125
126         return true;
127 }
128
129 static bool
130 svcxdr_encode_testrply(struct xdr_stream *xdr, const struct nlm_res *resp)
131 {
132         if (!svcxdr_encode_stats(xdr, resp->status))
133                 return false;
134         switch (resp->status) {
135         case nlm_lck_denied:
136                 if (!svcxdr_encode_holder(xdr, &resp->lock))
137                         return false;
138         }
139
140         return true;
141 }
142
143
144 /*
145  * Decode Call arguments
146  */
147
148 int
149 nlmsvc_decode_void(struct svc_rqst *rqstp, __be32 *p)
150 {
151         return 1;
152 }
153
154 int
155 nlmsvc_decode_testargs(struct svc_rqst *rqstp, __be32 *p)
156 {
157         struct xdr_stream *xdr = &rqstp->rq_arg_stream;
158         struct nlm_args *argp = rqstp->rq_argp;
159         u32 exclusive;
160
161         if (!svcxdr_decode_cookie(xdr, &argp->cookie))
162                 return 0;
163         if (xdr_stream_decode_bool(xdr, &exclusive) < 0)
164                 return 0;
165         if (!svcxdr_decode_lock(xdr, &argp->lock))
166                 return 0;
167         if (exclusive)
168                 argp->lock.fl.fl_type = F_WRLCK;
169
170         return 1;
171 }
172
173 int
174 nlmsvc_decode_lockargs(struct svc_rqst *rqstp, __be32 *p)
175 {
176         struct xdr_stream *xdr = &rqstp->rq_arg_stream;
177         struct nlm_args *argp = rqstp->rq_argp;
178         u32 exclusive;
179
180         if (!svcxdr_decode_cookie(xdr, &argp->cookie))
181                 return 0;
182         if (xdr_stream_decode_bool(xdr, &argp->block) < 0)
183                 return 0;
184         if (xdr_stream_decode_bool(xdr, &exclusive) < 0)
185                 return 0;
186         if (!svcxdr_decode_lock(xdr, &argp->lock))
187                 return 0;
188         if (exclusive)
189                 argp->lock.fl.fl_type = F_WRLCK;
190         if (xdr_stream_decode_bool(xdr, &argp->reclaim) < 0)
191                 return 0;
192         if (xdr_stream_decode_u32(xdr, &argp->state) < 0)
193                 return 0;
194         argp->monitor = 1;              /* monitor client by default */
195
196         return 1;
197 }
198
199 int
200 nlmsvc_decode_cancargs(struct svc_rqst *rqstp, __be32 *p)
201 {
202         struct xdr_stream *xdr = &rqstp->rq_arg_stream;
203         struct nlm_args *argp = rqstp->rq_argp;
204         u32 exclusive;
205
206         if (!svcxdr_decode_cookie(xdr, &argp->cookie))
207                 return 0;
208         if (xdr_stream_decode_bool(xdr, &argp->block) < 0)
209                 return 0;
210         if (xdr_stream_decode_bool(xdr, &exclusive) < 0)
211                 return 0;
212         if (!svcxdr_decode_lock(xdr, &argp->lock))
213                 return 0;
214         if (exclusive)
215                 argp->lock.fl.fl_type = F_WRLCK;
216
217         return 1;
218 }
219
220 int
221 nlmsvc_decode_unlockargs(struct svc_rqst *rqstp, __be32 *p)
222 {
223         struct xdr_stream *xdr = &rqstp->rq_arg_stream;
224         struct nlm_args *argp = rqstp->rq_argp;
225
226         if (!svcxdr_decode_cookie(xdr, &argp->cookie))
227                 return 0;
228         if (!svcxdr_decode_lock(xdr, &argp->lock))
229                 return 0;
230         argp->lock.fl.fl_type = F_UNLCK;
231
232         return 1;
233 }
234
235 int
236 nlmsvc_decode_res(struct svc_rqst *rqstp, __be32 *p)
237 {
238         struct xdr_stream *xdr = &rqstp->rq_arg_stream;
239         struct nlm_res *resp = rqstp->rq_argp;
240
241         if (!svcxdr_decode_cookie(xdr, &resp->cookie))
242                 return 0;
243         if (!svcxdr_decode_stats(xdr, &resp->status))
244                 return 0;
245
246         return 1;
247 }
248
249 int
250 nlmsvc_decode_reboot(struct svc_rqst *rqstp, __be32 *p)
251 {
252         struct xdr_stream *xdr = &rqstp->rq_arg_stream;
253         struct nlm_reboot *argp = rqstp->rq_argp;
254         u32 len;
255
256         if (xdr_stream_decode_u32(xdr, &len) < 0)
257                 return 0;
258         if (len > SM_MAXSTRLEN)
259                 return 0;
260         p = xdr_inline_decode(xdr, len);
261         if (!p)
262                 return 0;
263         argp->len = len;
264         argp->mon = (char *)p;
265         if (xdr_stream_decode_u32(xdr, &argp->state) < 0)
266                 return 0;
267         p = xdr_inline_decode(xdr, SM_PRIV_SIZE);
268         if (!p)
269                 return 0;
270         memcpy(&argp->priv.data, p, sizeof(argp->priv.data));
271
272         return 1;
273 }
274
275 int
276 nlmsvc_decode_shareargs(struct svc_rqst *rqstp, __be32 *p)
277 {
278         struct xdr_stream *xdr = &rqstp->rq_arg_stream;
279         struct nlm_args *argp = rqstp->rq_argp;
280         struct nlm_lock *lock = &argp->lock;
281
282         memset(lock, 0, sizeof(*lock));
283         locks_init_lock(&lock->fl);
284         lock->svid = ~(u32)0;
285
286         if (!svcxdr_decode_cookie(xdr, &argp->cookie))
287                 return 0;
288         if (!svcxdr_decode_string(xdr, &lock->caller, &lock->len))
289                 return 0;
290         if (!svcxdr_decode_fhandle(xdr, &lock->fh))
291                 return 0;
292         if (!svcxdr_decode_owner(xdr, &lock->oh))
293                 return 0;
294         /* XXX: Range checks are missing in the original code */
295         if (xdr_stream_decode_u32(xdr, &argp->fsm_mode) < 0)
296                 return 0;
297         if (xdr_stream_decode_u32(xdr, &argp->fsm_access) < 0)
298                 return 0;
299
300         return 1;
301 }
302
303 int
304 nlmsvc_decode_notify(struct svc_rqst *rqstp, __be32 *p)
305 {
306         struct xdr_stream *xdr = &rqstp->rq_arg_stream;
307         struct nlm_args *argp = rqstp->rq_argp;
308         struct nlm_lock *lock = &argp->lock;
309
310         if (!svcxdr_decode_string(xdr, &lock->caller, &lock->len))
311                 return 0;
312         if (xdr_stream_decode_u32(xdr, &argp->state) < 0)
313                 return 0;
314
315         return 1;
316 }
317
318
319 /*
320  * Encode Reply results
321  */
322
323 int
324 nlmsvc_encode_void(struct svc_rqst *rqstp, __be32 *p)
325 {
326         return 1;
327 }
328
329 int
330 nlmsvc_encode_testres(struct svc_rqst *rqstp, __be32 *p)
331 {
332         struct xdr_stream *xdr = &rqstp->rq_res_stream;
333         struct nlm_res *resp = rqstp->rq_resp;
334
335         return svcxdr_encode_cookie(xdr, &resp->cookie) &&
336                 svcxdr_encode_testrply(xdr, resp);
337 }
338
339 int
340 nlmsvc_encode_res(struct svc_rqst *rqstp, __be32 *p)
341 {
342         struct xdr_stream *xdr = &rqstp->rq_res_stream;
343         struct nlm_res *resp = rqstp->rq_resp;
344
345         return svcxdr_encode_cookie(xdr, &resp->cookie) &&
346                 svcxdr_encode_stats(xdr, resp->status);
347 }
348
349 int
350 nlmsvc_encode_shareres(struct svc_rqst *rqstp, __be32 *p)
351 {
352         struct xdr_stream *xdr = &rqstp->rq_res_stream;
353         struct nlm_res *resp = rqstp->rq_resp;
354
355         if (!svcxdr_encode_cookie(xdr, &resp->cookie))
356                 return 0;
357         if (!svcxdr_encode_stats(xdr, resp->status))
358                 return 0;
359         /* sequence */
360         if (xdr_stream_encode_u32(xdr, 0) < 0)
361                 return 0;
362
363         return 1;
364 }