Back to index

glibc  2.9
xdr.c
Go to the documentation of this file.
00001 /* @(#)xdr.c  2.1 88/07/29 4.0 RPCSRC */
00002 /*
00003  * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
00004  * unrestricted use provided that this legend is included on all tape
00005  * media and as a part of the software program in whole or part.  Users
00006  * may copy or modify Sun RPC without charge, but are not authorized
00007  * to license or distribute it to anyone else except as part of a product or
00008  * program developed by the user.
00009  *
00010  * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
00011  * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
00012  * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
00013  *
00014  * Sun RPC is provided with no support and without any obligation on the
00015  * part of Sun Microsystems, Inc. to assist in its use, correction,
00016  * modification or enhancement.
00017  *
00018  * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
00019  * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
00020  * OR ANY PART THEREOF.
00021  *
00022  * In no event will Sun Microsystems, Inc. be liable for any lost revenue
00023  * or profits or other special, indirect and consequential damages, even if
00024  * Sun has been advised of the possibility of such damages.
00025  *
00026  * Sun Microsystems, Inc.
00027  * 2550 Garcia Avenue
00028  * Mountain View, California  94043
00029  */
00030 #if !defined(lint) && defined(SCCSIDS)
00031 static char sccsid[] = "@(#)xdr.c 1.35 87/08/12";
00032 #endif
00033 
00034 /*
00035  * xdr.c, Generic XDR routines implementation.
00036  *
00037  * Copyright (C) 1986, Sun Microsystems, Inc.
00038  *
00039  * These are the "generic" xdr routines used to serialize and de-serialize
00040  * most common data items.  See xdr.h for more info on the interface to
00041  * xdr.
00042  */
00043 
00044 #include <stdio.h>
00045 #include <limits.h>
00046 #include <string.h>
00047 #include <libintl.h>
00048 
00049 #include <rpc/types.h>
00050 #include <rpc/xdr.h>
00051 
00052 #ifdef USE_IN_LIBIO
00053 # include <wchar.h>
00054 #endif
00055 
00056 /*
00057  * constants specific to the xdr "protocol"
00058  */
00059 #define XDR_FALSE    ((long) 0)
00060 #define XDR_TRUE     ((long) 1)
00061 #define LASTUNSIGNED ((u_int) 0-1)
00062 
00063 /*
00064  * for unit alignment
00065  */
00066 static const char xdr_zero[BYTES_PER_XDR_UNIT] = {0, 0, 0, 0};
00067 
00068 /*
00069  * Free a data structure using XDR
00070  * Not a filter, but a convenient utility nonetheless
00071  */
00072 void
00073 xdr_free (xdrproc_t proc, char *objp)
00074 {
00075   XDR x;
00076 
00077   x.x_op = XDR_FREE;
00078   (*proc) (&x, objp);
00079 }
00080 
00081 /*
00082  * XDR nothing
00083  */
00084 bool_t
00085 xdr_void (void)
00086 {
00087   return TRUE;
00088 }
00089 INTDEF(xdr_void)
00090 
00091 /*
00092  * XDR integers
00093  */
00094 bool_t
00095 xdr_int (XDR *xdrs, int *ip)
00096 {
00097 
00098 #if INT_MAX < LONG_MAX
00099   long l;
00100 
00101   switch (xdrs->x_op)
00102     {
00103     case XDR_ENCODE:
00104       l = (long) *ip;
00105       return XDR_PUTLONG (xdrs, &l);
00106 
00107     case XDR_DECODE:
00108       if (!XDR_GETLONG (xdrs, &l))
00109        {
00110          return FALSE;
00111        }
00112       *ip = (int) l;
00113     case XDR_FREE:
00114       return TRUE;
00115     }
00116   return FALSE;
00117 #elif INT_MAX == LONG_MAX
00118   return INTUSE(xdr_long) (xdrs, (long *) ip);
00119 #elif INT_MAX == SHRT_MAX
00120   return INTUSE(xdr_short) (xdrs, (short *) ip);
00121 #else
00122 #error unexpected integer sizes in_xdr_int()
00123 #endif
00124 }
00125 INTDEF(xdr_int)
00126 
00127 /*
00128  * XDR unsigned integers
00129  */
00130 bool_t
00131 xdr_u_int (XDR *xdrs, u_int *up)
00132 {
00133 #if UINT_MAX < ULONG_MAX
00134   long l;
00135 
00136   switch (xdrs->x_op)
00137     {
00138     case XDR_ENCODE:
00139       l = (u_long) * up;
00140       return XDR_PUTLONG (xdrs, &l);
00141 
00142     case XDR_DECODE:
00143       if (!XDR_GETLONG (xdrs, &l))
00144        {
00145          return FALSE;
00146        }
00147       *up = (u_int) (u_long) l;
00148     case XDR_FREE:
00149       return TRUE;
00150     }
00151   return FALSE;
00152 #elif UINT_MAX == ULONG_MAX
00153   return INTUSE(xdr_u_long) (xdrs, (u_long *) up);
00154 #elif UINT_MAX == USHRT_MAX
00155   return INTUSE(xdr_short) (xdrs, (short *) up);
00156 #else
00157 #error unexpected integer sizes in_xdr_u_int()
00158 #endif
00159 }
00160 INTDEF(xdr_u_int)
00161 
00162 /*
00163  * XDR long integers
00164  * The definition of xdr_long() is kept for backward
00165  * compatibility. Instead xdr_int() should be used.
00166  */
00167 bool_t
00168 xdr_long (XDR *xdrs, long *lp)
00169 {
00170 
00171   if (xdrs->x_op == XDR_ENCODE
00172       && (sizeof (int32_t) == sizeof (long)
00173          || (int32_t) *lp == *lp))
00174     return XDR_PUTLONG (xdrs, lp);
00175 
00176   if (xdrs->x_op == XDR_DECODE)
00177     return XDR_GETLONG (xdrs, lp);
00178 
00179   if (xdrs->x_op == XDR_FREE)
00180     return TRUE;
00181 
00182   return FALSE;
00183 }
00184 INTDEF(xdr_long)
00185 
00186 /*
00187  * XDR unsigned long integers
00188  * The definition of xdr_u_long() is kept for backward
00189  * compatibility. Instead xdr_u_int() should be used.
00190  */
00191 bool_t
00192 xdr_u_long (XDR *xdrs, u_long *ulp)
00193 {
00194   switch (xdrs->x_op)
00195     {
00196     case XDR_DECODE:
00197       {
00198        long int tmp;
00199 
00200        if (XDR_GETLONG (xdrs, &tmp) == FALSE)
00201          return FALSE;
00202 
00203        *ulp = (uint32_t) tmp;
00204        return TRUE;
00205       }
00206 
00207     case XDR_ENCODE:
00208       if (sizeof (uint32_t) != sizeof (u_long)
00209          && (uint32_t) *ulp != *ulp)
00210        return FALSE;
00211 
00212       return XDR_PUTLONG (xdrs, (long *) ulp);
00213 
00214     case XDR_FREE:
00215       return TRUE;
00216     }
00217   return FALSE;
00218 }
00219 INTDEF(xdr_u_long)
00220 
00221 /*
00222  * XDR hyper integers
00223  * same as xdr_u_hyper - open coded to save a proc call!
00224  */
00225 bool_t
00226 xdr_hyper (XDR *xdrs, quad_t *llp)
00227 {
00228   long int t1, t2;
00229 
00230   if (xdrs->x_op == XDR_ENCODE)
00231     {
00232       t1 = (long) ((*llp) >> 32);
00233       t2 = (long) (*llp);
00234       return (XDR_PUTLONG(xdrs, &t1) && XDR_PUTLONG(xdrs, &t2));
00235     }
00236 
00237   if (xdrs->x_op == XDR_DECODE)
00238     {
00239       if (!XDR_GETLONG(xdrs, &t1) || !XDR_GETLONG(xdrs, &t2))
00240        return FALSE;
00241       *llp = ((quad_t) t1) << 32;
00242       *llp |= (uint32_t) t2;
00243       return TRUE;
00244     }
00245 
00246   if (xdrs->x_op == XDR_FREE)
00247     return TRUE;
00248 
00249   return FALSE;
00250 }
00251 INTDEF(xdr_hyper)
00252 
00253 
00254 /*
00255  * XDR hyper integers
00256  * same as xdr_hyper - open coded to save a proc call!
00257  */
00258 bool_t
00259 xdr_u_hyper (XDR *xdrs, u_quad_t *ullp)
00260 {
00261   long int t1, t2;
00262 
00263   if (xdrs->x_op == XDR_ENCODE)
00264     {
00265       t1 = (unsigned long) ((*ullp) >> 32);
00266       t2 = (unsigned long) (*ullp);
00267       return (XDR_PUTLONG(xdrs, &t1) && XDR_PUTLONG(xdrs, &t2));
00268     }
00269 
00270   if (xdrs->x_op == XDR_DECODE)
00271     {
00272       if (!XDR_GETLONG(xdrs, &t1) || !XDR_GETLONG(xdrs, &t2))
00273        return FALSE;
00274       *ullp = ((u_quad_t) t1) << 32;
00275       *ullp |= (uint32_t) t2;
00276       return TRUE;
00277     }
00278 
00279   if (xdrs->x_op == XDR_FREE)
00280     return TRUE;
00281 
00282   return FALSE;
00283 }
00284 INTDEF(xdr_u_hyper)
00285 
00286 bool_t
00287 xdr_longlong_t (XDR *xdrs, quad_t *llp)
00288 {
00289   return INTUSE(xdr_hyper) (xdrs, llp);
00290 }
00291 
00292 bool_t
00293 xdr_u_longlong_t (XDR *xdrs, u_quad_t *ullp)
00294 {
00295   return INTUSE(xdr_u_hyper) (xdrs, ullp);
00296 }
00297 
00298 /*
00299  * XDR short integers
00300  */
00301 bool_t
00302 xdr_short (XDR *xdrs, short *sp)
00303 {
00304   long l;
00305 
00306   switch (xdrs->x_op)
00307     {
00308     case XDR_ENCODE:
00309       l = (long) *sp;
00310       return XDR_PUTLONG (xdrs, &l);
00311 
00312     case XDR_DECODE:
00313       if (!XDR_GETLONG (xdrs, &l))
00314        {
00315          return FALSE;
00316        }
00317       *sp = (short) l;
00318       return TRUE;
00319 
00320     case XDR_FREE:
00321       return TRUE;
00322     }
00323   return FALSE;
00324 }
00325 INTDEF(xdr_short)
00326 
00327 /*
00328  * XDR unsigned short integers
00329  */
00330 bool_t
00331 xdr_u_short (XDR *xdrs, u_short *usp)
00332 {
00333   long l;
00334 
00335   switch (xdrs->x_op)
00336     {
00337     case XDR_ENCODE:
00338       l = (u_long) * usp;
00339       return XDR_PUTLONG (xdrs, &l);
00340 
00341     case XDR_DECODE:
00342       if (!XDR_GETLONG (xdrs, &l))
00343        {
00344          return FALSE;
00345        }
00346       *usp = (u_short) (u_long) l;
00347       return TRUE;
00348 
00349     case XDR_FREE:
00350       return TRUE;
00351     }
00352   return FALSE;
00353 }
00354 INTDEF(xdr_u_short)
00355 
00356 
00357 /*
00358  * XDR a char
00359  */
00360 bool_t
00361 xdr_char (XDR *xdrs, char *cp)
00362 {
00363   int i;
00364 
00365   i = (*cp);
00366   if (!INTUSE(xdr_int) (xdrs, &i))
00367     {
00368       return FALSE;
00369     }
00370   *cp = i;
00371   return TRUE;
00372 }
00373 
00374 /*
00375  * XDR an unsigned char
00376  */
00377 bool_t
00378 xdr_u_char (XDR *xdrs, u_char *cp)
00379 {
00380   u_int u;
00381 
00382   u = (*cp);
00383   if (!INTUSE(xdr_u_int) (xdrs, &u))
00384     {
00385       return FALSE;
00386     }
00387   *cp = u;
00388   return TRUE;
00389 }
00390 
00391 /*
00392  * XDR booleans
00393  */
00394 bool_t
00395 xdr_bool (XDR *xdrs, bool_t *bp)
00396 {
00397   long lb;
00398 
00399   switch (xdrs->x_op)
00400     {
00401     case XDR_ENCODE:
00402       lb = *bp ? XDR_TRUE : XDR_FALSE;
00403       return XDR_PUTLONG (xdrs, &lb);
00404 
00405     case XDR_DECODE:
00406       if (!XDR_GETLONG (xdrs, &lb))
00407        {
00408          return FALSE;
00409        }
00410       *bp = (lb == XDR_FALSE) ? FALSE : TRUE;
00411       return TRUE;
00412 
00413     case XDR_FREE:
00414       return TRUE;
00415     }
00416   return FALSE;
00417 }
00418 INTDEF(xdr_bool)
00419 
00420 /*
00421  * XDR enumerations
00422  */
00423 bool_t
00424 xdr_enum (XDR *xdrs, enum_t *ep)
00425 {
00426   enum sizecheck
00427     {
00428       SIZEVAL
00429     };                      /* used to find the size of an enum */
00430 
00431   /*
00432    * enums are treated as ints
00433    */
00434   if (sizeof (enum sizecheck) == 4)
00435     {
00436 #if INT_MAX < LONG_MAX
00437       long l;
00438 
00439       switch (xdrs->x_op)
00440        {
00441        case XDR_ENCODE:
00442          l = *ep;
00443          return XDR_PUTLONG (xdrs, &l);
00444 
00445        case XDR_DECODE:
00446          if (!XDR_GETLONG (xdrs, &l))
00447            {
00448              return FALSE;
00449            }
00450          *ep = l;
00451        case XDR_FREE:
00452          return TRUE;
00453 
00454        }
00455       return FALSE;
00456 #else
00457       return INTUSE(xdr_long) (xdrs, (long *) ep);
00458 #endif
00459     }
00460   else if (sizeof (enum sizecheck) == sizeof (short))
00461     {
00462       return INTUSE(xdr_short) (xdrs, (short *) ep);
00463     }
00464   else
00465     {
00466       return FALSE;
00467     }
00468 }
00469 INTDEF(xdr_enum)
00470 
00471 /*
00472  * XDR opaque data
00473  * Allows the specification of a fixed size sequence of opaque bytes.
00474  * cp points to the opaque object and cnt gives the byte length.
00475  */
00476 bool_t
00477 xdr_opaque (XDR *xdrs, caddr_t cp, u_int cnt)
00478 {
00479   u_int rndup;
00480   static char crud[BYTES_PER_XDR_UNIT];
00481 
00482   /*
00483    * if no data we are done
00484    */
00485   if (cnt == 0)
00486     return TRUE;
00487 
00488   /*
00489    * round byte count to full xdr units
00490    */
00491   rndup = cnt % BYTES_PER_XDR_UNIT;
00492   if (rndup > 0)
00493     rndup = BYTES_PER_XDR_UNIT - rndup;
00494 
00495   switch (xdrs->x_op)
00496     {
00497     case XDR_DECODE:
00498       if (!XDR_GETBYTES (xdrs, cp, cnt))
00499        {
00500          return FALSE;
00501        }
00502       if (rndup == 0)
00503        return TRUE;
00504       return XDR_GETBYTES (xdrs, (caddr_t)crud, rndup);
00505 
00506     case XDR_ENCODE:
00507       if (!XDR_PUTBYTES (xdrs, cp, cnt))
00508        {
00509          return FALSE;
00510        }
00511       if (rndup == 0)
00512        return TRUE;
00513       return XDR_PUTBYTES (xdrs, xdr_zero, rndup);
00514 
00515     case XDR_FREE:
00516       return TRUE;
00517     }
00518   return FALSE;
00519 }
00520 INTDEF(xdr_opaque)
00521 
00522 /*
00523  * XDR counted bytes
00524  * *cpp is a pointer to the bytes, *sizep is the count.
00525  * If *cpp is NULL maxsize bytes are allocated
00526  */
00527 bool_t
00528 xdr_bytes (xdrs, cpp, sizep, maxsize)
00529      XDR *xdrs;
00530      char **cpp;
00531      u_int *sizep;
00532      u_int maxsize;
00533 {
00534   char *sp = *cpp;   /* sp is the actual string pointer */
00535   u_int nodesize;
00536 
00537   /*
00538    * first deal with the length since xdr bytes are counted
00539    */
00540   if (!INTUSE(xdr_u_int) (xdrs, sizep))
00541     {
00542       return FALSE;
00543     }
00544   nodesize = *sizep;
00545   if ((nodesize > maxsize) && (xdrs->x_op != XDR_FREE))
00546     {
00547       return FALSE;
00548     }
00549 
00550   /*
00551    * now deal with the actual bytes
00552    */
00553   switch (xdrs->x_op)
00554     {
00555     case XDR_DECODE:
00556       if (nodesize == 0)
00557        {
00558          return TRUE;
00559        }
00560       if (sp == NULL)
00561        {
00562          *cpp = sp = (char *) mem_alloc (nodesize);
00563        }
00564       if (sp == NULL)
00565        {
00566          (void) __fxprintf (NULL, "%s: %s", __func__, _("out of memory\n"));
00567          return FALSE;
00568        }
00569       /* fall into ... */
00570 
00571     case XDR_ENCODE:
00572       return INTUSE(xdr_opaque) (xdrs, sp, nodesize);
00573 
00574     case XDR_FREE:
00575       if (sp != NULL)
00576        {
00577          mem_free (sp, nodesize);
00578          *cpp = NULL;
00579        }
00580       return TRUE;
00581     }
00582   return FALSE;
00583 }
00584 INTDEF(xdr_bytes)
00585 
00586 /*
00587  * Implemented here due to commonality of the object.
00588  */
00589 bool_t
00590 xdr_netobj (xdrs, np)
00591      XDR *xdrs;
00592      struct netobj *np;
00593 {
00594 
00595   return INTUSE(xdr_bytes) (xdrs, &np->n_bytes, &np->n_len, MAX_NETOBJ_SZ);
00596 }
00597 INTDEF(xdr_netobj)
00598 
00599 /*
00600  * XDR a discriminated union
00601  * Support routine for discriminated unions.
00602  * You create an array of xdrdiscrim structures, terminated with
00603  * an entry with a null procedure pointer.  The routine gets
00604  * the discriminant value and then searches the array of xdrdiscrims
00605  * looking for that value.  It calls the procedure given in the xdrdiscrim
00606  * to handle the discriminant.  If there is no specific routine a default
00607  * routine may be called.
00608  * If there is no specific or default routine an error is returned.
00609  */
00610 bool_t
00611 xdr_union (xdrs, dscmp, unp, choices, dfault)
00612      XDR *xdrs;
00613      enum_t *dscmp;         /* enum to decide which arm to work on */
00614      char *unp;                    /* the union itself */
00615      const struct xdr_discrim *choices;   /* [value, xdr proc] for each arm */
00616      xdrproc_t dfault;             /* default xdr routine */
00617 {
00618   enum_t dscm;
00619 
00620   /*
00621    * we deal with the discriminator;  it's an enum
00622    */
00623   if (!INTUSE(xdr_enum) (xdrs, dscmp))
00624     {
00625       return FALSE;
00626     }
00627   dscm = *dscmp;
00628 
00629   /*
00630    * search choices for a value that matches the discriminator.
00631    * if we find one, execute the xdr routine for that value.
00632    */
00633   for (; choices->proc != NULL_xdrproc_t; choices++)
00634     {
00635       if (choices->value == dscm)
00636        return (*(choices->proc)) (xdrs, unp, LASTUNSIGNED);
00637     }
00638 
00639   /*
00640    * no match - execute the default xdr routine if there is one
00641    */
00642   return ((dfault == NULL_xdrproc_t) ? FALSE :
00643          (*dfault) (xdrs, unp, LASTUNSIGNED));
00644 }
00645 INTDEF(xdr_union)
00646 
00647 
00648 /*
00649  * Non-portable xdr primitives.
00650  * Care should be taken when moving these routines to new architectures.
00651  */
00652 
00653 
00654 /*
00655  * XDR null terminated ASCII strings
00656  * xdr_string deals with "C strings" - arrays of bytes that are
00657  * terminated by a NULL character.  The parameter cpp references a
00658  * pointer to storage; If the pointer is null, then the necessary
00659  * storage is allocated.  The last parameter is the max allowed length
00660  * of the string as specified by a protocol.
00661  */
00662 bool_t
00663 xdr_string (xdrs, cpp, maxsize)
00664      XDR *xdrs;
00665      char **cpp;
00666      u_int maxsize;
00667 {
00668   char *sp = *cpp;   /* sp is the actual string pointer */
00669   u_int size;
00670   u_int nodesize;
00671 
00672   /*
00673    * first deal with the length since xdr strings are counted-strings
00674    */
00675   switch (xdrs->x_op)
00676     {
00677     case XDR_FREE:
00678       if (sp == NULL)
00679        {
00680          return TRUE;              /* already free */
00681        }
00682       /* fall through... */
00683     case XDR_ENCODE:
00684       if (sp == NULL)
00685        return FALSE;
00686       size = strlen (sp);
00687       break;
00688     case XDR_DECODE:
00689       break;
00690     }
00691   if (!INTUSE(xdr_u_int) (xdrs, &size))
00692     {
00693       return FALSE;
00694     }
00695   if (size > maxsize)
00696     {
00697       return FALSE;
00698     }
00699   nodesize = size + 1;
00700   if (nodesize == 0)
00701     {
00702       /* This means an overflow.  It a bug in the caller which
00703         provided a too large maxsize but nevertheless catch it
00704         here.  */
00705       return FALSE;
00706     }
00707 
00708   /*
00709    * now deal with the actual bytes
00710    */
00711   switch (xdrs->x_op)
00712     {
00713     case XDR_DECODE:
00714       if (sp == NULL)
00715        *cpp = sp = (char *) mem_alloc (nodesize);
00716       if (sp == NULL)
00717        {
00718          (void) __fxprintf (NULL, "%s: %s", __func__, _("out of memory\n"));
00719          return FALSE;
00720        }
00721       sp[size] = 0;
00722       /* fall into ... */
00723 
00724     case XDR_ENCODE:
00725       return INTUSE(xdr_opaque) (xdrs, sp, size);
00726 
00727     case XDR_FREE:
00728       mem_free (sp, nodesize);
00729       *cpp = NULL;
00730       return TRUE;
00731     }
00732   return FALSE;
00733 }
00734 INTDEF(xdr_string)
00735 
00736 /*
00737  * Wrapper for xdr_string that can be called directly from
00738  * routines like clnt_call
00739  */
00740 bool_t
00741 xdr_wrapstring (xdrs, cpp)
00742      XDR *xdrs;
00743      char **cpp;
00744 {
00745   if (INTUSE(xdr_string) (xdrs, cpp, LASTUNSIGNED))
00746     {
00747       return TRUE;
00748     }
00749   return FALSE;
00750 }