1*0Sstevel@tonic-gate /* 2*0Sstevel@tonic-gate * CDDL HEADER START 3*0Sstevel@tonic-gate * 4*0Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*0Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*0Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*0Sstevel@tonic-gate * with the License. 8*0Sstevel@tonic-gate * 9*0Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*0Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*0Sstevel@tonic-gate * See the License for the specific language governing permissions 12*0Sstevel@tonic-gate * and limitations under the License. 13*0Sstevel@tonic-gate * 14*0Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*0Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*0Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*0Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*0Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*0Sstevel@tonic-gate * 20*0Sstevel@tonic-gate * CDDL HEADER END 21*0Sstevel@tonic-gate * 22*0Sstevel@tonic-gate * Copyright 1999 Sun Microsystems, Inc. All rights reserved. 23*0Sstevel@tonic-gate * Use is subject to license terms. 24*0Sstevel@tonic-gate */ 25*0Sstevel@tonic-gate /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */ 26*0Sstevel@tonic-gate /* All Rights Reserved */ 27*0Sstevel@tonic-gate /* 28*0Sstevel@tonic-gate * Portions of this source code were derived from Berkeley 29*0Sstevel@tonic-gate * 4.3 BSD under license from the Regents of the University of 30*0Sstevel@tonic-gate * California. 31*0Sstevel@tonic-gate */ 32*0Sstevel@tonic-gate 33*0Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 34*0Sstevel@tonic-gate 35*0Sstevel@tonic-gate #ifdef PORTMAP 36*0Sstevel@tonic-gate /* 37*0Sstevel@tonic-gate * pmap_clnt.c 38*0Sstevel@tonic-gate * interface to pmap rpc service. 39*0Sstevel@tonic-gate * 40*0Sstevel@tonic-gate */ 41*0Sstevel@tonic-gate 42*0Sstevel@tonic-gate #include "rpc_mt.h" 43*0Sstevel@tonic-gate #include <rpc/rpc.h> 44*0Sstevel@tonic-gate #include <rpc/nettype.h> 45*0Sstevel@tonic-gate #include <rpc/trace.h> 46*0Sstevel@tonic-gate #include <netdir.h> 47*0Sstevel@tonic-gate #include <rpc/pmap_prot.h> 48*0Sstevel@tonic-gate #include <rpc/pmap_clnt.h> 49*0Sstevel@tonic-gate #include <rpc/pmap_rmt.h> 50*0Sstevel@tonic-gate #include <syslog.h> 51*0Sstevel@tonic-gate #include <netinet/in.h> 52*0Sstevel@tonic-gate #include <sys/socket.h> 53*0Sstevel@tonic-gate 54*0Sstevel@tonic-gate static const struct timeval timeout = { 5, 0 }; 55*0Sstevel@tonic-gate static const struct timeval tottimeout = { 60, 0 }; 56*0Sstevel@tonic-gate static const struct timeval rmttimeout = { 3, 0 }; 57*0Sstevel@tonic-gate 58*0Sstevel@tonic-gate /* 59*0Sstevel@tonic-gate * Set a mapping between program, version and port. 60*0Sstevel@tonic-gate * Calls the pmap service remotely to do the mapping. 61*0Sstevel@tonic-gate */ 62*0Sstevel@tonic-gate bool_t 63*0Sstevel@tonic-gate #ifdef __STDC__ 64*0Sstevel@tonic-gate pmap_set(rpcprog_t program, rpcvers_t version, rpcprot_t protocol, u_short port) 65*0Sstevel@tonic-gate #else 66*0Sstevel@tonic-gate pmap_set(program, version, protocol, port) 67*0Sstevel@tonic-gate rpcprog_t program; 68*0Sstevel@tonic-gate rpcvers_t version; 69*0Sstevel@tonic-gate rpcprot_t protocol; 70*0Sstevel@tonic-gate u_short port; 71*0Sstevel@tonic-gate #endif 72*0Sstevel@tonic-gate { 73*0Sstevel@tonic-gate bool_t rslt; 74*0Sstevel@tonic-gate struct netbuf *na; 75*0Sstevel@tonic-gate struct netconfig *nconf; 76*0Sstevel@tonic-gate char buf[32]; 77*0Sstevel@tonic-gate 78*0Sstevel@tonic-gate trace1(TR_pmap_set, 0); 79*0Sstevel@tonic-gate if ((protocol != IPPROTO_UDP) && (protocol != IPPROTO_TCP)) { 80*0Sstevel@tonic-gate trace1(TR_pmap_set, 1); 81*0Sstevel@tonic-gate return (FALSE); 82*0Sstevel@tonic-gate } 83*0Sstevel@tonic-gate nconf = __rpc_getconfip(protocol == IPPROTO_UDP ? "udp" : "tcp"); 84*0Sstevel@tonic-gate if (! nconf) { 85*0Sstevel@tonic-gate trace1(TR_pmap_set, 1); 86*0Sstevel@tonic-gate return (FALSE); 87*0Sstevel@tonic-gate } 88*0Sstevel@tonic-gate sprintf(buf, "0.0.0.0.%d.%d", port >> 8 & 0xff, port & 0xff); 89*0Sstevel@tonic-gate na = uaddr2taddr(nconf, buf); 90*0Sstevel@tonic-gate if (! na) { 91*0Sstevel@tonic-gate freenetconfigent(nconf); 92*0Sstevel@tonic-gate trace1(TR_pmap_set, 1); 93*0Sstevel@tonic-gate return (FALSE); 94*0Sstevel@tonic-gate } 95*0Sstevel@tonic-gate rslt = rpcb_set(program, version, nconf, na); 96*0Sstevel@tonic-gate netdir_free((char *)na, ND_ADDR); 97*0Sstevel@tonic-gate freenetconfigent(nconf); 98*0Sstevel@tonic-gate trace1(TR_pmap_set, 1); 99*0Sstevel@tonic-gate return (rslt); 100*0Sstevel@tonic-gate } 101*0Sstevel@tonic-gate 102*0Sstevel@tonic-gate /* 103*0Sstevel@tonic-gate * Remove the mapping between program, version and port. 104*0Sstevel@tonic-gate * Calls the pmap service remotely to do the un-mapping. 105*0Sstevel@tonic-gate */ 106*0Sstevel@tonic-gate bool_t 107*0Sstevel@tonic-gate pmap_unset(program, version) 108*0Sstevel@tonic-gate rpcprog_t program; 109*0Sstevel@tonic-gate rpcvers_t version; 110*0Sstevel@tonic-gate { 111*0Sstevel@tonic-gate struct netconfig *nconf; 112*0Sstevel@tonic-gate bool_t udp_rslt = FALSE; 113*0Sstevel@tonic-gate bool_t tcp_rslt = FALSE; 114*0Sstevel@tonic-gate 115*0Sstevel@tonic-gate trace1(TR_pmap_unset, 0); 116*0Sstevel@tonic-gate nconf = __rpc_getconfip("udp"); 117*0Sstevel@tonic-gate if (nconf) { 118*0Sstevel@tonic-gate udp_rslt = rpcb_unset(program, version, nconf); 119*0Sstevel@tonic-gate freenetconfigent(nconf); 120*0Sstevel@tonic-gate } 121*0Sstevel@tonic-gate nconf = __rpc_getconfip("tcp"); 122*0Sstevel@tonic-gate if (nconf) { 123*0Sstevel@tonic-gate tcp_rslt = rpcb_unset(program, version, nconf); 124*0Sstevel@tonic-gate freenetconfigent(nconf); 125*0Sstevel@tonic-gate } 126*0Sstevel@tonic-gate /* 127*0Sstevel@tonic-gate * XXX: The call may still succeed even if only one of the 128*0Sstevel@tonic-gate * calls succeeded. This was the best that could be 129*0Sstevel@tonic-gate * done for backward compatibility. 130*0Sstevel@tonic-gate */ 131*0Sstevel@tonic-gate trace1(TR_pmap_unset, 1); 132*0Sstevel@tonic-gate return (tcp_rslt || udp_rslt); 133*0Sstevel@tonic-gate } 134*0Sstevel@tonic-gate 135*0Sstevel@tonic-gate /* 136*0Sstevel@tonic-gate * Find the mapped port for program, version. 137*0Sstevel@tonic-gate * Calls the pmap service remotely to do the lookup. 138*0Sstevel@tonic-gate * Returns 0 if no map exists. 139*0Sstevel@tonic-gate * 140*0Sstevel@tonic-gate * XXX: It talks only to the portmapper and not to the rpcbind 141*0Sstevel@tonic-gate * service. There may be implementations out there which do not 142*0Sstevel@tonic-gate * run portmapper as a part of rpcbind. 143*0Sstevel@tonic-gate */ 144*0Sstevel@tonic-gate u_short 145*0Sstevel@tonic-gate pmap_getport(address, program, version, protocol) 146*0Sstevel@tonic-gate struct sockaddr_in *address; 147*0Sstevel@tonic-gate rpcprog_t program; 148*0Sstevel@tonic-gate rpcvers_t version; 149*0Sstevel@tonic-gate rpcprot_t protocol; 150*0Sstevel@tonic-gate { 151*0Sstevel@tonic-gate u_short port = 0; 152*0Sstevel@tonic-gate int fd = RPC_ANYFD; 153*0Sstevel@tonic-gate register CLIENT *client; 154*0Sstevel@tonic-gate struct pmap parms; 155*0Sstevel@tonic-gate 156*0Sstevel@tonic-gate trace1(TR_pmap_getport, 0); 157*0Sstevel@tonic-gate address->sin_port = htons(PMAPPORT); 158*0Sstevel@tonic-gate client = clntudp_bufcreate(address, PMAPPROG, PMAPVERS, timeout, 159*0Sstevel@tonic-gate &fd, RPCSMALLMSGSIZE, RPCSMALLMSGSIZE); 160*0Sstevel@tonic-gate if (client != (CLIENT *)NULL) { 161*0Sstevel@tonic-gate parms.pm_prog = program; 162*0Sstevel@tonic-gate parms.pm_vers = version; 163*0Sstevel@tonic-gate parms.pm_prot = protocol; 164*0Sstevel@tonic-gate parms.pm_port = 0; /* not needed or used */ 165*0Sstevel@tonic-gate if (CLNT_CALL(client, PMAPPROC_GETPORT, (xdrproc_t) xdr_pmap, 166*0Sstevel@tonic-gate (caddr_t) &parms, (xdrproc_t) xdr_u_short, 167*0Sstevel@tonic-gate (caddr_t) &port, tottimeout) != RPC_SUCCESS) { 168*0Sstevel@tonic-gate rpc_createerr.cf_stat = RPC_PMAPFAILURE; 169*0Sstevel@tonic-gate clnt_geterr(client, &rpc_createerr.cf_error); 170*0Sstevel@tonic-gate } else if (port == 0) { 171*0Sstevel@tonic-gate rpc_createerr.cf_stat = RPC_PROGNOTREGISTERED; 172*0Sstevel@tonic-gate } 173*0Sstevel@tonic-gate CLNT_DESTROY(client); 174*0Sstevel@tonic-gate } 175*0Sstevel@tonic-gate address->sin_port = 0; 176*0Sstevel@tonic-gate trace1(TR_pmap_getport, 1); 177*0Sstevel@tonic-gate return (port); 178*0Sstevel@tonic-gate } 179*0Sstevel@tonic-gate 180*0Sstevel@tonic-gate /* 181*0Sstevel@tonic-gate * Get a copy of the current port maps. 182*0Sstevel@tonic-gate * Calls the pmap service remotely to do get the maps. 183*0Sstevel@tonic-gate */ 184*0Sstevel@tonic-gate struct pmaplist * 185*0Sstevel@tonic-gate pmap_getmaps(address) 186*0Sstevel@tonic-gate struct sockaddr_in *address; 187*0Sstevel@tonic-gate { 188*0Sstevel@tonic-gate pmaplist_ptr head = (pmaplist_ptr)NULL; 189*0Sstevel@tonic-gate int fd = RPC_ANYFD; 190*0Sstevel@tonic-gate struct timeval minutetimeout; 191*0Sstevel@tonic-gate register CLIENT *client; 192*0Sstevel@tonic-gate 193*0Sstevel@tonic-gate trace1(TR_pmap_getmaps, 0); 194*0Sstevel@tonic-gate minutetimeout.tv_sec = 60; 195*0Sstevel@tonic-gate minutetimeout.tv_usec = 0; 196*0Sstevel@tonic-gate address->sin_port = htons(PMAPPORT); 197*0Sstevel@tonic-gate client = clnttcp_create(address, PMAPPROG, PMAPVERS, &fd, 50, 500); 198*0Sstevel@tonic-gate if (client != (CLIENT *)NULL) { 199*0Sstevel@tonic-gate if (CLNT_CALL(client, PMAPPROC_DUMP, (xdrproc_t) xdr_void, 200*0Sstevel@tonic-gate (caddr_t) NULL, (xdrproc_t) xdr_pmaplist_ptr, 201*0Sstevel@tonic-gate (caddr_t) &head, minutetimeout) != RPC_SUCCESS) { 202*0Sstevel@tonic-gate (void) syslog(LOG_ERR, 203*0Sstevel@tonic-gate clnt_sperror(client, "pmap_getmaps rpc problem")); 204*0Sstevel@tonic-gate } 205*0Sstevel@tonic-gate CLNT_DESTROY(client); 206*0Sstevel@tonic-gate } 207*0Sstevel@tonic-gate address->sin_port = 0; 208*0Sstevel@tonic-gate trace1(TR_pmap_getmaps, 1); 209*0Sstevel@tonic-gate return ((struct pmaplist *)head); 210*0Sstevel@tonic-gate } 211*0Sstevel@tonic-gate 212*0Sstevel@tonic-gate /* 213*0Sstevel@tonic-gate * pmapper remote-call-service interface. 214*0Sstevel@tonic-gate * This routine is used to call the pmapper remote call service 215*0Sstevel@tonic-gate * which will look up a service program in the port maps, and then 216*0Sstevel@tonic-gate * remotely call that routine with the given parameters. This allows 217*0Sstevel@tonic-gate * programs to do a lookup and call in one step. 218*0Sstevel@tonic-gate */ 219*0Sstevel@tonic-gate enum clnt_stat 220*0Sstevel@tonic-gate pmap_rmtcall(addr, prog, vers, proc, xdrargs, argsp, xdrres, resp, 221*0Sstevel@tonic-gate tout, port_ptr) 222*0Sstevel@tonic-gate struct sockaddr_in *addr; 223*0Sstevel@tonic-gate rpcprog_t prog; 224*0Sstevel@tonic-gate rpcvers_t vers; 225*0Sstevel@tonic-gate rpcproc_t proc; 226*0Sstevel@tonic-gate xdrproc_t xdrargs, xdrres; 227*0Sstevel@tonic-gate caddr_t argsp, resp; 228*0Sstevel@tonic-gate struct timeval tout; 229*0Sstevel@tonic-gate rpcport_t *port_ptr; 230*0Sstevel@tonic-gate { 231*0Sstevel@tonic-gate int fd = RPC_ANYFD; 232*0Sstevel@tonic-gate register CLIENT *client; 233*0Sstevel@tonic-gate struct p_rmtcallargs a; 234*0Sstevel@tonic-gate struct p_rmtcallres r; 235*0Sstevel@tonic-gate enum clnt_stat stat; 236*0Sstevel@tonic-gate short tmp = addr->sin_port; 237*0Sstevel@tonic-gate 238*0Sstevel@tonic-gate trace1(TR_pmap_rmtcall, 0); 239*0Sstevel@tonic-gate addr->sin_port = htons(PMAPPORT); 240*0Sstevel@tonic-gate client = clntudp_create(addr, PMAPPROG, PMAPVERS, rmttimeout, &fd); 241*0Sstevel@tonic-gate if (client != (CLIENT *)NULL) { 242*0Sstevel@tonic-gate a.prog = prog; 243*0Sstevel@tonic-gate a.vers = vers; 244*0Sstevel@tonic-gate a.proc = proc; 245*0Sstevel@tonic-gate a.args.args_val = argsp; 246*0Sstevel@tonic-gate a.xdr_args = xdrargs; 247*0Sstevel@tonic-gate r.res.res_val = resp; 248*0Sstevel@tonic-gate r.xdr_res = xdrres; 249*0Sstevel@tonic-gate stat = CLNT_CALL(client, PMAPPROC_CALLIT, 250*0Sstevel@tonic-gate (xdrproc_t)xdr_rmtcallargs, 251*0Sstevel@tonic-gate (caddr_t) &a, (xdrproc_t) xdr_rmtcallres, 252*0Sstevel@tonic-gate (caddr_t) &r, tout); 253*0Sstevel@tonic-gate CLNT_DESTROY(client); 254*0Sstevel@tonic-gate } else { 255*0Sstevel@tonic-gate stat = RPC_FAILED; 256*0Sstevel@tonic-gate } 257*0Sstevel@tonic-gate addr->sin_port = tmp; 258*0Sstevel@tonic-gate *port_ptr = r.port; 259*0Sstevel@tonic-gate trace1(TR_pmap_rmtcall, 1); 260*0Sstevel@tonic-gate return (stat); 261*0Sstevel@tonic-gate } 262*0Sstevel@tonic-gate #endif /* PORTMAP */ 263