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