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