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