mirror of https://github.com/dirtbags/netarch.git
Added pcapfile demuxer
This commit is contained in:
parent
9949fc600c
commit
6e27defe53
52
ip.py
52
ip.py
|
@ -4,6 +4,8 @@ import StringIO
|
||||||
import struct
|
import struct
|
||||||
import socket
|
import socket
|
||||||
import warnings
|
import warnings
|
||||||
|
import heapq
|
||||||
|
|
||||||
|
|
||||||
def unpack(fmt, buf):
|
def unpack(fmt, buf):
|
||||||
"""Unpack buf based on fmt, assuming the rest is a string."""
|
"""Unpack buf based on fmt, assuming the rest is a string."""
|
||||||
|
@ -108,7 +110,6 @@ class Frame:
|
||||||
self.dst_addr, self.dport,
|
self.dst_addr, self.dport,
|
||||||
len(self.payload))
|
len(self.payload))
|
||||||
|
|
||||||
|
|
||||||
class Chunk:
|
class Chunk:
|
||||||
"""Chunk of frames, possibly with gaps.
|
"""Chunk of frames, possibly with gaps.
|
||||||
|
|
||||||
|
@ -116,7 +117,7 @@ class Chunk:
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, seq, drop='3'):
|
def __init__(self, seq=None, drop='3'):
|
||||||
# chr(0x33) == '3'. If you see a bunch of 3s, in the ascii or
|
# chr(0x33) == '3'. If you see a bunch of 3s, in the ascii or
|
||||||
# the hex view, suspect a drop.
|
# the hex view, suspect a drop.
|
||||||
assert len(drop) == 1, "Don't yet support len(drop) > 1"
|
assert len(drop) == 1, "Don't yet support len(drop) > 1"
|
||||||
|
@ -127,9 +128,11 @@ class Chunk:
|
||||||
self.first = None
|
self.first = None
|
||||||
|
|
||||||
def add(self, frame):
|
def add(self, frame):
|
||||||
assert frame.seq >= self.seq, (frame.seq, self.seq)
|
|
||||||
if not self.first:
|
if not self.first:
|
||||||
self.first = frame
|
self.first = frame
|
||||||
|
if self.seq is None:
|
||||||
|
self.seq = frame.seq
|
||||||
|
assert frame.seq >= self.seq, (frame.seq, self.seq)
|
||||||
self.collection[frame.seq] = frame
|
self.collection[frame.seq] = frame
|
||||||
end = frame.seq - self.seq + len(frame.payload)
|
end = frame.seq - self.seq + len(frame.payload)
|
||||||
self.length = max(self.length, long(end))
|
self.length = max(self.length, long(end))
|
||||||
|
@ -159,13 +162,15 @@ class Chunk:
|
||||||
s += self.drop
|
s += self.drop
|
||||||
return s
|
return s
|
||||||
|
|
||||||
|
def extend(self, other):
|
||||||
|
self.seq = min(self.seq or other.seq, other.seq)
|
||||||
|
for frame in other.collection.itervalues():
|
||||||
|
self.add(frame)
|
||||||
|
|
||||||
def __add__(self, next):
|
def __add__(self, next):
|
||||||
seq = min(self.seq, next.seq)
|
new = self.__class__(self.seq, self.drop)
|
||||||
new = Chunk(seq, self.drop)
|
new.extend(self)
|
||||||
for frame in self.collection.itervalues():
|
new.extend(next)
|
||||||
new.add(frame)
|
|
||||||
for frame in next.collection.itervalues():
|
|
||||||
new.add(frame)
|
|
||||||
return new
|
return new
|
||||||
|
|
||||||
|
|
||||||
|
@ -175,11 +180,11 @@ RST = 4
|
||||||
PSH = 8
|
PSH = 8
|
||||||
ACK = 16
|
ACK = 16
|
||||||
|
|
||||||
class TCP_Session:
|
class TCP_Resequence:
|
||||||
"""TCP session resequencer.
|
"""TCP session resequencer.
|
||||||
|
|
||||||
>>> p = pcap.open('whatever.pcap')
|
>>> p = pcap.open('whatever.pcap')
|
||||||
>>> s = TCP_Session()
|
>>> s = TCP_Resequence()
|
||||||
>>> while True:
|
>>> while True:
|
||||||
... pkt = p.read()
|
... pkt = p.read()
|
||||||
... if not pkt:
|
... if not pkt:
|
||||||
|
@ -357,14 +362,37 @@ def resequence(pc):
|
||||||
# compute TCP session hash
|
# compute TCP session hash
|
||||||
s = sessions.get(f.hash)
|
s = sessions.get(f.hash)
|
||||||
if not s:
|
if not s:
|
||||||
s = TCP_Session()
|
s = TCP_Resequence()
|
||||||
sessions[f.hash] = s
|
sessions[f.hash] = s
|
||||||
chunk = s.handle(f)
|
chunk = s.handle(f)
|
||||||
if chunk:
|
if chunk:
|
||||||
yield chunk
|
yield chunk
|
||||||
|
|
||||||
|
def demux(*pcs):
|
||||||
|
"""Demultiplex pcap objects based on time.
|
||||||
|
|
||||||
|
This is iterable just like a pcap object, so you could for instance do:
|
||||||
|
|
||||||
|
>>> resequence(demux(pcap1, pcap2, pcap3))
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
tops = []
|
||||||
|
for pc in pcs:
|
||||||
|
frame = pc.read()
|
||||||
|
if frame:
|
||||||
|
heapq.heappush(tops, (frame, pc))
|
||||||
|
|
||||||
|
while tops:
|
||||||
|
frame, pc = heapq.heappop(tops)
|
||||||
|
yield frame
|
||||||
|
frame = pc.read()
|
||||||
|
if frame:
|
||||||
|
heapq.heappush(tops, (frame, pc))
|
||||||
|
|
||||||
|
|
||||||
def process_http(filename):
|
def process_http(filename):
|
||||||
|
# XXX: probably broken
|
||||||
import pcap
|
import pcap
|
||||||
|
|
||||||
pc = pcap.open(filename)
|
pc = pcap.open(filename)
|
||||||
|
|
Loading…
Reference in New Issue