2004-08-09 22:31:21 +00:00
|
|
|
/* addr_resolv.c
|
1998-09-16 02:39:15 +00:00
|
|
|
* Routines for network object lookup
|
|
|
|
*
|
2004-07-18 00:24:25 +00:00
|
|
|
* $Id$
|
1998-09-16 03:22:19 +00:00
|
|
|
*
|
2003-01-26 19:35:31 +00:00
|
|
|
* Laurent Deniel <laurent.deniel@free.fr>
|
1998-09-16 02:39:15 +00:00
|
|
|
*
|
2006-05-21 05:12:17 +00:00
|
|
|
* Wireshark - Network traffic analyzer
|
|
|
|
* By Gerald Combs <gerald@wireshark.org>
|
1998-09-16 02:39:15 +00:00
|
|
|
* Copyright 1998 Gerald Combs
|
2002-08-28 20:41:00 +00:00
|
|
|
*
|
1998-09-16 02:39:15 +00:00
|
|
|
* This program is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU General Public License
|
|
|
|
* as published by the Free Software Foundation; either version 2
|
|
|
|
* of the License, or (at your option) any later version.
|
2002-08-28 20:41:00 +00:00
|
|
|
*
|
1998-09-16 02:39:15 +00:00
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
2002-08-28 20:41:00 +00:00
|
|
|
*
|
1998-09-16 02:39:15 +00:00
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
# include "config.h"
|
|
|
|
#endif
|
|
|
|
|
2002-09-09 19:38:11 +00:00
|
|
|
#include <ctype.h>
|
1998-09-16 02:39:15 +00:00
|
|
|
#include <stdio.h>
|
1998-12-17 05:42:33 +00:00
|
|
|
#include <stdlib.h>
|
1998-09-16 02:39:15 +00:00
|
|
|
#include <string.h>
|
2005-01-13 09:09:56 +00:00
|
|
|
#include <errno.h>
|
1999-07-13 02:53:26 +00:00
|
|
|
|
2003-11-20 05:04:57 +00:00
|
|
|
/*
|
2004-10-05 22:48:36 +00:00
|
|
|
* Win32 doesn't have SIGALRM (and it's the OS where name lookup calls
|
|
|
|
* are most likely to take a long time, given the way address-to-name
|
|
|
|
* lookups are done over NBNS).
|
2003-11-20 05:04:57 +00:00
|
|
|
*
|
2004-10-05 22:48:36 +00:00
|
|
|
* Mac OS X does have SIGALRM, but if you longjmp() out of a name resolution
|
|
|
|
* call in a signal handler, you might crash, because the state of the
|
|
|
|
* resolution code that sends messages to lookupd might be inconsistent
|
|
|
|
* if you jump out of it in middle of a call.
|
|
|
|
*
|
|
|
|
* In at least some Linux distributions (e.g., RedHat Linux 9), if ADNS
|
|
|
|
* is used, we appear to hang in host_name_lookup6() in a gethostbyaddr()
|
2004-10-06 07:25:38 +00:00
|
|
|
* call (and possibly in other gethostbyaddr() calls), because there's
|
|
|
|
* a mutex lock held in gethostbyaddr() and it doesn't get released
|
|
|
|
* if we longjmp out of it.
|
2003-11-20 05:04:57 +00:00
|
|
|
*
|
|
|
|
* There's no guarantee that longjmp()ing out of name resolution calls
|
|
|
|
* will work on *any* platform; OpenBSD got rid of the alarm/longjmp
|
|
|
|
* code in tcpdump, to avoid those sorts of problems, and that was
|
|
|
|
* picked up by tcpdump.org tcpdump.
|
2004-10-05 22:48:36 +00:00
|
|
|
*
|
|
|
|
* So, for now, we do not define AVOID_DNS_TIMEOUT. If we get a
|
|
|
|
* significantly more complaints about lookups taking a long time,
|
|
|
|
* we can reconsider that decision. (Note that tcpdump originally
|
|
|
|
* added that for the benefit of systems using NIS to look up host
|
|
|
|
* names; that might now be fixed in NIS implementations, for those
|
|
|
|
* sites still using NIS rather than DNS for that....)
|
2003-11-20 05:04:57 +00:00
|
|
|
*/
|
1999-07-13 02:53:26 +00:00
|
|
|
|
|
|
|
#ifdef HAVE_UNISTD_H
|
1998-09-16 02:39:15 +00:00
|
|
|
#include <unistd.h>
|
1999-07-13 02:53:26 +00:00
|
|
|
#endif
|
1998-09-16 02:39:15 +00:00
|
|
|
|
|
|
|
#ifdef HAVE_NETINET_IN_H
|
|
|
|
# include <netinet/in.h>
|
|
|
|
#endif
|
|
|
|
|
1999-07-13 02:53:26 +00:00
|
|
|
#ifdef HAVE_NETDB_H
|
1998-09-16 02:39:15 +00:00
|
|
|
#include <netdb.h>
|
1999-07-13 02:53:26 +00:00
|
|
|
#endif
|
|
|
|
|
2000-01-10 17:33:17 +00:00
|
|
|
#ifdef HAVE_ARPA_INET_H
|
Have "get_host_ipaddr()" return a Boolean indicating whether it
succeeded or failed, and, if it succeeded, have it fill in the IP
address if found through a pointer passed as the second argument.
Have it first try interpreting its first argument as a dotted-quad IP
address, with "inet_aton()", and, if that fails, have it try to
interpret it as a host name with "gethostbyname()"; don't bother with
"gethostbyaddr()", as we should be allowed to filter on IP addresses
even if there's no host name associated with them (there's no guarantee
that "gethostbyaddr()" will succeed if handed an IP address with no
corresponding name - and it looks as if FreeBSD 3.2, at least, may not
succeed in that case).
Add a "dfilter_fail()" routine that takes "printf()"-like arguments and
uses them to set an error message for the parse; doing so means that
even if the filter expression is syntactically valid, we treat it as
being invalid. (Is there a better way to force a parse to fail from
arbitrary places in routines called by the parser?)
Use that routine in the lexical analyzer.
If that error message was set, use it as is as the failure message,
rather than adding "Unable to parse filter string XXX" to it.
Have the code to handle IP addresses and host names in display filters
check whether "get_host_ipaddr()" succeeded or failed and, if it failed,
arrange that the parse fail with an error message indicating the source
of the problem.
svn path=/trunk/; revision=802
1999-10-11 03:03:12 +00:00
|
|
|
#include <arpa/inet.h>
|
2000-01-10 17:33:17 +00:00
|
|
|
#endif
|
Have "get_host_ipaddr()" return a Boolean indicating whether it
succeeded or failed, and, if it succeeded, have it fill in the IP
address if found through a pointer passed as the second argument.
Have it first try interpreting its first argument as a dotted-quad IP
address, with "inet_aton()", and, if that fails, have it try to
interpret it as a host name with "gethostbyname()"; don't bother with
"gethostbyaddr()", as we should be allowed to filter on IP addresses
even if there's no host name associated with them (there's no guarantee
that "gethostbyaddr()" will succeed if handed an IP address with no
corresponding name - and it looks as if FreeBSD 3.2, at least, may not
succeed in that case).
Add a "dfilter_fail()" routine that takes "printf()"-like arguments and
uses them to set an error message for the parse; doing so means that
even if the filter expression is syntactically valid, we treat it as
being invalid. (Is there a better way to force a parse to fail from
arbitrary places in routines called by the parser?)
Use that routine in the lexical analyzer.
If that error message was set, use it as is as the failure message,
rather than adding "Unable to parse filter string XXX" to it.
Have the code to handle IP addresses and host names in display filters
check whether "get_host_ipaddr()" succeeded or failed and, if it failed,
arrange that the parse fail with an error message indicating the source
of the problem.
svn path=/trunk/; revision=802
1999-10-11 03:03:12 +00:00
|
|
|
|
1998-09-16 02:39:15 +00:00
|
|
|
#include <signal.h>
|
1999-07-13 02:53:26 +00:00
|
|
|
|
|
|
|
#ifdef HAVE_SYS_SOCKET_H
|
2009-09-07 16:07:04 +00:00
|
|
|
#include <sys/socket.h> /* needed to define AF_ values on UNIX */
|
2002-10-29 00:28:11 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef HAVE_WINSOCK2_H
|
2009-09-07 16:07:04 +00:00
|
|
|
#include <winsock2.h> /* needed to define AF_ values on Windows */
|
1999-07-13 02:53:26 +00:00
|
|
|
#endif
|
1998-09-16 02:39:15 +00:00
|
|
|
|
Apparently, on systems with glibc 2.2, "inet_aton()" is declared in
<arpa/inet.h>, but is, in some fashion, declared differently from the
way we declare it in "inet_v6defs.h", but "inet_ntop()" isn't defined,
so we include "inet_v6defs.h" in "inet_pton.c", which causes
"inet_pton.c" not to compile as we get a collision between the two
declarations.
Move the declaration of "inet_aton()" to "inet_aton.h", define
"NEED_INET_ATON_H" iff we didn't find "inet_aton()" in the system
libraries, and include "inet_aton.h" in the callers of "inet_aton()" iff
"NEED_INET_ATON_H" is defined, so that it doesn't get declared by us if
"inet_aton()" is defined by a system library (which hopefully means it's
declared in <arpa/inet.h> instead).
svn path=/trunk/; revision=2137
2000-07-14 07:11:53 +00:00
|
|
|
#ifdef NEED_INET_ATON_H
|
2010-05-28 20:19:55 +00:00
|
|
|
# include "wsutil/inet_aton.h"
|
Apparently, on systems with glibc 2.2, "inet_aton()" is declared in
<arpa/inet.h>, but is, in some fashion, declared differently from the
way we declare it in "inet_v6defs.h", but "inet_ntop()" isn't defined,
so we include "inet_v6defs.h" in "inet_pton.c", which causes
"inet_pton.c" not to compile as we get a collision between the two
declarations.
Move the declaration of "inet_aton()" to "inet_aton.h", define
"NEED_INET_ATON_H" iff we didn't find "inet_aton()" in the system
libraries, and include "inet_aton.h" in the callers of "inet_aton()" iff
"NEED_INET_ATON_H" is defined, so that it doesn't get declared by us if
"inet_aton()" is defined by a system library (which hopefully means it's
declared in <arpa/inet.h> instead).
svn path=/trunk/; revision=2137
2000-07-14 07:11:53 +00:00
|
|
|
#endif
|
|
|
|
|
1999-10-14 06:55:11 +00:00
|
|
|
#ifdef NEED_INET_V6DEFS_H
|
2010-05-28 20:19:55 +00:00
|
|
|
# include "wsutil/inet_v6defs.h"
|
1999-10-14 06:55:11 +00:00
|
|
|
#endif
|
|
|
|
|
2004-09-11 23:03:36 +00:00
|
|
|
#if defined(_WIN32) && defined(INET6)
|
2003-08-18 18:40:10 +00:00
|
|
|
# include <ws2tcpip.h>
|
|
|
|
#endif
|
|
|
|
|
2008-08-11 21:59:59 +00:00
|
|
|
#ifdef HAVE_C_ARES
|
|
|
|
# if defined(_WIN32) && !defined(INET6)
|
|
|
|
# define socklen_t unsigned int
|
|
|
|
# endif
|
|
|
|
# include <ares.h>
|
2008-12-23 18:15:09 +00:00
|
|
|
# include <ares_version.h>
|
2008-08-11 21:59:59 +00:00
|
|
|
#else
|
|
|
|
# ifdef HAVE_GNU_ADNS
|
|
|
|
# include <errno.h>
|
|
|
|
# include <adns.h>
|
2009-04-01 00:30:45 +00:00
|
|
|
# if defined(inet_aton) && defined(_WIN32)
|
2008-08-11 21:59:59 +00:00
|
|
|
# undef inet_aton
|
|
|
|
# endif
|
2009-09-07 16:07:04 +00:00
|
|
|
# endif /* HAVE_GNU_ADNS */
|
|
|
|
#endif /* HAVE_C_ARES */
|
2008-08-11 21:59:59 +00:00
|
|
|
|
|
|
|
|
2005-01-13 09:09:56 +00:00
|
|
|
#include <glib.h>
|
|
|
|
|
|
|
|
#include "report_err.h"
|
1998-09-16 02:39:15 +00:00
|
|
|
#include "packet.h"
|
2001-04-01 07:06:24 +00:00
|
|
|
#include "ipv6-utils.h"
|
2004-08-06 19:57:49 +00:00
|
|
|
#include "addr_resolv.h"
|
2001-03-31 22:53:09 +00:00
|
|
|
#include "filesystem.h"
|
2007-10-26 05:42:12 +00:00
|
|
|
|
|
|
|
#include <epan/strutil.h>
|
2008-05-22 15:46:27 +00:00
|
|
|
#include <wsutil/file_util.h>
|
2004-09-27 22:55:15 +00:00
|
|
|
#include <epan/prefs.h>
|
2005-08-17 09:36:20 +00:00
|
|
|
#include <epan/emem.h>
|
1998-09-16 02:39:15 +00:00
|
|
|
|
2009-09-07 16:07:04 +00:00
|
|
|
#define ENAME_HOSTS "hosts"
|
|
|
|
#define ENAME_SUBNETS "subnets"
|
2009-09-13 17:24:51 +00:00
|
|
|
#define ENAME_ETHERS "ethers"
|
|
|
|
#define ENAME_IPXNETS "ipxnets"
|
2009-09-07 16:07:04 +00:00
|
|
|
#define ENAME_MANUF "manuf"
|
|
|
|
#define ENAME_SERVICES "services"
|
|
|
|
|
2010-06-28 22:43:13 +00:00
|
|
|
#define HASHETHSIZE 2048
|
|
|
|
#define HASHHOSTSIZE 2048
|
|
|
|
#define HASHIPXNETSIZE 256
|
|
|
|
#define HASHMANUFSIZE 256
|
|
|
|
#define HASHPORTSIZE 256
|
|
|
|
#define SUBNETLENGTHSIZE 32 /*1-32 inc.*/
|
1998-09-16 02:39:15 +00:00
|
|
|
|
2004-11-17 08:53:20 +00:00
|
|
|
/* hash table used for IPv4 lookup */
|
1998-09-16 02:39:15 +00:00
|
|
|
|
2009-09-04 10:53:37 +00:00
|
|
|
#define HASH_IPV4_ADDRESS(addr) (g_htonl(addr) & (HASHHOSTSIZE - 1))
|
2001-06-07 22:07:02 +00:00
|
|
|
|
2011-03-24 22:47:57 +00:00
|
|
|
/*
|
|
|
|
* XXX Some of this is duplicated in addrinfo_list. We may want to replace the
|
|
|
|
* addr and name parts with a struct addrinfo or create our own addrinfo-like
|
|
|
|
* struct that simply points to the data below.
|
|
|
|
*/
|
2004-11-17 08:53:20 +00:00
|
|
|
typedef struct hashipv4 {
|
2009-09-07 16:07:04 +00:00
|
|
|
guint addr;
|
|
|
|
gboolean is_dummy_entry; /* name is IPv4 address in dot format */
|
2010-06-28 22:43:13 +00:00
|
|
|
gboolean resolve; /* already tried to resolve it */
|
2009-09-07 16:07:04 +00:00
|
|
|
struct hashipv4 *next;
|
|
|
|
gchar ip[16];
|
|
|
|
gchar name[MAXNAMELEN];
|
2004-11-17 08:53:20 +00:00
|
|
|
} hashipv4_t;
|
|
|
|
|
2004-11-17 09:44:41 +00:00
|
|
|
/* hash table used for IPv6 lookup */
|
|
|
|
|
2009-09-07 16:07:04 +00:00
|
|
|
#define HASH_IPV6_ADDRESS(addr) \
|
|
|
|
((((addr).bytes[14] << 8)|((addr).bytes[15])) & (HASHHOSTSIZE - 1))
|
2004-11-17 09:44:41 +00:00
|
|
|
|
|
|
|
typedef struct hashipv6 {
|
2009-09-07 16:07:04 +00:00
|
|
|
struct e_in6_addr addr;
|
|
|
|
gboolean is_dummy_entry; /* name is IPv6 address in colon format */
|
2010-06-28 22:43:13 +00:00
|
|
|
gboolean resolve; /* */
|
2009-09-07 16:07:04 +00:00
|
|
|
struct hashipv6 *next;
|
2010-06-28 22:43:13 +00:00
|
|
|
gchar ip6[47]; /* XX */
|
2009-09-07 16:07:04 +00:00
|
|
|
gchar name[MAXNAMELEN];
|
2004-11-17 09:44:41 +00:00
|
|
|
} hashipv6_t;
|
|
|
|
|
2008-01-21 21:44:34 +00:00
|
|
|
/* Array of entries of subnets of different lengths */
|
|
|
|
typedef struct {
|
2010-06-28 22:43:13 +00:00
|
|
|
gsize mask_length; /*1-32*/
|
|
|
|
guint32 mask; /* e.g. 255.255.255.*/
|
2010-04-27 22:46:39 +00:00
|
|
|
hashipv4_t** subnet_addresses; /* Hash table of subnet addresses */
|
2008-01-21 21:44:34 +00:00
|
|
|
} subnet_length_entry_t;
|
|
|
|
|
2004-11-17 08:53:20 +00:00
|
|
|
/* hash table used for TCP/UDP/SCTP port lookup */
|
|
|
|
|
2009-09-07 16:07:04 +00:00
|
|
|
#define HASH_PORT(port) ((port) & (HASHPORTSIZE - 1))
|
2004-11-17 08:53:20 +00:00
|
|
|
|
|
|
|
typedef struct hashport {
|
2010-06-28 22:43:13 +00:00
|
|
|
guint16 port;
|
|
|
|
struct hashport *next;
|
|
|
|
gchar name[MAXNAMELEN];
|
2004-11-17 08:53:20 +00:00
|
|
|
} hashport_t;
|
1998-09-16 02:39:15 +00:00
|
|
|
|
1999-11-21 16:32:23 +00:00
|
|
|
/* hash table used for IPX network lookup */
|
|
|
|
|
2001-06-07 22:07:02 +00:00
|
|
|
/* XXX - check goodness of hash function */
|
|
|
|
|
2009-09-07 16:07:04 +00:00
|
|
|
#define HASH_IPX_NET(net) ((net) & (HASHIPXNETSIZE - 1))
|
2001-06-07 22:07:02 +00:00
|
|
|
|
2004-11-17 08:53:20 +00:00
|
|
|
typedef struct hashipxnet {
|
2010-06-28 22:43:13 +00:00
|
|
|
guint addr;
|
|
|
|
struct hashipxnet *next;
|
|
|
|
gchar name[MAXNAMELEN];
|
2004-11-17 08:53:20 +00:00
|
|
|
} hashipxnet_t;
|
1999-11-21 16:32:23 +00:00
|
|
|
|
1998-09-25 23:24:07 +00:00
|
|
|
/* hash tables used for ethernet and manufacturer lookup */
|
|
|
|
|
2001-06-07 22:07:02 +00:00
|
|
|
#define HASH_ETH_ADDRESS(addr) \
|
2009-09-07 16:07:04 +00:00
|
|
|
(((((addr)[2] << 8) | (addr)[3]) ^ (((addr)[4] << 8) | (addr)[5])) & \
|
|
|
|
(HASHETHSIZE - 1))
|
2001-06-07 22:07:02 +00:00
|
|
|
|
|
|
|
#define HASH_ETH_MANUF(addr) (((int)(addr)[2]) & (HASHMANUFSIZE - 1))
|
|
|
|
|
1998-09-25 23:24:07 +00:00
|
|
|
typedef struct hashmanuf {
|
2010-06-28 22:43:13 +00:00
|
|
|
struct hashmanuf *next;
|
2010-06-29 02:53:17 +00:00
|
|
|
guint8 addr[3];
|
2010-11-30 22:28:34 +00:00
|
|
|
char *name;
|
1998-09-25 23:24:07 +00:00
|
|
|
} hashmanuf_t;
|
|
|
|
|
2010-07-01 15:11:02 +00:00
|
|
|
#define HASHETHER_STATUS_UNRESOLVED 1
|
|
|
|
#define HASHETHER_STATUS_RESOLVED_DUMMY 2
|
|
|
|
#define HASHETHER_STATUS_RESOLVED_NAME 3
|
|
|
|
|
1998-09-25 23:24:07 +00:00
|
|
|
typedef struct hashether {
|
2010-06-28 22:43:13 +00:00
|
|
|
struct hashether *next;
|
2010-07-01 15:11:02 +00:00
|
|
|
guint status; /* (See above) */
|
2010-06-29 02:53:17 +00:00
|
|
|
guint8 addr[6];
|
2010-07-01 15:11:02 +00:00
|
|
|
char hexaddr[6*3];
|
|
|
|
char resolved_name[MAXNAMELEN];
|
1998-09-25 23:24:07 +00:00
|
|
|
} hashether_t;
|
|
|
|
|
2010-06-29 02:53:17 +00:00
|
|
|
typedef struct hashwka {
|
|
|
|
struct hashwka *next;
|
|
|
|
guint8 addr[6];
|
|
|
|
char name[MAXNAMELEN];
|
|
|
|
} hashwka_t;
|
|
|
|
|
1998-09-25 23:24:07 +00:00
|
|
|
/* internal ethernet type */
|
1998-09-16 02:39:15 +00:00
|
|
|
|
1998-09-25 23:24:07 +00:00
|
|
|
typedef struct _ether
|
|
|
|
{
|
2010-06-29 02:53:17 +00:00
|
|
|
guint8 addr[6];
|
|
|
|
char name[MAXNAMELEN];
|
1998-09-25 23:24:07 +00:00
|
|
|
} ether_t;
|
|
|
|
|
1999-11-21 16:32:23 +00:00
|
|
|
/* internal ipxnet type */
|
|
|
|
|
|
|
|
typedef struct _ipxnet
|
|
|
|
{
|
2010-06-29 02:53:17 +00:00
|
|
|
guint addr;
|
|
|
|
char name[MAXNAMELEN];
|
1999-11-21 16:32:23 +00:00
|
|
|
} ipxnet_t;
|
|
|
|
|
2009-09-07 16:07:04 +00:00
|
|
|
static hashipv4_t *ipv4_table[HASHHOSTSIZE];
|
|
|
|
static hashipv6_t *ipv6_table[HASHHOSTSIZE];
|
2008-04-12 14:08:19 +00:00
|
|
|
|
2009-09-07 16:07:04 +00:00
|
|
|
static hashport_t **cb_port_table;
|
|
|
|
static gchar *cb_service;
|
2008-04-12 14:08:19 +00:00
|
|
|
|
2009-09-07 16:07:04 +00:00
|
|
|
static hashport_t *udp_port_table[HASHPORTSIZE];
|
|
|
|
static hashport_t *tcp_port_table[HASHPORTSIZE];
|
|
|
|
static hashport_t *sctp_port_table[HASHPORTSIZE];
|
|
|
|
static hashport_t *dccp_port_table[HASHPORTSIZE];
|
|
|
|
static hashether_t *eth_table[HASHETHSIZE];
|
|
|
|
static hashmanuf_t *manuf_table[HASHMANUFSIZE];
|
2010-06-29 02:53:17 +00:00
|
|
|
static hashwka_t *(*wka_table[48])[HASHETHSIZE];
|
2009-09-07 16:07:04 +00:00
|
|
|
static hashipxnet_t *ipxnet_table[HASHIPXNETSIZE];
|
1998-09-25 23:24:07 +00:00
|
|
|
|
2008-01-21 21:44:34 +00:00
|
|
|
static subnet_length_entry_t subnet_length_entries[SUBNETLENGTHSIZE]; /* Ordered array of entries */
|
|
|
|
static gboolean have_subnet_entry = FALSE;
|
|
|
|
|
2010-07-01 15:11:02 +00:00
|
|
|
static gboolean eth_resolution_initialized = FALSE;
|
2009-09-07 16:07:04 +00:00
|
|
|
static int ipxnet_resolution_initialized = 0;
|
|
|
|
static int service_resolution_initialized = 0;
|
2009-12-22 20:01:06 +00:00
|
|
|
static gboolean new_resolved_objects = FALSE;
|
1998-09-25 23:24:07 +00:00
|
|
|
|
2011-03-24 22:47:57 +00:00
|
|
|
static struct addrinfo *addrinfo_list = NULL; /* IPv4 and IPv6 */
|
|
|
|
static struct addrinfo *addrinfo_list_last = NULL;
|
|
|
|
|
2004-01-10 17:31:40 +00:00
|
|
|
static hashether_t *add_eth_name(const guint8 *addr, const gchar *name);
|
2010-04-03 18:18:50 +00:00
|
|
|
static void add_serv_port_cb(const guint32 port);
|
2002-09-09 19:38:11 +00:00
|
|
|
|
2002-01-13 20:35:12 +00:00
|
|
|
/*
|
|
|
|
* Flag controlling what names to resolve.
|
|
|
|
*/
|
2010-10-12 13:15:08 +00:00
|
|
|
guint32 gbl_resolv_flags;
|
2002-01-13 20:35:12 +00:00
|
|
|
|
1998-09-25 23:24:07 +00:00
|
|
|
/*
|
|
|
|
* Global variables (can be changed in GUI sections)
|
2001-10-21 19:54:49 +00:00
|
|
|
* XXX - they could be changed in GUI code, but there's currently no
|
|
|
|
* GUI code to change them.
|
1998-09-25 23:24:07 +00:00
|
|
|
*/
|
|
|
|
|
2010-04-27 22:46:39 +00:00
|
|
|
gchar *g_ethers_path = NULL; /* global ethers file */
|
|
|
|
gchar *g_pethers_path = NULL; /* personal ethers file */
|
|
|
|
gchar *g_ipxnets_path = NULL; /* global ipxnets file */
|
|
|
|
gchar *g_pipxnets_path = NULL; /* personal ipxnets file */
|
2009-09-07 16:07:04 +00:00
|
|
|
gchar *g_services_path = NULL; /* global services file */
|
|
|
|
gchar *g_pservices_path = NULL; /* personal services file */
|
2010-04-27 22:46:39 +00:00
|
|
|
/* first resolving call */
|
1998-09-16 02:39:15 +00:00
|
|
|
|
2008-08-07 21:41:48 +00:00
|
|
|
/* c-ares */
|
|
|
|
#ifdef HAVE_C_ARES
|
|
|
|
/*
|
|
|
|
* Submitted queries trigger a callback (c_ares_ghba_cb()).
|
|
|
|
* Queries are added to c_ares_queue_head. During processing, queries are
|
|
|
|
* popped off the front of c_ares_queue_head and submitted using
|
|
|
|
* ares_gethostbyaddr().
|
|
|
|
* The callback processes the response, then frees the request.
|
|
|
|
*/
|
2009-09-13 17:24:51 +00:00
|
|
|
#define ASYNC_DNS
|
|
|
|
typedef struct _async_dns_queue_msg
|
2008-08-07 21:41:48 +00:00
|
|
|
{
|
|
|
|
union {
|
|
|
|
guint32 ip4;
|
|
|
|
struct e_in6_addr ip6;
|
|
|
|
} addr;
|
|
|
|
int family;
|
2009-09-13 17:24:51 +00:00
|
|
|
} async_dns_queue_msg_t;
|
2008-08-07 21:41:48 +00:00
|
|
|
|
2009-12-24 00:58:31 +00:00
|
|
|
typedef struct _async_hostent {
|
|
|
|
int addr_size;
|
2010-06-28 22:43:13 +00:00
|
|
|
int copied;
|
2009-12-24 00:58:31 +00:00
|
|
|
void *addrp;
|
|
|
|
} async_hostent_t;
|
|
|
|
|
2009-01-06 18:31:57 +00:00
|
|
|
#if ( ( ARES_VERSION_MAJOR < 1 ) \
|
|
|
|
|| ( 1 == ARES_VERSION_MAJOR && ARES_VERSION_MINOR < 5 ) )
|
2008-12-23 18:15:09 +00:00
|
|
|
static void c_ares_ghba_cb(void *arg, int status, struct hostent *hostent);
|
|
|
|
#else
|
2008-08-07 21:41:48 +00:00
|
|
|
static void c_ares_ghba_cb(void *arg, int status, int timeouts _U_, struct hostent *hostent);
|
2010-01-19 23:18:23 +00:00
|
|
|
#endif
|
2009-12-24 00:58:31 +00:00
|
|
|
|
|
|
|
ares_channel ghba_chan; /* ares_gethostbyaddr -- Usually non-interactive, no timeout */
|
|
|
|
ares_channel ghbn_chan; /* ares_gethostbyname -- Usually interactive, timeout */
|
2003-05-04 18:50:56 +00:00
|
|
|
|
2008-08-07 21:41:48 +00:00
|
|
|
#else
|
|
|
|
/* GNU ADNS */
|
2003-05-04 18:50:56 +00:00
|
|
|
#ifdef HAVE_GNU_ADNS
|
2009-09-13 17:24:51 +00:00
|
|
|
#define ASYNC_DNS
|
2008-08-07 21:41:48 +00:00
|
|
|
/*
|
|
|
|
* Submitted queries have to be checked individually using adns_check().
|
|
|
|
* Queries are added to adns_queue_head. During processing, the list is
|
|
|
|
* iterated twice: once to request queries up to the concurrency limit,
|
|
|
|
* and once to check the status of each query.
|
|
|
|
*/
|
2004-11-10 04:57:34 +00:00
|
|
|
|
2003-05-04 18:50:56 +00:00
|
|
|
adns_state ads;
|
|
|
|
|
2009-09-13 17:24:51 +00:00
|
|
|
typedef struct _async_dns_queue_msg
|
2003-05-04 18:50:56 +00:00
|
|
|
{
|
2010-06-28 22:43:13 +00:00
|
|
|
gboolean submitted;
|
|
|
|
guint32 ip4_addr;
|
|
|
|
int type;
|
|
|
|
adns_query query;
|
2009-09-13 17:24:51 +00:00
|
|
|
} async_dns_queue_msg_t;
|
2003-05-04 18:50:56 +00:00
|
|
|
|
|
|
|
#endif /* HAVE_GNU_ADNS */
|
2008-08-07 21:41:48 +00:00
|
|
|
#endif /* HAVE_C_ARES */
|
2009-09-13 17:24:51 +00:00
|
|
|
#ifdef ASYNC_DNS
|
2010-06-28 22:43:13 +00:00
|
|
|
static gboolean async_dns_initialized = FALSE;
|
|
|
|
static int async_dns_in_flight = 0;
|
|
|
|
static GList *async_dns_queue_head = NULL;
|
2009-09-13 17:24:51 +00:00
|
|
|
|
|
|
|
/* push a dns request */
|
|
|
|
static void
|
|
|
|
add_async_dns_ipv4(int type, guint32 addr)
|
|
|
|
{
|
2010-04-27 22:46:39 +00:00
|
|
|
async_dns_queue_msg_t *msg;
|
2009-09-13 17:24:51 +00:00
|
|
|
|
2010-04-27 22:46:39 +00:00
|
|
|
msg = g_malloc(sizeof(async_dns_queue_msg_t));
|
2009-09-13 17:24:51 +00:00
|
|
|
#ifdef HAVE_C_ARES
|
2010-04-27 22:46:39 +00:00
|
|
|
msg->family = type;
|
|
|
|
msg->addr.ip4 = addr;
|
2009-09-13 17:24:51 +00:00
|
|
|
#else
|
2010-04-27 22:46:39 +00:00
|
|
|
msg->type = type;
|
|
|
|
msg->ip4_addr = addr;
|
|
|
|
msg->submitted = FALSE;
|
2009-09-13 17:24:51 +00:00
|
|
|
#endif
|
2010-04-27 22:46:39 +00:00
|
|
|
async_dns_queue_head = g_list_append(async_dns_queue_head, (gpointer) msg);
|
2009-09-13 17:24:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|
2003-05-04 18:50:56 +00:00
|
|
|
|
2008-01-21 21:44:34 +00:00
|
|
|
typedef struct {
|
2010-06-28 22:43:13 +00:00
|
|
|
guint32 mask;
|
|
|
|
gsize mask_length;
|
2010-04-27 22:46:39 +00:00
|
|
|
const gchar* name; /* Shallow copy */
|
2008-01-21 21:44:34 +00:00
|
|
|
} subnet_entry_t;
|
2007-08-06 08:44:26 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Miscellaneous functions
|
|
|
|
*/
|
|
|
|
|
2010-04-29 18:17:29 +00:00
|
|
|
static int
|
|
|
|
fgetline(char **buf, int *size, FILE *fp)
|
2007-08-06 08:44:26 +00:00
|
|
|
{
|
|
|
|
int len;
|
|
|
|
int c;
|
|
|
|
|
2009-10-05 18:12:16 +00:00
|
|
|
if (fp == NULL || buf == NULL)
|
2007-08-06 08:44:26 +00:00
|
|
|
return -1;
|
|
|
|
|
|
|
|
if (*buf == NULL) {
|
|
|
|
if (*size == 0)
|
|
|
|
*size = BUFSIZ;
|
|
|
|
|
2010-04-29 18:17:29 +00:00
|
|
|
*buf = g_malloc(*size);
|
2007-08-06 08:44:26 +00:00
|
|
|
}
|
|
|
|
|
2009-09-06 14:53:21 +00:00
|
|
|
g_assert(*buf);
|
|
|
|
g_assert(*size > 0);
|
|
|
|
|
2007-08-06 08:44:26 +00:00
|
|
|
if (feof(fp))
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
len = 0;
|
|
|
|
while ((c = getc(fp)) != EOF && c != '\r' && c != '\n') {
|
|
|
|
if (len+1 >= *size) {
|
2009-09-06 14:53:21 +00:00
|
|
|
*buf = g_realloc(*buf, *size += BUFSIZ);
|
2007-08-06 08:44:26 +00:00
|
|
|
}
|
|
|
|
(*buf)[len++] = c;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (len == 0 && c == EOF)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
(*buf)[len] = '\0';
|
|
|
|
|
|
|
|
return len;
|
|
|
|
|
|
|
|
} /* fgetline */
|
|
|
|
|
|
|
|
|
1998-09-25 23:24:07 +00:00
|
|
|
/*
|
2002-08-28 20:41:00 +00:00
|
|
|
* Local function definitions
|
1998-09-25 23:24:07 +00:00
|
|
|
*/
|
2008-01-21 21:44:34 +00:00
|
|
|
static subnet_entry_t subnet_lookup(const guint32 addr);
|
2010-04-03 18:18:50 +00:00
|
|
|
static void subnet_entry_set(guint32 subnet_addr, const guint32 mask_length, const gchar* name);
|
1998-09-16 02:39:15 +00:00
|
|
|
|
2007-08-06 08:44:26 +00:00
|
|
|
|
2010-04-29 18:17:29 +00:00
|
|
|
static void
|
|
|
|
add_service_name(hashport_t **proto_table, const guint port, const char *service_name)
|
2007-08-06 08:44:26 +00:00
|
|
|
{
|
|
|
|
int hash_idx;
|
|
|
|
hashport_t *tp;
|
2008-05-22 15:46:27 +00:00
|
|
|
|
2007-08-06 08:44:26 +00:00
|
|
|
|
|
|
|
hash_idx = HASH_PORT(port);
|
|
|
|
tp = proto_table[hash_idx];
|
|
|
|
|
|
|
|
if( tp == NULL ) {
|
|
|
|
tp = proto_table[hash_idx] = (hashport_t *)g_malloc(sizeof(hashport_t));
|
|
|
|
} else {
|
|
|
|
while(1) {
|
|
|
|
if( tp->port == port ) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (tp->next == NULL) {
|
|
|
|
tp->next = (hashport_t *)g_malloc(sizeof(hashport_t));
|
|
|
|
tp = tp->next;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
tp = tp->next;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* fill in a new entry */
|
|
|
|
tp->port = port;
|
|
|
|
tp->next = NULL;
|
|
|
|
|
2007-10-26 05:42:12 +00:00
|
|
|
g_strlcpy(tp->name, service_name, MAXNAMELEN);
|
2010-01-19 23:18:23 +00:00
|
|
|
|
2009-12-22 20:01:06 +00:00
|
|
|
new_resolved_objects = TRUE;
|
2007-08-06 08:44:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-04-29 18:17:29 +00:00
|
|
|
static void
|
|
|
|
parse_service_line (char *line)
|
2007-08-06 08:44:26 +00:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
* See the services(4) or services(5) man page for services file format
|
|
|
|
* (not available on all systems).
|
|
|
|
*/
|
|
|
|
|
|
|
|
gchar *cp;
|
|
|
|
gchar *service;
|
|
|
|
gchar *port;
|
|
|
|
|
2008-04-12 14:08:19 +00:00
|
|
|
range_t *port_rng = NULL;
|
|
|
|
guint32 max_port = MAX_UDP_PORT;
|
2007-08-06 08:44:26 +00:00
|
|
|
|
|
|
|
if ((cp = strchr(line, '#')))
|
|
|
|
*cp = '\0';
|
|
|
|
|
|
|
|
if ((cp = strtok(line, " \t")) == NULL)
|
|
|
|
return;
|
|
|
|
|
|
|
|
service = cp;
|
|
|
|
|
|
|
|
if ((cp = strtok(NULL, " \t")) == NULL)
|
|
|
|
return;
|
|
|
|
|
|
|
|
port = cp;
|
|
|
|
|
2011-04-04 15:31:33 +00:00
|
|
|
if (strtok(cp, "/") == NULL)
|
2007-08-06 08:44:26 +00:00
|
|
|
return;
|
|
|
|
|
|
|
|
if ((cp = strtok(NULL, "/")) == NULL)
|
|
|
|
return;
|
|
|
|
|
|
|
|
/* seems we got all interesting things from the file */
|
|
|
|
if(strcmp(cp, "tcp") == 0) {
|
2008-04-12 14:08:19 +00:00
|
|
|
max_port = MAX_TCP_PORT;
|
|
|
|
cb_port_table = tcp_port_table;
|
2007-08-06 08:44:26 +00:00
|
|
|
}
|
2008-04-12 14:08:19 +00:00
|
|
|
else if(strcmp(cp, "udp") == 0) {
|
|
|
|
max_port = MAX_UDP_PORT;
|
|
|
|
cb_port_table = udp_port_table;
|
2007-08-06 08:44:26 +00:00
|
|
|
}
|
2008-04-12 14:08:19 +00:00
|
|
|
else if(strcmp(cp, "sctp") == 0) {
|
|
|
|
max_port = MAX_SCTP_PORT;
|
|
|
|
cb_port_table = sctp_port_table;
|
|
|
|
}
|
|
|
|
else if(strcmp(cp, "dccp") == 0) {
|
|
|
|
max_port = MAX_DCCP_PORT;
|
|
|
|
cb_port_table = dccp_port_table;
|
|
|
|
} else {
|
2007-08-06 08:44:26 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2008-04-12 14:08:19 +00:00
|
|
|
if(CVT_NO_ERROR != range_convert_str(&port_rng, port, max_port) ) {
|
|
|
|
/* some assertion here? */
|
2007-08-06 08:44:26 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2008-04-12 14:08:19 +00:00
|
|
|
cb_service = service;
|
|
|
|
range_foreach(port_rng, add_serv_port_cb);
|
2008-09-20 14:24:29 +00:00
|
|
|
g_free (port_rng);
|
2007-08-06 08:44:26 +00:00
|
|
|
} /* parse_service_line */
|
|
|
|
|
|
|
|
|
2008-04-12 14:08:19 +00:00
|
|
|
static void
|
2010-04-03 18:18:50 +00:00
|
|
|
add_serv_port_cb(const guint32 port)
|
2008-04-12 14:08:19 +00:00
|
|
|
{
|
2010-04-27 22:46:39 +00:00
|
|
|
if ( port ) {
|
|
|
|
add_service_name(cb_port_table, port, cb_service);
|
|
|
|
}
|
2008-04-12 14:08:19 +00:00
|
|
|
}
|
|
|
|
|
2007-08-06 08:44:26 +00:00
|
|
|
|
2010-04-29 18:17:29 +00:00
|
|
|
static void
|
|
|
|
parse_services_file(const char * path)
|
2007-08-06 08:44:26 +00:00
|
|
|
{
|
|
|
|
FILE *serv_p;
|
2009-09-06 08:59:30 +00:00
|
|
|
static int size = 0;
|
|
|
|
static char *buf = NULL;
|
2007-08-06 08:44:26 +00:00
|
|
|
|
|
|
|
/* services hash table initialization */
|
2008-05-22 15:46:27 +00:00
|
|
|
serv_p = ws_fopen(path, "r");
|
2007-08-06 08:44:26 +00:00
|
|
|
|
|
|
|
if (serv_p == NULL)
|
|
|
|
return;
|
|
|
|
|
|
|
|
while (fgetline(&buf, &size, serv_p) >= 0) {
|
|
|
|
parse_service_line (buf);
|
|
|
|
}
|
2009-09-06 08:59:30 +00:00
|
|
|
|
2007-08-06 08:44:26 +00:00
|
|
|
fclose(serv_p);
|
|
|
|
}
|
|
|
|
|
2010-04-29 18:17:29 +00:00
|
|
|
static void
|
|
|
|
initialize_services(void)
|
2007-08-06 08:44:26 +00:00
|
|
|
{
|
|
|
|
|
|
|
|
/* the hash table won't ignore duplicates, so use the personal path first */
|
|
|
|
|
|
|
|
/* set personal services path */
|
|
|
|
if (g_pservices_path == NULL)
|
2008-01-14 16:40:23 +00:00
|
|
|
g_pservices_path = get_persconffile_path(ENAME_SERVICES, FALSE, FALSE);
|
2007-08-06 08:44:26 +00:00
|
|
|
|
|
|
|
parse_services_file(g_pservices_path);
|
|
|
|
|
|
|
|
/* Compute the pathname of the services file. */
|
|
|
|
if (g_services_path == NULL) {
|
|
|
|
g_services_path = get_datafile_path(ENAME_SERVICES);
|
|
|
|
}
|
|
|
|
|
|
|
|
parse_services_file(g_services_path);
|
|
|
|
|
|
|
|
} /* initialize_services */
|
|
|
|
|
|
|
|
|
|
|
|
|
2010-04-29 18:17:29 +00:00
|
|
|
static gchar
|
|
|
|
*serv_name_lookup(const guint port, const port_type proto)
|
1998-09-16 02:39:15 +00:00
|
|
|
{
|
2001-06-07 22:07:02 +00:00
|
|
|
int hash_idx;
|
2004-11-17 08:53:20 +00:00
|
|
|
hashport_t *tp;
|
|
|
|
hashport_t **table;
|
2005-07-23 11:41:25 +00:00
|
|
|
const char *serv_proto = NULL;
|
1998-09-16 02:39:15 +00:00
|
|
|
struct servent *servp;
|
|
|
|
|
2007-08-06 08:44:26 +00:00
|
|
|
|
|
|
|
if (!service_resolution_initialized) {
|
|
|
|
initialize_services();
|
|
|
|
service_resolution_initialized = 1;
|
|
|
|
}
|
|
|
|
|
1998-09-16 02:39:15 +00:00
|
|
|
switch(proto) {
|
2000-08-19 08:26:04 +00:00
|
|
|
case PT_UDP:
|
1998-09-16 02:39:15 +00:00
|
|
|
table = udp_port_table;
|
|
|
|
serv_proto = "udp";
|
|
|
|
break;
|
2000-08-19 08:26:04 +00:00
|
|
|
case PT_TCP:
|
1998-09-16 02:39:15 +00:00
|
|
|
table = tcp_port_table;
|
|
|
|
serv_proto = "tcp";
|
|
|
|
break;
|
2000-08-19 08:26:04 +00:00
|
|
|
case PT_SCTP:
|
|
|
|
table = sctp_port_table;
|
|
|
|
serv_proto = "sctp";
|
|
|
|
break;
|
2005-09-20 15:18:28 +00:00
|
|
|
case PT_DCCP:
|
|
|
|
table = dccp_port_table;
|
|
|
|
serv_proto = "dcp";
|
|
|
|
break;
|
1998-09-16 02:39:15 +00:00
|
|
|
default:
|
|
|
|
/* not yet implemented */
|
|
|
|
return NULL;
|
|
|
|
/*NOTREACHED*/
|
|
|
|
} /* proto */
|
2002-08-28 20:41:00 +00:00
|
|
|
|
2001-06-07 22:07:02 +00:00
|
|
|
hash_idx = HASH_PORT(port);
|
|
|
|
tp = table[hash_idx];
|
1998-09-16 02:39:15 +00:00
|
|
|
|
|
|
|
if( tp == NULL ) {
|
2004-11-17 08:53:20 +00:00
|
|
|
tp = table[hash_idx] = (hashport_t *)g_malloc(sizeof(hashport_t));
|
2002-08-28 20:41:00 +00:00
|
|
|
} else {
|
1998-09-16 02:39:15 +00:00
|
|
|
while(1) {
|
2004-11-17 08:53:20 +00:00
|
|
|
if( tp->port == port ) {
|
2010-04-29 18:17:29 +00:00
|
|
|
return tp->name;
|
1998-09-16 02:39:15 +00:00
|
|
|
}
|
|
|
|
if (tp->next == NULL) {
|
2010-06-28 22:43:13 +00:00
|
|
|
tp->next = (hashport_t *)g_malloc(sizeof(hashport_t));
|
|
|
|
tp = tp->next;
|
|
|
|
break;
|
1998-09-16 02:39:15 +00:00
|
|
|
}
|
|
|
|
tp = tp->next;
|
|
|
|
}
|
|
|
|
}
|
2002-08-28 20:41:00 +00:00
|
|
|
|
1998-09-16 02:39:15 +00:00
|
|
|
/* fill in a new entry */
|
2004-11-17 08:53:20 +00:00
|
|
|
tp->port = port;
|
1998-09-16 02:39:15 +00:00
|
|
|
tp->next = NULL;
|
|
|
|
|
2010-10-12 13:15:08 +00:00
|
|
|
if (!(gbl_resolv_flags & RESOLV_TRANSPORT) ||
|
2002-08-02 21:29:45 +00:00
|
|
|
(servp = getservbyport(g_htons(port), serv_proto)) == NULL) {
|
1998-09-16 02:39:15 +00:00
|
|
|
/* unknown port */
|
2010-02-23 19:28:38 +00:00
|
|
|
guint32_to_str_buf(port, tp->name, MAXNAMELEN);
|
1998-09-16 02:39:15 +00:00
|
|
|
} else {
|
2007-10-26 05:42:12 +00:00
|
|
|
g_strlcpy(tp->name, servp->s_name, MAXNAMELEN);
|
1998-09-16 02:39:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return (tp->name);
|
|
|
|
|
|
|
|
} /* serv_name_lookup */
|
|
|
|
|
2003-05-04 18:50:56 +00:00
|
|
|
|
2008-08-07 21:41:48 +00:00
|
|
|
/* Fill in an IP4 structure with info from subnets file or just with the
|
|
|
|
* string form of the address.
|
2008-01-21 21:44:34 +00:00
|
|
|
*/
|
2010-04-29 18:17:29 +00:00
|
|
|
static void
|
|
|
|
fill_dummy_ip4(const guint addr, hashipv4_t* volatile tp)
|
2008-01-21 21:44:34 +00:00
|
|
|
{
|
|
|
|
subnet_entry_t subnet_entry;
|
2009-09-06 08:59:30 +00:00
|
|
|
|
|
|
|
if (tp->is_dummy_entry)
|
|
|
|
return; /* already done */
|
|
|
|
|
2008-01-21 21:44:34 +00:00
|
|
|
tp->is_dummy_entry = TRUE; /* Overwrite if we get async DNS reply */
|
|
|
|
|
|
|
|
/* Do we have a subnet for this address? */
|
|
|
|
subnet_entry = subnet_lookup(addr);
|
|
|
|
if(0 != subnet_entry.mask) {
|
2010-04-27 22:46:39 +00:00
|
|
|
/* Print name, then '.' then IP address after subnet mask */
|
|
|
|
guint32 host_addr;
|
|
|
|
gchar buffer[MAX_IP_STR_LEN];
|
|
|
|
gchar* paddr;
|
|
|
|
gsize i;
|
|
|
|
|
|
|
|
host_addr = addr & (~(guint32)subnet_entry.mask);
|
|
|
|
ip_to_str_buf((guint8 *)&host_addr, buffer, MAX_IP_STR_LEN);
|
|
|
|
paddr = buffer;
|
|
|
|
|
|
|
|
/* Skip to first octet that is not totally masked
|
|
|
|
* If length of mask is 32, we chomp the whole address.
|
|
|
|
* If the address string starts '.' (should not happen?),
|
|
|
|
* we skip that '.'.
|
|
|
|
*/
|
|
|
|
i = subnet_entry.mask_length / 8;
|
|
|
|
while(*(paddr) != '\0' && i > 0) {
|
|
|
|
if(*(++paddr) == '.') {
|
|
|
|
--i;
|
2008-01-21 21:44:34 +00:00
|
|
|
}
|
2010-04-27 22:46:39 +00:00
|
|
|
}
|
2008-01-21 21:44:34 +00:00
|
|
|
|
2010-04-27 22:46:39 +00:00
|
|
|
/* There are more efficient ways to do this, but this is safe if we
|
|
|
|
* trust g_snprintf and MAXNAMELEN
|
|
|
|
*/
|
|
|
|
g_snprintf(tp->name, MAXNAMELEN, "%s%s", subnet_entry.name, paddr);
|
2008-05-22 15:46:27 +00:00
|
|
|
} else {
|
2010-04-27 22:46:39 +00:00
|
|
|
ip_to_str_buf((guint8 *)&addr, tp->name, MAXNAMELEN);
|
2008-01-21 21:44:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-08-07 21:41:48 +00:00
|
|
|
#ifdef HAVE_C_ARES
|
|
|
|
|
|
|
|
static void
|
2009-01-06 18:31:57 +00:00
|
|
|
#if ( ( ARES_VERSION_MAJOR < 1 ) \
|
|
|
|
|| ( 1 == ARES_VERSION_MAJOR && ARES_VERSION_MINOR < 5 ) )
|
2008-12-23 18:15:09 +00:00
|
|
|
c_ares_ghba_cb(void *arg, int status, struct hostent *he) {
|
|
|
|
#else
|
2008-08-07 21:41:48 +00:00
|
|
|
c_ares_ghba_cb(void *arg, int status, int timeouts _U_, struct hostent *he) {
|
2008-12-23 18:15:09 +00:00
|
|
|
#endif
|
2009-09-13 17:24:51 +00:00
|
|
|
async_dns_queue_msg_t *caqm = arg;
|
2008-08-07 21:41:48 +00:00
|
|
|
char **p;
|
|
|
|
|
|
|
|
if (!caqm) return;
|
2009-09-13 17:24:51 +00:00
|
|
|
async_dns_in_flight--;
|
2008-08-07 21:41:48 +00:00
|
|
|
|
|
|
|
if (status == ARES_SUCCESS) {
|
|
|
|
for (p = he->h_addr_list; *p != NULL; p++) {
|
|
|
|
switch(caqm->family) {
|
2010-06-28 22:43:13 +00:00
|
|
|
case AF_INET:
|
|
|
|
add_ipv4_name(caqm->addr.ip4, he->h_name);
|
|
|
|
break;
|
|
|
|
case AF_INET6:
|
|
|
|
add_ipv6_name(&caqm->addr.ip6, he->h_name);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
/* Throw an exception? */
|
|
|
|
break;
|
2008-08-07 21:41:48 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
g_free(caqm);
|
|
|
|
}
|
|
|
|
#endif /* HAVE_C_ARES */
|
|
|
|
|
2009-09-06 08:59:30 +00:00
|
|
|
/* --------------- */
|
2010-04-29 18:17:29 +00:00
|
|
|
static hashipv4_t *
|
|
|
|
new_ipv4(const guint addr)
|
2009-09-06 08:59:30 +00:00
|
|
|
{
|
2010-04-27 22:46:39 +00:00
|
|
|
hashipv4_t *tp = g_malloc(sizeof(hashipv4_t));
|
|
|
|
tp->addr = addr;
|
|
|
|
tp->next = NULL;
|
|
|
|
tp->resolve = FALSE;
|
|
|
|
tp->is_dummy_entry = FALSE;
|
|
|
|
ip_to_str_buf((guint8 *)&addr, tp->ip, sizeof(tp->ip));
|
|
|
|
return tp;
|
2009-09-06 08:59:30 +00:00
|
|
|
}
|
|
|
|
|
2010-04-29 18:17:29 +00:00
|
|
|
static hashipv4_t *
|
|
|
|
host_lookup(const guint addr, const gboolean resolve, gboolean *found)
|
1998-09-16 02:39:15 +00:00
|
|
|
{
|
2001-06-07 22:07:02 +00:00
|
|
|
int hash_idx;
|
2004-11-17 08:53:20 +00:00
|
|
|
hashipv4_t * volatile tp;
|
1998-09-16 02:39:15 +00:00
|
|
|
struct hostent *hostp;
|
|
|
|
|
2000-08-10 20:09:29 +00:00
|
|
|
*found = TRUE;
|
|
|
|
|
2001-06-07 22:07:02 +00:00
|
|
|
hash_idx = HASH_IPV4_ADDRESS(addr);
|
|
|
|
|
2004-11-17 08:53:20 +00:00
|
|
|
tp = ipv4_table[hash_idx];
|
1998-09-16 02:39:15 +00:00
|
|
|
|
|
|
|
if( tp == NULL ) {
|
2009-09-06 08:59:30 +00:00
|
|
|
tp = ipv4_table[hash_idx] = new_ipv4(addr);
|
2002-08-28 20:41:00 +00:00
|
|
|
} else {
|
1998-09-16 02:39:15 +00:00
|
|
|
while(1) {
|
|
|
|
if( tp->addr == addr ) {
|
2010-04-27 22:46:39 +00:00
|
|
|
if (tp->is_dummy_entry && !tp->resolve)
|
|
|
|
break;
|
|
|
|
if (tp->is_dummy_entry)
|
|
|
|
*found = FALSE;
|
|
|
|
return tp;
|
1998-09-16 02:39:15 +00:00
|
|
|
}
|
|
|
|
if (tp->next == NULL) {
|
2010-04-27 22:46:39 +00:00
|
|
|
tp->next = new_ipv4(addr);
|
|
|
|
tp = tp->next;
|
|
|
|
break;
|
1998-09-16 02:39:15 +00:00
|
|
|
}
|
|
|
|
tp = tp->next;
|
|
|
|
}
|
|
|
|
}
|
2002-08-28 20:41:00 +00:00
|
|
|
|
2009-09-06 08:59:30 +00:00
|
|
|
if (resolve) {
|
2010-04-27 22:46:39 +00:00
|
|
|
tp->resolve = TRUE;
|
2009-09-13 17:24:51 +00:00
|
|
|
#ifdef ASYNC_DNS
|
2010-10-12 13:15:08 +00:00
|
|
|
if ((gbl_resolv_flags & RESOLV_CONCURRENT) &&
|
2010-04-27 22:46:39 +00:00
|
|
|
prefs.name_resolve_concurrency > 0 &&
|
|
|
|
async_dns_initialized) {
|
|
|
|
add_async_dns_ipv4(AF_INET, addr);
|
|
|
|
/* XXX found is set to TRUE, which seems a bit odd, but I'm not
|
|
|
|
* going to risk changing the semantics.
|
|
|
|
*/
|
|
|
|
fill_dummy_ip4(addr, tp);
|
|
|
|
return tp;
|
|
|
|
}
|
2009-09-13 17:24:51 +00:00
|
|
|
#endif /* ASYNC_DNS */
|
2003-05-04 18:50:56 +00:00
|
|
|
|
2010-04-27 22:46:39 +00:00
|
|
|
/*
|
|
|
|
* The Windows "gethostbyaddr()" insists on translating 0.0.0.0 to
|
|
|
|
* the name of the host on which it's running; to work around that
|
|
|
|
* botch, we don't try to translate an all-zero IP address to a host
|
|
|
|
* name.
|
|
|
|
*/
|
2010-10-12 13:15:08 +00:00
|
|
|
if (addr != 0 && (gbl_resolv_flags & RESOLV_NETWORK)) {
|
2010-04-27 22:46:39 +00:00
|
|
|
/* Use async DNS if possible, else fall back to timeouts,
|
|
|
|
* else call gethostbyaddr and hope for the best
|
|
|
|
*/
|
2003-05-04 18:50:56 +00:00
|
|
|
|
2000-08-10 22:35:30 +00:00
|
|
|
hostp = gethostbyaddr((char *)&addr, 4, AF_INET);
|
2003-05-04 18:50:56 +00:00
|
|
|
|
2000-08-10 22:35:30 +00:00
|
|
|
if (hostp != NULL) {
|
2010-04-27 22:46:39 +00:00
|
|
|
g_strlcpy(tp->name, hostp->h_name, MAXNAMELEN);
|
|
|
|
tp->is_dummy_entry = FALSE;
|
|
|
|
return tp;
|
2000-08-10 22:35:30 +00:00
|
|
|
}
|
2010-04-27 22:46:39 +00:00
|
|
|
}
|
1998-09-16 02:39:15 +00:00
|
|
|
|
2010-04-27 22:46:39 +00:00
|
|
|
/* unknown host or DNS timeout */
|
2009-09-06 08:59:30 +00:00
|
|
|
|
|
|
|
}
|
|
|
|
|
2000-08-10 20:09:29 +00:00
|
|
|
*found = FALSE;
|
1998-09-25 23:24:07 +00:00
|
|
|
|
2008-01-21 21:44:34 +00:00
|
|
|
fill_dummy_ip4(addr, tp);
|
2009-09-06 08:59:30 +00:00
|
|
|
return tp;
|
1998-09-16 02:39:15 +00:00
|
|
|
|
|
|
|
} /* host_name_lookup */
|
|
|
|
|
2010-04-29 18:17:29 +00:00
|
|
|
static gchar *
|
|
|
|
host_name_lookup(const guint addr, gboolean *found)
|
2009-09-06 08:59:30 +00:00
|
|
|
{
|
|
|
|
hashipv4_t *tp;
|
|
|
|
tp = host_lookup(addr, TRUE, found);
|
|
|
|
return tp->name;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* --------------- */
|
2010-04-29 18:17:29 +00:00
|
|
|
static hashipv6_t *
|
|
|
|
new_ipv6(const struct e_in6_addr *addr)
|
2009-09-06 08:59:30 +00:00
|
|
|
{
|
2010-04-27 22:46:39 +00:00
|
|
|
hashipv6_t *tp = g_malloc(sizeof(hashipv6_t));
|
|
|
|
tp->addr = *addr;
|
|
|
|
tp->next = NULL;
|
|
|
|
tp->resolve = FALSE;
|
|
|
|
tp->is_dummy_entry = FALSE;
|
|
|
|
ip6_to_str_buf(addr, tp->ip6);
|
|
|
|
return tp;
|
2009-09-06 08:59:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* ------------------------------------ */
|
2010-04-29 18:17:29 +00:00
|
|
|
static hashipv6_t *
|
|
|
|
host_lookup6(const struct e_in6_addr *addr, const gboolean resolve, gboolean *found)
|
1999-03-28 18:32:03 +00:00
|
|
|
{
|
2004-11-17 09:44:41 +00:00
|
|
|
int hash_idx;
|
|
|
|
hashipv6_t * volatile tp;
|
2009-09-29 09:49:43 +00:00
|
|
|
#ifdef INET6
|
2008-08-07 21:41:48 +00:00
|
|
|
#ifdef HAVE_C_ARES
|
2009-09-13 17:24:51 +00:00
|
|
|
async_dns_queue_msg_t *caqm;
|
2008-08-07 21:41:48 +00:00
|
|
|
#endif /* HAVE_C_ARES */
|
1999-03-28 18:32:03 +00:00
|
|
|
struct hostent *hostp;
|
2010-10-05 17:57:23 +00:00
|
|
|
#endif /* INET6 */
|
2000-08-10 22:35:30 +00:00
|
|
|
|
2004-11-17 09:44:41 +00:00
|
|
|
*found = TRUE;
|
|
|
|
|
|
|
|
hash_idx = HASH_IPV6_ADDRESS(*addr);
|
|
|
|
|
|
|
|
tp = ipv6_table[hash_idx];
|
|
|
|
|
|
|
|
if( tp == NULL ) {
|
2009-09-06 08:59:30 +00:00
|
|
|
tp = ipv6_table[hash_idx] = new_ipv6(addr);
|
2004-11-17 09:44:41 +00:00
|
|
|
} else {
|
|
|
|
while(1) {
|
|
|
|
if( memcmp(&tp->addr, addr, sizeof (struct e_in6_addr)) == 0 ) {
|
2010-04-27 22:46:39 +00:00
|
|
|
if (tp->is_dummy_entry && !tp->resolve)
|
|
|
|
break;
|
|
|
|
if (tp->is_dummy_entry)
|
|
|
|
*found = FALSE;
|
|
|
|
return tp;
|
2004-11-17 09:44:41 +00:00
|
|
|
}
|
|
|
|
if (tp->next == NULL) {
|
2010-04-27 22:46:39 +00:00
|
|
|
tp->next = new_ipv6(addr);
|
|
|
|
tp = tp->next;
|
|
|
|
break;
|
2004-11-17 09:44:41 +00:00
|
|
|
}
|
|
|
|
tp = tp->next;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-09-06 08:59:30 +00:00
|
|
|
if (resolve) {
|
2010-04-27 22:46:39 +00:00
|
|
|
tp->resolve = TRUE;
|
2009-09-06 08:59:30 +00:00
|
|
|
#ifdef INET6
|
2004-11-17 09:44:41 +00:00
|
|
|
|
2008-08-07 21:41:48 +00:00
|
|
|
#ifdef HAVE_C_ARES
|
2010-10-12 13:15:08 +00:00
|
|
|
if ((gbl_resolv_flags & RESOLV_CONCURRENT) &&
|
2008-08-07 21:41:48 +00:00
|
|
|
prefs.name_resolve_concurrency > 0 &&
|
2009-09-13 17:24:51 +00:00
|
|
|
async_dns_initialized) {
|
|
|
|
caqm = g_malloc(sizeof(async_dns_queue_msg_t));
|
2008-08-07 21:41:48 +00:00
|
|
|
caqm->family = AF_INET6;
|
|
|
|
memcpy(&caqm->addr.ip6, addr, sizeof(caqm->addr.ip6));
|
2009-09-13 17:24:51 +00:00
|
|
|
async_dns_queue_head = g_list_append(async_dns_queue_head, (gpointer) caqm);
|
2008-08-07 21:41:48 +00:00
|
|
|
|
|
|
|
/* XXX found is set to TRUE, which seems a bit odd, but I'm not
|
|
|
|
* going to risk changing the semantics.
|
|
|
|
*/
|
2009-09-07 16:07:04 +00:00
|
|
|
if (!tp->is_dummy_entry) {
|
2010-05-02 20:21:39 +00:00
|
|
|
g_strlcpy(tp->name, tp->ip6, MAXNAMELEN);
|
2010-04-27 22:46:39 +00:00
|
|
|
ip6_to_str_buf(addr, tp->name);
|
|
|
|
tp->is_dummy_entry = TRUE;
|
2009-09-07 16:07:04 +00:00
|
|
|
}
|
|
|
|
return tp;
|
2008-08-07 21:41:48 +00:00
|
|
|
}
|
|
|
|
#endif /* HAVE_C_ARES */
|
|
|
|
|
2010-04-27 22:46:39 +00:00
|
|
|
/* Quick hack to avoid DNS/YP timeout */
|
|
|
|
hostp = gethostbyaddr((char *)addr, sizeof(*addr), AF_INET6);
|
2004-11-17 09:44:41 +00:00
|
|
|
|
2010-04-27 22:46:39 +00:00
|
|
|
if (hostp != NULL) {
|
|
|
|
g_strlcpy(tp->name, hostp->h_name, MAXNAMELEN);
|
|
|
|
tp->is_dummy_entry = FALSE;
|
|
|
|
return tp;
|
|
|
|
}
|
2009-09-06 08:59:30 +00:00
|
|
|
#endif /* INET6 */
|
2000-08-10 22:35:30 +00:00
|
|
|
}
|
1999-03-28 18:32:03 +00:00
|
|
|
|
|
|
|
/* unknown host or DNS timeout */
|
2009-09-06 08:59:30 +00:00
|
|
|
if (!tp->is_dummy_entry) {
|
2009-09-07 16:07:04 +00:00
|
|
|
tp->is_dummy_entry = TRUE;
|
2010-05-02 20:21:39 +00:00
|
|
|
g_strlcpy(tp->name, tp->ip6, MAXNAMELEN);
|
2009-09-06 08:59:30 +00:00
|
|
|
}
|
2000-08-10 20:09:29 +00:00
|
|
|
*found = FALSE;
|
2009-09-06 08:59:30 +00:00
|
|
|
return tp;
|
|
|
|
|
|
|
|
} /* host_lookup6 */
|
2004-11-17 09:44:41 +00:00
|
|
|
|
2009-09-06 08:59:30 +00:00
|
|
|
#if 0
|
2010-04-29 18:17:29 +00:00
|
|
|
static gchar *
|
|
|
|
host_name_lookup6(struct e_in6_addr *addr, gboolean *found)
|
2009-09-06 08:59:30 +00:00
|
|
|
{
|
|
|
|
hashipv6_t *tp;
|
|
|
|
tp = host_lookup6(addr, TRUE, found);
|
|
|
|
return tp->name;
|
|
|
|
}
|
|
|
|
#endif
|
1999-03-28 18:32:03 +00:00
|
|
|
|
2010-04-29 18:17:29 +00:00
|
|
|
static const gchar *
|
|
|
|
solve_address_to_name(const address *addr)
|
2005-02-22 01:55:04 +00:00
|
|
|
{
|
|
|
|
switch (addr->type) {
|
|
|
|
|
|
|
|
case AT_ETHER:
|
|
|
|
return get_ether_name(addr->data);
|
|
|
|
|
2009-09-07 15:49:14 +00:00
|
|
|
case AT_IPv4: {
|
2010-01-28 16:03:03 +00:00
|
|
|
guint32 ip4_addr;
|
|
|
|
memcpy(&ip4_addr, addr->data, sizeof ip4_addr);
|
|
|
|
return get_hostname(ip4_addr);
|
2009-09-07 15:49:14 +00:00
|
|
|
}
|
2005-02-22 01:55:04 +00:00
|
|
|
|
2009-09-07 15:49:14 +00:00
|
|
|
case AT_IPv6: {
|
2010-01-28 16:03:03 +00:00
|
|
|
struct e_in6_addr ip6_addr;
|
|
|
|
memcpy(&ip6_addr.bytes, addr->data, sizeof ip6_addr.bytes);
|
|
|
|
return get_hostname6(&ip6_addr);
|
2009-09-07 15:49:14 +00:00
|
|
|
}
|
2005-02-22 01:55:04 +00:00
|
|
|
|
|
|
|
case AT_STRINGZ:
|
2007-03-28 21:55:11 +00:00
|
|
|
return addr->data;
|
2005-02-22 01:55:04 +00:00
|
|
|
|
|
|
|
default:
|
|
|
|
return NULL;
|
|
|
|
}
|
2009-09-07 15:49:14 +00:00
|
|
|
}
|
2005-02-22 01:55:04 +00:00
|
|
|
|
2010-04-29 18:17:29 +00:00
|
|
|
static const gchar *
|
|
|
|
se_solve_address_to_name(const address *addr)
|
2009-09-07 16:05:37 +00:00
|
|
|
{
|
|
|
|
switch (addr->type) {
|
|
|
|
|
|
|
|
case AT_ETHER:
|
|
|
|
return get_ether_name(addr->data);
|
|
|
|
|
|
|
|
case AT_IPv4: {
|
2010-01-28 16:03:03 +00:00
|
|
|
guint32 ip4_addr;
|
|
|
|
memcpy(&ip4_addr, addr->data, sizeof ip4_addr);
|
|
|
|
return get_hostname(ip4_addr);
|
2009-09-07 16:05:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
case AT_IPv6: {
|
2010-01-28 16:03:03 +00:00
|
|
|
struct e_in6_addr ip6_addr;
|
|
|
|
memcpy(&ip6_addr.bytes, addr->data, sizeof ip6_addr.bytes);
|
|
|
|
return get_hostname6(&ip6_addr);
|
2009-09-07 16:05:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
case AT_STRINGZ:
|
|
|
|
return se_strdup(addr->data);
|
|
|
|
|
|
|
|
default:
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1998-09-25 23:24:07 +00:00
|
|
|
/*
|
|
|
|
* Ethernet / manufacturer resolution
|
|
|
|
*
|
|
|
|
* The following functions implement ethernet address resolution and
|
2002-08-28 20:41:00 +00:00
|
|
|
* ethers files parsing (see ethers(4)).
|
1998-09-25 23:24:07 +00:00
|
|
|
*
|
2002-08-28 20:41:00 +00:00
|
|
|
* The manuf file has the same format as ethers(4) except that names are
|
2010-11-30 22:28:34 +00:00
|
|
|
* truncated to MAXMANUFLEN-1 (8) characters and that an address contains
|
1998-09-25 23:24:07 +00:00
|
|
|
* only 3 bytes (instead of 6).
|
|
|
|
*
|
|
|
|
* Notes:
|
|
|
|
*
|
2002-08-28 20:41:00 +00:00
|
|
|
* I decide to not use the existing functions (see ethers(3) on some
|
1998-09-25 23:24:07 +00:00
|
|
|
* operating systems) for the following reasons:
|
|
|
|
* - performance gains (use of hash tables and some other enhancements),
|
|
|
|
* - use of two ethers files (system-wide and per user),
|
|
|
|
* - avoid the use of NIS maps,
|
|
|
|
* - lack of these functions on some systems.
|
|
|
|
*
|
|
|
|
* So the following functions do _not_ behave as the standard ones.
|
|
|
|
*
|
|
|
|
* -- Laurent.
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
2002-09-09 19:38:11 +00:00
|
|
|
/*
|
|
|
|
* If "manuf_file" is FALSE, parse a 6-byte MAC address.
|
|
|
|
* If "manuf_file" is TRUE, parse an up-to-6-byte sequence with an optional
|
|
|
|
* mask.
|
|
|
|
*/
|
|
|
|
static gboolean
|
|
|
|
parse_ether_address(const char *cp, ether_t *eth, unsigned int *mask,
|
2010-04-03 18:18:50 +00:00
|
|
|
const gboolean manuf_file)
|
2002-09-09 19:38:11 +00:00
|
|
|
{
|
|
|
|
int i;
|
|
|
|
unsigned long num;
|
|
|
|
char *p;
|
|
|
|
char sep = '\0';
|
|
|
|
|
|
|
|
for (i = 0; i < 6; i++) {
|
|
|
|
/* Get a hex number, 1 or 2 digits, no sign characters allowed. */
|
|
|
|
if (!isxdigit((unsigned char)*cp))
|
|
|
|
return FALSE;
|
|
|
|
num = strtoul(cp, &p, 16);
|
|
|
|
if (p == cp)
|
2009-09-07 16:07:04 +00:00
|
|
|
return FALSE; /* failed */
|
2002-09-09 19:38:11 +00:00
|
|
|
if (num > 0xFF)
|
2009-09-07 16:07:04 +00:00
|
|
|
return FALSE; /* not a valid octet */
|
2004-01-05 18:11:28 +00:00
|
|
|
eth->addr[i] = (guint8) num;
|
2009-09-07 16:07:04 +00:00
|
|
|
cp = p; /* skip past the number */
|
2002-09-09 19:38:11 +00:00
|
|
|
|
|
|
|
/* OK, what character terminated the octet? */
|
|
|
|
if (*cp == '/') {
|
|
|
|
/* "/" - this has a mask. */
|
|
|
|
if (!manuf_file) {
|
2009-09-07 16:07:04 +00:00
|
|
|
/* Entries with masks are allowed only in the "manuf" files. */
|
2010-04-27 22:46:39 +00:00
|
|
|
return FALSE;
|
2002-09-09 19:38:11 +00:00
|
|
|
}
|
2009-09-07 16:07:04 +00:00
|
|
|
cp++; /* skip past the '/' to get to the mask */
|
2002-09-09 19:38:11 +00:00
|
|
|
if (!isdigit((unsigned char)*cp))
|
2010-04-27 22:46:39 +00:00
|
|
|
return FALSE; /* no sign allowed */
|
2002-09-09 19:38:11 +00:00
|
|
|
num = strtoul(cp, &p, 10);
|
|
|
|
if (p == cp)
|
2010-04-27 22:46:39 +00:00
|
|
|
return FALSE; /* failed */
|
2009-09-07 16:07:04 +00:00
|
|
|
cp = p; /* skip past the number */
|
2002-09-09 19:38:11 +00:00
|
|
|
if (*cp != '\0' && !isspace((unsigned char)*cp))
|
2010-04-27 22:46:39 +00:00
|
|
|
return FALSE; /* bogus terminator */
|
2002-09-09 19:38:11 +00:00
|
|
|
if (num == 0 || num >= 48)
|
2010-04-27 22:46:39 +00:00
|
|
|
return FALSE; /* bogus mask */
|
2002-09-09 19:38:11 +00:00
|
|
|
/* Mask out the bits not covered by the mask */
|
|
|
|
*mask = num;
|
|
|
|
for (i = 0; num >= 8; i++, num -= 8)
|
2010-04-27 22:46:39 +00:00
|
|
|
; /* skip octets entirely covered by the mask */
|
2002-09-09 19:38:11 +00:00
|
|
|
/* Mask out the first masked octet */
|
|
|
|
eth->addr[i] &= (0xFF << (8 - num));
|
|
|
|
i++;
|
|
|
|
/* Mask out completely-masked-out octets */
|
|
|
|
for (; i < 6; i++)
|
2010-04-27 22:46:39 +00:00
|
|
|
eth->addr[i] = 0;
|
2002-09-09 19:38:11 +00:00
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
if (*cp == '\0') {
|
|
|
|
/* We're at the end of the address, and there's no mask. */
|
|
|
|
if (i == 2) {
|
2010-04-27 22:46:39 +00:00
|
|
|
/* We got 3 bytes, so this is a manufacturer ID. */
|
|
|
|
if (!manuf_file) {
|
|
|
|
/* Manufacturer IDs are only allowed in the "manuf"
|
|
|
|
files. */
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
/* Indicate that this is a manufacturer ID (0 is not allowed
|
|
|
|
as a mask). */
|
|
|
|
*mask = 0;
|
|
|
|
return TRUE;
|
2002-09-09 19:38:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (i == 5) {
|
2010-04-27 22:46:39 +00:00
|
|
|
/* We got 6 bytes, so this is a MAC address.
|
|
|
|
If we're reading one of the "manuf" files, indicate that
|
|
|
|
this is a MAC address (48 is not allowed as a mask). */
|
|
|
|
if (manuf_file)
|
|
|
|
*mask = 48;
|
|
|
|
return TRUE;
|
2002-09-09 19:38:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* We didn't get 3 or 6 bytes, and there's no mask; this is
|
|
|
|
illegal. */
|
|
|
|
return FALSE;
|
|
|
|
} else {
|
|
|
|
if (sep == '\0') {
|
2010-04-27 22:46:39 +00:00
|
|
|
/* We don't know the separator used in this number; it can either
|
|
|
|
be ':', '-', or '.'. */
|
|
|
|
if (*cp != ':' && *cp != '-' && *cp != '.')
|
|
|
|
return FALSE;
|
|
|
|
sep = *cp; /* subsequent separators must be the same */
|
2002-09-09 19:38:11 +00:00
|
|
|
} else {
|
2010-04-27 22:46:39 +00:00
|
|
|
/* It has to be the same as the first separator */
|
|
|
|
if (*cp != sep)
|
|
|
|
return FALSE;
|
2002-09-09 19:38:11 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
cp++;
|
|
|
|
}
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2010-04-29 18:17:29 +00:00
|
|
|
static int
|
|
|
|
parse_ether_line(char *line, ether_t *eth, unsigned int *mask,
|
|
|
|
const gboolean manuf_file)
|
1998-09-25 23:24:07 +00:00
|
|
|
{
|
|
|
|
/*
|
2004-11-17 08:34:36 +00:00
|
|
|
* See the ethers(4) or ethers(5) man page for ethers file format
|
1998-09-25 23:24:07 +00:00
|
|
|
* (not available on all systems).
|
1999-11-21 16:32:23 +00:00
|
|
|
* We allow both ethernet address separators (':' and '-'),
|
2006-05-28 19:49:07 +00:00
|
|
|
* as well as Wireshark's '.' separator.
|
1998-09-25 23:24:07 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
gchar *cp;
|
2002-08-28 20:41:00 +00:00
|
|
|
|
1998-09-25 23:24:07 +00:00
|
|
|
if ((cp = strchr(line, '#')))
|
|
|
|
*cp = '\0';
|
2002-08-28 20:41:00 +00:00
|
|
|
|
2004-11-17 08:34:36 +00:00
|
|
|
if ((cp = strtok(line, " \t")) == NULL)
|
1998-09-25 23:24:07 +00:00
|
|
|
return -1;
|
|
|
|
|
2002-09-09 19:38:11 +00:00
|
|
|
if (!parse_ether_address(cp, eth, mask, manuf_file))
|
|
|
|
return -1;
|
1998-09-25 23:24:07 +00:00
|
|
|
|
2004-11-17 08:34:36 +00:00
|
|
|
if ((cp = strtok(NULL, " \t")) == NULL)
|
1998-09-25 23:24:07 +00:00
|
|
|
return -1;
|
|
|
|
|
2007-10-26 05:42:12 +00:00
|
|
|
g_strlcpy(eth->name, cp, MAXNAMELEN);
|
1998-09-25 23:24:07 +00:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
} /* parse_ether_line */
|
|
|
|
|
|
|
|
static FILE *eth_p = NULL;
|
|
|
|
|
2010-04-29 18:17:29 +00:00
|
|
|
static void
|
|
|
|
set_ethent(char *path)
|
1998-09-25 23:24:07 +00:00
|
|
|
{
|
|
|
|
if (eth_p)
|
|
|
|
rewind(eth_p);
|
|
|
|
else
|
2008-05-22 15:46:27 +00:00
|
|
|
eth_p = ws_fopen(path, "r");
|
1998-09-25 23:24:07 +00:00
|
|
|
}
|
|
|
|
|
2010-04-29 18:17:29 +00:00
|
|
|
static void
|
|
|
|
end_ethent(void)
|
1998-09-25 23:24:07 +00:00
|
|
|
{
|
|
|
|
if (eth_p) {
|
|
|
|
fclose(eth_p);
|
|
|
|
eth_p = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-04-29 18:17:29 +00:00
|
|
|
static ether_t *
|
|
|
|
get_ethent(unsigned int *mask, const gboolean manuf_file)
|
1998-09-25 23:24:07 +00:00
|
|
|
{
|
2002-08-28 20:41:00 +00:00
|
|
|
|
1998-09-25 23:24:07 +00:00
|
|
|
static ether_t eth;
|
|
|
|
static int size = 0;
|
|
|
|
static char *buf = NULL;
|
2002-08-28 20:41:00 +00:00
|
|
|
|
|
|
|
if (eth_p == NULL)
|
1998-09-25 23:24:07 +00:00
|
|
|
return NULL;
|
|
|
|
|
|
|
|
while (fgetline(&buf, &size, eth_p) >= 0) {
|
2002-09-09 19:38:11 +00:00
|
|
|
if (parse_ether_line(buf, ð, mask, manuf_file) == 0) {
|
1998-09-25 23:24:07 +00:00
|
|
|
return ð
|
|
|
|
}
|
|
|
|
}
|
2002-08-28 20:41:00 +00:00
|
|
|
|
1998-09-25 23:24:07 +00:00
|
|
|
return NULL;
|
|
|
|
|
|
|
|
} /* get_ethent */
|
|
|
|
|
2010-04-29 18:17:29 +00:00
|
|
|
static ether_t *
|
|
|
|
get_ethbyname(const gchar *name)
|
1998-09-25 23:24:07 +00:00
|
|
|
{
|
|
|
|
ether_t *eth;
|
2002-08-28 20:41:00 +00:00
|
|
|
|
2005-07-19 20:44:45 +00:00
|
|
|
set_ethent(g_pethers_path);
|
1998-09-25 23:24:07 +00:00
|
|
|
|
2011-02-17 01:11:05 +00:00
|
|
|
while (((eth = get_ethent(NULL, FALSE)) != NULL) && strncmp(name, eth->name, MAXNAMELEN) != 0)
|
1998-09-25 23:24:07 +00:00
|
|
|
;
|
|
|
|
|
|
|
|
if (eth == NULL) {
|
|
|
|
end_ethent();
|
2002-08-28 20:41:00 +00:00
|
|
|
|
2005-07-19 20:44:45 +00:00
|
|
|
set_ethent(g_ethers_path);
|
1998-09-25 23:24:07 +00:00
|
|
|
|
2011-02-17 01:11:05 +00:00
|
|
|
while (((eth = get_ethent(NULL, FALSE)) != NULL) && strncmp(name, eth->name, MAXNAMELEN) != 0)
|
1998-09-25 23:24:07 +00:00
|
|
|
;
|
|
|
|
|
|
|
|
end_ethent();
|
|
|
|
}
|
|
|
|
|
|
|
|
return eth;
|
|
|
|
|
|
|
|
} /* get_ethbyname */
|
|
|
|
|
2010-04-29 18:17:29 +00:00
|
|
|
static ether_t *
|
|
|
|
get_ethbyaddr(const guint8 *addr)
|
1998-09-25 23:24:07 +00:00
|
|
|
{
|
|
|
|
|
|
|
|
ether_t *eth;
|
2002-08-28 20:41:00 +00:00
|
|
|
|
2005-07-19 20:44:45 +00:00
|
|
|
set_ethent(g_pethers_path);
|
1998-09-25 23:24:07 +00:00
|
|
|
|
2011-02-17 01:11:05 +00:00
|
|
|
while (((eth = get_ethent(NULL, FALSE)) != NULL) && memcmp(addr, eth->addr, 6) != 0)
|
1998-09-25 23:24:07 +00:00
|
|
|
;
|
|
|
|
|
|
|
|
if (eth == NULL) {
|
|
|
|
end_ethent();
|
2002-08-28 20:41:00 +00:00
|
|
|
|
2005-07-19 20:44:45 +00:00
|
|
|
set_ethent(g_ethers_path);
|
2002-08-28 20:41:00 +00:00
|
|
|
|
2011-02-17 01:11:05 +00:00
|
|
|
while (((eth = get_ethent(NULL, FALSE)) != NULL) && memcmp(addr, eth->addr, 6) != 0)
|
1998-09-25 23:24:07 +00:00
|
|
|
;
|
2002-08-28 20:41:00 +00:00
|
|
|
|
1998-09-25 23:24:07 +00:00
|
|
|
end_ethent();
|
|
|
|
}
|
|
|
|
|
|
|
|
return eth;
|
|
|
|
|
|
|
|
} /* get_ethbyaddr */
|
|
|
|
|
2010-04-29 18:17:29 +00:00
|
|
|
static int
|
|
|
|
hash_eth_wka(const guint8 *addr, unsigned int mask)
|
2002-09-09 19:38:11 +00:00
|
|
|
{
|
|
|
|
if (mask <= 8) {
|
|
|
|
/* All but the topmost byte is masked out */
|
|
|
|
return (addr[0] & (0xFF << (8 - mask))) & (HASHETHSIZE - 1);
|
|
|
|
}
|
|
|
|
mask -= 8;
|
|
|
|
if (mask <= 8) {
|
|
|
|
/* All but the topmost 2 bytes are masked out */
|
|
|
|
return ((addr[0] << 8) | (addr[1] & (0xFF << (8 - mask)))) &
|
|
|
|
(HASHETHSIZE - 1);
|
|
|
|
}
|
|
|
|
mask -= 8;
|
|
|
|
if (mask <= 8) {
|
|
|
|
/* All but the topmost 3 bytes are masked out */
|
|
|
|
return ((addr[0] << 16) | (addr[1] << 8) | (addr[2] & (0xFF << (8 - mask))))
|
|
|
|
& (HASHETHSIZE - 1);
|
|
|
|
}
|
|
|
|
mask -= 8;
|
|
|
|
if (mask <= 8) {
|
|
|
|
/* All but the topmost 4 bytes are masked out */
|
|
|
|
return ((((addr[0] << 8) | addr[1]) ^
|
|
|
|
((addr[2] << 8) | (addr[3] & (0xFF << (8 - mask)))))) &
|
2010-04-29 18:17:29 +00:00
|
|
|
(HASHETHSIZE - 1);
|
2002-09-09 19:38:11 +00:00
|
|
|
}
|
|
|
|
mask -= 8;
|
|
|
|
if (mask <= 8) {
|
|
|
|
/* All but the topmost 5 bytes are masked out */
|
|
|
|
return ((((addr[1] << 8) | addr[2]) ^
|
|
|
|
((addr[3] << 8) | (addr[4] & (0xFF << (8 - mask)))))) &
|
2010-04-29 18:17:29 +00:00
|
|
|
(HASHETHSIZE - 1);
|
2002-09-09 19:38:11 +00:00
|
|
|
}
|
|
|
|
mask -= 8;
|
|
|
|
/* No bytes are fully masked out */
|
|
|
|
return ((((addr[1] << 8) | addr[2]) ^
|
|
|
|
((addr[3] << 8) | (addr[4] & (0xFF << (8 - mask)))))) &
|
2010-04-29 18:17:29 +00:00
|
|
|
(HASHETHSIZE - 1);
|
2002-09-09 19:38:11 +00:00
|
|
|
}
|
|
|
|
|
2010-07-01 15:11:02 +00:00
|
|
|
static hashmanuf_t *
|
2010-11-30 22:28:34 +00:00
|
|
|
manuf_hash_new_entry(const guint8 *addr, gchar *name)
|
|
|
|
{
|
2010-07-01 15:11:02 +00:00
|
|
|
hashmanuf_t *mtp;
|
|
|
|
|
|
|
|
mtp = (hashmanuf_t *)g_malloc(sizeof(hashmanuf_t));
|
|
|
|
memcpy(mtp->addr, addr, sizeof(mtp->addr));
|
2010-11-30 22:28:34 +00:00
|
|
|
/* The length of this name is limited (in the number of UTF-8 characters,
|
|
|
|
* not bytes) in make-manuf. That doesn't mean a user can't put a longer
|
|
|
|
* name in their personal manuf file, though...
|
|
|
|
*/
|
|
|
|
mtp->name = g_strdup(name);
|
2010-07-01 15:11:02 +00:00
|
|
|
mtp->next = NULL;
|
|
|
|
return mtp;
|
|
|
|
} /* manuf_hash_new_entry */
|
|
|
|
|
|
|
|
static hashwka_t *
|
2010-11-30 22:28:34 +00:00
|
|
|
wka_hash_new_entry(const guint8 *addr, gchar *name)
|
|
|
|
{
|
2010-07-01 15:11:02 +00:00
|
|
|
hashwka_t *wtp;
|
|
|
|
|
|
|
|
wtp = (hashwka_t *)g_malloc(sizeof(hashwka_t));
|
|
|
|
memcpy(wtp->addr, addr, sizeof(wtp->addr));
|
|
|
|
g_strlcpy(wtp->name, name, MAXNAMELEN);
|
|
|
|
wtp->next = NULL;
|
|
|
|
return wtp;
|
|
|
|
} /* wka_hash_new_entry */
|
|
|
|
|
2010-04-29 18:17:29 +00:00
|
|
|
static void
|
|
|
|
add_manuf_name(const guint8 *addr, unsigned int mask, gchar *name)
|
1998-09-25 23:24:07 +00:00
|
|
|
{
|
2010-06-29 02:53:17 +00:00
|
|
|
gint hash_idx;
|
|
|
|
hashmanuf_t *mtp;
|
|
|
|
hashwka_t *(*wka_tp)[HASHETHSIZE], *wtp;
|
1998-09-25 23:24:07 +00:00
|
|
|
|
2011-02-17 09:08:11 +00:00
|
|
|
/*
|
|
|
|
* XXX - can we use Standard Annotation Language annotations to
|
|
|
|
* note that mask, as returned by parse_ether_address() (and thus
|
|
|
|
* by the routines that call it, and thus passed to us) cannot be > 48,
|
|
|
|
* or is SAL too weak to express that?
|
|
|
|
*/
|
2011-02-17 01:11:05 +00:00
|
|
|
if (mask >= 48) {
|
2002-09-09 19:38:11 +00:00
|
|
|
/* This is a well-known MAC address; just add this to the Ethernet
|
|
|
|
hash table */
|
|
|
|
add_eth_name(addr, name);
|
|
|
|
return;
|
|
|
|
}
|
2001-06-07 22:07:02 +00:00
|
|
|
|
2002-09-09 19:38:11 +00:00
|
|
|
if (mask == 0) {
|
|
|
|
/* This is a manufacturer ID; add it to the manufacturer ID hash table */
|
1998-09-25 23:24:07 +00:00
|
|
|
|
2002-09-09 19:38:11 +00:00
|
|
|
hash_idx = HASH_ETH_MANUF(addr);
|
2010-06-29 02:53:17 +00:00
|
|
|
mtp = manuf_table[hash_idx];
|
2002-09-09 19:38:11 +00:00
|
|
|
|
2010-06-29 02:53:17 +00:00
|
|
|
if( mtp == NULL ) {
|
2010-07-01 15:11:02 +00:00
|
|
|
manuf_table[hash_idx] = manuf_hash_new_entry(addr, name);
|
|
|
|
return;
|
2002-09-09 19:38:11 +00:00
|
|
|
} else {
|
2010-07-01 15:11:02 +00:00
|
|
|
while(TRUE) {
|
2010-06-29 02:53:17 +00:00
|
|
|
if (mtp->next == NULL) {
|
2010-07-01 15:11:02 +00:00
|
|
|
mtp->next = manuf_hash_new_entry(addr, name);
|
|
|
|
return;
|
2010-06-28 22:43:13 +00:00
|
|
|
}
|
2010-06-29 02:53:17 +00:00
|
|
|
mtp = mtp->next;
|
2002-09-09 19:38:11 +00:00
|
|
|
}
|
|
|
|
}
|
2010-07-01 15:11:02 +00:00
|
|
|
} /* mask == 0 */
|
2002-09-09 19:38:11 +00:00
|
|
|
|
|
|
|
/* This is a range of well-known addresses; add it to the appropriate
|
|
|
|
well-known-address table, creating that table if necessary. */
|
|
|
|
wka_tp = wka_table[mask];
|
|
|
|
if (wka_tp == NULL)
|
2002-09-10 10:12:34 +00:00
|
|
|
wka_tp = wka_table[mask] = g_malloc0(sizeof *wka_table[mask]);
|
2002-09-09 19:38:11 +00:00
|
|
|
|
|
|
|
hash_idx = hash_eth_wka(addr, mask);
|
|
|
|
|
2010-06-29 02:53:17 +00:00
|
|
|
wtp = (*wka_tp)[hash_idx];
|
2002-09-09 19:38:11 +00:00
|
|
|
|
2010-06-29 02:53:17 +00:00
|
|
|
if( wtp == NULL ) {
|
2010-07-01 15:11:02 +00:00
|
|
|
(*wka_tp)[hash_idx] = wka_hash_new_entry(addr, name);
|
|
|
|
return;
|
2002-08-28 20:41:00 +00:00
|
|
|
} else {
|
2010-07-01 15:11:02 +00:00
|
|
|
while(TRUE) {
|
2010-06-29 02:53:17 +00:00
|
|
|
if (memcmp(wtp->addr, addr, sizeof(wtp->addr)) == 0) {
|
2010-06-28 22:43:13 +00:00
|
|
|
/* address already known */
|
|
|
|
return;
|
2002-09-09 19:38:11 +00:00
|
|
|
}
|
2010-06-29 02:53:17 +00:00
|
|
|
if (wtp->next == NULL) {
|
2010-07-01 15:11:02 +00:00
|
|
|
wtp->next = wka_hash_new_entry(addr, name);
|
|
|
|
return;
|
1998-09-25 23:24:07 +00:00
|
|
|
}
|
2010-06-29 02:53:17 +00:00
|
|
|
wtp = wtp->next;
|
1998-09-25 23:24:07 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
} /* add_manuf_name */
|
|
|
|
|
2010-04-29 18:17:29 +00:00
|
|
|
static hashmanuf_t *
|
|
|
|
manuf_name_lookup(const guint8 *addr)
|
1998-09-25 23:24:07 +00:00
|
|
|
{
|
2010-06-29 02:53:17 +00:00
|
|
|
gint hash_idx;
|
|
|
|
hashmanuf_t *mtp;
|
|
|
|
guint8 stripped_addr[3];
|
1998-09-25 23:24:07 +00:00
|
|
|
|
2001-06-07 22:07:02 +00:00
|
|
|
hash_idx = HASH_ETH_MANUF(addr);
|
|
|
|
|
2007-08-14 23:52:51 +00:00
|
|
|
/* first try to find a "perfect match" */
|
2010-06-29 02:53:17 +00:00
|
|
|
mtp = manuf_table[hash_idx];
|
|
|
|
while(mtp != NULL) {
|
|
|
|
if (memcmp(mtp->addr, addr, sizeof(mtp->addr)) == 0) {
|
|
|
|
return mtp;
|
1998-09-25 23:24:07 +00:00
|
|
|
}
|
2010-06-29 02:53:17 +00:00
|
|
|
mtp = mtp->next;
|
1998-09-25 23:24:07 +00:00
|
|
|
}
|
2002-08-28 20:41:00 +00:00
|
|
|
|
2007-08-15 13:21:23 +00:00
|
|
|
/* Mask out the broadcast/multicast flag but not the locally
|
|
|
|
* administered flag as localy administered means: not assigend
|
|
|
|
* by the IEEE but the local administrator instead.
|
|
|
|
* 0x01 multicast / broadcast bit
|
|
|
|
* 0x02 locally administered bit */
|
2007-08-14 23:52:51 +00:00
|
|
|
memcpy(stripped_addr, addr, 3);
|
2007-08-15 13:21:23 +00:00
|
|
|
stripped_addr[0] &= 0xFE;
|
2007-08-14 23:52:51 +00:00
|
|
|
|
2010-06-29 02:53:17 +00:00
|
|
|
mtp = manuf_table[hash_idx];
|
|
|
|
while(mtp != NULL) {
|
|
|
|
if (memcmp(mtp->addr, stripped_addr, sizeof(mtp->addr)) == 0) {
|
|
|
|
return mtp;
|
2007-08-14 23:52:51 +00:00
|
|
|
}
|
2010-06-29 02:53:17 +00:00
|
|
|
mtp = mtp->next;
|
2007-08-14 23:52:51 +00:00
|
|
|
}
|
|
|
|
|
1998-09-25 23:24:07 +00:00
|
|
|
return NULL;
|
|
|
|
|
|
|
|
} /* manuf_name_lookup */
|
|
|
|
|
2010-06-29 02:53:17 +00:00
|
|
|
static hashwka_t *
|
2010-04-29 18:17:29 +00:00
|
|
|
wka_name_lookup(const guint8 *addr, const unsigned int mask)
|
2002-09-09 19:38:11 +00:00
|
|
|
{
|
2010-06-29 02:53:17 +00:00
|
|
|
gint hash_idx;
|
|
|
|
hashwka_t *(*wka_tp)[HASHETHSIZE];
|
|
|
|
hashwka_t *wtp;
|
|
|
|
guint8 masked_addr[6];
|
|
|
|
guint num;
|
|
|
|
gint i;
|
2002-09-09 19:38:11 +00:00
|
|
|
|
|
|
|
wka_tp = wka_table[mask];
|
|
|
|
if (wka_tp == NULL) {
|
|
|
|
/* There are no entries in the table for that mask value, as there is
|
|
|
|
no table for that mask value. */
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Get the part of the address covered by the mask. */
|
|
|
|
for (i = 0, num = mask; num >= 8; i++, num -= 8)
|
2009-09-07 16:07:04 +00:00
|
|
|
masked_addr[i] = addr[i]; /* copy octets entirely covered by the mask */
|
2002-09-09 19:38:11 +00:00
|
|
|
/* Mask out the first masked octet */
|
|
|
|
masked_addr[i] = addr[i] & (0xFF << (8 - num));
|
|
|
|
i++;
|
|
|
|
/* Zero out completely-masked-out octets */
|
|
|
|
for (; i < 6; i++)
|
|
|
|
masked_addr[i] = 0;
|
|
|
|
|
|
|
|
hash_idx = hash_eth_wka(masked_addr, mask);
|
|
|
|
|
2010-06-29 02:53:17 +00:00
|
|
|
wtp = (*wka_tp)[hash_idx];
|
2002-09-09 19:38:11 +00:00
|
|
|
|
2010-06-29 02:53:17 +00:00
|
|
|
while(wtp != NULL) {
|
|
|
|
if (memcmp(wtp->addr, masked_addr, sizeof(wtp->addr)) == 0) {
|
|
|
|
return wtp;
|
2002-09-09 19:38:11 +00:00
|
|
|
}
|
2010-06-29 02:53:17 +00:00
|
|
|
wtp = wtp->next;
|
2002-09-09 19:38:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
} /* wka_name_lookup */
|
|
|
|
|
2010-04-29 18:17:29 +00:00
|
|
|
static void
|
|
|
|
initialize_ethers(void)
|
1999-11-20 05:35:15 +00:00
|
|
|
{
|
|
|
|
ether_t *eth;
|
2010-06-29 02:53:17 +00:00
|
|
|
char *manuf_path;
|
|
|
|
guint mask;
|
1999-11-20 05:35:15 +00:00
|
|
|
|
2001-10-21 21:48:00 +00:00
|
|
|
/* Compute the pathname of the ethers file. */
|
2001-10-21 19:54:49 +00:00
|
|
|
if (g_ethers_path == NULL) {
|
2004-05-20 13:43:14 +00:00
|
|
|
g_ethers_path = g_strdup_printf("%s" G_DIR_SEPARATOR_S "%s",
|
2010-06-28 22:43:13 +00:00
|
|
|
get_systemfile_dir(), ENAME_ETHERS);
|
2001-10-21 19:54:49 +00:00
|
|
|
}
|
|
|
|
|
1999-11-20 05:35:15 +00:00
|
|
|
/* Set g_pethers_path here, but don't actually do anything
|
|
|
|
* with it. It's used in get_ethbyname() and get_ethbyaddr()
|
|
|
|
*/
|
2001-10-24 07:18:39 +00:00
|
|
|
if (g_pethers_path == NULL)
|
2008-01-14 16:40:23 +00:00
|
|
|
g_pethers_path = get_persconffile_path(ENAME_ETHERS, FALSE, FALSE);
|
1999-11-20 05:35:15 +00:00
|
|
|
|
|
|
|
/* manuf hash table initialization */
|
|
|
|
|
On Windows, use the directory in which the binary resides as the
directory in which global data files are stored. If an installed binary
is being run, that's the correct directory for them; if a build-tree
binary is being run, the "manuf" file will be there, and you can put
other data files there as well, if necessary.
Do the same with plugins, except that, if there's no
"plugins\\{version}" subdirectory of that directory, fall back on the
default installation directory, so you at least have a place where you
can put plugins for use by build-tree binaries. (Should we, instead,
have the Windows build procedure create a subdirectory of the "plugins"
source directory, with the plugin version number as its name, and copy
the plugins there, so you'd use the build-tree plugin binaries?)
Move "test_for_directory()" out of "util.c" and into
"epan/filesystem.c", with the other file system access portability
wrappers and convenience routines. Fix "util.h" not to declare it - or
other routines moved to "epan/filesystem.c" a while ago.
svn path=/trunk/; revision=3858
2001-08-21 06:39:18 +00:00
|
|
|
/* Compute the pathname of the manuf file */
|
2003-05-15 07:44:54 +00:00
|
|
|
manuf_path = get_datafile_path(ENAME_MANUF);
|
2002-08-28 20:41:00 +00:00
|
|
|
|
On Windows, use the directory in which the binary resides as the
directory in which global data files are stored. If an installed binary
is being run, that's the correct directory for them; if a build-tree
binary is being run, the "manuf" file will be there, and you can put
other data files there as well, if necessary.
Do the same with plugins, except that, if there's no
"plugins\\{version}" subdirectory of that directory, fall back on the
default installation directory, so you at least have a place where you
can put plugins for use by build-tree binaries. (Should we, instead,
have the Windows build procedure create a subdirectory of the "plugins"
source directory, with the plugin version number as its name, and copy
the plugins there, so you'd use the build-tree plugin binaries?)
Move "test_for_directory()" out of "util.c" and into
"epan/filesystem.c", with the other file system access portability
wrappers and convenience routines. Fix "util.h" not to declare it - or
other routines moved to "epan/filesystem.c" a while ago.
svn path=/trunk/; revision=3858
2001-08-21 06:39:18 +00:00
|
|
|
/* Read it and initialize the hash table */
|
|
|
|
set_ethent(manuf_path);
|
1999-11-20 05:35:15 +00:00
|
|
|
|
2002-09-09 19:38:11 +00:00
|
|
|
while ((eth = get_ethent(&mask, TRUE))) {
|
|
|
|
add_manuf_name(eth->addr, mask, eth->name);
|
1999-11-20 05:35:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
end_ethent();
|
|
|
|
|
On Windows, use the directory in which the binary resides as the
directory in which global data files are stored. If an installed binary
is being run, that's the correct directory for them; if a build-tree
binary is being run, the "manuf" file will be there, and you can put
other data files there as well, if necessary.
Do the same with plugins, except that, if there's no
"plugins\\{version}" subdirectory of that directory, fall back on the
default installation directory, so you at least have a place where you
can put plugins for use by build-tree binaries. (Should we, instead,
have the Windows build procedure create a subdirectory of the "plugins"
source directory, with the plugin version number as its name, and copy
the plugins there, so you'd use the build-tree plugin binaries?)
Move "test_for_directory()" out of "util.c" and into
"epan/filesystem.c", with the other file system access portability
wrappers and convenience routines. Fix "util.h" not to declare it - or
other routines moved to "epan/filesystem.c" a while ago.
svn path=/trunk/; revision=3858
2001-08-21 06:39:18 +00:00
|
|
|
g_free(manuf_path);
|
|
|
|
|
1999-11-20 05:35:15 +00:00
|
|
|
} /* initialize_ethers */
|
|
|
|
|
2010-07-01 15:11:02 +00:00
|
|
|
/* Resolve ethernet address */
|
2010-04-29 18:17:29 +00:00
|
|
|
static hashether_t *
|
2010-07-01 15:11:02 +00:00
|
|
|
eth_addr_resolve(hashether_t *tp) {
|
2010-06-29 02:53:17 +00:00
|
|
|
ether_t *eth;
|
2010-07-01 15:11:02 +00:00
|
|
|
const guint8 *addr = tp->addr;
|
2002-08-28 20:41:00 +00:00
|
|
|
|
2010-07-01 15:11:02 +00:00
|
|
|
if ( (eth = get_ethbyaddr(addr)) != NULL) {
|
|
|
|
g_strlcpy(tp->resolved_name, eth->name, MAXNAMELEN);
|
|
|
|
tp->status = HASHETHER_STATUS_RESOLVED_NAME;
|
2010-04-27 22:46:39 +00:00
|
|
|
return tp;
|
2010-07-01 15:11:02 +00:00
|
|
|
} else {
|
|
|
|
hashwka_t *wtp;
|
|
|
|
hashmanuf_t *mtp;
|
|
|
|
guint mask;
|
1998-09-25 23:24:07 +00:00
|
|
|
|
2002-09-09 19:38:11 +00:00
|
|
|
/* Unknown name. Try looking for it in the well-known-address
|
|
|
|
tables for well-known address ranges smaller than 2^24. */
|
|
|
|
mask = 7;
|
|
|
|
for (;;) {
|
|
|
|
/* Only the topmost 5 bytes participate fully */
|
2010-06-29 02:53:17 +00:00
|
|
|
if ((wtp = wka_name_lookup(addr, mask+40)) != NULL) {
|
2010-07-01 15:11:02 +00:00
|
|
|
g_snprintf(tp->resolved_name, MAXNAMELEN, "%s_%02x",
|
2010-06-29 02:53:17 +00:00
|
|
|
wtp->name, addr[5] & (0xFF >> mask));
|
2010-07-01 15:11:02 +00:00
|
|
|
tp->status = HASHETHER_STATUS_RESOLVED_DUMMY;
|
2010-04-27 22:46:39 +00:00
|
|
|
return tp;
|
2002-09-09 19:38:11 +00:00
|
|
|
}
|
|
|
|
if (mask == 0)
|
|
|
|
break;
|
|
|
|
mask--;
|
|
|
|
}
|
|
|
|
|
|
|
|
mask = 7;
|
|
|
|
for (;;) {
|
|
|
|
/* Only the topmost 4 bytes participate fully */
|
2010-06-29 02:53:17 +00:00
|
|
|
if ((wtp = wka_name_lookup(addr, mask+32)) != NULL) {
|
2010-07-01 15:11:02 +00:00
|
|
|
g_snprintf(tp->resolved_name, MAXNAMELEN, "%s_%02x:%02x",
|
2010-06-29 02:53:17 +00:00
|
|
|
wtp->name, addr[4] & (0xFF >> mask), addr[5]);
|
2010-07-01 15:11:02 +00:00
|
|
|
tp->status = HASHETHER_STATUS_RESOLVED_DUMMY;
|
2010-04-27 22:46:39 +00:00
|
|
|
return tp;
|
2002-09-09 19:38:11 +00:00
|
|
|
}
|
|
|
|
if (mask == 0)
|
|
|
|
break;
|
|
|
|
mask--;
|
|
|
|
}
|
|
|
|
|
|
|
|
mask = 7;
|
|
|
|
for (;;) {
|
|
|
|
/* Only the topmost 3 bytes participate fully */
|
2010-06-29 02:53:17 +00:00
|
|
|
if ((wtp = wka_name_lookup(addr, mask+24)) != NULL) {
|
2010-07-01 15:11:02 +00:00
|
|
|
g_snprintf(tp->resolved_name, MAXNAMELEN, "%s_%02x:%02x:%02x",
|
2010-06-29 02:53:17 +00:00
|
|
|
wtp->name, addr[3] & (0xFF >> mask), addr[4], addr[5]);
|
2010-07-01 15:11:02 +00:00
|
|
|
tp->status = HASHETHER_STATUS_RESOLVED_DUMMY;
|
2010-04-27 22:46:39 +00:00
|
|
|
return tp;
|
2002-09-09 19:38:11 +00:00
|
|
|
}
|
|
|
|
if (mask == 0)
|
|
|
|
break;
|
|
|
|
mask--;
|
|
|
|
}
|
1998-09-25 23:24:07 +00:00
|
|
|
|
2002-09-09 19:38:11 +00:00
|
|
|
/* Now try looking in the manufacturer table. */
|
2010-06-29 02:53:17 +00:00
|
|
|
if ((mtp = manuf_name_lookup(addr)) != NULL) {
|
2010-07-01 15:11:02 +00:00
|
|
|
g_snprintf(tp->resolved_name, MAXNAMELEN, "%s_%02x:%02x:%02x",
|
2010-06-29 02:53:17 +00:00
|
|
|
mtp->name, addr[3], addr[4], addr[5]);
|
2010-07-01 15:11:02 +00:00
|
|
|
tp->status = HASHETHER_STATUS_RESOLVED_DUMMY;
|
2009-09-06 08:59:30 +00:00
|
|
|
return tp;
|
2002-09-09 19:38:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Now try looking for it in the well-known-address
|
|
|
|
tables for well-known address ranges larger than 2^24. */
|
|
|
|
mask = 7;
|
|
|
|
for (;;) {
|
|
|
|
/* Only the topmost 2 bytes participate fully */
|
2010-06-29 02:53:17 +00:00
|
|
|
if ((wtp = wka_name_lookup(addr, mask+16)) != NULL) {
|
2010-07-01 15:11:02 +00:00
|
|
|
g_snprintf(tp->resolved_name, MAXNAMELEN, "%s_%02x:%02x:%02x:%02x",
|
2010-06-29 02:53:17 +00:00
|
|
|
wtp->name, addr[2] & (0xFF >> mask), addr[3], addr[4],
|
2010-04-27 22:46:39 +00:00
|
|
|
addr[5]);
|
2010-07-01 15:11:02 +00:00
|
|
|
tp->status = HASHETHER_STATUS_RESOLVED_DUMMY;
|
2010-04-27 22:46:39 +00:00
|
|
|
return tp;
|
2002-09-09 19:38:11 +00:00
|
|
|
}
|
|
|
|
if (mask == 0)
|
|
|
|
break;
|
|
|
|
mask--;
|
|
|
|
}
|
|
|
|
|
|
|
|
mask = 7;
|
|
|
|
for (;;) {
|
|
|
|
/* Only the topmost byte participates fully */
|
2010-06-29 02:53:17 +00:00
|
|
|
if ((wtp = wka_name_lookup(addr, mask+8)) != NULL) {
|
2010-07-01 15:11:02 +00:00
|
|
|
g_snprintf(tp->resolved_name, MAXNAMELEN, "%s_%02x:%02x:%02x:%02x:%02x",
|
2010-06-29 02:53:17 +00:00
|
|
|
wtp->name, addr[1] & (0xFF >> mask), addr[2], addr[3],
|
2010-04-27 22:46:39 +00:00
|
|
|
addr[4], addr[5]);
|
2010-07-01 15:11:02 +00:00
|
|
|
tp->status = HASHETHER_STATUS_RESOLVED_DUMMY;
|
2010-04-27 22:46:39 +00:00
|
|
|
return tp;
|
2002-09-09 19:38:11 +00:00
|
|
|
}
|
|
|
|
if (mask == 0)
|
|
|
|
break;
|
|
|
|
mask--;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (mask = 7; mask > 0; mask--) {
|
|
|
|
/* Not even the topmost byte participates fully */
|
2010-06-29 02:53:17 +00:00
|
|
|
if ((wtp = wka_name_lookup(addr, mask)) != NULL) {
|
2010-07-01 15:11:02 +00:00
|
|
|
g_snprintf(tp->resolved_name, MAXNAMELEN, "%s_%02x:%02x:%02x:%02x:%02x:%02x",
|
2010-06-29 02:53:17 +00:00
|
|
|
wtp->name, addr[0] & (0xFF >> mask), addr[1], addr[2],
|
2010-04-27 22:46:39 +00:00
|
|
|
addr[3], addr[4], addr[5]);
|
2010-07-01 15:11:02 +00:00
|
|
|
tp->status = HASHETHER_STATUS_RESOLVED_DUMMY;
|
2010-04-27 22:46:39 +00:00
|
|
|
return tp;
|
2002-09-09 19:38:11 +00:00
|
|
|
}
|
|
|
|
}
|
1998-09-25 23:24:07 +00:00
|
|
|
|
2002-09-09 19:38:11 +00:00
|
|
|
/* No match whatsoever. */
|
2010-07-01 15:11:02 +00:00
|
|
|
g_snprintf(tp->resolved_name, MAXNAMELEN, "%s", ether_to_str(addr));
|
|
|
|
tp->status = HASHETHER_STATUS_RESOLVED_DUMMY;
|
|
|
|
return tp;
|
|
|
|
}
|
|
|
|
g_assert_not_reached();
|
|
|
|
} /* eth_addr_resolve */
|
1999-11-20 05:35:15 +00:00
|
|
|
|
2010-07-01 15:11:02 +00:00
|
|
|
static hashether_t *
|
|
|
|
eth_hash_new_entry(const guint8 *addr, const gboolean resolve) {
|
|
|
|
hashether_t *tp;
|
|
|
|
|
|
|
|
tp = (hashether_t *)g_malloc(sizeof(hashether_t));
|
|
|
|
memcpy(tp->addr, addr, sizeof(tp->addr));
|
|
|
|
tp->status = HASHETHER_STATUS_UNRESOLVED;
|
|
|
|
g_strlcpy(tp->hexaddr, bytestring_to_str(addr, sizeof(tp->addr), ':'), sizeof(tp->hexaddr));
|
|
|
|
tp->resolved_name[0] = '\0';
|
|
|
|
tp->next = NULL;
|
|
|
|
|
|
|
|
if (resolve)
|
|
|
|
eth_addr_resolve(tp);
|
|
|
|
|
|
|
|
return tp;
|
|
|
|
} /* eth_hash_new_entry */
|
|
|
|
|
|
|
|
static hashether_t *
|
|
|
|
add_eth_name(const guint8 *addr, const gchar *name)
|
|
|
|
{
|
|
|
|
gint hash_idx;
|
|
|
|
hashether_t *tp;
|
|
|
|
|
|
|
|
hash_idx = HASH_ETH_ADDRESS(addr);
|
|
|
|
|
|
|
|
tp = eth_table[hash_idx];
|
|
|
|
if( tp == NULL ) {
|
|
|
|
tp = eth_table[hash_idx] = eth_hash_new_entry(addr, FALSE);
|
1998-09-25 23:24:07 +00:00
|
|
|
} else {
|
2010-07-01 15:11:02 +00:00
|
|
|
while(TRUE) {
|
|
|
|
if (memcmp(tp->addr, addr, sizeof(tp->addr)) == 0) {
|
|
|
|
/* address already known */
|
|
|
|
if (tp->status == HASHETHER_STATUS_RESOLVED_NAME)
|
|
|
|
return tp; /* Entry with a name already in table; ignore attempted replacement */
|
|
|
|
break; /* Update name of existing entry */
|
|
|
|
}
|
|
|
|
if (tp->next == NULL) {
|
|
|
|
tp = tp->next = eth_hash_new_entry(addr, FALSE);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
tp = tp->next;
|
|
|
|
}
|
1998-09-25 23:24:07 +00:00
|
|
|
}
|
|
|
|
|
2010-07-01 15:11:02 +00:00
|
|
|
g_strlcpy(tp->resolved_name, name, MAXNAMELEN);
|
|
|
|
tp->status = HASHETHER_STATUS_RESOLVED_NAME;
|
|
|
|
new_resolved_objects = TRUE;
|
|
|
|
|
2009-09-06 08:59:30 +00:00
|
|
|
return tp;
|
2010-07-01 15:11:02 +00:00
|
|
|
} /* add_eth_name */
|
1998-09-25 23:24:07 +00:00
|
|
|
|
2010-07-01 15:11:02 +00:00
|
|
|
static hashether_t *
|
|
|
|
eth_name_lookup(const guint8 *addr, const gboolean resolve) {
|
|
|
|
gint hash_idx;
|
|
|
|
hashether_t *tp;
|
|
|
|
|
|
|
|
hash_idx = HASH_ETH_ADDRESS(addr);
|
|
|
|
|
|
|
|
tp = eth_table[hash_idx];
|
|
|
|
if( tp == NULL ) {
|
|
|
|
tp = eth_table[hash_idx] = eth_hash_new_entry(addr, resolve);
|
|
|
|
return tp;
|
|
|
|
} else {
|
|
|
|
while(TRUE) {
|
|
|
|
if (memcmp(tp->addr, addr, sizeof(tp->addr)) == 0) {
|
|
|
|
if (resolve && (tp->status == HASHETHER_STATUS_UNRESOLVED))
|
|
|
|
eth_addr_resolve(tp); /* Found but needs to be resolved */
|
|
|
|
return tp;
|
|
|
|
}
|
|
|
|
if (tp->next == NULL) {
|
|
|
|
tp->next = eth_hash_new_entry(addr, resolve);
|
|
|
|
return tp->next;
|
|
|
|
}
|
|
|
|
tp = tp->next;
|
|
|
|
}
|
|
|
|
}
|
1998-09-25 23:24:07 +00:00
|
|
|
} /* eth_name_lookup */
|
|
|
|
|
2010-04-29 18:17:29 +00:00
|
|
|
static guint8 *
|
|
|
|
eth_addr_lookup(const gchar *name)
|
1999-11-20 05:35:15 +00:00
|
|
|
{
|
2010-06-29 02:53:17 +00:00
|
|
|
ether_t *eth;
|
|
|
|
hashether_t *tp;
|
1999-11-20 05:35:15 +00:00
|
|
|
hashether_t **table = eth_table;
|
2010-06-29 02:53:17 +00:00
|
|
|
gint i;
|
1999-11-20 05:35:15 +00:00
|
|
|
|
1999-11-21 16:32:23 +00:00
|
|
|
/* to be optimized (hash table from name to addr) */
|
|
|
|
for (i = 0; i < HASHETHSIZE; i++) {
|
|
|
|
tp = table[i];
|
|
|
|
while (tp) {
|
2010-07-01 15:11:02 +00:00
|
|
|
if (strcmp(tp->resolved_name, name) == 0)
|
2010-06-28 22:43:13 +00:00
|
|
|
return tp->addr;
|
1999-11-21 16:32:23 +00:00
|
|
|
tp = tp->next;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* not in hash table : performs a file lookup */
|
|
|
|
|
|
|
|
if ((eth = get_ethbyname(name)) == NULL)
|
1999-11-20 05:35:15 +00:00
|
|
|
return NULL;
|
1999-11-21 16:32:23 +00:00
|
|
|
|
|
|
|
/* add new entry in hash table */
|
|
|
|
|
|
|
|
tp = add_eth_name(eth->addr, name);
|
|
|
|
|
|
|
|
return tp->addr;
|
|
|
|
|
|
|
|
} /* eth_addr_lookup */
|
|
|
|
|
|
|
|
|
|
|
|
/* IPXNETS */
|
2010-04-29 18:17:29 +00:00
|
|
|
static int
|
|
|
|
parse_ipxnets_line(char *line, ipxnet_t *ipxnet)
|
1999-11-21 16:32:23 +00:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
* We allow three address separators (':', '-', and '.'),
|
|
|
|
* as well as no separators
|
|
|
|
*/
|
|
|
|
|
2009-09-07 16:07:04 +00:00
|
|
|
gchar *cp;
|
|
|
|
guint32 a, a0, a1, a2, a3;
|
|
|
|
gboolean found_single_number = FALSE;
|
2002-08-28 20:41:00 +00:00
|
|
|
|
1999-11-21 16:32:23 +00:00
|
|
|
if ((cp = strchr(line, '#')))
|
|
|
|
*cp = '\0';
|
2002-08-28 20:41:00 +00:00
|
|
|
|
1999-11-21 16:32:23 +00:00
|
|
|
if ((cp = strtok(line, " \t\n")) == NULL)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
/* Either fill a0,a1,a2,a3 and found_single_number is FALSE,
|
|
|
|
* fill a and found_single_number is TRUE,
|
|
|
|
* or return -1
|
|
|
|
*/
|
|
|
|
if (sscanf(cp, "%x:%x:%x:%x", &a0, &a1, &a2, &a3) != 4) {
|
|
|
|
if (sscanf(cp, "%x-%x-%x-%x", &a0, &a1, &a2, &a3) != 4) {
|
|
|
|
if (sscanf(cp, "%x.%x.%x.%x", &a0, &a1, &a2, &a3) != 4) {
|
|
|
|
if (sscanf(cp, "%x", &a) == 1) {
|
2010-04-27 22:46:39 +00:00
|
|
|
found_single_number = TRUE;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
return -1;
|
|
|
|
}
|
1999-11-21 16:32:23 +00:00
|
|
|
}
|
|
|
|
}
|
1999-11-20 05:35:15 +00:00
|
|
|
}
|
|
|
|
|
1999-11-21 16:32:23 +00:00
|
|
|
if ((cp = strtok(NULL, " \t\n")) == NULL)
|
|
|
|
return -1;
|
1999-11-20 05:35:15 +00:00
|
|
|
|
1999-11-21 16:32:23 +00:00
|
|
|
if (found_single_number) {
|
2009-09-07 16:07:04 +00:00
|
|
|
ipxnet->addr = a;
|
1999-11-21 16:32:23 +00:00
|
|
|
}
|
|
|
|
else {
|
2009-09-07 16:07:04 +00:00
|
|
|
ipxnet->addr = (a0 << 24) | (a1 << 16) | (a2 << 8) | a3;
|
1999-11-21 16:32:23 +00:00
|
|
|
}
|
|
|
|
|
2007-10-26 05:42:12 +00:00
|
|
|
g_strlcpy(ipxnet->name, cp, MAXNAMELEN);
|
1999-11-21 16:32:23 +00:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
} /* parse_ipxnets_line */
|
|
|
|
|
|
|
|
static FILE *ipxnet_p = NULL;
|
|
|
|
|
2010-04-29 18:17:29 +00:00
|
|
|
static void
|
|
|
|
set_ipxnetent(char *path)
|
1999-11-21 16:32:23 +00:00
|
|
|
{
|
|
|
|
if (ipxnet_p)
|
|
|
|
rewind(ipxnet_p);
|
|
|
|
else
|
2008-05-22 15:46:27 +00:00
|
|
|
ipxnet_p = ws_fopen(path, "r");
|
1999-11-21 16:32:23 +00:00
|
|
|
}
|
|
|
|
|
2010-04-29 18:17:29 +00:00
|
|
|
static void
|
|
|
|
end_ipxnetent(void)
|
1999-11-21 16:32:23 +00:00
|
|
|
{
|
|
|
|
if (ipxnet_p) {
|
|
|
|
fclose(ipxnet_p);
|
|
|
|
ipxnet_p = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-04-29 18:17:29 +00:00
|
|
|
static ipxnet_t *
|
|
|
|
get_ipxnetent(void)
|
1999-11-21 16:32:23 +00:00
|
|
|
{
|
2002-08-28 20:41:00 +00:00
|
|
|
|
1999-11-21 16:32:23 +00:00
|
|
|
static ipxnet_t ipxnet;
|
|
|
|
static int size = 0;
|
|
|
|
static char *buf = NULL;
|
2002-08-28 20:41:00 +00:00
|
|
|
|
|
|
|
if (ipxnet_p == NULL)
|
1999-11-21 16:32:23 +00:00
|
|
|
return NULL;
|
|
|
|
|
|
|
|
while (fgetline(&buf, &size, ipxnet_p) >= 0) {
|
|
|
|
if (parse_ipxnets_line(buf, &ipxnet) == 0) {
|
|
|
|
return &ipxnet;
|
|
|
|
}
|
|
|
|
}
|
2002-08-28 20:41:00 +00:00
|
|
|
|
1999-11-21 16:32:23 +00:00
|
|
|
return NULL;
|
|
|
|
|
|
|
|
} /* get_ipxnetent */
|
|
|
|
|
2010-04-29 18:17:29 +00:00
|
|
|
static ipxnet_t *
|
|
|
|
get_ipxnetbyname(const gchar *name)
|
1999-11-21 16:32:23 +00:00
|
|
|
{
|
|
|
|
ipxnet_t *ipxnet;
|
2002-08-28 20:41:00 +00:00
|
|
|
|
1999-11-21 16:32:23 +00:00
|
|
|
set_ipxnetent(g_ipxnets_path);
|
|
|
|
|
2011-02-17 01:11:05 +00:00
|
|
|
while (((ipxnet = get_ipxnetent()) != NULL) && strncmp(name, ipxnet->name, MAXNAMELEN) != 0)
|
1999-11-21 16:32:23 +00:00
|
|
|
;
|
|
|
|
|
|
|
|
if (ipxnet == NULL) {
|
|
|
|
end_ipxnetent();
|
2002-08-28 20:41:00 +00:00
|
|
|
|
1999-11-21 16:32:23 +00:00
|
|
|
set_ipxnetent(g_pipxnets_path);
|
|
|
|
|
2011-02-17 01:11:05 +00:00
|
|
|
while (((ipxnet = get_ipxnetent()) != NULL) && strncmp(name, ipxnet->name, MAXNAMELEN) != 0)
|
1999-11-21 16:32:23 +00:00
|
|
|
;
|
|
|
|
|
|
|
|
end_ipxnetent();
|
|
|
|
}
|
|
|
|
|
|
|
|
return ipxnet;
|
|
|
|
|
|
|
|
} /* get_ipxnetbyname */
|
|
|
|
|
2010-04-29 18:17:29 +00:00
|
|
|
static ipxnet_t *
|
|
|
|
get_ipxnetbyaddr(guint32 addr)
|
1999-11-21 16:32:23 +00:00
|
|
|
{
|
|
|
|
ipxnet_t *ipxnet;
|
2002-08-28 20:41:00 +00:00
|
|
|
|
1999-11-21 16:32:23 +00:00
|
|
|
set_ipxnetent(g_ipxnets_path);
|
|
|
|
|
2011-02-17 01:11:05 +00:00
|
|
|
while (((ipxnet = get_ipxnetent()) != NULL) && (addr != ipxnet->addr) ) ;
|
1999-11-21 16:32:23 +00:00
|
|
|
|
|
|
|
if (ipxnet == NULL) {
|
|
|
|
end_ipxnetent();
|
2002-08-28 20:41:00 +00:00
|
|
|
|
1999-11-21 16:32:23 +00:00
|
|
|
set_ipxnetent(g_pipxnets_path);
|
2002-08-28 20:41:00 +00:00
|
|
|
|
2011-02-17 01:11:05 +00:00
|
|
|
while (((ipxnet = get_ipxnetent()) != NULL) && (addr != ipxnet->addr) )
|
1999-11-21 16:32:23 +00:00
|
|
|
;
|
2002-08-28 20:41:00 +00:00
|
|
|
|
1999-11-21 16:32:23 +00:00
|
|
|
end_ipxnetent();
|
|
|
|
}
|
|
|
|
|
|
|
|
return ipxnet;
|
|
|
|
|
|
|
|
} /* get_ipxnetbyaddr */
|
|
|
|
|
2010-04-29 18:17:29 +00:00
|
|
|
static void
|
|
|
|
initialize_ipxnets(void)
|
1999-11-21 16:32:23 +00:00
|
|
|
{
|
2001-10-21 19:54:49 +00:00
|
|
|
/* Compute the pathname of the ipxnets file.
|
|
|
|
*
|
|
|
|
* XXX - is there a notion of an "ipxnets file" in any flavor of
|
|
|
|
* UNIX, or with any add-on Netware package for UNIX? If not,
|
|
|
|
* should the UNIX version of the ipxnets file be in the datafile
|
|
|
|
* directory as well?
|
|
|
|
*/
|
|
|
|
if (g_ipxnets_path == NULL) {
|
2009-09-07 16:07:04 +00:00
|
|
|
g_ipxnets_path = g_strdup_printf("%s" G_DIR_SEPARATOR_S "%s",
|
2010-04-27 22:46:39 +00:00
|
|
|
get_systemfile_dir(), ENAME_IPXNETS);
|
2001-10-21 19:54:49 +00:00
|
|
|
}
|
1999-11-21 16:32:23 +00:00
|
|
|
|
|
|
|
/* Set g_pipxnets_path here, but don't actually do anything
|
|
|
|
* with it. It's used in get_ipxnetbyname() and get_ipxnetbyaddr()
|
|
|
|
*/
|
2001-10-24 07:18:39 +00:00
|
|
|
if (g_pipxnets_path == NULL)
|
2008-01-14 16:40:23 +00:00
|
|
|
g_pipxnets_path = get_persconffile_path(ENAME_IPXNETS, FALSE, FALSE);
|
1999-11-21 16:32:23 +00:00
|
|
|
|
|
|
|
} /* initialize_ipxnets */
|
|
|
|
|
2010-04-29 18:17:29 +00:00
|
|
|
static hashipxnet_t *
|
|
|
|
add_ipxnet_name(guint addr, const gchar *name)
|
1999-11-21 16:32:23 +00:00
|
|
|
{
|
2001-06-07 22:07:02 +00:00
|
|
|
int hash_idx;
|
1999-11-21 16:32:23 +00:00
|
|
|
hashipxnet_t *tp;
|
|
|
|
|
2001-06-07 22:07:02 +00:00
|
|
|
hash_idx = HASH_IPX_NET(addr);
|
1999-11-21 16:32:23 +00:00
|
|
|
|
2001-06-07 22:07:02 +00:00
|
|
|
tp = ipxnet_table[hash_idx];
|
1999-11-20 05:35:15 +00:00
|
|
|
|
|
|
|
if( tp == NULL ) {
|
2001-06-07 22:07:02 +00:00
|
|
|
tp = ipxnet_table[hash_idx] = (hashipxnet_t *)g_malloc(sizeof(hashipxnet_t));
|
2002-08-28 20:41:00 +00:00
|
|
|
} else {
|
1999-11-21 16:32:23 +00:00
|
|
|
while(1) {
|
|
|
|
if (tp->next == NULL) {
|
2009-12-22 20:01:06 +00:00
|
|
|
tp->next = (hashipxnet_t *)g_malloc(sizeof(hashipxnet_t));
|
|
|
|
tp = tp->next;
|
|
|
|
break;
|
1999-11-21 16:32:23 +00:00
|
|
|
}
|
|
|
|
tp = tp->next;
|
|
|
|
}
|
1999-11-20 05:35:15 +00:00
|
|
|
}
|
2002-08-28 20:41:00 +00:00
|
|
|
|
1999-11-21 16:32:23 +00:00
|
|
|
tp->addr = addr;
|
2007-10-26 05:42:12 +00:00
|
|
|
g_strlcpy(tp->name, name, MAXNAMELEN);
|
1999-11-21 16:32:23 +00:00
|
|
|
tp->next = NULL;
|
2009-12-22 20:01:06 +00:00
|
|
|
new_resolved_objects = TRUE;
|
1999-11-21 16:32:23 +00:00
|
|
|
|
|
|
|
return tp;
|
|
|
|
|
|
|
|
} /* add_ipxnet_name */
|
|
|
|
|
2010-04-29 18:17:29 +00:00
|
|
|
static gchar *
|
|
|
|
ipxnet_name_lookup(const guint addr)
|
1999-11-21 16:32:23 +00:00
|
|
|
{
|
2001-06-07 22:07:02 +00:00
|
|
|
int hash_idx;
|
1999-11-21 16:32:23 +00:00
|
|
|
hashipxnet_t *tp;
|
|
|
|
ipxnet_t *ipxnet;
|
|
|
|
|
2001-06-07 22:07:02 +00:00
|
|
|
hash_idx = HASH_IPX_NET(addr);
|
|
|
|
|
|
|
|
tp = ipxnet_table[hash_idx];
|
1999-11-21 16:32:23 +00:00
|
|
|
|
|
|
|
if( tp == NULL ) {
|
2001-06-07 22:07:02 +00:00
|
|
|
tp = ipxnet_table[hash_idx] = (hashipxnet_t *)g_malloc(sizeof(hashipxnet_t));
|
2002-08-28 20:41:00 +00:00
|
|
|
} else {
|
1999-11-20 05:35:15 +00:00
|
|
|
while(1) {
|
1999-11-21 16:32:23 +00:00
|
|
|
if (tp->addr == addr) {
|
2010-06-28 22:43:13 +00:00
|
|
|
return tp->name;
|
1999-11-20 05:35:15 +00:00
|
|
|
}
|
|
|
|
if (tp->next == NULL) {
|
2010-06-28 22:43:13 +00:00
|
|
|
tp->next = (hashipxnet_t *)g_malloc(sizeof(hashipxnet_t));
|
|
|
|
tp = tp->next;
|
|
|
|
break;
|
1999-11-20 05:35:15 +00:00
|
|
|
}
|
|
|
|
tp = tp->next;
|
|
|
|
}
|
|
|
|
}
|
2002-08-28 20:41:00 +00:00
|
|
|
|
1999-11-21 16:32:23 +00:00
|
|
|
/* fill in a new entry */
|
1999-11-20 05:35:15 +00:00
|
|
|
|
1999-11-21 16:32:23 +00:00
|
|
|
tp->addr = addr;
|
|
|
|
tp->next = NULL;
|
|
|
|
|
|
|
|
if ( (ipxnet = get_ipxnetbyaddr(addr)) == NULL) {
|
|
|
|
/* unknown name */
|
2010-04-29 18:17:29 +00:00
|
|
|
g_snprintf(tp->name, MAXNAMELEN, "%X", addr);
|
1999-11-21 16:32:23 +00:00
|
|
|
|
|
|
|
} else {
|
2007-10-26 05:42:12 +00:00
|
|
|
g_strlcpy(tp->name, ipxnet->name, MAXNAMELEN);
|
1999-11-21 16:32:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return (tp->name);
|
|
|
|
|
|
|
|
} /* ipxnet_name_lookup */
|
|
|
|
|
2010-04-29 18:17:29 +00:00
|
|
|
static guint
|
|
|
|
ipxnet_addr_lookup(const gchar *name, gboolean *success)
|
1998-09-25 23:24:07 +00:00
|
|
|
{
|
1999-11-21 16:32:23 +00:00
|
|
|
ipxnet_t *ipxnet;
|
|
|
|
hashipxnet_t *tp;
|
|
|
|
hashipxnet_t **table = ipxnet_table;
|
1998-09-25 23:24:07 +00:00
|
|
|
int i;
|
|
|
|
|
|
|
|
/* to be optimized (hash table from name to addr) */
|
1999-11-21 16:32:23 +00:00
|
|
|
for (i = 0; i < HASHIPXNETSIZE; i++) {
|
1998-09-25 23:24:07 +00:00
|
|
|
tp = table[i];
|
|
|
|
while (tp) {
|
2005-05-12 02:50:27 +00:00
|
|
|
if (strcmp(tp->name, name) == 0) {
|
|
|
|
*success = TRUE;
|
2010-06-28 22:43:13 +00:00
|
|
|
return tp->addr;
|
2005-05-12 02:50:27 +00:00
|
|
|
}
|
1998-09-25 23:24:07 +00:00
|
|
|
tp = tp->next;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* not in hash table : performs a file lookup */
|
|
|
|
|
1999-11-21 16:32:23 +00:00
|
|
|
if ((ipxnet = get_ipxnetbyname(name)) == NULL) {
|
2005-05-12 02:50:27 +00:00
|
|
|
*success = FALSE;
|
|
|
|
return 0;
|
1999-11-21 16:32:23 +00:00
|
|
|
}
|
1998-09-25 23:24:07 +00:00
|
|
|
|
|
|
|
/* add new entry in hash table */
|
|
|
|
|
1999-11-21 16:32:23 +00:00
|
|
|
tp = add_ipxnet_name(ipxnet->addr, name);
|
1998-09-25 23:24:07 +00:00
|
|
|
|
1999-11-21 16:32:23 +00:00
|
|
|
*success = TRUE;
|
1998-09-25 23:24:07 +00:00
|
|
|
return tp->addr;
|
|
|
|
|
1999-11-21 16:32:23 +00:00
|
|
|
} /* ipxnet_addr_lookup */
|
1998-09-25 23:24:07 +00:00
|
|
|
|
2011-03-24 22:47:57 +00:00
|
|
|
gboolean
|
2005-01-07 10:20:17 +00:00
|
|
|
read_hosts_file (const char *hostspath)
|
2004-11-17 08:34:36 +00:00
|
|
|
{
|
2005-01-07 10:20:17 +00:00
|
|
|
FILE *hf;
|
2004-11-17 08:34:36 +00:00
|
|
|
char *line = NULL;
|
|
|
|
int size = 0;
|
|
|
|
gchar *cp;
|
|
|
|
guint32 host_addr[4]; /* IPv4 or IPv6 */
|
2010-01-28 16:03:03 +00:00
|
|
|
struct e_in6_addr ip6_addr;
|
2004-11-17 08:34:36 +00:00
|
|
|
gboolean is_ipv6;
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* See the hosts(4) or hosts(5) man page for hosts file format
|
|
|
|
* (not available on all systems).
|
|
|
|
*/
|
2008-05-22 15:46:27 +00:00
|
|
|
if ((hf = ws_fopen(hostspath, "r")) == NULL)
|
2005-01-07 10:20:17 +00:00
|
|
|
return FALSE;
|
|
|
|
|
2004-11-17 08:34:36 +00:00
|
|
|
while (fgetline(&line, &size, hf) >= 0) {
|
|
|
|
if ((cp = strchr(line, '#')))
|
|
|
|
*cp = '\0';
|
|
|
|
|
|
|
|
if ((cp = strtok(line, " \t")) == NULL)
|
|
|
|
continue; /* no tokens in the line */
|
|
|
|
|
|
|
|
ret = inet_pton(AF_INET6, cp, &host_addr);
|
|
|
|
if (ret == -1)
|
|
|
|
continue; /* error parsing */
|
|
|
|
if (ret == 1) {
|
|
|
|
/* Valid IPv6 */
|
|
|
|
is_ipv6 = TRUE;
|
|
|
|
} else {
|
|
|
|
/* Not valid IPv6 - valid IPv4? */
|
|
|
|
if (inet_pton(AF_INET, cp, &host_addr) != 1)
|
|
|
|
continue; /* no */
|
|
|
|
is_ipv6 = FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((cp = strtok(NULL, " \t")) == NULL)
|
|
|
|
continue; /* no host name */
|
|
|
|
|
2004-11-17 09:44:41 +00:00
|
|
|
if (is_ipv6) {
|
2010-01-28 16:03:03 +00:00
|
|
|
memcpy(&ip6_addr, host_addr, sizeof ip6_addr);
|
|
|
|
add_ipv6_name(&ip6_addr, cp);
|
2004-11-17 09:44:41 +00:00
|
|
|
} else
|
2004-11-17 08:53:20 +00:00
|
|
|
add_ipv4_name(host_addr[0], cp);
|
2004-11-17 08:34:36 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Add the aliases, too, if there are any.
|
2011-03-24 22:47:57 +00:00
|
|
|
* XXX - host_lookup() only returns the first entry.
|
2004-11-17 08:34:36 +00:00
|
|
|
*/
|
|
|
|
while ((cp = strtok(NULL, " \t")) != NULL) {
|
2004-11-17 09:44:41 +00:00
|
|
|
if (is_ipv6) {
|
2010-01-28 16:03:03 +00:00
|
|
|
memcpy(&ip6_addr, host_addr, sizeof ip6_addr);
|
|
|
|
add_ipv6_name(&ip6_addr, cp);
|
2004-11-17 09:44:41 +00:00
|
|
|
} else
|
2004-11-17 08:53:20 +00:00
|
|
|
add_ipv4_name(host_addr[0], cp);
|
2004-11-17 08:34:36 +00:00
|
|
|
}
|
|
|
|
}
|
2009-03-13 22:06:48 +00:00
|
|
|
g_free(line);
|
2005-01-07 10:20:17 +00:00
|
|
|
|
|
|
|
fclose(hf);
|
|
|
|
return TRUE;
|
2004-11-17 08:34:36 +00:00
|
|
|
} /* read_hosts_file */
|
1998-09-25 23:24:07 +00:00
|
|
|
|
2010-04-27 06:51:16 +00:00
|
|
|
gboolean
|
2010-04-27 22:46:39 +00:00
|
|
|
add_ip_name_from_string (const char *addr, const char *name)
|
2010-04-27 06:51:16 +00:00
|
|
|
{
|
|
|
|
guint32 host_addr[4]; /* IPv4 */
|
|
|
|
struct e_in6_addr ip6_addr; /* IPv6 */
|
|
|
|
gboolean is_ipv6;
|
|
|
|
int ret;
|
|
|
|
|
2010-04-27 22:46:39 +00:00
|
|
|
ret = inet_pton(AF_INET6, addr, &ip6_addr);
|
2010-04-27 06:51:16 +00:00
|
|
|
if (ret == -1)
|
|
|
|
/* Error parsing address */
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
if (ret == 1) {
|
|
|
|
/* Valid IPv6 */
|
|
|
|
is_ipv6 = TRUE;
|
|
|
|
} else {
|
|
|
|
/* Not valid IPv6 - valid IPv4? */
|
2010-04-27 22:46:39 +00:00
|
|
|
if (inet_pton(AF_INET, addr, &host_addr) != 1)
|
2010-04-27 06:51:16 +00:00
|
|
|
return FALSE; /* no */
|
|
|
|
is_ipv6 = FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (is_ipv6) {
|
|
|
|
add_ipv6_name(&ip6_addr, name);
|
|
|
|
} else {
|
|
|
|
add_ipv4_name(host_addr[0], name);
|
|
|
|
}
|
|
|
|
|
|
|
|
return TRUE;
|
2010-04-27 22:46:39 +00:00
|
|
|
} /* add_ip_name_from_string */
|
2010-04-27 06:51:16 +00:00
|
|
|
|
2011-03-24 22:47:57 +00:00
|
|
|
struct addrinfo *
|
|
|
|
get_addrinfo_list(void) {
|
|
|
|
return addrinfo_list;
|
|
|
|
}
|
2008-01-21 21:44:34 +00:00
|
|
|
|
|
|
|
/* Read in a list of subnet definition - name pairs.
|
|
|
|
* <line> = <comment> | <entry> | <whitespace>
|
|
|
|
* <comment> = <whitespace>#<any>
|
2008-05-22 15:46:27 +00:00
|
|
|
* <entry> = <subnet_definition> <whitespace> <subnet_name> [<comment>|<whitespace><any>]
|
2008-01-21 21:44:34 +00:00
|
|
|
* <subnet_definition> = <ipv4_address> / <subnet_mask_length>
|
|
|
|
* <ipv4_address> is a full address; it will be masked to get the subnet-ID.
|
|
|
|
* <subnet_mask_length> is a decimal 1-31
|
|
|
|
* <subnet_name> is a string containing no whitespace.
|
|
|
|
* <whitespace> = (space | tab)+
|
|
|
|
* Any malformed entries are ignored.
|
|
|
|
* Any trailing data after the subnet_name is ignored.
|
|
|
|
*
|
|
|
|
* XXX Support IPv6
|
|
|
|
*/
|
|
|
|
static gboolean
|
|
|
|
read_subnets_file (const char *subnetspath)
|
|
|
|
{
|
|
|
|
FILE *hf;
|
|
|
|
char *line = NULL;
|
|
|
|
int size = 0;
|
|
|
|
gchar *cp, *cp2;
|
|
|
|
guint32 host_addr; /* IPv4 ONLY */
|
|
|
|
int mask_length;
|
|
|
|
|
2008-05-22 15:46:27 +00:00
|
|
|
if ((hf = ws_fopen(subnetspath, "r")) == NULL)
|
2008-01-21 21:44:34 +00:00
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
while (fgetline(&line, &size, hf) >= 0) {
|
|
|
|
if ((cp = strchr(line, '#')))
|
|
|
|
*cp = '\0';
|
|
|
|
|
|
|
|
if ((cp = strtok(line, " \t")) == NULL)
|
|
|
|
continue; /* no tokens in the line */
|
|
|
|
|
|
|
|
|
|
|
|
/* Expected format is <IP4 address>/<subnet length> */
|
|
|
|
cp2 = strchr(cp, '/');
|
|
|
|
if(NULL == cp2) {
|
2008-01-24 18:51:54 +00:00
|
|
|
/* No length */
|
2008-01-21 21:44:34 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
*cp2 = '\0'; /* Cut token */
|
|
|
|
++cp2 ;
|
2008-05-22 15:46:27 +00:00
|
|
|
|
2008-01-21 21:44:34 +00:00
|
|
|
/* Check if this is a valid IPv4 address */
|
|
|
|
if (inet_pton(AF_INET, cp, &host_addr) != 1) {
|
|
|
|
continue; /* no */
|
|
|
|
}
|
|
|
|
|
|
|
|
mask_length = atoi(cp2);
|
|
|
|
if(0 >= mask_length || mask_length > 31) {
|
|
|
|
continue; /* invalid mask length */
|
2008-05-22 15:46:27 +00:00
|
|
|
}
|
2008-01-21 21:44:34 +00:00
|
|
|
|
|
|
|
if ((cp = strtok(NULL, " \t")) == NULL)
|
|
|
|
continue; /* no subnet name */
|
|
|
|
|
|
|
|
subnet_entry_set(host_addr, (guint32)mask_length, cp);
|
|
|
|
}
|
2009-03-13 22:06:48 +00:00
|
|
|
g_free(line);
|
2008-01-21 21:44:34 +00:00
|
|
|
|
|
|
|
fclose(hf);
|
|
|
|
return TRUE;
|
|
|
|
} /* read_subnets_file */
|
|
|
|
|
2010-04-29 18:17:29 +00:00
|
|
|
static subnet_entry_t
|
|
|
|
subnet_lookup(const guint32 addr)
|
2008-01-21 21:44:34 +00:00
|
|
|
{
|
2010-04-27 22:46:39 +00:00
|
|
|
subnet_entry_t subnet_entry;
|
|
|
|
guint32 i;
|
2008-01-21 21:44:34 +00:00
|
|
|
|
2010-04-27 22:46:39 +00:00
|
|
|
/* Search mask lengths linearly, longest first */
|
2008-01-21 21:44:34 +00:00
|
|
|
|
2010-04-27 22:46:39 +00:00
|
|
|
i = SUBNETLENGTHSIZE;
|
|
|
|
while(have_subnet_entry && i > 0) {
|
|
|
|
guint32 masked_addr;
|
|
|
|
subnet_length_entry_t* length_entry;
|
2008-05-22 15:46:27 +00:00
|
|
|
|
2010-04-27 22:46:39 +00:00
|
|
|
/* Note that we run from 31 (length 32) to 0 (length 1) */
|
|
|
|
--i;
|
|
|
|
g_assert(i < SUBNETLENGTHSIZE);
|
2008-01-21 21:44:34 +00:00
|
|
|
|
|
|
|
|
2010-04-27 22:46:39 +00:00
|
|
|
length_entry = &subnet_length_entries[i];
|
2008-01-21 21:44:34 +00:00
|
|
|
|
2010-04-27 22:46:39 +00:00
|
|
|
if(NULL != length_entry->subnet_addresses) {
|
|
|
|
hashipv4_t * tp;
|
|
|
|
guint32 hash_idx;
|
2008-05-22 15:46:27 +00:00
|
|
|
|
2010-04-27 22:46:39 +00:00
|
|
|
masked_addr = addr & length_entry->mask;
|
|
|
|
hash_idx = HASH_IPV4_ADDRESS(masked_addr);
|
2008-01-21 21:44:34 +00:00
|
|
|
|
2010-04-27 22:46:39 +00:00
|
|
|
tp = length_entry->subnet_addresses[hash_idx];
|
|
|
|
while(tp != NULL && tp->addr != masked_addr) {
|
|
|
|
tp = tp->next;
|
|
|
|
}
|
2008-01-21 21:44:34 +00:00
|
|
|
|
2010-04-27 22:46:39 +00:00
|
|
|
if(NULL != tp) {
|
|
|
|
subnet_entry.mask = length_entry->mask;
|
|
|
|
subnet_entry.mask_length = i + 1; /* Length is offset + 1 */
|
|
|
|
subnet_entry.name = tp->name;
|
|
|
|
return subnet_entry;
|
|
|
|
}
|
2008-01-21 21:44:34 +00:00
|
|
|
}
|
2010-04-27 22:46:39 +00:00
|
|
|
}
|
2008-05-22 15:46:27 +00:00
|
|
|
|
2010-04-27 22:46:39 +00:00
|
|
|
subnet_entry.mask = 0;
|
|
|
|
subnet_entry.mask_length = 0;
|
|
|
|
subnet_entry.name = NULL;
|
2008-01-21 21:44:34 +00:00
|
|
|
|
2010-04-27 22:46:39 +00:00
|
|
|
return subnet_entry;
|
2008-01-21 21:44:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Add a subnet-definition - name pair to the set.
|
|
|
|
* The definition is taken by masking the address passed in with the mask of the
|
|
|
|
* given length.
|
|
|
|
*/
|
2010-04-29 18:17:29 +00:00
|
|
|
static void
|
|
|
|
subnet_entry_set(guint32 subnet_addr, const guint32 mask_length, const gchar* name)
|
2008-01-21 21:44:34 +00:00
|
|
|
{
|
2010-04-27 22:46:39 +00:00
|
|
|
subnet_length_entry_t* entry;
|
|
|
|
hashipv4_t * tp;
|
|
|
|
gsize hash_idx;
|
2008-01-21 21:44:34 +00:00
|
|
|
|
2010-04-27 22:46:39 +00:00
|
|
|
g_assert(mask_length > 0 && mask_length <= 32);
|
2008-01-21 21:44:34 +00:00
|
|
|
|
2010-04-27 22:46:39 +00:00
|
|
|
entry = &subnet_length_entries[mask_length - 1];
|
2008-01-21 21:44:34 +00:00
|
|
|
|
2010-04-27 22:46:39 +00:00
|
|
|
subnet_addr &= entry->mask;
|
2008-01-21 21:44:34 +00:00
|
|
|
|
2010-04-27 22:46:39 +00:00
|
|
|
hash_idx = HASH_IPV4_ADDRESS(subnet_addr);
|
2008-01-21 21:44:34 +00:00
|
|
|
|
2010-04-27 22:46:39 +00:00
|
|
|
if(NULL == entry->subnet_addresses) {
|
|
|
|
entry->subnet_addresses = g_new0(hashipv4_t*,HASHHOSTSIZE);
|
|
|
|
}
|
2008-01-21 21:44:34 +00:00
|
|
|
|
2010-04-27 22:46:39 +00:00
|
|
|
if(NULL != (tp = entry->subnet_addresses[hash_idx])) {
|
|
|
|
if(tp->addr == subnet_addr) {
|
|
|
|
return; /* XXX provide warning that an address was repeated? */
|
2008-01-21 21:44:34 +00:00
|
|
|
} else {
|
2010-04-27 22:46:39 +00:00
|
|
|
hashipv4_t * new_tp = g_new(hashipv4_t,1);
|
|
|
|
tp->next = new_tp;
|
|
|
|
tp = new_tp;
|
2008-01-21 21:44:34 +00:00
|
|
|
}
|
2010-04-27 22:46:39 +00:00
|
|
|
} else {
|
|
|
|
tp = entry->subnet_addresses[hash_idx] = g_new(hashipv4_t,1);
|
|
|
|
}
|
2008-01-21 21:44:34 +00:00
|
|
|
|
2010-04-27 22:46:39 +00:00
|
|
|
tp->next = NULL;
|
|
|
|
tp->addr = subnet_addr;
|
|
|
|
tp->is_dummy_entry = FALSE; /*Never used again...*/
|
|
|
|
g_strlcpy(tp->name, name, MAXNAMELEN); /* This is longer than subnet names can actually be */
|
|
|
|
have_subnet_entry = TRUE;
|
2008-01-21 21:44:34 +00:00
|
|
|
}
|
|
|
|
|
2010-04-29 18:17:29 +00:00
|
|
|
static guint32
|
|
|
|
get_subnet_mask(const guint32 mask_length) {
|
2008-01-21 21:44:34 +00:00
|
|
|
|
2010-04-27 22:46:39 +00:00
|
|
|
static guint32 masks[SUBNETLENGTHSIZE];
|
|
|
|
static gboolean initialised = FALSE;
|
2008-05-22 15:46:27 +00:00
|
|
|
|
2010-04-27 22:46:39 +00:00
|
|
|
if(!initialised) {
|
|
|
|
memset(masks, 0, sizeof(masks));
|
|
|
|
|
|
|
|
initialised = TRUE;
|
|
|
|
|
|
|
|
/* XXX There must be a better way to do this than
|
|
|
|
* hand-coding the values, but I can't seem to
|
|
|
|
* come up with one!
|
|
|
|
*/
|
|
|
|
|
|
|
|
inet_pton(AF_INET, "128.0.0.0", &masks[0]);
|
|
|
|
inet_pton(AF_INET, "192.0.0.0", &masks[1]);
|
|
|
|
inet_pton(AF_INET, "224.0.0.0", &masks[2]);
|
|
|
|
inet_pton(AF_INET, "240.0.0.0", &masks[3]);
|
|
|
|
inet_pton(AF_INET, "248.0.0.0", &masks[4]);
|
|
|
|
inet_pton(AF_INET, "252.0.0.0", &masks[5]);
|
|
|
|
inet_pton(AF_INET, "254.0.0.0", &masks[6]);
|
|
|
|
inet_pton(AF_INET, "255.0.0.0", &masks[7]);
|
|
|
|
|
|
|
|
inet_pton(AF_INET, "255.128.0.0", &masks[8]);
|
|
|
|
inet_pton(AF_INET, "255.192.0.0", &masks[9]);
|
|
|
|
inet_pton(AF_INET, "255.224.0.0", &masks[10]);
|
|
|
|
inet_pton(AF_INET, "255.240.0.0", &masks[11]);
|
|
|
|
inet_pton(AF_INET, "255.248.0.0", &masks[12]);
|
|
|
|
inet_pton(AF_INET, "255.252.0.0", &masks[13]);
|
|
|
|
inet_pton(AF_INET, "255.254.0.0", &masks[14]);
|
|
|
|
inet_pton(AF_INET, "255.255.0.0", &masks[15]);
|
|
|
|
|
|
|
|
inet_pton(AF_INET, "255.255.128.0", &masks[16]);
|
|
|
|
inet_pton(AF_INET, "255.255.192.0", &masks[17]);
|
|
|
|
inet_pton(AF_INET, "255.255.224.0", &masks[18]);
|
|
|
|
inet_pton(AF_INET, "255.255.240.0", &masks[19]);
|
|
|
|
inet_pton(AF_INET, "255.255.248.0", &masks[20]);
|
|
|
|
inet_pton(AF_INET, "255.255.252.0", &masks[21]);
|
|
|
|
inet_pton(AF_INET, "255.255.254.0", &masks[22]);
|
|
|
|
inet_pton(AF_INET, "255.255.255.0", &masks[23]);
|
|
|
|
|
|
|
|
inet_pton(AF_INET, "255.255.255.128", &masks[24]);
|
|
|
|
inet_pton(AF_INET, "255.255.255.192", &masks[25]);
|
|
|
|
inet_pton(AF_INET, "255.255.255.224", &masks[26]);
|
|
|
|
inet_pton(AF_INET, "255.255.255.240", &masks[27]);
|
|
|
|
inet_pton(AF_INET, "255.255.255.248", &masks[28]);
|
|
|
|
inet_pton(AF_INET, "255.255.255.252", &masks[29]);
|
|
|
|
inet_pton(AF_INET, "255.255.255.254", &masks[30]);
|
|
|
|
inet_pton(AF_INET, "255.255.255.255", &masks[31]);
|
|
|
|
}
|
|
|
|
|
|
|
|
if(mask_length == 0 || mask_length > SUBNETLENGTHSIZE) {
|
|
|
|
g_assert_not_reached();
|
|
|
|
return 0;
|
|
|
|
} else {
|
|
|
|
return masks[mask_length - 1];
|
|
|
|
}
|
2008-01-21 21:44:34 +00:00
|
|
|
}
|
|
|
|
|
2010-04-29 18:17:29 +00:00
|
|
|
static void
|
|
|
|
subnet_name_lookup_init(void)
|
2008-01-21 21:44:34 +00:00
|
|
|
{
|
2010-04-27 22:46:39 +00:00
|
|
|
gchar* subnetspath;
|
|
|
|
guint32 i;
|
2010-04-29 18:17:29 +00:00
|
|
|
|
2010-04-27 22:46:39 +00:00
|
|
|
for(i = 0; i < SUBNETLENGTHSIZE; ++i) {
|
|
|
|
guint32 length = i + 1;
|
2008-05-22 15:46:27 +00:00
|
|
|
|
2010-04-27 22:46:39 +00:00
|
|
|
subnet_length_entries[i].subnet_addresses = NULL;
|
|
|
|
subnet_length_entries[i].mask_length = length;
|
|
|
|
subnet_length_entries[i].mask = get_subnet_mask(length);
|
|
|
|
}
|
2008-01-21 21:44:34 +00:00
|
|
|
|
2010-04-27 22:46:39 +00:00
|
|
|
subnetspath = get_persconffile_path(ENAME_SUBNETS, FALSE, FALSE);
|
|
|
|
if (!read_subnets_file(subnetspath) && errno != ENOENT) {
|
|
|
|
report_open_failure(subnetspath, errno, FALSE);
|
|
|
|
}
|
|
|
|
g_free(subnetspath);
|
2008-01-21 21:44:34 +00:00
|
|
|
|
2010-04-27 22:46:39 +00:00
|
|
|
/*
|
|
|
|
* Load the global subnets file, if we have one.
|
|
|
|
*/
|
|
|
|
subnetspath = get_datafile_path(ENAME_SUBNETS);
|
|
|
|
if (!read_subnets_file(subnetspath) && errno != ENOENT) {
|
|
|
|
report_open_failure(subnetspath, errno, FALSE);
|
|
|
|
}
|
|
|
|
g_free(subnetspath);
|
2008-01-21 21:44:34 +00:00
|
|
|
}
|
|
|
|
|
2011-03-24 22:47:57 +00:00
|
|
|
|
2002-08-28 20:41:00 +00:00
|
|
|
/*
|
1998-09-25 23:24:07 +00:00
|
|
|
* External Functions
|
|
|
|
*/
|
1998-09-16 02:39:15 +00:00
|
|
|
|
2004-11-10 04:57:34 +00:00
|
|
|
void
|
2003-05-05 00:53:06 +00:00
|
|
|
host_name_lookup_init(void) {
|
2005-01-07 11:22:18 +00:00
|
|
|
char *hostspath;
|
2011-03-24 22:47:57 +00:00
|
|
|
struct addrinfo *ai;
|
2005-07-19 20:44:45 +00:00
|
|
|
|
2005-07-19 22:24:28 +00:00
|
|
|
#ifdef HAVE_GNU_ADNS
|
2007-06-03 16:07:07 +00:00
|
|
|
#ifdef _WIN32
|
2005-07-19 22:24:28 +00:00
|
|
|
char *sysroot;
|
|
|
|
static char rootpath_nt[] = "\\system32\\drivers\\etc\\hosts";
|
|
|
|
static char rootpath_ot[] = "\\hosts";
|
2007-06-03 16:07:07 +00:00
|
|
|
#endif /* _WIN32 */
|
2005-07-19 22:24:28 +00:00
|
|
|
#endif /*GNU_ADNS */
|
|
|
|
|
2011-03-24 22:47:57 +00:00
|
|
|
if (!addrinfo_list) {
|
|
|
|
ai = g_malloc0(sizeof(struct addrinfo));
|
|
|
|
addrinfo_list = addrinfo_list_last = ai;
|
|
|
|
}
|
|
|
|
|
2005-07-19 20:44:45 +00:00
|
|
|
/*
|
|
|
|
* Load the user's hosts file, if they have one.
|
|
|
|
*/
|
2008-01-14 16:40:23 +00:00
|
|
|
hostspath = get_persconffile_path(ENAME_HOSTS, FALSE, FALSE);
|
2005-07-19 20:44:45 +00:00
|
|
|
if (!read_hosts_file(hostspath) && errno != ENOENT) {
|
|
|
|
report_open_failure(hostspath, errno, FALSE);
|
|
|
|
}
|
|
|
|
g_free(hostspath);
|
|
|
|
|
2006-03-02 00:06:15 +00:00
|
|
|
/*
|
|
|
|
* Load the global hosts file, if we have one.
|
|
|
|
*/
|
|
|
|
hostspath = get_datafile_path(ENAME_HOSTS);
|
|
|
|
if (!read_hosts_file(hostspath) && errno != ENOENT) {
|
|
|
|
report_open_failure(hostspath, errno, FALSE);
|
|
|
|
}
|
|
|
|
g_free(hostspath);
|
2011-03-24 22:47:57 +00:00
|
|
|
|
2008-08-07 21:41:48 +00:00
|
|
|
#ifdef HAVE_C_ARES
|
2009-10-30 21:57:43 +00:00
|
|
|
#ifdef CARES_HAVE_ARES_LIBRARY_INIT
|
|
|
|
if (ares_library_init(ARES_LIB_INIT_ALL) == ARES_SUCCESS) {
|
|
|
|
#endif
|
2009-12-24 00:58:31 +00:00
|
|
|
if (ares_init(&ghba_chan) == ARES_SUCCESS && ares_init(&ghbn_chan) == ARES_SUCCESS) {
|
2009-09-13 17:24:51 +00:00
|
|
|
async_dns_initialized = TRUE;
|
2008-08-07 21:41:48 +00:00
|
|
|
}
|
2009-10-30 21:57:43 +00:00
|
|
|
#ifdef CARES_HAVE_ARES_LIBRARY_INIT
|
|
|
|
}
|
|
|
|
#endif
|
2008-08-07 21:41:48 +00:00
|
|
|
#else
|
2005-01-13 09:09:56 +00:00
|
|
|
#ifdef HAVE_GNU_ADNS
|
|
|
|
/*
|
|
|
|
* We're using GNU ADNS, which doesn't check the system hosts file;
|
|
|
|
* we load that file ourselves.
|
|
|
|
*/
|
2007-06-03 16:07:07 +00:00
|
|
|
#ifdef _WIN32
|
2004-11-17 08:34:36 +00:00
|
|
|
|
2006-01-12 22:32:29 +00:00
|
|
|
sysroot = getenv_utf8("WINDIR");
|
2005-01-07 10:20:17 +00:00
|
|
|
if (sysroot != NULL) {
|
|
|
|
/*
|
2005-01-17 19:30:31 +00:00
|
|
|
* The file should be under WINDIR.
|
|
|
|
* If this is Windows NT (NT 4.0,2K,XP,Server2K3), it's in
|
|
|
|
* %WINDIR%\system32\drivers\etc\hosts.
|
|
|
|
* If this is Windows OT (95,98,Me), it's in %WINDIR%\hosts.
|
|
|
|
* Try both.
|
|
|
|
* XXX - should we base it on the dwPlatformId value from
|
|
|
|
* GetVersionEx()?
|
2005-01-07 10:20:17 +00:00
|
|
|
*/
|
2005-01-17 19:30:31 +00:00
|
|
|
hostspath = g_strconcat(sysroot, rootpath_nt, NULL);
|
|
|
|
if (!read_hosts_file(hostspath)) {
|
|
|
|
g_free(hostspath);
|
|
|
|
hostspath = g_strconcat(sysroot, rootpath_ot, NULL);
|
2005-01-17 21:38:31 +00:00
|
|
|
read_hosts_file(hostspath);
|
2005-01-07 10:20:17 +00:00
|
|
|
}
|
2005-01-17 19:30:31 +00:00
|
|
|
g_free(hostspath);
|
2005-01-07 10:20:17 +00:00
|
|
|
}
|
2007-06-03 16:07:07 +00:00
|
|
|
#else /* _WIN32 */
|
2005-01-07 10:20:17 +00:00
|
|
|
read_hosts_file("/etc/hosts");
|
2007-06-03 16:07:07 +00:00
|
|
|
#endif /* _WIN32 */
|
2004-11-17 08:34:36 +00:00
|
|
|
|
2003-05-04 18:50:56 +00:00
|
|
|
/* XXX - Any flags we should be using? */
|
|
|
|
/* XXX - We could provide config settings for DNS servers, and
|
|
|
|
pass them to ADNS with adns_init_strcfg */
|
2004-11-10 04:57:34 +00:00
|
|
|
if (adns_init(&ads, 0, 0 /*0=>stderr*/) != 0) {
|
|
|
|
/*
|
|
|
|
* XXX - should we report the error? I'm assuming that some crashes
|
|
|
|
* reported on a Windows machine with TCP/IP not configured are due
|
|
|
|
* to "adns_init()" failing (due to the lack of TCP/IP) and leaving
|
|
|
|
* ADNS in a state where it crashes due to that. We'll still try
|
|
|
|
* doing name resolution anyway.
|
|
|
|
*/
|
|
|
|
return;
|
|
|
|
}
|
2009-09-13 17:24:51 +00:00
|
|
|
async_dns_initialized = TRUE;
|
|
|
|
async_dns_in_flight = 0;
|
2005-01-13 09:09:56 +00:00
|
|
|
#endif /* HAVE_GNU_ADNS */
|
2008-08-07 21:41:48 +00:00
|
|
|
#endif /* HAVE_C_ARES */
|
2008-01-21 21:44:34 +00:00
|
|
|
|
2010-04-29 18:17:29 +00:00
|
|
|
subnet_name_lookup_init();
|
2003-05-04 18:50:56 +00:00
|
|
|
}
|
|
|
|
|
2008-08-07 21:41:48 +00:00
|
|
|
#ifdef HAVE_C_ARES
|
|
|
|
gboolean
|
|
|
|
host_name_lookup_process(gpointer data _U_) {
|
2009-09-13 17:24:51 +00:00
|
|
|
async_dns_queue_msg_t *caqm;
|
2008-08-07 21:41:48 +00:00
|
|
|
struct timeval tv = { 0, 0 };
|
|
|
|
int nfds;
|
|
|
|
fd_set rfds, wfds;
|
2009-12-22 20:01:06 +00:00
|
|
|
gboolean nro = new_resolved_objects;
|
|
|
|
|
|
|
|
new_resolved_objects = FALSE;
|
2008-08-07 21:41:48 +00:00
|
|
|
|
2009-09-13 17:24:51 +00:00
|
|
|
if (!async_dns_initialized)
|
2009-06-24 19:10:50 +00:00
|
|
|
/* c-ares not initialized. Bail out and cancel timers. */
|
2009-12-22 20:01:06 +00:00
|
|
|
return nro;
|
2009-06-24 19:10:50 +00:00
|
|
|
|
2009-09-13 17:24:51 +00:00
|
|
|
async_dns_queue_head = g_list_first(async_dns_queue_head);
|
2008-08-07 21:41:48 +00:00
|
|
|
|
2011-02-17 01:11:05 +00:00
|
|
|
while (async_dns_queue_head != NULL && async_dns_in_flight <= prefs.name_resolve_concurrency) {
|
2009-09-13 17:24:51 +00:00
|
|
|
caqm = (async_dns_queue_msg_t *) async_dns_queue_head->data;
|
|
|
|
async_dns_queue_head = g_list_remove(async_dns_queue_head, (void *) caqm);
|
2008-08-07 21:41:48 +00:00
|
|
|
if (caqm->family == AF_INET) {
|
2009-12-24 00:58:31 +00:00
|
|
|
ares_gethostbyaddr(ghba_chan, &caqm->addr.ip4, sizeof(guint32), AF_INET,
|
2010-06-28 22:43:13 +00:00
|
|
|
c_ares_ghba_cb, caqm);
|
2009-09-13 17:24:51 +00:00
|
|
|
async_dns_in_flight++;
|
2008-08-07 21:41:48 +00:00
|
|
|
} else if (caqm->family == AF_INET6) {
|
2009-12-24 00:58:31 +00:00
|
|
|
ares_gethostbyaddr(ghba_chan, &caqm->addr.ip6, sizeof(struct e_in6_addr),
|
2010-04-29 18:17:29 +00:00
|
|
|
AF_INET6, c_ares_ghba_cb, caqm);
|
2009-09-13 17:24:51 +00:00
|
|
|
async_dns_in_flight++;
|
2008-08-07 21:41:48 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
FD_ZERO(&rfds);
|
|
|
|
FD_ZERO(&wfds);
|
2009-12-24 00:58:31 +00:00
|
|
|
nfds = ares_fds(ghba_chan, &rfds, &wfds);
|
2008-08-07 21:41:48 +00:00
|
|
|
if (nfds > 0) {
|
|
|
|
select(nfds, &rfds, &wfds, NULL, &tv);
|
2009-12-24 00:58:31 +00:00
|
|
|
ares_process(ghba_chan, &rfds, &wfds);
|
2008-08-07 21:41:48 +00:00
|
|
|
}
|
|
|
|
|
2009-12-22 20:01:06 +00:00
|
|
|
/* Any new entries? */
|
|
|
|
return nro;
|
2008-08-07 21:41:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
host_name_lookup_cleanup(void) {
|
|
|
|
GList *cur;
|
|
|
|
|
2009-09-13 17:24:51 +00:00
|
|
|
cur = g_list_first(async_dns_queue_head);
|
2008-08-07 21:41:48 +00:00
|
|
|
while (cur) {
|
|
|
|
g_free(cur->data);
|
2008-08-12 16:47:54 +00:00
|
|
|
cur = g_list_next (cur);
|
2008-08-07 21:41:48 +00:00
|
|
|
}
|
|
|
|
|
2009-09-13 17:24:51 +00:00
|
|
|
g_list_free(async_dns_queue_head);
|
2008-08-07 21:41:48 +00:00
|
|
|
|
2009-10-30 21:57:43 +00:00
|
|
|
if (async_dns_initialized) {
|
2009-12-24 00:58:31 +00:00
|
|
|
ares_destroy(ghba_chan);
|
|
|
|
ares_destroy(ghbn_chan);
|
2009-10-30 21:57:43 +00:00
|
|
|
}
|
|
|
|
#ifdef CARES_HAVE_ARES_LIBRARY_INIT
|
|
|
|
ares_library_cleanup();
|
|
|
|
#endif
|
2009-09-13 17:24:51 +00:00
|
|
|
async_dns_initialized = FALSE;
|
2008-08-07 21:41:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#elif defined(HAVE_GNU_ADNS)
|
2005-01-13 09:09:56 +00:00
|
|
|
|
2003-05-04 18:50:56 +00:00
|
|
|
/* XXX - The ADNS "documentation" isn't very clear:
|
|
|
|
* - Do we need to keep our query structures around?
|
|
|
|
*/
|
2008-07-08 02:25:30 +00:00
|
|
|
gboolean
|
2003-05-04 18:50:56 +00:00
|
|
|
host_name_lookup_process(gpointer data _U_) {
|
2009-09-13 17:24:51 +00:00
|
|
|
async_dns_queue_msg_t *almsg;
|
2003-05-04 18:50:56 +00:00
|
|
|
GList *cur;
|
|
|
|
char addr_str[] = "111.222.333.444.in-addr.arpa.";
|
|
|
|
guint8 *addr_bytes;
|
|
|
|
adns_answer *ans;
|
|
|
|
int ret;
|
|
|
|
gboolean dequeue;
|
2009-12-22 20:01:06 +00:00
|
|
|
gboolean nro = new_resolved_objects;
|
2003-05-04 18:50:56 +00:00
|
|
|
|
2009-12-22 20:01:06 +00:00
|
|
|
new_resolved_objects = FALSE;
|
2009-09-13 17:24:51 +00:00
|
|
|
async_dns_queue_head = g_list_first(async_dns_queue_head);
|
2003-05-04 18:50:56 +00:00
|
|
|
|
2009-09-13 17:24:51 +00:00
|
|
|
cur = async_dns_queue_head;
|
|
|
|
while (cur && async_dns_in_flight <= prefs.name_resolve_concurrency) {
|
|
|
|
almsg = (async_dns_queue_msg_t *) cur->data;
|
2003-05-04 18:50:56 +00:00
|
|
|
if (! almsg->submitted && almsg->type == AF_INET) {
|
|
|
|
addr_bytes = (guint8 *) &almsg->ip4_addr;
|
2005-08-08 18:50:39 +00:00
|
|
|
g_snprintf(addr_str, sizeof addr_str, "%u.%u.%u.%u.in-addr.arpa.", addr_bytes[3],
|
2010-06-28 22:43:13 +00:00
|
|
|
addr_bytes[2], addr_bytes[1], addr_bytes[0]);
|
2004-11-10 04:57:34 +00:00
|
|
|
/* XXX - what if it fails? */
|
2003-05-04 18:50:56 +00:00
|
|
|
adns_submit (ads, addr_str, adns_r_ptr, 0, NULL, &almsg->query);
|
|
|
|
almsg->submitted = TRUE;
|
2010-04-29 18:17:29 +00:00
|
|
|
async_dns_in_flight++;
|
2003-05-04 18:50:56 +00:00
|
|
|
}
|
|
|
|
cur = cur->next;
|
|
|
|
}
|
|
|
|
|
2009-09-13 17:24:51 +00:00
|
|
|
cur = async_dns_queue_head;
|
2003-05-04 18:50:56 +00:00
|
|
|
while (cur) {
|
|
|
|
dequeue = FALSE;
|
2009-09-13 17:24:51 +00:00
|
|
|
almsg = (async_dns_queue_msg_t *) cur->data;
|
2003-05-04 18:50:56 +00:00
|
|
|
if (almsg->submitted) {
|
|
|
|
ret = adns_check(ads, &almsg->query, &ans, NULL);
|
|
|
|
if (ret == 0) {
|
2010-06-28 22:43:13 +00:00
|
|
|
if (ans->status == adns_s_ok) {
|
|
|
|
add_ipv4_name(almsg->ip4_addr, *ans->rrs.str);
|
|
|
|
}
|
|
|
|
dequeue = TRUE;
|
2003-05-04 18:50:56 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
cur = cur->next;
|
|
|
|
if (dequeue) {
|
2009-09-13 17:24:51 +00:00
|
|
|
async_dns_queue_head = g_list_remove(async_dns_queue_head, (void *) almsg);
|
2003-05-04 18:50:56 +00:00
|
|
|
g_free(almsg);
|
2010-04-29 18:17:29 +00:00
|
|
|
async_dns_in_flight--;
|
2003-05-04 18:50:56 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2003-05-05 00:53:06 +00:00
|
|
|
/* Keep the timeout in place */
|
2009-12-22 20:01:06 +00:00
|
|
|
return nro;
|
2003-05-04 18:50:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2003-05-05 00:53:06 +00:00
|
|
|
host_name_lookup_cleanup(void) {
|
2003-05-04 18:50:56 +00:00
|
|
|
void *qdata;
|
|
|
|
|
2009-09-13 17:24:51 +00:00
|
|
|
async_dns_queue_head = g_list_first(async_dns_queue_head);
|
|
|
|
while (async_dns_queue_head) {
|
|
|
|
qdata = async_dns_queue_head->data;
|
|
|
|
async_dns_queue_head = g_list_remove(async_dns_queue_head, qdata);
|
2003-05-04 18:50:56 +00:00
|
|
|
g_free(qdata);
|
|
|
|
}
|
2006-01-19 23:01:24 +00:00
|
|
|
|
2009-09-13 17:24:51 +00:00
|
|
|
if (async_dns_initialized)
|
2004-11-10 05:01:09 +00:00
|
|
|
adns_finish(ads);
|
2010-04-29 18:17:29 +00:00
|
|
|
async_dns_initialized = FALSE;
|
2003-05-04 18:50:56 +00:00
|
|
|
}
|
|
|
|
|
2008-08-07 21:41:48 +00:00
|
|
|
#else /* HAVE_GNU_ADNS */
|
2003-05-05 00:53:06 +00:00
|
|
|
|
2008-07-08 02:25:30 +00:00
|
|
|
gboolean
|
2003-05-05 00:53:06 +00:00
|
|
|
host_name_lookup_process(gpointer data _U_) {
|
2009-12-22 20:01:06 +00:00
|
|
|
gboolean nro = new_resolved_objects;
|
2010-01-19 23:18:23 +00:00
|
|
|
|
2009-12-22 20:01:06 +00:00
|
|
|
new_resolved_objects = FALSE;
|
|
|
|
|
|
|
|
return nro;
|
2003-05-05 00:53:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
host_name_lookup_cleanup(void) {
|
|
|
|
}
|
|
|
|
|
2008-08-07 21:41:48 +00:00
|
|
|
#endif /* HAVE_C_ARES */
|
2003-05-04 18:50:56 +00:00
|
|
|
|
2010-04-29 18:17:29 +00:00
|
|
|
extern const gchar *
|
|
|
|
get_hostname(const guint addr)
|
1998-09-16 02:39:15 +00:00
|
|
|
{
|
2000-08-10 20:09:29 +00:00
|
|
|
gboolean found;
|
2010-10-12 13:15:08 +00:00
|
|
|
gboolean resolve = gbl_resolv_flags & RESOLV_NETWORK;
|
2009-09-06 08:59:30 +00:00
|
|
|
hashipv4_t *tp = host_lookup(addr, resolve, &found);
|
2000-08-10 20:09:29 +00:00
|
|
|
|
2009-09-06 08:59:30 +00:00
|
|
|
if (!resolve)
|
|
|
|
return tp->ip;
|
|
|
|
|
|
|
|
return tp->name;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* -------------------------- */
|
|
|
|
|
2010-04-29 18:17:29 +00:00
|
|
|
extern const gchar *
|
|
|
|
get_hostname6(const struct e_in6_addr *addr)
|
1999-03-28 18:32:03 +00:00
|
|
|
{
|
2000-08-10 20:09:29 +00:00
|
|
|
gboolean found;
|
2010-10-12 13:15:08 +00:00
|
|
|
gboolean resolve = gbl_resolv_flags & RESOLV_NETWORK;
|
2009-09-06 08:59:30 +00:00
|
|
|
hashipv6_t *tp = host_lookup6(addr, resolve, &found);
|
2000-08-10 20:09:29 +00:00
|
|
|
|
2011-01-25 22:11:59 +00:00
|
|
|
if (!resolve)
|
2009-09-06 08:59:30 +00:00
|
|
|
return tp->ip6;
|
2011-01-25 22:11:59 +00:00
|
|
|
|
2009-09-06 08:59:30 +00:00
|
|
|
return tp->name;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* -------------------------- */
|
2010-04-29 18:17:29 +00:00
|
|
|
extern void
|
|
|
|
add_ipv4_name(const guint addr, const gchar *name)
|
1998-09-25 23:24:07 +00:00
|
|
|
{
|
2001-06-07 22:07:02 +00:00
|
|
|
int hash_idx;
|
2004-11-17 08:53:20 +00:00
|
|
|
hashipv4_t *tp;
|
2011-03-24 22:47:57 +00:00
|
|
|
struct addrinfo *ai;
|
|
|
|
struct sockaddr_in *sa4;
|
1998-09-25 23:24:07 +00:00
|
|
|
|
2001-06-07 22:07:02 +00:00
|
|
|
hash_idx = HASH_IPV4_ADDRESS(addr);
|
|
|
|
|
2004-11-17 08:53:20 +00:00
|
|
|
tp = ipv4_table[hash_idx];
|
1998-09-25 23:24:07 +00:00
|
|
|
|
|
|
|
if( tp == NULL ) {
|
2009-09-06 08:59:30 +00:00
|
|
|
tp = ipv4_table[hash_idx] = new_ipv4(addr);
|
2002-08-28 20:41:00 +00:00
|
|
|
} else {
|
1998-09-25 23:24:07 +00:00
|
|
|
while(1) {
|
2000-08-10 20:09:29 +00:00
|
|
|
if (tp->addr == addr) {
|
2010-04-27 22:46:39 +00:00
|
|
|
/* address already known */
|
|
|
|
if (!tp->is_dummy_entry) {
|
|
|
|
return;
|
|
|
|
} else {
|
|
|
|
/* replace this dummy entry with the new one */
|
|
|
|
break;
|
|
|
|
}
|
2000-08-08 16:21:24 +00:00
|
|
|
}
|
1998-09-25 23:24:07 +00:00
|
|
|
if (tp->next == NULL) {
|
2010-04-27 22:46:39 +00:00
|
|
|
tp->next = new_ipv4(addr);
|
|
|
|
tp = tp->next;
|
|
|
|
break;
|
1998-09-25 23:24:07 +00:00
|
|
|
}
|
|
|
|
tp = tp->next;
|
|
|
|
}
|
|
|
|
}
|
2007-10-26 05:42:12 +00:00
|
|
|
g_strlcpy(tp->name, name, MAXNAMELEN);
|
2009-09-06 08:59:30 +00:00
|
|
|
tp->resolve = TRUE;
|
2009-12-22 20:01:06 +00:00
|
|
|
new_resolved_objects = TRUE;
|
2011-03-24 22:47:57 +00:00
|
|
|
|
|
|
|
if (!addrinfo_list) {
|
|
|
|
ai = g_malloc0(sizeof(struct addrinfo));
|
|
|
|
addrinfo_list = addrinfo_list_last = ai;
|
|
|
|
}
|
|
|
|
|
|
|
|
sa4 = g_malloc0(sizeof(struct sockaddr_in));
|
|
|
|
sa4->sin_family = AF_INET;
|
|
|
|
sa4->sin_addr.s_addr = addr;
|
|
|
|
|
|
|
|
ai = g_malloc0(sizeof(struct addrinfo));
|
|
|
|
ai->ai_family = AF_INET;
|
|
|
|
ai->ai_addrlen = sizeof(struct sockaddr_in);
|
|
|
|
ai->ai_canonname = (char *) tp->name;
|
|
|
|
ai->ai_addr = (struct sockaddr*) sa4;
|
|
|
|
|
|
|
|
addrinfo_list_last->ai_next = ai;
|
|
|
|
addrinfo_list_last = ai;
|
|
|
|
|
2004-11-17 08:53:20 +00:00
|
|
|
} /* add_ipv4_name */
|
1998-09-25 23:24:07 +00:00
|
|
|
|
2009-09-06 08:59:30 +00:00
|
|
|
/* -------------------------- */
|
2010-04-29 18:17:29 +00:00
|
|
|
extern void
|
|
|
|
add_ipv6_name(const struct e_in6_addr *addrp, const gchar *name)
|
2004-11-17 09:44:41 +00:00
|
|
|
{
|
|
|
|
int hash_idx;
|
|
|
|
hashipv6_t *tp;
|
2011-03-24 22:47:57 +00:00
|
|
|
struct addrinfo *ai;
|
|
|
|
struct sockaddr_in6 *sa6;
|
2004-11-17 09:44:41 +00:00
|
|
|
|
|
|
|
hash_idx = HASH_IPV6_ADDRESS(*addrp);
|
|
|
|
|
|
|
|
tp = ipv6_table[hash_idx];
|
|
|
|
|
|
|
|
if( tp == NULL ) {
|
2009-09-06 08:59:30 +00:00
|
|
|
tp = ipv6_table[hash_idx] = new_ipv6(addrp);
|
2004-11-17 09:44:41 +00:00
|
|
|
} else {
|
|
|
|
while(1) {
|
|
|
|
if (memcmp(&tp->addr, addrp, sizeof (struct e_in6_addr)) == 0) {
|
2010-04-27 22:46:39 +00:00
|
|
|
/* address already known */
|
|
|
|
if (!tp->is_dummy_entry) {
|
|
|
|
return;
|
|
|
|
} else {
|
|
|
|
/* replace this dummy entry with the new one */
|
|
|
|
break;
|
|
|
|
}
|
2004-11-17 09:44:41 +00:00
|
|
|
}
|
|
|
|
if (tp->next == NULL) {
|
2010-04-27 22:46:39 +00:00
|
|
|
tp->next = new_ipv6(addrp);
|
|
|
|
tp = tp->next;
|
|
|
|
break;
|
2004-11-17 09:44:41 +00:00
|
|
|
}
|
|
|
|
tp = tp->next;
|
|
|
|
}
|
|
|
|
}
|
2007-10-26 05:42:12 +00:00
|
|
|
g_strlcpy(tp->name, name, MAXNAMELEN);
|
2009-09-06 08:59:30 +00:00
|
|
|
tp->resolve = TRUE;
|
2009-12-22 20:01:06 +00:00
|
|
|
new_resolved_objects = TRUE;
|
2004-11-17 09:44:41 +00:00
|
|
|
|
2011-03-24 22:47:57 +00:00
|
|
|
if (!addrinfo_list) {
|
|
|
|
ai = g_malloc0(sizeof(struct addrinfo));
|
|
|
|
addrinfo_list = addrinfo_list_last = ai;
|
|
|
|
}
|
|
|
|
|
|
|
|
sa6 = g_malloc0(sizeof(struct sockaddr_in6));
|
|
|
|
sa6->sin6_family = AF_INET;
|
|
|
|
memcpy(sa6->sin6_addr.s6_addr, addrp, 16);
|
|
|
|
|
|
|
|
ai = g_malloc0(sizeof(struct addrinfo));
|
|
|
|
ai->ai_family = AF_INET6;
|
|
|
|
ai->ai_addrlen = sizeof(struct sockaddr_in);
|
|
|
|
ai->ai_canonname = (char *) tp->name;
|
|
|
|
ai->ai_addr = (struct sockaddr *) sa6;
|
|
|
|
|
|
|
|
addrinfo_list_last->ai_next = ai;
|
|
|
|
addrinfo_list_last = ai;
|
|
|
|
|
2004-11-17 09:44:41 +00:00
|
|
|
} /* add_ipv6_name */
|
|
|
|
|
2007-11-09 05:55:33 +00:00
|
|
|
/* -----------------
|
|
|
|
* unsigned integer to ascii
|
|
|
|
*/
|
2010-04-29 18:17:29 +00:00
|
|
|
static gchar *
|
|
|
|
ep_utoa(guint port)
|
2007-11-09 05:55:33 +00:00
|
|
|
{
|
|
|
|
gchar *bp = ep_alloc(MAXNAMELEN);
|
2008-05-22 15:46:27 +00:00
|
|
|
|
2010-02-23 19:28:38 +00:00
|
|
|
/* XXX, guint32_to_str() ? */
|
|
|
|
guint32_to_str_buf(port, bp, MAXNAMELEN);
|
2007-11-09 05:55:33 +00:00
|
|
|
return bp;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-04-29 18:17:29 +00:00
|
|
|
extern gchar *
|
|
|
|
get_udp_port(guint port)
|
1998-09-16 02:39:15 +00:00
|
|
|
{
|
|
|
|
|
2010-10-12 13:15:08 +00:00
|
|
|
if (!(gbl_resolv_flags & RESOLV_TRANSPORT)) {
|
2007-11-09 05:55:33 +00:00
|
|
|
return ep_utoa(port);
|
1998-09-16 02:39:15 +00:00
|
|
|
}
|
|
|
|
|
2000-08-19 08:26:04 +00:00
|
|
|
return serv_name_lookup(port, PT_UDP);
|
1998-09-16 02:39:15 +00:00
|
|
|
|
|
|
|
} /* get_udp_port */
|
|
|
|
|
2010-04-29 18:17:29 +00:00
|
|
|
extern gchar *
|
|
|
|
get_dccp_port(guint port)
|
2005-09-20 15:18:28 +00:00
|
|
|
{
|
|
|
|
|
2010-10-12 13:15:08 +00:00
|
|
|
if (!(gbl_resolv_flags & RESOLV_TRANSPORT)) {
|
2007-11-09 05:55:33 +00:00
|
|
|
return ep_utoa(port);
|
2005-09-20 15:18:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return serv_name_lookup(port, PT_DCCP);
|
|
|
|
|
|
|
|
} /* get_dccp_port */
|
|
|
|
|
|
|
|
|
2010-04-29 18:17:29 +00:00
|
|
|
extern gchar *
|
|
|
|
get_tcp_port(guint port)
|
1998-09-16 02:39:15 +00:00
|
|
|
{
|
|
|
|
|
2010-10-12 13:15:08 +00:00
|
|
|
if (!(gbl_resolv_flags & RESOLV_TRANSPORT)) {
|
2007-11-09 05:55:33 +00:00
|
|
|
return ep_utoa(port);
|
1998-09-16 02:39:15 +00:00
|
|
|
}
|
|
|
|
|
2000-08-19 08:26:04 +00:00
|
|
|
return serv_name_lookup(port, PT_TCP);
|
1998-09-16 02:39:15 +00:00
|
|
|
|
|
|
|
} /* get_tcp_port */
|
|
|
|
|
2010-04-29 18:17:29 +00:00
|
|
|
extern gchar *
|
|
|
|
get_sctp_port(guint port)
|
2000-08-19 08:26:04 +00:00
|
|
|
{
|
|
|
|
|
2010-10-12 13:15:08 +00:00
|
|
|
if (!(gbl_resolv_flags & RESOLV_TRANSPORT)) {
|
2007-11-09 05:55:33 +00:00
|
|
|
return ep_utoa(port);
|
2000-08-19 08:26:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return serv_name_lookup(port, PT_SCTP);
|
|
|
|
|
|
|
|
} /* get_sctp_port */
|
|
|
|
|
2010-04-29 18:17:29 +00:00
|
|
|
const gchar *
|
|
|
|
get_addr_name(const address *addr)
|
2004-12-30 02:10:24 +00:00
|
|
|
{
|
2005-02-22 01:55:04 +00:00
|
|
|
const gchar *result;
|
2006-01-19 23:01:24 +00:00
|
|
|
|
2005-02-22 01:55:04 +00:00
|
|
|
result = solve_address_to_name(addr);
|
2006-01-19 23:01:24 +00:00
|
|
|
|
2009-09-07 16:05:37 +00:00
|
|
|
if (result != NULL)
|
2010-04-27 22:46:39 +00:00
|
|
|
return result;
|
2009-09-07 16:05:37 +00:00
|
|
|
|
|
|
|
/* if it gets here, either it is of type AT_NONE, */
|
|
|
|
/* or it should be solvable in address_to_str -unless addr->type is wrongly defined */
|
|
|
|
|
|
|
|
if (addr->type == AT_NONE){
|
2010-04-27 22:46:39 +00:00
|
|
|
return "NONE";
|
2005-02-22 01:55:04 +00:00
|
|
|
}
|
2006-01-19 23:01:24 +00:00
|
|
|
|
2009-09-07 16:05:37 +00:00
|
|
|
/* We need an ephemeral allocated string */
|
|
|
|
return ep_address_to_str(addr);
|
|
|
|
}
|
|
|
|
|
2010-04-29 18:17:29 +00:00
|
|
|
const gchar *
|
|
|
|
se_get_addr_name(const address *addr)
|
2009-09-07 16:05:37 +00:00
|
|
|
{
|
|
|
|
const gchar *result;
|
|
|
|
|
|
|
|
result = se_solve_address_to_name(addr);
|
|
|
|
|
|
|
|
if (result != NULL)
|
2010-04-27 22:46:39 +00:00
|
|
|
return result;
|
2009-09-07 16:05:37 +00:00
|
|
|
|
2005-02-22 01:55:04 +00:00
|
|
|
/* if it gets here, either it is of type AT_NONE, */
|
2009-09-07 16:05:37 +00:00
|
|
|
/* or it should be solvable in se_address_to_str -unless addr->type is wrongly defined */
|
2006-01-19 23:01:24 +00:00
|
|
|
|
2005-02-22 01:55:04 +00:00
|
|
|
if (addr->type == AT_NONE){
|
2010-04-27 22:46:39 +00:00
|
|
|
return "NONE";
|
2005-02-22 01:55:04 +00:00
|
|
|
}
|
2006-01-19 23:01:24 +00:00
|
|
|
|
2009-09-07 14:03:05 +00:00
|
|
|
/* We need a "permanently" allocated string */
|
2009-09-07 16:05:37 +00:00
|
|
|
return se_address_to_str(addr);
|
|
|
|
}
|
2006-01-19 23:01:24 +00:00
|
|
|
|
2010-04-29 18:17:29 +00:00
|
|
|
void
|
|
|
|
get_addr_name_buf(const address *addr, gchar *buf, gsize size)
|
2005-02-22 01:55:04 +00:00
|
|
|
{
|
2007-09-28 18:23:59 +00:00
|
|
|
const gchar *result = get_addr_name(addr);
|
2004-12-30 02:10:24 +00:00
|
|
|
|
2009-07-17 08:24:06 +00:00
|
|
|
g_strlcpy(buf, result, size);
|
2005-02-22 01:55:04 +00:00
|
|
|
} /* get_addr_name_buf */
|
2004-12-30 02:10:24 +00:00
|
|
|
|
|
|
|
|
2010-04-29 18:17:29 +00:00
|
|
|
gchar *
|
|
|
|
get_ether_name(const guint8 *addr)
|
1998-09-25 23:24:07 +00:00
|
|
|
{
|
2009-09-06 08:59:30 +00:00
|
|
|
hashether_t *tp;
|
2010-10-12 13:15:08 +00:00
|
|
|
gboolean resolve = (gbl_resolv_flags & RESOLV_MAC) != 0;
|
2010-07-01 15:11:02 +00:00
|
|
|
|
2009-09-06 08:59:30 +00:00
|
|
|
if (resolve && !eth_resolution_initialized) {
|
2009-09-07 16:07:04 +00:00
|
|
|
initialize_ethers();
|
2010-07-01 15:11:02 +00:00
|
|
|
eth_resolution_initialized = TRUE;
|
1998-09-25 23:24:07 +00:00
|
|
|
}
|
|
|
|
|
2009-09-06 08:59:30 +00:00
|
|
|
tp = eth_name_lookup(addr, resolve);
|
2010-07-01 15:11:02 +00:00
|
|
|
|
|
|
|
return resolve ? tp->resolved_name : tp->hexaddr;
|
|
|
|
|
1998-09-25 23:24:07 +00:00
|
|
|
} /* get_ether_name */
|
|
|
|
|
2010-06-28 22:29:49 +00:00
|
|
|
/* Look for a (non-dummy) ether name in the hash, and return it if found.
|
|
|
|
* If it's not found, simply return NULL.
|
1999-11-21 16:32:23 +00:00
|
|
|
*/
|
2010-04-29 18:17:29 +00:00
|
|
|
gchar *
|
|
|
|
get_ether_name_if_known(const guint8 *addr)
|
1999-11-21 16:32:23 +00:00
|
|
|
{
|
|
|
|
hashether_t *tp;
|
|
|
|
|
|
|
|
/* Initialize ether structs if we're the first
|
|
|
|
* ether-related function called */
|
2010-10-12 13:15:08 +00:00
|
|
|
if (!(gbl_resolv_flags & RESOLV_MAC))
|
1999-11-21 16:32:23 +00:00
|
|
|
return NULL;
|
2002-08-28 20:41:00 +00:00
|
|
|
|
1999-11-21 16:32:23 +00:00
|
|
|
if (!eth_resolution_initialized) {
|
|
|
|
initialize_ethers();
|
2010-07-01 15:11:02 +00:00
|
|
|
eth_resolution_initialized = TRUE;
|
1999-11-21 16:32:23 +00:00
|
|
|
}
|
|
|
|
|
2010-07-01 15:11:02 +00:00
|
|
|
/* eth_name_lookup will create a (resolved) hash entry if it doesn't exist */
|
2010-06-28 22:29:49 +00:00
|
|
|
tp = eth_name_lookup(addr, TRUE);
|
|
|
|
g_assert(tp != NULL);
|
1999-11-21 16:32:23 +00:00
|
|
|
|
2010-07-01 15:11:02 +00:00
|
|
|
if (tp->status == HASHETHER_STATUS_RESOLVED_NAME) {
|
2010-06-28 22:29:49 +00:00
|
|
|
/* Name is from an ethers file (or is a "well-known" MAC address name from the manuf file) */
|
2010-07-01 15:11:02 +00:00
|
|
|
return tp->resolved_name;
|
1999-11-21 16:32:23 +00:00
|
|
|
}
|
2002-08-28 20:41:00 +00:00
|
|
|
else {
|
2010-06-28 22:29:49 +00:00
|
|
|
/* Name was created */
|
|
|
|
return NULL;
|
1999-11-21 16:32:23 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-04-29 18:17:29 +00:00
|
|
|
extern guint8 *
|
|
|
|
get_ether_addr(const gchar *name)
|
1998-09-25 23:24:07 +00:00
|
|
|
{
|
|
|
|
|
2010-10-12 13:15:08 +00:00
|
|
|
/* force resolution (do not check gbl_resolv_flags) */
|
1998-09-25 23:24:07 +00:00
|
|
|
|
|
|
|
if (!eth_resolution_initialized) {
|
|
|
|
initialize_ethers();
|
2010-07-01 15:11:02 +00:00
|
|
|
eth_resolution_initialized = TRUE;
|
1998-09-25 23:24:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return eth_addr_lookup(name);
|
|
|
|
|
|
|
|
} /* get_ether_addr */
|
|
|
|
|
2010-04-29 18:17:29 +00:00
|
|
|
extern void
|
|
|
|
add_ether_byip(const guint ip, const guint8 *eth)
|
2000-08-10 20:09:29 +00:00
|
|
|
{
|
|
|
|
|
2004-01-10 17:31:40 +00:00
|
|
|
gchar *host;
|
2000-08-10 20:09:29 +00:00
|
|
|
gboolean found;
|
|
|
|
|
|
|
|
/* first check that IP address can be resolved */
|
2010-10-12 13:15:08 +00:00
|
|
|
if (!(gbl_resolv_flags & RESOLV_NETWORK))
|
2009-09-06 08:59:30 +00:00
|
|
|
return;
|
2000-08-10 20:09:29 +00:00
|
|
|
|
2009-09-06 08:59:30 +00:00
|
|
|
if ((host = host_name_lookup(ip, &found)) == NULL)
|
2000-08-10 20:09:29 +00:00
|
|
|
return;
|
2002-08-28 20:41:00 +00:00
|
|
|
|
2000-08-10 20:09:29 +00:00
|
|
|
/* ok, we can add this entry in the ethers hashtable */
|
|
|
|
|
|
|
|
if (found)
|
|
|
|
add_eth_name(eth, host);
|
|
|
|
|
|
|
|
} /* add_ether_byip */
|
1999-11-21 16:32:23 +00:00
|
|
|
|
2010-04-29 18:17:29 +00:00
|
|
|
extern const gchar *
|
|
|
|
get_ipxnet_name(const guint32 addr)
|
1999-11-21 16:32:23 +00:00
|
|
|
{
|
1999-11-22 06:03:46 +00:00
|
|
|
|
2010-10-12 13:15:08 +00:00
|
|
|
if (!(gbl_resolv_flags & RESOLV_NETWORK)) {
|
2010-04-27 22:46:39 +00:00
|
|
|
return ipxnet_to_str_punct(addr, '\0');
|
1999-11-22 06:03:46 +00:00
|
|
|
}
|
1999-11-21 16:32:23 +00:00
|
|
|
|
|
|
|
if (!ipxnet_resolution_initialized) {
|
|
|
|
initialize_ipxnets();
|
|
|
|
ipxnet_resolution_initialized = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ipxnet_name_lookup(addr);
|
|
|
|
|
|
|
|
} /* get_ipxnet_name */
|
|
|
|
|
2010-04-29 18:17:29 +00:00
|
|
|
extern guint32
|
|
|
|
get_ipxnet_addr(const gchar *name, gboolean *known)
|
1999-11-21 16:32:23 +00:00
|
|
|
{
|
2001-04-02 09:41:56 +00:00
|
|
|
guint32 addr;
|
|
|
|
gboolean success;
|
1999-11-21 16:32:23 +00:00
|
|
|
|
2010-10-12 13:15:08 +00:00
|
|
|
/* force resolution (do not check gbl_resolv_flags) */
|
1999-11-21 16:32:23 +00:00
|
|
|
|
|
|
|
if (!ipxnet_resolution_initialized) {
|
|
|
|
initialize_ipxnets();
|
|
|
|
ipxnet_resolution_initialized = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
addr = ipxnet_addr_lookup(name, &success);
|
|
|
|
|
|
|
|
*known = success;
|
|
|
|
return addr;
|
|
|
|
|
|
|
|
} /* get_ipxnet_addr */
|
|
|
|
|
2010-04-29 18:17:29 +00:00
|
|
|
extern const gchar *
|
|
|
|
get_manuf_name(const guint8 *addr)
|
1998-09-25 23:24:07 +00:00
|
|
|
{
|
2005-08-17 09:36:20 +00:00
|
|
|
gchar *cur;
|
2010-06-29 02:53:17 +00:00
|
|
|
hashmanuf_t *mtp;
|
1998-09-25 23:24:07 +00:00
|
|
|
|
2010-10-12 13:15:08 +00:00
|
|
|
if ((gbl_resolv_flags & RESOLV_MAC) && !eth_resolution_initialized) {
|
1998-09-25 23:24:07 +00:00
|
|
|
initialize_ethers();
|
2010-07-01 15:11:02 +00:00
|
|
|
eth_resolution_initialized = TRUE;
|
1998-09-25 23:24:07 +00:00
|
|
|
}
|
|
|
|
|
2010-10-12 13:15:08 +00:00
|
|
|
if (!(gbl_resolv_flags & RESOLV_MAC) || ((mtp = manuf_name_lookup(addr)) == NULL)) {
|
2010-11-30 22:28:34 +00:00
|
|
|
cur=ep_strdup_printf("%02x:%02x:%02x", addr[0], addr[1], addr[2]);
|
1998-09-25 23:24:07 +00:00
|
|
|
return cur;
|
|
|
|
}
|
2002-08-28 20:41:00 +00:00
|
|
|
|
2010-06-29 02:53:17 +00:00
|
|
|
return mtp->name;
|
1998-09-25 23:24:07 +00:00
|
|
|
|
|
|
|
} /* get_manuf_name */
|
1999-07-07 22:52:57 +00:00
|
|
|
|
|
|
|
|
2010-04-29 18:17:29 +00:00
|
|
|
const gchar *
|
|
|
|
get_manuf_name_if_known(const guint8 *addr)
|
2005-05-20 21:44:17 +00:00
|
|
|
{
|
2010-06-29 02:53:17 +00:00
|
|
|
hashmanuf_t *mtp;
|
2005-05-20 21:44:17 +00:00
|
|
|
|
|
|
|
if (!eth_resolution_initialized) {
|
|
|
|
initialize_ethers();
|
2010-07-01 15:11:02 +00:00
|
|
|
eth_resolution_initialized = TRUE;
|
2005-05-20 21:44:17 +00:00
|
|
|
}
|
|
|
|
|
2010-06-29 02:53:17 +00:00
|
|
|
if ((mtp = manuf_name_lookup(addr)) == NULL) {
|
2005-05-20 21:44:17 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2010-06-29 02:53:17 +00:00
|
|
|
return mtp->name;
|
2005-05-20 21:44:17 +00:00
|
|
|
|
|
|
|
} /* get_manuf_name_if_known */
|
|
|
|
|
1999-07-07 22:52:57 +00:00
|
|
|
|
2009-12-24 00:58:31 +00:00
|
|
|
#ifdef HAVE_C_ARES
|
|
|
|
#define GHI_TIMEOUT (250 * 1000)
|
|
|
|
static void
|
|
|
|
#if ( ( ARES_VERSION_MAJOR < 1 ) \
|
|
|
|
|| ( 1 == ARES_VERSION_MAJOR && ARES_VERSION_MINOR < 5 ) )
|
|
|
|
c_ares_ghi_cb(void *arg, int status, struct hostent *hp) {
|
|
|
|
#else
|
|
|
|
c_ares_ghi_cb(void *arg, int status, int timeouts _U_, struct hostent *hp) {
|
|
|
|
#endif
|
|
|
|
/*
|
|
|
|
* XXX - If we wanted to be really fancy we could cache results here and
|
|
|
|
* look them up in get_host_ipaddr* below.
|
|
|
|
*/
|
|
|
|
async_hostent_t *ahp = arg;
|
|
|
|
if (status == ARES_SUCCESS && hp && ahp && hp->h_length == ahp->addr_size) {
|
|
|
|
memcpy(ahp->addrp, hp->h_addr, hp->h_length);
|
|
|
|
ahp->copied = hp->h_length;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif /* HAVE_C_ARES */
|
|
|
|
|
Have "get_host_ipaddr()" return a Boolean indicating whether it
succeeded or failed, and, if it succeeded, have it fill in the IP
address if found through a pointer passed as the second argument.
Have it first try interpreting its first argument as a dotted-quad IP
address, with "inet_aton()", and, if that fails, have it try to
interpret it as a host name with "gethostbyname()"; don't bother with
"gethostbyaddr()", as we should be allowed to filter on IP addresses
even if there's no host name associated with them (there's no guarantee
that "gethostbyaddr()" will succeed if handed an IP address with no
corresponding name - and it looks as if FreeBSD 3.2, at least, may not
succeed in that case).
Add a "dfilter_fail()" routine that takes "printf()"-like arguments and
uses them to set an error message for the parse; doing so means that
even if the filter expression is syntactically valid, we treat it as
being invalid. (Is there a better way to force a parse to fail from
arbitrary places in routines called by the parser?)
Use that routine in the lexical analyzer.
If that error message was set, use it as is as the failure message,
rather than adding "Unable to parse filter string XXX" to it.
Have the code to handle IP addresses and host names in display filters
check whether "get_host_ipaddr()" succeeded or failed and, if it failed,
arrange that the parse fail with an error message indicating the source
of the problem.
svn path=/trunk/; revision=802
1999-10-11 03:03:12 +00:00
|
|
|
/* Translate a string, assumed either to be a dotted-quad IP address or
|
|
|
|
* a host name, to a numeric IP address. Return TRUE if we succeed and
|
|
|
|
* set "*addrp" to that numeric IP address; return FALSE if we fail.
|
1999-07-07 22:52:57 +00:00
|
|
|
* Used more in the dfilter parser rather than in packet dissectors */
|
2010-04-29 18:17:29 +00:00
|
|
|
gboolean
|
|
|
|
get_host_ipaddr(const char *host, guint32 *addrp)
|
1999-07-07 22:52:57 +00:00
|
|
|
{
|
2010-04-27 22:46:39 +00:00
|
|
|
struct in_addr ipaddr;
|
2009-12-24 00:58:31 +00:00
|
|
|
#ifdef HAVE_C_ARES
|
2010-04-27 22:46:39 +00:00
|
|
|
struct timeval tv = { 0, GHI_TIMEOUT }, *tvp;
|
|
|
|
int nfds;
|
|
|
|
fd_set rfds, wfds;
|
|
|
|
async_hostent_t ahe;
|
2009-12-24 00:58:31 +00:00
|
|
|
#else /* HAVE_C_ARES */
|
2010-04-27 22:46:39 +00:00
|
|
|
struct hostent *hp;
|
2009-12-24 00:58:31 +00:00
|
|
|
#endif /* HAVE_C_ARES */
|
2009-09-07 16:07:04 +00:00
|
|
|
|
2010-04-27 22:46:39 +00:00
|
|
|
/*
|
|
|
|
* don't change it to inet_pton(AF_INET), they are not 100% compatible.
|
|
|
|
* inet_pton(AF_INET) does not support hexadecimal notation nor
|
|
|
|
* less-than-4 octet notation.
|
|
|
|
*/
|
|
|
|
if (!inet_aton(host, &ipaddr)) {
|
2010-10-12 13:15:08 +00:00
|
|
|
if (! (gbl_resolv_flags & RESOLV_NETWORK)) {
|
2010-04-27 22:46:39 +00:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
/* It's not a valid dotted-quad IP address; is it a valid
|
|
|
|
* host name? */
|
2009-12-24 00:58:31 +00:00
|
|
|
#ifdef HAVE_C_ARES
|
2010-10-12 13:15:08 +00:00
|
|
|
if (! (gbl_resolv_flags & RESOLV_CONCURRENT) ||
|
2010-04-27 22:46:39 +00:00
|
|
|
prefs.name_resolve_concurrency < 1 ||
|
|
|
|
! async_dns_initialized) {
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
ahe.addr_size = (int) sizeof (struct in_addr);
|
|
|
|
ahe.copied = 0;
|
|
|
|
ahe.addrp = addrp;
|
|
|
|
ares_gethostbyname(ghbn_chan, host, AF_INET, c_ares_ghi_cb, &ahe);
|
|
|
|
FD_ZERO(&rfds);
|
|
|
|
FD_ZERO(&wfds);
|
|
|
|
nfds = ares_fds(ghbn_chan, &rfds, &wfds);
|
|
|
|
if (nfds > 0) {
|
|
|
|
tvp = ares_timeout(ghbn_chan, &tv, &tv);
|
|
|
|
select(nfds, &rfds, &wfds, NULL, tvp);
|
|
|
|
ares_process(ghbn_chan, &rfds, &wfds);
|
|
|
|
}
|
|
|
|
ares_cancel(ghbn_chan);
|
|
|
|
if (ahe.addr_size == ahe.copied) {
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
return FALSE;
|
2009-12-24 00:58:31 +00:00
|
|
|
#else /* ! HAVE_C_ARES */
|
2010-04-27 22:46:39 +00:00
|
|
|
hp = gethostbyname(host);
|
|
|
|
if (hp == NULL) {
|
|
|
|
/* No. */
|
|
|
|
return FALSE;
|
|
|
|
/* Apparently, some versions of gethostbyaddr can
|
|
|
|
* return IPv6 addresses. */
|
|
|
|
} else if (hp->h_length <= (int) sizeof (struct in_addr)) {
|
|
|
|
memcpy(&ipaddr, hp->h_addr, hp->h_length);
|
2009-09-07 16:07:04 +00:00
|
|
|
} else {
|
2010-04-27 22:46:39 +00:00
|
|
|
return FALSE;
|
2009-09-07 16:07:04 +00:00
|
|
|
}
|
2010-04-27 22:46:39 +00:00
|
|
|
#endif /* HAVE_C_ARES */
|
|
|
|
} else {
|
|
|
|
/* Does the string really contain dotted-quad IP?
|
|
|
|
* Check against inet_atons that accept strings such as
|
|
|
|
* "130.230" as valid addresses and try to convert them
|
|
|
|
* to some form of a classful (host.net) notation.
|
|
|
|
*/
|
|
|
|
unsigned int a0, a1, a2, a3;
|
|
|
|
if (sscanf(host, "%u.%u.%u.%u", &a0, &a1, &a2, &a3) != 4)
|
|
|
|
return FALSE;
|
|
|
|
}
|
2009-09-07 16:07:04 +00:00
|
|
|
|
2010-04-27 22:46:39 +00:00
|
|
|
*addrp = g_ntohl(ipaddr.s_addr);
|
|
|
|
return TRUE;
|
1999-07-07 22:52:57 +00:00
|
|
|
}
|
1999-10-14 05:41:33 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Translate IPv6 numeric address or FQDN hostname, into binary IPv6 address.
|
|
|
|
* Return TRUE if we succeed and set "*addrp" to that numeric IP address;
|
|
|
|
* return FALSE if we fail.
|
|
|
|
*/
|
2010-04-29 18:17:29 +00:00
|
|
|
gboolean
|
|
|
|
get_host_ipaddr6(const char *host, struct e_in6_addr *addrp)
|
1999-10-14 05:41:33 +00:00
|
|
|
{
|
2009-12-24 00:58:31 +00:00
|
|
|
#ifdef HAVE_C_ARES
|
2010-04-27 22:46:39 +00:00
|
|
|
struct timeval tv = { 0, GHI_TIMEOUT }, *tvp;
|
|
|
|
int nfds;
|
|
|
|
fd_set rfds, wfds;
|
|
|
|
async_hostent_t ahe;
|
2010-08-09 11:19:15 +00:00
|
|
|
#elif defined(HAVE_GETHOSTBYNAME2)
|
2010-04-27 22:46:39 +00:00
|
|
|
struct hostent *hp;
|
2009-12-24 00:58:31 +00:00
|
|
|
#endif /* HAVE_C_ARES */
|
1999-10-14 05:41:33 +00:00
|
|
|
|
2010-04-27 22:46:39 +00:00
|
|
|
if (inet_pton(AF_INET6, host, addrp) == 1)
|
|
|
|
return TRUE;
|
1999-10-14 05:41:33 +00:00
|
|
|
|
2010-10-12 13:15:08 +00:00
|
|
|
if (! (gbl_resolv_flags & RESOLV_NETWORK)) {
|
2010-04-27 22:46:39 +00:00
|
|
|
return FALSE;
|
|
|
|
}
|
2009-12-24 17:21:02 +00:00
|
|
|
|
2010-04-27 22:46:39 +00:00
|
|
|
/* try FQDN */
|
2009-12-24 00:58:31 +00:00
|
|
|
#ifdef HAVE_C_ARES
|
2010-10-12 13:15:08 +00:00
|
|
|
if (! (gbl_resolv_flags & RESOLV_CONCURRENT) ||
|
2010-04-27 22:46:39 +00:00
|
|
|
prefs.name_resolve_concurrency < 1 ||
|
|
|
|
! async_dns_initialized) {
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
ahe.addr_size = (int) sizeof (struct e_in6_addr);
|
|
|
|
ahe.copied = 0;
|
|
|
|
ahe.addrp = addrp;
|
|
|
|
ares_gethostbyname(ghbn_chan, host, AF_INET6, c_ares_ghi_cb, &ahe);
|
|
|
|
FD_ZERO(&rfds);
|
|
|
|
FD_ZERO(&wfds);
|
|
|
|
nfds = ares_fds(ghbn_chan, &rfds, &wfds);
|
|
|
|
if (nfds > 0) {
|
|
|
|
tvp = ares_timeout(ghbn_chan, &tv, &tv);
|
|
|
|
select(nfds, &rfds, &wfds, NULL, tvp);
|
|
|
|
ares_process(ghbn_chan, &rfds, &wfds);
|
|
|
|
}
|
|
|
|
ares_cancel(ghbn_chan);
|
|
|
|
if (ahe.addr_size == ahe.copied) {
|
|
|
|
return TRUE;
|
|
|
|
}
|
2009-12-24 00:58:31 +00:00
|
|
|
#elif defined(HAVE_GETHOSTBYNAME2)
|
2010-04-27 22:46:39 +00:00
|
|
|
hp = gethostbyname2(host, AF_INET6);
|
|
|
|
if (hp != NULL && hp->h_length == sizeof(struct e_in6_addr)) {
|
|
|
|
memcpy(addrp, hp->h_addr, hp->h_length);
|
|
|
|
return TRUE;
|
|
|
|
}
|
2009-12-24 00:58:31 +00:00
|
|
|
#endif
|
1999-10-14 05:41:33 +00:00
|
|
|
|
2010-04-27 22:46:39 +00:00
|
|
|
return FALSE;
|
1999-10-14 05:41:33 +00:00
|
|
|
}
|
2004-06-25 07:00:54 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Find out whether a hostname resolves to an ip or ipv6 address
|
|
|
|
* Return "ip6" if it is IPv6, "ip" otherwise (including the case
|
|
|
|
* that we don't know)
|
|
|
|
*/
|
2004-12-27 13:17:20 +00:00
|
|
|
const char* host_ip_af(const char *host
|
|
|
|
#ifndef HAVE_GETHOSTBYNAME2
|
|
|
|
_U_
|
|
|
|
#endif
|
|
|
|
)
|
2004-06-25 07:00:54 +00:00
|
|
|
{
|
|
|
|
#ifdef HAVE_GETHOSTBYNAME2
|
2010-04-27 22:46:39 +00:00
|
|
|
struct hostent *h;
|
|
|
|
return (h = gethostbyname2(host, AF_INET6)) && h->h_addrtype == AF_INET6 ? "ip6" : "ip";
|
2004-06-25 07:00:54 +00:00
|
|
|
#else
|
2010-04-27 22:46:39 +00:00
|
|
|
return "ip";
|
2004-06-25 07:00:54 +00:00
|
|
|
#endif
|
|
|
|
}
|