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