]> git.ipfire.org Git - thirdparty/dbus.git/commitdiff
dbus-monitor: add options to log binary data with or without pcap framing
authorSimon McVittie <simon.mcvittie@collabora.co.uk>
Fri, 23 Jan 2015 19:32:31 +0000 (19:32 +0000)
committerSimon McVittie <simon.mcvittie@collabora.co.uk>
Wed, 4 Feb 2015 17:15:34 +0000 (17:15 +0000)
Bug: https://bugs.freedesktop.org/show_bug.cgi?id=46787
Reviewed-by: Philip Withnall <philip.withnall@collabora.co.uk>
cmake/tools/CMakeLists.txt
doc/dbus-monitor.1.xml.in
tools/dbus-monitor.c
tools/tool-common.c
tools/tool-common.h

index e406daa7576da5531bd90ac1e8b518c8291b49b1..d4eeb70866c6da5c4e3c7b6ccdf2e32b22e97d95 100644 (file)
@@ -1,3 +1,5 @@
+add_definitions("-DDBUS_COMPILATION")
+
 set (dbus_send_SOURCES
        ../../tools/dbus-print-message.c                        
        ../../tools/dbus-print-message.h                        
index af05e3aaf5ccc5230ba9655941b9ca893b237df5..2f807d2f118eec4be599fea7f7156f060f434a9b 100644 (file)
@@ -22,7 +22,7 @@
 <cmdsynopsis>
   <command>dbus-monitor</command>
     <group choice='opt'><arg choice='plain'>--system </arg><arg choice='plain'>--session </arg><arg choice='plain'>--address <replaceable>ADDRESS</replaceable></arg></group>
-    <group choice='opt'><arg choice='plain'>--profile </arg><arg choice='plain'>--monitor </arg></group>
+    <group choice='opt'><arg choice='plain'>--profile </arg><arg choice='plain'>--monitor </arg><arg choice='plain'>--pcap </arg><arg choice='plain'>--binary </arg></group>
     <arg choice='opt'><arg choice='plain'><replaceable>watch</replaceable></arg><arg choice='plain'><replaceable>expressions</replaceable></arg></arg>
     <sbr/>
 </cmdsynopsis>
@@ -44,11 +44,22 @@ monitor the system or session buses respectively.  If neither is
 specified, <command>dbus-monitor</command> monitors the session bus.</para>
 
 
-<para><command>dbus-monitor</command> has two different output modes, the 'classic'-style
-monitoring mode and profiling mode. The profiling format is a compact
+<para><command>dbus-monitor</command> has two different text output
+modes: the 'classic'-style
+monitoring mode, and profiling mode. The profiling format is a compact
 format with a single line per message and microsecond-resolution timing
 information. The --profile and --monitor options select the profiling
-and monitoring output format respectively. If neither is specified,
+and monitoring output format respectively.</para>
+
+<para><command>dbus-monitor</command> also has two binary output modes.
+  The binary mode, selected by <literal>--binary</literal>, outputs the
+  entire binary message stream (without the initial authentication handshake).
+  The PCAP mode, selected by <literal>--pcap</literal>, adds a
+  PCAP file header to the beginning of the output, and prepends a PCAP
+  message header to each message; this produces a binary file that can
+  be read by, for instance, Wireshark.</para>
+
+<para>If no mode is specified,
 <command>dbus-monitor</command> uses the monitoring output format.</para>
 
 
index 5792112caee5bd9835144ba51b13c95ae1cce3f0..ad77690446d179a13774dc60b6e8eb51f70629c3 100644 (file)
@@ -20,6 +20,9 @@
  */
 
 #include <config.h>
+
+#include "dbus/dbus-internals.h"        /* just for the macros */
+
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 
 #define EAVESDROPPING_RULE "eavesdrop=true"
 
+#ifndef STDOUT_FILENO
+#define STDOUT_FILENO 1
+#endif
+
+/* http://www.tcpdump.org/linktypes.html */
+#define LINKTYPE_DBUS 231
+
 #ifdef DBUS_WIN
 
 /* gettimeofday is not defined on windows */
@@ -213,10 +223,85 @@ profile_filter_func (DBusConnection       *connection,
   return DBUS_HANDLER_RESULT_HANDLED;
 }
 
+typedef enum {
+    BINARY_MODE_NOT,
+    BINARY_MODE_RAW,
+    BINARY_MODE_PCAP
+} BinaryMode;
+
+static DBusHandlerResult
+binary_filter_func (DBusConnection *connection,
+                    DBusMessage    *message,
+                    void           *user_data)
+{
+  BinaryMode mode = _DBUS_POINTER_TO_INT (user_data);
+  char *blob;
+  int len;
+
+  /* It would be nice if we could do a zero-copy "peek" one day, but libdbus
+   * is so copy-happy that this isn't really a big deal.
+   */
+  if (!dbus_message_marshal (message, &blob, &len))
+    tool_oom ("retrieving message");
+
+  switch (mode)
+    {
+      case BINARY_MODE_PCAP:
+          {
+            struct timeval t = { 0, 0 };
+            /* seconds, microseconds, bytes captured (possibly truncated),
+             * original length.
+             * http://wiki.wireshark.org/Development/LibpcapFileFormat
+             */
+            dbus_uint32_t header[4] = { 0, 0, len, len };
+
+            /* If this gets padded then we'd need to write it out in pieces */
+            _DBUS_STATIC_ASSERT (sizeof (header) == 16);
+
+            if (_DBUS_UNLIKELY (gettimeofday (&t, NULL) < 0))
+              {
+                /* I'm fairly sure this can't actually happen */
+                perror ("dbus-monitor: gettimeofday");
+                exit (1);
+              }
+
+            header[0] = t.tv_sec;
+            header[1] = t.tv_usec;
+
+            if (!tool_write_all (STDOUT_FILENO, header, sizeof (header)))
+              {
+                perror ("dbus-monitor: write");
+                exit (1);
+              }
+          }
+        break;
+
+      case BINARY_MODE_RAW:
+      default:
+        /* nothing special, just the raw message stream */
+        break;
+    }
+
+  if (!tool_write_all (STDOUT_FILENO, blob, len))
+    {
+      perror ("dbus-monitor: write");
+      exit (1);
+    }
+
+  dbus_free (blob);
+
+  if (dbus_message_is_signal (message,
+                              DBUS_INTERFACE_LOCAL,
+                              "Disconnected"))
+    exit (0);
+
+  return DBUS_HANDLER_RESULT_HANDLED;
+}
+
 static void
 usage (char *name, int ecode)
 {
-  fprintf (stderr, "Usage: %s [--system | --session | --address ADDRESS] [--monitor | --profile ] [watch expressions]\n", name);
+  fprintf (stderr, "Usage: %s [--system | --session | --address ADDRESS] [--monitor | --profile | --pcap | --binary ] [watch expressions]\n", name);
   exit (ecode);
 }
 
@@ -304,7 +389,7 @@ main (int argc, char *argv[])
   DBusHandleMessageFunction filter_func = monitor_filter_func;
   char *address = NULL;
   dbus_bool_t seen_bus_type = FALSE;
-  
+  BinaryMode binary_mode = BINARY_MODE_NOT;
   int i = 0, j = 0, numFilters = 0;
   char **filters = NULL;
 
@@ -348,9 +433,25 @@ main (int argc, char *argv[])
       else if (!strcmp (arg, "--help"))
        usage (argv[0], 0);
       else if (!strcmp (arg, "--monitor"))
-       filter_func = monitor_filter_func;
+        {
+          filter_func = monitor_filter_func;
+          binary_mode = BINARY_MODE_NOT;
+        }
       else if (!strcmp (arg, "--profile"))
-       filter_func = profile_filter_func;
+        {
+          filter_func = profile_filter_func;
+          binary_mode = BINARY_MODE_NOT;
+        }
+      else if (!strcmp (arg, "--binary"))
+        {
+          filter_func = binary_filter_func;
+          binary_mode = BINARY_MODE_RAW;
+        }
+      else if (!strcmp (arg, "--pcap"))
+        {
+          filter_func = binary_filter_func;
+          binary_mode = BINARY_MODE_PCAP;
+        }
       else if (!strcmp (arg, "--"))
        continue;
       else if (arg[0] == '-')
@@ -418,7 +519,8 @@ main (int argc, char *argv[])
       exit (1);
     }
 
-  if (!dbus_connection_add_filter (connection, filter_func, NULL, NULL))
+  if (!dbus_connection_add_filter (connection, filter_func,
+                                   _DBUS_INT_TO_POINTER (binary_mode), NULL))
     {
       fprintf (stderr, "Couldn't add filter!\n");
       exit (1);
@@ -472,6 +574,45 @@ main (int argc, char *argv[])
         }
     }
 
+  switch (binary_mode)
+    {
+      case BINARY_MODE_NOT:
+      case BINARY_MODE_RAW:
+        break;
+
+      case BINARY_MODE_PCAP:
+          {
+            /* We're not using libpcap because the file format is simple
+             * enough not to need it.
+             * http://wiki.wireshark.org/Development/LibpcapFileFormat */
+            struct {
+                dbus_uint32_t magic;
+                dbus_uint16_t major_version;
+                dbus_uint16_t minor_version;
+                dbus_int32_t timezone;
+                dbus_uint32_t precision;
+                dbus_uint32_t max_length;
+                dbus_uint32_t link_type;
+            } header = {
+                0xA1B2C3D4U,  /* magic number */
+                2, 4,         /* v2.4 */
+                0,            /* capture in GMT */
+                0,            /* no opinion on timestamp precision */
+                (1 << 27),    /* D-Bus spec says so */
+                LINKTYPE_DBUS
+            };
+
+            /* Assert that there is no padding */
+            _DBUS_STATIC_ASSERT (sizeof (header) == 24);
+
+            if (!tool_write_all (STDOUT_FILENO, &header, sizeof (header)))
+              {
+                perror ("dbus-monitor: write");
+                exit (1);
+              }
+          }
+        break;
+    }
 
   while (dbus_connection_read_write_dispatch(connection, -1))
     ;
index b6af629f3a9b5152ba43f7c647d88f9bf03c857b..ee5099dba954df88f93f0a3dc6a4bfbe5b37e23a 100644 (file)
 #include <config.h>
 #include "tool-common.h"
 
+#include <errno.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <time.h>
 
 #ifdef DBUS_WIN
+#include <io.h>
 #include <windows.h>
+#else
+#include <unistd.h>
 #endif
 
 /* a hack to avoid having to depend on the static -util version of libdbus;
@@ -58,3 +62,37 @@ tool_oom (const char *doing)
   fprintf (stderr, "OOM while %s\n", doing);
   exit (1);
 }
+
+#ifdef DBUS_WIN
+typedef int WriteResult;
+#define write(fd, buf, len) _write(fd, buf, len)
+#else
+typedef ssize_t WriteResult;
+#endif
+
+dbus_bool_t
+tool_write_all (int fd,
+    const void *buf,
+    size_t size)
+{
+  const char *p = buf;
+  size_t bytes_written = 0;
+
+  while (size > bytes_written)
+    {
+      WriteResult this_time = write (fd, p, size - bytes_written);
+
+      if (this_time < 0)
+        {
+          if (errno == EINTR)
+            continue;
+          else
+            return FALSE;
+        }
+
+      p += this_time;
+      bytes_written += this_time;
+    }
+
+  return TRUE;
+}
index f31076fefa66c5bf6af28c94c293f7fe6b07f2ff..d56abf8ab7009f867c9b0764a0fc8241b944dc51 100644 (file)
@@ -34,5 +34,6 @@
 
 void tool_millisleep (int ms);
 void tool_oom (const char *doing);
+dbus_bool_t tool_write_all (int fd, const void *buf, size_t size);
 
 #endif