Bug Summary

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