rx: Tidy header includes
[openafs.git] / src / rx / 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
30 #include <afsconfig.h>
31 #include <afs/param.h>
32
33 #ifndef KERNEL
34 # include <roken.h>
35 #endif
36
37
38 /*
39  * xdr.c, Generic XDR routines implementation.
40  *
41  * Copyright (C) 1984, Sun Microsystems, Inc.
42  *
43  * These are the "generic" xdr routines used to serialize and de-serialize
44  * most common data items.  See xdr.h for more info on the interface to
45  * xdr.
46  */
47
48 #ifndef NeXT
49
50 #if defined(KERNEL) && !defined(UKERNEL)
51 #include <sys/param.h>
52 #ifndef AFS_LINUX20_ENV
53 #include <sys/systm.h>
54 #endif
55 #endif
56 #include "xdr.h"
57 #include "rx.h"
58
59 /*
60  * constants specific to the xdr "protocol"
61  */
62 #define XDR_FALSE       ((afs_int32) 0)
63 #define XDR_TRUE        ((afs_int32) 1)
64 #define LASTUNSIGNED    ((u_int) 0-1)
65
66 /*
67  * for unit alignment
68  */
69
70
71 /*
72  * XDR nothing
73  */
74 bool_t
75 xdr_void(void)
76 {
77     return (TRUE);
78 }
79
80 /*
81  * XDR integers
82  */
83 bool_t
84 xdr_int(XDR * xdrs, int *ip)
85 {
86     afs_int32 l;
87
88     switch (xdrs->x_op) {
89
90     case XDR_ENCODE:
91         l = (afs_int32) * ip;
92         return (XDR_PUTINT32(xdrs, &l));
93
94     case XDR_DECODE:
95         if (!XDR_GETINT32(xdrs, &l)) {
96             return (FALSE);
97         }
98         *ip = (int)l;
99         return (TRUE);
100
101     case XDR_FREE:
102         return (TRUE);
103     }
104     return (FALSE);
105 }
106
107 /*
108  * XDR unsigned integers
109  */
110 bool_t
111 xdr_u_int(XDR * xdrs, u_int * uip)
112 {
113     afs_uint32 l;
114
115     switch (xdrs->x_op) {
116
117     case XDR_ENCODE:
118         l = (afs_uint32) * uip;
119         return (XDR_PUTINT32(xdrs, (afs_int32 *) &l));
120
121     case XDR_DECODE:
122         if (!XDR_GETINT32(xdrs, (afs_int32 *) &l)) {
123             return (FALSE);
124         }
125         *uip = (u_int) l;
126         return (TRUE);
127
128     case XDR_FREE:
129         return (TRUE);
130     }
131     return (FALSE);
132 }
133
134
135 /*
136  * XDR long integers
137  */
138 bool_t
139 xdr_long(XDR * xdrs, long *lp)
140 {
141     afs_int32 l;
142
143     switch (xdrs->x_op) {
144
145     case XDR_ENCODE:
146         l = (afs_int32) * lp;
147         return (XDR_PUTINT32(xdrs, &l));
148
149     case XDR_DECODE:
150         if (!XDR_GETINT32(xdrs, &l)) {
151             return (FALSE);
152         }
153         *lp = (long)l;
154         return (TRUE);
155
156     case XDR_FREE:
157         return (TRUE);
158     }
159     return (FALSE);
160 }
161
162 /*
163  * XDR unsigned long integers
164  */
165 bool_t
166 xdr_u_long(XDR * xdrs, u_long * ulp)
167 {
168     afs_uint32 l;
169
170     switch (xdrs->x_op) {
171
172     case XDR_ENCODE:
173         l = (afs_uint32) * ulp;
174         return (XDR_PUTINT32(xdrs, (afs_int32 *)&l));
175
176     case XDR_DECODE:
177         if (!XDR_GETINT32(xdrs, (afs_int32 *)&l)) {
178             return (FALSE);
179         }
180         *ulp = (u_long) l;
181         return (TRUE);
182
183     case XDR_FREE:
184         return (TRUE);
185     }
186     return (FALSE);
187 }
188
189
190 /*
191  * XDR chars
192  */
193 bool_t
194 xdr_char(XDR * xdrs, char *sp)
195 {
196     afs_int32 l;
197
198     switch (xdrs->x_op) {
199
200     case XDR_ENCODE:
201         l = (afs_int32) * sp;
202         return (XDR_PUTINT32(xdrs, &l));
203
204     case XDR_DECODE:
205         if (!XDR_GETINT32(xdrs, &l)) {
206             return (FALSE);
207         }
208         *sp = (char)l;
209         return (TRUE);
210
211     case XDR_FREE:
212         return (TRUE);
213     }
214     return (FALSE);
215 }
216
217 /*
218  * XDR unsigned chars
219  */
220 bool_t
221 xdr_u_char(XDR * xdrs, u_char * usp)
222 {
223     afs_uint32 l;
224
225     switch (xdrs->x_op) {
226
227     case XDR_ENCODE:
228         l = (afs_uint32) * usp;
229         return (XDR_PUTINT32(xdrs, (afs_int32 *)&l));
230
231     case XDR_DECODE:
232         if (!XDR_GETINT32(xdrs, (afs_int32 *)&l)) {
233             return (FALSE);
234         }
235         *usp = (u_char) l;
236         return (TRUE);
237
238     case XDR_FREE:
239         return (TRUE);
240     }
241     return (FALSE);
242 }
243
244
245 /*
246  * XDR short integers
247  */
248 bool_t
249 xdr_short(XDR * xdrs, short *sp)
250 {
251     afs_int32 l;
252
253     switch (xdrs->x_op) {
254
255     case XDR_ENCODE:
256         l = (afs_int32) * sp;
257         return (XDR_PUTINT32(xdrs, &l));
258
259     case XDR_DECODE:
260         if (!XDR_GETINT32(xdrs, &l)) {
261             return (FALSE);
262         }
263         *sp = (short)l;
264         return (TRUE);
265
266     case XDR_FREE:
267         return (TRUE);
268     }
269     return (FALSE);
270 }
271
272 /*
273  * XDR unsigned short integers
274  */
275 bool_t
276 xdr_u_short(XDR * xdrs, u_short * usp)
277 {
278     afs_uint32 l;
279
280     switch (xdrs->x_op) {
281
282     case XDR_ENCODE:
283         l = (afs_uint32) * usp;
284         return (XDR_PUTINT32(xdrs, (afs_int32 *)&l));
285
286     case XDR_DECODE:
287         if (!XDR_GETINT32(xdrs, (afs_int32 *)&l)) {
288             return (FALSE);
289         }
290         *usp = (u_short) l;
291         return (TRUE);
292
293     case XDR_FREE:
294         return (TRUE);
295     }
296     return (FALSE);
297 }
298
299
300 /*
301  * XDR booleans
302  */
303 bool_t
304 xdr_bool(XDR * xdrs, bool_t * bp)
305 {
306     afs_int32 lb;
307
308     switch (xdrs->x_op) {
309
310     case XDR_ENCODE:
311         lb = *bp ? XDR_TRUE : XDR_FALSE;
312         return (XDR_PUTINT32(xdrs, &lb));
313
314     case XDR_DECODE:
315         if (!XDR_GETINT32(xdrs, &lb)) {
316             return (FALSE);
317         }
318         *bp = (lb == XDR_FALSE) ? FALSE : TRUE;
319         return (TRUE);
320
321     case XDR_FREE:
322         return (TRUE);
323     }
324     return (FALSE);
325 }
326
327 /*
328  * XDR enumerations
329  */
330 bool_t
331 xdr_enum(XDR * xdrs, enum_t * ep)
332 {
333     enum sizecheck { SIZEVAL }; /* used to find the size of an enum */
334
335     /*
336      * enums are treated as ints
337      */
338
339     return (xdr_long(xdrs, (long *)ep));
340
341 }
342
343 /*
344  * XDR opaque data
345  * Allows the specification of a fixed size sequence of opaque bytes.
346  * cp points to the opaque object and cnt gives the byte length.
347  */
348 bool_t
349 xdr_opaque(XDR * xdrs, caddr_t cp, u_int cnt)
350 {
351     u_int rndup;
352     int crud[BYTES_PER_XDR_UNIT];
353     char xdr_zero[BYTES_PER_XDR_UNIT] = { 0, 0, 0, 0 };
354
355     /*
356      * if no data we are done
357      */
358     if (cnt == 0)
359         return (TRUE);
360
361     /*
362      * round byte count to full xdr units
363      */
364     rndup = cnt % BYTES_PER_XDR_UNIT;
365     if (rndup > 0)
366         rndup = BYTES_PER_XDR_UNIT - rndup;
367
368     if (xdrs->x_op == XDR_DECODE) {
369         if (!XDR_GETBYTES(xdrs, cp, cnt)) {
370             return (FALSE);
371         }
372         if (rndup == 0)
373             return (TRUE);
374         return (XDR_GETBYTES(xdrs, (caddr_t)crud, rndup));
375     }
376
377     if (xdrs->x_op == XDR_ENCODE) {
378         if (!XDR_PUTBYTES(xdrs, cp, cnt)) {
379             return (FALSE);
380         }
381         if (rndup == 0)
382             return (TRUE);
383         return (XDR_PUTBYTES(xdrs, xdr_zero, rndup));
384     }
385
386     if (xdrs->x_op == XDR_FREE) {
387         return (TRUE);
388     }
389
390     return (FALSE);
391 }
392
393 /*
394  * XDR counted bytes
395  * *cpp is a pointer to the bytes, *sizep is the count.
396  * If *cpp is NULL maxsize bytes are allocated
397  */
398 bool_t
399 xdr_bytes(XDR * xdrs, char **cpp, u_int * sizep,
400           u_int maxsize)
401 {
402     char *sp = *cpp;    /* sp is the actual string pointer */
403     u_int nodesize;
404
405     /*
406      * first deal with the length since xdr bytes are counted
407      */
408     if (!xdr_u_int(xdrs, sizep)) {
409         return (FALSE);
410     }
411     nodesize = *sizep;
412     if ((nodesize > maxsize) && (xdrs->x_op != XDR_FREE)) {
413         return (FALSE);
414     }
415
416     /*
417      * now deal with the actual bytes
418      */
419     switch (xdrs->x_op) {
420
421     case XDR_DECODE:
422         if (sp == NULL) {
423             *cpp = sp = (char *)osi_alloc(nodesize);
424         }
425         if (sp == NULL) {
426             return (FALSE);
427         }
428         /* fall into ... */
429
430     case XDR_ENCODE:
431         return (xdr_opaque(xdrs, sp, nodesize));
432
433     case XDR_FREE:
434         if (sp != NULL) {
435             osi_free(sp, nodesize);
436             *cpp = NULL;
437         }
438         return (TRUE);
439     }
440     return (FALSE);
441 }
442
443 /*
444  * XDR a descriminated union
445  * Support routine for discriminated unions.
446  * You create an array of xdrdiscrim structures, terminated with
447  * an entry with a null procedure pointer.  The routine gets
448  * the discriminant value and then searches the array of xdrdiscrims
449  * looking for that value.  It calls the procedure given in the xdrdiscrim
450  * to handle the discriminant.  If there is no specific routine a default
451  * routine may be called.
452  * If there is no specific or default routine an error is returned.
453  */
454 /*
455         enum_t *dscmp;          * enum to decide which arm to work on *
456         caddr_t unp;            * the union itself *
457         struct xdr_discrim *choices;    * [value, xdr proc] for each arm *
458         xdrproc_t dfault;       * default xdr routine *
459 */
460 bool_t
461 xdr_union(XDR * xdrs, enum_t * dscmp, caddr_t unp,
462           struct xdr_discrim * choices, xdrproc_t dfault)
463 {
464     enum_t dscm;
465
466     /*
467      * we deal with the discriminator;  it's an enum
468      */
469     if (!xdr_enum(xdrs, dscmp)) {
470         return (FALSE);
471     }
472     dscm = *dscmp;
473
474     /*
475      * search choices for a value that matches the discriminator.
476      * if we find one, execute the xdr routine for that value.
477      */
478     for (; choices->proc != NULL_xdrproc_t; choices++) {
479         if (choices->value == dscm)
480             return ((*(choices->proc)) (xdrs, unp, LASTUNSIGNED));
481     }
482
483     /*
484      * no match - execute the default xdr routine if there is one
485      */
486     return ((dfault == NULL_xdrproc_t) ? FALSE : (*dfault) (xdrs, unp,
487                                                             LASTUNSIGNED));
488 }
489
490
491 /*
492  * Non-portable xdr primitives.
493  * Care should be taken when moving these routines to new architectures.
494  */
495
496
497 /*
498  * XDR null terminated ASCII strings
499  * xdr_string deals with "C strings" - arrays of bytes that are
500  * terminated by a NULL character.  The parameter cpp references a
501  * pointer to storage; If the pointer is null, then the necessary
502  * storage is allocated.  The last parameter is the max allowed length
503  * of the string as specified by a protocol.
504  */
505 bool_t
506 xdr_string(XDR * xdrs, char **cpp, u_int maxsize)
507 {
508     char *sp = *cpp;    /* sp is the actual string pointer */
509     u_int size;
510     u_int nodesize;
511
512     /* FIXME: this does not look correct: MSVC 6 computes -2 here */
513     if (maxsize > ((~0) >> 1) - 1)
514         maxsize = ((~0) >> 1) - 1;
515
516     /*
517      * first deal with the length since xdr strings are counted-strings
518      */
519     switch (xdrs->x_op) {
520     case XDR_FREE:
521         if (sp == NULL) {
522             return (TRUE);      /* already free */
523         }
524         /* Fall through */
525     case XDR_ENCODE:
526         size = strlen(sp);
527         break;
528     case XDR_DECODE:
529         break;
530     }
531
532     if (!xdr_u_int(xdrs, &size)) {
533         return (FALSE);
534     }
535     if (size > maxsize) {
536         return (FALSE);
537     }
538     nodesize = size + 1;
539
540     /*
541      * now deal with the actual bytes
542      */
543     switch (xdrs->x_op) {
544
545     case XDR_DECODE:
546         if (sp == NULL)
547             *cpp = sp = (char *)osi_alloc(nodesize);
548         if (sp == NULL) {
549             return (FALSE);
550         }
551         sp[size] = 0;
552         /* fall into ... */
553
554     case XDR_ENCODE:
555         return (xdr_opaque(xdrs, sp, size));
556
557     case XDR_FREE:
558         if (sp != NULL) {
559             osi_free(sp, nodesize);
560             *cpp = NULL;
561         }
562         return (TRUE);
563     }
564     return (FALSE);
565 }
566
567 /*
568  * Wrapper for xdr_string that can be called directly from
569  * routines like clnt_call
570  */
571 #ifndef KERNEL
572 bool_t
573 xdr_wrapstring(XDR * xdrs, char **cpp)
574 {
575     if (xdr_string(xdrs, cpp, BUFSIZ)) {
576         return (TRUE);
577     }
578     return (FALSE);
579 }
580 #endif
581
582 void *
583 xdr_alloc(afs_int32 size)
584 {
585     return osi_alloc(size);
586 }
587
588 void
589 xdr_free(xdrproc_t proc, void *obj)
590 {
591     XDR x;
592
593     x.x_op = XDR_FREE;
594
595     /* See note in xdr.h for the method behind this madness */
596 #if defined(AFS_I386_LINUX26_ENV) && defined(KERNEL) && !defined(UKERNEL)
597     (*proc)(&x, obj, 0);
598 #else
599     (*proc)(&x, obj);
600 #endif
601 }
602 #endif /* NeXT */