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 */ 103typedef enum xdrbuf_type { XDRBUF_BUFFER=1 } xdrbuf_type; 104 105struct 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 126void xb_init(struct xdrbuf *, xdrbuf_type); 127void xb_init_buffer(struct xdrbuf *, char *, size_t); 128void xb_cleanup(struct xdrbuf *); 129void *xb_malloc(size_t); 130void xb_free(void *); 131int xb_grow(struct xdrbuf *); 132void xb_set_cur_buf_len(struct xdrbuf *); 133char *xb_buffer_base(struct xdrbuf *); 134int xb_advance(struct xdrbuf *, uint32_t); 135int xb_offset(struct xdrbuf *); 136int xb_seek(struct xdrbuf *, uint32_t); 137int xb_add_bytes(struct xdrbuf *, const char *, uint32_t, int); 138int 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 */ 145void 146xb_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 */ 156void 157xb_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 * get the pointer to the single-buffer xdrbuf's buffer 172 */ 173char * 174xb_buffer_base(struct xdrbuf *xbp) 175{ 176 return (xbp->xb_u.xb_buffer.xbb_base); 177} 178 179/* 180 * clean up any resources held by an xdrbuf 181 */ 182void 183xb_cleanup(struct xdrbuf *xbp) 184{ 185 if (!(xbp->xb_flags & XB_CLEANUP)) 186 return; 187 switch (xbp->xb_type) { 188 case XDRBUF_BUFFER: 189 if (xbp->xb_u.xb_buffer.xbb_base) 190 xb_free(xbp->xb_u.xb_buffer.xbb_base); 191 break; 192 } 193 xbp->xb_flags &= ~XB_CLEANUP; 194} 195 196/* 197 * set the length of valid data in the current buffer to 198 * be up to the current location within the buffer 199 */ 200void 201xb_set_cur_buf_len(struct xdrbuf *xbp) 202{ 203 switch (xbp->xb_type) { 204 case XDRBUF_BUFFER: 205 xbp->xb_u.xb_buffer.xbb_len = xbp->xb_ptr - xbp->xb_u.xb_buffer.xbb_base; 206 break; 207 } 208} 209 210/* 211 * advance forward through existing data in xdrbuf 212 */ 213int 214xb_advance(struct xdrbuf *xbp, uint32_t len) 215{ 216 uint32_t tlen; 217 218 while (len) { 219 if (xbp->xb_left <= 0) 220 return (EBADRPC); 221 tlen = MIN(xbp->xb_left, len); 222 if (tlen) { 223 xbp->xb_ptr += tlen; 224 xbp->xb_left -= tlen; 225 len -= tlen; 226 } 227 } 228 return (0); 229} 230 231/* 232 * Calculate the current offset in the XDR buffer. 233 */ 234int 235xb_offset(struct xdrbuf *xbp) 236{ 237 uint32_t offset = 0; 238 239 switch (xbp->xb_type) { 240 case XDRBUF_BUFFER: 241 offset = xbp->xb_ptr - xbp->xb_u.xb_buffer.xbb_base; 242 break; 243 } 244 245 return (offset); 246} 247 248/* 249 * Seek to the given offset in the existing data in the XDR buffer. 250 */ 251int 252xb_seek(struct xdrbuf *xbp, uint32_t offset) 253{ 254 255 switch (xbp->xb_type) { 256 case XDRBUF_BUFFER: 257 xbp->xb_ptr = xbp->xb_u.xb_buffer.xbb_base + offset; 258 xbp->xb_left = xbp->xb_u.xb_buffer.xbb_len - offset; 259 break; 260 } 261 262 return (0); 263} 264 265/* 266 * allocate memory 267 */ 268void * 269xb_malloc(size_t size) 270{ 271 void *buf = NULL; 272 273#ifdef KERNEL 274 MALLOC(buf, void *, size, M_TEMP, M_WAITOK); 275#else 276 buf = malloc(size); 277#endif 278 return (buf); 279} 280/* 281 * free a chunk of memory allocated with xb_malloc() 282 */ 283void 284xb_free(void *buf) 285{ 286#ifdef KERNEL 287 FREE(buf, M_TEMP); 288#else 289 free(buf); 290#endif 291} 292 293/* 294 * Increase space available for new data in XDR buffer. 295 */ 296int 297xb_grow(struct xdrbuf *xbp) 298{ 299 char *newbuf, *oldbuf; 300 size_t newsize, oldsize; 301 302 switch (xbp->xb_type) { 303 case XDRBUF_BUFFER: 304 oldsize = xbp->xb_u.xb_buffer.xbb_size; 305 oldbuf = xbp->xb_u.xb_buffer.xbb_base; 306 newsize = oldsize + xbp->xb_growsize; 307 newbuf = xb_malloc(newsize); 308 if (newbuf == NULL) 309 return (ENOMEM); 310 if (oldbuf != NULL) { 311 bcopy(oldbuf, newbuf, oldsize); 312 xb_free(oldbuf); 313 } 314 xbp->xb_u.xb_buffer.xbb_base = newbuf; 315 xbp->xb_u.xb_buffer.xbb_size = newsize; 316 xbp->xb_ptr = newbuf + oldsize; 317 xbp->xb_left = xbp->xb_growsize; 318 break; 319 } 320 321 return (0); 322} 323 324/* 325 * xb_add_bytes() 326 * 327 * Add "count" bytes of opaque data pointed to by "buf" to the given XDR buffer. 328 */ 329int 330xb_add_bytes(struct xdrbuf *xbp, const char *buf, uint32_t count, int nopad) 331{ 332 uint32_t len, tlen; 333 int error; 334 335 len = nopad ? count : xdr_rndup(count); 336 337 /* copy in "count" bytes and zero out any pad bytes */ 338 while (len) { 339 if (xbp->xb_left <= 0) { 340 /* need more space */ 341 if ((error = xb_grow(xbp))) 342 return (error); 343 if (xbp->xb_left <= 0) 344 return (ENOMEM); 345 } 346 tlen = MIN(xbp->xb_left, len); 347 if (tlen) { 348 if (count) { 349 if (tlen > count) 350 tlen = count; 351 bcopy(buf, xbp->xb_ptr, tlen); 352 } else { 353 bzero(xbp->xb_ptr, tlen); 354 } 355 xbp->xb_ptr += tlen; 356 xbp->xb_left -= tlen; 357 len -= tlen; 358 if (count) { 359 buf += tlen; 360 count -= tlen; 361 } 362 } 363 } 364 return (0); 365} 366 367/* 368 * xb_get_bytes() 369 * 370 * Get "count" bytes of opaque data from the given XDR buffer. 371 */ 372int 373xb_get_bytes(struct xdrbuf *xbp, char *buf, uint32_t count, int nopad) 374{ 375 uint32_t len, tlen; 376 377 len = nopad ? count : xdr_rndup(count); 378 379 /* copy in "count" bytes and zero out any pad bytes */ 380 while (len) { 381 if (xbp->xb_left <= 0) 382 return (ENOMEM); 383 tlen = MIN(xbp->xb_left, len); 384 if (tlen) { 385 if (count) { 386 if (tlen > count) 387 tlen = count; 388 bcopy(xbp->xb_ptr, buf, tlen); 389 } 390 xbp->xb_ptr += tlen; 391 xbp->xb_left -= tlen; 392 len -= tlen; 393 if (count) { 394 buf += tlen; 395 count -= tlen; 396 } 397 } 398 } 399 return (0); 400} 401 402#endif /* _NFS_XDR_SUBS_FUNCS_ */ 403 404 405/* 406 * macros for building XDR data 407 */ 408 409/* finalize the data that has been added to the buffer */ 410#define xb_build_done(E, XB) \ 411 do { \ 412 if (E) break; \ 413 xb_set_cur_buf_len(XB); \ 414 } while (0) 415 416/* add a 32-bit value */ 417#define xb_add_32(E, XB, VAL) \ 418 do { \ 419 uint32_t __tmp; \ 420 if (E) break; \ 421 __tmp = txdr_unsigned(VAL); \ 422 (E) = xb_add_bytes((XB), (void*)&__tmp, XDRWORD, 0); \ 423 } while (0) 424 425/* add a 64-bit value */ 426#define xb_add_64(E, XB, VAL) \ 427 do { \ 428 uint64_t __tmp1, __tmp2; \ 429 if (E) break; \ 430 __tmp1 = (VAL); \ 431 txdr_hyper(&__tmp1, &__tmp2); \ 432 (E) = xb_add_bytes((XB), (char*)&__tmp2, 2 * XDRWORD, 0); \ 433 } while (0) 434 435/* add an array of XDR words */ 436#define xb_add_word_array(E, XB, A, LEN) \ 437 do { \ 438 uint32_t __i; \ 439 xb_add_32((E), (XB), (LEN)); \ 440 for (__i=0; __i < (uint32_t)(LEN); __i++) \ 441 xb_add_32((E), (XB), (A)[__i]); \ 442 } while (0) 443#define xb_add_bitmap(E, XB, B, LEN) xb_add_word_array((E), (XB), (B), (LEN)) 444 445/* add a file handle */ 446#define xb_add_fh(E, XB, FHP, FHLEN) \ 447 do { \ 448 xb_add_32((E), (XB), (FHLEN)); \ 449 if (E) break; \ 450 (E) = xb_add_bytes((XB), (char*)(FHP), (FHLEN), 0); \ 451 } while (0) 452 453/* add a string */ 454#define xb_add_string(E, XB, S, LEN) \ 455 do { \ 456 xb_add_32((E), (XB), (LEN)); \ 457 if (E) break; \ 458 (E) = xb_add_bytes((XB), (const char*)(S), (LEN), 0); \ 459 } while (0) 460 461 462/* 463 * macros for decoding XDR data 464 */ 465 466/* skip past data in the buffer */ 467#define xb_skip(E, XB, LEN) \ 468 do { \ 469 if (E) break; \ 470 (E) = xb_advance((XB), (LEN)); \ 471 } while (0) 472 473/* get a 32-bit value */ 474#define xb_get_32(E, XB, LVAL) \ 475 do { \ 476 uint32_t __tmp; \ 477 if (E) break; \ 478 (E) = xb_get_bytes((XB), (char*)&__tmp, XDRWORD, 0); \ 479 if (E) break; \ 480 (LVAL) = fxdr_unsigned(uint32_t, __tmp); \ 481 } while (0) 482 483/* get a 64-bit value */ 484#define xb_get_64(E, XB, LVAL) \ 485 do { \ 486 uint64_t __tmp; \ 487 if (E) break; \ 488 (E) = xb_get_bytes((XB), (char*)&__tmp, 2 * XDRWORD, 0); \ 489 if (E) break; \ 490 fxdr_hyper(&__tmp, &(LVAL)); \ 491 } while (0) 492 493/* get an array of XDR words (of a given expected/maximum length) */ 494#define xb_get_word_array(E, XB, A, LEN) \ 495 do { \ 496 uint32_t __len = 0, __i; \ 497 xb_get_32((E), (XB), __len); \ 498 if (E) break; \ 499 for (__i=0; __i < MIN(__len, (uint32_t)(LEN)); __i++) \ 500 xb_get_32((E), (XB), (A)[__i]); \ 501 if (E) break; \ 502 for (; __i < __len; __i++) \ 503 xb_skip((E), (XB), XDRWORD); \ 504 for (; __i < (uint32_t)(LEN); __i++) \ 505 (A)[__i] = 0; \ 506 (LEN) = __len; \ 507 } while (0) 508#define xb_get_bitmap(E, XB, B, LEN) xb_get_word_array((E), (XB), (B), (LEN)) 509 510#endif /* __APPLE_API_PRIVATE */ 511#endif /* _NFS_XDR_SUBS_H_ */ 512