Mini Shell
"""
Internet Protocol version 4 (TCP/IP protocol stack)
"""
from construct import *
import six
from binascii import unhexlify
try:
bytes
except NameError:
bytes = str
class IpAddressAdapter(Adapter):
def _encode(self, obj, context):
if bytes is str:
return "".join(chr(int(b)) for b in obj.split("."))
else:
return bytes(int(b) for b in obj.split("."))
def _decode(self, obj, context):
if bytes is str:
return ".".join(str(ord(b)) for b in obj)
else:
return ".".join("%d" % (b,) for b in obj)
def IpAddress(name):
return IpAddressAdapter(Bytes(name, 4))
def ProtocolEnum(code):
return Enum(code,
ICMP = 1,
TCP = 6,
UDP = 17,
)
ipv4_header = Struct("ip_header",
EmbeddedBitStruct(
Const(Nibble("version"), 4),
ExprAdapter(Nibble("header_length"),
decoder = lambda obj, ctx: obj * 4,
encoder = lambda obj, ctx: obj / 4
),
),
BitStruct("tos",
Bits("precedence", 3),
Flag("minimize_delay"),
Flag("high_throuput"),
Flag("high_reliability"),
Flag("minimize_cost"),
Padding(1),
),
UBInt16("total_length"),
Value("payload_length", lambda ctx: ctx.total_length - ctx.header_length),
UBInt16("identification"),
EmbeddedBitStruct(
Struct("flags",
Padding(1),
Flag("dont_fragment"),
Flag("more_fragments"),
),
Bits("frame_offset", 13),
),
UBInt8("ttl"),
ProtocolEnum(UBInt8("protocol")),
UBInt16("checksum"),
IpAddress("source"),
IpAddress("destination"),
Field("options", lambda ctx: ctx.header_length - 20),
)
if __name__ == "__main__":
cap = unhexlify(six.b("4500003ca0e3000080116185c0a80205d474a126"))
obj = ipv4_header.parse(cap)
print (obj)
print (repr(ipv4_header.build(obj)))
Zerion Mini Shell 1.0