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