2 * Routines for network object lookup
4 * Laurent Deniel <laurent.deniel@free.fr>
6 * Add option to resolv VLAN ID to describing name
7 * Uli Heilmeier, March 2016
9 * Wireshark - Network traffic analyzer
10 * By Gerald Combs <gerald@wireshark.org>
11 * Copyright 1998 Gerald Combs
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License
15 * as published by the Free Software Foundation; either version 2
16 * of the License, or (at your option) any later version.
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
35 #include <wsutil/strtoi.h>
38 * Win32 doesn't have SIGALRM (and it's the OS where name lookup calls
39 * are most likely to take a long time, given the way address-to-name
40 * lookups are done over NBNS).
42 * Mac OS X does have SIGALRM, but if you longjmp() out of a name resolution
43 * call in a signal handler, you might crash, because the state of the
44 * resolution code that sends messages to lookupd might be inconsistent
45 * if you jump out of it in middle of a call.
47 * There's no guarantee that longjmp()ing out of name resolution calls
48 * will work on *any* platform; OpenBSD got rid of the alarm/longjmp
49 * code in tcpdump, to avoid those sorts of problems, and that was
50 * picked up by tcpdump.org tcpdump.
52 * So, for now, we do not use alarm() and SIGALRM to time out host name
53 * lookups. If we get a lot of complaints about lookups taking a long time,
54 * we can reconsider that decision. (Note that tcpdump originally added
55 * such a timeout mechanism that for the benefit of systems using NIS to
56 * look up host names; that might now be fixed in NIS implementations, for
57 * those sites still using NIS rather than DNS for that.... tcpdump no
58 * longer does that, for the same reasons that we don't.)
60 * If we're using an asynchronous DNS resolver, that shouldn't be an issue.
61 * If we're using a synchronous name lookup mechanism (which we'd do mainly
62 * to support resolving addresses and host names using more mechanisms than
63 * just DNS, such as NIS, NBNS, or Mr. Hosts File), we could do that in
64 * a separate thread, making it, in effect, asynchronous.
67 #ifdef HAVE_NETINET_IN_H
68 # include <netinet/in.h>
75 #ifdef HAVE_SYS_SOCKET_H
76 #include <sys/socket.h> /* needed to define AF_ values on UNIX */
79 #ifdef HAVE_WINSOCK2_H
80 #include <winsock2.h> /* needed to define AF_ values on Windows */
84 # include <ws2tcpip.h>
89 # define socklen_t unsigned int
92 # include <ares_version.h>
93 #endif /* HAVE_C_ARES */
98 #include "addr_and_mask.h"
100 #include "addr_resolv.h"
101 #include "wsutil/filesystem.h"
103 #include <wsutil/report_err.h>
104 #include <wsutil/file_util.h>
105 #include <wsutil/pint.h>
106 #include "wsutil/inet_aton.h"
107 #include <wsutil/inet_addr.h>
109 #include <epan/strutil.h>
110 #include <epan/to_str-int.h>
111 #include <epan/prefs.h>
113 #define ENAME_HOSTS "hosts"
114 #define ENAME_SUBNETS "subnets"
115 #define ENAME_ETHERS "ethers"
116 #define ENAME_IPXNETS "ipxnets"
117 #define ENAME_MANUF "manuf"
118 #define ENAME_SERVICES "services"
119 #define ENAME_VLANS "vlans"
120 #define ENAME_SS7PCS "ss7pcs"
122 #define HASHETHSIZE 2048
123 #define HASHHOSTSIZE 2048
124 #define HASHIPXNETSIZE 256
125 #define SUBNETLENGTHSIZE 32 /*1-32 inc.*/
127 /* hash table used for IPv4 lookup */
129 #define HASH_IPV4_ADDRESS(addr) (g_htonl(addr) & (HASHHOSTSIZE - 1))
132 typedef struct sub_net_hashipv4 {
134 guint8 flags; /* B0 dummy_entry, B1 resolve, B2 If the address is used in the trace */
135 struct sub_net_hashipv4 *next;
136 gchar name[MAXNAMELEN];
137 } sub_net_hashipv4_t;
139 /* Array of entries of subnets of different lengths */
141 gsize mask_length; /*1-32*/
142 guint32 mask; /* e.g. 255.255.255.*/
143 sub_net_hashipv4_t** subnet_addresses; /* Hash table of subnet addresses */
144 } subnet_length_entry_t;
147 /* hash table used for IPX network lookup */
149 /* XXX - check goodness of hash function */
151 #define HASH_IPX_NET(net) ((net) & (HASHIPXNETSIZE - 1))
153 typedef struct hashipxnet {
155 struct hashipxnet *next;
156 gchar name[MAXNAMELEN];
159 typedef struct hashvlan {
161 /* struct hashvlan *next; */
162 gchar name[MAXVLANNAMELEN];
165 typedef struct ss7pc {
166 guint32 id; /* 1st byte NI, 3 following bytes: Point Code */
167 gchar pc_addr[MAXNAMELEN];
168 gchar name[MAXNAMELEN];
171 /* hash tables used for ethernet and manufacturer lookup */
172 #define HASHETHER_STATUS_UNRESOLVED 1
173 #define HASHETHER_STATUS_RESOLVED_DUMMY 2
174 #define HASHETHER_STATUS_RESOLVED_NAME 3
177 guint status; /* (See above) */
180 char resolved_name[MAXNAMELEN];
184 guint status; /* (See above) */
187 char resolved_name[MAXNAMELEN];
190 /* internal ethernet type */
191 typedef struct _ether
194 char name[MAXNAMELEN];
197 /* internal ipxnet type */
198 typedef struct _ipxnet
201 char name[MAXNAMELEN];
204 /* internal vlan type */
208 char name[MAXVLANNAMELEN];
211 static wmem_map_t *ipxnet_hash_table = NULL;
212 static wmem_map_t *ipv4_hash_table = NULL;
213 static wmem_map_t *ipv6_hash_table = NULL;
214 static wmem_map_t *vlan_hash_table = NULL;
215 static wmem_map_t *ss7pc_hash_table = NULL;
217 static wmem_list_t *manually_resolved_ipv4_list = NULL;
218 static wmem_list_t *manually_resolved_ipv6_list = NULL;
220 typedef struct _resolved_ipv4
223 char name[MAXNAMELEN];
226 typedef struct _resolved_ipv6
228 struct e_in6_addr ip6_addr;
229 char name[MAXNAMELEN];
232 static addrinfo_lists_t addrinfo_lists = { NULL, NULL};
234 static gchar *cb_service;
235 static port_type cb_proto = PT_NONE;
238 static wmem_map_t *manuf_hashtable = NULL;
239 static wmem_map_t *wka_hashtable = NULL;
240 static wmem_map_t *eth_hashtable = NULL;
241 static wmem_map_t *serv_port_hashtable = NULL;
243 static subnet_length_entry_t subnet_length_entries[SUBNETLENGTHSIZE]; /* Ordered array of entries */
244 static gboolean have_subnet_entry = FALSE;
246 static gboolean new_resolved_objects = FALSE;
248 static GPtrArray* extra_hosts_files = NULL;
250 static hashether_t *add_eth_name(const guint8 *addr, const gchar *name);
251 static void add_serv_port_cb(const guint32 port);
254 /* http://eternallyconfuzzled.com/tuts/algorithms/jsw_tut_hashing.aspx#existing
258 ipv6_oat_hash(gconstpointer key)
261 const unsigned char *p = (const unsigned char *)key;
265 for ( i = 0; i < len; i++ ) {
279 ipv6_equal(gconstpointer v1, gconstpointer v2)
282 if (memcmp(v1, v2, sizeof (struct e_in6_addr)) == 0) {
290 * Flag controlling what names to resolve.
292 e_addr_resolve gbl_resolv_flags = {
294 FALSE, /* network_name */
295 FALSE, /* transport_name */
296 TRUE, /* dns_pkt_addr_resolution */
297 TRUE, /* use_external_net_name_resolver */
298 FALSE, /* load_hosts_file_from_profile_only */
299 FALSE, /* vlan_name */
300 FALSE /* ss7 point code names */
303 static guint name_resolve_concurrency = 500;
307 * Global variables (can be changed in GUI sections)
308 * XXX - they could be changed in GUI code, but there's currently no
309 * GUI code to change them.
312 gchar *g_ethers_path = NULL; /* global ethers file */
313 gchar *g_pethers_path = NULL; /* personal ethers file */
314 gchar *g_ipxnets_path = NULL; /* global ipxnets file */
315 gchar *g_pipxnets_path = NULL; /* personal ipxnets file */
316 gchar *g_services_path = NULL; /* global services file */
317 gchar *g_pservices_path = NULL; /* personal services file */
318 gchar *g_pvlan_path = NULL; /* personal vlans file */
319 gchar *g_ss7pcs_path = NULL; /* personal ss7pcs file */
320 /* first resolving call */
325 * Submitted queries trigger a callback (c_ares_ghba_cb()).
326 * Queries are added to c_ares_queue_head. During processing, queries are
327 * popped off the front of c_ares_queue_head and submitted using
328 * ares_gethostbyaddr().
329 * The callback processes the response, then frees the request.
331 typedef struct _async_dns_queue_msg
335 struct e_in6_addr ip6;
338 } async_dns_queue_msg_t;
340 typedef struct _async_hostent {
346 #if ( ( ARES_VERSION_MAJOR < 1 ) \
347 || ( 1 == ARES_VERSION_MAJOR && ARES_VERSION_MINOR < 5 ) )
348 static void c_ares_ghba_cb(void *arg, int status, struct hostent *hostent);
350 static void c_ares_ghba_cb(void *arg, int status, int timeouts _U_, struct hostent *hostent);
353 ares_channel ghba_chan; /* ares_gethostbyaddr -- Usually non-interactive, no timeout */
354 ares_channel ghbn_chan; /* ares_gethostbyname -- Usually interactive, timeout */
356 static gboolean async_dns_initialized = FALSE;
357 static guint async_dns_in_flight = 0;
358 static wmem_list_t *async_dns_queue_head = NULL;
360 /* push a dns request */
362 add_async_dns_ipv4(int type, guint32 addr)
364 async_dns_queue_msg_t *msg;
366 msg = wmem_new(wmem_epan_scope(), async_dns_queue_msg_t);
368 msg->addr.ip4 = addr;
369 wmem_list_append(async_dns_queue_head, (gpointer) msg);
371 #endif /* HAVE_C_ARES */
376 const gchar* name; /* Shallow copy */
380 * Miscellaneous functions
384 fgetline(char **buf, int *size, FILE *fp)
389 if (fp == NULL || buf == NULL)
396 *buf = (char *)wmem_alloc(wmem_epan_scope(), *size);
406 while ((c = ws_getc_unlocked(fp)) != EOF && c != '\r' && c != '\n') {
407 if (len+1 >= *size) {
408 *buf = (char *)wmem_realloc(wmem_epan_scope(), *buf, *size += BUFSIZ);
413 if (len == 0 && c == EOF)
424 * Local function definitions
426 static subnet_entry_t subnet_lookup(const guint32 addr);
427 static void subnet_entry_set(guint32 subnet_addr, const guint8 mask_length, const gchar* name);
431 add_service_name(port_type proto, const guint port, const char *service_name)
433 serv_port_t *serv_port_table;
436 key = (int *)wmem_new(wmem_epan_scope(), int);
439 serv_port_table = (serv_port_t *)wmem_map_lookup(serv_port_hashtable, &port);
440 if (serv_port_table == NULL) {
441 serv_port_table = wmem_new0(wmem_epan_scope(), serv_port_t);
442 wmem_map_insert(serv_port_hashtable, key, serv_port_table);
445 wmem_free(wmem_epan_scope(), key);
450 wmem_free(wmem_epan_scope(), serv_port_table->tcp_name);
451 serv_port_table->tcp_name = wmem_strdup(wmem_epan_scope(), service_name);
454 wmem_free(wmem_epan_scope(), serv_port_table->udp_name);
455 serv_port_table->udp_name = wmem_strdup(wmem_epan_scope(), service_name);
458 wmem_free(wmem_epan_scope(), serv_port_table->sctp_name);
459 serv_port_table->sctp_name = wmem_strdup(wmem_epan_scope(), service_name);
462 wmem_free(wmem_epan_scope(), serv_port_table->dccp_name);
463 serv_port_table->dccp_name = wmem_strdup(wmem_epan_scope(), service_name);
467 /* Should not happen */
470 new_resolved_objects = TRUE;
475 parse_service_line (char *line)
478 * See the services(4) or services(5) man page for services file format
479 * (not available on all systems).
487 range_t *port_rng = NULL;
488 guint32 max_port = MAX_UDP_PORT;
490 if ((cp = strchr(line, '#')))
493 if ((cp = strtok(line, " \t")) == NULL)
498 if ((cp = strtok(NULL, " \t")) == NULL)
503 if (strtok(cp, "/") == NULL)
506 if ((cp = strtok(NULL, "/")) == NULL)
509 /* seems we got all interesting things from the file */
510 if (strcmp(cp, "tcp") == 0) {
511 max_port = MAX_TCP_PORT;
514 else if (strcmp(cp, "udp") == 0) {
515 max_port = MAX_UDP_PORT;
518 else if (strcmp(cp, "sctp") == 0) {
519 max_port = MAX_SCTP_PORT;
522 else if (strcmp(cp, "dccp") == 0) {
523 max_port = MAX_DCCP_PORT;
529 if (CVT_NO_ERROR != range_convert_str(NULL, &port_rng, port, max_port)) {
530 /* some assertion here? */
531 wmem_free (NULL, port_rng);
535 cb_service = service;
537 range_foreach(port_rng, add_serv_port_cb);
538 wmem_free (NULL, port_rng);
540 } /* parse_service_line */
544 add_serv_port_cb(const guint32 port)
547 add_service_name(cb_proto, port, cb_service);
553 parse_services_file(const char * path)
557 static char *buf = NULL;
559 /* services hash table initialization */
560 serv_p = ws_fopen(path, "r");
565 while (fgetline(&buf, &size, serv_p) >= 0) {
566 parse_service_line(buf);
574 * unsigned integer to ascii
577 wmem_utoa(wmem_allocator_t *allocator, guint port)
579 gchar *bp = (gchar *)wmem_alloc(allocator, MAXNAMELEN);
581 /* XXX, guint32_to_str() ? */
582 guint32_to_str_buf(port, bp, MAXNAMELEN);
587 _serv_name_lookup(port_type proto, guint port, serv_port_t **value_ret)
589 serv_port_t *serv_port_table;
591 serv_port_table = (serv_port_t *)wmem_map_lookup(serv_port_hashtable, &port);
593 if (value_ret != NULL)
594 *value_ret = serv_port_table;
596 if (serv_port_table == NULL)
601 return serv_port_table->udp_name;
603 return serv_port_table->tcp_name;
605 return serv_port_table->sctp_name;
607 return serv_port_table->dccp_name;
615 try_serv_name_lookup(port_type proto, guint port)
617 return _serv_name_lookup(proto, port, NULL);
621 serv_name_lookup(port_type proto, guint port)
623 serv_port_t *serv_port_table = NULL;
627 name = _serv_name_lookup(proto, port, &serv_port_table);
631 if (serv_port_table == NULL) {
632 key = (guint *)wmem_new(wmem_epan_scope(), guint);
634 serv_port_table = wmem_new0(wmem_epan_scope(), serv_port_t);
635 wmem_map_insert(serv_port_hashtable, key, serv_port_table);
637 if (serv_port_table->numeric == NULL) {
638 serv_port_table->numeric = wmem_strdup_printf(wmem_epan_scope(), "%u", port);
641 return serv_port_table->numeric;
645 initialize_services(void)
647 gboolean parse_file = TRUE;
648 g_assert(serv_port_hashtable == NULL);
649 serv_port_hashtable = wmem_map_new(wmem_epan_scope(), g_int_hash, g_int_equal);
651 /* Compute the pathname of the services file. */
652 if (g_services_path == NULL) {
653 g_services_path = get_datafile_path(ENAME_SERVICES);
655 parse_services_file(g_services_path);
657 /* Compute the pathname of the personal services file */
658 if (g_pservices_path == NULL) {
659 /* Check profile directory before personal configuration */
660 g_pservices_path = get_persconffile_path(ENAME_SERVICES, TRUE);
661 if (!parse_services_file(g_pservices_path)) {
662 g_pservices_path = get_persconffile_path(ENAME_SERVICES, FALSE);
668 parse_services_file(g_pservices_path);
673 service_name_lookup_cleanup(void)
675 serv_port_hashtable = NULL;
676 g_free(g_services_path);
677 g_services_path = NULL;
678 g_free(g_pservices_path);
679 g_pservices_path = NULL;
682 /* Fill in an IP4 structure with info from subnets file or just with the
683 * string form of the address.
686 fill_dummy_ip4(const guint addr, hashipv4_t* volatile tp)
688 subnet_entry_t subnet_entry;
690 if (tp->flags & DUMMY_ADDRESS_ENTRY)
691 return; /* already done */
693 tp->flags |= DUMMY_ADDRESS_ENTRY; /* Overwrite if we get async DNS reply */
695 /* Do we have a subnet for this address? */
696 subnet_entry = subnet_lookup(addr);
697 if (0 != subnet_entry.mask) {
698 /* Print name, then '.' then IP address after subnet mask */
700 gchar buffer[MAX_IP_STR_LEN];
704 host_addr = addr & (~(guint32)subnet_entry.mask);
705 ip_to_str_buf((guint8 *)&host_addr, buffer, MAX_IP_STR_LEN);
708 /* Skip to first octet that is not totally masked
709 * If length of mask is 32, we chomp the whole address.
710 * If the address string starts '.' (should not happen?),
713 i = subnet_entry.mask_length / 8;
714 while(*(paddr) != '\0' && i > 0) {
715 if (*(++paddr) == '.') {
720 /* There are more efficient ways to do this, but this is safe if we
721 * trust g_snprintf and MAXNAMELEN
723 g_snprintf(tp->name, MAXNAMELEN, "%s%s", subnet_entry.name, paddr);
725 ip_to_str_buf((const guint8 *)&addr, tp->name, MAXNAMELEN);
730 /* Fill in an IP6 structure with the string form of the address.
733 fill_dummy_ip6(hashipv6_t* volatile tp)
735 if (tp->flags & DUMMY_ADDRESS_ENTRY)
736 return; /* already done */
738 tp->flags |= DUMMY_ADDRESS_ENTRY; /* Overwrite if we get async DNS reply */
739 g_strlcpy(tp->name, tp->ip6, MAXNAMELEN);
748 #if ( ( ARES_VERSION_MAJOR < 1 ) \
749 || ( 1 == ARES_VERSION_MAJOR && ARES_VERSION_MINOR < 5 ) )
757 async_dns_queue_msg_t *caqm = (async_dns_queue_msg_t *)arg;
761 /* XXX, what to do if async_dns_in_flight == 0? */
762 async_dns_in_flight--;
764 if (status == ARES_SUCCESS) {
765 for (p = he->h_addr_list; *p != NULL; p++) {
766 switch(caqm->family) {
768 add_ipv4_name(caqm->addr.ip4, he->h_name);
771 add_ipv6_name(&caqm->addr.ip6, he->h_name);
774 /* Throw an exception? */
779 wmem_free(wmem_epan_scope(), caqm);
781 #endif /* HAVE_C_ARES */
783 /* --------------- */
785 new_ipv4(const guint addr)
787 hashipv4_t *tp = wmem_new(wmem_epan_scope(), hashipv4_t);
791 ip_to_str_buf((const guint8 *)&addr, tp->ip, sizeof(tp->ip));
796 host_lookup(const guint addr)
798 hashipv4_t * volatile tp;
800 tp = (hashipv4_t *)wmem_map_lookup(ipv4_hash_table, GUINT_TO_POINTER(addr));
803 * We don't already have an entry for this host name; create one,
804 * and then try to resolve it.
807 wmem_map_insert(ipv4_hash_table, GUINT_TO_POINTER(addr), tp);
808 } else if ((tp->flags & DUMMY_AND_RESOLVE_FLGS) != DUMMY_ADDRESS_ENTRY) {
813 * This hasn't been resolved yet, and we haven't tried to
814 * resolve it already.
817 fill_dummy_ip4(addr, tp);
818 if (!gbl_resolv_flags.network_name)
821 if (gbl_resolv_flags.use_external_net_name_resolver) {
822 tp->flags |= TRIED_RESOLVE_ADDRESS;
825 if (async_dns_initialized && name_resolve_concurrency > 0) {
826 add_async_dns_ipv4(AF_INET, addr);
835 /* --------------- */
837 new_ipv6(const struct e_in6_addr *addr)
839 hashipv6_t *tp = wmem_new(wmem_epan_scope(), hashipv6_t);
840 memcpy(tp->addr, addr->bytes, sizeof tp->addr);
843 ip6_to_str_buf(addr, tp->ip6, sizeof(tp->ip6));
847 /* ------------------------------------ */
849 host_lookup6(const struct e_in6_addr *addr)
851 hashipv6_t * volatile tp;
853 async_dns_queue_msg_t *caqm;
856 tp = (hashipv6_t *)wmem_map_lookup(ipv6_hash_table, addr);
859 * We don't already have an entry for this host name; create one,
860 * and then try to resolve it.
862 struct e_in6_addr *addr_key;
864 addr_key = wmem_new(wmem_epan_scope(), struct e_in6_addr);
866 memcpy(addr_key, addr, 16);
867 wmem_map_insert(ipv6_hash_table, addr_key, tp);
868 } else if ((tp->flags & DUMMY_AND_RESOLVE_FLGS) != DUMMY_ADDRESS_ENTRY) {
873 * This hasn't been resolved yet, and we haven't tried to
874 * resolve it already.
878 if (!gbl_resolv_flags.network_name)
881 if (gbl_resolv_flags.use_external_net_name_resolver) {
882 tp->flags |= TRIED_RESOLVE_ADDRESS;
884 if (async_dns_initialized && name_resolve_concurrency > 0) {
885 caqm = wmem_new(wmem_epan_scope(), async_dns_queue_msg_t);
886 caqm->family = AF_INET6;
887 memcpy(&caqm->addr.ip6, addr, sizeof(caqm->addr.ip6));
888 wmem_list_append(async_dns_queue_head, (gpointer) caqm);
898 * Ethernet / manufacturer resolution
900 * The following functions implement ethernet address resolution and
901 * ethers files parsing (see ethers(4)).
903 * The manuf file has the same format as ethers(4) except that names are
904 * truncated to MAXMANUFLEN-1 (8) characters and that an address contains
905 * only 3 bytes (instead of 6).
909 * I decide to not use the existing functions (see ethers(3) on some
910 * operating systems) for the following reasons:
911 * - performance gains (use of hash tables and some other enhancements),
912 * - use of two ethers files (system-wide and per user),
913 * - avoid the use of NIS maps,
914 * - lack of these functions on some systems.
916 * So the following functions do _not_ behave as the standard ones.
923 * If "manuf_file" is FALSE, parse a 6-byte MAC address.
924 * If "manuf_file" is TRUE, parse an up-to-6-byte sequence with an optional
928 parse_ether_address(const char *cp, ether_t *eth, unsigned int *mask,
929 const gboolean manuf_file)
936 for (i = 0; i < 6; i++) {
937 /* Get a hex number, 1 or 2 digits, no sign characters allowed. */
938 if (!g_ascii_isxdigit(*cp))
940 num = strtoul(cp, &p, 16);
942 return FALSE; /* failed */
944 return FALSE; /* not a valid octet */
945 eth->addr[i] = (guint8) num;
946 cp = p; /* skip past the number */
948 /* OK, what character terminated the octet? */
950 /* "/" - this has a mask. */
952 /* Entries with masks are allowed only in the "manuf" files. */
955 cp++; /* skip past the '/' to get to the mask */
956 if (!g_ascii_isdigit(*cp))
957 return FALSE; /* no sign allowed */
958 num = strtoul(cp, &p, 10);
960 return FALSE; /* failed */
961 cp = p; /* skip past the number */
962 if (*cp != '\0' && !g_ascii_isspace(*cp))
963 return FALSE; /* bogus terminator */
964 if (num == 0 || num >= 48)
965 return FALSE; /* bogus mask */
966 /* Mask out the bits not covered by the mask */
968 for (i = 0; num >= 8; i++, num -= 8)
969 ; /* skip octets entirely covered by the mask */
970 /* Mask out the first masked octet */
971 eth->addr[i] &= (0xFF << (8 - num));
973 /* Mask out completely-masked-out octets */
979 /* We're at the end of the address, and there's no mask. */
981 /* We got 3 bytes, so this is a manufacturer ID. */
983 /* Manufacturer IDs are only allowed in the "manuf"
987 /* Indicate that this is a manufacturer ID (0 is not allowed
994 /* We got 6 bytes, so this is a MAC address.
995 If we're reading one of the "manuf" files, indicate that
996 this is a MAC address (48 is not allowed as a mask). */
1002 /* We didn't get 3 or 6 bytes, and there's no mask; this is
1007 /* We don't know the separator used in this number; it can either
1008 be ':', '-', or '.'. */
1009 if (*cp != ':' && *cp != '-' && *cp != '.')
1011 sep = *cp; /* subsequent separators must be the same */
1013 /* It has to be the same as the first separator */
1025 parse_ether_line(char *line, ether_t *eth, unsigned int *mask,
1026 const gboolean manuf_file)
1029 * See the ethers(4) or ethers(5) man page for ethers file format
1030 * (not available on all systems).
1031 * We allow both ethernet address separators (':' and '-'),
1032 * as well as Wireshark's '.' separator.
1037 if ((cp = strchr(line, '#')))
1040 if ((cp = strtok(line, " \t")) == NULL)
1043 if (!parse_ether_address(cp, eth, mask, manuf_file))
1046 if ((cp = strtok(NULL, " \t")) == NULL)
1049 g_strlcpy(eth->name, cp, MAXNAMELEN);
1053 } /* parse_ether_line */
1055 static FILE *eth_p = NULL;
1058 set_ethent(char *path)
1063 eth_p = ws_fopen(path, "r");
1076 get_ethent(unsigned int *mask, const gboolean manuf_file)
1080 static int size = 0;
1081 static char *buf = NULL;
1086 while (fgetline(&buf, &size, eth_p) >= 0) {
1087 if (parse_ether_line(buf, ð, mask, manuf_file) == 0) {
1098 get_ethbyname(const gchar *name)
1102 set_ethent(g_pethers_path);
1104 while (((eth = get_ethent(NULL, FALSE)) != NULL) && strncmp(name, eth->name, MAXNAMELEN) != 0)
1110 set_ethent(g_ethers_path);
1112 while (((eth = get_ethent(NULL, FALSE)) != NULL) && strncmp(name, eth->name, MAXNAMELEN) != 0)
1120 } /* get_ethbyname */
1124 get_ethbyaddr(const guint8 *addr)
1129 set_ethent(g_pethers_path);
1131 while (((eth = get_ethent(NULL, FALSE)) != NULL) && memcmp(addr, eth->addr, 6) != 0)
1137 set_ethent(g_ethers_path);
1139 while (((eth = get_ethent(NULL, FALSE)) != NULL) && memcmp(addr, eth->addr, 6) != 0)
1147 } /* get_ethbyaddr */
1149 static hashmanuf_t *
1150 manuf_hash_new_entry(const guint8 *addr, char* name)
1153 hashmanuf_t *manuf_value;
1156 /* manuf needs only the 3 most significant octets of the ethernet address */
1157 manuf_key = (int *)wmem_new(wmem_epan_scope(), int);
1158 *manuf_key = (int)((addr[0] << 16) + (addr[1] << 8) + addr[2]);
1159 manuf_value = wmem_new(wmem_epan_scope(), hashmanuf_t);
1161 memcpy(manuf_value->addr, addr, 3);
1163 g_strlcpy(manuf_value->resolved_name, name, MAXNAMELEN);
1164 manuf_value->status = HASHETHER_STATUS_RESOLVED_NAME;
1167 manuf_value->status = HASHETHER_STATUS_UNRESOLVED;
1168 manuf_value->resolved_name[0] = '\0';
1170 /* Values returned by bytes_to_hexstr_punct() are *not* null-terminated */
1171 endp = bytes_to_hexstr_punct(manuf_value->hexaddr, addr, sizeof(manuf_value->addr), ':');
1174 wmem_map_insert(manuf_hashtable, manuf_key, manuf_value);
1179 wka_hash_new_entry(const guint8 *addr, char* name)
1183 wka_key = (guint8 *)wmem_alloc(wmem_epan_scope(), 6);
1184 memcpy(wka_key, addr, 6);
1186 wmem_map_insert(wka_hashtable, wka_key, wmem_strdup(wmem_epan_scope(), name));
1190 add_manuf_name(const guint8 *addr, unsigned int mask, gchar *name)
1195 /* This is a manufacturer ID; add it to the manufacturer ID hash table */
1196 manuf_hash_new_entry(addr, name);
1200 /* This is a well-known MAC address; add it to the Ethernet hash table */
1201 add_eth_name(addr, name);
1205 /* This is a range of well-known addresses; add it to the well-known-address table */
1206 wka_hash_new_entry(addr, name);
1209 } /* add_manuf_name */
1211 static hashmanuf_t *
1212 manuf_name_lookup(const guint8 *addr)
1214 gint32 manuf_key = 0;
1216 hashmanuf_t *manuf_value;
1218 /* manuf needs only the 3 most significant octets of the ethernet address */
1219 manuf_key = addr[0];
1220 manuf_key = manuf_key<<8;
1222 manuf_key = manuf_key | oct;
1223 manuf_key = manuf_key<<8;
1225 manuf_key = manuf_key | oct;
1228 /* first try to find a "perfect match" */
1229 manuf_value = (hashmanuf_t*)wmem_map_lookup(manuf_hashtable, &manuf_key);
1230 if (manuf_value != NULL) {
1234 /* Mask out the broadcast/multicast flag but not the locally
1235 * administered flag as locally administered means: not assigned
1236 * by the IEEE but the local administrator instead.
1237 * 0x01 multicast / broadcast bit
1238 * 0x02 locally administered bit */
1239 if ((manuf_key & 0x00010000) != 0) {
1240 manuf_key &= 0x00FEFFFF;
1241 manuf_value = (hashmanuf_t*)wmem_map_lookup(manuf_hashtable, &manuf_key);
1242 if (manuf_value != NULL) {
1247 /* Add the address as a hex string */
1248 return manuf_hash_new_entry(addr, NULL);
1250 } /* manuf_name_lookup */
1253 wka_name_lookup(const guint8 *addr, const unsigned int mask)
1255 guint8 masked_addr[6];
1260 if (wka_hashtable == NULL) {
1263 /* Get the part of the address covered by the mask. */
1264 for (i = 0, num = mask; num >= 8; i++, num -= 8)
1265 masked_addr[i] = addr[i]; /* copy octets entirely covered by the mask */
1266 /* Mask out the first masked octet */
1267 masked_addr[i] = addr[i] & (0xFF << (8 - num));
1269 /* Zero out completely-masked-out octets */
1273 name = (gchar *)wmem_map_lookup(wka_hashtable, masked_addr);
1277 } /* wka_name_lookup */
1280 guint get_hash_ether_status(hashether_t* ether)
1282 return ether->status;
1285 char* get_hash_ether_hexaddr(hashether_t* ether)
1287 return ether->hexaddr;
1290 char* get_hash_ether_resolved_name(hashether_t* ether)
1292 return ether->resolved_name;
1296 eth_addr_hash(gconstpointer key)
1298 return wmem_strong_hash((const guint8 *)key, 6);
1302 eth_addr_cmp(gconstpointer a, gconstpointer b)
1304 return (memcmp(a, b, 6) == 0);
1308 initialize_ethers(void)
1314 /* hash table initialization */
1315 wka_hashtable = wmem_map_new(wmem_epan_scope(), eth_addr_hash, eth_addr_cmp);
1316 manuf_hashtable = wmem_map_new(wmem_epan_scope(), g_int_hash, g_int_equal);
1317 eth_hashtable = wmem_map_new(wmem_epan_scope(), eth_addr_hash, eth_addr_cmp);
1319 /* Compute the pathname of the ethers file. */
1320 if (g_ethers_path == NULL) {
1321 g_ethers_path = wmem_strdup_printf(wmem_epan_scope(), "%s" G_DIR_SEPARATOR_S "%s",
1322 get_systemfile_dir(), ENAME_ETHERS);
1325 /* Set g_pethers_path here, but don't actually do anything
1326 * with it. It's used in get_ethbyname() and get_ethbyaddr()
1328 if (g_pethers_path == NULL)
1329 g_pethers_path = get_persconffile_path(ENAME_ETHERS, FALSE);
1331 /* Compute the pathname of the manuf file */
1332 manuf_path = get_datafile_path(ENAME_MANUF);
1334 /* Read it and initialize the hash table */
1335 set_ethent(manuf_path);
1337 while ((eth = get_ethent(&mask, TRUE))) {
1338 add_manuf_name(eth->addr, mask, eth->name);
1345 } /* initialize_ethers */
1348 ethers_cleanup(void)
1350 g_free(g_pethers_path);
1351 g_pethers_path = NULL;
1354 /* Resolve ethernet address */
1355 static hashether_t *
1356 eth_addr_resolve(hashether_t *tp) {
1358 hashmanuf_t *manuf_value;
1359 const guint8 *addr = tp->addr;
1361 if ( (eth = get_ethbyaddr(addr)) != NULL) {
1362 g_strlcpy(tp->resolved_name, eth->name, MAXNAMELEN);
1363 tp->status = HASHETHER_STATUS_RESOLVED_NAME;
1370 /* Unknown name. Try looking for it in the well-known-address
1371 tables for well-known address ranges smaller than 2^24. */
1374 /* Only the topmost 5 bytes participate fully */
1375 if ((name = wka_name_lookup(addr, mask+40)) != NULL) {
1376 g_snprintf(tp->resolved_name, MAXNAMELEN, "%s_%02x",
1377 name, addr[5] & (0xFF >> mask));
1378 tp->status = HASHETHER_STATUS_RESOLVED_DUMMY;
1385 /* Only the topmost 4 bytes participate fully */
1386 if ((name = wka_name_lookup(addr, mask+32)) != NULL) {
1387 g_snprintf(tp->resolved_name, MAXNAMELEN, "%s_%02x:%02x",
1388 name, addr[4] & (0xFF >> mask), addr[5]);
1389 tp->status = HASHETHER_STATUS_RESOLVED_DUMMY;
1396 /* Only the topmost 3 bytes participate fully */
1397 if ((name = wka_name_lookup(addr, mask+24)) != NULL) {
1398 g_snprintf(tp->resolved_name, MAXNAMELEN, "%s_%02x:%02x:%02x",
1399 name, addr[3] & (0xFF >> mask), addr[4], addr[5]);
1400 tp->status = HASHETHER_STATUS_RESOLVED_DUMMY;
1405 /* Now try looking in the manufacturer table. */
1406 manuf_value = manuf_name_lookup(addr);
1407 if ((manuf_value != NULL) && (manuf_value->status != HASHETHER_STATUS_UNRESOLVED)) {
1408 g_snprintf(tp->resolved_name, MAXNAMELEN, "%s_%02x:%02x:%02x",
1409 manuf_value->resolved_name, addr[3], addr[4], addr[5]);
1410 tp->status = HASHETHER_STATUS_RESOLVED_DUMMY;
1414 /* Now try looking for it in the well-known-address
1415 tables for well-known address ranges larger than 2^24. */
1418 /* Only the topmost 2 bytes participate fully */
1419 if ((name = wka_name_lookup(addr, mask+16)) != NULL) {
1420 g_snprintf(tp->resolved_name, MAXNAMELEN, "%s_%02x:%02x:%02x:%02x",
1421 name, addr[2] & (0xFF >> mask), addr[3], addr[4],
1423 tp->status = HASHETHER_STATUS_RESOLVED_DUMMY;
1430 /* Only the topmost byte participates fully */
1431 if ((name = wka_name_lookup(addr, mask+8)) != NULL) {
1432 g_snprintf(tp->resolved_name, MAXNAMELEN, "%s_%02x:%02x:%02x:%02x:%02x",
1433 name, addr[1] & (0xFF >> mask), addr[2], addr[3],
1435 tp->status = HASHETHER_STATUS_RESOLVED_DUMMY;
1442 /* Not even the topmost byte participates fully */
1443 if ((name = wka_name_lookup(addr, mask)) != NULL) {
1444 g_snprintf(tp->resolved_name, MAXNAMELEN, "%s_%02x:%02x:%02x:%02x:%02x:%02x",
1445 name, addr[0] & (0xFF >> mask), addr[1], addr[2],
1446 addr[3], addr[4], addr[5]);
1447 tp->status = HASHETHER_STATUS_RESOLVED_DUMMY;
1450 } while (--mask); /* Work down to the last bit */
1452 /* No match whatsoever. */
1453 set_address(ðer_addr, AT_ETHER, 6, addr);
1454 address_to_str_buf(ðer_addr, tp->resolved_name, MAXNAMELEN);
1455 tp->status = HASHETHER_STATUS_RESOLVED_DUMMY;
1458 g_assert_not_reached();
1459 } /* eth_addr_resolve */
1461 static hashether_t *
1462 eth_hash_new_entry(const guint8 *addr, const gboolean resolve)
1467 tp = wmem_new(wmem_epan_scope(), hashether_t);
1468 memcpy(tp->addr, addr, sizeof(tp->addr));
1469 tp->status = HASHETHER_STATUS_UNRESOLVED;
1470 /* Values returned by bytes_to_hexstr_punct() are *not* null-terminated */
1471 endp = bytes_to_hexstr_punct(tp->hexaddr, addr, sizeof(tp->addr), ':');
1473 tp->resolved_name[0] = '\0';
1476 eth_addr_resolve(tp);
1478 wmem_map_insert(eth_hashtable, tp->addr, tp);
1481 } /* eth_hash_new_entry */
1483 static hashether_t *
1484 add_eth_name(const guint8 *addr, const gchar *name)
1488 tp = (hashether_t *)wmem_map_lookup(eth_hashtable, addr);
1491 tp = eth_hash_new_entry(addr, FALSE);
1494 if (strcmp(tp->resolved_name, name) != 0) {
1495 g_strlcpy(tp->resolved_name, name, MAXNAMELEN);
1496 tp->status = HASHETHER_STATUS_RESOLVED_NAME;
1497 new_resolved_objects = TRUE;
1501 } /* add_eth_name */
1503 static hashether_t *
1504 eth_name_lookup(const guint8 *addr, const gboolean resolve)
1508 tp = (hashether_t *)wmem_map_lookup(eth_hashtable, addr);
1511 tp = eth_hash_new_entry(addr, resolve);
1513 if (resolve && (tp->status == HASHETHER_STATUS_UNRESOLVED)) {
1514 eth_addr_resolve(tp); /* Found but needs to be resolved */
1520 } /* eth_name_lookup */
1523 eth_addr_lookup(const gchar *name _U_)
1526 /* XXX Do we need reverse lookup??? */
1529 hashether_t **table = eth_table;
1532 /* to be optimized (hash table from name to addr) */
1533 for (i = 0; i < HASHETHSIZE; i++) {
1536 if (strcmp(tp->resolved_name, name) == 0)
1542 /* not in hash table : performs a file lookup */
1544 if ((eth = get_ethbyname(name)) == NULL)
1547 /* add new entry in hash table */
1549 tp = add_eth_name(eth->addr, name);
1555 } /* eth_addr_lookup */
1560 parse_ipxnets_line(char *line, ipxnet_t *ipxnet)
1563 * We allow three address separators (':', '-', and '.'),
1564 * as well as no separators
1568 guint32 a, a0, a1, a2, a3;
1569 gboolean found_single_number = FALSE;
1571 if ((cp = strchr(line, '#')))
1574 if ((cp = strtok(line, " \t\n")) == NULL)
1577 /* Either fill a0,a1,a2,a3 and found_single_number is FALSE,
1578 * fill a and found_single_number is TRUE,
1581 if (sscanf(cp, "%x:%x:%x:%x", &a0, &a1, &a2, &a3) != 4) {
1582 if (sscanf(cp, "%x-%x-%x-%x", &a0, &a1, &a2, &a3) != 4) {
1583 if (sscanf(cp, "%x.%x.%x.%x", &a0, &a1, &a2, &a3) != 4) {
1584 if (sscanf(cp, "%x", &a) == 1) {
1585 found_single_number = TRUE;
1594 if ((cp = strtok(NULL, " \t\n")) == NULL)
1597 if (found_single_number) {
1601 ipxnet->addr = (a0 << 24) | (a1 << 16) | (a2 << 8) | a3;
1604 g_strlcpy(ipxnet->name, cp, MAXNAMELEN);
1608 } /* parse_ipxnets_line */
1610 static FILE *ipxnet_p = NULL;
1613 set_ipxnetent(char *path)
1618 ipxnet_p = ws_fopen(path, "r");
1634 static ipxnet_t ipxnet;
1635 static int size = 0;
1636 static char *buf = NULL;
1638 if (ipxnet_p == NULL)
1641 while (fgetline(&buf, &size, ipxnet_p) >= 0) {
1642 if (parse_ipxnets_line(buf, &ipxnet) == 0) {
1649 } /* get_ipxnetent */
1654 get_ipxnetbyname(const gchar *name)
1658 set_ipxnetent(g_ipxnets_path);
1660 while (((ipxnet = get_ipxnetent()) != NULL) && strncmp(name, ipxnet->name, MAXNAMELEN) != 0)
1663 if (ipxnet == NULL) {
1666 set_ipxnetent(g_pipxnets_path);
1668 while (((ipxnet = get_ipxnetent()) != NULL) && strncmp(name, ipxnet->name, MAXNAMELEN) != 0)
1676 } /* get_ipxnetbyname */
1680 get_ipxnetbyaddr(guint32 addr)
1684 set_ipxnetent(g_ipxnets_path);
1686 while (((ipxnet = get_ipxnetent()) != NULL) && (addr != ipxnet->addr) ) ;
1688 if (ipxnet == NULL) {
1691 set_ipxnetent(g_pipxnets_path);
1693 while (((ipxnet = get_ipxnetent()) != NULL) && (addr != ipxnet->addr) )
1701 } /* get_ipxnetbyaddr */
1704 initialize_ipxnets(void)
1706 /* Compute the pathname of the ipxnets file.
1708 * XXX - is there a notion of an "ipxnets file" in any flavor of
1709 * UNIX, or with any add-on Netware package for UNIX? If not,
1710 * should the UNIX version of the ipxnets file be in the datafile
1711 * directory as well?
1713 if (g_ipxnets_path == NULL) {
1714 g_ipxnets_path = wmem_strdup_printf(wmem_epan_scope(), "%s" G_DIR_SEPARATOR_S "%s",
1715 get_systemfile_dir(), ENAME_IPXNETS);
1718 /* Set g_pipxnets_path here, but don't actually do anything
1719 * with it. It's used in get_ipxnetbyname() and get_ipxnetbyaddr()
1721 if (g_pipxnets_path == NULL)
1722 g_pipxnets_path = get_persconffile_path(ENAME_IPXNETS, FALSE);
1724 } /* initialize_ipxnets */
1727 ipx_name_lookup_cleanup(void)
1729 ipxnet_hash_table = NULL;
1730 g_free(g_pipxnets_path);
1731 g_pipxnets_path = NULL;
1735 static hashipxnet_t *
1736 add_ipxnet_name(guint addr, const gchar *name)
1740 tp = (hashipxnet_t *)g_hash_table_lookup(ipxnet_hash_table, &addr);
1742 g_strlcpy(tp->name, name, MAXNAMELEN);
1746 key = (int *)g_new(int, 1);
1748 tp = g_new(hashipxnet_t,1);
1749 g_strlcpy(tp->name, name, MAXNAMELEN);
1750 g_hash_table_insert(ipxnet_hash_table, key, tp);
1754 g_strlcpy(tp->name, name, MAXNAMELEN);
1756 new_resolved_objects = TRUE;
1760 } /* add_ipxnet_name */
1764 ipxnet_name_lookup(wmem_allocator_t *allocator, const guint addr)
1769 tp = (hashipxnet_t *)wmem_map_lookup(ipxnet_hash_table, &addr);
1773 key = (int *)wmem_new(wmem_epan_scope(), int);
1775 tp = wmem_new(wmem_epan_scope(), hashipxnet_t);
1776 wmem_map_insert(ipxnet_hash_table, key, tp);
1778 return wmem_strdup(allocator, tp->name);
1781 /* fill in a new entry */
1785 if ( (ipxnet = get_ipxnetbyaddr(addr)) == NULL) {
1787 g_snprintf(tp->name, MAXNAMELEN, "%X", addr);
1790 g_strlcpy(tp->name, ipxnet->name, MAXNAMELEN);
1793 return wmem_strdup(allocator, tp->name);
1795 } /* ipxnet_name_lookup */
1798 ipxnet_addr_lookup(const gchar *name _U_, gboolean *success)
1803 /* XXX Do we need reverse lookup??? */
1806 hashipxnet_t **table = ipxnet_table;
1809 /* to be optimized (hash table from name to addr) */
1810 for (i = 0; i < HASHIPXNETSIZE; i++) {
1813 if (strcmp(tp->name, name) == 0) {
1821 /* not in hash table : performs a file lookup */
1823 if ((ipxnet = get_ipxnetbyname(name)) == NULL) {
1828 /* add new entry in hash table */
1830 tp = add_ipxnet_name(ipxnet->addr, name);
1835 } /* ipxnet_addr_lookup */
1839 parse_vlan_line(char *line, vlan_t *vlan)
1844 if ((cp = strchr(line, '#')))
1847 if ((cp = strtok(line, " \t\n")) == NULL)
1850 if (sscanf(cp, "%" G_GUINT16_FORMAT, &id) == 1) {
1857 if ((cp = strtok(NULL, "\t\n")) == NULL)
1860 g_strlcpy(vlan->name, cp, MAXVLANNAMELEN);
1864 } /* parse_vlan_line */
1866 static FILE *vlan_p = NULL;
1869 set_vlanent(char *path)
1874 vlan_p = ws_fopen(path, "r");
1891 static int size = 0;
1892 static char *buf = NULL;
1897 while (fgetline(&buf, &size, vlan_p) >= 0) {
1898 if (parse_vlan_line(buf, &vlan) == 0) {
1908 get_vlannamebyid(guint16 id)
1912 set_vlanent(g_pvlan_path);
1914 while (((vlan = get_vlanent()) != NULL) && (id != vlan->id) ) ;
1923 } /* get_vlannamebyid */
1926 initialize_vlans(void)
1928 g_assert(vlan_hash_table == NULL);
1929 vlan_hash_table = wmem_map_new(wmem_epan_scope(), g_int_hash, g_int_equal);
1931 /* Set g_pvlan_path here, but don't actually do anything
1932 * with it. It's used in get_vlannamebyid()
1934 if (g_pvlan_path == NULL)
1935 g_pvlan_path = get_persconffile_path(ENAME_VLANS, FALSE);
1937 } /* initialize_vlans */
1940 vlan_name_lookup_cleanup(void)
1942 vlan_hash_table = NULL;
1943 g_free(g_pvlan_path);
1944 g_pvlan_path = NULL;
1947 static const gchar *
1948 vlan_name_lookup(const guint id)
1953 tp = (hashvlan_t *)wmem_map_lookup(vlan_hash_table, &id);
1957 key = (int *)wmem_new(wmem_epan_scope(), int);
1959 tp = wmem_new(wmem_epan_scope(), hashvlan_t);
1960 wmem_map_insert(vlan_hash_table, key, tp);
1965 /* fill in a new entry */
1969 if ( (vlan = get_vlannamebyid(id)) == NULL) {
1971 g_snprintf(tp->name, MAXVLANNAMELEN, "<%u>", id);
1974 g_strlcpy(tp->name, vlan->name, MAXVLANNAMELEN);
1979 } /* vlan_name_lookup */
1983 read_hosts_file (const char *hostspath, gboolean store_entries)
1991 struct e_in6_addr ip6_addr;
1993 gboolean is_ipv6, entry_found = FALSE;
1996 * See the hosts(4) or hosts(5) man page for hosts file format
1997 * (not available on all systems).
1999 if ((hf = ws_fopen(hostspath, "r")) == NULL)
2002 while (fgetline(&line, &size, hf) >= 0) {
2003 if ((cp = strchr(line, '#')))
2006 if ((cp = strtok(line, " \t")) == NULL)
2007 continue; /* no tokens in the line */
2009 if (ws_inet_pton6(cp, &host_addr.ip6_addr)) {
2012 } else if (ws_inet_pton4(cp, &host_addr.ip4_addr)) {
2019 if ((cp = strtok(NULL, " \t")) == NULL)
2020 continue; /* no host name */
2023 if (store_entries) {
2025 add_ipv6_name(&host_addr.ip6_addr, cp);
2027 add_ipv4_name(host_addr.ip4_addr, cp);
2031 wmem_free(wmem_epan_scope(), line);
2034 return entry_found ? TRUE : FALSE;
2035 } /* read_hosts_file */
2038 add_hosts_file (const char *hosts_file)
2040 gboolean found = FALSE;
2046 if (!extra_hosts_files)
2047 extra_hosts_files = g_ptr_array_new();
2049 for (i = 0; i < extra_hosts_files->len; i++) {
2050 if (strcmp(hosts_file, (const char *) g_ptr_array_index(extra_hosts_files, i)) == 0)
2055 g_ptr_array_add(extra_hosts_files, wmem_strdup(wmem_epan_scope(), hosts_file));
2056 return read_hosts_file (hosts_file, FALSE);
2062 add_ip_name_from_string (const char *addr, const char *name)
2066 struct e_in6_addr ip6_addr;
2069 resolved_ipv4_t *resolved_ipv4_entry;
2070 resolved_ipv6_t *resolved_ipv6_entry;
2072 if (ws_inet_pton6(addr, &host_addr.ip6_addr)) {
2074 } else if (ws_inet_pton4(addr, &host_addr.ip4_addr)) {
2081 resolved_ipv6_entry = wmem_new(wmem_epan_scope(), resolved_ipv6_t);
2082 memcpy(&(resolved_ipv6_entry->ip6_addr), &host_addr.ip6_addr, 16);
2083 g_strlcpy(resolved_ipv6_entry->name, name, MAXNAMELEN);
2084 wmem_list_prepend(manually_resolved_ipv6_list, resolved_ipv6_entry);
2086 resolved_ipv4_entry = wmem_new(wmem_epan_scope(), resolved_ipv4_t);
2087 resolved_ipv4_entry->host_addr = host_addr.ip4_addr;
2088 g_strlcpy(resolved_ipv4_entry->name, name, MAXNAMELEN);
2089 wmem_list_prepend(manually_resolved_ipv4_list, resolved_ipv4_entry);
2093 } /* add_ip_name_from_string */
2096 * Add the resolved addresses that are in use to the list used to create the NRB
2099 ipv4_hash_table_resolved_to_list(gpointer key _U_, gpointer value, gpointer user_data)
2101 addrinfo_lists_t *lists = (addrinfo_lists_t*)user_data;
2102 hashipv4_t *ipv4_hash_table_entry = (hashipv4_t *)value;
2104 if ((ipv4_hash_table_entry->flags & USED_AND_RESOLVED_MASK) == RESOLVED_ADDRESS_USED) {
2105 lists->ipv4_addr_list = g_list_prepend(lists->ipv4_addr_list, ipv4_hash_table_entry);
2111 * Add the resolved addresses that are in use to the list used to create the NRB
2115 ipv6_hash_table_resolved_to_list(gpointer key _U_, gpointer value, gpointer user_data)
2117 addrinfo_lists_t *lists = (addrinfo_lists_t*)user_data;
2118 hashipv6_t *ipv6_hash_table_entry = (hashipv6_t *)value;
2120 if ((ipv6_hash_table_entry->flags & USED_AND_RESOLVED_MASK) == RESOLVED_ADDRESS_USED) {
2121 lists->ipv6_addr_list = g_list_prepend (lists->ipv6_addr_list, ipv6_hash_table_entry);
2127 get_addrinfo_list(void)
2129 if (ipv4_hash_table) {
2130 wmem_map_foreach(ipv4_hash_table, ipv4_hash_table_resolved_to_list, &addrinfo_lists);
2133 if (ipv6_hash_table) {
2134 wmem_map_foreach(ipv6_hash_table, ipv6_hash_table_resolved_to_list, &addrinfo_lists);
2137 return &addrinfo_lists;
2140 /* Read in a list of subnet definition - name pairs.
2141 * <line> = <comment> | <entry> | <whitespace>
2142 * <comment> = <whitespace>#<any>
2143 * <entry> = <subnet_definition> <whitespace> <subnet_name> [<comment>|<whitespace><any>]
2144 * <subnet_definition> = <ipv4_address> / <subnet_mask_length>
2145 * <ipv4_address> is a full address; it will be masked to get the subnet-ID.
2146 * <subnet_mask_length> is a decimal 1-31
2147 * <subnet_name> is a string containing no whitespace.
2148 * <whitespace> = (space | tab)+
2149 * Any malformed entries are ignored.
2150 * Any trailing data after the subnet_name is ignored.
2155 read_subnets_file (const char *subnetspath)
2161 guint32 host_addr; /* IPv4 ONLY */
2164 if ((hf = ws_fopen(subnetspath, "r")) == NULL)
2167 while (fgetline(&line, &size, hf) >= 0) {
2168 if ((cp = strchr(line, '#')))
2171 if ((cp = strtok(line, " \t")) == NULL)
2172 continue; /* no tokens in the line */
2175 /* Expected format is <IP4 address>/<subnet length> */
2176 cp2 = strchr(cp, '/');
2181 *cp2 = '\0'; /* Cut token */
2184 /* Check if this is a valid IPv4 address */
2185 if (!str_to_ip(cp, &host_addr)) {
2189 if (!ws_strtou8(cp2, NULL, &mask_length) || mask_length == 0 || mask_length > 32) {
2190 continue; /* invalid mask length */
2193 if ((cp = strtok(NULL, " \t")) == NULL)
2194 continue; /* no subnet name */
2196 subnet_entry_set(host_addr, mask_length, cp);
2198 wmem_free(wmem_epan_scope(), line);
2202 } /* read_subnets_file */
2204 static subnet_entry_t
2205 subnet_lookup(const guint32 addr)
2207 subnet_entry_t subnet_entry;
2210 /* Search mask lengths linearly, longest first */
2212 i = SUBNETLENGTHSIZE;
2213 while(have_subnet_entry && i > 0) {
2214 guint32 masked_addr;
2215 subnet_length_entry_t* length_entry;
2217 /* Note that we run from 31 (length 32) to 0 (length 1) */
2219 g_assert(i < SUBNETLENGTHSIZE);
2222 length_entry = &subnet_length_entries[i];
2224 if (NULL != length_entry->subnet_addresses) {
2225 sub_net_hashipv4_t * tp;
2228 masked_addr = addr & length_entry->mask;
2229 hash_idx = HASH_IPV4_ADDRESS(masked_addr);
2231 tp = length_entry->subnet_addresses[hash_idx];
2232 while(tp != NULL && tp->addr != masked_addr) {
2237 subnet_entry.mask = length_entry->mask;
2238 subnet_entry.mask_length = i + 1; /* Length is offset + 1 */
2239 subnet_entry.name = tp->name;
2240 return subnet_entry;
2245 subnet_entry.mask = 0;
2246 subnet_entry.mask_length = 0;
2247 subnet_entry.name = NULL;
2249 return subnet_entry;
2252 /* Add a subnet-definition - name pair to the set.
2253 * The definition is taken by masking the address passed in with the mask of the
2257 subnet_entry_set(guint32 subnet_addr, const guint8 mask_length, const gchar* name)
2259 subnet_length_entry_t* entry;
2260 sub_net_hashipv4_t * tp;
2263 g_assert(mask_length > 0 && mask_length <= 32);
2265 entry = &subnet_length_entries[mask_length - 1];
2267 subnet_addr &= entry->mask;
2269 hash_idx = HASH_IPV4_ADDRESS(subnet_addr);
2271 if (NULL == entry->subnet_addresses) {
2272 entry->subnet_addresses = (sub_net_hashipv4_t**)wmem_alloc0(wmem_epan_scope(), sizeof(sub_net_hashipv4_t*) * HASHHOSTSIZE);
2275 if (NULL != (tp = entry->subnet_addresses[hash_idx])) {
2276 sub_net_hashipv4_t * new_tp;
2279 if (tp->addr == subnet_addr) {
2280 return; /* XXX provide warning that an address was repeated? */
2286 new_tp = wmem_new(wmem_epan_scope(), sub_net_hashipv4_t);
2290 tp = entry->subnet_addresses[hash_idx] = wmem_new(wmem_epan_scope(), sub_net_hashipv4_t);
2294 tp->addr = subnet_addr;
2295 /* Clear DUMMY_ADDRESS_ENTRY */
2296 tp->flags &= ~DUMMY_ADDRESS_ENTRY; /*Never used again...*/
2297 g_strlcpy(tp->name, name, MAXNAMELEN); /* This is longer than subnet names can actually be */
2298 have_subnet_entry = TRUE;
2302 subnet_name_lookup_init(void)
2307 for(i = 0; i < SUBNETLENGTHSIZE; ++i) {
2308 guint32 length = i + 1;
2310 subnet_length_entries[i].subnet_addresses = NULL;
2311 subnet_length_entries[i].mask_length = length;
2312 subnet_length_entries[i].mask = g_htonl(ip_get_subnet_mask(length));
2315 /* Check profile directory before personal configuration */
2316 subnetspath = get_persconffile_path(ENAME_SUBNETS, TRUE);
2317 if (!read_subnets_file(subnetspath)) {
2318 if (errno != ENOENT) {
2319 report_open_failure(subnetspath, errno, FALSE);
2322 g_free(subnetspath);
2323 subnetspath = get_persconffile_path(ENAME_SUBNETS, FALSE);
2324 if (!read_subnets_file(subnetspath) && errno != ENOENT) {
2325 report_open_failure(subnetspath, errno, FALSE);
2328 g_free(subnetspath);
2331 * Load the global subnets file, if we have one.
2333 subnetspath = get_datafile_path(ENAME_SUBNETS);
2334 if (!read_subnets_file(subnetspath) && errno != ENOENT) {
2335 report_open_failure(subnetspath, errno, FALSE);
2337 g_free(subnetspath);
2340 /* SS7 PC Name Resolution Portion */
2341 static hashss7pc_t *
2342 new_ss7pc(const guint8 ni, const guint32 pc)
2344 hashss7pc_t *tp = wmem_new(wmem_epan_scope(), hashss7pc_t);
2345 tp->id = (ni<<24) + (pc&0xffffff);
2346 tp->pc_addr[0] = '\0';
2352 static hashss7pc_t *
2353 host_lookup_ss7pc(const guint8 ni, const guint32 pc)
2355 hashss7pc_t * volatile tp;
2358 id = (ni<<24) + (pc&0xffffff);
2360 tp = (hashss7pc_t *)wmem_map_lookup(ss7pc_hash_table, GUINT_TO_POINTER(id));
2362 tp = new_ss7pc(ni, pc);
2363 wmem_map_insert(ss7pc_hash_table, GUINT_TO_POINTER(id), tp);
2369 void fill_unresolved_ss7pc(const gchar * pc_addr, const guint8 ni, const guint32 pc)
2371 hashss7pc_t *tp = host_lookup_ss7pc(ni, pc);
2373 g_strlcpy(tp->pc_addr, pc_addr, MAXNAMELEN);
2377 get_hostname_ss7pc(const guint8 ni, const guint32 pc)
2379 hashss7pc_t *tp = host_lookup_ss7pc(ni, pc);
2381 /* never resolved yet*/
2382 if (tp->pc_addr[0] == '\0')
2385 /* Don't have name in file */
2386 if (tp->name[0] == '\0')
2389 if (!gbl_resolv_flags.ss7pc_name)
2396 add_ss7pc_name(const guint8 ni, guint32 pc, const gchar *name)
2401 if (!name || name[0] == '\0')
2404 id = (ni<<24) + (pc&0xffffff);
2405 tp = (hashss7pc_t *)wmem_map_lookup(ss7pc_hash_table, GUINT_TO_POINTER(id));
2407 tp = new_ss7pc(ni, pc);
2408 wmem_map_insert(ss7pc_hash_table, GUINT_TO_POINTER(id), tp);
2411 if (g_ascii_strcasecmp(tp->name, name)) {
2412 g_strlcpy(tp->name, name, MAXNAMELEN);
2417 read_ss7pcs_file(const char *ss7pcspath)
2425 gboolean entry_found = FALSE;
2428 * File format is Network Indicator (decimal)<dash>Point Code (Decimal)<tab/space>Hostname
2430 if ((hf = ws_fopen(ss7pcspath, "r")) == NULL)
2433 while (fgetline(&line, &size, hf) >= 0) {
2434 if ((cp = strchr(line, '#')))
2437 if ((cp = strtok(line, "-")) == NULL)
2438 continue; /*no ni-pc separator*/
2439 if (!ws_strtou8(cp, NULL, &ni))
2444 if ((cp = strtok(NULL, " \t")) == NULL)
2445 continue; /* no tokens for pc and name */
2446 if (!ws_strtou32(cp, NULL, &pc))
2451 if ((cp = strtok(NULL, " \t")) == NULL)
2452 continue; /* no host name */
2455 add_ss7pc_name(ni, pc, cp);
2457 wmem_free(wmem_epan_scope(), line);
2460 return entry_found ? TRUE : FALSE;
2464 ss7pc_name_lookup_init(void)
2468 g_assert(ss7pc_hash_table == NULL);
2470 ss7pc_hash_table = wmem_map_new(wmem_epan_scope(), g_direct_hash, g_direct_equal);
2473 * Load the user's ss7pcs file
2475 ss7pcspath = get_persconffile_path(ENAME_SS7PCS, TRUE);
2476 if (!read_ss7pcs_file(ss7pcspath) && errno != ENOENT) {
2477 report_open_failure(ss7pcspath, errno, FALSE);
2482 /* SS7PC Name Resolution End*/
2486 * External Functions
2490 addr_resolve_pref_init(module_t *nameres)
2492 prefs_register_bool_preference(nameres, "mac_name",
2493 "Resolve MAC addresses",
2494 "Resolve Ethernet MAC addresses to host names from the preferences"
2495 " or system's Ethers file, or to a manufacturer based name.",
2496 &gbl_resolv_flags.mac_name);
2498 prefs_register_bool_preference(nameres, "transport_name",
2499 "Resolve transport names",
2500 "Resolve TCP/UDP ports into service names",
2501 &gbl_resolv_flags.transport_name);
2503 prefs_register_bool_preference(nameres, "network_name",
2504 "Resolve network (IP) addresses",
2505 "Resolve IPv4, IPv6, and IPX addresses into host names."
2506 " The next set of check boxes determines how name resolution should be performed."
2507 " If no other options are checked name resolution is made from Wireshark's host file,"
2508 " capture file name resolution blocks and DNS packets in the capture.",
2509 &gbl_resolv_flags.network_name);
2511 prefs_register_bool_preference(nameres, "dns_pkt_addr_resolution",
2512 "Use captured DNS packet data for address resolution",
2513 "Whether address/name pairs found in captured DNS packets should be used by Wireshark for name resolution.",
2514 &gbl_resolv_flags.dns_pkt_addr_resolution);
2517 prefs_register_bool_preference(nameres, "use_external_name_resolver",
2518 "Use an external network name resolver",
2519 "Use your system's configured name resolver"
2520 " (usually DNS) to resolve network names."
2521 " Only applies when network name resolution"
2523 &gbl_resolv_flags.use_external_net_name_resolver);
2525 prefs_register_obsolete_preference(nameres, "concurrent_dns");
2527 prefs_register_uint_preference(nameres, "name_resolve_concurrency",
2528 "Maximum concurrent requests",
2529 "The maximum number of DNS requests that may"
2530 " be active at any time. A large value (many"
2531 " thousands) might overload the network or make"
2532 " your DNS server behave badly.",
2534 &name_resolve_concurrency);
2536 prefs_register_static_text_preference(nameres, "use_external_name_resolver",
2537 "Use an external network name resolver: N/A",
2538 "Support for using a concurrent external name resolver was not"
2539 " compiled into this version of Wireshark");
2542 prefs_register_bool_preference(nameres, "hosts_file_handling",
2543 "Only use the profile \"hosts\" file",
2544 "By default \"hosts\" files will be loaded from multiple sources."
2545 " Checking this box only loads the \"hosts\" in the current profile.",
2546 &gbl_resolv_flags.load_hosts_file_from_profile_only);
2548 prefs_register_bool_preference(nameres, "vlan_name",
2550 "Resolve VLAN IDs to network names from the preferences \"vlans\" file."
2551 " Format of the file is: \"ID<Tab>Name\"."
2552 " One line per VLAN, e.g.: 1 Management",
2553 &gbl_resolv_flags.vlan_name);
2555 prefs_register_bool_preference(nameres, "ss7_pc_name",
2557 "Resolve SS7 Point Codes to node names from the profiles \"ss7pcs\" file."
2558 " Format of the file is: \"Network_Indicator<Dash>PC_Decimal<Tab>Name\"."
2559 " One line per Point Code, e.g.: 2-1234 MyPointCode1",
2560 &gbl_resolv_flags.ss7pc_name);
2565 disable_name_resolution(void) {
2566 gbl_resolv_flags.mac_name = FALSE;
2567 gbl_resolv_flags.network_name = FALSE;
2568 gbl_resolv_flags.transport_name = FALSE;
2569 gbl_resolv_flags.dns_pkt_addr_resolution = FALSE;
2570 gbl_resolv_flags.use_external_net_name_resolver = FALSE;
2571 gbl_resolv_flags.vlan_name = FALSE;
2572 gbl_resolv_flags.ss7pc_name = FALSE;
2577 host_name_lookup_process(void) {
2578 async_dns_queue_msg_t *caqm;
2579 struct timeval tv = { 0, 0 };
2582 gboolean nro = new_resolved_objects;
2583 wmem_list_frame_t* head;
2585 new_resolved_objects = FALSE;
2587 if (!async_dns_initialized)
2588 /* c-ares not initialized. Bail out and cancel timers. */
2591 head = wmem_list_head(async_dns_queue_head);
2593 while (head != NULL && async_dns_in_flight <= name_resolve_concurrency) {
2594 caqm = (async_dns_queue_msg_t *)wmem_list_frame_data(head);
2595 wmem_list_remove_frame(async_dns_queue_head, head);
2596 if (caqm->family == AF_INET) {
2597 ares_gethostbyaddr(ghba_chan, &caqm->addr.ip4, sizeof(guint32), AF_INET,
2598 c_ares_ghba_cb, caqm);
2599 async_dns_in_flight++;
2600 } else if (caqm->family == AF_INET6) {
2601 ares_gethostbyaddr(ghba_chan, &caqm->addr.ip6, sizeof(struct e_in6_addr),
2602 AF_INET6, c_ares_ghba_cb, caqm);
2603 async_dns_in_flight++;
2606 head = wmem_list_head(async_dns_queue_head);
2611 nfds = ares_fds(ghba_chan, &rfds, &wfds);
2613 if (select(nfds, &rfds, &wfds, NULL, &tv) == -1) { /* call to select() failed */
2614 fprintf(stderr, "Warning: call to select() failed, error is %s\n", g_strerror(errno));
2617 ares_process(ghba_chan, &rfds, &wfds);
2620 /* Any new entries? */
2625 _host_name_lookup_cleanup(void) {
2626 async_dns_queue_head = NULL;
2628 if (async_dns_initialized) {
2629 ares_destroy(ghba_chan);
2630 ares_destroy(ghbn_chan);
2632 #ifdef CARES_HAVE_ARES_LIBRARY_INIT
2633 ares_library_cleanup();
2635 async_dns_initialized = FALSE;
2641 host_name_lookup_process(void) {
2642 gboolean nro = new_resolved_objects;
2644 new_resolved_objects = FALSE;
2650 _host_name_lookup_cleanup(void) {
2653 #endif /* HAVE_C_ARES */
2656 get_hostname(const guint addr)
2658 /* XXX why do we call this if we're not resolving? To create hash entries?
2661 hashipv4_t *tp = host_lookup(addr);
2663 if (!gbl_resolv_flags.network_name)
2666 tp->flags |= RESOLVED_ADDRESS_USED;
2671 /* -------------------------- */
2674 get_hostname6(const struct e_in6_addr *addr)
2676 /* XXX why do we call this if we're not resolving? To create hash entries?
2679 hashipv6_t *tp = host_lookup6(addr);
2681 if (!gbl_resolv_flags.network_name)
2684 tp->flags |= RESOLVED_ADDRESS_USED;
2689 /* -------------------------- */
2691 add_ipv4_name(const guint addr, const gchar *name)
2696 * Don't add zero-length names; apparently, some resolvers will return
2697 * them if they get them from DNS.
2699 if (!name || name[0] == '\0')
2702 tp = (hashipv4_t *)wmem_map_lookup(ipv4_hash_table, GUINT_TO_POINTER(addr));
2704 tp = new_ipv4(addr);
2705 wmem_map_insert(ipv4_hash_table, GUINT_TO_POINTER(addr), tp);
2708 if (g_ascii_strcasecmp(tp->name, name)) {
2709 g_strlcpy(tp->name, name, MAXNAMELEN);
2710 new_resolved_objects = TRUE;
2712 tp->flags |= TRIED_RESOLVE_ADDRESS|NAME_RESOLVED;
2713 } /* add_ipv4_name */
2715 /* -------------------------- */
2717 add_ipv6_name(const struct e_in6_addr *addrp, const gchar *name)
2722 * Don't add zero-length names; apparently, some resolvers will return
2723 * them if they get them from DNS.
2725 if (!name || name[0] == '\0')
2728 tp = (hashipv6_t *)wmem_map_lookup(ipv6_hash_table, addrp);
2730 struct e_in6_addr *addr_key;
2732 addr_key = wmem_new(wmem_epan_scope(), struct e_in6_addr);
2733 tp = new_ipv6(addrp);
2734 memcpy(addr_key, addrp, 16);
2735 wmem_map_insert(ipv6_hash_table, addr_key, tp);
2738 if (g_ascii_strcasecmp(tp->name, name)) {
2739 g_strlcpy(tp->name, name, MAXNAMELEN);
2740 new_resolved_objects = TRUE;
2742 tp->flags |= TRIED_RESOLVE_ADDRESS|NAME_RESOLVED;
2743 } /* add_ipv6_name */
2746 add_manually_resolved_ipv4(gpointer data, gpointer user_data _U_)
2748 resolved_ipv4_t *resolved_ipv4_entry = (resolved_ipv4_t *)data;
2750 add_ipv4_name(resolved_ipv4_entry->host_addr, resolved_ipv4_entry->name);
2754 add_manually_resolved_ipv6(gpointer data, gpointer user_data _U_)
2756 resolved_ipv6_t *resolved_ipv6_entry = (resolved_ipv6_t *)data;
2758 add_ipv6_name(&(resolved_ipv6_entry->ip6_addr), resolved_ipv6_entry->name);
2762 add_manually_resolved(void)
2764 if (manually_resolved_ipv4_list) {
2765 wmem_list_foreach(manually_resolved_ipv4_list, add_manually_resolved_ipv4, NULL);
2768 if (manually_resolved_ipv6_list) {
2769 wmem_list_foreach(manually_resolved_ipv6_list, add_manually_resolved_ipv6, NULL);
2774 host_name_lookup_init(void)
2779 g_assert(ipxnet_hash_table == NULL);
2780 ipxnet_hash_table = wmem_map_new(wmem_epan_scope(), g_int_hash, g_int_equal);
2782 g_assert(ipv4_hash_table == NULL);
2783 ipv4_hash_table = wmem_map_new(wmem_epan_scope(), g_direct_hash, g_direct_equal);
2785 g_assert(ipv6_hash_table == NULL);
2786 ipv6_hash_table = wmem_map_new(wmem_epan_scope(), ipv6_oat_hash, ipv6_equal);
2789 g_assert(async_dns_queue_head == NULL);
2790 async_dns_queue_head = wmem_list_new(wmem_epan_scope());
2793 if (manually_resolved_ipv4_list == NULL)
2794 manually_resolved_ipv4_list = wmem_list_new(wmem_epan_scope());
2796 if (manually_resolved_ipv6_list == NULL)
2797 manually_resolved_ipv6_list = wmem_list_new(wmem_epan_scope());
2800 * Load the global hosts file, if we have one.
2802 if (!gbl_resolv_flags.load_hosts_file_from_profile_only) {
2803 hostspath = get_datafile_path(ENAME_HOSTS);
2804 if (!read_hosts_file(hostspath, TRUE) && errno != ENOENT) {
2805 report_open_failure(hostspath, errno, FALSE);
2810 * Load the user's hosts file no matter what, if they have one.
2812 hostspath = get_persconffile_path(ENAME_HOSTS, TRUE);
2813 if (!read_hosts_file(hostspath, TRUE) && errno != ENOENT) {
2814 report_open_failure(hostspath, errno, FALSE);
2818 #ifdef CARES_HAVE_ARES_LIBRARY_INIT
2819 if (ares_library_init(ARES_LIB_INIT_ALL) == ARES_SUCCESS) {
2821 if (ares_init(&ghba_chan) == ARES_SUCCESS && ares_init(&ghbn_chan) == ARES_SUCCESS) {
2822 async_dns_initialized = TRUE;
2824 #ifdef CARES_HAVE_ARES_LIBRARY_INIT
2828 #endif /* HAVE_C_ARES */
2830 if (extra_hosts_files && !gbl_resolv_flags.load_hosts_file_from_profile_only) {
2831 for (i = 0; i < extra_hosts_files->len; i++) {
2832 read_hosts_file((const char *) g_ptr_array_index(extra_hosts_files, i), TRUE);
2836 subnet_name_lookup_init();
2838 add_manually_resolved();
2840 ss7pc_name_lookup_init();
2844 host_name_lookup_cleanup(void)
2847 sub_net_hashipv4_t *entry, *next_entry;
2849 _host_name_lookup_cleanup();
2851 ipxnet_hash_table = NULL;
2852 ipv4_hash_table = NULL;
2853 ipv6_hash_table = NULL;
2854 ss7pc_hash_table = NULL;
2856 for(i = 0; i < SUBNETLENGTHSIZE; ++i) {
2857 if (subnet_length_entries[i].subnet_addresses != NULL) {
2858 for (j = 0; j < HASHHOSTSIZE; j++) {
2859 for (entry = subnet_length_entries[i].subnet_addresses[j];
2860 entry != NULL; entry = next_entry) {
2861 next_entry = entry->next;
2862 wmem_free(wmem_epan_scope(), entry);
2865 wmem_free(wmem_epan_scope(), subnet_length_entries[i].subnet_addresses);
2866 subnet_length_entries[i].subnet_addresses = NULL;
2870 have_subnet_entry = FALSE;
2871 new_resolved_objects = FALSE;
2875 manually_resolve_cleanup(void)
2877 wmem_destroy_list(manually_resolved_ipv4_list);
2878 manually_resolved_ipv4_list = NULL;
2879 wmem_destroy_list(manually_resolved_ipv6_list);
2880 manually_resolved_ipv6_list = NULL;
2884 udp_port_to_display(wmem_allocator_t *allocator, guint port)
2887 if (!gbl_resolv_flags.transport_name) {
2888 return wmem_utoa(allocator, port);
2891 return wmem_strdup(allocator, serv_name_lookup(PT_UDP, port));
2893 } /* udp_port_to_display */
2896 dccp_port_to_display(wmem_allocator_t *allocator, guint port)
2899 if (!gbl_resolv_flags.transport_name) {
2900 return wmem_utoa(allocator, port);
2903 return wmem_strdup(allocator, serv_name_lookup(PT_DCCP, port));
2905 } /* dccp_port_to_display */
2908 tcp_port_to_display(wmem_allocator_t *allocator, guint port)
2911 if (!gbl_resolv_flags.transport_name) {
2912 return wmem_utoa(allocator, port);
2915 return wmem_strdup(allocator, serv_name_lookup(PT_TCP, port));
2917 } /* tcp_port_to_display */
2920 sctp_port_to_display(wmem_allocator_t *allocator, guint port)
2923 if (!gbl_resolv_flags.transport_name) {
2924 return wmem_utoa(allocator, port);
2927 return wmem_strdup(allocator, serv_name_lookup(PT_SCTP, port));
2929 } /* sctp_port_to_display */
2932 port_with_resolution_to_str(wmem_allocator_t *scope, port_type proto, guint port)
2934 const gchar *port_str;
2936 if (!gbl_resolv_flags.transport_name || (proto == PT_NONE)) {
2937 /* No name resolution support, just return port string */
2938 return wmem_strdup_printf(scope, "%u", port);
2940 port_str = serv_name_lookup(proto, port);
2942 return wmem_strdup_printf(scope, "%s (%u)", port_str, port);
2946 port_with_resolution_to_str_buf(gchar *buf, gulong buf_size, port_type proto, guint port)
2948 const gchar *port_str;
2950 if (!gbl_resolv_flags.transport_name || (proto == PT_NONE)) {
2951 /* No name resolution support, just return port string */
2952 return g_snprintf(buf, buf_size, "%u", port);
2954 port_str = serv_name_lookup(proto, port);
2956 return g_snprintf(buf, buf_size, "%s (%u)", port_str, port);
2960 get_ether_name(const guint8 *addr)
2963 gboolean resolve = gbl_resolv_flags.mac_name;
2965 tp = eth_name_lookup(addr, resolve);
2967 return resolve ? tp->resolved_name : tp->hexaddr;
2969 } /* get_ether_name */
2972 tvb_get_ether_name(tvbuff_t *tvb, gint offset)
2974 return get_ether_name(tvb_get_ptr(tvb, offset, 6));
2977 /* Look for a (non-dummy) ether name in the hash, and return it if found.
2978 * If it's not found, simply return NULL.
2981 get_ether_name_if_known(const guint8 *addr)
2985 /* Initialize ether structs if we're the first
2986 * ether-related function called */
2987 if (!gbl_resolv_flags.mac_name)
2990 /* eth_name_lookup will create a (resolved) hash entry if it doesn't exist */
2991 tp = eth_name_lookup(addr, TRUE);
2992 g_assert(tp != NULL);
2994 if (tp->status == HASHETHER_STATUS_RESOLVED_NAME) {
2995 /* Name is from an ethers file */
2996 return tp->resolved_name;
2999 /* Name was created */
3005 get_ether_addr(const gchar *name)
3008 /* force resolution (do not check gbl_resolv_flags) */
3009 return eth_addr_lookup(name);
3011 } /* get_ether_addr */
3014 add_ether_byip(const guint ip, const guint8 *eth)
3018 /* first check that IP address can be resolved */
3019 if (!gbl_resolv_flags.network_name)
3022 tp = host_lookup(ip);
3025 * Was this IP address resolved to a host name?
3027 if (tp->flags & NAME_RESOLVED) {
3029 * Yes, so add an entry in the ethers hashtable resolving
3030 * the MAC address to that name.
3032 add_eth_name(eth, tp->name);
3035 } /* add_ether_byip */
3038 ipxnet_to_str_punct(wmem_allocator_t *allocator, const guint32 ad, const char punct)
3040 gchar *buf = (gchar *)wmem_alloc(allocator, 12);
3042 *dword_to_hex_punct(buf, ad, punct) = '\0';
3047 get_ipxnet_name(wmem_allocator_t *allocator, const guint32 addr)
3050 if (!gbl_resolv_flags.network_name) {
3051 return ipxnet_to_str_punct(allocator, addr, '\0');
3054 return ipxnet_name_lookup(allocator, addr);
3056 } /* get_ipxnet_name */
3059 get_ipxnet_addr(const gchar *name, gboolean *known)
3064 /* force resolution (do not check gbl_resolv_flags) */
3065 addr = ipxnet_addr_lookup(name, &success);
3070 } /* get_ipxnet_addr */
3073 get_vlan_name(wmem_allocator_t *allocator, const guint16 id)
3076 if (!gbl_resolv_flags.vlan_name) {
3080 return wmem_strdup(allocator, vlan_name_lookup(id));
3082 } /* get_vlan_name */
3085 get_manuf_name(const guint8 *addr)
3087 hashmanuf_t *manuf_value;
3089 manuf_value = manuf_name_lookup(addr);
3090 if (gbl_resolv_flags.mac_name && manuf_value->status != HASHETHER_STATUS_UNRESOLVED)
3091 return manuf_value->resolved_name;
3093 return manuf_value->hexaddr;
3095 } /* get_manuf_name */
3098 uint_get_manuf_name(const guint oid)
3102 addr[0] = (oid >> 16) & 0xFF;
3103 addr[1] = (oid >> 8) & 0xFF;
3104 addr[2] = (oid >> 0) & 0xFF;
3105 return get_manuf_name(addr);
3109 tvb_get_manuf_name(tvbuff_t *tvb, gint offset)
3111 return get_manuf_name(tvb_get_ptr(tvb, offset, 3));
3115 get_manuf_name_if_known(const guint8 *addr)
3117 hashmanuf_t *manuf_value;
3121 /* manuf needs only the 3 most significant octets of the ethernet address */
3122 manuf_key = addr[0];
3123 manuf_key = manuf_key<<8;
3125 manuf_key = manuf_key | oct;
3126 manuf_key = manuf_key<<8;
3128 manuf_key = manuf_key | oct;
3130 manuf_value = (hashmanuf_t *)wmem_map_lookup(manuf_hashtable, &manuf_key);
3131 if ((manuf_value == NULL) || (manuf_value->status == HASHETHER_STATUS_UNRESOLVED)) {
3135 return manuf_value->resolved_name;
3137 } /* get_manuf_name_if_known */
3140 uint_get_manuf_name_if_known(const guint manuf_key)
3142 hashmanuf_t *manuf_value;
3144 manuf_value = (hashmanuf_t *)wmem_map_lookup(manuf_hashtable, &manuf_key);
3145 if ((manuf_value == NULL) || (manuf_value->status == HASHETHER_STATUS_UNRESOLVED)) {
3149 return manuf_value->resolved_name;
3153 tvb_get_manuf_name_if_known(tvbuff_t *tvb, gint offset)
3155 return get_manuf_name_if_known(tvb_get_ptr(tvb, offset, 3));
3158 char* get_hash_manuf_resolved_name(hashmanuf_t* manuf)
3160 return manuf->resolved_name;
3164 eui64_to_display(wmem_allocator_t *allocator, const guint64 addr_eui64)
3166 guint8 *addr = (guint8 *)wmem_alloc(NULL, 8);
3167 hashmanuf_t *manuf_value;
3170 /* Copy and convert the address to network byte order. */
3171 *(guint64 *)(void *)(addr) = pntoh64(&(addr_eui64));
3173 manuf_value = manuf_name_lookup(addr);
3174 if (!gbl_resolv_flags.mac_name || (manuf_value->status == HASHETHER_STATUS_UNRESOLVED)) {
3175 ret = wmem_strdup_printf(allocator, "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", addr[0], addr[1], addr[2], addr[3], addr[4], addr[5], addr[6], addr[7]);
3177 ret = wmem_strdup_printf(allocator, "%s_%02x:%02x:%02x:%02x:%02x", manuf_value->resolved_name, addr[3], addr[4], addr[5], addr[6], addr[7]);
3180 wmem_free(NULL, addr);
3182 } /* eui64_to_display */
3185 #define GHI_TIMEOUT (250 * 1000)
3190 #if ( ( ARES_VERSION_MAJOR < 1 ) \
3191 || ( 1 == ARES_VERSION_MAJOR && ARES_VERSION_MINOR < 5 ) )
3200 * XXX - If we wanted to be really fancy we could cache results here and
3201 * look them up in get_host_ipaddr* below.
3203 async_hostent_t *ahp = (async_hostent_t *)arg;
3204 if (status == ARES_SUCCESS && hp && ahp && hp->h_length == ahp->addr_size) {
3205 memcpy(ahp->addrp, hp->h_addr, hp->h_length);
3206 ahp->copied = hp->h_length;
3209 #endif /* HAVE_C_ARES */
3211 /* Translate a string, assumed either to be a dotted-quad IP address or
3212 * a host name, to a numeric IP address. Return TRUE if we succeed and
3213 * set "*addrp" to that numeric IP address; return FALSE if we fail.
3214 * Used more in the dfilter parser rather than in packet dissectors */
3216 get_host_ipaddr(const char *host, guint32 *addrp)
3218 struct in_addr ipaddr;
3220 struct timeval tv = { 0, GHI_TIMEOUT }, *tvp;
3223 async_hostent_t ahe;
3227 * don't change it to inet_pton(AF_INET), they are not 100% compatible.
3228 * inet_pton(AF_INET) does not support hexadecimal notation nor
3229 * less-than-4 octet notation.
3231 if (!inet_aton(host, &ipaddr)) {
3233 /* It's not a valid dotted-quad IP address; is it a valid
3237 /* If we're not allowed to do name resolution, don't do name
3240 if (!gbl_resolv_flags.network_name ||
3241 !gbl_resolv_flags.use_external_net_name_resolver) {
3246 if (!async_dns_initialized || name_resolve_concurrency < 1) {
3249 ahe.addr_size = (int) sizeof (struct in_addr);
3252 ares_gethostbyname(ghbn_chan, host, AF_INET, c_ares_ghi_cb, &ahe);
3255 nfds = ares_fds(ghbn_chan, &rfds, &wfds);
3257 tvp = ares_timeout(ghbn_chan, &tv, &tv);
3258 if (select(nfds, &rfds, &wfds, NULL, tvp) == -1) { /* call to select() failed */
3259 fprintf(stderr, "Warning: call to select() failed, error is %s\n", g_strerror(errno));
3262 ares_process(ghbn_chan, &rfds, &wfds);
3264 ares_cancel(ghbn_chan);
3265 if (ahe.addr_size == ahe.copied) {
3271 /* Does the string really contain dotted-quad IP?
3272 * Check against inet_atons that accept strings such as
3273 * "130.230" as valid addresses and try to convert them
3274 * to some form of a classful (host.net) notation.
3276 unsigned int a0, a1, a2, a3;
3277 if (sscanf(host, "%u.%u.%u.%u", &a0, &a1, &a2, &a3) != 4)
3281 *addrp = ipaddr.s_addr;
3286 * Translate IPv6 numeric address or FQDN hostname, into binary IPv6 address.
3287 * Return TRUE if we succeed and set "*addrp" to that numeric IP address;
3288 * return FALSE if we fail.
3291 get_host_ipaddr6(const char *host, struct e_in6_addr *addrp)
3294 struct timeval tv = { 0, GHI_TIMEOUT }, *tvp;
3297 async_hostent_t ahe;
3298 #endif /* HAVE_C_ARES */
3300 if (str_to_ip6(host, addrp))
3303 /* It's not a valid dotted-quad IP address; is it a valid
3307 /* If we're not allowed to do name resolution, don't do name
3310 if (!gbl_resolv_flags.network_name ||
3311 !gbl_resolv_flags.use_external_net_name_resolver) {
3317 if (!async_dns_initialized || name_resolve_concurrency < 1) {
3320 ahe.addr_size = (int) sizeof (struct e_in6_addr);
3323 ares_gethostbyname(ghbn_chan, host, AF_INET6, c_ares_ghi_cb, &ahe);
3326 nfds = ares_fds(ghbn_chan, &rfds, &wfds);
3328 tvp = ares_timeout(ghbn_chan, &tv, &tv);
3329 if (select(nfds, &rfds, &wfds, NULL, tvp) == -1) { /* call to select() failed */
3330 fprintf(stderr, "Warning: call to select() failed, error is %s\n", g_strerror(errno));
3333 ares_process(ghbn_chan, &rfds, &wfds);
3335 ares_cancel(ghbn_chan);
3336 if (ahe.addr_size == ahe.copied) {
3345 get_manuf_hashtable(void)
3347 return manuf_hashtable;
3351 get_wka_hashtable(void)
3353 return wka_hashtable;
3357 get_eth_hashtable(void)
3359 return eth_hashtable;
3363 get_serv_port_hashtable(void)
3365 return serv_port_hashtable;
3369 get_ipxnet_hash_table(void)
3371 return ipxnet_hash_table;
3375 get_vlan_hash_table(void)
3377 return vlan_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();
3399 /* host name initialization is done on a per-capture-file basis */
3400 /*host_name_lookup_init();*/
3403 /* Clean up all the address resolution subsystems in this file */
3405 addr_resolv_cleanup(void)
3407 vlan_name_lookup_cleanup();
3408 service_name_lookup_cleanup();
3410 ipx_name_lookup_cleanup();
3411 /* host name initialization is done on a per-capture-file basis */
3412 /*host_name_lookup_cleanup();*/
3416 str_to_ip(const char *str, void *dst)
3418 return ws_inet_pton4(str, (guint32 *)dst);
3422 str_to_ip6(const char *str, void *dst)
3424 return ws_inet_pton6(str, (struct e_in6_addr *)dst);
3428 * Editor modelines - http://www.wireshark.org/tools/modelines.html
3433 * indent-tabs-mode: nil
3436 * vi: set shiftwidth=4 tabstop=8 expandtab:
3437 * :indentSize=4:tabSize=8:noTabs=true: