Bug Summary

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