mirror of https://github.com/dirtbags/netarch.git
Integrate GapString and a few tweaks
This commit is contained in:
parent
473d1fc440
commit
9d487edfb3
99
__init__.py
99
__init__.py
|
@ -10,47 +10,82 @@ def unpack(fmt, buf):
|
||||||
"""Unpack buf based on fmt, return the rest as a string."""
|
"""Unpack buf based on fmt, return the rest as a string."""
|
||||||
|
|
||||||
size = struct.calcsize(fmt)
|
size = struct.calcsize(fmt)
|
||||||
vals = struct.unpack(fmt, buf[:size])
|
vals = struct.unpack(fmt, str(buf[:size]))
|
||||||
return vals + (buf[size:],)
|
return vals + (buf[size:],)
|
||||||
|
|
||||||
|
|
||||||
def to_printable(c):
|
class HexDumper:
|
||||||
if c in printable:
|
def __init__(self, fd=sys.stdout):
|
||||||
return c
|
self.fd = fd
|
||||||
elif c == '\0':
|
self.offset = 0
|
||||||
return '␀'
|
self.buf = []
|
||||||
elif c == '\r':
|
|
||||||
return '␍'
|
def _to_printable(self, c):
|
||||||
elif c == '\n':
|
if not c:
|
||||||
return ''
|
return '◆'
|
||||||
else:
|
elif c in printable:
|
||||||
return '·'
|
return c
|
||||||
|
elif c == '\0':
|
||||||
|
return '␀'
|
||||||
|
elif c == '\r':
|
||||||
|
return '␍'
|
||||||
|
elif c == '\n':
|
||||||
|
return ''
|
||||||
|
else:
|
||||||
|
return '·'
|
||||||
|
|
||||||
|
|
||||||
|
def _flush(self):
|
||||||
|
if not self.buf:
|
||||||
|
return
|
||||||
|
|
||||||
|
o = []
|
||||||
|
for c in self.buf:
|
||||||
|
if c:
|
||||||
|
o.append('%02x' % ord(c))
|
||||||
|
else:
|
||||||
|
o.append('--')
|
||||||
|
o += ([' '] * (16 - len(self.buf)))
|
||||||
|
p = [self._to_printable(c) for c in self.buf]
|
||||||
|
|
||||||
|
self.fd.write('%08x ' % self.offset)
|
||||||
|
|
||||||
|
self.fd.write(' '.join(o[:8]))
|
||||||
|
self.fd.write(' ')
|
||||||
|
self.fd.write(' '.join(o[8:]))
|
||||||
|
|
||||||
|
self.fd.write(' ║')
|
||||||
|
|
||||||
|
self.fd.write(''.join(p))
|
||||||
|
|
||||||
|
self.fd.write('║\n')
|
||||||
|
|
||||||
|
self.buf = []
|
||||||
|
self.offset += 16
|
||||||
|
|
||||||
|
def dump_chr(self, c):
|
||||||
|
self.buf.append(c)
|
||||||
|
if len(self.buf) == 16:
|
||||||
|
self._flush()
|
||||||
|
|
||||||
|
def dump_drop(self):
|
||||||
|
self.buf.append(None)
|
||||||
|
if len(self.buf) == 16:
|
||||||
|
self._flush()
|
||||||
|
|
||||||
|
def finish(self):
|
||||||
|
self._flush()
|
||||||
|
self.fd.write('%08x\n' % self.offset)
|
||||||
|
|
||||||
|
|
||||||
def hexdump(buf, f=sys.stdout):
|
def hexdump(buf, f=sys.stdout):
|
||||||
"Print a hex dump of buf"
|
"Print a hex dump of buf"
|
||||||
|
|
||||||
offset = 0
|
d = HexDumper()
|
||||||
|
|
||||||
while buf:
|
for c in buf:
|
||||||
s = buf[:16]
|
d.dump_chr(c)
|
||||||
o = [('%02x' % ord(c)) for c in s] + ([' '] * (16 - len(s)))
|
d.finish()
|
||||||
p = [to_printable(c) for c in s]
|
|
||||||
|
|
||||||
f.write('%08x ' % offset)
|
|
||||||
|
|
||||||
f.write(' '.join(o[:8]))
|
|
||||||
f.write(' ')
|
|
||||||
f.write(' '.join(o[8:]))
|
|
||||||
|
|
||||||
f.write(' ║')
|
|
||||||
|
|
||||||
f.write(''.join(p))
|
|
||||||
|
|
||||||
f.write('║\n')
|
|
||||||
|
|
||||||
buf = buf[16:]
|
|
||||||
offset += 16
|
|
||||||
|
|
||||||
|
|
||||||
def cstring(buf):
|
def cstring(buf):
|
||||||
|
|
|
@ -186,11 +186,10 @@ tabula_recta = caesars('ABCDEFGHIJKLMNOPQRSTUVWXYZ')
|
||||||
|
|
||||||
|
|
||||||
def xor(n, txt):
|
def xor(n, txt):
|
||||||
out = ''
|
if n == 0:
|
||||||
for c in txt:
|
return txt
|
||||||
o = ord(c) ^ n
|
out = [(chr(ord(c) ^ n)) for c in txt]
|
||||||
out += chr(o)
|
return ''.join(out)
|
||||||
return out
|
|
||||||
|
|
||||||
def xors(txt):
|
def xors(txt):
|
||||||
ret = []
|
ret = []
|
||||||
|
|
|
@ -48,7 +48,7 @@ class GapString:
|
||||||
else:
|
else:
|
||||||
for c in i:
|
for c in i:
|
||||||
d.dump_chr(c)
|
d.dump_chr(c)
|
||||||
d.flush()
|
d.finish()
|
||||||
|
|
||||||
def extend(self, other):
|
def extend(self, other):
|
||||||
self.contents += other.contents
|
self.contents += other.contents
|
||||||
|
@ -56,10 +56,14 @@ class GapString:
|
||||||
|
|
||||||
def __getslice__(self, start, end):
|
def __getslice__(self, start, end):
|
||||||
end = min(self.length, end)
|
end = min(self.length, end)
|
||||||
|
start = min(self.length, start)
|
||||||
|
|
||||||
new = self.__class__(self.drop)
|
new = self.__class__(self.drop)
|
||||||
new.contents = self.contents[:]
|
new.contents = self.contents[:]
|
||||||
new.length = end - start
|
new.length = end - start
|
||||||
|
if new.length == 0:
|
||||||
|
return new
|
||||||
|
|
||||||
l = self.length - new.length - start
|
l = self.length - new.length - start
|
||||||
|
|
||||||
# Trim off the beginning
|
# Trim off the beginning
|
||||||
|
|
48
ip.py
48
ip.py
|
@ -5,6 +5,7 @@ import struct
|
||||||
import socket
|
import socket
|
||||||
import warnings
|
import warnings
|
||||||
import heapq
|
import heapq
|
||||||
|
import gapstr
|
||||||
|
|
||||||
|
|
||||||
def unpack(fmt, buf):
|
def unpack(fmt, buf):
|
||||||
|
@ -110,18 +111,13 @@ 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.
|
||||||
|
|
||||||
Currently, gaps show up as a string of 0x33, ascii '3'.
|
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, seq=None, drop='3'):
|
def __init__(self, seq=None):
|
||||||
# chr(0x33) == '3'. If you see a bunch of 3s, in the ascii or
|
|
||||||
# the hex view, suspect a drop.
|
|
||||||
assert len(drop) == 1, "Don't yet support len(drop) > 1"
|
|
||||||
self.drop = drop
|
|
||||||
self.collection = {}
|
self.collection = {}
|
||||||
self.length = 0
|
self.length = 0
|
||||||
self.seq = seq
|
self.seq = seq
|
||||||
|
@ -130,8 +126,8 @@ class Chunk:
|
||||||
def add(self, frame):
|
def add(self, frame):
|
||||||
if not self.first:
|
if not self.first:
|
||||||
self.first = frame
|
self.first = frame
|
||||||
if self.seq is None:
|
if self.seq is None:
|
||||||
self.seq = frame.seq
|
self.seq = frame.seq
|
||||||
assert frame.seq >= self.seq, (frame.seq, self.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)
|
||||||
|
@ -150,25 +146,35 @@ class Chunk:
|
||||||
else:
|
else:
|
||||||
return '<Chunk (no frames)>'
|
return '<Chunk (no frames)>'
|
||||||
|
|
||||||
def __str__(self):
|
def gapstr(self, drop='?'):
|
||||||
s = ''
|
"""Return contents as a GapString"""
|
||||||
while len(s) < self.length:
|
|
||||||
f = self.collection.get(self.seq + len(s))
|
ret = gapstr.GapString(drop)
|
||||||
|
while len(ret) < self.length:
|
||||||
|
f = self.collection.get(self.seq + len(ret))
|
||||||
if f:
|
if f:
|
||||||
s += f.payload
|
ret.append(f.payload)
|
||||||
else:
|
else:
|
||||||
# This is where to fix it for len(drop) > 1.
|
# This is where to fix big inefficiency for dropped packets.
|
||||||
# This is also where to fix big inefficiency for dropped packets.
|
l = 1
|
||||||
s += self.drop
|
while ((len(ret) + l < self.length) and
|
||||||
return s
|
(not (self.seq + len(ret) + l) in self.collection)):
|
||||||
|
l += 1
|
||||||
|
ret.append(l)
|
||||||
|
return ret
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return str(self.gapstr())
|
||||||
|
|
||||||
def extend(self, other):
|
def extend(self, other):
|
||||||
self.seq = min(self.seq or other.seq, other.seq)
|
self.seq = min(self.seq or other.seq, other.seq)
|
||||||
for frame in other.collection.itervalues():
|
self.length = self.length + other.length
|
||||||
self.add(frame)
|
if not self.first:
|
||||||
|
self.first = other.first
|
||||||
|
self.collection.update(other.collection)
|
||||||
|
|
||||||
def __add__(self, next):
|
def __add__(self, next):
|
||||||
new = self.__class__(self.seq, self.drop)
|
new = self.__class__(self.seq)
|
||||||
new.extend(self)
|
new.extend(self)
|
||||||
new.extend(next)
|
new.extend(next)
|
||||||
return new
|
return new
|
||||||
|
|
Loading…
Reference in New Issue