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; }
/* * 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); }
/* * 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); }
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); }
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); }
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; }
/* * 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); }
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); }
/* * 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); }
/* * 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; }
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; }
/* * 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 */