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