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