Invert check for getopt: NEED_GETOPT_H -> HAVE_GETOPT_H
[obnox/wireshark/wip.git] / dumpcap.c
index 7820cb736761fa8c42889704cff0db791f469136..99dd98f0d18db73a04f1d9542db00e9a3d4ebfcb 100644 (file)
--- a/dumpcap.c
+++ b/dumpcap.c
@@ -25,6 +25,7 @@
 # include "config.h"
 #endif
 
+#include <stdio.h>
 #include <stdlib.h> /* for exit() */
 #include <glib.h>
 
 #include <signal.h>
 #include <errno.h>
 
-#ifdef NEED_GETOPT_H
-#include "getopt.h"
+#ifdef HAVE_GETOPT_H
+#include <getopt.h>
+#else
+#include "wsgetopt.h"
 #endif
 
 #ifdef HAVE_NETDB_H
@@ -61,7 +64,6 @@
 #ifdef HAVE_LIBCAP
 # include <sys/prctl.h>
 # include <sys/capability.h>
-# include <stdio.h>
 #endif
 
 #include "ringbuffer.h"
@@ -76,9 +78,6 @@
 
 #ifdef _WIN32
 #include "capture-wpcap.h"
-#endif
-
-#ifdef _WIN32
 #include <wsutil/unicode-utils.h>
 #endif
 
@@ -111,10 +110,20 @@ FILE *debug_log;   /* for logging debug messages to  */
                    /*  is defined                    */
 #endif
 
+#ifdef _WIN32
+#define USE_THREADS
+#endif
+
 static gboolean capture_child = FALSE; /* FALSE: standalone call, TRUE: this is an Wireshark capture child */
 #ifdef _WIN32
 static gchar *sig_pipe_name = NULL;
 static HANDLE sig_pipe_handle = NULL;
+static gboolean signal_pipe_check_running(void);
+#endif
+
+#ifdef USE_THREADS
+static GAsyncQueue *cap_pipe_pending_q, *cap_pipe_done_q;
+static GMutex *cap_pipe_read_mtx;
 #endif
 
 /** Stop a low-level capture (stops the capture child). */
@@ -129,7 +138,7 @@ static void capture_loop_stop(void);
  * is interrupted by a signal on UN*X, just go back and try again to
  * read again.
  *
- * On UN*X, we catch SIGUSR1 as a "stop capturing" signal, and, in
+ * On UN*X, we catch SIGINT as a "stop capturing" signal, and, in
  * the signal handler, set a flag to stop capturing; however, without
  * a guarantee of that sort, we can't guarantee that we'll stop capturing
  * if the read will be retried and won't time out if no packets arrive.
@@ -152,7 +161,7 @@ static void capture_loop_stop(void);
  * exit pcap_dispatch() with an indication that no packets have arrived,
  * and will break out of the capture loop at that point.
  *
- * On Windows, we can't send a SIGUSR1 to stop capturing, so none of this
+ * On Windows, we can't send a SIGINT to stop capturing, so none of this
  * applies in any case.
  *
  * XXX - the various BSDs appear to define BSD in <sys/param.h>; we don't
@@ -197,11 +206,18 @@ typedef struct _loop_data {
   gboolean       from_cap_pipe;         /* TRUE if we are capturing data from a capture pipe */
   struct pcap_hdr cap_pipe_hdr;         /* Pcap header when capturing from a pipe */
   struct pcaprec_modified_hdr cap_pipe_rechdr;  /* Pcap record header when capturing from a pipe */
+#ifdef _WIN32
+  HANDLE         cap_pipe_h;            /* The handle of the capture pipe */
+#else
   int            cap_pipe_fd;           /* the file descriptor of the capture pipe */
+#endif
   gboolean       cap_pipe_modified;     /* TRUE if data in the pipe uses modified pcap headers */
   gboolean       cap_pipe_byte_swapped; /* TRUE if data in the pipe is byte swapped */
-  unsigned int   cap_pipe_bytes_to_read;/* Used by cap_pipe_dispatch */
-  unsigned int   cap_pipe_bytes_read;   /* Used by cap_pipe_dispatch */
+#ifdef USE_THREADS
+  char *         cap_pipe_buf;          /* Pointer to the data buffer we read into */
+#endif /* USE_THREADS */
+  int   cap_pipe_bytes_to_read;/* Used by cap_pipe_dispatch */
+  int   cap_pipe_bytes_read;   /* Used by cap_pipe_dispatch */
   enum {
          STATE_EXPECT_REC_HDR,
          STATE_READ_REC_HDR,
@@ -213,6 +229,7 @@ typedef struct _loop_data {
   /* output file */
   FILE          *pdh;
   int            linktype;
+  int            file_snaplen;
   gint           wtap_linktype;
   long           bytes_written;
 
@@ -226,7 +243,7 @@ static const char please_report[] =
     "(This is not a crash; please do not report it as such.)";
 
 /*
- * This needs to be static, so that the SIGUSR1 handler can clear the "go"
+ * This needs to be static, so that the SIGINT handler can clear the "go"
  * flag.
  */
 static loop_data   global_ld;
@@ -235,7 +252,15 @@ static loop_data   global_ld;
 /*
  * Timeout, in milliseconds, for reads from the stream of captured packets.
  */
+#if defined(__APPLE__) && defined(__LP64__)
+#define        CAP_READ_TIMEOUT        1000
+#else
 #define        CAP_READ_TIMEOUT        250
+#endif
+/*
+ * Timeout, in microseconds, for threaded reads from a pipe.
+ */
+#define THREAD_READ_TIMEOUT   100
 static char *cap_pipe_err_str;
 
 static void
@@ -250,12 +275,7 @@ static void capture_loop_packet_cb(u_char *user, const struct pcap_pkthdr *phdr,
 static void capture_loop_get_errmsg(char *errmsg, int errmsglen, const char *fname,
                          int err, gboolean is_close);
 
-
-#if __GNUC__ >= 2
-static void exit_main(int err) __attribute__ ((noreturn));
-#else
-static void exit_main(int err);
-#endif
+static void exit_main(int err) G_GNUC_NORETURN;
 
 static void report_new_capture_file(const char *filename);
 static void report_packet_count(int packet_count);
@@ -263,10 +283,6 @@ static void report_packet_drops(guint32 drops);
 static void report_capture_error(const char *error_msg, const char *secondary_error_msg);
 static void report_cfilter_error(const char *cfilter, const char *errmsg);
 
-#ifdef _WIN32
-static gboolean signal_pipe_check_running(void);
-#endif
-
 static void
 print_usage(gboolean print_ver) {
 
@@ -321,6 +337,7 @@ print_usage(gboolean print_ver) {
   fprintf(output, "  -b <ringbuffer opt.> ... duration:NUM - switch to next file after NUM secs\n");
   fprintf(output, "                           filesize:NUM - switch to next file after NUM KB\n");
   fprintf(output, "                              files:NUM - ringbuffer: replace after NUM files\n");
+  fprintf(output, "  -n                       use pcapng format instead of pcap\n");
   /*fprintf(output, "\n");*/
   fprintf(output, "Miscellaneous:\n");
   fprintf(output, "  -v                       print version information and exit\n");
@@ -411,9 +428,6 @@ print_statistics_loop(gboolean machine_readable)
     pcap_t      *pch;
     char        errbuf[PCAP_ERRBUF_SIZE];
     struct pcap_stat ps;
-#ifndef _WIN32
-    struct sigaction act;
-#endif 
 
     if_list = get_interface_list(&err, &err_str);
     if (if_list == NULL) {
@@ -456,14 +470,6 @@ print_statistics_loop(gboolean machine_readable)
             "Dropped");
     }
 
-#ifndef _WIN32
-    /* handle SIGPIPE signal to default action */
-    act.sa_handler = SIG_DFL;
-    sigemptyset(&act.sa_mask);
-    act.sa_flags = SA_RESTART;
-    sigaction(SIGPIPE,&act,NULL);
-#endif 
-
     global_ld.go = TRUE;
     while (global_ld.go) {
         for (stat_entry = g_list_first(stat_list); stat_entry != NULL; stat_entry = g_list_next(stat_entry)) {
@@ -480,7 +486,8 @@ print_statistics_loop(gboolean machine_readable)
             }
         }
 #ifdef _WIN32
-        Sleep(1 * 1000);
+        if (! global_ld.from_cap_pipe)
+            Sleep(1 * 1000);
 #else
         sleep(1);
 #endif
@@ -502,7 +509,7 @@ print_statistics_loop(gboolean machine_readable)
 
 #ifdef _WIN32
 static BOOL WINAPI
-capture_cleanup(DWORD dwCtrlType)
+capture_cleanup_handler(DWORD dwCtrlType)
 {
     /* CTRL_C_EVENT is sort of like SIGINT, CTRL_BREAK_EVENT is unique to
        Windows, CTRL_CLOSE_EVENT is sort of like SIGHUP, CTRL_LOGOFF_EVENT
@@ -534,16 +541,16 @@ capture_cleanup(DWORD dwCtrlType)
 }
 #else
 static void
-capture_cleanup(int signum)
+capture_cleanup_handler(int signum _U_)
 {
     /* On UN*X, we cleanly shut down the capture on SIGINT, SIGHUP, and
        SIGTERM.  We assume that if the user wanted it to keep running
        after they logged out, they'd have nohupped it. */
 
-    g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_INFO,
-        "Console: Signal");
-    g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG,
-        "Console: Signal, signal value: %u", signum);
+    /* Note: don't call g_log() in the signal handler: if we happened to be in
+     * g_log() in process context when the signal came in, g_log will detect
+     * the "recursion" and abort.
+     */
 
     capture_loop_stop();
 }
@@ -683,18 +690,100 @@ cap_pipe_adjust_header(gboolean byte_swapped, struct pcap_hdr *hdr, struct pcapr
   }
 }
 
-/* Provide select() functionality for a single file descriptor
- * on both UNIX/POSIX and Windows.
+#ifdef USE_THREADS
+/*
+ * Thread function that reads from a pipe and pushes the data
+ * to the main application thread.
+ */
+/*
+ * XXX Right now we use async queues for basic signaling. The main thread
+ * sets cap_pipe_buf and cap_bytes_to_read, then pushes an item onto
+ * cap_pipe_pending_q which triggers a read in the cap_pipe_read thread.
+ * Iff the read is successful cap_pipe_read pushes an item onto
+ * cap_pipe_done_q, otherwise an error is signaled. No data is passed in
+ * the queues themselves (yet).
  *
- * The Windows version calls WaitForSingleObject instead of
- * select().
+ * We might want to move some of the cap_pipe_dispatch logic here so that
+ * we can let cap_pipe_read run independently, queuing up multiple reads
+ * for the main thread (and possibly get rid of cap_pipe_read_mtx).
+ */
+static void *cap_pipe_read(void *ld_ptr) {
+    loop_data *ld = (loop_data *)ld_ptr;
+    int bytes_read;
+#ifdef _WIN32
+    BOOL res;
+    DWORD b, last_err;
+#else /* _WIN32 */
+    int b;
+#endif /* _WIN32 */
+
+    while (ld->cap_pipe_err == PIPOK) {
+        g_async_queue_pop(cap_pipe_pending_q); /* Wait for our cue (ahem) from the main thread */
+        g_mutex_lock(cap_pipe_read_mtx);
+        bytes_read = 0;
+        while (bytes_read < (int) ld->cap_pipe_bytes_to_read) {
+#ifdef _WIN32
+            /* If we try to use read() on a named pipe on Windows with partial
+             * data it appears to return EOF.
+             */
+            res = ReadFile(ld->cap_pipe_h, ld->cap_pipe_buf+bytes_read,
+                           ld->cap_pipe_bytes_to_read - bytes_read,
+                           &b, NULL);
+
+            bytes_read += b;
+            if (!res) {
+                last_err = GetLastError();
+                if (last_err == ERROR_MORE_DATA) {
+                    continue;
+                } else if (last_err == ERROR_HANDLE_EOF || last_err == ERROR_BROKEN_PIPE || last_err == ERROR_PIPE_NOT_CONNECTED) {
+                    ld->cap_pipe_err = PIPEOF;
+                    bytes_read = 0;
+                    break;
+                }
+                ld->cap_pipe_err = PIPERR;
+                bytes_read = -1;
+                break;
+            } else if (b == 0 && ld->cap_pipe_bytes_to_read > 0) {
+                ld->cap_pipe_err = PIPEOF;
+                bytes_read = 0;
+                break;
+            }
+#else /* _WIN32 */
+            b = read(ld->cap_pipe_fd, ld->cap_pipe_buf+bytes_read,
+                     ld->cap_pipe_bytes_to_read - bytes_read);
+            if (b <= 0) {
+                if (b == 0) {
+                    ld->cap_pipe_err = PIPEOF;
+                    bytes_read = 0;
+                    break;
+                } else {
+                    ld->cap_pipe_err = PIPERR;
+                    bytes_read = -1;
+                    break;
+                }
+            } else {
+                bytes_read += b;
+            }
+#endif /*_WIN32 */
+        }
+        ld->cap_pipe_bytes_read = bytes_read;
+        if (ld->cap_pipe_bytes_read >= ld->cap_pipe_bytes_to_read) {
+            g_async_queue_push(cap_pipe_done_q, ld->cap_pipe_buf); /* Any non-NULL value will do */
+        }
+        g_mutex_unlock(cap_pipe_read_mtx);
+    }
+    return NULL;
+}
+#endif /* USE_THREADS */
+
+/* Provide select() functionality for a single file descriptor
+ * on UNIX/POSIX. Windows uses cap_pipe_read via a thread.
  *
  * Returns the same values as select.  If an error is returned,
  * the string cap_pipe_err_str should be used instead of errno.
  */
 static int
 cap_pipe_select(int pipe_fd) {
-#ifndef _WIN32
   fd_set      rfds;
   struct timeval timeout, *pto;
   int sel_ret;
@@ -713,44 +802,6 @@ cap_pipe_select(int pipe_fd) {
     cap_pipe_err_str = strerror(errno);
   return sel_ret;
 }
-#else
-  /* XXX - Should we just use file handles exclusively under Windows?
-   * Otherwise we have to convert between file handles and file descriptors
-   * here and when we open a named pipe.
-   */
-  HANDLE hPipe = (HANDLE) _get_osfhandle(pipe_fd);
-  wchar_t *err_str;
-  DWORD wait_ret;
-
-  if (hPipe == INVALID_HANDLE_VALUE) {
-    cap_pipe_err_str = "Could not open standard input";
-    return -1;
-  }
-
-  cap_pipe_err_str = "Unknown error";
-
-  wait_ret = WaitForSingleObject(hPipe, CAP_READ_TIMEOUT);
-  switch (wait_ret) {
-    /* XXX - This probably isn't correct */
-    case WAIT_ABANDONED:
-      errno = EINTR;
-      return -1;
-    case WAIT_OBJECT_0:
-      return 1;
-    case WAIT_TIMEOUT:
-      return 0;
-    case WAIT_FAILED:
-      FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER,
-        NULL, GetLastError(), 0, (LPTSTR) &err_str, 0, NULL);
-      cap_pipe_err_str = utf_16to8(err_str);
-      LocalFree(err_str);
-      return -1;
-    default:
-      g_assert_not_reached();
-      return -1;
-  }
-}
-#endif
 
 
 /* Mimic pcap_open_live() for pipe captures
@@ -758,38 +809,39 @@ cap_pipe_select(int pipe_fd) {
  * header.
  * N.B. : we can't read the libpcap formats used in RedHat 6.1 or SuSE 6.3
  * because we can't seek on pipes (see wiretap/libpcap.c for details) */
-static int
+static void
 cap_pipe_open_live(char *pipename, struct pcap_hdr *hdr, loop_data *ld,
                  char *errmsg, int errmsgl)
 {
 #ifndef _WIN32
   struct stat pipe_stat;
-#else
+  int          sel_ret;
+  int          b;
+  unsigned int bytes_read;
+  int          fd;
+#else /* _WIN32 */
 #if 1
   char *pncopy, *pos;
   wchar_t *err_str;
 #endif
-  HANDLE hPipe = NULL;
 #endif
-  int          sel_ret;
-  int          fd;
-  int          b;
-  guint32       magic;
-  unsigned int bytes_read;
+  guint32       magic = 0;
 
+#ifndef _WIN32
+  ld->cap_pipe_fd = -1;
+#else
+  ld->cap_pipe_h = INVALID_HANDLE_VALUE;
+#endif
   g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG, "cap_pipe_open_live: %s", pipename);
 
   /*
    * XXX (T)Wireshark blocks until we return
    */
   if (strcmp(pipename, "-") == 0) {
+#ifndef _WIN32
     fd = 0; /* read from stdin */
-#ifdef _WIN32
-    /*
-     * This is needed to set the stdin pipe into binary mode, otherwise
-     * CR/LF are mangled...
-     */
-    _setmode(0, _O_BINARY);
+#else /* _WIN32 */
+    ld->cap_pipe_h = GetStdHandle(STD_INPUT_HANDLE);
 #endif  /* _WIN32 */
   } else {
 #ifndef _WIN32
@@ -802,7 +854,7 @@ cap_pipe_open_live(char *pipename, struct pcap_hdr *hdr, loop_data *ld,
           "due to error on pipe: %s", strerror(errno));
         ld->cap_pipe_err = PIPERR;
       }
-      return -1;
+      return;
     }
     if (! S_ISFIFO(pipe_stat.st_mode)) {
       if (S_ISCHR(pipe_stat.st_mode)) {
@@ -818,7 +870,7 @@ cap_pipe_open_live(char *pipename, struct pcap_hdr *hdr, loop_data *ld,
             "\"%s\" is neither an interface nor a pipe", pipename);
         ld->cap_pipe_err = PIPERR;
       }
-      return -1;
+      return;
     }
     fd = ws_open(pipename, O_RDONLY | O_NONBLOCK, 0000 /* no creation so don't matter */);
     if (fd == -1) {
@@ -826,7 +878,7 @@ cap_pipe_open_live(char *pipename, struct pcap_hdr *hdr, loop_data *ld,
           "The capture session could not be initiated "
           "due to error on pipe open: %s", strerror(errno));
       ld->cap_pipe_err = PIPERR;
-      return -1;
+      return;
     }
 #else /* _WIN32 */
 #define PIPE_STR "\\pipe\\"
@@ -847,55 +899,48 @@ cap_pipe_open_live(char *pipename, struct pcap_hdr *hdr, loop_data *ld,
           "The capture session could not be initiated because\n"
           "\"%s\" is neither an interface nor a pipe", pipename);
       ld->cap_pipe_err = PIPNEXIST;
-      return -1;
+      return;
     }
 
     /* Wait for the pipe to appear */
     while (1) {
-      hPipe = CreateFile(utf_8to16(pipename), GENERIC_READ, 0, NULL,
+      ld->cap_pipe_h = CreateFile(utf_8to16(pipename), GENERIC_READ, 0, NULL,
           OPEN_EXISTING, 0, NULL);
 
-      if (hPipe != INVALID_HANDLE_VALUE)
+      if (ld->cap_pipe_h != INVALID_HANDLE_VALUE)
         break;
 
       if (GetLastError() != ERROR_PIPE_BUSY) {
         FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER,
           NULL, GetLastError(), 0, (LPTSTR) &err_str, 0, NULL);
         g_snprintf(errmsg, errmsgl,
-            "The capture session on \"%s\" could not be initiated "
-            "due to error on pipe open: pipe busy: %s (error %d)",
-           pipename, utf_16to8(err_str), GetLastError());
+            "The capture session on \"%s\" could not be started "
+            "due to error on pipe open: %s (error %d)",
+            pipename, utf_16to8(err_str), GetLastError());
         LocalFree(err_str);
         ld->cap_pipe_err = PIPERR;
-        return -1;
+        return;
       }
 
       if (!WaitNamedPipe(utf_8to16(pipename), 30 * 1000)) {
         FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER,
           NULL, GetLastError(), 0, (LPTSTR) &err_str, 0, NULL);
         g_snprintf(errmsg, errmsgl,
-            "The capture session could not be initiated "
-            "due to error on named pipe open: %s (error %d)",
-           utf_16to8(err_str), GetLastError());
+            "The capture session on \"%s\" timed out during "
+            "pipe open: %s (error %d)",
+            pipename, utf_16to8(err_str), GetLastError());
         LocalFree(err_str);
         ld->cap_pipe_err = PIPERR;
-        return -1;
+        return;
       }
     }
 
-    fd = _open_osfhandle((long) hPipe, _O_RDONLY);
-    if (fd == -1) {
-      g_snprintf(errmsg, errmsgl,
-          "The capture session could not be initiated "
-          "due to error on pipe open: %s", strerror(errno));
-      ld->cap_pipe_err = PIPERR;
-      return -1;
-    }
 #endif /* _WIN32 */
   }
 
   ld->from_cap_pipe = TRUE;
 
+#ifndef USE_THREADS
   /* read the pcap header */
   bytes_read = 0;
   while (bytes_read < sizeof magic) {
@@ -908,15 +953,33 @@ cap_pipe_open_live(char *pipename, struct pcap_hdr *hdr, loop_data *ld,
       b = read(fd, ((char *)&magic)+bytes_read, sizeof magic-bytes_read);
       if (b <= 0) {
         if (b == 0)
-          g_snprintf(errmsg, errmsgl, "End of file on pipe during open");
+          g_snprintf(errmsg, errmsgl, "End of file on pipe magic during open");
         else
-          g_snprintf(errmsg, errmsgl, "Error on pipe during open: %s",
+          g_snprintf(errmsg, errmsgl, "Error on pipe magic during open: %s",
             strerror(errno));
         goto error;
       }
       bytes_read += b;
     }
   }
+#else /* USE_THREADS */
+  g_thread_create(&cap_pipe_read, ld, FALSE, NULL);
+
+  ld->cap_pipe_buf = (char *) &magic;
+  ld->cap_pipe_bytes_read = 0;
+  ld->cap_pipe_bytes_to_read = sizeof(magic);
+  /* We don't have to worry about cap_pipe_read_mtx here */
+  g_async_queue_push(cap_pipe_pending_q, ld->cap_pipe_buf);
+  g_async_queue_pop(cap_pipe_done_q);
+  if (ld->cap_pipe_bytes_read <= 0) {
+    if (ld->cap_pipe_bytes_read == 0)
+      g_snprintf(errmsg, errmsgl, "End of file on pipe magic during open");
+    else
+      g_snprintf(errmsg, errmsgl, "Error on pipe magic during open: %s",
+                 strerror(errno));
+    goto error;
+  }
+#endif /* USE_THREADS */
 
   switch (magic) {
   case PCAP_MAGIC:
@@ -951,6 +1014,7 @@ cap_pipe_open_live(char *pipename, struct pcap_hdr *hdr, loop_data *ld,
     goto error;
   }
 
+#ifndef USE_THREADS
   /* Read the rest of the header */
   bytes_read = 0;
   while (bytes_read < sizeof(struct pcap_hdr)) {
@@ -964,15 +1028,30 @@ cap_pipe_open_live(char *pipename, struct pcap_hdr *hdr, loop_data *ld,
             sizeof(struct pcap_hdr) - bytes_read);
       if (b <= 0) {
         if (b == 0)
-          g_snprintf(errmsg, errmsgl, "End of file on pipe during open");
+          g_snprintf(errmsg, errmsgl, "End of file on pipe header during open");
         else
-          g_snprintf(errmsg, errmsgl, "Error on pipe during open: %s",
+          g_snprintf(errmsg, errmsgl, "Error on pipe header during open: %s",
             strerror(errno));
         goto error;
       }
       bytes_read += b;
     }
   }
+#else /* USE_THREADS */
+  ld->cap_pipe_buf = (char *) hdr;
+  ld->cap_pipe_bytes_read = 0;
+  ld->cap_pipe_bytes_to_read = sizeof(struct pcap_hdr);
+  g_async_queue_push(cap_pipe_pending_q, ld->cap_pipe_buf);
+  g_async_queue_pop(cap_pipe_done_q);
+  if (ld->cap_pipe_bytes_read <= 0) {
+    if (ld->cap_pipe_bytes_read == 0)
+      g_snprintf(errmsg, errmsgl, "End of file on pipe header during open");
+    else
+      g_snprintf(errmsg, errmsgl, "Error on pipe header header during open: %s",
+            strerror(errno));
+    goto error;
+  }
+#endif /* USE_THREADS */
 
   if (ld->cap_pipe_byte_swapped) {
     /* Byte-swap the header fields about which we care. */
@@ -990,13 +1069,19 @@ cap_pipe_open_live(char *pipename, struct pcap_hdr *hdr, loop_data *ld,
 
   ld->cap_pipe_state = STATE_EXPECT_REC_HDR;
   ld->cap_pipe_err = PIPOK;
-  return fd;
+#ifndef _WIN32
+  ld->cap_pipe_fd = fd;
+#endif
+  return;
 
 error:
   g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG, "cap_pipe_open_live: error %s", errmsg);
   ld->cap_pipe_err = PIPERR;
+#ifndef _WIN32
   ws_close(fd);
-  return -1;
+  ld->cap_pipe_fd = -1;
+#endif
+  return;
 
 }
 
@@ -1007,10 +1092,17 @@ static int
 cap_pipe_dispatch(loop_data *ld, guchar *data, char *errmsg, int errmsgl)
 {
   struct pcap_pkthdr phdr;
-  int b;
   enum { PD_REC_HDR_READ, PD_DATA_READ, PD_PIPE_EOF, PD_PIPE_ERR,
-          PD_ERR } result;
-
+         PD_ERR } result;
+#ifdef USE_THREADS
+  GTimeVal wait_time;
+  gpointer q_status;
+#else
+  int b;
+#endif
+#ifdef _WIN32
+  wchar_t *err_str;
+#endif
 
 #ifdef LOG_CAPTURE_VERBOSE
   g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG, "cap_pipe_dispatch");
@@ -1019,13 +1111,25 @@ cap_pipe_dispatch(loop_data *ld, guchar *data, char *errmsg, int errmsgl)
   switch (ld->cap_pipe_state) {
 
   case STATE_EXPECT_REC_HDR:
+#ifdef USE_THREADS
+    if (g_mutex_trylock(cap_pipe_read_mtx)) {
+#endif
+
+    ld->cap_pipe_state = STATE_READ_REC_HDR;
     ld->cap_pipe_bytes_to_read = ld->cap_pipe_modified ?
       sizeof(struct pcaprec_modified_hdr) : sizeof(struct pcaprec_hdr);
     ld->cap_pipe_bytes_read = 0;
-    ld->cap_pipe_state = STATE_READ_REC_HDR;
+
+#ifdef USE_THREADS
+      ld->cap_pipe_buf = (char *) &ld->cap_pipe_rechdr;
+      g_async_queue_push(cap_pipe_pending_q, ld->cap_pipe_buf);
+      g_mutex_unlock(cap_pipe_read_mtx);
+    }
+#endif
     /* Fall through */
 
   case STATE_READ_REC_HDR:
+#ifndef USE_THREADS
     b = read(ld->cap_pipe_fd, ((char *)&ld->cap_pipe_rechdr)+ld->cap_pipe_bytes_read,
              ld->cap_pipe_bytes_to_read - ld->cap_pipe_bytes_read);
     if (b <= 0) {
@@ -1035,19 +1139,48 @@ cap_pipe_dispatch(loop_data *ld, guchar *data, char *errmsg, int errmsgl)
         result = PD_PIPE_ERR;
       break;
     }
-    if ((ld->cap_pipe_bytes_read += b) < ld->cap_pipe_bytes_to_read)
+    ld->cap_pipe_bytes_read += b;
+#else /* USE_THREADS */
+    g_get_current_time(&wait_time);
+    g_time_val_add(&wait_time, THREAD_READ_TIMEOUT);
+    q_status = g_async_queue_timed_pop(cap_pipe_done_q, &wait_time);
+    if (ld->cap_pipe_err == PIPEOF) {
+      result = PD_PIPE_EOF;
+      break;
+    } else if (ld->cap_pipe_err == PIPERR) {
+      result = PD_PIPE_ERR;
+      break;
+    }
+    if (!q_status) {
+      return 0;
+    }
+#endif /* USE_THREADS */
+    if ((ld->cap_pipe_bytes_read) < ld->cap_pipe_bytes_to_read)
         return 0;
     result = PD_REC_HDR_READ;
     break;
 
   case STATE_EXPECT_DATA:
-    ld->cap_pipe_bytes_read = 0;
+#ifdef USE_THREADS
+    if (g_mutex_trylock(cap_pipe_read_mtx)) {
+#endif
+
     ld->cap_pipe_state = STATE_READ_DATA;
+    ld->cap_pipe_bytes_to_read = ld->cap_pipe_rechdr.hdr.incl_len;
+    ld->cap_pipe_bytes_read = 0;
+
+#ifdef USE_THREADS
+      ld->cap_pipe_buf = (char *) data;
+      g_async_queue_push(cap_pipe_pending_q, ld->cap_pipe_buf);
+      g_mutex_unlock(cap_pipe_read_mtx);
+    }
+#endif
     /* Fall through */
 
   case STATE_READ_DATA:
+#ifndef USE_THREADS
     b = read(ld->cap_pipe_fd, data+ld->cap_pipe_bytes_read,
-             ld->cap_pipe_rechdr.hdr.incl_len - ld->cap_pipe_bytes_read);
+             ld->cap_pipe_bytes_to_read - ld->cap_pipe_bytes_read);
     if (b <= 0) {
       if (b == 0)
         result = PD_PIPE_EOF;
@@ -1055,8 +1188,24 @@ cap_pipe_dispatch(loop_data *ld, guchar *data, char *errmsg, int errmsgl)
         result = PD_PIPE_ERR;
       break;
     }
-    if ((ld->cap_pipe_bytes_read += b) < ld->cap_pipe_rechdr.hdr.incl_len)
+    ld->cap_pipe_bytes_read += b;
+#else /* USE_THREADS */
+    g_get_current_time(&wait_time);
+    g_time_val_add(&wait_time, THREAD_READ_TIMEOUT);
+    q_status = g_async_queue_timed_pop(cap_pipe_done_q, &wait_time);
+    if (ld->cap_pipe_err == PIPEOF) {
+      result = PD_PIPE_EOF;
+      break;
+    } else if (ld->cap_pipe_err == PIPERR) {
+      result = PD_PIPE_ERR;
+      break;
+    }
+    if (!q_status) {
       return 0;
+    }
+#endif /* USE_THREADS */
+    if ((ld->cap_pipe_bytes_read) < ld->cap_pipe_bytes_to_read)
+        return 0;
     result = PD_DATA_READ;
     break;
 
@@ -1100,8 +1249,17 @@ cap_pipe_dispatch(loop_data *ld, guchar *data, char *errmsg, int errmsgl)
     return -1;
 
   case PD_PIPE_ERR:
+#ifdef _WIN32
+    FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER,
+      NULL, GetLastError(), 0, (LPTSTR) &err_str, 0, NULL);
+    g_snprintf(errmsg, errmsgl,
+        "Error reading from pipe: %s (error %d)",
+        utf_16to8(err_str), GetLastError());
+    LocalFree(err_str);
+#else
     g_snprintf(errmsg, errmsgl, "Error reading from pipe: %s",
       strerror(errno));
+#endif
     /* Fall through */
   case PD_ERR:
     break;
@@ -1152,37 +1310,37 @@ capture_loop_open_input(capture_options *capture_opts, loop_data *ld,
     switch (err) {
 
     case WSASYSNOTREADY:
-      g_snprintf(errmsg, errmsg_len,
+      g_snprintf(errmsg, (gulong) errmsg_len,
         "Couldn't initialize Windows Sockets: Network system not ready for network communication");
       break;
 
     case WSAVERNOTSUPPORTED:
-      g_snprintf(errmsg, errmsg_len,
+      g_snprintf(errmsg, (gulong) errmsg_len,
         "Couldn't initialize Windows Sockets: Windows Sockets version %u.%u not supported",
         LOBYTE(wVersionRequested), HIBYTE(wVersionRequested));
       break;
 
     case WSAEINPROGRESS:
-      g_snprintf(errmsg, errmsg_len,
+      g_snprintf(errmsg, (gulong) errmsg_len,
         "Couldn't initialize Windows Sockets: Blocking operation is in progress");
       break;
 
     case WSAEPROCLIM:
-      g_snprintf(errmsg, errmsg_len,
+      g_snprintf(errmsg, (gulong) errmsg_len,
         "Couldn't initialize Windows Sockets: Limit on the number of tasks supported by this WinSock implementation has been reached");
       break;
 
     case WSAEFAULT:
-      g_snprintf(errmsg, errmsg_len,
+      g_snprintf(errmsg, (gulong) errmsg_len,
         "Couldn't initialize Windows Sockets: Bad pointer passed to WSAStartup");
       break;
 
     default:
-      g_snprintf(errmsg, errmsg_len,
+      g_snprintf(errmsg, (gulong) errmsg_len,
         "Couldn't initialize Windows Sockets: error %d", err);
       break;
     }
-    g_snprintf(secondary_errmsg, secondary_errmsg_len, please_report);
+    g_snprintf(secondary_errmsg, (gulong) secondary_errmsg_len, please_report);
     return FALSE;
   }
 #endif
@@ -1208,10 +1366,10 @@ capture_loop_open_input(capture_options *capture_opts, loop_data *ld,
                CAP_READ_TIMEOUT, &auth, open_err_str);
 #else
   ld->pcap_h = pcap_open_live(capture_opts->iface,
-                      capture_opts->has_snaplen ? capture_opts->snaplen :
-                                                 WTAP_MAX_PACKET_SIZE,
-                      capture_opts->promisc_mode, CAP_READ_TIMEOUT,
-                      open_err_str);
+                              capture_opts->has_snaplen ? capture_opts->snaplen :
+                                                          WTAP_MAX_PACKET_SIZE,
+                              capture_opts->promisc_mode, CAP_READ_TIMEOUT,
+                              open_err_str);
 #endif
 
 /* If not using libcap: we now can now set euid/egid to ruid/rgid         */
@@ -1230,7 +1388,7 @@ capture_loop_open_input(capture_options *capture_opts, loop_data *ld,
 #ifdef _WIN32
     /* try to set the capture buffer size */
     if (capture_opts->buffer_size > 1 &&
-       pcap_setbuff(ld->pcap_h, capture_opts->buffer_size * 1024 * 1024) != 0) {
+        pcap_setbuff(ld->pcap_h, capture_opts->buffer_size * 1024 * 1024) != 0) {
         sync_secondary_msg_str = g_strdup_printf(
           "The capture buffer size of %luMB seems to be too high for your machine,\n"
           "the default of 1MB will be used.\n"
@@ -1283,52 +1441,56 @@ capture_loop_open_input(capture_options *capture_opts, loop_data *ld,
     /* setting the data link type only works on real interfaces */
     if (capture_opts->linktype != -1) {
       set_linktype_err_str = set_pcap_linktype(ld->pcap_h, capture_opts->iface,
-       capture_opts->linktype);
+        capture_opts->linktype);
       if (set_linktype_err_str != NULL) {
-       g_snprintf(errmsg, errmsg_len, "Unable to set data link type (%s).",
-                  set_linktype_err_str);
-        g_snprintf(secondary_errmsg, secondary_errmsg_len, please_report);
-       return FALSE;
+        g_snprintf(errmsg, (gulong) errmsg_len, "Unable to set data link type (%s).",
+                set_linktype_err_str);
+        g_snprintf(secondary_errmsg, (gulong) secondary_errmsg_len, please_report);
+        return FALSE;
       }
     }
     ld->linktype = get_pcap_linktype(ld->pcap_h, capture_opts->iface);
   } else {
     /* We couldn't open "iface" as a network device. */
     /* Try to open it as a pipe */
-    ld->cap_pipe_fd = cap_pipe_open_live(capture_opts->iface, &ld->cap_pipe_hdr, ld, errmsg, errmsg_len);
+    cap_pipe_open_live(capture_opts->iface, &ld->cap_pipe_hdr, ld, errmsg, (int) errmsg_len);
 
+#ifndef _WIN32
     if (ld->cap_pipe_fd == -1) {
+#else
+    if (ld->cap_pipe_h == INVALID_HANDLE_VALUE) {
+#endif
 
       if (ld->cap_pipe_err == PIPNEXIST) {
-       /* Pipe doesn't exist, so output message for interface */
-
-       /* If we got a "can't find PPA for X" message, warn the user (who
-          is running (T)Wireshark on HP-UX) that they don't have a version
-          of libpcap that properly handles HP-UX (libpcap 0.6.x and later
-          versions, which properly handle HP-UX, say "can't find /dev/dlpi
-          PPA for X" rather than "can't find PPA for X"). */
-       if (strncmp(open_err_str, ppamsg, sizeof ppamsg - 1) == 0)
-         libpcap_warn =
-           "\n\n"
-           "You are running (T)Wireshark with a version of the libpcap library\n"
-           "that doesn't handle HP-UX network devices well; this means that\n"
-           "(T)Wireshark may not be able to capture packets.\n"
-           "\n"
-           "To fix this, you should install libpcap 0.6.2, or a later version\n"
-           "of libpcap, rather than libpcap 0.4 or 0.5.x.  It is available in\n"
-           "packaged binary form from the Software Porting And Archive Centre\n"
-           "for HP-UX; the Centre is at http://hpux.connect.org.uk/ - the page\n"
-           "at the URL lists a number of mirror sites.";
-       else
-         libpcap_warn = "";
-       g_snprintf(errmsg, errmsg_len,
-         "The capture session could not be initiated (%s).", open_err_str);
+        /* Pipe doesn't exist, so output message for interface */
+
+        /* If we got a "can't find PPA for X" message, warn the user (who
+           is running (T)Wireshark on HP-UX) that they don't have a version
+           of libpcap that properly handles HP-UX (libpcap 0.6.x and later
+           versions, which properly handle HP-UX, say "can't find /dev/dlpi
+           PPA for X" rather than "can't find PPA for X"). */
+        if (strncmp(open_err_str, ppamsg, sizeof ppamsg - 1) == 0)
+          libpcap_warn =
+            "\n\n"
+            "You are running (T)Wireshark with a version of the libpcap library\n"
+            "that doesn't handle HP-UX network devices well; this means that\n"
+            "(T)Wireshark may not be able to capture packets.\n"
+            "\n"
+            "To fix this, you should install libpcap 0.6.2, or a later version\n"
+            "of libpcap, rather than libpcap 0.4 or 0.5.x.  It is available in\n"
+            "packaged binary form from the Software Porting And Archive Centre\n"
+            "for HP-UX; the Centre is at http://hpux.connect.org.uk/ - the page\n"
+            "at the URL lists a number of mirror sites.";
+        else
+          libpcap_warn = "";
+        g_snprintf(errmsg, (gulong) errmsg_len,
+          "The capture session could not be initiated (%s).", open_err_str);
 #ifndef _WIN32
-       g_snprintf(secondary_errmsg, secondary_errmsg_len,
+        g_snprintf(secondary_errmsg, (gulong) secondary_errmsg_len,
 "Please check to make sure you have sufficient permissions, and that you have "
 "the proper interface or pipe specified.%s", libpcap_warn);
 #else
-    g_snprintf(secondary_errmsg, secondary_errmsg_len,
+    g_snprintf(secondary_errmsg, (gulong) secondary_errmsg_len,
 "\n"
 "Please check that \"%s\" is the proper interface.\n"
 "\n"
@@ -1380,15 +1542,22 @@ static void capture_loop_close_input(loop_data *ld) {
   g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG, "capture_loop_close_input");
 
   /* if open, close the capture pipe "input file" */
+#ifndef _WIN32
   if (ld->cap_pipe_fd >= 0) {
     g_assert(ld->from_cap_pipe);
     ws_close(ld->cap_pipe_fd);
     ld->cap_pipe_fd = 0;
   }
+#else
+  if (ld->cap_pipe_h != INVALID_HANDLE_VALUE) {
+    CloseHandle(ld->cap_pipe_h);
+    ld->cap_pipe_h = INVALID_HANDLE_VALUE;
+  }
+#endif
 
   /* if open, close the pcap "input file" */
   if(ld->pcap_h != NULL) {
-    g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG, "capture_loop_close_input: closing %p", ld->pcap_h);
+    g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG, "capture_loop_close_input: closing %p", (void *)ld->pcap_h);
     g_assert(!ld->from_cap_pipe);
     pcap_close(ld->pcap_h);
     ld->pcap_h = NULL;
@@ -1454,7 +1623,6 @@ capture_loop_init_filter(pcap_t *pcap_h, gboolean from_cap_pipe, gchar * iface,
 /* set up to write to the already-opened capture output file/files */
 static gboolean
 capture_loop_init_output(capture_options *capture_opts, int save_file_fd, loop_data *ld, char *errmsg, int errmsg_len) {
-  int         file_snaplen;
   int         err;
 
 
@@ -1462,19 +1630,36 @@ capture_loop_init_output(capture_options *capture_opts, int save_file_fd, loop_d
 
   /* get snaplen */
   if (ld->from_cap_pipe) {
-    file_snaplen = ld->cap_pipe_hdr.snaplen;
+    ld->file_snaplen = ld->cap_pipe_hdr.snaplen;
   } else
   {
-    file_snaplen = pcap_snapshot(ld->pcap_h);
+    ld->file_snaplen = pcap_snapshot(ld->pcap_h);
   }
 
   /* Set up to write to the capture file. */
   if (capture_opts->multi_files_on) {
-    ld->pdh = ringbuf_init_libpcap_fdopen(ld->linktype, file_snaplen,
-                                          &ld->bytes_written, &err);
+    ld->pdh = ringbuf_init_libpcap_fdopen(&err);
   } else {
-    ld->pdh = libpcap_fdopen(save_file_fd, ld->linktype, file_snaplen,
-                             &ld->bytes_written, &err);
+    ld->pdh = libpcap_fdopen(save_file_fd, &err);
+  }
+  if (ld->pdh) {
+    gboolean successful;
+
+    ld->bytes_written = 0;
+    if (capture_opts->use_pcapng) {
+      char appname[100];
+
+      g_snprintf(appname, sizeof(appname), "Dumpcap " VERSION "%s", wireshark_svnversion);
+      successful = libpcap_write_session_header_block(ld->pdh, appname, &ld->bytes_written, &err) &&
+                   libpcap_write_interface_description_block(ld->pdh, capture_opts->iface, capture_opts->cfilter, ld->linktype, ld->file_snaplen, &ld->bytes_written, &err);
+    } else {
+      successful = libpcap_write_file_header(ld->pdh, ld->linktype, ld->file_snaplen,
+                                             &ld->bytes_written, &err);
+    }
+    if (!successful) {
+      fclose(ld->pdh);
+      ld->pdh = NULL;
+    }
   }
 
   if (ld->pdh == NULL) {
@@ -1495,14 +1680,14 @@ capture_loop_init_output(capture_options *capture_opts, int save_file_fd, loop_d
     default:
       if (err < 0) {
         g_snprintf(errmsg, errmsg_len,
-                    "The file to which the capture would be"
-                     " saved (\"%s\") could not be opened: Error %d.",
-                       capture_opts->save_file, err);
+                   "The file to which the capture would be"
+                   " saved (\"%s\") could not be opened: Error %d.",
+                   capture_opts->save_file, err);
       } else {
         g_snprintf(errmsg, errmsg_len,
-                    "The file to which the capture would be"
-                     " saved (\"%s\") could not be opened: %s.",
-                       capture_opts->save_file, strerror(err));
+                    "The file to which the capture would be"
+                    " saved (\"%s\") could not be opened: %s.",
+                    capture_opts->save_file, strerror(err));
       }
       break;
     }
@@ -1521,6 +1706,9 @@ capture_loop_close_output(capture_options *capture_opts, loop_data *ld, int *err
   if (capture_opts->multi_files_on) {
     return ringbuf_libpcap_dump_close(&capture_opts->save_file, err_close);
   } else {
+    if (capture_opts->use_pcapng) {
+      libpcap_write_interface_statistics_block(ld->pdh, 0, ld->pcap_h, &ld->bytes_written, err_close);
+    }
     return libpcap_dump_close(ld->pdh, err_close);
   }
 }
@@ -1541,9 +1729,11 @@ capture_loop_dispatch(capture_options *capture_opts _U_, loop_data *ld,
                      char *errmsg, int errmsg_len)
 {
   int       inpkts;
-  int       sel_ret;
   gint      packet_count_before;
   guchar    pcap_data[WTAP_MAX_PACKET_SIZE];
+#ifndef USE_THREADS
+  int       sel_ret;
+#endif
 
   packet_count_before = ld->packet_count;
   if (ld->from_cap_pipe) {
@@ -1551,6 +1741,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
+#ifndef USE_THREADS
     sel_ret = cap_pipe_select(ld->cap_pipe_fd);
     if (sel_ret <= 0) {
       inpkts = 0;
@@ -1564,11 +1755,14 @@ capture_loop_dispatch(capture_options *capture_opts _U_, loop_data *ld,
       /*
        * "select()" says we can read from the pipe without blocking
        */
+#endif /* USE_THREADS */
       inpkts = cap_pipe_dispatch(ld, pcap_data, errmsg, errmsg_len);
       if (inpkts < 0) {
         ld->go = FALSE;
       }
+#ifndef USE_THREADS
     }
+#endif
   }
   else
   {
@@ -1605,7 +1799,10 @@ capture_loop_dispatch(capture_options *capture_opts _U_, loop_data *ld,
         inpkts = pcap_dispatch(ld->pcap_h, 1, capture_loop_packet_cb,
                                (u_char *)ld);
         if (inpkts < 0) {
-          ld->pcap_err = TRUE;
+            if (inpkts == -1) {
+                /* Error, rather than pcap_breakloop(). */
+                ld->pcap_err = TRUE;
+            }
           ld->go = FALSE; /* error or pcap_breakloop() - stop capturing */
         }
       } else {
@@ -1692,7 +1889,7 @@ static gboolean
 capture_loop_open_output(capture_options *capture_opts, int *save_file_fd,
                      char *errmsg, int errmsg_len) {
 
-  char tmpname[128+1];
+  char *tmpname;
   gchar *capfile_name;
   gboolean is_tempfile;
 #ifndef _WIN32
@@ -1747,7 +1944,7 @@ capture_loop_open_output(capture_options *capture_opts, int *save_file_fd,
     is_tempfile = FALSE;
   } else {
     /* Choose a random name for the temporary capture buffer */
-    *save_file_fd = create_tempfile(tmpname, sizeof tmpname, "wireshark");
+    *save_file_fd = create_tempfile(&tmpname, "wireshark");
     capfile_name = g_strdup(tmpname);
     is_tempfile = TRUE;
   }
@@ -1786,13 +1983,6 @@ capture_loop_open_output(capture_options *capture_opts, int *save_file_fd,
 }
 
 
-static void
-capture_loop_stop_signal_handler(int signo _U_)
-{
-  g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_INFO, "Signal: Stop capture");
-  capture_loop_stop();
-}
-
 #ifdef _WIN32
 #define TIME_GET() GetTickCount()
 #else
@@ -1804,9 +1994,6 @@ capture_loop_stop_signal_handler(int signo _U_)
 static gboolean
 capture_loop_start(capture_options *capture_opts, gboolean *stats_known, struct pcap_stat *stats)
 {
-#ifndef _WIN32
-  struct sigaction act;
-#endif
   time_t      upd_time, cur_time;
   time_t      start_time;
   int         err_close;
@@ -1840,7 +2027,11 @@ capture_loop_start(capture_options *capture_opts, gboolean *stats_known, struct
   global_ld.pcap_err           = FALSE;
   global_ld.from_cap_pipe      = FALSE;
   global_ld.pdh                = NULL;
+#ifndef _WIN32
   global_ld.cap_pipe_fd        = -1;
+#else
+  global_ld.cap_pipe_h         = INVALID_HANDLE_VALUE;
+#endif
 #ifdef MUST_DO_SELECT
   global_ld.pcap_fd            = 0;
 #endif
@@ -1848,22 +2039,6 @@ capture_loop_start(capture_options *capture_opts, gboolean *stats_known, struct
   /* We haven't yet gotten the capture statistics. */
   *stats_known      = FALSE;
 
-#ifndef _WIN32
-  /*
-   * Catch SIGUSR1, so that we exit cleanly if the parent process
-   * kills us with it due to the user selecting "Capture->Stop".
-   */
-  act.sa_handler = capture_loop_stop_signal_handler;
-  /*
-   * Arrange that system calls not get restarted, because when
-   * our signal handler returns we don't want to restart
-   * a call that was waiting for packets to arrive.
-   */
-  act.sa_flags = 0;
-  sigemptyset(&act.sa_mask);
-  sigaction(SIGUSR1, &act, NULL);
-#endif /* _WIN32 */
-
   g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_INFO, "Capture loop starting ...");
   capture_opts_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG, capture_opts);
 
@@ -1980,8 +2155,27 @@ capture_loop_start(capture_options *capture_opts, gboolean *stats_known, struct
 
           /* Switch to the next ringbuffer file */
           if (ringbuf_switch_file(&global_ld.pdh, &capture_opts->save_file,
-              &save_file_fd, &global_ld.bytes_written, &global_ld.err)) {
+                                  &save_file_fd, &global_ld.err)) {
+            gboolean successful;
+
             /* File switch succeeded: reset the conditions */
+            global_ld.bytes_written = 0;
+            if (capture_opts->use_pcapng) {
+              char appname[100];
+
+              g_snprintf(appname, sizeof(appname), "Dumpcap " VERSION "%s", wireshark_svnversion);
+              successful = libpcap_write_session_header_block(global_ld.pdh, appname, &global_ld.bytes_written, &global_ld.err) &&
+                           libpcap_write_interface_description_block(global_ld.pdh, capture_opts->iface, capture_opts->cfilter, global_ld.linktype, global_ld.file_snaplen, &global_ld.bytes_written, &global_ld.err);
+            } else {
+              successful = libpcap_write_file_header(global_ld.pdh, global_ld.linktype, global_ld.file_snaplen,
+                                                     &global_ld.bytes_written, &global_ld.err);
+            }
+            if (!successful) {
+              fclose(global_ld.pdh);
+              global_ld.pdh = NULL;
+              global_ld.go = FALSE;
+              continue;
+            }
             cnd_reset(cnd_autostop_size);
             if (cnd_file_duration) {
               cnd_reset(cnd_file_duration);
@@ -2053,9 +2247,27 @@ capture_loop_start(capture_options *capture_opts, gboolean *stats_known, struct
 
           /* Switch to the next ringbuffer file */
           if (ringbuf_switch_file(&global_ld.pdh, &capture_opts->save_file,
-                                  &save_file_fd, &global_ld.bytes_written,
-                                 &global_ld.err)) {
+                                  &save_file_fd, &global_ld.err)) {
+            gboolean successful;
+
             /* file switch succeeded: reset the conditions */
+            global_ld.bytes_written = 0;
+            if (capture_opts->use_pcapng) {
+              char appname[100];
+
+              g_snprintf(appname, sizeof(appname), "Dumpcap " VERSION "%s", wireshark_svnversion);
+              successful = libpcap_write_session_header_block(global_ld.pdh, appname, &global_ld.bytes_written, &global_ld.err) &&
+                           libpcap_write_interface_description_block(global_ld.pdh, capture_opts->iface, capture_opts->cfilter, global_ld.linktype, global_ld.file_snaplen, &global_ld.bytes_written, &global_ld.err);
+            } else {
+              successful = libpcap_write_file_header(global_ld.pdh, global_ld.linktype, global_ld.file_snaplen,
+                                                     &global_ld.bytes_written, &global_ld.err);
+            }
+            if (!successful) {
+              fclose(global_ld.pdh);
+              global_ld.pdh = NULL;
+              global_ld.go = FALSE;
+              continue;
+            }
             cnd_reset(cnd_file_duration);
             if(cnd_autostop_size)
               cnd_reset(cnd_autostop_size);
@@ -2304,10 +2516,16 @@ capture_loop_packet_cb(u_char *user, const struct pcap_pkthdr *phdr,
     return;
 
   if (ld->pdh) {
+    gboolean successful;
     /* We're supposed to write the packet to a file; do so.
        If this fails, set "ld->go" to FALSE, to stop the capture, and set
        "ld->err" to the error. */
-    if (!libpcap_write_packet(ld->pdh, phdr, pd, &ld->bytes_written, &err)) {
+    if (global_capture_opts.use_pcapng) {
+      successful = libpcap_write_enhanced_packet_block(ld->pdh, phdr, 0, pd, &ld->bytes_written, &err);
+    } else {
+      successful = libpcap_write_packet(ld->pdh, phdr, pd, &ld->bytes_written, &err);
+    }
+    if (!successful) {
       ld->go = FALSE;
       ld->err = err;
     } else {
@@ -2327,7 +2545,6 @@ int
 main(int argc, char *argv[])
 {
   int                  opt;
-  extern char         *optarg;
   gboolean             arg_error = FALSE;
 
 #ifdef _WIN32
@@ -2348,9 +2565,9 @@ main(int argc, char *argv[])
   gint                 i;
 
 #ifdef HAVE_PCAP_REMOTE
-#define OPTSTRING_INIT "a:A:b:c:Df:hi:Lm:MprSs:uvw:y:Z:"
+#define OPTSTRING_INIT "a:A:b:c:Df:hi:Lm:MnprSs:uvw:y:Z:"
 #else
-#define OPTSTRING_INIT "a:b:c:Df:hi:LMpSs:vw:y:Z:"
+#define OPTSTRING_INIT "a:b:c:Df:hi:LMnpSs:vw:y:Z:"
 #endif
 
 #ifdef _WIN32
@@ -2435,15 +2652,29 @@ main(int argc, char *argv[])
   WSAStartup( MAKEWORD( 1, 1 ), &wsaData );
 
   /* Set handler for Ctrl+C key */
-  SetConsoleCtrlHandler(capture_cleanup, TRUE);
+  SetConsoleCtrlHandler(capture_cleanup_handler, TRUE);
+
+  /* Prepare to read from a pipe */
+  if (!g_thread_supported ())
+    g_thread_init (NULL);
+  cap_pipe_pending_q = g_async_queue_new();
+  cap_pipe_done_q = g_async_queue_new();
+  cap_pipe_read_mtx = g_mutex_new();
+
 #else
   /* Catch SIGINT and SIGTERM and, if we get either of them, clean up
      and exit. */
-  action.sa_handler = capture_cleanup;
+  action.sa_handler = capture_cleanup_handler;
+  /*
+   * Arrange that system calls not get restarted, because when
+   * our signal handler returns we don't want to restart
+   * a call that was waiting for packets to arrive.
+   */
   action.sa_flags = 0;
   sigemptyset(&action.sa_mask);
   sigaction(SIGTERM, &action, NULL);
   sigaction(SIGINT, &action, NULL);
+  sigaction(SIGPIPE, &action, NULL);
   sigaction(SIGHUP, NULL, &oldaction);
   if (oldaction.sa_handler == SIG_DFL)
     sigaction(SIGHUP, &action, NULL);
@@ -2505,7 +2736,7 @@ main(int argc, char *argv[])
   /*                                                                   */
   /*        It is therefore conceivable that if dumpcap somehow hangs  */
   /*        in pcap_open_live or before that wireshark will not        */
-  /*        be able to stop dumpcap using a signal (USR1, TERM, etc).  */
+  /*        be able to stop dumpcap using a signal (INT, TERM, etc).  */
   /*        In this case, exiting wireshark will kill the child        */
   /*        dumpcap process.                                           */
   /*                                                                   */
@@ -2573,6 +2804,7 @@ main(int argc, char *argv[])
       case 'c':        /* Capture x packets */
       case 'f':        /* capture filter */
       case 'i':        /* Use interface x */
+      case 'n':        /* Use pcapng format */
       case 'p':        /* Don't capture in promiscuous mode */
       case 's':        /* Set the snapshot (capture) length */
       case 'w':        /* Write to capture file x */
@@ -2945,3 +3177,16 @@ signal_pipe_check_running(void)
     }
 }
 #endif
+
+/*
+ * Editor modelines  -  http://www.wireshark.org/tools/modelines.html
+ *
+ * Local variables:
+ * c-basic-offset: 4
+ * tab-width: 8
+ * indent-tabs-mode: nil
+ * End:
+ *
+ * vi: set shiftwidth=4 tabstop=8 expandtab
+ * :indentSize=4:tabSize=8:noTabs=true:
+ */