]> git.saurik.com Git - apple/xnu.git/blob - bsd/nfs/xdr_subs.h
24295f4875ddd28eb64549cbe528b150115e664c
[apple/xnu.git] / bsd / nfs / xdr_subs.h
1 /*
2 * Copyright (c) 2000-2011 Apple Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
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.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
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
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
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.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28 /* Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved */
29 /*
30 * Copyright (c) 1989, 1993
31 * The Regents of the University of California. All rights reserved.
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:
46 * This product includes software developed by the University of
47 * California, Berkeley and its contributors.
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 *
64 * @(#)xdr_subs.h 8.3 (Berkeley) 3/30/95
65 * FreeBSD-Id: xdr_subs.h,v 1.9 1997/02/22 09:42:53 peter Exp $
66 */
67
68 #ifndef _NFS_XDR_SUBS_H_
69 #define _NFS_XDR_SUBS_H_
70
71 #include <sys/appleapiopts.h>
72
73 #ifdef __APPLE_API_PRIVATE
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
85 #define fxdr_unsigned(t, v) ((t)ntohl((uint32_t)(v)))
86 #define txdr_unsigned(v) (htonl((uint32_t)(v)))
87
88 #define fxdr_hyper(f, t) { \
89 ((uint32_t *)(t))[_QUAD_HIGHWORD] = ntohl(((uint32_t *)(f))[0]); \
90 ((uint32_t *)(t))[_QUAD_LOWWORD] = ntohl(((uint32_t *)(f))[1]); \
91 }
92 #define txdr_hyper(f, t) { \
93 ((uint32_t *)(t))[0] = htonl(((uint32_t *)(f))[_QUAD_HIGHWORD]); \
94 ((uint32_t *)(t))[1] = htonl(((uint32_t *)(f))[_QUAD_LOWWORD]); \
95 }
96
97
98 /*
99 * xdrbuf
100 *
101 * generalized functionality for managing the building/dissecting of XDR data
102 */
103 typedef enum xdrbuf_type { XDRBUF_BUFFER=1 } xdrbuf_type;
104
105 struct xdrbuf {
106 union {
107 struct {
108 char * xbb_base; /* base address of buffer */
109 uint32_t xbb_size; /* size of buffer */
110 uint32_t xbb_len; /* length of data in buffer */
111 } xb_buffer;
112 } xb_u;
113 char * xb_ptr; /* pointer to current position */
114 size_t xb_left; /* bytes remaining in current buffer */
115 size_t xb_growsize; /* bytes to allocate when growing */
116 xdrbuf_type xb_type; /* type of xdr buffer */
117 uint32_t xb_flags; /* XB_* (see below) */
118 };
119
120 #define XB_CLEANUP 0x0001 /* needs cleanup */
121
122 #define XDRWORD 4 /* the basic XDR building block is a 4 byte (32 bit) word */
123 #define xdr_rndup(a) (((a)+3)&(~0x3)) /* round up to XDRWORD size */
124 #define xdr_pad(a) (xdr_rndup(a) - (a)) /* calculate round up padding */
125
126 void xb_init(struct xdrbuf *, xdrbuf_type);
127 void xb_init_buffer(struct xdrbuf *, char *, size_t);
128 void xb_cleanup(struct xdrbuf *);
129 void *xb_malloc(size_t);
130 void xb_free(void *);
131 int xb_grow(struct xdrbuf *);
132 void xb_set_cur_buf_len(struct xdrbuf *);
133 char *xb_buffer_base(struct xdrbuf *);
134 int xb_advance(struct xdrbuf *, uint32_t);
135 int xb_offset(struct xdrbuf *);
136 int xb_seek(struct xdrbuf *, uint32_t);
137 int xb_add_bytes(struct xdrbuf *, const char *, uint32_t, int);
138 int xb_get_bytes(struct xdrbuf *, char *, uint32_t, int);
139
140 #ifdef _NFS_XDR_SUBS_FUNCS_
141
142 /*
143 * basic initialization of xdrbuf structure
144 */
145 void
146 xb_init(struct xdrbuf *xbp, xdrbuf_type type)
147 {
148 bzero(xbp, sizeof(*xbp));
149 xbp->xb_type = type;
150 xbp->xb_flags |= XB_CLEANUP;
151 }
152
153 /*
154 * initialize a single-buffer xdrbuf
155 */
156 void
157 xb_init_buffer(struct xdrbuf *xbp, char *buf, size_t buflen)
158 {
159 xb_init(xbp, XDRBUF_BUFFER);
160 xbp->xb_u.xb_buffer.xbb_base = buf;
161 xbp->xb_u.xb_buffer.xbb_size = buflen;
162 xbp->xb_u.xb_buffer.xbb_len = buflen;
163 xbp->xb_growsize = 512;
164 xbp->xb_ptr = buf;
165 xbp->xb_left = buflen;
166 if (buf) { /* when using an existing buffer, xb code should skip cleanup */
167 xbp->xb_flags &= ~XB_CLEANUP;
168 }
169 }
170
171 /*
172 * get the pointer to the single-buffer xdrbuf's buffer
173 */
174 char *
175 xb_buffer_base(struct xdrbuf *xbp)
176 {
177 return xbp->xb_u.xb_buffer.xbb_base;
178 }
179
180 /*
181 * clean up any resources held by an xdrbuf
182 */
183 void
184 xb_cleanup(struct xdrbuf *xbp)
185 {
186 if (!(xbp->xb_flags & XB_CLEANUP)) {
187 return;
188 }
189 switch (xbp->xb_type) {
190 case XDRBUF_BUFFER:
191 if (xbp->xb_u.xb_buffer.xbb_base) {
192 xb_free(xbp->xb_u.xb_buffer.xbb_base);
193 }
194 break;
195 }
196 xbp->xb_flags &= ~XB_CLEANUP;
197 }
198
199 /*
200 * set the length of valid data in the current buffer to
201 * be up to the current location within the buffer
202 */
203 void
204 xb_set_cur_buf_len(struct xdrbuf *xbp)
205 {
206 switch (xbp->xb_type) {
207 case XDRBUF_BUFFER:
208 xbp->xb_u.xb_buffer.xbb_len = xbp->xb_ptr - xbp->xb_u.xb_buffer.xbb_base;
209 break;
210 }
211 }
212
213 /*
214 * advance forward through existing data in xdrbuf
215 */
216 int
217 xb_advance(struct xdrbuf *xbp, uint32_t len)
218 {
219 uint32_t tlen;
220
221 while (len) {
222 if (xbp->xb_left <= 0) {
223 return EBADRPC;
224 }
225 tlen = MIN(xbp->xb_left, len);
226 if (tlen) {
227 xbp->xb_ptr += tlen;
228 xbp->xb_left -= tlen;
229 len -= tlen;
230 }
231 }
232 return 0;
233 }
234
235 /*
236 * Calculate the current offset in the XDR buffer.
237 */
238 int
239 xb_offset(struct xdrbuf *xbp)
240 {
241 uint32_t offset = 0;
242
243 switch (xbp->xb_type) {
244 case XDRBUF_BUFFER:
245 offset = xbp->xb_ptr - xbp->xb_u.xb_buffer.xbb_base;
246 break;
247 }
248
249 return offset;
250 }
251
252 /*
253 * Seek to the given offset in the existing data in the XDR buffer.
254 */
255 int
256 xb_seek(struct xdrbuf *xbp, uint32_t offset)
257 {
258 switch (xbp->xb_type) {
259 case XDRBUF_BUFFER:
260 xbp->xb_ptr = xbp->xb_u.xb_buffer.xbb_base + offset;
261 xbp->xb_left = xbp->xb_u.xb_buffer.xbb_len - offset;
262 break;
263 }
264
265 return 0;
266 }
267
268 /*
269 * allocate memory
270 */
271 void *
272 xb_malloc(size_t size)
273 {
274 void *buf = NULL;
275
276 #ifdef KERNEL
277 MALLOC(buf, void *, size, M_TEMP, M_WAITOK);
278 #else
279 buf = malloc(size);
280 #endif
281 return buf;
282 }
283 /*
284 * free a chunk of memory allocated with xb_malloc()
285 */
286 void
287 xb_free(void *buf)
288 {
289 #ifdef KERNEL
290 FREE(buf, M_TEMP);
291 #else
292 free(buf);
293 #endif
294 }
295
296 /*
297 * Increase space available for new data in XDR buffer.
298 */
299 int
300 xb_grow(struct xdrbuf *xbp)
301 {
302 char *newbuf, *oldbuf;
303 size_t newsize, oldsize;
304
305 switch (xbp->xb_type) {
306 case XDRBUF_BUFFER:
307 oldsize = xbp->xb_u.xb_buffer.xbb_size;
308 oldbuf = xbp->xb_u.xb_buffer.xbb_base;
309 newsize = oldsize + xbp->xb_growsize;
310 if (newsize < oldsize) {
311 return ENOMEM;
312 }
313 newbuf = xb_malloc(newsize);
314 if (newbuf == NULL) {
315 return ENOMEM;
316 }
317 if (oldbuf != NULL) {
318 bcopy(oldbuf, newbuf, oldsize);
319 xb_free(oldbuf);
320 }
321 xbp->xb_u.xb_buffer.xbb_base = newbuf;
322 xbp->xb_u.xb_buffer.xbb_size = newsize;
323 xbp->xb_ptr = newbuf + oldsize;
324 xbp->xb_left = xbp->xb_growsize;
325 break;
326 }
327
328 return 0;
329 }
330
331 /*
332 * xb_add_bytes()
333 *
334 * Add "count" bytes of opaque data pointed to by "buf" to the given XDR buffer.
335 */
336 int
337 xb_add_bytes(struct xdrbuf *xbp, const char *buf, uint32_t count, int nopad)
338 {
339 uint32_t len, tlen;
340 int error;
341
342 len = nopad ? count : xdr_rndup(count);
343
344 /* copy in "count" bytes and zero out any pad bytes */
345 while (len) {
346 if (xbp->xb_left <= 0) {
347 /* need more space */
348 if ((error = xb_grow(xbp))) {
349 return error;
350 }
351 if (xbp->xb_left <= 0) {
352 return ENOMEM;
353 }
354 }
355 tlen = MIN(xbp->xb_left, len);
356 if (tlen) {
357 if (count) {
358 if (tlen > count) {
359 tlen = count;
360 }
361 bcopy(buf, xbp->xb_ptr, tlen);
362 } else {
363 bzero(xbp->xb_ptr, tlen);
364 }
365 xbp->xb_ptr += tlen;
366 xbp->xb_left -= tlen;
367 len -= tlen;
368 if (count) {
369 buf += tlen;
370 count -= tlen;
371 }
372 }
373 }
374 return 0;
375 }
376
377 /*
378 * xb_get_bytes()
379 *
380 * Get "count" bytes of opaque data from the given XDR buffer.
381 */
382 int
383 xb_get_bytes(struct xdrbuf *xbp, char *buf, uint32_t count, int nopad)
384 {
385 uint32_t len, tlen;
386
387 len = nopad ? count : xdr_rndup(count);
388
389 /* copy in "count" bytes and zero out any pad bytes */
390 while (len) {
391 if (xbp->xb_left <= 0) {
392 return ENOMEM;
393 }
394 tlen = MIN(xbp->xb_left, len);
395 if (tlen) {
396 if (count) {
397 if (tlen > count) {
398 tlen = count;
399 }
400 bcopy(xbp->xb_ptr, buf, tlen);
401 }
402 xbp->xb_ptr += tlen;
403 xbp->xb_left -= tlen;
404 len -= tlen;
405 if (count) {
406 buf += tlen;
407 count -= tlen;
408 }
409 }
410 }
411 return 0;
412 }
413
414 #endif /* _NFS_XDR_SUBS_FUNCS_ */
415
416
417 /*
418 * macros for building XDR data
419 */
420
421 /* finalize the data that has been added to the buffer */
422 #define xb_build_done(E, XB) \
423 do { \
424 if (E) break; \
425 xb_set_cur_buf_len(XB); \
426 } while (0)
427
428 /* add a 32-bit value */
429 #define xb_add_32(E, XB, VAL) \
430 do { \
431 uint32_t __tmp; \
432 if (E) break; \
433 __tmp = txdr_unsigned(VAL); \
434 (E) = xb_add_bytes((XB), (void*)&__tmp, XDRWORD, 0); \
435 } while (0)
436
437 /* add a 64-bit value */
438 #define xb_add_64(E, XB, VAL) \
439 do { \
440 uint64_t __tmp1, __tmp2; \
441 if (E) break; \
442 __tmp1 = (VAL); \
443 txdr_hyper(&__tmp1, &__tmp2); \
444 (E) = xb_add_bytes((XB), (char*)&__tmp2, 2 * XDRWORD, 0); \
445 } while (0)
446
447 /* add an array of XDR words */
448 #define xb_add_word_array(E, XB, A, LEN) \
449 do { \
450 uint32_t __i; \
451 xb_add_32((E), (XB), (LEN)); \
452 for (__i=0; __i < (uint32_t)(LEN); __i++) \
453 xb_add_32((E), (XB), (A)[__i]); \
454 } while (0)
455 #define xb_add_bitmap(E, XB, B, LEN) xb_add_word_array((E), (XB), (B), (LEN))
456
457 /* add a file handle */
458 #define xb_add_fh(E, XB, FHP, FHLEN) \
459 do { \
460 xb_add_32((E), (XB), (FHLEN)); \
461 if (E) break; \
462 (E) = xb_add_bytes((XB), (char*)(FHP), (FHLEN), 0); \
463 } while (0)
464
465 /* add a string */
466 #define xb_add_string(E, XB, S, LEN) \
467 do { \
468 xb_add_32((E), (XB), (LEN)); \
469 if (E) break; \
470 (E) = xb_add_bytes((XB), (const char*)(S), (LEN), 0); \
471 } while (0)
472
473
474 /*
475 * macros for decoding XDR data
476 */
477
478 /* skip past data in the buffer */
479 #define xb_skip(E, XB, LEN) \
480 do { \
481 if (E) break; \
482 (E) = xb_advance((XB), (LEN)); \
483 } while (0)
484
485 /* get a 32-bit value */
486 #define xb_get_32(E, XB, LVAL) \
487 do { \
488 uint32_t __tmp; \
489 if (E) break; \
490 (E) = xb_get_bytes((XB), (char*)&__tmp, XDRWORD, 0); \
491 if (E) break; \
492 (LVAL) = fxdr_unsigned(uint32_t, __tmp); \
493 } while (0)
494
495 /* get a 64-bit value */
496 #define xb_get_64(E, XB, LVAL) \
497 do { \
498 uint64_t __tmp; \
499 if (E) break; \
500 (E) = xb_get_bytes((XB), (char*)&__tmp, 2 * XDRWORD, 0); \
501 if (E) break; \
502 fxdr_hyper(&__tmp, &(LVAL)); \
503 } while (0)
504
505 /* get an array of XDR words (of a given expected/maximum length) */
506 #define xb_get_word_array(E, XB, A, LEN) \
507 do { \
508 uint32_t __len = 0, __i; \
509 xb_get_32((E), (XB), __len); \
510 if (E) break; \
511 for (__i=0; __i < MIN(__len, (uint32_t)(LEN)); __i++) \
512 xb_get_32((E), (XB), (A)[__i]); \
513 if (E) break; \
514 for (; __i < __len; __i++) \
515 xb_skip((E), (XB), XDRWORD); \
516 for (; __i < (uint32_t)(LEN); __i++) \
517 (A)[__i] = 0; \
518 (LEN) = __len; \
519 } while (0)
520 #define xb_get_bitmap(E, XB, B, LEN) xb_get_word_array((E), (XB), (B), (LEN))
521
522 #endif /* __APPLE_API_PRIVATE */
523 #endif /* _NFS_XDR_SUBS_H_ */