1 // SPDX-License-Identifier: GPL-2.0
3 * linux/fs/lockd/xdr4.c
5 * XDR support for lockd and the lock client.
7 * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de>
8 * Copyright (C) 1999, Trond Myklebust <trond.myklebust@fys.uio.no>
11 #include <linux/types.h>
12 #include <linux/sched.h>
13 #include <linux/nfs.h>
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>
21 #define NLMDBG_FACILITY NLMDBG_XDR
24 s64_to_loff_t(__s64 offset
)
26 return (loff_t
)offset
;
31 loff_t_to_s64(loff_t offset
)
34 if (offset
> NLM4_OFFSET_MAX
)
35 res
= NLM4_OFFSET_MAX
;
36 else if (offset
< -NLM4_OFFSET_MAX
)
37 res
= -NLM4_OFFSET_MAX
;
44 * XDR functions for basic NLM types
47 nlm4_decode_cookie(__be32
*p
, struct nlm_cookie
*c
)
56 memset(c
->data
, 0, 4); /* hockeypux brain damage */
58 else if(len
<=NLM_MAXCOOKIELEN
)
61 memcpy(c
->data
, p
, len
);
66 dprintk("lockd: bad cookie size %d (only cookies under "
67 "%d bytes are supported.)\n",
68 len
, NLM_MAXCOOKIELEN
);
75 nlm4_encode_cookie(__be32
*p
, struct nlm_cookie
*c
)
78 memcpy(p
, c
->data
, c
->len
);
79 p
+=XDR_QUADLEN(c
->len
);
84 nlm4_decode_fh(__be32
*p
, struct nfs_fh
*f
)
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
);
93 memcpy(f
->data
, p
, f
->size
);
94 return p
+ XDR_QUADLEN(f
->size
);
98 * Encode and decode owner handle
101 nlm4_decode_oh(__be32
*p
, struct xdr_netobj
*oh
)
103 return xdr_decode_netobj(p
, oh
);
107 nlm4_decode_lock(__be32
*p
, struct nlm_lock
*lock
)
109 struct file_lock
*fl
= &lock
->fl
;
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
)))
118 lock
->svid
= ntohl(*p
++);
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;
127 fl
->fl_start
= s64_to_loff_t(start
);
129 if (len
== 0 || end
< 0)
130 fl
->fl_end
= OFFSET_MAX
;
132 fl
->fl_end
= s64_to_loff_t(end
);
137 * Encode result of a TEST/TEST_MSG call
140 nlm4_encode_testres(__be32
*p
, struct nlm_res
*resp
)
144 dprintk("xdr: before encode_testres (p %p resp %p)\n", p
, resp
);
145 if (!(p
= nlm4_encode_cookie(p
, &resp
->cookie
)))
149 if (resp
->status
== nlm_lck_denied
) {
150 struct file_lock
*fl
= &resp
->lock
.fl
;
152 *p
++ = (fl
->fl_type
== F_RDLCK
)? xdr_zero
: xdr_one
;
153 *p
++ = htonl(resp
->lock
.svid
);
155 /* Encode owner handle. */
156 if (!(p
= xdr_encode_netobj(p
, &resp
->lock
.oh
)))
159 start
= loff_t_to_s64(fl
->fl_start
);
160 if (fl
->fl_end
== OFFSET_MAX
)
163 len
= loff_t_to_s64(fl
->fl_end
- fl
->fl_start
+ 1);
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
);
172 dprintk("xdr: after encode_testres (p %p resp %p)\n", p
, resp
);
178 * First, the server side XDR functions
181 nlm4svc_decode_testargs(struct svc_rqst
*rqstp
, __be32
*p
)
183 struct nlm_args
*argp
= rqstp
->rq_argp
;
186 if (!(p
= nlm4_decode_cookie(p
, &argp
->cookie
)))
189 exclusive
= ntohl(*p
++);
190 if (!(p
= nlm4_decode_lock(p
, &argp
->lock
)))
193 argp
->lock
.fl
.fl_type
= F_WRLCK
;
195 return xdr_argsize_check(rqstp
, p
);
199 nlm4svc_encode_testres(struct svc_rqst
*rqstp
, __be32
*p
)
201 struct nlm_res
*resp
= rqstp
->rq_resp
;
203 if (!(p
= nlm4_encode_testres(p
, resp
)))
205 return xdr_ressize_check(rqstp
, p
);
209 nlm4svc_decode_lockargs(struct svc_rqst
*rqstp
, __be32
*p
)
211 struct nlm_args
*argp
= rqstp
->rq_argp
;
214 if (!(p
= nlm4_decode_cookie(p
, &argp
->cookie
)))
216 argp
->block
= ntohl(*p
++);
217 exclusive
= ntohl(*p
++);
218 if (!(p
= nlm4_decode_lock(p
, &argp
->lock
)))
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 */
226 return xdr_argsize_check(rqstp
, p
);
230 nlm4svc_decode_cancargs(struct svc_rqst
*rqstp
, __be32
*p
)
232 struct nlm_args
*argp
= rqstp
->rq_argp
;
235 if (!(p
= nlm4_decode_cookie(p
, &argp
->cookie
)))
237 argp
->block
= ntohl(*p
++);
238 exclusive
= ntohl(*p
++);
239 if (!(p
= nlm4_decode_lock(p
, &argp
->lock
)))
242 argp
->lock
.fl
.fl_type
= F_WRLCK
;
243 return xdr_argsize_check(rqstp
, p
);
247 nlm4svc_decode_unlockargs(struct svc_rqst
*rqstp
, __be32
*p
)
249 struct nlm_args
*argp
= rqstp
->rq_argp
;
251 if (!(p
= nlm4_decode_cookie(p
, &argp
->cookie
))
252 || !(p
= nlm4_decode_lock(p
, &argp
->lock
)))
254 argp
->lock
.fl
.fl_type
= F_UNLCK
;
255 return xdr_argsize_check(rqstp
, p
);
259 nlm4svc_decode_shareargs(struct svc_rqst
*rqstp
, __be32
*p
)
261 struct nlm_args
*argp
= rqstp
->rq_argp
;
262 struct nlm_lock
*lock
= &argp
->lock
;
264 memset(lock
, 0, sizeof(*lock
));
265 locks_init_lock(&lock
->fl
);
266 lock
->svid
= ~(u32
) 0;
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
)))
274 argp
->fsm_mode
= ntohl(*p
++);
275 argp
->fsm_access
= ntohl(*p
++);
276 return xdr_argsize_check(rqstp
, p
);
280 nlm4svc_encode_shareres(struct svc_rqst
*rqstp
, __be32
*p
)
282 struct nlm_res
*resp
= rqstp
->rq_resp
;
284 if (!(p
= nlm4_encode_cookie(p
, &resp
->cookie
)))
287 *p
++ = xdr_zero
; /* sequence argument */
288 return xdr_ressize_check(rqstp
, p
);
292 nlm4svc_encode_res(struct svc_rqst
*rqstp
, __be32
*p
)
294 struct nlm_res
*resp
= rqstp
->rq_resp
;
296 if (!(p
= nlm4_encode_cookie(p
, &resp
->cookie
)))
299 return xdr_ressize_check(rqstp
, p
);
303 nlm4svc_decode_notify(struct svc_rqst
*rqstp
, __be32
*p
)
305 struct nlm_args
*argp
= rqstp
->rq_argp
;
306 struct nlm_lock
*lock
= &argp
->lock
;
308 if (!(p
= xdr_decode_string_inplace(p
, &lock
->caller
,
309 &lock
->len
, NLM_MAXSTRLEN
)))
311 argp
->state
= ntohl(*p
++);
312 return xdr_argsize_check(rqstp
, p
);
316 nlm4svc_decode_reboot(struct svc_rqst
*rqstp
, __be32
*p
)
318 struct nlm_reboot
*argp
= rqstp
->rq_argp
;
320 if (!(p
= xdr_decode_string_inplace(p
, &argp
->mon
, &argp
->len
, SM_MAXSTRLEN
)))
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
);
329 nlm4svc_decode_res(struct svc_rqst
*rqstp
, __be32
*p
)
331 struct nlm_res
*resp
= rqstp
->rq_argp
;
333 if (!(p
= nlm4_decode_cookie(p
, &resp
->cookie
)))
336 return xdr_argsize_check(rqstp
, p
);
340 nlm4svc_decode_void(struct svc_rqst
*rqstp
, __be32
*p
)
342 return xdr_argsize_check(rqstp
, p
);
346 nlm4svc_encode_void(struct svc_rqst
*rqstp
, __be32
*p
)
348 return xdr_ressize_check(rqstp
, p
);