8098 Some xdr_simple(3nsl) and xdr_complex(3nsl) functions can succeed for undefined...
[unleashed.git] / usr / src / lib / libnsl / rpc / xdr.c
blobdd1314046c26c0f8739823491b1386d56cc5b3cd
1 /*
2 * CDDL HEADER START
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
7 * with the License.
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]
20 * CDDL HEADER END
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
33 * California.
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
41 * xdr.
43 #include "mt.h"
44 #include <stdlib.h>
45 #include <sys/types.h>
46 #include <sys/isa_defs.h>
47 #include <syslog.h>
48 #include <stdio.h>
49 #include <stdlib.h>
50 #include <string.h>
51 #include <limits.h>
52 #include <rpc/types.h>
53 #include <rpc/xdr.h>
54 #include <inttypes.h>
55 #include <sys/sysmacros.h>
56 #include <assert.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
84 * for unit alignment
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
92 void
93 xdr_free(xdrproc_t proc, char *objp)
95 XDR x;
97 x.x_op = XDR_FREE;
98 (*proc)(&x, objp);
102 * XDR nothing
104 bool_t
105 xdr_void(void)
107 return (TRUE);
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.
116 bool_t
117 xdr_time_t(XDR *xdrs, time_t *tp)
119 int32_t i;
121 switch (xdrs->x_op) {
122 case XDR_ENCODE:
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.
128 #if defined(_LP64)
129 if (*tp > INT32_MAX)
130 *tp = INT32_MAX;
131 else if (*tp < INT32_MIN)
132 *tp = INT32_MIN;
133 #endif
134 i = (int32_t)*tp;
135 return (XDR_PUTINT32(xdrs, &i));
137 case XDR_DECODE:
138 if (!XDR_GETINT32(xdrs, &i))
139 return (FALSE);
140 *tp = (time_t)i;
141 return (TRUE);
143 case XDR_FREE:
144 return (TRUE);
146 return (FALSE);
150 * XDR integers
152 bool_t
153 xdr_int(XDR *xdrs, int *ip)
155 switch (xdrs->x_op) {
156 case XDR_ENCODE:
157 return (XDR_PUTINT32(xdrs, ip));
158 case XDR_DECODE:
159 return (XDR_GETINT32(xdrs, ip));
160 case XDR_FREE:
161 return (TRUE);
163 return (FALSE);
167 * XDR unsigned integers
169 bool_t
170 xdr_u_int(XDR *xdrs, uint_t *up)
172 switch (xdrs->x_op) {
173 case XDR_ENCODE:
174 return (XDR_PUTINT32(xdrs, (int *)up));
175 case XDR_DECODE:
176 return (XDR_GETINT32(xdrs, (int *)up));
177 case XDR_FREE:
178 return (TRUE);
180 return (FALSE);
184 * The definition of xdr_long()/xdr_u_long() is kept for backward
185 * compatibitlity.
186 * XDR long integers, same as xdr_u_long
188 bool_t
189 xdr_long(XDR *xdrs, long *lp)
191 int32_t i;
193 switch (xdrs->x_op) {
194 case XDR_ENCODE:
195 #if defined(_LP64)
196 if ((*lp > INT32_MAX) || (*lp < INT32_MIN))
197 return (FALSE);
198 #endif
199 i = (int32_t)*lp;
200 return (XDR_PUTINT32(xdrs, &i));
201 case XDR_DECODE:
202 if (!XDR_GETINT32(xdrs, &i))
203 return (FALSE);
204 *lp = (long)i;
205 return (TRUE);
206 case XDR_FREE:
207 return (TRUE);
209 return (FALSE);
213 * XDR unsigned long integers
214 * same as xdr_long
216 bool_t
217 xdr_u_long(XDR *xdrs, ulong_t *ulp)
219 uint32_t ui;
221 switch (xdrs->x_op) {
222 case XDR_ENCODE:
223 #if defined(_LP64)
224 if (*ulp > UINT32_MAX)
225 return (FALSE);
226 #endif
227 ui = (uint32_t)*ulp;
228 return (XDR_PUTINT32(xdrs, (int32_t *)&ui));
229 case XDR_DECODE:
230 if (!XDR_GETINT32(xdrs, (int32_t *)&ui))
231 return (FALSE);
232 *ulp = (ulong_t)ui;
233 return (TRUE);
234 case XDR_FREE:
235 return (TRUE);
237 return (FALSE);
241 * XDR short integers
243 bool_t
244 xdr_short(XDR *xdrs, short *sp)
246 int32_t l;
248 switch (xdrs->x_op) {
249 case XDR_ENCODE:
250 l = (int32_t)*sp;
251 return (XDR_PUTINT32(xdrs, &l));
252 case XDR_DECODE:
253 if (!XDR_GETINT32(xdrs, &l))
254 return (FALSE);
255 *sp = (short)l;
256 return (TRUE);
257 case XDR_FREE:
258 return (TRUE);
260 return (FALSE);
264 * XDR unsigned short integers
266 bool_t
267 xdr_u_short(XDR *xdrs, ushort_t *usp)
269 uint_t i;
271 switch (xdrs->x_op) {
272 case XDR_ENCODE:
273 i = (uint_t)*usp;
274 return (XDR_PUTINT32(xdrs, (int *)&i));
275 case XDR_DECODE:
276 if (!XDR_GETINT32(xdrs, (int *)&i))
277 return (FALSE);
278 *usp = (ushort_t)i;
279 return (TRUE);
280 case XDR_FREE:
281 return (TRUE);
283 return (FALSE);
288 * XDR a char
290 bool_t
291 xdr_char(XDR *xdrs, char *cp)
293 int i;
295 switch (xdrs->x_op) {
296 case XDR_ENCODE:
297 i = (*cp);
298 return (XDR_PUTINT32(xdrs, &i));
299 case XDR_DECODE:
300 if (!XDR_GETINT32(xdrs, &i))
301 return (FALSE);
302 *cp = (char)i;
303 return (TRUE);
304 case XDR_FREE:
305 return (TRUE);
307 return (FALSE);
311 * XDR an unsigned char
313 bool_t
314 xdr_u_char(XDR *xdrs, uchar_t *cp)
316 int i;
318 switch (xdrs->x_op) {
319 case XDR_ENCODE:
320 i = (*cp);
321 return (XDR_PUTINT32(xdrs, &i));
322 case XDR_DECODE:
323 if (!XDR_GETINT32(xdrs, &i))
324 return (FALSE);
325 *cp = (uchar_t)i;
326 return (TRUE);
327 case XDR_FREE:
328 return (TRUE);
330 return (FALSE);
334 * XDR booleans
336 bool_t
337 xdr_bool(XDR *xdrs, bool_t *bp)
339 int i;
341 switch (xdrs->x_op) {
342 case XDR_ENCODE:
343 i = *bp ? XDR_TRUE : XDR_FALSE;
344 return (XDR_PUTINT32(xdrs, &i));
345 case XDR_DECODE:
346 if (!XDR_GETINT32(xdrs, &i))
347 return (FALSE);
348 *bp = (i == XDR_FALSE) ? FALSE : TRUE;
349 return (TRUE);
350 case XDR_FREE:
351 return (TRUE);
353 return (FALSE);
357 * XDR enumerations
359 bool_t
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
367 /* CONSTCOND */
368 assert(sizeof (enum sizecheck) == sizeof (int32_t));
369 return (xdr_int(xdrs, (int *)ep));
373 * XDR opaque data
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.
377 bool_t
378 xdr_opaque(XDR *xdrs, caddr_t cp, const uint_t cnt)
380 uint_t rndup;
381 char crud[BYTES_PER_XDR_UNIT];
384 * round byte count to full xdr units
386 rndup = cnt % BYTES_PER_XDR_UNIT;
387 if ((int)rndup > 0)
388 rndup = BYTES_PER_XDR_UNIT - rndup;
390 switch (xdrs->x_op) {
391 case XDR_DECODE:
392 if (!XDR_GETBYTES(xdrs, cp, cnt))
393 return (FALSE);
394 if (rndup == 0)
395 return (TRUE);
396 return (XDR_GETBYTES(xdrs, crud, rndup));
397 case XDR_ENCODE:
398 if (!XDR_PUTBYTES(xdrs, cp, cnt))
399 return (FALSE);
400 if (rndup == 0)
401 return (TRUE);
402 return (XDR_PUTBYTES(xdrs, (caddr_t)&xdr_zero[0], rndup));
403 case XDR_FREE:
404 return (TRUE);
406 return (FALSE);
410 * XDR counted bytes
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";
417 bool_t
418 xdr_bytes(XDR *xdrs, char **cpp, uint_t *sizep, const uint_t maxsize)
420 char *sp = *cpp; /* sp is the actual string pointer */
421 uint_t nodesize;
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))
430 return (FALSE);
431 nodesize = *sizep;
432 if ((nodesize > maxsize) && (xdrs->x_op != XDR_FREE))
433 return (FALSE);
436 * now deal with the actual bytes
438 switch (xdrs->x_op) {
439 case XDR_DECODE:
440 if (nodesize == 0)
441 return (TRUE);
442 if (sp == NULL)
443 *cpp = sp = malloc(nodesize);
444 if (sp == NULL) {
445 (void) syslog(LOG_ERR, xdr_err, (const char *)"bytes");
446 return (FALSE);
448 /*FALLTHROUGH*/
449 case XDR_ENCODE:
450 return (xdr_opaque(xdrs, sp, nodesize));
451 case XDR_FREE:
452 if (sp != NULL) {
453 free(sp);
454 *cpp = NULL;
456 return (TRUE);
458 return (FALSE);
462 * Implemented here due to commonality of the object.
464 bool_t
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.
481 bool_t
482 xdr_union(XDR *xdrs, enum_t *dscmp, char *unp,
483 const struct xdr_discrim *choices, const xdrproc_t dfault)
485 enum_t dscm;
488 * we deal with the discriminator; it's an enum
490 if (!xdr_enum(xdrs, dscmp))
491 return (FALSE);
492 dscm = *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.
525 bool_t
526 xdr_string(XDR *xdrs, char **cpp, const uint_t maxsize)
528 char *newsp, *sp = *cpp; /* sp is the actual string pointer */
529 uint_t size, block;
530 uint64_t bytesread;
533 * first deal with the length since xdr strings are counted-strings
535 switch (xdrs->x_op) {
536 case XDR_FREE:
537 if (sp == NULL)
538 return (TRUE); /* already free */
539 /*FALLTHROUGH*/
540 case XDR_ENCODE:
541 size = (sp != NULL) ? (uint_t)strlen(sp) : 0;
542 break;
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))
550 return (FALSE);
551 if (size > maxsize)
552 return (FALSE);
555 * now deal with the actual bytes
557 switch (xdrs->x_op) {
558 case XDR_DECODE:
559 /* if buffer is already given, call xdr_opaque() directly */
560 if (sp != NULL) {
561 if (!xdr_opaque(xdrs, sp, size))
562 return (FALSE);
563 sp[size] = 0;
564 return (TRUE);
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.
575 bytesread = 0;
576 do {
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);
583 if (newsp == NULL) {
584 if (sp != NULL)
585 free(sp);
586 return (FALSE);
588 sp = newsp;
589 if (!xdr_opaque(xdrs, &sp[bytesread], block)) {
590 free(sp);
591 return (FALSE);
593 bytesread += block;
594 } while (bytesread < size);
596 sp[bytesread] = 0; /* terminate the string with a NULL */
597 *cpp = sp;
598 return (TRUE);
599 case XDR_ENCODE:
600 return (xdr_opaque(xdrs, sp, size));
601 case XDR_FREE:
602 free(sp);
603 *cpp = NULL;
604 return (TRUE);
606 return (FALSE);
609 bool_t
610 xdr_hyper(XDR *xdrs, longlong_t *hp)
612 switch (xdrs->x_op) {
613 case XDR_ENCODE:
614 #if defined(_LONG_LONG_HTOL)
615 if (XDR_PUTINT32(xdrs, (int *)hp) == TRUE)
616 /* LINTED pointer cast */
617 return (XDR_PUTINT32(xdrs, (int *)((char *)hp +
618 BYTES_PER_XDR_UNIT)));
619 #else
620 /* LINTED pointer cast */
621 if (XDR_PUTINT32(xdrs, (int *)((char *)hp +
622 BYTES_PER_XDR_UNIT)) == TRUE)
623 return (XDR_PUTINT32(xdrs, (int32_t *)hp));
624 #endif
625 return (FALSE);
626 case XDR_DECODE:
627 #if defined(_LONG_LONG_HTOL)
628 if (XDR_GETINT32(xdrs, (int *)hp) == FALSE ||
629 /* LINTED pointer cast */
630 (XDR_GETINT32(xdrs, (int *)((char *)hp +
631 BYTES_PER_XDR_UNIT)) == FALSE))
632 return (FALSE);
633 #else
634 /* LINTED pointer cast */
635 if ((XDR_GETINT32(xdrs, (int *)((char *)hp +
636 BYTES_PER_XDR_UNIT)) == FALSE) ||
637 (XDR_GETINT32(xdrs, (int *)hp) == FALSE))
638 return (FALSE);
639 #endif
640 return (TRUE);
641 case XDR_FREE:
642 return (TRUE);
644 return (FALSE);
647 bool_t
648 xdr_u_hyper(XDR *xdrs, u_longlong_t *hp)
650 return (xdr_hyper(xdrs, (longlong_t *)hp));
653 bool_t
654 xdr_longlong_t(XDR *xdrs, longlong_t *hp)
656 return (xdr_hyper(xdrs, hp));
659 bool_t
660 xdr_u_longlong_t(XDR *xdrs, u_longlong_t *hp)
662 return (xdr_hyper(xdrs, (longlong_t *)hp));
666 * Wrapper for xdr_string that can be called directly from
667 * routines like clnt_call
669 bool_t
670 xdr_wrapstring(XDR *xdrs, char **cpp)
672 return (xdr_string(xdrs, cpp, LASTUNSIGNED));