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