summaryrefslogtreecommitdiffstats
path: root/wsutil
diff options
context:
space:
mode:
Diffstat (limited to 'wsutil')
-rw-r--r--wsutil/.clang-tidy10
-rw-r--r--wsutil/.editorconfig5
-rw-r--r--wsutil/802_11-utils.c34
-rw-r--r--wsutil/802_11-utils.h9
-rw-r--r--wsutil/CMakeLists.txt15
-rw-r--r--wsutil/adler32.c15
-rw-r--r--wsutil/array.h25
-rw-r--r--wsutil/bits_count_ones.h8
-rw-r--r--wsutil/buffer.c2
-rw-r--r--wsutil/clopts_common.c38
-rw-r--r--wsutil/clopts_common.h24
-rw-r--r--wsutil/codecs.c6
-rw-r--r--wsutil/console_win32.c10
-rw-r--r--wsutil/cpu_info.c5
-rw-r--r--wsutil/crc16.c4
-rw-r--r--wsutil/crc32.c17
-rw-r--r--wsutil/epochs.h8
-rw-r--r--wsutil/exported_pdu_tlvs.h13
-rw-r--r--wsutil/feature_list.c6
-rw-r--r--wsutil/file_util.c10
-rw-r--r--wsutil/filesystem.c227
-rw-r--r--wsutil/filesystem.h14
-rw-r--r--wsutil/filter_files.c174
-rw-r--r--wsutil/filter_files.h40
-rw-r--r--wsutil/g711.c10
-rw-r--r--wsutil/glib-compat.h64
-rw-r--r--wsutil/inet_addr.h94
-rw-r--r--wsutil/inet_cidr.c110
-rw-r--r--wsutil/inet_cidr.h62
-rw-r--r--wsutil/inet_ipv4.h57
-rw-r--r--wsutil/inet_ipv6.h103
-rw-r--r--wsutil/json_dumper.c10
-rw-r--r--wsutil/json_dumper.h2
-rw-r--r--wsutil/nstime.c25
-rw-r--r--wsutil/nstime.h7
-rw-r--r--wsutil/os_version_info.c4
-rw-r--r--wsutil/path_config.h.in1
-rw-r--r--wsutil/pint.h5
-rw-r--r--wsutil/plugins.c56
-rw-r--r--wsutil/plugins.h10
-rw-r--r--wsutil/privileges.c2
-rw-r--r--wsutil/regex.c12
-rw-r--r--wsutil/regex.h10
-rw-r--r--wsutil/report_message.c2
-rw-r--r--wsutil/report_message.h6
-rw-r--r--wsutil/sign_ext.h4
-rw-r--r--wsutil/str_util.c296
-rw-r--r--wsutil/str_util.h64
-rw-r--r--wsutil/test_wsutil.c60
-rw-r--r--wsutil/time_util.c2
-rw-r--r--wsutil/to_str.c91
-rw-r--r--wsutil/to_str.h32
-rw-r--r--wsutil/type_util.c6
-rw-r--r--wsutil/type_util.h12
-rw-r--r--wsutil/unicode-utils.c2
-rw-r--r--wsutil/unicode-utils.h2
-rw-r--r--wsutil/utf8_entities.h2
-rw-r--r--wsutil/version_info.c43
-rw-r--r--wsutil/version_info.h12
-rw-r--r--wsutil/win32-utils.c31
-rw-r--r--wsutil/win32-utils.h11
-rw-r--r--wsutil/wmem/wmem_allocator_block.c4
-rw-r--r--wsutil/wmem/wmem_core.c2
-rw-r--r--wsutil/wmem/wmem_core.h8
-rw-r--r--wsutil/wmem/wmem_interval_tree.c1
-rw-r--r--wsutil/wmem/wmem_list.c50
-rw-r--r--wsutil/wmem/wmem_list.h7
-rw-r--r--wsutil/wmem/wmem_map.c6
-rw-r--r--wsutil/wmem/wmem_map.h6
-rw-r--r--wsutil/wmem/wmem_miscutl.c4
-rw-r--r--wsutil/wmem/wmem_miscutl.h6
-rw-r--r--wsutil/wmem/wmem_strutl.c15
-rw-r--r--wsutil/wmem/wmem_strutl.h4
-rw-r--r--wsutil/wmem/wmem_test.c6
-rw-r--r--wsutil/wmem/wmem_tree.c1
-rw-r--r--wsutil/ws_mempbrk.c15
-rw-r--r--wsutil/ws_mempbrk.h5
-rw-r--r--wsutil/ws_pipe.c8
-rw-r--r--wsutil/ws_strptime.c2
-rw-r--r--wsutil/wsjson.c37
-rw-r--r--wsutil/wsjson.h6
-rw-r--r--wsutil/wslog.c33
-rw-r--r--wsutil/wslog.h11
83 files changed, 1635 insertions, 643 deletions
diff --git a/wsutil/.clang-tidy b/wsutil/.clang-tidy
new file mode 100644
index 00000000..84ea0537
--- /dev/null
+++ b/wsutil/.clang-tidy
@@ -0,0 +1,10 @@
+InheritParentConfig: true
+
+# We don't want to do any checks in this directory yet so hack around
+# the fact that Clang-Tidy won't let us disable all checks.
+# https://stackoverflow.com/a/58379342/82195
+Checks:
+ - '-*'
+ - 'misc-definitions-in-headers'
+CheckOptions:
+ - { key: 'HeaderFileExtensions', value: 'DISABLED' }
diff --git a/wsutil/.editorconfig b/wsutil/.editorconfig
index 78cac438..03257de7 100644
--- a/wsutil/.editorconfig
+++ b/wsutil/.editorconfig
@@ -97,8 +97,9 @@ indent_size = tab
[type_util.[ch]]
indent_size = 2
-[u3.[ch]]
-indent_size = 2
+[version_info.[ch]]
+indent_style = tab
+indent_size = tab
[ws_getopt.[ch]]
indent_style = tab
diff --git a/wsutil/802_11-utils.c b/wsutil/802_11-utils.c
index ee79f839..2ad5da81 100644
--- a/wsutil/802_11-utils.c
+++ b/wsutil/802_11-utils.c
@@ -10,6 +10,7 @@
#include "config.h"
#include "802_11-utils.h"
+#include <wsutil/array.h>
typedef struct freq_cvt_s {
unsigned fmin; /* Minimum frequency in MHz */
@@ -41,7 +42,7 @@ static freq_cvt_t freq_cvt[] = {
{ 4910, 4980, 182, false },
};
-#define NUM_FREQ_CVT (sizeof(freq_cvt) / sizeof(freq_cvt_t))
+#define NUM_FREQ_CVT array_length(freq_cvt)
#define MAX_CHANNEL(fc) ( (int) ((fc.fmax - fc.fmin) / FREQ_STEP) + fc.cmin )
/*
@@ -84,17 +85,44 @@ ieee80211_chan_to_mhz(int chan, bool is_bg) {
}
/*
+ * Get Frequency given a Channel number and band.
+ */
+unsigned
+ieee80211_chan_band_to_mhz(int chan, bool is_bg, bool is_6ghz) {
+ unsigned i;
+
+ int start_idx = 0;
+ if (is_6ghz) {
+ start_idx = 3;
+ }
+ for (i = start_idx; i < NUM_FREQ_CVT; i++) {
+ if (is_bg == freq_cvt[i].is_bg &&
+ chan >= freq_cvt[i].cmin && chan <= MAX_CHANNEL(freq_cvt[i])) {
+ return ((chan - freq_cvt[i].cmin) * FREQ_STEP) + freq_cvt[i].fmin;
+ }
+ }
+ return 0;
+}
+
+/*
* Get channel representation string given a Frequency
*/
char*
ieee80211_mhz_to_str(unsigned freq){
int chan = ieee80211_mhz_to_chan(freq);
- bool is_bg = FREQ_IS_BG(freq);
+ const char* band;
+ if (FREQ_IS_BG(freq)) {
+ band = "2.4 GHz";
+ } else if (FREQ_IS_6G(freq)) {
+ band = "6 GHz";
+ } else {
+ band = "5 GHz";
+ }
if (chan < 0) {
return ws_strdup_printf("%u", freq);
} else {
- return ws_strdup_printf("%u [%s %u]", freq, is_bg ? "BG" : "A",
+ return ws_strdup_printf("%u [%s %u]", freq, band,
chan);
}
}
diff --git a/wsutil/802_11-utils.h b/wsutil/802_11-utils.h
index 887faddb..5c496da2 100644
--- a/wsutil/802_11-utils.h
+++ b/wsutil/802_11-utils.h
@@ -51,10 +51,19 @@ WS_DLL_PUBLIC
char*
ieee80211_mhz_to_str(unsigned freq);
+/*
+ * Get Frequency given a Channel number and band.
+ */
+WS_DLL_PUBLIC
+unsigned
+ieee80211_chan_band_to_mhz(int chan, bool is_bg, bool is_6ghz);
+
/* Should this be "(freq < 4920)", or something else? */
#define FREQ_IS_BG(freq) ((freq) <= 2484)
#define CHAN_IS_BG(chan) ((chan) <= 14)
+#define FREQ_IS_6G(freq) (5950 <= (freq) && (freq) <= 7125)
+
/*
* Test whether a data rate is an {HR}/DSSS (legacy DSSS/11b) data rate
* and whether it's an OFDM (11a/11g OFDM mode) data rate.
diff --git a/wsutil/CMakeLists.txt b/wsutil/CMakeLists.txt
index ba8633e1..c4bf10bd 100644
--- a/wsutil/CMakeLists.txt
+++ b/wsutil/CMakeLists.txt
@@ -17,6 +17,8 @@ file(TO_NATIVE_PATH "${PLUGIN_INSTALL_LIBDIR}" PATH_PLUGIN_DIR)
string(REPLACE "\\" "\\\\" PATH_PLUGIN_DIR "${PATH_PLUGIN_DIR}")
file(TO_NATIVE_PATH "${EXTCAP_INSTALL_LIBDIR}" PATH_EXTCAP_DIR)
string(REPLACE "\\" "\\\\" PATH_EXTCAP_DIR "${PATH_EXTCAP_DIR}")
+file(TO_NATIVE_PATH "${LOG_EXTCAP_INSTALL_LIBDIR}" PATH_LOG_EXTCAP_DIR)
+string(REPLACE "\\" "\\\\" PATH_LOG_EXTCAP_DIR "${PATH_LOG_EXTCAP_DIR}")
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/path_config.h.in ${CMAKE_CURRENT_BINARY_DIR}/path_config.h)
@@ -74,6 +76,7 @@ set(WMEM_FILES
set(WSUTIL_PUBLIC_HEADERS
802_11-utils.h
adler32.h
+ array.h
base32.h
bits_count_ones.h
bits_ctz.h
@@ -102,8 +105,7 @@ set(WSUTIL_PUBLIC_HEADERS
filesystem.h
g711.h
inet_addr.h
- inet_ipv4.h
- inet_ipv6.h
+ inet_cidr.h
interface.h
introspection.h
jsmn.h
@@ -113,6 +115,7 @@ set(WSUTIL_PUBLIC_HEADERS
os_version_info.h
pint.h
please_report_bug.h
+ plugins.h
pow2.h
privileges.h
processes.h
@@ -173,6 +176,7 @@ set(WSUTIL_COMMON_FILES
filter_files.c
g711.c
inet_addr.c
+ inet_cidr.c
interface.c
introspection.c
jsmn.c
@@ -354,7 +358,7 @@ target_compile_definitions(wsutil PRIVATE
set_target_properties(wsutil PROPERTIES
PREFIX "lib"
LINK_FLAGS "${WS_LINK_FLAGS}"
- VERSION "15.0.0" SOVERSION 15
+ VERSION "16.0.0" SOVERSION 16
FOLDER "DLLs"
INSTALL_RPATH "${LIBRARY_INSTALL_RPATH}"
)
@@ -371,7 +375,9 @@ target_link_libraries(wsutil
${CMAKE_DL_LIBS}
${GCRYPT_LIBRARIES}
${GNUTLS_LIBRARIES}
+ ${M_LIBRARIES}
${ZLIB_LIBRARIES}
+ ${ZLIBNG_LIBRARIES}
$<IF:$<CONFIG:Debug>,${PCRE2_DEBUG_LIBRARIES},${PCRE2_LIBRARIES}>
${WIN_IPHLPAPI_LIBRARY}
${WIN_WS2_32_LIBRARY}
@@ -385,6 +391,7 @@ target_include_directories(wsutil SYSTEM
PRIVATE
${GMODULE2_INCLUDE_DIRS}
${ZLIB_INCLUDE_DIRS}
+ ${ZLIBNG_INCLUDE_DIRS}
${PCRE2_INCLUDE_DIRS}
)
@@ -426,6 +433,7 @@ target_link_libraries(wsutil_static
${GCRYPT_LIBRARIES}
${GNUTLS_LIBRARIES}
${ZLIB_LIBRARIES}
+ ${ZLIBNG_LIBRARIES}
$<IF:$<CONFIG:Debug>,${PCRE2_DEBUG_LIBRARIES},${PCRE2_LIBRARIES}>
${WIN_IPHLPAPI_LIBRARY}
${WIN_WS2_32_LIBRARY}
@@ -439,6 +447,7 @@ target_include_directories(wsutil_static SYSTEM
PRIVATE
${GMODULE2_INCLUDE_DIRS}
${ZLIB_INCLUDE_DIRS}
+ ${ZLIBNG_INCLUDE_DIRS}
${PCRE2_INCLUDE_DIRS}
)
diff --git a/wsutil/adler32.c b/wsutil/adler32.c
index 2830eab4..bdd99395 100644
--- a/wsutil/adler32.c
+++ b/wsutil/adler32.c
@@ -12,6 +12,13 @@
#include <wsutil/adler32.h>
+#ifdef HAVE_ZLIBNG
+#include <zlib-ng.h>
+#else
+#ifdef HAVE_ZLIB
+#include <zlib.h>
+#endif /* HAVE_ZLIB */
+#endif
#include <string.h>
#define BASE 65521 /* largest prime smaller than 65536 */
@@ -19,6 +26,13 @@
/*--- update_adler32 --------------------------------------------------------*/
uint32_t update_adler32(uint32_t adler, const uint8_t *buf, size_t len)
{
+#if defined (HAVE_ZLIB) || defined (HAVE_ZLIBNG)
+#ifdef HAVE_ZLIBNG
+ return (uint32_t)zng_adler32(adler, buf, len);
+#else
+ return (uint32_t)adler32(adler, buf, len);
+#endif
+#endif
uint32_t s1 = adler & 0xffff;
uint32_t s2 = (adler >> 16) & 0xffff;
size_t n;
@@ -28,6 +42,7 @@ uint32_t update_adler32(uint32_t adler, const uint8_t *buf, size_t len)
s2 = (s2 + s1) % BASE;
}
return (s2 << 16) + s1;
+
}
/*--- adler32 ---------------------------------------------------------------*/
diff --git a/wsutil/array.h b/wsutil/array.h
new file mode 100644
index 00000000..1e23b5f6
--- /dev/null
+++ b/wsutil/array.h
@@ -0,0 +1,25 @@
+/** @file
+ * Utility functions/macros for handling arrays, C and/or glib.
+ *
+ * Wireshark - Network traffic analyzer
+ * By Gerald Combs <gerald@wireshark.org>
+ * Copyright 1998 Gerald Combs
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#ifndef __WSUTIL_ARRAY_H__
+#define __WSUTIL_ARRAY_H__
+
+#include <stdlib.h>
+#include <glib.h>
+
+/** Useful when you have an array whose size is known at compile-time. */
+#define array_length(x) (sizeof (x) / sizeof (x)[0])
+
+/** glib doesn't have g_ptr_array_len, of all things! */
+#ifndef g_ptr_array_len
+#define g_ptr_array_len(a) ((a) ? (a)->len : 0)
+#endif
+
+#endif /* __WSUTIL_ARRAY_H__ */
diff --git a/wsutil/bits_count_ones.h b/wsutil/bits_count_ones.h
index 1b4f1d68..a77025d7 100644
--- a/wsutil/bits_count_ones.h
+++ b/wsutil/bits_count_ones.h
@@ -41,11 +41,11 @@ ws_count_ones(const uint64_t x)
{
uint64_t bits = x;
- bits = bits - ((bits >> 1) & G_GUINT64_CONSTANT(0x5555555555555555));
- bits = (bits & G_GUINT64_CONSTANT(0x3333333333333333)) + ((bits >> 2) & G_GUINT64_CONSTANT(0x3333333333333333));
- bits = (bits + (bits >> 4)) & G_GUINT64_CONSTANT(0x0F0F0F0F0F0F0F0F);
+ bits = bits - ((bits >> 1) & UINT64_C(0x5555555555555555));
+ bits = (bits & UINT64_C(0x3333333333333333)) + ((bits >> 2) & UINT64_C(0x3333333333333333));
+ bits = (bits + (bits >> 4)) & UINT64_C(0x0F0F0F0F0F0F0F0F);
- return (int)((bits * G_GUINT64_CONSTANT(0x0101010101010101)) >> 56);
+ return (int)((bits * UINT64_C(0x0101010101010101)) >> 56);
}
#endif /* __WSUTIL_BITS_COUNT_ONES_H__ */
diff --git a/wsutil/buffer.c b/wsutil/buffer.c
index 95330086..cdb16a83 100644
--- a/wsutil/buffer.c
+++ b/wsutil/buffer.c
@@ -16,7 +16,7 @@
#include <wsutil/wslog.h>
#define SMALL_BUFFER_SIZE (2 * 1024) /* Everyone still uses 1500 byte frames, right? */
-static GPtrArray *small_buffers = NULL; /* Guaranteed to be at least SMALL_BUFFER_SIZE */
+static GPtrArray *small_buffers; /* Guaranteed to be at least SMALL_BUFFER_SIZE */
/* XXX - Add medium and large buffers? */
/* Initializes a buffer with a certain amount of allocated space */
diff --git a/wsutil/clopts_common.c b/wsutil/clopts_common.c
index fa17f8e3..f361b4ef 100644
--- a/wsutil/clopts_common.c
+++ b/wsutil/clopts_common.c
@@ -59,7 +59,7 @@ get_positive_int(const char *string, const char *name)
}
uint32_t
-get_guint32(const char *string, const char *name)
+get_uint32(const char *string, const char *name)
{
uint32_t number;
@@ -76,11 +76,43 @@ get_guint32(const char *string, const char *name)
}
uint32_t
-get_nonzero_guint32(const char *string, const char *name)
+get_nonzero_uint32(const char *string, const char *name)
{
uint32_t number;
- number = get_guint32(string, name);
+ number = get_uint32(string, name);
+
+ if (number == 0) {
+ cmdarg_err("The specified %s is zero", name);
+ exit(1);
+ }
+
+ return number;
+}
+
+uint64_t
+get_uint64(const char *string, const char *name)
+{
+ uint64_t number;
+
+ if (!ws_strtou64(string, NULL, &number)) {
+ if (errno == EINVAL) {
+ cmdarg_err("The specified %s \"%s\" isn't a decimal number", name, string);
+ exit(1);
+ }
+ cmdarg_err("The specified %s \"%s\" is too large (greater than %" PRIu64 ")",
+ name, string, number);
+ exit(1);
+ }
+ return number;
+}
+
+uint64_t
+get_nonzero_uint64(const char *string, const char *name)
+{
+ uint64_t number;
+
+ number = get_uint64(string, name);
if (number == 0) {
cmdarg_err("The specified %s is zero", name);
diff --git a/wsutil/clopts_common.h b/wsutil/clopts_common.h
index 3f8b7f71..b401ddeb 100644
--- a/wsutil/clopts_common.h
+++ b/wsutil/clopts_common.h
@@ -34,6 +34,12 @@ extern "C" {
// Base value for GUI specific long options
#define LONGOPT_BASE_GUI 4000
+#define LONGOPT_READ_CAPTURE_COMMON \
+ {"read-file", ws_required_argument, NULL, 'r' }, \
+
+#define OPTSTRING_READ_CAPTURE_COMMON \
+ "r:"
+
WS_DLL_PUBLIC int
get_natural_int(const char *string, const char *name);
@@ -41,10 +47,24 @@ WS_DLL_PUBLIC int
get_positive_int(const char *string, const char *name);
WS_DLL_PUBLIC uint32_t
-get_guint32(const char *string, const char *name);
+get_uint32(const char *string, const char *name);
+
+WS_DEPRECATED_X("Use get_uint32 instead")
+static inline uint32_t
+get_guint32(const char *string, const char *name) { return get_uint32(string, name); }
WS_DLL_PUBLIC uint32_t
-get_nonzero_guint32(const char *string, const char *name);
+get_nonzero_uint32(const char *string, const char *name);
+
+WS_DEPRECATED_X("Use get_nonzero_uint32 instead")
+static inline uint32_t
+get_nonzero_guint32(const char *string, const char *name) { return get_nonzero_uint32(string, name); }
+
+WS_DLL_PUBLIC uint64_t
+get_uint64(const char *string, const char *name);
+
+WS_DLL_PUBLIC uint64_t
+get_nonzero_uint64(const char *string, const char *name);
WS_DLL_PUBLIC double
get_positive_double(const char *string, const char *name);
diff --git a/wsutil/codecs.c b/wsutil/codecs.c
index 857cd33b..dfd5c0e0 100644
--- a/wsutil/codecs.c
+++ b/wsutil/codecs.c
@@ -18,10 +18,10 @@
#endif
#ifdef HAVE_PLUGINS
-static plugins_t *libwscodecs_plugins = NULL;
+static plugins_t *libwscodecs_plugins;
#endif
-static GSList *codecs_plugins = NULL;
+static GSList *codecs_plugins;
#ifdef HAVE_PLUGINS
void
@@ -84,7 +84,7 @@ struct codec_handle {
/*
* List of registered codecs.
*/
-static GHashTable *registered_codecs = NULL;
+static GHashTable *registered_codecs;
/* Find a registered codec by name. */
diff --git a/wsutil/console_win32.c b/wsutil/console_win32.c
index eed18c88..9548ff9b 100644
--- a/wsutil/console_win32.c
+++ b/wsutil/console_win32.c
@@ -15,7 +15,9 @@
#include <stdlib.h>
#include <glib.h>
+
#include <wsutil/file_util.h>
+#include <wsutil/filesystem.h>
#include "console_win32.h"
@@ -26,7 +28,7 @@
static bool has_console; /* true if app has console */
static bool console_wait; /* "Press any key..." */
-static bool stdin_capture = false; /* Don't grab stdin & stdout if true */
+static bool stdin_capture; /* Don't grab stdin & stdout if true */
/*
* Check whether a given standard handle needs to be redirected.
@@ -161,7 +163,11 @@ do a FreeConsole() first. */
if (AllocConsole()) {
/* That succeeded. */
console_wait = true;
- SetConsoleTitle(_T("Wireshark Debug Console"));
+ if (is_packet_configuration_namespace()) {
+ SetConsoleTitle(_T("Wireshark Debug Console"));
+ } else {
+ SetConsoleTitle(_T("Logray Debug Console"));
+ }
} else {
/* On Windows XP, this still fails; FreeConsole() apparently
doesn't clear the state, as it does on Windows 7. */
diff --git a/wsutil/cpu_info.c b/wsutil/cpu_info.c
index f9e6aa25..7c31a3bd 100644
--- a/wsutil/cpu_info.c
+++ b/wsutil/cpu_info.c
@@ -36,7 +36,7 @@
* model strings.
*/
static int
-compare_model_names(gconstpointer a, gconstpointer b, void * user_data _U_)
+compare_model_names(const void *a, const void *b, void * user_data _U_)
{
return strcmp((const char *)a, (const char *)b);
}
@@ -201,7 +201,7 @@ get_cpu_info(GString *str)
/*
* Allocate a buffer for the subkey.
*/
- subkey_buf = (wchar_t *)g_malloc(max_subkey_len * sizeof (wchar_t));
+ subkey_buf = g_new(wchar_t, max_subkey_len);
if (subkey_buf == NULL) {
/* Just give up. */
g_tree_destroy(model_names);
@@ -383,6 +383,7 @@ get_cpu_info(GString *str)
*/
uint32_t CPUInfo[4];
char CPUBrandString[0x40];
+ char *model_name;
unsigned nExIds;
/*
diff --git a/wsutil/crc16.c b/wsutil/crc16.c
index dfb2e2d6..547206b1 100644
--- a/wsutil/crc16.c
+++ b/wsutil/crc16.c
@@ -375,7 +375,7 @@ static const uint16_t crc16_usb_xorout = 0xFFFF;
static uint16_t crc16_unreflected(const uint8_t *buf, unsigned len,
uint16_t crc_in, const unsigned table[])
{
- /* we use guints, rather than guint16s, as they are likely to be
+ /* we use uints, rather than uint16s, as they are likely to be
faster. We just ignore the top 16 bits and let them do what they want.
*/
unsigned crc16 = (unsigned)crc_in;
@@ -389,7 +389,7 @@ static uint16_t crc16_unreflected(const uint8_t *buf, unsigned len,
static uint16_t crc16_reflected(const uint8_t *buf, unsigned len,
uint16_t crc_in, const unsigned table[])
{
- /* we use guints, rather than guint16s, as they are likely to be
+ /* we use uints, rather than uint16s, as they are likely to be
faster. We just ignore the top 16 bits and let them do what they want.
XXX - does any time saved not zero-extending uint16_t's to 32 bits
into a register outweigh any increased cache footprint from the
diff --git a/wsutil/crc32.c b/wsutil/crc32.c
index 4be3d651..96ec9db0 100644
--- a/wsutil/crc32.c
+++ b/wsutil/crc32.c
@@ -17,6 +17,15 @@
#include <wsutil/crc32.h>
+#ifdef HAVE_ZLIBNG
+#include <zlib-ng.h>
+#else
+#ifdef HAVE_ZLIB
+#define ZLIB_CONST
+#include <zlib.h>
+#endif /* HAVE_ZLIB */
+#endif
+
#define CRC32_ACCUMULATE(c,d,table) (c=(c>>8)^(table)[(c^(d))&0xFF])
/*****************************************************************/
@@ -395,6 +404,13 @@ crc32_ccitt(const uint8_t *buf, unsigned len)
uint32_t
crc32_ccitt_seed(const uint8_t *buf, unsigned len, uint32_t seed)
{
+#if defined (HAVE_ZLIB) || defined (HAVE_ZLIBNG)
+#ifdef HAVE_ZLIBNG
+ return (unsigned)zng_crc32(~seed, buf, len);
+#else
+ return (unsigned)crc32(~seed, buf, len);
+#endif
+#else
unsigned i;
uint32_t crc32 = seed;
@@ -402,6 +418,7 @@ crc32_ccitt_seed(const uint8_t *buf, unsigned len, uint32_t seed)
CRC32_ACCUMULATE(crc32, buf[i], crc32_ccitt_table);
return ( ~crc32 );
+#endif
}
uint32_t
diff --git a/wsutil/epochs.h b/wsutil/epochs.h
index 17d62728..27a88473 100644
--- a/wsutil/epochs.h
+++ b/wsutil/epochs.h
@@ -62,6 +62,12 @@
* (as they lack a leap year), and one leftover year, 1969, that is
* 365 days long.
*/
-#define EPOCH_DELTA_1601_01_01_00_00_00_UTC G_GUINT64_CONSTANT(11644473600)
+#define EPOCH_DELTA_1601_01_01_00_00_00_UTC UINT64_C(11644473600)
+
+/*
+ * 2000-01-01 00:00:00 UTC.
+ * Used by the Zigbee Zigbee Cluster Library protocol.
+ */
+#define EPOCH_DELTA_2000_01_01_00_00_00_UTC ((unsigned)(((3*365 + 366)*7 + 2*365)*24*3600))
#endif /* __EPOCHS_H__ */
diff --git a/wsutil/exported_pdu_tlvs.h b/wsutil/exported_pdu_tlvs.h
index 4850be8e..2799b8a7 100644
--- a/wsutil/exported_pdu_tlvs.h
+++ b/wsutil/exported_pdu_tlvs.h
@@ -175,11 +175,22 @@
#define EXP_PDU_TAG_P2P_DIRECTION 35 /**< The packet direction (P2P_DIR_SENT, P2P_DIR_RECV). */
-#define EXP_PDU_TAG_COL_INFO_TEXT 36 /**< UTF-8 text string to put in COL_INFO, useful when puting meta data into the packet list.
+#define EXP_PDU_TAG_COL_INFO_TEXT 36 /**< UTF-8 text string to put in COL_INFO, useful when putting meta data into the packet list.
*/
#define EXP_PDU_TAG_USER_DATA_PDU 37 /**< Raw user data PDU which can be dissected as any protocol. */
+/* 3GPP identity types for EXP_PDU_TAG_3GPP_ID */
+#define EXP_PDU_3GPP_ID_CGI 0 /**< 56-bit 2G/3G Cell Global Identifier (MNC big-endian encoding) */
+#define EXP_PDU_3GPP_ID_ECGI 1 /**< 52-bit 4G E-UTRAN Cell Global Identifier (MNC big-endian encoding) */
+#define EXP_PDU_3GPP_ID_NCGI 2 /**< 60-bit NR Cell Global Identifier (MNC big-endian encoding) */
+
+/**< Stores a 3GPP identifier.
+ The value begins with a 1-byte identity type (EXP_PDU_3GPP_ID_*),
+ followed by the identity itself.
+*/
+#define EXP_PDU_TAG_3GPP_ID 38
+
#define EXP_PDU_TAG_IPV4_LEN 4
#define EXP_PDU_TAG_IPV6_LEN 16
diff --git a/wsutil/feature_list.c b/wsutil/feature_list.c
index f0c30d66..c06a453e 100644
--- a/wsutil/feature_list.c
+++ b/wsutil/feature_list.c
@@ -22,7 +22,7 @@ with_feature(feature_list l, const char *fmt, ...)
va_start(arg, fmt);
g_string_append_vprintf(msg, fmt, arg);
va_end(arg);
- *l = g_list_prepend(*l, g_string_free(msg, false));
+ *l = g_list_prepend(*l, g_string_free(msg, FALSE));
}
void
@@ -33,11 +33,11 @@ without_feature(feature_list l, const char *fmt, ...)
va_start(arg, fmt);
g_string_append_vprintf(msg, fmt, arg);
va_end(arg);
- *l = g_list_prepend(*l, g_string_free(msg, false));
+ *l = g_list_prepend(*l, g_string_free(msg, FALSE));
}
static int
-feature_sort_alpha(gconstpointer a, gconstpointer b)
+feature_sort_alpha(const void *a, const void *b)
{
return g_ascii_strcasecmp((char *)a + 1, (char *)b + 1);
}
diff --git a/wsutil/file_util.c b/wsutil/file_util.c
index 4fd55180..d36ae75f 100644
--- a/wsutil/file_util.c
+++ b/wsutil/file_util.c
@@ -60,9 +60,9 @@
#include "file_util.h"
#include "ws_attributes.h"
-static char *program_path = NULL;
-static char *system_path = NULL;
-static char *npcap_path = NULL;
+static char *program_path;
+static char *system_path;
+static char *npcap_path;
/**
* g_open:
@@ -630,8 +630,8 @@ load_wpcap_module(void)
*/
#define WIRESHARK_IS_RUNNING_UUID "9CA78EEA-EA4D-4490-9240-FC01FCEF464B"
-static HANDLE local_running_mutex = NULL;
-static HANDLE global_running_mutex = NULL;
+static HANDLE local_running_mutex;
+static HANDLE global_running_mutex;
void create_app_running_mutex(void) {
SECURITY_DESCRIPTOR sec_descriptor;
diff --git a/wsutil/filesystem.c b/wsutil/filesystem.c
index 065cdd3c..bec1cea2 100644
--- a/wsutil/filesystem.c
+++ b/wsutil/filesystem.c
@@ -9,10 +9,10 @@
*/
#include "config.h"
-#include "filesystem.h"
-
#define WS_LOG_DOMAIN LOG_DOMAIN_WSUTIL
+#include "filesystem.h"
+
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -73,18 +73,19 @@ enum configuration_namespace_e configuration_namespace = CONFIGURATION_NAMESPACE
#define CONFIGURATION_NAMESPACE_LOWER (configuration_namespace == CONFIGURATION_NAMESPACE_WIRESHARK ? "wireshark" : "logray")
#define CONFIGURATION_ENVIRONMENT_VARIABLE(suffix) (configuration_namespace == CONFIGURATION_NAMESPACE_WIRESHARK ? "WIRESHARK_" suffix : "LOGRAY_" suffix)
-char *persconffile_dir = NULL;
-char *datafile_dir = NULL;
-char *persdatafile_dir = NULL;
-char *persconfprofile = NULL;
-char *doc_dir = NULL;
+char *persconffile_dir;
+char *datafile_dir;
+char *persdatafile_dir;
+char *persconfprofile;
+char *doc_dir;
+char *current_working_dir;
/* Directory from which the executable came. */
-static char *progfile_dir = NULL;
-static char *install_prefix = NULL;
+static char *progfile_dir;
+static char *install_prefix;
-static bool do_store_persconffiles = false;
-static GHashTable *profile_files = NULL;
+static bool do_store_persconffiles;
+static GHashTable *profile_files;
/*
* Given a pathname, return a pointer to the last pathname separator
@@ -219,6 +220,21 @@ test_for_fifo(const char *path)
return 0;
}
+bool
+test_for_regular_file(const char *path)
+{
+ ws_statb64 statb;
+
+ if (!path) {
+ return false;
+ }
+
+ if (ws_stat64(path, &statb) != 0)
+ return false;
+
+ return S_ISREG(statb.st_mode);
+}
+
#ifdef ENABLE_APPLICATION_BUNDLE
/*
* Directory of the application bundle in which we're contained,
@@ -278,7 +294,7 @@ static char *appbundle_dir;
* true if we're running from the build directory and we aren't running
* with special privileges.
*/
-static bool running_in_build_directory_flag = false;
+static bool running_in_build_directory_flag;
/*
* Set our configuration namespace. This will be used for top-level
@@ -524,6 +540,13 @@ get_current_executable_path(void)
static void trim_progfile_dir(void)
{
+#ifdef _WIN32
+ char *namespace_last_dir = find_last_pathname_separator(progfile_dir);
+ if (namespace_last_dir && strncmp(namespace_last_dir + 1, CONFIGURATION_NAMESPACE_LOWER, sizeof(CONFIGURATION_NAMESPACE_LOWER)) == 0) {
+ *namespace_last_dir = '\0';
+ }
+#endif
+
char *progfile_last_dir = find_last_pathname_separator(progfile_dir);
if (! (progfile_last_dir && strncmp(progfile_last_dir + 1, "extcap", sizeof("extcap")) == 0)) {
@@ -581,7 +604,7 @@ get_executable_path(const char *program_name)
* g_mallocated string containing an error on failure.
*/
#ifdef _WIN32
-char *
+static char *
configuration_init_w32(const char* arg0 _U_)
{
TCHAR prog_pathname_w[_MAX_PATH+2];
@@ -666,7 +689,7 @@ configuration_init_w32(const char* arg0 _U_)
#else /* !_WIN32 */
-char *
+static char *
configuration_init_posix(const char* arg0)
{
const char *execname;
@@ -943,6 +966,33 @@ get_progfile_dir(void)
return progfile_dir;
}
+extern const char *
+get_current_working_dir(void)
+{
+ if (current_working_dir != NULL) {
+ return current_working_dir;
+ }
+
+ /*
+ * It's good to cache this because on Windows Microsoft cautions
+ * against using GetCurrentDirectory except early on, e.g. when
+ * parsing command line options.
+ */
+ current_working_dir = g_get_current_dir();
+ /*
+ * The above always returns something, with a fallback, e.g., on macOS
+ * if the program is run from Finder, of G_DIR_SEPARATOR_S.
+ * On Windows when run from a shortcut / taskbar it returns whatever
+ * the "run in" directory is on the shortcut, which is usually the
+ * directory where the program resides, which isn't that useful.
+ * Should we set it to the home directory on macOS or the
+ * "My Documents" folder on Windows in those cases,
+ * as we do in get_persdatafile_dir()? This isn't the default preference
+ * setting so perhaps caveat emptor is ok.
+ */
+ return current_working_dir;
+}
+
/*
* Get the directory in which the global configuration and data files are
* stored.
@@ -1000,7 +1050,7 @@ get_datafile_dir(void)
if (running_in_build_directory_flag) {
datafile_dir = g_strdup(install_prefix);
} else {
- datafile_dir = g_build_filename(install_prefix, DATA_DIR, (char *)NULL);
+ datafile_dir = g_build_filename(install_prefix, DATA_DIR, CONFIGURATION_NAMESPACE_LOWER, (char *)NULL);
}
#elif defined(_WIN32)
/*
@@ -1057,7 +1107,7 @@ get_datafile_dir(void)
*/
datafile_dir = g_strdup(progfile_dir);
} else {
- datafile_dir = g_build_filename(install_prefix, DATA_DIR, (char *)NULL);
+ datafile_dir = g_build_filename(install_prefix, DATA_DIR, CONFIGURATION_NAMESPACE_LOWER, (char *)NULL);
}
#endif
return datafile_dir;
@@ -1099,8 +1149,7 @@ get_doc_dir(void)
* it; we don't need to call started_with_special_privs().)
*/
else if (appbundle_dir != NULL) {
- doc_dir = ws_strdup_printf("%s/Contents/Resources/%s",
- appbundle_dir, DOC_DIR);
+ doc_dir = g_strdup(get_datafile_dir());
}
#endif
else if (running_in_build_directory_flag && progfile_dir != NULL) {
@@ -1138,11 +1187,11 @@ get_doc_dir(void)
* otherwise, we use the PLUGIN_DIR value supplied by the
* configure script.
*/
-static char *plugin_dir = NULL;
-static char *plugin_dir_with_version = NULL;
-static char *plugin_pers_dir = NULL;
-static char *plugin_pers_dir_with_version = NULL;
-static char *extcap_pers_dir = NULL;
+static char *plugin_dir;
+static char *plugin_dir_with_version;
+static char *plugin_pers_dir;
+static char *plugin_pers_dir_with_version;
+static char *extcap_pers_dir;
static void
init_plugin_dir(void)
@@ -1155,47 +1204,22 @@ init_plugin_dir(void)
* Let {WIRESHARK,LOGRAY}_PLUGIN_DIR take precedence.
*/
plugin_dir = g_strdup(g_getenv(plugin_dir_envar));
- return;
}
#if defined(HAVE_PLUGINS) || defined(HAVE_LUA)
#if defined(HAVE_MSYSTEM)
- if (running_in_build_directory_flag) {
+ else if (running_in_build_directory_flag) {
plugin_dir = g_build_filename(install_prefix, "plugins", (char *)NULL);
} else {
plugin_dir = g_build_filename(install_prefix, PLUGIN_DIR, (char *)NULL);
}
#elif defined(_WIN32)
- /*
- * On Windows, the data file directory is the installation
- * directory; the plugins are stored under it.
- *
- * Assume we're running the installed version of Wireshark;
- * on Windows, the data file directory is the directory
- * in which the Wireshark binary resides.
- */
- plugin_dir = g_build_filename(get_datafile_dir(), "plugins", (char *)NULL);
-
- /*
- * Make sure that pathname refers to a directory.
- */
- if (test_for_directory(plugin_dir) != EISDIR) {
+ else {
/*
- * Either it doesn't refer to a directory or it
- * refers to something that doesn't exist.
- *
- * Assume that means we're running a version of
- * Wireshark we've built in a build directory,
- * in which case {datafile dir}\plugins is the
- * top-level plugins source directory, and use
- * that directory and set the "we're running in
- * a build directory" flag, so the plugin
- * scanner will check all subdirectories of that
- * directory for plugins.
+ * On Windows, plugins are stored under the program file directory
+ * in both the build and the installation directories.
*/
- g_free(plugin_dir);
- plugin_dir = g_build_filename(get_datafile_dir(), "plugins", (char *)NULL);
- running_in_build_directory_flag = true;
+ plugin_dir = g_build_filename(get_progfile_dir(), "plugins", (char *)NULL);
}
#else
#ifdef ENABLE_APPLICATION_BUNDLE
@@ -1212,7 +1236,7 @@ init_plugin_dir(void)
plugin_dir = g_build_filename(appbundle_dir, "Contents/PlugIns",
CONFIGURATION_NAMESPACE_LOWER, (char *)NULL);
}
-#endif
+#endif // ENABLE_APPLICATION_BUNDLE
else if (running_in_build_directory_flag) {
/*
* We're (probably) being run from the build directory and
@@ -1224,7 +1248,7 @@ init_plugin_dir(void)
} else {
plugin_dir = g_build_filename(install_prefix, PLUGIN_DIR, (char *)NULL);
}
-#endif
+#endif // HAVE_MSYSTEM / _WIN32
#endif /* defined(HAVE_PLUGINS) || defined(HAVE_LUA) */
}
@@ -1287,7 +1311,7 @@ get_plugins_pers_dir_with_version(void)
* If the WIRESHARK_EXTCAP_DIR environment variable is set and we are not
* running with special privileges, use that. Otherwise:
*
- * On Windows, we use the "extcap" subdirectory of the datafile directory.
+ * On Windows, we use the "extcap" subdirectory of the program directory.
*
* On UN*X:
*
@@ -1299,7 +1323,7 @@ get_plugins_pers_dir_with_version(void)
*
* otherwise, we use the EXTCAP_DIR value supplied by CMake.
*/
-static char *extcap_dir = NULL;
+static char *extcap_dir;
static void
init_extcap_dir(void)
@@ -1322,25 +1346,14 @@ init_extcap_dir(void)
#elif defined(_WIN32)
else {
/*
- * On Windows, the data file directory is the installation
- * directory; the extcap hooks are stored under it.
- *
- * Assume we're running the installed version of Wireshark;
- * on Windows, the data file directory is the directory
- * in which the Wireshark binary resides.
+ * On Windows, extcap utilities are stored in "extcap/<program name>"
+ * in the program file directory in both the build and installation
+ * directories.
*/
- extcap_dir = g_build_filename(get_datafile_dir(), "extcap", (char *)NULL);
+ extcap_dir = g_build_filename(get_progfile_dir(), EXTCAP_DIR_NAME,
+ CONFIGURATION_NAMESPACE_LOWER, (char *)NULL);
}
#else
- else if (running_in_build_directory_flag) {
- /*
- * We're (probably) being run from the build directory and
- * weren't started with special privileges, so we'll use
- * the "extcap hooks" subdirectory of the directory where the program
- * we're running is (that's the build directory).
- */
- extcap_dir = g_build_filename(get_progfile_dir(), "extcap", (char *)NULL);
- }
#ifdef ENABLE_APPLICATION_BUNDLE
else if (appbundle_dir != NULL) {
/*
@@ -1354,11 +1367,22 @@ init_extcap_dir(void)
*/
extcap_dir = g_build_filename(appbundle_dir, "Contents/MacOS/extcap", (char *)NULL);
}
-#endif
+#endif // ENABLE_APPLICATION_BUNDLE
+ else if (running_in_build_directory_flag) {
+ /*
+ * We're (probably) being run from the build directory and
+ * weren't started with special privileges, so we'll use
+ * the "extcap hooks" subdirectory of the directory where the program
+ * we're running is (that's the build directory).
+ */
+ extcap_dir = g_build_filename(get_progfile_dir(), EXTCAP_DIR_NAME,
+ CONFIGURATION_NAMESPACE_LOWER, (char *)NULL);
+ }
else {
- extcap_dir = g_build_filename(install_prefix, EXTCAP_DIR, (char *)NULL);
+ extcap_dir = g_build_filename(install_prefix,
+ is_packet_configuration_namespace() ? EXTCAP_DIR : LOG_EXTCAP_DIR, (char *)NULL);
}
-#endif
+#endif // HAVE_MSYSTEM / _WIN32
}
static void
@@ -2040,7 +2064,7 @@ copy_persconffile_profile(const char *toname, const char *fromname, bool from_gl
from_file = ws_strdup_printf ("%s%s%s", from_dir, G_DIR_SEPARATOR_S, filename);
to_file = ws_strdup_printf ("%s%s%s", to_dir, G_DIR_SEPARATOR_S, filename);
- if (file_exists(from_file) && !copy_file_binary_mode(from_file, to_file)) {
+ if (test_for_regular_file(from_file) && !copy_file_binary_mode(from_file, to_file)) {
*pf_filename_return = g_strdup(filename);
g_free (from_file);
g_free (to_file);
@@ -2393,37 +2417,48 @@ bool config_file_exists_with_entries(const char *fname, char comment_char)
bool
files_identical(const char *fname1, const char *fname2)
{
- /* Two different implementations, because:
- *
- * - _fullpath is not available on UN*X, so we can't get full
- * paths and compare them (which wouldn't work with hard links
- * in any case);
- *
- * - st_ino isn't filled in with a meaningful value on Windows.
+ /* Two different implementations, because st_ino isn't filled in with
+ * a meaningful value on Windows. Use the Windows API and FILE_ID_INFO
+ * instead.
*/
#ifdef _WIN32
- char full1[MAX_PATH], full2[MAX_PATH];
+
+ FILE_ID_INFO filestat1, filestat2;
/*
- * Get the absolute full paths of the file and compare them.
- * That won't work if you have hard links, but those aren't
- * much used on Windows, even though NTFS supports them.
- *
- * XXX - will _fullpath work with UNC?
+ * Compare VolumeSerialNumber and FileId.
*/
- if( _fullpath( full1, fname1, MAX_PATH ) == NULL ) {
+
+ HANDLE h1 = CreateFile(utf_8to16(fname1), 0,
+ FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
+ NULL, OPEN_EXISTING, 0, NULL);
+
+ if (h1 == INVALID_HANDLE_VALUE) {
return false;
}
- if( _fullpath( full2, fname2, MAX_PATH ) == NULL ) {
+ if (!GetFileInformationByHandleEx(h1, FileIdInfo, &filestat1, sizeof(FILE_ID_INFO))) {
+ CloseHandle(h1);
return false;
}
+ CloseHandle(h1);
- if(strcmp(full1, full2) == 0) {
- return true;
- } else {
+ HANDLE h2 = CreateFile(utf_8to16(fname2), 0,
+ FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
+ NULL, OPEN_EXISTING, 0, NULL);
+
+ if (h2 == INVALID_HANDLE_VALUE) {
return false;
}
+
+ if (!GetFileInformationByHandleEx(h2, FileIdInfo, &filestat2, sizeof(FILE_ID_INFO))) {
+ CloseHandle(h2);
+ return false;
+ }
+ CloseHandle(h2);
+
+ return ((memcmp(&filestat1.FileId, &filestat2.FileId, sizeof(FILE_ID_128)) == 0) &&
+ filestat1.VolumeSerialNumber == filestat2.VolumeSerialNumber);
#else
ws_statb64 filestat1, filestat2;
@@ -2692,6 +2727,8 @@ free_progdirs(void)
doc_dir = NULL;
g_free(install_prefix);
install_prefix = NULL;
+ g_free(current_working_dir);
+ current_working_dir = NULL;
#if defined(HAVE_PLUGINS) || defined(HAVE_LUA)
g_free(plugin_dir);
plugin_dir = NULL;
diff --git a/wsutil/filesystem.h b/wsutil/filesystem.h
index fd3e3ebc..e1e2aead 100644
--- a/wsutil/filesystem.h
+++ b/wsutil/filesystem.h
@@ -302,6 +302,11 @@ WS_DLL_PUBLIC const char *get_persdatafile_dir(void);
WS_DLL_PUBLIC void set_persdatafile_dir(const char *p);
/*
+ * Get the current working directory.
+ */
+WS_DLL_PUBLIC WS_RETNONNULL const char *get_current_working_dir(void);
+
+/*
* Return an error message for UNIX-style errno indications on open or
* create operations.
*/
@@ -359,7 +364,14 @@ WS_DLL_PUBLIC int test_for_directory(const char *);
WS_DLL_PUBLIC int test_for_fifo(const char *);
/*
- * Check, if file is existing.
+ * Given a pathname, return true if the attempt to "stat()" the file
+ * succeeds, and it turns out to be a regular file. "stat()" follows
+ * links, so returns true if the pathname is a link to a regular file.
+ */
+WS_DLL_PUBLIC bool test_for_regular_file(const char *);
+
+/*
+ * Check if a file exists.
*/
WS_DLL_PUBLIC bool file_exists(const char *fname);
diff --git a/wsutil/filter_files.c b/wsutil/filter_files.c
index 48464892..1c3c013f 100644
--- a/wsutil/filter_files.c
+++ b/wsutil/filter_files.c
@@ -23,16 +23,6 @@
#include <wsutil/ws_assert.h>
/*
- * List of capture filters - saved.
- */
-static GList *capture_filters = NULL;
-
-/*
- * List of display filters - saved.
- */
-static GList *display_filters = NULL;
-
-/*
* Read in a list of filters.
*
* On error, report the error via the UI.
@@ -60,16 +50,10 @@ free_filter_entry(void * data)
g_free(filt);
}
-void free_filter_lists(void)
+void ws_filter_list_free(filter_list_t *fl)
{
- if (capture_filters) {
- g_list_free_full(capture_filters, free_filter_entry);
- capture_filters = NULL;
- }
- if (display_filters) {
- g_list_free_full(display_filters, free_filter_entry);
- display_filters = NULL;
- }
+ g_list_free_full(fl->list, free_filter_entry);
+ g_free(fl);
}
static GList *
@@ -114,36 +98,42 @@ getc_crlf(FILE *ff)
return c;
}
-void
-read_filter_list(filter_list_type_t list_type)
+filter_list_t *
+ws_filter_list_read(filter_list_type_t list_type)
{
const char *ff_name, *ff_description;
char *ff_path;
FILE *ff;
- GList **flpp;
+ GList *flp = NULL;
int c;
char *filt_name, *filt_expr;
int filt_name_len, filt_expr_len;
int filt_name_index, filt_expr_index;
int line = 1;
+ filter_list_t *list = g_new(filter_list_t, 1);
+ list->type = list_type;
+ list->list = NULL;
+
switch (list_type) {
case CFILTER_LIST:
ff_name = CFILTER_FILE_NAME;
ff_description = "capture";
- flpp = &capture_filters;
break;
case DFILTER_LIST:
ff_name = DFILTER_FILE_NAME;
ff_description = "display";
- flpp = &display_filters;
+ break;
+
+ case DMACROS_LIST:
+ ff_name = DMACROS_FILE_NAME;
+ ff_description = "display filter macro";
break;
default:
ws_assert_not_reached();
- return;
}
/* try to open personal "cfilters"/"dfilters" file */
@@ -159,59 +149,28 @@ read_filter_list(filter_list_type_t list_type)
report_warning("Could not open your %s filter file\n\"%s\": %s.",
ff_description, ff_path, g_strerror(errno));
g_free(ff_path);
- return;
+ return list;
}
/*
- * Yes. See if there's an "old style" personal "filters" file; if so, read it.
- * This means that a user will start out with their capture and
- * display filter lists being identical; each list may contain
- * filters that don't belong in that list. The user can edit
- * the filter lists, and delete the ones that don't belong in
- * a particular list.
+ * Yes. Try to open the global "cfilters/dfilters" file.
*/
g_free(ff_path);
- ff_path = get_persconffile_path(FILTER_FILE_NAME, false);
+ ff_path = get_datafile_path(ff_name);
if ((ff = ws_fopen(ff_path, "r")) == NULL) {
/*
- * Did that fail because the file didn't exist?
+ * Well, that didn't work, either. Just give up.
+ * Report an error if the file existed but we couldn't open it.
*/
if (errno != ENOENT) {
- /*
- * No. Just give up.
- */
report_warning("Could not open your %s filter file\n\"%s\": %s.",
ff_description, ff_path, g_strerror(errno));
- g_free(ff_path);
- return;
}
-
- /*
- * Try to open the global "cfilters/dfilters" file.
- */
g_free(ff_path);
- ff_path = get_datafile_path(ff_name);
- if ((ff = ws_fopen(ff_path, "r")) == NULL) {
- /*
- * Well, that didn't work, either. Just give up.
- * Report an error if the file existed but we couldn't open it.
- */
- if (errno != ENOENT) {
- report_warning("Could not open your %s filter file\n\"%s\": %s.",
- ff_description, ff_path, g_strerror(errno));
- }
- g_free(ff_path);
- return;
- }
+ return list;
}
}
- /* If we already have a list of filters, discard it. */
- /* this should never happen - this function is called only once for each list! */
- while(*flpp) {
- *flpp = remove_filter_entry(*flpp, g_list_first(*flpp));
- }
-
/* Allocate the filter name buffer. */
filt_name_len = INIT_BUF_SIZE;
filt_name = (char *)g_malloc(filt_name_len + 1);
@@ -235,6 +194,12 @@ read_filter_list(filter_list_type_t list_type)
break; /* Nothing more to read */
if (c == '\n')
continue; /* Blank line. */
+ if (c == '#') {
+ /* Comment. */
+ while (c != '\n')
+ c = getc(ff); /* skip to the end of the line */
+ continue;
+ }
/* "c" is the first non-white-space character.
If it's not a quote, it's an error. */
@@ -319,7 +284,7 @@ read_filter_list(filter_list_type_t list_type)
for (;;) {
/* Add this character to the filter expression string. */
if (filt_expr_index >= filt_expr_len) {
- /* Filter expressioin buffer isn't long enough; double its length. */
+ /* Filter expression buffer isn't long enough; double its length. */
filt_expr_len *= 2;
filt_expr = (char *)g_realloc(filt_expr, filt_expr_len + 1);
}
@@ -343,14 +308,14 @@ read_filter_list(filter_list_type_t list_type)
/* We saw the ending newline; terminate the filter expression string */
if (filt_expr_index >= filt_expr_len) {
- /* Filter expressioin buffer isn't long enough; double its length. */
+ /* Filter expression buffer isn't long enough; double its length. */
filt_expr_len *= 2;
filt_expr = (char *)g_realloc(filt_expr, filt_expr_len + 1);
}
filt_expr[filt_expr_index] = '\0';
/* Add the new filter to the list of filters */
- *flpp = add_filter_entry(*flpp, filt_name, filt_expr);
+ flp = add_filter_entry(flp, filt_name, filt_expr);
}
if (ferror(ff)) {
report_warning("Error reading your %s filter file\n\"%s\": %s.",
@@ -360,71 +325,44 @@ read_filter_list(filter_list_type_t list_type)
fclose(ff);
g_free(filt_name);
g_free(filt_expr);
+ list->list = flp;
+ return list;
}
/*
- * Get a pointer to a list of filters.
+ * Add a new filter to the end of a list.
*/
-static GList **
-get_filter_list(filter_list_type_t list_type)
+void
+ws_filter_list_add(filter_list_t *fl, const char *name,
+ const char *expression)
{
- GList **flpp;
-
- switch (list_type) {
-
- case CFILTER_LIST:
- flpp = &capture_filters;
- break;
-
- case DFILTER_LIST:
- flpp = &display_filters;
- break;
-
- default:
- ws_assert_not_reached();
- flpp = NULL;
- }
- return flpp;
+ fl->list = add_filter_entry(fl->list, name, expression);
}
-/*
- * Get a pointer to the first entry in a filter list.
- */
-GList *
-get_filter_list_first(filter_list_type_t list_type)
+static int
+compare_def(const void *def, const void *name)
{
- GList **flpp;
-
- flpp = get_filter_list(list_type);
- return g_list_first(*flpp);
+ return g_strcmp0(((filter_def *)def)->name, name);
}
-/*
- * Add a new filter to the end of a list.
- * Returns a pointer to the newly-added entry.
- */
-GList *
-add_to_filter_list(filter_list_type_t list_type, const char *name,
- const char *expression)
+GList *ws_filter_list_find(filter_list_t *list, const char *name)
{
- GList **flpp;
-
- flpp = get_filter_list(list_type);
- *flpp = add_filter_entry(*flpp, name, expression);
-
- return g_list_last(*flpp);
+ return g_list_find_custom(list->list, name, compare_def);
}
/*
* Remove a filter from a list.
*/
-void
-remove_from_filter_list(filter_list_type_t list_type, GList *fl_entry)
+bool
+ws_filter_list_remove(filter_list_t *list, const char *name)
{
- GList **flpp;
+ GList *p;
- flpp = get_filter_list(list_type);
- *flpp = remove_filter_entry(*flpp, fl_entry);
+ p = g_list_find_custom(list->list, name, compare_def);
+ if (p == NULL)
+ return false;
+ list->list = remove_filter_entry(list->list, p);
+ return true;
}
/*
@@ -433,7 +371,7 @@ remove_from_filter_list(filter_list_type_t list_type, GList *fl_entry)
* On error, report the error via the UI.
*/
void
-save_filter_list(filter_list_type_t list_type)
+ws_filter_list_write(filter_list_t *list)
{
char *pf_dir_path;
const char *ff_name, *ff_description;
@@ -444,24 +382,28 @@ save_filter_list(filter_list_type_t list_type)
FILE *ff;
unsigned char *p, c;
- switch (list_type) {
+ switch (list->type) {
case CFILTER_LIST:
ff_name = CFILTER_FILE_NAME;
ff_description = "capture";
- fl = capture_filters;
break;
case DFILTER_LIST:
ff_name = DFILTER_FILE_NAME;
ff_description = "display";
- fl = display_filters;
+ break;
+
+ case DMACROS_LIST:
+ ff_name = DMACROS_FILE_NAME;
+ ff_description = "display filter macros";
break;
default:
ws_assert_not_reached();
return;
}
+ fl = list->list;
/* Create the directory that holds personal configuration files,
if necessary. */
diff --git a/wsutil/filter_files.h b/wsutil/filter_files.h
index f3e67872..b493d68a 100644
--- a/wsutil/filter_files.h
+++ b/wsutil/filter_files.h
@@ -19,11 +19,6 @@ extern "C" {
#endif /* __cplusplus */
/*
- * Old filter file name.
- */
-#define FILTER_FILE_NAME "filters"
-
-/*
* Capture filter file name.
*/
#define CFILTER_FILE_NAME "cfilters"
@@ -34,11 +29,17 @@ extern "C" {
#define DFILTER_FILE_NAME "dfilters"
/*
+ * Display filter file name.
+ */
+#define DMACROS_FILE_NAME "dmacros"
+
+/*
* Filter lists.
*/
typedef enum {
CFILTER_LIST, /* capture filter list - saved */
- DFILTER_LIST /* display filter list - saved */
+ DFILTER_LIST, /* display filter list - saved */
+ DMACROS_LIST, /* display filter macro list - saved */
} filter_list_type_t;
/*
@@ -49,33 +50,40 @@ typedef struct {
char *strval; /* filter expression */
} filter_def;
+typedef struct {
+ filter_list_type_t type;
+ GList *list;
+} filter_list_t;
+
/*
* Read in a list of filters.
*
* On error, report the error via the UI.
*/
WS_DLL_PUBLIC
-void read_filter_list(filter_list_type_t list_type);
+WS_RETNONNULL
+filter_list_t *ws_filter_list_read(filter_list_type_t list_type);
/*
- * Get a pointer to the first entry in a filter list.
+ * Add a new filter to the end of a list.
+ * Returns a pointer to the newly-added entry.
*/
WS_DLL_PUBLIC
-GList *get_filter_list_first(filter_list_type_t list);
+void ws_filter_list_add(filter_list_t *list, const char *name,
+ const char *expression);
/*
- * Add a new filter to the end of a list.
- * Returns a pointer to the newly-added entry.
+ * Find a filter in a list by name.
+ * Returns a pointer to the found entry.
*/
WS_DLL_PUBLIC
-GList *add_to_filter_list(filter_list_type_t list, const char *name,
- const char *expression);
+GList *ws_filter_list_find(filter_list_t *list, const char *name);
/*
* Remove a filter from a list.
*/
WS_DLL_PUBLIC
-void remove_from_filter_list(filter_list_type_t list, GList *fl_entry);
+bool ws_filter_list_remove(filter_list_t *list, const char *name);
/*
* Write out a list of filters.
@@ -83,13 +91,13 @@ void remove_from_filter_list(filter_list_type_t list, GList *fl_entry);
* On error, report the error via the UI.
*/
WS_DLL_PUBLIC
-void save_filter_list(filter_list_type_t list_type);
+void ws_filter_list_write(filter_list_t *list);
/*
* Free all filter lists
*/
WS_DLL_PUBLIC
-void free_filter_lists(void);
+void ws_filter_list_free(filter_list_t *list);
#ifdef __cplusplus
}
diff --git a/wsutil/g711.c b/wsutil/g711.c
index e6c3dcae..7e2345c1 100644
--- a/wsutil/g711.c
+++ b/wsutil/g711.c
@@ -37,11 +37,11 @@
#define SEG_SHIFT (4) /* Left shift for segment number. */
#define SEG_MASK (0x70) /* Segment field mask. */
-static short seg_end[8] = {0xFF, 0x1FF, 0x3FF, 0x7FF,
- 0xFFF, 0x1FFF, 0x3FFF, 0x7FFF};
+static const short seg_end[8] = {0xFF, 0x1FF, 0x3FF, 0x7FF,
+ 0xFFF, 0x1FFF, 0x3FFF, 0x7FFF};
/* copy from CCITT G.711 specifications */
-unsigned char _u2a[128] = { /* u- to A-law conversions */
+const unsigned char _u2a[128] = { /* u- to A-law conversions */
1, 1, 2, 2, 3, 3, 4, 4,
5, 5, 6, 6, 7, 7, 8, 8,
9, 10, 11, 12, 13, 14, 15, 16,
@@ -59,7 +59,7 @@ unsigned char _u2a[128] = { /* u- to A-law conversions */
113, 114, 115, 116, 117, 118, 119, 120,
121, 122, 123, 124, 125, 126, 127, 128};
-unsigned char _a2u[128] = { /* A- to u-law conversions */
+const unsigned char _a2u[128] = { /* A- to u-law conversions */
1, 3, 5, 7, 9, 11, 13, 15,
16, 17, 18, 19, 20, 21, 22, 23,
24, 25, 26, 27, 28, 29, 30, 31,
@@ -80,7 +80,7 @@ unsigned char _a2u[128] = { /* A- to u-law conversions */
static int
search(
int val,
- short *table,
+ const short *table,
int size)
{
int i;
diff --git a/wsutil/glib-compat.h b/wsutil/glib-compat.h
index 08c87009..ed7511cf 100644
--- a/wsutil/glib-compat.h
+++ b/wsutil/glib-compat.h
@@ -22,9 +22,71 @@
extern "C" {
#endif /* __cplusplus */
+#if !GLIB_CHECK_VERSION(2, 61, 2)
+
+typedef volatile gint gatomicrefcount;
+
+typedef struct _GRealArray GRealArray;
+struct _GRealArray
+{
+ guint8 *data;
+ guint len;
+ guint alloc;
+ guint elt_size;
+ guint zero_terminated ;
+ guint clear;
+ gatomicrefcount ref_count;
+ GDestroyNotify clear_func;
+};
+
+static inline gboolean
+g_array_binary_search (GArray *array,
+ const void * target,
+ GCompareFunc compare_func,
+ guint *out_match_index)
+{
+ gboolean result = FALSE;
+ GRealArray *_array = (GRealArray *) array;
+ guint left, middle, right;
+ gint val;
+
+ g_return_val_if_fail (_array != NULL, FALSE);
+ g_return_val_if_fail (compare_func != NULL, FALSE);
+
+ if (G_LIKELY(_array->len))
+ {
+ left = 0;
+ right = _array->len - 1;
+
+ while (left <= right)
+ {
+ middle = left + (right - left) / 2;
+
+ val = compare_func (_array->data + (_array->elt_size * middle), target);
+ if (val == 0)
+ {
+ result = TRUE;
+ break;
+ }
+ else if (val < 0)
+ left = middle + 1;
+ else if (/* val > 0 && */ middle > 0)
+ right = middle - 1;
+ else
+ break; /* element not found */
+ }
+ }
+
+ if (result && out_match_index != NULL)
+ *out_match_index = middle;
+
+ return result;
+}
+#endif
+
#if !GLIB_CHECK_VERSION(2, 68, 0)
static inline void *
-g_memdup2(gconstpointer mem, size_t byte_size)
+g_memdup2(const void *mem, size_t byte_size)
{
void * new_mem;
diff --git a/wsutil/inet_addr.h b/wsutil/inet_addr.h
index 7147c2ae..6c7feb9b 100644
--- a/wsutil/inet_addr.h
+++ b/wsutil/inet_addr.h
@@ -12,8 +12,79 @@
#include <wireshark.h>
-#include "inet_ipv4.h"
-#include "inet_ipv6.h"
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+typedef uint32_t ws_in4_addr; /* 32 bit IPv4 address, in network byte order */
+
+typedef struct e_in6_addr {
+ uint8_t bytes[16]; /* 128 bit IPv6 address */
+} ws_in6_addr;
+
+
+/**
+ * Unicast Local
+ * Returns true if the address is in the 224.0.0.0/24 local network
+ * control block
+ */
+#define in4_addr_is_local_network_control_block(addr) \
+ ((addr & 0xffffff00) == 0xe0000000)
+
+/**
+ * Multicast
+ * Returns true if the address is in the 224.0.0.0/4 network block
+ */
+#define in4_addr_is_multicast(addr) \
+ ((addr & 0xf0000000) == 0xe0000000)
+
+/**
+ * Private address
+ * Returns true if the address is in one of the three blocks reserved
+ * for private IPv4 addresses by section 3 of RFC 1918, namely:
+ * 10/8, 172.16/12, and 192.168/16
+ */
+#define in4_addr_is_private(addr) \
+ (((addr & 0xff000000) == 0x0a000000) || \
+ ((addr & 0xfff00000) == 0xac100000) || \
+ ((addr & 0xffff0000) == 0xc0a80000))
+
+/**
+ * Link-local address
+ * Returns true if the address is in the 169.254/16 network block
+ */
+#define in4_addr_is_link_local(addr) \
+ ((addr & 0xffff0000) == 0xa9fe0000)
+
+/**
+ * Unicast Scope
+ * Note that we must check topmost 10 bits only, not 16 bits (see RFC2373).
+ */
+static inline bool
+in6_addr_is_linklocal(const ws_in6_addr *a)
+{
+ return (a->bytes[0] == 0xfe) && ((a->bytes[1] & 0xc0) == 0x80);
+}
+
+static inline bool
+in6_addr_is_sitelocal(const ws_in6_addr *a)
+{
+ return (a->bytes[0] == 0xfe) && ((a->bytes[1] & 0xc0) == 0xc0);
+}
+
+static inline bool in6_addr_is_uniquelocal(const ws_in6_addr *a)
+{
+ return (a->bytes[0] & 0xfe) == 0xfc;
+}
+
+/**
+ * Multicast
+ */
+static inline bool
+in6_addr_is_multicast(const ws_in6_addr *a)
+{
+ return a->bytes[0] == 0xff;
+}
/*
* These are the values specified by RFC 2133 and its successors for
@@ -48,24 +119,29 @@
#define WS_INET_ADDRSTRLEN 16
#define WS_INET6_ADDRSTRLEN 46
-#ifdef __cplusplus
-extern "C" {
-#endif /* __cplusplus */
+/*
+ * Utility for CIDR notation of subnets
+ */
+#define WS_INET_CIDRADDRSTRLEN 19
/*
* To check for errors set errno to zero before calling ws_inet_ntop{4,6}.
* ENOSPC is set if the result exceeds the given buffer size.
*/
-WS_DLL_PUBLIC WS_RETNONNULL const char *
+WS_DLL_PUBLIC WS_RETNONNULL
+const char *
ws_inet_ntop4(const void *src, char *dst, size_t dst_size);
-WS_DLL_PUBLIC WS_RETNONNULL const char *
+WS_DLL_PUBLIC WS_RETNONNULL
+const char *
ws_inet_ntop6(const void *src, char *dst, size_t dst_size);
-WS_DLL_PUBLIC bool
+WS_DLL_PUBLIC
+bool
ws_inet_pton4(const char *src, ws_in4_addr *dst);
-WS_DLL_PUBLIC bool
+WS_DLL_PUBLIC
+bool
ws_inet_pton6(const char *src, ws_in6_addr *dst);
#ifdef __cplusplus
diff --git a/wsutil/inet_cidr.c b/wsutil/inet_cidr.c
new file mode 100644
index 00000000..89777e16
--- /dev/null
+++ b/wsutil/inet_cidr.c
@@ -0,0 +1,110 @@
+/* ipv4.c
+ *
+ * Wireshark - Network traffic analyzer
+ * By Gerald Combs <gerald@wireshark.org>
+ * Copyright 1998 Gerald Combs
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "inet_cidr.h"
+
+
+uint32_t
+ws_ipv4_get_subnet_mask(const uint32_t mask_length)
+{
+ static const uint32_t masks[33] = {
+ 0x00000000,
+ 0x80000000, 0xc0000000, 0xe0000000, 0xf0000000,
+ 0xf8000000, 0xfc000000, 0xfe000000, 0xff000000,
+ 0xff800000, 0xffc00000, 0xffe00000, 0xfff00000,
+ 0xfff80000, 0xfffc0000, 0xfffe0000, 0xffff0000,
+ 0xffff8000, 0xffffc000, 0xffffe000, 0xfffff000,
+ 0xfffff800, 0xfffffc00, 0xfffffe00, 0xffffff00,
+ 0xffffff80, 0xffffffc0, 0xffffffe0, 0xfffffff0,
+ 0xfffffff8, 0xfffffffc, 0xfffffffe, 0xffffffff,
+ };
+
+ ws_assert(mask_length <= 32);
+
+ return masks[mask_length];
+}
+
+static int
+compare_ipv4(const ipv4_addr_and_mask *a, const ipv4_addr_and_mask *b)
+{
+ uint32_t addr_a, addr_b, nmask;
+
+ nmask = MIN(a->nmask, b->nmask);
+ addr_a = a->addr & nmask;
+ addr_b = b->addr & nmask;
+ if (addr_a < addr_b)
+ return -1;
+ if (addr_a > addr_b)
+ return 1;
+ return 0;
+}
+
+void
+ws_ipv4_addr_and_mask_init(ipv4_addr_and_mask *dst, ws_in4_addr src_addr, int src_bits)
+{
+ dst->addr = g_ntohl(src_addr);
+ dst->nmask = ws_ipv4_get_subnet_mask(src_bits);
+}
+
+bool
+ws_ipv4_addr_and_mask_contains(const ipv4_addr_and_mask *ipv4, const ws_in4_addr *in_addr)
+{
+ ipv4_addr_and_mask addr_and_mask;
+
+ addr_and_mask.addr = g_ntohl(*in_addr);
+ addr_and_mask.nmask = ws_ipv4_get_subnet_mask(32);
+ return compare_ipv4(ipv4, &addr_and_mask) == 0;
+}
+
+static const uint8_t bitmasks[9] =
+ { 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff };
+
+static int
+compare_ipv6(const ipv6_addr_and_prefix *a, const ipv6_addr_and_prefix *b)
+{
+ uint32_t prefix;
+ int pos = 0;
+
+ prefix = MIN(a->prefix, b->prefix); /* MIN() like IPv4 */
+ prefix = MIN(prefix, 128); /* sanitize, max prefix is 128 */
+
+ while (prefix >= 8) {
+ int byte_a = (int) (a->addr.bytes[pos]);
+ int byte_b = (int) (b->addr.bytes[pos]);
+
+ if (byte_a != byte_b) {
+ return byte_a - byte_b;
+ }
+
+ prefix -= 8;
+ pos++;
+ }
+
+ if (prefix != 0) {
+ int byte_a = (int) (a->addr.bytes[pos] & (bitmasks[prefix]));
+ int byte_b = (int) (b->addr.bytes[pos] & (bitmasks[prefix]));
+
+ if (byte_a != byte_b) {
+ return byte_a - byte_b;
+ }
+ }
+
+ return 0;
+}
+
+
+bool
+ws_ipv6_addr_and_prefix_contains(const ipv6_addr_and_prefix *ipv6, const ws_in6_addr *in_addr)
+{
+ ipv6_addr_and_prefix addr_and_mask;
+
+ addr_and_mask.addr = *in_addr;
+ addr_and_mask.prefix = 128;
+ return compare_ipv6(ipv6, &addr_and_mask) == 0;
+}
diff --git a/wsutil/inet_cidr.h b/wsutil/inet_cidr.h
new file mode 100644
index 00000000..352b01de
--- /dev/null
+++ b/wsutil/inet_cidr.h
@@ -0,0 +1,62 @@
+/** @file
+ * Definitions of IPv4 address-and-mask structure, which is what an
+ * FT_IPV4 value is (even if there's no mask in a packet, those
+ * values can be compared against an address+mask in a filter
+ * expression).
+ *
+ * Gilbert Ramirez <gram@alumni.rice.edu>
+ *
+ * Wireshark - Network traffic analyzer
+ * By Gerald Combs <gerald@wireshark.org>
+ * Copyright 1998 Gerald Combs
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#ifndef __IPV4_H__
+#define __IPV4_H__
+
+#include <wireshark.h>
+#include <wsutil/inet_addr.h>
+
+typedef struct {
+ uint32_t addr; /* stored in host order */
+ uint32_t nmask; /* stored in host order */
+} ipv4_addr_and_mask;
+
+typedef struct {
+ ws_in6_addr addr;
+ uint32_t prefix;
+} ipv6_addr_and_prefix;
+
+/*
+ ********** IPv4 *********
+ */
+
+/**
+* Returns the IPv4 subnet mask of the specified length
+*
+* @param mask_length the number of bits in the subnet mask (max of 32)
+* @return the subnet mask of the specified length
+*/
+WS_DLL_PUBLIC
+uint32_t
+ws_ipv4_get_subnet_mask(const uint32_t mask_length);
+
+WS_DLL_PUBLIC
+void
+ws_ipv4_addr_and_mask_init(ipv4_addr_and_mask *dst, ws_in4_addr src_addr, int src_bits);
+
+WS_DLL_PUBLIC
+bool
+ws_ipv4_addr_and_mask_contains(const ipv4_addr_and_mask *ipv4, const ws_in4_addr *addr);
+
+/*
+ ********** IPv6 *********
+ */
+
+WS_DLL_PUBLIC
+bool
+ws_ipv6_addr_and_prefix_contains(const ipv6_addr_and_prefix *ipv6, const ws_in6_addr *addr);
+
+#endif
diff --git a/wsutil/inet_ipv4.h b/wsutil/inet_ipv4.h
deleted file mode 100644
index a5a8fddd..00000000
--- a/wsutil/inet_ipv4.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/** @file
- *
- * Wireshark - Network traffic analyzer
- * By Gerald Combs <gerald@wireshark.org>
- * Copyright 1998 Gerald Combs
- *
- * SPDX-License-Identifier: GPL-2.0-or-later
- */
-
-#ifndef __INET_IPV4_H__
-#define __INET_IPV4_H__
-
-#include <inttypes.h>
-#include <glib.h>
-
-typedef uint32_t ws_in4_addr; /* 32 bit IPv4 address, in network byte order */
-
-/*
- * We define these in *network byte order*, unlike the C library. Therefore
- * it uses a different prefix than INADDR_* to make the distinction more obvious.
- */
-#define WS_IN4_LOOPBACK ((ws_in4_addr)GUINT32_TO_BE(0x7f000001))
-
-/**
- * Unicast Local
- * Returns true if the address is in the 224.0.0.0/24 local network
- * control block
- */
-#define in4_addr_is_local_network_control_block(addr) \
- ((addr & 0xffffff00) == 0xe0000000)
-
-/**
- * Multicast
- * Returns true if the address is in the 224.0.0.0/4 network block
- */
-#define in4_addr_is_multicast(addr) \
- ((addr & 0xf0000000) == 0xe0000000)
-
-/**
- * Private address
- * Returns true if the address is in one of the three blocks reserved
- * for private IPv4 addresses by section 3 of RFC 1918, namely:
- * 10/8, 172.16/12, and 192.168/16
- */
-#define in4_addr_is_private(addr) \
- (((addr & 0xff000000) == 0x0a000000) || \
- ((addr & 0xfff00000) == 0xac100000) || \
- ((addr & 0xffff0000) == 0xc0a80000))
-
-/**
- * Link-local address
- * Returns true if the address is in the 169.254/16 network block
- */
-#define in4_addr_is_link_local(addr) \
- ((addr & 0xffff0000) == 0xa9fe0000)
-
-#endif
diff --git a/wsutil/inet_ipv6.h b/wsutil/inet_ipv6.h
deleted file mode 100644
index 0cd70394..00000000
--- a/wsutil/inet_ipv6.h
+++ /dev/null
@@ -1,103 +0,0 @@
-/** @file
- *
- * Wireshark - Network traffic analyzer
- * By Gerald Combs <gerald@wireshark.org>
- * Copyright 1998 Gerald Combs
- *
- * SPDX-License-Identifier: GPL-2.0-or-later
- */
-
-#ifndef __INET_IPV6_H__
-#define __INET_IPV6_H__
-
-#include <inttypes.h>
-#include <stdbool.h>
-
-#define IPv6_ADDR_SIZE 16
-
-#define IPv6_HDR_SIZE 40
-#define IPv6_FRAGMENT_HDR_SIZE 8
-
-typedef struct e_in6_addr {
- uint8_t bytes[16]; /* 128 bit IPv6 address */
-} ws_in6_addr;
-
-/*
- * Definition for internet protocol version 6.
- * RFC 2460
- */
-struct ws_ip6_hdr {
- uint32_t ip6h_vc_flow; /* version, class, flow */
- uint16_t ip6h_plen; /* payload length */
- uint8_t ip6h_nxt; /* next header */
- uint8_t ip6h_hlim; /* hop limit */
- ws_in6_addr ip6h_src; /* source address */
- ws_in6_addr ip6h_dst; /* destination address */
-};
-
-/*
- * Extension Headers
- */
-
-struct ip6_ext {
- unsigned char ip6e_nxt;
- unsigned char ip6e_len;
-};
-
-/* Routing header */
-struct ip6_rthdr {
- uint8_t ip6r_nxt; /* next header */
- uint8_t ip6r_len; /* length in units of 8 octets */
- uint8_t ip6r_type; /* routing type */
- uint8_t ip6r_segleft; /* segments left */
- /* followed by routing type specific data */
-};
-
-/* Type 0 Routing header */
-struct ip6_rthdr0 {
- uint8_t ip6r0_nxt; /* next header */
- uint8_t ip6r0_len; /* length in units of 8 octets */
- uint8_t ip6r0_type; /* always zero */
- uint8_t ip6r0_segleft; /* segments left */
- uint8_t ip6r0_reserved; /* reserved field */
- uint8_t ip6r0_slmap[3]; /* strict/loose bit map */
- /* followed by up to 127 addresses */
- ws_in6_addr ip6r0_addr[1];
-};
-
-/* Fragment header */
-struct ip6_frag {
- uint8_t ip6f_nxt; /* next header */
- uint8_t ip6f_reserved; /* reserved field */
- uint16_t ip6f_offlg; /* offset, reserved, and flag */
- uint32_t ip6f_ident; /* identification */
-};
-
-#define IP6F_OFF_MASK 0xfff8 /* mask out offset from _offlg */
-#define IP6F_RESERVED_MASK 0x0006 /* reserved bits in ip6f_offlg */
-#define IP6F_MORE_FRAG 0x0001 /* more-fragments flag */
-
-
-/**
- * Unicast Scope
- * Note that we must check topmost 10 bits only, not 16 bits (see RFC2373).
- */
-static inline bool in6_addr_is_linklocal(const ws_in6_addr *a)
-{
- return (a->bytes[0] == 0xfe) && ((a->bytes[1] & 0xc0) == 0x80);
-}
-
-static inline bool in6_addr_is_sitelocal(const ws_in6_addr *a)
-{
- return (a->bytes[0] == 0xfe) && ((a->bytes[1] & 0xc0) == 0xc0);
-}
-
-/**
- * Multicast
- */
-static inline bool in6_addr_is_multicast(const ws_in6_addr *a)
-{
- return a->bytes[0] == 0xff;
-}
-
-#endif
diff --git a/wsutil/json_dumper.c b/wsutil/json_dumper.c
index 5cbc9494..2761d37c 100644
--- a/wsutil/json_dumper.c
+++ b/wsutil/json_dumper.c
@@ -11,13 +11,15 @@
* SPDX-License-Identifier: GPL-2.0-or-later
*/
+#include "config.h"
+#define WS_LOG_DOMAIN LOG_DOMAIN_WSUTIL
+
#include <glib.h>
#include "json_dumper.h"
-#define WS_LOG_DOMAIN LOG_DOMAIN_WSUTIL
-
#include <math.h>
+#include <wsutil/array.h>
#include <wsutil/wslog.h>
/*
@@ -49,7 +51,7 @@ static const char *json_dumper_element_type_names[] = {
[JSON_DUMPER_TYPE_ARRAY] = "array",
[JSON_DUMPER_TYPE_BASE64] = "base64"
};
-#define NUM_JSON_DUMPER_ELEMENT_TYPE_NAMES (sizeof json_dumper_element_type_names / sizeof json_dumper_element_type_names[0])
+#define NUM_JSON_DUMPER_ELEMENT_TYPE_NAMES array_length(json_dumper_element_type_names)
#define JSON_DUMPER_FLAGS_ERROR (1 << 16) /* Output flag: an error occurred. */
@@ -414,7 +416,7 @@ json_dumper_end_nested_element(json_dumper *dumper, enum json_dumper_element_typ
break;
}
default:
- json_dumper_bad(dumper, "endning unknown nested element type");
+ json_dumper_bad(dumper, "ending unknown nested element type");
return false;
}
diff --git a/wsutil/json_dumper.h b/wsutil/json_dumper.h
index 184960ae..d74c6027 100644
--- a/wsutil/json_dumper.h
+++ b/wsutil/json_dumper.h
@@ -59,7 +59,7 @@ typedef struct json_dumper {
GString *output_string; /**< Output GLib strings. If it is not NULL, JSON will be dumped in the string. */
#define JSON_DUMPER_FLAGS_PRETTY_PRINT (1 << 0) /* Enable pretty printing. */
#define JSON_DUMPER_DOT_TO_UNDERSCORE (1 << 1) /* Convert dots to underscores in keys */
-#define JSON_DUMPER_FLAGS_NO_DEBUG (1 << 17) /* Disable fatal ws_error messsges on error(intended for speeding up fuzzing). */
+#define JSON_DUMPER_FLAGS_NO_DEBUG (1 << 17) /* Disable fatal ws_error messages on error(intended for speeding up fuzzing). */
int flags;
/* for internal use, initialize with zeroes. */
unsigned current_depth;
diff --git a/wsutil/nstime.c b/wsutil/nstime.c
index 1f58dbb4..70890afa 100644
--- a/wsutil/nstime.c
+++ b/wsutil/nstime.c
@@ -183,6 +183,8 @@ double nstime_to_sec(const nstime_t *nstime)
}
/*
+ * Compute the minimum and maximum time_t values.
+ *
* This code is based on the Samba code:
*
* Unix SMB/Netbios implementation.
@@ -252,7 +254,7 @@ filetime_to_nstime(nstime_t *nstime, uint64_t filetime)
}
/*
- * function: nsfiletime_to_nstime
+ * function: filetime_ns_to_nstime
* converts a Windows FILETIME-like value, but given in nanoseconds
* rather than 10ths of microseconds, to an nstime_t
* returns true if the conversion succeeds, false if it doesn't
@@ -260,7 +262,7 @@ filetime_to_nstime(nstime_t *nstime, uint64_t filetime)
* underflows time_t)
*/
bool
-nsfiletime_to_nstime(nstime_t *nstime, uint64_t nsfiletime)
+filetime_ns_to_nstime(nstime_t *nstime, uint64_t nsfiletime)
{
uint64_t ftsecs;
int nsecs;
@@ -273,6 +275,25 @@ nsfiletime_to_nstime(nstime_t *nstime, uint64_t nsfiletime)
}
/*
+ * function: filetime_1sec_to_nstime
+ * converts a Windows FILETIME-like value, but given in seconds
+ * rather than 10ths of microseconds, to an nstime_t
+ * returns true if the conversion succeeds, false if it doesn't
+ * (for example, with a 32-bit time_t, the time overflows or
+ * underflows time_t)
+ */
+bool
+filetime_1sec_to_nstime(nstime_t *nstime, uint64_t filetime_1sec)
+{
+ /*
+ * Make sure filetime_1sec fits in a 64-bit signed integer.
+ */
+ if (filetime_1sec > INT64_MAX)
+ return false; /* No, it doesn't */
+ return common_filetime_to_nstime(nstime, filetime_1sec, 0);
+}
+
+/*
* function: iso8601_to_nstime
* parses a character string for a date and time given in
* ISO 8601 date-time format (eg: 2014-04-07T05:41:56.782+00:00)
diff --git a/wsutil/nstime.h b/wsutil/nstime.h
index acc78b53..bfac25e6 100644
--- a/wsutil/nstime.h
+++ b/wsutil/nstime.h
@@ -121,7 +121,12 @@ WS_DLL_PUBLIC bool filetime_to_nstime(nstime_t *nstime, uint64_t filetime);
/** converts time like Windows FILETIME, but expressed in nanoseconds
rather than tenths of microseconds, to nstime, returns true on success,
false on failure */
-WS_DLL_PUBLIC bool nsfiletime_to_nstime(nstime_t *nstime, uint64_t nsfiletime);
+WS_DLL_PUBLIC bool filetime_ns_to_nstime(nstime_t *nstime, uint64_t nsfiletime);
+
+/** converts time like Windows FILETIME, but expressed in seconds
+ rather than tenths of microseconds, to nstime, returns true on success,
+ false on failure */
+WS_DLL_PUBLIC bool filetime_1sec_to_nstime(nstime_t *nstime, uint64_t filetime);
typedef enum {
ISO8601_DATETIME, /** e.g. 2014-07-04T12:34:56.789+00:00 */
diff --git a/wsutil/os_version_info.c b/wsutil/os_version_info.c
index 69a80c8f..7e9daa05 100644
--- a/wsutil/os_version_info.c
+++ b/wsutil/os_version_info.c
@@ -565,7 +565,7 @@ DIAG_ON(cast-function-type)
* trusted at all?
*
* As for the Windows Server 2022 entry,
- * is that just becuase that script doesn't
+ * is that just because that script doesn't
* bother checking for "workstation" vs.
* "server"?
*/
@@ -760,7 +760,7 @@ DIAG_ON(cast-function-type)
* The first line parser reads the first line of the file.
* If a string is passed to it, it constructs a distribution
* name string by concatenating the parameter, a space,
- * and the contents of that line (iwth the newline removed),
+ * and the contents of that line (with the newline removed),
* otherwise it constructs it from the contents of the line.
*
* Fall back on just "Linux" if nothing works.
diff --git a/wsutil/path_config.h.in b/wsutil/path_config.h.in
index 6539a5ab..59d1f504 100644
--- a/wsutil/path_config.h.in
+++ b/wsutil/path_config.h.in
@@ -6,5 +6,6 @@
#define DOC_DIR "@PATH_DOC_DIR@"
#define PLUGIN_DIR "@PATH_PLUGIN_DIR@"
#define EXTCAP_DIR "@PATH_EXTCAP_DIR@"
+#define LOG_EXTCAP_DIR "@PATH_LOG_EXTCAP_DIR@"
#endif
diff --git a/wsutil/pint.h b/wsutil/pint.h
index 97b6da23..b4984b5f 100644
--- a/wsutil/pint.h
+++ b/wsutil/pint.h
@@ -52,7 +52,7 @@
*/
#if defined(_MSC_VER) && !defined(__INTEL_COMPILER) && !defined(__INTEL_LLVM_COMPILER) && !defined(__clang__)
/* Intel and clang-cl both define _MSC_VER when compiling on Windows for
- * greater compatiblity (just as they define __GNUC__ on other platforms).
+ * greater compatibility (just as they define __GNUC__ on other platforms).
* However, at least on some versions, while including the MSVC <stdlib.h>
* provides access to the _byteswap_ intrinsics, they are not actually
* optimized into a single x86 BSWAP function, unlike the gcc-style intrinsics
@@ -366,9 +366,6 @@ static inline uint64_t pletoh56(const void *p)
(uint64_t)*((const uint8_t *)(p)+0)<<0;
}
-/* Subtract two guint32s with respect to wraparound */
-#define guint32_wraparound_diff(higher, lower) ((higher>lower)?(higher-lower):(higher+0xffffffff-lower+1))
-
#endif /* PINT_H */
/*
diff --git a/wsutil/plugins.c b/wsutil/plugins.c
index 2798fdc3..23862949 100644
--- a/wsutil/plugins.c
+++ b/wsutil/plugins.c
@@ -30,19 +30,14 @@ typedef struct _plugin {
GModule *handle; /* handle returned by g_module_open */
char *name; /* plugin name */
const char *version; /* plugin version */
- const char *type_name; /* user-facing name (what it does). Should these be capitalized? */
+ uint32_t flags; /* plugin flags */
} plugin;
#define TYPE_DIR_EPAN "epan"
#define TYPE_DIR_WIRETAP "wiretap"
#define TYPE_DIR_CODECS "codecs"
-#define TYPE_NAME_DISSECTOR "dissector"
-#define TYPE_NAME_FILE_TYPE "file type"
-#define TYPE_NAME_CODEC "codec"
-
-
-static GSList *plugins_module_list = NULL;
+static GSList *plugins_module_list;
static inline const char *
@@ -63,20 +58,24 @@ type_to_dir(plugin_type_e type)
}
static inline const char *
-type_to_name(plugin_type_e type)
+flags_to_str(uint32_t flags)
{
- switch (type) {
- case WS_PLUGIN_EPAN:
- return TYPE_NAME_DISSECTOR;
- case WS_PLUGIN_WIRETAP:
- return TYPE_NAME_FILE_TYPE;
- case WS_PLUGIN_CODEC:
- return TYPE_NAME_CODEC;
- default:
- ws_error("Unknown plugin type: %u. Aborting.", (unsigned) type);
- break;
- }
- ws_assert_not_reached();
+ /* XXX: Allow joining multiple types? Our plugins only implement a
+ * single type but out in the wild this may not be true. */
+ if (flags & WS_PLUGIN_DESC_DISSECTOR)
+ return "dissector";
+ else if (flags & WS_PLUGIN_DESC_FILE_TYPE)
+ return "file type";
+ else if (flags & WS_PLUGIN_DESC_CODEC)
+ return "codec";
+ else if (flags & WS_PLUGIN_DESC_EPAN)
+ return "epan";
+ else if (flags & WS_PLUGIN_DESC_TAP_LISTENER)
+ return "tap listener";
+ else if (flags & WS_PLUGIN_DESC_DFILTER)
+ return "dfilter";
+ else
+ return "unknown";
}
static void
@@ -89,7 +88,7 @@ free_plugin(void * data)
}
static int
-compare_plugins(gconstpointer a, gconstpointer b)
+compare_plugins(const void *a, const void *b)
{
return g_strcmp0((*(plugin *const *)a)->name, (*(plugin *const *)b)->name);
}
@@ -138,6 +137,7 @@ scan_plugins_dir(GHashTable *plugins_module, const char *dirpath, plugin_type_e
GModule *handle; /* handle returned by g_module_open */
void * symbol;
const char *plug_version;
+ uint32_t flags;
plugin *new_plug;
if (append_type)
@@ -206,11 +206,17 @@ DIAG_OFF_PEDANTIC
((plugin_register_func)symbol)();
DIAG_ON_PEDANTIC
+ /* Search for the (optional) description flag registration function */
+ if (g_module_symbol(handle, "plugin_describe", &symbol))
+ flags = ((plugin_describe_func)symbol)();
+ else
+ flags = 0;
+
new_plug = g_new(plugin, 1);
new_plug->handle = handle;
new_plug->name = g_strdup(name);
new_plug->version = plug_version;
- new_plug->type_name = type_to_name(type);
+ new_plug->flags = flags;
/* Add it to the list of plugins. */
g_hash_table_replace(plugins_module, new_plug->name, new_plug);
@@ -272,7 +278,7 @@ plugins_get_descriptions(plugin_description_callback callback, void *callback_da
for (unsigned i = 0; i < plugins_array->len; i++) {
plugin *plug = (plugin *)plugins_array->pdata[i];
- callback(plug->name, plug->version, plug->type_name, g_module_name(plug->handle), callback_data);
+ callback(plug->name, plug->version, plug->flags, g_module_name(plug->handle), callback_data);
}
g_ptr_array_free(plugins_array, true);
@@ -280,10 +286,10 @@ plugins_get_descriptions(plugin_description_callback callback, void *callback_da
static void
print_plugin_description(const char *name, const char *version,
- const char *description, const char *filename,
+ uint32_t flags, const char *filename,
void *user_data _U_)
{
- printf("%-16s\t%s\t%s\t%s\n", name, version, description, filename);
+ printf("%-16s\t%s\t%s\t%s\n", name, version, flags_to_str(flags), filename);
}
void
diff --git a/wsutil/plugins.h b/wsutil/plugins.h
index 96f3ac03..113f1f68 100644
--- a/wsutil/plugins.h
+++ b/wsutil/plugins.h
@@ -18,6 +18,7 @@ extern "C" {
#endif /* __cplusplus */
typedef void (*plugin_register_func)(void);
+typedef uint32_t (*plugin_describe_func)(void);
typedef void plugins_t;
@@ -27,10 +28,17 @@ typedef enum {
WS_PLUGIN_CODEC
} plugin_type_e;
+#define WS_PLUGIN_DESC_DISSECTOR (1UL << 0)
+#define WS_PLUGIN_DESC_FILE_TYPE (1UL << 1)
+#define WS_PLUGIN_DESC_CODEC (1UL << 2)
+#define WS_PLUGIN_DESC_EPAN (1UL << 3)
+#define WS_PLUGIN_DESC_TAP_LISTENER (1UL << 4)
+#define WS_PLUGIN_DESC_DFILTER (1UL << 5)
+
WS_DLL_PUBLIC plugins_t *plugins_init(plugin_type_e type);
typedef void (*plugin_description_callback)(const char *name, const char *version,
- const char *types, const char *filename,
+ uint32_t flags, const char *filename,
void *user_data);
WS_DLL_PUBLIC void plugins_get_descriptions(plugin_description_callback callback, void *user_data);
diff --git a/wsutil/privileges.c b/wsutil/privileges.c
index 2ca30203..6ee0dfd5 100644
--- a/wsutil/privileges.c
+++ b/wsutil/privileges.c
@@ -118,7 +118,7 @@ get_cur_groupname(void) {
static uid_t ruid, euid;
static gid_t rgid, egid;
-static bool init_process_policies_called = false;
+static bool init_process_policies_called;
/*
* Called when the program starts, to save whatever credential information
diff --git a/wsutil/regex.c b/wsutil/regex.c
index bb27189b..464a4223 100644
--- a/wsutil/regex.c
+++ b/wsutil/regex.c
@@ -60,6 +60,8 @@ compile_pcre2(const char *patt, ssize_t size, char **errmsg, unsigned flags)
options |= PCRE2_NEVER_UTF;
if (flags & WS_REGEX_CASELESS)
options |= PCRE2_CASELESS;
+ if (flags & WS_REGEX_ANCHORED)
+ options |= PCRE2_ANCHORED;
/* By default UTF-8 is off. */
code = pcre2_compile_8((PCRE2_SPTR)patt,
@@ -103,7 +105,7 @@ ws_regex_compile(const char *patt, char **errmsg)
static bool
match_pcre2(pcre2_code *code, const char *subject, ssize_t subj_length,
- pcre2_match_data *match_data)
+ size_t subj_offset, pcre2_match_data *match_data)
{
PCRE2_SIZE length;
int rc;
@@ -116,7 +118,7 @@ match_pcre2(pcre2_code *code, const char *subject, ssize_t subj_length,
rc = pcre2_match(code,
subject,
length,
- 0, /* start at offset zero of the subject */
+ (PCRE2_SIZE)subj_offset,
0, /* default options */
match_data,
NULL);
@@ -158,7 +160,7 @@ ws_regex_matches_length(const ws_regex_t *re,
/* We don't use the matched substring but pcre2_match requires
* at least one pair of offsets. */
match_data = pcre2_match_data_create(1, NULL);
- matched = match_pcre2(re->code, subj, subj_length, match_data);
+ matched = match_pcre2(re->code, subj, subj_length, 0, match_data);
pcre2_match_data_free(match_data);
return matched;
}
@@ -167,7 +169,7 @@ ws_regex_matches_length(const ws_regex_t *re,
bool
ws_regex_matches_pos(const ws_regex_t *re,
const char *subj, ssize_t subj_length,
- size_t pos_vect[2])
+ size_t subj_offset, size_t pos_vect[2])
{
bool matched;
pcre2_match_data *match_data;
@@ -176,7 +178,7 @@ ws_regex_matches_pos(const ws_regex_t *re,
ws_return_val_if(!subj, false);
match_data = pcre2_match_data_create(1, NULL);
- matched = match_pcre2(re->code, subj, subj_length, match_data);
+ matched = match_pcre2(re->code, subj, subj_length, subj_offset, match_data);
if (matched && pos_vect) {
PCRE2_SIZE *ovect = pcre2_get_ovector_pointer(match_data);
pos_vect[0] = ovect[0];
diff --git a/wsutil/regex.h b/wsutil/regex.h
index 0484eab3..199779a2 100644
--- a/wsutil/regex.h
+++ b/wsutil/regex.h
@@ -26,6 +26,7 @@ ws_regex_compile(const char *patt, char **errmsg);
/* By default UTF-8 is off. This option also prevents it from being
* turned on using a pattern option. */
#define WS_REGEX_NEVER_UTF (1U << 1)
+#define WS_REGEX_ANCHORED (1U << 2)
WS_DLL_PUBLIC ws_regex_t *
ws_regex_compile_ex(const char *patt, ssize_t size, char **errmsg, unsigned flags);
@@ -41,14 +42,19 @@ ws_regex_matches_length(const ws_regex_t *re,
/** Returns start and end position of the matched substring.
*
+ * @note Using a nonzero subj_offset produces different results than
+ * passing a pointer to the later offset as subj when the pattern
+ * begins with a lookbehind.
+ *
* pos_vect[0] is first codepoint in the matched substring.
- * pos_vect[1] is the next to last codepoint in the matched substring.
+ * pos_vect[1] is first codepoint past the matched substring.
* pos_vect[1] - pos_vect[0] is the matched substring length.
+ *
*/
WS_DLL_PUBLIC bool
ws_regex_matches_pos(const ws_regex_t *re,
const char *subj, ssize_t subj_length,
- size_t pos_vect[2]);
+ size_t subj_offset, size_t pos_vect[2]);
WS_DLL_PUBLIC void
ws_regex_free(ws_regex_t *re);
diff --git a/wsutil/report_message.c b/wsutil/report_message.c
index 6f797fab..5e88466a 100644
--- a/wsutil/report_message.c
+++ b/wsutil/report_message.c
@@ -124,7 +124,7 @@ report_cfile_read_failure(const char *filename, int err, char *err_info)
*/
void
report_cfile_write_failure(const char *in_filename, const char *out_filename,
- int err, char *err_info, uint32_t framenum, int file_type_subtype)
+ int err, char *err_info, uint64_t framenum, int file_type_subtype)
{
(*routines->report_cfile_write_failure)(in_filename, out_filename,
err, err_info, framenum, file_type_subtype);
diff --git a/wsutil/report_message.h b/wsutil/report_message.h
index 7be1808b..7c64e8ae 100644
--- a/wsutil/report_message.h
+++ b/wsutil/report_message.h
@@ -32,14 +32,14 @@ extern "C" {
struct report_message_routines {
void (*vreport_failure)(const char *, va_list);
void (*vreport_warning)(const char *, va_list);
- void (*report_open_failure)(const char *, int, gboolean);
+ void (*report_open_failure)(const char *, int, bool);
void (*report_read_failure)(const char *, int);
void (*report_write_failure)(const char *, int);
void (*report_cfile_open_failure)(const char *, int, char *);
void (*report_cfile_dump_open_failure)(const char *, int, char *, int);
void (*report_cfile_read_failure)(const char *, int, char *);
void (*report_cfile_write_failure)(const char *, const char *,
- int, char *, uint32_t, int);
+ int, char *, uint64_t, int);
void (*report_cfile_close_failure)(const char *, int, char *);
};
@@ -99,7 +99,7 @@ WS_DLL_PUBLIC void report_cfile_read_failure(const char *filename,
* Report an error from attempting to write to a capture file.
*/
WS_DLL_PUBLIC void report_cfile_write_failure(const char *in_filename,
- const char *out_filename, int err, char *err_info, uint32_t framenum,
+ const char *out_filename, int err, char *err_info, uint64_t framenum,
int file_type_subtype);
/*
diff --git a/wsutil/sign_ext.h b/wsutil/sign_ext.h
index 67401edb..e8c622a9 100644
--- a/wsutil/sign_ext.h
+++ b/wsutil/sign_ext.h
@@ -52,8 +52,8 @@ ws_sign_ext64(uint64_t val, int no_of_bits)
* the number of bits in the value - 1, and we might get
* compile-time or run-time complaints about that.
*/
- if (val & (G_GUINT64_CONSTANT(1) << (no_of_bits-1)))
- val |= (G_GUINT64_CONSTANT(0xFFFFFFFFFFFFFFFF) << no_of_bits);
+ if (val & (UINT64_C(1) << (no_of_bits-1)))
+ val |= (UINT64_C(0xFFFFFFFFFFFFFFFF) << no_of_bits);
return val;
}
diff --git a/wsutil/str_util.c b/wsutil/str_util.c
index 4243b22b..556ef5a9 100644
--- a/wsutil/str_util.c
+++ b/wsutil/str_util.c
@@ -13,6 +13,8 @@
#include "str_util.h"
#include <string.h>
+#include <locale.h>
+#include <math.h>
#include <ws_codepoints.h>
@@ -339,10 +341,41 @@ ws_ascii_strcasestr(const char *haystack, const char *needle)
return NULL;
}
+/* Return the last occurrence of ch in the n bytes of haystack.
+ * If not found or n is 0, return NULL. */
+const uint8_t *
+ws_memrchr(const void *_haystack, int ch, size_t n)
+{
+#ifdef HAVE_MEMRCHR
+ return memrchr(_haystack, ch, n);
+#else
+ /* A generic implementation. This could be optimized considerably,
+ * e.g. by fetching a word at a time.
+ */
+ if (n == 0) {
+ return NULL;
+ }
+ const uint8_t *haystack = _haystack;
+ const uint8_t *p;
+ uint8_t c = (uint8_t)ch;
+
+ const uint8_t *const end = haystack + n - 1;
+
+ for (p = end; p >= haystack; --p) {
+ if (*p == c) {
+ return p;
+ }
+ }
+
+ return NULL;
+#endif /* HAVE_MEMRCHR */
+}
+
#define FORMAT_SIZE_UNIT_MASK 0x00ff
#define FORMAT_SIZE_PFX_MASK 0xff00
-static const char *thousands_grouping_fmt = NULL;
+static const char *thousands_grouping_fmt;
+static const char *thousands_grouping_fmt_flt;
DIAG_OFF(format)
static void test_printf_thousands_grouping(void) {
@@ -351,16 +384,213 @@ static void test_printf_thousands_grouping(void) {
wmem_strbuf_append_printf(buf, "%'d", 22);
if (g_strcmp0(wmem_strbuf_get_str(buf), "22") == 0) {
thousands_grouping_fmt = "%'"PRId64;
+ thousands_grouping_fmt_flt = "%'.*f";
} else {
/* Don't use */
thousands_grouping_fmt = "%"PRId64;
+ thousands_grouping_fmt_flt = "%.*f";
}
wmem_strbuf_destroy(buf);
}
DIAG_ON(format)
+static const char* decimal_point = NULL;
+
+static void truncate_numeric_strbuf(wmem_strbuf_t *strbuf, int n) {
+
+ const char *s = wmem_strbuf_get_str(strbuf);
+ char *p;
+ int count;
+
+ if (decimal_point == NULL) {
+ decimal_point = localeconv()->decimal_point;
+ }
+
+ p = strchr(s, decimal_point[0]);
+ if (p != NULL) {
+ count = n;
+ while (count >= 0) {
+ count--;
+ if (*p == '\0')
+ break;
+ p++;
+ }
+
+ p--;
+ while (*p == '0') {
+ p--;
+ }
+
+ if (*p != decimal_point[0]) {
+ p++;
+ }
+ wmem_strbuf_truncate(strbuf, p - s);
+ }
+}
+
+/* Given a floating point value, return it in a human-readable format,
+ * using units with metric prefixes (falling back to scientific notation
+ * with the base units if outside the range.)
+ */
+char *
+format_units(wmem_allocator_t *allocator, double size,
+ format_size_units_e unit, uint16_t flags,
+ int precision)
+{
+ wmem_strbuf_t *human_str = wmem_strbuf_new(allocator, NULL);
+ double power = 1000.0;
+ int pfx_off = 6;
+ bool is_small = false;
+ /* is_small is when to use the longer, spelled out unit.
+ * We use it for inf, NaN, 0, and unprefixed small values,
+ * but not for unprefixed values using scientific notation
+ * the value is outside the supported prefix range.
+ */
+ bool scientific = false;
+ double abs_size = fabs(size);
+ int exponent = 0;
+ static const char * const si_prefix[] = {" a", " f", " p", " n", " μ", " m", " ", " k", " M", " G", " T", " P", " E"};
+ static const char * const iec_prefix[] = {" ", " Ki", " Mi", " Gi", " Ti", " Pi", " Ei"};
+ const char * const *prefix = si_prefix;
+ int max_exp = (int)G_N_ELEMENTS(si_prefix) - 1;
+
+ char *ret_val;
+
+ if (thousands_grouping_fmt == NULL)
+ test_printf_thousands_grouping();
+
+ if (flags & FORMAT_SIZE_PREFIX_IEC) {
+ prefix = iec_prefix;
+ max_exp = (int)G_N_ELEMENTS(iec_prefix) - 1;
+ power = 1024.0;
+ }
+
+ if (isfinite(size) && size != 0.0) {
+
+ double comp = precision == 0 ? 10.0 : 1.0;
+
+ /* For precision 0, use the range [10, 10*power) because only
+ * one significant digit is not as useful. This is what format_size
+ * does for integers. ("ls -h" uses one digit after the decimal
+ * point only for the [1, 10) range, g_format_size() always displays
+ * tenths.) Prefer non-prefixed units for the range [1,10), though.
+ *
+ * We have a limited number of units to check, so this (which
+ * can be unrolled) is presumably faster than log + floor + pow/exp
+ */
+ if (abs_size < 1.0) {
+ while (abs_size < comp) {
+ abs_size *= power;
+ exponent--;
+ if ((exponent + pfx_off) < 0) {
+ scientific = true;
+ break;
+ }
+ }
+ } else {
+ while (abs_size >= comp*power) {
+ abs_size *= 1/power;
+ exponent++;
+ if ((exponent + pfx_off) > max_exp) {
+ scientific = true;
+ break;
+ }
+ }
+ }
+ }
+
+ if (scientific) {
+ wmem_strbuf_append_printf(human_str, "%.*g", precision + 1, size);
+ exponent = 0;
+ } else {
+ if (exponent == 0) {
+ is_small = true;
+ }
+ size = copysign(abs_size, size);
+ // Truncate trailing zeros, but do it this way because we know
+ // we don't want scientific notation, and we don't want %g to
+ // switch to that if precision is small. (We could always use
+ // %g when precision is large.)
+ wmem_strbuf_append_printf(human_str, thousands_grouping_fmt_flt, precision, size);
+ truncate_numeric_strbuf(human_str, precision);
+ // XXX - when rounding to a certain precision, printf might
+ // round up to "power" from something like 999.99999995, which
+ // looks a little odd on a graph when transitioning from 1,000 bytes
+ // (for values just under 1 kB) to 1 kB (for values 1 kB and larger.)
+ // Due to edge cases in binary fp representation and how printf might
+ // round things, the right way to handle it is taking the printf output
+ // and comparing it to "1000" and "1024" and adjusting the exponent
+ // if so - though we need to compare to the version with the thousands
+ // separator if we have that (which makes it harder to use strnatcmp
+ // as is.)
+ }
+
+ if ((size_t)(pfx_off + exponent) < G_N_ELEMENTS(si_prefix)) {
+ wmem_strbuf_append(human_str, prefix[pfx_off+exponent]);
+ }
+
+ switch (unit) {
+ case FORMAT_SIZE_UNIT_NONE:
+ break;
+ case FORMAT_SIZE_UNIT_BYTES:
+ wmem_strbuf_append(human_str, is_small ? "bytes" : "B");
+ break;
+ case FORMAT_SIZE_UNIT_BITS:
+ wmem_strbuf_append(human_str, is_small ? "bits" : "b");
+ break;
+ case FORMAT_SIZE_UNIT_BITS_S:
+ wmem_strbuf_append(human_str, is_small ? "bits/s" : "bps");
+ break;
+ case FORMAT_SIZE_UNIT_BYTES_S:
+ wmem_strbuf_append(human_str, is_small ? "bytes/s" : "Bps");
+ break;
+ case FORMAT_SIZE_UNIT_PACKETS:
+ wmem_strbuf_append(human_str, is_small ? "packets" : "packets");
+ break;
+ case FORMAT_SIZE_UNIT_PACKETS_S:
+ wmem_strbuf_append(human_str, is_small ? "packets/s" : "packets/s");
+ break;
+ case FORMAT_SIZE_UNIT_EVENTS:
+ wmem_strbuf_append(human_str, is_small ? "events" : "events");
+ break;
+ case FORMAT_SIZE_UNIT_EVENTS_S:
+ wmem_strbuf_append(human_str, is_small ? "events/s" : "events/s");
+ break;
+ case FORMAT_SIZE_UNIT_FIELDS:
+ wmem_strbuf_append(human_str, is_small ? "fields" : "fields");
+ break;
+ case FORMAT_SIZE_UNIT_SECONDS:
+ wmem_strbuf_append(human_str, is_small ? "seconds" : "s");
+ break;
+ case FORMAT_SIZE_UNIT_ERLANGS:
+ wmem_strbuf_append(human_str, is_small ? "erlangs" : "E");
+ break;
+ default:
+ ws_assert_not_reached();
+ }
+
+ ret_val = wmem_strbuf_finalize(human_str);
+ /* Convention is a space between the value and the units. If we have
+ * a prefix, the space is before the prefix. There are two possible
+ * uses of FORMAT_SIZE_UNIT_NONE:
+ * 1. Add a unit immediately after the string returned. In this case,
+ * we would want the string to end with a space if there's no prefix.
+ * 2. The unit appears somewhere else, e.g. in a legend, header, or
+ * different column. In this case, we don't want the string to end
+ * with a space if there's no prefix.
+ * chomping the string here, as we've traditionally done, optimizes for
+ * the latter case but makes the former case harder.
+ * Perhaps the right approach is to distinguish the cases with a new
+ * enum value.
+ */
+ return g_strchomp(ret_val);
+}
+
/* Given a size, return its value in a human-readable format */
-/* This doesn't handle fractional values. We might want to make size a double. */
+/* This doesn't handle fractional values. We might want to just
+ * call the version with the double and precision 0 (possibly
+ * slower due to the use of floating point math, but do we care?)
+ */
char *
format_size_wmem(wmem_allocator_t *allocator, int64_t size,
format_size_units_e unit, uint16_t flags)
@@ -418,6 +648,18 @@ format_size_wmem(wmem_allocator_t *allocator, int64_t size,
case FORMAT_SIZE_UNIT_PACKETS_S:
wmem_strbuf_append(human_str, is_small ? " packets/s" : "packets/s");
break;
+ case FORMAT_SIZE_UNIT_FIELDS:
+ wmem_strbuf_append(human_str, is_small ? " fields" : "fields");
+ break;
+ /* These aren't that practical to use with integers, but
+ * perhaps better than asserting.
+ */
+ case FORMAT_SIZE_UNIT_SECONDS:
+ wmem_strbuf_append(human_str, is_small ? " seconds" : "s");
+ break;
+ case FORMAT_SIZE_UNIT_ERLANGS:
+ wmem_strbuf_append(human_str, is_small ? " erlangs" : "E");
+ break;
default:
ws_assert_not_reached();
}
@@ -443,8 +685,9 @@ escape_char(char c, char *p)
ws_assert(p);
/*
- * Backslashes and double-quotes must
- * be escaped. Whitespace is also escaped.
+ * backslashes and double-quotes must be escaped (double-quotes
+ * are escaped by passing '"' as quote_char in escape_string_len)
+ * whitespace is also escaped.
*/
switch (c) {
case '\a': r = 'a'; break;
@@ -454,7 +697,6 @@ escape_char(char c, char *p)
case '\r': r = 'r'; break;
case '\t': r = 't'; break;
case '\v': r = 'v'; break;
- case '"': r = '"'; break;
case '\\': r = '\\'; break;
case '\0': r = '0'; break;
}
@@ -479,7 +721,8 @@ escape_null(char c, char *p)
static char *
escape_string_len(wmem_allocator_t *alloc, const char *string, ssize_t len,
- bool (*escape_func)(char c, char *p), bool add_quotes)
+ bool (*escape_func)(char c, char *p), bool add_quotes,
+ char quote_char, bool double_quote)
{
char c, r;
wmem_strbuf_t *buf;
@@ -495,8 +738,8 @@ escape_string_len(wmem_allocator_t *alloc, const char *string, ssize_t len,
buf = wmem_strbuf_new_sized(alloc, alloc_size);
- if (add_quotes)
- wmem_strbuf_append_c(buf, '"');
+ if (add_quotes && quote_char != '\0')
+ wmem_strbuf_append_c(buf, quote_char);
for (i = 0; i < len; i++) {
c = string[i];
@@ -504,14 +747,30 @@ escape_string_len(wmem_allocator_t *alloc, const char *string, ssize_t len,
wmem_strbuf_append_c(buf, '\\');
wmem_strbuf_append_c(buf, r);
}
+ else if (c == quote_char && quote_char != '\0') {
+ /* If quoting, we must escape the quote_char somehow. */
+ if (double_quote) {
+ wmem_strbuf_append_c(buf, c);
+ wmem_strbuf_append_c(buf, c);
+ } else {
+ wmem_strbuf_append_c(buf, '\\');
+ wmem_strbuf_append_c(buf, c);
+ }
+ }
+ else if (c == '\\' && quote_char != '\0' && !double_quote) {
+ /* If quoting, and escaping the quote_char with a backslash,
+ * then backslash must be escaped, even if escape_func doesn't. */
+ wmem_strbuf_append_c(buf, '\\');
+ wmem_strbuf_append_c(buf, '\\');
+ }
else {
/* Other UTF-8 bytes are passed through. */
wmem_strbuf_append_c(buf, c);
}
}
- if (add_quotes)
- wmem_strbuf_append_c(buf, '"');
+ if (add_quotes && quote_char != '\0')
+ wmem_strbuf_append_c(buf, quote_char);
return wmem_strbuf_finalize(buf);
}
@@ -519,18 +778,29 @@ escape_string_len(wmem_allocator_t *alloc, const char *string, ssize_t len,
char *
ws_escape_string_len(wmem_allocator_t *alloc, const char *string, ssize_t len, bool add_quotes)
{
- return escape_string_len(alloc, string, len, escape_char, add_quotes);
+ return escape_string_len(alloc, string, len, escape_char, add_quotes, '"', false);
}
char *
ws_escape_string(wmem_allocator_t *alloc, const char *string, bool add_quotes)
{
- return escape_string_len(alloc, string, -1, escape_char, add_quotes);
+ return escape_string_len(alloc, string, -1, escape_char, add_quotes, '"', false);
}
char *ws_escape_null(wmem_allocator_t *alloc, const char *string, size_t len, bool add_quotes)
{
- return escape_string_len(alloc, string, len, escape_null, add_quotes);
+ /* XXX: The existing behavior (maintained) here is not to escape
+ * backslashes even though NUL is escaped.
+ */
+ return escape_string_len(alloc, string, len, escape_null, add_quotes, add_quotes ? '"' : '\0', false);
+}
+
+char *ws_escape_csv(wmem_allocator_t *alloc, const char *string, bool add_quotes, char quote_char, bool double_quote, bool escape_whitespace)
+{
+ if (escape_whitespace)
+ return escape_string_len(alloc, string, -1, escape_char, add_quotes, quote_char, double_quote);
+ else
+ return escape_string_len(alloc, string, -1, escape_null, add_quotes, quote_char, double_quote);
}
const char *
diff --git a/wsutil/str_util.h b/wsutil/str_util.h
index 7f1362f4..6cbcc6b3 100644
--- a/wsutil/str_util.h
+++ b/wsutil/str_util.h
@@ -182,6 +182,17 @@ bool isdigit_string(const unsigned char *str);
WS_DLL_PUBLIC
const char *ws_ascii_strcasestr(const char *haystack, const char *needle);
+/** Like the memchr() function, except it scans backwards from the end.
+ *
+ * @param haystack Pointer to the bytes of memory to search
+ * @param ch The character to search
+ * @param n The length of bytes to search from the end
+ * @return A pointer to the last occurrence of "ch" in "haystack".
+ * If "ch" isn't found or "n" is 0, returns NULL.
+ */
+WS_DLL_PUBLIC
+const uint8_t *ws_memrchr(const void *haystack, int ch, size_t n);
+
WS_DLL_PUBLIC
char *ws_escape_string(wmem_allocator_t *alloc, const char *string, bool add_quotes);
@@ -192,22 +203,75 @@ char *ws_escape_string_len(wmem_allocator_t *alloc, const char *string, ssize_t
WS_DLL_PUBLIC
char *ws_escape_null(wmem_allocator_t *alloc, const char *string, size_t len, bool add_quotes);
+/* Escape as in a number of CSV dialects.
+ *
+ * @param allocator The wmem scope to use to allocate the returned string
+ * @param string The input string to escape
+ * @param add_quotes Whether to surround the string with quote_char
+ * @param quote_char The quote character, always escaped in some way.
+ * @param double_quote Whether to escape the quote character by doubling it
+ * @param escape_whitespace Whether to escape whitespace with a backslash
+ * @return The escaped string
+ *
+ * @note If double_quote is false, then quote_or_delim is escaped with a
+ * backslash ('\'). The quote character can be '\0', in which case it is
+ * ignored. If any character is being escaped with a backslash (i.e.,
+ * quote_char is not '\0' and double_quote is false, or escape_whitespace
+ * is true), then backslash is also escaped. If add_quotes is false, then
+ * quote_char can either be a quote character (if the string will be quoted
+ * later after further manipulation) or the delimiter (to escape it, since
+ * the string is not being quoted.).
+ */
+WS_DLL_PUBLIC
+char *ws_escape_csv(wmem_allocator_t *alloc, const char *string, bool add_quotes, char quote_char, bool double_quote, bool escape_whitespace);
+
WS_DLL_PUBLIC
int ws_xton(char ch);
typedef enum {
FORMAT_SIZE_UNIT_NONE, /**< No unit will be appended. You must supply your own. */
+ /* XXX - This does not append a trailing space if there is no prefix.
+ * That's good if you intend to list the unit somewhere else, e.g. in a
+ * legend, header, or other column, but doesn't work well if intending
+ * to append your own unit. You can test whether there's a prefix or
+ * not with g_ascii_isdigit() (plus special handling for inf and NaN).
+ */
FORMAT_SIZE_UNIT_BYTES, /**< "bytes" for un-prefixed sizes, "B" otherwise. */
FORMAT_SIZE_UNIT_BITS, /**< "bits" for un-prefixed sizes, "b" otherwise. */
FORMAT_SIZE_UNIT_BITS_S, /**< "bits/s" for un-prefixed sizes, "bps" otherwise. */
FORMAT_SIZE_UNIT_BYTES_S, /**< "bytes/s" for un-prefixed sizes, "Bps" otherwise. */
FORMAT_SIZE_UNIT_PACKETS, /**< "packets" */
FORMAT_SIZE_UNIT_PACKETS_S, /**< "packets/s" */
+ FORMAT_SIZE_UNIT_EVENTS, /**< "events" */
+ FORMAT_SIZE_UNIT_EVENTS_S, /**< "events/s" */
+ FORMAT_SIZE_UNIT_FIELDS, /**< "fields" */
+ /* These next two aren't really for format_size (which takes an int) */
+ FORMAT_SIZE_UNIT_SECONDS, /**< "seconds" for un-prefixed sizes, "s" otherwise. */
+ FORMAT_SIZE_UNIT_ERLANGS, /**< "erlangs" for un-prefixed sizes, "E" otherwise. */
} format_size_units_e;
#define FORMAT_SIZE_PREFIX_SI (1 << 0) /**< SI (power of 1000) prefixes will be used. */
#define FORMAT_SIZE_PREFIX_IEC (1 << 1) /**< IEC (power of 1024) prefixes will be used. */
+/** Given a floating point value, return it in a human-readable format
+ *
+ * Prefixes up to "E/Ei" (exa, exbi) and down to "a" (atto; negative
+ * prefixes are SI-only) are currently supported. Values outside that
+ * range will use scientific notation.
+ *
+ * @param size The size value
+ * @param flags Flags to control the output (unit of measurement,
+ * SI vs IEC, etc). Unit and prefix flags may be ORed together.
+ * @param precision Maximum number of digits to appear after the
+ * decimal point. Trailing zeros are removed, as is the decimal
+ * point if not digits follow it.
+ * @return A newly-allocated string representing the value.
+ */
+WS_DLL_PUBLIC
+char *format_units(wmem_allocator_t *allocator, double size,
+ format_size_units_e unit, uint16_t flags,
+ int precision);
+
/** Given a size, return its value in a human-readable format
*
* Prefixes up to "T/Ti" (tera, tebi) are currently supported.
diff --git a/wsutil/test_wsutil.c b/wsutil/test_wsutil.c
index ff9e2f82..755f0853 100644
--- a/wsutil/test_wsutil.c
+++ b/wsutil/test_wsutil.c
@@ -12,6 +12,7 @@
#include <glib.h>
#include <wsutil/utf8_entities.h>
#include <wsutil/time_util.h>
+#include <wsutil/to_str.h>
#include "inet_addr.h"
@@ -46,7 +47,7 @@ struct in6_test {
ws_in6_addr addr;
};
-static struct in6_test in6_test1 = {
+static const struct in6_test in6_test1 = {
.str = "2001:db8:ffaa:ddbb:1199:2288:3377:1",
.addr = { { 0x20, 0x01, 0x0d, 0xb8, 0xff, 0xaa, 0xdd, 0xbb,
0x11, 0x99, 0x22, 0x88, 0x33, 0x77, 0x00, 0x01 } }
@@ -72,6 +73,19 @@ static void test_inet_ntop6_test1(void)
g_assert_cmpstr(result, ==, in6_test1.str);
}
+static void test_ip_addr_to_str_test1(void)
+{
+ char result[WS_INET_ADDRSTRLEN];
+ const char *expect;
+ ws_in4_addr addr;
+
+ addr = g_htonl(3325256904);
+ expect = "198.51.100.200";
+ ip_addr_to_str_buf(&addr, result, sizeof(result));
+
+ g_assert_cmpstr(result, ==, expect);
+}
+
#include "str_util.h"
static void test_format_size(void)
@@ -107,6 +121,15 @@ static void test_escape_string(void)
buf = ws_escape_null(NULL, s1, sizeof(s1), true);
g_assert_cmpstr(buf, ==, "\"abc\\0efg\"");
wmem_free(NULL, buf);
+
+ const char s2[] = { 'a', 'b', 'c', '\0', '"', 'e', 'f', 'g'};
+ buf = ws_escape_null(NULL, s2, sizeof(s2), true);
+ g_assert_cmpstr(buf, ==, "\"abc\\0\\\"efg\"");
+ wmem_free(NULL, buf);
+
+ buf = ws_escape_csv(NULL, "CSV-style \" escape", true, '"', true, false);
+ g_assert_cmpstr(buf, ==, "\"CSV-style \"\" escape\"");
+ wmem_free(NULL, buf);
}
static void test_strconcat(void)
@@ -261,7 +284,7 @@ static void test_word_to_hex(void)
static char buf[32];
char *str; /* String is not NULL terminated. */
- str = guint8_to_hex(buf, 0x34);
+ str = uint8_to_hex(buf, 0x34);
g_assert_true(str == buf + 2);
g_assert_cmpint(str[-1], ==, '4');
g_assert_cmpint(str[-2], ==, '3');
@@ -284,7 +307,7 @@ static void test_word_to_hex(void)
g_assert_cmpint(str[-7], ==, '0');
g_assert_cmpint(str[-8], ==, '0');
- str = qword_to_hex(buf, G_GUINT64_CONSTANT(0xFEDCBA987654321));
+ str = qword_to_hex(buf, UINT64_C(0xFEDCBA987654321));
g_assert_true(str == buf + 16);
g_assert_cmpint(str[-1], ==, '1');
g_assert_cmpint(str[-2], ==, '2');
@@ -448,13 +471,13 @@ static void test_oct64_to_str_back(void)
{
char *str;
- str = oct64_to_str_back(BACK_PTR, G_GUINT64_CONSTANT(13873797580070999420));
+ str = oct64_to_str_back(BACK_PTR, UINT64_C(13873797580070999420));
g_assert_cmpstr(str, ==, "01402115026217563452574");
- str = oct64_to_str_back(BACK_PTR, G_GUINT64_CONSTANT(7072159458371400691));
+ str = oct64_to_str_back(BACK_PTR, UINT64_C(7072159458371400691));
g_assert_cmpstr(str, ==, "0610452670726711271763");
- str = oct64_to_str_back(BACK_PTR, G_GUINT64_CONSTANT(12453513102400590374));
+ str = oct64_to_str_back(BACK_PTR, UINT64_C(12453513102400590374));
g_assert_cmpstr(str, ==, "01263236102754220511046");
}
@@ -476,13 +499,13 @@ static void test_hex64_to_str_back_len(void)
{
char *str;
- str = hex64_to_str_back_len(BACK_PTR, G_GUINT64_CONSTANT(1), 16);
+ str = hex64_to_str_back_len(BACK_PTR, UINT64_C(1), 16);
g_assert_cmpstr(str, ==, "0x0000000000000001");
- str = hex64_to_str_back_len(BACK_PTR, G_GUINT64_CONSTANT(4294967295), 16);
+ str = hex64_to_str_back_len(BACK_PTR, UINT64_C(4294967295), 16);
g_assert_cmpstr(str, ==, "0x00000000ffffffff");
- str = hex64_to_str_back_len(BACK_PTR, G_GUINT64_CONSTANT(18446744073709551615), 16);
+ str = hex64_to_str_back_len(BACK_PTR, UINT64_C(18446744073709551615), 16);
g_assert_cmpstr(str, ==, "0xffffffffffffffff");
}
@@ -504,13 +527,13 @@ static void test_uint64_to_str_back(void)
{
char *str;
- str = uint64_to_str_back(BACK_PTR, G_GUINT64_CONSTANT(585143757104211265));
+ str = uint64_to_str_back(BACK_PTR, UINT64_C(585143757104211265));
g_assert_cmpstr(str, ==, "585143757104211265");
- str = uint64_to_str_back(BACK_PTR, G_GUINT64_CONSTANT(7191580247919484847));
+ str = uint64_to_str_back(BACK_PTR, UINT64_C(7191580247919484847));
g_assert_cmpstr(str, ==, "7191580247919484847");
- str = uint64_to_str_back(BACK_PTR, G_GUINT64_CONSTANT(95778573911934485));
+ str = uint64_to_str_back(BACK_PTR, UINT64_C(95778573911934485));
g_assert_cmpstr(str, ==, "95778573911934485");
}
@@ -532,13 +555,13 @@ static void test_uint64_to_str_back_len(void)
{
char *str;
- str = uint64_to_str_back_len(BACK_PTR, G_GUINT64_CONSTANT(1), 16);
+ str = uint64_to_str_back_len(BACK_PTR, UINT64_C(1), 16);
g_assert_cmpstr(str, ==, "0000000000000001");
- str = uint64_to_str_back_len(BACK_PTR, G_GUINT64_CONSTANT(4294967295), 16);
+ str = uint64_to_str_back_len(BACK_PTR, UINT64_C(4294967295), 16);
g_assert_cmpstr(str, ==, "0000004294967295");
- str = uint64_to_str_back_len(BACK_PTR, G_GUINT64_CONSTANT(18446744073709551615), 16);
+ str = uint64_to_str_back_len(BACK_PTR, UINT64_C(18446744073709551615), 16);
g_assert_cmpstr(str, ==, "18446744073709551615");
}
@@ -560,13 +583,13 @@ static void test_int64_to_str_back(void)
{
char *str;
- str = int64_to_str_back(BACK_PTR, G_GINT64_CONSTANT(-9223372036854775807));
+ str = int64_to_str_back(BACK_PTR, INT64_C(-9223372036854775807));
g_assert_cmpstr(str, ==, "-9223372036854775807");
- str = int64_to_str_back(BACK_PTR, G_GINT64_CONSTANT(1));
+ str = int64_to_str_back(BACK_PTR, INT64_C(1));
g_assert_cmpstr(str, ==, "1");
- str = int64_to_str_back(BACK_PTR, G_GINT64_CONSTANT(9223372036854775807));
+ str = int64_to_str_back(BACK_PTR, INT64_C(9223372036854775807));
g_assert_cmpstr(str, ==, "9223372036854775807");
}
@@ -854,6 +877,7 @@ int main(int argc, char **argv)
g_test_add_func("/to_str/uint64_to_str_back_len", test_uint64_to_str_back_len);
g_test_add_func("/to_str/int_to_str_back", test_int_to_str_back);
g_test_add_func("/to_str/int64_to_str_back", test_int64_to_str_back);
+ g_test_add_func("/to_str/ip_addr_to_str_test1", test_ip_addr_to_str_test1);
g_test_add_func("/nstime/from_iso8601", test_nstime_from_iso8601);
diff --git a/wsutil/time_util.c b/wsutil/time_util.c
index 6d967953..1fda2c57 100644
--- a/wsutil/time_util.c
+++ b/wsutil/time_util.c
@@ -199,7 +199,7 @@ void log_resource_usage(bool reset_delta, const char *format, ...) {
va_end(ap);
ws_warning("%s", log_str->str);
- g_string_free(log_str, true);
+ g_string_free(log_str, TRUE);
}
diff --git a/wsutil/to_str.c b/wsutil/to_str.c
index d3e41538..58dda056 100644
--- a/wsutil/to_str.c
+++ b/wsutil/to_str.c
@@ -95,7 +95,7 @@ byte_to_hex(char *out, uint32_t dword)
}
char *
-guint8_to_hex(char *out, uint8_t val)
+uint8_to_hex(char *out, uint8_t val)
{
return byte_to_hex(out, val);
}
@@ -418,7 +418,7 @@ uint_to_str_back_len(char *ptr, uint32_t value, int len)
new_ptr = uint_to_str_back(ptr, value);
- /* substract from len number of generated characters */
+ /* subtract from len number of generated characters */
len -= (int)(ptr - new_ptr);
/* pad remaining with '0' */
@@ -438,7 +438,7 @@ uint64_to_str_back_len(char *ptr, uint64_t value, int len)
new_ptr = uint64_to_str_back(ptr, value);
- /* substract from len number of generated characters */
+ /* subtract from len number of generated characters */
len -= (int)(ptr - new_ptr);
/* pad remaining with '0' */
@@ -476,7 +476,7 @@ int64_to_str_back(char *ptr, int64_t value)
}
static size_t
-guint32_to_str_buf_len(const uint32_t u)
+uint32_to_str_buf_len(const uint32_t u)
{
/* ((2^32)-1) == 2147483647 */
if (u >= 1000000000)return 10;
@@ -493,9 +493,9 @@ guint32_to_str_buf_len(const uint32_t u)
}
void
-guint32_to_str_buf(uint32_t u, char *buf, size_t buf_len)
+uint32_to_str_buf(uint32_t u, char *buf, size_t buf_len)
{
- size_t str_len = guint32_to_str_buf_len(u)+1;
+ size_t str_len = uint32_to_str_buf_len(u)+1;
char *bp = &buf[str_len];
@@ -507,37 +507,37 @@ guint32_to_str_buf(uint32_t u, char *buf, size_t buf_len)
}
static size_t
-guint64_to_str_buf_len(const uint64_t u)
+uint64_to_str_buf_len(const uint64_t u)
{
/* ((2^64)-1) == 18446744073709551615 */
- if (u >= G_GUINT64_CONSTANT(10000000000000000000)) return 20;
- if (u >= G_GUINT64_CONSTANT(1000000000000000000)) return 19;
- if (u >= G_GUINT64_CONSTANT(100000000000000000)) return 18;
- if (u >= G_GUINT64_CONSTANT(10000000000000000)) return 17;
- if (u >= G_GUINT64_CONSTANT(1000000000000000)) return 16;
- if (u >= G_GUINT64_CONSTANT(100000000000000)) return 15;
- if (u >= G_GUINT64_CONSTANT(10000000000000)) return 14;
- if (u >= G_GUINT64_CONSTANT(1000000000000)) return 13;
- if (u >= G_GUINT64_CONSTANT(100000000000)) return 12;
- if (u >= G_GUINT64_CONSTANT(10000000000)) return 11;
- if (u >= G_GUINT64_CONSTANT(1000000000)) return 10;
- if (u >= G_GUINT64_CONSTANT(100000000)) return 9;
- if (u >= G_GUINT64_CONSTANT(10000000)) return 8;
- if (u >= G_GUINT64_CONSTANT(1000000)) return 7;
- if (u >= G_GUINT64_CONSTANT(100000)) return 6;
- if (u >= G_GUINT64_CONSTANT(10000)) return 5;
- if (u >= G_GUINT64_CONSTANT(1000)) return 4;
- if (u >= G_GUINT64_CONSTANT(100)) return 3;
- if (u >= G_GUINT64_CONSTANT(10)) return 2;
+ if (u >= UINT64_C(10000000000000000000)) return 20;
+ if (u >= UINT64_C(1000000000000000000)) return 19;
+ if (u >= UINT64_C(100000000000000000)) return 18;
+ if (u >= UINT64_C(10000000000000000)) return 17;
+ if (u >= UINT64_C(1000000000000000)) return 16;
+ if (u >= UINT64_C(100000000000000)) return 15;
+ if (u >= UINT64_C(10000000000000)) return 14;
+ if (u >= UINT64_C(1000000000000)) return 13;
+ if (u >= UINT64_C(100000000000)) return 12;
+ if (u >= UINT64_C(10000000000)) return 11;
+ if (u >= UINT64_C(1000000000)) return 10;
+ if (u >= UINT64_C(100000000)) return 9;
+ if (u >= UINT64_C(10000000)) return 8;
+ if (u >= UINT64_C(1000000)) return 7;
+ if (u >= UINT64_C(100000)) return 6;
+ if (u >= UINT64_C(10000)) return 5;
+ if (u >= UINT64_C(1000)) return 4;
+ if (u >= UINT64_C(100)) return 3;
+ if (u >= UINT64_C(10)) return 2;
return 1;
}
void
-guint64_to_str_buf(uint64_t u, char *buf, size_t buf_len)
+uint64_to_str_buf(uint64_t u, char *buf, size_t buf_len)
{
- size_t str_len = guint64_to_str_buf_len(u)+1;
+ size_t str_len = uint64_to_str_buf_len(u)+1;
char *bp = &buf[str_len];
@@ -553,8 +553,9 @@ guint64_to_str_buf(uint64_t u, char *buf, size_t buf_len)
XXX update the address_to_str stuff to use this function.
*/
void
-ip_to_str_buf(const uint8_t *ad, char *buf, const int buf_len)
+ip_addr_to_str_buf(const ws_in4_addr *_ad, char *buf, const int buf_len)
{
+ uint8_t *ad = (uint8_t *)_ad;
register char const *p;
register char *b=buf;
@@ -589,16 +590,44 @@ ip_to_str_buf(const uint8_t *ad, char *buf, const int buf_len)
*b=0;
}
-char *ip_to_str(wmem_allocator_t *scope, const uint8_t *ad)
+char *
+ip_addr_to_str(wmem_allocator_t *scope, const ws_in4_addr *ad)
{
char *buf = wmem_alloc(scope, WS_INET_ADDRSTRLEN * sizeof(char));
- ip_to_str_buf(ad, buf, WS_INET_ADDRSTRLEN);
+ ip_addr_to_str_buf(ad, buf, WS_INET_ADDRSTRLEN);
return buf;
}
void
+ip_num_to_str_buf(uint32_t ad, char *buf, const int buf_len)
+{
+ ws_in4_addr addr = g_htonl(ad);
+ ip_addr_to_str_buf(&addr, buf, buf_len);
+}
+
+/* Host byte order */
+char *
+ip_num_to_str(wmem_allocator_t *scope, uint32_t ad)
+{
+ ws_in4_addr addr = g_htonl(ad);
+ return ip_addr_to_str(scope, &addr);
+}
+
+void
+ip_to_str_buf(const uint8_t *ad, char *buf, const int buf_len)
+{
+ ip_addr_to_str_buf((const ws_in4_addr *)ad, buf, buf_len);
+}
+
+char *
+ip_to_str(wmem_allocator_t *scope, const uint8_t *ad)
+{
+ return ip_addr_to_str(scope, (const ws_in4_addr *)ad);
+}
+
+void
ip6_to_str_buf(const ws_in6_addr *addr, char *buf, size_t buf_size)
{
/*
diff --git a/wsutil/to_str.h b/wsutil/to_str.h
index 08bd536b..565d34b3 100644
--- a/wsutil/to_str.h
+++ b/wsutil/to_str.h
@@ -15,7 +15,7 @@
#include <wireshark.h>
#include <wsutil/wmem/wmem.h>
-#include <wsutil/inet_ipv6.h>
+#include <wsutil/inet_addr.h>
#include <wsutil/nstime.h>
#ifdef __cplusplus
@@ -23,7 +23,7 @@ extern "C" {
#endif /* __cplusplus */
/**
- * guint8_to_hex()
+ * uint8_to_hex()
*
* Output uint8_t hex representation to 'out', and return pointer after last character (out + 2).
* It will always output full representation (padded with 0).
@@ -31,7 +31,10 @@ extern "C" {
* String is not NUL terminated by this routine.
* There needs to be at least 2 bytes in the buffer.
*/
-WS_DLL_PUBLIC char *guint8_to_hex(char *out, uint8_t val);
+WS_DLL_PUBLIC char *uint8_to_hex(char *out, uint8_t val);
+
+WS_DEPRECATED_X("Use uint8_to_hex instead")
+static inline char *guint8_to_hex(char *out, uint8_t val) { return uint8_to_hex(out, val); }
/**
* word_to_hex()
@@ -282,15 +285,32 @@ WS_DLL_PUBLIC char *int_to_str_back(char *ptr, int32_t value);
*/
WS_DLL_PUBLIC char *int64_to_str_back(char *ptr, int64_t value);
-WS_DLL_PUBLIC void guint32_to_str_buf(uint32_t u, char *buf, size_t buf_len);
+WS_DLL_PUBLIC void uint32_to_str_buf(uint32_t u, char *buf, size_t buf_len);
+
+WS_DEPRECATED_X("Use uint32_to_str_buf instead")
+static inline void guint32_to_str_buf(uint32_t u, char *buf, size_t buf_len) { uint32_to_str_buf(u, buf, buf_len); }
-WS_DLL_PUBLIC void guint64_to_str_buf(uint64_t u, char *buf, size_t buf_len);
+WS_DLL_PUBLIC void uint64_to_str_buf(uint64_t u, char *buf, size_t buf_len);
+WS_DEPRECATED_X("Use uint64_to_str_buf instead")
+static inline void guint64_to_str_buf(uint64_t u, char *buf, size_t buf_len) { uint64_to_str_buf(u, buf, buf_len); }
+
+WS_DEPRECATED_X("Use ip_num_to_str_buf() or ip_addr_to_str() instead")
WS_DLL_PUBLIC void ip_to_str_buf(const uint8_t *ad, char *buf, const int buf_len);
+WS_DEPRECATED_X("Use ip_num_to_str() or ip_addr_to_str() instead")
WS_DLL_PUBLIC char *ip_to_str(wmem_allocator_t *scope, const uint8_t *ad);
-/* Returns length of the result. */
+/* Host byte order */
+WS_DLL_PUBLIC void ip_num_to_str_buf(uint32_t ad, char *buf, const int buf_len);
+
+/* Host byte order */
+WS_DLL_PUBLIC char *ip_num_to_str(wmem_allocator_t *scope, uint32_t ad);
+
+WS_DLL_PUBLIC void ip_addr_to_str_buf(const ws_in4_addr *ad, char *buf, const int buf_len);
+
+WS_DLL_PUBLIC char *ip_addr_to_str(wmem_allocator_t *scope, const ws_in4_addr *ad);
+
WS_DLL_PUBLIC void ip6_to_str_buf(const ws_in6_addr *ad, char *buf, size_t buf_size);
WS_DLL_PUBLIC char *ip6_to_str(wmem_allocator_t *scope, const ws_in6_addr *ad);
diff --git a/wsutil/type_util.c b/wsutil/type_util.c
index f98a1b1d..cfe9fe70 100644
--- a/wsutil/type_util.c
+++ b/wsutil/type_util.c
@@ -36,16 +36,16 @@
*/
double
-type_util_guint64_to_gdouble(uint64_t value)
+type_util_uint64_to_double(uint64_t value)
{
- if (value & G_GUINT64_CONSTANT (0x8000000000000000))
+ if (value & UINT64_C (0x8000000000000000))
return (double) ((int64_t) value) + (double) 18446744073709551616.;
else
return (double) ((int64_t) value);
}
uint64_t
-type_util_gdouble_to_guint64(double value)
+type_util_double_to_uint64(double value)
{
if (value < (double) 9223372036854775808.) /* 1 << 63 */
return ((uint64_t) ((int64_t) value));
diff --git a/wsutil/type_util.h b/wsutil/type_util.h
index eab9ff9b..cc8199f5 100644
--- a/wsutil/type_util.h
+++ b/wsutil/type_util.h
@@ -29,16 +29,16 @@
*/
WS_DLL_PUBLIC
-uint64_t type_util_gdouble_to_guint64(double value);
+uint64_t type_util_double_to_uint64(double value);
WS_DLL_PUBLIC
-double type_util_guint64_to_gdouble(uint64_t value);
+double type_util_uint64_to_double(uint64_t value);
#ifdef _WIN32
-#define gdouble_to_guint64(value) type_util_gdouble_to_guint64(value)
-#define guint64_to_gdouble(value) type_util_guint64_to_gdouble(value)
+#define double_to_uint64(value) type_util_double_to_uint64(value)
+#define uint64_to_double(value) type_util_uint64_to_double(value)
#else
-#define gdouble_to_guint64(value) ((uint64_t)(value))
-#define guint64_to_gdouble(value) ((double)(value))
+#define double_to_uint64(value) ((uint64_t)(value))
+#define uint64_to_double(value) ((double)(value))
#endif
#endif /* __TYPE_UTIL_H__ */
diff --git a/wsutil/unicode-utils.c b/wsutil/unicode-utils.c
index 4ed4b326..2e50393a 100644
--- a/wsutil/unicode-utils.c
+++ b/wsutil/unicode-utils.c
@@ -12,7 +12,7 @@
#include "unicode-utils.h"
-int ws_utf8_seqlen[256] = {
+const int ws_utf8_seqlen[256] = {
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 0x00...0x0f */
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 0x10...0x1f */
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 0x20...0x2f */
diff --git a/wsutil/unicode-utils.h b/wsutil/unicode-utils.h
index 21c50ec0..d8a9a9bf 100644
--- a/wsutil/unicode-utils.h
+++ b/wsutil/unicode-utils.h
@@ -50,7 +50,7 @@ extern "C" {
_CHECK_UTF_8(LOG_LEVEL_ECHO, str, len)
WSUTIL_EXPORT
-int ws_utf8_seqlen[256];
+const int ws_utf8_seqlen[256];
/** Given the first byte in an UTF-8 encoded code point,
* return the length of the multibyte sequence, or *ZERO*
diff --git a/wsutil/utf8_entities.h b/wsutil/utf8_entities.h
index 3d2f2533..e7ad8cbc 100644
--- a/wsutil/utf8_entities.h
+++ b/wsutil/utf8_entities.h
@@ -47,6 +47,8 @@
#define UTF8_RIGHTWARDS_ARROW "\xe2\x86\x92" /* 8594 / 0x2192 */
#define UTF8_LEFT_RIGHT_ARROW "\xe2\x86\x94" /* 8596 / 0x2194 */
+#define UTF8_SQUARE_ROOT "\xe2\x88\x9a" /* 8730 / 0x221a */
+
/* macOS command key */
#define UTF8_PLACE_OF_INTEREST_SIGN "\xe2\x8c\x98" /* 8984 / 0x2318 */
diff --git a/wsutil/version_info.c b/wsutil/version_info.c
index ab450686..9fbee0d2 100644
--- a/wsutil/version_info.c
+++ b/wsutil/version_info.c
@@ -32,6 +32,10 @@
#include <zlib.h>
#endif
+//#ifdef HAVE_ZLIBNG
+//#include <zlib-ng.h>
+//#endif
+
#include "vcs_version.h"
#include <wsutil/cpu_info.h>
@@ -60,11 +64,11 @@ ws_init_version_info(const char *appname,
copyright_info_str = g_string_new(get_copyright_info());
end_string(copyright_info_str);
- copyright_info = g_string_free(copyright_info_str, false);
+ copyright_info = g_string_free(copyright_info_str, FALSE);
license_info_str = g_string_new(get_license_info_short());
end_string(license_info_str);
- license_info = g_string_free(license_info_str, false);
+ license_info = g_string_free(license_info_str, FALSE);
/*
* Combine the supplied application name string with the
@@ -86,8 +90,8 @@ ws_init_version_info(const char *appname,
/* Get the run-time version information string */
runtime_info_str = get_runtime_version_info(gather_runtime);
- comp_info = g_string_free(comp_info_str, false);
- runtime_info = g_string_free(runtime_info_str, false);
+ comp_info = g_string_free(comp_info_str, FALSE);
+ runtime_info = g_string_free(runtime_info_str, FALSE);
/* Add this information to the information to be reported on a crash. */
ws_add_crash_info("%s\n"
@@ -162,7 +166,7 @@ gather_zlib_compile_info(feature_list l)
{
#ifdef HAVE_ZLIB
#ifdef ZLIB_VERSION
- with_feature(l, "zlib "ZLIB_VERSION);
+ with_feature(l, "zlib " ZLIB_VERSION);
#else
with_feature(l, "zlib (version unknown)");
#endif /* ZLIB_VERSION */
@@ -171,6 +175,17 @@ gather_zlib_compile_info(feature_list l)
#endif /* HAVE_ZLIB */
}
+void
+gather_zlib_ng_compile_info(feature_list l)
+{
+#ifdef HAVE_ZLIBNG
+ with_feature(l, "zlib-ng " ZLIBNG_VERSION_STRING);
+#else
+ without_feature(l, "zlib-ng");
+#endif /* HAVE_ZLIB */
+}
+
+
/*
* Get various library compile-time versions, put them in a GString,
* and return the GString.
@@ -513,18 +528,28 @@ get_runtime_version_info(gather_feature_func gather_runtime)
const char *
get_ws_vcs_version_info(void)
{
-#ifdef VCSVERSION
- return VERSION " (" VCSVERSION ")";
+#ifdef VCS_VERSION
+ return VERSION " (" VCS_VERSION ")";
#else
return VERSION;
#endif
}
const char *
+get_lr_vcs_version_info(void)
+{
+#ifdef VCS_COMMIT_ID
+ return LOG_VERSION " (" VCS_NUM_COMMITS "-" VCS_COMMIT_ID ")";
+#else
+ return LOG_VERSION;
+#endif
+}
+
+const char *
get_ws_vcs_version_info_short(void)
{
-#ifdef VCSVERSION
- return VCSVERSION;
+#ifdef VCS_VERSION
+ return VCS_VERSION;
#else
return VERSION;
#endif
diff --git a/wsutil/version_info.h b/wsutil/version_info.h
index 1285cd2c..d7b8d228 100644
--- a/wsutil/version_info.h
+++ b/wsutil/version_info.h
@@ -60,6 +60,10 @@ WS_DLL_PUBLIC
void
gather_zlib_compile_info(feature_list l);
+WS_DLL_PUBLIC
+void
+gather_zlib_ng_compile_info(feature_list l);
+
/*
* Get various library compile-time versions, put them in a GString,
* and return the GString.
@@ -99,6 +103,14 @@ WS_DLL_PUBLIC
const char *get_ws_vcs_version_info(void);
/*
+ * Return a version number string for Logray, including, for builds
+ * from a tree checked out from Logray's version control system,
+ * something identifying what version was checked out.
+ */
+WS_DLL_PUBLIC
+const char *get_lr_vcs_version_info(void);
+
+/*
* Shorter version of get_ws_vcs_version_info().
*/
WS_DLL_PUBLIC
diff --git a/wsutil/win32-utils.c b/wsutil/win32-utils.c
index b1cef5cd..60c7378c 100644
--- a/wsutil/win32-utils.c
+++ b/wsutil/win32-utils.c
@@ -9,6 +9,7 @@
*/
#include <config.h>
+#include <wsutil/array.h>
#include "win32-utils.h"
@@ -43,7 +44,7 @@ protect_arg (const char *argv)
else if (*p == '\\') {
const char *pp = p;
- while (*pp && *pp == '\\')
+ while (*pp == '\\')
pp++;
if (*pp == '"')
len++;
@@ -52,7 +53,7 @@ protect_arg (const char *argv)
p++;
}
- q = new_arg = g_malloc (len + need_dblquotes*2 + 1);
+ q = new_arg = g_malloc (len + (need_dblquotes ? 2 : 0) + 1);
p = argv;
if (need_dblquotes)
@@ -64,7 +65,7 @@ protect_arg (const char *argv)
else if (*p == '\\') {
const char *pp = p;
- while (*pp && *pp == '\\')
+ while (*pp == '\\')
pp++;
if (*pp == '"')
*q++ = '\\';
@@ -80,6 +81,28 @@ protect_arg (const char *argv)
return new_arg;
}
+#define PIPE_STR "\\pipe\\"
+
+bool
+win32_is_pipe_name(const char *pipe_name)
+{
+ char *pncopy, *pos;
+ /* Under Windows, named pipes _must_ have the form
+ * "\\<server>\pipe\<pipename>". <server> may be "." for localhost.
+ * https://learn.microsoft.com/en-us/windows/win32/ipc/pipe-names
+ */
+ pncopy = g_strdup(pipe_name);
+ if ((pos = strstr(pncopy, "\\\\")) == pncopy) {
+ pos = strchr(pncopy + 3, '\\');
+ if (pos && g_ascii_strncasecmp(pos, PIPE_STR, strlen(PIPE_STR)) != 0)
+ pos = NULL;
+ }
+
+ g_free(pncopy);
+
+ return (pos != NULL);
+}
+
/*
* Generate a UTF-8 string for a Windows error.
*/
@@ -176,7 +199,7 @@ win32strexception(DWORD exception)
{ EXCEPTION_STACK_OVERFLOW, "Stack overflow" },
{ 0, NULL }
};
-#define N_EXCEPTIONS (sizeof exceptions / sizeof exceptions[0])
+#define N_EXCEPTIONS array_length(exceptions)
for (size_t i = 0; i < N_EXCEPTIONS; i++) {
if (exceptions[i].code == exception)
diff --git a/wsutil/win32-utils.h b/wsutil/win32-utils.h
index 44471c59..1fba0c0a 100644
--- a/wsutil/win32-utils.h
+++ b/wsutil/win32-utils.h
@@ -41,6 +41,17 @@ extern "C" {
WS_DLL_PUBLIC
char * protect_arg (const char *argv);
+/** Tests a UTF-8 string to see if it is a Windows pipe name.
+ * Under Windows, named pipes _must_ have the form "\\<server>\pipe\<pipename>".
+ * <server> may be "." for localhost. This does not check that a pipe server
+ * has actually created the pipe, only that the name is the proper form.
+ *
+ * @param pipename The UTF-8 string to be checked
+ * @return TRUE if the string is a valid Windows pipe name.
+ */
+WS_DLL_PUBLIC
+bool win32_is_pipe_name(const char* pipe_name);
+
/** Generate a string for a Windows error.
*
* @param error The Windows error code
diff --git a/wsutil/wmem/wmem_allocator_block.c b/wsutil/wmem/wmem_allocator_block.c
index b8a0f598..4723f0f3 100644
--- a/wsutil/wmem/wmem_allocator_block.c
+++ b/wsutil/wmem/wmem_allocator_block.c
@@ -18,7 +18,7 @@
#include "wmem_allocator.h"
#include "wmem_allocator_block.h"
-/* This has turned into a very interesting excercise in algorithms and data
+/* This has turned into a very interesting exercise in algorithms and data
* structures.
*
* HISTORY
@@ -479,7 +479,7 @@ wmem_block_pop_master(wmem_block_allocator_t *allocator)
/* CHUNK HELPERS */
/* Takes a free chunk and checks the chunks to its immediate right and left in
- * the block. If they are also free, the contigous free chunks are merged into
+ * the block. If they are also free, the contiguous free chunks are merged into
* a single free chunk. The resulting chunk ends up in either the master list or
* the recycler, depending on where the merged chunks were originally.
*/
diff --git a/wsutil/wmem/wmem_core.c b/wsutil/wmem/wmem_core.c
index a166bf84..6a589db1 100644
--- a/wsutil/wmem/wmem_core.c
+++ b/wsutil/wmem/wmem_core.c
@@ -25,7 +25,7 @@
/* Set according to the WIRESHARK_DEBUG_WMEM_OVERRIDE environment variable in
* wmem_init. Should not be set again. */
-static bool do_override = false;
+static bool do_override;
static wmem_allocator_type_t override_type;
void *
diff --git a/wsutil/wmem/wmem_core.h b/wsutil/wmem/wmem_core.h
index 2f423133..25784c19 100644
--- a/wsutil/wmem/wmem_core.h
+++ b/wsutil/wmem/wmem_core.h
@@ -73,7 +73,8 @@ typedef enum _wmem_allocator_type_t {
WS_DLL_PUBLIC
void *
wmem_alloc(wmem_allocator_t *allocator, const size_t size)
-G_GNUC_MALLOC;
+G_GNUC_MALLOC
+G_GNUC_ALLOC_SIZE(2);
/** Allocate memory sufficient to hold one object of the given type.
*
@@ -112,7 +113,8 @@ G_GNUC_MALLOC;
WS_DLL_PUBLIC
void *
wmem_alloc0(wmem_allocator_t *allocator, const size_t size)
-G_GNUC_MALLOC;
+G_GNUC_MALLOC
+G_GNUC_ALLOC_SIZE(2);
/** Allocate memory sufficient to hold one object of the given type.
* Initializes the allocated memory with zeroes.
@@ -161,7 +163,7 @@ wmem_free(wmem_allocator_t *allocator, void *ptr);
WS_DLL_PUBLIC
void *
wmem_realloc(wmem_allocator_t *allocator, void *ptr, const size_t size)
-G_GNUC_MALLOC;
+G_GNUC_ALLOC_SIZE(3);
/** Frees all the memory allocated in a pool. Depending on the allocator
* implementation used this can be significantly cheaper than calling
diff --git a/wsutil/wmem/wmem_interval_tree.c b/wsutil/wmem/wmem_interval_tree.c
index 8b28549a..d8ed8e48 100644
--- a/wsutil/wmem/wmem_interval_tree.c
+++ b/wsutil/wmem/wmem_interval_tree.c
@@ -25,7 +25,6 @@
#include "wmem_interval_tree.h"
#include "wmem_user_cb.h"
-
static void
print_range(const void *value)
{
diff --git a/wsutil/wmem/wmem_list.c b/wsutil/wmem/wmem_list.c
index c03ffe31..b5b4c52f 100644
--- a/wsutil/wmem/wmem_list.c
+++ b/wsutil/wmem/wmem_list.c
@@ -218,6 +218,56 @@ wmem_list_insert_sorted(wmem_list_t *list, void* data, GCompareFunc func)
new_frame->next->prev = new_frame;
}
+void
+wmem_list_append_sorted(wmem_list_t *list, void* data, GCompareFunc func)
+{
+ wmem_list_frame_t *new_frame;
+ wmem_list_frame_t *cur;
+ wmem_list_frame_t *next;
+
+ new_frame = wmem_new(list->allocator, wmem_list_frame_t);
+ new_frame->data = data;
+ new_frame->next = NULL;
+ new_frame->prev = NULL;
+
+ list->count++;
+
+ if (!list->head) {
+ list->head = new_frame;
+ list->tail = new_frame;
+ return;
+ }
+
+ cur = list->tail;
+
+ /* best case scenario: append */
+ if (func(cur->data, data) <= 0) {
+ cur->next = new_frame;
+ new_frame->prev = cur;
+ list->tail = new_frame;
+ return;
+ }
+
+ do {
+ next = cur;
+ cur = cur->prev;
+ } while (cur && func(cur->data, data) >= 0);
+
+ /* worst case scenario: prepend */
+ if (!cur) {
+ next->prev = new_frame;
+ new_frame->next = next;
+ list->head = new_frame;
+ return;
+ }
+
+ /* ordinary case: insert */
+ new_frame->next = next;
+ new_frame->prev = cur;
+ new_frame->prev->next = new_frame;
+ new_frame->next->prev = new_frame;
+}
+
wmem_list_t *
wmem_list_new(wmem_allocator_t *allocator)
{
diff --git a/wsutil/wmem/wmem_list.h b/wsutil/wmem/wmem_list.h
index fc0e5229..6b73e992 100644
--- a/wsutil/wmem/wmem_list.h
+++ b/wsutil/wmem/wmem_list.h
@@ -91,6 +91,13 @@ WS_DLL_PUBLIC
void
wmem_list_insert_sorted(wmem_list_t *list, void* data, GCompareFunc func);
+/*
+ * Appender Insertion (start search from the tail)
+ */
+WS_DLL_PUBLIC
+void
+wmem_list_append_sorted(wmem_list_t *list, void* data, GCompareFunc func);
+
WS_DLL_PUBLIC
wmem_list_t *
diff --git a/wsutil/wmem/wmem_map.c b/wsutil/wmem/wmem_map.c
index 047b8457..b3c581ae 100644
--- a/wsutil/wmem/wmem_map.c
+++ b/wsutil/wmem/wmem_map.c
@@ -484,19 +484,19 @@ wmem_strong_hash(const uint8_t *buf, const size_t len)
}
unsigned
-wmem_str_hash(gconstpointer key)
+wmem_str_hash(const void *key)
{
return wmem_strong_hash((const uint8_t *)key, strlen((const char *)key));
}
unsigned
-wmem_int64_hash(gconstpointer key)
+wmem_int64_hash(const void *key)
{
return wmem_strong_hash((const uint8_t *)key, sizeof(uint64_t));
}
unsigned
-wmem_double_hash(gconstpointer key)
+wmem_double_hash(const void *key)
{
return wmem_strong_hash((const uint8_t *)key, sizeof(double));
}
diff --git a/wsutil/wmem/wmem_map.h b/wsutil/wmem/wmem_map.h
index cb296fb4..6105aee9 100644
--- a/wsutil/wmem/wmem_map.h
+++ b/wsutil/wmem/wmem_map.h
@@ -207,21 +207,21 @@ wmem_strong_hash(const uint8_t *buf, const size_t len);
*/
WS_DLL_PUBLIC
unsigned
-wmem_str_hash(gconstpointer key);
+wmem_str_hash(const void *key);
/** An implementation of GHashFunc using wmem_strong_hash. Prefer this over
* g_int64_hash when the data comes from an untrusted source.
*/
WS_DLL_PUBLIC
unsigned
-wmem_int64_hash(gconstpointer key);
+wmem_int64_hash(const void *key);
/** An implementation of GHashFunc using wmem_strong_hash. Prefer this over
* g_double_hash when the data comes from an untrusted source.
*/
WS_DLL_PUBLIC
unsigned
-wmem_double_hash(gconstpointer key);
+wmem_double_hash(const void *key);
/** @}
* @} */
diff --git a/wsutil/wmem/wmem_miscutl.c b/wsutil/wmem/wmem_miscutl.c
index 14426447..6e3e2a3a 100644
--- a/wsutil/wmem/wmem_miscutl.c
+++ b/wsutil/wmem/wmem_miscutl.c
@@ -30,13 +30,13 @@ wmem_memdup(wmem_allocator_t *allocator, const void *source, const size_t size)
}
int
-wmem_compare_int(gconstpointer a, gconstpointer b)
+wmem_compare_int(const void *a, const void *b)
{
return GPOINTER_TO_INT(a) - GPOINTER_TO_INT(b);
}
int
-wmem_compare_uint(gconstpointer a, gconstpointer b)
+wmem_compare_uint(const void *a, const void *b)
{
return GPOINTER_TO_UINT(a) > GPOINTER_TO_UINT(b) ? 1 : (GPOINTER_TO_UINT(a) < GPOINTER_TO_UINT(b) ? -1 : 0);
}
diff --git a/wsutil/wmem/wmem_miscutl.h b/wsutil/wmem/wmem_miscutl.h
index 714ee5cc..1d988878 100644
--- a/wsutil/wmem/wmem_miscutl.h
+++ b/wsutil/wmem/wmem_miscutl.h
@@ -38,17 +38,17 @@ extern "C" {
WS_DLL_PUBLIC
void *
wmem_memdup(wmem_allocator_t *allocator, const void *source, const size_t size)
-G_GNUC_MALLOC;
+G_GNUC_ALLOC_SIZE(3);
/** Generic GCompareFunc implementations to compare signed/unsigned integer
*/
WS_DLL_PUBLIC
int
-wmem_compare_int(gconstpointer a, gconstpointer b);
+wmem_compare_int(const void *a, const void *b);
WS_DLL_PUBLIC
int
-wmem_compare_uint(gconstpointer a, gconstpointer b);
+wmem_compare_uint(const void *a, const void *b);
/** @}
* @} */
diff --git a/wsutil/wmem/wmem_strutl.c b/wsutil/wmem/wmem_strutl.c
index 99f1f8c6..2ff3d5a7 100644
--- a/wsutil/wmem/wmem_strutl.c
+++ b/wsutil/wmem/wmem_strutl.c
@@ -111,7 +111,8 @@ wmem_strdup_vprintf(wmem_allocator_t *allocator, const char *fmt, va_list ap)
/* Return the first occurrence of needle in haystack.
* If not found, return NULL.
- * If either haystack or needle has 0 length, return NULL.*/
+ * If either haystack has 0 length, return NULL.
+ * If needle has 0 length, return pointer to haystack. */
const uint8_t *
ws_memmem(const void *_haystack, size_t haystack_len,
const void *_needle, size_t needle_len)
@@ -126,7 +127,11 @@ ws_memmem(const void *_haystack, size_t haystack_len,
const uint8_t *const last_possible = haystack + haystack_len - needle_len;
if (needle_len == 0) {
- return NULL;
+ return haystack;
+ }
+
+ if (needle_len == 1) {
+ return memchr(haystack, needle[0], haystack_len);
}
if (needle_len > haystack_len) {
@@ -134,9 +139,9 @@ ws_memmem(const void *_haystack, size_t haystack_len,
}
for (begin = haystack ; begin <= last_possible; ++begin) {
- if (begin[0] == needle[0] &&
- !memcmp(&begin[1], needle + 1,
- needle_len - 1)) {
+ begin = memchr(begin, needle[0], last_possible - begin + 1);
+ if (begin == NULL) break;
+ if (!memcmp(&begin[1], needle + 1, needle_len - 1)) {
return begin;
}
}
diff --git a/wsutil/wmem/wmem_strutl.h b/wsutil/wmem/wmem_strutl.h
index ee3aed65..104a1eba 100644
--- a/wsutil/wmem/wmem_strutl.h
+++ b/wsutil/wmem/wmem_strutl.h
@@ -65,8 +65,8 @@ G_GNUC_MALLOC;
* @param needle The string to look for
* @param needle_len The length of the search string
* @return A pointer to the first occurrence of "needle" in
- * "haystack". If "needle" isn't found or is NULL, or if
- * "needle_len" is 0, NULL is returned.
+ * "haystack". If "needle" isn't found or is NULL, NULL is returned.
+ * If "needle_len" is 0, a pointer to "haystack" is returned.
*/
WS_DLL_PUBLIC
const uint8_t *ws_memmem(const void *haystack, size_t haystack_len,
diff --git a/wsutil/wmem/wmem_test.c b/wsutil/wmem/wmem_test.c
index 0dc908b7..65be3502 100644
--- a/wsutil/wmem/wmem_test.c
+++ b/wsutil/wmem/wmem_test.c
@@ -91,7 +91,7 @@ wmem_test_rand_string(wmem_allocator_t *allocator, int minlen, int maxlen)
}
static int
-wmem_test_compare_guint32(const void *a, const void *b)
+wmem_test_compare_uint32(const void *a, const void *b)
{
uint32_t l, r;
@@ -692,7 +692,7 @@ wmem_test_array(void)
}
}
- wmem_array_sort(array, wmem_test_compare_guint32);
+ wmem_array_sort(array, wmem_test_compare_uint32);
for (i=0, k=0; i<8; i++) {
for (j=0; j<=i; j++, k++) {
val = *(uint32_t*)wmem_array_index(array, k);
@@ -736,7 +736,7 @@ check_val_list(void * val, void * val_to_check)
}
static int
-str_compare(gconstpointer a, gconstpointer b)
+str_compare(const void *a, const void *b)
{
return strcmp((const char*)a, (const char*)b);
}
diff --git a/wsutil/wmem/wmem_tree.c b/wsutil/wmem/wmem_tree.c
index 05fa638e..d982b3b0 100644
--- a/wsutil/wmem/wmem_tree.c
+++ b/wsutil/wmem/wmem_tree.c
@@ -23,7 +23,6 @@
#include "wmem_tree-int.h"
#include "wmem_user_cb.h"
-
static wmem_tree_node_t *
node_uncle(wmem_tree_node_t *node)
{
diff --git a/wsutil/ws_mempbrk.c b/wsutil/ws_mempbrk.c
index f3f99b71..55334242 100644
--- a/wsutil/ws_mempbrk.c
+++ b/wsutil/ws_mempbrk.c
@@ -72,6 +72,21 @@ ws_mempbrk_exec(const uint8_t* haystack, size_t haystacklen, const ws_mempbrk_pa
return ws_mempbrk_portable_exec(haystack, haystacklen, pattern, found_needle);
}
+WS_DLL_PUBLIC const uint8_t *
+ws_memrpbrk_exec(const uint8_t* haystack, size_t haystacklen, const ws_mempbrk_pattern* pattern, unsigned char *found_needle)
+{
+ const uint8_t *haystack_end = haystack + haystacklen;
+
+ while (haystack_end > haystack) {
+ if (pattern->patt[*(--haystack_end)]) {
+ if (found_needle)
+ *found_needle = *haystack_end;
+ return haystack_end;
+ }
+ }
+
+ return NULL;
+}
/*
* Editor modelines - https://www.wireshark.org/tools/modelines.html
diff --git a/wsutil/ws_mempbrk.h b/wsutil/ws_mempbrk.h
index 7aff505f..210fdfce 100644
--- a/wsutil/ws_mempbrk.h
+++ b/wsutil/ws_mempbrk.h
@@ -34,4 +34,9 @@ WS_DLL_PUBLIC void ws_mempbrk_compile(ws_mempbrk_pattern* pattern, const char *n
*/
WS_DLL_PUBLIC const uint8_t *ws_mempbrk_exec(const uint8_t* haystack, size_t haystacklen, const ws_mempbrk_pattern* pattern, unsigned char *found_needle);
+/** Scan for the needles specified by the compiled pattern, starting at the
+ * end of the haystack and working backwards.
+ */
+WS_DLL_PUBLIC const uint8_t *ws_memrpbrk_exec(const uint8_t* haystack, size_t haystacklen, const ws_mempbrk_pattern* pattern, unsigned char *found_needle);
+
#endif /* __WS_MEMPBRK_H__ */
diff --git a/wsutil/ws_pipe.c b/wsutil/ws_pipe.c
index 7689f933..2add60a9 100644
--- a/wsutil/ws_pipe.c
+++ b/wsutil/ws_pipe.c
@@ -29,12 +29,14 @@
#endif
#endif
+#if !GLIB_CHECK_VERSION(2, 58, 2)
#ifdef __linux__
#define HAS_G_SPAWN_LINUX_THREAD_SAFETY_BUG
#include <fcntl.h>
#include <sys/syscall.h> /* for syscall and SYS_getdents64 */
#include <wsutil/file_util.h> /* for ws_open -> open to pacify checkAPIs.pl */
#endif
+#endif
#include "wsutil/filesystem.h"
#include "wsutil/wslog.h"
@@ -153,7 +155,7 @@ ws_pipe_create_overlapped_read(HANDLE *read_pipe_handle, HANDLE *write_pipe_hand
*read_pipe_handle = read_pipe;
*write_pipe_handle = write_pipe;
g_free(wname);
- return(true);
+ return true;
}
#endif
@@ -221,7 +223,7 @@ convert_to_command_line(char **argv)
g_free(quoted_arg);
}
#endif
- return g_string_free(command_line, false);
+ return g_string_free(command_line, FALSE);
}
bool ws_pipe_spawn_sync(const char *working_directory, const char *command, int argc, char **args, char **command_output)
@@ -455,7 +457,7 @@ bool ws_pipe_spawn_sync(const char *working_directory, const char *command, int
status = false;
}
- local_output = g_string_free(output_string, false);
+ local_output = g_string_free(output_string, FALSE);
CloseHandle(child_stdout_rd);
CloseHandle(child_stderr_rd);
diff --git a/wsutil/ws_strptime.c b/wsutil/ws_strptime.c
index 3c55d93e..7a8a37f5 100644
--- a/wsutil/ws_strptime.c
+++ b/wsutil/ws_strptime.c
@@ -118,7 +118,7 @@ static const unsigned char *find_string(const unsigned char *, int *, const char
#define HAVE_YEAR(s) (s & S_YEAR)
#define HAVE_HOUR(s) (s & S_HOUR)
-static char utc[] = { "UTC" };
+static const char utc[] = { "UTC" };
/* RFC-822/RFC-2822 */
static const char * const nast[5] = {
"EST", "CST", "MST", "PST", "\0\0\0"
diff --git a/wsutil/wsjson.c b/wsutil/wsjson.c
index d2e55771..4a53e971 100644
--- a/wsutil/wsjson.c
+++ b/wsutil/wsjson.c
@@ -194,6 +194,43 @@ bool json_get_double(char *buf, jsmntok_t *parent, const char *name, double *val
return false;
}
+bool json_get_boolean(char *buf, jsmntok_t *parent, const char *name, bool *val)
+{
+ int i;
+ size_t tok_len;
+ jsmntok_t *cur = parent+1;
+
+ for (i = 0; i < parent->size; i++) {
+ if (cur->type == JSMN_STRING &&
+ !strncmp(&buf[cur->start], name, cur->end - cur->start)
+ && strlen(name) == (size_t)(cur->end - cur->start) &&
+ cur->size == 1 && (cur+1)->type == JSMN_PRIMITIVE) {
+ /* JSMN_STRICT guarantees that a primitive starts with the
+ * correct character.
+ */
+ tok_len = (cur+1)->end - (cur+1)->start;
+ switch (buf[(cur+1)->start]) {
+ case 't':
+ if (tok_len == 4 && strncmp(&buf[(cur+1)->start], "true", tok_len) == 0) {
+ *val = true;
+ return true;
+ }
+ return false;
+ case 'f':
+ if (tok_len == 5 && strncmp(&buf[(cur+1)->start], "false", tok_len) == 0) {
+ *val = false;
+ return true;
+ }
+ return false;
+ default:
+ return false;
+ }
+ }
+ cur = json_get_next_object(cur);
+ }
+ return false;
+}
+
bool
json_decode_string_inplace(char *text)
{
diff --git a/wsutil/wsjson.h b/wsutil/wsjson.h
index be232767..180c0fb1 100644
--- a/wsutil/wsjson.h
+++ b/wsutil/wsjson.h
@@ -70,6 +70,12 @@ WS_DLL_PUBLIC char *json_get_string(char *buf, jsmntok_t *parent, const char *na
WS_DLL_PUBLIC bool json_get_double(char *buf, jsmntok_t *parent, const char *name, double *val);
/**
+ * Get the value of a boolean belonging to parent object and named as the name variable.
+ * Returns false if not found. (Not the same as the boolean present but false.)
+ */
+WS_DLL_PUBLIC bool json_get_boolean(char *buf, jsmntok_t *parent, const char *name, bool *val);
+
+/**
* Decode the contents of a JSON string value by overwriting the input data.
* Returns true on success and false if invalid characters were encountered.
*/
diff --git a/wsutil/wslog.c b/wsutil/wslog.c
index e181e5ed..4b35c294 100644
--- a/wsutil/wslog.c
+++ b/wsutil/wslog.c
@@ -87,40 +87,40 @@ typedef struct {
* will be printed regardless of log level. This is a feature, not a bug. */
static enum ws_log_level current_log_level = LOG_LEVEL_NONE;
-static bool stdout_color_enabled = false;
+static bool stdout_color_enabled;
-static bool stderr_color_enabled = false;
+static bool stderr_color_enabled;
/* Use stdout for levels "info" and below, for backward compatibility
* with GLib. */
-static bool stdout_logging_enabled = false;
+static bool stdout_logging_enabled;
static const char *registered_progname = DEFAULT_PROGNAME;
/* List of domains to filter. */
-static log_filter_t *domain_filter = NULL;
+static log_filter_t *domain_filter;
/* List of domains to output debug level unconditionally. */
-static log_filter_t *debug_filter = NULL;
+static log_filter_t *debug_filter;
/* List of domains to output noisy level unconditionally. */
-static log_filter_t *noisy_filter = NULL;
+static log_filter_t *noisy_filter;
/* List of domains that are fatal. */
-static log_filter_t *fatal_filter = NULL;
+static log_filter_t *fatal_filter;
-static ws_log_writer_cb *registered_log_writer = NULL;
+static ws_log_writer_cb *registered_log_writer;
-static void *registered_log_writer_data = NULL;
+static void *registered_log_writer_data;
-static ws_log_writer_free_data_cb *registered_log_writer_data_free = NULL;
+static ws_log_writer_free_data_cb *registered_log_writer_data_free;
-static FILE *custom_log = NULL;
+static FILE *custom_log;
static enum ws_log_level fatal_log_level = LOG_LEVEL_ERROR;
#ifdef WS_DEBUG
-static bool init_complete = false;
+static bool init_complete;
#endif
ws_log_console_open_pref ws_log_console_open = LOG_CONSOLE_OPEN_NEVER;
@@ -864,13 +864,8 @@ void ws_log_init(const char *progname,
if ((fd = fileno(stderr)) >= 0)
stderr_color_enabled = g_log_writer_supports_color(fd);
- /* Set the GLib log handler for the default domain. */
- g_log_set_handler(NULL, G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL,
- glib_log_handler, NULL);
-
- /* Set the GLib log handler for GLib itself. */
- g_log_set_handler("GLib", G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL,
- glib_log_handler, NULL);
+ /* Set ourselves as the default log handler for all GLib domains. */
+ g_log_set_default_handler(glib_log_handler, NULL);
#ifdef _WIN32
load_registry();
diff --git a/wsutil/wslog.h b/wsutil/wslog.h
index 8044ad10..8f97a543 100644
--- a/wsutil/wslog.h
+++ b/wsutil/wslog.h
@@ -357,18 +357,19 @@ void ws_log_fatal_full(const char *domain, enum ws_log_level level,
/** Logs with "message" level.
*
- * Accepts a format string and *does not* include the file and function
- * name. This is the default log level.
+ * Accepts a format string and does not include the file and function
+ * name (use ws_log_full instead). This is the default log level.
*/
#define ws_message(...) \
_LOG_SIMPLE(true, LOG_LEVEL_MESSAGE, __VA_ARGS__)
/** Logs with "info" level.
*
- * Accepts a format string and includes the file and function name.
+ * Accepts a format string and does not include the file and function
+ * name (use ws_log_full instead).
*/
#define ws_info(...) \
- _LOG_FULL(true, LOG_LEVEL_INFO, __VA_ARGS__)
+ _LOG_SIMPLE(true, LOG_LEVEL_INFO, __VA_ARGS__)
/** Logs with "debug" level.
*
@@ -388,6 +389,8 @@ void ws_log_fatal_full(const char *domain, enum ws_log_level level,
#define WS_DEBUG_HERE(...) \
_LOG_FULL(true, LOG_LEVEL_ECHO, __VA_ARGS__)
+#define WS_NOT_IMPLEMENTED() \
+ ws_error("Not implemented yet")
WS_DLL_PUBLIC
void ws_log_utf8_full(const char *domain, enum ws_log_level level,