mirror of https://github.com/dirtbags/netarch.git
Removed scapy dependence
This commit is contained in:
parent
344caeb0c4
commit
3232991bc8
106
resequence.py
106
resequence.py
|
@ -1,11 +1,71 @@
|
||||||
#! /usr/bin/python
|
#! /usr/bin/python
|
||||||
|
|
||||||
import scapy
|
|
||||||
import StringIO
|
import StringIO
|
||||||
|
import struct
|
||||||
|
import socket
|
||||||
|
|
||||||
IP = scapy.IP
|
def unpack(fmt, buf):
|
||||||
TCP = scapy.TCP
|
"""Unpack buf based on fmt, assuming the rest is a string."""
|
||||||
Raw = scapy.Raw
|
|
||||||
|
size = struct.calcsize(fmt)
|
||||||
|
vals = struct.unpack(fmt, buf[:size])
|
||||||
|
return vals + (buf[size:],)
|
||||||
|
|
||||||
|
def unpack_nybbles(byte):
|
||||||
|
return (byte >> 4, byte & 0x0F)
|
||||||
|
|
||||||
|
class Frame:
|
||||||
|
def __init__(self, frame):
|
||||||
|
(self.eth_dhost,
|
||||||
|
self.eth_shost,
|
||||||
|
self.eth_type,
|
||||||
|
p) = unpack('!6s6sH', frame)
|
||||||
|
if self.eth_type != 0x0800:
|
||||||
|
raise ValueError('Not IP %04x' % self.eth_type)
|
||||||
|
|
||||||
|
(self.ihlvers,
|
||||||
|
self.tos,
|
||||||
|
self.tot_len,
|
||||||
|
self.id,
|
||||||
|
self.frag_off,
|
||||||
|
self.ttl,
|
||||||
|
self.protocol,
|
||||||
|
self.check,
|
||||||
|
self.saddr,
|
||||||
|
self.daddr,
|
||||||
|
p) = unpack("!BBHHHBBH4s4s", p)
|
||||||
|
if self.protocol != 6:
|
||||||
|
raise ValueError('Not TCP')
|
||||||
|
|
||||||
|
(self.th_sport,
|
||||||
|
self.th_dport,
|
||||||
|
self.th_seq,
|
||||||
|
self.th_ack,
|
||||||
|
x2off,
|
||||||
|
self.th_flags,
|
||||||
|
self.th_win,
|
||||||
|
self.th_sum,
|
||||||
|
self.th_urp,
|
||||||
|
p) = unpack("!HHLLBBHHH", p)
|
||||||
|
(th_off, th_x2) = unpack_nybbles(x2off)
|
||||||
|
opt_length = th_off * 4
|
||||||
|
|
||||||
|
self.th_options = p[20:opt_length]
|
||||||
|
payload = p[opt_length:self.tot_len - 40]
|
||||||
|
|
||||||
|
self.src = (self.saddr, self.th_sport)
|
||||||
|
self.dst = (self.daddr, self.th_dport)
|
||||||
|
self.seq = self.th_seq
|
||||||
|
self.ack = self.th_ack
|
||||||
|
self.payload = payload
|
||||||
|
|
||||||
|
self.saddr = socket.inet_ntoa(self.saddr)
|
||||||
|
self.daddr = socket.inet_ntoa(self.daddr)
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return '<Frame %s:%d -> %s:%d len %d>' % (self.saddr, self.th_sport,
|
||||||
|
self.daddr, self.th_dport,
|
||||||
|
len(self.payload))
|
||||||
|
|
||||||
|
|
||||||
class DropStringIO(StringIO.StringIO):
|
class DropStringIO(StringIO.StringIO):
|
||||||
|
@ -57,33 +117,37 @@ class TCP_Session:
|
||||||
self.read_handshake()
|
self.read_handshake()
|
||||||
|
|
||||||
def read_packet(self):
|
def read_packet(self):
|
||||||
|
while True:
|
||||||
p = self.pc.read()
|
p = self.pc.read()
|
||||||
if not p:
|
if not p:
|
||||||
return
|
return
|
||||||
return scapy.Ether(p[1])
|
try:
|
||||||
|
return Frame(p[1])
|
||||||
|
except ValueError:
|
||||||
|
raise
|
||||||
|
|
||||||
def read_handshake(self):
|
def read_handshake(self):
|
||||||
# Read SYN
|
# Read SYN
|
||||||
pkt = self.read_packet()
|
pkt = self.read_packet()
|
||||||
assert (pkt[TCP].flags == 2) # XXX: There's got to be a better way
|
assert (pkt.th_flags == 2) # XXX: There's got to be a better way
|
||||||
self.cli = (pkt[IP].src, pkt.sport)
|
self.cli = pkt.src
|
||||||
self.srv = (pkt[IP].dst, pkt.dport)
|
self.srv = pkt.dst
|
||||||
self.seq[0] = pkt.seq + 1
|
self.seq[0] = pkt.seq + 1
|
||||||
|
|
||||||
# Read SYN-ACK
|
# Read SYN-ACK
|
||||||
while True:
|
while True:
|
||||||
pkt = self.read_packet()
|
pkt = self.read_packet()
|
||||||
if ((pkt[IP].src == self.srv[0]) and
|
if ((pkt.src == self.srv) and
|
||||||
(pkt[TCP].flags == 18)):
|
(pkt.th_flags == 18)):
|
||||||
self.seq[1] = pkt.seq + 1
|
self.seq[1] = pkt.th_seq + 1
|
||||||
break
|
break
|
||||||
|
|
||||||
# Read ACK
|
# Read ACK
|
||||||
while True:
|
while True:
|
||||||
pkt = self.read_packet()
|
pkt = self.read_packet()
|
||||||
if ((pkt[IP].src == self.cli[0]) and
|
if ((pkt.src == self.cli) and
|
||||||
(pkt[TCP].flags == 16)):
|
(pkt.th_flags == 16)):
|
||||||
assert (self.seq[0] == pkt.seq)
|
assert (self.seq[0] == pkt.th_seq)
|
||||||
break
|
break
|
||||||
|
|
||||||
self.frames = 3
|
self.frames = 3
|
||||||
|
@ -96,30 +160,30 @@ class TCP_Session:
|
||||||
self.frames += 1
|
self.frames += 1
|
||||||
|
|
||||||
# Which way is this going?
|
# Which way is this going?
|
||||||
idx = int(pkt[IP].src == self.srv[0])
|
idx = int(pkt.src == self.srv)
|
||||||
xdi = 1 - idx
|
xdi = 1 - idx
|
||||||
|
|
||||||
# Does this ACK after the last output sequence number?
|
# Does this ACK after the last output sequence number?
|
||||||
if pkt.ack > self.seq[xdi]:
|
if pkt.th_ack > self.seq[xdi]:
|
||||||
pending = self.pending[xdi]
|
pending = self.pending[xdi]
|
||||||
seq = self.seq[xdi]
|
seq = self.seq[xdi]
|
||||||
ret = DropStringIO()
|
ret = DropStringIO()
|
||||||
keys = pending.keys()
|
keys = pending.keys()
|
||||||
for key in keys:
|
for key in keys:
|
||||||
if key >= pkt.ack:
|
if key >= pkt.th_ack:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
pkt2 = pending[key]
|
pkt2 = pending[key]
|
||||||
del pending[key]
|
del pending[key]
|
||||||
|
|
||||||
ret.seek(pkt2.seq - seq)
|
ret.seek(pkt2.th_seq - seq)
|
||||||
ret.write(pkt2[TCP][Raw].load)
|
ret.write(pkt2.payload)
|
||||||
self.seq[xdi] = pkt.ack
|
self.seq[xdi] = pkt.th_ack
|
||||||
|
|
||||||
yield (xdi, ret.getvalue())
|
yield (xdi, ret.getvalue())
|
||||||
|
|
||||||
# If it has a payload, stick it into pending
|
# If it has a payload, stick it into pending
|
||||||
if hasattr(pkt[TCP][Raw], 'load'):
|
if pkt.payload:
|
||||||
self.pending[idx][pkt.seq] = pkt
|
self.pending[idx][pkt.seq] = pkt
|
||||||
self.done()
|
self.done()
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue