Bug Summary

File:builds/wireshark/wireshark/capture/capture_sync.c
Warning:line 963, column 9
Potential leak of memory pointed to by 'argv'

Annotated Source Code

Press '?' to see keyboard shortcuts

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