From 98d3ff422570ae47c2f19f7d8115431e0e2b6ed3 Mon Sep 17 00:00:00 2001 From: Pierre Lalet <pierre@droids-corp.org> Date: Wed, 13 Apr 2016 09:51:24 +0000 Subject: [PATCH] PacketList.conversations(): add labels, support ARP by default (#122) * PacketList.conversations(): include ARP packets by default * PacketList.conversations(): accept a label instead of counting * PacketList.conversations(): display the label in the graph --- scapy/plist.py | 30 +++++++++++++++++++++++------- 1 file changed, 23 insertions(+), 7 deletions(-) diff --git a/scapy/plist.py b/scapy/plist.py index 3dc64866..987d39db 100644 --- a/scapy/plist.py +++ b/scapy/plist.py @@ -284,25 +284,41 @@ lfilter: truth function to apply to each packet to decide whether it will be dis def conversations(self, getsrcdst=None,**kargs): """Graphes a conversations between sources and destinations and display it (using graphviz and imagemagick) - getsrcdst: a function that takes an element of the list and return the source and dest - by defaults, return source and destination IP + getsrcdst: a function that takes an element of the list and + returns the source, the destination and optionally + a label. By default, returns the IP source and + destination from IP and ARP layers type: output type (svg, ps, gif, jpg, etc.), passed to dot's "-T" option target: filename or redirect. Defaults pipe to Imagemagick's display program prog: which graphviz program to use""" if getsrcdst is None: - getsrcdst = lambda x:(x['IP'].src, x['IP'].dst) + def getsrcdst(pkt): + if IP in pkt: + return (pkt[IP].src, pkt[IP].dst) + if ARP in pkt: + return (pkt[ARP].psrc, pkt[ARP].pdst) + raise TypeError() conv = {} for p in self.res: p = self._elt2pkt(p) try: c = getsrcdst(p) except: - #XXX warning() + # No warning here: it's OK that getsrcdst() raises an + # exception, since it might be, for example, a + # function that expects a specific layer in each + # packet. The try/except approach is faster and + # considered more Pythonic than adding tests. continue - conv[c] = conv.get(c,0)+1 + if len(c) == 3: + conv.setdefault(c[:2], set()).add(c[2]) + else: + conv[c] = conv.get(c, 0) + 1 gr = 'digraph "conv" {\n' - for s,d in conv: - gr += '\t "%s" -> "%s"\n' % (s,d) + for (s, d), l in conv.iteritems(): + gr += '\t "%s" -> "%s" [label="%s"]\n' % ( + s, d, ', '.join(str(x) for x in l) if isinstance(l, set) else l + ) gr += "}\n" return do_graph(gr, **kargs) -- GitLab