Added pcapfile demuxer

This commit is contained in:
Neale Pickett 2008-01-10 17:53:11 -07:00
parent 9949fc600c
commit 6e27defe53
1 changed files with 40 additions and 12 deletions

52
ip.py
View File

@ -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)