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