diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-09-19 04:14:26 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-09-19 04:14:26 +0000 |
commit | c4e8a3222648fcf22ca207f1815ebbf7cd144eeb (patch) | |
tree | 93d5c6aa93d9987680dd1adad5685e2ad698f223 /extcap | |
parent | Adding upstream version 4.2.6. (diff) | |
download | wireshark-c4e8a3222648fcf22ca207f1815ebbf7cd144eeb.tar.xz wireshark-c4e8a3222648fcf22ca207f1815ebbf7cd144eeb.zip |
Adding upstream version 4.4.0.upstream/4.4.0upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'extcap')
-rw-r--r-- | extcap/CMakeLists.txt | 81 | ||||
-rw-r--r-- | extcap/androiddump.c | 75 | ||||
-rw-r--r-- | extcap/ciscodump.c | 16 | ||||
-rw-r--r-- | extcap/dpauxmon.c | 9 | ||||
-rw-r--r-- | extcap/etl.c | 10 | ||||
-rw-r--r-- | extcap/etw_message.c | 2 | ||||
-rw-r--r-- | extcap/etw_ndiscap.c | 24 | ||||
-rw-r--r-- | extcap/etwdump.c | 4 | ||||
-rw-r--r-- | extcap/extcap-base.c | 16 | ||||
-rw-r--r-- | extcap/extcap-base.h | 2 | ||||
-rw-r--r-- | extcap/falcodump.cpp | 363 | ||||
-rw-r--r-- | extcap/randpktdump.c | 6 | ||||
-rw-r--r-- | extcap/sdjournal.c | 2 | ||||
-rw-r--r-- | extcap/ssh-base.c | 83 | ||||
-rw-r--r-- | extcap/ssh-base.h | 7 | ||||
-rw-r--r-- | extcap/sshdump.c | 10 | ||||
-rwxr-xr-x | extcap/ubxdump.py | 469 | ||||
-rw-r--r-- | extcap/udpdump.c | 4 | ||||
-rw-r--r-- | extcap/wifidump.c | 4 |
19 files changed, 999 insertions, 188 deletions
diff --git a/extcap/CMakeLists.txt b/extcap/CMakeLists.txt index 48c45164..435ea7bc 100644 --- a/extcap/CMakeLists.txt +++ b/extcap/CMakeLists.txt @@ -42,15 +42,15 @@ macro(set_extcap_executable_properties _executable) if(CMAKE_CONFIGURATION_TYPES) set_target_properties(${_executable} PROPERTIES - RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/run/extcap - RUNTIME_OUTPUT_DIRECTORY_DEBUG ${CMAKE_BINARY_DIR}/run/Debug/extcap - RUNTIME_OUTPUT_DIRECTORY_RELEASE ${CMAKE_BINARY_DIR}/run/Release/extcap - RUNTIME_OUTPUT_DIRECTORY_MINSIZEREL ${CMAKE_BINARY_DIR}/run/MinSizeRel/extcap - RUNTIME_OUTPUT_DIRECTORY_RELWITHDEBINFO ${CMAKE_BINARY_DIR}/run/RelWithDebInfo/extcap + RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/run/extcap/wireshark + RUNTIME_OUTPUT_DIRECTORY_DEBUG ${CMAKE_BINARY_DIR}/run/Debug/extcap/wireshark + RUNTIME_OUTPUT_DIRECTORY_RELEASE ${CMAKE_BINARY_DIR}/run/Release/extcap/wireshark + RUNTIME_OUTPUT_DIRECTORY_MINSIZEREL ${CMAKE_BINARY_DIR}/run/MinSizeRel/extcap/wireshark + RUNTIME_OUTPUT_DIRECTORY_RELWITHDEBINFO ${CMAKE_BINARY_DIR}/run/RelWithDebInfo/extcap/wireshark ) else() set_target_properties(${_executable} PROPERTIES - RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/run/extcap + RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/run/extcap/wireshark ) if(ENABLE_APPLICATION_BUNDLE) if(NOT CMAKE_CFG_INTDIR STREQUAL ".") @@ -83,26 +83,47 @@ endmacro() macro(set_extlog_executable_properties _executable) set_target_properties(${_executable} PROPERTIES - RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/run/extcap + LINK_FLAGS "${WS_LINK_FLAGS}" + FOLDER "Executables/Extcaps" + INSTALL_RPATH "${EXTCAP_INSTALL_RPATH}" ) - if(ENABLE_APPLICATION_BUNDLE) - if(NOT CMAKE_CFG_INTDIR STREQUAL ".") - # Xcode - set_target_properties(${_executable} PROPERTIES - RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/run/$<CONFIG>/Logray.app/Contents/MacOS/extcap - ) - else() - set_target_properties(${_executable} PROPERTIES - RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/run/Logray.app/Contents/MacOS/extcap - ) - # Create a convenience link from run/<name> to its respective - # target in the application bundle. - add_custom_target(${_executable}-symlink - COMMAND ln -s -f - Logray.app/Contents/MacOS/extcap/${_executable} - ${CMAKE_BINARY_DIR}/run/${_executable} - ) - add_dependencies(${_executable} ${_executable}-symlink) + if(MSVC) + set_target_properties(${_executable} PROPERTIES LINK_FLAGS_DEBUG "${WS_MSVC_DEBUG_LINK_FLAGS}") + endif() + + set(PROGLIST ${PROGLIST} ${_executable}) + + if(CMAKE_CONFIGURATION_TYPES) + set_target_properties(${_executable} PROPERTIES + RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/run/extcap/logray + RUNTIME_OUTPUT_DIRECTORY_DEBUG ${CMAKE_BINARY_DIR}/run/Debug/extcap/logray + RUNTIME_OUTPUT_DIRECTORY_RELEASE ${CMAKE_BINARY_DIR}/run/Release/extcap/logray + RUNTIME_OUTPUT_DIRECTORY_MINSIZEREL ${CMAKE_BINARY_DIR}/run/MinSizeRel/extcap/logray + RUNTIME_OUTPUT_DIRECTORY_RELWITHDEBINFO ${CMAKE_BINARY_DIR}/run/RelWithDebInfo/extcap/logray + ) + else() + set_target_properties(${_executable} PROPERTIES + RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/run/extcap/logray + ) + if(ENABLE_APPLICATION_BUNDLE) + if(NOT CMAKE_CFG_INTDIR STREQUAL ".") + # Xcode + set_target_properties(${_executable} PROPERTIES + RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/run/$<CONFIG>/Logray.app/Contents/MacOS/extcap + ) + else() + set_target_properties(${_executable} PROPERTIES + RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/run/Logray.app/Contents/MacOS/extcap + ) + # Create a convenience link from run/<name> to its respective + # target in the application bundle. + add_custom_target(${_executable}-symlink + COMMAND ln -s -f + Logray.app/Contents/MacOS/extcap/${_executable} + ${CMAKE_BINARY_DIR}/run/${_executable} + ) + add_dependencies(${_executable} ${_executable}-symlink) + endif() endif() endif() endmacro() @@ -365,12 +386,14 @@ if(BUILD_falcodump AND SINSP_FOUND) set_extlog_executable_properties(falcodump) target_link_libraries(falcodump ${falcodump_LIBS}) target_include_directories(falcodump SYSTEM PRIVATE ${SINSP_INCLUDE_DIRS}) - install(TARGETS falcodump RUNTIME DESTINATION ${EXTCAP_INSTALL_LIBDIR}) + if(WIN32) + # libsinsp/dumper.h includes libscap/scap_savefile_api.h, which includes + # libscap/scap_zlib.h. + target_include_directories(falcodump SYSTEM PRIVATE ${ZLIB_INCLUDE_DIR}) + endif() + install(TARGETS falcodump RUNTIME DESTINATION ${LOG_EXTCAP_INSTALL_LIBDIR}) add_dependencies(extcaps falcodump) - # XXX Hack; We need to fix this in falcosecurity-libs. - target_compile_definitions(falcodump PRIVATE HAVE_STRLCPY=1) - endif() # diff --git a/extcap/androiddump.c b/extcap/androiddump.c index 7ba573a5..9cb8f8c3 100644 --- a/extcap/androiddump.c +++ b/extcap/androiddump.c @@ -19,6 +19,7 @@ #include <string.h> #include <errno.h> #include <time.h> +#include <fcntl.h> #include <wsutil/strtoi.h> #include <wsutil/filesystem.h> #include <wsutil/privileges.h> @@ -199,7 +200,7 @@ enum { OPT_CONFIG_BT_LOCAL_TCP_PORT }; -static struct ws_option longopts[] = { +static const struct ws_option longopts[] = { EXTCAP_BASE_OPTIONS, { "help", ws_no_argument, NULL, OPT_HELP}, { "version", ws_no_argument, NULL, OPT_VERSION}, @@ -385,48 +386,40 @@ static void useSndTimeout(socket_handle_t sock) { } static void useNonBlockingConnectTimeout(socket_handle_t sock) { - int res_snd; - int res_rcv; #ifdef _WIN32 - const DWORD socket_timeout = SOCKET_RW_TIMEOUT_MS; unsigned long non_blocking = 1; - res_snd = setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, (const char *) &socket_timeout, sizeof(socket_timeout)); - res_rcv = setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (const char *) &socket_timeout, sizeof(socket_timeout)); - /* set socket to non-blocking */ ioctlsocket(sock, FIONBIO, &non_blocking); #else - const struct timeval socket_timeout = { - .tv_sec = SOCKET_RW_TIMEOUT_MS / 1000, - .tv_usec = (SOCKET_RW_TIMEOUT_MS % 1000) * 1000 - }; - - res_snd = setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, &socket_timeout, sizeof(socket_timeout)); - res_rcv = setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, &socket_timeout, sizeof(socket_timeout)); + int flags = fcntl(sock, F_GETFL); + fcntl(sock, F_SETFL, flags | O_NONBLOCK); #endif - if (res_snd != 0) - ws_debug("Can't set socket timeout, using default"); - if (res_rcv != 0) - ws_debug("Can't set socket timeout, using default"); } static void useNormalConnectTimeout(socket_handle_t sock) { + int res_snd; int res_rcv; #ifdef _WIN32 - const DWORD socket_timeout = 0; + const DWORD socket_timeout = SOCKET_RW_TIMEOUT_MS; unsigned long non_blocking = 0; + res_snd = setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, (const char *) &socket_timeout, sizeof(socket_timeout)); res_rcv = setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (const char *) &socket_timeout, sizeof(socket_timeout)); ioctlsocket(sock, FIONBIO, &non_blocking); #else + int flags = fcntl(sock, F_GETFL); + fcntl(sock, F_SETFL, flags & ~O_NONBLOCK); const struct timeval socket_timeout = { .tv_sec = SOCKET_RW_TIMEOUT_MS / 1000, .tv_usec = (SOCKET_RW_TIMEOUT_MS % 1000) * 1000 }; + res_snd = setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, &socket_timeout, sizeof(socket_timeout)); res_rcv = setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, &socket_timeout, sizeof(socket_timeout)); #endif + if (res_snd != 0) + ws_debug("Can't set socket timeout, using default"); if (res_rcv != 0) ws_debug("Can't set socket timeout, using default"); } @@ -543,6 +536,9 @@ static socket_handle_t adb_connect(const char *server_ip, unsigned short *server struct sockaddr_in server; struct sockaddr_in client; int status; +#ifndef _WIN32 + int result; +#endif int tries = 0; memset(&server, 0x0, sizeof(server)); @@ -557,12 +553,14 @@ static socket_handle_t adb_connect(const char *server_ip, unsigned short *server } useNonBlockingConnectTimeout(sock); - while (tries < SOCKET_CONNECT_TIMEOUT_TRIES) { - status = connect(sock, (struct sockaddr *) &server, (socklen_t)sizeof(server)); - tries += 1; - + status = connect(sock, (struct sockaddr *) &server, (socklen_t)sizeof(server)); #ifdef _WIN32 - if ((status == SOCKET_ERROR) && (WSAGetLastError() == WSAEWOULDBLOCK)) { + if ((status == SOCKET_ERROR) && (WSAGetLastError() == WSAEWOULDBLOCK)) { +#else + if ((status == SOCKET_ERROR) && (errno == EINPROGRESS)) { +#endif + while (tries < SOCKET_CONNECT_TIMEOUT_TRIES) { + tries += 1; struct timeval timeout = { .tv_sec = 0, .tv_usec = SOCKET_CONNECT_DELAY_US, @@ -570,15 +568,24 @@ static socket_handle_t adb_connect(const char *server_ip, unsigned short *server fd_set fdset; FD_ZERO(&fdset); FD_SET(sock, &fdset); - if ((select(0, NULL, &fdset, NULL, &timeout) != 0) && (FD_ISSET(sock, &fdset))) { + if ((select(sock+1, NULL, &fdset, NULL, &timeout) != 0) && (FD_ISSET(sock, &fdset))) { +#ifdef _WIN32 status = 0; + break; +#else + length = sizeof(result); + getsockopt(sock, SOL_SOCKET, SO_ERROR, &result, &length); + if (result == 0) { + status = 0; + } else { + ws_debug("Error connecting to ADB: <%s>", strerror(result)); + } + break; +#endif + } else { + ws_debug("Try %i: Timeout connecting to ADB", tries); } } -#endif - - if (status != SOCKET_ERROR) - break; - g_usleep(SOCKET_CONNECT_DELAY_US); } useNormalConnectTimeout(sock); @@ -607,7 +614,7 @@ static socket_handle_t adb_connect(const char *server_ip, unsigned short *server return INVALID_SOCKET; } #else - ws_debug("Cannot connect to ADB: <%s> Please check that adb daemon is running.", strerror(errno)); + ws_debug("Cannot connect to ADB: Please check that adb daemon is running."); closesocket(sock); return INVALID_SOCKET; #endif @@ -2639,13 +2646,13 @@ int main(int argc, char *argv[]) { if (ws_optarg && !*ws_optarg) logcat_text = true; else - logcat_text = (g_ascii_strncasecmp(ws_optarg, "TRUE", 4) == 0); + logcat_text = (g_ascii_strncasecmp(ws_optarg, "true", 4) == 0); break; case OPT_CONFIG_LOGCAT_IGNORE_LOG_BUFFER: if (ws_optarg == NULL || (ws_optarg && !*ws_optarg)) logcat_ignore_log_buffer = true; else - logcat_ignore_log_buffer = (g_ascii_strncasecmp(ws_optarg, "TRUE", 4) == 0); + logcat_ignore_log_buffer = (g_ascii_strncasecmp(ws_optarg, "true", 4) == 0); break; case OPT_CONFIG_LOGCAT_CUSTOM_OPTIONS: if (ws_optarg == NULL || (ws_optarg && *ws_optarg == '\0')) { @@ -2673,7 +2680,7 @@ int main(int argc, char *argv[]) { } break; case OPT_CONFIG_BT_FORWARD_SOCKET: - bt_forward_socket = (g_ascii_strncasecmp(ws_optarg, "TRUE", 4) == 0); + bt_forward_socket = (g_ascii_strncasecmp(ws_optarg, "true", 4) == 0); break; case OPT_CONFIG_BT_LOCAL_IP: bt_local_ip = ws_optarg; diff --git a/extcap/ciscodump.c b/extcap/ciscodump.c index f9a61099..e01669cc 100644 --- a/extcap/ciscodump.c +++ b/extcap/ciscodump.c @@ -110,9 +110,9 @@ enum { static char prompt_str[SSH_READ_BLOCK_SIZE + 1]; static int32_t prompt_len = -1; CISCO_SW_TYPE global_sw_type = CISCO_UNKNOWN; -static bool send_output_quit = false; /* IOS XE 17: send quit during output */ +static bool send_output_quit; /* IOS XE 17: send quit during output */ -static struct ws_option longopts[] = { +static const struct ws_option longopts[] = { EXTCAP_BASE_OPTIONS, { "help", ws_no_argument, NULL, OPT_HELP}, { "version", ws_no_argument, NULL, OPT_VERSION}, @@ -162,7 +162,7 @@ static char* interfaces_list_to_filter(GSList* interfaces, unsigned int remote_p g_string_append_printf(filter, ", permit ip any any"); } - return g_string_free(filter, false); + return g_string_free(filter, FALSE); } static char* local_interfaces_to_filter(const unsigned int remote_port) @@ -182,7 +182,7 @@ static int read_output_bytes_any(ssh_channel channel, int bytes, char* outbuf) int total; int bytes_read; - total = (bytes > 0 ? bytes : G_MAXINT); + total = (bytes > 0 ? bytes : INT_MAX); bytes_read = 0; while(ssh_channel_read_timeout(channel, &chr, 1, 0, CISCODUMP_READ_TIMEOUT_MSEC) > 0 && bytes_read < total) { @@ -205,7 +205,7 @@ static int read_output_bytes(ssh_channel channel, int bytes, char* outbuf) int total; int bytes_read; - total = (bytes > 0 ? bytes : G_MAXINT); + total = (bytes > 0 ? bytes : INT_MAX); bytes_read = 0; while(ssh_channel_read_timeout(channel, &chr, 1, 0, CISCODUMP_READ_TIMEOUT_MSEC) > 0 && bytes_read < total) { @@ -222,7 +222,7 @@ static int read_output_bytes(ssh_channel channel, int bytes, char* outbuf) /* Reads input to buffer and parses EOL * If line is NULL, just received count of characters in len is calculated * It returns: - * READ_LINE_ERROR - any ssh error occured + * READ_LINE_ERROR - any ssh error occurred * READ_LINE_EOLN - EOLN found, line/len contains \0 terminated string * READ_LINE_TIMEOUT - reading ended with timeout, line/len contains \0 terminate prompt * READ_LINE_TOO_LONG - buffer is full with no EOLN nor PROMPT found, line is filled with NOT \0 terminated data @@ -264,7 +264,7 @@ static int ssh_channel_read_line_timeout(ssh_channel channel, char *line, int *l /* Reads input to buffer and parses EOL or prompt_str PROMPT * It returns: - * READ_PROMPT_ERROR - any ssh error occured + * READ_PROMPT_ERROR - any ssh error occurred * READ_PROMPT_EOLN - EOLN found, line/len contains \0 terminated string * READ_PROMPT_PROMPT - reading ended and it ends with PROMPT, line/len contains \0 terminate prompt * READ_PROMPT_TOO_LONG - buffer is full with no EOLN nor PROMPT found, line is filled with NOT \0 terminated data @@ -2491,7 +2491,7 @@ int main(int argc, char *argv[]) ws_warning("ERROR: count of packets must be specified (--remote-count)"); goto end; } - ssh_params->debug = extcap_conf->debug; + ssh_params_set_log_level(ssh_params, extcap_conf->debug); ret = ssh_open_remote_connection(ssh_params, remote_interface, remote_filter, count, extcap_conf->fifo); } else { diff --git a/extcap/dpauxmon.c b/extcap/dpauxmon.c index 68280a9f..e025b596 100644 --- a/extcap/dpauxmon.c +++ b/extcap/dpauxmon.c @@ -17,6 +17,7 @@ #include "extcap-base.h" +#include <wsutil/array.h> #include <wsutil/strtoi.h> #include <wsutil/filesystem.h> #include <wsutil/privileges.h> @@ -41,7 +42,7 @@ #define DPAUXMON_VERSION_MINOR "1" #define DPAUXMON_VERSION_RELEASE "0" -FILE* pcap_fp = NULL; +FILE* pcap_fp; enum { EXTCAP_BASE_OPTIONS_ENUM, @@ -50,7 +51,7 @@ enum { OPT_INTERFACE_ID, }; -static struct ws_option longopts[] = { +static const struct ws_option longopts[] = { EXTCAP_BASE_OPTIONS, /* Generic application options */ { "help", ws_no_argument, NULL, OPT_HELP}, @@ -387,12 +388,10 @@ static struct genl_cmd cmds[] = { }, }; -#define ARRAY_SIZE(X) (sizeof(X) / sizeof((X)[0])) - static struct genl_ops ops = { .o_name = "dpauxmon", .o_cmds = cmds, - .o_ncmds = ARRAY_SIZE(cmds), + .o_ncmds = array_length(cmds), }; struct nl_sock *sock; diff --git a/extcap/etl.c b/extcap/etl.c index 78f2bf22..3fae1232 100644 --- a/extcap/etl.c +++ b/extcap/etl.c @@ -59,7 +59,7 @@ enum { OPT_LEVEL, }; -static struct ws_option longopts[] = { +static const struct ws_option longopts[] = { { "p", ws_required_argument, NULL, OPT_PROVIDER}, { "k", ws_required_argument, NULL, OPT_KEYWORD}, { "l", ws_required_argument, NULL, OPT_LEVEL}, @@ -72,12 +72,12 @@ typedef struct _PROVIDER_FILTER { UCHAR Level; } PROVIDER_FILTER; -char g_err_info[FILENAME_MAX] = { 0 }; +char g_err_info[FILENAME_MAX]; int g_err = ERROR_SUCCESS; -static wtap_dumper* g_pdh = NULL; +static wtap_dumper* g_pdh; extern ULONGLONG g_num_events; -static PROVIDER_FILTER g_provider_filters[32] = { 0 }; -static BOOL g_is_live_session = false; +static PROVIDER_FILTER g_provider_filters[32]; +static BOOL g_is_live_session; static void WINAPI event_callback(PEVENT_RECORD ev); void etw_dump_write_opn_event(PEVENT_RECORD ev, ULARGE_INTEGER timestamp); diff --git a/extcap/etw_message.c b/extcap/etw_message.c index c99eaea8..66364b83 100644 --- a/extcap/etw_message.c +++ b/extcap/etw_message.c @@ -13,7 +13,7 @@ #include "etw_message.h" #include <wsutil/wslog.h> -ULONGLONG g_num_events = 0; +ULONGLONG g_num_events; VOID format_message(WCHAR* lpszMessage, PROPERTY_KEY_VALUE* propArray, DWORD dwPropertyCount, WCHAR* lpszOutBuffer, DWORD dwOutBufferCount) { diff --git a/extcap/etw_ndiscap.c b/extcap/etw_ndiscap.c index d7aab65d..56fa92ec 100644 --- a/extcap/etw_ndiscap.c +++ b/extcap/etw_ndiscap.c @@ -87,12 +87,12 @@ static const char* DOT11_PHY_TYPE_NAMES[] = { "802.11ax" // dot11_phy_type_he = 10 }; -unsigned long long NumFramesConverted = 0; +unsigned long long NumFramesConverted; char AuxFragBuf[MAX_PACKET_SIZE] = {0}; -unsigned long AuxFragBufOffset = 0; +unsigned long AuxFragBufOffset; DOT11_EXTSTA_RECV_CONTEXT PacketMetadata; -BOOLEAN AddWlanMetadata = false; +BOOLEAN AddWlanMetadata; typedef struct _NDIS_NET_BUFFER_LIST_8021Q_INFO { union { @@ -135,7 +135,7 @@ typedef struct _VMSWITCH_PACKET_FRAGMENT { short VlanId; } VMSWITCH_PACKET_FRAGMENT, *PVMSWITCH_PACKET_FRAGMENT; -BOOLEAN CurrentPacketIsVMSwitchPacketFragment = false; +BOOLEAN CurrentPacketIsVMSwitchPacketFragment; VMSWITCH_PACKET_FRAGMENT VMSwitchPacketFragment; struct INTERFACE { @@ -151,8 +151,8 @@ struct INTERFACE { }; #define IFACE_HT_SIZE 100 -struct INTERFACE* InterfaceHashTable[IFACE_HT_SIZE] = {0}; -unsigned long NumInterfaces = 0; +struct INTERFACE* InterfaceHashTable[IFACE_HT_SIZE]; +unsigned long NumInterfaces; void wtap_etl_rec_dump(char* etl_record, ULONG total_packet_length, ULONG original_packet_length, unsigned int interface_id, BOOLEAN is_inbound, ULARGE_INTEGER timestamp, int pkt_encap, char* comment, unsigned short comment_length); void wtap_etl_add_interface(int pkt_encap, char* interface_name, unsigned short interface_name_length, char* interface_desc, unsigned short interface_desc_length); @@ -316,7 +316,7 @@ struct INTERFACE* AddInterface(PEVENT_RECORD ev, unsigned long LowerIfIndex, uns switch (NewIface->PktEncapType) { case WTAP_ENCAP_ETHERNET: if (NewIface->IsVMNic) { - printf("IF: medium=%s\tID=%u\tIfIndex=%u\tVlanID=%i", + printf("IF: medium=%s\tID=%lu\tIfIndex=%lu\tVlanID=%i", NewIface->VMNic.SourceNicType, NewIface->PcapNgIfIndex, NewIface->VMNic.SourcePortId, @@ -338,18 +338,18 @@ struct INTERFACE* AddInterface(PEVENT_RECORD ev, unsigned long LowerIfIndex, uns } break; case WTAP_ENCAP_IEEE_802_11: - printf("IF: medium=wifi ID=%u\tIfIndex=%u", NewIface->PcapNgIfIndex, NewIface->LowerIfIndex); + printf("IF: medium=wifi ID=%lu\tIfIndex=%lu", NewIface->PcapNgIfIndex, NewIface->LowerIfIndex); StringCchPrintfA(IfName, IF_STRING_MAX_SIZE, "wifi:%lu", NewIface->LowerIfIndex); break; case WTAP_ENCAP_RAW_IP: - printf("IF: medium=mbb ID=%u\tIfIndex=%u", NewIface->PcapNgIfIndex, NewIface->LowerIfIndex); + printf("IF: medium=mbb ID=%lu\tIfIndex=%lu", NewIface->PcapNgIfIndex, NewIface->LowerIfIndex); StringCchPrintfA(IfName, IF_STRING_MAX_SIZE, "mbb:%lu", NewIface->LowerIfIndex); break; } StringCchLengthA(IfName, IF_STRING_MAX_SIZE, &IfNameLength); if (NewIface->LowerIfIndex != NewIface->MiniportIfIndex) { - printf("\t(LWF over IfIndex %u)", NewIface->MiniportIfIndex); + printf("\t(LWF over IfIndex %lu)", NewIface->MiniportIfIndex); StringCchPrintfA(IfDesc, IF_STRING_MAX_SIZE, "LWF over IfIndex %lu", NewIface->MiniportIfIndex); StringCchLengthA(IfDesc, IF_STRING_MAX_SIZE, &IfDescLength); } @@ -635,12 +635,12 @@ void etw_dump_write_ndiscap_event(PEVENT_RECORD ev, ULARGE_INTEGER timestamp) } if (Err != NO_ERROR) { - printf("Failed converting comment to string with error: %u\n", Err); + printf("Failed converting comment to string with error: %d\n", Err); } else { Err = StringCchLengthA(Comment, COMMENT_MAX_SIZE, &CommentLength); if (Err != NO_ERROR) { - printf("Failed getting length of comment string with error: %u\n", Err); + printf("Failed getting length of comment string with error: %d\n", Err); CommentLength = 0; memset(Comment, 0, COMMENT_MAX_SIZE); } diff --git a/extcap/etwdump.c b/extcap/etwdump.c index ea803a70..60189e1c 100644 --- a/extcap/etwdump.c +++ b/extcap/etwdump.c @@ -42,7 +42,7 @@ enum { OPT_PARAMS }; -static struct ws_option longopts[] = { +static const struct ws_option longopts[] = { EXTCAP_BASE_OPTIONS, { "help", ws_no_argument, NULL, OPT_HELP}, { "version", ws_no_argument, NULL, OPT_VERSION}, @@ -52,7 +52,7 @@ static struct ws_option longopts[] = { { 0, 0, 0, 0 } }; -int g_include_undecidable_event = false; +int g_include_undecidable_event; void SignalHandler(_U_ int signal) { diff --git a/extcap/extcap-base.c b/extcap/extcap-base.c index 13d42b7a..f30f2f13 100644 --- a/extcap/extcap-base.c +++ b/extcap/extcap-base.c @@ -44,12 +44,12 @@ typedef struct _extcap_option { char * optdesc; } extcap_option_t; -static FILE *custom_log = NULL; +static FILE *custom_log; /* used to inform to extcap application that end of application is requested */ -bool extcap_end_application = false; +bool extcap_end_application; /* graceful shutdown callback, can be null */ -void (*extcap_graceful_shutdown_cb)(void) = NULL; +void (*extcap_graceful_shutdown_cb)(void); static void extcap_init_log_file(const char *filename); @@ -184,9 +184,7 @@ uint8_t extcap_base_parse_options(extcap_parameters * extcap, int result, char * /* Invalid log level string. */ ret = 0; } - else if (level <= LOG_LEVEL_DEBUG) { - extcap->debug = true; - } + extcap->debug = level; break; case EXTCAP_OPT_LOG_FILE: extcap_init_log_file(optargument); @@ -234,7 +232,7 @@ static void extcap_iface_print(void * data, void * userdata _U_) printf ("\n"); } -static int extcap_iface_compare(gconstpointer a, gconstpointer b) +static int extcap_iface_compare(const void * a, const void * b) { const extcap_interface * iface_a = (const extcap_interface *)a; @@ -278,7 +276,7 @@ static int extcap_iface_listall(extcap_parameters * extcap, uint8_t list_ifs) uint8_t extcap_base_handle_interface(extcap_parameters * extcap) { /* A fifo must be provided for capture */ - if (extcap->capture && (extcap->fifo == NULL || strlen(extcap->fifo) <= 0)) { + if (extcap->capture && (extcap->fifo == NULL || strlen(extcap->fifo) == 0)) { extcap->capture = 0; ws_error("Extcap Error: No FIFO pipe provided"); return 0; @@ -410,7 +408,7 @@ void extcap_cmdline_debug(char** ar, const unsigned n) for (i = 0; i < n; i++) g_string_append_printf(cmdline, "%s ", ar[i]); ws_debug("%s", cmdline->str); - g_string_free(cmdline, true); + g_string_free(cmdline, TRUE); } /* diff --git a/extcap/extcap-base.h b/extcap/extcap-base.h index 4bbfb1b4..b0fa872b 100644 --- a/extcap/extcap-base.h +++ b/extcap/extcap-base.h @@ -81,7 +81,7 @@ typedef struct _extcap_parameters char * help_header; GList * help_options; - bool debug; + enum ws_log_level debug; } extcap_parameters; /* used to inform to extcap application that end of application is requested */ diff --git a/extcap/falcodump.cpp b/extcap/falcodump.cpp index b8710644..bb34652f 100644 --- a/extcap/falcodump.cpp +++ b/extcap/falcodump.cpp @@ -27,9 +27,11 @@ #include "config.h" -#include <sinsp.h> +#include <libsinsp/sinsp.h> #include <plugin_manager.h> +#include <scap_engines.h> + #define WS_LOG_DOMAIN "falcodump" #include <extcap/extcap-base.h> @@ -57,6 +59,10 @@ enum { OPT_HELP, OPT_VERSION, OPT_PLUGIN_API_VERSION, +#if defined(HAS_ENGINE_KMOD) || defined(HAS_ENGINE_MODERN_BPF) + OPT_INCLUDE_CAPTURE_PROCESSES, + OPT_INCLUDE_SWITCH_CALLS, +#endif OPT_PLUGIN_SOURCE, OPT_SCHEMA_PROPERTIES_START, }; @@ -77,6 +83,13 @@ struct config_properties { std::string current_value; }; +#if defined(HAS_ENGINE_KMOD) || defined(HAS_ENGINE_MODERN_BPF) +struct syscall_configuration { + bool include_capture_processes; + bool include_switch_calls; +}; +#endif + struct plugin_configuration { std::vector<struct config_properties> property_list; @@ -133,14 +146,14 @@ fgetline(char *buf, int size, FILE *fp) static const size_t MAX_AWS_LINELEN = 2048; void print_cloudtrail_aws_profile_config(int arg_num, const char *display, const char *description) { char buf[MAX_AWS_LINELEN]; - char profile[MAX_AWS_LINELEN]; + char profile_name[MAX_AWS_LINELEN]; FILE *aws_fp; std::set<std::string>profiles; // Look in files as specified in https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-envvars.html char *cred_path = g_strdup(g_getenv("AWS_SHARED_CREDENTIALS_FILE")); if (cred_path == NULL) { - cred_path = g_build_filename(g_get_home_dir(), ".aws", "credentials", (gchar *)NULL); + cred_path = g_build_filename(g_get_home_dir(), ".aws", "credentials", (char *)NULL); } aws_fp = ws_fopen(cred_path, "r"); @@ -148,11 +161,11 @@ void print_cloudtrail_aws_profile_config(int arg_num, const char *display, const if (aws_fp != NULL) { while (fgetline(buf, sizeof(buf), aws_fp) >= 0) { - if (sscanf(buf, "[%2047[^]]s]", profile) == 1) { - if (strcmp(profile, "default") == 0) { + if (sscanf(buf, "[%2047[^]]s]", profile_name) == 1) { + if (strcmp(profile_name, "default") == 0) { continue; } - profiles.insert(profile); + profiles.insert(profile_name); } } fclose(aws_fp); @@ -160,7 +173,7 @@ void print_cloudtrail_aws_profile_config(int arg_num, const char *display, const char *conf_path = g_strdup(g_getenv("AWS_CONFIG_FILE")); if (conf_path == NULL) { - conf_path = g_build_filename(g_get_home_dir(), ".aws", "config", (gchar *)NULL); + conf_path = g_build_filename(g_get_home_dir(), ".aws", "config", (char *)NULL); } aws_fp = ws_fopen(conf_path, "r"); @@ -168,11 +181,11 @@ void print_cloudtrail_aws_profile_config(int arg_num, const char *display, const if (aws_fp != NULL) { while (fgetline(buf, sizeof(buf), aws_fp) >= 0) { - if (sscanf(buf, "[profile %2047[^]]s]", profile) == 1) { - if (strcmp(profile, "default") == 0) { + if (sscanf(buf, "[profile %2047[^]]s]", profile_name) == 1) { + if (strcmp(profile_name, "default") == 0) { continue; } - profiles.insert(profile); + profiles.insert(profile_name); } } fclose(aws_fp); @@ -223,6 +236,7 @@ void print_cloudtrail_aws_region_config(int arg_num, const char *display, const "ap-southeast-3", "ap-southeast-4", "ca-central-1", + "ca-west-1", "eu-central-1", "eu-central-2", "eu-north-1", @@ -231,6 +245,7 @@ void print_cloudtrail_aws_region_config(int arg_num, const char *display, const "eu-west-1", "eu-west-2", "eu-west-3", + "il-central-1", "me-central-1", "me-south-1", "sa-east-1", @@ -277,8 +292,10 @@ static void load_plugins(sinsp &inspector) { WS_DIR *dir; WS_DIRENT *file; char *plugin_paths[] = { - g_build_filename(get_plugins_dir_with_version(), "falco", NULL), - g_build_filename(get_plugins_pers_dir_with_version(), "falco", NULL) + // XXX Falco plugins should probably be installed in a path that reflects + // the Falco version or its plugin API version. + g_build_filename(get_plugins_dir(), "falco", NULL), + g_build_filename(get_plugins_pers_dir(), "falco", NULL) }; for (size_t idx = 0; idx < 2; idx++) { @@ -522,7 +539,7 @@ const std::pair<const std::string,bool> get_schema_properties(const std::string default_value, }; property_list.push_back(properties); - g_free((gpointer)call); + g_free((void *)call); idx += prop_tokens; opt_idx++; } @@ -700,6 +717,10 @@ static const std::vector<ws_option> get_longopts(const std::map<std::string, str { "help", ws_no_argument, NULL, OPT_HELP}, { "version", ws_no_argument, NULL, OPT_VERSION}, { "plugin-api-version", ws_no_argument, NULL, OPT_PLUGIN_API_VERSION}, +#if defined(HAS_ENGINE_KMOD) || defined(HAS_ENGINE_MODERN_BPF) + { "include-capture-processes", ws_required_argument, NULL, OPT_INCLUDE_CAPTURE_PROCESSES }, + { "include-switch-calls", ws_required_argument, NULL, OPT_INCLUDE_SWITCH_CALLS }, +#endif { "plugin-source", ws_required_argument, NULL, OPT_PLUGIN_SOURCE }, { 0, 0, 0, 0} }; @@ -708,8 +729,8 @@ static const std::vector<ws_option> get_longopts(const std::map<std::string, str longopts.push_back(base_longopts[idx]); } for (const auto &it : plugin_configs) { - const struct plugin_configuration plugin_configs = it.second; - for (const auto &prop : plugin_configs.property_list) { + const struct plugin_configuration plugin_config = it.second; + for (const auto &prop : plugin_config.property_list) { ws_option option = { g_strdup(prop.option.c_str()), ws_required_argument, NULL, prop.option_index }; longopts.push_back(option); } @@ -718,8 +739,111 @@ static const std::vector<ws_option> get_longopts(const std::map<std::string, str return longopts; } +#if defined(HAS_ENGINE_KMOD) || defined(HAS_ENGINE_MODERN_BPF) +static bool +get_bool_value(const char *bool_str) +{ + if (!bool_str) { + return false; + } + switch (bool_str[0]) { + case 'f': + case 'F': + case '0': + return false; + default: + return true; + } +} + // Show the configuration for a given plugin/interface. -static int show_config(const std::string &interface, const struct plugin_configuration &plugin_config) +static int show_syscall_config(void) +{ + printf( + "arg {number=0}" + "{call=--include-capture-processes}" + "{display=Include capture processes}" + "{type=boolean}" + "{tooltip=Include system calls made by any capture processes (falcodump, dumpcap, and Logray)}" + "{required=false}" + "{group=Capture}\n" + + "arg {number=1}" + "{call=--include-switch-calls}" + "{display=Include \"switch\" calls}" + "{type=boolean}" + "{tooltip=Include \"switch\" system calls}" + "{required=false}" + "{group=Capture}\n" + + "value {arg=0}{value=1}\n" + ); + + return EXIT_SUCCESS; +} + +#include <fstream> +#include <iostream> +static const std::string syscall_capture_filter(const struct syscall_configuration &syscall_config, const char *capture_filter) +{ + if (syscall_config.include_capture_processes && syscall_config.include_switch_calls) { + if (capture_filter) { + return std::string(capture_filter); + } else { + return std::string(); + } + } + + std::string filter; + + if (capture_filter) { + filter = "(" + std::string(capture_filter) + ") and ("; + } + + if (!syscall_config.include_capture_processes) { + // We want to exclude Logray and any of its children, including + // this one (falcodump). + + std::string pid, comm, _s, ppid; + + // Exclude this process only at a minimum. + std::ifstream stat_stream("/proc/self/stat"); + stat_stream >> pid >> comm >> _s >> ppid; + std::string process_filter = "proc.pid != " + pid; + if (comm != "(falcodump)") { + ws_warning("Our process is named %s, not falcodump", comm.c_str()); + } + stat_stream.close(); + + // If our parent is Logray, exclude it and its direct children. + std::ifstream pstat_stream("/proc/" + ppid + "/stat"); + pstat_stream >> _s >> comm; + if (comm == "(logray)") { + // XXX Use proc.apid instead? + process_filter = "proc.pid != " + ppid + " and proc.ppid != " + ppid; + } + pstat_stream.close(); + + filter += process_filter; + } + + if (!syscall_config.include_switch_calls) { + if (!syscall_config.include_capture_processes) { + filter += " and "; + } + filter += "evt.type != switch"; + } + + if (capture_filter) { + filter += ")"; + } + + return filter; +} +#endif // HAS_ENGINE_KMOD || HAS_ENGINE_MODERN_BPF + +// Show the configuration for a given plugin/interface. +static int show_plugin_config(const std::string &interface, const struct plugin_configuration &plugin_config) { unsigned arg_num = 0; // char* plugin_filter; @@ -755,7 +879,7 @@ static int show_config(const std::string &interface, const struct plugin_configu print_cloudtrail_aws_region_config(arg_num, properties.display.c_str(), properties.description.c_str()); } else { printf( - "arg {number=%d}" + "arg {number=%u}" "{call=--%s}" "{display=%s}" "{type=%s}" @@ -767,7 +891,7 @@ static int show_config(const std::string &interface, const struct plugin_configu if (properties.enum_values.size() > 0) { for (const auto &enum_val : properties.enum_values) { printf( - "value {arg=%d}" + "value {arg=%u}" "{value=%s}" "{display=%s}" "%s" @@ -791,6 +915,9 @@ int main(int argc, char **argv) int ret = EXIT_FAILURE; extcap_parameters* extcap_conf = g_new0(extcap_parameters, 1); std::map<std::string, struct plugin_configuration> plugin_configs; +#if defined(HAS_ENGINE_KMOD) || defined(HAS_ENGINE_MODERN_BPF) + struct syscall_configuration syscall_config = {}; +#endif char* help_url; char* help_header = NULL; sinsp inspector; @@ -815,16 +942,41 @@ int main(int argc, char **argv) g_free(configuration_init_error); } + // Plain eBPF requires extra configuration, so probe for kmod and modern BPF support only for now. +#ifdef HAS_ENGINE_KMOD + try { + inspector.open_kmod(); + extcap_base_register_interface(extcap_conf, KMOD_ENGINE, "System calls via kernel module", 147, "USER0"); + } catch (sinsp_exception &e) { + ws_warning("Unable to open kmod: %s", e.what()); + } + inspector.close(); +#endif +#ifdef HAS_ENGINE_MODERN_BPF + try { + inspector.open_modern_bpf(); + extcap_base_register_interface(extcap_conf, MODERN_BPF_ENGINE, "System calls via modern eBPF", 147, "USER0"); + } catch (sinsp_exception &e) { + ws_warning("Unable to open kmod: %s", e.what()); + } + inspector.close(); +#endif + load_plugins(inspector); - if (!get_source_plugins(inspector, plugin_configs)) { - goto end; + if (get_source_plugins(inspector, plugin_configs)) { + for (auto iter = plugin_configs.begin(); iter != plugin_configs.end(); ++iter) { + // Where we're going we don't need DLTs, so use USER0 (147). + // Additional info available via plugin->description() and plugin->event_source(). + extcap_base_register_interface(extcap_conf, iter->first.c_str(), "Falco plugin", 147, "USER0"); + } + } else { + ws_warning("Unable to load plugins."); } - for (auto iter = plugin_configs.begin(); iter != plugin_configs.end(); ++iter) { - // We don't have a Falco source plugins DLT, so use USER0 (147). - // Additional info available via plugin->description() and plugin->event_source(). - extcap_base_register_interface(extcap_conf, iter->first.c_str(), "Falco plugin", 147, "USER0"); + if (g_list_length(extcap_conf->interfaces) < 1) { + ws_debug("No source plugins found."); + goto end; } help_url = data_file_url("falcodump.html"); @@ -834,12 +986,14 @@ int main(int argc, char **argv) help_header = ws_strdup_printf( " %s --extcap-interfaces\n" + " %s --extcap-interface=%s --extcap-capture-filter=<filter>\n" " %s --extcap-interface=%s --extcap-dlts\n" " %s --extcap-interface=%s --extcap-config\n" - " %s --extcap-interface=%s --fifo=<filename> --capture --plugin-source=<source url>\n", + " %s --extcap-interface=%s --fifo=<filename> --capture --plugin-source=<source url> [--extcap-capture-filter=<filter>]\n", argv[0], argv[0], FALCODUMP_PLUGIN_PLACEHOLDER, argv[0], FALCODUMP_PLUGIN_PLACEHOLDER, + argv[0], FALCODUMP_PLUGIN_PLACEHOLDER, argv[0], FALCODUMP_PLUGIN_PLACEHOLDER); extcap_help_add_header(extcap_conf, help_header); g_free(help_header); @@ -847,10 +1001,12 @@ int main(int argc, char **argv) extcap_help_add_option(extcap_conf, "--version", "print the version"); extcap_help_add_option(extcap_conf, "--plugin-api-version", "print the Falco plugin API version"); extcap_help_add_option(extcap_conf, "--plugin-source", "plugin source URL"); + extcap_help_add_option(extcap_conf, "--include-capture-processes", "Include capture processes"); + extcap_help_add_option(extcap_conf, "--include-switch-calls", "Include \"switch\" calls"); for (const auto &it : plugin_configs) { - const struct plugin_configuration plugin_configs = it.second; - for (const auto &prop : plugin_configs.property_list) { + const struct plugin_configuration plugin_config = it.second; + for (const auto &prop : plugin_config.property_list) { if (prop.option_index < OPT_SCHEMA_PROPERTIES_START) { continue; } @@ -886,6 +1042,16 @@ int main(int argc, char **argv) ret = EXIT_SUCCESS; goto end; +#if defined(HAS_ENGINE_KMOD) || defined(HAS_ENGINE_MODERN_BPF) + case OPT_INCLUDE_CAPTURE_PROCESSES: + syscall_config.include_capture_processes = get_bool_value(ws_optarg); + break; + + case OPT_INCLUDE_SWITCH_CALLS: + syscall_config.include_switch_calls = get_bool_value(ws_optarg); + break; +#endif + case OPT_PLUGIN_SOURCE: plugin_source = ws_optarg; break; @@ -924,60 +1090,142 @@ int main(int argc, char **argv) extcap_cmdline_debug(argv, argc); - if (plugin_configs.size() < 1) { - ws_warning("No source plugins found."); - goto end; - } - if (extcap_base_handle_interface(extcap_conf)) { ret = EXIT_SUCCESS; goto end; } if (extcap_conf->show_config) { - ret = show_config(extcap_conf->interface, plugin_configs.at(extcap_conf->interface)); +#ifdef HAS_ENGINE_KMOD + if (strcmp(extcap_conf->interface, KMOD_ENGINE) == 0) + { + ret = show_syscall_config(); + } + else +#endif +#ifdef HAS_ENGINE_MODERN_BPF + if (strcmp(extcap_conf->interface, MODERN_BPF_ENGINE) == 0) + { + ret = show_syscall_config(); + } + else +#endif + { + ret = show_plugin_config(extcap_conf->interface, plugin_configs.at(extcap_conf->interface)); + } goto end; } - if (extcap_conf->capture) { - if (plugin_source.empty()) { - ws_warning("Missing or invalid parameter: --plugin-source"); - goto end; + if (extcap_conf->capture || extcap_conf->capture_filter) { + bool builtin_capture = false; + +#ifdef DEBUG_SINSP + inspector.set_debug_mode(true); + inspector.set_log_stderr(); +#endif + +#ifdef HAS_ENGINE_KMOD + if (strcmp(extcap_conf->interface, KMOD_ENGINE) == 0) + { + try { + inspector.open_kmod(); + builtin_capture = true; + } catch (sinsp_exception &e) { + ws_warning("Unable to open " KMOD_ENGINE ": %s", e.what()); + } + } + else +#endif +#ifdef HAS_ENGINE_MODERN_BPF + if (strcmp(extcap_conf->interface, MODERN_BPF_ENGINE) == 0) + { + try { + inspector.open_modern_bpf(); + builtin_capture = true; + } catch (sinsp_exception &e) { + ws_warning("Unable to open " MODERN_BPF_ENGINE ": %s", e.what()); + } } + else +#endif + { + if (plugin_source.empty()) { + if (extcap_conf->capture) { + ws_warning("Missing or invalid parameter: --plugin-source"); + } else { + // XXX Can we bypass this somehow? + fprintf(stdout, "Validating a capture filter requires a plugin source"); + } + goto end; + } - std::shared_ptr<sinsp_plugin> plugin_interface; - const auto plugin_manager = inspector.get_plugin_manager(); - for (auto &plugin : plugin_manager->plugins()) { - if (plugin->name() == extcap_conf->interface) { - plugin_interface = plugin; + std::shared_ptr<sinsp_plugin> plugin_interface; + const auto plugin_manager = inspector.get_plugin_manager(); + for (auto &plugin : plugin_manager->plugins()) { + if (plugin->name() == extcap_conf->interface) { + plugin_interface = plugin; + } + } + + if (plugin_interface == nullptr) { + ws_warning("Unable to find interface %s", extcap_conf->interface); + goto end; + } + + try { + std::string init_err; + plugin_interface->init(plugin_configs[extcap_conf->interface].json_config().c_str(), init_err); + if (!init_err.empty()) { + ws_warning("%s", init_err.c_str()); + goto end; + } + inspector.open_plugin(extcap_conf->interface, plugin_source); + // scap_dump_open handles "-" + } catch (sinsp_exception &e) { + ws_warning("%s", e.what()); + goto end; } } - if (plugin_interface == nullptr) { - ws_warning("Unable to find interface %s", extcap_conf->interface); + if (!extcap_conf->capture) { + // Check our filter syntax + try { + sinsp_filter_compiler compiler(&inspector, extcap_conf->capture_filter); + compiler.compile(); + } catch (sinsp_exception &e) { + fprintf(stdout, "%s", e.what()); + goto end; + } + ret = EXIT_SUCCESS; goto end; } sinsp_dumper dumper; -#ifdef DEBUG_SINSP - inspector.set_debug_mode(true); - inspector.set_log_stderr(); -#endif try { - std::string init_err; - plugin_interface->init(plugin_configs[extcap_conf->interface].json_config().c_str(), init_err); - if (!init_err.empty()) { - ws_warning("%s", init_err.c_str()); - goto end; - } - inspector.open_plugin(extcap_conf->interface, plugin_source); - // scap_dump_open handles "-" dumper.open(&inspector, extcap_conf->fifo, false); } catch (sinsp_exception &e) { dumper.close(); ws_warning("%s", e.what()); goto end; } + +#if defined(HAS_ENGINE_KMOD) || defined(HAS_ENGINE_MODERN_BPF) + std::string capture_filter = syscall_capture_filter(syscall_config, extcap_conf->capture_filter); + if (!capture_filter.empty()) { + ws_debug("Setting filter %s\n", capture_filter.c_str()); + try { + inspector.set_filter(capture_filter); + } catch (sinsp_exception &e) { + fprintf(stdout, "%s", e.what()); + goto end; + } + } +#endif + + if (builtin_capture) { + inspector.start_capture(); + } + sinsp_evt *evt; ws_noisy("Starting capture loop."); while (!extcap_end_application) { @@ -1002,6 +1250,9 @@ int main(int argc, char **argv) } } ws_noisy("Closing dumper and inspector."); + if (builtin_capture) { + inspector.stop_capture(); + } dumper.close(); inspector.close(); ret = EXIT_SUCCESS; diff --git a/extcap/randpktdump.c b/extcap/randpktdump.c index 6d518350..5ee2eb8d 100644 --- a/extcap/randpktdump.c +++ b/extcap/randpktdump.c @@ -43,7 +43,7 @@ enum { OPT_TYPE }; -static struct ws_option longopts[] = { +static const struct ws_option longopts[] = { EXTCAP_BASE_OPTIONS, { "help", ws_no_argument, NULL, OPT_HELP}, { "version", ws_no_argument, NULL, OPT_VERSION}, @@ -140,8 +140,8 @@ int main(int argc, char *argv[]) uint16_t maxbytes = 5000; uint64_t count = 1000; uint64_t packet_delay_ms = 0; - int random_type = false; - int all_random = false; + bool random_type = false; + bool all_random = false; char* type = NULL; int produce_type = -1; int file_type_subtype = WTAP_FILE_TYPE_SUBTYPE_UNKNOWN; diff --git a/extcap/sdjournal.c b/extcap/sdjournal.c index 879fea87..e2f8ba81 100644 --- a/extcap/sdjournal.c +++ b/extcap/sdjournal.c @@ -50,7 +50,7 @@ enum { OPT_START_FROM }; -static struct ws_option longopts[] = { +static const struct ws_option longopts[] = { EXTCAP_BASE_OPTIONS, { "help", ws_no_argument, NULL, OPT_HELP}, { "version", ws_no_argument, NULL, OPT_VERSION}, diff --git a/extcap/ssh-base.c b/extcap/ssh-base.c index be9717c5..b52dee5d 100644 --- a/extcap/ssh-base.c +++ b/extcap/ssh-base.c @@ -60,9 +60,41 @@ "hmac-sha1-etm@openssh.com,hmac-sha1" #endif -static void extcap_log(int priority _U_, const char *function, const char *buffer, void *userdata _U_) +static void extcap_log(int priority, const char *function, const char *buffer, void *userdata _U_) { - ws_debug("[%s] %s", function, buffer); + enum ws_log_level level = LOG_LEVEL_DEBUG; + switch (priority) { + case SSH_LOG_TRACE: + level = LOG_LEVEL_NOISY; + break; + case SSH_LOG_DEBUG: + level = LOG_LEVEL_DEBUG; + break; + case SSH_LOG_INFO: + level = LOG_LEVEL_INFO; + break; + case SSH_LOG_WARN: + default: + /* Prior to 0.11.0 libssh prints far too much at SSH_LOG_WARN, + * including merely informational messages. + * Lower them to LOG_LEVEL_INFO, which won't get shown in the GUI + * and aren't shown by default. (Anything INFO and below goes to + * stdout due to ws_log_console_writer_set_use_stdout in extcap-base.c) + * After the following commit libssh only uses LOG_LEVEL_WARN for + * serious issues: + * https://gitlab.com/libssh/libssh-mirror/-/commit/657d9143d121dfff74f5a63f734d0096c7f37194 + */ +#if LIBSSH_VERSION_INT < SSH_VERSION_INT(0,11,0) + level = LOG_LEVEL_INFO; +#else + level = LOG_LEVEL_WARNING; +#endif + break; + } + /* We set the libssh log level to specifically ask for this, so don't + * both checking the log level a second time. + */ + ws_log_write_always_full("libssh", level, NULL, 0, function, "%s", buffer); } void add_libssh_info(extcap_parameters * extcap_conf) @@ -101,23 +133,18 @@ ssh_session create_ssh_connection(const ssh_params_t* ssh_params, char** err_inf goto failure; } - if (ssh_params->debug) { - int debug_level = SSH_LOG_INFO; - ssh_options_set(sshs, SSH_OPTIONS_LOG_VERBOSITY, &debug_level); - ssh_set_log_callback(extcap_log); - } + ssh_options_set(sshs, SSH_OPTIONS_LOG_VERBOSITY, &ssh_params->debug); + ssh_set_log_callback(extcap_log); if (ssh_params->ssh_sha1) { if (ssh_options_set(sshs, SSH_OPTIONS_HOSTKEYS, HOSTKEYS_SHA1)) { *err_info = ws_strdup_printf("Can't set host keys to allow SHA-1."); goto failure; } -#if LIBSSH_VERSION_INT >= SSH_VERSION_INT(0,8,3) if (ssh_options_set(sshs, SSH_OPTIONS_PUBLICKEY_ACCEPTED_TYPES, HOSTKEYS_SHA1)) { *err_info = ws_strdup_printf("Can't set public key algorithms to allow SSH-RSA (SHA-1)."); goto failure; } -#endif if (ssh_options_set(sshs, SSH_OPTIONS_KEY_EXCHANGE, KEY_EXCHANGE_SHA1)) { *err_info = ws_strdup_printf("Can't set key exchange methods to allow SHA-1."); goto failure; @@ -176,15 +203,32 @@ ssh_session create_ssh_connection(const ssh_params_t* ssh_params, char** err_inf ws_info("Connecting using public key in %s...", ssh_params->sshkey_path); ret = ssh_pki_import_privkey_file(ssh_params->sshkey_path, ssh_params->sshkey_passphrase, NULL, NULL, &pkey); - if (ret == SSH_OK) { + switch (ret) { + + case SSH_OK: if (ssh_userauth_publickey(sshs, NULL, pkey) == SSH_AUTH_SUCCESS) { ws_info("done"); ssh_key_free(pkey); return sshs; } + ws_info("failed (%s)", ssh_get_error(sshs)); + break; + case SSH_EOF: + ws_warning("Error importing key from %s. File doesn't exist or permission denied.", + ssh_params->sshkey_path); + break; + case SSH_ERROR: + /* Unfortunately we can't call ssh_get_error() on the + * key to determine why import failed. + */ + ws_warning("Error importing key from %s. Make sure it is a valid" + " private key file and any necessary passphrase is configured.", + ssh_params->sshkey_path); + break; + default: + ws_warning("Unknown error from ssh_pki_import_privkey_file"); } ssh_key_free(pkey); - ws_info("failed (%s)", ssh_get_error(sshs)); } /* Workaround: it may happen that libssh closes socket in meantime and any next ssh_ call fails so we should detect it in advance */ @@ -276,6 +320,23 @@ void ssh_params_free(ssh_params_t* ssh_params) g_free(ssh_params); } +void ssh_params_set_log_level(ssh_params_t* ssh_params, enum ws_log_level level) +{ + switch (level) { + case LOG_LEVEL_NOISY: + ssh_params->debug = SSH_LOG_TRACE; + break; + case LOG_LEVEL_DEBUG: + ssh_params->debug = SSH_LOG_DEBUG; + break; + case LOG_LEVEL_INFO: + ssh_params->debug = SSH_LOG_INFO; + break; + default: + ssh_params->debug = SSH_LOG_WARN; + } +} + /* * Editor modelines - https://www.wireshark.org/tools/modelines.html * diff --git a/extcap/ssh-base.h b/extcap/ssh-base.h index 9ac59230..9c8aa93b 100644 --- a/extcap/ssh-base.h +++ b/extcap/ssh-base.h @@ -50,13 +50,13 @@ typedef struct _ssh_params { char* sshkey_passphrase; char* proxycommand; bool ssh_sha1; - bool debug; + int debug; } ssh_params_t; /* Add libssh version information to an extcap_parameters structure */ void add_libssh_info(extcap_parameters * extcap_conf); -/* Create a ssh connection using all the possible authentication menthods */ +/* Create a ssh connection using all the possible authentication methods */ ssh_session create_ssh_connection(const ssh_params_t* ssh_params, char** err_info); /* Write a formatted message in the channel */ @@ -71,6 +71,9 @@ ssh_params_t* ssh_params_new(void); /* Clean the ssh params */ void ssh_params_free(ssh_params_t* ssh_params); +/* Sets the libssh log level to match the ws log level */ +void ssh_params_set_log_level(ssh_params_t* ssh_params, enum ws_log_level level); + #endif /* diff --git a/extcap/sshdump.c b/extcap/sshdump.c index e4cfc793..8da2bb37 100644 --- a/extcap/sshdump.c +++ b/extcap/sshdump.c @@ -65,7 +65,7 @@ enum { OPT_REMOTE_NOPROM }; -static struct ws_option longopts[] = { +static const struct ws_option longopts[] = { EXTCAP_BASE_OPTIONS, { "help", ws_no_argument, NULL, OPT_HELP}, { "version", ws_no_argument, NULL, OPT_VERSION}, @@ -196,7 +196,7 @@ static ssh_channel run_ssh_command(ssh_session sshs, const char* capture_command g_string_append_printf(ifaces_string, "-i %s ", quoted_iface); ifaces_array_num++; } - ifaces = g_string_free(ifaces_string, false); + ifaces = g_string_free(ifaces_string, FALSE); } quoted_filter = g_shell_quote(cfilter ? cfilter : ""); if (count > 0) @@ -306,7 +306,7 @@ static char* interfaces_list_to_filter(GSList* interfaces, unsigned int remote_p } g_string_append_printf(filter, ") and port %u)", remote_port); } - return g_string_free(filter, false); + return g_string_free(filter, FALSE); } static int list_config(char *interface, unsigned int remote_port) @@ -659,13 +659,13 @@ int main(int argc, char *argv[]) // given is always using the default SSH port since there's no remote SSH port // given on the command line to get the extcap arguments. // However the remote SSH port used here is the one given on the command line - // when the capture us started, which is the indended one. + // when the capture us started, which is the intended one. // And this is only happening when no remote filter is specified on the command // line to start the capture. if (remote_filter == NULL) remote_filter = local_interfaces_to_filter(ssh_params->port); filter = concat_filters(extcap_conf->capture_filter, remote_filter); - ssh_params->debug = extcap_conf->debug; + ssh_params_set_log_level(ssh_params, extcap_conf->debug); ret = ssh_open_remote_connection(ssh_params, remote_interface, filter, remote_capture_command_select, remote_capture_command, privilege, noprom, count, extcap_conf->fifo); diff --git a/extcap/ubxdump.py b/extcap/ubxdump.py new file mode 100755 index 00000000..914728cf --- /dev/null +++ b/extcap/ubxdump.py @@ -0,0 +1,469 @@ +#!/usr/bin/env python3 + +# Extcap for u-blox GNSS receiver +# By Timo Warns <timo.warns@gmail.com> +# Copyright 2024 Timo Warns +# +# The extcap is based on Wireshark's extcap_example.py with +# Copyright 2014 Roland Knall <rknall [AT] gmail.com> +# +# Wireshark - Network traffic analyzer +# By Gerald Combs <gerald@wireshark.org> +# Copyright 1998 Gerald Combs +# +# SPDX-License-Identifier: GPL-2.0-or-later +# + +""" +Extcap for UBX messages from an u-blox GNSS receiver. +Tested with UBX protocol version 18. +""" + +import argparse, serial.tools.list_ports, serial, struct, sys, time +from threading import Thread + +VERSION = "0.1" + + +################################ +# u-blox / UBX related constants +################################ + +UBLOX_DEV_DESCRIPTION = 'u-blox GNSS receiver' + +# UBX message structure-related definitions +UBX_PREAMBLE_1 = 0xb5 +UBX_PREAMBLE_2 = 0x62 +UBX_HEADER_SIZE = 6 +UBX_CHKSUM_SIZE = 2 +UBX_PAYLOAD_LEN_OFFSET = 4 + +# UBX GNSS Identifiers +UBX_GNSS_ID_GPS = 0 +UBX_GNSS_ID_SBAS = 1 +UBX_GNSS_ID_GALILEO = 2 +UBX_GNSS_ID_BEIDOU = 3 +UBX_GNSS_ID_IMES = 4 +UBX_GNSS_ID_QZSS = 5 +UBX_GNSS_ID_GLONASS = 6 + +# UBX message class and identifiers +UBX_NAV = 0x01 +UBX_NAV_POSECEF = [UBX_NAV, 0x01] +UBX_NAV_DOP = [UBX_NAV, 0x04] +UBX_NAV_PVT = [UBX_NAV, 0x07] +UBX_NAV_ODO = [UBX_NAV, 0x09] +UBX_NAV_VELECEF = [UBX_NAV, 0x11] +UBX_NAV_TIMEGPS = [UBX_NAV, 0x20] +UBX_NAV_TIMEUTC = [UBX_NAV, 0x21] +UBX_NAV_TIMELS = [UBX_NAV, 0x26] +UBX_NAV_SBAS = [UBX_NAV, 0x32] +UBX_NAV_SAT = [UBX_NAV, 0x35] +UBX_NAV_EOE = [UBX_NAV, 0x61] + +UBX_RXM = 0x02 +UBX_RXM_SFRBX = [UBX_RXM, 0x13] +UBX_RXM_MEASX = [UBX_RXM, 0x14] +UBX_RXM_RAWX = [UBX_RXM, 0x15] + +UBX_CFG = 0x06 +UBX_CFG_MSG = [UBX_CFG, 0x01] +UBX_CFG_SBAS = [UBX_CFG, 0x16] +UBX_CFG_GNSS = [UBX_CFG, 0x3e] + +UBX_NMEA = 0xf0 +UBX_NMEA_GGA = [UBX_NMEA, 0x00] +UBX_NMEA_GLL = [UBX_NMEA, 0x01] +UBX_NMEA_GSA = [UBX_NMEA, 0x02] +UBX_NMEA_GSV = [UBX_NMEA, 0x03] +UBX_NMEA_RMC = [UBX_NMEA, 0x04] +UBX_NMEA_VTG = [UBX_NMEA, 0x05] +UBX_NMEA_GRS = [UBX_NMEA, 0x06] +UBX_NMEA_GST = [UBX_NMEA, 0x07] +UBX_NMEA_ZDA = [UBX_NMEA, 0x08] +UBX_NMEA_GBS = [UBX_NMEA, 0x09] +UBX_NMEA_TXT = [UBX_NMEA, 0x41] + + +# Defines the desired rate per UBX message type. +# NMEA messages are disabled by setting their rate to 0. +# +# Eventually, this could be made configurable / controllable via the extcap +# config interface. +UBX_MSG_RATES = [ + (UBX_NAV_POSECEF, 0x01), + (UBX_NAV_DOP, 0x01), + (UBX_NAV_PVT, 0x01), + (UBX_NAV_ODO, 0x01), + (UBX_NAV_VELECEF, 0x01), + (UBX_NAV_TIMEGPS, 0x01), + (UBX_NAV_TIMEUTC, 0x01), + (UBX_NAV_TIMELS, 0xff), + (UBX_NAV_SBAS, 0x01), + (UBX_NAV_SAT, 0x01), + (UBX_NAV_EOE, 0x01), + (UBX_RXM_SFRBX, 0x01), + (UBX_RXM_MEASX, 0x01), + (UBX_RXM_RAWX, 0x01), + (UBX_NMEA_GGA, 0x00), + (UBX_NMEA_GLL, 0x00), + (UBX_NMEA_GSA, 0x00), + (UBX_NMEA_GSV, 0x00), + (UBX_NMEA_RMC, 0x00), + (UBX_NMEA_VTG, 0x00), + (UBX_NMEA_GRS, 0x00), + (UBX_NMEA_GST, 0x00), + (UBX_NMEA_ZDA, 0x00), + (UBX_NMEA_GBS, 0x00), + (UBX_NMEA_TXT, 0x00), + ] + +# Defines the desired GNSS config. +# Format is (GNSS ID, resTrkCh, maxTrkCh, enable, sigCfgMask). +# +# Eventually, this could be made configurable / controllable via the extcap +# config interface. +UBX_GNSS_CONFIGS = [ + (UBX_GNSS_ID_GPS, 8, 14, True, 0x01), + (UBX_GNSS_ID_GLONASS, 0, 0, False, 0x00), + (UBX_GNSS_ID_SBAS, 2, 4, True, 0x01), + (UBX_GNSS_ID_GALILEO, 8, 14, True, 0x01) + ] + +######################## +# PCAP-related constants +######################## + +DLT = "147" +DLT_NAME = "DLT_USER0" + +PCAP_MAGIC = 0xa1b2c3d4 +PCAP_VERSION_MAJOR = 2 +PCAP_VERSION_MINOR = 4 +PCAP_THISZONE = 0 +PCAP_SIGFIGS = 0 +PCAP_SNAPLEN = 0xffffffff + +########################## +# extcap-related constants +########################## + +ERROR_USAGE = 0 +ERROR_ARG = 1 +ERROR_INTERFACE = 2 +ERROR_FIFO = 3 + +CTRL_CMD_INITIALIZED = 0 +CTRL_CMD_SET = 1 +CTRL_CMD_ADD = 2 +CTRL_CMD_REMOVE = 3 +CTRL_CMD_ENABLE = 4 +CTRL_CMD_DISABLE = 5 +CTRL_CMD_STATUSBAR_MSG = 6 +CTRL_CMD_INFO_MSG = 7 +CTRL_CMD_WARN_MSG = 8 +CTRL_CMD_ERROR_MSG = 9 + +CTRL_ARG_LOGGER = 0 + +initialized = False +fn_out = None + +def extcap_config(option): + # not options implemented for the moment + return + +def extcap_version(): + print(f"extcap {{version={VERSION}}}{{help=https://www.wireshark.org}}{{display=u-blox UBX extcap interface}}") + +def extcap_interfaces(): + extcap_version() + for i in serial.tools.list_ports.grep(UBLOX_DEV_DESCRIPTION): + print(f"interface {{value={i.device}}}{{display=u-blox UBX capture}}") + + print(f"control {{number={CTRL_ARG_LOGGER}}}{{type=button}}{{role=logger}}{{display=Log}}{{tooltip=Show capture log}}") + +def extcap_dlts(): + print(f"dlt {{number={DLT}}}{{name={DLT_NAME}}}{{display=UBX DLT ({DLT_NAME})}}") + +def log(msg): + control_write(CTRL_ARG_LOGGER, CTRL_CMD_ADD, msg) + +def pcap_header(): + return struct.pack( + "!IHHiIII", + PCAP_MAGIC, + PCAP_VERSION_MAJOR, + PCAP_VERSION_MINOR, + PCAP_THISZONE, + PCAP_SIGFIGS, + PCAP_SNAPLEN, + int(DLT)) + +def pcap_packet(ubx_msg): + pcap = bytearray() + + caplength = len(ubx_msg) + timestamp = int(time.time()) + + pcap += struct.pack("!IIII", int(timestamp), 0, caplength, caplength) + pcap += ubx_msg + + return pcap + +def ubxChecksum(msg): + ck_a = 0 + ck_b = 0 + + for b in msg: + ck_a += b + ck_b += ck_a + + return [ck_a & 0xff, ck_b & 0xff] + +def ubxMsg(ubxClassId, payload): + + payloadLength = len(payload) + + msg = bytearray(UBX_HEADER_SIZE + payloadLength + UBX_CHKSUM_SIZE) + + # add preamble + msg[0:2] = [UBX_PREAMBLE_1, UBX_PREAMBLE_2] + + # add class/id + msg[2:4] = ubxClassId + + # add payload length + struct.pack_into('<H', msg, UBX_PAYLOAD_LEN_OFFSET, payloadLength) + + # add payload + msg[UBX_HEADER_SIZE:-UBX_CHKSUM_SIZE] = payload + + # add checksum + msg[-UBX_CHKSUM_SIZE:] = ubxChecksum(msg[2:-UBX_CHKSUM_SIZE]) + + return msg + +def sendUbxMsg(receiver, msg): + log("Sending UBX message: " + msg.hex() + "\n") + receiver.write(msg) + +def ubxCfgMsg(ubxMsgClassId, rate): + return ubxMsg(UBX_CFG_MSG, ubxMsgClassId + [rate]) + +def ubxCfgGnss(gnssId, resTrkCh, maxTrkCh, enable, sigCfgMask): + + msgVer = 0x00 + numTrkChHw = 0x00 # read only + numTrkChUse = 0xff + numConfigBlocks = 0x01 # one config block only + + payload = bytearray(12) + + payload[0] = msgVer + payload[1] = numTrkChHw + payload[2] = numTrkChUse + payload[3] = numConfigBlocks + + payload[4] = gnssId + payload[5] = resTrkCh + payload[6] = maxTrkCh + payload[7] = 0 # reserved1 + payload[8] = 1 if enable else 0 + payload[9] = 0 # flags, reserved + payload[10] = sigCfgMask + payload[11] = 0 # flags, reserved + + return ubxMsg(UBX_CFG_GNSS, payload) + + +def control_read(fn): + try: + header = fn.read(6) + sp, _, length, arg, typ = struct.unpack('>sBHBB', header) + if length > 2: + payload = fn.read(length - 2).decode('utf-8', 'replace') + else: + payload = '' + return arg, typ, payload + except Exception: + return None, None, None + +def control_read_thread(control_in): + global initialized + with open(control_in, 'rb', 0) as fn: + arg = 0 + while arg is not None: + arg, typ, payload = control_read(fn) + + if typ == CTRL_CMD_INITIALIZED: + initialized = True + +def control_write(arg, typ, payload): + global fn_out + + if fn_out is not None: + packet = bytearray() + packet += struct.pack('>sBHBB', b'T', 0, len(payload) + 2, arg, typ) + if sys.version_info[0] >= 3 and isinstance(payload, str): + packet += payload.encode('utf-8') + else: + packet += payload + + fn_out.write(packet) + +def extcap_capture(interface, fifo, control_in, control_out): + global fn_out + + counter = 1 + + with open(fifo, 'wb', 0) as fh: + + fh.write(pcap_header()) + + if control_out is not None: + fn_out = open(control_out, 'wb', 0) + control_write(CTRL_ARG_LOGGER, CTRL_CMD_SET, "Log started at " + time.strftime("%c") + "\n") + + if control_in is not None: + # Start reading thread + thread = Thread(target=control_read_thread, args=(control_in,)) + thread.start() + + with serial.Serial(baudrate=9600, + bytesize=serial.EIGHTBITS, + parity=serial.PARITY_NONE, + port=interface, + stopbits=serial.STOPBITS_ONE, + timeout = 0.1) as receiver: + + # set GNSS config + log("Configuring GNSS constellations:\n") + for (gnssId, resTrkCh, maxTrkCh, enable, sigCfgMask) in UBX_GNSS_CONFIGS: + sendUbxMsg(receiver, ubxCfgGnss(gnssId, resTrkCh, maxTrkCh, enable, sigCfgMask)) + + # query GNSS config + log("Querying GNSS constellation config:\n") + sendUbxMsg(receiver, ubxMsg(UBX_CFG_GNSS, [])) + + # query SBAS config + log("Querying SBAS config:\n") + sendUbxMsg(receiver, ubxMsg(UBX_CFG_SBAS, [])) + + # set the message rates + log("Setting UBX msg rates:\n") + for (ubxClassId, rate) in UBX_MSG_RATES: + sendUbxMsg(receiver, ubxCfgMsg(ubxClassId, rate)) + + ubx_in_data = bytearray() + + while True: + ubx_in_data += receiver.read(8192) + + i = 0 + + # Is there enough data remaining for a packet of min. possible size? + while i < len(ubx_in_data) - UBX_HEADER_SIZE - UBX_CHKSUM_SIZE + 1: + + if ubx_in_data[i] == UBX_PREAMBLE_1 and ubx_in_data[i+1] == UBX_PREAMBLE_2: + + (payload_len,) = struct.unpack("<H", ubx_in_data[i + UBX_PAYLOAD_LEN_OFFSET : i + UBX_PAYLOAD_LEN_OFFSET + 2]) + + # Is there enough data remaining for the complete message? + if i + UBX_HEADER_SIZE + payload_len + UBX_CHKSUM_SIZE <= len(ubx_in_data): + ubx_frame = ubx_in_data[i : i + UBX_HEADER_SIZE + payload_len + UBX_CHKSUM_SIZE] + + log("Emitting UBX PCAP packet with header " + ubx_frame[0:6].hex() + "\n") + + fh.write(pcap_packet(ubx_frame)) + + i = i + UBX_HEADER_SIZE + payload_len + UBX_CHKSUM_SIZE + + else: + break + + else: + i += 1 + + ubx_in_data = ubx_in_data[i:] + + thread.join() + if fn_out is not None: + fn_out.close() + +def extcap_close_fifo(fifo): + # This is apparently needed to workaround an issue on Windows/macOS + # where the message cannot be read. (really?) + fh = open(fifo, 'wb', 0) + fh.close() + +def usage(): + print("Usage: %s <--extcap-interfaces | --extcap-dlts | --extcap-interface | --extcap-config | --capture | --extcap-capture-filter | --fifo>" % sys.argv[0] ) + +if __name__ == '__main__': + option = "" + + parser = argparse.ArgumentParser(description="u-blox UBX extcap") + + # Extcap Arguments + parser.add_argument("--capture", help="Start the capture routine", action="store_true" ) + parser.add_argument("--extcap-interfaces", help="Provide a list of interfaces to capture from", action="store_true") + parser.add_argument("--extcap-interface", help="Provide the interface to capture from") + parser.add_argument("--extcap-dlts", help="Provide a list of dlts for the given interface", action="store_true") + parser.add_argument("--extcap-config", help="Provide a list of configurations for the given interface", action="store_true") + parser.add_argument("--extcap-capture-filter", help="Used together with capture to provide a capture filter") + parser.add_argument("--fifo", help="Use together with capture to provide the fifo to dump data to") + parser.add_argument("--extcap-control-in", help="Used to get control messages from toolbar") + parser.add_argument("--extcap-control-out", help="Used to send control messages to toolbar") + parser.add_argument("--extcap-version", help="Shows the version of this utility", nargs='?', default="") + parser.add_argument("--extcap-reload-option", help="Reload elements for the given option") + + try: + args, unknown = parser.parse_known_args() + except argparse.ArgumentError as exc: + print("%s: %s" % (exc.argument.dest, exc.message), file=sys.stderr) + fifo_found = 0 + fifo = "" + for arg in sys.argv: + if arg == "--fifo" or arg == "--extcap-fifo": + fifo_found = 1 + elif fifo_found == 1: + fifo = arg + break + extcap_close_fifo(fifo) + sys.exit(ERROR_ARG) + + if len(sys.argv) <= 1: + parser.exit("No arguments given!") + + if args.extcap_version and not args.extcap_interfaces: + extcap_version() + sys.exit(0) + + if not args.extcap_interfaces and args.extcap_interface is None: + parser.exit("An interface must be provided or the selection must be displayed") + + if args.extcap_interfaces or args.extcap_interface is None: + extcap_interfaces() + sys.exit(0) + + if len(unknown) > 1: + print(f"{len(unknown)} unknown arguments given") + + if args.extcap_reload_option and len(args.extcap_reload_option) > 0: + option = args.extcap_reload_option + + if args.extcap_config: + extcap_config(option) + elif args.extcap_dlts: + extcap_dlts() + elif args.capture: + if args.fifo is None: + sys.exit(ERROR_FIFO) + try: + extcap_capture(args.extcap_interface, args.fifo, args.extcap_control_in, args.extcap_control_out) + except KeyboardInterrupt: + pass + else: + usage() + sys.exit(ERROR_USAGE) diff --git a/extcap/udpdump.c b/extcap/udpdump.c index 7f4602ac..e7ff3db4 100644 --- a/extcap/udpdump.c +++ b/extcap/udpdump.c @@ -70,7 +70,7 @@ enum { OPT_PAYLOAD }; -static struct ws_option longopts[] = { +static const struct ws_option longopts[] = { EXTCAP_BASE_OPTIONS, /* Generic application options */ { "help", ws_no_argument, NULL, OPT_HELP}, @@ -253,7 +253,7 @@ static int dump_packet(const char* proto_name, const uint16_t listenport, const add_proto_name(mbuf, &offset, proto_name); add_ip_source_address(mbuf, &offset, clientaddr.sin_addr.s_addr); - add_ip_dest_address(mbuf, &offset, WS_IN4_LOOPBACK); + add_ip_dest_address(mbuf, &offset, g_htonl(INADDR_LOOPBACK)); add_udp_source_port(mbuf, &offset, clientaddr.sin_port); add_udp_dst_port(mbuf, &offset, listenport); add_end_options(mbuf, &offset); diff --git a/extcap/wifidump.c b/extcap/wifidump.c index ba3a6364..57a9c07a 100644 --- a/extcap/wifidump.c +++ b/extcap/wifidump.c @@ -63,7 +63,7 @@ enum { OPT_REMOTE_COUNT }; -static struct ws_option longopts[] = { +static const struct ws_option longopts[] = { EXTCAP_BASE_OPTIONS, { "help", ws_no_argument, NULL, OPT_HELP}, { "version", ws_no_argument, NULL, OPT_VERSION}, @@ -724,7 +724,7 @@ int main(int argc, char *argv[]) } remote_center_frequency = center_freq(remote_channel_frequency, remote_channel_width); filter = concat_filters(extcap_conf->capture_filter, remote_filter); - ssh_params->debug = extcap_conf->debug; + ssh_params_set_log_level(ssh_params, extcap_conf->debug); ret = ssh_open_remote_connection(ssh_params, remote_capture_functions, remote_interface, remote_channel_frequency, remote_channel_width, remote_center_frequency, filter, count, extcap_conf->fifo); |