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.
36 * Win32 doesn't have SIGALRM (and it's the OS where name lookup calls
37 * are most likely to take a long time, given the way address-to-name
38 * lookups are done over NBNS).
40 * Mac OS X does have SIGALRM, but if you longjmp() out of a name resolution
41 * call in a signal handler, you might crash, because the state of the
42 * resolution code that sends messages to lookupd might be inconsistent
43 * if you jump out of it in middle of a call.
45 * There's no guarantee that longjmp()ing out of name resolution calls
46 * will work on *any* platform; OpenBSD got rid of the alarm/longjmp
47 * code in tcpdump, to avoid those sorts of problems, and that was
48 * picked up by tcpdump.org tcpdump.
50 * So, for now, we do not use alarm() and SIGALRM to time out host name
51 * lookups. If we get a lot of complaints about lookups taking a long time,
52 * we can reconsider that decision. (Note that tcpdump originally added
53 * such a timeout mechanism that for the benefit of systems using NIS to
54 * look up host names; that might now be fixed in NIS implementations, for
55 * those sites still using NIS rather than DNS for that.... tcpdump no
56 * longer does that, for the same reasons that we don't.)
58 * If we're using an asynchronous DNS resolver, that shouldn't be an issue.
59 * If we're using a synchronous name lookup mechanism (which we'd do mainly
60 * to support resolving addresses and host names using more mechanisms than
61 * just DNS, such as NIS, NBNS, or Mr. Hosts File), we could do that in
62 * a separate thread, making it, in effect, asynchronous.
65 #ifdef HAVE_NETINET_IN_H
66 # include <netinet/in.h>
73 #ifdef HAVE_SYS_SOCKET_H
74 #include <sys/socket.h> /* needed to define AF_ values on UNIX */
77 #ifdef HAVE_WINSOCK2_H
78 #include <winsock2.h> /* needed to define AF_ values on Windows */
82 # include <ws2tcpip.h>
87 # define socklen_t unsigned int
90 # include <ares_version.h>
91 #endif /* HAVE_C_ARES */
96 #include "addr_and_mask.h"
98 #include "addr_resolv.h"
99 #include "wsutil/filesystem.h"
101 #include <wsutil/report_err.h>
102 #include <wsutil/file_util.h>
103 #include <wsutil/pint.h>
104 #include "wsutil/inet_aton.h"
105 #include <wsutil/inet_addr.h>
107 #include <epan/strutil.h>
108 #include <epan/to_str-int.h>
109 #include <epan/prefs.h>
111 #define ENAME_HOSTS "hosts"
112 #define ENAME_SUBNETS "subnets"
113 #define ENAME_ETHERS "ethers"
114 #define ENAME_IPXNETS "ipxnets"
115 #define ENAME_MANUF "manuf"
116 #define ENAME_SERVICES "services"
117 #define ENAME_VLANS "vlans"
119 #define HASHETHSIZE 2048
120 #define HASHHOSTSIZE 2048
121 #define HASHIPXNETSIZE 256
122 #define SUBNETLENGTHSIZE 32 /*1-32 inc.*/
124 /* hash table used for IPv4 lookup */
126 #define HASH_IPV4_ADDRESS(addr) (g_htonl(addr) & (HASHHOSTSIZE - 1))
129 typedef struct sub_net_hashipv4 {
131 guint8 flags; /* B0 dummy_entry, B1 resolve, B2 If the address is used in the trace */
132 struct sub_net_hashipv4 *next;
134 gchar name[MAXNAMELEN];
135 } sub_net_hashipv4_t;
137 /* Array of entries of subnets of different lengths */
139 gsize mask_length; /*1-32*/
140 guint32 mask; /* e.g. 255.255.255.*/
141 sub_net_hashipv4_t** subnet_addresses; /* Hash table of subnet addresses */
142 } subnet_length_entry_t;
145 /* hash table used for IPX network lookup */
147 /* XXX - check goodness of hash function */
149 #define HASH_IPX_NET(net) ((net) & (HASHIPXNETSIZE - 1))
151 typedef struct hashipxnet {
153 struct hashipxnet *next;
154 gchar name[MAXNAMELEN];
157 typedef struct hashvlan {
159 /* struct hashvlan *next; */
160 gchar name[MAXVLANNAMELEN];
163 /* hash tables used for ethernet and manufacturer lookup */
164 #define HASHETHER_STATUS_UNRESOLVED 1
165 #define HASHETHER_STATUS_RESOLVED_DUMMY 2
166 #define HASHETHER_STATUS_RESOLVED_NAME 3
169 guint status; /* (See above) */
172 char resolved_name[MAXNAMELEN];
176 guint status; /* (See above) */
179 char resolved_name[MAXNAMELEN];
182 /* internal ethernet type */
183 typedef struct _ether
186 char name[MAXNAMELEN];
189 /* internal ipxnet type */
190 typedef struct _ipxnet
193 char name[MAXNAMELEN];
196 /* internal vlan type */
200 char name[MAXVLANNAMELEN];
203 static GHashTable *ipxnet_hash_table = NULL;
204 static GHashTable *ipv4_hash_table = NULL;
205 static GHashTable *ipv6_hash_table = NULL;
206 static GHashTable *vlan_hash_table = NULL;
208 static GSList *manually_resolved_ipv4_list = NULL;
209 static GSList *manually_resolved_ipv6_list = NULL;
211 typedef struct _resolved_ipv4
214 char name[MAXNAMELEN];
217 typedef struct _resolved_ipv6
219 struct e_in6_addr ip6_addr;
220 char name[MAXNAMELEN];
223 static addrinfo_lists_t addrinfo_lists = { NULL, NULL};
225 static gchar *cb_service;
226 static port_type cb_proto = PT_NONE;
229 static GHashTable *manuf_hashtable = NULL;
230 static GHashTable *wka_hashtable = NULL;
231 static GHashTable *eth_hashtable = NULL;
232 static GHashTable *serv_port_hashtable = NULL;
234 static subnet_length_entry_t subnet_length_entries[SUBNETLENGTHSIZE]; /* Ordered array of entries */
235 static gboolean have_subnet_entry = FALSE;
237 static gboolean new_resolved_objects = FALSE;
239 static GPtrArray* extra_hosts_files = NULL;
241 static hashether_t *add_eth_name(const guint8 *addr, const gchar *name);
242 static void add_serv_port_cb(const guint32 port);
245 /* http://eternallyconfuzzled.com/tuts/algorithms/jsw_tut_hashing.aspx#existing
249 ipv6_oat_hash(gconstpointer key)
252 const unsigned char *p = (const unsigned char *)key;
256 for ( i = 0; i < len; i++ ) {
270 ipv6_equal(gconstpointer v1, gconstpointer v2)
273 if (memcmp(v1, v2, sizeof (struct e_in6_addr)) == 0) {
281 * Flag controlling what names to resolve.
283 e_addr_resolve gbl_resolv_flags = {
285 FALSE, /* network_name */
286 FALSE, /* transport_name */
287 TRUE, /* dns_pkt_addr_resolution */
288 TRUE, /* use_external_net_name_resolver */
289 FALSE, /* load_hosts_file_from_profile_only */
290 FALSE /* vlan_name */
293 static guint name_resolve_concurrency = 500;
297 * Global variables (can be changed in GUI sections)
298 * XXX - they could be changed in GUI code, but there's currently no
299 * GUI code to change them.
302 gchar *g_ethers_path = NULL; /* global ethers file */
303 gchar *g_pethers_path = NULL; /* personal ethers file */
304 gchar *g_ipxnets_path = NULL; /* global ipxnets file */
305 gchar *g_pipxnets_path = NULL; /* personal ipxnets file */
306 gchar *g_services_path = NULL; /* global services file */
307 gchar *g_pservices_path = NULL; /* personal services file */
308 gchar *g_pvlan_path = NULL; /* personal vlans file */
309 /* first resolving call */
314 * Submitted queries trigger a callback (c_ares_ghba_cb()).
315 * Queries are added to c_ares_queue_head. During processing, queries are
316 * popped off the front of c_ares_queue_head and submitted using
317 * ares_gethostbyaddr().
318 * The callback processes the response, then frees the request.
320 typedef struct _async_dns_queue_msg
324 struct e_in6_addr ip6;
327 } async_dns_queue_msg_t;
329 typedef struct _async_hostent {
335 #if ( ( ARES_VERSION_MAJOR < 1 ) \
336 || ( 1 == ARES_VERSION_MAJOR && ARES_VERSION_MINOR < 5 ) )
337 static void c_ares_ghba_cb(void *arg, int status, struct hostent *hostent);
339 static void c_ares_ghba_cb(void *arg, int status, int timeouts _U_, struct hostent *hostent);
342 ares_channel ghba_chan; /* ares_gethostbyaddr -- Usually non-interactive, no timeout */
343 ares_channel ghbn_chan; /* ares_gethostbyname -- Usually interactive, timeout */
345 static gboolean async_dns_initialized = FALSE;
346 static guint async_dns_in_flight = 0;
347 static GList *async_dns_queue_head = NULL;
349 /* push a dns request */
351 add_async_dns_ipv4(int type, guint32 addr)
353 async_dns_queue_msg_t *msg;
355 msg = g_new(async_dns_queue_msg_t,1);
357 msg->addr.ip4 = addr;
358 async_dns_queue_head = g_list_append(async_dns_queue_head, (gpointer) msg);
360 #endif /* HAVE_C_ARES */
365 const gchar* name; /* Shallow copy */
369 * Miscellaneous functions
373 fgetline(char **buf, int *size, FILE *fp)
378 if (fp == NULL || buf == NULL)
385 *buf = (char *)g_malloc(*size);
395 while ((c = getc(fp)) != EOF && c != '\r' && c != '\n') {
396 if (len+1 >= *size) {
397 *buf = (char *)g_realloc(*buf, *size += BUFSIZ);
402 if (len == 0 && c == EOF)
413 * Local function definitions
415 static subnet_entry_t subnet_lookup(const guint32 addr);
416 static void subnet_entry_set(guint32 subnet_addr, const guint32 mask_length, const gchar* name);
420 add_service_name(port_type proto, const guint port, const char *service_name)
422 serv_port_t *serv_port_table;
425 key = (int *)g_new(int, 1);
428 serv_port_table = (serv_port_t *)g_hash_table_lookup(serv_port_hashtable, &port);
429 if (serv_port_table == NULL) {
430 serv_port_table = g_new0(serv_port_t,1);
431 g_hash_table_insert(serv_port_hashtable, key, serv_port_table);
439 g_free(serv_port_table->tcp_name);
440 serv_port_table->tcp_name = g_strdup(service_name);
443 g_free(serv_port_table->udp_name);
444 serv_port_table->udp_name = g_strdup(service_name);
447 g_free(serv_port_table->sctp_name);
448 serv_port_table->sctp_name = g_strdup(service_name);
451 g_free(serv_port_table->dccp_name);
452 serv_port_table->dccp_name = g_strdup(service_name);
456 /* Should not happen */
459 new_resolved_objects = TRUE;
464 parse_service_line (char *line)
467 * See the services(4) or services(5) man page for services file format
468 * (not available on all systems).
476 range_t *port_rng = NULL;
477 guint32 max_port = MAX_UDP_PORT;
479 if ((cp = strchr(line, '#')))
482 if ((cp = strtok(line, " \t")) == NULL)
487 if ((cp = strtok(NULL, " \t")) == NULL)
492 if (strtok(cp, "/") == NULL)
495 if ((cp = strtok(NULL, "/")) == NULL)
498 /* seems we got all interesting things from the file */
499 if (strcmp(cp, "tcp") == 0) {
500 max_port = MAX_TCP_PORT;
503 else if (strcmp(cp, "udp") == 0) {
504 max_port = MAX_UDP_PORT;
507 else if (strcmp(cp, "sctp") == 0) {
508 max_port = MAX_SCTP_PORT;
511 else if (strcmp(cp, "dccp") == 0) {
512 max_port = MAX_DCCP_PORT;
518 if (CVT_NO_ERROR != range_convert_str(&port_rng, port, max_port)) {
519 /* some assertion here? */
523 cb_service = service;
525 range_foreach(port_rng, add_serv_port_cb);
528 } /* parse_service_line */
532 add_serv_port_cb(const guint32 port)
535 add_service_name(cb_proto, port, cb_service);
541 parse_services_file(const char * path)
545 static char *buf = NULL;
547 /* services hash table initialization */
548 serv_p = ws_fopen(path, "r");
553 while (fgetline(&buf, &size, serv_p) >= 0) {
554 parse_service_line (buf);
561 * unsigned integer to ascii
564 wmem_utoa(wmem_allocator_t *allocator, guint port)
566 gchar *bp = (gchar *)wmem_alloc(allocator, MAXNAMELEN);
568 /* XXX, guint32_to_str() ? */
569 guint32_to_str_buf(port, bp, MAXNAMELEN);
574 _serv_name_lookup(port_type proto, guint port, serv_port_t **value_ret)
576 serv_port_t *serv_port_table;
578 serv_port_table = (serv_port_t *)g_hash_table_lookup(serv_port_hashtable, &port);
580 if (value_ret != NULL)
581 *value_ret = serv_port_table;
583 if (serv_port_table == NULL)
588 return serv_port_table->udp_name;
590 return serv_port_table->tcp_name;
592 return serv_port_table->sctp_name;
594 return serv_port_table->dccp_name;
602 try_serv_name_lookup(port_type proto, guint port)
604 return _serv_name_lookup(proto, port, NULL);
608 serv_name_lookup(port_type proto, guint port)
610 serv_port_t *serv_port_table = NULL;
614 name = _serv_name_lookup(proto, port, &serv_port_table);
618 if (serv_port_table == NULL) {
619 key = (guint *)g_new(guint, 1);
621 serv_port_table = g_new0(serv_port_t, 1);
622 g_hash_table_insert(serv_port_hashtable, key, serv_port_table);
624 if (serv_port_table->numeric == NULL) {
625 serv_port_table->numeric = g_strdup_printf("%u", port);
628 return serv_port_table->numeric;
632 destroy_serv_port(gpointer data)
634 serv_port_t *table = (serv_port_t*)data;
635 g_free(table->udp_name);
636 g_free(table->tcp_name);
637 g_free(table->sctp_name);
638 g_free(table->dccp_name);
639 g_free(table->numeric);
644 initialize_services(void)
646 g_assert(serv_port_hashtable == NULL);
647 serv_port_hashtable = g_hash_table_new_full(g_int_hash, g_int_equal, g_free, destroy_serv_port);
649 /* Compute the pathname of the services file. */
650 if (g_services_path == NULL) {
651 g_services_path = get_datafile_path(ENAME_SERVICES);
653 parse_services_file(g_services_path);
655 /* Compute the pathname of the personal services file */
656 if (g_pservices_path == NULL) {
657 g_pservices_path = get_persconffile_path(ENAME_SERVICES, FALSE);
659 parse_services_file(g_pservices_path);
663 service_name_lookup_cleanup(void)
665 if (serv_port_hashtable) {
666 g_hash_table_destroy(serv_port_hashtable);
667 serv_port_hashtable = NULL;
671 /* Fill in an IP4 structure with info from subnets file or just with the
672 * string form of the address.
675 fill_dummy_ip4(const guint addr, hashipv4_t* volatile tp)
677 subnet_entry_t subnet_entry;
679 if (tp->flags & DUMMY_ADDRESS_ENTRY)
680 return; /* already done */
682 tp->flags |= DUMMY_ADDRESS_ENTRY; /* Overwrite if we get async DNS reply */
684 /* Do we have a subnet for this address? */
685 subnet_entry = subnet_lookup(addr);
686 if (0 != subnet_entry.mask) {
687 /* Print name, then '.' then IP address after subnet mask */
689 gchar buffer[MAX_IP_STR_LEN];
693 host_addr = addr & (~(guint32)subnet_entry.mask);
694 ip_to_str_buf((guint8 *)&host_addr, buffer, MAX_IP_STR_LEN);
697 /* Skip to first octet that is not totally masked
698 * If length of mask is 32, we chomp the whole address.
699 * If the address string starts '.' (should not happen?),
702 i = subnet_entry.mask_length / 8;
703 while(*(paddr) != '\0' && i > 0) {
704 if (*(++paddr) == '.') {
709 /* There are more efficient ways to do this, but this is safe if we
710 * trust g_snprintf and MAXNAMELEN
712 g_snprintf(tp->name, MAXNAMELEN, "%s%s", subnet_entry.name, paddr);
714 ip_to_str_buf((const guint8 *)&addr, tp->name, MAXNAMELEN);
719 /* Fill in an IP6 structure with the string form of the address.
722 fill_dummy_ip6(hashipv6_t* volatile tp)
724 if (tp->flags & DUMMY_ADDRESS_ENTRY)
725 return; /* already done */
727 tp->flags |= DUMMY_ADDRESS_ENTRY; /* Overwrite if we get async DNS reply */
728 g_strlcpy(tp->name, tp->ip6, MAXNAMELEN);
737 #if ( ( ARES_VERSION_MAJOR < 1 ) \
738 || ( 1 == ARES_VERSION_MAJOR && ARES_VERSION_MINOR < 5 ) )
746 async_dns_queue_msg_t *caqm = (async_dns_queue_msg_t *)arg;
750 /* XXX, what to do if async_dns_in_flight == 0? */
751 async_dns_in_flight--;
753 if (status == ARES_SUCCESS) {
754 for (p = he->h_addr_list; *p != NULL; p++) {
755 switch(caqm->family) {
757 add_ipv4_name(caqm->addr.ip4, he->h_name);
760 add_ipv6_name(&caqm->addr.ip6, he->h_name);
763 /* Throw an exception? */
770 #endif /* HAVE_C_ARES */
772 /* --------------- */
774 new_ipv4(const guint addr)
776 hashipv4_t *tp = g_new(hashipv4_t, 1);
780 ip_to_str_buf((const guint8 *)&addr, tp->ip, sizeof(tp->ip));
785 host_lookup(const guint addr)
787 hashipv4_t * volatile tp;
789 tp = (hashipv4_t *)g_hash_table_lookup(ipv4_hash_table, GUINT_TO_POINTER(addr));
792 * We don't already have an entry for this host name; create one,
793 * and then try to resolve it.
796 g_hash_table_insert(ipv4_hash_table, GUINT_TO_POINTER(addr), tp);
797 } else if ((tp->flags & DUMMY_AND_RESOLVE_FLGS) != DUMMY_ADDRESS_ENTRY) {
802 * This hasn't been resolved yet, and we haven't tried to
803 * resolve it already.
806 fill_dummy_ip4(addr, tp);
807 if (!gbl_resolv_flags.network_name)
810 if (gbl_resolv_flags.use_external_net_name_resolver) {
811 tp->flags |= TRIED_RESOLVE_ADDRESS;
814 if (async_dns_initialized && name_resolve_concurrency > 0) {
815 add_async_dns_ipv4(AF_INET, addr);
824 /* --------------- */
826 new_ipv6(const struct e_in6_addr *addr)
828 hashipv6_t *tp = g_new(hashipv6_t,1);
829 memcpy(tp->addr, addr->bytes, sizeof tp->addr);
832 ip6_to_str_buf(addr, tp->ip6);
836 /* ------------------------------------ */
838 host_lookup6(const struct e_in6_addr *addr)
840 hashipv6_t * volatile tp;
842 async_dns_queue_msg_t *caqm;
845 tp = (hashipv6_t *)g_hash_table_lookup(ipv6_hash_table, addr);
848 * We don't already have an entry for this host name; create one,
849 * and then try to resolve it.
851 struct e_in6_addr *addr_key;
853 addr_key = g_new(struct e_in6_addr,1);
855 memcpy(addr_key, addr, 16);
856 g_hash_table_insert(ipv6_hash_table, addr_key, tp);
857 } else if ((tp->flags & DUMMY_AND_RESOLVE_FLGS) != DUMMY_ADDRESS_ENTRY) {
862 * This hasn't been resolved yet, and we haven't tried to
863 * resolve it already.
867 if (!gbl_resolv_flags.network_name)
870 if (gbl_resolv_flags.use_external_net_name_resolver) {
871 tp->flags |= TRIED_RESOLVE_ADDRESS;
873 if (async_dns_initialized && name_resolve_concurrency > 0) {
874 caqm = g_new(async_dns_queue_msg_t,1);
875 caqm->family = AF_INET6;
876 memcpy(&caqm->addr.ip6, addr, sizeof(caqm->addr.ip6));
877 async_dns_queue_head = g_list_append(async_dns_queue_head, (gpointer) caqm);
887 * Ethernet / manufacturer resolution
889 * The following functions implement ethernet address resolution and
890 * ethers files parsing (see ethers(4)).
892 * The manuf file has the same format as ethers(4) except that names are
893 * truncated to MAXMANUFLEN-1 (8) characters and that an address contains
894 * only 3 bytes (instead of 6).
898 * I decide to not use the existing functions (see ethers(3) on some
899 * operating systems) for the following reasons:
900 * - performance gains (use of hash tables and some other enhancements),
901 * - use of two ethers files (system-wide and per user),
902 * - avoid the use of NIS maps,
903 * - lack of these functions on some systems.
905 * So the following functions do _not_ behave as the standard ones.
912 * If "manuf_file" is FALSE, parse a 6-byte MAC address.
913 * If "manuf_file" is TRUE, parse an up-to-6-byte sequence with an optional
917 parse_ether_address(const char *cp, ether_t *eth, unsigned int *mask,
918 const gboolean manuf_file)
925 for (i = 0; i < 6; i++) {
926 /* Get a hex number, 1 or 2 digits, no sign characters allowed. */
927 if (!g_ascii_isxdigit(*cp))
929 num = strtoul(cp, &p, 16);
931 return FALSE; /* failed */
933 return FALSE; /* not a valid octet */
934 eth->addr[i] = (guint8) num;
935 cp = p; /* skip past the number */
937 /* OK, what character terminated the octet? */
939 /* "/" - this has a mask. */
941 /* Entries with masks are allowed only in the "manuf" files. */
944 cp++; /* skip past the '/' to get to the mask */
945 if (!g_ascii_isdigit(*cp))
946 return FALSE; /* no sign allowed */
947 num = strtoul(cp, &p, 10);
949 return FALSE; /* failed */
950 cp = p; /* skip past the number */
951 if (*cp != '\0' && !g_ascii_isspace(*cp))
952 return FALSE; /* bogus terminator */
953 if (num == 0 || num >= 48)
954 return FALSE; /* bogus mask */
955 /* Mask out the bits not covered by the mask */
957 for (i = 0; num >= 8; i++, num -= 8)
958 ; /* skip octets entirely covered by the mask */
959 /* Mask out the first masked octet */
960 eth->addr[i] &= (0xFF << (8 - num));
962 /* Mask out completely-masked-out octets */
968 /* We're at the end of the address, and there's no mask. */
970 /* We got 3 bytes, so this is a manufacturer ID. */
972 /* Manufacturer IDs are only allowed in the "manuf"
976 /* Indicate that this is a manufacturer ID (0 is not allowed
983 /* We got 6 bytes, so this is a MAC address.
984 If we're reading one of the "manuf" files, indicate that
985 this is a MAC address (48 is not allowed as a mask). */
991 /* We didn't get 3 or 6 bytes, and there's no mask; this is
996 /* We don't know the separator used in this number; it can either
997 be ':', '-', or '.'. */
998 if (*cp != ':' && *cp != '-' && *cp != '.')
1000 sep = *cp; /* subsequent separators must be the same */
1002 /* It has to be the same as the first separator */
1014 parse_ether_line(char *line, ether_t *eth, unsigned int *mask,
1015 const gboolean manuf_file)
1018 * See the ethers(4) or ethers(5) man page for ethers file format
1019 * (not available on all systems).
1020 * We allow both ethernet address separators (':' and '-'),
1021 * as well as Wireshark's '.' separator.
1026 if ((cp = strchr(line, '#')))
1029 if ((cp = strtok(line, " \t")) == NULL)
1032 if (!parse_ether_address(cp, eth, mask, manuf_file))
1035 if ((cp = strtok(NULL, " \t")) == NULL)
1038 g_strlcpy(eth->name, cp, MAXNAMELEN);
1042 } /* parse_ether_line */
1044 static FILE *eth_p = NULL;
1047 set_ethent(char *path)
1052 eth_p = ws_fopen(path, "r");
1065 get_ethent(unsigned int *mask, const gboolean manuf_file)
1069 static int size = 0;
1070 static char *buf = NULL;
1075 while (fgetline(&buf, &size, eth_p) >= 0) {
1076 if (parse_ether_line(buf, ð, mask, manuf_file) == 0) {
1087 get_ethbyname(const gchar *name)
1091 set_ethent(g_pethers_path);
1093 while (((eth = get_ethent(NULL, FALSE)) != NULL) && strncmp(name, eth->name, MAXNAMELEN) != 0)
1099 set_ethent(g_ethers_path);
1101 while (((eth = get_ethent(NULL, FALSE)) != NULL) && strncmp(name, eth->name, MAXNAMELEN) != 0)
1109 } /* get_ethbyname */
1113 get_ethbyaddr(const guint8 *addr)
1118 set_ethent(g_pethers_path);
1120 while (((eth = get_ethent(NULL, FALSE)) != NULL) && memcmp(addr, eth->addr, 6) != 0)
1126 set_ethent(g_ethers_path);
1128 while (((eth = get_ethent(NULL, FALSE)) != NULL) && memcmp(addr, eth->addr, 6) != 0)
1136 } /* get_ethbyaddr */
1138 static hashmanuf_t *manuf_hash_new_entry(const guint8 *addr, char* name)
1141 hashmanuf_t *manuf_value;
1144 /* manuf needs only the 3 most significant octets of the ethernet address */
1145 manuf_key = (int *)g_new(int, 1);
1146 *manuf_key = (int)((addr[0] << 16) + (addr[1] << 8) + addr[2]);
1147 manuf_value = g_new(hashmanuf_t, 1);
1149 memcpy(manuf_value->addr, addr, 3);
1150 manuf_value->status = (name != NULL) ? HASHETHER_STATUS_RESOLVED_NAME : HASHETHER_STATUS_UNRESOLVED;
1152 g_strlcpy(manuf_value->resolved_name, name, MAXNAMELEN);
1153 manuf_value->status = HASHETHER_STATUS_RESOLVED_NAME;
1156 manuf_value->status = HASHETHER_STATUS_UNRESOLVED;
1157 manuf_value->resolved_name[0] = '\0';
1159 /* Values returned by bytes_to_hexstr_punct() are *not* null-terminated */
1160 endp = bytes_to_hexstr_punct(manuf_value->hexaddr, addr, sizeof(manuf_value->addr), ':');
1163 g_hash_table_insert(manuf_hashtable, manuf_key, manuf_value);
1168 add_manuf_name(const guint8 *addr, unsigned int mask, gchar *name)
1173 * XXX - can we use Standard Annotation Language annotations to
1174 * note that mask, as returned by parse_ethe)r_address() (and thus
1175 * by the routines that call it, and thus passed to us) cannot be > 48,
1176 * or is SAL too weak to express that?
1179 /* This is a well-known MAC address; just add this to the Ethernet
1181 add_eth_name(addr, name);
1186 /* This is a manufacturer ID; add it to the manufacturer ID hash table */
1187 manuf_hash_new_entry(addr, name);
1191 /* This is a range of well-known addresses; add it to the appropriate
1192 well-known-address table, creating that table if necessary. */
1194 wka_key = (guint8 *)g_malloc(6);
1195 memcpy(wka_key, addr, 6);
1197 g_hash_table_insert(wka_hashtable, wka_key, g_strdup(name));
1199 } /* add_manuf_name */
1201 static hashmanuf_t *
1202 manuf_name_lookup(const guint8 *addr)
1204 gint32 manuf_key = 0;
1206 hashmanuf_t *manuf_value;
1208 /* manuf needs only the 3 most significant octets of the ethernet address */
1209 manuf_key = addr[0];
1210 manuf_key = manuf_key<<8;
1212 manuf_key = manuf_key | oct;
1213 manuf_key = manuf_key<<8;
1215 manuf_key = manuf_key | oct;
1218 /* first try to find a "perfect match" */
1219 manuf_value = (hashmanuf_t*)g_hash_table_lookup(manuf_hashtable, &manuf_key);
1220 if (manuf_value != NULL) {
1224 /* Mask out the broadcast/multicast flag but not the locally
1225 * administered flag as locally administered means: not assigned
1226 * by the IEEE but the local administrator instead.
1227 * 0x01 multicast / broadcast bit
1228 * 0x02 locally administered bit */
1229 if ((manuf_key & 0x00010000) != 0) {
1230 manuf_key &= 0x00FEFFFF;
1231 manuf_value = (hashmanuf_t*)g_hash_table_lookup(manuf_hashtable, &manuf_key);
1232 if (manuf_value != NULL) {
1237 /* Add the address as a hex string */
1238 return manuf_hash_new_entry(addr, NULL);
1240 } /* manuf_name_lookup */
1243 wka_name_lookup(const guint8 *addr, const unsigned int mask)
1245 guint8 masked_addr[6];
1250 if (wka_hashtable == NULL) {
1253 /* Get the part of the address covered by the mask. */
1254 for (i = 0, num = mask; num >= 8; i++, num -= 8)
1255 masked_addr[i] = addr[i]; /* copy octets entirely covered by the mask */
1256 /* Mask out the first masked octet */
1257 masked_addr[i] = addr[i] & (0xFF << (8 - num));
1259 /* Zero out completely-masked-out octets */
1263 name = (gchar *)g_hash_table_lookup(wka_hashtable, masked_addr);
1267 } /* wka_name_lookup */
1270 guint get_hash_ether_status(hashether_t* ether)
1272 return ether->status;
1275 char* get_hash_ether_hexaddr(hashether_t* ether)
1277 return ether->hexaddr;
1280 char* get_hash_ether_resolved_name(hashether_t* ether)
1282 return ether->resolved_name;
1286 eth_addr_hash(gconstpointer key)
1288 return wmem_strong_hash((const guint8 *)key, 6);
1292 eth_addr_cmp(gconstpointer a, gconstpointer b)
1294 return (memcmp(a, b, 6) == 0);
1298 initialize_ethers(void)
1304 /* hash table initialization */
1305 wka_hashtable = g_hash_table_new_full(eth_addr_hash, eth_addr_cmp, g_free, g_free);
1306 manuf_hashtable = g_hash_table_new_full(g_int_hash, g_int_equal, g_free, g_free);
1307 eth_hashtable = g_hash_table_new_full(eth_addr_hash, eth_addr_cmp, NULL, g_free);
1309 /* Compute the pathname of the ethers file. */
1310 if (g_ethers_path == NULL) {
1311 g_ethers_path = g_strdup_printf("%s" G_DIR_SEPARATOR_S "%s",
1312 get_systemfile_dir(), ENAME_ETHERS);
1315 /* Set g_pethers_path here, but don't actually do anything
1316 * with it. It's used in get_ethbyname() and get_ethbyaddr()
1318 if (g_pethers_path == NULL)
1319 g_pethers_path = get_persconffile_path(ENAME_ETHERS, FALSE);
1321 /* Compute the pathname of the manuf file */
1322 manuf_path = get_datafile_path(ENAME_MANUF);
1324 /* Read it and initialize the hash table */
1325 set_ethent(manuf_path);
1327 while ((eth = get_ethent(&mask, TRUE))) {
1328 add_manuf_name(eth->addr, mask, eth->name);
1335 } /* initialize_ethers */
1337 /* this is only needed when shuting down application (if at all) */
1339 eth_name_lookup_cleanup(void)
1342 if (manuf_hashtable) {
1343 g_hash_table_destroy(manuf_hashtable);
1344 manuf_hashtable = NULL;
1346 if (wka_hashtable) {
1347 g_hash_table_destroy(wka_hashtable);
1348 wka_hashtable = NULL;
1351 if (eth_hashtable) {
1352 g_hash_table_destroy(eth_hashtable);
1353 eth_hashtable = NULL;
1358 /* Resolve ethernet address */
1359 static hashether_t *
1360 eth_addr_resolve(hashether_t *tp) {
1362 hashmanuf_t *manuf_value;
1363 const guint8 *addr = tp->addr;
1365 if ( (eth = get_ethbyaddr(addr)) != NULL) {
1366 g_strlcpy(tp->resolved_name, eth->name, MAXNAMELEN);
1367 tp->status = HASHETHER_STATUS_RESOLVED_NAME;
1374 /* Unknown name. Try looking for it in the well-known-address
1375 tables for well-known address ranges smaller than 2^24. */
1378 /* Only the topmost 5 bytes participate fully */
1379 if ((name = wka_name_lookup(addr, mask+40)) != NULL) {
1380 g_snprintf(tp->resolved_name, MAXNAMELEN, "%s_%02x",
1381 name, addr[5] & (0xFF >> mask));
1382 tp->status = HASHETHER_STATUS_RESOLVED_DUMMY;
1392 /* Only the topmost 4 bytes participate fully */
1393 if ((name = wka_name_lookup(addr, mask+32)) != NULL) {
1394 g_snprintf(tp->resolved_name, MAXNAMELEN, "%s_%02x:%02x",
1395 name, addr[4] & (0xFF >> mask), addr[5]);
1396 tp->status = HASHETHER_STATUS_RESOLVED_DUMMY;
1406 /* Only the topmost 3 bytes participate fully */
1407 if ((name = wka_name_lookup(addr, mask+24)) != NULL) {
1408 g_snprintf(tp->resolved_name, MAXNAMELEN, "%s_%02x:%02x:%02x",
1409 name, addr[3] & (0xFF >> mask), addr[4], addr[5]);
1410 tp->status = HASHETHER_STATUS_RESOLVED_DUMMY;
1418 /* Now try looking in the manufacturer table. */
1419 manuf_value = manuf_name_lookup(addr);
1420 if ((manuf_value != NULL) && (manuf_value->status != HASHETHER_STATUS_UNRESOLVED)) {
1421 g_snprintf(tp->resolved_name, MAXNAMELEN, "%s_%02x:%02x:%02x",
1422 manuf_value->resolved_name, addr[3], addr[4], addr[5]);
1423 tp->status = HASHETHER_STATUS_RESOLVED_DUMMY;
1427 /* Now try looking for it in the well-known-address
1428 tables for well-known address ranges larger than 2^24. */
1431 /* Only the topmost 2 bytes participate fully */
1432 if ((name = wka_name_lookup(addr, mask+16)) != NULL) {
1433 g_snprintf(tp->resolved_name, MAXNAMELEN, "%s_%02x:%02x:%02x:%02x",
1434 name, addr[2] & (0xFF >> mask), addr[3], addr[4],
1436 tp->status = HASHETHER_STATUS_RESOLVED_DUMMY;
1446 /* Only the topmost byte participates fully */
1447 if ((name = wka_name_lookup(addr, mask+8)) != NULL) {
1448 g_snprintf(tp->resolved_name, MAXNAMELEN, "%s_%02x:%02x:%02x:%02x:%02x",
1449 name, addr[1] & (0xFF >> mask), addr[2], addr[3],
1451 tp->status = HASHETHER_STATUS_RESOLVED_DUMMY;
1459 for (mask = 7; mask > 0; mask--) {
1460 /* Not even the topmost byte participates fully */
1461 if ((name = wka_name_lookup(addr, mask)) != NULL) {
1462 g_snprintf(tp->resolved_name, MAXNAMELEN, "%s_%02x:%02x:%02x:%02x:%02x:%02x",
1463 name, addr[0] & (0xFF >> mask), addr[1], addr[2],
1464 addr[3], addr[4], addr[5]);
1465 tp->status = HASHETHER_STATUS_RESOLVED_DUMMY;
1470 /* No match whatsoever. */
1471 set_address(ðer_addr, AT_ETHER, 6, addr);
1472 address_to_str_buf(ðer_addr, tp->resolved_name, MAXNAMELEN);
1473 tp->status = HASHETHER_STATUS_RESOLVED_DUMMY;
1476 g_assert_not_reached();
1477 } /* eth_addr_resolve */
1479 static hashether_t *
1480 eth_hash_new_entry(const guint8 *addr, const gboolean resolve)
1485 tp = g_new(hashether_t, 1);
1486 memcpy(tp->addr, addr, sizeof(tp->addr));
1487 tp->status = HASHETHER_STATUS_UNRESOLVED;
1488 /* Values returned by bytes_to_hexstr_punct() are *not* null-terminated */
1489 endp = bytes_to_hexstr_punct(tp->hexaddr, addr, sizeof(tp->addr), ':');
1491 tp->resolved_name[0] = '\0';
1494 eth_addr_resolve(tp);
1496 g_hash_table_insert(eth_hashtable, tp->addr, tp);
1499 } /* eth_hash_new_entry */
1501 static hashether_t *
1502 add_eth_name(const guint8 *addr, const gchar *name)
1506 tp = (hashether_t *)g_hash_table_lookup(eth_hashtable, addr);
1509 tp = eth_hash_new_entry(addr, FALSE);
1512 if (strcmp(tp->resolved_name, name) != 0) {
1513 g_strlcpy(tp->resolved_name, name, MAXNAMELEN);
1514 tp->status = HASHETHER_STATUS_RESOLVED_NAME;
1515 new_resolved_objects = TRUE;
1519 } /* add_eth_name */
1521 static hashether_t *
1522 eth_name_lookup(const guint8 *addr, const gboolean resolve)
1526 tp = (hashether_t *)g_hash_table_lookup(eth_hashtable, addr);
1528 tp = eth_hash_new_entry(addr, resolve);
1530 if (resolve && (tp->status == HASHETHER_STATUS_UNRESOLVED)) {
1531 eth_addr_resolve(tp); /* Found but needs to be resolved */
1537 } /* eth_name_lookup */
1540 eth_addr_lookup(const gchar *name _U_)
1543 /* XXX Do we need reverse lookup??? */
1546 hashether_t **table = eth_table;
1549 /* to be optimized (hash table from name to addr) */
1550 for (i = 0; i < HASHETHSIZE; i++) {
1553 if (strcmp(tp->resolved_name, name) == 0)
1559 /* not in hash table : performs a file lookup */
1561 if ((eth = get_ethbyname(name)) == NULL)
1564 /* add new entry in hash table */
1566 tp = add_eth_name(eth->addr, name);
1572 } /* eth_addr_lookup */
1577 parse_ipxnets_line(char *line, ipxnet_t *ipxnet)
1580 * We allow three address separators (':', '-', and '.'),
1581 * as well as no separators
1585 guint32 a, a0, a1, a2, a3;
1586 gboolean found_single_number = FALSE;
1588 if ((cp = strchr(line, '#')))
1591 if ((cp = strtok(line, " \t\n")) == NULL)
1594 /* Either fill a0,a1,a2,a3 and found_single_number is FALSE,
1595 * fill a and found_single_number is TRUE,
1598 if (sscanf(cp, "%x:%x:%x:%x", &a0, &a1, &a2, &a3) != 4) {
1599 if (sscanf(cp, "%x-%x-%x-%x", &a0, &a1, &a2, &a3) != 4) {
1600 if (sscanf(cp, "%x.%x.%x.%x", &a0, &a1, &a2, &a3) != 4) {
1601 if (sscanf(cp, "%x", &a) == 1) {
1602 found_single_number = TRUE;
1611 if ((cp = strtok(NULL, " \t\n")) == NULL)
1614 if (found_single_number) {
1618 ipxnet->addr = (a0 << 24) | (a1 << 16) | (a2 << 8) | a3;
1621 g_strlcpy(ipxnet->name, cp, MAXNAMELEN);
1625 } /* parse_ipxnets_line */
1627 static FILE *ipxnet_p = NULL;
1630 set_ipxnetent(char *path)
1635 ipxnet_p = ws_fopen(path, "r");
1651 static ipxnet_t ipxnet;
1652 static int size = 0;
1653 static char *buf = NULL;
1655 if (ipxnet_p == NULL)
1658 while (fgetline(&buf, &size, ipxnet_p) >= 0) {
1659 if (parse_ipxnets_line(buf, &ipxnet) == 0) {
1666 } /* get_ipxnetent */
1671 get_ipxnetbyname(const gchar *name)
1675 set_ipxnetent(g_ipxnets_path);
1677 while (((ipxnet = get_ipxnetent()) != NULL) && strncmp(name, ipxnet->name, MAXNAMELEN) != 0)
1680 if (ipxnet == NULL) {
1683 set_ipxnetent(g_pipxnets_path);
1685 while (((ipxnet = get_ipxnetent()) != NULL) && strncmp(name, ipxnet->name, MAXNAMELEN) != 0)
1693 } /* get_ipxnetbyname */
1697 get_ipxnetbyaddr(guint32 addr)
1701 set_ipxnetent(g_ipxnets_path);
1703 while (((ipxnet = get_ipxnetent()) != NULL) && (addr != ipxnet->addr) ) ;
1705 if (ipxnet == NULL) {
1708 set_ipxnetent(g_pipxnets_path);
1710 while (((ipxnet = get_ipxnetent()) != NULL) && (addr != ipxnet->addr) )
1718 } /* get_ipxnetbyaddr */
1721 initialize_ipxnets(void)
1723 /* Compute the pathname of the ipxnets file.
1725 * XXX - is there a notion of an "ipxnets file" in any flavor of
1726 * UNIX, or with any add-on Netware package for UNIX? If not,
1727 * should the UNIX version of the ipxnets file be in the datafile
1728 * directory as well?
1730 if (g_ipxnets_path == NULL) {
1731 g_ipxnets_path = g_strdup_printf("%s" G_DIR_SEPARATOR_S "%s",
1732 get_systemfile_dir(), ENAME_IPXNETS);
1735 /* Set g_pipxnets_path here, but don't actually do anything
1736 * with it. It's used in get_ipxnetbyname() and get_ipxnetbyaddr()
1738 if (g_pipxnets_path == NULL)
1739 g_pipxnets_path = get_persconffile_path(ENAME_IPXNETS, FALSE);
1741 } /* initialize_ipxnets */
1744 ipx_name_lookup_cleanup(void)
1746 if (ipxnet_hash_table) {
1747 g_hash_table_destroy(ipxnet_hash_table);
1748 ipxnet_hash_table = NULL;
1754 static hashipxnet_t *
1755 add_ipxnet_name(guint addr, const gchar *name)
1759 tp = (hashipxnet_t *)g_hash_table_lookup(ipxnet_hash_table, &addr);
1761 g_strlcpy(tp->name, name, MAXNAMELEN);
1765 key = (int *)g_new(int, 1);
1767 tp = g_new(hashipxnet_t,1);
1768 g_strlcpy(tp->name, name, MAXNAMELEN);
1769 g_hash_table_insert(ipxnet_hash_table, key, tp);
1773 g_strlcpy(tp->name, name, MAXNAMELEN);
1775 new_resolved_objects = TRUE;
1779 } /* add_ipxnet_name */
1783 ipxnet_name_lookup(wmem_allocator_t *allocator, const guint addr)
1788 tp = (hashipxnet_t *)g_hash_table_lookup(ipxnet_hash_table, &addr);
1792 key = (int *)g_new(int, 1);
1794 tp = g_new(hashipxnet_t, 1);
1795 g_hash_table_insert(ipxnet_hash_table, key, tp);
1797 return wmem_strdup(allocator, tp->name);
1800 /* fill in a new entry */
1804 if ( (ipxnet = get_ipxnetbyaddr(addr)) == NULL) {
1806 g_snprintf(tp->name, MAXNAMELEN, "%X", addr);
1809 g_strlcpy(tp->name, ipxnet->name, MAXNAMELEN);
1812 return wmem_strdup(allocator, tp->name);
1814 } /* ipxnet_name_lookup */
1817 ipxnet_addr_lookup(const gchar *name _U_, gboolean *success)
1822 /* XXX Do we need reverse lookup??? */
1825 hashipxnet_t **table = ipxnet_table;
1828 /* to be optimized (hash table from name to addr) */
1829 for (i = 0; i < HASHIPXNETSIZE; i++) {
1832 if (strcmp(tp->name, name) == 0) {
1840 /* not in hash table : performs a file lookup */
1842 if ((ipxnet = get_ipxnetbyname(name)) == NULL) {
1847 /* add new entry in hash table */
1849 tp = add_ipxnet_name(ipxnet->addr, name);
1854 } /* ipxnet_addr_lookup */
1858 parse_vlan_line(char *line, vlan_t *vlan)
1863 if ((cp = strchr(line, '#')))
1866 if ((cp = strtok(line, " \t\n")) == NULL)
1869 if (sscanf(cp, "%" G_GUINT16_FORMAT, &id) == 1) {
1876 if ((cp = strtok(NULL, "\t\n")) == NULL)
1879 g_strlcpy(vlan->name, cp, MAXVLANNAMELEN);
1883 } /* parse_vlan_line */
1885 static FILE *vlan_p = NULL;
1888 set_vlanent(char *path)
1893 vlan_p = ws_fopen(path, "r");
1910 static int size = 0;
1911 static char *buf = NULL;
1916 while (fgetline(&buf, &size, vlan_p) >= 0) {
1917 if (parse_vlan_line(buf, &vlan) == 0) {
1927 get_vlannamebyid(guint16 id)
1931 set_vlanent(g_pvlan_path);
1933 while (((vlan = get_vlanent()) != NULL) && (id != vlan->id) ) ;
1942 } /* get_vlannamebyid */
1945 initialize_vlans(void)
1947 g_assert(vlan_hash_table == NULL);
1948 vlan_hash_table = g_hash_table_new_full(g_int_hash, g_int_equal, g_free, g_free);
1950 /* Set g_pipxnets_path here, but don't actually do anything
1951 * with it. It's used in get_ipxnetbyname() and get_ipxnetbyaddr()
1953 if (g_pvlan_path == NULL)
1954 g_pvlan_path = get_persconffile_path(ENAME_VLANS, FALSE);
1956 } /* initialize_vlans */
1959 vlan_name_lookup_cleanup(void)
1961 if (vlan_hash_table) {
1962 g_hash_table_destroy(vlan_hash_table);
1963 vlan_hash_table = NULL;
1968 static const gchar *
1969 vlan_name_lookup(const guint id)
1974 tp = (hashvlan_t *)g_hash_table_lookup(vlan_hash_table, &id);
1978 key = (int *)g_new(int, 1);
1980 tp = g_new(hashvlan_t, 1);
1981 g_hash_table_insert(vlan_hash_table, key, tp);
1986 /* fill in a new entry */
1990 if ( (vlan = get_vlannamebyid(id)) == NULL) {
1992 g_snprintf(tp->name, MAXVLANNAMELEN, "<%u>", id);
1995 g_strlcpy(tp->name, vlan->name, MAXVLANNAMELEN);
2000 } /* vlan_name_lookup */
2004 read_hosts_file (const char *hostspath, gboolean store_entries)
2012 struct e_in6_addr ip6_addr;
2014 gboolean is_ipv6, entry_found = FALSE;
2017 * See the hosts(4) or hosts(5) man page for hosts file format
2018 * (not available on all systems).
2020 if ((hf = ws_fopen(hostspath, "r")) == NULL)
2023 while (fgetline(&line, &size, hf) >= 0) {
2024 if ((cp = strchr(line, '#')))
2027 if ((cp = strtok(line, " \t")) == NULL)
2028 continue; /* no tokens in the line */
2030 if (ws_inet_pton6(cp, &host_addr.ip6_addr)) {
2033 } else if (ws_inet_pton4(cp, &host_addr.ip4_addr)) {
2040 if ((cp = strtok(NULL, " \t")) == NULL)
2041 continue; /* no host name */
2044 if (store_entries) {
2046 add_ipv6_name(&host_addr.ip6_addr, cp);
2048 add_ipv4_name(host_addr.ip4_addr, cp);
2055 return entry_found ? TRUE : FALSE;
2056 } /* read_hosts_file */
2059 add_hosts_file (const char *hosts_file)
2061 gboolean found = FALSE;
2067 if (!extra_hosts_files)
2068 extra_hosts_files = g_ptr_array_new();
2070 for (i = 0; i < extra_hosts_files->len; i++) {
2071 if (strcmp(hosts_file, (const char *) g_ptr_array_index(extra_hosts_files, i)) == 0)
2076 g_ptr_array_add(extra_hosts_files, g_strdup(hosts_file));
2077 return read_hosts_file (hosts_file, FALSE);
2083 add_ip_name_from_string (const char *addr, const char *name)
2087 struct e_in6_addr ip6_addr;
2090 resolved_ipv4_t *resolved_ipv4_entry;
2091 resolved_ipv6_t *resolved_ipv6_entry;
2093 if (ws_inet_pton6(addr, &host_addr.ip6_addr)) {
2095 } else if (ws_inet_pton4(addr, &host_addr.ip4_addr)) {
2102 resolved_ipv6_entry = g_new(resolved_ipv6_t, 1);
2103 memcpy(&(resolved_ipv6_entry->ip6_addr), &host_addr.ip6_addr, 16);
2104 g_strlcpy(resolved_ipv6_entry->name, name, MAXNAMELEN);
2105 manually_resolved_ipv6_list = g_slist_prepend(manually_resolved_ipv6_list, resolved_ipv6_entry);
2107 resolved_ipv4_entry = g_new(resolved_ipv4_t, 1);
2108 resolved_ipv4_entry->host_addr = host_addr.ip4_addr;
2109 g_strlcpy(resolved_ipv4_entry->name, name, MAXNAMELEN);
2110 manually_resolved_ipv4_list = g_slist_prepend(manually_resolved_ipv4_list, resolved_ipv4_entry);
2114 } /* add_ip_name_from_string */
2117 * Add the resolved addresses that are in use to the list used to create the NRB
2120 ipv4_hash_table_resolved_to_list(gpointer key _U_, gpointer value, gpointer user_data)
2122 addrinfo_lists_t *lists = (addrinfo_lists_t*)user_data;
2123 hashipv4_t *ipv4_hash_table_entry = (hashipv4_t *)value;
2125 if ((ipv4_hash_table_entry->flags & USED_AND_RESOLVED_MASK) == RESOLVED_ADDRESS_USED) {
2126 lists->ipv4_addr_list = g_list_prepend (lists->ipv4_addr_list, ipv4_hash_table_entry);
2132 * Add the resolved addresses that are in use to the list used to create the NRB
2136 ipv6_hash_table_resolved_to_list(gpointer key _U_, gpointer value, gpointer user_data)
2138 addrinfo_lists_t *lists = (addrinfo_lists_t*)user_data;
2139 hashipv6_t *ipv6_hash_table_entry = (hashipv6_t *)value;
2141 if ((ipv6_hash_table_entry->flags & USED_AND_RESOLVED_MASK) == RESOLVED_ADDRESS_USED) {
2142 lists->ipv6_addr_list = g_list_prepend (lists->ipv6_addr_list, ipv6_hash_table_entry);
2148 get_addrinfo_list(void) {
2150 if (ipv4_hash_table) {
2151 g_hash_table_foreach(ipv4_hash_table, ipv4_hash_table_resolved_to_list, &addrinfo_lists);
2154 if (ipv6_hash_table) {
2155 g_hash_table_foreach(ipv6_hash_table, ipv6_hash_table_resolved_to_list, &addrinfo_lists);
2158 return &addrinfo_lists;
2161 /* Read in a list of subnet definition - name pairs.
2162 * <line> = <comment> | <entry> | <whitespace>
2163 * <comment> = <whitespace>#<any>
2164 * <entry> = <subnet_definition> <whitespace> <subnet_name> [<comment>|<whitespace><any>]
2165 * <subnet_definition> = <ipv4_address> / <subnet_mask_length>
2166 * <ipv4_address> is a full address; it will be masked to get the subnet-ID.
2167 * <subnet_mask_length> is a decimal 1-31
2168 * <subnet_name> is a string containing no whitespace.
2169 * <whitespace> = (space | tab)+
2170 * Any malformed entries are ignored.
2171 * Any trailing data after the subnet_name is ignored.
2176 read_subnets_file (const char *subnetspath)
2182 guint32 host_addr; /* IPv4 ONLY */
2185 if ((hf = ws_fopen(subnetspath, "r")) == NULL)
2188 while (fgetline(&line, &size, hf) >= 0) {
2189 if ((cp = strchr(line, '#')))
2192 if ((cp = strtok(line, " \t")) == NULL)
2193 continue; /* no tokens in the line */
2196 /* Expected format is <IP4 address>/<subnet length> */
2197 cp2 = strchr(cp, '/');
2202 *cp2 = '\0'; /* Cut token */
2205 /* Check if this is a valid IPv4 address */
2206 if (!str_to_ip(cp, &host_addr)) {
2210 mask_length = atoi(cp2);
2211 if (0 >= mask_length || mask_length > 32) {
2212 continue; /* invalid mask length */
2215 if ((cp = strtok(NULL, " \t")) == NULL)
2216 continue; /* no subnet name */
2218 subnet_entry_set(host_addr, (guint32)mask_length, cp);
2224 } /* read_subnets_file */
2226 static subnet_entry_t
2227 subnet_lookup(const guint32 addr)
2229 subnet_entry_t subnet_entry;
2232 /* Search mask lengths linearly, longest first */
2234 i = SUBNETLENGTHSIZE;
2235 while(have_subnet_entry && i > 0) {
2236 guint32 masked_addr;
2237 subnet_length_entry_t* length_entry;
2239 /* Note that we run from 31 (length 32) to 0 (length 1) */
2241 g_assert(i < SUBNETLENGTHSIZE);
2244 length_entry = &subnet_length_entries[i];
2246 if (NULL != length_entry->subnet_addresses) {
2247 sub_net_hashipv4_t * tp;
2250 masked_addr = addr & length_entry->mask;
2251 hash_idx = HASH_IPV4_ADDRESS(masked_addr);
2253 tp = length_entry->subnet_addresses[hash_idx];
2254 while(tp != NULL && tp->addr != masked_addr) {
2259 subnet_entry.mask = length_entry->mask;
2260 subnet_entry.mask_length = i + 1; /* Length is offset + 1 */
2261 subnet_entry.name = tp->name;
2262 return subnet_entry;
2267 subnet_entry.mask = 0;
2268 subnet_entry.mask_length = 0;
2269 subnet_entry.name = NULL;
2271 return subnet_entry;
2274 /* Add a subnet-definition - name pair to the set.
2275 * The definition is taken by masking the address passed in with the mask of the
2279 subnet_entry_set(guint32 subnet_addr, const guint32 mask_length, const gchar* name)
2281 subnet_length_entry_t* entry;
2282 sub_net_hashipv4_t * tp;
2285 g_assert(mask_length > 0 && mask_length <= 32);
2287 entry = &subnet_length_entries[mask_length - 1];
2289 subnet_addr &= entry->mask;
2291 hash_idx = HASH_IPV4_ADDRESS(subnet_addr);
2293 if (NULL == entry->subnet_addresses) {
2294 entry->subnet_addresses = (sub_net_hashipv4_t**) g_malloc0(sizeof(sub_net_hashipv4_t*) * HASHHOSTSIZE);
2297 if (NULL != (tp = entry->subnet_addresses[hash_idx])) {
2298 sub_net_hashipv4_t * new_tp;
2301 if (tp->addr == subnet_addr) {
2302 return; /* XXX provide warning that an address was repeated? */
2308 new_tp = g_new(sub_net_hashipv4_t, 1);
2312 tp = entry->subnet_addresses[hash_idx] = g_new(sub_net_hashipv4_t, 1);
2316 tp->addr = subnet_addr;
2317 /* Clear DUMMY_ADDRESS_ENTRY */
2318 tp->flags &= ~DUMMY_ADDRESS_ENTRY; /*Never used again...*/
2319 g_strlcpy(tp->name, name, MAXNAMELEN); /* This is longer than subnet names can actually be */
2320 have_subnet_entry = TRUE;
2324 subnet_name_lookup_init(void)
2329 for(i = 0; i < SUBNETLENGTHSIZE; ++i) {
2330 guint32 length = i + 1;
2332 subnet_length_entries[i].subnet_addresses = NULL;
2333 subnet_length_entries[i].mask_length = length;
2334 subnet_length_entries[i].mask = g_htonl(ip_get_subnet_mask(length));
2337 subnetspath = get_persconffile_path(ENAME_SUBNETS, FALSE);
2338 if (!read_subnets_file(subnetspath) && errno != ENOENT) {
2339 report_open_failure(subnetspath, errno, FALSE);
2341 g_free(subnetspath);
2344 * Load the global subnets file, if we have one.
2346 subnetspath = get_datafile_path(ENAME_SUBNETS);
2347 if (!read_subnets_file(subnetspath) && errno != ENOENT) {
2348 report_open_failure(subnetspath, errno, FALSE);
2350 g_free(subnetspath);
2354 cleanup_subnet_entry(sub_net_hashipv4_t* entry)
2356 if ((entry != NULL) && (entry->next != NULL)) {
2357 cleanup_subnet_entry(entry->next);
2364 * External Functions
2368 addr_resolve_pref_init(module_t *nameres)
2370 prefs_register_bool_preference(nameres, "mac_name",
2371 "Resolve MAC addresses",
2372 "Resolve Ethernet MAC address to manufacturer names",
2373 &gbl_resolv_flags.mac_name);
2375 prefs_register_bool_preference(nameres, "transport_name",
2376 "Resolve transport names",
2377 "Resolve TCP/UDP ports into service names",
2378 &gbl_resolv_flags.transport_name);
2380 prefs_register_bool_preference(nameres, "network_name",
2381 "Resolve network (IP) addresses",
2382 "Resolve IPv4, IPv6, and IPX addresses into host names."
2383 " The next set of check boxes determines how name resolution should be performed."
2384 " If no other options are checked name resolution is made from Wireshark's host file,"
2385 " capture file name resolution blocks and DNS packets in the capture.",
2386 &gbl_resolv_flags.network_name);
2388 prefs_register_bool_preference(nameres, "dns_pkt_addr_resolution",
2389 "Use captured DNS packet data for address resolution",
2390 "Whether address/name pairs found in captured DNS packets should be used by Wireshark for name resolution.",
2391 &gbl_resolv_flags.dns_pkt_addr_resolution);
2394 prefs_register_bool_preference(nameres, "use_external_name_resolver",
2395 "Use an external network name resolver",
2396 "Use your system's configured name resolver"
2397 " (usually DNS) to resolve network names."
2398 " Only applies when network name resolution"
2400 &gbl_resolv_flags.use_external_net_name_resolver);
2402 prefs_register_obsolete_preference(nameres, "concurrent_dns");
2404 prefs_register_uint_preference(nameres, "name_resolve_concurrency",
2405 "Maximum concurrent requests",
2406 "The maximum number of DNS requests that may"
2407 " be active at any time. A large value (many"
2408 " thousands) might overload the network or make"
2409 " your DNS server behave badly.",
2411 &name_resolve_concurrency);
2413 prefs_register_static_text_preference(nameres, "use_external_name_resolver",
2414 "Use an external network name resolver: N/A",
2415 "Support for using a concurrent external name resolver was not"
2416 " compiled into this version of Wireshark");
2419 prefs_register_bool_preference(nameres, "hosts_file_handling",
2420 "Only use the profile \"hosts\" file",
2421 "By default \"hosts\" files will be loaded from multiple sources."
2422 " Checking this box only loads the \"hosts\" in the current profile.",
2423 &gbl_resolv_flags.load_hosts_file_from_profile_only);
2425 prefs_register_bool_preference(nameres, "vlan_name",
2427 "Resolve VLAN IDs to describing names."
2428 " To do so you need a file called vlans in your"
2429 " user preference directory. Format of the file is:"
2431 " One line per VLAN.",
2432 &gbl_resolv_flags.vlan_name);
2437 disable_name_resolution(void) {
2438 gbl_resolv_flags.mac_name = FALSE;
2439 gbl_resolv_flags.network_name = FALSE;
2440 gbl_resolv_flags.transport_name = FALSE;
2441 gbl_resolv_flags.dns_pkt_addr_resolution = FALSE;
2442 gbl_resolv_flags.use_external_net_name_resolver = FALSE;
2443 gbl_resolv_flags.vlan_name = FALSE;
2448 host_name_lookup_process(void) {
2449 async_dns_queue_msg_t *caqm;
2450 struct timeval tv = { 0, 0 };
2453 gboolean nro = new_resolved_objects;
2455 new_resolved_objects = FALSE;
2457 if (!async_dns_initialized)
2458 /* c-ares not initialized. Bail out and cancel timers. */
2461 async_dns_queue_head = g_list_first(async_dns_queue_head);
2463 while (async_dns_queue_head != NULL && async_dns_in_flight <= name_resolve_concurrency) {
2464 caqm = (async_dns_queue_msg_t *) async_dns_queue_head->data;
2465 async_dns_queue_head = g_list_remove(async_dns_queue_head, (void *) caqm);
2466 if (caqm->family == AF_INET) {
2467 ares_gethostbyaddr(ghba_chan, &caqm->addr.ip4, sizeof(guint32), AF_INET,
2468 c_ares_ghba_cb, caqm);
2469 async_dns_in_flight++;
2470 } else if (caqm->family == AF_INET6) {
2471 ares_gethostbyaddr(ghba_chan, &caqm->addr.ip6, sizeof(struct e_in6_addr),
2472 AF_INET6, c_ares_ghba_cb, caqm);
2473 async_dns_in_flight++;
2479 nfds = ares_fds(ghba_chan, &rfds, &wfds);
2481 if (select(nfds, &rfds, &wfds, NULL, &tv) == -1) { /* call to select() failed */
2482 fprintf(stderr, "Warning: call to select() failed, error is %s\n", g_strerror(errno));
2485 ares_process(ghba_chan, &rfds, &wfds);
2488 /* Any new entries? */
2493 _host_name_lookup_cleanup(void) {
2496 cur = g_list_first(async_dns_queue_head);
2499 cur = g_list_next (cur);
2502 g_list_free(async_dns_queue_head);
2503 async_dns_queue_head = NULL;
2505 if (async_dns_initialized) {
2506 ares_destroy(ghba_chan);
2507 ares_destroy(ghbn_chan);
2509 #ifdef CARES_HAVE_ARES_LIBRARY_INIT
2510 ares_library_cleanup();
2512 async_dns_initialized = FALSE;
2518 host_name_lookup_process(void) {
2519 gboolean nro = new_resolved_objects;
2521 new_resolved_objects = FALSE;
2527 _host_name_lookup_cleanup(void) {
2530 #endif /* HAVE_C_ARES */
2533 get_hostname(const guint addr)
2535 /* XXX why do we call this if we're not resolving? To create hash entries?
2538 hashipv4_t *tp = host_lookup(addr);
2540 if (!gbl_resolv_flags.network_name)
2543 tp->flags |= RESOLVED_ADDRESS_USED;
2548 /* -------------------------- */
2551 get_hostname6(const struct e_in6_addr *addr)
2553 /* XXX why do we call this if we're not resolving? To create hash entries?
2556 hashipv6_t *tp = host_lookup6(addr);
2558 if (!gbl_resolv_flags.network_name)
2561 tp->flags |= RESOLVED_ADDRESS_USED;
2566 /* -------------------------- */
2568 add_ipv4_name(const guint addr, const gchar *name)
2573 * Don't add zero-length names; apparently, some resolvers will return
2574 * them if they get them from DNS.
2576 if (!name || name[0] == '\0')
2579 tp = (hashipv4_t *)g_hash_table_lookup(ipv4_hash_table, GUINT_TO_POINTER(addr));
2581 tp = new_ipv4(addr);
2582 g_hash_table_insert(ipv4_hash_table, GUINT_TO_POINTER(addr), tp);
2585 if (g_ascii_strcasecmp(tp->name, name)) {
2586 g_strlcpy(tp->name, name, MAXNAMELEN);
2587 new_resolved_objects = TRUE;
2589 tp->flags |= TRIED_RESOLVE_ADDRESS|NAME_RESOLVED;
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 || name[0] == '\0')
2605 tp = (hashipv6_t *)g_hash_table_lookup(ipv6_hash_table, addrp);
2607 struct e_in6_addr *addr_key;
2609 addr_key = g_new(struct e_in6_addr,1);
2610 tp = new_ipv6(addrp);
2611 memcpy(addr_key, addrp, 16);
2612 g_hash_table_insert(ipv6_hash_table, addr_key, tp);
2615 if (g_ascii_strcasecmp(tp->name, name)) {
2616 g_strlcpy(tp->name, name, MAXNAMELEN);
2617 new_resolved_objects = TRUE;
2619 tp->flags |= TRIED_RESOLVE_ADDRESS|NAME_RESOLVED;
2620 } /* add_ipv6_name */
2623 add_manually_resolved_ipv4(gpointer data, gpointer user_data _U_)
2625 resolved_ipv4_t *resolved_ipv4_entry = (resolved_ipv4_t *)data;
2627 add_ipv4_name(resolved_ipv4_entry->host_addr, resolved_ipv4_entry->name);
2631 add_manually_resolved_ipv6(gpointer data, gpointer user_data _U_)
2633 resolved_ipv6_t *resolved_ipv6_entry = (resolved_ipv6_t *)data;
2635 add_ipv6_name(&(resolved_ipv6_entry->ip6_addr), resolved_ipv6_entry->name);
2639 add_manually_resolved(void)
2641 if (manually_resolved_ipv4_list) {
2642 g_slist_foreach(manually_resolved_ipv4_list, add_manually_resolved_ipv4, NULL);
2645 if (manually_resolved_ipv6_list) {
2646 g_slist_foreach(manually_resolved_ipv6_list, add_manually_resolved_ipv6, NULL);
2651 host_name_lookup_init(void)
2656 g_assert(ipxnet_hash_table == NULL);
2657 ipxnet_hash_table = g_hash_table_new_full(g_int_hash, g_int_equal, g_free, g_free);
2659 g_assert(ipv4_hash_table == NULL);
2660 ipv4_hash_table = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, g_free);
2662 g_assert(ipv6_hash_table == NULL);
2663 ipv6_hash_table = g_hash_table_new_full(ipv6_oat_hash, ipv6_equal, g_free, g_free);
2666 * Load the global hosts file, if we have one.
2668 if (!gbl_resolv_flags.load_hosts_file_from_profile_only) {
2669 hostspath = get_datafile_path(ENAME_HOSTS);
2670 if (!read_hosts_file(hostspath, TRUE) && errno != ENOENT) {
2671 report_open_failure(hostspath, errno, FALSE);
2676 * Load the user's hosts file no matter what, if they have one.
2678 hostspath = get_persconffile_path(ENAME_HOSTS, TRUE);
2679 if (!read_hosts_file(hostspath, TRUE) && errno != ENOENT) {
2680 report_open_failure(hostspath, errno, FALSE);
2684 #ifdef CARES_HAVE_ARES_LIBRARY_INIT
2685 if (ares_library_init(ARES_LIB_INIT_ALL) == ARES_SUCCESS) {
2687 if (ares_init(&ghba_chan) == ARES_SUCCESS && ares_init(&ghbn_chan) == ARES_SUCCESS) {
2688 async_dns_initialized = TRUE;
2690 #ifdef CARES_HAVE_ARES_LIBRARY_INIT
2694 #endif /* HAVE_C_ARES */
2696 if (extra_hosts_files && !gbl_resolv_flags.load_hosts_file_from_profile_only) {
2697 for (i = 0; i < extra_hosts_files->len; i++) {
2698 read_hosts_file((const char *) g_ptr_array_index(extra_hosts_files, i), TRUE);
2702 subnet_name_lookup_init();
2704 add_manually_resolved();
2708 host_name_lookup_cleanup(void)
2711 _host_name_lookup_cleanup();
2713 if (ipxnet_hash_table) {
2714 g_hash_table_destroy(ipxnet_hash_table);
2715 ipxnet_hash_table = NULL;
2718 if (ipv4_hash_table) {
2719 g_hash_table_destroy(ipv4_hash_table);
2720 ipv4_hash_table = NULL;
2723 if (ipv6_hash_table) {
2724 g_hash_table_destroy(ipv6_hash_table);
2725 ipv6_hash_table = NULL;
2728 for(i = 0; i < SUBNETLENGTHSIZE; ++i) {
2729 if (subnet_length_entries[i].subnet_addresses != NULL) {
2730 for (j = 0; j < HASHHOSTSIZE; j++) {
2731 if (subnet_length_entries[i].subnet_addresses[j] != NULL)
2733 cleanup_subnet_entry(subnet_length_entries[i].subnet_addresses[j]);
2736 g_free(subnet_length_entries[i].subnet_addresses);
2737 subnet_length_entries[i].subnet_addresses = NULL;
2741 have_subnet_entry = FALSE;
2742 new_resolved_objects = FALSE;
2746 free_manually_resolved_ipv4(gpointer data, gpointer user_data _U_)
2748 resolved_ipv4_t *resolved_ipv4_entry = (resolved_ipv4_t *)data;
2750 g_free(resolved_ipv4_entry);
2754 free_manually_resolved_ipv6(gpointer data, gpointer user_data _U_)
2756 resolved_ipv6_t *resolved_ipv6_entry = (resolved_ipv6_t *)data;
2758 g_free(resolved_ipv6_entry);
2762 manually_resolve_cleanup(void)
2764 if (manually_resolved_ipv4_list) {
2765 g_slist_foreach(manually_resolved_ipv4_list, free_manually_resolved_ipv4, NULL);
2766 g_slist_free(manually_resolved_ipv4_list);
2767 manually_resolved_ipv4_list = NULL;
2770 if (manually_resolved_ipv6_list) {
2771 g_slist_foreach(manually_resolved_ipv6_list, free_manually_resolved_ipv6, NULL);
2772 g_slist_free(manually_resolved_ipv6_list);
2773 manually_resolved_ipv6_list = NULL;
2779 udp_port_to_display(wmem_allocator_t *allocator, guint port)
2782 if (!gbl_resolv_flags.transport_name) {
2783 return wmem_utoa(allocator, port);
2786 return wmem_strdup(allocator, serv_name_lookup(PT_UDP, port));
2788 } /* udp_port_to_display */
2791 dccp_port_to_display(wmem_allocator_t *allocator, guint port)
2794 if (!gbl_resolv_flags.transport_name) {
2795 return wmem_utoa(allocator, port);
2798 return wmem_strdup(allocator, serv_name_lookup(PT_DCCP, port));
2800 } /* dccp_port_to_display */
2803 tcp_port_to_display(wmem_allocator_t *allocator, guint port)
2806 if (!gbl_resolv_flags.transport_name) {
2807 return wmem_utoa(allocator, port);
2810 return wmem_strdup(allocator, serv_name_lookup(PT_TCP, port));
2812 } /* tcp_port_to_display */
2815 sctp_port_to_display(wmem_allocator_t *allocator, guint port)
2818 if (!gbl_resolv_flags.transport_name) {
2819 return wmem_utoa(allocator, port);
2822 return wmem_strdup(allocator, serv_name_lookup(PT_SCTP, port));
2824 } /* sctp_port_to_display */
2827 port_with_resolution_to_str(wmem_allocator_t *scope, port_type proto, guint port)
2829 const gchar *port_str;
2831 if (!gbl_resolv_flags.transport_name || (proto == PT_NONE)) {
2832 /* No name resolution support, just return port string */
2833 return wmem_strdup_printf(scope, "%u", port);
2835 port_str = serv_name_lookup(proto, port);
2837 return wmem_strdup_printf(scope, "%s (%u)", port_str, port);
2841 port_with_resolution_to_str_buf(gchar *buf, gulong buf_size, port_type proto, guint port)
2843 const gchar *port_str;
2845 if (!gbl_resolv_flags.transport_name || (proto == PT_NONE)) {
2846 /* No name resolution support, just return port string */
2847 return g_snprintf(buf, buf_size, "%u", port);
2849 port_str = serv_name_lookup(proto, port);
2851 return g_snprintf(buf, buf_size, "%s (%u)", port_str, port);
2855 get_ether_name(const guint8 *addr)
2858 gboolean resolve = gbl_resolv_flags.mac_name;
2860 tp = eth_name_lookup(addr, resolve);
2862 return resolve ? tp->resolved_name : tp->hexaddr;
2864 } /* get_ether_name */
2867 tvb_get_ether_name(tvbuff_t *tvb, gint offset)
2869 return get_ether_name(tvb_get_ptr(tvb, offset, 6));
2872 /* Look for a (non-dummy) ether name in the hash, and return it if found.
2873 * If it's not found, simply return NULL.
2876 get_ether_name_if_known(const guint8 *addr)
2880 /* Initialize ether structs if we're the first
2881 * ether-related function called */
2882 if (!gbl_resolv_flags.mac_name)
2885 /* eth_name_lookup will create a (resolved) hash entry if it doesn't exist */
2886 tp = eth_name_lookup(addr, TRUE);
2887 g_assert(tp != NULL);
2889 if (tp->status == HASHETHER_STATUS_RESOLVED_NAME) {
2890 /* Name is from an ethers file (or is a "well-known" MAC address name from the manuf file) */
2891 return tp->resolved_name;
2894 /* Name was created */
2900 get_ether_addr(const gchar *name)
2903 /* force resolution (do not check gbl_resolv_flags) */
2904 return eth_addr_lookup(name);
2906 } /* get_ether_addr */
2909 add_ether_byip(const guint ip, const guint8 *eth)
2913 /* first check that IP address can be resolved */
2914 if (!gbl_resolv_flags.network_name)
2917 tp = host_lookup(ip);
2920 * Was this IP address resolved to a host name?
2922 if (tp->flags & NAME_RESOLVED) {
2924 * Yes, so add an entry in the ethers hashtable resolving
2925 * the MAC address to that name.
2927 add_eth_name(eth, tp->name);
2930 } /* add_ether_byip */
2933 ipxnet_to_str_punct(wmem_allocator_t *scope, const guint32 ad, const char punct)
2935 gchar *buf = (gchar *)wmem_alloc(scope, 12);
2937 *dword_to_hex_punct(buf, ad, punct) = '\0';
2942 get_ipxnet_name(wmem_allocator_t *allocator, const guint32 addr)
2945 if (!gbl_resolv_flags.network_name) {
2946 return ipxnet_to_str_punct(allocator, addr, '\0');
2949 return ipxnet_name_lookup(allocator, addr);
2951 } /* get_ipxnet_name */
2954 get_ipxnet_addr(const gchar *name, gboolean *known)
2959 /* force resolution (do not check gbl_resolv_flags) */
2960 addr = ipxnet_addr_lookup(name, &success);
2965 } /* get_ipxnet_addr */
2968 get_vlan_name(wmem_allocator_t *allocator, const guint16 id)
2971 if (!gbl_resolv_flags.vlan_name) {
2975 return wmem_strdup(allocator, vlan_name_lookup(id));
2977 } /* get_vlan_name */
2980 get_manuf_name(const guint8 *addr)
2982 hashmanuf_t *manuf_value;
2984 manuf_value = manuf_name_lookup(addr);
2985 if (gbl_resolv_flags.mac_name && manuf_value->status != HASHETHER_STATUS_UNRESOLVED)
2986 return manuf_value->resolved_name;
2988 return manuf_value->hexaddr;
2990 } /* get_manuf_name */
2993 uint_get_manuf_name(const guint oid)
2997 addr[0] = (oid >> 16) & 0xFF;
2998 addr[1] = (oid >> 8) & 0xFF;
2999 addr[2] = (oid >> 0) & 0xFF;
3000 return get_manuf_name(addr);
3004 tvb_get_manuf_name(tvbuff_t *tvb, gint offset)
3006 return get_manuf_name(tvb_get_ptr(tvb, offset, 3));
3010 get_manuf_name_if_known(const guint8 *addr)
3012 hashmanuf_t *manuf_value;
3016 /* manuf needs only the 3 most significant octets of the ethernet address */
3017 manuf_key = addr[0];
3018 manuf_key = manuf_key<<8;
3020 manuf_key = manuf_key | oct;
3021 manuf_key = manuf_key<<8;
3023 manuf_key = manuf_key | oct;
3025 manuf_value = (hashmanuf_t *)g_hash_table_lookup(manuf_hashtable, &manuf_key);
3026 if ((manuf_value == NULL) || (manuf_value->status != HASHETHER_STATUS_UNRESOLVED)) {
3030 return manuf_value->resolved_name;
3032 } /* get_manuf_name_if_known */
3035 uint_get_manuf_name_if_known(const guint manuf_key)
3037 hashmanuf_t *manuf_value;
3039 manuf_value = (hashmanuf_t *)g_hash_table_lookup(manuf_hashtable, &manuf_key);
3040 if ((manuf_value == NULL) || (manuf_value->status != HASHETHER_STATUS_UNRESOLVED)) {
3044 return manuf_value->resolved_name;
3048 tvb_get_manuf_name_if_known(tvbuff_t *tvb, gint offset)
3050 return get_manuf_name_if_known(tvb_get_ptr(tvb, offset, 3));
3053 char* get_hash_manuf_resolved_name(hashmanuf_t* manuf)
3055 return manuf->resolved_name;
3059 eui64_to_display(wmem_allocator_t *allocator, const guint64 addr_eui64)
3061 guint8 *addr = (guint8 *)wmem_alloc(NULL, 8);
3062 hashmanuf_t *manuf_value;
3065 /* Copy and convert the address to network byte order. */
3066 *(guint64 *)(void *)(addr) = pntoh64(&(addr_eui64));
3068 manuf_value = manuf_name_lookup(addr);
3069 if (!gbl_resolv_flags.mac_name || (manuf_value->status == HASHETHER_STATUS_UNRESOLVED)) {
3070 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]);
3072 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]);
3075 wmem_free(NULL, addr);
3077 } /* eui64_to_display */
3080 #define GHI_TIMEOUT (250 * 1000)
3085 #if ( ( ARES_VERSION_MAJOR < 1 ) \
3086 || ( 1 == ARES_VERSION_MAJOR && ARES_VERSION_MINOR < 5 ) )
3095 * XXX - If we wanted to be really fancy we could cache results here and
3096 * look them up in get_host_ipaddr* below.
3098 async_hostent_t *ahp = (async_hostent_t *)arg;
3099 if (status == ARES_SUCCESS && hp && ahp && hp->h_length == ahp->addr_size) {
3100 memcpy(ahp->addrp, hp->h_addr, hp->h_length);
3101 ahp->copied = hp->h_length;
3104 #endif /* HAVE_C_ARES */
3106 /* Translate a string, assumed either to be a dotted-quad IP address or
3107 * a host name, to a numeric IP address. Return TRUE if we succeed and
3108 * set "*addrp" to that numeric IP address; return FALSE if we fail.
3109 * Used more in the dfilter parser rather than in packet dissectors */
3111 get_host_ipaddr(const char *host, guint32 *addrp)
3113 struct in_addr ipaddr;
3115 struct timeval tv = { 0, GHI_TIMEOUT }, *tvp;
3118 async_hostent_t ahe;
3122 * don't change it to inet_pton(AF_INET), they are not 100% compatible.
3123 * inet_pton(AF_INET) does not support hexadecimal notation nor
3124 * less-than-4 octet notation.
3126 if (!inet_aton(host, &ipaddr)) {
3128 /* It's not a valid dotted-quad IP address; is it a valid
3132 /* If we're not allowed to do name resolution, don't do name
3135 if (!gbl_resolv_flags.network_name ||
3136 !gbl_resolv_flags.use_external_net_name_resolver) {
3141 if (!async_dns_initialized || name_resolve_concurrency < 1) {
3144 ahe.addr_size = (int) sizeof (struct in_addr);
3147 ares_gethostbyname(ghbn_chan, host, AF_INET, c_ares_ghi_cb, &ahe);
3150 nfds = ares_fds(ghbn_chan, &rfds, &wfds);
3152 tvp = ares_timeout(ghbn_chan, &tv, &tv);
3153 if (select(nfds, &rfds, &wfds, NULL, tvp) == -1) { /* call to select() failed */
3154 fprintf(stderr, "Warning: call to select() failed, error is %s\n", g_strerror(errno));
3157 ares_process(ghbn_chan, &rfds, &wfds);
3159 ares_cancel(ghbn_chan);
3160 if (ahe.addr_size == ahe.copied) {
3166 /* Does the string really contain dotted-quad IP?
3167 * Check against inet_atons that accept strings such as
3168 * "130.230" as valid addresses and try to convert them
3169 * to some form of a classful (host.net) notation.
3171 unsigned int a0, a1, a2, a3;
3172 if (sscanf(host, "%u.%u.%u.%u", &a0, &a1, &a2, &a3) != 4)
3176 *addrp = ipaddr.s_addr;
3181 * Translate IPv6 numeric address or FQDN hostname, into binary IPv6 address.
3182 * Return TRUE if we succeed and set "*addrp" to that numeric IP address;
3183 * return FALSE if we fail.
3186 get_host_ipaddr6(const char *host, struct e_in6_addr *addrp)
3189 struct timeval tv = { 0, GHI_TIMEOUT }, *tvp;
3192 async_hostent_t ahe;
3193 #endif /* HAVE_C_ARES */
3195 if (str_to_ip6(host, addrp))
3198 /* It's not a valid dotted-quad IP address; is it a valid
3202 /* If we're not allowed to do name resolution, don't do name
3205 if (!gbl_resolv_flags.network_name ||
3206 !gbl_resolv_flags.use_external_net_name_resolver) {
3212 if (!async_dns_initialized || name_resolve_concurrency < 1) {
3215 ahe.addr_size = (int) sizeof (struct e_in6_addr);
3218 ares_gethostbyname(ghbn_chan, host, AF_INET6, c_ares_ghi_cb, &ahe);
3221 nfds = ares_fds(ghbn_chan, &rfds, &wfds);
3223 tvp = ares_timeout(ghbn_chan, &tv, &tv);
3224 if (select(nfds, &rfds, &wfds, NULL, tvp) == -1) { /* call to select() failed */
3225 fprintf(stderr, "Warning: call to select() failed, error is %s\n", g_strerror(errno));
3228 ares_process(ghbn_chan, &rfds, &wfds);
3230 ares_cancel(ghbn_chan);
3231 if (ahe.addr_size == ahe.copied) {
3240 * Find out whether a hostname resolves to an ip or ipv6 address
3241 * Return "ip6" if it is IPv6, "ip" otherwise (including the case
3242 * that we don't know)
3245 #ifdef HAVE_GETADDRINFO
3246 host_ip_af(const char *host)
3248 host_ip_af(const char *host _U_)
3251 const char *af = "ip";
3253 #ifdef HAVE_GETADDRINFO
3254 struct addrinfo hint, *result = NULL;
3255 memset(&hint, 0, sizeof(hint));
3256 hint.ai_family = AF_UNSPEC;
3257 if (getaddrinfo(host, NULL, &hint, &result) == 0) {
3258 if (result->ai_family == AF_INET6) {
3261 freeaddrinfo(result);
3268 get_manuf_hashtable(void)
3270 return manuf_hashtable;
3274 get_wka_hashtable(void)
3276 return wka_hashtable;
3280 get_eth_hashtable(void)
3282 return eth_hashtable;
3286 get_serv_port_hashtable(void)
3288 return serv_port_hashtable;
3292 get_ipxnet_hash_table(void)
3294 return ipxnet_hash_table;
3298 get_vlan_hash_table(void)
3300 return vlan_hash_table;
3304 get_ipv4_hash_table(void)
3306 return ipv4_hash_table;
3310 get_ipv6_hash_table(void)
3312 return ipv6_hash_table;
3314 /* Initialize all the address resolution subsystems in this file */
3316 addr_resolv_init(void)
3318 initialize_services();
3319 initialize_ethers();
3320 initialize_ipxnets();
3322 /* host name initialization is done on a per-capture-file basis */
3323 /*host_name_lookup_init();*/
3326 /* Clean up all the address resolution subsystems in this file */
3328 addr_resolv_cleanup(void)
3330 service_name_lookup_cleanup();
3331 eth_name_lookup_cleanup();
3332 ipx_name_lookup_cleanup();
3333 vlan_name_lookup_cleanup();
3334 /* host name initialization is done on a per-capture-file basis */
3335 /*host_name_lookup_cleanup();*/
3339 str_to_ip(const char *str, void *dst)
3341 return ws_inet_pton4(str, (guint32 *)dst);
3345 str_to_ip6(const char *str, void *dst)
3347 return ws_inet_pton6(str, (struct e_in6_addr *)dst);
3351 * Editor modelines - http://www.wireshark.org/tools/modelines.html
3356 * indent-tabs-mode: nil
3359 * vi: set shiftwidth=4 tabstop=8 expandtab:
3360 * :indentSize=4:tabSize=8:noTabs=true: