Root/fs/lockd/xdr.c

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

Archive Download this file



interactive