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