Example #1
0
bool_t xdr_Create_LinkParms (XDR *xdrs, Create_LinkParms *objp)
{
#if defined(SOLARIS) && !defined(_LP64)
  register long *buf;
#else
  register int32_t *buf;
#endif

  if (xdrs->x_op == XDR_ENCODE) {
    buf = XDR_INLINE (xdrs, 3 * BYTES_PER_XDR_UNIT);
    if (buf == NULL) {
      if (!xdr_long (xdrs, &objp->clientId))
        return FALSE;
      if (!xdr_bool (xdrs, &objp->lockDevice))
        return FALSE;
      if (!xdr_u_long (xdrs, &objp->lock_timeout))
        return FALSE;

    } else {
      IXDR_PUT_INT32(buf, objp->clientId);
      IXDR_PUT_BOOL(buf, objp->lockDevice);
      IXDR_PUT_U_INT32(buf, objp->lock_timeout);
    }
    if (!xdr_string (xdrs, &objp->device, ~0))
      return FALSE;
    return TRUE;
  } else if (xdrs->x_op == XDR_DECODE) {
    buf = XDR_INLINE (xdrs, 3 * BYTES_PER_XDR_UNIT);
    if (buf == NULL) {
      if (!xdr_long (xdrs, &objp->clientId))
        return FALSE;
      if (!xdr_bool (xdrs, &objp->lockDevice))
        return FALSE;
      if (!xdr_u_long (xdrs, &objp->lock_timeout))
        return FALSE;

    } else {
      objp->clientId = IXDR_GET_INT32(buf);
      objp->lockDevice = IXDR_GET_BOOL(buf);
      objp->lock_timeout = IXDR_GET_U_INT32(buf);
    }
    if (!xdr_string (xdrs, &objp->device, ~0))
      return FALSE;
    return TRUE;
  }

  if (!xdr_long (xdrs, &objp->clientId))
    return FALSE;
  if (!xdr_bool (xdrs, &objp->lockDevice))
    return FALSE;
  if (!xdr_u_long (xdrs, &objp->lock_timeout))
    return FALSE;
  if (!xdr_string (xdrs, &objp->device, ~0))
    return FALSE;
  return TRUE;
}
Example #2
0
/*
 * encrypt/decrypt ID (val1) and R (val2)
 * return FALSE on failure and TRUE on success
 */
bool_t
__npd_ecb_crypt(
	uint32_t	*val1,
	uint32_t	*val2,
	des_block	*buf,
	unsigned int	bufsize,
	unsigned int	mode,
	des_block	*deskey)
{
	int	status;
	int32_t	*ixdr;


	if (bufsize > MAX_KEY_CRYPT_LEN)
		return (FALSE);
	ixdr = (int32_t *)buf;
	if (mode == DES_ENCRYPT) {
		(void) memset((char *)buf, 0, bufsize);
		IXDR_PUT_U_INT32(ixdr, *val1);
		IXDR_PUT_U_INT32(ixdr, *val2);

		status = ecb_crypt((char *)deskey, (char *)buf,
				bufsize, mode | DES_HW);
		if (DES_FAILED(status))
			return (FALSE);
	} else {
		status = ecb_crypt((char *)deskey, (char *)buf,
				bufsize, mode | DES_HW);

		if (DES_FAILED(status))
			return (FALSE);

		*val1 = IXDR_GET_U_INT32(ixdr);
		*val2 = IXDR_GET_U_INT32(ixdr);
	}
	return (TRUE);
}
Example #3
0
/*
 * encrypt/decrypt R (val) and password (str)
 * return FALSE on failure and TRUE on success
 */
bool_t
__npd_cbc_crypt(
	uint32_t	*val,
	char	*str,
	unsigned int	strsize,
	npd_newpass	*buf,
	unsigned int	bufsize,
	unsigned int	mode,
	des_block	*deskey)
{
	int	status, i;
	int32_t	*ixdr;
	des_block	ivec;

	if (bufsize > MAX_KEY_CRYPT_LEN)
		return (FALSE);
	ivec.key.low = ivec.key.high = 0;
	ixdr = (int32_t *)buf;
	if (mode == DES_ENCRYPT) {
		if ((strsize + 4) > bufsize)
			return (FALSE);
		IXDR_PUT_U_INT32(ixdr, *val);
		(void) strcpy((char *)buf->pass, str);
		for (i = strsize; i < __NPD_MAXPASSBYTES; i++)
			buf->pass[i] = '\0';

		status = cbc_crypt((char *)deskey, (char *)buf,
				bufsize, mode | DES_HW, (char *)&ivec);
		if (DES_FAILED(status))
			return (FALSE);
	} else {
		status = cbc_crypt((char *)deskey, (char *)buf,
				bufsize, mode | DES_HW, (char *)&ivec);

		if (DES_FAILED(status))
			return (FALSE);

		*val = IXDR_GET_U_INT32(ixdr);
		if (strlen((char *)buf->pass) > strsize)
			return (FALSE);
		(void) strcpy(str, (char *)buf->pass);
	}
	return (TRUE);
}
Example #4
0
static enum clnt_stat
clnt_dg_send(CLIENT *cl, rpcproc_t proc, xdrproc_t xargs, caddr_t argsp)
{
/* LINTED pointer alignment */
	struct cu_data *cu = (struct cu_data *)cl->cl_private;
	XDR *xdrs;
	int outlen;
	struct t_unitdata tu_data;
	uint32_t x_id;

	if (rpc_fd_lock(dgtbl, cu->cu_fd)) {
		rpc_callerr.re_status = RPC_FAILED;
		rpc_callerr.re_errno = errno;
		rpc_fd_unlock(dgtbl, cu->cu_fd);
		return (RPC_FAILED);
	}

	tu_data.addr = cu->cu_raddr;

	xdrs = &(cu->cu_outxdrs);
	xdrs->x_op = XDR_ENCODE;
	XDR_SETPOS(xdrs, 0);
	/*
	 * Due to little endian byte order, it is necessary to convert to host
	 * format before incrementing xid.
	 */
/* LINTED pointer alignment */
	x_id = ntohl(*(uint32_t *)(cu->cu_outbuf)) + 1;		/* set XID */
	/* LINTED pointer cast */
	*(uint32_t *)cu->cu_outbuf = htonl(x_id);

	if (cl->cl_auth->ah_cred.oa_flavor != RPCSEC_GSS) {
		if ((!XDR_PUTBYTES(xdrs, cu->cu_outbuf, cu->cu_xdrpos)) ||
		    (!XDR_PUTINT32(xdrs, (int32_t *)&proc)) ||
		    (!AUTH_MARSHALL(cl->cl_auth, xdrs)) ||
		    (!xargs(xdrs, argsp))) {
			rpc_fd_unlock(dgtbl, cu->cu_fd);
			return (rpc_callerr.re_status = RPC_CANTENCODEARGS);
		}
	} else {
/* LINTED pointer alignment */
		uint32_t *u = (uint32_t *)&cu->cu_outbuf[cu->cu_xdrpos];
		IXDR_PUT_U_INT32(u, proc);
		if (!__rpc_gss_wrap(cl->cl_auth, cu->cu_outbuf,
		    ((char *)u) - cu->cu_outbuf, xdrs, xargs, argsp)) {
			rpc_fd_unlock(dgtbl, cu->cu_fd);
			return (rpc_callerr.re_status = RPC_CANTENCODEARGS);
		}
	}
	outlen = (int)XDR_GETPOS(xdrs);

	tu_data.udata.buf = cu->cu_outbuf_start;
	tu_data.udata.len = outlen;
	tu_data.opt.len = 0;
	if (t_sndudata(cu->cu_fd, &tu_data) == -1) {
		rpc_callerr.re_terrno = t_errno;
		rpc_callerr.re_errno = errno;
		rpc_fd_unlock(dgtbl, cu->cu_fd);
		return (rpc_callerr.re_status = RPC_CANTSEND);
	}

	rpc_fd_unlock(dgtbl, cu->cu_fd);
	return (rpc_callerr.re_status = RPC_SUCCESS);
}
Example #5
0
static enum clnt_stat
clnt_dg_call(CLIENT *cl, rpcproc_t proc, xdrproc_t xargs, caddr_t argsp,
	xdrproc_t xresults, caddr_t resultsp, struct timeval utimeout)
{
/* LINTED pointer alignment */
	struct cu_data *cu = (struct cu_data *)cl->cl_private;
	XDR *xdrs;
	int outlen;
	struct rpc_msg reply_msg;
	XDR reply_xdrs;
	struct timeval time_waited;
	bool_t ok;
	int nrefreshes = 2;		/* number of times to refresh cred */
	struct timeval timeout;
	struct timeval retransmit_time;
	struct timeval poll_time;
	struct timeval startime, curtime;
	struct t_unitdata tu_data;
	int res;			/* result of operations */
	uint32_t x_id;

	if (rpc_fd_lock(dgtbl, cu->cu_fd)) {
		rpc_callerr.re_status = RPC_FAILED;
		rpc_callerr.re_errno = errno;
		rpc_fd_unlock(dgtbl, cu->cu_fd);
		return (RPC_FAILED);
	}

	if (cu->cu_total.tv_usec == -1) {
		timeout = utimeout;	/* use supplied timeout */
	} else {
		timeout = cu->cu_total;	/* use default timeout */
	}

	time_waited.tv_sec = 0;
	time_waited.tv_usec = 0;
	retransmit_time = cu->cu_wait;

	tu_data.addr = cu->cu_raddr;

call_again:
	xdrs = &(cu->cu_outxdrs);
	xdrs->x_op = XDR_ENCODE;
	XDR_SETPOS(xdrs, 0);
	/*
	 * Due to little endian byte order, it is necessary to convert to host
	 * format before incrementing xid.
	 */
	/* LINTED pointer cast */
	x_id = ntohl(*(uint32_t *)(cu->cu_outbuf)) + 1;		/* set XID */
	/* LINTED pointer cast */
	*(uint32_t *)cu->cu_outbuf = htonl(x_id);

	if (cl->cl_auth->ah_cred.oa_flavor != RPCSEC_GSS) {
		if ((!XDR_PUTBYTES(xdrs, cu->cu_outbuf, cu->cu_xdrpos)) ||
		    (!XDR_PUTINT32(xdrs, (int32_t *)&proc)) ||
		    (!AUTH_MARSHALL(cl->cl_auth, xdrs)) ||
		    (!xargs(xdrs, argsp))) {
			rpc_fd_unlock(dgtbl, cu->cu_fd);
			return (rpc_callerr.re_status = RPC_CANTENCODEARGS);
		}
	} else {
/* LINTED pointer alignment */
		uint32_t *u = (uint32_t *)&cu->cu_outbuf[cu->cu_xdrpos];
		IXDR_PUT_U_INT32(u, proc);
		if (!__rpc_gss_wrap(cl->cl_auth, cu->cu_outbuf,
		    ((char *)u) - cu->cu_outbuf, xdrs, xargs, argsp)) {
			rpc_fd_unlock(dgtbl, cu->cu_fd);
			return (rpc_callerr.re_status = RPC_CANTENCODEARGS);
		}
	}
	outlen = (int)XDR_GETPOS(xdrs);

send_again:
	tu_data.udata.buf = cu->cu_outbuf_start;
	tu_data.udata.len = outlen;
	tu_data.opt.len = 0;
	if (t_sndudata(cu->cu_fd, &tu_data) == -1) {
		rpc_callerr.re_terrno = t_errno;
		rpc_callerr.re_errno = errno;
		rpc_fd_unlock(dgtbl, cu->cu_fd);
		return (rpc_callerr.re_status = RPC_CANTSEND);
	}

	/*
	 * Hack to provide rpc-based message passing
	 */
	if (timeout.tv_sec == 0 && timeout.tv_usec == 0) {
		rpc_fd_unlock(dgtbl, cu->cu_fd);
		return (rpc_callerr.re_status = RPC_TIMEDOUT);
	}
	/*
	 * sub-optimal code appears here because we have
	 * some clock time to spare while the packets are in flight.
	 * (We assume that this is actually only executed once.)
	 */
	reply_msg.acpted_rply.ar_verf = _null_auth;
	reply_msg.acpted_rply.ar_results.where = NULL;
	reply_msg.acpted_rply.ar_results.proc = xdr_void;

	/*
	 * Set polling time so that we don't wait for
	 * longer than specified by the total time to wait,
	 * or the retransmit time.
	 */
	poll_time.tv_sec = timeout.tv_sec - time_waited.tv_sec;
	poll_time.tv_usec = timeout.tv_usec - time_waited.tv_usec;
	while (poll_time.tv_usec < 0) {
		poll_time.tv_usec += 1000000;
		poll_time.tv_sec--;
	}

	if (poll_time.tv_sec < 0 || (poll_time.tv_sec == 0 &&
	    poll_time.tv_usec == 0)) {
		/*
		 * this could happen if time_waited >= timeout
		 */
		rpc_fd_unlock(dgtbl, cu->cu_fd);
		return (rpc_callerr.re_status = RPC_TIMEDOUT);
	}

	if (poll_time.tv_sec > retransmit_time.tv_sec ||
	    (poll_time.tv_sec == retransmit_time.tv_sec &&
	    poll_time.tv_usec > retransmit_time.tv_usec))
		poll_time = retransmit_time;


	for (;;) {

		(void) gettimeofday(&startime, NULL);

		switch (poll(&cu->pfdp, 1,
		    __rpc_timeval_to_msec(&poll_time))) {
		case -1:
			if (errno != EINTR && errno != EAGAIN) {
				rpc_callerr.re_errno = errno;
				rpc_callerr.re_terrno = 0;
				rpc_fd_unlock(dgtbl, cu->cu_fd);
				return (rpc_callerr.re_status = RPC_CANTRECV);
			}
			/*FALLTHROUGH*/

		case 0:
			/*
			 * update time waited
			 */
timeout:			(void) gettimeofday(&curtime, NULL);
			time_waited.tv_sec += curtime.tv_sec - startime.tv_sec;
			time_waited.tv_usec += curtime.tv_usec -
			    startime.tv_usec;
			while (time_waited.tv_usec >= 1000000) {
				time_waited.tv_usec -= 1000000;
				time_waited.tv_sec++;
			}
			while (time_waited.tv_usec < 0) {
				time_waited.tv_usec += 1000000;
				time_waited.tv_sec--;
			}

			/*
			 * decrement time left to poll by same amount
			 */
			poll_time.tv_sec -= curtime.tv_sec - startime.tv_sec;
			poll_time.tv_usec -= curtime.tv_usec - startime.tv_usec;
			while (poll_time.tv_usec >= 1000000) {
				poll_time.tv_usec -= 1000000;
				poll_time.tv_sec++;
			}
			while (poll_time.tv_usec < 0) {
				poll_time.tv_usec += 1000000;
				poll_time.tv_sec--;
			}

			/*
			 * if there's time left to poll, poll again
			 */
			if (poll_time.tv_sec > 0 ||
			    (poll_time.tv_sec == 0 && poll_time.tv_usec > 0))
				continue;

			/*
			 * if there's more time left, retransmit;
			 * otherwise, return timeout error
			 */
			if (time_waited.tv_sec < timeout.tv_sec ||
			    (time_waited.tv_sec == timeout.tv_sec &&
			    time_waited.tv_usec < timeout.tv_usec)) {
				/*
				 * update retransmit_time
				 */
				retransmit_time.tv_usec *= 2;
				retransmit_time.tv_sec *= 2;
				while (retransmit_time.tv_usec >= 1000000) {
					retransmit_time.tv_usec -= 1000000;
					retransmit_time.tv_sec++;
				}
				if (retransmit_time.tv_sec >= RPC_MAX_BACKOFF) {
					retransmit_time.tv_sec =
					    RPC_MAX_BACKOFF;
					retransmit_time.tv_usec = 0;
				}
				/*
				 * redo AUTH_MARSHAL if AUTH_DES or RPCSEC_GSS.
				 */
				if (cl->cl_auth->ah_cred.oa_flavor ==
				    AUTH_DES ||
				    cl->cl_auth->ah_cred.oa_flavor ==
				    RPCSEC_GSS)
					goto call_again;
				else
					goto send_again;
			}
			rpc_fd_unlock(dgtbl, cu->cu_fd);
			return (rpc_callerr.re_status = RPC_TIMEDOUT);

		default:
			break;
		}

		if (cu->pfdp.revents & POLLNVAL || (cu->pfdp.revents == 0)) {
			rpc_callerr.re_status = RPC_CANTRECV;
			/*
			 *	Note:  we're faking errno here because we
			 *	previously would have expected select() to
			 *	return -1 with errno EBADF.  Poll(BA_OS)
			 *	returns 0 and sets the POLLNVAL revents flag
			 *	instead.
			 */
			rpc_callerr.re_errno = errno = EBADF;
			rpc_fd_unlock(dgtbl, cu->cu_fd);
			return (-1);
		}

		/* We have some data now */
		do {
			int moreflag;		/* flag indicating more data */

			moreflag = 0;

			res = t_rcvudata(cu->cu_fd, cu->cu_tr_data, &moreflag);

			if (moreflag & T_MORE) {
				/*
				 * Drop this packet. I aint got any
				 * more space.
				 */
				res = -1;
				/* I should not really be doing this */
				errno = 0;
				/*
				 * XXX: Not really Buffer overflow in the
				 * sense of TLI.
				 */
				t_errno = TBUFOVFLW;
			}
		} while (res < 0 && (t_errno == TSYSERR && errno == EINTR));
		if (res < 0) {
			int err, errnoflag = FALSE;
#ifdef sun
			if (t_errno == TSYSERR && errno == EWOULDBLOCK)
#else
			if (t_errno == TSYSERR && errno == EAGAIN)
#endif
				continue;
			if (t_errno == TLOOK) {
				if ((err = _rcv_unitdata_err(cu)) == 0)
					continue;
				else if (err == 1)
					errnoflag = TRUE;
			} else {
				rpc_callerr.re_terrno = t_errno;
			}
			if (errnoflag == FALSE)
				rpc_callerr.re_errno = errno;
			rpc_fd_unlock(dgtbl, cu->cu_fd);
			return (rpc_callerr.re_status = RPC_CANTRECV);
		}
		if (cu->cu_tr_data->udata.len < (uint_t)sizeof (uint32_t))
			continue;
		/* see if reply transaction id matches sent id */
		/* LINTED pointer alignment */
		if (*((uint32_t *)(cu->cu_inbuf)) !=
		    /* LINTED pointer alignment */
		    *((uint32_t *)(cu->cu_outbuf)))
			goto timeout;
		/* we now assume we have the proper reply */
		break;
	}

	/*
	 * now decode and validate the response
	 */

	xdrmem_create(&reply_xdrs, cu->cu_inbuf,
	    (uint_t)cu->cu_tr_data->udata.len, XDR_DECODE);
	ok = xdr_replymsg(&reply_xdrs, &reply_msg);
	/* XDR_DESTROY(&reply_xdrs);	save a few cycles on noop destroy */
	if (ok) {
		if ((reply_msg.rm_reply.rp_stat == MSG_ACCEPTED) &&
		    (reply_msg.acpted_rply.ar_stat == SUCCESS))
			rpc_callerr.re_status = RPC_SUCCESS;
		else
			__seterr_reply(&reply_msg, &(rpc_callerr));

		if (rpc_callerr.re_status == RPC_SUCCESS) {
			if (!AUTH_VALIDATE(cl->cl_auth,
			    &reply_msg.acpted_rply.ar_verf)) {
				rpc_callerr.re_status = RPC_AUTHERROR;
				rpc_callerr.re_why = AUTH_INVALIDRESP;
			} else if (cl->cl_auth->ah_cred.oa_flavor !=
			    RPCSEC_GSS) {
				if (!(*xresults)(&reply_xdrs, resultsp)) {
					if (rpc_callerr.re_status ==
					    RPC_SUCCESS)
						rpc_callerr.re_status =
						    RPC_CANTDECODERES;
				}
			} else if (!__rpc_gss_unwrap(cl->cl_auth, &reply_xdrs,
			    xresults, resultsp)) {
				if (rpc_callerr.re_status == RPC_SUCCESS)
					rpc_callerr.re_status =
					    RPC_CANTDECODERES;
			}
		}		/* end successful completion */
		/*
		 * If unsuccesful AND error is an authentication error
		 * then refresh credentials and try again, else break
		 */
		else if (rpc_callerr.re_status == RPC_AUTHERROR)
			/* maybe our credentials need to be refreshed ... */
			if (nrefreshes-- &&
			    AUTH_REFRESH(cl->cl_auth, &reply_msg))
				goto call_again;
			else
				/*
				 * We are setting rpc_callerr here given that
				 * libnsl is not reentrant thereby
				 * reinitializing the TSD.  If not set here then
				 * success could be returned even though refresh
				 * failed.
				 */
				rpc_callerr.re_status = RPC_AUTHERROR;

		/* end of unsuccessful completion */
		/* free verifier */
		if (reply_msg.rm_reply.rp_stat == MSG_ACCEPTED &&
		    reply_msg.acpted_rply.ar_verf.oa_base != NULL) {
			xdrs->x_op = XDR_FREE;
			(void) xdr_opaque_auth(xdrs,
			    &(reply_msg.acpted_rply.ar_verf));
		}
	}	/* end of valid reply message */
	else {
		rpc_callerr.re_status = RPC_CANTDECODERES;

	}
	rpc_fd_unlock(dgtbl, cu->cu_fd);
	return (rpc_callerr.re_status);
}
Example #6
0
bool_t xdr_Device_ReadParms (XDR *xdrs, Device_ReadParms *objp)
{
#if defined(SOLARIS) && !defined(_LP64)
  register long *buf;
#else
  register int32_t *buf;
#endif

  if (xdrs->x_op == XDR_ENCODE) {
    if (!xdr_Device_Link (xdrs, &objp->lid))
      return FALSE;
    buf = XDR_INLINE (xdrs, 3 * BYTES_PER_XDR_UNIT);
    if (buf == NULL) {
      if (!xdr_u_long (xdrs, &objp->requestSize))
        return FALSE;
      if (!xdr_u_long (xdrs, &objp->io_timeout))
        return FALSE;
      if (!xdr_u_long (xdrs, &objp->lock_timeout))
        return FALSE;

    } else {
      IXDR_PUT_U_INT32(buf, objp->requestSize);
      IXDR_PUT_U_INT32(buf, objp->io_timeout);
      IXDR_PUT_U_INT32(buf, objp->lock_timeout);
    }
    if (!xdr_Device_Flags (xdrs, &objp->flags))
      return FALSE;
    if (!xdr_char (xdrs, &objp->termChar))
      return FALSE;
    return TRUE;
  } else if (xdrs->x_op == XDR_DECODE) {
    if (!xdr_Device_Link (xdrs, &objp->lid))
      return FALSE;
    buf = XDR_INLINE (xdrs, 3 * BYTES_PER_XDR_UNIT);
    if (buf == NULL) {
      if (!xdr_u_long (xdrs, &objp->requestSize))
        return FALSE;
      if (!xdr_u_long (xdrs, &objp->io_timeout))
        return FALSE;
      if (!xdr_u_long (xdrs, &objp->lock_timeout))
        return FALSE;

    } else {
      objp->requestSize = IXDR_GET_U_INT32(buf);
      objp->io_timeout = IXDR_GET_U_INT32(buf);
      objp->lock_timeout = IXDR_GET_U_INT32(buf);
    }
    if (!xdr_Device_Flags (xdrs, &objp->flags))
      return FALSE;
    if (!xdr_char (xdrs, &objp->termChar))
      return FALSE;
    return TRUE;
  }

  if (!xdr_Device_Link (xdrs, &objp->lid))
    return FALSE;
  if (!xdr_u_long (xdrs, &objp->requestSize))
    return FALSE;
  if (!xdr_u_long (xdrs, &objp->io_timeout))
    return FALSE;
  if (!xdr_u_long (xdrs, &objp->lock_timeout))
    return FALSE;
  if (!xdr_Device_Flags (xdrs, &objp->flags))
    return FALSE;
  if (!xdr_char (xdrs, &objp->termChar))
    return FALSE;
  return TRUE;
}
Example #7
0
/*
 * Arguments to remote write and writecache
 */
bool_t
xdr_writeargs(XDR *xdrs, struct nfswriteargs *wa)
{
	int32_t *ptr;
	int32_t *fhp;

	switch (xdrs->x_op) {
	case XDR_DECODE:
		wa->wa_args = &wa->wa_args_buf;
		ptr = XDR_INLINE(xdrs, RNDUP(sizeof (fhandle_t)) +
		    3 * BYTES_PER_XDR_UNIT);
		if (ptr != NULL) {
			fhp = (int32_t *)&wa->wa_fhandle;
			*fhp++ = *ptr++;
			*fhp++ = *ptr++;
			*fhp++ = *ptr++;
			*fhp++ = *ptr++;
			*fhp++ = *ptr++;
			*fhp++ = *ptr++;
			*fhp++ = *ptr++;
			*fhp = *ptr++;
			wa->wa_begoff = IXDR_GET_U_INT32(ptr);
			wa->wa_offset = IXDR_GET_U_INT32(ptr);
			wa->wa_totcount = IXDR_GET_U_INT32(ptr);
			wa->wa_mblk = NULL;
			wa->wa_data = NULL;
			wa->wa_rlist = NULL;
			wa->wa_conn = NULL;
			if (xdrs->x_ops == &xdrmblk_ops) {
				return (xdrmblk_getmblk(xdrs, &wa->wa_mblk,
				    &wa->wa_count));
			} else {
				if (xdrs->x_ops == &xdrrdmablk_ops) {
					if (xdrrdma_getrdmablk(xdrs,
					    &wa->wa_rlist,
					    &wa->wa_count,
					    &wa->wa_conn,
					    NFS_MAXDATA) == TRUE)
					return (xdrrdma_read_from_client(
					    wa->wa_rlist,
					    &wa->wa_conn,
					    wa->wa_count));

					wa->wa_rlist = NULL;
					wa->wa_conn = NULL;
				}
			}

			/*
			 * It is just as efficient to xdr_bytes
			 * an array of unknown length as to inline copy it.
			 */
			return (xdr_bytes(xdrs, &wa->wa_data,
			    &wa->wa_count, NFS_MAXDATA));
		}
		if (xdr_fhandle(xdrs, &wa->wa_fhandle) &&
		    xdr_u_int(xdrs, &wa->wa_begoff) &&
		    xdr_u_int(xdrs, &wa->wa_offset) &&
		    xdr_u_int(xdrs, &wa->wa_totcount)) {
			/* deal with the variety of data transfer types */

			wa->wa_mblk = NULL;
			wa->wa_data = NULL;
			wa->wa_rlist = NULL;
			wa->wa_conn = NULL;

			if (xdrs->x_ops == &xdrmblk_ops) {
				if (xdrmblk_getmblk(xdrs, &wa->wa_mblk,
				    &wa->wa_count) == TRUE)
					return (TRUE);
			} else {
				if (xdrs->x_ops == &xdrrdmablk_ops) {
					if (xdrrdma_getrdmablk(xdrs,
					    &wa->wa_rlist,
					    &wa->wa_count,
					    &wa->wa_conn,
					    NFS_MAXDATA) == TRUE)
					return (xdrrdma_read_from_client(
					    wa->wa_rlist,
					    &wa->wa_conn,
					    wa->wa_count));

					wa->wa_rlist = NULL;
					wa->wa_conn = NULL;
				}
			}
			return (xdr_bytes(xdrs, &wa->wa_data,
			    &wa->wa_count, NFS_MAXDATA));
		}
		return (FALSE);
	case XDR_ENCODE:
		ptr = XDR_INLINE(xdrs, RNDUP(sizeof (fhandle_t)) +
		    3 * BYTES_PER_XDR_UNIT);
		if (ptr != NULL) {
			fhp = (int32_t *)&wa->wa_fhandle;
			*ptr++ = *fhp++;
			*ptr++ = *fhp++;
			*ptr++ = *fhp++;
			*ptr++ = *fhp++;
			*ptr++ = *fhp++;
			*ptr++ = *fhp++;
			*ptr++ = *fhp++;
			*ptr++ = *fhp;
			IXDR_PUT_U_INT32(ptr, wa->wa_begoff);
			IXDR_PUT_U_INT32(ptr, wa->wa_offset);
			IXDR_PUT_U_INT32(ptr, wa->wa_totcount);
		} else {
			if (!(xdr_fhandle(xdrs, &wa->wa_fhandle) &&
			    xdr_u_int(xdrs, &wa->wa_begoff) &&
			    xdr_u_int(xdrs, &wa->wa_offset) &&
			    xdr_u_int(xdrs, &wa->wa_totcount)))
				return (FALSE);
		}

		return (xdr_bytes(xdrs, &wa->wa_data, &wa->wa_count,
		    NFS_MAXDATA));
	case XDR_FREE:
		if (wa->wa_rlist) {
			(void) xdrrdma_free_clist(wa->wa_conn, wa->wa_rlist);
			wa->wa_rlist = NULL;
		}

		if (wa->wa_data != NULL) {
			kmem_free(wa->wa_data, wa->wa_count);
			wa->wa_data = NULL;
		}
		return (TRUE);
	}
	return (FALSE);
}
Example #8
0
bool_t
xdr_rpcbs_rmtcalllist(XDR *xdrs, rpcbs_rmtcalllist *objp)
{
	int32_t *buf;
	struct rpcbs_rmtcalllist **pnext;

	if (xdrs->x_op == XDR_ENCODE) {
	buf = XDR_INLINE(xdrs, 6 * BYTES_PER_XDR_UNIT);
	if (buf == NULL) {
		if (!xdr_u_int32_t(xdrs, &objp->prog)) {
			return (FALSE);
		}
		if (!xdr_u_int32_t(xdrs, &objp->vers)) {
			return (FALSE);
		}
		if (!xdr_u_int32_t(xdrs, &objp->proc)) {
			return (FALSE);
		}
		if (!xdr_int(xdrs, &objp->success)) {
			return (FALSE);
		}
		if (!xdr_int(xdrs, &objp->failure)) {
			return (FALSE);
		}
		if (!xdr_int(xdrs, &objp->indirect)) {
			return (FALSE);
		}
	} else {
		IXDR_PUT_U_INT32(buf, objp->prog);
		IXDR_PUT_U_INT32(buf, objp->vers);
		IXDR_PUT_U_INT32(buf, objp->proc);
		IXDR_PUT_INT32(buf, objp->success);
		IXDR_PUT_INT32(buf, objp->failure);
		IXDR_PUT_INT32(buf, objp->indirect);
	}
	if (!xdr_string(xdrs, &objp->netid, (u_int)~0)) {
		return (FALSE);
	}
	pnext = &objp->next;
	if (!xdr_pointer(xdrs, (char **) pnext,
			sizeof (rpcbs_rmtcalllist),
			(xdrproc_t)xdr_rpcbs_rmtcalllist)) {
		return (FALSE);
	}
	return (TRUE);
	} else if (xdrs->x_op == XDR_DECODE) {
	buf = XDR_INLINE(xdrs, 6 * BYTES_PER_XDR_UNIT);
	if (buf == NULL) {
		if (!xdr_u_int32_t(xdrs, &objp->prog)) {
			return (FALSE);
		}
		if (!xdr_u_int32_t(xdrs, &objp->vers)) {
			return (FALSE);
		}
		if (!xdr_u_int32_t(xdrs, &objp->proc)) {
			return (FALSE);
		}
		if (!xdr_int(xdrs, &objp->success)) {
			return (FALSE);
		}
		if (!xdr_int(xdrs, &objp->failure)) {
			return (FALSE);
		}
		if (!xdr_int(xdrs, &objp->indirect)) {
			return (FALSE);
		}
	} else {
		objp->prog = (rpcprog_t)IXDR_GET_U_INT32(buf);
		objp->vers = (rpcvers_t)IXDR_GET_U_INT32(buf);
		objp->proc = (rpcproc_t)IXDR_GET_U_INT32(buf);
		objp->success = (int)IXDR_GET_INT32(buf);
		objp->failure = (int)IXDR_GET_INT32(buf);
		objp->indirect = (int)IXDR_GET_INT32(buf);
	}
	if (!xdr_string(xdrs, &objp->netid, (u_int)~0)) {
		return (FALSE);
	}
	if (!xdr_pointer(xdrs, (char **) pnext,
			sizeof (rpcbs_rmtcalllist),
			(xdrproc_t)xdr_rpcbs_rmtcalllist)) {
		return (FALSE);
	}
	return (TRUE);
	}
	if (!xdr_u_int32_t(xdrs, &objp->prog)) {
		return (FALSE);
	}
	if (!xdr_u_int32_t(xdrs, &objp->vers)) {
		return (FALSE);
	}
	if (!xdr_u_int32_t(xdrs, &objp->proc)) {
		return (FALSE);
	}
	if (!xdr_int(xdrs, &objp->success)) {
		return (FALSE);
	}
	if (!xdr_int(xdrs, &objp->failure)) {
		return (FALSE);
	}
	if (!xdr_int(xdrs, &objp->indirect)) {
		return (FALSE);
	}
	if (!xdr_string(xdrs, &objp->netid, (u_int)~0)) {
		return (FALSE);
	}
	if (!xdr_pointer(xdrs, (char **) pnext,
			sizeof (rpcbs_rmtcalllist),
			(xdrproc_t)xdr_rpcbs_rmtcalllist)) {
		return (FALSE);
	}
	return (TRUE);
}
Example #9
0
/*
 * 2. Marshal
 */
static bool_t
authdes_marshal(AUTH *auth, XDR *xdrs)
{
/* LINTED pointer alignment */
	struct ad_private *ad = AUTH_PRIVATE(auth);
	struct authdes_cred *cred = &ad->ad_cred;
	struct authdes_verf *verf = &ad->ad_verf;
	des_block cryptbuf[2];	
	des_block ivec;
	int status;
	int len;
	rpc_inline_t *ixdr;

	/*
	 * Figure out the "time", accounting for any time difference
	 * with the server if necessary.
	 */
	(void)gettimeofday(&ad->ad_timestamp, NULL);
	ad->ad_timestamp.tv_sec += ad->ad_timediff.tv_sec;
	ad->ad_timestamp.tv_usec += ad->ad_timediff.tv_usec;
	while (ad->ad_timestamp.tv_usec >= USEC_PER_SEC) {
		ad->ad_timestamp.tv_usec -= USEC_PER_SEC;
		ad->ad_timestamp.tv_sec++;
	}

	/*
	 * XDR the timestamp and possibly some other things, then
	 * encrypt them.
	 */
	ixdr = (rpc_inline_t *)cryptbuf;
	IXDR_PUT_INT32(ixdr, ad->ad_timestamp.tv_sec);
	IXDR_PUT_INT32(ixdr, ad->ad_timestamp.tv_usec);
	if (ad->ad_cred.adc_namekind == ADN_FULLNAME) {
		IXDR_PUT_U_INT32(ixdr, ad->ad_window);
		IXDR_PUT_U_INT32(ixdr, ad->ad_window - 1);
		ivec.key.high = ivec.key.low = 0;	
		status = cbc_crypt((char *)&auth->ah_key, (char *)cryptbuf, 
			(u_int) 2 * sizeof (des_block),
			DES_ENCRYPT | DES_HW, (char *)&ivec);
	} else {
		status = ecb_crypt((char *)&auth->ah_key, (char *)cryptbuf, 
			(u_int) sizeof (des_block),
			DES_ENCRYPT | DES_HW);
	}
	if (DES_FAILED(status)) {
		syslog(LOG_ERR, "authdes_marshal: DES encryption failure");
		return (FALSE);
	}
	ad->ad_verf.adv_xtimestamp = cryptbuf[0];
	if (ad->ad_cred.adc_namekind == ADN_FULLNAME) {
		ad->ad_cred.adc_fullname.window = cryptbuf[1].key.high;
		ad->ad_verf.adv_winverf = cryptbuf[1].key.low;
	} else {
		ad->ad_cred.adc_nickname = ad->ad_nickname;
		ad->ad_verf.adv_winverf = 0;
	}

	/*
	 * Serialize the credential and verifier into opaque
	 * authentication data.
	 */
	if (ad->ad_cred.adc_namekind == ADN_FULLNAME) {
		len = ((1 + 1 + 2 + 1)*BYTES_PER_XDR_UNIT + ad->ad_fullnamelen);
	} else {
		len = (1 + 1)*BYTES_PER_XDR_UNIT;
	}

	if ((ixdr = xdr_inline(xdrs, 2*BYTES_PER_XDR_UNIT))) {
		IXDR_PUT_INT32(ixdr, AUTH_DES);
		IXDR_PUT_INT32(ixdr, len);
	} else {
		ATTEMPT(xdr_putint32(xdrs, (int *)&auth->ah_cred.oa_flavor));
		ATTEMPT(xdr_putint32(xdrs, &len));
	}
	ATTEMPT(xdr_authdes_cred(xdrs, cred));

	len = (2 + 1)*BYTES_PER_XDR_UNIT; 
	if ((ixdr = xdr_inline(xdrs, 2*BYTES_PER_XDR_UNIT))) {
		IXDR_PUT_INT32(ixdr, AUTH_DES);
		IXDR_PUT_INT32(ixdr, len);
	} else {
		ATTEMPT(xdr_putint32(xdrs, (int *)&auth->ah_verf.oa_flavor));
		ATTEMPT(xdr_putint32(xdrs, &len));
	}
	ATTEMPT(xdr_authdes_verf(xdrs, verf));
	return (TRUE);
}
static int
clnt_compose_rpcmsg(CLIENT *h, rpcproc_t procnum,
    rdma_buf_t *rpcmsg, XDR *xdrs,
    xdrproc_t xdr_args, caddr_t argsp)
{
	cku_private_t *p = htop(h);

	if (h->cl_auth->ah_cred.oa_flavor != RPCSEC_GSS) {
		/*
		 * Copy in the preserialized RPC header
		 * information.
		 */
		bcopy(p->cku_rpchdr, rpcmsg->addr, CKU_HDRSIZE);

		/*
		 * transaction id is the 1st thing in the output
		 * buffer.
		 */
		/* LINTED pointer alignment */
		(*(uint32_t *)(rpcmsg->addr)) = p->cku_xid;

		/* Skip the preserialized stuff. */
		XDR_SETPOS(xdrs, CKU_HDRSIZE);

		/* Serialize dynamic stuff into the output buffer. */
		if ((!XDR_PUTINT32(xdrs, (int32_t *)&procnum)) ||
		    (!AUTH_MARSHALL(h->cl_auth, xdrs, p->cku_cred)) ||
		    (!(*xdr_args)(xdrs, argsp))) {
			DTRACE_PROBE(krpc__e__clntrdma__rpcmsg__dynargs);
			return (CLNT_RDMA_FAIL);
		}
		p->cku_outsz = XDR_GETPOS(xdrs);
	} else {
		uint32_t *uproc = (uint32_t *)&p->cku_rpchdr[CKU_HDRSIZE];
		IXDR_PUT_U_INT32(uproc, procnum);
		(*(uint32_t *)(&p->cku_rpchdr[0])) = p->cku_xid;
		XDR_SETPOS(xdrs, 0);

		/* Serialize the procedure number and the arguments. */
		if (!AUTH_WRAP(h->cl_auth, (caddr_t)p->cku_rpchdr,
		    CKU_HDRSIZE+4, xdrs, xdr_args, argsp)) {
			if (rpcmsg->addr != xdrs->x_base) {
				rpcmsg->addr = xdrs->x_base;
				rpcmsg->len = xdr_getbufsize(xdrs);
			}
			DTRACE_PROBE(krpc__e__clntrdma__rpcmsg__procnum);
			return (CLNT_RDMA_FAIL);
		}
		/*
		 * If we had to allocate a new buffer while encoding
		 * then update the addr and len.
		 */
		if (rpcmsg->addr != xdrs->x_base) {
			rpcmsg->addr = xdrs->x_base;
			rpcmsg->len = xdr_getbufsize(xdrs);
		}

		p->cku_outsz = XDR_GETPOS(xdrs);
		DTRACE_PROBE1(krpc__i__compose__size__sec, int, p->cku_outsz)
	}

	return (CLNT_RDMA_SUCCESS);
}
Example #11
0
/*
 * 2. Marshal
 */
static bool_t
authdes_marshal (AUTH *auth, XDR *xdrs)
{
  struct ad_private *ad = AUTH_PRIVATE (auth);
  struct authdes_cred *cred = &ad->ad_cred;
  struct authdes_verf *verf = &ad->ad_verf;
  des_block cryptbuf[2];
  des_block ivec;
  int status;
  int len;
  register int32_t *ixdr;
  struct timeval tval;

  /*
   * Figure out the "time", accounting for any time difference
   * with the server if necessary.
   */
  __gettimeofday (&tval, (struct timezone *) NULL);
  ad->ad_timestamp.tv_sec = tval.tv_sec + ad->ad_timediff.tv_sec;
  ad->ad_timestamp.tv_usec = tval.tv_usec + ad->ad_timediff.tv_usec;
  if (ad->ad_timestamp.tv_usec >= MILLION)
    {
      ad->ad_timestamp.tv_usec -= MILLION;
      ad->ad_timestamp.tv_sec += 1;
    }

  /*
   * XDR the timestamp and possibly some other things, then
   * encrypt them.
   * XXX We have a real Year 2038 problem here.
   */
  ixdr = (int32_t *) cryptbuf;
  IXDR_PUT_INT32 (ixdr, ad->ad_timestamp.tv_sec);
  IXDR_PUT_INT32 (ixdr, ad->ad_timestamp.tv_usec);
  if (ad->ad_cred.adc_namekind == ADN_FULLNAME)
    {
      IXDR_PUT_U_INT32 (ixdr, ad->ad_window);
      IXDR_PUT_U_INT32 (ixdr, ad->ad_window - 1);
      ivec.key.high = ivec.key.low = 0;
      status = cbc_crypt ((char *) &auth->ah_key, (char *) cryptbuf,
	      2 * sizeof (des_block), DES_ENCRYPT | DES_HW, (char *) &ivec);
    }
  else
    status = ecb_crypt ((char *) &auth->ah_key, (char *) cryptbuf,
			sizeof (des_block), DES_ENCRYPT | DES_HW);

  if (DES_FAILED (status))
    {
      debug ("authdes_marshal: DES encryption failure");
      return FALSE;
    }
  ad->ad_verf.adv_xtimestamp = cryptbuf[0];
  if (ad->ad_cred.adc_namekind == ADN_FULLNAME)
    {
      ad->ad_cred.adc_fullname.window = cryptbuf[1].key.high;
      ad->ad_verf.adv_winverf = cryptbuf[1].key.low;
    }
  else
    {
      ad->ad_cred.adc_nickname = ad->ad_nickname;
      ad->ad_verf.adv_winverf = 0;
    }

  /*
   * Serialize the credential and verifier into opaque
   * authentication data.
   */
  if (ad->ad_cred.adc_namekind == ADN_FULLNAME)
    len = ((1 + 1 + 2 + 1) * BYTES_PER_XDR_UNIT + ad->ad_fullnamelen);
  else
    len = (1 + 1) * BYTES_PER_XDR_UNIT;

  if ((ixdr = xdr_inline (xdrs, 2 * BYTES_PER_XDR_UNIT)) != NULL)
    {
      IXDR_PUT_INT32 (ixdr, AUTH_DES);
      IXDR_PUT_U_INT32 (ixdr, len);
    }
  else
    {
      ATTEMPT (xdr_putint32 (xdrs, &auth->ah_cred.oa_flavor));
      ATTEMPT (xdr_putint32 (xdrs, &len));
    }
  ATTEMPT (xdr_authdes_cred (xdrs, cred));

  len = (2 + 1) * BYTES_PER_XDR_UNIT;
  if ((ixdr = xdr_inline (xdrs, 2 * BYTES_PER_XDR_UNIT)) != NULL)
    {
      IXDR_PUT_INT32 (ixdr, AUTH_DES);
      IXDR_PUT_U_INT32 (ixdr, len);
    }
  else
    {
      ATTEMPT (xdr_putint32 (xdrs, &auth->ah_verf.oa_flavor));
      ATTEMPT (xdr_putint32 (xdrs, &len));
    }
  ATTEMPT (xdr_authdes_verf (xdrs, verf));

  return TRUE;
}
Example #12
0
bool xdr_sq_dqblk(XDR * xdrs, sq_dqblk * objp)
{
	register int32_t *buf;

	if (xdrs->x_op == XDR_ENCODE) {
		buf = xdr_inline_encode(xdrs, 8 * BYTES_PER_XDR_UNIT);
		if (buf != NULL) {
			/* most likely */
			IXDR_PUT_U_INT32(buf, objp->rq_bhardlimit);
			IXDR_PUT_U_INT32(buf, objp->rq_bsoftlimit);
			IXDR_PUT_U_INT32(buf, objp->rq_curblocks);
			IXDR_PUT_U_INT32(buf, objp->rq_fhardlimit);
			IXDR_PUT_U_INT32(buf, objp->rq_fsoftlimit);
			IXDR_PUT_U_INT32(buf, objp->rq_curfiles);
			IXDR_PUT_U_INT32(buf, objp->rq_btimeleft);
			IXDR_PUT_U_INT32(buf, objp->rq_ftimeleft);
		} else {
			if (!XDR_PUTUINT32(xdrs, objp->rq_bhardlimit))
				return false;
			if (!XDR_PUTUINT32(xdrs, objp->rq_bsoftlimit))
				return false;
			if (!XDR_PUTUINT32(xdrs, objp->rq_curblocks))
				return false;
			if (!XDR_PUTUINT32(xdrs, objp->rq_fhardlimit))
				return false;
			if (!XDR_PUTUINT32(xdrs, objp->rq_fsoftlimit))
				return false;
			if (!XDR_PUTUINT32(xdrs, objp->rq_curfiles))
				return false;
			if (!XDR_PUTUINT32(xdrs, objp->rq_btimeleft))
				return false;
			if (!XDR_PUTUINT32(xdrs, objp->rq_ftimeleft))
				return false;
		}
		return true;
	}

	if (xdrs->x_op == XDR_DECODE) {
		buf = xdr_inline_decode(xdrs, 8 * BYTES_PER_XDR_UNIT);
		if (buf != NULL) {
			/* most likely */
			objp->rq_bhardlimit = IXDR_GET_U_INT32(buf);
			objp->rq_bsoftlimit = IXDR_GET_U_INT32(buf);
			objp->rq_curblocks = IXDR_GET_U_INT32(buf);
			objp->rq_fhardlimit = IXDR_GET_U_INT32(buf);
			objp->rq_fsoftlimit = IXDR_GET_U_INT32(buf);
			objp->rq_curfiles = IXDR_GET_U_INT32(buf);
			objp->rq_btimeleft = IXDR_GET_U_INT32(buf);
			objp->rq_ftimeleft = IXDR_GET_U_INT32(buf);
		} else {
			if (!XDR_GETUINT32(xdrs, &objp->rq_bhardlimit))
				return false;
			if (!XDR_GETUINT32(xdrs, &objp->rq_bsoftlimit))
				return false;
			if (!XDR_GETUINT32(xdrs, &objp->rq_curblocks))
				return false;
			if (!XDR_GETUINT32(xdrs, &objp->rq_fhardlimit))
				return false;
			if (!XDR_GETUINT32(xdrs, &objp->rq_fsoftlimit))
				return false;
			if (!XDR_GETUINT32(xdrs, &objp->rq_curfiles))
				return false;
			if (!XDR_GETUINT32(xdrs, &objp->rq_btimeleft))
				return false;
			if (!XDR_GETUINT32(xdrs, &objp->rq_ftimeleft))
				return false;
		}
		return true;
	}

	if (!xdr_u_int(xdrs, &objp->rq_bhardlimit))
		return false;
	if (!xdr_u_int(xdrs, &objp->rq_bsoftlimit))
		return false;
	if (!xdr_u_int(xdrs, &objp->rq_curblocks))
		return false;
	if (!xdr_u_int(xdrs, &objp->rq_fhardlimit))
		return false;
	if (!xdr_u_int(xdrs, &objp->rq_fsoftlimit))
		return false;
	if (!xdr_u_int(xdrs, &objp->rq_curfiles))
		return false;
	if (!xdr_u_int(xdrs, &objp->rq_btimeleft))
		return false;
	if (!xdr_u_int(xdrs, &objp->rq_ftimeleft))
		return false;
	return true;
}
Example #13
0
/*
 * encode a reply message, log error messages
 */
bool
xdr_reply_encode(XDR *xdrs, struct rpc_msg *dmsg)
{
	struct opaque_auth *oa;
	int32_t *buf;

	switch (dmsg->rm_reply.rp_stat) {
	case MSG_ACCEPTED:
	{
		struct accepted_reply *ar = (struct accepted_reply *)
						&(dmsg->rm_reply.ru);

		oa = &ar->ar_verf;
		if (oa->oa_length > MAX_AUTH_BYTES) {
			__warnx(TIRPC_DEBUG_FLAG_ERROR,
				"%s:%u ERROR ar_verf.oa_length (%u) > %u",
				__func__, __LINE__,
				oa->oa_length,
				MAX_AUTH_BYTES);
			return (false);
		}
		buf = XDR_INLINE(xdrs,
				 6 * BYTES_PER_XDR_UNIT +
				 RNDUP(oa->oa_length));

		if (buf != NULL) {
			__warnx(TIRPC_DEBUG_FLAG_RPC_MSG,
				"%s:%u ACCEPTED INLINE",
				__func__, __LINE__);
			IXDR_PUT_INT32(buf, dmsg->rm_xid);
			IXDR_PUT_ENUM(buf, dmsg->rm_direction);
			IXDR_PUT_ENUM(buf, dmsg->rm_reply.rp_stat);
			IXDR_PUT_ENUM(buf, oa->oa_flavor);
			IXDR_PUT_INT32(buf, oa->oa_length);
			if (oa->oa_length) {
				memcpy(buf, oa->oa_base, oa->oa_length);
				buf += RNDUP(oa->oa_length) / sizeof(int32_t);
			}

			IXDR_PUT_ENUM(buf, ar->ar_stat);
			switch (ar->ar_stat) {
			case SUCCESS:
				__warnx(TIRPC_DEBUG_FLAG_RPC_MSG,
					"%s:%u SUCCESS",
					__func__, __LINE__);
				return ((*(ar->ar_results.proc))(xdrs,
						ar->ar_results.where));

			case PROG_MISMATCH:
				__warnx(TIRPC_DEBUG_FLAG_RPC_MSG,
					"%s:%u MISMATCH",
					__func__, __LINE__);
				buf = XDR_INLINE(xdrs,
					2 * BYTES_PER_XDR_UNIT);
				if (buf != NULL) {
					IXDR_PUT_ENUM(buf, ar->ar_vers.low);
					IXDR_PUT_ENUM(buf, ar->ar_vers.high);
				} else if (!xdr_putuint32(xdrs,
						&(ar->ar_vers.low))) {
					__warnx(TIRPC_DEBUG_FLAG_ERROR,
						"%s:%u ERROR ar_vers.low %u",
						__func__, __LINE__,
						ar->ar_vers.low);
					return (false);
				} else if (!xdr_putuint32(xdrs,
						&(ar->ar_vers.high))) {
					__warnx(TIRPC_DEBUG_FLAG_ERROR,
						"%s:%u ERROR ar_vers.high %u",
						__func__, __LINE__,
						ar->ar_vers.high);
					return (false);
				}
				/* fallthru */
			case GARBAGE_ARGS:
			case SYSTEM_ERR:
			case PROC_UNAVAIL:
			case PROG_UNAVAIL:
				break;
			};
			return (true);
		} else {
			__warnx(TIRPC_DEBUG_FLAG_RPC_MSG,
				"%s:%u ACCEPTED non-INLINE",
				__func__, __LINE__);
			return (inline_xdr_union(xdrs,
				(enum_t *) &(dmsg->rm_reply.rp_stat),
				(caddr_t)(void *)&(dmsg->rm_reply.ru),
				reply_dscrm, NULL_xdrproc_t));
		}
		/* never arrives here */
		break;
	}
	case MSG_DENIED:
	{
		struct rejected_reply *rr = (struct rejected_reply *)
						&(dmsg->rm_reply.ru);
		switch (rr->rj_stat) {
		case RPC_MISMATCH:
			__warnx(TIRPC_DEBUG_FLAG_RPC_MSG,
				"%s:%u DENIED MISMATCH",
				__func__, __LINE__);
			buf = XDR_INLINE(xdrs, 3 * BYTES_PER_XDR_UNIT);

			if (buf != NULL) {
				IXDR_PUT_ENUM(buf, rr->rj_stat);
				IXDR_PUT_U_INT32(buf, rr->rj_vers.low);
				IXDR_PUT_U_INT32(buf, rr->rj_vers.high);
			} else if (!xdr_putenum(xdrs, rr->rj_stat)) {
				__warnx(TIRPC_DEBUG_FLAG_ERROR,
					"%s:%u ERROR rj_stat %u",
					__func__, __LINE__,
					rr->rj_stat);
				return (false);
			} else if (!xdr_putuint32(xdrs,
						&(rr->rj_vers.low))) {
				__warnx(TIRPC_DEBUG_FLAG_ERROR,
					"%s:%u ERROR rj_vers.low %u",
					__func__, __LINE__,
					rr->rj_vers.low);
				return (false);
			} else if (!xdr_putuint32(xdrs,
						&(rr->rj_vers.high))) {
				__warnx(TIRPC_DEBUG_FLAG_ERROR,
					"%s:%u ERROR rj_vers.high %u",
					__func__, __LINE__,
					rr->rj_vers.high);
				return (false);
			}
			return (true); /* bugfix */
		case AUTH_ERROR:
			__warnx(TIRPC_DEBUG_FLAG_RPC_MSG,
				"%s:%u DENIED AUTH",
				__func__, __LINE__);
			buf = XDR_INLINE(xdrs, 2 * BYTES_PER_XDR_UNIT);

			if (buf != NULL) {
				IXDR_PUT_ENUM(buf, rr->rj_stat);
				IXDR_PUT_ENUM(buf, rr->rj_why);
			} else if (!xdr_putenum(xdrs, rr->rj_stat)) {
				__warnx(TIRPC_DEBUG_FLAG_ERROR,
					"%s:%u ERROR rj_stat %u",
					__func__, __LINE__,
					rr->rj_stat);
				return (false);
			} else if (!xdr_putenum(xdrs, rr->rj_why)) {
				__warnx(TIRPC_DEBUG_FLAG_ERROR,
					"%s:%u ERROR rj_why %u",
					__func__, __LINE__,
					rr->rj_why);
				return (false);
			}
			return (true); /* bugfix */
		default:
			__warnx(TIRPC_DEBUG_FLAG_ERROR,
				"%s:%u ERROR rr->rj_stat (%u)",
				__func__, __LINE__,
				rr->rj_stat);
			break;
		};
		break;
	}
	default:
		__warnx(TIRPC_DEBUG_FLAG_ERROR,
			"%s:%u ERROR dmsg->rm_reply.rp_stat (%u)",
			__func__, __LINE__,
			dmsg->rm_reply.rp_stat);
		break;
	};

	return (false);
}			/* XDR_ENCODE */