#ifdef HAVE_PCAP_SETSAMPLING
char ssampling[ARGV_NUMBER_LEN];
#endif
-#ifdef _WIN32
+#if defined(_WIN32) || defined(HAVE_PCAP_CREATE)
char buffer_size[ARGV_NUMBER_LEN];
+#endif
+#ifdef _WIN32
HANDLE sync_pipe_read; /* pipe used to send messages from child to parent */
HANDLE sync_pipe_write; /* pipe used to send messages from child to parent */
HANDLE signal_pipe; /* named pipe used to send messages from parent to child (currently only stop) */
if (capture_opts->linktype != -1) {
argv = sync_pipe_add_arg(argv, &argc, "-y");
-#ifdef HAVE_PCAP_DATALINK_VAL_TO_NAME
g_snprintf(sdlt, ARGV_NUMBER_LEN, "%s",linktype_val_to_name(capture_opts->linktype));
-#else
- /* we can't get the type name, just treat it as a number */
- g_snprintf(sdlt, ARGV_NUMBER_LEN, "%d",capture_opts->linktype);
-#endif
argv = sync_pipe_add_arg(argv, &argc, sdlt);
}
if (!capture_opts->promisc_mode)
argv = sync_pipe_add_arg(argv, &argc, "-p");
+#ifdef HAVE_PCAP_CREATE
+ if (capture_opts->monitor_mode)
+ argv = sync_pipe_add_arg(argv, &argc, "-I");
+#endif
+ if (capture_opts->use_pcapng)
+ argv = sync_pipe_add_arg(argv, &argc, "-n");
#ifdef HAVE_PCAP_REMOTE
if (capture_opts->datatx_udp)
argv = sync_pipe_add_arg(argv, &argc, "-u");
#endif
#endif
-#ifdef _WIN32
+#if defined(_WIN32) || defined(HAVE_PCAP_CREATE)
argv = sync_pipe_add_arg(argv, &argc, "-B");
#ifdef HAVE_PCAP_REMOTE
if (capture_opts->src_type == CAPTURE_IFREMOTE)
}
/*
- * Open dumpcap with the supplied arguments. On success, msg points to
- * a buffer containing the dumpcap output and returns 0. read_fd and
- * fork_child point to the pipe's file descriptor and child PID/handle,
- * respectively. On failure, msg points to the error message returned by
- * dumpcap, and returns dumpcap's exit value. In either case, msg must be
- * freed with g_free().
+ * Open a pipe to dumpcap with the supplied arguments. On success, *msg
+ * is unchanged and 0 is returned; read_fd and fork_child point to the
+ * pipe's file descriptor and child PID/handle, respectively. On failure,
+ * *msg points to an error message for the failure, and -1 is returned.
+ * In the latter case, *msg must be freed with g_free().
*/
/* XXX - This duplicates a lot of code in sync_pipe_start() */
#define PIPE_BUF_SIZE 5120
sa.lpSecurityDescriptor = NULL;
/* Create a pipe for the child process */
- /* (inrease this value if you have trouble while fast capture file switches) */
+ /* (increase this value if you have trouble while fast capture file switches) */
if (! CreatePipe(&sync_pipe_read, &sync_pipe_write, &sa, 5120)) {
/* Couldn't create the pipe between parent and child. */
*msg = g_strdup_printf("Couldn't create sync pipe: %s", strerror(errno));
g_free( (gpointer) argv[0]);
g_free( (gpointer) argv);
- return CANT_RUN_DUMPCAP;
+ return -1;
}
/* init STARTUPINFO */
CloseHandle(sync_pipe_write);
g_free( (gpointer) argv[0]);
g_free( (gpointer) argv);
- return CANT_RUN_DUMPCAP;
+ return -1;
}
*fork_child = (int) pi.hProcess;
g_string_free(args, TRUE);
*msg = g_strdup_printf("Couldn't create sync pipe: %s", strerror(errno));
g_free( (gpointer) argv[0]);
g_free(argv);
- return CANT_RUN_DUMPCAP;
+ return -1;
}
if ((*fork_child = fork()) == 0) {
/* We couldn't even create the child process. */
*msg = g_strdup_printf("Couldn't create child process: %s", strerror(errno));
ws_close(*read_fd);
- return CANT_RUN_DUMPCAP;
+ return -1;
}
/* we might wait for a moment till child is ready, so update screen now */
return 0;
}
+/*
+ * Wait for dumpcap to finish. On success, *msg is unchanged, and 0 is
+ * returned. On failure, *msg points to an error message for the
+ * failure, and -1 is returned. In the latter case, *msg must be
+ * freed with g_free().
+ */
static int
#ifdef _WIN32
sync_pipe_close_command(int *read_fd, int *fork_child, gchar **msg) {
if (_cwait(&fork_child_status, *fork_child, _WAIT_CHILD) == -1) {
*msg = g_strdup_printf("Child capture process stopped unexpectedly "
"(errno:%u)", errno);
- return CANT_RUN_DUMPCAP;
+ return -1;
}
#else
if (wait(&fork_child_status) != -1) {
*msg = g_strdup_printf("Child capture process died: wait status %#o",
fork_child_status);
}
- return CANT_RUN_DUMPCAP;
+ return -1;
}
} else {
*msg = g_strdup_printf("Child capture process stopped unexpectedly "
"(errno:%u)", errno);
- return CANT_RUN_DUMPCAP;
+ return -1;
}
#endif
return 0;
}
/*
- * Run dumpcap with the supplied arguments. On success, msg points to
- * a buffer containing the dumpcap output and returns 0. On failure, msg
- * points to the error message returned by dumpcap, and returns dumpcap's
- * exit value. In either case, msg must be freed with g_free().
+ * Run dumpcap with the supplied arguments. On success, *msg points to
+ * a buffer containing the dumpcap output, and 0 is returned. On failure,
+ * *msg points to an error message, and -1 is returned. In either case,
+ * *msg must be freed with g_free().
+ *
+ * XXX - this doesn't check the exit status of dumpcap if it can be
+ * started and its return status could be fetched.
*/
/* XXX - This duplicates a lot of code in sync_pipe_start() */
#define PIPE_BUF_SIZE 5120
if (ret)
return ret;
- /* We were able to set up to read dumpcap's output. Do so and
- return its exit value. */
+ /* We were able to set up to read dumpcap's output. Do so. */
msg_buf = g_string_new("");
while ((count = ws_read(sync_pipe_read_fd, buf, PIPE_BUF_SIZE)) > 0) {
buf[count] = '\0';
}
/*
- * Get an interface list using dumpcap. On success, msg points to
- * a buffer containing the dumpcap output and returns 0. On failure, msg
- * points to the error message returned by dumpcap, and returns dumpcap's
- * exit value. In either case, msg must be freed with g_free().
+ * Get an interface list using dumpcap. On success, *msg points to
+ * a buffer containing the dumpcap output, and 0 is returned. On failure,
+ * *msg points to an error message, and -1 is returned. In either case,
+ * msg must be freed with g_free().
*/
int
sync_interface_list_open(gchar **msg) {
if (!argv) {
*msg = g_strdup_printf("We don't know where to find dumpcap.");
- return CANT_RUN_DUMPCAP;
+ return -1;
}
/* Ask for the interface list */
}
/*
- * Get an linktype list using dumpcap. On success, msg points to
- * a buffer containing the dumpcap output and returns 0. On failure, msg
- * points to the error message returned by dumpcap, and returns dumpcap's
- * exit value. In either case, msg must be freed with g_free().
+ * Get interface capabilities using dumpcap. On success, *msg points to
+ * a buffer containing the dumpcap output, and 0 is returned. On failure,
+ * *msg points to an error message, and -1 is returned. In either case,
+ * *msg must be freed with g_free().
*/
int
-sync_linktype_list_open(const gchar *ifname, gchar **msg) {
+sync_if_capabilities_open(const gchar *ifname, gboolean monitor_mode,
+ gchar **msg)
+{
int argc;
const char **argv;
if (!argv) {
*msg = g_strdup_printf("We don't know where to find dumpcap.");
- return CANT_RUN_DUMPCAP;
+ return -1;
}
- /* Ask for the linktype list */
+ /* Ask for the interface capabilities */
argv = sync_pipe_add_arg(argv, &argc, "-i");
argv = sync_pipe_add_arg(argv, &argc, ifname);
argv = sync_pipe_add_arg(argv, &argc, "-L");
+ if (monitor_mode)
+ argv = sync_pipe_add_arg(argv, &argc, "-I");
argv = sync_pipe_add_arg(argv, &argc, "-M");
#if 0
/*
* Start getting interface statistics using dumpcap. On success, read_fd
- * contains the file descriptor for the pipe's stdout, msg is unchanged,
- * and zero is returned. On failure, msg will point to an error message
- * that must be g_free()d and a nonzero error value will be returned.
+ * contains the file descriptor for the pipe's stdout, *msg is unchanged,
+ * and zero is returned. On failure, *msg will point to an error message
+ * that must be g_free()d, and -1 will be returned.
*/
int
sync_interface_stats_open(int *read_fd, int *fork_child, gchar **msg) {
if (!argv) {
*msg = g_strdup_printf("We don't know where to find dumpcap.");
- return CANT_RUN_DUMPCAP;
+ return -1;
}
/* Ask for the interface statistics */
/* read a number of bytes from a pipe */
/* (blocks until enough bytes read or an error occurs) */
static int
-pipe_read_bytes(int pipe, char *bytes, int required) {
+pipe_read_bytes(int pipe_fd, char *bytes, int required) {
int newly;
int offset = 0;
while(required) {
- newly = read(pipe, &bytes[offset], required);
+ newly = read(pipe_fd, &bytes[offset], required);
if (newly == 0) {
/* EOF */
g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG,
- "read from pipe %d: EOF (capture closed?)", pipe);
+ "read from pipe %d: EOF (capture closed?)", pipe_fd);
return offset;
}
if (newly < 0) {
/* error */
g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG,
- "read from pipe %d: error(%u): %s", pipe, errno, strerror(errno));
+ "read from pipe %d: error(%u): %s", pipe_fd, errno, strerror(errno));
return newly;
}
return offset;
}
-static gboolean pipe_data_available(int pipe) {
+static gboolean pipe_data_available(int pipe_fd) {
#ifdef _WIN32 /* PeekNamedPipe */
- HANDLE hPipe = (HANDLE) _get_osfhandle(pipe);
+ HANDLE hPipe = (HANDLE) _get_osfhandle(pipe_fd);
DWORD bytes_avail;
if (hPipe == INVALID_HANDLE_VALUE)
struct timeval timeout;
FD_ZERO(&rfds);
- FD_SET(pipe, &rfds);
+ FD_SET(pipe_fd, &rfds);
timeout.tv_sec = 0;
timeout.tv_usec = 0;
- if (select(pipe+1, &rfds, NULL, NULL, &timeout) > 0)
+ if (select(pipe_fd+1, &rfds, NULL, NULL, &timeout) > 0)
return TRUE;
return FALSE;
(1-byte message indicator, 3-byte message length (excluding length
and indicator field), and the rest is the message) */
static int
-pipe_read_block(int pipe, char *indicator, int len, char *msg) {
+pipe_read_block(int pipe_fd, char *indicator, int len, char *msg) {
int required;
int newly;
guchar header[4];
/* read header (indicator and 3-byte length) */
- newly = pipe_read_bytes(pipe, header, 4);
+ newly = pipe_read_bytes(pipe_fd, header, 4);
if(newly != 4) {
g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG,
- "read %d failed to read header: %u", pipe, newly);
+ "read %d failed to read header: %u", pipe_fd, newly);
return -1;
}
/* only indicator with no value? */
if(required == 0) {
g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG,
- "read %d indicator: %c empty value", pipe, *indicator);
+ "read %d indicator: %c empty value", pipe_fd, *indicator);
return 4;
}
if(required > len) {
g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG,
"read %d length error, required %d > len %d, indicator: %u",
- pipe, required, len, *indicator);
+ pipe_fd, required, len, *indicator);
/* we have a problem here, try to read some more bytes from the pipe to debug where the problem really is */
memcpy(msg, header, sizeof(header));
- newly = read(pipe, &msg[sizeof(header)], len-sizeof(header));
+ newly = read(pipe_fd, &msg[sizeof(header)], len-sizeof(header));
g_warning("Unknown message from dumpcap, try to show it as a string: %s", msg);
return -1;
}
len = required;
/* read the actual block data */
- newly = pipe_read_bytes(pipe, msg, required);
+ newly = pipe_read_bytes(pipe_fd, msg, required);
if(newly != required) {
g_warning("Unknown message from dumpcap, try to show it as a string: %s", msg);
return -1;
/* XXX If message is "2part", the msg probably won't be sent to debug log correctly */
g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG,
- "read %d ok indicator: %c len: %u msg: %s", pipe, *indicator,
+ "read %d ok indicator: %c len: %u msg: %s", pipe_fd, *indicator,
len, msg);
return newly + 4;
}
if (capture_opts->fork_child != -1) {
#ifndef _WIN32
- /* send the SIGUSR1 signal to close the capture child gracefully. */
- int sts = kill(capture_opts->fork_child, SIGUSR1);
+ /* send the SIGINT signal to close the capture child gracefully. */
+ int sts = kill(capture_opts->fork_child, SIGINT);
if (sts != 0) {
g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_WARNING,
- "Sending SIGUSR1 to child failed: %s\n", strerror(errno));
+ "Sending SIGINT to child failed: %s\n", strerror(errno));
}
#else
#define STOP_SLEEP_TIME 500 /* ms */