14a5d661aSToomas Soome /* $NetBSD: rpc.c,v 1.18 1998/01/23 19:27:45 thorpej Exp $ */ 24a5d661aSToomas Soome 34a5d661aSToomas Soome /* 44a5d661aSToomas Soome * Copyright (c) 1992 Regents of the University of California. 54a5d661aSToomas Soome * All rights reserved. 64a5d661aSToomas Soome * 74a5d661aSToomas Soome * This software was developed by the Computer Systems Engineering group 84a5d661aSToomas Soome * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and 94a5d661aSToomas Soome * contributed to Berkeley. 104a5d661aSToomas Soome * 114a5d661aSToomas Soome * Redistribution and use in source and binary forms, with or without 124a5d661aSToomas Soome * modification, are permitted provided that the following conditions 134a5d661aSToomas Soome * are met: 144a5d661aSToomas Soome * 1. Redistributions of source code must retain the above copyright 154a5d661aSToomas Soome * notice, this list of conditions and the following disclaimer. 164a5d661aSToomas Soome * 2. Redistributions in binary form must reproduce the above copyright 174a5d661aSToomas Soome * notice, this list of conditions and the following disclaimer in the 184a5d661aSToomas Soome * documentation and/or other materials provided with the distribution. 194a5d661aSToomas Soome * 4. Neither the name of the University nor the names of its contributors 204a5d661aSToomas Soome * may be used to endorse or promote products derived from this software 214a5d661aSToomas Soome * without specific prior written permission. 224a5d661aSToomas Soome * 234a5d661aSToomas Soome * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 244a5d661aSToomas Soome * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 254a5d661aSToomas Soome * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 264a5d661aSToomas Soome * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 274a5d661aSToomas Soome * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 284a5d661aSToomas Soome * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 294a5d661aSToomas Soome * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 304a5d661aSToomas Soome * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 314a5d661aSToomas Soome * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 324a5d661aSToomas Soome * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 334a5d661aSToomas Soome * SUCH DAMAGE. 344a5d661aSToomas Soome * 354a5d661aSToomas Soome * @(#) Header: rpc.c,v 1.12 93/09/28 08:31:56 leres Exp (LBL) 364a5d661aSToomas Soome */ 374a5d661aSToomas Soome 384a5d661aSToomas Soome #include <sys/cdefs.h> 394a5d661aSToomas Soome 404a5d661aSToomas Soome /* 414a5d661aSToomas Soome * RPC functions used by NFS and bootparams. 424a5d661aSToomas Soome * Note that bootparams requires the ability to find out the 434a5d661aSToomas Soome * address of the server from which its response has come. 444a5d661aSToomas Soome * This is supported by keeping the IP/UDP headers in the 454a5d661aSToomas Soome * buffer space provided by the caller. (See rpc_fromaddr) 464a5d661aSToomas Soome */ 474a5d661aSToomas Soome 484a5d661aSToomas Soome #include <sys/param.h> 494a5d661aSToomas Soome #include <sys/socket.h> 504a5d661aSToomas Soome 514a5d661aSToomas Soome #include <netinet/in.h> 524a5d661aSToomas Soome #include <netinet/in_systm.h> 534a5d661aSToomas Soome 544a5d661aSToomas Soome #include <string.h> 554a5d661aSToomas Soome 564a5d661aSToomas Soome #include "rpcv2.h" 574a5d661aSToomas Soome 584a5d661aSToomas Soome #include "stand.h" 594a5d661aSToomas Soome #include "net.h" 604a5d661aSToomas Soome #include "netif.h" 614a5d661aSToomas Soome #include "rpc.h" 624a5d661aSToomas Soome 634a5d661aSToomas Soome struct auth_info { 644a5d661aSToomas Soome int32_t authtype; /* auth type */ 654a5d661aSToomas Soome u_int32_t authlen; /* auth length */ 664a5d661aSToomas Soome }; 674a5d661aSToomas Soome 684a5d661aSToomas Soome struct auth_unix { 694a5d661aSToomas Soome int32_t ua_time; 704a5d661aSToomas Soome int32_t ua_hostname; /* null */ 714a5d661aSToomas Soome int32_t ua_uid; 724a5d661aSToomas Soome int32_t ua_gid; 734a5d661aSToomas Soome int32_t ua_gidlist; /* null */ 744a5d661aSToomas Soome }; 754a5d661aSToomas Soome 764a5d661aSToomas Soome struct rpc_call { 774a5d661aSToomas Soome u_int32_t rp_xid; /* request transaction id */ 784a5d661aSToomas Soome int32_t rp_direction; /* call direction (0) */ 794a5d661aSToomas Soome u_int32_t rp_rpcvers; /* rpc version (2) */ 804a5d661aSToomas Soome u_int32_t rp_prog; /* program */ 814a5d661aSToomas Soome u_int32_t rp_vers; /* version */ 824a5d661aSToomas Soome u_int32_t rp_proc; /* procedure */ 834a5d661aSToomas Soome }; 844a5d661aSToomas Soome 854a5d661aSToomas Soome struct rpc_reply { 864a5d661aSToomas Soome u_int32_t rp_xid; /* request transaction id */ 874a5d661aSToomas Soome int32_t rp_direction; /* call direction (1) */ 884a5d661aSToomas Soome int32_t rp_astatus; /* accept status (0: accepted) */ 894a5d661aSToomas Soome union { 904a5d661aSToomas Soome u_int32_t rpu_errno; 914a5d661aSToomas Soome struct { 924a5d661aSToomas Soome struct auth_info rok_auth; 934a5d661aSToomas Soome u_int32_t rok_status; 944a5d661aSToomas Soome } rpu_rok; 954a5d661aSToomas Soome } rp_u; 964a5d661aSToomas Soome }; 974a5d661aSToomas Soome 984a5d661aSToomas Soome /* Local forwards */ 99*7b2a1233SToomas Soome static ssize_t recvrpc(struct iodesc *, void **, void **, time_t); 1004a5d661aSToomas Soome static int rpc_getport(struct iodesc *, n_long, n_long); 1014a5d661aSToomas Soome 1024a5d661aSToomas Soome int rpc_xid; 1034a5d661aSToomas Soome int rpc_port = 0x400; /* predecrement */ 1044a5d661aSToomas Soome 1054a5d661aSToomas Soome /* 1064a5d661aSToomas Soome * Make a rpc call; return length of answer 1074a5d661aSToomas Soome * Note: Caller must leave room for headers. 1084a5d661aSToomas Soome */ 1094a5d661aSToomas Soome ssize_t 1104a5d661aSToomas Soome rpc_call(struct iodesc *d, n_long prog, n_long vers, n_long proc, 111*7b2a1233SToomas Soome void *sdata, size_t slen, void **rdata, void **pkt) 1124a5d661aSToomas Soome { 113*7b2a1233SToomas Soome ssize_t cc, rsize; 1144a5d661aSToomas Soome struct auth_info *auth; 1154a5d661aSToomas Soome struct rpc_call *call; 1164a5d661aSToomas Soome struct rpc_reply *reply; 1174a5d661aSToomas Soome char *send_head, *send_tail; 118*7b2a1233SToomas Soome void *ptr; 1194a5d661aSToomas Soome n_long x; 1204a5d661aSToomas Soome int port; /* host order */ 1214a5d661aSToomas Soome 1224a5d661aSToomas Soome #ifdef RPC_DEBUG 1234a5d661aSToomas Soome if (debug) 1244a5d661aSToomas Soome printf("rpc_call: prog=0x%x vers=%d proc=%d\n", 1254a5d661aSToomas Soome prog, vers, proc); 1264a5d661aSToomas Soome #endif 1274a5d661aSToomas Soome 1284a5d661aSToomas Soome port = rpc_getport(d, prog, vers); 1294a5d661aSToomas Soome if (port == -1) 1304a5d661aSToomas Soome return (-1); 1314a5d661aSToomas Soome 1324a5d661aSToomas Soome d->destport = htons(port); 1334a5d661aSToomas Soome 1344a5d661aSToomas Soome /* 1354a5d661aSToomas Soome * Prepend authorization stuff and headers. 1364a5d661aSToomas Soome * Note, must prepend things in reverse order. 1374a5d661aSToomas Soome */ 1384a5d661aSToomas Soome send_head = sdata; 1394a5d661aSToomas Soome send_tail = (char *)sdata + slen; 1404a5d661aSToomas Soome 1414a5d661aSToomas Soome /* Auth verifier is always auth_null */ 1424a5d661aSToomas Soome send_head -= sizeof(*auth); 1434a5d661aSToomas Soome auth = (struct auth_info *)send_head; 1444a5d661aSToomas Soome auth->authtype = htonl(RPCAUTH_NULL); 1454a5d661aSToomas Soome auth->authlen = 0; 1464a5d661aSToomas Soome 1474a5d661aSToomas Soome /* Auth credentials: always auth unix (as root) */ 1484a5d661aSToomas Soome send_head -= sizeof(struct auth_unix); 1494a5d661aSToomas Soome bzero(send_head, sizeof(struct auth_unix)); 1504a5d661aSToomas Soome send_head -= sizeof(*auth); 1514a5d661aSToomas Soome auth = (struct auth_info *)send_head; 1524a5d661aSToomas Soome auth->authtype = htonl(RPCAUTH_UNIX); 1534a5d661aSToomas Soome auth->authlen = htonl(sizeof(struct auth_unix)); 1544a5d661aSToomas Soome 1554a5d661aSToomas Soome /* RPC call structure. */ 1564a5d661aSToomas Soome send_head -= sizeof(*call); 1574a5d661aSToomas Soome call = (struct rpc_call *)send_head; 1584a5d661aSToomas Soome rpc_xid++; 1594a5d661aSToomas Soome call->rp_xid = htonl(rpc_xid); 1604a5d661aSToomas Soome call->rp_direction = htonl(RPC_CALL); 1614a5d661aSToomas Soome call->rp_rpcvers = htonl(RPC_VER2); 1624a5d661aSToomas Soome call->rp_prog = htonl(prog); 1634a5d661aSToomas Soome call->rp_vers = htonl(vers); 1644a5d661aSToomas Soome call->rp_proc = htonl(proc); 1654a5d661aSToomas Soome 166*7b2a1233SToomas Soome ptr = NULL; 1674a5d661aSToomas Soome cc = sendrecv(d, 1684a5d661aSToomas Soome sendudp, send_head, send_tail - send_head, 169*7b2a1233SToomas Soome recvrpc, &ptr, (void **)&reply); 1704a5d661aSToomas Soome 1714a5d661aSToomas Soome #ifdef RPC_DEBUG 1724a5d661aSToomas Soome if (debug) 173*7b2a1233SToomas Soome printf("callrpc: cc=%zd\n", cc); 1744a5d661aSToomas Soome #endif 1754a5d661aSToomas Soome if (cc == -1) 1764a5d661aSToomas Soome return (-1); 1774a5d661aSToomas Soome 1784a5d661aSToomas Soome if (cc <= sizeof(*reply)) { 1794a5d661aSToomas Soome errno = EBADRPC; 180*7b2a1233SToomas Soome free(ptr); 1814a5d661aSToomas Soome return (-1); 1824a5d661aSToomas Soome } 1834a5d661aSToomas Soome 1844a5d661aSToomas Soome /* 1854a5d661aSToomas Soome * Check the RPC reply status. 1864a5d661aSToomas Soome * The xid, dir, astatus were already checked. 1874a5d661aSToomas Soome */ 1884a5d661aSToomas Soome auth = &reply->rp_u.rpu_rok.rok_auth; 1894a5d661aSToomas Soome x = ntohl(auth->authlen); 1904a5d661aSToomas Soome if (x != 0) { 1914a5d661aSToomas Soome #ifdef RPC_DEBUG 1924a5d661aSToomas Soome if (debug) 1934a5d661aSToomas Soome printf("callrpc: reply auth != NULL\n"); 1944a5d661aSToomas Soome #endif 1954a5d661aSToomas Soome errno = EBADRPC; 196*7b2a1233SToomas Soome free(ptr); 1974a5d661aSToomas Soome return (-1); 1984a5d661aSToomas Soome } 1994a5d661aSToomas Soome x = ntohl(reply->rp_u.rpu_rok.rok_status); 2004a5d661aSToomas Soome if (x != 0) { 2014a5d661aSToomas Soome printf("callrpc: error = %ld\n", (long)x); 2024a5d661aSToomas Soome errno = EBADRPC; 203*7b2a1233SToomas Soome free(ptr); 2044a5d661aSToomas Soome return (-1); 2054a5d661aSToomas Soome } 2064a5d661aSToomas Soome 207*7b2a1233SToomas Soome rsize = cc - sizeof(*reply); 208*7b2a1233SToomas Soome *rdata = (void *)((uintptr_t)reply + sizeof(*reply)); 209*7b2a1233SToomas Soome *pkt = ptr; 210*7b2a1233SToomas Soome return (rsize); 2114a5d661aSToomas Soome } 2124a5d661aSToomas Soome 2134a5d661aSToomas Soome /* 2144a5d661aSToomas Soome * Returns true if packet is the one we're waiting for. 2154a5d661aSToomas Soome * This just checks the XID, direction, acceptance. 2164a5d661aSToomas Soome * Remaining checks are done by callrpc 2174a5d661aSToomas Soome */ 2184a5d661aSToomas Soome static ssize_t 219*7b2a1233SToomas Soome recvrpc(struct iodesc *d, void **pkt, void **payload, time_t tleft) 2204a5d661aSToomas Soome { 221*7b2a1233SToomas Soome void *ptr; 2224a5d661aSToomas Soome struct rpc_reply *reply; 2234a5d661aSToomas Soome ssize_t n; 2244a5d661aSToomas Soome int x; 2254a5d661aSToomas Soome 2264a5d661aSToomas Soome errno = 0; 2274a5d661aSToomas Soome #ifdef RPC_DEBUG 2284a5d661aSToomas Soome if (debug) 229*7b2a1233SToomas Soome printf("recvrpc: called\n"); 2304a5d661aSToomas Soome #endif 2314a5d661aSToomas Soome 232*7b2a1233SToomas Soome ptr = NULL; 233*7b2a1233SToomas Soome n = readudp(d, &ptr, (void **)&reply, tleft); 234*7b2a1233SToomas Soome if (n <= (4 * 4)) { 235*7b2a1233SToomas Soome free(ptr); 236*7b2a1233SToomas Soome return (-1); 237*7b2a1233SToomas Soome } 2384a5d661aSToomas Soome 2394a5d661aSToomas Soome x = ntohl(reply->rp_xid); 2404a5d661aSToomas Soome if (x != rpc_xid) { 2414a5d661aSToomas Soome #ifdef RPC_DEBUG 2424a5d661aSToomas Soome if (debug) 2434a5d661aSToomas Soome printf("recvrpc: rp_xid %d != xid %d\n", x, rpc_xid); 2444a5d661aSToomas Soome #endif 245*7b2a1233SToomas Soome free(ptr); 246*7b2a1233SToomas Soome return (-1); 2474a5d661aSToomas Soome } 2484a5d661aSToomas Soome 2494a5d661aSToomas Soome x = ntohl(reply->rp_direction); 2504a5d661aSToomas Soome if (x != RPC_REPLY) { 2514a5d661aSToomas Soome #ifdef RPC_DEBUG 2524a5d661aSToomas Soome if (debug) 2534a5d661aSToomas Soome printf("recvrpc: rp_direction %d != REPLY\n", x); 2544a5d661aSToomas Soome #endif 255*7b2a1233SToomas Soome free(ptr); 256*7b2a1233SToomas Soome return (-1); 2574a5d661aSToomas Soome } 2584a5d661aSToomas Soome 2594a5d661aSToomas Soome x = ntohl(reply->rp_astatus); 2604a5d661aSToomas Soome if (x != RPC_MSGACCEPTED) { 2614a5d661aSToomas Soome errno = ntohl(reply->rp_u.rpu_errno); 2624a5d661aSToomas Soome printf("recvrpc: reject, astat=%d, errno=%d\n", x, errno); 263*7b2a1233SToomas Soome free(ptr); 264*7b2a1233SToomas Soome return (-1); 2654a5d661aSToomas Soome } 2664a5d661aSToomas Soome 267*7b2a1233SToomas Soome *pkt = ptr; 268*7b2a1233SToomas Soome *payload = reply; 2694a5d661aSToomas Soome /* Return data count (thus indicating success) */ 2704a5d661aSToomas Soome return (n); 2714a5d661aSToomas Soome } 2724a5d661aSToomas Soome 2734a5d661aSToomas Soome /* 2744a5d661aSToomas Soome * Given a pointer to a reply just received, 2754a5d661aSToomas Soome * dig out the IP address/port from the headers. 2764a5d661aSToomas Soome */ 2774a5d661aSToomas Soome void 2784a5d661aSToomas Soome rpc_fromaddr(void *pkt, struct in_addr *addr, u_short *port) 2794a5d661aSToomas Soome { 2804a5d661aSToomas Soome struct hackhdr { 2814a5d661aSToomas Soome /* Tail of IP header: just IP addresses */ 2824a5d661aSToomas Soome n_long ip_src; 2834a5d661aSToomas Soome n_long ip_dst; 2844a5d661aSToomas Soome /* UDP header: */ 2854a5d661aSToomas Soome u_int16_t uh_sport; /* source port */ 2864a5d661aSToomas Soome u_int16_t uh_dport; /* destination port */ 2874a5d661aSToomas Soome int16_t uh_ulen; /* udp length */ 2884a5d661aSToomas Soome u_int16_t uh_sum; /* udp checksum */ 2894a5d661aSToomas Soome /* RPC reply header: */ 2904a5d661aSToomas Soome struct rpc_reply rpc; 2914a5d661aSToomas Soome } *hhdr; 2924a5d661aSToomas Soome 2934a5d661aSToomas Soome hhdr = ((struct hackhdr *)pkt) - 1; 2944a5d661aSToomas Soome addr->s_addr = hhdr->ip_src; 2954a5d661aSToomas Soome *port = hhdr->uh_sport; 2964a5d661aSToomas Soome } 2974a5d661aSToomas Soome 2984a5d661aSToomas Soome /* 2994a5d661aSToomas Soome * RPC Portmapper cache 3004a5d661aSToomas Soome */ 3014a5d661aSToomas Soome #define PMAP_NUM 8 /* need at most 5 pmap entries */ 3024a5d661aSToomas Soome 3034a5d661aSToomas Soome int rpc_pmap_num; 3044a5d661aSToomas Soome struct pmap_list { 3054a5d661aSToomas Soome struct in_addr addr; /* server, net order */ 3064a5d661aSToomas Soome u_int prog; /* host order */ 3074a5d661aSToomas Soome u_int vers; /* host order */ 3084a5d661aSToomas Soome int port; /* host order */ 3094a5d661aSToomas Soome } rpc_pmap_list[PMAP_NUM]; 3104a5d661aSToomas Soome 3114a5d661aSToomas Soome /* 3124a5d661aSToomas Soome * return port number in host order, or -1. 3134a5d661aSToomas Soome * arguments are: 3144a5d661aSToomas Soome * addr .. server, net order. 3154a5d661aSToomas Soome * prog .. host order. 3164a5d661aSToomas Soome * vers .. host order. 3174a5d661aSToomas Soome */ 3184a5d661aSToomas Soome int 3194a5d661aSToomas Soome rpc_pmap_getcache(struct in_addr addr, u_int prog, u_int vers) 3204a5d661aSToomas Soome { 3214a5d661aSToomas Soome struct pmap_list *pl; 3224a5d661aSToomas Soome 3234a5d661aSToomas Soome for (pl = rpc_pmap_list; pl < &rpc_pmap_list[rpc_pmap_num]; pl++) { 3244a5d661aSToomas Soome if (pl->addr.s_addr == addr.s_addr && 3254a5d661aSToomas Soome pl->prog == prog && pl->vers == vers ) 3264a5d661aSToomas Soome { 3274a5d661aSToomas Soome return (pl->port); 3284a5d661aSToomas Soome } 3294a5d661aSToomas Soome } 3304a5d661aSToomas Soome return (-1); 3314a5d661aSToomas Soome } 3324a5d661aSToomas Soome 3334a5d661aSToomas Soome /* 3344a5d661aSToomas Soome * arguments are: 3354a5d661aSToomas Soome * addr .. server, net order. 3364a5d661aSToomas Soome * prog .. host order. 3374a5d661aSToomas Soome * vers .. host order. 3384a5d661aSToomas Soome * port .. host order. 3394a5d661aSToomas Soome */ 3404a5d661aSToomas Soome void 3414a5d661aSToomas Soome rpc_pmap_putcache(struct in_addr addr, u_int prog, u_int vers, int port) 3424a5d661aSToomas Soome { 3434a5d661aSToomas Soome struct pmap_list *pl; 3444a5d661aSToomas Soome 3454a5d661aSToomas Soome /* Don't overflow cache... */ 3464a5d661aSToomas Soome if (rpc_pmap_num >= PMAP_NUM) { 3474a5d661aSToomas Soome /* ... just re-use the last entry. */ 3484a5d661aSToomas Soome rpc_pmap_num = PMAP_NUM - 1; 3494a5d661aSToomas Soome #ifdef RPC_DEBUG 3504a5d661aSToomas Soome printf("rpc_pmap_putcache: cache overflow\n"); 3514a5d661aSToomas Soome #endif 3524a5d661aSToomas Soome } 3534a5d661aSToomas Soome 3544a5d661aSToomas Soome pl = &rpc_pmap_list[rpc_pmap_num]; 3554a5d661aSToomas Soome rpc_pmap_num++; 3564a5d661aSToomas Soome 3574a5d661aSToomas Soome /* Cache answer */ 3584a5d661aSToomas Soome pl->addr = addr; 3594a5d661aSToomas Soome pl->prog = prog; 3604a5d661aSToomas Soome pl->vers = vers; 3614a5d661aSToomas Soome pl->port = port; 3624a5d661aSToomas Soome } 3634a5d661aSToomas Soome 3644a5d661aSToomas Soome 3654a5d661aSToomas Soome /* 3664a5d661aSToomas Soome * Request a port number from the port mapper. 3674a5d661aSToomas Soome * Returns the port in host order. 3684a5d661aSToomas Soome * prog and vers are host order. 3694a5d661aSToomas Soome */ 3704a5d661aSToomas Soome int 3714a5d661aSToomas Soome rpc_getport(struct iodesc *d, n_long prog, n_long vers) 3724a5d661aSToomas Soome { 3734a5d661aSToomas Soome struct args { 3744a5d661aSToomas Soome n_long prog; /* call program */ 3754a5d661aSToomas Soome n_long vers; /* call version */ 3764a5d661aSToomas Soome n_long proto; /* call protocol */ 3774a5d661aSToomas Soome n_long port; /* call port (unused) */ 3784a5d661aSToomas Soome } *args; 3794a5d661aSToomas Soome struct res { 3804a5d661aSToomas Soome n_long port; 3814a5d661aSToomas Soome } *res; 3824a5d661aSToomas Soome struct { 3834a5d661aSToomas Soome n_long h[RPC_HEADER_WORDS]; 3844a5d661aSToomas Soome struct args d; 3854a5d661aSToomas Soome } sdata; 386*7b2a1233SToomas Soome void *pkt; 3874a5d661aSToomas Soome ssize_t cc; 3884a5d661aSToomas Soome int port; 3894a5d661aSToomas Soome 3904a5d661aSToomas Soome #ifdef RPC_DEBUG 3914a5d661aSToomas Soome if (debug) 3924a5d661aSToomas Soome printf("%s: prog=0x%x vers=%d\n", __func__, prog, vers); 3934a5d661aSToomas Soome #endif 3944a5d661aSToomas Soome 3954a5d661aSToomas Soome /* This one is fixed forever. */ 3964a5d661aSToomas Soome if (prog == PMAPPROG) { 3974a5d661aSToomas Soome port = PMAPPORT; 3984a5d661aSToomas Soome goto out; 3994a5d661aSToomas Soome } 4004a5d661aSToomas Soome 4014a5d661aSToomas Soome /* Try for cached answer first */ 4024a5d661aSToomas Soome port = rpc_pmap_getcache(d->destip, prog, vers); 4034a5d661aSToomas Soome if (port != -1) 4044a5d661aSToomas Soome goto out; 4054a5d661aSToomas Soome 4064a5d661aSToomas Soome args = &sdata.d; 4074a5d661aSToomas Soome args->prog = htonl(prog); 4084a5d661aSToomas Soome args->vers = htonl(vers); 4094a5d661aSToomas Soome args->proto = htonl(IPPROTO_UDP); 4104a5d661aSToomas Soome args->port = 0; 411*7b2a1233SToomas Soome pkt = NULL; 4124a5d661aSToomas Soome 4134a5d661aSToomas Soome cc = rpc_call(d, PMAPPROG, PMAPVERS, PMAPPROC_GETPORT, 414*7b2a1233SToomas Soome args, sizeof(*args), (void **)&res, &pkt); 4154a5d661aSToomas Soome if (cc < sizeof(*res)) { 4164a5d661aSToomas Soome printf("getport: %s", strerror(errno)); 4174a5d661aSToomas Soome errno = EBADRPC; 418*7b2a1233SToomas Soome free(pkt); 4194a5d661aSToomas Soome return (-1); 4204a5d661aSToomas Soome } 4214a5d661aSToomas Soome port = (int)ntohl(res->port); 422*7b2a1233SToomas Soome free(pkt); 4234a5d661aSToomas Soome 4244a5d661aSToomas Soome rpc_pmap_putcache(d->destip, prog, vers, port); 4254a5d661aSToomas Soome 4264a5d661aSToomas Soome out: 4274a5d661aSToomas Soome #ifdef RPC_DEBUG 4284a5d661aSToomas Soome if (debug) 4294a5d661aSToomas Soome printf("%s: port=%u\n", __func__, port); 4304a5d661aSToomas Soome #endif 4314a5d661aSToomas Soome return (port); 4324a5d661aSToomas Soome } 433