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