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