Transition from GeoIP Legacy to MaxMindDB.

MaxMind is discontinuing its legacy databases in April in favor of
GeoIP2, which use a newer database format (MaxMind DB). The reference C
library (libmaxminddb) is available under the Apache 2.0 license which
isn't quite compatible with ours.

Add mmdbresolve, a utility that reads IPv4 and IPv6 addresses on stdin
and prints resolved information on stdout. Place it under a liberal
license (MIT) so that we can keep libmaxminddb at arm's length. Add
epan/maxmind_db.[ch], which spawns mmdbresolve and communicates with it
via stdio.

Migrate the preferences and documentation to MaxMindDB.

Change the IPv4 and IPv6 asnum fields to FT_UINT32s. Change the
geographic coordinate fields to FT_DOUBLEs.

Bug: 10658
Change-Id: I24aeed637bea1b41d173270bda413af230f4425f
Reviewed-on: https://code.wireshark.org/review/26214
Petri-Dish: Gerald Combs <gerald@wireshark.org>
Tested-by: Petri Dish Buildbot
Reviewed-by: Gerald Combs <gerald@wireshark.org>
This commit is contained in:
Gerald Combs 2018-02-08 17:20:26 -08:00
parent b2d3680558
commit a1da75c554
55 changed files with 1539 additions and 1518 deletions

View File

@ -923,6 +923,11 @@ if(BUILD_wireshark)
endif()
endif()
# MaxMind DB address resolution
if(BUILD_mmdbresolve)
set(PACKAGELIST ${PACKAGELIST} MaxMindDB)
endif()
# SMI SNMP
if(ENABLE_SMI)
set(PACKAGELIST ${PACKAGELIST} SMI)
@ -991,11 +996,6 @@ if(ENABLE_LUA)
set(PACKAGELIST ${PACKAGELIST} LUA)
endif()
# GeoIP address resolving
if(ENABLE_GEOIP)
set(PACKAGELIST ${PACKAGELIST} GEOIP)
endif()
if(ENABLE_NETLINK)
set(PACKAGELIST ${PACKAGELIST} NL)
endif()
@ -1117,8 +1117,8 @@ endif()
if(HAVE_LIBKERBEROS)
set(HAVE_KERBEROS 1)
endif()
if(HAVE_LIBGEOIP)
set(HAVE_GEOIP 1)
if(MAXMINDDB_FOUND)
set(HAVE_MAXMINDDB 1)
endif()
if(LIBSSH_FOUND)
set(HAVE_LIBSSH 1)
@ -1648,6 +1648,10 @@ set(INSTALL_FILES
${CMAKE_BINARY_DIR}/doc/wireshark-filter.html
)
if(MAXMINDDB_FOUND)
list(APPEND INSTALL_FILES ${CMAKE_BINARY_DIR}/doc/mmdbresolve.html)
endif()
if (BUILD_corbaidl2wrs)
list(APPEND INSTALL_FILES ${CMAKE_BINARY_DIR}/doc/idl2wrs.html)
endif()
@ -2919,6 +2923,20 @@ if(BUILD_randpktdump)
add_dependencies(extcaps randpktdump)
endif()
if (MAXMINDDB_FOUND)
set(mmdbresolve_LIBS
# Note: libmaxminddb is not GPL-2 compatible.
${MAXMINDDB_LIBRARY}
)
set(mmdbresolve_FILES
mmdbresolve.c
)
add_executable(mmdbresolve ${mmdbresolve_FILES})
set_extra_executable_properties(mmdbresolve "Executables")
target_link_libraries(mmdbresolve ${mmdbresolve_LIBS})
install(TARGETS mmdbresolve RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
endif()
if(ENABLE_APPLICATION_BUNDLE)
add_custom_target(app_bundle)
set_target_properties(app_bundle PROPERTIES FOLDER "Copy Tasks")
@ -2990,7 +3008,7 @@ set(CLEAN_C_FILES
${androiddump_FILES}
${sshdump_FILES}
${ciscodump_FILES}
${udpdump_FILES}
${mmdbresolve_FILES}
)
# Make sure we don't pass /WX to rc.exe. Rc doesn't have a /WX flag,

View File

@ -24,6 +24,7 @@ option(BUILD_randpktdump "Build randpktdump" ON)
option(BUILD_udpdump "Build udpdump" ON)
option(BUILD_sharkd "Build sharkd" ON)
option(BUILD_fuzzshark "Build fuzzshark" ON)
option(BUILD_mmdbresolve "Build MaxMind DB resolver" ON)
option(DISABLE_WERROR "Do not treat warnings as errors" OFF)
option(DISABLE_FRAME_LARGER_THAN_WARNING "Disable warning if the size of a function frame is large" OFF)
@ -67,7 +68,6 @@ option(ENABLE_NGHTTP2 "Build with HTTP/2 header decompression support" ON)
option(ENABLE_LUA "Build with Lua dissector support" ON)
option(ENABLE_SMI "Build with libsmi snmp support" ON)
option(ENABLE_GNUTLS "Build with GNU TLS support" ON)
option(ENABLE_GEOIP "Build with GeoIP support" ON)
if(WIN32)
option(ENABLE_WINSPARKLE "Enable WinSparkle support" ON)
endif()

View File

@ -43,7 +43,7 @@ bin_PROGRAMS = \
@randpkt_bin@ \
@dumpcap_bin@ \
@reordercap_bin@ \
@rawshark_bin@ \
@mmdbresolve_bin@ \
@sharkd_bin@
noinst_PROGRAMS = \
@ -52,7 +52,7 @@ noinst_PROGRAMS = \
EXTRA_PROGRAMS = wireshark-gtk wireshark tshark tfshark capinfos captype \
editcap mergecap dftest randpkt text2pcap dumpcap reordercap \
rawshark sharkd fuzzshark
mmdbresolve rawshark sharkd fuzzshark
#
# Wireshark configuration files are put in $(pkgdatadir).
@ -531,6 +531,11 @@ rawshark_LDADD = \
@PCAP_LIBS@ \
${EPAN_EXTRA_LIBS}
mmdbresolve_SOURCES = mmdbresolve.c
mmdbresolve_CPPFLAGS = $(AM_CPPFLAGS)
mmdbresolve_LDFLAGS = $(AM_LDFLAGS)
mmdbresolve_LDADD = @MAXMINDDB_LIBS@
sharkd_SOURCES = \
$(SHARK_COMMON_SRC) \
sharkd.c \

View File

@ -149,13 +149,6 @@ Newer versions don't have this problem, but still fail to build on Lion
if a universal build is attempted. The tools/macos-setup.sh script
downloads a newer version, and also suppresses the universal build.
GeoIP - Their man pages "helpfully" have an ISO 8859-1 copyright symbol
in the copyright notice, but macOS's default character encoding is
UTF-8. sed on Mountain Lion barfs at the "illegal character sequence"
represented by an ISO 8859-1 copyright symbol, as it's not a valid UTF-8
sequence. The tools/macos-setup.sh script uses iconv to convert the man
page files from ISO 8859-1 to UTF-8.
If you want to build Wireshark installer packages on a system that
doesn't include Xcode 3.x or earlier, you will need to install some
additional tools. From the Xcode menu, select the Open Developer Tool

View File

@ -1162,36 +1162,24 @@ AC_DEFUN([AC_WIRESHARK_KRB5_CHECK],
])
#
# AC_WIRESHARK_GEOIP_CHECK
# AC_WIRESHARK_MAXMINDDB_CHECK
#
AC_DEFUN([AC_WIRESHARK_GEOIP_CHECK],
AC_DEFUN([AC_WIRESHARK_MAXMINDDB_CHECK],
[
want_geoip=defaultyes
want_maxminddb=defaultyes
if test "x$want_geoip" = "xdefaultyes"; then
want_geoip=yes
if test "x$want_maxminddb" = "xdefaultyes"; then
want_maxminddb=yes
fi
if test "x$want_geoip" = "xyes"; then
AC_CHECK_LIB(GeoIP, GeoIP_new,
if test "x$want_maxminddb" = "xyes"; then
AC_CHECK_LIB(maxminddb, MMDB_open,
[
GEOIP_LIBS=-lGeoIP
AC_DEFINE(HAVE_GEOIP, 1, [Define to use GeoIP library])
have_good_geoip=yes
MAXMINDDB_LIBS=-lmaxminddb
AC_DEFINE(HAVE_MAXMINDDB, 1, [Define to use MaxMind DB library])
have_good_maxminddb=yes
],,
)
if test "x$have_good_geoip" = "xyes"; then
AC_CHECK_LIB(GeoIP, GeoIP_country_name_by_ipnum_v6,
[
AC_DEFINE(HAVE_GEOIP_V6, 1, [Define if GeoIP supports IPv6 (GeoIP 1.4.5 and later)])
],,
)
AC_CHECK_LIB(GeoIP, GeoIP_free,
[
AC_DEFINE(HAVE_GEOIP_FREE, 1, [Define if GeoIP has GeoIP_free])
],,
)
fi
else
AC_MSG_RESULT(not required)
fi

View File

@ -1,74 +0,0 @@
#
# - Find GeoIP
# Find the native GEOIP includes and library
#
# GEOIP_INCLUDE_DIRS - where to find GeoIP.h, etc.
# GEOIP_LIBRARIES - List of libraries when using GeoIP.
# GEOIP_FOUND - True if GeoIP found.
# GEOIP_DLL_DIR - (Windows) Path to the GeoIP DLL.
# GEOIP_DLL - (Windows) Name of the GeoIP DLL.
IF (GEOIP_INCLUDE_DIRS)
# Already in cache, be silent
SET(GEOIP_FIND_QUIETLY TRUE)
ENDIF (GEOIP_INCLUDE_DIRS)
INCLUDE(FindWSWinLibs)
FindWSWinLibs("GeoIP-.*" "GEOIP_HINTS")
IF (NOT WIN32)
find_package(PkgConfig)
pkg_search_module(GEOIP geoip)
endif()
FIND_PATH(GEOIP_INCLUDE_DIR GeoIP.h
HINTS
"${GEOIP_INCLUDEDIR}"
"${GEOIP_HINTS}/include"
)
SET(GEOIP_NAMES GeoIP libGeoIP-1)
FIND_LIBRARY(GEOIP_LIBRARY NAMES ${GEOIP_NAMES}
HINTS
"${GEOIP_LIBDIR}"
"${GEOIP_HINTS}/lib"
)
# handle the QUIETLY and REQUIRED arguments and set GEOIP_FOUND to TRUE if
# all listed variables are TRUE
INCLUDE(FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(GEOIP DEFAULT_MSG GEOIP_LIBRARY GEOIP_INCLUDE_DIR)
IF(GEOIP_FOUND)
INCLUDE(CMakePushCheckState)
CMAKE_PUSH_CHECK_STATE()
SET(GEOIP_LIBRARIES ${GEOIP_LIBRARY} )
SET(GEOIP_INCLUDE_DIRS ${GEOIP_INCLUDE_DIR} )
INCLUDE(CheckFunctionExists)
SET(CMAKE_REQUIRED_INCLUDES ${GEOIP_INCLUDE_DIRS})
SET(CMAKE_REQUIRED_LIBRARIES ${GEOIP_LIBRARIES})
CHECK_FUNCTION_EXISTS("GeoIP_country_name_by_ipnum_v6" HAVE_GEOIP_V6)
CHECK_FUNCTION_EXISTS("GeoIP_free" HAVE_GEOIP_FREE)
CMAKE_POP_CHECK_STATE()
if (WIN32)
set ( GEOIP_DLL_DIR "${GEOIP_HINTS}/bin"
CACHE PATH "Path to the GeoIP DLL"
)
file( GLOB _geoip_dll RELATIVE "${GEOIP_DLL_DIR}"
"${GEOIP_DLL_DIR}/libGeoIP-*.dll"
)
set ( GEOIP_DLL ${_geoip_dll}
# We're storing filenames only. Should we use STRING instead?
CACHE FILEPATH "GeoIP DLL file name"
)
mark_as_advanced( GEOIP_DLL_DIR GEOIP_DLL )
endif()
ELSE(GEOIP_FOUND)
SET(GEOIP_LIBRARIES )
SET(GEOIP_INCLUDE_DIRS )
SET(GEOIP_DLL_DIR )
SET(GEOIP_DLL )
ENDIF(GEOIP_FOUND)
MARK_AS_ADVANCED( GEOIP_LIBRARIES GEOIP_INCLUDE_DIRS )

View File

@ -0,0 +1,74 @@
#
# - Try to find libmaxminddb.
# Once done this will define
# MAXMINDDB_FOUND - System has libmaxminddb
# MAXMINDDB_INCLUDE_DIRS - The libmaxminddb include directories
# MAXMINDDB_LIBRARIES - The libraries needed to use libmaxminddb
# MAXMINDDB_DEFINITIONS - Compiler switches required for using libmaxminddb
# MAXMINDDB_DLL_DIR - (Windows) Path to the MaxMindDB DLL.
# MAXMINDDB_DLL - (Windows) Name of the MaxMindDB DLL.
IF (MAXMINDDB_INCLUDE_DIRS)
# Already in cache, be silent
SET(MAXMINDDB_FIND_QUIETLY TRUE)
ENDIF (MAXMINDDB_INCLUDE_DIRS)
INCLUDE(FindWSWinLibs)
FindWSWinLibs("MaxMindDB-.*" "MAXMINDDB_HINTS")
IF (NOT WIN32)
find_package(PkgConfig)
pkg_check_modules(PC_LIBMAXMINDDB QUIET libmaxminddb)
set(MAXMINDDB_DEFINITIONS ${PC_LIBMAXMINDDB_CFLAGS_OTHER})
endif()
FIND_PATH(MAXMINDDB_INCLUDE_DIR maxminddb.h
HINTS
${PC_LIBMAXMINDDB_INCLUDEDIR} ${PC_LIBMAXMINDDB_INCLUDE_DIRS}
PATH_SUFFIXES maxminddb
)
find_library(MAXMINDDB_LIBRARY
NAMES
maxminddb libmaxminddb
HINTS
${PC_LIBMAXMINDDB_LIBDIR} ${PC_LIBMAXMINDDB_LIBRARY_DIRS}
"${MAXMINDDB_HINTS}/lib"
)
include(FindPackageHandleStandardArgs)
# handle the QUIETLY and REQUIRED arguments and set MAXMINDDB_FOUND to TRUE
# if all listed variables are TRUE
find_package_handle_standard_args(MaxMindDB DEFAULT_MSG
MAXMINDDB_LIBRARY MAXMINDDB_INCLUDE_DIR)
IF(MAXMINDDB_FOUND)
INCLUDE(CMakePushCheckState)
CMAKE_PUSH_CHECK_STATE()
SET(MAXMINDDB_LIBRARIES ${MAXMINDDB_LIBRARY} )
SET(MAXMINDDB_INCLUDE_DIRS ${MAXMINDDB_INCLUDE_DIR} )
INCLUDE(CheckFunctionExists)
SET(CMAKE_REQUIRED_INCLUDES ${MAXMINDDB_INCLUDE_DIRS})
SET(CMAKE_REQUIRED_LIBRARIES ${MAXMINDDB_LIBRARIES})
CMAKE_POP_CHECK_STATE()
if (WIN32)
set ( MAXMINDDB_DLL_DIR "${MAXMINDDB_HINTS}/bin"
CACHE PATH "Path to the MaxMindDB DLL"
)
file( GLOB _MAXMINDDB_dll RELATIVE "${MAXMINDDB_DLL_DIR}"
"${MAXMINDDB_DLL_DIR}/libmaxminddb*.dll"
)
set ( MAXMINDDB_DLL ${_MAXMINDDB_dll}
# We're storing filenames only. Should we use STRING instead?
CACHE FILEPATH "MaxMindDB DLL file name"
)
mark_as_advanced( MAXMINDDB_DLL_DIR MAXMINDDB_DLL )
endif()
ELSE(MAXMINDDB_FOUND)
SET(MAXMINDDB_LIBRARIES )
SET(MAXMINDDB_INCLUDE_DIRS )
SET(MAXMINDDB_DLL_DIR )
SET(MAXMINDDB_DLL )
ENDIF(MAXMINDDB_FOUND)
MARK_AS_ADVANCED( MAXMINDDB_LIBRARIES MAXMINDDB_INCLUDE_DIRS )

View File

@ -62,14 +62,8 @@
/* Define to 1 if you have the <fcntl.h> header file. */
#cmakedefine HAVE_FCNTL_H 1
/* Define to use GeoIP library */
#cmakedefine HAVE_GEOIP 1
/* Define if GeoIP supports IPv6 (GeoIP 1.4.5 and later) */
#cmakedefine HAVE_GEOIP_V6 1
/* Define if GeoIP has GeoIP_free */
#cmakedefine HAVE_GEOIP_FREE 1
/* Define to use the MaxMind DB library */
#cmakedefine HAVE_MAXMINDDB 1
/* Define to 1 if you have the <ifaddrs.h> header file. */
#cmakedefine HAVE_IFADDRS_H 1

View File

@ -2183,30 +2183,40 @@ else
fi
AC_SUBST(C_ARES_LIBS)
dnl GEOIP Check
GEOIP_LIBS=''
AC_MSG_CHECKING(whether to use the GeoIP IP address mapping library if available)
dnl MaxMind DB Check
MAXMINDDB_LIBS=''
AC_MSG_CHECKING(whether to use the MaxMind DB IP address mapping library if available)
AC_ARG_WITH(geoip,
AC_HELP_STRING( [--with-geoip@<:@=DIR@:>@],
[use GeoIP (located in directory DIR, if supplied) @<:@default=yes, if present@:>@]),
AC_ARG_WITH(maxminddb,
AC_HELP_STRING( [--with-maxminddb@<:@=DIR@:>@],
[use MaxMind DB (located in directory DIR, if supplied) @<:@default=yes, if present@:>@]),
[
if test "x$withval" = "xno"; then
want_geoip=no
want_maxminddb=no
elif test "x$withval" = "xyes"; then
want_geoip=yes
want_maxminddb=yes
elif test -d "$withval"; then
want_geoip=yes
want_maxminddb=yes
AC_WIRESHARK_ADD_DASH_L(WS_LDFLAGS, ${withval}/lib)
fi
])
if test "x$want_geoip" = "xno"; then
if test "x$want_maxminddb" = "xno"; then
AC_MSG_RESULT(no)
else
AC_MSG_RESULT(yes)
AC_WIRESHARK_GEOIP_CHECK
AC_WIRESHARK_MAXMINDDB_CHECK
fi
AC_SUBST(GEOIP_LIBS)
AC_SUBST(MAXMINDDB_LIBS)
if test "x$have_good_maxminddb" = "xyes" ; then
mmdbresolve_bin="mmdbresolve\$(EXEEXT)"
mmdbresolve_man="mmdbresolve.1"
else
mmdbresolve_bin=""
mmdbresolve_man=""
fi
AC_SUBST(mmdbresolve_bin)
AC_SUBST(mmdbresolve_man)
dnl LIBSSH Check
LIBSSH=''
@ -2901,10 +2911,10 @@ else
libcap_message="no"
fi
if test "x$have_good_geoip" = "xyes" ; then
geoip_message="yes"
if test "x$have_good_maxminddb" = "xyes" ; then
maxminddb_message="yes"
else
geoip_message="no"
maxminddb_message="no"
fi
if test "x$have_good_libssh" = "xyes" ; then
@ -2969,6 +2979,7 @@ echo " Build sshdump : $enable_sshdump"
echo " Build ciscodump : $enable_ciscodump"
echo " Build randpktdump : $enable_randpktdump"
echo " Build udpdump : $enable_udpdump"
echo " Build MaxMind DB resolver : $maxminddb_message"
echo " Build User's Guide : $wsug_message"
echo ""
echo " Save files as pcapng by default : $enable_pcap_ng_default"
@ -2987,7 +2998,6 @@ echo " Use SMI MIB library : $have_libsmi"
echo " Use GNU gcrypt library : yes"
echo " Use GnuTLS library : $tls_message"
echo " Use POSIX capabilities library : $libcap_message"
echo " Use GeoIP library : $geoip_message"
echo " Use libssh library : ${libssh_message}${ssh_userauth_agent_message}"
echo " Use nl library : $libnl_message"
echo " Use SBC codec library : $have_sbc"

4
debian/control vendored
View File

@ -19,7 +19,7 @@ Build-Depends: libgtk-3-dev, lsb-release,
# enable backports-compatible libgnutls-dev
libgnutls-dev,
libgcrypt-dev, portaudio19-dev, libkrb5-dev, liblua5.2-dev, libsmi2-dev,
libgeoip-dev, dpkg-dev (>= 1.16.1~),
libmaxminddb-dev, dpkg-dev (>= 1.16.1~),
libnl-genl-3-dev [linux-any], libnl-route-3-dev [linux-any], asciidoctor,
cmake (>= 2.8.12), libsbc-dev, libnghttp2-dev, libssh-gcrypt-dev,
liblz4-dev, libsnappy-dev, libspandsp-dev, libxml2-dev
@ -198,7 +198,7 @@ Multi-Arch: foreign
Depends: ${misc:Depends}
Conflicts: wireshark-common (<< 1.4.0~rc2-1)
Replaces: wireshark-common (<< 1.4.0~rc2-1)
Recommends: geoip-database, geoip-database-extra
#Recommends: geoip-database-contrib # Only includes legacy?
Suggests: snmp-mibs-downloader
Description: network packet dissection library -- data files
The libwireshark library provides the network packet dissection services

View File

@ -1,3 +1,3 @@
usr/share/wireshark/*
etc/wireshark/init.lua
debian/geoip_db_paths /usr/share/wireshark
debian/maxmind_db_paths /usr/share/wireshark

View File

@ -699,12 +699,6 @@ libwireshark.so.0 libwireshark0 #MINVER#
gcamel_StatSRT@Base 1.9.1
gcp_cmd_type@Base 1.9.1
gcp_term_types@Base 1.9.1
geoip_db_get_paths@Base 1.9.1
geoip_db_lookup_ipv4@Base 1.9.1
geoip_db_lookup_ipv6@Base 1.9.1
geoip_db_name@Base 1.9.1
geoip_db_num_dbs@Base 1.9.1
geoip_db_type@Base 1.9.1
get_8859_1_string@Base 1.12.0~rc1
get_CDR_any@Base 1.9.1
get_CDR_boolean@Base 1.9.1
@ -902,6 +896,9 @@ libwireshark.so.0 libwireshark0 #MINVER#
make_printable_string@Base 1.9.1
manually_resolve_cleanup@Base 1.12.0~rc1
mark_frame_as_depended_upon@Base 1.9.1
maxmind_db_get_paths@Base 2.5.0
maxmind_db_lookup_ipv4@Base 2.5.0
maxmind_db_lookup_ipv6@Base 2.5.0
mbim_register_uuid_ext@Base 1.12.0~rc1
memory_usage_component_register@Base 1.12.0~rc1
memory_usage_gc@Base 1.12.0~rc1

View File

@ -57,10 +57,12 @@ else()
)
endif()
pod2manhtml(${CMAKE_CURRENT_BINARY_DIR}/wireshark 1)
pod2manhtml(${CMAKE_CURRENT_SOURCE_DIR}/androiddump 1)
pod2manhtml(${CMAKE_CURRENT_SOURCE_DIR}/udpdump 1)
pod2manhtml(${CMAKE_CURRENT_SOURCE_DIR}/capinfos 1)
pod2manhtml(${CMAKE_CURRENT_SOURCE_DIR}/captype 1)
pod2manhtml(${CMAKE_CURRENT_SOURCE_DIR}/ciscodump 1)
pod2manhtml(${CMAKE_CURRENT_SOURCE_DIR}/dftest 1)
pod2manhtml(${CMAKE_CURRENT_SOURCE_DIR}/dumpcap 1)
pod2manhtml(${CMAKE_CURRENT_SOURCE_DIR}/editcap 1)
@ -70,14 +72,17 @@ pod2manhtml(${CMAKE_CURRENT_SOURCE_DIR}/randpktdump 1)
pod2manhtml(${CMAKE_CURRENT_SOURCE_DIR}/rawshark 1)
pod2manhtml(${CMAKE_CURRENT_SOURCE_DIR}/reordercap 1)
pod2manhtml(${CMAKE_CURRENT_SOURCE_DIR}/sshdump 1)
pod2manhtml(${CMAKE_CURRENT_SOURCE_DIR}/ciscodump 1)
pod2manhtml(${CMAKE_CURRENT_SOURCE_DIR}/text2pcap 1)
pod2manhtml(${CMAKE_CURRENT_SOURCE_DIR}/tshark 1)
pod2manhtml(${CMAKE_CURRENT_BINARY_DIR}/wireshark 1)
pod2manhtml(${CMAKE_CURRENT_SOURCE_DIR}/udpdump 1)
pod2manhtml(${CMAKE_CURRENT_SOURCE_DIR}/extcap 4)
pod2manhtml(${CMAKE_CURRENT_SOURCE_DIR}/wireshark-filter 4)
if(MAXMINDDB_FOUND)
pod2manhtml(${CMAKE_CURRENT_SOURCE_DIR}/mmdbresolve 1)
endif()
if (BUILD_corbaidl2wrs)
pod2manhtml(${CMAKE_CURRENT_SOURCE_DIR}/idl2wrs 1)
endif()
@ -88,10 +93,10 @@ endif()
set(MAN1_INSTALL_FILES
${CMAKE_CURRENT_BINARY_DIR}/androiddump.1
${CMAKE_CURRENT_BINARY_DIR}/udpdump.1
${CMAKE_CURRENT_BINARY_DIR}/capinfos.1
${CMAKE_CURRENT_BINARY_DIR}/captype.1
${CMAKE_CURRENT_BINARY_DIR}/ciscodump.1
${CMAKE_CURRENT_BINARY_DIR}/ciscodump.1
${CMAKE_CURRENT_BINARY_DIR}/dftest.1
${CMAKE_CURRENT_BINARY_DIR}/dumpcap.1
${CMAKE_CURRENT_BINARY_DIR}/editcap.1
@ -101,12 +106,16 @@ set(MAN1_INSTALL_FILES
${CMAKE_CURRENT_BINARY_DIR}/rawshark.1
${CMAKE_CURRENT_BINARY_DIR}/reordercap.1
${CMAKE_CURRENT_BINARY_DIR}/sshdump.1
${CMAKE_CURRENT_BINARY_DIR}/ciscodump.1
${CMAKE_CURRENT_BINARY_DIR}/text2pcap.1
${CMAKE_CURRENT_BINARY_DIR}/tshark.1
${CMAKE_CURRENT_BINARY_DIR}/udpdump.1
${CMAKE_CURRENT_BINARY_DIR}/wireshark.1
)
if(MAXMINDDB_FOUND)
list(APPEND MAN1_INSTALL_FILES ${CMAKE_CURRENT_BINARY_DIR}/mmdbresolve.1)
endif()
if (BUILD_corbaidl2wrs)
list(APPEND MAN1_INSTALL_FILES ${CMAKE_CURRENT_BINARY_DIR}/idl2wrs.1)
endif()
@ -132,10 +141,10 @@ add_custom_target(manpages DEPENDS
set(HTML_INSTALL_FILES
${CMAKE_CURRENT_BINARY_DIR}/androiddump.html
${CMAKE_CURRENT_BINARY_DIR}/udpdump.html
${CMAKE_CURRENT_BINARY_DIR}/capinfos.html
${CMAKE_CURRENT_BINARY_DIR}/captype.html
${CMAKE_CURRENT_BINARY_DIR}/ciscodump.html
${CMAKE_CURRENT_BINARY_DIR}/ciscodump.html
${CMAKE_CURRENT_BINARY_DIR}/dftest.html
${CMAKE_CURRENT_BINARY_DIR}/dumpcap.html
${CMAKE_CURRENT_BINARY_DIR}/editcap.html
@ -146,13 +155,17 @@ set(HTML_INSTALL_FILES
${CMAKE_CURRENT_BINARY_DIR}/rawshark.html
${CMAKE_CURRENT_BINARY_DIR}/reordercap.html
${CMAKE_CURRENT_BINARY_DIR}/sshdump.html
${CMAKE_CURRENT_BINARY_DIR}/ciscodump.html
${CMAKE_CURRENT_BINARY_DIR}/text2pcap.html
${CMAKE_CURRENT_BINARY_DIR}/tshark.html
${CMAKE_CURRENT_BINARY_DIR}/wireshark.html
${CMAKE_CURRENT_BINARY_DIR}/udpdump.html
${CMAKE_CURRENT_BINARY_DIR}/wireshark-filter.html
${CMAKE_CURRENT_BINARY_DIR}/wireshark.html
)
if(MAXMINDDB_FOUND)
list(APPEND HTML_INSTALL_FILES ${CMAKE_CURRENT_BINARY_DIR}/mmdbresolve.html)
endif()
if (BUILD_corbaidl2wrs)
list(APPEND HTML_INSTALL_FILES ${CMAKE_CURRENT_BINARY_DIR}/idl2wrs.html)
endif()

View File

@ -65,7 +65,8 @@ man1_MANS = \
@ciscodump_man@ \
@sshdump_man@ \
@randpktdump_man@ \
@udpdump_man@
@udpdump_man@ \
@mmdbresolve_man@
man4_MANS = \
@extcap_man@ \
@ -81,7 +82,7 @@ pkgdata_DATA = AUTHORS-SHORT $(top_srcdir)/docbook/ws.css wireshark.html \
tshark.html wireshark-filter.html capinfos.html captype.html ciscodump.html \
editcap.html mergecap.html reordercap.html text2pcap.html dumpcap.html \
androiddump.html sshdump.html randpktdump.html rawshark.html dftest.html \
randpkt.html extcap.html udpdump.html
randpkt.html extcap.html udpdump.html mmdbresolve.html
#
# Build the short version of the authors file for the about dialog
@ -278,6 +279,13 @@ udpdump.html: udpdump.pod ../config.h $(top_srcdir)/docbook/ws.css
--noindex \
$(srcdir)/udpdump.pod > udpdump.html
mmdbresolve.html: mmdbresolve.pod ../config.h $(top_srcdir)/docbook/ws.css
$(AM_V_POD2HTML)$(POD2HTML) \
--title="mmdbresolve - The Wireshark Network Analyzer $(VERSION)" \
--css=$(POD_CSS_URL) \
--noindex \
$(srcdir)/mmdbresolve.pod > mmdbresolve.html
CLEANFILES = \
wireshark.pod \
*.1 \
@ -340,6 +348,7 @@ EXTRA_DIST = \
text2pcap.pod \
tshark.pod \
udpdump.pod \
mmdbresolve.pod \
wireshark-filter.pod \
wireshark.pod.template \
CMakeLists.txt

69
doc/mmdbresolve.pod Normal file
View File

@ -0,0 +1,69 @@
=head1 NAME
mmdbresolve - Read IPv4 and IPv6 addresses and print their IP geolocation information.
=head1 SYNOPSIS
B<mmdbresolve>
S<B<-f E<lt>dbfileE<gt>>>
S<[ B<-f E<lt>dbfileE<gt>> ]>
I<...>
=head1 DESCRIPTION
B<mmdbresolve> reads IPv4 and IPv6 addresses on stdin and prints their IP geolocation information
on stdout. Each input line must contain exactly one address. Output is in INI format, with a section
delimiter named after the query address followed by a set of "key: value" pairs. A comment
beginning with "# End" is appended to each section.
At startup an "[init]" section is printed that shows the status of each datbase and of mmdbresolve
itself.
=head1 OPTIONS
=over 4
=item -f
Path to a MaxMind Database file. Multiple databases may be specified.
=back
=head1 EXAMPLES
To resolve a single address:
echo 4.4.4.4 | mmdbresolve -f /usr/share/GeoIP/GeoLite2-City.mmdb
Example output:
[init]
db.0.path: /usr/share/GeoIP/GeoLite2-City.mmdb
db.0.status: OK
mmdbresolve.status: true
# End init
[4.4.4.4]
# GeoLite2-City
country.iso_code: US
country.names.en: United States
location.latitude: 37.751000
location.longitude: -97.822000
# End 4.4.4.4
=head1 SEE ALSO
wireshark(1), tshark(1)
=head1 NOTES
B<mmdbresolve> is part of the B<Wireshark> distribution. The latest version
of B<Wireshark> can be found at L<https://www.wireshark.org>.
HTML versions of the Wireshark project man pages are available at:
L<https://www.wireshark.org/docs/man-pages>.
=head1 AUTHORS
Original Author
---------------
Gerald Combs <gerald[AT]wireshark.org>

View File

@ -40,6 +40,8 @@ The following features are new (or have been significantly updated)
since version 2.5.0:
* HTTP Referer statistics are now supported.
* Wireshark now supports MaxMind DB files. Support for GeoIP and GeoLite
Legacy databases has been removed.
* The Windows packages are now built using Microsoft Visual Studio 2017.
* The IP map feature (the “Map” button in the “Endpoints” dialog) has been removed.

View File

@ -353,26 +353,19 @@ The PortAudio sources are downloaded from
https://anonsvn.wireshark.org/wireshark-win32-libs/trunk/packages/[] and compiled
locally.
[[ChLibsGeoIP]]
[[ChLibsMaxMindDB]]
=== GeoIP (optional)
=== MaxMindDB (optional)
MaxMind Inc. publishes a GeoIP database for use in open source software.
It can be used to map IP addresses to geographical locations.
MaxMind Inc. publishes a set of IP geolocation databases and related
open source libraries. They can be used to map IP addresses to
geographical locations and other information.
[[ChLibsUnixGeoIP]]
==== Unix
If this library isn't already installed or available as a
If libmaxminddb library isn't already installed or available as a
package for your platform, you can get it at
http://www.maxmind.com/app/c[].
https://github.com/maxmind/libmaxminddb[].
[[ChLibsWin32GeoIP]]
==== Win32 MSVC
We provide a package cross-compiled using MinGW32 at
We provide a package for Windows at
https://anonsvn.wireshark.org/wireshark-win32-libs/trunk/packages/[].
[[ChLibsWinSparkle]]

View File

@ -746,7 +746,7 @@ Configuration files stored in the Profiles:
* ESS Category Attributes (ess_category_attributes)
(<<ChEssCategoryAttributes>>)
* GeoIP Database Paths (geoip_db_paths) (<<ChGeoIPDbPaths>>)
* MaxMind Database Paths (maxmind_db_paths) (<<ChMaxMindDbPaths>>)
* K12 Protocols (k12_protos) (<<ChK12ProtocolsSection>>)
@ -876,28 +876,35 @@ The value (Label And Cert Value) representing the Category.
Name::
The textual representation for the value.
[[ChGeoIPDbPaths]]
[[ChMaxMindDbPaths]]
=== GeoIP Database Paths
=== MaxMind Database Paths
If your copy of Wireshark supports link:http://www.maxmind.com/[MaxMinds]
GeoIP library, you can use their databases to match IP addresses to countries,
cites, autonomous system numbers, ISPs, and other bits of information. Some
databases are link:http://www.maxmind.com/download/geoip/database/[available
at no cost], while others require a licensing fee. See
link:http://www.maxmind.com/app/ip-location[the MaxMind web site] for more
information.
If your copy of Wireshark supports
link:http://www.maxmind.com/[MaxMinds] MaxMindDB library, you can use
their databases to match IP addresses to countries, cites, autonomous
system numbers, and other bits of information. Some databases are
link:https://dev.maxmind.com/geoip/geoip2/downloadable/[available at no
cost], while others require a licensing fee. See
link:http://www.maxmind.com/[the MaxMind web site] for more information.
This table is handled by an <<ChUserTable>> with the following fields.
Database pathname::
This specifies a directory containing GeoIP data files. Any files beginning with
_Geo_ and ending with _.dat_ will be automatically loaded. A total of 8 files
can be loaded.
+
The locations for your data files are up to you, but `/usr/share/GeoIP` (Linux),
`C:\GeoIP` (Windows), `C:\Program Files\Wireshark\GeoIP` (Windows) might be good
choices.
This specifies a directory containing MaxMind data files. Any files
ending with _.mmdb_ will be automatically loaded.
The locations for your data files are up to you, but `/usr/share/GeoIP`
and `/var/lib/GeoIP` are common on Linux and `C:\ProgramData\GeoIP`,
`C:\Program Files\Wireshark\GeoIP` might be good choices on Windows.
[[ChGeoIPDbPaths]]
Previous versions of Wireshark supported MaxMind's original GeoIP Legacy
database format. They were configured similar to MaxMindDB files above,
except GeoIP files must begin with _Geo_ and end with _.dat_. They are
no longer supported and MaxMind stopped distributing GeoLite Legacy
databases in April 2018.
[[ChIKEv2DecryptionSection]]

View File

@ -255,11 +255,12 @@ related page can still be selected).
Each row in the list shows the statistical values for exactly one endpoint.
_Name resolution_ will be done if selected in the window and if it is active for
the specific protocol layer (MAC layer for the selected Ethernet endpoints
page). _Limit to display filter_ will only show conversations matching the
current display filter. Note that in this example we have GeoIP configured which
gives us extra geographic columns. See <<ChGeoIPDbPaths>> for more information.
_Name resolution_ will be done if selected in the window and if it is
active for the specific protocol layer (MAC layer for the selected
Ethernet endpoints page). _Limit to display filter_ will only show
conversations matching the current display filter. Note that in this
example we have MaxMind DB configured which gives us extra geographic
columns. See <<ChMaxMindDbPaths>> for more information.
The btn:[Copy] button will copy the list values to the clipboard in CSV
(Comma Separated Values) or YAML format.

View File

@ -893,9 +893,10 @@ There is a context menu (right mouse click) available. See details in
Some protocol fields have special meanings.
* *Generated fields.* Wireshark itself will generate additional protocol
information which isnt present in the captured data. This information is
enclosed in square brackets (“[” and “]”). Generated information includes
response times, TCP analysis, GeoIP information, and checksum validation.
information which isnt present in the captured data. This information
is enclosed in square brackets (“[” and “]”). Generated information
includes response times, TCP analysis, IP geolocation information, and
checksum validation.
* *Links.* If Wireshark detects a relationship to another packet in the capture
file it will generate a link to that packet. Links are underlined and

View File

@ -105,7 +105,7 @@ set(LIBWIRESHARK_PUBLIC_HEADERS
frame_data_sequence.h
funnel.h
garrayfix.h
geoip_db.h
#geoip_db.h
golay.h
guid-utils.h
iana_charsets.h
@ -117,6 +117,7 @@ set(LIBWIRESHARK_PUBLIC_HEADERS
ipv6.h
lapd_sapi.h
llcsaps.h
maxmind_db.h
media_params.h
next_tvb.h
nlpid.h
@ -208,12 +209,13 @@ set(LIBWIRESHARK_NONGENERATED_FILES
frame_data.c
frame_data_sequence.c
funnel.c
geoip_db.c
#geoip_db.c
golay.c
guid-utils.c
iana_charsets.c
in_cksum.c
ipproto.c
maxmind_db.c
media_params.c
next_tvb.c
oids.c
@ -278,8 +280,9 @@ set(epan_LIBS
wsutil
${CARES_LIBRARIES}
${GCRYPT_LIBRARIES}
${GEOIP_LIBRARIES}
#${GEOIP_LIBRARIES}
${GLIB2_LIBRARIES}
${GIO2_LIBRARIES}
${GTHREAD2_LIBRARIES}
${GNUTLS_LIBRARIES}
${KERBEROS_LIBRARIES}

View File

@ -31,8 +31,8 @@ SUBDIRS = crypt ftypes dfilter dissectors wmem $(wslua_dir)
AM_CPPFLAGS = $(INCLUDEDIRS) $(WS_CPPFLAGS) \
$(GLIB_CFLAGS) $(PCAP_CFLAGS) $(LUA_CFLAGS) $(LIBGNUTLS_CFLAGS) \
$(LIBGCRYPT_CFLAGS) $(LIBSMI_CFLAGS) $(LIBGEOIP_CFLAGS) \
$(LZ4_CFLAGS) $(KRB5_CFLAGS) $(SNAPPY_CFLAGS) $(LIBXML2_CFLAGS)
$(LIBGCRYPT_CFLAGS) $(LIBSMI_CFLAGS) $(LZ4_CFLAGS) $(KRB5_CFLAGS) \
$(SNAPPY_CFLAGS) $(LIBXML2_CFLAGS)
lib_LTLIBRARIES = libwireshark.la
@ -71,12 +71,12 @@ LIBWIRESHARK_NONGENERATED_SRC = \
frame_data.c \
frame_data_sequence.c \
funnel.c \
geoip_db.c \
golay.c \
guid-utils.c \
iana_charsets.c \
in_cksum.c \
ipproto.c \
maxmind_db.c \
media_params.c \
next_tvb.c \
oids.c \
@ -212,7 +212,6 @@ LIBWIRESHARK_INCLUDES_PUBLIC = \
frame_data_sequence.h \
funnel.h \
garrayfix.h \
geoip_db.h \
golay.h \
guid-utils.h \
iana_charsets.h \
@ -224,6 +223,7 @@ LIBWIRESHARK_INCLUDES_PUBLIC = \
ipv6.h \
lapd_sapi.h \
llcsaps.h \
maxmind_db.h \
media_params.h \
next_tvb.h \
nlpid.h \
@ -321,7 +321,6 @@ libwireshark_la_LIBADD = \
${top_builddir}/wiretap/libwiretap.la \
${top_builddir}/wsutil/libwsutil.la \
@C_ARES_LIBS@ \
@GEOIP_LIBS@ \
@KRB5_LIBS@ \
@LIBGCRYPT_LIBS@ \
@LIBGNUTLS_LIBS@ \

View File

@ -92,6 +92,7 @@
#include <epan/strutil.h>
#include <epan/to_str-int.h>
#include <epan/maxmind_db.h>
#include <epan/prefs.h>
#define ENAME_HOSTS "hosts"
@ -245,12 +246,12 @@ static void add_serv_port_cb(const guint32 port, gpointer ptr);
/* http://eternallyconfuzzled.com/tuts/algorithms/jsw_tut_hashing.aspx#existing
* One-at-a-Time hash
*/
static guint32
guint
ipv6_oat_hash(gconstpointer key)
{
int len = 16;
const unsigned char *p = (const unsigned char *)key;
guint32 h = 0;
guint h = 0;
int i;
for ( i = 0; i < len; i++ ) {
@ -266,7 +267,7 @@ ipv6_oat_hash(gconstpointer key)
return h;
}
static gboolean
gboolean
ipv6_equal(gconstpointer v1, gconstpointer v2)
{
@ -2519,6 +2520,7 @@ host_name_lookup_process(void) {
wmem_list_frame_t* head;
new_resolved_objects = FALSE;
nro |= maxmind_db_lookup_process();
if (!async_dns_initialized)
/* c-ares not initialized. Bail out and cancel timers. */
@ -2579,6 +2581,8 @@ host_name_lookup_process(void) {
new_resolved_objects = FALSE;
nro |= maxmind_db_lookup_process();
return nro;
}

View File

@ -381,6 +381,12 @@ gboolean str_to_ip(const char *str, void *dst);
WS_DLL_PUBLIC
gboolean str_to_ip6(const char *str, void *dst);
WS_DLL_LOCAL
guint ipv6_oat_hash(gconstpointer key);
WS_DLL_LOCAL
gboolean ipv6_equal(gconstpointer v1, gconstpointer v2);
#ifdef __cplusplus
}
#endif /* __cplusplus */

View File

@ -22,7 +22,7 @@ include $(top_srcdir)/Makefile.am.inc
AM_CPPFLAGS = $(INCLUDEDIRS) -I$(top_srcdir)/epan $(WS_CPPFLAGS) \
$(GLIB_CFLAGS) $(LIBGNUTLS_CFLAGS) $(LIBGCRYPT_CFLAGS) \
$(LIBGEOIP_CFLAGS) $(KRB5_CFLAGS) $(LIBXML2_CFLAGS)
$(KRB5_CFLAGS) $(LIBXML2_CFLAGS)
include Custom.common

View File

@ -18,6 +18,7 @@
#include <epan/packet.h>
#include <epan/capture_dissectors.h>
#include <epan/addr_resolv.h>
#include <epan/maxmind_db.h>
#include <epan/ipproto.h>
#include <epan/expert.h>
#include <epan/ip_opts.h>
@ -48,11 +49,6 @@
#include "packet-mpls.h"
#include "packet-nsh.h"
#ifdef HAVE_GEOIP
#include <GeoIP.h>
#include <epan/geoip_db.h>
#endif /* HAVE_GEOIP */
void proto_register_ip(void);
void proto_reg_handoff_ip(void);
@ -76,10 +72,8 @@ static gboolean ip_tso_supported = TRUE;
/* Use heuristics to determine subdissector */
static gboolean try_heuristic_first = FALSE;
#ifdef HAVE_GEOIP
/* Look up addresses in GeoIP */
/* Look up addresses via mmdbresolve */
static gboolean ip_use_geoip = TRUE;
#endif /* HAVE_GEOIP */
/* Interpret the reserved flag as security flag (RFC 3514) */
static gboolean ip_security_flag = FALSE;
@ -204,29 +198,26 @@ static int hf_ip_cipso_doi = -1;
static int hf_ip_opt_time_stamp = -1;
static int hf_ip_opt_time_stamp_addr = -1;
#ifdef HAVE_GEOIP
static int hf_geoip_country = -1;
static int hf_geoip_city = -1;
static int hf_geoip_org = -1;
static int hf_geoip_isp = -1;
static int hf_geoip_asnum = -1;
static int hf_geoip_lat = -1;
static int hf_geoip_lon = -1;
static int hf_geoip_as_number = -1;
static int hf_geoip_as_org = -1;
static int hf_geoip_latitude = -1;
static int hf_geoip_longitude = -1;
static int hf_geoip_src_summary = -1;
static int hf_geoip_src_country = -1;
static int hf_geoip_src_city = -1;
static int hf_geoip_src_org = -1;
static int hf_geoip_src_isp = -1;
static int hf_geoip_src_asnum = -1;
static int hf_geoip_src_lat = -1;
static int hf_geoip_src_lon = -1;
static int hf_geoip_src_as_number = -1;
static int hf_geoip_src_as_org = -1;
static int hf_geoip_src_latitude = -1;
static int hf_geoip_src_longitude = -1;
static int hf_geoip_dst_summary = -1;
static int hf_geoip_dst_country = -1;
static int hf_geoip_dst_city = -1;
static int hf_geoip_dst_org = -1;
static int hf_geoip_dst_isp = -1;
static int hf_geoip_dst_asnum = -1;
static int hf_geoip_dst_lat = -1;
static int hf_geoip_dst_lon = -1;
#endif /* HAVE_GEOIP */
static int hf_geoip_dst_as_number = -1;
static int hf_geoip_dst_as_org = -1;
static int hf_geoip_dst_latitude = -1;
static int hf_geoip_dst_longitude = -1;
static gint ett_ip = -1;
static gint ett_ip_dsfield = -1;
@ -271,9 +262,7 @@ static expert_field ei_ip_bogus_ip_version = EI_INIT;
static dissector_handle_t ip_handle;
static dissector_table_t ip_option_table;
#ifdef HAVE_GEOIP
static gint ett_geoip_info = -1;
#endif /* HAVE_GEOIP */
static const fragment_items ip_frag_items = {
&ett_ip_fragment,
@ -576,110 +565,93 @@ capture_ip(const guchar *pd, int offset, int len, capture_packet_info_t *cpinfo,
return try_capture_dissector("ip.proto", pd[offset + 9], pd, offset+IPH_MIN_LEN, len, cpinfo, pseudo_header);
}
#ifdef HAVE_GEOIP
static void
add_geoip_info_entry(proto_tree *geoip_info_tree, proto_item *geoip_info_item, tvbuff_t *tvb, gint offset, guint32 ip, int isdst)
add_geoip_info_entry(proto_tree *tree, tvbuff_t *tvb, gint offset, guint32 ip, int isdst)
{
guint num_dbs = geoip_db_num_dbs();
guint item_cnt = 0;
guint dbnum;
const mmdb_lookup_t *lookup = maxmind_db_lookup_ipv4(ip);
if (!lookup->found) return;
for (dbnum = 0; dbnum < num_dbs; dbnum++) {
char *geoip_str = geoip_db_lookup_ipv4(dbnum, ip, NULL);
int db_type = geoip_db_type(dbnum);
int geoip_hf, geoip_local_hf;
switch (db_type) {
case GEOIP_COUNTRY_EDITION:
geoip_hf = hf_geoip_country;
geoip_local_hf = (isdst) ? hf_geoip_dst_country : hf_geoip_src_country;
break;
case GEOIP_CITY_EDITION_REV0:
geoip_hf = hf_geoip_city;
geoip_local_hf = (isdst) ? hf_geoip_dst_city : hf_geoip_src_city;
break;
case GEOIP_CITY_EDITION_REV1:
geoip_hf = hf_geoip_city;
geoip_local_hf = (isdst) ? hf_geoip_dst_city : hf_geoip_src_city;
break;
case GEOIP_ORG_EDITION:
geoip_hf = hf_geoip_org;
geoip_local_hf = (isdst) ? hf_geoip_dst_org : hf_geoip_src_org;
break;
case GEOIP_ISP_EDITION:
geoip_hf = hf_geoip_isp;
geoip_local_hf = (isdst) ? hf_geoip_dst_isp : hf_geoip_src_isp;
break;
case GEOIP_ASNUM_EDITION:
geoip_hf = hf_geoip_asnum;
geoip_local_hf = (isdst) ? hf_geoip_dst_asnum : hf_geoip_src_asnum;
break;
case WS_LAT_FAKE_EDITION:
geoip_hf = hf_geoip_lat;
geoip_local_hf = (isdst) ? hf_geoip_dst_lat : hf_geoip_src_lat;
break;
case WS_LON_FAKE_EDITION:
geoip_hf = hf_geoip_lon;
geoip_local_hf = (isdst) ? hf_geoip_dst_lon : hf_geoip_src_lon;
break;
default:
continue;
}
if (geoip_str) {
proto_item *item;
if (db_type == WS_LAT_FAKE_EDITION || db_type == WS_LON_FAKE_EDITION) {
/* Convert latitude, longitude to double. Fix bug #5077 */
item = proto_tree_add_double_format_value(geoip_info_tree, geoip_local_hf,
tvb, offset, 4, g_ascii_strtod(geoip_str, NULL), "%s", geoip_str);
PROTO_ITEM_SET_GENERATED(item);
item = proto_tree_add_double_format_value(geoip_info_tree, geoip_hf,
tvb, offset, 4, g_ascii_strtod(geoip_str, NULL), "%s", geoip_str);
PROTO_ITEM_SET_GENERATED(item);
PROTO_ITEM_SET_HIDDEN(item);
} else {
item = proto_tree_add_string(geoip_info_tree, geoip_local_hf,
tvb, offset, 4, geoip_str);
PROTO_ITEM_SET_GENERATED(item);
item = proto_tree_add_string(geoip_info_tree, geoip_hf,
tvb, offset, 4, geoip_str);
PROTO_ITEM_SET_GENERATED(item);
PROTO_ITEM_SET_HIDDEN(item);
}
item_cnt++;
proto_item_append_text(geoip_info_item, "%s%s",
plurality(item_cnt, "", ", "), geoip_str);
wmem_free(NULL, geoip_str);
}
wmem_strbuf_t *summary = wmem_strbuf_new(wmem_packet_scope(), "");
if (lookup->city) {
wmem_strbuf_append(summary, lookup->city);
}
if (lookup->country) {
if (wmem_strbuf_get_len(summary) > 0) wmem_strbuf_append(summary, ", ");
wmem_strbuf_append(summary, lookup->country);
}
if (lookup->as_number > 0) {
if (wmem_strbuf_get_len(summary) > 0) wmem_strbuf_append(summary, ", ");
wmem_strbuf_append_printf(summary, "ASN %u", lookup->as_number);
}
if (lookup->as_org) {
if (wmem_strbuf_get_len(summary) > 0) wmem_strbuf_append(summary, ", ");
wmem_strbuf_append(summary, lookup->as_org);
}
if (item_cnt == 0)
proto_item_append_text(geoip_info_item, "Unknown");
int addr_offset = offset + isdst ? IPH_DST : IPH_SRC;
int dir_hf = isdst ? hf_geoip_dst_summary : hf_geoip_src_summary;
proto_item *geoip_info_item = proto_tree_add_string(tree, dir_hf, tvb, addr_offset, 4, wmem_strbuf_finalize(summary));
PROTO_ITEM_SET_GENERATED(geoip_info_item);
proto_tree *geoip_info_tree = proto_item_add_subtree(geoip_info_item, ett_geoip_info);
proto_item *item;
if (lookup->city) {
dir_hf = isdst ? hf_geoip_dst_city : hf_geoip_src_city;
item = proto_tree_add_string(geoip_info_tree, dir_hf, tvb, addr_offset, 4, lookup->city);
PROTO_ITEM_SET_GENERATED(item);
item = proto_tree_add_string(geoip_info_tree, hf_geoip_city, tvb, addr_offset, 4, lookup->city);
PROTO_ITEM_SET_GENERATED(item);
}
if (lookup->country) {
dir_hf = isdst ? hf_geoip_dst_country : hf_geoip_src_country;
item = proto_tree_add_string(geoip_info_tree, dir_hf, tvb, addr_offset, 4, lookup->country);
PROTO_ITEM_SET_GENERATED(item);
item = proto_tree_add_string(geoip_info_tree, hf_geoip_country, tvb, addr_offset, 4, lookup->country);
PROTO_ITEM_SET_GENERATED(item);
}
if (lookup->as_number > 0) {
dir_hf = isdst ? hf_geoip_dst_as_number : hf_geoip_src_as_number;
item = proto_tree_add_uint(geoip_info_tree, dir_hf, tvb, addr_offset, 4, lookup->as_number);
PROTO_ITEM_SET_GENERATED(item);
item = proto_tree_add_uint(geoip_info_tree, hf_geoip_as_number, tvb, addr_offset, 4, lookup->as_number);
PROTO_ITEM_SET_GENERATED(item);
}
if (lookup->as_org) {
dir_hf = isdst ? hf_geoip_dst_as_org : hf_geoip_src_as_org;
item = proto_tree_add_string(geoip_info_tree, dir_hf, tvb, addr_offset, 4, lookup->as_org);
PROTO_ITEM_SET_GENERATED(item);
item = proto_tree_add_string(geoip_info_tree, hf_geoip_as_org, tvb, addr_offset, 4, lookup->as_org);
PROTO_ITEM_SET_GENERATED(item);
}
if (lookup->latitude >= -90.0 && lookup->latitude <= 90.0) {
dir_hf = isdst ? hf_geoip_dst_latitude : hf_geoip_src_latitude;
item = proto_tree_add_double(geoip_info_tree, dir_hf, tvb, addr_offset, 4, lookup->latitude);
PROTO_ITEM_SET_GENERATED(item);
item = proto_tree_add_double(geoip_info_tree, hf_geoip_latitude, tvb, addr_offset, 4, lookup->latitude);
PROTO_ITEM_SET_GENERATED(item);
}
if (lookup->longitude >= -180.0 && lookup->longitude <= 180.0) {
dir_hf = isdst ? hf_geoip_dst_longitude : hf_geoip_src_longitude;
item = proto_tree_add_double(geoip_info_tree, dir_hf, tvb, addr_offset, 4, lookup->longitude);
PROTO_ITEM_SET_GENERATED(item);
item = proto_tree_add_double(geoip_info_tree, hf_geoip_longitude, tvb, addr_offset, 4, lookup->longitude);
PROTO_ITEM_SET_GENERATED(item);
}
}
static void
add_geoip_info(proto_tree *tree, tvbuff_t *tvb, gint offset, guint32 src32,
guint32 dst32)
{
guint num_dbs;
proto_item *geoip_info_item;
proto_tree *geoip_info_tree;
num_dbs = geoip_db_num_dbs();
if (num_dbs < 1)
return;
geoip_info_tree = proto_tree_add_subtree(tree, tvb, offset + IPH_SRC, 4, ett_geoip_info, &geoip_info_item, "Source GeoIP: ");
PROTO_ITEM_SET_GENERATED(geoip_info_item);
add_geoip_info_entry(geoip_info_tree, geoip_info_item, tvb, offset + IPH_SRC, src32, 0);
geoip_info_tree = proto_tree_add_subtree(tree, tvb, offset + IPH_DST, 4, ett_geoip_info, &geoip_info_item, "Destination GeoIP: ");
PROTO_ITEM_SET_GENERATED(geoip_info_item);
add_geoip_info_entry(geoip_info_tree, geoip_info_item, tvb, offset + IPH_DST, dst32, 1);
add_geoip_info_entry(tree, tvb, offset, g_htonl(src32), FALSE);
add_geoip_info_entry(tree, tvb, offset, g_htonl(dst32), TRUE);
}
#endif /* HAVE_GEOIP */
const value_string ipopt_type_class_vals[] = {
{(IPOPT_CONTROL & IPOPT_CLASS_MASK) >> 5, "Control"},
@ -2206,13 +2178,11 @@ dissect_ip_v4(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, void*
PROTO_ITEM_SET_GENERATED(item);
PROTO_ITEM_SET_HIDDEN(item);
}
}
#ifdef HAVE_GEOIP
if (tree && ip_use_geoip) {
add_geoip_info(ip_tree, tvb, offset, src32, dst32);
if (ip_use_geoip) {
add_geoip_info(ip_tree, tvb, offset, src32, dst32);
}
}
#endif
/* Decode IP options, if any. */
if (hlen > IPH_MIN_LEN) {
@ -2522,71 +2492,66 @@ proto_register_ip(void)
{ "Source or Destination Host", "ip.host", FT_STRING, BASE_NONE,
NULL, 0x0, NULL, HFILL }},
#ifdef HAVE_GEOIP
{ &hf_geoip_country,
{ "Source or Destination GeoIP Country", "ip.geoip.country",
FT_STRING, STR_UNICODE, NULL, 0x0, NULL, HFILL }},
{ &hf_geoip_city,
{ "Source or Destination GeoIP City", "ip.geoip.city",
FT_STRING, STR_UNICODE, NULL, 0x0, NULL, HFILL }},
{ &hf_geoip_org,
{ "Source or Destination GeoIP Organization", "ip.geoip.org",
FT_STRING, STR_UNICODE, NULL, 0x0, NULL, HFILL }},
{ &hf_geoip_isp,
{ "Source or Destination GeoIP ISP", "ip.geoip.isp",
FT_STRING, STR_UNICODE, NULL, 0x0, NULL, HFILL }},
{ &hf_geoip_asnum,
{ &hf_geoip_as_number,
{ "Source or Destination GeoIP AS Number", "ip.geoip.asnum",
FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
{ &hf_geoip_as_org,
{ "Source or Destination GeoIP AS Organization", "ip.geoip.org",
FT_STRING, STR_UNICODE, NULL, 0x0, NULL, HFILL }},
{ &hf_geoip_lat,
{ &hf_geoip_latitude,
{ "Source or Destination GeoIP Latitude", "ip.geoip.lat",
FT_DOUBLE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
{ &hf_geoip_lon,
{ &hf_geoip_longitude,
{ "Source or Destination GeoIP Longitude", "ip.geoip.lon",
FT_DOUBLE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
{ &hf_geoip_src_summary,
{ "Source GeoIP", "ip.geoip.src_summary",
FT_STRING, STR_UNICODE, NULL, 0x0, NULL, HFILL }},
{ &hf_geoip_src_country,
{ "Source GeoIP Country", "ip.geoip.src_country",
FT_STRING, STR_UNICODE, NULL, 0x0, NULL, HFILL }},
{ &hf_geoip_src_city,
{ "Source GeoIP City", "ip.geoip.src_city",
FT_STRING, STR_UNICODE, NULL, 0x0, NULL, HFILL }},
{ &hf_geoip_src_org,
{ "Source GeoIP Organization", "ip.geoip.src_org",
FT_STRING, STR_UNICODE, NULL, 0x0, NULL, HFILL }},
{ &hf_geoip_src_isp,
{ "Source GeoIP ISP", "ip.geoip.src_isp",
FT_STRING, STR_UNICODE, NULL, 0x0, NULL, HFILL }},
{ &hf_geoip_src_asnum,
{ &hf_geoip_src_as_number,
{ "Source GeoIP AS Number", "ip.geoip.src_asnum",
FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
{ &hf_geoip_src_as_org,
{ "Source GeoIP AS Organization", "ip.geoip.src_org",
FT_STRING, STR_UNICODE, NULL, 0x0, NULL, HFILL }},
{ &hf_geoip_src_lat,
{ &hf_geoip_src_latitude,
{ "Source GeoIP Latitude", "ip.geoip.src_lat",
FT_DOUBLE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
{ &hf_geoip_src_lon,
{ &hf_geoip_src_longitude,
{ "Source GeoIP Longitude", "ip.geoip.src_lon",
FT_DOUBLE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
{ &hf_geoip_dst_summary,
{ "Destination GeoIP", "ip.geoip.dst_summary",
FT_STRING, STR_UNICODE, NULL, 0x0, NULL, HFILL }},
{ &hf_geoip_dst_country,
{ "Destination GeoIP Country", "ip.geoip.dst_country",
FT_STRING, STR_UNICODE, NULL, 0x0, NULL, HFILL }},
{ &hf_geoip_dst_city,
{ "Destination GeoIP City", "ip.geoip.dst_city",
FT_STRING, STR_UNICODE, NULL, 0x0, NULL, HFILL }},
{ &hf_geoip_dst_org,
{ "Destination GeoIP Organization", "ip.geoip.dst_org",
FT_STRING, STR_UNICODE, NULL, 0x0, NULL, HFILL }},
{ &hf_geoip_dst_isp,
{ "Destination GeoIP ISP", "ip.geoip.dst_isp",
FT_STRING, STR_UNICODE, NULL, 0x0, NULL, HFILL }},
{ &hf_geoip_dst_asnum,
{ &hf_geoip_dst_as_number,
{ "Destination GeoIP AS Number", "ip.geoip.dst_asnum",
FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
{ &hf_geoip_dst_as_org,
{ "Destination GeoIP AS Organization", "ip.geoip.dst_org",
FT_STRING, STR_UNICODE, NULL, 0x0, NULL, HFILL }},
{ &hf_geoip_dst_lat,
{ &hf_geoip_dst_latitude,
{ "Destination GeoIP Latitude", "ip.geoip.dst_lat",
FT_DOUBLE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
{ &hf_geoip_dst_lon,
{ &hf_geoip_dst_longitude,
{ "Destination GeoIP Longitude", "ip.geoip.dst_lon",
FT_DOUBLE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
#endif /* HAVE_GEOIP */
{ &hf_ip_flags,
{ "Flags", "ip.flags", FT_UINT16, BASE_HEX,
@ -2906,9 +2871,7 @@ proto_register_ip(void)
&ett_ip_opt_type,
&ett_ip_opt_sec_prot_auth_flags,
&ett_ip_unknown_opt,
#ifdef HAVE_GEOIP
&ett_geoip_info
#endif
};
static ei_register_info ei[] = {
{ &ei_ip_opt_len_invalid, { "ip.opt.len.invalid", PI_PROTOCOL, PI_WARN, "Invalid length for option", EXPFILL }},
@ -2970,12 +2933,10 @@ proto_register_ip(void)
"Support packet-capture from IP TSO-enabled hardware",
"Whether to correct for TSO-enabled (TCP segmentation offload) hardware "
"captures, such as spoofing the IP packet length", &ip_tso_supported);
#ifdef HAVE_GEOIP
prefs_register_bool_preference(ip_module, "use_geoip",
"Enable GeoIP lookups",
"Whether to look up IP addresses in each GeoIP database we have loaded",
"Enable IPv4 geolocation",
"Whether to look up IP addresses in each MaxMind database we have loaded",
&ip_use_geoip);
#endif /* HAVE_GEOIP */
prefs_register_bool_preference(ip_module, "security_flag" ,
"Interpret Reserved flag as Security flag (RFC 3514)",
"Whether to interpret the originally reserved flag as security flag",

View File

@ -20,6 +20,7 @@
#include <epan/expert.h>
#include <epan/ip_opts.h>
#include <epan/addr_resolv.h>
#include <epan/maxmind_db.h>
#include <epan/prefs.h>
#include <epan/conversation_table.h>
#include <epan/dissector_filters.h>
@ -43,11 +44,6 @@
#include "packet-mpls.h"
#include "packet-nsh.h"
#ifdef HAVE_GEOIP_V6
#include <GeoIP.h>
#include <epan/geoip_db.h>
#endif /* HAVE_GEOIP_V6 */
void proto_register_ipv6(void);
void proto_reg_handoff_ipv6(void);
@ -269,29 +265,26 @@ static int hf_ipv6_routing_srh_flag_unused2 = -1;
static int hf_ipv6_routing_srh_reserved = -1;
static int hf_ipv6_routing_srh_addr = -1;
#ifdef HAVE_GEOIP_V6
static int hf_geoip_country = -1;
static int hf_geoip_city = -1;
static int hf_geoip_org = -1;
static int hf_geoip_isp = -1;
static int hf_geoip_asnum = -1;
static int hf_geoip_lat = -1;
static int hf_geoip_lon = -1;
static int hf_geoip_as_number = -1;
static int hf_geoip_as_org = -1;
static int hf_geoip_latitude = -1;
static int hf_geoip_longitude = -1;
static int hf_geoip_src_summary = -1;
static int hf_geoip_src_country = -1;
static int hf_geoip_src_city = -1;
static int hf_geoip_src_org = -1;
static int hf_geoip_src_isp = -1;
static int hf_geoip_src_asnum = -1;
static int hf_geoip_src_lat = -1;
static int hf_geoip_src_lon = -1;
static int hf_geoip_src_as_number = -1;
static int hf_geoip_src_as_org = -1;
static int hf_geoip_src_latitude = -1;
static int hf_geoip_src_longitude = -1;
static int hf_geoip_dst_summary = -1;
static int hf_geoip_dst_country = -1;
static int hf_geoip_dst_city = -1;
static int hf_geoip_dst_org = -1;
static int hf_geoip_dst_isp = -1;
static int hf_geoip_dst_asnum = -1;
static int hf_geoip_dst_lat = -1;
static int hf_geoip_dst_lon = -1;
#endif /* HAVE_GEOIP_V6 */
static int hf_geoip_dst_as_number = -1;
static int hf_geoip_dst_as_org = -1;
static int hf_geoip_dst_latitude = -1;
static int hf_geoip_dst_longitude = -1;
static gint ett_ipv6_proto = -1;
static gint ett_ipv6_traffic_class = -1;
@ -309,9 +302,7 @@ static gint ett_ipv6_fragments = -1;
static gint ett_ipv6_fragment = -1;
static gint ett_ipv6_dstopts_proto = -1;
#ifdef HAVE_GEOIP_V6
static gint ett_geoip_info = -1;
#endif /* HAVE_GEOIP_V6 */
static expert_field ei_ipv6_routing_invalid_length = EI_INIT;
static expert_field ei_ipv6_routing_invalid_segleft = EI_INIT;
@ -523,10 +514,8 @@ static gboolean ipv6_reassemble = TRUE;
/* Place IPv6 summary in proto tree */
static gboolean ipv6_summary_in_tree = TRUE;
#ifdef HAVE_GEOIP_V6
/* Look up addresses in GeoIP */
/* Look up addresses via mmdbresolve */
static gboolean ipv6_use_geoip = TRUE;
#endif /* HAVE_GEOIP_V6 */
/* Perform strict RFC adherence checking */
static gboolean g_ipv6_rpl_srh_strict_rfc_checking = FALSE;
@ -713,107 +702,92 @@ capture_ipv6_exthdr(const guchar *pd, int offset, int len, capture_packet_info_t
return try_capture_dissector("ip.proto", nxt, pd, offset, len, cpinfo, pseudo_header);
}
#ifdef HAVE_GEOIP_V6
static void
add_geoip_info_entry(proto_tree *geoip_info_tree, proto_item *geoip_info_item, tvbuff_t *tvb, gint offset, const ws_in6_addr *ip, int isdst)
add_geoip_info_entry(proto_tree *tree, tvbuff_t *tvb, gint offset, const ws_in6_addr *ip6, int isdst)
{
guint num_dbs = geoip_db_num_dbs();
guint item_cnt = 0;
guint dbnum;
const mmdb_lookup_t *lookup = maxmind_db_lookup_ipv6(ip6);
if (!lookup->found) return;
for (dbnum = 0; dbnum < num_dbs; dbnum++) {
char *geoip_str = geoip_db_lookup_ipv6(dbnum, *ip, NULL);
int db_type = geoip_db_type(dbnum);
int geoip_hf, geoip_local_hf;
switch (db_type) {
case GEOIP_COUNTRY_EDITION_V6:
geoip_hf = hf_geoip_country;
geoip_local_hf = (isdst) ? hf_geoip_dst_country : hf_geoip_src_country;
break;
#if NUM_DB_TYPES > 31
case GEOIP_CITY_EDITION_REV0_V6:
case GEOIP_CITY_EDITION_REV1_V6:
geoip_hf = hf_geoip_city;
geoip_local_hf = (isdst) ? hf_geoip_dst_city : hf_geoip_src_city;
break;
case GEOIP_ORG_EDITION_V6:
geoip_hf = hf_geoip_org;
geoip_local_hf = (isdst) ? hf_geoip_dst_org : hf_geoip_src_org;
break;
case GEOIP_ISP_EDITION_V6:
geoip_hf = hf_geoip_isp;
geoip_local_hf = (isdst) ? hf_geoip_dst_isp : hf_geoip_src_isp;
break;
case GEOIP_ASNUM_EDITION_V6:
geoip_hf = hf_geoip_asnum;
geoip_local_hf = (isdst) ? hf_geoip_dst_asnum : hf_geoip_src_asnum;
break;
#endif /* DB_NUM_TYPES */
case WS_LAT_FAKE_EDITION:
geoip_hf = hf_geoip_lat;
geoip_local_hf = (isdst) ? hf_geoip_dst_lat : hf_geoip_src_lat;
break;
case WS_LON_FAKE_EDITION:
geoip_hf = hf_geoip_lon;
geoip_local_hf = (isdst) ? hf_geoip_dst_lon : hf_geoip_src_lon;
break;
default:
continue;
}
if (geoip_str) {
proto_item *item;
if (db_type == WS_LAT_FAKE_EDITION || db_type == WS_LON_FAKE_EDITION) {
/* Convert latitude, longitude to double. Fix bug #5077 */
item = proto_tree_add_double_format_value(geoip_info_tree, geoip_local_hf, tvb,
offset, 16, g_ascii_strtod(geoip_str, NULL), "%s", geoip_str);
PROTO_ITEM_SET_GENERATED(item);
item = proto_tree_add_double_format_value(geoip_info_tree, geoip_hf, tvb,
offset, 16, g_ascii_strtod(geoip_str, NULL), "%s", geoip_str);
PROTO_ITEM_SET_GENERATED(item);
PROTO_ITEM_SET_HIDDEN(item);
} else {
item = proto_tree_add_string(geoip_info_tree, geoip_local_hf, tvb,
offset, 16, geoip_str);
PROTO_ITEM_SET_GENERATED(item);
item = proto_tree_add_string(geoip_info_tree, geoip_hf, tvb,
offset, 16, geoip_str);
PROTO_ITEM_SET_GENERATED(item);
PROTO_ITEM_SET_HIDDEN(item);
}
item_cnt++;
proto_item_append_text(geoip_info_item, "%s%s", plurality(item_cnt, "", ", "), geoip_str);
wmem_free(NULL, geoip_str);
}
wmem_strbuf_t *summary = wmem_strbuf_new(wmem_packet_scope(), "");
if (lookup->city) {
wmem_strbuf_append(summary, lookup->city);
}
if (lookup->country) {
if (wmem_strbuf_get_len(summary) > 0) wmem_strbuf_append(summary, ", ");
wmem_strbuf_append(summary, lookup->country);
}
if (lookup->as_number > 0) {
if (wmem_strbuf_get_len(summary) > 0) wmem_strbuf_append(summary, ", ");
wmem_strbuf_append_printf(summary, "ASN %u", lookup->as_number);
}
if (lookup->as_org) {
if (wmem_strbuf_get_len(summary) > 0) wmem_strbuf_append(summary, ", ");
wmem_strbuf_append(summary, lookup->as_org);
}
if (item_cnt == 0)
proto_item_append_text(geoip_info_item, "Unknown");
int addr_offset = offset + isdst ? IP6H_DST : IP6H_SRC;
int dir_hf = isdst ? hf_geoip_dst_summary : hf_geoip_src_summary;
proto_item *geoip_info_item = proto_tree_add_string(tree, dir_hf, tvb, addr_offset, 16, wmem_strbuf_finalize(summary));
PROTO_ITEM_SET_GENERATED(geoip_info_item);
proto_tree *geoip_info_tree = proto_item_add_subtree(geoip_info_item, ett_geoip_info);
proto_item *item;
if (lookup->city) {
dir_hf = isdst ? hf_geoip_dst_city : hf_geoip_src_city;
item = proto_tree_add_string(geoip_info_tree, dir_hf, tvb, addr_offset, 16, lookup->city);
PROTO_ITEM_SET_GENERATED(item);
item = proto_tree_add_string(geoip_info_tree, hf_geoip_city, tvb, addr_offset, 16, lookup->city);
PROTO_ITEM_SET_GENERATED(item);
}
if (lookup->country) {
dir_hf = isdst ? hf_geoip_dst_country : hf_geoip_src_country;
item = proto_tree_add_string(geoip_info_tree, dir_hf, tvb, addr_offset, 16, lookup->country);
PROTO_ITEM_SET_GENERATED(item);
item = proto_tree_add_string(geoip_info_tree, hf_geoip_country, tvb, addr_offset, 16, lookup->country);
PROTO_ITEM_SET_GENERATED(item);
}
if (lookup->as_number > 0) {
dir_hf = isdst ? hf_geoip_dst_as_number : hf_geoip_src_as_number;
item = proto_tree_add_uint(geoip_info_tree, dir_hf, tvb, addr_offset, 16, lookup->as_number);
PROTO_ITEM_SET_GENERATED(item);
item = proto_tree_add_uint(geoip_info_tree, hf_geoip_as_number, tvb, addr_offset, 16, lookup->as_number);
PROTO_ITEM_SET_GENERATED(item);
}
if (lookup->as_org) {
dir_hf = isdst ? hf_geoip_dst_as_org : hf_geoip_src_as_org;
item = proto_tree_add_string(geoip_info_tree, dir_hf, tvb, addr_offset, 16, lookup->as_org);
PROTO_ITEM_SET_GENERATED(item);
item = proto_tree_add_string(geoip_info_tree, hf_geoip_as_org, tvb, addr_offset, 16, lookup->as_org);
PROTO_ITEM_SET_GENERATED(item);
}
if (lookup->latitude >= -90.0 && lookup->latitude <= 90.0) {
dir_hf = isdst ? hf_geoip_dst_latitude : hf_geoip_src_latitude;
item = proto_tree_add_double(geoip_info_tree, dir_hf, tvb, addr_offset, 16, lookup->latitude);
PROTO_ITEM_SET_GENERATED(item);
item = proto_tree_add_double(geoip_info_tree, hf_geoip_latitude, tvb, addr_offset, 16, lookup->latitude);
PROTO_ITEM_SET_GENERATED(item);
}
if (lookup->longitude >= -180.0 && lookup->longitude <= 180.0) {
dir_hf = isdst ? hf_geoip_dst_longitude : hf_geoip_src_longitude;
item = proto_tree_add_double(geoip_info_tree, dir_hf, tvb, addr_offset, 16, lookup->longitude);
PROTO_ITEM_SET_GENERATED(item);
item = proto_tree_add_double(geoip_info_tree, hf_geoip_longitude, tvb, addr_offset, 16, lookup->longitude);
PROTO_ITEM_SET_GENERATED(item);
}
}
static void
add_geoip_info(proto_tree *tree, tvbuff_t *tvb, gint offset, const ws_in6_addr *src, const ws_in6_addr *dst)
{
guint num_dbs;
proto_item *geoip_info_item;
proto_tree *geoip_info_tree;
num_dbs = geoip_db_num_dbs();
if (num_dbs < 1)
return;
geoip_info_tree = proto_tree_add_subtree(tree, tvb, offset + IP6H_SRC, 16, ett_geoip_info, &geoip_info_item, "Source GeoIP: ");
PROTO_ITEM_SET_GENERATED(geoip_info_item);
add_geoip_info_entry(geoip_info_tree, geoip_info_item, tvb, offset + IP6H_SRC, src, 0);
geoip_info_tree = proto_tree_add_subtree(tree, tvb, offset + IP6H_DST, 16, ett_geoip_info, &geoip_info_item, "Destination GeoIP: ");
PROTO_ITEM_SET_GENERATED(geoip_info_item);
add_geoip_info_entry(geoip_info_tree, geoip_info_item, tvb, offset + IP6H_DST, dst, 1);
add_geoip_info_entry(tree, tvb, offset, src, FALSE);
add_geoip_info_entry(tree, tvb, offset, dst, TRUE);
}
#endif /* HAVE_GEOIP_V6 */
/* Returns TRUE if reassembled */
static gboolean
@ -2365,13 +2339,11 @@ dissect_ipv6(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_
add_ipv6_address_embed_ipv4(ipv6_tree, tvb, offset + IP6H_SRC, hf_ipv6_src_embed_ipv4);
add_ipv6_address_embed_ipv4(ipv6_tree, tvb, offset + IP6H_DST, hf_ipv6_dst_embed_ipv4);
}
#ifdef HAVE_GEOIP_V6
if (tree && ipv6_use_geoip) {
add_geoip_info(ipv6_tree, tvb, offset, ip6_src, ip6_dst);
if (ipv6_use_geoip) {
add_geoip_info(ipv6_tree, tvb, offset, ip6_src, ip6_dst);
}
}
#endif
/* Increment offset to point to next header (may be an extension header) */
offset += IPv6_HDR_SIZE;
@ -2675,7 +2647,6 @@ proto_register_ipv6(void)
"IPv4-Embedded IPv6 Address with Well-Known Prefix", HFILL }
},
#ifdef HAVE_GEOIP_V6
{ &hf_geoip_country,
{ "Source or Destination GeoIP Country", "ipv6.geoip.country",
FT_STRING, STR_UNICODE, NULL, 0x0,
@ -2686,31 +2657,31 @@ proto_register_ipv6(void)
FT_STRING, STR_UNICODE, NULL, 0x0,
NULL, HFILL }
},
{ &hf_geoip_org,
{ "Source or Destination GeoIP Organization", "ipv6.geoip.org",
FT_STRING, STR_UNICODE, NULL, 0x0,
NULL, HFILL }
},
{ &hf_geoip_isp,
{ "Source or Destination GeoIP ISP", "ipv6.geoip.isp",
FT_STRING, STR_UNICODE, NULL, 0x0,
NULL, HFILL }
},
{ &hf_geoip_asnum,
{ &hf_geoip_as_number,
{ "Source or Destination GeoIP AS Number", "ipv6.geoip.asnum",
FT_UINT32, BASE_DEC, NULL, 0x0,
NULL, HFILL }
},
{ &hf_geoip_as_org,
{ "Source or Destination GeoIP AS Organization", "ipv6.geoip.org",
FT_STRING, STR_UNICODE, NULL, 0x0,
NULL, HFILL }
},
{ &hf_geoip_lat,
{ &hf_geoip_latitude,
{ "Source or Destination GeoIP Latitude", "ipv6.geoip.lat",
FT_DOUBLE, BASE_NONE, NULL, 0x0,
NULL, HFILL }
},
{ &hf_geoip_lon,
{ &hf_geoip_longitude,
{ "Source or Destination GeoIP Longitude", "ipv6.geoip.lon",
FT_DOUBLE, BASE_NONE, NULL, 0x0,
NULL, HFILL }
},
{ &hf_geoip_src_summary,
{ "Source GeoIP", "ipv6.geoip.src_summary",
FT_STRING, STR_UNICODE, NULL, 0x0,
NULL, HFILL }
},
{ &hf_geoip_src_country,
{ "Source GeoIP Country", "ipv6.geoip.src_country",
FT_STRING, STR_UNICODE, NULL, 0x0,
@ -2721,31 +2692,31 @@ proto_register_ipv6(void)
FT_STRING, STR_UNICODE, NULL, 0x0,
NULL, HFILL }
},
{ &hf_geoip_src_org,
{ "Source GeoIP Organization", "ipv6.geoip.src_org",
FT_STRING, STR_UNICODE, NULL, 0x0,
NULL, HFILL }
},
{ &hf_geoip_src_isp,
{ "Source GeoIP ISP", "ipv6.geoip.src_isp",
FT_STRING, STR_UNICODE, NULL, 0x0,
NULL, HFILL }
},
{ &hf_geoip_src_asnum,
{ &hf_geoip_src_as_number,
{ "Source GeoIP AS Number", "ipv6.geoip.src_asnum",
FT_UINT32, BASE_DEC, NULL, 0x0,
NULL, HFILL }
},
{ &hf_geoip_src_as_org,
{ "Source GeoIP AS Organization", "ipv6.geoip.src_org",
FT_STRING, STR_UNICODE, NULL, 0x0,
NULL, HFILL }
},
{ &hf_geoip_src_lat,
{ &hf_geoip_src_latitude,
{ "Source GeoIP Latitude", "ipv6.geoip.src_lat",
FT_DOUBLE, BASE_NONE, NULL, 0x0,
NULL, HFILL }
},
{ &hf_geoip_src_lon,
{ &hf_geoip_src_longitude,
{ "Source GeoIP Longitude", "ipv6.geoip.src_lon",
FT_DOUBLE, BASE_NONE, NULL, 0x0,
NULL, HFILL }
},
{ &hf_geoip_dst_summary,
{ "Destination GeoIP", "ipv6.geoip.dst_summary",
FT_STRING, STR_UNICODE, NULL, 0x0,
NULL, HFILL }
},
{ &hf_geoip_dst_country,
{ "Destination GeoIP Country", "ipv6.geoip.dst_country",
FT_STRING, STR_UNICODE, NULL, 0x0,
@ -2756,32 +2727,26 @@ proto_register_ipv6(void)
FT_STRING, STR_UNICODE, NULL, 0x0,
NULL, HFILL }
},
{ &hf_geoip_dst_org,
{ "Destination GeoIP Organization", "ipv6.geoip.dst_org",
FT_STRING, STR_UNICODE, NULL, 0x0,
NULL, HFILL }
},
{ &hf_geoip_dst_isp,
{ "Destination GeoIP ISP", "ipv6.geoip.dst_isp",
FT_STRING, STR_UNICODE, NULL, 0x0,
NULL, HFILL }
},
{ &hf_geoip_dst_asnum,
{ &hf_geoip_dst_as_number,
{ "Destination GeoIP AS Number", "ipv6.geoip.dst_asnum",
FT_UINT32, BASE_DEC, NULL, 0x0,
NULL, HFILL }
},
{ &hf_geoip_dst_as_org,
{ "Destination GeoIP AS Organization", "ipv6.geoip.dst_org",
FT_STRING, STR_UNICODE, NULL, 0x0,
NULL, HFILL }
},
{ &hf_geoip_dst_lat,
{ &hf_geoip_dst_latitude,
{ "Destination GeoIP Latitude", "ipv6.geoip.dst_lat",
FT_DOUBLE, BASE_NONE, NULL, 0x0,
NULL, HFILL }
},
{ &hf_geoip_dst_lon,
{ &hf_geoip_dst_longitude,
{ "Destination GeoIP Longitude", "ipv6.geoip.dst_lon",
FT_DOUBLE, BASE_NONE, NULL, 0x0,
NULL, HFILL }
},
#endif /* HAVE_GEOIP_V6 */
{ &hf_ipv6_opt,
{ "IPv6 Option", "ipv6.opt",
@ -3369,9 +3334,7 @@ proto_register_ipv6(void)
static gint *ett_ipv6[] = {
&ett_ipv6_proto,
&ett_ipv6_traffic_class,
#ifdef HAVE_GEOIP_V6
&ett_geoip_info,
#endif /* HAVE_GEOIP_V6 */
&ett_ipv6_opt,
&ett_ipv6_opt_type,
&ett_ipv6_opt_rpl,
@ -3576,12 +3539,10 @@ proto_register_ipv6(void)
"Show IPv6 summary in protocol tree",
"Whether the IPv6 summary line should be shown in the protocol tree",
&ipv6_summary_in_tree);
#ifdef HAVE_GEOIP_V6
prefs_register_bool_preference(ipv6_module, "use_geoip" ,
"Enable GeoIP lookups",
"Whether to look up IPv6 addresses in each GeoIP database we have loaded",
"Enable IPv6 geolocation",
"Whether to look up IPv6 addresses in each MaxMind database we have loaded",
&ipv6_use_geoip);
#endif /* HAVE_GEOIP_V6 */
/* RPL Strict Header Checking */
prefs_register_bool_preference(ipv6_module, "perform_strict_rpl_srh_rfc_checking",

View File

@ -727,13 +727,13 @@ epan_get_compiled_version_info(GString *str)
g_string_append(str, "without Kerberos");
#endif /* HAVE_KERBEROS */
/* GeoIP */
/* MaxMindDB */
g_string_append(str, ", ");
#ifdef HAVE_GEOIP
g_string_append(str, "with GeoIP");
#ifdef HAVE_MAXMINDDB
g_string_append(str, "with MaxMind DB resolver");
#else
g_string_append(str, "without GeoIP");
#endif /* HAVE_GEOIP */
g_string_append(str, "without MaxMind DB resolver");
#endif /* HAVE_MAXMINDDB */
/* nghttp2 */
g_string_append(str, ", ");

View File

@ -1,638 +0,0 @@
/* geoip_db.c
* GeoIP database support
*
* Copyright 2008, Gerald Combs <gerald@wireshark.org>
*
* Wireshark - Network traffic analyzer
* By Gerald Combs <gerald@wireshark.org>
* Copyright 1998 Gerald Combs
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
/* To do:
* We currently return a single string for each database. Some databases,
* e.g. GeoIPCity, can return other info such as area codes.
*/
#include "config.h"
#include <glib.h>
#include <epan/wmem/wmem.h>
#ifdef HAVE_GEOIP
#include <GeoIP.h>
#include <GeoIPCity.h>
#include <epan/geoip_db.h>
#include <epan/uat.h>
#include <epan/prefs.h>
#include <epan/value_string.h>
#include <wsutil/report_message.h>
#include <wsutil/file_util.h>
/* This needs to match NUM_GEOIP_COLS in hostlist_table.h */
#define MAX_GEOIP_DBS 13
/*
* GeoIP_free is patched into our GeoIP distribution on Windows.
* See bug 13598.
*/
#ifndef HAVE_GEOIP_FREE
#define GeoIP_free free
#endif
/* Column names for each database type */
value_string geoip_type_name_vals[] = {
{ GEOIP_COUNTRY_EDITION, "Country" },
{ GEOIP_REGION_EDITION_REV0, "Region" },
{ GEOIP_CITY_EDITION_REV0, "City"},
{ GEOIP_ORG_EDITION, "Organization" },
{ GEOIP_ISP_EDITION, "ISP" },
{ GEOIP_CITY_EDITION_REV1, "City" },
{ GEOIP_REGION_EDITION_REV1, "Region" },
{ GEOIP_PROXY_EDITION, "Proxy" },
{ GEOIP_ASNUM_EDITION, "AS Number" },
{ GEOIP_NETSPEED_EDITION, "Speed" },
{ GEOIP_DOMAIN_EDITION, "Domain" },
#ifdef HAVE_GEOIP_V6
{ GEOIP_COUNTRY_EDITION_V6, "Country" },
/* This is the closest thing to a version that GeoIP.h seems to provide. */
#if NUM_DB_TYPES > 31 /* 1.4.7 */
{ GEOIP_CITY_EDITION_REV0_V6, "City"},
{ GEOIP_CITY_EDITION_REV1_V6, "City"},
{ GEOIP_ASNUM_EDITION_V6, "AS Number" },
{ GEOIP_ISP_EDITION_V6, "ISP" },
{ GEOIP_ORG_EDITION_V6, "Organization" },
{ GEOIP_DOMAIN_EDITION_V6, "Domain" },
#endif /* NUM_DB_TYPES > 31 */
#if NUM_DB_TYPES > 32 /* 1.4.8 */
{ GEOIP_NETSPEED_EDITION_REV1_V6, "Speed" },
#endif /* NUM_DB_TYPES > 32 */
#endif /* HAVE_GEOIP_V6 */
{ WS_LAT_FAKE_EDITION, "Latitude" }, /* fake database */
{ WS_LON_FAKE_EDITION, "Longitude" }, /* fake database */
{ 0, NULL }
};
static GArray *geoip_dat_arr = NULL;
/* UAT definitions. Copied from oids.c */
typedef struct _geoip_db_path_t {
char* path;
} geoip_db_path_t;
static geoip_db_path_t *geoip_db_paths = NULL;
static guint num_geoip_db_paths = 0;
static const geoip_db_path_t geoip_db_system_paths[] = {
#ifdef G_OS_UNIX
{ "/usr/share/GeoIP" },
#endif
{ NULL }
};
static uat_t *geoip_db_paths_uat = NULL;
UAT_DIRECTORYNAME_CB_DEF(geoip_mod, path, geoip_db_path_t)
/**
* Scan a directory for GeoIP databases and load them
*/
static void
geoip_dat_scan_dir(const char *dirname) {
WS_DIR *dir;
WS_DIRENT *file;
const char *name;
char *datname;
GeoIP *gi;
if ((dir = ws_dir_open(dirname, 0, NULL)) != NULL) {
while ((file = ws_dir_read_name(dir)) != NULL) {
name = ws_dir_get_name(file);
if (g_str_has_prefix(file, "Geo") && g_str_has_suffix(file, ".dat")) {
datname = g_strdup_printf("%s" G_DIR_SEPARATOR_S "%s", dirname, name);
gi = GeoIP_open(datname, GEOIP_MEMORY_CACHE);
if (gi) {
g_array_append_val(geoip_dat_arr, gi);
}
g_free(datname);
}
}
ws_dir_close (dir);
}
}
/* UAT callbacks */
static void* geoip_db_path_copy_cb(void* dest, const void* orig, size_t len _U_) {
const geoip_db_path_t *m = (const geoip_db_path_t *)orig;
geoip_db_path_t *d = (geoip_db_path_t *)dest;
d->path = g_strdup(m->path);
return d;
}
static void geoip_db_path_free_cb(void* p) {
geoip_db_path_t *m = (geoip_db_path_t *)p;
g_free(m->path);
}
static void geoip_dat_cleanup(void) {
GeoIP *gi;
guint i;
/* If we have old data, clear out the whole thing
* and start again. TODO: Just update the ones that
* have changed for efficiency's sake. */
if (geoip_dat_arr) {
/* skip the last two, as they are fake */
for (i = 0; i < geoip_db_num_dbs() - 2; i++) {
gi = g_array_index(geoip_dat_arr, GeoIP *, i);
if (gi) {
GeoIP_delete(gi);
}
}
/* don't use GeoIP_delete() on the two fake
* databases as they weren't created by GeoIP_new()
* or GeoIP_open() */
gi = g_array_index(geoip_dat_arr, GeoIP *, i);
g_free(gi);
gi = g_array_index(geoip_dat_arr, GeoIP *, i+1);
g_free(gi);
/* finally, free the array itself */
g_array_free(geoip_dat_arr, TRUE);
geoip_dat_arr = NULL;
}
}
/* called every time the user presses "Apply" or "OK in the list of
* GeoIP directories, and also once on startup */
static void geoip_db_post_update_cb(void) {
guint i;
GeoIP* gi;
geoip_dat_cleanup();
/* allocate the array */
geoip_dat_arr = g_array_new(FALSE, FALSE, sizeof(GeoIP *));
/* First try the system paths */
for (i = 0; geoip_db_system_paths[i].path != NULL; i++) {
geoip_dat_scan_dir(geoip_db_system_paths[i].path);
}
/* Walk all the directories */
for (i = 0; i < num_geoip_db_paths; i++) {
if (geoip_db_paths[i].path) {
geoip_dat_scan_dir(geoip_db_paths[i].path);
}
}
/* add fake databases for latitude and longitude
* (using "City" in reality) */
/* latitude */
gi = (GeoIP *)g_malloc(sizeof (GeoIP));
gi->databaseType = WS_LAT_FAKE_EDITION;
g_array_append_val(geoip_dat_arr, gi);
/* longitude */
gi = (GeoIP *)g_malloc(sizeof (GeoIP));
gi->databaseType = WS_LON_FAKE_EDITION;
g_array_append_val(geoip_dat_arr, gi);
}
static void geoip_db_cleanup(void)
{
geoip_dat_cleanup();
}
/**
* Initialize GeoIP lookups
*/
void
geoip_db_pref_init(module_t *nameres)
{
static uat_field_t geoip_db_paths_fields[] = {
UAT_FLD_DIRECTORYNAME(geoip_mod, path, "GeoIP Database Directory", "The GeoIP database directory path"),
UAT_END_FIELDS
};
geoip_db_paths_uat = uat_new("GeoIP Database Paths",
sizeof(geoip_db_path_t),
"geoip_db_paths",
FALSE,
(void**)&geoip_db_paths,
&num_geoip_db_paths,
/* affects dissection of packets (as the GeoIP database is
used when dissecting), but not set of named fields */
UAT_AFFECTS_DISSECTION,
"ChGeoIPDbPaths",
geoip_db_path_copy_cb,
NULL,
geoip_db_path_free_cb,
geoip_db_post_update_cb,
geoip_db_cleanup,
geoip_db_paths_fields);
prefs_register_uat_preference(nameres,
"geoip_db_paths",
"GeoIP database directories",
"Search paths for GeoIP address mapping databases."
" Wireshark will look in each directory for files beginning"
" with \"Geo\" and ending with \".dat\".",
geoip_db_paths_uat);
}
guint
geoip_db_num_dbs(void) {
return (geoip_dat_arr == NULL) ? 0 : geoip_dat_arr->len;
}
const gchar *
geoip_db_name(guint dbnum) {
GeoIP *gi;
gi = g_array_index(geoip_dat_arr, GeoIP *, dbnum);
if (gi) {
return (val_to_str_const(gi->databaseType, geoip_type_name_vals, "Unknown database"));
}
return "Invalid database";
}
int
geoip_db_type(guint dbnum) {
GeoIP *gi;
gi = g_array_index(geoip_dat_arr, GeoIP *, dbnum);
if (gi) {
return (gi->databaseType);
}
return -1;
}
static int
geoip_db_lookup_latlon4(guint32 addr, float *lat, float *lon) {
GeoIP *gi;
GeoIPRecord *gir;
guint i;
for (i = 0; i < geoip_db_num_dbs(); i++) {
gi = g_array_index(geoip_dat_arr, GeoIP *, i);
if (gi) {
switch (gi->databaseType) {
case GEOIP_CITY_EDITION_REV0:
case GEOIP_CITY_EDITION_REV1:
gir = GeoIP_record_by_ipnum(gi, addr);
if (gir) {
*lat = gir->latitude;
*lon = gir->longitude;
GeoIPRecord_delete(gir);
return 0;
}
return -1;
/*break;*/
default:
break;
}
}
}
return -1;
}
/*
* GeoIP 1.4.3 and later provide GeoIP_set_charset(), but in versions
* 1.4.3 to 1.4.6 that only applies to the City databases. I.e., it's
* possible to produce invalid UTF-8 sequences even if GeoIP_set_charset()
* is used.
*/
/* Ensure that a given db value is UTF-8 */
static char *
db_val_to_utf_8(const char *val, GeoIP *gi) {
if (GeoIP_charset(gi) == GEOIP_CHARSET_ISO_8859_1) {
char *utf8_val;
utf8_val = g_convert(val, -1, "UTF-8", "ISO-8859-1", NULL, NULL, NULL);
if (utf8_val) {
char *ret_val = wmem_strdup(NULL, utf8_val);
g_free(utf8_val);
return ret_val;
}
}
return wmem_strdup(NULL, val);
}
char *
geoip_db_lookup_ipv4(guint dbnum, guint32 addr, const char *not_found) {
GeoIP *gi;
GeoIPRecord *gir;
char *name;
const char *country;
char *val, *ret = NULL;
if (dbnum > geoip_db_num_dbs()) {
if (not_found == NULL)
return NULL;
return wmem_strdup(NULL, not_found);
}
gi = g_array_index(geoip_dat_arr, GeoIP *, dbnum);
if (gi) {
switch (gi->databaseType) {
case GEOIP_COUNTRY_EDITION:
country = GeoIP_country_name_by_ipnum(gi, addr);
if (country) {
ret = db_val_to_utf_8(country, gi);
}
break;
case GEOIP_CITY_EDITION_REV0:
case GEOIP_CITY_EDITION_REV1:
gir = GeoIP_record_by_ipnum(gi, addr);
if (gir && gir->city && gir->region) {
val = wmem_strdup_printf(NULL, "%s, %s", gir->city, gir->region);
ret = db_val_to_utf_8(val, gi);
wmem_free(NULL, val);
} else if (gir && gir->city) {
ret = db_val_to_utf_8(gir->city, gi);
}
if (gir)
GeoIPRecord_delete(gir);
break;
case GEOIP_ORG_EDITION:
case GEOIP_ISP_EDITION:
case GEOIP_ASNUM_EDITION:
name = GeoIP_name_by_ipnum(gi, addr);
if (name) {
ret = db_val_to_utf_8(name, gi);
GeoIP_free(name);
}
break;
case WS_LAT_FAKE_EDITION:
{
float lat;
float lon;
char *c;
if(geoip_db_lookup_latlon4(addr, &lat, &lon) == 0) {
val = wmem_strdup_printf(NULL, "%f", lat);
c = strchr(val, ',');
if (c != NULL) *c = '.';
ret = val;
}
}
break;
case WS_LON_FAKE_EDITION:
{
float lat;
float lon;
char *c;
if(geoip_db_lookup_latlon4(addr, &lat, &lon) == 0) {
val = wmem_strdup_printf(NULL, "%f", lon);
c = strchr(val, ',');
if (c != NULL) *c = '.';
ret = val;
}
}
break;
default:
break;
}
}
if (ret == NULL) {
if (not_found == NULL)
return NULL;
return wmem_strdup(NULL, not_found);
}
return ret;
}
#ifdef HAVE_GEOIP_V6
static int
#if NUM_DB_TYPES > 31 /* 1.4.7 */
geoip_db_lookup_latlon6(geoipv6_t addr, float *lat, float *lon) {
GeoIP *gi;
GeoIPRecord *gir;
guint i;
for (i = 0; i < geoip_db_num_dbs(); i++) {
gi = g_array_index(geoip_dat_arr, GeoIP *, i);
if (gi) {
switch (gi->databaseType) {
case GEOIP_CITY_EDITION_REV0_V6:
case GEOIP_CITY_EDITION_REV1_V6:
gir = GeoIP_record_by_ipnum_v6(gi, addr);
if(gir) {
*lat = gir->latitude;
*lon = gir->longitude;
return 0;
}
return -1;
/*break;*/
default:
break;
}
}
}
return -1;
}
#else /* NUM_DB_TYPES */
geoip_db_lookup_latlon6(geoipv6_t addr _U_, float *lat _U_, float *lon _U_) {
return -1;
}
#endif /* NUM_DB_TYPES */
char *
geoip_db_lookup_ipv6(guint dbnum, ws_in6_addr addr, const char *not_found) {
GeoIP *gi;
geoipv6_t gaddr;
char *name;
const char *country;
char *val, *ret = NULL;
#if NUM_DB_TYPES > 31
GeoIPRecord *gir;
#endif
if (dbnum > geoip_db_num_dbs()) {
if (not_found == NULL)
return NULL;
return wmem_strdup(NULL, not_found);
}
memcpy(&gaddr, &addr, sizeof(addr));
gi = g_array_index(geoip_dat_arr, GeoIP *, dbnum);
if (gi) {
switch (gi->databaseType) {
case GEOIP_COUNTRY_EDITION_V6:
country = GeoIP_country_name_by_ipnum_v6(gi, gaddr);
if (country) {
ret = db_val_to_utf_8(country, gi);
}
break;
#if NUM_DB_TYPES > 31
case GEOIP_CITY_EDITION_REV0_V6:
case GEOIP_CITY_EDITION_REV1_V6:
gir = GeoIP_record_by_ipnum_v6(gi, gaddr);
if (gir && gir->city && gir->region) {
val = wmem_strdup_printf(NULL, "%s, %s", gir->city, gir->region);
ret = db_val_to_utf_8(val, gi);
wmem_free(NULL, val);
} else if (gir && gir->city) {
ret = db_val_to_utf_8(gir->city, gi);
}
break;
case GEOIP_ORG_EDITION_V6:
case GEOIP_ISP_EDITION_V6:
case GEOIP_ASNUM_EDITION_V6:
name = GeoIP_name_by_ipnum_v6(gi, gaddr);
if (name) {
ret = db_val_to_utf_8(name, gi);
GeoIP_free(name);
}
break;
#endif /* NUM_DB_TYPES */
case WS_LAT_FAKE_EDITION:
{
float lat;
float lon;
char *c;
if(geoip_db_lookup_latlon6(gaddr, &lat, &lon) == 0) {
val = wmem_strdup_printf(NULL, "%f", lat);
c = strchr(val, ',');
if (c != NULL) *c = '.';
ret = val;
}
}
break;
case WS_LON_FAKE_EDITION:
{
float lat;
float lon;
char *c;
if(geoip_db_lookup_latlon6(gaddr, &lat, &lon) == 0) {
val = wmem_strdup_printf(NULL, "%f", lon);
c = strchr(val, ',');
if (c != NULL) *c = '.';
ret = val;
}
}
break;
default:
break;
}
}
if (ret == NULL) {
if (not_found == NULL)
return NULL;
return wmem_strdup(NULL, not_found);
}
return ret;
}
#else /* HAVE_GEOIP_V6 */
char *
geoip_db_lookup_ipv6(guint dbnum _U_, ws_in6_addr addr _U_, const char *not_found) {
if (not_found == NULL)
return NULL;
return wmem_strdup(NULL, not_found);
}
#endif /* HAVE_GEOIP_V6 */
gchar *
geoip_db_get_paths(void) {
GString* path_str = NULL;
guint i;
path_str = g_string_new("");
for (i = 0; geoip_db_system_paths[i].path != NULL; i++) {
g_string_append_printf(path_str,
"%s" G_SEARCHPATH_SEPARATOR_S, geoip_db_system_paths[i].path);
}
for (i = 0; i < num_geoip_db_paths; i++) {
if (geoip_db_paths[i].path) {
g_string_append_printf(path_str,
"%s" G_SEARCHPATH_SEPARATOR_S, geoip_db_paths[i].path);
}
}
g_string_truncate(path_str, path_str->len-1);
return g_string_free(path_str, FALSE);
}
#else /* HAVE_GEOIP */
guint
geoip_db_num_dbs(void) {
return 0;
}
const gchar *
geoip_db_name(guint dbnum _U_) {
return "Unsupported";
}
int
geoip_db_type(guint dbnum _U_) {
return -1;
}
char *
geoip_db_lookup_ipv4(guint dbnum _U_, guint32 addr _U_, const char *not_found) {
if (not_found == NULL)
return NULL;
return (char *)wmem_strdup(NULL, not_found);
}
char *
geoip_db_lookup_ipv6(guint dbnum _U_, guint32 addr _U_, const char *not_found) {
if (not_found == NULL)
return NULL;
return (char *)wmem_strdup(NULL, not_found);
}
gchar *
geoip_db_get_paths(void) {
return g_strdup("");
}
#endif /* HAVE_GEOIP */
/*
* Editor modelines
*
* Local Variables:
* c-basic-offset: 4
* tab-width: 8
* indent-tabs-mode: nil
* End:
*
* ex: set shiftwidth=4 tabstop=8 expandtab:
* :indentSize=4:tabSize=8:noTabs=true:
*/

View File

@ -1,104 +0,0 @@
/* geoip_db.h
* GeoIP database support
*
* Copyright 2008, Gerald Combs <gerald@wireshark.org>
*
* Wireshark - Network traffic analyzer
* By Gerald Combs <gerald@wireshark.org>
* Copyright 1998 Gerald Combs
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#ifndef __GEOIP_DB_H__
#define __GEOIP_DB_H__
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
#include <epan/ipv6.h>
#include <epan/prefs.h>
#include "ws_symbol_export.h"
/* Fake databases to make lat/lon values available */
/* XXX - find a better way to interface */
#define WS_LAT_FAKE_EDITION (NUM_DB_TYPES+1)
#define WS_LON_FAKE_EDITION (NUM_DB_TYPES+2)
/**
* Init function called from epan.h
*/
extern void geoip_db_pref_init(module_t *nameres);
/**
* Number of databases we have loaded
*
* @return The number GeoIP databases successfully loaded
*/
WS_DLL_PUBLIC guint geoip_db_num_dbs(void);
/**
* Fetch the name of a database
*
* @param dbnum Database index
* @return The database name or "Invalid database"
*/
WS_DLL_PUBLIC const gchar *geoip_db_name(guint dbnum);
/**
* Fetch the database type. Types are enumerated in GeoIPDBTypes in GeoIP.h.
*
* @param dbnum Database index
* @return The database type or -1
*/
WS_DLL_PUBLIC int geoip_db_type(guint dbnum);
/**
* Look up an IPv4 address in a database
*
* @param dbnum Database index
* @param addr IPv4 address to look up
* @param not_found The string to return if the lookup fails. May be NULL.
*
* @return The database entry if found, else not_found. Return value must be freed with wmem_free.
*/
WS_DLL_PUBLIC char *geoip_db_lookup_ipv4(guint dbnum, guint32 addr, const char *not_found);
/**
* Look up an IPv6 address in a database
*
* @param dbnum Database index
* @param addr IPv6 address to look up
* @param not_found The string to return if the lookup fails. May be NULL.
*
* @return The database entry if found, else not_found. Return value must be freed with wmem_free.
*/
WS_DLL_PUBLIC char *geoip_db_lookup_ipv6(guint dbnum, ws_in6_addr addr, const char *not_found);
/**
* Get all configured paths
*
* @return String with all paths separated by a path separator
*/
WS_DLL_PUBLIC gchar *geoip_db_get_paths(void);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* __GEOIP_DB_H__ */
/*
* Editor modelines
*
* Local Variables:
* c-basic-offset: 4
* tab-width: 8
* indent-tabs-mode: nil
* End:
*
* ex: set shiftwidth=4 tabstop=8 expandtab:
* :indentSize=4:tabSize=8:noTabs=true:
*/

513
epan/maxmind_db.c Normal file
View File

@ -0,0 +1,513 @@
/* maxmind_db.c
* GeoIP database support
*
* Copyright 2018, Gerald Combs <gerald@wireshark.org>
*
* Wireshark - Network traffic analyzer
* By Gerald Combs <gerald@wireshark.org>
* Copyright 1998 Gerald Combs
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#include "config.h"
#include <glib.h>
#include <epan/maxmind_db.h>
static mmdb_lookup_t mmdb_not_found;
#ifdef HAVE_MAXMINDDB
#include <fcntl.h>
#include <errno.h>
#include <epan/wmem/wmem.h>
#include <epan/addr_resolv.h>
#include <epan/uat.h>
#include <epan/prefs.h>
#include <wsutil/report_message.h>
#include <wsutil/file_util.h>
#include <wsutil/filesystem.h>
#include <wsutil/ws_pipe.h>
// To do:
// - If we can't reliably do non-blocking reads, move process_mmdbr_stdout to a worker thread.
// - Add RBL lookups? Along with the "is this a spammer" information that most RBL databases
// provide, you can also fetch AS information: http://www.team-cymru.org/IP-ASN-mapping.html
// - Switch to a different format? I was going to use g_key_file_* to parse
// the mmdbresolve output, but it was easier to just parse it directly.
// Hashes of mmdb_lookup_t
static wmem_map_t *mmdb_ipv4_map;
static wmem_map_t *mmdb_ipv6_map;
// Interned strings
static wmem_map_t *mmdb_str_chunk;
/* Child mmdbresolve process */
static char cur_addr[WS_INET6_ADDRSTRLEN];
static mmdb_lookup_t cur_lookup;
static ws_pipe_t mmdbr_pipe;
/* UAT definitions. Copied from oids.c */
typedef struct _maxmind_db_path_t {
char* path;
} maxmind_db_path_t;
static maxmind_db_path_t *maxmind_db_paths;
static guint num_maxmind_db_paths;
static const maxmind_db_path_t maxmind_db_system_paths[] = {
#ifdef _WIN32
// XXX Properly expand "%ProgramData%\GeoIP".
{ "C:\\ProgramData\\GeoIP" },
{ "C:\\GeoIP" },
#else
{ "/usr/share/GeoIP" },
{ "/var/lib/GeoIP" },
#endif
{ NULL }
};
static uat_t *maxmind_db_paths_uat;
UAT_DIRECTORYNAME_CB_DEF(maxmind_mod, path, maxmind_db_path_t)
static GPtrArray *mmdb_file_arr; // .mmdb files
#if 0
#define MMDB_DEBUG(...) { \
char *MMDB_DEBUG_MSG = g_strdup_printf(__VA_ARGS__); \
g_warning("mmdb: %s:%d %s", G_STRFUNC, __LINE__, MMDB_DEBUG_MSG); \
g_free(MMDB_DEBUG_MSG); \
}
#else
#define MMDB_DEBUG(...)
#endif
static void mmdb_resolve_stop(void);
// Hopefully scanning a few lines asynchronously has less overhead than
// reading in a child thread.
#define RES_STATUS_ERROR "mmdbresolve.status: false"
#define RES_COUNTRY_ISO_CODE "country.iso_code" // Unused.
#define RES_COUNTRY_NAMES_EN "country.names.en"
#define RES_CITY_NAMES_EN "city.names.en"
#define RES_ASN_ORG "autonomous_system_organization"
#define RES_ASN_NUMBER "autonomous_system_number"
#define RES_LOCATION_LATITUDE "location.latitude"
#define RES_LOCATION_LONGITUDE "location.longitude"
#define RES_END "# End "
// Interned strings, similar to GLib's string chunks.
static const char *chunkify_string(char *key) {
g_strstrip(key);
char *chunk_string = (char *) wmem_map_lookup(mmdb_str_chunk, key);
if (!chunk_string) {
chunk_string = wmem_strdup(wmem_epan_scope(), key);
wmem_map_insert(mmdb_str_chunk, key, chunk_string);
}
return chunk_string;
}
static gboolean
process_mmdbr_stdout(int fd) {
size_t read_buf_size = 65536;
char *read_buf = (char *) g_malloc((gsize) read_buf_size);
gboolean new_entries = FALSE;
MMDB_DEBUG("start %d", ws_pipe_data_available(fd));
while (ws_pipe_data_available(fd)) {
read_buf[0] = '\0';
ssize_t read_status = ws_read(fd, read_buf, read_buf_size);
if (read_status < 1) {
MMDB_DEBUG("read error %s", g_strerror(errno));
mmdb_resolve_stop();
break;
}
size_t read_len = strlen(read_buf);
MMDB_DEBUG("read %zd bytes", read_len);
if (read_len < 1) {
break;
}
char **lines = g_strsplit(read_buf, "\n", -1);
for (size_t idx = 0; lines[idx]; idx++) {
char *line = lines[idx];
size_t line_len = strlen(line);
char *val_start = strchr(line, ':');
if (val_start) val_start++;
if (line_len < 1) continue;
MMDB_DEBUG("line %s", line);
if (line[0] == '[') {
// [init] or resolved address in square brackets.
line[line_len - 1] = '\0';
g_strlcpy(cur_addr, line + 1, WS_INET6_ADDRSTRLEN);
memset(&cur_lookup, 0, sizeof(cur_lookup));
} else if (strcmp(line, RES_STATUS_ERROR) == 0) {
// Error during init.
cur_addr[0] = '\0';
memset(&cur_lookup, 0, sizeof(cur_lookup));
mmdb_resolve_stop();
} else if (val_start && g_str_has_prefix(line, RES_COUNTRY_NAMES_EN)) {
cur_lookup.found = TRUE;
cur_lookup.country = chunkify_string(val_start);
} else if (g_str_has_prefix(line, RES_CITY_NAMES_EN)) {
cur_lookup.found = TRUE;
cur_lookup.city = chunkify_string(val_start);
} else if (g_str_has_prefix(line, RES_ASN_ORG)) {
cur_lookup.found = TRUE;
cur_lookup.as_org = chunkify_string(val_start);
} else if (g_str_has_prefix(line, RES_ASN_NUMBER)) {
cur_lookup.found = TRUE;
cur_lookup.as_number = (unsigned int) strtoul(val_start, NULL, 10);
} else if (g_str_has_prefix(line, RES_LOCATION_LATITUDE)) {
cur_lookup.found = TRUE;
cur_lookup.latitude = strtod(val_start, NULL);
} else if (g_str_has_prefix(line, RES_LOCATION_LONGITUDE)) {
cur_lookup.found = TRUE;
cur_lookup.longitude = strtod(val_start, NULL);
} else if (g_str_has_prefix(line, RES_END)) {
if (cur_lookup.found) {
mmdb_lookup_t *mmdb_val = (mmdb_lookup_t *) wmem_memdup(wmem_epan_scope(), &cur_lookup, sizeof(cur_lookup));
if (strstr(cur_addr, ".")) {
MMDB_DEBUG("inserting v4 %p %s: city %s country %s", (void *) mmdb_val, cur_addr, mmdb_val->city, mmdb_val->country);
guint32 addr;
ws_inet_pton4(cur_addr, &addr);
wmem_map_insert(mmdb_ipv4_map, GUINT_TO_POINTER(addr), mmdb_val);
new_entries = TRUE;
} else if (strstr(cur_addr, ":")) {
MMDB_DEBUG("inserting v6 %p %s: city %s country %s", (void *) mmdb_val, cur_addr, mmdb_val->city, mmdb_val->country);
ws_in6_addr addr;
ws_inet_pton6(cur_addr, &addr);
wmem_map_insert(mmdb_ipv6_map, addr.bytes, mmdb_val);
new_entries = TRUE;
}
}
cur_addr[0] = '\0';
memset(&cur_lookup, 0, sizeof(cur_lookup));
}
}
g_strfreev(lines);
}
return new_entries;
}
/**
* Stop our mmdbresolve process.
*/
static void mmdb_resolve_stop(void) {
if (!mmdbr_pipe.pid) return;
ws_close(mmdbr_pipe.stdin_fd);
MMDB_DEBUG("closing pid %d", mmdbr_pipe.pid);
g_spawn_close_pid(mmdbr_pipe.pid);
mmdbr_pipe.pid = WS_INVALID_PID;
}
/**
* Start an mmdbresolve process.
*/
static void mmdb_resolve_start(void) {
if (!mmdb_ipv4_map) {
mmdb_ipv4_map = wmem_map_new(wmem_epan_scope(), g_direct_hash, g_direct_equal);
}
if (!mmdb_ipv6_map) {
mmdb_ipv6_map = wmem_map_new(wmem_epan_scope(), ipv6_oat_hash, ipv6_equal);
}
if (!mmdb_str_chunk) {
mmdb_str_chunk = wmem_map_new(wmem_epan_scope(), wmem_str_hash, g_str_equal);
}
if (!mmdb_file_arr) return;
mmdb_resolve_stop();
GPtrArray *args = g_ptr_array_new();
char *mmdbresolve = g_strdup_printf("%s%c%s", get_progfile_dir(), G_DIR_SEPARATOR, "mmdbresolve");
g_ptr_array_add(args, mmdbresolve);
for (guint i = 0; i < mmdb_file_arr->len; i++) {
g_ptr_array_add(args, g_strdup("-f"));
g_ptr_array_add(args, g_strdup(g_ptr_array_index(mmdb_file_arr, i)));
}
g_ptr_array_add(args, NULL);
ws_pipe_init(&mmdbr_pipe);
GPid pipe_pid = ws_pipe_spawn_async(&mmdbr_pipe, args);
MMDB_DEBUG("spawned %s pid %d", mmdbresolve, pipe_pid);
for (guint i = 0; i < args->len; i++) {
g_free(g_ptr_array_index(args, i));
}
g_ptr_array_free(args, TRUE);
if (pipe_pid == WS_INVALID_PID) {
ws_pipe_init(&mmdbr_pipe);
return;
}
// [init]
process_mmdbr_stdout(mmdbr_pipe.stdout_fd);
}
/**
* Scan a directory for GeoIP databases and load them
*/
static void
maxmind_db_scan_dir(const char *dirname) {
WS_DIR *dir;
WS_DIRENT *file;
if ((dir = ws_dir_open(dirname, 0, NULL)) != NULL) {
while ((file = ws_dir_read_name(dir)) != NULL) {
const char *name = ws_dir_get_name(file);
if (g_str_has_suffix(file, ".mmdb")) {
char *datname = g_strdup_printf("%s" G_DIR_SEPARATOR_S "%s", dirname, name);
FILE *mmdb_f = ws_fopen(datname, "r");
if (mmdb_f) {
g_ptr_array_add(mmdb_file_arr, datname);
fclose(mmdb_f);
} else {
g_free(datname);
}
}
}
ws_dir_close (dir);
}
}
/* UAT callbacks */
static void* maxmind_db_path_copy_cb(void* dest, const void* orig, size_t len _U_) {
const maxmind_db_path_t *m = (const maxmind_db_path_t *)orig;
maxmind_db_path_t *d = (maxmind_db_path_t *)dest;
d->path = g_strdup(m->path);
return d;
}
static void maxmind_db_path_free_cb(void* p) {
maxmind_db_path_t *m = (maxmind_db_path_t *)p;
g_free(m->path);
}
static void maxmind_db_cleanup(void) {
guint i;
mmdb_resolve_stop();
/* If we have old data, clear out the whole thing
* and start again. TODO: Just update the ones that
* have changed for efficiency's sake. */
if (mmdb_file_arr) {
for (i = 0; i < mmdb_file_arr->len; i++) {
g_free(g_ptr_array_index(mmdb_file_arr, i));
}
/* finally, free the array itself */
g_ptr_array_free(mmdb_file_arr, TRUE);
mmdb_file_arr = NULL;
}
}
/* called every time the user presses "Apply" or "OK in the list of
* GeoIP directories, and also once on startup */
static void maxmind_db_post_update_cb(void) {
guint i;
maxmind_db_cleanup();
/* allocate the array */
mmdb_file_arr = g_ptr_array_new();
/* First try the system paths */
for (i = 0; maxmind_db_system_paths[i].path != NULL; i++) {
maxmind_db_scan_dir(maxmind_db_system_paths[i].path);
}
/* Walk all the directories */
for (i = 0; i < num_maxmind_db_paths; i++) {
if (maxmind_db_paths[i].path) {
maxmind_db_scan_dir(maxmind_db_paths[i].path);
}
}
mmdb_resolve_start();
}
/**
* Initialize GeoIP lookups
*/
void
maxmind_db_pref_init(module_t *nameres)
{
static uat_field_t maxmind_db_paths_fields[] = {
UAT_FLD_DIRECTORYNAME(maxmind_mod, path, "MaxMind Database Directory", "The MaxMind database directory path"),
UAT_END_FIELDS
};
maxmind_db_paths_uat = uat_new("MaxMind Database Paths",
sizeof(maxmind_db_path_t),
"maxmind_db_paths",
FALSE, // Global, not per-profile
(void**)&maxmind_db_paths,
&num_maxmind_db_paths,
UAT_AFFECTS_DISSECTION, // Affects IP4 and IPv6 packets.
"ChMaxMindDbPaths",
maxmind_db_path_copy_cb,
NULL, // update_cb
maxmind_db_path_free_cb,
maxmind_db_post_update_cb,
maxmind_db_cleanup,
maxmind_db_paths_fields);
prefs_register_uat_preference(nameres,
"maxmind_db_paths",
"MaxMind database directories",
"Search paths for MaxMind address mapping databases."
" Wireshark will look in each directory for files ending"
" with \".mmdb\".",
maxmind_db_paths_uat);
}
void maxmind_db_pref_cleanup(void)
{
mmdb_resolve_stop();
}
/**
* Public API
*/
gboolean maxmind_db_lookup_process(void)
{
if (mmdbr_pipe.pid == WS_INVALID_PID) return FALSE;
return process_mmdbr_stdout(mmdbr_pipe.stdout_fd);
}
const mmdb_lookup_t *
maxmind_db_lookup_ipv4(guint32 addr) {
mmdb_lookup_t *result = (mmdb_lookup_t *) wmem_map_lookup(mmdb_ipv4_map, GUINT_TO_POINTER(addr));
if (!result) {
if (mmdbr_pipe.stdin_fd) {
char addr_str[WS_INET_ADDRSTRLEN + 1];
ws_inet_ntop4(&addr, addr_str, WS_INET_ADDRSTRLEN);
MMDB_DEBUG("looking up %s", addr_str);
g_strlcat(addr_str, "\n", (gsize) sizeof(addr_str));
ssize_t write_status = ws_write(mmdbr_pipe.stdin_fd, addr_str, strlen(addr_str));
if (write_status < 0) {
MMDB_DEBUG("write error %s", g_strerror(errno));
mmdb_resolve_stop();
}
}
result = &mmdb_not_found;
wmem_map_insert(mmdb_ipv4_map, GUINT_TO_POINTER(addr), result);
}
return result;
}
const mmdb_lookup_t *
maxmind_db_lookup_ipv6(const ws_in6_addr *addr) {
mmdb_lookup_t * result = (mmdb_lookup_t *) wmem_map_lookup(mmdb_ipv6_map, addr->bytes);
if (!result) {
if (mmdbr_pipe.stdin_fd) {
char addr_str[WS_INET6_ADDRSTRLEN + 1];
ws_inet_ntop6(addr, addr_str, WS_INET6_ADDRSTRLEN);
MMDB_DEBUG("looking up %s", addr_str);
g_strlcat(addr_str, "\n", (gsize) sizeof(addr_str));
ssize_t write_status = ws_write(mmdbr_pipe.stdin_fd, addr_str, strlen(addr_str));
if (write_status < 0) {
MMDB_DEBUG("write error %s", g_strerror(errno));
mmdb_resolve_stop();
}
}
result = &mmdb_not_found;
wmem_map_insert(mmdb_ipv6_map, addr->bytes, result);
}
return result;
}
gchar *
maxmind_db_get_paths(void) {
GString* path_str = NULL;
guint i;
path_str = g_string_new("");
for (i = 0; maxmind_db_system_paths[i].path != NULL; i++) {
g_string_append_printf(path_str,
"%s" G_SEARCHPATH_SEPARATOR_S, maxmind_db_system_paths[i].path);
}
for (i = 0; i < num_maxmind_db_paths; i++) {
if (maxmind_db_paths[i].path) {
g_string_append_printf(path_str,
"%s" G_SEARCHPATH_SEPARATOR_S, maxmind_db_paths[i].path);
}
}
g_string_truncate(path_str, path_str->len-1);
return g_string_free(path_str, FALSE);
}
#else // HAVE_MAXMINDDB
void
maxmind_db_pref_init(module_t *nameres _U_) {}
void
maxmind_db_pref_cleanup(void) {}
gboolean
maxmind_db_lookup_process(void)
{
return FALSE;
}
const mmdb_lookup_t *
maxmind_db_lookup_ipv4(guint32 addr _U_) {
return &mmdb_not_found;
}
const mmdb_lookup_t *
maxmind_db_lookup_ipv6(const ws_in6_addr *addr _U_) {
return &mmdb_not_found;
}
gchar *
maxmind_db_get_paths(void) {
return g_strdup("");
}
#endif // HAVE_MAXMINDDB
/*
* Editor modelines
*
* Local Variables:
* c-basic-offset: 4
* tab-width: 8
* indent-tabs-mode: nil
* End:
*
* ex: set shiftwidth=4 tabstop=8 expandtab:
* :indentSize=4:tabSize=8:noTabs=true:
*/

93
epan/maxmind_db.h Normal file
View File

@ -0,0 +1,93 @@
/* maxmind_db.h
* Maxmind database support
*
* Copyright 2018, Gerald Combs <gerald@wireshark.org>
*
* Wireshark - Network traffic analyzer
* By Gerald Combs <gerald@wireshark.org>
* Copyright 1998 Gerald Combs
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#ifndef __MAXMIND_DB_H__
#define __MAXMIND_DB_H__
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
#include <epan/ipv6.h>
#include <epan/prefs.h>
#include "ws_symbol_export.h"
typedef struct _mmdb_lookup_t {
gboolean found;
const char *country;
const char *city;
unsigned int as_number;
const char *as_org;
double latitude;
double longitude;
} mmdb_lookup_t;
/**
* Init function called from epan.h
*/
WS_DLL_LOCAL void maxmind_db_pref_init(module_t *nameres);
/**
* Cleanup function called from epan.h
*/
WS_DLL_LOCAL void maxmind_db_pref_cleanup(void);
/**
* Look up an IPv4 address in a database
*
* @param addr IPv4 address to look up
*
* @return The database entry if found, else NULL.
*/
WS_DLL_PUBLIC WS_RETNONNULL const mmdb_lookup_t *maxmind_db_lookup_ipv4(guint32 addr);
/**
* Look up an IPv6 address in a database
*
* @param addr IPv6 address to look up
*
* @return The database entry if found, else NULL.
*/
WS_DLL_PUBLIC WS_RETNONNULL const mmdb_lookup_t *maxmind_db_lookup_ipv6(const ws_in6_addr *addr);
/**
* Get all configured paths
*
* @return String with all paths separated by a path separator
*/
WS_DLL_PUBLIC gchar *maxmind_db_get_paths(void);
/**
* Process outstanding requests.
*
* @return True if any new addresses were resolved.
*/
WS_DLL_LOCAL gboolean maxmind_db_lookup_process(void);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* __MAXMIND_DB_H__ */
/*
* Editor modelines
*
* Local Variables:
* c-basic-offset: 4
* tab-width: 8
* indent-tabs-mode: nil
* End:
*
* ex: set shiftwidth=4 tabstop=8 expandtab:
* :indentSize=4:tabSize=8:noTabs=true:
*/

View File

@ -21,9 +21,7 @@
#include <epan/address.h>
#include <epan/addr_resolv.h>
#include <epan/oids.h>
#ifdef HAVE_GEOIP
#include <epan/geoip_db.h>
#endif
#include <epan/maxmind_db.h>
#include <epan/packet.h>
#include <epan/prefs.h>
#include <epan/proto.h>
@ -3506,9 +3504,7 @@ prefs_register_modules(void)
"Name Resolution", NULL, TRUE);
addr_resolve_pref_init(nameres_module);
oid_pref_init(nameres_module);
#ifdef HAVE_GEOIP
geoip_db_pref_init(nameres_module);
#endif
maxmind_db_pref_init(nameres_module);
/* Printing */
printing = prefs_register_module(NULL, "print", "Printing",

169
mmdbresolve.c Normal file
View File

@ -0,0 +1,169 @@
/* Read IPv4 and IPv6 addresses on stdin and print their MMDB entries on stdout.
*
* Wireshark - Network traffic analyzer
* By Gerald Combs <gerald@wireshark.org>
* Copyright 1998 Gerald Combs
*
* This progam uses the MaxMind DB library (libmaxminddb) and MUST be
* compatible with its license (Apache 2.0).
*
* SPDX-License-Identifier: MIT
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <string.h>
#include <maxminddb.h>
#define MAX_ADDR_LEN 46
#define MMDBR_STRINGIFY(x) MMDBR_STRINGIFY_S(x)
#define MMDBR_STRINGIFY_S(s) #s
#define OUT_BUF_SIZE 65536
static const char *co_iso_key[] = {"country", "iso_code", NULL};
static const char *co_name_key[] = {"country", "names", "en", NULL};
static const char *ci_name_key[] = {"city", "names", "en", NULL};
static const char *asn_o_key[] = {"autonomous_system_organization", NULL};
static const char *asn_key[] = {"autonomous_system_number", NULL};
static const char *l_lat_key[] = {"location", "latitude", NULL};
static const char *l_lon_key[] = {"location", "longitude", NULL};
static const char *empty_key[] = {NULL};
static const char **lookup_keys[] = {
co_iso_key,
co_name_key,
ci_name_key,
asn_o_key,
asn_key,
l_lat_key,
l_lon_key,
empty_key
};
static void print_usage(void) {
fprintf(stderr, "Usage: mmdbresolve -f db_file [-f db_file ...]\n");
}
int
main(int argc, char *argv[])
{
char addr_str[MAX_ADDR_LEN+1];
size_t mmdb_count = 0;
MMDB_s *mmdbs = NULL;
int mmdb_err;
int opt;
const char *optstring = "f:";
char *out_buf = (char *) malloc(OUT_BUF_SIZE);
setvbuf(stdout, out_buf, _IOFBF, OUT_BUF_SIZE);
fprintf(stdout, "[init]\n");
while ((opt = getopt(argc, argv, optstring)) != -1) {
if (opt == 'f') {
MMDB_s try_mmdb;
mmdb_err = MMDB_open(optarg, 0, &try_mmdb);
fprintf(stdout, "db.%zd.path: %s\n", mmdb_count, optarg);
fprintf(stdout, "db.%zd.status: ", mmdb_count);
if (mmdb_err == MMDB_SUCCESS) {
mmdb_count++;
mmdbs = (MMDB_s *) realloc(mmdbs, mmdb_count * sizeof(MMDB_s));
mmdbs[mmdb_count - 1] = try_mmdb;
fprintf(stdout, "OK\n");
fprintf(stdout, "db.%zd.type: %s\n", mmdb_count, mmdbs[mmdb_count - 1].metadata.database_type);
} else {
fprintf(stdout, "ERROR %s\n", MMDB_strerror(mmdb_err));
}
};
}
fprintf(stdout, "mmdbresolve.status: %s\n", mmdb_count > 0 ? "true": "false");
fprintf(stdout, "# End init\n");
fflush(stdout);
if (mmdb_count < 1) {
print_usage();
exit(1);
}
while (!feof(stdin)) {
int gai_err;
if (fscanf(stdin, "%" MMDBR_STRINGIFY(MAX_ADDR_LEN) "s", addr_str) < 1) {
continue;
}
fprintf(stdout, "[%s]\n", addr_str);
for (size_t mmdb_idx = 0; mmdb_idx < mmdb_count; mmdb_idx++) {
fprintf(stdout, "# %s\n", mmdbs[mmdb_idx].metadata.database_type);
MMDB_lookup_result_s result = MMDB_lookup_string(&mmdbs[mmdb_idx], addr_str, &gai_err, &mmdb_err);
if (result.found_entry && gai_err == 0 && mmdb_err == MMDB_SUCCESS) {
for (size_t key_idx = 0; lookup_keys[key_idx][0]; key_idx++) {
MMDB_entry_data_s entry_data;
int status = MMDB_aget_value(&result.entry, &entry_data, lookup_keys[key_idx]);
if (status == MMDB_SUCCESS && entry_data.has_data) {
char *sep = "";
for (int idx = 0; lookup_keys[key_idx][idx] != 0; idx++) {
fprintf(stdout, "%s%s", sep, lookup_keys[key_idx][idx]);
sep = ".";
}
switch (entry_data.type) {
case MMDB_DATA_TYPE_UTF8_STRING:
{
char len_fmt[12]; // : %.xxxxxs\n\0
snprintf(len_fmt, 11, ": %%.%us\n", entry_data.data_size);
fprintf(stdout, len_fmt, entry_data.utf8_string);
}
break;
case MMDB_DATA_TYPE_UINT16:
fprintf(stdout, ": %u\n", entry_data.uint16);
break;
case MMDB_DATA_TYPE_UINT32:
fprintf(stdout, ": %u\n", entry_data.uint32);
break;
case MMDB_DATA_TYPE_INT32:
fprintf(stdout, ": %d\n", entry_data.int32);
break;
case MMDB_DATA_TYPE_BOOLEAN:
fprintf(stdout, ": %s\n", entry_data.boolean ? "True" : "False");
break;
case MMDB_DATA_TYPE_DOUBLE:
fprintf(stdout, ": %f\n", entry_data.double_value);
break;
case MMDB_DATA_TYPE_FLOAT:
fprintf(stdout, ": %f\n", entry_data.float_value);
break;
default:
fprintf(stdout, ": UNKNOWN (%d)\n", entry_data.type);
}
}
}
} else {
// dump error info.
}
}
fprintf(stdout, "# End %s\n", addr_str);
fflush(stdout);
}
return 0;
}
/*
* Editor modelines - http://www.wireshark.org/tools/modelines.html
*
* Local variables:
* c-basic-offset: 4
* tab-width: 8
* indent-tabs-mode: nil
* End:
*
* vi: set shiftwidth=4 tabstop=8 expandtab:
* :indentSize=4:tabSize=8:noTabs=true:
*/

View File

@ -7,6 +7,7 @@ BINARIES="
dumpcap
editcap
mergecap
mmdbresolve
randpkt
rawshark
text2pcap

View File

@ -139,10 +139,13 @@ file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/config.nsh" "${_config_nsh_contents}")
# all-manifest.nsh. Can be created at configure time.
set(_all_manifest "${CMAKE_CURRENT_BINARY_DIR}/all-manifest.nsh")
set(_all_manifest_contents "# Files required for all sections. Generated by CMake.\n")
foreach(_dll ${GLIB2_DLLS} ${CARES_DLL} ${GCRYPT_DLLS} ${GEOIP_DLL}
foreach(_dll ${GLIB2_DLLS} ${CARES_DLL} ${GCRYPT_DLLS}
${GNUTLS_DLLS} ${KERBEROS_DLLS} ${LIBSSH_DLL} ${LUA_DLL}
${LZ4_DLL} ${NGHTTP2_DLL} ${SBC_DLL} ${SMI_DLL} ${SNAPPY_DLL}
${SPANDSP_DLL} ${BCG729_DLL} ${LIBXML2_DLL} ${WINSPARKLE_DLL} ${ZLIB_DLL}
${SPANDSP_DLL} ${BCG729_DLL} ${LIBXML2_DLL} ${WINSPARKLE_DLL}
${ZLIB_DLL}
# Needed for mmdbresolve
${MAXMINDDB_DLL}
)
set(_all_manifest_contents "${_all_manifest_contents}File \"\${STAGING_DIR}\\${_dll}\"\n")
endforeach()

View File

@ -125,22 +125,22 @@ SetShellVarContext all
!insertmacro IsWiresharkRunning
Push "${EXECUTABLE_MARKER}"
Push "androiddump"
Push "ciscodump"
Push "sshdump"
Push "udpdump"
Push "dumpcap"
Push "${PROGRAM_NAME}"
Push "tshark"
Push "qtshark"
Push "editcap"
Push "text2pcap"
Push "mergecap"
Push "randpktdump"
Push "reordercap"
Push "androiddump"
Push "capinfos"
Push "rawshark"
Push "ciscodump"
Push "dftest"
Push "dumpcap"
Push "editcap"
Push "mergecap"
Push "mmdbresolve"
Push "randpktdump"
Push "rawshark"
Push "reordercap"
Push "sshdump"
Push "text2pcap"
Push "tshark"
Push "udpdump"
Pop $EXECUTABLE
${DoUntil} $EXECUTABLE == ${EXECUTABLE_MARKER}

View File

@ -1117,6 +1117,14 @@ File "${STAGING_DIR}\rawshark.exe"
File "${STAGING_DIR}\rawshark.html"
SectionEnd
Section /o "MMDBResolve" SecMMDBResolve
;-------------------------------------------
SetOutPath $INSTDIR
File "${STAGING_DIR}\mmdbresolve.html"
SetOutPath $INSTDIR
File "${STAGING_DIR}\mmdbresolve.exe"
SectionEnd
Section /o "Androiddump" SecAndroiddumpinfos
;-------------------------------------------
SetOutPath $INSTDIR

View File

@ -252,8 +252,8 @@ Requires: libxml2
%endif
# Uncomment these if you want to be sure you get them...
#BuildRequires: GeoIP-devel
#Requires: GeoIP
#BuildRequires: libmaxminddb-devel
#Requires: libmaxminddb
# Add this for more readable fonts on some distributions/versions
#Requires: dejavu-sans-mono-fonts

View File

@ -136,10 +136,13 @@ file(APPEND "${_all_manifest_wix}" "<?include InputPaths.wxi ?>\n")
file(APPEND "${_all_manifest_wix}" " <Fragment>\n")
file(APPEND "${_all_manifest_wix}" " <DirectoryRef Id=\"INSTALLFOLDER\">\n")
SET(unique_component "")
foreach(_dll ${GLIB2_DLLS} ${CARES_DLL} ${GCRYPT_DLLS} ${GEOIP_DLL}
foreach(_dll ${GLIB2_DLLS} ${CARES_DLL} ${GCRYPT_DLLS}
${GNUTLS_DLLS} ${KERBEROS_DLLS} ${LIBSSH_DLL} ${LUA_DLL}
${LZ4_DLL} ${NGHTTP2_DLL} ${SBC_DLL} ${SMI_DLL} ${SNAPPY_DLL}
${SPANDSP_DLL} ${BCG729_DLL} ${LIBXML2_DLL} ${WINSPARKLE_DLL} ${ZLIB_DLL}
${SPANDSP_DLL} ${BCG729_DLL} ${LIBXML2_DLL} ${WINSPARKLE_DLL}
${ZLIB_DLL}
# Required for mmdbresolve
${MAXMINDDB_DLL}
)
#ensure uniqueness of files
IF(NOT "${unique_component}" MATCHES "(^|;)${_dll}(;|$)")
@ -161,10 +164,12 @@ file(APPEND "${_all_manifest_wix}" " </Fragment>\n")
file(APPEND "${_all_manifest_wix}" " <Fragment>\n")
file(APPEND "${_all_manifest_wix}" " <ComponentGroup Id=\"CG.RequiredDependencies\">\n")
SET(unique_file "")
foreach(_dll ${GLIB2_DLLS} ${CARES_DLL} ${GCRYPT_DLLS} ${GEOIP_DLL}
foreach(_dll ${GLIB2_DLLS} ${CARES_DLL} ${GCRYPT_DLLS} ${ZLIB_DLL}
${GNUTLS_DLLS} ${KERBEROS_DLLS} ${LIBSSH_DLL} ${LUA_DLL}
${LZ4_DLL} ${NGHTTP2_DLL} ${SBC_DLL} ${SMI_DLL} ${SNAPPY_DLL}
${SPANDSP_DLL} ${BCG729_DLL} ${LIBXML2_DLL} ${WINSPARKLE_DLL} ${ZLIB_DLL}
${SPANDSP_DLL} ${BCG729_DLL} ${LIBXML2_DLL} ${WINSPARKLE_DLL}
# mmdbresolve
${MAXMINDDB_DLL}
)
#ensure uniqueness of files
IF(NOT "${unique_file}" MATCHES "(^|;)${_dll}(;|$)")

View File

@ -433,6 +433,24 @@
</ComponentGroup>
</Fragment>
<!-- MMDBResolve -->
<Fragment>
<DirectoryRef Id="INSTALLFOLDER">
<Component Id="cmpMmdbresolve_exe" Guid="*">
<File Id="filMmdbresolve_exe" KeyPath="yes" Source="$(var.Staging.Dir)\mmdbresolve.exe" />
</Component>
<Component Id="cmpMmdbresolve_html" Guid="*">
<File Id="filMmdbresolve_html" KeyPath="yes" Source="$(var.Staging.Dir)\rawshark.html" />
</Component>
</DirectoryRef>
</Fragment>
<Fragment>
<ComponentGroup Id="CG.Tools.MMDBResolve">
<ComponentRef Id="cmpMmdbresolve_exe" />
<ComponentRef Id="cmpMmdbresolve_html" />
</ComponentGroup>
</Fragment>
<!-- Androiddump -->
<Fragment>
<DirectoryRef Id="dirExtcap">

View File

@ -81,6 +81,9 @@
<Feature Id="Fe.Tools.Rawshark" Title="Rawshark" Level="1" AllowAdvertise="yes" Display="expand" Description="Raw packet filter.">
<ComponentGroupRef Id="CG.Tools.Rawshark" />
</Feature>
<Feature Id="Fe.Tools.MMDBResolve" Title="MMDBResolve" Level="1" AllowAdvertise="yes" Display="expand" Description="IP geolocation database resolution.">
<ComponentGroupRef Id="CG.Tools.MMDBResolve" />
</Feature>
<Feature Id="Fe.Tools.Androiddump" Title="Androiddump" Level="2" AllowAdvertise="yes" Display="expand" Description="Provide capture interfaces from Android devices.">
<ComponentGroupRef Id="CG.Tools.Androiddump" />
</Feature>

View File

@ -88,7 +88,6 @@ $SoftBins = (
"libgcrypt-20.dll",
"libgdk-win32-2.0-0.dll",
"libgdk_pixbuf-2.0-0.dll",
"libGeoIP-1.dll",
"libgio-2.0-0.dll",
"libglib-2.0-0.dll",
"libgmodule-2.0-0.dll",
@ -103,6 +102,7 @@ $SoftBins = (
"libjasper-1.dll",
"libjpeg-8.dll",
"liblzma-5.dll",
"libmaxminddb.dll",
"libnettle-4-6.dll",
"libp11-kit-0.dll",
"libpango-1.0-0.dll",

View File

@ -55,7 +55,7 @@ BASIC_LIST="libgtk2.0-dev libpcap-dev bison flex make automake \
ADDITIONAL_LIST="libnl-3-dev qttools5-dev qttools5-dev-tools libgtk-3-dev \
libc-ares-dev libkrb5-dev libqt5svg5-dev libsmi2-dev \
portaudio19-dev asciidoctor libsbc-dev libgeoip-dev \
portaudio19-dev asciidoctor libsbc-dev \
qtmultimedia5-dev liblua5.2-dev libnl-cli-3-dev \
libparse-yapp-perl qt5-default cmake libcap-dev \
liblz4-dev libsnappy-dev libspandsp-dev libxml2-dev \
@ -92,6 +92,10 @@ add_package ADDITIONAL_LIST libgnutls28-dev ||
add_package ADDITIONAL_LIST libgnutls-dev ||
echo "libgnutls28-dev and libgnutls-dev are unavailable" >&2
# mmdbresolve
add_package ADDITIONAL_LIST libmaxminddb-dev ||
echo "libmaxminddb-dev is unavailable" >&2
ACTUAL_LIST=$BASIC_LIST
# Now arrange for optional support libraries

View File

@ -45,7 +45,6 @@ then
NGHTTP2="nghttp2"
# SUSE doesn't split the pod2* commands into a separate package like RH
PERLPODS=""
GEOIP="libGeoIP-devel"
GNUTLS="libgnutls-devel"
GETTEXT="gettext-tools"
QT5="libqt5-linguist-devel libqt5-qtsvg-devel libqt5-qtmultimedia-devel
@ -76,10 +75,11 @@ else
CARES="c-ares-devel c-ares"
NGHTTP2="libnghttp2"
PERLPODS="perl-podlators"
GEOIP="GeoIP-devel"
GNUTLS="gnutls-devel"
GETTEXT="gettext-devel"
QT5="qt5-linguist qt5-qtsvg-devel"
# mmdbresolve
MAXMINDDB="libmaxminddb-devel"
fi
PKGS="autoconf automake libtool gcc flex bison python perl $GLIB2
@ -87,7 +87,7 @@ $PCAP $ZLIB lua-devel lua $CARES $GTK3 $GTK2 desktop-file-utils $QT fop
asciidoc git git-review $PERLPODS"
PKGS_OPT="libnl3-devel libnghttp2-devel $NGHTTP2 $SNAPPY $LZ4 libcap $CAP_PROGS
libcap-devel $GEOIP libgcrypt-devel $GNUTLS $GETTEXT libssh-devel
libcap-devel $MAXMINDDB libgcrypt-devel $GNUTLS $GETTEXT libssh-devel
krb5-devel perl-Parse-Yapp sbc-devel libsmi-devel $POD2HTML $QT5 asciidoctor"
echo "Run this command (as root):"

View File

@ -155,12 +155,13 @@ SNAPPY_VERSION=1.1.4
LIBXML2_VERSION=2.9.4
LZ4_VERSION=1.7.5
SBC_VERSION=1.3
GEOIP_VERSION=1.6.10
CARES_VERSION=1.12.0
# Redmine used by libssh.org numbers the files available for download,
# so using version only isn't enough
LIBSSH_VERSION=0.7.4
LIBSSH_FILENUM=210
# mmdbresolve
MAXMINDDB_VERSION=1.3.2
NGHTTP2_VERSION=1.21.0
SPANDSP_VERSION=0.0.6
@ -1687,67 +1688,42 @@ uninstall_sbc() {
fi
}
install_geoip() {
if [ "$GEOIP_VERSION" -a ! -f geoip-$GEOIP_VERSION-done ] ; then
echo "Downloading, building, and installing GeoIP API:"
GEOIP_MAJOR_VERSION="`expr $GEOIP_VERSION : '\([0-9][0-9]*\).*'`"
GEOIP_MINOR_VERSION="`expr $GEOIP_VERSION : '[0-9][0-9]*\.\([0-9][0-9]*\).*'`"
GEOIP_DOTDOT_VERSION="`expr $GEOIP_VERSION : '[0-9][0-9]*\.[0-9][0-9]*\.\([0-9][0-9]*\).*'`"
if [[ $GEOIP_MAJOR_VERSION -gt 1 ||
($GEOIP_MAJOR_VERSION -eq 1 && $GEOIP_MINOR_VERSION -gt 6) ||
($GEOIP_MAJOR_VERSION -eq 1 && $GEOIP_MINOR_VERSION -eq 6 && $GEOIP_DOTDOT_VERSION -ge 1) ]]
then
#
# Starting with GeoIP 1.6.1, the tarballs are on GitHub.
#
[ -f GeoIP-$GEOIP_VERSION.tar.gz ] || curl -L -O https://github.com/maxmind/geoip-api-c/releases/download/v$GEOIP_VERSION/GeoIP-$GEOIP_VERSION.tar.gz || exit 1
else
[ -f GeoIP-$GEOIP_VERSION.tar.gz ] || curl -L -O http://geolite.maxmind.com/download/geoip/api/c/GeoIP-$GEOIP_VERSION.tar.gz || exit 1
fi
install_maxminddb() {
if [ "$MAXMINDDB_VERSION" -a ! -f maxminddb-$MAXMINDDB_VERSION-done ] ; then
echo "Downloading, building, and installing MaxMindDB API:"
MAXMINDDB_MAJOR_VERSION="`expr $MAXMINDDB_VERSION : '\([0-9][0-9]*\).*'`"
MAXMINDDB_MINOR_VERSION="`expr $MAXMINDDB_VERSION : '[0-9][0-9]*\.\([0-9][0-9]*\).*'`"
MAXMINDDB_DOTDOT_VERSION="`expr $MAXMINDDB_VERSION : '[0-9][0-9]*\.[0-9][0-9]*\.\([0-9][0-9]*\).*'`"
[ -f libmaxminddb-$MAXMINDDB_VERSION.tar.gz ] || curl -L -O https://github.com/maxmind/libmaxminddb/releases/download/$MAXMINDDB_VERSION/libmaxminddb-$MAXMINDDB_VERSION.tar.gz || exit 1
$no_build && echo "Skipping installation" && return
gzcat GeoIP-$GEOIP_VERSION.tar.gz | tar xf - || exit 1
cd GeoIP-$GEOIP_VERSION
gzcat libmaxminddb-$MAXMINDDB_VERSION.tar.gz | tar xf - || exit 1
cd libmaxminddb-$MAXMINDDB_VERSION
CFLAGS="$CFLAGS $VERSION_MIN_FLAGS $SDKFLAGS" CXXFLAGS="$CXXFLAGS $VERSION_MIN_FLAGS $SDKFLAGS" LDFLAGS="$LDFLAGS $VERSION_MIN_FLAGS $SDKFLAGS" ./configure || exit 1
#
# Grr. Their man pages "helpfully" have an ISO 8859-1
# copyright symbol in the copyright notice, but macOS's
# default character encoding is UTF-8. sed on Mountain
# Lion barfs at the "illegal character sequence" represented
# by an ISO 8859-1 copyright symbol, as it's not a valid
# UTF-8 sequence.
#
# iconv the relevant man pages into UTF-8.
#
for i in geoipupdate.1.in geoiplookup6.1.in geoiplookup.1.in
do
iconv -f iso8859-1 -t utf-8 man/"$i" >man/"$i".tmp &&
mv man/"$i".tmp man/"$i"
done
make $MAKE_BUILD_OPTS || exit 1
$DO_MAKE_INSTALL || exit 1
cd ..
touch geoip-$GEOIP_VERSION-done
touch maxminddb-$MAXMINDDB_VERSION-done
fi
}
uninstall_geoip() {
if [ ! -z "$installed_geoip_version" ] ; then
echo "Uninstalling GeoIP API:"
cd GeoIP-$installed_geoip_version
uninstall_maxminddb() {
if [ ! -z "$installed_maxminddb_version" ] ; then
echo "Uninstalling MaxMindDB API:"
cd libmaxminddb-$installed_maxminddb_version
$DO_MAKE_UNINSTALL || exit 1
make distclean || exit 1
cd ..
rm geoip-$installed_geoip_version-done
rm maxminddb-$installed_maxminddb_version-done
if [ "$#" -eq 1 -a "$1" = "-r" ] ; then
#
# Get rid of the previously downloaded and unpacked version.
#
rm -rf GeoIP-$installed_geoip_version
rm -rf GeoIP-$installed_geoip_version.tar.gz
rm -rf libmaxminddb-$installed_maxminddb_version
rm -rf libmaxminddb-$installed_maxminddb_version.tar.gz
fi
installed_geoip_version=""
installed_maxminddb_version=""
fi
}
@ -2056,15 +2032,15 @@ install_all() {
uninstall_c_ares -r
fi
if [ ! -z "$installed_geoip_version" -a \
"$installed_geoip_version" != "$GEOIP_VERSION" ] ; then
echo "Installed GeoIP API version is $installed_geoip_version"
if [ -z "$GEOIP_VERSION" ] ; then
echo "GeoIP is not requested"
if [ ! -z "$installed_maxminddb_version" -a \
"$installed_maxminddb_version" != "$MAXMINDDB_VERSION" ] ; then
echo "Installed MaxMindDB API version is $installed_maxminddb_version"
if [ -z "$MAXMINDDB_VERSION" ] ; then
echo "MaxMindDB is not requested"
else
echo "Requested GeoIP version is $GEOIP_VERSION"
echo "Requested MaxMindDB version is $MAXMINDDB_VERSION"
fi
uninstall_geoip -r
uninstall_maxminddb -r
fi
if [ ! -z "$installed_sbc_version" -a \
@ -2490,7 +2466,7 @@ install_all() {
# Now we have reached a point where we can build everything including
# the GUI (Wireshark), but not with any optional features such as
# SNMP OID resolution, some forms of decryption, Lua scripting, playback
# of audio, or GeoIP mapping of IP addresses.
# of audio, or MaxMindDB mapping of IP addresses.
#
# We now conditionally download optional libraries to support them;
# the default is to download them all.
@ -2520,7 +2496,7 @@ install_all() {
install_sbc
install_geoip
install_maxminddb
install_c_ares
@ -2561,7 +2537,7 @@ uninstall_all() {
uninstall_c_ares
uninstall_geoip
uninstall_maxminddb
uninstall_portaudio
@ -2658,7 +2634,7 @@ fi
dir=`dirname $0`
cd $dir/..
#
#
#
# If we have SDKs available, the default target OS is the major version
# of the one we're running; get that and strip off the third component
@ -2747,7 +2723,7 @@ then
installed_libxml2_version=`ls libxml2-*-done 2>/dev/null | sed 's/libxml2-\(.*\)-done/\1/'`
installed_lz4_version=`ls lz4-*-done 2>/dev/null | sed 's/lz4-\(.*\)-done/\1/'`
installed_sbc_version=`ls sbc-*-done 2>/dev/null | sed 's/sbc-\(.*\)-done/\1/'`
installed_geoip_version=`ls geoip-*-done 2>/dev/null | sed 's/geoip-\(.*\)-done/\1/'`
installed_maxminddb_version=`ls maxminddb-*-done 2>/dev/null | sed 's/maxminddb-\(.*\)-done/\1/'`
installed_cares_version=`ls c-ares-*-done 2>/dev/null | sed 's/c-ares-\(.*\)-done/\1/'`
installed_libssh_version=`ls libssh-*-done 2>/dev/null | sed 's/libssh-\(.*\)-done/\1/'`
installed_nghttp2_version=`ls nghttp2-*-done 2>/dev/null | sed 's/nghttp2-\(.*\)-done/\1/'`

View File

@ -18,6 +18,7 @@ epan/wmem/wmem_strbuf.c
epan/wmem/wmem_strutil.c
extcap/*
image/stock_icons/*
mmdbresolve.c
tools/lemon/*
wsutil/file_util.h
wsutil/strptime.c

View File

@ -121,8 +121,8 @@ echo "lz4 devel is unavailable" >&2
add_package ADDITIONAL_LIST libcap-progs || echo "cap progs are unavailable" >&2
add_package ADDITIONAL_LIST GeoIP-devel || add_package ADDITIONAL_LIST libGeoIP-devel ||
echo "GeoIP devel is unavailable" >&2
add_package ADDITIONAL_LIST libmaxminddb-devel ||
echo "MaxMind DB devel is unavailable" >&2
add_package ADDITIONAL_LIST gnutls-devel || add_package ADDITIONAL_LIST libgnutls-devel ||
echo "gnutls devel is unavailable" >&2

View File

@ -107,7 +107,7 @@ $Win64Archives = @{
"AirPcap_Devpack_4_1_0_1622.zip" = "AirPcap_Devpack_4_1_0_1622";
"bcg729-1.0.4-win64ws.zip" = "";
"c-ares-1.13.0-win64ws.zip" = "";
"GeoIP-1.6.10-win64ws.zip" = "";
#"GeoIP-1.6.10-win64ws.zip" = "";
"gnutls-3.4.11-1.35-win64ws.zip" = "";
"gtk+-bundle_2.24.23-3.39-2_win64ws.zip" = "gtk2";
"kfw-3-2-2-x64-ws.zip" = "";
@ -131,7 +131,7 @@ $Win32Archives = @{
"AirPcap_Devpack_4_1_0_1622.zip" = "AirPcap_Devpack_4_1_0_1622";
"bcg729-1.0.4-win32ws.zip" = "";
"c-ares-1.13.0-win32ws.zip" = "";
"GeoIP-1.6.10-win32ws.zip" = "";
#"GeoIP-1.6.10-win32ws.zip" = "";
"gnutls-3.4.11-1.36-win32ws.zip" = "";
"gtk+-bundle_2.24.23-1.1-1_win32ws.zip" = "gtk2";
"kfw-3-2-2-i386-ws-vc6.zip" = "";

View File

@ -85,9 +85,7 @@
#if defined(HAVE_LIBSMI)
#include "epan/oids.h"
#endif
#if defined(HAVE_GEOIP)
#include "epan/geoip_db.h"
#endif
#include "epan/maxmind_db.h"
#include "epan/register.h"
#include <epan/epan_dissect.h>
#include <epan/tap.h>
@ -618,18 +616,16 @@ about_folders(void)
g_strfreev(resultArray);
#ifdef HAVE_GEOIP
/* GeoIP */
path = geoip_db_get_paths();
/* MaxMindDB */
path = maxmind_db_get_paths();
resultArray = g_strsplit(path, G_SEARCHPATH_SEPARATOR_S, 10);
for(i = 0; resultArray[i]; i++)
printf("%-21s\t%s\n", "GeoIP path:", g_strstrip(resultArray[i]));
printf("%-21s\t%s\n", "MaxMind database path:", g_strstrip(resultArray[i]));
g_strfreev(resultArray);
g_free(path);
#endif
#ifdef HAVE_LIBSMI
/* SMI MIBs/PIBs */

View File

@ -8,17 +8,14 @@
#include "endpoint_dialog.h"
#ifdef HAVE_GEOIP
#include <GeoIP.h>
#include <epan/geoip_db.h>
#include <wsutil/pint.h>
#endif
#include <epan/maxmind_db.h>
#include <epan/prefs.h>
#include "ui/recent.h"
#include "ui/traffic_table_ui.h"
#include "wsutil/pint.h"
#include "wsutil/str_util.h"
#include <ui/qt/utils/qt_ui_utils.h>
@ -160,9 +157,7 @@ void init_endpoint_table(struct register_ct* ct, const char *filter)
// EndpointTreeWidgetItem
// TrafficTableTreeWidgetItem / QTreeWidgetItem subclass that allows sorting
#ifdef HAVE_GEOIP
static const char *geoip_none_ = UTF8_EM_DASH;
#endif
static const char *data_none_ = UTF8_EM_DASH;
class EndpointTreeWidgetItem : public TrafficTableTreeWidgetItem
{
@ -198,17 +193,10 @@ public:
return QString("%L1").arg(endp_item->rx_frames);
case ENDP_COLUMN_BYTES_BA:
return gchar_free_to_qstring(format_size(endp_item->rx_bytes, format_size_unit_none|format_size_prefix_si));
#ifdef HAVE_GEOIP
default:
{
QString geoip_str = colData(column, resolve_names, true).toString();
if (geoip_str.isEmpty()) geoip_str = geoip_none_;
return geoip_str;
}
#else
default:
return colData(column, resolve_names, true);
#endif
QVariant col_data = colData(column, resolve_names);
if (col_data.isValid()) return col_data;
return QVariant(data_none_);
}
}
return QTreeWidgetItem::data(column, role);
@ -216,12 +204,16 @@ public:
// Column text raw representation.
// Return a string, qulonglong, double, or invalid QVariant representing the raw column data.
QVariant colData(int col, bool resolve_names, bool strings_only) const {
#ifndef HAVE_GEOIP
Q_UNUSED(strings_only)
#endif
QVariant colData(int col, bool resolve_names) const {
hostlist_talker_t *endp_item = &g_array_index(conv_array_, hostlist_talker_t, conv_idx_);
const mmdb_lookup_t *mmdb_lookup = NULL;
if (endp_item->myaddress.type == AT_IPv4) {
mmdb_lookup = maxmind_db_lookup_ipv4(pntoh32(endp_item->myaddress.data));
} else if (endp_item->myaddress.type == AT_IPv6) {
mmdb_lookup = maxmind_db_lookup_ipv6((ws_in6_addr *) endp_item->myaddress.data);
}
switch (col) {
case ENDP_COLUMN_ADDR:
{
@ -251,55 +243,32 @@ public:
return quint64(endp_item->rx_frames);
case ENDP_COLUMN_BYTES_BA:
return quint64(endp_item->rx_bytes);
#ifdef HAVE_GEOIP
default:
{
QString geoip_str;
/* Filled in from the GeoIP config, if any */
EndpointTreeWidget *ep_tree = qobject_cast<EndpointTreeWidget *>(treeWidget());
if (!ep_tree) return geoip_str;
foreach (unsigned db, ep_tree->columnToDb(col)) {
if (endp_item->myaddress.type == AT_IPv4) {
geoip_str = geoip_db_lookup_ipv4(db, pntoh32(endp_item->myaddress.data), NULL);
} else if (endp_item->myaddress.type == AT_IPv6) {
const ws_in6_addr *addr = (const ws_in6_addr *) endp_item->myaddress.data;
geoip_str = geoip_db_lookup_ipv6(db, *addr, NULL);
}
if (!geoip_str.isEmpty()) {
break;
}
case ENDP_COLUMN_GEO_COUNTRY:
if (mmdb_lookup && mmdb_lookup->found && mmdb_lookup->country) {
return QVariant(mmdb_lookup->country);
}
if (strings_only) return geoip_str;
bool ok;
double dval = geoip_str.toDouble(&ok);
if (ok) { // Assume lat / lon
return dval;
return QVariant();
case ENDP_COLUMN_GEO_CITY:
if (mmdb_lookup && mmdb_lookup->found && mmdb_lookup->city) {
return QVariant(mmdb_lookup->city);
}
qulonglong ullval = geoip_str.toULongLong(&ok);
if (ok) { // Assume uint
return ullval;
return QVariant();
case ENDP_COLUMN_GEO_AS_NUM:
if (mmdb_lookup && mmdb_lookup->found && mmdb_lookup->as_number) {
return QVariant(mmdb_lookup->as_number);
}
qlonglong llval = geoip_str.toLongLong(&ok);
if (ok) { // Assume int
return llval;
return QVariant();
case ENDP_COLUMN_GEO_AS_ORG:
if (mmdb_lookup && mmdb_lookup->found && mmdb_lookup->as_org) {
return QVariant(mmdb_lookup->as_org);
}
return QVariant();
return geoip_str;
}
#else
default:
return QVariant();
#endif
}
}
virtual QVariant colData(int col, bool resolve_names) const { return colData(col, resolve_names, false); }
bool operator< (const QTreeWidgetItem &other) const
{
const EndpointTreeWidgetItem *other_row = static_cast<const EndpointTreeWidgetItem *>(&other);
@ -325,26 +294,26 @@ public:
return endp_item->rx_frames < other_item->rx_frames;
case ENDP_COLUMN_BYTES_BA:
return endp_item->rx_bytes < other_item->rx_bytes;
#ifdef HAVE_GEOIP
default:
case ENDP_COLUMN_GEO_COUNTRY:
case ENDP_COLUMN_GEO_CITY:
case ENDP_COLUMN_GEO_AS_ORG:
{
double ei_val, oi_val;
bool ei_ok, oi_ok;
ei_val = text(sort_col).toDouble(&ei_ok);
oi_val = other.text(sort_col).toDouble(&oi_ok);
if (ei_ok && oi_ok) { // Assume lat / lon
return ei_val < oi_val;
} else {
// XXX Fall back to string comparison. We might want to try sorting naturally
// using QCollator instead.
return text(sort_col) < other.text(sort_col);
}
QString this_str = data(sort_col, Qt::DisplayRole).toString();
QString other_str = other_row->data(sort_col, Qt::DisplayRole).toString();
return (this_str < other_str);
}
case ENDP_COLUMN_GEO_AS_NUM:
{
// Valid values first, similar to strings above.
bool ok;
unsigned this_asn = colData(sort_col, false).toUInt(&ok);
if (!ok) this_asn = UINT_MAX;
unsigned other_asn = other_row->colData(sort_col, false).toUInt(&ok);
if (!ok) other_asn = UINT_MAX;
return (this_asn < other_asn);
}
#else
default:
return false;
#endif
}
}
private:
@ -359,40 +328,32 @@ private:
//
EndpointTreeWidget::EndpointTreeWidget(QWidget *parent, register_ct_t *table) :
TrafficTableTreeWidget(parent, table)
#ifdef HAVE_GEOIP
, has_geoip_data_(false)
#endif
TrafficTableTreeWidget(parent, table),
table_address_type_(AT_NONE)
{
setColumnCount(ENDP_NUM_COLUMNS);
setUniformRowHeights(true);
for (int i = 0; i < ENDP_NUM_COLUMNS; i++) {
headerItem()->setText(i, endp_column_titles[i]);
QString proto_filter_name = proto_get_protocol_filter_name(get_conversation_proto_id(table_));
if (proto_filter_name == "ip") {
table_address_type_ = AT_IPv4;
} else if (proto_filter_name == "ipv6") {
table_address_type_ = AT_IPv6;
}
if (get_conversation_hide_ports(table_)) {
hideColumn(ENDP_COLUMN_PORT);
} else if (!strcmp(proto_get_protocol_filter_name(get_conversation_proto_id(table_)), "ncp")) {
} else if (proto_filter_name == "ncp") {
headerItem()->setText(ENDP_COLUMN_PORT, endp_conn_title);
}
#ifdef HAVE_GEOIP
QMap<QString, int> db_name_to_col;
for (unsigned db = 0; db < geoip_db_num_dbs(); db++) {
QString db_name = geoip_db_name(db);
int col = db_name_to_col.value(db_name, -1);
if (col < 0) {
col = columnCount();
setColumnCount(col + 1);
headerItem()->setText(col, db_name);
hideColumn(col);
db_name_to_col[db_name] = col;
}
col_to_db_[col] << db;
int column_count = ENDP_NUM_COLUMNS;
if (table_address_type_ == AT_IPv4 || table_address_type_ == AT_IPv6) {
column_count = ENDP_NUM_GEO_COLUMNS;
}
#endif
for (int col = 0; col < column_count; col++) {
headerItem()->setText(col, endp_column_titles[col]);
}
int one_en = fontMetrics().height() / 2;
for (int i = 0; i < columnCount(); i++) {
@ -414,7 +375,7 @@ EndpointTreeWidget::EndpointTreeWidget(QWidget *parent, register_ct_t *table) :
setColumnWidth(i, one_en * (int) strlen("000,000"));
break;
default:
setColumnWidth(i, one_en * (int) strlen("-00.000000")); // GeoIP
setColumnWidth(i, one_en * 15); // Geolocation
}
}
@ -494,19 +455,6 @@ void EndpointTreeWidget::updateItems()
return;
}
#ifdef HAVE_GEOIP
if (topLevelItemCount() < 1 && hash_.conv_array->len > 0) {
hostlist_talker_t *endp_item = &g_array_index(hash_.conv_array, hostlist_talker_t, 0);
if (endp_item->myaddress.type == AT_IPv4 || endp_item->myaddress.type == AT_IPv6) {
for (unsigned i = 0; i < geoip_db_num_dbs(); i++) {
showColumn(ENDP_NUM_COLUMNS + i);
}
has_geoip_data_ = true;
emit geoIPStatusChanged();
}
}
#endif
setSortingEnabled(false);
QList<QTreeWidgetItem *>new_items;

View File

@ -18,28 +18,14 @@ public:
explicit EndpointTreeWidget(QWidget *parent, register_ct_t* table);
~EndpointTreeWidget();
#ifdef HAVE_GEOIP
bool hasGeoIPData() const { return has_geoip_data_; }
#endif
static void tapReset(void *conv_hash_ptr);
static void tapDraw(void *conv_hash_ptr);
#ifdef HAVE_GEOIP
public:
const QList<int> columnToDb(int column) const { return col_to_db_.value(column, QList<int>()); }
signals:
void geoIPStatusChanged();
private:
QMap<int, QList<int> > col_to_db_; // Map tree columns to GeoIP databases
bool has_geoip_data_;
#endif
private:
void updateItems();
address_type table_address_type_;
private slots:
void filterActionTriggered();
};

View File

@ -35,7 +35,7 @@ const char *conv_conn_a_title = "Connection A";
const char *conv_conn_b_title = "Connection B";
const char *conv_abs_start_title = "Abs Start";
const char *endp_column_titles[ENDP_NUM_COLUMNS] = {
const char *endp_column_titles[ENDP_NUM_GEO_COLUMNS] = {
"Address",
"Port",
"Packets",
@ -43,7 +43,11 @@ const char *endp_column_titles[ENDP_NUM_COLUMNS] = {
"Tx Packets",
"Tx Bytes",
"Rx Packets",
"Rx Bytes"
"Rx Bytes",
"Country",
"City",
"AS Number",
"AS Organization"
};
const char *endp_conn_title = "Connection";

View File

@ -53,10 +53,15 @@ typedef enum
ENDP_COLUMN_BYTES_AB,
ENDP_COLUMN_PKT_BA,
ENDP_COLUMN_BYTES_BA,
ENDP_NUM_COLUMNS
ENDP_NUM_COLUMNS,
ENDP_COLUMN_GEO_COUNTRY = ENDP_NUM_COLUMNS,
ENDP_COLUMN_GEO_CITY,
ENDP_COLUMN_GEO_AS_NUM,
ENDP_COLUMN_GEO_AS_ORG,
ENDP_NUM_GEO_COLUMNS,
} endpoint_column_type_e;
extern const char *endp_column_titles[ENDP_NUM_COLUMNS];
extern const char *endp_column_titles[ENDP_NUM_GEO_COLUMNS];
extern const char *endp_conn_title;