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