18360efbdSAlfred Perlstein /* $NetBSD: rpcb_clnt.c,v 1.6 2000/07/16 06:41:43 itojun Exp $ */ 28360efbdSAlfred Perlstein 38360efbdSAlfred Perlstein /* 44e37855eSAlfred Perlstein * The contents of this file are subject to the Sun Standards 54e37855eSAlfred Perlstein * License Version 1.0 the (the "License";) You may not use 64e37855eSAlfred Perlstein * this file except in compliance with the License. You may 74e37855eSAlfred Perlstein * obtain a copy of the License at lib/libc/rpc/LICENSE 84e37855eSAlfred Perlstein * 94e37855eSAlfred Perlstein * Software distributed under the License is distributed on 104e37855eSAlfred Perlstein * an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either 114e37855eSAlfred Perlstein * express or implied. See the License for the specific 124e37855eSAlfred Perlstein * language governing rights and limitations under the License. 134e37855eSAlfred Perlstein * 144e37855eSAlfred Perlstein * The Original Code is Copyright 1998 by Sun Microsystems, Inc 154e37855eSAlfred Perlstein * 164e37855eSAlfred Perlstein * The Initial Developer of the Original Code is: Sun 174e37855eSAlfred Perlstein * Microsystems, Inc. 184e37855eSAlfred Perlstein * 194e37855eSAlfred Perlstein * All Rights Reserved. 204e37855eSAlfred Perlstein * 218360efbdSAlfred Perlstein * Sun RPC is a product of Sun Microsystems, Inc. and is provided for 228360efbdSAlfred Perlstein * unrestricted use provided that this legend is included on all tape 238360efbdSAlfred Perlstein * media and as a part of the software program in whole or part. Users 248360efbdSAlfred Perlstein * may copy or modify Sun RPC without charge, but are not authorized 258360efbdSAlfred Perlstein * to license or distribute it to anyone else except as part of a product or 268360efbdSAlfred Perlstein * program developed by the user. 278360efbdSAlfred Perlstein * 288360efbdSAlfred Perlstein * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE 298360efbdSAlfred Perlstein * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR 308360efbdSAlfred Perlstein * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. 318360efbdSAlfred Perlstein * 328360efbdSAlfred Perlstein * Sun RPC is provided with no support and without any obligation on the 338360efbdSAlfred Perlstein * part of Sun Microsystems, Inc. to assist in its use, correction, 348360efbdSAlfred Perlstein * modification or enhancement. 358360efbdSAlfred Perlstein * 368360efbdSAlfred Perlstein * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE 378360efbdSAlfred Perlstein * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC 388360efbdSAlfred Perlstein * OR ANY PART THEREOF. 398360efbdSAlfred Perlstein * 408360efbdSAlfred Perlstein * In no event will Sun Microsystems, Inc. be liable for any lost revenue 418360efbdSAlfred Perlstein * or profits or other special, indirect and consequential damages, even if 428360efbdSAlfred Perlstein * Sun has been advised of the possibility of such damages. 438360efbdSAlfred Perlstein * 448360efbdSAlfred Perlstein * Sun Microsystems, Inc. 458360efbdSAlfred Perlstein * 2550 Garcia Avenue 468360efbdSAlfred Perlstein * Mountain View, California 94043 478360efbdSAlfred Perlstein */ 488360efbdSAlfred Perlstein /* 498360efbdSAlfred Perlstein * Copyright (c) 1986-1991 by Sun Microsystems Inc. 508360efbdSAlfred Perlstein */ 518360efbdSAlfred Perlstein 528360efbdSAlfred Perlstein /* #ident "@(#)rpcb_clnt.c 1.27 94/04/24 SMI" */ 538360efbdSAlfred Perlstein 548360efbdSAlfred Perlstein 55a986ef57SDavid E. O'Brien #if defined(LIBC_SCCS) && !defined(lint) 568360efbdSAlfred Perlstein static char sccsid[] = "@(#)rpcb_clnt.c 1.30 89/06/21 Copyr 1988 Sun Micro"; 578360efbdSAlfred Perlstein #endif 58d3d20c82SDavid E. O'Brien #include <sys/cdefs.h> 59d3d20c82SDavid E. O'Brien __FBSDID("$FreeBSD$"); 608360efbdSAlfred Perlstein 618360efbdSAlfred Perlstein /* 628360efbdSAlfred Perlstein * rpcb_clnt.c 638360efbdSAlfred Perlstein * interface to rpcbind rpc service. 648360efbdSAlfred Perlstein * 658360efbdSAlfred Perlstein * Copyright (C) 1988, Sun Microsystems, Inc. 668360efbdSAlfred Perlstein */ 678360efbdSAlfred Perlstein 688360efbdSAlfred Perlstein #include "namespace.h" 699f5afc13SIan Dowse #include "reentrant.h" 708360efbdSAlfred Perlstein #include <sys/types.h> 718360efbdSAlfred Perlstein #include <sys/socket.h> 728360efbdSAlfred Perlstein #include <sys/un.h> 738360efbdSAlfred Perlstein #include <sys/utsname.h> 748360efbdSAlfred Perlstein #include <rpc/rpc.h> 758360efbdSAlfred Perlstein #include <rpc/rpcb_prot.h> 768360efbdSAlfred Perlstein #include <rpc/nettype.h> 778360efbdSAlfred Perlstein #include <netconfig.h> 788360efbdSAlfred Perlstein #ifdef PORTMAP 798360efbdSAlfred Perlstein #include <netinet/in.h> /* FOR IPPROTO_TCP/UDP definitions */ 808360efbdSAlfred Perlstein #include <rpc/pmap_prot.h> 818360efbdSAlfred Perlstein #endif /* PORTMAP */ 828360efbdSAlfred Perlstein #include <stdio.h> 838360efbdSAlfred Perlstein #include <errno.h> 848360efbdSAlfred Perlstein #include <stdlib.h> 858360efbdSAlfred Perlstein #include <string.h> 868360efbdSAlfred Perlstein #include <unistd.h> 878360efbdSAlfred Perlstein #include <netdb.h> 888360efbdSAlfred Perlstein #include <syslog.h> 898360efbdSAlfred Perlstein #include "un-namespace.h" 908360efbdSAlfred Perlstein 918360efbdSAlfred Perlstein #include "rpc_com.h" 92235baf26SDaniel Eischen #include "mt_misc.h" 938360efbdSAlfred Perlstein 948360efbdSAlfred Perlstein static struct timeval tottimeout = { 60, 0 }; 958360efbdSAlfred Perlstein static const struct timeval rmttimeout = { 3, 0 }; 964e37855eSAlfred Perlstein static struct timeval rpcbrmttime = { 15, 0 }; 978360efbdSAlfred Perlstein 98c05ac53bSDavid E. O'Brien extern bool_t xdr_wrapstring(XDR *, char **); 998360efbdSAlfred Perlstein 1008360efbdSAlfred Perlstein static const char nullstring[] = "\000"; 1018360efbdSAlfred Perlstein 1028360efbdSAlfred Perlstein #define CACHESIZE 6 1038360efbdSAlfred Perlstein 1048360efbdSAlfred Perlstein struct address_cache { 1058360efbdSAlfred Perlstein char *ac_host; 1068360efbdSAlfred Perlstein char *ac_netid; 1078360efbdSAlfred Perlstein char *ac_uaddr; 1088360efbdSAlfred Perlstein struct netbuf *ac_taddr; 1098360efbdSAlfred Perlstein struct address_cache *ac_next; 1108360efbdSAlfred Perlstein }; 1118360efbdSAlfred Perlstein 1128360efbdSAlfred Perlstein static struct address_cache *front; 1138360efbdSAlfred Perlstein static int cachesize; 1148360efbdSAlfred Perlstein 1158360efbdSAlfred Perlstein #define CLCR_GET_RPCB_TIMEOUT 1 1168360efbdSAlfred Perlstein #define CLCR_SET_RPCB_TIMEOUT 2 1178360efbdSAlfred Perlstein 1188360efbdSAlfred Perlstein 1198360efbdSAlfred Perlstein extern int __rpc_lowvers; 1208360efbdSAlfred Perlstein 121c05ac53bSDavid E. O'Brien static struct address_cache *check_cache(const char *, const char *); 122c05ac53bSDavid E. O'Brien static void delete_cache(struct netbuf *); 1231372519bSDavid E. O'Brien static void add_cache(const char *, const char *, struct netbuf *, char *); 1241372519bSDavid E. O'Brien static CLIENT *getclnthandle(const char *, const struct netconfig *, char **); 125c05ac53bSDavid E. O'Brien static CLIENT *local_rpcb(void); 1261372519bSDavid E. O'Brien static struct netbuf *got_entry(rpcb_entry_list_ptr, const struct netconfig *); 1278360efbdSAlfred Perlstein 1288360efbdSAlfred Perlstein /* 1298360efbdSAlfred Perlstein * This routine adjusts the timeout used for calls to the remote rpcbind. 1308360efbdSAlfred Perlstein * Also, this routine can be used to set the use of portmapper version 2 1318360efbdSAlfred Perlstein * only when doing rpc_broadcasts 1328360efbdSAlfred Perlstein * These are private routines that may not be provided in future releases. 1338360efbdSAlfred Perlstein */ 1348360efbdSAlfred Perlstein bool_t 1358360efbdSAlfred Perlstein __rpc_control(request, info) 1368360efbdSAlfred Perlstein int request; 1378360efbdSAlfred Perlstein void *info; 1388360efbdSAlfred Perlstein { 1398360efbdSAlfred Perlstein switch (request) { 1408360efbdSAlfred Perlstein case CLCR_GET_RPCB_TIMEOUT: 1418360efbdSAlfred Perlstein *(struct timeval *)info = tottimeout; 1428360efbdSAlfred Perlstein break; 1438360efbdSAlfred Perlstein case CLCR_SET_RPCB_TIMEOUT: 1448360efbdSAlfred Perlstein tottimeout = *(struct timeval *)info; 1458360efbdSAlfred Perlstein break; 1468360efbdSAlfred Perlstein case CLCR_SET_LOWVERS: 1478360efbdSAlfred Perlstein __rpc_lowvers = *(int *)info; 1488360efbdSAlfred Perlstein break; 1498360efbdSAlfred Perlstein case CLCR_GET_LOWVERS: 1508360efbdSAlfred Perlstein *(int *)info = __rpc_lowvers; 1518360efbdSAlfred Perlstein break; 1528360efbdSAlfred Perlstein default: 1538360efbdSAlfred Perlstein return (FALSE); 1548360efbdSAlfred Perlstein } 1558360efbdSAlfred Perlstein return (TRUE); 1568360efbdSAlfred Perlstein } 1578360efbdSAlfred Perlstein 1588360efbdSAlfred Perlstein /* 1598360efbdSAlfred Perlstein * It might seem that a reader/writer lock would be more reasonable here. 1608360efbdSAlfred Perlstein * However because getclnthandle(), the only user of the cache functions, 1618360efbdSAlfred Perlstein * may do a delete_cache() operation if a check_cache() fails to return an 1628360efbdSAlfred Perlstein * address useful to clnt_tli_create(), we may as well use a mutex. 1638360efbdSAlfred Perlstein */ 1648360efbdSAlfred Perlstein /* 1658360efbdSAlfred Perlstein * As it turns out, if the cache lock is *not* a reader/writer lock, we will 1668360efbdSAlfred Perlstein * block all clnt_create's if we are trying to connect to a host that's down, 1678360efbdSAlfred Perlstein * since the lock will be held all during that time. 1688360efbdSAlfred Perlstein */ 1698360efbdSAlfred Perlstein 1708360efbdSAlfred Perlstein /* 1718360efbdSAlfred Perlstein * The routines check_cache(), add_cache(), delete_cache() manage the 1728360efbdSAlfred Perlstein * cache of rpcbind addresses for (host, netid). 1738360efbdSAlfred Perlstein */ 1748360efbdSAlfred Perlstein 1758360efbdSAlfred Perlstein static struct address_cache * 1768360efbdSAlfred Perlstein check_cache(host, netid) 1778360efbdSAlfred Perlstein const char *host, *netid; 1788360efbdSAlfred Perlstein { 1798360efbdSAlfred Perlstein struct address_cache *cptr; 1808360efbdSAlfred Perlstein 1818360efbdSAlfred Perlstein /* READ LOCK HELD ON ENTRY: rpcbaddr_cache_lock */ 1828360efbdSAlfred Perlstein 1838360efbdSAlfred Perlstein for (cptr = front; cptr != NULL; cptr = cptr->ac_next) { 1848360efbdSAlfred Perlstein if (!strcmp(cptr->ac_host, host) && 1858360efbdSAlfred Perlstein !strcmp(cptr->ac_netid, netid)) { 1868360efbdSAlfred Perlstein #ifdef ND_DEBUG 1878360efbdSAlfred Perlstein fprintf(stderr, "Found cache entry for %s: %s\n", 1888360efbdSAlfred Perlstein host, netid); 1898360efbdSAlfred Perlstein #endif 1908360efbdSAlfred Perlstein return (cptr); 1918360efbdSAlfred Perlstein } 1928360efbdSAlfred Perlstein } 1938360efbdSAlfred Perlstein return ((struct address_cache *) NULL); 1948360efbdSAlfred Perlstein } 1958360efbdSAlfred Perlstein 1968360efbdSAlfred Perlstein static void 1978360efbdSAlfred Perlstein delete_cache(addr) 1988360efbdSAlfred Perlstein struct netbuf *addr; 1998360efbdSAlfred Perlstein { 2008360efbdSAlfred Perlstein struct address_cache *cptr, *prevptr = NULL; 2018360efbdSAlfred Perlstein 2028360efbdSAlfred Perlstein /* WRITE LOCK HELD ON ENTRY: rpcbaddr_cache_lock */ 2038360efbdSAlfred Perlstein for (cptr = front; cptr != NULL; cptr = cptr->ac_next) { 2048360efbdSAlfred Perlstein if (!memcmp(cptr->ac_taddr->buf, addr->buf, addr->len)) { 2058360efbdSAlfred Perlstein free(cptr->ac_host); 2068360efbdSAlfred Perlstein free(cptr->ac_netid); 2078360efbdSAlfred Perlstein free(cptr->ac_taddr->buf); 2088360efbdSAlfred Perlstein free(cptr->ac_taddr); 2098360efbdSAlfred Perlstein if (cptr->ac_uaddr) 2108360efbdSAlfred Perlstein free(cptr->ac_uaddr); 2118360efbdSAlfred Perlstein if (prevptr) 2128360efbdSAlfred Perlstein prevptr->ac_next = cptr->ac_next; 2138360efbdSAlfred Perlstein else 2148360efbdSAlfred Perlstein front = cptr->ac_next; 2158360efbdSAlfred Perlstein free(cptr); 2168360efbdSAlfred Perlstein cachesize--; 2178360efbdSAlfred Perlstein break; 2188360efbdSAlfred Perlstein } 2198360efbdSAlfred Perlstein prevptr = cptr; 2208360efbdSAlfred Perlstein } 2218360efbdSAlfred Perlstein } 2228360efbdSAlfred Perlstein 2238360efbdSAlfred Perlstein static void 2248360efbdSAlfred Perlstein add_cache(host, netid, taddr, uaddr) 2258360efbdSAlfred Perlstein const char *host, *netid; 2268360efbdSAlfred Perlstein char *uaddr; 2278360efbdSAlfred Perlstein struct netbuf *taddr; 2288360efbdSAlfred Perlstein { 2298360efbdSAlfred Perlstein struct address_cache *ad_cache, *cptr, *prevptr; 2308360efbdSAlfred Perlstein 2318360efbdSAlfred Perlstein ad_cache = (struct address_cache *) 2328360efbdSAlfred Perlstein malloc(sizeof (struct address_cache)); 2338360efbdSAlfred Perlstein if (!ad_cache) { 2348360efbdSAlfred Perlstein return; 2358360efbdSAlfred Perlstein } 2368360efbdSAlfred Perlstein ad_cache->ac_host = strdup(host); 2378360efbdSAlfred Perlstein ad_cache->ac_netid = strdup(netid); 2388360efbdSAlfred Perlstein ad_cache->ac_uaddr = uaddr ? strdup(uaddr) : NULL; 2398360efbdSAlfred Perlstein ad_cache->ac_taddr = (struct netbuf *)malloc(sizeof (struct netbuf)); 2408360efbdSAlfred Perlstein if (!ad_cache->ac_host || !ad_cache->ac_netid || !ad_cache->ac_taddr || 2418360efbdSAlfred Perlstein (uaddr && !ad_cache->ac_uaddr)) { 242f340bd40SMartin Blapp goto out; 2438360efbdSAlfred Perlstein } 2448360efbdSAlfred Perlstein ad_cache->ac_taddr->len = ad_cache->ac_taddr->maxlen = taddr->len; 2458360efbdSAlfred Perlstein ad_cache->ac_taddr->buf = (char *) malloc(taddr->len); 2468360efbdSAlfred Perlstein if (ad_cache->ac_taddr->buf == NULL) { 247f340bd40SMartin Blapp out: 248f340bd40SMartin Blapp if (ad_cache->ac_host) 249f340bd40SMartin Blapp free(ad_cache->ac_host); 250f340bd40SMartin Blapp if (ad_cache->ac_netid) 251f340bd40SMartin Blapp free(ad_cache->ac_netid); 252f340bd40SMartin Blapp if (ad_cache->ac_uaddr) 253f340bd40SMartin Blapp free(ad_cache->ac_uaddr); 254f340bd40SMartin Blapp if (ad_cache->ac_taddr) 255f340bd40SMartin Blapp free(ad_cache->ac_taddr); 256f340bd40SMartin Blapp free(ad_cache); 2578360efbdSAlfred Perlstein return; 2588360efbdSAlfred Perlstein } 2598360efbdSAlfred Perlstein memcpy(ad_cache->ac_taddr->buf, taddr->buf, taddr->len); 2608360efbdSAlfred Perlstein #ifdef ND_DEBUG 2618360efbdSAlfred Perlstein fprintf(stderr, "Added to cache: %s : %s\n", host, netid); 2628360efbdSAlfred Perlstein #endif 2638360efbdSAlfred Perlstein 2648360efbdSAlfred Perlstein /* VARIABLES PROTECTED BY rpcbaddr_cache_lock: cptr */ 2658360efbdSAlfred Perlstein 2668360efbdSAlfred Perlstein rwlock_wrlock(&rpcbaddr_cache_lock); 2678360efbdSAlfred Perlstein if (cachesize < CACHESIZE) { 2688360efbdSAlfred Perlstein ad_cache->ac_next = front; 2698360efbdSAlfred Perlstein front = ad_cache; 2708360efbdSAlfred Perlstein cachesize++; 2718360efbdSAlfred Perlstein } else { 2728360efbdSAlfred Perlstein /* Free the last entry */ 2738360efbdSAlfred Perlstein cptr = front; 2748360efbdSAlfred Perlstein prevptr = NULL; 2758360efbdSAlfred Perlstein while (cptr->ac_next) { 2768360efbdSAlfred Perlstein prevptr = cptr; 2778360efbdSAlfred Perlstein cptr = cptr->ac_next; 2788360efbdSAlfred Perlstein } 2798360efbdSAlfred Perlstein 2808360efbdSAlfred Perlstein #ifdef ND_DEBUG 2818360efbdSAlfred Perlstein fprintf(stderr, "Deleted from cache: %s : %s\n", 2828360efbdSAlfred Perlstein cptr->ac_host, cptr->ac_netid); 2838360efbdSAlfred Perlstein #endif 2848360efbdSAlfred Perlstein free(cptr->ac_host); 2858360efbdSAlfred Perlstein free(cptr->ac_netid); 2868360efbdSAlfred Perlstein free(cptr->ac_taddr->buf); 2878360efbdSAlfred Perlstein free(cptr->ac_taddr); 2888360efbdSAlfred Perlstein if (cptr->ac_uaddr) 2898360efbdSAlfred Perlstein free(cptr->ac_uaddr); 2908360efbdSAlfred Perlstein 2918360efbdSAlfred Perlstein if (prevptr) { 2928360efbdSAlfred Perlstein prevptr->ac_next = NULL; 2938360efbdSAlfred Perlstein ad_cache->ac_next = front; 2948360efbdSAlfred Perlstein front = ad_cache; 2958360efbdSAlfred Perlstein } else { 2968360efbdSAlfred Perlstein front = ad_cache; 2978360efbdSAlfred Perlstein ad_cache->ac_next = NULL; 2988360efbdSAlfred Perlstein } 2998360efbdSAlfred Perlstein free(cptr); 3008360efbdSAlfred Perlstein } 3018360efbdSAlfred Perlstein rwlock_unlock(&rpcbaddr_cache_lock); 3028360efbdSAlfred Perlstein } 3038360efbdSAlfred Perlstein 3048360efbdSAlfred Perlstein /* 3058360efbdSAlfred Perlstein * This routine will return a client handle that is connected to the 306e73bb7f1SIan Dowse * rpcbind. If targaddr is non-NULL, the "universal address" of the 307e73bb7f1SIan Dowse * host will be stored in *targaddr; the caller is responsible for 308e73bb7f1SIan Dowse * freeing this string. 309e73bb7f1SIan Dowse * On error, returns NULL and free's everything. 3108360efbdSAlfred Perlstein */ 3118360efbdSAlfred Perlstein static CLIENT * 3128360efbdSAlfred Perlstein getclnthandle(host, nconf, targaddr) 3138360efbdSAlfred Perlstein const char *host; 3148360efbdSAlfred Perlstein const struct netconfig *nconf; 3158360efbdSAlfred Perlstein char **targaddr; 3168360efbdSAlfred Perlstein { 3178360efbdSAlfred Perlstein CLIENT *client; 3188360efbdSAlfred Perlstein struct netbuf *addr, taddr; 3198360efbdSAlfred Perlstein struct netbuf addr_to_delete; 3208360efbdSAlfred Perlstein struct __rpc_sockinfo si; 3218360efbdSAlfred Perlstein struct addrinfo hints, *res, *tres; 3228360efbdSAlfred Perlstein struct address_cache *ad_cache; 3238360efbdSAlfred Perlstein char *tmpaddr; 3248360efbdSAlfred Perlstein 3258360efbdSAlfred Perlstein /* VARIABLES PROTECTED BY rpcbaddr_cache_lock: ad_cache */ 3268360efbdSAlfred Perlstein 3278360efbdSAlfred Perlstein /* Get the address of the rpcbind. Check cache first */ 32852353da8SIan Dowse client = NULL; 3298360efbdSAlfred Perlstein addr_to_delete.len = 0; 3308360efbdSAlfred Perlstein rwlock_rdlock(&rpcbaddr_cache_lock); 331e4db1131SAlfred Perlstein ad_cache = NULL; 332e4db1131SAlfred Perlstein if (host != NULL) 3338360efbdSAlfred Perlstein ad_cache = check_cache(host, nconf->nc_netid); 3348360efbdSAlfred Perlstein if (ad_cache != NULL) { 3358360efbdSAlfred Perlstein addr = ad_cache->ac_taddr; 3368360efbdSAlfred Perlstein client = clnt_tli_create(RPC_ANYFD, nconf, addr, 3378360efbdSAlfred Perlstein (rpcprog_t)RPCBPROG, (rpcvers_t)RPCBVERS4, 0, 0); 3388360efbdSAlfred Perlstein if (client != NULL) { 3398360efbdSAlfred Perlstein if (targaddr) 340e73bb7f1SIan Dowse *targaddr = strdup(ad_cache->ac_uaddr); 3418360efbdSAlfred Perlstein rwlock_unlock(&rpcbaddr_cache_lock); 3428360efbdSAlfred Perlstein return (client); 3438360efbdSAlfred Perlstein } 3448360efbdSAlfred Perlstein addr_to_delete.len = addr->len; 3458360efbdSAlfred Perlstein addr_to_delete.buf = (char *)malloc(addr->len); 3468360efbdSAlfred Perlstein if (addr_to_delete.buf == NULL) { 3478360efbdSAlfred Perlstein addr_to_delete.len = 0; 3488360efbdSAlfred Perlstein } else { 3498360efbdSAlfred Perlstein memcpy(addr_to_delete.buf, addr->buf, addr->len); 3508360efbdSAlfred Perlstein } 3518360efbdSAlfred Perlstein } 3528360efbdSAlfred Perlstein rwlock_unlock(&rpcbaddr_cache_lock); 3538360efbdSAlfred Perlstein if (addr_to_delete.len != 0) { 3548360efbdSAlfred Perlstein /* 3558360efbdSAlfred Perlstein * Assume this may be due to cache data being 3568360efbdSAlfred Perlstein * outdated 3578360efbdSAlfred Perlstein */ 3588360efbdSAlfred Perlstein rwlock_wrlock(&rpcbaddr_cache_lock); 3598360efbdSAlfred Perlstein delete_cache(&addr_to_delete); 3608360efbdSAlfred Perlstein rwlock_unlock(&rpcbaddr_cache_lock); 3618360efbdSAlfred Perlstein free(addr_to_delete.buf); 3628360efbdSAlfred Perlstein } 3638360efbdSAlfred Perlstein if (!__rpc_nconf2sockinfo(nconf, &si)) { 3648360efbdSAlfred Perlstein rpc_createerr.cf_stat = RPC_UNKNOWNPROTO; 3658360efbdSAlfred Perlstein return NULL; 3668360efbdSAlfred Perlstein } 3678360efbdSAlfred Perlstein 3688360efbdSAlfred Perlstein memset(&hints, 0, sizeof hints); 3698360efbdSAlfred Perlstein hints.ai_family = si.si_af; 3708360efbdSAlfred Perlstein hints.ai_socktype = si.si_socktype; 3718360efbdSAlfred Perlstein hints.ai_protocol = si.si_proto; 3728360efbdSAlfred Perlstein 3738360efbdSAlfred Perlstein #ifdef CLNT_DEBUG 3748360efbdSAlfred Perlstein printf("trying netid %s family %d proto %d socktype %d\n", 3758360efbdSAlfred Perlstein nconf->nc_netid, si.si_af, si.si_proto, si.si_socktype); 3768360efbdSAlfred Perlstein #endif 3778360efbdSAlfred Perlstein 378e4db1131SAlfred Perlstein if (nconf->nc_protofmly != NULL && strcmp(nconf->nc_protofmly, NC_LOOPBACK) == 0) { 379e4db1131SAlfred Perlstein client = local_rpcb(); 380e4db1131SAlfred Perlstein if (! client) { 381e4db1131SAlfred Perlstein #ifdef ND_DEBUG 382e4db1131SAlfred Perlstein clnt_pcreateerror("rpcbind clnt interface"); 383e4db1131SAlfred Perlstein #endif 384e4db1131SAlfred Perlstein return (NULL); 385e4db1131SAlfred Perlstein } else { 386e4db1131SAlfred Perlstein struct sockaddr_un sun; 387330e445cSMatteo Riondato if (targaddr) { 388e4db1131SAlfred Perlstein *targaddr = malloc(sizeof(sun.sun_path)); 389330e445cSMatteo Riondato if (*targaddr == NULL) { 390330e445cSMatteo Riondato CLNT_DESTROY(client); 391330e445cSMatteo Riondato return (NULL); 392330e445cSMatteo Riondato } 393e4db1131SAlfred Perlstein strncpy(*targaddr, _PATH_RPCBINDSOCK, 394e4db1131SAlfred Perlstein sizeof(sun.sun_path)); 395330e445cSMatteo Riondato } 396e4db1131SAlfred Perlstein return (client); 397e4db1131SAlfred Perlstein } 398e4db1131SAlfred Perlstein } else { 3998360efbdSAlfred Perlstein if (getaddrinfo(host, "sunrpc", &hints, &res) != 0) { 4008360efbdSAlfred Perlstein rpc_createerr.cf_stat = RPC_UNKNOWNHOST; 4018360efbdSAlfred Perlstein return NULL; 4028360efbdSAlfred Perlstein } 403e4db1131SAlfred Perlstein } 4048360efbdSAlfred Perlstein 4058360efbdSAlfred Perlstein for (tres = res; tres != NULL; tres = tres->ai_next) { 4068360efbdSAlfred Perlstein taddr.buf = tres->ai_addr; 4078360efbdSAlfred Perlstein taddr.len = taddr.maxlen = tres->ai_addrlen; 4088360efbdSAlfred Perlstein 4098360efbdSAlfred Perlstein #ifdef ND_DEBUG 4108360efbdSAlfred Perlstein { 4118360efbdSAlfred Perlstein char *ua; 4128360efbdSAlfred Perlstein 4138360efbdSAlfred Perlstein ua = taddr2uaddr(nconf, &taddr); 4148360efbdSAlfred Perlstein fprintf(stderr, "Got it [%s]\n", ua); 4158360efbdSAlfred Perlstein free(ua); 4168360efbdSAlfred Perlstein } 4178360efbdSAlfred Perlstein #endif 4188360efbdSAlfred Perlstein 4198360efbdSAlfred Perlstein #ifdef ND_DEBUG 4208360efbdSAlfred Perlstein { 4218360efbdSAlfred Perlstein int i; 4228360efbdSAlfred Perlstein 4238360efbdSAlfred Perlstein fprintf(stderr, "\tnetbuf len = %d, maxlen = %d\n", 4248360efbdSAlfred Perlstein taddr.len, taddr.maxlen); 4258360efbdSAlfred Perlstein fprintf(stderr, "\tAddress is "); 4268360efbdSAlfred Perlstein for (i = 0; i < taddr.len; i++) 4278360efbdSAlfred Perlstein fprintf(stderr, "%u.", ((char *)(taddr.buf))[i]); 4288360efbdSAlfred Perlstein fprintf(stderr, "\n"); 4298360efbdSAlfred Perlstein } 4308360efbdSAlfred Perlstein #endif 4318360efbdSAlfred Perlstein client = clnt_tli_create(RPC_ANYFD, nconf, &taddr, 4328360efbdSAlfred Perlstein (rpcprog_t)RPCBPROG, (rpcvers_t)RPCBVERS4, 0, 0); 4338360efbdSAlfred Perlstein #ifdef ND_DEBUG 4348360efbdSAlfred Perlstein if (! client) { 4358360efbdSAlfred Perlstein clnt_pcreateerror("rpcbind clnt interface"); 4368360efbdSAlfred Perlstein } 4378360efbdSAlfred Perlstein #endif 4388360efbdSAlfred Perlstein 4398360efbdSAlfred Perlstein if (client) { 4408360efbdSAlfred Perlstein tmpaddr = targaddr ? taddr2uaddr(nconf, &taddr) : NULL; 4418360efbdSAlfred Perlstein add_cache(host, nconf->nc_netid, &taddr, tmpaddr); 4428360efbdSAlfred Perlstein if (targaddr) 4438360efbdSAlfred Perlstein *targaddr = tmpaddr; 4448360efbdSAlfred Perlstein break; 4458360efbdSAlfred Perlstein } 4468360efbdSAlfred Perlstein } 447e4db1131SAlfred Perlstein if (res) 4488360efbdSAlfred Perlstein freeaddrinfo(res); 4498360efbdSAlfred Perlstein return (client); 4508360efbdSAlfred Perlstein } 4518360efbdSAlfred Perlstein 4528360efbdSAlfred Perlstein /* XXX */ 4538360efbdSAlfred Perlstein #define IN4_LOCALHOST_STRING "127.0.0.1" 4548360efbdSAlfred Perlstein #define IN6_LOCALHOST_STRING "::1" 4558360efbdSAlfred Perlstein 4568360efbdSAlfred Perlstein /* 4578360efbdSAlfred Perlstein * This routine will return a client handle that is connected to the local 4588360efbdSAlfred Perlstein * rpcbind. Returns NULL on error and free's everything. 4598360efbdSAlfred Perlstein */ 4608360efbdSAlfred Perlstein static CLIENT * 4618360efbdSAlfred Perlstein local_rpcb() 4628360efbdSAlfred Perlstein { 4638360efbdSAlfred Perlstein CLIENT *client; 4648360efbdSAlfred Perlstein static struct netconfig *loopnconf; 4658360efbdSAlfred Perlstein static char *hostname; 4668360efbdSAlfred Perlstein int sock; 4678360efbdSAlfred Perlstein size_t tsize; 4688360efbdSAlfred Perlstein struct netbuf nbuf; 4698360efbdSAlfred Perlstein struct sockaddr_un sun; 4708360efbdSAlfred Perlstein 4718360efbdSAlfred Perlstein /* 4728360efbdSAlfred Perlstein * Try connecting to the local rpcbind through a local socket 4738360efbdSAlfred Perlstein * first. If this doesn't work, try all transports defined in 4748360efbdSAlfred Perlstein * the netconfig file. 4758360efbdSAlfred Perlstein */ 4768360efbdSAlfred Perlstein memset(&sun, 0, sizeof sun); 4778360efbdSAlfred Perlstein sock = _socket(AF_LOCAL, SOCK_STREAM, 0); 4788360efbdSAlfred Perlstein if (sock < 0) 4798360efbdSAlfred Perlstein goto try_nconf; 4808360efbdSAlfred Perlstein sun.sun_family = AF_LOCAL; 4818360efbdSAlfred Perlstein strcpy(sun.sun_path, _PATH_RPCBINDSOCK); 4828360efbdSAlfred Perlstein nbuf.len = sun.sun_len = SUN_LEN(&sun); 4838360efbdSAlfred Perlstein nbuf.maxlen = sizeof (struct sockaddr_un); 4848360efbdSAlfred Perlstein nbuf.buf = &sun; 4858360efbdSAlfred Perlstein 4868360efbdSAlfred Perlstein tsize = __rpc_get_t_size(AF_LOCAL, 0, 0); 4878360efbdSAlfred Perlstein client = clnt_vc_create(sock, &nbuf, (rpcprog_t)RPCBPROG, 4888360efbdSAlfred Perlstein (rpcvers_t)RPCBVERS, tsize, tsize); 4898360efbdSAlfred Perlstein 4906112fceeSIan Dowse if (client != NULL) { 4916112fceeSIan Dowse /* Mark the socket to be closed in destructor */ 4926112fceeSIan Dowse (void) CLNT_CONTROL(client, CLSET_FD_CLOSE, NULL); 4938360efbdSAlfred Perlstein return client; 4946112fceeSIan Dowse } 4956112fceeSIan Dowse 4966112fceeSIan Dowse /* Nobody needs this socket anymore; free the descriptor. */ 4976112fceeSIan Dowse _close(sock); 4988360efbdSAlfred Perlstein 4998360efbdSAlfred Perlstein try_nconf: 5008360efbdSAlfred Perlstein 5018360efbdSAlfred Perlstein /* VARIABLES PROTECTED BY loopnconf_lock: loopnconf */ 5028360efbdSAlfred Perlstein mutex_lock(&loopnconf_lock); 5038360efbdSAlfred Perlstein if (loopnconf == NULL) { 5048360efbdSAlfred Perlstein struct netconfig *nconf, *tmpnconf = NULL; 5058360efbdSAlfred Perlstein void *nc_handle; 5068360efbdSAlfred Perlstein int fd; 5078360efbdSAlfred Perlstein 5088360efbdSAlfred Perlstein nc_handle = setnetconfig(); 5098360efbdSAlfred Perlstein if (nc_handle == NULL) { 5108360efbdSAlfred Perlstein /* fails to open netconfig file */ 5118360efbdSAlfred Perlstein syslog (LOG_ERR, "rpc: failed to open " NETCONFIG); 5128360efbdSAlfred Perlstein rpc_createerr.cf_stat = RPC_UNKNOWNPROTO; 5138360efbdSAlfred Perlstein mutex_unlock(&loopnconf_lock); 5148360efbdSAlfred Perlstein return (NULL); 5158360efbdSAlfred Perlstein } 5168360efbdSAlfred Perlstein while ((nconf = getnetconfig(nc_handle)) != NULL) { 5178360efbdSAlfred Perlstein #ifdef INET6 5188360efbdSAlfred Perlstein if ((strcmp(nconf->nc_protofmly, NC_INET6) == 0 || 5198360efbdSAlfred Perlstein #else 5208360efbdSAlfred Perlstein if (( 5218360efbdSAlfred Perlstein #endif 5228360efbdSAlfred Perlstein strcmp(nconf->nc_protofmly, NC_INET) == 0) && 5238360efbdSAlfred Perlstein (nconf->nc_semantics == NC_TPI_COTS || 5248360efbdSAlfred Perlstein nconf->nc_semantics == NC_TPI_COTS_ORD)) { 5258360efbdSAlfred Perlstein fd = __rpc_nconf2fd(nconf); 5268360efbdSAlfred Perlstein /* 5278360efbdSAlfred Perlstein * Can't create a socket, assume that 5288360efbdSAlfred Perlstein * this family isn't configured in the kernel. 5298360efbdSAlfred Perlstein */ 5308360efbdSAlfred Perlstein if (fd < 0) 5318360efbdSAlfred Perlstein continue; 5328360efbdSAlfred Perlstein _close(fd); 5338360efbdSAlfred Perlstein tmpnconf = nconf; 5348360efbdSAlfred Perlstein if (!strcmp(nconf->nc_protofmly, NC_INET)) 5358360efbdSAlfred Perlstein hostname = IN4_LOCALHOST_STRING; 5368360efbdSAlfred Perlstein else 5378360efbdSAlfred Perlstein hostname = IN6_LOCALHOST_STRING; 5388360efbdSAlfred Perlstein } 5398360efbdSAlfred Perlstein } 5408360efbdSAlfred Perlstein if (tmpnconf == NULL) { 5418360efbdSAlfred Perlstein rpc_createerr.cf_stat = RPC_UNKNOWNPROTO; 5428360efbdSAlfred Perlstein mutex_unlock(&loopnconf_lock); 5438360efbdSAlfred Perlstein return (NULL); 5448360efbdSAlfred Perlstein } 5458360efbdSAlfred Perlstein loopnconf = getnetconfigent(tmpnconf->nc_netid); 5468360efbdSAlfred Perlstein /* loopnconf is never freed */ 5478360efbdSAlfred Perlstein endnetconfig(nc_handle); 5488360efbdSAlfred Perlstein } 5498360efbdSAlfred Perlstein mutex_unlock(&loopnconf_lock); 5508360efbdSAlfred Perlstein client = getclnthandle(hostname, loopnconf, NULL); 5518360efbdSAlfred Perlstein return (client); 5528360efbdSAlfred Perlstein } 5538360efbdSAlfred Perlstein 5548360efbdSAlfred Perlstein /* 5558360efbdSAlfred Perlstein * Set a mapping between program, version and address. 5568360efbdSAlfred Perlstein * Calls the rpcbind service to do the mapping. 5578360efbdSAlfred Perlstein */ 5588360efbdSAlfred Perlstein bool_t 5598360efbdSAlfred Perlstein rpcb_set(program, version, nconf, address) 5608360efbdSAlfred Perlstein rpcprog_t program; 5618360efbdSAlfred Perlstein rpcvers_t version; 5628360efbdSAlfred Perlstein const struct netconfig *nconf; /* Network structure of transport */ 5638360efbdSAlfred Perlstein const struct netbuf *address; /* Services netconfig address */ 5648360efbdSAlfred Perlstein { 5658360efbdSAlfred Perlstein CLIENT *client; 5668360efbdSAlfred Perlstein bool_t rslt = FALSE; 5678360efbdSAlfred Perlstein RPCB parms; 5688360efbdSAlfred Perlstein char uidbuf[32]; 5698360efbdSAlfred Perlstein 5708360efbdSAlfred Perlstein /* parameter checking */ 5718360efbdSAlfred Perlstein if (nconf == NULL) { 5728360efbdSAlfred Perlstein rpc_createerr.cf_stat = RPC_UNKNOWNPROTO; 5738360efbdSAlfred Perlstein return (FALSE); 5748360efbdSAlfred Perlstein } 5758360efbdSAlfred Perlstein if (address == NULL) { 5768360efbdSAlfred Perlstein rpc_createerr.cf_stat = RPC_UNKNOWNADDR; 5778360efbdSAlfred Perlstein return (FALSE); 5788360efbdSAlfred Perlstein } 5798360efbdSAlfred Perlstein client = local_rpcb(); 5808360efbdSAlfred Perlstein if (! client) { 5818360efbdSAlfred Perlstein return (FALSE); 5828360efbdSAlfred Perlstein } 5838360efbdSAlfred Perlstein 5848360efbdSAlfred Perlstein /* convert to universal */ 5858360efbdSAlfred Perlstein /*LINTED const castaway*/ 5868360efbdSAlfred Perlstein parms.r_addr = taddr2uaddr((struct netconfig *) nconf, 5878360efbdSAlfred Perlstein (struct netbuf *)address); 5888360efbdSAlfred Perlstein if (!parms.r_addr) { 5896112fceeSIan Dowse CLNT_DESTROY(client); 5908360efbdSAlfred Perlstein rpc_createerr.cf_stat = RPC_N2AXLATEFAILURE; 5918360efbdSAlfred Perlstein return (FALSE); /* no universal address */ 5928360efbdSAlfred Perlstein } 5938360efbdSAlfred Perlstein parms.r_prog = program; 5948360efbdSAlfred Perlstein parms.r_vers = version; 5958360efbdSAlfred Perlstein parms.r_netid = nconf->nc_netid; 5968360efbdSAlfred Perlstein /* 5978360efbdSAlfred Perlstein * Though uid is not being used directly, we still send it for 5988360efbdSAlfred Perlstein * completeness. For non-unix platforms, perhaps some other 5998360efbdSAlfred Perlstein * string or an empty string can be sent. 6008360efbdSAlfred Perlstein */ 6018360efbdSAlfred Perlstein (void) snprintf(uidbuf, sizeof uidbuf, "%d", geteuid()); 6028360efbdSAlfred Perlstein parms.r_owner = uidbuf; 6038360efbdSAlfred Perlstein 6048360efbdSAlfred Perlstein CLNT_CALL(client, (rpcproc_t)RPCBPROC_SET, (xdrproc_t) xdr_rpcb, 6058360efbdSAlfred Perlstein (char *)(void *)&parms, (xdrproc_t) xdr_bool, 6068360efbdSAlfred Perlstein (char *)(void *)&rslt, tottimeout); 6078360efbdSAlfred Perlstein 6088360efbdSAlfred Perlstein CLNT_DESTROY(client); 6098360efbdSAlfred Perlstein free(parms.r_addr); 6108360efbdSAlfred Perlstein return (rslt); 6118360efbdSAlfred Perlstein } 6128360efbdSAlfred Perlstein 6138360efbdSAlfred Perlstein /* 6148360efbdSAlfred Perlstein * Remove the mapping between program, version and netbuf address. 6158360efbdSAlfred Perlstein * Calls the rpcbind service to do the un-mapping. 6168360efbdSAlfred Perlstein * If netbuf is NULL, unset for all the transports, otherwise unset 6178360efbdSAlfred Perlstein * only for the given transport. 6188360efbdSAlfred Perlstein */ 6198360efbdSAlfred Perlstein bool_t 6208360efbdSAlfred Perlstein rpcb_unset(program, version, nconf) 6218360efbdSAlfred Perlstein rpcprog_t program; 6228360efbdSAlfred Perlstein rpcvers_t version; 6238360efbdSAlfred Perlstein const struct netconfig *nconf; 6248360efbdSAlfred Perlstein { 6258360efbdSAlfred Perlstein CLIENT *client; 6268360efbdSAlfred Perlstein bool_t rslt = FALSE; 6278360efbdSAlfred Perlstein RPCB parms; 6288360efbdSAlfred Perlstein char uidbuf[32]; 6298360efbdSAlfred Perlstein 6308360efbdSAlfred Perlstein client = local_rpcb(); 6318360efbdSAlfred Perlstein if (! client) { 6328360efbdSAlfred Perlstein return (FALSE); 6338360efbdSAlfred Perlstein } 6348360efbdSAlfred Perlstein 6358360efbdSAlfred Perlstein parms.r_prog = program; 6368360efbdSAlfred Perlstein parms.r_vers = version; 6378360efbdSAlfred Perlstein if (nconf) 6388360efbdSAlfred Perlstein parms.r_netid = nconf->nc_netid; 6398360efbdSAlfred Perlstein else { 6408360efbdSAlfred Perlstein /*LINTED const castaway*/ 6418360efbdSAlfred Perlstein parms.r_netid = (char *) &nullstring[0]; /* unsets all */ 6428360efbdSAlfred Perlstein } 6438360efbdSAlfred Perlstein /*LINTED const castaway*/ 6448360efbdSAlfred Perlstein parms.r_addr = (char *) &nullstring[0]; 6458360efbdSAlfred Perlstein (void) snprintf(uidbuf, sizeof uidbuf, "%d", geteuid()); 6468360efbdSAlfred Perlstein parms.r_owner = uidbuf; 6478360efbdSAlfred Perlstein 6488360efbdSAlfred Perlstein CLNT_CALL(client, (rpcproc_t)RPCBPROC_UNSET, (xdrproc_t) xdr_rpcb, 6498360efbdSAlfred Perlstein (char *)(void *)&parms, (xdrproc_t) xdr_bool, 6508360efbdSAlfred Perlstein (char *)(void *)&rslt, tottimeout); 6518360efbdSAlfred Perlstein 6528360efbdSAlfred Perlstein CLNT_DESTROY(client); 6538360efbdSAlfred Perlstein return (rslt); 6548360efbdSAlfred Perlstein } 6558360efbdSAlfred Perlstein 6568360efbdSAlfred Perlstein /* 6578360efbdSAlfred Perlstein * From the merged list, find the appropriate entry 6588360efbdSAlfred Perlstein */ 6598360efbdSAlfred Perlstein static struct netbuf * 6608360efbdSAlfred Perlstein got_entry(relp, nconf) 6618360efbdSAlfred Perlstein rpcb_entry_list_ptr relp; 6628360efbdSAlfred Perlstein const struct netconfig *nconf; 6638360efbdSAlfred Perlstein { 6648360efbdSAlfred Perlstein struct netbuf *na = NULL; 6658360efbdSAlfred Perlstein rpcb_entry_list_ptr sp; 6668360efbdSAlfred Perlstein rpcb_entry *rmap; 6678360efbdSAlfred Perlstein 6688360efbdSAlfred Perlstein for (sp = relp; sp != NULL; sp = sp->rpcb_entry_next) { 6698360efbdSAlfred Perlstein rmap = &sp->rpcb_entry_map; 6708360efbdSAlfred Perlstein if ((strcmp(nconf->nc_proto, rmap->r_nc_proto) == 0) && 6718360efbdSAlfred Perlstein (strcmp(nconf->nc_protofmly, rmap->r_nc_protofmly) == 0) && 6728360efbdSAlfred Perlstein (nconf->nc_semantics == rmap->r_nc_semantics) && 673b6c452a8SMartin Blapp (rmap->r_maddr != NULL) && (rmap->r_maddr[0] != 0)) { 6748360efbdSAlfred Perlstein na = uaddr2taddr(nconf, rmap->r_maddr); 6758360efbdSAlfred Perlstein #ifdef ND_DEBUG 6768360efbdSAlfred Perlstein fprintf(stderr, "\tRemote address is [%s].\n", 6778360efbdSAlfred Perlstein rmap->r_maddr); 6788360efbdSAlfred Perlstein if (!na) 6798360efbdSAlfred Perlstein fprintf(stderr, 6808360efbdSAlfred Perlstein "\tCouldn't resolve remote address!\n"); 6818360efbdSAlfred Perlstein #endif 6828360efbdSAlfred Perlstein break; 6838360efbdSAlfred Perlstein } 6848360efbdSAlfred Perlstein } 6858360efbdSAlfred Perlstein return (na); 6868360efbdSAlfred Perlstein } 6878360efbdSAlfred Perlstein 6888360efbdSAlfred Perlstein /* 6894e37855eSAlfred Perlstein * Quick check to see if rpcbind is up. Tries to connect over 6904e37855eSAlfred Perlstein * local transport. 6914e37855eSAlfred Perlstein */ 692235baf26SDaniel Eischen static bool_t 6934e37855eSAlfred Perlstein __rpcbind_is_up() 6944e37855eSAlfred Perlstein { 6954e37855eSAlfred Perlstein struct netconfig *nconf; 6964e37855eSAlfred Perlstein struct sockaddr_un sun; 6974e37855eSAlfred Perlstein void *localhandle; 6984e37855eSAlfred Perlstein int sock; 6994e37855eSAlfred Perlstein 7004e37855eSAlfred Perlstein nconf = NULL; 7014e37855eSAlfred Perlstein localhandle = setnetconfig(); 702bb1ca86fSIan Dowse while ((nconf = getnetconfig(localhandle)) != NULL) { 7034e37855eSAlfred Perlstein if (nconf->nc_protofmly != NULL && 7044e37855eSAlfred Perlstein strcmp(nconf->nc_protofmly, NC_LOOPBACK) == 0) 7054e37855eSAlfred Perlstein break; 7064e37855eSAlfred Perlstein } 7074e37855eSAlfred Perlstein if (nconf == NULL) 7084e37855eSAlfred Perlstein return (FALSE); 7094e37855eSAlfred Perlstein 7104e37855eSAlfred Perlstein endnetconfig(localhandle); 7114e37855eSAlfred Perlstein 7124e37855eSAlfred Perlstein memset(&sun, 0, sizeof sun); 7134e37855eSAlfred Perlstein sock = _socket(AF_LOCAL, SOCK_STREAM, 0); 7144e37855eSAlfred Perlstein if (sock < 0) 7154e37855eSAlfred Perlstein return (FALSE); 7164e37855eSAlfred Perlstein sun.sun_family = AF_LOCAL; 7174e37855eSAlfred Perlstein strncpy(sun.sun_path, _PATH_RPCBINDSOCK, sizeof(sun.sun_path)); 7184e37855eSAlfred Perlstein sun.sun_len = SUN_LEN(&sun); 7194e37855eSAlfred Perlstein 7204e37855eSAlfred Perlstein if (_connect(sock, (struct sockaddr *)&sun, sun.sun_len) < 0) { 7214e37855eSAlfred Perlstein _close(sock); 7224e37855eSAlfred Perlstein return (FALSE); 7234e37855eSAlfred Perlstein } 7244e37855eSAlfred Perlstein 7254e37855eSAlfred Perlstein _close(sock); 7264e37855eSAlfred Perlstein return (TRUE); 7274e37855eSAlfred Perlstein } 7284e37855eSAlfred Perlstein 7294e37855eSAlfred Perlstein /* 7308360efbdSAlfred Perlstein * An internal function which optimizes rpcb_getaddr function. It also 7318360efbdSAlfred Perlstein * returns the client handle that it uses to contact the remote rpcbind. 7328360efbdSAlfred Perlstein * 7338360efbdSAlfred Perlstein * The algorithm used: If the transports is TCP or UDP, it first tries 7348360efbdSAlfred Perlstein * version 2 (portmap), 4 and then 3 (svr4). This order should be 7358360efbdSAlfred Perlstein * changed in the next OS release to 4, 2 and 3. We are assuming that by 7368360efbdSAlfred Perlstein * that time, version 4 would be available on many machines on the network. 7378360efbdSAlfred Perlstein * With this algorithm, we get performance as well as a plan for 7388360efbdSAlfred Perlstein * obsoleting version 2. 7398360efbdSAlfred Perlstein * 7408360efbdSAlfred Perlstein * For all other transports, the algorithm remains as 4 and then 3. 7418360efbdSAlfred Perlstein * 7428360efbdSAlfred Perlstein * XXX: Due to some problems with t_connect(), we do not reuse the same client 7438360efbdSAlfred Perlstein * handle for COTS cases and hence in these cases we do not return the 7448360efbdSAlfred Perlstein * client handle. This code will change if t_connect() ever 7458360efbdSAlfred Perlstein * starts working properly. Also look under clnt_vc.c. 7468360efbdSAlfred Perlstein */ 7478360efbdSAlfred Perlstein struct netbuf * 7484e37855eSAlfred Perlstein __rpcb_findaddr_timed(program, version, nconf, host, clpp, tp) 7498360efbdSAlfred Perlstein rpcprog_t program; 7508360efbdSAlfred Perlstein rpcvers_t version; 7518360efbdSAlfred Perlstein const struct netconfig *nconf; 7528360efbdSAlfred Perlstein const char *host; 7538360efbdSAlfred Perlstein CLIENT **clpp; 7544e37855eSAlfred Perlstein struct timeval *tp; 7558360efbdSAlfred Perlstein { 7564e37855eSAlfred Perlstein static bool_t check_rpcbind = TRUE; 7578360efbdSAlfred Perlstein CLIENT *client = NULL; 7588360efbdSAlfred Perlstein RPCB parms; 7598360efbdSAlfred Perlstein enum clnt_stat clnt_st; 7608360efbdSAlfred Perlstein char *ua = NULL; 7618360efbdSAlfred Perlstein rpcvers_t vers; 7628360efbdSAlfred Perlstein struct netbuf *address = NULL; 7638360efbdSAlfred Perlstein rpcvers_t start_vers = RPCBVERS4; 7648360efbdSAlfred Perlstein struct netbuf servaddr; 7658360efbdSAlfred Perlstein 7668360efbdSAlfred Perlstein /* parameter checking */ 7678360efbdSAlfred Perlstein if (nconf == NULL) { 7688360efbdSAlfred Perlstein rpc_createerr.cf_stat = RPC_UNKNOWNPROTO; 7698360efbdSAlfred Perlstein return (NULL); 7708360efbdSAlfred Perlstein } 7718360efbdSAlfred Perlstein 7728360efbdSAlfred Perlstein parms.r_addr = NULL; 7738360efbdSAlfred Perlstein 7744e37855eSAlfred Perlstein /* 7754e37855eSAlfred Perlstein * Use default total timeout if no timeout is specified. 7764e37855eSAlfred Perlstein */ 7774e37855eSAlfred Perlstein if (tp == NULL) 7784e37855eSAlfred Perlstein tp = &tottimeout; 7794e37855eSAlfred Perlstein 7808360efbdSAlfred Perlstein #ifdef PORTMAP 7818360efbdSAlfred Perlstein /* Try version 2 for TCP or UDP */ 7828360efbdSAlfred Perlstein if (strcmp(nconf->nc_protofmly, NC_INET) == 0) { 7838360efbdSAlfred Perlstein u_short port = 0; 7848360efbdSAlfred Perlstein struct netbuf remote; 7858360efbdSAlfred Perlstein rpcvers_t pmapvers = 2; 7868360efbdSAlfred Perlstein struct pmap pmapparms; 7878360efbdSAlfred Perlstein 7888360efbdSAlfred Perlstein /* 7898360efbdSAlfred Perlstein * Try UDP only - there are some portmappers out 7908360efbdSAlfred Perlstein * there that use UDP only. 7918360efbdSAlfred Perlstein */ 7928360efbdSAlfred Perlstein if (strcmp(nconf->nc_proto, NC_TCP) == 0) { 7938360efbdSAlfred Perlstein struct netconfig *newnconf; 7948360efbdSAlfred Perlstein 795bb1ca86fSIan Dowse if ((newnconf = getnetconfigent("udp")) == NULL) { 7968360efbdSAlfred Perlstein rpc_createerr.cf_stat = RPC_UNKNOWNPROTO; 7978360efbdSAlfred Perlstein return (NULL); 7988360efbdSAlfred Perlstein } 7998360efbdSAlfred Perlstein client = getclnthandle(host, newnconf, &parms.r_addr); 800bb1ca86fSIan Dowse freenetconfigent(newnconf); 8018360efbdSAlfred Perlstein } else { 8028360efbdSAlfred Perlstein client = getclnthandle(host, nconf, &parms.r_addr); 8038360efbdSAlfred Perlstein } 8044e37855eSAlfred Perlstein if (client == NULL) 8058360efbdSAlfred Perlstein return (NULL); 8068360efbdSAlfred Perlstein 8074e37855eSAlfred Perlstein /* 8084e37855eSAlfred Perlstein * Set version and retry timeout. 8094e37855eSAlfred Perlstein */ 8104e37855eSAlfred Perlstein CLNT_CONTROL(client, CLSET_RETRY_TIMEOUT, (char *)&rpcbrmttime); 8114e37855eSAlfred Perlstein CLNT_CONTROL(client, CLSET_VERS, (char *)&pmapvers); 8124e37855eSAlfred Perlstein 8138360efbdSAlfred Perlstein pmapparms.pm_prog = program; 8148360efbdSAlfred Perlstein pmapparms.pm_vers = version; 8158360efbdSAlfred Perlstein pmapparms.pm_prot = strcmp(nconf->nc_proto, NC_TCP) ? 8168360efbdSAlfred Perlstein IPPROTO_UDP : IPPROTO_TCP; 8178360efbdSAlfred Perlstein pmapparms.pm_port = 0; /* not needed */ 8188360efbdSAlfred Perlstein clnt_st = CLNT_CALL(client, (rpcproc_t)PMAPPROC_GETPORT, 8198360efbdSAlfred Perlstein (xdrproc_t) xdr_pmap, (caddr_t)(void *)&pmapparms, 8208360efbdSAlfred Perlstein (xdrproc_t) xdr_u_short, (caddr_t)(void *)&port, 8214e37855eSAlfred Perlstein *tp); 8228360efbdSAlfred Perlstein if (clnt_st != RPC_SUCCESS) { 8238360efbdSAlfred Perlstein if ((clnt_st == RPC_PROGVERSMISMATCH) || 8248360efbdSAlfred Perlstein (clnt_st == RPC_PROGUNAVAIL)) 8258360efbdSAlfred Perlstein goto try_rpcbind; /* Try different versions */ 8268360efbdSAlfred Perlstein rpc_createerr.cf_stat = RPC_PMAPFAILURE; 8278360efbdSAlfred Perlstein clnt_geterr(client, &rpc_createerr.cf_error); 8288360efbdSAlfred Perlstein goto error; 8298360efbdSAlfred Perlstein } else if (port == 0) { 8308360efbdSAlfred Perlstein address = NULL; 8318360efbdSAlfred Perlstein rpc_createerr.cf_stat = RPC_PROGNOTREGISTERED; 8328360efbdSAlfred Perlstein goto error; 8338360efbdSAlfred Perlstein } 8348360efbdSAlfred Perlstein port = htons(port); 8354e37855eSAlfred Perlstein CLNT_CONTROL(client, CLGET_SVC_ADDR, (char *)&remote); 8368360efbdSAlfred Perlstein if (((address = (struct netbuf *) 8378360efbdSAlfred Perlstein malloc(sizeof (struct netbuf))) == NULL) || 8388360efbdSAlfred Perlstein ((address->buf = (char *) 8398360efbdSAlfred Perlstein malloc(remote.len)) == NULL)) { 8408360efbdSAlfred Perlstein rpc_createerr.cf_stat = RPC_SYSTEMERROR; 8418360efbdSAlfred Perlstein clnt_geterr(client, &rpc_createerr.cf_error); 8428360efbdSAlfred Perlstein if (address) { 8438360efbdSAlfred Perlstein free(address); 8448360efbdSAlfred Perlstein address = NULL; 8458360efbdSAlfred Perlstein } 8468360efbdSAlfred Perlstein goto error; 8478360efbdSAlfred Perlstein } 8488360efbdSAlfred Perlstein memcpy(address->buf, remote.buf, remote.len); 8498360efbdSAlfred Perlstein memcpy(&((char *)address->buf)[sizeof (short)], 8508360efbdSAlfred Perlstein (char *)(void *)&port, sizeof (short)); 8518360efbdSAlfred Perlstein address->len = address->maxlen = remote.len; 8528360efbdSAlfred Perlstein goto done; 8538360efbdSAlfred Perlstein } 8548360efbdSAlfred Perlstein #endif /* PORTMAP */ 8558360efbdSAlfred Perlstein 8568360efbdSAlfred Perlstein try_rpcbind: 8578360efbdSAlfred Perlstein /* 8584e37855eSAlfred Perlstein * Check if rpcbind is up. This prevents needless delays when 8594e37855eSAlfred Perlstein * accessing applications such as the keyserver while booting 8604e37855eSAlfred Perlstein * disklessly. 8614e37855eSAlfred Perlstein */ 8624e37855eSAlfred Perlstein if (check_rpcbind && strcmp(nconf->nc_protofmly, NC_LOOPBACK) == 0) { 8634e37855eSAlfred Perlstein if (!__rpcbind_is_up()) { 8644e37855eSAlfred Perlstein rpc_createerr.cf_stat = RPC_PMAPFAILURE; 8654e37855eSAlfred Perlstein rpc_createerr.cf_error.re_errno = 0; 8664e37855eSAlfred Perlstein goto error; 8674e37855eSAlfred Perlstein } 8684e37855eSAlfred Perlstein check_rpcbind = FALSE; 8694e37855eSAlfred Perlstein } 8704e37855eSAlfred Perlstein 8714e37855eSAlfred Perlstein /* 8728360efbdSAlfred Perlstein * Now we try version 4 and then 3. 8738360efbdSAlfred Perlstein * We also send the remote system the address we used to 8748360efbdSAlfred Perlstein * contact it in case it can help to connect back with us 8758360efbdSAlfred Perlstein */ 8768360efbdSAlfred Perlstein parms.r_prog = program; 8778360efbdSAlfred Perlstein parms.r_vers = version; 8788360efbdSAlfred Perlstein /*LINTED const castaway*/ 8798360efbdSAlfred Perlstein parms.r_owner = (char *) &nullstring[0]; /* not needed; */ 8808360efbdSAlfred Perlstein /* just for xdring */ 8818360efbdSAlfred Perlstein parms.r_netid = nconf->nc_netid; /* not really needed */ 8828360efbdSAlfred Perlstein 8838360efbdSAlfred Perlstein /* 8848360efbdSAlfred Perlstein * If a COTS transport is being used, try getting address via CLTS 8858360efbdSAlfred Perlstein * transport. This works only with version 4. 8868360efbdSAlfred Perlstein */ 8874e37855eSAlfred Perlstein if (nconf->nc_semantics == NC_TPI_COTS_ORD || 8884e37855eSAlfred Perlstein nconf->nc_semantics == NC_TPI_COTS) { 8894e37855eSAlfred Perlstein 8908360efbdSAlfred Perlstein void *handle; 8918360efbdSAlfred Perlstein struct netconfig *nconf_clts; 8928360efbdSAlfred Perlstein rpcb_entry_list_ptr relp = NULL; 8938360efbdSAlfred Perlstein 8948360efbdSAlfred Perlstein if (client == NULL) { 8958360efbdSAlfred Perlstein /* This did not go through the above PORTMAP/TCP code */ 8968360efbdSAlfred Perlstein if ((handle = __rpc_setconf("datagram_v")) != NULL) { 8978360efbdSAlfred Perlstein while ((nconf_clts = __rpc_getconf(handle)) 8988360efbdSAlfred Perlstein != NULL) { 8998360efbdSAlfred Perlstein if (strcmp(nconf_clts->nc_protofmly, 9008360efbdSAlfred Perlstein nconf->nc_protofmly) != 0) { 9018360efbdSAlfred Perlstein continue; 9028360efbdSAlfred Perlstein } 9038360efbdSAlfred Perlstein client = getclnthandle(host, nconf_clts, 9048360efbdSAlfred Perlstein &parms.r_addr); 9058360efbdSAlfred Perlstein break; 9068360efbdSAlfred Perlstein } 9078360efbdSAlfred Perlstein __rpc_endconf(handle); 9088360efbdSAlfred Perlstein } 9098360efbdSAlfred Perlstein if (client == NULL) 9108360efbdSAlfred Perlstein goto regular_rpcbind; /* Go the regular way */ 9118360efbdSAlfred Perlstein } else { 9128360efbdSAlfred Perlstein /* This is a UDP PORTMAP handle. Change to version 4 */ 9138360efbdSAlfred Perlstein vers = RPCBVERS4; 9148360efbdSAlfred Perlstein CLNT_CONTROL(client, CLSET_VERS, (char *)(void *)&vers); 9158360efbdSAlfred Perlstein } 9168360efbdSAlfred Perlstein /* 9178360efbdSAlfred Perlstein * We also send the remote system the address we used to 9188360efbdSAlfred Perlstein * contact it in case it can help it connect back with us 9198360efbdSAlfred Perlstein */ 9208360efbdSAlfred Perlstein if (parms.r_addr == NULL) { 9218360efbdSAlfred Perlstein /*LINTED const castaway*/ 9228360efbdSAlfred Perlstein parms.r_addr = (char *) &nullstring[0]; /* for XDRing */ 9238360efbdSAlfred Perlstein } 9244e37855eSAlfred Perlstein 9254e37855eSAlfred Perlstein CLNT_CONTROL(client, CLSET_RETRY_TIMEOUT, (char *)&rpcbrmttime); 9264e37855eSAlfred Perlstein 9278360efbdSAlfred Perlstein clnt_st = CLNT_CALL(client, (rpcproc_t)RPCBPROC_GETADDRLIST, 9288360efbdSAlfred Perlstein (xdrproc_t) xdr_rpcb, (char *)(void *)&parms, 9298360efbdSAlfred Perlstein (xdrproc_t) xdr_rpcb_entry_list_ptr, 9304e37855eSAlfred Perlstein (char *)(void *)&relp, *tp); 9318360efbdSAlfred Perlstein if (clnt_st == RPC_SUCCESS) { 9328360efbdSAlfred Perlstein if ((address = got_entry(relp, nconf)) != NULL) { 9338360efbdSAlfred Perlstein xdr_free((xdrproc_t) xdr_rpcb_entry_list_ptr, 9348360efbdSAlfred Perlstein (char *)(void *)&relp); 93577335102SMartin Blapp CLNT_CONTROL(client, CLGET_SVC_ADDR, 93677335102SMartin Blapp (char *)(void *)&servaddr); 93777335102SMartin Blapp __rpc_fixup_addr(address, &servaddr); 9388360efbdSAlfred Perlstein goto done; 9398360efbdSAlfred Perlstein } 9408360efbdSAlfred Perlstein /* Entry not found for this transport */ 9418360efbdSAlfred Perlstein xdr_free((xdrproc_t) xdr_rpcb_entry_list_ptr, 9428360efbdSAlfred Perlstein (char *)(void *)&relp); 9438360efbdSAlfred Perlstein /* 9448360efbdSAlfred Perlstein * XXX: should have perhaps returned with error but 9458360efbdSAlfred Perlstein * since the remote machine might not always be able 9468360efbdSAlfred Perlstein * to send the address on all transports, we try the 9478360efbdSAlfred Perlstein * regular way with regular_rpcbind 9488360efbdSAlfred Perlstein */ 9498360efbdSAlfred Perlstein goto regular_rpcbind; 9508360efbdSAlfred Perlstein } else if ((clnt_st == RPC_PROGVERSMISMATCH) || 9518360efbdSAlfred Perlstein (clnt_st == RPC_PROGUNAVAIL)) { 9528360efbdSAlfred Perlstein start_vers = RPCBVERS; /* Try version 3 now */ 9538360efbdSAlfred Perlstein goto regular_rpcbind; /* Try different versions */ 9548360efbdSAlfred Perlstein } else { 9558360efbdSAlfred Perlstein rpc_createerr.cf_stat = RPC_PMAPFAILURE; 9568360efbdSAlfred Perlstein clnt_geterr(client, &rpc_createerr.cf_error); 9578360efbdSAlfred Perlstein goto error; 9588360efbdSAlfred Perlstein } 9598360efbdSAlfred Perlstein } 9608360efbdSAlfred Perlstein 9618360efbdSAlfred Perlstein regular_rpcbind: 9628360efbdSAlfred Perlstein 9638360efbdSAlfred Perlstein /* Now the same transport is to be used to get the address */ 9648360efbdSAlfred Perlstein if (client && ((nconf->nc_semantics == NC_TPI_COTS_ORD) || 9658360efbdSAlfred Perlstein (nconf->nc_semantics == NC_TPI_COTS))) { 9668360efbdSAlfred Perlstein /* A CLTS type of client - destroy it */ 9678360efbdSAlfred Perlstein CLNT_DESTROY(client); 9688360efbdSAlfred Perlstein client = NULL; 9698360efbdSAlfred Perlstein } 9708360efbdSAlfred Perlstein 9718360efbdSAlfred Perlstein if (client == NULL) { 9728360efbdSAlfred Perlstein client = getclnthandle(host, nconf, &parms.r_addr); 9738360efbdSAlfred Perlstein if (client == NULL) { 9748360efbdSAlfred Perlstein goto error; 9758360efbdSAlfred Perlstein } 9768360efbdSAlfred Perlstein } 9778360efbdSAlfred Perlstein if (parms.r_addr == NULL) { 9788360efbdSAlfred Perlstein /*LINTED const castaway*/ 9798360efbdSAlfred Perlstein parms.r_addr = (char *) &nullstring[0]; 9808360efbdSAlfred Perlstein } 9818360efbdSAlfred Perlstein 9828360efbdSAlfred Perlstein /* First try from start_vers and then version 3 (RPCBVERS) */ 9834e37855eSAlfred Perlstein 9844e37855eSAlfred Perlstein CLNT_CONTROL(client, CLSET_RETRY_TIMEOUT, (char *) &rpcbrmttime); 9858360efbdSAlfred Perlstein for (vers = start_vers; vers >= RPCBVERS; vers--) { 9868360efbdSAlfred Perlstein /* Set the version */ 9878360efbdSAlfred Perlstein CLNT_CONTROL(client, CLSET_VERS, (char *)(void *)&vers); 9888360efbdSAlfred Perlstein clnt_st = CLNT_CALL(client, (rpcproc_t)RPCBPROC_GETADDR, 9898360efbdSAlfred Perlstein (xdrproc_t) xdr_rpcb, (char *)(void *)&parms, 9904e37855eSAlfred Perlstein (xdrproc_t) xdr_wrapstring, (char *)(void *) &ua, *tp); 9918360efbdSAlfred Perlstein if (clnt_st == RPC_SUCCESS) { 992b6c452a8SMartin Blapp if ((ua == NULL) || (ua[0] == 0)) { 9938360efbdSAlfred Perlstein /* address unknown */ 9948360efbdSAlfred Perlstein rpc_createerr.cf_stat = RPC_PROGNOTREGISTERED; 9958360efbdSAlfred Perlstein goto error; 9968360efbdSAlfred Perlstein } 9978360efbdSAlfred Perlstein address = uaddr2taddr(nconf, ua); 9988360efbdSAlfred Perlstein #ifdef ND_DEBUG 9998360efbdSAlfred Perlstein fprintf(stderr, "\tRemote address is [%s]\n", ua); 10008360efbdSAlfred Perlstein if (!address) 10018360efbdSAlfred Perlstein fprintf(stderr, 10028360efbdSAlfred Perlstein "\tCouldn't resolve remote address!\n"); 10038360efbdSAlfred Perlstein #endif 10048360efbdSAlfred Perlstein xdr_free((xdrproc_t)xdr_wrapstring, 10058360efbdSAlfred Perlstein (char *)(void *)&ua); 10068360efbdSAlfred Perlstein 10078360efbdSAlfred Perlstein if (! address) { 10088360efbdSAlfred Perlstein /* We don't know about your universal address */ 10098360efbdSAlfred Perlstein rpc_createerr.cf_stat = RPC_N2AXLATEFAILURE; 10108360efbdSAlfred Perlstein goto error; 10118360efbdSAlfred Perlstein } 10128360efbdSAlfred Perlstein CLNT_CONTROL(client, CLGET_SVC_ADDR, 10138360efbdSAlfred Perlstein (char *)(void *)&servaddr); 10148360efbdSAlfred Perlstein __rpc_fixup_addr(address, &servaddr); 10158360efbdSAlfred Perlstein goto done; 10168360efbdSAlfred Perlstein } else if (clnt_st == RPC_PROGVERSMISMATCH) { 10178360efbdSAlfred Perlstein struct rpc_err rpcerr; 10188360efbdSAlfred Perlstein 10198360efbdSAlfred Perlstein clnt_geterr(client, &rpcerr); 10208360efbdSAlfred Perlstein if (rpcerr.re_vers.low > RPCBVERS4) 10218360efbdSAlfred Perlstein goto error; /* a new version, can't handle */ 10228360efbdSAlfred Perlstein } else if (clnt_st != RPC_PROGUNAVAIL) { 10238360efbdSAlfred Perlstein /* Cant handle this error */ 10248360efbdSAlfred Perlstein rpc_createerr.cf_stat = clnt_st; 10258360efbdSAlfred Perlstein clnt_geterr(client, &rpc_createerr.cf_error); 10268360efbdSAlfred Perlstein goto error; 10278360efbdSAlfred Perlstein } 10288360efbdSAlfred Perlstein } 10298360efbdSAlfred Perlstein 10308360efbdSAlfred Perlstein error: 10318360efbdSAlfred Perlstein if (client) { 10328360efbdSAlfred Perlstein CLNT_DESTROY(client); 10338360efbdSAlfred Perlstein client = NULL; 10348360efbdSAlfred Perlstein } 10358360efbdSAlfred Perlstein done: 10368360efbdSAlfred Perlstein if (nconf->nc_semantics != NC_TPI_CLTS) { 10378360efbdSAlfred Perlstein /* This client is the connectionless one */ 10388360efbdSAlfred Perlstein if (client) { 10398360efbdSAlfred Perlstein CLNT_DESTROY(client); 10408360efbdSAlfred Perlstein client = NULL; 10418360efbdSAlfred Perlstein } 10428360efbdSAlfred Perlstein } 10438360efbdSAlfred Perlstein if (clpp) { 10448360efbdSAlfred Perlstein *clpp = client; 10458360efbdSAlfred Perlstein } else if (client) { 10468360efbdSAlfred Perlstein CLNT_DESTROY(client); 10478360efbdSAlfred Perlstein } 104852353da8SIan Dowse if (parms.r_addr != NULL && parms.r_addr != nullstring) 104952353da8SIan Dowse free(parms.r_addr); 10508360efbdSAlfred Perlstein return (address); 10518360efbdSAlfred Perlstein } 10528360efbdSAlfred Perlstein 10538360efbdSAlfred Perlstein 10548360efbdSAlfred Perlstein /* 10558360efbdSAlfred Perlstein * Find the mapped address for program, version. 10568360efbdSAlfred Perlstein * Calls the rpcbind service remotely to do the lookup. 10578360efbdSAlfred Perlstein * Uses the transport specified in nconf. 10588360efbdSAlfred Perlstein * Returns FALSE (0) if no map exists, else returns 1. 10598360efbdSAlfred Perlstein * 10608360efbdSAlfred Perlstein * Assuming that the address is all properly allocated 10618360efbdSAlfred Perlstein */ 10628360efbdSAlfred Perlstein int 10638360efbdSAlfred Perlstein rpcb_getaddr(program, version, nconf, address, host) 10648360efbdSAlfred Perlstein rpcprog_t program; 10658360efbdSAlfred Perlstein rpcvers_t version; 10668360efbdSAlfred Perlstein const struct netconfig *nconf; 10678360efbdSAlfred Perlstein struct netbuf *address; 10688360efbdSAlfred Perlstein const char *host; 10698360efbdSAlfred Perlstein { 10708360efbdSAlfred Perlstein struct netbuf *na; 10718360efbdSAlfred Perlstein 10724e37855eSAlfred Perlstein if ((na = __rpcb_findaddr_timed(program, version, 10734e37855eSAlfred Perlstein (struct netconfig *) nconf, (char *) host, 10744e37855eSAlfred Perlstein (CLIENT **) NULL, (struct timeval *) NULL)) == NULL) 10758360efbdSAlfred Perlstein return (FALSE); 10768360efbdSAlfred Perlstein 10778360efbdSAlfred Perlstein if (na->len > address->maxlen) { 10788360efbdSAlfred Perlstein /* Too long address */ 10798360efbdSAlfred Perlstein free(na->buf); 10808360efbdSAlfred Perlstein free(na); 10818360efbdSAlfred Perlstein rpc_createerr.cf_stat = RPC_FAILED; 10828360efbdSAlfred Perlstein return (FALSE); 10838360efbdSAlfred Perlstein } 10848360efbdSAlfred Perlstein memcpy(address->buf, na->buf, (size_t)na->len); 10858360efbdSAlfred Perlstein address->len = na->len; 10868360efbdSAlfred Perlstein free(na->buf); 10878360efbdSAlfred Perlstein free(na); 10888360efbdSAlfred Perlstein return (TRUE); 10898360efbdSAlfred Perlstein } 10908360efbdSAlfred Perlstein 10918360efbdSAlfred Perlstein /* 10928360efbdSAlfred Perlstein * Get a copy of the current maps. 10938360efbdSAlfred Perlstein * Calls the rpcbind service remotely to get the maps. 10948360efbdSAlfred Perlstein * 10958360efbdSAlfred Perlstein * It returns only a list of the services 10968360efbdSAlfred Perlstein * It returns NULL on failure. 10978360efbdSAlfred Perlstein */ 10988360efbdSAlfred Perlstein rpcblist * 10998360efbdSAlfred Perlstein rpcb_getmaps(nconf, host) 11008360efbdSAlfred Perlstein const struct netconfig *nconf; 11018360efbdSAlfred Perlstein const char *host; 11028360efbdSAlfred Perlstein { 11038360efbdSAlfred Perlstein rpcblist_ptr head = NULL; 11048360efbdSAlfred Perlstein CLIENT *client; 11058360efbdSAlfred Perlstein enum clnt_stat clnt_st; 11068360efbdSAlfred Perlstein rpcvers_t vers = 0; 11078360efbdSAlfred Perlstein 11088360efbdSAlfred Perlstein client = getclnthandle(host, nconf, NULL); 11098360efbdSAlfred Perlstein if (client == NULL) { 11108360efbdSAlfred Perlstein return (head); 11118360efbdSAlfred Perlstein } 11128360efbdSAlfred Perlstein clnt_st = CLNT_CALL(client, (rpcproc_t)RPCBPROC_DUMP, 11138360efbdSAlfred Perlstein (xdrproc_t) xdr_void, NULL, (xdrproc_t) xdr_rpcblist_ptr, 11148360efbdSAlfred Perlstein (char *)(void *)&head, tottimeout); 11158360efbdSAlfred Perlstein if (clnt_st == RPC_SUCCESS) 11168360efbdSAlfred Perlstein goto done; 11178360efbdSAlfred Perlstein 11188360efbdSAlfred Perlstein if ((clnt_st != RPC_PROGVERSMISMATCH) && 11198360efbdSAlfred Perlstein (clnt_st != RPC_PROGUNAVAIL)) { 11208360efbdSAlfred Perlstein rpc_createerr.cf_stat = RPC_RPCBFAILURE; 11218360efbdSAlfred Perlstein clnt_geterr(client, &rpc_createerr.cf_error); 11228360efbdSAlfred Perlstein goto done; 11238360efbdSAlfred Perlstein } 11248360efbdSAlfred Perlstein 11258360efbdSAlfred Perlstein /* fall back to earlier version */ 11268360efbdSAlfred Perlstein CLNT_CONTROL(client, CLGET_VERS, (char *)(void *)&vers); 11278360efbdSAlfred Perlstein if (vers == RPCBVERS4) { 11288360efbdSAlfred Perlstein vers = RPCBVERS; 11298360efbdSAlfred Perlstein CLNT_CONTROL(client, CLSET_VERS, (char *)(void *)&vers); 11308360efbdSAlfred Perlstein if (CLNT_CALL(client, (rpcproc_t)RPCBPROC_DUMP, 11318360efbdSAlfred Perlstein (xdrproc_t) xdr_void, NULL, (xdrproc_t) xdr_rpcblist_ptr, 11328360efbdSAlfred Perlstein (char *)(void *)&head, tottimeout) == RPC_SUCCESS) 11338360efbdSAlfred Perlstein goto done; 11348360efbdSAlfred Perlstein } 11358360efbdSAlfred Perlstein rpc_createerr.cf_stat = RPC_RPCBFAILURE; 11368360efbdSAlfred Perlstein clnt_geterr(client, &rpc_createerr.cf_error); 11378360efbdSAlfred Perlstein 11388360efbdSAlfred Perlstein done: 11398360efbdSAlfred Perlstein CLNT_DESTROY(client); 11408360efbdSAlfred Perlstein return (head); 11418360efbdSAlfred Perlstein } 11428360efbdSAlfred Perlstein 11438360efbdSAlfred Perlstein /* 11448360efbdSAlfred Perlstein * rpcbinder remote-call-service interface. 11458360efbdSAlfred Perlstein * This routine is used to call the rpcbind remote call service 11468360efbdSAlfred Perlstein * which will look up a service program in the address maps, and then 11478360efbdSAlfred Perlstein * remotely call that routine with the given parameters. This allows 11488360efbdSAlfred Perlstein * programs to do a lookup and call in one step. 11498360efbdSAlfred Perlstein */ 11508360efbdSAlfred Perlstein enum clnt_stat 11518360efbdSAlfred Perlstein rpcb_rmtcall(nconf, host, prog, vers, proc, xdrargs, argsp, 11528360efbdSAlfred Perlstein xdrres, resp, tout, addr_ptr) 11538360efbdSAlfred Perlstein const struct netconfig *nconf; /* Netconfig structure */ 11548360efbdSAlfred Perlstein const char *host; /* Remote host name */ 11558360efbdSAlfred Perlstein rpcprog_t prog; 11568360efbdSAlfred Perlstein rpcvers_t vers; 11578360efbdSAlfred Perlstein rpcproc_t proc; /* Remote proc identifiers */ 11588360efbdSAlfred Perlstein xdrproc_t xdrargs, xdrres; /* XDR routines */ 11598360efbdSAlfred Perlstein caddr_t argsp, resp; /* Argument and Result */ 11608360efbdSAlfred Perlstein struct timeval tout; /* Timeout value for this call */ 11618360efbdSAlfred Perlstein const struct netbuf *addr_ptr; /* Preallocated netbuf address */ 11628360efbdSAlfred Perlstein { 11638360efbdSAlfred Perlstein CLIENT *client; 11648360efbdSAlfred Perlstein enum clnt_stat stat; 11658360efbdSAlfred Perlstein struct r_rpcb_rmtcallargs a; 11668360efbdSAlfred Perlstein struct r_rpcb_rmtcallres r; 11678360efbdSAlfred Perlstein rpcvers_t rpcb_vers; 11688360efbdSAlfred Perlstein 116952353da8SIan Dowse stat = 0; 11708360efbdSAlfred Perlstein client = getclnthandle(host, nconf, NULL); 11718360efbdSAlfred Perlstein if (client == NULL) { 11728360efbdSAlfred Perlstein return (RPC_FAILED); 11738360efbdSAlfred Perlstein } 11748360efbdSAlfred Perlstein /*LINTED const castaway*/ 11758360efbdSAlfred Perlstein CLNT_CONTROL(client, CLSET_RETRY_TIMEOUT, (char *)(void *)&rmttimeout); 11768360efbdSAlfred Perlstein a.prog = prog; 11778360efbdSAlfred Perlstein a.vers = vers; 11788360efbdSAlfred Perlstein a.proc = proc; 11798360efbdSAlfred Perlstein a.args.args_val = argsp; 11808360efbdSAlfred Perlstein a.xdr_args = xdrargs; 11818360efbdSAlfred Perlstein r.addr = NULL; 11828360efbdSAlfred Perlstein r.results.results_val = resp; 11838360efbdSAlfred Perlstein r.xdr_res = xdrres; 11848360efbdSAlfred Perlstein 11858360efbdSAlfred Perlstein for (rpcb_vers = RPCBVERS4; rpcb_vers >= RPCBVERS; rpcb_vers--) { 11868360efbdSAlfred Perlstein CLNT_CONTROL(client, CLSET_VERS, (char *)(void *)&rpcb_vers); 11878360efbdSAlfred Perlstein stat = CLNT_CALL(client, (rpcproc_t)RPCBPROC_CALLIT, 11888360efbdSAlfred Perlstein (xdrproc_t) xdr_rpcb_rmtcallargs, (char *)(void *)&a, 11898360efbdSAlfred Perlstein (xdrproc_t) xdr_rpcb_rmtcallres, (char *)(void *)&r, tout); 11908360efbdSAlfred Perlstein if ((stat == RPC_SUCCESS) && (addr_ptr != NULL)) { 11918360efbdSAlfred Perlstein struct netbuf *na; 11928360efbdSAlfred Perlstein /*LINTED const castaway*/ 11938360efbdSAlfred Perlstein na = uaddr2taddr((struct netconfig *) nconf, r.addr); 11948360efbdSAlfred Perlstein if (!na) { 11958360efbdSAlfred Perlstein stat = RPC_N2AXLATEFAILURE; 11968360efbdSAlfred Perlstein /*LINTED const castaway*/ 11978360efbdSAlfred Perlstein ((struct netbuf *) addr_ptr)->len = 0; 11988360efbdSAlfred Perlstein goto error; 11998360efbdSAlfred Perlstein } 12008360efbdSAlfred Perlstein if (na->len > addr_ptr->maxlen) { 12018360efbdSAlfred Perlstein /* Too long address */ 12028360efbdSAlfred Perlstein stat = RPC_FAILED; /* XXX A better error no */ 12038360efbdSAlfred Perlstein free(na->buf); 12048360efbdSAlfred Perlstein free(na); 12058360efbdSAlfred Perlstein /*LINTED const castaway*/ 12068360efbdSAlfred Perlstein ((struct netbuf *) addr_ptr)->len = 0; 12078360efbdSAlfred Perlstein goto error; 12088360efbdSAlfred Perlstein } 12098360efbdSAlfred Perlstein memcpy(addr_ptr->buf, na->buf, (size_t)na->len); 12108360efbdSAlfred Perlstein /*LINTED const castaway*/ 12118360efbdSAlfred Perlstein ((struct netbuf *)addr_ptr)->len = na->len; 12128360efbdSAlfred Perlstein free(na->buf); 12138360efbdSAlfred Perlstein free(na); 12148360efbdSAlfred Perlstein break; 12158360efbdSAlfred Perlstein } else if ((stat != RPC_PROGVERSMISMATCH) && 12168360efbdSAlfred Perlstein (stat != RPC_PROGUNAVAIL)) { 12178360efbdSAlfred Perlstein goto error; 12188360efbdSAlfred Perlstein } 12198360efbdSAlfred Perlstein } 12208360efbdSAlfred Perlstein error: 12218360efbdSAlfred Perlstein CLNT_DESTROY(client); 12228360efbdSAlfred Perlstein if (r.addr) 12238360efbdSAlfred Perlstein xdr_free((xdrproc_t) xdr_wrapstring, (char *)(void *)&r.addr); 12248360efbdSAlfred Perlstein return (stat); 12258360efbdSAlfred Perlstein } 12268360efbdSAlfred Perlstein 12278360efbdSAlfred Perlstein /* 12288360efbdSAlfred Perlstein * Gets the time on the remote host. 12298360efbdSAlfred Perlstein * Returns 1 if succeeds else 0. 12308360efbdSAlfred Perlstein */ 12318360efbdSAlfred Perlstein bool_t 12328360efbdSAlfred Perlstein rpcb_gettime(host, timep) 12338360efbdSAlfred Perlstein const char *host; 12348360efbdSAlfred Perlstein time_t *timep; 12358360efbdSAlfred Perlstein { 12368360efbdSAlfred Perlstein CLIENT *client = NULL; 12378360efbdSAlfred Perlstein void *handle; 12388360efbdSAlfred Perlstein struct netconfig *nconf; 12398360efbdSAlfred Perlstein rpcvers_t vers; 12408360efbdSAlfred Perlstein enum clnt_stat st; 12418360efbdSAlfred Perlstein 12428360efbdSAlfred Perlstein 1243b6c452a8SMartin Blapp if ((host == NULL) || (host[0] == 0)) { 12448360efbdSAlfred Perlstein time(timep); 12458360efbdSAlfred Perlstein return (TRUE); 12468360efbdSAlfred Perlstein } 12478360efbdSAlfred Perlstein 12488360efbdSAlfred Perlstein if ((handle = __rpc_setconf("netpath")) == NULL) { 12498360efbdSAlfred Perlstein rpc_createerr.cf_stat = RPC_UNKNOWNPROTO; 12508360efbdSAlfred Perlstein return (FALSE); 12518360efbdSAlfred Perlstein } 12528360efbdSAlfred Perlstein rpc_createerr.cf_stat = RPC_SUCCESS; 12538360efbdSAlfred Perlstein while (client == NULL) { 12548360efbdSAlfred Perlstein if ((nconf = __rpc_getconf(handle)) == NULL) { 12558360efbdSAlfred Perlstein if (rpc_createerr.cf_stat == RPC_SUCCESS) 12568360efbdSAlfred Perlstein rpc_createerr.cf_stat = RPC_UNKNOWNPROTO; 12578360efbdSAlfred Perlstein break; 12588360efbdSAlfred Perlstein } 12598360efbdSAlfred Perlstein client = getclnthandle(host, nconf, NULL); 12608360efbdSAlfred Perlstein if (client) 12618360efbdSAlfred Perlstein break; 12628360efbdSAlfred Perlstein } 12638360efbdSAlfred Perlstein __rpc_endconf(handle); 12648360efbdSAlfred Perlstein if (client == (CLIENT *) NULL) { 12658360efbdSAlfred Perlstein return (FALSE); 12668360efbdSAlfred Perlstein } 12678360efbdSAlfred Perlstein 12688360efbdSAlfred Perlstein st = CLNT_CALL(client, (rpcproc_t)RPCBPROC_GETTIME, 12698360efbdSAlfred Perlstein (xdrproc_t) xdr_void, NULL, 12708360efbdSAlfred Perlstein (xdrproc_t) xdr_int, (char *)(void *)timep, tottimeout); 12718360efbdSAlfred Perlstein 12728360efbdSAlfred Perlstein if ((st == RPC_PROGVERSMISMATCH) || (st == RPC_PROGUNAVAIL)) { 12738360efbdSAlfred Perlstein CLNT_CONTROL(client, CLGET_VERS, (char *)(void *)&vers); 12748360efbdSAlfred Perlstein if (vers == RPCBVERS4) { 12758360efbdSAlfred Perlstein /* fall back to earlier version */ 12768360efbdSAlfred Perlstein vers = RPCBVERS; 12778360efbdSAlfred Perlstein CLNT_CONTROL(client, CLSET_VERS, (char *)(void *)&vers); 12788360efbdSAlfred Perlstein st = CLNT_CALL(client, (rpcproc_t)RPCBPROC_GETTIME, 12798360efbdSAlfred Perlstein (xdrproc_t) xdr_void, NULL, 12808360efbdSAlfred Perlstein (xdrproc_t) xdr_int, (char *)(void *)timep, 12818360efbdSAlfred Perlstein tottimeout); 12828360efbdSAlfred Perlstein } 12838360efbdSAlfred Perlstein } 12848360efbdSAlfred Perlstein CLNT_DESTROY(client); 12858360efbdSAlfred Perlstein return (st == RPC_SUCCESS? TRUE: FALSE); 12868360efbdSAlfred Perlstein } 12878360efbdSAlfred Perlstein 12888360efbdSAlfred Perlstein /* 12898360efbdSAlfred Perlstein * Converts taddr to universal address. This routine should never 12908360efbdSAlfred Perlstein * really be called because local n2a libraries are always provided. 12918360efbdSAlfred Perlstein */ 12928360efbdSAlfred Perlstein char * 12938360efbdSAlfred Perlstein rpcb_taddr2uaddr(nconf, taddr) 12948360efbdSAlfred Perlstein struct netconfig *nconf; 12958360efbdSAlfred Perlstein struct netbuf *taddr; 12968360efbdSAlfred Perlstein { 12978360efbdSAlfred Perlstein CLIENT *client; 12988360efbdSAlfred Perlstein char *uaddr = NULL; 12998360efbdSAlfred Perlstein 13008360efbdSAlfred Perlstein 13018360efbdSAlfred Perlstein /* parameter checking */ 13028360efbdSAlfred Perlstein if (nconf == NULL) { 13038360efbdSAlfred Perlstein rpc_createerr.cf_stat = RPC_UNKNOWNPROTO; 13048360efbdSAlfred Perlstein return (NULL); 13058360efbdSAlfred Perlstein } 13068360efbdSAlfred Perlstein if (taddr == NULL) { 13078360efbdSAlfred Perlstein rpc_createerr.cf_stat = RPC_UNKNOWNADDR; 13088360efbdSAlfred Perlstein return (NULL); 13098360efbdSAlfred Perlstein } 13108360efbdSAlfred Perlstein client = local_rpcb(); 13118360efbdSAlfred Perlstein if (! client) { 13128360efbdSAlfred Perlstein return (NULL); 13138360efbdSAlfred Perlstein } 13148360efbdSAlfred Perlstein 13158360efbdSAlfred Perlstein CLNT_CALL(client, (rpcproc_t)RPCBPROC_TADDR2UADDR, 13168360efbdSAlfred Perlstein (xdrproc_t) xdr_netbuf, (char *)(void *)taddr, 13178360efbdSAlfred Perlstein (xdrproc_t) xdr_wrapstring, (char *)(void *)&uaddr, tottimeout); 13188360efbdSAlfred Perlstein CLNT_DESTROY(client); 13198360efbdSAlfred Perlstein return (uaddr); 13208360efbdSAlfred Perlstein } 13218360efbdSAlfred Perlstein 13228360efbdSAlfred Perlstein /* 13238360efbdSAlfred Perlstein * Converts universal address to netbuf. This routine should never 13248360efbdSAlfred Perlstein * really be called because local n2a libraries are always provided. 13258360efbdSAlfred Perlstein */ 13268360efbdSAlfred Perlstein struct netbuf * 13278360efbdSAlfred Perlstein rpcb_uaddr2taddr(nconf, uaddr) 13288360efbdSAlfred Perlstein struct netconfig *nconf; 13298360efbdSAlfred Perlstein char *uaddr; 13308360efbdSAlfred Perlstein { 13318360efbdSAlfred Perlstein CLIENT *client; 13328360efbdSAlfred Perlstein struct netbuf *taddr; 13338360efbdSAlfred Perlstein 13348360efbdSAlfred Perlstein 13358360efbdSAlfred Perlstein /* parameter checking */ 13368360efbdSAlfred Perlstein if (nconf == NULL) { 13378360efbdSAlfred Perlstein rpc_createerr.cf_stat = RPC_UNKNOWNPROTO; 13388360efbdSAlfred Perlstein return (NULL); 13398360efbdSAlfred Perlstein } 13408360efbdSAlfred Perlstein if (uaddr == NULL) { 13418360efbdSAlfred Perlstein rpc_createerr.cf_stat = RPC_UNKNOWNADDR; 13428360efbdSAlfred Perlstein return (NULL); 13438360efbdSAlfred Perlstein } 13448360efbdSAlfred Perlstein client = local_rpcb(); 13458360efbdSAlfred Perlstein if (! client) { 13468360efbdSAlfred Perlstein return (NULL); 13478360efbdSAlfred Perlstein } 13488360efbdSAlfred Perlstein 13498360efbdSAlfred Perlstein taddr = (struct netbuf *)calloc(1, sizeof (struct netbuf)); 13508360efbdSAlfred Perlstein if (taddr == NULL) { 13518360efbdSAlfred Perlstein CLNT_DESTROY(client); 13528360efbdSAlfred Perlstein return (NULL); 13538360efbdSAlfred Perlstein } 13548360efbdSAlfred Perlstein if (CLNT_CALL(client, (rpcproc_t)RPCBPROC_UADDR2TADDR, 13558360efbdSAlfred Perlstein (xdrproc_t) xdr_wrapstring, (char *)(void *)&uaddr, 13568360efbdSAlfred Perlstein (xdrproc_t) xdr_netbuf, (char *)(void *)taddr, 13578360efbdSAlfred Perlstein tottimeout) != RPC_SUCCESS) { 13588360efbdSAlfred Perlstein free(taddr); 13598360efbdSAlfred Perlstein taddr = NULL; 13608360efbdSAlfred Perlstein } 13618360efbdSAlfred Perlstein CLNT_DESTROY(client); 13628360efbdSAlfred Perlstein return (taddr); 13638360efbdSAlfred Perlstein } 1364