static enum clnt_stat clnt_vc_call(CLIENT *cl, rpcproc_t proc, xdrproc_t xdr_args, void *args_ptr, xdrproc_t xdr_results, void *results_ptr, struct timeval timeout) { struct ct_data *ct = (struct ct_data *) cl->cl_private; XDR *xdrs = &(ct->ct_xdrs); struct rpc_msg reply_msg; u_int32_t x_id; u_int32_t *msg_x_id = &ct->ct_u.ct_mcalli; /* yuk */ bool_t shipnow; int refreshes = 2; sigset_t mask, newmask; int rpc_lock_value; bool_t reply_stat; assert(cl != NULL); sigfillset(&newmask); thr_sigsetmask(SIG_SETMASK, &newmask, &mask); mutex_lock(&clnt_fd_lock); while (vc_fd_locks[ct->ct_fd]) cond_wait(&vc_cv[ct->ct_fd], &clnt_fd_lock); if (__isthreaded) rpc_lock_value = 1; else rpc_lock_value = 0; vc_fd_locks[ct->ct_fd] = rpc_lock_value; mutex_unlock(&clnt_fd_lock); if (!ct->ct_waitset) { /* If time is not within limits, we ignore it. */ if (time_not_ok(&timeout) == FALSE) 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 (cl->cl_auth->ah_cred.oa_flavor != RPCSEC_GSS) { if ((! XDR_PUTBYTES(xdrs, ct->ct_u.ct_mcallc, ct->ct_mpos)) || (! XDR_PUTINT32(xdrs, &proc)) || (! AUTH_MARSHALL(cl->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); release_fd_lock(ct->ct_fd, mask); return (ct->ct_error.re_status); } } else { *(uint32_t *) &ct->ct_u.ct_mcallc[ct->ct_mpos] = htonl(proc); if (! __rpc_gss_wrap(cl->cl_auth, ct->ct_u.ct_mcallc, ct->ct_mpos + sizeof(uint32_t), 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); release_fd_lock(ct->ct_fd, mask); return (ct->ct_error.re_status); } } if (! xdrrec_endofrecord(xdrs, shipnow)) { release_fd_lock(ct->ct_fd, mask); return (ct->ct_error.re_status = RPC_CANTSEND); } if (! shipnow) { release_fd_lock(ct->ct_fd, mask); return (RPC_SUCCESS); } /* * Hack to provide rpc-based message passing */ if (timeout.tv_sec == 0 && timeout.tv_usec == 0) { release_fd_lock(ct->ct_fd, mask); 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 = (xdrproc_t)xdr_void; if (! xdrrec_skiprecord(xdrs)) { release_fd_lock(ct->ct_fd, mask); 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; release_fd_lock(ct->ct_fd, mask); 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(cl->cl_auth, &reply_msg.acpted_rply.ar_verf)) { ct->ct_error.re_status = RPC_AUTHERROR; ct->ct_error.re_why = AUTH_INVALIDRESP; } else { if (cl->cl_auth->ah_cred.oa_flavor != RPCSEC_GSS) { reply_stat = (*xdr_results)(xdrs, results_ptr); } else { reply_stat = __rpc_gss_unwrap(cl->cl_auth, xdrs, xdr_results, results_ptr); } if (! reply_stat) { 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(cl->cl_auth, &reply_msg)) goto call_again; } /* end of unsuccessful completion */ release_fd_lock(ct->ct_fd, mask); return (ct->ct_error.re_status); }
static bool_t clnt_vc_control(CLIENT *cl, u_int request, void *info) { struct ct_data *ct; void *infop = info; sigset_t mask; sigset_t newmask; int rpc_lock_value; assert(cl != NULL); ct = (struct ct_data *)cl->cl_private; sigfillset(&newmask); thr_sigsetmask(SIG_SETMASK, &newmask, &mask); mutex_lock(&clnt_fd_lock); while (vc_fd_locks[ct->ct_fd]) cond_wait(&vc_cv[ct->ct_fd], &clnt_fd_lock); if (__isthreaded) rpc_lock_value = 1; else rpc_lock_value = 0; vc_fd_locks[ct->ct_fd] = rpc_lock_value; mutex_unlock(&clnt_fd_lock); switch (request) { case CLSET_FD_CLOSE: ct->ct_closeit = TRUE; release_fd_lock(ct->ct_fd, mask); return (TRUE); case CLSET_FD_NCLOSE: ct->ct_closeit = FALSE; release_fd_lock(ct->ct_fd, mask); return (TRUE); default: break; } /* for other requests which use info */ if (info == NULL) { release_fd_lock(ct->ct_fd, mask); return (FALSE); } switch (request) { case CLSET_TIMEOUT: if (time_not_ok((struct timeval *)info)) { release_fd_lock(ct->ct_fd, mask); return (FALSE); } ct->ct_wait = *(struct timeval *)infop; ct->ct_waitset = TRUE; break; case CLGET_TIMEOUT: *(struct timeval *)infop = ct->ct_wait; break; case CLGET_SERVER_ADDR: (void) memcpy(info, ct->ct_addr.buf, (size_t)ct->ct_addr.len); break; case CLGET_FD: *(int *)info = ct->ct_fd; break; case CLGET_SVC_ADDR: /* The caller should not free this memory area */ *(struct netbuf *)info = ct->ct_addr; break; case CLSET_SVC_ADDR: /* set to new address */ release_fd_lock(ct->ct_fd, mask); return (FALSE); case CLGET_XID: /* * use the knowledge that xid is the * first element in the call structure * This will get the xid of the PREVIOUS call */ *(u_int32_t *)info = ntohl(*(u_int32_t *)(void *)&ct->ct_u.ct_mcalli); break; case CLSET_XID: /* This will set the xid of the NEXT call */ *(u_int32_t *)(void *)&ct->ct_u.ct_mcalli = htonl(*((u_int32_t *)info) + 1); /* increment by 1 as clnt_vc_call() decrements once */ break; case CLGET_VERS: /* * This RELIES on the information that, in the call body, * the version number field is the fifth field from the * begining of the RPC header. MUST be changed if the * call_struct is changed */ *(u_int32_t *)info = ntohl(*(u_int32_t *)(void *)(ct->ct_u.ct_mcallc + 4 * BYTES_PER_XDR_UNIT)); break; case CLSET_VERS: *(u_int32_t *)(void *)(ct->ct_u.ct_mcallc + 4 * BYTES_PER_XDR_UNIT) = htonl(*(u_int32_t *)info); break; case CLGET_PROG: /* * This RELIES on the information that, in the call body, * the program number field is the fourth field from the * begining of the RPC header. MUST be changed if the * call_struct is changed */ *(u_int32_t *)info = ntohl(*(u_int32_t *)(void *)(ct->ct_u.ct_mcallc + 3 * BYTES_PER_XDR_UNIT)); break; case CLSET_PROG: *(u_int32_t *)(void *)(ct->ct_u.ct_mcallc + 3 * BYTES_PER_XDR_UNIT) = htonl(*(u_int32_t *)info); break; default: release_fd_lock(ct->ct_fd, mask); return (FALSE); } release_fd_lock(ct->ct_fd, mask); return (TRUE); }
static bool_t clnt_dg_control(CLIENT *cl, int request, char *info) { /* LINTED pointer alignment */ struct cu_data *cu = (struct cu_data *)cl->cl_private; struct netbuf *addr; if (rpc_fd_lock(dgtbl, cu->cu_fd)) { rpc_fd_unlock(dgtbl, cu->cu_fd); return (FALSE); } switch (request) { case CLSET_FD_CLOSE: cu->cu_closeit = TRUE; rpc_fd_unlock(dgtbl, cu->cu_fd); return (TRUE); case CLSET_FD_NCLOSE: cu->cu_closeit = FALSE; rpc_fd_unlock(dgtbl, cu->cu_fd); return (TRUE); } /* for other requests which use info */ if (info == NULL) { rpc_fd_unlock(dgtbl, cu->cu_fd); return (FALSE); } switch (request) { case CLSET_TIMEOUT: /* LINTED pointer alignment */ if (time_not_ok((struct timeval *)info)) { rpc_fd_unlock(dgtbl, cu->cu_fd); return (FALSE); } /* LINTED pointer alignment */ cu->cu_total = *(struct timeval *)info; break; case CLGET_TIMEOUT: /* LINTED pointer alignment */ *(struct timeval *)info = cu->cu_total; break; case CLGET_SERVER_ADDR: /* Give him the fd address */ /* Now obsolete. Only for backword compatibility */ (void) memcpy(info, cu->cu_raddr.buf, (size_t)cu->cu_raddr.len); break; case CLSET_RETRY_TIMEOUT: /* LINTED pointer alignment */ if (time_not_ok((struct timeval *)info)) { rpc_fd_unlock(dgtbl, cu->cu_fd); return (FALSE); } /* LINTED pointer alignment */ cu->cu_wait = *(struct timeval *)info; break; case CLGET_RETRY_TIMEOUT: /* LINTED pointer alignment */ *(struct timeval *)info = cu->cu_wait; break; case CLGET_FD: /* LINTED pointer alignment */ *(int *)info = cu->cu_fd; break; case CLGET_SVC_ADDR: /* LINTED pointer alignment */ *(struct netbuf *)info = cu->cu_raddr; break; case CLSET_SVC_ADDR: /* set to new address */ /* LINTED pointer alignment */ addr = (struct netbuf *)info; if (cu->cu_raddr.maxlen < addr->len) { free(cu->cu_raddr.buf); if ((cu->cu_raddr.buf = malloc(addr->len)) == NULL) { rpc_fd_unlock(dgtbl, cu->cu_fd); return (FALSE); } cu->cu_raddr.maxlen = addr->len; } cu->cu_raddr.len = addr->len; (void) memcpy(cu->cu_raddr.buf, addr->buf, addr->len); break; case CLGET_XID: /* * use the knowledge that xid is the * first element in the call structure *. * This will get the xid of the PREVIOUS call */ /* LINTED pointer alignment */ *(uint32_t *)info = ntohl(*(uint32_t *)cu->cu_outbuf); break; case CLSET_XID: /* This will set the xid of the NEXT call */ /* LINTED pointer alignment */ *(uint32_t *)cu->cu_outbuf = htonl(*(uint32_t *)info - 1); /* decrement by 1 as clnt_dg_call() increments once */ break; case CLGET_VERS: /* * This RELIES on the information that, in the call body, * the version number field is the fifth field from the * begining of the RPC header. MUST be changed if the * call_struct is changed */ /* LINTED pointer alignment */ *(uint32_t *)info = ntohl(*(uint32_t *)(cu->cu_outbuf + 4 * BYTES_PER_XDR_UNIT)); break; case CLSET_VERS: /* LINTED pointer alignment */ *(uint32_t *)(cu->cu_outbuf + 4 * BYTES_PER_XDR_UNIT) = /* LINTED pointer alignment */ htonl(*(uint32_t *)info); break; case CLGET_PROG: /* * This RELIES on the information that, in the call body, * the program number field is the fourth field from the * begining of the RPC header. MUST be changed if the * call_struct is changed */ /* LINTED pointer alignment */ *(uint32_t *)info = ntohl(*(uint32_t *)(cu->cu_outbuf + 3 * BYTES_PER_XDR_UNIT)); break; case CLSET_PROG: /* LINTED pointer alignment */ *(uint32_t *)(cu->cu_outbuf + 3 * BYTES_PER_XDR_UNIT) = /* LINTED pointer alignment */ htonl(*(uint32_t *)info); break; default: rpc_fd_unlock(dgtbl, cu->cu_fd); return (FALSE); } rpc_fd_unlock(dgtbl, cu->cu_fd); return (TRUE); }
static enum clnt_stat clnt_vc_call( CLIENT *h, rpcproc_t proc, xdrproc_t xdr_args, const char *args_ptr, xdrproc_t xdr_results, caddr_t results_ptr, struct timeval timeout ) { struct ct_data *ct; XDR *xdrs; struct rpc_msg reply_msg; u_int32_t x_id; u_int32_t *msg_x_id; bool_t shipnow; int refreshes = 2; #ifdef _REENTRANT sigset_t mask, newmask; #endif _DIAGASSERT(h != NULL); ct = (struct ct_data *) h->cl_private; #ifdef _REENTRANT __clnt_sigfillset(&newmask); thr_sigsetmask(SIG_SETMASK, &newmask, &mask); mutex_lock(&clnt_fd_lock); while (vc_fd_locks[ct->ct_fd]) cond_wait(&vc_cv[ct->ct_fd], &clnt_fd_lock); vc_fd_locks[ct->ct_fd] = __rpc_lock_value; mutex_unlock(&clnt_fd_lock); #endif xdrs = &(ct->ct_xdrs); msg_x_id = &ct->ct_u.ct_mcalli; if (!ct->ct_waitset) { if (time_not_ok(&timeout) == FALSE) 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_u.ct_mcallc, ct->ct_mpos)) || (! XDR_PUTINT32(xdrs, (int32_t *)&proc)) || (! AUTH_MARSHALL(h->cl_auth, xdrs)) || (! (*xdr_args)(xdrs, __UNCONST(args_ptr)))) { if (ct->ct_error.re_status == RPC_SUCCESS) ct->ct_error.re_status = RPC_CANTENCODEARGS; (void)xdrrec_endofrecord(xdrs, TRUE); release_fd_lock(ct->ct_fd, mask); return (ct->ct_error.re_status); } if (! xdrrec_endofrecord(xdrs, shipnow)) { release_fd_lock(ct->ct_fd, mask); return (ct->ct_error.re_status = RPC_CANTSEND); } if (! shipnow) { release_fd_lock(ct->ct_fd, mask); return (RPC_SUCCESS); } /* * Hack to provide rpc-based message passing */ if (timeout.tv_sec == 0 && timeout.tv_usec == 0) { release_fd_lock(ct->ct_fd, mask); return(ct->ct_error.re_status = RPC_TIMEDOUT); } /* * Keep receiving until we get a valid transaction id */ xdrs->x_op = XDR_DECODE; for (;;) { reply_msg.acpted_rply.ar_verf = _null_auth; reply_msg.acpted_rply.ar_results.where = NULL; reply_msg.acpted_rply.ar_results.proc = (xdrproc_t)xdr_void; if (! xdrrec_skiprecord(xdrs)) { release_fd_lock(ct->ct_fd, mask); 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; release_fd_lock(ct->ct_fd, mask); 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 */ release_fd_lock(ct->ct_fd, mask); return (ct->ct_error.re_status); }
static bool clnt_dg_control(CLIENT *clnt, u_int request, void *info) { struct cu_data *cu = CU_DATA((struct cx_data *)clnt->cl_p1); struct netbuf *addr; bool rslt = true; /* always take recv lock first, if taking both locks together */ rpc_dplx_rlc(clnt); rpc_dplx_slc(clnt); switch (request) { case CLSET_FD_CLOSE: cu->cu_closeit = true; rslt = true; goto unlock; case CLSET_FD_NCLOSE: cu->cu_closeit = false; rslt = true; goto unlock; } /* for other requests which use info */ if (info == NULL) { rslt = false; goto unlock; } switch (request) { case CLSET_TIMEOUT: if (time_not_ok((struct timeval *)info)) { rslt = false; goto unlock; } cu->cu_total = *(struct timeval *)info; break; case CLGET_TIMEOUT: *(struct timeval *)info = cu->cu_total; break; case CLGET_SERVER_ADDR: /* Give him the fd address */ /* Now obsolete. Only for backward compatibility */ (void)memcpy(info, &cu->cu_raddr, (size_t) cu->cu_rlen); break; case CLSET_RETRY_TIMEOUT: if (time_not_ok((struct timeval *)info)) { rslt = false; goto unlock; } cu->cu_wait = *(struct timeval *)info; break; case CLGET_RETRY_TIMEOUT: *(struct timeval *)info = cu->cu_wait; break; case CLGET_FD: *(int *)info = cu->cu_fd; break; case CLGET_SVC_ADDR: addr = (struct netbuf *)info; addr->buf = &cu->cu_raddr; addr->len = cu->cu_rlen; addr->maxlen = sizeof(cu->cu_raddr); break; case CLSET_SVC_ADDR: /* set to new address */ addr = (struct netbuf *)info; if (addr->len < sizeof(cu->cu_raddr)) { rslt = false; goto unlock; } (void)memcpy(&cu->cu_raddr, addr->buf, addr->len); cu->cu_rlen = addr->len; break; case CLGET_XID: /* * use the knowledge that xid is the * first element in the call structure *. * This will get the xid of the PREVIOUS call */ *(u_int32_t *) info = ntohl(*(u_int32_t *) (void *)cu->cu_outbuf); break; case CLSET_XID: /* This will set the xid of the NEXT call */ *(u_int32_t *) (void *)cu->cu_outbuf = htonl(*(u_int32_t *) info - 1); /* decrement by 1 as clnt_dg_call() increments once */ break; case CLGET_VERS: /* * This RELIES on the information that, in the call body, * the version number field is the fifth field from the * begining of the RPC header. MUST be changed if the * call_struct is changed */ *(u_int32_t *) info = ntohl(*(u_int32_t *) (void *) (cu->cu_outbuf + 4 * BYTES_PER_XDR_UNIT)); break; case CLSET_VERS: *(u_int32_t *) (void *)(cu->cu_outbuf + 4 * BYTES_PER_XDR_UNIT) = htonl(*(u_int32_t *) info); break; case CLGET_PROG: /* * This RELIES on the information that, in the call body, * the program number field is the fourth field from the * begining of the RPC header. MUST be changed if the * call_struct is changed */ *(u_int32_t *) info = ntohl(*(u_int32_t *) (void *) (cu->cu_outbuf + 3 * BYTES_PER_XDR_UNIT)); break; case CLSET_PROG: *(u_int32_t *) (void *)(cu->cu_outbuf + 3 * BYTES_PER_XDR_UNIT) = htonl(*(u_int32_t *) info); break; case CLSET_ASYNC: cu->cu_async = *(int *)info; break; case CLSET_CONNECT: cu->cu_connect = *(int *)info; break; default: break; } unlock: rpc_dplx_ruc(clnt); rpc_dplx_suc(clnt); return (rslt); }
static bool clnt_rdma_control(CLIENT *cl, u_int request, void *info) { struct cm_data *cm = CM_DATA((struct cx_data *) cl->cl_p1); sigset_t mask; bool result = TRUE; thr_sigsetmask(SIG_SETMASK, (sigset_t *) 0, &mask); /* XXX */ /* always take recv lock first if taking together */ rpc_dplx_rlc(cl); //receive lock clnt rpc_dplx_slc(cl); //send lock clnt switch (request) { case CLSET_FD_CLOSE: cm->cm_closeit = TRUE; result = TRUE; goto unlock; case CLSET_FD_NCLOSE: cm->cm_closeit = FALSE; result = TRUE; goto unlock; } /* for other requests which use info */ if (info == NULL) { result = FALSE; goto unlock; } switch (request) { case CLSET_TIMEOUT: if (time_not_ok((struct timeval *)info)) { result = FALSE; goto unlock; } cm->cm_total = *(struct timeval *)info; break; case CLGET_TIMEOUT: *(struct timeval *)info = cm->cm_total; break; case CLSET_RETRY_TIMEOUT: if (time_not_ok((struct timeval *)info)) { result = FALSE; goto unlock; } cm->cm_wait = *(struct timeval *)info; break; case CLGET_RETRY_TIMEOUT: *(struct timeval *)info = cm->cm_wait; break; case CLGET_FD: *(RDMAXPRT **)info = cm->cm_xdrs.x_lib[1]; break; case CLGET_XID: /* * use the knowledge that xid is the * first element in the call structure *. * This will get the xid of the PREVIOUS call */ *(u_int32_t *)info = cm->call_msg.rm_xid - 1; break; case CLSET_XID: /* This will set the xid of the NEXT call */ cm->call_msg.rm_xid = *(u_int32_t *)info; break; case CLGET_VERS: *(u_int32_t *)info = cm->call_msg.rm_call.cb_vers; break; case CLSET_VERS: cm->call_msg.rm_call.cb_vers = *(u_int32_t *)info; break; case CLGET_PROG: *(u_int32_t *)info = cm->call_msg.rm_call.cb_prog; break; case CLSET_PROG: cm->call_msg.rm_call.cb_prog = *(u_int32_t *)info; break; case CLSET_ASYNC: //FIXME cm->cm_async = *(int *)info; break; case CLSET_CONNECT: //FIXMEcm->cm_connect = *(int *)info; break; default: break; } unlock: rpc_dplx_ruc(cl); rpc_dplx_suc(cl); return (result); }
static bool_t clnt_msk_control(CLIENT *cl, u_int request, void *info) { struct cm_data *cm = CM_DATA((struct cx_data *) cl->cl_private); sigset_t mask; bool_t result = TRUE; thr_sigsetmask(SIG_SETMASK, (sigset_t *) 0, &mask); /* XXX */ vc_fd_lock_c(cl, &mask); switch (request) { case CLSET_FD_CLOSE: cm->cm_closeit = TRUE; result = TRUE; goto unlock; case CLSET_FD_NCLOSE: cm->cm_closeit = FALSE; result = TRUE; goto unlock; } /* for other requests which use info */ if (info == NULL) { result = FALSE; goto unlock; } switch (request) { case CLSET_TIMEOUT: if (time_not_ok((struct timeval *)info)) { result = FALSE; goto unlock; } cm->cm_total = *(struct timeval *)info; break; case CLGET_TIMEOUT: *(struct timeval *)info = cm->cm_total; break; case CLSET_RETRY_TIMEOUT: if (time_not_ok((struct timeval *)info)) { result = FALSE; goto unlock; } cm->cm_wait = *(struct timeval *)info; break; case CLGET_RETRY_TIMEOUT: *(struct timeval *)info = cm->cm_wait; break; case CLGET_FD: *(msk_trans_t **)info = cm->trans; break; case CLGET_XID: /* * use the knowledge that xid is the * first element in the call structure *. * This will get the xid of the PREVIOUS call */ *(u_int32_t *)info = cm->call_msg.rm_xid - 1; break; case CLSET_XID: /* This will set the xid of the NEXT call */ cm->call_msg.rm_xid = *(u_int32_t *)info; break; case CLGET_VERS: *(u_int32_t *)info = cm->call_msg.rm_call.cb_vers; break; case CLSET_VERS: cm->call_msg.rm_call.cb_vers = *(u_int32_t *)info; break; case CLGET_PROG: *(u_int32_t *)info = cm->call_msg.rm_call.cb_prog; break; case CLSET_PROG: cm->call_msg.rm_call.cb_prog = *(u_int32_t *)info; break; case CLSET_ASYNC: //FIXME cm->cm_async = *(int *)info; break; case CLSET_CONNECT: //FIXMEcm->cm_connect = *(int *)info; break; default: break; } unlock: vc_fd_unlock_c(cl, &mask); return (result); }