]> git.saurik.com Git - apple/xnu.git/blame - bsd/nfs/xdr_subs.h
xnu-7195.101.1.tar.gz
[apple/xnu.git] / bsd / nfs / xdr_subs.h
CommitLineData
1c79356b 1/*
6d2010ae 2 * Copyright (c) 2000-2011 Apple Inc. All rights reserved.
5d5c5d0d 3 *
2d21ac55 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
0a7de745 5 *
2d21ac55
A
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
0a7de745 14 *
2d21ac55
A
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
0a7de745 17 *
2d21ac55
A
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
8f6c56a5
A
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
2d21ac55
A
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
0a7de745 25 *
2d21ac55 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
1c79356b
A
27 */
28/* Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved */
29/*
30 * Copyright (c) 1989, 1993
91447636 31 * The Regents of the University of California. All rights reserved.
1c79356b
A
32 *
33 * This code is derived from software contributed to Berkeley by
34 * Rick Macklem at The University of Guelph.
35 *
36 * Redistribution and use in source and binary forms, with or without
37 * modification, are permitted provided that the following conditions
38 * are met:
39 * 1. Redistributions of source code must retain the above copyright
40 * notice, this list of conditions and the following disclaimer.
41 * 2. Redistributions in binary form must reproduce the above copyright
42 * notice, this list of conditions and the following disclaimer in the
43 * documentation and/or other materials provided with the distribution.
44 * 3. All advertising materials mentioning features or use of this software
45 * must display the following acknowledgement:
91447636
A
46 * This product includes software developed by the University of
47 * California, Berkeley and its contributors.
1c79356b
A
48 * 4. Neither the name of the University nor the names of its contributors
49 * may be used to endorse or promote products derived from this software
50 * without specific prior written permission.
51 *
52 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
53 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
54 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
55 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
56 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
57 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
58 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
59 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
60 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
61 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
62 * SUCH DAMAGE.
63 *
91447636 64 * @(#)xdr_subs.h 8.3 (Berkeley) 3/30/95
1c79356b
A
65 * FreeBSD-Id: xdr_subs.h,v 1.9 1997/02/22 09:42:53 peter Exp $
66 */
1c79356b
A
67
68#ifndef _NFS_XDR_SUBS_H_
69#define _NFS_XDR_SUBS_H_
70
9bccf70c
A
71#include <sys/appleapiopts.h>
72
73#ifdef __APPLE_API_PRIVATE
1c79356b
A
74/*
75 * Macros used for conversion to/from xdr representation by nfs...
76 * These use the MACHINE DEPENDENT routines ntohl, htonl
77 * As defined by "XDR: External Data Representation Standard" RFC1014
78 *
79 * To simplify the implementation, we use ntohl/htonl even on big-endian
80 * machines, and count on them being `#define'd away. Some of these
81 * might be slightly more efficient as quad_t copies on a big-endian,
82 * but we cannot count on their alignment anyway.
83 */
84
0a7de745
A
85#define fxdr_unsigned(t, v) ((t)ntohl((uint32_t)(v)))
86#define txdr_unsigned(v) (htonl((uint32_t)(v)))
1c79356b 87
0a7de745 88#define fxdr_hyper(f, t) { \
b0d623f7
A
89 ((uint32_t *)(t))[_QUAD_HIGHWORD] = ntohl(((uint32_t *)(f))[0]); \
90 ((uint32_t *)(t))[_QUAD_LOWWORD] = ntohl(((uint32_t *)(f))[1]); \
1c79356b 91}
0a7de745 92#define txdr_hyper(f, t) { \
b0d623f7
A
93 ((uint32_t *)(t))[0] = htonl(((uint32_t *)(f))[_QUAD_HIGHWORD]); \
94 ((uint32_t *)(t))[1] = htonl(((uint32_t *)(f))[_QUAD_LOWWORD]); \
1c79356b
A
95}
96
6d2010ae
A
97
98/*
99 * xdrbuf
100 *
101 * generalized functionality for managing the building/dissecting of XDR data
102 */
cb323159
A
103typedef enum xdrbuf_type {
104 XDRBUF_NONE = 0,
105 XDRBUF_BUFFER = 1,
106} xdrbuf_type;
6d2010ae
A
107
108struct xdrbuf {
109 union {
110 struct {
0a7de745 111 char * xbb_base; /* base address of buffer */
f427ee49
A
112 size_t xbb_size; /* size of buffer */
113 size_t xbb_len; /* length of data in buffer */
6d2010ae
A
114 } xb_buffer;
115 } xb_u;
0a7de745
A
116 char * xb_ptr; /* pointer to current position */
117 size_t xb_left; /* bytes remaining in current buffer */
118 size_t xb_growsize; /* bytes to allocate when growing */
119 xdrbuf_type xb_type; /* type of xdr buffer */
120 uint32_t xb_flags; /* XB_* (see below) */
6d2010ae
A
121};
122
0a7de745 123#define XB_CLEANUP 0x0001 /* needs cleanup */
6d2010ae 124
0a7de745
A
125#define XDRWORD 4 /* the basic XDR building block is a 4 byte (32 bit) word */
126#define xdr_rndup(a) (((a)+3)&(~0x3)) /* round up to XDRWORD size */
127#define xdr_pad(a) (xdr_rndup(a) - (a)) /* calculate round up padding */
6d2010ae
A
128
129void xb_init(struct xdrbuf *, xdrbuf_type);
130void xb_init_buffer(struct xdrbuf *, char *, size_t);
131void xb_cleanup(struct xdrbuf *);
132void *xb_malloc(size_t);
133void xb_free(void *);
134int xb_grow(struct xdrbuf *);
135void xb_set_cur_buf_len(struct xdrbuf *);
136char *xb_buffer_base(struct xdrbuf *);
f427ee49
A
137int xb_advance(struct xdrbuf *, size_t);
138size_t xb_offset(struct xdrbuf *);
139int xb_seek(struct xdrbuf *, size_t);
140int xb_add_bytes(struct xdrbuf *, const char *, size_t, int);
6d2010ae
A
141int xb_get_bytes(struct xdrbuf *, char *, uint32_t, int);
142
143#ifdef _NFS_XDR_SUBS_FUNCS_
144
145/*
146 * basic initialization of xdrbuf structure
147 */
148void
149xb_init(struct xdrbuf *xbp, xdrbuf_type type)
150{
151 bzero(xbp, sizeof(*xbp));
152 xbp->xb_type = type;
153 xbp->xb_flags |= XB_CLEANUP;
154}
155
156/*
157 * initialize a single-buffer xdrbuf
158 */
159void
160xb_init_buffer(struct xdrbuf *xbp, char *buf, size_t buflen)
161{
162 xb_init(xbp, XDRBUF_BUFFER);
163 xbp->xb_u.xb_buffer.xbb_base = buf;
164 xbp->xb_u.xb_buffer.xbb_size = buflen;
165 xbp->xb_u.xb_buffer.xbb_len = buflen;
166 xbp->xb_growsize = 512;
167 xbp->xb_ptr = buf;
168 xbp->xb_left = buflen;
0a7de745 169 if (buf) { /* when using an existing buffer, xb code should skip cleanup */
6d2010ae 170 xbp->xb_flags &= ~XB_CLEANUP;
0a7de745 171 }
6d2010ae
A
172}
173
174/*
175 * get the pointer to the single-buffer xdrbuf's buffer
176 */
177char *
178xb_buffer_base(struct xdrbuf *xbp)
179{
0a7de745 180 return xbp->xb_u.xb_buffer.xbb_base;
6d2010ae
A
181}
182
183/*
184 * clean up any resources held by an xdrbuf
185 */
186void
187xb_cleanup(struct xdrbuf *xbp)
188{
0a7de745 189 if (!(xbp->xb_flags & XB_CLEANUP)) {
6d2010ae 190 return;
0a7de745 191 }
6d2010ae
A
192 switch (xbp->xb_type) {
193 case XDRBUF_BUFFER:
0a7de745 194 if (xbp->xb_u.xb_buffer.xbb_base) {
6d2010ae 195 xb_free(xbp->xb_u.xb_buffer.xbb_base);
0a7de745 196 }
6d2010ae 197 break;
cb323159
A
198 default:
199 break;
6d2010ae
A
200 }
201 xbp->xb_flags &= ~XB_CLEANUP;
202}
203
204/*
205 * set the length of valid data in the current buffer to
206 * be up to the current location within the buffer
207 */
208void
209xb_set_cur_buf_len(struct xdrbuf *xbp)
210{
211 switch (xbp->xb_type) {
212 case XDRBUF_BUFFER:
213 xbp->xb_u.xb_buffer.xbb_len = xbp->xb_ptr - xbp->xb_u.xb_buffer.xbb_base;
214 break;
cb323159
A
215 default:
216 break;
6d2010ae
A
217 }
218}
219
220/*
221 * advance forward through existing data in xdrbuf
222 */
223int
f427ee49 224xb_advance(struct xdrbuf *xbp, size_t len)
6d2010ae 225{
f427ee49 226 size_t tlen;
6d2010ae
A
227
228 while (len) {
0a7de745
A
229 if (xbp->xb_left <= 0) {
230 return EBADRPC;
231 }
6d2010ae
A
232 tlen = MIN(xbp->xb_left, len);
233 if (tlen) {
234 xbp->xb_ptr += tlen;
235 xbp->xb_left -= tlen;
236 len -= tlen;
237 }
238 }
0a7de745 239 return 0;
6d2010ae
A
240}
241
242/*
243 * Calculate the current offset in the XDR buffer.
244 */
f427ee49 245size_t
6d2010ae
A
246xb_offset(struct xdrbuf *xbp)
247{
f427ee49 248 size_t offset = 0;
6d2010ae
A
249
250 switch (xbp->xb_type) {
251 case XDRBUF_BUFFER:
252 offset = xbp->xb_ptr - xbp->xb_u.xb_buffer.xbb_base;
253 break;
cb323159
A
254 default:
255 break;
6d2010ae
A
256 }
257
0a7de745 258 return offset;
6d2010ae
A
259}
260
261/*
262 * Seek to the given offset in the existing data in the XDR buffer.
263 */
264int
f427ee49 265xb_seek(struct xdrbuf *xbp, size_t offset)
6d2010ae 266{
6d2010ae
A
267 switch (xbp->xb_type) {
268 case XDRBUF_BUFFER:
269 xbp->xb_ptr = xbp->xb_u.xb_buffer.xbb_base + offset;
270 xbp->xb_left = xbp->xb_u.xb_buffer.xbb_len - offset;
271 break;
cb323159
A
272 default:
273 break;
6d2010ae
A
274 }
275
0a7de745 276 return 0;
6d2010ae
A
277}
278
279/*
280 * allocate memory
281 */
282void *
283xb_malloc(size_t size)
284{
285 void *buf = NULL;
286
287#ifdef KERNEL
288 MALLOC(buf, void *, size, M_TEMP, M_WAITOK);
289#else
290 buf = malloc(size);
291#endif
0a7de745 292 return buf;
6d2010ae
A
293}
294/*
295 * free a chunk of memory allocated with xb_malloc()
296 */
297void
298xb_free(void *buf)
299{
300#ifdef KERNEL
301 FREE(buf, M_TEMP);
302#else
303 free(buf);
304#endif
305}
306
307/*
308 * Increase space available for new data in XDR buffer.
309 */
310int
311xb_grow(struct xdrbuf *xbp)
312{
313 char *newbuf, *oldbuf;
314 size_t newsize, oldsize;
315
316 switch (xbp->xb_type) {
317 case XDRBUF_BUFFER:
318 oldsize = xbp->xb_u.xb_buffer.xbb_size;
319 oldbuf = xbp->xb_u.xb_buffer.xbb_base;
320 newsize = oldsize + xbp->xb_growsize;
0a7de745
A
321 if (newsize < oldsize) {
322 return ENOMEM;
323 }
6d2010ae 324 newbuf = xb_malloc(newsize);
0a7de745
A
325 if (newbuf == NULL) {
326 return ENOMEM;
327 }
6d2010ae
A
328 if (oldbuf != NULL) {
329 bcopy(oldbuf, newbuf, oldsize);
330 xb_free(oldbuf);
331 }
332 xbp->xb_u.xb_buffer.xbb_base = newbuf;
333 xbp->xb_u.xb_buffer.xbb_size = newsize;
334 xbp->xb_ptr = newbuf + oldsize;
335 xbp->xb_left = xbp->xb_growsize;
336 break;
cb323159
A
337 default:
338 break;
6d2010ae
A
339 }
340
0a7de745 341 return 0;
6d2010ae
A
342}
343
344/*
345 * xb_add_bytes()
346 *
347 * Add "count" bytes of opaque data pointed to by "buf" to the given XDR buffer.
348 */
349int
f427ee49 350xb_add_bytes(struct xdrbuf *xbp, const char *buf, size_t count, int nopad)
6d2010ae 351{
f427ee49 352 size_t len, tlen;
6d2010ae
A
353 int error;
354
355 len = nopad ? count : xdr_rndup(count);
356
357 /* copy in "count" bytes and zero out any pad bytes */
358 while (len) {
359 if (xbp->xb_left <= 0) {
360 /* need more space */
0a7de745
A
361 if ((error = xb_grow(xbp))) {
362 return error;
363 }
364 if (xbp->xb_left <= 0) {
365 return ENOMEM;
366 }
6d2010ae
A
367 }
368 tlen = MIN(xbp->xb_left, len);
369 if (tlen) {
370 if (count) {
0a7de745 371 if (tlen > count) {
6d2010ae 372 tlen = count;
0a7de745 373 }
6d2010ae
A
374 bcopy(buf, xbp->xb_ptr, tlen);
375 } else {
376 bzero(xbp->xb_ptr, tlen);
377 }
378 xbp->xb_ptr += tlen;
379 xbp->xb_left -= tlen;
380 len -= tlen;
381 if (count) {
382 buf += tlen;
383 count -= tlen;
384 }
385 }
386 }
0a7de745 387 return 0;
6d2010ae
A
388}
389
390/*
391 * xb_get_bytes()
392 *
393 * Get "count" bytes of opaque data from the given XDR buffer.
394 */
395int
396xb_get_bytes(struct xdrbuf *xbp, char *buf, uint32_t count, int nopad)
397{
f427ee49 398 size_t len, tlen;
6d2010ae
A
399
400 len = nopad ? count : xdr_rndup(count);
401
402 /* copy in "count" bytes and zero out any pad bytes */
403 while (len) {
0a7de745
A
404 if (xbp->xb_left <= 0) {
405 return ENOMEM;
406 }
6d2010ae
A
407 tlen = MIN(xbp->xb_left, len);
408 if (tlen) {
409 if (count) {
0a7de745 410 if (tlen > count) {
6d2010ae 411 tlen = count;
0a7de745 412 }
6d2010ae
A
413 bcopy(xbp->xb_ptr, buf, tlen);
414 }
415 xbp->xb_ptr += tlen;
416 xbp->xb_left -= tlen;
417 len -= tlen;
418 if (count) {
419 buf += tlen;
420 count -= tlen;
421 }
422 }
423 }
0a7de745 424 return 0;
6d2010ae
A
425}
426
427#endif /* _NFS_XDR_SUBS_FUNCS_ */
428
429
430/*
431 * macros for building XDR data
432 */
433
434/* finalize the data that has been added to the buffer */
435#define xb_build_done(E, XB) \
436 do { \
0a7de745
A
437 if (E) break; \
438 xb_set_cur_buf_len(XB); \
6d2010ae
A
439 } while (0)
440
441/* add a 32-bit value */
442#define xb_add_32(E, XB, VAL) \
443 do { \
0a7de745
A
444 uint32_t __tmp; \
445 if (E) break; \
446 __tmp = txdr_unsigned(VAL); \
447 (E) = xb_add_bytes((XB), (void*)&__tmp, XDRWORD, 0); \
6d2010ae
A
448 } while (0)
449
450/* add a 64-bit value */
451#define xb_add_64(E, XB, VAL) \
452 do { \
0a7de745
A
453 uint64_t __tmp1, __tmp2; \
454 if (E) break; \
455 __tmp1 = (VAL); \
456 txdr_hyper(&__tmp1, &__tmp2); \
457 (E) = xb_add_bytes((XB), (char*)&__tmp2, 2 * XDRWORD, 0); \
6d2010ae
A
458 } while (0)
459
460/* add an array of XDR words */
461#define xb_add_word_array(E, XB, A, LEN) \
462 do { \
0a7de745
A
463 uint32_t __i; \
464 xb_add_32((E), (XB), (LEN)); \
465 for (__i=0; __i < (uint32_t)(LEN); __i++) \
466 xb_add_32((E), (XB), (A)[__i]); \
6d2010ae 467 } while (0)
0a7de745 468#define xb_add_bitmap(E, XB, B, LEN) xb_add_word_array((E), (XB), (B), (LEN))
6d2010ae
A
469
470/* add a file handle */
471#define xb_add_fh(E, XB, FHP, FHLEN) \
472 do { \
0a7de745
A
473 xb_add_32((E), (XB), (FHLEN)); \
474 if (E) break; \
475 (E) = xb_add_bytes((XB), (char*)(FHP), (FHLEN), 0); \
6d2010ae
A
476 } while (0)
477
478/* add a string */
479#define xb_add_string(E, XB, S, LEN) \
480 do { \
0a7de745
A
481 xb_add_32((E), (XB), (LEN)); \
482 if (E) break; \
483 (E) = xb_add_bytes((XB), (const char*)(S), (LEN), 0); \
6d2010ae
A
484 } while (0)
485
486
487/*
488 * macros for decoding XDR data
489 */
490
491/* skip past data in the buffer */
492#define xb_skip(E, XB, LEN) \
493 do { \
0a7de745
A
494 if (E) break; \
495 (E) = xb_advance((XB), (LEN)); \
6d2010ae
A
496 } while (0)
497
498/* get a 32-bit value */
499#define xb_get_32(E, XB, LVAL) \
500 do { \
0a7de745 501 uint32_t __tmp; \
f427ee49 502 (LVAL) = (typeof((LVAL))) 0; \
0a7de745
A
503 if (E) break; \
504 (E) = xb_get_bytes((XB), (char*)&__tmp, XDRWORD, 0); \
505 if (E) break; \
506 (LVAL) = fxdr_unsigned(uint32_t, __tmp); \
6d2010ae
A
507 } while (0)
508
509/* get a 64-bit value */
510#define xb_get_64(E, XB, LVAL) \
511 do { \
0a7de745 512 uint64_t __tmp; \
f427ee49 513 (LVAL) = 0; \
0a7de745
A
514 if (E) break; \
515 (E) = xb_get_bytes((XB), (char*)&__tmp, 2 * XDRWORD, 0); \
516 if (E) break; \
517 fxdr_hyper(&__tmp, &(LVAL)); \
6d2010ae
A
518 } while (0)
519
520/* get an array of XDR words (of a given expected/maximum length) */
521#define xb_get_word_array(E, XB, A, LEN) \
522 do { \
0a7de745
A
523 uint32_t __len = 0, __i; \
524 xb_get_32((E), (XB), __len); \
525 if (E) break; \
526 for (__i=0; __i < MIN(__len, (uint32_t)(LEN)); __i++) \
527 xb_get_32((E), (XB), (A)[__i]); \
528 if (E) break; \
529 for (; __i < __len; __i++) \
530 xb_skip((E), (XB), XDRWORD); \
531 for (; __i < (uint32_t)(LEN); __i++) \
532 (A)[__i] = 0; \
533 (LEN) = __len; \
6d2010ae 534 } while (0)
0a7de745 535#define xb_get_bitmap(E, XB, B, LEN) xb_get_word_array((E), (XB), (B), (LEN))
6d2010ae 536
9bccf70c
A
537#endif /* __APPLE_API_PRIVATE */
538#endif /* _NFS_XDR_SUBS_H_ */