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