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
|
|
|
|
2007-03-26 06:10:52 +00:00
|
|
|
#ifdef HAVE_GNU_ADNS
|
|
|
|
# include <errno.h>
|
|
|
|
# include <adns.h>
|
|
|
|
# ifdef inet_aton
|
|
|
|
# undef inet_aton
|
|
|
|
# endif
|
|
|
|
#endif
|
|
|
|
|
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
|
2002-10-29 00:28:11 +00:00
|
|
|
#include <sys/socket.h> /* needed to define AF_ values on UNIX */
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef HAVE_WINSOCK2_H
|
|
|
|
#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
|
|
|
|
|
|
|
#ifdef AVOID_DNS_TIMEOUT
|
|
|
|
# include <setjmp.h>
|
|
|
|
#endif
|
|
|
|
|
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
|
|
|
|
# include "inet_aton.h"
|
|
|
|
#endif
|
|
|
|
|
1999-10-14 06:55:11 +00:00
|
|
|
#ifdef NEED_INET_V6DEFS_H
|
|
|
|
# include "inet_v6defs.h"
|
|
|
|
#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
|
|
|
|
|
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>
|
2005-11-07 02:47:09 +00:00
|
|
|
#include <wiretap/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
|
|
|
|
2005-01-13 09:09:56 +00:00
|
|
|
#define ENAME_HOSTS "hosts"
|
2001-10-21 19:54:49 +00:00
|
|
|
#define ENAME_ETHERS "ethers"
|
|
|
|
#define ENAME_IPXNETS "ipxnets"
|
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
|
|
|
#define ENAME_MANUF "manuf"
|
2007-08-06 08:44:26 +00:00
|
|
|
#define ENAME_SERVICES "services"
|
Give libethereal its own configuration file, and have that configuration
file, rather than the top-level Ethereal configuration file, check for
"inet_aton()", "inet_pton()", and "inet_ntop()". Then make its
Makefile.am include the appropriate object files if necessary.
Otherwise, they don't get built and put into libethereal, and therefore
attempts to link with anything in libethereal that uses them fail on
platforms that lack ethem, causing the build to fail.
That means a bunch of things need to be fixed to cope with libethereal
having its own "config.h" file; this means removing the include of
"config.h" from some libethereal header files. Move the definitions of
the path names used only by "resolv.c" to "resolv.c" from "resolv.h" (so
"resolv.h" doesn't need "config.h", define HAVE_PLUGINS in the configure
script (so we don't have to include it in "plugins.h" to check whether
HAVE_DLFCN_H is defined).
Unfortunately, stuff outside libethereal needs to know PLUGIN_DIR; for
now, define that in the top-level configuration file, and have Ethereal
and Tethereal pass it as an argument to "epan_init()" - that should be
cleaned up at some point.
Remove from the top-level configure script checks for things used only
in libethereal.
svn path=/trunk/; revision=2498
2000-10-16 23:18:05 +00:00
|
|
|
|
1998-09-25 23:24:07 +00:00
|
|
|
#define MAXMANUFLEN 9 /* max vendor name length with ending '\0' */
|
|
|
|
#define HASHETHSIZE 1024
|
1998-09-16 02:39:15 +00:00
|
|
|
#define HASHHOSTSIZE 1024
|
1999-11-21 16:32:23 +00:00
|
|
|
#define HASHIPXNETSIZE 256
|
1998-09-25 23:24:07 +00:00
|
|
|
#define HASHMANUFSIZE 256
|
1998-09-16 02:39:15 +00:00
|
|
|
#define HASHPORTSIZE 256
|
|
|
|
|
2004-11-17 08:53:20 +00:00
|
|
|
/* hash table used for IPv4 lookup */
|
1998-09-16 02:39:15 +00:00
|
|
|
|
2001-06-07 22:07:02 +00:00
|
|
|
#define HASH_IPV4_ADDRESS(addr) ((addr) & (HASHHOSTSIZE - 1))
|
|
|
|
|
2004-11-17 08:53:20 +00:00
|
|
|
typedef struct hashipv4 {
|
2001-04-02 09:41:56 +00:00
|
|
|
guint addr;
|
2004-11-17 09:44:41 +00:00
|
|
|
gboolean is_dummy_entry; /* name is IPv4 address in dot format */
|
2004-11-17 08:53:20 +00:00
|
|
|
struct hashipv4 *next;
|
2006-02-27 09:01:10 +00:00
|
|
|
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 */
|
|
|
|
|
2004-11-17 19:41:56 +00:00
|
|
|
#define HASH_IPV6_ADDRESS(addr) \
|
2005-09-12 06:21:35 +00:00
|
|
|
((((addr).bytes[14] << 8)|((addr).bytes[15])) & (HASHHOSTSIZE - 1))
|
2004-11-17 09:44:41 +00:00
|
|
|
|
|
|
|
typedef struct hashipv6 {
|
|
|
|
struct e_in6_addr addr;
|
|
|
|
gchar name[MAXNAMELEN];
|
|
|
|
gboolean is_dummy_entry; /* name is IPv6 address in colon format */
|
|
|
|
struct hashipv6 *next;
|
|
|
|
} hashipv6_t;
|
|
|
|
|
2004-11-17 08:53:20 +00:00
|
|
|
/* hash table used for TCP/UDP/SCTP port lookup */
|
|
|
|
|
|
|
|
#define HASH_PORT(port) ((port) & (HASHPORTSIZE - 1))
|
|
|
|
|
|
|
|
typedef struct hashport {
|
|
|
|
guint16 port;
|
|
|
|
gchar name[MAXNAMELEN];
|
|
|
|
struct hashport *next;
|
|
|
|
} 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 */
|
|
|
|
|
|
|
|
#define HASH_IPX_NET(net) ((net) & (HASHIPXNETSIZE - 1))
|
|
|
|
|
2004-11-17 08:53:20 +00:00
|
|
|
typedef struct hashipxnet {
|
|
|
|
guint addr;
|
|
|
|
gchar name[MAXNAMELEN];
|
|
|
|
struct hashipxnet *next;
|
|
|
|
} 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) \
|
|
|
|
(((((addr)[2] << 8) | (addr)[3]) ^ (((addr)[4] << 8) | (addr)[5])) & \
|
|
|
|
(HASHETHSIZE - 1))
|
|
|
|
|
|
|
|
#define HASH_ETH_MANUF(addr) (((int)(addr)[2]) & (HASHMANUFSIZE - 1))
|
|
|
|
|
1998-09-25 23:24:07 +00:00
|
|
|
typedef struct hashmanuf {
|
2001-04-02 09:41:56 +00:00
|
|
|
guint8 addr[3];
|
1998-09-25 23:24:07 +00:00
|
|
|
char name[MAXMANUFLEN];
|
|
|
|
struct hashmanuf *next;
|
|
|
|
} hashmanuf_t;
|
|
|
|
|
|
|
|
typedef struct hashether {
|
2001-04-02 09:41:56 +00:00
|
|
|
guint8 addr[6];
|
1998-09-25 23:24:07 +00:00
|
|
|
char name[MAXNAMELEN];
|
2000-08-10 20:09:29 +00:00
|
|
|
gboolean is_dummy_entry; /* not a complete entry */
|
1998-09-25 23:24:07 +00:00
|
|
|
struct hashether *next;
|
|
|
|
} hashether_t;
|
|
|
|
|
|
|
|
/* internal ethernet type */
|
1998-09-16 02:39:15 +00:00
|
|
|
|
1998-09-25 23:24:07 +00:00
|
|
|
typedef struct _ether
|
|
|
|
{
|
2001-04-02 09:41:56 +00:00
|
|
|
guint8 addr[6];
|
1998-09-25 23:24:07 +00:00
|
|
|
char name[MAXNAMELEN];
|
|
|
|
} ether_t;
|
|
|
|
|
1999-11-21 16:32:23 +00:00
|
|
|
/* internal ipxnet type */
|
|
|
|
|
|
|
|
typedef struct _ipxnet
|
|
|
|
{
|
2001-04-02 09:41:56 +00:00
|
|
|
guint addr;
|
1999-11-21 16:32:23 +00:00
|
|
|
char name[MAXNAMELEN];
|
|
|
|
} ipxnet_t;
|
|
|
|
|
2004-11-17 08:53:20 +00:00
|
|
|
static hashipv4_t *ipv4_table[HASHHOSTSIZE];
|
2004-11-17 09:44:41 +00:00
|
|
|
static hashipv6_t *ipv6_table[HASHHOSTSIZE];
|
2004-11-17 08:53:20 +00:00
|
|
|
static hashport_t *udp_port_table[HASHPORTSIZE];
|
|
|
|
static hashport_t *tcp_port_table[HASHPORTSIZE];
|
|
|
|
static hashport_t *sctp_port_table[HASHPORTSIZE];
|
2005-09-20 15:18:28 +00:00
|
|
|
static hashport_t *dccp_port_table[HASHPORTSIZE];
|
2004-11-17 08:53:20 +00:00
|
|
|
static hashether_t *eth_table[HASHETHSIZE];
|
|
|
|
static hashmanuf_t *manuf_table[HASHMANUFSIZE];
|
|
|
|
static hashether_t *(*wka_table[48])[HASHETHSIZE];
|
|
|
|
static hashipxnet_t *ipxnet_table[HASHIPXNETSIZE];
|
1998-09-25 23:24:07 +00:00
|
|
|
|
|
|
|
static int eth_resolution_initialized = 0;
|
1999-11-21 16:32:23 +00:00
|
|
|
static int ipxnet_resolution_initialized = 0;
|
2007-08-06 08:44:26 +00:00
|
|
|
static int service_resolution_initialized = 0;
|
1998-09-25 23:24:07 +00:00
|
|
|
|
2004-01-10 17:31:40 +00:00
|
|
|
static hashether_t *add_eth_name(const guint8 *addr, const gchar *name);
|
2002-09-09 19:38:11 +00:00
|
|
|
|
2002-01-13 20:35:12 +00:00
|
|
|
/*
|
|
|
|
* Flag controlling what names to resolve.
|
|
|
|
*/
|
|
|
|
guint32 g_resolv_flags;
|
|
|
|
|
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
|
|
|
*/
|
|
|
|
|
2001-10-21 21:48:00 +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 */
|
2007-08-06 08:44:26 +00:00
|
|
|
gchar *g_services_path = NULL; /* global services file */
|
|
|
|
gchar *g_pservices_path = NULL; /* personal services file */
|
2001-10-21 21:48:00 +00:00
|
|
|
/* first resolving call */
|
1998-09-16 02:39:15 +00:00
|
|
|
|
2003-05-04 18:50:56 +00:00
|
|
|
/* GNU ADNS */
|
|
|
|
|
|
|
|
#ifdef HAVE_GNU_ADNS
|
|
|
|
|
2004-11-10 04:57:34 +00:00
|
|
|
static gboolean gnu_adns_initialized = FALSE;
|
|
|
|
|
2003-05-04 18:50:56 +00:00
|
|
|
adns_state ads;
|
|
|
|
|
|
|
|
int adns_currently_queued = 0;
|
|
|
|
|
|
|
|
typedef struct _adns_queue_msg
|
|
|
|
{
|
|
|
|
gboolean submitted;
|
|
|
|
guint32 ip4_addr;
|
|
|
|
struct e_in6_addr ip6_addr;
|
|
|
|
int type;
|
|
|
|
adns_query query;
|
|
|
|
} adns_queue_msg_t;
|
|
|
|
|
|
|
|
GList *adns_queue_head = NULL;
|
|
|
|
|
|
|
|
#endif /* HAVE_GNU_ADNS */
|
|
|
|
|
2007-08-06 08:44:26 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Miscellaneous functions
|
|
|
|
*/
|
|
|
|
|
|
|
|
static int fgetline(char **buf, int *size, FILE *fp)
|
|
|
|
{
|
|
|
|
int len;
|
|
|
|
int c;
|
|
|
|
|
|
|
|
if (fp == NULL)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
if (*buf == NULL) {
|
|
|
|
if (*size == 0)
|
|
|
|
*size = BUFSIZ;
|
|
|
|
|
|
|
|
if ((*buf = g_malloc(*size)) == NULL)
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (feof(fp))
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
len = 0;
|
|
|
|
while ((c = getc(fp)) != EOF && c != '\r' && c != '\n') {
|
|
|
|
if (len+1 >= *size) {
|
|
|
|
if ((*buf = g_realloc(*buf, *size += BUFSIZ)) == NULL)
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
(*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
|
|
|
*/
|
1998-09-16 02:39:15 +00:00
|
|
|
|
2007-08-06 08:44:26 +00:00
|
|
|
|
|
|
|
static void add_service_name(hashport_t **proto_table, guint port, const char *service_name)
|
|
|
|
{
|
|
|
|
int hash_idx;
|
|
|
|
hashport_t *tp;
|
|
|
|
|
|
|
|
|
|
|
|
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);
|
2007-08-06 08:44:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void parse_service_line (char *line)
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* See the services(4) or services(5) man page for services file format
|
|
|
|
* (not available on all systems).
|
|
|
|
*/
|
|
|
|
|
|
|
|
gchar *cp;
|
|
|
|
gchar *service;
|
|
|
|
gchar *port;
|
|
|
|
|
|
|
|
|
|
|
|
if ((cp = strchr(line, '#')))
|
|
|
|
*cp = '\0';
|
|
|
|
|
|
|
|
if ((cp = strtok(line, " \t")) == NULL)
|
|
|
|
return;
|
|
|
|
|
|
|
|
service = cp;
|
|
|
|
|
|
|
|
if ((cp = strtok(NULL, " \t")) == NULL)
|
|
|
|
return;
|
|
|
|
|
|
|
|
port = cp;
|
|
|
|
|
|
|
|
if ((cp = strtok(cp, "/")) == NULL)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if ((cp = strtok(NULL, "/")) == NULL)
|
|
|
|
return;
|
|
|
|
|
|
|
|
/* seems we got all interesting things from the file */
|
|
|
|
if(strcmp(cp, "tcp") == 0) {
|
|
|
|
add_service_name(tcp_port_table, atoi(port), service);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(strcmp(cp, "udp") == 0) {
|
|
|
|
add_service_name(udp_port_table, atoi(port), service);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(strcmp(cp, "sctp") == 0) {
|
|
|
|
add_service_name(sctp_port_table, atoi(port), service);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(strcmp(cp, "dcp") == 0) {
|
|
|
|
add_service_name(dccp_port_table, atoi(port), service);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
} /* parse_service_line */
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void parse_services_file(const char * path)
|
|
|
|
{
|
|
|
|
FILE *serv_p;
|
|
|
|
static int size = 0;
|
|
|
|
static char *buf = NULL;
|
|
|
|
|
|
|
|
/* services hash table initialization */
|
|
|
|
serv_p = eth_fopen(path, "r");
|
|
|
|
|
|
|
|
if (serv_p == NULL)
|
|
|
|
return;
|
|
|
|
|
|
|
|
while (fgetline(&buf, &size, serv_p) >= 0) {
|
|
|
|
parse_service_line (buf);
|
|
|
|
}
|
|
|
|
|
|
|
|
fclose(serv_p);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void initialize_services(void)
|
|
|
|
{
|
|
|
|
|
|
|
|
/* the hash table won't ignore duplicates, so use the personal path first */
|
|
|
|
|
|
|
|
/* set personal services path */
|
|
|
|
if (g_pservices_path == NULL)
|
|
|
|
g_pservices_path = get_persconffile_path(ENAME_SERVICES, FALSE);
|
|
|
|
|
|
|
|
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 */
|
|
|
|
|
|
|
|
|
|
|
|
|
2004-01-10 17:31:40 +00:00
|
|
|
static gchar *serv_name_lookup(guint port, 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*/
|
|
|
|
break;
|
|
|
|
} /* 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 ) {
|
1998-09-16 02:39:15 +00:00
|
|
|
return tp->name;
|
|
|
|
}
|
|
|
|
if (tp->next == NULL) {
|
2004-11-17 08:53:20 +00:00
|
|
|
tp->next = (hashport_t *)g_malloc(sizeof(hashport_t));
|
1998-09-16 02:39:15 +00:00
|
|
|
tp = tp->next;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
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;
|
|
|
|
|
2002-08-28 20:41:00 +00:00
|
|
|
if (!(g_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 */
|
2005-08-30 09:25:44 +00:00
|
|
|
g_snprintf(tp->name, MAXNAMELEN, "%d", port);
|
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
|
|
|
|
1998-09-16 02:39:15 +00:00
|
|
|
#ifdef AVOID_DNS_TIMEOUT
|
|
|
|
|
1999-09-18 16:01:52 +00:00
|
|
|
#define DNS_TIMEOUT 2 /* max sec per call */
|
1998-09-16 02:39:15 +00:00
|
|
|
|
|
|
|
jmp_buf hostname_env;
|
|
|
|
|
2002-03-02 20:51:46 +00:00
|
|
|
static void abort_network_query(int sig _U_)
|
1998-09-16 02:39:15 +00:00
|
|
|
{
|
|
|
|
longjmp(hostname_env, 1);
|
|
|
|
}
|
|
|
|
#endif /* AVOID_DNS_TIMEOUT */
|
|
|
|
|
2004-01-10 17:31:40 +00:00
|
|
|
static gchar *host_name_lookup(guint addr, 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;
|
2003-05-04 18:50:56 +00:00
|
|
|
#ifdef HAVE_GNU_ADNS
|
|
|
|
adns_queue_msg_t *qmsg;
|
|
|
|
#endif
|
1998-09-16 02:39:15 +00:00
|
|
|
|
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 ) {
|
2004-11-17 08:53:20 +00:00
|
|
|
tp = ipv4_table[hash_idx] = (hashipv4_t *)g_malloc(sizeof(hashipv4_t));
|
2002-08-28 20:41:00 +00:00
|
|
|
} else {
|
1998-09-16 02:39:15 +00:00
|
|
|
while(1) {
|
|
|
|
if( tp->addr == addr ) {
|
2000-08-10 20:09:29 +00:00
|
|
|
if (tp->is_dummy_entry)
|
|
|
|
*found = FALSE;
|
1998-09-16 02:39:15 +00:00
|
|
|
return tp->name;
|
|
|
|
}
|
|
|
|
if (tp->next == NULL) {
|
2004-11-17 08:53:20 +00:00
|
|
|
tp->next = (hashipv4_t *)g_malloc(sizeof(hashipv4_t));
|
1998-09-16 02:39:15 +00:00
|
|
|
tp = tp->next;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
tp = tp->next;
|
|
|
|
}
|
|
|
|
}
|
2002-08-28 20:41:00 +00:00
|
|
|
|
1998-09-16 02:39:15 +00:00
|
|
|
/* fill in a new entry */
|
|
|
|
tp->addr = addr;
|
|
|
|
tp->next = NULL;
|
|
|
|
|
2003-05-04 18:50:56 +00:00
|
|
|
#ifdef HAVE_GNU_ADNS
|
2006-01-19 23:01:24 +00:00
|
|
|
if ((g_resolv_flags & RESOLV_CONCURRENT) &&
|
2004-11-10 04:57:34 +00:00
|
|
|
prefs.name_resolve_concurrency > 0 &&
|
|
|
|
gnu_adns_initialized) {
|
2003-07-22 03:14:31 +00:00
|
|
|
qmsg = g_malloc(sizeof(adns_queue_msg_t));
|
|
|
|
qmsg->type = AF_INET;
|
|
|
|
qmsg->ip4_addr = addr;
|
|
|
|
qmsg->submitted = FALSE;
|
|
|
|
adns_queue_head = g_list_append(adns_queue_head, (gpointer) qmsg);
|
2003-05-04 18:50:56 +00:00
|
|
|
|
2003-07-22 03:14:31 +00:00
|
|
|
tp->is_dummy_entry = TRUE;
|
2007-01-29 20:25:26 +00:00
|
|
|
ip_to_str_buf((guint8 *)&addr, tp->name, MAXNAMELEN);
|
2003-07-22 03:14:31 +00:00
|
|
|
return tp->name;
|
|
|
|
}
|
2003-08-26 20:21:08 +00:00
|
|
|
#endif /* HAVE_GNU_ADNS */
|
2003-05-04 18:50:56 +00:00
|
|
|
|
2001-12-20 19:19:41 +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.
|
|
|
|
*/
|
2002-01-13 20:35:12 +00:00
|
|
|
if (addr != 0 && (g_resolv_flags & RESOLV_NETWORK)) {
|
2003-05-04 18:50:56 +00:00
|
|
|
/* Use async DNS if possible, else fall back to timeouts,
|
|
|
|
* else call gethostbyaddr and hope for the best
|
|
|
|
*/
|
|
|
|
|
|
|
|
# ifdef AVOID_DNS_TIMEOUT
|
2002-08-28 20:41:00 +00:00
|
|
|
|
2000-08-10 22:35:30 +00:00
|
|
|
/* Quick hack to avoid DNS/YP timeout */
|
2002-08-28 20:41:00 +00:00
|
|
|
|
2000-08-10 22:35:30 +00:00
|
|
|
if (!setjmp(hostname_env)) {
|
|
|
|
signal(SIGALRM, abort_network_query);
|
|
|
|
alarm(DNS_TIMEOUT);
|
2003-05-04 18:50:56 +00:00
|
|
|
# endif /* AVOID_DNS_TIMEOUT */
|
|
|
|
|
2000-08-10 22:35:30 +00:00
|
|
|
hostp = gethostbyaddr((char *)&addr, 4, AF_INET);
|
2003-05-04 18:50:56 +00:00
|
|
|
|
|
|
|
# ifdef AVOID_DNS_TIMEOUT
|
2000-08-10 22:35:30 +00:00
|
|
|
alarm(0);
|
2003-05-04 18:50:56 +00:00
|
|
|
# endif /* AVOID_DNS_TIMEOUT */
|
|
|
|
|
2000-08-10 22:35:30 +00:00
|
|
|
if (hostp != NULL) {
|
2007-10-26 05:42:12 +00:00
|
|
|
g_strlcpy(tp->name, hostp->h_name, MAXNAMELEN);
|
2000-08-10 22:35:30 +00:00
|
|
|
tp->is_dummy_entry = FALSE;
|
|
|
|
return tp->name;
|
|
|
|
}
|
2003-05-04 18:50:56 +00:00
|
|
|
|
|
|
|
# ifdef AVOID_DNS_TIMEOUT
|
2000-08-10 22:35:30 +00:00
|
|
|
}
|
2003-05-04 18:50:56 +00:00
|
|
|
# endif /* AVOID_DNS_TIMEOUT */
|
|
|
|
|
2000-08-10 22:35:30 +00:00
|
|
|
}
|
1998-09-16 02:39:15 +00:00
|
|
|
|
|
|
|
/* unknown host or DNS timeout */
|
|
|
|
|
2007-01-29 20:25:26 +00:00
|
|
|
ip_to_str_buf((guint8 *)&addr, tp->name, MAXNAMELEN);
|
2000-08-10 20:09:29 +00:00
|
|
|
tp->is_dummy_entry = TRUE;
|
|
|
|
*found = FALSE;
|
1998-09-25 23:24:07 +00:00
|
|
|
|
1998-09-16 02:39:15 +00:00
|
|
|
return (tp->name);
|
|
|
|
|
|
|
|
} /* host_name_lookup */
|
|
|
|
|
2004-01-10 17:31:40 +00:00
|
|
|
static gchar *host_name_lookup6(struct e_in6_addr *addr, 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;
|
2004-11-21 11:52:34 +00:00
|
|
|
#ifdef INET6
|
1999-03-28 18:32:03 +00:00
|
|
|
struct hostent *hostp;
|
2004-11-21 11:52:34 +00:00
|
|
|
#endif
|
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 ) {
|
|
|
|
tp = ipv6_table[hash_idx] = (hashipv6_t *)g_malloc(sizeof(hashipv6_t));
|
|
|
|
} else {
|
|
|
|
while(1) {
|
|
|
|
if( memcmp(&tp->addr, addr, sizeof (struct e_in6_addr)) == 0 ) {
|
|
|
|
if (tp->is_dummy_entry)
|
|
|
|
*found = FALSE;
|
|
|
|
return tp->name;
|
|
|
|
}
|
|
|
|
if (tp->next == NULL) {
|
|
|
|
tp->next = (hashipv6_t *)g_malloc(sizeof(hashipv6_t));
|
|
|
|
tp = tp->next;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
tp = tp->next;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* fill in a new entry */
|
|
|
|
tp->addr = *addr;
|
|
|
|
tp->next = NULL;
|
|
|
|
|
2004-11-17 19:46:34 +00:00
|
|
|
#ifdef INET6
|
2002-01-13 20:35:12 +00:00
|
|
|
if (g_resolv_flags & RESOLV_NETWORK) {
|
1999-03-28 18:32:03 +00:00
|
|
|
#ifdef AVOID_DNS_TIMEOUT
|
2002-08-28 20:41:00 +00:00
|
|
|
|
2000-08-10 22:35:30 +00:00
|
|
|
/* Quick hack to avoid DNS/YP timeout */
|
2002-08-28 20:41:00 +00:00
|
|
|
|
2000-08-10 22:35:30 +00:00
|
|
|
if (!setjmp(hostname_env)) {
|
|
|
|
signal(SIGALRM, abort_network_query);
|
|
|
|
alarm(DNS_TIMEOUT);
|
1999-03-28 18:32:03 +00:00
|
|
|
#endif /* AVOID_DNS_TIMEOUT */
|
2000-08-10 22:35:30 +00:00
|
|
|
hostp = gethostbyaddr((char *)addr, sizeof(*addr), AF_INET6);
|
1999-03-28 18:32:03 +00:00
|
|
|
#ifdef AVOID_DNS_TIMEOUT
|
2000-08-10 22:35:30 +00:00
|
|
|
alarm(0);
|
2004-11-17 09:44:41 +00:00
|
|
|
# endif /* AVOID_DNS_TIMEOUT */
|
|
|
|
|
2000-08-10 22:35:30 +00:00
|
|
|
if (hostp != NULL) {
|
2007-10-26 05:42:12 +00:00
|
|
|
g_strlcpy(tp->name, hostp->h_name, MAXNAMELEN);
|
2004-11-17 09:44:41 +00:00
|
|
|
tp->is_dummy_entry = FALSE;
|
|
|
|
return tp->name;
|
2000-08-10 22:35:30 +00:00
|
|
|
}
|
2004-11-17 09:44:41 +00:00
|
|
|
|
1999-03-28 18:32:03 +00:00
|
|
|
#ifdef AVOID_DNS_TIMEOUT
|
2000-08-10 22:35:30 +00:00
|
|
|
}
|
2004-11-17 09:44:41 +00:00
|
|
|
# endif /* AVOID_DNS_TIMEOUT */
|
|
|
|
|
2000-08-10 22:35:30 +00:00
|
|
|
}
|
1999-03-28 18:32:03 +00:00
|
|
|
|
|
|
|
/* unknown host or DNS timeout */
|
|
|
|
#endif /* INET6 */
|
2004-11-17 09:44:41 +00:00
|
|
|
ip6_to_str_buf(addr, tp->name);
|
|
|
|
tp->is_dummy_entry = TRUE;
|
2000-08-10 20:09:29 +00:00
|
|
|
*found = FALSE;
|
2004-11-17 09:44:41 +00:00
|
|
|
return (tp->name);
|
|
|
|
|
|
|
|
} /* host_name_lookup6 */
|
1999-03-28 18:32:03 +00:00
|
|
|
|
2005-07-23 11:41:25 +00:00
|
|
|
static const gchar *solve_address_to_name(address *addr)
|
2005-02-22 01:55:04 +00:00
|
|
|
{
|
|
|
|
guint32 ipv4_addr;
|
|
|
|
struct e_in6_addr ipv6_addr;
|
|
|
|
|
|
|
|
switch (addr->type) {
|
|
|
|
|
|
|
|
case AT_ETHER:
|
|
|
|
return get_ether_name(addr->data);
|
|
|
|
|
|
|
|
case AT_IPv4:
|
|
|
|
memcpy(&ipv4_addr, addr->data, sizeof ipv4_addr);
|
|
|
|
return get_hostname(ipv4_addr);
|
|
|
|
|
|
|
|
case AT_IPv6:
|
2005-09-12 06:21:35 +00:00
|
|
|
memcpy(&ipv6_addr.bytes, addr->data, sizeof ipv6_addr.bytes);
|
2005-02-22 01:55:04 +00:00
|
|
|
return get_hostname6(&ipv6_addr);
|
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
} /* solve_address_to_name */
|
|
|
|
|
|
|
|
|
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
|
|
|
|
* truncated to MAXMANUFLEN-1 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,
|
|
|
|
gboolean manuf_file)
|
|
|
|
{
|
|
|
|
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)
|
|
|
|
return FALSE; /* failed */
|
|
|
|
if (num > 0xFF)
|
|
|
|
return FALSE; /* not a valid octet */
|
2004-01-05 18:11:28 +00:00
|
|
|
eth->addr[i] = (guint8) num;
|
2002-09-09 19:38:11 +00:00
|
|
|
cp = p; /* skip past the number */
|
|
|
|
|
|
|
|
/* OK, what character terminated the octet? */
|
|
|
|
if (*cp == '/') {
|
|
|
|
/* "/" - this has a mask. */
|
|
|
|
if (!manuf_file) {
|
|
|
|
/* Entries with masks are allowed only in the "manuf" files. */
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
cp++; /* skip past the '/' to get to the mask */
|
|
|
|
if (!isdigit((unsigned char)*cp))
|
|
|
|
return FALSE; /* no sign allowed */
|
|
|
|
num = strtoul(cp, &p, 10);
|
|
|
|
if (p == cp)
|
|
|
|
return FALSE; /* failed */
|
|
|
|
cp = p; /* skip past the number */
|
|
|
|
if (*cp != '\0' && !isspace((unsigned char)*cp))
|
|
|
|
return FALSE; /* bogus terminator */
|
|
|
|
if (num == 0 || num >= 48)
|
|
|
|
return FALSE; /* bogus mask */
|
|
|
|
/* Mask out the bits not covered by the mask */
|
|
|
|
*mask = num;
|
|
|
|
for (i = 0; num >= 8; i++, num -= 8)
|
|
|
|
; /* skip octets entirely covered by the mask */
|
|
|
|
/* Mask out the first masked octet */
|
|
|
|
eth->addr[i] &= (0xFF << (8 - num));
|
|
|
|
i++;
|
|
|
|
/* Mask out completely-masked-out octets */
|
|
|
|
for (; i < 6; i++)
|
|
|
|
eth->addr[i] = 0;
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
if (*cp == '\0') {
|
|
|
|
/* We're at the end of the address, and there's no mask. */
|
|
|
|
if (i == 2) {
|
|
|
|
/* 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;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (i == 5) {
|
|
|
|
/* 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;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* We didn't get 3 or 6 bytes, and there's no mask; this is
|
|
|
|
illegal. */
|
|
|
|
return FALSE;
|
|
|
|
} else {
|
|
|
|
if (sep == '\0') {
|
|
|
|
/* 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 */
|
|
|
|
} else {
|
|
|
|
/* It has to be the same as the first separator */
|
|
|
|
if (*cp != sep)
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
cp++;
|
|
|
|
}
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int parse_ether_line(char *line, ether_t *eth, unsigned int *mask,
|
|
|
|
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;
|
|
|
|
|
|
|
|
static void set_ethent(char *path)
|
|
|
|
{
|
|
|
|
if (eth_p)
|
|
|
|
rewind(eth_p);
|
|
|
|
else
|
2005-11-06 22:43:25 +00:00
|
|
|
eth_p = eth_fopen(path, "r");
|
1998-09-25 23:24:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void end_ethent(void)
|
|
|
|
{
|
|
|
|
if (eth_p) {
|
|
|
|
fclose(eth_p);
|
|
|
|
eth_p = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2002-09-09 19:38:11 +00:00
|
|
|
static ether_t *get_ethent(unsigned int *mask, 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 */
|
|
|
|
|
2004-01-10 17:31:40 +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
|
|
|
|
2002-09-09 19:38:11 +00:00
|
|
|
while ((eth = get_ethent(NULL, FALSE)) && 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
|
|
|
|
2002-09-09 19:38:11 +00:00
|
|
|
while ((eth = get_ethent(NULL, FALSE)) && strncmp(name, eth->name, MAXNAMELEN) != 0)
|
1998-09-25 23:24:07 +00:00
|
|
|
;
|
|
|
|
|
|
|
|
end_ethent();
|
|
|
|
}
|
|
|
|
|
|
|
|
return eth;
|
|
|
|
|
|
|
|
} /* get_ethbyname */
|
|
|
|
|
2001-04-02 09:41:56 +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
|
|
|
|
2002-09-09 19:38:11 +00:00
|
|
|
while ((eth = get_ethent(NULL, FALSE)) && 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
|
|
|
|
2002-09-09 19:38:11 +00:00
|
|
|
while ((eth = get_ethent(NULL, FALSE)) && 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 */
|
|
|
|
|
2002-09-09 19:38:11 +00:00
|
|
|
static int hash_eth_wka(const guint8 *addr, unsigned int mask)
|
|
|
|
{
|
|
|
|
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)))))) &
|
|
|
|
(HASHETHSIZE - 1);
|
|
|
|
}
|
|
|
|
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)))))) &
|
|
|
|
(HASHETHSIZE - 1);
|
|
|
|
}
|
|
|
|
mask -= 8;
|
|
|
|
/* No bytes are fully masked out */
|
|
|
|
return ((((addr[1] << 8) | addr[2]) ^
|
|
|
|
((addr[3] << 8) | (addr[4] & (0xFF << (8 - mask)))))) &
|
|
|
|
(HASHETHSIZE - 1);
|
|
|
|
}
|
|
|
|
|
2004-01-10 17:31:40 +00:00
|
|
|
static void add_manuf_name(guint8 *addr, unsigned int mask, gchar *name)
|
1998-09-25 23:24:07 +00:00
|
|
|
{
|
2001-06-07 22:07:02 +00:00
|
|
|
int hash_idx;
|
1998-09-25 23:24:07 +00:00
|
|
|
hashmanuf_t *tp;
|
2002-09-09 19:38:11 +00:00
|
|
|
hashether_t *(*wka_tp)[HASHETHSIZE], *etp;
|
1998-09-25 23:24:07 +00:00
|
|
|
|
2002-09-09 19:38:11 +00:00
|
|
|
if (mask == 48) {
|
|
|
|
/* 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);
|
|
|
|
|
|
|
|
tp = manuf_table[hash_idx];
|
|
|
|
|
|
|
|
if( tp == NULL ) {
|
|
|
|
tp = manuf_table[hash_idx] = (hashmanuf_t *)g_malloc(sizeof(hashmanuf_t));
|
|
|
|
} else {
|
|
|
|
while(1) {
|
|
|
|
if (tp->next == NULL) {
|
|
|
|
tp->next = (hashmanuf_t *)g_malloc(sizeof(hashmanuf_t));
|
|
|
|
tp = tp->next;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
tp = tp->next;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
memcpy(tp->addr, addr, sizeof(tp->addr));
|
2007-10-26 05:42:12 +00:00
|
|
|
g_strlcpy(tp->name, name, MAXMANUFLEN);
|
2002-09-09 19:38:11 +00:00
|
|
|
tp->next = NULL;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* 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);
|
|
|
|
|
|
|
|
etp = (*wka_tp)[hash_idx];
|
|
|
|
|
|
|
|
if( etp == NULL ) {
|
|
|
|
etp = (*wka_tp)[hash_idx] = (hashether_t *)g_malloc(sizeof(hashether_t));
|
2002-08-28 20:41:00 +00:00
|
|
|
} else {
|
1998-09-25 23:24:07 +00:00
|
|
|
while(1) {
|
2002-09-09 19:38:11 +00:00
|
|
|
if (memcmp(etp->addr, addr, sizeof(etp->addr)) == 0) {
|
|
|
|
/* address already known */
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (etp->next == NULL) {
|
|
|
|
etp->next = (hashether_t *)g_malloc(sizeof(hashether_t));
|
|
|
|
etp = etp->next;
|
1998-09-25 23:24:07 +00:00
|
|
|
break;
|
|
|
|
}
|
2002-09-09 19:38:11 +00:00
|
|
|
etp = etp->next;
|
1998-09-25 23:24:07 +00:00
|
|
|
}
|
|
|
|
}
|
2002-08-28 20:41:00 +00:00
|
|
|
|
2002-09-09 19:38:11 +00:00
|
|
|
memcpy(etp->addr, addr, sizeof(etp->addr));
|
2007-10-26 05:42:12 +00:00
|
|
|
g_strlcpy(etp->name, name, MAXNAMELEN);
|
2002-09-09 19:38:11 +00:00
|
|
|
etp->next = NULL;
|
|
|
|
etp->is_dummy_entry = FALSE;
|
1998-09-25 23:24:07 +00:00
|
|
|
|
|
|
|
} /* add_manuf_name */
|
|
|
|
|
2001-04-02 09:41:56 +00:00
|
|
|
static hashmanuf_t *manuf_name_lookup(const guint8 *addr)
|
1998-09-25 23:24:07 +00:00
|
|
|
{
|
2001-06-07 22:07:02 +00:00
|
|
|
int hash_idx;
|
1998-09-25 23:24:07 +00:00
|
|
|
hashmanuf_t *tp;
|
2007-08-14 23:52:51 +00:00
|
|
|
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" */
|
2001-06-07 22:07:02 +00:00
|
|
|
tp = manuf_table[hash_idx];
|
1998-09-25 23:24:07 +00:00
|
|
|
while(tp != NULL) {
|
|
|
|
if (memcmp(tp->addr, addr, sizeof(tp->addr)) == 0) {
|
|
|
|
return tp;
|
|
|
|
}
|
|
|
|
tp = tp->next;
|
|
|
|
}
|
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
|
|
|
|
|
|
|
tp = manuf_table[hash_idx];
|
|
|
|
while(tp != NULL) {
|
|
|
|
if (memcmp(tp->addr, stripped_addr, sizeof(tp->addr)) == 0) {
|
|
|
|
return tp;
|
|
|
|
}
|
|
|
|
tp = tp->next;
|
|
|
|
}
|
|
|
|
|
1998-09-25 23:24:07 +00:00
|
|
|
return NULL;
|
|
|
|
|
|
|
|
} /* manuf_name_lookup */
|
|
|
|
|
2002-09-09 19:38:11 +00:00
|
|
|
static hashether_t *wka_name_lookup(const guint8 *addr, unsigned int mask)
|
|
|
|
{
|
|
|
|
int hash_idx;
|
|
|
|
hashether_t *(*wka_tp)[HASHETHSIZE];
|
|
|
|
hashether_t *tp;
|
|
|
|
guint8 masked_addr[6];
|
|
|
|
unsigned int num;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
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)
|
|
|
|
masked_addr[i] = addr[i]; /* copy octets entirely covered by the mask */
|
|
|
|
/* 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);
|
|
|
|
|
|
|
|
tp = (*wka_tp)[hash_idx];
|
|
|
|
|
|
|
|
while(tp != NULL) {
|
|
|
|
if (memcmp(tp->addr, masked_addr, sizeof(tp->addr)) == 0) {
|
|
|
|
return tp;
|
|
|
|
}
|
|
|
|
tp = tp->next;
|
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
} /* wka_name_lookup */
|
|
|
|
|
1999-11-20 05:35:15 +00:00
|
|
|
static void initialize_ethers(void)
|
|
|
|
{
|
|
|
|
ether_t *eth;
|
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
|
|
|
char *manuf_path;
|
2002-09-09 19:38:11 +00:00
|
|
|
unsigned int 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",
|
2001-10-21 21:48:00 +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)
|
|
|
|
g_pethers_path = get_persconffile_path(ENAME_ETHERS, 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 */
|
|
|
|
|
2004-01-10 17:31:40 +00:00
|
|
|
static hashether_t *add_eth_name(const guint8 *addr, const gchar *name)
|
1998-09-25 23:24:07 +00:00
|
|
|
{
|
2001-06-07 22:07:02 +00:00
|
|
|
int hash_idx;
|
1998-09-25 23:24:07 +00:00
|
|
|
hashether_t *tp;
|
2006-02-27 09:01:10 +00:00
|
|
|
int new_one = TRUE;
|
1998-09-25 23:24:07 +00:00
|
|
|
|
2001-06-07 22:07:02 +00:00
|
|
|
hash_idx = HASH_ETH_ADDRESS(addr);
|
1998-09-25 23:24:07 +00:00
|
|
|
|
2001-06-07 22:07:02 +00:00
|
|
|
tp = eth_table[hash_idx];
|
1998-09-25 23:24:07 +00:00
|
|
|
|
|
|
|
if( tp == NULL ) {
|
2001-06-07 22:07:02 +00:00
|
|
|
tp = eth_table[hash_idx] = (hashether_t *)g_malloc(sizeof(hashether_t));
|
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 (memcmp(tp->addr, addr, sizeof(tp->addr)) == 0) {
|
|
|
|
/* address already known */
|
|
|
|
if (!tp->is_dummy_entry) {
|
|
|
|
return tp;
|
|
|
|
} else {
|
|
|
|
/* replace this dummy (manuf) entry with a real name */
|
2006-02-27 09:01:10 +00:00
|
|
|
new_one = FALSE;
|
2000-08-10 20:09:29 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
1998-09-25 23:24:07 +00:00
|
|
|
if (tp->next == NULL) {
|
|
|
|
tp->next = (hashether_t *)g_malloc(sizeof(hashether_t));
|
|
|
|
tp = tp->next;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
tp = tp->next;
|
|
|
|
}
|
|
|
|
}
|
2002-08-28 20:41:00 +00:00
|
|
|
|
2007-10-26 05:42:12 +00:00
|
|
|
g_strlcpy(tp->name, name, MAXNAMELEN);
|
2006-02-27 09:01:10 +00:00
|
|
|
if (new_one) {
|
|
|
|
memcpy(tp->addr, addr, sizeof(tp->addr));
|
|
|
|
tp->next = NULL;
|
|
|
|
}
|
2000-08-10 20:09:29 +00:00
|
|
|
tp->is_dummy_entry = FALSE;
|
1998-09-25 23:24:07 +00:00
|
|
|
|
|
|
|
return tp;
|
|
|
|
|
|
|
|
} /* add_eth_name */
|
|
|
|
|
2004-01-10 17:31:40 +00:00
|
|
|
static gchar *eth_name_lookup(const guint8 *addr)
|
1998-09-25 23:24:07 +00:00
|
|
|
{
|
2001-06-07 22:07:02 +00:00
|
|
|
int hash_idx;
|
1998-09-25 23:24:07 +00:00
|
|
|
hashmanuf_t *manufp;
|
|
|
|
hashether_t *tp;
|
|
|
|
ether_t *eth;
|
2002-09-09 19:38:11 +00:00
|
|
|
hashether_t *etp;
|
|
|
|
unsigned int mask;
|
1998-09-25 23:24:07 +00:00
|
|
|
|
2001-06-07 22:07:02 +00:00
|
|
|
hash_idx = HASH_ETH_ADDRESS(addr);
|
1998-09-25 23:24:07 +00:00
|
|
|
|
2001-06-07 22:07:02 +00:00
|
|
|
tp = eth_table[hash_idx];
|
1998-09-25 23:24:07 +00:00
|
|
|
|
|
|
|
if( tp == NULL ) {
|
2001-06-07 22:07:02 +00:00
|
|
|
tp = eth_table[hash_idx] = (hashether_t *)g_malloc(sizeof(hashether_t));
|
2002-08-28 20:41:00 +00:00
|
|
|
} else {
|
1998-09-25 23:24:07 +00:00
|
|
|
while(1) {
|
|
|
|
if (memcmp(tp->addr, addr, sizeof(tp->addr)) == 0) {
|
|
|
|
return tp->name;
|
|
|
|
}
|
|
|
|
if (tp->next == NULL) {
|
|
|
|
tp->next = (hashether_t *)g_malloc(sizeof(hashether_t));
|
|
|
|
tp = tp->next;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
tp = tp->next;
|
|
|
|
}
|
|
|
|
}
|
2002-08-28 20:41:00 +00:00
|
|
|
|
1998-09-25 23:24:07 +00:00
|
|
|
/* fill in a new entry */
|
|
|
|
|
|
|
|
memcpy(tp->addr, addr, sizeof(tp->addr));
|
|
|
|
tp->next = NULL;
|
|
|
|
|
|
|
|
if ( (eth = get_ethbyaddr(addr)) == NULL) {
|
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 */
|
|
|
|
if ((etp = wka_name_lookup(addr, mask+40)) != NULL) {
|
2005-08-30 09:25:44 +00:00
|
|
|
g_snprintf(tp->name, MAXNAMELEN, "%s_%02x",
|
2002-09-09 19:38:11 +00:00
|
|
|
etp->name, addr[5] & (0xFF >> mask));
|
|
|
|
tp->is_dummy_entry = TRUE;
|
|
|
|
return (tp->name);
|
|
|
|
}
|
|
|
|
if (mask == 0)
|
|
|
|
break;
|
|
|
|
mask--;
|
|
|
|
}
|
|
|
|
|
|
|
|
mask = 7;
|
|
|
|
for (;;) {
|
|
|
|
/* Only the topmost 4 bytes participate fully */
|
|
|
|
if ((etp = wka_name_lookup(addr, mask+32)) != NULL) {
|
2005-08-30 09:25:44 +00:00
|
|
|
g_snprintf(tp->name, MAXNAMELEN, "%s_%02x:%02x",
|
2002-09-09 19:38:11 +00:00
|
|
|
etp->name, addr[4] & (0xFF >> mask), addr[5]);
|
|
|
|
tp->is_dummy_entry = TRUE;
|
|
|
|
return (tp->name);
|
|
|
|
}
|
|
|
|
if (mask == 0)
|
|
|
|
break;
|
|
|
|
mask--;
|
|
|
|
}
|
|
|
|
|
|
|
|
mask = 7;
|
|
|
|
for (;;) {
|
|
|
|
/* Only the topmost 3 bytes participate fully */
|
|
|
|
if ((etp = wka_name_lookup(addr, mask+24)) != NULL) {
|
2005-08-30 09:25:44 +00:00
|
|
|
g_snprintf(tp->name, MAXNAMELEN, "%s_%02x:%02x:%02x",
|
2002-09-09 19:38:11 +00:00
|
|
|
etp->name, addr[3] & (0xFF >> mask), addr[4], addr[5]);
|
|
|
|
tp->is_dummy_entry = TRUE;
|
|
|
|
return (tp->name);
|
|
|
|
}
|
|
|
|
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. */
|
|
|
|
if ((manufp = manuf_name_lookup(addr)) != NULL) {
|
2005-08-30 09:25:44 +00:00
|
|
|
g_snprintf(tp->name, MAXNAMELEN, "%s_%02x:%02x:%02x",
|
1998-09-25 23:24:07 +00:00
|
|
|
manufp->name, addr[3], addr[4], addr[5]);
|
2002-09-09 19:38:11 +00:00
|
|
|
tp->is_dummy_entry = TRUE;
|
|
|
|
return (tp->name);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* 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 */
|
|
|
|
if ((etp = wka_name_lookup(addr, mask+16)) != NULL) {
|
2005-08-30 09:25:44 +00:00
|
|
|
g_snprintf(tp->name, MAXNAMELEN, "%s_%02x:%02x:%02x:%02x",
|
2002-09-09 19:38:11 +00:00
|
|
|
etp->name, addr[2] & (0xFF >> mask), addr[3], addr[4],
|
|
|
|
addr[5]);
|
|
|
|
tp->is_dummy_entry = TRUE;
|
|
|
|
return (tp->name);
|
|
|
|
}
|
|
|
|
if (mask == 0)
|
|
|
|
break;
|
|
|
|
mask--;
|
|
|
|
}
|
|
|
|
|
|
|
|
mask = 7;
|
|
|
|
for (;;) {
|
|
|
|
/* Only the topmost byte participates fully */
|
|
|
|
if ((etp = wka_name_lookup(addr, mask+8)) != NULL) {
|
2005-08-30 09:25:44 +00:00
|
|
|
g_snprintf(tp->name, MAXNAMELEN, "%s_%02x:%02x:%02x:%02x:%02x",
|
2002-09-09 19:38:11 +00:00
|
|
|
etp->name, addr[1] & (0xFF >> mask), addr[2], addr[3],
|
|
|
|
addr[4], addr[5]);
|
|
|
|
tp->is_dummy_entry = TRUE;
|
|
|
|
return (tp->name);
|
|
|
|
}
|
|
|
|
if (mask == 0)
|
|
|
|
break;
|
|
|
|
mask--;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (mask = 7; mask > 0; mask--) {
|
|
|
|
/* Not even the topmost byte participates fully */
|
|
|
|
if ((etp = wka_name_lookup(addr, mask)) != NULL) {
|
2005-08-30 09:25:44 +00:00
|
|
|
g_snprintf(tp->name, MAXNAMELEN, "%s_%02x:%02x:%02x:%02x:%02x:%02x",
|
2002-09-09 19:38:11 +00:00
|
|
|
etp->name, addr[0] & (0xFF >> mask), addr[1], addr[2],
|
|
|
|
addr[3], addr[4], addr[5]);
|
|
|
|
tp->is_dummy_entry = TRUE;
|
|
|
|
return (tp->name);
|
|
|
|
}
|
|
|
|
}
|
1998-09-25 23:24:07 +00:00
|
|
|
|
2002-09-09 19:38:11 +00:00
|
|
|
/* No match whatsoever. */
|
2005-08-30 09:25:44 +00:00
|
|
|
g_snprintf(tp->name, MAXNAMELEN, "%s", ether_to_str(addr));
|
2000-08-10 20:09:29 +00:00
|
|
|
tp->is_dummy_entry = TRUE;
|
1999-11-20 05:35:15 +00:00
|
|
|
|
1998-09-25 23:24:07 +00:00
|
|
|
} else {
|
2007-10-26 05:42:12 +00:00
|
|
|
g_strlcpy(tp->name, eth->name, MAXNAMELEN);
|
2000-08-10 20:09:29 +00:00
|
|
|
tp->is_dummy_entry = FALSE;
|
1998-09-25 23:24:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return (tp->name);
|
|
|
|
|
|
|
|
} /* eth_name_lookup */
|
|
|
|
|
2004-01-10 17:31:40 +00:00
|
|
|
static guint8 *eth_addr_lookup(const gchar *name)
|
1999-11-20 05:35:15 +00:00
|
|
|
{
|
1999-11-21 16:32:23 +00:00
|
|
|
ether_t *eth;
|
1999-11-20 05:35:15 +00:00
|
|
|
hashether_t *tp;
|
|
|
|
hashether_t **table = eth_table;
|
1999-11-21 16:32:23 +00:00
|
|
|
int 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) {
|
|
|
|
if (strcmp(tp->name, name) == 0)
|
|
|
|
return tp->addr;
|
|
|
|
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 */
|
|
|
|
static int parse_ipxnets_line(char *line, ipxnet_t *ipxnet)
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* We allow three address separators (':', '-', and '.'),
|
|
|
|
* as well as no separators
|
|
|
|
*/
|
|
|
|
|
|
|
|
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) {
|
|
|
|
found_single_number = TRUE;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
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) {
|
|
|
|
ipxnet->addr = a;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
ipxnet->addr = (a0 << 24) | (a1 << 16) | (a2 << 8) | a3;
|
|
|
|
}
|
|
|
|
|
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;
|
|
|
|
|
|
|
|
static void set_ipxnetent(char *path)
|
|
|
|
{
|
|
|
|
if (ipxnet_p)
|
|
|
|
rewind(ipxnet_p);
|
|
|
|
else
|
2005-11-06 22:43:25 +00:00
|
|
|
ipxnet_p = eth_fopen(path, "r");
|
1999-11-21 16:32:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void end_ipxnetent(void)
|
|
|
|
{
|
|
|
|
if (ipxnet_p) {
|
|
|
|
fclose(ipxnet_p);
|
|
|
|
ipxnet_p = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static ipxnet_t *get_ipxnetent(void)
|
|
|
|
{
|
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 */
|
|
|
|
|
2004-01-10 17:31:40 +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);
|
|
|
|
|
|
|
|
while ((ipxnet = get_ipxnetent()) && strncmp(name, ipxnet->name, MAXNAMELEN) != 0)
|
|
|
|
;
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
|
|
|
while ((ipxnet = get_ipxnetent()) && strncmp(name, ipxnet->name, MAXNAMELEN) != 0)
|
|
|
|
;
|
|
|
|
|
|
|
|
end_ipxnetent();
|
|
|
|
}
|
|
|
|
|
|
|
|
return ipxnet;
|
|
|
|
|
|
|
|
} /* get_ipxnetbyname */
|
|
|
|
|
|
|
|
static ipxnet_t *get_ipxnetbyaddr(guint32 addr)
|
|
|
|
{
|
|
|
|
|
|
|
|
ipxnet_t *ipxnet;
|
2002-08-28 20:41:00 +00:00
|
|
|
|
1999-11-21 16:32:23 +00:00
|
|
|
set_ipxnetent(g_ipxnets_path);
|
|
|
|
|
|
|
|
while ((ipxnet = get_ipxnetent()) && (addr != ipxnet->addr) ) ;
|
|
|
|
|
|
|
|
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
|
|
|
|
1999-11-21 16:32:23 +00:00
|
|
|
while ((ipxnet = get_ipxnetent()) && (addr != ipxnet->addr) )
|
|
|
|
;
|
2002-08-28 20:41:00 +00:00
|
|
|
|
1999-11-21 16:32:23 +00:00
|
|
|
end_ipxnetent();
|
|
|
|
}
|
|
|
|
|
|
|
|
return ipxnet;
|
|
|
|
|
|
|
|
} /* get_ipxnetbyaddr */
|
|
|
|
|
|
|
|
static void initialize_ipxnets(void)
|
|
|
|
{
|
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) {
|
2005-08-08 18:50:39 +00:00
|
|
|
g_ipxnets_path = g_strdup_printf("%s" G_DIR_SEPARATOR_S "%s",
|
2001-10-21 21:48:00 +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)
|
|
|
|
g_pipxnets_path = get_persconffile_path(ENAME_IPXNETS, FALSE);
|
1999-11-21 16:32:23 +00:00
|
|
|
|
|
|
|
} /* initialize_ipxnets */
|
|
|
|
|
2004-01-10 17:31:40 +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) {
|
|
|
|
tp->next = (hashipxnet_t *)g_malloc(sizeof(hashipxnet_t));
|
|
|
|
tp = tp->next;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
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;
|
|
|
|
|
|
|
|
return tp;
|
|
|
|
|
|
|
|
} /* add_ipxnet_name */
|
|
|
|
|
2004-01-10 17:31:40 +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) {
|
|
|
|
return tp->name;
|
1999-11-20 05:35:15 +00:00
|
|
|
}
|
|
|
|
if (tp->next == NULL) {
|
1999-11-21 16:32:23 +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 */
|
2005-08-30 09:25:44 +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 */
|
|
|
|
|
2004-01-10 17:31:40 +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;
|
1998-09-25 23:24:07 +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
|
|
|
|
2005-01-07 10:20:17 +00:00
|
|
|
static gboolean
|
|
|
|
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 */
|
2004-11-17 09:44:41 +00:00
|
|
|
struct e_in6_addr ipv6_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).
|
|
|
|
*/
|
2005-11-06 22:43:25 +00:00
|
|
|
if ((hf = eth_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) {
|
|
|
|
memcpy(&ipv6_addr, host_addr, sizeof ipv6_addr);
|
|
|
|
add_ipv6_name(&ipv6_addr, cp);
|
|
|
|
} 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.
|
|
|
|
*/
|
|
|
|
while ((cp = strtok(NULL, " \t")) != NULL) {
|
2004-11-17 09:44:41 +00:00
|
|
|
if (is_ipv6) {
|
|
|
|
memcpy(&ipv6_addr, host_addr, sizeof ipv6_addr);
|
|
|
|
add_ipv6_name(&ipv6_addr, cp);
|
|
|
|
} else
|
2004-11-17 08:53:20 +00:00
|
|
|
add_ipv4_name(host_addr[0], cp);
|
2004-11-17 08:34:36 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if (line != NULL)
|
|
|
|
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
|
|
|
|
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;
|
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 */
|
|
|
|
|
2005-07-19 20:44:45 +00:00
|
|
|
/*
|
|
|
|
* Load the user's hosts file, if they have one.
|
|
|
|
*/
|
|
|
|
hostspath = get_persconffile_path(ENAME_HOSTS, FALSE);
|
|
|
|
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);
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
gnu_adns_initialized = TRUE;
|
2003-05-04 18:50:56 +00:00
|
|
|
adns_currently_queued = 0;
|
2005-01-13 09:09:56 +00:00
|
|
|
#endif /* HAVE_GNU_ADNS */
|
2003-05-04 18:50:56 +00:00
|
|
|
}
|
|
|
|
|
2005-01-13 09:09:56 +00:00
|
|
|
#ifdef HAVE_GNU_ADNS
|
|
|
|
|
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?
|
|
|
|
*/
|
|
|
|
gint
|
|
|
|
host_name_lookup_process(gpointer data _U_) {
|
|
|
|
adns_queue_msg_t *almsg;
|
|
|
|
GList *cur;
|
|
|
|
char addr_str[] = "111.222.333.444.in-addr.arpa.";
|
|
|
|
guint8 *addr_bytes;
|
|
|
|
adns_answer *ans;
|
|
|
|
int ret;
|
|
|
|
gboolean dequeue;
|
|
|
|
|
|
|
|
adns_queue_head = g_list_first(adns_queue_head);
|
|
|
|
|
|
|
|
cur = adns_queue_head;
|
2003-07-22 03:14:31 +00:00
|
|
|
while (cur && adns_currently_queued <= prefs.name_resolve_concurrency) {
|
|
|
|
almsg = (adns_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],
|
2003-05-04 18:50:56 +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;
|
|
|
|
adns_currently_queued++;
|
|
|
|
}
|
|
|
|
cur = cur->next;
|
|
|
|
}
|
|
|
|
|
|
|
|
cur = adns_queue_head;
|
|
|
|
while (cur) {
|
|
|
|
dequeue = FALSE;
|
|
|
|
almsg = (adns_queue_msg_t *) cur->data;
|
|
|
|
if (almsg->submitted) {
|
|
|
|
ret = adns_check(ads, &almsg->query, &ans, NULL);
|
|
|
|
if (ret == 0) {
|
|
|
|
if (ans->status == adns_s_ok) {
|
2004-11-17 08:53:20 +00:00
|
|
|
add_ipv4_name(almsg->ip4_addr, *ans->rrs.str);
|
2003-05-04 18:50:56 +00:00
|
|
|
}
|
|
|
|
dequeue = TRUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
cur = cur->next;
|
|
|
|
if (dequeue) {
|
|
|
|
adns_queue_head = g_list_remove(adns_queue_head, (void *) almsg);
|
|
|
|
g_free(almsg);
|
|
|
|
adns_currently_queued--;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2003-05-05 00:53:06 +00:00
|
|
|
/* Keep the timeout in place */
|
2003-05-04 18:50:56 +00:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2003-05-05 00:53:06 +00:00
|
|
|
host_name_lookup_cleanup(void) {
|
2003-05-04 18:50:56 +00:00
|
|
|
void *qdata;
|
|
|
|
|
|
|
|
adns_queue_head = g_list_first(adns_queue_head);
|
|
|
|
while (adns_queue_head) {
|
|
|
|
qdata = adns_queue_head->data;
|
|
|
|
adns_queue_head = g_list_remove(adns_queue_head, qdata);
|
|
|
|
g_free(qdata);
|
|
|
|
}
|
2006-01-19 23:01:24 +00:00
|
|
|
|
2004-11-10 06:50:55 +00:00
|
|
|
if (gnu_adns_initialized)
|
2004-11-10 05:01:09 +00:00
|
|
|
adns_finish(ads);
|
2003-05-04 18:50:56 +00:00
|
|
|
}
|
|
|
|
|
2003-05-05 00:53:06 +00:00
|
|
|
#else
|
|
|
|
|
|
|
|
gint
|
|
|
|
host_name_lookup_process(gpointer data _U_) {
|
|
|
|
/* Kill the timeout, as there's nothing for it to do */
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
host_name_lookup_cleanup(void) {
|
|
|
|
}
|
|
|
|
|
2003-05-04 18:50:56 +00:00
|
|
|
#endif /* HAVE_GNU_ADNS */
|
|
|
|
|
2004-01-10 17:31:40 +00:00
|
|
|
extern gchar *get_hostname(guint addr)
|
1998-09-16 02:39:15 +00:00
|
|
|
{
|
2000-08-10 20:09:29 +00:00
|
|
|
gboolean found;
|
|
|
|
|
2002-01-13 20:35:12 +00:00
|
|
|
if (!(g_resolv_flags & RESOLV_NETWORK))
|
1998-09-16 02:39:15 +00:00
|
|
|
return ip_to_str((guint8 *)&addr);
|
|
|
|
|
2000-08-10 20:09:29 +00:00
|
|
|
return host_name_lookup(addr, &found);
|
1998-09-16 02:39:15 +00:00
|
|
|
}
|
|
|
|
|
2004-01-10 17:31:40 +00:00
|
|
|
extern const gchar *get_hostname6(struct e_in6_addr *addr)
|
1999-03-28 18:32:03 +00:00
|
|
|
{
|
2000-08-10 20:09:29 +00:00
|
|
|
gboolean found;
|
|
|
|
|
2002-01-13 20:35:12 +00:00
|
|
|
if (!(g_resolv_flags & RESOLV_NETWORK))
|
1999-03-28 18:32:03 +00:00
|
|
|
return ip6_to_str(addr);
|
2005-09-12 06:21:35 +00:00
|
|
|
if (E_IN6_IS_ADDR_LINKLOCAL(addr) || E_IN6_IS_ADDR_MULTICAST(addr))
|
1999-03-28 18:32:03 +00:00
|
|
|
return ip6_to_str(addr);
|
2000-08-10 20:09:29 +00:00
|
|
|
return host_name_lookup6(addr, &found);
|
1999-03-28 18:32:03 +00:00
|
|
|
}
|
|
|
|
|
2004-11-17 08:53:20 +00:00
|
|
|
extern void add_ipv4_name(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;
|
2006-02-27 09:01:10 +00:00
|
|
|
int new_one = TRUE;
|
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 ) {
|
2004-11-17 08:53:20 +00:00
|
|
|
tp = ipv4_table[hash_idx] = (hashipv4_t *)g_malloc(sizeof(hashipv4_t));
|
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) {
|
2000-08-08 16:21:24 +00:00
|
|
|
/* address already known */
|
2000-08-10 20:09:29 +00:00
|
|
|
if (!tp->is_dummy_entry) {
|
|
|
|
return;
|
|
|
|
} else {
|
|
|
|
/* replace this dummy entry with the new one */
|
2006-02-27 09:01:10 +00:00
|
|
|
new_one = FALSE;
|
2000-08-10 20:09:29 +00:00
|
|
|
break;
|
|
|
|
}
|
2000-08-08 16:21:24 +00:00
|
|
|
}
|
1998-09-25 23:24:07 +00:00
|
|
|
if (tp->next == NULL) {
|
2004-11-17 08:53:20 +00:00
|
|
|
tp->next = (hashipv4_t *)g_malloc(sizeof(hashipv4_t));
|
1998-09-25 23:24:07 +00:00
|
|
|
tp = tp->next;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
tp = tp->next;
|
|
|
|
}
|
|
|
|
}
|
2002-08-28 20:41:00 +00:00
|
|
|
|
2007-10-26 05:42:12 +00:00
|
|
|
g_strlcpy(tp->name, name, MAXNAMELEN);
|
2006-02-27 09:01:10 +00:00
|
|
|
if (new_one) {
|
|
|
|
tp->addr = addr;
|
|
|
|
tp->next = NULL;
|
|
|
|
}
|
2000-08-10 20:09:29 +00:00
|
|
|
tp->is_dummy_entry = FALSE;
|
1998-09-25 23:24:07 +00:00
|
|
|
|
2004-11-17 08:53:20 +00:00
|
|
|
} /* add_ipv4_name */
|
1998-09-25 23:24:07 +00:00
|
|
|
|
2004-11-17 09:44:41 +00:00
|
|
|
extern void add_ipv6_name(struct e_in6_addr *addrp, const gchar *name)
|
|
|
|
{
|
|
|
|
int hash_idx;
|
|
|
|
hashipv6_t *tp;
|
2006-02-27 09:01:10 +00:00
|
|
|
int new_one = TRUE;
|
2004-11-17 09:44:41 +00:00
|
|
|
|
|
|
|
hash_idx = HASH_IPV6_ADDRESS(*addrp);
|
|
|
|
|
|
|
|
tp = ipv6_table[hash_idx];
|
|
|
|
|
|
|
|
if( tp == NULL ) {
|
|
|
|
tp = ipv6_table[hash_idx] = (hashipv6_t *)g_malloc(sizeof(hashipv6_t));
|
|
|
|
} else {
|
|
|
|
while(1) {
|
|
|
|
if (memcmp(&tp->addr, addrp, sizeof (struct e_in6_addr)) == 0) {
|
|
|
|
/* address already known */
|
|
|
|
if (!tp->is_dummy_entry) {
|
|
|
|
return;
|
|
|
|
} else {
|
|
|
|
/* replace this dummy entry with the new one */
|
2006-02-27 09:01:10 +00:00
|
|
|
new_one = FALSE;
|
2004-11-17 09:44:41 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (tp->next == NULL) {
|
|
|
|
tp->next = (hashipv6_t *)g_malloc(sizeof(hashipv6_t));
|
|
|
|
tp = tp->next;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
tp = tp->next;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-10-26 05:42:12 +00:00
|
|
|
g_strlcpy(tp->name, name, MAXNAMELEN);
|
2006-02-27 09:01:10 +00:00
|
|
|
if (new_one) {
|
|
|
|
tp->addr = *addrp;
|
|
|
|
tp->next = NULL;
|
|
|
|
}
|
2004-11-17 09:44:41 +00:00
|
|
|
tp->is_dummy_entry = FALSE;
|
|
|
|
|
|
|
|
} /* add_ipv6_name */
|
|
|
|
|
2007-11-09 05:55:33 +00:00
|
|
|
/* -----------------
|
|
|
|
* unsigned integer to ascii
|
|
|
|
*/
|
|
|
|
static gchar *ep_utoa(guint port)
|
|
|
|
{
|
|
|
|
gchar *bp = ep_alloc(MAXNAMELEN);
|
|
|
|
|
|
|
|
bp = &bp[MAXNAMELEN -1];
|
|
|
|
|
|
|
|
*bp = 0;
|
|
|
|
do {
|
|
|
|
*--bp = (port % 10) +'0';
|
|
|
|
} while ((port /= 10) != 0);
|
|
|
|
return bp;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-01-10 17:31:40 +00:00
|
|
|
extern gchar *get_udp_port(guint port)
|
1998-09-16 02:39:15 +00:00
|
|
|
{
|
|
|
|
|
2002-01-13 20:35:12 +00:00
|
|
|
if (!(g_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 */
|
|
|
|
|
2005-09-20 15:18:28 +00:00
|
|
|
extern gchar *get_dccp_port(guint port)
|
|
|
|
{
|
|
|
|
|
|
|
|
if (!(g_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 */
|
|
|
|
|
|
|
|
|
2004-01-10 17:31:40 +00:00
|
|
|
extern gchar *get_tcp_port(guint port)
|
1998-09-16 02:39:15 +00:00
|
|
|
{
|
|
|
|
|
2002-01-13 20:35:12 +00:00
|
|
|
if (!(g_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 */
|
|
|
|
|
2004-01-10 17:31:40 +00:00
|
|
|
extern gchar *get_sctp_port(guint port)
|
2000-08-19 08:26:04 +00:00
|
|
|
{
|
|
|
|
|
2002-01-13 20:35:12 +00:00
|
|
|
if (!(g_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 */
|
|
|
|
|
2005-02-22 01:55:04 +00:00
|
|
|
|
2004-12-30 02:10:24 +00:00
|
|
|
const gchar *get_addr_name(address *addr)
|
|
|
|
{
|
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
|
|
|
|
2005-02-22 01:55:04 +00:00
|
|
|
if (result!=NULL){
|
|
|
|
return result;
|
|
|
|
}
|
2006-01-19 23:01:24 +00:00
|
|
|
|
2005-02-22 01:55:04 +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- */
|
2006-01-19 23:01:24 +00:00
|
|
|
|
2005-02-22 01:55:04 +00:00
|
|
|
if (addr->type == AT_NONE){
|
|
|
|
return "NONE";
|
|
|
|
}
|
2006-01-19 23:01:24 +00:00
|
|
|
|
2005-02-22 01:55:04 +00:00
|
|
|
return(address_to_str(addr));
|
|
|
|
} /* get_addr_name */
|
2006-01-19 23:01:24 +00:00
|
|
|
|
|
|
|
|
2005-02-22 01:55:04 +00:00
|
|
|
void get_addr_name_buf(address *addr, gchar *buf, guint size)
|
|
|
|
{
|
2007-09-28 18:23:59 +00:00
|
|
|
const gchar *result = get_addr_name(addr);
|
2004-12-30 02:10:24 +00:00
|
|
|
|
2007-09-28 18:23:59 +00:00
|
|
|
g_snprintf(buf, size, "%s", result);
|
2005-02-22 01:55:04 +00:00
|
|
|
} /* get_addr_name_buf */
|
2004-12-30 02:10:24 +00:00
|
|
|
|
|
|
|
|
2004-01-10 17:31:40 +00:00
|
|
|
extern gchar *get_ether_name(const guint8 *addr)
|
1998-09-25 23:24:07 +00:00
|
|
|
{
|
2002-01-13 20:35:12 +00:00
|
|
|
if (!(g_resolv_flags & RESOLV_MAC))
|
2002-11-27 22:42:40 +00:00
|
|
|
return ether_to_str(addr);
|
1998-09-25 23:24:07 +00:00
|
|
|
|
|
|
|
if (!eth_resolution_initialized) {
|
|
|
|
initialize_ethers();
|
|
|
|
eth_resolution_initialized = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return eth_name_lookup(addr);
|
|
|
|
|
|
|
|
} /* get_ether_name */
|
|
|
|
|
1999-11-21 16:32:23 +00:00
|
|
|
/* Look for an ether name in the hash, and return it if found.
|
|
|
|
* If it's not found, simply return NULL. We DO NOT make a new
|
|
|
|
* hash entry for it with the hex digits turned into a string.
|
|
|
|
*/
|
2004-01-10 17:31:40 +00:00
|
|
|
gchar *get_ether_name_if_known(const guint8 *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
|
|
|
hashether_t *tp;
|
|
|
|
|
|
|
|
/* Initialize ether structs if we're the first
|
|
|
|
* ether-related function called */
|
2002-01-13 20:35:12 +00:00
|
|
|
if (!(g_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();
|
|
|
|
eth_resolution_initialized = 1;
|
|
|
|
}
|
|
|
|
|
2001-06-07 22:07:02 +00:00
|
|
|
hash_idx = HASH_ETH_ADDRESS(addr);
|
1999-11-21 16:32:23 +00:00
|
|
|
|
2001-06-07 22:07:02 +00:00
|
|
|
tp = eth_table[hash_idx];
|
1999-11-21 16:32:23 +00:00
|
|
|
|
|
|
|
if( tp == NULL ) {
|
|
|
|
/* Hash key not found in table.
|
|
|
|
* Force a lookup (and a hash entry) for addr, then call
|
|
|
|
* myself. I plan on not getting into an infinite loop because
|
|
|
|
* eth_name_lookup() is guaranteed to make a hashtable entry,
|
|
|
|
* so when I call myself again, I can never get into this
|
|
|
|
* block of code again. Knock on wood...
|
|
|
|
*/
|
|
|
|
(void) eth_name_lookup(addr);
|
|
|
|
return get_ether_name_if_known(addr); /* a well-placed goto would suffice */
|
|
|
|
}
|
2002-08-28 20:41:00 +00:00
|
|
|
else {
|
1999-11-21 16:32:23 +00:00
|
|
|
while(1) {
|
|
|
|
if (memcmp(tp->addr, addr, sizeof(tp->addr)) == 0) {
|
2000-08-10 20:09:29 +00:00
|
|
|
if (!tp->is_dummy_entry) {
|
1999-11-21 16:32:23 +00:00
|
|
|
/* A name was found, and its origin is an ethers file */
|
|
|
|
return tp->name;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
/* A name was found, but it was created, not found in a file */
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (tp->next == NULL) {
|
|
|
|
/* Read my reason above for why I'm sure I can't get into an infinite loop */
|
|
|
|
(void) eth_name_lookup(addr);
|
|
|
|
return get_ether_name_if_known(addr); /* a well-placed goto would suffice */
|
|
|
|
}
|
|
|
|
tp = tp->next;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
g_assert_not_reached();
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-01-10 17:31:40 +00:00
|
|
|
extern guint8 *get_ether_addr(const gchar *name)
|
1998-09-25 23:24:07 +00:00
|
|
|
{
|
|
|
|
|
2002-01-13 20:35:12 +00:00
|
|
|
/* force resolution (do not check g_resolv_flags) */
|
1998-09-25 23:24:07 +00:00
|
|
|
|
|
|
|
if (!eth_resolution_initialized) {
|
|
|
|
initialize_ethers();
|
|
|
|
eth_resolution_initialized = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return eth_addr_lookup(name);
|
|
|
|
|
|
|
|
} /* get_ether_addr */
|
|
|
|
|
2001-04-02 09:41:56 +00:00
|
|
|
extern void add_ether_byip(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 */
|
|
|
|
|
2006-02-09 09:18:15 +00:00
|
|
|
if (!(g_resolv_flags & RESOLV_NETWORK) || ((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
|
|
|
|
2004-01-10 17:31:40 +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
|
|
|
|
2002-01-13 20:35:12 +00:00
|
|
|
if (!(g_resolv_flags & RESOLV_NETWORK)) {
|
1999-11-22 06:03:46 +00:00
|
|
|
return ipxnet_to_str_punct(addr, '\0');
|
|
|
|
}
|
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 */
|
|
|
|
|
2004-01-10 17:31:40 +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
|
|
|
|
2002-01-13 20:35:12 +00:00
|
|
|
/* force resolution (do not check g_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 */
|
|
|
|
|
2004-01-10 17:31:40 +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;
|
1998-09-25 23:24:07 +00:00
|
|
|
hashmanuf_t *manufp;
|
|
|
|
|
2002-01-13 20:35:12 +00:00
|
|
|
if ((g_resolv_flags & RESOLV_MAC) && !eth_resolution_initialized) {
|
1998-09-25 23:24:07 +00:00
|
|
|
initialize_ethers();
|
|
|
|
eth_resolution_initialized = 1;
|
|
|
|
}
|
|
|
|
|
2002-01-13 20:35:12 +00:00
|
|
|
if (!(g_resolv_flags & RESOLV_MAC) || ((manufp = manuf_name_lookup(addr)) == NULL)) {
|
2005-08-17 09:36:20 +00:00
|
|
|
cur=ep_alloc(MAXMANUFLEN);
|
2005-08-08 18:50:39 +00:00
|
|
|
g_snprintf(cur, MAXMANUFLEN, "%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
|
|
|
|
1998-09-25 23:24:07 +00:00
|
|
|
return manufp->name;
|
|
|
|
|
|
|
|
} /* get_manuf_name */
|
1999-07-07 22:52:57 +00:00
|
|
|
|
|
|
|
|
2005-05-20 21:44:17 +00:00
|
|
|
const gchar *get_manuf_name_if_known(const guint8 *addr)
|
|
|
|
{
|
|
|
|
hashmanuf_t *manufp;
|
|
|
|
|
|
|
|
if (!eth_resolution_initialized) {
|
|
|
|
initialize_ethers();
|
|
|
|
eth_resolution_initialized = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((manufp = manuf_name_lookup(addr)) == NULL) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return manufp->name;
|
|
|
|
|
|
|
|
} /* get_manuf_name_if_known */
|
|
|
|
|
1999-07-07 22:52:57 +00:00
|
|
|
|
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 */
|
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
|
|
|
gboolean get_host_ipaddr(const char *host, guint32 *addrp)
|
1999-07-07 22:52:57 +00:00
|
|
|
{
|
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
|
|
|
struct in_addr ipaddr;
|
|
|
|
struct hostent *hp;
|
1999-07-07 22:52:57 +00:00
|
|
|
|
1999-10-14 05:41:33 +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.
|
|
|
|
*/
|
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
|
|
|
if (!inet_aton(host, &ipaddr)) {
|
|
|
|
/* It's not a valid dotted-quad IP address; is it a valid
|
|
|
|
* host name? */
|
|
|
|
hp = gethostbyname(host);
|
1999-07-07 22:52:57 +00:00
|
|
|
if (hp == NULL) {
|
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
|
|
|
/* No. */
|
|
|
|
return FALSE;
|
2000-11-19 19:45:54 +00:00
|
|
|
/* Apparently, some versions of gethostbyaddr can
|
|
|
|
* return IPv6 addresses. */
|
2001-10-26 17:29:12 +00:00
|
|
|
} else if (hp->h_length <= (int) sizeof (struct in_addr)) {
|
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
|
|
|
memcpy(&ipaddr, hp->h_addr, hp->h_length);
|
2000-11-19 19:45:54 +00:00
|
|
|
} else {
|
|
|
|
return FALSE;
|
1999-07-07 22:52:57 +00:00
|
|
|
}
|
2002-03-03 21:42:54 +00:00
|
|
|
} 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;
|
2004-01-25 15:35:45 +00:00
|
|
|
if (sscanf(host, "%u.%u.%u.%u", &a0, &a1, &a2, &a3) != 4)
|
2002-03-03 21:42:54 +00:00
|
|
|
return FALSE;
|
1999-07-07 22:52:57 +00:00
|
|
|
}
|
|
|
|
|
2002-08-02 21:29:45 +00:00
|
|
|
*addrp = g_ntohl(ipaddr.s_addr);
|
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
|
|
|
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.
|
|
|
|
*/
|
|
|
|
gboolean get_host_ipaddr6(const char *host, struct e_in6_addr *addrp)
|
|
|
|
{
|
|
|
|
struct hostent *hp;
|
|
|
|
|
|
|
|
if (inet_pton(AF_INET6, host, addrp) == 1)
|
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
/* try FQDN */
|
|
|
|
#ifdef HAVE_GETHOSTBYNAME2
|
|
|
|
hp = gethostbyname2(host, AF_INET6);
|
|
|
|
#else
|
|
|
|
hp = NULL;
|
|
|
|
#endif
|
|
|
|
if (hp != NULL && hp->h_length == sizeof(struct e_in6_addr)) {
|
|
|
|
memcpy(addrp, hp->h_addr, hp->h_length);
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
}
|
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
|
|
|
|
struct hostent *h;
|
|
|
|
return (h = gethostbyname2(host, AF_INET6)) && h->h_addrtype == AF_INET6 ? "ip6" : "ip";
|
|
|
|
#else
|
|
|
|
return "ip";
|
|
|
|
#endif
|
|
|
|
}
|