Commit 1a28f829 authored by Simon McVittie's avatar Simon McVittie

dbus-monitor: add options to log binary data with or without pcap framing

Bug: https://bugs.freedesktop.org/show_bug.cgi?id=46787Reviewed-by: Philip Withnall's avatarPhilip Withnall <philip.withnall@collabora.co.uk>
parent 8a621b8f
add_definitions("-DDBUS_COMPILATION")
set (dbus_send_SOURCES
../../tools/dbus-print-message.c
../../tools/dbus-print-message.h
......
......@@ -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>
......
......@@ -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))
;
......
......@@ -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;
}
......@@ -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
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment