4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
24 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
25 * Use is subject to license terms.
28 /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
29 /* All Rights Reserved */
31 * Portions of this source code were derived from Berkeley
32 * 4.3 BSD under license from the Regents of the University of
37 * Generic XDR routines implementation.
39 * These are the "generic" xdr routines used to serialize and de-serialize
40 * most common data items. See xdr.h for more info on the interface to
45 #include <sys/types.h>
46 #include <sys/isa_defs.h>
52 #include <rpc/types.h>
55 #include <sys/sysmacros.h>
58 #pragma weak xdr_int64_t = xdr_hyper
59 #pragma weak xdr_uint64_t = xdr_u_hyper
60 #pragma weak xdr_int32_t = xdr_int
61 #pragma weak xdr_uint32_t = xdr_u_int
62 #pragma weak xdr_int16_t = xdr_short
63 #pragma weak xdr_uint16_t = xdr_u_short
64 #pragma weak xdr_int8_t = xdr_char
65 #pragma weak xdr_uint8_t = xdr_u_char
68 * The following routine was part of a workaround for an rpcgen
69 * that was fixed, this routine should be removed sometime.
71 #pragma weak xdr_ulonglong_t = xdr_u_longlong_t
74 * constants specific to the xdr "protocol"
76 #define XDR_FALSE ((uint_t)0)
77 #define XDR_TRUE ((uint_t)1)
78 #define LASTUNSIGNED ((uint_t)0-1)
80 /* fragment size to use when doing an xdr_string() */
81 #define FRAGMENT 65536
86 static const char xdr_zero
[BYTES_PER_XDR_UNIT
] = { 0 };
89 * Free a data structure using XDR
90 * Not a filter, but a convenient utility nonetheless
93 xdr_free(xdrproc_t proc
, char *objp
)
111 * xdr_time_t sends time_t value over the wire.
112 * Due to RPC Protocol limitation, it can only send
113 * up to 32-bit integer quantity over the wire.
117 xdr_time_t(XDR
*xdrs
, time_t *tp
)
121 switch (xdrs
->x_op
) {
124 * Check for the time overflow, when encoding it.
125 * Don't want to send OTW the time value too large to
126 * handle by the protocol.
131 else if (*tp
< INT32_MIN
)
135 return (XDR_PUTINT32(xdrs
, &i
));
138 if (!XDR_GETINT32(xdrs
, &i
))
153 xdr_int(XDR
*xdrs
, int *ip
)
155 switch (xdrs
->x_op
) {
157 return (XDR_PUTINT32(xdrs
, ip
));
159 return (XDR_GETINT32(xdrs
, ip
));
167 * XDR unsigned integers
170 xdr_u_int(XDR
*xdrs
, uint_t
*up
)
172 switch (xdrs
->x_op
) {
174 return (XDR_PUTINT32(xdrs
, (int *)up
));
176 return (XDR_GETINT32(xdrs
, (int *)up
));
184 * The definition of xdr_long()/xdr_u_long() is kept for backward
186 * XDR long integers, same as xdr_u_long
189 xdr_long(XDR
*xdrs
, long *lp
)
193 switch (xdrs
->x_op
) {
196 if ((*lp
> INT32_MAX
) || (*lp
< INT32_MIN
))
200 return (XDR_PUTINT32(xdrs
, &i
));
202 if (!XDR_GETINT32(xdrs
, &i
))
213 * XDR unsigned long integers
217 xdr_u_long(XDR
*xdrs
, ulong_t
*ulp
)
221 switch (xdrs
->x_op
) {
224 if (*ulp
> UINT32_MAX
)
228 return (XDR_PUTINT32(xdrs
, (int32_t *)&ui
));
230 if (!XDR_GETINT32(xdrs
, (int32_t *)&ui
))
244 xdr_short(XDR
*xdrs
, short *sp
)
248 switch (xdrs
->x_op
) {
251 return (XDR_PUTINT32(xdrs
, &l
));
253 if (!XDR_GETINT32(xdrs
, &l
))
264 * XDR unsigned short integers
267 xdr_u_short(XDR
*xdrs
, ushort_t
*usp
)
271 switch (xdrs
->x_op
) {
274 return (XDR_PUTINT32(xdrs
, (int *)&i
));
276 if (!XDR_GETINT32(xdrs
, (int *)&i
))
291 xdr_char(XDR
*xdrs
, char *cp
)
295 switch (xdrs
->x_op
) {
298 return (XDR_PUTINT32(xdrs
, &i
));
300 if (!XDR_GETINT32(xdrs
, &i
))
311 * XDR an unsigned char
314 xdr_u_char(XDR
*xdrs
, uchar_t
*cp
)
318 switch (xdrs
->x_op
) {
321 return (XDR_PUTINT32(xdrs
, &i
));
323 if (!XDR_GETINT32(xdrs
, &i
))
337 xdr_bool(XDR
*xdrs
, bool_t
*bp
)
341 switch (xdrs
->x_op
) {
343 i
= *bp
? XDR_TRUE
: XDR_FALSE
;
344 return (XDR_PUTINT32(xdrs
, &i
));
346 if (!XDR_GETINT32(xdrs
, &i
))
348 *bp
= (i
== XDR_FALSE
) ? FALSE
: TRUE
;
360 xdr_enum(XDR
*xdrs
, enum_t
*ep
)
362 enum sizecheck
{ SIZEVAL
}; /* used to find the size of an enum */
365 * enums are treated as ints
368 assert(sizeof (enum sizecheck
) == sizeof (int32_t));
369 return (xdr_int(xdrs
, (int *)ep
));
374 * Allows the specification of a fixed size sequence of opaque bytes.
375 * cp points to the opaque object and cnt gives the byte length.
378 xdr_opaque(XDR
*xdrs
, caddr_t cp
, const uint_t cnt
)
381 char crud
[BYTES_PER_XDR_UNIT
];
384 * round byte count to full xdr units
386 rndup
= cnt
% BYTES_PER_XDR_UNIT
;
388 rndup
= BYTES_PER_XDR_UNIT
- rndup
;
390 switch (xdrs
->x_op
) {
392 if (!XDR_GETBYTES(xdrs
, cp
, cnt
))
396 return (XDR_GETBYTES(xdrs
, crud
, rndup
));
398 if (!XDR_PUTBYTES(xdrs
, cp
, cnt
))
402 return (XDR_PUTBYTES(xdrs
, (caddr_t
)&xdr_zero
[0], rndup
));
411 * *cpp is a pointer to the bytes, *sizep is the count.
412 * If *cpp is NULL maxsize bytes are allocated
415 static const char xdr_err
[] = "xdr_%s: out of memory";
418 xdr_bytes(XDR
*xdrs
, char **cpp
, uint_t
*sizep
, const uint_t maxsize
)
420 char *sp
= *cpp
; /* sp is the actual string pointer */
424 * first deal with the length since xdr bytes are counted
425 * We decided not to use MACRO XDR_U_INT here, because the
426 * advantages here will be miniscule compared to xdr_bytes.
427 * This saved us 100 bytes in the library size.
429 if (!xdr_u_int(xdrs
, sizep
))
432 if ((nodesize
> maxsize
) && (xdrs
->x_op
!= XDR_FREE
))
436 * now deal with the actual bytes
438 switch (xdrs
->x_op
) {
443 *cpp
= sp
= malloc(nodesize
);
445 (void) syslog(LOG_ERR
, xdr_err
, (const char *)"bytes");
450 return (xdr_opaque(xdrs
, sp
, nodesize
));
462 * Implemented here due to commonality of the object.
465 xdr_netobj(XDR
*xdrs
, struct netobj
*np
)
467 return (xdr_bytes(xdrs
, &np
->n_bytes
, &np
->n_len
, MAX_NETOBJ_SZ
));
471 * XDR a descriminated union
472 * Support routine for discriminated unions.
473 * You create an array of xdrdiscrim structures, terminated with
474 * an entry with a null procedure pointer. The routine gets
475 * the discriminant value and then searches the array of xdrdiscrims
476 * looking for that value. It calls the procedure given in the xdrdiscrim
477 * to handle the discriminant. If there is no specific routine a default
478 * routine may be called.
479 * If there is no specific or default routine an error is returned.
482 xdr_union(XDR
*xdrs
, enum_t
*dscmp
, char *unp
,
483 const struct xdr_discrim
*choices
, const xdrproc_t dfault
)
488 * we deal with the discriminator; it's an enum
490 if (!xdr_enum(xdrs
, dscmp
))
495 * search choices for a value that matches the discriminator.
496 * if we find one, execute the xdr routine for that value.
498 for (; choices
->proc
!= NULL_xdrproc_t
; choices
++) {
499 if (choices
->value
== dscm
)
500 return ((*(choices
->proc
))(xdrs
, unp
, LASTUNSIGNED
));
504 * no match - execute the default xdr routine if there is one
506 return ((dfault
== NULL_xdrproc_t
) ? FALSE
:
507 (*dfault
)(xdrs
, unp
, LASTUNSIGNED
));
512 * Non-portable xdr primitives.
513 * Care should be taken when moving these routines to new architectures.
518 * XDR null terminated ASCII strings
519 * xdr_string deals with "C strings" - arrays of bytes that are
520 * terminated by a NULL character. The parameter cpp references a
521 * pointer to storage; If the pointer is null, then the necessary
522 * storage is allocated. The last parameter is the max allowed length
523 * of the string as specified by a protocol.
526 xdr_string(XDR
*xdrs
, char **cpp
, const uint_t maxsize
)
528 char *newsp
, *sp
= *cpp
; /* sp is the actual string pointer */
533 * first deal with the length since xdr strings are counted-strings
535 switch (xdrs
->x_op
) {
538 return (TRUE
); /* already free */
541 size
= (sp
!= NULL
) ? (uint_t
)strlen(sp
) : 0;
545 * We decided not to use MACRO XDR_U_INT here, because the
546 * advantages here will be miniscule compared to xdr_string.
547 * This saved us 100 bytes in the library size.
549 if (!xdr_u_int(xdrs
, &size
))
555 * now deal with the actual bytes
557 switch (xdrs
->x_op
) {
559 /* if buffer is already given, call xdr_opaque() directly */
561 if (!xdr_opaque(xdrs
, sp
, size
))
568 * We have to allocate a buffer of size 'size'. To avoid
569 * malloc()ing one huge chunk, we'll read the bytes in max
570 * FRAGMENT size blocks and keep realloc()ing. 'block' is
571 * the number of bytes to read in each xdr_opaque() and
572 * 'bytesread' is what we have already read. sp is NULL
573 * when we are in the loop for the first time.
577 block
= MIN(size
- bytesread
, FRAGMENT
);
579 * allocate enough for 'bytesread + block' bytes and
580 * one extra for the terminating NULL.
582 newsp
= realloc(sp
, bytesread
+ block
+ 1);
588 if (!xdr_opaque(xdrs
, &sp
[bytesread
], block
)) {
593 } while (bytesread
< size
);
595 sp
[bytesread
] = 0; /* terminate the string with a NULL */
599 return (xdr_opaque(xdrs
, sp
, size
));
609 xdr_hyper(XDR
*xdrs
, longlong_t
*hp
)
611 switch (xdrs
->x_op
) {
613 #if defined(_LONG_LONG_HTOL)
614 if (XDR_PUTINT32(xdrs
, (int *)hp
) == TRUE
)
615 /* LINTED pointer cast */
616 return (XDR_PUTINT32(xdrs
, (int *)((char *)hp
+
617 BYTES_PER_XDR_UNIT
)));
619 /* LINTED pointer cast */
620 if (XDR_PUTINT32(xdrs
, (int *)((char *)hp
+
621 BYTES_PER_XDR_UNIT
)) == TRUE
)
622 return (XDR_PUTINT32(xdrs
, (int32_t *)hp
));
626 #if defined(_LONG_LONG_HTOL)
627 if (XDR_GETINT32(xdrs
, (int *)hp
) == FALSE
||
628 /* LINTED pointer cast */
629 (XDR_GETINT32(xdrs
, (int *)((char *)hp
+
630 BYTES_PER_XDR_UNIT
)) == FALSE
))
633 /* LINTED pointer cast */
634 if ((XDR_GETINT32(xdrs
, (int *)((char *)hp
+
635 BYTES_PER_XDR_UNIT
)) == FALSE
) ||
636 (XDR_GETINT32(xdrs
, (int *)hp
) == FALSE
))
647 xdr_u_hyper(XDR
*xdrs
, u_longlong_t
*hp
)
649 return (xdr_hyper(xdrs
, (longlong_t
*)hp
));
653 xdr_longlong_t(XDR
*xdrs
, longlong_t
*hp
)
655 return (xdr_hyper(xdrs
, hp
));
659 xdr_u_longlong_t(XDR
*xdrs
, u_longlong_t
*hp
)
661 return (xdr_hyper(xdrs
, (longlong_t
*)hp
));
665 * Wrapper for xdr_string that can be called directly from
666 * routines like clnt_call
669 xdr_wrapstring(XDR
*xdrs
, char **cpp
)
671 return (xdr_string(xdrs
, cpp
, LASTUNSIGNED
));