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