18360efbdSAlfred Perlstein /* $NetBSD: rpcb_clnt.c,v 1.6 2000/07/16 06:41:43 itojun Exp $ */ 28360efbdSAlfred Perlstein 344443e42SHiroki Sato /*- 444443e42SHiroki Sato * Copyright (c) 2010, Oracle America, Inc. 544443e42SHiroki Sato * All rights reserved. 64e37855eSAlfred Perlstein * 744443e42SHiroki Sato * Redistribution and use in source and binary forms, with or without 844443e42SHiroki Sato * modification, are permitted provided that the following conditions are met: 944443e42SHiroki Sato * - Redistributions of source code must retain the above copyright notice, 1044443e42SHiroki Sato * this list of conditions and the following disclaimer. 1144443e42SHiroki Sato * - Redistributions in binary form must reproduce the above copyright notice, 1244443e42SHiroki Sato * this list of conditions and the following disclaimer in the documentation 1344443e42SHiroki Sato * and/or other materials provided with the distribution. 1444443e42SHiroki Sato * - Neither the name of the "Oracle America, Inc." nor the names of its 1544443e42SHiroki Sato * contributors may be used to endorse or promote products derived 1644443e42SHiroki Sato * from this software without specific prior written permission. 174e37855eSAlfred Perlstein * 1844443e42SHiroki Sato * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 1944443e42SHiroki Sato * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2044443e42SHiroki Sato * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2144443e42SHiroki Sato * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 2244443e42SHiroki Sato * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 2344443e42SHiroki Sato * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 2444443e42SHiroki Sato * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 2544443e42SHiroki Sato * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 2644443e42SHiroki Sato * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 2744443e42SHiroki Sato * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 2844443e42SHiroki Sato * POSSIBILITY OF SUCH DAMAGE. 298360efbdSAlfred Perlstein */ 308360efbdSAlfred Perlstein 318360efbdSAlfred Perlstein /* #ident "@(#)rpcb_clnt.c 1.27 94/04/24 SMI" */ 328360efbdSAlfred Perlstein 338360efbdSAlfred Perlstein 34a986ef57SDavid E. O'Brien #if defined(LIBC_SCCS) && !defined(lint) 358360efbdSAlfred Perlstein static char sccsid[] = "@(#)rpcb_clnt.c 1.30 89/06/21 Copyr 1988 Sun Micro"; 368360efbdSAlfred Perlstein #endif 37d3d20c82SDavid E. O'Brien #include <sys/cdefs.h> 38d3d20c82SDavid E. O'Brien __FBSDID("$FreeBSD$"); 398360efbdSAlfred Perlstein 408360efbdSAlfred Perlstein /* 418360efbdSAlfred Perlstein * rpcb_clnt.c 428360efbdSAlfred Perlstein * interface to rpcbind rpc service. 438360efbdSAlfred Perlstein */ 448360efbdSAlfred Perlstein 458360efbdSAlfred Perlstein #include "namespace.h" 469f5afc13SIan Dowse #include "reentrant.h" 478360efbdSAlfred Perlstein #include <sys/types.h> 488360efbdSAlfred Perlstein #include <sys/socket.h> 498360efbdSAlfred Perlstein #include <sys/un.h> 508360efbdSAlfred Perlstein #include <sys/utsname.h> 518360efbdSAlfred Perlstein #include <rpc/rpc.h> 528360efbdSAlfred Perlstein #include <rpc/rpcb_prot.h> 538360efbdSAlfred Perlstein #include <rpc/nettype.h> 548360efbdSAlfred Perlstein #include <netconfig.h> 558360efbdSAlfred Perlstein #ifdef PORTMAP 568360efbdSAlfred Perlstein #include <netinet/in.h> /* FOR IPPROTO_TCP/UDP definitions */ 578360efbdSAlfred Perlstein #include <rpc/pmap_prot.h> 588360efbdSAlfred Perlstein #endif /* PORTMAP */ 598360efbdSAlfred Perlstein #include <stdio.h> 608360efbdSAlfred Perlstein #include <errno.h> 618360efbdSAlfred Perlstein #include <stdlib.h> 628360efbdSAlfred Perlstein #include <string.h> 638360efbdSAlfred Perlstein #include <unistd.h> 648360efbdSAlfred Perlstein #include <netdb.h> 658360efbdSAlfred Perlstein #include <syslog.h> 668360efbdSAlfred Perlstein #include "un-namespace.h" 678360efbdSAlfred Perlstein 688360efbdSAlfred Perlstein #include "rpc_com.h" 69235baf26SDaniel Eischen #include "mt_misc.h" 708360efbdSAlfred Perlstein 718360efbdSAlfred Perlstein static struct timeval tottimeout = { 60, 0 }; 728360efbdSAlfred Perlstein static const struct timeval rmttimeout = { 3, 0 }; 734e37855eSAlfred Perlstein static struct timeval rpcbrmttime = { 15, 0 }; 748360efbdSAlfred Perlstein 75c05ac53bSDavid E. O'Brien extern bool_t xdr_wrapstring(XDR *, char **); 768360efbdSAlfred Perlstein 778360efbdSAlfred Perlstein static const char nullstring[] = "\000"; 788360efbdSAlfred Perlstein 798360efbdSAlfred Perlstein #define CACHESIZE 6 808360efbdSAlfred Perlstein 818360efbdSAlfred Perlstein struct address_cache { 828360efbdSAlfred Perlstein char *ac_host; 838360efbdSAlfred Perlstein char *ac_netid; 848360efbdSAlfred Perlstein char *ac_uaddr; 858360efbdSAlfred Perlstein struct netbuf *ac_taddr; 868360efbdSAlfred Perlstein struct address_cache *ac_next; 878360efbdSAlfred Perlstein }; 888360efbdSAlfred Perlstein 898360efbdSAlfred Perlstein static struct address_cache *front; 908360efbdSAlfred Perlstein static int cachesize; 918360efbdSAlfred Perlstein 928360efbdSAlfred Perlstein #define CLCR_GET_RPCB_TIMEOUT 1 938360efbdSAlfred Perlstein #define CLCR_SET_RPCB_TIMEOUT 2 948360efbdSAlfred Perlstein 958360efbdSAlfred Perlstein 968360efbdSAlfred Perlstein extern int __rpc_lowvers; 978360efbdSAlfred Perlstein 98c05ac53bSDavid E. O'Brien static struct address_cache *check_cache(const char *, const char *); 99c05ac53bSDavid E. O'Brien static void delete_cache(struct netbuf *); 1001372519bSDavid E. O'Brien static void add_cache(const char *, const char *, struct netbuf *, char *); 1011372519bSDavid E. O'Brien static CLIENT *getclnthandle(const char *, const struct netconfig *, char **); 102c05ac53bSDavid E. O'Brien static CLIENT *local_rpcb(void); 1031372519bSDavid E. O'Brien static struct netbuf *got_entry(rpcb_entry_list_ptr, const struct netconfig *); 1048360efbdSAlfred Perlstein 1058360efbdSAlfred Perlstein /* 1068360efbdSAlfred Perlstein * This routine adjusts the timeout used for calls to the remote rpcbind. 1078360efbdSAlfred Perlstein * Also, this routine can be used to set the use of portmapper version 2 1088360efbdSAlfred Perlstein * only when doing rpc_broadcasts 1098360efbdSAlfred Perlstein * These are private routines that may not be provided in future releases. 1108360efbdSAlfred Perlstein */ 1118360efbdSAlfred Perlstein bool_t 11268895e38SCraig Rodrigues __rpc_control(int request, void *info) 1138360efbdSAlfred Perlstein { 1148360efbdSAlfred Perlstein switch (request) { 1158360efbdSAlfred Perlstein case CLCR_GET_RPCB_TIMEOUT: 1168360efbdSAlfred Perlstein *(struct timeval *)info = tottimeout; 1178360efbdSAlfred Perlstein break; 1188360efbdSAlfred Perlstein case CLCR_SET_RPCB_TIMEOUT: 1198360efbdSAlfred Perlstein tottimeout = *(struct timeval *)info; 1208360efbdSAlfred Perlstein break; 1218360efbdSAlfred Perlstein case CLCR_SET_LOWVERS: 1228360efbdSAlfred Perlstein __rpc_lowvers = *(int *)info; 1238360efbdSAlfred Perlstein break; 1248360efbdSAlfred Perlstein case CLCR_GET_LOWVERS: 1258360efbdSAlfred Perlstein *(int *)info = __rpc_lowvers; 1268360efbdSAlfred Perlstein break; 1278360efbdSAlfred Perlstein default: 1288360efbdSAlfred Perlstein return (FALSE); 1298360efbdSAlfred Perlstein } 1308360efbdSAlfred Perlstein return (TRUE); 1318360efbdSAlfred Perlstein } 1328360efbdSAlfred Perlstein 1338360efbdSAlfred Perlstein /* 1348360efbdSAlfred Perlstein * It might seem that a reader/writer lock would be more reasonable here. 1358360efbdSAlfred Perlstein * However because getclnthandle(), the only user of the cache functions, 1368360efbdSAlfred Perlstein * may do a delete_cache() operation if a check_cache() fails to return an 1378360efbdSAlfred Perlstein * address useful to clnt_tli_create(), we may as well use a mutex. 1388360efbdSAlfred Perlstein */ 1398360efbdSAlfred Perlstein /* 1408360efbdSAlfred Perlstein * As it turns out, if the cache lock is *not* a reader/writer lock, we will 1418360efbdSAlfred Perlstein * block all clnt_create's if we are trying to connect to a host that's down, 1428360efbdSAlfred Perlstein * since the lock will be held all during that time. 1438360efbdSAlfred Perlstein */ 1448360efbdSAlfred Perlstein 1458360efbdSAlfred Perlstein /* 1468360efbdSAlfred Perlstein * The routines check_cache(), add_cache(), delete_cache() manage the 1478360efbdSAlfred Perlstein * cache of rpcbind addresses for (host, netid). 1488360efbdSAlfred Perlstein */ 1498360efbdSAlfred Perlstein 1508360efbdSAlfred Perlstein static struct address_cache * 15168895e38SCraig Rodrigues check_cache(const char *host, const char *netid) 1528360efbdSAlfred Perlstein { 1538360efbdSAlfred Perlstein struct address_cache *cptr; 1548360efbdSAlfred Perlstein 1558360efbdSAlfred Perlstein /* READ LOCK HELD ON ENTRY: rpcbaddr_cache_lock */ 1568360efbdSAlfred Perlstein 1578360efbdSAlfred Perlstein for (cptr = front; cptr != NULL; cptr = cptr->ac_next) { 1588360efbdSAlfred Perlstein if (!strcmp(cptr->ac_host, host) && 1598360efbdSAlfred Perlstein !strcmp(cptr->ac_netid, netid)) { 1608360efbdSAlfred Perlstein #ifdef ND_DEBUG 1618360efbdSAlfred Perlstein fprintf(stderr, "Found cache entry for %s: %s\n", 1628360efbdSAlfred Perlstein host, netid); 1638360efbdSAlfred Perlstein #endif 1648360efbdSAlfred Perlstein return (cptr); 1658360efbdSAlfred Perlstein } 1668360efbdSAlfred Perlstein } 1678360efbdSAlfred Perlstein return ((struct address_cache *) NULL); 1688360efbdSAlfred Perlstein } 1698360efbdSAlfred Perlstein 1708360efbdSAlfred Perlstein static void 17168895e38SCraig Rodrigues delete_cache(struct netbuf *addr) 1728360efbdSAlfred Perlstein { 1738360efbdSAlfred Perlstein struct address_cache *cptr, *prevptr = NULL; 1748360efbdSAlfred Perlstein 1758360efbdSAlfred Perlstein /* WRITE LOCK HELD ON ENTRY: rpcbaddr_cache_lock */ 1768360efbdSAlfred Perlstein for (cptr = front; cptr != NULL; cptr = cptr->ac_next) { 1778360efbdSAlfred Perlstein if (!memcmp(cptr->ac_taddr->buf, addr->buf, addr->len)) { 1788360efbdSAlfred Perlstein free(cptr->ac_host); 1798360efbdSAlfred Perlstein free(cptr->ac_netid); 1808360efbdSAlfred Perlstein free(cptr->ac_taddr->buf); 1818360efbdSAlfred Perlstein free(cptr->ac_taddr); 1828360efbdSAlfred Perlstein free(cptr->ac_uaddr); 1838360efbdSAlfred Perlstein if (prevptr) 1848360efbdSAlfred Perlstein prevptr->ac_next = cptr->ac_next; 1858360efbdSAlfred Perlstein else 1868360efbdSAlfred Perlstein front = cptr->ac_next; 1878360efbdSAlfred Perlstein free(cptr); 1888360efbdSAlfred Perlstein cachesize--; 1898360efbdSAlfred Perlstein break; 1908360efbdSAlfred Perlstein } 1918360efbdSAlfred Perlstein prevptr = cptr; 1928360efbdSAlfred Perlstein } 1938360efbdSAlfred Perlstein } 1948360efbdSAlfred Perlstein 1958360efbdSAlfred Perlstein static void 196587cf682SCraig Rodrigues add_cache(const char *host, const char *netid, struct netbuf *taddr, 197587cf682SCraig Rodrigues char *uaddr) 1988360efbdSAlfred Perlstein { 1998360efbdSAlfred Perlstein struct address_cache *ad_cache, *cptr, *prevptr; 2008360efbdSAlfred Perlstein 2018360efbdSAlfred Perlstein ad_cache = (struct address_cache *) 2028360efbdSAlfred Perlstein malloc(sizeof (struct address_cache)); 2038360efbdSAlfred Perlstein if (!ad_cache) { 2048360efbdSAlfred Perlstein return; 2058360efbdSAlfred Perlstein } 2068360efbdSAlfred Perlstein ad_cache->ac_host = strdup(host); 2078360efbdSAlfred Perlstein ad_cache->ac_netid = strdup(netid); 2088360efbdSAlfred Perlstein ad_cache->ac_uaddr = uaddr ? strdup(uaddr) : NULL; 2098360efbdSAlfred Perlstein ad_cache->ac_taddr = (struct netbuf *)malloc(sizeof (struct netbuf)); 2108360efbdSAlfred Perlstein if (!ad_cache->ac_host || !ad_cache->ac_netid || !ad_cache->ac_taddr || 2118360efbdSAlfred Perlstein (uaddr && !ad_cache->ac_uaddr)) { 212f340bd40SMartin Blapp goto out; 2138360efbdSAlfred Perlstein } 2148360efbdSAlfred Perlstein ad_cache->ac_taddr->len = ad_cache->ac_taddr->maxlen = taddr->len; 2158360efbdSAlfred Perlstein ad_cache->ac_taddr->buf = (char *) malloc(taddr->len); 2168360efbdSAlfred Perlstein if (ad_cache->ac_taddr->buf == NULL) { 217f340bd40SMartin Blapp out: 218f340bd40SMartin Blapp free(ad_cache->ac_host); 219f340bd40SMartin Blapp free(ad_cache->ac_netid); 220f340bd40SMartin Blapp free(ad_cache->ac_uaddr); 221f340bd40SMartin Blapp free(ad_cache->ac_taddr); 222f340bd40SMartin Blapp free(ad_cache); 2238360efbdSAlfred Perlstein return; 2248360efbdSAlfred Perlstein } 2258360efbdSAlfred Perlstein memcpy(ad_cache->ac_taddr->buf, taddr->buf, taddr->len); 2268360efbdSAlfred Perlstein #ifdef ND_DEBUG 2278360efbdSAlfred Perlstein fprintf(stderr, "Added to cache: %s : %s\n", host, netid); 2288360efbdSAlfred Perlstein #endif 2298360efbdSAlfred Perlstein 2308360efbdSAlfred Perlstein /* VARIABLES PROTECTED BY rpcbaddr_cache_lock: cptr */ 2318360efbdSAlfred Perlstein 2328360efbdSAlfred Perlstein rwlock_wrlock(&rpcbaddr_cache_lock); 2338360efbdSAlfred Perlstein if (cachesize < CACHESIZE) { 2348360efbdSAlfred Perlstein ad_cache->ac_next = front; 2358360efbdSAlfred Perlstein front = ad_cache; 2368360efbdSAlfred Perlstein cachesize++; 2378360efbdSAlfred Perlstein } else { 2388360efbdSAlfred Perlstein /* Free the last entry */ 2398360efbdSAlfred Perlstein cptr = front; 2408360efbdSAlfred Perlstein prevptr = NULL; 2418360efbdSAlfred Perlstein while (cptr->ac_next) { 2428360efbdSAlfred Perlstein prevptr = cptr; 2438360efbdSAlfred Perlstein cptr = cptr->ac_next; 2448360efbdSAlfred Perlstein } 2458360efbdSAlfred Perlstein 2468360efbdSAlfred Perlstein #ifdef ND_DEBUG 2478360efbdSAlfred Perlstein fprintf(stderr, "Deleted from cache: %s : %s\n", 2488360efbdSAlfred Perlstein cptr->ac_host, cptr->ac_netid); 2498360efbdSAlfred Perlstein #endif 2508360efbdSAlfred Perlstein free(cptr->ac_host); 2518360efbdSAlfred Perlstein free(cptr->ac_netid); 2528360efbdSAlfred Perlstein free(cptr->ac_taddr->buf); 2538360efbdSAlfred Perlstein free(cptr->ac_taddr); 2548360efbdSAlfred Perlstein free(cptr->ac_uaddr); 2558360efbdSAlfred Perlstein 2568360efbdSAlfred Perlstein if (prevptr) { 2578360efbdSAlfred Perlstein prevptr->ac_next = NULL; 2588360efbdSAlfred Perlstein ad_cache->ac_next = front; 2598360efbdSAlfred Perlstein front = ad_cache; 2608360efbdSAlfred Perlstein } else { 2618360efbdSAlfred Perlstein front = ad_cache; 2628360efbdSAlfred Perlstein ad_cache->ac_next = NULL; 2638360efbdSAlfred Perlstein } 2648360efbdSAlfred Perlstein free(cptr); 2658360efbdSAlfred Perlstein } 2668360efbdSAlfred Perlstein rwlock_unlock(&rpcbaddr_cache_lock); 2678360efbdSAlfred Perlstein } 2688360efbdSAlfred Perlstein 2698360efbdSAlfred Perlstein /* 2708360efbdSAlfred Perlstein * This routine will return a client handle that is connected to the 271e73bb7f1SIan Dowse * rpcbind. If targaddr is non-NULL, the "universal address" of the 272e73bb7f1SIan Dowse * host will be stored in *targaddr; the caller is responsible for 273e73bb7f1SIan Dowse * freeing this string. 274e73bb7f1SIan Dowse * On error, returns NULL and free's everything. 2758360efbdSAlfred Perlstein */ 2768360efbdSAlfred Perlstein static CLIENT * 27768895e38SCraig Rodrigues getclnthandle(const char *host, const struct netconfig *nconf, char **targaddr) 2788360efbdSAlfred Perlstein { 2798360efbdSAlfred Perlstein CLIENT *client; 2808360efbdSAlfred Perlstein struct netbuf *addr, taddr; 2818360efbdSAlfred Perlstein struct netbuf addr_to_delete; 2828360efbdSAlfred Perlstein struct __rpc_sockinfo si; 2838360efbdSAlfred Perlstein struct addrinfo hints, *res, *tres; 2848360efbdSAlfred Perlstein struct address_cache *ad_cache; 2858360efbdSAlfred Perlstein char *tmpaddr; 2868360efbdSAlfred Perlstein 2878360efbdSAlfred Perlstein /* VARIABLES PROTECTED BY rpcbaddr_cache_lock: ad_cache */ 2888360efbdSAlfred Perlstein 2898360efbdSAlfred Perlstein /* Get the address of the rpcbind. Check cache first */ 29052353da8SIan Dowse client = NULL; 2918360efbdSAlfred Perlstein addr_to_delete.len = 0; 2928360efbdSAlfred Perlstein rwlock_rdlock(&rpcbaddr_cache_lock); 293e4db1131SAlfred Perlstein ad_cache = NULL; 294e4db1131SAlfred Perlstein if (host != NULL) 2958360efbdSAlfred Perlstein ad_cache = check_cache(host, nconf->nc_netid); 2968360efbdSAlfred Perlstein if (ad_cache != NULL) { 2978360efbdSAlfred Perlstein addr = ad_cache->ac_taddr; 2988360efbdSAlfred Perlstein client = clnt_tli_create(RPC_ANYFD, nconf, addr, 2998360efbdSAlfred Perlstein (rpcprog_t)RPCBPROG, (rpcvers_t)RPCBVERS4, 0, 0); 3008360efbdSAlfred Perlstein if (client != NULL) { 3018360efbdSAlfred Perlstein if (targaddr) 302e73bb7f1SIan Dowse *targaddr = strdup(ad_cache->ac_uaddr); 3038360efbdSAlfred Perlstein rwlock_unlock(&rpcbaddr_cache_lock); 3048360efbdSAlfred Perlstein return (client); 3058360efbdSAlfred Perlstein } 3068360efbdSAlfred Perlstein addr_to_delete.len = addr->len; 3078360efbdSAlfred Perlstein addr_to_delete.buf = (char *)malloc(addr->len); 3088360efbdSAlfred Perlstein if (addr_to_delete.buf == NULL) { 3098360efbdSAlfred Perlstein addr_to_delete.len = 0; 3108360efbdSAlfred Perlstein } else { 3118360efbdSAlfred Perlstein memcpy(addr_to_delete.buf, addr->buf, addr->len); 3128360efbdSAlfred Perlstein } 3138360efbdSAlfred Perlstein } 3148360efbdSAlfred Perlstein rwlock_unlock(&rpcbaddr_cache_lock); 3158360efbdSAlfred Perlstein if (addr_to_delete.len != 0) { 3168360efbdSAlfred Perlstein /* 3178360efbdSAlfred Perlstein * Assume this may be due to cache data being 3188360efbdSAlfred Perlstein * outdated 3198360efbdSAlfred Perlstein */ 3208360efbdSAlfred Perlstein rwlock_wrlock(&rpcbaddr_cache_lock); 3218360efbdSAlfred Perlstein delete_cache(&addr_to_delete); 3228360efbdSAlfred Perlstein rwlock_unlock(&rpcbaddr_cache_lock); 3238360efbdSAlfred Perlstein free(addr_to_delete.buf); 3248360efbdSAlfred Perlstein } 3258360efbdSAlfred Perlstein if (!__rpc_nconf2sockinfo(nconf, &si)) { 3268360efbdSAlfred Perlstein rpc_createerr.cf_stat = RPC_UNKNOWNPROTO; 3278360efbdSAlfred Perlstein return NULL; 3288360efbdSAlfred Perlstein } 3298360efbdSAlfred Perlstein 3308360efbdSAlfred Perlstein memset(&hints, 0, sizeof hints); 3318360efbdSAlfred Perlstein hints.ai_family = si.si_af; 3328360efbdSAlfred Perlstein hints.ai_socktype = si.si_socktype; 3338360efbdSAlfred Perlstein hints.ai_protocol = si.si_proto; 3348360efbdSAlfred Perlstein 3358360efbdSAlfred Perlstein #ifdef CLNT_DEBUG 3368360efbdSAlfred Perlstein printf("trying netid %s family %d proto %d socktype %d\n", 3378360efbdSAlfred Perlstein nconf->nc_netid, si.si_af, si.si_proto, si.si_socktype); 3388360efbdSAlfred Perlstein #endif 3398360efbdSAlfred Perlstein 340e4db1131SAlfred Perlstein if (nconf->nc_protofmly != NULL && strcmp(nconf->nc_protofmly, NC_LOOPBACK) == 0) { 341e4db1131SAlfred Perlstein client = local_rpcb(); 342e4db1131SAlfred Perlstein if (! client) { 343e4db1131SAlfred Perlstein #ifdef ND_DEBUG 344e4db1131SAlfred Perlstein clnt_pcreateerror("rpcbind clnt interface"); 345e4db1131SAlfred Perlstein #endif 346e4db1131SAlfred Perlstein return (NULL); 347e4db1131SAlfred Perlstein } else { 348e4db1131SAlfred Perlstein struct sockaddr_un sun; 349330e445cSMatteo Riondato if (targaddr) { 350e4db1131SAlfred Perlstein *targaddr = malloc(sizeof(sun.sun_path)); 351330e445cSMatteo Riondato if (*targaddr == NULL) { 352330e445cSMatteo Riondato CLNT_DESTROY(client); 353330e445cSMatteo Riondato return (NULL); 354330e445cSMatteo Riondato } 355e4db1131SAlfred Perlstein strncpy(*targaddr, _PATH_RPCBINDSOCK, 356e4db1131SAlfred Perlstein sizeof(sun.sun_path)); 357330e445cSMatteo Riondato } 358e4db1131SAlfred Perlstein return (client); 359e4db1131SAlfred Perlstein } 360e4db1131SAlfred Perlstein } else { 3618360efbdSAlfred Perlstein if (getaddrinfo(host, "sunrpc", &hints, &res) != 0) { 3628360efbdSAlfred Perlstein rpc_createerr.cf_stat = RPC_UNKNOWNHOST; 3638360efbdSAlfred Perlstein return NULL; 3648360efbdSAlfred Perlstein } 365e4db1131SAlfred Perlstein } 3668360efbdSAlfred Perlstein 3678360efbdSAlfred Perlstein for (tres = res; tres != NULL; tres = tres->ai_next) { 3688360efbdSAlfred Perlstein taddr.buf = tres->ai_addr; 3698360efbdSAlfred Perlstein taddr.len = taddr.maxlen = tres->ai_addrlen; 3708360efbdSAlfred Perlstein 3718360efbdSAlfred Perlstein #ifdef ND_DEBUG 3728360efbdSAlfred Perlstein { 3738360efbdSAlfred Perlstein char *ua; 3748360efbdSAlfred Perlstein 3758360efbdSAlfred Perlstein ua = taddr2uaddr(nconf, &taddr); 3768360efbdSAlfred Perlstein fprintf(stderr, "Got it [%s]\n", ua); 3778360efbdSAlfred Perlstein free(ua); 3788360efbdSAlfred Perlstein } 3798360efbdSAlfred Perlstein #endif 3808360efbdSAlfred Perlstein 3818360efbdSAlfred Perlstein #ifdef ND_DEBUG 3828360efbdSAlfred Perlstein { 3838360efbdSAlfred Perlstein int i; 3848360efbdSAlfred Perlstein 3858360efbdSAlfred Perlstein fprintf(stderr, "\tnetbuf len = %d, maxlen = %d\n", 3868360efbdSAlfred Perlstein taddr.len, taddr.maxlen); 3878360efbdSAlfred Perlstein fprintf(stderr, "\tAddress is "); 3888360efbdSAlfred Perlstein for (i = 0; i < taddr.len; i++) 3898360efbdSAlfred Perlstein fprintf(stderr, "%u.", ((char *)(taddr.buf))[i]); 3908360efbdSAlfred Perlstein fprintf(stderr, "\n"); 3918360efbdSAlfred Perlstein } 3928360efbdSAlfred Perlstein #endif 3938360efbdSAlfred Perlstein client = clnt_tli_create(RPC_ANYFD, nconf, &taddr, 3948360efbdSAlfred Perlstein (rpcprog_t)RPCBPROG, (rpcvers_t)RPCBVERS4, 0, 0); 3958360efbdSAlfred Perlstein #ifdef ND_DEBUG 3968360efbdSAlfred Perlstein if (! client) { 3978360efbdSAlfred Perlstein clnt_pcreateerror("rpcbind clnt interface"); 3988360efbdSAlfred Perlstein } 3998360efbdSAlfred Perlstein #endif 4008360efbdSAlfred Perlstein 4018360efbdSAlfred Perlstein if (client) { 4028360efbdSAlfred Perlstein tmpaddr = targaddr ? taddr2uaddr(nconf, &taddr) : NULL; 4038360efbdSAlfred Perlstein add_cache(host, nconf->nc_netid, &taddr, tmpaddr); 4048360efbdSAlfred Perlstein if (targaddr) 4058360efbdSAlfred Perlstein *targaddr = tmpaddr; 4068360efbdSAlfred Perlstein break; 4078360efbdSAlfred Perlstein } 4088360efbdSAlfred Perlstein } 409e4db1131SAlfred Perlstein if (res) 4108360efbdSAlfred Perlstein freeaddrinfo(res); 4118360efbdSAlfred Perlstein return (client); 4128360efbdSAlfred Perlstein } 4138360efbdSAlfred Perlstein 4148360efbdSAlfred Perlstein /* XXX */ 4158360efbdSAlfred Perlstein #define IN4_LOCALHOST_STRING "127.0.0.1" 4168360efbdSAlfred Perlstein #define IN6_LOCALHOST_STRING "::1" 4178360efbdSAlfred Perlstein 4188360efbdSAlfred Perlstein /* 4198360efbdSAlfred Perlstein * This routine will return a client handle that is connected to the local 4208360efbdSAlfred Perlstein * rpcbind. Returns NULL on error and free's everything. 4218360efbdSAlfred Perlstein */ 4228360efbdSAlfred Perlstein static CLIENT * 423587cf682SCraig Rodrigues local_rpcb(void) 4248360efbdSAlfred Perlstein { 4258360efbdSAlfred Perlstein CLIENT *client; 4268360efbdSAlfred Perlstein static struct netconfig *loopnconf; 4278360efbdSAlfred Perlstein static char *hostname; 4288360efbdSAlfred Perlstein int sock; 4298360efbdSAlfred Perlstein size_t tsize; 4308360efbdSAlfred Perlstein struct netbuf nbuf; 4318360efbdSAlfred Perlstein struct sockaddr_un sun; 4328360efbdSAlfred Perlstein 4338360efbdSAlfred Perlstein /* 4348360efbdSAlfred Perlstein * Try connecting to the local rpcbind through a local socket 4358360efbdSAlfred Perlstein * first. If this doesn't work, try all transports defined in 4368360efbdSAlfred Perlstein * the netconfig file. 4378360efbdSAlfred Perlstein */ 4388360efbdSAlfred Perlstein memset(&sun, 0, sizeof sun); 4398360efbdSAlfred Perlstein sock = _socket(AF_LOCAL, SOCK_STREAM, 0); 4408360efbdSAlfred Perlstein if (sock < 0) 4418360efbdSAlfred Perlstein goto try_nconf; 4428360efbdSAlfred Perlstein sun.sun_family = AF_LOCAL; 4438360efbdSAlfred Perlstein strcpy(sun.sun_path, _PATH_RPCBINDSOCK); 4448360efbdSAlfred Perlstein nbuf.len = sun.sun_len = SUN_LEN(&sun); 4458360efbdSAlfred Perlstein nbuf.maxlen = sizeof (struct sockaddr_un); 4468360efbdSAlfred Perlstein nbuf.buf = &sun; 4478360efbdSAlfred Perlstein 4488360efbdSAlfred Perlstein tsize = __rpc_get_t_size(AF_LOCAL, 0, 0); 4498360efbdSAlfred Perlstein client = clnt_vc_create(sock, &nbuf, (rpcprog_t)RPCBPROG, 4508360efbdSAlfred Perlstein (rpcvers_t)RPCBVERS, tsize, tsize); 4518360efbdSAlfred Perlstein 4526112fceeSIan Dowse if (client != NULL) { 4536112fceeSIan Dowse /* Mark the socket to be closed in destructor */ 4546112fceeSIan Dowse (void) CLNT_CONTROL(client, CLSET_FD_CLOSE, NULL); 4558360efbdSAlfred Perlstein return client; 4566112fceeSIan Dowse } 4576112fceeSIan Dowse 4586112fceeSIan Dowse /* Nobody needs this socket anymore; free the descriptor. */ 4596112fceeSIan Dowse _close(sock); 4608360efbdSAlfred Perlstein 4618360efbdSAlfred Perlstein try_nconf: 4628360efbdSAlfred Perlstein 4638360efbdSAlfred Perlstein /* VARIABLES PROTECTED BY loopnconf_lock: loopnconf */ 4648360efbdSAlfred Perlstein mutex_lock(&loopnconf_lock); 4658360efbdSAlfred Perlstein if (loopnconf == NULL) { 4668360efbdSAlfred Perlstein struct netconfig *nconf, *tmpnconf = NULL; 4678360efbdSAlfred Perlstein void *nc_handle; 4688360efbdSAlfred Perlstein int fd; 4698360efbdSAlfred Perlstein 4708360efbdSAlfred Perlstein nc_handle = setnetconfig(); 4718360efbdSAlfred Perlstein if (nc_handle == NULL) { 4728360efbdSAlfred Perlstein /* fails to open netconfig file */ 4738360efbdSAlfred Perlstein syslog (LOG_ERR, "rpc: failed to open " NETCONFIG); 4748360efbdSAlfred Perlstein rpc_createerr.cf_stat = RPC_UNKNOWNPROTO; 4758360efbdSAlfred Perlstein mutex_unlock(&loopnconf_lock); 4768360efbdSAlfred Perlstein return (NULL); 4778360efbdSAlfred Perlstein } 4788360efbdSAlfred Perlstein while ((nconf = getnetconfig(nc_handle)) != NULL) { 4798360efbdSAlfred Perlstein #ifdef INET6 4808360efbdSAlfred Perlstein if ((strcmp(nconf->nc_protofmly, NC_INET6) == 0 || 4818360efbdSAlfred Perlstein #else 4828360efbdSAlfred Perlstein if (( 4838360efbdSAlfred Perlstein #endif 4848360efbdSAlfred Perlstein strcmp(nconf->nc_protofmly, NC_INET) == 0) && 4858360efbdSAlfred Perlstein (nconf->nc_semantics == NC_TPI_COTS || 4868360efbdSAlfred Perlstein nconf->nc_semantics == NC_TPI_COTS_ORD)) { 4878360efbdSAlfred Perlstein fd = __rpc_nconf2fd(nconf); 4888360efbdSAlfred Perlstein /* 4898360efbdSAlfred Perlstein * Can't create a socket, assume that 4908360efbdSAlfred Perlstein * this family isn't configured in the kernel. 4918360efbdSAlfred Perlstein */ 4928360efbdSAlfred Perlstein if (fd < 0) 4938360efbdSAlfred Perlstein continue; 4948360efbdSAlfred Perlstein _close(fd); 4958360efbdSAlfred Perlstein tmpnconf = nconf; 4968360efbdSAlfred Perlstein if (!strcmp(nconf->nc_protofmly, NC_INET)) 4978360efbdSAlfred Perlstein hostname = IN4_LOCALHOST_STRING; 4988360efbdSAlfred Perlstein else 4998360efbdSAlfred Perlstein hostname = IN6_LOCALHOST_STRING; 5008360efbdSAlfred Perlstein } 5018360efbdSAlfred Perlstein } 5028360efbdSAlfred Perlstein if (tmpnconf == NULL) { 503*091867a6SXin LI endnetconfig(nc_handle); 5048360efbdSAlfred Perlstein rpc_createerr.cf_stat = RPC_UNKNOWNPROTO; 5058360efbdSAlfred Perlstein mutex_unlock(&loopnconf_lock); 5068360efbdSAlfred Perlstein return (NULL); 5078360efbdSAlfred Perlstein } 5088360efbdSAlfred Perlstein loopnconf = getnetconfigent(tmpnconf->nc_netid); 5098360efbdSAlfred Perlstein /* loopnconf is never freed */ 510*091867a6SXin LI endnetconfig(nc_handle); 5118360efbdSAlfred Perlstein } 5128360efbdSAlfred Perlstein mutex_unlock(&loopnconf_lock); 5138360efbdSAlfred Perlstein client = getclnthandle(hostname, loopnconf, NULL); 5148360efbdSAlfred Perlstein return (client); 5158360efbdSAlfred Perlstein } 5168360efbdSAlfred Perlstein 5178360efbdSAlfred Perlstein /* 5188360efbdSAlfred Perlstein * Set a mapping between program, version and address. 5198360efbdSAlfred Perlstein * Calls the rpcbind service to do the mapping. 52068895e38SCraig Rodrigues * 52168895e38SCraig Rodrigues * nconf - Network structure of transport 52268895e38SCraig Rodrigues * address - Services netconfig address 5238360efbdSAlfred Perlstein */ 5248360efbdSAlfred Perlstein bool_t 52568895e38SCraig Rodrigues rpcb_set(rpcprog_t program, rpcvers_t version, const struct netconfig *nconf, 52668895e38SCraig Rodrigues const struct netbuf *address) 5278360efbdSAlfred Perlstein { 5288360efbdSAlfred Perlstein CLIENT *client; 5298360efbdSAlfred Perlstein bool_t rslt = FALSE; 5308360efbdSAlfred Perlstein RPCB parms; 5318360efbdSAlfred Perlstein char uidbuf[32]; 5328360efbdSAlfred Perlstein 5338360efbdSAlfred Perlstein /* parameter checking */ 5348360efbdSAlfred Perlstein if (nconf == NULL) { 5358360efbdSAlfred Perlstein rpc_createerr.cf_stat = RPC_UNKNOWNPROTO; 5368360efbdSAlfred Perlstein return (FALSE); 5378360efbdSAlfred Perlstein } 5388360efbdSAlfred Perlstein if (address == NULL) { 5398360efbdSAlfred Perlstein rpc_createerr.cf_stat = RPC_UNKNOWNADDR; 5408360efbdSAlfred Perlstein return (FALSE); 5418360efbdSAlfred Perlstein } 5428360efbdSAlfred Perlstein client = local_rpcb(); 5438360efbdSAlfred Perlstein if (! client) { 5448360efbdSAlfred Perlstein return (FALSE); 5458360efbdSAlfred Perlstein } 5468360efbdSAlfred Perlstein 5478360efbdSAlfred Perlstein /* convert to universal */ 5488360efbdSAlfred Perlstein /*LINTED const castaway*/ 5498360efbdSAlfred Perlstein parms.r_addr = taddr2uaddr((struct netconfig *) nconf, 5508360efbdSAlfred Perlstein (struct netbuf *)address); 5518360efbdSAlfred Perlstein if (!parms.r_addr) { 5526112fceeSIan Dowse CLNT_DESTROY(client); 5538360efbdSAlfred Perlstein rpc_createerr.cf_stat = RPC_N2AXLATEFAILURE; 5548360efbdSAlfred Perlstein return (FALSE); /* no universal address */ 5558360efbdSAlfred Perlstein } 5568360efbdSAlfred Perlstein parms.r_prog = program; 5578360efbdSAlfred Perlstein parms.r_vers = version; 5588360efbdSAlfred Perlstein parms.r_netid = nconf->nc_netid; 5598360efbdSAlfred Perlstein /* 5608360efbdSAlfred Perlstein * Though uid is not being used directly, we still send it for 5618360efbdSAlfred Perlstein * completeness. For non-unix platforms, perhaps some other 5628360efbdSAlfred Perlstein * string or an empty string can be sent. 5638360efbdSAlfred Perlstein */ 5648360efbdSAlfred Perlstein (void) snprintf(uidbuf, sizeof uidbuf, "%d", geteuid()); 5658360efbdSAlfred Perlstein parms.r_owner = uidbuf; 5668360efbdSAlfred Perlstein 5678360efbdSAlfred Perlstein CLNT_CALL(client, (rpcproc_t)RPCBPROC_SET, (xdrproc_t) xdr_rpcb, 5688360efbdSAlfred Perlstein (char *)(void *)&parms, (xdrproc_t) xdr_bool, 5698360efbdSAlfred Perlstein (char *)(void *)&rslt, tottimeout); 5708360efbdSAlfred Perlstein 5718360efbdSAlfred Perlstein CLNT_DESTROY(client); 5728360efbdSAlfred Perlstein free(parms.r_addr); 5738360efbdSAlfred Perlstein return (rslt); 5748360efbdSAlfred Perlstein } 5758360efbdSAlfred Perlstein 5768360efbdSAlfred Perlstein /* 5778360efbdSAlfred Perlstein * Remove the mapping between program, version and netbuf address. 5788360efbdSAlfred Perlstein * Calls the rpcbind service to do the un-mapping. 5798360efbdSAlfred Perlstein * If netbuf is NULL, unset for all the transports, otherwise unset 5808360efbdSAlfred Perlstein * only for the given transport. 5818360efbdSAlfred Perlstein */ 5828360efbdSAlfred Perlstein bool_t 58368895e38SCraig Rodrigues rpcb_unset(rpcprog_t program, rpcvers_t version, const struct netconfig *nconf) 5848360efbdSAlfred Perlstein { 5858360efbdSAlfred Perlstein CLIENT *client; 5868360efbdSAlfred Perlstein bool_t rslt = FALSE; 5878360efbdSAlfred Perlstein RPCB parms; 5888360efbdSAlfred Perlstein char uidbuf[32]; 5898360efbdSAlfred Perlstein 5908360efbdSAlfred Perlstein client = local_rpcb(); 5918360efbdSAlfred Perlstein if (! client) { 5928360efbdSAlfred Perlstein return (FALSE); 5938360efbdSAlfred Perlstein } 5948360efbdSAlfred Perlstein 5958360efbdSAlfred Perlstein parms.r_prog = program; 5968360efbdSAlfred Perlstein parms.r_vers = version; 5978360efbdSAlfred Perlstein if (nconf) 5988360efbdSAlfred Perlstein parms.r_netid = nconf->nc_netid; 5998360efbdSAlfred Perlstein else { 6008360efbdSAlfred Perlstein /*LINTED const castaway*/ 6018360efbdSAlfred Perlstein parms.r_netid = (char *) &nullstring[0]; /* unsets all */ 6028360efbdSAlfred Perlstein } 6038360efbdSAlfred Perlstein /*LINTED const castaway*/ 6048360efbdSAlfred Perlstein parms.r_addr = (char *) &nullstring[0]; 6058360efbdSAlfred Perlstein (void) snprintf(uidbuf, sizeof uidbuf, "%d", geteuid()); 6068360efbdSAlfred Perlstein parms.r_owner = uidbuf; 6078360efbdSAlfred Perlstein 6088360efbdSAlfred Perlstein CLNT_CALL(client, (rpcproc_t)RPCBPROC_UNSET, (xdrproc_t) xdr_rpcb, 6098360efbdSAlfred Perlstein (char *)(void *)&parms, (xdrproc_t) xdr_bool, 6108360efbdSAlfred Perlstein (char *)(void *)&rslt, tottimeout); 6118360efbdSAlfred Perlstein 6128360efbdSAlfred Perlstein CLNT_DESTROY(client); 6138360efbdSAlfred Perlstein return (rslt); 6148360efbdSAlfred Perlstein } 6158360efbdSAlfred Perlstein 6168360efbdSAlfred Perlstein /* 6178360efbdSAlfred Perlstein * From the merged list, find the appropriate entry 6188360efbdSAlfred Perlstein */ 6198360efbdSAlfred Perlstein static struct netbuf * 62068895e38SCraig Rodrigues got_entry(rpcb_entry_list_ptr relp, const struct netconfig *nconf) 6218360efbdSAlfred Perlstein { 6228360efbdSAlfred Perlstein struct netbuf *na = NULL; 6238360efbdSAlfred Perlstein rpcb_entry_list_ptr sp; 6248360efbdSAlfred Perlstein rpcb_entry *rmap; 6258360efbdSAlfred Perlstein 6268360efbdSAlfred Perlstein for (sp = relp; sp != NULL; sp = sp->rpcb_entry_next) { 6278360efbdSAlfred Perlstein rmap = &sp->rpcb_entry_map; 6288360efbdSAlfred Perlstein if ((strcmp(nconf->nc_proto, rmap->r_nc_proto) == 0) && 6298360efbdSAlfred Perlstein (strcmp(nconf->nc_protofmly, rmap->r_nc_protofmly) == 0) && 6308360efbdSAlfred Perlstein (nconf->nc_semantics == rmap->r_nc_semantics) && 631b6c452a8SMartin Blapp (rmap->r_maddr != NULL) && (rmap->r_maddr[0] != 0)) { 6328360efbdSAlfred Perlstein na = uaddr2taddr(nconf, rmap->r_maddr); 6338360efbdSAlfred Perlstein #ifdef ND_DEBUG 6348360efbdSAlfred Perlstein fprintf(stderr, "\tRemote address is [%s].\n", 6358360efbdSAlfred Perlstein rmap->r_maddr); 6368360efbdSAlfred Perlstein if (!na) 6378360efbdSAlfred Perlstein fprintf(stderr, 6388360efbdSAlfred Perlstein "\tCouldn't resolve remote address!\n"); 6398360efbdSAlfred Perlstein #endif 6408360efbdSAlfred Perlstein break; 6418360efbdSAlfred Perlstein } 6428360efbdSAlfred Perlstein } 6438360efbdSAlfred Perlstein return (na); 6448360efbdSAlfred Perlstein } 6458360efbdSAlfred Perlstein 6468360efbdSAlfred Perlstein /* 6474e37855eSAlfred Perlstein * Quick check to see if rpcbind is up. Tries to connect over 6484e37855eSAlfred Perlstein * local transport. 6494e37855eSAlfred Perlstein */ 650235baf26SDaniel Eischen static bool_t 65177601543SCraig Rodrigues __rpcbind_is_up(void) 6524e37855eSAlfred Perlstein { 6534e37855eSAlfred Perlstein struct netconfig *nconf; 6544e37855eSAlfred Perlstein struct sockaddr_un sun; 6554e37855eSAlfred Perlstein void *localhandle; 6564e37855eSAlfred Perlstein int sock; 6574e37855eSAlfred Perlstein 6584e37855eSAlfred Perlstein nconf = NULL; 6594e37855eSAlfred Perlstein localhandle = setnetconfig(); 660bb1ca86fSIan Dowse while ((nconf = getnetconfig(localhandle)) != NULL) { 6614e37855eSAlfred Perlstein if (nconf->nc_protofmly != NULL && 6624e37855eSAlfred Perlstein strcmp(nconf->nc_protofmly, NC_LOOPBACK) == 0) 6634e37855eSAlfred Perlstein break; 6644e37855eSAlfred Perlstein } 6657f3159edSEnji Cooper endnetconfig(localhandle); 6667f3159edSEnji Cooper 6674e37855eSAlfred Perlstein if (nconf == NULL) 6684e37855eSAlfred Perlstein return (FALSE); 6694e37855eSAlfred Perlstein 6704e37855eSAlfred Perlstein memset(&sun, 0, sizeof sun); 6714e37855eSAlfred Perlstein sock = _socket(AF_LOCAL, SOCK_STREAM, 0); 6724e37855eSAlfred Perlstein if (sock < 0) 6734e37855eSAlfred Perlstein return (FALSE); 6744e37855eSAlfred Perlstein sun.sun_family = AF_LOCAL; 6754e37855eSAlfred Perlstein strncpy(sun.sun_path, _PATH_RPCBINDSOCK, sizeof(sun.sun_path)); 6764e37855eSAlfred Perlstein sun.sun_len = SUN_LEN(&sun); 6774e37855eSAlfred Perlstein 6784e37855eSAlfred Perlstein if (_connect(sock, (struct sockaddr *)&sun, sun.sun_len) < 0) { 6794e37855eSAlfred Perlstein _close(sock); 6804e37855eSAlfred Perlstein return (FALSE); 6814e37855eSAlfred Perlstein } 6824e37855eSAlfred Perlstein 6834e37855eSAlfred Perlstein _close(sock); 6844e37855eSAlfred Perlstein return (TRUE); 6854e37855eSAlfred Perlstein } 6864e37855eSAlfred Perlstein 6874e37855eSAlfred Perlstein /* 6888360efbdSAlfred Perlstein * An internal function which optimizes rpcb_getaddr function. It also 6898360efbdSAlfred Perlstein * returns the client handle that it uses to contact the remote rpcbind. 6908360efbdSAlfred Perlstein * 6918360efbdSAlfred Perlstein * The algorithm used: If the transports is TCP or UDP, it first tries 6928360efbdSAlfred Perlstein * version 2 (portmap), 4 and then 3 (svr4). This order should be 6938360efbdSAlfred Perlstein * changed in the next OS release to 4, 2 and 3. We are assuming that by 6948360efbdSAlfred Perlstein * that time, version 4 would be available on many machines on the network. 6958360efbdSAlfred Perlstein * With this algorithm, we get performance as well as a plan for 6968360efbdSAlfred Perlstein * obsoleting version 2. 6978360efbdSAlfred Perlstein * 6988360efbdSAlfred Perlstein * For all other transports, the algorithm remains as 4 and then 3. 6998360efbdSAlfred Perlstein * 7008360efbdSAlfred Perlstein * XXX: Due to some problems with t_connect(), we do not reuse the same client 7018360efbdSAlfred Perlstein * handle for COTS cases and hence in these cases we do not return the 7028360efbdSAlfred Perlstein * client handle. This code will change if t_connect() ever 7038360efbdSAlfred Perlstein * starts working properly. Also look under clnt_vc.c. 7048360efbdSAlfred Perlstein */ 7058360efbdSAlfred Perlstein struct netbuf * 70668895e38SCraig Rodrigues __rpcb_findaddr_timed(rpcprog_t program, rpcvers_t version, 70768895e38SCraig Rodrigues const struct netconfig *nconf, const char *host, 70868895e38SCraig Rodrigues CLIENT **clpp, struct timeval *tp) 7098360efbdSAlfred Perlstein { 7104e37855eSAlfred Perlstein static bool_t check_rpcbind = TRUE; 7118360efbdSAlfred Perlstein CLIENT *client = NULL; 7128360efbdSAlfred Perlstein RPCB parms; 7138360efbdSAlfred Perlstein enum clnt_stat clnt_st; 7148360efbdSAlfred Perlstein char *ua = NULL; 7158360efbdSAlfred Perlstein rpcvers_t vers; 7168360efbdSAlfred Perlstein struct netbuf *address = NULL; 7178360efbdSAlfred Perlstein rpcvers_t start_vers = RPCBVERS4; 7188360efbdSAlfred Perlstein struct netbuf servaddr; 7198360efbdSAlfred Perlstein 7208360efbdSAlfred Perlstein /* parameter checking */ 7218360efbdSAlfred Perlstein if (nconf == NULL) { 7228360efbdSAlfred Perlstein rpc_createerr.cf_stat = RPC_UNKNOWNPROTO; 7238360efbdSAlfred Perlstein return (NULL); 7248360efbdSAlfred Perlstein } 7258360efbdSAlfred Perlstein 7268360efbdSAlfred Perlstein parms.r_addr = NULL; 7278360efbdSAlfred Perlstein 7284e37855eSAlfred Perlstein /* 7294e37855eSAlfred Perlstein * Use default total timeout if no timeout is specified. 7304e37855eSAlfred Perlstein */ 7314e37855eSAlfred Perlstein if (tp == NULL) 7324e37855eSAlfred Perlstein tp = &tottimeout; 7334e37855eSAlfred Perlstein 7348360efbdSAlfred Perlstein #ifdef PORTMAP 7358360efbdSAlfred Perlstein /* Try version 2 for TCP or UDP */ 7368360efbdSAlfred Perlstein if (strcmp(nconf->nc_protofmly, NC_INET) == 0) { 7378360efbdSAlfred Perlstein u_short port = 0; 7388360efbdSAlfred Perlstein struct netbuf remote; 7398360efbdSAlfred Perlstein rpcvers_t pmapvers = 2; 7408360efbdSAlfred Perlstein struct pmap pmapparms; 7418360efbdSAlfred Perlstein 7428360efbdSAlfred Perlstein /* 7438360efbdSAlfred Perlstein * Try UDP only - there are some portmappers out 7448360efbdSAlfred Perlstein * there that use UDP only. 7458360efbdSAlfred Perlstein */ 7468360efbdSAlfred Perlstein if (strcmp(nconf->nc_proto, NC_TCP) == 0) { 7478360efbdSAlfred Perlstein struct netconfig *newnconf; 7488360efbdSAlfred Perlstein 749bb1ca86fSIan Dowse if ((newnconf = getnetconfigent("udp")) == NULL) { 7508360efbdSAlfred Perlstein rpc_createerr.cf_stat = RPC_UNKNOWNPROTO; 7518360efbdSAlfred Perlstein return (NULL); 7528360efbdSAlfred Perlstein } 7538360efbdSAlfred Perlstein client = getclnthandle(host, newnconf, &parms.r_addr); 754bb1ca86fSIan Dowse freenetconfigent(newnconf); 7558360efbdSAlfred Perlstein } else { 7568360efbdSAlfred Perlstein client = getclnthandle(host, nconf, &parms.r_addr); 7578360efbdSAlfred Perlstein } 7584e37855eSAlfred Perlstein if (client == NULL) 7598360efbdSAlfred Perlstein return (NULL); 7608360efbdSAlfred Perlstein 7614e37855eSAlfred Perlstein /* 7624e37855eSAlfred Perlstein * Set version and retry timeout. 7634e37855eSAlfred Perlstein */ 7644e37855eSAlfred Perlstein CLNT_CONTROL(client, CLSET_RETRY_TIMEOUT, (char *)&rpcbrmttime); 7654e37855eSAlfred Perlstein CLNT_CONTROL(client, CLSET_VERS, (char *)&pmapvers); 7664e37855eSAlfred Perlstein 7678360efbdSAlfred Perlstein pmapparms.pm_prog = program; 7688360efbdSAlfred Perlstein pmapparms.pm_vers = version; 7698360efbdSAlfred Perlstein pmapparms.pm_prot = strcmp(nconf->nc_proto, NC_TCP) ? 7708360efbdSAlfred Perlstein IPPROTO_UDP : IPPROTO_TCP; 7718360efbdSAlfred Perlstein pmapparms.pm_port = 0; /* not needed */ 7728360efbdSAlfred Perlstein clnt_st = CLNT_CALL(client, (rpcproc_t)PMAPPROC_GETPORT, 7738360efbdSAlfred Perlstein (xdrproc_t) xdr_pmap, (caddr_t)(void *)&pmapparms, 7748360efbdSAlfred Perlstein (xdrproc_t) xdr_u_short, (caddr_t)(void *)&port, 7754e37855eSAlfred Perlstein *tp); 7768360efbdSAlfred Perlstein if (clnt_st != RPC_SUCCESS) { 7778360efbdSAlfred Perlstein if ((clnt_st == RPC_PROGVERSMISMATCH) || 7788360efbdSAlfred Perlstein (clnt_st == RPC_PROGUNAVAIL)) 7798360efbdSAlfred Perlstein goto try_rpcbind; /* Try different versions */ 7808360efbdSAlfred Perlstein rpc_createerr.cf_stat = RPC_PMAPFAILURE; 7818360efbdSAlfred Perlstein clnt_geterr(client, &rpc_createerr.cf_error); 7828360efbdSAlfred Perlstein goto error; 7838360efbdSAlfred Perlstein } else if (port == 0) { 7848360efbdSAlfred Perlstein address = NULL; 7858360efbdSAlfred Perlstein rpc_createerr.cf_stat = RPC_PROGNOTREGISTERED; 7868360efbdSAlfred Perlstein goto error; 7878360efbdSAlfred Perlstein } 7888360efbdSAlfred Perlstein port = htons(port); 7894e37855eSAlfred Perlstein CLNT_CONTROL(client, CLGET_SVC_ADDR, (char *)&remote); 7908360efbdSAlfred Perlstein if (((address = (struct netbuf *) 7918360efbdSAlfred Perlstein malloc(sizeof (struct netbuf))) == NULL) || 7928360efbdSAlfred Perlstein ((address->buf = (char *) 7938360efbdSAlfred Perlstein malloc(remote.len)) == NULL)) { 7948360efbdSAlfred Perlstein rpc_createerr.cf_stat = RPC_SYSTEMERROR; 7958360efbdSAlfred Perlstein clnt_geterr(client, &rpc_createerr.cf_error); 7968360efbdSAlfred Perlstein free(address); 7978360efbdSAlfred Perlstein address = NULL; 7988360efbdSAlfred Perlstein goto error; 7998360efbdSAlfred Perlstein } 8008360efbdSAlfred Perlstein memcpy(address->buf, remote.buf, remote.len); 8018360efbdSAlfred Perlstein memcpy(&((char *)address->buf)[sizeof (short)], 8028360efbdSAlfred Perlstein (char *)(void *)&port, sizeof (short)); 8038360efbdSAlfred Perlstein address->len = address->maxlen = remote.len; 8048360efbdSAlfred Perlstein goto done; 8058360efbdSAlfred Perlstein } 8068360efbdSAlfred Perlstein #endif /* PORTMAP */ 8078360efbdSAlfred Perlstein 8088360efbdSAlfred Perlstein try_rpcbind: 8098360efbdSAlfred Perlstein /* 8104e37855eSAlfred Perlstein * Check if rpcbind is up. This prevents needless delays when 8114e37855eSAlfred Perlstein * accessing applications such as the keyserver while booting 8124e37855eSAlfred Perlstein * disklessly. 8134e37855eSAlfred Perlstein */ 8144e37855eSAlfred Perlstein if (check_rpcbind && strcmp(nconf->nc_protofmly, NC_LOOPBACK) == 0) { 8154e37855eSAlfred Perlstein if (!__rpcbind_is_up()) { 8164e37855eSAlfred Perlstein rpc_createerr.cf_stat = RPC_PMAPFAILURE; 8174e37855eSAlfred Perlstein rpc_createerr.cf_error.re_errno = 0; 8184e37855eSAlfred Perlstein goto error; 8194e37855eSAlfred Perlstein } 8204e37855eSAlfred Perlstein check_rpcbind = FALSE; 8214e37855eSAlfred Perlstein } 8224e37855eSAlfred Perlstein 8234e37855eSAlfred Perlstein /* 8248360efbdSAlfred Perlstein * Now we try version 4 and then 3. 8258360efbdSAlfred Perlstein * We also send the remote system the address we used to 8268360efbdSAlfred Perlstein * contact it in case it can help to connect back with us 8278360efbdSAlfred Perlstein */ 8288360efbdSAlfred Perlstein parms.r_prog = program; 8298360efbdSAlfred Perlstein parms.r_vers = version; 8308360efbdSAlfred Perlstein /*LINTED const castaway*/ 8318360efbdSAlfred Perlstein parms.r_owner = (char *) &nullstring[0]; /* not needed; */ 8328360efbdSAlfred Perlstein /* just for xdring */ 8338360efbdSAlfred Perlstein parms.r_netid = nconf->nc_netid; /* not really needed */ 8348360efbdSAlfred Perlstein 8358360efbdSAlfred Perlstein /* 8368360efbdSAlfred Perlstein * If a COTS transport is being used, try getting address via CLTS 8378360efbdSAlfred Perlstein * transport. This works only with version 4. 8388360efbdSAlfred Perlstein */ 8394e37855eSAlfred Perlstein if (nconf->nc_semantics == NC_TPI_COTS_ORD || 8404e37855eSAlfred Perlstein nconf->nc_semantics == NC_TPI_COTS) { 8414e37855eSAlfred Perlstein 8428360efbdSAlfred Perlstein void *handle; 8438360efbdSAlfred Perlstein struct netconfig *nconf_clts; 8448360efbdSAlfred Perlstein rpcb_entry_list_ptr relp = NULL; 8458360efbdSAlfred Perlstein 8468360efbdSAlfred Perlstein if (client == NULL) { 8478360efbdSAlfred Perlstein /* This did not go through the above PORTMAP/TCP code */ 8488360efbdSAlfred Perlstein if ((handle = __rpc_setconf("datagram_v")) != NULL) { 8498360efbdSAlfred Perlstein while ((nconf_clts = __rpc_getconf(handle)) 8508360efbdSAlfred Perlstein != NULL) { 8518360efbdSAlfred Perlstein if (strcmp(nconf_clts->nc_protofmly, 8528360efbdSAlfred Perlstein nconf->nc_protofmly) != 0) { 8538360efbdSAlfred Perlstein continue; 8548360efbdSAlfred Perlstein } 8558360efbdSAlfred Perlstein client = getclnthandle(host, nconf_clts, 8568360efbdSAlfred Perlstein &parms.r_addr); 8578360efbdSAlfred Perlstein break; 8588360efbdSAlfred Perlstein } 8598360efbdSAlfred Perlstein __rpc_endconf(handle); 8608360efbdSAlfred Perlstein } 8618360efbdSAlfred Perlstein if (client == NULL) 8628360efbdSAlfred Perlstein goto regular_rpcbind; /* Go the regular way */ 8638360efbdSAlfred Perlstein } else { 8648360efbdSAlfred Perlstein /* This is a UDP PORTMAP handle. Change to version 4 */ 8658360efbdSAlfred Perlstein vers = RPCBVERS4; 8668360efbdSAlfred Perlstein CLNT_CONTROL(client, CLSET_VERS, (char *)(void *)&vers); 8678360efbdSAlfred Perlstein } 8688360efbdSAlfred Perlstein /* 8698360efbdSAlfred Perlstein * We also send the remote system the address we used to 8708360efbdSAlfred Perlstein * contact it in case it can help it connect back with us 8718360efbdSAlfred Perlstein */ 8728360efbdSAlfred Perlstein if (parms.r_addr == NULL) { 8738360efbdSAlfred Perlstein /*LINTED const castaway*/ 8748360efbdSAlfred Perlstein parms.r_addr = (char *) &nullstring[0]; /* for XDRing */ 8758360efbdSAlfred Perlstein } 8764e37855eSAlfred Perlstein 8774e37855eSAlfred Perlstein CLNT_CONTROL(client, CLSET_RETRY_TIMEOUT, (char *)&rpcbrmttime); 8784e37855eSAlfred Perlstein 8798360efbdSAlfred Perlstein clnt_st = CLNT_CALL(client, (rpcproc_t)RPCBPROC_GETADDRLIST, 8808360efbdSAlfred Perlstein (xdrproc_t) xdr_rpcb, (char *)(void *)&parms, 8818360efbdSAlfred Perlstein (xdrproc_t) xdr_rpcb_entry_list_ptr, 8824e37855eSAlfred Perlstein (char *)(void *)&relp, *tp); 8838360efbdSAlfred Perlstein if (clnt_st == RPC_SUCCESS) { 8848360efbdSAlfred Perlstein if ((address = got_entry(relp, nconf)) != NULL) { 8858360efbdSAlfred Perlstein xdr_free((xdrproc_t) xdr_rpcb_entry_list_ptr, 8868360efbdSAlfred Perlstein (char *)(void *)&relp); 88777335102SMartin Blapp CLNT_CONTROL(client, CLGET_SVC_ADDR, 88877335102SMartin Blapp (char *)(void *)&servaddr); 88977335102SMartin Blapp __rpc_fixup_addr(address, &servaddr); 8908360efbdSAlfred Perlstein goto done; 8918360efbdSAlfred Perlstein } 8928360efbdSAlfred Perlstein /* Entry not found for this transport */ 8938360efbdSAlfred Perlstein xdr_free((xdrproc_t) xdr_rpcb_entry_list_ptr, 8948360efbdSAlfred Perlstein (char *)(void *)&relp); 8958360efbdSAlfred Perlstein /* 8968360efbdSAlfred Perlstein * XXX: should have perhaps returned with error but 8978360efbdSAlfred Perlstein * since the remote machine might not always be able 8988360efbdSAlfred Perlstein * to send the address on all transports, we try the 8998360efbdSAlfred Perlstein * regular way with regular_rpcbind 9008360efbdSAlfred Perlstein */ 9018360efbdSAlfred Perlstein goto regular_rpcbind; 9028360efbdSAlfred Perlstein } else if ((clnt_st == RPC_PROGVERSMISMATCH) || 9038360efbdSAlfred Perlstein (clnt_st == RPC_PROGUNAVAIL)) { 9048360efbdSAlfred Perlstein start_vers = RPCBVERS; /* Try version 3 now */ 9058360efbdSAlfred Perlstein goto regular_rpcbind; /* Try different versions */ 9068360efbdSAlfred Perlstein } else { 9078360efbdSAlfred Perlstein rpc_createerr.cf_stat = RPC_PMAPFAILURE; 9088360efbdSAlfred Perlstein clnt_geterr(client, &rpc_createerr.cf_error); 9098360efbdSAlfred Perlstein goto error; 9108360efbdSAlfred Perlstein } 9118360efbdSAlfred Perlstein } 9128360efbdSAlfred Perlstein 9138360efbdSAlfred Perlstein regular_rpcbind: 9148360efbdSAlfred Perlstein 9158360efbdSAlfred Perlstein /* Now the same transport is to be used to get the address */ 9168360efbdSAlfred Perlstein if (client && ((nconf->nc_semantics == NC_TPI_COTS_ORD) || 9178360efbdSAlfred Perlstein (nconf->nc_semantics == NC_TPI_COTS))) { 9188360efbdSAlfred Perlstein /* A CLTS type of client - destroy it */ 9198360efbdSAlfred Perlstein CLNT_DESTROY(client); 9208360efbdSAlfred Perlstein client = NULL; 9218360efbdSAlfred Perlstein } 9228360efbdSAlfred Perlstein 9238360efbdSAlfred Perlstein if (client == NULL) { 9248360efbdSAlfred Perlstein client = getclnthandle(host, nconf, &parms.r_addr); 9258360efbdSAlfred Perlstein if (client == NULL) { 9268360efbdSAlfred Perlstein goto error; 9278360efbdSAlfred Perlstein } 9288360efbdSAlfred Perlstein } 9298360efbdSAlfred Perlstein if (parms.r_addr == NULL) { 9308360efbdSAlfred Perlstein /*LINTED const castaway*/ 9318360efbdSAlfred Perlstein parms.r_addr = (char *) &nullstring[0]; 9328360efbdSAlfred Perlstein } 9338360efbdSAlfred Perlstein 9348360efbdSAlfred Perlstein /* First try from start_vers and then version 3 (RPCBVERS) */ 9354e37855eSAlfred Perlstein 9364e37855eSAlfred Perlstein CLNT_CONTROL(client, CLSET_RETRY_TIMEOUT, (char *) &rpcbrmttime); 9378360efbdSAlfred Perlstein for (vers = start_vers; vers >= RPCBVERS; vers--) { 9388360efbdSAlfred Perlstein /* Set the version */ 9398360efbdSAlfred Perlstein CLNT_CONTROL(client, CLSET_VERS, (char *)(void *)&vers); 9408360efbdSAlfred Perlstein clnt_st = CLNT_CALL(client, (rpcproc_t)RPCBPROC_GETADDR, 9418360efbdSAlfred Perlstein (xdrproc_t) xdr_rpcb, (char *)(void *)&parms, 9424e37855eSAlfred Perlstein (xdrproc_t) xdr_wrapstring, (char *)(void *) &ua, *tp); 9438360efbdSAlfred Perlstein if (clnt_st == RPC_SUCCESS) { 944b6c452a8SMartin Blapp if ((ua == NULL) || (ua[0] == 0)) { 9458360efbdSAlfred Perlstein /* address unknown */ 9468360efbdSAlfred Perlstein rpc_createerr.cf_stat = RPC_PROGNOTREGISTERED; 9478360efbdSAlfred Perlstein goto error; 9488360efbdSAlfred Perlstein } 9498360efbdSAlfred Perlstein address = uaddr2taddr(nconf, ua); 9508360efbdSAlfred Perlstein #ifdef ND_DEBUG 9518360efbdSAlfred Perlstein fprintf(stderr, "\tRemote address is [%s]\n", ua); 9528360efbdSAlfred Perlstein if (!address) 9538360efbdSAlfred Perlstein fprintf(stderr, 9548360efbdSAlfred Perlstein "\tCouldn't resolve remote address!\n"); 9558360efbdSAlfred Perlstein #endif 9568360efbdSAlfred Perlstein xdr_free((xdrproc_t)xdr_wrapstring, 9578360efbdSAlfred Perlstein (char *)(void *)&ua); 9588360efbdSAlfred Perlstein 9598360efbdSAlfred Perlstein if (! address) { 9608360efbdSAlfred Perlstein /* We don't know about your universal address */ 9618360efbdSAlfred Perlstein rpc_createerr.cf_stat = RPC_N2AXLATEFAILURE; 9628360efbdSAlfred Perlstein goto error; 9638360efbdSAlfred Perlstein } 9648360efbdSAlfred Perlstein CLNT_CONTROL(client, CLGET_SVC_ADDR, 9658360efbdSAlfred Perlstein (char *)(void *)&servaddr); 9668360efbdSAlfred Perlstein __rpc_fixup_addr(address, &servaddr); 9678360efbdSAlfred Perlstein goto done; 9688360efbdSAlfred Perlstein } else if (clnt_st == RPC_PROGVERSMISMATCH) { 9698360efbdSAlfred Perlstein struct rpc_err rpcerr; 9708360efbdSAlfred Perlstein 9718360efbdSAlfred Perlstein clnt_geterr(client, &rpcerr); 9728360efbdSAlfred Perlstein if (rpcerr.re_vers.low > RPCBVERS4) 9738360efbdSAlfred Perlstein goto error; /* a new version, can't handle */ 9748360efbdSAlfred Perlstein } else if (clnt_st != RPC_PROGUNAVAIL) { 9758360efbdSAlfred Perlstein /* Cant handle this error */ 9768360efbdSAlfred Perlstein rpc_createerr.cf_stat = clnt_st; 9778360efbdSAlfred Perlstein clnt_geterr(client, &rpc_createerr.cf_error); 9788360efbdSAlfred Perlstein goto error; 9798360efbdSAlfred Perlstein } 9808360efbdSAlfred Perlstein } 9818360efbdSAlfred Perlstein 9828360efbdSAlfred Perlstein error: 9838360efbdSAlfred Perlstein if (client) { 9848360efbdSAlfred Perlstein CLNT_DESTROY(client); 9858360efbdSAlfred Perlstein client = NULL; 9868360efbdSAlfred Perlstein } 9878360efbdSAlfred Perlstein done: 9888360efbdSAlfred Perlstein if (nconf->nc_semantics != NC_TPI_CLTS) { 9898360efbdSAlfred Perlstein /* This client is the connectionless one */ 9908360efbdSAlfred Perlstein if (client) { 9918360efbdSAlfred Perlstein CLNT_DESTROY(client); 9928360efbdSAlfred Perlstein client = NULL; 9938360efbdSAlfred Perlstein } 9948360efbdSAlfred Perlstein } 9958360efbdSAlfred Perlstein if (clpp) { 9968360efbdSAlfred Perlstein *clpp = client; 9978360efbdSAlfred Perlstein } else if (client) { 9988360efbdSAlfred Perlstein CLNT_DESTROY(client); 9998360efbdSAlfred Perlstein } 100052353da8SIan Dowse if (parms.r_addr != NULL && parms.r_addr != nullstring) 100152353da8SIan Dowse free(parms.r_addr); 10028360efbdSAlfred Perlstein return (address); 10038360efbdSAlfred Perlstein } 10048360efbdSAlfred Perlstein 10058360efbdSAlfred Perlstein 10068360efbdSAlfred Perlstein /* 10078360efbdSAlfred Perlstein * Find the mapped address for program, version. 10088360efbdSAlfred Perlstein * Calls the rpcbind service remotely to do the lookup. 10098360efbdSAlfred Perlstein * Uses the transport specified in nconf. 10108360efbdSAlfred Perlstein * Returns FALSE (0) if no map exists, else returns 1. 10118360efbdSAlfred Perlstein * 10128360efbdSAlfred Perlstein * Assuming that the address is all properly allocated 10138360efbdSAlfred Perlstein */ 101488609a6aSKevin Lo bool_t 101568895e38SCraig Rodrigues rpcb_getaddr(rpcprog_t program, rpcvers_t version, const struct netconfig *nconf, 101668895e38SCraig Rodrigues struct netbuf *address, const char *host) 10178360efbdSAlfred Perlstein { 10188360efbdSAlfred Perlstein struct netbuf *na; 10198360efbdSAlfred Perlstein 10204e37855eSAlfred Perlstein if ((na = __rpcb_findaddr_timed(program, version, 10214e37855eSAlfred Perlstein (struct netconfig *) nconf, (char *) host, 10224e37855eSAlfred Perlstein (CLIENT **) NULL, (struct timeval *) NULL)) == NULL) 10238360efbdSAlfred Perlstein return (FALSE); 10248360efbdSAlfred Perlstein 10258360efbdSAlfred Perlstein if (na->len > address->maxlen) { 10268360efbdSAlfred Perlstein /* Too long address */ 10278360efbdSAlfred Perlstein free(na->buf); 10288360efbdSAlfred Perlstein free(na); 10298360efbdSAlfred Perlstein rpc_createerr.cf_stat = RPC_FAILED; 10308360efbdSAlfred Perlstein return (FALSE); 10318360efbdSAlfred Perlstein } 10328360efbdSAlfred Perlstein memcpy(address->buf, na->buf, (size_t)na->len); 10338360efbdSAlfred Perlstein address->len = na->len; 10348360efbdSAlfred Perlstein free(na->buf); 10358360efbdSAlfred Perlstein free(na); 10368360efbdSAlfred Perlstein return (TRUE); 10378360efbdSAlfred Perlstein } 10388360efbdSAlfred Perlstein 10398360efbdSAlfred Perlstein /* 10408360efbdSAlfred Perlstein * Get a copy of the current maps. 10418360efbdSAlfred Perlstein * Calls the rpcbind service remotely to get the maps. 10428360efbdSAlfred Perlstein * 10438360efbdSAlfred Perlstein * It returns only a list of the services 10448360efbdSAlfred Perlstein * It returns NULL on failure. 10458360efbdSAlfred Perlstein */ 10468360efbdSAlfred Perlstein rpcblist * 104768895e38SCraig Rodrigues rpcb_getmaps(const struct netconfig *nconf, const char *host) 10488360efbdSAlfred Perlstein { 10498360efbdSAlfred Perlstein rpcblist_ptr head = NULL; 10508360efbdSAlfred Perlstein CLIENT *client; 10518360efbdSAlfred Perlstein enum clnt_stat clnt_st; 10528360efbdSAlfred Perlstein rpcvers_t vers = 0; 10538360efbdSAlfred Perlstein 10548360efbdSAlfred Perlstein client = getclnthandle(host, nconf, NULL); 10558360efbdSAlfred Perlstein if (client == NULL) { 10568360efbdSAlfred Perlstein return (head); 10578360efbdSAlfred Perlstein } 10588360efbdSAlfred Perlstein clnt_st = CLNT_CALL(client, (rpcproc_t)RPCBPROC_DUMP, 10598360efbdSAlfred Perlstein (xdrproc_t) xdr_void, NULL, (xdrproc_t) xdr_rpcblist_ptr, 10608360efbdSAlfred Perlstein (char *)(void *)&head, tottimeout); 10618360efbdSAlfred Perlstein if (clnt_st == RPC_SUCCESS) 10628360efbdSAlfred Perlstein goto done; 10638360efbdSAlfred Perlstein 10648360efbdSAlfred Perlstein if ((clnt_st != RPC_PROGVERSMISMATCH) && 10658360efbdSAlfred Perlstein (clnt_st != RPC_PROGUNAVAIL)) { 10668360efbdSAlfred Perlstein rpc_createerr.cf_stat = RPC_RPCBFAILURE; 10678360efbdSAlfred Perlstein clnt_geterr(client, &rpc_createerr.cf_error); 10688360efbdSAlfred Perlstein goto done; 10698360efbdSAlfred Perlstein } 10708360efbdSAlfred Perlstein 10718360efbdSAlfred Perlstein /* fall back to earlier version */ 10728360efbdSAlfred Perlstein CLNT_CONTROL(client, CLGET_VERS, (char *)(void *)&vers); 10738360efbdSAlfred Perlstein if (vers == RPCBVERS4) { 10748360efbdSAlfred Perlstein vers = RPCBVERS; 10758360efbdSAlfred Perlstein CLNT_CONTROL(client, CLSET_VERS, (char *)(void *)&vers); 10768360efbdSAlfred Perlstein if (CLNT_CALL(client, (rpcproc_t)RPCBPROC_DUMP, 10778360efbdSAlfred Perlstein (xdrproc_t) xdr_void, NULL, (xdrproc_t) xdr_rpcblist_ptr, 10788360efbdSAlfred Perlstein (char *)(void *)&head, tottimeout) == RPC_SUCCESS) 10798360efbdSAlfred Perlstein goto done; 10808360efbdSAlfred Perlstein } 10818360efbdSAlfred Perlstein rpc_createerr.cf_stat = RPC_RPCBFAILURE; 10828360efbdSAlfred Perlstein clnt_geterr(client, &rpc_createerr.cf_error); 10838360efbdSAlfred Perlstein 10848360efbdSAlfred Perlstein done: 10858360efbdSAlfred Perlstein CLNT_DESTROY(client); 10868360efbdSAlfred Perlstein return (head); 10878360efbdSAlfred Perlstein } 10888360efbdSAlfred Perlstein 10898360efbdSAlfred Perlstein /* 10908360efbdSAlfred Perlstein * rpcbinder remote-call-service interface. 10918360efbdSAlfred Perlstein * This routine is used to call the rpcbind remote call service 10928360efbdSAlfred Perlstein * which will look up a service program in the address maps, and then 10938360efbdSAlfred Perlstein * remotely call that routine with the given parameters. This allows 10948360efbdSAlfred Perlstein * programs to do a lookup and call in one step. 1095587cf682SCraig Rodrigues * 1096587cf682SCraig Rodrigues * nconf -Netconfig structure 1097587cf682SCraig Rodrigues * host - Remote host name 1098587cf682SCraig Rodrigues * proc - Remote proc identifiers 1099587cf682SCraig Rodrigues * xdrargs, xdrres; XDR routines 1100587cf682SCraig Rodrigues * argsp, resp - Argument and Result 1101587cf682SCraig Rodrigues * tout - Timeout value for this call 1102587cf682SCraig Rodrigues * addr_ptr - Preallocated netbuf address 11038360efbdSAlfred Perlstein */ 11048360efbdSAlfred Perlstein enum clnt_stat 1105587cf682SCraig Rodrigues rpcb_rmtcall(const struct netconfig *nconf, const char *host, rpcprog_t prog, 1106587cf682SCraig Rodrigues rpcvers_t vers, rpcproc_t proc, xdrproc_t xdrargs, caddr_t argsp, 1107587cf682SCraig Rodrigues xdrproc_t xdrres, caddr_t resp, struct timeval tout, 1108587cf682SCraig Rodrigues const struct netbuf *addr_ptr) 11098360efbdSAlfred Perlstein { 11108360efbdSAlfred Perlstein CLIENT *client; 11118360efbdSAlfred Perlstein enum clnt_stat stat; 11128360efbdSAlfred Perlstein struct r_rpcb_rmtcallargs a; 11138360efbdSAlfred Perlstein struct r_rpcb_rmtcallres r; 11148360efbdSAlfred Perlstein rpcvers_t rpcb_vers; 11158360efbdSAlfred Perlstein 111652353da8SIan Dowse stat = 0; 11178360efbdSAlfred Perlstein client = getclnthandle(host, nconf, NULL); 11188360efbdSAlfred Perlstein if (client == NULL) { 11198360efbdSAlfred Perlstein return (RPC_FAILED); 11208360efbdSAlfred Perlstein } 11218360efbdSAlfred Perlstein /*LINTED const castaway*/ 11228360efbdSAlfred Perlstein CLNT_CONTROL(client, CLSET_RETRY_TIMEOUT, (char *)(void *)&rmttimeout); 11238360efbdSAlfred Perlstein a.prog = prog; 11248360efbdSAlfred Perlstein a.vers = vers; 11258360efbdSAlfred Perlstein a.proc = proc; 11268360efbdSAlfred Perlstein a.args.args_val = argsp; 11278360efbdSAlfred Perlstein a.xdr_args = xdrargs; 11288360efbdSAlfred Perlstein r.addr = NULL; 11298360efbdSAlfred Perlstein r.results.results_val = resp; 11308360efbdSAlfred Perlstein r.xdr_res = xdrres; 11318360efbdSAlfred Perlstein 11328360efbdSAlfred Perlstein for (rpcb_vers = RPCBVERS4; rpcb_vers >= RPCBVERS; rpcb_vers--) { 11338360efbdSAlfred Perlstein CLNT_CONTROL(client, CLSET_VERS, (char *)(void *)&rpcb_vers); 11348360efbdSAlfred Perlstein stat = CLNT_CALL(client, (rpcproc_t)RPCBPROC_CALLIT, 11358360efbdSAlfred Perlstein (xdrproc_t) xdr_rpcb_rmtcallargs, (char *)(void *)&a, 11368360efbdSAlfred Perlstein (xdrproc_t) xdr_rpcb_rmtcallres, (char *)(void *)&r, tout); 11378360efbdSAlfred Perlstein if ((stat == RPC_SUCCESS) && (addr_ptr != NULL)) { 11388360efbdSAlfred Perlstein struct netbuf *na; 11398360efbdSAlfred Perlstein /*LINTED const castaway*/ 11408360efbdSAlfred Perlstein na = uaddr2taddr((struct netconfig *) nconf, r.addr); 11418360efbdSAlfred Perlstein if (!na) { 11428360efbdSAlfred Perlstein stat = RPC_N2AXLATEFAILURE; 11438360efbdSAlfred Perlstein /*LINTED const castaway*/ 11448360efbdSAlfred Perlstein ((struct netbuf *) addr_ptr)->len = 0; 11458360efbdSAlfred Perlstein goto error; 11468360efbdSAlfred Perlstein } 11478360efbdSAlfred Perlstein if (na->len > addr_ptr->maxlen) { 11488360efbdSAlfred Perlstein /* Too long address */ 11498360efbdSAlfred Perlstein stat = RPC_FAILED; /* XXX A better error no */ 11508360efbdSAlfred Perlstein free(na->buf); 11518360efbdSAlfred Perlstein free(na); 11528360efbdSAlfred Perlstein /*LINTED const castaway*/ 11538360efbdSAlfred Perlstein ((struct netbuf *) addr_ptr)->len = 0; 11548360efbdSAlfred Perlstein goto error; 11558360efbdSAlfred Perlstein } 11568360efbdSAlfred Perlstein memcpy(addr_ptr->buf, na->buf, (size_t)na->len); 11578360efbdSAlfred Perlstein /*LINTED const castaway*/ 11588360efbdSAlfred Perlstein ((struct netbuf *)addr_ptr)->len = na->len; 11598360efbdSAlfred Perlstein free(na->buf); 11608360efbdSAlfred Perlstein free(na); 11618360efbdSAlfred Perlstein break; 11628360efbdSAlfred Perlstein } else if ((stat != RPC_PROGVERSMISMATCH) && 11638360efbdSAlfred Perlstein (stat != RPC_PROGUNAVAIL)) { 11648360efbdSAlfred Perlstein goto error; 11658360efbdSAlfred Perlstein } 11668360efbdSAlfred Perlstein } 11678360efbdSAlfred Perlstein error: 11688360efbdSAlfred Perlstein CLNT_DESTROY(client); 11698360efbdSAlfred Perlstein if (r.addr) 11708360efbdSAlfred Perlstein xdr_free((xdrproc_t) xdr_wrapstring, (char *)(void *)&r.addr); 11718360efbdSAlfred Perlstein return (stat); 11728360efbdSAlfred Perlstein } 11738360efbdSAlfred Perlstein 11748360efbdSAlfred Perlstein /* 11758360efbdSAlfred Perlstein * Gets the time on the remote host. 11768360efbdSAlfred Perlstein * Returns 1 if succeeds else 0. 11778360efbdSAlfred Perlstein */ 11788360efbdSAlfred Perlstein bool_t 117968895e38SCraig Rodrigues rpcb_gettime(const char *host, time_t *timep) 11808360efbdSAlfred Perlstein { 11818360efbdSAlfred Perlstein CLIENT *client = NULL; 11828360efbdSAlfred Perlstein void *handle; 11838360efbdSAlfred Perlstein struct netconfig *nconf; 11848360efbdSAlfred Perlstein rpcvers_t vers; 11858360efbdSAlfred Perlstein enum clnt_stat st; 11868360efbdSAlfred Perlstein 11878360efbdSAlfred Perlstein 1188b6c452a8SMartin Blapp if ((host == NULL) || (host[0] == 0)) { 11898360efbdSAlfred Perlstein time(timep); 11908360efbdSAlfred Perlstein return (TRUE); 11918360efbdSAlfred Perlstein } 11928360efbdSAlfred Perlstein 11938360efbdSAlfred Perlstein if ((handle = __rpc_setconf("netpath")) == NULL) { 11948360efbdSAlfred Perlstein rpc_createerr.cf_stat = RPC_UNKNOWNPROTO; 11958360efbdSAlfred Perlstein return (FALSE); 11968360efbdSAlfred Perlstein } 11978360efbdSAlfred Perlstein rpc_createerr.cf_stat = RPC_SUCCESS; 11988360efbdSAlfred Perlstein while (client == NULL) { 11998360efbdSAlfred Perlstein if ((nconf = __rpc_getconf(handle)) == NULL) { 12008360efbdSAlfred Perlstein if (rpc_createerr.cf_stat == RPC_SUCCESS) 12018360efbdSAlfred Perlstein rpc_createerr.cf_stat = RPC_UNKNOWNPROTO; 12028360efbdSAlfred Perlstein break; 12038360efbdSAlfred Perlstein } 12048360efbdSAlfred Perlstein client = getclnthandle(host, nconf, NULL); 12058360efbdSAlfred Perlstein if (client) 12068360efbdSAlfred Perlstein break; 12078360efbdSAlfred Perlstein } 12088360efbdSAlfred Perlstein __rpc_endconf(handle); 12098360efbdSAlfred Perlstein if (client == (CLIENT *) NULL) { 12108360efbdSAlfred Perlstein return (FALSE); 12118360efbdSAlfred Perlstein } 12128360efbdSAlfred Perlstein 12138360efbdSAlfred Perlstein st = CLNT_CALL(client, (rpcproc_t)RPCBPROC_GETTIME, 12148360efbdSAlfred Perlstein (xdrproc_t) xdr_void, NULL, 12158360efbdSAlfred Perlstein (xdrproc_t) xdr_int, (char *)(void *)timep, tottimeout); 12168360efbdSAlfred Perlstein 12178360efbdSAlfred Perlstein if ((st == RPC_PROGVERSMISMATCH) || (st == RPC_PROGUNAVAIL)) { 12188360efbdSAlfred Perlstein CLNT_CONTROL(client, CLGET_VERS, (char *)(void *)&vers); 12198360efbdSAlfred Perlstein if (vers == RPCBVERS4) { 12208360efbdSAlfred Perlstein /* fall back to earlier version */ 12218360efbdSAlfred Perlstein vers = RPCBVERS; 12228360efbdSAlfred Perlstein CLNT_CONTROL(client, CLSET_VERS, (char *)(void *)&vers); 12238360efbdSAlfred Perlstein st = CLNT_CALL(client, (rpcproc_t)RPCBPROC_GETTIME, 12248360efbdSAlfred Perlstein (xdrproc_t) xdr_void, NULL, 12258360efbdSAlfred Perlstein (xdrproc_t) xdr_int, (char *)(void *)timep, 12268360efbdSAlfred Perlstein tottimeout); 12278360efbdSAlfred Perlstein } 12288360efbdSAlfred Perlstein } 12298360efbdSAlfred Perlstein CLNT_DESTROY(client); 12308360efbdSAlfred Perlstein return (st == RPC_SUCCESS? TRUE: FALSE); 12318360efbdSAlfred Perlstein } 12328360efbdSAlfred Perlstein 12338360efbdSAlfred Perlstein /* 12348360efbdSAlfred Perlstein * Converts taddr to universal address. This routine should never 12358360efbdSAlfred Perlstein * really be called because local n2a libraries are always provided. 12368360efbdSAlfred Perlstein */ 12378360efbdSAlfred Perlstein char * 123868895e38SCraig Rodrigues rpcb_taddr2uaddr(struct netconfig *nconf, struct netbuf *taddr) 12398360efbdSAlfred Perlstein { 12408360efbdSAlfred Perlstein CLIENT *client; 12418360efbdSAlfred Perlstein char *uaddr = NULL; 12428360efbdSAlfred Perlstein 12438360efbdSAlfred Perlstein 12448360efbdSAlfred Perlstein /* parameter checking */ 12458360efbdSAlfred Perlstein if (nconf == NULL) { 12468360efbdSAlfred Perlstein rpc_createerr.cf_stat = RPC_UNKNOWNPROTO; 12478360efbdSAlfred Perlstein return (NULL); 12488360efbdSAlfred Perlstein } 12498360efbdSAlfred Perlstein if (taddr == NULL) { 12508360efbdSAlfred Perlstein rpc_createerr.cf_stat = RPC_UNKNOWNADDR; 12518360efbdSAlfred Perlstein return (NULL); 12528360efbdSAlfred Perlstein } 12538360efbdSAlfred Perlstein client = local_rpcb(); 12548360efbdSAlfred Perlstein if (! client) { 12558360efbdSAlfred Perlstein return (NULL); 12568360efbdSAlfred Perlstein } 12578360efbdSAlfred Perlstein 12588360efbdSAlfred Perlstein CLNT_CALL(client, (rpcproc_t)RPCBPROC_TADDR2UADDR, 12598360efbdSAlfred Perlstein (xdrproc_t) xdr_netbuf, (char *)(void *)taddr, 12608360efbdSAlfred Perlstein (xdrproc_t) xdr_wrapstring, (char *)(void *)&uaddr, tottimeout); 12618360efbdSAlfred Perlstein CLNT_DESTROY(client); 12628360efbdSAlfred Perlstein return (uaddr); 12638360efbdSAlfred Perlstein } 12648360efbdSAlfred Perlstein 12658360efbdSAlfred Perlstein /* 12668360efbdSAlfred Perlstein * Converts universal address to netbuf. This routine should never 12678360efbdSAlfred Perlstein * really be called because local n2a libraries are always provided. 12688360efbdSAlfred Perlstein */ 12698360efbdSAlfred Perlstein struct netbuf * 127068895e38SCraig Rodrigues rpcb_uaddr2taddr(struct netconfig *nconf, char *uaddr) 12718360efbdSAlfred Perlstein { 12728360efbdSAlfred Perlstein CLIENT *client; 12738360efbdSAlfred Perlstein struct netbuf *taddr; 12748360efbdSAlfred Perlstein 12758360efbdSAlfred Perlstein 12768360efbdSAlfred Perlstein /* parameter checking */ 12778360efbdSAlfred Perlstein if (nconf == NULL) { 12788360efbdSAlfred Perlstein rpc_createerr.cf_stat = RPC_UNKNOWNPROTO; 12798360efbdSAlfred Perlstein return (NULL); 12808360efbdSAlfred Perlstein } 12818360efbdSAlfred Perlstein if (uaddr == NULL) { 12828360efbdSAlfred Perlstein rpc_createerr.cf_stat = RPC_UNKNOWNADDR; 12838360efbdSAlfred Perlstein return (NULL); 12848360efbdSAlfred Perlstein } 12858360efbdSAlfred Perlstein client = local_rpcb(); 12868360efbdSAlfred Perlstein if (! client) { 12878360efbdSAlfred Perlstein return (NULL); 12888360efbdSAlfred Perlstein } 12898360efbdSAlfred Perlstein 12908360efbdSAlfred Perlstein taddr = (struct netbuf *)calloc(1, sizeof (struct netbuf)); 12918360efbdSAlfred Perlstein if (taddr == NULL) { 12928360efbdSAlfred Perlstein CLNT_DESTROY(client); 12938360efbdSAlfred Perlstein return (NULL); 12948360efbdSAlfred Perlstein } 12958360efbdSAlfred Perlstein if (CLNT_CALL(client, (rpcproc_t)RPCBPROC_UADDR2TADDR, 12968360efbdSAlfred Perlstein (xdrproc_t) xdr_wrapstring, (char *)(void *)&uaddr, 12978360efbdSAlfred Perlstein (xdrproc_t) xdr_netbuf, (char *)(void *)taddr, 12988360efbdSAlfred Perlstein tottimeout) != RPC_SUCCESS) { 12998360efbdSAlfred Perlstein free(taddr); 13008360efbdSAlfred Perlstein taddr = NULL; 13018360efbdSAlfred Perlstein } 13028360efbdSAlfred Perlstein CLNT_DESTROY(client); 13038360efbdSAlfred Perlstein return (taddr); 13048360efbdSAlfred Perlstein } 1305