#include "mt.h"
#include <stdlib.h>
#include <sys/types.h>
#include <sys/isa_defs.h>
#include <syslog.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include <rpc/types.h>
#include <rpc/xdr.h>
#include <inttypes.h>
#include <sys/sysmacros.h>
#include <assert.h>
#pragma weak xdr_int64_t = xdr_hyper
#pragma weak xdr_uint64_t = xdr_u_hyper
#pragma weak xdr_int32_t = xdr_int
#pragma weak xdr_uint32_t = xdr_u_int
#pragma weak xdr_int16_t = xdr_short
#pragma weak xdr_uint16_t = xdr_u_short
#pragma weak xdr_int8_t = xdr_char
#pragma weak xdr_uint8_t = xdr_u_char
#pragma weak xdr_ulonglong_t = xdr_u_longlong_t
#define XDR_FALSE ((uint_t)0)
#define XDR_TRUE ((uint_t)1)
#define LASTUNSIGNED ((uint_t)0-1)
#define FRAGMENT 65536
static const char xdr_zero[BYTES_PER_XDR_UNIT] = { 0 };
void
xdr_free(xdrproc_t proc, char *objp)
{
XDR x;
x.x_op = XDR_FREE;
(*proc)(&x, objp);
}
bool_t
xdr_void(void)
{
return (TRUE);
}
bool_t
xdr_time_t(XDR *xdrs, time_t *tp)
{
int32_t i;
switch (xdrs->x_op) {
case XDR_ENCODE:
#if defined(_LP64)
if (*tp > INT32_MAX)
*tp = INT32_MAX;
else if (*tp < INT32_MIN)
*tp = INT32_MIN;
#endif
i = (int32_t)*tp;
return (XDR_PUTINT32(xdrs, &i));
case XDR_DECODE:
if (!XDR_GETINT32(xdrs, &i))
return (FALSE);
*tp = (time_t)i;
return (TRUE);
case XDR_FREE:
return (TRUE);
}
return (FALSE);
}
bool_t
xdr_int(XDR *xdrs, int *ip)
{
switch (xdrs->x_op) {
case XDR_ENCODE:
return (XDR_PUTINT32(xdrs, ip));
case XDR_DECODE:
return (XDR_GETINT32(xdrs, ip));
case XDR_FREE:
return (TRUE);
}
return (FALSE);
}
bool_t
xdr_u_int(XDR *xdrs, uint_t *up)
{
switch (xdrs->x_op) {
case XDR_ENCODE:
return (XDR_PUTINT32(xdrs, (int *)up));
case XDR_DECODE:
return (XDR_GETINT32(xdrs, (int *)up));
case XDR_FREE:
return (TRUE);
}
return (FALSE);
}
bool_t
xdr_long(XDR *xdrs, long *lp)
{
int32_t i;
switch (xdrs->x_op) {
case XDR_ENCODE:
#if defined(_LP64)
if ((*lp > INT32_MAX) || (*lp < INT32_MIN))
return (FALSE);
#endif
i = (int32_t)*lp;
return (XDR_PUTINT32(xdrs, &i));
case XDR_DECODE:
if (!XDR_GETINT32(xdrs, &i))
return (FALSE);
*lp = (long)i;
return (TRUE);
case XDR_FREE:
return (TRUE);
}
return (FALSE);
}
bool_t
xdr_u_long(XDR *xdrs, ulong_t *ulp)
{
uint32_t ui;
switch (xdrs->x_op) {
case XDR_ENCODE:
#if defined(_LP64)
if (*ulp > UINT32_MAX)
return (FALSE);
#endif
ui = (uint32_t)*ulp;
return (XDR_PUTINT32(xdrs, (int32_t *)&ui));
case XDR_DECODE:
if (!XDR_GETINT32(xdrs, (int32_t *)&ui))
return (FALSE);
*ulp = (ulong_t)ui;
return (TRUE);
case XDR_FREE:
return (TRUE);
}
return (FALSE);
}
bool_t
xdr_short(XDR *xdrs, short *sp)
{
int32_t l;
switch (xdrs->x_op) {
case XDR_ENCODE:
l = (int32_t)*sp;
return (XDR_PUTINT32(xdrs, &l));
case XDR_DECODE:
if (!XDR_GETINT32(xdrs, &l))
return (FALSE);
*sp = (short)l;
return (TRUE);
case XDR_FREE:
return (TRUE);
}
return (FALSE);
}
bool_t
xdr_u_short(XDR *xdrs, ushort_t *usp)
{
uint_t i;
switch (xdrs->x_op) {
case XDR_ENCODE:
i = (uint_t)*usp;
return (XDR_PUTINT32(xdrs, (int *)&i));
case XDR_DECODE:
if (!XDR_GETINT32(xdrs, (int *)&i))
return (FALSE);
*usp = (ushort_t)i;
return (TRUE);
case XDR_FREE:
return (TRUE);
}
return (FALSE);
}
bool_t
xdr_char(XDR *xdrs, char *cp)
{
int i;
switch (xdrs->x_op) {
case XDR_ENCODE:
i = (*cp);
return (XDR_PUTINT32(xdrs, &i));
case XDR_DECODE:
if (!XDR_GETINT32(xdrs, &i))
return (FALSE);
*cp = (char)i;
return (TRUE);
case XDR_FREE:
return (TRUE);
}
return (FALSE);
}
bool_t
xdr_u_char(XDR *xdrs, uchar_t *cp)
{
int i;
switch (xdrs->x_op) {
case XDR_ENCODE:
i = (*cp);
return (XDR_PUTINT32(xdrs, &i));
case XDR_DECODE:
if (!XDR_GETINT32(xdrs, &i))
return (FALSE);
*cp = (uchar_t)i;
return (TRUE);
case XDR_FREE:
return (TRUE);
}
return (FALSE);
}
bool_t
xdr_bool(XDR *xdrs, bool_t *bp)
{
int i;
switch (xdrs->x_op) {
case XDR_ENCODE:
i = *bp ? XDR_TRUE : XDR_FALSE;
return (XDR_PUTINT32(xdrs, &i));
case XDR_DECODE:
if (!XDR_GETINT32(xdrs, &i))
return (FALSE);
*bp = (i == XDR_FALSE) ? FALSE : TRUE;
return (TRUE);
case XDR_FREE:
return (TRUE);
}
return (FALSE);
}
bool_t
xdr_enum(XDR *xdrs, enum_t *ep)
{
enum sizecheck { SIZEVAL };
assert(sizeof (enum sizecheck) == sizeof (int32_t));
return (xdr_int(xdrs, (int *)ep));
}
bool_t
xdr_opaque(XDR *xdrs, caddr_t cp, const uint_t cnt)
{
uint_t rndup;
char crud[BYTES_PER_XDR_UNIT];
rndup = cnt % BYTES_PER_XDR_UNIT;
if ((int)rndup > 0)
rndup = BYTES_PER_XDR_UNIT - rndup;
switch (xdrs->x_op) {
case XDR_DECODE:
if (!XDR_GETBYTES(xdrs, cp, cnt))
return (FALSE);
if (rndup == 0)
return (TRUE);
return (XDR_GETBYTES(xdrs, crud, rndup));
case XDR_ENCODE:
if (!XDR_PUTBYTES(xdrs, cp, cnt))
return (FALSE);
if (rndup == 0)
return (TRUE);
return (XDR_PUTBYTES(xdrs, (caddr_t)&xdr_zero[0], rndup));
case XDR_FREE:
return (TRUE);
}
return (FALSE);
}
static const char xdr_err[] = "xdr_%s: out of memory";
bool_t
xdr_bytes(XDR *xdrs, char **cpp, uint_t *sizep, const uint_t maxsize)
{
char *sp = *cpp;
uint_t nodesize;
if (!xdr_u_int(xdrs, sizep))
return (FALSE);
nodesize = *sizep;
if ((nodesize > maxsize) && (xdrs->x_op != XDR_FREE))
return (FALSE);
switch (xdrs->x_op) {
case XDR_DECODE:
if (nodesize == 0)
return (TRUE);
if (sp == NULL)
*cpp = sp = malloc(nodesize);
if (sp == NULL) {
(void) syslog(LOG_ERR, xdr_err, (const char *)"bytes");
return (FALSE);
}
case XDR_ENCODE:
return (xdr_opaque(xdrs, sp, nodesize));
case XDR_FREE:
if (sp != NULL) {
free(sp);
*cpp = NULL;
}
return (TRUE);
}
return (FALSE);
}
bool_t
xdr_netobj(XDR *xdrs, struct netobj *np)
{
return (xdr_bytes(xdrs, &np->n_bytes, &np->n_len, MAX_NETOBJ_SZ));
}
bool_t
xdr_union(XDR *xdrs, enum_t *dscmp, char *unp,
const struct xdr_discrim *choices, const xdrproc_t dfault)
{
enum_t dscm;
if (!xdr_enum(xdrs, dscmp))
return (FALSE);
dscm = *dscmp;
for (; choices->proc != NULL_xdrproc_t; choices++) {
if (choices->value == dscm)
return ((*(choices->proc))(xdrs, unp, LASTUNSIGNED));
}
return ((dfault == NULL_xdrproc_t) ? FALSE :
(*dfault)(xdrs, unp, LASTUNSIGNED));
}
bool_t
xdr_string(XDR *xdrs, char **cpp, const uint_t maxsize)
{
char *newsp, *sp = *cpp;
uint_t size, block;
uint64_t bytesread;
switch (xdrs->x_op) {
case XDR_FREE:
if (sp == NULL)
return (TRUE);
case XDR_ENCODE:
size = (sp != NULL) ? (uint_t)strlen(sp) : 0;
break;
}
if (!xdr_u_int(xdrs, &size))
return (FALSE);
if (size > maxsize)
return (FALSE);
switch (xdrs->x_op) {
case XDR_DECODE:
if (sp != NULL) {
if (!xdr_opaque(xdrs, sp, size))
return (FALSE);
sp[size] = 0;
return (TRUE);
}
bytesread = 0;
do {
block = MIN(size - bytesread, FRAGMENT);
newsp = realloc(sp, bytesread + block + 1);
if (newsp == NULL) {
if (sp != NULL)
free(sp);
return (FALSE);
}
sp = newsp;
if (!xdr_opaque(xdrs, &sp[bytesread], block)) {
free(sp);
return (FALSE);
}
bytesread += block;
} while (bytesread < size);
sp[bytesread] = 0;
*cpp = sp;
return (TRUE);
case XDR_ENCODE:
return (xdr_opaque(xdrs, sp, size));
case XDR_FREE:
free(sp);
*cpp = NULL;
return (TRUE);
}
return (FALSE);
}
bool_t
xdr_hyper(XDR *xdrs, longlong_t *hp)
{
switch (xdrs->x_op) {
case XDR_ENCODE:
#if defined(_LONG_LONG_HTOL)
if (XDR_PUTINT32(xdrs, (int *)hp) == TRUE)
return (XDR_PUTINT32(xdrs, (int *)((char *)hp +
BYTES_PER_XDR_UNIT)));
#else
if (XDR_PUTINT32(xdrs, (int *)((char *)hp +
BYTES_PER_XDR_UNIT)) == TRUE)
return (XDR_PUTINT32(xdrs, (int32_t *)hp));
#endif
return (FALSE);
case XDR_DECODE:
#if defined(_LONG_LONG_HTOL)
if (XDR_GETINT32(xdrs, (int *)hp) == FALSE ||
(XDR_GETINT32(xdrs, (int *)((char *)hp +
BYTES_PER_XDR_UNIT)) == FALSE))
return (FALSE);
#else
if ((XDR_GETINT32(xdrs, (int *)((char *)hp +
BYTES_PER_XDR_UNIT)) == FALSE) ||
(XDR_GETINT32(xdrs, (int *)hp) == FALSE))
return (FALSE);
#endif
return (TRUE);
case XDR_FREE:
return (TRUE);
}
return (FALSE);
}
bool_t
xdr_u_hyper(XDR *xdrs, u_longlong_t *hp)
{
return (xdr_hyper(xdrs, (longlong_t *)hp));
}
bool_t
xdr_longlong_t(XDR *xdrs, longlong_t *hp)
{
return (xdr_hyper(xdrs, hp));
}
bool_t
xdr_u_longlong_t(XDR *xdrs, u_longlong_t *hp)
{
return (xdr_hyper(xdrs, (longlong_t *)hp));
}
bool_t
xdr_wrapstring(XDR *xdrs, char **cpp)
{
return (xdr_string(xdrs, cpp, LASTUNSIGNED));
}