18360efbdSAlfred Perlstein /* $NetBSD: rpcb_clnt.c,v 1.6 2000/07/16 06:41:43 itojun Exp $ */ 28360efbdSAlfred Perlstein /* $FreeBSD$ */ 38360efbdSAlfred Perlstein 48360efbdSAlfred Perlstein /* 58360efbdSAlfred Perlstein * Sun RPC is a product of Sun Microsystems, Inc. and is provided for 68360efbdSAlfred Perlstein * unrestricted use provided that this legend is included on all tape 78360efbdSAlfred Perlstein * media and as a part of the software program in whole or part. Users 88360efbdSAlfred Perlstein * may copy or modify Sun RPC without charge, but are not authorized 98360efbdSAlfred Perlstein * to license or distribute it to anyone else except as part of a product or 108360efbdSAlfred Perlstein * program developed by the user. 118360efbdSAlfred Perlstein * 128360efbdSAlfred Perlstein * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE 138360efbdSAlfred Perlstein * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR 148360efbdSAlfred Perlstein * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. 158360efbdSAlfred Perlstein * 168360efbdSAlfred Perlstein * Sun RPC is provided with no support and without any obligation on the 178360efbdSAlfred Perlstein * part of Sun Microsystems, Inc. to assist in its use, correction, 188360efbdSAlfred Perlstein * modification or enhancement. 198360efbdSAlfred Perlstein * 208360efbdSAlfred Perlstein * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE 218360efbdSAlfred Perlstein * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC 228360efbdSAlfred Perlstein * OR ANY PART THEREOF. 238360efbdSAlfred Perlstein * 248360efbdSAlfred Perlstein * In no event will Sun Microsystems, Inc. be liable for any lost revenue 258360efbdSAlfred Perlstein * or profits or other special, indirect and consequential damages, even if 268360efbdSAlfred Perlstein * Sun has been advised of the possibility of such damages. 278360efbdSAlfred Perlstein * 288360efbdSAlfred Perlstein * Sun Microsystems, Inc. 298360efbdSAlfred Perlstein * 2550 Garcia Avenue 308360efbdSAlfred Perlstein * Mountain View, California 94043 318360efbdSAlfred Perlstein */ 328360efbdSAlfred Perlstein /* 338360efbdSAlfred Perlstein * Copyright (c) 1986-1991 by Sun Microsystems Inc. 348360efbdSAlfred Perlstein */ 358360efbdSAlfred Perlstein 368360efbdSAlfred Perlstein /* #ident "@(#)rpcb_clnt.c 1.27 94/04/24 SMI" */ 378360efbdSAlfred Perlstein 388360efbdSAlfred Perlstein 398360efbdSAlfred Perlstein #if 0 408360efbdSAlfred Perlstein #if !defined(lint) && defined(SCCSIDS) 418360efbdSAlfred Perlstein static char sccsid[] = "@(#)rpcb_clnt.c 1.30 89/06/21 Copyr 1988 Sun Micro"; 428360efbdSAlfred Perlstein #endif 438360efbdSAlfred Perlstein #endif 448360efbdSAlfred Perlstein 458360efbdSAlfred Perlstein /* 468360efbdSAlfred Perlstein * rpcb_clnt.c 478360efbdSAlfred Perlstein * interface to rpcbind rpc service. 488360efbdSAlfred Perlstein * 498360efbdSAlfred Perlstein * Copyright (C) 1988, Sun Microsystems, Inc. 508360efbdSAlfred Perlstein */ 518360efbdSAlfred Perlstein 528360efbdSAlfred Perlstein #include "namespace.h" 539f5afc13SIan Dowse #include "reentrant.h" 548360efbdSAlfred Perlstein #include <sys/types.h> 558360efbdSAlfred Perlstein #include <sys/socket.h> 568360efbdSAlfred Perlstein #include <sys/un.h> 578360efbdSAlfred Perlstein #include <sys/utsname.h> 588360efbdSAlfred Perlstein #include <rpc/rpc.h> 598360efbdSAlfred Perlstein #include <rpc/rpcb_prot.h> 608360efbdSAlfred Perlstein #include <rpc/nettype.h> 618360efbdSAlfred Perlstein #include <netconfig.h> 628360efbdSAlfred Perlstein #ifdef PORTMAP 638360efbdSAlfred Perlstein #include <netinet/in.h> /* FOR IPPROTO_TCP/UDP definitions */ 648360efbdSAlfred Perlstein #include <rpc/pmap_prot.h> 658360efbdSAlfred Perlstein #endif /* PORTMAP */ 668360efbdSAlfred Perlstein #include <stdio.h> 678360efbdSAlfred Perlstein #include <errno.h> 688360efbdSAlfred Perlstein #include <stdlib.h> 698360efbdSAlfred Perlstein #include <string.h> 708360efbdSAlfred Perlstein #include <unistd.h> 718360efbdSAlfred Perlstein #include <netdb.h> 728360efbdSAlfred Perlstein #include <syslog.h> 738360efbdSAlfred Perlstein #include "un-namespace.h" 748360efbdSAlfred Perlstein 758360efbdSAlfred Perlstein #include "rpc_com.h" 768360efbdSAlfred Perlstein 778360efbdSAlfred Perlstein static struct timeval tottimeout = { 60, 0 }; 788360efbdSAlfred Perlstein static const struct timeval rmttimeout = { 3, 0 }; 798360efbdSAlfred Perlstein 808360efbdSAlfred Perlstein extern bool_t xdr_wrapstring __P((XDR *, char **)); 818360efbdSAlfred Perlstein 828360efbdSAlfred Perlstein static const char nullstring[] = "\000"; 838360efbdSAlfred Perlstein 848360efbdSAlfred Perlstein #define CACHESIZE 6 858360efbdSAlfred Perlstein 868360efbdSAlfred Perlstein struct address_cache { 878360efbdSAlfred Perlstein char *ac_host; 888360efbdSAlfred Perlstein char *ac_netid; 898360efbdSAlfred Perlstein char *ac_uaddr; 908360efbdSAlfred Perlstein struct netbuf *ac_taddr; 918360efbdSAlfred Perlstein struct address_cache *ac_next; 928360efbdSAlfred Perlstein }; 938360efbdSAlfred Perlstein 948360efbdSAlfred Perlstein static struct address_cache *front; 958360efbdSAlfred Perlstein static int cachesize; 968360efbdSAlfred Perlstein 978360efbdSAlfred Perlstein #define CLCR_GET_RPCB_TIMEOUT 1 988360efbdSAlfred Perlstein #define CLCR_SET_RPCB_TIMEOUT 2 998360efbdSAlfred Perlstein 1008360efbdSAlfred Perlstein 1018360efbdSAlfred Perlstein extern int __rpc_lowvers; 1028360efbdSAlfred Perlstein 1038360efbdSAlfred Perlstein static struct address_cache *check_cache __P((const char *, const char *)); 1048360efbdSAlfred Perlstein static void delete_cache __P((struct netbuf *)); 1058360efbdSAlfred Perlstein static void add_cache __P((const char *, const char *, struct netbuf *, 1068360efbdSAlfred Perlstein char *)); 1078360efbdSAlfred Perlstein static CLIENT *getclnthandle __P((const char *, const struct netconfig *, 1088360efbdSAlfred Perlstein char **)); 1098360efbdSAlfred Perlstein static CLIENT *local_rpcb __P((void)); 1108360efbdSAlfred Perlstein static struct netbuf *got_entry __P((rpcb_entry_list_ptr, 1118360efbdSAlfred Perlstein const struct netconfig *)); 1128360efbdSAlfred Perlstein 1138360efbdSAlfred Perlstein /* 1148360efbdSAlfred Perlstein * This routine adjusts the timeout used for calls to the remote rpcbind. 1158360efbdSAlfred Perlstein * Also, this routine can be used to set the use of portmapper version 2 1168360efbdSAlfred Perlstein * only when doing rpc_broadcasts 1178360efbdSAlfred Perlstein * These are private routines that may not be provided in future releases. 1188360efbdSAlfred Perlstein */ 1198360efbdSAlfred Perlstein bool_t 1208360efbdSAlfred Perlstein __rpc_control(request, info) 1218360efbdSAlfred Perlstein int request; 1228360efbdSAlfred Perlstein void *info; 1238360efbdSAlfred Perlstein { 1248360efbdSAlfred Perlstein switch (request) { 1258360efbdSAlfred Perlstein case CLCR_GET_RPCB_TIMEOUT: 1268360efbdSAlfred Perlstein *(struct timeval *)info = tottimeout; 1278360efbdSAlfred Perlstein break; 1288360efbdSAlfred Perlstein case CLCR_SET_RPCB_TIMEOUT: 1298360efbdSAlfred Perlstein tottimeout = *(struct timeval *)info; 1308360efbdSAlfred Perlstein break; 1318360efbdSAlfred Perlstein case CLCR_SET_LOWVERS: 1328360efbdSAlfred Perlstein __rpc_lowvers = *(int *)info; 1338360efbdSAlfred Perlstein break; 1348360efbdSAlfred Perlstein case CLCR_GET_LOWVERS: 1358360efbdSAlfred Perlstein *(int *)info = __rpc_lowvers; 1368360efbdSAlfred Perlstein break; 1378360efbdSAlfred Perlstein default: 1388360efbdSAlfred Perlstein return (FALSE); 1398360efbdSAlfred Perlstein } 1408360efbdSAlfred Perlstein return (TRUE); 1418360efbdSAlfred Perlstein } 1428360efbdSAlfred Perlstein 1438360efbdSAlfred Perlstein /* 1448360efbdSAlfred Perlstein * It might seem that a reader/writer lock would be more reasonable here. 1458360efbdSAlfred Perlstein * However because getclnthandle(), the only user of the cache functions, 1468360efbdSAlfred Perlstein * may do a delete_cache() operation if a check_cache() fails to return an 1478360efbdSAlfred Perlstein * address useful to clnt_tli_create(), we may as well use a mutex. 1488360efbdSAlfred Perlstein */ 1498360efbdSAlfred Perlstein /* 1508360efbdSAlfred Perlstein * As it turns out, if the cache lock is *not* a reader/writer lock, we will 1518360efbdSAlfred Perlstein * block all clnt_create's if we are trying to connect to a host that's down, 1528360efbdSAlfred Perlstein * since the lock will be held all during that time. 1538360efbdSAlfred Perlstein */ 1548360efbdSAlfred Perlstein extern rwlock_t rpcbaddr_cache_lock; 1558360efbdSAlfred Perlstein 1568360efbdSAlfred Perlstein /* 1578360efbdSAlfred Perlstein * The routines check_cache(), add_cache(), delete_cache() manage the 1588360efbdSAlfred Perlstein * cache of rpcbind addresses for (host, netid). 1598360efbdSAlfred Perlstein */ 1608360efbdSAlfred Perlstein 1618360efbdSAlfred Perlstein static struct address_cache * 1628360efbdSAlfred Perlstein check_cache(host, netid) 1638360efbdSAlfred Perlstein const char *host, *netid; 1648360efbdSAlfred Perlstein { 1658360efbdSAlfred Perlstein struct address_cache *cptr; 1668360efbdSAlfred Perlstein 1678360efbdSAlfred Perlstein /* READ LOCK HELD ON ENTRY: rpcbaddr_cache_lock */ 1688360efbdSAlfred Perlstein 1698360efbdSAlfred Perlstein for (cptr = front; cptr != NULL; cptr = cptr->ac_next) { 1708360efbdSAlfred Perlstein if (!strcmp(cptr->ac_host, host) && 1718360efbdSAlfred Perlstein !strcmp(cptr->ac_netid, netid)) { 1728360efbdSAlfred Perlstein #ifdef ND_DEBUG 1738360efbdSAlfred Perlstein fprintf(stderr, "Found cache entry for %s: %s\n", 1748360efbdSAlfred Perlstein host, netid); 1758360efbdSAlfred Perlstein #endif 1768360efbdSAlfred Perlstein return (cptr); 1778360efbdSAlfred Perlstein } 1788360efbdSAlfred Perlstein } 1798360efbdSAlfred Perlstein return ((struct address_cache *) NULL); 1808360efbdSAlfred Perlstein } 1818360efbdSAlfred Perlstein 1828360efbdSAlfred Perlstein static void 1838360efbdSAlfred Perlstein delete_cache(addr) 1848360efbdSAlfred Perlstein struct netbuf *addr; 1858360efbdSAlfred Perlstein { 1868360efbdSAlfred Perlstein struct address_cache *cptr, *prevptr = NULL; 1878360efbdSAlfred Perlstein 1888360efbdSAlfred Perlstein /* WRITE LOCK HELD ON ENTRY: rpcbaddr_cache_lock */ 1898360efbdSAlfred Perlstein for (cptr = front; cptr != NULL; cptr = cptr->ac_next) { 1908360efbdSAlfred Perlstein if (!memcmp(cptr->ac_taddr->buf, addr->buf, addr->len)) { 1918360efbdSAlfred Perlstein free(cptr->ac_host); 1928360efbdSAlfred Perlstein free(cptr->ac_netid); 1938360efbdSAlfred Perlstein free(cptr->ac_taddr->buf); 1948360efbdSAlfred Perlstein free(cptr->ac_taddr); 1958360efbdSAlfred Perlstein if (cptr->ac_uaddr) 1968360efbdSAlfred Perlstein free(cptr->ac_uaddr); 1978360efbdSAlfred Perlstein if (prevptr) 1988360efbdSAlfred Perlstein prevptr->ac_next = cptr->ac_next; 1998360efbdSAlfred Perlstein else 2008360efbdSAlfred Perlstein front = cptr->ac_next; 2018360efbdSAlfred Perlstein free(cptr); 2028360efbdSAlfred Perlstein cachesize--; 2038360efbdSAlfred Perlstein break; 2048360efbdSAlfred Perlstein } 2058360efbdSAlfred Perlstein prevptr = cptr; 2068360efbdSAlfred Perlstein } 2078360efbdSAlfred Perlstein } 2088360efbdSAlfred Perlstein 2098360efbdSAlfred Perlstein static void 2108360efbdSAlfred Perlstein add_cache(host, netid, taddr, uaddr) 2118360efbdSAlfred Perlstein const char *host, *netid; 2128360efbdSAlfred Perlstein char *uaddr; 2138360efbdSAlfred Perlstein struct netbuf *taddr; 2148360efbdSAlfred Perlstein { 2158360efbdSAlfred Perlstein struct address_cache *ad_cache, *cptr, *prevptr; 2168360efbdSAlfred Perlstein 2178360efbdSAlfred Perlstein ad_cache = (struct address_cache *) 2188360efbdSAlfred Perlstein malloc(sizeof (struct address_cache)); 2198360efbdSAlfred Perlstein if (!ad_cache) { 2208360efbdSAlfred Perlstein return; 2218360efbdSAlfred Perlstein } 2228360efbdSAlfred Perlstein ad_cache->ac_host = strdup(host); 2238360efbdSAlfred Perlstein ad_cache->ac_netid = strdup(netid); 2248360efbdSAlfred Perlstein ad_cache->ac_uaddr = uaddr ? strdup(uaddr) : NULL; 2258360efbdSAlfred Perlstein ad_cache->ac_taddr = (struct netbuf *)malloc(sizeof (struct netbuf)); 2268360efbdSAlfred Perlstein if (!ad_cache->ac_host || !ad_cache->ac_netid || !ad_cache->ac_taddr || 2278360efbdSAlfred Perlstein (uaddr && !ad_cache->ac_uaddr)) { 2288360efbdSAlfred Perlstein return; 2298360efbdSAlfred Perlstein } 2308360efbdSAlfred Perlstein ad_cache->ac_taddr->len = ad_cache->ac_taddr->maxlen = taddr->len; 2318360efbdSAlfred Perlstein ad_cache->ac_taddr->buf = (char *) malloc(taddr->len); 2328360efbdSAlfred Perlstein if (ad_cache->ac_taddr->buf == NULL) { 2338360efbdSAlfred Perlstein return; 2348360efbdSAlfred Perlstein } 2358360efbdSAlfred Perlstein memcpy(ad_cache->ac_taddr->buf, taddr->buf, taddr->len); 2368360efbdSAlfred Perlstein #ifdef ND_DEBUG 2378360efbdSAlfred Perlstein fprintf(stderr, "Added to cache: %s : %s\n", host, netid); 2388360efbdSAlfred Perlstein #endif 2398360efbdSAlfred Perlstein 2408360efbdSAlfred Perlstein /* VARIABLES PROTECTED BY rpcbaddr_cache_lock: cptr */ 2418360efbdSAlfred Perlstein 2428360efbdSAlfred Perlstein rwlock_wrlock(&rpcbaddr_cache_lock); 2438360efbdSAlfred Perlstein if (cachesize < CACHESIZE) { 2448360efbdSAlfred Perlstein ad_cache->ac_next = front; 2458360efbdSAlfred Perlstein front = ad_cache; 2468360efbdSAlfred Perlstein cachesize++; 2478360efbdSAlfred Perlstein } else { 2488360efbdSAlfred Perlstein /* Free the last entry */ 2498360efbdSAlfred Perlstein cptr = front; 2508360efbdSAlfred Perlstein prevptr = NULL; 2518360efbdSAlfred Perlstein while (cptr->ac_next) { 2528360efbdSAlfred Perlstein prevptr = cptr; 2538360efbdSAlfred Perlstein cptr = cptr->ac_next; 2548360efbdSAlfred Perlstein } 2558360efbdSAlfred Perlstein 2568360efbdSAlfred Perlstein #ifdef ND_DEBUG 2578360efbdSAlfred Perlstein fprintf(stderr, "Deleted from cache: %s : %s\n", 2588360efbdSAlfred Perlstein cptr->ac_host, cptr->ac_netid); 2598360efbdSAlfred Perlstein #endif 2608360efbdSAlfred Perlstein free(cptr->ac_host); 2618360efbdSAlfred Perlstein free(cptr->ac_netid); 2628360efbdSAlfred Perlstein free(cptr->ac_taddr->buf); 2638360efbdSAlfred Perlstein free(cptr->ac_taddr); 2648360efbdSAlfred Perlstein if (cptr->ac_uaddr) 2658360efbdSAlfred Perlstein free(cptr->ac_uaddr); 2668360efbdSAlfred Perlstein 2678360efbdSAlfred Perlstein if (prevptr) { 2688360efbdSAlfred Perlstein prevptr->ac_next = NULL; 2698360efbdSAlfred Perlstein ad_cache->ac_next = front; 2708360efbdSAlfred Perlstein front = ad_cache; 2718360efbdSAlfred Perlstein } else { 2728360efbdSAlfred Perlstein front = ad_cache; 2738360efbdSAlfred Perlstein ad_cache->ac_next = NULL; 2748360efbdSAlfred Perlstein } 2758360efbdSAlfred Perlstein free(cptr); 2768360efbdSAlfred Perlstein } 2778360efbdSAlfred Perlstein rwlock_unlock(&rpcbaddr_cache_lock); 2788360efbdSAlfred Perlstein } 2798360efbdSAlfred Perlstein 2808360efbdSAlfred Perlstein /* 2818360efbdSAlfred Perlstein * This routine will return a client handle that is connected to the 282e73bb7f1SIan Dowse * rpcbind. If targaddr is non-NULL, the "universal address" of the 283e73bb7f1SIan Dowse * host will be stored in *targaddr; the caller is responsible for 284e73bb7f1SIan Dowse * freeing this string. 285e73bb7f1SIan Dowse * On error, returns NULL and free's everything. 2868360efbdSAlfred Perlstein */ 2878360efbdSAlfred Perlstein static CLIENT * 2888360efbdSAlfred Perlstein getclnthandle(host, nconf, targaddr) 2898360efbdSAlfred Perlstein const char *host; 2908360efbdSAlfred Perlstein const struct netconfig *nconf; 2918360efbdSAlfred Perlstein char **targaddr; 2928360efbdSAlfred Perlstein { 2938360efbdSAlfred Perlstein CLIENT *client; 2948360efbdSAlfred Perlstein struct netbuf *addr, taddr; 2958360efbdSAlfred Perlstein struct netbuf addr_to_delete; 2968360efbdSAlfred Perlstein struct __rpc_sockinfo si; 2978360efbdSAlfred Perlstein struct addrinfo hints, *res, *tres; 2988360efbdSAlfred Perlstein struct address_cache *ad_cache; 2998360efbdSAlfred Perlstein char *tmpaddr; 3008360efbdSAlfred Perlstein 3018360efbdSAlfred Perlstein /* VARIABLES PROTECTED BY rpcbaddr_cache_lock: ad_cache */ 3028360efbdSAlfred Perlstein 3038360efbdSAlfred Perlstein /* Get the address of the rpcbind. Check cache first */ 30452353da8SIan Dowse client = NULL; 3058360efbdSAlfred Perlstein addr_to_delete.len = 0; 3068360efbdSAlfred Perlstein rwlock_rdlock(&rpcbaddr_cache_lock); 307e4db1131SAlfred Perlstein ad_cache = NULL; 308e4db1131SAlfred Perlstein if (host != NULL) 3098360efbdSAlfred Perlstein ad_cache = check_cache(host, nconf->nc_netid); 3108360efbdSAlfred Perlstein if (ad_cache != NULL) { 3118360efbdSAlfred Perlstein addr = ad_cache->ac_taddr; 3128360efbdSAlfred Perlstein client = clnt_tli_create(RPC_ANYFD, nconf, addr, 3138360efbdSAlfred Perlstein (rpcprog_t)RPCBPROG, (rpcvers_t)RPCBVERS4, 0, 0); 3148360efbdSAlfred Perlstein if (client != NULL) { 3158360efbdSAlfred Perlstein if (targaddr) 316e73bb7f1SIan Dowse *targaddr = strdup(ad_cache->ac_uaddr); 3178360efbdSAlfred Perlstein rwlock_unlock(&rpcbaddr_cache_lock); 3188360efbdSAlfred Perlstein return (client); 3198360efbdSAlfred Perlstein } 3208360efbdSAlfred Perlstein addr_to_delete.len = addr->len; 3218360efbdSAlfred Perlstein addr_to_delete.buf = (char *)malloc(addr->len); 3228360efbdSAlfred Perlstein if (addr_to_delete.buf == NULL) { 3238360efbdSAlfred Perlstein addr_to_delete.len = 0; 3248360efbdSAlfred Perlstein } else { 3258360efbdSAlfred Perlstein memcpy(addr_to_delete.buf, addr->buf, addr->len); 3268360efbdSAlfred Perlstein } 3278360efbdSAlfred Perlstein } 3288360efbdSAlfred Perlstein rwlock_unlock(&rpcbaddr_cache_lock); 3298360efbdSAlfred Perlstein if (addr_to_delete.len != 0) { 3308360efbdSAlfred Perlstein /* 3318360efbdSAlfred Perlstein * Assume this may be due to cache data being 3328360efbdSAlfred Perlstein * outdated 3338360efbdSAlfred Perlstein */ 3348360efbdSAlfred Perlstein rwlock_wrlock(&rpcbaddr_cache_lock); 3358360efbdSAlfred Perlstein delete_cache(&addr_to_delete); 3368360efbdSAlfred Perlstein rwlock_unlock(&rpcbaddr_cache_lock); 3378360efbdSAlfred Perlstein free(addr_to_delete.buf); 3388360efbdSAlfred Perlstein } 3398360efbdSAlfred Perlstein if (!__rpc_nconf2sockinfo(nconf, &si)) { 3408360efbdSAlfred Perlstein rpc_createerr.cf_stat = RPC_UNKNOWNPROTO; 3418360efbdSAlfred Perlstein return NULL; 3428360efbdSAlfred Perlstein } 3438360efbdSAlfred Perlstein 3448360efbdSAlfred Perlstein memset(&hints, 0, sizeof hints); 3458360efbdSAlfred Perlstein hints.ai_family = si.si_af; 3468360efbdSAlfred Perlstein hints.ai_socktype = si.si_socktype; 3478360efbdSAlfred Perlstein hints.ai_protocol = si.si_proto; 3488360efbdSAlfred Perlstein 3498360efbdSAlfred Perlstein #ifdef CLNT_DEBUG 3508360efbdSAlfred Perlstein printf("trying netid %s family %d proto %d socktype %d\n", 3518360efbdSAlfred Perlstein nconf->nc_netid, si.si_af, si.si_proto, si.si_socktype); 3528360efbdSAlfred Perlstein #endif 3538360efbdSAlfred Perlstein 354e4db1131SAlfred Perlstein if (nconf->nc_protofmly != NULL && strcmp(nconf->nc_protofmly, NC_LOOPBACK) == 0) { 355e4db1131SAlfred Perlstein client = local_rpcb(); 356e4db1131SAlfred Perlstein if (! client) { 357e4db1131SAlfred Perlstein #ifdef ND_DEBUG 358e4db1131SAlfred Perlstein clnt_pcreateerror("rpcbind clnt interface"); 359e4db1131SAlfred Perlstein #endif 360e4db1131SAlfred Perlstein return (NULL); 361e4db1131SAlfred Perlstein } else { 362e4db1131SAlfred Perlstein struct sockaddr_un sun; 363e4db1131SAlfred Perlstein 364e4db1131SAlfred Perlstein *targaddr = malloc(sizeof(sun.sun_path)); 365e4db1131SAlfred Perlstein strncpy(*targaddr, _PATH_RPCBINDSOCK, 366e4db1131SAlfred Perlstein sizeof(sun.sun_path)); 367e4db1131SAlfred Perlstein return (client); 368e4db1131SAlfred Perlstein } 369e4db1131SAlfred Perlstein } else { 3708360efbdSAlfred Perlstein if (getaddrinfo(host, "sunrpc", &hints, &res) != 0) { 3718360efbdSAlfred Perlstein rpc_createerr.cf_stat = RPC_UNKNOWNHOST; 3728360efbdSAlfred Perlstein return NULL; 3738360efbdSAlfred Perlstein } 374e4db1131SAlfred Perlstein } 3758360efbdSAlfred Perlstein 3768360efbdSAlfred Perlstein for (tres = res; tres != NULL; tres = tres->ai_next) { 3778360efbdSAlfred Perlstein taddr.buf = tres->ai_addr; 3788360efbdSAlfred Perlstein taddr.len = taddr.maxlen = tres->ai_addrlen; 3798360efbdSAlfred Perlstein 3808360efbdSAlfred Perlstein #ifdef ND_DEBUG 3818360efbdSAlfred Perlstein { 3828360efbdSAlfred Perlstein char *ua; 3838360efbdSAlfred Perlstein 3848360efbdSAlfred Perlstein ua = taddr2uaddr(nconf, &taddr); 3858360efbdSAlfred Perlstein fprintf(stderr, "Got it [%s]\n", ua); 3868360efbdSAlfred Perlstein free(ua); 3878360efbdSAlfred Perlstein } 3888360efbdSAlfred Perlstein #endif 3898360efbdSAlfred Perlstein 3908360efbdSAlfred Perlstein #ifdef ND_DEBUG 3918360efbdSAlfred Perlstein { 3928360efbdSAlfred Perlstein int i; 3938360efbdSAlfred Perlstein 3948360efbdSAlfred Perlstein fprintf(stderr, "\tnetbuf len = %d, maxlen = %d\n", 3958360efbdSAlfred Perlstein taddr.len, taddr.maxlen); 3968360efbdSAlfred Perlstein fprintf(stderr, "\tAddress is "); 3978360efbdSAlfred Perlstein for (i = 0; i < taddr.len; i++) 3988360efbdSAlfred Perlstein fprintf(stderr, "%u.", ((char *)(taddr.buf))[i]); 3998360efbdSAlfred Perlstein fprintf(stderr, "\n"); 4008360efbdSAlfred Perlstein } 4018360efbdSAlfred Perlstein #endif 4028360efbdSAlfred Perlstein client = clnt_tli_create(RPC_ANYFD, nconf, &taddr, 4038360efbdSAlfred Perlstein (rpcprog_t)RPCBPROG, (rpcvers_t)RPCBVERS4, 0, 0); 4048360efbdSAlfred Perlstein #ifdef ND_DEBUG 4058360efbdSAlfred Perlstein if (! client) { 4068360efbdSAlfred Perlstein clnt_pcreateerror("rpcbind clnt interface"); 4078360efbdSAlfred Perlstein } 4088360efbdSAlfred Perlstein #endif 4098360efbdSAlfred Perlstein 4108360efbdSAlfred Perlstein if (client) { 4118360efbdSAlfred Perlstein tmpaddr = targaddr ? taddr2uaddr(nconf, &taddr) : NULL; 4128360efbdSAlfred Perlstein add_cache(host, nconf->nc_netid, &taddr, tmpaddr); 4138360efbdSAlfred Perlstein if (targaddr) 4148360efbdSAlfred Perlstein *targaddr = tmpaddr; 4158360efbdSAlfred Perlstein break; 4168360efbdSAlfred Perlstein } 4178360efbdSAlfred Perlstein } 418e4db1131SAlfred Perlstein if (res) 4198360efbdSAlfred Perlstein freeaddrinfo(res); 4208360efbdSAlfred Perlstein return (client); 4218360efbdSAlfred Perlstein } 4228360efbdSAlfred Perlstein 4238360efbdSAlfred Perlstein /* XXX */ 4248360efbdSAlfred Perlstein #define IN4_LOCALHOST_STRING "127.0.0.1" 4258360efbdSAlfred Perlstein #define IN6_LOCALHOST_STRING "::1" 4268360efbdSAlfred Perlstein 4278360efbdSAlfred Perlstein /* 4288360efbdSAlfred Perlstein * This routine will return a client handle that is connected to the local 4298360efbdSAlfred Perlstein * rpcbind. Returns NULL on error and free's everything. 4308360efbdSAlfred Perlstein */ 4318360efbdSAlfred Perlstein static CLIENT * 4328360efbdSAlfred Perlstein local_rpcb() 4338360efbdSAlfred Perlstein { 4348360efbdSAlfred Perlstein CLIENT *client; 4358360efbdSAlfred Perlstein static struct netconfig *loopnconf; 4368360efbdSAlfred Perlstein static char *hostname; 4378360efbdSAlfred Perlstein extern mutex_t loopnconf_lock; 4388360efbdSAlfred Perlstein int sock; 4398360efbdSAlfred Perlstein size_t tsize; 4408360efbdSAlfred Perlstein struct netbuf nbuf; 4418360efbdSAlfred Perlstein struct sockaddr_un sun; 4428360efbdSAlfred Perlstein 4438360efbdSAlfred Perlstein /* 4448360efbdSAlfred Perlstein * Try connecting to the local rpcbind through a local socket 4458360efbdSAlfred Perlstein * first. If this doesn't work, try all transports defined in 4468360efbdSAlfred Perlstein * the netconfig file. 4478360efbdSAlfred Perlstein */ 4488360efbdSAlfred Perlstein memset(&sun, 0, sizeof sun); 4498360efbdSAlfred Perlstein sock = _socket(AF_LOCAL, SOCK_STREAM, 0); 4508360efbdSAlfred Perlstein if (sock < 0) 4518360efbdSAlfred Perlstein goto try_nconf; 4528360efbdSAlfred Perlstein sun.sun_family = AF_LOCAL; 4538360efbdSAlfred Perlstein strcpy(sun.sun_path, _PATH_RPCBINDSOCK); 4548360efbdSAlfred Perlstein nbuf.len = sun.sun_len = SUN_LEN(&sun); 4558360efbdSAlfred Perlstein nbuf.maxlen = sizeof (struct sockaddr_un); 4568360efbdSAlfred Perlstein nbuf.buf = &sun; 4578360efbdSAlfred Perlstein 4588360efbdSAlfred Perlstein tsize = __rpc_get_t_size(AF_LOCAL, 0, 0); 4598360efbdSAlfred Perlstein client = clnt_vc_create(sock, &nbuf, (rpcprog_t)RPCBPROG, 4608360efbdSAlfred Perlstein (rpcvers_t)RPCBVERS, tsize, tsize); 4618360efbdSAlfred Perlstein 4626112fceeSIan Dowse if (client != NULL) { 4636112fceeSIan Dowse /* Mark the socket to be closed in destructor */ 4646112fceeSIan Dowse (void) CLNT_CONTROL(client, CLSET_FD_CLOSE, NULL); 4658360efbdSAlfred Perlstein return client; 4666112fceeSIan Dowse } 4676112fceeSIan Dowse 4686112fceeSIan Dowse /* Nobody needs this socket anymore; free the descriptor. */ 4696112fceeSIan Dowse _close(sock); 4708360efbdSAlfred Perlstein 4718360efbdSAlfred Perlstein try_nconf: 4728360efbdSAlfred Perlstein 4738360efbdSAlfred Perlstein /* VARIABLES PROTECTED BY loopnconf_lock: loopnconf */ 4748360efbdSAlfred Perlstein mutex_lock(&loopnconf_lock); 4758360efbdSAlfred Perlstein if (loopnconf == NULL) { 4768360efbdSAlfred Perlstein struct netconfig *nconf, *tmpnconf = NULL; 4778360efbdSAlfred Perlstein void *nc_handle; 4788360efbdSAlfred Perlstein int fd; 4798360efbdSAlfred Perlstein 4808360efbdSAlfred Perlstein nc_handle = setnetconfig(); 4818360efbdSAlfred Perlstein if (nc_handle == NULL) { 4828360efbdSAlfred Perlstein /* fails to open netconfig file */ 4838360efbdSAlfred Perlstein syslog (LOG_ERR, "rpc: failed to open " NETCONFIG); 4848360efbdSAlfred Perlstein rpc_createerr.cf_stat = RPC_UNKNOWNPROTO; 4858360efbdSAlfred Perlstein mutex_unlock(&loopnconf_lock); 4868360efbdSAlfred Perlstein return (NULL); 4878360efbdSAlfred Perlstein } 4888360efbdSAlfred Perlstein while ((nconf = getnetconfig(nc_handle)) != NULL) { 4898360efbdSAlfred Perlstein #ifdef INET6 4908360efbdSAlfred Perlstein if ((strcmp(nconf->nc_protofmly, NC_INET6) == 0 || 4918360efbdSAlfred Perlstein #else 4928360efbdSAlfred Perlstein if (( 4938360efbdSAlfred Perlstein #endif 4948360efbdSAlfred Perlstein strcmp(nconf->nc_protofmly, NC_INET) == 0) && 4958360efbdSAlfred Perlstein (nconf->nc_semantics == NC_TPI_COTS || 4968360efbdSAlfred Perlstein nconf->nc_semantics == NC_TPI_COTS_ORD)) { 4978360efbdSAlfred Perlstein fd = __rpc_nconf2fd(nconf); 4988360efbdSAlfred Perlstein /* 4998360efbdSAlfred Perlstein * Can't create a socket, assume that 5008360efbdSAlfred Perlstein * this family isn't configured in the kernel. 5018360efbdSAlfred Perlstein */ 5028360efbdSAlfred Perlstein if (fd < 0) 5038360efbdSAlfred Perlstein continue; 5048360efbdSAlfred Perlstein _close(fd); 5058360efbdSAlfred Perlstein tmpnconf = nconf; 5068360efbdSAlfred Perlstein if (!strcmp(nconf->nc_protofmly, NC_INET)) 5078360efbdSAlfred Perlstein hostname = IN4_LOCALHOST_STRING; 5088360efbdSAlfred Perlstein else 5098360efbdSAlfred Perlstein hostname = IN6_LOCALHOST_STRING; 5108360efbdSAlfred Perlstein } 5118360efbdSAlfred Perlstein } 5128360efbdSAlfred Perlstein if (tmpnconf == NULL) { 5138360efbdSAlfred Perlstein rpc_createerr.cf_stat = RPC_UNKNOWNPROTO; 5148360efbdSAlfred Perlstein mutex_unlock(&loopnconf_lock); 5158360efbdSAlfred Perlstein return (NULL); 5168360efbdSAlfred Perlstein } 5178360efbdSAlfred Perlstein loopnconf = getnetconfigent(tmpnconf->nc_netid); 5188360efbdSAlfred Perlstein /* loopnconf is never freed */ 5198360efbdSAlfred Perlstein endnetconfig(nc_handle); 5208360efbdSAlfred Perlstein } 5218360efbdSAlfred Perlstein mutex_unlock(&loopnconf_lock); 5228360efbdSAlfred Perlstein client = getclnthandle(hostname, loopnconf, NULL); 5238360efbdSAlfred Perlstein return (client); 5248360efbdSAlfred Perlstein } 5258360efbdSAlfred Perlstein 5268360efbdSAlfred Perlstein /* 5278360efbdSAlfred Perlstein * Set a mapping between program, version and address. 5288360efbdSAlfred Perlstein * Calls the rpcbind service to do the mapping. 5298360efbdSAlfred Perlstein */ 5308360efbdSAlfred Perlstein bool_t 5318360efbdSAlfred Perlstein rpcb_set(program, version, nconf, address) 5328360efbdSAlfred Perlstein rpcprog_t program; 5338360efbdSAlfred Perlstein rpcvers_t version; 5348360efbdSAlfred Perlstein const struct netconfig *nconf; /* Network structure of transport */ 5358360efbdSAlfred Perlstein const struct netbuf *address; /* Services netconfig address */ 5368360efbdSAlfred Perlstein { 5378360efbdSAlfred Perlstein CLIENT *client; 5388360efbdSAlfred Perlstein bool_t rslt = FALSE; 5398360efbdSAlfred Perlstein RPCB parms; 5408360efbdSAlfred Perlstein char uidbuf[32]; 5418360efbdSAlfred Perlstein 5428360efbdSAlfred Perlstein /* parameter checking */ 5438360efbdSAlfred Perlstein if (nconf == NULL) { 5448360efbdSAlfred Perlstein rpc_createerr.cf_stat = RPC_UNKNOWNPROTO; 5458360efbdSAlfred Perlstein return (FALSE); 5468360efbdSAlfred Perlstein } 5478360efbdSAlfred Perlstein if (address == NULL) { 5488360efbdSAlfred Perlstein rpc_createerr.cf_stat = RPC_UNKNOWNADDR; 5498360efbdSAlfred Perlstein return (FALSE); 5508360efbdSAlfred Perlstein } 5518360efbdSAlfred Perlstein client = local_rpcb(); 5528360efbdSAlfred Perlstein if (! client) { 5538360efbdSAlfred Perlstein return (FALSE); 5548360efbdSAlfred Perlstein } 5558360efbdSAlfred Perlstein 5568360efbdSAlfred Perlstein /* convert to universal */ 5578360efbdSAlfred Perlstein /*LINTED const castaway*/ 5588360efbdSAlfred Perlstein parms.r_addr = taddr2uaddr((struct netconfig *) nconf, 5598360efbdSAlfred Perlstein (struct netbuf *)address); 5608360efbdSAlfred Perlstein if (!parms.r_addr) { 5616112fceeSIan Dowse CLNT_DESTROY(client); 5628360efbdSAlfred Perlstein rpc_createerr.cf_stat = RPC_N2AXLATEFAILURE; 5638360efbdSAlfred Perlstein return (FALSE); /* no universal address */ 5648360efbdSAlfred Perlstein } 5658360efbdSAlfred Perlstein parms.r_prog = program; 5668360efbdSAlfred Perlstein parms.r_vers = version; 5678360efbdSAlfred Perlstein parms.r_netid = nconf->nc_netid; 5688360efbdSAlfred Perlstein /* 5698360efbdSAlfred Perlstein * Though uid is not being used directly, we still send it for 5708360efbdSAlfred Perlstein * completeness. For non-unix platforms, perhaps some other 5718360efbdSAlfred Perlstein * string or an empty string can be sent. 5728360efbdSAlfred Perlstein */ 5738360efbdSAlfred Perlstein (void) snprintf(uidbuf, sizeof uidbuf, "%d", geteuid()); 5748360efbdSAlfred Perlstein parms.r_owner = uidbuf; 5758360efbdSAlfred Perlstein 5768360efbdSAlfred Perlstein CLNT_CALL(client, (rpcproc_t)RPCBPROC_SET, (xdrproc_t) xdr_rpcb, 5778360efbdSAlfred Perlstein (char *)(void *)&parms, (xdrproc_t) xdr_bool, 5788360efbdSAlfred Perlstein (char *)(void *)&rslt, tottimeout); 5798360efbdSAlfred Perlstein 5808360efbdSAlfred Perlstein CLNT_DESTROY(client); 5818360efbdSAlfred Perlstein free(parms.r_addr); 5828360efbdSAlfred Perlstein return (rslt); 5838360efbdSAlfred Perlstein } 5848360efbdSAlfred Perlstein 5858360efbdSAlfred Perlstein /* 5868360efbdSAlfred Perlstein * Remove the mapping between program, version and netbuf address. 5878360efbdSAlfred Perlstein * Calls the rpcbind service to do the un-mapping. 5888360efbdSAlfred Perlstein * If netbuf is NULL, unset for all the transports, otherwise unset 5898360efbdSAlfred Perlstein * only for the given transport. 5908360efbdSAlfred Perlstein */ 5918360efbdSAlfred Perlstein bool_t 5928360efbdSAlfred Perlstein rpcb_unset(program, version, nconf) 5938360efbdSAlfred Perlstein rpcprog_t program; 5948360efbdSAlfred Perlstein rpcvers_t version; 5958360efbdSAlfred Perlstein const struct netconfig *nconf; 5968360efbdSAlfred Perlstein { 5978360efbdSAlfred Perlstein CLIENT *client; 5988360efbdSAlfred Perlstein bool_t rslt = FALSE; 5998360efbdSAlfred Perlstein RPCB parms; 6008360efbdSAlfred Perlstein char uidbuf[32]; 6018360efbdSAlfred Perlstein 6028360efbdSAlfred Perlstein client = local_rpcb(); 6038360efbdSAlfred Perlstein if (! client) { 6048360efbdSAlfred Perlstein return (FALSE); 6058360efbdSAlfred Perlstein } 6068360efbdSAlfred Perlstein 6078360efbdSAlfred Perlstein parms.r_prog = program; 6088360efbdSAlfred Perlstein parms.r_vers = version; 6098360efbdSAlfred Perlstein if (nconf) 6108360efbdSAlfred Perlstein parms.r_netid = nconf->nc_netid; 6118360efbdSAlfred Perlstein else { 6128360efbdSAlfred Perlstein /*LINTED const castaway*/ 6138360efbdSAlfred Perlstein parms.r_netid = (char *) &nullstring[0]; /* unsets all */ 6148360efbdSAlfred Perlstein } 6158360efbdSAlfred Perlstein /*LINTED const castaway*/ 6168360efbdSAlfred Perlstein parms.r_addr = (char *) &nullstring[0]; 6178360efbdSAlfred Perlstein (void) snprintf(uidbuf, sizeof uidbuf, "%d", geteuid()); 6188360efbdSAlfred Perlstein parms.r_owner = uidbuf; 6198360efbdSAlfred Perlstein 6208360efbdSAlfred Perlstein CLNT_CALL(client, (rpcproc_t)RPCBPROC_UNSET, (xdrproc_t) xdr_rpcb, 6218360efbdSAlfred Perlstein (char *)(void *)&parms, (xdrproc_t) xdr_bool, 6228360efbdSAlfred Perlstein (char *)(void *)&rslt, tottimeout); 6238360efbdSAlfred Perlstein 6248360efbdSAlfred Perlstein CLNT_DESTROY(client); 6258360efbdSAlfred Perlstein return (rslt); 6268360efbdSAlfred Perlstein } 6278360efbdSAlfred Perlstein 6288360efbdSAlfred Perlstein /* 6298360efbdSAlfred Perlstein * From the merged list, find the appropriate entry 6308360efbdSAlfred Perlstein */ 6318360efbdSAlfred Perlstein static struct netbuf * 6328360efbdSAlfred Perlstein got_entry(relp, nconf) 6338360efbdSAlfred Perlstein rpcb_entry_list_ptr relp; 6348360efbdSAlfred Perlstein const struct netconfig *nconf; 6358360efbdSAlfred Perlstein { 6368360efbdSAlfred Perlstein struct netbuf *na = NULL; 6378360efbdSAlfred Perlstein rpcb_entry_list_ptr sp; 6388360efbdSAlfred Perlstein rpcb_entry *rmap; 6398360efbdSAlfred Perlstein 6408360efbdSAlfred Perlstein for (sp = relp; sp != NULL; sp = sp->rpcb_entry_next) { 6418360efbdSAlfred Perlstein rmap = &sp->rpcb_entry_map; 6428360efbdSAlfred Perlstein if ((strcmp(nconf->nc_proto, rmap->r_nc_proto) == 0) && 6438360efbdSAlfred Perlstein (strcmp(nconf->nc_protofmly, rmap->r_nc_protofmly) == 0) && 6448360efbdSAlfred Perlstein (nconf->nc_semantics == rmap->r_nc_semantics) && 6458360efbdSAlfred Perlstein (rmap->r_maddr != NULL) && (rmap->r_maddr[0] != NULL)) { 6468360efbdSAlfred Perlstein na = uaddr2taddr(nconf, rmap->r_maddr); 6478360efbdSAlfred Perlstein #ifdef ND_DEBUG 6488360efbdSAlfred Perlstein fprintf(stderr, "\tRemote address is [%s].\n", 6498360efbdSAlfred Perlstein rmap->r_maddr); 6508360efbdSAlfred Perlstein if (!na) 6518360efbdSAlfred Perlstein fprintf(stderr, 6528360efbdSAlfred Perlstein "\tCouldn't resolve remote address!\n"); 6538360efbdSAlfred Perlstein #endif 6548360efbdSAlfred Perlstein break; 6558360efbdSAlfred Perlstein } 6568360efbdSAlfred Perlstein } 6578360efbdSAlfred Perlstein return (na); 6588360efbdSAlfred Perlstein } 6598360efbdSAlfred Perlstein 6608360efbdSAlfred Perlstein /* 6618360efbdSAlfred Perlstein * An internal function which optimizes rpcb_getaddr function. It also 6628360efbdSAlfred Perlstein * returns the client handle that it uses to contact the remote rpcbind. 6638360efbdSAlfred Perlstein * 6648360efbdSAlfred Perlstein * The algorithm used: If the transports is TCP or UDP, it first tries 6658360efbdSAlfred Perlstein * version 2 (portmap), 4 and then 3 (svr4). This order should be 6668360efbdSAlfred Perlstein * changed in the next OS release to 4, 2 and 3. We are assuming that by 6678360efbdSAlfred Perlstein * that time, version 4 would be available on many machines on the network. 6688360efbdSAlfred Perlstein * With this algorithm, we get performance as well as a plan for 6698360efbdSAlfred Perlstein * obsoleting version 2. 6708360efbdSAlfred Perlstein * 6718360efbdSAlfred Perlstein * For all other transports, the algorithm remains as 4 and then 3. 6728360efbdSAlfred Perlstein * 6738360efbdSAlfred Perlstein * XXX: Due to some problems with t_connect(), we do not reuse the same client 6748360efbdSAlfred Perlstein * handle for COTS cases and hence in these cases we do not return the 6758360efbdSAlfred Perlstein * client handle. This code will change if t_connect() ever 6768360efbdSAlfred Perlstein * starts working properly. Also look under clnt_vc.c. 6778360efbdSAlfred Perlstein */ 6788360efbdSAlfred Perlstein struct netbuf * 6798360efbdSAlfred Perlstein __rpcb_findaddr(program, version, nconf, host, clpp) 6808360efbdSAlfred Perlstein rpcprog_t program; 6818360efbdSAlfred Perlstein rpcvers_t version; 6828360efbdSAlfred Perlstein const struct netconfig *nconf; 6838360efbdSAlfred Perlstein const char *host; 6848360efbdSAlfred Perlstein CLIENT **clpp; 6858360efbdSAlfred Perlstein { 6868360efbdSAlfred Perlstein CLIENT *client = NULL; 6878360efbdSAlfred Perlstein RPCB parms; 6888360efbdSAlfred Perlstein enum clnt_stat clnt_st; 6898360efbdSAlfred Perlstein char *ua = NULL; 6908360efbdSAlfred Perlstein rpcvers_t vers; 6918360efbdSAlfred Perlstein struct netbuf *address = NULL; 6928360efbdSAlfred Perlstein rpcvers_t start_vers = RPCBVERS4; 6938360efbdSAlfred Perlstein struct netbuf servaddr; 6948360efbdSAlfred Perlstein 6958360efbdSAlfred Perlstein /* parameter checking */ 6968360efbdSAlfred Perlstein if (nconf == NULL) { 6978360efbdSAlfred Perlstein rpc_createerr.cf_stat = RPC_UNKNOWNPROTO; 6988360efbdSAlfred Perlstein return (NULL); 6998360efbdSAlfred Perlstein } 7008360efbdSAlfred Perlstein 7018360efbdSAlfred Perlstein parms.r_addr = NULL; 7028360efbdSAlfred Perlstein 7038360efbdSAlfred Perlstein #ifdef PORTMAP 7048360efbdSAlfred Perlstein /* Try version 2 for TCP or UDP */ 7058360efbdSAlfred Perlstein if (strcmp(nconf->nc_protofmly, NC_INET) == 0) { 7068360efbdSAlfred Perlstein u_short port = 0; 7078360efbdSAlfred Perlstein struct netbuf remote; 7088360efbdSAlfred Perlstein rpcvers_t pmapvers = 2; 7098360efbdSAlfred Perlstein struct pmap pmapparms; 7108360efbdSAlfred Perlstein 7118360efbdSAlfred Perlstein /* 7128360efbdSAlfred Perlstein * Try UDP only - there are some portmappers out 7138360efbdSAlfred Perlstein * there that use UDP only. 7148360efbdSAlfred Perlstein */ 7158360efbdSAlfred Perlstein if (strcmp(nconf->nc_proto, NC_TCP) == 0) { 7168360efbdSAlfred Perlstein struct netconfig *newnconf; 7178360efbdSAlfred Perlstein 7188360efbdSAlfred Perlstein if ((newnconf = getnetconfigent("udp")) == NULL) { 7198360efbdSAlfred Perlstein rpc_createerr.cf_stat = RPC_UNKNOWNPROTO; 7208360efbdSAlfred Perlstein return (NULL); 7218360efbdSAlfred Perlstein } 7228360efbdSAlfred Perlstein client = getclnthandle(host, newnconf, &parms.r_addr); 7238360efbdSAlfred Perlstein freenetconfigent(newnconf); 7248360efbdSAlfred Perlstein } else { 7258360efbdSAlfred Perlstein client = getclnthandle(host, nconf, &parms.r_addr); 7268360efbdSAlfred Perlstein } 7278360efbdSAlfred Perlstein if (client == NULL) { 7288360efbdSAlfred Perlstein return (NULL); 7298360efbdSAlfred Perlstein } 7308360efbdSAlfred Perlstein 7318360efbdSAlfred Perlstein /* Set the version */ 7328360efbdSAlfred Perlstein CLNT_CONTROL(client, CLSET_VERS, (char *)(void *)&pmapvers); 7338360efbdSAlfred Perlstein pmapparms.pm_prog = program; 7348360efbdSAlfred Perlstein pmapparms.pm_vers = version; 7358360efbdSAlfred Perlstein pmapparms.pm_prot = strcmp(nconf->nc_proto, NC_TCP) ? 7368360efbdSAlfred Perlstein IPPROTO_UDP : IPPROTO_TCP; 7378360efbdSAlfred Perlstein pmapparms.pm_port = 0; /* not needed */ 7388360efbdSAlfred Perlstein clnt_st = CLNT_CALL(client, (rpcproc_t)PMAPPROC_GETPORT, 7398360efbdSAlfred Perlstein (xdrproc_t) xdr_pmap, (caddr_t)(void *)&pmapparms, 7408360efbdSAlfred Perlstein (xdrproc_t) xdr_u_short, (caddr_t)(void *)&port, 7418360efbdSAlfred Perlstein tottimeout); 7428360efbdSAlfred Perlstein if (clnt_st != RPC_SUCCESS) { 7438360efbdSAlfred Perlstein if ((clnt_st == RPC_PROGVERSMISMATCH) || 7448360efbdSAlfred Perlstein (clnt_st == RPC_PROGUNAVAIL)) 7458360efbdSAlfred Perlstein goto try_rpcbind; /* Try different versions */ 7468360efbdSAlfred Perlstein rpc_createerr.cf_stat = RPC_PMAPFAILURE; 7478360efbdSAlfred Perlstein clnt_geterr(client, &rpc_createerr.cf_error); 7488360efbdSAlfred Perlstein goto error; 7498360efbdSAlfred Perlstein } else if (port == 0) { 7508360efbdSAlfred Perlstein address = NULL; 7518360efbdSAlfred Perlstein rpc_createerr.cf_stat = RPC_PROGNOTREGISTERED; 7528360efbdSAlfred Perlstein goto error; 7538360efbdSAlfred Perlstein } 7548360efbdSAlfred Perlstein port = htons(port); 7558360efbdSAlfred Perlstein CLNT_CONTROL(client, CLGET_SVC_ADDR, (char *)(void *)&remote); 7568360efbdSAlfred Perlstein if (((address = (struct netbuf *) 7578360efbdSAlfred Perlstein malloc(sizeof (struct netbuf))) == NULL) || 7588360efbdSAlfred Perlstein ((address->buf = (char *) 7598360efbdSAlfred Perlstein malloc(remote.len)) == NULL)) { 7608360efbdSAlfred Perlstein rpc_createerr.cf_stat = RPC_SYSTEMERROR; 7618360efbdSAlfred Perlstein clnt_geterr(client, &rpc_createerr.cf_error); 7628360efbdSAlfred Perlstein if (address) { 7638360efbdSAlfred Perlstein free(address); 7648360efbdSAlfred Perlstein address = NULL; 7658360efbdSAlfred Perlstein } 7668360efbdSAlfred Perlstein goto error; 7678360efbdSAlfred Perlstein } 7688360efbdSAlfred Perlstein memcpy(address->buf, remote.buf, remote.len); 7698360efbdSAlfred Perlstein memcpy(&((char *)address->buf)[sizeof (short)], 7708360efbdSAlfred Perlstein (char *)(void *)&port, sizeof (short)); 7718360efbdSAlfred Perlstein address->len = address->maxlen = remote.len; 7728360efbdSAlfred Perlstein goto done; 7738360efbdSAlfred Perlstein } 7748360efbdSAlfred Perlstein #endif /* PORTMAP */ 7758360efbdSAlfred Perlstein 7768360efbdSAlfred Perlstein try_rpcbind: 7778360efbdSAlfred Perlstein /* 7788360efbdSAlfred Perlstein * Now we try version 4 and then 3. 7798360efbdSAlfred Perlstein * We also send the remote system the address we used to 7808360efbdSAlfred Perlstein * contact it in case it can help to connect back with us 7818360efbdSAlfred Perlstein */ 7828360efbdSAlfred Perlstein parms.r_prog = program; 7838360efbdSAlfred Perlstein parms.r_vers = version; 7848360efbdSAlfred Perlstein /*LINTED const castaway*/ 7858360efbdSAlfred Perlstein parms.r_owner = (char *) &nullstring[0]; /* not needed; */ 7868360efbdSAlfred Perlstein /* just for xdring */ 7878360efbdSAlfred Perlstein parms.r_netid = nconf->nc_netid; /* not really needed */ 7888360efbdSAlfred Perlstein 7898360efbdSAlfred Perlstein /* 7908360efbdSAlfred Perlstein * If a COTS transport is being used, try getting address via CLTS 7918360efbdSAlfred Perlstein * transport. This works only with version 4. 7928360efbdSAlfred Perlstein * NOTE: This is being done for all transports EXCEPT LOOPBACK 7938360efbdSAlfred Perlstein * because with loopback the cost to go to a COTS is same as 7948360efbdSAlfred Perlstein * the cost to go through CLTS, plus you get the advantage of 7958360efbdSAlfred Perlstein * finding out immediately if the local rpcbind process is dead. 7968360efbdSAlfred Perlstein */ 7978360efbdSAlfred Perlstein #if 1 7988360efbdSAlfred Perlstein if ((nconf->nc_semantics == NC_TPI_COTS_ORD || 7998360efbdSAlfred Perlstein nconf->nc_semantics == NC_TPI_COTS) && 8008360efbdSAlfred Perlstein (strcmp(nconf->nc_protofmly, NC_LOOPBACK) != 0)) { 8018360efbdSAlfred Perlstein #else 8028360efbdSAlfred Perlstein if (client != NULL) { 8038360efbdSAlfred Perlstein CLNT_DESTROY(client); 8048360efbdSAlfred Perlstein client = NULL; 8058360efbdSAlfred Perlstein } 8068360efbdSAlfred Perlstein if (nconf->nc_semantics == NC_TPI_CLTS) { 8078360efbdSAlfred Perlstein #endif 8088360efbdSAlfred Perlstein void *handle; 8098360efbdSAlfred Perlstein struct netconfig *nconf_clts; 8108360efbdSAlfred Perlstein rpcb_entry_list_ptr relp = NULL; 8118360efbdSAlfred Perlstein 8128360efbdSAlfred Perlstein if (client == NULL) { 8138360efbdSAlfred Perlstein /* This did not go through the above PORTMAP/TCP code */ 8148360efbdSAlfred Perlstein #if 1 8158360efbdSAlfred Perlstein if ((handle = __rpc_setconf("datagram_v")) != NULL) { 8168360efbdSAlfred Perlstein #else 8178360efbdSAlfred Perlstein if ((handle = __rpc_setconf("circuit_v")) != NULL) { 8188360efbdSAlfred Perlstein #endif 8198360efbdSAlfred Perlstein while ((nconf_clts = __rpc_getconf(handle)) 8208360efbdSAlfred Perlstein != NULL) { 8218360efbdSAlfred Perlstein if (strcmp(nconf_clts->nc_protofmly, 8228360efbdSAlfred Perlstein nconf->nc_protofmly) != 0) { 8238360efbdSAlfred Perlstein continue; 8248360efbdSAlfred Perlstein } 8258360efbdSAlfred Perlstein client = getclnthandle(host, nconf_clts, 8268360efbdSAlfred Perlstein &parms.r_addr); 8278360efbdSAlfred Perlstein break; 8288360efbdSAlfred Perlstein } 8298360efbdSAlfred Perlstein __rpc_endconf(handle); 8308360efbdSAlfred Perlstein } 8318360efbdSAlfred Perlstein if (client == NULL) 8328360efbdSAlfred Perlstein goto regular_rpcbind; /* Go the regular way */ 8338360efbdSAlfred Perlstein } else { 8348360efbdSAlfred Perlstein /* This is a UDP PORTMAP handle. Change to version 4 */ 8358360efbdSAlfred Perlstein vers = RPCBVERS4; 8368360efbdSAlfred Perlstein CLNT_CONTROL(client, CLSET_VERS, (char *)(void *)&vers); 8378360efbdSAlfred Perlstein } 8388360efbdSAlfred Perlstein /* 8398360efbdSAlfred Perlstein * We also send the remote system the address we used to 8408360efbdSAlfred Perlstein * contact it in case it can help it connect back with us 8418360efbdSAlfred Perlstein */ 8428360efbdSAlfred Perlstein if (parms.r_addr == NULL) { 8438360efbdSAlfred Perlstein /*LINTED const castaway*/ 8448360efbdSAlfred Perlstein parms.r_addr = (char *) &nullstring[0]; /* for XDRing */ 8458360efbdSAlfred Perlstein } 8468360efbdSAlfred Perlstein clnt_st = CLNT_CALL(client, (rpcproc_t)RPCBPROC_GETADDRLIST, 8478360efbdSAlfred Perlstein (xdrproc_t) xdr_rpcb, (char *)(void *)&parms, 8488360efbdSAlfred Perlstein (xdrproc_t) xdr_rpcb_entry_list_ptr, 8498360efbdSAlfred Perlstein (char *)(void *)&relp, tottimeout); 8508360efbdSAlfred Perlstein if (clnt_st == RPC_SUCCESS) { 8518360efbdSAlfred Perlstein if ((address = got_entry(relp, nconf)) != NULL) { 8528360efbdSAlfred Perlstein xdr_free((xdrproc_t) xdr_rpcb_entry_list_ptr, 8538360efbdSAlfred Perlstein (char *)(void *)&relp); 8548360efbdSAlfred Perlstein goto done; 8558360efbdSAlfred Perlstein } 8568360efbdSAlfred Perlstein /* Entry not found for this transport */ 8578360efbdSAlfred Perlstein xdr_free((xdrproc_t) xdr_rpcb_entry_list_ptr, 8588360efbdSAlfred Perlstein (char *)(void *)&relp); 8598360efbdSAlfred Perlstein /* 8608360efbdSAlfred Perlstein * XXX: should have perhaps returned with error but 8618360efbdSAlfred Perlstein * since the remote machine might not always be able 8628360efbdSAlfred Perlstein * to send the address on all transports, we try the 8638360efbdSAlfred Perlstein * regular way with regular_rpcbind 8648360efbdSAlfred Perlstein */ 8658360efbdSAlfred Perlstein goto regular_rpcbind; 8668360efbdSAlfred Perlstein } else if ((clnt_st == RPC_PROGVERSMISMATCH) || 8678360efbdSAlfred Perlstein (clnt_st == RPC_PROGUNAVAIL)) { 8688360efbdSAlfred Perlstein start_vers = RPCBVERS; /* Try version 3 now */ 8698360efbdSAlfred Perlstein goto regular_rpcbind; /* Try different versions */ 8708360efbdSAlfred Perlstein } else { 8718360efbdSAlfred Perlstein rpc_createerr.cf_stat = RPC_PMAPFAILURE; 8728360efbdSAlfred Perlstein clnt_geterr(client, &rpc_createerr.cf_error); 8738360efbdSAlfred Perlstein goto error; 8748360efbdSAlfred Perlstein } 8758360efbdSAlfred Perlstein } 8768360efbdSAlfred Perlstein 8778360efbdSAlfred Perlstein regular_rpcbind: 8788360efbdSAlfred Perlstein 8798360efbdSAlfred Perlstein /* Now the same transport is to be used to get the address */ 8808360efbdSAlfred Perlstein #if 1 8818360efbdSAlfred Perlstein if (client && ((nconf->nc_semantics == NC_TPI_COTS_ORD) || 8828360efbdSAlfred Perlstein (nconf->nc_semantics == NC_TPI_COTS))) { 8838360efbdSAlfred Perlstein #else 8848360efbdSAlfred Perlstein if (client && nconf->nc_semantics == NC_TPI_CLTS) { 8858360efbdSAlfred Perlstein #endif 8868360efbdSAlfred Perlstein /* A CLTS type of client - destroy it */ 8878360efbdSAlfred Perlstein CLNT_DESTROY(client); 8888360efbdSAlfred Perlstein client = NULL; 8898360efbdSAlfred Perlstein } 8908360efbdSAlfred Perlstein 8918360efbdSAlfred Perlstein if (client == NULL) { 8928360efbdSAlfred Perlstein client = getclnthandle(host, nconf, &parms.r_addr); 8938360efbdSAlfred Perlstein if (client == NULL) { 8948360efbdSAlfred Perlstein goto error; 8958360efbdSAlfred Perlstein } 8968360efbdSAlfred Perlstein } 8978360efbdSAlfred Perlstein if (parms.r_addr == NULL) { 8988360efbdSAlfred Perlstein /*LINTED const castaway*/ 8998360efbdSAlfred Perlstein parms.r_addr = (char *) &nullstring[0]; 9008360efbdSAlfred Perlstein } 9018360efbdSAlfred Perlstein 9028360efbdSAlfred Perlstein /* First try from start_vers and then version 3 (RPCBVERS) */ 9038360efbdSAlfred Perlstein for (vers = start_vers; vers >= RPCBVERS; vers--) { 9048360efbdSAlfred Perlstein /* Set the version */ 9058360efbdSAlfred Perlstein CLNT_CONTROL(client, CLSET_VERS, (char *)(void *)&vers); 9068360efbdSAlfred Perlstein clnt_st = CLNT_CALL(client, (rpcproc_t)RPCBPROC_GETADDR, 9078360efbdSAlfred Perlstein (xdrproc_t) xdr_rpcb, (char *)(void *)&parms, 9088360efbdSAlfred Perlstein (xdrproc_t) xdr_wrapstring, (char *)(void *) &ua, 9098360efbdSAlfred Perlstein tottimeout); 9108360efbdSAlfred Perlstein if (clnt_st == RPC_SUCCESS) { 9118360efbdSAlfred Perlstein if ((ua == NULL) || (ua[0] == NULL)) { 9128360efbdSAlfred Perlstein /* address unknown */ 9138360efbdSAlfred Perlstein rpc_createerr.cf_stat = RPC_PROGNOTREGISTERED; 9148360efbdSAlfred Perlstein goto error; 9158360efbdSAlfred Perlstein } 9168360efbdSAlfred Perlstein address = uaddr2taddr(nconf, ua); 9178360efbdSAlfred Perlstein #ifdef ND_DEBUG 9188360efbdSAlfred Perlstein fprintf(stderr, "\tRemote address is [%s]\n", ua); 9198360efbdSAlfred Perlstein if (!address) 9208360efbdSAlfred Perlstein fprintf(stderr, 9218360efbdSAlfred Perlstein "\tCouldn't resolve remote address!\n"); 9228360efbdSAlfred Perlstein #endif 9238360efbdSAlfred Perlstein xdr_free((xdrproc_t)xdr_wrapstring, 9248360efbdSAlfred Perlstein (char *)(void *)&ua); 9258360efbdSAlfred Perlstein 9268360efbdSAlfred Perlstein if (! address) { 9278360efbdSAlfred Perlstein /* We don't know about your universal address */ 9288360efbdSAlfred Perlstein rpc_createerr.cf_stat = RPC_N2AXLATEFAILURE; 9298360efbdSAlfred Perlstein goto error; 9308360efbdSAlfred Perlstein } 9318360efbdSAlfred Perlstein CLNT_CONTROL(client, CLGET_SVC_ADDR, 9328360efbdSAlfred Perlstein (char *)(void *)&servaddr); 9338360efbdSAlfred Perlstein __rpc_fixup_addr(address, &servaddr); 9348360efbdSAlfred Perlstein goto done; 9358360efbdSAlfred Perlstein } else if (clnt_st == RPC_PROGVERSMISMATCH) { 9368360efbdSAlfred Perlstein struct rpc_err rpcerr; 9378360efbdSAlfred Perlstein 9388360efbdSAlfred Perlstein clnt_geterr(client, &rpcerr); 9398360efbdSAlfred Perlstein if (rpcerr.re_vers.low > RPCBVERS4) 9408360efbdSAlfred Perlstein goto error; /* a new version, can't handle */ 9418360efbdSAlfred Perlstein } else if (clnt_st != RPC_PROGUNAVAIL) { 9428360efbdSAlfred Perlstein /* Cant handle this error */ 9438360efbdSAlfred Perlstein rpc_createerr.cf_stat = clnt_st; 9448360efbdSAlfred Perlstein clnt_geterr(client, &rpc_createerr.cf_error); 9458360efbdSAlfred Perlstein goto error; 9468360efbdSAlfred Perlstein } 9478360efbdSAlfred Perlstein } 9488360efbdSAlfred Perlstein 9498360efbdSAlfred Perlstein if ((address == NULL) || (address->len == 0)) { 9508360efbdSAlfred Perlstein rpc_createerr.cf_stat = RPC_PROGNOTREGISTERED; 9518360efbdSAlfred Perlstein clnt_geterr(client, &rpc_createerr.cf_error); 9528360efbdSAlfred Perlstein } 9538360efbdSAlfred Perlstein 9548360efbdSAlfred Perlstein error: 9558360efbdSAlfred Perlstein if (client) { 9568360efbdSAlfred Perlstein CLNT_DESTROY(client); 9578360efbdSAlfred Perlstein client = NULL; 9588360efbdSAlfred Perlstein } 9598360efbdSAlfred Perlstein done: 9608360efbdSAlfred Perlstein if (nconf->nc_semantics != NC_TPI_CLTS) { 9618360efbdSAlfred Perlstein /* This client is the connectionless one */ 9628360efbdSAlfred Perlstein if (client) { 9638360efbdSAlfred Perlstein CLNT_DESTROY(client); 9648360efbdSAlfred Perlstein client = NULL; 9658360efbdSAlfred Perlstein } 9668360efbdSAlfred Perlstein } 9678360efbdSAlfred Perlstein if (clpp) { 9688360efbdSAlfred Perlstein *clpp = client; 9698360efbdSAlfred Perlstein } else if (client) { 9708360efbdSAlfred Perlstein CLNT_DESTROY(client); 9718360efbdSAlfred Perlstein } 97252353da8SIan Dowse if (parms.r_addr != NULL && parms.r_addr != nullstring) 97352353da8SIan Dowse free(parms.r_addr); 9748360efbdSAlfred Perlstein return (address); 9758360efbdSAlfred Perlstein } 9768360efbdSAlfred Perlstein 9778360efbdSAlfred Perlstein 9788360efbdSAlfred Perlstein /* 9798360efbdSAlfred Perlstein * Find the mapped address for program, version. 9808360efbdSAlfred Perlstein * Calls the rpcbind service remotely to do the lookup. 9818360efbdSAlfred Perlstein * Uses the transport specified in nconf. 9828360efbdSAlfred Perlstein * Returns FALSE (0) if no map exists, else returns 1. 9838360efbdSAlfred Perlstein * 9848360efbdSAlfred Perlstein * Assuming that the address is all properly allocated 9858360efbdSAlfred Perlstein */ 9868360efbdSAlfred Perlstein int 9878360efbdSAlfred Perlstein rpcb_getaddr(program, version, nconf, address, host) 9888360efbdSAlfred Perlstein rpcprog_t program; 9898360efbdSAlfred Perlstein rpcvers_t version; 9908360efbdSAlfred Perlstein const struct netconfig *nconf; 9918360efbdSAlfred Perlstein struct netbuf *address; 9928360efbdSAlfred Perlstein const char *host; 9938360efbdSAlfred Perlstein { 9948360efbdSAlfred Perlstein struct netbuf *na; 9958360efbdSAlfred Perlstein 9968360efbdSAlfred Perlstein if ((na = __rpcb_findaddr(program, version, nconf, 9978360efbdSAlfred Perlstein host, (CLIENT **) NULL)) == NULL) 9988360efbdSAlfred Perlstein return (FALSE); 9998360efbdSAlfred Perlstein 10008360efbdSAlfred Perlstein if (na->len > address->maxlen) { 10018360efbdSAlfred Perlstein /* Too long address */ 10028360efbdSAlfred Perlstein free(na->buf); 10038360efbdSAlfred Perlstein free(na); 10048360efbdSAlfred Perlstein rpc_createerr.cf_stat = RPC_FAILED; 10058360efbdSAlfred Perlstein return (FALSE); 10068360efbdSAlfred Perlstein } 10078360efbdSAlfred Perlstein memcpy(address->buf, na->buf, (size_t)na->len); 10088360efbdSAlfred Perlstein address->len = na->len; 10098360efbdSAlfred Perlstein free(na->buf); 10108360efbdSAlfred Perlstein free(na); 10118360efbdSAlfred Perlstein return (TRUE); 10128360efbdSAlfred Perlstein } 10138360efbdSAlfred Perlstein 10148360efbdSAlfred Perlstein /* 10158360efbdSAlfred Perlstein * Get a copy of the current maps. 10168360efbdSAlfred Perlstein * Calls the rpcbind service remotely to get the maps. 10178360efbdSAlfred Perlstein * 10188360efbdSAlfred Perlstein * It returns only a list of the services 10198360efbdSAlfred Perlstein * It returns NULL on failure. 10208360efbdSAlfred Perlstein */ 10218360efbdSAlfred Perlstein rpcblist * 10228360efbdSAlfred Perlstein rpcb_getmaps(nconf, host) 10238360efbdSAlfred Perlstein const struct netconfig *nconf; 10248360efbdSAlfred Perlstein const char *host; 10258360efbdSAlfred Perlstein { 10268360efbdSAlfred Perlstein rpcblist_ptr head = NULL; 10278360efbdSAlfred Perlstein CLIENT *client; 10288360efbdSAlfred Perlstein enum clnt_stat clnt_st; 10298360efbdSAlfred Perlstein rpcvers_t vers = 0; 10308360efbdSAlfred Perlstein 10318360efbdSAlfred Perlstein client = getclnthandle(host, nconf, NULL); 10328360efbdSAlfred Perlstein if (client == NULL) { 10338360efbdSAlfred Perlstein return (head); 10348360efbdSAlfred Perlstein } 10358360efbdSAlfred Perlstein clnt_st = CLNT_CALL(client, (rpcproc_t)RPCBPROC_DUMP, 10368360efbdSAlfred Perlstein (xdrproc_t) xdr_void, NULL, (xdrproc_t) xdr_rpcblist_ptr, 10378360efbdSAlfred Perlstein (char *)(void *)&head, tottimeout); 10388360efbdSAlfred Perlstein if (clnt_st == RPC_SUCCESS) 10398360efbdSAlfred Perlstein goto done; 10408360efbdSAlfred Perlstein 10418360efbdSAlfred Perlstein if ((clnt_st != RPC_PROGVERSMISMATCH) && 10428360efbdSAlfred Perlstein (clnt_st != RPC_PROGUNAVAIL)) { 10438360efbdSAlfred Perlstein rpc_createerr.cf_stat = RPC_RPCBFAILURE; 10448360efbdSAlfred Perlstein clnt_geterr(client, &rpc_createerr.cf_error); 10458360efbdSAlfred Perlstein goto done; 10468360efbdSAlfred Perlstein } 10478360efbdSAlfred Perlstein 10488360efbdSAlfred Perlstein /* fall back to earlier version */ 10498360efbdSAlfred Perlstein CLNT_CONTROL(client, CLGET_VERS, (char *)(void *)&vers); 10508360efbdSAlfred Perlstein if (vers == RPCBVERS4) { 10518360efbdSAlfred Perlstein vers = RPCBVERS; 10528360efbdSAlfred Perlstein CLNT_CONTROL(client, CLSET_VERS, (char *)(void *)&vers); 10538360efbdSAlfred Perlstein if (CLNT_CALL(client, (rpcproc_t)RPCBPROC_DUMP, 10548360efbdSAlfred Perlstein (xdrproc_t) xdr_void, NULL, (xdrproc_t) xdr_rpcblist_ptr, 10558360efbdSAlfred Perlstein (char *)(void *)&head, tottimeout) == RPC_SUCCESS) 10568360efbdSAlfred Perlstein goto done; 10578360efbdSAlfred Perlstein } 10588360efbdSAlfred Perlstein rpc_createerr.cf_stat = RPC_RPCBFAILURE; 10598360efbdSAlfred Perlstein clnt_geterr(client, &rpc_createerr.cf_error); 10608360efbdSAlfred Perlstein 10618360efbdSAlfred Perlstein done: 10628360efbdSAlfred Perlstein CLNT_DESTROY(client); 10638360efbdSAlfred Perlstein return (head); 10648360efbdSAlfred Perlstein } 10658360efbdSAlfred Perlstein 10668360efbdSAlfred Perlstein /* 10678360efbdSAlfred Perlstein * rpcbinder remote-call-service interface. 10688360efbdSAlfred Perlstein * This routine is used to call the rpcbind remote call service 10698360efbdSAlfred Perlstein * which will look up a service program in the address maps, and then 10708360efbdSAlfred Perlstein * remotely call that routine with the given parameters. This allows 10718360efbdSAlfred Perlstein * programs to do a lookup and call in one step. 10728360efbdSAlfred Perlstein */ 10738360efbdSAlfred Perlstein enum clnt_stat 10748360efbdSAlfred Perlstein rpcb_rmtcall(nconf, host, prog, vers, proc, xdrargs, argsp, 10758360efbdSAlfred Perlstein xdrres, resp, tout, addr_ptr) 10768360efbdSAlfred Perlstein const struct netconfig *nconf; /* Netconfig structure */ 10778360efbdSAlfred Perlstein const char *host; /* Remote host name */ 10788360efbdSAlfred Perlstein rpcprog_t prog; 10798360efbdSAlfred Perlstein rpcvers_t vers; 10808360efbdSAlfred Perlstein rpcproc_t proc; /* Remote proc identifiers */ 10818360efbdSAlfred Perlstein xdrproc_t xdrargs, xdrres; /* XDR routines */ 10828360efbdSAlfred Perlstein caddr_t argsp, resp; /* Argument and Result */ 10838360efbdSAlfred Perlstein struct timeval tout; /* Timeout value for this call */ 10848360efbdSAlfred Perlstein const struct netbuf *addr_ptr; /* Preallocated netbuf address */ 10858360efbdSAlfred Perlstein { 10868360efbdSAlfred Perlstein CLIENT *client; 10878360efbdSAlfred Perlstein enum clnt_stat stat; 10888360efbdSAlfred Perlstein struct r_rpcb_rmtcallargs a; 10898360efbdSAlfred Perlstein struct r_rpcb_rmtcallres r; 10908360efbdSAlfred Perlstein rpcvers_t rpcb_vers; 10918360efbdSAlfred Perlstein 109252353da8SIan Dowse stat = 0; 10938360efbdSAlfred Perlstein client = getclnthandle(host, nconf, NULL); 10948360efbdSAlfred Perlstein if (client == NULL) { 10958360efbdSAlfred Perlstein return (RPC_FAILED); 10968360efbdSAlfred Perlstein } 10978360efbdSAlfred Perlstein /*LINTED const castaway*/ 10988360efbdSAlfred Perlstein CLNT_CONTROL(client, CLSET_RETRY_TIMEOUT, (char *)(void *)&rmttimeout); 10998360efbdSAlfred Perlstein a.prog = prog; 11008360efbdSAlfred Perlstein a.vers = vers; 11018360efbdSAlfred Perlstein a.proc = proc; 11028360efbdSAlfred Perlstein a.args.args_val = argsp; 11038360efbdSAlfred Perlstein a.xdr_args = xdrargs; 11048360efbdSAlfred Perlstein r.addr = NULL; 11058360efbdSAlfred Perlstein r.results.results_val = resp; 11068360efbdSAlfred Perlstein r.xdr_res = xdrres; 11078360efbdSAlfred Perlstein 11088360efbdSAlfred Perlstein for (rpcb_vers = RPCBVERS4; rpcb_vers >= RPCBVERS; rpcb_vers--) { 11098360efbdSAlfred Perlstein CLNT_CONTROL(client, CLSET_VERS, (char *)(void *)&rpcb_vers); 11108360efbdSAlfred Perlstein stat = CLNT_CALL(client, (rpcproc_t)RPCBPROC_CALLIT, 11118360efbdSAlfred Perlstein (xdrproc_t) xdr_rpcb_rmtcallargs, (char *)(void *)&a, 11128360efbdSAlfred Perlstein (xdrproc_t) xdr_rpcb_rmtcallres, (char *)(void *)&r, tout); 11138360efbdSAlfred Perlstein if ((stat == RPC_SUCCESS) && (addr_ptr != NULL)) { 11148360efbdSAlfred Perlstein struct netbuf *na; 11158360efbdSAlfred Perlstein /*LINTED const castaway*/ 11168360efbdSAlfred Perlstein na = uaddr2taddr((struct netconfig *) nconf, r.addr); 11178360efbdSAlfred Perlstein if (!na) { 11188360efbdSAlfred Perlstein stat = RPC_N2AXLATEFAILURE; 11198360efbdSAlfred Perlstein /*LINTED const castaway*/ 11208360efbdSAlfred Perlstein ((struct netbuf *) addr_ptr)->len = 0; 11218360efbdSAlfred Perlstein goto error; 11228360efbdSAlfred Perlstein } 11238360efbdSAlfred Perlstein if (na->len > addr_ptr->maxlen) { 11248360efbdSAlfred Perlstein /* Too long address */ 11258360efbdSAlfred Perlstein stat = RPC_FAILED; /* XXX A better error no */ 11268360efbdSAlfred Perlstein free(na->buf); 11278360efbdSAlfred Perlstein free(na); 11288360efbdSAlfred Perlstein /*LINTED const castaway*/ 11298360efbdSAlfred Perlstein ((struct netbuf *) addr_ptr)->len = 0; 11308360efbdSAlfred Perlstein goto error; 11318360efbdSAlfred Perlstein } 11328360efbdSAlfred Perlstein memcpy(addr_ptr->buf, na->buf, (size_t)na->len); 11338360efbdSAlfred Perlstein /*LINTED const castaway*/ 11348360efbdSAlfred Perlstein ((struct netbuf *)addr_ptr)->len = na->len; 11358360efbdSAlfred Perlstein free(na->buf); 11368360efbdSAlfred Perlstein free(na); 11378360efbdSAlfred Perlstein break; 11388360efbdSAlfred Perlstein } else if ((stat != RPC_PROGVERSMISMATCH) && 11398360efbdSAlfred Perlstein (stat != RPC_PROGUNAVAIL)) { 11408360efbdSAlfred Perlstein goto error; 11418360efbdSAlfred Perlstein } 11428360efbdSAlfred Perlstein } 11438360efbdSAlfred Perlstein error: 11448360efbdSAlfred Perlstein CLNT_DESTROY(client); 11458360efbdSAlfred Perlstein if (r.addr) 11468360efbdSAlfred Perlstein xdr_free((xdrproc_t) xdr_wrapstring, (char *)(void *)&r.addr); 11478360efbdSAlfred Perlstein return (stat); 11488360efbdSAlfred Perlstein } 11498360efbdSAlfred Perlstein 11508360efbdSAlfred Perlstein /* 11518360efbdSAlfred Perlstein * Gets the time on the remote host. 11528360efbdSAlfred Perlstein * Returns 1 if succeeds else 0. 11538360efbdSAlfred Perlstein */ 11548360efbdSAlfred Perlstein bool_t 11558360efbdSAlfred Perlstein rpcb_gettime(host, timep) 11568360efbdSAlfred Perlstein const char *host; 11578360efbdSAlfred Perlstein time_t *timep; 11588360efbdSAlfred Perlstein { 11598360efbdSAlfred Perlstein CLIENT *client = NULL; 11608360efbdSAlfred Perlstein void *handle; 11618360efbdSAlfred Perlstein struct netconfig *nconf; 11628360efbdSAlfred Perlstein rpcvers_t vers; 11638360efbdSAlfred Perlstein enum clnt_stat st; 11648360efbdSAlfred Perlstein 11658360efbdSAlfred Perlstein 11668360efbdSAlfred Perlstein if ((host == NULL) || (host[0] == NULL)) { 11678360efbdSAlfred Perlstein time(timep); 11688360efbdSAlfred Perlstein return (TRUE); 11698360efbdSAlfred Perlstein } 11708360efbdSAlfred Perlstein 11718360efbdSAlfred Perlstein if ((handle = __rpc_setconf("netpath")) == NULL) { 11728360efbdSAlfred Perlstein rpc_createerr.cf_stat = RPC_UNKNOWNPROTO; 11738360efbdSAlfred Perlstein return (FALSE); 11748360efbdSAlfred Perlstein } 11758360efbdSAlfred Perlstein rpc_createerr.cf_stat = RPC_SUCCESS; 11768360efbdSAlfred Perlstein while (client == NULL) { 11778360efbdSAlfred Perlstein if ((nconf = __rpc_getconf(handle)) == NULL) { 11788360efbdSAlfred Perlstein if (rpc_createerr.cf_stat == RPC_SUCCESS) 11798360efbdSAlfred Perlstein rpc_createerr.cf_stat = RPC_UNKNOWNPROTO; 11808360efbdSAlfred Perlstein break; 11818360efbdSAlfred Perlstein } 11828360efbdSAlfred Perlstein client = getclnthandle(host, nconf, NULL); 11838360efbdSAlfred Perlstein if (client) 11848360efbdSAlfred Perlstein break; 11858360efbdSAlfred Perlstein } 11868360efbdSAlfred Perlstein __rpc_endconf(handle); 11878360efbdSAlfred Perlstein if (client == (CLIENT *) NULL) { 11888360efbdSAlfred Perlstein return (FALSE); 11898360efbdSAlfred Perlstein } 11908360efbdSAlfred Perlstein 11918360efbdSAlfred Perlstein st = CLNT_CALL(client, (rpcproc_t)RPCBPROC_GETTIME, 11928360efbdSAlfred Perlstein (xdrproc_t) xdr_void, NULL, 11938360efbdSAlfred Perlstein (xdrproc_t) xdr_int, (char *)(void *)timep, tottimeout); 11948360efbdSAlfred Perlstein 11958360efbdSAlfred Perlstein if ((st == RPC_PROGVERSMISMATCH) || (st == RPC_PROGUNAVAIL)) { 11968360efbdSAlfred Perlstein CLNT_CONTROL(client, CLGET_VERS, (char *)(void *)&vers); 11978360efbdSAlfred Perlstein if (vers == RPCBVERS4) { 11988360efbdSAlfred Perlstein /* fall back to earlier version */ 11998360efbdSAlfred Perlstein vers = RPCBVERS; 12008360efbdSAlfred Perlstein CLNT_CONTROL(client, CLSET_VERS, (char *)(void *)&vers); 12018360efbdSAlfred Perlstein st = CLNT_CALL(client, (rpcproc_t)RPCBPROC_GETTIME, 12028360efbdSAlfred Perlstein (xdrproc_t) xdr_void, NULL, 12038360efbdSAlfred Perlstein (xdrproc_t) xdr_int, (char *)(void *)timep, 12048360efbdSAlfred Perlstein tottimeout); 12058360efbdSAlfred Perlstein } 12068360efbdSAlfred Perlstein } 12078360efbdSAlfred Perlstein CLNT_DESTROY(client); 12088360efbdSAlfred Perlstein return (st == RPC_SUCCESS? TRUE: FALSE); 12098360efbdSAlfred Perlstein } 12108360efbdSAlfred Perlstein 12118360efbdSAlfred Perlstein /* 12128360efbdSAlfred Perlstein * Converts taddr to universal address. This routine should never 12138360efbdSAlfred Perlstein * really be called because local n2a libraries are always provided. 12148360efbdSAlfred Perlstein */ 12158360efbdSAlfred Perlstein char * 12168360efbdSAlfred Perlstein rpcb_taddr2uaddr(nconf, taddr) 12178360efbdSAlfred Perlstein struct netconfig *nconf; 12188360efbdSAlfred Perlstein struct netbuf *taddr; 12198360efbdSAlfred Perlstein { 12208360efbdSAlfred Perlstein CLIENT *client; 12218360efbdSAlfred Perlstein char *uaddr = NULL; 12228360efbdSAlfred Perlstein 12238360efbdSAlfred Perlstein 12248360efbdSAlfred Perlstein /* parameter checking */ 12258360efbdSAlfred Perlstein if (nconf == NULL) { 12268360efbdSAlfred Perlstein rpc_createerr.cf_stat = RPC_UNKNOWNPROTO; 12278360efbdSAlfred Perlstein return (NULL); 12288360efbdSAlfred Perlstein } 12298360efbdSAlfred Perlstein if (taddr == NULL) { 12308360efbdSAlfred Perlstein rpc_createerr.cf_stat = RPC_UNKNOWNADDR; 12318360efbdSAlfred Perlstein return (NULL); 12328360efbdSAlfred Perlstein } 12338360efbdSAlfred Perlstein client = local_rpcb(); 12348360efbdSAlfred Perlstein if (! client) { 12358360efbdSAlfred Perlstein return (NULL); 12368360efbdSAlfred Perlstein } 12378360efbdSAlfred Perlstein 12388360efbdSAlfred Perlstein CLNT_CALL(client, (rpcproc_t)RPCBPROC_TADDR2UADDR, 12398360efbdSAlfred Perlstein (xdrproc_t) xdr_netbuf, (char *)(void *)taddr, 12408360efbdSAlfred Perlstein (xdrproc_t) xdr_wrapstring, (char *)(void *)&uaddr, tottimeout); 12418360efbdSAlfred Perlstein CLNT_DESTROY(client); 12428360efbdSAlfred Perlstein return (uaddr); 12438360efbdSAlfred Perlstein } 12448360efbdSAlfred Perlstein 12458360efbdSAlfred Perlstein /* 12468360efbdSAlfred Perlstein * Converts universal address to netbuf. This routine should never 12478360efbdSAlfred Perlstein * really be called because local n2a libraries are always provided. 12488360efbdSAlfred Perlstein */ 12498360efbdSAlfred Perlstein struct netbuf * 12508360efbdSAlfred Perlstein rpcb_uaddr2taddr(nconf, uaddr) 12518360efbdSAlfred Perlstein struct netconfig *nconf; 12528360efbdSAlfred Perlstein char *uaddr; 12538360efbdSAlfred Perlstein { 12548360efbdSAlfred Perlstein CLIENT *client; 12558360efbdSAlfred Perlstein struct netbuf *taddr; 12568360efbdSAlfred Perlstein 12578360efbdSAlfred Perlstein 12588360efbdSAlfred Perlstein /* parameter checking */ 12598360efbdSAlfred Perlstein if (nconf == NULL) { 12608360efbdSAlfred Perlstein rpc_createerr.cf_stat = RPC_UNKNOWNPROTO; 12618360efbdSAlfred Perlstein return (NULL); 12628360efbdSAlfred Perlstein } 12638360efbdSAlfred Perlstein if (uaddr == NULL) { 12648360efbdSAlfred Perlstein rpc_createerr.cf_stat = RPC_UNKNOWNADDR; 12658360efbdSAlfred Perlstein return (NULL); 12668360efbdSAlfred Perlstein } 12678360efbdSAlfred Perlstein client = local_rpcb(); 12688360efbdSAlfred Perlstein if (! client) { 12698360efbdSAlfred Perlstein return (NULL); 12708360efbdSAlfred Perlstein } 12718360efbdSAlfred Perlstein 12728360efbdSAlfred Perlstein taddr = (struct netbuf *)calloc(1, sizeof (struct netbuf)); 12738360efbdSAlfred Perlstein if (taddr == NULL) { 12748360efbdSAlfred Perlstein CLNT_DESTROY(client); 12758360efbdSAlfred Perlstein return (NULL); 12768360efbdSAlfred Perlstein } 12778360efbdSAlfred Perlstein if (CLNT_CALL(client, (rpcproc_t)RPCBPROC_UADDR2TADDR, 12788360efbdSAlfred Perlstein (xdrproc_t) xdr_wrapstring, (char *)(void *)&uaddr, 12798360efbdSAlfred Perlstein (xdrproc_t) xdr_netbuf, (char *)(void *)taddr, 12808360efbdSAlfred Perlstein tottimeout) != RPC_SUCCESS) { 12818360efbdSAlfred Perlstein free(taddr); 12828360efbdSAlfred Perlstein taddr = NULL; 12838360efbdSAlfred Perlstein } 12848360efbdSAlfred Perlstein CLNT_DESTROY(client); 12858360efbdSAlfred Perlstein return (taddr); 12868360efbdSAlfred Perlstein } 1287