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 2828360efbdSAlfred Perlstein * rpcbind. Returns NULL on error 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 */ 3018360efbdSAlfred Perlstein addr_to_delete.len = 0; 3028360efbdSAlfred Perlstein rwlock_rdlock(&rpcbaddr_cache_lock); 3038360efbdSAlfred Perlstein ad_cache = check_cache(host, nconf->nc_netid); 3048360efbdSAlfred Perlstein if (ad_cache != NULL) { 3058360efbdSAlfred Perlstein addr = ad_cache->ac_taddr; 3068360efbdSAlfred Perlstein client = clnt_tli_create(RPC_ANYFD, nconf, addr, 3078360efbdSAlfred Perlstein (rpcprog_t)RPCBPROG, (rpcvers_t)RPCBVERS4, 0, 0); 3088360efbdSAlfred Perlstein if (client != NULL) { 3098360efbdSAlfred Perlstein if (targaddr) 3108360efbdSAlfred Perlstein *targaddr = ad_cache->ac_uaddr; 3118360efbdSAlfred Perlstein rwlock_unlock(&rpcbaddr_cache_lock); 3128360efbdSAlfred Perlstein return (client); 3138360efbdSAlfred Perlstein } 3148360efbdSAlfred Perlstein addr_to_delete.len = addr->len; 3158360efbdSAlfred Perlstein addr_to_delete.buf = (char *)malloc(addr->len); 3168360efbdSAlfred Perlstein if (addr_to_delete.buf == NULL) { 3178360efbdSAlfred Perlstein addr_to_delete.len = 0; 3188360efbdSAlfred Perlstein } else { 3198360efbdSAlfred Perlstein memcpy(addr_to_delete.buf, addr->buf, addr->len); 3208360efbdSAlfred Perlstein } 3218360efbdSAlfred Perlstein } 3228360efbdSAlfred Perlstein rwlock_unlock(&rpcbaddr_cache_lock); 3238360efbdSAlfred Perlstein if (addr_to_delete.len != 0) { 3248360efbdSAlfred Perlstein /* 3258360efbdSAlfred Perlstein * Assume this may be due to cache data being 3268360efbdSAlfred Perlstein * outdated 3278360efbdSAlfred Perlstein */ 3288360efbdSAlfred Perlstein rwlock_wrlock(&rpcbaddr_cache_lock); 3298360efbdSAlfred Perlstein delete_cache(&addr_to_delete); 3308360efbdSAlfred Perlstein rwlock_unlock(&rpcbaddr_cache_lock); 3318360efbdSAlfred Perlstein free(addr_to_delete.buf); 3328360efbdSAlfred Perlstein } 3338360efbdSAlfred Perlstein if (!__rpc_nconf2sockinfo(nconf, &si)) { 3348360efbdSAlfred Perlstein rpc_createerr.cf_stat = RPC_UNKNOWNPROTO; 3358360efbdSAlfred Perlstein return NULL; 3368360efbdSAlfred Perlstein } 3378360efbdSAlfred Perlstein 3388360efbdSAlfred Perlstein memset(&hints, 0, sizeof hints); 3398360efbdSAlfred Perlstein hints.ai_family = si.si_af; 3408360efbdSAlfred Perlstein hints.ai_socktype = si.si_socktype; 3418360efbdSAlfred Perlstein hints.ai_protocol = si.si_proto; 3428360efbdSAlfred Perlstein 3438360efbdSAlfred Perlstein #ifdef CLNT_DEBUG 3448360efbdSAlfred Perlstein printf("trying netid %s family %d proto %d socktype %d\n", 3458360efbdSAlfred Perlstein nconf->nc_netid, si.si_af, si.si_proto, si.si_socktype); 3468360efbdSAlfred Perlstein #endif 3478360efbdSAlfred Perlstein 3488360efbdSAlfred Perlstein if (getaddrinfo(host, "sunrpc", &hints, &res) != 0) { 3498360efbdSAlfred Perlstein rpc_createerr.cf_stat = RPC_UNKNOWNHOST; 3508360efbdSAlfred Perlstein return NULL; 3518360efbdSAlfred Perlstein } 3528360efbdSAlfred Perlstein 3538360efbdSAlfred Perlstein for (tres = res; tres != NULL; tres = tres->ai_next) { 3548360efbdSAlfred Perlstein taddr.buf = tres->ai_addr; 3558360efbdSAlfred Perlstein taddr.len = taddr.maxlen = tres->ai_addrlen; 3568360efbdSAlfred Perlstein 3578360efbdSAlfred Perlstein #ifdef ND_DEBUG 3588360efbdSAlfred Perlstein { 3598360efbdSAlfred Perlstein char *ua; 3608360efbdSAlfred Perlstein 3618360efbdSAlfred Perlstein ua = taddr2uaddr(nconf, &taddr); 3628360efbdSAlfred Perlstein fprintf(stderr, "Got it [%s]\n", ua); 3638360efbdSAlfred Perlstein free(ua); 3648360efbdSAlfred Perlstein } 3658360efbdSAlfred Perlstein #endif 3668360efbdSAlfred Perlstein 3678360efbdSAlfred Perlstein #ifdef ND_DEBUG 3688360efbdSAlfred Perlstein { 3698360efbdSAlfred Perlstein int i; 3708360efbdSAlfred Perlstein 3718360efbdSAlfred Perlstein fprintf(stderr, "\tnetbuf len = %d, maxlen = %d\n", 3728360efbdSAlfred Perlstein taddr.len, taddr.maxlen); 3738360efbdSAlfred Perlstein fprintf(stderr, "\tAddress is "); 3748360efbdSAlfred Perlstein for (i = 0; i < taddr.len; i++) 3758360efbdSAlfred Perlstein fprintf(stderr, "%u.", ((char *)(taddr.buf))[i]); 3768360efbdSAlfred Perlstein fprintf(stderr, "\n"); 3778360efbdSAlfred Perlstein } 3788360efbdSAlfred Perlstein #endif 3798360efbdSAlfred Perlstein client = clnt_tli_create(RPC_ANYFD, nconf, &taddr, 3808360efbdSAlfred Perlstein (rpcprog_t)RPCBPROG, (rpcvers_t)RPCBVERS4, 0, 0); 3818360efbdSAlfred Perlstein #ifdef ND_DEBUG 3828360efbdSAlfred Perlstein if (! client) { 3838360efbdSAlfred Perlstein clnt_pcreateerror("rpcbind clnt interface"); 3848360efbdSAlfred Perlstein } 3858360efbdSAlfred Perlstein #endif 3868360efbdSAlfred Perlstein 3878360efbdSAlfred Perlstein if (client) { 3888360efbdSAlfred Perlstein tmpaddr = targaddr ? taddr2uaddr(nconf, &taddr) : NULL; 3898360efbdSAlfred Perlstein add_cache(host, nconf->nc_netid, &taddr, tmpaddr); 3908360efbdSAlfred Perlstein if (targaddr) 3918360efbdSAlfred Perlstein *targaddr = tmpaddr; 3928360efbdSAlfred Perlstein break; 3938360efbdSAlfred Perlstein } 3948360efbdSAlfred Perlstein } 3958360efbdSAlfred Perlstein freeaddrinfo(res); 3968360efbdSAlfred Perlstein return (client); 3978360efbdSAlfred Perlstein } 3988360efbdSAlfred Perlstein 3998360efbdSAlfred Perlstein /* XXX */ 4008360efbdSAlfred Perlstein #define IN4_LOCALHOST_STRING "127.0.0.1" 4018360efbdSAlfred Perlstein #define IN6_LOCALHOST_STRING "::1" 4028360efbdSAlfred Perlstein 4038360efbdSAlfred Perlstein /* 4048360efbdSAlfred Perlstein * This routine will return a client handle that is connected to the local 4058360efbdSAlfred Perlstein * rpcbind. Returns NULL on error and free's everything. 4068360efbdSAlfred Perlstein */ 4078360efbdSAlfred Perlstein static CLIENT * 4088360efbdSAlfred Perlstein local_rpcb() 4098360efbdSAlfred Perlstein { 4108360efbdSAlfred Perlstein CLIENT *client; 4118360efbdSAlfred Perlstein static struct netconfig *loopnconf; 4128360efbdSAlfred Perlstein static char *hostname; 4138360efbdSAlfred Perlstein extern mutex_t loopnconf_lock; 4148360efbdSAlfred Perlstein int sock; 4158360efbdSAlfred Perlstein size_t tsize; 4168360efbdSAlfred Perlstein struct netbuf nbuf; 4178360efbdSAlfred Perlstein struct sockaddr_un sun; 4188360efbdSAlfred Perlstein 4198360efbdSAlfred Perlstein /* 4208360efbdSAlfred Perlstein * Try connecting to the local rpcbind through a local socket 4218360efbdSAlfred Perlstein * first. If this doesn't work, try all transports defined in 4228360efbdSAlfred Perlstein * the netconfig file. 4238360efbdSAlfred Perlstein */ 4248360efbdSAlfred Perlstein memset(&sun, 0, sizeof sun); 4258360efbdSAlfred Perlstein sock = _socket(AF_LOCAL, SOCK_STREAM, 0); 4268360efbdSAlfred Perlstein if (sock < 0) 4278360efbdSAlfred Perlstein goto try_nconf; 4288360efbdSAlfred Perlstein sun.sun_family = AF_LOCAL; 4298360efbdSAlfred Perlstein strcpy(sun.sun_path, _PATH_RPCBINDSOCK); 4308360efbdSAlfred Perlstein nbuf.len = sun.sun_len = SUN_LEN(&sun); 4318360efbdSAlfred Perlstein nbuf.maxlen = sizeof (struct sockaddr_un); 4328360efbdSAlfred Perlstein nbuf.buf = &sun; 4338360efbdSAlfred Perlstein 4348360efbdSAlfred Perlstein tsize = __rpc_get_t_size(AF_LOCAL, 0, 0); 4358360efbdSAlfred Perlstein client = clnt_vc_create(sock, &nbuf, (rpcprog_t)RPCBPROG, 4368360efbdSAlfred Perlstein (rpcvers_t)RPCBVERS, tsize, tsize); 4378360efbdSAlfred Perlstein 4388360efbdSAlfred Perlstein if (client != NULL) 4398360efbdSAlfred Perlstein return client; 4408360efbdSAlfred Perlstein 4418360efbdSAlfred Perlstein try_nconf: 4428360efbdSAlfred Perlstein 4438360efbdSAlfred Perlstein /* VARIABLES PROTECTED BY loopnconf_lock: loopnconf */ 4448360efbdSAlfred Perlstein mutex_lock(&loopnconf_lock); 4458360efbdSAlfred Perlstein if (loopnconf == NULL) { 4468360efbdSAlfred Perlstein struct netconfig *nconf, *tmpnconf = NULL; 4478360efbdSAlfred Perlstein void *nc_handle; 4488360efbdSAlfred Perlstein int fd; 4498360efbdSAlfred Perlstein 4508360efbdSAlfred Perlstein nc_handle = setnetconfig(); 4518360efbdSAlfred Perlstein if (nc_handle == NULL) { 4528360efbdSAlfred Perlstein /* fails to open netconfig file */ 4538360efbdSAlfred Perlstein syslog (LOG_ERR, "rpc: failed to open " NETCONFIG); 4548360efbdSAlfred Perlstein rpc_createerr.cf_stat = RPC_UNKNOWNPROTO; 4558360efbdSAlfred Perlstein mutex_unlock(&loopnconf_lock); 4568360efbdSAlfred Perlstein return (NULL); 4578360efbdSAlfred Perlstein } 4588360efbdSAlfred Perlstein while ((nconf = getnetconfig(nc_handle)) != NULL) { 4598360efbdSAlfred Perlstein #ifdef INET6 4608360efbdSAlfred Perlstein if ((strcmp(nconf->nc_protofmly, NC_INET6) == 0 || 4618360efbdSAlfred Perlstein #else 4628360efbdSAlfred Perlstein if (( 4638360efbdSAlfred Perlstein #endif 4648360efbdSAlfred Perlstein strcmp(nconf->nc_protofmly, NC_INET) == 0) && 4658360efbdSAlfred Perlstein (nconf->nc_semantics == NC_TPI_COTS || 4668360efbdSAlfred Perlstein nconf->nc_semantics == NC_TPI_COTS_ORD)) { 4678360efbdSAlfred Perlstein fd = __rpc_nconf2fd(nconf); 4688360efbdSAlfred Perlstein /* 4698360efbdSAlfred Perlstein * Can't create a socket, assume that 4708360efbdSAlfred Perlstein * this family isn't configured in the kernel. 4718360efbdSAlfred Perlstein */ 4728360efbdSAlfred Perlstein if (fd < 0) 4738360efbdSAlfred Perlstein continue; 4748360efbdSAlfred Perlstein _close(fd); 4758360efbdSAlfred Perlstein tmpnconf = nconf; 4768360efbdSAlfred Perlstein if (!strcmp(nconf->nc_protofmly, NC_INET)) 4778360efbdSAlfred Perlstein hostname = IN4_LOCALHOST_STRING; 4788360efbdSAlfred Perlstein else 4798360efbdSAlfred Perlstein hostname = IN6_LOCALHOST_STRING; 4808360efbdSAlfred Perlstein } 4818360efbdSAlfred Perlstein } 4828360efbdSAlfred Perlstein if (tmpnconf == NULL) { 4838360efbdSAlfred Perlstein rpc_createerr.cf_stat = RPC_UNKNOWNPROTO; 4848360efbdSAlfred Perlstein mutex_unlock(&loopnconf_lock); 4858360efbdSAlfred Perlstein return (NULL); 4868360efbdSAlfred Perlstein } 4878360efbdSAlfred Perlstein loopnconf = getnetconfigent(tmpnconf->nc_netid); 4888360efbdSAlfred Perlstein /* loopnconf is never freed */ 4898360efbdSAlfred Perlstein endnetconfig(nc_handle); 4908360efbdSAlfred Perlstein } 4918360efbdSAlfred Perlstein mutex_unlock(&loopnconf_lock); 4928360efbdSAlfred Perlstein client = getclnthandle(hostname, loopnconf, NULL); 4938360efbdSAlfred Perlstein return (client); 4948360efbdSAlfred Perlstein } 4958360efbdSAlfred Perlstein 4968360efbdSAlfred Perlstein /* 4978360efbdSAlfred Perlstein * Set a mapping between program, version and address. 4988360efbdSAlfred Perlstein * Calls the rpcbind service to do the mapping. 4998360efbdSAlfred Perlstein */ 5008360efbdSAlfred Perlstein bool_t 5018360efbdSAlfred Perlstein rpcb_set(program, version, nconf, address) 5028360efbdSAlfred Perlstein rpcprog_t program; 5038360efbdSAlfred Perlstein rpcvers_t version; 5048360efbdSAlfred Perlstein const struct netconfig *nconf; /* Network structure of transport */ 5058360efbdSAlfred Perlstein const struct netbuf *address; /* Services netconfig address */ 5068360efbdSAlfred Perlstein { 5078360efbdSAlfred Perlstein CLIENT *client; 5088360efbdSAlfred Perlstein bool_t rslt = FALSE; 5098360efbdSAlfred Perlstein RPCB parms; 5108360efbdSAlfred Perlstein char uidbuf[32]; 5118360efbdSAlfred Perlstein 5128360efbdSAlfred Perlstein /* parameter checking */ 5138360efbdSAlfred Perlstein if (nconf == NULL) { 5148360efbdSAlfred Perlstein rpc_createerr.cf_stat = RPC_UNKNOWNPROTO; 5158360efbdSAlfred Perlstein return (FALSE); 5168360efbdSAlfred Perlstein } 5178360efbdSAlfred Perlstein if (address == NULL) { 5188360efbdSAlfred Perlstein rpc_createerr.cf_stat = RPC_UNKNOWNADDR; 5198360efbdSAlfred Perlstein return (FALSE); 5208360efbdSAlfred Perlstein } 5218360efbdSAlfred Perlstein client = local_rpcb(); 5228360efbdSAlfred Perlstein if (! client) { 5238360efbdSAlfred Perlstein return (FALSE); 5248360efbdSAlfred Perlstein } 5258360efbdSAlfred Perlstein 5268360efbdSAlfred Perlstein /* convert to universal */ 5278360efbdSAlfred Perlstein /*LINTED const castaway*/ 5288360efbdSAlfred Perlstein parms.r_addr = taddr2uaddr((struct netconfig *) nconf, 5298360efbdSAlfred Perlstein (struct netbuf *)address); 5308360efbdSAlfred Perlstein if (!parms.r_addr) { 5318360efbdSAlfred Perlstein rpc_createerr.cf_stat = RPC_N2AXLATEFAILURE; 5328360efbdSAlfred Perlstein return (FALSE); /* no universal address */ 5338360efbdSAlfred Perlstein } 5348360efbdSAlfred Perlstein parms.r_prog = program; 5358360efbdSAlfred Perlstein parms.r_vers = version; 5368360efbdSAlfred Perlstein parms.r_netid = nconf->nc_netid; 5378360efbdSAlfred Perlstein /* 5388360efbdSAlfred Perlstein * Though uid is not being used directly, we still send it for 5398360efbdSAlfred Perlstein * completeness. For non-unix platforms, perhaps some other 5408360efbdSAlfred Perlstein * string or an empty string can be sent. 5418360efbdSAlfred Perlstein */ 5428360efbdSAlfred Perlstein (void) snprintf(uidbuf, sizeof uidbuf, "%d", geteuid()); 5438360efbdSAlfred Perlstein parms.r_owner = uidbuf; 5448360efbdSAlfred Perlstein 5458360efbdSAlfred Perlstein CLNT_CALL(client, (rpcproc_t)RPCBPROC_SET, (xdrproc_t) xdr_rpcb, 5468360efbdSAlfred Perlstein (char *)(void *)&parms, (xdrproc_t) xdr_bool, 5478360efbdSAlfred Perlstein (char *)(void *)&rslt, tottimeout); 5488360efbdSAlfred Perlstein 5498360efbdSAlfred Perlstein CLNT_DESTROY(client); 5508360efbdSAlfred Perlstein free(parms.r_addr); 5518360efbdSAlfred Perlstein return (rslt); 5528360efbdSAlfred Perlstein } 5538360efbdSAlfred Perlstein 5548360efbdSAlfred Perlstein /* 5558360efbdSAlfred Perlstein * Remove the mapping between program, version and netbuf address. 5568360efbdSAlfred Perlstein * Calls the rpcbind service to do the un-mapping. 5578360efbdSAlfred Perlstein * If netbuf is NULL, unset for all the transports, otherwise unset 5588360efbdSAlfred Perlstein * only for the given transport. 5598360efbdSAlfred Perlstein */ 5608360efbdSAlfred Perlstein bool_t 5618360efbdSAlfred Perlstein rpcb_unset(program, version, nconf) 5628360efbdSAlfred Perlstein rpcprog_t program; 5638360efbdSAlfred Perlstein rpcvers_t version; 5648360efbdSAlfred Perlstein const struct netconfig *nconf; 5658360efbdSAlfred Perlstein { 5668360efbdSAlfred Perlstein CLIENT *client; 5678360efbdSAlfred Perlstein bool_t rslt = FALSE; 5688360efbdSAlfred Perlstein RPCB parms; 5698360efbdSAlfred Perlstein char uidbuf[32]; 5708360efbdSAlfred Perlstein 5718360efbdSAlfred Perlstein client = local_rpcb(); 5728360efbdSAlfred Perlstein if (! client) { 5738360efbdSAlfred Perlstein return (FALSE); 5748360efbdSAlfred Perlstein } 5758360efbdSAlfred Perlstein 5768360efbdSAlfred Perlstein parms.r_prog = program; 5778360efbdSAlfred Perlstein parms.r_vers = version; 5788360efbdSAlfred Perlstein if (nconf) 5798360efbdSAlfred Perlstein parms.r_netid = nconf->nc_netid; 5808360efbdSAlfred Perlstein else { 5818360efbdSAlfred Perlstein /*LINTED const castaway*/ 5828360efbdSAlfred Perlstein parms.r_netid = (char *) &nullstring[0]; /* unsets all */ 5838360efbdSAlfred Perlstein } 5848360efbdSAlfred Perlstein /*LINTED const castaway*/ 5858360efbdSAlfred Perlstein parms.r_addr = (char *) &nullstring[0]; 5868360efbdSAlfred Perlstein (void) snprintf(uidbuf, sizeof uidbuf, "%d", geteuid()); 5878360efbdSAlfred Perlstein parms.r_owner = uidbuf; 5888360efbdSAlfred Perlstein 5898360efbdSAlfred Perlstein CLNT_CALL(client, (rpcproc_t)RPCBPROC_UNSET, (xdrproc_t) xdr_rpcb, 5908360efbdSAlfred Perlstein (char *)(void *)&parms, (xdrproc_t) xdr_bool, 5918360efbdSAlfred Perlstein (char *)(void *)&rslt, tottimeout); 5928360efbdSAlfred Perlstein 5938360efbdSAlfred Perlstein CLNT_DESTROY(client); 5948360efbdSAlfred Perlstein return (rslt); 5958360efbdSAlfred Perlstein } 5968360efbdSAlfred Perlstein 5978360efbdSAlfred Perlstein /* 5988360efbdSAlfred Perlstein * From the merged list, find the appropriate entry 5998360efbdSAlfred Perlstein */ 6008360efbdSAlfred Perlstein static struct netbuf * 6018360efbdSAlfred Perlstein got_entry(relp, nconf) 6028360efbdSAlfred Perlstein rpcb_entry_list_ptr relp; 6038360efbdSAlfred Perlstein const struct netconfig *nconf; 6048360efbdSAlfred Perlstein { 6058360efbdSAlfred Perlstein struct netbuf *na = NULL; 6068360efbdSAlfred Perlstein rpcb_entry_list_ptr sp; 6078360efbdSAlfred Perlstein rpcb_entry *rmap; 6088360efbdSAlfred Perlstein 6098360efbdSAlfred Perlstein for (sp = relp; sp != NULL; sp = sp->rpcb_entry_next) { 6108360efbdSAlfred Perlstein rmap = &sp->rpcb_entry_map; 6118360efbdSAlfred Perlstein if ((strcmp(nconf->nc_proto, rmap->r_nc_proto) == 0) && 6128360efbdSAlfred Perlstein (strcmp(nconf->nc_protofmly, rmap->r_nc_protofmly) == 0) && 6138360efbdSAlfred Perlstein (nconf->nc_semantics == rmap->r_nc_semantics) && 6148360efbdSAlfred Perlstein (rmap->r_maddr != NULL) && (rmap->r_maddr[0] != NULL)) { 6158360efbdSAlfred Perlstein na = uaddr2taddr(nconf, rmap->r_maddr); 6168360efbdSAlfred Perlstein #ifdef ND_DEBUG 6178360efbdSAlfred Perlstein fprintf(stderr, "\tRemote address is [%s].\n", 6188360efbdSAlfred Perlstein rmap->r_maddr); 6198360efbdSAlfred Perlstein if (!na) 6208360efbdSAlfred Perlstein fprintf(stderr, 6218360efbdSAlfred Perlstein "\tCouldn't resolve remote address!\n"); 6228360efbdSAlfred Perlstein #endif 6238360efbdSAlfred Perlstein break; 6248360efbdSAlfred Perlstein } 6258360efbdSAlfred Perlstein } 6268360efbdSAlfred Perlstein return (na); 6278360efbdSAlfred Perlstein } 6288360efbdSAlfred Perlstein 6298360efbdSAlfred Perlstein /* 6308360efbdSAlfred Perlstein * An internal function which optimizes rpcb_getaddr function. It also 6318360efbdSAlfred Perlstein * returns the client handle that it uses to contact the remote rpcbind. 6328360efbdSAlfred Perlstein * 6338360efbdSAlfred Perlstein * The algorithm used: If the transports is TCP or UDP, it first tries 6348360efbdSAlfred Perlstein * version 2 (portmap), 4 and then 3 (svr4). This order should be 6358360efbdSAlfred Perlstein * changed in the next OS release to 4, 2 and 3. We are assuming that by 6368360efbdSAlfred Perlstein * that time, version 4 would be available on many machines on the network. 6378360efbdSAlfred Perlstein * With this algorithm, we get performance as well as a plan for 6388360efbdSAlfred Perlstein * obsoleting version 2. 6398360efbdSAlfred Perlstein * 6408360efbdSAlfred Perlstein * For all other transports, the algorithm remains as 4 and then 3. 6418360efbdSAlfred Perlstein * 6428360efbdSAlfred Perlstein * XXX: Due to some problems with t_connect(), we do not reuse the same client 6438360efbdSAlfred Perlstein * handle for COTS cases and hence in these cases we do not return the 6448360efbdSAlfred Perlstein * client handle. This code will change if t_connect() ever 6458360efbdSAlfred Perlstein * starts working properly. Also look under clnt_vc.c. 6468360efbdSAlfred Perlstein */ 6478360efbdSAlfred Perlstein struct netbuf * 6488360efbdSAlfred Perlstein __rpcb_findaddr(program, version, nconf, host, clpp) 6498360efbdSAlfred Perlstein rpcprog_t program; 6508360efbdSAlfred Perlstein rpcvers_t version; 6518360efbdSAlfred Perlstein const struct netconfig *nconf; 6528360efbdSAlfred Perlstein const char *host; 6538360efbdSAlfred Perlstein CLIENT **clpp; 6548360efbdSAlfred Perlstein { 6558360efbdSAlfred Perlstein CLIENT *client = NULL; 6568360efbdSAlfred Perlstein RPCB parms; 6578360efbdSAlfred Perlstein enum clnt_stat clnt_st; 6588360efbdSAlfred Perlstein char *ua = NULL; 6598360efbdSAlfred Perlstein rpcvers_t vers; 6608360efbdSAlfred Perlstein struct netbuf *address = NULL; 6618360efbdSAlfred Perlstein rpcvers_t start_vers = RPCBVERS4; 6628360efbdSAlfred Perlstein struct netbuf servaddr; 6638360efbdSAlfred Perlstein 6648360efbdSAlfred Perlstein /* parameter checking */ 6658360efbdSAlfred Perlstein if (nconf == NULL) { 6668360efbdSAlfred Perlstein rpc_createerr.cf_stat = RPC_UNKNOWNPROTO; 6678360efbdSAlfred Perlstein return (NULL); 6688360efbdSAlfred Perlstein } 6698360efbdSAlfred Perlstein 6708360efbdSAlfred Perlstein parms.r_addr = NULL; 6718360efbdSAlfred Perlstein 6728360efbdSAlfred Perlstein #ifdef PORTMAP 6738360efbdSAlfred Perlstein /* Try version 2 for TCP or UDP */ 6748360efbdSAlfred Perlstein if (strcmp(nconf->nc_protofmly, NC_INET) == 0) { 6758360efbdSAlfred Perlstein u_short port = 0; 6768360efbdSAlfred Perlstein struct netbuf remote; 6778360efbdSAlfred Perlstein rpcvers_t pmapvers = 2; 6788360efbdSAlfred Perlstein struct pmap pmapparms; 6798360efbdSAlfred Perlstein 6808360efbdSAlfred Perlstein /* 6818360efbdSAlfred Perlstein * Try UDP only - there are some portmappers out 6828360efbdSAlfred Perlstein * there that use UDP only. 6838360efbdSAlfred Perlstein */ 6848360efbdSAlfred Perlstein if (strcmp(nconf->nc_proto, NC_TCP) == 0) { 6858360efbdSAlfred Perlstein struct netconfig *newnconf; 6868360efbdSAlfred Perlstein 6878360efbdSAlfred Perlstein if ((newnconf = getnetconfigent("udp")) == NULL) { 6888360efbdSAlfred Perlstein rpc_createerr.cf_stat = RPC_UNKNOWNPROTO; 6898360efbdSAlfred Perlstein return (NULL); 6908360efbdSAlfred Perlstein } 6918360efbdSAlfred Perlstein client = getclnthandle(host, newnconf, &parms.r_addr); 6928360efbdSAlfred Perlstein freenetconfigent(newnconf); 6938360efbdSAlfred Perlstein } else { 6948360efbdSAlfred Perlstein client = getclnthandle(host, nconf, &parms.r_addr); 6958360efbdSAlfred Perlstein } 6968360efbdSAlfred Perlstein if (client == NULL) { 6978360efbdSAlfred Perlstein return (NULL); 6988360efbdSAlfred Perlstein } 6998360efbdSAlfred Perlstein 7008360efbdSAlfred Perlstein /* Set the version */ 7018360efbdSAlfred Perlstein CLNT_CONTROL(client, CLSET_VERS, (char *)(void *)&pmapvers); 7028360efbdSAlfred Perlstein pmapparms.pm_prog = program; 7038360efbdSAlfred Perlstein pmapparms.pm_vers = version; 7048360efbdSAlfred Perlstein pmapparms.pm_prot = strcmp(nconf->nc_proto, NC_TCP) ? 7058360efbdSAlfred Perlstein IPPROTO_UDP : IPPROTO_TCP; 7068360efbdSAlfred Perlstein pmapparms.pm_port = 0; /* not needed */ 7078360efbdSAlfred Perlstein clnt_st = CLNT_CALL(client, (rpcproc_t)PMAPPROC_GETPORT, 7088360efbdSAlfred Perlstein (xdrproc_t) xdr_pmap, (caddr_t)(void *)&pmapparms, 7098360efbdSAlfred Perlstein (xdrproc_t) xdr_u_short, (caddr_t)(void *)&port, 7108360efbdSAlfred Perlstein tottimeout); 7118360efbdSAlfred Perlstein if (clnt_st != RPC_SUCCESS) { 7128360efbdSAlfred Perlstein if ((clnt_st == RPC_PROGVERSMISMATCH) || 7138360efbdSAlfred Perlstein (clnt_st == RPC_PROGUNAVAIL)) 7148360efbdSAlfred Perlstein goto try_rpcbind; /* Try different versions */ 7158360efbdSAlfred Perlstein rpc_createerr.cf_stat = RPC_PMAPFAILURE; 7168360efbdSAlfred Perlstein clnt_geterr(client, &rpc_createerr.cf_error); 7178360efbdSAlfred Perlstein goto error; 7188360efbdSAlfred Perlstein } else if (port == 0) { 7198360efbdSAlfred Perlstein address = NULL; 7208360efbdSAlfred Perlstein rpc_createerr.cf_stat = RPC_PROGNOTREGISTERED; 7218360efbdSAlfred Perlstein goto error; 7228360efbdSAlfred Perlstein } 7238360efbdSAlfred Perlstein port = htons(port); 7248360efbdSAlfred Perlstein CLNT_CONTROL(client, CLGET_SVC_ADDR, (char *)(void *)&remote); 7258360efbdSAlfred Perlstein if (((address = (struct netbuf *) 7268360efbdSAlfred Perlstein malloc(sizeof (struct netbuf))) == NULL) || 7278360efbdSAlfred Perlstein ((address->buf = (char *) 7288360efbdSAlfred Perlstein malloc(remote.len)) == NULL)) { 7298360efbdSAlfred Perlstein rpc_createerr.cf_stat = RPC_SYSTEMERROR; 7308360efbdSAlfred Perlstein clnt_geterr(client, &rpc_createerr.cf_error); 7318360efbdSAlfred Perlstein if (address) { 7328360efbdSAlfred Perlstein free(address); 7338360efbdSAlfred Perlstein address = NULL; 7348360efbdSAlfred Perlstein } 7358360efbdSAlfred Perlstein goto error; 7368360efbdSAlfred Perlstein } 7378360efbdSAlfred Perlstein memcpy(address->buf, remote.buf, remote.len); 7388360efbdSAlfred Perlstein memcpy(&((char *)address->buf)[sizeof (short)], 7398360efbdSAlfred Perlstein (char *)(void *)&port, sizeof (short)); 7408360efbdSAlfred Perlstein address->len = address->maxlen = remote.len; 7418360efbdSAlfred Perlstein goto done; 7428360efbdSAlfred Perlstein } 7438360efbdSAlfred Perlstein #endif /* PORTMAP */ 7448360efbdSAlfred Perlstein 7458360efbdSAlfred Perlstein try_rpcbind: 7468360efbdSAlfred Perlstein /* 7478360efbdSAlfred Perlstein * Now we try version 4 and then 3. 7488360efbdSAlfred Perlstein * We also send the remote system the address we used to 7498360efbdSAlfred Perlstein * contact it in case it can help to connect back with us 7508360efbdSAlfred Perlstein */ 7518360efbdSAlfred Perlstein parms.r_prog = program; 7528360efbdSAlfred Perlstein parms.r_vers = version; 7538360efbdSAlfred Perlstein /*LINTED const castaway*/ 7548360efbdSAlfred Perlstein parms.r_owner = (char *) &nullstring[0]; /* not needed; */ 7558360efbdSAlfred Perlstein /* just for xdring */ 7568360efbdSAlfred Perlstein parms.r_netid = nconf->nc_netid; /* not really needed */ 7578360efbdSAlfred Perlstein 7588360efbdSAlfred Perlstein /* 7598360efbdSAlfred Perlstein * If a COTS transport is being used, try getting address via CLTS 7608360efbdSAlfred Perlstein * transport. This works only with version 4. 7618360efbdSAlfred Perlstein * NOTE: This is being done for all transports EXCEPT LOOPBACK 7628360efbdSAlfred Perlstein * because with loopback the cost to go to a COTS is same as 7638360efbdSAlfred Perlstein * the cost to go through CLTS, plus you get the advantage of 7648360efbdSAlfred Perlstein * finding out immediately if the local rpcbind process is dead. 7658360efbdSAlfred Perlstein */ 7668360efbdSAlfred Perlstein #if 1 7678360efbdSAlfred Perlstein if ((nconf->nc_semantics == NC_TPI_COTS_ORD || 7688360efbdSAlfred Perlstein nconf->nc_semantics == NC_TPI_COTS) && 7698360efbdSAlfred Perlstein (strcmp(nconf->nc_protofmly, NC_LOOPBACK) != 0)) { 7708360efbdSAlfred Perlstein #else 7718360efbdSAlfred Perlstein if (client != NULL) { 7728360efbdSAlfred Perlstein CLNT_DESTROY(client); 7738360efbdSAlfred Perlstein client = NULL; 7748360efbdSAlfred Perlstein } 7758360efbdSAlfred Perlstein if (nconf->nc_semantics == NC_TPI_CLTS) { 7768360efbdSAlfred Perlstein #endif 7778360efbdSAlfred Perlstein void *handle; 7788360efbdSAlfred Perlstein struct netconfig *nconf_clts; 7798360efbdSAlfred Perlstein rpcb_entry_list_ptr relp = NULL; 7808360efbdSAlfred Perlstein 7818360efbdSAlfred Perlstein if (client == NULL) { 7828360efbdSAlfred Perlstein /* This did not go through the above PORTMAP/TCP code */ 7838360efbdSAlfred Perlstein #if 1 7848360efbdSAlfred Perlstein if ((handle = __rpc_setconf("datagram_v")) != NULL) { 7858360efbdSAlfred Perlstein #else 7868360efbdSAlfred Perlstein if ((handle = __rpc_setconf("circuit_v")) != NULL) { 7878360efbdSAlfred Perlstein #endif 7888360efbdSAlfred Perlstein while ((nconf_clts = __rpc_getconf(handle)) 7898360efbdSAlfred Perlstein != NULL) { 7908360efbdSAlfred Perlstein if (strcmp(nconf_clts->nc_protofmly, 7918360efbdSAlfred Perlstein nconf->nc_protofmly) != 0) { 7928360efbdSAlfred Perlstein continue; 7938360efbdSAlfred Perlstein } 7948360efbdSAlfred Perlstein client = getclnthandle(host, nconf_clts, 7958360efbdSAlfred Perlstein &parms.r_addr); 7968360efbdSAlfred Perlstein break; 7978360efbdSAlfred Perlstein } 7988360efbdSAlfred Perlstein __rpc_endconf(handle); 7998360efbdSAlfred Perlstein } 8008360efbdSAlfred Perlstein if (client == NULL) 8018360efbdSAlfred Perlstein goto regular_rpcbind; /* Go the regular way */ 8028360efbdSAlfred Perlstein } else { 8038360efbdSAlfred Perlstein /* This is a UDP PORTMAP handle. Change to version 4 */ 8048360efbdSAlfred Perlstein vers = RPCBVERS4; 8058360efbdSAlfred Perlstein CLNT_CONTROL(client, CLSET_VERS, (char *)(void *)&vers); 8068360efbdSAlfred Perlstein } 8078360efbdSAlfred Perlstein /* 8088360efbdSAlfred Perlstein * We also send the remote system the address we used to 8098360efbdSAlfred Perlstein * contact it in case it can help it connect back with us 8108360efbdSAlfred Perlstein */ 8118360efbdSAlfred Perlstein if (parms.r_addr == NULL) { 8128360efbdSAlfred Perlstein /*LINTED const castaway*/ 8138360efbdSAlfred Perlstein parms.r_addr = (char *) &nullstring[0]; /* for XDRing */ 8148360efbdSAlfred Perlstein } 8158360efbdSAlfred Perlstein clnt_st = CLNT_CALL(client, (rpcproc_t)RPCBPROC_GETADDRLIST, 8168360efbdSAlfred Perlstein (xdrproc_t) xdr_rpcb, (char *)(void *)&parms, 8178360efbdSAlfred Perlstein (xdrproc_t) xdr_rpcb_entry_list_ptr, 8188360efbdSAlfred Perlstein (char *)(void *)&relp, tottimeout); 8198360efbdSAlfred Perlstein if (clnt_st == RPC_SUCCESS) { 8208360efbdSAlfred Perlstein if ((address = got_entry(relp, nconf)) != NULL) { 8218360efbdSAlfred Perlstein xdr_free((xdrproc_t) xdr_rpcb_entry_list_ptr, 8228360efbdSAlfred Perlstein (char *)(void *)&relp); 8238360efbdSAlfred Perlstein goto done; 8248360efbdSAlfred Perlstein } 8258360efbdSAlfred Perlstein /* Entry not found for this transport */ 8268360efbdSAlfred Perlstein xdr_free((xdrproc_t) xdr_rpcb_entry_list_ptr, 8278360efbdSAlfred Perlstein (char *)(void *)&relp); 8288360efbdSAlfred Perlstein /* 8298360efbdSAlfred Perlstein * XXX: should have perhaps returned with error but 8308360efbdSAlfred Perlstein * since the remote machine might not always be able 8318360efbdSAlfred Perlstein * to send the address on all transports, we try the 8328360efbdSAlfred Perlstein * regular way with regular_rpcbind 8338360efbdSAlfred Perlstein */ 8348360efbdSAlfred Perlstein goto regular_rpcbind; 8358360efbdSAlfred Perlstein } else if ((clnt_st == RPC_PROGVERSMISMATCH) || 8368360efbdSAlfred Perlstein (clnt_st == RPC_PROGUNAVAIL)) { 8378360efbdSAlfred Perlstein start_vers = RPCBVERS; /* Try version 3 now */ 8388360efbdSAlfred Perlstein goto regular_rpcbind; /* Try different versions */ 8398360efbdSAlfred Perlstein } else { 8408360efbdSAlfred Perlstein rpc_createerr.cf_stat = RPC_PMAPFAILURE; 8418360efbdSAlfred Perlstein clnt_geterr(client, &rpc_createerr.cf_error); 8428360efbdSAlfred Perlstein goto error; 8438360efbdSAlfred Perlstein } 8448360efbdSAlfred Perlstein } 8458360efbdSAlfred Perlstein 8468360efbdSAlfred Perlstein regular_rpcbind: 8478360efbdSAlfred Perlstein 8488360efbdSAlfred Perlstein /* Now the same transport is to be used to get the address */ 8498360efbdSAlfred Perlstein #if 1 8508360efbdSAlfred Perlstein if (client && ((nconf->nc_semantics == NC_TPI_COTS_ORD) || 8518360efbdSAlfred Perlstein (nconf->nc_semantics == NC_TPI_COTS))) { 8528360efbdSAlfred Perlstein #else 8538360efbdSAlfred Perlstein if (client && nconf->nc_semantics == NC_TPI_CLTS) { 8548360efbdSAlfred Perlstein #endif 8558360efbdSAlfred Perlstein /* A CLTS type of client - destroy it */ 8568360efbdSAlfred Perlstein CLNT_DESTROY(client); 8578360efbdSAlfred Perlstein client = NULL; 8588360efbdSAlfred Perlstein } 8598360efbdSAlfred Perlstein 8608360efbdSAlfred Perlstein if (client == NULL) { 8618360efbdSAlfred Perlstein client = getclnthandle(host, nconf, &parms.r_addr); 8628360efbdSAlfred Perlstein if (client == NULL) { 8638360efbdSAlfred Perlstein goto error; 8648360efbdSAlfred Perlstein } 8658360efbdSAlfred Perlstein } 8668360efbdSAlfred Perlstein if (parms.r_addr == NULL) { 8678360efbdSAlfred Perlstein /*LINTED const castaway*/ 8688360efbdSAlfred Perlstein parms.r_addr = (char *) &nullstring[0]; 8698360efbdSAlfred Perlstein } 8708360efbdSAlfred Perlstein 8718360efbdSAlfred Perlstein /* First try from start_vers and then version 3 (RPCBVERS) */ 8728360efbdSAlfred Perlstein for (vers = start_vers; vers >= RPCBVERS; vers--) { 8738360efbdSAlfred Perlstein /* Set the version */ 8748360efbdSAlfred Perlstein CLNT_CONTROL(client, CLSET_VERS, (char *)(void *)&vers); 8758360efbdSAlfred Perlstein clnt_st = CLNT_CALL(client, (rpcproc_t)RPCBPROC_GETADDR, 8768360efbdSAlfred Perlstein (xdrproc_t) xdr_rpcb, (char *)(void *)&parms, 8778360efbdSAlfred Perlstein (xdrproc_t) xdr_wrapstring, (char *)(void *) &ua, 8788360efbdSAlfred Perlstein tottimeout); 8798360efbdSAlfred Perlstein if (clnt_st == RPC_SUCCESS) { 8808360efbdSAlfred Perlstein if ((ua == NULL) || (ua[0] == NULL)) { 8818360efbdSAlfred Perlstein /* address unknown */ 8828360efbdSAlfred Perlstein rpc_createerr.cf_stat = RPC_PROGNOTREGISTERED; 8838360efbdSAlfred Perlstein goto error; 8848360efbdSAlfred Perlstein } 8858360efbdSAlfred Perlstein address = uaddr2taddr(nconf, ua); 8868360efbdSAlfred Perlstein #ifdef ND_DEBUG 8878360efbdSAlfred Perlstein fprintf(stderr, "\tRemote address is [%s]\n", ua); 8888360efbdSAlfred Perlstein if (!address) 8898360efbdSAlfred Perlstein fprintf(stderr, 8908360efbdSAlfred Perlstein "\tCouldn't resolve remote address!\n"); 8918360efbdSAlfred Perlstein #endif 8928360efbdSAlfred Perlstein xdr_free((xdrproc_t)xdr_wrapstring, 8938360efbdSAlfred Perlstein (char *)(void *)&ua); 8948360efbdSAlfred Perlstein 8958360efbdSAlfred Perlstein if (! address) { 8968360efbdSAlfred Perlstein /* We don't know about your universal address */ 8978360efbdSAlfred Perlstein rpc_createerr.cf_stat = RPC_N2AXLATEFAILURE; 8988360efbdSAlfred Perlstein goto error; 8998360efbdSAlfred Perlstein } 9008360efbdSAlfred Perlstein CLNT_CONTROL(client, CLGET_SVC_ADDR, 9018360efbdSAlfred Perlstein (char *)(void *)&servaddr); 9028360efbdSAlfred Perlstein __rpc_fixup_addr(address, &servaddr); 9038360efbdSAlfred Perlstein goto done; 9048360efbdSAlfred Perlstein } else if (clnt_st == RPC_PROGVERSMISMATCH) { 9058360efbdSAlfred Perlstein struct rpc_err rpcerr; 9068360efbdSAlfred Perlstein 9078360efbdSAlfred Perlstein clnt_geterr(client, &rpcerr); 9088360efbdSAlfred Perlstein if (rpcerr.re_vers.low > RPCBVERS4) 9098360efbdSAlfred Perlstein goto error; /* a new version, can't handle */ 9108360efbdSAlfred Perlstein } else if (clnt_st != RPC_PROGUNAVAIL) { 9118360efbdSAlfred Perlstein /* Cant handle this error */ 9128360efbdSAlfred Perlstein rpc_createerr.cf_stat = clnt_st; 9138360efbdSAlfred Perlstein clnt_geterr(client, &rpc_createerr.cf_error); 9148360efbdSAlfred Perlstein goto error; 9158360efbdSAlfred Perlstein } 9168360efbdSAlfred Perlstein } 9178360efbdSAlfred Perlstein 9188360efbdSAlfred Perlstein if ((address == NULL) || (address->len == 0)) { 9198360efbdSAlfred Perlstein rpc_createerr.cf_stat = RPC_PROGNOTREGISTERED; 9208360efbdSAlfred Perlstein clnt_geterr(client, &rpc_createerr.cf_error); 9218360efbdSAlfred Perlstein } 9228360efbdSAlfred Perlstein 9238360efbdSAlfred Perlstein error: 9248360efbdSAlfred Perlstein if (client) { 9258360efbdSAlfred Perlstein CLNT_DESTROY(client); 9268360efbdSAlfred Perlstein client = NULL; 9278360efbdSAlfred Perlstein } 9288360efbdSAlfred Perlstein done: 9298360efbdSAlfred Perlstein if (nconf->nc_semantics != NC_TPI_CLTS) { 9308360efbdSAlfred Perlstein /* This client is the connectionless one */ 9318360efbdSAlfred Perlstein if (client) { 9328360efbdSAlfred Perlstein CLNT_DESTROY(client); 9338360efbdSAlfred Perlstein client = NULL; 9348360efbdSAlfred Perlstein } 9358360efbdSAlfred Perlstein } 9368360efbdSAlfred Perlstein if (clpp) { 9378360efbdSAlfred Perlstein *clpp = client; 9388360efbdSAlfred Perlstein } else if (client) { 9398360efbdSAlfred Perlstein CLNT_DESTROY(client); 9408360efbdSAlfred Perlstein } 9418360efbdSAlfred Perlstein return (address); 9428360efbdSAlfred Perlstein } 9438360efbdSAlfred Perlstein 9448360efbdSAlfred Perlstein 9458360efbdSAlfred Perlstein /* 9468360efbdSAlfred Perlstein * Find the mapped address for program, version. 9478360efbdSAlfred Perlstein * Calls the rpcbind service remotely to do the lookup. 9488360efbdSAlfred Perlstein * Uses the transport specified in nconf. 9498360efbdSAlfred Perlstein * Returns FALSE (0) if no map exists, else returns 1. 9508360efbdSAlfred Perlstein * 9518360efbdSAlfred Perlstein * Assuming that the address is all properly allocated 9528360efbdSAlfred Perlstein */ 9538360efbdSAlfred Perlstein int 9548360efbdSAlfred Perlstein rpcb_getaddr(program, version, nconf, address, host) 9558360efbdSAlfred Perlstein rpcprog_t program; 9568360efbdSAlfred Perlstein rpcvers_t version; 9578360efbdSAlfred Perlstein const struct netconfig *nconf; 9588360efbdSAlfred Perlstein struct netbuf *address; 9598360efbdSAlfred Perlstein const char *host; 9608360efbdSAlfred Perlstein { 9618360efbdSAlfred Perlstein struct netbuf *na; 9628360efbdSAlfred Perlstein 9638360efbdSAlfred Perlstein if ((na = __rpcb_findaddr(program, version, nconf, 9648360efbdSAlfred Perlstein host, (CLIENT **) NULL)) == NULL) 9658360efbdSAlfred Perlstein return (FALSE); 9668360efbdSAlfred Perlstein 9678360efbdSAlfred Perlstein if (na->len > address->maxlen) { 9688360efbdSAlfred Perlstein /* Too long address */ 9698360efbdSAlfred Perlstein free(na->buf); 9708360efbdSAlfred Perlstein free(na); 9718360efbdSAlfred Perlstein rpc_createerr.cf_stat = RPC_FAILED; 9728360efbdSAlfred Perlstein return (FALSE); 9738360efbdSAlfred Perlstein } 9748360efbdSAlfred Perlstein memcpy(address->buf, na->buf, (size_t)na->len); 9758360efbdSAlfred Perlstein address->len = na->len; 9768360efbdSAlfred Perlstein free(na->buf); 9778360efbdSAlfred Perlstein free(na); 9788360efbdSAlfred Perlstein return (TRUE); 9798360efbdSAlfred Perlstein } 9808360efbdSAlfred Perlstein 9818360efbdSAlfred Perlstein /* 9828360efbdSAlfred Perlstein * Get a copy of the current maps. 9838360efbdSAlfred Perlstein * Calls the rpcbind service remotely to get the maps. 9848360efbdSAlfred Perlstein * 9858360efbdSAlfred Perlstein * It returns only a list of the services 9868360efbdSAlfred Perlstein * It returns NULL on failure. 9878360efbdSAlfred Perlstein */ 9888360efbdSAlfred Perlstein rpcblist * 9898360efbdSAlfred Perlstein rpcb_getmaps(nconf, host) 9908360efbdSAlfred Perlstein const struct netconfig *nconf; 9918360efbdSAlfred Perlstein const char *host; 9928360efbdSAlfred Perlstein { 9938360efbdSAlfred Perlstein rpcblist_ptr head = NULL; 9948360efbdSAlfred Perlstein CLIENT *client; 9958360efbdSAlfred Perlstein enum clnt_stat clnt_st; 9968360efbdSAlfred Perlstein rpcvers_t vers = 0; 9978360efbdSAlfred Perlstein 9988360efbdSAlfred Perlstein client = getclnthandle(host, nconf, NULL); 9998360efbdSAlfred Perlstein if (client == NULL) { 10008360efbdSAlfred Perlstein return (head); 10018360efbdSAlfred Perlstein } 10028360efbdSAlfred Perlstein clnt_st = CLNT_CALL(client, (rpcproc_t)RPCBPROC_DUMP, 10038360efbdSAlfred Perlstein (xdrproc_t) xdr_void, NULL, (xdrproc_t) xdr_rpcblist_ptr, 10048360efbdSAlfred Perlstein (char *)(void *)&head, tottimeout); 10058360efbdSAlfred Perlstein if (clnt_st == RPC_SUCCESS) 10068360efbdSAlfred Perlstein goto done; 10078360efbdSAlfred Perlstein 10088360efbdSAlfred Perlstein if ((clnt_st != RPC_PROGVERSMISMATCH) && 10098360efbdSAlfred Perlstein (clnt_st != RPC_PROGUNAVAIL)) { 10108360efbdSAlfred Perlstein rpc_createerr.cf_stat = RPC_RPCBFAILURE; 10118360efbdSAlfred Perlstein clnt_geterr(client, &rpc_createerr.cf_error); 10128360efbdSAlfred Perlstein goto done; 10138360efbdSAlfred Perlstein } 10148360efbdSAlfred Perlstein 10158360efbdSAlfred Perlstein /* fall back to earlier version */ 10168360efbdSAlfred Perlstein CLNT_CONTROL(client, CLGET_VERS, (char *)(void *)&vers); 10178360efbdSAlfred Perlstein if (vers == RPCBVERS4) { 10188360efbdSAlfred Perlstein vers = RPCBVERS; 10198360efbdSAlfred Perlstein CLNT_CONTROL(client, CLSET_VERS, (char *)(void *)&vers); 10208360efbdSAlfred Perlstein if (CLNT_CALL(client, (rpcproc_t)RPCBPROC_DUMP, 10218360efbdSAlfred Perlstein (xdrproc_t) xdr_void, NULL, (xdrproc_t) xdr_rpcblist_ptr, 10228360efbdSAlfred Perlstein (char *)(void *)&head, tottimeout) == RPC_SUCCESS) 10238360efbdSAlfred Perlstein goto done; 10248360efbdSAlfred Perlstein } 10258360efbdSAlfred Perlstein rpc_createerr.cf_stat = RPC_RPCBFAILURE; 10268360efbdSAlfred Perlstein clnt_geterr(client, &rpc_createerr.cf_error); 10278360efbdSAlfred Perlstein 10288360efbdSAlfred Perlstein done: 10298360efbdSAlfred Perlstein CLNT_DESTROY(client); 10308360efbdSAlfred Perlstein return (head); 10318360efbdSAlfred Perlstein } 10328360efbdSAlfred Perlstein 10338360efbdSAlfred Perlstein /* 10348360efbdSAlfred Perlstein * rpcbinder remote-call-service interface. 10358360efbdSAlfred Perlstein * This routine is used to call the rpcbind remote call service 10368360efbdSAlfred Perlstein * which will look up a service program in the address maps, and then 10378360efbdSAlfred Perlstein * remotely call that routine with the given parameters. This allows 10388360efbdSAlfred Perlstein * programs to do a lookup and call in one step. 10398360efbdSAlfred Perlstein */ 10408360efbdSAlfred Perlstein enum clnt_stat 10418360efbdSAlfred Perlstein rpcb_rmtcall(nconf, host, prog, vers, proc, xdrargs, argsp, 10428360efbdSAlfred Perlstein xdrres, resp, tout, addr_ptr) 10438360efbdSAlfred Perlstein const struct netconfig *nconf; /* Netconfig structure */ 10448360efbdSAlfred Perlstein const char *host; /* Remote host name */ 10458360efbdSAlfred Perlstein rpcprog_t prog; 10468360efbdSAlfred Perlstein rpcvers_t vers; 10478360efbdSAlfred Perlstein rpcproc_t proc; /* Remote proc identifiers */ 10488360efbdSAlfred Perlstein xdrproc_t xdrargs, xdrres; /* XDR routines */ 10498360efbdSAlfred Perlstein caddr_t argsp, resp; /* Argument and Result */ 10508360efbdSAlfred Perlstein struct timeval tout; /* Timeout value for this call */ 10518360efbdSAlfred Perlstein const struct netbuf *addr_ptr; /* Preallocated netbuf address */ 10528360efbdSAlfred Perlstein { 10538360efbdSAlfred Perlstein CLIENT *client; 10548360efbdSAlfred Perlstein enum clnt_stat stat; 10558360efbdSAlfred Perlstein struct r_rpcb_rmtcallargs a; 10568360efbdSAlfred Perlstein struct r_rpcb_rmtcallres r; 10578360efbdSAlfred Perlstein rpcvers_t rpcb_vers; 10588360efbdSAlfred Perlstein 10598360efbdSAlfred Perlstein 10608360efbdSAlfred Perlstein client = getclnthandle(host, nconf, NULL); 10618360efbdSAlfred Perlstein if (client == NULL) { 10628360efbdSAlfred Perlstein return (RPC_FAILED); 10638360efbdSAlfred Perlstein } 10648360efbdSAlfred Perlstein /*LINTED const castaway*/ 10658360efbdSAlfred Perlstein CLNT_CONTROL(client, CLSET_RETRY_TIMEOUT, (char *)(void *)&rmttimeout); 10668360efbdSAlfred Perlstein a.prog = prog; 10678360efbdSAlfred Perlstein a.vers = vers; 10688360efbdSAlfred Perlstein a.proc = proc; 10698360efbdSAlfred Perlstein a.args.args_val = argsp; 10708360efbdSAlfred Perlstein a.xdr_args = xdrargs; 10718360efbdSAlfred Perlstein r.addr = NULL; 10728360efbdSAlfred Perlstein r.results.results_val = resp; 10738360efbdSAlfred Perlstein r.xdr_res = xdrres; 10748360efbdSAlfred Perlstein 10758360efbdSAlfred Perlstein for (rpcb_vers = RPCBVERS4; rpcb_vers >= RPCBVERS; rpcb_vers--) { 10768360efbdSAlfred Perlstein CLNT_CONTROL(client, CLSET_VERS, (char *)(void *)&rpcb_vers); 10778360efbdSAlfred Perlstein stat = CLNT_CALL(client, (rpcproc_t)RPCBPROC_CALLIT, 10788360efbdSAlfred Perlstein (xdrproc_t) xdr_rpcb_rmtcallargs, (char *)(void *)&a, 10798360efbdSAlfred Perlstein (xdrproc_t) xdr_rpcb_rmtcallres, (char *)(void *)&r, tout); 10808360efbdSAlfred Perlstein if ((stat == RPC_SUCCESS) && (addr_ptr != NULL)) { 10818360efbdSAlfred Perlstein struct netbuf *na; 10828360efbdSAlfred Perlstein /*LINTED const castaway*/ 10838360efbdSAlfred Perlstein na = uaddr2taddr((struct netconfig *) nconf, r.addr); 10848360efbdSAlfred Perlstein if (!na) { 10858360efbdSAlfred Perlstein stat = RPC_N2AXLATEFAILURE; 10868360efbdSAlfred Perlstein /*LINTED const castaway*/ 10878360efbdSAlfred Perlstein ((struct netbuf *) addr_ptr)->len = 0; 10888360efbdSAlfred Perlstein goto error; 10898360efbdSAlfred Perlstein } 10908360efbdSAlfred Perlstein if (na->len > addr_ptr->maxlen) { 10918360efbdSAlfred Perlstein /* Too long address */ 10928360efbdSAlfred Perlstein stat = RPC_FAILED; /* XXX A better error no */ 10938360efbdSAlfred Perlstein free(na->buf); 10948360efbdSAlfred Perlstein free(na); 10958360efbdSAlfred Perlstein /*LINTED const castaway*/ 10968360efbdSAlfred Perlstein ((struct netbuf *) addr_ptr)->len = 0; 10978360efbdSAlfred Perlstein goto error; 10988360efbdSAlfred Perlstein } 10998360efbdSAlfred Perlstein memcpy(addr_ptr->buf, na->buf, (size_t)na->len); 11008360efbdSAlfred Perlstein /*LINTED const castaway*/ 11018360efbdSAlfred Perlstein ((struct netbuf *)addr_ptr)->len = na->len; 11028360efbdSAlfred Perlstein free(na->buf); 11038360efbdSAlfred Perlstein free(na); 11048360efbdSAlfred Perlstein break; 11058360efbdSAlfred Perlstein } else if ((stat != RPC_PROGVERSMISMATCH) && 11068360efbdSAlfred Perlstein (stat != RPC_PROGUNAVAIL)) { 11078360efbdSAlfred Perlstein goto error; 11088360efbdSAlfred Perlstein } 11098360efbdSAlfred Perlstein } 11108360efbdSAlfred Perlstein error: 11118360efbdSAlfred Perlstein CLNT_DESTROY(client); 11128360efbdSAlfred Perlstein if (r.addr) 11138360efbdSAlfred Perlstein xdr_free((xdrproc_t) xdr_wrapstring, (char *)(void *)&r.addr); 11148360efbdSAlfred Perlstein return (stat); 11158360efbdSAlfred Perlstein } 11168360efbdSAlfred Perlstein 11178360efbdSAlfred Perlstein /* 11188360efbdSAlfred Perlstein * Gets the time on the remote host. 11198360efbdSAlfred Perlstein * Returns 1 if succeeds else 0. 11208360efbdSAlfred Perlstein */ 11218360efbdSAlfred Perlstein bool_t 11228360efbdSAlfred Perlstein rpcb_gettime(host, timep) 11238360efbdSAlfred Perlstein const char *host; 11248360efbdSAlfred Perlstein time_t *timep; 11258360efbdSAlfred Perlstein { 11268360efbdSAlfred Perlstein CLIENT *client = NULL; 11278360efbdSAlfred Perlstein void *handle; 11288360efbdSAlfred Perlstein struct netconfig *nconf; 11298360efbdSAlfred Perlstein rpcvers_t vers; 11308360efbdSAlfred Perlstein enum clnt_stat st; 11318360efbdSAlfred Perlstein 11328360efbdSAlfred Perlstein 11338360efbdSAlfred Perlstein if ((host == NULL) || (host[0] == NULL)) { 11348360efbdSAlfred Perlstein time(timep); 11358360efbdSAlfred Perlstein return (TRUE); 11368360efbdSAlfred Perlstein } 11378360efbdSAlfred Perlstein 11388360efbdSAlfred Perlstein if ((handle = __rpc_setconf("netpath")) == NULL) { 11398360efbdSAlfred Perlstein rpc_createerr.cf_stat = RPC_UNKNOWNPROTO; 11408360efbdSAlfred Perlstein return (FALSE); 11418360efbdSAlfred Perlstein } 11428360efbdSAlfred Perlstein rpc_createerr.cf_stat = RPC_SUCCESS; 11438360efbdSAlfred Perlstein while (client == NULL) { 11448360efbdSAlfred Perlstein if ((nconf = __rpc_getconf(handle)) == NULL) { 11458360efbdSAlfred Perlstein if (rpc_createerr.cf_stat == RPC_SUCCESS) 11468360efbdSAlfred Perlstein rpc_createerr.cf_stat = RPC_UNKNOWNPROTO; 11478360efbdSAlfred Perlstein break; 11488360efbdSAlfred Perlstein } 11498360efbdSAlfred Perlstein client = getclnthandle(host, nconf, NULL); 11508360efbdSAlfred Perlstein if (client) 11518360efbdSAlfred Perlstein break; 11528360efbdSAlfred Perlstein } 11538360efbdSAlfred Perlstein __rpc_endconf(handle); 11548360efbdSAlfred Perlstein if (client == (CLIENT *) NULL) { 11558360efbdSAlfred Perlstein return (FALSE); 11568360efbdSAlfred Perlstein } 11578360efbdSAlfred Perlstein 11588360efbdSAlfred Perlstein st = CLNT_CALL(client, (rpcproc_t)RPCBPROC_GETTIME, 11598360efbdSAlfred Perlstein (xdrproc_t) xdr_void, NULL, 11608360efbdSAlfred Perlstein (xdrproc_t) xdr_int, (char *)(void *)timep, tottimeout); 11618360efbdSAlfred Perlstein 11628360efbdSAlfred Perlstein if ((st == RPC_PROGVERSMISMATCH) || (st == RPC_PROGUNAVAIL)) { 11638360efbdSAlfred Perlstein CLNT_CONTROL(client, CLGET_VERS, (char *)(void *)&vers); 11648360efbdSAlfred Perlstein if (vers == RPCBVERS4) { 11658360efbdSAlfred Perlstein /* fall back to earlier version */ 11668360efbdSAlfred Perlstein vers = RPCBVERS; 11678360efbdSAlfred Perlstein CLNT_CONTROL(client, CLSET_VERS, (char *)(void *)&vers); 11688360efbdSAlfred Perlstein st = CLNT_CALL(client, (rpcproc_t)RPCBPROC_GETTIME, 11698360efbdSAlfred Perlstein (xdrproc_t) xdr_void, NULL, 11708360efbdSAlfred Perlstein (xdrproc_t) xdr_int, (char *)(void *)timep, 11718360efbdSAlfred Perlstein tottimeout); 11728360efbdSAlfred Perlstein } 11738360efbdSAlfred Perlstein } 11748360efbdSAlfred Perlstein CLNT_DESTROY(client); 11758360efbdSAlfred Perlstein return (st == RPC_SUCCESS? TRUE: FALSE); 11768360efbdSAlfred Perlstein } 11778360efbdSAlfred Perlstein 11788360efbdSAlfred Perlstein /* 11798360efbdSAlfred Perlstein * Converts taddr to universal address. This routine should never 11808360efbdSAlfred Perlstein * really be called because local n2a libraries are always provided. 11818360efbdSAlfred Perlstein */ 11828360efbdSAlfred Perlstein char * 11838360efbdSAlfred Perlstein rpcb_taddr2uaddr(nconf, taddr) 11848360efbdSAlfred Perlstein struct netconfig *nconf; 11858360efbdSAlfred Perlstein struct netbuf *taddr; 11868360efbdSAlfred Perlstein { 11878360efbdSAlfred Perlstein CLIENT *client; 11888360efbdSAlfred Perlstein char *uaddr = NULL; 11898360efbdSAlfred Perlstein 11908360efbdSAlfred Perlstein 11918360efbdSAlfred Perlstein /* parameter checking */ 11928360efbdSAlfred Perlstein if (nconf == NULL) { 11938360efbdSAlfred Perlstein rpc_createerr.cf_stat = RPC_UNKNOWNPROTO; 11948360efbdSAlfred Perlstein return (NULL); 11958360efbdSAlfred Perlstein } 11968360efbdSAlfred Perlstein if (taddr == NULL) { 11978360efbdSAlfred Perlstein rpc_createerr.cf_stat = RPC_UNKNOWNADDR; 11988360efbdSAlfred Perlstein return (NULL); 11998360efbdSAlfred Perlstein } 12008360efbdSAlfred Perlstein client = local_rpcb(); 12018360efbdSAlfred Perlstein if (! client) { 12028360efbdSAlfred Perlstein return (NULL); 12038360efbdSAlfred Perlstein } 12048360efbdSAlfred Perlstein 12058360efbdSAlfred Perlstein CLNT_CALL(client, (rpcproc_t)RPCBPROC_TADDR2UADDR, 12068360efbdSAlfred Perlstein (xdrproc_t) xdr_netbuf, (char *)(void *)taddr, 12078360efbdSAlfred Perlstein (xdrproc_t) xdr_wrapstring, (char *)(void *)&uaddr, tottimeout); 12088360efbdSAlfred Perlstein CLNT_DESTROY(client); 12098360efbdSAlfred Perlstein return (uaddr); 12108360efbdSAlfred Perlstein } 12118360efbdSAlfred Perlstein 12128360efbdSAlfred Perlstein /* 12138360efbdSAlfred Perlstein * Converts universal address to netbuf. This routine should never 12148360efbdSAlfred Perlstein * really be called because local n2a libraries are always provided. 12158360efbdSAlfred Perlstein */ 12168360efbdSAlfred Perlstein struct netbuf * 12178360efbdSAlfred Perlstein rpcb_uaddr2taddr(nconf, uaddr) 12188360efbdSAlfred Perlstein struct netconfig *nconf; 12198360efbdSAlfred Perlstein char *uaddr; 12208360efbdSAlfred Perlstein { 12218360efbdSAlfred Perlstein CLIENT *client; 12228360efbdSAlfred Perlstein struct netbuf *taddr; 12238360efbdSAlfred Perlstein 12248360efbdSAlfred Perlstein 12258360efbdSAlfred Perlstein /* parameter checking */ 12268360efbdSAlfred Perlstein if (nconf == NULL) { 12278360efbdSAlfred Perlstein rpc_createerr.cf_stat = RPC_UNKNOWNPROTO; 12288360efbdSAlfred Perlstein return (NULL); 12298360efbdSAlfred Perlstein } 12308360efbdSAlfred Perlstein if (uaddr == NULL) { 12318360efbdSAlfred Perlstein rpc_createerr.cf_stat = RPC_UNKNOWNADDR; 12328360efbdSAlfred Perlstein return (NULL); 12338360efbdSAlfred Perlstein } 12348360efbdSAlfred Perlstein client = local_rpcb(); 12358360efbdSAlfred Perlstein if (! client) { 12368360efbdSAlfred Perlstein return (NULL); 12378360efbdSAlfred Perlstein } 12388360efbdSAlfred Perlstein 12398360efbdSAlfred Perlstein taddr = (struct netbuf *)calloc(1, sizeof (struct netbuf)); 12408360efbdSAlfred Perlstein if (taddr == NULL) { 12418360efbdSAlfred Perlstein CLNT_DESTROY(client); 12428360efbdSAlfred Perlstein return (NULL); 12438360efbdSAlfred Perlstein } 12448360efbdSAlfred Perlstein if (CLNT_CALL(client, (rpcproc_t)RPCBPROC_UADDR2TADDR, 12458360efbdSAlfred Perlstein (xdrproc_t) xdr_wrapstring, (char *)(void *)&uaddr, 12468360efbdSAlfred Perlstein (xdrproc_t) xdr_netbuf, (char *)(void *)taddr, 12478360efbdSAlfred Perlstein tottimeout) != RPC_SUCCESS) { 12488360efbdSAlfred Perlstein free(taddr); 12498360efbdSAlfred Perlstein taddr = NULL; 12508360efbdSAlfred Perlstein } 12518360efbdSAlfred Perlstein CLNT_DESTROY(client); 12528360efbdSAlfred Perlstein return (taddr); 12538360efbdSAlfred Perlstein } 1254