class Dot11EltMicrosoftWPA(Dot11Elt): name = "802.11 Microsoft WPA" match_subclass = True fields_desc = [ ByteField("ID", 221), ByteField("len", None), X3BytesField("oui", 0x0050f2), XByteField("type", 0x01), LEShortField("version", 1), PacketField("group_cipher_suite", RSNCipherSuite(), RSNCipherSuite), LEFieldLenField("nb_pairwise_cipher_suites", 1, count_of="pairwise_cipher_suites"), PacketListField("pairwise_cipher_suites", RSNCipherSuite(), RSNCipherSuite, count_from=lambda p: p.nb_pairwise_cipher_suites), LEFieldLenField("nb_akm_suites", 1, count_of="akm_suites"), PacketListField("akm_suites", AKMSuite(), AKMSuite, count_from=lambda p: p.nb_akm_suites) ]
class NSH(Packet): """Network Service Header. NSH MD-type 1 if there is no ContextHeaders""" name = "NSH" fields_desc = [ BitField('Ver', 0, 2), BitField('OAM', 0, 1), BitField('Critical', 0, 1), BitField('Reserved', 0, 6), BitField('Len', 0, 6), ByteEnumField('MDType', 1, { 1: 'Fixed Length', 2: 'Variable Length' }), ByteEnumField('NextProto', 3, { 1: 'IPv4', 2: 'IPv6', 3: 'Ethernet', 4: 'NSH', 5: 'MPLS' }), X3BytesField('NSP', 0), ByteField('NSI', 1), ConditionalField(XIntField('NPC', 0), lambda pkt: pkt.MDType == 1), ConditionalField(XIntField('NSC', 0), lambda pkt: pkt.MDType == 1), ConditionalField(XIntField('SPC', 0), lambda pkt: pkt.MDType == 1), ConditionalField(XIntField('SSC', 0), lambda pkt: pkt.MDType == 1), ConditionalField( PacketListField("ContextHeaders", None, NSHTLV, count_from="Length"), lambda pkt: pkt.MDType == 2) ] def mysummary(self): return self.sprintf("NSP: %NSP% - NSI: %NSI%")
class RSNCipherSuite(Packet): name = "Cipher suite" fields_desc = [ X3BytesField("oui", 0x000fac), ByteEnumField("cipher", 0x04, { 0x00: "Use group cipher suite", 0x01: "WEP-40", 0x02: "TKIP", 0x03: "OCB", 0x04: "CCMP", 0x05: "WEP-104", 0x06: "BIP-128", 0x07: "Group addressed traffic not allowed", 0x08: "GCMP-128", 0x09: "GCMP-256", 0x0A: "CCMP-256", 0x0B: "BIP-GMAC-128", 0x0C: "BIP-GMAC-256", 0x0D: "BIP-CMAC-256" }) ] def extract_padding(self, s): return "", s
class SNAP(Packet): name = "SNAP" fields_desc = [X3BytesField("OUI", 0x000000), XShortEnumField("code", 0x000, ETHER_TYPES)]
class SD(_SDPacketBase): """ SD Packet NOTE : when adding 'entries' or 'options', do not use list.append() method but create a new list e.g. : p = SD() p.option_array = [SDOption_Config(),SDOption_IP6_EndPoint()] """ SOMEIP_MSGID_SRVID = 0xffff SOMEIP_MSGID_SUBID = 0x1 SOMEIP_MSGID_EVENTID = 0x100 SOMEIP_PROTO_VER = 0x01 SOMEIP_IFACE_VER = 0x01 SOMEIP_MSG_TYPE = SOMEIP.TYPE_NOTIFICATION _sdFlag = collections.namedtuple('Flag', 'mask offset') FLAGSDEF = { "REBOOT": _sdFlag(mask=0x80, offset=7), "UNICAST": _sdFlag(mask=0x40, offset=6) } name = "SD" fields_desc = [ ByteField("flags", 0), X3BytesField("res", 0), FieldLenField("len_entry_array", None, length_of="entry_array", fmt="!I"), PacketListField("entry_array", None, cls=_SDEntry, length_from=lambda pkt: pkt.len_entry_array), FieldLenField("len_option_array", None, length_of="option_array", fmt="!I"), PacketListField("option_array", None, cls=_SDOption, length_from=lambda pkt: pkt.len_option_array) ] def get_flag(self, name): name = name.upper() if (name in self.FLAGSDEF): return ((self.flags & self.FLAGSDEF[name].mask) >> self.FLAGSDEF[name].offset) else: return None def set_flag(self, name, value): name = name.upper() if (name in self.FLAGSDEF): self.flags = (self.flags & (ctypes.c_ubyte(~self.FLAGSDEF[name].mask).value)) \ | ((value & 0x01) << self.FLAGSDEF[name].offset) def set_entryArray(self, entry_list): if (isinstance(entry_list, list)): self.entry_array = entry_list else: self.entry_array = [entry_list] def set_optionArray(self, option_list): if (isinstance(option_list, list)): self.option_array = option_list else: self.option_array = [option_list] def get_someip(self, stacked=False): p = SOMEIP() p.msg_id.srv_id = SD.SOMEIP_MSGID_SRVID p.msg_id.sub_id = SD.SOMEIP_MSGID_SUBID p.msg_id.event_id = SD.SOMEIP_MSGID_EVENTID p.proto_ver = SD.SOMEIP_PROTO_VER p.iface_ver = SD.SOMEIP_IFACE_VER p.msg_type = SD.SOMEIP_MSG_TYPE if (stacked): return (p / self) else: return (p)
class GTPPDUSessionContainer(Packet): # TS 38.415-g30 sect 5 name = "GTP PDU Session Container" deprecated_fields = { "qmp": ("QMP", "2.4.5"), "P": ("PPP", "2.4.5"), "R": ("RQI", "2.4.5"), "extraPadding": ("padding", "2.4.5"), } fields_desc = [ByteField("ExtHdrLen", None), BitEnumField("type", 0, 4, {0: "DL PDU SESSION INFORMATION", 1: "UL PDU SESSION INFORMATION"}), BitField("QMP", 0, 1), # UL (type 1) ConditionalField(BitField("dlDelayInd", 0, 1), lambda pkt: pkt.type == 1), ConditionalField(BitField("ulDelayInd", 0, 1), lambda pkt: pkt.type == 1), # Common BitField("SNP", 0, 1), # UL (type 1) ConditionalField(BitField("N3N9DelayInd", 0, 1), lambda pkt: pkt.type == 1), ConditionalField(XBitField("spareUl1", 0, 1), lambda pkt: pkt.type == 1), # DL (type 0) ConditionalField(XBitField("spareDl1", 0, 2), lambda pkt: pkt.type == 0), ConditionalField(BitField("PPP", 0, 1), lambda pkt: pkt.type == 0), ConditionalField(BitField("RQI", 0, 1), lambda pkt: pkt.type == 0), # Common BitField("QFI", 0, 6), # QoS Flow Identifier # DL (type 0) ConditionalField(XBitField("PPI", 0, 3), lambda pkt: pkt.type == 0 and pkt.PPP == 1), ConditionalField(XBitField("spareDl2", 0, 5), lambda pkt: pkt.type == 0 and pkt.PPP == 1), ConditionalField(XBitField("dlSendTime", 0, 64), lambda pkt: pkt.type == 0 and pkt.QMP == 1), ConditionalField(X3BytesField("dlQFISeqNum", 0), lambda pkt: pkt.type == 0 and pkt.SNP == 1), # UL (type 1) ConditionalField(XBitField("dlSendTimeRpt", 0, 64), lambda pkt: pkt.type == 1 and pkt.QMP == 1), ConditionalField(XBitField("dlRecvTime", 0, 64), lambda pkt: pkt.type == 1 and pkt.QMP == 1), ConditionalField(XBitField("ulSendTime", 0, 64), lambda pkt: pkt.type == 1 and pkt.QMP == 1), ConditionalField(XBitField("dlDelayRslt", 0, 32), lambda pkt: pkt.type == 1 and pkt.dlDelayInd == 1), ConditionalField(XBitField("ulDelayRslt", 0, 32), lambda pkt: pkt.type == 1 and pkt.ulDelayInd == 1), ConditionalField(XBitField("UlQFISeqNum", 0, 24), lambda pkt: pkt.type == 1 and pkt.SNP == 1), ConditionalField(XBitField("N3N9DelayRslt", 0, 32), lambda pkt: pkt.type == 1 and pkt.N3N9DelayInd == 1), # Common ByteEnumField("NextExtHdr", 0, ExtensionHeadersTypes), ConditionalField( StrLenField("padding", b"", length_from=lambda p: 0), lambda pkt: pkt.NextExtHdr == 0)] def guess_payload_class(self, payload): if self.NextExtHdr == 0: sub_proto = orb(payload[0]) if sub_proto >= 0x45 and sub_proto <= 0x4e: return IP elif (sub_proto & 0xf0) == 0x60: return IPv6 else: return PPP return GTPHeader.guess_payload_class(self, payload) def post_dissect(self, s): if self.NextExtHdr == 0: # Padding is handled in this layer length = len(self.original) - len(s) pad_length = (- length) % 4 self.padding = s[:pad_length] return s[pad_length:] return s def post_build(self, p, pay): # Length if self.NextExtHdr == 0: p += b"\x00" * ((-len(p)) % 4) else: pay += b"\x00" * ((-len(p + pay)) % 4) if self.ExtHdrLen is None: p = struct.pack("!B", len(p) // 4) + p[1:] return p + pay
class BTLE(Packet): name = "BT4LE" fields_desc = [ XLEIntField("access_addr", 0x8E89BED6), X3BytesField("crc", None) ] @staticmethod def compute_crc(pdu, init=0x555555): def swapbits(a): v = 0 if a & 0x80 != 0: v |= 0x01 if a & 0x40 != 0: v |= 0x02 if a & 0x20 != 0: v |= 0x04 if a & 0x10 != 0: v |= 0x08 if a & 0x08 != 0: v |= 0x10 if a & 0x04 != 0: v |= 0x20 if a & 0x02 != 0: v |= 0x40 if a & 0x01 != 0: v |= 0x80 return v state = swapbits(init & 0xff) + (swapbits((init >> 8) & 0xff) << 8) + ( swapbits((init >> 16) & 0xff) << 16) # noqa: E501 lfsr_mask = 0x5a6000 for i in (orb(x) for x in pdu): for j in range(8): next_bit = (state ^ i) & 1 i >>= 1 state >>= 1 if next_bit: state |= 1 << 23 state ^= lfsr_mask return struct.pack("<L", state)[:-1] def post_build(self, p, pay): # Switch payload and CRC crc = p[-3:] p = p[:-3] + pay p += crc if self.crc is not None else self.compute_crc(p[4:]) return p def post_dissect(self, s): self.raw_packet_cache = None # Reset packet to allow post_build return s def pre_dissect(self, s): # move crc return s[:4] + s[-3:] + s[4:-3] def post_dissection(self, pkt): if isinstance(pkt, PPI): pkt.notdecoded = PPIGenericFldHdr(pkt.notdecoded) def hashret(self): return struct.pack("!L", self.access_addr)
class EOAM_VendSpecificMsg(Packet): name = "Vendor-Specific OAM" fields_desc = [ X3BytesField("oui", 0x001000), ]
class DlChannelReq(Packet): name = "DlChannelReq" fields_desc = [ByteField("ChIndex", 0), X3BytesField("Freq", 0)]
class KWP_RMBA(Packet): name = 'ReadMemoryByAddress' fields_desc = [ X3BytesField('memoryAddress', 0), ByteField('memorySize', 0) ]
class SD(_SDPacketBase): """ SD Packet NOTE : when adding 'entries' or 'options', do not use list.append() method but create a new list e.g. : p = SD() p.option_array = [SDOption_Config(),SDOption_IP6_EndPoint()] """ SOMEIP_MSGID_SRVID = 0xffff SOMEIP_MSGID_SUBID = 0x1 SOMEIP_MSGID_EVENTID = 0x100 SOMEIP_CLIENT_ID = 0x0000 SOMEIP_MINIMUM_SESSION_ID = 0x0001 SOMEIP_PROTO_VER = 0x01 SOMEIP_IFACE_VER = 0x01 SOMEIP_MSG_TYPE = SOMEIP.TYPE_NOTIFICATION SOMEIP_RETCODE = SOMEIP.RET_E_OK _sdFlag = collections.namedtuple('Flag', 'mask offset') FLAGSDEF = { "REBOOT": _sdFlag(mask=0x80, offset=7), "UNICAST": _sdFlag(mask=0x40, offset=6) } name = "SD" fields_desc = [ XByteField("flags", 0), X3BytesField("res", 0), FieldLenField("len_entry_array", None, length_of="entry_array", fmt="!I"), PacketListField("entry_array", None, _sdentry_class, length_from=lambda pkt: pkt.len_entry_array), FieldLenField("len_option_array", None, length_of="option_array", fmt="!I"), PacketListField("option_array", None, _sdoption_class, length_from=lambda pkt: pkt.len_option_array) ] def get_flag(self, name): name = name.upper() if name in self.FLAGSDEF: return ((self.flags & self.FLAGSDEF[name].mask) >> self.FLAGSDEF[name].offset) else: return None def set_flag(self, name, value): name = name.upper() if name in self.FLAGSDEF: self.flags = (self.flags & (ctypes.c_ubyte(~self.FLAGSDEF[name].mask).value)) \ | ((value & 0x01) << self.FLAGSDEF[name].offset) def set_entryArray(self, entry_list): if isinstance(entry_list, list): self.entry_array = entry_list else: self.entry_array = [entry_list] def set_optionArray(self, option_list): if isinstance(option_list, list): self.option_array = option_list else: self.option_array = [option_list]
class VXLAN(Packet): name = "VXLAN" fields_desc = [ FlagsField( "flags", 0x8, 8, ['OAM', 'R', 'NextProtocol', 'Instance', 'V1', 'V2', 'R', 'G']), ConditionalField( ShortField("reserved0", 0), lambda pkt: pkt.flags.NextProtocol, ), ConditionalField( ByteEnumField('NextProtocol', 0, { 0: 'NotDefined', 1: 'IPv4', 2: 'IPv6', 3: 'Ethernet', 4: 'NSH' }), lambda pkt: pkt.flags.NextProtocol, ), ConditionalField( ThreeBytesField("reserved1", 0), lambda pkt: (not pkt.flags.G) and (not pkt.flags.NextProtocol), ), ConditionalField( FlagsField("gpflags", 0, 8, _GP_FLAGS), lambda pkt: pkt.flags.G, ), ConditionalField( ShortField("gpid", 0), lambda pkt: pkt.flags.G, ), X3BytesField("vni", 0), XByteField("reserved2", 0), ] # Use default linux implementation port overload_fields = { UDP: { 'dport': 8472 }, } def mysummary(self): if self.flags.G: return self.sprintf("VXLAN (vni=%VXLAN.vni% gpid=%VXLAN.gpid%)") else: return self.sprintf("VXLAN (vni=%VXLAN.vni%)") def guess_payload_class(self, payload): if self.underlayer is not None and \ isinstance(self.underlayer, UDP) and \ self.underlayer.dport == 250 and \ self.flags == 8: try: if six.PY2: first_byte = ord(payload[0]) else: first_byte = payload[0] except IndexError: return IP version = divmod(first_byte, 0x10)[0] if version == 4: return IP elif version == 6: return IPv6 else: return IP return Packet.guess_payload_class(self, payload)
class OFPATSetNwToS(OpenFlow): name = "OFPAT_SET_TP_TOS" fields_desc = [ShortEnumField("type", 8, ofp_action_types), ShortField("len", 8), ByteField("nw_tos", 0), X3BytesField("pad", 0)]
class OFPATSetVLANPCP(OpenFlow): name = "OFPAT_SET_VLAN_PCP" fields_desc = [ShortEnumField("type", 2, ofp_action_types), ShortField("len", 8), ByteField("vlan_pcp", 0), X3BytesField("pad", 0)]
class EOAM_VendSpecificMsg(Packet): name = "Vendor-Specific OAM" fields_desc = [ X3BytesField("oui", CABLELABS_OUI), ]
class RXParamSetupReq(Packet): name = "RXParamSetupReq" fields_desc = [DLsettings, X3BytesField("Frequency", 0)]
class NewChannelReq(Packet): name = "NewChannelReq" fields_desc = [ByteField("ChIndex", 0), X3BytesField("Freq", 0), DrRange]
class RTPSSubMessage_DATA(EPacket): """ 0...2...........7...............15.............23...............31 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | RTPS_DATA | flags | octetsToNextHeader | +---------------+---------------+---------------+---------------+ | Flags extraFlags | octetsToInlineQos | +---------------+---------------+---------------+---------------+ | EntityId readerEntityId | +---------------+---------------+---------------+---------------+ | EntityId writerEntityId | +---------------+---------------+---------------+---------------+ | | + SequenceNumber writerSeqNum + | | +---------------+---------------+---------------+---------------+ | | ~ ParameterList inlineQos [only if Q==1] ~ | | +---------------+---------------+---------------+---------------+ | | ~ SerializedData serializedData [only if D==1 || K==1] ~ | | +---------------+---------------+---------------+---------------+ """ name = "RTPS DATA (0x15)" fields_desc = [ XByteField("submessageId", 0x15), XByteField("submessageFlags", 0x00), EField(ShortField("octetsToNextHeader", 0)), XNBytesField("extraFlags", 0x0000, 2), EField(ShortField("octetsToInlineQoS", 0)), X3BytesField("readerEntityIdKey", 0), XByteField("readerEntityIdKind", 0), X3BytesField("writerEntityIdKey", 0), XByteField("writerEntityIdKind", 0), # EnumField( # "reader_id", # default=b"\x00\x00\x00\x00", # fmt="4s", # enum=_rtps_reserved_entity_ids, # ), # EnumField( # "writer_id", # default=b"\x00\x00\x00\x00", # fmt="4s", # enum=_rtps_reserved_entity_ids, # ), EField(IntField("writerSeqNumHi", 0)), EField(IntField("writerSeqNumLow", 0)), # ------------------------------------- ConditionalField( InlineQoSPacketField("inlineQoS", "", InlineQoSPacket), lambda pkt: pkt.submessageFlags & 0b00000010 == 0b00000010, ), ConditionalField( DataPacketField("key", "", DataPacket), lambda pkt: pkt.submessageFlags & 0b00001000 == 0b00001000, ), ConditionalField( DataPacketField("data", "", DataPacket), lambda pkt: pkt.submessageFlags & 0b00000100 == 0b00000100, ), ]
class RejoinReq(Packet): # LoRa 1.1 specs name = "RejoinReq" fields_desc = [ByteField("Type", 0), X3BytesField("NetID", 0), StrFixedLenField("DevEUI", b"\x00" * 8), XShortField("RJcount0", 0)]
class CRX1NewPacketContent(Packet): name = "CRX1 New Packet Content" fields_desc = [ XByteEnumField('protocol_number', 0x12, PROTOCOL_NUMBERS), # Login ConditionalField( BCDStrFixedLenField('terminal_id', '00000000', length=8), lambda pkt: len(pkt.original) > 5 and pkt.protocol_number == 0x01), # GPS Location ConditionalField( ByteField('year', 0x00), lambda pkt: len(pkt.original) > 5 and pkt. protocol_number in (0x12, 0x16)), ConditionalField( ByteField('month', 0x01), lambda pkt: len(pkt.original) > 5 and pkt .protocol_number in (0x12, 0x16)), ConditionalField( ByteField('day', 0x01), lambda pkt: len(pkt.original) > 5 and pkt. protocol_number in (0x12, 0x16)), ConditionalField( ByteField('hour', 0x00), lambda pkt: len(pkt.original) > 5 and pkt. protocol_number in (0x12, 0x16)), ConditionalField( ByteField('minute', 0x00), lambda pkt: len(pkt.original) > 5 and pkt.protocol_number in (0x12, 0x16)), ConditionalField( ByteField('second', 0x00), lambda pkt: len(pkt.original) > 5 and pkt.protocol_number in (0x12, 0x16)), ConditionalField( BitField('gps_information_length', 0x00, 4), lambda pkt: len( pkt.original) > 5 and pkt.protocol_number in (0x12, 0x16)), ConditionalField( BitField('positioning_satellite_number', 0x00, 4), lambda pkt: len( pkt.original) > 5 and pkt.protocol_number in (0x12, 0x16)), ConditionalField( ScalingField('latitude', 0x00, scaling=1.0 / 1800000, ndigits=6, fmt="!I"), lambda pkt: len(pkt.original) > 5 and \ pkt.protocol_number in (0x12, 0x16)), ConditionalField( ScalingField('longitude', 0x00, scaling=1.0 / 1800000, ndigits=6, fmt="!I"), lambda pkt: len(pkt.original) > 5 and \ pkt.protocol_number in (0x12, 0x16)), ConditionalField( ByteField('speed', 0x00), lambda pkt: len(pkt.original) > 5 and pkt .protocol_number in (0x12, 0x16)), ConditionalField( BitField('course', 0x00, 10), lambda pkt: len(pkt.original) > 5 and pkt.protocol_number in (0x12, 0x16)), ConditionalField( BitEnumField('latitude_hemisphere', 0x00, 1, { 0: "South", 1: "North" }), lambda pkt: len(pkt.original) > 5 and pkt.protocol_number in ( 0x12, 0x16)), ConditionalField( BitEnumField('longitude_hemisphere', 0x00, 1, { 0: "East", 1: "West" }), lambda pkt: len(pkt.original) > 5 and pkt.protocol_number in ( 0x12, 0x16)), ConditionalField( BitEnumField('gps_been_positioning', 0x00, 1, { 0: "No", 1: "Yes" }), lambda pkt: len(pkt.original) > 5 and pkt.protocol_number in ( 0x12, 0x16)), ConditionalField( BitEnumField('gps_status', 0x00, 1, { 0: "GPS real-time", 1: "Differential positioning" }), lambda pkt: len(pkt.original) > 5 and pkt.protocol_number in ( 0x12, 0x16)), ConditionalField( BitField('course_status_reserved', 0x00, 2), lambda pkt: len( pkt.original) > 5 and pkt.protocol_number in (0x12, 0x16)), ConditionalField( ByteField('lbs_length', 0x00), lambda pkt: len(pkt.original) > 5 and \ pkt.protocol_number in (0x16, )), ConditionalField( XShortField('mcc', 0x00), lambda pkt: len(pkt.original) > 5 and pkt .protocol_number in (0x12, 0x16)), ConditionalField( XByteField('mnc', 0x00), lambda pkt: len(pkt.original) > 5 and pkt. protocol_number in (0x12, 0x16)), ConditionalField( XShortField('lac', 0x00), lambda pkt: len(pkt.original) > 5 and pkt .protocol_number in (0x12, 0x16)), ConditionalField( X3BytesField('cell_id', 0x00), lambda pkt: len(pkt.original) > 5 and \ pkt.protocol_number in (0x12, 0x16)), ConditionalField( IntField('mileage', 0x00), lambda pkt: len(pkt.original) > 5 and pkt.protocol_number in (0x12, ) and len(pkt.original) > 31), # Heartbeat ConditionalField( BitEnumField('defence', 0x00, 1, { 0: "Deactivated", 1: "Activated" }), lambda pkt: len(pkt.original) > 5 and pkt.protocol_number in ( 0x13, 0x16)), ConditionalField( BitEnumField('acc', 0x00, 1, { 0: "Low", 1: "High" }), lambda pkt: len(pkt.original) > 5 and pkt.protocol_number in ( 0x13, 0x16)), ConditionalField( BitEnumField('charge', 0x00, 1, { 0: "Not Charge", 1: "Charging" }), lambda pkt: len(pkt.original) > 5 and pkt.protocol_number in ( 0x13, 0x16)), ConditionalField( BitEnumField( 'alarm', 0x00, 3, { 0: "Normal", 1: "Vibration", 2: "Power Cut", 3: "Low Battery", 4: "SOS" }), lambda pkt: len(pkt.original) > 5 and pkt.protocol_number in (0x13, 0x16)), ConditionalField( BitEnumField('gps_tracking', 0x00, 1, { 0: "Not Charge", 1: "Charging" }), lambda pkt: len(pkt.original) > 5 and pkt.protocol_number in ( 0x13, 0x16)), ConditionalField( BitEnumField('oil_and_eletricity', 0x00, 1, { 0: "Connected", 1: "Disconnected" }), lambda pkt: len(pkt.original) > 5 and pkt.protocol_number in ( 0x13, 0x16)), ConditionalField( ByteEnumField("voltage_level", 0x00, VOLTAGE_LEVELS), lambda pkt: len(pkt.original) > 5 and pkt.protocol_number in (0x13, 0x16)), ConditionalField( ByteEnumField("gsm_signal_strength", 0x00, GSM_SIGNAL_STRENGTH), lambda pkt: len(pkt.original) > 5 and pkt.protocol_number in (0x13, 0x16)), # Online Command ConditionalField( FieldLenField('command_length', None, fmt='B', length_of="command_content"), lambda pkt: len(pkt.original) > 5 and pkt.protocol_number in (0x80, 0x15)), ConditionalField( XIntField('server_flag_bit', 0x00), lambda pkt: len(pkt.original) > 5 and pkt.protocol_number in (0x80, 0x15)), ConditionalField( StrLenField( "command_content", "", length_from=lambda pkt: pkt.command_length - 4), lambda pkt: len(pkt.original) > 5 and pkt.protocol_number in (0x80, 0x15)), # Commun ConditionalField( ByteEnumField( "alarm_extended", 0x00, { 0x00: "Normal", 0x01: "SOS", 0x02: "Power cut", 0x03: "Vibration", 0x04: "Enter fence", 0x05: "Exit fence", 0x06: "Over speed", 0x09: "Displacement", 0x0a: "Enter GPS dead zone", 0x0b: "Exit GPS dead zone", 0x0c: "Power on", 0x0d: "GPS First fix notice", 0x0e: "Low battery", 0x0f: "Low battery protection", 0x10: "SIM Change", 0x11: "Power off", 0x12: "Airplane mode", 0x13: "Disassemble", 0x14: "Door", 0xfe: "ACC On", 0xff: "ACC Off", }), lambda pkt: len(pkt.original) > 5 and pkt.protocol_number in (0x13, 0x15, 0x16)), ConditionalField( ByteEnumField("language", 0x00, LANGUAGE), lambda pkt: len(pkt.original) > 5 and pkt. protocol_number in (0x13, 0x15, 0x16)), # Information transmission ConditionalField( ByteEnumField("subprotocol_number", 0x00, SUBPROTOCOL_NUMBERS), lambda pkt: len(pkt.original) > 5 and pkt.protocol_number in (0x94, )), ConditionalField( ShortField('external_battery', 0x00), lambda pkt: len(pkt.original) > 5 and pkt. protocol_number in (0x94, ) and pkt.subprotocol_number == 0x00), ConditionalField( FlagsField('external_io_detection', 0x00, 8, [ 'door_status', 'trigger_status', 'io_status', ]), lambda pkt: len(pkt.original) > 5 and pkt.protocol_number in ( 0x94, ) and pkt.subprotocol_number == 0x05), # Default XShortField('information_serial_number', None), XShortField('crc', None), ]