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