Branch data Line data Source code
1 : : /* SPDX-License-Identifier: GPL-2.0 */
2 : : /*
3 : : * XDR standard data types and function declarations
4 : : *
5 : : * Copyright (C) 1995-1997 Olaf Kirch <okir@monad.swb.de>
6 : : *
7 : : * Based on:
8 : : * RFC 4506 "XDR: External Data Representation Standard", May 2006
9 : : */
10 : :
11 : : #ifndef _SUNRPC_XDR_H_
12 : : #define _SUNRPC_XDR_H_
13 : :
14 : : #ifdef __KERNEL__
15 : :
16 : : #include <linux/uio.h>
17 : : #include <asm/byteorder.h>
18 : : #include <asm/unaligned.h>
19 : : #include <linux/scatterlist.h>
20 : :
21 : : struct bio_vec;
22 : : struct rpc_rqst;
23 : :
24 : : /*
25 : : * Buffer adjustment
26 : : */
27 : : #define XDR_QUADLEN(l) (((l) + 3) >> 2)
28 : :
29 : : /*
30 : : * Generic opaque `network object.' At the kernel level, this type
31 : : * is used only by lockd.
32 : : */
33 : : #define XDR_MAX_NETOBJ 1024
34 : : struct xdr_netobj {
35 : : unsigned int len;
36 : : u8 * data;
37 : : };
38 : :
39 : : /*
40 : : * Basic structure for transmission/reception of a client XDR message.
41 : : * Features a header (for a linear buffer containing RPC headers
42 : : * and the data payload for short messages), and then an array of
43 : : * pages.
44 : : * The tail iovec allows you to append data after the page array. Its
45 : : * main interest is for appending padding to the pages in order to
46 : : * satisfy the int_32-alignment requirements in RFC1832.
47 : : *
48 : : * For the future, we might want to string several of these together
49 : : * in a list if anybody wants to make use of NFSv4 COMPOUND
50 : : * operations and/or has a need for scatter/gather involving pages.
51 : : */
52 : : struct xdr_buf {
53 : : struct kvec head[1], /* RPC header + non-page data */
54 : : tail[1]; /* Appended after page data */
55 : :
56 : : struct bio_vec *bvec;
57 : : struct page ** pages; /* Array of pages */
58 : : unsigned int page_base, /* Start of page data */
59 : : page_len, /* Length of page data */
60 : : flags; /* Flags for data disposition */
61 : : #define XDRBUF_READ 0x01 /* target of file read */
62 : : #define XDRBUF_WRITE 0x02 /* source of file write */
63 : : #define XDRBUF_SPARSE_PAGES 0x04 /* Page array is sparse */
64 : :
65 : : unsigned int buflen, /* Total length of storage buffer */
66 : : len; /* Length of XDR encoded message */
67 : : };
68 : :
69 : : static inline void
70 : : xdr_buf_init(struct xdr_buf *buf, void *start, size_t len)
71 : : {
72 : 0 : buf->head[0].iov_base = start;
73 : 0 : buf->head[0].iov_len = len;
74 : 0 : buf->tail[0].iov_len = 0;
75 : 0 : buf->pages = NULL;
76 : 0 : buf->page_len = 0;
77 : 0 : buf->flags = 0;
78 : 0 : buf->len = 0;
79 : 0 : buf->buflen = len;
80 : : }
81 : :
82 : : /*
83 : : * pre-xdr'ed macros.
84 : : */
85 : :
86 : : #define xdr_zero cpu_to_be32(0)
87 : : #define xdr_one cpu_to_be32(1)
88 : : #define xdr_two cpu_to_be32(2)
89 : :
90 : : #define rpc_auth_null cpu_to_be32(RPC_AUTH_NULL)
91 : : #define rpc_auth_unix cpu_to_be32(RPC_AUTH_UNIX)
92 : : #define rpc_auth_short cpu_to_be32(RPC_AUTH_SHORT)
93 : : #define rpc_auth_gss cpu_to_be32(RPC_AUTH_GSS)
94 : :
95 : : #define rpc_call cpu_to_be32(RPC_CALL)
96 : : #define rpc_reply cpu_to_be32(RPC_REPLY)
97 : :
98 : : #define rpc_msg_accepted cpu_to_be32(RPC_MSG_ACCEPTED)
99 : :
100 : : #define rpc_success cpu_to_be32(RPC_SUCCESS)
101 : : #define rpc_prog_unavail cpu_to_be32(RPC_PROG_UNAVAIL)
102 : : #define rpc_prog_mismatch cpu_to_be32(RPC_PROG_MISMATCH)
103 : : #define rpc_proc_unavail cpu_to_be32(RPC_PROC_UNAVAIL)
104 : : #define rpc_garbage_args cpu_to_be32(RPC_GARBAGE_ARGS)
105 : : #define rpc_system_err cpu_to_be32(RPC_SYSTEM_ERR)
106 : : #define rpc_drop_reply cpu_to_be32(RPC_DROP_REPLY)
107 : :
108 : : #define rpc_mismatch cpu_to_be32(RPC_MISMATCH)
109 : : #define rpc_auth_error cpu_to_be32(RPC_AUTH_ERROR)
110 : :
111 : : #define rpc_auth_ok cpu_to_be32(RPC_AUTH_OK)
112 : : #define rpc_autherr_badcred cpu_to_be32(RPC_AUTH_BADCRED)
113 : : #define rpc_autherr_rejectedcred cpu_to_be32(RPC_AUTH_REJECTEDCRED)
114 : : #define rpc_autherr_badverf cpu_to_be32(RPC_AUTH_BADVERF)
115 : : #define rpc_autherr_rejectedverf cpu_to_be32(RPC_AUTH_REJECTEDVERF)
116 : : #define rpc_autherr_tooweak cpu_to_be32(RPC_AUTH_TOOWEAK)
117 : : #define rpcsec_gsserr_credproblem cpu_to_be32(RPCSEC_GSS_CREDPROBLEM)
118 : : #define rpcsec_gsserr_ctxproblem cpu_to_be32(RPCSEC_GSS_CTXPROBLEM)
119 : :
120 : : /*
121 : : * Miscellaneous XDR helper functions
122 : : */
123 : : __be32 *xdr_encode_opaque_fixed(__be32 *p, const void *ptr, unsigned int len);
124 : : __be32 *xdr_encode_opaque(__be32 *p, const void *ptr, unsigned int len);
125 : : __be32 *xdr_encode_string(__be32 *p, const char *s);
126 : : __be32 *xdr_decode_string_inplace(__be32 *p, char **sp, unsigned int *lenp,
127 : : unsigned int maxlen);
128 : : __be32 *xdr_encode_netobj(__be32 *p, const struct xdr_netobj *);
129 : : __be32 *xdr_decode_netobj(__be32 *p, struct xdr_netobj *);
130 : :
131 : : void xdr_inline_pages(struct xdr_buf *, unsigned int,
132 : : struct page **, unsigned int, unsigned int);
133 : : void xdr_terminate_string(struct xdr_buf *, const u32);
134 : : size_t xdr_buf_pagecount(struct xdr_buf *buf);
135 : : int xdr_alloc_bvec(struct xdr_buf *buf, gfp_t gfp);
136 : : void xdr_free_bvec(struct xdr_buf *buf);
137 : :
138 : : static inline __be32 *xdr_encode_array(__be32 *p, const void *s, unsigned int len)
139 : : {
140 : 0 : return xdr_encode_opaque(p, s, len);
141 : : }
142 : :
143 : : /*
144 : : * Decode 64bit quantities (NFSv3 support)
145 : : */
146 : : static inline __be32 *
147 : : xdr_encode_hyper(__be32 *p, __u64 val)
148 : : {
149 : : put_unaligned_be64(val, p);
150 : 0 : return p + 2;
151 : : }
152 : :
153 : : static inline __be32 *
154 : : xdr_decode_hyper(__be32 *p, __u64 *valp)
155 : : {
156 : 0 : *valp = get_unaligned_be64(p);
157 : 0 : return p + 2;
158 : : }
159 : :
160 : : static inline __be32 *
161 : : xdr_decode_opaque_fixed(__be32 *p, void *ptr, unsigned int len)
162 : : {
163 : 0 : memcpy(ptr, p, len);
164 : : return p + XDR_QUADLEN(len);
165 : : }
166 : :
167 : : static inline void xdr_netobj_dup(struct xdr_netobj *dst,
168 : : struct xdr_netobj *src, gfp_t gfp_mask)
169 : : {
170 : : dst->data = kmemdup(src->data, src->len, gfp_mask);
171 : : dst->len = src->len;
172 : : }
173 : :
174 : : /*
175 : : * Adjust kvec to reflect end of xdr'ed data (RPC client XDR)
176 : : */
177 : : static inline int
178 : : xdr_adjust_iovec(struct kvec *iov, __be32 *p)
179 : : {
180 : : return iov->iov_len = ((u8 *) p - (u8 *) iov->iov_base);
181 : : }
182 : :
183 : : /*
184 : : * XDR buffer helper functions
185 : : */
186 : : extern void xdr_shift_buf(struct xdr_buf *, size_t);
187 : : extern void xdr_buf_from_iov(struct kvec *, struct xdr_buf *);
188 : : extern int xdr_buf_subsegment(struct xdr_buf *, struct xdr_buf *, unsigned int, unsigned int);
189 : : extern void xdr_buf_trim(struct xdr_buf *, unsigned int);
190 : : extern int xdr_buf_read_mic(struct xdr_buf *, struct xdr_netobj *, unsigned int);
191 : : extern int read_bytes_from_xdr_buf(struct xdr_buf *, unsigned int, void *, unsigned int);
192 : : extern int write_bytes_to_xdr_buf(struct xdr_buf *, unsigned int, void *, unsigned int);
193 : :
194 : : /*
195 : : * Helper structure for copying from an sk_buff.
196 : : */
197 : : struct xdr_skb_reader {
198 : : struct sk_buff *skb;
199 : : unsigned int offset;
200 : : size_t count;
201 : : __wsum csum;
202 : : };
203 : :
204 : : typedef size_t (*xdr_skb_read_actor)(struct xdr_skb_reader *desc, void *to, size_t len);
205 : :
206 : : extern int csum_partial_copy_to_xdr(struct xdr_buf *, struct sk_buff *);
207 : :
208 : : extern int xdr_encode_word(struct xdr_buf *, unsigned int, u32);
209 : : extern int xdr_decode_word(struct xdr_buf *, unsigned int, u32 *);
210 : :
211 : : struct xdr_array2_desc;
212 : : typedef int (*xdr_xcode_elem_t)(struct xdr_array2_desc *desc, void *elem);
213 : : struct xdr_array2_desc {
214 : : unsigned int elem_size;
215 : : unsigned int array_len;
216 : : unsigned int array_maxlen;
217 : : xdr_xcode_elem_t xcode;
218 : : };
219 : :
220 : : extern int xdr_decode_array2(struct xdr_buf *buf, unsigned int base,
221 : : struct xdr_array2_desc *desc);
222 : : extern int xdr_encode_array2(struct xdr_buf *buf, unsigned int base,
223 : : struct xdr_array2_desc *desc);
224 : : extern void _copy_from_pages(char *p, struct page **pages, size_t pgbase,
225 : : size_t len);
226 : :
227 : : /*
228 : : * Provide some simple tools for XDR buffer overflow-checking etc.
229 : : */
230 : : struct xdr_stream {
231 : : __be32 *p; /* start of available buffer */
232 : : struct xdr_buf *buf; /* XDR buffer to read/write */
233 : :
234 : : __be32 *end; /* end of available buffer space */
235 : : struct kvec *iov; /* pointer to the current kvec */
236 : : struct kvec scratch; /* Scratch buffer */
237 : : struct page **page_ptr; /* pointer to the current page */
238 : : unsigned int nwords; /* Remaining decode buffer length */
239 : :
240 : : struct rpc_rqst *rqst; /* For debugging */
241 : : };
242 : :
243 : : /*
244 : : * These are the xdr_stream style generic XDR encode and decode functions.
245 : : */
246 : : typedef void (*kxdreproc_t)(struct rpc_rqst *rqstp, struct xdr_stream *xdr,
247 : : const void *obj);
248 : : typedef int (*kxdrdproc_t)(struct rpc_rqst *rqstp, struct xdr_stream *xdr,
249 : : void *obj);
250 : :
251 : : extern void xdr_init_encode(struct xdr_stream *xdr, struct xdr_buf *buf,
252 : : __be32 *p, struct rpc_rqst *rqst);
253 : : extern __be32 *xdr_reserve_space(struct xdr_stream *xdr, size_t nbytes);
254 : : extern void xdr_commit_encode(struct xdr_stream *xdr);
255 : : extern void xdr_truncate_encode(struct xdr_stream *xdr, size_t len);
256 : : extern int xdr_restrict_buflen(struct xdr_stream *xdr, int newbuflen);
257 : : extern void xdr_write_pages(struct xdr_stream *xdr, struct page **pages,
258 : : unsigned int base, unsigned int len);
259 : : extern unsigned int xdr_stream_pos(const struct xdr_stream *xdr);
260 : : extern void xdr_init_decode(struct xdr_stream *xdr, struct xdr_buf *buf,
261 : : __be32 *p, struct rpc_rqst *rqst);
262 : : extern void xdr_init_decode_pages(struct xdr_stream *xdr, struct xdr_buf *buf,
263 : : struct page **pages, unsigned int len);
264 : : extern void xdr_set_scratch_buffer(struct xdr_stream *xdr, void *buf, size_t buflen);
265 : : extern __be32 *xdr_inline_decode(struct xdr_stream *xdr, size_t nbytes);
266 : : extern unsigned int xdr_read_pages(struct xdr_stream *xdr, unsigned int len);
267 : : extern void xdr_enter_page(struct xdr_stream *xdr, unsigned int len);
268 : : extern int xdr_process_buf(struct xdr_buf *buf, unsigned int offset, unsigned int len, int (*actor)(struct scatterlist *, void *), void *data);
269 : :
270 : : /**
271 : : * xdr_stream_remaining - Return the number of bytes remaining in the stream
272 : : * @xdr: pointer to struct xdr_stream
273 : : *
274 : : * Return value:
275 : : * Number of bytes remaining in @xdr before xdr->end
276 : : */
277 : : static inline size_t
278 : : xdr_stream_remaining(const struct xdr_stream *xdr)
279 : : {
280 : 0 : return xdr->nwords << 2;
281 : : }
282 : :
283 : : ssize_t xdr_stream_decode_opaque(struct xdr_stream *xdr, void *ptr,
284 : : size_t size);
285 : : ssize_t xdr_stream_decode_opaque_dup(struct xdr_stream *xdr, void **ptr,
286 : : size_t maxlen, gfp_t gfp_flags);
287 : : ssize_t xdr_stream_decode_string(struct xdr_stream *xdr, char *str,
288 : : size_t size);
289 : : ssize_t xdr_stream_decode_string_dup(struct xdr_stream *xdr, char **str,
290 : : size_t maxlen, gfp_t gfp_flags);
291 : : /**
292 : : * xdr_align_size - Calculate padded size of an object
293 : : * @n: Size of an object being XDR encoded (in bytes)
294 : : *
295 : : * Return value:
296 : : * Size (in bytes) of the object including xdr padding
297 : : */
298 : : static inline size_t
299 : : xdr_align_size(size_t n)
300 : : {
301 : : const size_t mask = sizeof(__u32) - 1;
302 : :
303 : 0 : return (n + mask) & ~mask;
304 : : }
305 : :
306 : : /**
307 : : * xdr_stream_encode_u32 - Encode a 32-bit integer
308 : : * @xdr: pointer to xdr_stream
309 : : * @n: integer to encode
310 : : *
311 : : * Return values:
312 : : * On success, returns length in bytes of XDR buffer consumed
313 : : * %-EMSGSIZE on XDR buffer overflow
314 : : */
315 : : static inline ssize_t
316 : : xdr_stream_encode_u32(struct xdr_stream *xdr, __u32 n)
317 : : {
318 : : const size_t len = sizeof(n);
319 : 0 : __be32 *p = xdr_reserve_space(xdr, len);
320 : :
321 : 0 : if (unlikely(!p))
322 : : return -EMSGSIZE;
323 : 0 : *p = cpu_to_be32(n);
324 : : return len;
325 : : }
326 : :
327 : : /**
328 : : * xdr_stream_encode_u64 - Encode a 64-bit integer
329 : : * @xdr: pointer to xdr_stream
330 : : * @n: 64-bit integer to encode
331 : : *
332 : : * Return values:
333 : : * On success, returns length in bytes of XDR buffer consumed
334 : : * %-EMSGSIZE on XDR buffer overflow
335 : : */
336 : : static inline ssize_t
337 : 0 : xdr_stream_encode_u64(struct xdr_stream *xdr, __u64 n)
338 : : {
339 : : const size_t len = sizeof(n);
340 : 0 : __be32 *p = xdr_reserve_space(xdr, len);
341 : :
342 : 0 : if (unlikely(!p))
343 : : return -EMSGSIZE;
344 : : xdr_encode_hyper(p, n);
345 : 0 : return len;
346 : : }
347 : :
348 : : /**
349 : : * xdr_stream_encode_opaque_inline - Encode opaque xdr data
350 : : * @xdr: pointer to xdr_stream
351 : : * @ptr: pointer to void pointer
352 : : * @len: size of object
353 : : *
354 : : * Return values:
355 : : * On success, returns length in bytes of XDR buffer consumed
356 : : * %-EMSGSIZE on XDR buffer overflow
357 : : */
358 : : static inline ssize_t
359 : 0 : xdr_stream_encode_opaque_inline(struct xdr_stream *xdr, void **ptr, size_t len)
360 : : {
361 : 0 : size_t count = sizeof(__u32) + xdr_align_size(len);
362 : 0 : __be32 *p = xdr_reserve_space(xdr, count);
363 : :
364 : 0 : if (unlikely(!p)) {
365 : 0 : *ptr = NULL;
366 : 0 : return -EMSGSIZE;
367 : : }
368 : 0 : xdr_encode_opaque(p, NULL, len);
369 : 0 : *ptr = ++p;
370 : 0 : return count;
371 : : }
372 : :
373 : : /**
374 : : * xdr_stream_encode_opaque_fixed - Encode fixed length opaque xdr data
375 : : * @xdr: pointer to xdr_stream
376 : : * @ptr: pointer to opaque data object
377 : : * @len: size of object pointed to by @ptr
378 : : *
379 : : * Return values:
380 : : * On success, returns length in bytes of XDR buffer consumed
381 : : * %-EMSGSIZE on XDR buffer overflow
382 : : */
383 : : static inline ssize_t
384 : 0 : xdr_stream_encode_opaque_fixed(struct xdr_stream *xdr, const void *ptr, size_t len)
385 : : {
386 : 0 : __be32 *p = xdr_reserve_space(xdr, len);
387 : :
388 : 0 : if (unlikely(!p))
389 : : return -EMSGSIZE;
390 : 0 : xdr_encode_opaque_fixed(p, ptr, len);
391 : 0 : return xdr_align_size(len);
392 : : }
393 : :
394 : : /**
395 : : * xdr_stream_encode_opaque - Encode variable length opaque xdr data
396 : : * @xdr: pointer to xdr_stream
397 : : * @ptr: pointer to opaque data object
398 : : * @len: size of object pointed to by @ptr
399 : : *
400 : : * Return values:
401 : : * On success, returns length in bytes of XDR buffer consumed
402 : : * %-EMSGSIZE on XDR buffer overflow
403 : : */
404 : : static inline ssize_t
405 : 0 : xdr_stream_encode_opaque(struct xdr_stream *xdr, const void *ptr, size_t len)
406 : : {
407 : 0 : size_t count = sizeof(__u32) + xdr_align_size(len);
408 : 0 : __be32 *p = xdr_reserve_space(xdr, count);
409 : :
410 : 0 : if (unlikely(!p))
411 : : return -EMSGSIZE;
412 : 0 : xdr_encode_opaque(p, ptr, len);
413 : 0 : return count;
414 : : }
415 : :
416 : : /**
417 : : * xdr_stream_encode_uint32_array - Encode variable length array of integers
418 : : * @xdr: pointer to xdr_stream
419 : : * @array: array of integers
420 : : * @array_size: number of elements in @array
421 : : *
422 : : * Return values:
423 : : * On success, returns length in bytes of XDR buffer consumed
424 : : * %-EMSGSIZE on XDR buffer overflow
425 : : */
426 : : static inline ssize_t
427 : 0 : xdr_stream_encode_uint32_array(struct xdr_stream *xdr,
428 : : const __u32 *array, size_t array_size)
429 : : {
430 : 0 : ssize_t ret = (array_size+1) * sizeof(__u32);
431 : 0 : __be32 *p = xdr_reserve_space(xdr, ret);
432 : :
433 : 0 : if (unlikely(!p))
434 : : return -EMSGSIZE;
435 : 0 : *p++ = cpu_to_be32(array_size);
436 : 0 : for (; array_size > 0; p++, array++, array_size--)
437 : 0 : *p = cpu_to_be32p(array);
438 : : return ret;
439 : : }
440 : :
441 : : /**
442 : : * xdr_stream_decode_u32 - Decode a 32-bit integer
443 : : * @xdr: pointer to xdr_stream
444 : : * @ptr: location to store integer
445 : : *
446 : : * Return values:
447 : : * %0 on success
448 : : * %-EBADMSG on XDR buffer overflow
449 : : */
450 : : static inline ssize_t
451 : : xdr_stream_decode_u32(struct xdr_stream *xdr, __u32 *ptr)
452 : : {
453 : : const size_t count = sizeof(*ptr);
454 : 0 : __be32 *p = xdr_inline_decode(xdr, count);
455 : :
456 : 0 : if (unlikely(!p))
457 : : return -EBADMSG;
458 : 0 : *ptr = be32_to_cpup(p);
459 : : return 0;
460 : : }
461 : :
462 : : /**
463 : : * xdr_stream_decode_opaque_fixed - Decode fixed length opaque xdr data
464 : : * @xdr: pointer to xdr_stream
465 : : * @ptr: location to store data
466 : : * @len: size of buffer pointed to by @ptr
467 : : *
468 : : * Return values:
469 : : * On success, returns size of object stored in @ptr
470 : : * %-EBADMSG on XDR buffer overflow
471 : : */
472 : : static inline ssize_t
473 : 0 : xdr_stream_decode_opaque_fixed(struct xdr_stream *xdr, void *ptr, size_t len)
474 : : {
475 : 0 : __be32 *p = xdr_inline_decode(xdr, len);
476 : :
477 : 0 : if (unlikely(!p))
478 : : return -EBADMSG;
479 : : xdr_decode_opaque_fixed(p, ptr, len);
480 : 0 : return len;
481 : : }
482 : :
483 : : /**
484 : : * xdr_stream_decode_opaque_inline - Decode variable length opaque xdr data
485 : : * @xdr: pointer to xdr_stream
486 : : * @ptr: location to store pointer to opaque data
487 : : * @maxlen: maximum acceptable object size
488 : : *
489 : : * Note: the pointer stored in @ptr cannot be assumed valid after the XDR
490 : : * buffer has been destroyed, or even after calling xdr_inline_decode()
491 : : * on @xdr. It is therefore expected that the object it points to should
492 : : * be processed immediately.
493 : : *
494 : : * Return values:
495 : : * On success, returns size of object stored in *@ptr
496 : : * %-EBADMSG on XDR buffer overflow
497 : : * %-EMSGSIZE if the size of the object would exceed @maxlen
498 : : */
499 : : static inline ssize_t
500 : 0 : xdr_stream_decode_opaque_inline(struct xdr_stream *xdr, void **ptr, size_t maxlen)
501 : : {
502 : : __be32 *p;
503 : : __u32 len;
504 : :
505 : 0 : *ptr = NULL;
506 : 0 : if (unlikely(xdr_stream_decode_u32(xdr, &len) < 0))
507 : : return -EBADMSG;
508 : 0 : if (len != 0) {
509 : 0 : p = xdr_inline_decode(xdr, len);
510 : 0 : if (unlikely(!p))
511 : : return -EBADMSG;
512 : 0 : if (unlikely(len > maxlen))
513 : : return -EMSGSIZE;
514 : 0 : *ptr = p;
515 : : }
516 : 0 : return len;
517 : : }
518 : :
519 : : /**
520 : : * xdr_stream_decode_uint32_array - Decode variable length array of integers
521 : : * @xdr: pointer to xdr_stream
522 : : * @array: location to store the integer array or NULL
523 : : * @array_size: number of elements to store
524 : : *
525 : : * Return values:
526 : : * On success, returns number of elements stored in @array
527 : : * %-EBADMSG on XDR buffer overflow
528 : : * %-EMSGSIZE if the size of the array exceeds @array_size
529 : : */
530 : : static inline ssize_t
531 : 0 : xdr_stream_decode_uint32_array(struct xdr_stream *xdr,
532 : : __u32 *array, size_t array_size)
533 : : {
534 : : __be32 *p;
535 : : __u32 len;
536 : : ssize_t retval;
537 : :
538 : 0 : if (unlikely(xdr_stream_decode_u32(xdr, &len) < 0))
539 : : return -EBADMSG;
540 : 0 : p = xdr_inline_decode(xdr, len * sizeof(*p));
541 : 0 : if (unlikely(!p))
542 : : return -EBADMSG;
543 : 0 : if (array == NULL)
544 : 0 : return len;
545 : 0 : if (len <= array_size) {
546 : 0 : if (len < array_size)
547 : 0 : memset(array+len, 0, (array_size-len)*sizeof(*array));
548 : : array_size = len;
549 : 0 : retval = len;
550 : : } else
551 : : retval = -EMSGSIZE;
552 : 0 : for (; array_size > 0; p++, array++, array_size--)
553 : 0 : *array = be32_to_cpup(p);
554 : 0 : return retval;
555 : : }
556 : : #endif /* __KERNEL__ */
557 : :
558 : : #endif /* _SUNRPC_XDR_H_ */
|