1*0Sstevel@tonic-gate /*
2*0Sstevel@tonic-gate  * Copyright 2003 Sun Microsystems, Inc.  All rights reserved.
3*0Sstevel@tonic-gate  * Use is subject to license terms.
4*0Sstevel@tonic-gate  */
5*0Sstevel@tonic-gate 
6*0Sstevel@tonic-gate /*
7*0Sstevel@tonic-gate  * Copyright (c) 1996-1999 by Internet Software Consortium.
8*0Sstevel@tonic-gate  *
9*0Sstevel@tonic-gate  * Permission to use, copy, modify, and distribute this software for any
10*0Sstevel@tonic-gate  * purpose with or without fee is hereby granted, provided that the above
11*0Sstevel@tonic-gate  * copyright notice and this permission notice appear in all copies.
12*0Sstevel@tonic-gate  *
13*0Sstevel@tonic-gate  * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
14*0Sstevel@tonic-gate  * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
15*0Sstevel@tonic-gate  * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
16*0Sstevel@tonic-gate  * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
17*0Sstevel@tonic-gate  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
18*0Sstevel@tonic-gate  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
19*0Sstevel@tonic-gate  * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
20*0Sstevel@tonic-gate  * SOFTWARE.
21*0Sstevel@tonic-gate  */
22*0Sstevel@tonic-gate 
23*0Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
24*0Sstevel@tonic-gate 
25*0Sstevel@tonic-gate #if !defined(LINT) && !defined(CODECENTER)
26*0Sstevel@tonic-gate static const char rcsid[] = "$Id: gethostent.c,v 1.34 2003/05/29 00:05:18 marka Exp $";
27*0Sstevel@tonic-gate #endif
28*0Sstevel@tonic-gate 
29*0Sstevel@tonic-gate /* Imports */
30*0Sstevel@tonic-gate 
31*0Sstevel@tonic-gate #include "port_before.h"
32*0Sstevel@tonic-gate 
33*0Sstevel@tonic-gate #if !defined(__BIND_NOSTATIC)
34*0Sstevel@tonic-gate 
35*0Sstevel@tonic-gate #include <sys/types.h>
36*0Sstevel@tonic-gate #include <sys/param.h>
37*0Sstevel@tonic-gate #include <sys/socket.h>
38*0Sstevel@tonic-gate #include <sys/ioctl.h>
39*0Sstevel@tonic-gate #include <netinet/in.h>
40*0Sstevel@tonic-gate #include <net/if.h>
41*0Sstevel@tonic-gate #include <arpa/inet.h>
42*0Sstevel@tonic-gate #include <arpa/nameser.h>
43*0Sstevel@tonic-gate 
44*0Sstevel@tonic-gate #include <ctype.h>
45*0Sstevel@tonic-gate #include <errno.h>
46*0Sstevel@tonic-gate #include <stdlib.h>
47*0Sstevel@tonic-gate #include <netdb.h>
48*0Sstevel@tonic-gate #include <resolv.h>
49*0Sstevel@tonic-gate #include <stdio.h>
50*0Sstevel@tonic-gate #include <string.h>
51*0Sstevel@tonic-gate #include <unistd.h>
52*0Sstevel@tonic-gate 
53*0Sstevel@tonic-gate #include <irs.h>
54*0Sstevel@tonic-gate #include <isc/memcluster.h>
55*0Sstevel@tonic-gate 
56*0Sstevel@tonic-gate #include "port_after.h"
57*0Sstevel@tonic-gate 
58*0Sstevel@tonic-gate #include "irs_p.h"
59*0Sstevel@tonic-gate #include "irs_data.h"
60*0Sstevel@tonic-gate 
61*0Sstevel@tonic-gate /* Definitions */
62*0Sstevel@tonic-gate 
63*0Sstevel@tonic-gate struct pvt {
64*0Sstevel@tonic-gate 	char *		aliases[1];
65*0Sstevel@tonic-gate 	char *		addrs[2];
66*0Sstevel@tonic-gate 	char		addr[NS_IN6ADDRSZ];
67*0Sstevel@tonic-gate 	char		name[NS_MAXDNAME + 1];
68*0Sstevel@tonic-gate 	struct hostent	host;
69*0Sstevel@tonic-gate };
70*0Sstevel@tonic-gate 
71*0Sstevel@tonic-gate /* Forward */
72*0Sstevel@tonic-gate 
73*0Sstevel@tonic-gate static struct net_data *init(void);
74*0Sstevel@tonic-gate static void		freepvt(struct net_data *);
75*0Sstevel@tonic-gate static struct hostent  *fakeaddr(const char *, int, struct net_data *);
76*0Sstevel@tonic-gate 
77*0Sstevel@tonic-gate #ifdef	SUNW_OVERRIDE_RETRY
78*0Sstevel@tonic-gate extern int	__res_retry(int);
79*0Sstevel@tonic-gate extern int	__res_retry_reset(void);
80*0Sstevel@tonic-gate #endif	/* SUNW_OVERRIDE_RETRY */
81*0Sstevel@tonic-gate 
82*0Sstevel@tonic-gate /* Public */
83*0Sstevel@tonic-gate 
84*0Sstevel@tonic-gate struct hostent *
85*0Sstevel@tonic-gate gethostbyname(const char *name) {
86*0Sstevel@tonic-gate 	struct net_data *net_data = init();
87*0Sstevel@tonic-gate 
88*0Sstevel@tonic-gate 	return (gethostbyname_p(name, net_data));
89*0Sstevel@tonic-gate }
90*0Sstevel@tonic-gate 
91*0Sstevel@tonic-gate struct hostent *
92*0Sstevel@tonic-gate gethostbyname2(const char *name, int af) {
93*0Sstevel@tonic-gate 	struct net_data *net_data = init();
94*0Sstevel@tonic-gate 
95*0Sstevel@tonic-gate 	return (gethostbyname2_p(name, af, net_data));
96*0Sstevel@tonic-gate }
97*0Sstevel@tonic-gate 
98*0Sstevel@tonic-gate struct hostent *
99*0Sstevel@tonic-gate #ifdef ORIGINAL_ISC_CODE
100*0Sstevel@tonic-gate gethostbyaddr(const char *addr, int len, int af) {
101*0Sstevel@tonic-gate #else
102*0Sstevel@tonic-gate gethostbyaddr(const void *addr, socklen_t len, int af) {
103*0Sstevel@tonic-gate #endif /* ORIGINAL_ISC_CODE */
104*0Sstevel@tonic-gate 	struct net_data *net_data = init();
105*0Sstevel@tonic-gate 
106*0Sstevel@tonic-gate 	return (gethostbyaddr_p(addr, len, af, net_data));
107*0Sstevel@tonic-gate }
108*0Sstevel@tonic-gate 
109*0Sstevel@tonic-gate struct hostent *
110*0Sstevel@tonic-gate gethostent() {
111*0Sstevel@tonic-gate 	struct net_data *net_data = init();
112*0Sstevel@tonic-gate 
113*0Sstevel@tonic-gate 	return (gethostent_p(net_data));
114*0Sstevel@tonic-gate }
115*0Sstevel@tonic-gate 
116*0Sstevel@tonic-gate #ifdef	ORIGINAL_ISC_CODE
117*0Sstevel@tonic-gate void
118*0Sstevel@tonic-gate #else
119*0Sstevel@tonic-gate int
120*0Sstevel@tonic-gate #endif
121*0Sstevel@tonic-gate sethostent(int stayopen) {
122*0Sstevel@tonic-gate 	struct net_data *net_data = init();
123*0Sstevel@tonic-gate 	sethostent_p(stayopen, net_data);
124*0Sstevel@tonic-gate #ifdef	ORIGINAL_ISC_CODE
125*0Sstevel@tonic-gate #else
126*0Sstevel@tonic-gate 	return (0);
127*0Sstevel@tonic-gate #endif
128*0Sstevel@tonic-gate }
129*0Sstevel@tonic-gate 
130*0Sstevel@tonic-gate 
131*0Sstevel@tonic-gate #ifdef	ORIGINAL_ISC_CODE
132*0Sstevel@tonic-gate void
133*0Sstevel@tonic-gate #else
134*0Sstevel@tonic-gate int
135*0Sstevel@tonic-gate #endif
136*0Sstevel@tonic-gate endhostent() {
137*0Sstevel@tonic-gate 	struct net_data *net_data = init();
138*0Sstevel@tonic-gate 	endhostent_p(net_data);
139*0Sstevel@tonic-gate #ifdef	ORIGINAL_ISC_CODE
140*0Sstevel@tonic-gate #else
141*0Sstevel@tonic-gate 	return (0);
142*0Sstevel@tonic-gate #endif
143*0Sstevel@tonic-gate }
144*0Sstevel@tonic-gate 
145*0Sstevel@tonic-gate /* Shared private. */
146*0Sstevel@tonic-gate 
147*0Sstevel@tonic-gate struct hostent *
148*0Sstevel@tonic-gate gethostbyname_p(const char *name, struct net_data *net_data) {
149*0Sstevel@tonic-gate 	struct hostent *hp;
150*0Sstevel@tonic-gate 
151*0Sstevel@tonic-gate 	if (!net_data)
152*0Sstevel@tonic-gate #ifdef	SUNW_SETHERRNO
153*0Sstevel@tonic-gate 	{
154*0Sstevel@tonic-gate 		/*
155*0Sstevel@tonic-gate 		*  Should set the context h_errno, but since net_data
156*0Sstevel@tonic-gate 		 * is NULL, we don't have a context.
157*0Sstevel@tonic-gate 		 */
158*0Sstevel@tonic-gate 		h_errno = NETDB_INTERNAL;
159*0Sstevel@tonic-gate 		return (NULL);
160*0Sstevel@tonic-gate 	}
161*0Sstevel@tonic-gate #else
162*0Sstevel@tonic-gate 		return (NULL);
163*0Sstevel@tonic-gate #endif	/* SUNW_SETHERRNO */
164*0Sstevel@tonic-gate 
165*0Sstevel@tonic-gate 	if (net_data->res->options & RES_USE_INET6) {
166*0Sstevel@tonic-gate 		hp = gethostbyname2_p(name, AF_INET6, net_data);
167*0Sstevel@tonic-gate 		if (hp)
168*0Sstevel@tonic-gate 			return (hp);
169*0Sstevel@tonic-gate 	}
170*0Sstevel@tonic-gate 	return (gethostbyname2_p(name, AF_INET, net_data));
171*0Sstevel@tonic-gate }
172*0Sstevel@tonic-gate 
173*0Sstevel@tonic-gate struct hostent *
174*0Sstevel@tonic-gate gethostbyname2_p(const char *name, int af, struct net_data *net_data) {
175*0Sstevel@tonic-gate 	struct irs_ho *ho;
176*0Sstevel@tonic-gate 	char tmp[NS_MAXDNAME];
177*0Sstevel@tonic-gate 	struct hostent *hp;
178*0Sstevel@tonic-gate 	const char *cp;
179*0Sstevel@tonic-gate 	char **hap;
180*0Sstevel@tonic-gate 
181*0Sstevel@tonic-gate 	if (!net_data || !(ho = net_data->ho))
182*0Sstevel@tonic-gate #ifdef	SUNW_SETHERRNO
183*0Sstevel@tonic-gate 	{
184*0Sstevel@tonic-gate 		h_errno = NETDB_INTERNAL;
185*0Sstevel@tonic-gate 		return (NULL);
186*0Sstevel@tonic-gate 	}
187*0Sstevel@tonic-gate #else
188*0Sstevel@tonic-gate 		return (NULL);
189*0Sstevel@tonic-gate #endif	/* SUNW_SETHERRNO */
190*0Sstevel@tonic-gate 	if (net_data->ho_stayopen && net_data->ho_last &&
191*0Sstevel@tonic-gate 	net_data->ho_last->h_addrtype == af) {
192*0Sstevel@tonic-gate 		if (ns_samename(name, net_data->ho_last->h_name) == 1)
193*0Sstevel@tonic-gate 			return (net_data->ho_last);
194*0Sstevel@tonic-gate 		for (hap = net_data->ho_last->h_aliases; hap && *hap; hap++)
195*0Sstevel@tonic-gate 			if (ns_samename(name, *hap) == 1)
196*0Sstevel@tonic-gate 				return (net_data->ho_last);
197*0Sstevel@tonic-gate 	}
198*0Sstevel@tonic-gate 	if (!strchr(name, '.') && (cp = res_hostalias(net_data->res, name,
199*0Sstevel@tonic-gate 						      tmp, sizeof tmp)))
200*0Sstevel@tonic-gate 		name = cp;
201*0Sstevel@tonic-gate 	if ((hp = fakeaddr(name, af, net_data)) != NULL)
202*0Sstevel@tonic-gate 		return (hp);
203*0Sstevel@tonic-gate #ifdef	SUNW_OVERRIDE_RETRY
204*0Sstevel@tonic-gate 	net_data->res->retry = __res_retry(net_data->res->retry);
205*0Sstevel@tonic-gate #endif	/* SUNW_OVERRIDE_RETRY */
206*0Sstevel@tonic-gate 	net_data->ho_last = (*ho->byname2)(ho, name, af);
207*0Sstevel@tonic-gate #ifdef	SUNW_OVERRIDE_RETRY
208*0Sstevel@tonic-gate 	net_data->res->retry = __res_retry_reset();
209*0Sstevel@tonic-gate #endif	/* SUNW_OVERRIDE_RETRY */
210*0Sstevel@tonic-gate 	if (!net_data->ho_stayopen)
211*0Sstevel@tonic-gate 		endhostent();
212*0Sstevel@tonic-gate 	return (net_data->ho_last);
213*0Sstevel@tonic-gate }
214*0Sstevel@tonic-gate 
215*0Sstevel@tonic-gate struct hostent *
216*0Sstevel@tonic-gate gethostbyaddr_p(const char *addr, int len, int af, struct net_data *net_data) {
217*0Sstevel@tonic-gate 	struct irs_ho *ho;
218*0Sstevel@tonic-gate 	char **hap;
219*0Sstevel@tonic-gate 
220*0Sstevel@tonic-gate 	if (!net_data || !(ho = net_data->ho))
221*0Sstevel@tonic-gate #ifdef	SUNW_SETHERRNO
222*0Sstevel@tonic-gate 	{
223*0Sstevel@tonic-gate 		h_errno = NETDB_INTERNAL;
224*0Sstevel@tonic-gate 		return (NULL);
225*0Sstevel@tonic-gate 	}
226*0Sstevel@tonic-gate #else
227*0Sstevel@tonic-gate 		return (NULL);
228*0Sstevel@tonic-gate #endif	/* SUNW_SETHERRNO */
229*0Sstevel@tonic-gate 	if (net_data->ho_stayopen && net_data->ho_last &&
230*0Sstevel@tonic-gate 	    net_data->ho_last->h_length == len)
231*0Sstevel@tonic-gate 		for (hap = net_data->ho_last->h_addr_list;
232*0Sstevel@tonic-gate 		     hap && *hap;
233*0Sstevel@tonic-gate 		     hap++)
234*0Sstevel@tonic-gate 			if (!memcmp(addr, *hap, len))
235*0Sstevel@tonic-gate 				return (net_data->ho_last);
236*0Sstevel@tonic-gate 	net_data->ho_last = (*ho->byaddr)(ho, addr, len, af);
237*0Sstevel@tonic-gate 	if (!net_data->ho_stayopen)
238*0Sstevel@tonic-gate 		endhostent();
239*0Sstevel@tonic-gate 	return (net_data->ho_last);
240*0Sstevel@tonic-gate }
241*0Sstevel@tonic-gate 
242*0Sstevel@tonic-gate 
243*0Sstevel@tonic-gate struct hostent *
244*0Sstevel@tonic-gate gethostent_p(struct net_data *net_data) {
245*0Sstevel@tonic-gate 	struct irs_ho *ho;
246*0Sstevel@tonic-gate 	struct hostent *hp;
247*0Sstevel@tonic-gate 
248*0Sstevel@tonic-gate 	if (!net_data || !(ho = net_data->ho))
249*0Sstevel@tonic-gate #ifdef	SUNW_SETHERRNO
250*0Sstevel@tonic-gate 	{
251*0Sstevel@tonic-gate 		h_errno = NETDB_INTERNAL;
252*0Sstevel@tonic-gate 		return (NULL);
253*0Sstevel@tonic-gate 	}
254*0Sstevel@tonic-gate #else
255*0Sstevel@tonic-gate 		return (NULL);
256*0Sstevel@tonic-gate #endif	/* SUNW_SETHERRNO */
257*0Sstevel@tonic-gate 	while ((hp = (*ho->next)(ho)) != NULL &&
258*0Sstevel@tonic-gate 	       hp->h_addrtype == AF_INET6 &&
259*0Sstevel@tonic-gate 	       (net_data->res->options & RES_USE_INET6) == 0)
260*0Sstevel@tonic-gate 		continue;
261*0Sstevel@tonic-gate 	net_data->ho_last = hp;
262*0Sstevel@tonic-gate 	return (net_data->ho_last);
263*0Sstevel@tonic-gate }
264*0Sstevel@tonic-gate 
265*0Sstevel@tonic-gate 
266*0Sstevel@tonic-gate void
267*0Sstevel@tonic-gate sethostent_p(int stayopen, struct net_data *net_data) {
268*0Sstevel@tonic-gate 	struct irs_ho *ho;
269*0Sstevel@tonic-gate 
270*0Sstevel@tonic-gate 	if (!net_data || !(ho = net_data->ho))
271*0Sstevel@tonic-gate 		return;
272*0Sstevel@tonic-gate 	freepvt(net_data);
273*0Sstevel@tonic-gate 	(*ho->rewind)(ho);
274*0Sstevel@tonic-gate 	net_data->ho_stayopen = (stayopen != 0);
275*0Sstevel@tonic-gate 	if (stayopen == 0)
276*0Sstevel@tonic-gate 		net_data_minimize(net_data);
277*0Sstevel@tonic-gate }
278*0Sstevel@tonic-gate 
279*0Sstevel@tonic-gate void
280*0Sstevel@tonic-gate endhostent_p(struct net_data *net_data) {
281*0Sstevel@tonic-gate 	struct irs_ho *ho;
282*0Sstevel@tonic-gate 
283*0Sstevel@tonic-gate 	if ((net_data != NULL) && ((ho = net_data->ho) != NULL))
284*0Sstevel@tonic-gate 		(*ho->minimize)(ho);
285*0Sstevel@tonic-gate }
286*0Sstevel@tonic-gate 
287*0Sstevel@tonic-gate #ifndef IN6_IS_ADDR_V4COMPAT
288*0Sstevel@tonic-gate static const unsigned char in6addr_compat[12] = {
289*0Sstevel@tonic-gate 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
290*0Sstevel@tonic-gate #define IN6_IS_ADDR_V4COMPAT(x) (!memcmp((x)->s6_addr, in6addr_compat, 12) && \
291*0Sstevel@tonic-gate 				 ((x)->s6_addr[12] != 0 || \
292*0Sstevel@tonic-gate 				  (x)->s6_addr[13] != 0 || \
293*0Sstevel@tonic-gate 				  (x)->s6_addr[14] != 0 || \
294*0Sstevel@tonic-gate 				   ((x)->s6_addr[15] != 0 && \
295*0Sstevel@tonic-gate 				    (x)->s6_addr[15] != 1)))
296*0Sstevel@tonic-gate #endif
297*0Sstevel@tonic-gate #ifndef IN6_IS_ADDR_V4MAPPED
298*0Sstevel@tonic-gate #define IN6_IS_ADDR_V4MAPPED(x) (!memcmp((x)->s6_addr, in6addr_mapped, 12))
299*0Sstevel@tonic-gate #endif
300*0Sstevel@tonic-gate 
301*0Sstevel@tonic-gate static const unsigned char in6addr_mapped[12] = {
302*0Sstevel@tonic-gate 	0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0xff, 0xff };
303*0Sstevel@tonic-gate 
304*0Sstevel@tonic-gate static int scan_interfaces(int *, int *);
305*0Sstevel@tonic-gate static struct hostent *copyandmerge(struct hostent *, struct hostent *, int, int *);
306*0Sstevel@tonic-gate 
307*0Sstevel@tonic-gate /*
308*0Sstevel@tonic-gate  *	Public functions
309*0Sstevel@tonic-gate  */
310*0Sstevel@tonic-gate 
311*0Sstevel@tonic-gate /*
312*0Sstevel@tonic-gate  *	AI_V4MAPPED + AF_INET6
313*0Sstevel@tonic-gate  *	If no IPv6 address then a query for IPv4 and map returned values.
314*0Sstevel@tonic-gate  *
315*0Sstevel@tonic-gate  *	AI_ALL + AI_V4MAPPED + AF_INET6
316*0Sstevel@tonic-gate  *	Return IPv6 and IPv4 mapped.
317*0Sstevel@tonic-gate  *
318*0Sstevel@tonic-gate  *	AI_ADDRCONFIG
319*0Sstevel@tonic-gate  *	Only return IPv6 / IPv4 address if there is an interface of that
320*0Sstevel@tonic-gate  *	type active.
321*0Sstevel@tonic-gate  */
322*0Sstevel@tonic-gate 
323*0Sstevel@tonic-gate struct hostent *
324*0Sstevel@tonic-gate getipnodebyname(const char *name, int af, int flags, int *error_num) {
325*0Sstevel@tonic-gate 	int have_v4 = 1, have_v6 = 1;
326*0Sstevel@tonic-gate 	struct in_addr in4;
327*0Sstevel@tonic-gate 	struct in6_addr in6;
328*0Sstevel@tonic-gate 	struct hostent he, *he1 = NULL, *he2 = NULL, *he3;
329*0Sstevel@tonic-gate 	int v4 = 0, v6 = 0;
330*0Sstevel@tonic-gate 	struct net_data *net_data = init();
331*0Sstevel@tonic-gate 	u_long options;
332*0Sstevel@tonic-gate 	int tmp_err;
333*0Sstevel@tonic-gate 
334*0Sstevel@tonic-gate 	if (net_data == NULL) {
335*0Sstevel@tonic-gate 		*error_num = NO_RECOVERY;
336*0Sstevel@tonic-gate 		return (NULL);
337*0Sstevel@tonic-gate 	}
338*0Sstevel@tonic-gate 
339*0Sstevel@tonic-gate 	/* If we care about active interfaces then check. */
340*0Sstevel@tonic-gate 	if ((flags & AI_ADDRCONFIG) != 0)
341*0Sstevel@tonic-gate 		if (scan_interfaces(&have_v4, &have_v6) == -1) {
342*0Sstevel@tonic-gate 			*error_num = NO_RECOVERY;
343*0Sstevel@tonic-gate 			return (NULL);
344*0Sstevel@tonic-gate 		}
345*0Sstevel@tonic-gate 
346*0Sstevel@tonic-gate 	/* Check for literal address. */
347*0Sstevel@tonic-gate 	if ((v4 = inet_pton(AF_INET, name, &in4)) != 1)
348*0Sstevel@tonic-gate 		v6 = inet_pton(AF_INET6, name, &in6);
349*0Sstevel@tonic-gate 
350*0Sstevel@tonic-gate 	/* Impossible combination? */
351*0Sstevel@tonic-gate 
352*0Sstevel@tonic-gate 	if ((af == AF_INET6 && (flags & AI_V4MAPPED) == 0 && v4 == 1) ||
353*0Sstevel@tonic-gate 	    (af == AF_INET && v6 == 1) ||
354*0Sstevel@tonic-gate 	    (have_v4 == 0 && v4 == 1) ||
355*0Sstevel@tonic-gate 	    (have_v6 == 0 && v6 == 1) ||
356*0Sstevel@tonic-gate 	    (have_v4 == 0 && af == AF_INET) ||
357*0Sstevel@tonic-gate 	    (have_v6 == 0 && af == AF_INET6)) {
358*0Sstevel@tonic-gate 		*error_num = HOST_NOT_FOUND;
359*0Sstevel@tonic-gate 		return (NULL);
360*0Sstevel@tonic-gate 	}
361*0Sstevel@tonic-gate 
362*0Sstevel@tonic-gate 	/* Literal address? */
363*0Sstevel@tonic-gate 	if (v4 == 1 || v6 == 1) {
364*0Sstevel@tonic-gate 		char *addr_list[2];
365*0Sstevel@tonic-gate 		char *aliases[1];
366*0Sstevel@tonic-gate 
367*0Sstevel@tonic-gate 		DE_CONST(name, he.h_name);
368*0Sstevel@tonic-gate 		he.h_addr_list = addr_list;
369*0Sstevel@tonic-gate 		he.h_addr_list[0] = (v4 == 1) ? (char *)&in4 : (char *)&in6;
370*0Sstevel@tonic-gate 		he.h_addr_list[1] = NULL;
371*0Sstevel@tonic-gate 		he.h_aliases = aliases;
372*0Sstevel@tonic-gate 		he.h_aliases[0] = NULL;
373*0Sstevel@tonic-gate 		he.h_length = (v4 == 1) ? INADDRSZ : IN6ADDRSZ;
374*0Sstevel@tonic-gate 		he.h_addrtype = (v4 == 1) ? AF_INET : AF_INET6;
375*0Sstevel@tonic-gate 		return (copyandmerge(&he, NULL, af, error_num));
376*0Sstevel@tonic-gate 	}
377*0Sstevel@tonic-gate 
378*0Sstevel@tonic-gate 	options = net_data->res->options;
379*0Sstevel@tonic-gate 	net_data->res->options &= ~RES_USE_INET6;
380*0Sstevel@tonic-gate 
381*0Sstevel@tonic-gate 	tmp_err = NO_RECOVERY;
382*0Sstevel@tonic-gate 	if (have_v6 && af == AF_INET6) {
383*0Sstevel@tonic-gate 		he2 = gethostbyname2_p(name, AF_INET6, net_data);
384*0Sstevel@tonic-gate 		if (he2 != NULL) {
385*0Sstevel@tonic-gate 			he1 = copyandmerge(he2, NULL, af, error_num);
386*0Sstevel@tonic-gate 			if (he1 == NULL)
387*0Sstevel@tonic-gate 				return (NULL);
388*0Sstevel@tonic-gate 			he2 = NULL;
389*0Sstevel@tonic-gate 		} else {
390*0Sstevel@tonic-gate 			tmp_err = net_data->res->res_h_errno;
391*0Sstevel@tonic-gate 		}
392*0Sstevel@tonic-gate 	}
393*0Sstevel@tonic-gate 
394*0Sstevel@tonic-gate 	if (have_v4 &&
395*0Sstevel@tonic-gate 	    ((af == AF_INET) ||
396*0Sstevel@tonic-gate 	     (af == AF_INET6 && (flags & AI_V4MAPPED) != 0 &&
397*0Sstevel@tonic-gate 	      (he1 == NULL || (flags & AI_ALL) != 0)))) {
398*0Sstevel@tonic-gate 		he2 = gethostbyname2_p(name, AF_INET, net_data);
399*0Sstevel@tonic-gate 		if (he1 == NULL && he2 == NULL) {
400*0Sstevel@tonic-gate 			*error_num = net_data->res->res_h_errno;
401*0Sstevel@tonic-gate 			return (NULL);
402*0Sstevel@tonic-gate 		}
403*0Sstevel@tonic-gate 	} else
404*0Sstevel@tonic-gate 		*error_num = tmp_err;
405*0Sstevel@tonic-gate 
406*0Sstevel@tonic-gate 	net_data->res->options = options;
407*0Sstevel@tonic-gate 
408*0Sstevel@tonic-gate 	he3 = copyandmerge(he1, he2, af, error_num);
409*0Sstevel@tonic-gate 
410*0Sstevel@tonic-gate 	if (he1 != NULL)
411*0Sstevel@tonic-gate 		freehostent(he1);
412*0Sstevel@tonic-gate 	return (he3);
413*0Sstevel@tonic-gate }
414*0Sstevel@tonic-gate 
415*0Sstevel@tonic-gate struct hostent *
416*0Sstevel@tonic-gate getipnodebyaddr(const void *src, size_t len, int af, int *error_num) {
417*0Sstevel@tonic-gate 	struct hostent *he1, *he2;
418*0Sstevel@tonic-gate 	struct net_data *net_data = init();
419*0Sstevel@tonic-gate 
420*0Sstevel@tonic-gate 	/* Sanity Checks. */
421*0Sstevel@tonic-gate 	if (src == NULL) {
422*0Sstevel@tonic-gate 		*error_num = NO_RECOVERY;
423*0Sstevel@tonic-gate 		return (NULL);
424*0Sstevel@tonic-gate 	}
425*0Sstevel@tonic-gate 
426*0Sstevel@tonic-gate 	switch (af) {
427*0Sstevel@tonic-gate 	case AF_INET:
428*0Sstevel@tonic-gate 		if (len != INADDRSZ) {
429*0Sstevel@tonic-gate 			*error_num = NO_RECOVERY;
430*0Sstevel@tonic-gate 			return (NULL);
431*0Sstevel@tonic-gate 		}
432*0Sstevel@tonic-gate 		break;
433*0Sstevel@tonic-gate 	case AF_INET6:
434*0Sstevel@tonic-gate 		if (len != IN6ADDRSZ) {
435*0Sstevel@tonic-gate 			*error_num = NO_RECOVERY;
436*0Sstevel@tonic-gate 			return (NULL);
437*0Sstevel@tonic-gate 		}
438*0Sstevel@tonic-gate 		break;
439*0Sstevel@tonic-gate 	default:
440*0Sstevel@tonic-gate 		*error_num = NO_RECOVERY;
441*0Sstevel@tonic-gate 		return (NULL);
442*0Sstevel@tonic-gate 	}
443*0Sstevel@tonic-gate 
444*0Sstevel@tonic-gate 	/*
445*0Sstevel@tonic-gate 	 * Lookup IPv4 and IPv4 mapped/compatible addresses
446*0Sstevel@tonic-gate 	 */
447*0Sstevel@tonic-gate 	if ((af == AF_INET6 &&
448*0Sstevel@tonic-gate 	     IN6_IS_ADDR_V4COMPAT((const struct in6_addr *)src)) ||
449*0Sstevel@tonic-gate 	    (af == AF_INET6 &&
450*0Sstevel@tonic-gate 	     IN6_IS_ADDR_V4MAPPED((const struct in6_addr *)src)) ||
451*0Sstevel@tonic-gate 	    (af == AF_INET)) {
452*0Sstevel@tonic-gate 		const char *cp = src;
453*0Sstevel@tonic-gate 
454*0Sstevel@tonic-gate 		if (af == AF_INET6)
455*0Sstevel@tonic-gate 			cp += 12;
456*0Sstevel@tonic-gate 		he1 = gethostbyaddr_p(cp, 4, AF_INET, net_data);
457*0Sstevel@tonic-gate 		if (he1 == NULL) {
458*0Sstevel@tonic-gate 			*error_num = net_data->res->res_h_errno;
459*0Sstevel@tonic-gate 			return (NULL);
460*0Sstevel@tonic-gate 		}
461*0Sstevel@tonic-gate 		he2 = copyandmerge(he1, NULL, af, error_num);
462*0Sstevel@tonic-gate 		if (he2 == NULL)
463*0Sstevel@tonic-gate 			return (NULL);
464*0Sstevel@tonic-gate 		/*
465*0Sstevel@tonic-gate 		 * Restore original address if mapped/compatible.
466*0Sstevel@tonic-gate 		 */
467*0Sstevel@tonic-gate 		if (af == AF_INET6)
468*0Sstevel@tonic-gate 			memcpy(he1->h_addr, src, len);
469*0Sstevel@tonic-gate 		return (he2);
470*0Sstevel@tonic-gate 	}
471*0Sstevel@tonic-gate 
472*0Sstevel@tonic-gate 	/*
473*0Sstevel@tonic-gate 	 * Lookup IPv6 address.
474*0Sstevel@tonic-gate 	 */
475*0Sstevel@tonic-gate 	if (memcmp((const struct in6_addr *)src, &in6addr_any, 16) == 0) {
476*0Sstevel@tonic-gate 		*error_num = HOST_NOT_FOUND;
477*0Sstevel@tonic-gate 		return (NULL);
478*0Sstevel@tonic-gate 	}
479*0Sstevel@tonic-gate 
480*0Sstevel@tonic-gate 	he1 = gethostbyaddr_p(src, 16, AF_INET6, net_data);
481*0Sstevel@tonic-gate 	if (he1 == NULL) {
482*0Sstevel@tonic-gate 		*error_num = net_data->res->res_h_errno;
483*0Sstevel@tonic-gate 		return (NULL);
484*0Sstevel@tonic-gate 	}
485*0Sstevel@tonic-gate 	return (copyandmerge(he1, NULL, af, error_num));
486*0Sstevel@tonic-gate }
487*0Sstevel@tonic-gate 
488*0Sstevel@tonic-gate void
489*0Sstevel@tonic-gate freehostent(struct hostent *he) {
490*0Sstevel@tonic-gate 	char **cpp;
491*0Sstevel@tonic-gate 	int names = 1;
492*0Sstevel@tonic-gate 	int addresses = 1;
493*0Sstevel@tonic-gate 
494*0Sstevel@tonic-gate 	memput(he->h_name, strlen(he->h_name) + 1);
495*0Sstevel@tonic-gate 
496*0Sstevel@tonic-gate 	cpp = he->h_addr_list;
497*0Sstevel@tonic-gate 	while (*cpp != NULL) {
498*0Sstevel@tonic-gate 		memput(*cpp, (he->h_addrtype == AF_INET) ?
499*0Sstevel@tonic-gate 			     INADDRSZ : IN6ADDRSZ);
500*0Sstevel@tonic-gate 		*cpp = NULL;
501*0Sstevel@tonic-gate 		cpp++;
502*0Sstevel@tonic-gate 		addresses++;
503*0Sstevel@tonic-gate 	}
504*0Sstevel@tonic-gate 
505*0Sstevel@tonic-gate 	cpp = he->h_aliases;
506*0Sstevel@tonic-gate 	while (*cpp != NULL) {
507*0Sstevel@tonic-gate 		memput(*cpp, strlen(*cpp) + 1);
508*0Sstevel@tonic-gate 		cpp++;
509*0Sstevel@tonic-gate 		names++;
510*0Sstevel@tonic-gate 	}
511*0Sstevel@tonic-gate 
512*0Sstevel@tonic-gate 	memput(he->h_aliases, sizeof(char *) * (names));
513*0Sstevel@tonic-gate 	memput(he->h_addr_list, sizeof(char *) * (addresses));
514*0Sstevel@tonic-gate 	memput(he, sizeof *he);
515*0Sstevel@tonic-gate }
516*0Sstevel@tonic-gate 
517*0Sstevel@tonic-gate /*
518*0Sstevel@tonic-gate  * Private
519*0Sstevel@tonic-gate  */
520*0Sstevel@tonic-gate 
521*0Sstevel@tonic-gate /*
522*0Sstevel@tonic-gate  * Scan the interface table and set have_v4 and have_v6 depending
523*0Sstevel@tonic-gate  * upon whether there are IPv4 and IPv6 interface addresses.
524*0Sstevel@tonic-gate  *
525*0Sstevel@tonic-gate  * Returns:
526*0Sstevel@tonic-gate  *	0 on success
527*0Sstevel@tonic-gate  *	-1 on failure.
528*0Sstevel@tonic-gate  */
529*0Sstevel@tonic-gate 
530*0Sstevel@tonic-gate #if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR) && \
531*0Sstevel@tonic-gate     !defined(IRIX_EMUL_IOCTL_SIOCGIFCONF)
532*0Sstevel@tonic-gate 
533*0Sstevel@tonic-gate #define SETFAMILYFLAGS
534*0Sstevel@tonic-gate #define LIFCONF lifconf
535*0Sstevel@tonic-gate #define LIFREQ lifreq
536*0Sstevel@tonic-gate 
537*0Sstevel@tonic-gate static void
538*0Sstevel@tonic-gate scan_interfaces6(int *have_v4, int *have_v6) {
539*0Sstevel@tonic-gate 	struct LIFCONF lifc;
540*0Sstevel@tonic-gate 	struct LIFREQ lifreq;
541*0Sstevel@tonic-gate 	struct in_addr in4;
542*0Sstevel@tonic-gate 	struct in6_addr in6;
543*0Sstevel@tonic-gate 	char *buf = NULL, *cp, *cplim;
544*0Sstevel@tonic-gate 	static unsigned int bufsiz = 4095;
545*0Sstevel@tonic-gate 	int s, cpsize, n;
546*0Sstevel@tonic-gate 
547*0Sstevel@tonic-gate 	/* Get interface list from system. */
548*0Sstevel@tonic-gate 	if ((s = socket(AF_INET6, SOCK_DGRAM, 0)) == -1)
549*0Sstevel@tonic-gate 		goto cleanup;
550*0Sstevel@tonic-gate 
551*0Sstevel@tonic-gate 	/*
552*0Sstevel@tonic-gate 	 * Grow buffer until large enough to contain all interface
553*0Sstevel@tonic-gate 	 * descriptions.
554*0Sstevel@tonic-gate 	 */
555*0Sstevel@tonic-gate 	for (;;) {
556*0Sstevel@tonic-gate 		buf = memget(bufsiz);
557*0Sstevel@tonic-gate 		if (buf == NULL)
558*0Sstevel@tonic-gate 			goto cleanup;
559*0Sstevel@tonic-gate #ifdef SETFAMILYFLAGS
560*0Sstevel@tonic-gate 		lifc.lifc_family = AF_UNSPEC;	/* request all families */
561*0Sstevel@tonic-gate 		lifc.lifc_flags = 0;
562*0Sstevel@tonic-gate #endif
563*0Sstevel@tonic-gate 		lifc.lifc_len = bufsiz;
564*0Sstevel@tonic-gate 		lifc.lifc_buf = buf;
565*0Sstevel@tonic-gate 		if ((n = ioctl(s, SIOCGLIFCONF, (char *)&lifc)) != -1) {
566*0Sstevel@tonic-gate 			/*
567*0Sstevel@tonic-gate 			 * Some OS's just return what will fit rather
568*0Sstevel@tonic-gate 			 * than set EINVAL if the buffer is too small
569*0Sstevel@tonic-gate 			 * to fit all the interfaces in.  If
570*0Sstevel@tonic-gate 			 * lifc.lifc_len is too near to the end of the
571*0Sstevel@tonic-gate 			 * buffer we will grow it just in case and
572*0Sstevel@tonic-gate 			 * retry.
573*0Sstevel@tonic-gate 			 */
574*0Sstevel@tonic-gate 			if (lifc.lifc_len + 2 * sizeof(lifreq) < bufsiz)
575*0Sstevel@tonic-gate 				break;
576*0Sstevel@tonic-gate 		}
577*0Sstevel@tonic-gate 		if ((n == -1) && errno != EINVAL)
578*0Sstevel@tonic-gate 			goto cleanup;
579*0Sstevel@tonic-gate 
580*0Sstevel@tonic-gate 		if (bufsiz > 1000000)
581*0Sstevel@tonic-gate 			goto cleanup;
582*0Sstevel@tonic-gate 
583*0Sstevel@tonic-gate 		memput(buf, bufsiz);
584*0Sstevel@tonic-gate 		bufsiz += 4096;
585*0Sstevel@tonic-gate 	}
586*0Sstevel@tonic-gate 
587*0Sstevel@tonic-gate 	/* Parse system's interface list. */
588*0Sstevel@tonic-gate 	cplim = buf + lifc.lifc_len;    /* skip over if's with big ifr_addr's */
589*0Sstevel@tonic-gate 	for (cp = buf;
590*0Sstevel@tonic-gate 	     (*have_v4 == 0 || *have_v6 == 0) && cp < cplim;
591*0Sstevel@tonic-gate 	     cp += cpsize) {
592*0Sstevel@tonic-gate 		memcpy(&lifreq, cp, sizeof lifreq);
593*0Sstevel@tonic-gate #ifdef HAVE_SA_LEN
594*0Sstevel@tonic-gate #ifdef FIX_ZERO_SA_LEN
595*0Sstevel@tonic-gate 		if (lifreq.lifr_addr.sa_len == 0)
596*0Sstevel@tonic-gate 			lifreq.lifr_addr.sa_len = 16;
597*0Sstevel@tonic-gate #endif
598*0Sstevel@tonic-gate #ifdef HAVE_MINIMUM_IFREQ
599*0Sstevel@tonic-gate 		cpsize = sizeof lifreq;
600*0Sstevel@tonic-gate 		if (lifreq.lifr_addr.sa_len > sizeof (struct sockaddr))
601*0Sstevel@tonic-gate 			cpsize += (int)lifreq.lifr_addr.sa_len -
602*0Sstevel@tonic-gate 				(int)(sizeof (struct sockaddr));
603*0Sstevel@tonic-gate #else
604*0Sstevel@tonic-gate 		cpsize = sizeof lifreq.lifr_name + lifreq.lifr_addr.sa_len;
605*0Sstevel@tonic-gate #endif /* HAVE_MINIMUM_IFREQ */
606*0Sstevel@tonic-gate #elif defined SIOCGIFCONF_ADDR
607*0Sstevel@tonic-gate 		cpsize = sizeof lifreq;
608*0Sstevel@tonic-gate #else
609*0Sstevel@tonic-gate 		cpsize = sizeof lifreq.lifr_name;
610*0Sstevel@tonic-gate 		/* XXX maybe this should be a hard error? */
611*0Sstevel@tonic-gate 		if (ioctl(s, SIOCGLIFADDR, (char *)&lifreq) < 0)
612*0Sstevel@tonic-gate 			continue;
613*0Sstevel@tonic-gate #endif
614*0Sstevel@tonic-gate 		switch (lifreq.lifr_addr.ss_family) {
615*0Sstevel@tonic-gate 		case AF_INET:
616*0Sstevel@tonic-gate 			if (*have_v4 == 0) {
617*0Sstevel@tonic-gate 				memcpy(&in4,
618*0Sstevel@tonic-gate 				       &((struct sockaddr_in *)
619*0Sstevel@tonic-gate 				       &lifreq.lifr_addr)->sin_addr,
620*0Sstevel@tonic-gate 				       sizeof in4);
621*0Sstevel@tonic-gate 				if (in4.s_addr == INADDR_ANY)
622*0Sstevel@tonic-gate 					break;
623*0Sstevel@tonic-gate 				n = ioctl(s, SIOCGLIFFLAGS, (char *)&lifreq);
624*0Sstevel@tonic-gate 				if (n < 0)
625*0Sstevel@tonic-gate 					break;
626*0Sstevel@tonic-gate 				if ((lifreq.lifr_flags & IFF_UP) == 0)
627*0Sstevel@tonic-gate 					break;
628*0Sstevel@tonic-gate 				*have_v4 = 1;
629*0Sstevel@tonic-gate 			}
630*0Sstevel@tonic-gate 			break;
631*0Sstevel@tonic-gate 		case AF_INET6:
632*0Sstevel@tonic-gate 			if (*have_v6 == 0) {
633*0Sstevel@tonic-gate 				memcpy(&in6,
634*0Sstevel@tonic-gate 				       &((struct sockaddr_in6 *)
635*0Sstevel@tonic-gate 				       &lifreq.lifr_addr)->sin6_addr, sizeof in6);
636*0Sstevel@tonic-gate 				if (memcmp(&in6, &in6addr_any, sizeof in6) == 0)
637*0Sstevel@tonic-gate 					break;
638*0Sstevel@tonic-gate 				n = ioctl(s, SIOCGLIFFLAGS, (char *)&lifreq);
639*0Sstevel@tonic-gate 				if (n < 0)
640*0Sstevel@tonic-gate 					break;
641*0Sstevel@tonic-gate 				if ((lifreq.lifr_flags & IFF_UP) == 0)
642*0Sstevel@tonic-gate 					break;
643*0Sstevel@tonic-gate 				*have_v6 = 1;
644*0Sstevel@tonic-gate 			}
645*0Sstevel@tonic-gate 			break;
646*0Sstevel@tonic-gate 		}
647*0Sstevel@tonic-gate 	}
648*0Sstevel@tonic-gate 	if (buf != NULL)
649*0Sstevel@tonic-gate 		memput(buf, bufsiz);
650*0Sstevel@tonic-gate 	close(s);
651*0Sstevel@tonic-gate 	/* printf("scan interface -> 4=%d 6=%d\n", *have_v4, *have_v6); */
652*0Sstevel@tonic-gate 	return;
653*0Sstevel@tonic-gate  cleanup:
654*0Sstevel@tonic-gate 	if (buf != NULL)
655*0Sstevel@tonic-gate 		memput(buf, bufsiz);
656*0Sstevel@tonic-gate 	if (s != -1)
657*0Sstevel@tonic-gate 		close(s);
658*0Sstevel@tonic-gate 	/* printf("scan interface -> 4=%d 6=%d\n", *have_v4, *have_v6); */
659*0Sstevel@tonic-gate 	return;
660*0Sstevel@tonic-gate }
661*0Sstevel@tonic-gate #endif
662*0Sstevel@tonic-gate 
663*0Sstevel@tonic-gate static int
664*0Sstevel@tonic-gate scan_interfaces(int *have_v4, int *have_v6) {
665*0Sstevel@tonic-gate 	struct ifconf ifc;
666*0Sstevel@tonic-gate 	union {
667*0Sstevel@tonic-gate 		char _pad[256];		/* leave space for IPv6 addresses */
668*0Sstevel@tonic-gate 		struct ifreq ifreq;
669*0Sstevel@tonic-gate 	} u;
670*0Sstevel@tonic-gate 	struct in_addr in4;
671*0Sstevel@tonic-gate 	struct in6_addr in6;
672*0Sstevel@tonic-gate 	char *buf = NULL, *cp, *cplim;
673*0Sstevel@tonic-gate 	static unsigned int bufsiz = 4095;
674*0Sstevel@tonic-gate 	int s, n;
675*0Sstevel@tonic-gate 	size_t cpsize;
676*0Sstevel@tonic-gate 
677*0Sstevel@tonic-gate 	/* Set to zero.  Used as loop terminators below. */
678*0Sstevel@tonic-gate 	*have_v4 = *have_v6 = 0;
679*0Sstevel@tonic-gate 
680*0Sstevel@tonic-gate #if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR) && \
681*0Sstevel@tonic-gate     !defined(IRIX_EMUL_IOCTL_SIOCGIFCONF)
682*0Sstevel@tonic-gate 	/*
683*0Sstevel@tonic-gate 	 * Try to scan the interfaces using IPv6 ioctls().
684*0Sstevel@tonic-gate 	 */
685*0Sstevel@tonic-gate 	scan_interfaces6(have_v4, have_v6);
686*0Sstevel@tonic-gate 	if (*have_v4 != 0 && *have_v6 != 0)
687*0Sstevel@tonic-gate 		return (0);
688*0Sstevel@tonic-gate #endif
689*0Sstevel@tonic-gate 
690*0Sstevel@tonic-gate 	/* Get interface list from system. */
691*0Sstevel@tonic-gate 	if ((s = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
692*0Sstevel@tonic-gate 		goto err_ret;
693*0Sstevel@tonic-gate 
694*0Sstevel@tonic-gate 	/*
695*0Sstevel@tonic-gate 	 * Grow buffer until large enough to contain all interface
696*0Sstevel@tonic-gate 	 * descriptions.
697*0Sstevel@tonic-gate 	 */
698*0Sstevel@tonic-gate 	for (;;) {
699*0Sstevel@tonic-gate 		buf = memget(bufsiz);
700*0Sstevel@tonic-gate 		if (buf == NULL)
701*0Sstevel@tonic-gate 			goto err_ret;
702*0Sstevel@tonic-gate 		ifc.ifc_len = bufsiz;
703*0Sstevel@tonic-gate 		ifc.ifc_buf = buf;
704*0Sstevel@tonic-gate #ifdef IRIX_EMUL_IOCTL_SIOCGIFCONF
705*0Sstevel@tonic-gate 		/*
706*0Sstevel@tonic-gate 		 * This is a fix for IRIX OS in which the call to ioctl with
707*0Sstevel@tonic-gate 		 * the flag SIOCGIFCONF may not return an entry for all the
708*0Sstevel@tonic-gate 		 * interfaces like most flavors of Unix.
709*0Sstevel@tonic-gate 		 */
710*0Sstevel@tonic-gate 		if (emul_ioctl(&ifc) >= 0)
711*0Sstevel@tonic-gate 			break;
712*0Sstevel@tonic-gate #else
713*0Sstevel@tonic-gate 		if ((n = ioctl(s, SIOCGIFCONF, (char *)&ifc)) != -1) {
714*0Sstevel@tonic-gate 			/*
715*0Sstevel@tonic-gate 			 * Some OS's just return what will fit rather
716*0Sstevel@tonic-gate 			 * than set EINVAL if the buffer is too small
717*0Sstevel@tonic-gate 			 * to fit all the interfaces in.  If
718*0Sstevel@tonic-gate 			 * ifc.ifc_len is too near to the end of the
719*0Sstevel@tonic-gate 			 * buffer we will grow it just in case and
720*0Sstevel@tonic-gate 			 * retry.
721*0Sstevel@tonic-gate 			 */
722*0Sstevel@tonic-gate 			if (ifc.ifc_len + 2 * sizeof(u.ifreq) < bufsiz)
723*0Sstevel@tonic-gate 				break;
724*0Sstevel@tonic-gate 		}
725*0Sstevel@tonic-gate #endif
726*0Sstevel@tonic-gate 		if ((n == -1) && errno != EINVAL)
727*0Sstevel@tonic-gate 			goto err_ret;
728*0Sstevel@tonic-gate 
729*0Sstevel@tonic-gate 		if (bufsiz > 1000000)
730*0Sstevel@tonic-gate 			goto err_ret;
731*0Sstevel@tonic-gate 
732*0Sstevel@tonic-gate 		memput(buf, bufsiz);
733*0Sstevel@tonic-gate 		bufsiz += 4096;
734*0Sstevel@tonic-gate 	}
735*0Sstevel@tonic-gate 
736*0Sstevel@tonic-gate 	/* Parse system's interface list. */
737*0Sstevel@tonic-gate 	cplim = buf + ifc.ifc_len;    /* skip over if's with big ifr_addr's */
738*0Sstevel@tonic-gate 	for (cp = buf;
739*0Sstevel@tonic-gate 	     (*have_v4 == 0 || *have_v6 == 0) && cp < cplim;
740*0Sstevel@tonic-gate 	     cp += cpsize) {
741*0Sstevel@tonic-gate 		memcpy(&u.ifreq, cp, sizeof u.ifreq);
742*0Sstevel@tonic-gate #ifdef HAVE_SA_LEN
743*0Sstevel@tonic-gate #ifdef FIX_ZERO_SA_LEN
744*0Sstevel@tonic-gate 		if (u.ifreq.ifr_addr.sa_len == 0)
745*0Sstevel@tonic-gate 			u.ifreq.ifr_addr.sa_len = 16;
746*0Sstevel@tonic-gate #endif
747*0Sstevel@tonic-gate #ifdef HAVE_MINIMUM_IFREQ
748*0Sstevel@tonic-gate 		cpsize = sizeof u.ifreq;
749*0Sstevel@tonic-gate 		if (u.ifreq.ifr_addr.sa_len > sizeof (struct sockaddr))
750*0Sstevel@tonic-gate 			cpsize += (int)u.ifreq.ifr_addr.sa_len -
751*0Sstevel@tonic-gate 				(int)(sizeof (struct sockaddr));
752*0Sstevel@tonic-gate #else
753*0Sstevel@tonic-gate 		cpsize = sizeof u.ifreq.ifr_name + u.ifreq.ifr_addr.sa_len;
754*0Sstevel@tonic-gate #endif /* HAVE_MINIMUM_IFREQ */
755*0Sstevel@tonic-gate 		if (cpsize > sizeof u.ifreq && cpsize <= sizeof u)
756*0Sstevel@tonic-gate 			memcpy(&u.ifreq, cp, cpsize);
757*0Sstevel@tonic-gate #elif defined SIOCGIFCONF_ADDR
758*0Sstevel@tonic-gate 		cpsize = sizeof u.ifreq;
759*0Sstevel@tonic-gate #else
760*0Sstevel@tonic-gate 		cpsize = sizeof u.ifreq.ifr_name;
761*0Sstevel@tonic-gate 		/* XXX maybe this should be a hard error? */
762*0Sstevel@tonic-gate 		if (ioctl(s, SIOCGIFADDR, (char *)&u.ifreq) < 0)
763*0Sstevel@tonic-gate 			continue;
764*0Sstevel@tonic-gate #endif
765*0Sstevel@tonic-gate 		switch (u.ifreq.ifr_addr.sa_family) {
766*0Sstevel@tonic-gate 		case AF_INET:
767*0Sstevel@tonic-gate 			if (*have_v4 == 0) {
768*0Sstevel@tonic-gate 				memcpy(&in4,
769*0Sstevel@tonic-gate 				       &((struct sockaddr_in *)
770*0Sstevel@tonic-gate 				       &u.ifreq.ifr_addr)->sin_addr,
771*0Sstevel@tonic-gate 				       sizeof in4);
772*0Sstevel@tonic-gate 				if (in4.s_addr == INADDR_ANY)
773*0Sstevel@tonic-gate 					break;
774*0Sstevel@tonic-gate 				n = ioctl(s, SIOCGIFFLAGS, (char *)&u.ifreq);
775*0Sstevel@tonic-gate 				if (n < 0)
776*0Sstevel@tonic-gate 					break;
777*0Sstevel@tonic-gate 				if ((u.ifreq.ifr_flags & IFF_UP) == 0)
778*0Sstevel@tonic-gate 					break;
779*0Sstevel@tonic-gate 				*have_v4 = 1;
780*0Sstevel@tonic-gate 			}
781*0Sstevel@tonic-gate 			break;
782*0Sstevel@tonic-gate 		case AF_INET6:
783*0Sstevel@tonic-gate 			if (*have_v6 == 0) {
784*0Sstevel@tonic-gate 				memcpy(&in6,
785*0Sstevel@tonic-gate 				       &((struct sockaddr_in6 *)
786*0Sstevel@tonic-gate 				       &u.ifreq.ifr_addr)->sin6_addr,
787*0Sstevel@tonic-gate 				       sizeof in6);
788*0Sstevel@tonic-gate 				if (memcmp(&in6, &in6addr_any, sizeof in6) == 0)
789*0Sstevel@tonic-gate 					break;
790*0Sstevel@tonic-gate 				n = ioctl(s, SIOCGIFFLAGS, (char *)&u.ifreq);
791*0Sstevel@tonic-gate 				if (n < 0)
792*0Sstevel@tonic-gate 					break;
793*0Sstevel@tonic-gate 				if ((u.ifreq.ifr_flags & IFF_UP) == 0)
794*0Sstevel@tonic-gate 					break;
795*0Sstevel@tonic-gate 				*have_v6 = 1;
796*0Sstevel@tonic-gate 			}
797*0Sstevel@tonic-gate 			break;
798*0Sstevel@tonic-gate 		}
799*0Sstevel@tonic-gate 	}
800*0Sstevel@tonic-gate 	if (buf != NULL)
801*0Sstevel@tonic-gate 		memput(buf, bufsiz);
802*0Sstevel@tonic-gate 	close(s);
803*0Sstevel@tonic-gate 	/* printf("scan interface -> 4=%d 6=%d\n", *have_v4, *have_v6); */
804*0Sstevel@tonic-gate 	return (0);
805*0Sstevel@tonic-gate  err_ret:
806*0Sstevel@tonic-gate 	if (buf != NULL)
807*0Sstevel@tonic-gate 		memput(buf, bufsiz);
808*0Sstevel@tonic-gate 	if (s != -1)
809*0Sstevel@tonic-gate 		close(s);
810*0Sstevel@tonic-gate 	/* printf("scan interface -> 4=%d 6=%d\n", *have_v4, *have_v6); */
811*0Sstevel@tonic-gate 	return (-1);
812*0Sstevel@tonic-gate }
813*0Sstevel@tonic-gate 
814*0Sstevel@tonic-gate static struct hostent *
815*0Sstevel@tonic-gate copyandmerge(struct hostent *he1, struct hostent *he2, int af, int *error_num) {
816*0Sstevel@tonic-gate 	struct hostent *he = NULL;
817*0Sstevel@tonic-gate 	int addresses = 1;	/* NULL terminator */
818*0Sstevel@tonic-gate 	int names = 1;		/* NULL terminator */
819*0Sstevel@tonic-gate 	int len = 0;
820*0Sstevel@tonic-gate 	char **cpp, **npp;
821*0Sstevel@tonic-gate 
822*0Sstevel@tonic-gate 	/*
823*0Sstevel@tonic-gate 	 * Work out array sizes;
824*0Sstevel@tonic-gate 	 */
825*0Sstevel@tonic-gate 	if (he1 != NULL) {
826*0Sstevel@tonic-gate 		cpp = he1->h_addr_list;
827*0Sstevel@tonic-gate 		while (*cpp != NULL) {
828*0Sstevel@tonic-gate 			addresses++;
829*0Sstevel@tonic-gate 			cpp++;
830*0Sstevel@tonic-gate 		}
831*0Sstevel@tonic-gate 		cpp = he1->h_aliases;
832*0Sstevel@tonic-gate 		while (*cpp != NULL) {
833*0Sstevel@tonic-gate 			names++;
834*0Sstevel@tonic-gate 			cpp++;
835*0Sstevel@tonic-gate 		}
836*0Sstevel@tonic-gate 	}
837*0Sstevel@tonic-gate 
838*0Sstevel@tonic-gate 	if (he2 != NULL) {
839*0Sstevel@tonic-gate 		cpp = he2->h_addr_list;
840*0Sstevel@tonic-gate 		while (*cpp != NULL) {
841*0Sstevel@tonic-gate 			addresses++;
842*0Sstevel@tonic-gate 			cpp++;
843*0Sstevel@tonic-gate 		}
844*0Sstevel@tonic-gate 		if (he1 == NULL) {
845*0Sstevel@tonic-gate 			cpp = he2->h_aliases;
846*0Sstevel@tonic-gate 			while (*cpp != NULL) {
847*0Sstevel@tonic-gate 				names++;
848*0Sstevel@tonic-gate 				cpp++;
849*0Sstevel@tonic-gate 			}
850*0Sstevel@tonic-gate 		}
851*0Sstevel@tonic-gate 	}
852*0Sstevel@tonic-gate 
853*0Sstevel@tonic-gate 	if (addresses == 1) {
854*0Sstevel@tonic-gate 		*error_num = NO_ADDRESS;
855*0Sstevel@tonic-gate 		return (NULL);
856*0Sstevel@tonic-gate 	}
857*0Sstevel@tonic-gate 
858*0Sstevel@tonic-gate 	he = memget(sizeof *he);
859*0Sstevel@tonic-gate 	if (he == NULL)
860*0Sstevel@tonic-gate 		goto no_recovery;
861*0Sstevel@tonic-gate 
862*0Sstevel@tonic-gate 	he->h_addr_list = memget(sizeof(char *) * (addresses));
863*0Sstevel@tonic-gate 	if (he->h_addr_list == NULL)
864*0Sstevel@tonic-gate 		goto cleanup0;
865*0Sstevel@tonic-gate 	memset(he->h_addr_list, 0, sizeof(char *) * (addresses));
866*0Sstevel@tonic-gate 
867*0Sstevel@tonic-gate 	/* copy addresses */
868*0Sstevel@tonic-gate 	npp = he->h_addr_list;
869*0Sstevel@tonic-gate 	if (he1 != NULL) {
870*0Sstevel@tonic-gate 		cpp = he1->h_addr_list;
871*0Sstevel@tonic-gate 		while (*cpp != NULL) {
872*0Sstevel@tonic-gate 			*npp = memget((af == AF_INET) ? INADDRSZ : IN6ADDRSZ);
873*0Sstevel@tonic-gate 			if (*npp == NULL)
874*0Sstevel@tonic-gate 				goto cleanup1;
875*0Sstevel@tonic-gate 			/* convert to mapped if required */
876*0Sstevel@tonic-gate 			if (af == AF_INET6 && he1->h_addrtype == AF_INET) {
877*0Sstevel@tonic-gate 				memcpy(*npp, in6addr_mapped,
878*0Sstevel@tonic-gate 				       sizeof in6addr_mapped);
879*0Sstevel@tonic-gate 				memcpy(*npp + sizeof in6addr_mapped, *cpp,
880*0Sstevel@tonic-gate 				       INADDRSZ);
881*0Sstevel@tonic-gate 			} else {
882*0Sstevel@tonic-gate 				memcpy(*npp, *cpp,
883*0Sstevel@tonic-gate 				       (af == AF_INET) ? INADDRSZ : IN6ADDRSZ);
884*0Sstevel@tonic-gate 			}
885*0Sstevel@tonic-gate 			cpp++;
886*0Sstevel@tonic-gate 			npp++;
887*0Sstevel@tonic-gate 		}
888*0Sstevel@tonic-gate 	}
889*0Sstevel@tonic-gate 
890*0Sstevel@tonic-gate 	if (he2 != NULL) {
891*0Sstevel@tonic-gate 		cpp = he2->h_addr_list;
892*0Sstevel@tonic-gate 		while (*cpp != NULL) {
893*0Sstevel@tonic-gate 			*npp = memget((af == AF_INET) ? INADDRSZ : IN6ADDRSZ);
894*0Sstevel@tonic-gate 			if (*npp == NULL)
895*0Sstevel@tonic-gate 				goto cleanup1;
896*0Sstevel@tonic-gate 			/* convert to mapped if required */
897*0Sstevel@tonic-gate 			if (af == AF_INET6 && he2->h_addrtype == AF_INET) {
898*0Sstevel@tonic-gate 				memcpy(*npp, in6addr_mapped,
899*0Sstevel@tonic-gate 				       sizeof in6addr_mapped);
900*0Sstevel@tonic-gate 				memcpy(*npp + sizeof in6addr_mapped, *cpp,
901*0Sstevel@tonic-gate 				       INADDRSZ);
902*0Sstevel@tonic-gate 			} else {
903*0Sstevel@tonic-gate 				memcpy(*npp, *cpp,
904*0Sstevel@tonic-gate 				       (af == AF_INET) ? INADDRSZ : IN6ADDRSZ);
905*0Sstevel@tonic-gate 			}
906*0Sstevel@tonic-gate 			cpp++;
907*0Sstevel@tonic-gate 			npp++;
908*0Sstevel@tonic-gate 		}
909*0Sstevel@tonic-gate 	}
910*0Sstevel@tonic-gate 
911*0Sstevel@tonic-gate 	he->h_aliases = memget(sizeof(char *) * (names));
912*0Sstevel@tonic-gate 	if (he->h_aliases == NULL)
913*0Sstevel@tonic-gate 		goto cleanup1;
914*0Sstevel@tonic-gate 	memset(he->h_aliases, 0, sizeof(char *) * (names));
915*0Sstevel@tonic-gate 
916*0Sstevel@tonic-gate 	/* copy aliases */
917*0Sstevel@tonic-gate 	npp = he->h_aliases;
918*0Sstevel@tonic-gate 	cpp = (he1 != NULL) ? he1->h_aliases : he2->h_aliases;
919*0Sstevel@tonic-gate 	while (*cpp != NULL) {
920*0Sstevel@tonic-gate 		len = strlen (*cpp) + 1;
921*0Sstevel@tonic-gate 		*npp = memget(len);
922*0Sstevel@tonic-gate 		if (*npp == NULL)
923*0Sstevel@tonic-gate 			goto cleanup2;
924*0Sstevel@tonic-gate 		strcpy(*npp, *cpp);
925*0Sstevel@tonic-gate 		npp++;
926*0Sstevel@tonic-gate 		cpp++;
927*0Sstevel@tonic-gate 	}
928*0Sstevel@tonic-gate 
929*0Sstevel@tonic-gate 	/* copy hostname */
930*0Sstevel@tonic-gate 	he->h_name = memget(strlen((he1 != NULL) ?
931*0Sstevel@tonic-gate 			    he1->h_name : he2->h_name) + 1);
932*0Sstevel@tonic-gate 	if (he->h_name == NULL)
933*0Sstevel@tonic-gate 		goto cleanup2;
934*0Sstevel@tonic-gate 	strcpy(he->h_name, (he1 != NULL) ? he1->h_name : he2->h_name);
935*0Sstevel@tonic-gate 
936*0Sstevel@tonic-gate 	/* set address type and length */
937*0Sstevel@tonic-gate 	he->h_addrtype = af;
938*0Sstevel@tonic-gate 	he->h_length = (af == AF_INET) ? INADDRSZ : IN6ADDRSZ;
939*0Sstevel@tonic-gate 	return(he);
940*0Sstevel@tonic-gate 
941*0Sstevel@tonic-gate  cleanup2:
942*0Sstevel@tonic-gate 	cpp = he->h_aliases;
943*0Sstevel@tonic-gate 	while (*cpp != NULL) {
944*0Sstevel@tonic-gate 		memput(*cpp, strlen(*cpp) + 1);
945*0Sstevel@tonic-gate 		cpp++;
946*0Sstevel@tonic-gate 	}
947*0Sstevel@tonic-gate 	memput(he->h_aliases, sizeof(char *) * (names));
948*0Sstevel@tonic-gate 
949*0Sstevel@tonic-gate  cleanup1:
950*0Sstevel@tonic-gate 	cpp = he->h_addr_list;
951*0Sstevel@tonic-gate 	while (*cpp != NULL) {
952*0Sstevel@tonic-gate 		memput(*cpp, (af == AF_INET) ? INADDRSZ : IN6ADDRSZ);
953*0Sstevel@tonic-gate 		*cpp = NULL;
954*0Sstevel@tonic-gate 		cpp++;
955*0Sstevel@tonic-gate 	}
956*0Sstevel@tonic-gate 	memput(he->h_addr_list, sizeof(char *) * (addresses));
957*0Sstevel@tonic-gate 
958*0Sstevel@tonic-gate  cleanup0:
959*0Sstevel@tonic-gate 	memput(he, sizeof *he);
960*0Sstevel@tonic-gate 
961*0Sstevel@tonic-gate  no_recovery:
962*0Sstevel@tonic-gate 	*error_num = NO_RECOVERY;
963*0Sstevel@tonic-gate 	return (NULL);
964*0Sstevel@tonic-gate }
965*0Sstevel@tonic-gate 
966*0Sstevel@tonic-gate static struct net_data *
967*0Sstevel@tonic-gate init() {
968*0Sstevel@tonic-gate 	struct net_data *net_data;
969*0Sstevel@tonic-gate 
970*0Sstevel@tonic-gate 	if (!(net_data = net_data_init(NULL)))
971*0Sstevel@tonic-gate 		goto error;
972*0Sstevel@tonic-gate 	if (!net_data->ho) {
973*0Sstevel@tonic-gate 		net_data->ho = (*net_data->irs->ho_map)(net_data->irs);
974*0Sstevel@tonic-gate 		if (!net_data->ho || !net_data->res) {
975*0Sstevel@tonic-gate   error:
976*0Sstevel@tonic-gate 			errno = EIO;
977*0Sstevel@tonic-gate 			if (net_data && net_data->res)
978*0Sstevel@tonic-gate 				RES_SET_H_ERRNO(net_data->res, NETDB_INTERNAL);
979*0Sstevel@tonic-gate 			return (NULL);
980*0Sstevel@tonic-gate 		}
981*0Sstevel@tonic-gate 
982*0Sstevel@tonic-gate 		(*net_data->ho->res_set)(net_data->ho, net_data->res, NULL);
983*0Sstevel@tonic-gate 	}
984*0Sstevel@tonic-gate 
985*0Sstevel@tonic-gate 	return (net_data);
986*0Sstevel@tonic-gate }
987*0Sstevel@tonic-gate 
988*0Sstevel@tonic-gate static void
989*0Sstevel@tonic-gate freepvt(struct net_data *net_data) {
990*0Sstevel@tonic-gate 	if (net_data->ho_data) {
991*0Sstevel@tonic-gate 		free(net_data->ho_data);
992*0Sstevel@tonic-gate 		net_data->ho_data = NULL;
993*0Sstevel@tonic-gate 	}
994*0Sstevel@tonic-gate }
995*0Sstevel@tonic-gate 
996*0Sstevel@tonic-gate static struct hostent *
997*0Sstevel@tonic-gate fakeaddr(const char *name, int af, struct net_data *net_data) {
998*0Sstevel@tonic-gate 	struct pvt *pvt;
999*0Sstevel@tonic-gate 
1000*0Sstevel@tonic-gate 	freepvt(net_data);
1001*0Sstevel@tonic-gate 	net_data->ho_data = malloc(sizeof (struct pvt));
1002*0Sstevel@tonic-gate 	if (!net_data->ho_data) {
1003*0Sstevel@tonic-gate 		errno = ENOMEM;
1004*0Sstevel@tonic-gate 		RES_SET_H_ERRNO(net_data->res, NETDB_INTERNAL);
1005*0Sstevel@tonic-gate 		return (NULL);
1006*0Sstevel@tonic-gate 	}
1007*0Sstevel@tonic-gate 	pvt = net_data->ho_data;
1008*0Sstevel@tonic-gate #ifndef __bsdi__
1009*0Sstevel@tonic-gate 	/*
1010*0Sstevel@tonic-gate 	 * Unlike its forebear(inet_aton), our friendly inet_pton() is strict
1011*0Sstevel@tonic-gate 	 * in its interpretation of its input, and it will only return "1" if
1012*0Sstevel@tonic-gate 	 * the input string is a formally valid(and thus unambiguous with
1013*0Sstevel@tonic-gate 	 * respect to host names) internet address specification for this AF.
1014*0Sstevel@tonic-gate 	 *
1015*0Sstevel@tonic-gate 	 * This means "telnet 0xdeadbeef" and "telnet 127.1" are dead now.
1016*0Sstevel@tonic-gate 	 */
1017*0Sstevel@tonic-gate 	if (inet_pton(af, name, pvt->addr) != 1) {
1018*0Sstevel@tonic-gate #else
1019*0Sstevel@tonic-gate 	/* BSDI XXX
1020*0Sstevel@tonic-gate 	 * We put this back to inet_aton -- we really want the old behavior
1021*0Sstevel@tonic-gate 	 * Long live 127.1...
1022*0Sstevel@tonic-gate 	 */
1023*0Sstevel@tonic-gate 	if ((af != AF_INET ||
1024*0Sstevel@tonic-gate 	    inet_aton(name, (struct in_addr *)pvt->addr) != 1) &&
1025*0Sstevel@tonic-gate 	    inet_pton(af, name, pvt->addr) != 1) {
1026*0Sstevel@tonic-gate #endif
1027*0Sstevel@tonic-gate 		RES_SET_H_ERRNO(net_data->res, HOST_NOT_FOUND);
1028*0Sstevel@tonic-gate 		return (NULL);
1029*0Sstevel@tonic-gate 	}
1030*0Sstevel@tonic-gate 	strncpy(pvt->name, name, NS_MAXDNAME);
1031*0Sstevel@tonic-gate 	pvt->name[NS_MAXDNAME] = '\0';
1032*0Sstevel@tonic-gate 	if (af == AF_INET && (net_data->res->options & RES_USE_INET6) != 0) {
1033*0Sstevel@tonic-gate 		map_v4v6_address(pvt->addr, pvt->addr);
1034*0Sstevel@tonic-gate 		af = AF_INET6;
1035*0Sstevel@tonic-gate 	}
1036*0Sstevel@tonic-gate 	pvt->host.h_addrtype = af;
1037*0Sstevel@tonic-gate 	switch(af) {
1038*0Sstevel@tonic-gate 	case AF_INET:
1039*0Sstevel@tonic-gate 		pvt->host.h_length = NS_INADDRSZ;
1040*0Sstevel@tonic-gate 		break;
1041*0Sstevel@tonic-gate 	case AF_INET6:
1042*0Sstevel@tonic-gate 		pvt->host.h_length = NS_IN6ADDRSZ;
1043*0Sstevel@tonic-gate 		break;
1044*0Sstevel@tonic-gate 	default:
1045*0Sstevel@tonic-gate 		errno = EAFNOSUPPORT;
1046*0Sstevel@tonic-gate 		RES_SET_H_ERRNO(net_data->res, NETDB_INTERNAL);
1047*0Sstevel@tonic-gate 		return (NULL);
1048*0Sstevel@tonic-gate 	}
1049*0Sstevel@tonic-gate 	pvt->host.h_name = pvt->name;
1050*0Sstevel@tonic-gate 	pvt->host.h_aliases = pvt->aliases;
1051*0Sstevel@tonic-gate 	pvt->aliases[0] = NULL;
1052*0Sstevel@tonic-gate 	pvt->addrs[0] = (char *)pvt->addr;
1053*0Sstevel@tonic-gate 	pvt->addrs[1] = NULL;
1054*0Sstevel@tonic-gate 	pvt->host.h_addr_list = pvt->addrs;
1055*0Sstevel@tonic-gate 	RES_SET_H_ERRNO(net_data->res, NETDB_SUCCESS);
1056*0Sstevel@tonic-gate 	return (&pvt->host);
1057*0Sstevel@tonic-gate }
1058*0Sstevel@tonic-gate 
1059*0Sstevel@tonic-gate #ifdef grot	/* for future use in gethostbyaddr(), for "SUNSECURITY" */
1060*0Sstevel@tonic-gate 	struct hostent *rhp;
1061*0Sstevel@tonic-gate 	char **haddr;
1062*0Sstevel@tonic-gate 	u_long old_options;
1063*0Sstevel@tonic-gate 	char hname2[MAXDNAME+1];
1064*0Sstevel@tonic-gate 
1065*0Sstevel@tonic-gate 	if (af == AF_INET) {
1066*0Sstevel@tonic-gate 	    /*
1067*0Sstevel@tonic-gate 	     * turn off search as the name should be absolute,
1068*0Sstevel@tonic-gate 	     * 'localhost' should be matched by defnames
1069*0Sstevel@tonic-gate 	     */
1070*0Sstevel@tonic-gate 	    strncpy(hname2, hp->h_name, MAXDNAME);
1071*0Sstevel@tonic-gate 	    hname2[MAXDNAME] = '\0';
1072*0Sstevel@tonic-gate 	    old_options = net_data->res->options;
1073*0Sstevel@tonic-gate 	    net_data->res->options &= ~RES_DNSRCH;
1074*0Sstevel@tonic-gate 	    net_data->res->options |= RES_DEFNAMES;
1075*0Sstevel@tonic-gate 	    if (!(rhp = gethostbyname(hname2))) {
1076*0Sstevel@tonic-gate 		net_data->res->options = old_options;
1077*0Sstevel@tonic-gate 		RES_SET_H_ERRNO(net_data->res, HOST_NOT_FOUND);
1078*0Sstevel@tonic-gate 		return (NULL);
1079*0Sstevel@tonic-gate 	    }
1080*0Sstevel@tonic-gate 	    net_data->res->options = old_options;
1081*0Sstevel@tonic-gate 	    for (haddr = rhp->h_addr_list; *haddr; haddr++)
1082*0Sstevel@tonic-gate 		if (!memcmp(*haddr, addr, INADDRSZ))
1083*0Sstevel@tonic-gate 			break;
1084*0Sstevel@tonic-gate 	    if (!*haddr) {
1085*0Sstevel@tonic-gate 		RES_SET_H_ERRNO(net_data->res, HOST_NOT_FOUND);
1086*0Sstevel@tonic-gate 		return (NULL);
1087*0Sstevel@tonic-gate 	    }
1088*0Sstevel@tonic-gate 	}
1089*0Sstevel@tonic-gate #endif /* grot */
1090*0Sstevel@tonic-gate 
1091*0Sstevel@tonic-gate #endif /*__BIND_NOSTATIC*/
1092