(authunix_create_default): Don't allocate huge arrays on the stack.
[kopensolaris-gnu/glibc.git] / sunrpc / xdr.c
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 !defined(lint) && defined(SCCSIDS)
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 #ifdef USE_IN_LIBIO
53 # include <wchar.h>
54 #endif
55
56 /*
57  * constants specific to the xdr "protocol"
58  */
59 #define XDR_FALSE       ((long) 0)
60 #define XDR_TRUE        ((long) 1)
61 #define LASTUNSIGNED    ((u_int) 0-1)
62
63 /*
64  * for unit alignment
65  */
66 static const char xdr_zero[BYTES_PER_XDR_UNIT] = {0, 0, 0, 0};
67
68 /*
69  * Free a data structure using XDR
70  * Not a filter, but a convenient utility nonetheless
71  */
72 void
73 xdr_free (xdrproc_t proc, char *objp)
74 {
75   XDR x;
76
77   x.x_op = XDR_FREE;
78   (*proc) (&x, objp);
79 }
80
81 /*
82  * XDR nothing
83  */
84 bool_t
85 xdr_void (void)
86 {
87   return TRUE;
88 }
89 INTDEF(xdr_void)
90
91 /*
92  * XDR integers
93  */
94 bool_t
95 xdr_int (XDR *xdrs, int *ip)
96 {
97
98 #if INT_MAX < LONG_MAX
99   long l;
100
101   switch (xdrs->x_op)
102     {
103     case XDR_ENCODE:
104       l = (long) *ip;
105       return XDR_PUTLONG (xdrs, &l);
106
107     case XDR_DECODE:
108       if (!XDR_GETLONG (xdrs, &l))
109         {
110           return FALSE;
111         }
112       *ip = (int) l;
113     case XDR_FREE:
114       return TRUE;
115     }
116   return FALSE;
117 #elif INT_MAX == LONG_MAX
118   return INTUSE(xdr_long) (xdrs, (long *) ip);
119 #elif INT_MAX == SHRT_MAX
120   return INTUSE(xdr_short) (xdrs, (short *) ip);
121 #else
122 #error unexpected integer sizes in_xdr_int()
123 #endif
124 }
125 INTDEF(xdr_int)
126
127 /*
128  * XDR unsigned integers
129  */
130 bool_t
131 xdr_u_int (XDR *xdrs, u_int *up)
132 {
133 #if UINT_MAX < ULONG_MAX
134   u_long l;
135
136   switch (xdrs->x_op)
137     {
138     case XDR_ENCODE:
139       l = (u_long) * up;
140       return XDR_PUTLONG (xdrs, &l);
141
142     case XDR_DECODE:
143       if (!XDR_GETLONG (xdrs, &l))
144         {
145           return FALSE;
146         }
147       *up = (u_int) l;
148     case XDR_FREE:
149       return TRUE;
150     }
151   return FALSE;
152 #elif UINT_MAX == ULONG_MAX
153   return INTUSE(xdr_u_long) (xdrs, (u_long *) up);
154 #elif UINT_MAX == USHRT_MAX
155   return INTUSE(xdr_short) (xdrs, (short *) up);
156 #else
157 #error unexpected integer sizes in_xdr_u_int()
158 #endif
159 }
160 INTDEF(xdr_u_int)
161
162 /*
163  * XDR long integers
164  * The definition of xdr_long() is kept for backward
165  * compatibility. Instead xdr_int() should be used.
166  */
167 bool_t
168 xdr_long (XDR *xdrs, long *lp)
169 {
170
171   if (xdrs->x_op == XDR_ENCODE
172       && (sizeof (int32_t) == sizeof (long)
173           || (int32_t) *lp == *lp))
174     return XDR_PUTLONG (xdrs, lp);
175
176   if (xdrs->x_op == XDR_DECODE)
177     return XDR_GETLONG (xdrs, lp);
178
179   if (xdrs->x_op == XDR_FREE)
180     return TRUE;
181
182   return FALSE;
183 }
184 INTDEF(xdr_long)
185
186 /*
187  * XDR unsigned long integers
188  * The definition of xdr_u_long() is kept for backward
189  * compatibility. Instead xdr_u_int() should be used.
190  */
191 bool_t
192 xdr_u_long (XDR *xdrs, u_long *ulp)
193 {
194   switch (xdrs->x_op)
195     {
196     case XDR_DECODE:
197       {
198         long int tmp;
199
200         if (XDR_GETLONG (xdrs, &tmp) == FALSE)
201           return FALSE;
202
203         *ulp = (uint32_t) tmp;
204         return TRUE;
205       }
206
207     case XDR_ENCODE:
208       if (sizeof (uint32_t) != sizeof (u_long)
209           && (uint32_t) *ulp != *ulp)
210         return FALSE;
211
212       return XDR_PUTLONG (xdrs, (long *) ulp);
213
214     case XDR_FREE:
215       return TRUE;
216     }
217   return FALSE;
218 }
219 INTDEF(xdr_u_long)
220
221 /*
222  * XDR hyper integers
223  * same as xdr_u_hyper - open coded to save a proc call!
224  */
225 bool_t
226 xdr_hyper (XDR *xdrs, quad_t *llp)
227 {
228   long t1;
229   unsigned long int t2;
230
231   if (xdrs->x_op == XDR_ENCODE)
232     {
233       t1 = (long) ((*llp) >> 32);
234       t2 = (long) (*llp);
235       return (XDR_PUTLONG(xdrs, &t1) && XDR_PUTLONG(xdrs, &t2));
236     }
237
238   if (xdrs->x_op == XDR_DECODE)
239     {
240       if (!XDR_GETLONG(xdrs, &t1) || !XDR_GETLONG(xdrs, &t2))
241         return FALSE;
242       *llp = ((quad_t) t1) << 32;
243       *llp |= t2;
244       return TRUE;
245     }
246
247   if (xdrs->x_op == XDR_FREE)
248     return TRUE;
249
250   return FALSE;
251 }
252 INTDEF(xdr_hyper)
253
254
255 /*
256  * XDR hyper integers
257  * same as xdr_hyper - open coded to save a proc call!
258  */
259 bool_t
260 xdr_u_hyper (XDR *xdrs, u_quad_t *ullp)
261 {
262   unsigned long t1;
263   unsigned long 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 |= 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   u_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) 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 #ifdef USE_IN_LIBIO
569           if (_IO_fwide (stderr, 0) > 0)
570             (void) __fwprintf (stderr, L"%s", _("xdr_bytes: out of memory\n"));
571           else
572 #endif
573             (void) fputs (_("xdr_bytes: out of memory\n"), stderr);
574           return FALSE;
575         }
576       /* fall into ... */
577
578     case XDR_ENCODE:
579       return INTUSE(xdr_opaque) (xdrs, sp, nodesize);
580
581     case XDR_FREE:
582       if (sp != NULL)
583         {
584           mem_free (sp, nodesize);
585           *cpp = NULL;
586         }
587       return TRUE;
588     }
589   return FALSE;
590 }
591 INTDEF(xdr_bytes)
592
593 /*
594  * Implemented here due to commonality of the object.
595  */
596 bool_t
597 xdr_netobj (xdrs, np)
598      XDR *xdrs;
599      struct netobj *np;
600 {
601
602   return INTUSE(xdr_bytes) (xdrs, &np->n_bytes, &np->n_len, MAX_NETOBJ_SZ);
603 }
604 INTDEF(xdr_netobj)
605
606 /*
607  * XDR a discriminated union
608  * Support routine for discriminated unions.
609  * You create an array of xdrdiscrim structures, terminated with
610  * an entry with a null procedure pointer.  The routine gets
611  * the discriminant value and then searches the array of xdrdiscrims
612  * looking for that value.  It calls the procedure given in the xdrdiscrim
613  * to handle the discriminant.  If there is no specific routine a default
614  * routine may be called.
615  * If there is no specific or default routine an error is returned.
616  */
617 bool_t
618 xdr_union (xdrs, dscmp, unp, choices, dfault)
619      XDR *xdrs;
620      enum_t *dscmp;             /* enum to decide which arm to work on */
621      char *unp;                 /* the union itself */
622      const struct xdr_discrim *choices; /* [value, xdr proc] for each arm */
623      xdrproc_t dfault;          /* default xdr routine */
624 {
625   enum_t dscm;
626
627   /*
628    * we deal with the discriminator;  it's an enum
629    */
630   if (!INTUSE(xdr_enum) (xdrs, dscmp))
631     {
632       return FALSE;
633     }
634   dscm = *dscmp;
635
636   /*
637    * search choices for a value that matches the discriminator.
638    * if we find one, execute the xdr routine for that value.
639    */
640   for (; choices->proc != NULL_xdrproc_t; choices++)
641     {
642       if (choices->value == dscm)
643         return (*(choices->proc)) (xdrs, unp, LASTUNSIGNED);
644     }
645
646   /*
647    * no match - execute the default xdr routine if there is one
648    */
649   return ((dfault == NULL_xdrproc_t) ? FALSE :
650           (*dfault) (xdrs, unp, LASTUNSIGNED));
651 }
652 INTDEF(xdr_union)
653
654
655 /*
656  * Non-portable xdr primitives.
657  * Care should be taken when moving these routines to new architectures.
658  */
659
660
661 /*
662  * XDR null terminated ASCII strings
663  * xdr_string deals with "C strings" - arrays of bytes that are
664  * terminated by a NULL character.  The parameter cpp references a
665  * pointer to storage; If the pointer is null, then the necessary
666  * storage is allocated.  The last parameter is the max allowed length
667  * of the string as specified by a protocol.
668  */
669 bool_t
670 xdr_string (xdrs, cpp, maxsize)
671      XDR *xdrs;
672      char **cpp;
673      u_int maxsize;
674 {
675   char *sp = *cpp;      /* sp is the actual string pointer */
676   u_int size;
677   u_int nodesize;
678
679   /*
680    * first deal with the length since xdr strings are counted-strings
681    */
682   switch (xdrs->x_op)
683     {
684     case XDR_FREE:
685       if (sp == NULL)
686         {
687           return TRUE;          /* already free */
688         }
689       /* fall through... */
690     case XDR_ENCODE:
691       if (sp == NULL)
692         return FALSE;
693       size = strlen (sp);
694       break;
695     case XDR_DECODE:
696       break;
697     }
698   if (!INTUSE(xdr_u_int) (xdrs, &size))
699     {
700       return FALSE;
701     }
702   if (size > maxsize)
703     {
704       return FALSE;
705     }
706   nodesize = size + 1;
707   if (nodesize == 0)
708     {
709       /* This means an overflow.  It a bug in the caller which
710          provided a too large maxsize but nevertheless catch it
711          here.  */
712       return FALSE;
713     }
714
715   /*
716    * now deal with the actual bytes
717    */
718   switch (xdrs->x_op)
719     {
720     case XDR_DECODE:
721       if (sp == NULL)
722         *cpp = sp = (char *) mem_alloc (nodesize);
723       if (sp == NULL)
724         {
725 #ifdef USE_IN_LIBIO
726           if (_IO_fwide (stderr, 0) > 0)
727             (void) __fwprintf (stderr, L"%s",
728                                _("xdr_string: out of memory\n"));
729           else
730 #endif
731             (void) fputs (_("xdr_string: out of memory\n"), stderr);
732           return FALSE;
733         }
734       sp[size] = 0;
735       /* fall into ... */
736
737     case XDR_ENCODE:
738       return INTUSE(xdr_opaque) (xdrs, sp, size);
739
740     case XDR_FREE:
741       mem_free (sp, nodesize);
742       *cpp = NULL;
743       return TRUE;
744     }
745   return FALSE;
746 }
747 INTDEF(xdr_string)
748
749 /*
750  * Wrapper for xdr_string that can be called directly from
751  * routines like clnt_call
752  */
753 bool_t
754 xdr_wrapstring (xdrs, cpp)
755      XDR *xdrs;
756      char **cpp;
757 {
758   if (INTUSE(xdr_string) (xdrs, cpp, LASTUNSIGNED))
759     {
760       return TRUE;
761     }
762   return FALSE;
763 }