summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGerald Combs <gerald@wireshark.org>2007-10-26 16:32:28 +0000
committerGerald Combs <gerald@wireshark.org>2007-10-26 16:32:28 +0000
commit8f052940279d78755869b3bd9a1d91da022975d1 (patch)
treedd39295013303ddb2873ef04b583ab3d31c51c1b
parent381c1f1c9ecc1363f632540de214ef5e66a10124 (diff)
downloadwireshark-8f052940279d78755869b3bd9a1d91da022975d1.tar.gz
For the Wireshark/TShark -> dumpcap signal pipe on Windows, use a named
pipe instead of stdin. Add an argument (currently the parent PID) back to the "-Z" flag and use it to construct the pipe name. This lets us pass the parent's stdin handle to dumpcap, which lets us capture from stdin on Windows. Add a comment about checking for the parent process. In capture_loop.c, remove the wait_forever argument from cap_pipe_select() since it was always FALSE. Set the timeout under Windows to 250 ms instead of 250000 ms. svn path=/trunk/; revision=23279
-rw-r--r--Makefile.nmake4
-rw-r--r--capture_loop.c25
-rw-r--r--capture_sync.c31
-rw-r--r--capture_sync.h2
-rw-r--r--dumpcap.c52
5 files changed, 80 insertions, 34 deletions
diff --git a/Makefile.nmake b/Makefile.nmake
index 0c9f126603..83751d57f2 100644
--- a/Makefile.nmake
+++ b/Makefile.nmake
@@ -274,10 +274,10 @@ randpkt.exe : $(randpkt_OBJECTS) getopt.obj
mt.exe -nologo -manifest "randpkt.exe.manifest" -outputresource:randpkt.exe;1
!ENDIF
-dumpcap.exe : $(LIBS_CHECK) config.h svnversion.h $(dumpcap_OBJECTS) getopt.obj inet_ntop.obj mkstemp.obj wiretap\wiretap-$(WTAP_VERSION).lib image\dumpcap.res
+dumpcap.exe : $(LIBS_CHECK) config.h svnversion.h $(dumpcap_OBJECTS) getopt.obj epan/unicode-utils.obj inet_ntop.obj mkstemp.obj wiretap\wiretap-$(WTAP_VERSION).lib image\dumpcap.res
@echo Linking $@
$(LINK) @<<
- /OUT:dumpcap.exe $(conflags) $(conlibsdll) $(LDFLAGS) /SUBSYSTEM:console $(dumpcap_LIBS) $(dumpcap_OBJECTS) getopt.obj inet_ntop.obj mkstemp.obj image\dumpcap.res
+ /OUT:dumpcap.exe $(conflags) $(conlibsdll) $(LDFLAGS) /SUBSYSTEM:console $(dumpcap_LIBS) $(dumpcap_OBJECTS) getopt.obj epan/unicode-utils.obj inet_ntop.obj mkstemp.obj image\dumpcap.res
<<
!IF "$(MSVC_VARIANT)" == "MSVC2005" || "$(MSVC_VARIANT)" == "MSVC2005EE" || "$(MSVC_VARIANT)" == "DOTNET20"
mt.exe -nologo -manifest "dumpcap.exe.manifest" -outputresource:dumpcap.exe;1
diff --git a/capture_loop.c b/capture_loop.c
index 8493302087..de9538f9a3 100644
--- a/capture_loop.c
+++ b/capture_loop.c
@@ -156,7 +156,7 @@ cap_pipe_adjust_header(gboolean byte_swapped, struct pcap_hdr *hdr, struct pcapr
* the string cap_pipe_err_str should be used instead of errno.
*/
static int
-cap_pipe_select(int pipe_fd, gboolean wait_forever) {
+cap_pipe_select(int pipe_fd) {
#ifndef _WIN32
fd_set rfds;
struct timeval timeout, *pto;
@@ -166,13 +166,11 @@ cap_pipe_select(int pipe_fd, gboolean wait_forever) {
FD_ZERO(&rfds);
FD_SET(pipe_fd, &rfds);
- if (wait_forever) {
- pto = NULL;
- } else {
- timeout.tv_sec = 0;
- timeout.tv_usec = CAP_READ_TIMEOUT * 1000;
- pto = &timeout;
- }
+
+ timeout.tv_sec = 0;
+ timeout.tv_usec = CAP_READ_TIMEOUT * 1000;
+ pto = &timeout;
+
sel_ret = select(pipe_fd+1, &rfds, NULL, NULL, pto);
if (sel_ret < 0)
cap_pipe_err_str = strerror(errno);
@@ -185,7 +183,6 @@ cap_pipe_select(int pipe_fd, gboolean wait_forever) {
*/
HANDLE hPipe = (HANDLE) _get_osfhandle(pipe_fd);
wchar_t *err_str;
- DWORD timeout = wait_forever ? INFINITE : CAP_READ_TIMEOUT * 1000;
DWORD wait_ret;
if (hPipe == INVALID_HANDLE_VALUE) {
@@ -195,7 +192,7 @@ cap_pipe_select(int pipe_fd, gboolean wait_forever) {
cap_pipe_err_str = "Unknown error";
- wait_ret = WaitForSingleObject(hPipe, timeout);
+ wait_ret = WaitForSingleObject(hPipe, CAP_READ_TIMEOUT);
switch (wait_ret) {
/* XXX - This probably isn't correct */
case WAIT_ABANDONED:
@@ -374,7 +371,7 @@ cap_pipe_open_live(char *pipename, struct pcap_hdr *hdr, loop_data *ld,
/* read the pcap header */
bytes_read = 0;
while (bytes_read < sizeof magic) {
- sel_ret = cap_pipe_select(fd, FALSE);
+ sel_ret = cap_pipe_select(fd);
if (sel_ret < 0) {
g_snprintf(errmsg, errmsgl,
"Unexpected error from select: %s", strerror(errno));
@@ -429,7 +426,7 @@ cap_pipe_open_live(char *pipename, struct pcap_hdr *hdr, loop_data *ld,
/* Read the rest of the header */
bytes_read = 0;
while (bytes_read < sizeof(struct pcap_hdr)) {
- sel_ret = cap_pipe_select(fd, FALSE);
+ sel_ret = cap_pipe_select(fd);
if (sel_ret < 0) {
g_snprintf(errmsg, errmsgl,
"Unexpected error from select: %s", strerror(errno));
@@ -962,7 +959,7 @@ capture_loop_dispatch(capture_options *capture_opts _U_, loop_data *ld,
#ifdef LOG_CAPTURE_VERBOSE
g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG, "capture_loop_dispatch: from capture pipe");
#endif
- sel_ret = cap_pipe_select(ld->cap_pipe_fd, FALSE);
+ sel_ret = cap_pipe_select(ld->cap_pipe_fd);
if (sel_ret <= 0) {
inpkts = 0;
if (sel_ret < 0 && errno != EINTR) {
@@ -1002,7 +999,7 @@ capture_loop_dispatch(capture_options *capture_opts _U_, loop_data *ld,
g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG, "capture_loop_dispatch: from pcap_dispatch with select");
#endif
if (ld->pcap_fd != -1) {
- sel_ret = cap_pipe_select(ld->pcap_fd, FALSE);
+ sel_ret = cap_pipe_select(ld->pcap_fd);
if (sel_ret > 0) {
/*
* "select()" says we can read from it without blocking; go for
diff --git a/capture_sync.c b/capture_sync.c
index 1a9723344f..9c840ea264 100644
--- a/capture_sync.c
+++ b/capture_sync.c
@@ -254,14 +254,15 @@ sync_pipe_start(capture_options *capture_opts) {
char buffer_size[ARGV_NUMBER_LEN];
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_read; /* pipe used to send messages from parent to child (currently only stop) */
- HANDLE signal_pipe_write; /* pipe used to send messages from parent to child (currently only stop) */
+ HANDLE signal_pipe; /* named pipe used to send messages from parent to child (currently only stop) */
GString *args = g_string_sized_new(200);
gchar *quoted_arg;
SECURITY_ATTRIBUTES sa;
STARTUPINFO si;
PROCESS_INFORMATION pi;
int i;
+ char control_id[ARGV_NUMBER_LEN];
+ gchar *signal_pipe_name;
#else
char errmsg[1024+1];
int sync_pipe[2]; /* pipe used to send messages from child to parent */
@@ -354,6 +355,12 @@ sync_pipe_start(capture_options *capture_opts) {
/* dumpcap should be running in capture child mode (hidden feature) */
#ifndef DEBUG_CHILD
argv = sync_pipe_add_arg(argv, &argc, "-Z");
+#ifdef _WIN32
+ g_snprintf(control_id, ARGV_NUMBER_LEN, "%d", GetCurrentProcessId());
+ argv = sync_pipe_add_arg(argv, &argc, control_id);
+#else
+ argv = sync_pipe_add_arg(argv, &argc, SIGNAL_PIPE_CTRL_ID_NONE);
+#endif
#endif
#ifdef _WIN32
@@ -389,13 +396,16 @@ sync_pipe_start(capture_options *capture_opts) {
return FALSE;
}
- /* Create a pipe for the parent process */
- if (! CreatePipe(&signal_pipe_read, &signal_pipe_write, &sa, 512)) {
+ /* Create the signal pipe */
+ signal_pipe_name = g_strdup_printf(SIGNAL_PIPE_FORMAT, control_id);
+ signal_pipe = CreateNamedPipe(utf_8to16(signal_pipe_name),
+ PIPE_ACCESS_OUTBOUND, PIPE_TYPE_BYTE, 1, 65535, 65535, 0, NULL);
+ g_free(signal_pipe_name);
+
+ if (signal_pipe == INVALID_HANDLE_VALUE) {
/* Couldn't create the signal pipe between parent and child. */
simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "Couldn't create signal pipe: %s",
strerror(errno));
- CloseHandle(sync_pipe_read);
- CloseHandle(sync_pipe_write);
g_free( (gpointer) argv[0]);
g_free( (gpointer) argv);
return FALSE;
@@ -410,7 +420,7 @@ sync_pipe_start(capture_options *capture_opts) {
#else
si.dwFlags = STARTF_USESTDHANDLES|STARTF_USESHOWWINDOW;
si.wShowWindow = SW_HIDE; /* this hides the console window */
- si.hStdInput = signal_pipe_read;
+ si.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
si.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
si.hStdError = sync_pipe_write;
/*si.hStdError = (HANDLE) _get_osfhandle(2);*/
@@ -446,10 +456,8 @@ sync_pipe_start(capture_options *capture_opts) {
sync_pipe_read_fd = _open_osfhandle( (long) sync_pipe_read, _O_BINARY);
/* associate the operating system filehandle to a C run-time file handle */
- capture_opts->signal_pipe_write_fd = _open_osfhandle( (long) signal_pipe_write, _O_BINARY);
+ capture_opts->signal_pipe_write_fd = _open_osfhandle( (long) signal_pipe, _O_BINARY);
- /* child owns the read side now, close our handle */
- CloseHandle(signal_pipe_read);
#else /* _WIN32 */
if (pipe(sync_pipe) < 0) {
/* Couldn't create the pipe between parent and child. */
@@ -804,6 +812,7 @@ sync_interface_list_open(gchar **msg) {
/* dumpcap should be running in capture child mode (hidden feature) */
#ifndef DEBUG_CHILD
argv = sync_pipe_add_arg(argv, &argc, "-Z");
+ argv = sync_pipe_add_arg(argv, &argc, SIGNAL_PIPE_CTRL_ID_NONE);
#endif
return sync_pipe_run_command(argv, msg);
@@ -843,6 +852,7 @@ sync_linktype_list_open(gchar *ifname, gchar **msg) {
/* dumpcap should be running in capture child mode (hidden feature) */
#ifndef DEBUG_CHILD
argv = sync_pipe_add_arg(argv, &argc, "-Z");
+ argv = sync_pipe_add_arg(argv, &argc, SIGNAL_PIPE_CTRL_ID_NONE);
#endif
return sync_pipe_run_command(argv, msg);
@@ -880,6 +890,7 @@ sync_interface_stats_open(int *read_fd, int *fork_child, gchar **msg) {
/* dumpcap should be running in capture child mode (hidden feature) */
#ifndef DEBUG_CHILD
argv = sync_pipe_add_arg(argv, &argc, "-Z");
+ argv = sync_pipe_add_arg(argv, &argc, SIGNAL_PIPE_CTRL_ID_NONE);
#endif
return sync_pipe_open_command(argv, read_fd, fork_child, msg);
diff --git a/capture_sync.h b/capture_sync.h
index a0a9f55185..46eff4a715 100644
--- a/capture_sync.h
+++ b/capture_sync.h
@@ -58,9 +58,11 @@ extern void
sync_pipe_kill(int fork_child);
/** Has the parent signalled the child to stop? */
+#define SIGNAL_PIPE_CTRL_ID_NONE "none"
#ifdef _WIN32
extern gboolean
signal_pipe_check_running(void);
+#define SIGNAL_PIPE_FORMAT "\\\\.\\pipe\\wireshark.%s.signal"
#endif
/** Get an interface list using dumpcap */
diff --git a/dumpcap.c b/dumpcap.c
index 41603be2e1..3bdcf3ce44 100644
--- a/dumpcap.c
+++ b/dumpcap.c
@@ -55,6 +55,10 @@
#include "capture-wpcap.h"
#endif
+#ifdef _WIN32
+#include "epan/unicode-utils.h"
+#endif
+
#include "sync_pipe.h"
#include "capture.h"
@@ -70,6 +74,10 @@
/*#define DEBUG_DUMPCAP*/
gboolean capture_child = FALSE; /* FALSE: standalone call, TRUE: this is an Wireshark capture child */
+#ifdef _WIN32
+gchar *sig_pipe_name = NULL;
+HANDLE sig_pipe_handle = NULL;
+#endif
static void
console_log_handler(const char *log_domain, GLogLevelFlags log_level,
@@ -253,7 +261,7 @@ main(int argc, char *argv[])
gboolean print_statistics = FALSE;
int status, run_once_args = 0;
-#define OPTSTRING_INIT "a:b:c:Df:hi:LMpSs:vw:y:Z"
+#define OPTSTRING_INIT "a:b:c:Df:hi:LMpSs:vw:y:Z:"
#ifdef _WIN32
#define OPTSTRING_WIN32 "B:"
@@ -365,6 +373,23 @@ main(int argc, char *argv[])
#ifdef _WIN32
/* set output pipe to binary mode, to avoid ugly text conversions */
_setmode(2, O_BINARY);
+ /*
+ * optarg = the control ID, aka the PPID, currently used for the
+ * signal pipe name.
+ */
+ if (strcmp(optarg, SIGNAL_PIPE_CTRL_ID_NONE) != 0) {
+ sig_pipe_name = g_strdup_printf(SIGNAL_PIPE_FORMAT,
+ optarg);
+ sig_pipe_handle = CreateFile(utf_8to16(sig_pipe_name),
+ GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);
+
+ if (sig_pipe_handle == INVALID_HANDLE_VALUE) {
+ g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_INFO,
+ "Signal pipe: Unable to open %s. Dead parent?",
+ sig_pipe_name);
+ exit_main(1);
+ }
+ }
#endif
break;
@@ -632,27 +657,38 @@ report_packet_drops(int drops)
gboolean
signal_pipe_check_running(void)
{
- /* any news from our parent (stdin)? -> just stop the capture */
- HANDLE handle;
+ /* any news from our parent? -> just stop the capture */
DWORD avail = 0;
gboolean result;
-
/* if we are running standalone, no check required */
if(!capture_child) {
return TRUE;
}
- handle = (HANDLE) GetStdHandle(STD_INPUT_HANDLE);
- result = PeekNamedPipe(handle, NULL, 0, NULL, &avail, NULL);
+ if(!sig_pipe_name || !sig_pipe_handle) {
+ /* This shouldn't happen */
+ g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_INFO,
+ "Signal pipe: No name or handle");
+ return FALSE;
+ }
+
+ /*
+ * XXX - We should have the process ID of the parent (from the "-Z" flag)
+ * at this point. Should we check to see if the parent is still alive,
+ * e.g. by using OpenProcess?
+ */
+
+ result = PeekNamedPipe(sig_pipe_handle, NULL, 0, NULL, &avail, NULL);
if(!result || avail > 0) {
/* peek failed or some bytes really available */
/* (if not piping from stdin this would fail) */
g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_INFO,
- "Signal pipe: Stop capture");
+ "Signal pipe: Stop capture: %s", sig_pipe_name);
g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG,
- "Signal pipe: handle: %x result: %u avail: %u", handle, result, avail);
+ "Signal pipe: %s (%p) result: %u avail: %u", sig_pipe_name,
+ sig_pipe_handle, result, avail);
return FALSE;
} else {
/* pipe ok and no bytes available */