Bug Summary

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