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