0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #ifndef _SUNRPC_XDR_H_
0012 #define _SUNRPC_XDR_H_
0013
0014 #include <linux/uio.h>
0015 #include <asm/byteorder.h>
0016 #include <asm/unaligned.h>
0017 #include <linux/scatterlist.h>
0018
0019 struct bio_vec;
0020 struct rpc_rqst;
0021
0022
0023
0024
0025
0026
0027 #define XDR_UNIT sizeof(__be32)
0028
0029
0030
0031
0032 #define XDR_QUADLEN(l) (((l) + 3) >> 2)
0033
0034
0035
0036
0037 #define XDR_MAX_NETOBJ 1024
0038 struct xdr_netobj {
0039 unsigned int len;
0040 u8 * data;
0041 };
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056 struct xdr_buf {
0057 struct kvec head[1],
0058 tail[1];
0059
0060 struct bio_vec *bvec;
0061 struct page ** pages;
0062 unsigned int page_base,
0063 page_len,
0064 flags;
0065 #define XDRBUF_READ 0x01
0066 #define XDRBUF_WRITE 0x02
0067 #define XDRBUF_SPARSE_PAGES 0x04
0068
0069 unsigned int buflen,
0070 len;
0071 };
0072
0073 static inline void
0074 xdr_buf_init(struct xdr_buf *buf, void *start, size_t len)
0075 {
0076 buf->head[0].iov_base = start;
0077 buf->head[0].iov_len = len;
0078 buf->tail[0].iov_len = 0;
0079 buf->pages = NULL;
0080 buf->page_len = 0;
0081 buf->flags = 0;
0082 buf->len = 0;
0083 buf->buflen = len;
0084 }
0085
0086
0087
0088
0089
0090 #define xdr_zero cpu_to_be32(0)
0091 #define xdr_one cpu_to_be32(1)
0092 #define xdr_two cpu_to_be32(2)
0093
0094 #define rpc_auth_null cpu_to_be32(RPC_AUTH_NULL)
0095 #define rpc_auth_unix cpu_to_be32(RPC_AUTH_UNIX)
0096 #define rpc_auth_short cpu_to_be32(RPC_AUTH_SHORT)
0097 #define rpc_auth_gss cpu_to_be32(RPC_AUTH_GSS)
0098 #define rpc_auth_tls cpu_to_be32(RPC_AUTH_TLS)
0099
0100 #define rpc_call cpu_to_be32(RPC_CALL)
0101 #define rpc_reply cpu_to_be32(RPC_REPLY)
0102
0103 #define rpc_msg_accepted cpu_to_be32(RPC_MSG_ACCEPTED)
0104
0105 #define rpc_success cpu_to_be32(RPC_SUCCESS)
0106 #define rpc_prog_unavail cpu_to_be32(RPC_PROG_UNAVAIL)
0107 #define rpc_prog_mismatch cpu_to_be32(RPC_PROG_MISMATCH)
0108 #define rpc_proc_unavail cpu_to_be32(RPC_PROC_UNAVAIL)
0109 #define rpc_garbage_args cpu_to_be32(RPC_GARBAGE_ARGS)
0110 #define rpc_system_err cpu_to_be32(RPC_SYSTEM_ERR)
0111 #define rpc_drop_reply cpu_to_be32(RPC_DROP_REPLY)
0112
0113 #define rpc_mismatch cpu_to_be32(RPC_MISMATCH)
0114 #define rpc_auth_error cpu_to_be32(RPC_AUTH_ERROR)
0115
0116 #define rpc_auth_ok cpu_to_be32(RPC_AUTH_OK)
0117 #define rpc_autherr_badcred cpu_to_be32(RPC_AUTH_BADCRED)
0118 #define rpc_autherr_rejectedcred cpu_to_be32(RPC_AUTH_REJECTEDCRED)
0119 #define rpc_autherr_badverf cpu_to_be32(RPC_AUTH_BADVERF)
0120 #define rpc_autherr_rejectedverf cpu_to_be32(RPC_AUTH_REJECTEDVERF)
0121 #define rpc_autherr_tooweak cpu_to_be32(RPC_AUTH_TOOWEAK)
0122 #define rpcsec_gsserr_credproblem cpu_to_be32(RPCSEC_GSS_CREDPROBLEM)
0123 #define rpcsec_gsserr_ctxproblem cpu_to_be32(RPCSEC_GSS_CTXPROBLEM)
0124
0125
0126
0127
0128 __be32 *xdr_encode_opaque_fixed(__be32 *p, const void *ptr, unsigned int len);
0129 __be32 *xdr_encode_opaque(__be32 *p, const void *ptr, unsigned int len);
0130 __be32 *xdr_encode_string(__be32 *p, const char *s);
0131 __be32 *xdr_decode_string_inplace(__be32 *p, char **sp, unsigned int *lenp,
0132 unsigned int maxlen);
0133 __be32 *xdr_encode_netobj(__be32 *p, const struct xdr_netobj *);
0134 __be32 *xdr_decode_netobj(__be32 *p, struct xdr_netobj *);
0135
0136 void xdr_inline_pages(struct xdr_buf *, unsigned int,
0137 struct page **, unsigned int, unsigned int);
0138 void xdr_terminate_string(const struct xdr_buf *, const u32);
0139 size_t xdr_buf_pagecount(const struct xdr_buf *buf);
0140 int xdr_alloc_bvec(struct xdr_buf *buf, gfp_t gfp);
0141 void xdr_free_bvec(struct xdr_buf *buf);
0142
0143 static inline __be32 *xdr_encode_array(__be32 *p, const void *s, unsigned int len)
0144 {
0145 return xdr_encode_opaque(p, s, len);
0146 }
0147
0148
0149
0150
0151 static inline __be32 *
0152 xdr_encode_hyper(__be32 *p, __u64 val)
0153 {
0154 put_unaligned_be64(val, p);
0155 return p + 2;
0156 }
0157
0158 static inline __be32 *
0159 xdr_decode_hyper(__be32 *p, __u64 *valp)
0160 {
0161 *valp = get_unaligned_be64(p);
0162 return p + 2;
0163 }
0164
0165 static inline __be32 *
0166 xdr_decode_opaque_fixed(__be32 *p, void *ptr, unsigned int len)
0167 {
0168 memcpy(ptr, p, len);
0169 return p + XDR_QUADLEN(len);
0170 }
0171
0172 static inline void xdr_netobj_dup(struct xdr_netobj *dst,
0173 struct xdr_netobj *src, gfp_t gfp_mask)
0174 {
0175 dst->data = kmemdup(src->data, src->len, gfp_mask);
0176 dst->len = src->len;
0177 }
0178
0179
0180
0181
0182 static inline int
0183 xdr_adjust_iovec(struct kvec *iov, __be32 *p)
0184 {
0185 return iov->iov_len = ((u8 *) p - (u8 *) iov->iov_base);
0186 }
0187
0188
0189
0190
0191 extern void xdr_shift_buf(struct xdr_buf *, size_t);
0192 extern void xdr_buf_from_iov(const struct kvec *, struct xdr_buf *);
0193 extern int xdr_buf_subsegment(const struct xdr_buf *, struct xdr_buf *, unsigned int, unsigned int);
0194 extern void xdr_buf_trim(struct xdr_buf *, unsigned int);
0195 extern int read_bytes_from_xdr_buf(const struct xdr_buf *, unsigned int, void *, unsigned int);
0196 extern int write_bytes_to_xdr_buf(const struct xdr_buf *, unsigned int, void *, unsigned int);
0197
0198 extern int xdr_encode_word(const struct xdr_buf *, unsigned int, u32);
0199 extern int xdr_decode_word(const struct xdr_buf *, unsigned int, u32 *);
0200
0201 struct xdr_array2_desc;
0202 typedef int (*xdr_xcode_elem_t)(struct xdr_array2_desc *desc, void *elem);
0203 struct xdr_array2_desc {
0204 unsigned int elem_size;
0205 unsigned int array_len;
0206 unsigned int array_maxlen;
0207 xdr_xcode_elem_t xcode;
0208 };
0209
0210 extern int xdr_decode_array2(const struct xdr_buf *buf, unsigned int base,
0211 struct xdr_array2_desc *desc);
0212 extern int xdr_encode_array2(const struct xdr_buf *buf, unsigned int base,
0213 struct xdr_array2_desc *desc);
0214 extern void _copy_from_pages(char *p, struct page **pages, size_t pgbase,
0215 size_t len);
0216
0217
0218
0219
0220 struct xdr_stream {
0221 __be32 *p;
0222 struct xdr_buf *buf;
0223
0224 __be32 *end;
0225 struct kvec *iov;
0226 struct kvec scratch;
0227 struct page **page_ptr;
0228 unsigned int nwords;
0229
0230 struct rpc_rqst *rqst;
0231 };
0232
0233
0234
0235
0236 typedef void (*kxdreproc_t)(struct rpc_rqst *rqstp, struct xdr_stream *xdr,
0237 const void *obj);
0238 typedef int (*kxdrdproc_t)(struct rpc_rqst *rqstp, struct xdr_stream *xdr,
0239 void *obj);
0240
0241 extern void xdr_init_encode(struct xdr_stream *xdr, struct xdr_buf *buf,
0242 __be32 *p, struct rpc_rqst *rqst);
0243 extern __be32 *xdr_reserve_space(struct xdr_stream *xdr, size_t nbytes);
0244 extern int xdr_reserve_space_vec(struct xdr_stream *xdr, struct kvec *vec,
0245 size_t nbytes);
0246 extern void __xdr_commit_encode(struct xdr_stream *xdr);
0247 extern void xdr_truncate_encode(struct xdr_stream *xdr, size_t len);
0248 extern int xdr_restrict_buflen(struct xdr_stream *xdr, int newbuflen);
0249 extern void xdr_write_pages(struct xdr_stream *xdr, struct page **pages,
0250 unsigned int base, unsigned int len);
0251 extern unsigned int xdr_stream_pos(const struct xdr_stream *xdr);
0252 extern unsigned int xdr_page_pos(const struct xdr_stream *xdr);
0253 extern void xdr_init_decode(struct xdr_stream *xdr, struct xdr_buf *buf,
0254 __be32 *p, struct rpc_rqst *rqst);
0255 extern void xdr_init_decode_pages(struct xdr_stream *xdr, struct xdr_buf *buf,
0256 struct page **pages, unsigned int len);
0257 extern __be32 *xdr_inline_decode(struct xdr_stream *xdr, size_t nbytes);
0258 extern unsigned int xdr_read_pages(struct xdr_stream *xdr, unsigned int len);
0259 extern void xdr_enter_page(struct xdr_stream *xdr, unsigned int len);
0260 extern int xdr_process_buf(const struct xdr_buf *buf, unsigned int offset, unsigned int len, int (*actor)(struct scatterlist *, void *), void *data);
0261 extern void xdr_set_pagelen(struct xdr_stream *, unsigned int len);
0262 extern bool xdr_stream_subsegment(struct xdr_stream *xdr, struct xdr_buf *subbuf,
0263 unsigned int len);
0264 extern unsigned int xdr_stream_move_subsegment(struct xdr_stream *xdr, unsigned int offset,
0265 unsigned int target, unsigned int length);
0266 extern unsigned int xdr_stream_zero(struct xdr_stream *xdr, unsigned int offset,
0267 unsigned int length);
0268
0269
0270
0271
0272
0273
0274
0275
0276
0277
0278
0279
0280 static inline void
0281 xdr_set_scratch_buffer(struct xdr_stream *xdr, void *buf, size_t buflen)
0282 {
0283 xdr->scratch.iov_base = buf;
0284 xdr->scratch.iov_len = buflen;
0285 }
0286
0287
0288
0289
0290
0291
0292
0293
0294 static inline void
0295 xdr_set_scratch_page(struct xdr_stream *xdr, struct page *page)
0296 {
0297 xdr_set_scratch_buffer(xdr, page_address(page), PAGE_SIZE);
0298 }
0299
0300
0301
0302
0303
0304
0305
0306 static inline void
0307 xdr_reset_scratch_buffer(struct xdr_stream *xdr)
0308 {
0309 xdr_set_scratch_buffer(xdr, NULL, 0);
0310 }
0311
0312
0313
0314
0315
0316
0317
0318
0319
0320 static inline void xdr_commit_encode(struct xdr_stream *xdr)
0321 {
0322 if (unlikely(xdr->scratch.iov_len))
0323 __xdr_commit_encode(xdr);
0324 }
0325
0326
0327
0328
0329
0330
0331
0332
0333 static inline size_t
0334 xdr_stream_remaining(const struct xdr_stream *xdr)
0335 {
0336 return xdr->nwords << 2;
0337 }
0338
0339 ssize_t xdr_stream_decode_opaque(struct xdr_stream *xdr, void *ptr,
0340 size_t size);
0341 ssize_t xdr_stream_decode_opaque_dup(struct xdr_stream *xdr, void **ptr,
0342 size_t maxlen, gfp_t gfp_flags);
0343 ssize_t xdr_stream_decode_string(struct xdr_stream *xdr, char *str,
0344 size_t size);
0345 ssize_t xdr_stream_decode_string_dup(struct xdr_stream *xdr, char **str,
0346 size_t maxlen, gfp_t gfp_flags);
0347
0348
0349
0350
0351
0352
0353
0354 static inline size_t
0355 xdr_align_size(size_t n)
0356 {
0357 const size_t mask = XDR_UNIT - 1;
0358
0359 return (n + mask) & ~mask;
0360 }
0361
0362
0363
0364
0365
0366
0367
0368
0369
0370
0371
0372 static inline size_t xdr_pad_size(size_t n)
0373 {
0374 return xdr_align_size(n) - n;
0375 }
0376
0377
0378
0379
0380
0381
0382
0383
0384
0385 static inline ssize_t xdr_stream_encode_item_present(struct xdr_stream *xdr)
0386 {
0387 const size_t len = XDR_UNIT;
0388 __be32 *p = xdr_reserve_space(xdr, len);
0389
0390 if (unlikely(!p))
0391 return -EMSGSIZE;
0392 *p = xdr_one;
0393 return len;
0394 }
0395
0396
0397
0398
0399
0400
0401
0402
0403
0404 static inline int xdr_stream_encode_item_absent(struct xdr_stream *xdr)
0405 {
0406 const size_t len = XDR_UNIT;
0407 __be32 *p = xdr_reserve_space(xdr, len);
0408
0409 if (unlikely(!p))
0410 return -EMSGSIZE;
0411 *p = xdr_zero;
0412 return len;
0413 }
0414
0415
0416
0417
0418
0419
0420
0421
0422
0423 static inline __be32 *xdr_encode_bool(__be32 *p, u32 n)
0424 {
0425 *p++ = n ? xdr_one : xdr_zero;
0426 return p;
0427 }
0428
0429
0430
0431
0432
0433
0434
0435
0436
0437
0438 static inline int xdr_stream_encode_bool(struct xdr_stream *xdr, __u32 n)
0439 {
0440 const size_t len = XDR_UNIT;
0441 __be32 *p = xdr_reserve_space(xdr, len);
0442
0443 if (unlikely(!p))
0444 return -EMSGSIZE;
0445 xdr_encode_bool(p, n);
0446 return len;
0447 }
0448
0449
0450
0451
0452
0453
0454
0455
0456
0457
0458 static inline ssize_t
0459 xdr_stream_encode_u32(struct xdr_stream *xdr, __u32 n)
0460 {
0461 const size_t len = sizeof(n);
0462 __be32 *p = xdr_reserve_space(xdr, len);
0463
0464 if (unlikely(!p))
0465 return -EMSGSIZE;
0466 *p = cpu_to_be32(n);
0467 return len;
0468 }
0469
0470
0471
0472
0473
0474
0475
0476
0477
0478
0479 static inline ssize_t
0480 xdr_stream_encode_u64(struct xdr_stream *xdr, __u64 n)
0481 {
0482 const size_t len = sizeof(n);
0483 __be32 *p = xdr_reserve_space(xdr, len);
0484
0485 if (unlikely(!p))
0486 return -EMSGSIZE;
0487 xdr_encode_hyper(p, n);
0488 return len;
0489 }
0490
0491
0492
0493
0494
0495
0496
0497
0498
0499
0500
0501 static inline ssize_t
0502 xdr_stream_encode_opaque_inline(struct xdr_stream *xdr, void **ptr, size_t len)
0503 {
0504 size_t count = sizeof(__u32) + xdr_align_size(len);
0505 __be32 *p = xdr_reserve_space(xdr, count);
0506
0507 if (unlikely(!p)) {
0508 *ptr = NULL;
0509 return -EMSGSIZE;
0510 }
0511 xdr_encode_opaque(p, NULL, len);
0512 *ptr = ++p;
0513 return count;
0514 }
0515
0516
0517
0518
0519
0520
0521
0522
0523
0524
0525
0526 static inline ssize_t
0527 xdr_stream_encode_opaque_fixed(struct xdr_stream *xdr, const void *ptr, size_t len)
0528 {
0529 __be32 *p = xdr_reserve_space(xdr, len);
0530
0531 if (unlikely(!p))
0532 return -EMSGSIZE;
0533 xdr_encode_opaque_fixed(p, ptr, len);
0534 return xdr_align_size(len);
0535 }
0536
0537
0538
0539
0540
0541
0542
0543
0544
0545
0546
0547 static inline ssize_t
0548 xdr_stream_encode_opaque(struct xdr_stream *xdr, const void *ptr, size_t len)
0549 {
0550 size_t count = sizeof(__u32) + xdr_align_size(len);
0551 __be32 *p = xdr_reserve_space(xdr, count);
0552
0553 if (unlikely(!p))
0554 return -EMSGSIZE;
0555 xdr_encode_opaque(p, ptr, len);
0556 return count;
0557 }
0558
0559
0560
0561
0562
0563
0564
0565
0566
0567
0568
0569 static inline ssize_t
0570 xdr_stream_encode_uint32_array(struct xdr_stream *xdr,
0571 const __u32 *array, size_t array_size)
0572 {
0573 ssize_t ret = (array_size+1) * sizeof(__u32);
0574 __be32 *p = xdr_reserve_space(xdr, ret);
0575
0576 if (unlikely(!p))
0577 return -EMSGSIZE;
0578 *p++ = cpu_to_be32(array_size);
0579 for (; array_size > 0; p++, array++, array_size--)
0580 *p = cpu_to_be32p(array);
0581 return ret;
0582 }
0583
0584
0585
0586
0587
0588
0589
0590
0591
0592 static inline bool xdr_item_is_absent(const __be32 *p)
0593 {
0594 return *p == xdr_zero;
0595 }
0596
0597
0598
0599
0600
0601
0602
0603
0604
0605 static inline bool xdr_item_is_present(const __be32 *p)
0606 {
0607 return *p != xdr_zero;
0608 }
0609
0610
0611
0612
0613
0614
0615
0616
0617
0618
0619 static inline ssize_t
0620 xdr_stream_decode_bool(struct xdr_stream *xdr, __u32 *ptr)
0621 {
0622 const size_t count = sizeof(*ptr);
0623 __be32 *p = xdr_inline_decode(xdr, count);
0624
0625 if (unlikely(!p))
0626 return -EBADMSG;
0627 *ptr = (*p != xdr_zero);
0628 return 0;
0629 }
0630
0631
0632
0633
0634
0635
0636
0637
0638
0639
0640 static inline ssize_t
0641 xdr_stream_decode_u32(struct xdr_stream *xdr, __u32 *ptr)
0642 {
0643 const size_t count = sizeof(*ptr);
0644 __be32 *p = xdr_inline_decode(xdr, count);
0645
0646 if (unlikely(!p))
0647 return -EBADMSG;
0648 *ptr = be32_to_cpup(p);
0649 return 0;
0650 }
0651
0652
0653
0654
0655
0656
0657
0658
0659
0660
0661 static inline ssize_t
0662 xdr_stream_decode_u64(struct xdr_stream *xdr, __u64 *ptr)
0663 {
0664 const size_t count = sizeof(*ptr);
0665 __be32 *p = xdr_inline_decode(xdr, count);
0666
0667 if (unlikely(!p))
0668 return -EBADMSG;
0669 xdr_decode_hyper(p, ptr);
0670 return 0;
0671 }
0672
0673
0674
0675
0676
0677
0678
0679
0680
0681
0682
0683 static inline ssize_t
0684 xdr_stream_decode_opaque_fixed(struct xdr_stream *xdr, void *ptr, size_t len)
0685 {
0686 __be32 *p = xdr_inline_decode(xdr, len);
0687
0688 if (unlikely(!p))
0689 return -EBADMSG;
0690 xdr_decode_opaque_fixed(p, ptr, len);
0691 return len;
0692 }
0693
0694
0695
0696
0697
0698
0699
0700
0701
0702
0703
0704
0705
0706
0707
0708
0709
0710 static inline ssize_t
0711 xdr_stream_decode_opaque_inline(struct xdr_stream *xdr, void **ptr, size_t maxlen)
0712 {
0713 __be32 *p;
0714 __u32 len;
0715
0716 *ptr = NULL;
0717 if (unlikely(xdr_stream_decode_u32(xdr, &len) < 0))
0718 return -EBADMSG;
0719 if (len != 0) {
0720 p = xdr_inline_decode(xdr, len);
0721 if (unlikely(!p))
0722 return -EBADMSG;
0723 if (unlikely(len > maxlen))
0724 return -EMSGSIZE;
0725 *ptr = p;
0726 }
0727 return len;
0728 }
0729
0730
0731
0732
0733
0734
0735
0736
0737
0738
0739
0740
0741 static inline ssize_t
0742 xdr_stream_decode_uint32_array(struct xdr_stream *xdr,
0743 __u32 *array, size_t array_size)
0744 {
0745 __be32 *p;
0746 __u32 len;
0747 ssize_t retval;
0748
0749 if (unlikely(xdr_stream_decode_u32(xdr, &len) < 0))
0750 return -EBADMSG;
0751 if (len > SIZE_MAX / sizeof(*p))
0752 return -EBADMSG;
0753 p = xdr_inline_decode(xdr, len * sizeof(*p));
0754 if (unlikely(!p))
0755 return -EBADMSG;
0756 if (array == NULL)
0757 return len;
0758 if (len <= array_size) {
0759 if (len < array_size)
0760 memset(array+len, 0, (array_size-len)*sizeof(*array));
0761 array_size = len;
0762 retval = len;
0763 } else
0764 retval = -EMSGSIZE;
0765 for (; array_size > 0; p++, array++, array_size--)
0766 *array = be32_to_cpup(p);
0767 return retval;
0768 }
0769
0770 #endif