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