From a1da75c554881667dd92e11f098630f2d604872b Mon Sep 17 00:00:00 2001 From: Gerald Combs Date: Thu, 8 Feb 2018 17:20:26 -0800 Subject: [PATCH] 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 Tested-by: Petri Dish Buildbot Reviewed-by: Gerald Combs --- CMakeLists.txt | 34 +- CMakeOptions.txt | 2 +- Makefile.am | 9 +- README.macos | 7 - acinclude.m4 | 32 +- cmake/modules/FindGEOIP.cmake | 74 -- cmake/modules/FindMaxMindDB.cmake | 74 ++ cmakeconfig.h.in | 10 +- configure.ac | 42 +- debian/control | 4 +- debian/libwireshark-data.install | 2 +- debian/libwireshark0.symbols | 9 +- debian/{geoip_db_paths => maxmind_db_paths} | 0 doc/CMakeLists.txt | 29 +- doc/Makefile.am | 13 +- doc/mmdbresolve.pod | 69 ++ docbook/release-notes.asciidoc | 2 + .../wsdg_src/WSDG_chapter_libraries.asciidoc | 23 +- .../wsug_src/WSUG_chapter_customize.asciidoc | 41 +- .../wsug_src/WSUG_chapter_statistics.asciidoc | 11 +- docbook/wsug_src/WSUG_chapter_use.asciidoc | 7 +- epan/CMakeLists.txt | 9 +- epan/Makefile.am | 9 +- epan/addr_resolv.c | 10 +- epan/addr_resolv.h | 6 + epan/dissectors/Makefile.am | 2 +- epan/dissectors/packet-ip.c | 279 ++++---- epan/dissectors/packet-ipv6.c | 299 ++++---- epan/epan.c | 10 +- epan/geoip_db.c | 638 ------------------ epan/geoip_db.h | 104 --- epan/maxmind_db.c | 513 ++++++++++++++ epan/maxmind_db.h | 93 +++ epan/prefs.c | 8 +- mmdbresolve.c | 169 +++++ packaging/macosx/Scripts/cli-postinstall.sh | 1 + packaging/nsis/CMakeLists.txt | 7 +- packaging/nsis/uninstall.nsi | 26 +- packaging/nsis/wireshark.nsi | 8 + packaging/rpm/SPECS/wireshark.spec.in | 4 +- packaging/wix/CMakeLists.txt | 13 +- packaging/wix/ComponentGroups.wxi | 18 + packaging/wix/Features.wxi | 3 + tools/Get-HardenFlags.ps1 | 2 +- tools/debian-setup.sh | 6 +- tools/install_rpms_for_devel.sh | 6 +- tools/macos-setup.sh | 88 +-- tools/pre-commit-ignore.conf | 1 + tools/rpm_setup.sh | 4 +- tools/win-setup.ps1 | 4 +- tshark.c | 12 +- ui/qt/endpoint_dialog.cpp | 176 ++--- ui/qt/endpoint_dialog.h | 18 +- ui/traffic_table_ui.c | 8 +- ui/traffic_table_ui.h | 9 +- 55 files changed, 1539 insertions(+), 1518 deletions(-) delete mode 100644 cmake/modules/FindGEOIP.cmake create mode 100644 cmake/modules/FindMaxMindDB.cmake rename debian/{geoip_db_paths => maxmind_db_paths} (100%) create mode 100644 doc/mmdbresolve.pod delete mode 100644 epan/geoip_db.c delete mode 100644 epan/geoip_db.h create mode 100644 epan/maxmind_db.c create mode 100644 epan/maxmind_db.h create mode 100644 mmdbresolve.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 747223adf6..96b013892a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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, diff --git a/CMakeOptions.txt b/CMakeOptions.txt index c011f3e65b..e7903f5b0f 100644 --- a/CMakeOptions.txt +++ b/CMakeOptions.txt @@ -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() diff --git a/Makefile.am b/Makefile.am index 3f381f8a0e..f90fda4c32 100644 --- a/Makefile.am +++ b/Makefile.am @@ -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 \ diff --git a/README.macos b/README.macos index 7e533ca3f7..e53e946d2f 100644 --- a/README.macos +++ b/README.macos @@ -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 diff --git a/acinclude.m4 b/acinclude.m4 index c53ac7c46a..bfc715c3f1 100644 --- a/acinclude.m4 +++ b/acinclude.m4 @@ -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 diff --git a/cmake/modules/FindGEOIP.cmake b/cmake/modules/FindGEOIP.cmake deleted file mode 100644 index 518837be4b..0000000000 --- a/cmake/modules/FindGEOIP.cmake +++ /dev/null @@ -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 ) diff --git a/cmake/modules/FindMaxMindDB.cmake b/cmake/modules/FindMaxMindDB.cmake new file mode 100644 index 0000000000..cad4499e5b --- /dev/null +++ b/cmake/modules/FindMaxMindDB.cmake @@ -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 ) diff --git a/cmakeconfig.h.in b/cmakeconfig.h.in index 30660c259a..c78328ae08 100644 --- a/cmakeconfig.h.in +++ b/cmakeconfig.h.in @@ -62,14 +62,8 @@ /* Define to 1 if you have the 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 header file. */ #cmakedefine HAVE_IFADDRS_H 1 diff --git a/configure.ac b/configure.ac index 11ef8825e6..ebb8ba0364 100644 --- a/configure.ac +++ b/configure.ac @@ -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" diff --git a/debian/control b/debian/control index 2f1c62fd29..e1b1511cdd 100644 --- a/debian/control +++ b/debian/control @@ -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 diff --git a/debian/libwireshark-data.install b/debian/libwireshark-data.install index 568526fc2e..b717c62e2a 100644 --- a/debian/libwireshark-data.install +++ b/debian/libwireshark-data.install @@ -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 diff --git a/debian/libwireshark0.symbols b/debian/libwireshark0.symbols index a1bdc2116f..ea313849ce 100644 --- a/debian/libwireshark0.symbols +++ b/debian/libwireshark0.symbols @@ -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 diff --git a/debian/geoip_db_paths b/debian/maxmind_db_paths similarity index 100% rename from debian/geoip_db_paths rename to debian/maxmind_db_paths diff --git a/doc/CMakeLists.txt b/doc/CMakeLists.txt index c0cf6c11fc..798c49ee20 100644 --- a/doc/CMakeLists.txt +++ b/doc/CMakeLists.txt @@ -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() diff --git a/doc/Makefile.am b/doc/Makefile.am index 7c5b31ca15..c88ebc7bc4 100644 --- a/doc/Makefile.am +++ b/doc/Makefile.am @@ -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 diff --git a/doc/mmdbresolve.pod b/doc/mmdbresolve.pod new file mode 100644 index 0000000000..43a827e448 --- /dev/null +++ b/doc/mmdbresolve.pod @@ -0,0 +1,69 @@ + +=head1 NAME + +mmdbresolve - Read IPv4 and IPv6 addresses and print their IP geolocation information. + +=head1 SYNOPSIS + +B +SdbfileE>> +S<[ B<-f EdbfileE> ]> +I<...> + +=head1 DESCRIPTION + +B 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 is part of the B distribution. The latest version +of B can be found at L. + +HTML versions of the Wireshark project man pages are available at: +L. + +=head1 AUTHORS + + Original Author + --------------- + Gerald Combs diff --git a/docbook/release-notes.asciidoc b/docbook/release-notes.asciidoc index b2db89ff99..073d634a1d 100644 --- a/docbook/release-notes.asciidoc +++ b/docbook/release-notes.asciidoc @@ -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. diff --git a/docbook/wsdg_src/WSDG_chapter_libraries.asciidoc b/docbook/wsdg_src/WSDG_chapter_libraries.asciidoc index 247649d5a7..c184f867cf 100644 --- a/docbook/wsdg_src/WSDG_chapter_libraries.asciidoc +++ b/docbook/wsdg_src/WSDG_chapter_libraries.asciidoc @@ -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]] diff --git a/docbook/wsug_src/WSUG_chapter_customize.asciidoc b/docbook/wsug_src/WSUG_chapter_customize.asciidoc index 96e443468e..66ea7288da 100644 --- a/docbook/wsug_src/WSUG_chapter_customize.asciidoc +++ b/docbook/wsug_src/WSUG_chapter_customize.asciidoc @@ -746,7 +746,7 @@ Configuration files stored in the Profiles: * ESS Category Attributes (ess_category_attributes) (<>) -* GeoIP Database Paths (geoip_db_paths) (<>) +* MaxMind Database Paths (maxmind_db_paths) (<>) * K12 Protocols (k12_protos) (<>) @@ -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/[MaxMind’s] -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/[MaxMind’s] 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 <> 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]] diff --git a/docbook/wsug_src/WSUG_chapter_statistics.asciidoc b/docbook/wsug_src/WSUG_chapter_statistics.asciidoc index 6580c5c090..607ccfc9d7 100644 --- a/docbook/wsug_src/WSUG_chapter_statistics.asciidoc +++ b/docbook/wsug_src/WSUG_chapter_statistics.asciidoc @@ -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 <> 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 <> for more information. The btn:[Copy] button will copy the list values to the clipboard in CSV (Comma Separated Values) or YAML format. diff --git a/docbook/wsug_src/WSUG_chapter_use.asciidoc b/docbook/wsug_src/WSUG_chapter_use.asciidoc index fd21e7afa2..1ea8d65038 100644 --- a/docbook/wsug_src/WSUG_chapter_use.asciidoc +++ b/docbook/wsug_src/WSUG_chapter_use.asciidoc @@ -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 isn’t 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 isn’t 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 diff --git a/epan/CMakeLists.txt b/epan/CMakeLists.txt index 5bd3d40e4e..f0196fc57f 100644 --- a/epan/CMakeLists.txt +++ b/epan/CMakeLists.txt @@ -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} diff --git a/epan/Makefile.am b/epan/Makefile.am index d22d68e18b..c85fcd2d52 100644 --- a/epan/Makefile.am +++ b/epan/Makefile.am @@ -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@ \ diff --git a/epan/addr_resolv.c b/epan/addr_resolv.c index 1cae8a5733..56da73bf69 100644 --- a/epan/addr_resolv.c +++ b/epan/addr_resolv.c @@ -92,6 +92,7 @@ #include #include +#include #include #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; } diff --git a/epan/addr_resolv.h b/epan/addr_resolv.h index cfac1fc5c1..bc1d78d61a 100644 --- a/epan/addr_resolv.h +++ b/epan/addr_resolv.h @@ -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 */ diff --git a/epan/dissectors/Makefile.am b/epan/dissectors/Makefile.am index 423a5dda34..0367141e8e 100644 --- a/epan/dissectors/Makefile.am +++ b/epan/dissectors/Makefile.am @@ -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 diff --git a/epan/dissectors/packet-ip.c b/epan/dissectors/packet-ip.c index 1ab1b25812..02432764f1 100644 --- a/epan/dissectors/packet-ip.c +++ b/epan/dissectors/packet-ip.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -48,11 +49,6 @@ #include "packet-mpls.h" #include "packet-nsh.h" -#ifdef HAVE_GEOIP -#include -#include -#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", diff --git a/epan/dissectors/packet-ipv6.c b/epan/dissectors/packet-ipv6.c index 852cf192a6..40e11edd99 100644 --- a/epan/dissectors/packet-ipv6.c +++ b/epan/dissectors/packet-ipv6.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -43,11 +44,6 @@ #include "packet-mpls.h" #include "packet-nsh.h" -#ifdef HAVE_GEOIP_V6 -#include -#include -#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", diff --git a/epan/epan.c b/epan/epan.c index 076b557b5a..a1a9240a81 100644 --- a/epan/epan.c +++ b/epan/epan.c @@ -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, ", "); diff --git a/epan/geoip_db.c b/epan/geoip_db.c deleted file mode 100644 index f79b0f677b..0000000000 --- a/epan/geoip_db.c +++ /dev/null @@ -1,638 +0,0 @@ -/* geoip_db.c - * GeoIP database support - * - * Copyright 2008, Gerald Combs - * - * Wireshark - Network traffic analyzer - * By Gerald Combs - * 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 - -#include - -#ifdef HAVE_GEOIP -#include -#include - -#include -#include -#include -#include - -#include -#include - -/* 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: - */ diff --git a/epan/geoip_db.h b/epan/geoip_db.h deleted file mode 100644 index 20aa46a8c6..0000000000 --- a/epan/geoip_db.h +++ /dev/null @@ -1,104 +0,0 @@ -/* geoip_db.h - * GeoIP database support - * - * Copyright 2008, Gerald Combs - * - * Wireshark - Network traffic analyzer - * By Gerald Combs - * 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 -#include -#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: - */ diff --git a/epan/maxmind_db.c b/epan/maxmind_db.c new file mode 100644 index 0000000000..03e705660d --- /dev/null +++ b/epan/maxmind_db.c @@ -0,0 +1,513 @@ +/* maxmind_db.c + * GeoIP database support + * + * Copyright 2018, Gerald Combs + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "config.h" + +#include + +#include + +static mmdb_lookup_t mmdb_not_found; + +#ifdef HAVE_MAXMINDDB + +#include +#include + +#include + +#include +#include +#include + +#include +#include +#include +#include + +// 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: + */ diff --git a/epan/maxmind_db.h b/epan/maxmind_db.h new file mode 100644 index 0000000000..1b8e5fed0a --- /dev/null +++ b/epan/maxmind_db.h @@ -0,0 +1,93 @@ +/* maxmind_db.h + * Maxmind database support + * + * Copyright 2018, Gerald Combs + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * 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 +#include +#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: + */ diff --git a/epan/prefs.c b/epan/prefs.c index 1ccf5ac185..eb30c1628a 100644 --- a/epan/prefs.c +++ b/epan/prefs.c @@ -21,9 +21,7 @@ #include #include #include -#ifdef HAVE_GEOIP -#include -#endif +#include #include #include #include @@ -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", diff --git a/mmdbresolve.c b/mmdbresolve.c new file mode 100644 index 0000000000..3568a0b4b9 --- /dev/null +++ b/mmdbresolve.c @@ -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 + * 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 +#include +#include +#include + +#include + +#include + +#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: + */ diff --git a/packaging/macosx/Scripts/cli-postinstall.sh b/packaging/macosx/Scripts/cli-postinstall.sh index f83cf4faac..4c74a42847 100755 --- a/packaging/macosx/Scripts/cli-postinstall.sh +++ b/packaging/macosx/Scripts/cli-postinstall.sh @@ -7,6 +7,7 @@ BINARIES=" dumpcap editcap mergecap + mmdbresolve randpkt rawshark text2pcap diff --git a/packaging/nsis/CMakeLists.txt b/packaging/nsis/CMakeLists.txt index 6237f5b382..ce6024ad7b 100644 --- a/packaging/nsis/CMakeLists.txt +++ b/packaging/nsis/CMakeLists.txt @@ -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() diff --git a/packaging/nsis/uninstall.nsi b/packaging/nsis/uninstall.nsi index f552ffed74..74d2e28eae 100644 --- a/packaging/nsis/uninstall.nsi +++ b/packaging/nsis/uninstall.nsi @@ -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} diff --git a/packaging/nsis/wireshark.nsi b/packaging/nsis/wireshark.nsi index 21c67e31a5..404c6a326d 100644 --- a/packaging/nsis/wireshark.nsi +++ b/packaging/nsis/wireshark.nsi @@ -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 diff --git a/packaging/rpm/SPECS/wireshark.spec.in b/packaging/rpm/SPECS/wireshark.spec.in index 024e9fd4b2..3ddd8a00e8 100644 --- a/packaging/rpm/SPECS/wireshark.spec.in +++ b/packaging/rpm/SPECS/wireshark.spec.in @@ -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 diff --git a/packaging/wix/CMakeLists.txt b/packaging/wix/CMakeLists.txt index ec07991dc7..352e53f854 100644 --- a/packaging/wix/CMakeLists.txt +++ b/packaging/wix/CMakeLists.txt @@ -136,10 +136,13 @@ file(APPEND "${_all_manifest_wix}" "\n") file(APPEND "${_all_manifest_wix}" " \n") file(APPEND "${_all_manifest_wix}" " \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}" " \n") file(APPEND "${_all_manifest_wix}" " \n") file(APPEND "${_all_manifest_wix}" " \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}(;|$)") diff --git a/packaging/wix/ComponentGroups.wxi b/packaging/wix/ComponentGroups.wxi index 92fc09b157..8631c805d2 100644 --- a/packaging/wix/ComponentGroups.wxi +++ b/packaging/wix/ComponentGroups.wxi @@ -433,6 +433,24 @@ + + + + + + + + + + + + + + + + + + diff --git a/packaging/wix/Features.wxi b/packaging/wix/Features.wxi index 891d689b5e..277a713a14 100644 --- a/packaging/wix/Features.wxi +++ b/packaging/wix/Features.wxi @@ -81,6 +81,9 @@ + + + diff --git a/tools/Get-HardenFlags.ps1 b/tools/Get-HardenFlags.ps1 index 7503f13826..5f45cab3e8 100644 --- a/tools/Get-HardenFlags.ps1 +++ b/tools/Get-HardenFlags.ps1 @@ -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", diff --git a/tools/debian-setup.sh b/tools/debian-setup.sh index 2b7c672aac..44abcf76c1 100755 --- a/tools/debian-setup.sh +++ b/tools/debian-setup.sh @@ -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 diff --git a/tools/install_rpms_for_devel.sh b/tools/install_rpms_for_devel.sh index f6ac3f077c..c2362e70ff 100755 --- a/tools/install_rpms_for_devel.sh +++ b/tools/install_rpms_for_devel.sh @@ -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):" diff --git a/tools/macos-setup.sh b/tools/macos-setup.sh index a76ff3271e..30eb3d8928 100755 --- a/tools/macos-setup.sh +++ b/tools/macos-setup.sh @@ -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/'` diff --git a/tools/pre-commit-ignore.conf b/tools/pre-commit-ignore.conf index 27a860f63d..e10030d87f 100644 --- a/tools/pre-commit-ignore.conf +++ b/tools/pre-commit-ignore.conf @@ -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 diff --git a/tools/rpm_setup.sh b/tools/rpm_setup.sh index 4e6bf7fd54..c52afbfde8 100755 --- a/tools/rpm_setup.sh +++ b/tools/rpm_setup.sh @@ -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 diff --git a/tools/win-setup.ps1 b/tools/win-setup.ps1 index ccfffd13c6..6403aa42de 100644 --- a/tools/win-setup.ps1 +++ b/tools/win-setup.ps1 @@ -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" = ""; diff --git a/tshark.c b/tshark.c index 289ea98239..9061fa3444 100644 --- a/tshark.c +++ b/tshark.c @@ -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 #include @@ -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 */ diff --git a/ui/qt/endpoint_dialog.cpp b/ui/qt/endpoint_dialog.cpp index 37e5ccdb86..00cddeaa84 100644 --- a/ui/qt/endpoint_dialog.cpp +++ b/ui/qt/endpoint_dialog.cpp @@ -8,17 +8,14 @@ #include "endpoint_dialog.h" -#ifdef HAVE_GEOIP -#include -#include -#include -#endif +#include #include #include "ui/recent.h" #include "ui/traffic_table_ui.h" +#include "wsutil/pint.h" #include "wsutil/str_util.h" #include @@ -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(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(&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 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); QListnew_items; diff --git a/ui/qt/endpoint_dialog.h b/ui/qt/endpoint_dialog.h index b1186f4858..08bca0a759 100644 --- a/ui/qt/endpoint_dialog.h +++ b/ui/qt/endpoint_dialog.h @@ -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 columnToDb(int column) const { return col_to_db_.value(column, QList()); } - -signals: - void geoIPStatusChanged(); - -private: - QMap > 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(); }; diff --git a/ui/traffic_table_ui.c b/ui/traffic_table_ui.c index 02c6d16a5c..0f41f238f4 100644 --- a/ui/traffic_table_ui.c +++ b/ui/traffic_table_ui.c @@ -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"; diff --git a/ui/traffic_table_ui.h b/ui/traffic_table_ui.h index c89564d24e..f067297808 100644 --- a/ui/traffic_table_ui.h +++ b/ui/traffic_table_ui.h @@ -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;