Merge up from branch.
[shibboleth/cpp-sp.git] / oncrpc / xdr.c
1 /*********************************************************************
2  * RPC for the Windows NT Operating System
3  * 1993 by Martin F. Gergeleit
4  * Users may use, copy or modify Sun RPC for the Windows NT Operating 
5  * System according to the Sun copyright below.
6  *
7  * RPC for the Windows NT Operating System COMES WITH ABSOLUTELY NO 
8  * WARRANTY, NOR WILL I BE LIABLE FOR ANY DAMAGES INCURRED FROM THE 
9  * USE OF. USE ENTIRELY AT YOUR OWN RISK!!!
10  *********************************************************************/
11
12 /* @(#)xdr.c    2.1 88/07/29 4.0 RPCSRC */
13 /*
14  * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
15  * unrestricted use provided that this legend is included on all tape
16  * media and as a part of the software program in whole or part.  Users
17  * may copy or modify Sun RPC without charge, but are not authorized
18  * to license or distribute it to anyone else except as part of a product or
19  * program developed by the user.
20  *
21  * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
22  * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
23  * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
24  *
25  * Sun RPC is provided with no support and without any obligation on the
26  * part of Sun Microsystems, Inc. to assist in its use, correction,
27  * modification or enhancement.
28  *
29  * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
30  * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
31  * OR ANY PART THEREOF.
32  *
33  * In no event will Sun Microsystems, Inc. be liable for any lost revenue
34  * or profits or other special, indirect and consequential damages, even if
35  * Sun has been advised of the possibility of such damages.
36  *
37  * Sun Microsystems, Inc.
38  * 2550 Garcia Avenue
39  * Mountain View, California  94043
40  */
41 #if !defined(lint) && defined(SCCSIDS)
42 static char sccsid[] = "@(#)xdr.c 1.35 87/08/12";
43 #endif
44
45 /*
46  * xdr.c, Generic XDR routines implementation.
47  *
48  * Copyright (C) 1986, Sun Microsystems, Inc.
49  *
50  * These are the "generic" xdr routines used to serialize and de-serialize
51  * most common data items.  See xdr.h for more info on the interface to
52  * xdr.
53  */
54
55 // eventually we might be able to support autoconf via cygwin...
56 #if defined (_MSC_VER) || defined(__BORLANDC__)
57 # include "config_win32.h"
58 #else
59 # include "config.h"
60 #endif
61
62 #ifdef HAVE_STDINT_H
63 # include <stdint.h>
64 #endif
65 #include <stdio.h>
66 #ifndef WIN32
67 void *malloc();
68 #endif
69
70 #include <rpc/rpc.h>
71 #include <rpc/types.h>
72 #include <rpc/xdr.h>
73
74 /*
75  * constants specific to the xdr "protocol"
76  */
77 #define XDR_FALSE       ((long) 0)
78 #define XDR_TRUE        ((long) 1)
79 #define LASTUNSIGNED    ((u_int) 0-1)
80
81 /*
82  * for unit alignment
83  */
84 static char xdr_zero[BYTES_PER_XDR_UNIT] = { 0, 0, 0, 0 };
85
86 /*
87  * Free a data structure using XDR
88  * Not a filter, but a convenient utility nonetheless
89  */
90 void
91 xdr_free(proc, objp)
92         xdrproc_t proc;
93         char *objp;
94 {
95         XDR x;
96
97         x.x_op = XDR_FREE;
98         (*proc)(&x, objp);
99 }
100
101 /*
102  * XDR nothing
103  */
104 bool_t
105 xdr_void(/* xdrs, addr */)
106         /* XDR *xdrs; */
107         /* caddr_t addr; */
108 {
109
110         return (TRUE);
111 }
112
113 /*
114  * XDR integers
115  */
116 bool_t
117 xdr_int(xdrs, ip)
118         XDR *xdrs;
119         int *ip;
120 {
121
122 #ifdef lint
123         (void) (xdr_short(xdrs, (short *)ip));
124         return (xdr_long(xdrs, (long *)ip));
125 #else
126         if (sizeof (int) == sizeof (long)) {
127                 return (xdr_long(xdrs, (long *)ip));
128         } else {
129                 return (xdr_short(xdrs, (short *)ip));
130         }
131 #endif
132 }
133
134 /*
135  * XDR unsigned integers
136  */
137 bool_t
138 xdr_u_int(xdrs, up)
139         XDR *xdrs;
140         u_int *up;
141 {
142
143 #ifdef lint
144         (void) (xdr_short(xdrs, (short *)up));
145         return (xdr_u_long(xdrs, (u_long *)up));
146 #else
147         if (sizeof (u_int) == sizeof (u_long)) {
148                 return (xdr_u_long(xdrs, (u_long *)up));
149         } else {
150                 return (xdr_short(xdrs, (short *)up));
151         }
152 #endif
153 }
154
155 /*
156  * XDR 64-bit integers
157  */
158 bool_t
159 xdr_int64_t(xdrs, ip)
160         XDR *xdrs;
161         int64_t *ip;
162 {
163   if (sizeof (int64_t) <= sizeof (long)) {
164     return (xdr_long(xdrs, (long *)ip));
165   } else {
166     /* Assumes sizeof(long) == 4 */
167     int32_t t1;
168     uint32_t t2;
169     
170     switch (xdrs->x_op) {
171     case XDR_ENCODE:
172       t1 = (int32_t) ((*ip) >> 32);
173       t2 = (int32_t) (*ip);
174       return (XDR_PUTLONG(xdrs, &t1) && XDR_PUTLONG(xdrs, &t2));
175       
176     case XDR_DECODE:
177       if (!XDR_GETLONG(xdrs, &t1) || !XDR_GETLONG(xdrs, &t2))
178         return FALSE;
179       *ip = ((int64_t) t1) << 32;
180       *ip |= t2;
181       return TRUE;
182
183     case XDR_FREE:
184       return TRUE;
185
186     default:
187       return FALSE;
188     }
189   }
190 }
191
192 /*
193  * XDR unsigned 64-bit integers
194  */
195 bool_t
196 xdr_uint64_t(xdrs, up)
197         XDR *xdrs;
198         uint64_t *up;
199 {
200   if (sizeof (int64_t) <= sizeof (long)) {
201     return (xdr_long(xdrs, (long *)up));
202   } else {
203     /* Assumes sizeof(long) == 4 */
204     uint32_t t1;
205     uint32_t t2;
206     
207     switch (xdrs->x_op) {
208     case XDR_ENCODE:
209       t1 = (uint32_t) ((*up) >> 32);
210       t2 = (uint32_t) (*up);
211       return (XDR_PUTLONG(xdrs, &t1) && XDR_PUTLONG(xdrs, &t2));
212       
213     case XDR_DECODE:
214       if (!XDR_GETLONG(xdrs, &t1) || !XDR_GETLONG(xdrs, &t2))
215         return FALSE;
216       *up = ((uint64_t) t1) << 32;
217       *up |= t2;
218       return TRUE;
219
220     case XDR_FREE:
221       return TRUE;
222
223     default:
224       return FALSE;
225     }
226   }
227 }
228
229 /*
230  * XDR long integers
231  * same as xdr_u_long - open coded to save a proc call!
232  */
233 bool_t
234 xdr_long(xdrs, lp)
235         register XDR *xdrs;
236         long *lp;
237 {
238
239         if (xdrs->x_op == XDR_ENCODE)
240                 return (XDR_PUTLONG(xdrs, lp));
241
242         if (xdrs->x_op == XDR_DECODE)
243                 return (XDR_GETLONG(xdrs, lp));
244
245         if (xdrs->x_op == XDR_FREE)
246                 return (TRUE);
247
248         return (FALSE);
249 }
250
251 /*
252  * XDR unsigned long integers
253  * same as xdr_long - open coded to save a proc call!
254  */
255 bool_t
256 xdr_u_long(xdrs, ulp)
257         register XDR *xdrs;
258         u_long *ulp;
259 {
260
261         if (xdrs->x_op == XDR_DECODE)
262                 return (XDR_GETLONG(xdrs, (long *)ulp));
263         if (xdrs->x_op == XDR_ENCODE)
264                 return (XDR_PUTLONG(xdrs, (long *)ulp));
265         if (xdrs->x_op == XDR_FREE)
266                 return (TRUE);
267         return (FALSE);
268 }
269
270 /*
271  * XDR short integers
272  */
273 bool_t
274 xdr_short(xdrs, sp)
275         register XDR *xdrs;
276         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                         return (FALSE);
289                 }
290                 *sp = (short) l;
291                 return (TRUE);
292
293         case XDR_FREE:
294                 return (TRUE);
295         }
296         return (FALSE);
297 }
298
299 /*
300  * XDR unsigned short integers
301  */
302 bool_t
303 xdr_u_short(xdrs, usp)
304         register XDR *xdrs;
305         u_short *usp;
306 {
307         u_long l;
308
309         switch (xdrs->x_op) {
310
311         case XDR_ENCODE:
312                 l = (u_long) *usp;
313                 return (XDR_PUTLONG(xdrs, &l));
314
315         case XDR_DECODE:
316                 if (!XDR_GETLONG(xdrs, &l)) {
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(xdrs, cp)
334         XDR *xdrs;
335         char *cp;
336 {
337         int i;
338
339         i = (*cp);
340         if (!xdr_int(xdrs, &i)) {
341                 return (FALSE);
342         }
343         *cp = i;
344         return (TRUE);
345 }
346
347 /*
348  * XDR an unsigned char
349  */
350 bool_t
351 xdr_u_char(xdrs, cp)
352         XDR *xdrs;
353         char *cp;
354 {
355         u_int u;
356
357         u = (*cp);
358         if (!xdr_u_int(xdrs, &u)) {
359                 return (FALSE);
360         }
361         *cp = u;
362         return (TRUE);
363 }
364
365 /*
366  * XDR booleans
367  */
368 bool_t
369 xdr_bool(xdrs, bp)
370         register XDR *xdrs;
371         bool_t *bp;
372 {
373         long lb;
374
375         switch (xdrs->x_op) {
376
377         case XDR_ENCODE:
378                 lb = *bp ? XDR_TRUE : XDR_FALSE;
379                 return (XDR_PUTLONG(xdrs, &lb));
380
381         case XDR_DECODE:
382                 if (!XDR_GETLONG(xdrs, &lb)) {
383                         return (FALSE);
384                 }
385                 *bp = (lb == XDR_FALSE) ? FALSE : TRUE;
386                 return (TRUE);
387
388         case XDR_FREE:
389                 return (TRUE);
390         }
391         return (FALSE);
392 }
393
394 /*
395  * XDR enumerations
396  */
397 bool_t
398 xdr_enum(xdrs, ep)
399         XDR *xdrs;
400         enum_t *ep;
401 {
402 #ifndef lint
403         enum sizecheck { SIZEVAL };     /* used to find the size of an enum */
404
405         /*
406          * enums are treated as ints
407          */
408         if (sizeof (enum sizecheck) == sizeof (long)) {
409                 return (xdr_long(xdrs, (long *)ep));
410         } else if (sizeof (enum sizecheck) == sizeof (short)) {
411                 return (xdr_short(xdrs, (short *)ep));
412         } else {
413                 return (FALSE);
414         }
415 #else
416         (void) (xdr_short(xdrs, (short *)ep));
417         return (xdr_long(xdrs, (long *)ep));
418 #endif
419 }
420
421 /*
422  * XDR opaque data
423  * Allows the specification of a fixed size sequence of opaque bytes.
424  * cp points to the opaque object and cnt gives the byte length.
425  */
426 bool_t
427 xdr_opaque(xdrs, cp, cnt)
428         register XDR *xdrs;
429         caddr_t cp;
430         register u_int cnt;
431 {
432         register u_int rndup;
433         static crud[BYTES_PER_XDR_UNIT];
434
435         /*
436          * if no data we are done
437          */
438         if (cnt == 0)
439                 return (TRUE);
440
441         /*
442          * round byte count to full xdr units
443          */
444         rndup = cnt % BYTES_PER_XDR_UNIT;
445         if (rndup > 0)
446                 rndup = BYTES_PER_XDR_UNIT - rndup;
447
448         if (xdrs->x_op == XDR_DECODE) {
449                 if (!XDR_GETBYTES(xdrs, cp, cnt)) {
450                         return (FALSE);
451                 }
452                 if (rndup == 0)
453                         return (TRUE);
454                 return (XDR_GETBYTES(xdrs, crud, rndup));
455         }
456
457         if (xdrs->x_op == XDR_ENCODE) {
458                 if (!XDR_PUTBYTES(xdrs, cp, cnt)) {
459                         return (FALSE);
460                 }
461                 if (rndup == 0)
462                         return (TRUE);
463                 return (XDR_PUTBYTES(xdrs, xdr_zero, rndup));
464         }
465
466         if (xdrs->x_op == XDR_FREE) {
467                 return (TRUE);
468         }
469
470         return (FALSE);
471 }
472
473 /*
474  * XDR counted bytes
475  * *cpp is a pointer to the bytes, *sizep is the count.
476  * If *cpp is NULL maxsize bytes are allocated
477  */
478 bool_t
479 xdr_bytes(xdrs, cpp, sizep, maxsize)
480         register XDR *xdrs;
481         char **cpp;
482         register u_int *sizep;
483         u_int maxsize;
484 {
485         register char *sp = *cpp;  /* sp is the actual string pointer */
486         register u_int nodesize;
487
488         /*
489          * first deal with the length since xdr bytes are counted
490          */
491         if (! xdr_u_int(xdrs, sizep)) {
492                 return (FALSE);
493         }
494         nodesize = *sizep;
495         if ((nodesize > maxsize) && (xdrs->x_op != XDR_FREE)) {
496                 return (FALSE);
497         }
498
499         /*
500          * now deal with the actual bytes
501          */
502         switch (xdrs->x_op) {
503
504         case XDR_DECODE:
505                 if (nodesize == 0) {
506                         return (TRUE);
507                 }
508                 if (sp == NULL) {
509                         *cpp = sp = (char *)mem_alloc(nodesize);
510                 }
511                 if (sp == NULL) {
512 #ifdef WIN32
513                         nt_rpc_report("xdr_bytes: out of memory\n");
514 #else
515                         (void) fprintf(stderr, "xdr_bytes: out of memory\n");
516 #endif
517                         return (FALSE);
518                 }
519                 /* fall into ... */
520
521         case XDR_ENCODE:
522                 return (xdr_opaque(xdrs, sp, nodesize));
523
524         case XDR_FREE:
525                 if (sp != NULL) {
526                         mem_free(sp, nodesize);
527                         *cpp = NULL;
528                 }
529                 return (TRUE);
530         }
531         return (FALSE);
532 }
533
534 /*
535  * Implemented here due to commonality of the object.
536  */
537 bool_t
538 xdr_netobj(xdrs, np)
539         XDR *xdrs;
540         struct netobj *np;
541 {
542
543         return (xdr_bytes(xdrs, &np->n_bytes, &np->n_len, MAX_NETOBJ_SZ));
544 }
545
546 /*
547  * XDR a descriminated union
548  * Support routine for discriminated unions.
549  * You create an array of xdrdiscrim structures, terminated with
550  * an entry with a null procedure pointer.  The routine gets
551  * the discriminant value and then searches the array of xdrdiscrims
552  * looking for that value.  It calls the procedure given in the xdrdiscrim
553  * to handle the discriminant.  If there is no specific routine a default
554  * routine may be called.
555  * If there is no specific or default routine an error is returned.
556  */
557 bool_t
558 xdr_union(xdrs, dscmp, unp, choices, dfault)
559         register XDR *xdrs;
560         enum_t *dscmp;          /* enum to decide which arm to work on */
561         char *unp;              /* the union itself */
562         struct xdr_discrim *choices;    /* [value, xdr proc] for each arm */
563         xdrproc_t dfault;       /* default xdr routine */
564 {
565         register enum_t dscm;
566
567         /*
568          * we deal with the discriminator;  it's an enum
569          */
570         if (! xdr_enum(xdrs, dscmp)) {
571                 return (FALSE);
572         }
573         dscm = *dscmp;
574
575         /*
576          * search choices for a value that matches the discriminator.
577          * if we find one, execute the xdr routine for that value.
578          */
579         for (; choices->proc != NULL_xdrproc_t; choices++) {
580                 if (choices->value == dscm)
581                         return ((*(choices->proc))(xdrs, unp, LASTUNSIGNED));
582         }
583
584         /*
585          * no match - execute the default xdr routine if there is one
586          */
587         return ((dfault == NULL_xdrproc_t) ? FALSE :
588             (*dfault)(xdrs, unp, LASTUNSIGNED));
589 }
590
591
592 /*
593  * Non-portable xdr primitives.
594  * Care should be taken when moving these routines to new architectures.
595  */
596
597
598 /*
599  * XDR null terminated ASCII strings
600  * xdr_string deals with "C strings" - arrays of bytes that are
601  * terminated by a NULL character.  The parameter cpp references a
602  * pointer to storage; If the pointer is null, then the necessary
603  * storage is allocated.  The last parameter is the max allowed length
604  * of the string as specified by a protocol.
605  */
606 bool_t
607 xdr_string(xdrs, cpp, maxsize)
608         register XDR *xdrs;
609         char **cpp;
610         u_int maxsize;
611 {
612         register char *sp = *cpp;  /* sp is the actual string pointer */
613         u_int size;
614         u_int nodesize;
615
616         /*
617          * first deal with the length since xdr strings are counted-strings
618          */
619         switch (xdrs->x_op) {
620         case XDR_FREE:
621                 if (sp == NULL) {
622                         return(TRUE);   /* already free */
623                 }
624                 /* fall through... */
625         case XDR_ENCODE:
626                 size = strlen(sp);
627                 break;
628         }
629         if (! xdr_u_int(xdrs, &size)) {
630                 return (FALSE);
631         }
632         if (size > maxsize) {
633                 return (FALSE);
634         }
635         nodesize = size + 1;
636
637         /*
638          * now deal with the actual bytes
639          */
640         switch (xdrs->x_op) {
641
642         case XDR_DECODE:
643                 if (nodesize == 0) {
644                         return (TRUE);
645                 }
646                 if (sp == NULL)
647                         *cpp = sp = (char *)mem_alloc(nodesize);
648                 if (sp == NULL) {
649 #ifdef WIN32
650                         nt_rpc_report("xdr_string: out of memory\n");
651 #else
652                         (void) fprintf(stderr, "xdr_string: out of memory\n");
653 #endif
654                         return (FALSE);
655                 }
656                 sp[size] = 0;
657                 /* fall into ... */
658
659         case XDR_ENCODE:
660                 return (xdr_opaque(xdrs, sp, size));
661
662         case XDR_FREE:
663                 mem_free(sp, nodesize);
664                 *cpp = NULL;
665                 return (TRUE);
666         }
667         return (FALSE);
668 }
669
670 /*
671  * Wrapper for xdr_string that can be called directly from
672  * routines like clnt_call
673  */
674 bool_t
675 xdr_wrapstring(xdrs, cpp)
676         XDR *xdrs;
677         char **cpp;
678 {
679         if (xdr_string(xdrs, cpp, LASTUNSIGNED)) {
680                 return (TRUE);
681         }
682         return (FALSE);
683 }