4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
29 #include <sys/types.h>
30 #include <sys/socket.h>
31 #include <sys/sockio.h>
33 #include <netinet/in_systm.h>
34 #include <netinet/in.h>
35 #include <netinet/if_ether.h>
36 #include <netinet/ip.h>
41 #include <arpa/inet.h>
44 static sigjmp_buf nisjmp
;
46 #define MAXHASH 1024 /* must be a power of 2 */
48 #define SEPARATORS " \t\n"
51 struct hostdata
*h_next
;
58 struct hostdata4
*h4_next
;
62 struct in_addr h4_addr
;
66 struct hostdata6
*h6_next
;
70 struct in6_addr h6_addr
;
73 static struct hostdata
*addhost(int, const void *, const char *, char **);
75 static struct hostdata4
*h_table4
[MAXHASH
];
76 static struct hostdata6
*h_table6
[MAXHASH
];
78 #define iphash(e) ((e) & (MAXHASH-1))
84 siglongjmp(nisjmp
, 1);
87 extern char *inet_ntoa();
89 static struct hostdata
*
90 iplookup(struct in_addr ipaddr
)
92 register struct hostdata4
*h
;
93 struct hostent
*hp
= NULL
;
96 struct hostdata
*retval
;
98 for (h
= h_table4
[iphash(ipaddr
.s_addr
)]; h
; h
= h
->h4_next
) {
99 if (h
->h4_addr
.s_addr
== ipaddr
.s_addr
)
100 return ((struct hostdata
*)h
);
103 /* not found. Put it in */
105 if (ipaddr
.s_addr
== htonl(INADDR_BROADCAST
))
106 return (addhost(AF_INET
, &ipaddr
, "BROADCAST", NULL
));
107 if (ipaddr
.s_addr
== htonl(INADDR_ANY
))
108 return (addhost(AF_INET
, &ipaddr
, "OLD-BROADCAST", NULL
));
111 * Set an alarm here so we don't get held up by
112 * an unresponsive name server.
113 * Give it 3 sec to do its work.
115 if (! rflg
&& sigsetjmp(nisjmp
, 1) == 0) {
116 (void) snoop_alarm(3, wakeup
);
117 hp
= getipnodebyaddr((char *)&ipaddr
, sizeof (int),
118 AF_INET
, &error_num
);
119 if (hp
== NULL
&& inet_lnaof(ipaddr
) == 0) {
120 np
= getnetbyaddr(inet_netof(ipaddr
), AF_INET
);
122 return (addhost(AF_INET
, &ipaddr
, np
->n_name
,
125 (void) snoop_alarm(0, wakeup
);
128 retval
= addhost(AF_INET
, &ipaddr
,
129 hp
? hp
->h_name
: inet_ntoa(ipaddr
),
130 hp
? hp
->h_aliases
: NULL
);
136 static struct hostdata
*
137 ip6lookup(const struct in6_addr
*ip6addr
)
140 struct hostent
*hp
= NULL
;
142 char addrstr
[INET6_ADDRSTRLEN
];
144 struct hostdata
*retval
;
146 for (h
= h_table6
[iphash(((uint32_t *)ip6addr
)[3])]; h
;
148 if (IN6_ARE_ADDR_EQUAL(&h
->h6_addr
, ip6addr
))
149 return ((struct hostdata
*)h
);
152 /* not in the hash table, put it in */
153 if (IN6_IS_ADDR_UNSPECIFIED(ip6addr
))
154 return (addhost(AF_INET6
, ip6addr
, "UNSPECIFIED", NULL
));
157 * Set an alarm here so we don't get held up by
158 * an unresponsive name server.
159 * Give it 3 sec to do its work.
161 if (! rflg
&& sigsetjmp(nisjmp
, 1) == 0) {
162 (void) snoop_alarm(3, wakeup
);
163 hp
= getipnodebyaddr(ip6addr
, sizeof (struct in6_addr
),
164 AF_INET6
, &error_num
);
165 (void) snoop_alarm(0, wakeup
);
171 addname
= hp
->h_name
;
173 (void) inet_ntop(AF_INET6
, ip6addr
, addrstr
, INET6_ADDRSTRLEN
);
177 retval
= addhost(AF_INET6
, ip6addr
, addname
, hp
? hp
->h_aliases
: NULL
);
183 static struct hostdata
*
184 addhost(int family
, const void *ipaddr
, const char *name
, char **aliases
)
186 struct hostdata
**hp
, *n
= NULL
;
187 extern FILE *namefile
;
189 static char aname
[128];
191 static struct hostdata h
;
196 n
= (struct hostdata
*)malloc(sizeof (struct hostdata4
));
200 memset(n
, 0, sizeof (struct hostdata4
));
201 n
->h_hostname
= strdup(name
);
202 if (n
->h_hostname
== NULL
)
205 ((struct hostdata4
*)n
)->h4_addr
=
206 *(const struct in_addr
*)ipaddr
;
207 hashval
= ((struct in_addr
*)ipaddr
)->s_addr
;
208 hp
= (struct hostdata
**)&h_table4
[iphash(hashval
)];
211 n
= (struct hostdata
*)malloc(sizeof (struct hostdata6
));
215 memset(n
, 0, sizeof (struct hostdata6
));
216 n
->h_hostname
= strdup(name
);
217 if (n
->h_hostname
== NULL
)
220 memcpy(&((struct hostdata6
*)n
)->h6_addr
, ipaddr
,
221 sizeof (struct in6_addr
));
222 hashval
= ((const int *)ipaddr
)[3];
223 hp
= (struct hostdata
**)&h_table6
[iphash(hashval
)];
226 fprintf(stderr
, "snoop: ERROR: Unknown address family: %d",
234 if (namefile
!= NULL
) {
235 if (family
== AF_INET
) {
236 np
= inet_ntoa(*(const struct in_addr
*)ipaddr
);
238 (void) fprintf(namefile
, "%s\t%s", np
, name
);
241 aliases
[ind
] != NULL
;
243 (void) fprintf(namefile
, " %s",
247 (void) fprintf(namefile
, "\n");
249 } else if (family
== AF_INET6
) {
250 np
= (char *)inet_ntop(AF_INET6
, (void *)ipaddr
, aname
,
253 (void) fprintf(namefile
, "%s\t%s", np
, name
);
256 aliases
[ind
] != NULL
;
258 (void) fprintf(namefile
, " %s",
262 (void) fprintf(namefile
, "\n");
265 (void) fprintf(stderr
, "addhost: unknown family %d\n",
274 (void) fprintf(stderr
, "addhost: no mem\n");
277 memset(&h
, 0, sizeof (struct hostdata
));
278 h
.h_hostname
= aname
;
283 addrtoname(int family
, const void *ipaddr
)
287 return (iplookup(*(const struct in_addr
*)ipaddr
)->h_hostname
);
289 return (ip6lookup((const struct in6_addr
*)ipaddr
)->h_hostname
);
291 (void) fprintf(stderr
, "snoop: ERROR: unknown address family: %d\n",
302 char *addr
, *name
, *alias
;
305 struct in6_addr addrv6
;
309 (void) fprintf(stderr
, "Loading name file %s\n", fname
);
310 f
= fopen(fname
, "r");
316 while (fgets(buf
, 1024, f
) != NULL
) {
317 addr
= strtok(buf
, SEPARATORS
);
318 if (addr
== NULL
|| *addr
== '#')
320 if (inet_pton(AF_INET6
, addr
, (void *)&addrv6
) == 1) {
322 naddr
= (void *)&addrv6
;
323 } else if ((addrv4
= inet_addr(addr
)) != (ulong_t
)-1) {
325 naddr
= (void *)&addrv4
;
327 name
= strtok(NULL
, SEPARATORS
);
330 while ((alias
= strtok(NULL
, SEPARATORS
)) != NULL
&&
332 (void) addhost(family
, naddr
, alias
, NULL
);
334 (void) addhost(family
, naddr
, name
, NULL
);
335 /* Note: certain addresses such as broadcast are skipped */
342 * lgetipnodebyname: looks up hostname in cached address data. This allows
343 * filtering on hostnames from the .names file to work properly, and
344 * avoids name clashes between domains. Note that only the first of the
345 * ipv4, ipv6, or v4mapped address will be returned, because the
346 * cache does not contain information on multi-homed hosts.
350 lgetipnodebyname(const char *name
, int af
, int flags
, int *error_num
)
354 struct hostdata6
*h6
;
355 static struct hostent he
; /* host entry */
356 static struct in6_addr h46_addr
[MAXADDRS
]; /* v4mapped address */
357 static char h_name
[MAXHOSTNAMELEN
]; /* hostname */
358 static char *list
[MAXADDRS
]; /* addr_list array */
359 struct hostent
*hp
= &he
;
362 (void) memset((char *)hp
, 0, sizeof (struct hostent
));
365 strcpy(h_name
, name
);
367 hp
->h_addrtype
= AF_INET6
;
369 hp
->h_addr_list
= list
;
370 for (i
= 0; i
< MAXADDRS
; i
++)
371 hp
->h_addr_list
[i
] = NULL
;
375 if (af
== AF_INET6
) {
376 hp
->h_length
= sizeof (struct in6_addr
);
377 for (i
= 0; i
< MAXHASH
; i
++) {
378 for (h6
= h_table6
[i
]; h6
; h6
= h6
->h6_next
) {
379 if (strcmp(name
, h6
->h6_hostname
) == 0) {
380 if (ind
>= MAXADDRS
- 1) {
381 /* too many addresses */
384 /* found ipv6 addr */
385 hp
->h_addr_list
[ind
] =
386 (char *)&h6
->h6_addr
;
392 /* ipv4 or v4mapped lookup */
393 if (af
== AF_INET
|| (flags
& AI_ALL
)) {
394 for (i
= 0; i
< MAXHASH
; i
++) {
395 for (h
= h_table4
[i
]; h
; h
= h
->h4_next
) {
396 if (strcmp(name
, h
->h4_hostname
) == 0) {
397 if (ind
>= MAXADDRS
- 1) {
398 /* too many addresses */
402 /* found ipv4 addr */
403 hp
->h_addrtype
= AF_INET
;
405 sizeof (struct in_addr
);
406 hp
->h_addr_list
[ind
] =
410 /* found v4mapped addr */
412 sizeof (struct in6_addr
);
413 hp
->h_addr_list
[ind
] =
414 (char *)&h46_addr
[ind
];
415 IN6_INADDR_TO_V4MAPPED(
424 return (ind
> 0 ? hp
: NULL
);