2 * xdr.c, Generic XDR routines implementation.
4 * Copyright (C) 1986, Sun Microsystems, Inc.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are
10 * * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * * Redistributions in binary form must reproduce the above
13 * copyright notice, this list of conditions and the following
14 * disclaimer in the documentation and/or other materials
15 * provided with the distribution.
16 * * Neither the name of Sun Microsystems, Inc. nor the names of its
17 * contributors may be used to endorse or promote products derived
18 * from this software without specific prior written permission.
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24 * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
25 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
27 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
29 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
30 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 * These are the "generic" xdr routines used to serialize and de-serialize
34 * most common data items. See xdr.h for more info on the interface to
43 #include <rpc/types.h>
51 * constants specific to the xdr "protocol"
53 #define XDR_FALSE ((long) 0)
54 #define XDR_TRUE ((long) 1)
55 #define LASTUNSIGNED ((u_int) 0-1)
60 static const char xdr_zero
[BYTES_PER_XDR_UNIT
] = {0, 0, 0, 0};
63 * Free a data structure using XDR
64 * Not a filter, but a convenient utility nonetheless
67 xdr_free (xdrproc_t proc
, char *objp
)
89 xdr_int (XDR
*xdrs
, int *ip
)
92 #if INT_MAX < LONG_MAX
99 return XDR_PUTLONG (xdrs
, &l
);
102 if (!XDR_GETLONG (xdrs
, &l
))
111 #elif INT_MAX == LONG_MAX
112 return INTUSE(xdr_long
) (xdrs
, (long *) ip
);
113 #elif INT_MAX == SHRT_MAX
114 return INTUSE(xdr_short
) (xdrs
, (short *) ip
);
116 #error unexpected integer sizes in_xdr_int()
122 * XDR unsigned integers
125 xdr_u_int (XDR
*xdrs
, u_int
*up
)
127 #if UINT_MAX < ULONG_MAX
134 return XDR_PUTLONG (xdrs
, &l
);
137 if (!XDR_GETLONG (xdrs
, &l
))
141 *up
= (u_int
) (u_long
) l
;
146 #elif UINT_MAX == ULONG_MAX
147 return INTUSE(xdr_u_long
) (xdrs
, (u_long
*) up
);
148 #elif UINT_MAX == USHRT_MAX
149 return INTUSE(xdr_short
) (xdrs
, (short *) up
);
151 #error unexpected integer sizes in_xdr_u_int()
158 * The definition of xdr_long() is kept for backward
159 * compatibility. Instead xdr_int() should be used.
162 xdr_long (XDR
*xdrs
, long *lp
)
165 if (xdrs
->x_op
== XDR_ENCODE
166 && (sizeof (int32_t) == sizeof (long)
167 || (int32_t) *lp
== *lp
))
168 return XDR_PUTLONG (xdrs
, lp
);
170 if (xdrs
->x_op
== XDR_DECODE
)
171 return XDR_GETLONG (xdrs
, lp
);
173 if (xdrs
->x_op
== XDR_FREE
)
181 * XDR unsigned long integers
182 * The definition of xdr_u_long() is kept for backward
183 * compatibility. Instead xdr_u_int() should be used.
186 xdr_u_long (XDR
*xdrs
, u_long
*ulp
)
194 if (XDR_GETLONG (xdrs
, &tmp
) == FALSE
)
197 *ulp
= (uint32_t) tmp
;
202 if (sizeof (uint32_t) != sizeof (u_long
)
203 && (uint32_t) *ulp
!= *ulp
)
206 return XDR_PUTLONG (xdrs
, (long *) ulp
);
217 * same as xdr_u_hyper - open coded to save a proc call!
220 xdr_hyper (XDR
*xdrs
, quad_t
*llp
)
224 if (xdrs
->x_op
== XDR_ENCODE
)
226 t1
= (long) ((*llp
) >> 32);
228 return (XDR_PUTLONG(xdrs
, &t1
) && XDR_PUTLONG(xdrs
, &t2
));
231 if (xdrs
->x_op
== XDR_DECODE
)
233 if (!XDR_GETLONG(xdrs
, &t1
) || !XDR_GETLONG(xdrs
, &t2
))
235 *llp
= ((quad_t
) t1
) << 32;
236 *llp
|= (uint32_t) t2
;
240 if (xdrs
->x_op
== XDR_FREE
)
250 * same as xdr_hyper - open coded to save a proc call!
253 xdr_u_hyper (XDR
*xdrs
, u_quad_t
*ullp
)
257 if (xdrs
->x_op
== XDR_ENCODE
)
259 t1
= (unsigned long) ((*ullp
) >> 32);
260 t2
= (unsigned long) (*ullp
);
261 return (XDR_PUTLONG(xdrs
, &t1
) && XDR_PUTLONG(xdrs
, &t2
));
264 if (xdrs
->x_op
== XDR_DECODE
)
266 if (!XDR_GETLONG(xdrs
, &t1
) || !XDR_GETLONG(xdrs
, &t2
))
268 *ullp
= ((u_quad_t
) t1
) << 32;
269 *ullp
|= (uint32_t) t2
;
273 if (xdrs
->x_op
== XDR_FREE
)
281 xdr_longlong_t (XDR
*xdrs
, quad_t
*llp
)
283 return INTUSE(xdr_hyper
) (xdrs
, llp
);
287 xdr_u_longlong_t (XDR
*xdrs
, u_quad_t
*ullp
)
289 return INTUSE(xdr_u_hyper
) (xdrs
, ullp
);
296 xdr_short (XDR
*xdrs
, short *sp
)
304 return XDR_PUTLONG (xdrs
, &l
);
307 if (!XDR_GETLONG (xdrs
, &l
))
322 * XDR unsigned short integers
325 xdr_u_short (XDR
*xdrs
, u_short
*usp
)
333 return XDR_PUTLONG (xdrs
, &l
);
336 if (!XDR_GETLONG (xdrs
, &l
))
340 *usp
= (u_short
) (u_long
) l
;
355 xdr_char (XDR
*xdrs
, char *cp
)
360 if (!INTUSE(xdr_int
) (xdrs
, &i
))
369 * XDR an unsigned char
372 xdr_u_char (XDR
*xdrs
, u_char
*cp
)
377 if (!INTUSE(xdr_u_int
) (xdrs
, &u
))
389 xdr_bool (XDR
*xdrs
, bool_t
*bp
)
396 lb
= *bp
? XDR_TRUE
: XDR_FALSE
;
397 return XDR_PUTLONG (xdrs
, &lb
);
400 if (!XDR_GETLONG (xdrs
, &lb
))
404 *bp
= (lb
== XDR_FALSE
) ? FALSE
: TRUE
;
418 xdr_enum (XDR
*xdrs
, enum_t
*ep
)
423 }; /* used to find the size of an enum */
426 * enums are treated as ints
428 if (sizeof (enum sizecheck
) == 4)
430 #if INT_MAX < LONG_MAX
437 return XDR_PUTLONG (xdrs
, &l
);
440 if (!XDR_GETLONG (xdrs
, &l
))
451 return INTUSE(xdr_long
) (xdrs
, (long *) ep
);
454 else if (sizeof (enum sizecheck
) == sizeof (short))
456 return INTUSE(xdr_short
) (xdrs
, (short *) ep
);
467 * Allows the specification of a fixed size sequence of opaque bytes.
468 * cp points to the opaque object and cnt gives the byte length.
471 xdr_opaque (XDR
*xdrs
, caddr_t cp
, u_int cnt
)
474 static char crud
[BYTES_PER_XDR_UNIT
];
477 * if no data we are done
483 * round byte count to full xdr units
485 rndup
= cnt
% BYTES_PER_XDR_UNIT
;
487 rndup
= BYTES_PER_XDR_UNIT
- rndup
;
492 if (!XDR_GETBYTES (xdrs
, cp
, cnt
))
498 return XDR_GETBYTES (xdrs
, (caddr_t
)crud
, rndup
);
501 if (!XDR_PUTBYTES (xdrs
, cp
, cnt
))
507 return XDR_PUTBYTES (xdrs
, xdr_zero
, rndup
);
518 * *cpp is a pointer to the bytes, *sizep is the count.
519 * If *cpp is NULL maxsize bytes are allocated
522 xdr_bytes (xdrs
, cpp
, sizep
, maxsize
)
528 char *sp
= *cpp
; /* sp is the actual string pointer */
532 * first deal with the length since xdr bytes are counted
534 if (!INTUSE(xdr_u_int
) (xdrs
, sizep
))
539 if ((nodesize
> maxsize
) && (xdrs
->x_op
!= XDR_FREE
))
545 * now deal with the actual bytes
556 *cpp
= sp
= (char *) mem_alloc (nodesize
);
560 (void) __fxprintf (NULL
, "%s: %s", __func__
, _("out of memory\n"));
566 return INTUSE(xdr_opaque
) (xdrs
, sp
, nodesize
);
571 mem_free (sp
, nodesize
);
581 * Implemented here due to commonality of the object.
584 xdr_netobj (xdrs
, np
)
589 return INTUSE(xdr_bytes
) (xdrs
, &np
->n_bytes
, &np
->n_len
, MAX_NETOBJ_SZ
);
594 * XDR a discriminated union
595 * Support routine for discriminated unions.
596 * You create an array of xdrdiscrim structures, terminated with
597 * an entry with a null procedure pointer. The routine gets
598 * the discriminant value and then searches the array of xdrdiscrims
599 * looking for that value. It calls the procedure given in the xdrdiscrim
600 * to handle the discriminant. If there is no specific routine a default
601 * routine may be called.
602 * If there is no specific or default routine an error is returned.
605 xdr_union (xdrs
, dscmp
, unp
, choices
, dfault
)
607 enum_t
*dscmp
; /* enum to decide which arm to work on */
608 char *unp
; /* the union itself */
609 const struct xdr_discrim
*choices
; /* [value, xdr proc] for each arm */
610 xdrproc_t dfault
; /* default xdr routine */
615 * we deal with the discriminator; it's an enum
617 if (!INTUSE(xdr_enum
) (xdrs
, dscmp
))
624 * search choices for a value that matches the discriminator.
625 * if we find one, execute the xdr routine for that value.
627 for (; choices
->proc
!= NULL_xdrproc_t
; choices
++)
629 if (choices
->value
== dscm
)
630 return (*(choices
->proc
)) (xdrs
, unp
, LASTUNSIGNED
);
634 * no match - execute the default xdr routine if there is one
636 return ((dfault
== NULL_xdrproc_t
) ? FALSE
:
637 (*dfault
) (xdrs
, unp
, LASTUNSIGNED
));
643 * Non-portable xdr primitives.
644 * Care should be taken when moving these routines to new architectures.
649 * XDR null terminated ASCII strings
650 * xdr_string deals with "C strings" - arrays of bytes that are
651 * terminated by a NULL character. The parameter cpp references a
652 * pointer to storage; If the pointer is null, then the necessary
653 * storage is allocated. The last parameter is the max allowed length
654 * of the string as specified by a protocol.
657 xdr_string (xdrs
, cpp
, maxsize
)
662 char *sp
= *cpp
; /* sp is the actual string pointer */
667 * first deal with the length since xdr strings are counted-strings
674 return TRUE
; /* already free */
676 /* fall through... */
685 if (!INTUSE(xdr_u_int
) (xdrs
, &size
))
696 /* This means an overflow. It a bug in the caller which
697 provided a too large maxsize but nevertheless catch it
703 * now deal with the actual bytes
709 *cpp
= sp
= (char *) mem_alloc (nodesize
);
712 (void) __fxprintf (NULL
, "%s: %s", __func__
, _("out of memory\n"));
719 return INTUSE(xdr_opaque
) (xdrs
, sp
, size
);
722 mem_free (sp
, nodesize
);
731 * Wrapper for xdr_string that can be called directly from
732 * routines like clnt_call
735 xdr_wrapstring (xdrs
, cpp
)
739 if (INTUSE(xdr_string
) (xdrs
, cpp
, LASTUNSIGNED
))