In Solaris, the second argument to dladdr() is just a void *, not a
[obnox/wireshark/wip.git] / capture_sync.c
index f2d137d51697213b94c5f25a0e04ba911281677b..bca2336b08669e498148a9935e9df7d2788c0e3e 100644 (file)
@@ -44,7 +44,7 @@
 #include <signal.h>
 
 #ifdef _WIN32
-#include "epan/unicode-utils.h"
+#include <wsutil/unicode-utils.h>
 #endif
 
 #ifdef HAVE_SYS_WAIT_H
 #include "globals.h"
 #include "file.h"
 #include <epan/filesystem.h>
+#include <epan/report_err.h>
 
 #include "capture.h"
 #include "capture_sync.h"
-#include "simple_dialog.h"
 
 #include "sync_pipe.h"
 
@@ -98,7 +98,7 @@
 #include "capture-wpcap.h"
 #endif
 #include "ui_util.h"
-#include "file_util.h"
+#include <wsutil/file_util.h>
 #include "log.h"
 
 #ifdef _WIN32
@@ -288,10 +288,12 @@ sync_pipe_start(capture_options *capture_opts) {
     argv = init_pipe_args(&argc);
     if (!argv) {
         /* We don't know where to find dumpcap. */
-        simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "We don't know where to find dumpcap.");
+        report_failure("We don't know where to find dumpcap.");
         return FALSE;
     }
 
+    g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "argv[0]: %s", argv[0]);
+
     argv = sync_pipe_add_arg(argv, &argc, "-i");
     argv = sync_pipe_add_arg(argv, &argc, capture_opts->iface);
 
@@ -303,12 +305,7 @@ sync_pipe_start(capture_options *capture_opts) {
 
     if (capture_opts->linktype != -1) {
       argv = sync_pipe_add_arg(argv, &argc, "-y");
-#ifdef HAVE_PCAP_DATALINK_VAL_TO_NAME
       g_snprintf(sdlt, ARGV_NUMBER_LEN, "%s",linktype_val_to_name(capture_opts->linktype));
-#else
-      /* we can't get the type name, just treat it as a number */
-      g_snprintf(sdlt, ARGV_NUMBER_LEN, "%d",capture_opts->linktype);
-#endif
       argv = sync_pipe_add_arg(argv, &argc, sdlt);
     }
 
@@ -399,6 +396,12 @@ sync_pipe_start(capture_options *capture_opts) {
 
 #ifdef _WIN32
     argv = sync_pipe_add_arg(argv, &argc, "-B");
+#ifdef HAVE_PCAP_REMOTE
+    if (capture_opts->src_type == CAPTURE_IFREMOTE)
+      /* No buffer size when using remote interfaces */
+      g_snprintf(buffer_size, ARGV_NUMBER_LEN, "%d", 1);
+    else
+#endif
     g_snprintf(buffer_size, ARGV_NUMBER_LEN, "%d",capture_opts->buffer_size);
     argv = sync_pipe_add_arg(argv, &argc, buffer_size);
 #endif
@@ -423,8 +426,7 @@ sync_pipe_start(capture_options *capture_opts) {
     /* (increase this value if you have trouble while fast capture file switches) */
     if (! CreatePipe(&sync_pipe_read, &sync_pipe_write, &sa, 5120)) {
       /* Couldn't create the pipe between parent and child. */
-      simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "Couldn't create sync pipe: %s",
-                        strerror(errno));
+      report_failure("Couldn't create sync pipe: %s", strerror(errno));
       g_free( (gpointer) argv[0]);
       g_free( (gpointer) argv);
       return FALSE;
@@ -438,8 +440,7 @@ sync_pipe_start(capture_options *capture_opts) {
 
     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));
+      report_failure("Couldn't create signal pipe: %s", strerror(errno));
       g_free( (gpointer) argv[0]);
       g_free( (gpointer) argv);
       return FALSE;
@@ -473,9 +474,8 @@ sync_pipe_start(capture_options *capture_opts) {
     /* call dumpcap */
     if(!CreateProcess(NULL, utf_8to16(args->str), NULL, NULL, TRUE,
                       CREATE_NEW_CONSOLE, NULL, NULL, &si, &pi)) {
-      simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
-                    "Couldn't run %s in child process: error %u",
-                    args->str, GetLastError());
+      report_failure("Couldn't run %s in child process: error %u",
+                     args->str, GetLastError());
       CloseHandle(sync_pipe_read);
       CloseHandle(sync_pipe_write);
       g_free( (gpointer) argv[0]);
@@ -495,8 +495,7 @@ sync_pipe_start(capture_options *capture_opts) {
 #else /* _WIN32 */
     if (pipe(sync_pipe) < 0) {
       /* Couldn't create the pipe between parent and child. */
-      simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "Couldn't create sync pipe: %s",
-                       strerror(errno));
+      report_failure("Couldn't create sync pipe: %s", strerror(errno));
       g_free( (gpointer) argv[0]);
       g_free(argv);
       return FALSE;
@@ -508,7 +507,7 @@ sync_pipe_start(capture_options *capture_opts) {
        * it just capture with the specified capture parameters
        */
       dup2(sync_pipe[PIPE_WRITE], 2);
-      eth_close(sync_pipe[PIPE_READ]);
+      ws_close(sync_pipe[PIPE_READ]);
       execv(argv[0], (gpointer)argv);
       g_snprintf(errmsg, sizeof errmsg, "Couldn't run %s in child process: %s",
                argv[0], strerror(errno));
@@ -540,16 +539,15 @@ sync_pipe_start(capture_options *capture_opts) {
 #ifdef _WIN32
     CloseHandle(sync_pipe_write);
 #else
-    eth_close(sync_pipe[PIPE_WRITE]);
+    ws_close(sync_pipe[PIPE_WRITE]);
 #endif
 
     if (capture_opts->fork_child == -1) {
       /* We couldn't even create the child process. */
-      simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
-                       "Couldn't create child process: %s", strerror(errno));
-      eth_close(sync_pipe_read_fd);
+      report_failure("Couldn't create child process: %s", strerror(errno));
+      ws_close(sync_pipe_read_fd);
 #ifdef _WIN32
-      eth_close(capture_opts->signal_pipe_write_fd);
+      ws_close(capture_opts->signal_pipe_write_fd);
 #endif
       return FALSE;
     }
@@ -682,7 +680,7 @@ sync_pipe_open_command(const char** argv, int *read_fd, int *fork_child, gchar *
          * it just capture with the specified capture parameters
          */
         dup2(sync_pipe[PIPE_WRITE], 1);
-        eth_close(sync_pipe[PIPE_READ]);
+        ws_close(sync_pipe[PIPE_READ]);
         execv(argv[0], (gpointer)argv);
         g_snprintf(errmsg, sizeof errmsg, "Couldn't run %s in child process: %s",
                   argv[0], strerror(errno));
@@ -714,13 +712,13 @@ sync_pipe_open_command(const char** argv, int *read_fd, int *fork_child, gchar *
 #ifdef _WIN32
     CloseHandle(sync_pipe_write);
 #else
-    eth_close(sync_pipe[PIPE_WRITE]);
+    ws_close(sync_pipe[PIPE_WRITE]);
 #endif
 
     if (*fork_child == -1) {
         /* We couldn't even create the child process. */
         *msg = g_strdup_printf("Couldn't create child process: %s", strerror(errno));
-        eth_close(*read_fd);
+        ws_close(*read_fd);
         return CANT_RUN_DUMPCAP;
     }
 
@@ -737,7 +735,7 @@ sync_pipe_close_command(int *read_fd, gchar **msg) {
 #endif
     int fork_child_status;
 
-    eth_close(*read_fd);
+    ws_close(*read_fd);
 
     g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "sync_pipe_close_command: wait till child closed");
 
@@ -804,7 +802,7 @@ sync_pipe_run_command(const char** argv, gchar **msg) {
     /* We were able to set up to read dumpcap's output.  Do so and
        return its exit value. */
     msg_buf = g_string_new("");
-    while ((count = eth_read(sync_pipe_read_fd, buf, PIPE_BUF_SIZE)) > 0) {
+    while ((count = ws_read(sync_pipe_read_fd, buf, PIPE_BUF_SIZE)) > 0) {
         buf[count] = '\0';
         g_string_append(msg_buf, buf);
     }
@@ -854,10 +852,22 @@ sync_interface_list_open(gchar **msg) {
     argv = sync_pipe_add_arg(argv, &argc, "-D");
     argv = sync_pipe_add_arg(argv, &argc, "-M");
 
-    /* dumpcap should be running in capture child mode (hidden feature) */
+#if 0
+    /* dumpcap should be running in capture child mode (hidden feature)                   */
+    /* XXX: Actually: don't run dumpcap in capture_child_mode.                            */
+    /*     Instead run dumpcap in 'normal' mode so that dumpcap err msgs are sent to      */
+    /*     stderr in normal format and are then sent to whereever our stderr goes.        */
+    /*     Note: Using 'dumpcap -D -M -Z' (capture_child mode) changes only the format of */
+    /*           dumpcap err msgs. That is: dumpcap in capture_child mode outputs err     */
+    /*           msgs to stderr in a special type/len/string format which would then      */
+    /*           currently be sent as is to stderr resulting in garbled output.           */
+    /*     ToDo: Revise this code to be similar to sync_pipe_start so that 'dumpcap -Z'   */
+    /*     special format error messages to stderr are captured and returned to caller    */
+    /*     (eg: so can be processed and displayed in a pop-up box).                       */
 #ifndef DEBUG_CHILD
     argv = sync_pipe_add_arg(argv, &argc, "-Z");
     argv = sync_pipe_add_arg(argv, &argc, SIGNAL_PIPE_CTRL_ID_NONE);
+#endif
 #endif
 
     return sync_pipe_run_command(argv, msg);
@@ -894,12 +904,23 @@ sync_linktype_list_open(const gchar *ifname, gchar **msg) {
     argv = sync_pipe_add_arg(argv, &argc, "-L");
     argv = sync_pipe_add_arg(argv, &argc, "-M");
 
-    /* dumpcap should be running in capture child mode (hidden feature) */
+#if 0
+    /* dumpcap should be running in capture child mode (hidden feature)                   */
+    /* XXX: Actually: don't run dumpcap in capture_child_mode.                            */
+    /*     Instead run dumpcap in 'normal' mode so that dumpcap err msgs are sent to      */
+    /*     stderr in normal format and are then sent to whereever our stderr goes.        */
+    /*     Note: Using 'dumpcap -L -M -Z' (capture_child mode) changes only the format of */
+    /*           dumpcap err msgs. That is: dumpcap in capture_child mode outputs err     */
+    /*           msgs to stderr in a special type/len/string format which would then      */
+    /*           currently be sent as is to stderr resulting in garbled output.           */
+    /*     ToDo: Revise this code to be similar to sync_pipe_start so that 'dumpcap -Z'   */
+    /*     special format error messages to stderr are captured and returned to caller    */
+    /*     (eg: so can be processed and displayed in a pop-up box).                       */
 #ifndef DEBUG_CHILD
     argv = sync_pipe_add_arg(argv, &argc, "-Z");
     argv = sync_pipe_add_arg(argv, &argc, SIGNAL_PIPE_CTRL_ID_NONE);
 #endif
-
+#endif
     return sync_pipe_run_command(argv, msg);
 }
 
@@ -919,7 +940,7 @@ sync_interface_stats_open(int *read_fd, int *fork_child, gchar **msg) {
         return -1;
     }
 
-    g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "sync_linktype_list_open");
+    g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "sync_interface_stats_open");
 
     argv = init_pipe_args(&argc);
 
@@ -928,16 +949,27 @@ sync_interface_stats_open(int *read_fd, int *fork_child, gchar **msg) {
         return CANT_RUN_DUMPCAP;
     }
 
-    /* Ask for the linktype list */
+    /* Ask for the interface statistics */
     argv = sync_pipe_add_arg(argv, &argc, "-S");
     argv = sync_pipe_add_arg(argv, &argc, "-M");
 
-    /* dumpcap should be running in capture child mode (hidden feature) */
+#if 0
+    /* dumpcap should be running in capture child mode (hidden feature)                   */
+    /* XXX: Actually: don't run dumpcap in capture_child_mode.                            */
+    /*     Instead run dumpcap in 'normal' mode so that dumpcap err msgs are sent to      */
+    /*     stderr in normal format and are then sent to whereever our stderr goes.        */
+    /*     Note: Using 'dumpcap -S -M -Z' (capture_child mode) changes only the format of */
+    /*           dumpcap err msgs. That is: dumpcap in capture_child mode outputs err     */
+    /*           msgs to stderr in a special type/len/string format which would then      */
+    /*           currently be sent as is to stderr resulting in garbled output.           */
+    /*     ToDo: Revise this code to be similar to sync_pipe_start so that 'dumpcap -Z'   */
+    /*     special format error messages to stderr are captured and returned to caller    */
+    /*     (eg: so can be processed and displayed in a pop-up box).                       */
 #ifndef DEBUG_CHILD
     argv = sync_pipe_add_arg(argv, &argc, "-Z");
     argv = sync_pipe_add_arg(argv, &argc, SIGNAL_PIPE_CTRL_ID_NONE);
 #endif
-
+#endif
     return sync_pipe_open_command(argv, read_fd, fork_child, msg);
 }
 
@@ -1016,22 +1048,22 @@ static gboolean pipe_data_available(int pipe) {
 
 /* Read a line from a pipe, similar to fgets */
 int
-sync_pipe_gets_nonblock(int pipe, char *bytes, int max) {
+sync_pipe_gets_nonblock(int pipe_fd, char *bytes, int max) {
     int newly;
     int offset = -1;
 
     while(offset < max - 1) {
         offset++;
-        if (! pipe_data_available(pipe))
+        if (! pipe_data_available(pipe_fd))
             break;
-        newly = read(pipe, &bytes[offset], 1);
+        newly = read(pipe_fd, &bytes[offset], 1);
         if (newly == 0) {
             /* EOF - not necessarily an error */
             break;
         } else if (newly < 0) {
             /* error */
             g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG,
-                  "read from pipe %d: error(%u): %s", pipe, errno, strerror(errno));
+                  "read from pipe %d: error(%u): %s", pipe_fd, errno, strerror(errno));
             return newly;
         } else if (bytes[offset] == '\n') {
             break;
@@ -1105,6 +1137,7 @@ pipe_read_block(int pipe, char *indicator, int len, char *msg) {
         return -1;
     }
 
+    /* XXX If message is "2part", the msg probably won't be sent to debug log correctly */
     g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG,
           "read %d ok indicator: %c len: %u msg: %s", pipe, *indicator,
           len, msg);
@@ -1149,7 +1182,7 @@ sync_pipe_input_cb(gint source, gpointer user_data)
     sync_pipe_wait_for_child(capture_opts);
 
 #ifdef _WIN32
-    eth_close(capture_opts->signal_pipe_write_fd);
+    ws_close(capture_opts->signal_pipe_write_fd);
 #endif
     capture_input_closed(capture_opts);
     return FALSE;
@@ -1163,7 +1196,7 @@ sync_pipe_input_cb(gint source, gpointer user_data)
 
       /* We weren't able to open the new capture file; user has been
          alerted. Close the sync pipe. */
-      eth_close(source);
+      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.
@@ -1195,7 +1228,7 @@ sync_pipe_input_cb(gint source, gpointer user_data)
     /* the capture child will close the sync_pipe, nothing to do for now */
     break;
   case SP_DROPS:
-    capture_input_drops(capture_opts, atoi(buffer));
+    capture_input_drops(capture_opts, (guint32)strtoul(buffer, NULL, 10));
     break;
   default:
     g_assert_not_reached();
@@ -1218,8 +1251,8 @@ sync_pipe_wait_for_child(capture_options *capture_opts)
 
 #ifdef _WIN32
   if (_cwait(&wstatus, capture_opts->fork_child, _WAIT_CHILD) == -1) {
-    simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
-               "Child capture process stopped unexpectedly (errno:%u)", errno);
+    report_failure("Child capture process stopped unexpectedly (errno:%u)",
+                   errno);
   }
 #else
   if (wait(&wstatus) != -1) {
@@ -1231,26 +1264,22 @@ sync_pipe_wait_for_child(capture_options *capture_opts)
       /* If there are situations where the child won't send us such an error message, */
       /* this should be fixed in the child and not here! */
       if (WEXITSTATUS(wstatus) != 0 && WEXITSTATUS(wstatus) != 1) {
-        simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
-                     "Child capture process exited: exit status %d",
-                     WEXITSTATUS(wstatus));
+        report_failure("Child capture process exited: exit status %d",
+                      WEXITSTATUS(wstatus));
       }
     } else if (WIFSTOPPED(wstatus)) {
       /* It stopped, rather than exiting.  "Should not happen." */
-      simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
-                   "Child capture process stopped: %s",
-                   sync_pipe_signame(WSTOPSIG(wstatus)));
+      report_failure("Child capture process stopped: %s",
+                    sync_pipe_signame(WSTOPSIG(wstatus)));
     } else if (WIFSIGNALED(wstatus)) {
       /* It died with a signal. */
-      simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
-                   "Child capture process died: %s%s",
-                   sync_pipe_signame(WTERMSIG(wstatus)),
-                   WCOREDUMP(wstatus) ? " - core dumped" : "");
+      report_failure("Child capture process died: %s%s",
+                    sync_pipe_signame(WTERMSIG(wstatus)),
+                    WCOREDUMP(wstatus) ? " - core dumped" : "");
     } else {
       /* What?  It had to either have exited, or stopped, or died with
          a signal; what happened here? */
-      simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
-                   "Child capture process died: wait status %#o", wstatus);
+      report_failure("Child capture process died: wait status %#o", wstatus);
     }
   }
 #endif
@@ -1395,7 +1424,11 @@ sync_pipe_stop(capture_options *capture_opts)
   if (capture_opts->fork_child != -1) {
 #ifndef _WIN32
     /* send the SIGUSR1 signal to close the capture child gracefully. */
-    kill(capture_opts->fork_child, SIGUSR1);
+    int sts = kill(capture_opts->fork_child, SIGUSR1);
+    if (sts != 0) {
+        g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_WARNING,
+              "Sending SIGUSR1 to child failed: %s\n", strerror(errno));
+    }
 #else
 #define STOP_SLEEP_TIME 500 /* ms */
 #define STOP_CHECK_TIME 50
@@ -1429,9 +1462,13 @@ sync_pipe_stop(capture_options *capture_opts)
 void
 sync_pipe_kill(int fork_child)
 {
-  if (fork_child != -1) {
+    if (fork_child != -1) {
 #ifndef _WIN32
-      kill(fork_child, SIGTERM);       /* SIGTERM so it can clean up if necessary */
+        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));
+        }
 #else
       /* Remark: This is not the preferred method of closing a process!
        * the clean way would be getting the process id of the child process,
@@ -1451,9 +1488,9 @@ sync_pipe_kill(int fork_child)
        * us, as we might not be running in a console.
        * And this also will require to have the process id.
        */
-      TerminateProcess((HANDLE) (fork_child), 0);
+        TerminateProcess((HANDLE) (fork_child), 0);
 #endif
-  }
+    }
 }
 
 #endif /* HAVE_LIBPCAP */