xref: /titanic_44/usr/src/lib/libnsl/rpc/pmap_clnt.c (revision 09f67678c27dda8a89f87f1f408a87dd49ceb0e1)
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