xref: /OK3568_Linux_fs/kernel/include/linux/sunrpc/xdr.h (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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