Bug Summary

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