xref: /openbmc/linux/fs/lockd/xdr4.c (revision 7956521a)
1 // SPDX-License-Identifier: GPL-2.0
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>
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>
20 
21 #include "svcxdr.h"
22 
23 #define NLMDBG_FACILITY		NLMDBG_XDR
24 
25 static inline loff_t
26 s64_to_loff_t(__s64 offset)
27 {
28 	return (loff_t)offset;
29 }
30 
31 
32 static inline s64
33 loff_t_to_s64(loff_t offset)
34 {
35 	s64 res;
36 	if (offset > NLM4_OFFSET_MAX)
37 		res = NLM4_OFFSET_MAX;
38 	else if (offset < -NLM4_OFFSET_MAX)
39 		res = -NLM4_OFFSET_MAX;
40 	else
41 		res = offset;
42 	return res;
43 }
44 
45 /*
46  * XDR functions for basic NLM types
47  */
48 static __be32 *
49 nlm4_decode_cookie(__be32 *p, struct nlm_cookie *c)
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 	{
68 		dprintk("lockd: bad cookie size %d (only cookies under "
69 			"%d bytes are supported.)\n",
70 				len, NLM_MAXCOOKIELEN);
71 		return NULL;
72 	}
73 	return p;
74 }
75 
76 static __be32 *
77 nlm4_encode_cookie(__be32 *p, struct nlm_cookie *c)
78 {
79 	*p++ = htonl(c->len);
80 	memcpy(p, c->data, c->len);
81 	p+=XDR_QUADLEN(c->len);
82 	return p;
83 }
84 
85 static __be32 *
86 nlm4_decode_fh(__be32 *p, struct nfs_fh *f)
87 {
88 	memset(f->data, 0, sizeof(f->data));
89 	f->size = ntohl(*p++);
90 	if (f->size > NFS_MAXFHSIZE) {
91 		dprintk("lockd: bad fhandle size %d (should be <=%d)\n",
92 			f->size, NFS_MAXFHSIZE);
93 		return NULL;
94 	}
95       	memcpy(f->data, p, f->size);
96 	return p + XDR_QUADLEN(f->size);
97 }
98 
99 /*
100  * Encode and decode owner handle
101  */
102 static __be32 *
103 nlm4_decode_oh(__be32 *p, struct xdr_netobj *oh)
104 {
105 	return xdr_decode_netobj(p, oh);
106 }
107 
108 static __be32 *
109 nlm4_decode_lock(__be32 *p, struct nlm_lock *lock)
110 {
111 	struct file_lock	*fl = &lock->fl;
112 	__u64			len, start;
113 	__s64			end;
114 
115 	if (!(p = xdr_decode_string_inplace(p, &lock->caller,
116 					    &lock->len, NLM_MAXSTRLEN))
117 	 || !(p = nlm4_decode_fh(p, &lock->fh))
118 	 || !(p = nlm4_decode_oh(p, &lock->oh)))
119 		return NULL;
120 	lock->svid  = ntohl(*p++);
121 
122 	locks_init_lock(fl);
123 	fl->fl_flags = FL_POSIX;
124 	fl->fl_type  = F_RDLCK;		/* as good as anything else */
125 	p = xdr_decode_hyper(p, &start);
126 	p = xdr_decode_hyper(p, &len);
127 	end = start + len - 1;
128 
129 	fl->fl_start = s64_to_loff_t(start);
130 
131 	if (len == 0 || end < 0)
132 		fl->fl_end = OFFSET_MAX;
133 	else
134 		fl->fl_end = s64_to_loff_t(end);
135 	return p;
136 }
137 
138 /*
139  * Encode result of a TEST/TEST_MSG call
140  */
141 static __be32 *
142 nlm4_encode_testres(__be32 *p, struct nlm_res *resp)
143 {
144 	s64		start, len;
145 
146 	dprintk("xdr: before encode_testres (p %p resp %p)\n", p, resp);
147 	if (!(p = nlm4_encode_cookie(p, &resp->cookie)))
148 		return NULL;
149 	*p++ = resp->status;
150 
151 	if (resp->status == nlm_lck_denied) {
152 		struct file_lock	*fl = &resp->lock.fl;
153 
154 		*p++ = (fl->fl_type == F_RDLCK)? xdr_zero : xdr_one;
155 		*p++ = htonl(resp->lock.svid);
156 
157 		/* Encode owner handle. */
158 		if (!(p = xdr_encode_netobj(p, &resp->lock.oh)))
159 			return NULL;
160 
161 		start = loff_t_to_s64(fl->fl_start);
162 		if (fl->fl_end == OFFSET_MAX)
163 			len = 0;
164 		else
165 			len = loff_t_to_s64(fl->fl_end - fl->fl_start + 1);
166 
167 		p = xdr_encode_hyper(p, start);
168 		p = xdr_encode_hyper(p, len);
169 		dprintk("xdr: encode_testres (status %u pid %d type %d start %Ld end %Ld)\n",
170 			resp->status, (int)resp->lock.svid, fl->fl_type,
171 			(long long)fl->fl_start,  (long long)fl->fl_end);
172 	}
173 
174 	dprintk("xdr: after encode_testres (p %p resp %p)\n", p, resp);
175 	return p;
176 }
177 
178 
179 /*
180  * Decode Call arguments
181  */
182 
183 int
184 nlm4svc_decode_void(struct svc_rqst *rqstp, __be32 *p)
185 {
186 	return 1;
187 }
188 
189 int
190 nlm4svc_decode_testargs(struct svc_rqst *rqstp, __be32 *p)
191 {
192 	struct nlm_args *argp = rqstp->rq_argp;
193 	u32	exclusive;
194 
195 	if (!(p = nlm4_decode_cookie(p, &argp->cookie)))
196 		return 0;
197 
198 	exclusive = ntohl(*p++);
199 	if (!(p = nlm4_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 
207 int
208 nlm4svc_encode_testres(struct svc_rqst *rqstp, __be32 *p)
209 {
210 	struct nlm_res *resp = rqstp->rq_resp;
211 
212 	if (!(p = nlm4_encode_testres(p, resp)))
213 		return 0;
214 	return xdr_ressize_check(rqstp, p);
215 }
216 
217 int
218 nlm4svc_decode_lockargs(struct svc_rqst *rqstp, __be32 *p)
219 {
220 	struct nlm_args *argp = rqstp->rq_argp;
221 	u32	exclusive;
222 
223 	if (!(p = nlm4_decode_cookie(p, &argp->cookie)))
224 		return 0;
225 	argp->block  = ntohl(*p++);
226 	exclusive    = ntohl(*p++);
227 	if (!(p = nlm4_decode_lock(p, &argp->lock)))
228 		return 0;
229 	if (exclusive)
230 		argp->lock.fl.fl_type = F_WRLCK;
231 	argp->reclaim = ntohl(*p++);
232 	argp->state   = ntohl(*p++);
233 	argp->monitor = 1;		/* monitor client by default */
234 
235 	return xdr_argsize_check(rqstp, p);
236 }
237 
238 int
239 nlm4svc_decode_cancargs(struct svc_rqst *rqstp, __be32 *p)
240 {
241 	struct nlm_args *argp = rqstp->rq_argp;
242 	u32	exclusive;
243 
244 	if (!(p = nlm4_decode_cookie(p, &argp->cookie)))
245 		return 0;
246 	argp->block = ntohl(*p++);
247 	exclusive = ntohl(*p++);
248 	if (!(p = nlm4_decode_lock(p, &argp->lock)))
249 		return 0;
250 	if (exclusive)
251 		argp->lock.fl.fl_type = F_WRLCK;
252 	return xdr_argsize_check(rqstp, p);
253 }
254 
255 int
256 nlm4svc_decode_unlockargs(struct svc_rqst *rqstp, __be32 *p)
257 {
258 	struct nlm_args *argp = rqstp->rq_argp;
259 
260 	if (!(p = nlm4_decode_cookie(p, &argp->cookie))
261 	 || !(p = nlm4_decode_lock(p, &argp->lock)))
262 		return 0;
263 	argp->lock.fl.fl_type = F_UNLCK;
264 	return xdr_argsize_check(rqstp, p);
265 }
266 
267 int
268 nlm4svc_decode_shareargs(struct svc_rqst *rqstp, __be32 *p)
269 {
270 	struct nlm_args *argp = rqstp->rq_argp;
271 	struct nlm_lock	*lock = &argp->lock;
272 
273 	memset(lock, 0, sizeof(*lock));
274 	locks_init_lock(&lock->fl);
275 	lock->svid = ~(u32) 0;
276 
277 	if (!(p = nlm4_decode_cookie(p, &argp->cookie))
278 	 || !(p = xdr_decode_string_inplace(p, &lock->caller,
279 					    &lock->len, NLM_MAXSTRLEN))
280 	 || !(p = nlm4_decode_fh(p, &lock->fh))
281 	 || !(p = nlm4_decode_oh(p, &lock->oh)))
282 		return 0;
283 	argp->fsm_mode = ntohl(*p++);
284 	argp->fsm_access = ntohl(*p++);
285 	return xdr_argsize_check(rqstp, p);
286 }
287 
288 int
289 nlm4svc_encode_shareres(struct svc_rqst *rqstp, __be32 *p)
290 {
291 	struct nlm_res *resp = rqstp->rq_resp;
292 
293 	if (!(p = nlm4_encode_cookie(p, &resp->cookie)))
294 		return 0;
295 	*p++ = resp->status;
296 	*p++ = xdr_zero;		/* sequence argument */
297 	return xdr_ressize_check(rqstp, p);
298 }
299 
300 int
301 nlm4svc_encode_res(struct svc_rqst *rqstp, __be32 *p)
302 {
303 	struct nlm_res *resp = rqstp->rq_resp;
304 
305 	if (!(p = nlm4_encode_cookie(p, &resp->cookie)))
306 		return 0;
307 	*p++ = resp->status;
308 	return xdr_ressize_check(rqstp, p);
309 }
310 
311 int
312 nlm4svc_decode_notify(struct svc_rqst *rqstp, __be32 *p)
313 {
314 	struct nlm_args *argp = rqstp->rq_argp;
315 	struct nlm_lock	*lock = &argp->lock;
316 
317 	if (!(p = xdr_decode_string_inplace(p, &lock->caller,
318 					    &lock->len, NLM_MAXSTRLEN)))
319 		return 0;
320 	argp->state = ntohl(*p++);
321 	return xdr_argsize_check(rqstp, p);
322 }
323 
324 int
325 nlm4svc_decode_reboot(struct svc_rqst *rqstp, __be32 *p)
326 {
327 	struct nlm_reboot *argp = rqstp->rq_argp;
328 
329 	if (!(p = xdr_decode_string_inplace(p, &argp->mon, &argp->len, SM_MAXSTRLEN)))
330 		return 0;
331 	argp->state = ntohl(*p++);
332 	memcpy(&argp->priv.data, p, sizeof(argp->priv.data));
333 	p += XDR_QUADLEN(SM_PRIV_SIZE);
334 	return xdr_argsize_check(rqstp, p);
335 }
336 
337 int
338 nlm4svc_decode_res(struct svc_rqst *rqstp, __be32 *p)
339 {
340 	struct nlm_res *resp = rqstp->rq_argp;
341 
342 	if (!(p = nlm4_decode_cookie(p, &resp->cookie)))
343 		return 0;
344 	resp->status = *p++;
345 	return xdr_argsize_check(rqstp, p);
346 }
347 
348 int
349 nlm4svc_encode_void(struct svc_rqst *rqstp, __be32 *p)
350 {
351 	return xdr_ressize_check(rqstp, p);
352 }
353