2 * Routines for network object lookup
4 * Laurent Deniel <laurent.deniel@free.fr>
6 * Wireshark - Network traffic analyzer
7 * By Gerald Combs <gerald@wireshark.org>
8 * Copyright 1998 Gerald Combs
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * as published by the Free Software Foundation; either version 2
13 * of the License, or (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
34 * Win32 doesn't have SIGALRM (and it's the OS where name lookup calls
35 * are most likely to take a long time, given the way address-to-name
36 * lookups are done over NBNS).
38 * Mac OS X does have SIGALRM, but if you longjmp() out of a name resolution
39 * call in a signal handler, you might crash, because the state of the
40 * resolution code that sends messages to lookupd might be inconsistent
41 * if you jump out of it in middle of a call.
43 * In at least some Linux distributions (e.g., RedHat Linux 9), if ADNS
44 * is used, we appear to hang in host_name_lookup6() in a gethostbyaddr()
45 * call (and possibly in other gethostbyaddr() calls), because there's
46 * a mutex lock held in gethostbyaddr() and it doesn't get released
47 * if we longjmp out of it.
49 * There's no guarantee that longjmp()ing out of name resolution calls
50 * will work on *any* platform; OpenBSD got rid of the alarm/longjmp
51 * code in tcpdump, to avoid those sorts of problems, and that was
52 * picked up by tcpdump.org tcpdump.
54 * So, for now, we do not define AVOID_DNS_TIMEOUT. If we get a
55 * significantly more complaints about lookups taking a long time,
56 * we can reconsider that decision. (Note that tcpdump originally
57 * added that for the benefit of systems using NIS to look up host
58 * names; that might now be fixed in NIS implementations, for those
59 * sites still using NIS rather than DNS for that....)
66 #ifdef HAVE_NETINET_IN_H
67 # include <netinet/in.h>
74 #ifdef HAVE_ARPA_INET_H
75 #include <arpa/inet.h>
80 #ifdef HAVE_SYS_SOCKET_H
81 #include <sys/socket.h> /* needed to define AF_ values on UNIX */
84 #ifdef HAVE_WINSOCK2_H
85 #include <winsock2.h> /* needed to define AF_ values on Windows */
88 #ifndef HAVE_INET_ATON_H
89 # include "wsutil/inet_aton.h"
92 #ifdef NEED_INET_V6DEFS_H
93 # include "wsutil/inet_v6defs.h"
96 #if defined(_WIN32) && defined(INET6)
97 # include <ws2tcpip.h>
101 # if defined(_WIN32) && !defined(INET6)
102 # define socklen_t unsigned int
105 # include <ares_version.h>
107 # ifdef HAVE_GNU_ADNS
110 # if defined(inet_aton) && defined(_WIN32)
113 # endif /* HAVE_GNU_ADNS */
114 #endif /* HAVE_C_ARES */
120 #include "addr_and_mask.h"
121 #include "ipv6-utils.h"
122 #include "addr_resolv.h"
123 #include "wsutil/filesystem.h"
125 #include <wsutil/report_err.h>
126 #include <wsutil/file_util.h>
127 #include <wsutil/pint.h>
129 #include <epan/strutil.h>
130 #include <epan/to_str-int.h>
131 #include <epan/prefs.h>
132 #include <epan/emem.h>
134 #define ENAME_HOSTS "hosts"
135 #define ENAME_SUBNETS "subnets"
136 #define ENAME_ETHERS "ethers"
137 #define ENAME_IPXNETS "ipxnets"
138 #define ENAME_MANUF "manuf"
139 #define ENAME_SERVICES "services"
141 #define HASHETHSIZE 2048
142 #define HASHHOSTSIZE 2048
143 #define HASHIPXNETSIZE 256
144 #define SUBNETLENGTHSIZE 32 /*1-32 inc.*/
146 /* hash table used for IPv4 lookup */
148 #define HASH_IPV4_ADDRESS(addr) (g_htonl(addr) & (HASHHOSTSIZE - 1))
151 typedef struct sub_net_hashipv4 {
153 guint8 flags; /* B0 dummy_entry, B1 resolve, B2 If the address is used in the trace */
154 struct sub_net_hashipv4 *next;
156 gchar name[MAXNAMELEN];
157 } sub_net_hashipv4_t;
159 /* Array of entries of subnets of different lengths */
161 gsize mask_length; /*1-32*/
162 guint32 mask; /* e.g. 255.255.255.*/
163 sub_net_hashipv4_t** subnet_addresses; /* Hash table of subnet addresses */
164 } subnet_length_entry_t;
168 typedef struct serv_port {
175 /* hash table used for IPX network lookup */
177 /* XXX - check goodness of hash function */
179 #define HASH_IPX_NET(net) ((net) & (HASHIPXNETSIZE - 1))
181 typedef struct hashipxnet {
183 struct hashipxnet *next;
184 gchar name[MAXNAMELEN];
187 /* hash tables used for ethernet and manufacturer lookup */
188 #define HASHETHER_STATUS_UNRESOLVED 1
189 #define HASHETHER_STATUS_RESOLVED_DUMMY 2
190 #define HASHETHER_STATUS_RESOLVED_NAME 3
193 typedef struct hashether {
194 struct hashether *next;
195 guint status; /* (See above) */
198 char resolved_name[MAXNAMELEN];
201 /* internal ethernet type */
203 typedef struct _ether
206 char name[MAXNAMELEN];
209 /* internal ipxnet type */
211 typedef struct _ipxnet
214 char name[MAXNAMELEN];
217 static GHashTable *ipxnet_hash_table = NULL;
218 static GHashTable *ipv4_hash_table = NULL;
219 static GHashTable *ipv6_hash_table = NULL;
221 static GSList *manually_resolved_ipv4_list = NULL;
222 static GSList *manually_resolved_ipv6_list = NULL;
224 typedef struct _resolved_ipv4
227 char name[MAXNAMELEN];
230 typedef struct _resolved_ipv6
232 struct e_in6_addr ip6_addr;
233 char name[MAXNAMELEN];
236 static addrinfo_lists_t addrinfo_lists = { NULL, NULL};
238 static gchar *cb_service;
239 static port_type cb_proto = PT_NONE;
242 static GHashTable *manuf_hashtable = NULL;
243 static GHashTable *wka_hashtable = NULL;
244 static GHashTable *eth_hashtable = NULL;
245 static GHashTable *serv_port_hashtable = NULL;
247 static subnet_length_entry_t subnet_length_entries[SUBNETLENGTHSIZE]; /* Ordered array of entries */
248 static gboolean have_subnet_entry = FALSE;
250 static gboolean new_resolved_objects = FALSE;
252 static GPtrArray* extra_hosts_files = NULL;
254 static hashether_t *add_eth_name(const guint8 *addr, const gchar *name);
255 static void add_serv_port_cb(const guint32 port);
258 /* http://eternallyconfuzzled.com/tuts/algorithms/jsw_tut_hashing.aspx#existing
262 ipv6_oat_hash(gconstpointer key)
265 const unsigned char *p = (const unsigned char *)key;
269 for ( i = 0; i < len; i++ ) {
283 ipv6_equal(gconstpointer v1, gconstpointer v2)
286 if( memcmp(v1, v2, sizeof (struct e_in6_addr)) == 0 ) {
294 * Flag controlling what names to resolve.
296 e_addr_resolve gbl_resolv_flags = {TRUE, FALSE, FALSE, TRUE, TRUE, FALSE};
297 #if defined(HAVE_C_ARES) || defined(HAVE_GNU_ADNS)
298 static guint name_resolve_concurrency = 500;
302 * Global variables (can be changed in GUI sections)
303 * XXX - they could be changed in GUI code, but there's currently no
304 * GUI code to change them.
307 gchar *g_ethers_path = NULL; /* global ethers file */
308 gchar *g_pethers_path = NULL; /* personal ethers file */
309 gchar *g_ipxnets_path = NULL; /* global ipxnets file */
310 gchar *g_pipxnets_path = NULL; /* personal ipxnets file */
311 gchar *g_services_path = NULL; /* global services file */
312 gchar *g_pservices_path = NULL; /* personal services file */
313 /* first resolving call */
318 * Submitted queries trigger a callback (c_ares_ghba_cb()).
319 * Queries are added to c_ares_queue_head. During processing, queries are
320 * popped off the front of c_ares_queue_head and submitted using
321 * ares_gethostbyaddr().
322 * The callback processes the response, then frees the request.
325 typedef struct _async_dns_queue_msg
329 struct e_in6_addr ip6;
332 } async_dns_queue_msg_t;
334 typedef struct _async_hostent {
340 #if ( ( ARES_VERSION_MAJOR < 1 ) \
341 || ( 1 == ARES_VERSION_MAJOR && ARES_VERSION_MINOR < 5 ) )
342 static void c_ares_ghba_cb(void *arg, int status, struct hostent *hostent);
344 static void c_ares_ghba_cb(void *arg, int status, int timeouts _U_, struct hostent *hostent);
347 ares_channel ghba_chan; /* ares_gethostbyaddr -- Usually non-interactive, no timeout */
348 ares_channel ghbn_chan; /* ares_gethostbyname -- Usually interactive, timeout */
355 * Submitted queries have to be checked individually using adns_check().
356 * Queries are added to adns_queue_head. During processing, the list is
357 * iterated twice: once to request queries up to the concurrency limit,
358 * and once to check the status of each query.
363 typedef struct _async_dns_queue_msg
369 } async_dns_queue_msg_t;
371 #endif /* HAVE_GNU_ADNS */
372 #endif /* HAVE_C_ARES */
374 static gboolean async_dns_initialized = FALSE;
375 static guint async_dns_in_flight = 0;
376 static GList *async_dns_queue_head = NULL;
378 /* push a dns request */
380 add_async_dns_ipv4(int type, guint32 addr)
382 async_dns_queue_msg_t *msg;
384 msg = g_new(async_dns_queue_msg_t,1);
387 msg->addr.ip4 = addr;
390 msg->ip4_addr = addr;
391 msg->submitted = FALSE;
393 async_dns_queue_head = g_list_append(async_dns_queue_head, (gpointer) msg);
401 const gchar* name; /* Shallow copy */
405 * Miscellaneous functions
409 fgetline(char **buf, int *size, FILE *fp)
414 if (fp == NULL || buf == NULL)
421 *buf = (char *)g_malloc(*size);
431 while ((c = getc(fp)) != EOF && c != '\r' && c != '\n') {
432 if (len+1 >= *size) {
433 *buf = (char *)g_realloc(*buf, *size += BUFSIZ);
438 if (len == 0 && c == EOF)
449 * Local function definitions
451 static subnet_entry_t subnet_lookup(const guint32 addr);
452 static void subnet_entry_set(guint32 subnet_addr, const guint32 mask_length, const gchar* name);
456 add_service_name(port_type proto, const guint port, const char *service_name)
458 serv_port_t *serv_port_table;
461 key = (int *)g_new(int, 1);
464 serv_port_table = (serv_port_t *)g_hash_table_lookup(serv_port_hashtable, &port);
465 if (serv_port_table == NULL) {
466 serv_port_table = g_new0(serv_port_t,1);
467 g_hash_table_insert(serv_port_hashtable, key, serv_port_table);
475 g_free(serv_port_table->tcp_name);
476 serv_port_table->tcp_name = g_strdup(service_name);
479 g_free(serv_port_table->udp_name);
480 serv_port_table->udp_name = g_strdup(service_name);
483 g_free(serv_port_table->sctp_name);
484 serv_port_table->sctp_name = g_strdup(service_name);
487 g_free(serv_port_table->dccp_name);
488 serv_port_table->dccp_name = g_strdup(service_name);
492 /* Should not happen */
495 new_resolved_objects = TRUE;
500 parse_service_line (char *line)
503 * See the services(4) or services(5) man page for services file format
504 * (not available on all systems).
512 range_t *port_rng = NULL;
513 guint32 max_port = MAX_UDP_PORT;
515 if ((cp = strchr(line, '#')))
518 if ((cp = strtok(line, " \t")) == NULL)
523 if ((cp = strtok(NULL, " \t")) == NULL)
528 if (strtok(cp, "/") == NULL)
531 if ((cp = strtok(NULL, "/")) == NULL)
534 /* seems we got all interesting things from the file */
535 if(strcmp(cp, "tcp") == 0) {
536 max_port = MAX_TCP_PORT;
539 else if(strcmp(cp, "udp") == 0) {
540 max_port = MAX_UDP_PORT;
543 else if(strcmp(cp, "sctp") == 0) {
544 max_port = MAX_SCTP_PORT;
547 else if(strcmp(cp, "dccp") == 0) {
548 max_port = MAX_DCCP_PORT;
554 if(CVT_NO_ERROR != range_convert_str(&port_rng, port, max_port) ) {
555 /* some assertion here? */
559 cb_service = service;
561 range_foreach(port_rng, add_serv_port_cb);
564 } /* parse_service_line */
568 add_serv_port_cb(const guint32 port)
571 add_service_name(cb_proto, port, cb_service);
577 parse_services_file(const char * path)
581 static char *buf = NULL;
583 /* services hash table initialization */
584 serv_p = ws_fopen(path, "r");
589 while (fgetline(&buf, &size, serv_p) >= 0) {
590 parse_service_line (buf);
597 * unsigned integer to ascii
602 gchar *bp = (gchar *)ep_alloc(MAXNAMELEN);
604 /* XXX, guint32_to_str() ? */
605 guint32_to_str_buf(port, bp, MAXNAMELEN);
611 *serv_name_lookup(const guint port, const port_type proto)
613 serv_port_t *serv_port_table;
616 serv_port_table = (serv_port_t *)g_hash_table_lookup(serv_port_hashtable, &port);
619 /* Set which table we should look up port in */
622 if(serv_port_table->udp_name){
623 return serv_port_table->udp_name;
627 if(serv_port_table->tcp_name){
628 return serv_port_table->tcp_name;
632 if(serv_port_table->sctp_name){
633 return serv_port_table->sctp_name;
637 if(serv_port_table->dccp_name){
638 return serv_port_table->dccp_name;
642 /* not yet implemented */
648 /* getservbyport() was used here but it was to expensive, if the functionality is desired
649 * it would be better to pre parse etc/services or C:\Windows\System32\drivers\etc at
652 name = (gchar*)g_malloc(16);
653 guint32_to_str_buf(port, name, 16);
655 if(serv_port_table == NULL){
658 key = (int *)g_new(int, 1);
660 serv_port_table = g_new0(serv_port_t,1);
661 g_hash_table_insert(serv_port_hashtable, key, serv_port_table);
665 serv_port_table->udp_name = name;
668 serv_port_table->tcp_name = name;
671 serv_port_table->sctp_name = name;
674 serv_port_table->dccp_name = name;
682 } /* serv_name_lookup */
685 destroy_serv_port(gpointer data)
687 serv_port_t *table = (serv_port_t*)data;
688 g_free(table->udp_name);
689 g_free(table->tcp_name);
690 g_free(table->sctp_name);
691 g_free(table->dccp_name);
696 initialize_services(void)
701 static char rootpath_nt[] = "\\system32\\drivers\\etc\\services";
704 /* the hash table won't ignore duplicates, so use the personal path first */
705 g_assert(serv_port_hashtable == NULL);
706 serv_port_hashtable = g_hash_table_new_full(g_int_hash, g_int_equal, g_free, destroy_serv_port);
708 /* Read the system services file first */
711 sysroot = getenv_utf8("WINDIR");
712 if (sysroot != NULL) {
714 * The file should be under WINDIR.
715 * If this is Windows NT (NT 4.0,2K,XP,Server2K3), it's in
716 * %WINDIR%\system32\drivers\etc\services.
718 hostspath = g_strconcat(sysroot, rootpath_nt, NULL);
719 parse_services_file(hostspath);
723 parse_services_file("/etc/services");
727 /* set personal services path */
728 if (g_pservices_path == NULL)
729 g_pservices_path = get_persconffile_path(ENAME_SERVICES, FALSE);
731 parse_services_file(g_pservices_path);
733 /* Compute the pathname of the services file. */
734 if (g_services_path == NULL) {
735 g_services_path = get_datafile_path(ENAME_SERVICES);
738 parse_services_file(g_services_path);
740 } /* initialize_services */
743 service_name_lookup_cleanup(void)
745 if(serv_port_hashtable){
746 g_hash_table_destroy(serv_port_hashtable);
747 serv_port_hashtable = NULL;
751 /* Fill in an IP4 structure with info from subnets file or just with the
752 * string form of the address.
755 fill_dummy_ip4(const guint addr, hashipv4_t* volatile tp)
757 subnet_entry_t subnet_entry;
759 if ((tp->flags & DUMMY_ADDRESS_ENTRY) == DUMMY_ADDRESS_ENTRY)
760 return; /* already done */
762 tp->flags = tp->flags | DUMMY_ADDRESS_ENTRY; /* Overwrite if we get async DNS reply */
764 /* Do we have a subnet for this address? */
765 subnet_entry = subnet_lookup(addr);
766 if(0 != subnet_entry.mask) {
767 /* Print name, then '.' then IP address after subnet mask */
769 gchar buffer[MAX_IP_STR_LEN];
773 host_addr = addr & (~(guint32)subnet_entry.mask);
774 ip_to_str_buf((guint8 *)&host_addr, buffer, MAX_IP_STR_LEN);
777 /* Skip to first octet that is not totally masked
778 * If length of mask is 32, we chomp the whole address.
779 * If the address string starts '.' (should not happen?),
782 i = subnet_entry.mask_length / 8;
783 while(*(paddr) != '\0' && i > 0) {
784 if(*(++paddr) == '.') {
789 /* There are more efficient ways to do this, but this is safe if we
790 * trust g_snprintf and MAXNAMELEN
792 g_snprintf(tp->name, MAXNAMELEN, "%s%s", subnet_entry.name, paddr);
794 ip_to_str_buf((const guint8 *)&addr, tp->name, MAXNAMELEN);
804 #if ( ( ARES_VERSION_MAJOR < 1 ) \
805 || ( 1 == ARES_VERSION_MAJOR && ARES_VERSION_MINOR < 5 ) )
813 async_dns_queue_msg_t *caqm = (async_dns_queue_msg_t *)arg;
817 /* XXX, what to do if async_dns_in_flight == 0? */
818 async_dns_in_flight--;
820 if (status == ARES_SUCCESS) {
821 for (p = he->h_addr_list; *p != NULL; p++) {
822 switch(caqm->family) {
824 add_ipv4_name(caqm->addr.ip4, he->h_name);
827 add_ipv6_name(&caqm->addr.ip6, he->h_name);
830 /* Throw an exception? */
837 #endif /* HAVE_C_ARES */
839 /* --------------- */
841 new_ipv4(const guint addr)
843 hashipv4_t *tp = g_new(hashipv4_t, 1);
846 ip_to_str_buf((const guint8 *)&addr, tp->ip, sizeof(tp->ip));
851 host_lookup(const guint addr, gboolean *found)
853 hashipv4_t * volatile tp;
857 tp = (hashipv4_t *)g_hash_table_lookup(ipv4_hash_table, GUINT_TO_POINTER(addr));
860 g_hash_table_insert(ipv4_hash_table, GUINT_TO_POINTER(addr), tp);
862 if ((tp->flags & DUMMY_AND_RESOLVE_FLGS) == DUMMY_ADDRESS_ENTRY){
865 if ((tp->flags & DUMMY_ADDRESS_ENTRY) == DUMMY_ADDRESS_ENTRY){
872 if (gbl_resolv_flags.network_name && gbl_resolv_flags.use_external_net_name_resolver) {
873 tp->flags = tp->flags|TRIED_RESOLVE_ADDRESS;
876 if (gbl_resolv_flags.concurrent_dns &&
877 name_resolve_concurrency > 0 &&
878 async_dns_initialized) {
879 add_async_dns_ipv4(AF_INET, addr);
880 /* XXX found is set to TRUE, which seems a bit odd, but I'm not
881 * going to risk changing the semantics.
883 fill_dummy_ip4(addr, tp);
886 #endif /* ASYNC_DNS */
888 /* unknown host or DNS timeout */
894 fill_dummy_ip4(addr, tp);
899 /* --------------- */
901 new_ipv6(const struct e_in6_addr *addr)
903 hashipv6_t *tp = g_new(hashipv6_t,1);
906 ip6_to_str_buf(addr, tp->ip6);
910 /* ------------------------------------ */
912 host_lookup6(const struct e_in6_addr *addr, gboolean *found)
914 hashipv6_t * volatile tp;
917 async_dns_queue_msg_t *caqm;
918 #endif /* HAVE_C_ARES */
923 tp = (hashipv6_t *)g_hash_table_lookup(ipv6_hash_table, addr);
925 struct e_in6_addr *addr_key;
927 addr_key = g_new(struct e_in6_addr,1);
929 memcpy(addr_key, addr, 16);
930 g_hash_table_insert(ipv6_hash_table, addr_key, tp);
932 if ((tp->flags & DUMMY_AND_RESOLVE_FLGS) == DUMMY_ADDRESS_ENTRY){
935 if ((tp->flags & DUMMY_ADDRESS_ENTRY) == DUMMY_ADDRESS_ENTRY){
942 if (gbl_resolv_flags.network_name &&
943 gbl_resolv_flags.use_external_net_name_resolver) {
944 tp->flags = tp->flags|TRIED_RESOLVE_ADDRESS;
948 if ((gbl_resolv_flags.concurrent_dns) &&
949 name_resolve_concurrency > 0 &&
950 async_dns_initialized) {
951 caqm = g_new(async_dns_queue_msg_t,1);
952 caqm->family = AF_INET6;
953 memcpy(&caqm->addr.ip6, addr, sizeof(caqm->addr.ip6));
954 async_dns_queue_head = g_list_append(async_dns_queue_head, (gpointer) caqm);
956 /* XXX found is set to TRUE, which seems a bit odd, but I'm not
957 * going to risk changing the semantics.
959 if ((tp->flags & DUMMY_ADDRESS_ENTRY) == 0){
960 g_strlcpy(tp->name, tp->ip6, MAXNAMELEN);
961 ip6_to_str_buf(addr, tp->name);
962 tp->flags = tp->flags | DUMMY_ADDRESS_ENTRY;
966 #endif /* HAVE_C_ARES */
971 /* unknown host or DNS timeout */
972 if ((tp->flags & DUMMY_ADDRESS_ENTRY) == 0) {
973 tp->flags = tp->flags | DUMMY_ADDRESS_ENTRY;
974 g_strlcpy(tp->name, tp->ip6, MAXNAMELEN);
982 solve_address_to_name(const address *addr)
984 switch (addr->type) {
987 return get_ether_name((const guint8 *)addr->data);
991 memcpy(&ip4_addr, addr->data, sizeof ip4_addr);
992 return get_hostname(ip4_addr);
996 struct e_in6_addr ip6_addr;
997 memcpy(&ip6_addr.bytes, addr->data, sizeof ip6_addr.bytes);
998 return get_hostname6(&ip6_addr);
1002 return (const gchar *)addr->data;
1010 * Ethernet / manufacturer resolution
1012 * The following functions implement ethernet address resolution and
1013 * ethers files parsing (see ethers(4)).
1015 * The manuf file has the same format as ethers(4) except that names are
1016 * truncated to MAXMANUFLEN-1 (8) characters and that an address contains
1017 * only 3 bytes (instead of 6).
1021 * I decide to not use the existing functions (see ethers(3) on some
1022 * operating systems) for the following reasons:
1023 * - performance gains (use of hash tables and some other enhancements),
1024 * - use of two ethers files (system-wide and per user),
1025 * - avoid the use of NIS maps,
1026 * - lack of these functions on some systems.
1028 * So the following functions do _not_ behave as the standard ones.
1035 * If "manuf_file" is FALSE, parse a 6-byte MAC address.
1036 * If "manuf_file" is TRUE, parse an up-to-6-byte sequence with an optional
1040 parse_ether_address(const char *cp, ether_t *eth, unsigned int *mask,
1041 const gboolean manuf_file)
1048 for (i = 0; i < 6; i++) {
1049 /* Get a hex number, 1 or 2 digits, no sign characters allowed. */
1050 if (!isxdigit((unsigned char)*cp))
1052 num = strtoul(cp, &p, 16);
1054 return FALSE; /* failed */
1056 return FALSE; /* not a valid octet */
1057 eth->addr[i] = (guint8) num;
1058 cp = p; /* skip past the number */
1060 /* OK, what character terminated the octet? */
1062 /* "/" - this has a mask. */
1064 /* Entries with masks are allowed only in the "manuf" files. */
1067 cp++; /* skip past the '/' to get to the mask */
1068 if (!isdigit((unsigned char)*cp))
1069 return FALSE; /* no sign allowed */
1070 num = strtoul(cp, &p, 10);
1072 return FALSE; /* failed */
1073 cp = p; /* skip past the number */
1074 if (*cp != '\0' && !isspace((unsigned char)*cp))
1075 return FALSE; /* bogus terminator */
1076 if (num == 0 || num >= 48)
1077 return FALSE; /* bogus mask */
1078 /* Mask out the bits not covered by the mask */
1080 for (i = 0; num >= 8; i++, num -= 8)
1081 ; /* skip octets entirely covered by the mask */
1082 /* Mask out the first masked octet */
1083 eth->addr[i] &= (0xFF << (8 - num));
1085 /* Mask out completely-masked-out octets */
1091 /* We're at the end of the address, and there's no mask. */
1093 /* We got 3 bytes, so this is a manufacturer ID. */
1095 /* Manufacturer IDs are only allowed in the "manuf"
1099 /* Indicate that this is a manufacturer ID (0 is not allowed
1106 /* We got 6 bytes, so this is a MAC address.
1107 If we're reading one of the "manuf" files, indicate that
1108 this is a MAC address (48 is not allowed as a mask). */
1114 /* We didn't get 3 or 6 bytes, and there's no mask; this is
1119 /* We don't know the separator used in this number; it can either
1120 be ':', '-', or '.'. */
1121 if (*cp != ':' && *cp != '-' && *cp != '.')
1123 sep = *cp; /* subsequent separators must be the same */
1125 /* It has to be the same as the first separator */
1137 parse_ether_line(char *line, ether_t *eth, unsigned int *mask,
1138 const gboolean manuf_file)
1141 * See the ethers(4) or ethers(5) man page for ethers file format
1142 * (not available on all systems).
1143 * We allow both ethernet address separators (':' and '-'),
1144 * as well as Wireshark's '.' separator.
1149 if ((cp = strchr(line, '#')))
1152 if ((cp = strtok(line, " \t")) == NULL)
1155 if (!parse_ether_address(cp, eth, mask, manuf_file))
1158 if ((cp = strtok(NULL, " \t")) == NULL)
1161 g_strlcpy(eth->name, cp, MAXNAMELEN);
1165 } /* parse_ether_line */
1167 static FILE *eth_p = NULL;
1170 set_ethent(char *path)
1175 eth_p = ws_fopen(path, "r");
1188 get_ethent(unsigned int *mask, const gboolean manuf_file)
1192 static int size = 0;
1193 static char *buf = NULL;
1198 while (fgetline(&buf, &size, eth_p) >= 0) {
1199 if (parse_ether_line(buf, ð, mask, manuf_file) == 0) {
1210 get_ethbyname(const gchar *name)
1214 set_ethent(g_pethers_path);
1216 while (((eth = get_ethent(NULL, FALSE)) != NULL) && strncmp(name, eth->name, MAXNAMELEN) != 0)
1222 set_ethent(g_ethers_path);
1224 while (((eth = get_ethent(NULL, FALSE)) != NULL) && strncmp(name, eth->name, MAXNAMELEN) != 0)
1232 } /* get_ethbyname */
1236 get_ethbyaddr(const guint8 *addr)
1241 set_ethent(g_pethers_path);
1243 while (((eth = get_ethent(NULL, FALSE)) != NULL) && memcmp(addr, eth->addr, 6) != 0)
1249 set_ethent(g_ethers_path);
1251 while (((eth = get_ethent(NULL, FALSE)) != NULL) && memcmp(addr, eth->addr, 6) != 0)
1259 } /* get_ethbyaddr */
1263 add_manuf_name(const guint8 *addr, unsigned int mask, gchar *name)
1269 * XXX - can we use Standard Annotation Language annotations to
1270 * note that mask, as returned by parse_ethe)r_address() (and thus
1271 * by the routines that call it, and thus passed to us) cannot be > 48,
1272 * or is SAL too weak to express that?
1275 /* This is a well-known MAC address; just add this to the Ethernet
1277 add_eth_name(addr, name);
1282 /* This is a manufacturer ID; add it to the manufacturer ID hash table */
1284 /* manuf needs only the 3 most significant octets of the ethernet address */
1285 manuf_key = (int *)g_new(int, 1);
1286 *manuf_key = (int)((addr[2] << 16) + (addr[1] << 8) + addr[0]);
1288 g_hash_table_insert(manuf_hashtable, manuf_key, g_strdup(name));
1292 /* This is a range of well-known addresses; add it to the appropriate
1293 well-known-address table, creating that table if necessary. */
1295 wka_key = (guint8 *)g_malloc(6);
1296 memcpy(wka_key, addr, 6);
1298 g_hash_table_insert(wka_hashtable, wka_key, g_strdup(name));
1300 } /* add_manuf_name */
1303 manuf_name_lookup(const guint8 *addr)
1305 gint32 manuf_key = 0;
1309 /* manuf needs only the 3 most significant octets of the ethernet address */
1310 manuf_key = addr[0];
1311 manuf_key = manuf_key<<8;
1313 manuf_key = manuf_key | oct;
1314 manuf_key = manuf_key<<8;
1316 manuf_key = manuf_key | oct;
1319 /* first try to find a "perfect match" */
1320 name = (gchar *)g_hash_table_lookup(manuf_hashtable, &manuf_key);
1325 /* Mask out the broadcast/multicast flag but not the locally
1326 * administered flag as localy administered means: not assigend
1327 * by the IEEE but the local administrator instead.
1328 * 0x01 multicast / broadcast bit
1329 * 0x02 locally administered bit */
1330 if((manuf_key & 0x00010000) != 0){
1331 manuf_key &= 0x00FEFFFF;
1332 name = (gchar *)g_hash_table_lookup(manuf_hashtable, &manuf_key);
1340 } /* manuf_name_lookup */
1343 wka_name_lookup(const guint8 *addr, const unsigned int mask)
1345 guint8 masked_addr[6];
1350 if(wka_hashtable == NULL){
1353 /* Get the part of the address covered by the mask. */
1354 for (i = 0, num = mask; num >= 8; i++, num -= 8)
1355 masked_addr[i] = addr[i]; /* copy octets entirely covered by the mask */
1356 /* Mask out the first masked octet */
1357 masked_addr[i] = addr[i] & (0xFF << (8 - num));
1359 /* Zero out completely-masked-out octets */
1363 name = (gchar *)g_hash_table_lookup(wka_hashtable, masked_addr);
1367 } /* wka_name_lookup */
1370 eth_addr_hash(gconstpointer key)
1372 return wmem_strong_hash((const guint8 *)key, 6);
1376 eth_addr_cmp(gconstpointer a, gconstpointer b)
1378 return (memcmp(a, b, 6) == 0);
1382 initialize_ethers(void)
1388 /* hash table initialization */
1389 wka_hashtable = g_hash_table_new_full(eth_addr_hash, eth_addr_cmp, g_free, g_free);
1390 manuf_hashtable = g_hash_table_new_full(g_int_hash, g_int_equal, g_free, g_free);
1391 eth_hashtable = g_hash_table_new_full(eth_addr_hash, eth_addr_cmp, NULL, g_free);
1393 /* Compute the pathname of the ethers file. */
1394 if (g_ethers_path == NULL) {
1395 g_ethers_path = g_strdup_printf("%s" G_DIR_SEPARATOR_S "%s",
1396 get_systemfile_dir(), ENAME_ETHERS);
1399 /* Set g_pethers_path here, but don't actually do anything
1400 * with it. It's used in get_ethbyname() and get_ethbyaddr()
1402 if (g_pethers_path == NULL)
1403 g_pethers_path = get_persconffile_path(ENAME_ETHERS, FALSE);
1405 /* Compute the pathname of the manuf file */
1406 manuf_path = get_datafile_path(ENAME_MANUF);
1408 /* Read it and initialize the hash table */
1409 set_ethent(manuf_path);
1411 while ((eth = get_ethent(&mask, TRUE))) {
1412 add_manuf_name(eth->addr, mask, eth->name);
1419 } /* initialize_ethers */
1421 /* this is only needed when shuting down application (if at all) */
1423 eth_name_lookup_cleanup(void)
1426 if(manuf_hashtable) {
1427 g_hash_table_destroy(manuf_hashtable);
1428 manuf_hashtable = NULL;
1431 g_hash_table_destroy(wka_hashtable);
1432 wka_hashtable = NULL;
1436 g_hash_table_destroy(eth_hashtable);
1437 eth_hashtable = NULL;
1442 /* Resolve ethernet address */
1443 static hashether_t *
1444 eth_addr_resolve(hashether_t *tp) {
1446 const guint8 *addr = tp->addr;
1448 if ( (eth = get_ethbyaddr(addr)) != NULL) {
1449 g_strlcpy(tp->resolved_name, eth->name, MAXNAMELEN);
1450 tp->status = HASHETHER_STATUS_RESOLVED_NAME;
1456 /* Unknown name. Try looking for it in the well-known-address
1457 tables for well-known address ranges smaller than 2^24. */
1460 /* Only the topmost 5 bytes participate fully */
1461 if ((name = wka_name_lookup(addr, mask+40)) != NULL) {
1462 g_snprintf(tp->resolved_name, MAXNAMELEN, "%s_%02x",
1463 name, addr[5] & (0xFF >> mask));
1464 tp->status = HASHETHER_STATUS_RESOLVED_DUMMY;
1474 /* Only the topmost 4 bytes participate fully */
1475 if ((name = wka_name_lookup(addr, mask+32)) != NULL) {
1476 g_snprintf(tp->resolved_name, MAXNAMELEN, "%s_%02x:%02x",
1477 name, addr[4] & (0xFF >> mask), addr[5]);
1478 tp->status = HASHETHER_STATUS_RESOLVED_DUMMY;
1488 /* Only the topmost 3 bytes participate fully */
1489 if ((name = wka_name_lookup(addr, mask+24)) != NULL) {
1490 g_snprintf(tp->resolved_name, MAXNAMELEN, "%s_%02x:%02x:%02x",
1491 name, addr[3] & (0xFF >> mask), addr[4], addr[5]);
1492 tp->status = HASHETHER_STATUS_RESOLVED_DUMMY;
1500 /* Now try looking in the manufacturer table. */
1501 if ((name = manuf_name_lookup(addr)) != NULL) {
1502 g_snprintf(tp->resolved_name, MAXNAMELEN, "%s_%02x:%02x:%02x",
1503 name, addr[3], addr[4], addr[5]);
1504 tp->status = HASHETHER_STATUS_RESOLVED_DUMMY;
1508 /* Now try looking for it in the well-known-address
1509 tables for well-known address ranges larger than 2^24. */
1512 /* Only the topmost 2 bytes participate fully */
1513 if ((name = wka_name_lookup(addr, mask+16)) != NULL) {
1514 g_snprintf(tp->resolved_name, MAXNAMELEN, "%s_%02x:%02x:%02x:%02x",
1515 name, addr[2] & (0xFF >> mask), addr[3], addr[4],
1517 tp->status = HASHETHER_STATUS_RESOLVED_DUMMY;
1527 /* Only the topmost byte participates fully */
1528 if ((name = wka_name_lookup(addr, mask+8)) != NULL) {
1529 g_snprintf(tp->resolved_name, MAXNAMELEN, "%s_%02x:%02x:%02x:%02x:%02x",
1530 name, addr[1] & (0xFF >> mask), addr[2], addr[3],
1532 tp->status = HASHETHER_STATUS_RESOLVED_DUMMY;
1540 for (mask = 7; mask > 0; mask--) {
1541 /* Not even the topmost byte participates fully */
1542 if ((name = wka_name_lookup(addr, mask)) != NULL) {
1543 g_snprintf(tp->resolved_name, MAXNAMELEN, "%s_%02x:%02x:%02x:%02x:%02x:%02x",
1544 name, addr[0] & (0xFF >> mask), addr[1], addr[2],
1545 addr[3], addr[4], addr[5]);
1546 tp->status = HASHETHER_STATUS_RESOLVED_DUMMY;
1551 /* No match whatsoever. */
1552 g_snprintf(tp->resolved_name, MAXNAMELEN, "%s", ether_to_str(addr));
1553 tp->status = HASHETHER_STATUS_RESOLVED_DUMMY;
1556 g_assert_not_reached();
1557 } /* eth_addr_resolve */
1559 static hashether_t *
1560 eth_hash_new_entry(const guint8 *addr, const gboolean resolve)
1565 tp = g_new(hashether_t, 1);
1566 memcpy(tp->addr, addr, sizeof(tp->addr));
1567 tp->status = HASHETHER_STATUS_UNRESOLVED;
1568 /* Values returned by bytes_to_hexstr_punct() are *not* null-terminated */
1569 endp = bytes_to_hexstr_punct(tp->hexaddr, addr, sizeof(tp->addr), ':');
1571 tp->resolved_name[0] = '\0';
1574 eth_addr_resolve(tp);
1576 g_hash_table_insert(eth_hashtable, tp->addr, tp);
1579 } /* eth_hash_new_entry */
1581 static hashether_t *
1582 add_eth_name(const guint8 *addr, const gchar *name)
1586 tp = (hashether_t *)g_hash_table_lookup(eth_hashtable, addr);
1589 tp = eth_hash_new_entry(addr, FALSE);
1592 g_strlcpy(tp->resolved_name, name, MAXNAMELEN);
1593 tp->status = HASHETHER_STATUS_RESOLVED_NAME;
1594 new_resolved_objects = TRUE;
1597 } /* add_eth_name */
1599 static hashether_t *
1600 eth_name_lookup(const guint8 *addr, const gboolean resolve)
1604 tp = (hashether_t *)g_hash_table_lookup(eth_hashtable, addr);
1606 tp = eth_hash_new_entry(addr, resolve);
1608 if (resolve && (tp->status == HASHETHER_STATUS_UNRESOLVED)){
1609 eth_addr_resolve(tp); /* Found but needs to be resolved */
1615 } /* eth_name_lookup */
1618 eth_addr_lookup(const gchar *name _U_)
1621 /* XXX Do we need reverse lookup??? */
1624 hashether_t **table = eth_table;
1627 /* to be optimized (hash table from name to addr) */
1628 for (i = 0; i < HASHETHSIZE; i++) {
1631 if (strcmp(tp->resolved_name, name) == 0)
1637 /* not in hash table : performs a file lookup */
1639 if ((eth = get_ethbyname(name)) == NULL)
1642 /* add new entry in hash table */
1644 tp = add_eth_name(eth->addr, name);
1650 } /* eth_addr_lookup */
1655 parse_ipxnets_line(char *line, ipxnet_t *ipxnet)
1658 * We allow three address separators (':', '-', and '.'),
1659 * as well as no separators
1663 guint32 a, a0, a1, a2, a3;
1664 gboolean found_single_number = FALSE;
1666 if ((cp = strchr(line, '#')))
1669 if ((cp = strtok(line, " \t\n")) == NULL)
1672 /* Either fill a0,a1,a2,a3 and found_single_number is FALSE,
1673 * fill a and found_single_number is TRUE,
1676 if (sscanf(cp, "%x:%x:%x:%x", &a0, &a1, &a2, &a3) != 4) {
1677 if (sscanf(cp, "%x-%x-%x-%x", &a0, &a1, &a2, &a3) != 4) {
1678 if (sscanf(cp, "%x.%x.%x.%x", &a0, &a1, &a2, &a3) != 4) {
1679 if (sscanf(cp, "%x", &a) == 1) {
1680 found_single_number = TRUE;
1689 if ((cp = strtok(NULL, " \t\n")) == NULL)
1692 if (found_single_number) {
1696 ipxnet->addr = (a0 << 24) | (a1 << 16) | (a2 << 8) | a3;
1699 g_strlcpy(ipxnet->name, cp, MAXNAMELEN);
1703 } /* parse_ipxnets_line */
1705 static FILE *ipxnet_p = NULL;
1708 set_ipxnetent(char *path)
1713 ipxnet_p = ws_fopen(path, "r");
1729 static ipxnet_t ipxnet;
1730 static int size = 0;
1731 static char *buf = NULL;
1733 if (ipxnet_p == NULL)
1736 while (fgetline(&buf, &size, ipxnet_p) >= 0) {
1737 if (parse_ipxnets_line(buf, &ipxnet) == 0) {
1744 } /* get_ipxnetent */
1749 get_ipxnetbyname(const gchar *name)
1753 set_ipxnetent(g_ipxnets_path);
1755 while (((ipxnet = get_ipxnetent()) != NULL) && strncmp(name, ipxnet->name, MAXNAMELEN) != 0)
1758 if (ipxnet == NULL) {
1761 set_ipxnetent(g_pipxnets_path);
1763 while (((ipxnet = get_ipxnetent()) != NULL) && strncmp(name, ipxnet->name, MAXNAMELEN) != 0)
1771 } /* get_ipxnetbyname */
1775 get_ipxnetbyaddr(guint32 addr)
1779 set_ipxnetent(g_ipxnets_path);
1781 while (((ipxnet = get_ipxnetent()) != NULL) && (addr != ipxnet->addr) ) ;
1783 if (ipxnet == NULL) {
1786 set_ipxnetent(g_pipxnets_path);
1788 while (((ipxnet = get_ipxnetent()) != NULL) && (addr != ipxnet->addr) )
1796 } /* get_ipxnetbyaddr */
1799 initialize_ipxnets(void)
1801 /* Compute the pathname of the ipxnets file.
1803 * XXX - is there a notion of an "ipxnets file" in any flavor of
1804 * UNIX, or with any add-on Netware package for UNIX? If not,
1805 * should the UNIX version of the ipxnets file be in the datafile
1806 * directory as well?
1808 if (g_ipxnets_path == NULL) {
1809 g_ipxnets_path = g_strdup_printf("%s" G_DIR_SEPARATOR_S "%s",
1810 get_systemfile_dir(), ENAME_IPXNETS);
1813 /* Set g_pipxnets_path here, but don't actually do anything
1814 * with it. It's used in get_ipxnetbyname() and get_ipxnetbyaddr()
1816 if (g_pipxnets_path == NULL)
1817 g_pipxnets_path = get_persconffile_path(ENAME_IPXNETS, FALSE);
1819 } /* initialize_ipxnets */
1822 ipx_name_lookup_cleanup(void)
1824 if(ipxnet_hash_table){
1825 g_hash_table_destroy(ipxnet_hash_table);
1826 ipxnet_hash_table = NULL;
1832 static hashipxnet_t *
1833 add_ipxnet_name(guint addr, const gchar *name)
1837 tp = (hashipxnet_t *)g_hash_table_lookup(ipxnet_hash_table, &addr);
1839 g_strlcpy(tp->name, name, MAXNAMELEN);
1843 key = (int *)g_new(int, 1);
1845 tp = g_new(hashipxnet_t,1);
1846 g_strlcpy(tp->name, name, MAXNAMELEN);
1847 g_hash_table_insert(ipxnet_hash_table, key, tp);
1851 g_strlcpy(tp->name, name, MAXNAMELEN);
1853 new_resolved_objects = TRUE;
1857 } /* add_ipxnet_name */
1861 ipxnet_name_lookup(const guint addr)
1866 tp = (hashipxnet_t *)g_hash_table_lookup(ipxnet_hash_table, &addr);
1870 key = (int *)g_new(int, 1);
1872 tp = g_new(hashipxnet_t, 1);
1873 g_hash_table_insert(ipxnet_hash_table, key, tp);
1878 /* fill in a new entry */
1882 if ( (ipxnet = get_ipxnetbyaddr(addr)) == NULL) {
1884 g_snprintf(tp->name, MAXNAMELEN, "%X", addr);
1887 g_strlcpy(tp->name, ipxnet->name, MAXNAMELEN);
1892 } /* ipxnet_name_lookup */
1895 ipxnet_addr_lookup(const gchar *name _U_, gboolean *success)
1900 /* XXX Do we need reverse lookup??? */
1903 hashipxnet_t **table = ipxnet_table;
1906 /* to be optimized (hash table from name to addr) */
1907 for (i = 0; i < HASHIPXNETSIZE; i++) {
1910 if (strcmp(tp->name, name) == 0) {
1918 /* not in hash table : performs a file lookup */
1920 if ((ipxnet = get_ipxnetbyname(name)) == NULL) {
1925 /* add new entry in hash table */
1927 tp = add_ipxnet_name(ipxnet->addr, name);
1932 } /* ipxnet_addr_lookup */
1935 read_hosts_file (const char *hostspath)
1941 guint32 host_addr[4]; /* IPv4 or IPv6 */
1942 struct e_in6_addr ip6_addr;
1947 * See the hosts(4) or hosts(5) man page for hosts file format
1948 * (not available on all systems).
1950 if ((hf = ws_fopen(hostspath, "r")) == NULL)
1953 while (fgetline(&line, &size, hf) >= 0) {
1954 if ((cp = strchr(line, '#')))
1957 if ((cp = strtok(line, " \t")) == NULL)
1958 continue; /* no tokens in the line */
1960 ret = inet_pton(AF_INET6, cp, &host_addr);
1962 continue; /* error parsing */
1967 /* Not valid IPv6 - valid IPv4? */
1968 if (!str_to_ip(cp, &host_addr))
1973 if ((cp = strtok(NULL, " \t")) == NULL)
1974 continue; /* no host name */
1977 memcpy(&ip6_addr, host_addr, sizeof ip6_addr);
1978 add_ipv6_name(&ip6_addr, cp);
1980 add_ipv4_name(host_addr[0], cp);
1983 * Add the aliases, too, if there are any.
1984 * XXX - host_lookup() only returns the first entry.
1986 while ((cp = strtok(NULL, " \t")) != NULL) {
1988 memcpy(&ip6_addr, host_addr, sizeof ip6_addr);
1989 add_ipv6_name(&ip6_addr, cp);
1991 add_ipv4_name(host_addr[0], cp);
1998 } /* read_hosts_file */
2001 add_hosts_file (const char *hosts_file)
2003 gboolean found = FALSE;
2009 if (!extra_hosts_files)
2010 extra_hosts_files = g_ptr_array_new();
2012 for (i = 0; i < extra_hosts_files->len; i++) {
2013 if (strcmp(hosts_file, (const char *) g_ptr_array_index(extra_hosts_files, i)) == 0)
2018 g_ptr_array_add(extra_hosts_files, g_strdup(hosts_file));
2019 return read_hosts_file (hosts_file);
2025 add_ip_name_from_string (const char *addr, const char *name)
2027 guint32 host_addr[4]; /* IPv4 */
2028 struct e_in6_addr ip6_addr; /* IPv6 */
2031 resolved_ipv4_t *resolved_ipv4_entry;
2032 resolved_ipv6_t *resolved_ipv6_entry;
2034 ret = inet_pton(AF_INET6, addr, &ip6_addr);
2036 /* Error parsing address */
2043 /* Not valid IPv6 - valid IPv4? */
2044 if (!str_to_ip(addr, &host_addr))
2045 return FALSE; /* no */
2050 resolved_ipv6_entry = g_new(resolved_ipv6_t, 1);
2051 memcpy(&(resolved_ipv6_entry->ip6_addr), &ip6_addr, 16);
2052 g_strlcpy(resolved_ipv6_entry->name, name, MAXNAMELEN);
2053 manually_resolved_ipv6_list = g_slist_prepend(manually_resolved_ipv6_list, resolved_ipv6_entry);
2055 resolved_ipv4_entry = g_new(resolved_ipv4_t, 1);
2056 resolved_ipv4_entry->host_addr = host_addr[0];
2057 g_strlcpy(resolved_ipv4_entry->name, name, MAXNAMELEN);
2058 manually_resolved_ipv4_list = g_slist_prepend(manually_resolved_ipv4_list, resolved_ipv4_entry);
2062 } /* add_ip_name_from_string */
2065 * Add the resolved addresses that are in use to the list used to create the NRB
2068 ipv4_hash_table_resolved_to_list(gpointer key _U_, gpointer value, gpointer user_data)
2070 addrinfo_lists_t *lists = (addrinfo_lists_t*)user_data;
2071 hashipv4_t *ipv4_hash_table_entry = (hashipv4_t *)value;
2073 if((ipv4_hash_table_entry->flags & USED_AND_RESOLVED_MASK) == RESOLVED_ADDRESS_USED){
2074 lists->ipv4_addr_list = g_list_prepend (lists->ipv4_addr_list, ipv4_hash_table_entry);
2080 * Add the resolved addresses that are in use to the list used to create the NRB
2084 ipv6_hash_table_resolved_to_list(gpointer key _U_, gpointer value, gpointer user_data)
2086 addrinfo_lists_t *lists = (addrinfo_lists_t*)user_data;
2087 hashipv6_t *ipv6_hash_table_entry = (hashipv6_t *)value;
2089 if((ipv6_hash_table_entry->flags & USED_AND_RESOLVED_MASK) == RESOLVED_ADDRESS_USED){
2090 lists->ipv6_addr_list = g_list_prepend (lists->ipv6_addr_list, ipv6_hash_table_entry);
2096 get_addrinfo_list(void) {
2098 if(ipv4_hash_table){
2099 g_hash_table_foreach(ipv4_hash_table, ipv4_hash_table_resolved_to_list, &addrinfo_lists);
2102 if(ipv6_hash_table){
2103 g_hash_table_foreach(ipv6_hash_table, ipv6_hash_table_resolved_to_list, &addrinfo_lists);
2106 return &addrinfo_lists;
2109 /* Read in a list of subnet definition - name pairs.
2110 * <line> = <comment> | <entry> | <whitespace>
2111 * <comment> = <whitespace>#<any>
2112 * <entry> = <subnet_definition> <whitespace> <subnet_name> [<comment>|<whitespace><any>]
2113 * <subnet_definition> = <ipv4_address> / <subnet_mask_length>
2114 * <ipv4_address> is a full address; it will be masked to get the subnet-ID.
2115 * <subnet_mask_length> is a decimal 1-31
2116 * <subnet_name> is a string containing no whitespace.
2117 * <whitespace> = (space | tab)+
2118 * Any malformed entries are ignored.
2119 * Any trailing data after the subnet_name is ignored.
2124 read_subnets_file (const char *subnetspath)
2130 guint32 host_addr; /* IPv4 ONLY */
2133 if ((hf = ws_fopen(subnetspath, "r")) == NULL)
2136 while (fgetline(&line, &size, hf) >= 0) {
2137 if ((cp = strchr(line, '#')))
2140 if ((cp = strtok(line, " \t")) == NULL)
2141 continue; /* no tokens in the line */
2144 /* Expected format is <IP4 address>/<subnet length> */
2145 cp2 = strchr(cp, '/');
2150 *cp2 = '\0'; /* Cut token */
2153 /* Check if this is a valid IPv4 address */
2154 if (!str_to_ip(cp, &host_addr)) {
2158 mask_length = atoi(cp2);
2159 if(0 >= mask_length || mask_length > 31) {
2160 continue; /* invalid mask length */
2163 if ((cp = strtok(NULL, " \t")) == NULL)
2164 continue; /* no subnet name */
2166 subnet_entry_set(host_addr, (guint32)mask_length, cp);
2172 } /* read_subnets_file */
2174 static subnet_entry_t
2175 subnet_lookup(const guint32 addr)
2177 subnet_entry_t subnet_entry;
2180 /* Search mask lengths linearly, longest first */
2182 i = SUBNETLENGTHSIZE;
2183 while(have_subnet_entry && i > 0) {
2184 guint32 masked_addr;
2185 subnet_length_entry_t* length_entry;
2187 /* Note that we run from 31 (length 32) to 0 (length 1) */
2189 g_assert(i < SUBNETLENGTHSIZE);
2192 length_entry = &subnet_length_entries[i];
2194 if(NULL != length_entry->subnet_addresses) {
2195 sub_net_hashipv4_t * tp;
2198 masked_addr = addr & length_entry->mask;
2199 hash_idx = HASH_IPV4_ADDRESS(masked_addr);
2201 tp = length_entry->subnet_addresses[hash_idx];
2202 while(tp != NULL && tp->addr != masked_addr) {
2207 subnet_entry.mask = length_entry->mask;
2208 subnet_entry.mask_length = i + 1; /* Length is offset + 1 */
2209 subnet_entry.name = tp->name;
2210 return subnet_entry;
2215 subnet_entry.mask = 0;
2216 subnet_entry.mask_length = 0;
2217 subnet_entry.name = NULL;
2219 return subnet_entry;
2222 /* Add a subnet-definition - name pair to the set.
2223 * The definition is taken by masking the address passed in with the mask of the
2227 subnet_entry_set(guint32 subnet_addr, const guint32 mask_length, const gchar* name)
2229 subnet_length_entry_t* entry;
2230 sub_net_hashipv4_t * tp;
2233 g_assert(mask_length > 0 && mask_length <= 32);
2235 entry = &subnet_length_entries[mask_length - 1];
2237 subnet_addr &= entry->mask;
2239 hash_idx = HASH_IPV4_ADDRESS(subnet_addr);
2241 if(NULL == entry->subnet_addresses) {
2242 entry->subnet_addresses = (sub_net_hashipv4_t**) se_alloc0(sizeof(sub_net_hashipv4_t*) * HASHHOSTSIZE);
2245 if(NULL != (tp = entry->subnet_addresses[hash_idx])) {
2246 if(tp->addr == subnet_addr) {
2247 return; /* XXX provide warning that an address was repeated? */
2249 sub_net_hashipv4_t * new_tp = se_new(sub_net_hashipv4_t);
2254 tp = entry->subnet_addresses[hash_idx] = se_new(sub_net_hashipv4_t);
2258 tp->addr = subnet_addr;
2259 /* Clear DUMMY_ADDRESS_ENTRY */
2260 tp->flags = tp->flags & 0xfe; /*Never used again...*/
2261 g_strlcpy(tp->name, name, MAXNAMELEN); /* This is longer than subnet names can actually be */
2262 have_subnet_entry = TRUE;
2266 subnet_name_lookup_init(void)
2271 for(i = 0; i < SUBNETLENGTHSIZE; ++i) {
2272 guint32 length = i + 1;
2274 subnet_length_entries[i].subnet_addresses = NULL;
2275 subnet_length_entries[i].mask_length = length;
2276 subnet_length_entries[i].mask = g_htonl(ip_get_subnet_mask(length));
2279 subnetspath = get_persconffile_path(ENAME_SUBNETS, FALSE);
2280 if (!read_subnets_file(subnetspath) && errno != ENOENT) {
2281 report_open_failure(subnetspath, errno, FALSE);
2283 g_free(subnetspath);
2286 * Load the global subnets file, if we have one.
2288 subnetspath = get_datafile_path(ENAME_SUBNETS);
2289 if (!read_subnets_file(subnetspath) && errno != ENOENT) {
2290 report_open_failure(subnetspath, errno, FALSE);
2292 g_free(subnetspath);
2297 * External Functions
2301 addr_resolve_pref_init(module_t *nameres)
2303 prefs_register_bool_preference(nameres, "mac_name",
2304 "Resolve MAC addresses",
2305 "Resolve Ethernet MAC address to manufacturer names",
2306 &gbl_resolv_flags.mac_name);
2308 prefs_register_bool_preference(nameres, "transport_name",
2309 "Resolve transport names",
2310 "Resolve TCP/UDP ports into service names",
2311 &gbl_resolv_flags.transport_name);
2313 prefs_register_bool_preference(nameres, "network_name",
2314 "Resolve network (IP) addresses",
2315 "Resolve IPv4, IPv6, and IPX addresses into host names."
2316 " The next set of check boxes determines how name resolution should be performed."
2317 " If no other options are checked name resolution is made from Wireshark's host file,"
2318 " capture file name resolution blocks and DNS packets in the capture.",
2319 &gbl_resolv_flags.network_name);
2321 prefs_register_bool_preference(nameres, "use_external_name_resolver",
2322 "Use an external network name resolver",
2323 "Use your system's configured name resolver"
2324 " (usually DNS) to resolve network names."
2325 " Only applies when network name resolution"
2327 &gbl_resolv_flags.use_external_net_name_resolver);
2329 #if defined(HAVE_C_ARES) || defined(HAVE_GNU_ADNS)
2330 prefs_register_bool_preference(nameres, "concurrent_dns",
2331 "Enable concurrent DNS name resolution",
2332 "Enable concurrent DNS name resolution. Only"
2333 " applies when network name resolution is"
2334 " enabled. You probably want to enable this.",
2335 &gbl_resolv_flags.concurrent_dns);
2337 prefs_register_uint_preference(nameres, "name_resolve_concurrency",
2338 "Maximum concurrent requests",
2339 "The maximum number of DNS requests that may"
2340 " be active at any time. A large value (many"
2341 " thousands) might overload the network or make"
2342 " your DNS server behave badly.",
2344 &name_resolve_concurrency);
2346 prefs_register_static_text_preference(nameres, "concurrent_dns",
2347 "Enable concurrent DNS name resolution: N/A",
2348 "Support for concurrent DNS name resolution was not"
2349 " compiled into this version of Wireshark");
2352 prefs_register_bool_preference(nameres, "hosts_file_handling",
2353 "Only use the profile \"hosts\" file",
2354 "By default \"hosts\" files will be loaded from multiple sources."
2355 " Checking this box only loads the \"hosts\" in the current profile.",
2356 &gbl_resolv_flags.load_hosts_file_from_profile_only);
2362 host_name_lookup_process(void) {
2363 async_dns_queue_msg_t *caqm;
2364 struct timeval tv = { 0, 0 };
2367 gboolean nro = new_resolved_objects;
2369 new_resolved_objects = FALSE;
2371 if (!async_dns_initialized)
2372 /* c-ares not initialized. Bail out and cancel timers. */
2375 async_dns_queue_head = g_list_first(async_dns_queue_head);
2377 while (async_dns_queue_head != NULL && async_dns_in_flight <= name_resolve_concurrency) {
2378 caqm = (async_dns_queue_msg_t *) async_dns_queue_head->data;
2379 async_dns_queue_head = g_list_remove(async_dns_queue_head, (void *) caqm);
2380 if (caqm->family == AF_INET) {
2381 ares_gethostbyaddr(ghba_chan, &caqm->addr.ip4, sizeof(guint32), AF_INET,
2382 c_ares_ghba_cb, caqm);
2383 async_dns_in_flight++;
2384 } else if (caqm->family == AF_INET6) {
2385 ares_gethostbyaddr(ghba_chan, &caqm->addr.ip6, sizeof(struct e_in6_addr),
2386 AF_INET6, c_ares_ghba_cb, caqm);
2387 async_dns_in_flight++;
2393 nfds = ares_fds(ghba_chan, &rfds, &wfds);
2395 if (select(nfds, &rfds, &wfds, NULL, &tv) == -1) { /* call to select() failed */
2396 fprintf(stderr, "Warning: call to select() failed, error is %s\n", strerror(errno));
2399 ares_process(ghba_chan, &rfds, &wfds);
2402 /* Any new entries? */
2407 _host_name_lookup_cleanup(void) {
2410 cur = g_list_first(async_dns_queue_head);
2413 cur = g_list_next (cur);
2416 g_list_free(async_dns_queue_head);
2417 async_dns_queue_head = NULL;
2419 if (async_dns_initialized) {
2420 ares_destroy(ghba_chan);
2421 ares_destroy(ghbn_chan);
2423 #ifdef CARES_HAVE_ARES_LIBRARY_INIT
2424 ares_library_cleanup();
2426 async_dns_initialized = FALSE;
2429 #elif defined(HAVE_GNU_ADNS)
2431 /* XXX - The ADNS "documentation" isn't very clear:
2432 * - Do we need to keep our query structures around?
2435 host_name_lookup_process(void) {
2436 async_dns_queue_msg_t *almsg;
2438 char addr_str[] = "111.222.333.444.in-addr.arpa.";
2443 gboolean nro = new_resolved_objects;
2445 new_resolved_objects = FALSE;
2446 async_dns_queue_head = g_list_first(async_dns_queue_head);
2448 cur = async_dns_queue_head;
2449 while (cur && async_dns_in_flight <= name_resolve_concurrency) {
2450 almsg = (async_dns_queue_msg_t *) cur->data;
2451 if (! almsg->submitted && almsg->type == AF_INET) {
2452 addr_bytes = (guint8 *) &almsg->ip4_addr;
2453 g_snprintf(addr_str, sizeof addr_str, "%u.%u.%u.%u.in-addr.arpa.", addr_bytes[3],
2454 addr_bytes[2], addr_bytes[1], addr_bytes[0]);
2455 /* XXX - what if it fails? */
2456 adns_submit (ads, addr_str, adns_r_ptr, adns_qf_none, NULL, &almsg->query);
2457 almsg->submitted = TRUE;
2458 async_dns_in_flight++;
2463 cur = async_dns_queue_head;
2466 almsg = (async_dns_queue_msg_t *) cur->data;
2467 if (almsg->submitted) {
2468 ret = adns_check(ads, &almsg->query, &ans, NULL);
2470 if (ans->status == adns_s_ok) {
2471 add_ipv4_name(almsg->ip4_addr, *ans->rrs.str);
2478 async_dns_queue_head = g_list_remove(async_dns_queue_head, (void *) almsg);
2480 /* XXX, what to do if async_dns_in_flight == 0? */
2481 async_dns_in_flight--;
2485 /* Keep the timeout in place */
2490 _host_name_lookup_cleanup(void) {
2493 async_dns_queue_head = g_list_first(async_dns_queue_head);
2494 while (async_dns_queue_head) {
2495 qdata = async_dns_queue_head->data;
2496 async_dns_queue_head = g_list_remove(async_dns_queue_head, qdata);
2500 if (async_dns_initialized)
2502 async_dns_initialized = FALSE;
2505 #else /* HAVE_GNU_ADNS */
2508 host_name_lookup_process(void) {
2509 gboolean nro = new_resolved_objects;
2511 new_resolved_objects = FALSE;
2517 _host_name_lookup_cleanup(void) {
2520 #endif /* HAVE_C_ARES */
2523 get_hostname(const guint addr)
2527 /* XXX why do we call this if we're not resolving? To create hash entries?
2530 hashipv4_t *tp = host_lookup(addr, &found);
2532 if (!gbl_resolv_flags.network_name)
2535 tp->flags = tp->flags | RESOLVED_ADDRESS_USED;
2540 /* -------------------------- */
2543 get_hostname6(const struct e_in6_addr *addr)
2547 /* XXX why do we call this if we're not resolving? To create hash entries?
2550 hashipv6_t *tp = host_lookup6(addr, &found);
2552 if (!gbl_resolv_flags.network_name)
2555 tp->flags = tp->flags | RESOLVED_ADDRESS_USED;
2560 /* -------------------------- */
2562 add_ipv4_name(const guint addr, const gchar *name)
2567 * Don't add zero-length names; apparently, some resolvers will return
2568 * them if they get them from DNS.
2570 if (name[0] == '\0')
2574 tp = (hashipv4_t *)g_hash_table_lookup(ipv4_hash_table, GUINT_TO_POINTER(addr));
2576 g_strlcpy(tp->name, name, MAXNAMELEN);
2578 tp = new_ipv4(addr);
2579 g_strlcpy(tp->name, name, MAXNAMELEN);
2580 g_hash_table_insert(ipv4_hash_table, GUINT_TO_POINTER(addr), tp);
2583 g_strlcpy(tp->name, name, MAXNAMELEN);
2584 tp->flags = tp->flags | TRIED_RESOLVE_ADDRESS;
2585 new_resolved_objects = TRUE;
2587 } /* add_ipv4_name */
2589 /* -------------------------- */
2591 add_ipv6_name(const struct e_in6_addr *addrp, const gchar *name)
2596 * Don't add zero-length names; apparently, some resolvers will return
2597 * them if they get them from DNS.
2599 if (name[0] == '\0')
2602 tp = (hashipv6_t *)g_hash_table_lookup(ipv6_hash_table, addrp);
2604 g_strlcpy(tp->name, name, MAXNAMELEN);
2606 struct e_in6_addr *addr_key;
2608 addr_key = g_new(struct e_in6_addr,1);
2609 tp = new_ipv6(addrp);
2610 memcpy(addr_key, addrp, 16);
2611 g_strlcpy(tp->name, name, MAXNAMELEN);
2612 g_hash_table_insert(ipv6_hash_table, addr_key, tp);
2615 g_strlcpy(tp->name, name, MAXNAMELEN);
2616 tp->flags = tp->flags | TRIED_RESOLVE_ADDRESS;
2617 new_resolved_objects = TRUE;
2619 } /* add_ipv6_name */
2622 add_manually_resolved_ipv4(gpointer data, gpointer user_data _U_)
2624 resolved_ipv4_t *resolved_ipv4_entry = (resolved_ipv4_t *)data;
2626 add_ipv4_name(resolved_ipv4_entry->host_addr, resolved_ipv4_entry->name);
2630 add_manually_resolved_ipv6(gpointer data, gpointer user_data _U_)
2632 resolved_ipv6_t *resolved_ipv6_entry = (resolved_ipv6_t *)data;
2634 add_ipv6_name(&(resolved_ipv6_entry->ip6_addr), resolved_ipv6_entry->name);
2638 add_manually_resolved(void)
2640 if(manually_resolved_ipv4_list){
2641 g_slist_foreach(manually_resolved_ipv4_list, add_manually_resolved_ipv4, NULL);
2644 if(manually_resolved_ipv6_list){
2645 g_slist_foreach(manually_resolved_ipv6_list, add_manually_resolved_ipv6, NULL);
2650 host_name_lookup_init(void)
2655 #ifdef HAVE_GNU_ADNS
2658 static char rootpath_nt[] = "\\system32\\drivers\\etc\\hosts";
2659 static char rootpath_ot[] = "\\hosts";
2661 #endif /*GNU_ADNS */
2663 g_assert(ipxnet_hash_table == NULL);
2664 ipxnet_hash_table = g_hash_table_new_full(g_int_hash, g_int_equal, g_free, g_free);
2666 g_assert(ipv4_hash_table == NULL);
2667 ipv4_hash_table = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, g_free);
2669 g_assert(ipv6_hash_table == NULL);
2670 ipv6_hash_table = g_hash_table_new_full(ipv6_oat_hash, ipv6_equal, g_free, g_free);
2673 * Load the global hosts file, if we have one.
2675 if(!gbl_resolv_flags.load_hosts_file_from_profile_only){
2676 hostspath = get_datafile_path(ENAME_HOSTS);
2677 if (!read_hosts_file(hostspath) && errno != ENOENT) {
2678 report_open_failure(hostspath, errno, FALSE);
2683 * Load the user's hosts file no matter what, if they have one.
2685 hostspath = get_persconffile_path(ENAME_HOSTS, TRUE);
2686 if (!read_hosts_file(hostspath) && errno != ENOENT) {
2687 report_open_failure(hostspath, errno, FALSE);
2691 #ifdef CARES_HAVE_ARES_LIBRARY_INIT
2692 if (ares_library_init(ARES_LIB_INIT_ALL) == ARES_SUCCESS) {
2694 if (ares_init(&ghba_chan) == ARES_SUCCESS && ares_init(&ghbn_chan) == ARES_SUCCESS) {
2695 async_dns_initialized = TRUE;
2697 #ifdef CARES_HAVE_ARES_LIBRARY_INIT
2701 #ifdef HAVE_GNU_ADNS
2703 * We're using GNU ADNS, which doesn't check the system hosts file;
2704 * we load that file ourselves.
2708 sysroot = getenv_utf8("WINDIR");
2709 if (sysroot != NULL) {
2711 * The file should be under WINDIR.
2712 * If this is Windows NT (NT 4.0,2K,XP,Server2K3), it's in
2713 * %WINDIR%\system32\drivers\etc\hosts.
2714 * If this is Windows OT (95,98,Me), it's in %WINDIR%\hosts.
2716 * XXX - should we base it on the dwPlatformId value from
2719 if(!gbl_resolv_flags.load_hosts_file_from_profile_only){
2720 hostspath = g_strconcat(sysroot, rootpath_nt, NULL);
2721 if (!read_hosts_file(hostspath)) {
2723 hostspath = g_strconcat(sysroot, rootpath_ot, NULL);
2724 read_hosts_file(hostspath);
2730 if(!gbl_resolv_flags.load_hosts_file_from_profile_only){
2731 read_hosts_file("/etc/hosts");
2735 /* XXX - Any flags we should be using? */
2736 /* XXX - We could provide config settings for DNS servers, and
2737 pass them to ADNS with adns_init_strcfg */
2738 if (adns_init(&ads, adns_if_none, 0 /*0=>stderr*/) != 0) {
2740 * XXX - should we report the error? I'm assuming that some crashes
2741 * reported on a Windows machine with TCP/IP not configured are due
2742 * to "adns_init()" failing (due to the lack of TCP/IP) and leaving
2743 * ADNS in a state where it crashes due to that. We'll still try
2744 * doing name resolution anyway.
2748 async_dns_initialized = TRUE;
2749 async_dns_in_flight = 0;
2750 #endif /* HAVE_GNU_ADNS */
2751 #endif /* HAVE_C_ARES */
2753 if(extra_hosts_files && !gbl_resolv_flags.load_hosts_file_from_profile_only){
2754 for (i = 0; i < extra_hosts_files->len; i++) {
2755 read_hosts_file((const char *) g_ptr_array_index(extra_hosts_files, i));
2759 subnet_name_lookup_init();
2761 add_manually_resolved();
2765 host_name_lookup_cleanup(void)
2767 _host_name_lookup_cleanup();
2769 if(ipxnet_hash_table){
2770 g_hash_table_destroy(ipxnet_hash_table);
2771 ipxnet_hash_table = NULL;
2774 if(ipv4_hash_table){
2775 g_hash_table_destroy(ipv4_hash_table);
2776 ipv4_hash_table = NULL;
2779 if(ipv6_hash_table){
2780 g_hash_table_destroy(ipv6_hash_table);
2781 ipv6_hash_table = NULL;
2784 memset(subnet_length_entries, 0, sizeof(subnet_length_entries));
2786 have_subnet_entry = FALSE;
2787 new_resolved_objects = FALSE;
2791 free_manually_resolved_ipv4(gpointer data, gpointer user_data _U_)
2793 resolved_ipv4_t *resolved_ipv4_entry = (resolved_ipv4_t *)data;
2795 g_free(resolved_ipv4_entry);
2799 free_manually_resolved_ipv6(gpointer data, gpointer user_data _U_)
2801 resolved_ipv6_t *resolved_ipv6_entry = (resolved_ipv6_t *)data;
2803 g_free(resolved_ipv6_entry);
2807 manually_resolve_cleanup(void)
2809 if(manually_resolved_ipv4_list){
2810 g_slist_foreach(manually_resolved_ipv4_list, free_manually_resolved_ipv4, NULL);
2811 g_slist_free(manually_resolved_ipv4_list);
2812 manually_resolved_ipv4_list = NULL;
2815 if(manually_resolved_ipv6_list){
2816 g_slist_foreach(manually_resolved_ipv6_list, free_manually_resolved_ipv6, NULL);
2817 g_slist_free(manually_resolved_ipv6_list);
2818 manually_resolved_ipv6_list = NULL;
2824 ep_udp_port_to_display(guint port)
2827 if (!gbl_resolv_flags.transport_name) {
2828 return ep_utoa(port);
2831 return serv_name_lookup(port, PT_UDP);
2833 } /* ep_udp_port_to_display */
2836 ep_dccp_port_to_display(guint port)
2839 if (!gbl_resolv_flags.transport_name) {
2840 return ep_utoa(port);
2843 return serv_name_lookup(port, PT_DCCP);
2845 } /* ep_dccp_port_to_display */
2848 ep_tcp_port_to_display(guint port)
2851 if (!gbl_resolv_flags.transport_name) {
2852 return ep_utoa(port);
2855 return serv_name_lookup(port, PT_TCP);
2857 } /* ep_tcp_port_to_display */
2860 ep_sctp_port_to_display(guint port)
2863 if (!gbl_resolv_flags.transport_name) {
2864 return ep_utoa(port);
2867 return serv_name_lookup(port, PT_SCTP);
2869 } /* ep_sctp_port_to_display */
2872 ep_address_to_display(const address *addr)
2874 const gchar *result;
2876 result = solve_address_to_name(addr);
2881 /* if it gets here, either it is of type AT_NONE, */
2882 /* or it should be solvable in address_to_str -unless addr->type is wrongly defined */
2884 if (addr->type == AT_NONE){
2888 /* We need an ephemeral allocated string */
2889 return ep_address_to_str(addr);
2893 get_addr_name(const address *addr)
2896 struct e_in6_addr ip6_addr;
2899 * Try to look up a name for this address.
2900 * If it's not found, this might return a string corresponding to
2901 * the address, or it might return NULL.
2903 * Whatever string is returned has at least session scope.
2905 switch (addr->type) {
2908 return get_ether_name((const guint8 *)addr->data);
2911 memcpy(&ip4_addr, addr->data, sizeof ip4_addr);
2912 return get_hostname(ip4_addr);
2915 memcpy(&ip6_addr.bytes, addr->data, sizeof ip6_addr.bytes);
2916 return get_hostname6(&ip6_addr);
2924 get_addr_name_buf(const address *addr, gchar *buf, gsize size)
2926 const gchar *result = ep_address_to_display(addr);
2928 g_strlcpy(buf, result, size);
2929 } /* get_addr_name_buf */
2933 get_ether_name(const guint8 *addr)
2936 gboolean resolve = gbl_resolv_flags.mac_name;
2938 tp = eth_name_lookup(addr, resolve);
2940 return resolve ? tp->resolved_name : tp->hexaddr;
2942 } /* get_ether_name */
2944 /* Look for a (non-dummy) ether name in the hash, and return it if found.
2945 * If it's not found, simply return NULL.
2948 get_ether_name_if_known(const guint8 *addr)
2952 /* Initialize ether structs if we're the first
2953 * ether-related function called */
2954 if (!gbl_resolv_flags.mac_name)
2957 /* eth_name_lookup will create a (resolved) hash entry if it doesn't exist */
2958 tp = eth_name_lookup(addr, TRUE);
2959 g_assert(tp != NULL);
2961 if (tp->status == HASHETHER_STATUS_RESOLVED_NAME) {
2962 /* Name is from an ethers file (or is a "well-known" MAC address name from the manuf file) */
2963 return tp->resolved_name;
2966 /* Name was created */
2972 get_ether_addr(const gchar *name)
2975 /* force resolution (do not check gbl_resolv_flags) */
2976 return eth_addr_lookup(name);
2978 } /* get_ether_addr */
2981 add_ether_byip(const guint ip, const guint8 *eth)
2986 /* first check that IP address can be resolved */
2987 if (!gbl_resolv_flags.network_name)
2990 tp = host_lookup(ip, &found);
2992 /* ok, we can add this entry in the ethers hashtable */
2993 add_eth_name(eth, tp->name);
2996 } /* add_ether_byip */
2999 get_ipxnet_name(const guint32 addr)
3002 if (!gbl_resolv_flags.network_name) {
3003 return ipxnet_to_str_punct(addr, '\0');
3006 return ipxnet_name_lookup(addr);
3008 } /* get_ipxnet_name */
3011 get_ipxnet_addr(const gchar *name, gboolean *known)
3016 /* force resolution (do not check gbl_resolv_flags) */
3017 addr = ipxnet_addr_lookup(name, &success);
3022 } /* get_ipxnet_addr */
3025 get_manuf_name(const guint8 *addr)
3031 /* manuf needs only the 3 most significant octets of the ethernet address */
3032 manuf_key = addr[0];
3033 manuf_key = manuf_key<<8;
3035 manuf_key = manuf_key | oct;
3036 manuf_key = manuf_key<<8;
3038 manuf_key = manuf_key | oct;
3040 if (!gbl_resolv_flags.mac_name || ((cur = (gchar *)g_hash_table_lookup(manuf_hashtable, &manuf_key)) == NULL)) {
3041 cur=ep_strdup_printf("%02x:%02x:%02x", addr[0], addr[1], addr[2]);
3047 } /* get_manuf_name */
3050 uint_get_manuf_name(const guint oid)
3054 addr[0] = (oid >> 16) & 0xFF;
3055 addr[1] = (oid >> 8) & 0xFF;
3056 addr[2] = (oid >> 0) & 0xFF;
3057 return get_manuf_name(addr);
3061 tvb_get_manuf_name(tvbuff_t *tvb, gint offset)
3063 return get_manuf_name(tvb_get_ptr(tvb, offset, 3));
3067 get_manuf_name_if_known(const guint8 *addr)
3073 /* manuf needs only the 3 most significant octets of the ethernet address */
3074 manuf_key = addr[0];
3075 manuf_key = manuf_key<<8;
3077 manuf_key = manuf_key | oct;
3078 manuf_key = manuf_key<<8;
3080 manuf_key = manuf_key | oct;
3082 if ((cur = (gchar *)g_hash_table_lookup(manuf_hashtable, &manuf_key)) == NULL) {
3088 } /* get_manuf_name_if_known */
3091 uint_get_manuf_name_if_known(const guint manuf_key)
3095 if ((cur = (gchar *)g_hash_table_lookup(manuf_hashtable, &manuf_key)) == NULL) {
3103 tvb_get_manuf_name_if_known(tvbuff_t *tvb, gint offset)
3105 return get_manuf_name_if_known(tvb_get_ptr(tvb, offset, 3));
3109 ep_eui64_to_display(const guint64 addr_eui64)
3112 guint8 *addr = (guint8 *)ep_alloc(8);
3114 /* Copy and convert the address to network byte order. */
3115 *(guint64 *)(void *)(addr) = pntoh64(&(addr_eui64));
3117 if (!gbl_resolv_flags.mac_name || ((name = manuf_name_lookup(addr)) == NULL)) {
3118 cur=ep_strdup_printf("%02x:%02x:%02x%02x:%02x:%02x%02x:%02x", addr[0], addr[1], addr[2], addr[3], addr[4], addr[5], addr[6], addr[7]);
3121 cur=ep_strdup_printf("%s_%02x:%02x:%02x:%02x:%02x", name, addr[3], addr[4], addr[5], addr[6], addr[7]);
3124 } /* ep_eui64_to_display */
3128 ep_eui64_to_display_if_known(const guint64 addr_eui64)
3131 guint8 *addr = (guint8 *)ep_alloc(8);
3133 /* Copy and convert the address to network byte order. */
3134 *(guint64 *)(void *)(addr) = pntoh64(&(addr_eui64));
3136 if ((name = manuf_name_lookup(addr)) == NULL) {
3140 cur=ep_strdup_printf("%s_%02x:%02x:%02x:%02x:%02x", name, addr[3], addr[4], addr[5], addr[6], addr[7]);
3143 } /* ep_eui64_to_display_if_known */
3146 #define GHI_TIMEOUT (250 * 1000)
3151 #if ( ( ARES_VERSION_MAJOR < 1 ) \
3152 || ( 1 == ARES_VERSION_MAJOR && ARES_VERSION_MINOR < 5 ) )
3161 * XXX - If we wanted to be really fancy we could cache results here and
3162 * look them up in get_host_ipaddr* below.
3164 async_hostent_t *ahp = (async_hostent_t *)arg;
3165 if (status == ARES_SUCCESS && hp && ahp && hp->h_length == ahp->addr_size) {
3166 memcpy(ahp->addrp, hp->h_addr, hp->h_length);
3167 ahp->copied = hp->h_length;
3170 #endif /* HAVE_C_ARES */
3172 /* Translate a string, assumed either to be a dotted-quad IP address or
3173 * a host name, to a numeric IP address. Return TRUE if we succeed and
3174 * set "*addrp" to that numeric IP address; return FALSE if we fail.
3175 * Used more in the dfilter parser rather than in packet dissectors */
3177 get_host_ipaddr(const char *host, guint32 *addrp)
3179 struct in_addr ipaddr;
3181 struct timeval tv = { 0, GHI_TIMEOUT }, *tvp;
3184 async_hostent_t ahe;
3185 #else /* HAVE_C_ARES */
3187 #endif /* HAVE_C_ARES */
3190 * don't change it to inet_pton(AF_INET), they are not 100% compatible.
3191 * inet_pton(AF_INET) does not support hexadecimal notation nor
3192 * less-than-4 octet notation.
3194 if (!inet_aton(host, &ipaddr)) {
3196 /* It's not a valid dotted-quad IP address; is it a valid
3200 /* If we're not allowed to do name resolution, don't do name
3203 if (!gbl_resolv_flags.network_name ||
3204 !gbl_resolv_flags.use_external_net_name_resolver) {
3209 if (! (gbl_resolv_flags.concurrent_dns) ||
3210 name_resolve_concurrency < 1 ||
3211 ! async_dns_initialized) {
3214 ahe.addr_size = (int) sizeof (struct in_addr);
3217 ares_gethostbyname(ghbn_chan, host, AF_INET, c_ares_ghi_cb, &ahe);
3220 nfds = ares_fds(ghbn_chan, &rfds, &wfds);
3222 tvp = ares_timeout(ghbn_chan, &tv, &tv);
3223 if (select(nfds, &rfds, &wfds, NULL, tvp) == -1) { /* call to select() failed */
3224 fprintf(stderr, "Warning: call to select() failed, error is %s\n", strerror(errno));
3227 ares_process(ghbn_chan, &rfds, &wfds);
3229 ares_cancel(ghbn_chan);
3230 if (ahe.addr_size == ahe.copied) {
3234 #else /* ! HAVE_C_ARES */
3235 hp = gethostbyname(host);
3239 /* Apparently, some versions of gethostbyaddr can
3240 * return IPv6 addresses. */
3241 } else if (hp->h_length <= (int) sizeof (struct in_addr)) {
3242 memcpy(&ipaddr, hp->h_addr, hp->h_length);
3246 #endif /* HAVE_C_ARES */
3248 /* Does the string really contain dotted-quad IP?
3249 * Check against inet_atons that accept strings such as
3250 * "130.230" as valid addresses and try to convert them
3251 * to some form of a classful (host.net) notation.
3253 unsigned int a0, a1, a2, a3;
3254 if (sscanf(host, "%u.%u.%u.%u", &a0, &a1, &a2, &a3) != 4)
3258 *addrp = ipaddr.s_addr;
3263 * Translate IPv6 numeric address or FQDN hostname, into binary IPv6 address.
3264 * Return TRUE if we succeed and set "*addrp" to that numeric IP address;
3265 * return FALSE if we fail.
3268 get_host_ipaddr6(const char *host, struct e_in6_addr *addrp)
3271 struct timeval tv = { 0, GHI_TIMEOUT }, *tvp;
3274 async_hostent_t ahe;
3275 #elif defined(HAVE_GETHOSTBYNAME2)
3277 #endif /* HAVE_C_ARES */
3279 if (str_to_ip6(host, addrp))
3282 /* It's not a valid dotted-quad IP address; is it a valid
3286 /* If we're not allowed to do name resolution, don't do name
3289 if (!gbl_resolv_flags.network_name ||
3290 !gbl_resolv_flags.use_external_net_name_resolver) {
3296 if (! (gbl_resolv_flags.concurrent_dns) ||
3297 name_resolve_concurrency < 1 ||
3298 ! async_dns_initialized) {
3301 ahe.addr_size = (int) sizeof (struct e_in6_addr);
3304 ares_gethostbyname(ghbn_chan, host, AF_INET6, c_ares_ghi_cb, &ahe);
3307 nfds = ares_fds(ghbn_chan, &rfds, &wfds);
3309 tvp = ares_timeout(ghbn_chan, &tv, &tv);
3310 if (select(nfds, &rfds, &wfds, NULL, tvp) == -1) { /* call to select() failed */
3311 fprintf(stderr, "Warning: call to select() failed, error is %s\n", strerror(errno));
3314 ares_process(ghbn_chan, &rfds, &wfds);
3316 ares_cancel(ghbn_chan);
3317 if (ahe.addr_size == ahe.copied) {
3320 #elif defined(HAVE_GETHOSTBYNAME2)
3321 hp = gethostbyname2(host, AF_INET6);
3322 if (hp != NULL && hp->h_length == sizeof(struct e_in6_addr)) {
3323 memcpy(addrp, hp->h_addr, hp->h_length);
3332 * Find out whether a hostname resolves to an ip or ipv6 address
3333 * Return "ip6" if it is IPv6, "ip" otherwise (including the case
3334 * that we don't know)
3336 const char* host_ip_af(const char *host
3337 #ifndef HAVE_GETHOSTBYNAME2
3342 #ifdef HAVE_GETHOSTBYNAME2
3344 return (h = gethostbyname2(host, AF_INET6)) && h->h_addrtype == AF_INET6 ? "ip6" : "ip";
3351 get_manuf_hashtable(void)
3353 return manuf_hashtable;
3357 get_wka_hashtable(void)
3359 return wka_hashtable;
3363 get_eth_hashtable(void)
3365 return eth_hashtable;
3369 get_serv_port_hashtable(void)
3371 return serv_port_hashtable;
3375 get_ipxnet_hash_table(void)
3377 return ipxnet_hash_table;
3381 get_ipv4_hash_table(void)
3383 return ipv4_hash_table;
3387 get_ipv6_hash_table(void)
3389 return ipv6_hash_table;
3391 /* Initialize all the address resolution subsystems in this file */
3393 addr_resolv_init(void)
3395 initialize_services();
3396 initialize_ethers();
3397 initialize_ipxnets();
3398 /* host name initialization is done on a per-capture-file basis */
3399 /*host_name_lookup_init();*/
3402 /* Clean up all the address resolution subsystems in this file */
3404 addr_resolv_cleanup(void)
3406 service_name_lookup_cleanup();
3407 eth_name_lookup_cleanup();
3408 ipx_name_lookup_cleanup();
3409 /* host name initialization is done on a per-capture-file basis */
3410 /*host_name_lookup_cleanup();*/
3414 str_to_ip(const char *str, void *dst)
3416 return inet_pton(AF_INET, str, dst) > 0;
3420 str_to_ip6(const char *str, void *dst)
3422 return inet_pton(AF_INET6, str, dst) > 0;
3426 * Editor modelines - http://www.wireshark.org/tools/modelines.html
3431 * indent-tabs-mode: nil
3434 * vi: set shiftwidth=4 tabstop=8 expandtab:
3435 * :indentSize=4:tabSize=8:noTabs=true: