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