xref: /titanic_44/usr/src/lib/librdc/common/netaddrs.c (revision fcf3ce441efd61da9bb2884968af01cb7c1452cc)
1*fcf3ce44SJohn Forte /*
2*fcf3ce44SJohn Forte  * CDDL HEADER START
3*fcf3ce44SJohn Forte  *
4*fcf3ce44SJohn Forte  * The contents of this file are subject to the terms of the
5*fcf3ce44SJohn Forte  * Common Development and Distribution License (the "License").
6*fcf3ce44SJohn Forte  * You may not use this file except in compliance with the License.
7*fcf3ce44SJohn Forte  *
8*fcf3ce44SJohn Forte  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*fcf3ce44SJohn Forte  * or http://www.opensolaris.org/os/licensing.
10*fcf3ce44SJohn Forte  * See the License for the specific language governing permissions
11*fcf3ce44SJohn Forte  * and limitations under the License.
12*fcf3ce44SJohn Forte  *
13*fcf3ce44SJohn Forte  * When distributing Covered Code, include this CDDL HEADER in each
14*fcf3ce44SJohn Forte  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*fcf3ce44SJohn Forte  * If applicable, add the following below this CDDL HEADER, with the
16*fcf3ce44SJohn Forte  * fields enclosed by brackets "[]" replaced with your own identifying
17*fcf3ce44SJohn Forte  * information: Portions Copyright [yyyy] [name of copyright owner]
18*fcf3ce44SJohn Forte  *
19*fcf3ce44SJohn Forte  * CDDL HEADER END
20*fcf3ce44SJohn Forte  */
21*fcf3ce44SJohn Forte /*
22*fcf3ce44SJohn Forte  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
23*fcf3ce44SJohn Forte  * Use is subject to license terms.
24*fcf3ce44SJohn Forte  */
25*fcf3ce44SJohn Forte 
26*fcf3ce44SJohn Forte #include <locale.h>
27*fcf3ce44SJohn Forte #include <stdio.h>
28*fcf3ce44SJohn Forte #include <string.h>
29*fcf3ce44SJohn Forte #include <memory.h>
30*fcf3ce44SJohn Forte #include <varargs.h>
31*fcf3ce44SJohn Forte #include <unistd.h>
32*fcf3ce44SJohn Forte #include <ctype.h>
33*fcf3ce44SJohn Forte #include <stdlib.h>
34*fcf3ce44SJohn Forte #include <signal.h>
35*fcf3ce44SJohn Forte #include <sys/param.h>
36*fcf3ce44SJohn Forte #include <rpc/rpc.h>
37*fcf3ce44SJohn Forte #include <errno.h>
38*fcf3ce44SJohn Forte #include <sys/stat.h>
39*fcf3ce44SJohn Forte #include <netdb.h>
40*fcf3ce44SJohn Forte #include <sys/pathconf.h>
41*fcf3ce44SJohn Forte #include <netdir.h>
42*fcf3ce44SJohn Forte #include <netconfig.h>
43*fcf3ce44SJohn Forte #include <sys/sockio.h>
44*fcf3ce44SJohn Forte #include <net/if.h>
45*fcf3ce44SJohn Forte #include <syslog.h>
46*fcf3ce44SJohn Forte #include <netinet/in.h>
47*fcf3ce44SJohn Forte #include <nfs/nfs_sec.h>
48*fcf3ce44SJohn Forte #include <strings.h>
49*fcf3ce44SJohn Forte #include <sys/nsctl/rdc_prot.h>
50*fcf3ce44SJohn Forte #include <nsctl.h>
51*fcf3ce44SJohn Forte 
52*fcf3ce44SJohn Forte #include "librdc.h"
53*fcf3ce44SJohn Forte 
54*fcf3ce44SJohn Forte #define	MAXIFS 32
55*fcf3ce44SJohn Forte 
56*fcf3ce44SJohn Forte /* number of transports to try */
57*fcf3ce44SJohn Forte #define	MNT_PREF_LISTLEN	2
58*fcf3ce44SJohn Forte #define	FIRST_TRY		1
59*fcf3ce44SJohn Forte #define	SECOND_TRY		2
60*fcf3ce44SJohn Forte 
61*fcf3ce44SJohn Forte 
62*fcf3ce44SJohn Forte int
Is_ipv6present(void)63*fcf3ce44SJohn Forte Is_ipv6present(void)
64*fcf3ce44SJohn Forte {
65*fcf3ce44SJohn Forte #ifdef AF_INET6
66*fcf3ce44SJohn Forte 	int sock;
67*fcf3ce44SJohn Forte 	struct lifnum lifn;
68*fcf3ce44SJohn Forte 
69*fcf3ce44SJohn Forte 	sock = socket(AF_INET6, SOCK_DGRAM, 0);
70*fcf3ce44SJohn Forte 	if (sock < 0)
71*fcf3ce44SJohn Forte 		return (0);
72*fcf3ce44SJohn Forte 
73*fcf3ce44SJohn Forte 	lifn.lifn_family = AF_INET6;
74*fcf3ce44SJohn Forte 	lifn.lifn_flags = 0;
75*fcf3ce44SJohn Forte 	if (ioctl(sock, SIOCGLIFNUM, (char *)&lifn) < 0) {
76*fcf3ce44SJohn Forte 		close(sock);
77*fcf3ce44SJohn Forte 		return (0);
78*fcf3ce44SJohn Forte 	}
79*fcf3ce44SJohn Forte 	close(sock);
80*fcf3ce44SJohn Forte 	if (lifn.lifn_count == 0)
81*fcf3ce44SJohn Forte 		return (0);
82*fcf3ce44SJohn Forte 	return (1);
83*fcf3ce44SJohn Forte #else
84*fcf3ce44SJohn Forte 	return (0);
85*fcf3ce44SJohn Forte #endif
86*fcf3ce44SJohn Forte }
87*fcf3ce44SJohn Forte 
88*fcf3ce44SJohn Forte /*
89*fcf3ce44SJohn Forte  * The following is stolen from autod_nfs.c
90*fcf3ce44SJohn Forte  */
91*fcf3ce44SJohn Forte static void
getmyaddrs(struct ifconf * ifc)92*fcf3ce44SJohn Forte getmyaddrs(struct ifconf *ifc)
93*fcf3ce44SJohn Forte {
94*fcf3ce44SJohn Forte 	int sock;
95*fcf3ce44SJohn Forte 	int numifs;
96*fcf3ce44SJohn Forte 	char *buf;
97*fcf3ce44SJohn Forte 	int family;
98*fcf3ce44SJohn Forte 
99*fcf3ce44SJohn Forte 	ifc->ifc_buf = NULL;
100*fcf3ce44SJohn Forte 	ifc->ifc_len = 0;
101*fcf3ce44SJohn Forte 
102*fcf3ce44SJohn Forte #ifdef AF_INET6
103*fcf3ce44SJohn Forte 	family = AF_INET6;
104*fcf3ce44SJohn Forte #else
105*fcf3ce44SJohn Forte 	family = AF_INET;
106*fcf3ce44SJohn Forte #endif
107*fcf3ce44SJohn Forte 	if ((sock = socket(family, SOCK_DGRAM, 0)) < 0) {
108*fcf3ce44SJohn Forte #ifdef DEBUG
109*fcf3ce44SJohn Forte 		perror("getmyaddrs(): socket");
110*fcf3ce44SJohn Forte #endif
111*fcf3ce44SJohn Forte 		return;
112*fcf3ce44SJohn Forte 	}
113*fcf3ce44SJohn Forte 
114*fcf3ce44SJohn Forte 	if (ioctl(sock, SIOCGIFNUM, (char *)&numifs) < 0) {
115*fcf3ce44SJohn Forte #ifdef DEBUG
116*fcf3ce44SJohn Forte 		perror("getmyaddrs(): SIOCGIFNUM");
117*fcf3ce44SJohn Forte #endif
118*fcf3ce44SJohn Forte 		numifs = MAXIFS;
119*fcf3ce44SJohn Forte 	}
120*fcf3ce44SJohn Forte 
121*fcf3ce44SJohn Forte 	buf = (char *)malloc(numifs * sizeof (struct ifreq));
122*fcf3ce44SJohn Forte 	if (buf == NULL) {
123*fcf3ce44SJohn Forte #ifdef DEBUG
124*fcf3ce44SJohn Forte 		fprintf(stderr, "getmyaddrs(): malloc failed\n");
125*fcf3ce44SJohn Forte #endif
126*fcf3ce44SJohn Forte 		(void) close(sock);
127*fcf3ce44SJohn Forte 		return;
128*fcf3ce44SJohn Forte 	}
129*fcf3ce44SJohn Forte 
130*fcf3ce44SJohn Forte 	ifc->ifc_buf = buf;
131*fcf3ce44SJohn Forte 	ifc->ifc_len = numifs * sizeof (struct ifreq);
132*fcf3ce44SJohn Forte 
133*fcf3ce44SJohn Forte 	if (ioctl(sock, SIOCGIFCONF, (char *)ifc) < 0) {
134*fcf3ce44SJohn Forte #ifdef DEBUG
135*fcf3ce44SJohn Forte 		perror("getmyaddrs(): SIOCGIFCONF");
136*fcf3ce44SJohn Forte #else
137*fcf3ce44SJohn Forte 		;
138*fcf3ce44SJohn Forte 		/*EMPTY*/
139*fcf3ce44SJohn Forte #endif
140*fcf3ce44SJohn Forte 	}
141*fcf3ce44SJohn Forte 
142*fcf3ce44SJohn Forte 	(void) close(sock);
143*fcf3ce44SJohn Forte }
144*fcf3ce44SJohn Forte 
145*fcf3ce44SJohn Forte int
self_check(char * hostname)146*fcf3ce44SJohn Forte self_check(char *hostname)
147*fcf3ce44SJohn Forte {
148*fcf3ce44SJohn Forte 	int n;
149*fcf3ce44SJohn Forte 	struct sockaddr_in *s1, *s2;
150*fcf3ce44SJohn Forte 	struct ifreq *ifr;
151*fcf3ce44SJohn Forte 	struct nd_hostserv hs;
152*fcf3ce44SJohn Forte 	struct nd_addrlist *retaddrs;
153*fcf3ce44SJohn Forte 	struct netconfig *nconfp;
154*fcf3ce44SJohn Forte 	struct ifconf *ifc;
155*fcf3ce44SJohn Forte 	int retval;
156*fcf3ce44SJohn Forte 
157*fcf3ce44SJohn Forte 	ifc = malloc(sizeof (struct ifconf));
158*fcf3ce44SJohn Forte 	if (ifc == NULL)
159*fcf3ce44SJohn Forte 		return (0);
160*fcf3ce44SJohn Forte 	memset((char *)ifc, 0, sizeof (struct ifconf));
161*fcf3ce44SJohn Forte 	getmyaddrs(ifc);
162*fcf3ce44SJohn Forte 	/*
163*fcf3ce44SJohn Forte 	 * Get the IP address for hostname
164*fcf3ce44SJohn Forte 	 */
165*fcf3ce44SJohn Forte 	nconfp = getnetconfigent("udp");
166*fcf3ce44SJohn Forte 	if (nconfp == NULL) {
167*fcf3ce44SJohn Forte #ifdef DEBUG
168*fcf3ce44SJohn Forte 		fprintf(stderr, "self_check(): getnetconfigent failed\n");
169*fcf3ce44SJohn Forte #endif
170*fcf3ce44SJohn Forte 		retval = 0;
171*fcf3ce44SJohn Forte 		goto out;
172*fcf3ce44SJohn Forte 	}
173*fcf3ce44SJohn Forte 	hs.h_host = hostname;
174*fcf3ce44SJohn Forte 	hs.h_serv = "rpcbind";
175*fcf3ce44SJohn Forte 	if (netdir_getbyname(nconfp, &hs, &retaddrs) != ND_OK) {
176*fcf3ce44SJohn Forte 		freenetconfigent(nconfp);
177*fcf3ce44SJohn Forte 		retval = 0;
178*fcf3ce44SJohn Forte 		goto out;
179*fcf3ce44SJohn Forte 	}
180*fcf3ce44SJohn Forte 	freenetconfigent(nconfp);
181*fcf3ce44SJohn Forte 	/* LINTED pointer alignment */
182*fcf3ce44SJohn Forte 	s1 = (struct sockaddr_in *)retaddrs->n_addrs->buf;
183*fcf3ce44SJohn Forte 
184*fcf3ce44SJohn Forte 	/*
185*fcf3ce44SJohn Forte 	 * Now compare it against the list of
186*fcf3ce44SJohn Forte 	 * addresses for the interfaces on this
187*fcf3ce44SJohn Forte 	 * host.
188*fcf3ce44SJohn Forte 	 */
189*fcf3ce44SJohn Forte 	ifr = ifc->ifc_req;
190*fcf3ce44SJohn Forte 	n = ifc->ifc_len / sizeof (struct ifreq);
191*fcf3ce44SJohn Forte 	s2 = NULL;
192*fcf3ce44SJohn Forte 	for (; n > 0; n--, ifr++) {
193*fcf3ce44SJohn Forte 		if (ifr->ifr_addr.sa_family != AF_INET)
194*fcf3ce44SJohn Forte 			continue;
195*fcf3ce44SJohn Forte 
196*fcf3ce44SJohn Forte 		/* LINTED pointer alignment */
197*fcf3ce44SJohn Forte 		s2 = (struct sockaddr_in *)&ifr->ifr_addr;
198*fcf3ce44SJohn Forte 
199*fcf3ce44SJohn Forte 		if (memcmp((char *)&s2->sin_addr,
200*fcf3ce44SJohn Forte 			(char *)&s1->sin_addr, sizeof (s1->sin_addr)) == 0) {
201*fcf3ce44SJohn Forte 			netdir_free((void *)retaddrs, ND_ADDRLIST);
202*fcf3ce44SJohn Forte 			retval = 1;
203*fcf3ce44SJohn Forte 			goto out;	/* it's me */
204*fcf3ce44SJohn Forte 		}
205*fcf3ce44SJohn Forte 	}
206*fcf3ce44SJohn Forte 	netdir_free((void *)retaddrs, ND_ADDRLIST);
207*fcf3ce44SJohn Forte 	retval = 0;
208*fcf3ce44SJohn Forte 
209*fcf3ce44SJohn Forte out:
210*fcf3ce44SJohn Forte 	if (ifc->ifc_buf != NULL)
211*fcf3ce44SJohn Forte 		free(ifc->ifc_buf);
212*fcf3ce44SJohn Forte 	free(ifc);
213*fcf3ce44SJohn Forte 	return (retval);
214*fcf3ce44SJohn Forte }
215*fcf3ce44SJohn Forte 
216*fcf3ce44SJohn Forte 
217*fcf3ce44SJohn Forte int
convert_nconf_to_knconf(struct netconfig * nconf,struct knetconfig * knconf)218*fcf3ce44SJohn Forte convert_nconf_to_knconf(struct netconfig *nconf, struct knetconfig *knconf)
219*fcf3ce44SJohn Forte {
220*fcf3ce44SJohn Forte 	struct stat sb;
221*fcf3ce44SJohn Forte 
222*fcf3ce44SJohn Forte 	if (stat(nconf->nc_device, &sb) < 0) {
223*fcf3ce44SJohn Forte 		(void) syslog(LOG_ERR, "can't find device for transport %s\n",
224*fcf3ce44SJohn Forte 				nconf->nc_device);
225*fcf3ce44SJohn Forte 		return (-1);
226*fcf3ce44SJohn Forte 	}
227*fcf3ce44SJohn Forte #ifdef DEBUG_ADDR
228*fcf3ce44SJohn Forte 	printf("lib knconf %x %s %s %x\n", nconf->nc_semantics,
229*fcf3ce44SJohn Forte 		nconf->nc_protofmly, nconf->nc_proto, sb.st_rdev);
230*fcf3ce44SJohn Forte #endif
231*fcf3ce44SJohn Forte 
232*fcf3ce44SJohn Forte 	knconf->knc_semantics = nconf->nc_semantics;
233*fcf3ce44SJohn Forte 	knconf->knc_protofmly = nconf->nc_protofmly;
234*fcf3ce44SJohn Forte 	knconf->knc_proto = nconf->nc_proto;
235*fcf3ce44SJohn Forte 	knconf->knc_rdev = sb.st_rdev;
236*fcf3ce44SJohn Forte 
237*fcf3ce44SJohn Forte 	return (0);
238*fcf3ce44SJohn Forte }
239*fcf3ce44SJohn Forte 
240*fcf3ce44SJohn Forte struct hostent *
gethost_byname(const char * name)241*fcf3ce44SJohn Forte gethost_byname(const char *name)
242*fcf3ce44SJohn Forte {
243*fcf3ce44SJohn Forte 	int errnum;
244*fcf3ce44SJohn Forte #ifdef AF_INET6
245*fcf3ce44SJohn Forte 	return (getipnodebyname(name, AF_INET6, AI_DEFAULT, &errnum));
246*fcf3ce44SJohn Forte #else /* !AF_INET6 */
247*fcf3ce44SJohn Forte 	return (gethostbyname(name));
248*fcf3ce44SJohn Forte #endif /* AF_INET6 */
249*fcf3ce44SJohn Forte }
250*fcf3ce44SJohn Forte 
251*fcf3ce44SJohn Forte int
gethost_netaddrs(char * fromhost,char * tohost,char * fromnetaddr,char * tonetaddr)252*fcf3ce44SJohn Forte gethost_netaddrs(char *fromhost, char *tohost,
253*fcf3ce44SJohn Forte 	char *fromnetaddr, char *tonetaddr)
254*fcf3ce44SJohn Forte {
255*fcf3ce44SJohn Forte 	struct hostent *host;
256*fcf3ce44SJohn Forte 	int j;
257*fcf3ce44SJohn Forte 	int errnum;
258*fcf3ce44SJohn Forte 
259*fcf3ce44SJohn Forte #ifdef AF_INET6
260*fcf3ce44SJohn Forte 	host = getipnodebyname(fromhost, AF_INET6, AI_DEFAULT, &errnum);
261*fcf3ce44SJohn Forte 	if (host == NULL) {
262*fcf3ce44SJohn Forte #ifdef DEBUG
263*fcf3ce44SJohn Forte 		(void) fprintf(stderr, dgettext("sndr",
264*fcf3ce44SJohn Forte 		    "Could not find host %s"), fromhost);
265*fcf3ce44SJohn Forte #endif
266*fcf3ce44SJohn Forte 		return (-1);
267*fcf3ce44SJohn Forte 	}
268*fcf3ce44SJohn Forte 	for (j = 0; j < host->h_length; j++)
269*fcf3ce44SJohn Forte 		fromnetaddr[j] = host->h_addr[j];
270*fcf3ce44SJohn Forte 	freehostent(host);
271*fcf3ce44SJohn Forte #else /* !AF_INET6 */
272*fcf3ce44SJohn Forte 	host = gethostbyname(fromhost);
273*fcf3ce44SJohn Forte 	if (host == NULL) {
274*fcf3ce44SJohn Forte #ifdef DEBUG
275*fcf3ce44SJohn Forte 		(void) fprintf(stderr, dgettext("sndr",
276*fcf3ce44SJohn Forte 		    "Could not find host %s"), fromhost);
277*fcf3ce44SJohn Forte #endif
278*fcf3ce44SJohn Forte 		return (-1);
279*fcf3ce44SJohn Forte 	}
280*fcf3ce44SJohn Forte 
281*fcf3ce44SJohn Forte 	if (host->h_length < 4) {
282*fcf3ce44SJohn Forte #ifdef DEBUG
283*fcf3ce44SJohn Forte 		fprintf(stderr, "host->h_length(%d) < 4!\n", host->h_length);
284*fcf3ce44SJohn Forte #endif
285*fcf3ce44SJohn Forte 		return (-1);
286*fcf3ce44SJohn Forte 	}
287*fcf3ce44SJohn Forte 
288*fcf3ce44SJohn Forte 	for (j = 0; j < host->h_length; j++)
289*fcf3ce44SJohn Forte 		fromnetaddr[j] = host->h_addr[j];
290*fcf3ce44SJohn Forte #endif /* AF_INET6 */
291*fcf3ce44SJohn Forte 
292*fcf3ce44SJohn Forte #ifdef AF_INET6
293*fcf3ce44SJohn Forte 	host = getipnodebyname(tohost, AF_INET6, AI_DEFAULT, &errnum);
294*fcf3ce44SJohn Forte 	if (host == NULL) {
295*fcf3ce44SJohn Forte #ifdef DEBUG
296*fcf3ce44SJohn Forte 		(void) fprintf(stderr, dgettext("sndr",
297*fcf3ce44SJohn Forte 		    "Could not find host %s"), tohost);
298*fcf3ce44SJohn Forte #endif
299*fcf3ce44SJohn Forte 		return (-1);
300*fcf3ce44SJohn Forte 	}
301*fcf3ce44SJohn Forte 	for (j = 0; j < host->h_length; j++)
302*fcf3ce44SJohn Forte 		tonetaddr[j] = host->h_addr[j];
303*fcf3ce44SJohn Forte 	freehostent(host);
304*fcf3ce44SJohn Forte #else /* !AF_INET6 */
305*fcf3ce44SJohn Forte 	host = gethostbyname(tohost);
306*fcf3ce44SJohn Forte 	if (host == NULL) {
307*fcf3ce44SJohn Forte #ifdef DEBUG
308*fcf3ce44SJohn Forte 		(void) fprintf(stderr, dgettext("sndr",
309*fcf3ce44SJohn Forte 		    "Could not find host %s"), tohost);
310*fcf3ce44SJohn Forte #endif
311*fcf3ce44SJohn Forte 		return (-1);
312*fcf3ce44SJohn Forte 	}
313*fcf3ce44SJohn Forte 
314*fcf3ce44SJohn Forte 	if (host->h_length < 4) {
315*fcf3ce44SJohn Forte #ifdef DEBUG
316*fcf3ce44SJohn Forte 		fprintf(stderr, "host->h_length(%d) < 4!\n", host->h_length);
317*fcf3ce44SJohn Forte #endif
318*fcf3ce44SJohn Forte 		return (-1);
319*fcf3ce44SJohn Forte 	}
320*fcf3ce44SJohn Forte 
321*fcf3ce44SJohn Forte 	for (j = 0; j < host->h_length; j++)
322*fcf3ce44SJohn Forte 		tonetaddr[j] = host->h_addr[j];
323*fcf3ce44SJohn Forte #endif /* AF_INET6 */
324*fcf3ce44SJohn Forte 	return (0);
325*fcf3ce44SJohn Forte }
326*fcf3ce44SJohn Forte 
327*fcf3ce44SJohn Forte /*
328*fcf3ce44SJohn Forte  * Get the network address on "hostname" for program "prog"
329*fcf3ce44SJohn Forte  * with version "vers" by using the nconf configuration data
330*fcf3ce44SJohn Forte  * passed in.
331*fcf3ce44SJohn Forte  *
332*fcf3ce44SJohn Forte  * If the address of a netconfig pointer is null then
333*fcf3ce44SJohn Forte  * information is not sufficient and no netbuf will be returned.
334*fcf3ce44SJohn Forte  *
335*fcf3ce44SJohn Forte  * Finally, ping the null procedure of that service.
336*fcf3ce44SJohn Forte  *
337*fcf3ce44SJohn Forte  */
338*fcf3ce44SJohn Forte static struct netbuf *
get_the_addr(char * hostname,ulong_t prog,ulong_t vers,struct netconfig * nconf,ushort_t port,struct t_info * tinfo,int portmap)339*fcf3ce44SJohn Forte get_the_addr(char *hostname, ulong_t prog, ulong_t vers,
340*fcf3ce44SJohn Forte 	struct netconfig *nconf, ushort_t port, struct t_info *tinfo,
341*fcf3ce44SJohn Forte 	int portmap)
342*fcf3ce44SJohn Forte {
343*fcf3ce44SJohn Forte 	struct netbuf *nb = NULL;
344*fcf3ce44SJohn Forte 	struct t_bind *tbind = NULL;
345*fcf3ce44SJohn Forte 	CLIENT *cl = NULL;
346*fcf3ce44SJohn Forte 	struct timeval tv;
347*fcf3ce44SJohn Forte 	int fd = -1;
348*fcf3ce44SJohn Forte 	AUTH *ah = NULL;
349*fcf3ce44SJohn Forte 
350*fcf3ce44SJohn Forte 	if (nconf == NULL)
351*fcf3ce44SJohn Forte 		return (NULL);
352*fcf3ce44SJohn Forte 
353*fcf3ce44SJohn Forte 	if ((fd = t_open(nconf->nc_device, O_RDWR, tinfo)) == -1)
354*fcf3ce44SJohn Forte 		    goto done;
355*fcf3ce44SJohn Forte 
356*fcf3ce44SJohn Forte 	/* LINTED pointer alignment */
357*fcf3ce44SJohn Forte 	if ((tbind = (struct t_bind *)t_alloc(fd, T_BIND, T_ADDR)) == NULL)
358*fcf3ce44SJohn Forte 		goto done;
359*fcf3ce44SJohn Forte 
360*fcf3ce44SJohn Forte 	if (portmap) { /* contact rpcbind */
361*fcf3ce44SJohn Forte 		if (rpcb_getaddr(prog, vers, nconf, &tbind->addr,
362*fcf3ce44SJohn Forte 		    hostname) == FALSE) {
363*fcf3ce44SJohn Forte 			goto done;
364*fcf3ce44SJohn Forte 		}
365*fcf3ce44SJohn Forte 
366*fcf3ce44SJohn Forte 		if (port) {
367*fcf3ce44SJohn Forte 			if (strcmp(nconf->nc_protofmly, NC_INET) == 0)
368*fcf3ce44SJohn Forte 			    /* LINTED pointer alignment */
369*fcf3ce44SJohn Forte 			    ((struct sockaddr_in *)tbind->addr.buf)->sin_port
370*fcf3ce44SJohn Forte 					= port;
371*fcf3ce44SJohn Forte #ifdef NC_INET6
372*fcf3ce44SJohn Forte 			else if (strcmp(nconf->nc_protofmly, NC_INET6) == 0)
373*fcf3ce44SJohn Forte 			    /* LINTED pointer alignment */
374*fcf3ce44SJohn Forte 			    ((struct sockaddr_in6 *)tbind->addr.buf)->sin6_port
375*fcf3ce44SJohn Forte 					= port;
376*fcf3ce44SJohn Forte #endif
377*fcf3ce44SJohn Forte 		}
378*fcf3ce44SJohn Forte 
379*fcf3ce44SJohn Forte 		/* Simon -- we never use the client we create?! */
380*fcf3ce44SJohn Forte 		cl = clnt_tli_create(fd, nconf, &tbind->addr, prog, vers, 0, 0);
381*fcf3ce44SJohn Forte 		if (cl == NULL)
382*fcf3ce44SJohn Forte 			goto done;
383*fcf3ce44SJohn Forte 
384*fcf3ce44SJohn Forte 		ah = authsys_create_default();
385*fcf3ce44SJohn Forte 		if (ah != NULL)
386*fcf3ce44SJohn Forte 			cl->cl_auth = ah;
387*fcf3ce44SJohn Forte 
388*fcf3ce44SJohn Forte 		tv.tv_sec = 5;
389*fcf3ce44SJohn Forte 		tv.tv_usec = 0;
390*fcf3ce44SJohn Forte 
391*fcf3ce44SJohn Forte 		(void) clnt_control(cl, CLSET_TIMEOUT, (char *)&tv);
392*fcf3ce44SJohn Forte 	} else { /* create our own address and skip rpcbind */
393*fcf3ce44SJohn Forte 		struct netbuf *nb;
394*fcf3ce44SJohn Forte 		struct hostent *hp;
395*fcf3ce44SJohn Forte 		int j;
396*fcf3ce44SJohn Forte 		int errnum;
397*fcf3ce44SJohn Forte 		unsigned short family;
398*fcf3ce44SJohn Forte 		nb = &(tbind->addr);
399*fcf3ce44SJohn Forte 
400*fcf3ce44SJohn Forte #ifdef AF_INET6
401*fcf3ce44SJohn Forte 		if (strcmp(nconf->nc_protofmly, NC_INET6) == 0) {
402*fcf3ce44SJohn Forte 			hp = getipnodebyname(hostname, AF_INET6, 0, &errnum);
403*fcf3ce44SJohn Forte 			family = AF_INET6;
404*fcf3ce44SJohn Forte 			nb->len = nb->maxlen = sizeof (struct sockaddr_in6);
405*fcf3ce44SJohn Forte 		} else {
406*fcf3ce44SJohn Forte 			hp = getipnodebyname(hostname, AF_INET, 0, &errnum);
407*fcf3ce44SJohn Forte 			family = AF_INET;
408*fcf3ce44SJohn Forte 			nb->len = nb->maxlen = sizeof (struct sockaddr_in);
409*fcf3ce44SJohn Forte 		}
410*fcf3ce44SJohn Forte 		if (hp == NULL) {
411*fcf3ce44SJohn Forte #ifdef DEBUG_ADDR
412*fcf3ce44SJohn Forte 				(void) fprintf(stderr, dgettext("sndr",
413*fcf3ce44SJohn Forte 				    "Could not find host %s\n"), hostname);
414*fcf3ce44SJohn Forte #endif
415*fcf3ce44SJohn Forte 				goto done;
416*fcf3ce44SJohn Forte 		}
417*fcf3ce44SJohn Forte 		nb->buf = (char *)calloc(1, nb->maxlen);
418*fcf3ce44SJohn Forte 		if (nb->buf == NULL) {
419*fcf3ce44SJohn Forte 			(void) printf(dgettext("sndr", "no memory\n"));
420*fcf3ce44SJohn Forte 			goto done;
421*fcf3ce44SJohn Forte 		}
422*fcf3ce44SJohn Forte 
423*fcf3ce44SJohn Forte 		if (family == AF_INET) {
424*fcf3ce44SJohn Forte 			for (j = 0; j < hp->h_length; j++)
425*fcf3ce44SJohn Forte 				nb->buf[j+4] = hp->h_addr[j];
426*fcf3ce44SJohn Forte 			/* LINTED pointer alignment */
427*fcf3ce44SJohn Forte 			((struct sockaddr_in *)(nb->buf))->sin_port = port;
428*fcf3ce44SJohn Forte 			/* LINTED pointer alignment */
429*fcf3ce44SJohn Forte 			((struct sockaddr_in *)(nb->buf))->sin_family = AF_INET;
430*fcf3ce44SJohn Forte 		} else {
431*fcf3ce44SJohn Forte 			for (j = 0; j < hp->h_length; j++)
432*fcf3ce44SJohn Forte 				nb->buf[j+8] = hp->h_addr[j];
433*fcf3ce44SJohn Forte 			/* LINTED pointer alignment */
434*fcf3ce44SJohn Forte 			((struct sockaddr_in6 *)(nb->buf))->sin6_port = port;
435*fcf3ce44SJohn Forte 			/* LINTED pointer alignment */
436*fcf3ce44SJohn Forte 			((struct sockaddr_in6 *)(nb->buf))->sin6_family =
437*fcf3ce44SJohn Forte 			    AF_INET6;
438*fcf3ce44SJohn Forte 		}
439*fcf3ce44SJohn Forte 		freehostent(hp);
440*fcf3ce44SJohn Forte #else
441*fcf3ce44SJohn Forte 		hp = gethostbyname(hostname);
442*fcf3ce44SJohn Forte 		if (hp == NULL) {
443*fcf3ce44SJohn Forte #ifdef DEBUG
444*fcf3ce44SJohn Forte 			(void) fprintf(stderr, dgettext("sndr",
445*fcf3ce44SJohn Forte 			    "Could not find host %s"), hostname);
446*fcf3ce44SJohn Forte #endif
447*fcf3ce44SJohn Forte 			goto done;
448*fcf3ce44SJohn Forte 		}
449*fcf3ce44SJohn Forte 
450*fcf3ce44SJohn Forte 		nb->len = nb->maxlen = sizeof (struct sockaddr_in);
451*fcf3ce44SJohn Forte 		nb->buf = (char *)calloc(1, nb->maxlen);
452*fcf3ce44SJohn Forte 		if (nb->buf == NULL) {
453*fcf3ce44SJohn Forte 			(void) printf(dgettext("sndr", "no memory\n"));
454*fcf3ce44SJohn Forte 			free(nb);
455*fcf3ce44SJohn Forte 			nb = NULL;
456*fcf3ce44SJohn Forte 			goto done;
457*fcf3ce44SJohn Forte 		}
458*fcf3ce44SJohn Forte 
459*fcf3ce44SJohn Forte 		for (j = 0; j < hp->h_length; j++)
460*fcf3ce44SJohn Forte 			nb->buf[j+4] = hp->h_addr[j];
461*fcf3ce44SJohn Forte 
462*fcf3ce44SJohn Forte 		if (hp->h_addrtype == AF_INET) {
463*fcf3ce44SJohn Forte 			((struct sockaddr_in *)(nb->buf))->sin_port = port;
464*fcf3ce44SJohn Forte 			((struct sockaddr_in *)(nb->buf))->sin_family = AF_INET;
465*fcf3ce44SJohn Forte 		}
466*fcf3ce44SJohn Forte #endif
467*fcf3ce44SJohn Forte 	}
468*fcf3ce44SJohn Forte 
469*fcf3ce44SJohn Forte 	/*
470*fcf3ce44SJohn Forte 	 * Make a copy of the netbuf to return
471*fcf3ce44SJohn Forte 	 */
472*fcf3ce44SJohn Forte 	nb = (struct netbuf *)calloc(1, sizeof (*nb));
473*fcf3ce44SJohn Forte 	if (nb == NULL) {
474*fcf3ce44SJohn Forte 		(void) printf(dgettext("sndr", "no memory\n"));
475*fcf3ce44SJohn Forte 		goto done;
476*fcf3ce44SJohn Forte 	}
477*fcf3ce44SJohn Forte 
478*fcf3ce44SJohn Forte 	*nb = tbind->addr;	/* structure copy */
479*fcf3ce44SJohn Forte 
480*fcf3ce44SJohn Forte 	nb->buf = (char *)calloc(1, nb->maxlen);
481*fcf3ce44SJohn Forte 	if (nb->buf == NULL) {
482*fcf3ce44SJohn Forte 		(void) printf(dgettext("sndr", "no memory\n"));
483*fcf3ce44SJohn Forte 		free(nb);
484*fcf3ce44SJohn Forte 		nb = NULL;
485*fcf3ce44SJohn Forte 		goto done;
486*fcf3ce44SJohn Forte 	}
487*fcf3ce44SJohn Forte 
488*fcf3ce44SJohn Forte 	(void) memcpy(nb->buf, tbind->addr.buf, tbind->addr.len);
489*fcf3ce44SJohn Forte 
490*fcf3ce44SJohn Forte done:
491*fcf3ce44SJohn Forte 	if (cl) {
492*fcf3ce44SJohn Forte 		if (ah != NULL) {
493*fcf3ce44SJohn Forte 		    AUTH_DESTROY(cl->cl_auth);
494*fcf3ce44SJohn Forte 		    cl->cl_auth = NULL;
495*fcf3ce44SJohn Forte 		}
496*fcf3ce44SJohn Forte 
497*fcf3ce44SJohn Forte 		clnt_destroy(cl);
498*fcf3ce44SJohn Forte 		cl = NULL;
499*fcf3ce44SJohn Forte 	}
500*fcf3ce44SJohn Forte 
501*fcf3ce44SJohn Forte 	if (tbind) {
502*fcf3ce44SJohn Forte 		t_free((char *)tbind, T_BIND);
503*fcf3ce44SJohn Forte 		tbind = NULL;
504*fcf3ce44SJohn Forte 	}
505*fcf3ce44SJohn Forte 
506*fcf3ce44SJohn Forte 	if (fd >= 0)
507*fcf3ce44SJohn Forte 		(void) t_close(fd);
508*fcf3ce44SJohn Forte 	return (nb);
509*fcf3ce44SJohn Forte }
510*fcf3ce44SJohn Forte 
511*fcf3ce44SJohn Forte /*
512*fcf3ce44SJohn Forte  * Get a network address on "hostname" for program "prog"
513*fcf3ce44SJohn Forte  * with version "vers".  If the port number is specified (non zero)
514*fcf3ce44SJohn Forte  * then try for a TCP/UDP transport and set the port number of the
515*fcf3ce44SJohn Forte  * resulting IP address.
516*fcf3ce44SJohn Forte  *
517*fcf3ce44SJohn Forte  * If the address of a netconfig pointer was passed and
518*fcf3ce44SJohn Forte  * if it's not null, use it as the netconfig otherwise
519*fcf3ce44SJohn Forte  * assign the address of the netconfig that was used to
520*fcf3ce44SJohn Forte  * establish contact with the service.
521*fcf3ce44SJohn Forte  * If portmap is false, we return a similiar address and we do not
522*fcf3ce44SJohn Forte  * contact rpcbind
523*fcf3ce44SJohn Forte  *
524*fcf3ce44SJohn Forte  */
525*fcf3ce44SJohn Forte struct netbuf *
get_addr(char * hostname,ulong_t prog,ulong_t vers,struct netconfig ** nconfp,char * proto,char * srvport,struct t_info * tinfo,int portmap)526*fcf3ce44SJohn Forte get_addr(char *hostname, ulong_t prog, ulong_t vers, struct netconfig **nconfp,
527*fcf3ce44SJohn Forte 	char *proto, char *srvport, struct t_info *tinfo, int portmap)
528*fcf3ce44SJohn Forte {
529*fcf3ce44SJohn Forte 	struct netbuf *nb = NULL;
530*fcf3ce44SJohn Forte 	struct netconfig *nconf = NULL;
531*fcf3ce44SJohn Forte 	NCONF_HANDLE *nc = NULL;
532*fcf3ce44SJohn Forte 	int nthtry = FIRST_TRY;
533*fcf3ce44SJohn Forte 	struct servent *svp;
534*fcf3ce44SJohn Forte 	ushort_t port;
535*fcf3ce44SJohn Forte 
536*fcf3ce44SJohn Forte 	/*
537*fcf3ce44SJohn Forte 	 * First lets get the requested port
538*fcf3ce44SJohn Forte 	 */
539*fcf3ce44SJohn Forte 
540*fcf3ce44SJohn Forte 	if ((svp = getservbyname(srvport, proto)) == NULL)
541*fcf3ce44SJohn Forte 		goto done;
542*fcf3ce44SJohn Forte 	port = svp->s_port;
543*fcf3ce44SJohn Forte 	/*
544*fcf3ce44SJohn Forte 	 * No nconf passed in.
545*fcf3ce44SJohn Forte 	 *
546*fcf3ce44SJohn Forte 	 * Try to get a nconf from /etc/netconfig filtered by
547*fcf3ce44SJohn Forte 	 * the NETPATH environment variable.
548*fcf3ce44SJohn Forte 	 * First search for COTS, second for CLTS unless proto
549*fcf3ce44SJohn Forte 	 * is specified.  When we retry, we reset the
550*fcf3ce44SJohn Forte 	 * netconfig list so that we would search the whole list
551*fcf3ce44SJohn Forte 	 * all over again.
552*fcf3ce44SJohn Forte 	 */
553*fcf3ce44SJohn Forte 	if ((nc = setnetpath()) == NULL)
554*fcf3ce44SJohn Forte 		goto done;
555*fcf3ce44SJohn Forte 
556*fcf3ce44SJohn Forte 	/*
557*fcf3ce44SJohn Forte 	 * If proto is specified, then only search for the match,
558*fcf3ce44SJohn Forte 	 * otherwise try COTS first, if failed, try CLTS.
559*fcf3ce44SJohn Forte 	 */
560*fcf3ce44SJohn Forte 	if (proto) {
561*fcf3ce44SJohn Forte 		while (nconf = getnetpath(nc)) {
562*fcf3ce44SJohn Forte 			if (strcmp(nconf->nc_netid, proto) == 0) {
563*fcf3ce44SJohn Forte 				/*
564*fcf3ce44SJohn Forte 				 * If the port number is specified then TCP/UDP
565*fcf3ce44SJohn Forte 				 * is needed. Otherwise any cots/clts will do.
566*fcf3ce44SJohn Forte 				 */
567*fcf3ce44SJohn Forte 				if (port == 0)
568*fcf3ce44SJohn Forte 					break;
569*fcf3ce44SJohn Forte 
570*fcf3ce44SJohn Forte 				if ((strcmp(nconf->nc_protofmly, NC_INET) == 0
571*fcf3ce44SJohn Forte #ifdef NC_INET6
572*fcf3ce44SJohn Forte 				/* CSTYLED */
573*fcf3ce44SJohn Forte 				|| strcmp(nconf->nc_protofmly, NC_INET6) == 0
574*fcf3ce44SJohn Forte #endif
575*fcf3ce44SJohn Forte 				/* CSTYLED */
576*fcf3ce44SJohn Forte 				) &&
577*fcf3ce44SJohn Forte 				(strcmp(nconf->nc_proto, NC_TCP) == 0 ||
578*fcf3ce44SJohn Forte 				strcmp(nconf->nc_proto, NC_UDP) == 0))
579*fcf3ce44SJohn Forte 					break;
580*fcf3ce44SJohn Forte 				else {
581*fcf3ce44SJohn Forte 					nconf = NULL;
582*fcf3ce44SJohn Forte 					break;
583*fcf3ce44SJohn Forte 				}
584*fcf3ce44SJohn Forte 			}
585*fcf3ce44SJohn Forte 		}
586*fcf3ce44SJohn Forte 		if (nconf == NULL)
587*fcf3ce44SJohn Forte 			goto done;
588*fcf3ce44SJohn Forte 		if ((nb = get_the_addr(hostname, prog, vers, nconf, port,
589*fcf3ce44SJohn Forte 				tinfo, portmap)) == NULL) {
590*fcf3ce44SJohn Forte 			goto done;
591*fcf3ce44SJohn Forte 		}
592*fcf3ce44SJohn Forte 	} else {
593*fcf3ce44SJohn Forte retry:
594*fcf3ce44SJohn Forte 		while (nconf = getnetpath(nc)) {
595*fcf3ce44SJohn Forte 			if (nconf->nc_flag & NC_VISIBLE) {
596*fcf3ce44SJohn Forte 			    if (nthtry == FIRST_TRY) {
597*fcf3ce44SJohn Forte 				if ((nconf->nc_semantics == NC_TPI_COTS_ORD) ||
598*fcf3ce44SJohn Forte 					(nconf->nc_semantics == NC_TPI_COTS)) {
599*fcf3ce44SJohn Forte 				    if (port == 0)
600*fcf3ce44SJohn Forte 					break;
601*fcf3ce44SJohn Forte 				    if ((strcmp(nconf->nc_protofmly,
602*fcf3ce44SJohn Forte 					NC_INET) == 0
603*fcf3ce44SJohn Forte #ifdef NC_INET6
604*fcf3ce44SJohn Forte 					/* CSTYLED */
605*fcf3ce44SJohn Forte 					|| strcmp(nconf->nc_protofmly,
606*fcf3ce44SJohn Forte 					NC_INET6) == 0
607*fcf3ce44SJohn Forte #endif
608*fcf3ce44SJohn Forte 					/* CSTYLED */
609*fcf3ce44SJohn Forte 					) &&
610*fcf3ce44SJohn Forte 					(strcmp(nconf->nc_proto, NC_TCP) == 0))
611*fcf3ce44SJohn Forte 					break;
612*fcf3ce44SJohn Forte 				}
613*fcf3ce44SJohn Forte 			    }
614*fcf3ce44SJohn Forte 			}
615*fcf3ce44SJohn Forte 		} /* while */
616*fcf3ce44SJohn Forte 		if (nconf == NULL) {
617*fcf3ce44SJohn Forte 			if (++nthtry <= MNT_PREF_LISTLEN) {
618*fcf3ce44SJohn Forte 				endnetpath(nc);
619*fcf3ce44SJohn Forte 				if ((nc = setnetpath()) == NULL)
620*fcf3ce44SJohn Forte 					goto done;
621*fcf3ce44SJohn Forte 				goto retry;
622*fcf3ce44SJohn Forte 			} else
623*fcf3ce44SJohn Forte 				goto done;
624*fcf3ce44SJohn Forte 		} else {
625*fcf3ce44SJohn Forte 			if ((nb = get_the_addr(hostname, prog, vers, nconf,
626*fcf3ce44SJohn Forte 			    port, tinfo, portmap)) == NULL) {
627*fcf3ce44SJohn Forte 				/*
628*fcf3ce44SJohn Forte 				 * Continue the same search path in the
629*fcf3ce44SJohn Forte 				 * netconfig db until no more matched
630*fcf3ce44SJohn Forte 				 * nconf (nconf == NULL).
631*fcf3ce44SJohn Forte 				 */
632*fcf3ce44SJohn Forte 				goto retry;
633*fcf3ce44SJohn Forte 			}
634*fcf3ce44SJohn Forte #ifdef AF_INET6
635*fcf3ce44SJohn Forte 			if ((nb->len == 8) &&
636*fcf3ce44SJohn Forte 			    (strcmp(nconf->nc_protofmly, NC_INET6) == 0)) {
637*fcf3ce44SJohn Forte 				/*
638*fcf3ce44SJohn Forte 				 * We have a mismatch in the netconfig retry
639*fcf3ce44SJohn Forte 				 */
640*fcf3ce44SJohn Forte 				free(nb);
641*fcf3ce44SJohn Forte 				goto retry;
642*fcf3ce44SJohn Forte 			}
643*fcf3ce44SJohn Forte #endif
644*fcf3ce44SJohn Forte 		}
645*fcf3ce44SJohn Forte 	}
646*fcf3ce44SJohn Forte 
647*fcf3ce44SJohn Forte 	/*
648*fcf3ce44SJohn Forte 	 * Got nconf and nb.  Now dup the netconfig structure (nconf)
649*fcf3ce44SJohn Forte 	 * and return it thru nconfp.
650*fcf3ce44SJohn Forte 	 */
651*fcf3ce44SJohn Forte 	*nconfp = getnetconfigent(nconf->nc_netid);
652*fcf3ce44SJohn Forte 	if (*nconfp == NULL) {
653*fcf3ce44SJohn Forte 		syslog(LOG_ERR, "no memory\n");
654*fcf3ce44SJohn Forte 		free(nb);
655*fcf3ce44SJohn Forte 		nb = NULL;
656*fcf3ce44SJohn Forte 	}
657*fcf3ce44SJohn Forte done:
658*fcf3ce44SJohn Forte 	if (nc)
659*fcf3ce44SJohn Forte 		endnetpath(nc);
660*fcf3ce44SJohn Forte 	return (nb);
661*fcf3ce44SJohn Forte }
662*fcf3ce44SJohn Forte 
663*fcf3ce44SJohn Forte 
664*fcf3ce44SJohn Forte /* return values as for nsc_check_release() */
665*fcf3ce44SJohn Forte int
rdc_check_release(char ** reqd)666*fcf3ce44SJohn Forte rdc_check_release(char **reqd)
667*fcf3ce44SJohn Forte {
668*fcf3ce44SJohn Forte 	/* librdc.so must be built on the runtime OS release */
669*fcf3ce44SJohn Forte 	return (nsc_check_release(BUILD_REV_STR, NULL, reqd));
670*fcf3ce44SJohn Forte }
671