summaryrefslogtreecommitdiffstats
path: root/lib/libc/rpc/rpcb_clnt.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/libc/rpc/rpcb_clnt.c')
-rw-r--r--lib/libc/rpc/rpcb_clnt.c1363
1 files changed, 0 insertions, 1363 deletions
diff --git a/lib/libc/rpc/rpcb_clnt.c b/lib/libc/rpc/rpcb_clnt.c
deleted file mode 100644
index afef806..0000000
--- a/lib/libc/rpc/rpcb_clnt.c
+++ /dev/null
@@ -1,1363 +0,0 @@
-/* $NetBSD: rpcb_clnt.c,v 1.6 2000/07/16 06:41:43 itojun Exp $ */
-
-/*
- * 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.
- */
-
-/* #ident "@(#)rpcb_clnt.c 1.27 94/04/24 SMI" */
-
-
-#if defined(LIBC_SCCS) && !defined(lint)
-static char sccsid[] = "@(#)rpcb_clnt.c 1.30 89/06/21 Copyr 1988 Sun Micro";
-#endif
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-/*
- * rpcb_clnt.c
- * interface to rpcbind rpc service.
- *
- * Copyright (C) 1988, Sun Microsystems, Inc.
- */
-
-#include "namespace.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 "un-namespace.h"
-
-#include "rpc_com.h"
-#include "mt_misc.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.
- */
-
-/*
- * 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)) {
- goto out;
- }
- 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) {
-out:
- if (ad_cache->ac_host)
- free(ad_cache->ac_host);
- if (ad_cache->ac_netid)
- free(ad_cache->ac_netid);
- if (ad_cache->ac_uaddr)
- free(ad_cache->ac_uaddr);
- if (ad_cache->ac_taddr)
- free(ad_cache->ac_taddr);
- free(ad_cache);
- 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;
- if (targaddr) {
- *targaddr = malloc(sizeof(sun.sun_path));
- if (*targaddr == NULL) {
- CLNT_DESTROY(client);
- return (NULL);
- }
- 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;
- 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.sun_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 *)(void *)&parms, (xdrproc_t) xdr_bool,
- (char *)(void *)&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.
- */
-static 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));
- sun.sun_len = SUN_LEN(&sun);
-
- if (_connect(sock, (struct sockaddr *)&sun, sun.sun_len) < 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
- /* 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;
- }
-#endif /* PORTMAP */
-
-try_rpcbind:
- /*
- * 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:
-
- /* 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;
- }
- }
-
-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);
-}
OpenPOWER on IntegriCloud