summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChuck Lever <chuck.lever@oracle.com>2009-05-28 10:27:10 -0400
committerSteve Dickson <steved@redhat.com>2009-05-28 10:27:10 -0400
commitefd09566cf9c1f7ca0e2a2f8626d17920193d18c (patch)
tree98409cce0b7a7428cace32e1bcd030258db33129
parenta0b9b6cd58378f0cb24c7eae82185b06e5aaec37 (diff)
downloadti-rpc-efd09566cf9c1f7ca0e2a2f8626d17920193d18c.tar.gz
Remove editor save files in src/
Clean up: delete some old editor save files in libtirpc/src. Signed-off-by: Chuck Lever <chuck.lever@oracle.com> Signed-off-by: Steve Dickson <steved@redhat.com>
-rw-r--r--src/#clnt_dg.c#725
-rw-r--r--src/clnt_dg.c~724
-rw-r--r--src/rpbc_clnt.c1239
-rw-r--r--src/rpcb_clnt.c.ref1342
-rw-r--r--src/rpcb_clnt.c~1235
5 files changed, 0 insertions, 5265 deletions
diff --git a/src/#clnt_dg.c# b/src/#clnt_dg.c#
deleted file mode 100644
index 8816872..0000000
--- a/src/#clnt_dg.c#
+++ /dev/null
@@ -1,725 +0,0 @@
-/*
- * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
- * unrestricted use provided that this legend is included on all tape
- * media and as a part of the software program in whole or part. Users
- * may copy or modify Sun RPC without charge, but are not authorized
- * to license or distribute it to anyone else except as part of a product or
- * program developed by the user.
- *
- * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
- * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
- *
- * Sun RPC is provided with no support and without any obligation on the
- * part of Sun Microsystems, Inc. to assist in its use, correction,
- * modification or enhancement.
- *
- * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
- * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
- * OR ANY PART THEREOF.
- *
- * In no event will Sun Microsystems, Inc. be liable for any lost revenue
- * or profits or other special, indirect and consequential damages, even if
- * Sun has been advised of the possibility of such damages.
- *
- * Sun Microsystems, Inc.
- * 2550 Garcia Avenue
- * Mountain View, California 94043
- */
-/*
- * Copyright (c) 1986-1991 by Sun Microsystems Inc.
- */
-
-/*
- * Implements a connectionless client side RPC.
- */
-#include <pthread.h>
-#include <reentrant.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <stdint.h>
-#include <sys/poll.h>
-
-#include <sys/time.h>
-
-#include <sys/ioctl.h>
-#include <rpc/clnt.h>
-#include <arpa/inet.h>
-#include <rpc/rpc.h>
-#include <rpc/xdr.h>
-#include <errno.h>
-#include <stdlib.h>
-#include <string.h>
-#include <signal.h>
-#include <unistd.h>
-#include <err.h>
-#include "rpc_com.h"
-
-#define MAX_DEFAULT_FDS 20000
-
-static struct clnt_ops *clnt_dg_ops(void);
-static bool_t time_not_ok(struct timeval *);
-static enum clnt_stat clnt_dg_call(CLIENT *, rpcproc_t, xdrproc_t, void *,
- xdrproc_t, void *, struct timeval);
-static void clnt_dg_geterr(CLIENT *, struct rpc_err *);
-static bool_t clnt_dg_freeres(CLIENT *, xdrproc_t, void *);
-static void clnt_dg_abort(CLIENT *);
-static bool_t clnt_dg_control(CLIENT *, u_int, void *);
-static void clnt_dg_destroy(CLIENT *);
-
-
-/*
- * This machinery implements per-fd locks for MT-safety. It is not
- * sufficient to do per-CLIENT handle locks for MT-safety because a
- * user may create more than one CLIENT handle with the same fd behind
- * it. Therfore, we allocate an array of flags (dg_fd_locks), protected
- * by the clnt_fd_lock mutex, and an array (dg_cv) of condition variables
- * similarly protected. Dg_fd_lock[fd] == 1 => a call is activte on some
- * CLIENT handle created for that fd.
- * The current implementation holds locks across the entire RPC and reply,
- * including retransmissions. Yes, this is silly, and as soon as this
- * code is proven to work, this should be the first thing fixed. One step
- * at a time.
- */
-static int *dg_fd_locks;
-extern mutex_t clnt_fd_lock;
-static cond_t *dg_cv;
-#define release_fd_lock(fd, mask) { \
- mutex_lock(&clnt_fd_lock); \
- dg_fd_locks[fd] = 0; \
- mutex_unlock(&clnt_fd_lock); \
- thr_sigsetmask(SIG_SETMASK, &(mask), NULL); \
- cond_signal(&dg_cv[fd]); \
-}
-
-static const char mem_err_clnt_dg[] = "clnt_dg_create: out of memory";
-
-/* VARIABLES PROTECTED BY clnt_fd_lock: dg_fd_locks, dg_cv */
-
-/*
- * Private data kept per client handle
- */
-struct cu_data {
- int cu_fd; /* connections fd */
- bool_t cu_closeit; /* opened by library */
- struct sockaddr_storage cu_raddr; /* remote address */
- int cu_rlen;
- struct timeval cu_wait; /* retransmit interval */
- struct timeval cu_total; /* total time for the call */
- struct rpc_err cu_error;
- XDR cu_outxdrs;
- u_int cu_xdrpos;
- u_int cu_sendsz; /* send size */
- char *cu_outbuf;
- u_int cu_recvsz; /* recv size */
- int cu_async;
- int cu_connect; /* Use connect(). */
- int cu_connected; /* Have done connect(). */
- char cu_inbuf[1];
-};
-
-/*
- * Connection less client creation returns with client handle parameters.
- * Default options are set, which the user can change using clnt_control().
- * fd should be open and bound.
- * NB: The rpch->cl_auth is initialized to null authentication.
- * Caller may wish to set this something more useful.
- *
- * sendsz and recvsz are the maximum allowable packet sizes that can be
- * sent and received. Normally they are the same, but they can be
- * changed to improve the program efficiency and buffer allocation.
- * If they are 0, use the transport default.
- *
- * If svcaddr is NULL, returns NULL.
- */
-CLIENT *
-clnt_dg_create(fd, svcaddr, program, version, sendsz, recvsz)
- int fd; /* open file descriptor */
- const struct netbuf *svcaddr; /* servers address */
- rpcprog_t program; /* program number */
- rpcvers_t version; /* version number */
- u_int sendsz; /* buffer recv size */
- u_int recvsz; /* buffer send size */
-{
- CLIENT *cl = NULL; /* client handle */
- struct cu_data *cu = NULL; /* private data */
- struct timeval now;
- struct rpc_msg call_msg;
- sigset_t mask;
- sigset_t newmask;
- struct __rpc_sockinfo si;
- int one = 1;
-
- sigfillset(&newmask);
- thr_sigsetmask(SIG_SETMASK, &newmask, &mask);
- mutex_lock(&clnt_fd_lock);
- if (dg_fd_locks == (int *) NULL) {
- int cv_allocsz;
- size_t fd_allocsz;
- int dtbsize = __rpc_dtbsize();
-
- fd_allocsz = dtbsize * sizeof (int);
- dg_fd_locks = (int *) mem_alloc(fd_allocsz);
- if (dg_fd_locks == (int *) NULL) {
- mutex_unlock(&clnt_fd_lock);
- thr_sigsetmask(SIG_SETMASK, &(mask), NULL);
- goto err1;
- } else
- memset(dg_fd_locks, '\0', fd_allocsz);
-
- cv_allocsz = dtbsize * sizeof (cond_t);
- dg_cv = (cond_t *) mem_alloc(cv_allocsz);
- if (dg_cv == (cond_t *) NULL) {
- mem_free(dg_fd_locks, fd_allocsz);
- dg_fd_locks = (int *) NULL;
- mutex_unlock(&clnt_fd_lock);
- thr_sigsetmask(SIG_SETMASK, &(mask), NULL);
- goto err1;
- } else {
- int i;
-
- for (i = 0; i < dtbsize; i++)
- cond_init(&dg_cv[i], 0, (void *) 0);
- }
- }
-
- mutex_unlock(&clnt_fd_lock);
- thr_sigsetmask(SIG_SETMASK, &(mask), NULL);
-
- if (svcaddr == NULL) {
- rpc_createerr.cf_stat = RPC_UNKNOWNADDR;
- return (NULL);
- }
-
- if (!__rpc_fd2sockinfo(fd, &si)) {
- rpc_createerr.cf_stat = RPC_TLIERROR;
- rpc_createerr.cf_error.re_errno = 0;
- return (NULL);
- }
- /*
- * Find the receive and the send size
- */
- sendsz = __rpc_get_t_size(si.si_af, si.si_proto, (int)sendsz);
- recvsz = __rpc_get_t_size(si.si_af, si.si_proto, (int)recvsz);
- if ((sendsz == 0) || (recvsz == 0)) {
- rpc_createerr.cf_stat = RPC_TLIERROR; /* XXX */
- rpc_createerr.cf_error.re_errno = 0;
- return (NULL);
- }
-
- if ((cl = mem_alloc(sizeof (CLIENT))) == NULL)
- goto err1;
- /*
- * Should be multiple of 4 for XDR.
- */
- sendsz = ((sendsz + 3) / 4) * 4;
- recvsz = ((recvsz + 3) / 4) * 4;
- cu = mem_alloc(sizeof (*cu) + sendsz + recvsz);
- if (cu == NULL)
- goto err1;
- (void) memcpy(&cu->cu_raddr, svcaddr->buf, (size_t)svcaddr->len);
- cu->cu_rlen = svcaddr->len;
- cu->cu_outbuf = &cu->cu_inbuf[recvsz];
- /* Other values can also be set through clnt_control() */
- cu->cu_wait.tv_sec = 15; /* heuristically chosen */
- cu->cu_wait.tv_usec = 0;
- cu->cu_total.tv_sec = -1;
- cu->cu_total.tv_usec = -1;
- cu->cu_sendsz = sendsz;
- cu->cu_recvsz = recvsz;
- cu->cu_async = FALSE;
- cu->cu_connect = FALSE;
- cu->cu_connected = FALSE;
- (void) gettimeofday(&now, NULL);
- call_msg.rm_xid = __RPC_GETXID(&now);
- call_msg.rm_call.cb_prog = program;
- call_msg.rm_call.cb_vers = version;
- xdrmem_create(&(cu->cu_outxdrs), cu->cu_outbuf, sendsz, XDR_ENCODE);
- if (! xdr_callhdr(&(cu->cu_outxdrs), &call_msg)) {
- rpc_createerr.cf_stat = RPC_CANTENCODEARGS; /* XXX */
- rpc_createerr.cf_error.re_errno = 0;
- goto err2;
- }
- cu->cu_xdrpos = XDR_GETPOS(&(cu->cu_outxdrs));
-
- /* XXX fvdl - do we still want this? */
-#if 0
- (void)bindresvport_sa(fd, (struct sockaddr *)svcaddr->buf);
-#endif
- ioctl(fd, FIONBIO, (char *)(void *)&one);
- /*
- * By default, closeit is always FALSE. It is users responsibility
- * to do a close on it, else the user may use clnt_control
- * to let clnt_destroy do it for him/her.
- */
- cu->cu_closeit = FALSE;
- cu->cu_fd = fd;
- cl->cl_ops = clnt_dg_ops();
- cl->cl_private = (caddr_t)(void *)cu;
- cl->cl_auth = authnone_create();
- cl->cl_tp = NULL;
- cl->cl_netid = NULL;
-
- return (cl);
-err1:
- warnx(mem_err_clnt_dg);
- rpc_createerr.cf_stat = RPC_SYSTEMERROR;
- rpc_createerr.cf_error.re_errno = errno;
-err2:
- if (cl) {
- mem_free(cl, sizeof (CLIENT));
- if (cu)
- mem_free(cu, sizeof (*cu) + sendsz + recvsz);
- }
- return (NULL);
-}
-
-static enum clnt_stat
-clnt_dg_call(cl, proc, xargs, argsp, xresults, resultsp, utimeout)
- CLIENT *cl; /* client handle */
- rpcproc_t proc; /* procedure number */
- xdrproc_t xargs; /* xdr routine for args */
- void *argsp; /* pointer to args */
- xdrproc_t xresults; /* xdr routine for results */
- void *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;
- size_t outlen = 0;
- struct rpc_msg reply_msg;
- XDR reply_xdrs;
- bool_t ok;
- int nrefreshes = 2; /* number of times to refresh cred */
- struct timeval timeout;
- struct pollfd fd;
- int total_time, nextsend_time, tv;
- struct sockaddr *sa;
- sigset_t mask;
- sigset_t newmask;
- socklen_t inlen, salen;
- ssize_t recvlen = 0;
- int rpc_lock_value;
- u_int32_t xid;
-
- outlen = 0;
- sigfillset(&newmask);
- thr_sigsetmask(SIG_SETMASK, &newmask, &mask);
- mutex_lock(&clnt_fd_lock);
- while (dg_fd_locks[cu->cu_fd])
- cond_wait(&dg_cv[cu->cu_fd], &clnt_fd_lock);
- rpc_lock_value = 1;
- dg_fd_locks[cu->cu_fd] = rpc_lock_value;
- mutex_unlock(&clnt_fd_lock);
- if (cu->cu_total.tv_usec == -1) {
- timeout = utimeout; /* use supplied timeout */
- } else {
- timeout = cu->cu_total; /* use default timeout */
- }
- total_time = timeout.tv_sec * 1000 + timeout.tv_usec / 1000;
- nextsend_time = cu->cu_wait.tv_sec * 1000 + cu->cu_wait.tv_usec / 1000;
-
- if (cu->cu_connect && !cu->cu_connected) {
- if (connect(cu->cu_fd, (struct sockaddr *)&cu->cu_raddr,
- cu->cu_rlen) < 0) {
- cu->cu_error.re_errno = errno;
- cu->cu_error.re_status = RPC_CANTSEND;
- goto out;
- }
- cu->cu_connected = 1;
- }
- if (cu->cu_connected) {
- sa = NULL;
- salen = 0;
- } else {
- sa = (struct sockaddr *)&cu->cu_raddr;
- salen = cu->cu_rlen;
- }
-
- /* Clean up in case the last call ended in a longjmp(3) call. */
-call_again:
- xdrs = &(cu->cu_outxdrs);
- if (cu->cu_async == TRUE && 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
- * XXX Yes, and it's in network byte order, so we should to
- * be careful when we increment it, shouldn't we.
- */
- xid = ntohl(*(u_int32_t *)(void *)(cu->cu_outbuf));
- xid++;
- *(u_int32_t *)(void *)(cu->cu_outbuf) = htonl(xid);
-
- if ((! XDR_PUTINT32(xdrs, &proc)) ||
- (! AUTH_MARSHALL(cl->cl_auth, xdrs)) ||
- (! (*xargs)(xdrs, argsp))) {
- cu->cu_error.re_status = RPC_CANTENCODEARGS;
- goto out;
- }
- outlen = (size_t)XDR_GETPOS(xdrs);
-
- /*
- * Hack to provide rpc-based message passing
- */
- if (timeout.tv_sec == 0 && timeout.tv_usec == 0) {
- cu->cu_error.re_status = RPC_TIMEDOUT;
- goto out;
- }
-
-send_again:
- nextsend_time = cu->cu_wait.tv_sec * 1000 + cu->cu_wait.tv_usec / 1000;
- if (sendto(cu->cu_fd, cu->cu_outbuf, outlen, 0, sa, salen) != outlen) {
- cu->cu_error.re_errno = errno;
- cu->cu_error.re_status = RPC_CANTSEND;
- goto out;
- }
-
-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_fd;
- fd.events = POLLIN;
- while (total_time > 0) {
- tv = total_time < nextsend_time ? total_time : nextsend_time;
- switch (poll(&fd, 1, tv)) {
- case 0:
- total_time -= tv;
- goto send_again;
- case -1:
- if (errno == EINTR)
- continue;
- cu->cu_error.re_status = RPC_CANTRECV;
- cu->cu_error.re_errno = errno;
- goto out;
- }
- break;
- }
-
- /* We have some data now */
- do {
- recvlen = recvfrom(cu->cu_fd, cu->cu_inbuf,
- cu->cu_recvsz, 0, NULL, NULL);
- } while (recvlen < 0 && errno == EINTR);
- if (recvlen < 0 && errno != EWOULDBLOCK) {
- cu->cu_error.re_errno = errno;
- cu->cu_error.re_status = RPC_CANTRECV;
- goto out;
- }
- if (recvlen >= sizeof(u_int32_t) &&
- (cu->cu_async == TRUE ||
- *((u_int32_t *)(void *)(cu->cu_inbuf)) ==
- *((u_int32_t *)(void *)(cu->cu_outbuf))))
- inlen = (socklen_t)recvlen;
- else {
- total_time -= tv;
- goto send_again;
- }
-
- /*
- * now decode and validate the response
- */
-
- xdrmem_create(&reply_xdrs, cu->cu_inbuf, (u_int)recvlen, 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))
- cu->cu_error.re_status = RPC_SUCCESS;
- else
- _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 */
- /*
- * If unsuccesful AND error is an authentication error
- * then refresh credentials and try again, else break
- */
- else if (cu->cu_error.re_status == RPC_AUTHERROR)
- /* maybe our credentials need to be refreshed ... */
- if (nrefreshes > 0 &&
- AUTH_REFRESH(cl->cl_auth, &reply_msg)) {
- nrefreshes--;
- goto call_again;
- }
- /* end of unsuccessful completion */
- } /* end of valid reply message */
- else {
- cu->cu_error.re_status = RPC_CANTDECODERES;
-
- }
-out:
- release_fd_lock(cu->cu_fd, mask);
- return (cu->cu_error.re_status);
-}
-
-static void
-clnt_dg_geterr(cl, errp)
- CLIENT *cl;
- struct rpc_err *errp;
-{
- struct cu_data *cu = (struct cu_data *)cl->cl_private;
-
- *errp = cu->cu_error;
-}
-
-static bool_t
-clnt_dg_freeres(cl, xdr_res, res_ptr)
- CLIENT *cl;
- xdrproc_t xdr_res;
- void *res_ptr;
-{
- struct cu_data *cu = (struct cu_data *)cl->cl_private;
- XDR *xdrs = &(cu->cu_outxdrs);
- bool_t dummy;
- sigset_t mask;
- sigset_t newmask;
-
- sigfillset(&newmask);
- thr_sigsetmask(SIG_SETMASK, &newmask, &mask);
- mutex_lock(&clnt_fd_lock);
- while (dg_fd_locks[cu->cu_fd])
- cond_wait(&dg_cv[cu->cu_fd], &clnt_fd_lock);
- xdrs->x_op = XDR_FREE;
- dummy = (*xdr_res)(xdrs, res_ptr);
- mutex_unlock(&clnt_fd_lock);
- thr_sigsetmask(SIG_SETMASK, &mask, NULL);
- cond_signal(&dg_cv[cu->cu_fd]);
- return (dummy);
-}
-
-/*ARGSUSED*/
-static void
-clnt_dg_abort(h)
- CLIENT *h;
-{
-}
-
-static bool_t
-clnt_dg_control(cl, request, info)
- CLIENT *cl;
- u_int request;
- void *info;
-{
- struct cu_data *cu = (struct cu_data *)cl->cl_private;
- struct netbuf *addr;
- sigset_t mask;
- sigset_t newmask;
- int rpc_lock_value;
-
- sigfillset(&newmask);
- thr_sigsetmask(SIG_SETMASK, &newmask, &mask);
- mutex_lock(&clnt_fd_lock);
- while (dg_fd_locks[cu->cu_fd])
- cond_wait(&dg_cv[cu->cu_fd], &clnt_fd_lock);
- rpc_lock_value = 1;
- dg_fd_locks[cu->cu_fd] = rpc_lock_value;
- mutex_unlock(&clnt_fd_lock);
- switch (request) {
- case CLSET_FD_CLOSE:
- cu->cu_closeit = TRUE;
- release_fd_lock(cu->cu_fd, mask);
- return (TRUE);
- case CLSET_FD_NCLOSE:
- cu->cu_closeit = FALSE;
- release_fd_lock(cu->cu_fd, mask);
- return (TRUE);
- }
-
- /* for other requests which use info */
- if (info == NULL) {
- release_fd_lock(cu->cu_fd, mask);
- return (FALSE);
- }
- switch (request) {
- case CLSET_TIMEOUT:
- if (time_not_ok((struct timeval *)info)) {
- release_fd_lock(cu->cu_fd, mask);
- return (FALSE);
- }
- 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)) {
- release_fd_lock(cu->cu_fd, mask);
- return (FALSE);
- }
- 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) {
- release_fd_lock(cu->cu_fd, mask);
- return (FALSE);
- }
- (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:
- release_fd_lock(cu->cu_fd, mask);
- return (FALSE);
- }
- release_fd_lock(cu->cu_fd, mask);
- return (TRUE);
-}
-
-static void
-clnt_dg_destroy(cl)
- CLIENT *cl;
-{
- struct cu_data *cu = (struct cu_data *)cl->cl_private;
- int cu_fd = cu->cu_fd;
- sigset_t mask;
- sigset_t newmask;
-
- sigfillset(&newmask);
- thr_sigsetmask(SIG_SETMASK, &newmask, &mask);
- mutex_lock(&clnt_fd_lock);
- while (dg_fd_locks[cu_fd])
- cond_wait(&dg_cv[cu_fd], &clnt_fd_lock);
- if (cu->cu_closeit)
- (void)close(cu_fd);
- XDR_DESTROY(&(cu->cu_outxdrs));
- mem_free(cu, (sizeof (*cu) + cu->cu_sendsz + cu->cu_recvsz));
- if (cl->cl_netid && cl->cl_netid[0])
- mem_free(cl->cl_netid, strlen(cl->cl_netid) +1);
- if (cl->cl_tp && cl->cl_tp[0])
- mem_free(cl->cl_tp, strlen(cl->cl_tp) +1);
- mem_free(cl, sizeof (CLIENT));
- mutex_unlock(&clnt_fd_lock);
- thr_sigsetmask(SIG_SETMASK, &mask, NULL);
- cond_signal(&dg_cv[cu_fd]);
-}
-
-static struct clnt_ops *
-clnt_dg_ops()
-{
- static struct clnt_ops ops;
- extern mutex_t ops_lock;
- sigset_t mask;
- sigset_t newmask;
-
-/* VARIABLES PROTECTED BY ops_lock: ops */
-
- sigfillset(&newmask);
- thr_sigsetmask(SIG_SETMASK, &newmask, &mask);
- mutex_lock(&ops_lock);
- if (ops.cl_call == NULL) {
- ops.cl_call = clnt_dg_call;
- ops.cl_abort = clnt_dg_abort;
- ops.cl_geterr = clnt_dg_geterr;
- ops.cl_freeres = clnt_dg_freeres;
- ops.cl_destroy = clnt_dg_destroy;
- ops.cl_control = clnt_dg_control;
- }
- mutex_unlock(&ops_lock);
- thr_sigsetmask(SIG_SETMASK, &mask, NULL);
- return (&ops);
-}
-
-/*
- * Make sure that the time is not garbage. -1 value is allowed.
- */
-static bool_t
-time_not_ok(t)
- struct timeval *t;
-{
- return (t->tv_sec < -1 || t->tv_sec > 100000000 ||
- t->tv_usec < -1 || t->tv_usec > 1000000);
-}
-
diff --git a/src/clnt_dg.c~ b/src/clnt_dg.c~
deleted file mode 100644
index cb480dc..0000000
--- a/src/clnt_dg.c~
+++ /dev/null
@@ -1,724 +0,0 @@
-/*
- * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
- * unrestricted use provided that this legend is included on all tape
- * media and as a part of the software program in whole or part. Users
- * may copy or modify Sun RPC without charge, but are not authorized
- * to license or distribute it to anyone else except as part of a product or
- * program developed by the user.
- *
- * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
- * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
- *
- * Sun RPC is provided with no support and without any obligation on the
- * part of Sun Microsystems, Inc. to assist in its use, correction,
- * modification or enhancement.
- *
- * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
- * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
- * OR ANY PART THEREOF.
- *
- * In no event will Sun Microsystems, Inc. be liable for any lost revenue
- * or profits or other special, indirect and consequential damages, even if
- * Sun has been advised of the possibility of such damages.
- *
- * Sun Microsystems, Inc.
- * 2550 Garcia Avenue
- * Mountain View, California 94043
- */
-/*
- * Copyright (c) 1986-1991 by Sun Microsystems Inc.
- */
-
-/*
- * Implements a connectionless client side RPC.
- */
-#include <pthread.h>
-#include <reentrant.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <stdint.h>
-#include <sys/poll.h>
-
-#include <sys/time.h>
-
-#include <sys/ioctl.h>
-#include <rpc/clnt.h>
-#include <arpa/inet.h>
-#include <rpc/rpc.h>
-#include <errno.h>
-#include <stdlib.h>
-#include <string.h>
-#include <signal.h>
-#include <unistd.h>
-#include <err.h>
-#include "rpc_com.h"
-
-#define MAX_DEFAULT_FDS 20000
-
-static struct clnt_ops *clnt_dg_ops(void);
-static bool_t time_not_ok(struct timeval *);
-static enum clnt_stat clnt_dg_call(CLIENT *, rpcproc_t, xdrproc_t, void *,
- xdrproc_t, void *, struct timeval);
-static void clnt_dg_geterr(CLIENT *, struct rpc_err *);
-static bool_t clnt_dg_freeres(CLIENT *, xdrproc_t, void *);
-static void clnt_dg_abort(CLIENT *);
-static bool_t clnt_dg_control(CLIENT *, u_int, void *);
-static void clnt_dg_destroy(CLIENT *);
-
-
-/*
- * This machinery implements per-fd locks for MT-safety. It is not
- * sufficient to do per-CLIENT handle locks for MT-safety because a
- * user may create more than one CLIENT handle with the same fd behind
- * it. Therfore, we allocate an array of flags (dg_fd_locks), protected
- * by the clnt_fd_lock mutex, and an array (dg_cv) of condition variables
- * similarly protected. Dg_fd_lock[fd] == 1 => a call is activte on some
- * CLIENT handle created for that fd.
- * The current implementation holds locks across the entire RPC and reply,
- * including retransmissions. Yes, this is silly, and as soon as this
- * code is proven to work, this should be the first thing fixed. One step
- * at a time.
- */
-static int *dg_fd_locks;
-extern mutex_t clnt_fd_lock;
-static cond_t *dg_cv;
-#define release_fd_lock(fd, mask) { \
- mutex_lock(&clnt_fd_lock); \
- dg_fd_locks[fd] = 0; \
- mutex_unlock(&clnt_fd_lock); \
- thr_sigsetmask(SIG_SETMASK, &(mask), NULL); \
- cond_signal(&dg_cv[fd]); \
-}
-
-static const char mem_err_clnt_dg[] = "clnt_dg_create: out of memory";
-
-/* VARIABLES PROTECTED BY clnt_fd_lock: dg_fd_locks, dg_cv */
-
-/*
- * Private data kept per client handle
- */
-struct cu_data {
- int cu_fd; /* connections fd */
- bool_t cu_closeit; /* opened by library */
- struct sockaddr_storage cu_raddr; /* remote address */
- int cu_rlen;
- struct timeval cu_wait; /* retransmit interval */
- struct timeval cu_total; /* total time for the call */
- struct rpc_err cu_error;
- XDR cu_outxdrs;
- u_int cu_xdrpos;
- u_int cu_sendsz; /* send size */
- char *cu_outbuf;
- u_int cu_recvsz; /* recv size */
- int cu_async;
- int cu_connect; /* Use connect(). */
- int cu_connected; /* Have done connect(). */
- char cu_inbuf[1];
-};
-
-/*
- * Connection less client creation returns with client handle parameters.
- * Default options are set, which the user can change using clnt_control().
- * fd should be open and bound.
- * NB: The rpch->cl_auth is initialized to null authentication.
- * Caller may wish to set this something more useful.
- *
- * sendsz and recvsz are the maximum allowable packet sizes that can be
- * sent and received. Normally they are the same, but they can be
- * changed to improve the program efficiency and buffer allocation.
- * If they are 0, use the transport default.
- *
- * If svcaddr is NULL, returns NULL.
- */
-CLIENT *
-clnt_dg_create(fd, svcaddr, program, version, sendsz, recvsz)
- int fd; /* open file descriptor */
- const struct netbuf *svcaddr; /* servers address */
- rpcprog_t program; /* program number */
- rpcvers_t version; /* version number */
- u_int sendsz; /* buffer recv size */
- u_int recvsz; /* buffer send size */
-{
- CLIENT *cl = NULL; /* client handle */
- struct cu_data *cu = NULL; /* private data */
- struct timeval now;
- struct rpc_msg call_msg;
- sigset_t mask;
- sigset_t newmask;
- struct __rpc_sockinfo si;
- int one = 1;
-
- sigfillset(&newmask);
- thr_sigsetmask(SIG_SETMASK, &newmask, &mask);
- mutex_lock(&clnt_fd_lock);
- if (dg_fd_locks == (int *) NULL) {
- int cv_allocsz;
- size_t fd_allocsz;
- int dtbsize = __rpc_dtbsize();
-
- fd_allocsz = dtbsize * sizeof (int);
- dg_fd_locks = (int *) mem_alloc(fd_allocsz);
- if (dg_fd_locks == (int *) NULL) {
- mutex_unlock(&clnt_fd_lock);
- thr_sigsetmask(SIG_SETMASK, &(mask), NULL);
- goto err1;
- } else
- memset(dg_fd_locks, '\0', fd_allocsz);
-
- cv_allocsz = dtbsize * sizeof (cond_t);
- dg_cv = (cond_t *) mem_alloc(cv_allocsz);
- if (dg_cv == (cond_t *) NULL) {
- mem_free(dg_fd_locks, fd_allocsz);
- dg_fd_locks = (int *) NULL;
- mutex_unlock(&clnt_fd_lock);
- thr_sigsetmask(SIG_SETMASK, &(mask), NULL);
- goto err1;
- } else {
- int i;
-
- for (i = 0; i < dtbsize; i++)
- cond_init(&dg_cv[i], 0, (void *) 0);
- }
- }
-
- mutex_unlock(&clnt_fd_lock);
- thr_sigsetmask(SIG_SETMASK, &(mask), NULL);
-
- if (svcaddr == NULL) {
- rpc_createerr.cf_stat = RPC_UNKNOWNADDR;
- return (NULL);
- }
-
- if (!__rpc_fd2sockinfo(fd, &si)) {
- rpc_createerr.cf_stat = RPC_TLIERROR;
- rpc_createerr.cf_error.re_errno = 0;
- return (NULL);
- }
- /*
- * Find the receive and the send size
- */
- sendsz = __rpc_get_t_size(si.si_af, si.si_proto, (int)sendsz);
- recvsz = __rpc_get_t_size(si.si_af, si.si_proto, (int)recvsz);
- if ((sendsz == 0) || (recvsz == 0)) {
- rpc_createerr.cf_stat = RPC_TLIERROR; /* XXX */
- rpc_createerr.cf_error.re_errno = 0;
- return (NULL);
- }
-
- if ((cl = mem_alloc(sizeof (CLIENT))) == NULL)
- goto err1;
- /*
- * Should be multiple of 4 for XDR.
- */
- sendsz = ((sendsz + 3) / 4) * 4;
- recvsz = ((recvsz + 3) / 4) * 4;
- cu = mem_alloc(sizeof (*cu) + sendsz + recvsz);
- if (cu == NULL)
- goto err1;
- (void) memcpy(&cu->cu_raddr, svcaddr->buf, (size_t)svcaddr->len);
- cu->cu_rlen = svcaddr->len;
- cu->cu_outbuf = &cu->cu_inbuf[recvsz];
- /* Other values can also be set through clnt_control() */
- cu->cu_wait.tv_sec = 15; /* heuristically chosen */
- cu->cu_wait.tv_usec = 0;
- cu->cu_total.tv_sec = -1;
- cu->cu_total.tv_usec = -1;
- cu->cu_sendsz = sendsz;
- cu->cu_recvsz = recvsz;
- cu->cu_async = FALSE;
- cu->cu_connect = FALSE;
- cu->cu_connected = FALSE;
- (void) gettimeofday(&now, NULL);
- call_msg.rm_xid = __RPC_GETXID(&now);
- call_msg.rm_call.cb_prog = program;
- call_msg.rm_call.cb_vers = version;
- xdrmem_create(&(cu->cu_outxdrs), cu->cu_outbuf, sendsz, XDR_ENCODE);
- if (! xdr_callhdr(&(cu->cu_outxdrs), &call_msg)) {
- rpc_createerr.cf_stat = RPC_CANTENCODEARGS; /* XXX */
- rpc_createerr.cf_error.re_errno = 0;
- goto err2;
- }
- cu->cu_xdrpos = XDR_GETPOS(&(cu->cu_outxdrs));
-
- /* XXX fvdl - do we still want this? */
-#if 0
- (void)bindresvport_sa(fd, (struct sockaddr *)svcaddr->buf);
-#endif
- ioctl(fd, FIONBIO, (char *)(void *)&one);
- /*
- * By default, closeit is always FALSE. It is users responsibility
- * to do a close on it, else the user may use clnt_control
- * to let clnt_destroy do it for him/her.
- */
- cu->cu_closeit = FALSE;
- cu->cu_fd = fd;
- cl->cl_ops = clnt_dg_ops();
- cl->cl_private = (caddr_t)(void *)cu;
- cl->cl_auth = authnone_create();
- cl->cl_tp = NULL;
- cl->cl_netid = NULL;
-
- return (cl);
-err1:
- warnx(mem_err_clnt_dg);
- rpc_createerr.cf_stat = RPC_SYSTEMERROR;
- rpc_createerr.cf_error.re_errno = errno;
-err2:
- if (cl) {
- mem_free(cl, sizeof (CLIENT));
- if (cu)
- mem_free(cu, sizeof (*cu) + sendsz + recvsz);
- }
- return (NULL);
-}
-
-static enum clnt_stat
-clnt_dg_call(cl, proc, xargs, argsp, xresults, resultsp, utimeout)
- CLIENT *cl; /* client handle */
- rpcproc_t proc; /* procedure number */
- xdrproc_t xargs; /* xdr routine for args */
- void *argsp; /* pointer to args */
- xdrproc_t xresults; /* xdr routine for results */
- void *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;
- size_t outlen = 0;
- struct rpc_msg reply_msg;
- XDR reply_xdrs;
- bool_t ok;
- int nrefreshes = 2; /* number of times to refresh cred */
- struct timeval timeout;
- struct pollfd fd;
- int total_time, nextsend_time, tv;
- struct sockaddr *sa;
- sigset_t mask;
- sigset_t newmask;
- socklen_t inlen, salen;
- ssize_t recvlen = 0;
- int rpc_lock_value;
- u_int32_t xid;
-
- outlen = 0;
- sigfillset(&newmask);
- thr_sigsetmask(SIG_SETMASK, &newmask, &mask);
- mutex_lock(&clnt_fd_lock);
- while (dg_fd_locks[cu->cu_fd])
- cond_wait(&dg_cv[cu->cu_fd], &clnt_fd_lock);
- rpc_lock_value = 1;
- dg_fd_locks[cu->cu_fd] = rpc_lock_value;
- mutex_unlock(&clnt_fd_lock);
- if (cu->cu_total.tv_usec == -1) {
- timeout = utimeout; /* use supplied timeout */
- } else {
- timeout = cu->cu_total; /* use default timeout */
- }
- total_time = timeout.tv_sec * 1000 + timeout.tv_usec / 1000;
- nextsend_time = cu->cu_wait.tv_sec * 1000 + cu->cu_wait.tv_usec / 1000;
-
- if (cu->cu_connect && !cu->cu_connected) {
- if (connect(cu->cu_fd, (struct sockaddr *)&cu->cu_raddr,
- cu->cu_rlen) < 0) {
- cu->cu_error.re_errno = errno;
- cu->cu_error.re_status = RPC_CANTSEND;
- goto out;
- }
- cu->cu_connected = 1;
- }
- if (cu->cu_connected) {
- sa = NULL;
- salen = 0;
- } else {
- sa = (struct sockaddr *)&cu->cu_raddr;
- salen = cu->cu_rlen;
- }
-
- /* Clean up in case the last call ended in a longjmp(3) call. */
-call_again:
- xdrs = &(cu->cu_outxdrs);
- if (cu->cu_async == TRUE && 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
- * XXX Yes, and it's in network byte order, so we should to
- * be careful when we increment it, shouldn't we.
- */
- xid = ntohl(*(u_int32_t *)(void *)(cu->cu_outbuf));
- xid++;
- *(u_int32_t *)(void *)(cu->cu_outbuf) = htonl(xid);
-
- if ((! XDR_PUTINT32(xdrs, &proc)) ||
- (! AUTH_MARSHALL(cl->cl_auth, xdrs)) ||
- (! (*xargs)(xdrs, argsp))) {
- cu->cu_error.re_status = RPC_CANTENCODEARGS;
- goto out;
- }
- outlen = (size_t)XDR_GETPOS(xdrs);
-
- /*
- * Hack to provide rpc-based message passing
- */
- if (timeout.tv_sec == 0 && timeout.tv_usec == 0) {
- cu->cu_error.re_status = RPC_TIMEDOUT;
- goto out;
- }
-
-send_again:
- nextsend_time = cu->cu_wait.tv_sec * 1000 + cu->cu_wait.tv_usec / 1000;
- if (sendto(cu->cu_fd, cu->cu_outbuf, outlen, 0, sa, salen) != outlen) {
- cu->cu_error.re_errno = errno;
- cu->cu_error.re_status = RPC_CANTSEND;
- goto out;
- }
-
-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_fd;
- fd.events = POLLIN;
- while (total_time > 0) {
- tv = total_time < nextsend_time ? total_time : nextsend_time;
- switch (poll(&fd, 1, tv)) {
- case 0:
- total_time -= tv;
- goto send_again;
- case -1:
- if (errno == EINTR)
- continue;
- cu->cu_error.re_status = RPC_CANTRECV;
- cu->cu_error.re_errno = errno;
- goto out;
- }
- break;
- }
-
- /* We have some data now */
- do {
- recvlen = recvfrom(cu->cu_fd, cu->cu_inbuf,
- cu->cu_recvsz, 0, NULL, NULL);
- } while (recvlen < 0 && errno == EINTR);
- if (recvlen < 0 && errno != EWOULDBLOCK) {
- cu->cu_error.re_errno = errno;
- cu->cu_error.re_status = RPC_CANTRECV;
- goto out;
- }
- if (recvlen >= sizeof(u_int32_t) &&
- (cu->cu_async == TRUE ||
- *((u_int32_t *)(void *)(cu->cu_inbuf)) ==
- *((u_int32_t *)(void *)(cu->cu_outbuf))))
- inlen = (socklen_t)recvlen;
- else {
- total_time -= tv;
- goto send_again;
- }
-
- /*
- * now decode and validate the response
- */
-
- xdrmem_create(&reply_xdrs, cu->cu_inbuf, (u_int)recvlen, 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))
- cu->cu_error.re_status = RPC_SUCCESS;
- else
- _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 */
- /*
- * If unsuccesful AND error is an authentication error
- * then refresh credentials and try again, else break
- */
- else if (cu->cu_error.re_status == RPC_AUTHERROR)
- /* maybe our credentials need to be refreshed ... */
- if (nrefreshes > 0 &&
- AUTH_REFRESH(cl->cl_auth, &reply_msg)) {
- nrefreshes--;
- goto call_again;
- }
- /* end of unsuccessful completion */
- } /* end of valid reply message */
- else {
- cu->cu_error.re_status = RPC_CANTDECODERES;
-
- }
-out:
- release_fd_lock(cu->cu_fd, mask);
- return (cu->cu_error.re_status);
-}
-
-static void
-clnt_dg_geterr(cl, errp)
- CLIENT *cl;
- struct rpc_err *errp;
-{
- struct cu_data *cu = (struct cu_data *)cl->cl_private;
-
- *errp = cu->cu_error;
-}
-
-static bool_t
-clnt_dg_freeres(cl, xdr_res, res_ptr)
- CLIENT *cl;
- xdrproc_t xdr_res;
- void *res_ptr;
-{
- struct cu_data *cu = (struct cu_data *)cl->cl_private;
- XDR *xdrs = &(cu->cu_outxdrs);
- bool_t dummy;
- sigset_t mask;
- sigset_t newmask;
-
- sigfillset(&newmask);
- thr_sigsetmask(SIG_SETMASK, &newmask, &mask);
- mutex_lock(&clnt_fd_lock);
- while (dg_fd_locks[cu->cu_fd])
- cond_wait(&dg_cv[cu->cu_fd], &clnt_fd_lock);
- xdrs->x_op = XDR_FREE;
- dummy = (*xdr_res)(xdrs, res_ptr);
- mutex_unlock(&clnt_fd_lock);
- thr_sigsetmask(SIG_SETMASK, &mask, NULL);
- cond_signal(&dg_cv[cu->cu_fd]);
- return (dummy);
-}
-
-/*ARGSUSED*/
-static void
-clnt_dg_abort(h)
- CLIENT *h;
-{
-}
-
-static bool_t
-clnt_dg_control(cl, request, info)
- CLIENT *cl;
- u_int request;
- void *info;
-{
- struct cu_data *cu = (struct cu_data *)cl->cl_private;
- struct netbuf *addr;
- sigset_t mask;
- sigset_t newmask;
- int rpc_lock_value;
-
- sigfillset(&newmask);
- thr_sigsetmask(SIG_SETMASK, &newmask, &mask);
- mutex_lock(&clnt_fd_lock);
- while (dg_fd_locks[cu->cu_fd])
- cond_wait(&dg_cv[cu->cu_fd], &clnt_fd_lock);
- rpc_lock_value = 1;
- dg_fd_locks[cu->cu_fd] = rpc_lock_value;
- mutex_unlock(&clnt_fd_lock);
- switch (request) {
- case CLSET_FD_CLOSE:
- cu->cu_closeit = TRUE;
- release_fd_lock(cu->cu_fd, mask);
- return (TRUE);
- case CLSET_FD_NCLOSE:
- cu->cu_closeit = FALSE;
- release_fd_lock(cu->cu_fd, mask);
- return (TRUE);
- }
-
- /* for other requests which use info */
- if (info == NULL) {
- release_fd_lock(cu->cu_fd, mask);
- return (FALSE);
- }
- switch (request) {
- case CLSET_TIMEOUT:
- if (time_not_ok((struct timeval *)info)) {
- release_fd_lock(cu->cu_fd, mask);
- return (FALSE);
- }
- 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)) {
- release_fd_lock(cu->cu_fd, mask);
- return (FALSE);
- }
- 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) {
- release_fd_lock(cu->cu_fd, mask);
- return (FALSE);
- }
- (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:
- release_fd_lock(cu->cu_fd, mask);
- return (FALSE);
- }
- release_fd_lock(cu->cu_fd, mask);
- return (TRUE);
-}
-
-static void
-clnt_dg_destroy(cl)
- CLIENT *cl;
-{
- struct cu_data *cu = (struct cu_data *)cl->cl_private;
- int cu_fd = cu->cu_fd;
- sigset_t mask;
- sigset_t newmask;
-
- sigfillset(&newmask);
- thr_sigsetmask(SIG_SETMASK, &newmask, &mask);
- mutex_lock(&clnt_fd_lock);
- while (dg_fd_locks[cu_fd])
- cond_wait(&dg_cv[cu_fd], &clnt_fd_lock);
- if (cu->cu_closeit)
- (void)close(cu_fd);
- XDR_DESTROY(&(cu->cu_outxdrs));
- mem_free(cu, (sizeof (*cu) + cu->cu_sendsz + cu->cu_recvsz));
- if (cl->cl_netid && cl->cl_netid[0])
- mem_free(cl->cl_netid, strlen(cl->cl_netid) +1);
- if (cl->cl_tp && cl->cl_tp[0])
- mem_free(cl->cl_tp, strlen(cl->cl_tp) +1);
- mem_free(cl, sizeof (CLIENT));
- mutex_unlock(&clnt_fd_lock);
- thr_sigsetmask(SIG_SETMASK, &mask, NULL);
- cond_signal(&dg_cv[cu_fd]);
-}
-
-static struct clnt_ops *
-clnt_dg_ops()
-{
- static struct clnt_ops ops;
- extern mutex_t ops_lock;
- sigset_t mask;
- sigset_t newmask;
-
-/* VARIABLES PROTECTED BY ops_lock: ops */
-
- sigfillset(&newmask);
- thr_sigsetmask(SIG_SETMASK, &newmask, &mask);
- mutex_lock(&ops_lock);
- if (ops.cl_call == NULL) {
- ops.cl_call = clnt_dg_call;
- ops.cl_abort = clnt_dg_abort;
- ops.cl_geterr = clnt_dg_geterr;
- ops.cl_freeres = clnt_dg_freeres;
- ops.cl_destroy = clnt_dg_destroy;
- ops.cl_control = clnt_dg_control;
- }
- mutex_unlock(&ops_lock);
- thr_sigsetmask(SIG_SETMASK, &mask, NULL);
- return (&ops);
-}
-
-/*
- * Make sure that the time is not garbage. -1 value is allowed.
- */
-static bool_t
-time_not_ok(t)
- struct timeval *t;
-{
- return (t->tv_sec < -1 || t->tv_sec > 100000000 ||
- t->tv_usec < -1 || t->tv_usec > 1000000);
-}
-
diff --git a/src/rpbc_clnt.c b/src/rpbc_clnt.c
deleted file mode 100644
index 0e25747..0000000
--- a/src/rpbc_clnt.c
+++ /dev/null
@@ -1,1239 +0,0 @@
-/*
- * The contents of this file are subject to the Sun Standards
- * License Version 1.0 the (the "License";) You may not use
- * this file except in compliance with the License. You may
- * obtain a copy of the License at lib/libc/rpc/LICENSE
- *
- * Software distributed under the License is distributed on
- * an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either
- * express or implied. See the License for the specific
- * language governing rights and limitations under the License.
- *
- * The Original Code is Copyright 1998 by Sun Microsystems, Inc
- *
- * The Initial Developer of the Original Code is: Sun
- * Microsystems, Inc.
- *
- * All Rights Reserved.
- *
- * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
- * unrestricted use provided that this legend is included on all tape
- * media and as a part of the software program in whole or part. Users
- * may copy or modify Sun RPC without charge, but are not authorized
- * to license or distribute it to anyone else except as part of a product or
- * program developed by the user.
- *
- * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
- * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
- *
- * Sun RPC is provided with no support and without any obligation on the
- * part of Sun Microsystems, Inc. to assist in its use, correction,
- * modification or enhancement.
- *
- * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
- * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
- * OR ANY PART THEREOF.
- *
- * In no event will Sun Microsystems, Inc. be liable for any lost revenue
- * or profits or other special, indirect and consequential damages, even if
- * Sun has been advised of the possibility of such damages.
- *
- * Sun Microsystems, Inc.
- * 2550 Garcia Avenue
- * Mountain View, California 94043
- */
-/*
- * Copyright (c) 1986-1991 by Sun Microsystems Inc.
- */
-
-/*
- * rpcb_clnt.c
- * interface to rpcbind rpc service.
- *
- * Copyright (C) 1988, Sun Microsystems, Inc.
- */
-#include <pthread.h>
-#include <reentrant.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/un.h>
-#include <sys/utsname.h>
-#include <rpc/rpc.h>
-#include <rpc/rpcb_prot.h>
-#include <rpc/nettype.h>
-#include <netconfig.h>
-#ifdef PORTMAP
-#include <netinet/in.h> /* FOR IPPROTO_TCP/UDP definitions */
-#include <rpc/pmap_prot.h>
-#endif /* PORTMAP */
-#include <stdio.h>
-#include <errno.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <netdb.h>
-#include <syslog.h>
-
-#include "rpc_com.h"
-
-static struct timeval tottimeout = { 60, 0 };
-static const struct timeval rmttimeout = { 3, 0 };
-static struct timeval rpcbrmttime = { 15, 0 };
-
-extern bool_t xdr_wrapstring(XDR *, char **);
-
-static const char nullstring[] = "\000";
-
-#define CACHESIZE 6
-
-struct address_cache {
- char *ac_host;
- char *ac_netid;
- char *ac_uaddr;
- struct netbuf *ac_taddr;
- struct address_cache *ac_next;
-};
-
-static struct address_cache *front;
-static int cachesize;
-
-#define CLCR_GET_RPCB_TIMEOUT 1
-#define CLCR_SET_RPCB_TIMEOUT 2
-
-
-extern int __rpc_lowvers;
-
-static struct address_cache *check_cache(const char *, const char *);
-static void delete_cache(struct netbuf *);
-static void add_cache(const char *, const char *, struct netbuf *, char *);
-static CLIENT *getclnthandle(const char *, const struct netconfig *, char **);
-static CLIENT *local_rpcb(void);
-#if NOTUSED
-static struct netbuf *got_entry(rpcb_entry_list_ptr, const struct netconfig *);
-#endif
-
-/*
- * This routine adjusts the timeout used for calls to the remote rpcbind.
- * Also, this routine can be used to set the use of portmapper version 2
- * only when doing rpc_broadcasts
- * These are private routines that may not be provided in future releases.
- */
-bool_t
-__rpc_control(request, info)
- int request;
- void *info;
-{
- switch (request) {
- case CLCR_GET_RPCB_TIMEOUT:
- *(struct timeval *)info = tottimeout;
- break;
- case CLCR_SET_RPCB_TIMEOUT:
- tottimeout = *(struct timeval *)info;
- break;
- case CLCR_SET_LOWVERS:
- __rpc_lowvers = *(int *)info;
- break;
- case CLCR_GET_LOWVERS:
- *(int *)info = __rpc_lowvers;
- break;
- default:
- return (FALSE);
- }
- return (TRUE);
-}
-
-/*
- * It might seem that a reader/writer lock would be more reasonable here.
- * However because getclnthandle(), the only user of the cache functions,
- * may do a delete_cache() operation if a check_cache() fails to return an
- * address useful to clnt_tli_create(), we may as well use a mutex.
- */
-/*
- * As it turns out, if the cache lock is *not* a reader/writer lock, we will
- * block all clnt_create's if we are trying to connect to a host that's down,
- * since the lock will be held all during that time.
- */
-extern rwlock_t rpcbaddr_cache_lock;
-
-/*
- * The routines check_cache(), add_cache(), delete_cache() manage the
- * cache of rpcbind addresses for (host, netid).
- */
-
-static struct address_cache *
-check_cache(host, netid)
- const char *host, *netid;
-{
- struct address_cache *cptr;
-
- /* READ LOCK HELD ON ENTRY: rpcbaddr_cache_lock */
-
- for (cptr = front; cptr != NULL; cptr = cptr->ac_next) {
- if (!strcmp(cptr->ac_host, host) &&
- !strcmp(cptr->ac_netid, netid)) {
-#ifdef ND_DEBUG
- fprintf(stderr, "Found cache entry for %s: %s\n",
- host, netid);
-#endif
- return (cptr);
- }
- }
- return ((struct address_cache *) NULL);
-}
-
-static void
-delete_cache(addr)
- struct netbuf *addr;
-{
- struct address_cache *cptr, *prevptr = NULL;
-
- /* WRITE LOCK HELD ON ENTRY: rpcbaddr_cache_lock */
- for (cptr = front; cptr != NULL; cptr = cptr->ac_next) {
- if (!memcmp(cptr->ac_taddr->buf, addr->buf, addr->len)) {
- free(cptr->ac_host);
- free(cptr->ac_netid);
- free(cptr->ac_taddr->buf);
- free(cptr->ac_taddr);
- if (cptr->ac_uaddr)
- free(cptr->ac_uaddr);
- if (prevptr)
- prevptr->ac_next = cptr->ac_next;
- else
- front = cptr->ac_next;
- free(cptr);
- cachesize--;
- break;
- }
- prevptr = cptr;
- }
-}
-
-static void
-add_cache(host, netid, taddr, uaddr)
- const char *host, *netid;
- char *uaddr;
- struct netbuf *taddr;
-{
- struct address_cache *ad_cache, *cptr, *prevptr;
-
- ad_cache = (struct address_cache *)
- malloc(sizeof (struct address_cache));
- if (!ad_cache) {
- return;
- }
- ad_cache->ac_host = strdup(host);
- ad_cache->ac_netid = strdup(netid);
- ad_cache->ac_uaddr = uaddr ? strdup(uaddr) : NULL;
- ad_cache->ac_taddr = (struct netbuf *)malloc(sizeof (struct netbuf));
- if (!ad_cache->ac_host || !ad_cache->ac_netid || !ad_cache->ac_taddr ||
- (uaddr && !ad_cache->ac_uaddr)) {
- return;
- }
- ad_cache->ac_taddr->len = ad_cache->ac_taddr->maxlen = taddr->len;
- ad_cache->ac_taddr->buf = (char *) malloc(taddr->len);
- if (ad_cache->ac_taddr->buf == NULL) {
- return;
- }
- memcpy(ad_cache->ac_taddr->buf, taddr->buf, taddr->len);
-#ifdef ND_DEBUG
- fprintf(stderr, "Added to cache: %s : %s\n", host, netid);
-#endif
-
-/* VARIABLES PROTECTED BY rpcbaddr_cache_lock: cptr */
-
- rwlock_wrlock(&rpcbaddr_cache_lock);
- if (cachesize < CACHESIZE) {
- ad_cache->ac_next = front;
- front = ad_cache;
- cachesize++;
- } else {
- /* Free the last entry */
- cptr = front;
- prevptr = NULL;
- while (cptr->ac_next) {
- prevptr = cptr;
- cptr = cptr->ac_next;
- }
-
-#ifdef ND_DEBUG
- fprintf(stderr, "Deleted from cache: %s : %s\n",
- cptr->ac_host, cptr->ac_netid);
-#endif
- free(cptr->ac_host);
- free(cptr->ac_netid);
- free(cptr->ac_taddr->buf);
- free(cptr->ac_taddr);
- if (cptr->ac_uaddr)
- free(cptr->ac_uaddr);
-
- if (prevptr) {
- prevptr->ac_next = NULL;
- ad_cache->ac_next = front;
- front = ad_cache;
- } else {
- front = ad_cache;
- ad_cache->ac_next = NULL;
- }
- free(cptr);
- }
- rwlock_unlock(&rpcbaddr_cache_lock);
-}
-
-/*
- * This routine will return a client handle that is connected to the
- * rpcbind. If targaddr is non-NULL, the "universal address" of the
- * host will be stored in *targaddr; the caller is responsible for
- * freeing this string.
- * On error, returns NULL and free's everything.
- */
-static CLIENT *
-getclnthandle(host, nconf, targaddr)
- const char *host;
- const struct netconfig *nconf;
- char **targaddr;
-{
- CLIENT *client;
- struct netbuf *addr, taddr;
- struct netbuf addr_to_delete;
- struct __rpc_sockinfo si;
- struct addrinfo hints, *res, *tres;
- struct address_cache *ad_cache;
- char *tmpaddr;
-
-/* VARIABLES PROTECTED BY rpcbaddr_cache_lock: ad_cache */
-
- /* Get the address of the rpcbind. Check cache first */
- client = NULL;
- addr_to_delete.len = 0;
- rwlock_rdlock(&rpcbaddr_cache_lock);
- ad_cache = NULL;
- if (host != NULL)
- ad_cache = check_cache(host, nconf->nc_netid);
- if (ad_cache != NULL) {
- addr = ad_cache->ac_taddr;
- client = clnt_tli_create(RPC_ANYFD, nconf, addr,
- (rpcprog_t)RPCBPROG, (rpcvers_t)RPCBVERS4, 0, 0);
- if (client != NULL) {
- if (targaddr)
- *targaddr = strdup(ad_cache->ac_uaddr);
- rwlock_unlock(&rpcbaddr_cache_lock);
- return (client);
- }
- addr_to_delete.len = addr->len;
- addr_to_delete.buf = (char *)malloc(addr->len);
- if (addr_to_delete.buf == NULL) {
- addr_to_delete.len = 0;
- } else {
- memcpy(addr_to_delete.buf, addr->buf, addr->len);
- }
- }
- rwlock_unlock(&rpcbaddr_cache_lock);
- if (addr_to_delete.len != 0) {
- /*
- * Assume this may be due to cache data being
- * outdated
- */
- rwlock_wrlock(&rpcbaddr_cache_lock);
- delete_cache(&addr_to_delete);
- rwlock_unlock(&rpcbaddr_cache_lock);
- free(addr_to_delete.buf);
- }
- if (!__rpc_nconf2sockinfo(nconf, &si)) {
- rpc_createerr.cf_stat = RPC_UNKNOWNPROTO;
- return NULL;
- }
-
- memset(&hints, 0, sizeof hints);
- hints.ai_family = si.si_af;
- hints.ai_socktype = si.si_socktype;
- hints.ai_protocol = si.si_proto;
-
-#ifdef CLNT_DEBUG
- printf("trying netid %s family %d proto %d socktype %d\n",
- nconf->nc_netid, si.si_af, si.si_proto, si.si_socktype);
-#endif
-
- if (nconf->nc_protofmly != NULL && strcmp(nconf->nc_protofmly, NC_LOOPBACK) == 0) {
- client = local_rpcb();
- if (! client) {
-#ifdef ND_DEBUG
- clnt_pcreateerror("rpcbind clnt interface");
-#endif
- return (NULL);
- } else {
- struct sockaddr_un sun;
-
- *targaddr = malloc(sizeof(sun.sun_path));
- strncpy(*targaddr, _PATH_RPCBINDSOCK,
- sizeof(sun.sun_path));
- return (client);
- }
- } else {
- if (getaddrinfo(host, "sunrpc", &hints, &res) != 0) {
- rpc_createerr.cf_stat = RPC_UNKNOWNHOST;
- return NULL;
- }
- }
-
- for (tres = res; tres != NULL; tres = tres->ai_next) {
- taddr.buf = tres->ai_addr;
- taddr.len = taddr.maxlen = tres->ai_addrlen;
-
-#ifdef ND_DEBUG
- {
- char *ua;
-
- ua = taddr2uaddr(nconf, &taddr);
- fprintf(stderr, "Got it [%s]\n", ua);
- free(ua);
- }
-#endif
-
-#ifdef ND_DEBUG
- {
- int i;
-
- fprintf(stderr, "\tnetbuf len = %d, maxlen = %d\n",
- taddr.len, taddr.maxlen);
- fprintf(stderr, "\tAddress is ");
- for (i = 0; i < taddr.len; i++)
- fprintf(stderr, "%u.", ((char *)(taddr.buf))[i]);
- fprintf(stderr, "\n");
- }
-#endif
- client = clnt_tli_create(RPC_ANYFD, nconf, &taddr,
- (rpcprog_t)RPCBPROG, (rpcvers_t)RPCBVERS4, 0, 0);
-#ifdef ND_DEBUG
- if (! client) {
- clnt_pcreateerror("rpcbind clnt interface");
- }
-#endif
-
- if (client) {
- tmpaddr = targaddr ? taddr2uaddr(nconf, &taddr) : NULL;
- add_cache(host, nconf->nc_netid, &taddr, tmpaddr);
- if (targaddr)
- *targaddr = tmpaddr;
- break;
- }
- }
- if (res)
- freeaddrinfo(res);
- return (client);
-}
-
-/* XXX */
-#define IN4_LOCALHOST_STRING "127.0.0.1"
-#define IN6_LOCALHOST_STRING "::1"
-
-/*
- * This routine will return a client handle that is connected to the local
- * rpcbind. Returns NULL on error and free's everything.
- */
-static CLIENT *
-local_rpcb()
-{
- CLIENT *client;
- static struct netconfig *loopnconf;
- static char *hostname;
- extern mutex_t loopnconf_lock;
- int sock;
- size_t tsize;
- struct netbuf nbuf;
- struct sockaddr_un sun;
-
- /*
- * Try connecting to the local rpcbind through a local socket
- * first. If this doesn't work, try all transports defined in
- * the netconfig file.
- */
- memset(&sun, 0, sizeof sun);
- sock = socket(AF_LOCAL, SOCK_STREAM, 0);
- if (sock < 0)
- goto try_nconf;
- sun.sun_family = AF_LOCAL;
- strcpy(sun.sun_path, _PATH_RPCBINDSOCK);
- nbuf.len = SUN_LEN(&sun);
- nbuf.maxlen = sizeof (struct sockaddr_un);
- nbuf.buf = &sun;
-
- tsize = __rpc_get_t_size(AF_LOCAL, 0, 0);
- client = clnt_vc_create(sock, &nbuf, (rpcprog_t)RPCBPROG,
- (rpcvers_t)RPCBVERS, tsize, tsize);
-
- if (client != NULL) {
- /* Mark the socket to be closed in destructor */
- (void) CLNT_CONTROL(client, CLSET_FD_CLOSE, NULL);
- return client;
- }
-
- /* Nobody needs this socket anymore; free the descriptor. */
- close(sock);
-
-try_nconf:
-
-/* VARIABLES PROTECTED BY loopnconf_lock: loopnconf */
- mutex_lock(&loopnconf_lock);
- if (loopnconf == NULL) {
- struct netconfig *nconf, *tmpnconf = NULL;
- void *nc_handle;
- int fd;
-
- nc_handle = setnetconfig();
- if (nc_handle == NULL) {
- /* fails to open netconfig file */
- syslog (LOG_ERR, "rpc: failed to open " NETCONFIG);
- rpc_createerr.cf_stat = RPC_UNKNOWNPROTO;
- mutex_unlock(&loopnconf_lock);
- return (NULL);
- }
- while ((nconf = getnetconfig(nc_handle)) != NULL) {
-#ifdef INET6
- if ((strcmp(nconf->nc_protofmly, NC_INET6) == 0 ||
-#else
- if ((
-#endif
- strcmp(nconf->nc_protofmly, NC_INET) == 0) &&
- (nconf->nc_semantics == NC_TPI_COTS ||
- nconf->nc_semantics == NC_TPI_COTS_ORD)) {
- fd = __rpc_nconf2fd(nconf);
- /*
- * Can't create a socket, assume that
- * this family isn't configured in the kernel.
- */
- if (fd < 0)
- continue;
- close(fd);
- tmpnconf = nconf;
- if (!strcmp(nconf->nc_protofmly, NC_INET))
- hostname = IN4_LOCALHOST_STRING;
- else
- hostname = IN6_LOCALHOST_STRING;
- }
- }
- if (tmpnconf == NULL) {
- rpc_createerr.cf_stat = RPC_UNKNOWNPROTO;
- mutex_unlock(&loopnconf_lock);
- return (NULL);
- }
- loopnconf = getnetconfigent(tmpnconf->nc_netid);
- /* loopnconf is never freed */
- endnetconfig(nc_handle);
- }
- mutex_unlock(&loopnconf_lock);
- client = getclnthandle(hostname, loopnconf, NULL);
- return (client);
-}
-
-/*
- * Set a mapping between program, version and address.
- * Calls the rpcbind service to do the mapping.
- */
-bool_t
-rpcb_set(program, version, nconf, address)
- rpcprog_t program;
- rpcvers_t version;
- const struct netconfig *nconf; /* Network structure of transport */
- const struct netbuf *address; /* Services netconfig address */
-{
- CLIENT *client;
- bool_t rslt = FALSE;
- RPCB parms;
- char uidbuf[32];
-
- /* parameter checking */
- if (nconf == NULL) {
- rpc_createerr.cf_stat = RPC_UNKNOWNPROTO;
- return (FALSE);
- }
- if (address == NULL) {
- rpc_createerr.cf_stat = RPC_UNKNOWNADDR;
- return (FALSE);
- }
- client = local_rpcb();
- if (! client) {
- return (FALSE);
- }
-
- /* convert to universal */
- /*LINTED const castaway*/
- parms.r_addr = taddr2uaddr((struct netconfig *) nconf,
- (struct netbuf *)address);
- if (!parms.r_addr) {
- CLNT_DESTROY(client);
- rpc_createerr.cf_stat = RPC_N2AXLATEFAILURE;
- return (FALSE); /* no universal address */
- }
- parms.r_prog = program;
- parms.r_vers = version;
- parms.r_netid = nconf->nc_netid;
- /*
- * Though uid is not being used directly, we still send it for
- * completeness. For non-unix platforms, perhaps some other
- * string or an empty string can be sent.
- */
- (void) snprintf(uidbuf, sizeof uidbuf, "%d", geteuid());
- parms.r_owner = uidbuf;
-
- CLNT_CALL(client, (rpcproc_t)RPCBPROC_SET, (xdrproc_t) xdr_rpcb,
- (char *)&parms, (xdrproc_t) xdr_bool,
- (char *)&rslt, tottimeout);
-
- CLNT_DESTROY(client);
- free(parms.r_addr);
- return (rslt);
-}
-
-/*
- * Remove the mapping between program, version and netbuf address.
- * Calls the rpcbind service to do the un-mapping.
- * If netbuf is NULL, unset for all the transports, otherwise unset
- * only for the given transport.
- */
-bool_t
-rpcb_unset(program, version, nconf)
- rpcprog_t program;
- rpcvers_t version;
- const struct netconfig *nconf;
-{
- CLIENT *client;
- bool_t rslt = FALSE;
- RPCB parms;
- char uidbuf[32];
-
- client = local_rpcb();
- if (! client) {
- return (FALSE);
- }
-
- parms.r_prog = program;
- parms.r_vers = version;
- if (nconf)
- parms.r_netid = nconf->nc_netid;
- else {
- /*LINTED const castaway*/
- parms.r_netid = (char *) &nullstring[0]; /* unsets all */
- }
- /*LINTED const castaway*/
- parms.r_addr = (char *) &nullstring[0];
- (void) snprintf(uidbuf, sizeof uidbuf, "%d", geteuid());
- parms.r_owner = uidbuf;
-
- CLNT_CALL(client, (rpcproc_t)RPCBPROC_UNSET, (xdrproc_t) xdr_rpcb,
- (char *)(void *)&parms, (xdrproc_t) xdr_bool,
- (char *)(void *)&rslt, tottimeout);
-
- CLNT_DESTROY(client);
- return (rslt);
-}
-#ifdef NOTUSED
-/*
- * From the merged list, find the appropriate entry
- */
-static struct netbuf *
-got_entry(relp, nconf)
- rpcb_entry_list_ptr relp;
- const struct netconfig *nconf;
-{
- struct netbuf *na = NULL;
- rpcb_entry_list_ptr sp;
- rpcb_entry *rmap;
-
- for (sp = relp; sp != NULL; sp = sp->rpcb_entry_next) {
- rmap = &sp->rpcb_entry_map;
- if ((strcmp(nconf->nc_proto, rmap->r_nc_proto) == 0) &&
- (strcmp(nconf->nc_protofmly, rmap->r_nc_protofmly) == 0) &&
- (nconf->nc_semantics == rmap->r_nc_semantics) &&
- (rmap->r_maddr != NULL) && (rmap->r_maddr[0] != 0)) {
- na = uaddr2taddr(nconf, rmap->r_maddr);
-#ifdef ND_DEBUG
- fprintf(stderr, "\tRemote address is [%s].\n",
- rmap->r_maddr);
- if (!na)
- fprintf(stderr,
- "\tCouldn't resolve remote address!\n");
-#endif
- break;
- }
- }
- return (na);
-}
-#endif
-/*
- * Quick check to see if rpcbind is up. Tries to connect over
- * local transport.
- */
-bool_t
-__rpcbind_is_up()
-{
- struct netconfig *nconf;
- struct sockaddr_un sun;
- void *localhandle;
- int sock;
-
- nconf = NULL;
- localhandle = setnetconfig();
- while ((nconf = getnetconfig(localhandle)) != NULL) {
- if (nconf->nc_protofmly != NULL &&
- strcmp(nconf->nc_protofmly, NC_LOOPBACK) == 0)
- break;
- }
- if (nconf == NULL)
- return (FALSE);
-
- endnetconfig(localhandle);
-
- memset(&sun, 0, sizeof sun);
- sock = socket(AF_LOCAL, SOCK_STREAM, 0);
- if (sock < 0)
- return (FALSE);
- sun.sun_family = AF_LOCAL;
- strncpy(sun.sun_path, _PATH_RPCBINDSOCK, sizeof(sun.sun_path));
-
- if (connect(sock, (struct sockaddr *)&sun, sizeof(sun)) < 0) {
- close(sock);
- return (FALSE);
- }
-
- close(sock);
- return (TRUE);
-}
-
-/*
- * An internal function which optimizes rpcb_getaddr function. It also
- * returns the client handle that it uses to contact the remote rpcbind.
- *
- * The algorithm used: If the transports is TCP or UDP, it first tries
- * version 2 (portmap), 4 and then 3 (svr4). This order should be
- * changed in the next OS release to 4, 2 and 3. We are assuming that by
- * that time, version 4 would be available on many machines on the network.
- * With this algorithm, we get performance as well as a plan for
- * obsoleting version 2.
- *
- * For all other transports, the algorithm remains as 4 and then 3.
- *
- * XXX: Due to some problems with t_connect(), we do not reuse the same client
- * handle for COTS cases and hence in these cases we do not return the
- * client handle. This code will change if t_connect() ever
- * starts working properly. Also look under clnt_vc.c.
- */
-struct netbuf *
-__rpcb_findaddr_timed(program, version, nconf, host, clpp, tp)
- rpcprog_t program;
- rpcvers_t version;
- const struct netconfig *nconf;
- const char *host;
- CLIENT **clpp;
- struct timeval *tp;
-{
-#ifdef NOTUSED
- static bool_t check_rpcbind = TRUE;
-#endif
- CLIENT *client = NULL;
- RPCB parms;
- enum clnt_stat clnt_st;
- char *ua = NULL;
- rpcvers_t vers;
- struct netbuf *address = NULL;
- rpcvers_t start_vers = RPCBVERS4;
- struct netbuf servaddr;
-
- /* parameter checking */
- if (nconf == NULL) {
- rpc_createerr.cf_stat = RPC_UNKNOWNPROTO;
- return (NULL);
- }
-
- parms.r_addr = NULL;
-
- /*
- * Use default total timeout if no timeout is specified.
- */
- if (tp == NULL)
- tp = &tottimeout;
-
- /* try rpcbind */
- /* Now the same transport is to be used to get the address */
- if (client && ((nconf->nc_semantics == NC_TPI_COTS_ORD) ||
- (nconf->nc_semantics == NC_TPI_COTS))) {
- /* A CLTS type of client - destroy it */
- CLNT_DESTROY(client);
- client = NULL;
- }
-
- if (client == NULL) {
- client = getclnthandle(host, nconf, &parms.r_addr);
- if (client == NULL) {
- goto error;
- }
- }
- if (parms.r_addr == NULL) {
- /*LINTED const castaway*/
- parms.r_addr = (char *) &nullstring[0];
- }
-
- /* First try from start_vers(4) and then version 3 (RPCBVERS) */
-
- CLNT_CONTROL(client, CLSET_RETRY_TIMEOUT, (char *) &rpcbrmttime);
- for (vers = start_vers; vers >= RPCBVERS; vers--) {
- /* Set the version */
- CLNT_CONTROL(client, CLSET_VERS, (char *)(void *)&vers);
- clnt_st = CLNT_CALL(client, (rpcproc_t)RPCBPROC_GETADDR,
- (xdrproc_t) xdr_rpcb, (char *)(void *)&parms,
- (xdrproc_t) xdr_wrapstring, (char *)(void *) &ua, *tp);
- if (clnt_st == RPC_SUCCESS) {
- if ((ua == NULL) || (ua[0] == 0)) {
- /* address unknown */
- rpc_createerr.cf_stat = RPC_PROGNOTREGISTERED;
- continue; /* try other versions */
- }
- address = uaddr2taddr(nconf, ua);
-#ifdef ND_DEBUG
- fprintf(stderr, "\tRemote address is [%s]\n", ua);
- if (!address)
- fprintf(stderr,
- "\tCouldn't resolve remote address!\n");
-#endif
- xdr_free((xdrproc_t)xdr_wrapstring,
- (char *)(void *)&ua);
-
- if (! address) {
- /* We don't know about your universal address */
- rpc_createerr.cf_stat = RPC_N2AXLATEFAILURE;
- goto error;
- }
- CLNT_CONTROL(client, CLGET_SVC_ADDR,
- (char *)(void *)&servaddr);
- __rpc_fixup_addr(address, &servaddr);
- goto done;
- } else if (clnt_st == RPC_PROGVERSMISMATCH) {
- struct rpc_err rpcerr;
- clnt_geterr(client, &rpcerr);
- if (rpcerr.re_vers.low > RPCBVERS4)
- goto error; /* a new version, can't handle */
- } else if (clnt_st != RPC_PROGUNAVAIL) {
- /* Cant handle this error */
- rpc_createerr.cf_stat = clnt_st;
- clnt_geterr(client, &rpc_createerr.cf_error);
- goto error;
- }
- }
- /* if rpcbind requests failed -> try portmapper version 2 */
-#ifdef PORTMAP
- /* Try version 2 for TCP or UDP */
- if (strcmp(nconf->nc_protofmly, NC_INET) == 0) {
- u_short port = 0;
- struct netbuf remote;
- rpcvers_t pmapvers = 2;
- struct pmap pmapparms;
-
- /*
- * Try UDP only - there are some portmappers out
- * there that use UDP only.
- */
- if (strcmp(nconf->nc_proto, NC_TCP) == 0) {
- struct netconfig *newnconf;
-
- if ((newnconf = getnetconfigent("udp")) == NULL) {
- rpc_createerr.cf_stat = RPC_UNKNOWNPROTO;
- return (NULL);
- }
- client = getclnthandle(host, newnconf, &parms.r_addr);
- freenetconfigent(newnconf);
- } else {
- client = getclnthandle(host, nconf, &parms.r_addr);
- }
- if (client == NULL)
- return (NULL);
-
- /*
- * Set version and retry timeout.
- */
- CLNT_CONTROL(client, CLSET_RETRY_TIMEOUT, (char *)&rpcbrmttime);
- CLNT_CONTROL(client, CLSET_VERS, (char *)&pmapvers);
-
- pmapparms.pm_prog = program;
- pmapparms.pm_vers = version;
- pmapparms.pm_prot = strcmp(nconf->nc_proto, NC_TCP) ?
- IPPROTO_UDP : IPPROTO_TCP;
- pmapparms.pm_port = 0; /* not needed */
- clnt_st = CLNT_CALL(client, (rpcproc_t)PMAPPROC_GETPORT,
- (xdrproc_t) xdr_pmap, (caddr_t)(void *)&pmapparms,
- (xdrproc_t) xdr_u_short, (caddr_t)(void *)&port,
- *tp);
- if (clnt_st != RPC_SUCCESS) {
- if ((clnt_st == RPC_PROGVERSMISMATCH) ||
- (clnt_st == RPC_PROGUNAVAIL))
- goto error; /* All portmap/rpcbind versions failed */
- rpc_createerr.cf_stat = RPC_PMAPFAILURE;
- clnt_geterr(client, &rpc_createerr.cf_error);
- goto error;
- } else if (port == 0) {
- address = NULL;
- rpc_createerr.cf_stat = RPC_PROGNOTREGISTERED;
- goto error;
- }
- port = htons(port);
- CLNT_CONTROL(client, CLGET_SVC_ADDR, (char *)&remote);
- if (((address = (struct netbuf *)
- malloc(sizeof (struct netbuf))) == NULL) ||
- ((address->buf = (char *)
- malloc(remote.len)) == NULL)) {
- rpc_createerr.cf_stat = RPC_SYSTEMERROR;
- clnt_geterr(client, &rpc_createerr.cf_error);
- if (address) {
- free(address);
- address = NULL;
- }
- goto error;
- }
- memcpy(address->buf, remote.buf, remote.len);
- memcpy(&((char *)address->buf)[sizeof (short)],
- (char *)(void *)&port, sizeof (short));
- address->len = address->maxlen = remote.len;
- goto done;
- }
-
-
- //try_rpcbind:
-#endif /* PORTMAP */
-
- if ((address == NULL) || (address->len == 0)) {
- rpc_createerr.cf_stat = RPC_PROGNOTREGISTERED;
- clnt_geterr(client, &rpc_createerr.cf_error);
- }
-
-error:
- if (client) {
- CLNT_DESTROY(client);
- client = NULL;
- }
-done:
- if (nconf->nc_semantics != NC_TPI_CLTS) {
- /* This client is the connectionless one */
- if (client) {
- CLNT_DESTROY(client);
- client = NULL;
- }
- }
- if (clpp) {
- *clpp = client;
- } else if (client) {
- CLNT_DESTROY(client);
- }
- if (parms.r_addr != NULL && parms.r_addr != nullstring)
- free(parms.r_addr);
- return (address);
-}
-
-
-/*
- * Find the mapped address for program, version.
- * Calls the rpcbind service remotely to do the lookup.
- * Uses the transport specified in nconf.
- * Returns FALSE (0) if no map exists, else returns 1.
- *
- * Assuming that the address is all properly allocated
- */
-int
-rpcb_getaddr(program, version, nconf, address, host)
- rpcprog_t program;
- rpcvers_t version;
- const struct netconfig *nconf;
- struct netbuf *address;
- const char *host;
-{
- struct netbuf *na;
-
- if ((na = __rpcb_findaddr_timed(program, version,
- (struct netconfig *) nconf, (char *) host,
- (CLIENT **) NULL, (struct timeval *) NULL)) == NULL)
- return (FALSE);
-
- if (na->len > address->maxlen) {
- /* Too long address */
- free(na->buf);
- free(na);
- rpc_createerr.cf_stat = RPC_FAILED;
- return (FALSE);
- }
- memcpy(address->buf, na->buf, (size_t)na->len);
- address->len = na->len;
- free(na->buf);
- free(na);
- return (TRUE);
-}
-
-/*
- * Get a copy of the current maps.
- * Calls the rpcbind service remotely to get the maps.
- *
- * It returns only a list of the services
- * It returns NULL on failure.
- */
-rpcblist *
-rpcb_getmaps(nconf, host)
- const struct netconfig *nconf;
- const char *host;
-{
- rpcblist_ptr head = NULL;
- CLIENT *client;
- enum clnt_stat clnt_st;
- rpcvers_t vers = 0;
-
- client = getclnthandle(host, nconf, NULL);
- if (client == NULL) {
- return (head);
- }
- clnt_st = CLNT_CALL(client, (rpcproc_t)RPCBPROC_DUMP,
- (xdrproc_t) xdr_void, NULL, (xdrproc_t) xdr_rpcblist_ptr,
- (char *)(void *)&head, tottimeout);
- if (clnt_st == RPC_SUCCESS)
- goto done;
-
- if ((clnt_st != RPC_PROGVERSMISMATCH) &&
- (clnt_st != RPC_PROGUNAVAIL)) {
- rpc_createerr.cf_stat = RPC_RPCBFAILURE;
- clnt_geterr(client, &rpc_createerr.cf_error);
- goto done;
- }
-
- /* fall back to earlier version */
- CLNT_CONTROL(client, CLGET_VERS, (char *)(void *)&vers);
- if (vers == RPCBVERS4) {
- vers = RPCBVERS;
- CLNT_CONTROL(client, CLSET_VERS, (char *)(void *)&vers);
- if (CLNT_CALL(client, (rpcproc_t)RPCBPROC_DUMP,
- (xdrproc_t) xdr_void, NULL, (xdrproc_t) xdr_rpcblist_ptr,
- (char *)(void *)&head, tottimeout) == RPC_SUCCESS)
- goto done;
- }
- rpc_createerr.cf_stat = RPC_RPCBFAILURE;
- clnt_geterr(client, &rpc_createerr.cf_error);
-
-done:
- CLNT_DESTROY(client);
- return (head);
-}
-
-/*
- * rpcbinder remote-call-service interface.
- * This routine is used to call the rpcbind remote call service
- * which will look up a service program in the address maps, and then
- * remotely call that routine with the given parameters. This allows
- * programs to do a lookup and call in one step.
-*/
-enum clnt_stat
-rpcb_rmtcall(nconf, host, prog, vers, proc, xdrargs, argsp,
- xdrres, resp, tout, addr_ptr)
- const struct netconfig *nconf; /* Netconfig structure */
- const char *host; /* Remote host name */
- rpcprog_t prog;
- rpcvers_t vers;
- rpcproc_t proc; /* Remote proc identifiers */
- xdrproc_t xdrargs, xdrres; /* XDR routines */
- caddr_t argsp, resp; /* Argument and Result */
- struct timeval tout; /* Timeout value for this call */
- const struct netbuf *addr_ptr; /* Preallocated netbuf address */
-{
- CLIENT *client;
- enum clnt_stat stat;
- struct r_rpcb_rmtcallargs a;
- struct r_rpcb_rmtcallres r;
- rpcvers_t rpcb_vers;
-
- stat = 0;
- client = getclnthandle(host, nconf, NULL);
- if (client == NULL) {
- return (RPC_FAILED);
- }
- /*LINTED const castaway*/
- CLNT_CONTROL(client, CLSET_RETRY_TIMEOUT, (char *)(void *)&rmttimeout);
- a.prog = prog;
- a.vers = vers;
- a.proc = proc;
- a.args.args_val = argsp;
- a.xdr_args = xdrargs;
- r.addr = NULL;
- r.results.results_val = resp;
- r.xdr_res = xdrres;
-
- for (rpcb_vers = RPCBVERS4; rpcb_vers >= RPCBVERS; rpcb_vers--) {
- CLNT_CONTROL(client, CLSET_VERS, (char *)(void *)&rpcb_vers);
- stat = CLNT_CALL(client, (rpcproc_t)RPCBPROC_CALLIT,
- (xdrproc_t) xdr_rpcb_rmtcallargs, (char *)(void *)&a,
- (xdrproc_t) xdr_rpcb_rmtcallres, (char *)(void *)&r, tout);
- if ((stat == RPC_SUCCESS) && (addr_ptr != NULL)) {
- struct netbuf *na;
- /*LINTED const castaway*/
- na = uaddr2taddr((struct netconfig *) nconf, r.addr);
- if (!na) {
- stat = RPC_N2AXLATEFAILURE;
- /*LINTED const castaway*/
- ((struct netbuf *) addr_ptr)->len = 0;
- goto error;
- }
- if (na->len > addr_ptr->maxlen) {
- /* Too long address */
- stat = RPC_FAILED; /* XXX A better error no */
- free(na->buf);
- free(na);
- /*LINTED const castaway*/
- ((struct netbuf *) addr_ptr)->len = 0;
- goto error;
- }
- memcpy(addr_ptr->buf, na->buf, (size_t)na->len);
- /*LINTED const castaway*/
- ((struct netbuf *)addr_ptr)->len = na->len;
- free(na->buf);
- free(na);
- break;
- } else if ((stat != RPC_PROGVERSMISMATCH) &&
- (stat != RPC_PROGUNAVAIL)) {
- goto error;
- }
- }
-error:
- CLNT_DESTROY(client);
- if (r.addr)
- xdr_free((xdrproc_t) xdr_wrapstring, (char *)(void *)&r.addr);
- return (stat);
-}
-
-/*
- * Gets the time on the remote host.
- * Returns 1 if succeeds else 0.
- */
-bool_t
-rpcb_gettime(host, timep)
- const char *host;
- time_t *timep;
-{
- CLIENT *client = NULL;
- void *handle;
- struct netconfig *nconf;
- rpcvers_t vers;
- enum clnt_stat st;
-
- if ((host == NULL) || (host[0] == 0)) {
- time(timep);
- return (TRUE);
- }
-
- if ((handle = __rpc_setconf("netpath")) == NULL) {
- rpc_createerr.cf_stat = RPC_UNKNOWNPROTO;
- return (FALSE);
- }
- rpc_createerr.cf_stat = RPC_SUCCESS;
- while (client == NULL) {
- if ((nconf = __rpc_getconf(handle)) == NULL) {
- if (rpc_createerr.cf_stat == RPC_SUCCESS)
- rpc_createerr.cf_stat = RPC_UNKNOWNPROTO;
- break;
- }
- client = getclnthandle(host, nconf, NULL);
- if (client)
- break;
- }
- __rpc_endconf(handle);
- if (client == (CLIENT *) NULL) {
- return (FALSE);
- }
-
- st = CLNT_CALL(client, (rpcproc_t)RPCBPROC_GETTIME,
- (xdrproc_t) xdr_void, NULL,
- (xdrproc_t) xdr_int, (char *)(void *)timep, tottimeout);
-
- if ((st == RPC_PROGVERSMISMATCH) || (st == RPC_PROGUNAVAIL)) {
- CLNT_CONTROL(client, CLGET_VERS, (char *)(void *)&vers);
- if (vers == RPCBVERS4) {
- /* fall back to earlier version */
- vers = RPCBVERS;
- CLNT_CONTROL(client, CLSET_VERS, (char *)(void *)&vers);
- st = CLNT_CALL(client, (rpcproc_t)RPCBPROC_GETTIME,
- (xdrproc_t) xdr_void, NULL,
- (xdrproc_t) xdr_int, (char *)(void *)timep,
- tottimeout);
- }
- }
- CLNT_DESTROY(client);
- return (st == RPC_SUCCESS? TRUE: FALSE);
-}
-
-/*
- * Converts taddr to universal address. This routine should never
- * really be called because local n2a libraries are always provided.
- */
-char *
-rpcb_taddr2uaddr(nconf, taddr)
- struct netconfig *nconf;
- struct netbuf *taddr;
-{
- CLIENT *client;
- char *uaddr = NULL;
-
-
- /* parameter checking */
- if (nconf == NULL) {
- rpc_createerr.cf_stat = RPC_UNKNOWNPROTO;
- return (NULL);
- }
- if (taddr == NULL) {
- rpc_createerr.cf_stat = RPC_UNKNOWNADDR;
- return (NULL);
- }
- client = local_rpcb();
- if (! client) {
- return (NULL);
- }
-
- CLNT_CALL(client, (rpcproc_t)RPCBPROC_TADDR2UADDR,
- (xdrproc_t) xdr_netbuf, (char *)(void *)taddr,
- (xdrproc_t) xdr_wrapstring, (char *)(void *)&uaddr, tottimeout);
- CLNT_DESTROY(client);
- return (uaddr);
-}
-
-/*
- * Converts universal address to netbuf. This routine should never
- * really be called because local n2a libraries are always provided.
- */
-struct netbuf *
-rpcb_uaddr2taddr(nconf, uaddr)
- struct netconfig *nconf;
- char *uaddr;
-{
- CLIENT *client;
- struct netbuf *taddr;
-
-
- /* parameter checking */
- if (nconf == NULL) {
- rpc_createerr.cf_stat = RPC_UNKNOWNPROTO;
- return (NULL);
- }
- if (uaddr == NULL) {
- rpc_createerr.cf_stat = RPC_UNKNOWNADDR;
- return (NULL);
- }
- client = local_rpcb();
- if (! client) {
- return (NULL);
- }
-
- taddr = (struct netbuf *)calloc(1, sizeof (struct netbuf));
- if (taddr == NULL) {
- CLNT_DESTROY(client);
- return (NULL);
- }
- if (CLNT_CALL(client, (rpcproc_t)RPCBPROC_UADDR2TADDR,
- (xdrproc_t) xdr_wrapstring, (char *)(void *)&uaddr,
- (xdrproc_t) xdr_netbuf, (char *)(void *)taddr,
- tottimeout) != RPC_SUCCESS) {
- free(taddr);
- taddr = NULL;
- }
- CLNT_DESTROY(client);
- return (taddr);
-}
diff --git a/src/rpcb_clnt.c.ref b/src/rpcb_clnt.c.ref
deleted file mode 100644
index 23c0daa..0000000
--- a/src/rpcb_clnt.c.ref
+++ /dev/null
@@ -1,1342 +0,0 @@
-/*
- * The contents of this file are subject to the Sun Standards
- * License Version 1.0 the (the "License";) You may not use
- * this file except in compliance with the License. You may
- * obtain a copy of the License at lib/libc/rpc/LICENSE
- *
- * Software distributed under the License is distributed on
- * an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either
- * express or implied. See the License for the specific
- * language governing rights and limitations under the License.
- *
- * The Original Code is Copyright 1998 by Sun Microsystems, Inc
- *
- * The Initial Developer of the Original Code is: Sun
- * Microsystems, Inc.
- *
- * All Rights Reserved.
- *
- * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
- * unrestricted use provided that this legend is included on all tape
- * media and as a part of the software program in whole or part. Users
- * may copy or modify Sun RPC without charge, but are not authorized
- * to license or distribute it to anyone else except as part of a product or
- * program developed by the user.
- *
- * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
- * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
- *
- * Sun RPC is provided with no support and without any obligation on the
- * part of Sun Microsystems, Inc. to assist in its use, correction,
- * modification or enhancement.
- *
- * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
- * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
- * OR ANY PART THEREOF.
- *
- * In no event will Sun Microsystems, Inc. be liable for any lost revenue
- * or profits or other special, indirect and consequential damages, even if
- * Sun has been advised of the possibility of such damages.
- *
- * Sun Microsystems, Inc.
- * 2550 Garcia Avenue
- * Mountain View, California 94043
- */
-/*
- * Copyright (c) 1986-1991 by Sun Microsystems Inc.
- */
-
-/*
- * rpcb_clnt.c
- * interface to rpcbind rpc service.
- *
- * Copyright (C) 1988, Sun Microsystems, Inc.
- */
-#include <pthread.h>
-#include <reentrant.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/un.h>
-#include <sys/utsname.h>
-#include <rpc/rpc.h>
-#include <rpc/rpcb_prot.h>
-#include <rpc/nettype.h>
-#include <netconfig.h>
-#ifdef PORTMAP
-#include <netinet/in.h> /* FOR IPPROTO_TCP/UDP definitions */
-#include <rpc/pmap_prot.h>
-#endif /* PORTMAP */
-#include <stdio.h>
-#include <errno.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <netdb.h>
-#include <syslog.h>
-
-#include "rpc_com.h"
-
-static struct timeval tottimeout = { 60, 0 };
-static const struct timeval rmttimeout = { 3, 0 };
-static struct timeval rpcbrmttime = { 15, 0 };
-
-extern bool_t xdr_wrapstring(XDR *, char **);
-
-static const char nullstring[] = "\000";
-
-#define CACHESIZE 6
-
-struct address_cache {
- char *ac_host;
- char *ac_netid;
- char *ac_uaddr;
- struct netbuf *ac_taddr;
- struct address_cache *ac_next;
-};
-
-static struct address_cache *front;
-static int cachesize;
-
-#define CLCR_GET_RPCB_TIMEOUT 1
-#define CLCR_SET_RPCB_TIMEOUT 2
-
-
-extern int __rpc_lowvers;
-
-static struct address_cache *check_cache(const char *, const char *);
-static void delete_cache(struct netbuf *);
-static void add_cache(const char *, const char *, struct netbuf *, char *);
-static CLIENT *getclnthandle(const char *, const struct netconfig *, char **);
-static CLIENT *local_rpcb(void);
-static struct netbuf *got_entry(rpcb_entry_list_ptr, const struct netconfig *);
-
-/*
- * This routine adjusts the timeout used for calls to the remote rpcbind.
- * Also, this routine can be used to set the use of portmapper version 2
- * only when doing rpc_broadcasts
- * These are private routines that may not be provided in future releases.
- */
-bool_t
-__rpc_control(request, info)
- int request;
- void *info;
-{
- switch (request) {
- case CLCR_GET_RPCB_TIMEOUT:
- *(struct timeval *)info = tottimeout;
- break;
- case CLCR_SET_RPCB_TIMEOUT:
- tottimeout = *(struct timeval *)info;
- break;
- case CLCR_SET_LOWVERS:
- __rpc_lowvers = *(int *)info;
- break;
- case CLCR_GET_LOWVERS:
- *(int *)info = __rpc_lowvers;
- break;
- default:
- return (FALSE);
- }
- return (TRUE);
-}
-
-/*
- * It might seem that a reader/writer lock would be more reasonable here.
- * However because getclnthandle(), the only user of the cache functions,
- * may do a delete_cache() operation if a check_cache() fails to return an
- * address useful to clnt_tli_create(), we may as well use a mutex.
- */
-/*
- * As it turns out, if the cache lock is *not* a reader/writer lock, we will
- * block all clnt_create's if we are trying to connect to a host that's down,
- * since the lock will be held all during that time.
- */
-extern rwlock_t rpcbaddr_cache_lock;
-
-/*
- * The routines check_cache(), add_cache(), delete_cache() manage the
- * cache of rpcbind addresses for (host, netid).
- */
-
-static struct address_cache *
-check_cache(host, netid)
- const char *host, *netid;
-{
- struct address_cache *cptr;
-
- /* READ LOCK HELD ON ENTRY: rpcbaddr_cache_lock */
-
- for (cptr = front; cptr != NULL; cptr = cptr->ac_next) {
- if (!strcmp(cptr->ac_host, host) &&
- !strcmp(cptr->ac_netid, netid)) {
-#ifdef ND_DEBUG
- fprintf(stderr, "Found cache entry for %s: %s\n",
- host, netid);
-#endif
- return (cptr);
- }
- }
- return ((struct address_cache *) NULL);
-}
-
-static void
-delete_cache(addr)
- struct netbuf *addr;
-{
- struct address_cache *cptr, *prevptr = NULL;
-
- /* WRITE LOCK HELD ON ENTRY: rpcbaddr_cache_lock */
- for (cptr = front; cptr != NULL; cptr = cptr->ac_next) {
- if (!memcmp(cptr->ac_taddr->buf, addr->buf, addr->len)) {
- free(cptr->ac_host);
- free(cptr->ac_netid);
- free(cptr->ac_taddr->buf);
- free(cptr->ac_taddr);
- if (cptr->ac_uaddr)
- free(cptr->ac_uaddr);
- if (prevptr)
- prevptr->ac_next = cptr->ac_next;
- else
- front = cptr->ac_next;
- free(cptr);
- cachesize--;
- break;
- }
- prevptr = cptr;
- }
-}
-
-static void
-add_cache(host, netid, taddr, uaddr)
- const char *host, *netid;
- char *uaddr;
- struct netbuf *taddr;
-{
- struct address_cache *ad_cache, *cptr, *prevptr;
-
- ad_cache = (struct address_cache *)
- malloc(sizeof (struct address_cache));
- if (!ad_cache) {
- return;
- }
- ad_cache->ac_host = strdup(host);
- ad_cache->ac_netid = strdup(netid);
- ad_cache->ac_uaddr = uaddr ? strdup(uaddr) : NULL;
- ad_cache->ac_taddr = (struct netbuf *)malloc(sizeof (struct netbuf));
- if (!ad_cache->ac_host || !ad_cache->ac_netid || !ad_cache->ac_taddr ||
- (uaddr && !ad_cache->ac_uaddr)) {
- return;
- }
- ad_cache->ac_taddr->len = ad_cache->ac_taddr->maxlen = taddr->len;
- ad_cache->ac_taddr->buf = (char *) malloc(taddr->len);
- if (ad_cache->ac_taddr->buf == NULL) {
- return;
- }
- memcpy(ad_cache->ac_taddr->buf, taddr->buf, taddr->len);
-#ifdef ND_DEBUG
- fprintf(stderr, "Added to cache: %s : %s\n", host, netid);
-#endif
-
-/* VARIABLES PROTECTED BY rpcbaddr_cache_lock: cptr */
-
- rwlock_wrlock(&rpcbaddr_cache_lock);
- if (cachesize < CACHESIZE) {
- ad_cache->ac_next = front;
- front = ad_cache;
- cachesize++;
- } else {
- /* Free the last entry */
- cptr = front;
- prevptr = NULL;
- while (cptr->ac_next) {
- prevptr = cptr;
- cptr = cptr->ac_next;
- }
-
-#ifdef ND_DEBUG
- fprintf(stderr, "Deleted from cache: %s : %s\n",
- cptr->ac_host, cptr->ac_netid);
-#endif
- free(cptr->ac_host);
- free(cptr->ac_netid);
- free(cptr->ac_taddr->buf);
- free(cptr->ac_taddr);
- if (cptr->ac_uaddr)
- free(cptr->ac_uaddr);
-
- if (prevptr) {
- prevptr->ac_next = NULL;
- ad_cache->ac_next = front;
- front = ad_cache;
- } else {
- front = ad_cache;
- ad_cache->ac_next = NULL;
- }
- free(cptr);
- }
- rwlock_unlock(&rpcbaddr_cache_lock);
-}
-
-/*
- * This routine will return a client handle that is connected to the
- * rpcbind. If targaddr is non-NULL, the "universal address" of the
- * host will be stored in *targaddr; the caller is responsible for
- * freeing this string.
- * On error, returns NULL and free's everything.
- */
-static CLIENT *
-getclnthandle(host, nconf, targaddr)
- const char *host;
- const struct netconfig *nconf;
- char **targaddr;
-{
- CLIENT *client;
- struct netbuf *addr, taddr;
- struct netbuf addr_to_delete;
- struct __rpc_sockinfo si;
- struct addrinfo hints, *res, *tres;
- struct address_cache *ad_cache;
- char *tmpaddr;
-
-/* VARIABLES PROTECTED BY rpcbaddr_cache_lock: ad_cache */
-
- /* Get the address of the rpcbind. Check cache first */
- client = NULL;
- addr_to_delete.len = 0;
- rwlock_rdlock(&rpcbaddr_cache_lock);
- ad_cache = NULL;
- if (host != NULL)
- ad_cache = check_cache(host, nconf->nc_netid);
- if (ad_cache != NULL) {
- addr = ad_cache->ac_taddr;
- client = clnt_tli_create(RPC_ANYFD, nconf, addr,
- (rpcprog_t)RPCBPROG, (rpcvers_t)RPCBVERS4, 0, 0);
- if (client != NULL) {
- if (targaddr)
- *targaddr = strdup(ad_cache->ac_uaddr);
- rwlock_unlock(&rpcbaddr_cache_lock);
- return (client);
- }
- addr_to_delete.len = addr->len;
- addr_to_delete.buf = (char *)malloc(addr->len);
- if (addr_to_delete.buf == NULL) {
- addr_to_delete.len = 0;
- } else {
- memcpy(addr_to_delete.buf, addr->buf, addr->len);
- }
- }
- rwlock_unlock(&rpcbaddr_cache_lock);
- if (addr_to_delete.len != 0) {
- /*
- * Assume this may be due to cache data being
- * outdated
- */
- rwlock_wrlock(&rpcbaddr_cache_lock);
- delete_cache(&addr_to_delete);
- rwlock_unlock(&rpcbaddr_cache_lock);
- free(addr_to_delete.buf);
- }
- if (!__rpc_nconf2sockinfo(nconf, &si)) {
- rpc_createerr.cf_stat = RPC_UNKNOWNPROTO;
- return NULL;
- }
-
- memset(&hints, 0, sizeof hints);
- hints.ai_family = si.si_af;
- hints.ai_socktype = si.si_socktype;
- hints.ai_protocol = si.si_proto;
-
-#ifdef CLNT_DEBUG
- printf("trying netid %s family %d proto %d socktype %d\n",
- nconf->nc_netid, si.si_af, si.si_proto, si.si_socktype);
-#endif
-
- if (nconf->nc_protofmly != NULL && strcmp(nconf->nc_protofmly, NC_LOOPBACK) == 0) {
- client = local_rpcb();
- if (! client) {
-#ifdef ND_DEBUG
- clnt_pcreateerror("rpcbind clnt interface");
-#endif
- return (NULL);
- } else {
- struct sockaddr_un sun;
-
- *targaddr = malloc(sizeof(sun.sun_path));
- strncpy(*targaddr, _PATH_RPCBINDSOCK,
- sizeof(sun.sun_path));
- return (client);
- }
- } else {
- if (getaddrinfo(host, "sunrpc", &hints, &res) != 0) {
- rpc_createerr.cf_stat = RPC_UNKNOWNHOST;
- return NULL;
- }
- }
-
- for (tres = res; tres != NULL; tres = tres->ai_next) {
- taddr.buf = tres->ai_addr;
- taddr.len = taddr.maxlen = tres->ai_addrlen;
-
-#ifdef ND_DEBUG
- {
- char *ua;
-
- ua = taddr2uaddr(nconf, &taddr);
- fprintf(stderr, "Got it [%s]\n", ua);
- free(ua);
- }
-#endif
-
-#ifdef ND_DEBUG
- {
- int i;
-
- fprintf(stderr, "\tnetbuf len = %d, maxlen = %d\n",
- taddr.len, taddr.maxlen);
- fprintf(stderr, "\tAddress is ");
- for (i = 0; i < taddr.len; i++)
- fprintf(stderr, "%u.", ((char *)(taddr.buf))[i]);
- fprintf(stderr, "\n");
- }
-#endif
- client = clnt_tli_create(RPC_ANYFD, nconf, &taddr,
- (rpcprog_t)RPCBPROG, (rpcvers_t)RPCBVERS4, 0, 0);
-#ifdef ND_DEBUG
- if (! client) {
- clnt_pcreateerror("rpcbind clnt interface");
- }
-#endif
-
- if (client) {
- tmpaddr = targaddr ? taddr2uaddr(nconf, &taddr) : NULL;
- add_cache(host, nconf->nc_netid, &taddr, tmpaddr);
- if (targaddr)
- *targaddr = tmpaddr;
- break;
- }
- }
- if (res)
- freeaddrinfo(res);
- return (client);
-}
-
-/* XXX */
-#define IN4_LOCALHOST_STRING "127.0.0.1"
-#define IN6_LOCALHOST_STRING "::1"
-
-/*
- * This routine will return a client handle that is connected to the local
- * rpcbind. Returns NULL on error and free's everything.
- */
-static CLIENT *
-local_rpcb()
-{
- CLIENT *client;
- static struct netconfig *loopnconf;
- static char *hostname;
- extern mutex_t loopnconf_lock;
- int sock;
- size_t tsize;
- struct netbuf nbuf;
- struct sockaddr_un sun;
-
- /*
- * Try connecting to the local rpcbind through a local socket
- * first. If this doesn't work, try all transports defined in
- * the netconfig file.
- */
- memset(&sun, 0, sizeof sun);
- sock = socket(AF_LOCAL, SOCK_STREAM, 0);
- if (sock < 0)
- goto try_nconf;
- sun.sun_family = AF_LOCAL;
- strcpy(sun.sun_path, _PATH_RPCBINDSOCK);
- nbuf.len = SUN_LEN(&sun);
- nbuf.maxlen = sizeof (struct sockaddr_un);
- nbuf.buf = &sun;
-
- tsize = __rpc_get_t_size(AF_LOCAL, 0, 0);
- client = clnt_vc_create(sock, &nbuf, (rpcprog_t)RPCBPROG,
- (rpcvers_t)RPCBVERS, tsize, tsize);
-
- if (client != NULL) {
- /* Mark the socket to be closed in destructor */
- (void) CLNT_CONTROL(client, CLSET_FD_CLOSE, NULL);
- return client;
- }
-
- /* Nobody needs this socket anymore; free the descriptor. */
- close(sock);
-
-try_nconf:
-
-/* VARIABLES PROTECTED BY loopnconf_lock: loopnconf */
- mutex_lock(&loopnconf_lock);
- if (loopnconf == NULL) {
- struct netconfig *nconf, *tmpnconf = NULL;
- void *nc_handle;
- int fd;
-
- nc_handle = setnetconfig();
- if (nc_handle == NULL) {
- /* fails to open netconfig file */
- syslog (LOG_ERR, "rpc: failed to open " NETCONFIG);
- rpc_createerr.cf_stat = RPC_UNKNOWNPROTO;
- mutex_unlock(&loopnconf_lock);
- return (NULL);
- }
- while ((nconf = getnetconfig(nc_handle)) != NULL) {
-#ifdef INET6
- if ((strcmp(nconf->nc_protofmly, NC_INET6) == 0 ||
-#else
- if ((
-#endif
- strcmp(nconf->nc_protofmly, NC_INET) == 0) &&
- (nconf->nc_semantics == NC_TPI_COTS ||
- nconf->nc_semantics == NC_TPI_COTS_ORD)) {
- fd = __rpc_nconf2fd(nconf);
- /*
- * Can't create a socket, assume that
- * this family isn't configured in the kernel.
- */
- if (fd < 0)
- continue;
- close(fd);
- tmpnconf = nconf;
- if (!strcmp(nconf->nc_protofmly, NC_INET))
- hostname = IN4_LOCALHOST_STRING;
- else
- hostname = IN6_LOCALHOST_STRING;
- }
- }
- if (tmpnconf == NULL) {
- rpc_createerr.cf_stat = RPC_UNKNOWNPROTO;
- mutex_unlock(&loopnconf_lock);
- return (NULL);
- }
- loopnconf = getnetconfigent(tmpnconf->nc_netid);
- /* loopnconf is never freed */
- endnetconfig(nc_handle);
- }
- mutex_unlock(&loopnconf_lock);
- client = getclnthandle(hostname, loopnconf, NULL);
- return (client);
-}
-
-/*
- * Set a mapping between program, version and address.
- * Calls the rpcbind service to do the mapping.
- */
-bool_t
-rpcb_set(program, version, nconf, address)
- rpcprog_t program;
- rpcvers_t version;
- const struct netconfig *nconf; /* Network structure of transport */
- const struct netbuf *address; /* Services netconfig address */
-{
- CLIENT *client;
- bool_t rslt = FALSE;
- RPCB parms;
- char uidbuf[32];
-
- /* parameter checking */
- if (nconf == NULL) {
- rpc_createerr.cf_stat = RPC_UNKNOWNPROTO;
- return (FALSE);
- }
- if (address == NULL) {
- rpc_createerr.cf_stat = RPC_UNKNOWNADDR;
- return (FALSE);
- }
- client = local_rpcb();
- if (! client) {
- return (FALSE);
- }
-
- /* convert to universal */
- /*LINTED const castaway*/
- parms.r_addr = taddr2uaddr((struct netconfig *) nconf,
- (struct netbuf *)address);
- if (!parms.r_addr) {
- CLNT_DESTROY(client);
- rpc_createerr.cf_stat = RPC_N2AXLATEFAILURE;
- return (FALSE); /* no universal address */
- }
- parms.r_prog = program;
- parms.r_vers = version;
- parms.r_netid = nconf->nc_netid;
- /*
- * Though uid is not being used directly, we still send it for
- * completeness. For non-unix platforms, perhaps some other
- * string or an empty string can be sent.
- */
- (void) snprintf(uidbuf, sizeof uidbuf, "%d", geteuid());
- parms.r_owner = uidbuf;
-
- CLNT_CALL(client, (rpcproc_t)RPCBPROC_SET, (xdrproc_t) xdr_rpcb,
- (char *)&parms, (xdrproc_t) xdr_bool,
- (char *)&rslt, tottimeout);
-
- CLNT_DESTROY(client);
- free(parms.r_addr);
- return (rslt);
-}
-
-/*
- * Remove the mapping between program, version and netbuf address.
- * Calls the rpcbind service to do the un-mapping.
- * If netbuf is NULL, unset for all the transports, otherwise unset
- * only for the given transport.
- */
-bool_t
-rpcb_unset(program, version, nconf)
- rpcprog_t program;
- rpcvers_t version;
- const struct netconfig *nconf;
-{
- CLIENT *client;
- bool_t rslt = FALSE;
- RPCB parms;
- char uidbuf[32];
-
- client = local_rpcb();
- if (! client) {
- return (FALSE);
- }
-
- parms.r_prog = program;
- parms.r_vers = version;
- if (nconf)
- parms.r_netid = nconf->nc_netid;
- else {
- /*LINTED const castaway*/
- parms.r_netid = (char *) &nullstring[0]; /* unsets all */
- }
- /*LINTED const castaway*/
- parms.r_addr = (char *) &nullstring[0];
- (void) snprintf(uidbuf, sizeof uidbuf, "%d", geteuid());
- parms.r_owner = uidbuf;
-
- CLNT_CALL(client, (rpcproc_t)RPCBPROC_UNSET, (xdrproc_t) xdr_rpcb,
- (char *)(void *)&parms, (xdrproc_t) xdr_bool,
- (char *)(void *)&rslt, tottimeout);
-
- CLNT_DESTROY(client);
- return (rslt);
-}
-
-/*
- * From the merged list, find the appropriate entry
- */
-static struct netbuf *
-got_entry(relp, nconf)
- rpcb_entry_list_ptr relp;
- const struct netconfig *nconf;
-{
- struct netbuf *na = NULL;
- rpcb_entry_list_ptr sp;
- rpcb_entry *rmap;
-
- for (sp = relp; sp != NULL; sp = sp->rpcb_entry_next) {
- rmap = &sp->rpcb_entry_map;
- if ((strcmp(nconf->nc_proto, rmap->r_nc_proto) == 0) &&
- (strcmp(nconf->nc_protofmly, rmap->r_nc_protofmly) == 0) &&
- (nconf->nc_semantics == rmap->r_nc_semantics) &&
- (rmap->r_maddr != NULL) && (rmap->r_maddr[0] != 0)) {
- na = uaddr2taddr(nconf, rmap->r_maddr);
-#ifdef ND_DEBUG
- fprintf(stderr, "\tRemote address is [%s].\n",
- rmap->r_maddr);
- if (!na)
- fprintf(stderr,
- "\tCouldn't resolve remote address!\n");
-#endif
- break;
- }
- }
- return (na);
-}
-
-/*
- * Quick check to see if rpcbind is up. Tries to connect over
- * local transport.
- */
-bool_t
-__rpcbind_is_up()
-{
- struct netconfig *nconf;
- struct sockaddr_un sun;
- void *localhandle;
- int sock;
-
- nconf = NULL;
- localhandle = setnetconfig();
- while ((nconf = getnetconfig(localhandle)) != NULL) {
- if (nconf->nc_protofmly != NULL &&
- strcmp(nconf->nc_protofmly, NC_LOOPBACK) == 0)
- break;
- }
- if (nconf == NULL)
- return (FALSE);
-
- endnetconfig(localhandle);
-
- memset(&sun, 0, sizeof sun);
- sock = socket(AF_LOCAL, SOCK_STREAM, 0);
- if (sock < 0)
- return (FALSE);
- sun.sun_family = AF_LOCAL;
- strncpy(sun.sun_path, _PATH_RPCBINDSOCK, sizeof(sun.sun_path));
-
- if (connect(sock, (struct sockaddr *)&sun, sizeof(sun)) < 0) {
- close(sock);
- return (FALSE);
- }
-
- close(sock);
- return (TRUE);
-}
-
-/*
- * An internal function which optimizes rpcb_getaddr function. It also
- * returns the client handle that it uses to contact the remote rpcbind.
- *
- * The algorithm used: If the transports is TCP or UDP, it first tries
- * version 2 (portmap), 4 and then 3 (svr4). This order should be
- * changed in the next OS release to 4, 2 and 3. We are assuming that by
- * that time, version 4 would be available on many machines on the network.
- * With this algorithm, we get performance as well as a plan for
- * obsoleting version 2.
- *
- * For all other transports, the algorithm remains as 4 and then 3.
- *
- * XXX: Due to some problems with t_connect(), we do not reuse the same client
- * handle for COTS cases and hence in these cases we do not return the
- * client handle. This code will change if t_connect() ever
- * starts working properly. Also look under clnt_vc.c.
- */
-struct netbuf *
-__rpcb_findaddr_timed(program, version, nconf, host, clpp, tp)
- rpcprog_t program;
- rpcvers_t version;
- const struct netconfig *nconf;
- const char *host;
- CLIENT **clpp;
- struct timeval *tp;
-{
- static bool_t check_rpcbind = TRUE;
- CLIENT *client = NULL;
- RPCB parms;
- enum clnt_stat clnt_st;
- char *ua = NULL;
- rpcvers_t vers;
- struct netbuf *address = NULL;
- rpcvers_t start_vers = RPCBVERS4;
- struct netbuf servaddr;
-
- /* parameter checking */
- if (nconf == NULL) {
- rpc_createerr.cf_stat = RPC_UNKNOWNPROTO;
- return (NULL);
- }
-
- parms.r_addr = NULL;
-
- /*
- * Use default total timeout if no timeout is specified.
- */
- if (tp == NULL)
- tp = &tottimeout;
-
-#ifdef PORTMAP
- printf("try portmap vers 2\n");
- /* Try version 2 for TCP or UDP */
- if (strcmp(nconf->nc_protofmly, NC_INET) == 0) {
- u_short port = 0;
- struct netbuf remote;
- rpcvers_t pmapvers = 2;
- struct pmap pmapparms;
-
- /*
- * Try UDP only - there are some portmappers out
- * there that use UDP only.
- */
- if (strcmp(nconf->nc_proto, NC_TCP) == 0) {
- struct netconfig *newnconf;
-
- if ((newnconf = getnetconfigent("udp")) == NULL) {
- rpc_createerr.cf_stat = RPC_UNKNOWNPROTO;
- return (NULL);
- }
- client = getclnthandle(host, newnconf, &parms.r_addr);
- freenetconfigent(newnconf);
- } else {
- client = getclnthandle(host, nconf, &parms.r_addr);
- }
- if (client == NULL)
- return (NULL);
-
- /*
- * Set version and retry timeout.
- */
- CLNT_CONTROL(client, CLSET_RETRY_TIMEOUT, (char *)&rpcbrmttime);
- CLNT_CONTROL(client, CLSET_VERS, (char *)&pmapvers);
-
- pmapparms.pm_prog = program;
- pmapparms.pm_vers = version;
- pmapparms.pm_prot = strcmp(nconf->nc_proto, NC_TCP) ?
- IPPROTO_UDP : IPPROTO_TCP;
- pmapparms.pm_port = 0; /* not needed */
- clnt_st = CLNT_CALL(client, (rpcproc_t)PMAPPROC_GETPORT,
- (xdrproc_t) xdr_pmap, (caddr_t)(void *)&pmapparms,
- (xdrproc_t) xdr_u_short, (caddr_t)(void *)&port,
- *tp);
- if (clnt_st != RPC_SUCCESS) {
- if ((clnt_st == RPC_PROGVERSMISMATCH) ||
- (clnt_st == RPC_PROGUNAVAIL))
- goto try_rpcbind; /* Try different versions */
- rpc_createerr.cf_stat = RPC_PMAPFAILURE;
- clnt_geterr(client, &rpc_createerr.cf_error);
- goto error;
- } else if (port == 0) {
- address = NULL;
- rpc_createerr.cf_stat = RPC_PROGNOTREGISTERED;
- goto error;
- }
- port = htons(port);
- CLNT_CONTROL(client, CLGET_SVC_ADDR, (char *)&remote);
- if (((address = (struct netbuf *)
- malloc(sizeof (struct netbuf))) == NULL) ||
- ((address->buf = (char *)
- malloc(remote.len)) == NULL)) {
- rpc_createerr.cf_stat = RPC_SYSTEMERROR;
- clnt_geterr(client, &rpc_createerr.cf_error);
- if (address) {
- free(address);
- address = NULL;
- }
- goto error;
- }
- memcpy(address->buf, remote.buf, remote.len);
- memcpy(&((char *)address->buf)[sizeof (short)],
- (char *)(void *)&port, sizeof (short));
- address->len = address->maxlen = remote.len;
- goto done;
- }
-
-
-try_rpcbind:
-#endif /* PORTMAP */
- printf("try rpcbbind vers 4 -> GETADDRLIST\n");
- /*
- * Check if rpcbind is up. This prevents needless delays when
- * accessing applications such as the keyserver while booting
- * disklessly.
- */
- if (check_rpcbind && strcmp(nconf->nc_protofmly, NC_LOOPBACK) == 0) {
- if (!__rpcbind_is_up()) {
- rpc_createerr.cf_stat = RPC_PMAPFAILURE;
- rpc_createerr.cf_error.re_errno = 0;
- goto error;
- }
- check_rpcbind = FALSE;
- }
-
- /*
- * Now we try version 4 and then 3.
- * We also send the remote system the address we used to
- * contact it in case it can help to connect back with us
- */
- parms.r_prog = program;
- parms.r_vers = version;
- /*LINTED const castaway*/
- parms.r_owner = (char *) &nullstring[0]; /* not needed; */
- /* just for xdring */
- parms.r_netid = nconf->nc_netid; /* not really needed */
-
- /*
- * If a COTS transport is being used, try getting address via CLTS
- * transport. This works only with version 4.
- */
- if (nconf->nc_semantics == NC_TPI_COTS_ORD ||
- nconf->nc_semantics == NC_TPI_COTS) {
-
- void *handle;
- struct netconfig *nconf_clts;
- rpcb_entry_list_ptr relp = NULL;
-
- if (client == NULL) {
- /* This did not go through the above PORTMAP/TCP code */
- if ((handle = __rpc_setconf("datagram_v")) != NULL) {
- while ((nconf_clts = __rpc_getconf(handle))
- != NULL) {
- if (strcmp(nconf_clts->nc_protofmly,
- nconf->nc_protofmly) != 0) {
- continue;
- }
- client = getclnthandle(host, nconf_clts,
- &parms.r_addr);
- break;
- }
- __rpc_endconf(handle);
- }
- if (client == NULL)
- goto regular_rpcbind; /* Go the regular way */
- } else {
- /* This is a UDP PORTMAP handle. Change to version 4 */
- vers = RPCBVERS4;
- CLNT_CONTROL(client, CLSET_VERS, (char *)(void *)&vers);
- }
- /*
- * We also send the remote system the address we used to
- * contact it in case it can help it connect back with us
- */
- if (parms.r_addr == NULL) {
- /*LINTED const castaway*/
- parms.r_addr = (char *) &nullstring[0]; /* for XDRing */
- }
-
- CLNT_CONTROL(client, CLSET_RETRY_TIMEOUT, (char *)&rpcbrmttime);
-
- clnt_st = CLNT_CALL(client, (rpcproc_t)RPCBPROC_GETADDRLIST,
- (xdrproc_t) xdr_rpcb, (char *)(void *)&parms,
- (xdrproc_t) xdr_rpcb_entry_list_ptr,
- (char *)(void *)&relp, *tp);
- if (clnt_st == RPC_SUCCESS) {
- if ((address = got_entry(relp, nconf)) != NULL) {
- xdr_free((xdrproc_t) xdr_rpcb_entry_list_ptr,
- (char *)(void *)&relp);
- CLNT_CONTROL(client, CLGET_SVC_ADDR,
- (char *)(void *)&servaddr);
- __rpc_fixup_addr(address, &servaddr);
- goto done;
- }
- /* Entry not found for this transport */
- xdr_free((xdrproc_t) xdr_rpcb_entry_list_ptr,
- (char *)(void *)&relp);
- /*
- * XXX: should have perhaps returned with error but
- * since the remote machine might not always be able
- * to send the address on all transports, we try the
- * regular way with regular_rpcbind
- */
- goto regular_rpcbind;
- } else if ((clnt_st == RPC_PROGVERSMISMATCH) ||
- (clnt_st == RPC_PROGUNAVAIL)) {
- start_vers = RPCBVERS; /* Try version 3 now */
- goto regular_rpcbind; /* Try different versions */
- } else {
- rpc_createerr.cf_stat = RPC_PMAPFAILURE;
- clnt_geterr(client, &rpc_createerr.cf_error);
- goto error;
- }
- }
-
-regular_rpcbind:
- printf("try rpcbbind vers 3 -> RPCBPROC_GETADDR \n");
- /* Now the same transport is to be used to get the address */
- if (client && ((nconf->nc_semantics == NC_TPI_COTS_ORD) ||
- (nconf->nc_semantics == NC_TPI_COTS))) {
- /* A CLTS type of client - destroy it */
- CLNT_DESTROY(client);
- client = NULL;
- }
-
- if (client == NULL) {
- client = getclnthandle(host, nconf, &parms.r_addr);
- if (client == NULL) {
- goto error;
- }
- }
- if (parms.r_addr == NULL) {
- /*LINTED const castaway*/
- parms.r_addr = (char *) &nullstring[0];
- }
-
- /* First try from start_vers and then version 3 (RPCBVERS) */
-
- CLNT_CONTROL(client, CLSET_RETRY_TIMEOUT, (char *) &rpcbrmttime);
- for (vers = start_vers; vers >= RPCBVERS; vers--) {
- /* Set the version */
- CLNT_CONTROL(client, CLSET_VERS, (char *)(void *)&vers);
- clnt_st = CLNT_CALL(client, (rpcproc_t)RPCBPROC_GETADDR,
- (xdrproc_t) xdr_rpcb, (char *)(void *)&parms,
- (xdrproc_t) xdr_wrapstring, (char *)(void *) &ua, *tp);
- if (clnt_st == RPC_SUCCESS) {
- if ((ua == NULL) || (ua[0] == 0)) {
- /* address unknown */
- rpc_createerr.cf_stat = RPC_PROGNOTREGISTERED;
- goto error;
- }
- address = uaddr2taddr(nconf, ua);
-#ifdef ND_DEBUG
- fprintf(stderr, "\tRemote address is [%s]\n", ua);
- if (!address)
- fprintf(stderr,
- "\tCouldn't resolve remote address!\n");
-#endif
- xdr_free((xdrproc_t)xdr_wrapstring,
- (char *)(void *)&ua);
-
- if (! address) {
- /* We don't know about your universal address */
- rpc_createerr.cf_stat = RPC_N2AXLATEFAILURE;
- goto error;
- }
- CLNT_CONTROL(client, CLGET_SVC_ADDR,
- (char *)(void *)&servaddr);
- __rpc_fixup_addr(address, &servaddr);
- goto done;
- } else if (clnt_st == RPC_PROGVERSMISMATCH) {
- struct rpc_err rpcerr;
-
- clnt_geterr(client, &rpcerr);
- if (rpcerr.re_vers.low > RPCBVERS4)
- goto error; /* a new version, can't handle */
- } else if (clnt_st != RPC_PROGUNAVAIL) {
- /* Cant handle this error */
- rpc_createerr.cf_stat = clnt_st;
- clnt_geterr(client, &rpc_createerr.cf_error);
- goto error;
- }
- }
-
- if ((address == NULL) || (address->len == 0)) {
- rpc_createerr.cf_stat = RPC_PROGNOTREGISTERED;
- clnt_geterr(client, &rpc_createerr.cf_error);
- }
-
-error:
- if (client) {
- CLNT_DESTROY(client);
- client = NULL;
- }
-done:
- if (nconf->nc_semantics != NC_TPI_CLTS) {
- /* This client is the connectionless one */
- if (client) {
- CLNT_DESTROY(client);
- client = NULL;
- }
- }
- if (clpp) {
- *clpp = client;
- } else if (client) {
- CLNT_DESTROY(client);
- }
- if (parms.r_addr != NULL && parms.r_addr != nullstring)
- free(parms.r_addr);
- return (address);
-}
-
-
-/*
- * Find the mapped address for program, version.
- * Calls the rpcbind service remotely to do the lookup.
- * Uses the transport specified in nconf.
- * Returns FALSE (0) if no map exists, else returns 1.
- *
- * Assuming that the address is all properly allocated
- */
-int
-rpcb_getaddr(program, version, nconf, address, host)
- rpcprog_t program;
- rpcvers_t version;
- const struct netconfig *nconf;
- struct netbuf *address;
- const char *host;
-{
- struct netbuf *na;
-
- if ((na = __rpcb_findaddr_timed(program, version,
- (struct netconfig *) nconf, (char *) host,
- (CLIENT **) NULL, (struct timeval *) NULL)) == NULL)
- return (FALSE);
-
- if (na->len > address->maxlen) {
- /* Too long address */
- free(na->buf);
- free(na);
- rpc_createerr.cf_stat = RPC_FAILED;
- return (FALSE);
- }
- memcpy(address->buf, na->buf, (size_t)na->len);
- address->len = na->len;
- free(na->buf);
- free(na);
- return (TRUE);
-}
-
-/*
- * Get a copy of the current maps.
- * Calls the rpcbind service remotely to get the maps.
- *
- * It returns only a list of the services
- * It returns NULL on failure.
- */
-rpcblist *
-rpcb_getmaps(nconf, host)
- const struct netconfig *nconf;
- const char *host;
-{
- rpcblist_ptr head = NULL;
- CLIENT *client;
- enum clnt_stat clnt_st;
- rpcvers_t vers = 0;
-
- client = getclnthandle(host, nconf, NULL);
- if (client == NULL) {
- return (head);
- }
- clnt_st = CLNT_CALL(client, (rpcproc_t)RPCBPROC_DUMP,
- (xdrproc_t) xdr_void, NULL, (xdrproc_t) xdr_rpcblist_ptr,
- (char *)(void *)&head, tottimeout);
- if (clnt_st == RPC_SUCCESS)
- goto done;
-
- if ((clnt_st != RPC_PROGVERSMISMATCH) &&
- (clnt_st != RPC_PROGUNAVAIL)) {
- rpc_createerr.cf_stat = RPC_RPCBFAILURE;
- clnt_geterr(client, &rpc_createerr.cf_error);
- goto done;
- }
-
- /* fall back to earlier version */
- CLNT_CONTROL(client, CLGET_VERS, (char *)(void *)&vers);
- if (vers == RPCBVERS4) {
- vers = RPCBVERS;
- CLNT_CONTROL(client, CLSET_VERS, (char *)(void *)&vers);
- if (CLNT_CALL(client, (rpcproc_t)RPCBPROC_DUMP,
- (xdrproc_t) xdr_void, NULL, (xdrproc_t) xdr_rpcblist_ptr,
- (char *)(void *)&head, tottimeout) == RPC_SUCCESS)
- goto done;
- }
- rpc_createerr.cf_stat = RPC_RPCBFAILURE;
- clnt_geterr(client, &rpc_createerr.cf_error);
-
-done:
- CLNT_DESTROY(client);
- return (head);
-}
-
-/*
- * rpcbinder remote-call-service interface.
- * This routine is used to call the rpcbind remote call service
- * which will look up a service program in the address maps, and then
- * remotely call that routine with the given parameters. This allows
- * programs to do a lookup and call in one step.
-*/
-enum clnt_stat
-rpcb_rmtcall(nconf, host, prog, vers, proc, xdrargs, argsp,
- xdrres, resp, tout, addr_ptr)
- const struct netconfig *nconf; /* Netconfig structure */
- const char *host; /* Remote host name */
- rpcprog_t prog;
- rpcvers_t vers;
- rpcproc_t proc; /* Remote proc identifiers */
- xdrproc_t xdrargs, xdrres; /* XDR routines */
- caddr_t argsp, resp; /* Argument and Result */
- struct timeval tout; /* Timeout value for this call */
- const struct netbuf *addr_ptr; /* Preallocated netbuf address */
-{
- CLIENT *client;
- enum clnt_stat stat;
- struct r_rpcb_rmtcallargs a;
- struct r_rpcb_rmtcallres r;
- rpcvers_t rpcb_vers;
-
- stat = 0;
- client = getclnthandle(host, nconf, NULL);
- if (client == NULL) {
- return (RPC_FAILED);
- }
- /*LINTED const castaway*/
- CLNT_CONTROL(client, CLSET_RETRY_TIMEOUT, (char *)(void *)&rmttimeout);
- a.prog = prog;
- a.vers = vers;
- a.proc = proc;
- a.args.args_val = argsp;
- a.xdr_args = xdrargs;
- r.addr = NULL;
- r.results.results_val = resp;
- r.xdr_res = xdrres;
-
- for (rpcb_vers = RPCBVERS4; rpcb_vers >= RPCBVERS; rpcb_vers--) {
- CLNT_CONTROL(client, CLSET_VERS, (char *)(void *)&rpcb_vers);
- stat = CLNT_CALL(client, (rpcproc_t)RPCBPROC_CALLIT,
- (xdrproc_t) xdr_rpcb_rmtcallargs, (char *)(void *)&a,
- (xdrproc_t) xdr_rpcb_rmtcallres, (char *)(void *)&r, tout);
- if ((stat == RPC_SUCCESS) && (addr_ptr != NULL)) {
- struct netbuf *na;
- /*LINTED const castaway*/
- na = uaddr2taddr((struct netconfig *) nconf, r.addr);
- if (!na) {
- stat = RPC_N2AXLATEFAILURE;
- /*LINTED const castaway*/
- ((struct netbuf *) addr_ptr)->len = 0;
- goto error;
- }
- if (na->len > addr_ptr->maxlen) {
- /* Too long address */
- stat = RPC_FAILED; /* XXX A better error no */
- free(na->buf);
- free(na);
- /*LINTED const castaway*/
- ((struct netbuf *) addr_ptr)->len = 0;
- goto error;
- }
- memcpy(addr_ptr->buf, na->buf, (size_t)na->len);
- /*LINTED const castaway*/
- ((struct netbuf *)addr_ptr)->len = na->len;
- free(na->buf);
- free(na);
- break;
- } else if ((stat != RPC_PROGVERSMISMATCH) &&
- (stat != RPC_PROGUNAVAIL)) {
- goto error;
- }
- }
-error:
- CLNT_DESTROY(client);
- if (r.addr)
- xdr_free((xdrproc_t) xdr_wrapstring, (char *)(void *)&r.addr);
- return (stat);
-}
-
-/*
- * Gets the time on the remote host.
- * Returns 1 if succeeds else 0.
- */
-bool_t
-rpcb_gettime(host, timep)
- const char *host;
- time_t *timep;
-{
- CLIENT *client = NULL;
- void *handle;
- struct netconfig *nconf;
- rpcvers_t vers;
- enum clnt_stat st;
-
- if ((host == NULL) || (host[0] == 0)) {
- time(timep);
- return (TRUE);
- }
-
- if ((handle = __rpc_setconf("netpath")) == NULL) {
- rpc_createerr.cf_stat = RPC_UNKNOWNPROTO;
- return (FALSE);
- }
- rpc_createerr.cf_stat = RPC_SUCCESS;
- while (client == NULL) {
- if ((nconf = __rpc_getconf(handle)) == NULL) {
- if (rpc_createerr.cf_stat == RPC_SUCCESS)
- rpc_createerr.cf_stat = RPC_UNKNOWNPROTO;
- break;
- }
- client = getclnthandle(host, nconf, NULL);
- if (client)
- break;
- }
- __rpc_endconf(handle);
- if (client == (CLIENT *) NULL) {
- return (FALSE);
- }
-
- st = CLNT_CALL(client, (rpcproc_t)RPCBPROC_GETTIME,
- (xdrproc_t) xdr_void, NULL,
- (xdrproc_t) xdr_int, (char *)(void *)timep, tottimeout);
-
- if ((st == RPC_PROGVERSMISMATCH) || (st == RPC_PROGUNAVAIL)) {
- CLNT_CONTROL(client, CLGET_VERS, (char *)(void *)&vers);
- if (vers == RPCBVERS4) {
- /* fall back to earlier version */
- vers = RPCBVERS;
- CLNT_CONTROL(client, CLSET_VERS, (char *)(void *)&vers);
- st = CLNT_CALL(client, (rpcproc_t)RPCBPROC_GETTIME,
- (xdrproc_t) xdr_void, NULL,
- (xdrproc_t) xdr_int, (char *)(void *)timep,
- tottimeout);
- }
- }
- CLNT_DESTROY(client);
- return (st == RPC_SUCCESS? TRUE: FALSE);
-}
-
-/*
- * Converts taddr to universal address. This routine should never
- * really be called because local n2a libraries are always provided.
- */
-char *
-rpcb_taddr2uaddr(nconf, taddr)
- struct netconfig *nconf;
- struct netbuf *taddr;
-{
- CLIENT *client;
- char *uaddr = NULL;
-
-
- /* parameter checking */
- if (nconf == NULL) {
- rpc_createerr.cf_stat = RPC_UNKNOWNPROTO;
- return (NULL);
- }
- if (taddr == NULL) {
- rpc_createerr.cf_stat = RPC_UNKNOWNADDR;
- return (NULL);
- }
- client = local_rpcb();
- if (! client) {
- return (NULL);
- }
-
- CLNT_CALL(client, (rpcproc_t)RPCBPROC_TADDR2UADDR,
- (xdrproc_t) xdr_netbuf, (char *)(void *)taddr,
- (xdrproc_t) xdr_wrapstring, (char *)(void *)&uaddr, tottimeout);
- CLNT_DESTROY(client);
- return (uaddr);
-}
-
-/*
- * Converts universal address to netbuf. This routine should never
- * really be called because local n2a libraries are always provided.
- */
-struct netbuf *
-rpcb_uaddr2taddr(nconf, uaddr)
- struct netconfig *nconf;
- char *uaddr;
-{
- CLIENT *client;
- struct netbuf *taddr;
-
-
- /* parameter checking */
- if (nconf == NULL) {
- rpc_createerr.cf_stat = RPC_UNKNOWNPROTO;
- return (NULL);
- }
- if (uaddr == NULL) {
- rpc_createerr.cf_stat = RPC_UNKNOWNADDR;
- return (NULL);
- }
- client = local_rpcb();
- if (! client) {
- return (NULL);
- }
-
- taddr = (struct netbuf *)calloc(1, sizeof (struct netbuf));
- if (taddr == NULL) {
- CLNT_DESTROY(client);
- return (NULL);
- }
- if (CLNT_CALL(client, (rpcproc_t)RPCBPROC_UADDR2TADDR,
- (xdrproc_t) xdr_wrapstring, (char *)(void *)&uaddr,
- (xdrproc_t) xdr_netbuf, (char *)(void *)taddr,
- tottimeout) != RPC_SUCCESS) {
- free(taddr);
- taddr = NULL;
- }
- CLNT_DESTROY(client);
- return (taddr);
-}
diff --git a/src/rpcb_clnt.c~ b/src/rpcb_clnt.c~
deleted file mode 100644
index 75811f0..0000000
--- a/src/rpcb_clnt.c~
+++ /dev/null
@@ -1,1235 +0,0 @@
-/*
- * The contents of this file are subject to the Sun Standards
- * License Version 1.0 the (the "License";) You may not use
- * this file except in compliance with the License. You may
- * obtain a copy of the License at lib/libc/rpc/LICENSE
- *
- * Software distributed under the License is distributed on
- * an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either
- * express or implied. See the License for the specific
- * language governing rights and limitations under the License.
- *
- * The Original Code is Copyright 1998 by Sun Microsystems, Inc
- *
- * The Initial Developer of the Original Code is: Sun
- * Microsystems, Inc.
- *
- * All Rights Reserved.
- *
- * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
- * unrestricted use provided that this legend is included on all tape
- * media and as a part of the software program in whole or part. Users
- * may copy or modify Sun RPC without charge, but are not authorized
- * to license or distribute it to anyone else except as part of a product or
- * program developed by the user.
- *
- * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
- * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
- *
- * Sun RPC is provided with no support and without any obligation on the
- * part of Sun Microsystems, Inc. to assist in its use, correction,
- * modification or enhancement.
- *
- * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
- * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
- * OR ANY PART THEREOF.
- *
- * In no event will Sun Microsystems, Inc. be liable for any lost revenue
- * or profits or other special, indirect and consequential damages, even if
- * Sun has been advised of the possibility of such damages.
- *
- * Sun Microsystems, Inc.
- * 2550 Garcia Avenue
- * Mountain View, California 94043
- */
-/*
- * Copyright (c) 1986-1991 by Sun Microsystems Inc.
- */
-
-/*
- * rpcb_clnt.c
- * interface to rpcbind rpc service.
- *
- * Copyright (C) 1988, Sun Microsystems, Inc.
- */
-#include <pthread.h>
-#include <reentrant.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/un.h>
-#include <sys/utsname.h>
-#include <rpc/rpc.h>
-#include <rpc/rpcb_prot.h>
-#include <rpc/nettype.h>
-#include <netconfig.h>
-#ifdef PORTMAP
-#include <netinet/in.h> /* FOR IPPROTO_TCP/UDP definitions */
-#include <rpc/pmap_prot.h>
-#endif /* PORTMAP */
-#include <stdio.h>
-#include <errno.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <netdb.h>
-#include <syslog.h>
-
-#include "rpc_com.h"
-
-static struct timeval tottimeout = { 60, 0 };
-static const struct timeval rmttimeout = { 3, 0 };
-static struct timeval rpcbrmttime = { 15, 0 };
-
-extern bool_t xdr_wrapstring(XDR *, char **);
-
-static const char nullstring[] = "\000";
-
-#define CACHESIZE 6
-
-struct address_cache {
- char *ac_host;
- char *ac_netid;
- char *ac_uaddr;
- struct netbuf *ac_taddr;
- struct address_cache *ac_next;
-};
-
-static struct address_cache *front;
-static int cachesize;
-
-#define CLCR_GET_RPCB_TIMEOUT 1
-#define CLCR_SET_RPCB_TIMEOUT 2
-
-
-extern int __rpc_lowvers;
-
-static struct address_cache *check_cache(const char *, const char *);
-static void delete_cache(struct netbuf *);
-static void add_cache(const char *, const char *, struct netbuf *, char *);
-static CLIENT *getclnthandle(const char *, const struct netconfig *, char **);
-static CLIENT *local_rpcb(void);
-static struct netbuf *got_entry(rpcb_entry_list_ptr, const struct netconfig *);
-
-/*
- * This routine adjusts the timeout used for calls to the remote rpcbind.
- * Also, this routine can be used to set the use of portmapper version 2
- * only when doing rpc_broadcasts
- * These are private routines that may not be provided in future releases.
- */
-bool_t
-__rpc_control(request, info)
- int request;
- void *info;
-{
- switch (request) {
- case CLCR_GET_RPCB_TIMEOUT:
- *(struct timeval *)info = tottimeout;
- break;
- case CLCR_SET_RPCB_TIMEOUT:
- tottimeout = *(struct timeval *)info;
- break;
- case CLCR_SET_LOWVERS:
- __rpc_lowvers = *(int *)info;
- break;
- case CLCR_GET_LOWVERS:
- *(int *)info = __rpc_lowvers;
- break;
- default:
- return (FALSE);
- }
- return (TRUE);
-}
-
-/*
- * It might seem that a reader/writer lock would be more reasonable here.
- * However because getclnthandle(), the only user of the cache functions,
- * may do a delete_cache() operation if a check_cache() fails to return an
- * address useful to clnt_tli_create(), we may as well use a mutex.
- */
-/*
- * As it turns out, if the cache lock is *not* a reader/writer lock, we will
- * block all clnt_create's if we are trying to connect to a host that's down,
- * since the lock will be held all during that time.
- */
-extern rwlock_t rpcbaddr_cache_lock;
-
-/*
- * The routines check_cache(), add_cache(), delete_cache() manage the
- * cache of rpcbind addresses for (host, netid).
- */
-
-static struct address_cache *
-check_cache(host, netid)
- const char *host, *netid;
-{
- struct address_cache *cptr;
-
- /* READ LOCK HELD ON ENTRY: rpcbaddr_cache_lock */
-
- for (cptr = front; cptr != NULL; cptr = cptr->ac_next) {
- if (!strcmp(cptr->ac_host, host) &&
- !strcmp(cptr->ac_netid, netid)) {
-#ifdef ND_DEBUG
- fprintf(stderr, "Found cache entry for %s: %s\n",
- host, netid);
-#endif
- return (cptr);
- }
- }
- return ((struct address_cache *) NULL);
-}
-
-static void
-delete_cache(addr)
- struct netbuf *addr;
-{
- struct address_cache *cptr, *prevptr = NULL;
-
- /* WRITE LOCK HELD ON ENTRY: rpcbaddr_cache_lock */
- for (cptr = front; cptr != NULL; cptr = cptr->ac_next) {
- if (!memcmp(cptr->ac_taddr->buf, addr->buf, addr->len)) {
- free(cptr->ac_host);
- free(cptr->ac_netid);
- free(cptr->ac_taddr->buf);
- free(cptr->ac_taddr);
- if (cptr->ac_uaddr)
- free(cptr->ac_uaddr);
- if (prevptr)
- prevptr->ac_next = cptr->ac_next;
- else
- front = cptr->ac_next;
- free(cptr);
- cachesize--;
- break;
- }
- prevptr = cptr;
- }
-}
-
-static void
-add_cache(host, netid, taddr, uaddr)
- const char *host, *netid;
- char *uaddr;
- struct netbuf *taddr;
-{
- struct address_cache *ad_cache, *cptr, *prevptr;
-
- ad_cache = (struct address_cache *)
- malloc(sizeof (struct address_cache));
- if (!ad_cache) {
- return;
- }
- ad_cache->ac_host = strdup(host);
- ad_cache->ac_netid = strdup(netid);
- ad_cache->ac_uaddr = uaddr ? strdup(uaddr) : NULL;
- ad_cache->ac_taddr = (struct netbuf *)malloc(sizeof (struct netbuf));
- if (!ad_cache->ac_host || !ad_cache->ac_netid || !ad_cache->ac_taddr ||
- (uaddr && !ad_cache->ac_uaddr)) {
- return;
- }
- ad_cache->ac_taddr->len = ad_cache->ac_taddr->maxlen = taddr->len;
- ad_cache->ac_taddr->buf = (char *) malloc(taddr->len);
- if (ad_cache->ac_taddr->buf == NULL) {
- return;
- }
- memcpy(ad_cache->ac_taddr->buf, taddr->buf, taddr->len);
-#ifdef ND_DEBUG
- fprintf(stderr, "Added to cache: %s : %s\n", host, netid);
-#endif
-
-/* VARIABLES PROTECTED BY rpcbaddr_cache_lock: cptr */
-
- rwlock_wrlock(&rpcbaddr_cache_lock);
- if (cachesize < CACHESIZE) {
- ad_cache->ac_next = front;
- front = ad_cache;
- cachesize++;
- } else {
- /* Free the last entry */
- cptr = front;
- prevptr = NULL;
- while (cptr->ac_next) {
- prevptr = cptr;
- cptr = cptr->ac_next;
- }
-
-#ifdef ND_DEBUG
- fprintf(stderr, "Deleted from cache: %s : %s\n",
- cptr->ac_host, cptr->ac_netid);
-#endif
- free(cptr->ac_host);
- free(cptr->ac_netid);
- free(cptr->ac_taddr->buf);
- free(cptr->ac_taddr);
- if (cptr->ac_uaddr)
- free(cptr->ac_uaddr);
-
- if (prevptr) {
- prevptr->ac_next = NULL;
- ad_cache->ac_next = front;
- front = ad_cache;
- } else {
- front = ad_cache;
- ad_cache->ac_next = NULL;
- }
- free(cptr);
- }
- rwlock_unlock(&rpcbaddr_cache_lock);
-}
-
-/*
- * This routine will return a client handle that is connected to the
- * rpcbind. If targaddr is non-NULL, the "universal address" of the
- * host will be stored in *targaddr; the caller is responsible for
- * freeing this string.
- * On error, returns NULL and free's everything.
- */
-static CLIENT *
-getclnthandle(host, nconf, targaddr)
- const char *host;
- const struct netconfig *nconf;
- char **targaddr;
-{
- CLIENT *client;
- struct netbuf *addr, taddr;
- struct netbuf addr_to_delete;
- struct __rpc_sockinfo si;
- struct addrinfo hints, *res, *tres;
- struct address_cache *ad_cache;
- char *tmpaddr;
-
-/* VARIABLES PROTECTED BY rpcbaddr_cache_lock: ad_cache */
-
- /* Get the address of the rpcbind. Check cache first */
- client = NULL;
- addr_to_delete.len = 0;
- rwlock_rdlock(&rpcbaddr_cache_lock);
- ad_cache = NULL;
- if (host != NULL)
- ad_cache = check_cache(host, nconf->nc_netid);
- if (ad_cache != NULL) {
- addr = ad_cache->ac_taddr;
- client = clnt_tli_create(RPC_ANYFD, nconf, addr,
- (rpcprog_t)RPCBPROG, (rpcvers_t)RPCBVERS4, 0, 0);
- if (client != NULL) {
- if (targaddr)
- *targaddr = strdup(ad_cache->ac_uaddr);
- rwlock_unlock(&rpcbaddr_cache_lock);
- return (client);
- }
- addr_to_delete.len = addr->len;
- addr_to_delete.buf = (char *)malloc(addr->len);
- if (addr_to_delete.buf == NULL) {
- addr_to_delete.len = 0;
- } else {
- memcpy(addr_to_delete.buf, addr->buf, addr->len);
- }
- }
- rwlock_unlock(&rpcbaddr_cache_lock);
- if (addr_to_delete.len != 0) {
- /*
- * Assume this may be due to cache data being
- * outdated
- */
- rwlock_wrlock(&rpcbaddr_cache_lock);
- delete_cache(&addr_to_delete);
- rwlock_unlock(&rpcbaddr_cache_lock);
- free(addr_to_delete.buf);
- }
- if (!__rpc_nconf2sockinfo(nconf, &si)) {
- rpc_createerr.cf_stat = RPC_UNKNOWNPROTO;
- return NULL;
- }
-
- memset(&hints, 0, sizeof hints);
- hints.ai_family = si.si_af;
- hints.ai_socktype = si.si_socktype;
- hints.ai_protocol = si.si_proto;
-
-#ifdef CLNT_DEBUG
- printf("trying netid %s family %d proto %d socktype %d\n",
- nconf->nc_netid, si.si_af, si.si_proto, si.si_socktype);
-#endif
-
- if (nconf->nc_protofmly != NULL && strcmp(nconf->nc_protofmly, NC_LOOPBACK) == 0) {
- client = local_rpcb();
- if (! client) {
-#ifdef ND_DEBUG
- clnt_pcreateerror("rpcbind clnt interface");
-#endif
- return (NULL);
- } else {
- struct sockaddr_un sun;
-
- *targaddr = malloc(sizeof(sun.sun_path));
- strncpy(*targaddr, _PATH_RPCBINDSOCK,
- sizeof(sun.sun_path));
- return (client);
- }
- } else {
- if (getaddrinfo(host, "sunrpc", &hints, &res) != 0) {
- rpc_createerr.cf_stat = RPC_UNKNOWNHOST;
- return NULL;
- }
- }
-
- for (tres = res; tres != NULL; tres = tres->ai_next) {
- taddr.buf = tres->ai_addr;
- taddr.len = taddr.maxlen = tres->ai_addrlen;
-
-#ifdef ND_DEBUG
- {
- char *ua;
-
- ua = taddr2uaddr(nconf, &taddr);
- fprintf(stderr, "Got it [%s]\n", ua);
- free(ua);
- }
-#endif
-
-#ifdef ND_DEBUG
- {
- int i;
-
- fprintf(stderr, "\tnetbuf len = %d, maxlen = %d\n",
- taddr.len, taddr.maxlen);
- fprintf(stderr, "\tAddress is ");
- for (i = 0; i < taddr.len; i++)
- fprintf(stderr, "%u.", ((char *)(taddr.buf))[i]);
- fprintf(stderr, "\n");
- }
-#endif
- client = clnt_tli_create(RPC_ANYFD, nconf, &taddr,
- (rpcprog_t)RPCBPROG, (rpcvers_t)RPCBVERS4, 0, 0);
-#ifdef ND_DEBUG
- if (! client) {
- clnt_pcreateerror("rpcbind clnt interface");
- }
-#endif
-
- if (client) {
- tmpaddr = targaddr ? taddr2uaddr(nconf, &taddr) : NULL;
- add_cache(host, nconf->nc_netid, &taddr, tmpaddr);
- if (targaddr)
- *targaddr = tmpaddr;
- break;
- }
- }
- if (res)
- freeaddrinfo(res);
- return (client);
-}
-
-/* XXX */
-#define IN4_LOCALHOST_STRING "127.0.0.1"
-#define IN6_LOCALHOST_STRING "::1"
-
-/*
- * This routine will return a client handle that is connected to the local
- * rpcbind. Returns NULL on error and free's everything.
- */
-static CLIENT *
-local_rpcb()
-{
- CLIENT *client;
- static struct netconfig *loopnconf;
- static char *hostname;
- extern mutex_t loopnconf_lock;
- int sock;
- size_t tsize;
- struct netbuf nbuf;
- struct sockaddr_un sun;
-
- /*
- * Try connecting to the local rpcbind through a local socket
- * first. If this doesn't work, try all transports defined in
- * the netconfig file.
- */
- memset(&sun, 0, sizeof sun);
- sock = socket(AF_LOCAL, SOCK_STREAM, 0);
- if (sock < 0)
- goto try_nconf;
- sun.sun_family = AF_LOCAL;
- strcpy(sun.sun_path, _PATH_RPCBINDSOCK);
- nbuf.len = SUN_LEN(&sun);
- nbuf.maxlen = sizeof (struct sockaddr_un);
- nbuf.buf = &sun;
-
- tsize = __rpc_get_t_size(AF_LOCAL, 0, 0);
- client = clnt_vc_create(sock, &nbuf, (rpcprog_t)RPCBPROG,
- (rpcvers_t)RPCBVERS, tsize, tsize);
-
- if (client != NULL) {
- /* Mark the socket to be closed in destructor */
- (void) CLNT_CONTROL(client, CLSET_FD_CLOSE, NULL);
- return client;
- }
-
- /* Nobody needs this socket anymore; free the descriptor. */
- close(sock);
-
-try_nconf:
-
-/* VARIABLES PROTECTED BY loopnconf_lock: loopnconf */
- mutex_lock(&loopnconf_lock);
- if (loopnconf == NULL) {
- struct netconfig *nconf, *tmpnconf = NULL;
- void *nc_handle;
- int fd;
-
- nc_handle = setnetconfig();
- if (nc_handle == NULL) {
- /* fails to open netconfig file */
- syslog (LOG_ERR, "rpc: failed to open " NETCONFIG);
- rpc_createerr.cf_stat = RPC_UNKNOWNPROTO;
- mutex_unlock(&loopnconf_lock);
- return (NULL);
- }
- while ((nconf = getnetconfig(nc_handle)) != NULL) {
-#ifdef INET6
- if ((strcmp(nconf->nc_protofmly, NC_INET6) == 0 ||
-#else
- if ((
-#endif
- strcmp(nconf->nc_protofmly, NC_INET) == 0) &&
- (nconf->nc_semantics == NC_TPI_COTS ||
- nconf->nc_semantics == NC_TPI_COTS_ORD)) {
- fd = __rpc_nconf2fd(nconf);
- /*
- * Can't create a socket, assume that
- * this family isn't configured in the kernel.
- */
- if (fd < 0)
- continue;
- close(fd);
- tmpnconf = nconf;
- if (!strcmp(nconf->nc_protofmly, NC_INET))
- hostname = IN4_LOCALHOST_STRING;
- else
- hostname = IN6_LOCALHOST_STRING;
- }
- }
- if (tmpnconf == NULL) {
- rpc_createerr.cf_stat = RPC_UNKNOWNPROTO;
- mutex_unlock(&loopnconf_lock);
- return (NULL);
- }
- loopnconf = getnetconfigent(tmpnconf->nc_netid);
- /* loopnconf is never freed */
- endnetconfig(nc_handle);
- }
- mutex_unlock(&loopnconf_lock);
- client = getclnthandle(hostname, loopnconf, NULL);
- return (client);
-}
-
-/*
- * Set a mapping between program, version and address.
- * Calls the rpcbind service to do the mapping.
- */
-bool_t
-rpcb_set(program, version, nconf, address)
- rpcprog_t program;
- rpcvers_t version;
- const struct netconfig *nconf; /* Network structure of transport */
- const struct netbuf *address; /* Services netconfig address */
-{
- CLIENT *client;
- bool_t rslt = FALSE;
- RPCB parms;
- char uidbuf[32];
-
- /* parameter checking */
- if (nconf == NULL) {
- rpc_createerr.cf_stat = RPC_UNKNOWNPROTO;
- return (FALSE);
- }
- if (address == NULL) {
- rpc_createerr.cf_stat = RPC_UNKNOWNADDR;
- return (FALSE);
- }
- client = local_rpcb();
- if (! client) {
- return (FALSE);
- }
-
- /* convert to universal */
- /*LINTED const castaway*/
- parms.r_addr = taddr2uaddr((struct netconfig *) nconf,
- (struct netbuf *)address);
- if (!parms.r_addr) {
- CLNT_DESTROY(client);
- rpc_createerr.cf_stat = RPC_N2AXLATEFAILURE;
- return (FALSE); /* no universal address */
- }
- parms.r_prog = program;
- parms.r_vers = version;
- parms.r_netid = nconf->nc_netid;
- /*
- * Though uid is not being used directly, we still send it for
- * completeness. For non-unix platforms, perhaps some other
- * string or an empty string can be sent.
- */
- (void) snprintf(uidbuf, sizeof uidbuf, "%d", geteuid());
- parms.r_owner = uidbuf;
-
- CLNT_CALL(client, (rpcproc_t)RPCBPROC_SET, (xdrproc_t) xdr_rpcb,
- (char *)&parms, (xdrproc_t) xdr_bool,
- (char *)&rslt, tottimeout);
-
- CLNT_DESTROY(client);
- free(parms.r_addr);
- return (rslt);
-}
-
-/*
- * Remove the mapping between program, version and netbuf address.
- * Calls the rpcbind service to do the un-mapping.
- * If netbuf is NULL, unset for all the transports, otherwise unset
- * only for the given transport.
- */
-bool_t
-rpcb_unset(program, version, nconf)
- rpcprog_t program;
- rpcvers_t version;
- const struct netconfig *nconf;
-{
- CLIENT *client;
- bool_t rslt = FALSE;
- RPCB parms;
- char uidbuf[32];
-
- client = local_rpcb();
- if (! client) {
- return (FALSE);
- }
-
- parms.r_prog = program;
- parms.r_vers = version;
- if (nconf)
- parms.r_netid = nconf->nc_netid;
- else {
- /*LINTED const castaway*/
- parms.r_netid = (char *) &nullstring[0]; /* unsets all */
- }
- /*LINTED const castaway*/
- parms.r_addr = (char *) &nullstring[0];
- (void) snprintf(uidbuf, sizeof uidbuf, "%d", geteuid());
- parms.r_owner = uidbuf;
-
- CLNT_CALL(client, (rpcproc_t)RPCBPROC_UNSET, (xdrproc_t) xdr_rpcb,
- (char *)(void *)&parms, (xdrproc_t) xdr_bool,
- (char *)(void *)&rslt, tottimeout);
-
- CLNT_DESTROY(client);
- return (rslt);
-}
-
-/*
- * From the merged list, find the appropriate entry
- */
-static struct netbuf *
-got_entry(relp, nconf)
- rpcb_entry_list_ptr relp;
- const struct netconfig *nconf;
-{
- struct netbuf *na = NULL;
- rpcb_entry_list_ptr sp;
- rpcb_entry *rmap;
-
- for (sp = relp; sp != NULL; sp = sp->rpcb_entry_next) {
- rmap = &sp->rpcb_entry_map;
- if ((strcmp(nconf->nc_proto, rmap->r_nc_proto) == 0) &&
- (strcmp(nconf->nc_protofmly, rmap->r_nc_protofmly) == 0) &&
- (nconf->nc_semantics == rmap->r_nc_semantics) &&
- (rmap->r_maddr != NULL) && (rmap->r_maddr[0] != 0)) {
- na = uaddr2taddr(nconf, rmap->r_maddr);
-#ifdef ND_DEBUG
- fprintf(stderr, "\tRemote address is [%s].\n",
- rmap->r_maddr);
- if (!na)
- fprintf(stderr,
- "\tCouldn't resolve remote address!\n");
-#endif
- break;
- }
- }
- return (na);
-}
-
-/*
- * Quick check to see if rpcbind is up. Tries to connect over
- * local transport.
- */
-bool_t
-__rpcbind_is_up()
-{
- struct netconfig *nconf;
- struct sockaddr_un sun;
- void *localhandle;
- int sock;
-
- nconf = NULL;
- localhandle = setnetconfig();
- while ((nconf = getnetconfig(localhandle)) != NULL) {
- if (nconf->nc_protofmly != NULL &&
- strcmp(nconf->nc_protofmly, NC_LOOPBACK) == 0)
- break;
- }
- if (nconf == NULL)
- return (FALSE);
-
- endnetconfig(localhandle);
-
- memset(&sun, 0, sizeof sun);
- sock = socket(AF_LOCAL, SOCK_STREAM, 0);
- if (sock < 0)
- return (FALSE);
- sun.sun_family = AF_LOCAL;
- strncpy(sun.sun_path, _PATH_RPCBINDSOCK, sizeof(sun.sun_path));
-
- if (connect(sock, (struct sockaddr *)&sun, sizeof(sun)) < 0) {
- close(sock);
- return (FALSE);
- }
-
- close(sock);
- return (TRUE);
-}
-
-/*
- * An internal function which optimizes rpcb_getaddr function. It also
- * returns the client handle that it uses to contact the remote rpcbind.
- *
- * The algorithm used: If the transports is TCP or UDP, it first tries
- * version 2 (portmap), 4 and then 3 (svr4). This order should be
- * changed in the next OS release to 4, 2 and 3. We are assuming that by
- * that time, version 4 would be available on many machines on the network.
- * With this algorithm, we get performance as well as a plan for
- * obsoleting version 2.
- *
- * For all other transports, the algorithm remains as 4 and then 3.
- *
- * XXX: Due to some problems with t_connect(), we do not reuse the same client
- * handle for COTS cases and hence in these cases we do not return the
- * client handle. This code will change if t_connect() ever
- * starts working properly. Also look under clnt_vc.c.
- */
-struct netbuf *
-__rpcb_findaddr_timed(program, version, nconf, host, clpp, tp)
- rpcprog_t program;
- rpcvers_t version;
- const struct netconfig *nconf;
- const char *host;
- CLIENT **clpp;
- struct timeval *tp;
-{
- static bool_t check_rpcbind = TRUE;
- CLIENT *client = NULL;
- RPCB parms;
- enum clnt_stat clnt_st;
- char *ua = NULL;
- rpcvers_t vers;
- struct netbuf *address = NULL;
- rpcvers_t start_vers = RPCBVERS4;
- struct netbuf servaddr;
-
- /* parameter checking */
- if (nconf == NULL) {
- rpc_createerr.cf_stat = RPC_UNKNOWNPROTO;
- return (NULL);
- }
-
- parms.r_addr = NULL;
-
- /*
- * Use default total timeout if no timeout is specified.
- */
- if (tp == NULL)
- tp = &tottimeout;
-
- /* try rpcbind */
- /* Now the same transport is to be used to get the address */
- if (client && ((nconf->nc_semantics == NC_TPI_COTS_ORD) ||
- (nconf->nc_semantics == NC_TPI_COTS))) {
- /* A CLTS type of client - destroy it */
- CLNT_DESTROY(client);
- client = NULL;
- }
-
- if (client == NULL) {
- client = getclnthandle(host, nconf, &parms.r_addr);
- if (client == NULL) {
- goto error;
- }
- }
- if (parms.r_addr == NULL) {
- /*LINTED const castaway*/
- parms.r_addr = (char *) &nullstring[0];
- }
-
- /* First try from start_vers(4) and then version 3 (RPCBVERS) */
-
- CLNT_CONTROL(client, CLSET_RETRY_TIMEOUT, (char *) &rpcbrmttime);
- for (vers = start_vers; vers >= RPCBVERS; vers--) {
- /* Set the version */
- CLNT_CONTROL(client, CLSET_VERS, (char *)(void *)&vers);
- clnt_st = CLNT_CALL(client, (rpcproc_t)RPCBPROC_GETADDR,
- (xdrproc_t) xdr_rpcb, (char *)(void *)&parms,
- (xdrproc_t) xdr_wrapstring, (char *)(void *) &ua, *tp);
- if (clnt_st == RPC_SUCCESS) {
- if ((ua == NULL) || (ua[0] == 0)) {
- /* address unknown */
- rpc_createerr.cf_stat = RPC_PROGNOTREGISTERED;
- continue; /* try other versions */
- }
- address = uaddr2taddr(nconf, ua);
-#ifdef ND_DEBUG
- fprintf(stderr, "\tRemote address is [%s]\n", ua);
- if (!address)
- fprintf(stderr,
- "\tCouldn't resolve remote address!\n");
-#endif
- xdr_free((xdrproc_t)xdr_wrapstring,
- (char *)(void *)&ua);
-
- if (! address) {
- /* We don't know about your universal address */
- rpc_createerr.cf_stat = RPC_N2AXLATEFAILURE;
- goto error;
- }
- CLNT_CONTROL(client, CLGET_SVC_ADDR,
- (char *)(void *)&servaddr);
- __rpc_fixup_addr(address, &servaddr);
- goto done;
- } else if (clnt_st == RPC_PROGVERSMISMATCH) {
- struct rpc_err rpcerr;
- clnt_geterr(client, &rpcerr);
- if (rpcerr.re_vers.low > RPCBVERS4)
- goto error; /* a new version, can't handle */
- } else if (clnt_st != RPC_PROGUNAVAIL) {
- /* Cant handle this error */
- rpc_createerr.cf_stat = clnt_st;
- clnt_geterr(client, &rpc_createerr.cf_error);
- goto error;
- }
- }
- /* if rpcbind requests failed -> try portmapper version 2 */
-#ifdef PORTMAP
- /* Try version 2 for TCP or UDP */
- if (strcmp(nconf->nc_protofmly, NC_INET) == 0) {
- u_short port = 0;
- struct netbuf remote;
- rpcvers_t pmapvers = 2;
- struct pmap pmapparms;
-
- /*
- * Try UDP only - there are some portmappers out
- * there that use UDP only.
- */
- if (strcmp(nconf->nc_proto, NC_TCP) == 0) {
- struct netconfig *newnconf;
-
- if ((newnconf = getnetconfigent("udp")) == NULL) {
- rpc_createerr.cf_stat = RPC_UNKNOWNPROTO;
- return (NULL);
- }
- client = getclnthandle(host, newnconf, &parms.r_addr);
- freenetconfigent(newnconf);
- } else {
- client = getclnthandle(host, nconf, &parms.r_addr);
- }
- if (client == NULL)
- return (NULL);
-
- /*
- * Set version and retry timeout.
- */
- CLNT_CONTROL(client, CLSET_RETRY_TIMEOUT, (char *)&rpcbrmttime);
- CLNT_CONTROL(client, CLSET_VERS, (char *)&pmapvers);
-
- pmapparms.pm_prog = program;
- pmapparms.pm_vers = version;
- pmapparms.pm_prot = strcmp(nconf->nc_proto, NC_TCP) ?
- IPPROTO_UDP : IPPROTO_TCP;
- pmapparms.pm_port = 0; /* not needed */
- clnt_st = CLNT_CALL(client, (rpcproc_t)PMAPPROC_GETPORT,
- (xdrproc_t) xdr_pmap, (caddr_t)(void *)&pmapparms,
- (xdrproc_t) xdr_u_short, (caddr_t)(void *)&port,
- *tp);
- if (clnt_st != RPC_SUCCESS) {
- if ((clnt_st == RPC_PROGVERSMISMATCH) ||
- (clnt_st == RPC_PROGUNAVAIL))
- goto error; /* All portmap/rpcbind versions failed */
- rpc_createerr.cf_stat = RPC_PMAPFAILURE;
- clnt_geterr(client, &rpc_createerr.cf_error);
- goto error;
- } else if (port == 0) {
- address = NULL;
- rpc_createerr.cf_stat = RPC_PROGNOTREGISTERED;
- goto error;
- }
- port = htons(port);
- CLNT_CONTROL(client, CLGET_SVC_ADDR, (char *)&remote);
- if (((address = (struct netbuf *)
- malloc(sizeof (struct netbuf))) == NULL) ||
- ((address->buf = (char *)
- malloc(remote.len)) == NULL)) {
- rpc_createerr.cf_stat = RPC_SYSTEMERROR;
- clnt_geterr(client, &rpc_createerr.cf_error);
- if (address) {
- free(address);
- address = NULL;
- }
- goto error;
- }
- memcpy(address->buf, remote.buf, remote.len);
- memcpy(&((char *)address->buf)[sizeof (short)],
- (char *)(void *)&port, sizeof (short));
- address->len = address->maxlen = remote.len;
- goto done;
- }
-
-
- //try_rpcbind:
-#endif /* PORTMAP */
-
- if ((address == NULL) || (address->len == 0)) {
- rpc_createerr.cf_stat = RPC_PROGNOTREGISTERED;
- clnt_geterr(client, &rpc_createerr.cf_error);
- }
-
-error:
- if (client) {
- CLNT_DESTROY(client);
- client = NULL;
- }
-done:
- if (nconf->nc_semantics != NC_TPI_CLTS) {
- /* This client is the connectionless one */
- if (client) {
- CLNT_DESTROY(client);
- client = NULL;
- }
- }
- if (clpp) {
- *clpp = client;
- } else if (client) {
- CLNT_DESTROY(client);
- }
- if (parms.r_addr != NULL && parms.r_addr != nullstring)
- free(parms.r_addr);
- return (address);
-}
-
-
-/*
- * Find the mapped address for program, version.
- * Calls the rpcbind service remotely to do the lookup.
- * Uses the transport specified in nconf.
- * Returns FALSE (0) if no map exists, else returns 1.
- *
- * Assuming that the address is all properly allocated
- */
-int
-rpcb_getaddr(program, version, nconf, address, host)
- rpcprog_t program;
- rpcvers_t version;
- const struct netconfig *nconf;
- struct netbuf *address;
- const char *host;
-{
- struct netbuf *na;
-
- if ((na = __rpcb_findaddr_timed(program, version,
- (struct netconfig *) nconf, (char *) host,
- (CLIENT **) NULL, (struct timeval *) NULL)) == NULL)
- return (FALSE);
-
- if (na->len > address->maxlen) {
- /* Too long address */
- free(na->buf);
- free(na);
- rpc_createerr.cf_stat = RPC_FAILED;
- return (FALSE);
- }
- memcpy(address->buf, na->buf, (size_t)na->len);
- address->len = na->len;
- free(na->buf);
- free(na);
- return (TRUE);
-}
-
-/*
- * Get a copy of the current maps.
- * Calls the rpcbind service remotely to get the maps.
- *
- * It returns only a list of the services
- * It returns NULL on failure.
- */
-rpcblist *
-rpcb_getmaps(nconf, host)
- const struct netconfig *nconf;
- const char *host;
-{
- rpcblist_ptr head = NULL;
- CLIENT *client;
- enum clnt_stat clnt_st;
- rpcvers_t vers = 0;
-
- client = getclnthandle(host, nconf, NULL);
- if (client == NULL) {
- return (head);
- }
- clnt_st = CLNT_CALL(client, (rpcproc_t)RPCBPROC_DUMP,
- (xdrproc_t) xdr_void, NULL, (xdrproc_t) xdr_rpcblist_ptr,
- (char *)(void *)&head, tottimeout);
- if (clnt_st == RPC_SUCCESS)
- goto done;
-
- if ((clnt_st != RPC_PROGVERSMISMATCH) &&
- (clnt_st != RPC_PROGUNAVAIL)) {
- rpc_createerr.cf_stat = RPC_RPCBFAILURE;
- clnt_geterr(client, &rpc_createerr.cf_error);
- goto done;
- }
-
- /* fall back to earlier version */
- CLNT_CONTROL(client, CLGET_VERS, (char *)(void *)&vers);
- if (vers == RPCBVERS4) {
- vers = RPCBVERS;
- CLNT_CONTROL(client, CLSET_VERS, (char *)(void *)&vers);
- if (CLNT_CALL(client, (rpcproc_t)RPCBPROC_DUMP,
- (xdrproc_t) xdr_void, NULL, (xdrproc_t) xdr_rpcblist_ptr,
- (char *)(void *)&head, tottimeout) == RPC_SUCCESS)
- goto done;
- }
- rpc_createerr.cf_stat = RPC_RPCBFAILURE;
- clnt_geterr(client, &rpc_createerr.cf_error);
-
-done:
- CLNT_DESTROY(client);
- return (head);
-}
-
-/*
- * rpcbinder remote-call-service interface.
- * This routine is used to call the rpcbind remote call service
- * which will look up a service program in the address maps, and then
- * remotely call that routine with the given parameters. This allows
- * programs to do a lookup and call in one step.
-*/
-enum clnt_stat
-rpcb_rmtcall(nconf, host, prog, vers, proc, xdrargs, argsp,
- xdrres, resp, tout, addr_ptr)
- const struct netconfig *nconf; /* Netconfig structure */
- const char *host; /* Remote host name */
- rpcprog_t prog;
- rpcvers_t vers;
- rpcproc_t proc; /* Remote proc identifiers */
- xdrproc_t xdrargs, xdrres; /* XDR routines */
- caddr_t argsp, resp; /* Argument and Result */
- struct timeval tout; /* Timeout value for this call */
- const struct netbuf *addr_ptr; /* Preallocated netbuf address */
-{
- CLIENT *client;
- enum clnt_stat stat;
- struct r_rpcb_rmtcallargs a;
- struct r_rpcb_rmtcallres r;
- rpcvers_t rpcb_vers;
-
- stat = 0;
- client = getclnthandle(host, nconf, NULL);
- if (client == NULL) {
- return (RPC_FAILED);
- }
- /*LINTED const castaway*/
- CLNT_CONTROL(client, CLSET_RETRY_TIMEOUT, (char *)(void *)&rmttimeout);
- a.prog = prog;
- a.vers = vers;
- a.proc = proc;
- a.args.args_val = argsp;
- a.xdr_args = xdrargs;
- r.addr = NULL;
- r.results.results_val = resp;
- r.xdr_res = xdrres;
-
- for (rpcb_vers = RPCBVERS4; rpcb_vers >= RPCBVERS; rpcb_vers--) {
- CLNT_CONTROL(client, CLSET_VERS, (char *)(void *)&rpcb_vers);
- stat = CLNT_CALL(client, (rpcproc_t)RPCBPROC_CALLIT,
- (xdrproc_t) xdr_rpcb_rmtcallargs, (char *)(void *)&a,
- (xdrproc_t) xdr_rpcb_rmtcallres, (char *)(void *)&r, tout);
- if ((stat == RPC_SUCCESS) && (addr_ptr != NULL)) {
- struct netbuf *na;
- /*LINTED const castaway*/
- na = uaddr2taddr((struct netconfig *) nconf, r.addr);
- if (!na) {
- stat = RPC_N2AXLATEFAILURE;
- /*LINTED const castaway*/
- ((struct netbuf *) addr_ptr)->len = 0;
- goto error;
- }
- if (na->len > addr_ptr->maxlen) {
- /* Too long address */
- stat = RPC_FAILED; /* XXX A better error no */
- free(na->buf);
- free(na);
- /*LINTED const castaway*/
- ((struct netbuf *) addr_ptr)->len = 0;
- goto error;
- }
- memcpy(addr_ptr->buf, na->buf, (size_t)na->len);
- /*LINTED const castaway*/
- ((struct netbuf *)addr_ptr)->len = na->len;
- free(na->buf);
- free(na);
- break;
- } else if ((stat != RPC_PROGVERSMISMATCH) &&
- (stat != RPC_PROGUNAVAIL)) {
- goto error;
- }
- }
-error:
- CLNT_DESTROY(client);
- if (r.addr)
- xdr_free((xdrproc_t) xdr_wrapstring, (char *)(void *)&r.addr);
- return (stat);
-}
-
-/*
- * Gets the time on the remote host.
- * Returns 1 if succeeds else 0.
- */
-bool_t
-rpcb_gettime(host, timep)
- const char *host;
- time_t *timep;
-{
- CLIENT *client = NULL;
- void *handle;
- struct netconfig *nconf;
- rpcvers_t vers;
- enum clnt_stat st;
-
- if ((host == NULL) || (host[0] == 0)) {
- time(timep);
- return (TRUE);
- }
-
- if ((handle = __rpc_setconf("netpath")) == NULL) {
- rpc_createerr.cf_stat = RPC_UNKNOWNPROTO;
- return (FALSE);
- }
- rpc_createerr.cf_stat = RPC_SUCCESS;
- while (client == NULL) {
- if ((nconf = __rpc_getconf(handle)) == NULL) {
- if (rpc_createerr.cf_stat == RPC_SUCCESS)
- rpc_createerr.cf_stat = RPC_UNKNOWNPROTO;
- break;
- }
- client = getclnthandle(host, nconf, NULL);
- if (client)
- break;
- }
- __rpc_endconf(handle);
- if (client == (CLIENT *) NULL) {
- return (FALSE);
- }
-
- st = CLNT_CALL(client, (rpcproc_t)RPCBPROC_GETTIME,
- (xdrproc_t) xdr_void, NULL,
- (xdrproc_t) xdr_int, (char *)(void *)timep, tottimeout);
-
- if ((st == RPC_PROGVERSMISMATCH) || (st == RPC_PROGUNAVAIL)) {
- CLNT_CONTROL(client, CLGET_VERS, (char *)(void *)&vers);
- if (vers == RPCBVERS4) {
- /* fall back to earlier version */
- vers = RPCBVERS;
- CLNT_CONTROL(client, CLSET_VERS, (char *)(void *)&vers);
- st = CLNT_CALL(client, (rpcproc_t)RPCBPROC_GETTIME,
- (xdrproc_t) xdr_void, NULL,
- (xdrproc_t) xdr_int, (char *)(void *)timep,
- tottimeout);
- }
- }
- CLNT_DESTROY(client);
- return (st == RPC_SUCCESS? TRUE: FALSE);
-}
-
-/*
- * Converts taddr to universal address. This routine should never
- * really be called because local n2a libraries are always provided.
- */
-char *
-rpcb_taddr2uaddr(nconf, taddr)
- struct netconfig *nconf;
- struct netbuf *taddr;
-{
- CLIENT *client;
- char *uaddr = NULL;
-
-
- /* parameter checking */
- if (nconf == NULL) {
- rpc_createerr.cf_stat = RPC_UNKNOWNPROTO;
- return (NULL);
- }
- if (taddr == NULL) {
- rpc_createerr.cf_stat = RPC_UNKNOWNADDR;
- return (NULL);
- }
- client = local_rpcb();
- if (! client) {
- return (NULL);
- }
-
- CLNT_CALL(client, (rpcproc_t)RPCBPROC_TADDR2UADDR,
- (xdrproc_t) xdr_netbuf, (char *)(void *)taddr,
- (xdrproc_t) xdr_wrapstring, (char *)(void *)&uaddr, tottimeout);
- CLNT_DESTROY(client);
- return (uaddr);
-}
-
-/*
- * Converts universal address to netbuf. This routine should never
- * really be called because local n2a libraries are always provided.
- */
-struct netbuf *
-rpcb_uaddr2taddr(nconf, uaddr)
- struct netconfig *nconf;
- char *uaddr;
-{
- CLIENT *client;
- struct netbuf *taddr;
-
-
- /* parameter checking */
- if (nconf == NULL) {
- rpc_createerr.cf_stat = RPC_UNKNOWNPROTO;
- return (NULL);
- }
- if (uaddr == NULL) {
- rpc_createerr.cf_stat = RPC_UNKNOWNADDR;
- return (NULL);
- }
- client = local_rpcb();
- if (! client) {
- return (NULL);
- }
-
- taddr = (struct netbuf *)calloc(1, sizeof (struct netbuf));
- if (taddr == NULL) {
- CLNT_DESTROY(client);
- return (NULL);
- }
- if (CLNT_CALL(client, (rpcproc_t)RPCBPROC_UADDR2TADDR,
- (xdrproc_t) xdr_wrapstring, (char *)(void *)&uaddr,
- (xdrproc_t) xdr_netbuf, (char *)(void *)taddr,
- tottimeout) != RPC_SUCCESS) {
- free(taddr);
- taddr = NULL;
- }
- CLNT_DESTROY(client);
- return (taddr);
-}