/* * XDR 32-bit integers * same as xdr_u_int32_t - open coded to save a proc call! */ bool_t xdr_int32_t(XDR *xdrs, int32_t *int32_p) { long l; switch (xdrs->x_op) { case XDR_ENCODE: l = (long) *int32_p; return (XDR_PUTLONG(xdrs, &l)); case XDR_DECODE: if (!XDR_GETLONG(xdrs, &l)) { return (FALSE); } *int32_p = (int32_t) l; return (TRUE); case XDR_FREE: return (TRUE); } return (FALSE); }
/* * XDR unsigned short integers */ bool_t xdr_u_short(register XDR *xdrs, u_short *usp) { long l; switch (xdrs->x_op) { case XDR_ENCODE: l = (long) *usp; return (XDR_PUTLONG(xdrs, &l)); case XDR_DECODE: if (!XDR_GETLONG(xdrs, &l)) { return (FALSE); } *usp = (u_short) l; return (TRUE); case XDR_FREE: return (TRUE); } return (FALSE); }
/* * XDR unsigned integers */ bool_t xdr_u_int(XDR *xdrs, u_int *up) { u_long l; switch (xdrs->x_op) { case XDR_ENCODE: l = (u_long) *up; return (XDR_PUTLONG(xdrs, (long *)&l)); case XDR_DECODE: if (!XDR_GETLONG(xdrs, (long *)&l)) { return (FALSE); } *up = (u_int) l; return (TRUE); case XDR_FREE: return (TRUE); } return (FALSE); }
/* * XDR short integers */ bool_t xdr_short(XDR *xdrs, short int *sp) { long l; switch (xdrs->x_op) { case XDR_ENCODE: l = (long) *sp; return (XDR_PUTLONG(xdrs, &l)); case XDR_DECODE: if (!XDR_GETLONG(xdrs, &l)) { return (FALSE); } *sp = (short) l; return (TRUE); case XDR_FREE: return (TRUE); } return (FALSE); }
/* * XDR booleans */ bool_t xdr_bool(XDR *xdrs, int32_t *bp) { long lb; switch (xdrs->x_op) { case XDR_ENCODE: lb = *bp ? XDR_TRUE : XDR_FALSE; return (XDR_PUTLONG(xdrs, &lb)); case XDR_DECODE: if (!XDR_GETLONG(xdrs, &lb)) { return (FALSE); } *bp = (lb == XDR_FALSE) ? FALSE : TRUE; return (TRUE); case XDR_FREE: return (TRUE); } return (FALSE); }
/* * XDR integers */ bool_t xdr_int(XDR *xdrs, int *ip) { long l; switch (xdrs->x_op) { case XDR_ENCODE: l = (long) *ip; return (XDR_PUTLONG(xdrs, &l)); case XDR_DECODE: if (!XDR_GETLONG(xdrs, &l)) { return (FALSE); } *ip = (int) l; return (TRUE); case XDR_FREE: return (TRUE); } /* NOTREACHED */ return (FALSE); }
/* * XDR unsigned 16-bit integers */ bool_t xdr_uint16_t(XDR *xdrs, uint16_t *uint16_p) { u_long l; switch (xdrs->x_op) { case XDR_ENCODE: l = (u_long) *uint16_p; return (XDR_PUTLONG(xdrs, (long *)&l)); case XDR_DECODE: if (!XDR_GETLONG(xdrs, (long *)&l)) { return (FALSE); } *uint16_p = (uint16_t) l; return (TRUE); case XDR_FREE: return (TRUE); } /* NOTREACHED */ return (FALSE); }
/* * XDR unsigned short integers */ bool_t xdr_u_short(XDR *xdrs, u_short *usp) { u_long l; switch (xdrs->x_op) { case XDR_ENCODE: VALGRIND_CHECK_DEFINED(*usp); l = (u_long) *usp; return (XDR_PUTLONG(xdrs, (long *) &l)); case XDR_DECODE: if (!XDR_GETLONG(xdrs, (long *) &l)) { return (FALSE); } *usp = (u_short) l; return (TRUE); case XDR_FREE: return (TRUE); } return (FALSE); }
/* * XDR unsigned long integers * same as xdr_long - open coded to save a proc call! */ bool_t xdr_u_long(XDR* xdrs, unsigned long* ulp) { if (xdrs->x_op == XDR_DECODE) { long l; if (XDR_GETLONG(xdrs, &l) == FALSE) return FALSE; *ulp = (uint32_t) l; return TRUE; } if (xdrs->x_op == XDR_ENCODE) { if (sizeof(uint32_t) != sizeof(unsigned long) && (uint32_t) *ulp != *ulp) return FALSE; return (XDR_PUTLONG(xdrs, (long *) ulp)); } if (xdrs->x_op == XDR_FREE) return (TRUE); return (FALSE); }
/* * XDR unsigned short integers */ bool xdr_u_short(XDR *xdrs, u_short *usp) { u_long l; switch (xdrs->x_op) { case XDR_ENCODE: l = (u_long) *usp; return (XDR_PUTLONG(xdrs, (long *)&l)); case XDR_DECODE: if (!XDR_GETLONG(xdrs, (long *)&l)) { return (FALSE); } *usp = (u_short) l; return (TRUE); case XDR_FREE: return (TRUE); } /* NOTREACHED */ return (FALSE); }
enum clnt_stat qrpc_clnt_raw_call(CLIENT *cl, u_long proc, xdrproc_t xargs, caddr_t argsp, xdrproc_t xresults, caddr_t resultsp, struct timeval utimeout) { struct qrpc_clnt_raw_priv *priv = (struct qrpc_clnt_raw_priv *)cl->cl_private; XDR *xdrs_out = &priv->xdrs_out; XDR *xdrs_in = &priv->xdrs_in; struct rpc_msg reply_msg; struct timeval curr_time; struct qrpc_frame_hdr *hdr; uint16_t tmp; if (xargs) { xdrs_out->x_op = XDR_ENCODE; XDR_SETPOS(xdrs_out, priv->xdrs_outpos); if ((!XDR_PUTLONG(xdrs_out, (long *)&proc)) || (!AUTH_MARSHALL(cl->cl_auth, xdrs_out)) || (!(*xargs) (xdrs_out, argsp))) { priv->rpc_error.re_status = RPC_CANTENCODEARGS; return priv->rpc_error.re_status; } tmp = ntohs(priv->out_hdr.seq); priv->out_hdr.seq = htons(tmp + 1); if (qrpc_clnt_raw_call_send(priv, XDR_GETPOS(xdrs_out)) < 0) { return priv->rpc_error.re_status; } } if (gettimeofday(&curr_time, NULL) < 0) { priv->rpc_error.re_status = RPC_SYSTEMERROR; return priv->rpc_error.re_status; } utimeout.tv_sec += curr_time.tv_sec; /* Waiting for reply */ do { if (qrpc_clnt_raw_call_recv(priv) < 0) { if (priv->rpc_error.re_status == RPC_TIMEDOUT) continue; else break; } hdr = (struct qrpc_frame_hdr *)priv->inbuf; if (xargs && priv->out_hdr.seq != hdr->seq) { continue; } xdrs_in->x_op = XDR_DECODE; XDR_SETPOS(xdrs_in, 0); reply_msg.acpted_rply.ar_verf = _null_auth; reply_msg.acpted_rply.ar_results.where = resultsp; reply_msg.acpted_rply.ar_results.proc = xresults; if (xdr_replymsg(xdrs_in, &reply_msg)) { if (reply_msg.rm_xid != (unsigned long)getpid()) { continue; } _seterr_reply(&reply_msg, &priv->rpc_error); if (priv->rpc_error.re_status == RPC_SUCCESS) { if (!AUTH_VALIDATE(cl->cl_auth, &reply_msg.acpted_rply.ar_verf)) { priv->rpc_error.re_status = RPC_AUTHERROR; priv->rpc_error.re_why = AUTH_INVALIDRESP; } break; } } else { priv->rpc_error.re_status = RPC_CANTDECODERES; } } while ((gettimeofday(&curr_time, NULL) == 0) && (curr_time.tv_sec < utimeout.tv_sec)); return priv->rpc_error.re_status; }
static enum clnt_stat clnttcp_call(CLIENT *h, u_long proc, xdrproc_t xdr_args, caddr_t args_ptr, xdrproc_t xdr_results, caddr_t results_ptr, struct timeval timeout) { struct ct_data *ct = (struct ct_data *) h->cl_private; XDR *xdrs = &(ct->ct_xdrs); struct rpc_msg reply_msg; u_long x_id; u_int32_t *msg_x_id = (u_int32_t *)(ct->ct_mcall); /* yuk */ bool_t shipnow; int refreshes = 2; if (!ct->ct_waitset) { ct->ct_wait = timeout; } shipnow = (xdr_results == NULL && timeout.tv_sec == 0 && timeout.tv_usec == 0) ? FALSE : TRUE; call_again: xdrs->x_op = XDR_ENCODE; ct->ct_error.re_status = RPC_SUCCESS; x_id = ntohl(--(*msg_x_id)); if ((! XDR_PUTBYTES(xdrs, ct->ct_mcall, ct->ct_mpos)) || (! XDR_PUTLONG(xdrs, (long *)&proc)) || (! AUTH_MARSHALL(h->cl_auth, xdrs)) || (! (*xdr_args)(xdrs, args_ptr))) { if (ct->ct_error.re_status == RPC_SUCCESS) ct->ct_error.re_status = RPC_CANTENCODEARGS; (void)xdrrec_endofrecord(xdrs, TRUE); return (ct->ct_error.re_status); } if (! xdrrec_endofrecord(xdrs, shipnow)) return (ct->ct_error.re_status = RPC_CANTSEND); if (! shipnow) return (RPC_SUCCESS); /* * Hack to provide rpc-based message passing */ if (timeout.tv_sec == 0 && timeout.tv_usec == 0) { return(ct->ct_error.re_status = RPC_TIMEDOUT); } /* * Keep receiving until we get a valid transaction id */ xdrs->x_op = XDR_DECODE; while (TRUE) { 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; if (! xdrrec_skiprecord(xdrs)) return (ct->ct_error.re_status); /* now decode and validate the response header */ if (! xdr_replymsg(xdrs, &reply_msg)) { if (ct->ct_error.re_status == RPC_SUCCESS) continue; return (ct->ct_error.re_status); } if (reply_msg.rm_xid == x_id) break; } /* * process header */ _seterr_reply(&reply_msg, &(ct->ct_error)); if (ct->ct_error.re_status == RPC_SUCCESS) { if (! AUTH_VALIDATE(h->cl_auth, &reply_msg.acpted_rply.ar_verf)) { ct->ct_error.re_status = RPC_AUTHERROR; ct->ct_error.re_why = AUTH_INVALIDRESP; } else if (! (*xdr_results)(xdrs, results_ptr)) { if (ct->ct_error.re_status == RPC_SUCCESS) ct->ct_error.re_status = RPC_CANTDECODERES; } /* free verifier ... */ if (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 successful completion */ else { /* maybe our credentials need to be refreshed ... */ if (refreshes-- && AUTH_REFRESH(h->cl_auth)) goto call_again; } /* end of unsuccessful completion */ return (ct->ct_error.re_status); }
static enum clnt_stat clntudp_call(CLIENT *cl, unsigned long proc, xdrproc_t xargs, char* argsp, xdrproc_t xresults, char* resultsp, struct timeval utimeout) { register struct cu_data *cu = (struct cu_data *) cl->cl_private; register XDR *xdrs; register int outlen; register int inlen; socklen_t fromlen; struct sockaddr_in from; struct rpc_msg reply_msg; XDR reply_xdrs; bool_t ok; int nrefreshes = 2; /* number of times to refresh cred */ call_again: xdrs = &(cu->cu_outxdrs); xdrs->x_op = XDR_ENCODE; XDR_SETPOS(xdrs, cu->cu_xdrpos); /* * the transaction is the first thing in the out buffer */ (*(unsigned long *) (cu->cu_outbuf))++; if ((!XDR_PUTLONG(xdrs, (long *) &proc)) || (!AUTH_MARSHALL(cl->cl_auth, xdrs)) || (!(*xargs) (xdrs, argsp))) return (cu->cu_error.re_status = RPC_CANTENCODEARGS); outlen = (int) XDR_GETPOS(xdrs); send_again: if (sendto(cu->cu_sock, cu->cu_outbuf, outlen, 0, (struct sockaddr *) &(cu->cu_raddr), cu->cu_rlen) != outlen) { cu->cu_error.re_errno = errno; return (cu->cu_error.re_status = RPC_CANTSEND); } /* * 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 = resultsp; reply_msg.acpted_rply.ar_results.proc = xresults; /* do recv */ do { fromlen = sizeof(struct sockaddr); inlen = recvfrom(cu->cu_sock, cu->cu_inbuf, (int) cu->cu_recvsz, 0, (struct sockaddr *) &from, &fromlen); }while (inlen < 0 && errno == EINTR); if (inlen < 4) { rt_kprintf("recv error, len %d\n", inlen); cu->cu_error.re_errno = errno; return (cu->cu_error.re_status = RPC_CANTRECV); } /* see if reply transaction id matches sent id */ if (*((uint32_t *) (cu->cu_inbuf)) != *((uint32_t *) (cu->cu_outbuf))) goto send_again; /* we now assume we have the proper reply */ /* * now decode and validate the response */ xdrmem_create(&reply_xdrs, cu->cu_inbuf, (unsigned int) inlen, XDR_DECODE); ok = xdr_replymsg(&reply_xdrs, &reply_msg); /* XDR_DESTROY(&reply_xdrs); save a few cycles on noop destroy */ if (ok) { _seterr_reply(&reply_msg, &(cu->cu_error)); if (cu->cu_error.re_status == RPC_SUCCESS) { if (!AUTH_VALIDATE(cl->cl_auth, &reply_msg.acpted_rply.ar_verf)) { cu->cu_error.re_status = RPC_AUTHERROR; cu->cu_error.re_why = AUTH_INVALIDRESP; } if (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 successful completion */ else { /* maybe our credentials need to be refreshed ... */ if (nrefreshes > 0 && AUTH_REFRESH(cl->cl_auth)) { nrefreshes--; goto call_again; } } /* end of unsuccessful completion */ } /* end of valid reply message */ else { cu->cu_error.re_status = RPC_CANTDECODERES; } return (cu->cu_error.re_status); }
static enum clnt_stat clntudp_call ( CLIENT *cl, /* client handle */ u_long proc, /* procedure number */ xdrproc_t xargs, /* xdr routine for args */ caddr_t argsp, /* pointer to args */ xdrproc_t xresults, /* xdr routine for results */ caddr_t resultsp, /* pointer to results */ struct timeval utimeout /* seconds to wait before giving up */) { struct cu_data *cu = (struct cu_data *) cl->cl_private; XDR *xdrs; int outlen = 0; int inlen; socklen_t fromlen; struct pollfd fd; int milliseconds = (cu->cu_wait.tv_sec * 1000) + (cu->cu_wait.tv_usec / 1000); struct sockaddr_in from; 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; int anyup; /* any network interface up */ 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; call_again: xdrs = &(cu->cu_outxdrs); if (xargs == NULL) goto get_reply; xdrs->x_op = XDR_ENCODE; XDR_SETPOS (xdrs, cu->cu_xdrpos); /* * the transaction is the first thing in the out buffer */ (*(uint32_t *) (cu->cu_outbuf))++; if ((!XDR_PUTLONG (xdrs, (long *) &proc)) || (!AUTH_MARSHALL (cl->cl_auth, xdrs)) || (!(*xargs) (xdrs, argsp))) return (cu->cu_error.re_status = RPC_CANTENCODEARGS); outlen = (int) XDR_GETPOS (xdrs); send_again: if (sendto (cu->cu_sock, cu->cu_outbuf, outlen, 0, (struct sockaddr *) &(cu->cu_raddr), cu->cu_rlen) != outlen) { cu->cu_error.re_errno = errno; return (cu->cu_error.re_status = RPC_CANTSEND); } /* * Hack to provide rpc-based message passing */ if (timeout.tv_sec == 0 && timeout.tv_usec == 0) { return (cu->cu_error.re_status = RPC_TIMEDOUT); } get_reply: /* * 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 = resultsp; reply_msg.acpted_rply.ar_results.proc = xresults; fd.fd = cu->cu_sock; fd.events = POLLIN; anyup = 0; for (;;) { switch (poll (&fd, 1, milliseconds)) { case 0: if (anyup == 0) { anyup = is_network_up (cu->cu_sock); if (!anyup) return (cu->cu_error.re_status = RPC_CANTRECV); } time_waited.tv_sec += cu->cu_wait.tv_sec; time_waited.tv_usec += cu->cu_wait.tv_usec; while (time_waited.tv_usec >= 1000000) { time_waited.tv_sec++; time_waited.tv_usec -= 1000000; } if ((time_waited.tv_sec < timeout.tv_sec) || ((time_waited.tv_sec == timeout.tv_sec) && (time_waited.tv_usec < timeout.tv_usec))) goto send_again; return (cu->cu_error.re_status = RPC_TIMEDOUT); /* * buggy in other cases because time_waited is not being * updated. */ case -1: if (errno == EINTR) continue; cu->cu_error.re_errno = errno; return (cu->cu_error.re_status = RPC_CANTRECV); } #ifdef IP_RECVERR if (fd.revents & POLLERR) { struct msghdr msg; struct cmsghdr *cmsg; struct sock_extended_err *e; struct sockaddr_in err_addr; struct iovec iov; char *cbuf = (char *) alloca (outlen + 256); int ret; iov.iov_base = cbuf + 256; iov.iov_len = outlen; msg.msg_name = (void *) &err_addr; msg.msg_namelen = sizeof (err_addr); msg.msg_iov = &iov; msg.msg_iovlen = 1; msg.msg_flags = 0; msg.msg_control = cbuf; msg.msg_controllen = 256; ret = recvmsg (cu->cu_sock, &msg, MSG_ERRQUEUE); if (ret >= 0 && memcmp (cbuf + 256, cu->cu_outbuf, ret) == 0 && (msg.msg_flags & MSG_ERRQUEUE) && ((msg.msg_namelen == 0 && ret >= 12) || (msg.msg_namelen == sizeof (err_addr) && err_addr.sin_family == AF_INET && memcmp (&err_addr.sin_addr, &cu->cu_raddr.sin_addr, sizeof (err_addr.sin_addr)) == 0 && err_addr.sin_port == cu->cu_raddr.sin_port))) for (cmsg = CMSG_FIRSTHDR (&msg); cmsg; cmsg = CMSG_NXTHDR (&msg, cmsg)) if (cmsg->cmsg_level == SOL_IP && cmsg->cmsg_type == IP_RECVERR) { e = (struct sock_extended_err *) CMSG_DATA(cmsg); cu->cu_error.re_errno = e->ee_errno; return (cu->cu_error.re_status = RPC_CANTRECV); } } #endif do { fromlen = sizeof (struct sockaddr); inlen = recvfrom (cu->cu_sock, cu->cu_inbuf, (int) cu->cu_recvsz, 0, (struct sockaddr *) &from, &fromlen); } while (inlen < 0 && errno == EINTR); if (inlen < 0) { if (errno == EWOULDBLOCK) continue; cu->cu_error.re_errno = errno; return (cu->cu_error.re_status = RPC_CANTRECV); } if (inlen < 4) continue; /* see if reply transaction id matches sent id. Don't do this if we only wait for a replay */ if (xargs != NULL && (*((u_int32_t *) (cu->cu_inbuf)) != *((u_int32_t *) (cu->cu_outbuf)))) continue; /* we now assume we have the proper reply */ break; } /* * now decode and validate the response */ xdrmem_create (&reply_xdrs, cu->cu_inbuf, (u_int) inlen, XDR_DECODE); ok = xdr_replymsg (&reply_xdrs, &reply_msg); /* XDR_DESTROY(&reply_xdrs); save a few cycles on noop destroy */ if (ok) { _seterr_reply (&reply_msg, &(cu->cu_error)); if (cu->cu_error.re_status == RPC_SUCCESS) { if (!AUTH_VALIDATE (cl->cl_auth, &reply_msg.acpted_rply.ar_verf)) { cu->cu_error.re_status = RPC_AUTHERROR; cu->cu_error.re_why = AUTH_INVALIDRESP; } if (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 successful completion */ else { /* maybe our credentials need to be refreshed ... */ if (nrefreshes > 0 && AUTH_REFRESH (cl->cl_auth)) { nrefreshes--; goto call_again; } } /* end of unsuccessful completion */ } /* end of valid reply message */ else { cu->cu_error.re_status = RPC_CANTDECODERES; } return cu->cu_error.re_status; }
static enum clnt_stat clntraw_call (CLIENT *h, u_long proc, xdrproc_t xargs, caddr_t argsp, xdrproc_t xresults, caddr_t resultsp, struct timeval timeout) { struct clntraw_private_s *clp = clntraw_private; XDR *xdrs = &clp->xdr_stream; struct rpc_msg msg; enum clnt_stat status; struct rpc_err error; if (clp == NULL) return RPC_FAILED; call_again: /* * send request */ xdrs->x_op = XDR_ENCODE; XDR_SETPOS (xdrs, 0); /* Just checking the union definition to access rm_xid is correct. */ if (offsetof (struct rpc_msg, rm_xid) != 0) abort (); clp->mashl_callmsg.rm_xid++; if ((!XDR_PUTBYTES (xdrs, clp->mashl_callmsg.msg, clp->mcnt)) || (!XDR_PUTLONG (xdrs, (long *) &proc)) || (!AUTH_MARSHALL (h->cl_auth, xdrs)) || (!(*xargs) (xdrs, argsp))) { return (RPC_CANTENCODEARGS); } (void) XDR_GETPOS (xdrs); /* called just to cause overhead */ /* * We have to call server input routine here because this is * all going on in one process. Yuk. */ svc_getreq (1); /* * get results */ xdrs->x_op = XDR_DECODE; XDR_SETPOS (xdrs, 0); msg.acpted_rply.ar_verf = _null_auth; msg.acpted_rply.ar_results.where = resultsp; msg.acpted_rply.ar_results.proc = xresults; if (!xdr_replymsg (xdrs, &msg)) return RPC_CANTDECODERES; _seterr_reply (&msg, &error); status = error.re_status; if (status == RPC_SUCCESS) { if (!AUTH_VALIDATE (h->cl_auth, &msg.acpted_rply.ar_verf)) { status = RPC_AUTHERROR; } } /* end successful completion */ else { if (AUTH_REFRESH (h->cl_auth)) goto call_again; } /* end of unsuccessful completion */ if (status == RPC_SUCCESS) { if (!AUTH_VALIDATE (h->cl_auth, &msg.acpted_rply.ar_verf)) { status = RPC_AUTHERROR; } if (msg.acpted_rply.ar_verf.oa_base != NULL) { xdrs->x_op = XDR_FREE; (void) xdr_opaque_auth (xdrs, &(msg.acpted_rply.ar_verf)); } } return status; }
static enum clnt_stat clnttcp_call( CLIENT *h, rpcproc_t proc, xdrproc_t xdr_args, void * args_ptr, xdrproc_t xdr_results, void * results_ptr, struct timeval timeout) { struct ct_data *ct = h->cl_private; XDR *xdrs = &ct->ct_xdrs; struct rpc_msg reply_msg; uint32_t x_id; uint32_t *msg_x_id = &ct->ct_u.ct_mcalli; /* yuk */ bool_t shipnow; int refreshes = 2; long procl = proc; if (!ct->ct_waitset) { ct->ct_wait = timeout; } shipnow = (xdr_results == (xdrproc_t)0 && timeout.tv_sec == 0 && timeout.tv_usec == 0) ? FALSE : TRUE; call_again: xdrs->x_op = XDR_ENCODE; ct->ct_error.re_status = RPC_SUCCESS; x_id = ntohl(--(*msg_x_id)); if ((! XDR_PUTBYTES(xdrs, ct->ct_u.ct_mcall, ct->ct_mpos)) || (! XDR_PUTLONG(xdrs, &procl)) || (! AUTH_MARSHALL(h->cl_auth, xdrs)) || (! AUTH_WRAP(h->cl_auth, xdrs, xdr_args, args_ptr))) { if (ct->ct_error.re_status == RPC_SUCCESS) ct->ct_error.re_status = RPC_CANTENCODEARGS; (void)xdrrec_endofrecord(xdrs, TRUE); return (ct->ct_error.re_status); } if (! xdrrec_endofrecord(xdrs, shipnow)) return (ct->ct_error.re_status = RPC_CANTSEND); if (! shipnow) return (RPC_SUCCESS); /* * Hack to provide rpc-based message passing */ if (timeout.tv_sec == 0 && timeout.tv_usec == 0) { return(ct->ct_error.re_status = RPC_TIMEDOUT); } /* * Keep receiving until we get a valid transaction id */ xdrs->x_op = XDR_DECODE; while (TRUE) { reply_msg.acpted_rply.ar_verf = gssrpc__null_auth; reply_msg.acpted_rply.ar_results.where = NULL; reply_msg.acpted_rply.ar_results.proc = xdr_void; if (! xdrrec_skiprecord(xdrs)) return (ct->ct_error.re_status); /* now decode and validate the response header */ if (! xdr_replymsg(xdrs, &reply_msg)) { /* * Free some stuff allocated by xdr_replymsg() * to avoid leaks, since it may allocate * memory from partially successful decodes. */ enum xdr_op op = xdrs->x_op; xdrs->x_op = XDR_FREE; xdr_replymsg(xdrs, &reply_msg); xdrs->x_op = op; if (ct->ct_error.re_status == RPC_SUCCESS) continue; return (ct->ct_error.re_status); } if (reply_msg.rm_xid == x_id) break; } /* * process header */ gssrpc__seterr_reply(&reply_msg, &(ct->ct_error)); if (ct->ct_error.re_status == RPC_SUCCESS) { if (! AUTH_VALIDATE(h->cl_auth, &reply_msg.acpted_rply.ar_verf)) { ct->ct_error.re_status = RPC_AUTHERROR; ct->ct_error.re_why = AUTH_INVALIDRESP; } else if (! AUTH_UNWRAP(h->cl_auth, xdrs, xdr_results, results_ptr)) { if (ct->ct_error.re_status == RPC_SUCCESS) ct->ct_error.re_status = RPC_CANTDECODERES; } } /* end successful completion */ else { /* maybe our credentials need to be refreshed ... */ if (refreshes-- && AUTH_REFRESH(h->cl_auth, &reply_msg)) goto call_again; } /* 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)); } return (ct->ct_error.re_status); }