debug keys
[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  * SPDX-License-Identifier: GPL-2.0-or-later
14  */
15
16 #include "config.h"
17
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <string.h>
21 #include <errno.h>
22
23 #include <wsutil/strtoi.h>
24
25 /*
26  * Win32 doesn't have SIGALRM (and it's the OS where name lookup calls
27  * are most likely to take a long time, given the way address-to-name
28  * lookups are done over NBNS).
29  *
30  * macOS does have SIGALRM, but if you longjmp() out of a name resolution
31  * call in a signal handler, you might crash, because the state of the
32  * resolution code that sends messages to lookupd might be inconsistent
33  * if you jump out of it in middle of a call.
34  *
35  * There's no guarantee that longjmp()ing out of name resolution calls
36  * will work on *any* platform; OpenBSD got rid of the alarm/longjmp
37  * code in tcpdump, to avoid those sorts of problems, and that was
38  * picked up by tcpdump.org tcpdump.
39  *
40  * So, for now, we do not use alarm() and SIGALRM to time out host name
41  * lookups.  If we get a lot of complaints about lookups taking a long time,
42  * we can reconsider that decision.  (Note that tcpdump originally added
43  * such a timeout mechanism that for the benefit of systems using NIS to
44  * look up host names; that might now be fixed in NIS implementations, for
45  * those sites still using NIS rather than DNS for that....  tcpdump no
46  * longer does that, for the same reasons that we don't.)
47  *
48  * If we're using an asynchronous DNS resolver, that shouldn't be an issue.
49  * If we're using a synchronous name lookup mechanism (which we'd do mainly
50  * to support resolving addresses and host names using more mechanisms than
51  * just DNS, such as NIS, NBNS, or Mr. Hosts File), we could do that in
52  * a separate thread, making it, in effect, asynchronous.
53  */
54
55 #ifdef HAVE_NETINET_IN_H
56 # include <netinet/in.h>
57 #endif
58
59 #ifdef HAVE_NETDB_H
60 #include <netdb.h>
61 #endif
62
63 #ifdef HAVE_SYS_SOCKET_H
64 #include <sys/socket.h>     /* needed to define AF_ values on UNIX */
65 #endif
66
67 #ifdef _WIN32
68 #include <winsock2.h>       /* needed to define AF_ values on Windows */
69 #include <ws2tcpip.h>
70 #endif
71
72 #ifdef HAVE_C_ARES
73 # ifdef _WIN32
74 #  define socklen_t unsigned int
75 # endif
76 # include <ares.h>
77 # include <ares_version.h>
78 #endif  /* HAVE_C_ARES */
79
80 #include <glib.h>
81
82 #include "packet.h"
83 #include "addr_and_mask.h"
84 #include "ipv6.h"
85 #include "addr_resolv.h"
86 #include "wsutil/filesystem.h"
87
88 #include <wsutil/report_message.h>
89 #include <wsutil/file_util.h>
90 #include <wsutil/pint.h>
91 #include <wsutil/inet_addr.h>
92
93 #include <epan/strutil.h>
94 #include <epan/to_str-int.h>
95 #include <epan/maxmind_db.h>
96 #include <epan/prefs.h>
97
98 #define ENAME_HOSTS     "hosts"
99 #define ENAME_SUBNETS   "subnets"
100 #define ENAME_ETHERS    "ethers"
101 #define ENAME_IPXNETS   "ipxnets"
102 #define ENAME_MANUF     "manuf"
103 #define ENAME_WKA       "wka"
104 #define ENAME_SERVICES  "services"
105 #define ENAME_VLANS     "vlans"
106 #define ENAME_SS7PCS    "ss7pcs"
107 #define ENAME_ENTERPRISES "enterprises.tsv"
108
109 #define HASHETHSIZE      2048
110 #define HASHHOSTSIZE     2048
111 #define HASHIPXNETSIZE    256
112 #define SUBNETLENGTHSIZE   32  /*1-32 inc.*/
113
114 /* hash table used for IPv4 lookup */
115
116 #define HASH_IPV4_ADDRESS(addr) (g_htonl(addr) & (HASHHOSTSIZE - 1))
117
118
119 typedef struct sub_net_hashipv4 {
120     guint             addr;
121     /* XXX: No longer needed?*/
122     guint8            flags;          /* B0 dummy_entry, B1 resolve, B2 If the address is used in the trace */
123     struct sub_net_hashipv4   *next;
124     gchar             name[MAXNAMELEN];
125 } sub_net_hashipv4_t;
126
127 /* Array of entries of subnets of different lengths */
128 typedef struct {
129     gsize        mask_length;      /*1-32*/
130     guint32      mask;             /* e.g. 255.255.255.*/
131     sub_net_hashipv4_t** subnet_addresses; /* Hash table of subnet addresses */
132 } subnet_length_entry_t;
133
134
135 /* hash table used for IPX network lookup */
136
137 /* XXX - check goodness of hash function */
138
139 #define HASH_IPX_NET(net)   ((net) & (HASHIPXNETSIZE - 1))
140
141 typedef struct hashipxnet {
142     guint               addr;
143     struct hashipxnet  *next;
144     gchar               name[MAXNAMELEN];
145 } hashipxnet_t;
146
147 typedef struct hashvlan {
148     guint               id;
149 /*    struct hashvlan     *next; */
150     gchar               name[MAXVLANNAMELEN];
151 } hashvlan_t;
152
153 typedef struct ss7pc {
154     guint32             id; /* 1st byte NI, 3 following bytes: Point Code */
155     gchar               pc_addr[MAXNAMELEN];
156     gchar               name[MAXNAMELEN];
157 } hashss7pc_t;
158
159 /* hash tables used for ethernet and manufacturer lookup */
160 #define HASHETHER_STATUS_UNRESOLVED     1
161 #define HASHETHER_STATUS_RESOLVED_DUMMY 2
162 #define HASHETHER_STATUS_RESOLVED_NAME  3
163
164 struct hashether {
165     guint             status;  /* (See above) */
166     guint8            addr[6];
167     char              hexaddr[6*3];
168     char              resolved_name[MAXNAMELEN];
169 };
170
171 struct hashmanuf {
172     guint             status;  /* (See above) */
173     guint8            addr[3];
174     char              hexaddr[3*3];
175     char              resolved_name[MAXNAMELEN];
176     char              resolved_longname[MAXNAMELEN];
177 };
178
179 /* internal ethernet type */
180 typedef struct _ether
181 {
182     guint8            addr[6];
183     char              name[MAXNAMELEN];
184     char              longname[MAXNAMELEN];
185 } ether_t;
186
187 /* internal ipxnet type */
188 typedef struct _ipxnet
189 {
190     guint             addr;
191     char              name[MAXNAMELEN];
192 } ipxnet_t;
193
194 /* internal vlan type */
195 typedef struct _vlan
196 {
197     guint             id;
198     char              name[MAXVLANNAMELEN];
199 } vlan_t;
200
201 // Maps guint -> hashipxnet_t*
202 static wmem_map_t *ipxnet_hash_table = NULL;
203 static wmem_map_t *ipv4_hash_table = NULL;
204 static wmem_map_t *ipv6_hash_table = NULL;
205 // Maps guint -> hashvlan_t*
206 static wmem_map_t *vlan_hash_table = NULL;
207 static wmem_map_t *ss7pc_hash_table = NULL;
208
209 static wmem_list_t *manually_resolved_ipv4_list = NULL;
210 static wmem_list_t *manually_resolved_ipv6_list = NULL;
211
212 typedef struct _resolved_ipv4
213 {
214     guint32          host_addr;
215     char             name[MAXNAMELEN];
216 } resolved_ipv4_t;
217
218 typedef struct _resolved_ipv6
219 {
220     ws_in6_addr  ip6_addr;
221     char               name[MAXNAMELEN];
222 } resolved_ipv6_t;
223
224 static addrinfo_lists_t addrinfo_lists = { NULL, NULL};
225
226 struct cb_serv_data {
227     gchar       *service;
228     port_type    proto;
229 };
230
231 // Maps guint -> hashmanuf_t*
232 static wmem_map_t *manuf_hashtable = NULL;
233 static wmem_map_t *wka_hashtable = NULL;
234 static wmem_map_t *eth_hashtable = NULL;
235 // Maps guint -> serv_port_t*
236 static wmem_map_t *serv_port_hashtable = NULL;
237 static GHashTable *enterprises_hashtable = NULL;
238
239 static subnet_length_entry_t subnet_length_entries[SUBNETLENGTHSIZE]; /* Ordered array of entries */
240 static gboolean have_subnet_entry = FALSE;
241
242 static gboolean new_resolved_objects = FALSE;
243
244 static GPtrArray* extra_hosts_files = NULL;
245
246 static hashether_t *add_eth_name(const guint8 *addr, const gchar *name);
247 static void add_serv_port_cb(const guint32 port, gpointer ptr);
248
249
250 /* http://eternallyconfuzzled.com/tuts/algorithms/jsw_tut_hashing.aspx#existing
251  * One-at-a-Time hash
252  */
253 guint
254 ipv6_oat_hash(gconstpointer key)
255 {
256     int len = 16;
257     const unsigned char *p = (const unsigned char *)key;
258     guint h = 0;
259     int i;
260
261     for ( i = 0; i < len; i++ ) {
262         h += p[i];
263         h += ( h << 10 );
264         h ^= ( h >> 6 );
265     }
266
267     h += ( h << 3 );
268     h ^= ( h >> 11 );
269     h += ( h << 15 );
270
271     return h;
272 }
273
274 gboolean
275 ipv6_equal(gconstpointer v1, gconstpointer v2)
276 {
277
278     if (memcmp(v1, v2, sizeof (ws_in6_addr)) == 0) {
279         return TRUE;
280     }
281
282     return FALSE;
283 }
284
285 /*
286  * Flag controlling what names to resolve.
287  */
288 e_addr_resolve gbl_resolv_flags = {
289     TRUE,   /* mac_name */
290     FALSE,  /* network_name */
291     FALSE,  /* transport_name */
292     TRUE,   /* dns_pkt_addr_resolution */
293     TRUE,   /* use_external_net_name_resolver */
294     FALSE,  /* load_hosts_file_from_profile_only */
295     FALSE,  /* vlan_name */
296     FALSE   /* ss7 point code names */
297 };
298 #ifdef HAVE_C_ARES
299 static guint name_resolve_concurrency = 500;
300 static gboolean resolve_synchronously = FALSE;
301 #endif
302
303 /*
304  *  Global variables (can be changed in GUI sections)
305  *  XXX - they could be changed in GUI code, but there's currently no
306  *  GUI code to change them.
307  */
308
309 gchar *g_ethers_path    = NULL;     /* global ethers file     */
310 gchar *g_pethers_path   = NULL;     /* personal ethers file   */
311 gchar *g_wka_path       = NULL;     /* global well-known-addresses file */
312 gchar *g_manuf_path     = NULL;     /* global manuf file      */
313 gchar *g_ipxnets_path   = NULL;     /* global ipxnets file    */
314 gchar *g_pipxnets_path  = NULL;     /* personal ipxnets file  */
315 gchar *g_services_path  = NULL;     /* global services file   */
316 gchar *g_pservices_path = NULL;     /* personal services file */
317 gchar *g_pvlan_path     = NULL;     /* personal vlans file    */
318 gchar *g_ss7pcs_path    = NULL;     /* personal ss7pcs file   */
319 gchar *g_enterprises_path = NULL;   /* global enterprises file   */
320 gchar *g_penterprises_path = NULL;  /* personal enterprises file */
321                                     /* first resolving call   */
322
323 /* c-ares */
324 #ifdef HAVE_C_ARES
325 /*
326  * Submitted asynchronous queries trigger a callback (c_ares_ghba_cb()).
327  * Queries are added to c_ares_queue_head. During processing, queries are
328  * popped off the front of c_ares_queue_head and submitted using
329  * ares_gethostbyaddr().
330  * The callback processes the response, then frees the request.
331  */
332 typedef struct _async_dns_queue_msg
333 {
334     union {
335         guint32           ip4;
336         ws_in6_addr ip6;
337     } addr;
338     int                 family;
339 } async_dns_queue_msg_t;
340
341 typedef struct _async_hostent {
342     int addr_size;
343     int   copied;
344     void *addrp;
345 } async_hostent_t;
346
347 /*
348  * Submitted synchronous queries trigger a callback (c_ares_ghba_sync_cb()).
349  * The callback processes the response, sets completed to TRUE if
350  * completed is non-NULL, then frees the request.
351  */
352 typedef struct _sync_dns_data
353 {
354     union {
355         guint32      ip4;
356         ws_in6_addr  ip6;
357     } addr;
358     int              family;
359     gboolean        *completed;
360 } sync_dns_data_t;
361
362 static ares_channel ghba_chan; /* ares_gethostbyaddr -- Usually non-interactive, no timeout */
363 static ares_channel ghbn_chan; /* ares_gethostbyname -- Usually interactive, timeout */
364
365 static  gboolean  async_dns_initialized = FALSE;
366 static  guint       async_dns_in_flight = 0;
367 static  wmem_list_t *async_dns_queue_head = NULL;
368
369 static void
370 c_ares_ghba_sync_cb(void *arg, int status, int timeouts _U_, struct hostent *he) {
371     sync_dns_data_t *sdd = (sync_dns_data_t *)arg;
372     char **p;
373
374     if (status == ARES_SUCCESS) {
375         for (p = he->h_addr_list; *p != NULL; p++) {
376             switch(sdd->family) {
377                 case AF_INET:
378                     add_ipv4_name(sdd->addr.ip4, he->h_name);
379                     break;
380                 case AF_INET6:
381                     add_ipv6_name(&sdd->addr.ip6, he->h_name);
382                     break;
383                 default:
384                     /* Throw an exception? */
385                     break;
386             }
387         }
388
389     }
390
391     /*
392      * Let our caller know that this is complete.
393      */
394     *sdd->completed = TRUE;
395
396     /*
397      * Free the structure for this call.
398      */
399     g_free(sdd);
400 }
401
402 static void
403 wait_for_sync_resolv(gboolean *completed) {
404     int nfds;
405     fd_set rfds, wfds;
406     struct timeval tv;
407
408     while (!*completed) {
409         /*
410          * Not yet resolved; wait for something to show up on the
411          * address-to-name C-ARES channel.
412          *
413          * To quote the source code for ares_timeout() as of C-ARES
414          * 1.12.0, "WARNING: Beware that this is linear in the number
415          * of outstanding requests! You are probably far better off
416          * just calling ares_process() once per second, rather than
417          * calling ares_timeout() to figure out when to next call
418          * ares_process().", although we should have only one request
419          * outstanding.
420          *
421          * And, yes, we have to reset it each time, as select(), in
422          * some OSes modifies the timeout to reflect the time remaining
423          * (e.g., Linux) and select() in other OSes doesn't (most if not
424          * all other UN*Xes, Windows?), so we can't rely on *either*
425          * behavior.
426          */
427         tv.tv_sec = 1;
428         tv.tv_usec = 0;
429
430         FD_ZERO(&rfds);
431         FD_ZERO(&wfds);
432         nfds = ares_fds(ghba_chan, &rfds, &wfds);
433         if (nfds > 0) {
434             if (select(nfds, &rfds, &wfds, NULL, &tv) == -1) { /* call to select() failed */
435                 fprintf(stderr, "Warning: call to select() failed, error is %s\n", g_strerror(errno));
436                 return;
437             }
438             ares_process(ghba_chan, &rfds, &wfds);
439         }
440     }
441 }
442
443 static void
444 sync_lookup_ip4(const guint32 addr)
445 {
446     gboolean completed = FALSE;
447     sync_dns_data_t *sdd;
448
449     if (!async_dns_initialized) {
450         /*
451          * c-ares not initialized.  Bail out.
452          */
453         return;
454     }
455
456     /*
457      * Start the request.
458      */
459     sdd = g_new(sync_dns_data_t, 1);
460     sdd->family = AF_INET;
461     sdd->addr.ip4 = addr;
462     sdd->completed = &completed;
463     ares_gethostbyaddr(ghba_chan, &addr, sizeof(guint32), AF_INET,
464                        c_ares_ghba_sync_cb, sdd);
465
466     /*
467      * Now wait for it to finish.
468      */
469     wait_for_sync_resolv(&completed);
470 }
471
472 static void
473 sync_lookup_ip6(const ws_in6_addr *addr)
474 {
475     gboolean completed = FALSE;
476     sync_dns_data_t *sdd;
477
478     if (!async_dns_initialized) {
479         /*
480          * c-ares not initialized.  Bail out.
481          */
482         return;
483     }
484
485     /*
486      * Start the request.
487      */
488     sdd = g_new(sync_dns_data_t, 1);
489     sdd->family = AF_INET6;
490     memcpy(&sdd->addr.ip6, addr, sizeof(sdd->addr.ip6));
491     sdd->completed = &completed;
492     ares_gethostbyaddr(ghba_chan, &addr, sizeof(ws_in6_addr), AF_INET6,
493                        c_ares_ghba_sync_cb, sdd);
494
495     /*
496      * Now wait for it to finish.
497      */
498     wait_for_sync_resolv(&completed);
499 }
500
501 void
502 set_resolution_synchrony(gboolean synchronous)
503 {
504     resolve_synchronously = synchronous;
505 }
506 #else
507 void
508 set_resolution_synchrony(gboolean synchronous _U_)
509 {
510     /* Nothing to set. */
511 }
512 #endif /* HAVE_C_ARES */
513
514 typedef struct {
515     guint32      mask;
516     gsize        mask_length;
517     const gchar* name; /* Shallow copy */
518 } subnet_entry_t;
519
520 /* Maximum supported line length of hosts, services, manuf, etc. */
521 #define MAX_LINELEN     1024
522
523 /** Read a line without trailing (CR)LF. Returns -1 on failure.  */
524 static int
525 fgetline(char *buf, int size, FILE *fp)
526 {
527     if (fgets(buf, size, fp)) {
528         int len = (int)strcspn(buf, "\r\n");
529         buf[len] = '\0';
530         return len;
531     }
532     return -1;
533
534 } /* fgetline */
535
536
537 /*
538  *  Local function definitions
539  */
540 static subnet_entry_t subnet_lookup(const guint32 addr);
541 static void subnet_entry_set(guint32 subnet_addr, const guint8 mask_length, const gchar* name);
542
543
544 static void
545 add_service_name(port_type proto, const guint port, const char *service_name)
546 {
547     serv_port_t *serv_port_table;
548
549     serv_port_table = (serv_port_t *)wmem_map_lookup(serv_port_hashtable, GUINT_TO_POINTER(port));
550     if (serv_port_table == NULL) {
551         serv_port_table = wmem_new0(wmem_epan_scope(), serv_port_t);
552         wmem_map_insert(serv_port_hashtable, GUINT_TO_POINTER(port), serv_port_table);
553     }
554
555     switch(proto) {
556         case PT_TCP:
557             wmem_free(wmem_epan_scope(), serv_port_table->tcp_name);
558             serv_port_table->tcp_name = wmem_strdup(wmem_epan_scope(), service_name);
559             break;
560         case PT_UDP:
561             wmem_free(wmem_epan_scope(), serv_port_table->udp_name);
562             serv_port_table->udp_name = wmem_strdup(wmem_epan_scope(), service_name);
563             break;
564         case PT_SCTP:
565             wmem_free(wmem_epan_scope(), serv_port_table->sctp_name);
566             serv_port_table->sctp_name = wmem_strdup(wmem_epan_scope(), service_name);
567             break;
568         case PT_DCCP:
569             wmem_free(wmem_epan_scope(), serv_port_table->dccp_name);
570             serv_port_table->dccp_name = wmem_strdup(wmem_epan_scope(), service_name);
571             break;
572         default:
573             return;
574             /* Should not happen */
575     }
576
577     new_resolved_objects = TRUE;
578 }
579
580
581 static void
582 parse_service_line (char *line)
583 {
584     gchar *cp;
585     gchar *service;
586     gchar *port;
587     port_type proto;
588     struct cb_serv_data cb_data;
589     range_t *port_rng = NULL;
590
591     if ((cp = strchr(line, '#')))
592         *cp = '\0';
593
594     if ((cp = strtok(line, " \t")) == NULL)
595         return;
596
597     service = cp;
598
599     if ((cp = strtok(NULL, " \t")) == NULL)
600         return;
601
602     port = cp;
603
604     if (strtok(cp, "/") == NULL)
605         return;
606
607     if (range_convert_str(NULL, &port_rng, port, G_MAXUINT16) != CVT_NO_ERROR) {
608         wmem_free (NULL, port_rng);
609         return;
610     }
611
612     while ((cp = strtok(NULL, "/")) != NULL) {
613         if (strcmp(cp, "tcp") == 0) {
614             proto = PT_TCP;
615         }
616         else if (strcmp(cp, "udp") == 0) {
617             proto = PT_UDP;
618         }
619         else if (strcmp(cp, "sctp") == 0) {
620             proto = PT_SCTP;
621         }
622         else if (strcmp(cp, "dccp") == 0) {
623             proto = PT_DCCP;
624         }
625         else {
626             break;
627         }
628         cb_data.service = service;
629         cb_data.proto = proto;
630         range_foreach(port_rng, add_serv_port_cb, &cb_data);
631     }
632
633     wmem_free (NULL, port_rng);
634 } /* parse_service_line */
635
636
637 static void
638 add_serv_port_cb(const guint32 port, gpointer ptr)
639 {
640     struct cb_serv_data *cb_data = (struct cb_serv_data *)ptr;
641
642     if ( port ) {
643         add_service_name(cb_data->proto, port, cb_data->service);
644     }
645 }
646
647
648 static gboolean
649 parse_services_file(const char * path)
650 {
651     FILE *serv_p;
652     char    buf[MAX_LINELEN];
653
654     /* services hash table initialization */
655     serv_p = ws_fopen(path, "r");
656
657     if (serv_p == NULL)
658         return FALSE;
659
660     while (fgetline(buf, sizeof(buf), serv_p) >= 0) {
661         parse_service_line(buf);
662     }
663
664     fclose(serv_p);
665     return TRUE;
666 }
667
668 /* -----------------
669  * unsigned integer to ascii
670  */
671 static gchar *
672 wmem_utoa(wmem_allocator_t *allocator, guint port)
673 {
674     gchar *bp = (gchar *)wmem_alloc(allocator, MAXNAMELEN);
675
676     /* XXX, guint32_to_str() ? */
677     guint32_to_str_buf(port, bp, MAXNAMELEN);
678     return bp;
679 }
680
681 static const gchar *
682 _serv_name_lookup(port_type proto, guint port, serv_port_t **value_ret)
683 {
684     serv_port_t *serv_port_table;
685
686     serv_port_table = (serv_port_t *)wmem_map_lookup(serv_port_hashtable, GUINT_TO_POINTER(port));
687
688     if (value_ret != NULL)
689         *value_ret = serv_port_table;
690
691     if (serv_port_table == NULL)
692         return NULL;
693
694     switch (proto) {
695         case PT_UDP:
696             return serv_port_table->udp_name;
697         case PT_TCP:
698             return serv_port_table->tcp_name;
699         case PT_SCTP:
700             return serv_port_table->sctp_name;
701         case PT_DCCP:
702             return serv_port_table->dccp_name;
703         default:
704             break;
705     }
706     return NULL;
707 }
708
709 const gchar *
710 try_serv_name_lookup(port_type proto, guint port)
711 {
712     return _serv_name_lookup(proto, port, NULL);
713 }
714
715 const gchar *
716 serv_name_lookup(port_type proto, guint port)
717 {
718     serv_port_t *serv_port_table = NULL;
719     const char *name;
720
721     name = _serv_name_lookup(proto, port, &serv_port_table);
722     if (name != NULL)
723         return name;
724
725     if (serv_port_table == NULL) {
726         serv_port_table = wmem_new0(wmem_epan_scope(), serv_port_t);
727         wmem_map_insert(serv_port_hashtable, GUINT_TO_POINTER(port), serv_port_table);
728     }
729     if (serv_port_table->numeric == NULL) {
730         serv_port_table->numeric = wmem_strdup_printf(wmem_epan_scope(), "%u", port);
731     }
732
733     return serv_port_table->numeric;
734 }
735
736 static void
737 initialize_services(void)
738 {
739     gboolean parse_file = TRUE;
740     g_assert(serv_port_hashtable == NULL);
741     serv_port_hashtable = wmem_map_new(wmem_epan_scope(), g_direct_hash, g_direct_equal);
742
743     /* Compute the pathname of the services file. */
744     if (g_services_path == NULL) {
745         g_services_path = get_datafile_path(ENAME_SERVICES);
746     }
747     parse_services_file(g_services_path);
748
749     /* Compute the pathname of the personal services file */
750     if (g_pservices_path == NULL) {
751         /* Check profile directory before personal configuration */
752         g_pservices_path = get_persconffile_path(ENAME_SERVICES, TRUE);
753         if (!parse_services_file(g_pservices_path)) {
754             g_free(g_pservices_path);
755             g_pservices_path = get_persconffile_path(ENAME_SERVICES, FALSE);
756         } else {
757             parse_file = FALSE;
758         }
759     }
760     if (parse_file) {
761         parse_services_file(g_pservices_path);
762     }
763 }
764
765 static void
766 service_name_lookup_cleanup(void)
767 {
768     serv_port_hashtable = NULL;
769     g_free(g_services_path);
770     g_services_path = NULL;
771     g_free(g_pservices_path);
772     g_pservices_path = NULL;
773 }
774
775 static void
776 parse_enterprises_line (char *line)
777 {
778     char *tok, *dec_str, *org_str;
779     guint32 dec;
780
781     if ((tok = strchr(line, '#')))
782         *tok = '\0';
783     dec_str = strtok(line, " \t");
784     if (!dec_str)
785         return;
786     org_str = strtok(NULL, ""); /* everything else */
787     if (org_str)
788         org_str = g_strstrip(org_str);
789     if (!org_str)
790         return;
791     if (!ws_strtou32(dec_str, NULL, &dec))
792         return;
793     g_hash_table_replace(enterprises_hashtable, GUINT_TO_POINTER(dec), g_strdup(org_str));
794 }
795
796
797 static gboolean
798 parse_enterprises_file(const char * path)
799 {
800     FILE *fp;
801     char    buf[MAX_LINELEN];
802
803     fp = ws_fopen(path, "r");
804     if (fp == NULL)
805         return FALSE;
806
807     while (fgetline(buf, sizeof(buf), fp) >= 0) {
808         parse_enterprises_line(buf);
809     }
810
811     fclose(fp);
812     return TRUE;
813 }
814
815 static void
816 initialize_enterprises(void)
817 {
818     g_assert(enterprises_hashtable == NULL);
819     enterprises_hashtable = g_hash_table_new_full(NULL, NULL, NULL, g_free);
820
821     if (g_enterprises_path == NULL) {
822         g_enterprises_path = get_datafile_path(ENAME_ENTERPRISES);
823     }
824     parse_enterprises_file(g_enterprises_path);
825
826     if (g_penterprises_path == NULL) {
827         g_penterprises_path = get_persconffile_path(ENAME_ENTERPRISES, FALSE);
828     }
829     parse_enterprises_file(g_penterprises_path);
830 }
831
832 const gchar *
833 try_enterprises_lookup(guint32 value)
834 {
835     return (const gchar *)g_hash_table_lookup(enterprises_hashtable, GUINT_TO_POINTER(value));
836 }
837
838 const gchar *
839 enterprises_lookup(guint32 value, const char *unknown_str)
840 {
841     const gchar *s;
842
843     s = try_enterprises_lookup(value);
844     if (s != NULL)
845         return s;
846     if (unknown_str != NULL)
847         return unknown_str;
848     return "<Unknown>";
849 }
850
851 void
852 enterprises_base_custom(char *buf, guint32 value)
853 {
854     const gchar *s;
855
856     if ((s = try_enterprises_lookup(value)) == NULL)
857         s = ITEM_LABEL_UNKNOWN_STR;
858     g_snprintf(buf, ITEM_LABEL_LENGTH, "%s (%u)", s, value);
859 }
860
861 static void
862 enterprises_cleanup(void)
863 {
864     g_assert(enterprises_hashtable);
865     g_hash_table_destroy(enterprises_hashtable);
866     enterprises_hashtable = NULL;
867     g_assert(g_enterprises_path);
868     g_free(g_enterprises_path);
869     g_enterprises_path = NULL;
870     g_free(g_penterprises_path);
871     g_penterprises_path = NULL;
872     g_free(g_pservices_path);
873     g_pservices_path = NULL;
874 }
875
876 /* Fill in an IP4 structure with info from subnets file or just with the
877  * string form of the address.
878  */
879 static void
880 fill_dummy_ip4(const guint addr, hashipv4_t* volatile tp)
881 {
882     subnet_entry_t subnet_entry;
883
884     /* Overwrite if we get async DNS reply */
885
886     /* Do we have a subnet for this address? */
887     subnet_entry = subnet_lookup(addr);
888     if (0 != subnet_entry.mask) {
889         /* Print name, then '.' then IP address after subnet mask */
890         guint32 host_addr;
891         gchar buffer[WS_INET_ADDRSTRLEN];
892         gchar* paddr;
893         gsize i;
894
895         host_addr = addr & (~subnet_entry.mask);
896         ip_to_str_buf((guint8 *)&host_addr, buffer, WS_INET_ADDRSTRLEN);
897         paddr = buffer;
898
899         /* Skip to first octet that is not totally masked
900          * If length of mask is 32, we chomp the whole address.
901          * If the address string starts '.' (should not happen?),
902          * we skip that '.'.
903          */
904         i = subnet_entry.mask_length / 8;
905         while(*(paddr) != '\0' && i > 0) {
906             if (*(++paddr) == '.') {
907                 --i;
908             }
909         }
910
911         /* There are more efficient ways to do this, but this is safe if we
912          * trust g_snprintf and MAXNAMELEN
913          */
914         g_snprintf(tp->name, MAXNAMELEN, "%s%s", subnet_entry.name, paddr);
915     } else {
916         /* XXX: This means we end up printing "1.2.3.4 (1.2.3.4)" in many cases */
917         ip_to_str_buf((const guint8 *)&addr, tp->name, MAXNAMELEN);
918     }
919 }
920
921
922 /* Fill in an IP6 structure with the string form of the address.
923  */
924 static void
925 fill_dummy_ip6(hashipv6_t* volatile tp)
926 {
927     /* Overwrite if we get async DNS reply */
928     g_strlcpy(tp->name, tp->ip6, MAXNAMELEN);
929 }
930
931 #ifdef HAVE_C_ARES
932
933 static void
934 c_ares_ghba_cb(void *arg, int status, int timeouts _U_, struct hostent *he) {
935     async_dns_queue_msg_t *caqm = (async_dns_queue_msg_t *)arg;
936     char **p;
937
938     if (!caqm) return;
939     /* XXX, what to do if async_dns_in_flight == 0? */
940     async_dns_in_flight--;
941
942     if (status == ARES_SUCCESS) {
943         for (p = he->h_addr_list; *p != NULL; p++) {
944             switch(caqm->family) {
945                 case AF_INET:
946                     add_ipv4_name(caqm->addr.ip4, he->h_name);
947                     break;
948                 case AF_INET6:
949                     add_ipv6_name(&caqm->addr.ip6, he->h_name);
950                     break;
951                 default:
952                     /* Throw an exception? */
953                     break;
954             }
955         }
956     }
957     wmem_free(wmem_epan_scope(), caqm);
958 }
959 #endif /* HAVE_C_ARES */
960
961 /* --------------- */
962 static hashipv4_t *
963 new_ipv4(const guint addr)
964 {
965     hashipv4_t *tp = wmem_new(wmem_epan_scope(), hashipv4_t);
966     tp->addr = addr;
967     tp->flags = 0;
968     tp->name[0] = '\0';
969     ip_to_str_buf((const guint8 *)&addr, tp->ip, sizeof(tp->ip));
970     return tp;
971 }
972
973 static hashipv4_t *
974 host_lookup(const guint addr)
975 {
976     hashipv4_t * volatile tp;
977
978     tp = (hashipv4_t *)wmem_map_lookup(ipv4_hash_table, GUINT_TO_POINTER(addr));
979     if (tp == NULL) {
980         /*
981          * We don't already have an entry for this host name; create one,
982          * and then try to resolve it.
983          */
984         tp = new_ipv4(addr);
985         fill_dummy_ip4(addr, tp);
986         wmem_map_insert(ipv4_hash_table, GUINT_TO_POINTER(addr), tp);
987     } else if (tp->flags & TRIED_OR_RESOLVED_MASK) {
988         return tp;
989     }
990
991     /*
992      * This hasn't been resolved yet, and we haven't tried to
993      * resolve it already.
994      */
995
996     if (!gbl_resolv_flags.network_name)
997         return tp;
998
999     if (gbl_resolv_flags.use_external_net_name_resolver) {
1000         tp->flags |= TRIED_RESOLVE_ADDRESS;
1001
1002 #ifdef HAVE_C_ARES
1003         if (async_dns_initialized) {
1004             /* c-ares is initialized, so we can use it */
1005             if (resolve_synchronously || name_resolve_concurrency == 0) {
1006                 /*
1007                  * Either all names are to be resolved synchronously or
1008                  * the concurrencly level is 0; do the resolution
1009                  * synchronously.
1010                  */
1011                 sync_lookup_ip4(addr);
1012             } else {
1013                 /*
1014                  * Names are to be resolved asynchronously, and we
1015                  * allow at least one asynchronous request in flight;
1016                  * post an asynchronous request.
1017                  */
1018                 async_dns_queue_msg_t *caqm;
1019
1020                 caqm = wmem_new(wmem_epan_scope(), async_dns_queue_msg_t);
1021                 caqm->family = AF_INET;
1022                 caqm->addr.ip4 = addr;
1023                 wmem_list_append(async_dns_queue_head, (gpointer) caqm);
1024             }
1025         }
1026 #endif
1027     }
1028
1029     return tp;
1030
1031 } /* host_lookup */
1032
1033 /* --------------- */
1034 static hashipv6_t *
1035 new_ipv6(const ws_in6_addr *addr)
1036 {
1037     hashipv6_t *tp = wmem_new(wmem_epan_scope(), hashipv6_t);
1038     memcpy(tp->addr, addr->bytes, sizeof tp->addr);
1039     tp->flags = 0;
1040     tp->name[0] = '\0';
1041     ip6_to_str_buf(addr, tp->ip6, sizeof(tp->ip6));
1042     return tp;
1043 }
1044
1045 /* ------------------------------------ */
1046 static hashipv6_t *
1047 host_lookup6(const ws_in6_addr *addr)
1048 {
1049     hashipv6_t * volatile tp;
1050
1051     tp = (hashipv6_t *)wmem_map_lookup(ipv6_hash_table, addr);
1052     if (tp == NULL) {
1053         /*
1054          * We don't already have an entry for this host name; create one,
1055          * and then try to resolve it.
1056          */
1057         ws_in6_addr *addr_key;
1058
1059         addr_key = wmem_new(wmem_epan_scope(), ws_in6_addr);
1060         tp = new_ipv6(addr);
1061         memcpy(addr_key, addr, 16);
1062         fill_dummy_ip6(tp);
1063         wmem_map_insert(ipv6_hash_table, addr_key, tp);
1064     } else if (tp->flags & TRIED_OR_RESOLVED_MASK) {
1065         return tp;
1066     }
1067
1068     /*
1069      * This hasn't been resolved yet, and we haven't tried to
1070      * resolve it already.
1071      */
1072
1073     if (!gbl_resolv_flags.network_name)
1074         return tp;
1075
1076     if (gbl_resolv_flags.use_external_net_name_resolver) {
1077         tp->flags |= TRIED_RESOLVE_ADDRESS;
1078
1079 #ifdef HAVE_C_ARES
1080         if (async_dns_initialized) {
1081             /* c-ares is initialized, so we can use it */
1082             if (resolve_synchronously || name_resolve_concurrency == 0) {
1083                 /*
1084                  * Either all names are to be resolved synchronously or
1085                  * the concurrencly level is 0; do the resolution
1086                  * synchronously.
1087                  */
1088                 sync_lookup_ip6(addr);
1089             } else {
1090                 /*
1091                  * Names are to be resolved asynchronously, and we
1092                  * allow at least one asynchronous request in flight;
1093                  * post an asynchronous request.
1094                  */
1095                 async_dns_queue_msg_t *caqm;
1096
1097                 caqm = wmem_new(wmem_epan_scope(), async_dns_queue_msg_t);
1098                 caqm->family = AF_INET6;
1099                 memcpy(&caqm->addr.ip6, addr, sizeof(caqm->addr.ip6));
1100                 wmem_list_append(async_dns_queue_head, (gpointer) caqm);
1101             }
1102         }
1103 #endif
1104     }
1105
1106     return tp;
1107
1108 } /* host_lookup6 */
1109
1110 /*
1111  * Ethernet / manufacturer resolution
1112  *
1113  * The following functions implement ethernet address resolution and
1114  * ethers files parsing (see ethers(4)).
1115  *
1116  * The manuf file has the same format as ethers(4) except that names are
1117  * truncated to MAXMANUFLEN-1 (8) characters and that an address contains
1118  * only 3 bytes (instead of 6).
1119  *
1120  * Notes:
1121  *
1122  * I decide to not use the existing functions (see ethers(3) on some
1123  * operating systems) for the following reasons:
1124  * - performance gains (use of hash tables and some other enhancements),
1125  * - use of two ethers files (system-wide and per user),
1126  * - avoid the use of NIS maps,
1127  * - lack of these functions on some systems.
1128  *
1129  * So the following functions do _not_ behave as the standard ones.
1130  *
1131  * -- Laurent.
1132  */
1133
1134 /*
1135  * Converts Ethernet addresses of the form aa:bb:cc or aa:bb:cc:dd:ee:ff/28. The
1136  * octets must be exactly two hexadecimal characters and the mask must be either
1137  * 28 or 36. Pre-condition: cp MUST be at least 21 bytes.
1138  */
1139 static gboolean
1140 parse_ether_address_fast(const guchar *cp, ether_t *eth, unsigned int *mask,
1141         const gboolean accept_mask)
1142 {
1143     /* XXX copied from strutil.c */
1144     /* a map from ASCII hex chars to their value */
1145     static const gint8 str_to_nibble[256] = {
1146         -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
1147         -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
1148         -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
1149          0, 1, 2, 3, 4, 5, 6, 7, 8, 9,-1,-1,-1,-1,-1,-1,
1150         -1,10,11,12,13,14,15,-1,-1,-1,-1,-1,-1,-1,-1,-1,
1151         -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
1152         -1,10,11,12,13,14,15,-1,-1,-1,-1,-1,-1,-1,-1,-1,
1153         -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
1154         -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
1155         -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
1156         -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
1157         -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
1158         -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
1159         -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
1160         -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
1161         -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
1162     };
1163     const guint8 *str_to_nibble_usg = (const guint8 *)str_to_nibble;
1164
1165     if (cp[2] != ':' || cp[5] != ':') {
1166         /* Unexpected separators. */
1167         return FALSE;
1168     }
1169
1170     guint8 num0 = (str_to_nibble_usg[cp[0]] << 4) | str_to_nibble_usg[cp[1]];
1171     guint8 num1 = (str_to_nibble_usg[cp[3]] << 4) | str_to_nibble_usg[cp[4]];
1172     guint8 num2 = (str_to_nibble_usg[cp[6]] << 4) | str_to_nibble_usg[cp[7]];
1173     if (((num0 | num1 | num2) & 0x80)) {
1174         /* Not hexadecimal numbers. */
1175         return FALSE;
1176     }
1177
1178     eth->addr[0] = num0;
1179     eth->addr[1] = num1;
1180     eth->addr[2] = num2;
1181
1182     if (cp[8] == '\0' && accept_mask) {
1183         /* Indicate that this is a manufacturer ID (0 is not allowed as a mask). */
1184         *mask = 0;
1185         return TRUE;
1186     } else if (cp[8] != ':' || !accept_mask) {
1187         /* Format not handled by this fast path. */
1188         return FALSE;
1189     }
1190
1191     guint8 num3 = (str_to_nibble_usg[cp[9]] << 4) | str_to_nibble_usg[cp[10]];
1192     guint8 num4 = (str_to_nibble_usg[cp[12]] << 4) | str_to_nibble_usg[cp[13]];
1193     guint8 num5 = (str_to_nibble_usg[cp[15]] << 4) | str_to_nibble_usg[cp[16]];
1194     if (((num3 | num4 | num5) & 0x80) || cp[11] != ':' || cp[14] != ':') {
1195         /* Not hexadecimal numbers or invalid separators. */
1196         return FALSE;
1197     }
1198
1199     eth->addr[3] = num3;
1200     eth->addr[4] = num4;
1201     eth->addr[5] = num5;
1202     if (cp[17] == '\0') {
1203         /* We got 6 bytes, so this is a MAC address (48 is not allowed as a mask). */
1204         *mask = 48;
1205         return TRUE;
1206     } else if (cp[17] != '/' || cp[20] != '\0') {
1207         /* Format not handled by this fast path. */
1208         return FALSE;
1209     }
1210
1211     int m1 = cp[18];
1212     int m2 = cp[19];
1213     if (m1 == '3' && m2 == '6') {   /* Mask /36 */
1214         eth->addr[4] &= 0xf0;
1215         eth->addr[5] = 0;
1216         *mask = 36;
1217         return TRUE;
1218     }
1219     if (m1 == '2' && m2 == '8') {   /* Mask /28 */
1220         eth->addr[3] &= 0xf0;
1221         eth->addr[4] = 0;
1222         eth->addr[5] = 0;
1223         *mask = 28;
1224         return TRUE;
1225     }
1226     /* Unsupported mask */
1227     return FALSE;
1228 }
1229
1230 /*
1231  * If "accept_mask" is FALSE, cp must point to an address that consists
1232  * of exactly 6 bytes.
1233  * If "accept_mask" is TRUE, parse an up-to-6-byte sequence with an optional
1234  * mask.
1235  */
1236 static gboolean
1237 parse_ether_address(const char *cp, ether_t *eth, unsigned int *mask,
1238         const gboolean accept_mask)
1239 {
1240     int i;
1241     unsigned long num;
1242     char *p;
1243     char sep = '\0';
1244
1245     for (i = 0; i < 6; i++) {
1246         /* Get a hex number, 1 or 2 digits, no sign characters allowed. */
1247         if (!g_ascii_isxdigit(*cp))
1248             return FALSE;
1249         num = strtoul(cp, &p, 16);
1250         if (p == cp)
1251             return FALSE; /* failed */
1252         if (num > 0xFF)
1253             return FALSE; /* not a valid octet */
1254         eth->addr[i] = (guint8) num;
1255         cp = p;     /* skip past the number */
1256
1257         /* OK, what character terminated the octet? */
1258         if (*cp == '/') {
1259             /* "/" - this has a mask. */
1260             if (!accept_mask) {
1261                 /* Entries with masks are not allowed in this file. */
1262                 return FALSE;
1263             }
1264             cp++; /* skip past the '/' to get to the mask */
1265             if (!g_ascii_isdigit(*cp))
1266                 return FALSE;   /* no sign allowed */
1267             num = strtoul(cp, &p, 10);
1268             if (p == cp)
1269                 return FALSE;   /* failed */
1270             cp = p;   /* skip past the number */
1271             if (*cp != '\0' && !g_ascii_isspace(*cp))
1272                 return FALSE;   /* bogus terminator */
1273             if (num == 0 || num >= 48)
1274                 return FALSE;   /* bogus mask */
1275             /* Mask out the bits not covered by the mask */
1276             *mask = (int)num;
1277             for (i = 0; num >= 8; i++, num -= 8)
1278                 ;   /* skip octets entirely covered by the mask */
1279             /* Mask out the first masked octet */
1280             eth->addr[i] &= (0xFF << (8 - num));
1281             i++;
1282             /* Mask out completely-masked-out octets */
1283             for (; i < 6; i++)
1284                 eth->addr[i] = 0;
1285             return TRUE;
1286         }
1287         if (*cp == '\0') {
1288             /* We're at the end of the address, and there's no mask. */
1289             if (i == 2) {
1290                 /* We got 3 bytes, so this is a manufacturer ID. */
1291                 if (!accept_mask) {
1292                     /* Manufacturer IDs are not allowed in this file */
1293                     return FALSE;
1294                 }
1295                 /* Indicate that this is a manufacturer ID (0 is not allowed
1296                    as a mask). */
1297                 *mask = 0;
1298                 return TRUE;
1299             }
1300
1301             if (i == 5) {
1302                 /* We got 6 bytes, so this is a MAC address (48 is not allowed as a mask). */
1303                 if (accept_mask)
1304                     *mask = 48;
1305                 return TRUE;
1306             }
1307
1308             /* We didn't get 3 or 6 bytes, and there's no mask; this is
1309                illegal. */
1310             return FALSE;
1311         } else {
1312             if (sep == '\0') {
1313                 /* We don't know the separator used in this number; it can either
1314                    be ':', '-', or '.'. */
1315                 if (*cp != ':' && *cp != '-' && *cp != '.')
1316                     return FALSE;
1317                 sep = *cp;  /* subsequent separators must be the same */
1318             } else {
1319                 /* It has to be the same as the first separator */
1320                 if (*cp != sep)
1321                     return FALSE;
1322             }
1323         }
1324         cp++;
1325     }
1326
1327     return TRUE;
1328 }
1329
1330 static int
1331 parse_ether_line(char *line, ether_t *eth, unsigned int *mask,
1332         const gboolean accept_mask)
1333 {
1334     /*
1335      *  See the ethers(4) or ethers(5) man page for ethers file format
1336      *  (not available on all systems).
1337      *  We allow both ethernet address separators (':' and '-'),
1338      *  as well as Wireshark's '.' separator.
1339      */
1340
1341     gchar *cp;
1342
1343     line = g_strstrip(line);
1344     if (line[0] == '\0' || line[0] == '#')
1345         return -1;
1346
1347     if ((cp = strchr(line, '#'))) {
1348         *cp = '\0';
1349         g_strchomp(line);
1350     }
1351
1352     if ((cp = strtok(line, " \t")) == NULL)
1353         return -1;
1354
1355     /* First try to match the common format for the large ethers file. */
1356     if (!parse_ether_address_fast(cp, eth, mask, accept_mask)) {
1357         /* Fallback for the well-known addresses (wka) file. */
1358         if (!parse_ether_address(cp, eth, mask, accept_mask))
1359             return -1;
1360     }
1361
1362     if ((cp = strtok(NULL, " \t")) == NULL)
1363         return -1;
1364
1365     g_strlcpy(eth->name, cp, MAXNAMELEN);
1366
1367     if ((cp = strtok(NULL, "\t")) != NULL)
1368     {
1369         g_strlcpy(eth->longname, cp, MAXNAMELEN);
1370     } else {
1371         /* Make the long name the short name */
1372         g_strlcpy(eth->longname, eth->name, MAXNAMELEN);
1373     }
1374
1375     return 0;
1376
1377 } /* parse_ether_line */
1378
1379 static FILE *eth_p = NULL;
1380
1381 static void
1382 set_ethent(char *path)
1383 {
1384     if (eth_p)
1385         rewind(eth_p);
1386     else
1387         eth_p = ws_fopen(path, "r");
1388 }
1389
1390 static void
1391 end_ethent(void)
1392 {
1393     if (eth_p) {
1394         fclose(eth_p);
1395         eth_p = NULL;
1396     }
1397 }
1398
1399 static ether_t *
1400 get_ethent(unsigned int *mask, const gboolean accept_mask)
1401 {
1402
1403     static ether_t eth;
1404     char    buf[MAX_LINELEN];
1405
1406     if (eth_p == NULL)
1407         return NULL;
1408
1409     while (fgetline(buf, sizeof(buf), eth_p) >= 0) {
1410         if (parse_ether_line(buf, &eth, mask, accept_mask) == 0) {
1411             return &eth;
1412         }
1413     }
1414
1415     return NULL;
1416
1417 } /* get_ethent */
1418
1419 static ether_t *
1420 get_ethbyaddr(const guint8 *addr)
1421 {
1422
1423     ether_t *eth;
1424
1425     set_ethent(g_pethers_path);
1426
1427     while (((eth = get_ethent(NULL, FALSE)) != NULL) && memcmp(addr, eth->addr, 6) != 0)
1428         ;
1429
1430     if (eth == NULL) {
1431         end_ethent();
1432
1433         set_ethent(g_ethers_path);
1434
1435         while (((eth = get_ethent(NULL, FALSE)) != NULL) && memcmp(addr, eth->addr, 6) != 0)
1436             ;
1437
1438         end_ethent();
1439     }
1440
1441     return eth;
1442
1443 } /* get_ethbyaddr */
1444
1445 static hashmanuf_t *
1446 manuf_hash_new_entry(const guint8 *addr, char* name, char* longname)
1447 {
1448     guint manuf_key;
1449     hashmanuf_t *manuf_value;
1450     char *endp;
1451
1452     /* manuf needs only the 3 most significant octets of the ethernet address */
1453     manuf_key = (addr[0] << 16) + (addr[1] << 8) + addr[2];
1454     manuf_value = wmem_new(wmem_epan_scope(), hashmanuf_t);
1455
1456     memcpy(manuf_value->addr, addr, 3);
1457     if (name != NULL) {
1458         g_strlcpy(manuf_value->resolved_name, name, MAXNAMELEN);
1459         manuf_value->status = HASHETHER_STATUS_RESOLVED_NAME;
1460         if (longname != NULL) {
1461             g_strlcpy(manuf_value->resolved_longname, longname, MAXNAMELEN);
1462         }
1463         else {
1464             g_strlcpy(manuf_value->resolved_longname, name, MAXNAMELEN);
1465         }
1466     }
1467     else {
1468         manuf_value->status = HASHETHER_STATUS_UNRESOLVED;
1469         manuf_value->resolved_name[0] = '\0';
1470         manuf_value->resolved_longname[0] = '\0';
1471     }
1472     /* Values returned by bytes_to_hexstr_punct() are *not* null-terminated */
1473     endp = bytes_to_hexstr_punct(manuf_value->hexaddr, addr, sizeof(manuf_value->addr), ':');
1474     *endp = '\0';
1475
1476     wmem_map_insert(manuf_hashtable, GUINT_TO_POINTER(manuf_key), manuf_value);
1477     return manuf_value;
1478 }
1479
1480 static void
1481 wka_hash_new_entry(const guint8 *addr, char* name)
1482 {
1483     guint8 *wka_key;
1484
1485     wka_key = (guint8 *)wmem_alloc(wmem_epan_scope(), 6);
1486     memcpy(wka_key, addr, 6);
1487
1488     wmem_map_insert(wka_hashtable, wka_key, wmem_strdup(wmem_epan_scope(), name));
1489 }
1490
1491 static void
1492 add_manuf_name(const guint8 *addr, unsigned int mask, gchar *name, gchar *longname)
1493 {
1494     switch (mask)
1495     {
1496     case 0:
1497         /* This is a manufacturer ID; add it to the manufacturer ID hash table */
1498         manuf_hash_new_entry(addr, name, longname);
1499         break;
1500
1501     case 48:
1502         /* This is a well-known MAC address; add it to the Ethernet hash table */
1503         add_eth_name(addr, name);
1504         break;
1505
1506     default:
1507         /* This is a range of well-known addresses; add it to the well-known-address table */
1508         wka_hash_new_entry(addr, name);
1509         break;
1510     }
1511 } /* add_manuf_name */
1512
1513 static hashmanuf_t *
1514 manuf_name_lookup(const guint8 *addr)
1515 {
1516     guint32       manuf_key;
1517     guint8       oct;
1518     hashmanuf_t  *manuf_value;
1519
1520     /* manuf needs only the 3 most significant octets of the ethernet address */
1521     manuf_key = addr[0];
1522     manuf_key = manuf_key<<8;
1523     oct = addr[1];
1524     manuf_key = manuf_key | oct;
1525     manuf_key = manuf_key<<8;
1526     oct = addr[2];
1527     manuf_key = manuf_key | oct;
1528
1529
1530     /* first try to find a "perfect match" */
1531     manuf_value = (hashmanuf_t*)wmem_map_lookup(manuf_hashtable, GUINT_TO_POINTER(manuf_key));
1532     if (manuf_value != NULL) {
1533         return manuf_value;
1534     }
1535
1536     /* Mask out the broadcast/multicast flag but not the locally
1537      * administered flag as locally administered means: not assigned
1538      * by the IEEE but the local administrator instead.
1539      * 0x01 multicast / broadcast bit
1540      * 0x02 locally administered bit */
1541     if ((manuf_key & 0x00010000) != 0) {
1542         manuf_key &= 0x00FEFFFF;
1543         manuf_value = (hashmanuf_t*)wmem_map_lookup(manuf_hashtable, GUINT_TO_POINTER(manuf_key));
1544         if (manuf_value != NULL) {
1545             return manuf_value;
1546         }
1547     }
1548
1549     /* Add the address as a hex string */
1550     return manuf_hash_new_entry(addr, NULL, NULL);
1551
1552 } /* manuf_name_lookup */
1553
1554 static gchar *
1555 wka_name_lookup(const guint8 *addr, const unsigned int mask)
1556 {
1557     guint8     masked_addr[6];
1558     guint      num;
1559     gint       i;
1560     gchar     *name;
1561
1562     if (wka_hashtable == NULL) {
1563         return NULL;
1564     }
1565     /* Get the part of the address covered by the mask. */
1566     for (i = 0, num = mask; num >= 8; i++, num -= 8)
1567         masked_addr[i] = addr[i];   /* copy octets entirely covered by the mask */
1568     /* Mask out the first masked octet */
1569     masked_addr[i] = addr[i] & (0xFF << (8 - num));
1570     i++;
1571     /* Zero out completely-masked-out octets */
1572     for (; i < 6; i++)
1573         masked_addr[i] = 0;
1574
1575     name = (gchar *)wmem_map_lookup(wka_hashtable, masked_addr);
1576
1577     return name;
1578
1579 } /* wka_name_lookup */
1580
1581
1582 guint get_hash_ether_status(hashether_t* ether)
1583 {
1584     return ether->status;
1585 }
1586
1587 char* get_hash_ether_hexaddr(hashether_t* ether)
1588 {
1589     return ether->hexaddr;
1590 }
1591
1592 char* get_hash_ether_resolved_name(hashether_t* ether)
1593 {
1594     return ether->resolved_name;
1595 }
1596
1597 static guint
1598 eth_addr_hash(gconstpointer key)
1599 {
1600     return wmem_strong_hash((const guint8 *)key, 6);
1601 }
1602
1603 static gboolean
1604 eth_addr_cmp(gconstpointer a, gconstpointer b)
1605 {
1606     return (memcmp(a, b, 6) == 0);
1607 }
1608
1609 static void
1610 initialize_ethers(void)
1611 {
1612     ether_t *eth;
1613     guint    mask = 0;
1614
1615     /* hash table initialization */
1616     wka_hashtable   = wmem_map_new(wmem_epan_scope(), eth_addr_hash, eth_addr_cmp);
1617     manuf_hashtable = wmem_map_new(wmem_epan_scope(), g_direct_hash, g_direct_equal);
1618     eth_hashtable   = wmem_map_new(wmem_epan_scope(), eth_addr_hash, eth_addr_cmp);
1619
1620     /* Compute the pathname of the ethers file. */
1621     if (g_ethers_path == NULL) {
1622         g_ethers_path = g_build_filename(get_systemfile_dir(), ENAME_ETHERS, NULL);
1623     }
1624
1625     /* Set g_pethers_path here, but don't actually do anything
1626      * with it. It's used in get_ethbyaddr().
1627      */
1628     if (g_pethers_path == NULL)
1629         g_pethers_path = get_persconffile_path(ENAME_ETHERS, FALSE);
1630
1631     /* Compute the pathname of the manuf file */
1632     if (g_manuf_path == NULL)
1633         g_manuf_path = get_datafile_path(ENAME_MANUF);
1634
1635     /* Read it and initialize the hash table */
1636     set_ethent(g_manuf_path);
1637     while ((eth = get_ethent(&mask, TRUE))) {
1638         add_manuf_name(eth->addr, mask, eth->name, eth->longname);
1639     }
1640     end_ethent();
1641
1642     /* Compute the pathname of the wka file */
1643     if (g_wka_path == NULL)
1644         g_wka_path = get_datafile_path(ENAME_WKA);
1645
1646     /* Read it and initialize the hash table */
1647     set_ethent(g_wka_path);
1648     while ((eth = get_ethent(&mask, TRUE))) {
1649         add_manuf_name(eth->addr, mask, eth->name, eth->longname);
1650     }
1651     end_ethent();
1652
1653 } /* initialize_ethers */
1654
1655 static void
1656 ethers_cleanup(void)
1657 {
1658     g_free(g_ethers_path);
1659     g_ethers_path = NULL;
1660     g_free(g_pethers_path);
1661     g_pethers_path = NULL;
1662     g_free(g_manuf_path);
1663     g_manuf_path = NULL;
1664     g_free(g_wka_path);
1665     g_wka_path = NULL;
1666 }
1667
1668 /* Resolve ethernet address */
1669 static hashether_t *
1670 eth_addr_resolve(hashether_t *tp) {
1671     ether_t      *eth;
1672     hashmanuf_t *manuf_value;
1673     const guint8 *addr = tp->addr;
1674
1675     if ( (eth = get_ethbyaddr(addr)) != NULL) {
1676         g_strlcpy(tp->resolved_name, eth->name, MAXNAMELEN);
1677         tp->status = HASHETHER_STATUS_RESOLVED_NAME;
1678         return tp;
1679     } else {
1680         guint         mask;
1681         gchar        *name;
1682         address       ether_addr;
1683
1684         /* Unknown name.  Try looking for it in the well-known-address
1685            tables for well-known address ranges smaller than 2^24. */
1686         mask = 7;
1687         do {
1688             /* Only the topmost 5 bytes participate fully */
1689             if ((name = wka_name_lookup(addr, mask+40)) != NULL) {
1690                 g_snprintf(tp->resolved_name, MAXNAMELEN, "%s_%02x",
1691                         name, addr[5] & (0xFF >> mask));
1692                 tp->status = HASHETHER_STATUS_RESOLVED_DUMMY;
1693                 return tp;
1694             }
1695         } while (mask--);
1696
1697         mask = 7;
1698         do {
1699             /* Only the topmost 4 bytes participate fully */
1700             if ((name = wka_name_lookup(addr, mask+32)) != NULL) {
1701                 g_snprintf(tp->resolved_name, MAXNAMELEN, "%s_%02x:%02x",
1702                         name, addr[4] & (0xFF >> mask), addr[5]);
1703                 tp->status = HASHETHER_STATUS_RESOLVED_DUMMY;
1704                 return tp;
1705             }
1706         } while (mask--);
1707
1708         mask = 7;
1709         do {
1710             /* Only the topmost 3 bytes participate fully */
1711             if ((name = wka_name_lookup(addr, mask+24)) != NULL) {
1712                 g_snprintf(tp->resolved_name, MAXNAMELEN, "%s_%02x:%02x:%02x",
1713                         name, addr[3] & (0xFF >> mask), addr[4], addr[5]);
1714                 tp->status = HASHETHER_STATUS_RESOLVED_DUMMY;
1715                 return tp;
1716             }
1717         } while (mask--);
1718
1719         /* Now try looking in the manufacturer table. */
1720         manuf_value = manuf_name_lookup(addr);
1721         if ((manuf_value != NULL) && (manuf_value->status != HASHETHER_STATUS_UNRESOLVED)) {
1722             g_snprintf(tp->resolved_name, MAXNAMELEN, "%s_%02x:%02x:%02x",
1723                     manuf_value->resolved_name, addr[3], addr[4], addr[5]);
1724             tp->status = HASHETHER_STATUS_RESOLVED_DUMMY;
1725             return tp;
1726         }
1727
1728         /* Now try looking for it in the well-known-address
1729            tables for well-known address ranges larger than 2^24. */
1730         mask = 7;
1731         do {
1732             /* Only the topmost 2 bytes participate fully */
1733             if ((name = wka_name_lookup(addr, mask+16)) != NULL) {
1734                 g_snprintf(tp->resolved_name, MAXNAMELEN, "%s_%02x:%02x:%02x:%02x",
1735                         name, addr[2] & (0xFF >> mask), addr[3], addr[4],
1736                         addr[5]);
1737                 tp->status = HASHETHER_STATUS_RESOLVED_DUMMY;
1738                 return tp;
1739             }
1740         } while (mask--);
1741
1742         mask = 7;
1743         do {
1744             /* Only the topmost byte participates fully */
1745             if ((name = wka_name_lookup(addr, mask+8)) != NULL) {
1746                 g_snprintf(tp->resolved_name, MAXNAMELEN, "%s_%02x:%02x:%02x:%02x:%02x",
1747                         name, addr[1] & (0xFF >> mask), addr[2], addr[3],
1748                         addr[4], addr[5]);
1749                 tp->status = HASHETHER_STATUS_RESOLVED_DUMMY;
1750                 return tp;
1751             }
1752         } while (mask--);
1753
1754         mask = 7;
1755         do {
1756             /* Not even the topmost byte participates fully */
1757             if ((name = wka_name_lookup(addr, mask)) != NULL) {
1758                 g_snprintf(tp->resolved_name, MAXNAMELEN, "%s_%02x:%02x:%02x:%02x:%02x:%02x",
1759                         name, addr[0] & (0xFF >> mask), addr[1], addr[2],
1760                         addr[3], addr[4], addr[5]);
1761                 tp->status = HASHETHER_STATUS_RESOLVED_DUMMY;
1762                 return tp;
1763             }
1764         } while (--mask); /* Work down to the last bit */
1765
1766         /* No match whatsoever. */
1767         set_address(&ether_addr, AT_ETHER, 6, addr);
1768         address_to_str_buf(&ether_addr, tp->resolved_name, MAXNAMELEN);
1769         tp->status = HASHETHER_STATUS_RESOLVED_DUMMY;
1770         return tp;
1771     }
1772     g_assert_not_reached();
1773 } /* eth_addr_resolve */
1774
1775 static hashether_t *
1776 eth_hash_new_entry(const guint8 *addr, const gboolean resolve)
1777 {
1778     hashether_t *tp;
1779     char *endp;
1780
1781     tp = wmem_new(wmem_epan_scope(), hashether_t);
1782     memcpy(tp->addr, addr, sizeof(tp->addr));
1783     tp->status = HASHETHER_STATUS_UNRESOLVED;
1784     /* Values returned by bytes_to_hexstr_punct() are *not* null-terminated */
1785     endp = bytes_to_hexstr_punct(tp->hexaddr, addr, sizeof(tp->addr), ':');
1786     *endp = '\0';
1787     tp->resolved_name[0] = '\0';
1788
1789     if (resolve)
1790         eth_addr_resolve(tp);
1791
1792     wmem_map_insert(eth_hashtable, tp->addr, tp);
1793
1794     return tp;
1795 } /* eth_hash_new_entry */
1796
1797 static hashether_t *
1798 add_eth_name(const guint8 *addr, const gchar *name)
1799 {
1800     hashether_t *tp;
1801
1802     tp = (hashether_t *)wmem_map_lookup(eth_hashtable, addr);
1803
1804     if (tp == NULL) {
1805         tp = eth_hash_new_entry(addr, FALSE);
1806     }
1807
1808     if (strcmp(tp->resolved_name, name) != 0) {
1809         g_strlcpy(tp->resolved_name, name, MAXNAMELEN);
1810         tp->status = HASHETHER_STATUS_RESOLVED_NAME;
1811         new_resolved_objects = TRUE;
1812     }
1813
1814     return tp;
1815 } /* add_eth_name */
1816
1817 static hashether_t *
1818 eth_name_lookup(const guint8 *addr, const gboolean resolve)
1819 {
1820     hashether_t  *tp;
1821
1822     tp = (hashether_t *)wmem_map_lookup(eth_hashtable, addr);
1823
1824     if (tp == NULL) {
1825         tp = eth_hash_new_entry(addr, resolve);
1826     } else {
1827         if (resolve && (tp->status == HASHETHER_STATUS_UNRESOLVED)) {
1828             eth_addr_resolve(tp); /* Found but needs to be resolved */
1829         }
1830     }
1831
1832     return tp;
1833
1834 } /* eth_name_lookup */
1835
1836
1837 /* IPXNETS */
1838 static int
1839 parse_ipxnets_line(char *line, ipxnet_t *ipxnet)
1840 {
1841     /*
1842      *  We allow three address separators (':', '-', and '.'),
1843      *  as well as no separators
1844      */
1845
1846     gchar     *cp;
1847     guint32   a, a0, a1, a2, a3;
1848     gboolean  found_single_number = FALSE;
1849
1850     if ((cp = strchr(line, '#')))
1851         *cp = '\0';
1852
1853     if ((cp = strtok(line, " \t\n")) == NULL)
1854         return -1;
1855
1856     /* Either fill a0,a1,a2,a3 and found_single_number is FALSE,
1857      * fill a and found_single_number is TRUE,
1858      * or return -1
1859      */
1860     if (sscanf(cp, "%x:%x:%x:%x", &a0, &a1, &a2, &a3) != 4) {
1861         if (sscanf(cp, "%x-%x-%x-%x", &a0, &a1, &a2, &a3) != 4) {
1862             if (sscanf(cp, "%x.%x.%x.%x", &a0, &a1, &a2, &a3) != 4) {
1863                 if (sscanf(cp, "%x", &a) == 1) {
1864                     found_single_number = TRUE;
1865                 }
1866                 else {
1867                     return -1;
1868                 }
1869             }
1870         }
1871     }
1872
1873     if ((cp = strtok(NULL, " \t\n")) == NULL)
1874         return -1;
1875
1876     if (found_single_number) {
1877         ipxnet->addr = a;
1878     }
1879     else {
1880         ipxnet->addr = (a0 << 24) | (a1 << 16) | (a2 << 8) | a3;
1881     }
1882
1883     g_strlcpy(ipxnet->name, cp, MAXNAMELEN);
1884
1885     return 0;
1886
1887 } /* parse_ipxnets_line */
1888
1889 static FILE *ipxnet_p = NULL;
1890
1891 static void
1892 set_ipxnetent(char *path)
1893 {
1894     if (ipxnet_p)
1895         rewind(ipxnet_p);
1896     else
1897         ipxnet_p = ws_fopen(path, "r");
1898 }
1899
1900 static void
1901 end_ipxnetent(void)
1902 {
1903     if (ipxnet_p) {
1904         fclose(ipxnet_p);
1905         ipxnet_p = NULL;
1906     }
1907 }
1908
1909 static ipxnet_t *
1910 get_ipxnetent(void)
1911 {
1912
1913     static ipxnet_t ipxnet;
1914     char    buf[MAX_LINELEN];
1915
1916     if (ipxnet_p == NULL)
1917         return NULL;
1918
1919     while (fgetline(buf, sizeof(buf), ipxnet_p) >= 0) {
1920         if (parse_ipxnets_line(buf, &ipxnet) == 0) {
1921             return &ipxnet;
1922         }
1923     }
1924
1925     return NULL;
1926
1927 } /* get_ipxnetent */
1928
1929 static ipxnet_t *
1930 get_ipxnetbyaddr(guint32 addr)
1931 {
1932     ipxnet_t *ipxnet;
1933
1934     set_ipxnetent(g_ipxnets_path);
1935
1936     while (((ipxnet = get_ipxnetent()) != NULL) && (addr != ipxnet->addr) ) ;
1937
1938     if (ipxnet == NULL) {
1939         end_ipxnetent();
1940
1941         set_ipxnetent(g_pipxnets_path);
1942
1943         while (((ipxnet = get_ipxnetent()) != NULL) && (addr != ipxnet->addr) )
1944             ;
1945
1946         end_ipxnetent();
1947     }
1948
1949     return ipxnet;
1950
1951 } /* get_ipxnetbyaddr */
1952
1953 static void
1954 initialize_ipxnets(void)
1955 {
1956     /* Compute the pathname of the ipxnets file.
1957      *
1958      * XXX - is there a notion of an "ipxnets file" in any flavor of
1959      * UNIX, or with any add-on Netware package for UNIX?  If not,
1960      * should the UNIX version of the ipxnets file be in the datafile
1961      * directory as well?
1962      */
1963     if (g_ipxnets_path == NULL) {
1964         g_ipxnets_path = wmem_strdup_printf(wmem_epan_scope(), "%s" G_DIR_SEPARATOR_S "%s",
1965                 get_systemfile_dir(), ENAME_IPXNETS);
1966     }
1967
1968     /* Set g_pipxnets_path here, but don't actually do anything
1969      * with it. It's used in get_ipxnetbyaddr().
1970      */
1971     if (g_pipxnets_path == NULL)
1972         g_pipxnets_path = get_persconffile_path(ENAME_IPXNETS, FALSE);
1973
1974 } /* initialize_ipxnets */
1975
1976 static void
1977 ipx_name_lookup_cleanup(void)
1978 {
1979     ipxnet_hash_table = NULL;
1980     g_free(g_pipxnets_path);
1981     g_pipxnets_path = NULL;
1982 }
1983
1984 static gchar *
1985 ipxnet_name_lookup(wmem_allocator_t *allocator, const guint addr)
1986 {
1987     hashipxnet_t *tp;
1988     ipxnet_t *ipxnet;
1989
1990     tp = (hashipxnet_t *)wmem_map_lookup(ipxnet_hash_table, GUINT_TO_POINTER(addr));
1991     if (tp == NULL) {
1992         tp = wmem_new(wmem_epan_scope(), hashipxnet_t);
1993         wmem_map_insert(ipxnet_hash_table, GUINT_TO_POINTER(addr), tp);
1994     } else {
1995         return wmem_strdup(allocator, tp->name);
1996     }
1997
1998     /* fill in a new entry */
1999
2000     tp->addr = addr;
2001
2002     if ( (ipxnet = get_ipxnetbyaddr(addr)) == NULL) {
2003         /* unknown name */
2004         g_snprintf(tp->name, MAXNAMELEN, "%X", addr);
2005
2006     } else {
2007         g_strlcpy(tp->name, ipxnet->name, MAXNAMELEN);
2008     }
2009
2010     return wmem_strdup(allocator, tp->name);
2011
2012 } /* ipxnet_name_lookup */
2013
2014 /* VLANS */
2015 static int
2016 parse_vlan_line(char *line, vlan_t *vlan)
2017 {
2018     gchar     *cp;
2019     guint16   id;
2020
2021     if ((cp = strchr(line, '#')))
2022         *cp = '\0';
2023
2024     if ((cp = strtok(line, " \t\n")) == NULL)
2025         return -1;
2026
2027     if (sscanf(cp, "%" G_GUINT16_FORMAT, &id) == 1) {
2028         vlan->id = id;
2029     }
2030     else {
2031         return -1;
2032     }
2033
2034     if ((cp = strtok(NULL, "\t\n")) == NULL)
2035         return -1;
2036
2037     g_strlcpy(vlan->name, cp, MAXVLANNAMELEN);
2038
2039     return 0;
2040
2041 } /* parse_vlan_line */
2042
2043 static FILE *vlan_p = NULL;
2044
2045 static void
2046 set_vlanent(char *path)
2047 {
2048     if (vlan_p)
2049         rewind(vlan_p);
2050     else
2051         vlan_p = ws_fopen(path, "r");
2052 }
2053
2054 static void
2055 end_vlanent(void)
2056 {
2057     if (vlan_p) {
2058         fclose(vlan_p);
2059         vlan_p = NULL;
2060     }
2061 }
2062
2063 static vlan_t *
2064 get_vlanent(void)
2065 {
2066
2067     static vlan_t vlan;
2068     char    buf[MAX_LINELEN];
2069
2070     if (vlan_p == NULL)
2071         return NULL;
2072
2073     while (fgetline(buf, sizeof(buf), vlan_p) >= 0) {
2074         if (parse_vlan_line(buf, &vlan) == 0) {
2075             return &vlan;
2076         }
2077     }
2078
2079     return NULL;
2080
2081 } /* get_vlanent */
2082
2083 static vlan_t *
2084 get_vlannamebyid(guint16 id)
2085 {
2086     vlan_t *vlan;
2087
2088     set_vlanent(g_pvlan_path);
2089
2090     while (((vlan = get_vlanent()) != NULL) && (id != vlan->id) ) ;
2091
2092     if (vlan == NULL) {
2093         end_vlanent();
2094
2095     }
2096
2097     return vlan;
2098
2099 } /* get_vlannamebyid */
2100
2101 static void
2102 initialize_vlans(void)
2103 {
2104     g_assert(vlan_hash_table == NULL);
2105     vlan_hash_table = wmem_map_new(wmem_epan_scope(), g_direct_hash, g_direct_equal);
2106
2107     /* Set g_pvlan_path here, but don't actually do anything
2108      * with it. It's used in get_vlannamebyid()
2109      */
2110     if (g_pvlan_path == NULL)
2111         g_pvlan_path = get_persconffile_path(ENAME_VLANS, FALSE);
2112
2113 } /* initialize_vlans */
2114
2115 static void
2116 vlan_name_lookup_cleanup(void)
2117 {
2118     vlan_hash_table = NULL;
2119     g_free(g_pvlan_path);
2120     g_pvlan_path = NULL;
2121 }
2122
2123 static const gchar *
2124 vlan_name_lookup(const guint id)
2125 {
2126     hashvlan_t *tp;
2127     vlan_t *vlan;
2128
2129     tp = (hashvlan_t *)wmem_map_lookup(vlan_hash_table, GUINT_TO_POINTER(id));
2130     if (tp == NULL) {
2131         tp = wmem_new(wmem_epan_scope(), hashvlan_t);
2132         wmem_map_insert(vlan_hash_table, GUINT_TO_POINTER(id), tp);
2133     } else {
2134         return tp->name;
2135     }
2136
2137     /* fill in a new entry */
2138
2139     tp->id = id;
2140
2141     if ( (vlan = get_vlannamebyid(id)) == NULL) {
2142         /* unknown name */
2143         g_snprintf(tp->name, MAXVLANNAMELEN, "<%u>", id);
2144
2145     } else {
2146         g_strlcpy(tp->name, vlan->name, MAXVLANNAMELEN);
2147     }
2148
2149     return tp->name;
2150
2151 } /* vlan_name_lookup */
2152 /* VLAN END */
2153
2154 static gboolean
2155 read_hosts_file (const char *hostspath, gboolean store_entries)
2156 {
2157     FILE *hf;
2158     char line[MAX_LINELEN];
2159     gchar *cp;
2160     union {
2161         guint32 ip4_addr;
2162         ws_in6_addr ip6_addr;
2163     } host_addr;
2164     gboolean is_ipv6, entry_found = FALSE;
2165
2166     /*
2167      *  See the hosts(4) or hosts(5) man page for hosts file format
2168      *  (not available on all systems).
2169      */
2170     if ((hf = ws_fopen(hostspath, "r")) == NULL)
2171         return FALSE;
2172
2173     while (fgetline(line, sizeof(line), hf) >= 0) {
2174         if ((cp = strchr(line, '#')))
2175             *cp = '\0';
2176
2177         if ((cp = strtok(line, " \t")) == NULL)
2178             continue; /* no tokens in the line */
2179
2180         if (ws_inet_pton6(cp, &host_addr.ip6_addr)) {
2181             /* Valid IPv6 */
2182             is_ipv6 = TRUE;
2183         } else if (ws_inet_pton4(cp, &host_addr.ip4_addr)) {
2184             /* Valid IPv4 */
2185             is_ipv6 = FALSE;
2186         } else {
2187             continue;
2188         }
2189
2190         if ((cp = strtok(NULL, " \t")) == NULL)
2191             continue; /* no host name */
2192
2193         entry_found = TRUE;
2194         if (store_entries) {
2195             if (is_ipv6) {
2196                 add_ipv6_name(&host_addr.ip6_addr, cp);
2197             } else {
2198                 add_ipv4_name(host_addr.ip4_addr, cp);
2199             }
2200         }
2201     }
2202
2203     fclose(hf);
2204     return entry_found ? TRUE : FALSE;
2205 } /* read_hosts_file */
2206
2207 gboolean
2208 add_hosts_file (const char *hosts_file)
2209 {
2210     gboolean found = FALSE;
2211     guint i;
2212
2213     if (!hosts_file)
2214         return FALSE;
2215
2216     if (!extra_hosts_files)
2217         extra_hosts_files = g_ptr_array_new();
2218
2219     for (i = 0; i < extra_hosts_files->len; i++) {
2220         if (strcmp(hosts_file, (const char *) g_ptr_array_index(extra_hosts_files, i)) == 0)
2221             found = TRUE;
2222     }
2223
2224     if (!found) {
2225         g_ptr_array_add(extra_hosts_files, wmem_strdup(wmem_epan_scope(), hosts_file));
2226         return read_hosts_file (hosts_file, FALSE);
2227     }
2228     return TRUE;
2229 }
2230
2231 gboolean
2232 add_ip_name_from_string (const char *addr, const char *name)
2233 {
2234     union {
2235         guint32 ip4_addr;
2236         ws_in6_addr ip6_addr;
2237     } host_addr;
2238     gboolean is_ipv6;
2239     resolved_ipv4_t *resolved_ipv4_entry;
2240     resolved_ipv6_t *resolved_ipv6_entry;
2241
2242     if (ws_inet_pton6(addr, &host_addr.ip6_addr)) {
2243         is_ipv6 = TRUE;
2244     } else if (ws_inet_pton4(addr, &host_addr.ip4_addr)) {
2245         is_ipv6 = FALSE;
2246     } else {
2247         return FALSE;
2248     }
2249
2250     if (is_ipv6) {
2251         resolved_ipv6_entry = wmem_new(wmem_epan_scope(), resolved_ipv6_t);
2252         memcpy(&(resolved_ipv6_entry->ip6_addr), &host_addr.ip6_addr, 16);
2253         g_strlcpy(resolved_ipv6_entry->name, name, MAXNAMELEN);
2254         wmem_list_prepend(manually_resolved_ipv6_list, resolved_ipv6_entry);
2255     } else {
2256         resolved_ipv4_entry = wmem_new(wmem_epan_scope(), resolved_ipv4_t);
2257         resolved_ipv4_entry->host_addr = host_addr.ip4_addr;
2258         g_strlcpy(resolved_ipv4_entry->name, name, MAXNAMELEN);
2259         wmem_list_prepend(manually_resolved_ipv4_list, resolved_ipv4_entry);
2260     }
2261
2262     return TRUE;
2263 } /* add_ip_name_from_string */
2264
2265 /*
2266  * Add the resolved addresses that are in use to the list used to create the NRB
2267  */
2268 static void
2269 ipv4_hash_table_resolved_to_list(gpointer key _U_, gpointer value, gpointer user_data)
2270 {
2271     addrinfo_lists_t *lists = (addrinfo_lists_t*)user_data;
2272     hashipv4_t *ipv4_hash_table_entry = (hashipv4_t *)value;
2273
2274     if ((ipv4_hash_table_entry->flags & USED_AND_RESOLVED_MASK) == USED_AND_RESOLVED_MASK) {
2275         lists->ipv4_addr_list = g_list_prepend(lists->ipv4_addr_list, ipv4_hash_table_entry);
2276     }
2277
2278 }
2279
2280 /*
2281  * Add the resolved addresses that are in use to the list used to create the NRB
2282  */
2283
2284 static void
2285 ipv6_hash_table_resolved_to_list(gpointer key _U_, gpointer value, gpointer user_data)
2286 {
2287     addrinfo_lists_t *lists = (addrinfo_lists_t*)user_data;
2288     hashipv6_t *ipv6_hash_table_entry = (hashipv6_t *)value;
2289
2290     if ((ipv6_hash_table_entry->flags & USED_AND_RESOLVED_MASK) == USED_AND_RESOLVED_MASK) {
2291         lists->ipv6_addr_list = g_list_prepend (lists->ipv6_addr_list, ipv6_hash_table_entry);
2292     }
2293
2294 }
2295
2296 addrinfo_lists_t *
2297 get_addrinfo_list(void)
2298 {
2299     if (ipv4_hash_table) {
2300         wmem_map_foreach(ipv4_hash_table, ipv4_hash_table_resolved_to_list, &addrinfo_lists);
2301     }
2302
2303     if (ipv6_hash_table) {
2304         wmem_map_foreach(ipv6_hash_table, ipv6_hash_table_resolved_to_list, &addrinfo_lists);
2305     }
2306
2307     return &addrinfo_lists;
2308 }
2309
2310 /* Read in a list of subnet definition - name pairs.
2311  * <line> = <comment> | <entry> | <whitespace>
2312  * <comment> = <whitespace>#<any>
2313  * <entry> = <subnet_definition> <whitespace> <subnet_name> [<comment>|<whitespace><any>]
2314  * <subnet_definition> = <ipv4_address> / <subnet_mask_length>
2315  * <ipv4_address> is a full address; it will be masked to get the subnet-ID.
2316  * <subnet_mask_length> is a decimal 1-31
2317  * <subnet_name> is a string containing no whitespace.
2318  * <whitespace> = (space | tab)+
2319  * Any malformed entries are ignored.
2320  * Any trailing data after the subnet_name is ignored.
2321  *
2322  * XXX Support IPv6
2323  */
2324 static gboolean
2325 read_subnets_file (const char *subnetspath)
2326 {
2327     FILE *hf;
2328     char line[MAX_LINELEN];
2329     gchar *cp, *cp2;
2330     guint32 host_addr; /* IPv4 ONLY */
2331     guint8 mask_length;
2332
2333     if ((hf = ws_fopen(subnetspath, "r")) == NULL)
2334         return FALSE;
2335
2336     while (fgetline(line, sizeof(line), hf) >= 0) {
2337         if ((cp = strchr(line, '#')))
2338             *cp = '\0';
2339
2340         if ((cp = strtok(line, " \t")) == NULL)
2341             continue; /* no tokens in the line */
2342
2343
2344         /* Expected format is <IP4 address>/<subnet length> */
2345         cp2 = strchr(cp, '/');
2346         if (NULL == cp2) {
2347             /* No length */
2348             continue;
2349         }
2350         *cp2 = '\0'; /* Cut token */
2351         ++cp2    ;
2352
2353         /* Check if this is a valid IPv4 address */
2354         if (!str_to_ip(cp, &host_addr)) {
2355             continue; /* no */
2356         }
2357
2358         if (!ws_strtou8(cp2, NULL, &mask_length) || mask_length == 0 || mask_length > 32) {
2359             continue; /* invalid mask length */
2360         }
2361
2362         if ((cp = strtok(NULL, " \t")) == NULL)
2363             continue; /* no subnet name */
2364
2365         subnet_entry_set(host_addr, mask_length, cp);
2366     }
2367
2368     fclose(hf);
2369     return TRUE;
2370 } /* read_subnets_file */
2371
2372 static subnet_entry_t
2373 subnet_lookup(const guint32 addr)
2374 {
2375     subnet_entry_t subnet_entry;
2376     guint32 i;
2377
2378     /* Search mask lengths linearly, longest first */
2379
2380     i = SUBNETLENGTHSIZE;
2381     while(have_subnet_entry && i > 0) {
2382         guint32 masked_addr;
2383         subnet_length_entry_t* length_entry;
2384
2385         /* Note that we run from 31 (length 32)  to 0 (length 1)  */
2386         --i;
2387         g_assert(i < SUBNETLENGTHSIZE);
2388
2389
2390         length_entry = &subnet_length_entries[i];
2391
2392         if (NULL != length_entry->subnet_addresses) {
2393             sub_net_hashipv4_t * tp;
2394             guint32 hash_idx;
2395
2396             masked_addr = addr & length_entry->mask;
2397             hash_idx = HASH_IPV4_ADDRESS(masked_addr);
2398
2399             tp = length_entry->subnet_addresses[hash_idx];
2400             while(tp != NULL && tp->addr != masked_addr) {
2401                 tp = tp->next;
2402             }
2403
2404             if (NULL != tp) {
2405                 subnet_entry.mask = length_entry->mask;
2406                 subnet_entry.mask_length = i + 1; /* Length is offset + 1 */
2407                 subnet_entry.name = tp->name;
2408                 return subnet_entry;
2409             }
2410         }
2411     }
2412
2413     subnet_entry.mask = 0;
2414     subnet_entry.mask_length = 0;
2415     subnet_entry.name = NULL;
2416
2417     return subnet_entry;
2418 }
2419
2420 /* Add a subnet-definition - name pair to the set.
2421  * The definition is taken by masking the address passed in with the mask of the
2422  * given length.
2423  */
2424 static void
2425 subnet_entry_set(guint32 subnet_addr, const guint8 mask_length, const gchar* name)
2426 {
2427     subnet_length_entry_t* entry;
2428     sub_net_hashipv4_t * tp;
2429     gsize hash_idx;
2430
2431     g_assert(mask_length > 0 && mask_length <= 32);
2432
2433     entry = &subnet_length_entries[mask_length - 1];
2434
2435     subnet_addr &= entry->mask;
2436
2437     hash_idx = HASH_IPV4_ADDRESS(subnet_addr);
2438
2439     if (NULL == entry->subnet_addresses) {
2440         entry->subnet_addresses = (sub_net_hashipv4_t**)wmem_alloc0(wmem_epan_scope(), sizeof(sub_net_hashipv4_t*) * HASHHOSTSIZE);
2441     }
2442
2443     if (NULL != (tp = entry->subnet_addresses[hash_idx])) {
2444         sub_net_hashipv4_t * new_tp;
2445
2446         while (tp->next) {
2447             if (tp->addr == subnet_addr) {
2448                 return; /* XXX provide warning that an address was repeated? */
2449             } else {
2450                 tp = tp->next;
2451             }
2452         }
2453
2454         new_tp = wmem_new(wmem_epan_scope(), sub_net_hashipv4_t);
2455         tp->next = new_tp;
2456         tp = new_tp;
2457     } else {
2458         tp = entry->subnet_addresses[hash_idx] = wmem_new(wmem_epan_scope(), sub_net_hashipv4_t);
2459     }
2460
2461     tp->next = NULL;
2462     tp->addr = subnet_addr;
2463     g_strlcpy(tp->name, name, MAXNAMELEN); /* This is longer than subnet names can actually be */
2464     have_subnet_entry = TRUE;
2465 }
2466
2467 static void
2468 subnet_name_lookup_init(void)
2469 {
2470     gchar* subnetspath;
2471     guint32 i;
2472
2473     for(i = 0; i < SUBNETLENGTHSIZE; ++i) {
2474         guint32 length = i + 1;
2475
2476         subnet_length_entries[i].subnet_addresses  = NULL;
2477         subnet_length_entries[i].mask_length  = length;
2478         subnet_length_entries[i].mask = g_htonl(ip_get_subnet_mask(length));
2479     }
2480
2481     /* Check profile directory before personal configuration */
2482     subnetspath = get_persconffile_path(ENAME_SUBNETS, TRUE);
2483     if (!read_subnets_file(subnetspath)) {
2484         if (errno != ENOENT) {
2485             report_open_failure(subnetspath, errno, FALSE);
2486         }
2487
2488         g_free(subnetspath);
2489         subnetspath = get_persconffile_path(ENAME_SUBNETS, FALSE);
2490         if (!read_subnets_file(subnetspath) && errno != ENOENT) {
2491             report_open_failure(subnetspath, errno, FALSE);
2492         }
2493     }
2494     g_free(subnetspath);
2495
2496     /*
2497      * Load the global subnets file, if we have one.
2498      */
2499     subnetspath = get_datafile_path(ENAME_SUBNETS);
2500     if (!read_subnets_file(subnetspath) && errno != ENOENT) {
2501         report_open_failure(subnetspath, errno, FALSE);
2502     }
2503     g_free(subnetspath);
2504 }
2505
2506 /* SS7 PC Name Resolution Portion */
2507 static hashss7pc_t *
2508 new_ss7pc(const guint8 ni, const guint32 pc)
2509 {
2510     hashss7pc_t *tp = wmem_new(wmem_epan_scope(), hashss7pc_t);
2511     tp->id = (ni<<24) + (pc&0xffffff);
2512     tp->pc_addr[0] = '\0';
2513     tp->name[0] = '\0';
2514
2515     return tp;
2516 }
2517
2518 static hashss7pc_t *
2519 host_lookup_ss7pc(const guint8 ni, const guint32 pc)
2520 {
2521     hashss7pc_t * volatile tp;
2522     guint32 id;
2523
2524     id = (ni<<24) + (pc&0xffffff);
2525
2526     tp = (hashss7pc_t *)wmem_map_lookup(ss7pc_hash_table, GUINT_TO_POINTER(id));
2527     if (tp == NULL) {
2528         tp = new_ss7pc(ni, pc);
2529         wmem_map_insert(ss7pc_hash_table, GUINT_TO_POINTER(id), tp);
2530     }
2531
2532     return tp;
2533 }
2534
2535 void fill_unresolved_ss7pc(const gchar * pc_addr, const guint8 ni, const guint32 pc)
2536 {
2537     hashss7pc_t *tp = host_lookup_ss7pc(ni, pc);
2538
2539     g_strlcpy(tp->pc_addr, pc_addr, MAXNAMELEN);
2540 }
2541
2542 const gchar *
2543 get_hostname_ss7pc(const guint8 ni, const guint32 pc)
2544 {
2545     hashss7pc_t *tp = host_lookup_ss7pc(ni, pc);
2546
2547     /* never resolved yet*/
2548     if (tp->pc_addr[0] == '\0')
2549         return tp->pc_addr;
2550
2551     /* Don't have name in file */
2552     if (tp->name[0] == '\0')
2553         return tp->pc_addr;
2554
2555     if (!gbl_resolv_flags.ss7pc_name)
2556         return tp->pc_addr;
2557
2558     return tp->name;
2559 }
2560
2561 static void
2562 add_ss7pc_name(const guint8 ni, guint32 pc, const gchar *name)
2563 {
2564     hashss7pc_t *tp;
2565     guint32 id;
2566
2567     if (!name || name[0] == '\0')
2568         return;
2569
2570     id = (ni<<24) + (pc&0xffffff);
2571     tp = (hashss7pc_t *)wmem_map_lookup(ss7pc_hash_table, GUINT_TO_POINTER(id));
2572     if (!tp) {
2573         tp = new_ss7pc(ni, pc);
2574         wmem_map_insert(ss7pc_hash_table, GUINT_TO_POINTER(id), tp);
2575     }
2576
2577     if (g_ascii_strcasecmp(tp->name, name)) {
2578         g_strlcpy(tp->name, name, MAXNAMELEN);
2579     }
2580 }
2581
2582 static gboolean
2583 read_ss7pcs_file(const char *ss7pcspath)
2584 {
2585     FILE *hf;
2586     char line[MAX_LINELEN];
2587     gchar *cp;
2588     guint8 ni;
2589     guint32 pc;
2590     gboolean entry_found = FALSE;
2591
2592     /*
2593     *  File format is Network Indicator (decimal)<dash>Point Code (Decimal)<tab/space>Hostname
2594     */
2595     if ((hf = ws_fopen(ss7pcspath, "r")) == NULL)
2596         return FALSE;
2597
2598     while (fgetline(line, sizeof(line), hf) >= 0) {
2599         if ((cp = strchr(line, '#')))
2600             *cp = '\0';
2601
2602         if ((cp = strtok(line, "-")) == NULL)
2603             continue; /*no ni-pc separator*/
2604         if (!ws_strtou8(cp, NULL, &ni))
2605             continue;
2606         if (ni > 3)
2607              continue;
2608
2609         if ((cp = strtok(NULL, " \t")) == NULL)
2610             continue; /* no tokens for pc and name */
2611         if (!ws_strtou32(cp, NULL, &pc))
2612             continue;
2613         if (pc >> 24 > 0)
2614             continue;
2615
2616         if ((cp = strtok(NULL, " \t")) == NULL)
2617             continue; /* no host name */
2618
2619         entry_found = TRUE;
2620         add_ss7pc_name(ni, pc, cp);
2621     }
2622
2623     fclose(hf);
2624     return entry_found ? TRUE : FALSE;
2625 }
2626
2627 static void
2628 ss7pc_name_lookup_init(void)
2629 {
2630     char *ss7pcspath;
2631
2632     g_assert(ss7pc_hash_table == NULL);
2633
2634     ss7pc_hash_table = wmem_map_new(wmem_epan_scope(), g_direct_hash, g_direct_equal);
2635
2636     /*
2637      * Load the user's ss7pcs file
2638      */
2639     ss7pcspath = get_persconffile_path(ENAME_SS7PCS, TRUE);
2640     if (!read_ss7pcs_file(ss7pcspath) && errno != ENOENT) {
2641         report_open_failure(ss7pcspath, errno, FALSE);
2642     }
2643     g_free(ss7pcspath);
2644 }
2645
2646 /* SS7PC Name Resolution End*/
2647
2648
2649 /*
2650  *  External Functions
2651  */
2652
2653 void
2654 addr_resolve_pref_init(module_t *nameres)
2655 {
2656     prefs_register_bool_preference(nameres, "mac_name",
2657             "Resolve MAC addresses",
2658             "Resolve Ethernet MAC addresses to host names from the preferences"
2659             " or system's Ethers file, or to a manufacturer based name.",
2660             &gbl_resolv_flags.mac_name);
2661
2662     prefs_register_bool_preference(nameres, "transport_name",
2663             "Resolve transport names",
2664             "Resolve TCP/UDP ports into service names",
2665             &gbl_resolv_flags.transport_name);
2666
2667     prefs_register_bool_preference(nameres, "network_name",
2668             "Resolve network (IP) addresses",
2669             "Resolve IPv4, IPv6, and IPX addresses into host names."
2670             " The next set of check boxes determines how name resolution should be performed."
2671             " If no other options are checked name resolution is made from Wireshark's host file"
2672             " and capture file name resolution blocks.",
2673             &gbl_resolv_flags.network_name);
2674
2675     prefs_register_bool_preference(nameres, "dns_pkt_addr_resolution",
2676             "Use captured DNS packet data for address resolution",
2677             "Whether address/name pairs found in captured DNS packets should be used by Wireshark for name resolution.",
2678             &gbl_resolv_flags.dns_pkt_addr_resolution);
2679
2680 #ifdef HAVE_C_ARES
2681     prefs_register_bool_preference(nameres, "use_external_name_resolver",
2682             "Use an external network name resolver",
2683             "Use your system's configured name resolver"
2684             " (usually DNS) to resolve network names."
2685             " Only applies when network name resolution"
2686             " is enabled.",
2687             &gbl_resolv_flags.use_external_net_name_resolver);
2688
2689     prefs_register_obsolete_preference(nameres, "concurrent_dns");
2690
2691     prefs_register_uint_preference(nameres, "name_resolve_concurrency",
2692             "Maximum concurrent requests",
2693             "The maximum number of DNS requests that may"
2694             " be active at any time. A large value (many"
2695             " thousands) might overload the network or make"
2696             " your DNS server behave badly.",
2697             10,
2698             &name_resolve_concurrency);
2699 #else
2700     prefs_register_static_text_preference(nameres, "use_external_name_resolver",
2701             "Use an external network name resolver: N/A",
2702             "Support for using a concurrent external name resolver was not"
2703             " compiled into this version of Wireshark");
2704 #endif
2705
2706     prefs_register_bool_preference(nameres, "hosts_file_handling",
2707             "Only use the profile \"hosts\" file",
2708             "By default \"hosts\" files will be loaded from multiple sources."
2709             " Checking this box only loads the \"hosts\" in the current profile.",
2710             &gbl_resolv_flags.load_hosts_file_from_profile_only);
2711
2712     prefs_register_bool_preference(nameres, "vlan_name",
2713             "Resolve VLAN IDs",
2714             "Resolve VLAN IDs to network names from the preferences \"vlans\" file."
2715             " Format of the file is: \"ID<Tab>Name\"."
2716             " One line per VLAN, e.g.: 1 Management",
2717             &gbl_resolv_flags.vlan_name);
2718
2719     prefs_register_bool_preference(nameres, "ss7_pc_name",
2720             "Resolve SS7 PCs",
2721             "Resolve SS7 Point Codes to node names from the profiles \"ss7pcs\" file."
2722             " Format of the file is: \"Network_Indicator<Dash>PC_Decimal<Tab>Name\"."
2723             " One line per Point Code, e.g.: 2-1234 MyPointCode1",
2724             &gbl_resolv_flags.ss7pc_name);
2725
2726 }
2727
2728 void
2729 disable_name_resolution(void) {
2730     gbl_resolv_flags.mac_name                           = FALSE;
2731     gbl_resolv_flags.network_name                       = FALSE;
2732     gbl_resolv_flags.transport_name                     = FALSE;
2733     gbl_resolv_flags.dns_pkt_addr_resolution            = FALSE;
2734     gbl_resolv_flags.use_external_net_name_resolver     = FALSE;
2735     gbl_resolv_flags.vlan_name                          = FALSE;
2736     gbl_resolv_flags.ss7pc_name                         = FALSE;
2737 }
2738
2739 #ifdef HAVE_C_ARES
2740 gboolean
2741 host_name_lookup_process(void) {
2742     async_dns_queue_msg_t *caqm;
2743     struct timeval tv = { 0, 0 };
2744     int nfds;
2745     fd_set rfds, wfds;
2746     gboolean nro = new_resolved_objects;
2747     wmem_list_frame_t* head;
2748
2749     new_resolved_objects = FALSE;
2750     nro |= maxmind_db_lookup_process();
2751
2752     if (!async_dns_initialized)
2753         /* c-ares not initialized. Bail out and cancel timers. */
2754         return nro;
2755
2756     head = wmem_list_head(async_dns_queue_head);
2757
2758     while (head != NULL && async_dns_in_flight <= name_resolve_concurrency) {
2759         caqm = (async_dns_queue_msg_t *)wmem_list_frame_data(head);
2760         wmem_list_remove_frame(async_dns_queue_head, head);
2761         if (caqm->family == AF_INET) {
2762             ares_gethostbyaddr(ghba_chan, &caqm->addr.ip4, sizeof(guint32), AF_INET,
2763                     c_ares_ghba_cb, caqm);
2764             async_dns_in_flight++;
2765         } else if (caqm->family == AF_INET6) {
2766             ares_gethostbyaddr(ghba_chan, &caqm->addr.ip6, sizeof(ws_in6_addr),
2767                     AF_INET6, c_ares_ghba_cb, caqm);
2768             async_dns_in_flight++;
2769         }
2770
2771         head = wmem_list_head(async_dns_queue_head);
2772     }
2773
2774     FD_ZERO(&rfds);
2775     FD_ZERO(&wfds);
2776     nfds = ares_fds(ghba_chan, &rfds, &wfds);
2777     if (nfds > 0) {
2778         if (select(nfds, &rfds, &wfds, NULL, &tv) == -1) { /* call to select() failed */
2779             fprintf(stderr, "Warning: call to select() failed, error is %s\n", g_strerror(errno));
2780             return nro;
2781         }
2782         ares_process(ghba_chan, &rfds, &wfds);
2783     }
2784
2785     /* Any new entries? */
2786     return nro;
2787 }
2788
2789 static void
2790 _host_name_lookup_cleanup(void) {
2791     async_dns_queue_head = NULL;
2792
2793     if (async_dns_initialized) {
2794         ares_destroy(ghba_chan);
2795         ares_destroy(ghbn_chan);
2796     }
2797 #ifdef CARES_HAVE_ARES_LIBRARY_INIT
2798     ares_library_cleanup();
2799 #endif
2800     async_dns_initialized = FALSE;
2801 }
2802
2803 #else
2804
2805 gboolean
2806 host_name_lookup_process(void) {
2807     gboolean nro = new_resolved_objects;
2808
2809     new_resolved_objects = FALSE;
2810
2811     nro |= maxmind_db_lookup_process();
2812
2813     return nro;
2814 }
2815
2816 static void
2817 _host_name_lookup_cleanup(void) {
2818 }
2819
2820 #endif /* HAVE_C_ARES */
2821
2822 const gchar *
2823 get_hostname(const guint addr)
2824 {
2825     /* XXX why do we call this if we're not resolving? To create hash entries?
2826      * Why?
2827      */
2828     hashipv4_t *tp = host_lookup(addr);
2829
2830     if (!gbl_resolv_flags.network_name)
2831         return tp->ip;
2832
2833     tp->flags |= RESOLVED_ADDRESS_USED;
2834
2835     return tp->name;
2836 }
2837
2838 /* -------------------------- */
2839
2840 const gchar *
2841 get_hostname6(const ws_in6_addr *addr)
2842 {
2843     /* XXX why do we call this if we're not resolving? To create hash entries?
2844      * Why?
2845      */
2846     hashipv6_t *tp = host_lookup6(addr);
2847
2848     if (!gbl_resolv_flags.network_name)
2849         return tp->ip6;
2850
2851     tp->flags |= RESOLVED_ADDRESS_USED;
2852
2853     return tp->name;
2854 }
2855
2856 /* -------------------------- */
2857 void
2858 add_ipv4_name(const guint addr, const gchar *name)
2859 {
2860     hashipv4_t *tp;
2861
2862     /*
2863      * Don't add zero-length names; apparently, some resolvers will return
2864      * them if they get them from DNS.
2865      */
2866     if (!name || name[0] == '\0')
2867         return;
2868
2869     tp = (hashipv4_t *)wmem_map_lookup(ipv4_hash_table, GUINT_TO_POINTER(addr));
2870     if (!tp) {
2871         tp = new_ipv4(addr);
2872         wmem_map_insert(ipv4_hash_table, GUINT_TO_POINTER(addr), tp);
2873     }
2874
2875     if (g_ascii_strcasecmp(tp->name, name)) {
2876         g_strlcpy(tp->name, name, MAXNAMELEN);
2877         new_resolved_objects = TRUE;
2878     }
2879     tp->flags |= TRIED_RESOLVE_ADDRESS|NAME_RESOLVED;
2880 } /* add_ipv4_name */
2881
2882 /* -------------------------- */
2883 void
2884 add_ipv6_name(const ws_in6_addr *addrp, const gchar *name)
2885 {
2886     hashipv6_t *tp;
2887
2888     /*
2889      * Don't add zero-length names; apparently, some resolvers will return
2890      * them if they get them from DNS.
2891      */
2892     if (!name || name[0] == '\0')
2893         return;
2894
2895     tp = (hashipv6_t *)wmem_map_lookup(ipv6_hash_table, addrp);
2896     if (!tp) {
2897         ws_in6_addr *addr_key;
2898
2899         addr_key = wmem_new(wmem_epan_scope(), ws_in6_addr);
2900         tp = new_ipv6(addrp);
2901         memcpy(addr_key, addrp, 16);
2902         wmem_map_insert(ipv6_hash_table, addr_key, tp);
2903     }
2904
2905     if (g_ascii_strcasecmp(tp->name, name)) {
2906         g_strlcpy(tp->name, name, MAXNAMELEN);
2907         new_resolved_objects = TRUE;
2908     }
2909     tp->flags |= TRIED_RESOLVE_ADDRESS|NAME_RESOLVED;
2910 } /* add_ipv6_name */
2911
2912 static void
2913 add_manually_resolved_ipv4(gpointer data, gpointer user_data _U_)
2914 {
2915     resolved_ipv4_t *resolved_ipv4_entry = (resolved_ipv4_t *)data;
2916
2917     add_ipv4_name(resolved_ipv4_entry->host_addr, resolved_ipv4_entry->name);
2918 }
2919
2920 static void
2921 add_manually_resolved_ipv6(gpointer data, gpointer user_data _U_)
2922 {
2923     resolved_ipv6_t *resolved_ipv6_entry = (resolved_ipv6_t *)data;
2924
2925     add_ipv6_name(&(resolved_ipv6_entry->ip6_addr), resolved_ipv6_entry->name);
2926 }
2927
2928 static void
2929 add_manually_resolved(void)
2930 {
2931     if (manually_resolved_ipv4_list) {
2932         wmem_list_foreach(manually_resolved_ipv4_list, add_manually_resolved_ipv4, NULL);
2933     }
2934
2935     if (manually_resolved_ipv6_list) {
2936         wmem_list_foreach(manually_resolved_ipv6_list, add_manually_resolved_ipv6, NULL);
2937     }
2938 }
2939
2940 static void
2941 host_name_lookup_init(void)
2942 {
2943     char *hostspath;
2944     guint i;
2945
2946     g_assert(ipxnet_hash_table == NULL);
2947     ipxnet_hash_table = wmem_map_new(wmem_epan_scope(), g_direct_hash, g_direct_equal);
2948
2949     g_assert(ipv4_hash_table == NULL);
2950     ipv4_hash_table = wmem_map_new(wmem_epan_scope(), g_direct_hash, g_direct_equal);
2951
2952     g_assert(ipv6_hash_table == NULL);
2953     ipv6_hash_table = wmem_map_new(wmem_epan_scope(), ipv6_oat_hash, ipv6_equal);
2954
2955 #ifdef HAVE_C_ARES
2956     g_assert(async_dns_queue_head == NULL);
2957     async_dns_queue_head = wmem_list_new(wmem_epan_scope());
2958 #endif
2959
2960     if (manually_resolved_ipv4_list == NULL)
2961         manually_resolved_ipv4_list = wmem_list_new(wmem_epan_scope());
2962
2963     if (manually_resolved_ipv6_list == NULL)
2964         manually_resolved_ipv6_list = wmem_list_new(wmem_epan_scope());
2965
2966     /*
2967      * Load the global hosts file, if we have one.
2968      */
2969     if (!gbl_resolv_flags.load_hosts_file_from_profile_only) {
2970         hostspath = get_datafile_path(ENAME_HOSTS);
2971         if (!read_hosts_file(hostspath, TRUE) && errno != ENOENT) {
2972             report_open_failure(hostspath, errno, FALSE);
2973         }
2974         g_free(hostspath);
2975     }
2976     /*
2977      * Load the user's hosts file no matter what, if they have one.
2978      */
2979     hostspath = get_persconffile_path(ENAME_HOSTS, TRUE);
2980     if (!read_hosts_file(hostspath, TRUE) && errno != ENOENT) {
2981         report_open_failure(hostspath, errno, FALSE);
2982     }
2983     g_free(hostspath);
2984 #ifdef HAVE_C_ARES
2985 #ifdef CARES_HAVE_ARES_LIBRARY_INIT
2986     if (ares_library_init(ARES_LIB_INIT_ALL) == ARES_SUCCESS) {
2987 #endif
2988         if (ares_init(&ghba_chan) == ARES_SUCCESS && ares_init(&ghbn_chan) == ARES_SUCCESS) {
2989             async_dns_initialized = TRUE;
2990         }
2991 #ifdef CARES_HAVE_ARES_LIBRARY_INIT
2992     }
2993 #endif
2994 #else
2995 #endif /* HAVE_C_ARES */
2996
2997     if (extra_hosts_files && !gbl_resolv_flags.load_hosts_file_from_profile_only) {
2998         for (i = 0; i < extra_hosts_files->len; i++) {
2999             read_hosts_file((const char *) g_ptr_array_index(extra_hosts_files, i), TRUE);
3000         }
3001     }
3002
3003     subnet_name_lookup_init();
3004
3005     add_manually_resolved();
3006
3007     ss7pc_name_lookup_init();
3008 }
3009
3010 static void
3011 host_name_lookup_cleanup(void)
3012 {
3013     guint32 i, j;
3014     sub_net_hashipv4_t *entry, *next_entry;
3015
3016     _host_name_lookup_cleanup();
3017
3018     ipxnet_hash_table = NULL;
3019     ipv4_hash_table = NULL;
3020     ipv6_hash_table = NULL;
3021     ss7pc_hash_table = NULL;
3022
3023     for(i = 0; i < SUBNETLENGTHSIZE; ++i) {
3024         if (subnet_length_entries[i].subnet_addresses != NULL) {
3025             for (j = 0; j < HASHHOSTSIZE; j++) {
3026                 for (entry = subnet_length_entries[i].subnet_addresses[j];
3027                      entry != NULL; entry = next_entry) {
3028                     next_entry = entry->next;
3029                     wmem_free(wmem_epan_scope(), entry);
3030                 }
3031             }
3032             wmem_free(wmem_epan_scope(), subnet_length_entries[i].subnet_addresses);
3033             subnet_length_entries[i].subnet_addresses = NULL;
3034         }
3035     }
3036
3037     have_subnet_entry = FALSE;
3038     new_resolved_objects = FALSE;
3039 }
3040
3041
3042 void host_name_lookup_reset(void)
3043 {
3044     host_name_lookup_cleanup();
3045     host_name_lookup_init();
3046 }
3047
3048 void
3049 manually_resolve_cleanup(void)
3050 {
3051     if (manually_resolved_ipv4_list) {
3052         wmem_destroy_list(manually_resolved_ipv4_list);
3053         manually_resolved_ipv4_list = NULL;
3054     }
3055     if (manually_resolved_ipv6_list) {
3056         wmem_destroy_list(manually_resolved_ipv6_list);
3057         manually_resolved_ipv6_list = NULL;
3058     }
3059 }
3060
3061 gchar *
3062 udp_port_to_display(wmem_allocator_t *allocator, guint port)
3063 {
3064
3065     if (!gbl_resolv_flags.transport_name) {
3066         return wmem_utoa(allocator, port);
3067     }
3068
3069     return wmem_strdup(allocator, serv_name_lookup(PT_UDP, port));
3070
3071 } /* udp_port_to_display */
3072
3073 gchar *
3074 dccp_port_to_display(wmem_allocator_t *allocator, guint port)
3075 {
3076
3077     if (!gbl_resolv_flags.transport_name) {
3078         return wmem_utoa(allocator, port);
3079     }
3080
3081     return wmem_strdup(allocator, serv_name_lookup(PT_DCCP, port));
3082
3083 } /* dccp_port_to_display */
3084
3085 gchar *
3086 tcp_port_to_display(wmem_allocator_t *allocator, guint port)
3087 {
3088
3089     if (!gbl_resolv_flags.transport_name) {
3090         return wmem_utoa(allocator, port);
3091     }
3092
3093     return wmem_strdup(allocator, serv_name_lookup(PT_TCP, port));
3094
3095 } /* tcp_port_to_display */
3096
3097 gchar *
3098 sctp_port_to_display(wmem_allocator_t *allocator, guint port)
3099 {
3100
3101     if (!gbl_resolv_flags.transport_name) {
3102         return wmem_utoa(allocator, port);
3103     }
3104
3105     return wmem_strdup(allocator, serv_name_lookup(PT_SCTP, port));
3106
3107 } /* sctp_port_to_display */
3108
3109 gchar *
3110 port_with_resolution_to_str(wmem_allocator_t *scope, port_type proto, guint port)
3111 {
3112     const gchar *port_str;
3113
3114     if (!gbl_resolv_flags.transport_name || (proto == PT_NONE)) {
3115         /* No name resolution support, just return port string */
3116         return wmem_strdup_printf(scope, "%u", port);
3117     }
3118     port_str = serv_name_lookup(proto, port);
3119     g_assert(port_str);
3120     return wmem_strdup_printf(scope, "%s (%u)", port_str, port);
3121 }
3122
3123 int
3124 port_with_resolution_to_str_buf(gchar *buf, gulong buf_size, port_type proto, guint port)
3125 {
3126     const gchar *port_str;
3127
3128     if (!gbl_resolv_flags.transport_name || (proto == PT_NONE)) {
3129         /* No name resolution support, just return port string */
3130         return g_snprintf(buf, buf_size, "%u", port);
3131     }
3132     port_str = serv_name_lookup(proto, port);
3133     g_assert(port_str);
3134     return g_snprintf(buf, buf_size, "%s (%u)", port_str, port);
3135 }
3136
3137 const gchar *
3138 get_ether_name(const guint8 *addr)
3139 {
3140     hashether_t *tp;
3141     gboolean resolve = gbl_resolv_flags.mac_name;
3142
3143     tp = eth_name_lookup(addr, resolve);
3144
3145     return resolve ? tp->resolved_name : tp->hexaddr;
3146
3147 } /* get_ether_name */
3148
3149 const gchar *
3150 tvb_get_ether_name(tvbuff_t *tvb, gint offset)
3151 {
3152     return get_ether_name(tvb_get_ptr(tvb, offset, 6));
3153 }
3154
3155 /* Look for a (non-dummy) ether name in the hash, and return it if found.
3156  * If it's not found, simply return NULL.
3157  */
3158 const gchar *
3159 get_ether_name_if_known(const guint8 *addr)
3160 {
3161     hashether_t *tp;
3162
3163     /* Initialize ether structs if we're the first
3164      * ether-related function called */
3165     if (!gbl_resolv_flags.mac_name)
3166         return NULL;
3167
3168     /* eth_name_lookup will create a (resolved) hash entry if it doesn't exist */
3169     tp = eth_name_lookup(addr, TRUE);
3170     g_assert(tp != NULL);
3171
3172     if (tp->status == HASHETHER_STATUS_RESOLVED_NAME) {
3173         /* Name is from an ethers file */
3174         return tp->resolved_name;
3175     }
3176     else {
3177         /* Name was created */
3178         return NULL;
3179     }
3180 }
3181
3182 void
3183 add_ether_byip(const guint ip, const guint8 *eth)
3184 {
3185     hashipv4_t *tp;
3186
3187     /* first check that IP address can be resolved */
3188     if (!gbl_resolv_flags.network_name)
3189         return;
3190
3191     tp = host_lookup(ip);
3192
3193     /*
3194      * Was this IP address resolved to a host name?
3195      */
3196     if (tp->flags & NAME_RESOLVED) {
3197         /*
3198          * Yes, so add an entry in the ethers hashtable resolving
3199          * the MAC address to that name.
3200          */
3201         add_eth_name(eth, tp->name);
3202     }
3203
3204 } /* add_ether_byip */
3205
3206 gchar *
3207 ipxnet_to_str_punct(wmem_allocator_t *allocator, const guint32 ad, const char punct)
3208 {
3209     gchar *buf = (gchar *)wmem_alloc(allocator, 12);
3210
3211     *dword_to_hex_punct(buf, ad, punct) = '\0';
3212     return buf;
3213 }
3214
3215 gchar *
3216 get_ipxnet_name(wmem_allocator_t *allocator, const guint32 addr)
3217 {
3218
3219     if (!gbl_resolv_flags.network_name) {
3220         return ipxnet_to_str_punct(allocator, addr, '\0');
3221     }
3222
3223     return ipxnet_name_lookup(allocator, addr);
3224
3225 } /* get_ipxnet_name */
3226
3227 gchar *
3228 get_vlan_name(wmem_allocator_t *allocator, const guint16 id)
3229 {
3230
3231     if (!gbl_resolv_flags.vlan_name) {
3232         return NULL;
3233     }
3234
3235     return wmem_strdup(allocator, vlan_name_lookup(id));
3236
3237 } /* get_vlan_name */
3238
3239 const gchar *
3240 get_manuf_name(const guint8 *addr)
3241 {
3242     hashmanuf_t *manuf_value;
3243
3244     manuf_value = manuf_name_lookup(addr);
3245     if (gbl_resolv_flags.mac_name && manuf_value->status != HASHETHER_STATUS_UNRESOLVED)
3246         return manuf_value->resolved_name;
3247
3248     return manuf_value->hexaddr;
3249
3250 } /* get_manuf_name */
3251
3252 const gchar *
3253 tvb_get_manuf_name(tvbuff_t *tvb, gint offset)
3254 {
3255     return get_manuf_name(tvb_get_ptr(tvb, offset, 3));
3256 }
3257
3258 const gchar *
3259 get_manuf_name_if_known(const guint8 *addr)
3260 {
3261     hashmanuf_t *manuf_value;
3262     guint manuf_key;
3263     guint8 oct;
3264
3265     /* manuf needs only the 3 most significant octets of the ethernet address */
3266     manuf_key = addr[0];
3267     manuf_key = manuf_key<<8;
3268     oct = addr[1];
3269     manuf_key = manuf_key | oct;
3270     manuf_key = manuf_key<<8;
3271     oct = addr[2];
3272     manuf_key = manuf_key | oct;
3273
3274     manuf_value = (hashmanuf_t *)wmem_map_lookup(manuf_hashtable, GUINT_TO_POINTER(manuf_key));
3275     if ((manuf_value == NULL) || (manuf_value->status == HASHETHER_STATUS_UNRESOLVED)) {
3276         return NULL;
3277     }
3278
3279     return manuf_value->resolved_longname;
3280
3281 } /* get_manuf_name_if_known */
3282
3283 const gchar *
3284 uint_get_manuf_name_if_known(const guint manuf_key)
3285 {
3286     hashmanuf_t *manuf_value;
3287
3288     manuf_value = (hashmanuf_t *)wmem_map_lookup(manuf_hashtable, GUINT_TO_POINTER(manuf_key));
3289     if ((manuf_value == NULL) || (manuf_value->status == HASHETHER_STATUS_UNRESOLVED)) {
3290         return NULL;
3291     }
3292
3293     return manuf_value->resolved_longname;
3294 }
3295
3296 const gchar *
3297 tvb_get_manuf_name_if_known(tvbuff_t *tvb, gint offset)
3298 {
3299     return get_manuf_name_if_known(tvb_get_ptr(tvb, offset, 3));
3300 }
3301
3302 char* get_hash_manuf_resolved_name(hashmanuf_t* manuf)
3303 {
3304     return manuf->resolved_longname;
3305 }
3306
3307 gchar *
3308 eui64_to_display(wmem_allocator_t *allocator, const guint64 addr_eui64)
3309 {
3310     guint8 *addr = (guint8 *)wmem_alloc(NULL, 8);
3311     hashmanuf_t *manuf_value;
3312     gchar *ret;
3313
3314     /* Copy and convert the address to network byte order. */
3315     *(guint64 *)(void *)(addr) = pntoh64(&(addr_eui64));
3316
3317     manuf_value = manuf_name_lookup(addr);
3318     if (!gbl_resolv_flags.mac_name || (manuf_value->status == HASHETHER_STATUS_UNRESOLVED)) {
3319         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]);
3320     } else {
3321         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]);
3322     }
3323
3324     wmem_free(NULL, addr);
3325     return ret;
3326 } /* eui64_to_display */
3327
3328 #ifdef HAVE_C_ARES
3329 #define GHI_TIMEOUT (250 * 1000)
3330 static void
3331 c_ares_ghi_cb(void *arg, int status, int timeouts _U_, struct hostent *hp) {
3332     /*
3333      * XXX - If we wanted to be really fancy we could cache results here and
3334      * look them up in get_host_ipaddr* below.
3335      */
3336     async_hostent_t *ahp = (async_hostent_t *)arg;
3337     if (status == ARES_SUCCESS && hp && ahp && hp->h_length == ahp->addr_size) {
3338         memcpy(ahp->addrp, hp->h_addr, hp->h_length);
3339         ahp->copied = hp->h_length;
3340     }
3341 }
3342 #endif /* HAVE_C_ARES */
3343
3344 /* Translate a string, assumed either to be a dotted-quad IPv4 address or
3345  * a host name, to a numeric IPv4 address.  Return TRUE if we succeed and
3346  * set "*addrp" to that numeric IPv4 address; return FALSE if we fail. */
3347 gboolean
3348 get_host_ipaddr(const char *host, guint32 *addrp)
3349 {
3350 #ifdef HAVE_C_ARES
3351     struct timeval tv = { 0, GHI_TIMEOUT }, *tvp;
3352     int nfds;
3353     fd_set rfds, wfds;
3354     async_hostent_t ahe;
3355 #endif
3356
3357     /*
3358      * XXX - are there places where this is used to translate something
3359      * that's *only* supposed to be an IPv4 address, and where it
3360      * *shouldn't* translate host names?
3361      */
3362     if (!ws_inet_pton4(host, addrp)) {
3363
3364         /* It's not a valid dotted-quad IP address; is it a valid
3365          * host name?
3366          */
3367
3368         /* If we're not allowed to do name resolution, don't do name
3369          * resolution...
3370          */
3371         if (!gbl_resolv_flags.network_name ||
3372                 !gbl_resolv_flags.use_external_net_name_resolver) {
3373             return FALSE;
3374         }
3375
3376 #ifdef HAVE_C_ARES
3377         if (!async_dns_initialized || name_resolve_concurrency < 1) {
3378             return FALSE;
3379         }
3380         ahe.addr_size = (int) sizeof (struct in_addr);
3381         ahe.copied = 0;
3382         ahe.addrp = addrp;
3383         ares_gethostbyname(ghbn_chan, host, AF_INET, c_ares_ghi_cb, &ahe);
3384         FD_ZERO(&rfds);
3385         FD_ZERO(&wfds);
3386         nfds = ares_fds(ghbn_chan, &rfds, &wfds);
3387         if (nfds > 0) {
3388             tvp = ares_timeout(ghbn_chan, &tv, &tv);
3389             if (select(nfds, &rfds, &wfds, NULL, tvp) == -1) { /* call to select() failed */
3390                 fprintf(stderr, "Warning: call to select() failed, error is %s\n", g_strerror(errno));
3391                 return FALSE;
3392             }
3393             ares_process(ghbn_chan, &rfds, &wfds);
3394         }
3395         ares_cancel(ghbn_chan);
3396         if (ahe.addr_size == ahe.copied) {
3397             return TRUE;
3398         }
3399         return FALSE;
3400 #endif
3401     }
3402
3403     return TRUE;
3404 }
3405
3406 /*
3407  * Translate IPv6 numeric address or FQDN hostname into binary IPv6 address.
3408  * Return TRUE if we succeed and set "*addrp" to that numeric IPv6 address;
3409  * return FALSE if we fail.
3410  */
3411 gboolean
3412 get_host_ipaddr6(const char *host, ws_in6_addr *addrp)
3413 {
3414 #ifdef HAVE_C_ARES
3415     struct timeval tv = { 0, GHI_TIMEOUT }, *tvp;
3416     int nfds;
3417     fd_set rfds, wfds;
3418     async_hostent_t ahe;
3419 #endif /* HAVE_C_ARES */
3420
3421     if (str_to_ip6(host, addrp))
3422         return TRUE;
3423
3424     /* It's not a valid dotted-quad IP address; is it a valid
3425      * host name?
3426      *
3427      * XXX - are there places where this is used to translate something
3428      * that's *only* supposed to be an IPv6 address, and where it
3429      * *shouldn't* translate host names?
3430      */
3431
3432     /* If we're not allowed to do name resolution, don't do name
3433      * resolution...
3434      */
3435     if (!gbl_resolv_flags.network_name ||
3436             !gbl_resolv_flags.use_external_net_name_resolver) {
3437         return FALSE;
3438     }
3439
3440     /* try FQDN */
3441 #ifdef HAVE_C_ARES
3442     if (!async_dns_initialized || name_resolve_concurrency < 1) {
3443         return FALSE;
3444     }
3445     ahe.addr_size = (int) sizeof (ws_in6_addr);
3446     ahe.copied = 0;
3447     ahe.addrp = addrp;
3448     ares_gethostbyname(ghbn_chan, host, AF_INET6, c_ares_ghi_cb, &ahe);
3449     FD_ZERO(&rfds);
3450     FD_ZERO(&wfds);
3451     nfds = ares_fds(ghbn_chan, &rfds, &wfds);
3452     if (nfds > 0) {
3453         tvp = ares_timeout(ghbn_chan, &tv, &tv);
3454         if (select(nfds, &rfds, &wfds, NULL, tvp) == -1) { /* call to select() failed */
3455             fprintf(stderr, "Warning: call to select() failed, error is %s\n", g_strerror(errno));
3456             return FALSE;
3457         }
3458         ares_process(ghbn_chan, &rfds, &wfds);
3459     }
3460     ares_cancel(ghbn_chan);
3461     if (ahe.addr_size == ahe.copied) {
3462         return TRUE;
3463     }
3464 #endif
3465
3466     return FALSE;
3467 }
3468
3469 wmem_map_t *
3470 get_manuf_hashtable(void)
3471 {
3472     return manuf_hashtable;
3473 }
3474
3475 wmem_map_t *
3476 get_wka_hashtable(void)
3477 {
3478     return wka_hashtable;
3479 }
3480
3481 wmem_map_t *
3482 get_eth_hashtable(void)
3483 {
3484     return eth_hashtable;
3485 }
3486
3487 wmem_map_t *
3488 get_serv_port_hashtable(void)
3489 {
3490     return serv_port_hashtable;
3491 }
3492
3493 wmem_map_t *
3494 get_ipxnet_hash_table(void)
3495 {
3496         return ipxnet_hash_table;
3497 }
3498
3499 wmem_map_t *
3500 get_vlan_hash_table(void)
3501 {
3502         return vlan_hash_table;
3503 }
3504
3505 wmem_map_t *
3506 get_ipv4_hash_table(void)
3507 {
3508         return ipv4_hash_table;
3509 }
3510
3511 wmem_map_t *
3512 get_ipv6_hash_table(void)
3513 {
3514         return ipv6_hash_table;
3515 }
3516 /* Initialize all the address resolution subsystems in this file */
3517 void
3518 addr_resolv_init(void)
3519 {
3520     initialize_services();
3521     initialize_ethers();
3522     initialize_ipxnets();
3523     initialize_vlans();
3524     initialize_enterprises();
3525     host_name_lookup_init();
3526 }
3527
3528 /* Clean up all the address resolution subsystems in this file */
3529 void
3530 addr_resolv_cleanup(void)
3531 {
3532     vlan_name_lookup_cleanup();
3533     service_name_lookup_cleanup();
3534     ethers_cleanup();
3535     ipx_name_lookup_cleanup();
3536     enterprises_cleanup();
3537     host_name_lookup_cleanup();
3538 }
3539
3540 gboolean
3541 str_to_ip(const char *str, void *dst)
3542 {
3543     return ws_inet_pton4(str, (guint32 *)dst);
3544 }
3545
3546 gboolean
3547 str_to_ip6(const char *str, void *dst)
3548 {
3549     return ws_inet_pton6(str, (ws_in6_addr *)dst);
3550 }
3551
3552 /*
3553  * convert a 0-terminated string that contains an ethernet address into
3554  * the corresponding sequence of 6 bytes
3555  * eth_bytes is a buffer >= 6 bytes that was allocated by the caller
3556  */
3557 gboolean
3558 str_to_eth(const char *str, char *eth_bytes)
3559 {
3560     ether_t eth;
3561
3562     if (!parse_ether_address(str, &eth, NULL, FALSE))
3563         return FALSE;
3564
3565     memcpy(eth_bytes, eth.addr, sizeof(eth.addr));
3566     return TRUE;
3567 }
3568
3569 /*
3570  * Editor modelines  -  http://www.wireshark.org/tools/modelines.html
3571  *
3572  * Local variables:
3573  * c-basic-offset: 4
3574  * tab-width: 8
3575  * indent-tabs-mode: nil
3576  * End:
3577  *
3578  * vi: set shiftwidth=4 tabstop=8 expandtab:
3579  * :indentSize=4:tabSize=8:noTabs=true:
3580  */