xref: /onnv-gate/usr/src/cmd/cmd-inet/usr.sbin/snoop/snoop_ipaddr.c (revision 0:68f95e015346)
1*0Sstevel@tonic-gate /*
2*0Sstevel@tonic-gate  * CDDL HEADER START
3*0Sstevel@tonic-gate  *
4*0Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*0Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*0Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*0Sstevel@tonic-gate  * with the License.
8*0Sstevel@tonic-gate  *
9*0Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*0Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*0Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*0Sstevel@tonic-gate  * and limitations under the License.
13*0Sstevel@tonic-gate  *
14*0Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*0Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*0Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*0Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*0Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*0Sstevel@tonic-gate  *
20*0Sstevel@tonic-gate  * CDDL HEADER END
21*0Sstevel@tonic-gate  */
22*0Sstevel@tonic-gate /*
23*0Sstevel@tonic-gate  * Copyright 1991-2003 Sun Microsystems, Inc.  All rights reserved.
24*0Sstevel@tonic-gate  * Use is subject to license terms.
25*0Sstevel@tonic-gate  */
26*0Sstevel@tonic-gate 
27*0Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"	/* SunOS */
28*0Sstevel@tonic-gate 
29*0Sstevel@tonic-gate #include <stdio.h>
30*0Sstevel@tonic-gate #include <ctype.h>
31*0Sstevel@tonic-gate #include <sys/types.h>
32*0Sstevel@tonic-gate #include <sys/socket.h>
33*0Sstevel@tonic-gate #include <sys/sockio.h>
34*0Sstevel@tonic-gate #include <net/if.h>
35*0Sstevel@tonic-gate #include <netinet/in_systm.h>
36*0Sstevel@tonic-gate #include <netinet/in.h>
37*0Sstevel@tonic-gate #include <netinet/if_ether.h>
38*0Sstevel@tonic-gate #include <netinet/ip.h>
39*0Sstevel@tonic-gate #include <netdb.h>
40*0Sstevel@tonic-gate #include <string.h>
41*0Sstevel@tonic-gate #include <signal.h>
42*0Sstevel@tonic-gate #include <setjmp.h>
43*0Sstevel@tonic-gate 
44*0Sstevel@tonic-gate sigjmp_buf nisjmp;
45*0Sstevel@tonic-gate 
46*0Sstevel@tonic-gate #define	MAXHASH 1024  /* must be a power of 2 */
47*0Sstevel@tonic-gate 
48*0Sstevel@tonic-gate #define	SEPARATORS " \t\n"
49*0Sstevel@tonic-gate 
50*0Sstevel@tonic-gate struct hostdata {
51*0Sstevel@tonic-gate 	struct hostdata	*h_next;
52*0Sstevel@tonic-gate 	char		*h_hostname;
53*0Sstevel@tonic-gate 	int		h_pktsout;
54*0Sstevel@tonic-gate 	int		h_pktsin;
55*0Sstevel@tonic-gate };
56*0Sstevel@tonic-gate 
57*0Sstevel@tonic-gate struct hostdata4 {
58*0Sstevel@tonic-gate 	struct hostdata4	*h4_next;
59*0Sstevel@tonic-gate 	char		*h4_hostname;
60*0Sstevel@tonic-gate 	int		h4_pktsout;
61*0Sstevel@tonic-gate 	int		h4_pktsin;
62*0Sstevel@tonic-gate 	struct in_addr	h4_addr;
63*0Sstevel@tonic-gate };
64*0Sstevel@tonic-gate 
65*0Sstevel@tonic-gate struct hostdata6 {
66*0Sstevel@tonic-gate 	struct hostdata6	*h6_next;
67*0Sstevel@tonic-gate 	char		*h6_hostname;
68*0Sstevel@tonic-gate 	int		h6_pktsout;
69*0Sstevel@tonic-gate 	int		h6_pktsin;
70*0Sstevel@tonic-gate 	struct in6_addr	h6_addr;
71*0Sstevel@tonic-gate };
72*0Sstevel@tonic-gate 
73*0Sstevel@tonic-gate struct hostdata *addhost();
74*0Sstevel@tonic-gate 
75*0Sstevel@tonic-gate struct hostdata4 *h_table4[MAXHASH];
76*0Sstevel@tonic-gate struct hostdata6 *h_table6[MAXHASH];
77*0Sstevel@tonic-gate 
78*0Sstevel@tonic-gate #define	iphash(e)  ((e) & (MAXHASH-1))
79*0Sstevel@tonic-gate 
80*0Sstevel@tonic-gate static void
81*0Sstevel@tonic-gate wakeup(n)
82*0Sstevel@tonic-gate 	int n;
83*0Sstevel@tonic-gate {
84*0Sstevel@tonic-gate 	siglongjmp(nisjmp, 1);
85*0Sstevel@tonic-gate }
86*0Sstevel@tonic-gate 
87*0Sstevel@tonic-gate extern char *inet_ntoa();
88*0Sstevel@tonic-gate extern boolean_t rflg;
89*0Sstevel@tonic-gate 
90*0Sstevel@tonic-gate static struct hostdata *
91*0Sstevel@tonic-gate iplookup(struct in_addr ipaddr)
92*0Sstevel@tonic-gate {
93*0Sstevel@tonic-gate 	register struct hostdata4 *h;
94*0Sstevel@tonic-gate 	struct hostent *hp = NULL;
95*0Sstevel@tonic-gate 	struct netent *np;
96*0Sstevel@tonic-gate 	int error_num;
97*0Sstevel@tonic-gate 	struct hostdata *retval;
98*0Sstevel@tonic-gate 
99*0Sstevel@tonic-gate 	for (h = h_table4[iphash(ipaddr.s_addr)]; h; h = h->h4_next) {
100*0Sstevel@tonic-gate 		if (h->h4_addr.s_addr == ipaddr.s_addr)
101*0Sstevel@tonic-gate 			return ((struct hostdata *)h);
102*0Sstevel@tonic-gate 	}
103*0Sstevel@tonic-gate 
104*0Sstevel@tonic-gate 	/* not found.  Put it in */
105*0Sstevel@tonic-gate 
106*0Sstevel@tonic-gate 	if (ipaddr.s_addr == htonl(INADDR_BROADCAST))
107*0Sstevel@tonic-gate 		return (addhost(AF_INET, &ipaddr, "BROADCAST", NULL));
108*0Sstevel@tonic-gate 	if (ipaddr.s_addr == htonl(INADDR_ANY))
109*0Sstevel@tonic-gate 		return (addhost(AF_INET, &ipaddr, "OLD-BROADCAST", NULL));
110*0Sstevel@tonic-gate 
111*0Sstevel@tonic-gate 	/*
112*0Sstevel@tonic-gate 	 * Set an alarm here so we don't get held up by
113*0Sstevel@tonic-gate 	 * an unresponsive name server.
114*0Sstevel@tonic-gate 	 * Give it 3 sec to do its work.
115*0Sstevel@tonic-gate 	 */
116*0Sstevel@tonic-gate 	if (! rflg && sigsetjmp(nisjmp, 1) == 0) {
117*0Sstevel@tonic-gate 		(void) snoop_alarm(3, wakeup);
118*0Sstevel@tonic-gate 		hp = getipnodebyaddr((char *)&ipaddr, sizeof (int),
119*0Sstevel@tonic-gate 			AF_INET, &error_num);
120*0Sstevel@tonic-gate 		if (hp == NULL && inet_lnaof(ipaddr) == 0) {
121*0Sstevel@tonic-gate 			np = getnetbyaddr(inet_netof(ipaddr), AF_INET);
122*0Sstevel@tonic-gate 			if (np)
123*0Sstevel@tonic-gate 				return (addhost(AF_INET, &ipaddr, np->n_name,
124*0Sstevel@tonic-gate 					np->n_aliases));
125*0Sstevel@tonic-gate 		}
126*0Sstevel@tonic-gate 		(void) snoop_alarm(0, wakeup);
127*0Sstevel@tonic-gate 	}
128*0Sstevel@tonic-gate 
129*0Sstevel@tonic-gate 	retval = addhost(AF_INET, &ipaddr,
130*0Sstevel@tonic-gate 	    hp ? hp->h_name : inet_ntoa(ipaddr),
131*0Sstevel@tonic-gate 	    hp ? hp->h_aliases : NULL);
132*0Sstevel@tonic-gate 	if (hp != NULL)
133*0Sstevel@tonic-gate 		freehostent(hp);
134*0Sstevel@tonic-gate 	return (retval);
135*0Sstevel@tonic-gate }
136*0Sstevel@tonic-gate 
137*0Sstevel@tonic-gate static struct hostdata *
138*0Sstevel@tonic-gate ip6lookup(ip6addr)
139*0Sstevel@tonic-gate 	struct in6_addr *ip6addr;
140*0Sstevel@tonic-gate {
141*0Sstevel@tonic-gate 	struct hostdata6 *h;
142*0Sstevel@tonic-gate 	struct hostent *hp = NULL;
143*0Sstevel@tonic-gate 	int error_num;
144*0Sstevel@tonic-gate 	char addrstr[INET6_ADDRSTRLEN];
145*0Sstevel@tonic-gate 	const char *addname;
146*0Sstevel@tonic-gate 	struct hostdata *retval;
147*0Sstevel@tonic-gate 
148*0Sstevel@tonic-gate 	for (h = h_table6[iphash(((uint32_t *)ip6addr)[3])]; h;
149*0Sstevel@tonic-gate 	    h = h->h6_next) {
150*0Sstevel@tonic-gate 		if (IN6_ARE_ADDR_EQUAL(&h->h6_addr, ip6addr))
151*0Sstevel@tonic-gate 			return ((struct hostdata *)h);
152*0Sstevel@tonic-gate 	}
153*0Sstevel@tonic-gate 
154*0Sstevel@tonic-gate 	/* not in the hash table, put it in */
155*0Sstevel@tonic-gate 	if (IN6_IS_ADDR_UNSPECIFIED(ip6addr))
156*0Sstevel@tonic-gate 		return (addhost(AF_INET6, ip6addr, "UNSPECIFIED", NULL));
157*0Sstevel@tonic-gate 
158*0Sstevel@tonic-gate 	/*
159*0Sstevel@tonic-gate 	 * Set an alarm here so we don't get held up by
160*0Sstevel@tonic-gate 	 * an unresponsive name server.
161*0Sstevel@tonic-gate 	 * Give it 3 sec to do its work.
162*0Sstevel@tonic-gate 	 */
163*0Sstevel@tonic-gate 	if (! rflg && sigsetjmp(nisjmp, 1) == 0) {
164*0Sstevel@tonic-gate 		(void) snoop_alarm(3, wakeup);
165*0Sstevel@tonic-gate 		hp = getipnodebyaddr(ip6addr, sizeof (struct in6_addr),
166*0Sstevel@tonic-gate 		    AF_INET6, &error_num);
167*0Sstevel@tonic-gate 		(void) snoop_alarm(0, wakeup);
168*0Sstevel@tonic-gate 	} else {
169*0Sstevel@tonic-gate 		hp = NULL;
170*0Sstevel@tonic-gate 	}
171*0Sstevel@tonic-gate 
172*0Sstevel@tonic-gate 	if (hp != NULL)
173*0Sstevel@tonic-gate 		addname = hp->h_name;
174*0Sstevel@tonic-gate 	else {
175*0Sstevel@tonic-gate 		(void) inet_ntop(AF_INET6, ip6addr, addrstr, INET6_ADDRSTRLEN);
176*0Sstevel@tonic-gate 		addname = addrstr;
177*0Sstevel@tonic-gate 	}
178*0Sstevel@tonic-gate 
179*0Sstevel@tonic-gate 	retval = addhost(AF_INET6, ip6addr, addname, hp ? hp->h_aliases : NULL);
180*0Sstevel@tonic-gate 	if (hp != NULL)
181*0Sstevel@tonic-gate 		freehostent(hp);
182*0Sstevel@tonic-gate 	return (retval);
183*0Sstevel@tonic-gate }
184*0Sstevel@tonic-gate 
185*0Sstevel@tonic-gate static struct hostdata *
186*0Sstevel@tonic-gate addhost(family, ipaddr, name, aliases)
187*0Sstevel@tonic-gate 	int family;
188*0Sstevel@tonic-gate 	void *ipaddr;
189*0Sstevel@tonic-gate 	char *name;
190*0Sstevel@tonic-gate 	char **aliases;
191*0Sstevel@tonic-gate {
192*0Sstevel@tonic-gate 	register struct hostdata **hp, *n = NULL;
193*0Sstevel@tonic-gate 	extern FILE *namefile;
194*0Sstevel@tonic-gate 	int hashval;
195*0Sstevel@tonic-gate 	static char aname[128];
196*0Sstevel@tonic-gate 	char *np;
197*0Sstevel@tonic-gate 	static struct hostdata h;
198*0Sstevel@tonic-gate 	int ind;
199*0Sstevel@tonic-gate 
200*0Sstevel@tonic-gate 	switch (family) {
201*0Sstevel@tonic-gate 	case AF_INET:
202*0Sstevel@tonic-gate 		n = (struct hostdata *)malloc(sizeof (struct hostdata4));
203*0Sstevel@tonic-gate 		if (n == NULL)
204*0Sstevel@tonic-gate 			goto alloc_failed;
205*0Sstevel@tonic-gate 
206*0Sstevel@tonic-gate 		memset(n, 0, sizeof (struct hostdata4));
207*0Sstevel@tonic-gate 		n->h_hostname = strdup(name);
208*0Sstevel@tonic-gate 		if (n->h_hostname == NULL)
209*0Sstevel@tonic-gate 			goto alloc_failed;
210*0Sstevel@tonic-gate 
211*0Sstevel@tonic-gate 		((struct hostdata4 *)n)->h4_addr = *(struct in_addr *)ipaddr;
212*0Sstevel@tonic-gate 		hashval = ((struct in_addr *)ipaddr)->s_addr;
213*0Sstevel@tonic-gate 		hp = (struct hostdata **)&h_table4[iphash(hashval)];
214*0Sstevel@tonic-gate 		break;
215*0Sstevel@tonic-gate 	case AF_INET6:
216*0Sstevel@tonic-gate 		n = (struct hostdata *)malloc(sizeof (struct hostdata6));
217*0Sstevel@tonic-gate 		if (n == NULL)
218*0Sstevel@tonic-gate 			goto alloc_failed;
219*0Sstevel@tonic-gate 
220*0Sstevel@tonic-gate 		memset(n, 0, sizeof (struct hostdata6));
221*0Sstevel@tonic-gate 		n->h_hostname = strdup(name);
222*0Sstevel@tonic-gate 		if (n->h_hostname == NULL)
223*0Sstevel@tonic-gate 			goto alloc_failed;
224*0Sstevel@tonic-gate 
225*0Sstevel@tonic-gate 		memcpy(&((struct hostdata6 *)n)->h6_addr, ipaddr,
226*0Sstevel@tonic-gate 		    sizeof (struct in6_addr));
227*0Sstevel@tonic-gate 		hashval = ((int *)ipaddr)[3];
228*0Sstevel@tonic-gate 		hp = (struct hostdata **)&h_table6[iphash(hashval)];
229*0Sstevel@tonic-gate 		break;
230*0Sstevel@tonic-gate 	default:
231*0Sstevel@tonic-gate 		fprintf(stderr, "snoop: ERROR: Unknown address family: %d",
232*0Sstevel@tonic-gate 		    family);
233*0Sstevel@tonic-gate 		exit(1);
234*0Sstevel@tonic-gate 	}
235*0Sstevel@tonic-gate 
236*0Sstevel@tonic-gate 	n->h_next = *hp;
237*0Sstevel@tonic-gate 	*hp = n;
238*0Sstevel@tonic-gate 
239*0Sstevel@tonic-gate 	if (namefile != NULL) {
240*0Sstevel@tonic-gate 		if (family == AF_INET) {
241*0Sstevel@tonic-gate 			np = inet_ntoa(*(struct in_addr *)ipaddr);
242*0Sstevel@tonic-gate 			if (np) {
243*0Sstevel@tonic-gate 				(void) fprintf(namefile, "%s\t%s", np, name);
244*0Sstevel@tonic-gate 				if (aliases) {
245*0Sstevel@tonic-gate 					for (ind = 0;
246*0Sstevel@tonic-gate 					    aliases[ind] != NULL;
247*0Sstevel@tonic-gate 					    ind++) {
248*0Sstevel@tonic-gate 						(void) fprintf(namefile, " %s",
249*0Sstevel@tonic-gate 								aliases[ind]);
250*0Sstevel@tonic-gate 					}
251*0Sstevel@tonic-gate 				}
252*0Sstevel@tonic-gate 				(void) fprintf(namefile, "\n");
253*0Sstevel@tonic-gate 			}
254*0Sstevel@tonic-gate 		} else if (family == AF_INET6) {
255*0Sstevel@tonic-gate 			np = (char *)inet_ntop(AF_INET6, (void *)ipaddr, aname,
256*0Sstevel@tonic-gate 					sizeof (aname));
257*0Sstevel@tonic-gate 			if (np) {
258*0Sstevel@tonic-gate 				(void) fprintf(namefile, "%s\t%s", np, name);
259*0Sstevel@tonic-gate 				if (aliases) {
260*0Sstevel@tonic-gate 					for (ind = 0;
261*0Sstevel@tonic-gate 					    aliases[ind] != NULL;
262*0Sstevel@tonic-gate 					    ind++) {
263*0Sstevel@tonic-gate 						(void) fprintf(namefile, " %s",
264*0Sstevel@tonic-gate 								aliases[ind]);
265*0Sstevel@tonic-gate 					}
266*0Sstevel@tonic-gate 				}
267*0Sstevel@tonic-gate 				(void) fprintf(namefile, "\n");
268*0Sstevel@tonic-gate 			}
269*0Sstevel@tonic-gate 		} else {
270*0Sstevel@tonic-gate 			(void) fprintf(stderr, "addhost: unknown family %d\n",
271*0Sstevel@tonic-gate 				family);
272*0Sstevel@tonic-gate 		}
273*0Sstevel@tonic-gate 	}
274*0Sstevel@tonic-gate 	return (n);
275*0Sstevel@tonic-gate 
276*0Sstevel@tonic-gate alloc_failed:
277*0Sstevel@tonic-gate 	if (n)
278*0Sstevel@tonic-gate 		free(n);
279*0Sstevel@tonic-gate 	(void) fprintf(stderr, "addhost: no mem\n");
280*0Sstevel@tonic-gate 
281*0Sstevel@tonic-gate 	aname[0] = '\0';
282*0Sstevel@tonic-gate 	memset(&h, 0, sizeof (struct hostdata));
283*0Sstevel@tonic-gate 	h.h_hostname = aname;
284*0Sstevel@tonic-gate 	return (&h);
285*0Sstevel@tonic-gate }
286*0Sstevel@tonic-gate 
287*0Sstevel@tonic-gate char *
288*0Sstevel@tonic-gate addrtoname(family, ipaddr)
289*0Sstevel@tonic-gate 	int family;
290*0Sstevel@tonic-gate 	void *ipaddr;
291*0Sstevel@tonic-gate {
292*0Sstevel@tonic-gate 	switch (family) {
293*0Sstevel@tonic-gate 	case AF_INET:
294*0Sstevel@tonic-gate 		return (iplookup(*(struct in_addr *)ipaddr)->h_hostname);
295*0Sstevel@tonic-gate 	case AF_INET6:
296*0Sstevel@tonic-gate 		return (ip6lookup((struct in6_addr *)ipaddr)->h_hostname);
297*0Sstevel@tonic-gate 	default:
298*0Sstevel@tonic-gate 		fprintf(stderr, "snoop: ERROR: unknown address family: %d\n",
299*0Sstevel@tonic-gate 		    family);
300*0Sstevel@tonic-gate 		exit(1);
301*0Sstevel@tonic-gate 	}
302*0Sstevel@tonic-gate }
303*0Sstevel@tonic-gate 
304*0Sstevel@tonic-gate void
305*0Sstevel@tonic-gate load_names(fname)
306*0Sstevel@tonic-gate 	char *fname;
307*0Sstevel@tonic-gate {
308*0Sstevel@tonic-gate 	char buf[1024];
309*0Sstevel@tonic-gate 	char *addr, *name, *alias;
310*0Sstevel@tonic-gate 	FILE *f;
311*0Sstevel@tonic-gate 	unsigned int addrv4;
312*0Sstevel@tonic-gate 	struct in6_addr addrv6;
313*0Sstevel@tonic-gate 	int family;
314*0Sstevel@tonic-gate 	void *naddr;
315*0Sstevel@tonic-gate 
316*0Sstevel@tonic-gate 	(void) fprintf(stderr, "Loading name file %s\n", fname);
317*0Sstevel@tonic-gate 	f = fopen(fname, "r");
318*0Sstevel@tonic-gate 	if (f == NULL) {
319*0Sstevel@tonic-gate 		perror(fname);
320*0Sstevel@tonic-gate 		return;
321*0Sstevel@tonic-gate 	}
322*0Sstevel@tonic-gate 
323*0Sstevel@tonic-gate 	while (fgets(buf, 1024, f) != NULL) {
324*0Sstevel@tonic-gate 		addr = strtok(buf, SEPARATORS);
325*0Sstevel@tonic-gate 		if (addr == NULL || *addr == '#')
326*0Sstevel@tonic-gate 			continue;
327*0Sstevel@tonic-gate 		if (inet_pton(AF_INET6, addr, (void *)&addrv6) == 1) {
328*0Sstevel@tonic-gate 			family = AF_INET6;
329*0Sstevel@tonic-gate 			naddr = (void *)&addrv6;
330*0Sstevel@tonic-gate 		} else if ((addrv4 = inet_addr(addr)) != -1) {
331*0Sstevel@tonic-gate 			family = AF_INET;
332*0Sstevel@tonic-gate 			naddr = (void *)&addrv4;
333*0Sstevel@tonic-gate 		}
334*0Sstevel@tonic-gate 		name = strtok(NULL, SEPARATORS);
335*0Sstevel@tonic-gate 		if (name == NULL)
336*0Sstevel@tonic-gate 			continue;
337*0Sstevel@tonic-gate 		while ((alias = strtok(NULL, SEPARATORS)) && (*alias != '#')) {
338*0Sstevel@tonic-gate 			(void) addhost(family, naddr, alias, NULL);
339*0Sstevel@tonic-gate 		}
340*0Sstevel@tonic-gate 		(void) addhost(family, naddr, name, NULL);
341*0Sstevel@tonic-gate 		/* Note: certain addresses such as broadcast are skipped */
342*0Sstevel@tonic-gate 	}
343*0Sstevel@tonic-gate 
344*0Sstevel@tonic-gate 	(void) fclose(f);
345*0Sstevel@tonic-gate }
346*0Sstevel@tonic-gate 
347*0Sstevel@tonic-gate /*
348*0Sstevel@tonic-gate  * lgetipnodebyname: looks up hostname in cached address data. This allows
349*0Sstevel@tonic-gate  * filtering on hostnames from the .names file to work properly, and
350*0Sstevel@tonic-gate  * avoids name clashes between domains. Note that only the first of the
351*0Sstevel@tonic-gate  * ipv4, ipv6, or v4mapped address will be returned, because the
352*0Sstevel@tonic-gate  * cache does not contain information on multi-homed hosts.
353*0Sstevel@tonic-gate  */
354*0Sstevel@tonic-gate /*ARGSUSED*/
355*0Sstevel@tonic-gate struct hostent *
356*0Sstevel@tonic-gate lgetipnodebyname(const char *name, int af, int flags, int *error_num)
357*0Sstevel@tonic-gate {
358*0Sstevel@tonic-gate 	int i;
359*0Sstevel@tonic-gate 	struct hostdata4 *h;
360*0Sstevel@tonic-gate 	struct hostdata6 *h6;
361*0Sstevel@tonic-gate 	static struct hostent he;		/* host entry */
362*0Sstevel@tonic-gate 	static struct in6_addr h46_addr[MAXADDRS];	/* v4mapped address */
363*0Sstevel@tonic-gate 	static char h_name[MAXHOSTNAMELEN];	/* hostname */
364*0Sstevel@tonic-gate 	static char *list[MAXADDRS];		/* addr_list array */
365*0Sstevel@tonic-gate 	struct hostent *hp = &he;
366*0Sstevel@tonic-gate 	int ind;
367*0Sstevel@tonic-gate 
368*0Sstevel@tonic-gate 	(void) memset((char *)hp, 0, sizeof (struct hostent));
369*0Sstevel@tonic-gate 	hp->h_name = h_name;
370*0Sstevel@tonic-gate 	h_name[0] = '\0';
371*0Sstevel@tonic-gate 	strcpy(h_name, name);
372*0Sstevel@tonic-gate 
373*0Sstevel@tonic-gate 	hp->h_addrtype = AF_INET6;
374*0Sstevel@tonic-gate 
375*0Sstevel@tonic-gate 	hp->h_addr_list = list;
376*0Sstevel@tonic-gate 	for (i = 0; i < MAXADDRS; i++)
377*0Sstevel@tonic-gate 		hp->h_addr_list[i] = NULL;
378*0Sstevel@tonic-gate 	ind = 0;
379*0Sstevel@tonic-gate 
380*0Sstevel@tonic-gate 	/* ipv6 lookup */
381*0Sstevel@tonic-gate 	if (af == AF_INET6) {
382*0Sstevel@tonic-gate 		hp->h_length = sizeof (struct in6_addr);
383*0Sstevel@tonic-gate 		for (i = 0; i < MAXHASH; i++) {
384*0Sstevel@tonic-gate 			for (h6 = h_table6[i]; h6; h6 = h6->h6_next) {
385*0Sstevel@tonic-gate 				if (strcmp(name, h6->h6_hostname) == 0) {
386*0Sstevel@tonic-gate 					if (ind >= MAXADDRS - 1) {
387*0Sstevel@tonic-gate 						/* too many addresses */
388*0Sstevel@tonic-gate 						return (hp);
389*0Sstevel@tonic-gate 					}
390*0Sstevel@tonic-gate 					/* found ipv6 addr */
391*0Sstevel@tonic-gate 					hp->h_addr_list[ind] =
392*0Sstevel@tonic-gate 						(char *)&h6->h6_addr;
393*0Sstevel@tonic-gate 					ind++;
394*0Sstevel@tonic-gate 				}
395*0Sstevel@tonic-gate 			}
396*0Sstevel@tonic-gate 		}
397*0Sstevel@tonic-gate 	}
398*0Sstevel@tonic-gate 	/* ipv4 or v4mapped lookup */
399*0Sstevel@tonic-gate 	if (af == AF_INET || (flags & AI_ALL)) {
400*0Sstevel@tonic-gate 		for (i = 0; i < MAXHASH; i++) {
401*0Sstevel@tonic-gate 			for (h = h_table4[i]; h; h = h->h4_next) {
402*0Sstevel@tonic-gate 				if (strcmp(name, h->h4_hostname) == 0) {
403*0Sstevel@tonic-gate 					if (ind >= MAXADDRS - 1) {
404*0Sstevel@tonic-gate 						/* too many addresses */
405*0Sstevel@tonic-gate 						return (hp);
406*0Sstevel@tonic-gate 					}
407*0Sstevel@tonic-gate 					if (af == AF_INET) {
408*0Sstevel@tonic-gate 						/* found ipv4 addr */
409*0Sstevel@tonic-gate 						hp->h_addrtype = AF_INET;
410*0Sstevel@tonic-gate 						hp->h_length =
411*0Sstevel@tonic-gate 						    sizeof (struct in_addr);
412*0Sstevel@tonic-gate 						hp->h_addr_list[ind] =
413*0Sstevel@tonic-gate 						    (char *)&h->h4_addr;
414*0Sstevel@tonic-gate 						ind++;
415*0Sstevel@tonic-gate 					} else {
416*0Sstevel@tonic-gate 						/* found v4mapped addr */
417*0Sstevel@tonic-gate 						hp->h_length =
418*0Sstevel@tonic-gate 						    sizeof (struct in6_addr);
419*0Sstevel@tonic-gate 						hp->h_addr_list[ind] =
420*0Sstevel@tonic-gate 						    (char *)&h46_addr[ind];
421*0Sstevel@tonic-gate 						IN6_INADDR_TO_V4MAPPED(
422*0Sstevel@tonic-gate 							&h->h4_addr,
423*0Sstevel@tonic-gate 							&h46_addr[ind]);
424*0Sstevel@tonic-gate 						ind++;
425*0Sstevel@tonic-gate 					}
426*0Sstevel@tonic-gate 				}
427*0Sstevel@tonic-gate 			}
428*0Sstevel@tonic-gate 		}
429*0Sstevel@tonic-gate 	}
430*0Sstevel@tonic-gate 	return (ind > 0 ? hp : NULL);
431*0Sstevel@tonic-gate }
432