Update.
[platform/upstream/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
48 #include <rpc/types.h>
49 #include <rpc/xdr.h>
50
51 /*
52  * constants specific to the xdr "protocol"
53  */
54 #define XDR_FALSE       ((long) 0)
55 #define XDR_TRUE        ((long) 1)
56 #define LASTUNSIGNED    ((u_int) 0-1)
57
58 /*
59  * for unit alignment
60  */
61 static const char xdr_zero[BYTES_PER_XDR_UNIT] =
62 {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
69 xdr_free (proc, objp)
70      xdrproc_t proc;
71      char *objp;
72 {
73   XDR x;
74
75   x.x_op = XDR_FREE;
76   (*proc) (&x, objp);
77 }
78
79 /*
80  * XDR nothing
81  */
82 bool_t
83 xdr_void (void)
84 {
85   return TRUE;
86 }
87
88 /*
89  * XDR integers
90  */
91 bool_t
92 xdr_int (xdrs, ip)
93      XDR *xdrs;
94      int *ip;
95 {
96
97 #if INT_MAX < LONG_MAX
98   long l;
99
100   switch (xdrs->x_op)
101     {
102     case XDR_ENCODE:
103       l = (long) *ip;
104       return XDR_PUTLONG (xdrs, &l);
105
106     case XDR_DECODE:
107       if (!XDR_GETLONG (xdrs, &l))
108         {
109           return FALSE;
110         }
111       *ip = (int) l;
112     case XDR_FREE:
113       return TRUE;
114     }
115   return FALSE;
116 #elif INT_MAX == LONG_MAX
117   return xdr_long (xdrs, (long *) ip);
118 #elif INT_MAX == SHRT_MAX
119   return xdr_short (xdrs, (short *) ip);
120 #else
121 #error unexpected integer sizes in_xdr_int()
122 #endif
123 }
124
125 /*
126  * XDR unsigned integers
127  */
128 bool_t
129 xdr_u_int (xdrs, up)
130      XDR *xdrs;
131      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 xdr_u_long (xdrs, (u_long *) up);
154 #elif UINT_MAX == USHRT_MAX
155   return xdr_short (xdrs, (short *) up);
156 #else
157 #error unexpected integer sizes in_xdr_u_int()
158 #endif
159 }
160
161 /*
162  * XDR long integers
163  * same as xdr_u_long - open coded to save a proc call!
164  */
165 bool_t
166 xdr_long (xdrs, lp)
167      XDR *xdrs;
168      long *lp;
169 {
170
171   if (xdrs->x_op == XDR_ENCODE)
172     return XDR_PUTLONG (xdrs, lp);
173
174   if (xdrs->x_op == XDR_DECODE)
175     return XDR_GETLONG (xdrs, lp);
176
177   if (xdrs->x_op == XDR_FREE)
178     return TRUE;
179
180   return FALSE;
181 }
182
183 /*
184  * XDR unsigned long integers
185  * same as xdr_long - open coded to save a proc call!
186  */
187 bool_t
188 xdr_u_long (xdrs, ulp)
189      XDR *xdrs;
190      u_long *ulp;
191 {
192   switch (xdrs->x_op)
193     {
194     case XDR_DECODE:
195       return XDR_GETLONG (xdrs, (long *) ulp);
196
197     case XDR_ENCODE:
198       return XDR_PUTLONG (xdrs, (long *) ulp);
199
200     case XDR_FREE:
201       return TRUE;
202     }
203   return FALSE;
204 }
205
206 /*
207  * XDR short integers
208  */
209 bool_t
210 xdr_short (xdrs, sp)
211      XDR *xdrs;
212      short *sp;
213 {
214   long l;
215
216   switch (xdrs->x_op)
217     {
218     case XDR_ENCODE:
219       l = (long) *sp;
220       return XDR_PUTLONG (xdrs, &l);
221
222     case XDR_DECODE:
223       if (!XDR_GETLONG (xdrs, &l))
224         {
225           return FALSE;
226         }
227       *sp = (short) l;
228       return TRUE;
229
230     case XDR_FREE:
231       return TRUE;
232     }
233   return FALSE;
234 }
235
236 /*
237  * XDR unsigned short integers
238  */
239 bool_t
240 xdr_u_short (xdrs, usp)
241      XDR *xdrs;
242      u_short *usp;
243 {
244   u_long l;
245
246   switch (xdrs->x_op)
247     {
248     case XDR_ENCODE:
249       l = (u_long) * usp;
250       return XDR_PUTLONG (xdrs, &l);
251
252     case XDR_DECODE:
253       if (!XDR_GETLONG (xdrs, &l))
254         {
255           return FALSE;
256         }
257       *usp = (u_short) l;
258       return TRUE;
259
260     case XDR_FREE:
261       return TRUE;
262     }
263   return FALSE;
264 }
265
266
267 /*
268  * XDR a char
269  */
270 bool_t
271 xdr_char (xdrs, cp)
272      XDR *xdrs;
273      char *cp;
274 {
275   int i;
276
277   i = (*cp);
278   if (!xdr_int (xdrs, &i))
279     {
280       return FALSE;
281     }
282   *cp = i;
283   return TRUE;
284 }
285
286 /*
287  * XDR an unsigned char
288  */
289 bool_t
290 xdr_u_char (xdrs, cp)
291      XDR *xdrs;
292      u_char *cp;
293 {
294   u_int u;
295
296   u = (*cp);
297   if (!xdr_u_int (xdrs, &u))
298     {
299       return FALSE;
300     }
301   *cp = u;
302   return TRUE;
303 }
304
305 /*
306  * XDR booleans
307  */
308 bool_t
309 xdr_bool (xdrs, bp)
310      XDR *xdrs;
311      bool_t *bp;
312 {
313   long lb;
314
315   switch (xdrs->x_op)
316     {
317     case XDR_ENCODE:
318       lb = *bp ? XDR_TRUE : XDR_FALSE;
319       return XDR_PUTLONG (xdrs, &lb);
320
321     case XDR_DECODE:
322       if (!XDR_GETLONG (xdrs, &lb))
323         {
324           return FALSE;
325         }
326       *bp = (lb == XDR_FALSE) ? FALSE : TRUE;
327       return TRUE;
328
329     case XDR_FREE:
330       return TRUE;
331     }
332   return FALSE;
333 }
334
335 /*
336  * XDR enumerations
337  */
338 bool_t
339 xdr_enum (xdrs, ep)
340      XDR *xdrs;
341      enum_t *ep;
342 {
343   enum sizecheck
344     {
345       SIZEVAL
346     };                          /* used to find the size of an enum */
347
348   /*
349    * enums are treated as ints
350    */
351   if (sizeof (enum sizecheck) == 4)
352     {
353 #if INT_MAX < LONG_MAX
354       long l;
355
356       switch (xdrs->x_op)
357         {
358         case XDR_ENCODE:
359           l = *ep;
360           return XDR_PUTLONG (xdrs, &l);
361
362         case XDR_DECODE:
363           if (!XDR_GETLONG (xdrs, &l))
364             {
365               return FALSE;
366             }
367           *ep = l;
368         case XDR_FREE:
369           return TRUE;
370
371         }
372       return FALSE;
373 #else
374       return xdr_long (xdrs, (long *) ep);
375 #endif
376     }
377   else if (sizeof (enum sizecheck) == sizeof (short))
378     {
379       return xdr_short (xdrs, (short *) ep);
380     }
381   else
382     {
383       return FALSE;
384     }
385 }
386
387 /*
388  * XDR opaque data
389  * Allows the specification of a fixed size sequence of opaque bytes.
390  * cp points to the opaque object and cnt gives the byte length.
391  */
392 bool_t
393 xdr_opaque (xdrs, cp, cnt)
394      XDR *xdrs;
395      caddr_t cp;
396      u_int cnt;
397 {
398   u_int rndup;
399   static char crud[BYTES_PER_XDR_UNIT];
400
401   /*
402    * if no data we are done
403    */
404   if (cnt == 0)
405     return TRUE;
406
407   /*
408    * round byte count to full xdr units
409    */
410   rndup = cnt % BYTES_PER_XDR_UNIT;
411   if (rndup > 0)
412     rndup = BYTES_PER_XDR_UNIT - rndup;
413
414   switch (xdrs->x_op)
415     {
416     case XDR_DECODE:
417       if (!XDR_GETBYTES (xdrs, cp, cnt))
418         {
419           return FALSE;
420         }
421       if (rndup == 0)
422         return TRUE;
423       return XDR_GETBYTES (xdrs, (caddr_t)crud, rndup);
424
425     case XDR_ENCODE:
426       if (!XDR_PUTBYTES (xdrs, cp, cnt))
427         {
428           return FALSE;
429         }
430       if (rndup == 0)
431         return TRUE;
432       return XDR_PUTBYTES (xdrs, xdr_zero, rndup);
433
434     case XDR_FREE:
435       return TRUE;
436     }
437   return FALSE;
438 }
439
440 /*
441  * XDR counted bytes
442  * *cpp is a pointer to the bytes, *sizep is the count.
443  * If *cpp is NULL maxsize bytes are allocated
444  */
445 bool_t
446 xdr_bytes (xdrs, cpp, sizep, maxsize)
447      XDR *xdrs;
448      char **cpp;
449      u_int *sizep;
450      u_int maxsize;
451 {
452   char *sp = *cpp;      /* sp is the actual string pointer */
453   u_int nodesize;
454
455   /*
456    * first deal with the length since xdr bytes are counted
457    */
458   if (!xdr_u_int (xdrs, sizep))
459     {
460       return FALSE;
461     }
462   nodesize = *sizep;
463   if ((nodesize > maxsize) && (xdrs->x_op != XDR_FREE))
464     {
465       return FALSE;
466     }
467
468   /*
469    * now deal with the actual bytes
470    */
471   switch (xdrs->x_op)
472     {
473     case XDR_DECODE:
474       if (nodesize == 0)
475         {
476           return TRUE;
477         }
478       if (sp == NULL)
479         {
480           *cpp = sp = (char *) mem_alloc (nodesize);
481         }
482       if (sp == NULL)
483         {
484           (void) fprintf (stderr, "xdr_bytes: out of memory\n");
485           return FALSE;
486         }
487       /* fall into ... */
488
489     case XDR_ENCODE:
490       return xdr_opaque (xdrs, sp, nodesize);
491
492     case XDR_FREE:
493       if (sp != NULL)
494         {
495           mem_free (sp, nodesize);
496           *cpp = NULL;
497         }
498       return TRUE;
499     }
500   return FALSE;
501 }
502
503 /*
504  * Implemented here due to commonality of the object.
505  */
506 bool_t
507 xdr_netobj (xdrs, np)
508      XDR *xdrs;
509      struct netobj *np;
510 {
511
512   return xdr_bytes (xdrs, &np->n_bytes, &np->n_len, MAX_NETOBJ_SZ);
513 }
514
515 /*
516  * XDR a discriminated union
517  * Support routine for discriminated unions.
518  * You create an array of xdrdiscrim structures, terminated with
519  * an entry with a null procedure pointer.  The routine gets
520  * the discriminant value and then searches the array of xdrdiscrims
521  * looking for that value.  It calls the procedure given in the xdrdiscrim
522  * to handle the discriminant.  If there is no specific routine a default
523  * routine may be called.
524  * If there is no specific or default routine an error is returned.
525  */
526 bool_t
527 xdr_union (xdrs, dscmp, unp, choices, dfault)
528      XDR *xdrs;
529      enum_t *dscmp;             /* enum to decide which arm to work on */
530      char *unp;                 /* the union itself */
531      const struct xdr_discrim *choices; /* [value, xdr proc] for each arm */
532      xdrproc_t dfault;          /* default xdr routine */
533 {
534   enum_t dscm;
535
536   /*
537    * we deal with the discriminator;  it's an enum
538    */
539   if (!xdr_enum (xdrs, dscmp))
540     {
541       return FALSE;
542     }
543   dscm = *dscmp;
544
545   /*
546    * search choices for a value that matches the discriminator.
547    * if we find one, execute the xdr routine for that value.
548    */
549   for (; choices->proc != NULL_xdrproc_t; choices++)
550     {
551       if (choices->value == dscm)
552         return (*(choices->proc)) (xdrs, unp, LASTUNSIGNED);
553     }
554
555   /*
556    * no match - execute the default xdr routine if there is one
557    */
558   return ((dfault == NULL_xdrproc_t) ? FALSE :
559           (*dfault) (xdrs, unp, LASTUNSIGNED));
560 }
561
562
563 /*
564  * Non-portable xdr primitives.
565  * Care should be taken when moving these routines to new architectures.
566  */
567
568
569 /*
570  * XDR null terminated ASCII strings
571  * xdr_string deals with "C strings" - arrays of bytes that are
572  * terminated by a NULL character.  The parameter cpp references a
573  * pointer to storage; If the pointer is null, then the necessary
574  * storage is allocated.  The last parameter is the max allowed length
575  * of the string as specified by a protocol.
576  */
577 bool_t
578 xdr_string (xdrs, cpp, maxsize)
579      XDR *xdrs;
580      char **cpp;
581      u_int maxsize;
582 {
583   char *sp = *cpp;      /* sp is the actual string pointer */
584   u_int size;
585   u_int nodesize;
586
587   /*
588    * first deal with the length since xdr strings are counted-strings
589    */
590   switch (xdrs->x_op)
591     {
592     case XDR_FREE:
593       if (sp == NULL)
594         {
595           return TRUE;          /* already free */
596         }
597       /* fall through... */
598     case XDR_ENCODE:
599       if (sp == NULL)
600         return FALSE;
601       size = strlen (sp);
602       break;
603     case XDR_DECODE:
604       break;
605     }
606   if (!xdr_u_int (xdrs, &size))
607     {
608       return FALSE;
609     }
610   if (size > maxsize)
611     {
612       return FALSE;
613     }
614   nodesize = size + 1;
615
616   /*
617    * now deal with the actual bytes
618    */
619   switch (xdrs->x_op)
620     {
621     case XDR_DECODE:
622       if (nodesize == 0)
623         {
624           return TRUE;
625         }
626       if (sp == NULL)
627         *cpp = sp = (char *) mem_alloc (nodesize);
628       if (sp == NULL)
629         {
630           (void) fprintf (stderr, "xdr_string: out of memory\n");
631           return FALSE;
632         }
633       sp[size] = 0;
634       /* fall into ... */
635
636     case XDR_ENCODE:
637       return xdr_opaque (xdrs, sp, size);
638
639     case XDR_FREE:
640       mem_free (sp, nodesize);
641       *cpp = NULL;
642       return TRUE;
643     }
644   return FALSE;
645 }
646
647 /*
648  * Wrapper for xdr_string that can be called directly from
649  * routines like clnt_call
650  */
651 bool_t
652 xdr_wrapstring (xdrs, cpp)
653      XDR *xdrs;
654      char **cpp;
655 {
656   if (xdr_string (xdrs, cpp, LASTUNSIGNED))
657     {
658       return TRUE;
659     }
660   return FALSE;
661 }