Check profile directory before personal directory for services and subnets file
[metze/wireshark/wip.git] / epan / addr_resolv.c
1 /* addr_resolv.c
2  * Routines for network object lookup
3  *
4  * Laurent Deniel <laurent.deniel@free.fr>
5  *
6  * Add option to resolv VLAN ID to describing name
7  * Uli Heilmeier, March 2016
8  *
9  * Wireshark - Network traffic analyzer
10  * By Gerald Combs <gerald@wireshark.org>
11  * Copyright 1998 Gerald Combs
12  *
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.
17  *
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.
22  *
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.
26  */
27
28 #include "config.h"
29
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <string.h>
33 #include <errno.h>
34
35 #include <wsutil/strtoi.h>
36
37 /*
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).
41  *
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.
46  *
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.
51  *
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.)
59  *
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.
65  */
66
67 #ifdef HAVE_NETINET_IN_H
68 # include <netinet/in.h>
69 #endif
70
71 #ifdef HAVE_NETDB_H
72 #include <netdb.h>
73 #endif
74
75 #ifdef HAVE_SYS_SOCKET_H
76 #include <sys/socket.h>     /* needed to define AF_ values on UNIX */
77 #endif
78
79 #ifdef HAVE_WINSOCK2_H
80 #include <winsock2.h>       /* needed to define AF_ values on Windows */
81 #endif
82
83 #ifdef _WIN32
84 # include <ws2tcpip.h>
85 #endif
86
87 #ifdef HAVE_C_ARES
88 # ifdef _WIN32
89 #  define socklen_t unsigned int
90 # endif
91 # include <ares.h>
92 # include <ares_version.h>
93 #endif  /* HAVE_C_ARES */
94
95 #include <glib.h>
96
97 #include "packet.h"
98 #include "addr_and_mask.h"
99 #include "ipv6.h"
100 #include "addr_resolv.h"
101 #include "wsutil/filesystem.h"
102
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>
108
109 #include <epan/strutil.h>
110 #include <epan/to_str-int.h>
111 #include <epan/prefs.h>
112
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"
121
122 #define HASHETHSIZE      2048
123 #define HASHHOSTSIZE     2048
124 #define HASHIPXNETSIZE    256
125 #define SUBNETLENGTHSIZE   32  /*1-32 inc.*/
126
127 /* hash table used for IPv4 lookup */
128
129 #define HASH_IPV4_ADDRESS(addr) (g_htonl(addr) & (HASHHOSTSIZE - 1))
130
131
132 typedef struct sub_net_hashipv4 {
133     guint             addr;
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;
138
139 /* Array of entries of subnets of different lengths */
140 typedef struct {
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;
145
146
147 /* hash table used for IPX network lookup */
148
149 /* XXX - check goodness of hash function */
150
151 #define HASH_IPX_NET(net)   ((net) & (HASHIPXNETSIZE - 1))
152
153 typedef struct hashipxnet {
154     guint               addr;
155     struct hashipxnet  *next;
156     gchar               name[MAXNAMELEN];
157 } hashipxnet_t;
158
159 typedef struct hashvlan {
160     guint               id;
161 /*    struct hashvlan     *next; */
162     gchar               name[MAXVLANNAMELEN];
163 } hashvlan_t;
164
165 typedef struct ss7pc {
166     guint32             id; /* 1st byte NI, 3 following bytes: Point Code */
167     gchar               pc_addr[MAXNAMELEN];
168     gchar               name[MAXNAMELEN];
169 } hashss7pc_t;
170
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
175
176 struct hashether {
177     guint             status;  /* (See above) */
178     guint8            addr[6];
179     char              hexaddr[6*3];
180     char              resolved_name[MAXNAMELEN];
181 };
182
183 struct hashmanuf {
184     guint             status;  /* (See above) */
185     guint8            addr[3];
186     char              hexaddr[3*3];
187     char              resolved_name[MAXNAMELEN];
188 };
189
190 /* internal ethernet type */
191 typedef struct _ether
192 {
193     guint8            addr[6];
194     char              name[MAXNAMELEN];
195 } ether_t;
196
197 /* internal ipxnet type */
198 typedef struct _ipxnet
199 {
200     guint             addr;
201     char              name[MAXNAMELEN];
202 } ipxnet_t;
203
204 /* internal vlan type */
205 typedef struct _vlan
206 {
207     guint             id;
208     char              name[MAXVLANNAMELEN];
209 } vlan_t;
210
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;
216
217 static wmem_list_t *manually_resolved_ipv4_list = NULL;
218 static wmem_list_t *manually_resolved_ipv6_list = NULL;
219
220 typedef struct _resolved_ipv4
221 {
222     guint32          host_addr;
223     char             name[MAXNAMELEN];
224 } resolved_ipv4_t;
225
226 typedef struct _resolved_ipv6
227 {
228     struct e_in6_addr  ip6_addr;
229     char               name[MAXNAMELEN];
230 } resolved_ipv6_t;
231
232 static addrinfo_lists_t addrinfo_lists = { NULL, NULL};
233
234 static gchar        *cb_service;
235 static port_type    cb_proto = PT_NONE;
236
237
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;
242
243 static subnet_length_entry_t subnet_length_entries[SUBNETLENGTHSIZE]; /* Ordered array of entries */
244 static gboolean have_subnet_entry = FALSE;
245
246 static gboolean new_resolved_objects = FALSE;
247
248 static GPtrArray* extra_hosts_files = NULL;
249
250 static hashether_t *add_eth_name(const guint8 *addr, const gchar *name);
251 static void add_serv_port_cb(const guint32 port);
252
253
254 /* http://eternallyconfuzzled.com/tuts/algorithms/jsw_tut_hashing.aspx#existing
255  * One-at-a-Time hash
256  */
257 static guint32
258 ipv6_oat_hash(gconstpointer key)
259 {
260     int len = 16;
261     const unsigned char *p = (const unsigned char *)key;
262     guint32 h = 0;
263     int i;
264
265     for ( i = 0; i < len; i++ ) {
266         h += p[i];
267         h += ( h << 10 );
268         h ^= ( h >> 6 );
269     }
270
271     h += ( h << 3 );
272     h ^= ( h >> 11 );
273     h += ( h << 15 );
274
275     return h;
276 }
277
278 static gboolean
279 ipv6_equal(gconstpointer v1, gconstpointer v2)
280 {
281
282     if (memcmp(v1, v2, sizeof (struct e_in6_addr)) == 0) {
283         return TRUE;
284     }
285
286     return FALSE;
287 }
288
289 /*
290  * Flag controlling what names to resolve.
291  */
292 e_addr_resolve gbl_resolv_flags = {
293     TRUE,   /* mac_name */
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 */
301 };
302 #ifdef HAVE_C_ARES
303 static guint name_resolve_concurrency = 500;
304 #endif
305
306 /*
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.
310  */
311
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   */
321
322 /* c-ares */
323 #ifdef HAVE_C_ARES
324 /*
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.
330  */
331 typedef struct _async_dns_queue_msg
332 {
333     union {
334         guint32           ip4;
335         struct e_in6_addr ip6;
336     } addr;
337     int                 family;
338 } async_dns_queue_msg_t;
339
340 typedef struct _async_hostent {
341     int addr_size;
342     int   copied;
343     void *addrp;
344 } async_hostent_t;
345
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);
349 #else
350 static void c_ares_ghba_cb(void *arg, int status, int timeouts _U_, struct hostent *hostent);
351 #endif
352
353 ares_channel ghba_chan; /* ares_gethostbyaddr -- Usually non-interactive, no timeout */
354 ares_channel ghbn_chan; /* ares_gethostbyname -- Usually interactive, timeout */
355
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;
359
360 /* push a dns request */
361 static void
362 add_async_dns_ipv4(int type, guint32 addr)
363 {
364     async_dns_queue_msg_t *msg;
365
366     msg = wmem_new(wmem_epan_scope(), async_dns_queue_msg_t);
367     msg->family = type;
368     msg->addr.ip4 = addr;
369     wmem_list_append(async_dns_queue_head, (gpointer) msg);
370 }
371 #endif /* HAVE_C_ARES */
372
373 typedef struct {
374     guint32      mask;
375     gsize        mask_length;
376     const gchar* name; /* Shallow copy */
377 } subnet_entry_t;
378
379 /*
380  *  Miscellaneous functions
381  */
382
383 static int
384 fgetline(char **buf, int *size, FILE *fp)
385 {
386     int len;
387     int c;
388
389     if (fp == NULL || buf == NULL)
390         return -1;
391
392     if (*buf == NULL) {
393         if (*size == 0)
394             *size = BUFSIZ;
395
396         *buf = (char *)wmem_alloc(wmem_epan_scope(), *size);
397     }
398
399     g_assert(*buf);
400     g_assert(*size > 0);
401
402     if (feof(fp))
403         return -1;
404
405     len = 0;
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);
409         }
410         (*buf)[len++] = c;
411     }
412
413     if (len == 0 && c == EOF)
414         return -1;
415
416     (*buf)[len] = '\0';
417
418     return len;
419
420 } /* fgetline */
421
422
423 /*
424  *  Local function definitions
425  */
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);
428
429
430 static void
431 add_service_name(port_type proto, const guint port, const char *service_name)
432 {
433     serv_port_t *serv_port_table;
434     int *key;
435
436     key = (int *)wmem_new(wmem_epan_scope(), int);
437     *key = port;
438
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);
443     }
444     else {
445         wmem_free(wmem_epan_scope(), key);
446     }
447
448     switch(proto) {
449         case PT_TCP:
450             wmem_free(wmem_epan_scope(), serv_port_table->tcp_name);
451             serv_port_table->tcp_name = wmem_strdup(wmem_epan_scope(), service_name);
452             break;
453         case PT_UDP:
454             wmem_free(wmem_epan_scope(), serv_port_table->udp_name);
455             serv_port_table->udp_name = wmem_strdup(wmem_epan_scope(), service_name);
456             break;
457         case PT_SCTP:
458             wmem_free(wmem_epan_scope(), serv_port_table->sctp_name);
459             serv_port_table->sctp_name = wmem_strdup(wmem_epan_scope(), service_name);
460             break;
461         case PT_DCCP:
462             wmem_free(wmem_epan_scope(), serv_port_table->dccp_name);
463             serv_port_table->dccp_name = wmem_strdup(wmem_epan_scope(), service_name);
464             break;
465         default:
466             return;
467             /* Should not happen */
468     }
469
470     new_resolved_objects = TRUE;
471 }
472
473
474 static void
475 parse_service_line (char *line)
476 {
477     /*
478      *  See the services(4) or services(5) man page for services file format
479      *  (not available on all systems).
480      */
481
482     gchar *cp;
483     gchar *service;
484     gchar *port;
485     port_type proto;
486
487     range_t *port_rng = NULL;
488     guint32 max_port = MAX_UDP_PORT;
489
490     if ((cp = strchr(line, '#')))
491         *cp = '\0';
492
493     if ((cp = strtok(line, " \t")) == NULL)
494         return;
495
496     service = cp;
497
498     if ((cp = strtok(NULL, " \t")) == NULL)
499         return;
500
501     port = cp;
502
503     if (strtok(cp, "/") == NULL)
504         return;
505
506     if ((cp = strtok(NULL, "/")) == NULL)
507         return;
508
509     /* seems we got all interesting things from the file */
510     if (strcmp(cp, "tcp") == 0) {
511         max_port = MAX_TCP_PORT;
512         proto = PT_TCP;
513     }
514     else if (strcmp(cp, "udp") == 0) {
515         max_port = MAX_UDP_PORT;
516         proto = PT_UDP;
517     }
518     else if (strcmp(cp, "sctp") == 0) {
519         max_port = MAX_SCTP_PORT;
520         proto = PT_SCTP;
521     }
522     else if (strcmp(cp, "dccp") == 0) {
523         max_port = MAX_DCCP_PORT;
524         proto = PT_DCCP;
525     } else {
526         return;
527     }
528
529     if (CVT_NO_ERROR != range_convert_str(NULL, &port_rng, port, max_port)) {
530         /* some assertion here? */
531         wmem_free (NULL, port_rng);
532         return;
533     }
534
535     cb_service = service;
536     cb_proto = proto;
537     range_foreach(port_rng, add_serv_port_cb);
538     wmem_free (NULL, port_rng);
539     cb_proto = PT_NONE;
540 } /* parse_service_line */
541
542
543 static void
544 add_serv_port_cb(const guint32 port)
545 {
546     if ( port ) {
547         add_service_name(cb_proto, port, cb_service);
548     }
549 }
550
551
552 static gboolean
553 parse_services_file(const char * path)
554 {
555     FILE *serv_p;
556     static int     size = 0;
557     static char   *buf = NULL;
558
559     /* services hash table initialization */
560     serv_p = ws_fopen(path, "r");
561
562     if (serv_p == NULL)
563         return FALSE;
564
565     while (fgetline(&buf, &size, serv_p) >= 0) {
566         parse_service_line(buf);
567     }
568
569     fclose(serv_p);
570     return TRUE;
571 }
572
573 /* -----------------
574  * unsigned integer to ascii
575  */
576 static gchar *
577 wmem_utoa(wmem_allocator_t *allocator, guint port)
578 {
579     gchar *bp = (gchar *)wmem_alloc(allocator, MAXNAMELEN);
580
581     /* XXX, guint32_to_str() ? */
582     guint32_to_str_buf(port, bp, MAXNAMELEN);
583     return bp;
584 }
585
586 static const gchar *
587 _serv_name_lookup(port_type proto, guint port, serv_port_t **value_ret)
588 {
589     serv_port_t *serv_port_table;
590
591     serv_port_table = (serv_port_t *)wmem_map_lookup(serv_port_hashtable, &port);
592
593     if (value_ret != NULL)
594         *value_ret = serv_port_table;
595
596     if (serv_port_table == NULL)
597         return NULL;
598
599     switch (proto) {
600         case PT_UDP:
601             return serv_port_table->udp_name;
602         case PT_TCP:
603             return serv_port_table->tcp_name;
604         case PT_SCTP:
605             return serv_port_table->sctp_name;
606         case PT_DCCP:
607             return serv_port_table->dccp_name;
608         default:
609             break;
610     }
611     return NULL;
612 }
613
614 const gchar *
615 try_serv_name_lookup(port_type proto, guint port)
616 {
617     return _serv_name_lookup(proto, port, NULL);
618 }
619
620 const gchar *
621 serv_name_lookup(port_type proto, guint port)
622 {
623     serv_port_t *serv_port_table = NULL;
624     const char *name;
625     guint *key;
626
627     name = _serv_name_lookup(proto, port, &serv_port_table);
628     if (name != NULL)
629         return name;
630
631     if (serv_port_table == NULL) {
632         key = (guint *)wmem_new(wmem_epan_scope(), guint);
633         *key = port;
634         serv_port_table = wmem_new0(wmem_epan_scope(), serv_port_t);
635         wmem_map_insert(serv_port_hashtable, key, serv_port_table);
636     }
637     if (serv_port_table->numeric == NULL) {
638         serv_port_table->numeric = wmem_strdup_printf(wmem_epan_scope(), "%u", port);
639     }
640
641     return serv_port_table->numeric;
642 }
643
644 static void
645 initialize_services(void)
646 {
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);
650
651     /* Compute the pathname of the services file. */
652     if (g_services_path == NULL) {
653         g_services_path = get_datafile_path(ENAME_SERVICES);
654     }
655     parse_services_file(g_services_path);
656
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);
663         } else {
664             parse_file = FALSE;
665         }
666     }
667     if (parse_file) {
668         parse_services_file(g_pservices_path);
669     }
670 }
671
672 static void
673 service_name_lookup_cleanup(void)
674 {
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;
680 }
681
682 /* Fill in an IP4 structure with info from subnets file or just with the
683  * string form of the address.
684  */
685 static void
686 fill_dummy_ip4(const guint addr, hashipv4_t* volatile tp)
687 {
688     subnet_entry_t subnet_entry;
689
690     if (tp->flags & DUMMY_ADDRESS_ENTRY)
691         return; /* already done */
692
693     tp->flags |= DUMMY_ADDRESS_ENTRY; /* Overwrite if we get async DNS reply */
694
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 */
699         guint32 host_addr;
700         gchar buffer[MAX_IP_STR_LEN];
701         gchar* paddr;
702         gsize i;
703
704         host_addr = addr & (~(guint32)subnet_entry.mask);
705         ip_to_str_buf((guint8 *)&host_addr, buffer, MAX_IP_STR_LEN);
706         paddr = buffer;
707
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?),
711          * we skip that '.'.
712          */
713         i = subnet_entry.mask_length / 8;
714         while(*(paddr) != '\0' && i > 0) {
715             if (*(++paddr) == '.') {
716                 --i;
717             }
718         }
719
720         /* There are more efficient ways to do this, but this is safe if we
721          * trust g_snprintf and MAXNAMELEN
722          */
723         g_snprintf(tp->name, MAXNAMELEN, "%s%s", subnet_entry.name, paddr);
724     } else {
725         ip_to_str_buf((const guint8 *)&addr, tp->name, MAXNAMELEN);
726     }
727 }
728
729
730 /* Fill in an IP6 structure with the string form of the address.
731  */
732 static void
733 fill_dummy_ip6(hashipv6_t* volatile tp)
734 {
735     if (tp->flags & DUMMY_ADDRESS_ENTRY)
736         return; /* already done */
737
738     tp->flags |= DUMMY_ADDRESS_ENTRY; /* Overwrite if we get async DNS reply */
739     g_strlcpy(tp->name, tp->ip6, MAXNAMELEN);
740 }
741
742 #ifdef HAVE_C_ARES
743
744 static void
745 c_ares_ghba_cb(
746         void *arg,
747         int status,
748 #if ( ( ARES_VERSION_MAJOR < 1 )                                     \
749         || ( 1 == ARES_VERSION_MAJOR && ARES_VERSION_MINOR < 5 ) )
750         struct hostent *he
751 #else
752         int timeouts _U_,
753         struct hostent *he
754 #endif
755         ) {
756
757     async_dns_queue_msg_t *caqm = (async_dns_queue_msg_t *)arg;
758     char **p;
759
760     if (!caqm) return;
761     /* XXX, what to do if async_dns_in_flight == 0? */
762     async_dns_in_flight--;
763
764     if (status == ARES_SUCCESS) {
765         for (p = he->h_addr_list; *p != NULL; p++) {
766             switch(caqm->family) {
767                 case AF_INET:
768                     add_ipv4_name(caqm->addr.ip4, he->h_name);
769                     break;
770                 case AF_INET6:
771                     add_ipv6_name(&caqm->addr.ip6, he->h_name);
772                     break;
773                 default:
774                     /* Throw an exception? */
775                     break;
776             }
777         }
778     }
779     wmem_free(wmem_epan_scope(), caqm);
780 }
781 #endif /* HAVE_C_ARES */
782
783 /* --------------- */
784 static hashipv4_t *
785 new_ipv4(const guint addr)
786 {
787     hashipv4_t *tp = wmem_new(wmem_epan_scope(), hashipv4_t);
788     tp->addr = addr;
789     tp->flags = 0;
790     tp->name[0] = '\0';
791     ip_to_str_buf((const guint8 *)&addr, tp->ip, sizeof(tp->ip));
792     return tp;
793 }
794
795 static hashipv4_t *
796 host_lookup(const guint addr)
797 {
798     hashipv4_t * volatile tp;
799
800     tp = (hashipv4_t *)wmem_map_lookup(ipv4_hash_table, GUINT_TO_POINTER(addr));
801     if (tp == NULL) {
802         /*
803          * We don't already have an entry for this host name; create one,
804          * and then try to resolve it.
805          */
806         tp = new_ipv4(addr);
807         wmem_map_insert(ipv4_hash_table, GUINT_TO_POINTER(addr), tp);
808     } else if ((tp->flags & DUMMY_AND_RESOLVE_FLGS) != DUMMY_ADDRESS_ENTRY) {
809         return tp;
810     }
811
812     /*
813      * This hasn't been resolved yet, and we haven't tried to
814      * resolve it already.
815      */
816
817     fill_dummy_ip4(addr, tp);
818     if (!gbl_resolv_flags.network_name)
819         return tp;
820
821     if (gbl_resolv_flags.use_external_net_name_resolver) {
822         tp->flags |= TRIED_RESOLVE_ADDRESS;
823
824 #ifdef HAVE_C_ARES
825         if (async_dns_initialized && name_resolve_concurrency > 0) {
826             add_async_dns_ipv4(AF_INET, addr);
827         }
828 #endif
829     }
830
831     return tp;
832
833 } /* host_lookup */
834
835 /* --------------- */
836 static hashipv6_t *
837 new_ipv6(const struct e_in6_addr *addr)
838 {
839     hashipv6_t *tp = wmem_new(wmem_epan_scope(), hashipv6_t);
840     memcpy(tp->addr, addr->bytes, sizeof tp->addr);
841     tp->flags = 0;
842     tp->name[0] = '\0';
843     ip6_to_str_buf(addr, tp->ip6, sizeof(tp->ip6));
844     return tp;
845 }
846
847 /* ------------------------------------ */
848 static hashipv6_t *
849 host_lookup6(const struct e_in6_addr *addr)
850 {
851     hashipv6_t * volatile tp;
852 #ifdef HAVE_C_ARES
853     async_dns_queue_msg_t *caqm;
854 #endif
855
856     tp = (hashipv6_t *)wmem_map_lookup(ipv6_hash_table, addr);
857     if (tp == NULL) {
858         /*
859          * We don't already have an entry for this host name; create one,
860          * and then try to resolve it.
861          */
862         struct e_in6_addr *addr_key;
863
864         addr_key = wmem_new(wmem_epan_scope(), struct e_in6_addr);
865         tp = new_ipv6(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) {
869         return tp;
870     }
871
872     /*
873      * This hasn't been resolved yet, and we haven't tried to
874      * resolve it already.
875      */
876
877     fill_dummy_ip6(tp);
878     if (!gbl_resolv_flags.network_name)
879         return tp;
880
881     if (gbl_resolv_flags.use_external_net_name_resolver) {
882         tp->flags |= TRIED_RESOLVE_ADDRESS;
883 #ifdef HAVE_C_ARES
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);
889         }
890 #endif
891     }
892
893     return tp;
894
895 } /* host_lookup6 */
896
897 /*
898  * Ethernet / manufacturer resolution
899  *
900  * The following functions implement ethernet address resolution and
901  * ethers files parsing (see ethers(4)).
902  *
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).
906  *
907  * Notes:
908  *
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.
915  *
916  * So the following functions do _not_ behave as the standard ones.
917  *
918  * -- Laurent.
919  */
920
921
922 /*
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
925  * mask.
926  */
927 static gboolean
928 parse_ether_address(const char *cp, ether_t *eth, unsigned int *mask,
929         const gboolean manuf_file)
930 {
931     int i;
932     unsigned long num;
933     char *p;
934     char sep = '\0';
935
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))
939             return FALSE;
940         num = strtoul(cp, &p, 16);
941         if (p == cp)
942             return FALSE; /* failed */
943         if (num > 0xFF)
944             return FALSE; /* not a valid octet */
945         eth->addr[i] = (guint8) num;
946         cp = p;     /* skip past the number */
947
948         /* OK, what character terminated the octet? */
949         if (*cp == '/') {
950             /* "/" - this has a mask. */
951             if (!manuf_file) {
952                 /* Entries with masks are allowed only in the "manuf" files. */
953                 return FALSE;
954             }
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);
959             if (p == cp)
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 */
967             *mask = (int)num;
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));
972             i++;
973             /* Mask out completely-masked-out octets */
974             for (; i < 6; i++)
975                 eth->addr[i] = 0;
976             return TRUE;
977         }
978         if (*cp == '\0') {
979             /* We're at the end of the address, and there's no mask. */
980             if (i == 2) {
981                 /* We got 3 bytes, so this is a manufacturer ID. */
982                 if (!manuf_file) {
983                     /* Manufacturer IDs are only allowed in the "manuf"
984                        files. */
985                     return FALSE;
986                 }
987                 /* Indicate that this is a manufacturer ID (0 is not allowed
988                    as a mask). */
989                 *mask = 0;
990                 return TRUE;
991             }
992
993             if (i == 5) {
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). */
997                 if (manuf_file)
998                     *mask = 48;
999                 return TRUE;
1000             }
1001
1002             /* We didn't get 3 or 6 bytes, and there's no mask; this is
1003                illegal. */
1004             return FALSE;
1005         } else {
1006             if (sep == '\0') {
1007                 /* We don't know the separator used in this number; it can either
1008                    be ':', '-', or '.'. */
1009                 if (*cp != ':' && *cp != '-' && *cp != '.')
1010                     return FALSE;
1011                 sep = *cp;  /* subsequent separators must be the same */
1012             } else {
1013                 /* It has to be the same as the first separator */
1014                 if (*cp != sep)
1015                     return FALSE;
1016             }
1017         }
1018         cp++;
1019     }
1020
1021     return TRUE;
1022 }
1023
1024 static int
1025 parse_ether_line(char *line, ether_t *eth, unsigned int *mask,
1026         const gboolean manuf_file)
1027 {
1028     /*
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.
1033      */
1034
1035     gchar *cp;
1036
1037     if ((cp = strchr(line, '#')))
1038         *cp = '\0';
1039
1040     if ((cp = strtok(line, " \t")) == NULL)
1041         return -1;
1042
1043     if (!parse_ether_address(cp, eth, mask, manuf_file))
1044         return -1;
1045
1046     if ((cp = strtok(NULL, " \t")) == NULL)
1047         return -1;
1048
1049     g_strlcpy(eth->name, cp, MAXNAMELEN);
1050
1051     return 0;
1052
1053 } /* parse_ether_line */
1054
1055 static FILE *eth_p = NULL;
1056
1057 static void
1058 set_ethent(char *path)
1059 {
1060     if (eth_p)
1061         rewind(eth_p);
1062     else
1063         eth_p = ws_fopen(path, "r");
1064 }
1065
1066 static void
1067 end_ethent(void)
1068 {
1069     if (eth_p) {
1070         fclose(eth_p);
1071         eth_p = NULL;
1072     }
1073 }
1074
1075 static ether_t *
1076 get_ethent(unsigned int *mask, const gboolean manuf_file)
1077 {
1078
1079     static ether_t eth;
1080     static int     size = 0;
1081     static char   *buf = NULL;
1082
1083     if (eth_p == NULL)
1084         return NULL;
1085
1086     while (fgetline(&buf, &size, eth_p) >= 0) {
1087         if (parse_ether_line(buf, &eth, mask, manuf_file) == 0) {
1088             return &eth;
1089         }
1090     }
1091
1092     return NULL;
1093
1094 } /* get_ethent */
1095
1096 #if 0
1097 static ether_t *
1098 get_ethbyname(const gchar *name)
1099 {
1100     ether_t *eth;
1101
1102     set_ethent(g_pethers_path);
1103
1104     while (((eth = get_ethent(NULL, FALSE)) != NULL) && strncmp(name, eth->name, MAXNAMELEN) != 0)
1105         ;
1106
1107     if (eth == NULL) {
1108         end_ethent();
1109
1110         set_ethent(g_ethers_path);
1111
1112         while (((eth = get_ethent(NULL, FALSE)) != NULL) && strncmp(name, eth->name, MAXNAMELEN) != 0)
1113             ;
1114
1115         end_ethent();
1116     }
1117
1118     return eth;
1119
1120 } /* get_ethbyname */
1121 #endif
1122
1123 static ether_t *
1124 get_ethbyaddr(const guint8 *addr)
1125 {
1126
1127     ether_t *eth;
1128
1129     set_ethent(g_pethers_path);
1130
1131     while (((eth = get_ethent(NULL, FALSE)) != NULL) && memcmp(addr, eth->addr, 6) != 0)
1132         ;
1133
1134     if (eth == NULL) {
1135         end_ethent();
1136
1137         set_ethent(g_ethers_path);
1138
1139         while (((eth = get_ethent(NULL, FALSE)) != NULL) && memcmp(addr, eth->addr, 6) != 0)
1140             ;
1141
1142         end_ethent();
1143     }
1144
1145     return eth;
1146
1147 } /* get_ethbyaddr */
1148
1149 static hashmanuf_t *
1150 manuf_hash_new_entry(const guint8 *addr, char* name)
1151 {
1152     int    *manuf_key;
1153     hashmanuf_t *manuf_value;
1154     char *endp;
1155
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);
1160
1161     memcpy(manuf_value->addr, addr, 3);
1162     if (name != NULL) {
1163         g_strlcpy(manuf_value->resolved_name, name, MAXNAMELEN);
1164         manuf_value->status = HASHETHER_STATUS_RESOLVED_NAME;
1165     }
1166     else {
1167         manuf_value->status = HASHETHER_STATUS_UNRESOLVED;
1168         manuf_value->resolved_name[0] = '\0';
1169     }
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), ':');
1172     *endp = '\0';
1173
1174     wmem_map_insert(manuf_hashtable, manuf_key, manuf_value);
1175     return manuf_value;
1176 }
1177
1178 static void
1179 wka_hash_new_entry(const guint8 *addr, char* name)
1180 {
1181     guint8 *wka_key;
1182
1183     wka_key = (guint8 *)wmem_alloc(wmem_epan_scope(), 6);
1184     memcpy(wka_key, addr, 6);
1185
1186     wmem_map_insert(wka_hashtable, wka_key, wmem_strdup(wmem_epan_scope(), name));
1187 }
1188
1189 static void
1190 add_manuf_name(const guint8 *addr, unsigned int mask, gchar *name)
1191 {
1192     switch (mask)
1193     {
1194     case 0:
1195         /* This is a manufacturer ID; add it to the manufacturer ID hash table */
1196         manuf_hash_new_entry(addr, name);
1197         break;
1198
1199     case 48:
1200         /* This is a well-known MAC address; add it to the Ethernet hash table */
1201         add_eth_name(addr, name);
1202         break;
1203
1204     default:
1205         /* This is a range of well-known addresses; add it to the well-known-address table */
1206         wka_hash_new_entry(addr, name);
1207         break;
1208     }
1209 } /* add_manuf_name */
1210
1211 static hashmanuf_t *
1212 manuf_name_lookup(const guint8 *addr)
1213 {
1214     gint32       manuf_key = 0;
1215     guint8       oct;
1216     hashmanuf_t  *manuf_value;
1217
1218     /* manuf needs only the 3 most significant octets of the ethernet address */
1219     manuf_key = addr[0];
1220     manuf_key = manuf_key<<8;
1221     oct = addr[1];
1222     manuf_key = manuf_key | oct;
1223     manuf_key = manuf_key<<8;
1224     oct = addr[2];
1225     manuf_key = manuf_key | oct;
1226
1227
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) {
1231         return manuf_value;
1232     }
1233
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) {
1243             return manuf_value;
1244         }
1245     }
1246
1247     /* Add the address as a hex string */
1248     return manuf_hash_new_entry(addr, NULL);
1249
1250 } /* manuf_name_lookup */
1251
1252 static gchar *
1253 wka_name_lookup(const guint8 *addr, const unsigned int mask)
1254 {
1255     guint8     masked_addr[6];
1256     guint      num;
1257     gint       i;
1258     gchar     *name;
1259
1260     if (wka_hashtable == NULL) {
1261         return NULL;
1262     }
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));
1268     i++;
1269     /* Zero out completely-masked-out octets */
1270     for (; i < 6; i++)
1271         masked_addr[i] = 0;
1272
1273     name = (gchar *)wmem_map_lookup(wka_hashtable, masked_addr);
1274
1275     return name;
1276
1277 } /* wka_name_lookup */
1278
1279
1280 guint get_hash_ether_status(hashether_t* ether)
1281 {
1282     return ether->status;
1283 }
1284
1285 char* get_hash_ether_hexaddr(hashether_t* ether)
1286 {
1287     return ether->hexaddr;
1288 }
1289
1290 char* get_hash_ether_resolved_name(hashether_t* ether)
1291 {
1292     return ether->resolved_name;
1293 }
1294
1295 static guint
1296 eth_addr_hash(gconstpointer key)
1297 {
1298     return wmem_strong_hash((const guint8 *)key, 6);
1299 }
1300
1301 static gboolean
1302 eth_addr_cmp(gconstpointer a, gconstpointer b)
1303 {
1304     return (memcmp(a, b, 6) == 0);
1305 }
1306
1307 static void
1308 initialize_ethers(void)
1309 {
1310     ether_t *eth;
1311     char    *manuf_path;
1312     guint    mask = 0;
1313
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);
1318
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);
1323     }
1324
1325     /* Set g_pethers_path here, but don't actually do anything
1326      * with it. It's used in get_ethbyname() and get_ethbyaddr()
1327      */
1328     if (g_pethers_path == NULL)
1329         g_pethers_path = get_persconffile_path(ENAME_ETHERS, FALSE);
1330
1331     /* Compute the pathname of the manuf file */
1332     manuf_path = get_datafile_path(ENAME_MANUF);
1333
1334     /* Read it and initialize the hash table */
1335     set_ethent(manuf_path);
1336
1337     while ((eth = get_ethent(&mask, TRUE))) {
1338         add_manuf_name(eth->addr, mask, eth->name);
1339     }
1340
1341     end_ethent();
1342
1343     g_free(manuf_path);
1344
1345 } /* initialize_ethers */
1346
1347 static void
1348 ethers_cleanup(void)
1349 {
1350     g_free(g_pethers_path);
1351     g_pethers_path = NULL;
1352 }
1353
1354 /* Resolve ethernet address */
1355 static hashether_t *
1356 eth_addr_resolve(hashether_t *tp) {
1357     ether_t      *eth;
1358     hashmanuf_t *manuf_value;
1359     const guint8 *addr = tp->addr;
1360
1361     if ( (eth = get_ethbyaddr(addr)) != NULL) {
1362         g_strlcpy(tp->resolved_name, eth->name, MAXNAMELEN);
1363         tp->status = HASHETHER_STATUS_RESOLVED_NAME;
1364         return tp;
1365     } else {
1366         guint         mask;
1367         gchar        *name;
1368         address       ether_addr;
1369
1370         /* Unknown name.  Try looking for it in the well-known-address
1371            tables for well-known address ranges smaller than 2^24. */
1372         mask = 7;
1373         do {
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;
1379                 return tp;
1380             }
1381         } while (mask--);
1382
1383         mask = 7;
1384         do {
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;
1390                 return tp;
1391             }
1392         } while (mask--);
1393
1394         mask = 7;
1395         do {
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;
1401                 return tp;
1402             }
1403         } while (mask--);
1404
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;
1411             return tp;
1412         }
1413
1414         /* Now try looking for it in the well-known-address
1415            tables for well-known address ranges larger than 2^24. */
1416         mask = 7;
1417         do {
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],
1422                         addr[5]);
1423                 tp->status = HASHETHER_STATUS_RESOLVED_DUMMY;
1424                 return tp;
1425             }
1426         } while (mask--);
1427
1428         mask = 7;
1429         do {
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],
1434                         addr[4], addr[5]);
1435                 tp->status = HASHETHER_STATUS_RESOLVED_DUMMY;
1436                 return tp;
1437             }
1438         } while (mask--);
1439
1440         mask = 7;
1441         do {
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;
1448                 return tp;
1449             }
1450         } while (--mask); /* Work down to the last bit */
1451
1452         /* No match whatsoever. */
1453         set_address(&ether_addr, AT_ETHER, 6, addr);
1454         address_to_str_buf(&ether_addr, tp->resolved_name, MAXNAMELEN);
1455         tp->status = HASHETHER_STATUS_RESOLVED_DUMMY;
1456         return tp;
1457     }
1458     g_assert_not_reached();
1459 } /* eth_addr_resolve */
1460
1461 static hashether_t *
1462 eth_hash_new_entry(const guint8 *addr, const gboolean resolve)
1463 {
1464     hashether_t *tp;
1465     char *endp;
1466
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), ':');
1472     *endp = '\0';
1473     tp->resolved_name[0] = '\0';
1474
1475     if (resolve)
1476         eth_addr_resolve(tp);
1477
1478     wmem_map_insert(eth_hashtable, tp->addr, tp);
1479
1480     return tp;
1481 } /* eth_hash_new_entry */
1482
1483 static hashether_t *
1484 add_eth_name(const guint8 *addr, const gchar *name)
1485 {
1486     hashether_t *tp;
1487
1488     tp = (hashether_t *)wmem_map_lookup(eth_hashtable, addr);
1489
1490     if (tp == NULL) {
1491         tp = eth_hash_new_entry(addr, FALSE);
1492     }
1493
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;
1498     }
1499
1500     return tp;
1501 } /* add_eth_name */
1502
1503 static hashether_t *
1504 eth_name_lookup(const guint8 *addr, const gboolean resolve)
1505 {
1506     hashether_t  *tp;
1507
1508     tp = (hashether_t *)wmem_map_lookup(eth_hashtable, addr);
1509
1510     if (tp == NULL) {
1511         tp = eth_hash_new_entry(addr, resolve);
1512     } else {
1513         if (resolve && (tp->status == HASHETHER_STATUS_UNRESOLVED)) {
1514             eth_addr_resolve(tp); /* Found but needs to be resolved */
1515         }
1516     }
1517
1518     return tp;
1519
1520 } /* eth_name_lookup */
1521
1522 static guint8 *
1523 eth_addr_lookup(const gchar *name _U_)
1524 {
1525 #if 0
1526     /* XXX Do we need reverse lookup??? */
1527     ether_t      *eth;
1528     hashether_t  *tp;
1529     hashether_t **table = eth_table;
1530     gint          i;
1531
1532     /* to be optimized (hash table from name to addr) */
1533     for (i = 0; i < HASHETHSIZE; i++) {
1534         tp = table[i];
1535         while (tp) {
1536             if (strcmp(tp->resolved_name, name) == 0)
1537                 return tp->addr;
1538             tp = tp->next;
1539         }
1540     }
1541
1542     /* not in hash table : performs a file lookup */
1543
1544     if ((eth = get_ethbyname(name)) == NULL)
1545         return NULL;
1546
1547     /* add new entry in hash table */
1548
1549     tp = add_eth_name(eth->addr, name);
1550
1551     return tp->addr;
1552 #endif
1553     return NULL;
1554
1555 } /* eth_addr_lookup */
1556
1557
1558 /* IPXNETS */
1559 static int
1560 parse_ipxnets_line(char *line, ipxnet_t *ipxnet)
1561 {
1562     /*
1563      *  We allow three address separators (':', '-', and '.'),
1564      *  as well as no separators
1565      */
1566
1567     gchar     *cp;
1568     guint32   a, a0, a1, a2, a3;
1569     gboolean  found_single_number = FALSE;
1570
1571     if ((cp = strchr(line, '#')))
1572         *cp = '\0';
1573
1574     if ((cp = strtok(line, " \t\n")) == NULL)
1575         return -1;
1576
1577     /* Either fill a0,a1,a2,a3 and found_single_number is FALSE,
1578      * fill a and found_single_number is TRUE,
1579      * or return -1
1580      */
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;
1586                 }
1587                 else {
1588                     return -1;
1589                 }
1590             }
1591         }
1592     }
1593
1594     if ((cp = strtok(NULL, " \t\n")) == NULL)
1595         return -1;
1596
1597     if (found_single_number) {
1598         ipxnet->addr = a;
1599     }
1600     else {
1601         ipxnet->addr = (a0 << 24) | (a1 << 16) | (a2 << 8) | a3;
1602     }
1603
1604     g_strlcpy(ipxnet->name, cp, MAXNAMELEN);
1605
1606     return 0;
1607
1608 } /* parse_ipxnets_line */
1609
1610 static FILE *ipxnet_p = NULL;
1611
1612 static void
1613 set_ipxnetent(char *path)
1614 {
1615     if (ipxnet_p)
1616         rewind(ipxnet_p);
1617     else
1618         ipxnet_p = ws_fopen(path, "r");
1619 }
1620
1621 static void
1622 end_ipxnetent(void)
1623 {
1624     if (ipxnet_p) {
1625         fclose(ipxnet_p);
1626         ipxnet_p = NULL;
1627     }
1628 }
1629
1630 static ipxnet_t *
1631 get_ipxnetent(void)
1632 {
1633
1634     static ipxnet_t ipxnet;
1635     static int     size = 0;
1636     static char   *buf = NULL;
1637
1638     if (ipxnet_p == NULL)
1639         return NULL;
1640
1641     while (fgetline(&buf, &size, ipxnet_p) >= 0) {
1642         if (parse_ipxnets_line(buf, &ipxnet) == 0) {
1643             return &ipxnet;
1644         }
1645     }
1646
1647     return NULL;
1648
1649 } /* get_ipxnetent */
1650
1651 /* Unused ??? */
1652 #if 0
1653 static ipxnet_t *
1654 get_ipxnetbyname(const gchar *name)
1655 {
1656     ipxnet_t *ipxnet;
1657
1658     set_ipxnetent(g_ipxnets_path);
1659
1660     while (((ipxnet = get_ipxnetent()) != NULL) && strncmp(name, ipxnet->name, MAXNAMELEN) != 0)
1661         ;
1662
1663     if (ipxnet == NULL) {
1664         end_ipxnetent();
1665
1666         set_ipxnetent(g_pipxnets_path);
1667
1668         while (((ipxnet = get_ipxnetent()) != NULL) && strncmp(name, ipxnet->name, MAXNAMELEN) != 0)
1669             ;
1670
1671         end_ipxnetent();
1672     }
1673
1674     return ipxnet;
1675
1676 } /* get_ipxnetbyname */
1677 #endif
1678
1679 static ipxnet_t *
1680 get_ipxnetbyaddr(guint32 addr)
1681 {
1682     ipxnet_t *ipxnet;
1683
1684     set_ipxnetent(g_ipxnets_path);
1685
1686     while (((ipxnet = get_ipxnetent()) != NULL) && (addr != ipxnet->addr) ) ;
1687
1688     if (ipxnet == NULL) {
1689         end_ipxnetent();
1690
1691         set_ipxnetent(g_pipxnets_path);
1692
1693         while (((ipxnet = get_ipxnetent()) != NULL) && (addr != ipxnet->addr) )
1694             ;
1695
1696         end_ipxnetent();
1697     }
1698
1699     return ipxnet;
1700
1701 } /* get_ipxnetbyaddr */
1702
1703 static void
1704 initialize_ipxnets(void)
1705 {
1706     /* Compute the pathname of the ipxnets file.
1707      *
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?
1712      */
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);
1716     }
1717
1718     /* Set g_pipxnets_path here, but don't actually do anything
1719      * with it. It's used in get_ipxnetbyname() and get_ipxnetbyaddr()
1720      */
1721     if (g_pipxnets_path == NULL)
1722         g_pipxnets_path = get_persconffile_path(ENAME_IPXNETS, FALSE);
1723
1724 } /* initialize_ipxnets */
1725
1726 static void
1727 ipx_name_lookup_cleanup(void)
1728 {
1729     ipxnet_hash_table = NULL;
1730     g_free(g_pipxnets_path);
1731     g_pipxnets_path = NULL;
1732 }
1733
1734 #if 0
1735 static hashipxnet_t *
1736 add_ipxnet_name(guint addr, const gchar *name)
1737 {
1738     hashipxnet_t *tp;
1739
1740     tp = (hashipxnet_t   *)g_hash_table_lookup(ipxnet_hash_table, &addr);
1741     if (tp) {
1742         g_strlcpy(tp->name, name, MAXNAMELEN);
1743     } else {
1744         int *key;
1745
1746         key = (int *)g_new(int, 1);
1747         *key = addr;
1748         tp = g_new(hashipxnet_t,1);
1749         g_strlcpy(tp->name, name, MAXNAMELEN);
1750         g_hash_table_insert(ipxnet_hash_table, key, tp);
1751     }
1752
1753     tp->addr = addr;
1754     g_strlcpy(tp->name, name, MAXNAMELEN);
1755     tp->next = NULL;
1756     new_resolved_objects = TRUE;
1757
1758     return tp;
1759
1760 } /* add_ipxnet_name */
1761 #endif
1762
1763 static gchar *
1764 ipxnet_name_lookup(wmem_allocator_t *allocator, const guint addr)
1765 {
1766     hashipxnet_t *tp;
1767     ipxnet_t *ipxnet;
1768
1769     tp = (hashipxnet_t *)wmem_map_lookup(ipxnet_hash_table, &addr);
1770     if (tp == NULL) {
1771         int *key;
1772
1773         key = (int *)wmem_new(wmem_epan_scope(), int);
1774         *key = addr;
1775         tp = wmem_new(wmem_epan_scope(), hashipxnet_t);
1776         wmem_map_insert(ipxnet_hash_table, key, tp);
1777     } else {
1778         return wmem_strdup(allocator, tp->name);
1779     }
1780
1781     /* fill in a new entry */
1782
1783     tp->addr = addr;
1784
1785     if ( (ipxnet = get_ipxnetbyaddr(addr)) == NULL) {
1786         /* unknown name */
1787         g_snprintf(tp->name, MAXNAMELEN, "%X", addr);
1788
1789     } else {
1790         g_strlcpy(tp->name, ipxnet->name, MAXNAMELEN);
1791     }
1792
1793     return wmem_strdup(allocator, tp->name);
1794
1795 } /* ipxnet_name_lookup */
1796
1797 static guint
1798 ipxnet_addr_lookup(const gchar *name _U_, gboolean *success)
1799 {
1800     *success = FALSE;
1801     return 0;
1802 #if 0
1803     /* XXX Do we need reverse lookup??? */
1804     ipxnet_t *ipxnet;
1805     hashipxnet_t *tp;
1806     hashipxnet_t **table = ipxnet_table;
1807     int i;
1808
1809     /* to be optimized (hash table from name to addr) */
1810     for (i = 0; i < HASHIPXNETSIZE; i++) {
1811         tp = table[i];
1812         while (tp) {
1813             if (strcmp(tp->name, name) == 0) {
1814                 *success = TRUE;
1815                 return tp->addr;
1816             }
1817             tp = tp->next;
1818         }
1819     }
1820
1821     /* not in hash table : performs a file lookup */
1822
1823     if ((ipxnet = get_ipxnetbyname(name)) == NULL) {
1824         *success = FALSE;
1825         return 0;
1826     }
1827
1828     /* add new entry in hash table */
1829
1830     tp = add_ipxnet_name(ipxnet->addr, name);
1831
1832     *success = TRUE;
1833     return tp->addr;
1834 #endif
1835 } /* ipxnet_addr_lookup */
1836
1837 /* VLANS */
1838 static int
1839 parse_vlan_line(char *line, vlan_t *vlan)
1840 {
1841     gchar     *cp;
1842     guint16   id;
1843
1844     if ((cp = strchr(line, '#')))
1845         *cp = '\0';
1846
1847     if ((cp = strtok(line, " \t\n")) == NULL)
1848         return -1;
1849
1850     if (sscanf(cp, "%" G_GUINT16_FORMAT, &id) == 1) {
1851         vlan->id = id;
1852     }
1853     else {
1854         return -1;
1855     }
1856
1857     if ((cp = strtok(NULL, "\t\n")) == NULL)
1858         return -1;
1859
1860     g_strlcpy(vlan->name, cp, MAXVLANNAMELEN);
1861
1862     return 0;
1863
1864 } /* parse_vlan_line */
1865
1866 static FILE *vlan_p = NULL;
1867
1868 static void
1869 set_vlanent(char *path)
1870 {
1871     if (vlan_p)
1872         rewind(vlan_p);
1873     else
1874         vlan_p = ws_fopen(path, "r");
1875 }
1876
1877 static void
1878 end_vlanent(void)
1879 {
1880     if (vlan_p) {
1881         fclose(vlan_p);
1882         vlan_p = NULL;
1883     }
1884 }
1885
1886 static vlan_t *
1887 get_vlanent(void)
1888 {
1889
1890     static vlan_t vlan;
1891     static int     size = 0;
1892     static char   *buf = NULL;
1893
1894     if (vlan_p == NULL)
1895         return NULL;
1896
1897     while (fgetline(&buf, &size, vlan_p) >= 0) {
1898         if (parse_vlan_line(buf, &vlan) == 0) {
1899             return &vlan;
1900         }
1901     }
1902
1903     return NULL;
1904
1905 } /* get_vlanent */
1906
1907 static vlan_t *
1908 get_vlannamebyid(guint16 id)
1909 {
1910     vlan_t *vlan;
1911
1912     set_vlanent(g_pvlan_path);
1913
1914     while (((vlan = get_vlanent()) != NULL) && (id != vlan->id) ) ;
1915
1916     if (vlan == NULL) {
1917         end_vlanent();
1918
1919     }
1920
1921     return vlan;
1922
1923 } /* get_vlannamebyid */
1924
1925 static void
1926 initialize_vlans(void)
1927 {
1928     g_assert(vlan_hash_table == NULL);
1929     vlan_hash_table = wmem_map_new(wmem_epan_scope(), g_int_hash, g_int_equal);
1930
1931     /* Set g_pvlan_path here, but don't actually do anything
1932      * with it. It's used in get_vlannamebyid()
1933      */
1934     if (g_pvlan_path == NULL)
1935         g_pvlan_path = get_persconffile_path(ENAME_VLANS, FALSE);
1936
1937 } /* initialize_vlans */
1938
1939 static void
1940 vlan_name_lookup_cleanup(void)
1941 {
1942     vlan_hash_table = NULL;
1943     g_free(g_pvlan_path);
1944     g_pvlan_path = NULL;
1945 }
1946
1947 static const gchar *
1948 vlan_name_lookup(const guint id)
1949 {
1950     hashvlan_t *tp;
1951     vlan_t *vlan;
1952
1953     tp = (hashvlan_t *)wmem_map_lookup(vlan_hash_table, &id);
1954     if (tp == NULL) {
1955         int *key;
1956
1957         key = (int *)wmem_new(wmem_epan_scope(), int);
1958         *key = id;
1959         tp = wmem_new(wmem_epan_scope(), hashvlan_t);
1960         wmem_map_insert(vlan_hash_table, key, tp);
1961     } else {
1962         return tp->name;
1963     }
1964
1965     /* fill in a new entry */
1966
1967     tp->id = id;
1968
1969     if ( (vlan = get_vlannamebyid(id)) == NULL) {
1970         /* unknown name */
1971         g_snprintf(tp->name, MAXVLANNAMELEN, "<%u>", id);
1972
1973     } else {
1974         g_strlcpy(tp->name, vlan->name, MAXVLANNAMELEN);
1975     }
1976
1977     return tp->name;
1978
1979 } /* vlan_name_lookup */
1980 /* VLAN END */
1981
1982 static gboolean
1983 read_hosts_file (const char *hostspath, gboolean store_entries)
1984 {
1985     FILE *hf;
1986     char *line = NULL;
1987     int size = 0;
1988     gchar *cp;
1989     union {
1990         guint32 ip4_addr;
1991         struct e_in6_addr ip6_addr;
1992     } host_addr;
1993     gboolean is_ipv6, entry_found = FALSE;
1994
1995     /*
1996      *  See the hosts(4) or hosts(5) man page for hosts file format
1997      *  (not available on all systems).
1998      */
1999     if ((hf = ws_fopen(hostspath, "r")) == NULL)
2000         return FALSE;
2001
2002     while (fgetline(&line, &size, hf) >= 0) {
2003         if ((cp = strchr(line, '#')))
2004             *cp = '\0';
2005
2006         if ((cp = strtok(line, " \t")) == NULL)
2007             continue; /* no tokens in the line */
2008
2009         if (ws_inet_pton6(cp, &host_addr.ip6_addr)) {
2010             /* Valid IPv6 */
2011             is_ipv6 = TRUE;
2012         } else if (ws_inet_pton4(cp, &host_addr.ip4_addr)) {
2013             /* Valid IPv4 */
2014             is_ipv6 = FALSE;
2015         } else {
2016             continue;
2017         }
2018
2019         if ((cp = strtok(NULL, " \t")) == NULL)
2020             continue; /* no host name */
2021
2022         entry_found = TRUE;
2023         if (store_entries) {
2024             if (is_ipv6) {
2025                 add_ipv6_name(&host_addr.ip6_addr, cp);
2026             } else {
2027                 add_ipv4_name(host_addr.ip4_addr, cp);
2028             }
2029         }
2030     }
2031     wmem_free(wmem_epan_scope(), line);
2032
2033     fclose(hf);
2034     return entry_found ? TRUE : FALSE;
2035 } /* read_hosts_file */
2036
2037 gboolean
2038 add_hosts_file (const char *hosts_file)
2039 {
2040     gboolean found = FALSE;
2041     guint i;
2042
2043     if (!hosts_file)
2044         return FALSE;
2045
2046     if (!extra_hosts_files)
2047         extra_hosts_files = g_ptr_array_new();
2048
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)
2051             found = TRUE;
2052     }
2053
2054     if (!found) {
2055         g_ptr_array_add(extra_hosts_files, wmem_strdup(wmem_epan_scope(), hosts_file));
2056         return read_hosts_file (hosts_file, FALSE);
2057     }
2058     return TRUE;
2059 }
2060
2061 gboolean
2062 add_ip_name_from_string (const char *addr, const char *name)
2063 {
2064     union {
2065         guint32 ip4_addr;
2066         struct e_in6_addr ip6_addr;
2067     } host_addr;
2068     gboolean is_ipv6;
2069     resolved_ipv4_t *resolved_ipv4_entry;
2070     resolved_ipv6_t *resolved_ipv6_entry;
2071
2072     if (ws_inet_pton6(addr, &host_addr.ip6_addr)) {
2073         is_ipv6 = TRUE;
2074     } else if (ws_inet_pton4(addr, &host_addr.ip4_addr)) {
2075         is_ipv6 = FALSE;
2076     } else {
2077         return FALSE;
2078     }
2079
2080     if (is_ipv6) {
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);
2085     } else {
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);
2090     }
2091
2092     return TRUE;
2093 } /* add_ip_name_from_string */
2094
2095 /*
2096  * Add the resolved addresses that are in use to the list used to create the NRB
2097  */
2098 static void
2099 ipv4_hash_table_resolved_to_list(gpointer key _U_, gpointer value, gpointer user_data)
2100 {
2101     addrinfo_lists_t *lists = (addrinfo_lists_t*)user_data;
2102     hashipv4_t *ipv4_hash_table_entry = (hashipv4_t *)value;
2103
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);
2106     }
2107
2108 }
2109
2110 /*
2111  * Add the resolved addresses that are in use to the list used to create the NRB
2112  */
2113
2114 static void
2115 ipv6_hash_table_resolved_to_list(gpointer key _U_, gpointer value, gpointer user_data)
2116 {
2117     addrinfo_lists_t *lists = (addrinfo_lists_t*)user_data;
2118     hashipv6_t *ipv6_hash_table_entry = (hashipv6_t *)value;
2119
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);
2122     }
2123
2124 }
2125
2126 addrinfo_lists_t *
2127 get_addrinfo_list(void)
2128 {
2129     if (ipv4_hash_table) {
2130         wmem_map_foreach(ipv4_hash_table, ipv4_hash_table_resolved_to_list, &addrinfo_lists);
2131     }
2132
2133     if (ipv6_hash_table) {
2134         wmem_map_foreach(ipv6_hash_table, ipv6_hash_table_resolved_to_list, &addrinfo_lists);
2135     }
2136
2137     return &addrinfo_lists;
2138 }
2139
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.
2151  *
2152  * XXX Support IPv6
2153  */
2154 static gboolean
2155 read_subnets_file (const char *subnetspath)
2156 {
2157     FILE *hf;
2158     char *line = NULL;
2159     int size = 0;
2160     gchar *cp, *cp2;
2161     guint32 host_addr; /* IPv4 ONLY */
2162     guint8 mask_length;
2163
2164     if ((hf = ws_fopen(subnetspath, "r")) == NULL)
2165         return FALSE;
2166
2167     while (fgetline(&line, &size, hf) >= 0) {
2168         if ((cp = strchr(line, '#')))
2169             *cp = '\0';
2170
2171         if ((cp = strtok(line, " \t")) == NULL)
2172             continue; /* no tokens in the line */
2173
2174
2175         /* Expected format is <IP4 address>/<subnet length> */
2176         cp2 = strchr(cp, '/');
2177         if (NULL == cp2) {
2178             /* No length */
2179             continue;
2180         }
2181         *cp2 = '\0'; /* Cut token */
2182         ++cp2    ;
2183
2184         /* Check if this is a valid IPv4 address */
2185         if (!str_to_ip(cp, &host_addr)) {
2186             continue; /* no */
2187         }
2188
2189         if (!ws_strtou8(cp2, NULL, &mask_length) || mask_length == 0 || mask_length > 32) {
2190             continue; /* invalid mask length */
2191         }
2192
2193         if ((cp = strtok(NULL, " \t")) == NULL)
2194             continue; /* no subnet name */
2195
2196         subnet_entry_set(host_addr, mask_length, cp);
2197     }
2198     wmem_free(wmem_epan_scope(), line);
2199
2200     fclose(hf);
2201     return TRUE;
2202 } /* read_subnets_file */
2203
2204 static subnet_entry_t
2205 subnet_lookup(const guint32 addr)
2206 {
2207     subnet_entry_t subnet_entry;
2208     guint32 i;
2209
2210     /* Search mask lengths linearly, longest first */
2211
2212     i = SUBNETLENGTHSIZE;
2213     while(have_subnet_entry && i > 0) {
2214         guint32 masked_addr;
2215         subnet_length_entry_t* length_entry;
2216
2217         /* Note that we run from 31 (length 32)  to 0 (length 1)  */
2218         --i;
2219         g_assert(i < SUBNETLENGTHSIZE);
2220
2221
2222         length_entry = &subnet_length_entries[i];
2223
2224         if (NULL != length_entry->subnet_addresses) {
2225             sub_net_hashipv4_t * tp;
2226             guint32 hash_idx;
2227
2228             masked_addr = addr & length_entry->mask;
2229             hash_idx = HASH_IPV4_ADDRESS(masked_addr);
2230
2231             tp = length_entry->subnet_addresses[hash_idx];
2232             while(tp != NULL && tp->addr != masked_addr) {
2233                 tp = tp->next;
2234             }
2235
2236             if (NULL != tp) {
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;
2241             }
2242         }
2243     }
2244
2245     subnet_entry.mask = 0;
2246     subnet_entry.mask_length = 0;
2247     subnet_entry.name = NULL;
2248
2249     return subnet_entry;
2250 }
2251
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
2254  * given length.
2255  */
2256 static void
2257 subnet_entry_set(guint32 subnet_addr, const guint8 mask_length, const gchar* name)
2258 {
2259     subnet_length_entry_t* entry;
2260     sub_net_hashipv4_t * tp;
2261     gsize hash_idx;
2262
2263     g_assert(mask_length > 0 && mask_length <= 32);
2264
2265     entry = &subnet_length_entries[mask_length - 1];
2266
2267     subnet_addr &= entry->mask;
2268
2269     hash_idx = HASH_IPV4_ADDRESS(subnet_addr);
2270
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);
2273     }
2274
2275     if (NULL != (tp = entry->subnet_addresses[hash_idx])) {
2276         sub_net_hashipv4_t * new_tp;
2277
2278         while (tp->next) {
2279             if (tp->addr == subnet_addr) {
2280                 return; /* XXX provide warning that an address was repeated? */
2281             } else {
2282                 tp = tp->next;
2283             }
2284         }
2285
2286         new_tp = wmem_new(wmem_epan_scope(), sub_net_hashipv4_t);
2287         tp->next = new_tp;
2288         tp = new_tp;
2289     } else {
2290         tp = entry->subnet_addresses[hash_idx] = wmem_new(wmem_epan_scope(), sub_net_hashipv4_t);
2291     }
2292
2293     tp->next = NULL;
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;
2299 }
2300
2301 static void
2302 subnet_name_lookup_init(void)
2303 {
2304     gchar* subnetspath;
2305     guint32 i;
2306
2307     for(i = 0; i < SUBNETLENGTHSIZE; ++i) {
2308         guint32 length = i + 1;
2309
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));
2313     }
2314
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);
2320         }
2321
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);
2326         }
2327     }
2328     g_free(subnetspath);
2329
2330     /*
2331      * Load the global subnets file, if we have one.
2332      */
2333     subnetspath = get_datafile_path(ENAME_SUBNETS);
2334     if (!read_subnets_file(subnetspath) && errno != ENOENT) {
2335         report_open_failure(subnetspath, errno, FALSE);
2336     }
2337     g_free(subnetspath);
2338 }
2339
2340 /* SS7 PC Name Resolution Portion */
2341 static hashss7pc_t *
2342 new_ss7pc(const guint8 ni, const guint32 pc)
2343 {
2344     hashss7pc_t *tp = wmem_new(wmem_epan_scope(), hashss7pc_t);
2345     tp->id = (ni<<24) + (pc&0xffffff);
2346     tp->pc_addr[0] = '\0';
2347     tp->name[0] = '\0';
2348
2349     return tp;
2350 }
2351
2352 static hashss7pc_t *
2353 host_lookup_ss7pc(const guint8 ni, const guint32 pc)
2354 {
2355     hashss7pc_t * volatile tp;
2356     guint32 id;
2357
2358     id = (ni<<24) + (pc&0xffffff);
2359
2360     tp = (hashss7pc_t *)wmem_map_lookup(ss7pc_hash_table, GUINT_TO_POINTER(id));
2361     if (tp == NULL) {
2362         tp = new_ss7pc(ni, pc);
2363         wmem_map_insert(ss7pc_hash_table, GUINT_TO_POINTER(id), tp);
2364     }
2365
2366     return tp;
2367 }
2368
2369 void fill_unresolved_ss7pc(const gchar * pc_addr, const guint8 ni, const guint32 pc)
2370 {
2371     hashss7pc_t *tp = host_lookup_ss7pc(ni, pc);
2372
2373     g_strlcpy(tp->pc_addr, pc_addr, MAXNAMELEN);
2374 }
2375
2376 const gchar *
2377 get_hostname_ss7pc(const guint8 ni, const guint32 pc)
2378 {
2379     hashss7pc_t *tp = host_lookup_ss7pc(ni, pc);
2380
2381     /* never resolved yet*/
2382     if (tp->pc_addr[0] == '\0')
2383         return tp->pc_addr;
2384
2385     /* Don't have name in file */
2386     if (tp->name[0] == '\0')
2387         return tp->pc_addr;
2388
2389     if (!gbl_resolv_flags.ss7pc_name)
2390         return tp->pc_addr;
2391
2392     return tp->name;
2393 }
2394
2395 static void
2396 add_ss7pc_name(const guint8 ni, guint32 pc, const gchar *name)
2397 {
2398     hashss7pc_t *tp;
2399     guint32 id;
2400
2401     if (!name || name[0] == '\0')
2402         return;
2403
2404     id = (ni<<24) + (pc&0xffffff);
2405     tp = (hashss7pc_t *)wmem_map_lookup(ss7pc_hash_table, GUINT_TO_POINTER(id));
2406     if (!tp) {
2407         tp = new_ss7pc(ni, pc);
2408         wmem_map_insert(ss7pc_hash_table, GUINT_TO_POINTER(id), tp);
2409     }
2410
2411     if (g_ascii_strcasecmp(tp->name, name)) {
2412         g_strlcpy(tp->name, name, MAXNAMELEN);
2413     }
2414 }
2415
2416 static gboolean
2417 read_ss7pcs_file(const char *ss7pcspath)
2418 {
2419     FILE *hf;
2420     char *line = NULL;
2421     int size = 0;
2422     gchar *cp;
2423     guint8 ni;
2424     guint32 pc;
2425     gboolean entry_found = FALSE;
2426
2427     /*
2428     *  File format is Network Indicator (decimal)<dash>Point Code (Decimal)<tab/space>Hostname
2429     */
2430     if ((hf = ws_fopen(ss7pcspath, "r")) == NULL)
2431         return FALSE;
2432
2433     while (fgetline(&line, &size, hf) >= 0) {
2434         if ((cp = strchr(line, '#')))
2435             *cp = '\0';
2436
2437         if ((cp = strtok(line, "-")) == NULL)
2438             continue; /*no ni-pc separator*/
2439         if (!ws_strtou8(cp, NULL, &ni))
2440             continue;
2441         if (ni > 3)
2442              continue;
2443
2444         if ((cp = strtok(NULL, " \t")) == NULL)
2445             continue; /* no tokens for pc and name */
2446         if (!ws_strtou32(cp, NULL, &pc))
2447             continue;
2448         if (pc >> 24 > 0)
2449             continue;
2450
2451         if ((cp = strtok(NULL, " \t")) == NULL)
2452             continue; /* no host name */
2453
2454         entry_found = TRUE;
2455         add_ss7pc_name(ni, pc, cp);
2456     }
2457     wmem_free(wmem_epan_scope(), line);
2458
2459     fclose(hf);
2460     return entry_found ? TRUE : FALSE;
2461 }
2462
2463 static void
2464 ss7pc_name_lookup_init(void)
2465 {
2466     char *ss7pcspath;
2467
2468     g_assert(ss7pc_hash_table == NULL);
2469
2470     ss7pc_hash_table = wmem_map_new(wmem_epan_scope(), g_direct_hash, g_direct_equal);
2471
2472     /*
2473      * Load the user's ss7pcs file
2474      */
2475     ss7pcspath = get_persconffile_path(ENAME_SS7PCS, TRUE);
2476     if (!read_ss7pcs_file(ss7pcspath) && errno != ENOENT) {
2477         report_open_failure(ss7pcspath, errno, FALSE);
2478     }
2479     g_free(ss7pcspath);
2480 }
2481
2482 /* SS7PC Name Resolution End*/
2483
2484
2485 /*
2486  *  External Functions
2487  */
2488
2489 void
2490 addr_resolve_pref_init(module_t *nameres)
2491 {
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);
2497
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);
2502
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);
2510
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);
2515
2516 #ifdef HAVE_C_ARES
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"
2522             " is enabled.",
2523             &gbl_resolv_flags.use_external_net_name_resolver);
2524
2525     prefs_register_obsolete_preference(nameres, "concurrent_dns");
2526
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.",
2533             10,
2534             &name_resolve_concurrency);
2535 #else
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");
2540 #endif
2541
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);
2547
2548     prefs_register_bool_preference(nameres, "vlan_name",
2549             "Resolve VLAN IDs",
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);
2554
2555     prefs_register_bool_preference(nameres, "ss7_pc_name",
2556             "Resolve SS7 PCs",
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);
2561
2562 }
2563
2564 void
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;
2573 }
2574
2575 #ifdef HAVE_C_ARES
2576 gboolean
2577 host_name_lookup_process(void) {
2578     async_dns_queue_msg_t *caqm;
2579     struct timeval tv = { 0, 0 };
2580     int nfds;
2581     fd_set rfds, wfds;
2582     gboolean nro = new_resolved_objects;
2583     wmem_list_frame_t* head;
2584
2585     new_resolved_objects = FALSE;
2586
2587     if (!async_dns_initialized)
2588         /* c-ares not initialized. Bail out and cancel timers. */
2589         return nro;
2590
2591     head = wmem_list_head(async_dns_queue_head);
2592
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++;
2604         }
2605
2606         head = wmem_list_head(async_dns_queue_head);
2607     }
2608
2609     FD_ZERO(&rfds);
2610     FD_ZERO(&wfds);
2611     nfds = ares_fds(ghba_chan, &rfds, &wfds);
2612     if (nfds > 0) {
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));
2615             return nro;
2616         }
2617         ares_process(ghba_chan, &rfds, &wfds);
2618     }
2619
2620     /* Any new entries? */
2621     return nro;
2622 }
2623
2624 static void
2625 _host_name_lookup_cleanup(void) {
2626     async_dns_queue_head = NULL;
2627
2628     if (async_dns_initialized) {
2629         ares_destroy(ghba_chan);
2630         ares_destroy(ghbn_chan);
2631     }
2632 #ifdef CARES_HAVE_ARES_LIBRARY_INIT
2633     ares_library_cleanup();
2634 #endif
2635     async_dns_initialized = FALSE;
2636 }
2637
2638 #else
2639
2640 gboolean
2641 host_name_lookup_process(void) {
2642     gboolean nro = new_resolved_objects;
2643
2644     new_resolved_objects = FALSE;
2645
2646     return nro;
2647 }
2648
2649 static void
2650 _host_name_lookup_cleanup(void) {
2651 }
2652
2653 #endif /* HAVE_C_ARES */
2654
2655 const gchar *
2656 get_hostname(const guint addr)
2657 {
2658     /* XXX why do we call this if we're not resolving? To create hash entries?
2659      * Why?
2660      */
2661     hashipv4_t *tp = host_lookup(addr);
2662
2663     if (!gbl_resolv_flags.network_name)
2664         return tp->ip;
2665
2666     tp->flags |= RESOLVED_ADDRESS_USED;
2667
2668     return tp->name;
2669 }
2670
2671 /* -------------------------- */
2672
2673 const gchar *
2674 get_hostname6(const struct e_in6_addr *addr)
2675 {
2676     /* XXX why do we call this if we're not resolving? To create hash entries?
2677      * Why?
2678      */
2679     hashipv6_t *tp = host_lookup6(addr);
2680
2681     if (!gbl_resolv_flags.network_name)
2682         return tp->ip6;
2683
2684     tp->flags |= RESOLVED_ADDRESS_USED;
2685
2686     return tp->name;
2687 }
2688
2689 /* -------------------------- */
2690 void
2691 add_ipv4_name(const guint addr, const gchar *name)
2692 {
2693     hashipv4_t *tp;
2694
2695     /*
2696      * Don't add zero-length names; apparently, some resolvers will return
2697      * them if they get them from DNS.
2698      */
2699     if (!name || name[0] == '\0')
2700         return;
2701
2702     tp = (hashipv4_t *)wmem_map_lookup(ipv4_hash_table, GUINT_TO_POINTER(addr));
2703     if (!tp) {
2704         tp = new_ipv4(addr);
2705         wmem_map_insert(ipv4_hash_table, GUINT_TO_POINTER(addr), tp);
2706     }
2707
2708     if (g_ascii_strcasecmp(tp->name, name)) {
2709         g_strlcpy(tp->name, name, MAXNAMELEN);
2710         new_resolved_objects = TRUE;
2711     }
2712     tp->flags |= TRIED_RESOLVE_ADDRESS|NAME_RESOLVED;
2713 } /* add_ipv4_name */
2714
2715 /* -------------------------- */
2716 void
2717 add_ipv6_name(const struct e_in6_addr *addrp, const gchar *name)
2718 {
2719     hashipv6_t *tp;
2720
2721     /*
2722      * Don't add zero-length names; apparently, some resolvers will return
2723      * them if they get them from DNS.
2724      */
2725     if (!name || name[0] == '\0')
2726         return;
2727
2728     tp = (hashipv6_t *)wmem_map_lookup(ipv6_hash_table, addrp);
2729     if (!tp) {
2730         struct e_in6_addr *addr_key;
2731
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);
2736     }
2737
2738     if (g_ascii_strcasecmp(tp->name, name)) {
2739         g_strlcpy(tp->name, name, MAXNAMELEN);
2740         new_resolved_objects = TRUE;
2741     }
2742     tp->flags |= TRIED_RESOLVE_ADDRESS|NAME_RESOLVED;
2743 } /* add_ipv6_name */
2744
2745 static void
2746 add_manually_resolved_ipv4(gpointer data, gpointer user_data _U_)
2747 {
2748     resolved_ipv4_t *resolved_ipv4_entry = (resolved_ipv4_t *)data;
2749
2750     add_ipv4_name(resolved_ipv4_entry->host_addr, resolved_ipv4_entry->name);
2751 }
2752
2753 static void
2754 add_manually_resolved_ipv6(gpointer data, gpointer user_data _U_)
2755 {
2756     resolved_ipv6_t *resolved_ipv6_entry = (resolved_ipv6_t *)data;
2757
2758     add_ipv6_name(&(resolved_ipv6_entry->ip6_addr), resolved_ipv6_entry->name);
2759 }
2760
2761 static void
2762 add_manually_resolved(void)
2763 {
2764     if (manually_resolved_ipv4_list) {
2765         wmem_list_foreach(manually_resolved_ipv4_list, add_manually_resolved_ipv4, NULL);
2766     }
2767
2768     if (manually_resolved_ipv6_list) {
2769         wmem_list_foreach(manually_resolved_ipv6_list, add_manually_resolved_ipv6, NULL);
2770     }
2771 }
2772
2773 void
2774 host_name_lookup_init(void)
2775 {
2776     char *hostspath;
2777     guint i;
2778
2779     g_assert(ipxnet_hash_table == NULL);
2780     ipxnet_hash_table = wmem_map_new(wmem_epan_scope(), g_int_hash, g_int_equal);
2781
2782     g_assert(ipv4_hash_table == NULL);
2783     ipv4_hash_table = wmem_map_new(wmem_epan_scope(), g_direct_hash, g_direct_equal);
2784
2785     g_assert(ipv6_hash_table == NULL);
2786     ipv6_hash_table = wmem_map_new(wmem_epan_scope(), ipv6_oat_hash, ipv6_equal);
2787
2788 #ifdef HAVE_C_ARES
2789     g_assert(async_dns_queue_head == NULL);
2790     async_dns_queue_head = wmem_list_new(wmem_epan_scope());
2791 #endif
2792
2793     if (manually_resolved_ipv4_list == NULL)
2794         manually_resolved_ipv4_list = wmem_list_new(wmem_epan_scope());
2795
2796     if (manually_resolved_ipv6_list == NULL)
2797         manually_resolved_ipv6_list = wmem_list_new(wmem_epan_scope());
2798
2799     /*
2800      * Load the global hosts file, if we have one.
2801      */
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);
2806         }
2807         g_free(hostspath);
2808     }
2809     /*
2810      * Load the user's hosts file no matter what, if they have one.
2811      */
2812     hostspath = get_persconffile_path(ENAME_HOSTS, TRUE);
2813     if (!read_hosts_file(hostspath, TRUE) && errno != ENOENT) {
2814         report_open_failure(hostspath, errno, FALSE);
2815     }
2816     g_free(hostspath);
2817 #ifdef HAVE_C_ARES
2818 #ifdef CARES_HAVE_ARES_LIBRARY_INIT
2819     if (ares_library_init(ARES_LIB_INIT_ALL) == ARES_SUCCESS) {
2820 #endif
2821         if (ares_init(&ghba_chan) == ARES_SUCCESS && ares_init(&ghbn_chan) == ARES_SUCCESS) {
2822             async_dns_initialized = TRUE;
2823         }
2824 #ifdef CARES_HAVE_ARES_LIBRARY_INIT
2825     }
2826 #endif
2827 #else
2828 #endif /* HAVE_C_ARES */
2829
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);
2833         }
2834     }
2835
2836     subnet_name_lookup_init();
2837
2838     add_manually_resolved();
2839
2840     ss7pc_name_lookup_init();
2841 }
2842
2843 void
2844 host_name_lookup_cleanup(void)
2845 {
2846     guint32 i, j;
2847     sub_net_hashipv4_t *entry, *next_entry;
2848
2849     _host_name_lookup_cleanup();
2850
2851     ipxnet_hash_table = NULL;
2852     ipv4_hash_table = NULL;
2853     ipv6_hash_table = NULL;
2854     ss7pc_hash_table = NULL;
2855
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);
2863                 }
2864             }
2865             wmem_free(wmem_epan_scope(), subnet_length_entries[i].subnet_addresses);
2866             subnet_length_entries[i].subnet_addresses = NULL;
2867         }
2868     }
2869
2870     have_subnet_entry = FALSE;
2871     new_resolved_objects = FALSE;
2872 }
2873
2874 void
2875 manually_resolve_cleanup(void)
2876 {
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;
2881 }
2882
2883 gchar *
2884 udp_port_to_display(wmem_allocator_t *allocator, guint port)
2885 {
2886
2887     if (!gbl_resolv_flags.transport_name) {
2888         return wmem_utoa(allocator, port);
2889     }
2890
2891     return wmem_strdup(allocator, serv_name_lookup(PT_UDP, port));
2892
2893 } /* udp_port_to_display */
2894
2895 gchar *
2896 dccp_port_to_display(wmem_allocator_t *allocator, guint port)
2897 {
2898
2899     if (!gbl_resolv_flags.transport_name) {
2900         return wmem_utoa(allocator, port);
2901     }
2902
2903     return wmem_strdup(allocator, serv_name_lookup(PT_DCCP, port));
2904
2905 } /* dccp_port_to_display */
2906
2907 gchar *
2908 tcp_port_to_display(wmem_allocator_t *allocator, guint port)
2909 {
2910
2911     if (!gbl_resolv_flags.transport_name) {
2912         return wmem_utoa(allocator, port);
2913     }
2914
2915     return wmem_strdup(allocator, serv_name_lookup(PT_TCP, port));
2916
2917 } /* tcp_port_to_display */
2918
2919 gchar *
2920 sctp_port_to_display(wmem_allocator_t *allocator, guint port)
2921 {
2922
2923     if (!gbl_resolv_flags.transport_name) {
2924         return wmem_utoa(allocator, port);
2925     }
2926
2927     return wmem_strdup(allocator, serv_name_lookup(PT_SCTP, port));
2928
2929 } /* sctp_port_to_display */
2930
2931 gchar *
2932 port_with_resolution_to_str(wmem_allocator_t *scope, port_type proto, guint port)
2933 {
2934     const gchar *port_str;
2935
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);
2939     }
2940     port_str = serv_name_lookup(proto, port);
2941     g_assert(port_str);
2942     return wmem_strdup_printf(scope, "%s (%u)", port_str, port);
2943 }
2944
2945 int
2946 port_with_resolution_to_str_buf(gchar *buf, gulong buf_size, port_type proto, guint port)
2947 {
2948     const gchar *port_str;
2949
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);
2953     }
2954     port_str = serv_name_lookup(proto, port);
2955     g_assert(port_str);
2956     return g_snprintf(buf, buf_size, "%s (%u)", port_str, port);
2957 }
2958
2959 const gchar *
2960 get_ether_name(const guint8 *addr)
2961 {
2962     hashether_t *tp;
2963     gboolean resolve = gbl_resolv_flags.mac_name;
2964
2965     tp = eth_name_lookup(addr, resolve);
2966
2967     return resolve ? tp->resolved_name : tp->hexaddr;
2968
2969 } /* get_ether_name */
2970
2971 const gchar *
2972 tvb_get_ether_name(tvbuff_t *tvb, gint offset)
2973 {
2974     return get_ether_name(tvb_get_ptr(tvb, offset, 6));
2975 }
2976
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.
2979  */
2980 const gchar *
2981 get_ether_name_if_known(const guint8 *addr)
2982 {
2983     hashether_t *tp;
2984
2985     /* Initialize ether structs if we're the first
2986      * ether-related function called */
2987     if (!gbl_resolv_flags.mac_name)
2988         return NULL;
2989
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);
2993
2994     if (tp->status == HASHETHER_STATUS_RESOLVED_NAME) {
2995         /* Name is from an ethers file */
2996         return tp->resolved_name;
2997     }
2998     else {
2999         /* Name was created */
3000         return NULL;
3001     }
3002 }
3003
3004 guint8 *
3005 get_ether_addr(const gchar *name)
3006 {
3007
3008     /* force resolution (do not check gbl_resolv_flags) */
3009     return eth_addr_lookup(name);
3010
3011 } /* get_ether_addr */
3012
3013 void
3014 add_ether_byip(const guint ip, const guint8 *eth)
3015 {
3016     hashipv4_t *tp;
3017
3018     /* first check that IP address can be resolved */
3019     if (!gbl_resolv_flags.network_name)
3020         return;
3021
3022     tp = host_lookup(ip);
3023
3024     /*
3025      * Was this IP address resolved to a host name?
3026      */
3027     if (tp->flags & NAME_RESOLVED) {
3028         /*
3029          * Yes, so add an entry in the ethers hashtable resolving
3030          * the MAC address to that name.
3031          */
3032         add_eth_name(eth, tp->name);
3033     }
3034
3035 } /* add_ether_byip */
3036
3037 gchar *
3038 ipxnet_to_str_punct(wmem_allocator_t *allocator, const guint32 ad, const char punct)
3039 {
3040     gchar *buf = (gchar *)wmem_alloc(allocator, 12);
3041
3042     *dword_to_hex_punct(buf, ad, punct) = '\0';
3043     return buf;
3044 }
3045
3046 gchar *
3047 get_ipxnet_name(wmem_allocator_t *allocator, const guint32 addr)
3048 {
3049
3050     if (!gbl_resolv_flags.network_name) {
3051         return ipxnet_to_str_punct(allocator, addr, '\0');
3052     }
3053
3054     return ipxnet_name_lookup(allocator, addr);
3055
3056 } /* get_ipxnet_name */
3057
3058 guint32
3059 get_ipxnet_addr(const gchar *name, gboolean *known)
3060 {
3061     guint32 addr;
3062     gboolean success;
3063
3064     /* force resolution (do not check gbl_resolv_flags) */
3065     addr =  ipxnet_addr_lookup(name, &success);
3066
3067     *known = success;
3068     return addr;
3069
3070 } /* get_ipxnet_addr */
3071
3072 gchar *
3073 get_vlan_name(wmem_allocator_t *allocator, const guint16 id)
3074 {
3075
3076     if (!gbl_resolv_flags.vlan_name) {
3077         return NULL;
3078     }
3079
3080     return wmem_strdup(allocator, vlan_name_lookup(id));
3081
3082 } /* get_vlan_name */
3083
3084 const gchar *
3085 get_manuf_name(const guint8 *addr)
3086 {
3087     hashmanuf_t *manuf_value;
3088
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;
3092
3093     return manuf_value->hexaddr;
3094
3095 } /* get_manuf_name */
3096
3097 const gchar *
3098 uint_get_manuf_name(const guint oid)
3099 {
3100     guint8 addr[3];
3101
3102     addr[0] = (oid >> 16) & 0xFF;
3103     addr[1] = (oid >> 8) & 0xFF;
3104     addr[2] = (oid >> 0) & 0xFF;
3105     return get_manuf_name(addr);
3106 }
3107
3108 const gchar *
3109 tvb_get_manuf_name(tvbuff_t *tvb, gint offset)
3110 {
3111     return get_manuf_name(tvb_get_ptr(tvb, offset, 3));
3112 }
3113
3114 const gchar *
3115 get_manuf_name_if_known(const guint8 *addr)
3116 {
3117     hashmanuf_t *manuf_value;
3118     int manuf_key;
3119     guint8 oct;
3120
3121     /* manuf needs only the 3 most significant octets of the ethernet address */
3122     manuf_key = addr[0];
3123     manuf_key = manuf_key<<8;
3124     oct = addr[1];
3125     manuf_key = manuf_key | oct;
3126     manuf_key = manuf_key<<8;
3127     oct = addr[2];
3128     manuf_key = manuf_key | oct;
3129
3130     manuf_value = (hashmanuf_t *)wmem_map_lookup(manuf_hashtable, &manuf_key);
3131     if ((manuf_value == NULL) || (manuf_value->status == HASHETHER_STATUS_UNRESOLVED)) {
3132         return NULL;
3133     }
3134
3135     return manuf_value->resolved_name;
3136
3137 } /* get_manuf_name_if_known */
3138
3139 const gchar *
3140 uint_get_manuf_name_if_known(const guint manuf_key)
3141 {
3142     hashmanuf_t *manuf_value;
3143
3144     manuf_value = (hashmanuf_t *)wmem_map_lookup(manuf_hashtable, &manuf_key);
3145     if ((manuf_value == NULL) || (manuf_value->status == HASHETHER_STATUS_UNRESOLVED)) {
3146         return NULL;
3147     }
3148
3149     return manuf_value->resolved_name;
3150 }
3151
3152 const gchar *
3153 tvb_get_manuf_name_if_known(tvbuff_t *tvb, gint offset)
3154 {
3155     return get_manuf_name_if_known(tvb_get_ptr(tvb, offset, 3));
3156 }
3157
3158 char* get_hash_manuf_resolved_name(hashmanuf_t* manuf)
3159 {
3160     return manuf->resolved_name;
3161 }
3162
3163 gchar *
3164 eui64_to_display(wmem_allocator_t *allocator, const guint64 addr_eui64)
3165 {
3166     guint8 *addr = (guint8 *)wmem_alloc(NULL, 8);
3167     hashmanuf_t *manuf_value;
3168     gchar *ret;
3169
3170     /* Copy and convert the address to network byte order. */
3171     *(guint64 *)(void *)(addr) = pntoh64(&(addr_eui64));
3172
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]);
3176     } else {
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]);
3178     }
3179
3180     wmem_free(NULL, addr);
3181     return ret;
3182 } /* eui64_to_display */
3183
3184 #ifdef HAVE_C_ARES
3185 #define GHI_TIMEOUT (250 * 1000)
3186 static void
3187 c_ares_ghi_cb(
3188         void *arg,
3189         int status,
3190 #if ( ( ARES_VERSION_MAJOR < 1 )                                     \
3191     || ( 1 == ARES_VERSION_MAJOR && ARES_VERSION_MINOR < 5 ) )
3192         struct hostent *hp
3193 #else
3194         int timeouts _U_,
3195         struct hostent *hp
3196 #endif
3197         ) {
3198
3199     /*
3200      * XXX - If we wanted to be really fancy we could cache results here and
3201      * look them up in get_host_ipaddr* below.
3202      */
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;
3207     }
3208 }
3209 #endif /* HAVE_C_ARES */
3210
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 */
3215 gboolean
3216 get_host_ipaddr(const char *host, guint32 *addrp)
3217 {
3218     struct in_addr      ipaddr;
3219 #ifdef HAVE_C_ARES
3220     struct timeval tv = { 0, GHI_TIMEOUT }, *tvp;
3221     int nfds;
3222     fd_set rfds, wfds;
3223     async_hostent_t ahe;
3224 #endif
3225
3226     /*
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.
3230      */
3231     if (!inet_aton(host, &ipaddr)) {
3232
3233         /* It's not a valid dotted-quad IP address; is it a valid
3234          * host name?
3235          */
3236
3237         /* If we're not allowed to do name resolution, don't do name
3238          * resolution...
3239          */
3240         if (!gbl_resolv_flags.network_name ||
3241                 !gbl_resolv_flags.use_external_net_name_resolver) {
3242             return FALSE;
3243         }
3244
3245 #ifdef HAVE_C_ARES
3246         if (!async_dns_initialized || name_resolve_concurrency < 1) {
3247             return FALSE;
3248         }
3249         ahe.addr_size = (int) sizeof (struct in_addr);
3250         ahe.copied = 0;
3251         ahe.addrp = addrp;
3252         ares_gethostbyname(ghbn_chan, host, AF_INET, c_ares_ghi_cb, &ahe);
3253         FD_ZERO(&rfds);
3254         FD_ZERO(&wfds);
3255         nfds = ares_fds(ghbn_chan, &rfds, &wfds);
3256         if (nfds > 0) {
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));
3260                 return FALSE;
3261             }
3262             ares_process(ghbn_chan, &rfds, &wfds);
3263         }
3264         ares_cancel(ghbn_chan);
3265         if (ahe.addr_size == ahe.copied) {
3266             return TRUE;
3267         }
3268         return FALSE;
3269 #endif
3270     } else {
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.
3275          */
3276         unsigned int a0, a1, a2, a3;
3277         if (sscanf(host, "%u.%u.%u.%u", &a0, &a1, &a2, &a3) != 4)
3278             return FALSE;
3279     }
3280
3281     *addrp = ipaddr.s_addr;
3282     return TRUE;
3283 }
3284
3285 /*
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.
3289  */
3290 gboolean
3291 get_host_ipaddr6(const char *host, struct e_in6_addr *addrp)
3292 {
3293 #ifdef HAVE_C_ARES
3294     struct timeval tv = { 0, GHI_TIMEOUT }, *tvp;
3295     int nfds;
3296     fd_set rfds, wfds;
3297     async_hostent_t ahe;
3298 #endif /* HAVE_C_ARES */
3299
3300     if (str_to_ip6(host, addrp))
3301         return TRUE;
3302
3303     /* It's not a valid dotted-quad IP address; is it a valid
3304      * host name?
3305      */
3306
3307     /* If we're not allowed to do name resolution, don't do name
3308      * resolution...
3309      */
3310     if (!gbl_resolv_flags.network_name ||
3311             !gbl_resolv_flags.use_external_net_name_resolver) {
3312         return FALSE;
3313     }
3314
3315     /* try FQDN */
3316 #ifdef HAVE_C_ARES
3317     if (!async_dns_initialized || name_resolve_concurrency < 1) {
3318         return FALSE;
3319     }
3320     ahe.addr_size = (int) sizeof (struct e_in6_addr);
3321     ahe.copied = 0;
3322     ahe.addrp = addrp;
3323     ares_gethostbyname(ghbn_chan, host, AF_INET6, c_ares_ghi_cb, &ahe);
3324     FD_ZERO(&rfds);
3325     FD_ZERO(&wfds);
3326     nfds = ares_fds(ghbn_chan, &rfds, &wfds);
3327     if (nfds > 0) {
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));
3331             return FALSE;
3332         }
3333         ares_process(ghbn_chan, &rfds, &wfds);
3334     }
3335     ares_cancel(ghbn_chan);
3336     if (ahe.addr_size == ahe.copied) {
3337         return TRUE;
3338     }
3339 #endif
3340
3341     return FALSE;
3342 }
3343
3344 wmem_map_t *
3345 get_manuf_hashtable(void)
3346 {
3347     return manuf_hashtable;
3348 }
3349
3350 wmem_map_t *
3351 get_wka_hashtable(void)
3352 {
3353     return wka_hashtable;
3354 }
3355
3356 wmem_map_t *
3357 get_eth_hashtable(void)
3358 {
3359     return eth_hashtable;
3360 }
3361
3362 wmem_map_t *
3363 get_serv_port_hashtable(void)
3364 {
3365     return serv_port_hashtable;
3366 }
3367
3368 wmem_map_t *
3369 get_ipxnet_hash_table(void)
3370 {
3371         return ipxnet_hash_table;
3372 }
3373
3374 wmem_map_t *
3375 get_vlan_hash_table(void)
3376 {
3377         return vlan_hash_table;
3378 }
3379
3380 wmem_map_t *
3381 get_ipv4_hash_table(void)
3382 {
3383         return ipv4_hash_table;
3384 }
3385
3386 wmem_map_t *
3387 get_ipv6_hash_table(void)
3388 {
3389         return ipv6_hash_table;
3390 }
3391 /* Initialize all the address resolution subsystems in this file */
3392 void
3393 addr_resolv_init(void)
3394 {
3395     initialize_services();
3396     initialize_ethers();
3397     initialize_ipxnets();
3398     initialize_vlans();
3399     /* host name initialization is done on a per-capture-file basis */
3400     /*host_name_lookup_init();*/
3401 }
3402
3403 /* Clean up all the address resolution subsystems in this file */
3404 void
3405 addr_resolv_cleanup(void)
3406 {
3407     vlan_name_lookup_cleanup();
3408     service_name_lookup_cleanup();
3409     ethers_cleanup();
3410     ipx_name_lookup_cleanup();
3411     /* host name initialization is done on a per-capture-file basis */
3412     /*host_name_lookup_cleanup();*/
3413 }
3414
3415 gboolean
3416 str_to_ip(const char *str, void *dst)
3417 {
3418     return ws_inet_pton4(str, (guint32 *)dst);
3419 }
3420
3421 gboolean
3422 str_to_ip6(const char *str, void *dst)
3423 {
3424     return ws_inet_pton6(str, (struct e_in6_addr *)dst);
3425 }
3426
3427 /*
3428  * Editor modelines  -  http://www.wireshark.org/tools/modelines.html
3429  *
3430  * Local variables:
3431  * c-basic-offset: 4
3432  * tab-width: 8
3433  * indent-tabs-mode: nil
3434  * End:
3435  *
3436  * vi: set shiftwidth=4 tabstop=8 expandtab:
3437  * :indentSize=4:tabSize=8:noTabs=true:
3438  */