Bug Summary

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