summaryrefslogtreecommitdiffstats
path: root/extcap
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-09-19 04:14:53 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-09-19 04:14:53 +0000
commita86c5f7cae7ec9a3398300555a0b644689d946a1 (patch)
tree39fe4b107c71174fd1e8a8ceb9a4d2aa14116248 /extcap
parentReleasing progress-linux version 4.2.6-1~progress7.99u1. (diff)
downloadwireshark-a86c5f7cae7ec9a3398300555a0b644689d946a1.tar.xz
wireshark-a86c5f7cae7ec9a3398300555a0b644689d946a1.zip
Merging upstream version 4.4.0.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'extcap')
-rw-r--r--extcap/CMakeLists.txt81
-rw-r--r--extcap/androiddump.c75
-rw-r--r--extcap/ciscodump.c16
-rw-r--r--extcap/dpauxmon.c9
-rw-r--r--extcap/etl.c10
-rw-r--r--extcap/etw_message.c2
-rw-r--r--extcap/etw_ndiscap.c24
-rw-r--r--extcap/etwdump.c4
-rw-r--r--extcap/extcap-base.c16
-rw-r--r--extcap/extcap-base.h2
-rw-r--r--extcap/falcodump.cpp363
-rw-r--r--extcap/randpktdump.c6
-rw-r--r--extcap/sdjournal.c2
-rw-r--r--extcap/ssh-base.c83
-rw-r--r--extcap/ssh-base.h7
-rw-r--r--extcap/sshdump.c10
-rwxr-xr-xextcap/ubxdump.py469
-rw-r--r--extcap/udpdump.c4
-rw-r--r--extcap/wifidump.c4
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);