class _ESPPlain(Packet): """ Internal class to represent unencrypted ESP packets. """ name = 'ESP' fields_desc = [ XIntField('spi', 0x0), IntField('seq', 0), StrField('iv', ''), PacketField('data', '', Raw), StrField('padding', ''), ByteField('padlen', 0), ByteEnumField('nh', 0, IP_PROTOS), StrField('icv', ''), ] def data_for_encryption(self): return str(self.data) + self.padding + chr(self.padlen) + chr(self.nh)
class PPTPIncomingCallReply(PPTP): name = "PPTP Incoming Call Reply" fields_desc = [ LenField("len", 148), ShortEnumField("type", 1, _PPTP_msg_type), XIntField("magic_cookie", _PPTP_MAGIC_COOKIE), ShortEnumField("ctrl_msg_type", 10, _PPTP_ctrl_msg_type), XShortField("reserved_0", 0x0000), ShortField("call_id", 1), ShortField("peer_call_id", 1), ByteEnumField("result_code", 1, _PPTP_result_code), ByteEnumField("error_code", 0, _PPTP_general_error_code), ShortField("pkt_window_size", 64), ShortField("pkt_transmit_delay", 0), XShortField("reserved_1", 0x0000) ] def answers(self, other): return isinstance( other, PPTPIncomingCallRequest) and other.call_id == self.peer_call_id
class ESP(Packet): """ Encapsulated Security Payload See https://tools.ietf.org/rfc/rfc4303.txt """ name = 'ESP' fields_desc = [ XIntField('spi', 0x0), IntField('seq', 0), StrField('data', None), ] overload_fields = { IP: {'proto': socket.IPPROTO_ESP}, IPv6: {'nh': socket.IPPROTO_ESP}, IPv6ExtHdrHopByHop: {'nh': socket.IPPROTO_ESP}, IPv6ExtHdrDestOpt: {'nh': socket.IPPROTO_ESP}, IPv6ExtHdrRouting: {'nh': socket.IPPROTO_ESP}, }
class PPTPOutgoingCallRequest(PPTP): name = "PPTP Outgoing Call Request" fields_desc = [ LenField("len", 168), ShortEnumField("type", 1, _PPTP_msg_type), XIntField("magic_cookie", _PPTP_MAGIC_COOKIE), ShortEnumField("ctrl_msg_type", 7, _PPTP_ctrl_msg_type), XShortField("reserved_0", 0x0000), ShortField("call_id", 1), ShortField("call_serial_number", 0), IntField("minimum_bps", 32768), IntField("maximum_bps", 2147483648), IntEnumField("bearer_type", 3, _PPTP_bearer_type), IntEnumField("framing_type", 3, _PPTP_framing_type), ShortField("pkt_window_size", 16), ShortField("pkt_proc_delay", 0), ShortField('phone_number_len', 0), XShortField("reserved_1", 0x0000), StrFixedLenField("phone_number", '', 64), StrFixedLenField("subaddress", '', 64) ]
class AOE(Packet): name = "ATA over Ethernet" fields_desc = [ BitField("version", 1, 4), FlagsField("flags", 0, 4, ["Response", "Error", "r1", "r2"]), ByteEnumField( "error", 0, { 1: "Unrecognized command code", 2: "Bad argument parameter", 3: "Device unavailable", 4: "Config string present", 5: "Unsupported exception", 6: "Target is reserved" }), XShortField("major", 0xFFFF), XByteField("minor", 0xFF), ByteEnumField( "cmd", 1, { 0: "Issue ATA Command", 1: "Query Config Information", 2: "Mac Mask List", 3: "Reserve / Release" }), XIntField("tag", 0), ConditionalField( PacketField("i_ata_cmd", IssueATACommand(), IssueATACommand), lambda x: x.cmd == 0), ConditionalField( PacketField("q_conf_info", QueryConfigInformation(), QueryConfigInformation), lambda x: x.cmd == 1), ConditionalField(PacketField("mac_m_list", MacMaskList(), MacMaskList), lambda x: x.cmd == 2), ConditionalField( PacketField("res_rel", ReserveRelease(), ReserveRelease), lambda x: x.cmd == 3) ] def extract_padding(self, s): return "", s
class PPTP(Packet): name = "PPTP" fields_desc = [FieldLenField("len", None, fmt="H", length_of="data", adjust=lambda p, x: x + 12), ShortEnumField("type", 1, _PPTP_msg_type), XIntField("magic_cookie", _PPTP_MAGIC_COOKIE), ShortEnumField("ctrl_msg_type", 1, _PPTP_ctrl_msg_type), XShortField("reserved_0", 0x0000), StrLenField("data", "", length_from=lambda p: p.len - 12)] registered_options = {} @classmethod def register_variant(cls): cls.registered_options[cls.ctrl_msg_type.default] = cls @classmethod def dispatch_hook(cls, _pkt=None, *args, **kargs): if _pkt: o = orb(_pkt[9]) return cls.registered_options.get(o, cls) return cls
class PPTPStartControlConnectionReply(PPTP): name = "PPTP Start Control Connection Reply" fields_desc = [LenField("len", 156), ShortEnumField("type", 1, _PPTP_msg_type), XIntField("magic_cookie", _PPTP_MAGIC_COOKIE), ShortEnumField("ctrl_msg_type", 2, _PPTP_ctrl_msg_type), XShortField("reserved_0", 0x0000), ShortField("protocol_version", 0x0100), ByteEnumField("result_code", 1, _PPTP_start_control_connection_result), ByteEnumField("error_code", 0, _PPTP_general_error_code), FlagsField("framing_capabilities", 0, 32, _PPTP_FRAMING_CAPABILITIES_FLAGS), FlagsField("bearer_capabilities", 0, 32, _PPTP_BEARER_CAPABILITIES_FLAGS), ShortField("maximum_channels", 65535), ShortField("firmware_revision", 256), StrFixedLenField("host_name", "linux", 64), StrFixedLenField("vendor_string", "", 64)] def answers(self, other): return isinstance(other, PPTPStartControlConnectionRequest)
class AH(Packet): """ Authentication Header See https://tools.ietf.org/rfc/rfc4302.txt """ name = 'AH' def __get_icv_len(self): """ Compute the size of the ICV based on the payloadlen field. Padding size is included as it can only be known from the authentication # noqa: E501 algorithm provided by the Security Association. """ # payloadlen = length of AH in 32-bit words (4-byte units), minus "2" # payloadlen = 3 32-bit word fixed fields + ICV + padding - 2 # ICV = (payloadlen + 2 - 3 - padding) in 32-bit words return (self.payloadlen - 1) * 4 fields_desc = [ ByteEnumField('nh', None, IP_PROTOS), ByteField('payloadlen', None), ShortField('reserved', None), XIntField('spi', 0x0), IntField('seq', 0), XStrLenField('icv', None, length_from=__get_icv_len), # Padding len can only be known with the SecurityAssociation.auth_algo XStrLenField('padding', None, length_from=lambda x: 0), ] overload_fields = { IP: {'proto': socket.IPPROTO_AH}, IPv6: {'nh': socket.IPPROTO_AH}, IPv6ExtHdrHopByHop: {'nh': socket.IPPROTO_AH}, IPv6ExtHdrDestOpt: {'nh': socket.IPPROTO_AH}, IPv6ExtHdrRouting: {'nh': socket.IPPROTO_AH}, }
class PPTPOutgoingCallReply(PPTP): name = "PPTP Outgoing Call Reply" fields_desc = [ LenField("len", 32), ShortEnumField("type", 1, _PPTP_msg_type), XIntField("magic_cookie", _PPTP_MAGIC_COOKIE), ShortEnumField("ctrl_msg_type", 8, _PPTP_ctrl_msg_type), XShortField("reserved_0", 0x0000), ShortField("call_id", 1), ShortField("peer_call_id", 1), ByteEnumField("result_code", 1, _PPTP_result_code), ByteEnumField("error_code", 0, _PPTP_general_error_code), ShortField("cause_code", 0), IntField("connect_speed", 100000000), ShortField("pkt_window_size", 16), ShortField("pkt_proc_delay", 0), IntField("channel_id", 0) ] def answers(self, other): return isinstance( other, PPTPOutgoingCallRequest) and other.call_id == self.peer_call_id
class FSINFO_Reply(Packet): name = 'FSINFO Reply' fields_desc = [ IntEnumField('status', 0, nfsstat3), IntField('attributes_follow', 0), ConditionalField(PacketField('attributes', Fattr3(), Fattr3), lambda pkt: pkt.attributes_follow == 1), ConditionalField(IntField('rtmax', 0), lambda pkt: pkt.status == 0), ConditionalField(IntField('rtpref', 0), lambda pkt: pkt.status == 0), ConditionalField(IntField('rtmult', 0), lambda pkt: pkt.status == 0), ConditionalField(IntField('wtmax', 0), lambda pkt: pkt.status == 0), ConditionalField(IntField('wtpref', 0), lambda pkt: pkt.status == 0), ConditionalField(IntField('wtmult', 0), lambda pkt: pkt.status == 0), ConditionalField(IntField('dtpref', 0), lambda pkt: pkt.status == 0), ConditionalField(LongField('maxfilesize', 0), lambda pkt: pkt.status == 0), ConditionalField(IntField('timedelta_s', 0), lambda pkt: pkt.status == 0), ConditionalField(IntField('timedelta_ns', 0), lambda pkt: pkt.status == 0), ConditionalField(XIntField('properties', 0), lambda pkt: pkt.status == 0), ]
class ExpectedSubmodule(Packet): """Description of a submodule in an API of an expected submodule""" name = "Submodule" fields_desc = [ XShortField("SubslotNumber", 0), XIntField("SubmoduleIdentNumber", 0), # Submodule Properties XByteField("SubmoduleProperties_reserved_2", 0), BitField("SubmoduleProperties_reserved_1", 0, 2), BitField("SubmoduleProperties_DiscardIOXS", 0, 1), BitField("SubmoduleProperties_ReduceOutputSubmoduleDataLength", 0, 1), BitField("SubmoduleProperties_ReduceInputSubmoduleDataLength", 0, 1), BitField("SubmoduleProperties_SharedInput", 0, 1), BitEnumField("SubmoduleProperties_Type", 0, 2, ["NO_IO", "INPUT", "OUTPUT", "INPUT_OUTPUT"]), PacketListField( "DataDescription", [], ExpectedSubmoduleDataDescription, count_from=lambda p: 2 if p.SubmoduleProperties_Type == 3 else 1 ), ] def extract_padding(self, s): return None, s # No extra payload
class SCTPChunkData(_SCTPChunkGuessPayload, Packet): # TODO : add a padding function in post build if this layer is used to generate SCTP chunk data # noqa: E501 fields_desc = [ ByteEnumField("type", 0, sctpchunktypes), BitField("reserved", None, 4), BitField("delay_sack", 0, 1), BitField("unordered", 0, 1), BitField("beginning", 0, 1), BitField("ending", 0, 1), FieldLenField("len", None, length_of="data", adjust=lambda pkt, x: x + 16), # noqa: E501 XIntField("tsn", None), XShortField("stream_id", None), XShortField("stream_seq", None), IntEnumField("proto_id", None, SCTP_PAYLOAD_PROTOCOL_INDENTIFIERS), # noqa: E501 PadField( StrLenField("data", None, length_from=lambda pkt: pkt.len - 16), # noqa: E501 4, padwith=b"\x00"), ]
class AH(Packet): """ Authentication Header See https://tools.ietf.org/rfc/rfc4302.txt """ name = 'AH' fields_desc = [ ByteEnumField('nh', None, IP_PROTOS), ByteField('payloadlen', None), ShortField('reserved', None), XIntField('spi', 0x0), IntField('seq', 0), StrField('icv', None), StrField('padding', None), ] overload_fields = { IP: { 'proto': socket.IPPROTO_AH }, IPv6: { 'nh': socket.IPPROTO_AH }, IPv6ExtHdrHopByHop: { 'nh': socket.IPPROTO_AH }, IPv6ExtHdrDestOpt: { 'nh': socket.IPPROTO_AH }, IPv6ExtHdrRouting: { 'nh': socket.IPPROTO_AH }, }
class FParametersBlock(Packet): """F-Parameters configuration block""" name = "F-Parameters Block" fields_desc = [ # F_Prm_Flag1 BitField("F_Prm_Flag1_Reserved_7", 0, 1), BitField("F_CRC_Seed", 0, 1), BitEnumField("F_CRC_Length", 0, 2, ["CRC-24", "depreciated", "CRC-32", "reserved"]), BitEnumField("F_SIL", 2, 2, ["SIL_1", "SIL_2", "SIL_3", "No_SIL"]), BitField("F_Check_iPar", 0, 1), BitField("F_Check_SeqNr", 0, 1), # F_Prm_Flag2 BitEnumField("F_Par_Version", 1, 2, ["V1", "V2", "reserved_2", "reserved_3"]), BitEnumField("F_Block_ID", 0, 3, F_PARAMETERS_BLOCK_ID), BitField("F_Prm_Flag2_Reserved", 0, 2), BitField("F_Passivation", 0, 1), XShortField("F_Source_Add", 0), XShortField("F_Dest_Add", 0), ShortField("F_WD_Time", 0), ConditionalField( cond=lambda p: p.getfieldval("F_Block_ID") & 0b110 == 0b010, fld=ShortField("F_WD_Time_2", 0)), ConditionalField( cond=lambda p: p.getfieldval("F_Block_ID") & 0b101 == 0b001, fld=XIntField("F_iPar_CRC", 0)), XShortField("F_Par_CRC", 0) ] overload_fields = { IODWriteReq: { "index": 0x100, # commonly used index for F-Parameters block } }
class CARP(Packet): name = "CARP" fields_desc = [BitField("version", 4, 4), BitField("type", 4, 4), ByteField("vhid", 1), ByteField("advskew", 0), ByteField("authlen", 0), ByteField("demotion", 0), ByteField("advbase", 0), XShortField("chksum", 0), XIntField("counter1", 0), XIntField("counter2", 0), XIntField("hmac1", 0), XIntField("hmac2", 0), XIntField("hmac3", 0), XIntField("hmac4", 0), XIntField("hmac5", 0) ] def post_build(self, pkt, pay): if self.chksum == None: pkt = pkt[:6] + struct.pack("!H", checksum(pkt)) + pkt[8:] return pkt
class IE_ChargingId(IE_Base): name = "Charging ID" fields_desc = [ ByteEnumField("ietype", 127, IEType), XIntField("Charging_id", RandInt()) ]
class IE_TEICP(IE_Base): name = "Tunnel Endpoint Identifier Control Plane" fields_desc = [ ByteEnumField("ietype", 17, IEType), XIntField("TEICI", RandInt()) ]
class IE_TEIDI(IE_Base): name = "Tunnel Endpoint Identifier Data" fields_desc = [ ByteEnumField("ietype", 16, IEType), XIntField("TEIDI", RandInt()) ]
class DoIP(Packet): payload_types = { 0x0000: "Generic DoIP header NACK", 0x0001: "Vehicle identification request", 0x0002: "Vehicle identification request with EID", 0x0003: "Vehicle identification request with VIN", 0x0004: "Vehicle announcement message/vehicle identification response message", # noqa: E501 0x0005: "Routing activation request", 0x0006: "Routing activation response", 0x0007: "Alive check request", 0x0008: "Alive check response", 0x4001: "DoIP entity status request", 0x4002: "DoIP entity status response", 0x4003: "Diagnostic power mode information request", 0x4004: "Diagnostic power mode information response", 0x8001: "Diagnostic message", 0x8002: "Diagnostic message ACK", 0x8003: "Diagnostic message NACK" } name = 'DoIP' fields_desc = [ XByteField("protocol_version", 0x02), XByteField("inverse_version", 0xFD), XShortEnumField("payload_type", 0, payload_types), IntField("payload_length", None), ConditionalField( ByteEnumField( "nack", 0, { 0: "Incorrect pattern format", 1: "Unknown payload type", 2: "Message too large", 3: "Out of memory", 4: "Invalid payload length" }), lambda p: p.payload_type in [0x0]), ConditionalField(StrFixedLenField("vin", b"", 17), lambda p: p.payload_type in [3, 4]), ConditionalField(XShortField("logical_address", 0), lambda p: p.payload_type in [4]), ConditionalField(StrFixedLenField("eid", b"", 6), lambda p: p.payload_type in [2, 4]), ConditionalField(StrFixedLenField("gid", b"", 6), lambda p: p.payload_type in [4]), ConditionalField( XByteEnumField( "further_action", 0, { 0x00: "No further action required", 0x01: "Reserved by ISO 13400", 0x02: "Reserved by ISO 13400", 0x03: "Reserved by ISO 13400", 0x04: "Reserved by ISO 13400", 0x05: "Reserved by ISO 13400", 0x06: "Reserved by ISO 13400", 0x07: "Reserved by ISO 13400", 0x08: "Reserved by ISO 13400", 0x09: "Reserved by ISO 13400", 0x0a: "Reserved by ISO 13400", 0x0b: "Reserved by ISO 13400", 0x0c: "Reserved by ISO 13400", 0x0d: "Reserved by ISO 13400", 0x0e: "Reserved by ISO 13400", 0x0f: "Reserved by ISO 13400", 0x10: "Routing activation required to initiate central security", }), lambda p: p.payload_type in [4]), ConditionalField( XByteEnumField( "vin_gid_status", 0, { 0x00: "VIN and/or GID are synchronized", 0x01: "Reserved by ISO 13400", 0x02: "Reserved by ISO 13400", 0x03: "Reserved by ISO 13400", 0x04: "Reserved by ISO 13400", 0x05: "Reserved by ISO 13400", 0x06: "Reserved by ISO 13400", 0x07: "Reserved by ISO 13400", 0x08: "Reserved by ISO 13400", 0x09: "Reserved by ISO 13400", 0x0a: "Reserved by ISO 13400", 0x0b: "Reserved by ISO 13400", 0x0c: "Reserved by ISO 13400", 0x0d: "Reserved by ISO 13400", 0x0e: "Reserved by ISO 13400", 0x0f: "Reserved by ISO 13400", 0x10: "Incomplete: VIN and GID are NOT synchronized" }), lambda p: p.payload_type in [4]), ConditionalField( XShortField("source_address", 0), lambda p: p.payload_type in [5, 8, 0x8001, 0x8002, 0x8003]), # noqa: E501 ConditionalField( XByteEnumField("activation_type", 0, { 0: "Default", 1: "WWH-OBD", 0xe0: "Central security" }), lambda p: p.payload_type in [5]), ConditionalField(XShortField("logical_address_tester", 0), lambda p: p.payload_type in [6]), ConditionalField(XShortField("logical_address_doip_entity", 0), lambda p: p.payload_type in [6]), ConditionalField( XByteEnumField( "routing_activation_response", 0, { 0x00: "Routing activation denied due to unknown source address.", 0x01: "Routing activation denied because all concurrently supported TCP_DATA sockets are registered and active.", # noqa: E501 0x02: "Routing activation denied because an SA different from the table connection entry was received on the already activated TCP_DATA socket.", # noqa: E501 0x03: "Routing activation denied because the SA is already registered and active on a different TCP_DATA socket.", # noqa: E501 0x04: "Routing activation denied due to missing authentication.", 0x05: "Routing activation denied due to rejected confirmation.", 0x06: "Routing activation denied due to unsupported routing activation type.", # noqa: E501 0x07: "Reserved by ISO 13400.", 0x08: "Reserved by ISO 13400.", 0x09: "Reserved by ISO 13400.", 0x0a: "Reserved by ISO 13400.", 0x0b: "Reserved by ISO 13400.", 0x0c: "Reserved by ISO 13400.", 0x0d: "Reserved by ISO 13400.", 0x0e: "Reserved by ISO 13400.", 0x0f: "Reserved by ISO 13400.", 0x10: "Routing successfully activated.", 0x11: "Routing will be activated; confirmation required." }), lambda p: p.payload_type in [6]), ConditionalField(XIntField("reserved_iso", 0), lambda p: p.payload_type in [5, 6]), ConditionalField(XIntField("reserved_oem", 0), lambda p: p.payload_type in [5, 6]), ConditionalField( XByteEnumField("diagnostic_power_mode", 0, { 0: "not ready", 1: "ready", 2: "not supported" }), lambda p: p.payload_type in [0x4004]), ConditionalField( ByteEnumField("node_type", 0, { 0: "DoIP gateway", 1: "DoIP node" }), lambda p: p.payload_type in [0x4002]), ConditionalField(XByteField("max_open_sockets", 0), lambda p: p.payload_type in [0x4002]), ConditionalField(XByteField("cur_open_sockets", 0), lambda p: p.payload_type in [0x4002]), ConditionalField(IntField("max_data_size", 0), lambda p: p.payload_type in [0x4002]), ConditionalField(XShortField("target_address", 0), lambda p: p.payload_type in [0x8001, 0x8002, 0x8003 ]), # noqa: E501 ConditionalField(XByteEnumField("ack_code", 0, {0: "ACK"}), lambda p: p.payload_type in [0x8002]), ConditionalField( ByteEnumField( "nack_code", 0, { 0x00: "Reserved by ISO 13400", 0x01: "Reserved by ISO 13400", 0x02: "Invalid source address", 0x03: "Unknown target address", 0x04: "Diagnostic message too large", 0x05: "Out of memory", 0x06: "Target unreachable", 0x07: "Unknown network", 0x08: "Transport protocol error" }), lambda p: p.payload_type in [0x8003]), ] def answers(self, other): # type: (Packet) -> int """DEV: true if self is an answer from other""" if other.__class__ == self.__class__: if self.payload_type == 0: return 1 matches = [(4, 1), (4, 2), (4, 3), (6, 5), (8, 7), (0x4002, 0x4001), (0x4004, 0x4003), (0x8001, 0x8001), (0x8003, 0x8001)] if (self.payload_type, other.payload_type) in matches: if self.payload_type == 0x8001: return self.payload.answers(other.payload) return 1 return 0 def hashret(self): # type: () -> bytes if self.payload_type in [0x8001, 0x8002, 0x8003]: return bytes(self)[:2] + struct.pack( "H", self.target_address ^ self.source_address) return bytes(self)[:2] def post_build(self, pkt, pay): # type: (bytes, bytes) -> bytes """ This will set the Field 'payload_length' to the correct value. """ if self.payload_length is None: pkt = pkt[:4] + struct.pack("!I", len(pay) + len(pkt) - 8) + \ pkt[8:] return pkt + pay def extract_padding(self, s): # type: (bytes) -> Tuple[bytes, Optional[bytes]] if self.payload_type == 0x8001: return s[:self.payload_length - 4], None else: return b"", None
class GET_ACTIVE_CAL_PAGE_DTO(Packet): fields_desc = [XByteField('address_extension', 0), XIntField('address', 0)]
class PROGRAM_6_DTO(Packet): fields_desc = [ ByteField('MTA0_extension', 0), XIntField('MTA0_address', 0) ]
class WRITE_DAQ(Packet): fields_desc = [ XByteField('DAQ_size', 0), XByteField('address_extension', 0), XIntField('address', 0), ]
class SCTPChunkParamSuccessIndication(_SCTPChunkParam, Packet): fields_desc = [ShortEnumField("type", 0xc005, sctpchunkparamtypes), ShortField("len", 8), XIntField("correlation_id", None), ]
class SHORT_UP(Packet): fields_desc = [ XByteField('size', 0), XByteField('address_extension', 0), XIntField('address', 0), ]
class SET_MTA(Packet): fields_desc = [ XByteField('mta_num', 0), XByteField('address_extension', 0), XIntField('address', 0), ]
class SCTPChunkParamAdaptationLayer(_SCTPChunkParam, Packet): fields_desc = [ShortEnumField("type", 0xc006, sctpchunkparamtypes), ShortField("len", 8), XIntField("indication", None), ]
class Metadata(Packet): name = 'NSH metadata' fields_desc = [XIntField('value', 0)]
class DNLOAD_6_DTO(Packet): fields_desc = [ XByteField('MTA0_extension', 0), XIntField('MTA0_address', 0) ]
class GET_DAQ_SIZE(Packet): fields_desc = [ XByteField('DAQ_num', 0), XByteField('ccp_reserved', 0), XIntField('DTO_identifier', 0), ]
class SCTPChunkShutdown(_SCTPChunkGuessPayload, Packet): fields_desc = [ByteEnumField("type", 7, sctpchunktypes), XByteField("flags", None), ShortField("len", 8), XIntField("cumul_tsn_ack", None), ]