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
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[0] << 16) + (addr[1] << 8) + addr[2]);
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, gboolean store_entries)
1941 guint32 host_addr[4]; /* IPv4 or IPv6 */
1942 struct e_in6_addr ip6_addr;
1943 gboolean is_ipv6, entry_found = FALSE;
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 if (store_entries) {
1979 memcpy(&ip6_addr, host_addr, sizeof ip6_addr);
1980 add_ipv6_name(&ip6_addr, cp);
1982 add_ipv4_name(host_addr[0], cp);
1985 * Add the aliases, too, if there are any.
1986 * XXX - host_lookup() only returns the first entry.
1988 while ((cp = strtok(NULL, " \t")) != NULL) {
1990 memcpy(&ip6_addr, host_addr, sizeof ip6_addr);
1991 add_ipv6_name(&ip6_addr, cp);
1993 add_ipv4_name(host_addr[0], cp);
2000 return entry_found ? TRUE : FALSE;
2001 } /* read_hosts_file */
2004 add_hosts_file (const char *hosts_file)
2006 gboolean found = FALSE;
2012 if (!extra_hosts_files)
2013 extra_hosts_files = g_ptr_array_new();
2015 for (i = 0; i < extra_hosts_files->len; i++) {
2016 if (strcmp(hosts_file, (const char *) g_ptr_array_index(extra_hosts_files, i)) == 0)
2021 g_ptr_array_add(extra_hosts_files, g_strdup(hosts_file));
2022 return read_hosts_file (hosts_file, FALSE);
2028 add_ip_name_from_string (const char *addr, const char *name)
2030 guint32 host_addr[4]; /* IPv4 */
2031 struct e_in6_addr ip6_addr; /* IPv6 */
2034 resolved_ipv4_t *resolved_ipv4_entry;
2035 resolved_ipv6_t *resolved_ipv6_entry;
2037 ret = inet_pton(AF_INET6, addr, &ip6_addr);
2039 /* Error parsing address */
2046 /* Not valid IPv6 - valid IPv4? */
2047 if (!str_to_ip(addr, &host_addr))
2048 return FALSE; /* no */
2053 resolved_ipv6_entry = g_new(resolved_ipv6_t, 1);
2054 memcpy(&(resolved_ipv6_entry->ip6_addr), &ip6_addr, 16);
2055 g_strlcpy(resolved_ipv6_entry->name, name, MAXNAMELEN);
2056 manually_resolved_ipv6_list = g_slist_prepend(manually_resolved_ipv6_list, resolved_ipv6_entry);
2058 resolved_ipv4_entry = g_new(resolved_ipv4_t, 1);
2059 resolved_ipv4_entry->host_addr = host_addr[0];
2060 g_strlcpy(resolved_ipv4_entry->name, name, MAXNAMELEN);
2061 manually_resolved_ipv4_list = g_slist_prepend(manually_resolved_ipv4_list, resolved_ipv4_entry);
2065 } /* add_ip_name_from_string */
2068 * Add the resolved addresses that are in use to the list used to create the NRB
2071 ipv4_hash_table_resolved_to_list(gpointer key _U_, gpointer value, gpointer user_data)
2073 addrinfo_lists_t *lists = (addrinfo_lists_t*)user_data;
2074 hashipv4_t *ipv4_hash_table_entry = (hashipv4_t *)value;
2076 if((ipv4_hash_table_entry->flags & USED_AND_RESOLVED_MASK) == RESOLVED_ADDRESS_USED){
2077 lists->ipv4_addr_list = g_list_prepend (lists->ipv4_addr_list, ipv4_hash_table_entry);
2083 * Add the resolved addresses that are in use to the list used to create the NRB
2087 ipv6_hash_table_resolved_to_list(gpointer key _U_, gpointer value, gpointer user_data)
2089 addrinfo_lists_t *lists = (addrinfo_lists_t*)user_data;
2090 hashipv6_t *ipv6_hash_table_entry = (hashipv6_t *)value;
2092 if((ipv6_hash_table_entry->flags & USED_AND_RESOLVED_MASK) == RESOLVED_ADDRESS_USED){
2093 lists->ipv6_addr_list = g_list_prepend (lists->ipv6_addr_list, ipv6_hash_table_entry);
2099 get_addrinfo_list(void) {
2101 if(ipv4_hash_table){
2102 g_hash_table_foreach(ipv4_hash_table, ipv4_hash_table_resolved_to_list, &addrinfo_lists);
2105 if(ipv6_hash_table){
2106 g_hash_table_foreach(ipv6_hash_table, ipv6_hash_table_resolved_to_list, &addrinfo_lists);
2109 return &addrinfo_lists;
2112 /* Read in a list of subnet definition - name pairs.
2113 * <line> = <comment> | <entry> | <whitespace>
2114 * <comment> = <whitespace>#<any>
2115 * <entry> = <subnet_definition> <whitespace> <subnet_name> [<comment>|<whitespace><any>]
2116 * <subnet_definition> = <ipv4_address> / <subnet_mask_length>
2117 * <ipv4_address> is a full address; it will be masked to get the subnet-ID.
2118 * <subnet_mask_length> is a decimal 1-31
2119 * <subnet_name> is a string containing no whitespace.
2120 * <whitespace> = (space | tab)+
2121 * Any malformed entries are ignored.
2122 * Any trailing data after the subnet_name is ignored.
2127 read_subnets_file (const char *subnetspath)
2133 guint32 host_addr; /* IPv4 ONLY */
2136 if ((hf = ws_fopen(subnetspath, "r")) == NULL)
2139 while (fgetline(&line, &size, hf) >= 0) {
2140 if ((cp = strchr(line, '#')))
2143 if ((cp = strtok(line, " \t")) == NULL)
2144 continue; /* no tokens in the line */
2147 /* Expected format is <IP4 address>/<subnet length> */
2148 cp2 = strchr(cp, '/');
2153 *cp2 = '\0'; /* Cut token */
2156 /* Check if this is a valid IPv4 address */
2157 if (!str_to_ip(cp, &host_addr)) {
2161 mask_length = atoi(cp2);
2162 if(0 >= mask_length || mask_length > 31) {
2163 continue; /* invalid mask length */
2166 if ((cp = strtok(NULL, " \t")) == NULL)
2167 continue; /* no subnet name */
2169 subnet_entry_set(host_addr, (guint32)mask_length, cp);
2175 } /* read_subnets_file */
2177 static subnet_entry_t
2178 subnet_lookup(const guint32 addr)
2180 subnet_entry_t subnet_entry;
2183 /* Search mask lengths linearly, longest first */
2185 i = SUBNETLENGTHSIZE;
2186 while(have_subnet_entry && i > 0) {
2187 guint32 masked_addr;
2188 subnet_length_entry_t* length_entry;
2190 /* Note that we run from 31 (length 32) to 0 (length 1) */
2192 g_assert(i < SUBNETLENGTHSIZE);
2195 length_entry = &subnet_length_entries[i];
2197 if(NULL != length_entry->subnet_addresses) {
2198 sub_net_hashipv4_t * tp;
2201 masked_addr = addr & length_entry->mask;
2202 hash_idx = HASH_IPV4_ADDRESS(masked_addr);
2204 tp = length_entry->subnet_addresses[hash_idx];
2205 while(tp != NULL && tp->addr != masked_addr) {
2210 subnet_entry.mask = length_entry->mask;
2211 subnet_entry.mask_length = i + 1; /* Length is offset + 1 */
2212 subnet_entry.name = tp->name;
2213 return subnet_entry;
2218 subnet_entry.mask = 0;
2219 subnet_entry.mask_length = 0;
2220 subnet_entry.name = NULL;
2222 return subnet_entry;
2225 /* Add a subnet-definition - name pair to the set.
2226 * The definition is taken by masking the address passed in with the mask of the
2230 subnet_entry_set(guint32 subnet_addr, const guint32 mask_length, const gchar* name)
2232 subnet_length_entry_t* entry;
2233 sub_net_hashipv4_t * tp;
2236 g_assert(mask_length > 0 && mask_length <= 32);
2238 entry = &subnet_length_entries[mask_length - 1];
2240 subnet_addr &= entry->mask;
2242 hash_idx = HASH_IPV4_ADDRESS(subnet_addr);
2244 if(NULL == entry->subnet_addresses) {
2245 entry->subnet_addresses = (sub_net_hashipv4_t**) se_alloc0(sizeof(sub_net_hashipv4_t*) * HASHHOSTSIZE);
2248 if(NULL != (tp = entry->subnet_addresses[hash_idx])) {
2249 if(tp->addr == subnet_addr) {
2250 return; /* XXX provide warning that an address was repeated? */
2252 sub_net_hashipv4_t * new_tp = se_new(sub_net_hashipv4_t);
2257 tp = entry->subnet_addresses[hash_idx] = se_new(sub_net_hashipv4_t);
2261 tp->addr = subnet_addr;
2262 /* Clear DUMMY_ADDRESS_ENTRY */
2263 tp->flags = tp->flags & 0xfe; /*Never used again...*/
2264 g_strlcpy(tp->name, name, MAXNAMELEN); /* This is longer than subnet names can actually be */
2265 have_subnet_entry = TRUE;
2269 subnet_name_lookup_init(void)
2274 for(i = 0; i < SUBNETLENGTHSIZE; ++i) {
2275 guint32 length = i + 1;
2277 subnet_length_entries[i].subnet_addresses = NULL;
2278 subnet_length_entries[i].mask_length = length;
2279 subnet_length_entries[i].mask = g_htonl(ip_get_subnet_mask(length));
2282 subnetspath = get_persconffile_path(ENAME_SUBNETS, FALSE);
2283 if (!read_subnets_file(subnetspath) && errno != ENOENT) {
2284 report_open_failure(subnetspath, errno, FALSE);
2286 g_free(subnetspath);
2289 * Load the global subnets file, if we have one.
2291 subnetspath = get_datafile_path(ENAME_SUBNETS);
2292 if (!read_subnets_file(subnetspath) && errno != ENOENT) {
2293 report_open_failure(subnetspath, errno, FALSE);
2295 g_free(subnetspath);
2300 * External Functions
2304 addr_resolve_pref_init(module_t *nameres)
2306 prefs_register_bool_preference(nameres, "mac_name",
2307 "Resolve MAC addresses",
2308 "Resolve Ethernet MAC address to manufacturer names",
2309 &gbl_resolv_flags.mac_name);
2311 prefs_register_bool_preference(nameres, "transport_name",
2312 "Resolve transport names",
2313 "Resolve TCP/UDP ports into service names",
2314 &gbl_resolv_flags.transport_name);
2316 prefs_register_bool_preference(nameres, "network_name",
2317 "Resolve network (IP) addresses",
2318 "Resolve IPv4, IPv6, and IPX addresses into host names."
2319 " The next set of check boxes determines how name resolution should be performed."
2320 " If no other options are checked name resolution is made from Wireshark's host file,"
2321 " capture file name resolution blocks and DNS packets in the capture.",
2322 &gbl_resolv_flags.network_name);
2324 prefs_register_bool_preference(nameres, "use_external_name_resolver",
2325 "Use an external network name resolver",
2326 "Use your system's configured name resolver"
2327 " (usually DNS) to resolve network names."
2328 " Only applies when network name resolution"
2330 &gbl_resolv_flags.use_external_net_name_resolver);
2332 #if defined(HAVE_C_ARES) || defined(HAVE_GNU_ADNS)
2333 prefs_register_bool_preference(nameres, "concurrent_dns",
2334 "Enable concurrent DNS name resolution",
2335 "Enable concurrent DNS name resolution. Only"
2336 " applies when network name resolution is"
2337 " enabled. You probably want to enable this.",
2338 &gbl_resolv_flags.concurrent_dns);
2340 prefs_register_uint_preference(nameres, "name_resolve_concurrency",
2341 "Maximum concurrent requests",
2342 "The maximum number of DNS requests that may"
2343 " be active at any time. A large value (many"
2344 " thousands) might overload the network or make"
2345 " your DNS server behave badly.",
2347 &name_resolve_concurrency);
2349 prefs_register_static_text_preference(nameres, "concurrent_dns",
2350 "Enable concurrent DNS name resolution: N/A",
2351 "Support for concurrent DNS name resolution was not"
2352 " compiled into this version of Wireshark");
2355 prefs_register_bool_preference(nameres, "hosts_file_handling",
2356 "Only use the profile \"hosts\" file",
2357 "By default \"hosts\" files will be loaded from multiple sources."
2358 " Checking this box only loads the \"hosts\" in the current profile.",
2359 &gbl_resolv_flags.load_hosts_file_from_profile_only);
2365 host_name_lookup_process(void) {
2366 async_dns_queue_msg_t *caqm;
2367 struct timeval tv = { 0, 0 };
2370 gboolean nro = new_resolved_objects;
2372 new_resolved_objects = FALSE;
2374 if (!async_dns_initialized)
2375 /* c-ares not initialized. Bail out and cancel timers. */
2378 async_dns_queue_head = g_list_first(async_dns_queue_head);
2380 while (async_dns_queue_head != NULL && async_dns_in_flight <= name_resolve_concurrency) {
2381 caqm = (async_dns_queue_msg_t *) async_dns_queue_head->data;
2382 async_dns_queue_head = g_list_remove(async_dns_queue_head, (void *) caqm);
2383 if (caqm->family == AF_INET) {
2384 ares_gethostbyaddr(ghba_chan, &caqm->addr.ip4, sizeof(guint32), AF_INET,
2385 c_ares_ghba_cb, caqm);
2386 async_dns_in_flight++;
2387 } else if (caqm->family == AF_INET6) {
2388 ares_gethostbyaddr(ghba_chan, &caqm->addr.ip6, sizeof(struct e_in6_addr),
2389 AF_INET6, c_ares_ghba_cb, caqm);
2390 async_dns_in_flight++;
2396 nfds = ares_fds(ghba_chan, &rfds, &wfds);
2398 if (select(nfds, &rfds, &wfds, NULL, &tv) == -1) { /* call to select() failed */
2399 fprintf(stderr, "Warning: call to select() failed, error is %s\n", g_strerror(errno));
2402 ares_process(ghba_chan, &rfds, &wfds);
2405 /* Any new entries? */
2410 _host_name_lookup_cleanup(void) {
2413 cur = g_list_first(async_dns_queue_head);
2416 cur = g_list_next (cur);
2419 g_list_free(async_dns_queue_head);
2420 async_dns_queue_head = NULL;
2422 if (async_dns_initialized) {
2423 ares_destroy(ghba_chan);
2424 ares_destroy(ghbn_chan);
2426 #ifdef CARES_HAVE_ARES_LIBRARY_INIT
2427 ares_library_cleanup();
2429 async_dns_initialized = FALSE;
2432 #elif defined(HAVE_GNU_ADNS)
2434 /* XXX - The ADNS "documentation" isn't very clear:
2435 * - Do we need to keep our query structures around?
2438 host_name_lookup_process(void) {
2439 async_dns_queue_msg_t *almsg;
2441 char addr_str[] = "111.222.333.444.in-addr.arpa.";
2446 gboolean nro = new_resolved_objects;
2448 new_resolved_objects = FALSE;
2449 async_dns_queue_head = g_list_first(async_dns_queue_head);
2451 cur = async_dns_queue_head;
2452 while (cur && async_dns_in_flight <= name_resolve_concurrency) {
2453 almsg = (async_dns_queue_msg_t *) cur->data;
2454 if (! almsg->submitted && almsg->type == AF_INET) {
2455 addr_bytes = (guint8 *) &almsg->ip4_addr;
2456 g_snprintf(addr_str, sizeof addr_str, "%u.%u.%u.%u.in-addr.arpa.", addr_bytes[3],
2457 addr_bytes[2], addr_bytes[1], addr_bytes[0]);
2458 /* XXX - what if it fails? */
2459 adns_submit (ads, addr_str, adns_r_ptr, adns_qf_none, NULL, &almsg->query);
2460 almsg->submitted = TRUE;
2461 async_dns_in_flight++;
2466 cur = async_dns_queue_head;
2469 almsg = (async_dns_queue_msg_t *) cur->data;
2470 if (almsg->submitted) {
2471 ret = adns_check(ads, &almsg->query, &ans, NULL);
2473 if (ans->status == adns_s_ok) {
2474 add_ipv4_name(almsg->ip4_addr, *ans->rrs.str);
2481 async_dns_queue_head = g_list_remove(async_dns_queue_head, (void *) almsg);
2483 /* XXX, what to do if async_dns_in_flight == 0? */
2484 async_dns_in_flight--;
2488 /* Keep the timeout in place */
2493 _host_name_lookup_cleanup(void) {
2496 async_dns_queue_head = g_list_first(async_dns_queue_head);
2497 while (async_dns_queue_head) {
2498 qdata = async_dns_queue_head->data;
2499 async_dns_queue_head = g_list_remove(async_dns_queue_head, qdata);
2503 if (async_dns_initialized)
2505 async_dns_initialized = FALSE;
2508 #else /* HAVE_GNU_ADNS */
2511 host_name_lookup_process(void) {
2512 gboolean nro = new_resolved_objects;
2514 new_resolved_objects = FALSE;
2520 _host_name_lookup_cleanup(void) {
2523 #endif /* HAVE_C_ARES */
2526 get_hostname(const guint addr)
2530 /* XXX why do we call this if we're not resolving? To create hash entries?
2533 hashipv4_t *tp = host_lookup(addr, &found);
2535 if (!gbl_resolv_flags.network_name)
2538 tp->flags = tp->flags | RESOLVED_ADDRESS_USED;
2543 /* -------------------------- */
2546 get_hostname6(const struct e_in6_addr *addr)
2550 /* XXX why do we call this if we're not resolving? To create hash entries?
2553 hashipv6_t *tp = host_lookup6(addr, &found);
2555 if (!gbl_resolv_flags.network_name)
2558 tp->flags = tp->flags | RESOLVED_ADDRESS_USED;
2563 /* -------------------------- */
2565 add_ipv4_name(const guint addr, const gchar *name)
2570 * Don't add zero-length names; apparently, some resolvers will return
2571 * them if they get them from DNS.
2573 if (name[0] == '\0')
2577 tp = (hashipv4_t *)g_hash_table_lookup(ipv4_hash_table, GUINT_TO_POINTER(addr));
2579 g_strlcpy(tp->name, name, MAXNAMELEN);
2581 tp = new_ipv4(addr);
2582 g_strlcpy(tp->name, name, MAXNAMELEN);
2583 g_hash_table_insert(ipv4_hash_table, GUINT_TO_POINTER(addr), tp);
2586 g_strlcpy(tp->name, name, MAXNAMELEN);
2587 tp->flags = tp->flags | TRIED_RESOLVE_ADDRESS;
2588 new_resolved_objects = TRUE;
2590 } /* add_ipv4_name */
2592 /* -------------------------- */
2594 add_ipv6_name(const struct e_in6_addr *addrp, const gchar *name)
2599 * Don't add zero-length names; apparently, some resolvers will return
2600 * them if they get them from DNS.
2602 if (name[0] == '\0')
2605 tp = (hashipv6_t *)g_hash_table_lookup(ipv6_hash_table, addrp);
2607 g_strlcpy(tp->name, name, MAXNAMELEN);
2609 struct e_in6_addr *addr_key;
2611 addr_key = g_new(struct e_in6_addr,1);
2612 tp = new_ipv6(addrp);
2613 memcpy(addr_key, addrp, 16);
2614 g_strlcpy(tp->name, name, MAXNAMELEN);
2615 g_hash_table_insert(ipv6_hash_table, addr_key, tp);
2618 g_strlcpy(tp->name, name, MAXNAMELEN);
2619 tp->flags = tp->flags | TRIED_RESOLVE_ADDRESS;
2620 new_resolved_objects = TRUE;
2622 } /* add_ipv6_name */
2625 add_manually_resolved_ipv4(gpointer data, gpointer user_data _U_)
2627 resolved_ipv4_t *resolved_ipv4_entry = (resolved_ipv4_t *)data;
2629 add_ipv4_name(resolved_ipv4_entry->host_addr, resolved_ipv4_entry->name);
2633 add_manually_resolved_ipv6(gpointer data, gpointer user_data _U_)
2635 resolved_ipv6_t *resolved_ipv6_entry = (resolved_ipv6_t *)data;
2637 add_ipv6_name(&(resolved_ipv6_entry->ip6_addr), resolved_ipv6_entry->name);
2641 add_manually_resolved(void)
2643 if(manually_resolved_ipv4_list){
2644 g_slist_foreach(manually_resolved_ipv4_list, add_manually_resolved_ipv4, NULL);
2647 if(manually_resolved_ipv6_list){
2648 g_slist_foreach(manually_resolved_ipv6_list, add_manually_resolved_ipv6, NULL);
2653 host_name_lookup_init(void)
2658 #ifdef HAVE_GNU_ADNS
2661 static char rootpath_nt[] = "\\system32\\drivers\\etc\\hosts";
2662 static char rootpath_ot[] = "\\hosts";
2664 #endif /*GNU_ADNS */
2666 g_assert(ipxnet_hash_table == NULL);
2667 ipxnet_hash_table = g_hash_table_new_full(g_int_hash, g_int_equal, g_free, g_free);
2669 g_assert(ipv4_hash_table == NULL);
2670 ipv4_hash_table = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, g_free);
2672 g_assert(ipv6_hash_table == NULL);
2673 ipv6_hash_table = g_hash_table_new_full(ipv6_oat_hash, ipv6_equal, g_free, g_free);
2676 * Load the global hosts file, if we have one.
2678 if(!gbl_resolv_flags.load_hosts_file_from_profile_only){
2679 hostspath = get_datafile_path(ENAME_HOSTS);
2680 if (!read_hosts_file(hostspath, TRUE) && errno != ENOENT) {
2681 report_open_failure(hostspath, errno, FALSE);
2686 * Load the user's hosts file no matter what, if they have one.
2688 hostspath = get_persconffile_path(ENAME_HOSTS, TRUE);
2689 if (!read_hosts_file(hostspath, TRUE) && errno != ENOENT) {
2690 report_open_failure(hostspath, errno, FALSE);
2694 if (gbl_resolv_flags.concurrent_dns) {
2695 #ifdef CARES_HAVE_ARES_LIBRARY_INIT
2696 if (ares_library_init(ARES_LIB_INIT_ALL) == ARES_SUCCESS) {
2698 if (ares_init(&ghba_chan) == ARES_SUCCESS && ares_init(&ghbn_chan) == ARES_SUCCESS) {
2699 async_dns_initialized = TRUE;
2701 #ifdef CARES_HAVE_ARES_LIBRARY_INIT
2706 #ifdef HAVE_GNU_ADNS
2708 * We're using GNU ADNS, which doesn't check the system hosts file;
2709 * we load that file ourselves.
2713 sysroot = getenv_utf8("WINDIR");
2714 if (sysroot != NULL) {
2716 * The file should be under WINDIR.
2717 * If this is Windows NT (NT 4.0,2K,XP,Server2K3), it's in
2718 * %WINDIR%\system32\drivers\etc\hosts.
2719 * If this is Windows OT (95,98,Me), it's in %WINDIR%\hosts.
2721 * XXX - should we base it on the dwPlatformId value from
2724 if(!gbl_resolv_flags.load_hosts_file_from_profile_only){
2725 hostspath = g_strconcat(sysroot, rootpath_nt, NULL);
2726 if (!read_hosts_file(hostspath, TRUE)) {
2728 hostspath = g_strconcat(sysroot, rootpath_ot, NULL);
2729 read_hosts_file(hostspath, TRUE);
2735 if(!gbl_resolv_flags.load_hosts_file_from_profile_only){
2736 read_hosts_file("/etc/hosts", TRUE);
2740 if (gbl_resolv_flags.concurrent_dns) {
2741 /* XXX - Any flags we should be using? */
2742 /* XXX - We could provide config settings for DNS servers, and
2743 pass them to ADNS with adns_init_strcfg */
2744 if (adns_init(&ads, adns_if_none, 0 /*0=>stderr*/) != 0) {
2746 * XXX - should we report the error? I'm assuming that some crashes
2747 * reported on a Windows machine with TCP/IP not configured are due
2748 * to "adns_init()" failing (due to the lack of TCP/IP) and leaving
2749 * ADNS in a state where it crashes due to that. We'll still try
2750 * doing name resolution anyway.
2754 async_dns_initialized = TRUE;
2755 async_dns_in_flight = 0;
2757 #endif /* HAVE_GNU_ADNS */
2758 #endif /* HAVE_C_ARES */
2760 if(extra_hosts_files && !gbl_resolv_flags.load_hosts_file_from_profile_only){
2761 for (i = 0; i < extra_hosts_files->len; i++) {
2762 read_hosts_file((const char *) g_ptr_array_index(extra_hosts_files, i), TRUE);
2766 subnet_name_lookup_init();
2768 add_manually_resolved();
2772 host_name_lookup_cleanup(void)
2774 _host_name_lookup_cleanup();
2776 if(ipxnet_hash_table){
2777 g_hash_table_destroy(ipxnet_hash_table);
2778 ipxnet_hash_table = NULL;
2781 if(ipv4_hash_table){
2782 g_hash_table_destroy(ipv4_hash_table);
2783 ipv4_hash_table = NULL;
2786 if(ipv6_hash_table){
2787 g_hash_table_destroy(ipv6_hash_table);
2788 ipv6_hash_table = NULL;
2791 memset(subnet_length_entries, 0, sizeof(subnet_length_entries));
2793 have_subnet_entry = FALSE;
2794 new_resolved_objects = FALSE;
2798 free_manually_resolved_ipv4(gpointer data, gpointer user_data _U_)
2800 resolved_ipv4_t *resolved_ipv4_entry = (resolved_ipv4_t *)data;
2802 g_free(resolved_ipv4_entry);
2806 free_manually_resolved_ipv6(gpointer data, gpointer user_data _U_)
2808 resolved_ipv6_t *resolved_ipv6_entry = (resolved_ipv6_t *)data;
2810 g_free(resolved_ipv6_entry);
2814 manually_resolve_cleanup(void)
2816 if(manually_resolved_ipv4_list){
2817 g_slist_foreach(manually_resolved_ipv4_list, free_manually_resolved_ipv4, NULL);
2818 g_slist_free(manually_resolved_ipv4_list);
2819 manually_resolved_ipv4_list = NULL;
2822 if(manually_resolved_ipv6_list){
2823 g_slist_foreach(manually_resolved_ipv6_list, free_manually_resolved_ipv6, NULL);
2824 g_slist_free(manually_resolved_ipv6_list);
2825 manually_resolved_ipv6_list = NULL;
2831 ep_udp_port_to_display(guint port)
2834 if (!gbl_resolv_flags.transport_name) {
2835 return ep_utoa(port);
2838 return serv_name_lookup(port, PT_UDP);
2840 } /* ep_udp_port_to_display */
2843 ep_dccp_port_to_display(guint port)
2846 if (!gbl_resolv_flags.transport_name) {
2847 return ep_utoa(port);
2850 return serv_name_lookup(port, PT_DCCP);
2852 } /* ep_dccp_port_to_display */
2855 ep_tcp_port_to_display(guint port)
2858 if (!gbl_resolv_flags.transport_name) {
2859 return ep_utoa(port);
2862 return serv_name_lookup(port, PT_TCP);
2864 } /* ep_tcp_port_to_display */
2867 ep_sctp_port_to_display(guint port)
2870 if (!gbl_resolv_flags.transport_name) {
2871 return ep_utoa(port);
2874 return serv_name_lookup(port, PT_SCTP);
2876 } /* ep_sctp_port_to_display */
2879 ep_address_to_display(const address *addr)
2881 const gchar *result;
2883 result = solve_address_to_name(addr);
2888 /* if it gets here, either it is of type AT_NONE, */
2889 /* or it should be solvable in address_to_str -unless addr->type is wrongly defined */
2891 if (addr->type == AT_NONE){
2895 /* We need an ephemeral allocated string */
2896 return ep_address_to_str(addr);
2900 get_addr_name(const address *addr)
2903 struct e_in6_addr ip6_addr;
2906 * Try to look up a name for this address.
2907 * If it's not found, this might return a string corresponding to
2908 * the address, or it might return NULL.
2910 * Whatever string is returned has at least session scope.
2912 switch (addr->type) {
2915 return get_ether_name((const guint8 *)addr->data);
2918 memcpy(&ip4_addr, addr->data, sizeof ip4_addr);
2919 return get_hostname(ip4_addr);
2922 memcpy(&ip6_addr.bytes, addr->data, sizeof ip6_addr.bytes);
2923 return get_hostname6(&ip6_addr);
2931 get_addr_name_buf(const address *addr, gchar *buf, gsize size)
2933 const gchar *result = ep_address_to_display(addr);
2935 g_strlcpy(buf, result, size);
2936 } /* get_addr_name_buf */
2940 get_ether_name(const guint8 *addr)
2943 gboolean resolve = gbl_resolv_flags.mac_name;
2945 tp = eth_name_lookup(addr, resolve);
2947 return resolve ? tp->resolved_name : tp->hexaddr;
2949 } /* get_ether_name */
2951 /* Look for a (non-dummy) ether name in the hash, and return it if found.
2952 * If it's not found, simply return NULL.
2955 get_ether_name_if_known(const guint8 *addr)
2959 /* Initialize ether structs if we're the first
2960 * ether-related function called */
2961 if (!gbl_resolv_flags.mac_name)
2964 /* eth_name_lookup will create a (resolved) hash entry if it doesn't exist */
2965 tp = eth_name_lookup(addr, TRUE);
2966 g_assert(tp != NULL);
2968 if (tp->status == HASHETHER_STATUS_RESOLVED_NAME) {
2969 /* Name is from an ethers file (or is a "well-known" MAC address name from the manuf file) */
2970 return tp->resolved_name;
2973 /* Name was created */
2979 get_ether_addr(const gchar *name)
2982 /* force resolution (do not check gbl_resolv_flags) */
2983 return eth_addr_lookup(name);
2985 } /* get_ether_addr */
2988 add_ether_byip(const guint ip, const guint8 *eth)
2993 /* first check that IP address can be resolved */
2994 if (!gbl_resolv_flags.network_name)
2997 tp = host_lookup(ip, &found);
2999 /* ok, we can add this entry in the ethers hashtable */
3000 add_eth_name(eth, tp->name);
3003 } /* add_ether_byip */
3006 get_ipxnet_name(const guint32 addr)
3009 if (!gbl_resolv_flags.network_name) {
3010 return ipxnet_to_str_punct(addr, '\0');
3013 return ipxnet_name_lookup(addr);
3015 } /* get_ipxnet_name */
3018 get_ipxnet_addr(const gchar *name, gboolean *known)
3023 /* force resolution (do not check gbl_resolv_flags) */
3024 addr = ipxnet_addr_lookup(name, &success);
3029 } /* get_ipxnet_addr */
3032 get_manuf_name(const guint8 *addr)
3038 /* manuf needs only the 3 most significant octets of the ethernet address */
3039 manuf_key = addr[0];
3040 manuf_key = manuf_key<<8;
3042 manuf_key = manuf_key | oct;
3043 manuf_key = manuf_key<<8;
3045 manuf_key = manuf_key | oct;
3047 if (!gbl_resolv_flags.mac_name || ((cur = (gchar *)g_hash_table_lookup(manuf_hashtable, &manuf_key)) == NULL)) {
3048 cur=ep_strdup_printf("%02x:%02x:%02x", addr[0], addr[1], addr[2]);
3054 } /* get_manuf_name */
3057 uint_get_manuf_name(const guint oid)
3061 addr[0] = (oid >> 16) & 0xFF;
3062 addr[1] = (oid >> 8) & 0xFF;
3063 addr[2] = (oid >> 0) & 0xFF;
3064 return get_manuf_name(addr);
3068 tvb_get_manuf_name(tvbuff_t *tvb, gint offset)
3070 return get_manuf_name(tvb_get_ptr(tvb, offset, 3));
3074 get_manuf_name_if_known(const guint8 *addr)
3080 /* manuf needs only the 3 most significant octets of the ethernet address */
3081 manuf_key = addr[0];
3082 manuf_key = manuf_key<<8;
3084 manuf_key = manuf_key | oct;
3085 manuf_key = manuf_key<<8;
3087 manuf_key = manuf_key | oct;
3089 if ((cur = (gchar *)g_hash_table_lookup(manuf_hashtable, &manuf_key)) == NULL) {
3095 } /* get_manuf_name_if_known */
3098 uint_get_manuf_name_if_known(const guint manuf_key)
3102 if ((cur = (gchar *)g_hash_table_lookup(manuf_hashtable, &manuf_key)) == NULL) {
3110 tvb_get_manuf_name_if_known(tvbuff_t *tvb, gint offset)
3112 return get_manuf_name_if_known(tvb_get_ptr(tvb, offset, 3));
3116 ep_eui64_to_display(const guint64 addr_eui64)
3119 guint8 *addr = (guint8 *)ep_alloc(8);
3121 /* Copy and convert the address to network byte order. */
3122 *(guint64 *)(void *)(addr) = pntoh64(&(addr_eui64));
3124 if (!gbl_resolv_flags.mac_name || ((name = manuf_name_lookup(addr)) == NULL)) {
3125 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]);
3128 cur=ep_strdup_printf("%s_%02x:%02x:%02x:%02x:%02x", name, addr[3], addr[4], addr[5], addr[6], addr[7]);
3131 } /* ep_eui64_to_display */
3135 ep_eui64_to_display_if_known(const guint64 addr_eui64)
3138 guint8 *addr = (guint8 *)ep_alloc(8);
3140 /* Copy and convert the address to network byte order. */
3141 *(guint64 *)(void *)(addr) = pntoh64(&(addr_eui64));
3143 if ((name = manuf_name_lookup(addr)) == NULL) {
3147 cur=ep_strdup_printf("%s_%02x:%02x:%02x:%02x:%02x", name, addr[3], addr[4], addr[5], addr[6], addr[7]);
3150 } /* ep_eui64_to_display_if_known */
3153 #define GHI_TIMEOUT (250 * 1000)
3158 #if ( ( ARES_VERSION_MAJOR < 1 ) \
3159 || ( 1 == ARES_VERSION_MAJOR && ARES_VERSION_MINOR < 5 ) )
3168 * XXX - If we wanted to be really fancy we could cache results here and
3169 * look them up in get_host_ipaddr* below.
3171 async_hostent_t *ahp = (async_hostent_t *)arg;
3172 if (status == ARES_SUCCESS && hp && ahp && hp->h_length == ahp->addr_size) {
3173 memcpy(ahp->addrp, hp->h_addr, hp->h_length);
3174 ahp->copied = hp->h_length;
3177 #endif /* HAVE_C_ARES */
3179 /* Translate a string, assumed either to be a dotted-quad IP address or
3180 * a host name, to a numeric IP address. Return TRUE if we succeed and
3181 * set "*addrp" to that numeric IP address; return FALSE if we fail.
3182 * Used more in the dfilter parser rather than in packet dissectors */
3184 get_host_ipaddr(const char *host, guint32 *addrp)
3186 struct in_addr ipaddr;
3188 struct timeval tv = { 0, GHI_TIMEOUT }, *tvp;
3191 async_hostent_t ahe;
3192 #else /* HAVE_C_ARES */
3194 #endif /* HAVE_C_ARES */
3197 * don't change it to inet_pton(AF_INET), they are not 100% compatible.
3198 * inet_pton(AF_INET) does not support hexadecimal notation nor
3199 * less-than-4 octet notation.
3201 if (!inet_aton(host, &ipaddr)) {
3203 /* It's not a valid dotted-quad IP address; is it a valid
3207 /* If we're not allowed to do name resolution, don't do name
3210 if (!gbl_resolv_flags.network_name ||
3211 !gbl_resolv_flags.use_external_net_name_resolver) {
3216 if (! (gbl_resolv_flags.concurrent_dns) ||
3217 name_resolve_concurrency < 1 ||
3218 ! async_dns_initialized) {
3221 ahe.addr_size = (int) sizeof (struct in_addr);
3224 ares_gethostbyname(ghbn_chan, host, AF_INET, c_ares_ghi_cb, &ahe);
3227 nfds = ares_fds(ghbn_chan, &rfds, &wfds);
3229 tvp = ares_timeout(ghbn_chan, &tv, &tv);
3230 if (select(nfds, &rfds, &wfds, NULL, tvp) == -1) { /* call to select() failed */
3231 fprintf(stderr, "Warning: call to select() failed, error is %s\n", g_strerror(errno));
3234 ares_process(ghbn_chan, &rfds, &wfds);
3236 ares_cancel(ghbn_chan);
3237 if (ahe.addr_size == ahe.copied) {
3241 #else /* ! HAVE_C_ARES */
3242 hp = gethostbyname(host);
3246 /* Apparently, some versions of gethostbyaddr can
3247 * return IPv6 addresses. */
3248 } else if (hp->h_length <= (int) sizeof (struct in_addr)) {
3249 memcpy(&ipaddr, hp->h_addr, hp->h_length);
3253 #endif /* HAVE_C_ARES */
3255 /* Does the string really contain dotted-quad IP?
3256 * Check against inet_atons that accept strings such as
3257 * "130.230" as valid addresses and try to convert them
3258 * to some form of a classful (host.net) notation.
3260 unsigned int a0, a1, a2, a3;
3261 if (sscanf(host, "%u.%u.%u.%u", &a0, &a1, &a2, &a3) != 4)
3265 *addrp = ipaddr.s_addr;
3270 * Translate IPv6 numeric address or FQDN hostname, into binary IPv6 address.
3271 * Return TRUE if we succeed and set "*addrp" to that numeric IP address;
3272 * return FALSE if we fail.
3275 get_host_ipaddr6(const char *host, struct e_in6_addr *addrp)
3278 struct timeval tv = { 0, GHI_TIMEOUT }, *tvp;
3281 async_hostent_t ahe;
3282 #elif defined(HAVE_GETHOSTBYNAME2)
3284 #endif /* HAVE_C_ARES */
3286 if (str_to_ip6(host, addrp))
3289 /* It's not a valid dotted-quad IP address; is it a valid
3293 /* If we're not allowed to do name resolution, don't do name
3296 if (!gbl_resolv_flags.network_name ||
3297 !gbl_resolv_flags.use_external_net_name_resolver) {
3303 if (! (gbl_resolv_flags.concurrent_dns) ||
3304 name_resolve_concurrency < 1 ||
3305 ! async_dns_initialized) {
3308 ahe.addr_size = (int) sizeof (struct e_in6_addr);
3311 ares_gethostbyname(ghbn_chan, host, AF_INET6, c_ares_ghi_cb, &ahe);
3314 nfds = ares_fds(ghbn_chan, &rfds, &wfds);
3316 tvp = ares_timeout(ghbn_chan, &tv, &tv);
3317 if (select(nfds, &rfds, &wfds, NULL, tvp) == -1) { /* call to select() failed */
3318 fprintf(stderr, "Warning: call to select() failed, error is %s\n", g_strerror(errno));
3321 ares_process(ghbn_chan, &rfds, &wfds);
3323 ares_cancel(ghbn_chan);
3324 if (ahe.addr_size == ahe.copied) {
3327 #elif defined(HAVE_GETHOSTBYNAME2)
3328 hp = gethostbyname2(host, AF_INET6);
3329 if (hp != NULL && hp->h_length == sizeof(struct e_in6_addr)) {
3330 memcpy(addrp, hp->h_addr, hp->h_length);
3339 * Find out whether a hostname resolves to an ip or ipv6 address
3340 * Return "ip6" if it is IPv6, "ip" otherwise (including the case
3341 * that we don't know)
3343 const char* host_ip_af(const char *host
3344 #ifndef HAVE_GETHOSTBYNAME2
3349 #ifdef HAVE_GETHOSTBYNAME2
3351 return (h = gethostbyname2(host, AF_INET6)) && h->h_addrtype == AF_INET6 ? "ip6" : "ip";
3358 get_manuf_hashtable(void)
3360 return manuf_hashtable;
3364 get_wka_hashtable(void)
3366 return wka_hashtable;
3370 get_eth_hashtable(void)
3372 return eth_hashtable;
3376 get_serv_port_hashtable(void)
3378 return serv_port_hashtable;
3382 get_ipxnet_hash_table(void)
3384 return ipxnet_hash_table;
3388 get_ipv4_hash_table(void)
3390 return ipv4_hash_table;
3394 get_ipv6_hash_table(void)
3396 return ipv6_hash_table;
3398 /* Initialize all the address resolution subsystems in this file */
3400 addr_resolv_init(void)
3402 initialize_services();
3403 initialize_ethers();
3404 initialize_ipxnets();
3405 /* host name initialization is done on a per-capture-file basis */
3406 /*host_name_lookup_init();*/
3409 /* Clean up all the address resolution subsystems in this file */
3411 addr_resolv_cleanup(void)
3413 service_name_lookup_cleanup();
3414 eth_name_lookup_cleanup();
3415 ipx_name_lookup_cleanup();
3416 /* host name initialization is done on a per-capture-file basis */
3417 /*host_name_lookup_cleanup();*/
3421 str_to_ip(const char *str, void *dst)
3423 return inet_pton(AF_INET, str, dst) > 0;
3427 str_to_ip6(const char *str, void *dst)
3429 return inet_pton(AF_INET6, str, dst) > 0;
3433 * Editor modelines - http://www.wireshark.org/tools/modelines.html
3438 * indent-tabs-mode: nil
3441 * vi: set shiftwidth=4 tabstop=8 expandtab:
3442 * :indentSize=4:tabSize=8:noTabs=true: