xref: /onnv-gate/usr/src/lib/libnsl/rpc/rpc_soc.c (revision 3864:2ae506652d11)
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
51914Scasper  * Common Development and Distribution License (the "License").
61914Scasper  * 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
200Sstevel@tonic-gate  */
21132Srobinson 
220Sstevel@tonic-gate /*
23*3864Sraf  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
240Sstevel@tonic-gate  * Use is subject to license terms.
250Sstevel@tonic-gate  */
26*3864Sraf 
270Sstevel@tonic-gate /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
280Sstevel@tonic-gate /* All Rights Reserved */
290Sstevel@tonic-gate /*
300Sstevel@tonic-gate  * Portions of this source code were derived from Berkeley
310Sstevel@tonic-gate  * 4.3 BSD under license from the Regents of the University of
320Sstevel@tonic-gate  * California.
330Sstevel@tonic-gate  */
340Sstevel@tonic-gate 
350Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
360Sstevel@tonic-gate 
370Sstevel@tonic-gate #ifdef PORTMAP
380Sstevel@tonic-gate /*
390Sstevel@tonic-gate  * rpc_soc.c
400Sstevel@tonic-gate  *
410Sstevel@tonic-gate  * The backward compatibility routines for the earlier implementation
420Sstevel@tonic-gate  * of RPC, where the only transports supported were tcp/ip and udp/ip.
430Sstevel@tonic-gate  * Based on berkeley socket abstraction, now implemented on the top
440Sstevel@tonic-gate  * of TLI/Streams
450Sstevel@tonic-gate  */
460Sstevel@tonic-gate 
470Sstevel@tonic-gate #include "mt.h"
480Sstevel@tonic-gate #include "rpc_mt.h"
490Sstevel@tonic-gate #include <stdio.h>
500Sstevel@tonic-gate #include <sys/types.h>
510Sstevel@tonic-gate #include <rpc/rpc.h>
520Sstevel@tonic-gate #include <netinet/in.h>
530Sstevel@tonic-gate #include <sys/socket.h>
540Sstevel@tonic-gate #include <netdb.h>
550Sstevel@tonic-gate #include <netdir.h>
560Sstevel@tonic-gate #include <errno.h>
570Sstevel@tonic-gate #include <sys/syslog.h>
580Sstevel@tonic-gate #include <rpc/pmap_clnt.h>
590Sstevel@tonic-gate #include <rpc/pmap_prot.h>
600Sstevel@tonic-gate #include <rpc/nettype.h>
610Sstevel@tonic-gate #include <syslog.h>
620Sstevel@tonic-gate #include <string.h>
630Sstevel@tonic-gate #include <stdlib.h>
640Sstevel@tonic-gate #include <unistd.h>
650Sstevel@tonic-gate 
660Sstevel@tonic-gate int __rpc_bindresvport(int, struct sockaddr_in *, int *, int);
670Sstevel@tonic-gate int __rpc_bindresvport_ipv6(int, struct sockaddr *, int *, int, char *);
680Sstevel@tonic-gate void get_myaddress_ipv6(char *, struct sockaddr *);
690Sstevel@tonic-gate 
700Sstevel@tonic-gate extern mutex_t	rpcsoc_lock;
710Sstevel@tonic-gate 
720Sstevel@tonic-gate /*
730Sstevel@tonic-gate  * A common clnt create routine
740Sstevel@tonic-gate  */
750Sstevel@tonic-gate static CLIENT *
clnt_com_create(struct sockaddr_in * raddr,rpcprog_t prog,rpcvers_t vers,int * sockp,uint_t sendsz,uint_t recvsz,char * tp)76132Srobinson clnt_com_create(struct sockaddr_in *raddr, rpcprog_t prog, rpcvers_t vers,
77132Srobinson 	int *sockp, uint_t sendsz, uint_t recvsz, char *tp)
780Sstevel@tonic-gate {
790Sstevel@tonic-gate 	CLIENT *cl;
800Sstevel@tonic-gate 	int madefd = FALSE;
810Sstevel@tonic-gate 	int fd = *sockp;
820Sstevel@tonic-gate 	struct t_info tinfo;
830Sstevel@tonic-gate 	struct netconfig *nconf;
840Sstevel@tonic-gate 	int port;
850Sstevel@tonic-gate 	struct netbuf bindaddr;
860Sstevel@tonic-gate 	bool_t locked = TRUE;
870Sstevel@tonic-gate 
88132Srobinson 	(void) mutex_lock(&rpcsoc_lock);
890Sstevel@tonic-gate 	if ((nconf = __rpc_getconfip(tp)) == NULL) {
900Sstevel@tonic-gate 		rpc_createerr.cf_stat = RPC_UNKNOWNPROTO;
91132Srobinson 		(void) mutex_unlock(&rpcsoc_lock);
92132Srobinson 		return (NULL);
930Sstevel@tonic-gate 	}
940Sstevel@tonic-gate 	if (fd == RPC_ANYSOCK) {
950Sstevel@tonic-gate 		fd = t_open(nconf->nc_device, O_RDWR, &tinfo);
960Sstevel@tonic-gate 		if (fd == -1)
970Sstevel@tonic-gate 			goto syserror;
981914Scasper 		RPC_RAISEFD(fd);
990Sstevel@tonic-gate 		madefd = TRUE;
1000Sstevel@tonic-gate 	} else {
1010Sstevel@tonic-gate 		if (t_getinfo(fd, &tinfo) == -1)
1020Sstevel@tonic-gate 			goto syserror;
1030Sstevel@tonic-gate 	}
1040Sstevel@tonic-gate 
1050Sstevel@tonic-gate 	if (raddr->sin_port == 0) {
1060Sstevel@tonic-gate 		uint_t proto;
1070Sstevel@tonic-gate 		ushort_t sport;
1080Sstevel@tonic-gate 
109132Srobinson 		/* pmap_getport is recursive */
110132Srobinson 		(void) mutex_unlock(&rpcsoc_lock);
1110Sstevel@tonic-gate 		proto = strcmp(tp, "udp") == 0 ? IPPROTO_UDP : IPPROTO_TCP;
1120Sstevel@tonic-gate 		sport = pmap_getport(raddr, prog, vers, proto);
1130Sstevel@tonic-gate 		if (sport == 0) {
1140Sstevel@tonic-gate 			locked = FALSE;
1150Sstevel@tonic-gate 			goto err;
1160Sstevel@tonic-gate 		}
1170Sstevel@tonic-gate 		raddr->sin_port = htons(sport);
118132Srobinson 		/* pmap_getport is recursive */
119132Srobinson 		(void) mutex_lock(&rpcsoc_lock);
1200Sstevel@tonic-gate 	}
1210Sstevel@tonic-gate 
1220Sstevel@tonic-gate 	/* Transform sockaddr_in to netbuf */
1230Sstevel@tonic-gate 	bindaddr.maxlen = bindaddr.len =  __rpc_get_a_size(tinfo.addr);
1240Sstevel@tonic-gate 	bindaddr.buf = (char *)raddr;
1250Sstevel@tonic-gate 
126132Srobinson 	(void) __rpc_bindresvport(fd, NULL, &port, 0);
1270Sstevel@tonic-gate 	cl = clnt_tli_create(fd, nconf, &bindaddr, prog, vers,
1280Sstevel@tonic-gate 				sendsz, recvsz);
1290Sstevel@tonic-gate 	if (cl) {
1300Sstevel@tonic-gate 		if (madefd == TRUE) {
1310Sstevel@tonic-gate 			/*
1320Sstevel@tonic-gate 			 * The fd should be closed while destroying the handle.
1330Sstevel@tonic-gate 			 */
134132Srobinson 			(void) CLNT_CONTROL(cl, CLSET_FD_CLOSE, NULL);
1350Sstevel@tonic-gate 			*sockp = fd;
1360Sstevel@tonic-gate 		}
1370Sstevel@tonic-gate 		(void) freenetconfigent(nconf);
138132Srobinson 		(void) mutex_unlock(&rpcsoc_lock);
1390Sstevel@tonic-gate 		return (cl);
1400Sstevel@tonic-gate 	}
1410Sstevel@tonic-gate 	goto err;
1420Sstevel@tonic-gate 
1430Sstevel@tonic-gate syserror:
1440Sstevel@tonic-gate 	rpc_createerr.cf_stat = RPC_SYSTEMERROR;
1450Sstevel@tonic-gate 	rpc_createerr.cf_error.re_errno = errno;
1460Sstevel@tonic-gate 	rpc_createerr.cf_error.re_terrno = t_errno;
1470Sstevel@tonic-gate 
1480Sstevel@tonic-gate err:	if (madefd == TRUE)
1490Sstevel@tonic-gate 		(void) t_close(fd);
1500Sstevel@tonic-gate 	(void) freenetconfigent(nconf);
1510Sstevel@tonic-gate 	if (locked == TRUE)
152132Srobinson 		(void) mutex_unlock(&rpcsoc_lock);
153132Srobinson 	return (NULL);
1540Sstevel@tonic-gate }
1550Sstevel@tonic-gate 
1560Sstevel@tonic-gate CLIENT *
clntudp_bufcreate(struct sockaddr_in * raddr,rpcprog_t prog,rpcvers_t vers,struct timeval wait,int * sockp,uint_t sendsz,uint_t recvsz)157132Srobinson clntudp_bufcreate(struct sockaddr_in *raddr, rpcprog_t prog, rpcvers_t vers,
158132Srobinson 	struct timeval wait, int *sockp, uint_t sendsz, uint_t recvsz)
1590Sstevel@tonic-gate {
1600Sstevel@tonic-gate 	CLIENT *cl;
1610Sstevel@tonic-gate 
1620Sstevel@tonic-gate 	cl = clnt_com_create(raddr, prog, vers, sockp, sendsz, recvsz, "udp");
163132Srobinson 	if (cl == NULL)
164132Srobinson 		return (NULL);
1650Sstevel@tonic-gate 	(void) CLNT_CONTROL(cl, CLSET_RETRY_TIMEOUT, (char *)&wait);
1660Sstevel@tonic-gate 	return (cl);
1670Sstevel@tonic-gate }
1680Sstevel@tonic-gate 
1690Sstevel@tonic-gate CLIENT *
clntudp_create(struct sockaddr_in * raddr,rpcprog_t program,rpcvers_t version,struct timeval wait,int * sockp)170132Srobinson clntudp_create(struct sockaddr_in *raddr, rpcprog_t program, rpcvers_t version,
171132Srobinson 	struct timeval wait, int *sockp)
1720Sstevel@tonic-gate {
173132Srobinson 	return (clntudp_bufcreate(raddr, program, version, wait, sockp,
174132Srobinson 					UDPMSGSIZE, UDPMSGSIZE));
1750Sstevel@tonic-gate }
1760Sstevel@tonic-gate 
1770Sstevel@tonic-gate CLIENT *
clnttcp_create(struct sockaddr_in * raddr,rpcprog_t prog,rpcvers_t vers,int * sockp,uint_t sendsz,uint_t recvsz)178132Srobinson clnttcp_create(struct sockaddr_in *raddr, rpcprog_t prog, rpcvers_t vers,
179132Srobinson 	int *sockp, uint_t sendsz, uint_t recvsz)
1800Sstevel@tonic-gate {
181132Srobinson 	return (clnt_com_create(raddr, prog, vers, sockp, sendsz,
182132Srobinson 			recvsz, "tcp"));
1830Sstevel@tonic-gate }
1840Sstevel@tonic-gate 
1850Sstevel@tonic-gate CLIENT *
clntraw_create(rpcprog_t prog,rpcvers_t vers)186132Srobinson clntraw_create(rpcprog_t prog, rpcvers_t vers)
1870Sstevel@tonic-gate {
188132Srobinson 	return (clnt_raw_create(prog, vers));
1890Sstevel@tonic-gate }
1900Sstevel@tonic-gate 
1910Sstevel@tonic-gate /*
1920Sstevel@tonic-gate  * A common server create routine
1930Sstevel@tonic-gate  */
1940Sstevel@tonic-gate static SVCXPRT *
svc_com_create(int fd,uint_t sendsize,uint_t recvsize,char * netid)195132Srobinson svc_com_create(int fd, uint_t sendsize, uint_t recvsize, char *netid)
1960Sstevel@tonic-gate {
1970Sstevel@tonic-gate 	struct netconfig *nconf;
1980Sstevel@tonic-gate 	SVCXPRT *svc;
1990Sstevel@tonic-gate 	int madefd = FALSE;
2000Sstevel@tonic-gate 	int port;
2010Sstevel@tonic-gate 	int res;
2020Sstevel@tonic-gate 
2030Sstevel@tonic-gate 	if ((nconf = __rpc_getconfip(netid)) == NULL) {
2040Sstevel@tonic-gate 		(void) syslog(LOG_ERR, "Could not get %s transport", netid);
205132Srobinson 		return (NULL);
2060Sstevel@tonic-gate 	}
2070Sstevel@tonic-gate 	if (fd == RPC_ANYSOCK) {
208132Srobinson 		fd = t_open(nconf->nc_device, O_RDWR, NULL);
2090Sstevel@tonic-gate 		if (fd == -1) {
2100Sstevel@tonic-gate 			char errorstr[100];
2110Sstevel@tonic-gate 
2120Sstevel@tonic-gate 			__tli_sys_strerror(errorstr, sizeof (errorstr),
2130Sstevel@tonic-gate 					t_errno, errno);
2140Sstevel@tonic-gate 			(void) syslog(LOG_ERR,
2150Sstevel@tonic-gate 			"svc%s_create: could not open connection : %s", netid,
2160Sstevel@tonic-gate 				    errorstr);
2170Sstevel@tonic-gate 			(void) freenetconfigent(nconf);
218132Srobinson 			return (NULL);
2190Sstevel@tonic-gate 		}
2200Sstevel@tonic-gate 		madefd = TRUE;
2210Sstevel@tonic-gate 	}
2220Sstevel@tonic-gate 
223132Srobinson 	res = __rpc_bindresvport(fd, NULL, &port, 8);
224132Srobinson 	svc = svc_tli_create(fd, nconf, NULL,
2250Sstevel@tonic-gate 				sendsize, recvsize);
2260Sstevel@tonic-gate 	(void) freenetconfigent(nconf);
227132Srobinson 	if (svc == NULL) {
2280Sstevel@tonic-gate 		if (madefd)
2290Sstevel@tonic-gate 			(void) t_close(fd);
230132Srobinson 		return (NULL);
2310Sstevel@tonic-gate 	}
232132Srobinson 	if (res == -1)
233132Srobinson 		/* LINTED pointer cast */
2340Sstevel@tonic-gate 		port = (((struct sockaddr_in *)svc->xp_ltaddr.buf)->sin_port);
2350Sstevel@tonic-gate 	svc->xp_port = ntohs(port);
2360Sstevel@tonic-gate 	return (svc);
2370Sstevel@tonic-gate }
2380Sstevel@tonic-gate 
2390Sstevel@tonic-gate SVCXPRT *
svctcp_create(int fd,uint_t sendsize,uint_t recvsize)240132Srobinson svctcp_create(int fd, uint_t sendsize, uint_t recvsize)
2410Sstevel@tonic-gate {
242132Srobinson 	return (svc_com_create(fd, sendsize, recvsize, "tcp"));
2430Sstevel@tonic-gate }
2440Sstevel@tonic-gate 
2450Sstevel@tonic-gate SVCXPRT *
svcudp_bufcreate(int fd,uint_t sendsz,uint_t recvsz)246132Srobinson svcudp_bufcreate(int fd, uint_t sendsz, uint_t recvsz)
2470Sstevel@tonic-gate {
248132Srobinson 	return (svc_com_create(fd, sendsz, recvsz, "udp"));
2490Sstevel@tonic-gate }
2500Sstevel@tonic-gate 
2510Sstevel@tonic-gate SVCXPRT *
svcfd_create(int fd,uint_t sendsize,uint_t recvsize)252132Srobinson svcfd_create(int fd, uint_t sendsize, uint_t recvsize)
2530Sstevel@tonic-gate {
254132Srobinson 	return (svc_fd_create(fd, sendsize, recvsize));
2550Sstevel@tonic-gate }
2560Sstevel@tonic-gate 
2570Sstevel@tonic-gate 
2580Sstevel@tonic-gate SVCXPRT *
svcudp_create(int fd)259132Srobinson svcudp_create(int fd)
2600Sstevel@tonic-gate {
261132Srobinson 	return (svc_com_create(fd, UDPMSGSIZE, UDPMSGSIZE, "udp"));
2620Sstevel@tonic-gate }
2630Sstevel@tonic-gate 
2640Sstevel@tonic-gate SVCXPRT *
svcraw_create(void)265132Srobinson svcraw_create(void)
2660Sstevel@tonic-gate {
267132Srobinson 	return (svc_raw_create());
2680Sstevel@tonic-gate }
2690Sstevel@tonic-gate 
2700Sstevel@tonic-gate /*
2710Sstevel@tonic-gate  * Bind a fd to a privileged IP port.
2720Sstevel@tonic-gate  * This is slightly different from the code in netdir_options
2730Sstevel@tonic-gate  * because it has a different interface - main thing is that it
2740Sstevel@tonic-gate  * needs to know its own address.  We also wanted to set the qlen.
2750Sstevel@tonic-gate  * t_getname() can be used for those purposes and perhaps job can be done.
2760Sstevel@tonic-gate  */
2770Sstevel@tonic-gate int
__rpc_bindresvport_ipv6(int fd,struct sockaddr * sin,int * portp,int qlen,char * fmly)2780Sstevel@tonic-gate __rpc_bindresvport_ipv6(int fd, struct sockaddr *sin, int *portp, int qlen,
2790Sstevel@tonic-gate 			char *fmly)
2800Sstevel@tonic-gate {
2810Sstevel@tonic-gate 	int res;
2820Sstevel@tonic-gate 	static in_port_t port, *sinport;
2830Sstevel@tonic-gate 	struct sockaddr_in6 myaddr;
2840Sstevel@tonic-gate 	int i;
2850Sstevel@tonic-gate 	struct t_bind tbindstr, *tres;
2860Sstevel@tonic-gate 	struct t_info tinfo;
2870Sstevel@tonic-gate 	extern mutex_t portnum_lock;
2880Sstevel@tonic-gate 
2890Sstevel@tonic-gate 	/* VARIABLES PROTECTED BY portnum_lock: port */
2900Sstevel@tonic-gate 
2910Sstevel@tonic-gate #define	STARTPORT 600
2920Sstevel@tonic-gate #define	ENDPORT (IPPORT_RESERVED - 1)
2930Sstevel@tonic-gate #define	NPORTS	(ENDPORT - STARTPORT + 1)
2940Sstevel@tonic-gate 
2950Sstevel@tonic-gate 	if (sin == 0 && fmly == 0) {
2960Sstevel@tonic-gate 		errno = EINVAL;
2970Sstevel@tonic-gate 		return (-1);
2980Sstevel@tonic-gate 	}
2990Sstevel@tonic-gate 	if (geteuid()) {
3000Sstevel@tonic-gate 		errno = EACCES;
3010Sstevel@tonic-gate 		return (-1);
3020Sstevel@tonic-gate 	}
3030Sstevel@tonic-gate 	if ((i = t_getstate(fd)) != T_UNBND) {
3040Sstevel@tonic-gate 		if (t_errno == TBADF)
3050Sstevel@tonic-gate 			errno = EBADF;
3060Sstevel@tonic-gate 		if (i != -1)
3070Sstevel@tonic-gate 			errno = EISCONN;
3080Sstevel@tonic-gate 		return (-1);
3090Sstevel@tonic-gate 	}
3100Sstevel@tonic-gate 	if (sin == 0) {
3110Sstevel@tonic-gate 		sin = (struct sockaddr *)&myaddr;
3120Sstevel@tonic-gate 		get_myaddress_ipv6(fmly, sin);
3130Sstevel@tonic-gate 	}
3140Sstevel@tonic-gate 	if (sin->sa_family == AF_INET) {
315132Srobinson 		/* LINTED pointer cast */
3160Sstevel@tonic-gate 		sinport = &((struct sockaddr_in *)sin)->sin_port;
3170Sstevel@tonic-gate 	} else if (sin->sa_family == AF_INET6) {
318132Srobinson 		/* LINTED pointer cast */
3190Sstevel@tonic-gate 		sinport = &((struct sockaddr_in6 *)sin)->sin6_port;
3200Sstevel@tonic-gate 	} else {
3210Sstevel@tonic-gate 		errno = EPFNOSUPPORT;
3220Sstevel@tonic-gate 		return (-1);
3230Sstevel@tonic-gate 	}
3240Sstevel@tonic-gate 
3250Sstevel@tonic-gate 	/* Transform sockaddr to netbuf */
3260Sstevel@tonic-gate 	if (t_getinfo(fd, &tinfo) == -1) {
3270Sstevel@tonic-gate 		return (-1);
3280Sstevel@tonic-gate 	}
329132Srobinson 	/* LINTED pointer cast */
3300Sstevel@tonic-gate 	tres = (struct t_bind *)t_alloc(fd, T_BIND, T_ADDR);
331132Srobinson 	if (tres == NULL)
3320Sstevel@tonic-gate 		return (-1);
3330Sstevel@tonic-gate 
3340Sstevel@tonic-gate 	tbindstr.qlen = qlen;
3350Sstevel@tonic-gate 	tbindstr.addr.buf = (char *)sin;
3360Sstevel@tonic-gate 	tbindstr.addr.len = tbindstr.addr.maxlen = __rpc_get_a_size(tinfo.addr);
337132Srobinson 	/* LINTED pointer cast */
3380Sstevel@tonic-gate 	sin = (struct sockaddr *)tbindstr.addr.buf;
3390Sstevel@tonic-gate 
3400Sstevel@tonic-gate 	res = -1;
341132Srobinson 	(void) mutex_lock(&portnum_lock);
3420Sstevel@tonic-gate 	if (port == 0)
3430Sstevel@tonic-gate 		port = (getpid() % NPORTS) + STARTPORT;
3440Sstevel@tonic-gate 	for (i = 0; i < NPORTS; i++) {
3450Sstevel@tonic-gate 		*sinport = htons(port++);
3460Sstevel@tonic-gate 		if (port > ENDPORT)
3470Sstevel@tonic-gate 			port = STARTPORT;
3480Sstevel@tonic-gate 		res = t_bind(fd, &tbindstr, tres);
3490Sstevel@tonic-gate 		if (res == 0) {
3500Sstevel@tonic-gate 			if ((tbindstr.addr.len == tres->addr.len) &&
3510Sstevel@tonic-gate 				(memcmp(tbindstr.addr.buf, tres->addr.buf,
3520Sstevel@tonic-gate 					(int)tres->addr.len) == 0))
3530Sstevel@tonic-gate 				break;
3540Sstevel@tonic-gate 			(void) t_unbind(fd);
3550Sstevel@tonic-gate 			res = -1;
3560Sstevel@tonic-gate 		} else if (t_errno != TSYSERR || errno != EADDRINUSE)
3570Sstevel@tonic-gate 			break;
3580Sstevel@tonic-gate 	}
359132Srobinson 	(void) mutex_unlock(&portnum_lock);
3600Sstevel@tonic-gate 
3610Sstevel@tonic-gate 	if ((portp != NULL) && (res == 0))
3620Sstevel@tonic-gate 		*portp = *sinport;
3630Sstevel@tonic-gate 	(void) t_free((char *)tres, T_BIND);
3640Sstevel@tonic-gate 	return (res);
3650Sstevel@tonic-gate }
3660Sstevel@tonic-gate 
3670Sstevel@tonic-gate int
__rpc_bindresvport(int fd,struct sockaddr_in * sin,int * portp,int qlen)3680Sstevel@tonic-gate __rpc_bindresvport(int fd, struct sockaddr_in *sin, int *portp, int qlen)
3690Sstevel@tonic-gate {
3700Sstevel@tonic-gate 	return (__rpc_bindresvport_ipv6(fd, (struct sockaddr *)sin, portp,
3710Sstevel@tonic-gate 					qlen, NC_INET));
3720Sstevel@tonic-gate }
3730Sstevel@tonic-gate 
3740Sstevel@tonic-gate /*
3750Sstevel@tonic-gate  * Get clients IP address.
3760Sstevel@tonic-gate  * don't use gethostbyname, which would invoke yellow pages
3770Sstevel@tonic-gate  * Remains only for backward compatibility reasons.
3780Sstevel@tonic-gate  * Used mainly by the portmapper so that it can register
3790Sstevel@tonic-gate  * with itself. Also used by pmap*() routines
3800Sstevel@tonic-gate  */
3810Sstevel@tonic-gate void
get_myaddress_ipv6(char * fmly,struct sockaddr * addr)3820Sstevel@tonic-gate get_myaddress_ipv6(char *fmly, struct sockaddr *addr)
3830Sstevel@tonic-gate {
3840Sstevel@tonic-gate 	if (fmly != 0 && strcmp(fmly, NC_INET6) == 0) {
385132Srobinson 		/* LINTED pointer cast */
3860Sstevel@tonic-gate 		struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)addr;
387132Srobinson 		(void) memset(sin6, 0, sizeof (*sin6));
3880Sstevel@tonic-gate 		sin6->sin6_family = AF_INET6;
3890Sstevel@tonic-gate 		sin6->sin6_port = htons(PMAPPORT);
3900Sstevel@tonic-gate 		if (__can_use_af(AF_INET6)) {
3910Sstevel@tonic-gate 			/* Local copy of in6addr_any to avoid -lsocket */
3920Sstevel@tonic-gate 			struct in6_addr in6addr_any = IN6ADDR_ANY_INIT;
3930Sstevel@tonic-gate 			sin6->sin6_addr = in6addr_any;
3940Sstevel@tonic-gate 		} else {
3950Sstevel@tonic-gate 			struct in_addr in4;
3960Sstevel@tonic-gate 			in4.s_addr = INADDR_ANY;
3970Sstevel@tonic-gate 			IN6_INADDR_TO_V4MAPPED(&in4, &sin6->sin6_addr);
3980Sstevel@tonic-gate 		}
3990Sstevel@tonic-gate 	} else {
400132Srobinson 		/* LINTED pointer cast */
4010Sstevel@tonic-gate 		struct sockaddr_in	*sin = (struct sockaddr_in *)addr;
402132Srobinson 		(void) memset(sin, 0, sizeof (*sin));
4030Sstevel@tonic-gate 		sin->sin_family = AF_INET;
4040Sstevel@tonic-gate 		sin->sin_port = htons(PMAPPORT);
4050Sstevel@tonic-gate 		sin->sin_addr.s_addr = INADDR_ANY;
4060Sstevel@tonic-gate 	}
4070Sstevel@tonic-gate }
4080Sstevel@tonic-gate 
4090Sstevel@tonic-gate void
get_myaddress(struct sockaddr_in * addr)4100Sstevel@tonic-gate get_myaddress(struct sockaddr_in *addr)
4110Sstevel@tonic-gate {
4120Sstevel@tonic-gate 	get_myaddress_ipv6(0, (struct sockaddr *)addr);
4130Sstevel@tonic-gate }
4140Sstevel@tonic-gate 
4150Sstevel@tonic-gate /*
4160Sstevel@tonic-gate  * Get port used by specified service on specified host.
4170Sstevel@tonic-gate  * Exists for source compatibility only.
4180Sstevel@tonic-gate  * Obsoleted by rpcb_getaddr().
4190Sstevel@tonic-gate  */
4200Sstevel@tonic-gate ushort_t
getrpcport(char * host,rpcprog_t prognum,rpcvers_t versnum,rpcprot_t proto)4210Sstevel@tonic-gate getrpcport(char *host, rpcprog_t prognum, rpcvers_t versnum,
4220Sstevel@tonic-gate 	rpcprot_t proto)
4230Sstevel@tonic-gate {
4240Sstevel@tonic-gate 	struct sockaddr_in addr;
4250Sstevel@tonic-gate 	struct hostent *hp;
4260Sstevel@tonic-gate 
4270Sstevel@tonic-gate 	if ((hp = gethostbyname(host)) == NULL)
4280Sstevel@tonic-gate 		return (0);
429132Srobinson 	(void) memcpy(&addr.sin_addr, hp->h_addr, hp->h_length);
4300Sstevel@tonic-gate 	addr.sin_family = AF_INET;
4310Sstevel@tonic-gate 	addr.sin_port =  0;
4320Sstevel@tonic-gate 	return (pmap_getport(&addr, prognum, versnum, proto));
4330Sstevel@tonic-gate }
4340Sstevel@tonic-gate 
4350Sstevel@tonic-gate /*
4360Sstevel@tonic-gate  * For connectionless "udp" transport. Obsoleted by rpc_call().
4370Sstevel@tonic-gate  */
4380Sstevel@tonic-gate int
callrpc(char * host,rpcprog_t prognum,rpcvers_t versnum,rpcproc_t procnum,xdrproc_t inproc,char * in,xdrproc_t outproc,char * out)439132Srobinson callrpc(char *host, rpcprog_t prognum, rpcvers_t versnum, rpcproc_t procnum,
440132Srobinson 	xdrproc_t inproc, char *in, xdrproc_t outproc, char *out)
4410Sstevel@tonic-gate {
442132Srobinson 	return ((int)rpc_call(host, prognum, versnum, procnum, inproc,
443132Srobinson 				in, outproc, out, "udp"));
4440Sstevel@tonic-gate }
4450Sstevel@tonic-gate 
4460Sstevel@tonic-gate /*
4470Sstevel@tonic-gate  * For connectionless kind of transport. Obsoleted by rpc_reg()
4480Sstevel@tonic-gate  */
4490Sstevel@tonic-gate int
registerrpc(rpcprog_t prognum,rpcvers_t versnum,rpcproc_t procnum,char * (* progname)(),xdrproc_t inproc,xdrproc_t outproc)450132Srobinson registerrpc(rpcprog_t prognum, rpcvers_t versnum, rpcproc_t procnum,
451132Srobinson 	char *(*progname)(), xdrproc_t inproc, xdrproc_t outproc)
4520Sstevel@tonic-gate {
453132Srobinson 	return (rpc_reg(prognum, versnum, procnum, progname, inproc,
454132Srobinson 				outproc, "udp"));
4550Sstevel@tonic-gate }
4560Sstevel@tonic-gate 
4570Sstevel@tonic-gate /*
4580Sstevel@tonic-gate  * All the following clnt_broadcast stuff is convulated; it supports
4590Sstevel@tonic-gate  * the earlier calling style of the callback function
4600Sstevel@tonic-gate  */
461*3864Sraf static pthread_key_t	clnt_broadcast_key = PTHREAD_ONCE_KEY_NP;
4620Sstevel@tonic-gate static resultproc_t	clnt_broadcast_result_main;
4630Sstevel@tonic-gate 
4640Sstevel@tonic-gate /*
4650Sstevel@tonic-gate  * Need to translate the netbuf address into sockaddr_in address.
4660Sstevel@tonic-gate  * Dont care about netid here.
4670Sstevel@tonic-gate  */
468132Srobinson /* ARGSUSED2 */
4690Sstevel@tonic-gate static bool_t
rpc_wrap_bcast(char * resultp,struct netbuf * addr,struct netconfig * nconf)470132Srobinson rpc_wrap_bcast(char *resultp, struct netbuf *addr, struct netconfig *nconf)
4710Sstevel@tonic-gate {
4720Sstevel@tonic-gate 	resultproc_t clnt_broadcast_result;
4730Sstevel@tonic-gate 
4740Sstevel@tonic-gate 	clnt_broadcast_result = thr_main()? clnt_broadcast_result_main :
4750Sstevel@tonic-gate 		(resultproc_t)pthread_getspecific(clnt_broadcast_key);
476132Srobinson 	return ((*clnt_broadcast_result)(resultp,
477132Srobinson 				/* LINTED pointer cast */
478132Srobinson 				(struct sockaddr_in *)addr->buf));
4790Sstevel@tonic-gate }
4800Sstevel@tonic-gate 
4810Sstevel@tonic-gate /*
4820Sstevel@tonic-gate  * Broadcasts on UDP transport. Obsoleted by rpc_broadcast().
4830Sstevel@tonic-gate  */
4840Sstevel@tonic-gate enum clnt_stat
clnt_broadcast(rpcprog_t prog,rpcvers_t vers,rpcproc_t proc,xdrproc_t xargs,caddr_t argsp,xdrproc_t xresults,caddr_t resultsp,resultproc_t eachresult)485132Srobinson clnt_broadcast(rpcprog_t prog, rpcvers_t vers, rpcproc_t proc, xdrproc_t xargs,
486132Srobinson 	caddr_t argsp, xdrproc_t xresults,
487132Srobinson 	caddr_t resultsp, resultproc_t eachresult)
4880Sstevel@tonic-gate {
489132Srobinson 	if (thr_main()) {
4900Sstevel@tonic-gate 		clnt_broadcast_result_main = eachresult;
491132Srobinson 	} else {
492*3864Sraf 		(void) pthread_key_create_once_np(&clnt_broadcast_key, NULL);
493132Srobinson 		(void) pthread_setspecific(clnt_broadcast_key,
494132Srobinson 							(void *)eachresult);
4950Sstevel@tonic-gate 	}
496132Srobinson 	return (rpc_broadcast(prog, vers, proc, xargs, argsp, xresults,
497132Srobinson 				resultsp, (resultproc_t)rpc_wrap_bcast, "udp"));
4980Sstevel@tonic-gate }
4990Sstevel@tonic-gate 
5000Sstevel@tonic-gate /*
5010Sstevel@tonic-gate  * Create the client des authentication object. Obsoleted by
5020Sstevel@tonic-gate  * authdes_seccreate().
5030Sstevel@tonic-gate  */
5040Sstevel@tonic-gate AUTH *
authdes_create(char * servername,uint_t window,struct sockaddr_in * syncaddr,des_block * ckey)505132Srobinson authdes_create(char *servername, uint_t window, struct sockaddr_in *syncaddr,
506132Srobinson 	des_block *ckey)
5070Sstevel@tonic-gate {
5080Sstevel@tonic-gate 	char *hostname = NULL;
5090Sstevel@tonic-gate 
5100Sstevel@tonic-gate 	if (syncaddr) {
5110Sstevel@tonic-gate 		/*
5120Sstevel@tonic-gate 		 * Change addr to hostname, because that is the way
5130Sstevel@tonic-gate 		 * new interface takes it.
5140Sstevel@tonic-gate 		 */
5150Sstevel@tonic-gate 		struct netconfig *nconf;
5160Sstevel@tonic-gate 		struct netbuf nb_syncaddr;
5170Sstevel@tonic-gate 		struct nd_hostservlist *hlist;
5180Sstevel@tonic-gate 		AUTH *nauth;
5190Sstevel@tonic-gate 		int fd;
5200Sstevel@tonic-gate 		struct t_info tinfo;
5210Sstevel@tonic-gate 
5220Sstevel@tonic-gate 		if ((nconf = __rpc_getconfip("udp")) == NULL &&
5230Sstevel@tonic-gate 		    (nconf = __rpc_getconfip("tcp")) == NULL)
5240Sstevel@tonic-gate 			goto fallback;
5250Sstevel@tonic-gate 
5260Sstevel@tonic-gate 		/* Transform sockaddr_in to netbuf */
5270Sstevel@tonic-gate 		if ((fd = t_open(nconf->nc_device, O_RDWR, &tinfo)) == -1) {
5280Sstevel@tonic-gate 			(void) freenetconfigent(nconf);
5290Sstevel@tonic-gate 			goto fallback;
5300Sstevel@tonic-gate 		}
5310Sstevel@tonic-gate 		(void) t_close(fd);
5320Sstevel@tonic-gate 		nb_syncaddr.maxlen = nb_syncaddr.len =
5330Sstevel@tonic-gate 			__rpc_get_a_size(tinfo.addr);
5340Sstevel@tonic-gate 		nb_syncaddr.buf = (char *)syncaddr;
5350Sstevel@tonic-gate 		if (netdir_getbyaddr(nconf, &hlist, &nb_syncaddr)) {
5360Sstevel@tonic-gate 			(void) freenetconfigent(nconf);
5370Sstevel@tonic-gate 			goto fallback;
5380Sstevel@tonic-gate 		}
5390Sstevel@tonic-gate 		if (hlist && hlist->h_cnt > 0 && hlist->h_hostservs)
5400Sstevel@tonic-gate 			hostname = hlist->h_hostservs->h_host;
5410Sstevel@tonic-gate 		nauth = authdes_seccreate(servername, window, hostname, ckey);
5420Sstevel@tonic-gate 		(void) netdir_free((char *)hlist, ND_HOSTSERVLIST);
5430Sstevel@tonic-gate 		(void) freenetconfigent(nconf);
5440Sstevel@tonic-gate 		return (nauth);
5450Sstevel@tonic-gate 	}
5460Sstevel@tonic-gate fallback:
547132Srobinson 	return (authdes_seccreate(servername, window, hostname, ckey));
5480Sstevel@tonic-gate }
5490Sstevel@tonic-gate #endif /* PORTMAP */
550