Bug Summary

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