1 /* @(#)xdr.c 2.1 88/07/29 4.0 RPCSRC */
2 /*
3 * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
4 * unrestricted use provided that this legend is included on all tape
5 * media and as a part of the software program in whole or part. Users
6 * may copy or modify Sun RPC without charge, but are not authorized
7 * to license or distribute it to anyone else except as part of a product or
8 * program developed by the user.
9 *
10 * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
11 * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
12 * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
13 *
14 * Sun RPC is provided with no support and without any obligation on the
15 * part of Sun Microsystems, Inc. to assist in its use, correction,
16 * modification or enhancement.
17 *
18 * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
19 * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
20 * OR ANY PART THEREOF.
21 *
22 * In no event will Sun Microsystems, Inc. be liable for any lost revenue
23 * or profits or other special, indirect and consequential damages, even if
24 * Sun has been advised of the possibility of such damages.
25 *
26 * Sun Microsystems, Inc.
27 * 2550 Garcia Avenue
28 * Mountain View, California 94043
29 */
30 #if 0
31 static char sccsid[] = "@(#)xdr.c 1.35 87/08/12";
32 #endif
33
34 /*
35 * xdr.c, Generic XDR routines implementation.
36 *
37 * Copyright (C) 1986, Sun Microsystems, Inc.
38 *
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.
42 */
43
44 #include <stdio.h>
45 #include <limits.h>
46 #include <string.h>
47 #include <libintl.h>
48
49 #include <rpc/types.h>
50 #include <rpc/xdr.h>
51
52 /*
53 * constants specific to the xdr "protocol"
54 */
55 #define XDR_FALSE ((long) 0)
56 #define XDR_TRUE ((long) 1)
57 #define LASTUNSIGNED ((u_int) 0-1)
58
59 /*
60 * for unit alignment
61 */
62 static const char xdr_zero[BYTES_PER_XDR_UNIT] = {0, 0, 0, 0};
63
64 /*
65 * Free a data structure using XDR
66 * Not a filter, but a convenient utility nonetheless
67 */
68 void
xdr_free(xdrproc_t proc,char * objp)69 xdr_free (xdrproc_t proc, char *objp)
70 {
71 XDR x;
72
73 x.x_op = XDR_FREE;
74 (*proc) (&x, objp);
75 }
76
77 /*
78 * XDR nothing
79 */
80 bool_t
xdr_void(void)81 xdr_void (void)
82 {
83 return TRUE;
84 }
libc_hidden_def(xdr_void)85 libc_hidden_def(xdr_void)
86
87 /*
88 * XDR long integers
89 * The definition of xdr_long() is kept for backward
90 * compatibility. Instead xdr_int() should be used.
91 */
92 bool_t
93 xdr_long (XDR *xdrs, long *lp)
94 {
95 if (xdrs->x_op == XDR_ENCODE
96 && (sizeof (int32_t) == sizeof (long)
97 || (int32_t) *lp == *lp))
98 return XDR_PUTLONG (xdrs, lp);
99
100 if (xdrs->x_op == XDR_DECODE)
101 return XDR_GETLONG (xdrs, lp);
102
103 if (xdrs->x_op == XDR_FREE)
104 return TRUE;
105
106 return FALSE;
107 }
libc_hidden_def(xdr_long)108 libc_hidden_def(xdr_long)
109
110 /*
111 * XDR short integers
112 */
113 bool_t
114 xdr_short (XDR *xdrs, short *sp)
115 {
116 long l;
117
118 switch (xdrs->x_op)
119 {
120 case XDR_ENCODE:
121 l = (long) *sp;
122 return XDR_PUTLONG (xdrs, &l);
123
124 case XDR_DECODE:
125 if (!XDR_GETLONG (xdrs, &l))
126 {
127 return FALSE;
128 }
129 *sp = (short) l;
130 return TRUE;
131
132 case XDR_FREE:
133 return TRUE;
134 }
135 return FALSE;
136 }
libc_hidden_def(xdr_short)137 libc_hidden_def(xdr_short)
138
139 /*
140 * XDR integers
141 */
142 bool_t
143 xdr_int (XDR *xdrs, int *ip)
144 {
145
146 #if INT_MAX < LONG_MAX
147 long l;
148
149 switch (xdrs->x_op)
150 {
151 case XDR_ENCODE:
152 l = (long) *ip;
153 return XDR_PUTLONG (xdrs, &l);
154
155 case XDR_DECODE:
156 if (!XDR_GETLONG (xdrs, &l))
157 {
158 return FALSE;
159 }
160 *ip = (int) l;
161 case XDR_FREE:
162 return TRUE;
163 }
164 return FALSE;
165 #elif INT_MAX == LONG_MAX
166 return xdr_long (xdrs, (long *) ip);
167 #elif INT_MAX == SHRT_MAX
168 return xdr_short (xdrs, (short *) ip);
169 #else
170 #error unexpected integer sizes in xdr_int()
171 #endif
172 }
libc_hidden_def(xdr_int)173 libc_hidden_def(xdr_int)
174
175 /*
176 * XDR unsigned long integers
177 * The definition of xdr_u_long() is kept for backward
178 * compatibility. Instead xdr_u_int() should be used.
179 */
180 bool_t
181 xdr_u_long (XDR *xdrs, u_long *ulp)
182 {
183 switch (xdrs->x_op)
184 {
185 case XDR_DECODE:
186 {
187 long int tmp;
188
189 if (XDR_GETLONG (xdrs, &tmp) == FALSE)
190 return FALSE;
191
192 *ulp = (uint32_t) tmp;
193 return TRUE;
194 }
195
196 case XDR_ENCODE:
197 if (sizeof (uint32_t) != sizeof (u_long)
198 && (uint32_t) *ulp != *ulp)
199 return FALSE;
200
201 return XDR_PUTLONG (xdrs, (long *) ulp);
202
203 case XDR_FREE:
204 return TRUE;
205 }
206 return FALSE;
207 }
libc_hidden_def(xdr_u_long)208 libc_hidden_def(xdr_u_long)
209
210 /*
211 * XDR unsigned integers
212 */
213 bool_t
214 xdr_u_int (XDR *xdrs, u_int *up)
215 {
216 #if UINT_MAX < ULONG_MAX
217 u_long l;
218
219 switch (xdrs->x_op)
220 {
221 case XDR_ENCODE:
222 l = (u_long) * up;
223 return XDR_PUTLONG (xdrs, (long *) &l);
224
225 case XDR_DECODE:
226 if (!XDR_GETLONG (xdrs, (long *) &l))
227 {
228 return FALSE;
229 }
230 *up = (u_int) l;
231 case XDR_FREE:
232 return TRUE;
233 }
234 return FALSE;
235 #elif UINT_MAX == ULONG_MAX
236 return xdr_u_long (xdrs, (u_long *) up);
237 #elif UINT_MAX == USHRT_MAX
238 return xdr_short (xdrs, (short *) up);
239 #else
240 #error unexpected integer sizes in xdr_u_int()
241 #endif
242 }
libc_hidden_def(xdr_u_int)243 libc_hidden_def(xdr_u_int)
244
245 /*
246 * XDR hyper integers
247 * same as xdr_u_hyper - open coded to save a proc call!
248 */
249 bool_t
250 xdr_hyper (XDR *xdrs, quad_t *llp)
251 {
252 long t1;
253 unsigned long t2;
254
255 if (xdrs->x_op == XDR_ENCODE)
256 {
257 t1 = (long) ((*llp) >> 32);
258 t2 = (long) (*llp);
259 return (XDR_PUTLONG(xdrs, &t1) && XDR_PUTLONG(xdrs, (long *) &t2));
260 }
261
262 if (xdrs->x_op == XDR_DECODE)
263 {
264 if (!XDR_GETLONG(xdrs, &t1) || !XDR_GETLONG(xdrs, (long *) &t2))
265 return FALSE;
266 /* t2 must be unsigned for this to work */
267 *llp = ((quad_t) t1) << 32;
268 *llp |= t2;
269 return TRUE;
270 }
271
272 if (xdrs->x_op == XDR_FREE)
273 return TRUE;
274
275 return FALSE;
276 }
libc_hidden_def(xdr_hyper)277 libc_hidden_def(xdr_hyper)
278
279
280 /*
281 * XDR hyper integers
282 * same as xdr_hyper - open coded to save a proc call!
283 */
284 bool_t
285 xdr_u_hyper (XDR *xdrs, u_quad_t *ullp)
286 {
287 unsigned long t1;
288 unsigned long t2;
289
290 if (xdrs->x_op == XDR_ENCODE)
291 {
292 t1 = (unsigned long) ((*ullp) >> 32);
293 t2 = (unsigned long) (*ullp);
294 return (XDR_PUTLONG(xdrs, (long *) &t1) && XDR_PUTLONG(xdrs, (long *) &t2));
295 }
296
297 if (xdrs->x_op == XDR_DECODE)
298 {
299 if (!XDR_GETLONG(xdrs, (long *) &t1) || !XDR_GETLONG(xdrs, (long *) &t2))
300 return FALSE;
301 *ullp = ((u_quad_t) t1) << 32;
302 *ullp |= t2;
303 return TRUE;
304 }
305
306 if (xdrs->x_op == XDR_FREE)
307 return TRUE;
308
309 return FALSE;
310 }
libc_hidden_def(xdr_u_hyper)311 libc_hidden_def(xdr_u_hyper)
312
313 bool_t
314 xdr_longlong_t (XDR *xdrs, quad_t *llp)
315 {
316 return xdr_hyper (xdrs, llp);
317 }
318
319 bool_t
xdr_u_longlong_t(XDR * xdrs,u_quad_t * ullp)320 xdr_u_longlong_t (XDR *xdrs, u_quad_t *ullp)
321 {
322 return xdr_u_hyper (xdrs, ullp);
323 }
324
325 /*
326 * XDR unsigned short integers
327 */
328 bool_t
xdr_u_short(XDR * xdrs,u_short * usp)329 xdr_u_short (XDR *xdrs, u_short *usp)
330 {
331 u_long l;
332
333 switch (xdrs->x_op)
334 {
335 case XDR_ENCODE:
336 l = (u_long) * usp;
337 return XDR_PUTLONG (xdrs, (long *) &l);
338
339 case XDR_DECODE:
340 if (!XDR_GETLONG (xdrs, (long *) &l))
341 {
342 return FALSE;
343 }
344 *usp = (u_short) l;
345 return TRUE;
346
347 case XDR_FREE:
348 return TRUE;
349 }
350 return FALSE;
351 }
libc_hidden_def(xdr_u_short)352 libc_hidden_def(xdr_u_short)
353
354
355 /*
356 * XDR a char
357 */
358 bool_t
359 xdr_char (XDR *xdrs, char *cp)
360 {
361 int i;
362
363 i = (*cp);
364 if (!xdr_int (xdrs, &i))
365 {
366 return FALSE;
367 }
368 *cp = i;
369 return TRUE;
370 }
371
372 /*
373 * XDR an unsigned char
374 */
375 bool_t
xdr_u_char(XDR * xdrs,u_char * cp)376 xdr_u_char (XDR *xdrs, u_char *cp)
377 {
378 u_int u;
379
380 u = (*cp);
381 if (!xdr_u_int (xdrs, &u))
382 {
383 return FALSE;
384 }
385 *cp = u;
386 return TRUE;
387 }
388
389 /*
390 * XDR booleans
391 */
392 bool_t
xdr_bool(XDR * xdrs,bool_t * bp)393 xdr_bool (XDR *xdrs, bool_t *bp)
394 {
395 long lb;
396
397 switch (xdrs->x_op)
398 {
399 case XDR_ENCODE:
400 lb = *bp ? XDR_TRUE : XDR_FALSE;
401 return XDR_PUTLONG (xdrs, &lb);
402
403 case XDR_DECODE:
404 if (!XDR_GETLONG (xdrs, &lb))
405 {
406 return FALSE;
407 }
408 *bp = (lb == XDR_FALSE) ? FALSE : TRUE;
409 return TRUE;
410
411 case XDR_FREE:
412 return TRUE;
413 }
414 return FALSE;
415 }
libc_hidden_def(xdr_bool)416 libc_hidden_def(xdr_bool)
417
418 /*
419 * XDR enumerations
420 */
421 bool_t
422 xdr_enum (XDR *xdrs, enum_t *ep)
423 {
424 enum sizecheck
425 {
426 SIZEVAL
427 }; /* used to find the size of an enum */
428
429 /*
430 * enums are treated as ints
431 */
432 if (sizeof (enum sizecheck) == 4)
433 {
434 #if INT_MAX < LONG_MAX
435 long l;
436
437 switch (xdrs->x_op)
438 {
439 case XDR_ENCODE:
440 l = *ep;
441 return XDR_PUTLONG (xdrs, &l);
442
443 case XDR_DECODE:
444 if (!XDR_GETLONG (xdrs, &l))
445 {
446 return FALSE;
447 }
448 *ep = l;
449 case XDR_FREE:
450 return TRUE;
451
452 }
453 return FALSE;
454 #else
455 return xdr_long (xdrs, (long *) ep);
456 #endif
457 }
458 else if (sizeof (enum sizecheck) == sizeof (short))
459 {
460 return xdr_short (xdrs, (short *) ep);
461 }
462 else
463 {
464 return FALSE;
465 }
466 }
libc_hidden_def(xdr_enum)467 libc_hidden_def(xdr_enum)
468
469 /*
470 * XDR opaque data
471 * Allows the specification of a fixed size sequence of opaque bytes.
472 * cp points to the opaque object and cnt gives the byte length.
473 */
474 bool_t
475 xdr_opaque (XDR *xdrs, caddr_t cp, u_int cnt)
476 {
477 u_int rndup;
478 static char crud[BYTES_PER_XDR_UNIT];
479
480 /*
481 * if no data we are done
482 */
483 if (cnt == 0)
484 return TRUE;
485
486 /*
487 * round byte count to full xdr units
488 */
489 rndup = cnt % BYTES_PER_XDR_UNIT;
490 if (rndup > 0)
491 rndup = BYTES_PER_XDR_UNIT - rndup;
492
493 switch (xdrs->x_op)
494 {
495 case XDR_DECODE:
496 if (!XDR_GETBYTES (xdrs, cp, cnt))
497 {
498 return FALSE;
499 }
500 if (rndup == 0)
501 return TRUE;
502 return XDR_GETBYTES (xdrs, (caddr_t)crud, rndup);
503
504 case XDR_ENCODE:
505 if (!XDR_PUTBYTES (xdrs, cp, cnt))
506 {
507 return FALSE;
508 }
509 if (rndup == 0)
510 return TRUE;
511 return XDR_PUTBYTES (xdrs, xdr_zero, rndup);
512
513 case XDR_FREE:
514 return TRUE;
515 }
516 return FALSE;
517 }
libc_hidden_def(xdr_opaque)518 libc_hidden_def(xdr_opaque)
519
520 /*
521 * XDR counted bytes
522 * *cpp is a pointer to the bytes, *sizep is the count.
523 * If *cpp is NULL maxsize bytes are allocated
524 */
525 bool_t
526 xdr_bytes (XDR *xdrs, char **cpp, u_int *sizep, u_int maxsize)
527 {
528 char *sp = *cpp; /* sp is the actual string pointer */
529 u_int nodesize;
530
531 /*
532 * first deal with the length since xdr bytes are counted
533 */
534 if (!xdr_u_int (xdrs, sizep))
535 {
536 return FALSE;
537 }
538 nodesize = *sizep;
539 if ((nodesize > maxsize) && (xdrs->x_op != XDR_FREE))
540 {
541 return FALSE;
542 }
543
544 /*
545 * now deal with the actual bytes
546 */
547 switch (xdrs->x_op)
548 {
549 case XDR_DECODE:
550 if (nodesize == 0)
551 {
552 return TRUE;
553 }
554 if (sp == NULL)
555 {
556 *cpp = sp = (char *) mem_alloc (nodesize);
557 }
558 if (sp == NULL)
559 {
560 (void) fputs (_("xdr_bytes: out of memory\n"), stderr);
561 return FALSE;
562 }
563 /* fall into ... */
564
565 case XDR_ENCODE:
566 return xdr_opaque (xdrs, sp, nodesize);
567
568 case XDR_FREE:
569 if (sp != NULL)
570 {
571 mem_free (sp, nodesize);
572 *cpp = NULL;
573 }
574 return TRUE;
575 }
576 return FALSE;
577 }
libc_hidden_def(xdr_bytes)578 libc_hidden_def(xdr_bytes)
579
580 /*
581 * Implemented here due to commonality of the object.
582 */
583 bool_t
584 xdr_netobj (XDR *xdrs, struct netobj *np)
585 {
586
587 return xdr_bytes (xdrs, &np->n_bytes, &np->n_len, MAX_NETOBJ_SZ);
588 }
589
590 /*
591 * XDR a discriminated union
592 * Support routine for discriminated unions.
593 * You create an array of xdrdiscrim structures, terminated with
594 * an entry with a null procedure pointer. The routine gets
595 * the discriminant value and then searches the array of xdrdiscrims
596 * looking for that value. It calls the procedure given in the xdrdiscrim
597 * to handle the discriminant. If there is no specific routine a default
598 * routine may be called.
599 * If there is no specific or default routine an error is returned.
600 */
601 bool_t
xdr_union(XDR * xdrs,enum_t * dscmp,char * unp,const struct xdr_discrim * choices,xdrproc_t dfault)602 xdr_union (XDR *xdrs, enum_t *dscmp, char *unp, const struct xdr_discrim *choices, xdrproc_t dfault)
603 {
604 enum_t dscm;
605
606 /*
607 * we deal with the discriminator; it's an enum
608 */
609 if (!xdr_enum (xdrs, dscmp))
610 {
611 return FALSE;
612 }
613 dscm = *dscmp;
614
615 /*
616 * search choices for a value that matches the discriminator.
617 * if we find one, execute the xdr routine for that value.
618 */
619 for (; choices->proc != NULL_xdrproc_t; choices++)
620 {
621 if (choices->value == dscm)
622 return (*(choices->proc)) (xdrs, unp, LASTUNSIGNED);
623 }
624
625 /*
626 * no match - execute the default xdr routine if there is one
627 */
628 return ((dfault == NULL_xdrproc_t) ? FALSE :
629 (*dfault) (xdrs, unp, LASTUNSIGNED));
630 }
libc_hidden_def(xdr_union)631 libc_hidden_def(xdr_union)
632
633 /*
634 * Non-portable xdr primitives.
635 * Care should be taken when moving these routines to new architectures.
636 */
637
638
639 /*
640 * XDR null terminated ASCII strings
641 * xdr_string deals with "C strings" - arrays of bytes that are
642 * terminated by a NULL character. The parameter cpp references a
643 * pointer to storage; If the pointer is null, then the necessary
644 * storage is allocated. The last parameter is the max allowed length
645 * of the string as specified by a protocol.
646 */
647 bool_t
648 xdr_string (XDR *xdrs, char **cpp, u_int maxsize)
649 {
650 char *sp = *cpp; /* sp is the actual string pointer */
651 u_int size;
652 u_int nodesize;
653
654 /*
655 * first deal with the length since xdr strings are counted-strings
656 */
657 switch (xdrs->x_op)
658 {
659 case XDR_FREE:
660 if (sp == NULL)
661 {
662 return TRUE; /* already free */
663 }
664 /* fall through... */
665 case XDR_ENCODE:
666 if (sp == NULL)
667 return FALSE;
668 size = strlen (sp);
669 break;
670 case XDR_DECODE:
671 break;
672 }
673 if (!xdr_u_int (xdrs, &size))
674 {
675 return FALSE;
676 }
677 if (size > maxsize)
678 {
679 return FALSE;
680 }
681 nodesize = size + 1;
682
683 /*
684 * now deal with the actual bytes
685 */
686 switch (xdrs->x_op)
687 {
688 case XDR_DECODE:
689 if (nodesize == 0)
690 {
691 return TRUE;
692 }
693 if (sp == NULL)
694 *cpp = sp = (char *) mem_alloc (nodesize);
695 if (sp == NULL)
696 {
697 (void) fputs (_("xdr_string: out of memory\n"), stderr);
698 return FALSE;
699 }
700 sp[size] = 0;
701 /* fall into ... */
702
703 case XDR_ENCODE:
704 return xdr_opaque (xdrs, sp, size);
705
706 case XDR_FREE:
707 mem_free (sp, nodesize);
708 *cpp = NULL;
709 return TRUE;
710 }
711 return FALSE;
712 }
libc_hidden_def(xdr_string)713 libc_hidden_def(xdr_string)
714
715 /*
716 * Wrapper for xdr_string that can be called directly from
717 * routines like clnt_call
718 */
719 bool_t
720 xdr_wrapstring (XDR *xdrs, char **cpp)
721 {
722 if (xdr_string (xdrs, cpp, LASTUNSIGNED))
723 {
724 return TRUE;
725 }
726 return FALSE;
727 }
728