mirror of https://github.com/dirtbags/netarch.git
Refactored demux and resequence into new class
This commit is contained in:
parent
ef0b4ac1e3
commit
8c69a8933e
131
ip.py
131
ip.py
|
@ -10,6 +10,7 @@ import warnings
|
||||||
import heapq
|
import heapq
|
||||||
import gapstr
|
import gapstr
|
||||||
import time
|
import time
|
||||||
|
import pcap
|
||||||
import UserDict
|
import UserDict
|
||||||
from __init__ import *
|
from __init__ import *
|
||||||
|
|
||||||
|
@ -250,6 +251,7 @@ class TCP_Resequence:
|
||||||
self.pending = [{}, {}]
|
self.pending = [{}, {}]
|
||||||
self.frames = 0
|
self.frames = 0
|
||||||
self.closed = 0
|
self.closed = 0
|
||||||
|
self.midstream = False
|
||||||
|
|
||||||
self.handle = self.handle_handshake
|
self.handle = self.handle_handshake
|
||||||
|
|
||||||
|
@ -282,6 +284,8 @@ class TCP_Resequence:
|
||||||
self.handle = self.handle_packet
|
self.handle = self.handle_packet
|
||||||
else:
|
else:
|
||||||
# In the middle of a session, do the best we can
|
# In the middle of a session, do the best we can
|
||||||
|
warnings.warn('Starting mid-stream')
|
||||||
|
self.midstream = True
|
||||||
self.cli, self.srv = pkt.src, pkt.dst
|
self.cli, self.srv = pkt.src, pkt.dst
|
||||||
self.seq = [pkt.seq, pkt.ack]
|
self.seq = [pkt.seq, pkt.ack]
|
||||||
self.handle = self.handle_packet
|
self.handle = self.handle_packet
|
||||||
|
@ -332,50 +336,56 @@ class TCP_Resequence:
|
||||||
warnings.warn('Spurious frame after shutdown: %r %d' % (pkt, pkt.flags))
|
warnings.warn('Spurious frame after shutdown: %r %d' % (pkt, pkt.flags))
|
||||||
|
|
||||||
|
|
||||||
def resequence(pc):
|
class Resequence:
|
||||||
"""Re-sequence from a pcap stream.
|
def __init__(self, *filenames):
|
||||||
|
self.pcs = {}
|
||||||
|
|
||||||
>>> p = pcap.open('whatever.pcap')
|
self.sessions = {}
|
||||||
>>> for chunk in resequence(p):
|
self.tops = []
|
||||||
... print `chunk`
|
|
||||||
|
|
||||||
"""
|
self.last = None
|
||||||
|
|
||||||
sessions = {}
|
for fn in filenames:
|
||||||
for pkt in pc:
|
self.open(fn)
|
||||||
f = Frame(pkt)
|
|
||||||
if f.protocol == TCP:
|
|
||||||
# compute TCP session hash
|
|
||||||
tcp_sess = sessions.get(f.hash)
|
|
||||||
if not tcp_sess:
|
|
||||||
tcp_sess = TCP_Resequence()
|
|
||||||
sessions[f.hash] = tcp_sess
|
|
||||||
chunk = tcp_sess.handle(f)
|
|
||||||
if chunk:
|
|
||||||
yield chunk
|
|
||||||
|
|
||||||
def demux(*pcs):
|
def open(self, filename, literal=False):
|
||||||
"""Demultiplex pcap objects based on time.
|
if not literal:
|
||||||
|
parts = filename.split(':::')
|
||||||
|
fn = parts[0]
|
||||||
|
fd = file(fn)
|
||||||
|
pc = pcap.open(fd)
|
||||||
|
if len(parts) > 1:
|
||||||
|
pos = int(parts[1])
|
||||||
|
fd.seek(pos)
|
||||||
|
self._read(pc, fn, fd)
|
||||||
|
else:
|
||||||
|
fd = file(filename)
|
||||||
|
pc = pcap.open(fd)
|
||||||
|
self._read(pc, filename, fd)
|
||||||
|
|
||||||
This is iterable just like a pcap object, so you could for instance do:
|
def _read(self, pc, filename, fd):
|
||||||
|
pos = fd.tell()
|
||||||
>>> resequence(demux(pcap1, pcap2, pcap3))
|
pkt = pc.read()
|
||||||
|
if pkt:
|
||||||
"""
|
heapq.heappush(self.tops, (pkt, pc, filename, fd, pos))
|
||||||
|
|
||||||
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 __iter__(self):
|
||||||
|
while self.tops:
|
||||||
|
pkt, pc, filename, fd, pos = heapq.heappop(self.tops)
|
||||||
|
if not self.last:
|
||||||
|
self.last = (filename, pos)
|
||||||
|
frame = Frame(pkt)
|
||||||
|
if frame.protocol == TCP:
|
||||||
|
# compute TCP session hash
|
||||||
|
tcp_sess = self.sessions.get(frame.hash)
|
||||||
|
if not tcp_sess:
|
||||||
|
tcp_sess = TCP_Resequence()
|
||||||
|
self.sessions[frame.hash] = tcp_sess
|
||||||
|
chunk = tcp_sess.handle(frame)
|
||||||
|
if chunk:
|
||||||
|
yield chunk
|
||||||
|
self.last = None
|
||||||
|
self._read(pc, filename, fd)
|
||||||
|
|
||||||
|
|
||||||
##
|
##
|
||||||
|
@ -394,7 +404,8 @@ class Packet(UserDict.DictMixin):
|
||||||
|
|
||||||
opcodes = {}
|
opcodes = {}
|
||||||
|
|
||||||
def __init__(self, firstframe=None):
|
def __init__(self, session, firstframe=None):
|
||||||
|
self.session = session
|
||||||
self.firstframe = firstframe
|
self.firstframe = firstframe
|
||||||
self.opcode = None
|
self.opcode = None
|
||||||
self.opcode_desc = None
|
self.opcode_desc = None
|
||||||
|
@ -513,28 +524,41 @@ class Session:
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.pending = {}
|
self.pending = {}
|
||||||
|
self.count = 0
|
||||||
|
self.setup()
|
||||||
|
|
||||||
def handle(self, chunk):
|
def setup(self):
|
||||||
|
"""Set things up."""
|
||||||
|
|
||||||
|
pass
|
||||||
|
|
||||||
|
def handle(self, chunk, lastpos):
|
||||||
"""Handle a data burst.
|
"""Handle a data burst.
|
||||||
|
|
||||||
Pass in a chunk.
|
Pass in a chunk.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
saddr = chunk.first.saddr
|
self.lastpos = lastpos
|
||||||
try:
|
try:
|
||||||
(first, data) = self.pending.pop(saddr)
|
saddr = chunk.first.saddr
|
||||||
except KeyError:
|
try:
|
||||||
first = chunk.first
|
(first, data) = self.pending.pop(saddr)
|
||||||
data = gapstr.GapString()
|
except KeyError:
|
||||||
data.extend(chunk.gapstr())
|
first = chunk.first
|
||||||
try:
|
data = gapstr.GapString()
|
||||||
while data:
|
data.extend(chunk.gapstr())
|
||||||
p = self.Packet(first)
|
try:
|
||||||
data = p.handle(data)
|
while data:
|
||||||
self.process(p)
|
p = self.Packet(self, first)
|
||||||
except NeedMoreData:
|
data = p.handle(data)
|
||||||
self.pending[saddr] = (first, data)
|
self.process(p)
|
||||||
|
except NeedMoreData:
|
||||||
|
self.pending[saddr] = (first, data)
|
||||||
|
self.count += 1
|
||||||
|
except:
|
||||||
|
print 'Lastpos: %s:::%d' % lastpos
|
||||||
|
raise
|
||||||
|
|
||||||
def process(self, packet):
|
def process(self, packet):
|
||||||
"""Process a packet.
|
"""Process a packet.
|
||||||
|
@ -546,6 +570,7 @@ class Session:
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
print 'Lastpos: %s:::%d' % self.lastpos
|
||||||
packet.show()
|
packet.show()
|
||||||
|
|
||||||
def done(self):
|
def done(self):
|
||||||
|
|
Loading…
Reference in New Issue