Home | History | Annotate | Download | only in librpc
      1 #include <rpc/rpc.h>
      2 #include <string.h>
      3 
      4 #define LASTUNSIGNED    ((u_int)((int)0-1))
      5 
      6 /*
      7  * Primitives for stuffing data into and retrieving data from an XDR
      8  */
      9 
     10 bool_t xdr_bytes (XDR *xdr, char **cpp, u_int *sizep, u_int maxsize)
     11 {
     12     switch(xdr->x_op) {
     13     case XDR_DECODE:
     14         if(!XDR_RECV_UINT(xdr, sizep) || *sizep > maxsize)
     15             return FALSE;
     16         if(*sizep == 0)
     17             return TRUE;
     18         if(*cpp == NULL)
     19             *cpp = (char *) mem_alloc(*sizep);
     20         if(*cpp == NULL) return FALSE;
     21         return XDR_RECV_BYTES(xdr, (uint8 *) *cpp, *sizep);
     22     case XDR_ENCODE:
     23         return (XDR_SEND_UINT(xdr, sizep) &&
     24                 *sizep <= maxsize &&
     25                 XDR_SEND_BYTES(xdr, (uint8 *) *cpp, *sizep));
     26     case XDR_FREE:
     27         if (*cpp) {
     28             mem_free(*cpp);
     29             *cpp = NULL;
     30         }
     31         return TRUE;
     32     default:
     33         break;
     34     }
     35     return FALSE;
     36 } /* xdr_bytes */
     37 
     38 bool_t xdr_send_enum (xdr_s_type *xdr, const void *value, uint32 size)
     39 {
     40     switch (size) {
     41     case 4:
     42         return XDR_SEND_INT32(xdr, (int32 *) value);
     43     case 2:
     44         return XDR_SEND_INT16(xdr, (int16 *) value);
     45     case 1:
     46         return XDR_SEND_INT8(xdr, (int8 *) value);
     47     default:
     48         return FALSE;
     49     }
     50 } /* xdr_send_enum */
     51 
     52 bool_t xdr_recv_enum (xdr_s_type *xdr, void *value, uint32 size)
     53 {
     54     switch (size) {
     55     case 4:
     56         return XDR_RECV_INT32(xdr, (int32 *) value);
     57     case 2:
     58         return XDR_RECV_INT16(xdr, (int16 *) value);
     59     case 1:
     60         return XDR_RECV_INT8(xdr, (int8 *) value);
     61     default:
     62         return FALSE;
     63     }
     64 } /* xdr_recv_enum */
     65 
     66 #include <stdio.h>
     67 
     68 bool_t xdr_enum (XDR *xdr, enum_t *ep)
     69 {
     70     switch(xdr->x_op) {
     71     case XDR_ENCODE:
     72         return XDR_SEND_INT32(xdr, (int32 *)ep);
     73     case XDR_DECODE:
     74         return XDR_RECV_INT32(xdr, (int32 *)ep);
     75     case XDR_FREE:
     76         return TRUE;
     77     default:
     78         break;
     79     }
     80     return FALSE;
     81 } /* xdr_enum */
     82 
     83 bool_t xdr_u_int (XDR *xdr, u_int *uip)
     84 {
     85     switch(xdr->x_op) {
     86     case XDR_ENCODE:
     87         return XDR_SEND_UINT32(xdr, (uint32 *) uip);
     88     case XDR_DECODE:
     89         return XDR_RECV_UINT32(xdr, (uint32 *) uip);
     90     case XDR_FREE:
     91         return TRUE;
     92     default:
     93         break;
     94     }
     95     return FALSE;
     96 } /* xdr_u_int */
     97 
     98 bool_t xdr_u_char (XDR *xdr, u_char *cp)
     99 {
    100     u_int u = (*cp);
    101     if (!xdr_u_int (xdr, &u))
    102         return FALSE;
    103     *cp = (u_char) u;
    104     return TRUE;
    105 } /* xdr_u_char */
    106 
    107 bool_t xdr_long (XDR *xdr, long *lp)
    108 {
    109     switch (xdr->x_op) {
    110     case XDR_ENCODE:
    111         return XDR_SEND_INT32(xdr, (int32_t *)lp);
    112     case XDR_DECODE:
    113         return XDR_RECV_INT32(xdr, (int32_t *)lp);
    114     case XDR_FREE:
    115         return TRUE;
    116     default:
    117         break;
    118     }
    119     return FALSE;
    120 } /* xdr_long */
    121 
    122 bool_t xdr_u_long (XDR *xdr, u_long *ulp)
    123 {
    124     switch (xdr->x_op) {
    125     case XDR_ENCODE:
    126         return XDR_SEND_UINT32(xdr, (uint32_t *)ulp);
    127     case XDR_DECODE:
    128         return XDR_RECV_UINT32(xdr, (uint32_t *)ulp);
    129     case XDR_FREE:
    130         return TRUE;
    131     default:
    132         break;
    133     }
    134     return FALSE;
    135 } /* xdr_u_long */
    136 
    137 /*
    138  * XDR hyper integers
    139  * same as xdr_hyper - open coded to save a proc call!
    140  */
    141 bool_t xdr_u_hyper (XDR *xdrs, u_quad_t *ullp)
    142 {
    143     unsigned long t1;
    144     unsigned long t2;
    145 
    146     if (xdrs->x_op == XDR_ENCODE) {
    147         t1 = (unsigned long) ((*ullp) >> 32);
    148         t2 = (unsigned long) (*ullp);
    149         return (XDR_SEND_INT32(xdrs, (int32 *)&t1) &&
    150                 XDR_SEND_INT32(xdrs, (int32 *)&t2));
    151     }
    152 
    153     if (xdrs->x_op == XDR_DECODE) {
    154         if (!XDR_RECV_INT32(xdrs, (int32 *)&t1) ||
    155             !XDR_RECV_INT32(xdrs, (int32 *)&t2))
    156             return FALSE;
    157         *ullp = ((u_quad_t) t1) << 32;
    158         *ullp |= t2;
    159         return TRUE;
    160     }
    161 
    162     return xdrs->x_op == XDR_FREE;
    163 }
    164 
    165 bool_t
    166 xdr_u_quad_t (XDR *xdrs, u_quad_t *ullp)
    167 {
    168     return xdr_u_hyper(xdrs, ullp);
    169 }
    170 
    171 bool_t xdr_u_short (XDR *xdr, u_short *usp)
    172 {
    173     u_long l;
    174 
    175     switch (xdr->x_op) {
    176     case XDR_ENCODE:
    177         l = *usp;
    178         return XDR_SEND_UINT32(xdr, (uint32_t *)&l);
    179     case XDR_DECODE:
    180         if(!XDR_RECV_UINT32(xdr, (uint32_t *)&l))
    181             return FALSE;
    182         *usp = (u_short)l;
    183         return TRUE;
    184     case XDR_FREE:
    185         return TRUE;
    186     default:
    187         break;
    188     }
    189 
    190     return FALSE;
    191 } /* xdr_u_short */
    192 
    193 /*
    194  * xdr_vector():
    195  *
    196  * XDR a fixed length array. Unlike variable-length arrays,
    197  * the storage of fixed length arrays is static and unfreeable.
    198  * > basep: base of the array
    199  * > size: size of the array
    200  * > elemsize: size of each element
    201  * > xdr_elem: routine to XDR each element
    202  */
    203 bool_t
    204 xdr_vector (XDR *xdrs,
    205             char *basep,
    206             u_int nelem,
    207             u_int elemsize,
    208             xdrproc_t xdr_elem)
    209 {
    210     u_int i;
    211     char *elptr;
    212 
    213     elptr = basep;
    214     for (i = 0; i < nelem; i++) {
    215         if (!(*xdr_elem) (xdrs, elptr, LASTUNSIGNED))
    216             return FALSE;
    217         elptr += elemsize;
    218     }
    219     return TRUE;
    220 }
    221 
    222 bool_t xdr_bool (XDR *xdr, bool_t *bp)
    223 {
    224     uint32 lb;
    225 
    226     switch(xdr->x_op) {
    227     case XDR_ENCODE:
    228         lb = *bp ? TRUE : FALSE;
    229         return XDR_SEND_UINT32(xdr, &lb);
    230     case XDR_DECODE:
    231         if (!XDR_RECV_UINT32(xdr, &lb))
    232             return FALSE;
    233         *bp = (lb == FALSE) ? FALSE : TRUE;
    234         return TRUE;
    235     case XDR_FREE:
    236         return TRUE;
    237     default:
    238         break;
    239     }
    240 
    241     return FALSE;
    242 } /* xdr_bool */
    243 
    244 /*
    245  * XDR an indirect pointer
    246  * xdr_reference is for recursively translating a structure that is
    247  * referenced by a pointer inside the structure that is currently being
    248  * translated.  pp references a pointer to storage. If *pp is null
    249  * the  necessary storage is allocated.
    250  * size is the size of the referneced structure.
    251  * proc is the routine to handle the referenced structure.
    252  */
    253 bool_t
    254 xdr_reference (XDR *xdrs,
    255                caddr_t *pp,     /* the pointer to work on */
    256                u_int size,      /* size of the object pointed to */
    257                xdrproc_t proc)   /* xdr routine to handle the object */
    258 {
    259     bool_t stat;
    260 
    261     if (*pp == NULL) {
    262         switch (xdrs->x_op) {
    263         case XDR_FREE:
    264             return TRUE;
    265 
    266         case XDR_DECODE:
    267             *pp = (caddr_t) mem_alloc (size);
    268             if (*pp == NULL) return FALSE;
    269             memset(*pp, 0, size);
    270             break;
    271         default:
    272             break;
    273         }
    274     }
    275 
    276     stat = (*proc) (xdrs, *pp, LASTUNSIGNED);
    277 
    278     if (xdrs->x_op == XDR_FREE) {
    279         mem_free(*pp);
    280         *pp = NULL;
    281     }
    282     return stat;
    283 } /* xdr_reference */
    284 
    285 /*
    286  * xdr_pointer():
    287  *
    288  * XDR a pointer to a possibly recursive data structure. This
    289  * differs with xdr_reference in that it can serialize/deserialize
    290  * trees correctly.
    291  *
    292  *  What's sent is actually a union:
    293  *
    294  *  union object_pointer switch (bool_t b) {
    295  *  case TRUE: object_data data;
    296  *  case FALSE: void nothing;
    297  *  }
    298  *
    299  * > objpp: Pointer to the pointer to the object.
    300  * > obj_size: size of the object.
    301  * > xdr_obj: routine to XDR an object.
    302  *
    303  */
    304 
    305 bool_t
    306 xdr_pointer (XDR *xdrs,
    307              char **objpp,
    308              u_int obj_size,
    309              xdrproc_t xdr_obj)
    310 {
    311     bool_t more_data;
    312 
    313     more_data = (*objpp != NULL);
    314     if (!xdr_bool (xdrs, &more_data))
    315         return FALSE;
    316 
    317     if (!more_data) {
    318         *objpp = NULL;
    319         return TRUE;
    320     }
    321     return xdr_reference (xdrs, objpp, obj_size, xdr_obj);
    322 } /* xdr_pointer */
    323 
    324 bool_t xdr_void (void)
    325 {
    326     return TRUE;
    327 } /* xdr_void */
    328 
    329 /*
    330  * XDR an array of arbitrary elements
    331  * *addrp is a pointer to the array, *sizep is the number of elements.
    332  * If addrp is NULL (*sizep * elsize) bytes are allocated.
    333  * elsize is the size (in bytes) of each element, and elproc is the
    334  * xdr procedure to call to handle each element of the array.
    335  */
    336 bool_t
    337 xdr_array (XDR *xdrs,
    338            caddr_t *addrp,/* array pointer */
    339            u_int *sizep,  /* number of elements */
    340            u_int maxsize,  /* max numberof elements */
    341            u_int elsize,  /* size in bytes of each element */
    342            xdrproc_t elproc) /* xdr routine to handle each element */
    343 {
    344     u_int i;
    345     caddr_t target = *addrp;
    346     u_int c;/* the actual element count */
    347     bool_t stat = TRUE;
    348     u_int nodesize;
    349 
    350     /* like strings, arrays are really counted arrays */
    351     if (!xdr_u_int (xdrs, sizep))
    352         return FALSE;
    353     c = *sizep;
    354     if ((c > maxsize) && (xdrs->x_op != XDR_FREE))
    355         return FALSE;
    356     nodesize = c * elsize;
    357 
    358     /*
    359      * if we are deserializing, we may need to allocate an array.
    360      * We also save time by checking for a null array if we are freeing.
    361      */
    362     if (target == NULL)
    363         switch (xdrs->x_op) {
    364         case XDR_DECODE:
    365             if (c == 0)
    366                 return TRUE;
    367             *addrp = target = mem_alloc (nodesize);
    368             if (!*addrp) return FALSE;
    369             memset (target, 0, nodesize);
    370             break;
    371         case XDR_FREE:
    372             return TRUE;
    373         default:
    374             break;
    375         }
    376 
    377     /*
    378      * now we xdr each element of array
    379      */
    380     for (i = 0; (i < c) && stat; i++) {
    381         stat = (*elproc) (xdrs, target, LASTUNSIGNED);
    382         target += elsize;
    383     }
    384 
    385     /*
    386      * the array may need freeing
    387      */
    388     if (xdrs->x_op == XDR_FREE) {
    389         mem_free(*addrp);
    390         *addrp = NULL;
    391     }
    392 
    393     return stat;
    394 }
    395 
    396 bool_t xdr_int(XDR *xdr, int *ip)
    397 {
    398     switch (xdr->x_op) {
    399     case XDR_ENCODE:
    400         return XDR_SEND_INT32(xdr, (int32 *) ip);
    401     case XDR_DECODE:
    402         return XDR_RECV_INT32(xdr, (int32 *) ip);
    403     case XDR_FREE:
    404         return TRUE;
    405     default:
    406         break;
    407     }
    408 
    409     return FALSE;
    410 } /* xdr_int */
    411 
    412 bool_t xdr_opaque (XDR *xdr, caddr_t cp, u_int cnt)
    413 {
    414     /* if no data we are done */
    415     if (cnt == 0)
    416         return TRUE;
    417 
    418     switch (xdr->x_op) {
    419     case XDR_ENCODE:
    420         return XDR_SEND_BYTES(xdr, (uint8 *) cp, cnt);
    421     case XDR_DECODE:
    422         return XDR_RECV_BYTES(xdr, (uint8 *) cp, cnt);
    423     case XDR_FREE:
    424         return TRUE;
    425     default:
    426         break;
    427     }
    428 
    429     return FALSE;
    430 } /* xdr_opaque */
    431 
    432 bool_t xdr_char (XDR *xdr, char *cp)
    433 {
    434     int i;
    435     i = (*cp);
    436     if (!xdr_int (xdr, &i))
    437         return FALSE;
    438     *cp = i;
    439     return TRUE;
    440 } /* xdr_char */
    441 
    442 bool_t
    443 xdr_quad_t (XDR *xdrs, quad_t *llp)
    444 {
    445     return xdr_u_quad_t(xdrs, (u_quad_t *)llp);
    446 }
    447 
    448 bool_t xdr_short (XDR *xdr, short *sp)
    449 {
    450     long l;
    451     switch (xdr->x_op) {
    452     case XDR_ENCODE:
    453         l = *sp;
    454         return XDR_SEND_INT32(xdr, (int32_t *)&l);
    455     case XDR_DECODE:
    456         if (!XDR_RECV_INT32(xdr, (int32_t *)&l))
    457             return FALSE;
    458         *sp = (short)l;
    459         return TRUE;
    460     case XDR_FREE:
    461         return TRUE;
    462     default:
    463         break;
    464     }
    465     return FALSE;
    466 } /* xdr_short */
    467 
    468 /*
    469  * Non-portable xdr primitives.
    470  * Care should be taken when moving these routines to new architectures.
    471  */
    472 
    473 /*
    474  * XDR null terminated ASCII strings
    475  * xdr_string deals with "C strings" - arrays of bytes that are
    476  * terminated by a NULL character.  The parameter cpp references a
    477  * pointer to storage; If the pointer is null, then the necessary
    478  * storage is allocated.  The last parameter is the max allowed length
    479  * of the string as specified by a protocol.
    480  */
    481 bool_t xdr_string (XDR *xdr, char **cpp, u_int maxsize)
    482 {
    483     u_int size;
    484     u_int nodesize;
    485 
    486     /*
    487      * first deal with the length since xdr strings are counted-strings
    488      */
    489     switch (xdr->x_op) {
    490     case XDR_FREE:
    491         if (*cpp == NULL) return TRUE;
    492         /* fall through... */
    493     case XDR_ENCODE:
    494         if (*cpp == NULL) return FALSE;
    495         size = strlen(*cpp);
    496         break;
    497     case XDR_DECODE:
    498         break;
    499     default:
    500         break;
    501     }
    502 
    503     if (!xdr_u_int(xdr, &size)) return FALSE;
    504     if (size > maxsize) return FALSE;
    505     nodesize = size + 1;
    506 
    507     /*
    508      * now deal with the actual bytes
    509      */
    510     switch (xdr->x_op) {
    511     case XDR_DECODE:
    512         if (nodesize == 0) return TRUE;
    513         if (*cpp == NULL)
    514             *cpp = (char *)mem_alloc(nodesize);
    515         if (*cpp == NULL) return FALSE;
    516         (*cpp)[size] = 0;
    517         /* fall through... */
    518     case XDR_ENCODE:
    519         return xdr_opaque(xdr, *cpp, size);
    520     case XDR_FREE:
    521         mem_free(*cpp);
    522         *cpp = NULL;
    523         return TRUE;
    524     default:
    525         break;
    526     }
    527     return FALSE;
    528 } /* xdr_string */
    529