xref: /onnv-gate/usr/src/lib/libnsl/rpc/pmap_clnt.c (revision 12648:61bf50c7467b)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
52712Snn35248  * Common Development and Distribution License (the "License").
62712Snn35248  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
20132Srobinson  */
21132Srobinson 
22132Srobinson /*
23*12648SSurya.Prakki@Sun.COM  * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved.
240Sstevel@tonic-gate  */
251219Sraf 
260Sstevel@tonic-gate /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
270Sstevel@tonic-gate /* All Rights Reserved */
280Sstevel@tonic-gate /*
290Sstevel@tonic-gate  * Portions of this source code were derived from Berkeley
300Sstevel@tonic-gate  * 4.3 BSD under license from the Regents of the University of
310Sstevel@tonic-gate  * California.
320Sstevel@tonic-gate  */
330Sstevel@tonic-gate 
340Sstevel@tonic-gate #ifdef PORTMAP
352712Snn35248 
360Sstevel@tonic-gate /*
370Sstevel@tonic-gate  * interface to pmap rpc service.
380Sstevel@tonic-gate  */
391219Sraf #include "mt.h"
400Sstevel@tonic-gate #include "rpc_mt.h"
410Sstevel@tonic-gate #include <rpc/rpc.h>
420Sstevel@tonic-gate #include <rpc/nettype.h>
430Sstevel@tonic-gate #include <netdir.h>
440Sstevel@tonic-gate #include <rpc/pmap_prot.h>
450Sstevel@tonic-gate #include <rpc/pmap_clnt.h>
460Sstevel@tonic-gate #include <rpc/pmap_rmt.h>
472712Snn35248 #include <string.h>
480Sstevel@tonic-gate #include <syslog.h>
490Sstevel@tonic-gate #include <netinet/in.h>
500Sstevel@tonic-gate #include <sys/socket.h>
512712Snn35248 #include <unistd.h>
520Sstevel@tonic-gate 
532712Snn35248 int use_portmapper = 0;
540Sstevel@tonic-gate static const struct timeval timeout = { 5, 0 };
550Sstevel@tonic-gate static const struct timeval tottimeout = { 60, 0 };
560Sstevel@tonic-gate static const struct timeval rmttimeout = { 3, 0 };
570Sstevel@tonic-gate 
580Sstevel@tonic-gate /*
590Sstevel@tonic-gate  * Set a mapping between program, version and port.
600Sstevel@tonic-gate  * Calls the pmap service remotely to do the mapping.
610Sstevel@tonic-gate  */
620Sstevel@tonic-gate bool_t
pmap_set(rpcprog_t program,rpcvers_t version,rpcprot_t protocol,ushort_t port)63132Srobinson pmap_set(rpcprog_t program, rpcvers_t version, rpcprot_t protocol,
64132Srobinson 								ushort_t port)
650Sstevel@tonic-gate {
660Sstevel@tonic-gate 	bool_t rslt;
670Sstevel@tonic-gate 	struct netbuf *na;
680Sstevel@tonic-gate 	struct netconfig *nconf;
690Sstevel@tonic-gate 	char buf[32];
700Sstevel@tonic-gate 
71132Srobinson 	if ((protocol != IPPROTO_UDP) && (protocol != IPPROTO_TCP))
720Sstevel@tonic-gate 		return (FALSE);
730Sstevel@tonic-gate 	nconf = __rpc_getconfip(protocol == IPPROTO_UDP ? "udp" : "tcp");
74132Srobinson 	if (!nconf)
750Sstevel@tonic-gate 		return (FALSE);
76132Srobinson 	(void) sprintf(buf, "0.0.0.0.%d.%d", port >> 8 & 0xff, port & 0xff);
770Sstevel@tonic-gate 	na = uaddr2taddr(nconf, buf);
78132Srobinson 	if (!na) {
790Sstevel@tonic-gate 		freenetconfigent(nconf);
800Sstevel@tonic-gate 		return (FALSE);
810Sstevel@tonic-gate 	}
82*12648SSurya.Prakki@Sun.COM 	rslt = rpcb_set(program, version, nconf, na);
83*12648SSurya.Prakki@Sun.COM 
840Sstevel@tonic-gate 	netdir_free((char *)na, ND_ADDR);
850Sstevel@tonic-gate 	freenetconfigent(nconf);
860Sstevel@tonic-gate 	return (rslt);
870Sstevel@tonic-gate }
880Sstevel@tonic-gate 
890Sstevel@tonic-gate /*
900Sstevel@tonic-gate  * Remove the mapping between program, version and port.
910Sstevel@tonic-gate  * Calls the pmap service remotely to do the un-mapping.
920Sstevel@tonic-gate  */
930Sstevel@tonic-gate bool_t
pmap_unset(rpcprog_t program,rpcvers_t version)94132Srobinson pmap_unset(rpcprog_t program, rpcvers_t version)
950Sstevel@tonic-gate {
960Sstevel@tonic-gate 	struct netconfig *nconf;
970Sstevel@tonic-gate 	bool_t udp_rslt = FALSE;
980Sstevel@tonic-gate 	bool_t tcp_rslt = FALSE;
990Sstevel@tonic-gate 
1000Sstevel@tonic-gate 	nconf = __rpc_getconfip("udp");
1010Sstevel@tonic-gate 	if (nconf) {
1020Sstevel@tonic-gate 		udp_rslt = rpcb_unset(program, version, nconf);
1030Sstevel@tonic-gate 		freenetconfigent(nconf);
1040Sstevel@tonic-gate 	}
1050Sstevel@tonic-gate 	nconf = __rpc_getconfip("tcp");
1060Sstevel@tonic-gate 	if (nconf) {
1070Sstevel@tonic-gate 		tcp_rslt = rpcb_unset(program, version, nconf);
1080Sstevel@tonic-gate 		freenetconfigent(nconf);
1090Sstevel@tonic-gate 	}
1100Sstevel@tonic-gate 	/*
1110Sstevel@tonic-gate 	 * XXX: The call may still succeed even if only one of the
1120Sstevel@tonic-gate 	 * calls succeeded.  This was the best that could be
1130Sstevel@tonic-gate 	 * done for backward compatibility.
1140Sstevel@tonic-gate 	 */
1150Sstevel@tonic-gate 	return (tcp_rslt || udp_rslt);
1160Sstevel@tonic-gate }
1170Sstevel@tonic-gate 
1180Sstevel@tonic-gate /*
1190Sstevel@tonic-gate  * Find the mapped port for program, version.
1200Sstevel@tonic-gate  * Calls the pmap service remotely to do the lookup.
1210Sstevel@tonic-gate  * Returns 0 if no map exists.
1220Sstevel@tonic-gate  *
1230Sstevel@tonic-gate  * XXX: It talks only to the portmapper and not to the rpcbind
1240Sstevel@tonic-gate  * service.  There may be implementations out there which do not
1250Sstevel@tonic-gate  * run portmapper as a part of rpcbind.
1260Sstevel@tonic-gate  */
127132Srobinson ushort_t
pmap_getport(struct sockaddr_in * address,rpcprog_t program,rpcvers_t version,rpcprot_t protocol)128132Srobinson pmap_getport(struct sockaddr_in *address, rpcprog_t program,
129132Srobinson 					rpcvers_t version, rpcprot_t protocol)
1300Sstevel@tonic-gate {
131132Srobinson 	ushort_t port = 0;
1320Sstevel@tonic-gate 	int fd = RPC_ANYFD;
133132Srobinson 	CLIENT *client;
1340Sstevel@tonic-gate 	struct pmap parms;
1350Sstevel@tonic-gate 
1360Sstevel@tonic-gate 	address->sin_port = htons(PMAPPORT);
1370Sstevel@tonic-gate 	client = clntudp_bufcreate(address, PMAPPROG, PMAPVERS, timeout,
1380Sstevel@tonic-gate 				&fd, RPCSMALLMSGSIZE, RPCSMALLMSGSIZE);
139132Srobinson 	if (client != NULL) {
1400Sstevel@tonic-gate 		parms.pm_prog = program;
1410Sstevel@tonic-gate 		parms.pm_vers = version;
1420Sstevel@tonic-gate 		parms.pm_prot = protocol;
1430Sstevel@tonic-gate 		parms.pm_port = 0;	/* not needed or used */
144132Srobinson 		if (CLNT_CALL(client, PMAPPROC_GETPORT, (xdrproc_t)xdr_pmap,
145132Srobinson 			    (caddr_t)&parms, (xdrproc_t)xdr_u_short,
146132Srobinson 			    (caddr_t)&port, tottimeout) != RPC_SUCCESS) {
1470Sstevel@tonic-gate 			rpc_createerr.cf_stat = RPC_PMAPFAILURE;
1480Sstevel@tonic-gate 			clnt_geterr(client, &rpc_createerr.cf_error);
1490Sstevel@tonic-gate 		} else if (port == 0) {
1500Sstevel@tonic-gate 			rpc_createerr.cf_stat = RPC_PROGNOTREGISTERED;
1510Sstevel@tonic-gate 		}
1520Sstevel@tonic-gate 		CLNT_DESTROY(client);
1530Sstevel@tonic-gate 	}
1540Sstevel@tonic-gate 	address->sin_port = 0;
1550Sstevel@tonic-gate 	return (port);
1560Sstevel@tonic-gate }
1570Sstevel@tonic-gate 
1580Sstevel@tonic-gate /*
1590Sstevel@tonic-gate  * Get a copy of the current port maps.
1600Sstevel@tonic-gate  * Calls the pmap service remotely to do get the maps.
1610Sstevel@tonic-gate  */
1620Sstevel@tonic-gate struct pmaplist *
pmap_getmaps(struct sockaddr_in * address)163132Srobinson pmap_getmaps(struct sockaddr_in *address)
1640Sstevel@tonic-gate {
165132Srobinson 	pmaplist_ptr head = NULL;
1660Sstevel@tonic-gate 	int fd = RPC_ANYFD;
1670Sstevel@tonic-gate 	struct timeval minutetimeout;
168132Srobinson 	CLIENT *client;
1690Sstevel@tonic-gate 
1700Sstevel@tonic-gate 	minutetimeout.tv_sec = 60;
1710Sstevel@tonic-gate 	minutetimeout.tv_usec = 0;
1720Sstevel@tonic-gate 	address->sin_port = htons(PMAPPORT);
1730Sstevel@tonic-gate 	client = clnttcp_create(address, PMAPPROG, PMAPVERS, &fd, 50, 500);
174132Srobinson 	if (client != NULL) {
175132Srobinson 		if (CLNT_CALL(client, PMAPPROC_DUMP, (xdrproc_t)xdr_void,
176132Srobinson 			    NULL, (xdrproc_t)xdr_pmaplist_ptr,
177132Srobinson 			    (caddr_t)&head, minutetimeout) != RPC_SUCCESS) {
178132Srobinson 			(void) syslog(LOG_ERR, "%s",
1790Sstevel@tonic-gate 			clnt_sperror(client, "pmap_getmaps rpc problem"));
1800Sstevel@tonic-gate 		}
1810Sstevel@tonic-gate 		CLNT_DESTROY(client);
1820Sstevel@tonic-gate 	}
1830Sstevel@tonic-gate 	address->sin_port = 0;
1840Sstevel@tonic-gate 	return ((struct pmaplist *)head);
1850Sstevel@tonic-gate }
1860Sstevel@tonic-gate 
1870Sstevel@tonic-gate /*
1880Sstevel@tonic-gate  * pmapper remote-call-service interface.
1890Sstevel@tonic-gate  * This routine is used to call the pmapper remote call service
1900Sstevel@tonic-gate  * which will look up a service program in the port maps, and then
1910Sstevel@tonic-gate  * remotely call that routine with the given parameters. This allows
1920Sstevel@tonic-gate  * programs to do a lookup and call in one step.
1930Sstevel@tonic-gate  */
1940Sstevel@tonic-gate enum clnt_stat
pmap_rmtcall(struct sockaddr_in * addr,rpcprog_t prog,rpcvers_t vers,rpcproc_t proc,xdrproc_t xdrargs,caddr_t argsp,xdrproc_t xdrres,caddr_t resp,struct timeval tout,rpcport_t * port_ptr)195132Srobinson pmap_rmtcall(struct sockaddr_in *addr, rpcprog_t prog, rpcvers_t vers,
196132Srobinson 	rpcproc_t proc, xdrproc_t xdrargs, caddr_t argsp, xdrproc_t xdrres,
197132Srobinson 	caddr_t resp, struct timeval tout, rpcport_t *port_ptr)
1980Sstevel@tonic-gate {
1990Sstevel@tonic-gate 	int fd = RPC_ANYFD;
200132Srobinson 	CLIENT *client;
2010Sstevel@tonic-gate 	struct p_rmtcallargs a;
2020Sstevel@tonic-gate 	struct p_rmtcallres r;
2030Sstevel@tonic-gate 	enum clnt_stat stat;
2040Sstevel@tonic-gate 	short tmp = addr->sin_port;
2050Sstevel@tonic-gate 
2060Sstevel@tonic-gate 	addr->sin_port = htons(PMAPPORT);
2070Sstevel@tonic-gate 	client = clntudp_create(addr, PMAPPROG, PMAPVERS, rmttimeout, &fd);
208132Srobinson 	if (client != NULL) {
2090Sstevel@tonic-gate 		a.prog = prog;
2100Sstevel@tonic-gate 		a.vers = vers;
2110Sstevel@tonic-gate 		a.proc = proc;
2120Sstevel@tonic-gate 		a.args.args_val = argsp;
2130Sstevel@tonic-gate 		a.xdr_args = xdrargs;
2140Sstevel@tonic-gate 		r.res.res_val = resp;
2150Sstevel@tonic-gate 		r.xdr_res = xdrres;
2160Sstevel@tonic-gate 		stat = CLNT_CALL(client, PMAPPROC_CALLIT,
2170Sstevel@tonic-gate 				(xdrproc_t)xdr_rmtcallargs,
218132Srobinson 				(caddr_t)&a, (xdrproc_t)xdr_rmtcallres,
219132Srobinson 				(caddr_t)&r, tout);
2200Sstevel@tonic-gate 		CLNT_DESTROY(client);
2210Sstevel@tonic-gate 	} else {
2220Sstevel@tonic-gate 		stat = RPC_FAILED;
2230Sstevel@tonic-gate 	}
2240Sstevel@tonic-gate 	addr->sin_port = tmp;
2250Sstevel@tonic-gate 	*port_ptr = r.port;
2260Sstevel@tonic-gate 	return (stat);
2270Sstevel@tonic-gate }
2282712Snn35248 
2290Sstevel@tonic-gate #endif /* PORTMAP */
230