summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSimon McVittie <simon.mcvittie@collabora.co.uk>2015-01-23 19:32:31 +0000
committerSimon McVittie <simon.mcvittie@collabora.co.uk>2015-02-04 17:15:34 +0000
commit1a28f82926c31ae17b8688bdeb6d68f29d628592 (patch)
tree0ecd757a2b158f4c79841b705da72126ab7fa285
parent8a621b8f77706d2ce4feb7b0ffa946b4b95326c8 (diff)
downloaddbus-1a28f82926c31ae17b8688bdeb6d68f29d628592.tar.gz
dbus-monitor: add options to log binary data with or without pcap framing
Bug: https://bugs.freedesktop.org/show_bug.cgi?id=46787 Reviewed-by: Philip Withnall <philip.withnall@collabora.co.uk>
-rw-r--r--cmake/tools/CMakeLists.txt2
-rw-r--r--doc/dbus-monitor.1.xml.in19
-rw-r--r--tools/dbus-monitor.c151
-rw-r--r--tools/tool-common.c38
-rw-r--r--tools/tool-common.h1
5 files changed, 202 insertions, 9 deletions
diff --git a/cmake/tools/CMakeLists.txt b/cmake/tools/CMakeLists.txt
index e406daa7..d4eeb708 100644
--- a/cmake/tools/CMakeLists.txt
+++ b/cmake/tools/CMakeLists.txt
@@ -1,3 +1,5 @@
+add_definitions("-DDBUS_COMPILATION")
+
set (dbus_send_SOURCES
../../tools/dbus-print-message.c
../../tools/dbus-print-message.h
diff --git a/doc/dbus-monitor.1.xml.in b/doc/dbus-monitor.1.xml.in
index af05e3aa..2f807d2f 100644
--- a/doc/dbus-monitor.1.xml.in
+++ b/doc/dbus-monitor.1.xml.in
@@ -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>
diff --git a/tools/dbus-monitor.c b/tools/dbus-monitor.c
index 5792112c..ad776904 100644
--- a/tools/dbus-monitor.c
+++ b/tools/dbus-monitor.c
@@ -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>
@@ -38,6 +41,13 @@
#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))
;
diff --git a/tools/tool-common.c b/tools/tool-common.c
index b6af629f..ee5099db 100644
--- a/tools/tool-common.c
+++ b/tools/tool-common.c
@@ -24,13 +24,17 @@
#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;
+}
diff --git a/tools/tool-common.h b/tools/tool-common.h
index f31076fe..d56abf8a 100644
--- a/tools/tool-common.h
+++ b/tools/tool-common.h
@@ -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