xref: /titanic_51/usr/src/lib/libnsl/rpc/rpc_soc.c (revision cb6207858a9fcc2feaee22e626912fba281ac969)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5004388ebScasper  * Common Development and Distribution License (the "License").
6004388ebScasper  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
2161961e0fSrobinson 
227c478bd9Sstevel@tonic-gate /*
23*cb620785Sraf  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
247c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
257c478bd9Sstevel@tonic-gate  */
26*cb620785Sraf 
277c478bd9Sstevel@tonic-gate /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
287c478bd9Sstevel@tonic-gate /* All Rights Reserved */
297c478bd9Sstevel@tonic-gate /*
307c478bd9Sstevel@tonic-gate  * Portions of this source code were derived from Berkeley
317c478bd9Sstevel@tonic-gate  * 4.3 BSD under license from the Regents of the University of
327c478bd9Sstevel@tonic-gate  * California.
337c478bd9Sstevel@tonic-gate  */
347c478bd9Sstevel@tonic-gate 
357c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
367c478bd9Sstevel@tonic-gate 
377c478bd9Sstevel@tonic-gate #ifdef PORTMAP
387c478bd9Sstevel@tonic-gate /*
397c478bd9Sstevel@tonic-gate  * rpc_soc.c
407c478bd9Sstevel@tonic-gate  *
417c478bd9Sstevel@tonic-gate  * The backward compatibility routines for the earlier implementation
427c478bd9Sstevel@tonic-gate  * of RPC, where the only transports supported were tcp/ip and udp/ip.
437c478bd9Sstevel@tonic-gate  * Based on berkeley socket abstraction, now implemented on the top
447c478bd9Sstevel@tonic-gate  * of TLI/Streams
457c478bd9Sstevel@tonic-gate  */
467c478bd9Sstevel@tonic-gate 
477c478bd9Sstevel@tonic-gate #include "mt.h"
487c478bd9Sstevel@tonic-gate #include "rpc_mt.h"
497c478bd9Sstevel@tonic-gate #include <stdio.h>
507c478bd9Sstevel@tonic-gate #include <sys/types.h>
517c478bd9Sstevel@tonic-gate #include <rpc/rpc.h>
527c478bd9Sstevel@tonic-gate #include <netinet/in.h>
537c478bd9Sstevel@tonic-gate #include <sys/socket.h>
547c478bd9Sstevel@tonic-gate #include <netdb.h>
557c478bd9Sstevel@tonic-gate #include <netdir.h>
567c478bd9Sstevel@tonic-gate #include <errno.h>
577c478bd9Sstevel@tonic-gate #include <sys/syslog.h>
587c478bd9Sstevel@tonic-gate #include <rpc/pmap_clnt.h>
597c478bd9Sstevel@tonic-gate #include <rpc/pmap_prot.h>
607c478bd9Sstevel@tonic-gate #include <rpc/nettype.h>
617c478bd9Sstevel@tonic-gate #include <syslog.h>
627c478bd9Sstevel@tonic-gate #include <string.h>
637c478bd9Sstevel@tonic-gate #include <stdlib.h>
647c478bd9Sstevel@tonic-gate #include <unistd.h>
657c478bd9Sstevel@tonic-gate 
667c478bd9Sstevel@tonic-gate int __rpc_bindresvport(int, struct sockaddr_in *, int *, int);
677c478bd9Sstevel@tonic-gate int __rpc_bindresvport_ipv6(int, struct sockaddr *, int *, int, char *);
687c478bd9Sstevel@tonic-gate void get_myaddress_ipv6(char *, struct sockaddr *);
697c478bd9Sstevel@tonic-gate 
707c478bd9Sstevel@tonic-gate extern mutex_t	rpcsoc_lock;
717c478bd9Sstevel@tonic-gate 
727c478bd9Sstevel@tonic-gate /*
737c478bd9Sstevel@tonic-gate  * A common clnt create routine
747c478bd9Sstevel@tonic-gate  */
757c478bd9Sstevel@tonic-gate static CLIENT *
7661961e0fSrobinson clnt_com_create(struct sockaddr_in *raddr, rpcprog_t prog, rpcvers_t vers,
7761961e0fSrobinson 	int *sockp, uint_t sendsz, uint_t recvsz, char *tp)
787c478bd9Sstevel@tonic-gate {
797c478bd9Sstevel@tonic-gate 	CLIENT *cl;
807c478bd9Sstevel@tonic-gate 	int madefd = FALSE;
817c478bd9Sstevel@tonic-gate 	int fd = *sockp;
827c478bd9Sstevel@tonic-gate 	struct t_info tinfo;
837c478bd9Sstevel@tonic-gate 	struct netconfig *nconf;
847c478bd9Sstevel@tonic-gate 	int port;
857c478bd9Sstevel@tonic-gate 	struct netbuf bindaddr;
867c478bd9Sstevel@tonic-gate 	bool_t locked = TRUE;
877c478bd9Sstevel@tonic-gate 
8861961e0fSrobinson 	(void) mutex_lock(&rpcsoc_lock);
897c478bd9Sstevel@tonic-gate 	if ((nconf = __rpc_getconfip(tp)) == NULL) {
907c478bd9Sstevel@tonic-gate 		rpc_createerr.cf_stat = RPC_UNKNOWNPROTO;
9161961e0fSrobinson 		(void) mutex_unlock(&rpcsoc_lock);
9261961e0fSrobinson 		return (NULL);
937c478bd9Sstevel@tonic-gate 	}
947c478bd9Sstevel@tonic-gate 	if (fd == RPC_ANYSOCK) {
957c478bd9Sstevel@tonic-gate 		fd = t_open(nconf->nc_device, O_RDWR, &tinfo);
967c478bd9Sstevel@tonic-gate 		if (fd == -1)
977c478bd9Sstevel@tonic-gate 			goto syserror;
98004388ebScasper 		RPC_RAISEFD(fd);
997c478bd9Sstevel@tonic-gate 		madefd = TRUE;
1007c478bd9Sstevel@tonic-gate 	} else {
1017c478bd9Sstevel@tonic-gate 		if (t_getinfo(fd, &tinfo) == -1)
1027c478bd9Sstevel@tonic-gate 			goto syserror;
1037c478bd9Sstevel@tonic-gate 	}
1047c478bd9Sstevel@tonic-gate 
1057c478bd9Sstevel@tonic-gate 	if (raddr->sin_port == 0) {
1067c478bd9Sstevel@tonic-gate 		uint_t proto;
1077c478bd9Sstevel@tonic-gate 		ushort_t sport;
1087c478bd9Sstevel@tonic-gate 
10961961e0fSrobinson 		/* pmap_getport is recursive */
11061961e0fSrobinson 		(void) mutex_unlock(&rpcsoc_lock);
1117c478bd9Sstevel@tonic-gate 		proto = strcmp(tp, "udp") == 0 ? IPPROTO_UDP : IPPROTO_TCP;
1127c478bd9Sstevel@tonic-gate 		sport = pmap_getport(raddr, prog, vers, proto);
1137c478bd9Sstevel@tonic-gate 		if (sport == 0) {
1147c478bd9Sstevel@tonic-gate 			locked = FALSE;
1157c478bd9Sstevel@tonic-gate 			goto err;
1167c478bd9Sstevel@tonic-gate 		}
1177c478bd9Sstevel@tonic-gate 		raddr->sin_port = htons(sport);
11861961e0fSrobinson 		/* pmap_getport is recursive */
11961961e0fSrobinson 		(void) mutex_lock(&rpcsoc_lock);
1207c478bd9Sstevel@tonic-gate 	}
1217c478bd9Sstevel@tonic-gate 
1227c478bd9Sstevel@tonic-gate 	/* Transform sockaddr_in to netbuf */
1237c478bd9Sstevel@tonic-gate 	bindaddr.maxlen = bindaddr.len =  __rpc_get_a_size(tinfo.addr);
1247c478bd9Sstevel@tonic-gate 	bindaddr.buf = (char *)raddr;
1257c478bd9Sstevel@tonic-gate 
12661961e0fSrobinson 	(void) __rpc_bindresvport(fd, NULL, &port, 0);
1277c478bd9Sstevel@tonic-gate 	cl = clnt_tli_create(fd, nconf, &bindaddr, prog, vers,
1287c478bd9Sstevel@tonic-gate 				sendsz, recvsz);
1297c478bd9Sstevel@tonic-gate 	if (cl) {
1307c478bd9Sstevel@tonic-gate 		if (madefd == TRUE) {
1317c478bd9Sstevel@tonic-gate 			/*
1327c478bd9Sstevel@tonic-gate 			 * The fd should be closed while destroying the handle.
1337c478bd9Sstevel@tonic-gate 			 */
13461961e0fSrobinson 			(void) CLNT_CONTROL(cl, CLSET_FD_CLOSE, NULL);
1357c478bd9Sstevel@tonic-gate 			*sockp = fd;
1367c478bd9Sstevel@tonic-gate 		}
1377c478bd9Sstevel@tonic-gate 		(void) freenetconfigent(nconf);
13861961e0fSrobinson 		(void) mutex_unlock(&rpcsoc_lock);
1397c478bd9Sstevel@tonic-gate 		return (cl);
1407c478bd9Sstevel@tonic-gate 	}
1417c478bd9Sstevel@tonic-gate 	goto err;
1427c478bd9Sstevel@tonic-gate 
1437c478bd9Sstevel@tonic-gate syserror:
1447c478bd9Sstevel@tonic-gate 	rpc_createerr.cf_stat = RPC_SYSTEMERROR;
1457c478bd9Sstevel@tonic-gate 	rpc_createerr.cf_error.re_errno = errno;
1467c478bd9Sstevel@tonic-gate 	rpc_createerr.cf_error.re_terrno = t_errno;
1477c478bd9Sstevel@tonic-gate 
1487c478bd9Sstevel@tonic-gate err:	if (madefd == TRUE)
1497c478bd9Sstevel@tonic-gate 		(void) t_close(fd);
1507c478bd9Sstevel@tonic-gate 	(void) freenetconfigent(nconf);
1517c478bd9Sstevel@tonic-gate 	if (locked == TRUE)
15261961e0fSrobinson 		(void) mutex_unlock(&rpcsoc_lock);
15361961e0fSrobinson 	return (NULL);
1547c478bd9Sstevel@tonic-gate }
1557c478bd9Sstevel@tonic-gate 
1567c478bd9Sstevel@tonic-gate CLIENT *
15761961e0fSrobinson clntudp_bufcreate(struct sockaddr_in *raddr, rpcprog_t prog, rpcvers_t vers,
15861961e0fSrobinson 	struct timeval wait, int *sockp, uint_t sendsz, uint_t recvsz)
1597c478bd9Sstevel@tonic-gate {
1607c478bd9Sstevel@tonic-gate 	CLIENT *cl;
1617c478bd9Sstevel@tonic-gate 
1627c478bd9Sstevel@tonic-gate 	cl = clnt_com_create(raddr, prog, vers, sockp, sendsz, recvsz, "udp");
16361961e0fSrobinson 	if (cl == NULL)
16461961e0fSrobinson 		return (NULL);
1657c478bd9Sstevel@tonic-gate 	(void) CLNT_CONTROL(cl, CLSET_RETRY_TIMEOUT, (char *)&wait);
1667c478bd9Sstevel@tonic-gate 	return (cl);
1677c478bd9Sstevel@tonic-gate }
1687c478bd9Sstevel@tonic-gate 
1697c478bd9Sstevel@tonic-gate CLIENT *
17061961e0fSrobinson clntudp_create(struct sockaddr_in *raddr, rpcprog_t program, rpcvers_t version,
17161961e0fSrobinson 	struct timeval wait, int *sockp)
1727c478bd9Sstevel@tonic-gate {
17361961e0fSrobinson 	return (clntudp_bufcreate(raddr, program, version, wait, sockp,
17461961e0fSrobinson 					UDPMSGSIZE, UDPMSGSIZE));
1757c478bd9Sstevel@tonic-gate }
1767c478bd9Sstevel@tonic-gate 
1777c478bd9Sstevel@tonic-gate CLIENT *
17861961e0fSrobinson clnttcp_create(struct sockaddr_in *raddr, rpcprog_t prog, rpcvers_t vers,
17961961e0fSrobinson 	int *sockp, uint_t sendsz, uint_t recvsz)
1807c478bd9Sstevel@tonic-gate {
18161961e0fSrobinson 	return (clnt_com_create(raddr, prog, vers, sockp, sendsz,
18261961e0fSrobinson 			recvsz, "tcp"));
1837c478bd9Sstevel@tonic-gate }
1847c478bd9Sstevel@tonic-gate 
1857c478bd9Sstevel@tonic-gate CLIENT *
18661961e0fSrobinson clntraw_create(rpcprog_t prog, rpcvers_t vers)
1877c478bd9Sstevel@tonic-gate {
18861961e0fSrobinson 	return (clnt_raw_create(prog, vers));
1897c478bd9Sstevel@tonic-gate }
1907c478bd9Sstevel@tonic-gate 
1917c478bd9Sstevel@tonic-gate /*
1927c478bd9Sstevel@tonic-gate  * A common server create routine
1937c478bd9Sstevel@tonic-gate  */
1947c478bd9Sstevel@tonic-gate static SVCXPRT *
19561961e0fSrobinson svc_com_create(int fd, uint_t sendsize, uint_t recvsize, char *netid)
1967c478bd9Sstevel@tonic-gate {
1977c478bd9Sstevel@tonic-gate 	struct netconfig *nconf;
1987c478bd9Sstevel@tonic-gate 	SVCXPRT *svc;
1997c478bd9Sstevel@tonic-gate 	int madefd = FALSE;
2007c478bd9Sstevel@tonic-gate 	int port;
2017c478bd9Sstevel@tonic-gate 	int res;
2027c478bd9Sstevel@tonic-gate 
2037c478bd9Sstevel@tonic-gate 	if ((nconf = __rpc_getconfip(netid)) == NULL) {
2047c478bd9Sstevel@tonic-gate 		(void) syslog(LOG_ERR, "Could not get %s transport", netid);
20561961e0fSrobinson 		return (NULL);
2067c478bd9Sstevel@tonic-gate 	}
2077c478bd9Sstevel@tonic-gate 	if (fd == RPC_ANYSOCK) {
20861961e0fSrobinson 		fd = t_open(nconf->nc_device, O_RDWR, NULL);
2097c478bd9Sstevel@tonic-gate 		if (fd == -1) {
2107c478bd9Sstevel@tonic-gate 			char errorstr[100];
2117c478bd9Sstevel@tonic-gate 
2127c478bd9Sstevel@tonic-gate 			__tli_sys_strerror(errorstr, sizeof (errorstr),
2137c478bd9Sstevel@tonic-gate 					t_errno, errno);
2147c478bd9Sstevel@tonic-gate 			(void) syslog(LOG_ERR,
2157c478bd9Sstevel@tonic-gate 			"svc%s_create: could not open connection : %s", netid,
2167c478bd9Sstevel@tonic-gate 				    errorstr);
2177c478bd9Sstevel@tonic-gate 			(void) freenetconfigent(nconf);
21861961e0fSrobinson 			return (NULL);
2197c478bd9Sstevel@tonic-gate 		}
2207c478bd9Sstevel@tonic-gate 		madefd = TRUE;
2217c478bd9Sstevel@tonic-gate 	}
2227c478bd9Sstevel@tonic-gate 
22361961e0fSrobinson 	res = __rpc_bindresvport(fd, NULL, &port, 8);
22461961e0fSrobinson 	svc = svc_tli_create(fd, nconf, NULL,
2257c478bd9Sstevel@tonic-gate 				sendsize, recvsize);
2267c478bd9Sstevel@tonic-gate 	(void) freenetconfigent(nconf);
22761961e0fSrobinson 	if (svc == NULL) {
2287c478bd9Sstevel@tonic-gate 		if (madefd)
2297c478bd9Sstevel@tonic-gate 			(void) t_close(fd);
23061961e0fSrobinson 		return (NULL);
2317c478bd9Sstevel@tonic-gate 	}
23261961e0fSrobinson 	if (res == -1)
23361961e0fSrobinson 		/* LINTED pointer cast */
2347c478bd9Sstevel@tonic-gate 		port = (((struct sockaddr_in *)svc->xp_ltaddr.buf)->sin_port);
2357c478bd9Sstevel@tonic-gate 	svc->xp_port = ntohs(port);
2367c478bd9Sstevel@tonic-gate 	return (svc);
2377c478bd9Sstevel@tonic-gate }
2387c478bd9Sstevel@tonic-gate 
2397c478bd9Sstevel@tonic-gate SVCXPRT *
24061961e0fSrobinson svctcp_create(int fd, uint_t sendsize, uint_t recvsize)
2417c478bd9Sstevel@tonic-gate {
24261961e0fSrobinson 	return (svc_com_create(fd, sendsize, recvsize, "tcp"));
2437c478bd9Sstevel@tonic-gate }
2447c478bd9Sstevel@tonic-gate 
2457c478bd9Sstevel@tonic-gate SVCXPRT *
24661961e0fSrobinson svcudp_bufcreate(int fd, uint_t sendsz, uint_t recvsz)
2477c478bd9Sstevel@tonic-gate {
24861961e0fSrobinson 	return (svc_com_create(fd, sendsz, recvsz, "udp"));
2497c478bd9Sstevel@tonic-gate }
2507c478bd9Sstevel@tonic-gate 
2517c478bd9Sstevel@tonic-gate SVCXPRT *
25261961e0fSrobinson svcfd_create(int fd, uint_t sendsize, uint_t recvsize)
2537c478bd9Sstevel@tonic-gate {
25461961e0fSrobinson 	return (svc_fd_create(fd, sendsize, recvsize));
2557c478bd9Sstevel@tonic-gate }
2567c478bd9Sstevel@tonic-gate 
2577c478bd9Sstevel@tonic-gate 
2587c478bd9Sstevel@tonic-gate SVCXPRT *
25961961e0fSrobinson svcudp_create(int fd)
2607c478bd9Sstevel@tonic-gate {
26161961e0fSrobinson 	return (svc_com_create(fd, UDPMSGSIZE, UDPMSGSIZE, "udp"));
2627c478bd9Sstevel@tonic-gate }
2637c478bd9Sstevel@tonic-gate 
2647c478bd9Sstevel@tonic-gate SVCXPRT *
26561961e0fSrobinson svcraw_create(void)
2667c478bd9Sstevel@tonic-gate {
26761961e0fSrobinson 	return (svc_raw_create());
2687c478bd9Sstevel@tonic-gate }
2697c478bd9Sstevel@tonic-gate 
2707c478bd9Sstevel@tonic-gate /*
2717c478bd9Sstevel@tonic-gate  * Bind a fd to a privileged IP port.
2727c478bd9Sstevel@tonic-gate  * This is slightly different from the code in netdir_options
2737c478bd9Sstevel@tonic-gate  * because it has a different interface - main thing is that it
2747c478bd9Sstevel@tonic-gate  * needs to know its own address.  We also wanted to set the qlen.
2757c478bd9Sstevel@tonic-gate  * t_getname() can be used for those purposes and perhaps job can be done.
2767c478bd9Sstevel@tonic-gate  */
2777c478bd9Sstevel@tonic-gate int
2787c478bd9Sstevel@tonic-gate __rpc_bindresvport_ipv6(int fd, struct sockaddr *sin, int *portp, int qlen,
2797c478bd9Sstevel@tonic-gate 			char *fmly)
2807c478bd9Sstevel@tonic-gate {
2817c478bd9Sstevel@tonic-gate 	int res;
2827c478bd9Sstevel@tonic-gate 	static in_port_t port, *sinport;
2837c478bd9Sstevel@tonic-gate 	struct sockaddr_in6 myaddr;
2847c478bd9Sstevel@tonic-gate 	int i;
2857c478bd9Sstevel@tonic-gate 	struct t_bind tbindstr, *tres;
2867c478bd9Sstevel@tonic-gate 	struct t_info tinfo;
2877c478bd9Sstevel@tonic-gate 	extern mutex_t portnum_lock;
2887c478bd9Sstevel@tonic-gate 
2897c478bd9Sstevel@tonic-gate 	/* VARIABLES PROTECTED BY portnum_lock: port */
2907c478bd9Sstevel@tonic-gate 
2917c478bd9Sstevel@tonic-gate #define	STARTPORT 600
2927c478bd9Sstevel@tonic-gate #define	ENDPORT (IPPORT_RESERVED - 1)
2937c478bd9Sstevel@tonic-gate #define	NPORTS	(ENDPORT - STARTPORT + 1)
2947c478bd9Sstevel@tonic-gate 
2957c478bd9Sstevel@tonic-gate 	if (sin == 0 && fmly == 0) {
2967c478bd9Sstevel@tonic-gate 		errno = EINVAL;
2977c478bd9Sstevel@tonic-gate 		return (-1);
2987c478bd9Sstevel@tonic-gate 	}
2997c478bd9Sstevel@tonic-gate 	if (geteuid()) {
3007c478bd9Sstevel@tonic-gate 		errno = EACCES;
3017c478bd9Sstevel@tonic-gate 		return (-1);
3027c478bd9Sstevel@tonic-gate 	}
3037c478bd9Sstevel@tonic-gate 	if ((i = t_getstate(fd)) != T_UNBND) {
3047c478bd9Sstevel@tonic-gate 		if (t_errno == TBADF)
3057c478bd9Sstevel@tonic-gate 			errno = EBADF;
3067c478bd9Sstevel@tonic-gate 		if (i != -1)
3077c478bd9Sstevel@tonic-gate 			errno = EISCONN;
3087c478bd9Sstevel@tonic-gate 		return (-1);
3097c478bd9Sstevel@tonic-gate 	}
3107c478bd9Sstevel@tonic-gate 	if (sin == 0) {
3117c478bd9Sstevel@tonic-gate 		sin = (struct sockaddr *)&myaddr;
3127c478bd9Sstevel@tonic-gate 		get_myaddress_ipv6(fmly, sin);
3137c478bd9Sstevel@tonic-gate 	}
3147c478bd9Sstevel@tonic-gate 	if (sin->sa_family == AF_INET) {
31561961e0fSrobinson 		/* LINTED pointer cast */
3167c478bd9Sstevel@tonic-gate 		sinport = &((struct sockaddr_in *)sin)->sin_port;
3177c478bd9Sstevel@tonic-gate 	} else if (sin->sa_family == AF_INET6) {
31861961e0fSrobinson 		/* LINTED pointer cast */
3197c478bd9Sstevel@tonic-gate 		sinport = &((struct sockaddr_in6 *)sin)->sin6_port;
3207c478bd9Sstevel@tonic-gate 	} else {
3217c478bd9Sstevel@tonic-gate 		errno = EPFNOSUPPORT;
3227c478bd9Sstevel@tonic-gate 		return (-1);
3237c478bd9Sstevel@tonic-gate 	}
3247c478bd9Sstevel@tonic-gate 
3257c478bd9Sstevel@tonic-gate 	/* Transform sockaddr to netbuf */
3267c478bd9Sstevel@tonic-gate 	if (t_getinfo(fd, &tinfo) == -1) {
3277c478bd9Sstevel@tonic-gate 		return (-1);
3287c478bd9Sstevel@tonic-gate 	}
32961961e0fSrobinson 	/* LINTED pointer cast */
3307c478bd9Sstevel@tonic-gate 	tres = (struct t_bind *)t_alloc(fd, T_BIND, T_ADDR);
33161961e0fSrobinson 	if (tres == NULL)
3327c478bd9Sstevel@tonic-gate 		return (-1);
3337c478bd9Sstevel@tonic-gate 
3347c478bd9Sstevel@tonic-gate 	tbindstr.qlen = qlen;
3357c478bd9Sstevel@tonic-gate 	tbindstr.addr.buf = (char *)sin;
3367c478bd9Sstevel@tonic-gate 	tbindstr.addr.len = tbindstr.addr.maxlen = __rpc_get_a_size(tinfo.addr);
33761961e0fSrobinson 	/* LINTED pointer cast */
3387c478bd9Sstevel@tonic-gate 	sin = (struct sockaddr *)tbindstr.addr.buf;
3397c478bd9Sstevel@tonic-gate 
3407c478bd9Sstevel@tonic-gate 	res = -1;
34161961e0fSrobinson 	(void) mutex_lock(&portnum_lock);
3427c478bd9Sstevel@tonic-gate 	if (port == 0)
3437c478bd9Sstevel@tonic-gate 		port = (getpid() % NPORTS) + STARTPORT;
3447c478bd9Sstevel@tonic-gate 	for (i = 0; i < NPORTS; i++) {
3457c478bd9Sstevel@tonic-gate 		*sinport = htons(port++);
3467c478bd9Sstevel@tonic-gate 		if (port > ENDPORT)
3477c478bd9Sstevel@tonic-gate 			port = STARTPORT;
3487c478bd9Sstevel@tonic-gate 		res = t_bind(fd, &tbindstr, tres);
3497c478bd9Sstevel@tonic-gate 		if (res == 0) {
3507c478bd9Sstevel@tonic-gate 			if ((tbindstr.addr.len == tres->addr.len) &&
3517c478bd9Sstevel@tonic-gate 				(memcmp(tbindstr.addr.buf, tres->addr.buf,
3527c478bd9Sstevel@tonic-gate 					(int)tres->addr.len) == 0))
3537c478bd9Sstevel@tonic-gate 				break;
3547c478bd9Sstevel@tonic-gate 			(void) t_unbind(fd);
3557c478bd9Sstevel@tonic-gate 			res = -1;
3567c478bd9Sstevel@tonic-gate 		} else if (t_errno != TSYSERR || errno != EADDRINUSE)
3577c478bd9Sstevel@tonic-gate 			break;
3587c478bd9Sstevel@tonic-gate 	}
35961961e0fSrobinson 	(void) mutex_unlock(&portnum_lock);
3607c478bd9Sstevel@tonic-gate 
3617c478bd9Sstevel@tonic-gate 	if ((portp != NULL) && (res == 0))
3627c478bd9Sstevel@tonic-gate 		*portp = *sinport;
3637c478bd9Sstevel@tonic-gate 	(void) t_free((char *)tres, T_BIND);
3647c478bd9Sstevel@tonic-gate 	return (res);
3657c478bd9Sstevel@tonic-gate }
3667c478bd9Sstevel@tonic-gate 
3677c478bd9Sstevel@tonic-gate int
3687c478bd9Sstevel@tonic-gate __rpc_bindresvport(int fd, struct sockaddr_in *sin, int *portp, int qlen)
3697c478bd9Sstevel@tonic-gate {
3707c478bd9Sstevel@tonic-gate 	return (__rpc_bindresvport_ipv6(fd, (struct sockaddr *)sin, portp,
3717c478bd9Sstevel@tonic-gate 					qlen, NC_INET));
3727c478bd9Sstevel@tonic-gate }
3737c478bd9Sstevel@tonic-gate 
3747c478bd9Sstevel@tonic-gate /*
3757c478bd9Sstevel@tonic-gate  * Get clients IP address.
3767c478bd9Sstevel@tonic-gate  * don't use gethostbyname, which would invoke yellow pages
3777c478bd9Sstevel@tonic-gate  * Remains only for backward compatibility reasons.
3787c478bd9Sstevel@tonic-gate  * Used mainly by the portmapper so that it can register
3797c478bd9Sstevel@tonic-gate  * with itself. Also used by pmap*() routines
3807c478bd9Sstevel@tonic-gate  */
3817c478bd9Sstevel@tonic-gate void
3827c478bd9Sstevel@tonic-gate get_myaddress_ipv6(char *fmly, struct sockaddr *addr)
3837c478bd9Sstevel@tonic-gate {
3847c478bd9Sstevel@tonic-gate 	if (fmly != 0 && strcmp(fmly, NC_INET6) == 0) {
38561961e0fSrobinson 		/* LINTED pointer cast */
3867c478bd9Sstevel@tonic-gate 		struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)addr;
38761961e0fSrobinson 		(void) memset(sin6, 0, sizeof (*sin6));
3887c478bd9Sstevel@tonic-gate 		sin6->sin6_family = AF_INET6;
3897c478bd9Sstevel@tonic-gate 		sin6->sin6_port = htons(PMAPPORT);
3907c478bd9Sstevel@tonic-gate 		if (__can_use_af(AF_INET6)) {
3917c478bd9Sstevel@tonic-gate 			/* Local copy of in6addr_any to avoid -lsocket */
3927c478bd9Sstevel@tonic-gate 			struct in6_addr in6addr_any = IN6ADDR_ANY_INIT;
3937c478bd9Sstevel@tonic-gate 			sin6->sin6_addr = in6addr_any;
3947c478bd9Sstevel@tonic-gate 		} else {
3957c478bd9Sstevel@tonic-gate 			struct in_addr in4;
3967c478bd9Sstevel@tonic-gate 			in4.s_addr = INADDR_ANY;
3977c478bd9Sstevel@tonic-gate 			IN6_INADDR_TO_V4MAPPED(&in4, &sin6->sin6_addr);
3987c478bd9Sstevel@tonic-gate 		}
3997c478bd9Sstevel@tonic-gate 	} else {
40061961e0fSrobinson 		/* LINTED pointer cast */
4017c478bd9Sstevel@tonic-gate 		struct sockaddr_in	*sin = (struct sockaddr_in *)addr;
40261961e0fSrobinson 		(void) memset(sin, 0, sizeof (*sin));
4037c478bd9Sstevel@tonic-gate 		sin->sin_family = AF_INET;
4047c478bd9Sstevel@tonic-gate 		sin->sin_port = htons(PMAPPORT);
4057c478bd9Sstevel@tonic-gate 		sin->sin_addr.s_addr = INADDR_ANY;
4067c478bd9Sstevel@tonic-gate 	}
4077c478bd9Sstevel@tonic-gate }
4087c478bd9Sstevel@tonic-gate 
4097c478bd9Sstevel@tonic-gate void
4107c478bd9Sstevel@tonic-gate get_myaddress(struct sockaddr_in *addr)
4117c478bd9Sstevel@tonic-gate {
4127c478bd9Sstevel@tonic-gate 	get_myaddress_ipv6(0, (struct sockaddr *)addr);
4137c478bd9Sstevel@tonic-gate }
4147c478bd9Sstevel@tonic-gate 
4157c478bd9Sstevel@tonic-gate /*
4167c478bd9Sstevel@tonic-gate  * Get port used by specified service on specified host.
4177c478bd9Sstevel@tonic-gate  * Exists for source compatibility only.
4187c478bd9Sstevel@tonic-gate  * Obsoleted by rpcb_getaddr().
4197c478bd9Sstevel@tonic-gate  */
4207c478bd9Sstevel@tonic-gate ushort_t
4217c478bd9Sstevel@tonic-gate getrpcport(char *host, rpcprog_t prognum, rpcvers_t versnum,
4227c478bd9Sstevel@tonic-gate 	rpcprot_t proto)
4237c478bd9Sstevel@tonic-gate {
4247c478bd9Sstevel@tonic-gate 	struct sockaddr_in addr;
4257c478bd9Sstevel@tonic-gate 	struct hostent *hp;
4267c478bd9Sstevel@tonic-gate 
4277c478bd9Sstevel@tonic-gate 	if ((hp = gethostbyname(host)) == NULL)
4287c478bd9Sstevel@tonic-gate 		return (0);
42961961e0fSrobinson 	(void) memcpy(&addr.sin_addr, hp->h_addr, hp->h_length);
4307c478bd9Sstevel@tonic-gate 	addr.sin_family = AF_INET;
4317c478bd9Sstevel@tonic-gate 	addr.sin_port =  0;
4327c478bd9Sstevel@tonic-gate 	return (pmap_getport(&addr, prognum, versnum, proto));
4337c478bd9Sstevel@tonic-gate }
4347c478bd9Sstevel@tonic-gate 
4357c478bd9Sstevel@tonic-gate /*
4367c478bd9Sstevel@tonic-gate  * For connectionless "udp" transport. Obsoleted by rpc_call().
4377c478bd9Sstevel@tonic-gate  */
4387c478bd9Sstevel@tonic-gate int
43961961e0fSrobinson callrpc(char *host, rpcprog_t prognum, rpcvers_t versnum, rpcproc_t procnum,
44061961e0fSrobinson 	xdrproc_t inproc, char *in, xdrproc_t outproc, char *out)
4417c478bd9Sstevel@tonic-gate {
44261961e0fSrobinson 	return ((int)rpc_call(host, prognum, versnum, procnum, inproc,
44361961e0fSrobinson 				in, outproc, out, "udp"));
4447c478bd9Sstevel@tonic-gate }
4457c478bd9Sstevel@tonic-gate 
4467c478bd9Sstevel@tonic-gate /*
4477c478bd9Sstevel@tonic-gate  * For connectionless kind of transport. Obsoleted by rpc_reg()
4487c478bd9Sstevel@tonic-gate  */
4497c478bd9Sstevel@tonic-gate int
45061961e0fSrobinson registerrpc(rpcprog_t prognum, rpcvers_t versnum, rpcproc_t procnum,
45161961e0fSrobinson 	char *(*progname)(), xdrproc_t inproc, xdrproc_t outproc)
4527c478bd9Sstevel@tonic-gate {
45361961e0fSrobinson 	return (rpc_reg(prognum, versnum, procnum, progname, inproc,
45461961e0fSrobinson 				outproc, "udp"));
4557c478bd9Sstevel@tonic-gate }
4567c478bd9Sstevel@tonic-gate 
4577c478bd9Sstevel@tonic-gate /*
4587c478bd9Sstevel@tonic-gate  * All the following clnt_broadcast stuff is convulated; it supports
4597c478bd9Sstevel@tonic-gate  * the earlier calling style of the callback function
4607c478bd9Sstevel@tonic-gate  */
461*cb620785Sraf static pthread_key_t	clnt_broadcast_key = PTHREAD_ONCE_KEY_NP;
4627c478bd9Sstevel@tonic-gate static resultproc_t	clnt_broadcast_result_main;
4637c478bd9Sstevel@tonic-gate 
4647c478bd9Sstevel@tonic-gate /*
4657c478bd9Sstevel@tonic-gate  * Need to translate the netbuf address into sockaddr_in address.
4667c478bd9Sstevel@tonic-gate  * Dont care about netid here.
4677c478bd9Sstevel@tonic-gate  */
46861961e0fSrobinson /* ARGSUSED2 */
4697c478bd9Sstevel@tonic-gate static bool_t
47061961e0fSrobinson rpc_wrap_bcast(char *resultp, struct netbuf *addr, struct netconfig *nconf)
4717c478bd9Sstevel@tonic-gate {
4727c478bd9Sstevel@tonic-gate 	resultproc_t clnt_broadcast_result;
4737c478bd9Sstevel@tonic-gate 
4747c478bd9Sstevel@tonic-gate 	clnt_broadcast_result = thr_main()? clnt_broadcast_result_main :
4757c478bd9Sstevel@tonic-gate 		(resultproc_t)pthread_getspecific(clnt_broadcast_key);
47661961e0fSrobinson 	return ((*clnt_broadcast_result)(resultp,
47761961e0fSrobinson 				/* LINTED pointer cast */
47861961e0fSrobinson 				(struct sockaddr_in *)addr->buf));
4797c478bd9Sstevel@tonic-gate }
4807c478bd9Sstevel@tonic-gate 
4817c478bd9Sstevel@tonic-gate /*
4827c478bd9Sstevel@tonic-gate  * Broadcasts on UDP transport. Obsoleted by rpc_broadcast().
4837c478bd9Sstevel@tonic-gate  */
4847c478bd9Sstevel@tonic-gate enum clnt_stat
48561961e0fSrobinson clnt_broadcast(rpcprog_t prog, rpcvers_t vers, rpcproc_t proc, xdrproc_t xargs,
48661961e0fSrobinson 	caddr_t argsp, xdrproc_t xresults,
48761961e0fSrobinson 	caddr_t resultsp, resultproc_t eachresult)
4887c478bd9Sstevel@tonic-gate {
48961961e0fSrobinson 	if (thr_main()) {
4907c478bd9Sstevel@tonic-gate 		clnt_broadcast_result_main = eachresult;
49161961e0fSrobinson 	} else {
492*cb620785Sraf 		(void) pthread_key_create_once_np(&clnt_broadcast_key, NULL);
49361961e0fSrobinson 		(void) pthread_setspecific(clnt_broadcast_key,
49461961e0fSrobinson 							(void *)eachresult);
4957c478bd9Sstevel@tonic-gate 	}
49661961e0fSrobinson 	return (rpc_broadcast(prog, vers, proc, xargs, argsp, xresults,
49761961e0fSrobinson 				resultsp, (resultproc_t)rpc_wrap_bcast, "udp"));
4987c478bd9Sstevel@tonic-gate }
4997c478bd9Sstevel@tonic-gate 
5007c478bd9Sstevel@tonic-gate /*
5017c478bd9Sstevel@tonic-gate  * Create the client des authentication object. Obsoleted by
5027c478bd9Sstevel@tonic-gate  * authdes_seccreate().
5037c478bd9Sstevel@tonic-gate  */
5047c478bd9Sstevel@tonic-gate AUTH *
50561961e0fSrobinson authdes_create(char *servername, uint_t window, struct sockaddr_in *syncaddr,
50661961e0fSrobinson 	des_block *ckey)
5077c478bd9Sstevel@tonic-gate {
5087c478bd9Sstevel@tonic-gate 	char *hostname = NULL;
5097c478bd9Sstevel@tonic-gate 
5107c478bd9Sstevel@tonic-gate 	if (syncaddr) {
5117c478bd9Sstevel@tonic-gate 		/*
5127c478bd9Sstevel@tonic-gate 		 * Change addr to hostname, because that is the way
5137c478bd9Sstevel@tonic-gate 		 * new interface takes it.
5147c478bd9Sstevel@tonic-gate 		 */
5157c478bd9Sstevel@tonic-gate 		struct netconfig *nconf;
5167c478bd9Sstevel@tonic-gate 		struct netbuf nb_syncaddr;
5177c478bd9Sstevel@tonic-gate 		struct nd_hostservlist *hlist;
5187c478bd9Sstevel@tonic-gate 		AUTH *nauth;
5197c478bd9Sstevel@tonic-gate 		int fd;
5207c478bd9Sstevel@tonic-gate 		struct t_info tinfo;
5217c478bd9Sstevel@tonic-gate 
5227c478bd9Sstevel@tonic-gate 		if ((nconf = __rpc_getconfip("udp")) == NULL &&
5237c478bd9Sstevel@tonic-gate 		    (nconf = __rpc_getconfip("tcp")) == NULL)
5247c478bd9Sstevel@tonic-gate 			goto fallback;
5257c478bd9Sstevel@tonic-gate 
5267c478bd9Sstevel@tonic-gate 		/* Transform sockaddr_in to netbuf */
5277c478bd9Sstevel@tonic-gate 		if ((fd = t_open(nconf->nc_device, O_RDWR, &tinfo)) == -1) {
5287c478bd9Sstevel@tonic-gate 			(void) freenetconfigent(nconf);
5297c478bd9Sstevel@tonic-gate 			goto fallback;
5307c478bd9Sstevel@tonic-gate 		}
5317c478bd9Sstevel@tonic-gate 		(void) t_close(fd);
5327c478bd9Sstevel@tonic-gate 		nb_syncaddr.maxlen = nb_syncaddr.len =
5337c478bd9Sstevel@tonic-gate 			__rpc_get_a_size(tinfo.addr);
5347c478bd9Sstevel@tonic-gate 		nb_syncaddr.buf = (char *)syncaddr;
5357c478bd9Sstevel@tonic-gate 		if (netdir_getbyaddr(nconf, &hlist, &nb_syncaddr)) {
5367c478bd9Sstevel@tonic-gate 			(void) freenetconfigent(nconf);
5377c478bd9Sstevel@tonic-gate 			goto fallback;
5387c478bd9Sstevel@tonic-gate 		}
5397c478bd9Sstevel@tonic-gate 		if (hlist && hlist->h_cnt > 0 && hlist->h_hostservs)
5407c478bd9Sstevel@tonic-gate 			hostname = hlist->h_hostservs->h_host;
5417c478bd9Sstevel@tonic-gate 		nauth = authdes_seccreate(servername, window, hostname, ckey);
5427c478bd9Sstevel@tonic-gate 		(void) netdir_free((char *)hlist, ND_HOSTSERVLIST);
5437c478bd9Sstevel@tonic-gate 		(void) freenetconfigent(nconf);
5447c478bd9Sstevel@tonic-gate 		return (nauth);
5457c478bd9Sstevel@tonic-gate 	}
5467c478bd9Sstevel@tonic-gate fallback:
54761961e0fSrobinson 	return (authdes_seccreate(servername, window, hostname, ckey));
5487c478bd9Sstevel@tonic-gate }
5497c478bd9Sstevel@tonic-gate #endif /* PORTMAP */
550