From 58f4ff91d8c124f4540777cfb772e38c898341d6 Mon Sep 17 00:00:00 2001 From: Tim Wojtulewicz Date: Thu, 22 Dec 2022 13:35:51 -0700 Subject: [PATCH] Fixes to support the Npcap library on Windows - Ignore conan libpcap if PCAP_ROOT_DIR is passed - Update the cmake submodule to pick up changes for finding the right paths to npcap - Add lazy-loading of npcap so the library path gets set correctly at startup --- CMakeLists.txt | 11 +++++++---- cmake | 2 +- src/CMakeLists.txt | 9 +++++++++ src/main.cc | 34 ++++++++++++++++++++++++++++++++++ zeek-config.h.in | 3 +++ 5 files changed, 54 insertions(+), 5 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index b9f9c53a1a..e33923e518 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -71,10 +71,13 @@ if ( MSVC ) endif() # Set LibPCAP to point to libpcap binaries. - find_package(libpcap) - set(PCAP_ROOT_DIR "${libpcap_LIB_DIRS}/../") - set(PCAP_INCLUDE_DIR ${libpcap_INCLUDES}) - set(PCAP_LIBRARY ${libpcap_LIBS}) + if ( NOT PCAP_ROOT_DIR ) + find_package(libpcap) + set(PCAP_ROOT_DIR "${libpcap_LIB_DIRS}/../") + set(PCAP_INCLUDE_DIR ${libpcap_INCLUDES}) + set(PCAP_LIBRARY ${libpcap_LIBS}) + endif() + set(LIBPCAP_PCAP_COMPILE_NOPCAP_HAS_ERROR_PARAMETER false) # Set ZLib to point at the right variable. diff --git a/cmake b/cmake index 99ee0e757d..f69e08247e 160000 --- a/cmake +++ b/cmake @@ -1 +1 @@ -Subproject commit 99ee0e757df66d81d78e59a32f61101058bc00fc +Subproject commit f69e08247ed4d7e36258157df6328bad3c81269d diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index b126b8e3de..3538996585 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -543,6 +543,15 @@ if (ZEEK_STANDALONE) ${bro_SUBDIR_LIBS} ${bro_PLUGIN_LIBS} ) + + # npcap/winpcap need to be loaded in delayed mode so that we can set the load path + # correctly at runtime. See https://npcap.com/guide/npcap-devguide.html#npcap-feature-native + # for why this is necessary. + if ( MSVC AND HAVE_WPCAP ) + set(zeekdeps ${zeekdeps} delayimp.lib) + set_target_properties(zeek PROPERTIES LINK_FLAGS "/DELAYLOAD:wpcap.dll") + endif() + target_link_libraries(zeek ${bro_PLUGIN_LINK_LIBS} ${zeekdeps} ${CMAKE_THREAD_LIBS_INIT} ${CMAKE_DL_LIBS}) # Export symbols from zeek executable for use by plugins diff --git a/src/main.cc b/src/main.cc index 1de09fc9e7..a64280cf6e 100644 --- a/src/main.cc +++ b/src/main.cc @@ -11,6 +11,37 @@ #ifdef _MSC_VER #include // For _O_BINARY. + +// By default, Windows only looks in the System32 directory for dlls. Npcap installs +// into System32\Npcap, so we have to add that path to the search path for DLLs or +// the process won't find it. This is annoying, but it's how the Npcap project +// recommends we do it. See https://npcap.com/guide/npcap-devguide.html#npcap-feature-native +// for further info. +static void init_npcap_dll_path() + { +#ifdef HAVE_WPCAP + BOOL(WINAPI * SetDllDirectory)(LPCTSTR); + char sysdir_name[512]; + int len; + + SetDllDirectory = (BOOL(WINAPI*)(LPCTSTR))GetProcAddress(GetModuleHandle("kernel32.dll"), + "SetDllDirectoryA"); + if ( SetDllDirectory == NULL ) + { + fprintf(stderr, "Error in SetDllDirectory"); + } + else + { + len = GetSystemDirectory(sysdir_name, 480); // be safe + if ( ! len ) + fprintf(stderr, "Error in GetSystemDirectory (%d)", GetLastError()); + strcat(sysdir_name, "\\Npcap"); + if ( SetDllDirectory(sysdir_name) == 0 ) + fprintf(stderr, "Error in SetDllDirectory(\"System32\\Npcap\")"); + } +#endif + } + #endif int main(int argc, char** argv) @@ -18,7 +49,10 @@ int main(int argc, char** argv) #ifdef _MSC_VER _setmode(_fileno(stdout), _O_BINARY); _setmode(_fileno(stderr), _O_BINARY); + + init_npcap_dll_path(); #endif + auto time_start = zeek::util::current_time(true); auto setup_result = zeek::detail::setup(argc, argv); diff --git a/zeek-config.h.in b/zeek-config.h.in index f2aa463686..e0c4229b66 100644 --- a/zeek-config.h.in +++ b/zeek-config.h.in @@ -54,6 +54,9 @@ /* Define if libpcap supports pcap_dump_open_append(). */ #cmakedefine HAVE_PCAP_DUMP_OPEN_APPEND +/* Define if the pcap library is winpcap or npcap */ +#cmakedefine HAVE_WPCAP + /* line editing & history powers */ #cmakedefine HAVE_READLINE