Patrick Welche <prlw1@cam.ac.uk>
[netbsd-mini2440.git] / external / cddl / osnet / dist / uts / common / rpc / xdr.c
blob8514f67300bb7b304dc2f8126e2780eee63aa340
1 /*
2 * CDDL HEADER START
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
19 * CDDL HEADER END
22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
26 /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
27 /* All Rights Reserved */
30 * Portions of this source code were derived from Berkeley 4.3 BSD
31 * under license from the Regents of the University of California.
35 * xdr.c, generic XDR routines implementation.
36 * These are the "generic" xdr routines used to serialize and de-serialize
37 * most common data items. See xdr.h for more info on the interface to
38 * xdr.
41 #include <sys/param.h>
42 #include <sys/cmn_err.h>
43 #include <sys/types.h>
44 #include <sys/systm.h>
46 #include <rpc/types.h>
47 #include <rpc/xdr.h>
48 #include <sys/isa_defs.h>
50 #pragma weak xdr_int32_t = xdr_int
51 #pragma weak xdr_uint32_t = xdr_u_int
52 #pragma weak xdr_int64_t = xdr_longlong_t
53 #pragma weak xdr_uint64_t = xdr_u_longlong_t
55 #if !defined(_BIG_ENDIAN) && !defined(_LITTLE_ENDIAN)
56 #error "Exactly one of _BIG_ENDIAN or _LITTLE_ENDIAN must be defined"
57 #elif defined(_BIG_ENDIAN) && defined(_LITTLE_ENDIAN)
58 #error "Only one of _BIG_ENDIAN or _LITTLE_ENDIAN may be defined"
59 #endif
62 * constants specific to the xdr "protocol"
64 #define XDR_FALSE ((int32_t)0)
65 #define XDR_TRUE ((int32_t)1)
66 #define LASTUNSIGNED ((uint_t)0-1)
69 * for unit alignment
71 static char xdr_zero[BYTES_PER_XDR_UNIT] = { 0, 0, 0, 0 };
74 * Free a data structure using XDR
75 * Not a filter, but a convenient utility nonetheless
77 void
78 xdr_free(xdrproc_t proc, char *objp)
80 XDR x;
82 x.x_op = XDR_FREE;
83 (*proc)(&x, objp);
87 * XDR nothing
89 bool_t
90 xdr_void(void)
92 return (TRUE);
96 * XDR integers
98 * PSARC 2003/523 Contract Private Interface
99 * xdr_int
100 * Changes must be reviewed by Solaris File Sharing
101 * Changes must be communicated to contract-2003-523@sun.com
103 bool_t
104 xdr_int(XDR *xdrs, int *ip)
106 if (xdrs->x_op == XDR_ENCODE)
107 return (XDR_PUTINT32(xdrs, ip));
109 if (xdrs->x_op == XDR_DECODE)
110 return (XDR_GETINT32(xdrs, ip));
112 if (xdrs->x_op == XDR_FREE)
113 return (TRUE);
115 return (FALSE);
119 * XDR unsigned integers
121 * PSARC 2003/523 Contract Private Interface
122 * xdr_u_int
123 * Changes must be reviewed by Solaris File Sharing
124 * Changes must be communicated to contract-2003-523@sun.com
126 bool_t
127 xdr_u_int(XDR *xdrs, uint_t *up)
129 if (xdrs->x_op == XDR_ENCODE)
130 return (XDR_PUTINT32(xdrs, (int32_t *)up));
132 if (xdrs->x_op == XDR_DECODE)
133 return (XDR_GETINT32(xdrs, (int32_t *)up));
135 if (xdrs->x_op == XDR_FREE)
136 return (TRUE);
138 return (FALSE);
142 #if defined(_ILP32)
144 * xdr_long and xdr_u_long for binary compatability on ILP32 kernels.
146 * No prototypes since new code should not be using these interfaces.
148 bool_t
149 xdr_long(XDR *xdrs, long *ip)
151 return (xdr_int(xdrs, (int *)ip));
154 bool_t
155 xdr_u_long(XDR *xdrs, unsigned long *up)
157 return (xdr_u_int(xdrs, (uint_t *)up));
159 #endif /* _ILP32 */
163 * XDR long long integers
165 bool_t
166 xdr_longlong_t(XDR *xdrs, longlong_t *hp)
168 if (xdrs->x_op == XDR_ENCODE) {
169 #if defined(_LITTLE_ENDIAN)
170 if (XDR_PUTINT32(xdrs, (int32_t *)((char *)hp +
171 BYTES_PER_XDR_UNIT)) == TRUE) {
172 return (XDR_PUTINT32(xdrs, (int32_t *)hp));
174 #elif defined(_BIG_ENDIAN)
175 if (XDR_PUTINT32(xdrs, (int32_t *)hp) == TRUE) {
176 return (XDR_PUTINT32(xdrs, (int32_t *)((char *)hp +
177 BYTES_PER_XDR_UNIT)));
179 #endif
180 return (FALSE);
183 if (xdrs->x_op == XDR_DECODE) {
184 #if defined(_LITTLE_ENDIAN)
185 if (XDR_GETINT32(xdrs, (int32_t *)((char *)hp +
186 BYTES_PER_XDR_UNIT)) == TRUE) {
187 return (XDR_GETINT32(xdrs, (int32_t *)hp));
189 #elif defined(_BIG_ENDIAN)
190 if (XDR_GETINT32(xdrs, (int32_t *)hp) == TRUE) {
191 return (XDR_GETINT32(xdrs, (int32_t *)((char *)hp +
192 BYTES_PER_XDR_UNIT)));
194 #endif
195 return (FALSE);
197 return (TRUE);
201 * XDR unsigned long long integers
203 bool_t
204 xdr_u_longlong_t(XDR *xdrs, u_longlong_t *hp)
207 if (xdrs->x_op == XDR_ENCODE) {
208 #if defined(_LITTLE_ENDIAN)
209 if (XDR_PUTINT32(xdrs, (int32_t *)((char *)hp +
210 BYTES_PER_XDR_UNIT)) == TRUE) {
211 return (XDR_PUTINT32(xdrs, (int32_t *)hp));
213 #elif defined(_BIG_ENDIAN)
214 if (XDR_PUTINT32(xdrs, (int32_t *)hp) == TRUE) {
215 return (XDR_PUTINT32(xdrs, (int32_t *)((char *)hp +
216 BYTES_PER_XDR_UNIT)));
218 #endif
219 return (FALSE);
222 if (xdrs->x_op == XDR_DECODE) {
223 #if defined(_LITTLE_ENDIAN)
224 if (XDR_GETINT32(xdrs, (int32_t *)((char *)hp +
225 BYTES_PER_XDR_UNIT)) == TRUE) {
226 return (XDR_GETINT32(xdrs, (int32_t *)hp));
228 #elif defined(_BIG_ENDIAN)
229 if (XDR_GETINT32(xdrs, (int32_t *)hp) == TRUE) {
230 return (XDR_GETINT32(xdrs, (int32_t *)((char *)hp +
231 BYTES_PER_XDR_UNIT)));
233 #endif
234 return (FALSE);
236 return (TRUE);
240 * XDR short integers
242 bool_t
243 xdr_short(XDR *xdrs, short *sp)
245 int32_t l;
247 switch (xdrs->x_op) {
249 case XDR_ENCODE:
250 l = (int32_t)*sp;
251 return (XDR_PUTINT32(xdrs, &l));
253 case XDR_DECODE:
254 if (!XDR_GETINT32(xdrs, &l))
255 return (FALSE);
256 *sp = (short)l;
257 return (TRUE);
259 case XDR_FREE:
260 return (TRUE);
262 return (FALSE);
266 * XDR unsigned short integers
268 bool_t
269 xdr_u_short(XDR *xdrs, ushort_t *usp)
271 uint32_t l;
273 switch (xdrs->x_op) {
275 case XDR_ENCODE:
276 l = (uint32_t)*usp;
277 return (XDR_PUTINT32(xdrs, (int32_t *)&l));
279 case XDR_DECODE:
280 if (!XDR_GETINT32(xdrs, (int32_t *)&l)) {
281 return (FALSE);
283 *usp = (ushort_t)l;
284 return (TRUE);
286 case XDR_FREE:
287 return (TRUE);
289 return (FALSE);
294 * XDR a char
296 bool_t
297 xdr_char(XDR *xdrs, char *cp)
299 int i;
301 i = (*cp);
302 if (!xdr_int(xdrs, &i)) {
303 return (FALSE);
305 *cp = (char)i;
306 return (TRUE);
310 * XDR booleans
312 * PSARC 2003/523 Contract Private Interface
313 * xdr_bool
314 * Changes must be reviewed by Solaris File Sharing
315 * Changes must be communicated to contract-2003-523@sun.com
317 bool_t
318 xdr_bool(XDR *xdrs, bool_t *bp)
320 int32_t i32b;
322 switch (xdrs->x_op) {
324 case XDR_ENCODE:
325 i32b = *bp ? XDR_TRUE : XDR_FALSE;
326 return (XDR_PUTINT32(xdrs, &i32b));
328 case XDR_DECODE:
329 if (!XDR_GETINT32(xdrs, &i32b)) {
330 return (FALSE);
332 *bp = (i32b == XDR_FALSE) ? FALSE : TRUE;
333 return (TRUE);
335 case XDR_FREE:
336 return (TRUE);
338 return (FALSE);
342 * XDR enumerations
344 * PSARC 2003/523 Contract Private Interface
345 * xdr_enum
346 * Changes must be reviewed by Solaris File Sharing
347 * Changes must be communicated to contract-2003-523@sun.com
349 #ifndef lint
350 enum sizecheck { SIZEVAL } sizecheckvar; /* used to find the size of */
351 /* an enum */
352 #endif
353 bool_t
354 xdr_enum(XDR *xdrs, enum_t *ep)
356 #ifndef lint
358 * enums are treated as ints
360 if (sizeof (sizecheckvar) == sizeof (int32_t)) {
361 return (xdr_int(xdrs, (int32_t *)ep));
362 } else if (sizeof (sizecheckvar) == sizeof (short)) {
363 return (xdr_short(xdrs, (short *)ep));
364 } else {
365 return (FALSE);
367 #else
368 (void) (xdr_short(xdrs, (short *)ep));
369 return (xdr_int(xdrs, (int32_t *)ep));
370 #endif
374 * XDR opaque data
375 * Allows the specification of a fixed size sequence of opaque bytes.
376 * cp points to the opaque object and cnt gives the byte length.
378 * PSARC 2003/523 Contract Private Interface
379 * xdr_opaque
380 * Changes must be reviewed by Solaris File Sharing
381 * Changes must be communicated to contract-2003-523@sun.com
383 bool_t
384 xdr_opaque(XDR *xdrs, caddr_t cp, const uint_t cnt)
386 uint_t rndup;
387 static char crud[BYTES_PER_XDR_UNIT];
390 * if no data we are done
392 if (cnt == 0)
393 return (TRUE);
396 * round byte count to full xdr units
398 rndup = cnt % BYTES_PER_XDR_UNIT;
399 if (rndup != 0)
400 rndup = BYTES_PER_XDR_UNIT - rndup;
402 if (xdrs->x_op == XDR_DECODE) {
403 if (!XDR_GETBYTES(xdrs, cp, cnt)) {
404 return (FALSE);
406 if (rndup == 0)
407 return (TRUE);
408 return (XDR_GETBYTES(xdrs, (caddr_t)crud, rndup));
411 if (xdrs->x_op == XDR_ENCODE) {
412 if (!XDR_PUTBYTES(xdrs, cp, cnt)) {
413 return (FALSE);
415 if (rndup == 0)
416 return (TRUE);
417 return (XDR_PUTBYTES(xdrs, xdr_zero, rndup));
420 if (xdrs->x_op == XDR_FREE)
421 return (TRUE);
423 return (FALSE);
427 * XDR counted bytes
428 * *cpp is a pointer to the bytes, *sizep is the count.
429 * If *cpp is NULL maxsize bytes are allocated
431 * PSARC 2003/523 Contract Private Interface
432 * xdr_bytes
433 * Changes must be reviewed by Solaris File Sharing
434 * Changes must be communicated to contract-2003-523@sun.com
436 bool_t
437 xdr_bytes(XDR *xdrs, char **cpp, uint_t *sizep, const uint_t maxsize)
439 char *sp = *cpp; /* sp is the actual string pointer */
440 uint_t nodesize;
443 * first deal with the length since xdr bytes are counted
445 if (!xdr_u_int(xdrs, sizep)) {
446 return (FALSE);
448 nodesize = *sizep;
449 if ((nodesize > maxsize) && (xdrs->x_op != XDR_FREE)) {
450 return (FALSE);
454 * now deal with the actual bytes
456 switch (xdrs->x_op) {
457 case XDR_DECODE:
458 if (nodesize == 0)
459 return (TRUE);
460 if (sp == NULL)
461 *cpp = sp = (char *)mem_alloc(nodesize);
462 /* FALLTHROUGH */
464 case XDR_ENCODE:
465 return (xdr_opaque(xdrs, sp, nodesize));
467 case XDR_FREE:
468 if (sp != NULL) {
469 mem_free(sp, nodesize);
470 *cpp = NULL;
472 return (TRUE);
474 return (FALSE);
478 * Implemented here due to commonality of the object.
480 bool_t
481 xdr_netobj(XDR *xdrs, struct netobj *np)
483 return (xdr_bytes(xdrs, &np->n_bytes, &np->n_len, MAX_NETOBJ_SZ));
487 * XDR a descriminated union
488 * Support routine for discriminated unions.
489 * You create an array of xdrdiscrim structures, terminated with
490 * an entry with a null procedure pointer. The routine gets
491 * the discriminant value and then searches the array of xdrdiscrims
492 * looking for that value. It calls the procedure given in the xdrdiscrim
493 * to handle the discriminant. If there is no specific routine a default
494 * routine may be called.
495 * If there is no specific or default routine an error is returned.
497 bool_t
498 xdr_union(XDR *xdrs, enum_t *dscmp, char *unp,
499 const struct xdr_discrim *choices, const xdrproc_t dfault)
501 enum_t dscm;
504 * we deal with the discriminator; it's an enum
506 if (!xdr_enum(xdrs, dscmp)) {
507 return (FALSE);
509 dscm = *dscmp;
512 * search choices for a value that matches the discriminator.
513 * if we find one, execute the xdr routine for that value.
515 for (; choices->proc != NULL_xdrproc_t; choices++) {
516 if (choices->value == dscm)
517 return ((*(choices->proc))(xdrs, unp, LASTUNSIGNED));
521 * no match - execute the default xdr routine if there is one
523 return ((dfault == NULL_xdrproc_t) ? FALSE :
524 (*dfault)(xdrs, unp, LASTUNSIGNED));
529 * Non-portable xdr primitives.
530 * Care should be taken when moving these routines to new architectures.
535 * XDR null terminated ASCII strings
536 * xdr_string deals with "C strings" - arrays of bytes that are
537 * terminated by a NULL character. The parameter cpp references a
538 * pointer to storage; If the pointer is null, then the necessary
539 * storage is allocated. The last parameter is the max allowed length
540 * of the string as specified by a protocol.
542 bool_t
543 xdr_string(XDR *xdrs, char **cpp, const uint_t maxsize)
545 char *sp = *cpp; /* sp is the actual string pointer */
546 uint_t size;
547 uint_t nodesize;
550 * first deal with the length since xdr strings are counted-strings
552 switch (xdrs->x_op) {
553 case XDR_FREE:
554 if (sp == NULL)
555 return (TRUE); /* already free */
556 /* FALLTHROUGH */
557 case XDR_ENCODE:
558 size = (sp != NULL) ? (uint_t)strlen(sp) : 0;
559 break;
560 case XDR_DECODE:
561 break;
563 if (!xdr_u_int(xdrs, &size)) {
564 return (FALSE);
566 if (size > maxsize) {
567 return (FALSE);
569 nodesize = size + 1;
572 * now deal with the actual bytes
574 switch (xdrs->x_op) {
575 case XDR_DECODE:
576 if (nodesize == 0)
577 return (TRUE);
578 if (sp == NULL)
579 sp = (char *)mem_alloc(nodesize);
580 sp[size] = 0;
581 if (!xdr_opaque(xdrs, sp, size)) {
583 * free up memory if allocated here
585 if (*cpp == NULL) {
586 mem_free(sp, nodesize);
588 return (FALSE);
590 if (strlen(sp) != size) {
591 if (*cpp == NULL) {
592 mem_free(sp, nodesize);
594 return (FALSE);
596 *cpp = sp;
597 return (TRUE);
599 case XDR_ENCODE:
600 return (xdr_opaque(xdrs, sp, size));
602 case XDR_FREE:
603 mem_free(sp, nodesize);
604 *cpp = NULL;
605 return (TRUE);
607 return (FALSE);
611 * Wrapper for xdr_string that can be called directly from
612 * routines like clnt_call
614 bool_t
615 xdr_wrapstring(XDR *xdrs, char **cpp)
617 if (xdr_string(xdrs, cpp, LASTUNSIGNED))
618 return (TRUE);
619 return (FALSE);