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