2 * Routines for network object lookup
6 * Laurent Deniel <laurent.deniel@free.fr>
8 * Ethereal - Network traffic analyzer
9 * By Gerald Combs <gerald@ethereal.com>
10 * Copyright 1998 Gerald Combs
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
38 * Win32 doesn't have SIGALRM (and it's the OS where name lookup calls
39 * are most likely to take a long time, given the way address-to-name
40 * lookups are done over NBNS).
42 * Mac OS X does have SIGALRM, but if you longjmp() out of a name resolution
43 * call in a signal handler, you might crash, because the state of the
44 * resolution code that sends messages to lookupd might be inconsistent
45 * if you jump out of it in middle of a call.
47 * In at least some Linux distributions (e.g., RedHat Linux 9), if ADNS
48 * is used, we appear to hang in host_name_lookup6() in a gethostbyaddr()
49 * call (and possibly in other gethostbyaddr() calls), because there's
50 * a mutex lock held in gethostbyaddr() and it doesn't get released
51 * if we longjmp out of it.
53 * There's no guarantee that longjmp()ing out of name resolution calls
54 * will work on *any* platform; OpenBSD got rid of the alarm/longjmp
55 * code in tcpdump, to avoid those sorts of problems, and that was
56 * picked up by tcpdump.org tcpdump.
58 * So, for now, we do not define AVOID_DNS_TIMEOUT. If we get a
59 * significantly more complaints about lookups taking a long time,
60 * we can reconsider that decision. (Note that tcpdump originally
61 * added that for the benefit of systems using NIS to look up host
62 * names; that might now be fixed in NIS implementations, for those
63 * sites still using NIS rather than DNS for that....)
70 #ifdef HAVE_NETINET_IN_H
71 # include <netinet/in.h>
78 #ifdef HAVE_ARPA_INET_H
79 #include <arpa/inet.h>
84 #ifdef HAVE_SYS_SOCKET_H
85 #include <sys/socket.h> /* needed to define AF_ values on UNIX */
88 #ifdef HAVE_WINSOCK2_H
89 #include <winsock2.h> /* needed to define AF_ values on Windows */
92 #ifdef AVOID_DNS_TIMEOUT
96 #ifdef NEED_INET_ATON_H
97 # include "inet_aton.h"
100 #ifdef NEED_INET_V6DEFS_H
101 # include "inet_v6defs.h"
109 #if defined(_WIN32) && defined(INET6)
110 # include <ws2tcpip.h>
115 #include "report_err.h"
117 #include "ipv6-utils.h"
118 #include "addr_resolv.h"
119 #include "filesystem.h"
120 #include <epan/prefs.h>
122 #define ENAME_HOSTS "hosts"
123 #define ENAME_ETHERS "ethers"
124 #define ENAME_IPXNETS "ipxnets"
125 #define ENAME_MANUF "manuf"
127 #define MAXMANUFLEN 9 /* max vendor name length with ending '\0' */
128 #define HASHETHSIZE 1024
129 #define HASHHOSTSIZE 1024
130 #define HASHIPXNETSIZE 256
131 #define HASHMANUFSIZE 256
132 #define HASHPORTSIZE 256
134 /* hash table used for IPv4 lookup */
136 #define HASH_IPV4_ADDRESS(addr) ((addr) & (HASHHOSTSIZE - 1))
138 typedef struct hashipv4 {
140 gchar name[MAXNAMELEN];
141 gboolean is_dummy_entry; /* name is IPv4 address in dot format */
142 struct hashipv4 *next;
145 /* hash table used for IPv6 lookup */
147 #define HASH_IPV6_ADDRESS(addr) \
148 ((((addr).s6_addr8[14] << 8)|((addr).s6_addr8[15])) & (HASHHOSTSIZE - 1))
150 typedef struct hashipv6 {
151 struct e_in6_addr addr;
152 gchar name[MAXNAMELEN];
153 gboolean is_dummy_entry; /* name is IPv6 address in colon format */
154 struct hashipv6 *next;
157 /* hash table used for TCP/UDP/SCTP port lookup */
159 #define HASH_PORT(port) ((port) & (HASHPORTSIZE - 1))
161 typedef struct hashport {
163 gchar name[MAXNAMELEN];
164 struct hashport *next;
167 /* hash table used for IPX network lookup */
169 /* XXX - check goodness of hash function */
171 #define HASH_IPX_NET(net) ((net) & (HASHIPXNETSIZE - 1))
173 typedef struct hashipxnet {
175 gchar name[MAXNAMELEN];
176 struct hashipxnet *next;
179 /* hash tables used for ethernet and manufacturer lookup */
181 #define HASH_ETH_ADDRESS(addr) \
182 (((((addr)[2] << 8) | (addr)[3]) ^ (((addr)[4] << 8) | (addr)[5])) & \
185 #define HASH_ETH_MANUF(addr) (((int)(addr)[2]) & (HASHMANUFSIZE - 1))
187 typedef struct hashmanuf {
189 char name[MAXMANUFLEN];
190 struct hashmanuf *next;
193 typedef struct hashether {
195 char name[MAXNAMELEN];
196 gboolean is_dummy_entry; /* not a complete entry */
197 struct hashether *next;
200 /* internal ethernet type */
202 typedef struct _ether
205 char name[MAXNAMELEN];
208 /* internal ipxnet type */
210 typedef struct _ipxnet
213 char name[MAXNAMELEN];
216 static hashipv4_t *ipv4_table[HASHHOSTSIZE];
217 static hashipv6_t *ipv6_table[HASHHOSTSIZE];
218 static hashport_t *udp_port_table[HASHPORTSIZE];
219 static hashport_t *tcp_port_table[HASHPORTSIZE];
220 static hashport_t *sctp_port_table[HASHPORTSIZE];
221 static hashether_t *eth_table[HASHETHSIZE];
222 static hashmanuf_t *manuf_table[HASHMANUFSIZE];
223 static hashether_t *(*wka_table[48])[HASHETHSIZE];
224 static hashipxnet_t *ipxnet_table[HASHIPXNETSIZE];
226 static int eth_resolution_initialized = 0;
227 static int ipxnet_resolution_initialized = 0;
229 static hashether_t *add_eth_name(const guint8 *addr, const gchar *name);
232 * Flag controlling what names to resolve.
234 guint32 g_resolv_flags;
237 * Global variables (can be changed in GUI sections)
238 * XXX - they could be changed in GUI code, but there's currently no
239 * GUI code to change them.
242 gchar *g_ethers_path = NULL; /* global ethers file */
243 gchar *g_pethers_path = NULL; /* personal ethers file */
244 gchar *g_ipxnets_path = NULL; /* global ipxnets file */
245 gchar *g_pipxnets_path = NULL; /* personal ipxnets file */
246 /* first resolving call */
252 static gboolean gnu_adns_initialized = FALSE;
256 int adns_currently_queued = 0;
258 typedef struct _adns_queue_msg
262 struct e_in6_addr ip6_addr;
267 GList *adns_queue_head = NULL;
269 #endif /* HAVE_GNU_ADNS */
272 * Local function definitions
275 static gchar *serv_name_lookup(guint port, port_type proto)
280 char *serv_proto = NULL;
281 struct servent *servp;
285 table = udp_port_table;
289 table = tcp_port_table;
293 table = sctp_port_table;
297 /* not yet implemented */
303 hash_idx = HASH_PORT(port);
304 tp = table[hash_idx];
307 tp = table[hash_idx] = (hashport_t *)g_malloc(sizeof(hashport_t));
310 if( tp->port == port ) {
313 if (tp->next == NULL) {
314 tp->next = (hashport_t *)g_malloc(sizeof(hashport_t));
322 /* fill in a new entry */
326 if (!(g_resolv_flags & RESOLV_TRANSPORT) ||
327 (servp = getservbyport(g_htons(port), serv_proto)) == NULL) {
329 sprintf(tp->name, "%d", port);
331 strncpy(tp->name, servp->s_name, MAXNAMELEN);
332 tp->name[MAXNAMELEN-1] = '\0';
337 } /* serv_name_lookup */
340 #ifdef AVOID_DNS_TIMEOUT
342 #define DNS_TIMEOUT 2 /* max sec per call */
344 jmp_buf hostname_env;
346 static void abort_network_query(int sig _U_)
348 longjmp(hostname_env, 1);
350 #endif /* AVOID_DNS_TIMEOUT */
352 static gchar *host_name_lookup(guint addr, gboolean *found)
355 hashipv4_t * volatile tp;
356 struct hostent *hostp;
358 adns_queue_msg_t *qmsg;
363 hash_idx = HASH_IPV4_ADDRESS(addr);
365 tp = ipv4_table[hash_idx];
368 tp = ipv4_table[hash_idx] = (hashipv4_t *)g_malloc(sizeof(hashipv4_t));
371 if( tp->addr == addr ) {
372 if (tp->is_dummy_entry)
376 if (tp->next == NULL) {
377 tp->next = (hashipv4_t *)g_malloc(sizeof(hashipv4_t));
385 /* fill in a new entry */
390 if ((g_resolv_flags & RESOLV_CONCURRENT) &&
391 prefs.name_resolve_concurrency > 0 &&
392 gnu_adns_initialized) {
393 qmsg = g_malloc(sizeof(adns_queue_msg_t));
394 qmsg->type = AF_INET;
395 qmsg->ip4_addr = addr;
396 qmsg->submitted = FALSE;
397 adns_queue_head = g_list_append(adns_queue_head, (gpointer) qmsg);
399 tp->is_dummy_entry = TRUE;
400 ip_to_str_buf((guint8 *)&addr, tp->name);
403 #endif /* HAVE_GNU_ADNS */
406 * The Windows "gethostbyaddr()" insists on translating 0.0.0.0 to
407 * the name of the host on which it's running; to work around that
408 * botch, we don't try to translate an all-zero IP address to a host
411 if (addr != 0 && (g_resolv_flags & RESOLV_NETWORK)) {
412 /* Use async DNS if possible, else fall back to timeouts,
413 * else call gethostbyaddr and hope for the best
416 # ifdef AVOID_DNS_TIMEOUT
418 /* Quick hack to avoid DNS/YP timeout */
420 if (!setjmp(hostname_env)) {
421 signal(SIGALRM, abort_network_query);
423 # endif /* AVOID_DNS_TIMEOUT */
425 hostp = gethostbyaddr((char *)&addr, 4, AF_INET);
427 # ifdef AVOID_DNS_TIMEOUT
429 # endif /* AVOID_DNS_TIMEOUT */
432 strncpy(tp->name, hostp->h_name, MAXNAMELEN);
433 tp->name[MAXNAMELEN-1] = '\0';
434 tp->is_dummy_entry = FALSE;
438 # ifdef AVOID_DNS_TIMEOUT
440 # endif /* AVOID_DNS_TIMEOUT */
444 /* unknown host or DNS timeout */
446 ip_to_str_buf((guint8 *)&addr, tp->name);
447 tp->is_dummy_entry = TRUE;
452 } /* host_name_lookup */
454 static gchar *host_name_lookup6(struct e_in6_addr *addr, gboolean *found)
457 hashipv6_t * volatile tp;
459 struct hostent *hostp;
464 hash_idx = HASH_IPV6_ADDRESS(*addr);
466 tp = ipv6_table[hash_idx];
469 tp = ipv6_table[hash_idx] = (hashipv6_t *)g_malloc(sizeof(hashipv6_t));
472 if( memcmp(&tp->addr, addr, sizeof (struct e_in6_addr)) == 0 ) {
473 if (tp->is_dummy_entry)
477 if (tp->next == NULL) {
478 tp->next = (hashipv6_t *)g_malloc(sizeof(hashipv6_t));
486 /* fill in a new entry */
491 if (g_resolv_flags & RESOLV_NETWORK) {
492 #ifdef AVOID_DNS_TIMEOUT
494 /* Quick hack to avoid DNS/YP timeout */
496 if (!setjmp(hostname_env)) {
497 signal(SIGALRM, abort_network_query);
499 #endif /* AVOID_DNS_TIMEOUT */
500 hostp = gethostbyaddr((char *)addr, sizeof(*addr), AF_INET6);
501 #ifdef AVOID_DNS_TIMEOUT
503 # endif /* AVOID_DNS_TIMEOUT */
506 strncpy(tp->name, hostp->h_name, MAXNAMELEN);
507 tp->name[MAXNAMELEN-1] = '\0';
508 tp->is_dummy_entry = FALSE;
512 #ifdef AVOID_DNS_TIMEOUT
514 # endif /* AVOID_DNS_TIMEOUT */
518 /* unknown host or DNS timeout */
520 ip6_to_str_buf(addr, tp->name);
521 tp->is_dummy_entry = TRUE;
525 } /* host_name_lookup6 */
527 const gchar *solve_address_to_name(address *addr)
530 struct e_in6_addr ipv6_addr;
532 switch (addr->type) {
535 return get_ether_name(addr->data);
538 memcpy(&ipv4_addr, addr->data, sizeof ipv4_addr);
539 return get_hostname(ipv4_addr);
542 memcpy(&ipv6_addr.s6_addr, addr->data, sizeof ipv6_addr.s6_addr);
543 return get_hostname6(&ipv6_addr);
551 } /* solve_address_to_name */
555 * Miscellaneous functions
558 static int fgetline(char **buf, int *size, FILE *fp)
570 if ((*buf = g_malloc(*size)) == NULL)
578 while ((c = getc(fp)) != EOF && c != '\n') {
579 if (len+1 >= *size) {
580 if ((*buf = g_realloc(*buf, *size += BUFSIZ)) == NULL)
586 if (len == 0 && c == EOF)
597 * Ethernet / manufacturer resolution
599 * The following functions implement ethernet address resolution and
600 * ethers files parsing (see ethers(4)).
602 * The manuf file has the same format as ethers(4) except that names are
603 * truncated to MAXMANUFLEN-1 characters and that an address contains
604 * only 3 bytes (instead of 6).
608 * I decide to not use the existing functions (see ethers(3) on some
609 * operating systems) for the following reasons:
610 * - performance gains (use of hash tables and some other enhancements),
611 * - use of two ethers files (system-wide and per user),
612 * - avoid the use of NIS maps,
613 * - lack of these functions on some systems.
615 * So the following functions do _not_ behave as the standard ones.
622 * If "manuf_file" is FALSE, parse a 6-byte MAC address.
623 * If "manuf_file" is TRUE, parse an up-to-6-byte sequence with an optional
627 parse_ether_address(const char *cp, ether_t *eth, unsigned int *mask,
635 for (i = 0; i < 6; i++) {
636 /* Get a hex number, 1 or 2 digits, no sign characters allowed. */
637 if (!isxdigit((unsigned char)*cp))
639 num = strtoul(cp, &p, 16);
641 return FALSE; /* failed */
643 return FALSE; /* not a valid octet */
644 eth->addr[i] = (guint8) num;
645 cp = p; /* skip past the number */
647 /* OK, what character terminated the octet? */
649 /* "/" - this has a mask. */
651 /* Entries with masks are allowed only in the "manuf" files. */
654 cp++; /* skip past the '/' to get to the mask */
655 if (!isdigit((unsigned char)*cp))
656 return FALSE; /* no sign allowed */
657 num = strtoul(cp, &p, 10);
659 return FALSE; /* failed */
660 cp = p; /* skip past the number */
661 if (*cp != '\0' && !isspace((unsigned char)*cp))
662 return FALSE; /* bogus terminator */
663 if (num == 0 || num >= 48)
664 return FALSE; /* bogus mask */
665 /* Mask out the bits not covered by the mask */
667 for (i = 0; num >= 8; i++, num -= 8)
668 ; /* skip octets entirely covered by the mask */
669 /* Mask out the first masked octet */
670 eth->addr[i] &= (0xFF << (8 - num));
672 /* Mask out completely-masked-out octets */
678 /* We're at the end of the address, and there's no mask. */
680 /* We got 3 bytes, so this is a manufacturer ID. */
682 /* Manufacturer IDs are only allowed in the "manuf"
686 /* Indicate that this is a manufacturer ID (0 is not allowed
693 /* We got 6 bytes, so this is a MAC address.
694 If we're reading one of the "manuf" files, indicate that
695 this is a MAC address (48 is not allowed as a mask). */
701 /* We didn't get 3 or 6 bytes, and there's no mask; this is
706 /* We don't know the separator used in this number; it can either
707 be ':', '-', or '.'. */
708 if (*cp != ':' && *cp != '-' && *cp != '.')
710 sep = *cp; /* subsequent separators must be the same */
712 /* It has to be the same as the first separator */
723 static int parse_ether_line(char *line, ether_t *eth, unsigned int *mask,
727 * See the ethers(4) or ethers(5) man page for ethers file format
728 * (not available on all systems).
729 * We allow both ethernet address separators (':' and '-'),
730 * as well as Ethereal's '.' separator.
735 if ((cp = strchr(line, '#')))
738 if ((cp = strtok(line, " \t")) == NULL)
741 if (!parse_ether_address(cp, eth, mask, manuf_file))
744 if ((cp = strtok(NULL, " \t")) == NULL)
747 strncpy(eth->name, cp, MAXNAMELEN);
748 eth->name[MAXNAMELEN-1] = '\0';
752 } /* parse_ether_line */
754 static FILE *eth_p = NULL;
756 static void set_ethent(char *path)
761 eth_p = fopen(path, "r");
764 static void end_ethent(void)
772 static ether_t *get_ethent(unsigned int *mask, gboolean manuf_file)
777 static char *buf = NULL;
782 while (fgetline(&buf, &size, eth_p) >= 0) {
783 if (parse_ether_line(buf, ð, mask, manuf_file) == 0) {
792 static ether_t *get_ethbyname(const gchar *name)
796 set_ethent(g_ethers_path);
798 while ((eth = get_ethent(NULL, FALSE)) && strncmp(name, eth->name, MAXNAMELEN) != 0)
804 set_ethent(g_pethers_path);
806 while ((eth = get_ethent(NULL, FALSE)) && strncmp(name, eth->name, MAXNAMELEN) != 0)
814 } /* get_ethbyname */
816 static ether_t *get_ethbyaddr(const guint8 *addr)
821 set_ethent(g_ethers_path);
823 while ((eth = get_ethent(NULL, FALSE)) && memcmp(addr, eth->addr, 6) != 0)
829 set_ethent(g_pethers_path);
831 while ((eth = get_ethent(NULL, FALSE)) && memcmp(addr, eth->addr, 6) != 0)
839 } /* get_ethbyaddr */
841 static int hash_eth_wka(const guint8 *addr, unsigned int mask)
844 /* All but the topmost byte is masked out */
845 return (addr[0] & (0xFF << (8 - mask))) & (HASHETHSIZE - 1);
849 /* All but the topmost 2 bytes are masked out */
850 return ((addr[0] << 8) | (addr[1] & (0xFF << (8 - mask)))) &
855 /* All but the topmost 3 bytes are masked out */
856 return ((addr[0] << 16) | (addr[1] << 8) | (addr[2] & (0xFF << (8 - mask))))
861 /* All but the topmost 4 bytes are masked out */
862 return ((((addr[0] << 8) | addr[1]) ^
863 ((addr[2] << 8) | (addr[3] & (0xFF << (8 - mask)))))) &
868 /* All but the topmost 5 bytes are masked out */
869 return ((((addr[1] << 8) | addr[2]) ^
870 ((addr[3] << 8) | (addr[4] & (0xFF << (8 - mask)))))) &
874 /* No bytes are fully masked out */
875 return ((((addr[1] << 8) | addr[2]) ^
876 ((addr[3] << 8) | (addr[4] & (0xFF << (8 - mask)))))) &
880 static void add_manuf_name(guint8 *addr, unsigned int mask, gchar *name)
884 hashether_t *(*wka_tp)[HASHETHSIZE], *etp;
887 /* This is a well-known MAC address; just add this to the Ethernet
889 add_eth_name(addr, name);
894 /* This is a manufacturer ID; add it to the manufacturer ID hash table */
896 hash_idx = HASH_ETH_MANUF(addr);
898 tp = manuf_table[hash_idx];
901 tp = manuf_table[hash_idx] = (hashmanuf_t *)g_malloc(sizeof(hashmanuf_t));
904 if (tp->next == NULL) {
905 tp->next = (hashmanuf_t *)g_malloc(sizeof(hashmanuf_t));
913 memcpy(tp->addr, addr, sizeof(tp->addr));
914 strncpy(tp->name, name, MAXMANUFLEN);
915 tp->name[MAXMANUFLEN-1] = '\0';
920 /* This is a range of well-known addresses; add it to the appropriate
921 well-known-address table, creating that table if necessary. */
922 wka_tp = wka_table[mask];
924 wka_tp = wka_table[mask] = g_malloc0(sizeof *wka_table[mask]);
926 hash_idx = hash_eth_wka(addr, mask);
928 etp = (*wka_tp)[hash_idx];
931 etp = (*wka_tp)[hash_idx] = (hashether_t *)g_malloc(sizeof(hashether_t));
934 if (memcmp(etp->addr, addr, sizeof(etp->addr)) == 0) {
935 /* address already known */
938 if (etp->next == NULL) {
939 etp->next = (hashether_t *)g_malloc(sizeof(hashether_t));
947 memcpy(etp->addr, addr, sizeof(etp->addr));
948 strncpy(etp->name, name, MAXNAMELEN);
949 etp->name[MAXNAMELEN-1] = '\0';
951 etp->is_dummy_entry = FALSE;
953 } /* add_manuf_name */
955 static hashmanuf_t *manuf_name_lookup(const guint8 *addr)
960 hash_idx = HASH_ETH_MANUF(addr);
962 tp = manuf_table[hash_idx];
965 if (memcmp(tp->addr, addr, sizeof(tp->addr)) == 0) {
973 } /* manuf_name_lookup */
975 static hashether_t *wka_name_lookup(const guint8 *addr, unsigned int mask)
978 hashether_t *(*wka_tp)[HASHETHSIZE];
980 guint8 masked_addr[6];
984 wka_tp = wka_table[mask];
985 if (wka_tp == NULL) {
986 /* There are no entries in the table for that mask value, as there is
987 no table for that mask value. */
991 /* Get the part of the address covered by the mask. */
992 for (i = 0, num = mask; num >= 8; i++, num -= 8)
993 masked_addr[i] = addr[i]; /* copy octets entirely covered by the mask */
994 /* Mask out the first masked octet */
995 masked_addr[i] = addr[i] & (0xFF << (8 - num));
997 /* Zero out completely-masked-out octets */
1001 hash_idx = hash_eth_wka(masked_addr, mask);
1003 tp = (*wka_tp)[hash_idx];
1006 if (memcmp(tp->addr, masked_addr, sizeof(tp->addr)) == 0) {
1014 } /* wka_name_lookup */
1016 static void initialize_ethers(void)
1022 /* Compute the pathname of the ethers file. */
1023 if (g_ethers_path == NULL) {
1024 g_ethers_path = g_strdup_printf("%s" G_DIR_SEPARATOR_S "%s",
1025 get_systemfile_dir(), ENAME_ETHERS);
1028 /* Set g_pethers_path here, but don't actually do anything
1029 * with it. It's used in get_ethbyname() and get_ethbyaddr()
1031 if (g_pethers_path == NULL)
1032 g_pethers_path = get_persconffile_path(ENAME_ETHERS, FALSE);
1034 /* manuf hash table initialization */
1036 /* Compute the pathname of the manuf file */
1037 manuf_path = get_datafile_path(ENAME_MANUF);
1039 /* Read it and initialize the hash table */
1040 set_ethent(manuf_path);
1042 while ((eth = get_ethent(&mask, TRUE))) {
1043 add_manuf_name(eth->addr, mask, eth->name);
1050 } /* initialize_ethers */
1052 static hashether_t *add_eth_name(const guint8 *addr, const gchar *name)
1057 hash_idx = HASH_ETH_ADDRESS(addr);
1059 tp = eth_table[hash_idx];
1062 tp = eth_table[hash_idx] = (hashether_t *)g_malloc(sizeof(hashether_t));
1065 if (memcmp(tp->addr, addr, sizeof(tp->addr)) == 0) {
1066 /* address already known */
1067 if (!tp->is_dummy_entry) {
1070 /* replace this dummy (manuf) entry with a real name */
1074 if (tp->next == NULL) {
1075 tp->next = (hashether_t *)g_malloc(sizeof(hashether_t));
1083 memcpy(tp->addr, addr, sizeof(tp->addr));
1084 strncpy(tp->name, name, MAXNAMELEN);
1085 tp->name[MAXNAMELEN-1] = '\0';
1087 tp->is_dummy_entry = FALSE;
1091 } /* add_eth_name */
1093 static gchar *eth_name_lookup(const guint8 *addr)
1096 hashmanuf_t *manufp;
1102 hash_idx = HASH_ETH_ADDRESS(addr);
1104 tp = eth_table[hash_idx];
1107 tp = eth_table[hash_idx] = (hashether_t *)g_malloc(sizeof(hashether_t));
1110 if (memcmp(tp->addr, addr, sizeof(tp->addr)) == 0) {
1113 if (tp->next == NULL) {
1114 tp->next = (hashether_t *)g_malloc(sizeof(hashether_t));
1122 /* fill in a new entry */
1124 memcpy(tp->addr, addr, sizeof(tp->addr));
1127 if ( (eth = get_ethbyaddr(addr)) == NULL) {
1128 /* Unknown name. Try looking for it in the well-known-address
1129 tables for well-known address ranges smaller than 2^24. */
1132 /* Only the topmost 5 bytes participate fully */
1133 if ((etp = wka_name_lookup(addr, mask+40)) != NULL) {
1134 sprintf(tp->name, "%s_%02x",
1135 etp->name, addr[5] & (0xFF >> mask));
1136 tp->is_dummy_entry = TRUE;
1146 /* Only the topmost 4 bytes participate fully */
1147 if ((etp = wka_name_lookup(addr, mask+32)) != NULL) {
1148 sprintf(tp->name, "%s_%02x:%02x",
1149 etp->name, addr[4] & (0xFF >> mask), addr[5]);
1150 tp->is_dummy_entry = TRUE;
1160 /* Only the topmost 3 bytes participate fully */
1161 if ((etp = wka_name_lookup(addr, mask+24)) != NULL) {
1162 sprintf(tp->name, "%s_%02x:%02x:%02x",
1163 etp->name, addr[3] & (0xFF >> mask), addr[4], addr[5]);
1164 tp->is_dummy_entry = TRUE;
1172 /* Now try looking in the manufacturer table. */
1173 if ((manufp = manuf_name_lookup(addr)) != NULL) {
1174 sprintf(tp->name, "%s_%02x:%02x:%02x",
1175 manufp->name, addr[3], addr[4], addr[5]);
1176 tp->is_dummy_entry = TRUE;
1180 /* Now try looking for it in the well-known-address
1181 tables for well-known address ranges larger than 2^24. */
1184 /* Only the topmost 2 bytes participate fully */
1185 if ((etp = wka_name_lookup(addr, mask+16)) != NULL) {
1186 sprintf(tp->name, "%s_%02x:%02x:%02x:%02x",
1187 etp->name, addr[2] & (0xFF >> mask), addr[3], addr[4],
1189 tp->is_dummy_entry = TRUE;
1199 /* Only the topmost byte participates fully */
1200 if ((etp = wka_name_lookup(addr, mask+8)) != NULL) {
1201 sprintf(tp->name, "%s_%02x:%02x:%02x:%02x:%02x",
1202 etp->name, addr[1] & (0xFF >> mask), addr[2], addr[3],
1204 tp->is_dummy_entry = TRUE;
1212 for (mask = 7; mask > 0; mask--) {
1213 /* Not even the topmost byte participates fully */
1214 if ((etp = wka_name_lookup(addr, mask)) != NULL) {
1215 sprintf(tp->name, "%s_%02x:%02x:%02x:%02x:%02x:%02x",
1216 etp->name, addr[0] & (0xFF >> mask), addr[1], addr[2],
1217 addr[3], addr[4], addr[5]);
1218 tp->is_dummy_entry = TRUE;
1223 /* No match whatsoever. */
1224 sprintf(tp->name, "%s", ether_to_str(addr));
1225 tp->is_dummy_entry = TRUE;
1228 strncpy(tp->name, eth->name, MAXNAMELEN);
1229 tp->name[MAXNAMELEN-1] = '\0';
1230 tp->is_dummy_entry = FALSE;
1235 } /* eth_name_lookup */
1237 static guint8 *eth_addr_lookup(const gchar *name)
1241 hashether_t **table = eth_table;
1244 /* to be optimized (hash table from name to addr) */
1245 for (i = 0; i < HASHETHSIZE; i++) {
1248 if (strcmp(tp->name, name) == 0)
1254 /* not in hash table : performs a file lookup */
1256 if ((eth = get_ethbyname(name)) == NULL)
1259 /* add new entry in hash table */
1261 tp = add_eth_name(eth->addr, name);
1265 } /* eth_addr_lookup */
1269 static int parse_ipxnets_line(char *line, ipxnet_t *ipxnet)
1272 * We allow three address separators (':', '-', and '.'),
1273 * as well as no separators
1277 guint32 a, a0, a1, a2, a3;
1278 gboolean found_single_number = FALSE;
1280 if ((cp = strchr(line, '#')))
1283 if ((cp = strtok(line, " \t\n")) == NULL)
1286 /* Either fill a0,a1,a2,a3 and found_single_number is FALSE,
1287 * fill a and found_single_number is TRUE,
1290 if (sscanf(cp, "%x:%x:%x:%x", &a0, &a1, &a2, &a3) != 4) {
1291 if (sscanf(cp, "%x-%x-%x-%x", &a0, &a1, &a2, &a3) != 4) {
1292 if (sscanf(cp, "%x.%x.%x.%x", &a0, &a1, &a2, &a3) != 4) {
1293 if (sscanf(cp, "%x", &a) == 1) {
1294 found_single_number = TRUE;
1303 if ((cp = strtok(NULL, " \t\n")) == NULL)
1306 if (found_single_number) {
1310 ipxnet->addr = (a0 << 24) | (a1 << 16) | (a2 << 8) | a3;
1313 strncpy(ipxnet->name, cp, MAXNAMELEN);
1314 ipxnet->name[MAXNAMELEN-1] = '\0';
1318 } /* parse_ipxnets_line */
1320 static FILE *ipxnet_p = NULL;
1322 static void set_ipxnetent(char *path)
1327 ipxnet_p = fopen(path, "r");
1330 static void end_ipxnetent(void)
1338 static ipxnet_t *get_ipxnetent(void)
1341 static ipxnet_t ipxnet;
1342 static int size = 0;
1343 static char *buf = NULL;
1345 if (ipxnet_p == NULL)
1348 while (fgetline(&buf, &size, ipxnet_p) >= 0) {
1349 if (parse_ipxnets_line(buf, &ipxnet) == 0) {
1356 } /* get_ipxnetent */
1358 static ipxnet_t *get_ipxnetbyname(const gchar *name)
1362 set_ipxnetent(g_ipxnets_path);
1364 while ((ipxnet = get_ipxnetent()) && strncmp(name, ipxnet->name, MAXNAMELEN) != 0)
1367 if (ipxnet == NULL) {
1370 set_ipxnetent(g_pipxnets_path);
1372 while ((ipxnet = get_ipxnetent()) && strncmp(name, ipxnet->name, MAXNAMELEN) != 0)
1380 } /* get_ipxnetbyname */
1382 static ipxnet_t *get_ipxnetbyaddr(guint32 addr)
1387 set_ipxnetent(g_ipxnets_path);
1389 while ((ipxnet = get_ipxnetent()) && (addr != ipxnet->addr) ) ;
1391 if (ipxnet == NULL) {
1394 set_ipxnetent(g_pipxnets_path);
1396 while ((ipxnet = get_ipxnetent()) && (addr != ipxnet->addr) )
1404 } /* get_ipxnetbyaddr */
1406 static void initialize_ipxnets(void)
1408 /* Compute the pathname of the ipxnets file.
1410 * XXX - is there a notion of an "ipxnets file" in any flavor of
1411 * UNIX, or with any add-on Netware package for UNIX? If not,
1412 * should the UNIX version of the ipxnets file be in the datafile
1413 * directory as well?
1415 if (g_ipxnets_path == NULL) {
1416 g_ipxnets_path = g_malloc(strlen(get_systemfile_dir()) +
1417 strlen(ENAME_IPXNETS) + 2);
1418 sprintf(g_ipxnets_path, "%s" G_DIR_SEPARATOR_S "%s",
1419 get_systemfile_dir(), ENAME_IPXNETS);
1422 /* Set g_pipxnets_path here, but don't actually do anything
1423 * with it. It's used in get_ipxnetbyname() and get_ipxnetbyaddr()
1425 if (g_pipxnets_path == NULL)
1426 g_pipxnets_path = get_persconffile_path(ENAME_IPXNETS, FALSE);
1428 } /* initialize_ipxnets */
1430 static hashipxnet_t *add_ipxnet_name(guint addr, const gchar *name)
1435 hash_idx = HASH_IPX_NET(addr);
1437 tp = ipxnet_table[hash_idx];
1440 tp = ipxnet_table[hash_idx] = (hashipxnet_t *)g_malloc(sizeof(hashipxnet_t));
1443 if (tp->next == NULL) {
1444 tp->next = (hashipxnet_t *)g_malloc(sizeof(hashipxnet_t));
1453 strncpy(tp->name, name, MAXNAMELEN);
1454 tp->name[MAXNAMELEN-1] = '\0';
1459 } /* add_ipxnet_name */
1461 static gchar *ipxnet_name_lookup(const guint addr)
1467 hash_idx = HASH_IPX_NET(addr);
1469 tp = ipxnet_table[hash_idx];
1472 tp = ipxnet_table[hash_idx] = (hashipxnet_t *)g_malloc(sizeof(hashipxnet_t));
1475 if (tp->addr == addr) {
1478 if (tp->next == NULL) {
1479 tp->next = (hashipxnet_t *)g_malloc(sizeof(hashipxnet_t));
1487 /* fill in a new entry */
1492 if ( (ipxnet = get_ipxnetbyaddr(addr)) == NULL) {
1494 sprintf(tp->name, "%X", addr);
1497 strncpy(tp->name, ipxnet->name, MAXNAMELEN);
1498 tp->name[MAXNAMELEN-1] = '\0';
1503 } /* ipxnet_name_lookup */
1505 static guint ipxnet_addr_lookup(const gchar *name, gboolean *success)
1509 hashipxnet_t **table = ipxnet_table;
1512 /* to be optimized (hash table from name to addr) */
1513 for (i = 0; i < HASHIPXNETSIZE; i++) {
1516 if (strcmp(tp->name, name) == 0) {
1524 /* not in hash table : performs a file lookup */
1526 if ((ipxnet = get_ipxnetbyname(name)) == NULL) {
1531 /* add new entry in hash table */
1533 tp = add_ipxnet_name(ipxnet->addr, name);
1538 } /* ipxnet_addr_lookup */
1541 read_hosts_file (const char *hostspath)
1547 guint32 host_addr[4]; /* IPv4 or IPv6 */
1548 struct e_in6_addr ipv6_addr;
1553 * See the hosts(4) or hosts(5) man page for hosts file format
1554 * (not available on all systems).
1556 if ((hf = fopen(hostspath, "r")) == NULL)
1559 while (fgetline(&line, &size, hf) >= 0) {
1560 if ((cp = strchr(line, '#')))
1563 if ((cp = strtok(line, " \t")) == NULL)
1564 continue; /* no tokens in the line */
1566 ret = inet_pton(AF_INET6, cp, &host_addr);
1568 continue; /* error parsing */
1573 /* Not valid IPv6 - valid IPv4? */
1574 if (inet_pton(AF_INET, cp, &host_addr) != 1)
1579 if ((cp = strtok(NULL, " \t")) == NULL)
1580 continue; /* no host name */
1583 memcpy(&ipv6_addr, host_addr, sizeof ipv6_addr);
1584 add_ipv6_name(&ipv6_addr, cp);
1586 add_ipv4_name(host_addr[0], cp);
1589 * Add the aliases, too, if there are any.
1591 while ((cp = strtok(NULL, " \t")) != NULL) {
1593 memcpy(&ipv6_addr, host_addr, sizeof ipv6_addr);
1594 add_ipv6_name(&ipv6_addr, cp);
1596 add_ipv4_name(host_addr[0], cp);
1604 } /* read_hosts_file */
1607 * External Functions
1611 host_name_lookup_init(void) {
1613 #ifdef HAVE_GNU_ADNS
1615 * We're using GNU ADNS, which doesn't check the system hosts file;
1616 * we load that file ourselves.
1620 static char rootpath_nt[] = "\\system32\\drivers\\etc\\hosts";
1621 static char rootpath_ot[] = "\\hosts";
1623 sysroot = getenv("WINDIR");
1624 if (sysroot != NULL) {
1626 * The file should be under WINDIR.
1627 * If this is Windows NT (NT 4.0,2K,XP,Server2K3), it's in
1628 * %WINDIR%\system32\drivers\etc\hosts.
1629 * If this is Windows OT (95,98,Me), it's in %WINDIR%\hosts.
1631 * XXX - should we base it on the dwPlatformId value from
1634 hostspath = g_strconcat(sysroot, rootpath_nt, NULL);
1635 if (!read_hosts_file(hostspath)) {
1637 hostspath = g_strconcat(sysroot, rootpath_ot, NULL);
1638 read_hosts_file(hostspath);
1643 read_hosts_file("/etc/hosts");
1645 #endif /* HAVE_GNU_ADNS */
1648 * Load the user's hosts file, if they have one.
1650 hostspath = get_persconffile_path(ENAME_HOSTS, FALSE);
1651 if (!read_hosts_file(hostspath) && errno != ENOENT) {
1652 report_open_failure(hostspath, errno, FALSE);
1656 #ifdef HAVE_GNU_ADNS
1657 /* XXX - Any flags we should be using? */
1658 /* XXX - We could provide config settings for DNS servers, and
1659 pass them to ADNS with adns_init_strcfg */
1660 if (adns_init(&ads, 0, 0 /*0=>stderr*/) != 0) {
1662 * XXX - should we report the error? I'm assuming that some crashes
1663 * reported on a Windows machine with TCP/IP not configured are due
1664 * to "adns_init()" failing (due to the lack of TCP/IP) and leaving
1665 * ADNS in a state where it crashes due to that. We'll still try
1666 * doing name resolution anyway.
1670 gnu_adns_initialized = TRUE;
1671 adns_currently_queued = 0;
1672 #endif /* HAVE_GNU_ADNS */
1675 #ifdef HAVE_GNU_ADNS
1677 /* XXX - The ADNS "documentation" isn't very clear:
1678 * - Do we need to keep our query structures around?
1681 host_name_lookup_process(gpointer data _U_) {
1682 adns_queue_msg_t *almsg;
1684 char addr_str[] = "111.222.333.444.in-addr.arpa.";
1690 adns_queue_head = g_list_first(adns_queue_head);
1692 cur = adns_queue_head;
1693 while (cur && adns_currently_queued <= prefs.name_resolve_concurrency) {
1694 almsg = (adns_queue_msg_t *) cur->data;
1695 if (! almsg->submitted && almsg->type == AF_INET) {
1696 addr_bytes = (guint8 *) &almsg->ip4_addr;
1697 sprintf(addr_str, "%u.%u.%u.%u.in-addr.arpa.", addr_bytes[3],
1698 addr_bytes[2], addr_bytes[1], addr_bytes[0]);
1699 /* XXX - what if it fails? */
1700 adns_submit (ads, addr_str, adns_r_ptr, 0, NULL, &almsg->query);
1701 almsg->submitted = TRUE;
1702 adns_currently_queued++;
1707 cur = adns_queue_head;
1710 almsg = (adns_queue_msg_t *) cur->data;
1711 if (almsg->submitted) {
1712 ret = adns_check(ads, &almsg->query, &ans, NULL);
1714 if (ans->status == adns_s_ok) {
1715 add_ipv4_name(almsg->ip4_addr, *ans->rrs.str);
1722 adns_queue_head = g_list_remove(adns_queue_head, (void *) almsg);
1724 adns_currently_queued--;
1728 /* Keep the timeout in place */
1733 host_name_lookup_cleanup(void) {
1736 adns_queue_head = g_list_first(adns_queue_head);
1737 while (adns_queue_head) {
1738 qdata = adns_queue_head->data;
1739 adns_queue_head = g_list_remove(adns_queue_head, qdata);
1743 if (gnu_adns_initialized)
1750 host_name_lookup_process(gpointer data _U_) {
1751 /* Kill the timeout, as there's nothing for it to do */
1756 host_name_lookup_cleanup(void) {
1759 #endif /* HAVE_GNU_ADNS */
1761 extern gchar *get_hostname(guint addr)
1765 if (!(g_resolv_flags & RESOLV_NETWORK))
1766 return ip_to_str((guint8 *)&addr);
1768 return host_name_lookup(addr, &found);
1771 extern const gchar *get_hostname6(struct e_in6_addr *addr)
1776 if (!(g_resolv_flags & RESOLV_NETWORK))
1777 return ip6_to_str(addr);
1778 #ifdef SOLARIS8_INET6
1779 if (IN6_IS_ADDR_LINKLOCAL((struct in6_addr*)addr) || IN6_IS_ADDR_MULTICAST((struct in6_addr*)addr))
1781 if (IN6_IS_ADDR_LINKLOCAL(addr) || IN6_IS_ADDR_MULTICAST(addr))
1783 return ip6_to_str(addr);
1786 return host_name_lookup6(addr, &found);
1789 extern void add_ipv4_name(guint addr, const gchar *name)
1794 hash_idx = HASH_IPV4_ADDRESS(addr);
1796 tp = ipv4_table[hash_idx];
1799 tp = ipv4_table[hash_idx] = (hashipv4_t *)g_malloc(sizeof(hashipv4_t));
1802 if (tp->addr == addr) {
1803 /* address already known */
1804 if (!tp->is_dummy_entry) {
1807 /* replace this dummy entry with the new one */
1811 if (tp->next == NULL) {
1812 tp->next = (hashipv4_t *)g_malloc(sizeof(hashipv4_t));
1820 strncpy(tp->name, name, MAXNAMELEN);
1821 tp->name[MAXNAMELEN-1] = '\0';
1824 tp->is_dummy_entry = FALSE;
1826 } /* add_ipv4_name */
1828 extern void add_ipv6_name(struct e_in6_addr *addrp, const gchar *name)
1833 hash_idx = HASH_IPV6_ADDRESS(*addrp);
1835 tp = ipv6_table[hash_idx];
1838 tp = ipv6_table[hash_idx] = (hashipv6_t *)g_malloc(sizeof(hashipv6_t));
1841 if (memcmp(&tp->addr, addrp, sizeof (struct e_in6_addr)) == 0) {
1842 /* address already known */
1843 if (!tp->is_dummy_entry) {
1846 /* replace this dummy entry with the new one */
1850 if (tp->next == NULL) {
1851 tp->next = (hashipv6_t *)g_malloc(sizeof(hashipv6_t));
1859 strncpy(tp->name, name, MAXNAMELEN);
1860 tp->name[MAXNAMELEN-1] = '\0';
1863 tp->is_dummy_entry = FALSE;
1865 } /* add_ipv6_name */
1867 extern gchar *get_udp_port(guint port)
1869 static gchar str[3][MAXNAMELEN];
1872 if (!(g_resolv_flags & RESOLV_TRANSPORT)) {
1873 if (cur == &str[0][0]) {
1875 } else if (cur == &str[1][0]) {
1880 sprintf(cur, "%u", port);
1884 return serv_name_lookup(port, PT_UDP);
1886 } /* get_udp_port */
1888 extern gchar *get_tcp_port(guint port)
1890 static gchar str[3][MAXNAMELEN];
1893 if (!(g_resolv_flags & RESOLV_TRANSPORT)) {
1894 if (cur == &str[0][0]) {
1896 } else if (cur == &str[1][0]) {
1901 sprintf(cur, "%u", port);
1905 return serv_name_lookup(port, PT_TCP);
1907 } /* get_tcp_port */
1909 extern gchar *get_sctp_port(guint port)
1911 static gchar str[3][MAXNAMELEN];
1914 if (!(g_resolv_flags & RESOLV_TRANSPORT)) {
1915 if (cur == &str[0][0]) {
1917 } else if (cur == &str[1][0]) {
1922 sprintf(cur, "%u", port);
1926 return serv_name_lookup(port, PT_SCTP);
1928 } /* get_sctp_port */
1931 const gchar *get_addr_name(address *addr)
1933 const gchar *result;
1935 result = solve_address_to_name(addr);
1941 /* if it gets here, either it is of type AT_NONE, */
1942 /* or it should be solvable in address_to_str -unless addr->type is wrongly defined- */
1944 if (addr->type == AT_NONE){
1948 return(address_to_str(addr));
1949 } /* get_addr_name */
1952 void get_addr_name_buf(address *addr, gchar *buf, guint size)
1954 const gchar *result;
1956 result = get_addr_name(addr);
1958 strncpy(buf,result,size);
1962 } /* get_addr_name_buf */
1965 extern gchar *get_ether_name(const guint8 *addr)
1967 if (!(g_resolv_flags & RESOLV_MAC))
1968 return ether_to_str(addr);
1970 if (!eth_resolution_initialized) {
1971 initialize_ethers();
1972 eth_resolution_initialized = 1;
1975 return eth_name_lookup(addr);
1977 } /* get_ether_name */
1979 /* Look for an ether name in the hash, and return it if found.
1980 * If it's not found, simply return NULL. We DO NOT make a new
1981 * hash entry for it with the hex digits turned into a string.
1983 gchar *get_ether_name_if_known(const guint8 *addr)
1988 /* Initialize ether structs if we're the first
1989 * ether-related function called */
1990 if (!(g_resolv_flags & RESOLV_MAC))
1993 if (!eth_resolution_initialized) {
1994 initialize_ethers();
1995 eth_resolution_initialized = 1;
1998 hash_idx = HASH_ETH_ADDRESS(addr);
2000 tp = eth_table[hash_idx];
2003 /* Hash key not found in table.
2004 * Force a lookup (and a hash entry) for addr, then call
2005 * myself. I plan on not getting into an infinite loop because
2006 * eth_name_lookup() is guaranteed to make a hashtable entry,
2007 * so when I call myself again, I can never get into this
2008 * block of code again. Knock on wood...
2010 (void) eth_name_lookup(addr);
2011 return get_ether_name_if_known(addr); /* a well-placed goto would suffice */
2015 if (memcmp(tp->addr, addr, sizeof(tp->addr)) == 0) {
2016 if (!tp->is_dummy_entry) {
2017 /* A name was found, and its origin is an ethers file */
2021 /* A name was found, but it was created, not found in a file */
2025 if (tp->next == NULL) {
2026 /* Read my reason above for why I'm sure I can't get into an infinite loop */
2027 (void) eth_name_lookup(addr);
2028 return get_ether_name_if_known(addr); /* a well-placed goto would suffice */
2033 g_assert_not_reached();
2038 extern guint8 *get_ether_addr(const gchar *name)
2041 /* force resolution (do not check g_resolv_flags) */
2043 if (!eth_resolution_initialized) {
2044 initialize_ethers();
2045 eth_resolution_initialized = 1;
2048 return eth_addr_lookup(name);
2050 } /* get_ether_addr */
2052 extern void add_ether_byip(guint ip, const guint8 *eth)
2058 /* first check that IP address can be resolved */
2060 if ((host = host_name_lookup(ip, &found)) == NULL)
2063 /* ok, we can add this entry in the ethers hashtable */
2066 add_eth_name(eth, host);
2068 } /* add_ether_byip */
2070 extern const gchar *get_ipxnet_name(const guint32 addr)
2073 if (!(g_resolv_flags & RESOLV_NETWORK)) {
2074 return ipxnet_to_str_punct(addr, '\0');
2077 if (!ipxnet_resolution_initialized) {
2078 initialize_ipxnets();
2079 ipxnet_resolution_initialized = 1;
2082 return ipxnet_name_lookup(addr);
2084 } /* get_ipxnet_name */
2086 extern guint32 get_ipxnet_addr(const gchar *name, gboolean *known)
2091 /* force resolution (do not check g_resolv_flags) */
2093 if (!ipxnet_resolution_initialized) {
2094 initialize_ipxnets();
2095 ipxnet_resolution_initialized = 1;
2098 addr = ipxnet_addr_lookup(name, &success);
2103 } /* get_ipxnet_addr */
2105 extern const gchar *get_manuf_name(const guint8 *addr)
2107 static gchar str[3][MAXMANUFLEN];
2109 hashmanuf_t *manufp;
2111 if ((g_resolv_flags & RESOLV_MAC) && !eth_resolution_initialized) {
2112 initialize_ethers();
2113 eth_resolution_initialized = 1;
2116 if (!(g_resolv_flags & RESOLV_MAC) || ((manufp = manuf_name_lookup(addr)) == NULL)) {
2117 if (cur == &str[0][0]) {
2119 } else if (cur == &str[1][0]) {
2124 sprintf(cur, "%02x:%02x:%02x", addr[0], addr[1], addr[2]);
2128 return manufp->name;
2130 } /* get_manuf_name */
2133 const gchar *get_manuf_name_if_known(const guint8 *addr)
2135 hashmanuf_t *manufp;
2137 if (!eth_resolution_initialized) {
2138 initialize_ethers();
2139 eth_resolution_initialized = 1;
2142 if ((manufp = manuf_name_lookup(addr)) == NULL) {
2146 return manufp->name;
2148 } /* get_manuf_name_if_known */
2151 /* Translate a string, assumed either to be a dotted-quad IP address or
2152 * a host name, to a numeric IP address. Return TRUE if we succeed and
2153 * set "*addrp" to that numeric IP address; return FALSE if we fail.
2154 * Used more in the dfilter parser rather than in packet dissectors */
2155 gboolean get_host_ipaddr(const char *host, guint32 *addrp)
2157 struct in_addr ipaddr;
2161 * don't change it to inet_pton(AF_INET), they are not 100% compatible.
2162 * inet_pton(AF_INET) does not support hexadecimal notation nor
2163 * less-than-4 octet notation.
2165 if (!inet_aton(host, &ipaddr)) {
2166 /* It's not a valid dotted-quad IP address; is it a valid
2168 hp = gethostbyname(host);
2172 /* Apparently, some versions of gethostbyaddr can
2173 * return IPv6 addresses. */
2174 } else if (hp->h_length <= (int) sizeof (struct in_addr)) {
2175 memcpy(&ipaddr, hp->h_addr, hp->h_length);
2180 /* Does the string really contain dotted-quad IP?
2181 * Check against inet_atons that accept strings such as
2182 * "130.230" as valid addresses and try to convert them
2183 * to some form of a classful (host.net) notation.
2185 unsigned int a0, a1, a2, a3;
2186 if (sscanf(host, "%u.%u.%u.%u", &a0, &a1, &a2, &a3) != 4)
2190 *addrp = g_ntohl(ipaddr.s_addr);
2195 * Translate IPv6 numeric address or FQDN hostname, into binary IPv6 address.
2196 * Return TRUE if we succeed and set "*addrp" to that numeric IP address;
2197 * return FALSE if we fail.
2199 gboolean get_host_ipaddr6(const char *host, struct e_in6_addr *addrp)
2203 if (inet_pton(AF_INET6, host, addrp) == 1)
2207 #ifdef HAVE_GETHOSTBYNAME2
2208 hp = gethostbyname2(host, AF_INET6);
2212 if (hp != NULL && hp->h_length == sizeof(struct e_in6_addr)) {
2213 memcpy(addrp, hp->h_addr, hp->h_length);
2221 * Find out whether a hostname resolves to an ip or ipv6 address
2222 * Return "ip6" if it is IPv6, "ip" otherwise (including the case
2223 * that we don't know)
2225 const char* host_ip_af(const char *host
2226 #ifndef HAVE_GETHOSTBYNAME2
2231 #ifdef HAVE_GETHOSTBYNAME2
2233 return (h = gethostbyname2(host, AF_INET6)) && h->h_addrtype == AF_INET6 ? "ip6" : "ip";