Bug Summary

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