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