summaryrefslogtreecommitdiffstats
path: root/dumpcap.c
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-09-19 04:14:33 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-09-19 04:14:33 +0000
commit9f153fbfec0fb9c9ce38e749a7c6f4a5e115d4e9 (patch)
tree2784370cda9bbf2da9114d70f05399c0b229d28c /dumpcap.c
parentAdding debian version 4.2.6-1. (diff)
downloadwireshark-9f153fbfec0fb9c9ce38e749a7c6f4a5e115d4e9.tar.xz
wireshark-9f153fbfec0fb9c9ce38e749a7c6f4a5e115d4e9.zip
Merging upstream version 4.4.0.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'dumpcap.c')
-rw-r--r--dumpcap.c1612
1 files changed, 830 insertions, 782 deletions
diff --git a/dumpcap.c b/dumpcap.c
index b5a5423a..1231cb1d 100644
--- a/dumpcap.c
+++ b/dumpcap.c
@@ -16,6 +16,8 @@
#include <string.h>
+#include <ws_exit_codes.h>
+
#include <sys/types.h>
#ifdef HAVE_NETINET_IN_H
@@ -31,6 +33,7 @@
#include <signal.h>
#include <errno.h>
+#include <wsutil/array.h>
#include <wsutil/cmdarg_err.h>
#include <wsutil/strtoi.h>
#include <cli_main.h>
@@ -78,6 +81,7 @@
#include "wsutil/time_util.h"
#include "wsutil/please_report_bug.h"
#include "wsutil/glib-compat.h"
+#include <wsutil/json_dumper.h>
#include <wsutil/ws_assert.h>
#include "capture/ws80211_utils.h"
@@ -94,12 +98,14 @@
#include "wiretap/pcapng.h"
/*
- * Define these for extra logging messages at INFO and below. Note
- * that when dumpcap is spawned as a child process, logs are sent
- * to the parent via the sync pipe.
+ * Define these for extra logging. Note that when dumpcap is spawned as
+ * a child process, logs are sent to the parent via the sync pipe.
+ * The parent will pass along the Capchild domain log level settings,
+ * so "--log-debug Capchild" or "--log-level debug" can be used to get
+ * debugging from dumpcap sent to the parent.
*/
-/**#define DEBUG_DUMPCAP**/ /* Logs INFO and below messages normally */
-/**#define DEBUG_CHILD_DUMPCAP**/ /* Writes INFO and below logs to file */
+//#define DEBUG_DUMPCAP /* Waits for keypress on quitting on Windows */
+//#define DEBUG_CHILD_DUMPCAP /* Writes logs to file */
#ifdef _WIN32
#include "wsutil/win32-utils.h"
@@ -112,24 +118,23 @@
FILE *debug_log; /* for logging debug messages to */
/* a file if DEBUG_CHILD_DUMPCAP */
/* is defined */
-#ifdef DEBUG_DUMPCAP
#include <stdarg.h> /* va_copy */
#endif
-#endif
static GAsyncQueue *pcap_queue;
-static gint64 pcap_queue_bytes;
-static gint64 pcap_queue_packets;
-static gint64 pcap_queue_byte_limit = 0;
-static gint64 pcap_queue_packet_limit = 0;
+static int64_t pcap_queue_bytes;
+static int64_t pcap_queue_packets;
+static int64_t pcap_queue_byte_limit;
+static int64_t pcap_queue_packet_limit;
-static gboolean capture_child = FALSE; /* FALSE: standalone call, TRUE: this is an Wireshark capture child */
-static const char *report_capture_filename = NULL; /* capture child file name */
+static bool capture_child; /* false: standalone call, true: this is an Wireshark capture child */
+static const char *report_capture_filename; /* capture child file name */
#ifdef _WIN32
-static gchar *sig_pipe_name = NULL;
-static HANDLE sig_pipe_handle = NULL;
-static gboolean signal_pipe_check_running(void);
+static char *sig_pipe_name;
+static HANDLE sig_pipe_handle;
+static bool signal_pipe_check_running(void);
#endif
+static int sync_pipe_fd = 2;
#ifdef ENABLE_ASAN
/* This has public visibility so that if compiled with shared libasan (the
@@ -208,14 +213,14 @@ __asan_default_options(void)
#endif
#ifdef SIGINFO
-static gboolean infodelay; /* if TRUE, don't print capture info in SIGINFO handler */
-static gboolean infoprint; /* if TRUE, print capture info after clearing infodelay */
+static bool infodelay; /* if true, don't print capture info in SIGINFO handler */
+static bool infoprint; /* if true, print capture info after clearing infodelay */
#endif /* SIGINFO */
/** Stop a low-level capture (stops the capture child). */
static void capture_loop_stop(void);
-/** Close a pipe, or socket if \a from_socket is TRUE */
-static void cap_pipe_close(int pipe_fd, gboolean from_socket);
+/** Close a pipe, or socket if \a from_socket is true */
+static void cap_pipe_close(int pipe_fd, bool from_socket);
#if defined (__linux__)
/* whatever the deal with pcap_breakloop, linux doesn't support timeouts
@@ -251,7 +256,7 @@ typedef enum {
} cap_pipe_err_t;
typedef struct _pcap_pipe_info {
- gboolean byte_swapped; /**< TRUE if data in the pipe is byte swapped. */
+ bool byte_swapped; /**< true if data in the pipe is byte swapped. */
struct pcap_hdr hdr; /**< Pcap header when capturing from a pipe */
struct pcaprec_modified_hdr rechdr; /**< Pcap record header when capturing from a pipe */
} pcap_pipe_info_t;
@@ -267,24 +272,24 @@ struct _loop_data; /* forward declaration so we can use it in the cap_pipe_dispa
* A source of packets from which we're capturing.
*/
typedef struct _capture_src {
- guint32 received;
- guint32 dropped;
- guint32 flushed;
+ uint32_t received;
+ uint32_t dropped;
+ uint32_t flushed;
pcap_t *pcap_h;
#ifdef MUST_DO_SELECT
int pcap_fd; /**< pcap file descriptor */
#endif
- gboolean pcap_err;
- guint interface_id;
- guint idb_id; /**< If from_pcapng is false, the output IDB interface ID. Otherwise the mapping in src_iface_to_global is used. */
+ bool pcap_err;
+ unsigned interface_id;
+ unsigned idb_id; /**< If from_pcapng is false, the output IDB interface ID. Otherwise the mapping in src_iface_to_global is used. */
GThread *tid;
int snaplen;
int linktype;
- gboolean ts_nsec; /**< TRUE if we're using nanosecond precision. */
+ bool ts_nsec; /**< true if we're using nanosecond precision. */
/**< capture pipe (unix only "input file") */
- gboolean from_cap_pipe; /**< TRUE if we are capturing data from a capture pipe */
- gboolean from_cap_socket; /**< TRUE if we're capturing from socket */
- gboolean from_pcapng; /**< TRUE if we're capturing from pcapng format */
+ bool from_cap_pipe; /**< true if we are capturing data from a capture pipe */
+ bool from_cap_socket; /**< true if we're capturing from socket */
+ bool from_pcapng; /**< true if we're capturing from pcapng format */
union {
pcap_pipe_info_t pcap; /**< Pcap info when capturing from a pipe */
pcapng_pipe_info_t pcapng; /**< Pcapng info when capturing from a pipe */
@@ -293,10 +298,10 @@ typedef struct _capture_src {
HANDLE cap_pipe_h; /**< The handle of the capture pipe */
#endif
int cap_pipe_fd; /**< the file descriptor of the capture pipe */
- gboolean cap_pipe_modified; /**< TRUE if data in the pipe uses modified pcap headers */
+ bool cap_pipe_modified; /**< true if data in the pipe uses modified pcap headers */
char * cap_pipe_databuf; /**< Pointer to the data buffer we've allocated */
size_t cap_pipe_databuf_size; /**< Current size of the data buffer */
- guint cap_pipe_max_pkt_size; /**< Maximum packet size allowed */
+ unsigned cap_pipe_max_pkt_size; /**< Maximum packet size allowed */
#if defined(_WIN32)
char * cap_pipe_buf; /**< Pointer to the buffer we read into */
DWORD cap_pipe_bytes_to_read; /**< Used by cap_pipe_dispatch */
@@ -316,10 +321,10 @@ typedef struct _capture_src {
} capture_src;
typedef struct _saved_idb {
- gboolean deleted;
- guint interface_id; /* capture_src->interface_id for the associated SHB */
- guint8 *idb; /* If non-NULL, IDB read from capture_src. This is an interface specified on the command line otherwise. */
- guint idb_len;
+ bool deleted;
+ unsigned interface_id; /* capture_src->interface_id for the associated SHB */
+ uint8_t *idb; /* If non-NULL, IDB read from capture_src. This is an interface specified on the command line otherwise. */
+ unsigned idb_len;
} saved_idb_t;
/*
@@ -327,23 +332,23 @@ typedef struct _saved_idb {
*/
typedef struct _loop_data {
/* common */
- gboolean go; /**< TRUE as long as we're supposed to keep capturing */
+ bool go; /**< true as long as we're supposed to keep capturing */
int err; /**< if non-zero, error seen while capturing */
- gint packets_captured; /**< Number of packets we have already captured */
- guint inpkts_to_sync_pipe; /**< Packets not already send out to the sync_pipe */
+ int packets_captured; /**< Number of packets we have already captured */
+ unsigned inpkts_to_sync_pipe; /**< Packets not already send out to the sync_pipe */
#ifdef SIGINFO
- gboolean report_packet_count; /**< Set by SIGINFO handler; print packet count */
+ bool report_packet_count; /**< Set by SIGINFO handler; print packet count */
#endif
GArray *pcaps; /**< Array of capture_src's on which we're capturing */
- gboolean pcapng_passthrough; /**< We have one source and it's pcapng. Pass its SHB and IDBs through. */
- guint8 *saved_shb; /**< SHB to write when we have one pcapng input */
+ bool pcapng_passthrough; /**< We have one source and it's pcapng. Pass its SHB and IDBs through. */
+ uint8_t *saved_shb; /**< SHB to write when we have one pcapng input */
GArray *saved_idbs; /**< Array of saved_idb_t, written when we have a new section or output file. */
GRWLock saved_shb_idb_lock; /**< Saved IDB RW mutex */
/* output file(s) */
FILE *pdh;
int save_file_fd;
char *io_buffer; /**< Our IO buffer if we increase the size from the standard size */
- guint64 bytes_written; /**< Bytes written for the current file. */
+ uint64_t bytes_written; /**< Bytes written for the current file. */
/* autostop conditions */
int packets_written; /**< Packets written for the current file. */
int file_count;
@@ -359,7 +364,7 @@ typedef struct _pcap_queue_element {
struct pcap_pkthdr phdr;
pcapng_block_header_t bh;
} u;
- u_char *pd;
+ uint8_t *pd;
} pcap_queue_element;
/*
@@ -377,7 +382,7 @@ static loop_data global_ld;
* fixed in 10.6.2, re-broken in 10.6.3, and again fixed in 10.6.5.
*/
#if defined(__APPLE__) && defined(__LP64__)
-static gboolean need_timeout_workaround;
+static bool need_timeout_workaround;
#define CAP_READ_TIMEOUT (need_timeout_workaround ? 1000 : 250)
#else
@@ -412,30 +417,31 @@ dumpcap_log_writer(const char *domain, enum ws_log_level level,
/* capture related options */
static capture_options global_capture_opts;
-static GPtrArray *capture_comments = NULL;
-static gboolean quiet = FALSE;
-static gboolean use_threads = FALSE;
-static guint64 start_time;
-
-static void capture_loop_write_packet_cb(u_char *pcap_src_p, const struct pcap_pkthdr *phdr,
- const u_char *pd);
-static void capture_loop_queue_packet_cb(u_char *pcap_src_p, const struct pcap_pkthdr *phdr,
- const u_char *pd);
-static void capture_loop_write_pcapng_cb(capture_src *pcap_src, const pcapng_block_header_t *bh, u_char *pd);
-static void capture_loop_queue_pcapng_cb(capture_src *pcap_src, const pcapng_block_header_t *bh, u_char *pd);
+static GPtrArray *capture_comments;
+static bool quiet;
+static bool really_quiet;
+static bool use_threads;
+static uint64_t start_time;
+
+static void capture_loop_write_packet_cb(uint8_t *pcap_src_p, const struct pcap_pkthdr *phdr,
+ const uint8_t *pd);
+static void capture_loop_queue_packet_cb(uint8_t *pcap_src_p, const struct pcap_pkthdr *phdr,
+ const uint8_t *pd);
+static void capture_loop_write_pcapng_cb(capture_src *pcap_src, const pcapng_block_header_t *bh, uint8_t *pd);
+static void capture_loop_queue_pcapng_cb(capture_src *pcap_src, const pcapng_block_header_t *bh, uint8_t *pd);
static void capture_loop_get_errmsg(char *errmsg, size_t errmsglen,
char *secondary_errmsg,
size_t secondary_errmsglen,
const char *fname, int err,
- gboolean is_close);
+ bool is_close);
WS_NORETURN static void exit_main(int err);
static void report_new_capture_file(const char *filename);
static void report_packet_count(unsigned int packet_count);
-static void report_packet_drops(guint32 received, guint32 pcap_drops, guint32 drops, guint32 flushed, guint32 ps_ifdrop, gchar *name);
+static void report_packet_drops(uint32_t received, uint32_t pcap_drops, uint32_t drops, uint32_t flushed, uint32_t ps_ifdrop, char *name);
static void report_capture_error(const char *error_msg, const char *secondary_error_msg);
-static void report_cfilter_error(capture_options *capture_opts, guint i, const char *errmsg);
+static void report_cfilter_error(capture_options *capture_opts, unsigned i, const char *errmsg);
#define MSG_MAX_LENGTH 4096
@@ -447,8 +453,12 @@ print_usage(FILE *output)
fprintf(output, "Capture interface:\n");
fprintf(output, " -i <interface>, --interface <interface>\n");
fprintf(output, " name or idx of interface (def: first non-loopback),\n"
+#ifdef HAVE_PCAP_REMOTE
" or for remote capturing, use one of these formats:\n"
" rpcap://<host>/<interface>\n"
+#else
+ " or for remote capturing, use this format:\n"
+#endif
" TCP@<host>:<port>\n");
fprintf(output, " --ifname <name> name to use in the capture file for a pipe from which\n");
fprintf(output, " we're capturing\n");
@@ -559,10 +569,10 @@ static void
dumpcap_cmdarg_err(const char *fmt, va_list ap)
{
if (capture_child) {
- gchar *msg;
+ char *msg;
/* Generate a 'special format' message back to parent */
msg = ws_strdup_vprintf(fmt, ap);
- sync_pipe_write_errmsgs_to_parent(2, msg, "");
+ sync_pipe_write_errmsgs_to_parent(sync_pipe_fd, msg, "");
g_free(msg);
} else {
fprintf(stderr, "dumpcap: ");
@@ -580,9 +590,9 @@ static void
dumpcap_cmdarg_err_cont(const char *fmt, va_list ap)
{
if (capture_child) {
- gchar *msg;
+ char *msg;
msg = ws_strdup_vprintf(fmt, ap);
- sync_pipe_write_errmsgs_to_parent(2, msg, "");
+ sync_pipe_write_errmsgs_to_parent(sync_pipe_fd, msg, "");
g_free(msg);
} else {
vfprintf(stderr, fmt, ap);
@@ -592,20 +602,19 @@ dumpcap_cmdarg_err_cont(const char *fmt, va_list ap)
#ifdef HAVE_LIBCAP
static void
-#if 0 /* Set to enable capability debugging */
/* see 'man cap_to_text()' for explanation of output */
/* '=' means 'all= ' ie: no capabilities */
/* '=ip' means 'all=ip' ie: all capabilities are permissible and inheritable */
/* .... */
print_caps(const char *pfx) {
- cap_t caps = cap_get_proc();
- ws_debug("%s: EUID: %d Capabilities: %s", pfx, geteuid(), cap_to_text(caps, NULL));
- cap_free(caps);
-}
-#else
-print_caps(const char *pfx _U_) {
+ if (ws_log_msg_is_active(WS_LOG_DOMAIN, LOG_LEVEL_NOISY)) {
+ cap_t caps = cap_get_proc();
+ char *caps_text = cap_to_text(caps, NULL);
+ ws_noisy("%s: EUID: %d Capabilities: %s", pfx, geteuid(), caps_text);
+ cap_free(caps_text);
+ cap_free(caps);
+ }
}
-#endif
static void
relinquish_all_capabilities(void)
@@ -622,239 +631,6 @@ relinquish_all_capabilities(void)
}
#endif
-/*
- * Platform-dependent suggestions for fixing permissions.
- */
-
-#ifdef HAVE_LIBCAP
- #define LIBCAP_PERMISSIONS_SUGGESTION \
- "\n\n" \
- "If you did not install Wireshark from a package, ensure that Dumpcap " \
- "has the needed CAP_NET_RAW and CAP_NET_ADMIN capabilities by running " \
- "\n\n" \
- " sudo setcap cap_net_raw,cap_net_admin=ep {path/to/}dumpcap" \
- "\n\n" \
- "and then restarting Wireshark."
-#else
- #define LIBCAP_PERMISSIONS_SUGGESTION
-#endif
-
-#if defined(__linux__)
- #define PLATFORM_PERMISSIONS_SUGGESTION \
- "\n\n" \
- "On Debian and Debian derivatives such as Ubuntu, if you have " \
- "installed Wireshark from a package, try running" \
- "\n\n" \
- " sudo dpkg-reconfigure wireshark-common" \
- "\n\n" \
- "selecting \"<Yes>\" in response to the question" \
- "\n\n" \
- " Should non-superusers be able to capture packets?" \
- "\n\n" \
- "adding yourself to the \"wireshark\" group by running" \
- "\n\n" \
- " sudo usermod -a -G wireshark {your username}" \
- "\n\n" \
- "and then logging out and logging back in again." \
- LIBCAP_PERMISSIONS_SUGGESTION
-#elif defined(__APPLE__)
- #define PLATFORM_PERMISSIONS_SUGGESTION \
- "\n\n" \
- "If you installed Wireshark using the package from wireshark.org, " \
- "close this dialog and click on the \"installing ChmodBPF\" link in " \
- "\"You can fix this by installing ChmodBPF.\" on the main screen, " \
- "and then complete the installation procedure."
-#else
- #define PLATFORM_PERMISSIONS_SUGGESTION
-#endif
-
-#if defined(_WIN32)
-static const char *
-get_platform_pcap_failure_secondary_error_message(const char *open_status_str)
-{
- /*
- * The error string begins with the error produced by WinPcap
- * and Npcap if attempting to set promiscuous mode fails.
- * (Note that this string could have a specific error message
- * from an NDIS error after the initial part, so we do a prefix
- * check rather than an exact match check.)
- *
- * If this is with Npcap 1.71 through 1.73, which have bugs that
- * cause this error on Windows 11 with some drivers, suggest that
- * the user upgrade to the current version of Npcap;
- * otherwise, suggest that they turn off promiscuous mode
- * on that device.
- */
- static const char promisc_failed[] =
- "failed to set hardware filter to promiscuous mode";
-
- if (strncmp(open_status_str, promisc_failed, sizeof promisc_failed - 1) == 0) {
- unsigned int npcap_major, npcap_minor;
-
- if (caplibs_get_npcap_version(&npcap_major, &npcap_minor)) {
- if (npcap_major == 1 &&
- (npcap_minor >= 71 && npcap_minor <= 73)) {
- return
-"This is a bug in your version of Npcap.\n"
-"\n"
-"If you need to use promiscuous mode, you must upgrade to the current "
-"version of Npcap, which is available from https://npcap.com/\n"
-"\n"
-"Otherwise, turn off promiscuous mode for this device.";
- }
- }
- return
- "Please turn off promiscuous mode for this device.";
- }
- return NULL;
-}
-#elif defined(__linux__)
-static const char *
-get_platform_pcap_failure_secondary_error_message(const char *open_status_str)
-{
- /*
- * The error string is the message provided by libpcap on
- * Linux if an attempt to open a PF_PACKET socket failed
- * with EAFNOSUPPORT. This probably means that either 1)
- * the kernel doesn't have PF_PACKET support configured in
- * or 2) this is a Flatpak version of Wireshark that's been
- * sandboxed in a way that disallows opening PF_PACKET
- * sockets.
- *
- * Suggest that the user find some other package of
- * Wireshark if they want to capture traffic and are
- * running a Flatpak of Wireshark or that they configure
- * PF_PACKET support back in if it's configured out.
- */
- static const char af_notsup[] =
- "socket: Address family not supported by protocol";
-
- if (strcmp(open_status_str, af_notsup) == 0) {
- return
- "If you are running Wireshark from a Flatpak package, "
- "it does not support packet capture; you will need "
- "to run a different version of Wireshark in order "
- "to capture traffic.\n"
- "\n"
- "Otherwise, if your machine is running a kernel that "
- "was not configured with CONFIG_PACKET, that kernel "
- "does not support packet capture; you will need to "
- "use a kernel configured with CONFIG_PACKET.";
- }
- return NULL;
-}
-#else
-static const char *
-get_platform_pcap_failure_secondary_error_message(const char *open_status_str _U_)
-{
- /* No such message for platforms not handled above. */
- return NULL;
-}
-#endif
-
-static const char *
-get_pcap_failure_secondary_error_message(cap_device_open_status open_status,
- const char *open_status_str)
-{
- const char *platform_secondary_error_message;
-
-#ifdef _WIN32
- /*
- * On Windows, first make sure they *have* Npcap installed.
- */
- if (!has_wpcap) {
- return
- "In order to capture packets, Npcap or WinPcap must be installed. See\n"
- "\n"
- " https://npcap.com/\n"
- "\n"
- "for a downloadable version of Npcap and for instructions on how to\n"
- "install it.";
- }
-#endif
-
- /*
- * OK, now just return a largely platform-independent error that might
- * have platform-specific suggestions at the end (for example, suggestions
- * for how to get permission to capture).
- */
- switch (open_status) {
-
- case CAP_DEVICE_OPEN_NO_ERR:
- case CAP_DEVICE_OPEN_WARNING_PROMISC_NOTSUP:
- case CAP_DEVICE_OPEN_WARNING_TSTAMP_TYPE_NOTSUP:
- case CAP_DEVICE_OPEN_WARNING_OTHER:
- /* This should not happen, as those aren't errors. */
- return "";
-
- case CAP_DEVICE_OPEN_ERROR_NO_SUCH_DEVICE:
- case CAP_DEVICE_OPEN_ERROR_RFMON_NOTSUP:
- case CAP_DEVICE_OPEN_ERROR_IFACE_NOT_UP:
- /*
- * Not clear what suggestions to make for these cases.
- */
- return "";
-
- case CAP_DEVICE_OPEN_ERROR_PERM_DENIED:
- case CAP_DEVICE_OPEN_ERROR_PROMISC_PERM_DENIED:
- /*
- * This is a permissions error, so no need to specify any other
- * warnings.
- */
- return
- "Please check to make sure you have sufficient permissions."
- PLATFORM_PERMISSIONS_SUGGESTION;
- break;
-
- case CAP_DEVICE_OPEN_ERROR_OTHER:
- case CAP_DEVICE_OPEN_ERROR_GENERIC:
- /*
- * We don't know what kind of error it is. See if there's a hint
- * in the error string; if not, throw all generic suggestions at
- * the user.
- *
- * First, check for some text that pops up in some errors.
- * Do platform-specific checks first.
- */
- platform_secondary_error_message =
- get_platform_pcap_failure_secondary_error_message(open_status_str);
- if (platform_secondary_error_message != NULL) {
- /* We got one, so return it. */
- return platform_secondary_error_message;
- }
-
- /*
- * Not one of those particular problems. Was this a "generic"
- * error from pcap_open_live() or pcap_open(), in which case
- * it might be a permissions error?
- */
- if (open_status == CAP_DEVICE_OPEN_ERROR_GENERIC) {
- /* Yes. */
- return
- "Please check to make sure you have sufficient permissions, and that you have "
- "the proper interface or pipe specified."
- PLATFORM_PERMISSIONS_SUGGESTION;
- } else {
- /*
- * This is not a permissions error, so no need to suggest
- * checking permissions.
- */
- return
- "Please check that you have the proper interface or pipe specified.";
- }
- break;
-
- default:
- /*
- * This is not a permissions error, so no need to suggest
- * checking permissions.
- */
- return
- "Please check that you have the proper interface or pipe specified.";
- break;
- }
-}
-
static void
get_capture_device_open_failure_messages(cap_device_open_status open_status,
const char *open_status_str,
@@ -906,12 +682,12 @@ get_capture_device_open_failure_messages(cap_device_open_status open_status,
get_pcap_failure_secondary_error_message(open_status, open_status_str));
}
-static gboolean
+static bool
compile_capture_filter(const char *iface, pcap_t *pcap_h,
struct bpf_program *fcode, const char *cfilter)
{
bpf_u_int32 netnum, netmask;
- gchar lookup_net_err_str[PCAP_ERRBUF_SIZE];
+ char lookup_net_err_str[PCAP_ERRBUF_SIZE];
if (pcap_lookupnet(iface, &netnum, &netmask, lookup_net_err_str) < 0) {
/*
@@ -935,24 +711,24 @@ compile_capture_filter(const char *iface, pcap_t *pcap_h,
*/
DIAG_OFF(cast-qual)
if (pcap_compile(pcap_h, fcode, (char *)cfilter, 1, netmask) < 0)
- return FALSE;
+ return false;
DIAG_ON(cast-qual)
- return TRUE;
+ return true;
}
-static gboolean
+static bool
show_filter_code(capture_options *capture_opts)
{
interface_options *interface_opts;
pcap_t *pcap_h;
cap_device_open_status open_status;
- gchar open_status_str[PCAP_ERRBUF_SIZE];
+ char open_status_str[PCAP_ERRBUF_SIZE];
char errmsg[MSG_MAX_LENGTH+1];
char secondary_errmsg[MSG_MAX_LENGTH+1];
struct bpf_program fcode;
struct bpf_insn *insn;
u_int i;
- guint j;
+ unsigned j;
for (j = 0; j < capture_opts->ifaces->len; j++) {
interface_opts = &g_array_index(capture_opts->ifaces, interface_options, j);
@@ -967,7 +743,7 @@ show_filter_code(capture_options *capture_opts)
sizeof secondary_errmsg);
/* And report them */
report_capture_error(errmsg, secondary_errmsg);
- return FALSE;
+ return false;
}
/* Set the link-layer type. */
@@ -976,7 +752,7 @@ show_filter_code(capture_options *capture_opts)
secondary_errmsg, sizeof secondary_errmsg)) {
pcap_close(pcap_h);
report_capture_error(errmsg, secondary_errmsg);
- return FALSE;
+ return false;
}
/* OK, try to compile the capture filter. */
@@ -985,7 +761,7 @@ show_filter_code(capture_options *capture_opts)
snprintf(errmsg, sizeof(errmsg), "%s", pcap_geterr(pcap_h));
pcap_close(pcap_h);
report_cfilter_error(capture_opts, j, errmsg);
- return FALSE;
+ return false;
}
pcap_close(pcap_h);
@@ -1007,81 +783,116 @@ show_filter_code(capture_options *capture_opts)
#endif
if (capture_child) {
/* Let our parent know we succeeded. */
- sync_pipe_write_string_msg(2, SP_SUCCESS, NULL);
+ sync_pipe_write_string_msg(sync_pipe_fd, SP_SUCCESS, NULL);
}
- return TRUE;
+ return true;
}
+static void
+print_machine_readable_if_capabilities(json_dumper *dumper, if_capabilities_t *caps, int queries);
+
/*
* Output a machine readable list of the interfaces
* This list is retrieved by the sync_interface_list_open() function
* The actual output of this function can be viewed with the command "dumpcap -D -Z none"
*/
-static void
-print_machine_readable_interfaces(GList *if_list)
+static int
+print_machine_readable_interfaces(GList *if_list, int caps_queries, bool print_statistics)
{
- int i;
GList *if_entry;
if_info_t *if_info;
GSList *addr;
if_addr_t *if_addr;
char addr_str[WS_INET6_ADDRSTRLEN];
+ int status;
- if (capture_child) {
- /* Let our parent know we succeeded. */
- sync_pipe_write_string_msg(2, SP_SUCCESS, NULL);
- }
+ json_dumper dumper = {
+ .output_string = g_string_new(NULL),
+ .flags = JSON_DUMPER_FLAGS_NO_DEBUG,
+ // Don't abort on failure
+ };
+ json_dumper_begin_array(&dumper);
- i = 1; /* Interface id number */
+ /*
+ * Print the contents of the if_entry struct in a parseable format (JSON)
+ */
for (if_entry = g_list_first(if_list); if_entry != NULL;
if_entry = g_list_next(if_entry)) {
if_info = (if_info_t *)if_entry->data;
- printf("%d. %s\t", i++, if_info->name);
- /*
- * Print the contents of the if_entry struct in a parseable format.
- * Each if_entry element is tab-separated. Addresses are comma-
- * separated.
- */
- /* XXX - Make sure our description doesn't contain a tab */
- if (if_info->vendor_description != NULL)
- printf("%s\t", if_info->vendor_description);
- else
- printf("\t");
+ json_dumper_begin_object(&dumper);
+ json_dumper_set_member_name(&dumper, if_info->name);
- /* XXX - Make sure our friendly name doesn't contain a tab */
- if (if_info->friendly_name != NULL)
- printf("%s\t", if_info->friendly_name);
- else
- printf("\t");
+ json_dumper_begin_object(&dumper);
+
+ json_dumper_set_member_name(&dumper, "friendly_name");
+ json_dumper_value_string(&dumper, if_info->friendly_name);
+
+ json_dumper_set_member_name(&dumper, "vendor_description");
+ json_dumper_value_string(&dumper, if_info->vendor_description);
- printf("%i\t", if_info->type);
+ json_dumper_set_member_name(&dumper, "type");
+ json_dumper_value_anyf(&dumper, "%i", if_info->type);
+ json_dumper_set_member_name(&dumper, "addrs");
+
+ json_dumper_begin_array(&dumper);
for (addr = g_slist_nth(if_info->addrs, 0); addr != NULL;
addr = g_slist_next(addr)) {
- if (addr != g_slist_nth(if_info->addrs, 0))
- printf(",");
if_addr = (if_addr_t *)addr->data;
switch(if_addr->ifat_type) {
case IF_AT_IPv4:
- printf("%s", ws_inet_ntop4(&if_addr->addr.ip4_addr, addr_str, sizeof(addr_str)));
+ json_dumper_value_string(&dumper, ws_inet_ntop4(&if_addr->addr.ip4_addr, addr_str, sizeof(addr_str)));
break;
case IF_AT_IPv6:
- printf("%s", ws_inet_ntop6(&if_addr->addr.ip6_addr, addr_str, sizeof(addr_str)));
+ json_dumper_value_string(&dumper, ws_inet_ntop6(&if_addr->addr.ip6_addr, addr_str, sizeof(addr_str)));
break;
default:
- printf("<type unknown %i>", if_addr->ifat_type);
+ json_dumper_value_anyf(&dumper, "<type unknown %i>", if_addr->ifat_type);
}
}
+ json_dumper_end_array(&dumper);
- if (if_info->loopback)
- printf("\tloopback");
- else
- printf("\tnetwork");
- printf("\t%s", if_info->extcap);
- printf("\n");
+ json_dumper_set_member_name(&dumper, "loopback");
+ json_dumper_value_anyf(&dumper, "%s", if_info->loopback ? "true" : "false");
+
+ json_dumper_set_member_name(&dumper, "extcap");
+ json_dumper_value_string(&dumper, if_info->extcap);
+
+ if (if_info->caps && caps_queries) {
+ json_dumper_set_member_name(&dumper, "caps");
+ json_dumper_begin_object(&dumper);
+ print_machine_readable_if_capabilities(&dumper, if_info->caps, caps_queries);
+ json_dumper_end_object(&dumper);
+ }
+ json_dumper_end_object(&dumper);
+ json_dumper_end_object(&dumper);
+ }
+ json_dumper_end_array(&dumper);
+ if (json_dumper_finish(&dumper)) {
+ status = 0;
+ if (capture_child) {
+ if (print_statistics) {
+ sync_pipe_write_string_msg(sync_pipe_fd, SP_IFACE_LIST, dumper.output_string->str);
+ } else {
+ /* Let our parent know we succeeded. */
+ sync_pipe_write_string_msg(sync_pipe_fd, SP_SUCCESS, NULL);
+ printf("%s", dumper.output_string->str);
+ }
+ } else {
+ printf("%s", dumper.output_string->str);
+ }
+ } else {
+ status = 2;
+ if (capture_child) {
+ sync_pipe_write_errmsgs_to_parent(sync_pipe_fd, "Unexpected JSON error", "");
+ } else {
+ cmdarg_err("Unexpected JSON error");
+ }
}
+ g_string_free(dumper.output_string, TRUE);
+ return status;
}
/*
@@ -1089,21 +900,23 @@ print_machine_readable_interfaces(GList *if_list)
* you MUST update capture_ifinfo.c:capture_get_if_capabilities() accordingly!
*/
static void
-print_machine_readable_if_capabilities(if_capabilities_t *caps, int queries)
+print_machine_readable_if_capabilities(json_dumper *dumper, if_capabilities_t *caps, int queries)
{
GList *lt_entry, *ts_entry;
- const gchar *desc_str;
+ const char *desc_str;
- if (capture_child) {
- /* Let our parent know we succeeded. */
- sync_pipe_write_string_msg(2, SP_SUCCESS, NULL);
+ json_dumper_set_member_name(dumper, "status");
+ json_dumper_value_anyf(dumper, "%i", caps->status);
+ if (caps->primary_msg) {
+ json_dumper_set_member_name(dumper, "primary_msg");
+ json_dumper_value_string(dumper, caps->primary_msg);
}
if (queries & CAPS_QUERY_LINK_TYPES) {
- if (caps->can_set_rfmon)
- printf("1\n");
- else
- printf("0\n");
+ json_dumper_set_member_name(dumper, "rfmon");
+ json_dumper_value_anyf(dumper, "%s", caps->can_set_rfmon ? "true" : "false");
+ json_dumper_set_member_name(dumper, "data_link_types");
+ json_dumper_begin_array(dumper);
for (lt_entry = caps->data_link_types; lt_entry != NULL;
lt_entry = g_list_next(lt_entry)) {
data_link_info_t *data_link_info = (data_link_info_t *)lt_entry->data;
@@ -1111,12 +924,40 @@ print_machine_readable_if_capabilities(if_capabilities_t *caps, int queries)
desc_str = data_link_info->description;
else
desc_str = "(not supported)";
- printf("%d\t%s\t%s\n", data_link_info->dlt, data_link_info->name,
- desc_str);
+ json_dumper_begin_object(dumper);
+ json_dumper_set_member_name(dumper, "dlt");
+ json_dumper_value_anyf(dumper, "%d", data_link_info->dlt);
+ json_dumper_set_member_name(dumper, "name");
+ json_dumper_value_string(dumper, data_link_info->name);
+ json_dumper_set_member_name(dumper, "description");
+ json_dumper_value_string(dumper, desc_str);
+ json_dumper_end_object(dumper);
}
+ json_dumper_end_array(dumper);
+
+ json_dumper_set_member_name(dumper, "data_link_types_rfmon");
+ json_dumper_begin_array(dumper);
+ for (lt_entry = caps->data_link_types_rfmon; lt_entry != NULL;
+ lt_entry = g_list_next(lt_entry)) {
+ data_link_info_t *data_link_info = (data_link_info_t *)lt_entry->data;
+ if (data_link_info->description != NULL)
+ desc_str = data_link_info->description;
+ else
+ desc_str = "(not supported)";
+ json_dumper_begin_object(dumper);
+ json_dumper_set_member_name(dumper, "dlt");
+ json_dumper_value_anyf(dumper, "%d", data_link_info->dlt);
+ json_dumper_set_member_name(dumper, "name");
+ json_dumper_value_string(dumper, data_link_info->name);
+ json_dumper_set_member_name(dumper, "description");
+ json_dumper_value_string(dumper, desc_str);
+ json_dumper_end_object(dumper);
+ }
+ json_dumper_end_array(dumper);
}
- printf("\n");
if (queries & CAPS_QUERY_TIMESTAMP_TYPES) {
+ json_dumper_set_member_name(dumper, "timestamp_types");
+ json_dumper_begin_array(dumper);
for (ts_entry = caps->timestamp_types; ts_entry != NULL;
ts_entry = g_list_next(ts_entry)) {
timestamp_info_t *timestamp = (timestamp_info_t *)ts_entry->data;
@@ -1124,8 +965,14 @@ print_machine_readable_if_capabilities(if_capabilities_t *caps, int queries)
desc_str = timestamp->description;
else
desc_str = "(none)";
- printf("%s\t%s\n", timestamp->name, desc_str);
+ json_dumper_begin_object(dumper);
+ json_dumper_set_member_name(dumper, "name");
+ json_dumper_value_string(dumper, timestamp->name);
+ json_dumper_set_member_name(dumper, "description");
+ json_dumper_value_string(dumper, desc_str);
+ json_dumper_end_object(dumper);
}
+ json_dumper_end_array(dumper);
}
}
@@ -1136,21 +983,23 @@ typedef struct {
/* Print the number of packets captured for each interface until we're killed. */
static int
-print_statistics_loop(gboolean machine_readable)
+print_statistics_loop(bool machine_readable)
{
GList *if_list, *if_entry, *stat_list = NULL, *stat_entry;
if_info_t *if_info;
if_stat_t *if_stat;
int err;
- gchar *err_str;
+ char *err_str;
pcap_t *pch;
char errbuf[PCAP_ERRBUF_SIZE];
struct pcap_stat ps;
if_list = get_interface_list(&err, &err_str);
if (if_list == NULL) {
- if (err == 0)
+ if (err == 0) {
cmdarg_err("There are no interfaces on which a capture can be done");
+ err = WS_EXIT_NO_INTERFACES;
+ }
else {
cmdarg_err("%s", err_str);
g_free(err_str);
@@ -1197,7 +1046,7 @@ print_statistics_loop(gboolean machine_readable)
if (capture_child) {
/* Let our parent know we succeeded. */
- sync_pipe_write_string_msg(2, SP_SUCCESS, NULL);
+ sync_pipe_write_string_msg(sync_pipe_fd, SP_SUCCESS, NULL);
}
if (!machine_readable) {
@@ -1205,25 +1054,26 @@ print_statistics_loop(gboolean machine_readable)
"Dropped");
}
- global_ld.go = TRUE;
+ global_ld.go = true;
while (global_ld.go) {
for (stat_entry = g_list_first(stat_list); stat_entry != NULL; stat_entry = g_list_next(stat_entry)) {
if_stat = (if_stat_t *)stat_entry->data;
- pcap_stats(if_stat->pch, &ps);
-
- if (!machine_readable) {
- printf("%-15s %10u %10u\n", if_stat->name,
- ps.ps_recv, ps.ps_drop);
- } else {
- printf("%s\t%u\t%u\n", if_stat->name,
- ps.ps_recv, ps.ps_drop);
- fflush(stdout);
+ /* XXX - what if this fails? */
+ if (pcap_stats(if_stat->pch, &ps) == 0) {
+ if (!machine_readable) {
+ printf("%-15s %10u %10u\n", if_stat->name,
+ ps.ps_recv, ps.ps_drop);
+ } else {
+ printf("%s\t%u\t%u\n", if_stat->name,
+ ps.ps_recv, ps.ps_drop);
+ fflush(stdout);
+ }
}
}
#ifdef _WIN32
/* If we have a dummy signal pipe check it */
if (!signal_pipe_check_running()) {
- global_ld.go = FALSE;
+ global_ld.go = false;
}
Sleep(1 * 1000);
#else
@@ -1270,9 +1120,9 @@ capture_cleanup_handler(DWORD dwCtrlType)
/* Keep capture running if we're a service and a user logs off */
if (capture_child || (dwCtrlType != CTRL_LOGOFF_EVENT)) {
capture_loop_stop();
- return TRUE;
+ return true;
} else {
- return FALSE;
+ return false;
}
}
#else
@@ -1289,7 +1139,7 @@ capture_cleanup_handler(int signum _U_)
static void
-report_capture_count(gboolean reportit)
+report_capture_count(bool reportit)
{
/* Don't print this if we're a capture child. */
if (!capture_child && reportit) {
@@ -1305,7 +1155,7 @@ static void
report_counts_for_siginfo(void)
{
report_capture_count(quiet);
- infoprint = FALSE; /* we just reported it */
+ infoprint = false; /* we just reported it */
}
static void
@@ -1317,7 +1167,7 @@ report_counts_siginfo(int signum _U_)
that we print counts (if we're supposed to), otherwise print
the count of packets captured (if we're supposed to). */
if (infodelay)
- infoprint = TRUE;
+ infoprint = true;
else
report_counts_for_siginfo();
errno = sav_errno;
@@ -1358,46 +1208,95 @@ exit_main(int status)
static void
relinquish_privs_except_capture(void)
{
- /* If 'started_with_special_privs' (ie: suid) then enable for
- * ourself the NET_ADMIN and NET_RAW capabilities and then
- * drop our suid privileges.
+ /*
+ * Drop any capabilities other than NET_ADMIN and NET_RAW:
*
* CAP_NET_ADMIN: Promiscuous mode and a truckload of other
* stuff we don't need (and shouldn't have).
* CAP_NET_RAW: Packet capture (raw sockets).
+ *
+ * If 'started_with_special_privs' (ie: suid) then drop our
+ * suid privileges.
*/
- if (started_with_special_privs()) {
- cap_value_t cap_list[2] = { CAP_NET_ADMIN, CAP_NET_RAW };
- int cl_len = sizeof(cap_list) / sizeof(cap_value_t);
+ cap_t current_caps = cap_get_proc();
+ print_caps("Pre set");
- cap_t caps = cap_init(); /* all capabilities initialized to off */
+ cap_t caps = cap_init(); /* all capabilities initialized to off */
- print_caps("Pre drop, pre set");
+ /*
+ * We can only set capabilities that are in the permitted set.
+ * If the real or effective user ID is 0 (root), then the file
+ * inherited and permitted sets are ignored, and our permitted
+ * set should be all ones - unless the effective ID is 0, the
+ * real ID is not zero, and the binary has file capabilities,
+ * in which case the permitted set is only that of the file.
+ * (E.g., set-user-ID-root + file capabilities.)
+ *
+ * If one or more of the euid, ruid, and saved set user ID are
+ * all zero and all change to nonzero, then all capabilities are
+ * cleared from the permitted, effective, and ambient sets.
+ * PR_SET_KEEPCAPS causes the permitted set to be retained, so
+ * we can relinquish our changed user ID.
+ *
+ * All capabilities are always cleared from the effective set
+ * when the euid is changed from 0 to nonzero.
+ *
+ * See capabilities(7).
+ */
+ if (prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0) == -1) {
+ cmdarg_err("prctl() fail return: %s", g_strerror(errno));
+ }
- if (prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0) == -1) {
- cmdarg_err("prctl() fail return: %s", g_strerror(errno));
- }
+ if (started_with_special_privs()) {
+ relinquish_special_privs_perm();
+ }
- cap_set_flag(caps, CAP_PERMITTED, cl_len, cap_list, CAP_SET);
- cap_set_flag(caps, CAP_INHERITABLE, cl_len, cap_list, CAP_SET);
+ /*
+ * If cap_set_proc() fails, it leaves the capabilities unchanged.
+ * So the only way to guarantee that we've dropped all other
+ * capabilities is to ensure that cap_set_proc() succeeds.
+ * One option might be to exit if cap_set_proc() fails - but some
+ * captures will work with CAP_NET_RAW but not CAP_NET_ADMIN.
+ */
- if (cap_set_proc(caps)) {
- cmdarg_err("cap_set_proc() fail return: %s", g_strerror(errno));
- }
- print_caps("Pre drop, post set");
+ cap_value_t cap_list[1] = { CAP_NET_ADMIN };
+ int cl_len = array_length(cap_list);
+ cap_flag_value_t value;
- relinquish_special_privs_perm();
+ cap_get_flag(current_caps, cap_list[0], CAP_PERMITTED, &value);
- print_caps("Post drop, pre set");
- cap_set_flag(caps, CAP_EFFECTIVE, cl_len, cap_list, CAP_SET);
- if (cap_set_proc(caps)) {
- cmdarg_err("cap_set_proc() fail return: %s", g_strerror(errno));
- }
- print_caps("Post drop, post set");
+ if (value != CAP_SET) {
+ // XXX - Should we warn here? Some captures will still work.
+ }
+ cap_set_flag(caps, CAP_PERMITTED, cl_len, cap_list, value);
+ // XXX - Do we really need CAP_INHERITABLE?
+ cap_set_flag(caps, CAP_INHERITABLE, cl_len, cap_list, value);
+ cap_set_flag(caps, CAP_EFFECTIVE, cl_len, cap_list, value);
- cap_free(caps);
+ cap_list[0] = CAP_NET_RAW;
+ cap_get_flag(current_caps, cap_list[0], CAP_PERMITTED, &value);
+
+ if (value != CAP_SET) {
+ // XXX - Should we warn here?
}
+ cap_set_flag(caps, CAP_PERMITTED, cl_len, cap_list, value);
+ // XXX - Do we really need CAP_INHERITABLE?
+ cap_set_flag(caps, CAP_INHERITABLE, cl_len, cap_list, value);
+ cap_set_flag(caps, CAP_EFFECTIVE, cl_len, cap_list, value);
+
+ if (cap_set_proc(caps)) {
+ /*
+ * This shouldn't happen, we're only trying to set capabilities
+ * already in the permitted set.
+ */
+ cmdarg_err("cap_set_proc() fail return: %s", g_strerror(errno));
+ }
+
+ print_caps("Post set");
+
+ cap_free(current_caps);
+ cap_free(caps);
}
#endif /* HAVE_LIBCAP */
@@ -1561,7 +1460,7 @@ dlt_to_linktype(int dlt)
/* Take care of byte order in the libpcap headers read from pipes.
* (function taken from wiretap/libpcap.c) */
static void
-cap_pipe_adjust_pcap_header(gboolean byte_swapped, struct pcap_hdr *hdr, struct pcaprec_hdr *rechdr)
+cap_pipe_adjust_pcap_header(bool byte_swapped, struct pcap_hdr *hdr, struct pcaprec_hdr *rechdr)
{
if (byte_swapped) {
/* Byte-swap the record header fields. */
@@ -1581,7 +1480,7 @@ cap_pipe_adjust_pcap_header(gboolean byte_swapped, struct pcap_hdr *hdr, struct
if (hdr->version_major == 2 &&
(hdr->version_minor < 3 ||
(hdr->version_minor == 3 && rechdr->incl_len > rechdr->orig_len))) {
- guint32 temp;
+ uint32_t temp;
temp = rechdr->orig_len;
rechdr->orig_len = rechdr->incl_len;
@@ -1593,7 +1492,7 @@ cap_pipe_adjust_pcap_header(gboolean byte_swapped, struct pcap_hdr *hdr, struct
* or just read().
*/
static ssize_t
-cap_pipe_read(int pipe_fd, char *buf, size_t sz, gboolean from_socket _U_)
+cap_pipe_read(int pipe_fd, char *buf, size_t sz, bool from_socket _U_)
{
#ifdef _WIN32
if (from_socket) {
@@ -1797,11 +1696,11 @@ cap_open_socket(char *pipename, capture_src *pcap_src, char *errmsg, size_t errm
#endif
pcap_src->cap_pipe_err = PIPERR;
- cap_pipe_close(fd, TRUE);
+ cap_pipe_close(fd, true);
return -1;
}
- pcap_src->from_cap_socket = TRUE;
+ pcap_src->from_cap_socket = true;
return fd;
}
@@ -1809,7 +1708,7 @@ cap_open_socket(char *pipename, capture_src *pcap_src, char *errmsg, size_t errm
* otherwise.
*/
static void
-cap_pipe_close(int pipe_fd, gboolean from_socket)
+cap_pipe_close(int pipe_fd, bool from_socket)
{
#ifdef _WIN32
if (from_socket) {
@@ -1931,14 +1830,13 @@ cap_pipe_open_live(char *pipename,
ws_statb64 pipe_stat;
struct sockaddr_un sa;
#else /* _WIN32 */
- char *pncopy, *pos;
- guintptr extcap_pipe_handle;
+ uintptr_t extcap_pipe_handle;
#endif
- gboolean extcap_pipe = FALSE;
+ bool extcap_pipe = false;
ssize_t b;
int fd = -1, sel_ret;
size_t bytes_read;
- guint32 magic = 0;
+ uint32_t magic = 0;
pcap_src->cap_pipe_fd = -1;
#ifdef _WIN32
pcap_src->cap_pipe_h = INVALID_HANDLE_VALUE;
@@ -1963,7 +1861,7 @@ cap_pipe_open_live(char *pipename,
} else {
#ifndef _WIN32
if ( g_strrstr(pipename, EXTCAP_PIPE_PREFIX) != NULL )
- extcap_pipe = TRUE;
+ extcap_pipe = true;
if (ws_stat64(pipename, &pipe_stat) < 0) {
if (errno == ENOENT || errno == ENOTDIR)
@@ -2058,25 +1956,12 @@ cap_pipe_open_live(char *pipename,
/* The client is already connected to extcap pipe.
* We have inherited the handle from parent process.
*/
- extcap_pipe = TRUE;
+ extcap_pipe = true;
pcap_src->cap_pipe_h = (HANDLE)extcap_pipe_handle;
}
else
{
-#define PIPE_STR "\\pipe\\"
- /* Under Windows, named pipes _must_ have the form
- * "\\<server>\pipe\<pipename>". <server> may be "." for localhost.
- */
- pncopy = g_strdup(pipename);
- 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);
-
- if (!pos) {
+ if (!win32_is_pipe_name(pipename)) {
snprintf(errmsg, errmsgl,
"The capture session could not be initiated because\n"
"\"%s\" is neither an interface nor a pipe.", pipename);
@@ -2084,7 +1969,6 @@ cap_pipe_open_live(char *pipename,
return;
}
-
/* Wait for the pipe to appear */
while (1) {
pcap_src->cap_pipe_h = CreateFile(utf_8to16(pipename), GENERIC_READ, 0, NULL,
@@ -2115,7 +1999,7 @@ cap_pipe_open_live(char *pipename,
#endif /* _WIN32 */
}
- pcap_src->from_cap_pipe = TRUE;
+ pcap_src->from_cap_pipe = true;
/*
* We start with a 2KB buffer for packet data, which should be
@@ -2205,16 +2089,16 @@ cap_pipe_open_live(char *pipename,
/* This is a pcap file.
The host that wrote it has our byte order, and was running
a program using either standard or ss990417 libpcap. */
- pcap_src->cap_pipe_info.pcap.byte_swapped = FALSE;
- pcap_src->cap_pipe_modified = FALSE;
+ pcap_src->cap_pipe_info.pcap.byte_swapped = false;
+ pcap_src->cap_pipe_modified = false;
pcap_src->ts_nsec = magic == PCAP_NSEC_MAGIC;
break;
case PCAP_MODIFIED_MAGIC:
/* This is a pcap file.
The host that wrote it has our byte order, but was running
a program using either ss990915 or ss991029 libpcap. */
- pcap_src->cap_pipe_info.pcap.byte_swapped = FALSE;
- pcap_src->cap_pipe_modified = TRUE;
+ pcap_src->cap_pipe_info.pcap.byte_swapped = false;
+ pcap_src->cap_pipe_modified = true;
break;
case PCAP_SWAPPED_MAGIC:
case PCAP_SWAPPED_NSEC_MAGIC:
@@ -2222,8 +2106,8 @@ cap_pipe_open_live(char *pipename,
The host that wrote it has a byte order opposite to ours,
and was running a program using either standard or
ss990417 libpcap. */
- pcap_src->cap_pipe_info.pcap.byte_swapped = TRUE;
- pcap_src->cap_pipe_modified = FALSE;
+ pcap_src->cap_pipe_info.pcap.byte_swapped = true;
+ pcap_src->cap_pipe_modified = false;
pcap_src->ts_nsec = magic == PCAP_SWAPPED_NSEC_MAGIC;
break;
case PCAP_SWAPPED_MODIFIED_MAGIC:
@@ -2231,15 +2115,15 @@ cap_pipe_open_live(char *pipename,
The host that wrote it out has a byte order opposite to
ours, and was running a program using either ss990915
or ss991029 libpcap. */
- pcap_src->cap_pipe_info.pcap.byte_swapped = TRUE;
- pcap_src->cap_pipe_modified = TRUE;
+ pcap_src->cap_pipe_info.pcap.byte_swapped = true;
+ pcap_src->cap_pipe_modified = true;
break;
case BLOCK_TYPE_SHB:
/* This is a pcapng file. */
- pcap_src->from_pcapng = TRUE;
+ pcap_src->from_pcapng = true;
pcap_src->cap_pipe_dispatch = pcapng_pipe_dispatch;
- pcap_src->cap_pipe_info.pcapng.src_iface_to_global = g_array_new(FALSE, FALSE, sizeof(guint32));
- global_capture_opts.use_pcapng = TRUE; /* we can only output in pcapng format */
+ pcap_src->cap_pipe_info.pcapng.src_iface_to_global = g_array_new(FALSE, FALSE, sizeof(uint32_t));
+ global_capture_opts.use_pcapng = true; /* we can only output in pcapng format */
break;
default:
/* Not a pcapng file, and either not a pcap type we know about
@@ -2508,8 +2392,8 @@ pcapng_read_shb(capture_src *pcap_src,
* fix LINKTYPE_ values that are really platform-dependent DLT_ values.
* Rewrite EPB and ISB interface IDs.
*/
-static gboolean
-pcapng_adjust_block(capture_src *pcap_src, const pcapng_block_header_t *bh, u_char *pd)
+static bool
+pcapng_adjust_block(capture_src *pcap_src, const pcapng_block_header_t *bh, uint8_t *pd)
{
switch(bh->block_type) {
case BLOCK_TYPE_SHB:
@@ -2522,7 +2406,7 @@ pcapng_adjust_block(capture_src *pcap_src, const pcapng_block_header_t *bh, u_ch
* buffer files.
*/
g_free(global_ld.saved_shb);
- global_ld.saved_shb = (guint8 *) g_memdup2(pd, bh->block_total_length);
+ global_ld.saved_shb = (uint8_t *) g_memdup2(pd, bh->block_total_length);
/*
* We're dealing with one section at a time, so we can (and must)
@@ -2540,12 +2424,12 @@ pcapng_adjust_block(capture_src *pcap_src, const pcapng_block_header_t *bh, u_ch
* collected from this source as deleted.
*/
for (unsigned i = 0; i < pcap_src->cap_pipe_info.pcapng.src_iface_to_global->len; i++) {
- guint32 iface_id = g_array_index(pcap_src->cap_pipe_info.pcapng.src_iface_to_global, guint32, i);
+ uint32_t iface_id = g_array_index(pcap_src->cap_pipe_info.pcapng.src_iface_to_global, uint32_t, i);
saved_idb_t *idb_source = &g_array_index(global_ld.saved_idbs, saved_idb_t, iface_id);
ws_assert(idb_source->interface_id == pcap_src->interface_id);
g_free(idb_source->idb);
memset(idb_source, 0, sizeof(saved_idb_t));
- idb_source->deleted = TRUE;
+ idb_source->deleted = true;
ws_debug("%s: deleted pcapng IDB %u", G_STRFUNC, iface_id);
}
}
@@ -2561,9 +2445,9 @@ pcapng_adjust_block(capture_src *pcap_src, const pcapng_block_header_t *bh, u_ch
saved_idb_t idb_source = { 0 };
idb_source.interface_id = pcap_src->interface_id;
idb_source.idb_len = bh->block_total_length;
- idb_source.idb = (guint8 *) g_memdup2(pd, idb_source.idb_len);
+ idb_source.idb = (uint8_t *) g_memdup2(pd, idb_source.idb_len);
g_array_append_val(global_ld.saved_idbs, idb_source);
- guint32 iface_id = global_ld.saved_idbs->len - 1;
+ uint32_t iface_id = global_ld.saved_idbs->len - 1;
g_array_append_val(pcap_src->cap_pipe_info.pcapng.src_iface_to_global, iface_id);
ws_debug("%s: mapped pcapng IDB %u -> %u from source %u",
G_STRFUNC, pcap_src->cap_pipe_info.pcapng.src_iface_to_global->len - 1, iface_id, pcap_src->interface_id);
@@ -2577,14 +2461,14 @@ pcapng_adjust_block(capture_src *pcap_src, const pcapng_block_header_t *bh, u_ch
break;
}
/* The interface ID is the first 32-bit field after the BH for both EPBs and ISBs. */
- guint32 iface_id;
+ uint32_t iface_id;
memcpy(&iface_id, pd + sizeof(pcapng_block_header_t), 4);
if (iface_id < pcap_src->cap_pipe_info.pcapng.src_iface_to_global->len) {
memcpy(pd + sizeof(pcapng_block_header_t),
- &g_array_index(pcap_src->cap_pipe_info.pcapng.src_iface_to_global, guint32, iface_id), 4);
+ &g_array_index(pcap_src->cap_pipe_info.pcapng.src_iface_to_global, uint32_t, iface_id), 4);
} else {
ws_debug("%s: pcapng EPB or ISB interface id %u > max %u", G_STRFUNC, iface_id, pcap_src->cap_pipe_info.pcapng.src_iface_to_global->len);
- return FALSE;
+ return false;
}
}
break;
@@ -2592,7 +2476,29 @@ pcapng_adjust_block(capture_src *pcap_src, const pcapng_block_header_t *bh, u_ch
break;
}
- return TRUE;
+ return true;
+}
+
+/*
+ * Return true if the block contains packet, event, or log data. Return false otherwise.
+ */
+static bool is_data_block(uint32_t block_type)
+{
+ // Any block types that lead to calling wtap_read_packet_bytes in
+ // wiretap/pcapng.c should be listed here.
+ switch (block_type) {
+ case BLOCK_TYPE_PB:
+ case BLOCK_TYPE_EPB:
+ case BLOCK_TYPE_SPB:
+ case BLOCK_TYPE_SYSTEMD_JOURNAL_EXPORT:
+ case BLOCK_TYPE_SYSDIG_EVENT:
+ case BLOCK_TYPE_SYSDIG_EVENT_V2:
+ case BLOCK_TYPE_SYSDIG_EVENT_V2_LARGE:
+ return true;
+ default:
+ break;
+ }
+ return false;
}
/*
@@ -2605,7 +2511,7 @@ pcapng_pipe_open_live(int fd,
char *errmsg,
size_t errmsgl)
{
- guint32 type = BLOCK_TYPE_SHB;
+ uint32_t type = BLOCK_TYPE_SHB;
pcapng_block_header_t *bh = &pcap_src->cap_pipe_info.pcapng.bh;
ws_debug("pcapng_pipe_open_live: fd %d", fd);
@@ -2627,8 +2533,8 @@ pcapng_pipe_open_live(int fd,
if (pcap_src->from_cap_socket)
#endif
{
- memcpy(pcap_src->cap_pipe_databuf, &type, sizeof(guint32));
- pcap_src->cap_pipe_bytes_read = sizeof(guint32);
+ memcpy(pcap_src->cap_pipe_databuf, &type, sizeof(uint32_t));
+ pcap_src->cap_pipe_bytes_read = sizeof(uint32_t);
pcap_src->cap_pipe_bytes_to_read = sizeof(pcapng_block_header_t);
pcap_src->cap_pipe_fd = fd;
if (cap_pipe_read_data_bytes(pcap_src, errmsg, errmsgl) < 0) {
@@ -2689,10 +2595,10 @@ pcap_pipe_dispatch(loop_data *ld, capture_src *pcap_src, char *errmsg, size_t er
enum { PD_REC_HDR_READ, PD_DATA_READ, PD_PIPE_EOF, PD_PIPE_ERR,
PD_ERR } result;
#ifdef _WIN32
- gpointer q_status;
+ void * q_status;
#endif
ssize_t b;
- guint new_bufsize;
+ unsigned new_bufsize;
pcap_pipe_info_t *pcap_info = &pcap_src->cap_pipe_info.pcap;
#ifdef LOG_CAPTURE_VERBOSE
@@ -2900,9 +2806,9 @@ pcap_pipe_dispatch(loop_data *ld, capture_src *pcap_src, char *errmsg, size_t er
phdr.len = pcap_info->rechdr.hdr.orig_len;
if (use_threads) {
- capture_loop_queue_packet_cb((u_char *)pcap_src, &phdr, pcap_src->cap_pipe_databuf);
+ capture_loop_queue_packet_cb((uint8_t *)pcap_src, &phdr, pcap_src->cap_pipe_databuf);
} else {
- capture_loop_write_packet_cb((u_char *)pcap_src, &phdr, pcap_src->cap_pipe_databuf);
+ capture_loop_write_packet_cb((uint8_t *)pcap_src, &phdr, pcap_src->cap_pipe_databuf);
}
/*
@@ -2938,9 +2844,9 @@ pcapng_pipe_dispatch(loop_data *ld, capture_src *pcap_src, char *errmsg, size_t
enum { PD_REC_HDR_READ, PD_DATA_READ, PD_PIPE_EOF, PD_PIPE_ERR,
PD_ERR } result;
#ifdef _WIN32
- gpointer q_status;
+ void * q_status;
#endif
- guint new_bufsize;
+ unsigned new_bufsize;
pcapng_block_header_t *bh = &pcap_src->cap_pipe_info.pcapng.bh;
#ifdef LOG_CAPTURE_VERBOSE
@@ -3096,15 +3002,15 @@ pcapng_pipe_dispatch(loop_data *ld, capture_src *pcap_src, char *errmsg, size_t
bh->block_total_length);
break;
}
- if (bh->block_total_length > pcap_src->cap_pipe_max_pkt_size) {
+ if (is_data_block(bh->block_type) && bh->block_total_length > pcap_src->cap_pipe_max_pkt_size) {
/*
* The record contains more data than the advertised/allowed in the
* pcapng header, do not try to read more data (do not change to
* STATE_EXPECT_DATA) as that would not fit in the buffer and
* instead stop with an error.
*/
- snprintf(errmsg, errmsgl, "Frame %u too long (%d bytes)",
- ld->packets_captured+1, bh->block_total_length);
+ snprintf(errmsg, errmsgl, "Block %u type 0x%08x too long (%d bytes)",
+ ld->packets_captured+1, bh->block_type, bh->block_total_length);
break;
}
@@ -3124,12 +3030,12 @@ pcapng_pipe_dispatch(loop_data *ld, capture_src *pcap_src, char *errmsg, size_t
new_bufsize |= new_bufsize >> 8;
new_bufsize |= new_bufsize >> 16;
new_bufsize++;
- pcap_src->cap_pipe_databuf = (guchar*)g_realloc(pcap_src->cap_pipe_databuf, new_bufsize);
+ pcap_src->cap_pipe_databuf = (unsigned char*)g_realloc(pcap_src->cap_pipe_databuf, new_bufsize);
pcap_src->cap_pipe_databuf_size = new_bufsize;
}
/* The record always has at least the block total length following the header */
- if (bh->block_total_length < sizeof(pcapng_block_header_t)+sizeof(guint32)) {
+ if (bh->block_total_length < sizeof(pcapng_block_header_t)+sizeof(uint32_t)) {
snprintf(errmsg, errmsgl,
"malformed pcapng block_total_length < minimum");
pcap_src->cap_pipe_err = PIPEOF;
@@ -3182,24 +3088,24 @@ pcapng_pipe_dispatch(loop_data *ld, capture_src *pcap_src, char *errmsg, size_t
/** Open the capture input sources; each one is either a pcap device,
* a capture pipe, or a capture socket.
- * Returns TRUE if it succeeds, FALSE otherwise. */
-static gboolean
+ * Returns true if it succeeds, false otherwise. */
+static bool
capture_loop_open_input(capture_options *capture_opts, loop_data *ld,
char *errmsg, size_t errmsg_len,
char *secondary_errmsg, size_t secondary_errmsg_len)
{
cap_device_open_status open_status;
- gchar open_status_str[PCAP_ERRBUF_SIZE];
- gchar *sync_msg_str;
+ char open_status_str[PCAP_ERRBUF_SIZE];
+ char *sync_msg_str;
interface_options *interface_opts;
capture_src *pcap_src;
- guint i;
+ unsigned i;
- if ((use_threads == FALSE) &&
+ if ((use_threads == false) &&
(capture_opts->ifaces->len > 1)) {
snprintf(errmsg, errmsg_len,
"Using threads is required for capturing on multiple interfaces.");
- return FALSE;
+ return false;
}
int pcapng_src_count = 0;
@@ -3209,7 +3115,7 @@ capture_loop_open_input(capture_options *capture_opts, loop_data *ld,
if (pcap_src == NULL) {
snprintf(errmsg, errmsg_len,
"Could not allocate memory.");
- return FALSE;
+ return false;
}
#ifdef MUST_DO_SELECT
@@ -3280,13 +3186,13 @@ capture_loop_open_input(capture_options *capture_opts, loop_data *ld,
interface_opts->name,
errmsg, errmsg_len,
secondary_errmsg, secondary_errmsg_len)) {
- return FALSE;
+ return false;
}
pcap_src->linktype = dlt_to_linktype(get_pcap_datalink(pcap_src->pcap_h, interface_opts->name));
} else {
/* We couldn't open "iface" as a network device. */
/* Try to open it as a pipe */
- gboolean pipe_err = FALSE;
+ bool pipe_err = false;
cap_pipe_open_live(interface_opts->name, pcap_src,
&pcap_src->cap_pipe_info.pcap.hdr,
errmsg, errmsg_len,
@@ -3296,12 +3202,12 @@ capture_loop_open_input(capture_options *capture_opts, loop_data *ld,
if (pcap_src->from_cap_socket) {
#endif
if (pcap_src->cap_pipe_fd == -1) {
- pipe_err = TRUE;
+ pipe_err = true;
}
#ifdef _WIN32
} else {
if (pcap_src->cap_pipe_h == INVALID_HANDLE_VALUE) {
- pipe_err = TRUE;
+ pipe_err = true;
}
}
#endif
@@ -3326,7 +3232,7 @@ capture_loop_open_input(capture_options *capture_opts, loop_data *ld,
* Else pipe (or file) does exist and cap_pipe_open_live() has
* filled in errmsg
*/
- return FALSE;
+ return false;
} else {
/*
* We tried opening as an interface, and that failed,
@@ -3381,7 +3287,7 @@ capture_loop_open_input(capture_options *capture_opts, loop_data *ld,
* Yes; pass through SHBs and IDBs from the source, rather
* than generating our own.
*/
- ld->pcapng_passthrough = TRUE;
+ ld->pcapng_passthrough = true;
g_rw_lock_writer_lock (&ld->saved_shb_idb_lock);
ws_assert(global_ld.saved_idbs->len == 0);
ws_debug("%s: Pass through SHBs and IDBs directly", G_STRFUNC);
@@ -3398,13 +3304,13 @@ capture_loop_open_input(capture_options *capture_opts, loop_data *ld,
#else
relinquish_all_capabilities();
#endif
- return TRUE;
+ return true;
}
/* close the capture input file (pcap or capture pipe) */
static void capture_loop_close_input(loop_data *ld)
{
- guint i;
+ unsigned i;
capture_src *pcap_src;
ws_debug("capture_loop_close_input");
@@ -3443,14 +3349,14 @@ static void capture_loop_close_input(loop_data *ld)
}
}
- ld->go = FALSE;
+ ld->go = false;
}
/* init the capture filter */
static initfilter_status_t
-capture_loop_init_filter(pcap_t *pcap_h, gboolean from_cap_pipe,
- const gchar * name, const gchar * cfilter)
+capture_loop_init_filter(pcap_t *pcap_h, bool from_cap_pipe,
+ const char * name, const char * cfilter)
{
struct bpf_program fcode;
@@ -3483,7 +3389,7 @@ capture_loop_init_filter(pcap_t *pcap_h, gboolean from_cap_pipe,
* Write the dumpcap pcapng SHB and IDBs if needed.
* Called from capture_loop_init_output and do_file_switch_or_stop.
*/
-static gboolean
+static bool
capture_loop_init_pcapng_output(capture_options *capture_opts, loop_data *ld,
int *err)
{
@@ -3493,10 +3399,10 @@ capture_loop_init_pcapng_output(capture_options *capture_opts, loop_data *ld,
/* We have a single pcapng capture interface and this is the first or only output file. */
ws_debug("%s: skipping dumpcap SHB and IDBs in favor of source", G_STRFUNC);
g_rw_lock_reader_unlock (&ld->saved_shb_idb_lock);
- return TRUE;
+ return true;
}
- gboolean successful = TRUE;
+ bool successful = true;
GString *os_info_str = g_string_new("");
*err = 0;
@@ -3594,18 +3500,18 @@ capture_loop_init_pcapng_output(capture_options *capture_opts, loop_data *ld,
}
/* set up to write to the already-opened capture output file/files */
-static gboolean
+static bool
capture_loop_init_output(capture_options *capture_opts, loop_data *ld, char *errmsg, int errmsg_len)
{
int err = 0;
ws_debug("capture_loop_init_output");
- if ((capture_opts->use_pcapng == FALSE) &&
+ if ((capture_opts->use_pcapng == false) &&
(capture_opts->ifaces->len > 1)) {
snprintf(errmsg, errmsg_len,
"Using PCAPNG is required for capturing on multiple interfaces. Use the -n option.");
- return FALSE;
+ return false;
}
/* Set up to write to the capture file. */
@@ -3633,7 +3539,7 @@ capture_loop_init_output(capture_options *capture_opts, loop_data *ld, char *err
}
}
if (ld->pdh) {
- gboolean successful;
+ bool successful;
if (capture_opts->use_pcapng) {
successful = capture_loop_init_pcapng_output(capture_opts, ld, &err);
} else {
@@ -3669,20 +3575,20 @@ capture_loop_init_output(capture_options *capture_opts, loop_data *ld, char *err
" saved (\"%s\") could not be opened: %s.",
capture_opts->save_file, g_strerror(err));
}
- return FALSE;
+ return false;
}
- return TRUE;
+ return true;
}
-static gboolean
+static bool
capture_loop_close_output(capture_options *capture_opts, loop_data *ld, int *err_close)
{
unsigned int i;
capture_src *pcap_src;
- guint64 end_time = create_timestamp();
- gboolean success;
+ uint64_t end_time = create_timestamp();
+ bool success;
ws_debug("capture_loop_close_output");
@@ -3693,15 +3599,15 @@ capture_loop_close_output(capture_options *capture_opts, loop_data *ld, int *err
for (i = 0; i < global_ld.pcaps->len; i++) {
pcap_src = g_array_index(global_ld.pcaps, capture_src *, i);
if (!pcap_src->from_cap_pipe) {
- guint64 isb_ifrecv, isb_ifdrop;
+ uint64_t isb_ifrecv, isb_ifdrop;
struct pcap_stat stats;
if (pcap_stats(pcap_src->pcap_h, &stats) >= 0) {
isb_ifrecv = pcap_src->received;
isb_ifdrop = stats.ps_drop + pcap_src->dropped + pcap_src->flushed;
} else {
- isb_ifrecv = G_MAXUINT64;
- isb_ifdrop = G_MAXUINT64;
+ isb_ifrecv = UINT64_MAX;
+ isb_ifdrop = UINT64_MAX;
}
pcapng_write_interface_statistics_block(ld->pdh,
i,
@@ -3719,9 +3625,9 @@ capture_loop_close_output(capture_options *capture_opts, loop_data *ld, int *err
if (err_close != NULL) {
*err_close = errno;
}
- success = FALSE;
+ success = false;
} else {
- success = TRUE;
+ success = true;
}
g_free(ld->io_buffer);
ld->io_buffer = NULL;
@@ -3745,7 +3651,7 @@ capture_loop_dispatch(loop_data *ld,
char *errmsg, int errmsg_len, capture_src *pcap_src)
{
int inpkts = 0;
- gint packet_count_before;
+ int packet_count_before;
int sel_ret;
packet_count_before = ld->packets_captured;
@@ -3763,7 +3669,7 @@ capture_loop_dispatch(loop_data *ld,
snprintf(errmsg, errmsg_len,
"Unexpected error from select: %s", g_strerror(errno));
report_capture_error(errmsg, please_report_bug());
- ld->go = FALSE;
+ ld->go = false;
}
}
#ifdef _WIN32
@@ -3820,23 +3726,23 @@ capture_loop_dispatch(loop_data *ld,
* in a batch before quitting.
*/
if (use_threads) {
- inpkts = pcap_dispatch(pcap_src->pcap_h, 1, capture_loop_queue_packet_cb, (u_char *)pcap_src);
+ inpkts = pcap_dispatch(pcap_src->pcap_h, 1, capture_loop_queue_packet_cb, (uint8_t *)pcap_src);
} else {
- inpkts = pcap_dispatch(pcap_src->pcap_h, 1, capture_loop_write_packet_cb, (u_char *)pcap_src);
+ inpkts = pcap_dispatch(pcap_src->pcap_h, 1, capture_loop_write_packet_cb, (uint8_t *)pcap_src);
}
if (inpkts < 0) {
if (inpkts == -1) {
/* Error, rather than pcap_breakloop(). */
- pcap_src->pcap_err = TRUE;
+ pcap_src->pcap_err = true;
}
- ld->go = FALSE; /* error or pcap_breakloop() - stop capturing */
+ ld->go = false; /* error or pcap_breakloop() - stop capturing */
}
} else {
if (sel_ret < 0 && errno != EINTR) {
snprintf(errmsg, errmsg_len,
"Unexpected error from select: %s", g_strerror(errno));
report_capture_error(errmsg, please_report_bug());
- ld->go = FALSE;
+ ld->go = false;
}
}
}
@@ -3856,23 +3762,23 @@ capture_loop_dispatch(loop_data *ld,
* at a time, so that we can check the pipe after every packet.
*/
if (use_threads) {
- inpkts = pcap_dispatch(pcap_src->pcap_h, 1, capture_loop_queue_packet_cb, (u_char *)pcap_src);
+ inpkts = pcap_dispatch(pcap_src->pcap_h, 1, capture_loop_queue_packet_cb, (uint8_t *)pcap_src);
} else {
- inpkts = pcap_dispatch(pcap_src->pcap_h, 1, capture_loop_write_packet_cb, (u_char *)pcap_src);
+ inpkts = pcap_dispatch(pcap_src->pcap_h, 1, capture_loop_write_packet_cb, (uint8_t *)pcap_src);
}
#else
if (use_threads) {
- inpkts = pcap_dispatch(pcap_src->pcap_h, -1, capture_loop_queue_packet_cb, (u_char *)pcap_src);
+ inpkts = pcap_dispatch(pcap_src->pcap_h, -1, capture_loop_queue_packet_cb, (uint8_t *)pcap_src);
} else {
- inpkts = pcap_dispatch(pcap_src->pcap_h, -1, capture_loop_write_packet_cb, (u_char *)pcap_src);
+ inpkts = pcap_dispatch(pcap_src->pcap_h, -1, capture_loop_write_packet_cb, (uint8_t *)pcap_src);
}
#endif
if (inpkts < 0) {
if (inpkts == -1) {
/* Error, rather than pcap_breakloop(). */
- pcap_src->pcap_err = TRUE;
+ pcap_src->pcap_err = true;
}
- ld->go = FALSE; /* error or pcap_breakloop() - stop capturing */
+ ld->go = false; /* error or pcap_breakloop() - stop capturing */
}
#else /* pcap_next_ex */
#ifdef LOG_CAPTURE_VERBOSE
@@ -3893,21 +3799,21 @@ capture_loop_dispatch(loop_data *ld,
{
int in;
struct pcap_pkthdr *pkt_header;
- u_char *pkt_data;
+ uint8_t *pkt_data;
in = 0;
while(ld->go &&
(in = pcap_next_ex(pcap_src->pcap_h, &pkt_header, &pkt_data)) == 1) {
if (use_threads) {
- capture_loop_queue_packet_cb((u_char *)pcap_src, pkt_header, pkt_data);
+ capture_loop_queue_packet_cb((uint8_t *)pcap_src, pkt_header, pkt_data);
} else {
- capture_loop_write_packet_cb((u_char *)pcap_src, pkt_header, pkt_data);
+ capture_loop_write_packet_cb((uint8_t *)pcap_src, pkt_header, pkt_data);
}
}
if (in < 0) {
- pcap_src->pcap_err = TRUE;
- ld->go = FALSE;
+ pcap_src->pcap_err = true;
+ ld->go = false;
}
}
#endif /* pcap_next_ex */
@@ -3929,7 +3835,7 @@ capture_loop_dispatch(loop_data *ld,
static GString *
isolate_uuid(const char *iface)
{
- gchar *ptr;
+ char *ptr;
GString *gstr;
ptr = strchr(iface, '{');
@@ -3947,14 +3853,14 @@ isolate_uuid(const char *iface)
#endif
/* open the output file (temporary/specified name/ringbuffer/named pipe/stdout) */
-/* Returns TRUE if the file opened successfully, FALSE otherwise. */
-static gboolean
+/* Returns true if the file opened successfully, false otherwise. */
+static bool
capture_loop_open_output(capture_options *capture_opts, int *save_file_fd,
char *errmsg, int errmsg_len)
{
- gchar *capfile_name = NULL;
- gchar *prefix, *suffix;
- gboolean is_tempfile;
+ char *capfile_name = NULL;
+ char *prefix, *suffix;
+ bool is_tempfile;
GError *err_tempfile = NULL;
ws_debug("capture_loop_open_output: %s",
@@ -3967,13 +3873,13 @@ capture_loop_open_output(capture_options *capture_opts, int *save_file_fd,
*/
capfile_name = g_strdup(capture_opts->save_file);
- if (capture_opts->output_to_pipe == TRUE) { /* either "-" or named pipe */
+ if (capture_opts->output_to_pipe == true) { /* either "-" or named pipe */
if (capture_opts->multi_files_on) {
/* ringbuffer is enabled; that doesn't work with standard output or a named pipe */
snprintf(errmsg, errmsg_len,
"Ring buffer requested, but capture is being written to standard output or to a named pipe.");
g_free(capfile_name);
- return FALSE;
+ return false;
}
if (strcmp(capfile_name, "-") == 0) {
/* write to stdout */
@@ -4011,7 +3917,7 @@ capture_loop_open_output(capture_options *capture_opts, int *save_file_fd,
g_strerror(errno));
g_free(capfile_name);
ringbuf_error_cleanup();
- return FALSE;
+ return false;
}
}
} else {
@@ -4020,7 +3926,7 @@ capture_loop_open_output(capture_options *capture_opts, int *save_file_fd,
(capture_opts->group_read_access) ? 0640 : 0600);
}
}
- is_tempfile = FALSE;
+ is_tempfile = false;
} else {
/* Choose a random name for the temporary capture buffer */
if (global_capture_opts.ifaces->len > 1) {
@@ -4034,7 +3940,7 @@ capture_loop_open_output(capture_options *capture_opts, int *save_file_fd,
* One interface; use its description, if it has one, to generate
* the temporary file name, otherwise use its name.
*/
- gchar *basename;
+ char *basename;
const interface_options *interface_opts;
interface_opts = &g_array_index(global_capture_opts.ifaces, interface_options, 0);
@@ -4094,7 +4000,7 @@ capture_loop_open_output(capture_options *capture_opts, int *save_file_fd,
}
*save_file_fd = create_tempfile(capture_opts->temp_dir, &capfile_name, prefix, suffix, &err_tempfile);
g_free(prefix);
- is_tempfile = TRUE;
+ is_tempfile = true;
}
/* did we fail to open the output file? */
@@ -4118,7 +4024,7 @@ capture_loop_open_output(capture_options *capture_opts, int *save_file_fd,
g_strerror(errno));
}
g_free(capfile_name);
- return FALSE;
+ return false;
}
g_free(capture_opts->save_file);
@@ -4131,7 +4037,7 @@ capture_loop_open_output(capture_options *capture_opts, int *save_file_fd,
capture_opts->save_file = capfile_name;
}
- return TRUE;
+ return true;
}
static time_t get_next_time_interval(int interval_s) {
@@ -4143,17 +4049,17 @@ static time_t get_next_time_interval(int interval_s) {
/* Do the work of handling either the file size or file duration capture
conditions being reached, and switching files or stopping. */
-static gboolean
+static bool
do_file_switch_or_stop(capture_options *capture_opts)
{
- gboolean successful;
+ bool successful;
if (capture_opts->multi_files_on) {
if (capture_opts->has_autostop_files &&
++global_ld.file_count >= capture_opts->autostop_files) {
/* no files left: stop here */
- global_ld.go = FALSE;
- return FALSE;
+ global_ld.go = false;
+ return false;
}
/* Switch to the next ringbuffer file */
@@ -4175,10 +4081,10 @@ do_file_switch_or_stop(capture_options *capture_opts)
if (!successful) {
fclose(global_ld.pdh);
global_ld.pdh = NULL;
- global_ld.go = FALSE;
+ global_ld.go = false;
g_free(global_ld.io_buffer);
global_ld.io_buffer = NULL;
- return FALSE;
+ return false;
}
if (global_ld.file_duration_timer) {
g_timer_reset(global_ld.file_duration_timer);
@@ -4195,15 +4101,15 @@ do_file_switch_or_stop(capture_options *capture_opts)
report_new_capture_file(capture_opts->save_file);
} else {
/* File switch failed: stop here */
- global_ld.go = FALSE;
- return FALSE;
+ global_ld.go = false;
+ return false;
}
} else {
/* single file, stop now */
- global_ld.go = FALSE;
- return FALSE;
+ global_ld.go = false;
+ return false;
}
- return TRUE;
+ return true;
}
static void *
@@ -4226,7 +4132,7 @@ pcap_read_handler(void* arg)
}
/* Try to pop an item off the packet queue and if it exists, write it */
-static gboolean
+static bool
capture_loop_dequeue_packet(void) {
pcap_queue_element *queue_element;
@@ -4254,15 +4160,15 @@ capture_loop_dequeue_packet(void) {
ws_info("Dequeued a packet of length %d captured on interface %d.",
queue_element->u.phdr.caplen, queue_element->pcap_src->interface_id);
- capture_loop_write_packet_cb((u_char *) queue_element->pcap_src,
+ capture_loop_write_packet_cb((uint8_t *) queue_element->pcap_src,
&queue_element->u.phdr,
queue_element->pd);
}
g_free(queue_element->pd);
g_free(queue_element);
- return TRUE;
+ return true;
}
- return FALSE;
+ return false;
}
/*
@@ -4274,7 +4180,7 @@ capture_loop_dequeue_packet(void) {
static char *
handle_npcap_bug(char *adapter_name _U_, char *cap_err_str _U_)
{
- gboolean have_npcap = FALSE;
+ bool have_npcap = false;
#ifdef _WIN32
have_npcap = caplibs_have_npcap();
@@ -4297,35 +4203,35 @@ handle_npcap_bug(char *adapter_name _U_, char *cap_err_str _U_)
}
/* Do the low-level work of a capture.
- Returns TRUE if it succeeds, FALSE otherwise. */
-static gboolean
-capture_loop_start(capture_options *capture_opts, gboolean *stats_known, struct pcap_stat *stats)
+ Returns true if it succeeds, false otherwise. */
+static bool
+capture_loop_start(capture_options *capture_opts, bool *stats_known, struct pcap_stat *stats)
{
#ifdef _WIN32
- DWORD upd_time, cur_time; /* GetTickCount() returns a "DWORD" (which is 'unsigned long') */
+ ULONGLONG upd_time, cur_time; /* GetTickCount64() returns a "ULONGLONG" */
#else
struct timeval upd_time, cur_time;
#endif
int err_close;
int inpkts;
GTimer *autostop_duration_timer = NULL;
- gboolean write_ok;
- gboolean close_ok;
- gboolean cfilter_error = FALSE;
+ bool write_ok;
+ bool close_ok;
+ bool cfilter_error = false;
char errmsg[MSG_MAX_LENGTH+1];
char secondary_errmsg[MSG_MAX_LENGTH+1];
capture_src *pcap_src;
interface_options *interface_opts;
- guint i, error_index = 0;
+ unsigned i, error_index = 0;
*errmsg = '\0';
*secondary_errmsg = '\0';
/* init the loop data */
- global_ld.go = TRUE;
+ global_ld.go = true;
global_ld.packets_captured = 0;
#ifdef SIGINFO
- global_ld.report_packet_count = FALSE;
+ global_ld.report_packet_count = false;
#endif
global_ld.inpkts_to_sync_pipe = 0;
global_ld.err = 0; /* no error seen yet */
@@ -4338,7 +4244,7 @@ capture_loop_start(capture_options *capture_opts, gboolean *stats_known, struct
global_ld.interval_s = 0;
/* We haven't yet gotten the capture statistics. */
- *stats_known = FALSE;
+ *stats_known = false;
ws_info("Capture loop starting ...");
capture_opts_log(LOG_DOMAIN_CAPCHILD, LOG_LEVEL_DEBUG, capture_opts);
@@ -4365,7 +4271,7 @@ capture_loop_start(capture_options *capture_opts, gboolean *stats_known, struct
break;
case INITFILTER_BAD_FILTER:
- cfilter_error = TRUE;
+ cfilter_error = true;
error_index = i;
snprintf(errmsg, sizeof(errmsg), "%s", pcap_geterr(pcap_src->pcap_h));
goto error;
@@ -4415,8 +4321,8 @@ capture_loop_start(capture_options *capture_opts, gboolean *stats_known, struct
}
/* create stop conditions */
if (capture_opts->has_autostop_filesize) {
- if (capture_opts->autostop_filesize > (((guint32)INT_MAX + 1) / 1000)) {
- capture_opts->autostop_filesize = ((guint32)INT_MAX + 1) / 1000;
+ if (capture_opts->autostop_filesize > UINT32_C(2000000000)) {
+ capture_opts->autostop_filesize = UINT32_C(2000000000);
}
}
if (capture_opts->has_autostop_duration) {
@@ -4431,7 +4337,7 @@ capture_loop_start(capture_options *capture_opts, gboolean *stats_known, struct
/* init the time values */
#ifdef _WIN32
- upd_time = GetTickCount();
+ upd_time = GetTickCount64();
#else
gettimeofday(&upd_time, NULL);
#endif
@@ -4454,7 +4360,7 @@ capture_loop_start(capture_options *capture_opts, gboolean *stats_known, struct
while (global_ld.go) {
/* dispatch incoming packets */
if (use_threads) {
- gboolean dequeued = capture_loop_dequeue_packet();
+ bool dequeued = capture_loop_dequeue_packet();
if (dequeued) {
inpkts = 1;
@@ -4468,16 +4374,16 @@ capture_loop_start(capture_options *capture_opts, gboolean *stats_known, struct
}
if (inpkts == 0) {
/* Stop capturing if all of our sources are pipes and none of them are open. */
- gboolean open_interfaces = FALSE;
+ bool open_interfaces = false;
for (i = 0; i < global_ld.pcaps->len; i++) {
pcap_src = g_array_index(global_ld.pcaps, capture_src *, i);
if (pcap_src->cap_pipe_err == PIPOK) {
/* True for both non-pipes and open pipes. */
- open_interfaces = TRUE;
+ open_interfaces = true;
}
}
if (!open_interfaces) {
- global_ld.go = FALSE;
+ global_ld.go = false;
}
}
#ifdef SIGINFO
@@ -4485,14 +4391,14 @@ capture_loop_start(capture_options *capture_opts, gboolean *stats_known, struct
if (global_ld.report_packet_count) {
fprintf(stderr, "%u packet%s captured\n", global_ld.packets_captured,
plurality(global_ld.packets_captured, "", "s"));
- global_ld.report_packet_count = FALSE;
+ global_ld.report_packet_count = false;
}
#endif
#ifdef _WIN32
/* any news from our parent (signal pipe)? -> just stop the capture */
if (!signal_pipe_check_running()) {
- global_ld.go = FALSE;
+ global_ld.go = false;
}
#endif
@@ -4509,12 +4415,12 @@ capture_loop_start(capture_options *capture_opts, gboolean *stats_known, struct
* packets we haven't notified the parent about, such as on fast links?
*/
#ifdef _WIN32
- cur_time = GetTickCount(); /* Note: wraps to 0 if sys runs for 49.7 days */
- if ((cur_time - upd_time) > capture_opts->update_interval) /* wrap just causes an extra update */
+ cur_time = GetTickCount64();
+ if ((cur_time - upd_time) > capture_opts->update_interval)
#else
gettimeofday(&cur_time, NULL);
- if (((guint64)cur_time.tv_sec * 1000000 + cur_time.tv_usec) >
- ((guint64)upd_time.tv_sec * 1000000 + upd_time.tv_usec + capture_opts->update_interval*1000))
+ if (((uint64_t)cur_time.tv_sec * 1000000 + cur_time.tv_usec) >
+ ((uint64_t)upd_time.tv_sec * 1000000 + upd_time.tv_usec + capture_opts->update_interval*1000))
#endif
{
@@ -4522,7 +4428,7 @@ capture_loop_start(capture_options *capture_opts, gboolean *stats_known, struct
#if 0
if (pcap_stats(pch, stats) >= 0) {
- *stats_known = TRUE;
+ *stats_known = true;
}
#endif
/* Let the parent process know. */
@@ -4541,7 +4447,7 @@ capture_loop_start(capture_options *capture_opts, gboolean *stats_known, struct
/* check capture duration condition */
if (autostop_duration_timer != NULL && g_timer_elapsed(autostop_duration_timer, NULL) >= capture_opts->autostop_duration) {
/* The maximum capture time has elapsed; stop the capture. */
- global_ld.go = FALSE;
+ global_ld.go = false;
continue;
}
@@ -4571,7 +4477,7 @@ capture_loop_start(capture_options *capture_opts, gboolean *stats_known, struct
ws_info("Thread of interface %u terminated.", pcap_src->interface_id);
}
while (1) {
- gboolean dequeued = capture_loop_dequeue_packet();
+ bool dequeued = capture_loop_dequeue_packet();
if (!dequeued) {
break;
}
@@ -4707,20 +4613,20 @@ capture_loop_start(capture_options *capture_opts, gboolean *stats_known, struct
}
/* did we have an output error while capturing? */
if (global_ld.err == 0) {
- write_ok = TRUE;
+ write_ok = true;
} else {
capture_loop_get_errmsg(errmsg, sizeof(errmsg), secondary_errmsg,
sizeof(secondary_errmsg),
- capture_opts->save_file, global_ld.err, FALSE);
+ capture_opts->save_file, global_ld.err, false);
report_capture_error(errmsg, secondary_errmsg);
- write_ok = FALSE;
+ write_ok = false;
}
if (capture_opts->saving_to_file) {
/* close the output file */
close_ok = capture_loop_close_output(capture_opts, &global_ld, &err_close);
} else
- close_ok = TRUE;
+ close_ok = true;
/* there might be packets not yet notified to the parent */
/* (do this after closing the file, so all packets are already flushed) */
@@ -4735,7 +4641,7 @@ capture_loop_start(capture_options *capture_opts, gboolean *stats_known, struct
if (!close_ok && write_ok) {
capture_loop_get_errmsg(errmsg, sizeof(errmsg), secondary_errmsg,
sizeof(secondary_errmsg),
- capture_opts->save_file, err_close, TRUE);
+ capture_opts->save_file, err_close, true);
report_capture_error(errmsg, secondary_errmsg);
}
@@ -4748,12 +4654,12 @@ capture_loop_start(capture_options *capture_opts, gboolean *stats_known, struct
* mode, cap_pipe_open_live() will say "End of file on pipe during open".
*/
- report_capture_count(TRUE);
+ report_capture_count(!really_quiet);
/* get packet drop statistics from pcap */
for (i = 0; i < capture_opts->ifaces->len; i++) {
- guint32 received;
- guint32 pcap_dropped = 0;
+ uint32_t received;
+ uint32_t pcap_dropped = 0;
pcap_src = g_array_index(global_ld.pcaps, capture_src *, i);
interface_opts = &g_array_index(capture_opts->ifaces, interface_options, i);
@@ -4762,7 +4668,7 @@ capture_loop_start(capture_options *capture_opts, gboolean *stats_known, struct
ws_assert(!pcap_src->from_cap_pipe);
/* Get the capture statistics, so we know how many packets were dropped. */
if (pcap_stats(pcap_src->pcap_h, stats) >= 0) {
- *stats_known = TRUE;
+ *stats_known = true;
/* Let the parent process know. */
pcap_dropped += stats->ps_drop;
} else {
@@ -4810,14 +4716,14 @@ error:
ws_info("Capture loop stopped with error");
- return FALSE;
+ return false;
}
static void
capture_loop_stop(void)
{
- guint i;
+ unsigned i;
capture_src *pcap_src;
for (i = 0; i < global_ld.pcaps->len; i++) {
@@ -4825,14 +4731,14 @@ capture_loop_stop(void)
if (pcap_src->pcap_h != NULL)
pcap_breakloop(pcap_src->pcap_h);
}
- global_ld.go = FALSE;
+ global_ld.go = false;
}
static void
capture_loop_get_errmsg(char *errmsg, size_t errmsglen, char *secondary_errmsg,
size_t secondary_errmsglen, const char *fname,
- int err, gboolean is_close)
+ int err, bool is_close)
{
static const char find_space[] =
"You will need to free up space on that file system"
@@ -4899,13 +4805,13 @@ capture_loop_wrote_one_packet(capture_src *pcap_src) {
/* check -c NUM */
if (global_capture_opts.has_autostop_packets && global_ld.packets_captured >= global_capture_opts.autostop_packets) {
fflush(global_ld.pdh);
- global_ld.go = FALSE;
+ global_ld.go = false;
return;
}
/* check -a packets:NUM (treat like -c NUM) */
if (global_capture_opts.has_autostop_written_packets && global_ld.packets_captured >= global_capture_opts.autostop_written_packets) {
fflush(global_ld.pdh);
- global_ld.go = FALSE;
+ global_ld.go = false;
return;
}
/* check -b packets:NUM */
@@ -4925,7 +4831,7 @@ capture_loop_wrote_one_packet(capture_src *pcap_src) {
/* one pcapng block was captured, process it */
static void
-capture_loop_write_pcapng_cb(capture_src *pcap_src, const pcapng_block_header_t *bh, u_char *pd)
+capture_loop_write_pcapng_cb(capture_src *pcap_src, const pcapng_block_header_t *bh, uint8_t *pd)
{
int err;
@@ -4958,10 +4864,10 @@ capture_loop_write_pcapng_cb(capture_src *pcap_src, const pcapng_block_header_t
}
if (global_ld.pdh) {
- gboolean successful;
+ bool successful;
/* We're supposed to write the packet to a file; do so.
- If this fails, set "ld->go" to FALSE, to stop the capture, and set
+ If this fails, set "ld->go" to false, to stop the capture, and set
"ld->err" to the error. */
successful = pcapng_write_block(global_ld.pdh,
pd,
@@ -4970,22 +4876,18 @@ capture_loop_write_pcapng_cb(capture_src *pcap_src, const pcapng_block_header_t
fflush(global_ld.pdh);
if (!successful) {
- global_ld.go = FALSE;
+ global_ld.go = false;
global_ld.err = err;
pcap_src->dropped++;
- } else if (bh->block_type == BLOCK_TYPE_EPB || bh->block_type == BLOCK_TYPE_SPB || bh->block_type == BLOCK_TYPE_SYSTEMD_JOURNAL_EXPORT || bh->block_type == BLOCK_TYPE_SYSDIG_EVENT || bh->block_type == BLOCK_TYPE_SYSDIG_EVENT_V2 || bh->block_type == BLOCK_TYPE_SYSDIG_EVENT_V2_LARGE) {
+ } else if (is_data_block(bh->block_type)) {
/* Count packets for block types that should be dissected, i.e. ones that show up in the packet list. */
-#if defined(DEBUG_DUMPCAP) || defined(DEBUG_CHILD_DUMPCAP)
- ws_info("Wrote a pcapng block type %u of length %d captured on interface %u.",
+ ws_debug("Wrote a pcapng block type 0x%04x of length %d captured on interface %u.",
bh->block_type, bh->block_total_length, pcap_src->interface_id);
-#endif
capture_loop_wrote_one_packet(pcap_src);
} else if (bh->block_type == BLOCK_TYPE_SHB && report_capture_filename) {
-#if defined(DEBUG_DUMPCAP) || defined(DEBUG_CHILD_DUMPCAP)
- ws_info("Sending SP_FILE on first SHB");
-#endif
+ ws_debug("Sending SP_FILE on first SHB");
/* SHB is now ready for capture parent to read on SP_FILE message */
- sync_pipe_write_string_msg(2, SP_FILE, report_capture_filename);
+ sync_pipe_write_string_msg(sync_pipe_fd, SP_FILE, report_capture_filename);
report_capture_filename = NULL;
}
}
@@ -4993,12 +4895,12 @@ capture_loop_write_pcapng_cb(capture_src *pcap_src, const pcapng_block_header_t
/* one pcap packet was captured, process it */
static void
-capture_loop_write_packet_cb(u_char *pcap_src_p, const struct pcap_pkthdr *phdr,
- const u_char *pd)
+capture_loop_write_packet_cb(uint8_t *pcap_src_p, const struct pcap_pkthdr *phdr,
+ const uint8_t *pd)
{
capture_src *pcap_src = (capture_src *) (void *) pcap_src_p;
int err;
- guint ts_mul = pcap_src->ts_nsec ? 1000000000 : 1000000;
+ unsigned ts_mul = pcap_src->ts_nsec ? 1000000000 : 1000000;
ws_debug("capture_loop_write_packet_cb");
@@ -5011,15 +4913,15 @@ capture_loop_write_packet_cb(u_char *pcap_src_p, const struct pcap_pkthdr *phdr,
}
if (global_ld.pdh) {
- gboolean successful;
+ bool successful;
/* We're supposed to write the packet to a file; do so.
- If this fails, set "ld->go" to FALSE, to stop the capture, and set
+ If this fails, set "ld->go" to false, to stop the capture, and set
"ld->err" to the error. */
if (global_capture_opts.use_pcapng) {
successful = pcapng_write_enhanced_packet_block(global_ld.pdh,
NULL,
- phdr->ts.tv_sec, (gint32)phdr->ts.tv_usec,
+ phdr->ts.tv_sec, (int32_t)phdr->ts.tv_usec,
phdr->caplen, phdr->len,
pcap_src->idb_id,
ts_mul,
@@ -5027,20 +4929,18 @@ capture_loop_write_packet_cb(u_char *pcap_src_p, const struct pcap_pkthdr *phdr,
&global_ld.bytes_written, &err);
} else {
successful = libpcap_write_packet(global_ld.pdh,
- phdr->ts.tv_sec, (gint32)phdr->ts.tv_usec,
+ phdr->ts.tv_sec, (int32_t)phdr->ts.tv_usec,
phdr->caplen, phdr->len,
pd,
&global_ld.bytes_written, &err);
}
if (!successful) {
- global_ld.go = FALSE;
+ global_ld.go = false;
global_ld.err = err;
pcap_src->dropped++;
} else {
-#if defined(DEBUG_DUMPCAP) || defined(DEBUG_CHILD_DUMPCAP)
- ws_info("Wrote a pcap packet of length %d captured on interface %u.",
+ ws_debug("Wrote a pcap packet of length %d captured on interface %u.",
phdr->caplen, pcap_src->interface_id);
-#endif
capture_loop_wrote_one_packet(pcap_src);
}
}
@@ -5048,12 +4948,12 @@ capture_loop_write_packet_cb(u_char *pcap_src_p, const struct pcap_pkthdr *phdr,
/* one packet was captured, queue it */
static void
-capture_loop_queue_packet_cb(u_char *pcap_src_p, const struct pcap_pkthdr *phdr,
- const u_char *pd)
+capture_loop_queue_packet_cb(uint8_t *pcap_src_p, const struct pcap_pkthdr *phdr,
+ const uint8_t *pd)
{
capture_src *pcap_src = (capture_src *) (void *) pcap_src_p;
pcap_queue_element *queue_element;
- gboolean limit_reached;
+ bool limit_reached;
/* We may be called multiple times from pcap_dispatch(); if we've set
the "stop capturing" flag, ignore this packet, as we're not
@@ -5070,7 +4970,7 @@ capture_loop_queue_packet_cb(u_char *pcap_src_p, const struct pcap_pkthdr *phdr,
}
queue_element->pcap_src = pcap_src;
queue_element->u.phdr = *phdr;
- queue_element->pd = (u_char *)g_malloc(phdr->caplen);
+ queue_element->pd = (uint8_t *)g_malloc(phdr->caplen);
if (queue_element->pd == NULL) {
pcap_src->dropped++;
g_free(queue_element);
@@ -5080,12 +4980,12 @@ capture_loop_queue_packet_cb(u_char *pcap_src_p, const struct pcap_pkthdr *phdr,
g_async_queue_lock(pcap_queue);
if (((pcap_queue_byte_limit == 0) || (pcap_queue_bytes < pcap_queue_byte_limit)) &&
((pcap_queue_packet_limit == 0) || (pcap_queue_packets < pcap_queue_packet_limit))) {
- limit_reached = FALSE;
+ limit_reached = false;
g_async_queue_push_unlocked(pcap_queue, queue_element);
pcap_queue_bytes += phdr->caplen;
pcap_queue_packets += 1;
} else {
- limit_reached = TRUE;
+ limit_reached = true;
}
g_async_queue_unlock(pcap_queue);
if (limit_reached) {
@@ -5107,10 +5007,10 @@ capture_loop_queue_packet_cb(u_char *pcap_src_p, const struct pcap_pkthdr *phdr,
/* one pcapng block was captured, queue it */
static void
-capture_loop_queue_pcapng_cb(capture_src *pcap_src, const pcapng_block_header_t *bh, u_char *pd)
+capture_loop_queue_pcapng_cb(capture_src *pcap_src, const pcapng_block_header_t *bh, uint8_t *pd)
{
pcap_queue_element *queue_element;
- gboolean limit_reached;
+ bool limit_reached;
/* We may be called multiple times from pcap_dispatch(); if we've set
the "stop capturing" flag, ignore this packet, as we're not
@@ -5127,7 +5027,7 @@ capture_loop_queue_pcapng_cb(capture_src *pcap_src, const pcapng_block_header_t
}
queue_element->pcap_src = pcap_src;
queue_element->u.bh = *bh;
- queue_element->pd = (u_char *)g_malloc(bh->block_total_length);
+ queue_element->pd = (uint8_t *)g_malloc(bh->block_total_length);
if (queue_element->pd == NULL) {
pcap_src->dropped++;
g_free(queue_element);
@@ -5137,12 +5037,12 @@ capture_loop_queue_pcapng_cb(capture_src *pcap_src, const pcapng_block_header_t
g_async_queue_lock(pcap_queue);
if (((pcap_queue_byte_limit == 0) || (pcap_queue_bytes < pcap_queue_byte_limit)) &&
((pcap_queue_packet_limit == 0) || (pcap_queue_packets < pcap_queue_packet_limit))) {
- limit_reached = FALSE;
+ limit_reached = false;
g_async_queue_push_unlocked(pcap_queue, queue_element);
pcap_queue_bytes += bh->block_total_length;
pcap_queue_packets += 1;
} else {
- limit_reached = TRUE;
+ limit_reached = true;
}
g_async_queue_unlock(pcap_queue);
if (limit_reached) {
@@ -5165,13 +5065,13 @@ capture_loop_queue_pcapng_cb(capture_src *pcap_src, const pcapng_block_header_t
static int
set_80211_channel(const char *iface, const char *opt)
{
- guint32 freq = 0;
+ uint32_t freq = 0;
int type = -1;
- guint32 center_freq1 = 0;
- guint32 center_freq2 = 0;
+ uint32_t center_freq1 = 0;
+ uint32_t center_freq2 = 0;
int args;
int ret = 0;
- gchar **options = NULL;
+ char **options = NULL;
options = g_strsplit_set(opt, ",", 4);
for (args = 0; options[args]; args++)
@@ -5188,7 +5088,7 @@ set_80211_channel(const char *iface, const char *opt)
}
if (options[0])
- freq = get_nonzero_guint32(options[0], "802.11 channel frequency");
+ freq = get_nonzero_uint32(options[0], "802.11 channel frequency");
if (args >= 1 && options[1]) {
type = ws80211_str_to_chan_type(options[1]);
@@ -5200,10 +5100,10 @@ set_80211_channel(const char *iface, const char *opt)
}
if (args >= 2 && options[2])
- center_freq1 = get_nonzero_guint32(options[2], "VHT center frequency");
+ center_freq1 = get_nonzero_uint32(options[2], "VHT center frequency");
if (args >= 3 && options[3])
- center_freq2 = get_nonzero_guint32(options[3], "VHT center frequency 2");
+ center_freq2 = get_nonzero_uint32(options[3], "VHT center frequency 2");
ret = ws80211_set_freq(iface, freq, type, center_freq1, center_freq2);
@@ -5214,7 +5114,7 @@ set_80211_channel(const char *iface, const char *opt)
}
if (capture_child)
- sync_pipe_write_string_msg(2, SP_SUCCESS, NULL);
+ sync_pipe_write_string_msg(sync_pipe_fd, SP_SUCCESS, NULL);
out:
g_strfreev(options);
@@ -5238,6 +5138,9 @@ gather_dumpcap_runtime_info(feature_list l)
#define LONGOPT_IFNAME LONGOPT_BASE_APPLICATION+1
#define LONGOPT_IFDESCR LONGOPT_BASE_APPLICATION+2
#define LONGOPT_CAPTURE_COMMENT LONGOPT_BASE_APPLICATION+3
+#ifdef _WIN32
+#define LONGOPT_SIGNAL_PIPE LONGOPT_BASE_APPLICATION+4
+#endif
/* And now our feature presentation... [ fade to music ] */
int
@@ -5252,27 +5155,30 @@ main(int argc, char *argv[])
{"ifname", ws_required_argument, NULL, LONGOPT_IFNAME},
{"ifdescr", ws_required_argument, NULL, LONGOPT_IFDESCR},
{"capture-comment", ws_required_argument, NULL, LONGOPT_CAPTURE_COMMENT},
+#ifdef _WIN32
+ {"signal-pipe", ws_required_argument, NULL, LONGOPT_SIGNAL_PIPE},
+#endif
{0, 0, 0, 0 }
};
- gboolean arg_error = FALSE;
+ bool arg_error = false;
#ifndef _WIN32
struct sigaction action, oldaction;
#endif
- gboolean stats_known;
+ bool stats_known;
struct pcap_stat stats = {0};
- gboolean list_interfaces = FALSE;
+ bool list_interfaces = false;
int caps_queries = 0;
- gboolean print_bpf_code = FALSE;
- gboolean set_chan = FALSE;
- gchar *set_chan_arg = NULL;
- gboolean machine_readable = FALSE;
- gboolean print_statistics = FALSE;
+ bool print_bpf_code = false;
+ bool set_chan = false;
+ char *set_chan_arg = NULL;
+ bool machine_readable = false;
+ bool print_statistics = false;
int status, run_once_args = 0;
- gint i;
- guint j;
+ int i;
+ unsigned j;
#if defined(__APPLE__) && defined(__LP64__)
struct utsname osinfo;
#endif
@@ -5306,12 +5212,33 @@ main(int argc, char *argv[])
for (i=1; i<argc; i++) {
if (strcmp("-Z", argv[i]) == 0) {
- capture_child = TRUE;
- machine_readable = TRUE; /* request machine-readable output */
+ capture_child = true;
+ machine_readable = true; /* request machine-readable output */
+ i++;
+ if (i >= argc) {
+ exit_main(1);
+ }
+
+ if (strcmp(argv[i], SIGNAL_PIPE_CTRL_ID_NONE) != 0) {
+ // get_positive_int calls cmdarg_err
+ if (!ws_strtoi(argv[i], NULL, &sync_pipe_fd) || sync_pipe_fd <= 0) {
+ exit_main(1);
+ }
#ifdef _WIN32
- /* set output pipe to binary mode, to avoid ugly text conversions */
- _setmode(2, O_BINARY);
+ /* On UN*X the fd is the same when we fork + exec.
+ * On Windows the HANDLE value is the same for inherited
+ * handles in the child process and the parent, although
+ * not necessarily the fd value from _open_osfhandle.
+ * https://learn.microsoft.com/en-us/windows/win32/procthread/inheritance
+ * Also, "64-bit versions of Windows use 32-bit handles for
+ * interoperability... only the lower 32 bits are significant,
+ * so it is safe to truncate... or sign-extend the handle."
+ * https://learn.microsoft.com/en-us/windows/win32/winprog64/interprocess-communication
+ */
+ /* set output pipe to binary mode, avoid ugly text conversions */
+ sync_pipe_fd = _open_osfhandle( (intptr_t) sync_pipe_fd, _O_BINARY);
#endif
+ }
}
}
@@ -5323,17 +5250,14 @@ main(int argc, char *argv[])
/* Early logging command-line initialization. */
ws_log_parse_args(&argc, argv, vcmdarg_err, 1);
-#if defined(DEBUG_DUMPCAP) || defined(DEBUG_CHILD_DUMPCAP)
- /* sync_pipe_start does not pass along log level information from
- * the parent (XXX: it probably should.) Assume that if we're
- * specially compiled with dumpcap debugging then we want it on.
+#if DEBUG_CHILD_DUMPCAP
+ /* Assume that if we're specially compiled with dumpcap debugging
+ * then we want maximum debugging.
*/
if (capture_child) {
- ws_log_set_level(LOG_LEVEL_DEBUG);
+ ws_log_set_level(LOG_LEVEL_NOISY);
}
-#endif
-#ifdef DEBUG_CHILD_DUMPCAP
if ((debug_log = ws_fopen("dumpcap_debug_log.tmp","w")) == NULL) {
fprintf (stderr, "Unable to open debug log file .\n");
exit (1);
@@ -5373,7 +5297,7 @@ main(int argc, char *argv[])
#define OPTSTRING_m
#endif
-#define OPTSTRING OPTSTRING_CAPTURE_COMMON "C:dghk:" OPTSTRING_m "MN:nPq" OPTSTRING_r "St" OPTSTRING_u "vw:Z:"
+#define OPTSTRING OPTSTRING_CAPTURE_COMMON "C:dghk:" OPTSTRING_m "MN:nPqQ" OPTSTRING_r "St" OPTSTRING_u "vw:Z:"
#if defined(__APPLE__) && defined(__LP64__)
/*
@@ -5393,13 +5317,13 @@ main(int argc, char *argv[])
if (strcmp(osinfo.release, "10.0.0") == 0 || /* 10.6, 10.6.1 */
strcmp(osinfo.release, "10.3.0") == 0 || /* 10.6.3 */
strcmp(osinfo.release, "10.4.0") == 0) /* 10.6.4 */
- need_timeout_workaround = TRUE;
+ need_timeout_workaround = true;
}
#endif
/* Initialize the pcaps list and IDBs */
global_ld.pcaps = g_array_new(FALSE, FALSE, sizeof(capture_src *));
- global_ld.pcapng_passthrough = FALSE;
+ global_ld.pcapng_passthrough = false;
global_ld.saved_shb = NULL;
global_ld.saved_idbs = g_array_new(FALSE, TRUE, sizeof(saved_idb_t));
@@ -5416,7 +5340,7 @@ main(int argc, char *argv[])
#ifdef _WIN32
/* Set handler for Ctrl+C key */
- SetConsoleCtrlHandler(capture_cleanup_handler, TRUE);
+ SetConsoleCtrlHandler(capture_cleanup_handler, true);
#else
/* Catch SIGINT and SIGTERM and, if we get either of them, clean up
and exit. Do the same with SIGPIPE, in case, for example,
@@ -5543,8 +5467,8 @@ main(int argc, char *argv[])
capture_opts_init(&global_capture_opts, get_interface_list);
/* We always save to a file - if no file was specified, we save to a
temporary file. */
- global_capture_opts.saving_to_file = TRUE;
- global_capture_opts.has_ring_num_files = TRUE;
+ global_capture_opts.saving_to_file = true;
+ global_capture_opts.has_ring_num_files = true;
/* Pass on capture_child mode for capture_opts */
global_capture_opts.capture_child = capture_child;
@@ -5566,6 +5490,7 @@ main(int argc, char *argv[])
case 'b': /* Ringbuffer option */
case 'c': /* Capture x packets */
case 'f': /* capture filter */
+ case 'F': /* capture file type */
case 'g': /* enable group read access on file(s) */
case 'i': /* Use interface x */
case LONGOPT_SET_TSTAMP_TYPE: /* Set capture timestamp type */
@@ -5627,10 +5552,18 @@ main(int argc, char *argv[])
g_ptr_array_add(capture_comments, g_strdup(ws_optarg));
break;
case 'Z':
- capture_child = TRUE;
+ capture_child = true;
+ /*
+ * Handled above
+ */
+ break;
#ifdef _WIN32
- /* set output pipe to binary mode, to avoid ugly text conversions */
- _setmode(2, O_BINARY);
+ case LONGOPT_SIGNAL_PIPE:
+ if (!capture_child) {
+ /* We have already checked for -Z at the very beginning. */
+ cmdarg_err("--signal-pipe may only be specified with -Z");
+ exit_main(1);
+ }
/*
* ws_optarg = the control ID, aka the PPID, currently used for the
* signal pipe name.
@@ -5646,55 +5579,61 @@ main(int argc, char *argv[])
exit_main(1);
}
}
-#endif
break;
-
+#endif
case 'q': /* Quiet */
- quiet = TRUE;
+ quiet = true;
+ break;
+ case 'Q': /* Really quiet */
+ quiet = true;
+ really_quiet = true;
break;
case 't':
- use_threads = TRUE;
+ use_threads = true;
break;
/*** all non capture option specific ***/
case 'D': /* Print a list of capture devices and exit */
- if (!list_interfaces) {
- list_interfaces = TRUE;
+ if (!list_interfaces && !caps_queries & !print_statistics) {
run_once_args++;
}
+ list_interfaces = true;
break;
case 'L': /* Print list of link-layer types and exit */
- if (!(caps_queries & CAPS_QUERY_LINK_TYPES)) {
- caps_queries |= CAPS_QUERY_LINK_TYPES;
+ if (!list_interfaces && !caps_queries & !print_statistics) {
run_once_args++;
}
+ caps_queries |= CAPS_QUERY_LINK_TYPES;
break;
case LONGOPT_LIST_TSTAMP_TYPES:
- caps_queries |= CAPS_QUERY_TIMESTAMP_TYPES;
- break;
+ if (!list_interfaces && !caps_queries & !print_statistics) {
+ run_once_args++;
+ }
+ caps_queries |= CAPS_QUERY_TIMESTAMP_TYPES;
+ break;
case 'd': /* Print BPF code for capture filter and exit */
if (!print_bpf_code) {
- print_bpf_code = TRUE;
+ print_bpf_code = true;
run_once_args++;
}
break;
case 'S': /* Print interface statistics once a second */
- if (!print_statistics) {
- print_statistics = TRUE;
+ if (!list_interfaces && !caps_queries & !print_statistics) {
run_once_args++;
}
+ print_statistics = true;
break;
case 'k': /* Set wireless channel */
if (!set_chan) {
- set_chan = TRUE;
+ set_chan = true;
set_chan_arg = ws_optarg;
run_once_args++;
} else {
cmdarg_err("Only one -k flag may be specified");
- arg_error = TRUE;
+ arg_error = true;
}
break;
case 'M': /* For -D, -L, and -S, print machine-readable output */
- machine_readable = TRUE;
+ machine_readable = true;
break;
case 'C':
pcap_queue_byte_limit = get_positive_int(ws_optarg, "byte_limit");
@@ -5706,7 +5645,7 @@ main(int argc, char *argv[])
cmdarg_err("Invalid Option: %s", argv[ws_optind-1]);
/* FALLTHROUGH */
case '?': /* Bad flag - print usage message */
- arg_error = TRUE;
+ arg_error = true;
break;
}
}
@@ -5725,12 +5664,12 @@ main(int argc, char *argv[])
* XXX - interpret as capture filter, as tcpdump and tshark do?
*/
cmdarg_err("Invalid argument: %s", argv[0]);
- arg_error = TRUE;
+ arg_error = true;
}
}
if ((pcap_queue_byte_limit > 0) || (pcap_queue_packet_limit > 0)) {
- use_threads = TRUE;
+ use_threads = true;
}
if ((pcap_queue_byte_limit == 0) && (pcap_queue_packet_limit == 0)) {
/* Use some default if the user hasn't specified some */
@@ -5739,6 +5678,10 @@ main(int argc, char *argv[])
pcap_queue_packet_limit = 1000;
}
if (arg_error) {
+ if (ws_optopt == 'F') {
+ capture_opts_list_file_types();
+ exit_main(1);
+ }
print_usage(stderr);
exit_main(1);
}
@@ -5758,8 +5701,8 @@ main(int argc, char *argv[])
/* Are we capturing on multiple interface? If so, use threads and pcapng. */
if (global_capture_opts.ifaces->len > 1) {
- use_threads = TRUE;
- global_capture_opts.use_pcapng = TRUE;
+ use_threads = true;
+ global_capture_opts.use_pcapng = true;
}
if (capture_comments &&
@@ -5777,7 +5720,7 @@ main(int argc, char *argv[])
file size is set to "infinite". */
if (global_capture_opts.save_file == NULL) {
cmdarg_err("Ring buffer requested, but capture isn't being saved to a permanent file.");
- global_capture_opts.multi_files_on = FALSE;
+ global_capture_opts.multi_files_on = false;
}
if (!global_capture_opts.has_autostop_filesize &&
!global_capture_opts.has_file_duration &&
@@ -5787,7 +5730,7 @@ main(int argc, char *argv[])
"interval, or packets were specified.");
#if 0
/* XXX - this must be redesigned as the conditions changed */
- global_capture_opts.multi_files_on = FALSE;
+ global_capture_opts.multi_files_on = false;
#endif
}
if (global_capture_opts.has_file_duration && global_capture_opts.has_file_interval) {
@@ -5805,7 +5748,7 @@ main(int argc, char *argv[])
/* Get the list of interfaces */
GList *if_list;
int err;
- gchar *err_str;
+ char *err_str;
if_list = get_interface_list(&err, &err_str);
if (if_list == NULL) {
@@ -5827,12 +5770,68 @@ main(int argc, char *argv[])
}
}
- if (machine_readable) /* tab-separated values to stdout */
- print_machine_readable_interfaces(if_list);
- else
+ if (!machine_readable) {
+ status = 0;
capture_opts_print_interfaces(if_list);
+ }
+
+ if (caps_queries) {
+ if_info_t *if_info;
+ interface_options *interface_opts;
+ cap_device_open_status open_status;
+ char *open_status_str;
+ for (GList *if_entry = if_list; if_entry != NULL; if_entry = g_list_next(if_entry)) {
+ if_info = (if_info_t *)if_entry->data;
+
+ interface_opts = interface_opts_from_if_info(&global_capture_opts, if_info);
+
+ if_info->caps = get_if_capabilities(interface_opts, &open_status, &open_status_str);
+
+ if (!machine_readable) {
+ if (if_info->caps == NULL) {
+ cmdarg_err("The capabilities of the capture device "
+ "\"%s\" could not be obtained (%s).\n%s",
+ interface_opts->name, open_status_str,
+ get_pcap_failure_secondary_error_message(open_status, open_status_str));
+ g_free(open_status_str);
+ /* Break after one error, as when printing selected
+ * interface capabilities. (XXX: We could print all
+ * the primary status strings, and only the unique
+ * set of secondary messages / suggestions; printing
+ * the same long secondary error is a lot.)
+ */
+ interface_opts_free(interface_opts);
+ g_free(interface_opts);
+ break;
+ } else {
+ status = capture_opts_print_if_capabilities(if_info->caps, interface_opts, caps_queries);
+ if (status != 0) {
+ interface_opts_free(interface_opts);
+ g_free(interface_opts);
+ break;
+ }
+ }
+ } else {
+ if (if_info->caps == NULL) {
+ if_info->caps = g_new0(if_capabilities_t, 1);
+ if_info->caps->primary_msg = open_status_str;
+ if_info->caps->secondary_msg = g_strdup(get_pcap_failure_secondary_error_message(open_status, open_status_str));
+ }
+ if_info->caps->status = open_status;
+ }
+
+ interface_opts_free(interface_opts);
+ g_free(interface_opts);
+ }
+ }
+
+ if (machine_readable) {
+ status = print_machine_readable_interfaces(if_list, caps_queries, print_statistics);
+ }
free_interface_list(if_list);
- exit_main(0);
+ if (!print_statistics) {
+ exit_main(status);
+ }
}
/*
@@ -5871,46 +5870,89 @@ main(int argc, char *argv[])
/* Get the list of link-layer and/or timestamp types for the capture device. */
if_capabilities_t *caps;
cap_device_open_status open_status;
- gchar *open_status_str;
- guint ii;
+ char *open_status_str;
+ unsigned ii;
+
+ if (machine_readable) {
+ json_dumper dumper = {
+ .output_file = stdout,
+ .flags = JSON_DUMPER_FLAGS_NO_DEBUG,
+ // Don't abort on failure
+ };
+ json_dumper_begin_array(&dumper);
+ for (ii = 0; ii < global_capture_opts.ifaces->len; ii++) {
+ interface_options *interface_opts;
- for (ii = 0; ii < global_capture_opts.ifaces->len; ii++) {
- interface_options *interface_opts;
+ interface_opts = &g_array_index(global_capture_opts.ifaces, interface_options, ii);
+
+ json_dumper_begin_object(&dumper);
+ json_dumper_set_member_name(&dumper, interface_opts->name);
- interface_opts = &g_array_index(global_capture_opts.ifaces, interface_options, ii);
+ json_dumper_begin_object(&dumper);
- caps = get_if_capabilities(interface_opts, &open_status, &open_status_str);
- if (caps == NULL) {
+ open_status = CAP_DEVICE_OPEN_NO_ERR;
+ caps = get_if_capabilities(interface_opts, &open_status, &open_status_str);
+ if (caps == NULL) {
+ json_dumper_set_member_name(&dumper, "status");
+ json_dumper_value_anyf(&dumper, "%i", open_status);
+ json_dumper_set_member_name(&dumper, "primary_msg");
+ json_dumper_value_string(&dumper, open_status_str);
+ g_free(open_status_str);
+ } else {
+ caps->status = open_status;
+ print_machine_readable_if_capabilities(&dumper, caps, caps_queries);
+ free_if_capabilities(caps);
+ }
+ json_dumper_end_object(&dumper);
+ json_dumper_end_object(&dumper);
+ }
+ json_dumper_end_array(&dumper);
+ if (json_dumper_finish(&dumper)) {
+ status = 0;
if (capture_child) {
- char *error_msg = ws_strdup_printf("The capabilities of the capture device "
- "\"%s\" could not be obtained (%s)",
- interface_opts->name, open_status_str);
- sync_pipe_write_errmsgs_to_parent(2, error_msg,
- get_pcap_failure_secondary_error_message(open_status, open_status_str));
- g_free(error_msg);
+ /* Let our parent know we succeeded. */
+ sync_pipe_write_string_msg(sync_pipe_fd, SP_SUCCESS, NULL);
}
- else {
- cmdarg_err("The capabilities of the capture device "
- "\"%s\" could not be obtained (%s).\n%s",
- interface_opts->name, open_status_str,
- get_pcap_failure_secondary_error_message(open_status, open_status_str));
+ } else {
+ status = 2;
+ if (capture_child) {
+ sync_pipe_write_errmsgs_to_parent(sync_pipe_fd, "Unexpected JSON error", "");
}
- g_free(open_status_str);
- exit_main(2);
}
+ } else {
+ for (ii = 0; ii < global_capture_opts.ifaces->len; ii++) {
+ interface_options *interface_opts;
+
+ interface_opts = &g_array_index(global_capture_opts.ifaces, interface_options, ii);
+
+ caps = get_if_capabilities(interface_opts, &open_status, &open_status_str);
+ if (caps == NULL) {
+ if (capture_child) {
+ char *error_msg = ws_strdup_printf("The capabilities of the capture device "
+ "\"%s\" could not be obtained (%s)",
+ interface_opts->name, open_status_str);
+ sync_pipe_write_errmsgs_to_parent(sync_pipe_fd, error_msg,
+ get_pcap_failure_secondary_error_message(open_status, open_status_str));
+ g_free(error_msg);
+ }
+ else {
+ cmdarg_err("The capabilities of the capture device "
+ "\"%s\" could not be obtained (%s).\n%s",
+ interface_opts->name, open_status_str,
+ get_pcap_failure_secondary_error_message(open_status, open_status_str));
+ }
+ g_free(open_status_str);
+ exit_main(2);
+ }
- if (machine_readable) { /* tab-separated values to stdout */
- /* XXX: We need to change the format and adapt consumers */
- print_machine_readable_if_capabilities(caps, caps_queries);
- status = 0;
- } else
/* XXX: We might want to print also the interface name */
status = capture_opts_print_if_capabilities(caps,
interface_opts,
caps_queries);
- free_if_capabilities(caps);
- if (status != 0)
- break;
+ free_if_capabilities(caps);
+ if (status != 0)
+ break;
+ }
}
exit_main(status);
}
@@ -5985,7 +6027,8 @@ main(int argc, char *argv[])
} else {
g_string_append_printf(str, "%u interfaces", global_capture_opts.ifaces->len);
}
- fprintf(stderr, "Capturing on %s\n", str->str);
+ if (!really_quiet)
+ fprintf(stderr, "Capturing on %s\n", str->str);
g_string_free(str, TRUE);
}
@@ -6004,7 +6047,7 @@ main(int argc, char *argv[])
fflush(stderr);
/* Now start the capture. */
- if (capture_loop_start(&global_capture_opts, &stats_known, &stats) == TRUE) {
+ if (capture_loop_start(&global_capture_opts, &stats_known, &stats) == true) {
/* capture ok */
exit_main(0);
} else {
@@ -6022,18 +6065,36 @@ dumpcap_log_writer(const char *domain, enum ws_log_level level,
const char *user_format, va_list user_ap,
void *user_data _U_)
{
- /* DEBUG & INFO msgs (if we're debugging today) */
-#if defined(DEBUG_DUMPCAP) || defined(DEBUG_CHILD_DUMPCAP)
- if (level <= LOG_LEVEL_INFO && ws_log_msg_is_active(domain, level)) {
-#ifdef DEBUG_DUMPCAP
+ if (ws_log_msg_is_active(domain, level)) {
+ /* log messages go to stderr or */
+ /* to parent especially formatted if dumpcap running as child. */
#ifdef DEBUG_CHILD_DUMPCAP
va_list user_ap_copy;
va_copy(user_ap_copy, user_ap);
#endif
if (capture_child) {
- gchar *msg = ws_strdup_vprintf(user_format, user_ap);
- sync_pipe_write_errmsgs_to_parent(2, msg, "");
- g_free(msg);
+ /* Format the log mesage as the numeric level, followed
+ * by a colon and then a string matching the standard log
+ * string. In the future perhaps we serialize file, line,
+ * and func (which can be NULL) instead.
+ */
+ GString *msg = g_string_new(NULL);
+ g_string_append_printf(msg, "%u:", level);
+ if (file != NULL) {
+ g_string_append_printf(msg, "%s", file);
+ if (line >= 0) {
+ g_string_append_printf(msg, ":%ld", line);
+ }
+ }
+ g_string_append(msg, " --");
+ if (func != NULL) {
+ g_string_append_printf(msg, " %s():", func);
+ }
+ g_string_append_c(msg, ' ');
+ g_string_append_vprintf(msg, user_format, user_ap);
+
+ sync_pipe_write_string_msg(sync_pipe_fd, SP_LOG_MSG, msg->str);
+ g_string_free(msg, TRUE);
} else {
ws_log_console_writer(domain, level, file, line, func, mft, user_format, user_ap);
}
@@ -6041,21 +6102,6 @@ dumpcap_log_writer(const char *domain, enum ws_log_level level,
ws_log_file_writer(debug_log, domain, level, file, line, func, mft, user_format, user_ap_copy);
va_end(user_ap_copy);
#endif
-#elif defined(DEBUG_CHILD_DUMPCAP)
- ws_log_file_writer(debug_log, domain, level, file, line, func, mft, user_format, user_ap);
-#endif
- return;
- }
-#endif
-
- /* ERROR, CRITICAL, WARNING, MESSAGE messages goto stderr or */
- /* to parent especially formatted if dumpcap running as child. */
- if (capture_child) {
- gchar *msg = ws_strdup_vprintf(user_format, user_ap);
- sync_pipe_write_errmsgs_to_parent(2, msg, "");
- g_free(msg);
- } else if(ws_log_msg_is_active(domain, level)) {
- ws_log_console_writer(domain, level, file, line, func, mft, user_format, user_ap);
}
}
@@ -6071,7 +6117,7 @@ report_packet_count(unsigned int packet_count)
if (capture_child) {
ws_debug("Packets: %u", packet_count);
- sync_pipe_write_uint_msg(2, SP_PACKET_COUNT, packet_count);
+ sync_pipe_write_uint_msg(sync_pipe_fd, SP_PACKET_COUNT, packet_count);
} else {
count += packet_count;
fprintf(stderr, "\rPackets: %u ", count);
@@ -6087,12 +6133,10 @@ report_new_capture_file(const char *filename)
ws_debug("File: %s", filename);
if (global_ld.pcapng_passthrough) {
/* Save filename for sending SP_FILE to capture parent after SHB is passed-through */
-#if defined(DEBUG_DUMPCAP) || defined(DEBUG_CHILD_DUMPCAP)
- ws_info("Delaying SP_FILE until first SHB");
-#endif
+ ws_debug("Delaying SP_FILE until first SHB");
report_capture_filename = filename;
} else {
- sync_pipe_write_string_msg(2, SP_FILE, filename);
+ sync_pipe_write_string_msg(sync_pipe_fd, SP_FILE, filename);
}
} else {
#ifdef SIGINFO
@@ -6101,17 +6145,19 @@ report_new_capture_file(const char *filename)
* while we're doing so; instead, have it just set a flag telling
* us to print that information when we're done.
*/
- infodelay = TRUE;
+ infodelay = true;
#endif /* SIGINFO */
- fprintf(stderr, "File: %s\n", filename);
- /* stderr could be line buffered */
- fflush(stderr);
+ if (!really_quiet) {
+ fprintf(stderr, "File: %s\n", filename);
+ /* stderr could be line buffered */
+ fflush(stderr);
+ }
#ifdef SIGINFO
/*
* Allow SIGINFO handlers to write.
*/
- infodelay = FALSE;
+ infodelay = false;
/*
* If a SIGINFO handler asked us to write out capture counts, do so.
@@ -6123,7 +6169,7 @@ report_new_capture_file(const char *filename)
}
static void
-report_cfilter_error(capture_options *capture_opts, guint i, const char *errmsg)
+report_cfilter_error(capture_options *capture_opts, unsigned i, const char *errmsg)
{
interface_options *interface_opts;
char tmp[MSG_MAX_LENGTH+1+6];
@@ -6132,7 +6178,7 @@ report_cfilter_error(capture_options *capture_opts, guint i, const char *errmsg)
if (capture_child) {
snprintf(tmp, sizeof(tmp), "%u:%s", i, errmsg);
ws_debug("Capture filter error: %s", errmsg);
- sync_pipe_write_string_msg(2, SP_BAD_FILTER, tmp);
+ sync_pipe_write_string_msg(sync_pipe_fd, SP_BAD_FILTER, tmp);
} else {
/*
* clopts_step_invalid_capfilter in test/suite-clopts.sh MUST match
@@ -6155,7 +6201,7 @@ report_capture_error(const char *error_msg, const char *secondary_error_msg)
if (capture_child) {
ws_debug("Primary Error: %s", error_msg);
ws_debug("Secondary Error: %s", secondary_error_msg);
- sync_pipe_write_errmsgs_to_parent(2, error_msg, secondary_error_msg);
+ sync_pipe_write_errmsgs_to_parent(sync_pipe_fd, error_msg, secondary_error_msg);
} else {
cmdarg_err("%s", error_msg);
if (secondary_error_msg[0] != '\0')
@@ -6164,24 +6210,26 @@ report_capture_error(const char *error_msg, const char *secondary_error_msg)
}
static void
-report_packet_drops(guint32 received, guint32 pcap_drops, guint32 drops, guint32 flushed, guint32 ps_ifdrop, gchar *name)
+report_packet_drops(uint32_t received, uint32_t pcap_drops, uint32_t drops, uint32_t flushed, uint32_t ps_ifdrop, char *name)
{
- guint32 total_drops = pcap_drops + drops + flushed;
+ uint32_t total_drops = pcap_drops + drops + flushed;
if (capture_child) {
char* tmp = ws_strdup_printf("%u:%s", total_drops, name);
ws_debug("Packets received/dropped on interface '%s': %u/%u (pcap:%u/dumpcap:%u/flushed:%u/ps_ifdrop:%u)",
name, received, total_drops, pcap_drops, drops, flushed, ps_ifdrop);
- sync_pipe_write_string_msg(2, SP_DROPS, tmp);
+ sync_pipe_write_string_msg(sync_pipe_fd, SP_DROPS, tmp);
g_free(tmp);
} else {
- fprintf(stderr,
- "Packets received/dropped on interface '%s': %u/%u (pcap:%u/dumpcap:%u/flushed:%u/ps_ifdrop:%u) (%.1f%%)\n",
- name, received, total_drops, pcap_drops, drops, flushed, ps_ifdrop,
- received ? 100.0 * received / (received + total_drops) : 0.0);
- /* stderr could be line buffered */
- fflush(stderr);
+ if (!really_quiet) {
+ fprintf(stderr,
+ "Packets received/dropped on interface '%s': %u/%u (pcap:%u/dumpcap:%u/flushed:%u/ps_ifdrop:%u) (%.1f%%)\n",
+ name, received, total_drops, pcap_drops, drops, flushed, ps_ifdrop,
+ received ? 100.0 * received / (received + total_drops) : 0.0);
+ /* stderr could be line buffered */
+ fflush(stderr);
+ }
}
}
@@ -6191,22 +6239,22 @@ report_packet_drops(guint32 received, guint32 pcap_drops, guint32 drops, guint32
#ifdef _WIN32
-static gboolean
+static bool
signal_pipe_check_running(void)
{
/* any news from our parent? -> just stop the capture */
DWORD avail = 0;
- gboolean result;
+ bool result;
/* if we are running standalone, no check required */
if (!capture_child) {
- return TRUE;
+ return true;
}
if (!sig_pipe_name || !sig_pipe_handle) {
/* This shouldn't happen */
ws_info("Signal pipe: No name or handle");
- return FALSE;
+ return false;
}
/*
@@ -6223,10 +6271,10 @@ signal_pipe_check_running(void)
ws_info("Signal pipe: Stop capture: %s", sig_pipe_name);
ws_debug("Signal pipe: %s (%p) result: %u avail: %lu", sig_pipe_name,
sig_pipe_handle, result, avail);
- return FALSE;
+ return false;
} else {
/* pipe ok and no bytes available */
- return TRUE;
+ return true;
}
}
#endif