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