Move prefs.c and prefs.h into the epan subdirectory.
[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  * Ethereal - Network traffic analyzer
9  * By Gerald Combs <gerald@ethereal.com>
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
36 /*
37  * Win32 doesn't have SIGALRM.
38  *
39  * Mac OS X does, but if you longjmp() out of a name resolution call in
40  * a signal handler, you might crash, because the state of the resolution
41  * code that sends messages to lookupd might be inconsistent if you jump
42  * out of it in middle of a call.
43  *
44  * There's no guarantee that longjmp()ing out of name resolution calls
45  * will work on *any* platform; OpenBSD got rid of the alarm/longjmp
46  * code in tcpdump, to avoid those sorts of problems, and that was
47  * picked up by tcpdump.org tcpdump.
48  */
49 #if !defined(_WIN32) && !defined(__APPLE__)
50 #ifndef AVOID_DNS_TIMEOUT
51 #define AVOID_DNS_TIMEOUT
52 #endif
53 #endif
54
55 #ifdef HAVE_UNISTD_H
56 #include <unistd.h>
57 #endif
58
59 #ifdef HAVE_NETINET_IN_H
60 # include <netinet/in.h>
61 #endif
62
63 #ifdef HAVE_NETDB_H
64 #include <netdb.h>
65 #endif
66
67 #ifdef HAVE_ARPA_INET_H
68 #include <arpa/inet.h>
69 #endif
70
71 #include <signal.h>
72
73 #ifdef HAVE_SYS_SOCKET_H
74 #include <sys/socket.h>         /* needed to define AF_ values on UNIX */
75 #endif
76
77 #ifdef HAVE_WINSOCK2_H
78 #include <winsock2.h>           /* needed to define AF_ values on Windows */
79 #endif
80
81 #ifdef AVOID_DNS_TIMEOUT
82 # include <setjmp.h>
83 #endif
84
85 #ifdef NEED_INET_ATON_H
86 # include "inet_aton.h"
87 #endif
88
89 #ifdef NEED_INET_V6DEFS_H
90 # include "inet_v6defs.h"
91 #endif
92
93 #ifdef HAVE_GNU_ADNS
94 # include <errno.h>
95 # include <adns.h>
96 #endif
97
98 #if defined(_WIN32) && defined(INET6)
99 # include <ws2tcpip.h>
100 #endif
101
102 #include "packet.h"
103 #include "ipv6-utils.h"
104 #include "addr_resolv.h"
105 #include "filesystem.h"
106 #include <epan/prefs.h>
107
108 #define ENAME_ETHERS            "ethers"
109 #define ENAME_IPXNETS           "ipxnets"
110 #define ENAME_MANUF             "manuf"
111
112 #define MAXMANUFLEN     9       /* max vendor name length with ending '\0' */
113 #define HASHETHSIZE     1024
114 #define HASHHOSTSIZE    1024
115 #define HASHIPXNETSIZE  256
116 #define HASHMANUFSIZE   256
117 #define HASHPORTSIZE    256
118
119 /* hash table used for host and port lookup */
120
121 #define HASH_IPV4_ADDRESS(addr) ((addr) & (HASHHOSTSIZE - 1))
122
123 #define HASH_PORT(port) ((port) & (HASHPORTSIZE - 1))
124
125 typedef struct hashname {
126   guint                 addr;
127   gchar                 name[MAXNAMELEN];
128   gboolean              is_dummy_entry; /* name is IP address in dot format */
129   struct hashname       *next;
130 } hashname_t;
131
132 /* hash table used for IPX network lookup */
133
134 /* XXX - check goodness of hash function */
135
136 #define HASH_IPX_NET(net)       ((net) & (HASHIPXNETSIZE - 1))
137
138 typedef struct hashname hashipxnet_t;
139
140 /* hash tables used for ethernet and manufacturer lookup */
141
142 #define HASH_ETH_ADDRESS(addr) \
143         (((((addr)[2] << 8) | (addr)[3]) ^ (((addr)[4] << 8) | (addr)[5])) & \
144          (HASHETHSIZE - 1))
145
146 #define HASH_ETH_MANUF(addr) (((int)(addr)[2]) & (HASHMANUFSIZE - 1))
147
148 typedef struct hashmanuf {
149   guint8                addr[3];
150   char                  name[MAXMANUFLEN];
151   struct hashmanuf      *next;
152 } hashmanuf_t;
153
154 typedef struct hashether {
155   guint8                addr[6];
156   char                  name[MAXNAMELEN];
157   gboolean              is_dummy_entry;         /* not a complete entry */
158   struct hashether      *next;
159 } hashether_t;
160
161 /* internal ethernet type */
162
163 typedef struct _ether
164 {
165   guint8                addr[6];
166   char                  name[MAXNAMELEN];
167 } ether_t;
168
169 /* internal ipxnet type */
170
171 typedef struct _ipxnet
172 {
173   guint                 addr;
174   char                  name[MAXNAMELEN];
175 } ipxnet_t;
176
177 static hashname_t       *host_table[HASHHOSTSIZE];
178 static hashname_t       *udp_port_table[HASHPORTSIZE];
179 static hashname_t       *tcp_port_table[HASHPORTSIZE];
180 static hashname_t       *sctp_port_table[HASHPORTSIZE];
181 static hashether_t      *eth_table[HASHETHSIZE];
182 static hashmanuf_t      *manuf_table[HASHMANUFSIZE];
183 static hashether_t      *(*wka_table[48])[HASHETHSIZE];
184 static hashipxnet_t     *ipxnet_table[HASHIPXNETSIZE];
185
186 static int              eth_resolution_initialized = 0;
187 static int              ipxnet_resolution_initialized = 0;
188
189 static hashether_t *add_eth_name(const guint8 *addr, const gchar *name);
190
191 /*
192  * Flag controlling what names to resolve.
193  */
194 guint32 g_resolv_flags;
195
196 /*
197  *  Global variables (can be changed in GUI sections)
198  *  XXX - they could be changed in GUI code, but there's currently no
199  *  GUI code to change them.
200  */
201
202 gchar *g_ethers_path  = NULL;           /* global ethers file    */
203 gchar *g_pethers_path = NULL;           /* personal ethers file  */
204 gchar *g_ipxnets_path  = NULL;          /* global ipxnets file   */
205 gchar *g_pipxnets_path = NULL;          /* personal ipxnets file */
206                                         /* first resolving call  */
207
208 /* GNU ADNS */
209
210 #ifdef HAVE_GNU_ADNS
211
212 adns_state ads;
213
214 int adns_currently_queued = 0;
215
216 typedef struct _adns_queue_msg
217 {
218   gboolean          submitted;
219   guint32           ip4_addr;
220   struct e_in6_addr ip6_addr;
221   int               type;
222   adns_query        query;
223 } adns_queue_msg_t;
224
225 GList *adns_queue_head = NULL;
226
227 #endif /* HAVE_GNU_ADNS */
228
229 /*
230  *  Local function definitions
231  */
232
233 static gchar *serv_name_lookup(guint port, port_type proto)
234 {
235   int hash_idx;
236   hashname_t *tp;
237   hashname_t **table;
238   char *serv_proto = NULL;
239   struct servent *servp;
240
241   switch(proto) {
242   case PT_UDP:
243     table = udp_port_table;
244     serv_proto = "udp";
245     break;
246   case PT_TCP:
247     table = tcp_port_table;
248     serv_proto = "tcp";
249     break;
250   case PT_SCTP:
251     table = sctp_port_table;
252     serv_proto = "sctp";
253     break;
254   default:
255     /* not yet implemented */
256     return NULL;
257     /*NOTREACHED*/
258     break;
259   } /* proto */
260
261   hash_idx = HASH_PORT(port);
262   tp = table[hash_idx];
263
264   if( tp == NULL ) {
265     tp = table[hash_idx] = (hashname_t *)g_malloc(sizeof(hashname_t));
266   } else {
267     while(1) {
268       if( tp->addr == port ) {
269         return tp->name;
270       }
271       if (tp->next == NULL) {
272         tp->next = (hashname_t *)g_malloc(sizeof(hashname_t));
273         tp = tp->next;
274         break;
275       }
276       tp = tp->next;
277     }
278   }
279
280   /* fill in a new entry */
281   tp->addr = port;
282   tp->next = NULL;
283
284   if (!(g_resolv_flags & RESOLV_TRANSPORT) ||
285       (servp = getservbyport(g_htons(port), serv_proto)) == NULL) {
286     /* unknown port */
287     sprintf(tp->name, "%d", port);
288   } else {
289     strncpy(tp->name, servp->s_name, MAXNAMELEN);
290     tp->name[MAXNAMELEN-1] = '\0';
291   }
292
293   return (tp->name);
294
295 } /* serv_name_lookup */
296
297
298 #ifdef AVOID_DNS_TIMEOUT
299
300 #define DNS_TIMEOUT     2       /* max sec per call */
301
302 jmp_buf hostname_env;
303
304 static void abort_network_query(int sig _U_)
305 {
306   longjmp(hostname_env, 1);
307 }
308 #endif /* AVOID_DNS_TIMEOUT */
309
310 static gchar *host_name_lookup(guint addr, gboolean *found)
311 {
312   int hash_idx;
313   hashname_t * volatile tp;
314   struct hostent *hostp;
315 #ifdef HAVE_GNU_ADNS
316   adns_queue_msg_t *qmsg;
317 #endif
318
319   *found = TRUE;
320
321   hash_idx = HASH_IPV4_ADDRESS(addr);
322
323   tp = host_table[hash_idx];
324
325   if( tp == NULL ) {
326     tp = host_table[hash_idx] = (hashname_t *)g_malloc(sizeof(hashname_t));
327   } else {
328     while(1) {
329       if( tp->addr == addr ) {
330         if (tp->is_dummy_entry)
331           *found = FALSE;
332         return tp->name;
333       }
334       if (tp->next == NULL) {
335         tp->next = (hashname_t *)g_malloc(sizeof(hashname_t));
336         tp = tp->next;
337         break;
338       }
339       tp = tp->next;
340     }
341   }
342
343   /* fill in a new entry */
344   tp->addr = addr;
345   tp->next = NULL;
346
347 #ifdef HAVE_GNU_ADNS
348   if ((g_resolv_flags & RESOLV_CONCURRENT) && 
349       prefs.name_resolve_concurrency > 0) {
350     qmsg = g_malloc(sizeof(adns_queue_msg_t));
351     qmsg->type = AF_INET;
352     qmsg->ip4_addr = addr;
353     qmsg->submitted = FALSE;
354     adns_queue_head = g_list_append(adns_queue_head, (gpointer) qmsg);
355
356     tp->is_dummy_entry = TRUE;
357     ip_to_str_buf((guint8 *)&addr, tp->name);
358     return tp->name;
359   }
360 #endif /* HAVE_GNU_ADNS */
361
362   /*
363    * The Windows "gethostbyaddr()" insists on translating 0.0.0.0 to
364    * the name of the host on which it's running; to work around that
365    * botch, we don't try to translate an all-zero IP address to a host
366    * name.
367    */
368   if (addr != 0 && (g_resolv_flags & RESOLV_NETWORK)) {
369   /* Use async DNS if possible, else fall back to timeouts,
370    * else call gethostbyaddr and hope for the best
371    */
372
373 # ifdef AVOID_DNS_TIMEOUT
374
375     /* Quick hack to avoid DNS/YP timeout */
376
377     if (!setjmp(hostname_env)) {
378       signal(SIGALRM, abort_network_query);
379       alarm(DNS_TIMEOUT);
380 # endif /* AVOID_DNS_TIMEOUT */
381
382       hostp = gethostbyaddr((char *)&addr, 4, AF_INET);
383
384 # ifdef AVOID_DNS_TIMEOUT
385       alarm(0);
386 # endif /* AVOID_DNS_TIMEOUT */
387
388       if (hostp != NULL) {
389         strncpy(tp->name, hostp->h_name, MAXNAMELEN);
390         tp->name[MAXNAMELEN-1] = '\0';
391         tp->is_dummy_entry = FALSE;
392         return tp->name;
393       }
394
395 # ifdef AVOID_DNS_TIMEOUT
396     }
397 # endif /* AVOID_DNS_TIMEOUT */
398
399   }
400
401   /* unknown host or DNS timeout */
402
403   ip_to_str_buf((guint8 *)&addr, tp->name);
404   tp->is_dummy_entry = TRUE;
405   *found = FALSE;
406
407   return (tp->name);
408
409 } /* host_name_lookup */
410
411 static gchar *host_name_lookup6(struct e_in6_addr *addr, gboolean *found)
412 {
413   static gchar name[MAXNAMELEN];
414 #ifdef INET6
415   struct hostent *hostp;
416
417   if (g_resolv_flags & RESOLV_NETWORK) {
418 #ifdef AVOID_DNS_TIMEOUT
419
420     /* Quick hack to avoid DNS/YP timeout */
421
422     if (!setjmp(hostname_env)) {
423       signal(SIGALRM, abort_network_query);
424       alarm(DNS_TIMEOUT);
425 #endif /* AVOID_DNS_TIMEOUT */
426       hostp = gethostbyaddr((char *)addr, sizeof(*addr), AF_INET6);
427 #ifdef AVOID_DNS_TIMEOUT
428       alarm(0);
429 #endif
430       if (hostp != NULL) {
431         strncpy(name, hostp->h_name, MAXNAMELEN);
432         name[MAXNAMELEN-1] = '\0';
433         *found = TRUE;
434         return name;
435       }
436 #ifdef AVOID_DNS_TIMEOUT
437     }
438 #endif
439   }
440
441   /* unknown host or DNS timeout */
442 #endif /* INET6 */
443   *found = FALSE;
444   ip6_to_str_buf(addr, name);
445   return (name);
446 }
447
448 /*
449  *  Miscellaneous functions
450  */
451
452 static int fgetline(char **buf, int *size, FILE *fp)
453 {
454   int len;
455   int c;
456
457   if (fp == NULL)
458     return -1;
459
460   if (*buf == NULL) {
461     if (*size == 0)
462       *size = BUFSIZ;
463
464     if ((*buf = g_malloc(*size)) == NULL)
465       return -1;
466   }
467
468   if (feof(fp))
469     return -1;
470
471   len = 0;
472   while ((c = getc(fp)) != EOF && c != '\n') {
473     if (len+1 >= *size) {
474       if ((*buf = g_realloc(*buf, *size += BUFSIZ)) == NULL)
475         return -1;
476     }
477     (*buf)[len++] = c;
478   }
479
480   if (len == 0 && c == EOF)
481     return -1;
482
483   (*buf)[len] = '\0';
484
485   return len;
486
487 } /* fgetline */
488
489
490 /*
491  * Ethernet / manufacturer resolution
492  *
493  * The following functions implement ethernet address resolution and
494  * ethers files parsing (see ethers(4)).
495  *
496  * The manuf file has the same format as ethers(4) except that names are
497  * truncated to MAXMANUFLEN-1 characters and that an address contains
498  * only 3 bytes (instead of 6).
499  *
500  * Notes:
501  *
502  * I decide to not use the existing functions (see ethers(3) on some
503  * operating systems) for the following reasons:
504  * - performance gains (use of hash tables and some other enhancements),
505  * - use of two ethers files (system-wide and per user),
506  * - avoid the use of NIS maps,
507  * - lack of these functions on some systems.
508  *
509  * So the following functions do _not_ behave as the standard ones.
510  *
511  * -- Laurent.
512  */
513
514
515 /*
516  * If "manuf_file" is FALSE, parse a 6-byte MAC address.
517  * If "manuf_file" is TRUE, parse an up-to-6-byte sequence with an optional
518  * mask.
519  */
520 static gboolean
521 parse_ether_address(const char *cp, ether_t *eth, unsigned int *mask,
522                     gboolean manuf_file)
523 {
524   int i;
525   unsigned long num;
526   char *p;
527   char sep = '\0';
528
529   for (i = 0; i < 6; i++) {
530     /* Get a hex number, 1 or 2 digits, no sign characters allowed. */
531     if (!isxdigit((unsigned char)*cp))
532       return FALSE;
533     num = strtoul(cp, &p, 16);
534     if (p == cp)
535       return FALSE;     /* failed */
536     if (num > 0xFF)
537       return FALSE;     /* not a valid octet */
538     eth->addr[i] = (guint8) num;
539     cp = p;             /* skip past the number */
540
541     /* OK, what character terminated the octet? */
542     if (*cp == '/') {
543       /* "/" - this has a mask. */
544       if (!manuf_file) {
545         /* Entries with masks are allowed only in the "manuf" files. */
546         return FALSE;
547       }
548       cp++;     /* skip past the '/' to get to the mask */
549       if (!isdigit((unsigned char)*cp))
550         return FALSE;   /* no sign allowed */
551       num = strtoul(cp, &p, 10);
552       if (p == cp)
553         return FALSE;   /* failed */
554       cp = p;   /* skip past the number */
555       if (*cp != '\0' && !isspace((unsigned char)*cp))
556         return FALSE;   /* bogus terminator */
557       if (num == 0 || num >= 48)
558         return FALSE;   /* bogus mask */
559       /* Mask out the bits not covered by the mask */
560       *mask = num;
561       for (i = 0; num >= 8; i++, num -= 8)
562         ;       /* skip octets entirely covered by the mask */
563       /* Mask out the first masked octet */
564       eth->addr[i] &= (0xFF << (8 - num));
565       i++;
566       /* Mask out completely-masked-out octets */
567       for (; i < 6; i++)
568         eth->addr[i] = 0;
569       return TRUE;
570     }
571     if (*cp == '\0') {
572       /* We're at the end of the address, and there's no mask. */
573       if (i == 2) {
574         /* We got 3 bytes, so this is a manufacturer ID. */
575         if (!manuf_file) {
576           /* Manufacturer IDs are only allowed in the "manuf"
577              files. */
578           return FALSE;
579         }
580         /* Indicate that this is a manufacturer ID (0 is not allowed
581            as a mask). */
582         *mask = 0;
583         return TRUE;
584       }
585
586       if (i == 5) {
587         /* We got 6 bytes, so this is a MAC address.
588            If we're reading one of the "manuf" files, indicate that
589            this is a MAC address (48 is not allowed as a mask). */
590         if (manuf_file)
591           *mask = 48;
592         return TRUE;
593       }
594
595       /* We didn't get 3 or 6 bytes, and there's no mask; this is
596          illegal. */
597       return FALSE;
598     } else {
599       if (sep == '\0') {
600         /* We don't know the separator used in this number; it can either
601            be ':', '-', or '.'. */
602         if (*cp != ':' && *cp != '-' && *cp != '.')
603           return FALSE;
604         sep = *cp;      /* subsequent separators must be the same */
605       } else {
606           /* It has to be the same as the first separator */
607           if (*cp != sep)
608             return FALSE;
609       }
610     }
611     cp++;
612   }
613
614   return TRUE;
615 }
616
617 static int parse_ether_line(char *line, ether_t *eth, unsigned int *mask,
618                             gboolean manuf_file)
619 {
620   /*
621    *  See man ethers(4) for ethers file format
622    *  (not available on all systems).
623    *  We allow both ethernet address separators (':' and '-'),
624    *  as well as Ethereal's '.' separator.
625    */
626
627   gchar *cp;
628
629   if ((cp = strchr(line, '#')))
630     *cp = '\0';
631
632   if ((cp = strtok(line, " \t\n")) == NULL)
633     return -1;
634
635   if (!parse_ether_address(cp, eth, mask, manuf_file))
636     return -1;
637
638   if ((cp = strtok(NULL, " \t\n")) == NULL)
639     return -1;
640
641   strncpy(eth->name, cp, MAXNAMELEN);
642   eth->name[MAXNAMELEN-1] = '\0';
643
644   return 0;
645
646 } /* parse_ether_line */
647
648 static FILE *eth_p = NULL;
649
650 static void set_ethent(char *path)
651 {
652   if (eth_p)
653     rewind(eth_p);
654   else
655     eth_p = fopen(path, "r");
656 }
657
658 static void end_ethent(void)
659 {
660   if (eth_p) {
661     fclose(eth_p);
662     eth_p = NULL;
663   }
664 }
665
666 static ether_t *get_ethent(unsigned int *mask, gboolean manuf_file)
667 {
668
669   static ether_t eth;
670   static int     size = 0;
671   static char   *buf = NULL;
672
673   if (eth_p == NULL)
674     return NULL;
675
676   while (fgetline(&buf, &size, eth_p) >= 0) {
677     if (parse_ether_line(buf, &eth, mask, manuf_file) == 0) {
678       return &eth;
679     }
680   }
681
682   return NULL;
683
684 } /* get_ethent */
685
686 static ether_t *get_ethbyname(const gchar *name)
687 {
688   ether_t *eth;
689
690   set_ethent(g_ethers_path);
691
692   while ((eth = get_ethent(NULL, FALSE)) && strncmp(name, eth->name, MAXNAMELEN) != 0)
693     ;
694
695   if (eth == NULL) {
696     end_ethent();
697
698     set_ethent(g_pethers_path);
699
700     while ((eth = get_ethent(NULL, FALSE)) && strncmp(name, eth->name, MAXNAMELEN) != 0)
701       ;
702
703     end_ethent();
704   }
705
706   return eth;
707
708 } /* get_ethbyname */
709
710 static ether_t *get_ethbyaddr(const guint8 *addr)
711 {
712
713   ether_t *eth;
714
715   set_ethent(g_ethers_path);
716
717   while ((eth = get_ethent(NULL, FALSE)) && memcmp(addr, eth->addr, 6) != 0)
718     ;
719
720   if (eth == NULL) {
721     end_ethent();
722
723     set_ethent(g_pethers_path);
724
725     while ((eth = get_ethent(NULL, FALSE)) && memcmp(addr, eth->addr, 6) != 0)
726       ;
727
728     end_ethent();
729   }
730
731   return eth;
732
733 } /* get_ethbyaddr */
734
735 static int hash_eth_wka(const guint8 *addr, unsigned int mask)
736 {
737   if (mask <= 8) {
738     /* All but the topmost byte is masked out */
739     return (addr[0] & (0xFF << (8 - mask))) & (HASHETHSIZE - 1);
740   }
741   mask -= 8;
742   if (mask <= 8) {
743     /* All but the topmost 2 bytes are masked out */
744     return ((addr[0] << 8) | (addr[1] & (0xFF << (8 - mask)))) &
745             (HASHETHSIZE - 1);
746   }
747   mask -= 8;
748   if (mask <= 8) {
749     /* All but the topmost 3 bytes are masked out */
750     return ((addr[0] << 16) | (addr[1] << 8) | (addr[2] & (0xFF << (8 - mask))))
751      & (HASHETHSIZE - 1);
752   }
753   mask -= 8;
754   if (mask <= 8) {
755     /* All but the topmost 4 bytes are masked out */
756     return ((((addr[0] << 8) | addr[1]) ^
757              ((addr[2] << 8) | (addr[3] & (0xFF << (8 - mask)))))) &
758          (HASHETHSIZE - 1);
759   }
760   mask -= 8;
761   if (mask <= 8) {
762     /* All but the topmost 5 bytes are masked out */
763     return ((((addr[1] << 8) | addr[2]) ^
764              ((addr[3] << 8) | (addr[4] & (0xFF << (8 - mask)))))) &
765          (HASHETHSIZE - 1);
766   }
767   mask -= 8;
768   /* No bytes are fully masked out */
769   return ((((addr[1] << 8) | addr[2]) ^
770            ((addr[3] << 8) | (addr[4] & (0xFF << (8 - mask)))))) &
771             (HASHETHSIZE - 1);
772 }
773
774 static void add_manuf_name(guint8 *addr, unsigned int mask, gchar *name)
775 {
776   int hash_idx;
777   hashmanuf_t *tp;
778   hashether_t *(*wka_tp)[HASHETHSIZE], *etp;
779
780   if (mask == 48) {
781     /* This is a well-known MAC address; just add this to the Ethernet
782        hash table */
783     add_eth_name(addr, name);
784     return;
785   }
786
787   if (mask == 0) {
788     /* This is a manufacturer ID; add it to the manufacturer ID hash table */
789
790     hash_idx = HASH_ETH_MANUF(addr);
791
792     tp = manuf_table[hash_idx];
793
794     if( tp == NULL ) {
795       tp = manuf_table[hash_idx] = (hashmanuf_t *)g_malloc(sizeof(hashmanuf_t));
796     } else {
797       while(1) {
798         if (tp->next == NULL) {
799           tp->next = (hashmanuf_t *)g_malloc(sizeof(hashmanuf_t));
800           tp = tp->next;
801           break;
802         }
803         tp = tp->next;
804       }
805     }
806
807     memcpy(tp->addr, addr, sizeof(tp->addr));
808     strncpy(tp->name, name, MAXMANUFLEN);
809     tp->name[MAXMANUFLEN-1] = '\0';
810     tp->next = NULL;
811     return;
812   }
813
814   /* This is a range of well-known addresses; add it to the appropriate
815      well-known-address table, creating that table if necessary. */
816   wka_tp = wka_table[mask];
817   if (wka_tp == NULL)
818     wka_tp = wka_table[mask] = g_malloc0(sizeof *wka_table[mask]);
819
820   hash_idx = hash_eth_wka(addr, mask);
821
822   etp = (*wka_tp)[hash_idx];
823
824   if( etp == NULL ) {
825     etp = (*wka_tp)[hash_idx] = (hashether_t *)g_malloc(sizeof(hashether_t));
826   } else {
827     while(1) {
828       if (memcmp(etp->addr, addr, sizeof(etp->addr)) == 0) {
829         /* address already known */
830         return;
831       }
832       if (etp->next == NULL) {
833         etp->next = (hashether_t *)g_malloc(sizeof(hashether_t));
834         etp = etp->next;
835         break;
836       }
837       etp = etp->next;
838     }
839   }
840
841   memcpy(etp->addr, addr, sizeof(etp->addr));
842   strncpy(etp->name, name, MAXNAMELEN);
843   etp->name[MAXNAMELEN-1] = '\0';
844   etp->next = NULL;
845   etp->is_dummy_entry = FALSE;
846
847 } /* add_manuf_name */
848
849 static hashmanuf_t *manuf_name_lookup(const guint8 *addr)
850 {
851   int hash_idx;
852   hashmanuf_t *tp;
853
854   hash_idx = HASH_ETH_MANUF(addr);
855
856   tp = manuf_table[hash_idx];
857
858   while(tp != NULL) {
859     if (memcmp(tp->addr, addr, sizeof(tp->addr)) == 0) {
860       return tp;
861     }
862     tp = tp->next;
863   }
864
865   return NULL;
866
867 } /* manuf_name_lookup */
868
869 static hashether_t *wka_name_lookup(const guint8 *addr, unsigned int mask)
870 {
871   int hash_idx;
872   hashether_t *(*wka_tp)[HASHETHSIZE];
873   hashether_t *tp;
874   guint8 masked_addr[6];
875   unsigned int num;
876   int i;
877
878   wka_tp = wka_table[mask];
879   if (wka_tp == NULL) {
880     /* There are no entries in the table for that mask value, as there is
881        no table for that mask value. */
882     return NULL;
883   }
884
885   /* Get the part of the address covered by the mask. */
886   for (i = 0, num = mask; num >= 8; i++, num -= 8)
887     masked_addr[i] = addr[i];   /* copy octets entirely covered by the mask */
888   /* Mask out the first masked octet */
889   masked_addr[i] = addr[i] & (0xFF << (8 - num));
890   i++;
891   /* Zero out completely-masked-out octets */
892   for (; i < 6; i++)
893     masked_addr[i] = 0;
894
895   hash_idx = hash_eth_wka(masked_addr, mask);
896
897   tp = (*wka_tp)[hash_idx];
898
899   while(tp != NULL) {
900     if (memcmp(tp->addr, masked_addr, sizeof(tp->addr)) == 0) {
901       return tp;
902     }
903     tp = tp->next;
904   }
905
906   return NULL;
907
908 } /* wka_name_lookup */
909
910 static void initialize_ethers(void)
911 {
912   ether_t *eth;
913   char *manuf_path;
914   unsigned int mask;
915
916   /* Compute the pathname of the ethers file. */
917   if (g_ethers_path == NULL) {
918     g_ethers_path = g_strdup_printf("%s" G_DIR_SEPARATOR_S "%s",
919             get_systemfile_dir(), ENAME_ETHERS);
920   }
921
922   /* Set g_pethers_path here, but don't actually do anything
923    * with it. It's used in get_ethbyname() and get_ethbyaddr()
924    */
925   if (g_pethers_path == NULL)
926     g_pethers_path = get_persconffile_path(ENAME_ETHERS, FALSE);
927
928   /* manuf hash table initialization */
929
930   /* Compute the pathname of the manuf file */
931   manuf_path = get_datafile_path(ENAME_MANUF);
932
933   /* Read it and initialize the hash table */
934   set_ethent(manuf_path);
935
936   while ((eth = get_ethent(&mask, TRUE))) {
937     add_manuf_name(eth->addr, mask, eth->name);
938   }
939
940   end_ethent();
941
942   g_free(manuf_path);
943
944 } /* initialize_ethers */
945
946 static hashether_t *add_eth_name(const guint8 *addr, const gchar *name)
947 {
948   int hash_idx;
949   hashether_t *tp;
950
951   hash_idx = HASH_ETH_ADDRESS(addr);
952
953   tp = eth_table[hash_idx];
954
955   if( tp == NULL ) {
956     tp = eth_table[hash_idx] = (hashether_t *)g_malloc(sizeof(hashether_t));
957   } else {
958     while(1) {
959       if (memcmp(tp->addr, addr, sizeof(tp->addr)) == 0) {
960         /* address already known */
961         if (!tp->is_dummy_entry) {
962           return tp;
963         } else {
964           /* replace this dummy (manuf) entry with a real name */
965           break;
966         }
967       }
968       if (tp->next == NULL) {
969         tp->next = (hashether_t *)g_malloc(sizeof(hashether_t));
970         tp = tp->next;
971         break;
972       }
973       tp = tp->next;
974     }
975   }
976
977   memcpy(tp->addr, addr, sizeof(tp->addr));
978   strncpy(tp->name, name, MAXNAMELEN);
979   tp->name[MAXNAMELEN-1] = '\0';
980   tp->next = NULL;
981   tp->is_dummy_entry = FALSE;
982
983   return tp;
984
985 } /* add_eth_name */
986
987 static gchar *eth_name_lookup(const guint8 *addr)
988 {
989   int hash_idx;
990   hashmanuf_t *manufp;
991   hashether_t *tp;
992   ether_t *eth;
993   hashether_t *etp;
994   unsigned int mask;
995
996   hash_idx = HASH_ETH_ADDRESS(addr);
997
998   tp = eth_table[hash_idx];
999
1000   if( tp == NULL ) {
1001     tp = eth_table[hash_idx] = (hashether_t *)g_malloc(sizeof(hashether_t));
1002   } else {
1003     while(1) {
1004       if (memcmp(tp->addr, addr, sizeof(tp->addr)) == 0) {
1005         return tp->name;
1006       }
1007       if (tp->next == NULL) {
1008         tp->next = (hashether_t *)g_malloc(sizeof(hashether_t));
1009         tp = tp->next;
1010         break;
1011       }
1012       tp = tp->next;
1013     }
1014   }
1015
1016   /* fill in a new entry */
1017
1018   memcpy(tp->addr, addr, sizeof(tp->addr));
1019   tp->next = NULL;
1020
1021   if ( (eth = get_ethbyaddr(addr)) == NULL) {
1022     /* Unknown name.  Try looking for it in the well-known-address
1023        tables for well-known address ranges smaller than 2^24. */
1024     mask = 7;
1025     for (;;) {
1026       /* Only the topmost 5 bytes participate fully */
1027       if ((etp = wka_name_lookup(addr, mask+40)) != NULL) {
1028         sprintf(tp->name, "%s_%02x",
1029               etp->name, addr[5] & (0xFF >> mask));
1030         tp->is_dummy_entry = TRUE;
1031         return (tp->name);
1032       }
1033       if (mask == 0)
1034         break;
1035       mask--;
1036     }
1037
1038     mask = 7;
1039     for (;;) {
1040       /* Only the topmost 4 bytes participate fully */
1041       if ((etp = wka_name_lookup(addr, mask+32)) != NULL) {
1042         sprintf(tp->name, "%s_%02x:%02x",
1043               etp->name, addr[4] & (0xFF >> mask), addr[5]);
1044         tp->is_dummy_entry = TRUE;
1045         return (tp->name);
1046       }
1047       if (mask == 0)
1048         break;
1049       mask--;
1050     }
1051
1052     mask = 7;
1053     for (;;) {
1054       /* Only the topmost 3 bytes participate fully */
1055       if ((etp = wka_name_lookup(addr, mask+24)) != NULL) {
1056         sprintf(tp->name, "%s_%02x:%02x:%02x",
1057               etp->name, addr[3] & (0xFF >> mask), addr[4], addr[5]);
1058         tp->is_dummy_entry = TRUE;
1059         return (tp->name);
1060       }
1061       if (mask == 0)
1062         break;
1063       mask--;
1064     }
1065
1066     /* Now try looking in the manufacturer table. */
1067     if ((manufp = manuf_name_lookup(addr)) != NULL) {
1068       sprintf(tp->name, "%s_%02x:%02x:%02x",
1069               manufp->name, addr[3], addr[4], addr[5]);
1070       tp->is_dummy_entry = TRUE;
1071       return (tp->name);
1072     }
1073
1074     /* Now try looking for it in the well-known-address
1075        tables for well-known address ranges larger than 2^24. */
1076     mask = 7;
1077     for (;;) {
1078       /* Only the topmost 2 bytes participate fully */
1079       if ((etp = wka_name_lookup(addr, mask+16)) != NULL) {
1080         sprintf(tp->name, "%s_%02x:%02x:%02x:%02x",
1081               etp->name, addr[2] & (0xFF >> mask), addr[3], addr[4],
1082               addr[5]);
1083         tp->is_dummy_entry = TRUE;
1084         return (tp->name);
1085       }
1086       if (mask == 0)
1087         break;
1088       mask--;
1089     }
1090
1091     mask = 7;
1092     for (;;) {
1093       /* Only the topmost byte participates fully */
1094       if ((etp = wka_name_lookup(addr, mask+8)) != NULL) {
1095         sprintf(tp->name, "%s_%02x:%02x:%02x:%02x:%02x",
1096               etp->name, addr[1] & (0xFF >> mask), addr[2], addr[3],
1097               addr[4], addr[5]);
1098         tp->is_dummy_entry = TRUE;
1099         return (tp->name);
1100       }
1101       if (mask == 0)
1102         break;
1103       mask--;
1104     }
1105
1106     for (mask = 7; mask > 0; mask--) {
1107       /* Not even the topmost byte participates fully */
1108       if ((etp = wka_name_lookup(addr, mask)) != NULL) {
1109         sprintf(tp->name, "%s_%02x:%02x:%02x:%02x:%02x:%02x",
1110               etp->name, addr[0] & (0xFF >> mask), addr[1], addr[2],
1111               addr[3], addr[4], addr[5]);
1112         tp->is_dummy_entry = TRUE;
1113         return (tp->name);
1114       }
1115     }
1116
1117     /* No match whatsoever. */
1118     sprintf(tp->name, "%s", ether_to_str(addr));
1119     tp->is_dummy_entry = TRUE;
1120
1121   } else {
1122     strncpy(tp->name, eth->name, MAXNAMELEN);
1123     tp->name[MAXNAMELEN-1] = '\0';
1124     tp->is_dummy_entry = FALSE;
1125   }
1126
1127   return (tp->name);
1128
1129 } /* eth_name_lookup */
1130
1131 static guint8 *eth_addr_lookup(const gchar *name)
1132 {
1133   ether_t *eth;
1134   hashether_t *tp;
1135   hashether_t **table = eth_table;
1136   int i;
1137
1138   /* to be optimized (hash table from name to addr) */
1139   for (i = 0; i < HASHETHSIZE; i++) {
1140     tp = table[i];
1141     while (tp) {
1142       if (strcmp(tp->name, name) == 0)
1143         return tp->addr;
1144       tp = tp->next;
1145     }
1146   }
1147
1148   /* not in hash table : performs a file lookup */
1149
1150   if ((eth = get_ethbyname(name)) == NULL)
1151     return NULL;
1152
1153   /* add new entry in hash table */
1154
1155   tp = add_eth_name(eth->addr, name);
1156
1157   return tp->addr;
1158
1159 } /* eth_addr_lookup */
1160
1161
1162 /* IPXNETS */
1163 static int parse_ipxnets_line(char *line, ipxnet_t *ipxnet)
1164 {
1165   /*
1166    *  We allow three address separators (':', '-', and '.'),
1167    *  as well as no separators
1168    */
1169
1170   gchar         *cp;
1171   guint32       a, a0, a1, a2, a3;
1172   gboolean      found_single_number = FALSE;
1173
1174   if ((cp = strchr(line, '#')))
1175     *cp = '\0';
1176
1177   if ((cp = strtok(line, " \t\n")) == NULL)
1178     return -1;
1179
1180   /* Either fill a0,a1,a2,a3 and found_single_number is FALSE,
1181    * fill a and found_single_number is TRUE,
1182    * or return -1
1183    */
1184   if (sscanf(cp, "%x:%x:%x:%x", &a0, &a1, &a2, &a3) != 4) {
1185     if (sscanf(cp, "%x-%x-%x-%x", &a0, &a1, &a2, &a3) != 4) {
1186       if (sscanf(cp, "%x.%x.%x.%x", &a0, &a1, &a2, &a3) != 4) {
1187         if (sscanf(cp, "%x", &a) == 1) {
1188           found_single_number = TRUE;
1189         }
1190         else {
1191           return -1;
1192         }
1193       }
1194     }
1195   }
1196
1197   if ((cp = strtok(NULL, " \t\n")) == NULL)
1198     return -1;
1199
1200   if (found_single_number) {
1201         ipxnet->addr = a;
1202   }
1203   else {
1204         ipxnet->addr = (a0 << 24) | (a1 << 16) | (a2 << 8) | a3;
1205   }
1206
1207   strncpy(ipxnet->name, cp, MAXNAMELEN);
1208   ipxnet->name[MAXNAMELEN-1] = '\0';
1209
1210   return 0;
1211
1212 } /* parse_ipxnets_line */
1213
1214 static FILE *ipxnet_p = NULL;
1215
1216 static void set_ipxnetent(char *path)
1217 {
1218   if (ipxnet_p)
1219     rewind(ipxnet_p);
1220   else
1221     ipxnet_p = fopen(path, "r");
1222 }
1223
1224 static void end_ipxnetent(void)
1225 {
1226   if (ipxnet_p) {
1227     fclose(ipxnet_p);
1228     ipxnet_p = NULL;
1229   }
1230 }
1231
1232 static ipxnet_t *get_ipxnetent(void)
1233 {
1234
1235   static ipxnet_t ipxnet;
1236   static int     size = 0;
1237   static char   *buf = NULL;
1238
1239   if (ipxnet_p == NULL)
1240     return NULL;
1241
1242   while (fgetline(&buf, &size, ipxnet_p) >= 0) {
1243     if (parse_ipxnets_line(buf, &ipxnet) == 0) {
1244       return &ipxnet;
1245     }
1246   }
1247
1248   return NULL;
1249
1250 } /* get_ipxnetent */
1251
1252 static ipxnet_t *get_ipxnetbyname(const gchar *name)
1253 {
1254   ipxnet_t *ipxnet;
1255
1256   set_ipxnetent(g_ipxnets_path);
1257
1258   while ((ipxnet = get_ipxnetent()) && strncmp(name, ipxnet->name, MAXNAMELEN) != 0)
1259     ;
1260
1261   if (ipxnet == NULL) {
1262     end_ipxnetent();
1263
1264     set_ipxnetent(g_pipxnets_path);
1265
1266     while ((ipxnet = get_ipxnetent()) && strncmp(name, ipxnet->name, MAXNAMELEN) != 0)
1267       ;
1268
1269     end_ipxnetent();
1270   }
1271
1272   return ipxnet;
1273
1274 } /* get_ipxnetbyname */
1275
1276 static ipxnet_t *get_ipxnetbyaddr(guint32 addr)
1277 {
1278
1279   ipxnet_t *ipxnet;
1280
1281   set_ipxnetent(g_ipxnets_path);
1282
1283   while ((ipxnet = get_ipxnetent()) && (addr != ipxnet->addr) ) ;
1284
1285   if (ipxnet == NULL) {
1286     end_ipxnetent();
1287
1288     set_ipxnetent(g_pipxnets_path);
1289
1290     while ((ipxnet = get_ipxnetent()) && (addr != ipxnet->addr) )
1291       ;
1292
1293     end_ipxnetent();
1294   }
1295
1296   return ipxnet;
1297
1298 } /* get_ipxnetbyaddr */
1299
1300 static void initialize_ipxnets(void)
1301 {
1302   /* Compute the pathname of the ipxnets file.
1303    *
1304    * XXX - is there a notion of an "ipxnets file" in any flavor of
1305    * UNIX, or with any add-on Netware package for UNIX?  If not,
1306    * should the UNIX version of the ipxnets file be in the datafile
1307    * directory as well?
1308    */
1309   if (g_ipxnets_path == NULL) {
1310     g_ipxnets_path = g_malloc(strlen(get_systemfile_dir()) +
1311                               strlen(ENAME_IPXNETS) + 2);
1312     sprintf(g_ipxnets_path, "%s" G_DIR_SEPARATOR_S "%s",
1313             get_systemfile_dir(), ENAME_IPXNETS);
1314   }
1315
1316   /* Set g_pipxnets_path here, but don't actually do anything
1317    * with it. It's used in get_ipxnetbyname() and get_ipxnetbyaddr()
1318    */
1319   if (g_pipxnets_path == NULL)
1320     g_pipxnets_path = get_persconffile_path(ENAME_IPXNETS, FALSE);
1321
1322 } /* initialize_ipxnets */
1323
1324 static hashipxnet_t *add_ipxnet_name(guint addr, const gchar *name)
1325 {
1326   int hash_idx;
1327   hashipxnet_t *tp;
1328
1329   hash_idx = HASH_IPX_NET(addr);
1330
1331   tp = ipxnet_table[hash_idx];
1332
1333   if( tp == NULL ) {
1334     tp = ipxnet_table[hash_idx] = (hashipxnet_t *)g_malloc(sizeof(hashipxnet_t));
1335   } else {
1336     while(1) {
1337       if (tp->next == NULL) {
1338         tp->next = (hashipxnet_t *)g_malloc(sizeof(hashipxnet_t));
1339         tp = tp->next;
1340         break;
1341       }
1342       tp = tp->next;
1343     }
1344   }
1345
1346   tp->addr = addr;
1347   strncpy(tp->name, name, MAXNAMELEN);
1348   tp->name[MAXNAMELEN-1] = '\0';
1349   tp->next = NULL;
1350
1351   return tp;
1352
1353 } /* add_ipxnet_name */
1354
1355 static gchar *ipxnet_name_lookup(const guint addr)
1356 {
1357   int hash_idx;
1358   hashipxnet_t *tp;
1359   ipxnet_t *ipxnet;
1360
1361   hash_idx = HASH_IPX_NET(addr);
1362
1363   tp = ipxnet_table[hash_idx];
1364
1365   if( tp == NULL ) {
1366     tp = ipxnet_table[hash_idx] = (hashipxnet_t *)g_malloc(sizeof(hashipxnet_t));
1367   } else {
1368     while(1) {
1369       if (tp->addr == addr) {
1370         return tp->name;
1371       }
1372       if (tp->next == NULL) {
1373         tp->next = (hashipxnet_t *)g_malloc(sizeof(hashipxnet_t));
1374         tp = tp->next;
1375         break;
1376       }
1377       tp = tp->next;
1378     }
1379   }
1380
1381   /* fill in a new entry */
1382
1383   tp->addr = addr;
1384   tp->next = NULL;
1385
1386   if ( (ipxnet = get_ipxnetbyaddr(addr)) == NULL) {
1387     /* unknown name */
1388       sprintf(tp->name, "%X", addr);
1389
1390   } else {
1391     strncpy(tp->name, ipxnet->name, MAXNAMELEN);
1392     tp->name[MAXNAMELEN-1] = '\0';
1393   }
1394
1395   return (tp->name);
1396
1397 } /* ipxnet_name_lookup */
1398
1399 static guint ipxnet_addr_lookup(const gchar *name, gboolean *success)
1400 {
1401   ipxnet_t *ipxnet;
1402   hashipxnet_t *tp;
1403   hashipxnet_t **table = ipxnet_table;
1404   int i;
1405
1406   /* to be optimized (hash table from name to addr) */
1407   for (i = 0; i < HASHIPXNETSIZE; i++) {
1408     tp = table[i];
1409     while (tp) {
1410       if (strcmp(tp->name, name) == 0)
1411         return tp->addr;
1412       tp = tp->next;
1413     }
1414   }
1415
1416   /* not in hash table : performs a file lookup */
1417
1418   if ((ipxnet = get_ipxnetbyname(name)) == NULL) {
1419           *success = FALSE;
1420           return 0;
1421   }
1422
1423   /* add new entry in hash table */
1424
1425   tp = add_ipxnet_name(ipxnet->addr, name);
1426
1427   *success = TRUE;
1428   return tp->addr;
1429
1430 } /* ipxnet_addr_lookup */
1431
1432
1433 /*
1434  *  External Functions
1435  */
1436
1437 #ifdef HAVE_GNU_ADNS
1438
1439 void 
1440 host_name_lookup_init(void) {
1441   /* XXX - Any flags we should be using? */
1442   /* XXX - We could provide config settings for DNS servers, and
1443            pass them to ADNS with adns_init_strcfg */
1444   adns_init(&ads, 0, 0 /*0=>stderr*/);
1445   adns_currently_queued = 0;
1446 }
1447
1448 /* XXX - The ADNS "documentation" isn't very clear:
1449  * - Do we need to keep our query structures around?
1450  */
1451 gint
1452 host_name_lookup_process(gpointer data _U_) {
1453   adns_queue_msg_t *almsg;
1454   GList *cur;
1455   char addr_str[] = "111.222.333.444.in-addr.arpa.";
1456   guint8 *addr_bytes;
1457   adns_answer *ans;
1458   int ret;
1459   gboolean dequeue;
1460
1461   adns_queue_head = g_list_first(adns_queue_head);
1462
1463   cur = adns_queue_head;
1464   while (cur && adns_currently_queued <= prefs.name_resolve_concurrency) {
1465     almsg = (adns_queue_msg_t *) cur->data;
1466     if (! almsg->submitted && almsg->type == AF_INET) {
1467       addr_bytes = (guint8 *) &almsg->ip4_addr;
1468       sprintf(addr_str, "%u.%u.%u.%u.in-addr.arpa.", addr_bytes[3],
1469           addr_bytes[2], addr_bytes[1], addr_bytes[0]);
1470       adns_submit (ads, addr_str, adns_r_ptr, 0, NULL, &almsg->query);
1471       almsg->submitted = TRUE;
1472       adns_currently_queued++;
1473     }
1474     cur = cur->next;
1475   }
1476
1477   cur = adns_queue_head;
1478   while (cur) {
1479     dequeue = FALSE;
1480     almsg = (adns_queue_msg_t *) cur->data;
1481     if (almsg->submitted) {
1482       ret = adns_check(ads, &almsg->query, &ans, NULL);
1483       if (ret == 0) {
1484         if (ans->status == adns_s_ok) {
1485           add_host_name(almsg->ip4_addr, *ans->rrs.str);
1486         }
1487         dequeue = TRUE;
1488       }
1489     }
1490     cur = cur->next;
1491     if (dequeue) {
1492       adns_queue_head = g_list_remove(adns_queue_head, (void *) almsg);
1493       g_free(almsg);
1494       adns_currently_queued--;
1495     }
1496   }
1497
1498   /* Keep the timeout in place */
1499   return 1;
1500 }
1501
1502 void
1503 host_name_lookup_cleanup(void) {
1504   void *qdata;
1505
1506   adns_queue_head = g_list_first(adns_queue_head);
1507   while (adns_queue_head) {
1508     qdata = adns_queue_head->data;
1509     adns_queue_head = g_list_remove(adns_queue_head, qdata);
1510     g_free(qdata);
1511   }
1512   
1513   adns_finish(ads);
1514 }
1515
1516 #else
1517
1518 void
1519 host_name_lookup_init(void) {
1520 }
1521
1522 gint
1523 host_name_lookup_process(gpointer data _U_) {
1524   /* Kill the timeout, as there's nothing for it to do */
1525   return 0;
1526 }
1527
1528 void
1529 host_name_lookup_cleanup(void) {
1530 }
1531
1532 #endif /* HAVE_GNU_ADNS */
1533
1534 extern gchar *get_hostname(guint addr)
1535 {
1536   gboolean found;
1537
1538   if (!(g_resolv_flags & RESOLV_NETWORK))
1539     return ip_to_str((guint8 *)&addr);
1540
1541   return host_name_lookup(addr, &found);
1542 }
1543
1544 extern const gchar *get_hostname6(struct e_in6_addr *addr)
1545 {
1546   gboolean found;
1547
1548 #ifdef INET6
1549   if (!(g_resolv_flags & RESOLV_NETWORK))
1550     return ip6_to_str(addr);
1551 #ifdef SOLARIS8_INET6
1552   if (IN6_IS_ADDR_LINKLOCAL((struct in6_addr*)addr) || IN6_IS_ADDR_MULTICAST((struct in6_addr*)addr))
1553 #else
1554   if (IN6_IS_ADDR_LINKLOCAL(addr) || IN6_IS_ADDR_MULTICAST(addr))
1555 #endif
1556     return ip6_to_str(addr);
1557 #endif
1558
1559   return host_name_lookup6(addr, &found);
1560 }
1561
1562 extern void add_host_name(guint addr, const gchar *name)
1563 {
1564   int hash_idx;
1565   hashname_t *tp;
1566
1567   hash_idx = HASH_IPV4_ADDRESS(addr);
1568
1569   tp = host_table[hash_idx];
1570
1571   if( tp == NULL ) {
1572     tp = host_table[hash_idx] = (hashname_t *)g_malloc(sizeof(hashname_t));
1573   } else {
1574     while(1) {
1575       if (tp->addr == addr) {
1576         /* address already known */
1577         if (!tp->is_dummy_entry) {
1578           return;
1579         } else {
1580           /* replace this dummy entry with the new one */
1581           break;
1582         }
1583       }
1584       if (tp->next == NULL) {
1585         tp->next = (hashname_t *)g_malloc(sizeof(hashname_t));
1586         tp = tp->next;
1587         break;
1588       }
1589       tp = tp->next;
1590     }
1591   }
1592
1593   strncpy(tp->name, name, MAXNAMELEN);
1594   tp->name[MAXNAMELEN-1] = '\0';
1595   tp->addr = addr;
1596   tp->next = NULL;
1597   tp->is_dummy_entry = FALSE;
1598
1599 } /* add_host_name */
1600
1601 extern gchar *get_udp_port(guint port)
1602 {
1603   static gchar  str[3][MAXNAMELEN];
1604   static gchar *cur;
1605
1606   if (!(g_resolv_flags & RESOLV_TRANSPORT)) {
1607     if (cur == &str[0][0]) {
1608       cur = &str[1][0];
1609     } else if (cur == &str[1][0]) {
1610       cur = &str[2][0];
1611     } else {
1612       cur = &str[0][0];
1613     }
1614     sprintf(cur, "%u", port);
1615     return cur;
1616   }
1617
1618   return serv_name_lookup(port, PT_UDP);
1619
1620 } /* get_udp_port */
1621
1622 extern gchar *get_tcp_port(guint port)
1623 {
1624   static gchar  str[3][MAXNAMELEN];
1625   static gchar *cur;
1626
1627   if (!(g_resolv_flags & RESOLV_TRANSPORT)) {
1628     if (cur == &str[0][0]) {
1629       cur = &str[1][0];
1630     } else if (cur == &str[1][0]) {
1631       cur = &str[2][0];
1632     } else {
1633       cur = &str[0][0];
1634     }
1635     sprintf(cur, "%u", port);
1636     return cur;
1637   }
1638
1639   return serv_name_lookup(port, PT_TCP);
1640
1641 } /* get_tcp_port */
1642
1643 extern gchar *get_sctp_port(guint port)
1644 {
1645   static gchar  str[3][MAXNAMELEN];
1646   static gchar *cur;
1647
1648   if (!(g_resolv_flags & RESOLV_TRANSPORT)) {
1649     if (cur == &str[0][0]) {
1650       cur = &str[1][0];
1651     } else if (cur == &str[1][0]) {
1652       cur = &str[2][0];
1653     } else {
1654       cur = &str[0][0];
1655     }
1656     sprintf(cur, "%u", port);
1657     return cur;
1658   }
1659
1660   return serv_name_lookup(port, PT_SCTP);
1661
1662 } /* get_sctp_port */
1663
1664 extern gchar *get_ether_name(const guint8 *addr)
1665 {
1666   if (!(g_resolv_flags & RESOLV_MAC))
1667     return ether_to_str(addr);
1668
1669   if (!eth_resolution_initialized) {
1670     initialize_ethers();
1671     eth_resolution_initialized = 1;
1672   }
1673
1674   return eth_name_lookup(addr);
1675
1676 } /* get_ether_name */
1677
1678 /* Look for an ether name in the hash, and return it if found.
1679  * If it's not found, simply return NULL. We DO NOT make a new
1680  * hash entry for it with the hex digits turned into a string.
1681  */
1682 gchar *get_ether_name_if_known(const guint8 *addr)
1683 {
1684   int hash_idx;
1685   hashether_t *tp;
1686
1687   /* Initialize ether structs if we're the first
1688    * ether-related function called */
1689   if (!(g_resolv_flags & RESOLV_MAC))
1690     return NULL;
1691
1692   if (!eth_resolution_initialized) {
1693     initialize_ethers();
1694     eth_resolution_initialized = 1;
1695   }
1696
1697   hash_idx = HASH_ETH_ADDRESS(addr);
1698
1699   tp = eth_table[hash_idx];
1700
1701   if( tp == NULL ) {
1702           /* Hash key not found in table.
1703            * Force a lookup (and a hash entry) for addr, then call
1704            * myself. I plan on not getting into an infinite loop because
1705            * eth_name_lookup() is guaranteed to make a hashtable entry,
1706            * so when I call myself again, I can never get into this
1707            * block of code again. Knock on wood...
1708            */
1709           (void) eth_name_lookup(addr);
1710           return get_ether_name_if_known(addr); /* a well-placed goto would suffice */
1711   }
1712   else {
1713     while(1) {
1714       if (memcmp(tp->addr, addr, sizeof(tp->addr)) == 0) {
1715               if (!tp->is_dummy_entry) {
1716                 /* A name was found, and its origin is an ethers file */
1717                 return tp->name;
1718               }
1719               else {
1720                 /* A name was found, but it was created, not found in a file */
1721                 return NULL;
1722               }
1723       }
1724       if (tp->next == NULL) {
1725           /* Read my reason above for why I'm sure I can't get into an infinite loop */
1726           (void) eth_name_lookup(addr);
1727           return get_ether_name_if_known(addr); /* a well-placed goto would suffice */
1728       }
1729       tp = tp->next;
1730     }
1731   }
1732   g_assert_not_reached();
1733   return NULL;
1734 }
1735
1736
1737 extern guint8 *get_ether_addr(const gchar *name)
1738 {
1739
1740   /* force resolution (do not check g_resolv_flags) */
1741
1742   if (!eth_resolution_initialized) {
1743     initialize_ethers();
1744     eth_resolution_initialized = 1;
1745   }
1746
1747   return eth_addr_lookup(name);
1748
1749 } /* get_ether_addr */
1750
1751 extern void add_ether_byip(guint ip, const guint8 *eth)
1752 {
1753
1754   gchar *host;
1755   gboolean found;
1756
1757   /* first check that IP address can be resolved */
1758
1759   if ((host = host_name_lookup(ip, &found)) == NULL)
1760     return;
1761
1762   /* ok, we can add this entry in the ethers hashtable */
1763
1764   if (found)
1765     add_eth_name(eth, host);
1766
1767 } /* add_ether_byip */
1768
1769 extern const gchar *get_ipxnet_name(const guint32 addr)
1770 {
1771
1772   if (!(g_resolv_flags & RESOLV_NETWORK)) {
1773           return ipxnet_to_str_punct(addr, '\0');
1774   }
1775
1776   if (!ipxnet_resolution_initialized) {
1777     initialize_ipxnets();
1778     ipxnet_resolution_initialized = 1;
1779   }
1780
1781   return ipxnet_name_lookup(addr);
1782
1783 } /* get_ipxnet_name */
1784
1785 extern guint32 get_ipxnet_addr(const gchar *name, gboolean *known)
1786 {
1787   guint32 addr;
1788   gboolean success;
1789
1790   /* force resolution (do not check g_resolv_flags) */
1791
1792   if (!ipxnet_resolution_initialized) {
1793     initialize_ipxnets();
1794     ipxnet_resolution_initialized = 1;
1795   }
1796
1797   addr =  ipxnet_addr_lookup(name, &success);
1798
1799   *known = success;
1800   return addr;
1801
1802 } /* get_ipxnet_addr */
1803
1804 extern const gchar *get_manuf_name(const guint8 *addr)
1805 {
1806   static gchar  str[3][MAXMANUFLEN];
1807   static gchar *cur;
1808   hashmanuf_t  *manufp;
1809
1810   if ((g_resolv_flags & RESOLV_MAC) && !eth_resolution_initialized) {
1811     initialize_ethers();
1812     eth_resolution_initialized = 1;
1813   }
1814
1815   if (!(g_resolv_flags & RESOLV_MAC) || ((manufp = manuf_name_lookup(addr)) == NULL)) {
1816     if (cur == &str[0][0]) {
1817       cur = &str[1][0];
1818     } else if (cur == &str[1][0]) {
1819       cur = &str[2][0];
1820     } else {
1821       cur = &str[0][0];
1822     }
1823     sprintf(cur, "%02x:%02x:%02x", addr[0], addr[1], addr[2]);
1824     return cur;
1825   }
1826
1827   return manufp->name;
1828
1829 } /* get_manuf_name */
1830
1831
1832
1833 /* Translate a string, assumed either to be a dotted-quad IP address or
1834  * a host name, to a numeric IP address.  Return TRUE if we succeed and
1835  * set "*addrp" to that numeric IP address; return FALSE if we fail.
1836  * Used more in the dfilter parser rather than in packet dissectors */
1837 gboolean get_host_ipaddr(const char *host, guint32 *addrp)
1838 {
1839         struct in_addr          ipaddr;
1840         struct hostent          *hp;
1841
1842         /*
1843          * don't change it to inet_pton(AF_INET), they are not 100% compatible.
1844          * inet_pton(AF_INET) does not support hexadecimal notation nor
1845          * less-than-4 octet notation.
1846          */
1847         if (!inet_aton(host, &ipaddr)) {
1848                 /* It's not a valid dotted-quad IP address; is it a valid
1849                  * host name? */
1850                 hp = gethostbyname(host);
1851                 if (hp == NULL) {
1852                         /* No. */
1853                         return FALSE;
1854                         /* Apparently, some versions of gethostbyaddr can
1855                          * return IPv6 addresses. */
1856                 } else if (hp->h_length <= (int) sizeof (struct in_addr)) {
1857                         memcpy(&ipaddr, hp->h_addr, hp->h_length);
1858                 } else {
1859                         return FALSE;
1860                 }
1861         } else {
1862                 /* Does the string really contain dotted-quad IP?
1863                  * Check against inet_atons that accept strings such as
1864                  * "130.230" as valid addresses and try to convert them
1865                  * to some form of a classful (host.net) notation.
1866                  */
1867                 unsigned int a0, a1, a2, a3;
1868                 if (sscanf(host, "%u.%u.%u.%u", &a0, &a1, &a2, &a3) != 4)
1869                         return FALSE;
1870         }
1871
1872         *addrp = g_ntohl(ipaddr.s_addr);
1873         return TRUE;
1874 }
1875
1876 /*
1877  * Translate IPv6 numeric address or FQDN hostname, into binary IPv6 address.
1878  * Return TRUE if we succeed and set "*addrp" to that numeric IP address;
1879  * return FALSE if we fail.
1880  */
1881 gboolean get_host_ipaddr6(const char *host, struct e_in6_addr *addrp)
1882 {
1883         struct hostent *hp;
1884
1885         if (inet_pton(AF_INET6, host, addrp) == 1)
1886                 return TRUE;
1887
1888         /* try FQDN */
1889 #ifdef HAVE_GETHOSTBYNAME2
1890         hp = gethostbyname2(host, AF_INET6);
1891 #else
1892         hp = NULL;
1893 #endif
1894         if (hp != NULL && hp->h_length == sizeof(struct e_in6_addr)) {
1895                 memcpy(addrp, hp->h_addr, hp->h_length);
1896                 return TRUE;
1897         }
1898
1899         return FALSE;
1900 }
1901
1902 /*
1903  * Find out whether a hostname resolves to an ip or ipv6 address
1904  * Return "ip6" if it is IPv6, "ip" otherwise (including the case
1905  * that we don't know)
1906  */
1907 const char* host_ip_af(const char *host)
1908 {
1909 #ifdef HAVE_GETHOSTBYNAME2
1910         struct hostent *h;
1911         return (h = gethostbyname2(host, AF_INET6)) && h->h_addrtype == AF_INET6 ? "ip6" : "ip";
1912 #else
1913         return "ip";
1914 #endif
1915 }