Bug Summary

File:builds/wireshark/wireshark/capture/capture_sync.c
Warning:line 957, column 9
Potential leak of memory pointed to by 'argv'

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name capture_sync.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -fno-delete-null-pointer-checks -mframe-pointer=all -relaxed-aliasing -fmath-errno -ffp-contract=on -fno-rounding-math -ffloat16-excess-precision=fast -fbfloat16-excess-precision=fast -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/builds/wireshark/wireshark/build -fcoverage-compilation-dir=/builds/wireshark/wireshark/build -resource-dir /usr/lib/llvm-18/lib/clang/18 -isystem /usr/include/glib-2.0 -isystem /usr/lib/x86_64-linux-gnu/glib-2.0/include -D G_DISABLE_DEPRECATED -D G_DISABLE_SINGLE_INCLUDES -D WS_DEBUG -D WS_DEBUG_UTF_8 -I /builds/wireshark/wireshark/build -I /builds/wireshark/wireshark -I /builds/wireshark/wireshark/include -D _GLIBCXX_ASSERTIONS -internal-isystem /usr/lib/llvm-18/lib/clang/18/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -fmacro-prefix-map=/builds/wireshark/wireshark/= -fmacro-prefix-map=/builds/wireshark/wireshark/build/= -fmacro-prefix-map=../= -Wno-format-truncation -Wno-format-nonliteral -Wno-pointer-sign -std=gnu11 -ferror-limit 19 -fvisibility=hidden -fwrapv -fstrict-flex-arrays=3 -stack-protector 2 -fstack-clash-protection -fcf-protection=full -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -fexceptions -fcolor-diagnostics -analyzer-output=html -dwarf-debug-flags /usr/lib/llvm-18/bin/clang -### --analyze -x c -D G_DISABLE_DEPRECATED -D G_DISABLE_SINGLE_INCLUDES -D WS_DEBUG -D WS_DEBUG_UTF_8 -I /builds/wireshark/wireshark/build -I /builds/wireshark/wireshark -I /builds/wireshark/wireshark/include -isystem /usr/include/glib-2.0 -isystem /usr/lib/x86_64-linux-gnu/glib-2.0/include -fvisibility=hidden -fexcess-precision=fast -fstrict-flex-arrays=3 -fstack-clash-protection -fcf-protection=full -D _GLIBCXX_ASSERTIONS -fstack-protector-strong -fno-delete-null-pointer-checks -fno-strict-overflow -fno-strict-aliasing -fexceptions -Wno-format-truncation -Wno-format-nonliteral -fdiagnostics-color=always -Wno-pointer-sign -fmacro-prefix-map=/builds/wireshark/wireshark/= -fmacro-prefix-map=/builds/wireshark/wireshark/build/= -fmacro-prefix-map=../= -std=gnu11 -fPIC /builds/wireshark/wireshark/capture/capture_sync.c -o /builds/wireshark/wireshark/sbout/2025-06-29-100246-3847-1 -Xclang -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /builds/wireshark/wireshark/sbout/2025-06-29-100246-3847-1 -x c /builds/wireshark/wireshark/capture/capture_sync.c
1/* capture_sync.c
2 * Synchronisation between Wireshark capture parent and child instances
3 *
4 * Wireshark - Network traffic analyzer
5 * By Gerald Combs <gerald@wireshark.org>
6 * Copyright 1998 Gerald Combs
7 *
8 * SPDX-License-Identifier: GPL-2.0-or-later
9 */
10
11#include "config.h"
12#define WS_LOG_DOMAIN"Capture" LOG_DOMAIN_CAPTURE"Capture"
13
14#include <wireshark.h>
15
16#ifdef HAVE_LIBPCAP1
17
18#include <glib.h>
19#include <stdio.h>
20#include <stdlib.h>
21
22#include <signal.h>
23
24#include <ws_exit_codes.h>
25
26#include <wsutil/application_flavor.h>
27#include <wsutil/strtoi.h>
28#include <wsutil/ws_assert.h>
29
30#ifdef _WIN32
31#include <wsutil/unicode-utils.h>
32#include <wsutil/win32-utils.h>
33#include <wsutil/ws_pipe.h>
34#else
35#include <glib-unix1.h>
36#endif
37
38#ifdef HAVE_SYS_WAIT_H1
39# include <sys/wait.h>
40#endif
41
42#include "capture/capture-pcap-util.h"
43
44#ifndef _WIN32
45/*
46 * Define various POSIX macros (and, in the case of WCOREDUMP, non-POSIX
47 * macros) on UNIX systems that don't have them.
48 */
49#ifndef WIFEXITED
50# define WIFEXITED(status)(((status) & 0x7f) == 0) (((status) & 0177) == 0)
51#endif
52#ifndef WIFSTOPPED
53# define WIFSTOPPED(status)(((status) & 0xff) == 0x7f) (((status) & 0177) == 0177)
54#endif
55#ifndef WIFSIGNALED
56# define WIFSIGNALED(status)(((signed char) (((status) & 0x7f) + 1) >> 1) > 0
)
(!WIFSTOPPED(status)(((status) & 0xff) == 0x7f) && !WIFEXITED(status)(((status) & 0x7f) == 0))
57#endif
58#ifndef WEXITSTATUS
59# define WEXITSTATUS(status)(((status) & 0xff00) >> 8) ((status) >> 8)
60#endif
61#ifndef WTERMSIG
62# define WTERMSIG(status)((status) & 0x7f) ((status) & 0177)
63#endif
64#ifndef WCOREDUMP
65# define WCOREDUMP(status)((status) & 0x80) ((status) & 0200)
66#endif
67#ifndef WSTOPSIG
68# define WSTOPSIG(status)(((status) & 0xff00) >> 8) ((status) >> 8)
69#endif
70#endif /* _WIN32 */
71
72#include <epan/packet.h>
73#include <epan/prefs.h>
74
75#include "file.h"
76
77#include "ui/capture.h"
78#include <capture/capture_sync.h>
79
80#include "sync_pipe.h"
81
82#ifdef _WIN32
83#include "capture/capture-wpcap.h"
84#endif
85
86#include "ui/ws_ui_util.h"
87
88#include <wsutil/filesystem.h>
89#include <wsutil/file_util.h>
90#include <wsutil/report_message.h>
91#include "extcap.h"
92
93#ifdef _WIN32
94#include <process.h> /* For spawning child process */
95#endif
96
97#include <wsutil/ws_pipe.h>
98
99#ifdef _WIN32
100static int create_dummy_signal_pipe(char **msg);
101static HANDLE dummy_signal_pipe; /* Dummy named pipe which lets the child check for a dropped connection */
102static char *dummy_control_id;
103#else
104static const char *sync_pipe_signame(int);
105#endif
106
107/* We use this pipe buffer size for both the sync message pipe and the
108 * data pipe. Ensure that it's large enough for the indicator and header
109 * plus maximum message size.
110 */
111#define PIPE_BUF_SIZE((512 * 1000)+4) (SP_MAX_MSG_LEN(512 * 1000)+4)
112
113static gboolean sync_pipe_input_cb(GIOChannel *pipe_io, capture_session *cap_session);
114static int sync_pipe_wait_for_child(ws_process_id fork_child, char **msgp);
115static void pipe_convert_header(const unsigned char *header, int header_len, char *indicator, int *block_len);
116static ssize_t pipe_read_block(GIOChannel *pipe_io, char *indicator, int len, char *msg,
117 char **err_msg);
118
119static void (*fetch_dumpcap_pid)(ws_process_id);
120
121void
122capture_session_init(capture_session *cap_session, capture_file *cf,
123 new_file_fn new_file, new_packets_fn new_packets,
124 drops_fn drops, error_fn error,
125 cfilter_error_fn cfilter_error, closed_fn closed)
126{
127 cap_session->cf = cf;
128 cap_session->fork_child = WS_INVALID_PID-1; /* invalid process handle */
129 cap_session->pipe_input_id = 0;
130#ifdef _WIN32
131 cap_session->signal_pipe_write_fd = -1;
132#endif
133 cap_session->state = CAPTURE_STOPPED;
134#ifndef _WIN32
135 cap_session->owner = getuid();
136 cap_session->group = getgid();
137#endif
138 cap_session->count = 0;
139 cap_session->count_pending = 0;
140 cap_session->session_will_restart = false0;
141
142 cap_session->new_file = new_file;
143 cap_session->new_packets = new_packets;
144 cap_session->drops = drops;
145 cap_session->error = error;
146 cap_session->cfilter_error = cfilter_error;
147 cap_session->closed = closed;
148 cap_session->frame_cksum = NULL((void*)0);
149}
150
151void capture_process_finished(capture_session *cap_session)
152{
153 capture_options *capture_opts = cap_session->capture_opts;
154 interface_options *interface_opts;
155 GString *message;
156 unsigned i;
157
158 if (!extcap_session_stop(cap_session)) {
159 /* At least one extcap process did not fully finish yet, wait for it */
160 return;
161 }
162
163 if (cap_session->fork_child != WS_INVALID_PID-1) {
164 if (capture_opts->stop_after_extcaps) {
165 /* User has requested capture stop and all extcaps are gone now */
166 capture_opts->stop_after_extcaps = false0;
167 sync_pipe_stop(cap_session);
168 }
169 /* Wait for child process to end, session is not closed yet */
170 return;
171 }
172
173 /* Construct message and close session */
174 message = g_string_new(capture_opts->closed_msg);
175 for (i = 0; i < capture_opts->ifaces->len; i++) {
176 interface_opts = &g_array_index(capture_opts->ifaces, interface_options, i)(((interface_options*) (void *) (capture_opts->ifaces)->
data) [(i)])
;
177 if (interface_opts->if_type != IF_EXTCAP) {
178 continue;
179 }
180
181 if ((interface_opts->extcap_stderr != NULL((void*)0)) &&
182 (interface_opts->extcap_stderr->len > 0)) {
183 if (message->len > 0) {
184 g_string_append(message, "\n")(__builtin_constant_p ("\n") ? __extension__ ({ const char * const
__val = ("\n"); g_string_append_len_inline (message, __val, (
__val != ((void*)0)) ? (gssize) strlen (((__val) + !(__val)))
: (gssize) -1); }) : g_string_append_len_inline (message, "\n"
, (gssize) -1))
;
185 }
186 g_string_append(message, "Error from extcap pipe: ")(__builtin_constant_p ("Error from extcap pipe: ") ? __extension__
({ const char * const __val = ("Error from extcap pipe: "); g_string_append_len_inline
(message, __val, (__val != ((void*)0)) ? (gssize) strlen (((
__val) + !(__val))) : (gssize) -1); }) : g_string_append_len_inline
(message, "Error from extcap pipe: ", (gssize) -1))
;
187 g_string_append(message, interface_opts->extcap_stderr->str)(__builtin_constant_p (interface_opts->extcap_stderr->str
) ? __extension__ ({ const char * const __val = (interface_opts
->extcap_stderr->str); g_string_append_len_inline (message
, __val, (__val != ((void*)0)) ? (gssize) strlen (((__val) + !
(__val))) : (gssize) -1); }) : g_string_append_len_inline (message
, interface_opts->extcap_stderr->str, (gssize) -1))
;
188 }
189 }
190
191 cap_session->closed(cap_session, message->str);
192 g_string_free(message, TRUE)(__builtin_constant_p ((!(0))) ? (((!(0))) ? (g_string_free) (
(message), ((!(0)))) : g_string_free_and_steal (message)) : (
g_string_free) ((message), ((!(0)))))
;
193 g_free(capture_opts->closed_msg);
194 capture_opts->closed_msg = NULL((void*)0);
195 capture_opts->stop_after_extcaps = false0;
196}
197
198/* Append an arg (realloc) to an argc/argv array */
199/* (add a string pointer to a NULL-terminated array of string pointers) */
200/* XXX: For glib >= 2.68 we could use a GStrvBuilder.
201 */
202static char **
203sync_pipe_add_arg(char **args, int *argc, const char *arg)
204{
205 /* Grow the array; "*argc" currently contains the number of string
206 pointers, *not* counting the NULL pointer at the end, so we have
207 to add 2 in order to get the new size of the array, including the
208 new pointer and the terminating NULL pointer. */
209 args = (char **)g_realloc( (void *) args, (*argc + 2) * sizeof (char *));
14
Memory is allocated
210
211 /* Stuff the pointer into the penultimate element of the array, which
212 is the one at the index specified by "*argc". */
213 args[*argc] = g_strdup(arg)g_strdup_inline (arg);
214 /* Now bump the count. */
215 (*argc)++;
216
217 /* We overwrite the NULL pointer; put it back right after the
218 element we added. */
219 args[*argc] = NULL((void*)0);
220
221 return args;
222}
223
224/* Take a buffer from an SP_LOG_MSG from dumpcap and send it to our
225 * current logger. Keep this in sync with the format used in
226 * dumpcap_log_writer. (We might want to do more proper serialization
227 * of more than just the log level.)
228 */
229static void
230sync_pipe_handle_log_msg(const char *buffer) {
231 const char *log_msg = NULL((void*)0);
232 const char* end;
233 uint32_t level = 0;
234
235 if (ws_strtou32(buffer, &end, &level) && end[0] == ':') {
236 log_msg = end + 1;
237 }
238 ws_log(LOG_DOMAIN_CAPCHILD"Capchild", level, "%s", log_msg);
239}
240
241/* Initialize an argument list and add dumpcap to it. */
242static char **
243init_pipe_args(int *argc) {
244 char *exename;
245 char **argv;
246
247 /* Find the absolute path of the dumpcap executable. */
248 exename = get_executable_path("dumpcap");
249 if (exename == NULL((void*)0)) {
250 return NULL((void*)0);
251 }
252
253 /* Allocate the string pointer array with enough space for the
254 terminating NULL pointer. */
255 *argc = 0;
256 argv = (char **)g_malloc(sizeof (char *));
257 *argv = NULL((void*)0);
258
259 /* Make that the first argument in the argument list (argv[0]). */
260 argv = sync_pipe_add_arg(argv, argc, exename);
261
262 /* Tell dumpcap to log at the lowest level its domain (Capchild) is
263 * set to log in the main program. (It might be in the special noisy
264 * or debug filter, so we can't just check the overall level.)
265 */
266 for (enum ws_log_level level = LOG_LEVEL_NOISY; level != _LOG_LEVEL_LAST; level++) {
267 if (ws_log_msg_is_active(LOG_DOMAIN_CAPCHILD"Capchild", level)) {
268 argv = sync_pipe_add_arg(argv, argc, "--log-level");
269 argv = sync_pipe_add_arg(argv, argc, ws_log_level_to_string(level));
270 break;
271 }
272 }
273
274 argv = sync_pipe_add_arg(argv, argc, "--application-flavor");
275 argv = sync_pipe_add_arg(argv, argc, application_flavor_name_lower());
276
277 /* sync_pipe_add_arg strdupes exename, so we should free our copy */
278 g_free(exename);
279
280 return argv;
281}
282
283static gboolean
284pipe_io_cb(GIOChannel *pipe_io, GIOCondition condition _U___attribute__((unused)), void * user_data)
285{
286 capture_session *cap_session = (capture_session *)user_data;
287 if (!sync_pipe_input_cb(pipe_io, cap_session)) {
288 cap_session->pipe_input_id = 0;
289 return G_SOURCE_REMOVE(0);
290 }
291 return G_SOURCE_CONTINUE(!(0));
292}
293
294/*
295 * Open two pipes to dumpcap with the supplied arguments, one for its
296 * standard output and one for its standard error.
297 *
298 * On success, *msg is unchanged and 0 is returned; data_read_fd,
299 * message_read_fd, and fork_child point to the standard output pipe's
300 * file descriptor, the standard error pipe's file descriptor, and
301 * the child's PID/handle, respectively.
302 *
303 * On failure, *msg points to an error message for the failure, and -1 is
304 * returned, in which case *msg must be freed with g_free().
305 */
306#define ARGV_NUMBER_LEN24 24
307static int
308#ifdef _WIN32
309sync_pipe_open_command(char **argv, int *data_read_fd,
310 GIOChannel **message_read_io, int *signal_write_fd,
311 ws_process_id *fork_child, GArray *ifaces,
312 char **msg, void(*update_cb)(void))
313#else
314sync_pipe_open_command(char **argv, int *data_read_fd,
315 GIOChannel **message_read_io, int *signal_write_fd _U___attribute__((unused)),
316 ws_process_id *fork_child, GArray *ifaces _U___attribute__((unused)),
317 char **msg, void(*update_cb)(void))
318#endif
319{
320 enum PIPES { PIPE_READ, PIPE_WRITE }; /* Constants 0 and 1 for PIPE_READ and PIPE_WRITE */
321 int message_read_fd = -1;
322 char sync_id[ARGV_NUMBER_LEN24];
323#ifdef _WIN32
324 HANDLE sync_pipe[2]; /* pipe used to send messages from child to parent */
325 HANDLE data_pipe[2]; /* pipe used to send data from child to parent */
326 int signal_pipe_write_fd = -1;
327 HANDLE signal_pipe; /* named pipe used to send messages from parent to child (currently only stop) */
328 char control_id[ARGV_NUMBER_LEN24];
329 char *signal_pipe_name;
330 size_t i_handles = 0;
331 HANDLE *handles;
332 GString *args = g_string_sized_new(200);
333 char *quoted_arg;
334 SECURITY_ATTRIBUTES sa;
335 STARTUPINFO si;
336 PROCESS_INFORMATION pi;
337 int i;
338 unsigned j;
339 interface_options *interface_opts;
340#else
341 int sync_pipe[2]; /* pipe used to send messages from child to parent */
342 int data_pipe[2]; /* pipe used to send data from child to parent */
343#endif
344 *fork_child = WS_INVALID_PID-1;
345 if (data_read_fd != NULL((void*)0)) {
346 *data_read_fd = -1;
347 }
348 *message_read_io = NULL((void*)0);
349 ws_debug("sync_pipe_open_command")do { if (1) { ws_log_full("Capture", LOG_LEVEL_DEBUG, "capture/capture_sync.c"
, 349, __func__, "sync_pipe_open_command"); } } while (0)
;
350
351 if (!msg) {
352 /* We can't return anything */
353 g_strfreev(argv);
354#ifdef _WIN32
355 g_string_free(args, TRUE)(__builtin_constant_p ((!(0))) ? (((!(0))) ? (g_string_free) (
(args), ((!(0)))) : g_string_free_and_steal (args)) : (g_string_free
) ((args), ((!(0)))))
;
356#endif
357 return -1;
358 }
359
360#ifdef _WIN32
361 /* init SECURITY_ATTRIBUTES */
362 sa.nLength = sizeof(SECURITY_ATTRIBUTES);
363 sa.bInheritHandle = false0;
364 sa.lpSecurityDescriptor = NULL((void*)0);
365
366 /* Create a pipe for the child process to send us messages */
367 /* (increase this value if you have trouble while fast capture file switches) */
368 if (! CreatePipe(&sync_pipe[PIPE_READ], &sync_pipe[PIPE_WRITE], &sa, PIPE_BUF_SIZE((512 * 1000)+4))) {
369 /* Couldn't create the message pipe between parent and child. */
370 *msg = ws_strdup_printf("Couldn't create sync pipe: %s",wmem_strdup_printf(((void*)0), "Couldn't create sync pipe: %s"
, win32strerror(GetLastError()))
371 win32strerror(GetLastError()))wmem_strdup_printf(((void*)0), "Couldn't create sync pipe: %s"
, win32strerror(GetLastError()))
;
372 g_strfreev(argv);
373 return -1;
374 }
375
376 /*
377 * Associate a C run-time file handle with the Windows HANDLE for the
378 * read side of the message pipe.
379 *
380 * (See http://www.flounder.com/handles.htm for information on various
381 * types of file handle in C/C++ on Windows.)
382 */
383 message_read_fd = _open_osfhandle( (intptr_t) sync_pipe[PIPE_READ], _O_BINARY);
384 if (message_read_fd == -1) {
385 *msg = ws_strdup_printf("Couldn't get C file handle for message read pipe: %s", g_strerror(errno))wmem_strdup_printf(((void*)0), "Couldn't get C file handle for message read pipe: %s"
, g_strerror((*__errno_location ())))
;
386 g_strfreev(argv);
387 CloseHandle(sync_pipe[PIPE_READ]);
388 CloseHandle(sync_pipe[PIPE_WRITE]);
389 return -1;
390 }
391
392 if (data_read_fd != NULL((void*)0)) {
393 /* Create a pipe for the child process to send us data */
394 /* (increase this value if you have trouble while fast capture file switches) */
395 if (! CreatePipe(&data_pipe[PIPE_READ], &data_pipe[PIPE_WRITE], &sa, PIPE_BUF_SIZE((512 * 1000)+4))) {
396 /* Couldn't create the message pipe between parent and child. */
397 *msg = ws_strdup_printf("Couldn't create data pipe: %s",wmem_strdup_printf(((void*)0), "Couldn't create data pipe: %s"
, win32strerror(GetLastError()))
398 win32strerror(GetLastError()))wmem_strdup_printf(((void*)0), "Couldn't create data pipe: %s"
, win32strerror(GetLastError()))
;
399 g_strfreev(argv);
400 ws_closeclose(message_read_fd); /* Should close sync_pipe[PIPE_READ] */
401 CloseHandle(sync_pipe[PIPE_WRITE]);
402 return -1;
403 }
404
405 /*
406 * Associate a C run-time file handle with the Windows HANDLE for the
407 * read side of the data pipe.
408 *
409 * (See http://www.flounder.com/handles.htm for information on various
410 * types of file handle in C/C++ on Windows.)
411 */
412 *data_read_fd = _open_osfhandle( (intptr_t) data_pipe[PIPE_READ], _O_BINARY);
413 if (*data_read_fd == -1) {
414 *msg = ws_strdup_printf("Couldn't get C file handle for data read pipe: %s", g_strerror(errno))wmem_strdup_printf(((void*)0), "Couldn't get C file handle for data read pipe: %s"
, g_strerror((*__errno_location ())))
;
415 g_strfreev(argv);
416 CloseHandle(data_pipe[PIPE_READ]);
417 CloseHandle(data_pipe[PIPE_WRITE]);
418 ws_closeclose(message_read_fd); /* Should close sync_pipe[PIPE_READ] */
419 CloseHandle(sync_pipe[PIPE_WRITE]);
420 return -1;
421 }
422 }
423
424 if (signal_write_fd != NULL((void*)0)) {
425 /* Create the signal pipe */
426 snprintf(control_id, ARGV_NUMBER_LEN24, "%ld", GetCurrentProcessId());
427 signal_pipe_name = ws_strdup_printf(SIGNAL_PIPE_FORMAT, control_id)wmem_strdup_printf(((void*)0), SIGNAL_PIPE_FORMAT, control_id
)
;
428 signal_pipe = CreateNamedPipe(utf_8to16(signal_pipe_name),
429 PIPE_ACCESS_OUTBOUND, PIPE_TYPE_BYTE, 1, 65535, 65535, 0, NULL((void*)0));
430 g_free(signal_pipe_name);
431
432 if (signal_pipe == INVALID_HANDLE_VALUE) {
433 /* Couldn't create the signal pipe between parent and child. */
434 *msg = ws_strdup_printf("Couldn't create signal pipe: %s",wmem_strdup_printf(((void*)0), "Couldn't create signal pipe: %s"
, win32strerror(GetLastError()))
435 win32strerror(GetLastError()))wmem_strdup_printf(((void*)0), "Couldn't create signal pipe: %s"
, win32strerror(GetLastError()))
;
436 g_strfreev(argv);
437 ws_closeclose(message_read_fd); /* Should close sync_pipe[PIPE_READ] */
438 CloseHandle(sync_pipe[PIPE_WRITE]);
439 return -1;
440 }
441
442 /*
443 * Associate a C run-time file handle with the Windows HANDLE for the
444 * read side of the message pipe.
445 *
446 * (See http://www.flounder.com/handles.htm for information on various
447 * types of file handle in C/C++ on Windows.)
448 */
449 signal_pipe_write_fd = _open_osfhandle( (intptr_t) signal_pipe, _O_BINARY);
450 if (signal_pipe_write_fd == -1) {
451 /* Couldn't create the pipe between parent and child. */
452 *msg = ws_strdup_printf("Couldn't get C file handle for sync pipe: %s", g_strerror(errno))wmem_strdup_printf(((void*)0), "Couldn't get C file handle for sync pipe: %s"
, g_strerror((*__errno_location ())))
;
453 g_strfreev(argv);
454 ws_closeclose(message_read_fd); /* Should close sync_pipe[PIPE_READ] */
455 CloseHandle(sync_pipe[PIPE_WRITE]);
456 CloseHandle(signal_pipe);
457 return -1;
458 }
459 }
460
461 /* init STARTUPINFO & PROCESS_INFORMATION */
462 memset(&si, 0, sizeof(si));
463 si.cb = sizeof(si);
464 memset(&pi, 0, sizeof(pi));
465#ifdef DEBUG_CHILD
466 si.dwFlags = STARTF_USESHOWWINDOW;
467 si.wShowWindow = SW_SHOW;
468#else
469 si.dwFlags = STARTF_USESTDHANDLES|STARTF_USESHOWWINDOW;
470 si.wShowWindow = SW_HIDE; /* this hides the console window */
471
472 if (data_read_fd == NULL((void*)0)) {
473 si.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
474 si.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
475 } else {
476 si.hStdInput = NULL((void*)0); /* handle for named pipe*/
477 si.hStdOutput = data_pipe[PIPE_WRITE];
478 }
479 si.hStdError = GetStdHandle(STD_ERROR_HANDLE);
480
481 /* On Windows, "[a]n inherited handle refers to the same object in the child
482 * process as it does in the parent process. It also has the same value."
483 * https://learn.microsoft.com/en-us/windows/win32/procthread/inheritance
484 * When converted to a file descriptor (via _open_osfhandle), the fd
485 * value is not necessarily the same in the two processes, but the handle
486 * value can be shared.
487 * A HANDLE is a void* though "64-bit versions of Windows use 32-bit handles
488 * for interoperability... only the lower 32 bits are significant, so it is
489 * safe to truncate the handle... or sign-extend the handle"
490 * https://learn.microsoft.com/en-us/windows/win32/winprog64/interprocess-communication
491 * So it should be fine to call PtrToLong instead of casting to intptr_t.
492 * https://learn.microsoft.com/en-us/windows/win32/WinProg64/rules-for-using-pointers
493 */
494 int argc = g_strv_length(argv);
495 argv = sync_pipe_add_arg(argv, &argc, "-Z");
496 snprintf(sync_id, ARGV_NUMBER_LEN24, "%ld", PtrToLong(sync_pipe[PIPE_WRITE]));
497 argv = sync_pipe_add_arg(argv, &argc, sync_id);
498#endif
499
500 if (ifaces) {
501 for (j = 0; j < ifaces->len; j++) {
502 interface_opts = &g_array_index(ifaces, interface_options, j)(((interface_options*) (void *) (ifaces)->data) [(j)]);
503 if (interface_opts->extcap_fifo != NULL((void*)0)) {
504 i_handles++;
505 }
506 }
507 }
508 handles = g_new(HANDLE, 3 + i_handles)((HANDLE *) g_malloc_n ((3 + i_handles), sizeof (HANDLE)));
509 i_handles = 0;
510 if (si.hStdInput) {
511 handles[i_handles++] = si.hStdInput;
512 }
513 if (si.hStdOutput && (si.hStdOutput != si.hStdInput)) {
514 handles[i_handles++] = si.hStdOutput;
515 }
516 handles[i_handles++] = sync_pipe[PIPE_WRITE];
517 if (ifaces) {
518 for (j = 0; j < ifaces->len; j++) {
519 interface_opts = &g_array_index(ifaces, interface_options, j)(((interface_options*) (void *) (ifaces)->data) [(j)]);
520 if (interface_opts->extcap_fifo != NULL((void*)0)) {
521 handles[i_handles++] = interface_opts->extcap_pipe_h;
522 }
523 }
524 }
525
526 /* convert args array into a single string */
527 /* XXX - could change sync_pipe_add_arg() instead */
528 /* there is a drawback here: the length is internally limited to 1024 bytes */
529 for(i=0; argv[i] != 0; i++) {
530 if(i != 0) g_string_append_c(args, ' ')g_string_append_c_inline (args, ' '); /* don't prepend a space before the path!!! */
531 quoted_arg = protect_arg(argv[i]);
532 g_string_append(args, quoted_arg)(__builtin_constant_p (quoted_arg) ? __extension__ ({ const char
* const __val = (quoted_arg); g_string_append_len_inline (args
, __val, (__val != ((void*)0)) ? (gssize) strlen (((__val) + !
(__val))) : (gssize) -1); }) : g_string_append_len_inline (args
, quoted_arg, (gssize) -1))
;
533 g_free(quoted_arg);
534 }
535
536 /* call dumpcap */
537 if(!win32_create_process(argv[0], args->str, NULL((void*)0), NULL((void*)0), i_handles, handles,
538 CREATE_NEW_CONSOLE, NULL((void*)0), NULL((void*)0), &si, &pi)) {
539 *msg = ws_strdup_printf("Couldn't run %s in child process: %s",wmem_strdup_printf(((void*)0), "Couldn't run %s in child process: %s"
, args->str, win32strerror(GetLastError()))
540 args->str, win32strerror(GetLastError()))wmem_strdup_printf(((void*)0), "Couldn't run %s in child process: %s"
, args->str, win32strerror(GetLastError()))
;
541 if (data_read_fd) {
542 ws_closeclose(*data_read_fd); /* Should close data_pipe[PIPE_READ] */
543 CloseHandle(data_pipe[PIPE_WRITE]);
544 } else {
545 ws_closeclose(signal_pipe_write_fd);
546 }
547 ws_closeclose(message_read_fd); /* Should close sync_pipe[PIPE_READ] */
548 CloseHandle(sync_pipe[PIPE_WRITE]);
549 g_strfreev(argv);
550 g_string_free(args, TRUE)(__builtin_constant_p ((!(0))) ? (((!(0))) ? (g_string_free) (
(args), ((!(0)))) : g_string_free_and_steal (args)) : (g_string_free
) ((args), ((!(0)))))
;
551 g_free(handles);
552 return -1;
553 }
554 *fork_child = pi.hProcess;
555 /* We may need to store this and close it later */
556 CloseHandle(pi.hThread);
557 g_strfreev(argv);
558 g_string_free(args, TRUE)(__builtin_constant_p ((!(0))) ? (((!(0))) ? (g_string_free) (
(args), ((!(0)))) : g_string_free_and_steal (args)) : (g_string_free
) ((args), ((!(0)))))
;
559 g_free(handles);
560
561 if (signal_write_fd != NULL((void*)0)) {
562 *signal_write_fd = signal_pipe_write_fd;
563 }
564#else /* _WIN32 */
565 /* Create a pipe for the child process to send us messages */
566 if (pipe(sync_pipe) < 0) {
567 /* Couldn't create the message pipe between parent and child. */
568 *msg = ws_strdup_printf("Couldn't create sync pipe: %s", g_strerror(errno))wmem_strdup_printf(((void*)0), "Couldn't create sync pipe: %s"
, g_strerror((*__errno_location ())))
;
569 g_strfreev(argv);
570 return -1;
571 }
572
573 if (data_read_fd != NULL((void*)0)) {
574 /* Create a pipe for the child process to send us data */
575 if (pipe(data_pipe) < 0) {
576 /* Couldn't create the data pipe between parent and child. */
577 *msg = ws_strdup_printf("Couldn't create data pipe: %s", g_strerror(errno))wmem_strdup_printf(((void*)0), "Couldn't create data pipe: %s"
, g_strerror((*__errno_location ())))
;
578 g_strfreev(argv);
579 ws_closeclose(sync_pipe[PIPE_READ]);
580 ws_closeclose(sync_pipe[PIPE_WRITE]);
581 return -1;
582 }
583 }
584
585 if ((*fork_child = fork()) == 0) {
586 /*
587 * Child process - run dumpcap with the right arguments to make
588 * it just capture with the specified capture parameters
589 */
590 if (data_read_fd != NULL((void*)0)) {
591 dup2(data_pipe[PIPE_WRITE], 1);
592 ws_closeclose(data_pipe[PIPE_READ]);
593 ws_closeclose(data_pipe[PIPE_WRITE]);
594 }
595 ws_closeclose(sync_pipe[PIPE_READ]);
596 /* dumpcap should be running in capture child mode (hidden feature) */
597#ifndef DEBUG_CHILD
598 int argc = g_strv_length(argv);
599 argv = sync_pipe_add_arg(argv, &argc, "-Z");
600 snprintf(sync_id, ARGV_NUMBER_LEN24, "%d", sync_pipe[PIPE_WRITE]);
601 argv = sync_pipe_add_arg(argv, &argc, sync_id);
602#endif
603 execv(argv[0], argv);
604 sync_pipe_write_int_msg(sync_pipe[PIPE_WRITE], SP_EXEC_FAILED'X', errno(*__errno_location ()));
605
606 /* Exit with "_exit()", so that we don't close the connection
607 to the X server (and cause stuff buffered up by our parent but
608 not yet sent to be sent, as that stuff should only be sent by
609 our parent). We've sent an error message to the parent, so
610 we exit with an exit status of 1 (any exit status other than
611 0 or 1 will cause an additional message to report that exit
612 status, over and above the error message we sent to the parent). */
613 _exit(1);
614 }
615
616 g_strfreev(argv);
617
618 if (fetch_dumpcap_pid && *fork_child > 0)
619 fetch_dumpcap_pid(*fork_child);
620
621 if (data_read_fd != NULL((void*)0)) {
622 *data_read_fd = data_pipe[PIPE_READ];
623 }
624 message_read_fd = sync_pipe[PIPE_READ];
625
626#endif
627
628 /* Parent process - read messages from the child process over the
629 sync pipe. */
630
631 /* Close the write sides of the pipes, so that only the child has them
632 open, and thus they completely close, and thus return to us
633 an EOF indication, if the child closes them (either deliberately
634 or by exiting abnormally). */
635#ifdef _WIN32
636 if (data_read_fd != NULL((void*)0)) {
637 CloseHandle(data_pipe[PIPE_WRITE]);
638 }
639 CloseHandle(sync_pipe[PIPE_WRITE]);
640#else
641 if (data_read_fd != NULL((void*)0)) {
642 ws_closeclose(data_pipe[PIPE_WRITE]);
643 }
644 ws_closeclose(sync_pipe[PIPE_WRITE]);
645#endif
646
647 if (*fork_child == WS_INVALID_PID-1) {
648 /* We couldn't even create the child process. */
649 *msg = ws_strdup_printf("Couldn't create child process: %s", g_strerror(errno))wmem_strdup_printf(((void*)0), "Couldn't create child process: %s"
, g_strerror((*__errno_location ())))
;
650 if (data_read_fd != NULL((void*)0)) {
651 ws_closeclose(*data_read_fd);
652 }
653#ifdef _WIN32
654 if (signal_write_fd != NULL((void*)0)) {
655 ws_closeclose(signal_pipe_write_fd);
656 }
657#endif
658 ws_closeclose(message_read_fd);
659 return -1;
660 }
661
662#ifdef _WIN32
663 *message_read_io = g_io_channel_win32_new_fd(message_read_fd);
664#else
665 *message_read_io = g_io_channel_unix_new(message_read_fd);
666#endif
667 g_io_channel_set_encoding(*message_read_io, NULL((void*)0), NULL((void*)0));
668 g_io_channel_set_buffered(*message_read_io, false0);
669 g_io_channel_set_close_on_unref(*message_read_io, true1);
670
671 /* we might wait for a moment till child is ready, so update screen now */
672 if (update_cb) update_cb();
673 return 0;
674}
675
676/* a new capture run: start a new dumpcap task and hand over parameters through command line */
677bool_Bool
678sync_pipe_start(capture_options *capture_opts, GPtrArray *capture_comments,
679 capture_session *cap_session, info_data_t* cap_data,
680 void (*update_cb)(void))
681{
682#ifdef _WIN32
683 char control_id[ARGV_NUMBER_LEN24];
684#endif
685 GIOChannel *sync_pipe_read_io;
686 int argc;
687 char **argv;
688 int i;
689 unsigned j;
690 interface_options *interface_opts;
691
692 if (capture_opts->ifaces->len > 1)
1
Assuming field 'len' is <= 1
2
Taking false branch
693 capture_opts->use_pcapng = true1;
694 ws_debug("sync_pipe_start")do { if (1) { ws_log_full("Capture", LOG_LEVEL_DEBUG, "capture/capture_sync.c"
, 694, __func__, "sync_pipe_start"); } } while (0)
;
3
Taking true branch
4
Loop condition is false. Exiting loop
695 capture_opts_log(LOG_DOMAIN_CAPTURE"Capture", LOG_LEVEL_DEBUG, capture_opts);
696
697 cap_session->fork_child = WS_INVALID_PID-1;
698 cap_session->capture_opts = capture_opts;
699
700 if (!extcap_init_interfaces(cap_session)) {
5
Assuming the condition is false
6
Taking false branch
701 report_failure("Unable to init extcaps. (tmp fifo already exists?)");
702 return false0;
703 }
704
705 argv = init_pipe_args(&argc);
706 if (!argv) {
7
Assuming 'argv' is non-null
8
Taking false branch
707 /* We don't know where to find dumpcap. */
708 report_failure("We don't know where to find dumpcap.");
709 return false0;
710 }
711
712 if (capture_opts->ifaces->len > 1)
9
Assuming field 'len' is <= 1
10
Taking false branch
713 argv = sync_pipe_add_arg(argv, &argc, "-t");
714
715 argv = sync_pipe_add_arg(argv, &argc, "-F");
716 if (capture_opts->use_pcapng)
11
Assuming field 'use_pcapng' is false
12
Taking false branch
717 argv = sync_pipe_add_arg(argv, &argc, "pcapng");
718 else
719 argv = sync_pipe_add_arg(argv, &argc, "pcap");
13
Calling 'sync_pipe_add_arg'
15
Returned allocated memory
720
721 if (capture_comments != NULL((void*)0)) {
16
Assuming 'capture_comments' is equal to NULL
17
Taking false branch
722 for (j = 0; j < capture_comments->len; j++) {
723 argv = sync_pipe_add_arg(argv, &argc, "--capture-comment");
724 argv = sync_pipe_add_arg(argv, &argc, (char*)g_ptr_array_index(capture_comments, j)((capture_comments)->pdata)[j]);
725 }
726 }
727
728 if (capture_opts->temp_dir) {
18
Assuming field 'temp_dir' is null
19
Taking false branch
729 argv = sync_pipe_add_arg(argv, &argc, "--temp-dir");
730 argv = sync_pipe_add_arg(argv, &argc, capture_opts->temp_dir);
731 }
732
733 if (capture_opts->multi_files_on) {
20
Assuming field 'multi_files_on' is false
21
Taking false branch
734 if (capture_opts->has_autostop_filesize) {
735 char sfilesize[ARGV_NUMBER_LEN24];
736 argv = sync_pipe_add_arg(argv, &argc, "-b");
737 snprintf(sfilesize, ARGV_NUMBER_LEN24, "filesize:%u",capture_opts->autostop_filesize);
738 argv = sync_pipe_add_arg(argv, &argc, sfilesize);
739 }
740
741 if (capture_opts->has_file_duration) {
742 char sfile_duration[ARGV_NUMBER_LEN24];
743 argv = sync_pipe_add_arg(argv, &argc, "-b");
744 snprintf(sfile_duration, ARGV_NUMBER_LEN24, "duration:%f",capture_opts->file_duration);
745 argv = sync_pipe_add_arg(argv, &argc, sfile_duration);
746 }
747
748 if (capture_opts->has_file_interval) {
749 char sfile_interval[ARGV_NUMBER_LEN24];
750 argv = sync_pipe_add_arg(argv, &argc, "-b");
751 snprintf(sfile_interval, ARGV_NUMBER_LEN24, "interval:%d",capture_opts->file_interval);
752 argv = sync_pipe_add_arg(argv, &argc, sfile_interval);
753 }
754
755 if (capture_opts->has_file_packets) {
756 char sfile_packets[ARGV_NUMBER_LEN24];
757 argv = sync_pipe_add_arg(argv, &argc, "-b");
758 snprintf(sfile_packets, ARGV_NUMBER_LEN24, "packets:%d",capture_opts->file_packets);
759 argv = sync_pipe_add_arg(argv, &argc, sfile_packets);
760 }
761
762 if (capture_opts->has_ring_num_files) {
763 char sring_num_files[ARGV_NUMBER_LEN24];
764 argv = sync_pipe_add_arg(argv, &argc, "-b");
765 snprintf(sring_num_files, ARGV_NUMBER_LEN24, "files:%d",capture_opts->ring_num_files);
766 argv = sync_pipe_add_arg(argv, &argc, sring_num_files);
767 }
768
769 if (capture_opts->print_file_names) {
770 char *print_name = g_strdup_printf("printname:%s", capture_opts->print_name_to);
771 argv = sync_pipe_add_arg(argv, &argc, "-b");
772 argv = sync_pipe_add_arg(argv, &argc, print_name);
773 g_free(print_name);
774 }
775
776 if (capture_opts->has_nametimenum) {
777 char nametimenum[ARGV_NUMBER_LEN24];
778 argv = sync_pipe_add_arg(argv, &argc, "-b");
779 snprintf(nametimenum, ARGV_NUMBER_LEN24, "nametimenum:2");
780 argv = sync_pipe_add_arg(argv, &argc, nametimenum);
781 }
782
783 if (capture_opts->has_autostop_files) {
784 char sautostop_files[ARGV_NUMBER_LEN24];
785 argv = sync_pipe_add_arg(argv, &argc, "-a");
786 snprintf(sautostop_files, ARGV_NUMBER_LEN24, "files:%d",capture_opts->autostop_files);
787 argv = sync_pipe_add_arg(argv, &argc, sautostop_files);
788 }
789 } else {
790 if (capture_opts->has_autostop_filesize) {
22
Assuming field 'has_autostop_filesize' is false
23
Taking false branch
791 char sautostop_filesize[ARGV_NUMBER_LEN24];
792 argv = sync_pipe_add_arg(argv, &argc, "-a");
793 snprintf(sautostop_filesize, ARGV_NUMBER_LEN24, "filesize:%u",capture_opts->autostop_filesize);
794 argv = sync_pipe_add_arg(argv, &argc, sautostop_filesize);
795 }
796 }
797
798 if (capture_opts->has_autostop_packets) {
24
Assuming field 'has_autostop_packets' is false
25
Taking false branch
799 char scount[ARGV_NUMBER_LEN24];
800 argv = sync_pipe_add_arg(argv, &argc, "-c");
801 snprintf(scount, ARGV_NUMBER_LEN24, "%d",capture_opts->autostop_packets);
802 argv = sync_pipe_add_arg(argv, &argc, scount);
803 }
804
805 if (capture_opts->has_autostop_duration) {
26
Assuming field 'has_autostop_duration' is false
27
Taking false branch
806 char sautostop_duration[ARGV_NUMBER_LEN24];
807 argv = sync_pipe_add_arg(argv, &argc, "-a");
808 snprintf(sautostop_duration, ARGV_NUMBER_LEN24, "duration:%f",capture_opts->autostop_duration);
809 argv = sync_pipe_add_arg(argv, &argc, sautostop_duration);
810 }
811
812 if (capture_opts->has_autostop_written_packets) {
28
Assuming field 'has_autostop_written_packets' is false
29
Taking false branch
813 char scount[ARGV_NUMBER_LEN24];
814 argv = sync_pipe_add_arg(argv, &argc, "-a");
815 snprintf(scount, ARGV_NUMBER_LEN24, "packets:%d",capture_opts->autostop_written_packets);
816 argv = sync_pipe_add_arg(argv, &argc, scount);
817 }
818
819 if (capture_opts->group_read_access) {
30
Assuming field 'group_read_access' is false
31
Taking false branch
820 argv = sync_pipe_add_arg(argv, &argc, "-g");
821 }
822
823 if (capture_opts->update_interval != DEFAULT_UPDATE_INTERVAL100) {
32
Assuming field 'update_interval' is equal to DEFAULT_UPDATE_INTERVAL
33
Taking false branch
824 char scount[ARGV_NUMBER_LEN24];
825 argv = sync_pipe_add_arg(argv, &argc, "--update-interval");
826 snprintf(scount, ARGV_NUMBER_LEN24, "%d", capture_opts->update_interval);
827 argv = sync_pipe_add_arg(argv, &argc, scount);
828 }
829
830 for (j = 0; j < capture_opts->ifaces->len; j++) {
34
Assuming 'j' is >= field 'len'
35
Loop condition is false. Execution continues on line 939
831 interface_opts = &g_array_index(capture_opts->ifaces, interface_options, j)(((interface_options*) (void *) (capture_opts->ifaces)->
data) [(j)])
;
832
833 argv = sync_pipe_add_arg(argv, &argc, "-i");
834 if (interface_opts->extcap_fifo != NULL((void*)0))
835 {
836#ifdef _WIN32
837 char *pipe = ws_strdup_printf("%s%" PRIuMAX, EXTCAP_PIPE_PREFIX, (uintmax_t)interface_opts->extcap_pipe_h)wmem_strdup_printf(((void*)0), "%s%" "l" "u", "wireshark_extcap"
, (uintmax_t)interface_opts->extcap_pipe_h)
;
838 argv = sync_pipe_add_arg(argv, &argc, pipe);
839 g_free(pipe);
840#else
841 argv = sync_pipe_add_arg(argv, &argc, interface_opts->extcap_fifo);
842#endif
843 /* Add a name for the interface, to put into an IDB. */
844 argv = sync_pipe_add_arg(argv, &argc, "--ifname");
845 argv = sync_pipe_add_arg(argv, &argc, interface_opts->name);
846 }
847 else
848 argv = sync_pipe_add_arg(argv, &argc, interface_opts->name);
849
850 if (interface_opts->descr != NULL((void*)0))
851 {
852 /* Add a description for the interface to put into an IDB and
853 * use for the temporary filename. */
854 argv = sync_pipe_add_arg(argv, &argc, "--ifdescr");
855 argv = sync_pipe_add_arg(argv, &argc, interface_opts->descr);
856 }
857
858 if (interface_opts->cfilter != NULL((void*)0) && strlen(interface_opts->cfilter) != 0) {
859 argv = sync_pipe_add_arg(argv, &argc, "-f");
860 argv = sync_pipe_add_arg(argv, &argc, interface_opts->cfilter);
861 }
862 if (interface_opts->has_snaplen) {
863 char ssnap[ARGV_NUMBER_LEN24];
864 argv = sync_pipe_add_arg(argv, &argc, "-s");
865 snprintf(ssnap, ARGV_NUMBER_LEN24, "%d", interface_opts->snaplen);
866 argv = sync_pipe_add_arg(argv, &argc, ssnap);
867 }
868
869 if (interface_opts->linktype != -1) {
870 const char *linktype = linktype_val_to_name(interface_opts->linktype);
871 if ( linktype != NULL((void*)0) )
872 {
873 argv = sync_pipe_add_arg(argv, &argc, "-y");
874 argv = sync_pipe_add_arg(argv, &argc, linktype);
875 }
876 }
877
878 if (!interface_opts->promisc_mode) {
879 argv = sync_pipe_add_arg(argv, &argc, "-p");
880 }
881
882 if (interface_opts->buffer_size != DEFAULT_CAPTURE_BUFFER_SIZE2) {
883 char buffer_size[ARGV_NUMBER_LEN24];
884 argv = sync_pipe_add_arg(argv, &argc, "-B");
885 if(interface_opts->buffer_size == 0x00)
886 interface_opts->buffer_size = DEFAULT_CAPTURE_BUFFER_SIZE2;
887 snprintf(buffer_size, ARGV_NUMBER_LEN24, "%d", interface_opts->buffer_size);
888 argv = sync_pipe_add_arg(argv, &argc, buffer_size);
889 }
890
891 if (interface_opts->monitor_mode) {
892 argv = sync_pipe_add_arg(argv, &argc, "-I");
893 }
894
895#ifdef HAVE_PCAP_REMOTE
896 if (interface_opts->datatx_udp)
897 argv = sync_pipe_add_arg(argv, &argc, "-u");
898
899 if (!interface_opts->nocap_rpcap)
900 argv = sync_pipe_add_arg(argv, &argc, "-r");
901
902 if (interface_opts->auth_type == CAPTURE_AUTH_PWD) {
903 char sauth[256];
904 argv = sync_pipe_add_arg(argv, &argc, "-A");
905 snprintf(sauth, sizeof(sauth), "%s:%s",
906 interface_opts->auth_username,
907 interface_opts->auth_password);
908 argv = sync_pipe_add_arg(argv, &argc, sauth);
909 }
910#endif
911
912#ifdef HAVE_PCAP_SETSAMPLING
913 if (interface_opts->sampling_method != CAPTURE_SAMP_NONE) {
914 char ssampling[ARGV_NUMBER_LEN24];
915 argv = sync_pipe_add_arg(argv, &argc, "-m");
916 snprintf(ssampling, ARGV_NUMBER_LEN24, "%s:%d",
917 interface_opts->sampling_method == CAPTURE_SAMP_BY_COUNT ? "count" :
918 interface_opts->sampling_method == CAPTURE_SAMP_BY_TIMER ? "timer" :
919 "undef",
920 interface_opts->sampling_param);
921 argv = sync_pipe_add_arg(argv, &argc, ssampling);
922 }
923#endif
924 if (interface_opts->timestamp_type) {
925 argv = sync_pipe_add_arg(argv, &argc, "--time-stamp-type");
926 argv = sync_pipe_add_arg(argv, &argc, interface_opts->timestamp_type);
927 }
928 }
929
930#ifndef DEBUG_CHILD
931#ifdef _WIN32
932 /* pass process id to dumpcap for named signal pipe */
933 argv = sync_pipe_add_arg(argv, &argc, "--signal-pipe");
934 snprintf(control_id, ARGV_NUMBER_LEN24, "%ld", GetCurrentProcessId());
935 argv = sync_pipe_add_arg(argv, &argc, control_id);
936#endif
937#endif
938
939 if (capture_opts->save_file) {
36
Assuming field 'save_file' is null
37
Taking false branch
940 argv = sync_pipe_add_arg(argv, &argc, "-w");
941 argv = sync_pipe_add_arg(argv, &argc, capture_opts->save_file);
942 }
943 for (i = 0; i < argc; i++) {
38
Assuming 'i' is >= 'argc'
39
Loop condition is false. Execution continues on line 946
944 ws_debug("argv[%d]: %s", i, argv[i])do { if (1) { ws_log_full("Capture", LOG_LEVEL_DEBUG, "capture/capture_sync.c"
, 944, __func__, "argv[%d]: %s", i, argv[i]); } } while (0)
;
945 }
946 if (capture_opts->compress_type) {
40
Assuming field 'compress_type' is null
41
Taking false branch
947 argv = sync_pipe_add_arg(argv, &argc, "--compress-type");
948 argv = sync_pipe_add_arg(argv, &argc, capture_opts->compress_type);
949 }
950
951 int ret;
952 char* msg;
953#ifdef _WIN32
954 ret = sync_pipe_open_command(argv, NULL((void*)0), &sync_pipe_read_io, &cap_session->signal_pipe_write_fd,
955 &cap_session->fork_child, capture_opts->ifaces, &msg, update_cb);
956#else
957 ret = sync_pipe_open_command(argv, NULL((void*)0), &sync_pipe_read_io, NULL((void*)0),
42
Potential leak of memory pointed to by 'argv'
958 &cap_session->fork_child, NULL((void*)0), &msg, update_cb);
959#endif
960
961 if (ret == -1) {
962 report_failure("%s", msg);
963 g_free(msg);
964 return false0;
965 }
966
967 /* Parent process - read messages from the child process over the
968 sync pipe. */
969
970 cap_session->fork_child_status = 0;
971 cap_session->cap_data_info = cap_data;
972
973 /* We were able to set up to read the capture file;
974 arrange that our callback be called whenever it's possible
975 to read from the sync pipe, so that it's called when
976 the child process wants to tell us something. */
977
978 /* we have a running capture, now wait for the real capture filename */
979 if (cap_session->pipe_input_id) {
980 g_source_remove(cap_session->pipe_input_id);
981 cap_session->pipe_input_id = 0;
982 }
983 cap_session->pipe_input_id = g_io_add_watch(sync_pipe_read_io, G_IO_IN | G_IO_HUP, pipe_io_cb, cap_session);
984 /* Pipe will be closed when watch is removed */
985 g_io_channel_unref(sync_pipe_read_io);
986
987 return true1;
988}
989
990/*
991 * Close the pipes we're using to read from dumpcap, and wait for it
992 * to exit. On success, *msgp is unchanged, and the exit status of
993 * dumpcap is returned. On failure (which includes "dumpcap exited
994 * due to being killed by a signal or an exception"), *msgp points
995 * to an error message for the failure, and -1 is returned. In the
996 * latter case, *msgp must be freed with g_free().
997 */
998static int
999sync_pipe_close_command(int *data_read_fd, GIOChannel *message_read_io,
1000 ws_process_id *fork_child, char **msgp)
1001{
1002 ws_closeclose(*data_read_fd);
1003 if (message_read_io != NULL((void*)0))
1004 g_io_channel_unref(message_read_io);
1005
1006#ifdef _WIN32
1007 /* XXX - Should we signal the child somehow? */
1008 sync_pipe_kill(*fork_child);
1009#endif
1010
1011 return sync_pipe_wait_for_child(*fork_child, msgp);
1012}
1013
1014/*
1015 * Run dumpcap with the supplied arguments.
1016 *
1017 * On success, *data points to a buffer containing the dumpcap output,
1018 * *primary_msg and *secondary_message are NULL, and 0 is returned; *data
1019 * must be freed with g_free().
1020 *
1021 * On failure, *data is NULL, *primary_msg points to an error message,
1022 * *secondary_msg either points to an additional error message or is
1023 * NULL, and -1 is returned; *primary_msg, and *secondary_msg if not NULL,
1024 * must be freed with g_free().
1025 */
1026static int
1027sync_pipe_run_command_actual(char **argv, char **data, char **primary_msg,
1028 char **secondary_msg, void(*update_cb)(void))
1029{
1030 char *msg;
1031 int data_pipe_read_fd, ret;
1032 GIOChannel *sync_pipe_read_io;
1033 ws_process_id fork_child;
1034 char *wait_msg;
1035 char *buffer = g_malloc(PIPE_BUF_SIZE((512 * 1000)+4) + 1);
1036 ssize_t nread;
1037 char indicator;
1038 int32_t exec_errno = 0;
1039 int primary_msg_len;
1040 char *primary_msg_text;
1041 int secondary_msg_len;
1042 char *secondary_msg_text;
1043 char *combined_msg;
1044 GString *data_buf = NULL((void*)0);
1045 ssize_t count;
1046
1047 if (buffer == NULL((void*)0)) {
1048 /* g_malloc is supposed to terminate the program if this fails, but,
1049 * at least on a RELEASE build, some versions of gcc don't think that
1050 * happens.
1051 */
1052 *primary_msg = ws_strdup_printf("Couldn't allocate memory for dumpcap output buffer: %s",wmem_strdup_printf(((void*)0), "Couldn't allocate memory for dumpcap output buffer: %s"
, g_strerror((*__errno_location ())))
1053 g_strerror(errno))wmem_strdup_printf(((void*)0), "Couldn't allocate memory for dumpcap output buffer: %s"
, g_strerror((*__errno_location ())))
;
1054 *secondary_msg = NULL((void*)0);
1055 *data = NULL((void*)0);
1056 return -1;
1057 }
1058
1059 ret = sync_pipe_open_command(argv, &data_pipe_read_fd, &sync_pipe_read_io, NULL((void*)0),
1060 &fork_child, NULL((void*)0), &msg, update_cb);
1061 if (ret == -1) {
1062 *primary_msg = msg;
1063 *secondary_msg = NULL((void*)0);
1064 *data = NULL((void*)0);
1065 g_free(buffer);
1066 return -1;
1067 }
1068
1069 /*
1070 * We were able to set up to read dumpcap's output. Do so.
1071 *
1072 * First, wait for an SP_ERROR_MSG message or SP_SUCCESS message.
1073 */
1074 do {
1075 nread = pipe_read_block(sync_pipe_read_io, &indicator, SP_MAX_MSG_LEN(512 * 1000),
1076 buffer, primary_msg);
1077 if(nread <= 0) {
1078 /* We got a read error from the sync pipe, or we got no data at
1079 all from the sync pipe, so we're not going to be getting any
1080 data or error message from the child process. Pick up its
1081 exit status, and complain.
1082
1083 We don't have to worry about killing the child, if the sync pipe
1084 returned an error. Usually this error is caused as the child killed
1085 itself while going down. Even in the rare cases that this isn't the
1086 case, the child will get an error when writing to the broken pipe
1087 the next time, cleaning itself up then. */
1088 g_io_channel_unref(sync_pipe_read_io);
1089 ret = sync_pipe_wait_for_child(fork_child, &wait_msg);
1090 if(nread == 0) {
1091 /* We got an EOF from the sync pipe. That means that it exited
1092 before giving us any data to read. If ret is -1, we report
1093 that as a bad exit (e.g., exiting due to a signal); otherwise,
1094 we report it as a premature exit. */
1095 if (ret == -1)
1096 *primary_msg = wait_msg;
1097 else
1098 *primary_msg = g_strdup("Child dumpcap closed sync pipe prematurely")g_strdup_inline ("Child dumpcap closed sync pipe prematurely"
)
;
1099 } else {
1100 /* We got an error from the sync pipe. If ret is -1, report
1101 both the sync pipe I/O error and the wait error. */
1102 if (ret == -1) {
1103 combined_msg = ws_strdup_printf("%s\n\n%s", *primary_msg, wait_msg)wmem_strdup_printf(((void*)0), "%s\n\n%s", *primary_msg, wait_msg
)
;
1104 g_free(*primary_msg);
1105 g_free(wait_msg);
1106 *primary_msg = combined_msg;
1107 }
1108 }
1109 *secondary_msg = NULL((void*)0);
1110 *data = NULL((void*)0);
1111 g_free(buffer);
1112
1113 return -1;
1114 }
1115
1116 /* we got a valid message block from the child, process it */
1117 switch(indicator) {
1118
1119 case SP_EXEC_FAILED'X':
1120 /*
1121 * Exec of dumpcap failed. Get the errno for the failure.
1122 */
1123 if (!ws_strtoi32(buffer, NULL((void*)0), &exec_errno)) {
1124 ws_warning("Invalid errno: %s", buffer)do { if (1) { ws_log_full("Capture", LOG_LEVEL_WARNING, "capture/capture_sync.c"
, 1124, __func__, "Invalid errno: %s", buffer); } } while (0)
;
1125 }
1126
1127 /*
1128 * Pick up the child status.
1129 */
1130 ret = sync_pipe_close_command(&data_pipe_read_fd, sync_pipe_read_io,
1131 &fork_child, &msg);
1132 if (ret == -1) {
1133 /*
1134 * Child process failed unexpectedly, or wait failed; msg is the
1135 * error message.
1136 */
1137 *primary_msg = msg;
1138 *secondary_msg = NULL((void*)0);
1139 } else {
1140 /*
1141 * Child process failed, but returned the expected exit status.
1142 * Return the messages it gave us, and indicate failure.
1143 */
1144 *primary_msg = ws_strdup_printf("Couldn't run dumpcap in child process: %s",wmem_strdup_printf(((void*)0), "Couldn't run dumpcap in child process: %s"
, g_strerror(exec_errno))
1145 g_strerror(exec_errno))wmem_strdup_printf(((void*)0), "Couldn't run dumpcap in child process: %s"
, g_strerror(exec_errno))
;
1146 *secondary_msg = NULL((void*)0);
1147 ret = -1;
1148 }
1149 *data = NULL((void*)0);
1150 break;
1151
1152 case SP_ERROR_MSG'E':
1153 /*
1154 * Error from dumpcap; there will be a primary message and a
1155 * secondary message.
1156 */
1157
1158 /* convert primary message */
1159 pipe_convert_header((unsigned char*)buffer, 4, &indicator, &primary_msg_len);
1160 primary_msg_text = buffer+4;
1161 /* convert secondary message */
1162 pipe_convert_header((unsigned char*)primary_msg_text + primary_msg_len, 4, &indicator,
1163 &secondary_msg_len);
1164 secondary_msg_text = primary_msg_text + primary_msg_len + 4;
1165 /* the capture child will close the sync_pipe, nothing to do */
1166
1167 /*
1168 * Pick up the child status.
1169 */
1170 ret = sync_pipe_close_command(&data_pipe_read_fd, sync_pipe_read_io,
1171 &fork_child, &msg);
1172 if (ret == -1) {
1173 /*
1174 * Child process failed unexpectedly, or wait failed; msg is the
1175 * error message.
1176 */
1177 *primary_msg = msg;
1178 *secondary_msg = NULL((void*)0);
1179 } else {
1180 /*
1181 * Child process failed, but returned the expected exit status.
1182 * Return the messages it gave us, and indicate failure.
1183 */
1184 *primary_msg = g_strdup(primary_msg_text)g_strdup_inline (primary_msg_text);
1185 *secondary_msg = g_strdup(secondary_msg_text)g_strdup_inline (secondary_msg_text);
1186 ret = -1;
1187 }
1188 *data = NULL((void*)0);
1189 break;
1190
1191 case SP_LOG_MSG'L':
1192 /*
1193 * Log from dumpcap; pass to our log
1194 */
1195 sync_pipe_handle_log_msg(buffer);
1196 break;
1197
1198 case SP_SUCCESS'S':
1199 /* read the output from the command */
1200 data_buf = g_string_new("");
1201 while ((count = ws_readread(data_pipe_read_fd, buffer, PIPE_BUF_SIZE((512 * 1000)+4))) > 0) {
1202 buffer[count] = '\0';
1203 g_string_append(data_buf, buffer)(__builtin_constant_p (buffer) ? __extension__ ({ const char *
const __val = (buffer); g_string_append_len_inline (data_buf
, __val, (__val != ((void*)0)) ? (gssize) strlen (((__val) + !
(__val))) : (gssize) -1); }) : g_string_append_len_inline (data_buf
, buffer, (gssize) -1))
;
1204 }
1205
1206 /*
1207 * Pick up the child status.
1208 */
1209 ret = sync_pipe_close_command(&data_pipe_read_fd, sync_pipe_read_io,
1210 &fork_child, &msg);
1211 if (ret == -1) {
1212 /*
1213 * Child process failed unexpectedly, or wait failed; msg is the
1214 * error message.
1215 */
1216 *primary_msg = msg;
1217 *secondary_msg = NULL((void*)0);
1218 g_string_free(data_buf, TRUE)(__builtin_constant_p ((!(0))) ? (((!(0))) ? (g_string_free) (
(data_buf), ((!(0)))) : g_string_free_and_steal (data_buf)) :
(g_string_free) ((data_buf), ((!(0)))))
;
1219 *data = NULL((void*)0);
1220 } else {
1221 /*
1222 * Child process succeeded.
1223 */
1224 *primary_msg = NULL((void*)0);
1225 *secondary_msg = NULL((void*)0);
1226 *data = g_string_free(data_buf, FALSE)(__builtin_constant_p ((0)) ? (((0)) ? (g_string_free) ((data_buf
), ((0))) : g_string_free_and_steal (data_buf)) : (g_string_free
) ((data_buf), ((0))))
;
1227 }
1228 break;
1229
1230 default:
1231 /*
1232 * Pick up the child status.
1233 */
1234 ret = sync_pipe_close_command(&data_pipe_read_fd, sync_pipe_read_io,
1235 &fork_child, &msg);
1236 if (ret == -1) {
1237 /*
1238 * Child process failed unexpectedly, or wait failed; msg is the
1239 * error message.
1240 */
1241 *primary_msg = msg;
1242 *secondary_msg = NULL((void*)0);
1243 } else {
1244 /*
1245 * Child process returned an unknown status.
1246 */
1247 *primary_msg = ws_strdup_printf("dumpcap process gave an unexpected message type: 0x%02x",wmem_strdup_printf(((void*)0), "dumpcap process gave an unexpected message type: 0x%02x"
, indicator)
1248 indicator)wmem_strdup_printf(((void*)0), "dumpcap process gave an unexpected message type: 0x%02x"
, indicator)
;
1249 *secondary_msg = NULL((void*)0);
1250 ret = -1;
1251 }
1252 *data = NULL((void*)0);
1253 break;
1254 }
1255 } while (indicator != SP_SUCCESS'S' && ret != -1);
1256
1257 g_free(buffer);
1258 return ret;
1259}
1260
1261/* centralised logging and timing for sync_pipe_run_command_actual(),
1262* redirects to sync_pipe_run_command_actual()
1263*/
1264static int
1265sync_pipe_run_command(char **argv, char **data, char **primary_msg,
1266 char **secondary_msg, void (*update_cb)(void))
1267{
1268 int ret, i;
1269 int64_t start_time;
1270 double elapsed;
1271 int logging_enabled;
1272
1273 /* check if logging is actually enabled, otherwise don't expend the CPU generating logging */
1274 logging_enabled = ws_log_msg_is_active(WS_LOG_DOMAIN"Capture", LOG_LEVEL_INFO);
1275 if (logging_enabled) {
1276 start_time = g_get_monotonic_time();
1277 ws_debug("sync_pipe_run_command() starts")do { if (1) { ws_log_full("Capture", LOG_LEVEL_DEBUG, "capture/capture_sync.c"
, 1277, __func__, "sync_pipe_run_command() starts"); } } while
(0)
;
1278 for (i=0; argv[i] != 0; i++) {
1279 ws_noisy(" argv[%d]: %s", i, argv[i])do { if (1) { ws_log_full("Capture", LOG_LEVEL_NOISY, "capture/capture_sync.c"
, 1279, __func__, " argv[%d]: %s", i, argv[i]); } } while (0
)
;
1280 }
1281 }
1282 /* do the actual sync pipe run command */
1283 ret = sync_pipe_run_command_actual(argv, data, primary_msg, secondary_msg, update_cb);
1284
1285 if (logging_enabled) {
1286 elapsed = (g_get_monotonic_time() - start_time) / 1e6;
1287
1288 ws_debug("sync_pipe_run_command() ends, taking %.3fs, result=%d", elapsed, ret)do { if (1) { ws_log_full("Capture", LOG_LEVEL_DEBUG, "capture/capture_sync.c"
, 1288, __func__, "sync_pipe_run_command() ends, taking %.3fs, result=%d"
, elapsed, ret); } } while (0)
;
1289
1290 }
1291 return ret;
1292}
1293
1294
1295int
1296sync_interface_set_80211_chan(const char *iface, const char *freq, const char *type,
1297 const char *center_freq1, const char *center_freq2,
1298 char **data, char **primary_msg,
1299 char **secondary_msg, void (*update_cb)(void))
1300{
1301 int argc, ret;
1302 char **argv;
1303 char *opt;
1304
1305 argv = init_pipe_args(&argc);
1306
1307 if (!argv) {
1308 *primary_msg = g_strdup("We don't know where to find dumpcap.")g_strdup_inline ("We don't know where to find dumpcap.");
1309 *secondary_msg = NULL((void*)0);
1310 *data = NULL((void*)0);
1311 return -1;
1312 }
1313
1314 argv = sync_pipe_add_arg(argv, &argc, "-i");
1315 argv = sync_pipe_add_arg(argv, &argc, iface);
1316
1317 if (center_freq2)
1318 opt = ws_strdup_printf("%s,%s,%s,%s", freq, type, center_freq1, center_freq2)wmem_strdup_printf(((void*)0), "%s,%s,%s,%s", freq, type, center_freq1
, center_freq2)
;
1319 else if (center_freq1)
1320 opt = ws_strdup_printf("%s,%s,%s", freq, type, center_freq1)wmem_strdup_printf(((void*)0), "%s,%s,%s", freq, type, center_freq1
)
;
1321 else if (type)
1322 opt = ws_strdup_printf("%s,%s", freq, type)wmem_strdup_printf(((void*)0), "%s,%s", freq, type);
1323 else
1324 opt = g_strdup(freq)g_strdup_inline (freq);
1325
1326 if (!opt) {
1327 *primary_msg = g_strdup("Out of mem.")g_strdup_inline ("Out of mem.");
1328 *secondary_msg = NULL((void*)0);
1329 *data = NULL((void*)0);
1330 return -1;
1331 }
1332
1333 argv = sync_pipe_add_arg(argv, &argc, "-k");
1334 argv = sync_pipe_add_arg(argv, &argc, opt);
1335
1336 ret = sync_pipe_run_command(argv, data, primary_msg, secondary_msg, update_cb);
1337 g_free(opt);
1338 return ret;
1339}
1340
1341/*
1342 * Get the list of interfaces using dumpcap.
1343 *
1344 * On success, *data points to a buffer containing the dumpcap output,
1345 * *primary_msg and *secondary_msg are NULL, and 0 is returned. *data
1346 * must be freed with g_free().
1347 *
1348 * On failure, *data is NULL, *primary_msg points to an error message,
1349 * *secondary_msg either points to an additional error message or is
1350 * NULL, and -1 is returned; *primary_msg, and *secondary_msg if not NULL,
1351 * must be freed with g_free().
1352 */
1353int
1354sync_interface_list_open(char **data, char **primary_msg,
1355 char **secondary_msg, void (*update_cb)(void))
1356{
1357 int argc;
1358 char **argv;
1359 int ret;
1360
1361 ws_debug("sync_interface_list_open")do { if (1) { ws_log_full("Capture", LOG_LEVEL_DEBUG, "capture/capture_sync.c"
, 1361, __func__, "sync_interface_list_open"); } } while (0)
;
1362
1363 argv = init_pipe_args(&argc);
1364
1365 if (!argv) {
1366 *primary_msg = g_strdup("We don't know where to find dumpcap..")g_strdup_inline ("We don't know where to find dumpcap..");
1367 *secondary_msg = NULL((void*)0);
1368 *data = NULL((void*)0);
1369 return -1;
1370 }
1371
1372 /* Ask for the interface list */
1373 argv = sync_pipe_add_arg(argv, &argc, "-D");
1374
1375 ret = sync_pipe_run_command(argv, data, primary_msg, secondary_msg, update_cb);
1376 return ret;
1377}
1378
1379/*
1380 * Get the capabilities of an interface using dumpcap.
1381 *
1382 * On success, *data points to a buffer containing the dumpcap output,
1383 * *primary_msg and *secondary_msg are NULL, and 0 is returned. *data
1384 * must be freed with g_free().
1385 *
1386 * On failure, *data is NULL, *primary_msg points to an error message,
1387 * *secondary_msg either points to an additional error message or is
1388 * NULL, and -1 is returned; *primary_msg, and *secondary_msg if not NULL,
1389 * must be freed with g_free().
1390 */
1391int
1392sync_if_capabilities_open(const char *ifname, bool_Bool monitor_mode, const char* auth,
1393 char **data, char **primary_msg,
1394 char **secondary_msg, void (*update_cb)(void))
1395{
1396 int argc;
1397 char **argv;
1398 int ret;
1399
1400 ws_debug("sync_if_capabilities_open")do { if (1) { ws_log_full("Capture", LOG_LEVEL_DEBUG, "capture/capture_sync.c"
, 1400, __func__, "sync_if_capabilities_open"); } } while (0)
;
1401
1402 argv = init_pipe_args(&argc);
1403
1404 if (!argv) {
1405 *primary_msg = g_strdup("We don't know where to find dumpcap.")g_strdup_inline ("We don't know where to find dumpcap.");
1406 *secondary_msg = NULL((void*)0);
1407 *data = NULL((void*)0);
1408 return -1;
1409 }
1410
1411 /* Ask for the interface capabilities */
1412 argv = sync_pipe_add_arg(argv, &argc, "-i");
1413 argv = sync_pipe_add_arg(argv, &argc, ifname);
1414 argv = sync_pipe_add_arg(argv, &argc, "-L");
1415 argv = sync_pipe_add_arg(argv, &argc, "--list-time-stamp-types");
1416 if (monitor_mode)
1417 argv = sync_pipe_add_arg(argv, &argc, "-I");
1418 if (auth) {
1419 argv = sync_pipe_add_arg(argv, &argc, "-A");
1420 argv = sync_pipe_add_arg(argv, &argc, auth);
1421 }
1422
1423 ret = sync_pipe_run_command(argv, data, primary_msg, secondary_msg, update_cb);
1424 return ret;
1425}
1426
1427int
1428sync_if_list_capabilities_open(GList *if_queries,
1429 char **data, char **primary_msg,
1430 char **secondary_msg, void (*update_cb)(void))
1431{
1432 int argc;
1433 char **argv;
1434 int ret;
1435 if_cap_query_t *if_cap_query;
1436
1437 ws_debug("sync_if_list_capabilities_open")do { if (1) { ws_log_full("Capture", LOG_LEVEL_DEBUG, "capture/capture_sync.c"
, 1437, __func__, "sync_if_list_capabilities_open"); } } while
(0)
;
1438
1439 argv = init_pipe_args(&argc);
1440
1441 if (!argv) {
1442 *primary_msg = g_strdup("We don't know where to find dumpcap.")g_strdup_inline ("We don't know where to find dumpcap.");
1443 *secondary_msg = NULL((void*)0);
1444 *data = NULL((void*)0);
1445 return -1;
1446 }
1447
1448 for (GList *li = if_queries; li != NULL((void*)0); li = g_list_next(li)((li) ? (((GList *)(li))->next) : ((void*)0))) {
1449 if_cap_query = (if_cap_query_t*)li->data;
1450 /* Ask for the interface capabilities */
1451 argv = sync_pipe_add_arg(argv, &argc, "-i");
1452 argv = sync_pipe_add_arg(argv, &argc, if_cap_query->name);
1453 if (if_cap_query->monitor_mode)
1454 argv = sync_pipe_add_arg(argv, &argc, "-I");
1455 if (if_cap_query->auth_username && if_cap_query->auth_password) {
1456 char sauth[256];
1457 argv = sync_pipe_add_arg(argv, &argc, "-A");
1458 snprintf(sauth, sizeof(sauth), "%s:%s",
1459 if_cap_query->auth_username,
1460 if_cap_query->auth_password);
1461 argv = sync_pipe_add_arg(argv, &argc, sauth);
1462 }
1463 }
1464 argv = sync_pipe_add_arg(argv, &argc, "-L");
1465 argv = sync_pipe_add_arg(argv, &argc, "--list-time-stamp-types");
1466
1467 ret = sync_pipe_run_command(argv, data, primary_msg, secondary_msg, update_cb);
1468 return ret;
1469}
1470
1471/*
1472 * Start getting interface statistics using dumpcap. On success, read_fd
1473 * contains the file descriptor for the pipe's stdout, *msg is unchanged,
1474 * and zero is returned. On failure, *msg will point to an error message
1475 * that must be g_free()d, and -1 will be returned.
1476 * If data is not NULL, then it will also be set to point to a JSON
1477 * serialization of the list of local interfaces and their capabilities.
1478 */
1479int
1480sync_interface_stats_open(int *data_read_fd, ws_process_id *fork_child, char **data, char **msg, void (*update_cb)(void))
1481{
1482 int argc;
1483 char **argv;
1484 int ret;
1485 GIOChannel *message_read_io;
1486 char *wait_msg;
1487 char *buffer = g_malloc(PIPE_BUF_SIZE((512 * 1000)+4) + 1);
1488 ssize_t nread;
1489 char indicator;
1490 int32_t exec_errno = 0;
1491 int primary_msg_len;
1492 char *primary_msg_text;
1493 int secondary_msg_len;
1494 /*char *secondary_msg_text;*/
1495 char *combined_msg;
1496
1497 ws_debug("sync_interface_stats_open")do { if (1) { ws_log_full("Capture", LOG_LEVEL_DEBUG, "capture/capture_sync.c"
, 1497, __func__, "sync_interface_stats_open"); } } while (0)
;
1498
1499 argv = init_pipe_args(&argc);
1500
1501 if (!argv) {
1502 *msg = g_strdup("We don't know where to find dumpcap.")g_strdup_inline ("We don't know where to find dumpcap.");
1503 g_free(buffer);
1504 return -1;
1505 }
1506
1507 /* Ask for the interface statistics */
1508 argv = sync_pipe_add_arg(argv, &argc, "-S");
1509
1510 /* If requested, ask for the interface list and capabilities. */
1511 if (data) {
1512 argv = sync_pipe_add_arg(argv, &argc, "-D");
1513 argv = sync_pipe_add_arg(argv, &argc, "-L");
1514 }
1515
1516#ifndef DEBUG_CHILD
1517#ifdef _WIN32
1518 argv = sync_pipe_add_arg(argv, &argc, "--signal-pipe");
1519 ret = create_dummy_signal_pipe(msg);
1520 if (ret == -1) {
1521 g_free(buffer);
1522 return -1;
1523 }
1524 argv = sync_pipe_add_arg(argv, &argc, dummy_control_id);
1525#endif
1526#endif
1527 ret = sync_pipe_open_command(argv, data_read_fd, &message_read_io, NULL((void*)0),
1528 fork_child, NULL((void*)0), msg, update_cb);
1529 if (ret == -1) {
1530 g_free(buffer);
1531 return -1;
1532 }
1533
1534 /*
1535 * We were able to set up to read dumpcap's output. Do so.
1536 *
1537 * First, wait for an SP_ERROR_MSG message or SP_SUCCESS message.
1538 */
1539 do {
1540 nread = pipe_read_block(message_read_io, &indicator, SP_MAX_MSG_LEN(512 * 1000),
1541 buffer, msg);
1542 if(nread <= 0) {
1543 /* We got a read error from the sync pipe, or we got no data at
1544 all from the sync pipe, so we're not going to be getting any
1545 data or error message from the child process. Pick up its
1546 exit status, and complain.
1547
1548 We don't have to worry about killing the child, if the sync pipe
1549 returned an error. Usually this error is caused as the child killed
1550 itself while going down. Even in the rare cases that this isn't the
1551 case, the child will get an error when writing to the broken pipe
1552 the next time, cleaning itself up then. */
1553 g_io_channel_unref(message_read_io);
1554 ws_closeclose(*data_read_fd);
1555 ret = sync_pipe_wait_for_child(*fork_child, &wait_msg);
1556 if(nread == 0) {
1557 /* We got an EOF from the sync pipe. That means that it exited
1558 before giving us any data to read. If ret is -1, we report
1559 that as a bad exit (e.g., exiting due to a signal); otherwise,
1560 we report it as a premature exit. */
1561 if (ret == -1)
1562 *msg = wait_msg;
1563 else
1564 *msg = g_strdup("Child dumpcap closed sync pipe prematurely")g_strdup_inline ("Child dumpcap closed sync pipe prematurely"
)
;
1565 } else {
1566 /* We got an error from the sync pipe. If ret is -1, report
1567 both the sync pipe I/O error and the wait error. */
1568 if (ret == -1) {
1569 combined_msg = ws_strdup_printf("%s\n\n%s", *msg, wait_msg)wmem_strdup_printf(((void*)0), "%s\n\n%s", *msg, wait_msg);
1570 g_free(*msg);
1571 g_free(wait_msg);
1572 *msg = combined_msg;
1573 }
1574 }
1575 g_free(buffer);
1576 return -1;
1577 }
1578
1579 /* we got a valid message block from the child, process it */
1580 switch(indicator) {
1581
1582 case SP_EXEC_FAILED'X':
1583 /*
1584 * Exec of dumpcap failed. Get the errno for the failure.
1585 */
1586 if (!ws_strtoi32(buffer, NULL((void*)0), &exec_errno)) {
1587 ws_warning("Invalid errno: %s", buffer)do { if (1) { ws_log_full("Capture", LOG_LEVEL_WARNING, "capture/capture_sync.c"
, 1587, __func__, "Invalid errno: %s", buffer); } } while (0)
;
1588 }
1589 *msg = ws_strdup_printf("Couldn't run dumpcap in child process: %s",wmem_strdup_printf(((void*)0), "Couldn't run dumpcap in child process: %s"
, g_strerror(exec_errno))
1590 g_strerror(exec_errno))wmem_strdup_printf(((void*)0), "Couldn't run dumpcap in child process: %s"
, g_strerror(exec_errno))
;
1591
1592 /*
1593 * Pick up the child status.
1594 */
1595 char *close_msg = NULL((void*)0);
1596 sync_pipe_close_command(data_read_fd, message_read_io,
1597 fork_child, &close_msg);
1598 /*
1599 * Ignore the error from sync_pipe_close_command, presumably the one
1600 * returned by the child is more pertinent to what went wrong.
1601 */
1602 g_free(close_msg);
1603 ret = -1;
1604 break;
1605
1606 case SP_ERROR_MSG'E':
1607 /*
1608 * Error from dumpcap; there will be a primary message and a
1609 * secondary message.
1610 */
1611
1612 /* convert primary message */
1613 pipe_convert_header((unsigned char*)buffer, 4, &indicator, &primary_msg_len);
1614 primary_msg_text = buffer+4;
1615 /* convert secondary message */
1616 pipe_convert_header((unsigned char*)primary_msg_text + primary_msg_len, 4, &indicator,
1617 &secondary_msg_len);
1618 /*secondary_msg_text = primary_msg_text + primary_msg_len + 4;*/
1619 /* the capture child will close the sync_pipe, nothing to do */
1620
1621 /*
1622 * Pick up the child status.
1623 */
1624 ret = sync_pipe_close_command(data_read_fd, message_read_io,
1625 fork_child, msg);
1626 if (ret == -1) {
1627 /*
1628 * Child process failed unexpectedly, or wait failed; msg is the
1629 * error message.
1630 */
1631 } else if (ret == WS_EXIT_NO_INTERFACES12) {
1632 /*
1633 * No interfaces were found. If that's not the
1634 * result of an error when fetching the local
1635 * interfaces, let the user know.
1636 */
1637 *msg = g_strdup(primary_msg_text)g_strdup_inline (primary_msg_text);
1638 } else {
1639 /*
1640 * Child process failed, but returned the expected exit status.
1641 * Return the messages it gave us, and indicate failure.
1642 */
1643 *msg = g_strdup(primary_msg_text)g_strdup_inline (primary_msg_text);
1644 ret = -1;
1645 }
1646 g_free(buffer);
1647 return ret;
1648
1649 case SP_LOG_MSG'L':
1650 /*
1651 * Log from dumpcap; pass to our log
1652 */
1653 sync_pipe_handle_log_msg(buffer);
1654 break;
1655
1656 case SP_IFACE_LIST'I':
1657 /*
1658 * Dumpcap giving us the interface list
1659 */
1660
1661 /* convert primary message */
1662 if (data) {
1663 *data = g_strdup(buffer)g_strdup_inline (buffer);
1664 }
1665 break;
1666
1667 case SP_SUCCESS'S':
1668 /* Close the message pipe. */
1669 g_io_channel_unref(message_read_io);
1670 break;
1671
1672 default:
1673 /*
1674 * Pick up the child status.
1675 */
1676 ret = sync_pipe_close_command(data_read_fd, message_read_io,
1677 fork_child, msg);
1678 if (ret == -1) {
1679 /*
1680 * Child process failed unexpectedly, or wait failed; msg is the
1681 * error message.
1682 */
1683 } else {
1684 /*
1685 * Child process returned an unknown status.
1686 */
1687 *msg = ws_strdup_printf("dumpcap process gave an unexpected message type: 0x%02x",wmem_strdup_printf(((void*)0), "dumpcap process gave an unexpected message type: 0x%02x"
, indicator)
1688 indicator)wmem_strdup_printf(((void*)0), "dumpcap process gave an unexpected message type: 0x%02x"
, indicator)
;
1689 ret = -1;
1690 }
1691 break;
1692 }
1693 } while (indicator != SP_SUCCESS'S' && ret != -1);
1694
1695 g_free(buffer);
1696 return ret;
1697}
1698
1699/* Close down the stats process */
1700int
1701sync_interface_stats_close(int *read_fd, ws_process_id *fork_child, char **msg)
1702{
1703#ifdef _WIN32
1704 CloseHandle(dummy_signal_pipe);
1705 dummy_signal_pipe = NULL((void*)0);
1706#else
1707 /*
1708 * Don't bother waiting for the child. sync_pipe_close_command
1709 * does this for us on Windows.
1710 */
1711 sync_pipe_kill(*fork_child);
1712#endif
1713 return sync_pipe_close_command(read_fd, NULL((void*)0), fork_child, msg);
1714}
1715
1716/* read a number of bytes from a pipe */
1717/* (blocks until enough bytes read or an error occurs) */
1718static ssize_t
1719pipe_read_bytes(GIOChannel *pipe_io, char *bytes, size_t required, char **msg)
1720{
1721 GError *err = NULL((void*)0);
1722 size_t newly;
1723 size_t offset = 0;
1724
1725 while(required) {
1726 g_io_channel_read_chars(pipe_io, &bytes[offset], required, &newly, &err);
1727 if (err != NULL((void*)0)) {
1728 ws_debug("read from pipe %p: error(%u): %s", pipe_io, err->code, err->message)do { if (1) { ws_log_full("Capture", LOG_LEVEL_DEBUG, "capture/capture_sync.c"
, 1728, __func__, "read from pipe %p: error(%u): %s", pipe_io
, err->code, err->message); } } while (0)
;
1729 *msg = ws_strdup_printf("Error reading from sync pipe: %s", err->message)wmem_strdup_printf(((void*)0), "Error reading from sync pipe: %s"
, err->message)
;
1730 g_clear_error(&err);
1731 return -1;
1732 }
1733 if (newly == 0) {
1734 /* EOF */
1735 ws_debug("read from pipe %p: EOF (capture closed?)", pipe_io)do { if (1) { ws_log_full("Capture", LOG_LEVEL_DEBUG, "capture/capture_sync.c"
, 1735, __func__, "read from pipe %p: EOF (capture closed?)",
pipe_io); } } while (0)
;
1736 *msg = 0;
1737 return offset;
1738 }
1739
1740 required -= newly;
1741 offset += newly;
1742 }
1743
1744 *msg = NULL((void*)0);
1745 return offset;
1746}
1747
1748/*
1749 * Read a line from a pipe; similar to fgets, but doesn't block.
1750 *
1751 * XXX - just stops reading if there's nothing to be read right now;
1752 * that could conceivably mean that you don't get a complete line.
1753 */
1754int
1755sync_pipe_gets_nonblock(int pipe_fd, char *bytes, int max) {
1756 ssize_t newly;
1757 int offset = -1;
1758
1759 while(offset < max - 1) {
1760 offset++;
1761 if (! ws_pipe_data_available(pipe_fd))
1762 break;
1763 newly = ws_readread(pipe_fd, &bytes[offset], 1);
1764 if (newly == 0) {
1765 /* EOF - not necessarily an error */
1766 break;
1767 } else if (newly == -1) {
1768 /* error */
1769 ws_debug("read from pipe %d: error(%u): %s", pipe_fd, errno, g_strerror(errno))do { if (1) { ws_log_full("Capture", LOG_LEVEL_DEBUG, "capture/capture_sync.c"
, 1769, __func__, "read from pipe %d: error(%u): %s", pipe_fd
, (*__errno_location ()), g_strerror((*__errno_location ())))
; } } while (0)
;
1770 return -1;
1771 } else if (bytes[offset] == '\n') {
1772 break;
1773 }
1774 }
1775
1776 if (offset >= 0)
1777 bytes[offset] = '\0';
1778
1779 return offset;
1780}
1781
1782
1783/* convert header values (indicator and 3-byte length) */
1784static void
1785pipe_convert_header(const unsigned char *header, int header_len _U___attribute__((unused)), char *indicator, int *block_len) {
1786
1787 ws_assert(header_len == 4)do { if ((1) && !(header_len == 4)) ws_log_fatal_full
("Capture", LOG_LEVEL_ERROR, "capture/capture_sync.c", 1787, __func__
, "assertion failed: %s", "header_len == 4"); } while (0)
;
1788
1789 /* convert header values */
1790 *indicator = header[0];
1791 *block_len = (header[1]&0xFF)<<16 | (header[2]&0xFF)<<8 | (header[3]&0xFF);
1792}
1793
1794/* read a message from the sending pipe in the standard format
1795 (1-byte message indicator, 3-byte message length (excluding length
1796 and indicator field), and the rest is the message) */
1797static ssize_t
1798pipe_read_block(GIOChannel *pipe_io, char *indicator, int len, char *msg,
1799 char **err_msg)
1800{
1801 int required;
1802 ssize_t newly;
1803 char header[4];
1804
1805 /* read header (indicator and 3-byte length) */
1806 newly = pipe_read_bytes(pipe_io, header, 4, err_msg);
1807 if(newly != 4) {
1808 if (newly == 0) {
1809 /*
1810 * Immediate EOF; if the capture child exits normally, this
1811 * is an "I'm done" indication, so don't report it as an
1812 * error.
1813 */
1814 ws_debug("read %p got an EOF", pipe_io)do { if (1) { ws_log_full("Capture", LOG_LEVEL_DEBUG, "capture/capture_sync.c"
, 1814, __func__, "read %p got an EOF", pipe_io); } } while (
0)
;
1815 return 0;
1816 }
1817 ws_debug("read %p failed to read header: %lu", pipe_io, (long)newly)do { if (1) { ws_log_full("Capture", LOG_LEVEL_DEBUG, "capture/capture_sync.c"
, 1817, __func__, "read %p failed to read header: %lu", pipe_io
, (long)newly); } } while (0)
;
1818 if (newly != -1) {
1819 /*
1820 * Short read, but not an immediate EOF.
1821 */
1822 *err_msg = ws_strdup_printf("Premature EOF reading from sync pipe: got only %ld bytes",wmem_strdup_printf(((void*)0), "Premature EOF reading from sync pipe: got only %ld bytes"
, (long)newly)
1823 (long)newly)wmem_strdup_printf(((void*)0), "Premature EOF reading from sync pipe: got only %ld bytes"
, (long)newly)
;
1824 }
1825 return -1;
1826 }
1827
1828 /* convert header values */
1829 pipe_convert_header((unsigned char*)header, 4, indicator, &required);
1830
1831 /* only indicator with no value? */
1832 if(required == 0) {
1833 ws_debug("read %p indicator: %c empty value", pipe_io, *indicator)do { if (1) { ws_log_full("Capture", LOG_LEVEL_DEBUG, "capture/capture_sync.c"
, 1833, __func__, "read %p indicator: %c empty value", pipe_io
, *indicator); } } while (0)
;
1834 return 4;
1835 }
1836
1837 /* does the data fit into the given buffer? */
1838 if(required > len) {
1839 size_t bytes_read;
1840 GError *err = NULL((void*)0);
1841 ws_debug("read %p length error, required %d > len %d, header: 0x%02x 0x%02x 0x%02x 0x%02x",do { if (1) { ws_log_full("Capture", LOG_LEVEL_DEBUG, "capture/capture_sync.c"
, 1843, __func__, "read %p length error, required %d > len %d, header: 0x%02x 0x%02x 0x%02x 0x%02x"
, pipe_io, required, len, header[0], header[1], header[2], header
[3]); } } while (0)
1842 pipe_io, required, len,do { if (1) { ws_log_full("Capture", LOG_LEVEL_DEBUG, "capture/capture_sync.c"
, 1843, __func__, "read %p length error, required %d > len %d, header: 0x%02x 0x%02x 0x%02x 0x%02x"
, pipe_io, required, len, header[0], header[1], header[2], header
[3]); } } while (0)
1843 header[0], header[1], header[2], header[3])do { if (1) { ws_log_full("Capture", LOG_LEVEL_DEBUG, "capture/capture_sync.c"
, 1843, __func__, "read %p length error, required %d > len %d, header: 0x%02x 0x%02x 0x%02x 0x%02x"
, pipe_io, required, len, header[0], header[1], header[2], header
[3]); } } while (0)
;
1844
1845 /* we have a problem here, try to read some more bytes from the pipe to debug where the problem really is */
1846 g_io_channel_read_chars(pipe_io, msg, len, &bytes_read, &err);
1847 if (err != NULL((void*)0)) { /* error */
1848 ws_debug("read from pipe %p: error(%u): %s", pipe_io, err->code, err->message)do { if (1) { ws_log_full("Capture", LOG_LEVEL_DEBUG, "capture/capture_sync.c"
, 1848, __func__, "read from pipe %p: error(%u): %s", pipe_io
, err->code, err->message); } } while (0)
;
1849 g_clear_error(&err);
1850 }
1851 *err_msg = ws_strdup_printf("Message %c from dumpcap with length %d > buffer size %d! Partial message: %s",wmem_strdup_printf(((void*)0), "Message %c from dumpcap with length %d > buffer size %d! Partial message: %s"
, *indicator, required, len, msg)
1852 *indicator, required, len, msg)wmem_strdup_printf(((void*)0), "Message %c from dumpcap with length %d > buffer size %d! Partial message: %s"
, *indicator, required, len, msg)
;
1853 return -1;
1854 }
1855 len = required;
1856
1857 /* read the actual block data */
1858 newly = pipe_read_bytes(pipe_io, msg, required, err_msg);
1859 if(newly != required) {
1860 if (newly != -1) {
1861 *err_msg = ws_strdup_printf("Unknown message from dumpcap reading data, try to show it as a string: %s",wmem_strdup_printf(((void*)0), "Unknown message from dumpcap reading data, try to show it as a string: %s"
, msg)
1862 msg)wmem_strdup_printf(((void*)0), "Unknown message from dumpcap reading data, try to show it as a string: %s"
, msg)
;
1863 }
1864 return -1;
1865 }
1866
1867 /* XXX If message is "2part", the msg probably won't be sent to debug log correctly */
1868 ws_debug("read %p ok indicator: %c len: %u msg: %s", pipe_io, *indicator, len, msg)do { if (1) { ws_log_full("Capture", LOG_LEVEL_DEBUG, "capture/capture_sync.c"
, 1868, __func__, "read %p ok indicator: %c len: %u msg: %s",
pipe_io, *indicator, len, msg); } } while (0)
;
1869 *err_msg = NULL((void*)0);
1870 return newly + 4;
1871}
1872
1873
1874/* There's stuff to read from the sync pipe, meaning the child has sent
1875 us a message, or the sync pipe has closed, meaning the child has
1876 closed it (perhaps because it exited). */
1877static gboolean
1878sync_pipe_input_cb(GIOChannel *pipe_io, capture_session *cap_session)
1879{
1880 int ret;
1881 char *buffer = g_malloc(SP_MAX_MSG_LEN(512 * 1000) + 1);
1882 ssize_t nread;
1883 char indicator;
1884 int32_t exec_errno = 0;
1885 int primary_len;
1886 char *primary_msg;
1887 int secondary_len;
1888 char *secondary_msg;
1889 char *wait_msg, *combined_msg;
1890 uint32_t npackets = 0;
1891
1892 nread = pipe_read_block(pipe_io, &indicator, SP_MAX_MSG_LEN(512 * 1000), buffer,
1893 &primary_msg);
1894 if(nread <= 0) {
1895 /* We got a read error, or a bad message, or an EOF, from the sync pipe.
1896
1897 If we got a read error or a bad message, nread is -1 and
1898 primary_msg is set to point to an error message. We don't
1899 have to worry about killing the child; usually this error
1900 is caused as the child killed itself while going down.
1901 Even in the rare cases that this isn't the case, the child
1902 will get an error when writing to the broken pipe the next time,
1903 cleaning itself up then.
1904
1905 If we got an EOF, nread is 0 and primary_msg isn't set. This
1906 is an indication that the capture is finished. */
1907 ret = sync_pipe_wait_for_child(cap_session->fork_child, &wait_msg);
1908 if(nread == 0) {
1909 /* We got an EOF from the sync pipe. That means that the capture
1910 child exited, and not in the middle of a message; we treat
1911 that as an indication that it's done, and only report an
1912 error if ret is -1, in which case wait_msg is the error
1913 message. */
1914 if (ret == -1)
1915 primary_msg = wait_msg;
1916 } else {
1917 /* We got an error from the sync pipe. If ret is -1, report
1918 both the sync pipe I/O error and the wait error. */
1919 if (ret == -1) {
1920 combined_msg = ws_strdup_printf("%s\n\n%s", primary_msg, wait_msg)wmem_strdup_printf(((void*)0), "%s\n\n%s", primary_msg, wait_msg
)
;
1921 g_free(primary_msg);
1922 g_free(wait_msg);
1923 primary_msg = combined_msg;
1924 }
1925 }
1926
1927 /* No more child process. */
1928 cap_session->fork_child = WS_INVALID_PID-1;
1929 cap_session->fork_child_status = ret;
1930
1931#ifdef _WIN32
1932 ws_closeclose(cap_session->signal_pipe_write_fd);
1933#endif
1934 cap_session->capture_opts->closed_msg = primary_msg;
1935 if (extcap_session_stop(cap_session)) {
1936 capture_process_finished(cap_session);
1937 } else {
1938 extcap_request_stop(cap_session);
1939 }
1940 g_free(buffer);
1941 return false0;
1942 }
1943
1944 /* we got a valid message block from the child, process it */
1945 switch(indicator) {
1946 case SP_FILE'F':
1947 if(!cap_session->new_file(cap_session, buffer)) {
1948 ws_debug("file failed, closing capture")do { if (1) { ws_log_full("Capture", LOG_LEVEL_DEBUG, "capture/capture_sync.c"
, 1948, __func__, "file failed, closing capture"); } } while (
0)
;
1949
1950 /* We weren't able to open the new capture file; user has been
1951 alerted. The sync pipe will close after we return false. */
1952
1953 /* The child has sent us a filename which we couldn't open.
1954
1955 This could mean that the child is creating and deleting files
1956 (ring buffer mode) faster than we can handle it.
1957
1958 That should only be the case for very fast file switches;
1959 We can't do much more than telling the child to stop.
1960 (This is the "emergency brake" if the user e.g. wants to
1961 switch files every second).
1962
1963 This can also happen if the user specified "-", meaning
1964 "standard output", as the capture file. */
1965 sync_pipe_stop(cap_session);
1966 cap_session->closed(cap_session, NULL((void*)0));
1967 g_free(buffer);
1968 return false0;
1969 }
1970 break;
1971 case SP_PACKET_COUNT'P':
1972 if (!ws_strtou32(buffer, NULL((void*)0), &npackets)) {
1973 ws_warning("Invalid packets number: %s", buffer)do { if (1) { ws_log_full("Capture", LOG_LEVEL_WARNING, "capture/capture_sync.c"
, 1973, __func__, "Invalid packets number: %s", buffer); } } while
(0)
;
1974 }
1975 ws_debug("new packets %u", npackets)do { if (1) { ws_log_full("Capture", LOG_LEVEL_DEBUG, "capture/capture_sync.c"
, 1975, __func__, "new packets %u", npackets); } } while (0)
;
1976 cap_session->count += npackets;
1977 cap_session->new_packets(cap_session, npackets);
1978 break;
1979 case SP_EXEC_FAILED'X':
1980 /*
1981 * Exec of dumpcap failed. Get the errno for the failure.
1982 */
1983 if (!ws_strtoi32(buffer, NULL((void*)0), &exec_errno)) {
1984 ws_warning("Invalid errno: %s", buffer)do { if (1) { ws_log_full("Capture", LOG_LEVEL_WARNING, "capture/capture_sync.c"
, 1984, __func__, "Invalid errno: %s", buffer); } } while (0)
;
1985 }
1986 primary_msg = ws_strdup_printf("Couldn't run dumpcap in child process: %s",wmem_strdup_printf(((void*)0), "Couldn't run dumpcap in child process: %s"
, g_strerror(exec_errno))
1987 g_strerror(exec_errno))wmem_strdup_printf(((void*)0), "Couldn't run dumpcap in child process: %s"
, g_strerror(exec_errno))
;
1988 cap_session->error(cap_session, primary_msg, NULL((void*)0));
1989 /* the capture child will close the sync_pipe, nothing to do for now */
1990 /* (an error message doesn't mean we have to stop capturing) */
1991 break;
1992 case SP_ERROR_MSG'E':
1993 /* convert primary message */
1994 pipe_convert_header((unsigned char*)buffer, 4, &indicator, &primary_len);
1995 primary_msg = buffer+4;
1996 /* convert secondary message */
1997 pipe_convert_header((unsigned char*)primary_msg + primary_len, 4, &indicator, &secondary_len);
1998 secondary_msg = primary_msg + primary_len + 4;
1999 /* message output */
2000 cap_session->error(cap_session, primary_msg, secondary_msg);
2001 /* the capture child will close the sync_pipe, nothing to do for now */
2002 /* (an error message doesn't mean we have to stop capturing) */
2003 break;
2004 case SP_LOG_MSG'L':
2005 /*
2006 * Log from dumpcap; pass to our log
2007 */
2008 sync_pipe_handle_log_msg(buffer);
2009 break;
2010 case SP_BAD_FILTER'B': {
2011 const char *message=NULL((void*)0);
2012 uint32_t indx = 0;
2013 const char* end;
2014
2015 if (ws_strtou32(buffer, &end, &indx) && end[0] == ':') {
2016 message = end + 1;
2017 }
2018
2019 cap_session->cfilter_error(cap_session, indx, message);
2020 /* the capture child will close the sync_pipe, nothing to do for now */
2021 break;
2022 }
2023 case SP_DROPS'D': {
2024 const char *name = NULL((void*)0);
2025 const char* end;
2026 uint32_t num = 0;
2027
2028 if (ws_strtou32(buffer, &end, &num) && end[0] == ':') {
2029 name = end + 1;
2030 }
2031
2032 cap_session->drops(cap_session, num, name);
2033 break;
2034 }
2035 default:
2036 if (g_ascii_isprint(indicator)((g_ascii_table[(guchar) (indicator)] & G_ASCII_PRINT) !=
0)
)
2037 ws_warning("Unknown indicator '%c'", indicator)do { if (1) { ws_log_full("Capture", LOG_LEVEL_WARNING, "capture/capture_sync.c"
, 2037, __func__, "Unknown indicator '%c'", indicator); } } while
(0)
;
2038 else
2039 ws_warning("Unknown indicator '\\x%02x", indicator)do { if (1) { ws_log_full("Capture", LOG_LEVEL_WARNING, "capture/capture_sync.c"
, 2039, __func__, "Unknown indicator '\\x%02x", indicator); }
} while (0)
;
2040 break;
2041 }
2042
2043 g_free(buffer);
2044 return true1;
2045}
2046
2047
2048
2049/*
2050 * dumpcap is exiting; wait for it to exit. On success, *msgp is
2051 * unchanged, and the exit status of dumpcap is returned. On
2052 * failure (which includes "dumpcap exited due to being killed by
2053 * a signal or an exception"), *msgp points to an error message
2054 * for the failure, and -1 is returned. In the latter case, *msgp
2055 * must be freed with g_free().
2056 */
2057static int
2058sync_pipe_wait_for_child(ws_process_id fork_child, char **msgp)
2059{
2060 int fork_child_status;
2061#ifndef _WIN32
2062 int retry_waitpid = 3;
2063#endif
2064 int ret = -1;
2065 int64_t start_time;
2066 double elapsed;
2067
2068 start_time = g_get_monotonic_time();
2069
2070 ws_debug("wait till child closed")do { if (1) { ws_log_full("Capture", LOG_LEVEL_DEBUG, "capture/capture_sync.c"
, 2070, __func__, "wait till child closed"); } } while (0)
;
2071 ws_assert(fork_child != WS_INVALID_PID)do { if ((1) && !(fork_child != -1)) ws_log_fatal_full
("Capture", LOG_LEVEL_ERROR, "capture/capture_sync.c", 2071, __func__
, "assertion failed: %s", "fork_child != -1"); } while (0)
;
2072
2073 *msgp = NULL((void*)0); /* assume no error */
2074#ifdef _WIN32
2075 if (_cwait(&fork_child_status, (intptr_t) fork_child, _WAIT_CHILD) == -1) {
2076 *msgp = ws_strdup_printf("Error from cwait(): %s", g_strerror(errno))wmem_strdup_printf(((void*)0), "Error from cwait(): %s", g_strerror
((*__errno_location ())))
;
2077 ret = -1;
2078 } else {
2079 /*
2080 * The child exited; return its exit status. Do not treat this as
2081 * an error.
2082 */
2083 ret = fork_child_status;
2084 if ((fork_child_status & 0xC0000000) == ERROR_SEVERITY_ERROR) {
2085 /* Probably an exception code */
2086 *msgp = ws_strdup_printf("Child dumpcap process died: %s",wmem_strdup_printf(((void*)0), "Child dumpcap process died: %s"
, win32strexception(fork_child_status))
2087 win32strexception(fork_child_status))wmem_strdup_printf(((void*)0), "Child dumpcap process died: %s"
, win32strexception(fork_child_status))
;
2088 ret = -1;
2089 }
2090 }
2091#else
2092 while (--retry_waitpid >= 0) {
2093 if (waitpid(fork_child, &fork_child_status, 0) != -1) {
2094 /* waitpid() succeeded */
2095 if (WIFEXITED(fork_child_status)(((fork_child_status) & 0x7f) == 0)) {
2096 /*
2097 * The child exited; return its exit status. Do not treat this as
2098 * an error.
2099 */
2100 ret = WEXITSTATUS(fork_child_status)(((fork_child_status) & 0xff00) >> 8);
2101 } else if (WIFSTOPPED(fork_child_status)(((fork_child_status) & 0xff) == 0x7f)) {
2102 /* It stopped, rather than exiting. "Should not happen." */
2103 *msgp = ws_strdup_printf("Child dumpcap process stopped: %s",wmem_strdup_printf(((void*)0), "Child dumpcap process stopped: %s"
, sync_pipe_signame((((fork_child_status) & 0xff00) >>
8)))
2104 sync_pipe_signame(WSTOPSIG(fork_child_status)))wmem_strdup_printf(((void*)0), "Child dumpcap process stopped: %s"
, sync_pipe_signame((((fork_child_status) & 0xff00) >>
8)))
;
2105 ret = -1;
2106 } else if (WIFSIGNALED(fork_child_status)(((signed char) (((fork_child_status) & 0x7f) + 1) >>
1) > 0)
) {
2107 /* It died with a signal. */
2108 *msgp = ws_strdup_printf("Child dumpcap process died: %s%s",wmem_strdup_printf(((void*)0), "Child dumpcap process died: %s%s"
, sync_pipe_signame(((fork_child_status) & 0x7f)), ((fork_child_status
) & 0x80) ? " - core dumped" : "")
2109 sync_pipe_signame(WTERMSIG(fork_child_status)),wmem_strdup_printf(((void*)0), "Child dumpcap process died: %s%s"
, sync_pipe_signame(((fork_child_status) & 0x7f)), ((fork_child_status
) & 0x80) ? " - core dumped" : "")
2110 WCOREDUMP(fork_child_status) ? " - core dumped" : "")wmem_strdup_printf(((void*)0), "Child dumpcap process died: %s%s"
, sync_pipe_signame(((fork_child_status) & 0x7f)), ((fork_child_status
) & 0x80) ? " - core dumped" : "")
;
2111 ret = -1;
2112 } else {
2113 /* What? It had to either have exited, or stopped, or died with
2114 a signal; what happened here? */
2115 *msgp = ws_strdup_printf("Bad status from waitpid(): %#o",wmem_strdup_printf(((void*)0), "Bad status from waitpid(): %#o"
, fork_child_status)
2116 fork_child_status)wmem_strdup_printf(((void*)0), "Bad status from waitpid(): %#o"
, fork_child_status)
;
2117 ret = -1;
2118 }
2119 } else {
2120 /* waitpid() failed */
2121 if (errno(*__errno_location ()) == EINTR4) {
2122 /*
2123 * Signal interrupted waitpid().
2124 *
2125 * If it's SIGALRM, we just want to keep waiting, in case
2126 * there's some timer using it (e.g., in a GUI toolkit).
2127 *
2128 * If you ^C TShark (or Wireshark), that should deliver
2129 * SIGINT to dumpcap as well. dumpcap catches SIGINT,
2130 * and should clean up and exit, so we should eventually
2131 * see that and clean up and terminate.
2132 *
2133 * If we're sent a SIGTERM, we should (and do) catch it,
2134 * and TShark, at least, calls sync_pipe_stop(). which
2135 * kills dumpcap, so we should eventually see that and
2136 * clean up and terminate.
2137 */
2138 ws_warning("waitpid returned EINTR. retrying.")do { if (1) { ws_log_full("Capture", LOG_LEVEL_WARNING, "capture/capture_sync.c"
, 2138, __func__, "waitpid returned EINTR. retrying."); } } while
(0)
;
2139 continue;
2140 } else if (errno(*__errno_location ()) == ECHILD10) {
2141 /*
2142 * The process identified by fork_child either doesn't
2143 * exist any more or isn't our child process (anymore?).
2144 *
2145 * echld might have already reaped the child.
2146 */
2147 ret = fetch_dumpcap_pid ? 0 : -1;
2148 } else {
2149 /* Unknown error. */
2150 *msgp = ws_strdup_printf("Error from waitpid(): %s", g_strerror(errno))wmem_strdup_printf(((void*)0), "Error from waitpid(): %s", g_strerror
((*__errno_location ())))
;
2151 ret = -1;
2152 }
2153 }
2154 break;
2155 }
2156#endif
2157
2158 elapsed = (g_get_monotonic_time() - start_time) / 1e6;
2159 ws_debug("capture child closed after %.3fs", elapsed)do { if (1) { ws_log_full("Capture", LOG_LEVEL_DEBUG, "capture/capture_sync.c"
, 2159, __func__, "capture child closed after %.3fs", elapsed
); } } while (0)
;
2160 return ret;
2161}
2162
2163
2164#ifndef _WIN32
2165/* convert signal to corresponding name */
2166static const char *
2167sync_pipe_signame(int sig)
2168{
2169 const char *sigmsg;
2170 static char sigmsg_buf[6+1+3+1];
2171
2172 switch (sig) {
2173
2174 case SIGHUP1:
2175 sigmsg = "Hangup";
2176 break;
2177
2178 case SIGINT2:
2179 sigmsg = "Interrupted";
2180 break;
2181
2182 case SIGQUIT3:
2183 sigmsg = "Quit";
2184 break;
2185
2186 case SIGILL4:
2187 sigmsg = "Illegal instruction";
2188 break;
2189
2190 case SIGTRAP5:
2191 sigmsg = "Trace trap";
2192 break;
2193
2194 case SIGABRT6:
2195 sigmsg = "Abort";
2196 break;
2197
2198 case SIGFPE8:
2199 sigmsg = "Arithmetic exception";
2200 break;
2201
2202 case SIGKILL9:
2203 sigmsg = "Killed";
2204 break;
2205
2206 case SIGBUS7:
2207 sigmsg = "Bus error";
2208 break;
2209
2210 case SIGSEGV11:
2211 sigmsg = "Segmentation violation";
2212 break;
2213
2214 /* http://metalab.unc.edu/pub/Linux/docs/HOWTO/GCC-HOWTO
2215 Linux is POSIX compliant. These are not POSIX-defined signals ---
2216 ISO/IEC 9945-1:1990 (IEEE Std 1003.1-1990), paragraph B.3.3.1.1 sez:
2217
2218 ``The signals SIGBUS, SIGEMT, SIGIOT, SIGTRAP, and SIGSYS
2219 were omitted from POSIX.1 because their behavior is
2220 implementation dependent and could not be adequately catego-
2221 rized. Conforming implementations may deliver these sig-
2222 nals, but must document the circumstances under which they
2223 are delivered and note any restrictions concerning their
2224 delivery.''
2225
2226 So we only check for SIGSYS on those systems that happen to
2227 implement them (a system can be POSIX-compliant and implement
2228 them, it's just that POSIX doesn't *require* a POSIX-compliant
2229 system to implement them).
2230 */
2231
2232#ifdef SIGSYS31
2233 case SIGSYS31:
2234 sigmsg = "Bad system call";
2235 break;
2236#endif
2237
2238 case SIGPIPE13:
2239 sigmsg = "Broken pipe";
2240 break;
2241
2242 case SIGALRM14:
2243 sigmsg = "Alarm clock";
2244 break;
2245
2246 case SIGTERM15:
2247 sigmsg = "Terminated";
2248 break;
2249
2250 default:
2251 /* Returning a static buffer is ok in the context we use it here */
2252 snprintf(sigmsg_buf, sizeof sigmsg_buf, "Signal %d", sig);
2253 sigmsg = sigmsg_buf;
2254 break;
2255 }
2256 return sigmsg;
2257}
2258#endif
2259
2260
2261#ifdef _WIN32
2262
2263static int create_dummy_signal_pipe(char **msg) {
2264 char *dummy_signal_pipe_name;
2265
2266 if (dummy_signal_pipe != NULL((void*)0)) return 0;
2267
2268 if (!dummy_control_id) {
2269 dummy_control_id = ws_strdup_printf("%ld.dummy", GetCurrentProcessId())wmem_strdup_printf(((void*)0), "%ld.dummy", GetCurrentProcessId
())
;
2270 }
2271
2272 /* Create the signal pipe */
2273 dummy_signal_pipe_name = ws_strdup_printf(SIGNAL_PIPE_FORMAT, dummy_control_id)wmem_strdup_printf(((void*)0), SIGNAL_PIPE_FORMAT, dummy_control_id
)
;
2274 dummy_signal_pipe = CreateNamedPipe(utf_8to16(dummy_signal_pipe_name),
2275 PIPE_ACCESS_OUTBOUND, PIPE_TYPE_BYTE, 1, 65535, 65535, 0, NULL((void*)0));
2276 g_free(dummy_signal_pipe_name);
2277 if (dummy_signal_pipe == INVALID_HANDLE_VALUE) {
2278 *msg = ws_strdup_printf("Couldn't create signal pipe: %s",wmem_strdup_printf(((void*)0), "Couldn't create signal pipe: %s"
, win32strerror(GetLastError()))
2279 win32strerror(GetLastError()))wmem_strdup_printf(((void*)0), "Couldn't create signal pipe: %s"
, win32strerror(GetLastError()))
;
2280 return -1;
2281 }
2282 return 0;
2283}
2284
2285/* tell the child through the signal pipe that we want to quit the capture */
2286static void
2287signal_pipe_capquit_to_child(capture_session *cap_session)
2288{
2289 const char quit_msg[] = "QUIT";
2290 int ret;
2291
2292 ws_debug("signal_pipe_capquit_to_child")do { if (1) { ws_log_full("Capture", LOG_LEVEL_DEBUG, "capture/capture_sync.c"
, 2292, __func__, "signal_pipe_capquit_to_child"); } } while (
0)
;
2293
2294 /* it doesn't matter *what* we send here, the first byte will stop the capture */
2295 /* simply sending a "QUIT" string */
2296 /*sync_pipe_write_string_msg(cap_session->signal_pipe_write_fd, SP_QUIT, quit_msg);*/
2297 ret = ws_writewrite(cap_session->signal_pipe_write_fd, quit_msg, sizeof quit_msg);
2298 if(ret == -1) {
2299 ws_warning("%d header: error %s", cap_session->signal_pipe_write_fd, win32strerror(GetLastError()))do { if (1) { ws_log_full("Capture", LOG_LEVEL_WARNING, "capture/capture_sync.c"
, 2299, __func__, "%d header: error %s", cap_session->signal_pipe_write_fd
, win32strerror(GetLastError())); } } while (0)
;
2300 }
2301}
2302#endif
2303
2304
2305/* user wants to stop the capture run */
2306void
2307sync_pipe_stop(capture_session *cap_session)
2308{
2309 if (cap_session->fork_child != WS_INVALID_PID-1) {
2310#ifndef _WIN32
2311 /* send the SIGINT signal to close the capture child gracefully. */
2312 int sts = kill(cap_session->fork_child, SIGINT2);
2313 if (sts != 0) {
2314 ws_warning("Sending SIGINT to child failed: %s\n", g_strerror(errno))do { if (1) { ws_log_full("Capture", LOG_LEVEL_WARNING, "capture/capture_sync.c"
, 2314, __func__, "Sending SIGINT to child failed: %s\n", g_strerror
((*__errno_location ()))); } } while (0)
;
2315 }
2316#else
2317#define STOP_SLEEP_TIME 500 /* ms */
2318 DWORD status;
2319
2320 /* First, use the special signal pipe to try to close the capture child
2321 * gracefully.
2322 */
2323 signal_pipe_capquit_to_child(cap_session);
2324
2325 /* Next, wait for the process to exit on its own */
2326 status = WaitForSingleObject((HANDLE) cap_session->fork_child, STOP_SLEEP_TIME);
2327
2328 /* Force the issue. */
2329 if (status != WAIT_OBJECT_0) {
2330 ws_warning("sync_pipe_stop: forcing child to exit")do { if (1) { ws_log_full("Capture", LOG_LEVEL_WARNING, "capture/capture_sync.c"
, 2330, __func__, "sync_pipe_stop: forcing child to exit"); }
} while (0)
;
2331 sync_pipe_kill(cap_session->fork_child);
2332 }
2333#endif
2334 }
2335}
2336
2337
2338/* Wireshark has to exit, force the capture child to close */
2339void
2340sync_pipe_kill(ws_process_id fork_child)
2341{
2342 if (fork_child != WS_INVALID_PID-1) {
2343#ifndef _WIN32
2344 int sts = kill(fork_child, SIGTERM15); /* SIGTERM so it can clean up if necessary */
2345 if (sts != 0) {
2346 ws_warning("Sending SIGTERM to child failed: %s\n", g_strerror(errno))do { if (1) { ws_log_full("Capture", LOG_LEVEL_WARNING, "capture/capture_sync.c"
, 2346, __func__, "Sending SIGTERM to child failed: %s\n", g_strerror
((*__errno_location ()))); } } while (0)
;
2347 }
2348#else
2349 /* Remark: This is not the preferred method of closing a process!
2350 * the clean way would be getting the process id of the child process,
2351 * then getting window handle hWnd of that process (using EnumChildWindows),
2352 * and then do a SendMessage(hWnd, WM_CLOSE, 0, 0)
2353 *
2354 * Unfortunately, I don't know how to get the process id from the
2355 * handle. OpenProcess will get an handle (not a window handle)
2356 * from the process ID; it will not get a window handle from the
2357 * process ID. (How could it? A process can have more than one
2358 * window. For that matter, a process might have *no* windows,
2359 * as a process running dumpcap, the normal child process program,
2360 * probably does.)
2361 *
2362 * Hint: GenerateConsoleCtrlEvent() will only work if both processes are
2363 * running in the same console; that's not necessarily the case for
2364 * us, as we might not be running in a console.
2365 * And this also will require to have the process id.
2366 */
2367 TerminateProcess((HANDLE) (fork_child), 0);
2368
2369#endif
2370 }
2371}
2372
2373void capture_sync_set_fetch_dumpcap_pid_cb(void(*cb)(ws_process_id pid)) {
2374 fetch_dumpcap_pid = cb;
2375}
2376
2377#endif /* HAVE_LIBPCAP */