extcap: Multiple extcap instance support on Windows
authorTomasz Moń <desowin@gmail.com>
Wed, 11 Sep 2019 14:46:00 +0000 (16:46 +0200)
committerAnders Broman <a.broman58@gmail.com>
Mon, 23 Sep 2019 04:38:00 +0000 (04:38 +0000)
Wireshark does create named pipes and waits for the child process to
connect. The named pipe server handle is inheritable and thus available
in child dumpcap process. Pass the handle identifier instead of named
pipe name so dumpcap can use it.

Bug: 13653
Change-Id: Id2c019f67a63f1ea3d98b9da2153d6de5078cd01
Reviewed-on: https://code.wireshark.org/review/34503
Petri-Dish: Michael Mann <mmann78@netscape.net>
Tested-by: Petri Dish Buildbot
Reviewed-by: Anders Broman <a.broman58@gmail.com>
capchild/capture_sync.c
dumpcap.c
extcap.c

index c46871d229b7ec3e89bd2ea87c0abbd8b10286bf..d2ed2ee75ae7d810320e1a95c20d5fb1826025d4 100644 (file)
@@ -324,7 +324,15 @@ sync_pipe_start(capture_options *capture_opts, capture_session *cap_session, inf
 
         argv = sync_pipe_add_arg(argv, &argc, "-i");
         if (interface_opts->extcap_fifo != NULL)
+        {
+#ifdef _WIN32
+            char *pipe = g_strdup_printf("%s%" G_GUINTPTR_FORMAT, EXTCAP_PIPE_PREFIX, interface_opts->extcap_pipe_h);
+            argv = sync_pipe_add_arg(argv, &argc, pipe);
+            g_free(pipe);
+#else
             argv = sync_pipe_add_arg(argv, &argc, interface_opts->extcap_fifo);
+#endif
+        }
         else
             argv = sync_pipe_add_arg(argv, &argc, interface_opts->name);
 
@@ -500,11 +508,7 @@ sync_pipe_start(capture_options *capture_opts, capture_session *cap_session, inf
 #else
     si.dwFlags = STARTF_USESTDHANDLES|STARTF_USESHOWWINDOW;
     si.wShowWindow  = SW_HIDE;  /* this hides the console window */
-    if(interface_opts->extcap_pipe_h != INVALID_HANDLE_VALUE)
-        si.hStdInput = interface_opts->extcap_pipe_h;
-    else
-        si.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
-
+    si.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
     si.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
     si.hStdError = sync_pipe_write;
     /*si.hStdError = (HANDLE) _get_osfhandle(2);*/
index fa20b402b8ed000407ad9c4534db57f9317b4d1b..367a71ff8fe6aedf4ebd616c0e9f47a235bac531 100644 (file)
--- a/dumpcap.c
+++ b/dumpcap.c
@@ -1561,7 +1561,7 @@ cap_pipe_open_live(char *pipename,
     struct sockaddr_un sa;
 #else /* _WIN32 */
     char    *pncopy, *pos;
-    char* extcap_pipe_name;
+    guintptr extcap_pipe_handle;
 #endif
     gboolean extcap_pipe = FALSE;
     ssize_t  b;
@@ -1682,57 +1682,63 @@ cap_pipe_open_live(char *pipename,
         }
 
 #else /* _WIN32 */
-#define PIPE_STR "\\pipe\\"
-        /* Under Windows, named pipes _must_ have the form
-         * "\\<server>\pipe\<pipename>".  <server> may be "." for localhost.
-         */
-        pncopy = g_strdup(pipename);
-        if ( (pos=strstr(pncopy, "\\\\")) == pncopy) {
-            pos = strchr(pncopy + 3, '\\');
-            if (pos && g_ascii_strncasecmp(pos, PIPE_STR, strlen(PIPE_STR)) != 0)
-                pos = NULL;
+        if (sscanf(pipename, EXTCAP_PIPE_PREFIX "%" G_GUINTPTR_FORMAT, &extcap_pipe_handle) == 1)
+        {
+            /* The client is already connected to extcap pipe.
+             * We have inherited the handle from parent process.
+             */
+            extcap_pipe = TRUE;
+            pcap_src->cap_pipe_h = (HANDLE)extcap_pipe_handle;
         }
+        else
+        {
+#define PIPE_STR "\\pipe\\"
+            /* Under Windows, named pipes _must_ have the form
+             * "\\<server>\pipe\<pipename>".  <server> may be "." for localhost.
+             */
+            pncopy = g_strdup(pipename);
+            if ((pos = strstr(pncopy, "\\\\")) == pncopy) {
+                pos = strchr(pncopy + 3, '\\');
+                if (pos && g_ascii_strncasecmp(pos, PIPE_STR, strlen(PIPE_STR)) != 0)
+                    pos = NULL;
+            }
 
-        g_free(pncopy);
+            g_free(pncopy);
 
-        if (!pos) {
-            g_snprintf(errmsg, (gulong)errmsgl,
-                       "The capture session could not be initiated because\n"
-                       "\"%s\" is neither an interface nor a pipe.", pipename);
-            pcap_src->cap_pipe_err = PIPNEXIST;
-            return;
-        }
-        extcap_pipe_name = g_strconcat("\\\\.\\pipe\\", EXTCAP_PIPE_PREFIX, NULL);
-        extcap_pipe = strstr(pipename, extcap_pipe_name) ? TRUE : FALSE;
-        g_free(extcap_pipe_name);
+            if (!pos) {
+                g_snprintf(errmsg, (gulong)errmsgl,
+                    "The capture session could not be initiated because\n"
+                    "\"%s\" is neither an interface nor a pipe.", pipename);
+                pcap_src->cap_pipe_err = PIPNEXIST;
+                return;
+            }
 
-        /* Wait for the pipe to appear */
-        while (1) {
-            if(extcap_pipe)
-                pcap_src->cap_pipe_h = GetStdHandle(STD_INPUT_HANDLE);
-            else
+
+            /* Wait for the pipe to appear */
+            while (1) {
                 pcap_src->cap_pipe_h = CreateFile(utf_8to16(pipename), GENERIC_READ, 0, NULL,
-                                                   OPEN_EXISTING, 0, NULL);
+                        OPEN_EXISTING, 0, NULL);
 
-            if (pcap_src->cap_pipe_h != INVALID_HANDLE_VALUE)
-                break;
+                if (pcap_src->cap_pipe_h != INVALID_HANDLE_VALUE)
+                    break;
 
-            if (GetLastError() != ERROR_PIPE_BUSY) {
-                g_snprintf(errmsg, (gulong)errmsgl,
-                           "The capture session on \"%s\" could not be started "
-                           "due to error on pipe open: %s.",
-                           pipename, win32strerror(GetLastError()));
-                pcap_src->cap_pipe_err = PIPERR;
-                return;
-            }
+                if (GetLastError() != ERROR_PIPE_BUSY) {
+                    g_snprintf(errmsg, (gulong)errmsgl,
+                        "The capture session on \"%s\" could not be started "
+                        "due to error on pipe open: %s.",
+                        pipename, win32strerror(GetLastError()));
+                    pcap_src->cap_pipe_err = PIPERR;
+                    return;
+                }
 
-            if (!WaitNamedPipe(utf_8to16(pipename), 30 * 1000)) {
-                g_snprintf(errmsg, (gulong)errmsgl,
-                           "The capture session on \"%s\" timed out during "
-                           "pipe open: %s.",
-                           pipename, win32strerror(GetLastError()));
-                pcap_src->cap_pipe_err = PIPERR;
-                return;
+                if (!WaitNamedPipe(utf_8to16(pipename), 30 * 1000)) {
+                    g_snprintf(errmsg, (gulong)errmsgl,
+                        "The capture session on \"%s\" timed out during "
+                        "pipe open: %s.",
+                        pipename, win32strerror(GetLastError()));
+                    pcap_src->cap_pipe_err = PIPERR;
+                    return;
+                }
             }
         }
 #endif /* _WIN32 */
index 623ba189453cf07be08e5beb5c80f5560374ed0a..0fbfac3d9b5b84520e0e64d63bd01effb9c3be11 100644 (file)
--- a/extcap.c
+++ b/extcap.c
@@ -1511,7 +1511,7 @@ static gboolean extcap_create_pipe(const gchar *ifname, gchar **fifo, HANDLE *ha
     }
     else
     {
-        g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "\nWireshark Created pipe =>(%s)", pipename);
+        g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "\nWireshark Created pipe =>(%s) handle (%" G_GUINTPTR_FORMAT ")", pipename, *handle_out);
         *fifo = g_strdup(pipename);
     }