source: rtems/cpukit/librpc/src/xdr/xdr.c @ 33a105fb

4.115
Last change on this file since 33a105fb was 37da47a, checked in by Ralf Corsepius <ralf.corsepius@…>, on 03/28/10 at 02:40:16

Add HAVE_CONFIG_H support to let files receive configure defines.

  • Property mode set to 100644
File size: 14.5 KB
Line 
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#if defined(LIBC_SCCS) && !defined(lint)
31/*static char *sccsid = "from: @(#)xdr.c 1.35 87/08/12";*/
32/*static char *sccsid = "from: @(#)xdr.c        2.1 88/07/29 4.0 RPCSRC";*/
33static char *rcsid = "$FreeBSD: src/lib/libc/xdr/xdr.c,v 1.9 1999/08/28 00:02:55 peter Exp $";
34#endif
35
36/*
37 * xdr.c, Generic XDR routines implementation.
38 *
39 * Copyright (C) 1986, Sun Microsystems, Inc.
40 *
41 * These are the "generic" xdr routines used to serialize and de-serialize
42 * most common data items.  See xdr.h for more info on the interface to
43 * xdr.
44 */
45
46#ifdef HAVE_CONFIG_H
47#include "config.h"
48#endif
49
50#include <stdio.h>
51#include <stdlib.h>
52#include <string.h>
53
54#include <rpc/types.h>
55#include <rpc/xdr.h>
56
57#if defined(__rtems__)
58#define warnx(msg) fprintf(stderr, msg "\n");
59#endif
60
61/*
62 * constants specific to the xdr "protocol"
63 */
64#define XDR_FALSE       ((long) 0)
65#define XDR_TRUE        ((long) 1)
66#define LASTUNSIGNED    ((u_int) 0-1)
67
68/*
69 * for unit alignment
70 */
71static const char xdr_zero[BYTES_PER_XDR_UNIT] = { 0, 0, 0, 0 };
72
73/*
74 * Free a data structure using XDR
75 * Not a filter, but a convenient utility nonetheless
76 */
77void
78xdr_free(
79        xdrproc_t proc,
80        char *objp)
81{
82        XDR x;
83
84        x.x_op = XDR_FREE;
85        (*proc)(&x, objp);
86}
87
88/*
89 * XDR nothing
90 */
91bool_t
92xdr_void(void)
93{
94
95        return (TRUE);
96}
97
98
99/*
100 * XDR integers
101 */
102bool_t
103xdr_int(
104        XDR *xdrs,
105        int *ip)
106{
107        long l;
108
109        switch (xdrs->x_op) {
110
111        case XDR_ENCODE:
112                l = (long) *ip;
113                return (XDR_PUTLONG(xdrs, &l));
114
115        case XDR_DECODE:
116                if (!XDR_GETLONG(xdrs, &l)) {
117                        return (FALSE);
118                }
119                *ip = (int) l;
120                return (TRUE);
121
122        case XDR_FREE:
123                return (TRUE);
124        }
125        /* NOTREACHED */
126        return (FALSE);
127}
128
129/*
130 * XDR unsigned integers
131 */
132bool_t
133xdr_u_int(
134        XDR *xdrs,
135        u_int *up)
136{
137        u_long l;
138
139        switch (xdrs->x_op) {
140
141        case XDR_ENCODE:
142                l = (u_long) *up;
143                return (XDR_PUTLONG(xdrs, (long *)&l));
144
145        case XDR_DECODE:
146                if (!XDR_GETLONG(xdrs, (long *)&l)) {
147                        return (FALSE);
148                }
149                *up = (u_int) l;
150                return (TRUE);
151
152        case XDR_FREE:
153                return (TRUE);
154        }
155        /* NOTREACHED */
156        return (FALSE);
157}
158
159
160/*
161 * XDR long integers
162 * same as xdr_u_long - open coded to save a proc call!
163 */
164bool_t
165xdr_long(
166        XDR *xdrs,
167        long *lp)
168{
169        switch (xdrs->x_op) {
170        case XDR_ENCODE:
171                return (XDR_PUTLONG(xdrs, lp));
172        case XDR_DECODE:
173                return (XDR_GETLONG(xdrs, lp));
174        case XDR_FREE:
175                return (TRUE);
176        }
177        /* NOTREACHED */
178        return (FALSE);
179}
180
181/*
182 * XDR unsigned long integers
183 * same as xdr_long - open coded to save a proc call!
184 */
185bool_t
186xdr_u_long(
187        XDR *xdrs,
188        u_long *ulp)
189{
190        switch (xdrs->x_op) {
191        case XDR_ENCODE:
192                return (XDR_PUTLONG(xdrs, (long *)ulp));
193        case XDR_DECODE:
194                return (XDR_GETLONG(xdrs, (long *)ulp));
195        case XDR_FREE:
196                return (TRUE);
197        }
198        /* NOTREACHED */
199        return (FALSE);
200}
201
202
203/*
204 * XDR 32-bit integers
205 * same as xdr_u_int32_t - open coded to save a proc call!
206 */
207bool_t
208xdr_int32_t(
209        XDR *xdrs,
210        int32_t *int32_p)
211{
212        long l;
213
214        switch (xdrs->x_op) {
215
216        case XDR_ENCODE:
217                l = (long) *int32_p;
218                return (XDR_PUTLONG(xdrs, &l));
219
220        case XDR_DECODE:
221                if (!XDR_GETLONG(xdrs, &l)) {
222                        return (FALSE);
223                }
224                *int32_p = (int32_t) l;
225                return (TRUE);
226
227        case XDR_FREE:
228                return (TRUE);
229        }
230        /* NOTREACHED */
231        return (FALSE);
232}
233
234/*
235 * XDR unsigned 32-bit integers
236 * same as xdr_int32_t - open coded to save a proc call!
237 */
238bool_t
239xdr_u_int32_t(
240        XDR *xdrs,
241        u_int32_t *u_int32_p)
242{
243        u_long l;
244
245        switch (xdrs->x_op) {
246
247        case XDR_ENCODE:
248                l = (u_long) *u_int32_p;
249                return (XDR_PUTLONG(xdrs, (long *)&l));
250
251        case XDR_DECODE:
252                if (!XDR_GETLONG(xdrs, (long *)&l)) {
253                        return (FALSE);
254                }
255                *u_int32_p = (u_int32_t) l;
256                return (TRUE);
257
258        case XDR_FREE:
259                return (TRUE);
260        }
261        return (FALSE);
262}
263
264/*
265 * XDR short integers
266 */
267bool_t
268xdr_short(
269        XDR *xdrs,
270        short *sp)
271{
272        long l;
273
274        switch (xdrs->x_op) {
275
276        case XDR_ENCODE:
277                l = (long) *sp;
278                return (XDR_PUTLONG(xdrs, &l));
279
280        case XDR_DECODE:
281                if (!XDR_GETLONG(xdrs, &l)) {
282                        return (FALSE);
283                }
284                *sp = (short) l;
285                return (TRUE);
286
287        case XDR_FREE:
288                return (TRUE);
289        }
290        /* NOTREACHED */
291        return (FALSE);
292}
293
294/*
295 * XDR unsigned short integers
296 */
297bool_t
298xdr_u_short(
299        XDR *xdrs,
300        u_short *usp)
301{
302        u_long l;
303
304        switch (xdrs->x_op) {
305
306        case XDR_ENCODE:
307                l = (u_long) *usp;
308                return (XDR_PUTLONG(xdrs, (long *)&l));
309
310        case XDR_DECODE:
311                if (!XDR_GETLONG(xdrs, (long *)&l)) {
312                        return (FALSE);
313                }
314                *usp = (u_short) l;
315                return (TRUE);
316
317        case XDR_FREE:
318                return (TRUE);
319        }
320        /* NOTREACHED */
321        return (FALSE);
322}
323
324
325/*
326 * XDR 16-bit integers
327 */
328bool_t
329xdr_int16_t(
330        XDR *xdrs,
331        int16_t *int16_p)
332{
333        long l;
334
335        switch (xdrs->x_op) {
336
337        case XDR_ENCODE:
338                l = (long) *int16_p;
339                return (XDR_PUTLONG(xdrs, &l));
340
341        case XDR_DECODE:
342                if (!XDR_GETLONG(xdrs, &l)) {
343                        return (FALSE);
344                }
345                *int16_p = (int16_t) l;
346                return (TRUE);
347
348        case XDR_FREE:
349                return (TRUE);
350        }
351        /* NOTREACHED */
352        return (FALSE);
353}
354
355/*
356 * XDR unsigned 16-bit integers
357 */
358bool_t
359xdr_u_int16_t(
360        XDR *xdrs,
361        u_int16_t *u_int16_p)
362{
363        u_long l;
364
365        switch (xdrs->x_op) {
366
367        case XDR_ENCODE:
368                l = (u_long) *u_int16_p;
369                return (XDR_PUTLONG(xdrs, (long *)&l));
370
371        case XDR_DECODE:
372                if (!XDR_GETLONG(xdrs, (long *)&l)) {
373                        return (FALSE);
374                }
375                *u_int16_p = (u_int16_t) l;
376                return (TRUE);
377
378        case XDR_FREE:
379                return (TRUE);
380        }
381        /* NOTREACHED */
382        return (FALSE);
383}
384
385
386/*
387 * XDR a char
388 */
389bool_t
390xdr_char(
391        XDR *xdrs,
392        char *cp)
393{
394        int i;
395
396        i = (*cp);
397        if (!xdr_int(xdrs, &i)) {
398                return (FALSE);
399        }
400        *cp = i;
401        return (TRUE);
402}
403
404/*
405 * XDR an unsigned char
406 */
407bool_t
408xdr_u_char(
409        XDR *xdrs,
410        u_char *cp)
411{
412        u_int u;
413
414        u = (*cp);
415        if (!xdr_u_int(xdrs, &u)) {
416                return (FALSE);
417        }
418        *cp = u;
419        return (TRUE);
420}
421
422/*
423 * XDR booleans
424 */
425bool_t
426xdr_bool(
427        XDR *xdrs,
428        bool_t *bp)
429{
430        long lb;
431
432        switch (xdrs->x_op) {
433
434        case XDR_ENCODE:
435                lb = *bp ? XDR_TRUE : XDR_FALSE;
436                return (XDR_PUTLONG(xdrs, &lb));
437
438        case XDR_DECODE:
439                if (!XDR_GETLONG(xdrs, &lb)) {
440                        return (FALSE);
441                }
442                *bp = (lb == XDR_FALSE) ? FALSE : TRUE;
443                return (TRUE);
444
445        case XDR_FREE:
446                return (TRUE);
447        }
448        /* NOTREACHED */
449        return (FALSE);
450}
451
452/*
453 * XDR enumerations
454 */
455bool_t
456xdr_enum(
457        XDR *xdrs,
458        enum_t *ep)
459{
460#ifndef lint
461        enum sizecheck { SIZEVAL };     /* used to find the size of an enum */
462
463        /*
464         * enums are treated as ints
465         */
466        if (sizeof (enum sizecheck) == sizeof (long)) {
467                return (xdr_long(xdrs, (long *)ep));
468        } else if (sizeof (enum sizecheck) == sizeof (int)) {
469                return (xdr_int(xdrs, (int *)ep));
470        } else if (sizeof (enum sizecheck) == sizeof (short)) {
471                return (xdr_short(xdrs, (short *)ep));
472        } else {
473                return (FALSE);
474        }
475#else
476        (void) (xdr_short(xdrs, (short *)ep));
477        (void) (xdr_int(xdrs, (int *)ep));
478        return (xdr_long(xdrs, (long *)ep));
479#endif
480}
481
482/*
483 * XDR opaque data
484 * Allows the specification of a fixed size sequence of opaque bytes.
485 * cp points to the opaque object and cnt gives the byte length.
486 */
487bool_t
488xdr_opaque(
489        XDR *xdrs,
490        caddr_t cp,
491        u_int cnt)
492{
493        u_int rndup;
494        static int crud[BYTES_PER_XDR_UNIT];
495
496        /*
497         * if no data we are done
498         */
499        if (cnt == 0)
500                return (TRUE);
501
502        /*
503         * round byte count to full xdr units
504         */
505        rndup = cnt % BYTES_PER_XDR_UNIT;
506        if (rndup > 0)
507                rndup = BYTES_PER_XDR_UNIT - rndup;
508
509        if (xdrs->x_op == XDR_DECODE) {
510                if (!XDR_GETBYTES(xdrs, cp, cnt)) {
511                        return (FALSE);
512                }
513                if (rndup == 0)
514                        return (TRUE);
515                return (XDR_GETBYTES(xdrs, (caddr_t)crud, rndup));
516        }
517
518        if (xdrs->x_op == XDR_ENCODE) {
519                if (!XDR_PUTBYTES(xdrs, cp, cnt)) {
520                        return (FALSE);
521                }
522                if (rndup == 0)
523                        return (TRUE);
524                return (XDR_PUTBYTES(xdrs, xdr_zero, rndup));
525        }
526
527        if (xdrs->x_op == XDR_FREE) {
528                return (TRUE);
529        }
530
531        return (FALSE);
532}
533
534/*
535 * XDR counted bytes
536 * *cpp is a pointer to the bytes, *sizep is the count.
537 * If *cpp is NULL maxsize bytes are allocated
538 */
539bool_t
540xdr_bytes(
541        XDR *xdrs,
542        char **cpp,
543        u_int *sizep,
544        u_int maxsize)
545{
546        char *sp = *cpp;  /* sp is the actual string pointer */
547        u_int nodesize;
548
549        /*
550         * first deal with the length since xdr bytes are counted
551         */
552        if (! xdr_u_int(xdrs, sizep)) {
553                return (FALSE);
554        }
555        nodesize = *sizep;
556        if ((nodesize > maxsize) && (xdrs->x_op != XDR_FREE)) {
557                return (FALSE);
558        }
559
560        /*
561         * now deal with the actual bytes
562         */
563        switch (xdrs->x_op) {
564
565        case XDR_DECODE:
566                if (nodesize == 0) {
567                        return (TRUE);
568                }
569                if (sp == NULL) {
570                        *cpp = sp = mem_alloc(nodesize);
571                }
572                if (sp == NULL) {
573                        warnx("xdr_bytes: out of memory");
574                        return (FALSE);
575                }
576                /* FALLTHROUGH */
577
578        case XDR_ENCODE:
579                return (xdr_opaque(xdrs, sp, nodesize));
580
581        case XDR_FREE:
582                if (sp != NULL) {
583                        mem_free(sp, nodesize);
584                        *cpp = NULL;
585                }
586                return (TRUE);
587        }
588        /* NOTREACHED */
589        return (FALSE);
590}
591
592/*
593 * Implemented here due to commonality of the object.
594 */
595bool_t
596xdr_netobj(
597        XDR *xdrs,
598        struct netobj *np)
599{
600
601        return (xdr_bytes(xdrs, &np->n_bytes, &np->n_len, MAX_NETOBJ_SZ));
602}
603
604/*
605 * XDR a descriminated union
606 * Support routine for discriminated unions.
607 * You create an array of xdrdiscrim structures, terminated with
608 * an entry with a null procedure pointer.  The routine gets
609 * the discriminant value and then searches the array of xdrdiscrims
610 * looking for that value.  It calls the procedure given in the xdrdiscrim
611 * to handle the discriminant.  If there is no specific routine a default
612 * routine may be called.
613 * If there is no specific or default routine an error is returned.
614 */
615bool_t
616xdr_union(
617        XDR *xdrs,
618        enum_t *dscmp,          /* enum to decide which arm to work on */
619        char *unp,              /* the union itself */
620        const struct xdr_discrim *choices,      /* [value, xdr proc] for each arm */
621        xdrproc_t dfault)       /* default xdr routine */
622{
623        enum_t dscm;
624
625        /*
626         * we deal with the discriminator;  it's an enum
627         */
628        if (! xdr_enum(xdrs, dscmp)) {
629                return (FALSE);
630        }
631        dscm = *dscmp;
632
633        /*
634         * search choices for a value that matches the discriminator.
635         * if we find one, execute the xdr routine for that value.
636         */
637        for (; choices->proc != NULL_xdrproc_t; choices++) {
638                if (choices->value == dscm)
639                        return ((*(choices->proc))(xdrs, unp, LASTUNSIGNED));
640        }
641
642        /*
643         * no match - execute the default xdr routine if there is one
644         */
645        return ((dfault == NULL_xdrproc_t) ? FALSE :
646            (*dfault)(xdrs, unp, LASTUNSIGNED));
647}
648
649
650/*
651 * Non-portable xdr primitives.
652 * Care should be taken when moving these routines to new architectures.
653 */
654
655
656/*
657 * XDR null terminated ASCII strings
658 * xdr_string deals with "C strings" - arrays of bytes that are
659 * terminated by a NULL character.  The parameter cpp references a
660 * pointer to storage; If the pointer is null, then the necessary
661 * storage is allocated.  The last parameter is the max allowed length
662 * of the string as specified by a protocol.
663 */
664bool_t
665xdr_string(
666        XDR *xdrs,
667        char **cpp,
668        u_int maxsize)
669{
670        char *sp = *cpp;  /* sp is the actual string pointer */
671        u_int size = 0;
672        u_int nodesize;
673
674        /*
675         * first deal with the length since xdr strings are counted-strings
676         */
677        switch (xdrs->x_op) {
678        case XDR_FREE:
679                if (sp == NULL) {
680                        return(TRUE);   /* already free */
681                }
682                /* FALLTHROUGH */
683        case XDR_ENCODE:
684                size = strlen(sp);
685                break;
686        case XDR_DECODE:
687                break;
688        }
689        if (! xdr_u_int(xdrs, &size)) {
690                return (FALSE);
691        }
692        if (size > maxsize) {
693                return (FALSE);
694        }
695        nodesize = size + 1;
696
697        /*
698         * now deal with the actual bytes
699         */
700        switch (xdrs->x_op) {
701
702        case XDR_DECODE:
703                if (nodesize == 0) {
704                        return (TRUE);
705                }
706                if (sp == NULL)
707                        *cpp = sp = mem_alloc(nodesize);
708                if (sp == NULL) {
709                        warnx("xdr_string: out of memory");
710                        return (FALSE);
711                }
712                sp[size] = 0;
713                /* FALLTHROUGH */
714
715        case XDR_ENCODE:
716                return (xdr_opaque(xdrs, sp, size));
717
718        case XDR_FREE:
719                mem_free(sp, nodesize);
720                *cpp = NULL;
721                return (TRUE);
722        }
723        /* NOTREACHED */
724        return (FALSE);
725}
726
727/*
728 * Wrapper for xdr_string that can be called directly from
729 * routines like clnt_call
730 */
731bool_t
732xdr_wrapstring(
733        XDR *xdrs,
734        char **cpp)
735{
736        return xdr_string(xdrs, cpp, LASTUNSIGNED);
737}
738
739/*
740 * XDR 64-bit integers
741 */
742bool_t
743xdr_int64_t(
744        XDR *xdrs,
745        int64_t *int64_p)
746{
747        int64_t x;
748
749        switch (xdrs->x_op) {
750        case XDR_ENCODE:
751                return (xdr_opaque(xdrs, (caddr_t)int64_p, sizeof(int64_t)));
752        case XDR_DECODE:
753                if (!xdr_opaque(xdrs, (caddr_t)&x, sizeof x)) {
754                        return (FALSE);
755                }
756                *int64_p = x;
757                return (TRUE);
758        case XDR_FREE:
759                return (TRUE);
760        }
761        /* NOTREACHED */
762        return (FALSE);
763}
764
765
766/*
767 * XDR unsigned 64-bit integers
768 */
769bool_t
770xdr_u_int64_t(
771        XDR *xdrs,
772        u_int64_t *uint64_p)
773{
774        u_int64_t x;
775
776        switch (xdrs->x_op) {
777        case XDR_ENCODE:
778                return (xdr_opaque(xdrs, (caddr_t)uint64_p, sizeof(u_int64_t)));
779        case XDR_DECODE:
780                if (!xdr_opaque(xdrs, (caddr_t)&x, sizeof x)) {
781                        return (FALSE);
782                }
783                *uint64_p = x;
784                return (TRUE);
785        case XDR_FREE:
786                return (TRUE);
787        }
788        /* NOTREACHED */
789        return (FALSE);
790}
791
792/* FIXME: RTEMS does not support u_longlong_t and longlong_t, yet */
793#if !defined(__rtems__)
794/*
795 * XDR hypers
796 */
797bool_t
798xdr_hyper(xdrs, llp)
799        XDR *xdrs;
800        longlong_t *llp;
801{
802
803        /*
804         * Don't bother open-coding this; it's a fair amount of code.  Just
805         * call xdr_int64_t().
806         */
807        return (xdr_int64_t(xdrs, (int64_t *)llp));
808}
809
810
811/*
812 * XDR unsigned hypers
813 */
814bool_t
815xdr_u_hyper(xdrs, ullp)
816        XDR *xdrs;
817        u_longlong_t *ullp;
818{
819
820        /*
821         * Don't bother open-coding this; it's a fair amount of code.  Just
822         * call xdr_u_int64_t().
823         */
824        return (xdr_u_int64_t(xdrs, (u_int64_t *)ullp));
825}
826
827
828/*
829 * XDR longlong_t's
830 */
831bool_t
832xdr_longlong_t(xdrs, llp)
833        XDR *xdrs;
834        longlong_t *llp;
835{
836
837        /*
838         * Don't bother open-coding this; it's a fair amount of code.  Just
839         * call xdr_int64_t().
840         */
841        return (xdr_int64_t(xdrs, (int64_t *)llp));
842}
843
844
845/*
846 * XDR u_longlong_t's
847 */
848bool_t
849xdr_u_longlong_t(xdrs, ullp)
850        XDR *xdrs;
851        u_longlong_t *ullp;
852{
853
854        /*
855         * Don't bother open-coding this; it's a fair amount of code.  Just
856         * call xdr_u_int64_t().
857         */
858        return (xdr_u_int64_t(xdrs, (u_int64_t *)ullp));
859}
860#endif
Note: See TracBrowser for help on using the repository browser.