summary refs log tree commit diff
path: root/sunrpc
diff options
context:
space:
mode:
Diffstat (limited to 'sunrpc')
-rw-r--r--sunrpc/rpc/xdr.h23
-rw-r--r--sunrpc/svc_tcp.c5
-rw-r--r--sunrpc/xdr_mem.c38
-rw-r--r--sunrpc/xdr_rec.c60
-rw-r--r--sunrpc/xdr_sizeof.c10
-rw-r--r--sunrpc/xdr_stdio.c28
6 files changed, 145 insertions, 19 deletions
diff --git a/sunrpc/rpc/xdr.h b/sunrpc/rpc/xdr.h
index 44e30dfabe..8e74d3cd7f 100644
--- a/sunrpc/rpc/xdr.h
+++ b/sunrpc/rpc/xdr.h
@@ -82,12 +82,11 @@ __BEGIN_DECLS
  * XDR_FREE can be used to release the space allocated by an XDR_DECODE
  * request.
  */
-enum xdr_op
-  {
-    XDR_ENCODE = 0,
-    XDR_DECODE = 1,
-    XDR_FREE = 2
-  };
+enum xdr_op {
+  XDR_ENCODE = 0,
+  XDR_DECODE = 1,
+  XDR_FREE = 2
+};
 
 /*
  * This is the number of bytes per unit of external data.
@@ -135,6 +134,10 @@ struct XDR
 	/* buf quick ptr to buffered data */
 	void (*x_destroy) __PMT ((XDR *__xdrs));
 	/* free privates of this xdr_stream */
+	bool_t (*x_getint32) __PMT ((XDR *__xdrs, int32_t *__ip));
+	/* get a int from underlying stream */
+	bool_t (*x_putint32) __PMT ((XDR *__xdrs, __const int32_t *__ip));
+	/* put a int to " */
       }
      *x_ops;
     caddr_t x_public;		/* users' data */
@@ -165,14 +168,14 @@ typedef bool_t (*xdrproc_t) __PMT ((XDR *, void *,...));
  * u_int         pos;
  */
 #define XDR_GETINT32(xdrs, int32p)                      \
-        (*(xdrs)->x_ops->x_getlong)(xdrs, (long *)int32p)
+        (*(xdrs)->x_ops->x_getint32)(xdrs, int32p)
 #define xdr_getint32(xdrs, int32p)                      \
-        (*(xdrs)->x_ops->x_getlong)(xdrs, (long *)int32p)
+        (*(xdrs)->x_ops->x_getint32)(xdrs, int32p)
 
 #define XDR_PUTINT32(xdrs, int32p)                      \
-        (*(xdrs)->x_ops->x_putlong)(xdrs, (long *)int32p)
+        (*(xdrs)->x_ops->x_putint32)(xdrs, int32p)
 #define xdr_putint32(xdrs, int32p)                      \
-        (*(xdrs)->x_ops->x_putlong)(xdrs, (long *)int32p)
+        (*(xdrs)->x_ops->x_putint32)(xdrs, int32p)
 
 #define XDR_GETLONG(xdrs, longp)			\
 	(*(xdrs)->x_ops->x_getlong)(xdrs, longp)
diff --git a/sunrpc/svc_tcp.c b/sunrpc/svc_tcp.c
index cd5cecf0f7..cd24f726c9 100644
--- a/sunrpc/svc_tcp.c
+++ b/sunrpc/svc_tcp.c
@@ -312,8 +312,11 @@ readtcp (char *xprtptr, char *buf, int len)
 	case 0:
 	  goto fatal_err;
 	default:
+          if ((pollfd.revents & POLLERR) || (pollfd.revents & POLLHUP)
+              || (pollfd.revents & POLLNVAL))
+            goto fatal_err;
 	  break;
-	  }
+	}
     }
   while ((pollfd.revents & POLLIN) == 0);
 
diff --git a/sunrpc/xdr_mem.c b/sunrpc/xdr_mem.c
index 47b87eaf7a..9379048bf7 100644
--- a/sunrpc/xdr_mem.c
+++ b/sunrpc/xdr_mem.c
@@ -54,6 +54,8 @@ static u_int xdrmem_getpos (const XDR *);
 static bool_t xdrmem_setpos (XDR *, u_int);
 static long *xdrmem_inline (XDR *, int);
 static void xdrmem_destroy (XDR *);
+static bool_t xdrmem_getint32 (XDR *, int32_t *);
+static bool_t xdrmem_putint32 (XDR *, const int32_t *);
 
 static const struct xdr_ops xdrmem_ops =
 {
@@ -64,7 +66,9 @@ static const struct xdr_ops xdrmem_ops =
   xdrmem_getpos,
   xdrmem_setpos,
   xdrmem_inline,
-  xdrmem_destroy
+  xdrmem_destroy,
+  xdrmem_getint32,
+  xdrmem_putint32
 };
 
 /*
@@ -219,3 +223,35 @@ xdrmem_inline (xdrs, len)
     }
   return buf;
 }
+
+/*
+ * Gets the next word from the memory referenced by xdrs and places it
+ * in the int pointed to by ip.  It then increments the private word to
+ * point at the next element.  Neither object pointed to is const
+ */
+static bool_t
+xdrmem_getint32 (XDR *xdrs, int32_t *ip)
+{
+
+  if ((xdrs->x_handy -= 4) < 0)
+    return FALSE;
+  *ip = ntohl ((*((int32_t *) (xdrs->x_private))));
+  xdrs->x_private += 4;
+  return TRUE;
+}
+
+/*
+ * Puts the long pointed to by lp in the memory referenced by xdrs.  It
+ * then increments the private word to point at the next element.  The
+ * long pointed at is const
+ */
+static bool_t
+xdrmem_putint32 (XDR *xdrs, const int32_t *ip)
+{
+
+  if ((xdrs->x_handy -= 4) < 0)
+    return FALSE;
+  *(int32_t *) xdrs->x_private = htonl (*ip);
+  xdrs->x_private += 4;
+  return TRUE;
+}
diff --git a/sunrpc/xdr_rec.c b/sunrpc/xdr_rec.c
index 30be6393a2..e0f22c5595 100644
--- a/sunrpc/xdr_rec.c
+++ b/sunrpc/xdr_rec.c
@@ -66,6 +66,8 @@ static u_int xdrrec_getpos (const XDR *);
 static bool_t xdrrec_setpos (XDR *, u_int);
 static long *xdrrec_inline (XDR *, int);
 static void xdrrec_destroy (XDR *);
+static bool_t xdrrec_getint32 (XDR *, int32_t *);
+static bool_t xdrrec_putint32 (XDR *, const int32_t *);
 
 static const struct xdr_ops xdrrec_ops =
 {
@@ -76,7 +78,9 @@ static const struct xdr_ops xdrrec_ops =
   xdrrec_getpos,
   xdrrec_setpos,
   xdrrec_inline,
-  xdrrec_destroy
+  xdrrec_destroy,
+  xdrrec_getint32,
+  xdrrec_putint32
 };
 
 /*
@@ -251,11 +255,8 @@ xdrrec_putlong (xdrs, lp)
   return TRUE;
 }
 
-static bool_t			/* must manage buffers, fragments, and records */
-xdrrec_getbytes (xdrs, addr, len)
-     XDR *xdrs;
-     caddr_t addr;
-     u_int len;
+static bool_t	   /* must manage buffers, fragments, and records */
+xdrrec_getbytes (XDR *xdrs, caddr_t addr, u_int len)
 {
   RECSTREAM *rstrm = (RECSTREAM *) xdrs->x_private;
   u_int current;
@@ -420,6 +421,53 @@ xdrrec_destroy (xdrs)
   mem_free ((caddr_t) rstrm, sizeof (RECSTREAM));
 }
 
+static bool_t
+xdrrec_getint32 (XDR *xdrs, int32_t *ip)
+{
+  RECSTREAM *rstrm = (RECSTREAM *) xdrs->x_private;
+  int32_t *bufip = (int32_t *) rstrm->in_finger;
+  int32_t mylong;
+
+  /* first try the inline, fast case */
+  if (rstrm->fbtbc >= BYTES_PER_XDR_UNIT &&
+      rstrm->in_boundry - (char *) bufip >= BYTES_PER_XDR_UNIT)
+    {
+      *ip = ntohl (*bufip);
+      rstrm->fbtbc -= BYTES_PER_XDR_UNIT;
+      rstrm->in_finger += BYTES_PER_XDR_UNIT;
+    }
+  else
+    {
+      if (!xdrrec_getbytes (xdrs, (caddr_t) &mylong,
+			    BYTES_PER_XDR_UNIT))
+	return FALSE;
+      *ip = ntohl (mylong);
+    }
+  return TRUE;
+}
+
+static bool_t
+xdrrec_putint32 (XDR *xdrs, const int32_t *ip)
+{
+  RECSTREAM *rstrm = (RECSTREAM *) xdrs->x_private;
+  int32_t *dest_ip = (int32_t *) rstrm->out_finger;
+
+  if ((rstrm->out_finger += BYTES_PER_XDR_UNIT) > rstrm->out_boundry)
+    {
+      /*
+       * this case should almost never happen so the code is
+       * inefficient
+       */
+      rstrm->out_finger -= BYTES_PER_XDR_UNIT;
+      rstrm->frag_sent = TRUE;
+      if (!flush_out (rstrm, FALSE))
+	return FALSE;
+      dest_ip = (int32_t *) rstrm->out_finger;
+      rstrm->out_finger += BYTES_PER_XDR_UNIT;
+    }
+  *dest_ip = htonl (*ip);
+  return TRUE;
+}
 
 /*
  * Exported routines to manage xdr records
diff --git a/sunrpc/xdr_sizeof.c b/sunrpc/xdr_sizeof.c
index 72403e0a26..e999e0ef51 100644
--- a/sunrpc/xdr_sizeof.c
+++ b/sunrpc/xdr_sizeof.c
@@ -123,6 +123,13 @@ x_destroy (XDR *xdrs)
   return;
 }
 
+static bool_t
+x_putint32 (XDR *xdrs, const int32_t *int32p)
+{
+  xdrs->x_handy += BYTES_PER_XDR_UNIT;
+  return TRUE;
+}
+
 unsigned long
 xdr_sizeof (xdrproc_t func, void *data)
 {
@@ -132,6 +139,7 @@ xdr_sizeof (xdrproc_t func, void *data)
   /* to stop ANSI-C compiler from complaining */
   typedef bool_t (*dummyfunc1) (XDR *, long *);
   typedef bool_t (*dummyfunc2) (XDR *, caddr_t, u_int);
+  typedef bool_t (*dummyfunc3) (XDR *, int32_t *);
 
   ops.x_putlong = x_putlong;
   ops.x_putbytes = x_putbytes;
@@ -139,10 +147,12 @@ xdr_sizeof (xdrproc_t func, void *data)
   ops.x_getpostn = x_getpostn;
   ops.x_setpostn = x_setpostn;
   ops.x_destroy = x_destroy;
+  ops.x_putint32 = x_putint32;
 
   /* the other harmless ones */
   ops.x_getlong = (dummyfunc1) harmless;
   ops.x_getbytes = (dummyfunc2) harmless;
+  ops.x_getint32 = (dummyfunc3) harmless;
 
   x.x_op = XDR_ENCODE;
   x.x_ops = &ops;
diff --git a/sunrpc/xdr_stdio.c b/sunrpc/xdr_stdio.c
index 8588042eeb..e58137c559 100644
--- a/sunrpc/xdr_stdio.c
+++ b/sunrpc/xdr_stdio.c
@@ -61,6 +61,8 @@ static u_int xdrstdio_getpos (const XDR *);
 static bool_t xdrstdio_setpos (XDR *, u_int);
 static long *xdrstdio_inline (XDR *, int);
 static void xdrstdio_destroy (XDR *);
+static bool_t xdrstdio_getint32 (XDR *, int32_t *);
+static bool_t xdrstdio_putint32 (XDR *, const int32_t *);
 
 /*
  * Ops vector for stdio type XDR
@@ -74,7 +76,9 @@ static const struct xdr_ops xdrstdio_ops =
   xdrstdio_getpos,		/* get offset in the stream */
   xdrstdio_setpos,		/* set offset in the stream */
   xdrstdio_inline,		/* prime stream for inline macros */
-  xdrstdio_destroy		/* destroy stream */
+  xdrstdio_destroy,		/* destroy stream */
+  xdrstdio_getint32,		/* deserialize a int */
+  xdrstdio_putint32		/* serialize a int */
 };
 
 /*
@@ -181,3 +185,25 @@ xdrstdio_inline (XDR *xdrs, int len)
    */
   return NULL;
 }
+
+static bool_t
+xdrstdio_getint32 (XDR *xdrs, int32_t *ip)
+{
+  int32_t mycopy;
+
+  if (fread ((caddr_t) &mycopy, 4, 1, (FILE *) xdrs->x_private) != 1)
+    return FALSE;
+  *ip = ntohl (mycopy);
+  return TRUE;
+}
+
+static bool_t
+xdrstdio_putint32 (XDR *xdrs, const int32_t *ip)
+{
+  int32_t mycopy = htonl (*ip);
+
+  ip = &mycopy;
+  if (fwrite ((caddr_t) ip, 4, 1, (FILE *) xdrs->x_private) != 1)
+    return FALSE;
+  return TRUE;
+}