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