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