/* SPDX-License-Identifier: GPL-2.0 */ /* * XDR standard data types and function declarations * * Copyright (C) 1995-1997 Olaf Kirch <okir@monad.swb.de> * * Based on: * RFC 4506 "XDR: External Data Representation Standard", May 2006
*/
/* * Size of an XDR encoding unit in bytes, i.e. 32 bits, * as defined in Section 3 of RFC 4506. All encoded * XDR data items are aligned on a boundary of 32 bits.
*/ #define XDR_UNIT sizeof(__be32)
/* * Basic structure for transmission/reception of a client XDR message. * Features a header (for a linear buffer containing RPC headers * and the data payload for short messages), and then an array of * pages. * The tail iovec allows you to append data after the page array. Its * main interest is for appending padding to the pages in order to * satisfy the int_32-alignment requirements in RFC1832. * * For the future, we might want to string several of these together * in a list if anybody wants to make use of NFSv4 COMPOUND * operations and/or has a need for scatter/gather involving pages.
*/ struct xdr_buf { struct kvec head[1], /* RPC header + non-page data */
tail[1]; /* Appended after page data */
struct bio_vec *bvec; struct page ** pages; /* Array of pages */ unsignedint page_base, /* Start of page data */
page_len, /* Length of page data */
flags; /* Flags for data disposition */ #define XDRBUF_READ 0x01 /* target of file read */ #define XDRBUF_WRITE 0x02 /* source of file write */ #define XDRBUF_SPARSE_PAGES 0x04 /* Page array is sparse */
unsignedint buflen, /* Total length of storage buffer */
len; /* Length of XDR encoded message */
};
/* * Provide some simple tools for XDR buffer overflow-checking etc.
*/ struct xdr_stream {
__be32 *p; /* start of available buffer */ struct xdr_buf *buf; /* XDR buffer to read/write */
__be32 *end; /* end of available buffer space */ struct kvec *iov; /* pointer to the current kvec */ struct kvec scratch; /* Scratch buffer */ struct page **page_ptr; /* pointer to the current page */ void *page_kaddr; /* kmapped address of the current page */ unsignedint nwords; /* Remaining decode buffer length */
struct rpc_rqst *rqst; /* For debugging */
};
/* * These are the xdr_stream style generic XDR encode and decode functions.
*/ typedefvoid (*kxdreproc_t)(struct rpc_rqst *rqstp, struct xdr_stream *xdr, constvoid *obj); typedefint (*kxdrdproc_t)(struct rpc_rqst *rqstp, struct xdr_stream *xdr, void *obj);
/** * xdr_set_scratch_buffer - Attach a scratch buffer for decoding data. * @xdr: pointer to xdr_stream struct * @buf: pointer to an empty buffer * @buflen: size of 'buf' * * The scratch buffer is used when decoding from an array of pages. * If an xdr_inline_decode() call spans across page boundaries, then * we copy the data into the scratch buffer in order to allow linear * access.
*/ staticinlinevoid
xdr_set_scratch_buffer(struct xdr_stream *xdr, void *buf, size_t buflen)
{
xdr->scratch.iov_base = buf;
xdr->scratch.iov_len = buflen;
}
/** * xdr_set_scratch_page - Attach a scratch buffer for decoding data * @xdr: pointer to xdr_stream struct * @page: an anonymous page * * See xdr_set_scratch_buffer().
*/ staticinlinevoid
xdr_set_scratch_page(struct xdr_stream *xdr, struct page *page)
{
xdr_set_scratch_buffer(xdr, page_address(page), PAGE_SIZE);
}
/** * xdr_reset_scratch_buffer - Clear scratch buffer information * @xdr: pointer to xdr_stream struct * * See xdr_set_scratch_buffer().
*/ staticinlinevoid
xdr_reset_scratch_buffer(struct xdr_stream *xdr)
{
xdr_set_scratch_buffer(xdr, NULL, 0);
}
/** * xdr_commit_encode - Ensure all data is written to xdr->buf * @xdr: pointer to xdr_stream * * Handle encoding across page boundaries by giving the caller a * temporary location to write to, then later copying the data into * place. __xdr_commit_encode() does that copying.
*/ staticinlinevoid xdr_commit_encode(struct xdr_stream *xdr)
{ if (unlikely(xdr->scratch.iov_len))
__xdr_commit_encode(xdr);
}
/** * xdr_stream_remaining - Return the number of bytes remaining in the stream * @xdr: pointer to struct xdr_stream * * Return value: * Number of bytes remaining in @xdr before xdr->end
*/ staticinline size_t
xdr_stream_remaining(conststruct xdr_stream *xdr)
{ return xdr->nwords << 2;
}
/** * xdr_align_size - Calculate padded size of an object * @n: Size of an object being XDR encoded (in bytes) * * Return value: * Size (in bytes) of the object including xdr padding
*/ staticinline size_t
xdr_align_size(size_t n)
{ const size_t mask = XDR_UNIT - 1;
return (n + mask) & ~mask;
}
/** * xdr_pad_size - Calculate size of an object's pad * @n: Size of an object being XDR encoded (in bytes) * * This implementation avoids the need for conditional * branches or modulo division. * * Return value: * Size (in bytes) of the needed XDR pad
*/ staticinline size_t xdr_pad_size(size_t n)
{ return xdr_align_size(n) - n;
}
/** * xdr_stream_encode_item_present - Encode a "present" list item * @xdr: pointer to xdr_stream * * Return values: * On success, returns length in bytes of XDR buffer consumed * %-EMSGSIZE on XDR buffer overflow
*/ staticinline ssize_t xdr_stream_encode_item_present(struct xdr_stream *xdr)
{ const size_t len = XDR_UNIT;
__be32 *p = xdr_reserve_space(xdr, len);
if (unlikely(!p)) return -EMSGSIZE;
*p = xdr_one; return len;
}
/** * xdr_stream_encode_item_absent - Encode a "not present" list item * @xdr: pointer to xdr_stream * * Return values: * On success, returns length in bytes of XDR buffer consumed * %-EMSGSIZE on XDR buffer overflow
*/ staticinlineint xdr_stream_encode_item_absent(struct xdr_stream *xdr)
{ const size_t len = XDR_UNIT;
__be32 *p = xdr_reserve_space(xdr, len);
if (unlikely(!p)) return -EMSGSIZE;
*p = xdr_zero; return len;
}
/** * xdr_encode_bool - Encode a boolean item * @p: address in a buffer into which to encode * @n: boolean value to encode * * Return value: * Address of item following the encoded boolean
*/ staticinline __be32 *xdr_encode_bool(__be32 *p, u32 n)
{
*p++ = n ? xdr_one : xdr_zero; return p;
}
/** * xdr_stream_encode_bool - Encode a boolean item * @xdr: pointer to xdr_stream * @n: boolean value to encode * * Return values: * On success, returns length in bytes of XDR buffer consumed * %-EMSGSIZE on XDR buffer overflow
*/ staticinlineint xdr_stream_encode_bool(struct xdr_stream *xdr, __u32 n)
{ const size_t len = XDR_UNIT;
__be32 *p = xdr_reserve_space(xdr, len);
if (unlikely(!p)) return -EMSGSIZE;
xdr_encode_bool(p, n); return len;
}
/** * xdr_stream_encode_u32 - Encode a 32-bit integer * @xdr: pointer to xdr_stream * @n: integer to encode * * Return values: * On success, returns length in bytes of XDR buffer consumed * %-EMSGSIZE on XDR buffer overflow
*/ staticinline ssize_t
xdr_stream_encode_u32(struct xdr_stream *xdr, __u32 n)
{ const size_t len = sizeof(n);
__be32 *p = xdr_reserve_space(xdr, len);
if (unlikely(!p)) return -EMSGSIZE;
*p = cpu_to_be32(n); return len;
}
/** * xdr_stream_encode_be32 - Encode a big-endian 32-bit integer * @xdr: pointer to xdr_stream * @n: integer to encode * * Return values: * On success, returns length in bytes of XDR buffer consumed * %-EMSGSIZE on XDR buffer overflow
*/ staticinline ssize_t
xdr_stream_encode_be32(struct xdr_stream *xdr, __be32 n)
{ const size_t len = sizeof(n);
__be32 *p = xdr_reserve_space(xdr, len);
if (unlikely(!p)) return -EMSGSIZE;
*p = n; return len;
}
/** * xdr_stream_encode_u64 - Encode a 64-bit integer * @xdr: pointer to xdr_stream * @n: 64-bit integer to encode * * Return values: * On success, returns length in bytes of XDR buffer consumed * %-EMSGSIZE on XDR buffer overflow
*/ staticinline ssize_t
xdr_stream_encode_u64(struct xdr_stream *xdr, __u64 n)
{ const size_t len = sizeof(n);
__be32 *p = xdr_reserve_space(xdr, len);
if (unlikely(!p)) return -EMSGSIZE;
xdr_encode_hyper(p, n); return len;
}
/** * xdr_stream_encode_opaque_inline - Encode opaque xdr data * @xdr: pointer to xdr_stream * @ptr: pointer to void pointer * @len: size of object * * Return values: * On success, returns length in bytes of XDR buffer consumed * %-EMSGSIZE on XDR buffer overflow
*/ staticinline ssize_t
xdr_stream_encode_opaque_inline(struct xdr_stream *xdr, void **ptr, size_t len)
{
size_t count = sizeof(__u32) + xdr_align_size(len);
__be32 *p = xdr_reserve_space(xdr, count);
/** * xdr_item_is_absent - symbolically handle XDR discriminators * @p: pointer to undecoded discriminator * * Return values: * %true if the following XDR item is absent * %false if the following XDR item is present
*/ staticinlinebool xdr_item_is_absent(const __be32 *p)
{ return *p == xdr_zero;
}
/** * xdr_item_is_present - symbolically handle XDR discriminators * @p: pointer to undecoded discriminator * * Return values: * %true if the following XDR item is present * %false if the following XDR item is absent
*/ staticinlinebool xdr_item_is_present(const __be32 *p)
{ return *p != xdr_zero;
}
/** * xdr_stream_decode_bool - Decode a boolean * @xdr: pointer to xdr_stream * @ptr: pointer to a u32 in which to store the result * * Return values: * %0 on success * %-EBADMSG on XDR buffer overflow
*/ staticinline ssize_t
xdr_stream_decode_bool(struct xdr_stream *xdr, __u32 *ptr)
{ const size_t count = sizeof(*ptr);
__be32 *p = xdr_inline_decode(xdr, count);
/** * xdr_stream_decode_u32 - Decode a 32-bit integer * @xdr: pointer to xdr_stream * @ptr: location to store integer * * Return values: * %0 on success * %-EBADMSG on XDR buffer overflow
*/ staticinline ssize_t
xdr_stream_decode_u32(struct xdr_stream *xdr, __u32 *ptr)
{ const size_t count = sizeof(*ptr);
__be32 *p = xdr_inline_decode(xdr, count);
if (unlikely(!p)) return -EBADMSG;
*ptr = be32_to_cpup(p); return 0;
}
/** * xdr_stream_decode_be32 - Decode a big-endian 32-bit integer * @xdr: pointer to xdr_stream * @ptr: location to store integer * * Return values: * %0 on success * %-EBADMSG on XDR buffer overflow
*/ staticinline ssize_t
xdr_stream_decode_be32(struct xdr_stream *xdr, __be32 *ptr)
{ const size_t count = sizeof(*ptr);
__be32 *p = xdr_inline_decode(xdr, count);
if (unlikely(!p)) return -EBADMSG;
*ptr = *p; return 0;
}
/** * xdr_stream_decode_u64 - Decode a 64-bit integer * @xdr: pointer to xdr_stream * @ptr: location to store 64-bit integer * * Return values: * %0 on success * %-EBADMSG on XDR buffer overflow
*/ staticinline ssize_t
xdr_stream_decode_u64(struct xdr_stream *xdr, __u64 *ptr)
{ const size_t count = sizeof(*ptr);
__be32 *p = xdr_inline_decode(xdr, count);
if (unlikely(!p)) return -EBADMSG;
xdr_decode_hyper(p, ptr); return 0;
}
/** * xdr_stream_decode_opaque_fixed - Decode fixed length opaque xdr data * @xdr: pointer to xdr_stream * @ptr: location to store data * @len: size of buffer pointed to by @ptr * * Return values: * On success, returns size of object stored in @ptr * %-EBADMSG on XDR buffer overflow
*/ staticinline ssize_t
xdr_stream_decode_opaque_fixed(struct xdr_stream *xdr, void *ptr, size_t len)
{
__be32 *p = xdr_inline_decode(xdr, len);
if (unlikely(!p)) return -EBADMSG;
xdr_decode_opaque_fixed(p, ptr, len); return len;
}
/** * xdr_stream_decode_opaque_inline - Decode variable length opaque xdr data * @xdr: pointer to xdr_stream * @ptr: location to store pointer to opaque data * @maxlen: maximum acceptable object size * * Note: the pointer stored in @ptr cannot be assumed valid after the XDR * buffer has been destroyed, or even after calling xdr_inline_decode() * on @xdr. It is therefore expected that the object it points to should * be processed immediately. * * Return values: * On success, returns size of object stored in *@ptr * %-EBADMSG on XDR buffer overflow * %-EMSGSIZE if the size of the object would exceed @maxlen
*/ staticinline ssize_t
xdr_stream_decode_opaque_inline(struct xdr_stream *xdr, void **ptr, size_t maxlen)
{
__be32 *p;
__u32 len;
*ptr = NULL; if (unlikely(xdr_stream_decode_u32(xdr, &len) < 0)) return -EBADMSG; if (len != 0) {
p = xdr_inline_decode(xdr, len); if (unlikely(!p)) return -EBADMSG; if (unlikely(len > maxlen)) return -EMSGSIZE;
*ptr = p;
} return len;
}
/** * xdr_stream_decode_uint32_array - Decode variable length array of integers * @xdr: pointer to xdr_stream * @array: location to store the integer array or NULL * @array_size: number of elements to store * * Return values: * On success, returns number of elements stored in @array * %-EBADMSG on XDR buffer overflow * %-EMSGSIZE if the size of the array exceeds @array_size
*/ staticinline ssize_t
xdr_stream_decode_uint32_array(struct xdr_stream *xdr,
__u32 *array, size_t array_size)
{
__be32 *p;
__u32 len;
ssize_t retval;
if (unlikely(xdr_stream_decode_u32(xdr, &len) < 0)) return -EBADMSG; if (U32_MAX >= SIZE_MAX / sizeof(*p) && len > SIZE_MAX / sizeof(*p)) return -EBADMSG;
p = xdr_inline_decode(xdr, len * sizeof(*p)); if (unlikely(!p)) return -EBADMSG; if (array == NULL) return len; if (len <= array_size) { if (len < array_size)
memset(array+len, 0, (array_size-len)*sizeof(*array));
array_size = len;
retval = len;
} else
retval = -EMSGSIZE; for (; array_size > 0; p++, array++, array_size--)
*array = be32_to_cpup(p); return retval;
}
#endif/* _SUNRPC_XDR_H_ */
Messung V0.5
¤ Dauer der Verarbeitung: 0.32 Sekunden
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.