MBIM: add an option to force SMS PDU decoding format if MBIM_DEVICE_CAPS_INFO message...
[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_H
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[2] << 16) + (addr[1] << 8) + addr[0]);
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)
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;
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         if (is_ipv6) {
1977             memcpy(&ip6_addr, host_addr, sizeof ip6_addr);
1978             add_ipv6_name(&ip6_addr, cp);
1979         } else
1980             add_ipv4_name(host_addr[0], cp);
1981
1982         /*
1983          * Add the aliases, too, if there are any.
1984          * XXX - host_lookup() only returns the first entry.
1985          */
1986         while ((cp = strtok(NULL, " \t")) != NULL) {
1987             if (is_ipv6) {
1988                 memcpy(&ip6_addr, host_addr, sizeof ip6_addr);
1989                 add_ipv6_name(&ip6_addr, cp);
1990             } else
1991                 add_ipv4_name(host_addr[0], cp);
1992         }
1993     }
1994     g_free(line);
1995
1996     fclose(hf);
1997     return TRUE;
1998 } /* read_hosts_file */
1999
2000 gboolean
2001 add_hosts_file (const char *hosts_file)
2002 {
2003     gboolean found = FALSE;
2004     guint i;
2005
2006     if (!hosts_file)
2007         return FALSE;
2008
2009     if (!extra_hosts_files)
2010         extra_hosts_files = g_ptr_array_new();
2011
2012     for (i = 0; i < extra_hosts_files->len; i++) {
2013         if (strcmp(hosts_file, (const char *) g_ptr_array_index(extra_hosts_files, i)) == 0)
2014             found = TRUE;
2015     }
2016
2017     if (!found) {
2018         g_ptr_array_add(extra_hosts_files, g_strdup(hosts_file));
2019         return read_hosts_file (hosts_file);
2020     }
2021     return TRUE;
2022 }
2023
2024 gboolean
2025 add_ip_name_from_string (const char *addr, const char *name)
2026 {
2027     guint32 host_addr[4]; /* IPv4 */
2028     struct e_in6_addr ip6_addr; /* IPv6 */
2029     gboolean is_ipv6;
2030     int ret;
2031     resolved_ipv4_t *resolved_ipv4_entry;
2032     resolved_ipv6_t *resolved_ipv6_entry;
2033
2034     ret = inet_pton(AF_INET6, addr, &ip6_addr);
2035     if (ret < 0)
2036         /* Error parsing address */
2037         return FALSE;
2038
2039     if (ret > 0) {
2040         /* Valid IPv6 */
2041         is_ipv6 = TRUE;
2042     } else {
2043         /* Not valid IPv6 - valid IPv4? */
2044         if (!str_to_ip(addr, &host_addr))
2045             return FALSE; /* no */
2046         is_ipv6 = FALSE;
2047     }
2048
2049     if (is_ipv6) {
2050         resolved_ipv6_entry = g_new(resolved_ipv6_t, 1);
2051         memcpy(&(resolved_ipv6_entry->ip6_addr), &ip6_addr, 16);
2052         g_strlcpy(resolved_ipv6_entry->name, name, MAXNAMELEN);
2053         manually_resolved_ipv6_list = g_slist_prepend(manually_resolved_ipv6_list, resolved_ipv6_entry);
2054     } else {
2055         resolved_ipv4_entry = g_new(resolved_ipv4_t, 1);
2056         resolved_ipv4_entry->host_addr = host_addr[0];
2057         g_strlcpy(resolved_ipv4_entry->name, name, MAXNAMELEN);
2058         manually_resolved_ipv4_list = g_slist_prepend(manually_resolved_ipv4_list, resolved_ipv4_entry);
2059     }
2060
2061     return TRUE;
2062 } /* add_ip_name_from_string */
2063
2064 /*
2065  * Add the resolved addresses that are in use to the list used to create the NRB
2066  */
2067 static void
2068 ipv4_hash_table_resolved_to_list(gpointer key _U_, gpointer value, gpointer user_data)
2069 {
2070     addrinfo_lists_t *lists = (addrinfo_lists_t*)user_data;
2071     hashipv4_t *ipv4_hash_table_entry = (hashipv4_t *)value;
2072
2073     if((ipv4_hash_table_entry->flags & USED_AND_RESOLVED_MASK) == RESOLVED_ADDRESS_USED){
2074         lists->ipv4_addr_list = g_list_prepend (lists->ipv4_addr_list, ipv4_hash_table_entry);
2075     }
2076
2077 }
2078
2079 /*
2080  * Add the resolved addresses that are in use to the list used to create the NRB
2081  */
2082
2083 static void
2084 ipv6_hash_table_resolved_to_list(gpointer key _U_, gpointer value, gpointer user_data)
2085 {
2086     addrinfo_lists_t *lists = (addrinfo_lists_t*)user_data;
2087     hashipv6_t *ipv6_hash_table_entry = (hashipv6_t *)value;
2088
2089     if((ipv6_hash_table_entry->flags & USED_AND_RESOLVED_MASK) == RESOLVED_ADDRESS_USED){
2090         lists->ipv6_addr_list = g_list_prepend (lists->ipv6_addr_list, ipv6_hash_table_entry);
2091     }
2092
2093 }
2094
2095 addrinfo_lists_t *
2096 get_addrinfo_list(void) {
2097
2098     if(ipv4_hash_table){
2099         g_hash_table_foreach(ipv4_hash_table, ipv4_hash_table_resolved_to_list, &addrinfo_lists);
2100     }
2101
2102     if(ipv6_hash_table){
2103         g_hash_table_foreach(ipv6_hash_table, ipv6_hash_table_resolved_to_list, &addrinfo_lists);
2104     }
2105
2106     return &addrinfo_lists;
2107 }
2108
2109 /* Read in a list of subnet definition - name pairs.
2110  * <line> = <comment> | <entry> | <whitespace>
2111  * <comment> = <whitespace>#<any>
2112  * <entry> = <subnet_definition> <whitespace> <subnet_name> [<comment>|<whitespace><any>]
2113  * <subnet_definition> = <ipv4_address> / <subnet_mask_length>
2114  * <ipv4_address> is a full address; it will be masked to get the subnet-ID.
2115  * <subnet_mask_length> is a decimal 1-31
2116  * <subnet_name> is a string containing no whitespace.
2117  * <whitespace> = (space | tab)+
2118  * Any malformed entries are ignored.
2119  * Any trailing data after the subnet_name is ignored.
2120  *
2121  * XXX Support IPv6
2122  */
2123 static gboolean
2124 read_subnets_file (const char *subnetspath)
2125 {
2126     FILE *hf;
2127     char *line = NULL;
2128     int size = 0;
2129     gchar *cp, *cp2;
2130     guint32 host_addr; /* IPv4 ONLY */
2131     int mask_length;
2132
2133     if ((hf = ws_fopen(subnetspath, "r")) == NULL)
2134         return FALSE;
2135
2136     while (fgetline(&line, &size, hf) >= 0) {
2137         if ((cp = strchr(line, '#')))
2138             *cp = '\0';
2139
2140         if ((cp = strtok(line, " \t")) == NULL)
2141             continue; /* no tokens in the line */
2142
2143
2144         /* Expected format is <IP4 address>/<subnet length> */
2145         cp2 = strchr(cp, '/');
2146         if(NULL == cp2) {
2147             /* No length */
2148             continue;
2149         }
2150         *cp2 = '\0'; /* Cut token */
2151         ++cp2    ;
2152
2153         /* Check if this is a valid IPv4 address */
2154         if (!str_to_ip(cp, &host_addr)) {
2155             continue; /* no */
2156         }
2157
2158         mask_length = atoi(cp2);
2159         if(0 >= mask_length || mask_length > 31) {
2160             continue; /* invalid mask length */
2161         }
2162
2163         if ((cp = strtok(NULL, " \t")) == NULL)
2164             continue; /* no subnet name */
2165
2166         subnet_entry_set(host_addr, (guint32)mask_length, cp);
2167     }
2168     g_free(line);
2169
2170     fclose(hf);
2171     return TRUE;
2172 } /* read_subnets_file */
2173
2174 static subnet_entry_t
2175 subnet_lookup(const guint32 addr)
2176 {
2177     subnet_entry_t subnet_entry;
2178     guint32 i;
2179
2180     /* Search mask lengths linearly, longest first */
2181
2182     i = SUBNETLENGTHSIZE;
2183     while(have_subnet_entry && i > 0) {
2184         guint32 masked_addr;
2185         subnet_length_entry_t* length_entry;
2186
2187         /* Note that we run from 31 (length 32)  to 0 (length 1)  */
2188         --i;
2189         g_assert(i < SUBNETLENGTHSIZE);
2190
2191
2192         length_entry = &subnet_length_entries[i];
2193
2194         if(NULL != length_entry->subnet_addresses) {
2195             sub_net_hashipv4_t * tp;
2196             guint32 hash_idx;
2197
2198             masked_addr = addr & length_entry->mask;
2199             hash_idx = HASH_IPV4_ADDRESS(masked_addr);
2200
2201             tp = length_entry->subnet_addresses[hash_idx];
2202             while(tp != NULL && tp->addr != masked_addr) {
2203                 tp = tp->next;
2204             }
2205
2206             if(NULL != tp) {
2207                 subnet_entry.mask = length_entry->mask;
2208                 subnet_entry.mask_length = i + 1; /* Length is offset + 1 */
2209                 subnet_entry.name = tp->name;
2210                 return subnet_entry;
2211             }
2212         }
2213     }
2214
2215     subnet_entry.mask = 0;
2216     subnet_entry.mask_length = 0;
2217     subnet_entry.name = NULL;
2218
2219     return subnet_entry;
2220 }
2221
2222 /* Add a subnet-definition - name pair to the set.
2223  * The definition is taken by masking the address passed in with the mask of the
2224  * given length.
2225  */
2226 static void
2227 subnet_entry_set(guint32 subnet_addr, const guint32 mask_length, const gchar* name)
2228 {
2229     subnet_length_entry_t* entry;
2230     sub_net_hashipv4_t * tp;
2231     gsize hash_idx;
2232
2233     g_assert(mask_length > 0 && mask_length <= 32);
2234
2235     entry = &subnet_length_entries[mask_length - 1];
2236
2237     subnet_addr &= entry->mask;
2238
2239     hash_idx = HASH_IPV4_ADDRESS(subnet_addr);
2240
2241     if(NULL == entry->subnet_addresses) {
2242         entry->subnet_addresses = (sub_net_hashipv4_t**) se_alloc0(sizeof(sub_net_hashipv4_t*) * HASHHOSTSIZE);
2243     }
2244
2245     if(NULL != (tp = entry->subnet_addresses[hash_idx])) {
2246         if(tp->addr == subnet_addr) {
2247             return;    /* XXX provide warning that an address was repeated? */
2248         } else {
2249             sub_net_hashipv4_t * new_tp = se_new(sub_net_hashipv4_t);
2250             tp->next = new_tp;
2251             tp = new_tp;
2252         }
2253     } else {
2254         tp = entry->subnet_addresses[hash_idx] = se_new(sub_net_hashipv4_t);
2255     }
2256
2257     tp->next = NULL;
2258     tp->addr = subnet_addr;
2259     /* Clear DUMMY_ADDRESS_ENTRY */
2260     tp->flags = tp->flags & 0xfe; /*Never used again...*/
2261     g_strlcpy(tp->name, name, MAXNAMELEN); /* This is longer than subnet names can actually be */
2262     have_subnet_entry = TRUE;
2263 }
2264
2265 static void
2266 subnet_name_lookup_init(void)
2267 {
2268     gchar* subnetspath;
2269     guint32 i;
2270
2271     for(i = 0; i < SUBNETLENGTHSIZE; ++i) {
2272         guint32 length = i + 1;
2273
2274         subnet_length_entries[i].subnet_addresses  = NULL;
2275         subnet_length_entries[i].mask_length  = length;
2276         subnet_length_entries[i].mask = g_htonl(ip_get_subnet_mask(length));
2277     }
2278
2279     subnetspath = get_persconffile_path(ENAME_SUBNETS, FALSE);
2280     if (!read_subnets_file(subnetspath) && errno != ENOENT) {
2281         report_open_failure(subnetspath, errno, FALSE);
2282     }
2283     g_free(subnetspath);
2284
2285     /*
2286      * Load the global subnets file, if we have one.
2287      */
2288     subnetspath = get_datafile_path(ENAME_SUBNETS);
2289     if (!read_subnets_file(subnetspath) && errno != ENOENT) {
2290         report_open_failure(subnetspath, errno, FALSE);
2291     }
2292     g_free(subnetspath);
2293 }
2294
2295
2296 /*
2297  *  External Functions
2298  */
2299
2300 void
2301 addr_resolve_pref_init(module_t *nameres)
2302 {
2303     prefs_register_bool_preference(nameres, "mac_name",
2304             "Resolve MAC addresses",
2305             "Resolve Ethernet MAC address to manufacturer names",
2306             &gbl_resolv_flags.mac_name);
2307
2308     prefs_register_bool_preference(nameres, "transport_name",
2309             "Resolve transport names",
2310             "Resolve TCP/UDP ports into service names",
2311             &gbl_resolv_flags.transport_name);
2312
2313     prefs_register_bool_preference(nameres, "network_name",
2314             "Resolve network (IP) addresses",
2315             "Resolve IPv4, IPv6, and IPX addresses into host names."
2316             " The next set of check boxes determines how name resolution should be performed."
2317             " If no other options are checked name resolution is made from Wireshark's host file,"
2318             " capture file name resolution blocks and DNS packets in the capture.",
2319             &gbl_resolv_flags.network_name);
2320
2321     prefs_register_bool_preference(nameres, "use_external_name_resolver",
2322             "Use an external network name resolver",
2323             "Use your system's configured name resolver"
2324             " (usually DNS) to resolve network names."
2325             " Only applies when network name resolution"
2326             " is enabled.",
2327             &gbl_resolv_flags.use_external_net_name_resolver);
2328
2329 #if defined(HAVE_C_ARES) || defined(HAVE_GNU_ADNS)
2330     prefs_register_bool_preference(nameres, "concurrent_dns",
2331             "Enable concurrent DNS name resolution",
2332             "Enable concurrent DNS name resolution. Only"
2333             " applies when network name resolution is"
2334             " enabled. You probably want to enable this.",
2335             &gbl_resolv_flags.concurrent_dns);
2336
2337     prefs_register_uint_preference(nameres, "name_resolve_concurrency",
2338             "Maximum concurrent requests",
2339             "The maximum number of DNS requests that may"
2340             " be active at any time. A large value (many"
2341             " thousands) might overload the network or make"
2342             " your DNS server behave badly.",
2343             10,
2344             &name_resolve_concurrency);
2345 #else
2346     prefs_register_static_text_preference(nameres, "concurrent_dns",
2347             "Enable concurrent DNS name resolution: N/A",
2348             "Support for concurrent DNS name resolution was not"
2349             " compiled into this version of Wireshark");
2350 #endif
2351
2352     prefs_register_bool_preference(nameres, "hosts_file_handling",
2353             "Only use the profile \"hosts\" file",
2354             "By default \"hosts\" files will be loaded from multiple sources."
2355             " Checking this box only loads the \"hosts\" in the current profile.",
2356             &gbl_resolv_flags.load_hosts_file_from_profile_only);
2357
2358 }
2359
2360 #ifdef HAVE_C_ARES
2361 gboolean
2362 host_name_lookup_process(void) {
2363     async_dns_queue_msg_t *caqm;
2364     struct timeval tv = { 0, 0 };
2365     int nfds;
2366     fd_set rfds, wfds;
2367     gboolean nro = new_resolved_objects;
2368
2369     new_resolved_objects = FALSE;
2370
2371     if (!async_dns_initialized)
2372         /* c-ares not initialized. Bail out and cancel timers. */
2373         return nro;
2374
2375     async_dns_queue_head = g_list_first(async_dns_queue_head);
2376
2377     while (async_dns_queue_head != NULL && async_dns_in_flight <= name_resolve_concurrency) {
2378         caqm = (async_dns_queue_msg_t *) async_dns_queue_head->data;
2379         async_dns_queue_head = g_list_remove(async_dns_queue_head, (void *) caqm);
2380         if (caqm->family == AF_INET) {
2381             ares_gethostbyaddr(ghba_chan, &caqm->addr.ip4, sizeof(guint32), AF_INET,
2382                     c_ares_ghba_cb, caqm);
2383             async_dns_in_flight++;
2384         } else if (caqm->family == AF_INET6) {
2385             ares_gethostbyaddr(ghba_chan, &caqm->addr.ip6, sizeof(struct e_in6_addr),
2386                     AF_INET6, c_ares_ghba_cb, caqm);
2387             async_dns_in_flight++;
2388         }
2389     }
2390
2391     FD_ZERO(&rfds);
2392     FD_ZERO(&wfds);
2393     nfds = ares_fds(ghba_chan, &rfds, &wfds);
2394     if (nfds > 0) {
2395         if (select(nfds, &rfds, &wfds, NULL, &tv) == -1) { /* call to select() failed */
2396             fprintf(stderr, "Warning: call to select() failed, error is %s\n", strerror(errno));
2397             return nro;
2398         }
2399         ares_process(ghba_chan, &rfds, &wfds);
2400     }
2401
2402     /* Any new entries? */
2403     return nro;
2404 }
2405
2406 static void
2407 _host_name_lookup_cleanup(void) {
2408     GList *cur;
2409
2410     cur = g_list_first(async_dns_queue_head);
2411     while (cur) {
2412         g_free(cur->data);
2413         cur = g_list_next (cur);
2414     }
2415
2416     g_list_free(async_dns_queue_head);
2417     async_dns_queue_head = NULL;
2418
2419     if (async_dns_initialized) {
2420         ares_destroy(ghba_chan);
2421         ares_destroy(ghbn_chan);
2422     }
2423 #ifdef CARES_HAVE_ARES_LIBRARY_INIT
2424     ares_library_cleanup();
2425 #endif
2426     async_dns_initialized = FALSE;
2427 }
2428
2429 #elif defined(HAVE_GNU_ADNS)
2430
2431 /* XXX - The ADNS "documentation" isn't very clear:
2432  * - Do we need to keep our query structures around?
2433  */
2434 gboolean
2435 host_name_lookup_process(void) {
2436     async_dns_queue_msg_t *almsg;
2437     GList *cur;
2438     char addr_str[] = "111.222.333.444.in-addr.arpa.";
2439     guint8 *addr_bytes;
2440     adns_answer *ans;
2441     int ret;
2442     gboolean dequeue;
2443     gboolean nro = new_resolved_objects;
2444
2445     new_resolved_objects = FALSE;
2446     async_dns_queue_head = g_list_first(async_dns_queue_head);
2447
2448     cur = async_dns_queue_head;
2449     while (cur &&  async_dns_in_flight <= name_resolve_concurrency) {
2450         almsg = (async_dns_queue_msg_t *) cur->data;
2451         if (! almsg->submitted && almsg->type == AF_INET) {
2452             addr_bytes = (guint8 *) &almsg->ip4_addr;
2453             g_snprintf(addr_str, sizeof addr_str, "%u.%u.%u.%u.in-addr.arpa.", addr_bytes[3],
2454                     addr_bytes[2], addr_bytes[1], addr_bytes[0]);
2455             /* XXX - what if it fails? */
2456             adns_submit (ads, addr_str, adns_r_ptr, adns_qf_none, NULL, &almsg->query);
2457             almsg->submitted = TRUE;
2458             async_dns_in_flight++;
2459         }
2460         cur = cur->next;
2461     }
2462
2463     cur = async_dns_queue_head;
2464     while (cur) {
2465         dequeue = FALSE;
2466         almsg = (async_dns_queue_msg_t *) cur->data;
2467         if (almsg->submitted) {
2468             ret = adns_check(ads, &almsg->query, &ans, NULL);
2469             if (ret == 0) {
2470                 if (ans->status == adns_s_ok) {
2471                     add_ipv4_name(almsg->ip4_addr, *ans->rrs.str);
2472                 }
2473                 dequeue = TRUE;
2474             }
2475         }
2476         cur = cur->next;
2477         if (dequeue) {
2478             async_dns_queue_head = g_list_remove(async_dns_queue_head, (void *) almsg);
2479             g_free(almsg);
2480             /* XXX, what to do if async_dns_in_flight == 0? */
2481             async_dns_in_flight--;
2482         }
2483     }
2484
2485     /* Keep the timeout in place */
2486     return nro;
2487 }
2488
2489 static void
2490 _host_name_lookup_cleanup(void) {
2491     void *qdata;
2492
2493     async_dns_queue_head = g_list_first(async_dns_queue_head);
2494     while (async_dns_queue_head) {
2495         qdata = async_dns_queue_head->data;
2496         async_dns_queue_head = g_list_remove(async_dns_queue_head, qdata);
2497         g_free(qdata);
2498     }
2499
2500     if (async_dns_initialized)
2501         adns_finish(ads);
2502     async_dns_initialized = FALSE;
2503 }
2504
2505 #else /* HAVE_GNU_ADNS */
2506
2507 gboolean
2508 host_name_lookup_process(void) {
2509     gboolean nro = new_resolved_objects;
2510
2511     new_resolved_objects = FALSE;
2512
2513     return nro;
2514 }
2515
2516 static void
2517 _host_name_lookup_cleanup(void) {
2518 }
2519
2520 #endif /* HAVE_C_ARES */
2521
2522 const gchar *
2523 get_hostname(const guint addr)
2524 {
2525     gboolean found;
2526
2527     /* XXX why do we call this if we're not resolving? To create hash entries?
2528      * Why?
2529      */
2530     hashipv4_t *tp = host_lookup(addr, &found);
2531
2532     if (!gbl_resolv_flags.network_name)
2533         return tp->ip;
2534
2535     tp->flags = tp->flags | RESOLVED_ADDRESS_USED;
2536
2537     return tp->name;
2538 }
2539
2540 /* -------------------------- */
2541
2542 const gchar *
2543 get_hostname6(const struct e_in6_addr *addr)
2544 {
2545     gboolean found;
2546
2547     /* XXX why do we call this if we're not resolving? To create hash entries?
2548      * Why?
2549      */
2550     hashipv6_t *tp = host_lookup6(addr, &found);
2551
2552     if (!gbl_resolv_flags.network_name)
2553         return tp->ip6;
2554
2555     tp->flags = tp->flags | RESOLVED_ADDRESS_USED;
2556
2557     return tp->name;
2558 }
2559
2560 /* -------------------------- */
2561 void
2562 add_ipv4_name(const guint addr, const gchar *name)
2563 {
2564     hashipv4_t *tp;
2565
2566     /*
2567      * Don't add zero-length names; apparently, some resolvers will return
2568      * them if they get them from DNS.
2569      */
2570     if (name[0] == '\0')
2571         return;
2572
2573
2574     tp = (hashipv4_t *)g_hash_table_lookup(ipv4_hash_table, GUINT_TO_POINTER(addr));
2575     if(tp){
2576         g_strlcpy(tp->name, name, MAXNAMELEN);
2577     }else{
2578         tp = new_ipv4(addr);
2579         g_strlcpy(tp->name, name, MAXNAMELEN);
2580         g_hash_table_insert(ipv4_hash_table, GUINT_TO_POINTER(addr), tp);
2581     }
2582
2583     g_strlcpy(tp->name, name, MAXNAMELEN);
2584     tp->flags = tp->flags | TRIED_RESOLVE_ADDRESS;
2585     new_resolved_objects = TRUE;
2586
2587 } /* add_ipv4_name */
2588
2589 /* -------------------------- */
2590 void
2591 add_ipv6_name(const struct e_in6_addr *addrp, const gchar *name)
2592 {
2593     hashipv6_t *tp;
2594
2595     /*
2596      * Don't add zero-length names; apparently, some resolvers will return
2597      * them if they get them from DNS.
2598      */
2599     if (name[0] == '\0')
2600         return;
2601
2602     tp = (hashipv6_t *)g_hash_table_lookup(ipv6_hash_table, addrp);
2603     if(tp){
2604         g_strlcpy(tp->name, name, MAXNAMELEN);
2605     }else{
2606         struct e_in6_addr *addr_key;
2607
2608         addr_key = g_new(struct e_in6_addr,1);
2609         tp = new_ipv6(addrp);
2610         memcpy(addr_key, addrp, 16);
2611         g_strlcpy(tp->name, name, MAXNAMELEN);
2612         g_hash_table_insert(ipv6_hash_table, addr_key, tp);
2613     }
2614
2615     g_strlcpy(tp->name, name, MAXNAMELEN);
2616     tp->flags = tp->flags | TRIED_RESOLVE_ADDRESS;
2617     new_resolved_objects = TRUE;
2618
2619 } /* add_ipv6_name */
2620
2621 static void
2622 add_manually_resolved_ipv4(gpointer data, gpointer user_data _U_)
2623 {
2624     resolved_ipv4_t *resolved_ipv4_entry = (resolved_ipv4_t *)data;
2625
2626     add_ipv4_name(resolved_ipv4_entry->host_addr, resolved_ipv4_entry->name);
2627 }
2628
2629 static void
2630 add_manually_resolved_ipv6(gpointer data, gpointer user_data _U_)
2631 {
2632     resolved_ipv6_t *resolved_ipv6_entry = (resolved_ipv6_t *)data;
2633
2634     add_ipv6_name(&(resolved_ipv6_entry->ip6_addr), resolved_ipv6_entry->name);
2635 }
2636
2637 static void
2638 add_manually_resolved(void)
2639 {
2640     if(manually_resolved_ipv4_list){
2641         g_slist_foreach(manually_resolved_ipv4_list, add_manually_resolved_ipv4, NULL);
2642     }
2643
2644     if(manually_resolved_ipv6_list){
2645         g_slist_foreach(manually_resolved_ipv6_list, add_manually_resolved_ipv6, NULL);
2646     }
2647 }
2648
2649 void
2650 host_name_lookup_init(void)
2651 {
2652     char *hostspath;
2653     guint i;
2654
2655 #ifdef HAVE_GNU_ADNS
2656 #ifdef _WIN32
2657     char *sysroot;
2658     static char rootpath_nt[] = "\\system32\\drivers\\etc\\hosts";
2659     static char rootpath_ot[] = "\\hosts";
2660 #endif /* _WIN32 */
2661 #endif /*GNU_ADNS */
2662
2663     g_assert(ipxnet_hash_table == NULL);
2664     ipxnet_hash_table = g_hash_table_new_full(g_int_hash, g_int_equal, g_free, g_free);
2665
2666     g_assert(ipv4_hash_table == NULL);
2667     ipv4_hash_table = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, g_free);
2668
2669     g_assert(ipv6_hash_table == NULL);
2670     ipv6_hash_table = g_hash_table_new_full(ipv6_oat_hash, ipv6_equal, g_free, g_free);
2671
2672     /*
2673      * Load the global hosts file, if we have one.
2674      */
2675     if(!gbl_resolv_flags.load_hosts_file_from_profile_only){
2676         hostspath = get_datafile_path(ENAME_HOSTS);
2677         if (!read_hosts_file(hostspath) && errno != ENOENT) {
2678             report_open_failure(hostspath, errno, FALSE);
2679         }
2680         g_free(hostspath);
2681     }
2682     /*
2683      * Load the user's hosts file no matter what, if they have one.
2684      */
2685     hostspath = get_persconffile_path(ENAME_HOSTS, TRUE);
2686     if (!read_hosts_file(hostspath) && errno != ENOENT) {
2687         report_open_failure(hostspath, errno, FALSE);
2688     }
2689     g_free(hostspath);
2690 #ifdef HAVE_C_ARES
2691 #ifdef CARES_HAVE_ARES_LIBRARY_INIT
2692     if (ares_library_init(ARES_LIB_INIT_ALL) == ARES_SUCCESS) {
2693 #endif
2694         if (ares_init(&ghba_chan) == ARES_SUCCESS && ares_init(&ghbn_chan) == ARES_SUCCESS) {
2695             async_dns_initialized = TRUE;
2696         }
2697 #ifdef CARES_HAVE_ARES_LIBRARY_INIT
2698     }
2699 #endif
2700 #else
2701 #ifdef HAVE_GNU_ADNS
2702     /*
2703      * We're using GNU ADNS, which doesn't check the system hosts file;
2704      * we load that file ourselves.
2705      */
2706 #ifdef _WIN32
2707
2708     sysroot = getenv_utf8("WINDIR");
2709     if (sysroot != NULL) {
2710         /*
2711          * The file should be under WINDIR.
2712          * If this is Windows NT (NT 4.0,2K,XP,Server2K3), it's in
2713          * %WINDIR%\system32\drivers\etc\hosts.
2714          * If this is Windows OT (95,98,Me), it's in %WINDIR%\hosts.
2715          * Try both.
2716          * XXX - should we base it on the dwPlatformId value from
2717          * GetVersionEx()?
2718          */
2719         if(!gbl_resolv_flags.load_hosts_file_from_profile_only){
2720             hostspath = g_strconcat(sysroot, rootpath_nt, NULL);
2721             if (!read_hosts_file(hostspath)) {
2722                 g_free(hostspath);
2723                 hostspath = g_strconcat(sysroot, rootpath_ot, NULL);
2724                 read_hosts_file(hostspath);
2725             }
2726             g_free(hostspath);
2727         }
2728     }
2729 #else /* _WIN32 */
2730     if(!gbl_resolv_flags.load_hosts_file_from_profile_only){
2731         read_hosts_file("/etc/hosts");
2732     }
2733 #endif /* _WIN32 */
2734
2735     /* XXX - Any flags we should be using? */
2736     /* XXX - We could provide config settings for DNS servers, and
2737        pass them to ADNS with adns_init_strcfg */
2738     if (adns_init(&ads, adns_if_none, 0 /*0=>stderr*/) != 0) {
2739         /*
2740          * XXX - should we report the error?  I'm assuming that some crashes
2741          * reported on a Windows machine with TCP/IP not configured are due
2742          * to "adns_init()" failing (due to the lack of TCP/IP) and leaving
2743          * ADNS in a state where it crashes due to that.  We'll still try
2744          * doing name resolution anyway.
2745          */
2746         return;
2747     }
2748     async_dns_initialized = TRUE;
2749     async_dns_in_flight = 0;
2750 #endif /* HAVE_GNU_ADNS */
2751 #endif /* HAVE_C_ARES */
2752
2753     if(extra_hosts_files && !gbl_resolv_flags.load_hosts_file_from_profile_only){
2754         for (i = 0; i < extra_hosts_files->len; i++) {
2755             read_hosts_file((const char *) g_ptr_array_index(extra_hosts_files, i));
2756         }
2757     }
2758
2759     subnet_name_lookup_init();
2760
2761     add_manually_resolved();
2762 }
2763
2764 void
2765 host_name_lookup_cleanup(void)
2766 {
2767     _host_name_lookup_cleanup();
2768
2769     if(ipxnet_hash_table){
2770         g_hash_table_destroy(ipxnet_hash_table);
2771         ipxnet_hash_table = NULL;
2772     }
2773
2774     if(ipv4_hash_table){
2775         g_hash_table_destroy(ipv4_hash_table);
2776         ipv4_hash_table = NULL;
2777     }
2778
2779     if(ipv6_hash_table){
2780         g_hash_table_destroy(ipv6_hash_table);
2781         ipv6_hash_table = NULL;
2782     }
2783
2784     memset(subnet_length_entries, 0, sizeof(subnet_length_entries));
2785
2786     have_subnet_entry = FALSE;
2787     new_resolved_objects = FALSE;
2788 }
2789
2790 static void
2791 free_manually_resolved_ipv4(gpointer data, gpointer user_data _U_)
2792 {
2793     resolved_ipv4_t *resolved_ipv4_entry = (resolved_ipv4_t *)data;
2794
2795     g_free(resolved_ipv4_entry);
2796 }
2797
2798 static void
2799 free_manually_resolved_ipv6(gpointer data, gpointer user_data _U_)
2800 {
2801     resolved_ipv6_t *resolved_ipv6_entry = (resolved_ipv6_t *)data;
2802
2803     g_free(resolved_ipv6_entry);
2804 }
2805
2806 void
2807 manually_resolve_cleanup(void)
2808 {
2809     if(manually_resolved_ipv4_list){
2810         g_slist_foreach(manually_resolved_ipv4_list, free_manually_resolved_ipv4, NULL);
2811         g_slist_free(manually_resolved_ipv4_list);
2812         manually_resolved_ipv4_list = NULL;
2813     }
2814
2815     if(manually_resolved_ipv6_list){
2816         g_slist_foreach(manually_resolved_ipv6_list, free_manually_resolved_ipv6, NULL);
2817         g_slist_free(manually_resolved_ipv6_list);
2818         manually_resolved_ipv6_list = NULL;
2819     }
2820
2821 }
2822
2823 gchar *
2824 ep_udp_port_to_display(guint port)
2825 {
2826
2827     if (!gbl_resolv_flags.transport_name) {
2828         return ep_utoa(port);
2829     }
2830
2831     return serv_name_lookup(port, PT_UDP);
2832
2833 } /* ep_udp_port_to_display */
2834
2835 gchar *
2836 ep_dccp_port_to_display(guint port)
2837 {
2838
2839     if (!gbl_resolv_flags.transport_name) {
2840         return ep_utoa(port);
2841     }
2842
2843     return serv_name_lookup(port, PT_DCCP);
2844
2845 } /* ep_dccp_port_to_display */
2846
2847 gchar *
2848 ep_tcp_port_to_display(guint port)
2849 {
2850
2851     if (!gbl_resolv_flags.transport_name) {
2852         return ep_utoa(port);
2853     }
2854
2855     return serv_name_lookup(port, PT_TCP);
2856
2857 } /* ep_tcp_port_to_display */
2858
2859 gchar *
2860 ep_sctp_port_to_display(guint port)
2861 {
2862
2863     if (!gbl_resolv_flags.transport_name) {
2864         return ep_utoa(port);
2865     }
2866
2867     return serv_name_lookup(port, PT_SCTP);
2868
2869 } /* ep_sctp_port_to_display */
2870
2871 const gchar *
2872 ep_address_to_display(const address *addr)
2873 {
2874     const gchar *result;
2875
2876     result = solve_address_to_name(addr);
2877
2878     if (result != NULL)
2879         return result;
2880
2881     /* if it gets here, either it is of type AT_NONE, */
2882     /* or it should be solvable in address_to_str -unless addr->type is wrongly defined */
2883
2884     if (addr->type == AT_NONE){
2885         return "NONE";
2886     }
2887
2888     /* We need an ephemeral allocated string */
2889     return ep_address_to_str(addr);
2890 }
2891
2892 const gchar *
2893 get_addr_name(const address *addr)
2894 {
2895     guint32 ip4_addr;
2896     struct e_in6_addr ip6_addr;
2897
2898     /*
2899      * Try to look up a name for this address.
2900      * If it's not found, this might return a string corresponding to
2901      * the address, or it might return NULL.
2902      *
2903      * Whatever string is returned has at least session scope.
2904      */
2905     switch (addr->type) {
2906
2907     case AT_ETHER:
2908         return get_ether_name((const guint8 *)addr->data);
2909
2910     case AT_IPv4:
2911         memcpy(&ip4_addr, addr->data, sizeof ip4_addr);
2912         return get_hostname(ip4_addr);
2913
2914     case AT_IPv6:
2915         memcpy(&ip6_addr.bytes, addr->data, sizeof ip6_addr.bytes);
2916         return get_hostname6(&ip6_addr);
2917
2918     default:
2919         return NULL;
2920     }
2921 }
2922
2923 void
2924 get_addr_name_buf(const address *addr, gchar *buf, gsize size)
2925 {
2926     const gchar *result = ep_address_to_display(addr);
2927
2928     g_strlcpy(buf, result, size);
2929 } /* get_addr_name_buf */
2930
2931
2932 gchar *
2933 get_ether_name(const guint8 *addr)
2934 {
2935     hashether_t *tp;
2936     gboolean resolve = gbl_resolv_flags.mac_name;
2937
2938     tp = eth_name_lookup(addr, resolve);
2939
2940     return resolve ? tp->resolved_name : tp->hexaddr;
2941
2942 } /* get_ether_name */
2943
2944 /* Look for a (non-dummy) ether name in the hash, and return it if found.
2945  * If it's not found, simply return NULL.
2946  */
2947 gchar *
2948 get_ether_name_if_known(const guint8 *addr)
2949 {
2950     hashether_t *tp;
2951
2952     /* Initialize ether structs if we're the first
2953      * ether-related function called */
2954     if (!gbl_resolv_flags.mac_name)
2955         return NULL;
2956
2957     /* eth_name_lookup will create a (resolved) hash entry if it doesn't exist */
2958     tp = eth_name_lookup(addr, TRUE);
2959     g_assert(tp != NULL);
2960
2961     if (tp->status == HASHETHER_STATUS_RESOLVED_NAME) {
2962         /* Name is from an ethers file (or is a "well-known" MAC address name from the manuf file) */
2963         return tp->resolved_name;
2964     }
2965     else {
2966         /* Name was created */
2967         return NULL;
2968     }
2969 }
2970
2971 guint8 *
2972 get_ether_addr(const gchar *name)
2973 {
2974
2975     /* force resolution (do not check gbl_resolv_flags) */
2976     return eth_addr_lookup(name);
2977
2978 } /* get_ether_addr */
2979
2980 void
2981 add_ether_byip(const guint ip, const guint8 *eth)
2982 {
2983     gboolean found;
2984     hashipv4_t *tp;
2985
2986     /* first check that IP address can be resolved */
2987     if (!gbl_resolv_flags.network_name)
2988         return;
2989
2990     tp = host_lookup(ip, &found);
2991     if (found) {
2992         /* ok, we can add this entry in the ethers hashtable */
2993         add_eth_name(eth, tp->name);
2994     }
2995
2996 } /* add_ether_byip */
2997
2998 const gchar *
2999 get_ipxnet_name(const guint32 addr)
3000 {
3001
3002     if (!gbl_resolv_flags.network_name) {
3003         return ipxnet_to_str_punct(addr, '\0');
3004     }
3005
3006     return ipxnet_name_lookup(addr);
3007
3008 } /* get_ipxnet_name */
3009
3010 guint32
3011 get_ipxnet_addr(const gchar *name, gboolean *known)
3012 {
3013     guint32 addr;
3014     gboolean success;
3015
3016     /* force resolution (do not check gbl_resolv_flags) */
3017     addr =  ipxnet_addr_lookup(name, &success);
3018
3019     *known = success;
3020     return addr;
3021
3022 } /* get_ipxnet_addr */
3023
3024 const gchar *
3025 get_manuf_name(const guint8 *addr)
3026 {
3027     gchar *cur;
3028     int manuf_key;
3029     guint8 oct;
3030
3031     /* manuf needs only the 3 most significant octets of the ethernet address */
3032     manuf_key = addr[0];
3033     manuf_key = manuf_key<<8;
3034     oct = addr[1];
3035     manuf_key = manuf_key | oct;
3036     manuf_key = manuf_key<<8;
3037     oct = addr[2];
3038     manuf_key = manuf_key | oct;
3039
3040     if (!gbl_resolv_flags.mac_name || ((cur = (gchar *)g_hash_table_lookup(manuf_hashtable, &manuf_key)) == NULL)) {
3041         cur=ep_strdup_printf("%02x:%02x:%02x", addr[0], addr[1], addr[2]);
3042         return cur;
3043     }
3044
3045     return cur;
3046
3047 } /* get_manuf_name */
3048
3049 const gchar *
3050 uint_get_manuf_name(const guint oid)
3051 {
3052     guint8 addr[3];
3053
3054     addr[0] = (oid >> 16) & 0xFF;
3055     addr[1] = (oid >> 8) & 0xFF;
3056     addr[2] = (oid >> 0) & 0xFF;
3057     return get_manuf_name(addr);
3058 }
3059
3060 const gchar *
3061 tvb_get_manuf_name(tvbuff_t *tvb, gint offset)
3062 {
3063     return get_manuf_name(tvb_get_ptr(tvb, offset, 3));
3064 }
3065
3066 const gchar *
3067 get_manuf_name_if_known(const guint8 *addr)
3068 {
3069     gchar  *cur;
3070     int manuf_key;
3071     guint8 oct;
3072
3073     /* manuf needs only the 3 most significant octets of the ethernet address */
3074     manuf_key = addr[0];
3075     manuf_key = manuf_key<<8;
3076     oct = addr[1];
3077     manuf_key = manuf_key | oct;
3078     manuf_key = manuf_key<<8;
3079     oct = addr[2];
3080     manuf_key = manuf_key | oct;
3081
3082     if ((cur = (gchar *)g_hash_table_lookup(manuf_hashtable, &manuf_key)) == NULL) {
3083         return NULL;
3084     }
3085
3086     return cur;
3087
3088 } /* get_manuf_name_if_known */
3089
3090 const gchar *
3091 uint_get_manuf_name_if_known(const guint manuf_key)
3092 {
3093     gchar  *cur;
3094
3095     if ((cur = (gchar *)g_hash_table_lookup(manuf_hashtable, &manuf_key)) == NULL) {
3096         return NULL;
3097     }
3098
3099     return cur;
3100 }
3101
3102 const gchar *
3103 tvb_get_manuf_name_if_known(tvbuff_t *tvb, gint offset)
3104 {
3105     return get_manuf_name_if_known(tvb_get_ptr(tvb, offset, 3));
3106 }
3107
3108 const gchar *
3109 ep_eui64_to_display(const guint64 addr_eui64)
3110 {
3111     gchar *cur, *name;
3112     guint8 *addr = (guint8 *)ep_alloc(8);
3113
3114     /* Copy and convert the address to network byte order. */
3115     *(guint64 *)(void *)(addr) = pntoh64(&(addr_eui64));
3116
3117     if (!gbl_resolv_flags.mac_name || ((name = manuf_name_lookup(addr)) == NULL)) {
3118         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]);
3119         return cur;
3120     }
3121     cur=ep_strdup_printf("%s_%02x:%02x:%02x:%02x:%02x", name, addr[3], addr[4], addr[5], addr[6], addr[7]);
3122     return cur;
3123
3124 } /* ep_eui64_to_display */
3125
3126
3127 const gchar *
3128 ep_eui64_to_display_if_known(const guint64 addr_eui64)
3129 {
3130     gchar *cur, *name;
3131     guint8 *addr = (guint8 *)ep_alloc(8);
3132
3133     /* Copy and convert the address to network byte order. */
3134     *(guint64 *)(void *)(addr) = pntoh64(&(addr_eui64));
3135
3136     if ((name = manuf_name_lookup(addr)) == NULL) {
3137         return NULL;
3138     }
3139
3140     cur=ep_strdup_printf("%s_%02x:%02x:%02x:%02x:%02x", name, addr[3], addr[4], addr[5], addr[6], addr[7]);
3141     return cur;
3142
3143 } /* ep_eui64_to_display_if_known */
3144
3145 #ifdef HAVE_C_ARES
3146 #define GHI_TIMEOUT (250 * 1000)
3147 static void
3148 c_ares_ghi_cb(
3149         void *arg,
3150         int status,
3151 #if ( ( ARES_VERSION_MAJOR < 1 )                                     \
3152     || ( 1 == ARES_VERSION_MAJOR && ARES_VERSION_MINOR < 5 ) )
3153         struct hostent *hp
3154 #else
3155         int timeouts _U_,
3156         struct hostent *hp
3157 #endif
3158         ) {
3159
3160     /*
3161      * XXX - If we wanted to be really fancy we could cache results here and
3162      * look them up in get_host_ipaddr* below.
3163      */
3164     async_hostent_t *ahp = (async_hostent_t *)arg;
3165     if (status == ARES_SUCCESS && hp && ahp && hp->h_length == ahp->addr_size) {
3166         memcpy(ahp->addrp, hp->h_addr, hp->h_length);
3167         ahp->copied = hp->h_length;
3168     }
3169 }
3170 #endif /* HAVE_C_ARES */
3171
3172 /* Translate a string, assumed either to be a dotted-quad IP address or
3173  * a host name, to a numeric IP address.  Return TRUE if we succeed and
3174  * set "*addrp" to that numeric IP address; return FALSE if we fail.
3175  * Used more in the dfilter parser rather than in packet dissectors */
3176 gboolean
3177 get_host_ipaddr(const char *host, guint32 *addrp)
3178 {
3179     struct in_addr      ipaddr;
3180 #ifdef HAVE_C_ARES
3181     struct timeval tv = { 0, GHI_TIMEOUT }, *tvp;
3182     int nfds;
3183     fd_set rfds, wfds;
3184     async_hostent_t ahe;
3185 #else /* HAVE_C_ARES */
3186     struct hostent      *hp;
3187 #endif /* HAVE_C_ARES */
3188
3189     /*
3190      * don't change it to inet_pton(AF_INET), they are not 100% compatible.
3191      * inet_pton(AF_INET) does not support hexadecimal notation nor
3192      * less-than-4 octet notation.
3193      */
3194     if (!inet_aton(host, &ipaddr)) {
3195
3196         /* It's not a valid dotted-quad IP address; is it a valid
3197          * host name?
3198          */
3199
3200         /* If we're not allowed to do name resolution, don't do name
3201          * resolution...
3202          */
3203         if (!gbl_resolv_flags.network_name ||
3204                 !gbl_resolv_flags.use_external_net_name_resolver) {
3205             return FALSE;
3206         }
3207
3208 #ifdef HAVE_C_ARES
3209         if (! (gbl_resolv_flags.concurrent_dns) ||
3210                 name_resolve_concurrency < 1 ||
3211                 ! async_dns_initialized) {
3212             return FALSE;
3213         }
3214         ahe.addr_size = (int) sizeof (struct in_addr);
3215         ahe.copied = 0;
3216         ahe.addrp = addrp;
3217         ares_gethostbyname(ghbn_chan, host, AF_INET, c_ares_ghi_cb, &ahe);
3218         FD_ZERO(&rfds);
3219         FD_ZERO(&wfds);
3220         nfds = ares_fds(ghbn_chan, &rfds, &wfds);
3221         if (nfds > 0) {
3222             tvp = ares_timeout(ghbn_chan, &tv, &tv);
3223             if (select(nfds, &rfds, &wfds, NULL, tvp) == -1) { /* call to select() failed */
3224                 fprintf(stderr, "Warning: call to select() failed, error is %s\n", strerror(errno));
3225                 return FALSE;
3226             }
3227             ares_process(ghbn_chan, &rfds, &wfds);
3228         }
3229         ares_cancel(ghbn_chan);
3230         if (ahe.addr_size == ahe.copied) {
3231             return TRUE;
3232         }
3233         return FALSE;
3234 #else /* ! HAVE_C_ARES */
3235         hp = gethostbyname(host);
3236         if (hp == NULL) {
3237             /* No. */
3238             return FALSE;
3239             /* Apparently, some versions of gethostbyaddr can
3240              * return IPv6 addresses. */
3241         } else if (hp->h_length <= (int) sizeof (struct in_addr)) {
3242             memcpy(&ipaddr, hp->h_addr, hp->h_length);
3243         } else {
3244             return FALSE;
3245         }
3246 #endif /* HAVE_C_ARES */
3247     } else {
3248         /* Does the string really contain dotted-quad IP?
3249          * Check against inet_atons that accept strings such as
3250          * "130.230" as valid addresses and try to convert them
3251          * to some form of a classful (host.net) notation.
3252          */
3253         unsigned int a0, a1, a2, a3;
3254         if (sscanf(host, "%u.%u.%u.%u", &a0, &a1, &a2, &a3) != 4)
3255             return FALSE;
3256     }
3257
3258     *addrp = ipaddr.s_addr;
3259     return TRUE;
3260 }
3261
3262 /*
3263  * Translate IPv6 numeric address or FQDN hostname, into binary IPv6 address.
3264  * Return TRUE if we succeed and set "*addrp" to that numeric IP address;
3265  * return FALSE if we fail.
3266  */
3267 gboolean
3268 get_host_ipaddr6(const char *host, struct e_in6_addr *addrp)
3269 {
3270 #ifdef HAVE_C_ARES
3271     struct timeval tv = { 0, GHI_TIMEOUT }, *tvp;
3272     int nfds;
3273     fd_set rfds, wfds;
3274     async_hostent_t ahe;
3275 #elif defined(HAVE_GETHOSTBYNAME2)
3276     struct hostent *hp;
3277 #endif /* HAVE_C_ARES */
3278
3279     if (str_to_ip6(host, addrp))
3280         return TRUE;
3281
3282     /* It's not a valid dotted-quad IP address; is it a valid
3283      * host name?
3284      */
3285
3286     /* If we're not allowed to do name resolution, don't do name
3287      * resolution...
3288      */
3289     if (!gbl_resolv_flags.network_name ||
3290             !gbl_resolv_flags.use_external_net_name_resolver) {
3291         return FALSE;
3292     }
3293
3294     /* try FQDN */
3295 #ifdef HAVE_C_ARES
3296     if (! (gbl_resolv_flags.concurrent_dns) ||
3297             name_resolve_concurrency < 1 ||
3298             ! async_dns_initialized) {
3299         return FALSE;
3300     }
3301     ahe.addr_size = (int) sizeof (struct e_in6_addr);
3302     ahe.copied = 0;
3303     ahe.addrp = addrp;
3304     ares_gethostbyname(ghbn_chan, host, AF_INET6, c_ares_ghi_cb, &ahe);
3305     FD_ZERO(&rfds);
3306     FD_ZERO(&wfds);
3307     nfds = ares_fds(ghbn_chan, &rfds, &wfds);
3308     if (nfds > 0) {
3309         tvp = ares_timeout(ghbn_chan, &tv, &tv);
3310         if (select(nfds, &rfds, &wfds, NULL, tvp) == -1) { /* call to select() failed */
3311             fprintf(stderr, "Warning: call to select() failed, error is %s\n", strerror(errno));
3312             return FALSE;
3313         }
3314         ares_process(ghbn_chan, &rfds, &wfds);
3315     }
3316     ares_cancel(ghbn_chan);
3317     if (ahe.addr_size == ahe.copied) {
3318         return TRUE;
3319     }
3320 #elif defined(HAVE_GETHOSTBYNAME2)
3321     hp = gethostbyname2(host, AF_INET6);
3322     if (hp != NULL && hp->h_length == sizeof(struct e_in6_addr)) {
3323         memcpy(addrp, hp->h_addr, hp->h_length);
3324         return TRUE;
3325     }
3326 #endif
3327
3328     return FALSE;
3329 }
3330
3331 /*
3332  * Find out whether a hostname resolves to an ip or ipv6 address
3333  * Return "ip6" if it is IPv6, "ip" otherwise (including the case
3334  * that we don't know)
3335  */
3336 const char* host_ip_af(const char *host
3337 #ifndef HAVE_GETHOSTBYNAME2
3338         _U_
3339 #endif
3340         )
3341 {
3342 #ifdef HAVE_GETHOSTBYNAME2
3343     struct hostent *h;
3344     return (h = gethostbyname2(host, AF_INET6)) && h->h_addrtype == AF_INET6 ? "ip6" : "ip";
3345 #else
3346     return "ip";
3347 #endif
3348 }
3349
3350 GHashTable *
3351 get_manuf_hashtable(void)
3352 {
3353     return manuf_hashtable;
3354 }
3355
3356 GHashTable *
3357 get_wka_hashtable(void)
3358 {
3359     return wka_hashtable;
3360 }
3361
3362 GHashTable *
3363 get_eth_hashtable(void)
3364 {
3365     return eth_hashtable;
3366 }
3367
3368 GHashTable *
3369 get_serv_port_hashtable(void)
3370 {
3371     return serv_port_hashtable;
3372 }
3373
3374 GHashTable *
3375 get_ipxnet_hash_table(void)
3376 {
3377         return ipxnet_hash_table;
3378 }
3379
3380 GHashTable *
3381 get_ipv4_hash_table(void)
3382 {
3383         return ipv4_hash_table;
3384 }
3385
3386 GHashTable *
3387 get_ipv6_hash_table(void)
3388 {
3389         return ipv6_hash_table;
3390 }
3391 /* Initialize all the address resolution subsystems in this file */
3392 void
3393 addr_resolv_init(void)
3394 {
3395     initialize_services();
3396     initialize_ethers();
3397     initialize_ipxnets();
3398     /* host name initialization is done on a per-capture-file basis */
3399     /*host_name_lookup_init();*/
3400 }
3401
3402 /* Clean up all the address resolution subsystems in this file */
3403 void
3404 addr_resolv_cleanup(void)
3405 {
3406     service_name_lookup_cleanup();
3407     eth_name_lookup_cleanup();
3408     ipx_name_lookup_cleanup();
3409     /* host name initialization is done on a per-capture-file basis */
3410     /*host_name_lookup_cleanup();*/
3411 }
3412
3413 gboolean
3414 str_to_ip(const char *str, void *dst)
3415 {
3416     return inet_pton(AF_INET, str, dst) > 0;
3417 }
3418
3419 gboolean
3420 str_to_ip6(const char *str, void *dst)
3421 {
3422     return inet_pton(AF_INET6, str, dst) > 0;
3423 }
3424
3425 /*
3426  * Editor modelines  -  http://www.wireshark.org/tools/modelines.html
3427  *
3428  * Local variables:
3429  * c-basic-offset: 4
3430  * tab-width: 8
3431  * indent-tabs-mode: nil
3432  * End:
3433  *
3434  * vi: set shiftwidth=4 tabstop=8 expandtab:
3435  * :indentSize=4:tabSize=8:noTabs=true:
3436  */