Bug Summary

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