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 int xdr_buf_read_mic(struct xdr_buf *, struct xdr_netobj *, 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
 191/*
 192 * Helper structure for copying from an sk_buff.
 193 */
 194struct xdr_skb_reader {
 195        struct sk_buff  *skb;
 196        unsigned int    offset;
 197        size_t          count;
 198        __wsum          csum;
 199};
 200
 201typedef size_t (*xdr_skb_read_actor)(struct xdr_skb_reader *desc, void *to, size_t len);
 202
 203extern int csum_partial_copy_to_xdr(struct xdr_buf *, struct sk_buff *);
 204
 205extern int xdr_encode_word(struct xdr_buf *, unsigned int, u32);
 206extern int xdr_decode_word(struct xdr_buf *, unsigned int, u32 *);
 207
 208struct xdr_array2_desc;
 209typedef int (*xdr_xcode_elem_t)(struct xdr_array2_desc *desc, void *elem);
 210struct xdr_array2_desc {
 211        unsigned int elem_size;
 212        unsigned int array_len;
 213        unsigned int array_maxlen;
 214        xdr_xcode_elem_t xcode;
 215};
 216
 217extern int xdr_decode_array2(struct xdr_buf *buf, unsigned int base,
 218                             struct xdr_array2_desc *desc);
 219extern int xdr_encode_array2(struct xdr_buf *buf, unsigned int base,
 220                             struct xdr_array2_desc *desc);
 221extern void _copy_from_pages(char *p, struct page **pages, size_t pgbase,
 222                             size_t len);
 223
 224/*
 225 * Provide some simple tools for XDR buffer overflow-checking etc.
 226 */
 227struct xdr_stream {
 228        __be32 *p;              /* start of available buffer */
 229        struct xdr_buf *buf;    /* XDR buffer to read/write */
 230
 231        __be32 *end;            /* end of available buffer space */
 232        struct kvec *iov;       /* pointer to the current kvec */
 233        struct kvec scratch;    /* Scratch buffer */
 234        struct page **page_ptr; /* pointer to the current page */
 235        unsigned int nwords;    /* Remaining decode buffer length */
 236
 237        struct rpc_rqst *rqst;  /* For debugging */
 238};
 239
 240/*
 241 * These are the xdr_stream style generic XDR encode and decode functions.
 242 */
 243typedef void    (*kxdreproc_t)(struct rpc_rqst *rqstp, struct xdr_stream *xdr,
 244                const void *obj);
 245typedef int     (*kxdrdproc_t)(struct rpc_rqst *rqstp, struct xdr_stream *xdr,
 246                void *obj);
 247
 248extern void xdr_init_encode(struct xdr_stream *xdr, struct xdr_buf *buf,
 249                            __be32 *p, struct rpc_rqst *rqst);
 250extern __be32 *xdr_reserve_space(struct xdr_stream *xdr, size_t nbytes);
 251extern void xdr_commit_encode(struct xdr_stream *xdr);
 252extern void xdr_truncate_encode(struct xdr_stream *xdr, size_t len);
 253extern int xdr_restrict_buflen(struct xdr_stream *xdr, int newbuflen);
 254extern void xdr_write_pages(struct xdr_stream *xdr, struct page **pages,
 255                unsigned int base, unsigned int len);
 256extern unsigned int xdr_stream_pos(const struct xdr_stream *xdr);
 257extern void xdr_init_decode(struct xdr_stream *xdr, struct xdr_buf *buf,
 258                            __be32 *p, struct rpc_rqst *rqst);
 259extern void xdr_init_decode_pages(struct xdr_stream *xdr, struct xdr_buf *buf,
 260                struct page **pages, unsigned int len);
 261extern void xdr_set_scratch_buffer(struct xdr_stream *xdr, void *buf, size_t buflen);
 262extern __be32 *xdr_inline_decode(struct xdr_stream *xdr, size_t nbytes);
 263extern unsigned int xdr_read_pages(struct xdr_stream *xdr, unsigned int len);
 264extern void xdr_enter_page(struct xdr_stream *xdr, unsigned int len);
 265extern int xdr_process_buf(struct xdr_buf *buf, unsigned int offset, unsigned int len, int (*actor)(struct scatterlist *, void *), void *data);
 266
 267/**
 268 * xdr_stream_remaining - Return the number of bytes remaining in the stream
 269 * @xdr: pointer to struct xdr_stream
 270 *
 271 * Return value:
 272 *   Number of bytes remaining in @xdr before xdr->end
 273 */
 274static inline size_t
 275xdr_stream_remaining(const struct xdr_stream *xdr)
 276{
 277        return xdr->nwords << 2;
 278}
 279
 280ssize_t xdr_stream_decode_opaque(struct xdr_stream *xdr, void *ptr,
 281                size_t size);
 282ssize_t xdr_stream_decode_opaque_dup(struct xdr_stream *xdr, void **ptr,
 283                size_t maxlen, gfp_t gfp_flags);
 284ssize_t xdr_stream_decode_string(struct xdr_stream *xdr, char *str,
 285                size_t size);
 286ssize_t xdr_stream_decode_string_dup(struct xdr_stream *xdr, char **str,
 287                size_t maxlen, gfp_t gfp_flags);
 288/**
 289 * xdr_align_size - Calculate padded size of an object
 290 * @n: Size of an object being XDR encoded (in bytes)
 291 *
 292 * Return value:
 293 *   Size (in bytes) of the object including xdr padding
 294 */
 295static inline size_t
 296xdr_align_size(size_t n)
 297{
 298        const size_t mask = sizeof(__u32) - 1;
 299
 300        return (n + mask) & ~mask;
 301}
 302
 303/**
 304 * xdr_stream_encode_u32 - Encode a 32-bit integer
 305 * @xdr: pointer to xdr_stream
 306 * @n: integer to encode
 307 *
 308 * Return values:
 309 *   On success, returns length in bytes of XDR buffer consumed
 310 *   %-EMSGSIZE on XDR buffer overflow
 311 */
 312static inline ssize_t
 313xdr_stream_encode_u32(struct xdr_stream *xdr, __u32 n)
 314{
 315        const size_t len = sizeof(n);
 316        __be32 *p = xdr_reserve_space(xdr, len);
 317
 318        if (unlikely(!p))
 319                return -EMSGSIZE;
 320        *p = cpu_to_be32(n);
 321        return len;
 322}
 323
 324/**
 325 * xdr_stream_encode_u64 - Encode a 64-bit integer
 326 * @xdr: pointer to xdr_stream
 327 * @n: 64-bit integer to encode
 328 *
 329 * Return values:
 330 *   On success, returns length in bytes of XDR buffer consumed
 331 *   %-EMSGSIZE on XDR buffer overflow
 332 */
 333static inline ssize_t
 334xdr_stream_encode_u64(struct xdr_stream *xdr, __u64 n)
 335{
 336        const size_t len = sizeof(n);
 337        __be32 *p = xdr_reserve_space(xdr, len);
 338
 339        if (unlikely(!p))
 340                return -EMSGSIZE;
 341        xdr_encode_hyper(p, n);
 342        return len;
 343}
 344
 345/**
 346 * xdr_stream_encode_opaque_inline - Encode opaque xdr data
 347 * @xdr: pointer to xdr_stream
 348 * @ptr: pointer to void pointer
 349 * @len: size of object
 350 *
 351 * Return values:
 352 *   On success, returns length in bytes of XDR buffer consumed
 353 *   %-EMSGSIZE on XDR buffer overflow
 354 */
 355static inline ssize_t
 356xdr_stream_encode_opaque_inline(struct xdr_stream *xdr, void **ptr, size_t len)
 357{
 358        size_t count = sizeof(__u32) + xdr_align_size(len);
 359        __be32 *p = xdr_reserve_space(xdr, count);
 360
 361        if (unlikely(!p)) {
 362                *ptr = NULL;
 363                return -EMSGSIZE;
 364        }
 365        xdr_encode_opaque(p, NULL, len);
 366        *ptr = ++p;
 367        return count;
 368}
 369
 370/**
 371 * xdr_stream_encode_opaque_fixed - Encode fixed length opaque xdr data
 372 * @xdr: pointer to xdr_stream
 373 * @ptr: pointer to opaque data object
 374 * @len: size of object pointed to by @ptr
 375 *
 376 * Return values:
 377 *   On success, returns length in bytes of XDR buffer consumed
 378 *   %-EMSGSIZE on XDR buffer overflow
 379 */
 380static inline ssize_t
 381xdr_stream_encode_opaque_fixed(struct xdr_stream *xdr, const void *ptr, size_t len)
 382{
 383        __be32 *p = xdr_reserve_space(xdr, len);
 384
 385        if (unlikely(!p))
 386                return -EMSGSIZE;
 387        xdr_encode_opaque_fixed(p, ptr, len);
 388        return xdr_align_size(len);
 389}
 390
 391/**
 392 * xdr_stream_encode_opaque - Encode variable length opaque xdr data
 393 * @xdr: pointer to xdr_stream
 394 * @ptr: pointer to opaque data object
 395 * @len: size of object pointed to by @ptr
 396 *
 397 * Return values:
 398 *   On success, returns length in bytes of XDR buffer consumed
 399 *   %-EMSGSIZE on XDR buffer overflow
 400 */
 401static inline ssize_t
 402xdr_stream_encode_opaque(struct xdr_stream *xdr, const void *ptr, size_t len)
 403{
 404        size_t count = sizeof(__u32) + xdr_align_size(len);
 405        __be32 *p = xdr_reserve_space(xdr, count);
 406
 407        if (unlikely(!p))
 408                return -EMSGSIZE;
 409        xdr_encode_opaque(p, ptr, len);
 410        return count;
 411}
 412
 413/**
 414 * xdr_stream_encode_uint32_array - Encode variable length array of integers
 415 * @xdr: pointer to xdr_stream
 416 * @array: array of integers
 417 * @array_size: number of elements in @array
 418 *
 419 * Return values:
 420 *   On success, returns length in bytes of XDR buffer consumed
 421 *   %-EMSGSIZE on XDR buffer overflow
 422 */
 423static inline ssize_t
 424xdr_stream_encode_uint32_array(struct xdr_stream *xdr,
 425                const __u32 *array, size_t array_size)
 426{
 427        ssize_t ret = (array_size+1) * sizeof(__u32);
 428        __be32 *p = xdr_reserve_space(xdr, ret);
 429
 430        if (unlikely(!p))
 431                return -EMSGSIZE;
 432        *p++ = cpu_to_be32(array_size);
 433        for (; array_size > 0; p++, array++, array_size--)
 434                *p = cpu_to_be32p(array);
 435        return ret;
 436}
 437
 438/**
 439 * xdr_stream_decode_u32 - Decode a 32-bit integer
 440 * @xdr: pointer to xdr_stream
 441 * @ptr: location to store integer
 442 *
 443 * Return values:
 444 *   %0 on success
 445 *   %-EBADMSG on XDR buffer overflow
 446 */
 447static inline ssize_t
 448xdr_stream_decode_u32(struct xdr_stream *xdr, __u32 *ptr)
 449{
 450        const size_t count = sizeof(*ptr);
 451        __be32 *p = xdr_inline_decode(xdr, count);
 452
 453        if (unlikely(!p))
 454                return -EBADMSG;
 455        *ptr = be32_to_cpup(p);
 456        return 0;
 457}
 458
 459/**
 460 * xdr_stream_decode_opaque_fixed - Decode fixed length opaque xdr data
 461 * @xdr: pointer to xdr_stream
 462 * @ptr: location to store data
 463 * @len: size of buffer pointed to by @ptr
 464 *
 465 * Return values:
 466 *   On success, returns size of object stored in @ptr
 467 *   %-EBADMSG on XDR buffer overflow
 468 */
 469static inline ssize_t
 470xdr_stream_decode_opaque_fixed(struct xdr_stream *xdr, void *ptr, size_t len)
 471{
 472        __be32 *p = xdr_inline_decode(xdr, len);
 473
 474        if (unlikely(!p))
 475                return -EBADMSG;
 476        xdr_decode_opaque_fixed(p, ptr, len);
 477        return len;
 478}
 479
 480/**
 481 * xdr_stream_decode_opaque_inline - Decode variable length opaque xdr data
 482 * @xdr: pointer to xdr_stream
 483 * @ptr: location to store pointer to opaque data
 484 * @maxlen: maximum acceptable object size
 485 *
 486 * Note: the pointer stored in @ptr cannot be assumed valid after the XDR
 487 * buffer has been destroyed, or even after calling xdr_inline_decode()
 488 * on @xdr. It is therefore expected that the object it points to should
 489 * be processed immediately.
 490 *
 491 * Return values:
 492 *   On success, returns size of object stored in *@ptr
 493 *   %-EBADMSG on XDR buffer overflow
 494 *   %-EMSGSIZE if the size of the object would exceed @maxlen
 495 */
 496static inline ssize_t
 497xdr_stream_decode_opaque_inline(struct xdr_stream *xdr, void **ptr, size_t maxlen)
 498{
 499        __be32 *p;
 500        __u32 len;
 501
 502        *ptr = NULL;
 503        if (unlikely(xdr_stream_decode_u32(xdr, &len) < 0))
 504                return -EBADMSG;
 505        if (len != 0) {
 506                p = xdr_inline_decode(xdr, len);
 507                if (unlikely(!p))
 508                        return -EBADMSG;
 509                if (unlikely(len > maxlen))
 510                        return -EMSGSIZE;
 511                *ptr = p;
 512        }
 513        return len;
 514}
 515
 516/**
 517 * xdr_stream_decode_uint32_array - Decode variable length array of integers
 518 * @xdr: pointer to xdr_stream
 519 * @array: location to store the integer array or NULL
 520 * @array_size: number of elements to store
 521 *
 522 * Return values:
 523 *   On success, returns number of elements stored in @array
 524 *   %-EBADMSG on XDR buffer overflow
 525 *   %-EMSGSIZE if the size of the array exceeds @array_size
 526 */
 527static inline ssize_t
 528xdr_stream_decode_uint32_array(struct xdr_stream *xdr,
 529                __u32 *array, size_t array_size)
 530{
 531        __be32 *p;
 532        __u32 len;
 533        ssize_t retval;
 534
 535        if (unlikely(xdr_stream_decode_u32(xdr, &len) < 0))
 536                return -EBADMSG;
 537        p = xdr_inline_decode(xdr, len * sizeof(*p));
 538        if (unlikely(!p))
 539                return -EBADMSG;
 540        if (array == NULL)
 541                return len;
 542        if (len <= array_size) {
 543                if (len < array_size)
 544                        memset(array+len, 0, (array_size-len)*sizeof(*array));
 545                array_size = len;
 546                retval = len;
 547        } else
 548                retval = -EMSGSIZE;
 549        for (; array_size > 0; p++, array++, array_size--)
 550                *array = be32_to_cpup(p);
 551        return retval;
 552}
 553
 554#endif /* _SUNRPC_XDR_H_ */
 555