Branch data Line data Source code
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 : 0 : 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 : 0 : nlm4_decode_cookie(__be32 *p, struct nlm_cookie *c)
48 : : {
49 : : unsigned int len;
50 : :
51 : 0 : len = ntohl(*p++);
52 : :
53 : 0 : if(len==0)
54 : : {
55 : 0 : c->len=4;
56 : 0 : memset(c->data, 0, 4); /* hockeypux brain damage */
57 : : }
58 : 0 : else if(len<=NLM_MAXCOOKIELEN)
59 : : {
60 : 0 : c->len=len;
61 : 0 : memcpy(c->data, p, len);
62 : 0 : 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 : 0 : return p;
72 : : }
73 : :
74 : : static __be32 *
75 : 0 : nlm4_encode_cookie(__be32 *p, struct nlm_cookie *c)
76 : : {
77 : 0 : *p++ = htonl(c->len);
78 : 0 : memcpy(p, c->data, c->len);
79 : 0 : p+=XDR_QUADLEN(c->len);
80 : 0 : return p;
81 : : }
82 : :
83 : : static __be32 *
84 : 0 : nlm4_decode_fh(__be32 *p, struct nfs_fh *f)
85 : : {
86 : 0 : memset(f->data, 0, sizeof(f->data));
87 : 0 : f->size = ntohl(*p++);
88 : 0 : 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 : 0 : memcpy(f->data, p, f->size);
94 : 0 : 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 : 0 : return xdr_decode_netobj(p, oh);
104 : : }
105 : :
106 : : static __be32 *
107 : 0 : nlm4_decode_lock(__be32 *p, struct nlm_lock *lock)
108 : : {
109 : 0 : struct file_lock *fl = &lock->fl;
110 : : __u64 len, start;
111 : : __s64 end;
112 : :
113 : 0 : if (!(p = xdr_decode_string_inplace(p, &lock->caller,
114 : : &lock->len, NLM_MAXSTRLEN))
115 : 0 : || !(p = nlm4_decode_fh(p, &lock->fh))
116 : 0 : || !(p = nlm4_decode_oh(p, &lock->oh)))
117 : : return NULL;
118 : 0 : lock->svid = ntohl(*p++);
119 : :
120 : 0 : locks_init_lock(fl);
121 : 0 : fl->fl_flags = FL_POSIX;
122 : 0 : 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 : 0 : end = start + len - 1;
126 : :
127 : 0 : fl->fl_start = s64_to_loff_t(start);
128 : :
129 : 0 : if (len == 0 || end < 0)
130 : 0 : fl->fl_end = OFFSET_MAX;
131 : : else
132 : 0 : fl->fl_end = s64_to_loff_t(end);
133 : 0 : return p;
134 : : }
135 : :
136 : : /*
137 : : * Encode result of a TEST/TEST_MSG call
138 : : */
139 : : static __be32 *
140 : 0 : 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 : 0 : if (!(p = nlm4_encode_cookie(p, &resp->cookie)))
146 : : return NULL;
147 : 0 : *p++ = resp->status;
148 : :
149 : 0 : if (resp->status == nlm_lck_denied) {
150 : : struct file_lock *fl = &resp->lock.fl;
151 : :
152 : 0 : *p++ = (fl->fl_type == F_RDLCK)? xdr_zero : xdr_one;
153 : 0 : *p++ = htonl(resp->lock.svid);
154 : :
155 : : /* Encode owner handle. */
156 : 0 : if (!(p = xdr_encode_netobj(p, &resp->lock.oh)))
157 : : return NULL;
158 : :
159 : 0 : start = loff_t_to_s64(fl->fl_start);
160 : 0 : if (fl->fl_end == OFFSET_MAX)
161 : : len = 0;
162 : : else
163 : 0 : len = loff_t_to_s64(fl->fl_end - fl->fl_start + 1);
164 : :
165 : 0 : p = xdr_encode_hyper(p, start);
166 : 0 : 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 : 0 : return p;
174 : : }
175 : :
176 : :
177 : : /*
178 : : * First, the server side XDR functions
179 : : */
180 : : int
181 : 0 : nlm4svc_decode_testargs(struct svc_rqst *rqstp, __be32 *p)
182 : : {
183 : 0 : struct nlm_args *argp = rqstp->rq_argp;
184 : : u32 exclusive;
185 : :
186 : 0 : if (!(p = nlm4_decode_cookie(p, &argp->cookie)))
187 : : return 0;
188 : :
189 : 0 : exclusive = ntohl(*p++);
190 : 0 : if (!(p = nlm4_decode_lock(p, &argp->lock)))
191 : : return 0;
192 : 0 : if (exclusive)
193 : 0 : argp->lock.fl.fl_type = F_WRLCK;
194 : :
195 : 0 : return xdr_argsize_check(rqstp, p);
196 : : }
197 : :
198 : : int
199 : 0 : nlm4svc_encode_testres(struct svc_rqst *rqstp, __be32 *p)
200 : : {
201 : 0 : struct nlm_res *resp = rqstp->rq_resp;
202 : :
203 : 0 : if (!(p = nlm4_encode_testres(p, resp)))
204 : : return 0;
205 : 0 : return xdr_ressize_check(rqstp, p);
206 : : }
207 : :
208 : : int
209 : 0 : nlm4svc_decode_lockargs(struct svc_rqst *rqstp, __be32 *p)
210 : : {
211 : 0 : struct nlm_args *argp = rqstp->rq_argp;
212 : : u32 exclusive;
213 : :
214 : 0 : if (!(p = nlm4_decode_cookie(p, &argp->cookie)))
215 : : return 0;
216 : 0 : argp->block = ntohl(*p++);
217 : 0 : exclusive = ntohl(*p++);
218 : 0 : if (!(p = nlm4_decode_lock(p, &argp->lock)))
219 : : return 0;
220 : 0 : if (exclusive)
221 : 0 : argp->lock.fl.fl_type = F_WRLCK;
222 : 0 : argp->reclaim = ntohl(*p++);
223 : 0 : argp->state = ntohl(*p++);
224 : 0 : argp->monitor = 1; /* monitor client by default */
225 : :
226 : 0 : return xdr_argsize_check(rqstp, p);
227 : : }
228 : :
229 : : int
230 : 0 : nlm4svc_decode_cancargs(struct svc_rqst *rqstp, __be32 *p)
231 : : {
232 : 0 : struct nlm_args *argp = rqstp->rq_argp;
233 : : u32 exclusive;
234 : :
235 : 0 : if (!(p = nlm4_decode_cookie(p, &argp->cookie)))
236 : : return 0;
237 : 0 : argp->block = ntohl(*p++);
238 : 0 : exclusive = ntohl(*p++);
239 : 0 : if (!(p = nlm4_decode_lock(p, &argp->lock)))
240 : : return 0;
241 : 0 : if (exclusive)
242 : 0 : argp->lock.fl.fl_type = F_WRLCK;
243 : 0 : return xdr_argsize_check(rqstp, p);
244 : : }
245 : :
246 : : int
247 : 0 : nlm4svc_decode_unlockargs(struct svc_rqst *rqstp, __be32 *p)
248 : : {
249 : 0 : struct nlm_args *argp = rqstp->rq_argp;
250 : :
251 : 0 : if (!(p = nlm4_decode_cookie(p, &argp->cookie))
252 : 0 : || !(p = nlm4_decode_lock(p, &argp->lock)))
253 : : return 0;
254 : 0 : argp->lock.fl.fl_type = F_UNLCK;
255 : 0 : return xdr_argsize_check(rqstp, p);
256 : : }
257 : :
258 : : int
259 : 0 : nlm4svc_decode_shareargs(struct svc_rqst *rqstp, __be32 *p)
260 : : {
261 : 0 : struct nlm_args *argp = rqstp->rq_argp;
262 : 0 : struct nlm_lock *lock = &argp->lock;
263 : :
264 : 0 : memset(lock, 0, sizeof(*lock));
265 : 0 : locks_init_lock(&lock->fl);
266 : 0 : lock->svid = ~(u32) 0;
267 : :
268 : 0 : if (!(p = nlm4_decode_cookie(p, &argp->cookie))
269 : 0 : || !(p = xdr_decode_string_inplace(p, &lock->caller,
270 : : &lock->len, NLM_MAXSTRLEN))
271 : 0 : || !(p = nlm4_decode_fh(p, &lock->fh))
272 : 0 : || !(p = nlm4_decode_oh(p, &lock->oh)))
273 : : return 0;
274 : 0 : argp->fsm_mode = ntohl(*p++);
275 : 0 : argp->fsm_access = ntohl(*p++);
276 : 0 : return xdr_argsize_check(rqstp, p);
277 : : }
278 : :
279 : : int
280 : 0 : nlm4svc_encode_shareres(struct svc_rqst *rqstp, __be32 *p)
281 : : {
282 : 0 : struct nlm_res *resp = rqstp->rq_resp;
283 : :
284 : 0 : if (!(p = nlm4_encode_cookie(p, &resp->cookie)))
285 : : return 0;
286 : 0 : *p++ = resp->status;
287 : 0 : *p++ = xdr_zero; /* sequence argument */
288 : 0 : return xdr_ressize_check(rqstp, p);
289 : : }
290 : :
291 : : int
292 : 0 : nlm4svc_encode_res(struct svc_rqst *rqstp, __be32 *p)
293 : : {
294 : 0 : struct nlm_res *resp = rqstp->rq_resp;
295 : :
296 : 0 : if (!(p = nlm4_encode_cookie(p, &resp->cookie)))
297 : : return 0;
298 : 0 : *p++ = resp->status;
299 : 0 : return xdr_ressize_check(rqstp, p);
300 : : }
301 : :
302 : : int
303 : 0 : nlm4svc_decode_notify(struct svc_rqst *rqstp, __be32 *p)
304 : : {
305 : 0 : struct nlm_args *argp = rqstp->rq_argp;
306 : : struct nlm_lock *lock = &argp->lock;
307 : :
308 : 0 : if (!(p = xdr_decode_string_inplace(p, &lock->caller,
309 : : &lock->len, NLM_MAXSTRLEN)))
310 : : return 0;
311 : 0 : argp->state = ntohl(*p++);
312 : 0 : return xdr_argsize_check(rqstp, p);
313 : : }
314 : :
315 : : int
316 : 0 : nlm4svc_decode_reboot(struct svc_rqst *rqstp, __be32 *p)
317 : : {
318 : 0 : struct nlm_reboot *argp = rqstp->rq_argp;
319 : :
320 : 0 : if (!(p = xdr_decode_string_inplace(p, &argp->mon, &argp->len, SM_MAXSTRLEN)))
321 : : return 0;
322 : 0 : argp->state = ntohl(*p++);
323 : 0 : memcpy(&argp->priv.data, p, sizeof(argp->priv.data));
324 : 0 : p += XDR_QUADLEN(SM_PRIV_SIZE);
325 : 0 : return xdr_argsize_check(rqstp, p);
326 : : }
327 : :
328 : : int
329 : 0 : nlm4svc_decode_res(struct svc_rqst *rqstp, __be32 *p)
330 : : {
331 : 0 : struct nlm_res *resp = rqstp->rq_argp;
332 : :
333 : 0 : if (!(p = nlm4_decode_cookie(p, &resp->cookie)))
334 : : return 0;
335 : 0 : resp->status = *p++;
336 : 0 : return xdr_argsize_check(rqstp, p);
337 : : }
338 : :
339 : : int
340 : 0 : nlm4svc_decode_void(struct svc_rqst *rqstp, __be32 *p)
341 : : {
342 : 0 : return xdr_argsize_check(rqstp, p);
343 : : }
344 : :
345 : : int
346 : 0 : nlm4svc_encode_void(struct svc_rqst *rqstp, __be32 *p)
347 : : {
348 : 0 : return xdr_ressize_check(rqstp, p);
349 : : }
|