Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
"""Internet Group Management Protocol."""
from pypacker import pypacker, checksum
from pypacker.pypacker import FIELD_FLAG_AUTOUPDATE
class IGMP(pypacker.Packet):
__hdr__ = (
("type", "B", 0),
("maxresp", "B", 0),
("sum", "H", 0, FIELD_FLAG_AUTOUPDATE),
("group", "4s", b"\x00" * 4)
)
# Convenient access for: group[_s]
group_s = pypacker.get_property_ip4("group")
def _update_fields(self):
if self.sum_au_active and self._changed():
self.sum = 0
self.sum = checksum.in_cksum(pypacker.Packet.bin(self))
("hrd", "H", ARP_HRD_ETH),
("pro", "H", ARP_PRO_IP),
("hln", "B", 6), # hardware address length
("pln", "B", 4), # protocol address length
("op", "H", ARP_OP_REQUEST),
("sha", "6s", b"\x00" * 6), # sender mac
("spa", "4s", b"\x00" * 4), # sender ip
("tha", "6s", b"\x00" * 6), # target mac
("tpa", "4s", b"\x00" * 4) # target ip
)
# convenient access
sha_s = pypacker.get_property_mac("sha")
spa_s = pypacker.get_property_ip4("spa")
tha_s = pypacker.get_property_mac("tha")
tpa_s = pypacker.get_property_ip4("tpa")
("ciaddr", "4s", b"\x00" * 4),
("yiaddr", "4s", b"\x00" * 4),
("siaddr", "4s", b"\x00" * 4),
("giaddr", "4s", b"\x00" * 4),
# MAC + padding
("chaddr", "16s", b"\x00" * 6 + b"\x00" * 10),
("sname", "64s", b"\x00" * 64),
("file", "128s", b"\x00" * 128),
("magic", "I", DHCP_MAGIC),
("opts", None, triggerlist.TriggerList)
)
ciaddr_s = pypacker.get_property_ip4("ciaddr")
yiaddr_s = pypacker.get_property_ip4("yiaddr")
siaddr_s = pypacker.get_property_ip4("siaddr")
giaddr_s = pypacker.get_property_ip4("giaddr")
def _dissect(self, buf):
# logger.debug("DHCP: parsing options, buflen: %d" % len(buf))
self._init_triggerlist("opts", buf[28 + 16 + 64 + 128 + 4:], DHCP.__get_opts)
# logger.debug(buf[28+16+64+128+4:])
# logger.debug("amount of options after parsing: %d" % len(self.opts))
return len(buf)
@staticmethod
def __get_opts(buf):
# logger.debug("DHCP: parsing options from: %s" % buf)
opts = []
i = 0
while i < len(buf):
t = buf[i]
class ARP(pypacker.Packet):
__hdr__ = (
("hrd", "H", ARP_HRD_ETH),
("pro", "H", ARP_PRO_IP),
("hln", "B", 6), # hardware address length
("pln", "B", 4), # protocol address length
("op", "H", ARP_OP_REQUEST),
("sha", "6s", b"\x00" * 6), # sender mac
("spa", "4s", b"\x00" * 4), # sender ip
("tha", "6s", b"\x00" * 6), # target mac
("tpa", "4s", b"\x00" * 4) # target ip
)
# convenient access
sha_s = pypacker.get_property_mac("sha")
spa_s = pypacker.get_property_ip4("spa")
tha_s = pypacker.get_property_mac("tha")
tpa_s = pypacker.get_property_ip4("tpa")
# Simple constant field, deactivated (see Ethernet -> vlan)
# Switching between active/inactive should be avoided because of performance penalty :/
("idk", "H", None),
# Again a simple constant field
("flags", "B", 0),
# Dynamic field: bytestring format, *can* change in length, see dns.DNS
# Field type should be avoided because of performance penalty :/
("yolo", None, b"1234"),
# TriggerList field: variable length, can contain: raw bytes, key/value-tuples (see HTTP) and Packets (see IP)
# Here TriggerList will contain key/value Tuples like (b"\x00", b"1")
("options", None, triggerlist.TriggerList)
)
# Conveniant access should be enabled using properties eg using pypacker.get_property_xxx(...)
src_s = pypacker.get_property_ip4("src")
dst_s = pypacker.get_property_ip4("dst")
# xxx_s = pypacker.get_property_mac("xxx")
# xxx_s = pypacker.get_property_dnsname("xxx")
# Setting/getting values smaller then 1 Byte should be enabled using properties (see layer3/ip.IP -> v, hl)
def __get_flag_fluxcapacitor(self):
return (self.flags & 0x80) >> 15
def __set_flag_fluxcapacitor(self, value):
value_shift = (value & 1) << 15
self.flags = (self.flags & ~0x80) | value_shift
flag_fluxcapacitor = property(__get_flag_fluxcapacitor, __set_flag_fluxcapacitor)
@staticmethod
def _parse_options(buf):
"""
# more fragments follow
ip_frag.flags = 0x1
else:
# last fragment
ip_frag.flags = 0x0
ip_frag.offset = int(off / 8)
ip_frag.body_bytes = payload_sub
fragments.append(ip_frag)
off += fragment_len
return fragments
# Convenient access for: src[_s], dst[_s]
src_s = pypacker.get_property_ip4("src")
dst_s = pypacker.get_property_ip4("dst")
def _dissect(self, buf):
total_header_length = ((buf[0] & 0xf) << 2)
options_length = total_header_length - 20 # total IHL - standard IP-len = options length
if options_length > 0:
# logger.debug("got some IP options: %s" % tl_opts)
self._init_triggerlist("opts", buf[20: 20 + options_length], self._parse_opts)
elif options_length < 0:
# invalid header length: assume no options at all
raise Exception()
# TODO: extract real data length:
# There are some cases where padding can not be identified on ethernet -> do it here (eg VSS shit trailer)
self._init_handler(buf[9], buf[total_header_length:])
return total_header_length
("static_field0", "B", 123),
("static_field1", "H", 456),
("static_field2", "I", 789),
("static_field3_src", "4s", b"\x00" * 4),
("static_field4_dst", "4s", b"\x00" * 4),
# standard dynamic field, no cascading changes needed on changes
# to this header
("dynamic_field0", None, triggerlist.TriggerList),
# specialised dynamic field: update needed on change for subfield
# (part of static_field1)
("dynamic_field1", None, DynamicField),
)
## convenient access for static_field3_src and static_field4_dst: IP4 address
src_s = pypacker.get_property_ip4("static_field3_src")
dst_s = pypacker.get_property_ip4("static_field4_dst")
## values smaller than 1 Byte
def __get_v(self):
return self.static_field1 >> 4
def __set_v(self, value):
self.static_field1 = (value << 4) | (self.static_field1 & 0xf)
subfield = property(__get_v, __set_v)
def _dissect(self, buf):
# static part will be unpacked automatically
# skip 15 Bytes (= B + H + I + 4s + 4s)
self.dynamic_field0.init_lazy_dissect(buf[15:39], self.__dissect_dynamic0)
dynlen = buf[0]
self.dynamic_field1.init_lazy_dissect(buf[39:39 + dynlen], self.__dissect_dynamic1)
("flags", "H", 0),
("ciaddr", "4s", b"\x00" * 4),
("yiaddr", "4s", b"\x00" * 4),
("siaddr", "4s", b"\x00" * 4),
("giaddr", "4s", b"\x00" * 4),
# MAC + padding
("chaddr", "16s", b"\x00" * 6 + b"\x00" * 10),
("sname", "64s", b"\x00" * 64),
("file", "128s", b"\x00" * 128),
("magic", "I", DHCP_MAGIC),
("opts", None, triggerlist.TriggerList)
)
ciaddr_s = pypacker.get_property_ip4("ciaddr")
yiaddr_s = pypacker.get_property_ip4("yiaddr")
siaddr_s = pypacker.get_property_ip4("siaddr")
giaddr_s = pypacker.get_property_ip4("giaddr")
def _dissect(self, buf):
# logger.debug("DHCP: parsing options, buflen: %d" % len(buf))
self._init_triggerlist("opts", buf[28 + 16 + 64 + 128 + 4:], DHCP.__get_opts)
# logger.debug(buf[28+16+64+128+4:])
# logger.debug("amount of options after parsing: %d" % len(self.opts))
return len(buf)
@staticmethod
def __get_opts(buf):
# logger.debug("DHCP: parsing options from: %s" % buf)
opts = []
i = 0
while i < len(buf):
__hdr__ = (
("static_field0", "B", 123),
("static_field1", "H", 456),
("static_field2", "I", 789),
("static_field3_src", "4s", b"\x00" * 4),
("static_field4_dst", "4s", b"\x00" * 4),
# standard dynamic field, no cascading changes needed on changes
# to this header
("dynamic_field0", None, triggerlist.TriggerList),
# specialised dynamic field: update needed on change for subfield
# (part of static_field1)
("dynamic_field1", None, DynamicField),
)
## convenient access for static_field3_src and static_field4_dst: IP4 address
src_s = pypacker.get_property_ip4("static_field3_src")
dst_s = pypacker.get_property_ip4("static_field4_dst")
## values smaller than 1 Byte
def __get_v(self):
return self.static_field1 >> 4
def __set_v(self, value):
self.static_field1 = (value << 4) | (self.static_field1 & 0xf)
subfield = property(__get_v, __set_v)
def _dissect(self, buf):
# static part will be unpacked automatically
# skip 15 Bytes (= B + H + I + 4s + 4s)
self.dynamic_field0.init_lazy_dissect(buf[15:39], self.__dissect_dynamic0)
dynlen = buf[0]