dbus-pcap: Track method call responses, option to opt out
The filtering was previously strict on how it matched packets, however
this typically isn't what's desired when tracking down method calls:
Ideally we want to output the response as well.
Enable this by maintaining a set of outstanding method calls identified
by the packet's cookie and sender fields (the tuple is unique across
method calls). Once a corresponding reply is found the tuple is removed
from the call set and the packet yielded.
Signed-off-by: Andrew Jeffery <andrew@aj.id.au>
Change-Id: I6b168bf067e4ec93df2626e65b99edf4dccf6e30
diff --git a/amboar/obmc-scripts/dbus-pcap/dbus-pcap b/amboar/obmc-scripts/dbus-pcap/dbus-pcap
index 17a4f57..548468d 100755
--- a/amboar/obmc-scripts/dbus-pcap/dbus-pcap
+++ b/amboar/obmc-scripts/dbus-pcap/dbus-pcap
@@ -336,12 +336,31 @@
msg = parse_message(RawMessage(data[0], data[:12], data[12:]))
return msg
-def parse_session(session, matchers):
+CallEnvelope = namedtuple("CallEnvelope", "cookie, origin")
+def parse_session(session, matchers, track_calls):
+ calls = set()
for packet in session:
try:
cooked = parse_packet(packet)
- if not matchers or any(all(r(cooked) for r in m) for m in matchers):
+ if not matchers:
yield cooked
+ elif any(all(r(cooked) for r in m) for m in matchers):
+ if cooked.header.fixed.type == MessageType.METHOD_CALL.value:
+ s = [f for f in cooked.header.fields
+ if f.type == MessageFieldType.SENDER][0]
+ calls.add(CallEnvelope(cooked.header.fixed.cookie, s.data))
+ yield cooked
+ elif track_calls:
+ if cooked.header.fixed.type != MessageType.METHOD_RETURN.value:
+ continue
+ rs = [f for f in cooked.header.fields
+ if f.type == MessageFieldType.REPLY_SERIAL][0]
+ d = [f for f in cooked.header.fields
+ if f.type == MessageFieldType.DESTINATION][0]
+ ce = CallEnvelope(rs.data, d.data)
+ if ce in calls:
+ calls.remove(ce)
+ yield cooked
except MalformedPacketError as e:
pass
@@ -395,6 +414,8 @@
parser = ArgumentParser()
parser.add_argument("--json", action="store_true",
help="Emit a JSON representation of the messages")
+ parser.add_argument("--no-track-calls", action="store_true", default=False,
+ help="Make a call response pass filters")
parser.add_argument("file", help="The pcap file")
parser.add_argument("expressions", nargs="*",
help="DBus message match expressions")
@@ -403,10 +424,10 @@
matchers = parse_match_rules(args.expressions)
try:
if args.json:
- for msg in parse_session(stream, matchers):
+ for msg in parse_session(stream, matchers, not args.no_track_calls):
print(json.dumps(msg, default=packetconv))
else:
- for msg in parse_session(stream, matchers):
+ for msg in parse_session(stream, matchers, not args.no_track_calls):
print(msg)
except BrokenPipeError:
pass