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 23 /* 24 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 25 * Use is subject to license terms. 26 */ 27 28 /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */ 29 /* All Rights Reserved */ 30 /* 31 * Portions of this source code were derived from Berkeley 32 * 4.3 BSD under license from the Regents of the University of 33 * California. 34 */ 35 36 #pragma ident "%Z%%M% %I% %E% SMI" 37 38 #ifdef PORTMAP 39 /* 40 * interface to pmap rpc service. 41 */ 42 43 #include "mt.h" 44 #include "rpc_mt.h" 45 #include <rpc/rpc.h> 46 #include <rpc/nettype.h> 47 #include <netdir.h> 48 #include <rpc/pmap_prot.h> 49 #include <rpc/pmap_clnt.h> 50 #include <rpc/pmap_rmt.h> 51 #include <syslog.h> 52 #include <netinet/in.h> 53 #include <sys/socket.h> 54 55 static const struct timeval timeout = { 5, 0 }; 56 static const struct timeval tottimeout = { 60, 0 }; 57 static const struct timeval rmttimeout = { 3, 0 }; 58 59 /* 60 * Set a mapping between program, version and port. 61 * Calls the pmap service remotely to do the mapping. 62 */ 63 bool_t 64 pmap_set(rpcprog_t program, rpcvers_t version, rpcprot_t protocol, 65 ushort_t port) 66 { 67 bool_t rslt; 68 struct netbuf *na; 69 struct netconfig *nconf; 70 char buf[32]; 71 72 if ((protocol != IPPROTO_UDP) && (protocol != IPPROTO_TCP)) 73 return (FALSE); 74 nconf = __rpc_getconfip(protocol == IPPROTO_UDP ? "udp" : "tcp"); 75 if (!nconf) 76 return (FALSE); 77 (void) sprintf(buf, "0.0.0.0.%d.%d", port >> 8 & 0xff, port & 0xff); 78 na = uaddr2taddr(nconf, buf); 79 if (!na) { 80 freenetconfigent(nconf); 81 return (FALSE); 82 } 83 rslt = rpcb_set(program, version, nconf, na); 84 netdir_free((char *)na, ND_ADDR); 85 freenetconfigent(nconf); 86 return (rslt); 87 } 88 89 /* 90 * Remove the mapping between program, version and port. 91 * Calls the pmap service remotely to do the un-mapping. 92 */ 93 bool_t 94 pmap_unset(rpcprog_t program, rpcvers_t version) 95 { 96 struct netconfig *nconf; 97 bool_t udp_rslt = FALSE; 98 bool_t tcp_rslt = FALSE; 99 100 nconf = __rpc_getconfip("udp"); 101 if (nconf) { 102 udp_rslt = rpcb_unset(program, version, nconf); 103 freenetconfigent(nconf); 104 } 105 nconf = __rpc_getconfip("tcp"); 106 if (nconf) { 107 tcp_rslt = rpcb_unset(program, version, nconf); 108 freenetconfigent(nconf); 109 } 110 /* 111 * XXX: The call may still succeed even if only one of the 112 * calls succeeded. This was the best that could be 113 * done for backward compatibility. 114 */ 115 return (tcp_rslt || udp_rslt); 116 } 117 118 /* 119 * Find the mapped port for program, version. 120 * Calls the pmap service remotely to do the lookup. 121 * Returns 0 if no map exists. 122 * 123 * XXX: It talks only to the portmapper and not to the rpcbind 124 * service. There may be implementations out there which do not 125 * run portmapper as a part of rpcbind. 126 */ 127 ushort_t 128 pmap_getport(struct sockaddr_in *address, rpcprog_t program, 129 rpcvers_t version, rpcprot_t protocol) 130 { 131 ushort_t port = 0; 132 int fd = RPC_ANYFD; 133 CLIENT *client; 134 struct pmap parms; 135 136 address->sin_port = htons(PMAPPORT); 137 client = clntudp_bufcreate(address, PMAPPROG, PMAPVERS, timeout, 138 &fd, RPCSMALLMSGSIZE, RPCSMALLMSGSIZE); 139 if (client != NULL) { 140 parms.pm_prog = program; 141 parms.pm_vers = version; 142 parms.pm_prot = protocol; 143 parms.pm_port = 0; /* not needed or used */ 144 if (CLNT_CALL(client, PMAPPROC_GETPORT, (xdrproc_t)xdr_pmap, 145 (caddr_t)&parms, (xdrproc_t)xdr_u_short, 146 (caddr_t)&port, tottimeout) != RPC_SUCCESS) { 147 rpc_createerr.cf_stat = RPC_PMAPFAILURE; 148 clnt_geterr(client, &rpc_createerr.cf_error); 149 } else if (port == 0) { 150 rpc_createerr.cf_stat = RPC_PROGNOTREGISTERED; 151 } 152 CLNT_DESTROY(client); 153 } 154 address->sin_port = 0; 155 return (port); 156 } 157 158 /* 159 * Get a copy of the current port maps. 160 * Calls the pmap service remotely to do get the maps. 161 */ 162 struct pmaplist * 163 pmap_getmaps(struct sockaddr_in *address) 164 { 165 pmaplist_ptr head = NULL; 166 int fd = RPC_ANYFD; 167 struct timeval minutetimeout; 168 CLIENT *client; 169 170 minutetimeout.tv_sec = 60; 171 minutetimeout.tv_usec = 0; 172 address->sin_port = htons(PMAPPORT); 173 client = clnttcp_create(address, PMAPPROG, PMAPVERS, &fd, 50, 500); 174 if (client != NULL) { 175 if (CLNT_CALL(client, PMAPPROC_DUMP, (xdrproc_t)xdr_void, 176 NULL, (xdrproc_t)xdr_pmaplist_ptr, 177 (caddr_t)&head, minutetimeout) != RPC_SUCCESS) { 178 (void) syslog(LOG_ERR, "%s", 179 clnt_sperror(client, "pmap_getmaps rpc problem")); 180 } 181 CLNT_DESTROY(client); 182 } 183 address->sin_port = 0; 184 return ((struct pmaplist *)head); 185 } 186 187 /* 188 * pmapper remote-call-service interface. 189 * This routine is used to call the pmapper remote call service 190 * which will look up a service program in the port maps, and then 191 * remotely call that routine with the given parameters. This allows 192 * programs to do a lookup and call in one step. 193 */ 194 enum clnt_stat 195 pmap_rmtcall(struct sockaddr_in *addr, rpcprog_t prog, rpcvers_t vers, 196 rpcproc_t proc, xdrproc_t xdrargs, caddr_t argsp, xdrproc_t xdrres, 197 caddr_t resp, struct timeval tout, rpcport_t *port_ptr) 198 { 199 int fd = RPC_ANYFD; 200 CLIENT *client; 201 struct p_rmtcallargs a; 202 struct p_rmtcallres r; 203 enum clnt_stat stat; 204 short tmp = addr->sin_port; 205 206 addr->sin_port = htons(PMAPPORT); 207 client = clntudp_create(addr, PMAPPROG, PMAPVERS, rmttimeout, &fd); 208 if (client != NULL) { 209 a.prog = prog; 210 a.vers = vers; 211 a.proc = proc; 212 a.args.args_val = argsp; 213 a.xdr_args = xdrargs; 214 r.res.res_val = resp; 215 r.xdr_res = xdrres; 216 stat = CLNT_CALL(client, PMAPPROC_CALLIT, 217 (xdrproc_t)xdr_rmtcallargs, 218 (caddr_t)&a, (xdrproc_t)xdr_rmtcallres, 219 (caddr_t)&r, tout); 220 CLNT_DESTROY(client); 221 } else { 222 stat = RPC_FAILED; 223 } 224 addr->sin_port = tmp; 225 *port_ptr = r.port; 226 return (stat); 227 } 228 #endif /* PORTMAP */ 229