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