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