See whether we can whitelist 'GPL (v3 or later)' for the output of Bison
[metze/wireshark/wip.git] / capture_sync.c
index 0e00856d5f9c5ab41148f848bd43a1145b445284..fded034adfb96058138f760b46356d5484c75afd 100644 (file)
  *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  */
 
-#ifdef HAVE_CONFIG_H
-# include "config.h"
-#endif
+#include "config.h"
 
 #ifdef HAVE_LIBPCAP
 
@@ -97,7 +95,9 @@
 #ifdef _WIN32
 #include "capture-wpcap.h"
 #endif
-#include "ui_util.h"
+
+#include "ui/ui_util.h"
+
 #include <wsutil/file_util.h>
 #include "log.h"
 
@@ -115,7 +115,7 @@ static const char *sync_pipe_signame(int);
 static gboolean sync_pipe_input_cb(gint source, gpointer user_data);
 static int sync_pipe_wait_for_child(int fork_child, gchar **msgp);
 static void pipe_convert_header(const guchar *header, int header_len, char *indicator, int *block_len);
-static int pipe_read_block(int pipe_fd, char *indicator, int len, char *msg,
+static ssize_t pipe_read_block(int pipe_fd, char *indicator, int len, char *msg,
                            char **err_msg);
 
 
@@ -129,12 +129,11 @@ sync_pipe_add_arg(const char **args, int *argc, const char *arg)
        pointers, *not* counting the NULL pointer at the end, so we have
        to add 2 in order to get the new size of the array, including the
        new pointer and the terminating NULL pointer. */
-    args = g_realloc( (gpointer) args, (*argc + 2) * sizeof (char *));
+    args = (const char **)g_realloc( (gpointer) args, (*argc + 2) * sizeof (char *));
 
     /* Stuff the pointer into the penultimate element of the array, which
        is the one at the index specified by "*argc". */
-    args[*argc] = arg;
-
+    args[*argc] = g_strdup(arg);
     /* Now bump the count. */
     (*argc)++;
 
@@ -224,8 +223,8 @@ win32strerror(DWORD error)
     size_t errlen;
     char *p;
 
-    FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, NULL, error, 0, errbuf,
-                   ERRBUF_SIZE, NULL);
+    FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
+                  NULL, error, 0, errbuf, ERRBUF_SIZE, NULL);
 
     /*
      * "FormatMessage()" "helpfully" sticks CR/LF at the end of the
@@ -303,7 +302,7 @@ init_pipe_args(int *argc) {
     /* Allocate the string pointer array with enough space for the
        terminating NULL pointer. */
     *argc = 0;
-    argv = g_malloc(sizeof (char *));
+    argv = (const char **)g_malloc(sizeof (char *));
     *argv = NULL;
 
     /* take Wireshark's absolute program path and replace "Wireshark" with "dumpcap" */
@@ -312,6 +311,9 @@ init_pipe_args(int *argc) {
     /* Make that the first argument in the argument list (argv[0]). */
     argv = sync_pipe_add_arg(argv, argc, exename);
 
+    /* sync_pipe_add_arg strdupes exename, so we should free our copy */
+    g_free(exename);
+
     return argv;
 }
 
@@ -320,7 +322,6 @@ init_pipe_args(int *argc) {
 gboolean
 sync_pipe_start(capture_options *capture_opts) {
     char ssnap[ARGV_NUMBER_LEN];
-    char sdlt[ARGV_NUMBER_LEN];
     char scount[ARGV_NUMBER_LEN];
     char sfilesize[ARGV_NUMBER_LEN];
     char sfile_duration[ARGV_NUMBER_LEN];
@@ -361,7 +362,6 @@ sync_pipe_start(capture_options *capture_opts) {
     int i;
     guint j;
     interface_options interface_opts;
-    gboolean no_ifaces;
 
     if (capture_opts->ifaces->len > 1)
         capture_opts->use_pcapng = TRUE;
@@ -428,56 +428,9 @@ sync_pipe_start(capture_options *capture_opts) {
         g_snprintf(sautostop_duration, ARGV_NUMBER_LEN, "duration:%d",capture_opts->autostop_duration);
         argv = sync_pipe_add_arg(argv, &argc, sautostop_duration);
     }
-    if (capture_opts->ifaces->len == 0) {
-        no_ifaces = TRUE;
-        interface_opts.name = g_strdup(capture_opts->iface);
-        if (capture_opts->iface_descr) {
-            interface_opts.descr = g_strdup(capture_opts->iface_descr);
-        } else {
-            interface_opts.descr = NULL;
-        }
-        interface_opts.cfilter = g_strdup(capture_opts->cfilter);
-        interface_opts.snaplen = capture_opts->snaplen;
-        interface_opts.linktype = capture_opts->linktype;
-        interface_opts.promisc_mode = capture_opts->promisc_mode;
-#if defined(_WIN32) || defined(HAVE_PCAP_CREATE)
-        interface_opts.buffer_size = capture_opts->buffer_size;
-#endif
-        interface_opts.monitor_mode = capture_opts->monitor_mode;
-#ifdef HAVE_PCAP_REMOTE
-        interface_opts.src_type = capture_opts->src_type;
-        if (capture_opts->remote_host) {
-            interface_opts.remote_host = g_strdup(capture_opts->remote_host);
-        } else {
-            interface_opts.remote_host = NULL;
-        }
-        if (capture_opts->remote_port) {
-            interface_opts.remote_port = g_strdup(capture_opts->remote_port);
-        } else {
-            interface_opts.remote_port = NULL;
-        }
-        interface_opts.auth_type = capture_opts->auth_type;
-        if (capture_opts->auth_username) {
-            interface_opts.auth_username = g_strdup(capture_opts->auth_username);
-        } else {
-            interface_opts.auth_username = NULL;
-        }
-        if (capture_opts->auth_password) {
-            interface_opts.auth_password = g_strdup(capture_opts->auth_password);
-        } else {
-            interface_opts.auth_password = NULL;
-        }
-        interface_opts.datatx_udp = capture_opts->datatx_udp;
-        interface_opts.nocap_rpcap = capture_opts->nocap_rpcap;
-        interface_opts.nocap_local = capture_opts->nocap_local;
-#endif
-#ifdef HAVE_PCAP_SETSAMPLING
-        interface_opts.sampling_method = capture_opts->sampling_method;
-        interface_opts.sampling_param  = capture_opts->sampling_param;
-#endif
-        g_array_append_val(capture_opts->ifaces, interface_opts);
-    } else {
-        no_ifaces = FALSE;
+
+    if (capture_opts->group_read_access) {
+        argv = sync_pipe_add_arg(argv, &argc, "-g");
     }
 
     for (j = 0; j < capture_opts->ifaces->len; j++) {
@@ -490,7 +443,6 @@ sync_pipe_start(capture_options *capture_opts) {
             argv = sync_pipe_add_arg(argv, &argc, "-f");
             argv = sync_pipe_add_arg(argv, &argc, interface_opts.cfilter);
         }
-
         if (interface_opts.snaplen != WTAP_MAX_PACKET_SIZE) {
             argv = sync_pipe_add_arg(argv, &argc, "-s");
             g_snprintf(ssnap, ARGV_NUMBER_LEN, "%d", interface_opts.snaplen);
@@ -499,8 +451,7 @@ sync_pipe_start(capture_options *capture_opts) {
 
         if (interface_opts.linktype != -1) {
             argv = sync_pipe_add_arg(argv, &argc, "-y");
-            g_snprintf(sdlt, ARGV_NUMBER_LEN, "%s", linktype_val_to_name(interface_opts.linktype));
-            argv = sync_pipe_add_arg(argv, &argc, sdlt);
+            argv = sync_pipe_add_arg(argv, &argc, linktype_val_to_name(interface_opts.linktype));
         }
 
         if (!interface_opts.promisc_mode) {
@@ -508,16 +459,18 @@ sync_pipe_start(capture_options *capture_opts) {
         }
 
 #if defined(_WIN32) || defined(HAVE_PCAP_CREATE)
-        if (interface_opts.buffer_size != 1) {
+        if (interface_opts.buffer_size != DEFAULT_CAPTURE_BUFFER_SIZE) {
             argv = sync_pipe_add_arg(argv, &argc, "-B");
             g_snprintf(buffer_size, ARGV_NUMBER_LEN, "%d", interface_opts.buffer_size);
             argv = sync_pipe_add_arg(argv, &argc, buffer_size);
         }
 #endif
 
+#ifdef HAVE_PCAP_CREATE
         if (interface_opts.monitor_mode) {
             argv = sync_pipe_add_arg(argv, &argc, "-I");
         }
+#endif
 
 #ifdef HAVE_PCAP_REMOTE
         if (interface_opts.datatx_udp)
@@ -547,9 +500,6 @@ sync_pipe_start(capture_options *capture_opts) {
         }
 #endif
     }
-    if (no_ifaces) {
-        capture_opts->ifaces = g_array_remove_index(capture_opts->ifaces, 0);
-    }
 
     /* dumpcap should be running in capture child mode (hidden feature) */
 #ifndef DEBUG_CHILD
@@ -582,7 +532,9 @@ sync_pipe_start(capture_options *capture_opts) {
         /* Couldn't create the pipe between parent and child. */
         report_failure("Couldn't create sync pipe: %s",
                        win32strerror(GetLastError()));
-        g_free( (gpointer) argv[0]);
+        for (i = 0; i < argc; i++) {
+            g_free( (gpointer) argv[i]);
+        }
         g_free( (gpointer) argv);
         return FALSE;
     }
@@ -597,7 +549,9 @@ sync_pipe_start(capture_options *capture_opts) {
         /* Couldn't create the signal pipe between parent and child. */
         report_failure("Couldn't create signal pipe: %s",
                        win32strerror(GetLastError()));
-        g_free( (gpointer) argv[0]);
+        for (i = 0; i < argc; i++) {
+            g_free( (gpointer) argv[i]);
+        }
         g_free( (gpointer) argv);
         return FALSE;
     }
@@ -634,7 +588,9 @@ sync_pipe_start(capture_options *capture_opts) {
                        args->str, win32strerror(GetLastError()));
         CloseHandle(sync_pipe_read);
         CloseHandle(sync_pipe_write);
-        g_free( (gpointer) argv[0]);
+        for (i = 0; i < argc; i++) {
+            g_free( (gpointer) argv[i]);
+        }
         g_free( (gpointer) argv);
         return FALSE;
     }
@@ -651,8 +607,10 @@ sync_pipe_start(capture_options *capture_opts) {
 #else /* _WIN32 */
     if (pipe(sync_pipe) < 0) {
         /* Couldn't create the pipe between parent and child. */
-        report_failure("Couldn't create sync pipe: %s", strerror(errno));
-        g_free( (gpointer) argv[0]);
+        report_failure("Couldn't create sync pipe: %s", g_strerror(errno));
+        for (i = 0; i < argc; i++) {
+            g_free( (gpointer) argv[i]);
+        }
         g_free(argv);
         return FALSE;
     }
@@ -664,9 +622,9 @@ sync_pipe_start(capture_options *capture_opts) {
          */
         dup2(sync_pipe[PIPE_WRITE], 2);
         ws_close(sync_pipe[PIPE_READ]);
-        execv(argv[0], (gpointer)argv);
+        execv(argv[0], (char * const*)argv);
         g_snprintf(errmsg, sizeof errmsg, "Couldn't run %s in child process: %s",
-                   argv[0], strerror(errno));
+                   argv[0], g_strerror(errno));
         sync_pipe_errmsg_to_parent(2, errmsg, "");
 
         /* Exit with "_exit()", so that we don't close the connection
@@ -682,7 +640,9 @@ sync_pipe_start(capture_options *capture_opts) {
     sync_pipe_read_fd = sync_pipe[PIPE_READ];
 #endif
 
-    g_free( (gpointer) argv[0]);  /* exename */
+    for (i = 0; i < argc; i++) {
+        g_free( (gpointer) argv[i]);
+    }
 
     /* Parent process - read messages from the child process over the
        sync pipe. */
@@ -700,7 +660,7 @@ sync_pipe_start(capture_options *capture_opts) {
 
     if (capture_opts->fork_child == -1) {
         /* We couldn't even create the child process. */
-        report_failure("Couldn't create child process: %s", strerror(errno));
+        report_failure("Couldn't create child process: %s", g_strerror(errno));
         ws_close(sync_pipe_read_fd);
 #ifdef _WIN32
         ws_close(capture_opts->signal_pipe_write_fd);
@@ -753,13 +713,12 @@ sync_pipe_open_command(const char** argv, int *data_read_fd,
     SECURITY_ATTRIBUTES sa;
     STARTUPINFO si;
     PROCESS_INFORMATION pi;
-    int i;
 #else
     char errmsg[1024+1];
     int sync_pipe[2];                       /* pipe used to send messages from child to parent */
     int data_pipe[2];                       /* pipe used to send data from child to parent */
 #endif
-
+    int i;
     *fork_child = -1;
     *data_read_fd = -1;
     *message_read_fd = -1;
@@ -785,7 +744,9 @@ sync_pipe_open_command(const char** argv, int *data_read_fd,
         /* Couldn't create the message pipe between parent and child. */
         *msg = g_strdup_printf("Couldn't create sync pipe: %s",
                                win32strerror(GetLastError()));
-        g_free( (gpointer) argv[0]);
+        for (i = 0; argv[i] != NULL; i++) {
+            g_free( (gpointer) argv[i]);
+        }
         g_free( (gpointer) argv);
         return -1;
     }
@@ -798,7 +759,9 @@ sync_pipe_open_command(const char** argv, int *data_read_fd,
                                win32strerror(GetLastError()));
         CloseHandle(sync_pipe[PIPE_READ]);
         CloseHandle(sync_pipe[PIPE_WRITE]);
-        g_free( (gpointer) argv[0]);
+        for (i = 0; argv[i] != NULL; i++) {
+            g_free( (gpointer) argv[i]);
+        }
         g_free( (gpointer) argv);
         return -1;
     }
@@ -836,7 +799,9 @@ sync_pipe_open_command(const char** argv, int *data_read_fd,
         CloseHandle(data_pipe[PIPE_WRITE]);
         CloseHandle(sync_pipe[PIPE_READ]);
         CloseHandle(sync_pipe[PIPE_WRITE]);
-        g_free( (gpointer) argv[0]);
+        for (i = 0; argv[i] != NULL; i++) {
+            g_free( (gpointer) argv[i]);
+        }
         g_free( (gpointer) argv);
         return -1;
     }
@@ -851,8 +816,10 @@ sync_pipe_open_command(const char** argv, int *data_read_fd,
     /* Create a pipe for the child process to send us messages */
     if (pipe(sync_pipe) < 0) {
         /* Couldn't create the message pipe between parent and child. */
-        *msg = g_strdup_printf("Couldn't create sync pipe: %s", strerror(errno));
-        g_free( (gpointer) argv[0]);
+        *msg = g_strdup_printf("Couldn't create sync pipe: %s", g_strerror(errno));
+        for (i = 0; argv[i] != NULL; i++) {
+            g_free( (gpointer) argv[i]);
+        }
         g_free(argv);
         return -1;
     }
@@ -860,10 +827,12 @@ sync_pipe_open_command(const char** argv, int *data_read_fd,
     /* Create a pipe for the child process to send us data */
     if (pipe(data_pipe) < 0) {
         /* Couldn't create the data pipe between parent and child. */
-        *msg = g_strdup_printf("Couldn't create data pipe: %s", strerror(errno));
+        *msg = g_strdup_printf("Couldn't create data pipe: %s", g_strerror(errno));
         ws_close(sync_pipe[PIPE_READ]);
         ws_close(sync_pipe[PIPE_WRITE]);
-        g_free( (gpointer) argv[0]);
+        for (i = 0; argv[i] != NULL; i++) {
+            g_free( (gpointer) argv[i]);
+        }
         g_free(argv);
         return -1;
     }
@@ -879,9 +848,9 @@ sync_pipe_open_command(const char** argv, int *data_read_fd,
         dup2(sync_pipe[PIPE_WRITE], 2);
         ws_close(sync_pipe[PIPE_READ]);
         ws_close(sync_pipe[PIPE_WRITE]);
-        execv(argv[0], (gpointer)argv);
+        execv(argv[0], (char * const*)argv);
         g_snprintf(errmsg, sizeof errmsg, "Couldn't run %s in child process: %s",
-                   argv[0], strerror(errno));
+                   argv[0], g_strerror(errno));
         sync_pipe_errmsg_to_parent(2, errmsg, "");
 
         /* Exit with "_exit()", so that we don't close the connection
@@ -898,7 +867,9 @@ sync_pipe_open_command(const char** argv, int *data_read_fd,
     *message_read_fd = sync_pipe[PIPE_READ];
 #endif
 
-    g_free( (gpointer) argv[0]);  /* exename */
+    for (i = 0; argv[i] != NULL; i++) {
+        g_free( (gpointer) argv[i]);
+    }
 
     /* Parent process - read messages from the child process over the
        sync pipe. */
@@ -918,7 +889,7 @@ sync_pipe_open_command(const char** argv, int *data_read_fd,
 
     if (*fork_child == -1) {
         /* We couldn't even create the child process. */
-        *msg = g_strdup_printf("Couldn't create child process: %s", strerror(errno));
+        *msg = g_strdup_printf("Couldn't create child process: %s", g_strerror(errno));
         ws_close(*data_read_fd);
         ws_close(*message_read_fd);
         return -1;
@@ -930,14 +901,16 @@ sync_pipe_open_command(const char** argv, int *data_read_fd,
 }
 
 /*
- * 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().
+ * Close the pipes we're using to read from dumpcap, and wait for it
+ * to exit.  On success, *msgp is unchanged, and the exit status of
+ * dumpcap is returned.  On failure (which includes "dumpcap exited
+ * due to being killed by a signal or an exception"), *msgp points
+ * to an error message for the failure, and -1 is returned.  In the
+ * latter case, *msgp must be freed with g_free().
  */
 static int
 sync_pipe_close_command(int *data_read_fd, int *message_read_fd,
-                        int *fork_child, gchar **msg)
+                        int *fork_child, gchar **msgp)
 {
     ws_close(*data_read_fd);
     if (message_read_fd != NULL)
@@ -948,7 +921,7 @@ sync_pipe_close_command(int *data_read_fd, int *message_read_fd,
     sync_pipe_kill(*fork_child);
 #endif
 
-    return sync_pipe_wait_for_child(*fork_child, msg);
+    return sync_pipe_wait_for_child(*fork_child, msgp);
 }
 
 /*
@@ -974,7 +947,7 @@ sync_pipe_run_command(const char** argv, gchar **data, gchar **primary_msg,
     int data_pipe_read_fd, sync_pipe_read_fd, fork_child, ret;
     char *wait_msg;
     gchar buffer[PIPE_BUF_SIZE+1];
-    int  nread;
+    ssize_t nread;
     char indicator;
     int  primary_msg_len;
     char *primary_msg_text;
@@ -982,7 +955,7 @@ sync_pipe_run_command(const char** argv, gchar **data, gchar **primary_msg,
     char *secondary_msg_text;
     char *combined_msg;
     GString *data_buf = NULL;
-    int count;
+    ssize_t count;
 
     ret = sync_pipe_open_command(argv, &data_pipe_read_fd, &sync_pipe_read_fd,
                                  &fork_child, &msg);
@@ -1046,10 +1019,10 @@ sync_pipe_run_command(const char** argv, gchar **data, gchar **primary_msg,
          */
 
         /* convert primary message */
-        pipe_convert_header(buffer, 4, &indicator, &primary_msg_len);
+        pipe_convert_header((guchar*)buffer, 4, &indicator, &primary_msg_len);
         primary_msg_text = buffer+4;
         /* convert secondary message */
-        pipe_convert_header(primary_msg_text + primary_msg_len, 4, &indicator,
+        pipe_convert_header((guchar*)primary_msg_text + primary_msg_len, 4, &indicator,
                             &secondary_msg_len);
         secondary_msg_text = primary_msg_text + primary_msg_len + 4;
         /* the capture child will close the sync_pipe, nothing to do */
@@ -1139,6 +1112,53 @@ sync_pipe_run_command(const char** argv, gchar **data, gchar **primary_msg,
     return ret;
 }
 
+int
+sync_interface_set_80211_chan(const gchar *iface, const char *freq, const gchar *type,
+                              gchar **data, gchar **primary_msg,
+                              gchar **secondary_msg)
+{
+    int argc, ret;
+    const char **argv;
+    gchar *opt;
+
+    argv = init_pipe_args(&argc);
+
+    if (!argv) {
+        *primary_msg = g_strdup("We don't know where to find dumpcap.");
+        *secondary_msg = NULL;
+        *data = NULL;
+        return -1;
+    }
+
+    argv = sync_pipe_add_arg(argv, &argc, "-i");
+    argv = sync_pipe_add_arg(argv, &argc, iface);
+
+    if (type)
+        opt = g_strdup_printf("%s,%s", freq, type);
+    else
+        opt = g_strdup_printf("%s", freq);
+
+    if (!opt) {
+        *primary_msg = g_strdup("Out of mem.");
+        *secondary_msg = NULL;
+        *data = NULL;
+        return -1;
+    }
+
+    argv = sync_pipe_add_arg(argv, &argc, "-k");
+    argv = sync_pipe_add_arg(argv, &argc, opt);
+
+#ifndef DEBUG_CHILD
+    /* Run dumpcap in capture child mode */
+    argv = sync_pipe_add_arg(argv, &argc, "-Z");
+    argv = sync_pipe_add_arg(argv, &argc, SIGNAL_PIPE_CTRL_ID_NONE);
+#endif
+
+    ret = sync_pipe_run_command(argv, data, primary_msg, secondary_msg);
+    g_free(opt);
+    return ret;
+}
+
 /*
  * Get the list of interfaces using dumpcap.
  *
@@ -1240,7 +1260,7 @@ sync_interface_stats_open(int *data_read_fd, int *fork_child, gchar **msg)
     int message_read_fd, ret;
     char *wait_msg;
     gchar buffer[PIPE_BUF_SIZE+1];
-    int  nread;
+    ssize_t nread;
     char indicator;
     int  primary_msg_len;
     char *primary_msg_text;
@@ -1321,10 +1341,10 @@ sync_interface_stats_open(int *data_read_fd, int *fork_child, gchar **msg)
          */
 
         /* convert primary message */
-        pipe_convert_header(buffer, 4, &indicator, &primary_msg_len);
+        pipe_convert_header((guchar*)buffer, 4, &indicator, &primary_msg_len);
         primary_msg_text = buffer+4;
         /* convert secondary message */
-        pipe_convert_header(primary_msg_text + primary_msg_len, 4, &indicator,
+        pipe_convert_header((guchar*)primary_msg_text + primary_msg_len, 4, &indicator,
                             &secondary_msg_len);
         /*secondary_msg_text = primary_msg_text + primary_msg_len + 4;*/
         /* the capture child will close the sync_pipe, nothing to do */
@@ -1382,16 +1402,23 @@ sync_interface_stats_open(int *data_read_fd, int *fork_child, gchar **msg)
 int
 sync_interface_stats_close(int *read_fd, int *fork_child, gchar **msg)
 {
+#ifndef _WIN32
+    /*
+     * Don't bother waiting for the child. sync_pipe_close_command
+     * does this for us on Windows.
+     */
+    sync_pipe_kill(*fork_child);
+#endif
     return sync_pipe_close_command(read_fd, NULL, fork_child, msg);
 }
 
 /* read a number of bytes from a pipe */
 /* (blocks until enough bytes read or an error occurs) */
-static int
+static ssize_t
 pipe_read_bytes(int pipe_fd, char *bytes, int required, char **msg)
 {
-    int newly;
-    int offset = 0;
+    ssize_t newly;
+    ssize_t offset = 0;
     int error;
 
     while(required) {
@@ -1408,13 +1435,13 @@ pipe_read_bytes(int pipe_fd, char *bytes, int required, char **msg)
             error = errno;
             g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG,
                   "read from pipe %d: error(%u): %s", pipe_fd, error,
-                  strerror(error));
+                  g_strerror(error));
             *msg = g_strdup_printf("Error reading from sync pipe: %s",
-                                   strerror(error));
+                                   g_strerror(error));
             return newly;
         }
 
-        required -= newly;
+        required -= (int)newly;
         offset += newly;
     }
 
@@ -1455,7 +1482,7 @@ static gboolean pipe_data_available(int pipe_fd) {
 /* Read a line from a pipe, similar to fgets */
 int
 sync_pipe_gets_nonblock(int pipe_fd, char *bytes, int max) {
-    int newly;
+    ssize_t newly;
     int offset = -1;
 
     while(offset < max - 1) {
@@ -1466,11 +1493,11 @@ sync_pipe_gets_nonblock(int pipe_fd, char *bytes, int max) {
         if (newly == 0) {
             /* EOF - not necessarily an error */
             break;
-        } else if (newly < 0) {
+        } else if (newly == -1) {
             /* error */
             g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG,
-                  "read from pipe %d: error(%u): %s", pipe_fd, errno, strerror(errno));
-            return newly;
+                  "read from pipe %d: error(%u): %s", pipe_fd, errno, g_strerror(errno));
+            return -1;
         } else if (bytes[offset] == '\n') {
             break;
         }
@@ -1491,19 +1518,19 @@ pipe_convert_header(const guchar *header, int header_len, char *indicator, int *
 
     /* convert header values */
     *indicator = header[0];
-    *block_len = header[1]<<16 | header[2]<<8 | header[3];
+    *block_len = (header[1]&0xFF)<<16 | (header[2]&0xFF)<<8 | (header[3]&0xFF);
 }
 
 /* read a message from the sending pipe in the standard format
    (1-byte message indicator, 3-byte message length (excluding length
    and indicator field), and the rest is the message) */
-static int
+static ssize_t
 pipe_read_block(int pipe_fd, char *indicator, int len, char *msg,
                 char **err_msg)
 {
     int required;
-    int newly;
-    guchar header[4];
+    ssize_t newly;
+    gchar header[4];
 
     /* read header (indicator and 3-byte length) */
     newly = pipe_read_bytes(pipe_fd, header, 4, err_msg);
@@ -1519,19 +1546,19 @@ pipe_read_block(int pipe_fd, char *indicator, int len, char *msg,
             return 0;
         }
         g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG,
-              "read %d failed to read header: %u", pipe_fd, newly);
+              "read %d failed to read header: %lu", pipe_fd, (long)newly);
         if (newly != -1) {
             /*
              * Short read, but not an immediate EOF.
              */
-            *err_msg = g_strdup_printf("Premature EOF reading from sync pipe: got only %d bytes",
-                                       newly);
+            *err_msg = g_strdup_printf("Premature EOF reading from sync pipe: got only %ld bytes",
+                                       (long)newly);
         }
         return -1;
     }
 
     /* convert header values */
-    pipe_convert_header(header, 4, indicator, &required);
+    pipe_convert_header((guchar*)header, 4, indicator, &required);
 
     /* only indicator with no value? */
     if(required == 0) {
@@ -1543,12 +1570,17 @@ pipe_read_block(int pipe_fd, char *indicator, int len, char *msg,
     /* does the data fit into the given buffer? */
     if(required > len) {
         g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG,
-              "read %d length error, required %d > len %d, indicator: %u",
-              pipe_fd, required, len, *indicator);
+              "read %d length error, required %d > len %d, header: 0x%02x 0x%02x 0x%02x 0x%02x",
+              pipe_fd, required, len,
+              header[0], header[1], header[2], header[3]);
 
         /* 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_fd, &msg[sizeof(header)], len-sizeof(header));
+       if (newly < 0) { /* error */
+           g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG,
+                 "read from pipe %d: error(%u): %s", pipe_fd, errno, g_strerror(errno));
+       }
         *err_msg = g_strdup_printf("Unknown message from dumpcap, try to show it as a string: %s",
                                    msg);
         return -1;
@@ -1583,13 +1615,14 @@ sync_pipe_input_cb(gint source, gpointer user_data)
     capture_options *capture_opts = (capture_options *)user_data;
     int  ret;
     char buffer[SP_MAX_MSG_LEN+1];
-    int  nread;
+    ssize_t nread;
     char indicator;
     int  primary_len;
     char *primary_msg;
     int  secondary_len;
     char *secondary_msg;
     char *wait_msg, *combined_msg;
+    int npackets;
 
     nread = pipe_read_block(source, &indicator, SP_MAX_MSG_LEN, buffer,
                             &primary_msg);
@@ -1648,35 +1681,52 @@ sync_pipe_input_cb(gint source, gpointer user_data)
                alerted. Close the sync pipe. */
             ws_close(source);
 
-            /* the child has send us a filename which we couldn't open.
-               this probably means, the child is creating files faster than we can handle it.
-               this should only be the case for very fast file switches
-               we can't do much more than telling the child to stop
-               (this is the "emergency brake" if user e.g. wants to switch files every second) */
+            /* The child has sent us a filename which we couldn't open.
+
+               This could mean that the child is creating files faster
+              than we can handle it.  (XXX - why would that result in
+              a failure to open the file?)
+
+               That should only be the case for very fast file switches;
+               We can't do much more than telling the child to stop.
+               (This is the "emergency brake" if the user e.g. wants to
+              switch files every second).
+
+               This can also happen if the user specified "-", meaning
+               "standard output", as the capture file. */
             sync_pipe_stop(capture_opts);
+            capture_input_closed(capture_opts, NULL);
+            return FALSE;
         }
         break;
     case SP_PACKET_COUNT:
-        nread = atoi(buffer);
-        g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "sync_pipe_input_cb: new packets %u", nread);
-        capture_input_new_packets(capture_opts, nread);
+        npackets = atoi(buffer);
+        g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "sync_pipe_input_cb: new packets %u", npackets);
+        capture_input_new_packets(capture_opts, npackets);
         break;
     case SP_ERROR_MSG:
         /* convert primary message */
-        pipe_convert_header(buffer, 4, &indicator, &primary_len);
+        pipe_convert_header((guchar*)buffer, 4, &indicator, &primary_len);
         primary_msg = buffer+4;
         /* convert secondary message */
-        pipe_convert_header(primary_msg + primary_len, 4, &indicator, &secondary_len);
+        pipe_convert_header((guchar*)primary_msg + primary_len, 4, &indicator, &secondary_len);
         secondary_msg = primary_msg + primary_len + 4;
         /* message output */
         capture_input_error_message(capture_opts, primary_msg, secondary_msg);
         /* the capture child will close the sync_pipe, nothing to do for now */
         /* (an error message doesn't mean we have to stop capturing) */
         break;
-    case SP_BAD_FILTER:
-        capture_input_cfilter_error_message(capture_opts, buffer);
-        /* the capture child will close the sync_pipe, nothing to do for now */
-        break;
+    case SP_BAD_FILTER: {
+        char *ch;
+        int indx;
+
+        ch = strtok(buffer, ":");
+        indx = (int)strtol(ch, NULL, 10);
+        ch = strtok(NULL, ":");
+        capture_input_cfilter_error_message(capture_opts, indx, ch);
+         /* the capture child will close the sync_pipe, nothing to do for now */
+         break;
+        }
     case SP_DROPS:
         capture_input_drops(capture_opts, (guint32)strtoul(buffer, NULL, 10));
         break;
@@ -1689,21 +1739,36 @@ sync_pipe_input_cb(gint source, gpointer user_data)
 
 
 
-/* the child process is going down, wait until it's completely terminated */
+/*
+ * dumpcap is exiting; wait for it to exit.  On success, *msgp is
+ * unchanged, and the exit status of dumpcap is returned.  On
+ * failure (which includes "dumpcap exited due to being killed by
+ * a signal or an exception"), *msgp points to an error message
+ * for the failure, and -1 is returned.  In the latter case, *msgp
+ * must be freed with g_free().
+ */
 static int
 sync_pipe_wait_for_child(int fork_child, gchar **msgp)
 {
     int fork_child_status;
     int ret;
+    GTimeVal start_time;
+    GTimeVal end_time;
+    float elapsed;
+
+    /*
+     * GLIB_CHECK_VERSION(2,28,0) adds g_get_real_time which could minimize or
+     * replace this
+     */
+    g_get_current_time(&start_time);
 
     g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "sync_pipe_wait_for_child: wait till child closed");
     g_assert(fork_child != -1);
 
     *msgp = NULL; /* assume no error */
-    ret = 0;
 #ifdef _WIN32
     if (_cwait(&fork_child_status, fork_child, _WAIT_CHILD) == -1) {
-        *msgp = g_strdup_printf("Error from cwait(): %s", strerror(errno));
+        *msgp = g_strdup_printf("Error from cwait(): %s", g_strerror(errno));
         ret = -1;
     } else {
         /*
@@ -1745,12 +1810,15 @@ sync_pipe_wait_for_child(int fork_child, gchar **msgp)
             ret = -1;
         }
     } else {
-        *msgp = g_strdup_printf("Error from waitpid(): %s", strerror(errno));
+        *msgp = g_strdup_printf("Error from waitpid(): %s", g_strerror(errno));
         ret = -1;
     }
 #endif
 
-    g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "sync_pipe_wait_for_child: capture child closed");
+    g_get_current_time(&end_time);
+    elapsed = (float) ((end_time.tv_sec - start_time.tv_sec) +
+                       ((end_time.tv_usec - start_time.tv_usec) / 1e6));
+    g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "sync_pipe_wait_for_child: capture child closed after %.3fs", elapsed);
     return ret;
 }
 
@@ -1869,7 +1937,7 @@ signal_pipe_capquit_to_child(capture_options *capture_opts)
     ret = write(capture_opts->signal_pipe_write_fd, quit_msg, sizeof quit_msg);
     if(ret == -1) {
         g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_WARNING,
-              "signal_pipe_capquit_to_child: %d header: error %s", capture_opts->signal_pipe_write_fd, strerror(errno));
+              "signal_pipe_capquit_to_child: %d header: error %s", capture_opts->signal_pipe_write_fd, g_strerror(errno));
     }
 }
 #endif
@@ -1891,7 +1959,7 @@ sync_pipe_stop(capture_options *capture_opts)
         int sts = kill(capture_opts->fork_child, SIGINT);
         if (sts != 0) {
             g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_WARNING,
-                  "Sending SIGINT to child failed: %s\n", strerror(errno));
+                  "Sending SIGINT to child failed: %s\n", g_strerror(errno));
         }
 #else
 #define STOP_SLEEP_TIME 500 /* ms */
@@ -1931,7 +1999,7 @@ sync_pipe_kill(int fork_child)
         int sts = kill(fork_child, SIGTERM);    /* SIGTERM so it can clean up if necessary */
         if (sts != 0) {
             g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_WARNING,
-                  "Sending SIGTERM to child failed: %s\n", strerror(errno));
+                  "Sending SIGTERM to child failed: %s\n", g_strerror(errno));
         }
 #else
         /* Remark: This is not the preferred method of closing a process!