1 // SPDX-License-Identifier: GPL-2.0
5 * XDR support for lockd and the lock client.
7 * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de>
10 #include <linux/types.h>
11 #include <linux/sched.h>
12 #include <linux/nfs.h>
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>
20 #include <uapi/linux/nfs2.h>
26 s32_to_loff_t(__s32 offset
)
28 return (loff_t
)offset
;
32 loff_t_to_s32(loff_t offset
)
35 if (offset
>= NLM_OFFSET_MAX
)
37 else if (offset
<= -NLM_OFFSET_MAX
)
38 res
= -NLM_OFFSET_MAX
;
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
51 svcxdr_decode_fhandle(struct xdr_stream
*xdr
, struct nfs_fh
*fh
)
56 if (xdr_stream_decode_u32(xdr
, &len
) < 0)
58 if (len
!= NFS2_FHSIZE
)
61 p
= xdr_inline_decode(xdr
, len
);
64 fh
->size
= NFS2_FHSIZE
;
65 memcpy(fh
->data
, p
, len
);
66 memset(fh
->data
+ NFS2_FHSIZE
, 0, sizeof(fh
->data
) - NFS2_FHSIZE
);
72 svcxdr_decode_lock(struct xdr_stream
*xdr
, struct nlm_lock
*lock
)
74 struct file_lock
*fl
= &lock
->fl
;
77 if (!svcxdr_decode_string(xdr
, &lock
->caller
, &lock
->len
))
79 if (!svcxdr_decode_fhandle(xdr
, &lock
->fh
))
81 if (!svcxdr_decode_owner(xdr
, &lock
->oh
))
83 if (xdr_stream_decode_u32(xdr
, &lock
->svid
) < 0)
85 if (xdr_stream_decode_u32(xdr
, &start
) < 0)
87 if (xdr_stream_decode_u32(xdr
, &len
) < 0)
91 fl
->c
.flc_flags
= FL_POSIX
;
92 fl
->c
.flc_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
;
98 fl
->fl_end
= s32_to_loff_t(end
);
104 svcxdr_encode_holder(struct xdr_stream
*xdr
, const struct nlm_lock
*lock
)
106 const struct file_lock
*fl
= &lock
->fl
;
110 if (xdr_stream_encode_bool(xdr
, fl
->c
.flc_type
!= F_RDLCK
) < 0)
112 if (xdr_stream_encode_u32(xdr
, lock
->svid
) < 0)
114 if (!svcxdr_encode_owner(xdr
, &lock
->oh
))
116 start
= loff_t_to_s32(fl
->fl_start
);
117 if (fl
->fl_end
== OFFSET_MAX
)
120 len
= loff_t_to_s32(fl
->fl_end
- fl
->fl_start
+ 1);
121 if (xdr_stream_encode_u32(xdr
, start
) < 0)
123 if (xdr_stream_encode_u32(xdr
, len
) < 0)
130 svcxdr_encode_testrply(struct xdr_stream
*xdr
, const struct nlm_res
*resp
)
132 if (!svcxdr_encode_stats(xdr
, resp
->status
))
134 switch (resp
->status
) {
136 if (!svcxdr_encode_holder(xdr
, &resp
->lock
))
145 * Decode Call arguments
149 nlmsvc_decode_void(struct svc_rqst
*rqstp
, struct xdr_stream
*xdr
)
155 nlmsvc_decode_testargs(struct svc_rqst
*rqstp
, struct xdr_stream
*xdr
)
157 struct nlm_args
*argp
= rqstp
->rq_argp
;
160 if (!svcxdr_decode_cookie(xdr
, &argp
->cookie
))
162 if (xdr_stream_decode_bool(xdr
, &exclusive
) < 0)
164 if (!svcxdr_decode_lock(xdr
, &argp
->lock
))
167 argp
->lock
.fl
.c
.flc_type
= F_WRLCK
;
173 nlmsvc_decode_lockargs(struct svc_rqst
*rqstp
, struct xdr_stream
*xdr
)
175 struct nlm_args
*argp
= rqstp
->rq_argp
;
178 if (!svcxdr_decode_cookie(xdr
, &argp
->cookie
))
180 if (xdr_stream_decode_bool(xdr
, &argp
->block
) < 0)
182 if (xdr_stream_decode_bool(xdr
, &exclusive
) < 0)
184 if (!svcxdr_decode_lock(xdr
, &argp
->lock
))
187 argp
->lock
.fl
.c
.flc_type
= F_WRLCK
;
188 if (xdr_stream_decode_bool(xdr
, &argp
->reclaim
) < 0)
190 if (xdr_stream_decode_u32(xdr
, &argp
->state
) < 0)
192 argp
->monitor
= 1; /* monitor client by default */
198 nlmsvc_decode_cancargs(struct svc_rqst
*rqstp
, struct xdr_stream
*xdr
)
200 struct nlm_args
*argp
= rqstp
->rq_argp
;
203 if (!svcxdr_decode_cookie(xdr
, &argp
->cookie
))
205 if (xdr_stream_decode_bool(xdr
, &argp
->block
) < 0)
207 if (xdr_stream_decode_bool(xdr
, &exclusive
) < 0)
209 if (!svcxdr_decode_lock(xdr
, &argp
->lock
))
212 argp
->lock
.fl
.c
.flc_type
= F_WRLCK
;
218 nlmsvc_decode_unlockargs(struct svc_rqst
*rqstp
, struct xdr_stream
*xdr
)
220 struct nlm_args
*argp
= rqstp
->rq_argp
;
222 if (!svcxdr_decode_cookie(xdr
, &argp
->cookie
))
224 if (!svcxdr_decode_lock(xdr
, &argp
->lock
))
226 argp
->lock
.fl
.c
.flc_type
= F_UNLCK
;
232 nlmsvc_decode_res(struct svc_rqst
*rqstp
, struct xdr_stream
*xdr
)
234 struct nlm_res
*resp
= rqstp
->rq_argp
;
236 if (!svcxdr_decode_cookie(xdr
, &resp
->cookie
))
238 if (!svcxdr_decode_stats(xdr
, &resp
->status
))
245 nlmsvc_decode_reboot(struct svc_rqst
*rqstp
, struct xdr_stream
*xdr
)
247 struct nlm_reboot
*argp
= rqstp
->rq_argp
;
251 if (xdr_stream_decode_u32(xdr
, &len
) < 0)
253 if (len
> SM_MAXSTRLEN
)
255 p
= xdr_inline_decode(xdr
, len
);
259 argp
->mon
= (char *)p
;
260 if (xdr_stream_decode_u32(xdr
, &argp
->state
) < 0)
262 p
= xdr_inline_decode(xdr
, SM_PRIV_SIZE
);
265 memcpy(&argp
->priv
.data
, p
, sizeof(argp
->priv
.data
));
271 nlmsvc_decode_shareargs(struct svc_rqst
*rqstp
, struct xdr_stream
*xdr
)
273 struct nlm_args
*argp
= rqstp
->rq_argp
;
274 struct nlm_lock
*lock
= &argp
->lock
;
276 memset(lock
, 0, sizeof(*lock
));
277 locks_init_lock(&lock
->fl
);
278 lock
->svid
= ~(u32
)0;
280 if (!svcxdr_decode_cookie(xdr
, &argp
->cookie
))
282 if (!svcxdr_decode_string(xdr
, &lock
->caller
, &lock
->len
))
284 if (!svcxdr_decode_fhandle(xdr
, &lock
->fh
))
286 if (!svcxdr_decode_owner(xdr
, &lock
->oh
))
288 /* XXX: Range checks are missing in the original code */
289 if (xdr_stream_decode_u32(xdr
, &argp
->fsm_mode
) < 0)
291 if (xdr_stream_decode_u32(xdr
, &argp
->fsm_access
) < 0)
298 nlmsvc_decode_notify(struct svc_rqst
*rqstp
, struct xdr_stream
*xdr
)
300 struct nlm_args
*argp
= rqstp
->rq_argp
;
301 struct nlm_lock
*lock
= &argp
->lock
;
303 if (!svcxdr_decode_string(xdr
, &lock
->caller
, &lock
->len
))
305 if (xdr_stream_decode_u32(xdr
, &argp
->state
) < 0)
313 * Encode Reply results
317 nlmsvc_encode_void(struct svc_rqst
*rqstp
, struct xdr_stream
*xdr
)
323 nlmsvc_encode_testres(struct svc_rqst
*rqstp
, struct xdr_stream
*xdr
)
325 struct nlm_res
*resp
= rqstp
->rq_resp
;
327 return svcxdr_encode_cookie(xdr
, &resp
->cookie
) &&
328 svcxdr_encode_testrply(xdr
, resp
);
332 nlmsvc_encode_res(struct svc_rqst
*rqstp
, struct xdr_stream
*xdr
)
334 struct nlm_res
*resp
= rqstp
->rq_resp
;
336 return svcxdr_encode_cookie(xdr
, &resp
->cookie
) &&
337 svcxdr_encode_stats(xdr
, resp
->status
);
341 nlmsvc_encode_shareres(struct svc_rqst
*rqstp
, struct xdr_stream
*xdr
)
343 struct nlm_res
*resp
= rqstp
->rq_resp
;
345 if (!svcxdr_encode_cookie(xdr
, &resp
->cookie
))
347 if (!svcxdr_encode_stats(xdr
, resp
->status
))
350 if (xdr_stream_encode_u32(xdr
, 0) < 0)