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