regen pidl all: rm epan/dissectors/pidl/*-stamp; pushd epan/dissectors/pidl/ && make...
[wireshark-sm.git] / capture / capture_sync.c
blobd60511b47cd7ec3f11518ce98df0791263b1402b
1 /* capture_sync.c
2 * Synchronisation between Wireshark capture parent and child instances
4 * Wireshark - Network traffic analyzer
5 * By Gerald Combs <gerald@wireshark.org>
6 * Copyright 1998 Gerald Combs
8 * SPDX-License-Identifier: GPL-2.0-or-later
9 */
11 #include "config.h"
12 #define WS_LOG_DOMAIN LOG_DOMAIN_CAPTURE
14 #include <wireshark.h>
16 #ifdef HAVE_LIBPCAP
18 #include <glib.h>
19 #include <stdio.h>
20 #include <stdlib.h>
22 #include <signal.h>
24 #include <ws_exit_codes.h>
26 #include <wsutil/application_flavor.h>
27 #include <wsutil/strtoi.h>
28 #include <wsutil/ws_assert.h>
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-unix.h>
36 #endif
38 #ifdef HAVE_SYS_WAIT_H
39 # include <sys/wait.h>
40 #endif
42 #include "capture/capture-pcap-util.h"
44 #ifndef _WIN32
46 * Define various POSIX macros (and, in the case of WCOREDUMP, non-POSIX
47 * macros) on UNIX systems that don't have them.
49 #ifndef WIFEXITED
50 # define WIFEXITED(status) (((status) & 0177) == 0)
51 #endif
52 #ifndef WIFSTOPPED
53 # define WIFSTOPPED(status) (((status) & 0177) == 0177)
54 #endif
55 #ifndef WIFSIGNALED
56 # define WIFSIGNALED(status) (!WIFSTOPPED(status) && !WIFEXITED(status))
57 #endif
58 #ifndef WEXITSTATUS
59 # define WEXITSTATUS(status) ((status) >> 8)
60 #endif
61 #ifndef WTERMSIG
62 # define WTERMSIG(status) ((status) & 0177)
63 #endif
64 #ifndef WCOREDUMP
65 # define WCOREDUMP(status) ((status) & 0200)
66 #endif
67 #ifndef WSTOPSIG
68 # define WSTOPSIG(status) ((status) >> 8)
69 #endif
70 #endif /* _WIN32 */
72 #include <epan/packet.h>
73 #include <epan/prefs.h>
75 #include "file.h"
77 #include "ui/capture.h"
78 #include <capture/capture_sync.h>
80 #include "sync_pipe.h"
82 #ifdef _WIN32
83 #include "capture/capture-wpcap.h"
84 #endif
86 #include "ui/ws_ui_util.h"
88 #include <wsutil/filesystem.h>
89 #include <wsutil/file_util.h>
90 #include <wsutil/report_message.h>
91 #include "extcap.h"
93 #ifdef _WIN32
94 #include <process.h> /* For spawning child process */
95 #endif
97 #include <wsutil/ws_pipe.h>
99 #ifdef _WIN32
100 static int create_dummy_signal_pipe(char **msg);
101 static HANDLE dummy_signal_pipe; /* Dummy named pipe which lets the child check for a dropped connection */
102 static char *dummy_control_id;
103 #else
104 static const char *sync_pipe_signame(int);
105 #endif
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.
111 #define PIPE_BUF_SIZE (SP_MAX_MSG_LEN+4)
113 static gboolean sync_pipe_input_cb(GIOChannel *pipe_io, capture_session *cap_session);
114 static int sync_pipe_wait_for_child(ws_process_id fork_child, char **msgp);
115 static void pipe_convert_header(const unsigned char *header, int header_len, char *indicator, int *block_len);
116 static ssize_t pipe_read_block(GIOChannel *pipe_io, char *indicator, int len, char *msg,
117 char **err_msg);
119 static void (*fetch_dumpcap_pid)(ws_process_id);
121 void
122 capture_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)
127 cap_session->cf = cf;
128 cap_session->fork_child = WS_INVALID_PID; /* 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 = false;
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;
151 void capture_process_finished(capture_session *cap_session)
153 capture_options *capture_opts = cap_session->capture_opts;
154 interface_options *interface_opts;
155 GString *message;
156 unsigned i;
158 if (!extcap_session_stop(cap_session)) {
159 /* At least one extcap process did not fully finish yet, wait for it */
160 return;
163 if (cap_session->fork_child != WS_INVALID_PID) {
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 = false;
167 sync_pipe_stop(cap_session);
169 /* Wait for child process to end, session is not closed yet */
170 return;
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);
177 if (interface_opts->if_type != IF_EXTCAP) {
178 continue;
181 if ((interface_opts->extcap_stderr != NULL) &&
182 (interface_opts->extcap_stderr->len > 0)) {
183 if (message->len > 0) {
184 g_string_append(message, "\n");
186 g_string_append(message, "Error from extcap pipe: ");
187 g_string_append(message, interface_opts->extcap_stderr->str);
191 cap_session->closed(cap_session, message->str);
192 g_string_free(message, TRUE);
193 g_free(capture_opts->closed_msg);
194 capture_opts->closed_msg = NULL;
195 capture_opts->stop_after_extcaps = false;
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.
202 static char **
203 sync_pipe_add_arg(char **args, int *argc, const char *arg)
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 *));
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);
214 /* Now bump the count. */
215 (*argc)++;
217 /* We overwrite the NULL pointer; put it back right after the
218 element we added. */
219 args[*argc] = NULL;
221 return args;
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.)
229 static void
230 sync_pipe_handle_log_msg(const char *buffer) {
231 const char *log_msg = NULL;
232 const char* end;
233 uint32_t level = 0;
235 if (ws_strtou32(buffer, &end, &level) && end[0] == ':') {
236 log_msg = end + 1;
238 ws_log(LOG_DOMAIN_CAPCHILD, level, "%s", log_msg);
241 /* Initialize an argument list and add dumpcap to it. */
242 static char **
243 init_pipe_args(int *argc) {
244 char *exename;
245 char **argv;
247 /* Find the absolute path of the dumpcap executable. */
248 exename = get_executable_path("dumpcap");
249 if (exename == NULL) {
250 return NULL;
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;
259 /* Make that the first argument in the argument list (argv[0]). */
260 argv = sync_pipe_add_arg(argv, argc, exename);
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.)
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, 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;
274 argv = sync_pipe_add_arg(argv, argc, "--application-flavor");
275 argv = sync_pipe_add_arg(argv, argc, application_flavor_name_lower());
277 /* sync_pipe_add_arg strdupes exename, so we should free our copy */
278 g_free(exename);
280 return argv;
283 static gboolean
284 pipe_io_cb(GIOChannel *pipe_io, GIOCondition condition _U_, void * user_data)
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;
291 return G_SOURCE_CONTINUE;
295 * Open two pipes to dumpcap with the supplied arguments, one for its
296 * standard output and one for its standard error.
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.
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().
306 #define ARGV_NUMBER_LEN 24
307 static int
308 #ifdef _WIN32
309 sync_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
314 sync_pipe_open_command(char **argv, int *data_read_fd,
315 GIOChannel **message_read_io, int *signal_write_fd _U_,
316 ws_process_id *fork_child, GArray *ifaces _U_,
317 char **msg, void(*update_cb)(void))
318 #endif
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_LEN];
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_LEN];
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;
345 if (data_read_fd != NULL) {
346 *data_read_fd = -1;
348 *message_read_io = NULL;
349 ws_debug("sync_pipe_open_command");
351 if (!msg) {
352 /* We can't return anything */
353 g_strfreev(argv);
354 #ifdef _WIN32
355 g_string_free(args, TRUE);
356 #endif
357 return -1;
360 #ifdef _WIN32
361 /* init SECURITY_ATTRIBUTES */
362 sa.nLength = sizeof(SECURITY_ATTRIBUTES);
363 sa.bInheritHandle = false;
364 sa.lpSecurityDescriptor = NULL;
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)) {
369 /* Couldn't create the message pipe between parent and child. */
370 *msg = ws_strdup_printf("Couldn't create sync pipe: %s",
371 win32strerror(GetLastError()));
372 g_strfreev(argv);
373 return -1;
377 * Associate a C run-time file handle with the Windows HANDLE for the
378 * read side of the message pipe.
380 * (See http://www.flounder.com/handles.htm for information on various
381 * types of file handle in C/C++ on Windows.)
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));
386 g_strfreev(argv);
387 CloseHandle(sync_pipe[PIPE_READ]);
388 CloseHandle(sync_pipe[PIPE_WRITE]);
389 return -1;
392 if (data_read_fd != NULL) {
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)) {
396 /* Couldn't create the message pipe between parent and child. */
397 *msg = ws_strdup_printf("Couldn't create data pipe: %s",
398 win32strerror(GetLastError()));
399 g_strfreev(argv);
400 ws_close(message_read_fd); /* Should close sync_pipe[PIPE_READ] */
401 CloseHandle(sync_pipe[PIPE_WRITE]);
402 return -1;
406 * Associate a C run-time file handle with the Windows HANDLE for the
407 * read side of the data pipe.
409 * (See http://www.flounder.com/handles.htm for information on various
410 * types of file handle in C/C++ on Windows.)
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));
415 g_strfreev(argv);
416 CloseHandle(data_pipe[PIPE_READ]);
417 CloseHandle(data_pipe[PIPE_WRITE]);
418 ws_close(message_read_fd); /* Should close sync_pipe[PIPE_READ] */
419 CloseHandle(sync_pipe[PIPE_WRITE]);
420 return -1;
424 if (signal_write_fd != NULL) {
425 /* Create the signal pipe */
426 snprintf(control_id, ARGV_NUMBER_LEN, "%ld", GetCurrentProcessId());
427 signal_pipe_name = ws_strdup_printf(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);
430 g_free(signal_pipe_name);
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",
435 win32strerror(GetLastError()));
436 g_strfreev(argv);
437 ws_close(message_read_fd); /* Should close sync_pipe[PIPE_READ] */
438 CloseHandle(sync_pipe[PIPE_WRITE]);
439 return -1;
443 * Associate a C run-time file handle with the Windows HANDLE for the
444 * read side of the message pipe.
446 * (See http://www.flounder.com/handles.htm for information on various
447 * types of file handle in C/C++ on Windows.)
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));
453 g_strfreev(argv);
454 ws_close(message_read_fd); /* Should close sync_pipe[PIPE_READ] */
455 CloseHandle(sync_pipe[PIPE_WRITE]);
456 CloseHandle(signal_pipe);
457 return -1;
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 */
472 if (data_read_fd == NULL) {
473 si.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
474 si.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
475 } else {
476 si.hStdInput = NULL; /* handle for named pipe*/
477 si.hStdOutput = data_pipe[PIPE_WRITE];
479 si.hStdError = GetStdHandle(STD_ERROR_HANDLE);
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
494 int argc = g_strv_length(argv);
495 argv = sync_pipe_add_arg(argv, &argc, "-Z");
496 snprintf(sync_id, ARGV_NUMBER_LEN, "%ld", PtrToLong(sync_pipe[PIPE_WRITE]));
497 argv = sync_pipe_add_arg(argv, &argc, sync_id);
498 #endif
500 if (ifaces) {
501 for (j = 0; j < ifaces->len; j++) {
502 interface_opts = &g_array_index(ifaces, interface_options, j);
503 if (interface_opts->extcap_fifo != NULL) {
504 i_handles++;
508 handles = g_new(HANDLE, 3 + i_handles);
509 i_handles = 0;
510 if (si.hStdInput) {
511 handles[i_handles++] = si.hStdInput;
513 if (si.hStdOutput && (si.hStdOutput != si.hStdInput)) {
514 handles[i_handles++] = si.hStdOutput;
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);
520 if (interface_opts->extcap_fifo != NULL) {
521 handles[i_handles++] = interface_opts->extcap_pipe_h;
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, ' '); /* don't prepend a space before the path!!! */
531 quoted_arg = protect_arg(argv[i]);
532 g_string_append(args, quoted_arg);
533 g_free(quoted_arg);
536 /* call dumpcap */
537 if(!win32_create_process(argv[0], args->str, NULL, NULL, i_handles, handles,
538 CREATE_NEW_CONSOLE, NULL, NULL, &si, &pi)) {
539 *msg = ws_strdup_printf("Couldn't run %s in child process: %s",
540 args->str, win32strerror(GetLastError()));
541 if (data_read_fd) {
542 ws_close(*data_read_fd); /* Should close data_pipe[PIPE_READ] */
543 CloseHandle(data_pipe[PIPE_WRITE]);
544 } else {
545 ws_close(signal_pipe_write_fd);
547 ws_close(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);
551 g_free(handles);
552 return -1;
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);
559 g_free(handles);
561 if (signal_write_fd != NULL) {
562 *signal_write_fd = signal_pipe_write_fd;
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));
569 g_strfreev(argv);
570 return -1;
573 if (data_read_fd != NULL) {
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));
578 g_strfreev(argv);
579 ws_close(sync_pipe[PIPE_READ]);
580 ws_close(sync_pipe[PIPE_WRITE]);
581 return -1;
585 if ((*fork_child = fork()) == 0) {
587 * Child process - run dumpcap with the right arguments to make
588 * it just capture with the specified capture parameters
590 if (data_read_fd != NULL) {
591 dup2(data_pipe[PIPE_WRITE], 1);
592 ws_close(data_pipe[PIPE_READ]);
593 ws_close(data_pipe[PIPE_WRITE]);
595 ws_close(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_LEN, "%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, errno);
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);
616 g_strfreev(argv);
618 if (fetch_dumpcap_pid && *fork_child > 0)
619 fetch_dumpcap_pid(*fork_child);
621 if (data_read_fd != NULL) {
622 *data_read_fd = data_pipe[PIPE_READ];
624 message_read_fd = sync_pipe[PIPE_READ];
626 #endif
628 /* Parent process - read messages from the child process over the
629 sync pipe. */
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) {
637 CloseHandle(data_pipe[PIPE_WRITE]);
639 CloseHandle(sync_pipe[PIPE_WRITE]);
640 #else
641 if (data_read_fd != NULL) {
642 ws_close(data_pipe[PIPE_WRITE]);
644 ws_close(sync_pipe[PIPE_WRITE]);
645 #endif
647 if (*fork_child == WS_INVALID_PID) {
648 /* We couldn't even create the child process. */
649 *msg = ws_strdup_printf("Couldn't create child process: %s", g_strerror(errno));
650 if (data_read_fd != NULL) {
651 ws_close(*data_read_fd);
653 #ifdef _WIN32
654 if (signal_write_fd != NULL) {
655 ws_close(signal_pipe_write_fd);
657 #endif
658 ws_close(message_read_fd);
659 return -1;
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, NULL);
668 g_io_channel_set_buffered(*message_read_io, false);
669 g_io_channel_set_close_on_unref(*message_read_io, true);
671 /* we might wait for a moment till child is ready, so update screen now */
672 if (update_cb) update_cb();
673 return 0;
676 /* a new capture run: start a new dumpcap task and hand over parameters through command line */
677 bool
678 sync_pipe_start(capture_options *capture_opts, GPtrArray *capture_comments,
679 capture_session *cap_session, info_data_t* cap_data,
680 void (*update_cb)(void))
682 #ifdef _WIN32
683 size_t i_handles = 0;
684 char control_id[ARGV_NUMBER_LEN];
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;
693 if (capture_opts->ifaces->len > 1)
694 capture_opts->use_pcapng = true;
695 ws_debug("sync_pipe_start");
696 capture_opts_log(LOG_DOMAIN_CAPTURE, LOG_LEVEL_DEBUG, capture_opts);
698 cap_session->fork_child = WS_INVALID_PID;
699 cap_session->capture_opts = capture_opts;
701 if (!extcap_init_interfaces(cap_session)) {
702 report_failure("Unable to init extcaps. (tmp fifo already exists?)");
703 return false;
706 argv = init_pipe_args(&argc);
707 if (!argv) {
708 /* We don't know where to find dumpcap. */
709 report_failure("We don't know where to find dumpcap.");
710 return false;
713 if (capture_opts->ifaces->len > 1)
714 argv = sync_pipe_add_arg(argv, &argc, "-t");
716 argv = sync_pipe_add_arg(argv, &argc, "-F");
717 if (capture_opts->use_pcapng)
718 argv = sync_pipe_add_arg(argv, &argc, "pcapng");
719 else
720 argv = sync_pipe_add_arg(argv, &argc, "pcap");
722 if (capture_comments != NULL) {
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));
729 if (capture_opts->temp_dir) {
730 argv = sync_pipe_add_arg(argv, &argc, "--temp-dir");
731 argv = sync_pipe_add_arg(argv, &argc, capture_opts->temp_dir);
734 if (capture_opts->multi_files_on) {
735 if (capture_opts->has_autostop_filesize) {
736 char sfilesize[ARGV_NUMBER_LEN];
737 argv = sync_pipe_add_arg(argv, &argc, "-b");
738 snprintf(sfilesize, ARGV_NUMBER_LEN, "filesize:%u",capture_opts->autostop_filesize);
739 argv = sync_pipe_add_arg(argv, &argc, sfilesize);
742 if (capture_opts->has_file_duration) {
743 char sfile_duration[ARGV_NUMBER_LEN];
744 argv = sync_pipe_add_arg(argv, &argc, "-b");
745 snprintf(sfile_duration, ARGV_NUMBER_LEN, "duration:%f",capture_opts->file_duration);
746 argv = sync_pipe_add_arg(argv, &argc, sfile_duration);
749 if (capture_opts->has_file_interval) {
750 char sfile_interval[ARGV_NUMBER_LEN];
751 argv = sync_pipe_add_arg(argv, &argc, "-b");
752 snprintf(sfile_interval, ARGV_NUMBER_LEN, "interval:%d",capture_opts->file_interval);
753 argv = sync_pipe_add_arg(argv, &argc, sfile_interval);
756 if (capture_opts->has_file_packets) {
757 char sfile_packets[ARGV_NUMBER_LEN];
758 argv = sync_pipe_add_arg(argv, &argc, "-b");
759 snprintf(sfile_packets, ARGV_NUMBER_LEN, "packets:%d",capture_opts->file_packets);
760 argv = sync_pipe_add_arg(argv, &argc, sfile_packets);
763 if (capture_opts->has_ring_num_files) {
764 char sring_num_files[ARGV_NUMBER_LEN];
765 argv = sync_pipe_add_arg(argv, &argc, "-b");
766 snprintf(sring_num_files, ARGV_NUMBER_LEN, "files:%d",capture_opts->ring_num_files);
767 argv = sync_pipe_add_arg(argv, &argc, sring_num_files);
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);
777 if (capture_opts->has_nametimenum) {
778 char nametimenum[ARGV_NUMBER_LEN];
779 argv = sync_pipe_add_arg(argv, &argc, "-b");
780 snprintf(nametimenum, ARGV_NUMBER_LEN, "nametimenum:2");
781 argv = sync_pipe_add_arg(argv, &argc, nametimenum);
784 if (capture_opts->has_autostop_files) {
785 char sautostop_files[ARGV_NUMBER_LEN];
786 argv = sync_pipe_add_arg(argv, &argc, "-a");
787 snprintf(sautostop_files, ARGV_NUMBER_LEN, "files:%d",capture_opts->autostop_files);
788 argv = sync_pipe_add_arg(argv, &argc, sautostop_files);
790 } else {
791 if (capture_opts->has_autostop_filesize) {
792 char sautostop_filesize[ARGV_NUMBER_LEN];
793 argv = sync_pipe_add_arg(argv, &argc, "-a");
794 snprintf(sautostop_filesize, ARGV_NUMBER_LEN, "filesize:%u",capture_opts->autostop_filesize);
795 argv = sync_pipe_add_arg(argv, &argc, sautostop_filesize);
799 if (capture_opts->has_autostop_packets) {
800 char scount[ARGV_NUMBER_LEN];
801 argv = sync_pipe_add_arg(argv, &argc, "-c");
802 snprintf(scount, ARGV_NUMBER_LEN, "%d",capture_opts->autostop_packets);
803 argv = sync_pipe_add_arg(argv, &argc, scount);
806 if (capture_opts->has_autostop_duration) {
807 char sautostop_duration[ARGV_NUMBER_LEN];
808 argv = sync_pipe_add_arg(argv, &argc, "-a");
809 snprintf(sautostop_duration, ARGV_NUMBER_LEN, "duration:%f",capture_opts->autostop_duration);
810 argv = sync_pipe_add_arg(argv, &argc, sautostop_duration);
813 if (capture_opts->has_autostop_written_packets) {
814 char scount[ARGV_NUMBER_LEN];
815 argv = sync_pipe_add_arg(argv, &argc, "-a");
816 snprintf(scount, ARGV_NUMBER_LEN, "packets:%d",capture_opts->autostop_written_packets);
817 argv = sync_pipe_add_arg(argv, &argc, scount);
820 if (capture_opts->group_read_access) {
821 argv = sync_pipe_add_arg(argv, &argc, "-g");
824 if (capture_opts->update_interval != DEFAULT_UPDATE_INTERVAL) {
825 char scount[ARGV_NUMBER_LEN];
826 argv = sync_pipe_add_arg(argv, &argc, "--update-interval");
827 snprintf(scount, ARGV_NUMBER_LEN, "%d", capture_opts->update_interval);
828 argv = sync_pipe_add_arg(argv, &argc, scount);
831 for (j = 0; j < capture_opts->ifaces->len; j++) {
832 interface_opts = &g_array_index(capture_opts->ifaces, interface_options, j);
834 argv = sync_pipe_add_arg(argv, &argc, "-i");
835 if (interface_opts->extcap_fifo != NULL)
837 #ifdef _WIN32
838 char *pipe = ws_strdup_printf("%s%" PRIuMAX, EXTCAP_PIPE_PREFIX, (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);
849 else
850 argv = sync_pipe_add_arg(argv, &argc, interface_opts->name);
852 if (interface_opts->descr != NULL)
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);
860 if (interface_opts->cfilter != NULL && 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);
864 if (interface_opts->has_snaplen) {
865 char ssnap[ARGV_NUMBER_LEN];
866 argv = sync_pipe_add_arg(argv, &argc, "-s");
867 snprintf(ssnap, ARGV_NUMBER_LEN, "%d", interface_opts->snaplen);
868 argv = sync_pipe_add_arg(argv, &argc, ssnap);
871 if (interface_opts->linktype != -1) {
872 const char *linktype = linktype_val_to_name(interface_opts->linktype);
873 if ( linktype != NULL )
875 argv = sync_pipe_add_arg(argv, &argc, "-y");
876 argv = sync_pipe_add_arg(argv, &argc, linktype);
880 if (!interface_opts->promisc_mode) {
881 argv = sync_pipe_add_arg(argv, &argc, "-p");
884 #ifdef CAN_SET_CAPTURE_BUFFER_SIZE
885 if (interface_opts->buffer_size != DEFAULT_CAPTURE_BUFFER_SIZE) {
886 char buffer_size[ARGV_NUMBER_LEN];
887 argv = sync_pipe_add_arg(argv, &argc, "-B");
888 if(interface_opts->buffer_size == 0x00)
889 interface_opts->buffer_size = DEFAULT_CAPTURE_BUFFER_SIZE;
890 snprintf(buffer_size, ARGV_NUMBER_LEN, "%d", interface_opts->buffer_size);
891 argv = sync_pipe_add_arg(argv, &argc, buffer_size);
893 #endif
895 #ifdef HAVE_PCAP_CREATE
896 if (interface_opts->monitor_mode) {
897 argv = sync_pipe_add_arg(argv, &argc, "-I");
899 #endif
901 #ifdef HAVE_PCAP_REMOTE
902 if (interface_opts->datatx_udp)
903 argv = sync_pipe_add_arg(argv, &argc, "-u");
905 if (!interface_opts->nocap_rpcap)
906 argv = sync_pipe_add_arg(argv, &argc, "-r");
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);
916 #endif
918 #ifdef HAVE_PCAP_SETSAMPLING
919 if (interface_opts->sampling_method != CAPTURE_SAMP_NONE) {
920 char ssampling[ARGV_NUMBER_LEN];
921 argv = sync_pipe_add_arg(argv, &argc, "-m");
922 snprintf(ssampling, ARGV_NUMBER_LEN, "%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);
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);
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_LEN, "%ld", GetCurrentProcessId());
941 argv = sync_pipe_add_arg(argv, &argc, control_id);
942 #endif
943 #endif
945 if (capture_opts->save_file) {
946 argv = sync_pipe_add_arg(argv, &argc, "-w");
947 argv = sync_pipe_add_arg(argv, &argc, capture_opts->save_file);
949 for (i = 0; i < argc; i++) {
950 ws_debug("argv[%d]: %s", i, argv[i]);
952 if (capture_opts->compress_type) {
953 argv = sync_pipe_add_arg(argv, &argc, "--compress-type");
954 argv = sync_pipe_add_arg(argv, &argc, capture_opts->compress_type);
957 int ret;
958 char* msg;
959 #ifdef _WIN32
960 ret = sync_pipe_open_command(argv, NULL, &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, &sync_pipe_read_io, NULL,
964 &cap_session->fork_child, NULL, &msg, update_cb);
965 #endif
967 if (ret == -1) {
968 report_failure("%s", msg);
969 g_free(msg);
970 return false;
973 /* Parent process - read messages from the child process over the
974 sync pipe. */
976 cap_session->fork_child_status = 0;
977 cap_session->cap_data_info = cap_data;
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. */
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;
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);
993 return true;
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().
1004 static int
1005 sync_pipe_close_command(int *data_read_fd, GIOChannel *message_read_io,
1006 ws_process_id *fork_child, char **msgp)
1008 ws_close(*data_read_fd);
1009 if (message_read_io != NULL)
1010 g_io_channel_unref(message_read_io);
1012 #ifdef _WIN32
1013 /* XXX - Should we signal the child somehow? */
1014 sync_pipe_kill(*fork_child);
1015 #endif
1017 return sync_pipe_wait_for_child(*fork_child, msgp);
1021 * Run dumpcap with the supplied arguments.
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().
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().
1032 static int
1033 sync_pipe_run_command_actual(char **argv, char **data, char **primary_msg,
1034 char **secondary_msg, void(*update_cb)(void))
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 + 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;
1051 ssize_t count;
1053 if (buffer == NULL) {
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.
1058 *primary_msg = ws_strdup_printf("Couldn't allocate memory for dumpcap output buffer: %s",
1059 g_strerror(errno));
1060 *secondary_msg = NULL;
1061 *data = NULL;
1062 return -1;
1065 ret = sync_pipe_open_command(argv, &data_pipe_read_fd, &sync_pipe_read_io, NULL,
1066 &fork_child, NULL, &msg, update_cb);
1067 if (ret == -1) {
1068 *primary_msg = msg;
1069 *secondary_msg = NULL;
1070 *data = NULL;
1071 g_free(buffer);
1072 return -1;
1076 * We were able to set up to read dumpcap's output. Do so.
1078 * First, wait for an SP_ERROR_MSG message or SP_SUCCESS message.
1080 do {
1081 nread = pipe_read_block(sync_pipe_read_io, &indicator, SP_MAX_MSG_LEN,
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.
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");
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);
1110 g_free(*primary_msg);
1111 g_free(wait_msg);
1112 *primary_msg = combined_msg;
1115 *secondary_msg = NULL;
1116 *data = NULL;
1117 g_free(buffer);
1119 return -1;
1122 /* we got a valid message block from the child, process it */
1123 switch(indicator) {
1125 case SP_EXEC_FAILED:
1127 * Exec of dumpcap failed. Get the errno for the failure.
1129 if (!ws_strtoi32(buffer, NULL, &exec_errno)) {
1130 ws_warning("Invalid errno: %s", buffer);
1134 * Pick up the child status.
1136 ret = sync_pipe_close_command(&data_pipe_read_fd, sync_pipe_read_io,
1137 &fork_child, &msg);
1138 if (ret == -1) {
1140 * Child process failed unexpectedly, or wait failed; msg is the
1141 * error message.
1143 *primary_msg = msg;
1144 *secondary_msg = NULL;
1145 } else {
1147 * Child process failed, but returned the expected exit status.
1148 * Return the messages it gave us, and indicate failure.
1150 *primary_msg = ws_strdup_printf("Couldn't run dumpcap in child process: %s",
1151 g_strerror(exec_errno));
1152 *secondary_msg = NULL;
1153 ret = -1;
1155 *data = NULL;
1156 break;
1158 case SP_ERROR_MSG:
1160 * Error from dumpcap; there will be a primary message and a
1161 * secondary message.
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 */
1174 * Pick up the child status.
1176 ret = sync_pipe_close_command(&data_pipe_read_fd, sync_pipe_read_io,
1177 &fork_child, &msg);
1178 if (ret == -1) {
1180 * Child process failed unexpectedly, or wait failed; msg is the
1181 * error message.
1183 *primary_msg = msg;
1184 *secondary_msg = NULL;
1185 } else {
1187 * Child process failed, but returned the expected exit status.
1188 * Return the messages it gave us, and indicate failure.
1190 *primary_msg = g_strdup(primary_msg_text);
1191 *secondary_msg = g_strdup(secondary_msg_text);
1192 ret = -1;
1194 *data = NULL;
1195 break;
1197 case SP_LOG_MSG:
1199 * Log from dumpcap; pass to our log
1201 sync_pipe_handle_log_msg(buffer);
1202 break;
1204 case SP_SUCCESS:
1205 /* read the output from the command */
1206 data_buf = g_string_new("");
1207 while ((count = ws_read(data_pipe_read_fd, buffer, PIPE_BUF_SIZE)) > 0) {
1208 buffer[count] = '\0';
1209 g_string_append(data_buf, buffer);
1213 * Pick up the child status.
1215 ret = sync_pipe_close_command(&data_pipe_read_fd, sync_pipe_read_io,
1216 &fork_child, &msg);
1217 if (ret == -1) {
1219 * Child process failed unexpectedly, or wait failed; msg is the
1220 * error message.
1222 *primary_msg = msg;
1223 *secondary_msg = NULL;
1224 g_string_free(data_buf, TRUE);
1225 *data = NULL;
1226 } else {
1228 * Child process succeeded.
1230 *primary_msg = NULL;
1231 *secondary_msg = NULL;
1232 *data = g_string_free(data_buf, FALSE);
1234 break;
1236 default:
1238 * Pick up the child status.
1240 ret = sync_pipe_close_command(&data_pipe_read_fd, sync_pipe_read_io,
1241 &fork_child, &msg);
1242 if (ret == -1) {
1244 * Child process failed unexpectedly, or wait failed; msg is the
1245 * error message.
1247 *primary_msg = msg;
1248 *secondary_msg = NULL;
1249 } else {
1251 * Child process returned an unknown status.
1253 *primary_msg = ws_strdup_printf("dumpcap process gave an unexpected message type: 0x%02x",
1254 indicator);
1255 *secondary_msg = NULL;
1256 ret = -1;
1258 *data = NULL;
1259 break;
1261 } while (indicator != SP_SUCCESS && ret != -1);
1263 g_free(buffer);
1264 return ret;
1267 /* centralised logging and timing for sync_pipe_run_command_actual(),
1268 * redirects to sync_pipe_run_command_actual()
1270 static int
1271 sync_pipe_run_command(char **argv, char **data, char **primary_msg,
1272 char **secondary_msg, void (*update_cb)(void))
1274 int ret, i;
1275 int64_t start_time;
1276 double elapsed;
1277 int logging_enabled;
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, LOG_LEVEL_INFO);
1281 if (logging_enabled) {
1282 start_time = g_get_monotonic_time();
1283 ws_debug("sync_pipe_run_command() starts");
1284 for (i=0; argv[i] != 0; i++) {
1285 ws_noisy(" argv[%d]: %s", i, argv[i]);
1288 /* do the actual sync pipe run command */
1289 ret = sync_pipe_run_command_actual(argv, data, primary_msg, secondary_msg, update_cb);
1291 if (logging_enabled) {
1292 elapsed = (g_get_monotonic_time() - start_time) / 1e6;
1294 ws_debug("sync_pipe_run_command() ends, taking %.3fs, result=%d", elapsed, ret);
1297 return ret;
1302 sync_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))
1307 int argc, ret;
1308 char **argv;
1309 char *opt;
1311 argv = init_pipe_args(&argc);
1313 if (!argv) {
1314 *primary_msg = g_strdup("We don't know where to find dumpcap.");
1315 *secondary_msg = NULL;
1316 *data = NULL;
1317 return -1;
1320 argv = sync_pipe_add_arg(argv, &argc, "-i");
1321 argv = sync_pipe_add_arg(argv, &argc, iface);
1323 if (center_freq2)
1324 opt = ws_strdup_printf("%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);
1327 else if (type)
1328 opt = ws_strdup_printf("%s,%s", freq, type);
1329 else
1330 opt = g_strdup(freq);
1332 if (!opt) {
1333 *primary_msg = g_strdup("Out of mem.");
1334 *secondary_msg = NULL;
1335 *data = NULL;
1336 return -1;
1339 argv = sync_pipe_add_arg(argv, &argc, "-k");
1340 argv = sync_pipe_add_arg(argv, &argc, opt);
1342 ret = sync_pipe_run_command(argv, data, primary_msg, secondary_msg, update_cb);
1343 g_free(opt);
1344 return ret;
1348 * Get the list of interfaces using dumpcap.
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().
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().
1360 sync_interface_list_open(char **data, char **primary_msg,
1361 char **secondary_msg, void (*update_cb)(void))
1363 int argc;
1364 char **argv;
1365 int ret;
1367 ws_debug("sync_interface_list_open");
1369 argv = init_pipe_args(&argc);
1371 if (!argv) {
1372 *primary_msg = g_strdup("We don't know where to find dumpcap..");
1373 *secondary_msg = NULL;
1374 *data = NULL;
1375 return -1;
1378 /* Ask for the interface list */
1379 argv = sync_pipe_add_arg(argv, &argc, "-D");
1381 ret = sync_pipe_run_command(argv, data, primary_msg, secondary_msg, update_cb);
1382 return ret;
1386 * Get the capabilities of an interface using dumpcap.
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().
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().
1398 sync_if_capabilities_open(const char *ifname, bool monitor_mode, const char* auth,
1399 char **data, char **primary_msg,
1400 char **secondary_msg, void (*update_cb)(void))
1402 int argc;
1403 char **argv;
1404 int ret;
1406 ws_debug("sync_if_capabilities_open");
1408 argv = init_pipe_args(&argc);
1410 if (!argv) {
1411 *primary_msg = g_strdup("We don't know where to find dumpcap.");
1412 *secondary_msg = NULL;
1413 *data = NULL;
1414 return -1;
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);
1429 ret = sync_pipe_run_command(argv, data, primary_msg, secondary_msg, update_cb);
1430 return ret;
1434 sync_if_list_capabilities_open(GList *if_queries,
1435 char **data, char **primary_msg,
1436 char **secondary_msg, void (*update_cb)(void))
1438 int argc;
1439 char **argv;
1440 int ret;
1441 if_cap_query_t *if_cap_query;
1443 ws_debug("sync_if_list_capabilities_open");
1445 argv = init_pipe_args(&argc);
1447 if (!argv) {
1448 *primary_msg = g_strdup("We don't know where to find dumpcap.");
1449 *secondary_msg = NULL;
1450 *data = NULL;
1451 return -1;
1454 for (GList *li = if_queries; li != NULL; li = g_list_next(li)) {
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);
1470 argv = sync_pipe_add_arg(argv, &argc, "-L");
1471 argv = sync_pipe_add_arg(argv, &argc, "--list-time-stamp-types");
1473 ret = sync_pipe_run_command(argv, data, primary_msg, secondary_msg, update_cb);
1474 return ret;
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.
1486 sync_interface_stats_open(int *data_read_fd, ws_process_id *fork_child, char **data, char **msg, void (*update_cb)(void))
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 + 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;
1503 ws_debug("sync_interface_stats_open");
1505 argv = init_pipe_args(&argc);
1507 if (!argv) {
1508 *msg = g_strdup("We don't know where to find dumpcap.");
1509 g_free(buffer);
1510 return -1;
1513 /* Ask for the interface statistics */
1514 argv = sync_pipe_add_arg(argv, &argc, "-S");
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");
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;
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,
1534 fork_child, NULL, msg, update_cb);
1535 if (ret == -1) {
1536 g_free(buffer);
1537 return -1;
1541 * We were able to set up to read dumpcap's output. Do so.
1543 * First, wait for an SP_ERROR_MSG message or SP_SUCCESS message.
1545 do {
1546 nread = pipe_read_block(message_read_io, &indicator, SP_MAX_MSG_LEN,
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.
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_close(*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");
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);
1576 g_free(*msg);
1577 g_free(wait_msg);
1578 *msg = combined_msg;
1581 g_free(buffer);
1582 return -1;
1585 /* we got a valid message block from the child, process it */
1586 switch(indicator) {
1588 case SP_EXEC_FAILED:
1590 * Exec of dumpcap failed. Get the errno for the failure.
1592 if (!ws_strtoi32(buffer, NULL, &exec_errno)) {
1593 ws_warning("Invalid errno: %s", buffer);
1595 *msg = ws_strdup_printf("Couldn't run dumpcap in child process: %s",
1596 g_strerror(exec_errno));
1599 * Pick up the child status.
1601 char *close_msg = NULL;
1602 sync_pipe_close_command(data_read_fd, message_read_io,
1603 fork_child, &close_msg);
1605 * Ignore the error from sync_pipe_close_command, presumably the one
1606 * returned by the child is more pertinent to what went wrong.
1608 g_free(close_msg);
1609 ret = -1;
1610 break;
1612 case SP_ERROR_MSG:
1614 * Error from dumpcap; there will be a primary message and a
1615 * secondary message.
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 */
1628 * Pick up the child status.
1630 ret = sync_pipe_close_command(data_read_fd, message_read_io,
1631 fork_child, msg);
1632 if (ret == -1) {
1634 * Child process failed unexpectedly, or wait failed; msg is the
1635 * error message.
1637 } else if (ret == WS_EXIT_NO_INTERFACES) {
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.
1643 *msg = g_strdup(primary_msg_text);
1644 } else {
1646 * Child process failed, but returned the expected exit status.
1647 * Return the messages it gave us, and indicate failure.
1649 *msg = g_strdup(primary_msg_text);
1650 ret = -1;
1652 g_free(buffer);
1653 return ret;
1655 case SP_LOG_MSG:
1657 * Log from dumpcap; pass to our log
1659 sync_pipe_handle_log_msg(buffer);
1660 break;
1662 case SP_IFACE_LIST:
1664 * Dumpcap giving us the interface list
1667 /* convert primary message */
1668 if (data) {
1669 *data = g_strdup(buffer);
1671 break;
1673 case SP_SUCCESS:
1674 /* Close the message pipe. */
1675 g_io_channel_unref(message_read_io);
1676 break;
1678 default:
1680 * Pick up the child status.
1682 ret = sync_pipe_close_command(data_read_fd, message_read_io,
1683 fork_child, msg);
1684 if (ret == -1) {
1686 * Child process failed unexpectedly, or wait failed; msg is the
1687 * error message.
1689 } else {
1691 * Child process returned an unknown status.
1693 *msg = ws_strdup_printf("dumpcap process gave an unexpected message type: 0x%02x",
1694 indicator);
1695 ret = -1;
1697 break;
1699 } while (indicator != SP_SUCCESS && ret != -1);
1701 g_free(buffer);
1702 return ret;
1705 /* Close down the stats process */
1707 sync_interface_stats_close(int *read_fd, ws_process_id *fork_child, char **msg)
1709 #ifdef _WIN32
1710 CloseHandle(dummy_signal_pipe);
1711 dummy_signal_pipe = NULL;
1712 #else
1714 * Don't bother waiting for the child. sync_pipe_close_command
1715 * does this for us on Windows.
1717 sync_pipe_kill(*fork_child);
1718 #endif
1719 return sync_pipe_close_command(read_fd, NULL, fork_child, msg);
1722 /* read a number of bytes from a pipe */
1723 /* (blocks until enough bytes read or an error occurs) */
1724 static ssize_t
1725 pipe_read_bytes(GIOChannel *pipe_io, char *bytes, size_t required, char **msg)
1727 GError *err = NULL;
1728 size_t newly;
1729 size_t offset = 0;
1731 while(required) {
1732 g_io_channel_read_chars(pipe_io, &bytes[offset], required, &newly, &err);
1733 if (err != NULL) {
1734 ws_debug("read from pipe %p: error(%u): %s", pipe_io, err->code, err->message);
1735 *msg = ws_strdup_printf("Error reading from sync pipe: %s", err->message);
1736 g_clear_error(&err);
1737 return -1;
1739 if (newly == 0) {
1740 /* EOF */
1741 ws_debug("read from pipe %p: EOF (capture closed?)", pipe_io);
1742 *msg = 0;
1743 return offset;
1746 required -= newly;
1747 offset += newly;
1750 *msg = NULL;
1751 return offset;
1755 * Read a line from a pipe; similar to fgets, but doesn't block.
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.
1761 sync_pipe_gets_nonblock(int pipe_fd, char *bytes, int max) {
1762 ssize_t newly;
1763 int offset = -1;
1765 while(offset < max - 1) {
1766 offset++;
1767 if (! ws_pipe_data_available(pipe_fd))
1768 break;
1769 newly = ws_read(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));
1776 return -1;
1777 } else if (bytes[offset] == '\n') {
1778 break;
1782 if (offset >= 0)
1783 bytes[offset] = '\0';
1785 return offset;
1789 /* convert header values (indicator and 3-byte length) */
1790 static void
1791 pipe_convert_header(const unsigned char *header, int header_len _U_, char *indicator, int *block_len) {
1793 ws_assert(header_len == 4);
1795 /* convert header values */
1796 *indicator = header[0];
1797 *block_len = (header[1]&0xFF)<<16 | (header[2]&0xFF)<<8 | (header[3]&0xFF);
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) */
1803 static ssize_t
1804 pipe_read_block(GIOChannel *pipe_io, char *indicator, int len, char *msg,
1805 char **err_msg)
1807 int required;
1808 ssize_t newly;
1809 char header[4];
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) {
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.
1820 ws_debug("read %p got an EOF", pipe_io);
1821 return 0;
1823 ws_debug("read %p failed to read header: %lu", pipe_io, (long)newly);
1824 if (newly != -1) {
1826 * Short read, but not an immediate EOF.
1828 *err_msg = ws_strdup_printf("Premature EOF reading from sync pipe: got only %ld bytes",
1829 (long)newly);
1831 return -1;
1834 /* convert header values */
1835 pipe_convert_header((unsigned char*)header, 4, indicator, &required);
1837 /* only indicator with no value? */
1838 if(required == 0) {
1839 ws_debug("read %p indicator: %c empty value", pipe_io, *indicator);
1840 return 4;
1843 /* does the data fit into the given buffer? */
1844 if(required > len) {
1845 size_t bytes_read;
1846 GError *err = NULL;
1847 ws_debug("read %p length error, required %d > len %d, header: 0x%02x 0x%02x 0x%02x 0x%02x",
1848 pipe_io, required, len,
1849 header[0], header[1], header[2], header[3]);
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) { /* error */
1854 ws_debug("read from pipe %p: error(%u): %s", pipe_io, err->code, err->message);
1855 g_clear_error(&err);
1857 *err_msg = ws_strdup_printf("Message %c from dumpcap with length %d > buffer size %d! Partial message: %s",
1858 *indicator, required, len, msg);
1859 return -1;
1861 len = required;
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",
1868 msg);
1870 return -1;
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);
1875 *err_msg = NULL;
1876 return newly + 4;
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). */
1883 static gboolean
1884 sync_pipe_input_cb(GIOChannel *pipe_io, capture_session *cap_session)
1886 int ret;
1887 char *buffer = g_malloc(SP_MAX_MSG_LEN + 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;
1898 nread = pipe_read_block(pipe_io, &indicator, SP_MAX_MSG_LEN, 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.
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.
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);
1927 g_free(primary_msg);
1928 g_free(wait_msg);
1929 primary_msg = combined_msg;
1933 /* No more child process. */
1934 cap_session->fork_child = WS_INVALID_PID;
1935 cap_session->fork_child_status = ret;
1937 #ifdef _WIN32
1938 ws_close(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);
1946 g_free(buffer);
1947 return false;
1950 /* we got a valid message block from the child, process it */
1951 switch(indicator) {
1952 case SP_FILE:
1953 if(!cap_session->new_file(cap_session, buffer)) {
1954 ws_debug("file failed, closing capture");
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. */
1959 /* The child has sent us a filename which we couldn't open.
1961 This could mean that the child is creating and deleting files
1962 (ring buffer mode) faster than we can handle it.
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).
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);
1973 g_free(buffer);
1974 return false;
1976 break;
1977 case SP_PACKET_COUNT:
1978 if (!ws_strtou32(buffer, NULL, &npackets)) {
1979 ws_warning("Invalid packets number: %s", buffer);
1981 ws_debug("new packets %u", npackets);
1982 cap_session->count += npackets;
1983 cap_session->new_packets(cap_session, npackets);
1984 break;
1985 case SP_EXEC_FAILED:
1987 * Exec of dumpcap failed. Get the errno for the failure.
1989 if (!ws_strtoi32(buffer, NULL, &exec_errno)) {
1990 ws_warning("Invalid errno: %s", buffer);
1992 primary_msg = ws_strdup_printf("Couldn't run dumpcap in child process: %s",
1993 g_strerror(exec_errno));
1994 cap_session->error(cap_session, primary_msg, NULL);
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:
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:
2012 * Log from dumpcap; pass to our log
2014 sync_pipe_handle_log_msg(buffer);
2015 break;
2016 case SP_BAD_FILTER: {
2017 const char *message=NULL;
2018 uint32_t indx = 0;
2019 const char* end;
2021 if (ws_strtou32(buffer, &end, &indx) && end[0] == ':') {
2022 message = end + 1;
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;
2029 case SP_DROPS: {
2030 const char *name = NULL;
2031 const char* end;
2032 uint32_t num = 0;
2034 if (ws_strtou32(buffer, &end, &num) && end[0] == ':') {
2035 name = end + 1;
2038 cap_session->drops(cap_session, num, name);
2039 break;
2041 default:
2042 if (g_ascii_isprint(indicator))
2043 ws_warning("Unknown indicator '%c'", indicator);
2044 else
2045 ws_warning("Unknown indicator '\\x%02x", indicator);
2046 break;
2049 g_free(buffer);
2050 return true;
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().
2063 static int
2064 sync_pipe_wait_for_child(ws_process_id fork_child, char **msgp)
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;
2074 start_time = g_get_monotonic_time();
2076 ws_debug("wait till child closed");
2077 ws_assert(fork_child != WS_INVALID_PID);
2079 *msgp = NULL; /* 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));
2083 ret = -1;
2084 } else {
2086 * The child exited; return its exit status. Do not treat this as
2087 * an error.
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",
2093 win32strexception(fork_child_status));
2094 ret = -1;
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)) {
2103 * The child exited; return its exit status. Do not treat this as
2104 * an error.
2106 ret = WEXITSTATUS(fork_child_status);
2107 } else if (WIFSTOPPED(fork_child_status)) {
2108 /* It stopped, rather than exiting. "Should not happen." */
2109 *msgp = ws_strdup_printf("Child dumpcap process stopped: %s",
2110 sync_pipe_signame(WSTOPSIG(fork_child_status)));
2111 ret = -1;
2112 } else if (WIFSIGNALED(fork_child_status)) {
2113 /* It died with a signal. */
2114 *msgp = ws_strdup_printf("Child dumpcap process died: %s%s",
2115 sync_pipe_signame(WTERMSIG(fork_child_status)),
2116 WCOREDUMP(fork_child_status) ? " - 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",
2122 fork_child_status);
2123 ret = -1;
2125 } else {
2126 /* waitpid() failed */
2127 if (errno == EINTR) {
2129 * Signal interrupted waitpid().
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).
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.
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.
2144 ws_warning("waitpid returned EINTR. retrying.");
2145 continue;
2146 } else if (errno == ECHILD) {
2148 * The process identified by fork_child either doesn't
2149 * exist any more or isn't our child process (anymore?).
2151 * echld might have already reaped the child.
2153 ret = fetch_dumpcap_pid ? 0 : -1;
2154 } else {
2155 /* Unknown error. */
2156 *msgp = ws_strdup_printf("Error from waitpid(): %s", g_strerror(errno));
2157 ret = -1;
2160 break;
2162 #endif
2164 elapsed = (g_get_monotonic_time() - start_time) / 1e6;
2165 ws_debug("capture child closed after %.3fs", elapsed);
2166 return ret;
2170 #ifndef _WIN32
2171 /* convert signal to corresponding name */
2172 static const char *
2173 sync_pipe_signame(int sig)
2175 const char *sigmsg;
2176 static char sigmsg_buf[6+1+3+1];
2178 switch (sig) {
2180 case SIGHUP:
2181 sigmsg = "Hangup";
2182 break;
2184 case SIGINT:
2185 sigmsg = "Interrupted";
2186 break;
2188 case SIGQUIT:
2189 sigmsg = "Quit";
2190 break;
2192 case SIGILL:
2193 sigmsg = "Illegal instruction";
2194 break;
2196 case SIGTRAP:
2197 sigmsg = "Trace trap";
2198 break;
2200 case SIGABRT:
2201 sigmsg = "Abort";
2202 break;
2204 case SIGFPE:
2205 sigmsg = "Arithmetic exception";
2206 break;
2208 case SIGKILL:
2209 sigmsg = "Killed";
2210 break;
2212 case SIGBUS:
2213 sigmsg = "Bus error";
2214 break;
2216 case SIGSEGV:
2217 sigmsg = "Segmentation violation";
2218 break;
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:
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.''
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).
2238 #ifdef SIGSYS
2239 case SIGSYS:
2240 sigmsg = "Bad system call";
2241 break;
2242 #endif
2244 case SIGPIPE:
2245 sigmsg = "Broken pipe";
2246 break;
2248 case SIGALRM:
2249 sigmsg = "Alarm clock";
2250 break;
2252 case SIGTERM:
2253 sigmsg = "Terminated";
2254 break;
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;
2262 return sigmsg;
2264 #endif
2267 #ifdef _WIN32
2269 static int create_dummy_signal_pipe(char **msg) {
2270 char *dummy_signal_pipe_name;
2272 if (dummy_signal_pipe != NULL) return 0;
2274 if (!dummy_control_id) {
2275 dummy_control_id = ws_strdup_printf("%ld.dummy", GetCurrentProcessId());
2278 /* Create the signal pipe */
2279 dummy_signal_pipe_name = ws_strdup_printf(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);
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",
2285 win32strerror(GetLastError()));
2286 return -1;
2288 return 0;
2291 /* tell the child through the signal pipe that we want to quit the capture */
2292 static void
2293 signal_pipe_capquit_to_child(capture_session *cap_session)
2295 const char quit_msg[] = "QUIT";
2296 int ret;
2298 ws_debug("signal_pipe_capquit_to_child");
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_write(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()));
2308 #endif
2311 /* user wants to stop the capture run */
2312 void
2313 sync_pipe_stop(capture_session *cap_session)
2315 if (cap_session->fork_child != WS_INVALID_PID) {
2316 #ifndef _WIN32
2317 /* send the SIGINT signal to close the capture child gracefully. */
2318 int sts = kill(cap_session->fork_child, SIGINT);
2319 if (sts != 0) {
2320 ws_warning("Sending SIGINT to child failed: %s\n", g_strerror(errno));
2322 #else
2323 #define STOP_SLEEP_TIME 500 /* ms */
2324 DWORD status;
2326 /* First, use the special signal pipe to try to close the capture child
2327 * gracefully.
2329 signal_pipe_capquit_to_child(cap_session);
2331 /* Next, wait for the process to exit on its own */
2332 status = WaitForSingleObject((HANDLE) cap_session->fork_child, STOP_SLEEP_TIME);
2334 /* Force the issue. */
2335 if (status != WAIT_OBJECT_0) {
2336 ws_warning("sync_pipe_stop: forcing child to exit");
2337 sync_pipe_kill(cap_session->fork_child);
2339 #endif
2344 /* Wireshark has to exit, force the capture child to close */
2345 void
2346 sync_pipe_kill(ws_process_id fork_child)
2348 if (fork_child != WS_INVALID_PID) {
2349 #ifndef _WIN32
2350 int sts = kill(fork_child, SIGTERM); /* 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));
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)
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.)
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.
2373 TerminateProcess((HANDLE) (fork_child), 0);
2375 #endif
2379 void capture_sync_set_fetch_dumpcap_pid_cb(void(*cb)(ws_process_id pid)) {
2380 fetch_dumpcap_pid = cb;
2383 #endif /* HAVE_LIBPCAP */