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