class SLPSrvTypeRqst(Packet): name = "SLPSrvTypeRqst" fields_desc = [ FieldLenField("prlist_len", None, length_of="prlist"), BoundStrLenField("prlist", b"", length_from=lambda x: x.prlist_len), FieldLenField("naming_auth_len", None, length_of="naming_auth"), BoundStrLenField("naming_auth", b"", length_from=lambda x: x.naming_auth_len if x.naming_auth_len < 0xffff else 0), FieldLenField("scope_list_len", None, length_of="scope_list"), BoundStrLenField("scope_list", b"DEFAULT", length_from=lambda x: x.scope_list_len), ]
class ISIS_PaddingTlv(ISIS_GenericTlv): name = "ISIS Padding TLV" fields_desc = [ ByteEnumField("type", 8, _isis_tlv_names), FieldLenField("len", None, length_of="padding", fmt="B"), BoundStrLenField("padding", "", length_from=lambda pkt: pkt.len) ]
class _ISIS_GenericTlv_Base(Packet): fields_desc = [ByteField("type", 0), FieldLenField("len", None, length_of="val", fmt="B"), BoundStrLenField("val", "", length_from=lambda pkt: pkt.len)] # noqa: E501 def guess_payload_class(self, p): return conf.padding_layer
class ISIS_DynamicHostnameTlv(ISIS_GenericTlv): name = "ISIS Dynamic Hostname TLV" fields_desc = [ ByteEnumField("type", 137, _isis_tlv_names), FieldLenField("len", None, length_of="hostname", fmt="B"), BoundStrLenField("hostname", "", length_from=lambda pkt: pkt.len) ] # noqa: E501
class SLPExtension(Packet): name = "SLPExtension" __slots__ = ["my_offset", "pkt_len"] fields_desc = [ XShortField("ext_id", 0), ThreeBytesField("next_ext_off", 0), BoundStrLenField( "data", b"", length_from=lambda pkt, *args: pkt._length_from(pkt, *args)) ] @classmethod def _length_from(cls, x): ext_end = x.next_ext_off if x.next_ext_off else x.pkt_len r = max(0, ext_end - x.my_offset - 5) #log.debug(f"Ext: my_len {r} next_off {x.next_ext_off} my_off {x.my_offset} total {x.pkt_len}") if ext_end > x.pkt_len: raise Scapy_Exception( "%s: malformed packet, extension exceeds packet length" % cls.__name__) return r # https://github.com/secdev/scapy/blob/cfe00d5c952e9048a40150390e0025b5ceff7228/scapy/layers/bluetooth.py#L485 def __init__(self, _pkt=None, offset=0, pkt_len=0, **kwargs): self.my_offset = offset self.pkt_len = pkt_len Packet.__init__(self, _pkt, **kwargs) def extract_padding(self, p): return "", p
class ISIS_GenericSubTlv(Packet): name = "ISIS Generic Sub-TLV" fields_desc = [ByteField("type", 0), FieldLenField("len", None, length_of="val", fmt="B"), BoundStrLenField("val", "", length_from=lambda pkt: pkt.len)] def guess_payload_class(self, p): return conf.padding_layer
class SLPAuthBlock(Packet): name = "SLPAuthBlock" fields_desc = [ XShortField("block_structure_descriptor", 0), ShortField("auth_block_len", 0), IntField("timestamp", 0), FieldLenField("slp_spi_len", None, length_of="slp_spi"), BoundStrLenField("slp_spi", b"", length_from=lambda x: x.slp_spi_len), BoundStrLenField( "auth_block", b"", length_from=lambda x: x.auth_block_len - x.slp_spi_len - 8) ] def extract_padding(self, p): # log.debug("Auth >>>> ", p) return "", p
class SLPAttrRqst(Packet): name = "SLPAttrRqst" fields_desc = [ FieldLenField("prlist_len", None, length_of="prlist"), BoundStrLenField("prlist", b"", length_from=lambda x: x.prlist_len), FieldLenField("url_len", None, length_of="url"), BoundStrLenField("url", b"", length_from=lambda x: x.url_len), FieldLenField("scope_list_len", None, length_of="scope_list"), BoundStrLenField("scope_list", b"DEFAULT", length_from=lambda x: x.scope_list_len), FieldLenField("tag_list_len", None, length_of="tag_list"), BoundStrLenField("tag_list", b"", length_from=lambda x: x.tag_list_len), FieldLenField("slp_spi_len", None, length_of="slp_spi"), BoundStrLenField("slp_spi", b"", length_from=lambda x: x.slp_spi_len), ]
class SLPSrvTypeRply(Packet): name = "SLPSrvTypeRply" fields_desc = [ ShortField("error_code", 0), FieldLenField("srvtype_list_len", None, length_of="srvtype_list"), BoundStrLenField("srvtype_list", b"", length_from=lambda x: x.srvtype_list_len) ]
class SLPSrvRqst(Packet): name = "SLPSrvRqst" fields_desc = [ FieldLenField("prlist_len", None, length_of="prlist"), BoundStrLenField("prlist", b"", length_from=lambda x: x.prlist_len), FieldLenField("service_type_len", None, length_of="service_type"), BoundStrLenField("service_type", b"", length_from=lambda x: x.service_type_len), FieldLenField("scope_list_len", None, length_of="scope_list"), BoundStrLenField("scope_list", b"DEFAULT", length_from=lambda x: x.scope_list_len), FieldLenField("predicate_len", None, length_of="predicate"), BoundStrLenField("predicate", b"", length_from=lambda x: x.predicate_len), FieldLenField("slp_spi_len", None, length_of="slp_spi"), BoundStrLenField("slp_spi", b"", length_from=lambda x: x.slp_spi_len), ]
class _PIMGenericTlvBase(Packet): fields_desc = [ ByteField("type", 0), FieldLenField("length", None, length_of="value", fmt="B"), BoundStrLenField("value", "", length_from=lambda pkt: pkt.length) ] def guess_payload_class(self, p): return conf.padding_layer def extract_padding(self, s): return "", s
class SLPURLEntry(Packet): name = "SLPURLEntry" fields_desc = [ ByteField("reserved", 0), ShortField("lifetime", 0), FieldLenField("url_len", None, length_of="url"), BoundStrLenField("url", b"", length_from=lambda x: x.url_len) ] def extract_padding(self, p): # log.debug("URL >>>> ", p) return "", p
class SLPAttrRply(Packet): name = "SLPAttrRply" fields_desc = [ ShortField("error_code", 0), FieldLenField("attr_list_len", None, length_of="attr_list"), BoundStrLenField("attr_list", b"", length_from=lambda x: x.attr_list_len), FieldLenField("auth_blocks_cnt", None, fmt="b", count_of="auth_blocks"), PacketListField("auth_blocks", [], SLPAuthBlock, count_from=lambda pkt: pkt.auth_blocks_cnt), ]
class ISIS_AuthenticationTlv(ISIS_GenericTlv): name = "ISIS Authentication TLV" fields_desc = [ ByteEnumField("type", 10, _isis_tlv_names), FieldLenField("len", None, length_of="password", adjust=lambda pkt, x: x + 1, fmt="B"), # noqa: E501 ByteEnumField("authtype", 1, { 1: "Plain", 17: "HMAC-MD5" }), BoundStrLenField("password", "", maxlen=254, length_from=lambda pkt: pkt.len - 1) ] # noqa: E501
class SLPv2(Packet): name = "SLPv2" __slots__ = ["ext_len"] fields_desc = [ ByteField("version", 2), ByteEnumField("function", 1, _function_names), ThreeBytesField("length", None), FlagsField("flags", 0, 3, "OFR"), BitField("reserved", 0, 13), # TODO: handle sending extententions # http://www.networksorcery.com/enp/rfc/rfc2608.txt Section 9.1 ThreeBytesField("next_ext_off", 0), XShortField("xid", RandShort()), FieldLenField("lang_tag_len", None, length_of="lang_tag"), BoundStrLenField("lang_tag", b"en", length_from=lambda x: x.lang_tag_len), ConditionalField( PacketListField( "extensions", [], SLPExtension, next_cls_cb=lambda pkt, *args: pkt._next_cls_cb(pkt, *args)), # next_cls_cb=lambda pkt, lst, cur, remain: # SLPExtension if pkt.value_follows == 1 and # (len(lst) == 0 or cur.value_follows == 1) and # len(remain) > 4 else None), lambda pkt: pkt.next_ext_off > 0) ] @classmethod def _next_cls_cb(cls, pkt, lst, cur, remain): next_off = pkt.next_ext_off if cur is None else cur.next_ext_off if next_off == 0: return None if next_off + 5 > pkt.length: raise Scapy_Exception( "%s: malformed packet, extension header exceeds packet length" % cls.__name__) if cur is None and next_off < 15: raise Scapy_Exception( "%s: malformed packet, extension points to header" % cls.__name__) if cur is not None and cur.next_ext_off <= cur.my_offset + 5: raise Scapy_Exception("%s: malformed packet, extension overlap" % cls.__name__) return lambda *args: SLPExtension( *args, offset=next_off, pkt_len=pkt.length) # for fn, cls in _function_classes.items(): # def get_conditional_field(fn, cls): # return ConditionalField( # PacketField("slp_body", cls(), cls), # lambda pkt: pkt.function == fn # ) # fields_desc.append(get_conditional_field(fn, cls)) def guess_payload_class(self, payload): ret = _function_classes.get(self.function) #log.debug("Guess next payload", ret) return ret # def extract_padding(self, p): # log.debug(p) # return "", p def pre_dissect(self, s): # move extensions # log.debug(s) length = struct.unpack("!I", b"\x00" + s[2:5])[0] next_ext_offset = struct.unpack("!I", b"\x00" + s[7:10])[0] lang_tag_len = struct.unpack("!H", s[12:14])[0] header_len = 14 + lang_tag_len #log.debug("Len ", length, len(s), next_ext_offset, header_len) self.ext_len = 0 if length > len(s): raise Exception( "%s: malformed packet, shorter than header length" % cls.__name__) if next_ext_offset == 0: return s self.ext_len = len(s) - next_ext_offset #log.debug("ext_len", self.ext_len) # Dropping whats behind length from header,swap payload and extensions ret = s[:header_len] + s[next_ext_offset:length] + \ s[header_len:next_ext_offset] # [:4] + s[-3:] + s[4:-3] # log.debug(s) # log.debug(ret) return ret def post_build(self, p, pay): if len(self.extensions) > 0: raise NotImplementedError("Sending extensions not implemented yet") if self.length is None: tmp_len = len(pay) + len(p) # + 1 # +len(p) #log.debug(p, tmp_len) p = p[:2] + struct.pack("!I", tmp_len)[1:4] + p[5:] return p + pay