xref: /titanic_52/usr/src/cmd/ypcmd/rpc_bootstrap.c (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate  * CDDL HEADER START
3*7c478bd9Sstevel@tonic-gate  *
4*7c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*7c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*7c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*7c478bd9Sstevel@tonic-gate  * with the License.
8*7c478bd9Sstevel@tonic-gate  *
9*7c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*7c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*7c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*7c478bd9Sstevel@tonic-gate  * and limitations under the License.
13*7c478bd9Sstevel@tonic-gate  *
14*7c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*7c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*7c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*7c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*7c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*7c478bd9Sstevel@tonic-gate  *
20*7c478bd9Sstevel@tonic-gate  * CDDL HEADER END
21*7c478bd9Sstevel@tonic-gate  *
22*7c478bd9Sstevel@tonic-gate  * Copyright 2002 Sun Microsystems, Inc.  All rights reserved.
23*7c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
24*7c478bd9Sstevel@tonic-gate  */
25*7c478bd9Sstevel@tonic-gate 
26*7c478bd9Sstevel@tonic-gate /*	Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
27*7c478bd9Sstevel@tonic-gate /*	  All Rights Reserved   */
28*7c478bd9Sstevel@tonic-gate 
29*7c478bd9Sstevel@tonic-gate /*
30*7c478bd9Sstevel@tonic-gate  * Portions of this source code were derived from Berkeley
31*7c478bd9Sstevel@tonic-gate  * under license from the Regents of the University of
32*7c478bd9Sstevel@tonic-gate  * California.
33*7c478bd9Sstevel@tonic-gate  */
34*7c478bd9Sstevel@tonic-gate 
35*7c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
36*7c478bd9Sstevel@tonic-gate 
37*7c478bd9Sstevel@tonic-gate #include <sys/types.h>
38*7c478bd9Sstevel@tonic-gate #include <sys/file.h>
39*7c478bd9Sstevel@tonic-gate #include <stdlib.h>
40*7c478bd9Sstevel@tonic-gate #include <ctype.h>
41*7c478bd9Sstevel@tonic-gate #include <string.h>
42*7c478bd9Sstevel@tonic-gate #include <tiuser.h>
43*7c478bd9Sstevel@tonic-gate #include <netinet/in.h>
44*7c478bd9Sstevel@tonic-gate #include <arpa/inet.h>
45*7c478bd9Sstevel@tonic-gate #include <sys/socket.h>
46*7c478bd9Sstevel@tonic-gate #include <netdir.h>
47*7c478bd9Sstevel@tonic-gate #include <netdb.h>
48*7c478bd9Sstevel@tonic-gate #include <rpc/rpc.h>
49*7c478bd9Sstevel@tonic-gate #include <rpc/pmap_clnt.h>
50*7c478bd9Sstevel@tonic-gate #include <rpcsvc/nis.h>
51*7c478bd9Sstevel@tonic-gate 
52*7c478bd9Sstevel@tonic-gate CLIENT *__clnt_tp_create_bootstrap();
53*7c478bd9Sstevel@tonic-gate int __rpcb_getaddr_bootstrap();
54*7c478bd9Sstevel@tonic-gate struct hostent *__files_gethostbyname();
55*7c478bd9Sstevel@tonic-gate 
56*7c478bd9Sstevel@tonic-gate extern int hostNotKnownLocally;
57*7c478bd9Sstevel@tonic-gate 
58*7c478bd9Sstevel@tonic-gate static char *__map_addr();
59*7c478bd9Sstevel@tonic-gate 
60*7c478bd9Sstevel@tonic-gate /*
61*7c478bd9Sstevel@tonic-gate  * __clnt_tp_create_bootstrap()
62*7c478bd9Sstevel@tonic-gate  *
63*7c478bd9Sstevel@tonic-gate  * This routine is NOT TRANSPORT INDEPENDENT.
64*7c478bd9Sstevel@tonic-gate  *
65*7c478bd9Sstevel@tonic-gate  * It relies on the local /etc/hosts file for hostname to address
66*7c478bd9Sstevel@tonic-gate  * translation and does it itself instead of calling netdir_getbyname
67*7c478bd9Sstevel@tonic-gate  * thereby avoids recursion.
68*7c478bd9Sstevel@tonic-gate  */
69*7c478bd9Sstevel@tonic-gate CLIENT *
70*7c478bd9Sstevel@tonic-gate __clnt_tp_create_bootstrap(hostname, prog, vers, nconf)
71*7c478bd9Sstevel@tonic-gate 	char *hostname;
72*7c478bd9Sstevel@tonic-gate 	u_long prog, vers;
73*7c478bd9Sstevel@tonic-gate 	struct netconfig    *nconf;
74*7c478bd9Sstevel@tonic-gate {
75*7c478bd9Sstevel@tonic-gate 	CLIENT *cl;
76*7c478bd9Sstevel@tonic-gate 	struct netbuf	*svc_taddr;
77*7c478bd9Sstevel@tonic-gate 	struct sockaddr_in6	*sa;
78*7c478bd9Sstevel@tonic-gate 	int fd;
79*7c478bd9Sstevel@tonic-gate 
80*7c478bd9Sstevel@tonic-gate 	if (nconf == (struct netconfig *)NULL) {
81*7c478bd9Sstevel@tonic-gate 		rpc_createerr.cf_stat = RPC_N2AXLATEFAILURE;
82*7c478bd9Sstevel@tonic-gate 		return (NULL);
83*7c478bd9Sstevel@tonic-gate 	}
84*7c478bd9Sstevel@tonic-gate 	if ((fd = t_open(nconf->nc_device, O_RDWR, NULL)) == -1) {
85*7c478bd9Sstevel@tonic-gate 		rpc_createerr.cf_stat = RPC_TLIERROR;
86*7c478bd9Sstevel@tonic-gate 		return (NULL);
87*7c478bd9Sstevel@tonic-gate 	}
88*7c478bd9Sstevel@tonic-gate 	svc_taddr = (struct netbuf *) malloc(sizeof (struct netbuf));
89*7c478bd9Sstevel@tonic-gate 	if (! svc_taddr) {
90*7c478bd9Sstevel@tonic-gate 		rpc_createerr.cf_stat = RPC_SYSTEMERROR;
91*7c478bd9Sstevel@tonic-gate 		t_close(fd);
92*7c478bd9Sstevel@tonic-gate 		return (NULL);
93*7c478bd9Sstevel@tonic-gate 	}
94*7c478bd9Sstevel@tonic-gate 	sa = (struct sockaddr_in6 *)calloc(1, sizeof (*sa));
95*7c478bd9Sstevel@tonic-gate 	if (! sa) {
96*7c478bd9Sstevel@tonic-gate 		rpc_createerr.cf_stat = RPC_SYSTEMERROR;
97*7c478bd9Sstevel@tonic-gate 		t_close(fd);
98*7c478bd9Sstevel@tonic-gate 		free(svc_taddr);
99*7c478bd9Sstevel@tonic-gate 		return (NULL);
100*7c478bd9Sstevel@tonic-gate 	}
101*7c478bd9Sstevel@tonic-gate 	svc_taddr->maxlen = svc_taddr->len = sizeof (*sa);
102*7c478bd9Sstevel@tonic-gate 	svc_taddr->buf = (char *)sa;
103*7c478bd9Sstevel@tonic-gate 	if (__rpcb_getaddr_bootstrap(prog,
104*7c478bd9Sstevel@tonic-gate 		vers, nconf, svc_taddr, hostname) == FALSE) {
105*7c478bd9Sstevel@tonic-gate 		t_close(fd);
106*7c478bd9Sstevel@tonic-gate 		free(svc_taddr);
107*7c478bd9Sstevel@tonic-gate 		free(sa);
108*7c478bd9Sstevel@tonic-gate 		return (NULL);
109*7c478bd9Sstevel@tonic-gate 	}
110*7c478bd9Sstevel@tonic-gate 	rpc_createerr.cf_stat = RPC_SUCCESS;
111*7c478bd9Sstevel@tonic-gate 	cl = __nis_clnt_create(fd, nconf, 0, svc_taddr, 0, prog, vers, 0, 0);
112*7c478bd9Sstevel@tonic-gate 	if (cl == 0) {
113*7c478bd9Sstevel@tonic-gate 		if (rpc_createerr.cf_stat == RPC_SUCCESS)
114*7c478bd9Sstevel@tonic-gate 			rpc_createerr.cf_stat = RPC_TLIERROR;
115*7c478bd9Sstevel@tonic-gate 		t_close(fd);
116*7c478bd9Sstevel@tonic-gate 	}
117*7c478bd9Sstevel@tonic-gate 	free(svc_taddr);
118*7c478bd9Sstevel@tonic-gate 	free(sa);
119*7c478bd9Sstevel@tonic-gate 	return (cl);
120*7c478bd9Sstevel@tonic-gate }
121*7c478bd9Sstevel@tonic-gate 
122*7c478bd9Sstevel@tonic-gate /*
123*7c478bd9Sstevel@tonic-gate  * __rpcb_getaddr_bootstrap()
124*7c478bd9Sstevel@tonic-gate  *
125*7c478bd9Sstevel@tonic-gate  * This is our internal function that replaces rpcb_getaddr(). We
126*7c478bd9Sstevel@tonic-gate  * build our own to prevent calling netdir_getbyname() which could
127*7c478bd9Sstevel@tonic-gate  * recurse to the nameservice.
128*7c478bd9Sstevel@tonic-gate  */
129*7c478bd9Sstevel@tonic-gate int
130*7c478bd9Sstevel@tonic-gate __rpcb_getaddr_bootstrap(program, version, nconf, address, hostname)
131*7c478bd9Sstevel@tonic-gate 	u_long program;
132*7c478bd9Sstevel@tonic-gate 	u_long version;
133*7c478bd9Sstevel@tonic-gate 	struct netconfig *nconf;
134*7c478bd9Sstevel@tonic-gate 	struct netbuf *address; /* populate with the taddr of the service */
135*7c478bd9Sstevel@tonic-gate 	char *hostname;
136*7c478bd9Sstevel@tonic-gate {
137*7c478bd9Sstevel@tonic-gate 	char *svc_uaddr;
138*7c478bd9Sstevel@tonic-gate 	struct hostent *hent;
139*7c478bd9Sstevel@tonic-gate 	struct sockaddr_in *sa;
140*7c478bd9Sstevel@tonic-gate 	struct sockaddr_in6 *sa6;
141*7c478bd9Sstevel@tonic-gate 	struct netbuf rpcb_taddr;
142*7c478bd9Sstevel@tonic-gate 	struct sockaddr_in local_sa;
143*7c478bd9Sstevel@tonic-gate 	struct sockaddr_in6 local_sa6;
144*7c478bd9Sstevel@tonic-gate 	in_port_t inport;
145*7c478bd9Sstevel@tonic-gate 	int p1, p2;
146*7c478bd9Sstevel@tonic-gate 	char *ipaddr, *port;
147*7c478bd9Sstevel@tonic-gate 	int i, ipaddrlen;
148*7c478bd9Sstevel@tonic-gate 
149*7c478bd9Sstevel@tonic-gate 	if (strcmp(nconf->nc_protofmly, NC_INET) != 0 &&
150*7c478bd9Sstevel@tonic-gate 		strcmp(nconf->nc_protofmly, NC_INET6) != 0) {
151*7c478bd9Sstevel@tonic-gate 		rpc_createerr.cf_stat = RPC_UNKNOWNADDR;
152*7c478bd9Sstevel@tonic-gate 		return (FALSE);
153*7c478bd9Sstevel@tonic-gate 	}
154*7c478bd9Sstevel@tonic-gate 
155*7c478bd9Sstevel@tonic-gate 	/* Get the address of the RPCBIND at hostname */
156*7c478bd9Sstevel@tonic-gate 	hent = __files_gethostbyname(hostname, nconf->nc_protofmly);
157*7c478bd9Sstevel@tonic-gate 	if (hent == (struct hostent *)NULL) {
158*7c478bd9Sstevel@tonic-gate 		rpc_createerr.cf_stat = RPC_UNKNOWNHOST;
159*7c478bd9Sstevel@tonic-gate 		hostNotKnownLocally = 1;
160*7c478bd9Sstevel@tonic-gate 		return (FALSE);
161*7c478bd9Sstevel@tonic-gate 	}
162*7c478bd9Sstevel@tonic-gate 
163*7c478bd9Sstevel@tonic-gate 	switch (hent->h_addrtype) {
164*7c478bd9Sstevel@tonic-gate 	case AF_INET:
165*7c478bd9Sstevel@tonic-gate 		local_sa.sin_family = AF_INET;
166*7c478bd9Sstevel@tonic-gate 		local_sa.sin_port = htons(111); /* RPCBIND port */
167*7c478bd9Sstevel@tonic-gate 		memcpy((char *)&(local_sa.sin_addr.s_addr),
168*7c478bd9Sstevel@tonic-gate 			hent->h_addr_list[0], hent->h_length);
169*7c478bd9Sstevel@tonic-gate 		rpcb_taddr.buf = (char *)&local_sa;
170*7c478bd9Sstevel@tonic-gate 		rpcb_taddr.maxlen = sizeof (local_sa);
171*7c478bd9Sstevel@tonic-gate 		rpcb_taddr.len = rpcb_taddr.maxlen;
172*7c478bd9Sstevel@tonic-gate 		break;
173*7c478bd9Sstevel@tonic-gate 	case AF_INET6:
174*7c478bd9Sstevel@tonic-gate 		local_sa6.sin6_family = AF_INET6;
175*7c478bd9Sstevel@tonic-gate 		local_sa6.sin6_port = htons(111); /* RPCBIND port */
176*7c478bd9Sstevel@tonic-gate 		memcpy((char *)&(local_sa6.sin6_addr.s6_addr),
177*7c478bd9Sstevel@tonic-gate 			hent->h_addr_list[0], hent->h_length);
178*7c478bd9Sstevel@tonic-gate 		rpcb_taddr.buf = (char *)&local_sa6;
179*7c478bd9Sstevel@tonic-gate 		rpcb_taddr.maxlen = sizeof (local_sa6);
180*7c478bd9Sstevel@tonic-gate 		rpcb_taddr.len = rpcb_taddr.maxlen;
181*7c478bd9Sstevel@tonic-gate 		break;
182*7c478bd9Sstevel@tonic-gate 	default:
183*7c478bd9Sstevel@tonic-gate 		rpc_createerr.cf_stat = RPC_N2AXLATEFAILURE;
184*7c478bd9Sstevel@tonic-gate 		return (FALSE);
185*7c478bd9Sstevel@tonic-gate 	}
186*7c478bd9Sstevel@tonic-gate 
187*7c478bd9Sstevel@tonic-gate 	svc_uaddr = __map_addr(nconf, &rpcb_taddr, program, version);
188*7c478bd9Sstevel@tonic-gate 	if (! svc_uaddr)
189*7c478bd9Sstevel@tonic-gate 		return (FALSE);
190*7c478bd9Sstevel@tonic-gate 
191*7c478bd9Sstevel@tonic-gate /* do a local uaddr2taddr and stuff in the memory supplied by the caller */
192*7c478bd9Sstevel@tonic-gate 	ipaddr = svc_uaddr;
193*7c478bd9Sstevel@tonic-gate 	ipaddrlen = strlen(ipaddr);
194*7c478bd9Sstevel@tonic-gate 	/* Look for the first '.' starting from the end */
195*7c478bd9Sstevel@tonic-gate 	for (i = ipaddrlen-1; i >= 0; i--)
196*7c478bd9Sstevel@tonic-gate 		if (ipaddr[i] == '.') break;
197*7c478bd9Sstevel@tonic-gate 	/* Find the second dot (still counting from the end) */
198*7c478bd9Sstevel@tonic-gate 	for (i--; i >= 0; i--)
199*7c478bd9Sstevel@tonic-gate 		if (ipaddr[i] == '.') break;
200*7c478bd9Sstevel@tonic-gate 	/* If we didn't find it, the uaddr has a syntax error */
201*7c478bd9Sstevel@tonic-gate 	if (i < 0) {
202*7c478bd9Sstevel@tonic-gate 		rpc_createerr.cf_stat = RPC_N2AXLATEFAILURE;
203*7c478bd9Sstevel@tonic-gate 		return (FALSE);
204*7c478bd9Sstevel@tonic-gate 	}
205*7c478bd9Sstevel@tonic-gate 	port = &ipaddr[i+1];
206*7c478bd9Sstevel@tonic-gate 	ipaddr[i] = '\0';
207*7c478bd9Sstevel@tonic-gate 	sscanf(port, "%d.%d", &p1, &p2);
208*7c478bd9Sstevel@tonic-gate 	inport = (p1 << 8) + p2;
209*7c478bd9Sstevel@tonic-gate 	if (hent->h_addrtype == AF_INET) {
210*7c478bd9Sstevel@tonic-gate 		sa = (struct sockaddr_in *)address->buf;
211*7c478bd9Sstevel@tonic-gate 		address->len = sizeof (*sa);
212*7c478bd9Sstevel@tonic-gate 		if (inet_pton(AF_INET, ipaddr, &sa->sin_addr) != 1) {
213*7c478bd9Sstevel@tonic-gate 			rpc_createerr.cf_stat = RPC_N2AXLATEFAILURE;
214*7c478bd9Sstevel@tonic-gate 			return (FALSE);
215*7c478bd9Sstevel@tonic-gate 		}
216*7c478bd9Sstevel@tonic-gate 		sa->sin_port = htons(inport);
217*7c478bd9Sstevel@tonic-gate 		sa->sin_family = AF_INET;
218*7c478bd9Sstevel@tonic-gate 	} else {
219*7c478bd9Sstevel@tonic-gate 		sa6 = (struct sockaddr_in6 *)address->buf;
220*7c478bd9Sstevel@tonic-gate 		address->len = sizeof (*sa6);
221*7c478bd9Sstevel@tonic-gate 		if (inet_pton(AF_INET6, ipaddr, &sa6->sin6_addr) != 1) {
222*7c478bd9Sstevel@tonic-gate 			rpc_createerr.cf_stat = RPC_N2AXLATEFAILURE;
223*7c478bd9Sstevel@tonic-gate 			return (FALSE);
224*7c478bd9Sstevel@tonic-gate 		}
225*7c478bd9Sstevel@tonic-gate 		sa6->sin6_port = htons(inport);
226*7c478bd9Sstevel@tonic-gate 		sa6->sin6_family = AF_INET6;
227*7c478bd9Sstevel@tonic-gate 	}
228*7c478bd9Sstevel@tonic-gate 	return (TRUE);
229*7c478bd9Sstevel@tonic-gate }
230*7c478bd9Sstevel@tonic-gate 
231*7c478bd9Sstevel@tonic-gate /*
232*7c478bd9Sstevel@tonic-gate  * __map_addr()
233*7c478bd9Sstevel@tonic-gate  *
234*7c478bd9Sstevel@tonic-gate  */
235*7c478bd9Sstevel@tonic-gate static char *
236*7c478bd9Sstevel@tonic-gate __map_addr(nc, rpcb_taddr, prog, ver)
237*7c478bd9Sstevel@tonic-gate 	struct netconfig	*nc;		/* Our transport	*/
238*7c478bd9Sstevel@tonic-gate 	struct netbuf	*rpcb_taddr; /* RPCBIND address */
239*7c478bd9Sstevel@tonic-gate 	u_long			prog, ver;	/* Name service Prog/vers */
240*7c478bd9Sstevel@tonic-gate {
241*7c478bd9Sstevel@tonic-gate 	register CLIENT *client;
242*7c478bd9Sstevel@tonic-gate 	RPCB 		parms;		/* Parameters for RPC binder	  */
243*7c478bd9Sstevel@tonic-gate 	enum clnt_stat	clnt_st;	/* Result from the rpc call	  */
244*7c478bd9Sstevel@tonic-gate 	int		fd;		/* Stream file descriptor	  */
245*7c478bd9Sstevel@tonic-gate 	char 		*ua = NULL;	/* Universal address of service	  */
246*7c478bd9Sstevel@tonic-gate 	struct timeval	tv;		/* Timeout for our rpcb call	  */
247*7c478bd9Sstevel@tonic-gate 
248*7c478bd9Sstevel@tonic-gate 	/*
249*7c478bd9Sstevel@tonic-gate 	 * First we open a connection to the remote rpcbind process.
250*7c478bd9Sstevel@tonic-gate 	 */
251*7c478bd9Sstevel@tonic-gate 	if ((fd = t_open(nc->nc_device, O_RDWR, NULL)) == -1) {
252*7c478bd9Sstevel@tonic-gate 		rpc_createerr.cf_stat = RPC_TLIERROR;
253*7c478bd9Sstevel@tonic-gate 		return (NULL);
254*7c478bd9Sstevel@tonic-gate 	}
255*7c478bd9Sstevel@tonic-gate 
256*7c478bd9Sstevel@tonic-gate 	client = __nis_clnt_create(fd, nc, 0, rpcb_taddr, 0,
257*7c478bd9Sstevel@tonic-gate 					RPCBPROG, RPCBVERS, 0, 0);
258*7c478bd9Sstevel@tonic-gate 	if (! client) {
259*7c478bd9Sstevel@tonic-gate 		t_close(fd);
260*7c478bd9Sstevel@tonic-gate 		rpc_createerr.cf_stat = RPC_TLIERROR;
261*7c478bd9Sstevel@tonic-gate 		return (NULL);
262*7c478bd9Sstevel@tonic-gate 	}
263*7c478bd9Sstevel@tonic-gate 
264*7c478bd9Sstevel@tonic-gate 	/*
265*7c478bd9Sstevel@tonic-gate 	 * Now make the call to get the NIS service address.
266*7c478bd9Sstevel@tonic-gate 	 */
267*7c478bd9Sstevel@tonic-gate 	tv.tv_sec = 10;
268*7c478bd9Sstevel@tonic-gate 	tv.tv_usec = 0;
269*7c478bd9Sstevel@tonic-gate 	parms.r_prog = prog;
270*7c478bd9Sstevel@tonic-gate 	parms.r_vers = ver;
271*7c478bd9Sstevel@tonic-gate 	parms.r_netid = nc->nc_netid;	/* not needed */
272*7c478bd9Sstevel@tonic-gate 	parms.r_addr = "";	/* not needed; just for xdring */
273*7c478bd9Sstevel@tonic-gate 	parms.r_owner = "";	/* not needed; just for xdring */
274*7c478bd9Sstevel@tonic-gate 	clnt_st = clnt_call(client, RPCBPROC_GETADDR, xdr_rpcb, (char *)&parms,
275*7c478bd9Sstevel@tonic-gate 					    xdr_wrapstring, (char *)&ua, tv);
276*7c478bd9Sstevel@tonic-gate 
277*7c478bd9Sstevel@tonic-gate 	rpc_createerr.cf_stat = clnt_st;
278*7c478bd9Sstevel@tonic-gate 	if (clnt_st == RPC_SUCCESS) {
279*7c478bd9Sstevel@tonic-gate 
280*7c478bd9Sstevel@tonic-gate 		clnt_destroy(client);
281*7c478bd9Sstevel@tonic-gate 		t_close(fd);
282*7c478bd9Sstevel@tonic-gate 		if (*ua == '\0') {
283*7c478bd9Sstevel@tonic-gate 			xdr_free(xdr_wrapstring, (char *)&ua);
284*7c478bd9Sstevel@tonic-gate 			return (NULL);
285*7c478bd9Sstevel@tonic-gate 		}
286*7c478bd9Sstevel@tonic-gate 		return (ua);
287*7c478bd9Sstevel@tonic-gate 	} else if (((clnt_st == RPC_PROGVERSMISMATCH) ||
288*7c478bd9Sstevel@tonic-gate 			(clnt_st == RPC_PROGUNAVAIL) ||
289*7c478bd9Sstevel@tonic-gate 			(clnt_st == RPC_TIMEDOUT)) &&
290*7c478bd9Sstevel@tonic-gate 			(strcmp(nc->nc_protofmly, NC_INET) == 0)) {
291*7c478bd9Sstevel@tonic-gate 		/*
292*7c478bd9Sstevel@tonic-gate 		 * version 3 not available. Try version 2
293*7c478bd9Sstevel@tonic-gate 		 * The assumption here is that the netbuf
294*7c478bd9Sstevel@tonic-gate 		 * is arranged in the sockaddr_in
295*7c478bd9Sstevel@tonic-gate 		 * style for IP cases.
296*7c478bd9Sstevel@tonic-gate 		 */
297*7c478bd9Sstevel@tonic-gate 		u_short	port;
298*7c478bd9Sstevel@tonic-gate 		struct sockaddr_in	*sa;
299*7c478bd9Sstevel@tonic-gate 		struct netbuf 		remote;
300*7c478bd9Sstevel@tonic-gate 		int		protocol;
301*7c478bd9Sstevel@tonic-gate 		char	buf[32];
302*7c478bd9Sstevel@tonic-gate 		char	*res;
303*7c478bd9Sstevel@tonic-gate 
304*7c478bd9Sstevel@tonic-gate 		clnt_control(client, CLGET_SVC_ADDR, (char *) &remote);
305*7c478bd9Sstevel@tonic-gate 		sa = (struct sockaddr_in *)(remote.buf);
306*7c478bd9Sstevel@tonic-gate 		protocol = strcmp(nc->nc_proto, NC_TCP) ?
307*7c478bd9Sstevel@tonic-gate 				IPPROTO_UDP : IPPROTO_TCP;
308*7c478bd9Sstevel@tonic-gate 		port = (u_short) pmap_getport(sa, prog, ver, protocol);
309*7c478bd9Sstevel@tonic-gate 
310*7c478bd9Sstevel@tonic-gate 		if (port != 0) {
311*7c478bd9Sstevel@tonic-gate 			/* print s_addr (and port) in host byte order */
312*7c478bd9Sstevel@tonic-gate 			sa->sin_addr.s_addr = ntohl(sa->sin_addr.s_addr);
313*7c478bd9Sstevel@tonic-gate 			sprintf(buf, "%d.%d.%d.%d.%d.%d",
314*7c478bd9Sstevel@tonic-gate 				(sa->sin_addr.s_addr >> 24) & 0xff,
315*7c478bd9Sstevel@tonic-gate 				(sa->sin_addr.s_addr >> 16) & 0xff,
316*7c478bd9Sstevel@tonic-gate 				(sa->sin_addr.s_addr >>  8) & 0xff,
317*7c478bd9Sstevel@tonic-gate 				(sa->sin_addr.s_addr) & 0xff,
318*7c478bd9Sstevel@tonic-gate 				(port >> 8) & 0xff,
319*7c478bd9Sstevel@tonic-gate 				port & 0xff);
320*7c478bd9Sstevel@tonic-gate 			res = strdup(buf);
321*7c478bd9Sstevel@tonic-gate 			if (res != 0) {
322*7c478bd9Sstevel@tonic-gate 				rpc_createerr.cf_stat = RPC_SUCCESS;
323*7c478bd9Sstevel@tonic-gate 			} else {
324*7c478bd9Sstevel@tonic-gate 				rpc_createerr.cf_stat = RPC_SYSTEMERROR;
325*7c478bd9Sstevel@tonic-gate 			}
326*7c478bd9Sstevel@tonic-gate 		} else {
327*7c478bd9Sstevel@tonic-gate 			rpc_createerr.cf_stat = RPC_UNKNOWNADDR;
328*7c478bd9Sstevel@tonic-gate 			res = NULL;
329*7c478bd9Sstevel@tonic-gate 		}
330*7c478bd9Sstevel@tonic-gate 		clnt_destroy(client);
331*7c478bd9Sstevel@tonic-gate 		t_close(fd);
332*7c478bd9Sstevel@tonic-gate 		return (res);
333*7c478bd9Sstevel@tonic-gate 	}
334*7c478bd9Sstevel@tonic-gate 	clnt_destroy(client);
335*7c478bd9Sstevel@tonic-gate 	t_close(fd);
336*7c478bd9Sstevel@tonic-gate 	return (NULL);
337*7c478bd9Sstevel@tonic-gate }
338*7c478bd9Sstevel@tonic-gate 
339*7c478bd9Sstevel@tonic-gate #define	bcmp(s1, s2, len)	memcmp(s1, s2, len)
340*7c478bd9Sstevel@tonic-gate #define	bcopy(s1, s2, len)	memcpy(s2, s1, len)
341*7c478bd9Sstevel@tonic-gate 
342*7c478bd9Sstevel@tonic-gate #define	MAXALIASES	35
343*7c478bd9Sstevel@tonic-gate 
344*7c478bd9Sstevel@tonic-gate static char line[BUFSIZ+1];
345*7c478bd9Sstevel@tonic-gate static char hostaddr[sizeof (struct in6_addr)];
346*7c478bd9Sstevel@tonic-gate static struct hostent host;
347*7c478bd9Sstevel@tonic-gate static char *host_aliases[MAXALIASES];
348*7c478bd9Sstevel@tonic-gate static char *host_addrs[] = {
349*7c478bd9Sstevel@tonic-gate 	hostaddr,
350*7c478bd9Sstevel@tonic-gate 	NULL
351*7c478bd9Sstevel@tonic-gate };
352*7c478bd9Sstevel@tonic-gate 
353*7c478bd9Sstevel@tonic-gate static char *_hosts6[] = { "/etc/inet/ipnodes", 0 };
354*7c478bd9Sstevel@tonic-gate static char *_hosts4[] = { "/etc/inet/ipnodes", "/etc/hosts", 0 };
355*7c478bd9Sstevel@tonic-gate 
356*7c478bd9Sstevel@tonic-gate static char *any();
357*7c478bd9Sstevel@tonic-gate 
358*7c478bd9Sstevel@tonic-gate static struct hostent *__files_gethostent();
359*7c478bd9Sstevel@tonic-gate 
360*7c478bd9Sstevel@tonic-gate struct hostent *
361*7c478bd9Sstevel@tonic-gate __files_gethostbyname(char *nam, char *fmly)
362*7c478bd9Sstevel@tonic-gate {
363*7c478bd9Sstevel@tonic-gate 	register struct hostent *hp;
364*7c478bd9Sstevel@tonic-gate 	register char **cp;
365*7c478bd9Sstevel@tonic-gate 	char **file;
366*7c478bd9Sstevel@tonic-gate 	FILE *hostf;
367*7c478bd9Sstevel@tonic-gate 	sa_family_t af;
368*7c478bd9Sstevel@tonic-gate 
369*7c478bd9Sstevel@tonic-gate 	if (strcmp(fmly, NC_INET) == 0) {
370*7c478bd9Sstevel@tonic-gate 		af = AF_INET;
371*7c478bd9Sstevel@tonic-gate 		file = _hosts4;
372*7c478bd9Sstevel@tonic-gate 	} else if (strcmp(fmly, NC_INET6) == 0) {
373*7c478bd9Sstevel@tonic-gate 		af = AF_INET6;
374*7c478bd9Sstevel@tonic-gate 		file = _hosts6;
375*7c478bd9Sstevel@tonic-gate 	} else {
376*7c478bd9Sstevel@tonic-gate 		return (0);
377*7c478bd9Sstevel@tonic-gate 	}
378*7c478bd9Sstevel@tonic-gate 
379*7c478bd9Sstevel@tonic-gate 	for (; *file != 0; file++) {
380*7c478bd9Sstevel@tonic-gate 
381*7c478bd9Sstevel@tonic-gate 		if ((hostf = fopen(*file, "r")) == 0)
382*7c478bd9Sstevel@tonic-gate 			continue;
383*7c478bd9Sstevel@tonic-gate 
384*7c478bd9Sstevel@tonic-gate 		while (hp = __files_gethostent(hostf)) {
385*7c478bd9Sstevel@tonic-gate 			if (hp->h_addrtype != af)
386*7c478bd9Sstevel@tonic-gate 				continue;
387*7c478bd9Sstevel@tonic-gate 			if (strcasecmp(hp->h_name, nam) == 0) {
388*7c478bd9Sstevel@tonic-gate 				(void) fclose(hostf);
389*7c478bd9Sstevel@tonic-gate 				return (hp);
390*7c478bd9Sstevel@tonic-gate 			}
391*7c478bd9Sstevel@tonic-gate 			for (cp = hp->h_aliases; cp != 0 && *cp != 0; cp++)
392*7c478bd9Sstevel@tonic-gate 				if (strcasecmp(*cp, nam) == 0) {
393*7c478bd9Sstevel@tonic-gate 					(void) fclose(hostf);
394*7c478bd9Sstevel@tonic-gate 					return (hp);
395*7c478bd9Sstevel@tonic-gate 				}
396*7c478bd9Sstevel@tonic-gate 		}
397*7c478bd9Sstevel@tonic-gate 
398*7c478bd9Sstevel@tonic-gate 		(void) fclose(hostf);
399*7c478bd9Sstevel@tonic-gate 	}
400*7c478bd9Sstevel@tonic-gate 
401*7c478bd9Sstevel@tonic-gate 	return (0);
402*7c478bd9Sstevel@tonic-gate }
403*7c478bd9Sstevel@tonic-gate 
404*7c478bd9Sstevel@tonic-gate #define	isV6Addr(s)	(strchr(s, (int)':') != 0)
405*7c478bd9Sstevel@tonic-gate 
406*7c478bd9Sstevel@tonic-gate static struct hostent *
407*7c478bd9Sstevel@tonic-gate __files_gethostent(FILE *hostf)
408*7c478bd9Sstevel@tonic-gate {
409*7c478bd9Sstevel@tonic-gate 	char *p;
410*7c478bd9Sstevel@tonic-gate 	register char *cp, **q;
411*7c478bd9Sstevel@tonic-gate 	struct in6_addr in6;
412*7c478bd9Sstevel@tonic-gate 	struct in_addr in4;
413*7c478bd9Sstevel@tonic-gate 	void *addr;
414*7c478bd9Sstevel@tonic-gate 	sa_family_t af;
415*7c478bd9Sstevel@tonic-gate 	int len;
416*7c478bd9Sstevel@tonic-gate 
417*7c478bd9Sstevel@tonic-gate 	if (hostf == NULL)
418*7c478bd9Sstevel@tonic-gate 		return (NULL);
419*7c478bd9Sstevel@tonic-gate again:
420*7c478bd9Sstevel@tonic-gate 	if ((p = fgets(line, BUFSIZ, hostf)) == NULL)
421*7c478bd9Sstevel@tonic-gate 		return (NULL);
422*7c478bd9Sstevel@tonic-gate 	if (*p == '#')
423*7c478bd9Sstevel@tonic-gate 		goto again;
424*7c478bd9Sstevel@tonic-gate 	cp = any(p, "#\n");
425*7c478bd9Sstevel@tonic-gate 	if (cp == NULL)
426*7c478bd9Sstevel@tonic-gate 		goto again;
427*7c478bd9Sstevel@tonic-gate 	*cp = '\0';
428*7c478bd9Sstevel@tonic-gate 	cp = any(p, " \t");
429*7c478bd9Sstevel@tonic-gate 	if (cp == NULL)
430*7c478bd9Sstevel@tonic-gate 		goto again;
431*7c478bd9Sstevel@tonic-gate 	*cp++ = '\0';
432*7c478bd9Sstevel@tonic-gate 	/* THIS STUFF IS INTERNET SPECIFIC */
433*7c478bd9Sstevel@tonic-gate 	host.h_addr_list = host_addrs;
434*7c478bd9Sstevel@tonic-gate 	if (isV6Addr(p)) {
435*7c478bd9Sstevel@tonic-gate 		af = AF_INET6;
436*7c478bd9Sstevel@tonic-gate 		addr = (void *)&in6;
437*7c478bd9Sstevel@tonic-gate 		len = sizeof (in6);
438*7c478bd9Sstevel@tonic-gate 	} else {
439*7c478bd9Sstevel@tonic-gate 		af = AF_INET;
440*7c478bd9Sstevel@tonic-gate 		addr = (void *)&in4;
441*7c478bd9Sstevel@tonic-gate 		len = sizeof (in4);
442*7c478bd9Sstevel@tonic-gate 	}
443*7c478bd9Sstevel@tonic-gate 	if (inet_pton(af, p, addr) != 1)
444*7c478bd9Sstevel@tonic-gate 		goto again;
445*7c478bd9Sstevel@tonic-gate 	bcopy(addr, host.h_addr_list[0], len);
446*7c478bd9Sstevel@tonic-gate 	host.h_length = len;
447*7c478bd9Sstevel@tonic-gate 	host.h_addrtype = af;
448*7c478bd9Sstevel@tonic-gate 	while (*cp == ' ' || *cp == '\t')
449*7c478bd9Sstevel@tonic-gate 		cp++;
450*7c478bd9Sstevel@tonic-gate 	host.h_name = cp;
451*7c478bd9Sstevel@tonic-gate 	q = host.h_aliases = host_aliases;
452*7c478bd9Sstevel@tonic-gate 	cp = any(cp, " \t");
453*7c478bd9Sstevel@tonic-gate 	if (cp != NULL)
454*7c478bd9Sstevel@tonic-gate 		*cp++ = '\0';
455*7c478bd9Sstevel@tonic-gate 	while (cp && *cp) {
456*7c478bd9Sstevel@tonic-gate 		if (*cp == ' ' || *cp == '\t') {
457*7c478bd9Sstevel@tonic-gate 			cp++;
458*7c478bd9Sstevel@tonic-gate 			continue;
459*7c478bd9Sstevel@tonic-gate 		}
460*7c478bd9Sstevel@tonic-gate 		if (q < &host_aliases[MAXALIASES - 1])
461*7c478bd9Sstevel@tonic-gate 			*q++ = cp;
462*7c478bd9Sstevel@tonic-gate 		cp = any(cp, " \t");
463*7c478bd9Sstevel@tonic-gate 		if (cp != NULL)
464*7c478bd9Sstevel@tonic-gate 			*cp++ = '\0';
465*7c478bd9Sstevel@tonic-gate 	}
466*7c478bd9Sstevel@tonic-gate 	*q = NULL;
467*7c478bd9Sstevel@tonic-gate 	return (&host);
468*7c478bd9Sstevel@tonic-gate }
469*7c478bd9Sstevel@tonic-gate 
470*7c478bd9Sstevel@tonic-gate static char *
471*7c478bd9Sstevel@tonic-gate any(cp, match)
472*7c478bd9Sstevel@tonic-gate 	register char *cp;
473*7c478bd9Sstevel@tonic-gate 	char *match;
474*7c478bd9Sstevel@tonic-gate {
475*7c478bd9Sstevel@tonic-gate 	register char *mp, c;
476*7c478bd9Sstevel@tonic-gate 
477*7c478bd9Sstevel@tonic-gate 	while (c = *cp) {
478*7c478bd9Sstevel@tonic-gate 		for (mp = match; *mp; mp++)
479*7c478bd9Sstevel@tonic-gate 			if (*mp == c)
480*7c478bd9Sstevel@tonic-gate 				return (cp);
481*7c478bd9Sstevel@tonic-gate 		cp++;
482*7c478bd9Sstevel@tonic-gate 	}
483*7c478bd9Sstevel@tonic-gate 	return ((char *)0);
484*7c478bd9Sstevel@tonic-gate }
485