diff options
author | Simon McVittie <simon.mcvittie@collabora.co.uk> | 2015-01-23 19:32:31 +0000 |
---|---|---|
committer | Simon McVittie <simon.mcvittie@collabora.co.uk> | 2015-02-04 17:15:34 +0000 |
commit | 1a28f82926c31ae17b8688bdeb6d68f29d628592 (patch) | |
tree | 0ecd757a2b158f4c79841b705da72126ab7fa285 | |
parent | 8a621b8f77706d2ce4feb7b0ffa946b4b95326c8 (diff) | |
download | dbus-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.txt | 2 | ||||
-rw-r--r-- | doc/dbus-monitor.1.xml.in | 19 | ||||
-rw-r--r-- | tools/dbus-monitor.c | 151 | ||||
-rw-r--r-- | tools/tool-common.c | 38 | ||||
-rw-r--r-- | tools/tool-common.h | 1 |
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 |