class MacMaskList(Packet): name = "Mac Mask List" fields_desc = [ ByteField("reserved", 0), ByteEnumField("mcmd", 0, { 0: "Read Mac Mask List", 1: "Edit Mac Mask List" }), ByteEnumField( "merror", 0, { 0: "", 1: "Unspecified error", 2: "Bad dcmd directive", 3: "Mask List Full" }), FieldLenField("dir_count", None, count_of="directives"), PacketListField("directives", None, Directive, count_from=lambda pkt: pkt.dir_count) ] def extract_padding(self, s): return "", s
class GTPUpdatePDPContextRequest(Packet): # 3GPP TS 29.060 V9.1.0 (2009-12) name = "GTP Update PDP Context Request" fields_desc = [PacketListField("IE_list", [ IE_Cause(), IE_Recovery(), IE_TEIDI(), IE_TEICP(), IE_ChargingId(), IE_ProtocolConfigurationOptions(), IE_GSNAddress(), IE_GSNAddress(), IE_GSNAddress(), IE_GSNAddress(), IE_QoS(), IE_CharginGatewayAddress(), IE_CharginGatewayAddress(), IE_CommonFlags(), IE_APNRestriction(), IE_BearerControlMode(), IE_MSInfoChangeReportingAction(), IE_EvolvedAllocationRetentionPriority(), IE_PrivateExtension()], IE_Dispatcher)]
class Radius(Packet): """ Implements a RADIUS packet (RFC 2865). """ name = "RADIUS" fields_desc = [ ByteEnumField("code", 1, _packet_codes), ByteField("id", 0), FieldLenField("len", None, "attributes", "H", adjust=lambda pkt, x: len(pkt.attributes) + 20), XStrFixedLenField("authenticator", "", 16), PacketListField("attributes", [], RadiusAttribute, length_from=lambda pkt: pkt.len - 20) ] def compute_authenticator(self, packed_request_auth, shared_secret): """ Computes the authenticator field (RFC 2865 - Section 3) """ data = prepare_packed_data(self, packed_request_auth) radius_mac = hashlib.md5(data + shared_secret) return radius_mac.digest() def post_build(self, p, pay): p += pay length = self.len if length is None: length = len(p) p = p[:2] + struct.pack("!H", length) + p[4:] return p
class OFPTFlowMod(_ofp_header): name = "OFPT_FLOW_MOD" fields_desc = [ByteEnumField("version", 0x01, ofp_version), ByteEnumField("type", 14, ofp_type), ShortField("len", None), IntField("xid", 0), PacketField("match", OFPMatch(), OFPMatch), LongField("cookie", 0), ShortEnumField("cmd", 0, {0: "OFPFC_ADD", 1: "OFPFC_MODIFY", 2: "OFPFC_MODIFY_STRICT", 3: "OFPFC_DELETE", 4: "OFPFC_DELETE_STRICT"}), ShortField("idle_timeout", 0), ShortField("hard_timeout", 0), ShortField("priority", 0), IntEnumField("buffer_id", "NO_BUFFER", ofp_buffer), ShortEnumField("out_port", "NONE", ofp_port_no), FlagsField("flags", 0, 16, ["SEND_FLOW_REM", "CHECK_OVERLAP", "EMERG"]), PacketListField("actions", [], OFPAT, ofp_action_cls, length_from=lambda pkt:pkt.len - 72)]
class OBD_S08_TID(Packet): name = "Control Operation IDs" fields_desc = [PacketListField("data_records", None, OBD_TID_Record)]
class PPPoED_Tags(Packet): name = "PPPoE Tag List" fields_desc = [PacketListField('tag_list', None, PPPoETag)]
class SAPDiagDyntAtom(Packet): name = "SAP Diag Dynt Atom" fields_desc = [PacketListField("items", None, SAPDiagDyntAtomItem)]
class MQTTConnect(Packet): name = "MQTT connect" fields_desc = [ FieldLenField("length", None, length_of="protoname"), StrLenField("protoname", "", length_from=lambda pkt: pkt.length), ByteEnumField("protolevel", 5, PROTOCOL_LEVEL), BitEnumField("usernameflag", 0, 1, { 0: 'Disabled', 1: 'Enabled' }), BitEnumField("passwordflag", 0, 1, { 0: 'Disabled', 1: 'Enabled' }), BitEnumField("willretainflag", 0, 1, { 0: 'Disabled', 1: 'Enabled' }), BitEnumField("willQOSflag", 0, 2, QOS_LEVEL), BitEnumField("willflag", 0, 1, { 0: 'Disabled', 1: 'Enabled' }), BitEnumField("cleansess", 0, 1, { 0: 'Disabled', 1: 'Enabled' }), BitEnumField("reserved", 0, 1, { 0: 'Disabled', 1: 'Enabled' }), ShortField("klive", 0), #CONNECT PROPERTIES FieldLenField("proplen", None, fmt='B', length_of="properties"), ConditionalField( PacketListField("properties", [], pkt_cls=MQTTProperty, length_from=lambda pkt: pkt.proplen), lambda pkt: pkt.proplen != 0), FieldLenField("clientIdlen", None, length_of="clientId"), StrLenField("clientId", "", length_from=lambda pkt: pkt.clientIdlen), # Payload with optional fields depending on the flags # WILL PROPERTIES ConditionalField( FieldLenField("willproplen", None, fmt='B', length_of="willproperties"), lambda pkt: pkt.willflag == 1), ConditionalField( PacketListField("willproperties", [], pkt_cls=MQTTWillProperty, length_from=lambda pkt: pkt.willproplen), lambda pkt: pkt.willflag == 1), ConditionalField(FieldLenField("wtoplen", None, length_of="willtopic"), lambda pkt: pkt.willflag == 1), ConditionalField( StrLenField("willtopic", "", length_from=lambda pkt: pkt.wtoplen), lambda pkt: pkt.willflag == 1), ConditionalField(FieldLenField("wmsglen", None, length_of="willmsg"), lambda pkt: pkt.willflag == 1), ConditionalField( StrLenField("willmsg", "", length_from=lambda pkt: pkt.wmsglen), lambda pkt: pkt.willflag == 1), ConditionalField(FieldLenField("userlen", None, length_of="username"), lambda pkt: pkt.usernameflag == 1), ConditionalField( StrLenField("username", "", length_from=lambda pkt: pkt.userlen), lambda pkt: pkt.usernameflag == 1), ConditionalField(FieldLenField("passlen", None, length_of="password"), lambda pkt: pkt.passwordflag == 1), ConditionalField( StrLenField("password", "", length_from=lambda pkt: pkt.passlen), lambda pkt: pkt.passwordflag == 1), ]
class GTPErrorIndication(Packet): # 3GPP TS 29.060 V9.1.0 (2009-12) name = "GTP Error Indication" fields_desc = [PacketListField("IE_list", [], IE_Dispatcher)]
class MACCommand_down(Packet): name = "MACCommand_down" fields_desc = [ ByteEnumField("CID", 0, CIDs_up), ConditionalField( PacketListField("Reset", b"", ResetConf, length_from=lambda pkt: 1), lambda pkt: (pkt.CID == 0x01)), ConditionalField( PacketListField("LinkCheck", b"", LinkCheckAns, length_from=lambda pkt: 2), lambda pkt: (pkt.CID == 0x02)), ConditionalField( PacketListField("LinkADR", b"", LinkADRAns, length_from=lambda pkt: 0), lambda pkt: (pkt.CID == 0x03)), ConditionalField( PacketListField("DutyCycle", b"", DutyCycleAns, length_from=lambda pkt: 4), lambda pkt: (pkt.CID == 0x04)), ConditionalField( PacketListField("RXParamSetup", b"", RXParamSetupAns, length_from=lambda pkt: 1), lambda pkt: (pkt.CID == 0x05)), ConditionalField( PacketListField("DevStatusAns", b"", RXParamSetupAns, length_from=lambda pkt: 1), lambda pkt: (pkt.CID == 0x06)), ConditionalField( PacketListField("NewChannel", b"", NewChannelAns, length_from=lambda pkt: 1), lambda pkt: (pkt.CID == 0x07)), ConditionalField( PacketListField("RXTimingSetup", b"", RXTimingSetupAns, length_from=lambda pkt: 0), lambda pkt: (pkt.CID == 0x08)), ConditionalField( PacketListField("TxParamSetup", b"", TxParamSetupAns, length_from=lambda pkt: 0), lambda pkt: (pkt.CID == 0x09)), ConditionalField( PacketListField("DlChannel", b"", DlChannelAns, length_from=lambda pkt: 1), lambda pkt: (pkt.CID == 0x0A)), ConditionalField( PacketListField("Rekey", b"", RekeyConf, length_from=lambda pkt: 1), lambda pkt: (pkt.CID == 0x0B)), ConditionalField( PacketListField("ADRParamSetup", b"", ADRParamSetupAns, length_from=lambda pkt: 0), lambda pkt: (pkt.CID == 0x0C)), ConditionalField( PacketListField("DeviceTime", b"", DeviceTimeAns, length_from=lambda pkt: 5), lambda pkt: (pkt.CID == 0x0D)), ConditionalField( PacketListField("RejoinParamSetup", b"", RejoinParamSetupAns, length_from=lambda pkt: 1), lambda pkt: (pkt.CID == 0x0F)) ]
class PPP_ECP(Packet): fields_desc = [ByteEnumField("code", 1, _PPP_conftypes), XByteField("id", 0), FieldLenField("len", None, fmt="H", length_of="options", adjust=lambda p, x:x+4), PacketListField("options", [], PPP_ECP_Option, length_from=lambda p:p.len-4,)]
class SAPMS(Packet): """SAP Message Server packet This packet is used for the Message Server protocol. """ name = "SAP Message Server" fields_desc = [ StrFixedLenField("eyecatcher", "**MESSAGE**\x00", 12), ByteField("version", 0x04), ByteEnumKeysField("errorno", 0x00, ms_errorno_values), StrFixedLenField("toname", "-" + " " * 39, 40), FlagsField("msgtype", 0, 8, ["DIA", "UPD", "ENQ", "BTC", "SPO", "UP2", "ATP", "ICM"]), ByteField("reserved", 0x00), ByteEnumKeysField("domain", 0x00, ms_domain_values), ByteField("reserved", 0x00), StrFixedLenField("key", "\x00" * 8, 8), ByteEnumKeysField("flag", 0x01, ms_flag_values), ByteEnumKeysField("iflag", 0x01, ms_iflag_values), StrFixedLenField("fromname", "-" + " " * 39, 40), ShortField("padd", 0x0000), # OpCode fields ConditionalField(ByteEnumKeysField("opcode", 0x00, ms_opcode_values), lambda pkt: pkt.iflag in [0x00, 0x01]), ConditionalField( ByteEnumKeysField("opcode_error", 0x00, ms_opcode_error_values), lambda pkt: pkt.iflag in [0x00, 0x01]), ConditionalField(ByteField("opcode_version", 0x01), lambda pkt: pkt.iflag in [0x00, 0x01]), ConditionalField(ByteField("opcode_charset", 0x03), lambda pkt: pkt.iflag in [0x00, 0x01]), ConditionalField( StrField("opcode_value", ""), lambda pkt: pkt.iflag in [0x00, 0x01] and pkt.opcode not in [ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x11, 0x1c, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2f, 0x43, 0x44, 0x45, 0x46, 0x47, 0x4a ]), # Adm OpCode fields ConditionalField( StrFixedLenField("adm_eyecatcher", "AD-EYECATCH\x00", 12), lambda pkt: pkt.iflag == 0x05), ConditionalField(ByteField("adm_version", 0x01), lambda pkt: pkt.iflag == 0x05), ConditionalField( ByteEnumKeysField("adm_type", 0x01, ms_adm_type_values), lambda pkt: pkt.iflag == 0x05), ConditionalField(IntToStrField("adm_recsize", 104, 11), lambda pkt: pkt.iflag == 0x05), ConditionalField(IntToStrField("adm_recno", 1, 11), lambda pkt: pkt.iflag == 0x05), ConditionalField(PacketListField("adm_records", None, SAPMSAdmRecord), lambda pkt: pkt.iflag == 0x05), # Server List fields ConditionalField( PacketListField("clients", None, SAPMSClient1), lambda pkt: pkt. opcode in [0x02, 0x03, 0x04, 0x05] and pkt.opcode_version == 0x01), ConditionalField( PacketListField("clients", None, SAPMSClient2), lambda pkt: pkt. opcode in [0x02, 0x03, 0x04, 0x05] and pkt.opcode_version == 0x02), ConditionalField( PacketListField("clients", None, SAPMSClient3), lambda pkt: pkt. opcode in [0x02, 0x03, 0x04, 0x05] and pkt.opcode_version == 0x03), ConditionalField( PacketListField("clients", None, SAPMSClient4), lambda pkt: pkt. opcode in [0x02, 0x03, 0x04, 0x05] and pkt.opcode_version == 0x04), # Change IP fields ConditionalField(IPField("change_ip_addressv4", "0.0.0.0"), lambda pkt: pkt.opcode == 0x06), ConditionalField( IP6Field("change_ip_addressv6", "::"), lambda pkt: pkt.opcode == 0x06 and pkt.opcode_version == 0x02), # Get/Set Text fields ConditionalField(StrFixedLenField("text_name", "", 40), lambda pkt: pkt.opcode in [0x22, 0x23]), ConditionalField( FieldLenField("text_length", None, length_of="text_value", fmt="!I"), lambda pkt: pkt.opcode in [0x22, 0x23]), ConditionalField( StrFixedLenField("text_value", "", length_from=lambda pkt: pkt.text_length or 80), lambda pkt: pkt.opcode in [0x22, 0x23]), # Counter fields ConditionalField( PacketField("counter", None, SAPMSCounter), lambda pkt: pkt.opcode in [0x24, 0x25, 0x26, 0x27, 0x28, 0x29]), ConditionalField(PacketListField("counters", None, SAPMSCounter), lambda pkt: pkt.opcode in [0x2a]), # Security Key 1 fields ConditionalField(StrFixedLenField("security_name", None, 40), lambda pkt: pkt.opcode in [0x07, 0x08]), ConditionalField(StrFixedLenField("security_key", None, 256), lambda pkt: pkt.opcode in [0x07, 0x08]), # Security Key 2 fields ConditionalField(IPField("security2_addressv4", "0.0.0.0"), lambda pkt: pkt.opcode == 0x09), ConditionalField(ShortField("security2_port", 0), lambda pkt: pkt.opcode == 0x09), ConditionalField(StrFixedLenField("security2_key", None, 256), lambda pkt: pkt.opcode == 0x09), ConditionalField(IP6Field("security2_addressv6", "::"), lambda pkt: pkt.opcode == 0x09), # Hardware ID field ConditionalField(StrNullFixedLenField("hwid", "", length=99), lambda pkt: pkt.opcode == 0x0a), # Statistics ConditionalField(PacketField("stats", None, SAPMSStat3), lambda pkt: pkt.opcode == 0x11 and pkt.flag == 0x03), # Codepage ConditionalField(IntField("codepage", 0), lambda pkt: pkt.opcode == 0x1c and pkt.flag == 0x03), # Dump Info Request fields ConditionalField(ByteField("dump_dest", 0x02), lambda pkt: pkt.opcode == 0x1E and pkt.flag == 0x02), ConditionalField(StrFixedLenField("dump_filler", "\x00\x00\x00", 3), lambda pkt: pkt.opcode == 0x1E and pkt.flag == 0x02), ConditionalField(ShortField("dump_index", 0x00), lambda pkt: pkt.opcode == 0x1E and pkt.flag == 0x02), ConditionalField( ShortEnumKeysField("dump_command", 0x01, ms_dump_command_values), lambda pkt: pkt.opcode == 0x1E and pkt.flag == 0x02), ConditionalField(StrFixedLenField("dump_name", "\x00" * 40, 40), lambda pkt: pkt.opcode == 0x1E and pkt.flag == 0x02), # File Reload fields ConditionalField( ByteEnumKeysField("file_reload", 0, ms_file_reload_values), lambda pkt: pkt.opcode == 0x1f), ConditionalField(StrFixedLenField("file_filler", "\x00\x00\x00", 3), lambda pkt: pkt.opcode == 0x1f), # Get/Set/Del Logon fields ConditionalField(PacketField("logon", None, SAPMSLogon), lambda pkt: pkt.opcode in [0x2b, 0x2c, 0x2d]), # Server Disconnect/Shutdown fields ConditionalField(PacketField("shutdown_client", None, SAPMSClient3), lambda pkt: pkt.opcode in [0x2e, 0x2f, 0x30, 0x4a]), ConditionalField( FieldLenField("shutdown_reason_length", None, length_of="shutdown_reason", fmt="!H"), lambda pkt: pkt.opcode in [0x2e, 0x2f, 0x30, 0x4a]), ConditionalField( StrLenField("shutdown_reason", "", length_from=lambda pkt: pkt.shutdown_reason_length), lambda pkt: pkt.opcode in [0x2e, 0x2f, 0x30, 0x4a]), # Get/Set Property fields ConditionalField(PacketField("property", None, SAPMSProperty), lambda pkt: pkt.opcode in [0x43, 0x44, 0x45]), # IP/Port to name fields ConditionalField( IPField("ip_to_name_address4", "0.0.0.0"), lambda pkt: pkt.opcode == 0x46 and pkt.opcode_version == 0x01), ConditionalField( IP6Field("ip_to_name_address6", "::"), lambda pkt: pkt.opcode == 0x46 and pkt.opcode_version == 0x02), ConditionalField(ShortField("ip_to_name_port", 0), lambda pkt: pkt.opcode == 0x46), ConditionalField( FieldLenField("ip_to_name_length", None, length_of="ip_to_name", fmt="!I"), lambda pkt: pkt.opcode == 0x46), ConditionalField( StrLenField("ip_to_name", "", length_from=lambda pkt: pkt.logonname_length), lambda pkt: pkt.opcode == 0x46), # Check ACL fields ConditionalField(ShortField("error_code", 0), lambda pkt: pkt.opcode == 0x47), ConditionalField(StrFixedLenField("acl", "", 46), lambda pkt: pkt.opcode == 0x47), ]
class ParameterListPacket(EPacket): name = "PID list" fields_desc = [ PacketListField("parameterValues", [], next_cls_cb=get_pid_class), PacketField("sentinel", "", PID_SENTINEL), ]
class SAPDiag(PacketNoPadded): """SAP Diag packet This packet holds the Diag Header and serve as a container for :class:`SAPDiagItem` items. It handles compression/decompression, adding the appropriate Compression Header when necessary. """ name = "SAP Diag" fields_desc = [ ByteField("mode", 0), # Communication flags BitField("com_flag_TERM_GRA", 0, 1), BitField("com_flag_TERM_NNM", 0, 1), BitField("com_flag_TERM_CAS", 0, 1), BitField("com_flag_TERM_INI", 0, 1), BitField("com_flag_TERM_EOP", 0, 1), BitField("com_flag_TERM_NOP", 0, 1), BitField("com_flag_TERM_EOC", 0, 1), BitField("com_flag_TERM_EOS", 0, 1), ByteField("mode_stat", 0), ByteField("err_no", 0), ByteField("msg_type", 0), ByteField("msg_info", 0), ByteField("msg_rc", 0), ByteEnumKeysField("compress", 0, diag_compress_values), # Compression Header ConditionalField(LEIntField("uncompress_length", None), lambda pkt: pkt.compress == 1), ConditionalField( ByteEnumField("algorithm", 0x12, { 0x12: "LZH", 0x10: "LZC" }), lambda pkt: pkt.compress == 1), ConditionalField(StrFixedLenField("magic_bytes", "\x1f\x9d", 2), lambda pkt: pkt.compress == 1), ConditionalField(ByteField("special", 2), lambda pkt: pkt.compress == 1), # SNC Frame ConditionalField(PacketField("snc_frame", None, SAPSNCFrame), lambda pkt: pkt.compress in [2, 3]), # Message info ConditionalField(StrEncodedPaddedField("info", None), lambda pkt: pkt.err_no != 0), # Payload PacketListField("message", None, SAPDiagItem) ] def do_compress(self, s): """Compress a string using SAP compression C++ extension. :param s: string to compress :type s: C{string} :return: string compression header plus the compressed string :rtype: C{string} :raise pysapcompress.Error: when a compression error is raised """ if len(s) > 0: # Compress the payload and return the output (_, _, outbuffer) = pysapcompress.compress(s, pysapcompress.ALG_LZH) return outbuffer def do_decompress(self, s, length): """Decompress a string using SAP compression C++ extension. :param s: compression header plus compressed string :type s: C{string} :param length: reported compressed length :type length: ``int`` :return: decompressed string :rtype: C{string} :raise pysapcompress.Error: when a decompression error is raised """ if len(s) > 0: # Decompress the payload and return the output (_, _, outbuffer) = pysapcompress.decompress(s, length) return outbuffer def pre_dissect(self, s): """Prepares the packet for dissection. If the compression flag is set, decompress the payload. """ # If the compression flag is set, decompress everything after the headers if s[7] == "\x01": # First need to get the reported decompressed length (reported_length, ) = unpack("<I", s[8:12]) # Then return the headers (Diag and Compression) and the payload (message field) try: return s[:16] + self.do_decompress(s[8:], reported_length) except DecompressError: return s # Uncompressed packet, just return them return s def post_build(self, p, pay): """Compress the payload. If the compression flag is set, compress both the message field and the payload. """ if pay is None: pay = '' if self.compress == 1: payload = "".join([str(item) for item in self.message]) + pay if len(payload) > 0: try: return p[:8] + self.do_compress(payload) except CompressError: return p + pay return p + pay def get_item(self, item_type=None, item_id=None, item_sid=None): """Get an item from the packet's message. Returns None if the message is not found, or a list if the item is found multiple times. :param item_type: item type byte or string value :type item_type: ``int`` or C{string} or ``list`` :param item_id: item ID byte or string value :type item_id: ``int`` or C{string} or ``list`` :param item_sid: item SID byte or string value :type item_sid: ``int`` or C{string} or ``list`` :return: list of items found on the packet or None :rtype: ``list`` of :class:`SAPDiagItem` """ # Expand list lookups items = [] if item_type is not None and type(item_type) == list: for itype in item_type: items.extend(self.get_item(itype, item_id, item_sid)) return items if item_id is not None and type(item_id) == list: for iid in item_id: items.extend(self.get_item(item_type, iid, item_sid)) return items if item_sid is not None and type(item_sid) == list: for isid in item_sid: items.extend(self.get_item(item_type, item_id, isid)) return items # Perform name lookups if item_type is not None and isinstance(item_type, str): item_type = list(diag_item_types.keys())[list( diag_item_types.values()).index(item_type)] if item_id is not None and isinstance(item_id, str): item_id = list(diag_appl_ids.keys())[list( diag_appl_ids.values()).index(item_id)] if item_sid is not None and isinstance(item_sid, str): item_sid = list(diag_appl_sids[item_id].keys())[list( diag_appl_sids[item_id].values()).index(item_sid)] # Filter and return items if item_sid is None and item_id is None: items = [ item for item in self.message if hasattr(item, "item_type") and item.item_type == item_type ] elif item_sid is None: items = [ item for item in self.message if hasattr(item, "item_type") and item.item_type == item_type and item.item_id == item_id ] else: items = [ item for item in self.message if hasattr(item, "item_type") and item.item_type == item_type and item.item_id == item_id and item.item_sid == item_sid ] return items
class GTPV2Command(Packet): fields_desc = [PacketListField("IE_list", None, IE_Dispatcher)]
class GTPSupportedExtensionHeadersNotification(Packet): name = "GTP Supported Extension Headers Notification" fields_desc = [PacketListField("IE_list", [IE_ExtensionHeaderList(), ], IE_Dispatcher)]
class MACCommand_up(Packet): name = "MACCommand_up" fields_desc = [ ByteEnumField("CID", 0, CIDs_up), ConditionalField( PacketListField("Reset", b"", ResetInd, length_from=lambda pkt: 1), lambda pkt: (pkt.CID == 0x01)), ConditionalField( PacketListField("LinkCheck", b"", LinkCheckReq, length_from=lambda pkt: 0), lambda pkt: (pkt.CID == 0x02)), ConditionalField( PacketListField("LinkADR", b"", LinkADRReq, length_from=lambda pkt: 4), lambda pkt: (pkt.CID == 0x03)), ConditionalField( PacketListField("DutyCycle", b"", DutyCycleReq, length_from=lambda pkt: 4), lambda pkt: (pkt.CID == 0x04)), ConditionalField( PacketListField("RXParamSetup", b"", RXParamSetupReq, length_from=lambda pkt: 4), lambda pkt: (pkt.CID == 0x05)), ConditionalField( PacketListField("DevStatus", b"", DevStatusReq, length_from=lambda pkt: 2), lambda pkt: (pkt.CID == 0x06)), ConditionalField( PacketListField("NewChannel", b"", NewChannelReq, length_from=lambda pkt: 5), lambda pkt: (pkt.CID == 0x07)), ConditionalField( PacketListField("RXTimingSetup", b"", RXTimingSetupReq, length_from=lambda pkt: 1), lambda pkt: (pkt.CID == 0x08)), # specific to 1.1 from here ConditionalField( PacketListField("TxParamSetup", b"", TxParamSetupReq, length_from=lambda pkt: 1), lambda pkt: (pkt.CID == 0x09)), ConditionalField( PacketListField("DlChannel", b"", DlChannelReq, length_from=lambda pkt: 4), lambda pkt: (pkt.CID == 0x0A)), ConditionalField( PacketListField("Rekey", b"", RekeyInd, length_from=lambda pkt: 1), lambda pkt: (pkt.CID == 0x0B)), ConditionalField( PacketListField("ADRParamSetup", b"", ADRParamSetupReq, length_from=lambda pkt: 1), lambda pkt: (pkt.CID == 0x0C)), ConditionalField( PacketListField("DeviceTime", b"", DeviceTimeReq, length_from=lambda pkt: 0), lambda pkt: (pkt.CID == 0x0D)), ConditionalField( PacketListField("ForceRejoin", b"", ForceRejoinReq, length_from=lambda pkt: 2), lambda pkt: (pkt.CID == 0x0E)), ConditionalField( PacketListField("RejoinParamSetup", b"", RejoinParamSetupReq, length_from=lambda pkt: 1), lambda pkt: (pkt.CID == 0x0F)) ] # pylint: disable=R0201 def extract_padding(self, p): return "", p
class ISIS_AreaTlv(ISIS_GenericTlv): name = "ISIS Area TLV" fields_desc = [ByteEnumField("type", 1, _isis_tlv_names), FieldLenField("len", None, length_of="areas", fmt="B"), PacketListField("areas", [], ISIS_AreaEntry, length_from=lambda x: x.len)] # noqa: E501
class SAPEnqueue(PacketNoPadded): """SAP Enqueue Server packet This packet is used for general Enqueue packets. """ name = "SAP Enqueue" fields_desc = [ StrFixedLenField("magic_bytes", "\xab\xcd\xe1\x23", 4), IntField("id", 0), LenField("len", None, fmt="!I"), LenField("len_frag", None, fmt="!I"), ByteEnumKeysField("dest", 0x00, enqueue_dest_values), ByteEnumKeysField("opcode", 0x00, enqueue_conn_admin_opcode_values), ByteField("more_frags", 0), ByteEnumKeysField("type", 0x00, enqueue_type_values), # Server Admin fields ConditionalField(StrNullFixedLenField("adm_eyecatcher1", "ENC", 3), lambda pkt: pkt.dest == 3), ConditionalField(ByteField("adm_version", 1), lambda pkt: pkt.dest == 3), ConditionalField(ByteField("adm_padd1", 0), lambda pkt: pkt.dest == 3), ConditionalField(ByteField("adm_padd2", 0), lambda pkt: pkt.dest == 3), ConditionalField(ByteField("adm_padd3", 0), lambda pkt: pkt.dest == 3), ConditionalField(StrFixedLenField("adm_eyecatcher2", "#EAA", 4), lambda pkt: pkt.dest == 3), ConditionalField(ByteField("adm_1", 1), lambda pkt: pkt.dest == 3), ConditionalField(IntField("adm_len", 0), lambda pkt: pkt.dest == 3), ConditionalField( ByteEnumKeysField("adm_opcode", 0, enqueue_server_admin_opcode_values), lambda pkt: pkt.dest == 3), ConditionalField(ByteField("adm_flags", 0), lambda pkt: pkt.dest == 3), ConditionalField(IntField("adm_rc", 0), lambda pkt: pkt.dest == 3), ConditionalField(StrFixedLenField("adm_eyecatcher3", "#EAE", 4), lambda pkt: pkt.dest == 3), # Server Admin Trace fields ConditionalField( ByteField("adm_trace_protocol_version", 1), lambda pkt: pkt.dest == 3 and pkt.adm_opcode in [0x06]), ConditionalField( ByteEnumKeysField("adm_trace_action", 3, enqueue_server_admin_trace_action_values), lambda pkt: pkt.dest == 3 and pkt.adm_opcode in [0x06]), ConditionalField( ByteEnumKeysField("adm_trace_limit", 0, enqueue_server_admin_trace_limit_values), lambda pkt: pkt.dest == 3 and pkt.adm_opcode in [0x06]), ConditionalField( ByteEnumKeysField("adm_trace_thread", 0, enqueue_server_admin_trace_thread_values), lambda pkt: pkt.dest == 3 and pkt.adm_opcode in [0x06]), ConditionalField( IntField("adm_trace_unknown1", 0), lambda pkt: pkt.dest == 3 and pkt.adm_opcode in [0x06]), ConditionalField( IntField("adm_trace_level", 1), lambda pkt: pkt.dest == 3 and pkt.adm_opcode in [0x06]), ConditionalField( IntField("adm_trace_level1", 1), lambda pkt: pkt.dest == 3 and pkt.adm_opcode in [0x06]), ConditionalField( ByteField("adm_trace_logging", 0), lambda pkt: pkt.dest == 3 and pkt.adm_opcode in [0x06]), ConditionalField( IntField("adm_trace_max_file_size", 20 * 1024 * 1024), lambda pkt: pkt.dest == 3 and pkt.adm_opcode in [0x06]), ConditionalField( FieldLenField("adm_trace_nopatterns", 0, count_of="adm_trace_patterns", fmt="!I"), lambda pkt: pkt.dest == 3 and pkt.adm_opcode in [0x06]), ConditionalField( FieldLenField("adm_trace_nopatterns1", 0, count_of="adm_trace_patterns", fmt="!I"), lambda pkt: pkt.dest == 3 and pkt.adm_opcode in [0x06]), ConditionalField( IntField("adm_trace_unknown3", 37), lambda pkt: pkt.dest == 3 and pkt.adm_opcode in [0x06]), ConditionalField( StrFixedLenField("adm_trace_eyecatcher4", "#EAH", 4), lambda pkt: pkt.dest == 3 and pkt.adm_opcode in [0x06]), ConditionalField( PacketListField("adm_trace_patterns", None, SAPEnqueueTracePattern, count_from=lambda pkt: pkt.adm_trace_nopatterns), lambda pkt: pkt.dest == 3 and pkt.adm_opcode in [0x06]), ConditionalField( StrFixedLenField("adm_trace_eyecatcher5", "#EAD", 4), lambda pkt: pkt.dest == 3 and pkt.adm_opcode in [0x06]), # Connection Admin fields ConditionalField( FieldLenField("params_count", None, count_of="params", fmt="!I"), lambda pkt: pkt.dest == 6 and pkt.opcode in [1, 2]), ConditionalField( PacketListField("params", None, SAPEnqueueParam, count_from=lambda pkt: pkt.params_count), lambda pkt: pkt.dest == 6 and pkt.opcode in [1, 2]), ] def post_build(self, pkt, pay): """Adjust the len and len_frags fields after the build of the whole packet. """ l = struct.pack("!I", len(pkt) + len(pay)) pkt = pkt[:8] + l + l + pkt[16:] return pkt + pay
class ISIS_ExtendedIsReachabilityTlv(ISIS_GenericTlv): name = "ISIS Extended IS Reachability TLV" fields_desc = [ByteEnumField("type", 22, _isis_tlv_names), FieldLenField("len", None, length_of="neighbours", fmt="B"), PacketListField("neighbours", [], ISIS_ExtendedIsNeighbourEntry, length_from=lambda x: x.len)] # noqa: E501
class GTPDeletePDPContextResponse(Packet): # 3GPP TS 29.060 V9.1.0 (2009-12) name = "GTP Delete PDP Context Response" fields_desc = [PacketListField("IE_list", [], IE_Dispatcher)]
class ISIS_Ipv6ReachabilityTlv(ISIS_GenericTlv): name = "ISIS IPv6 Reachability TLV" fields_desc = [ByteEnumField("type", 236, _isis_tlv_names), FieldLenField("len", None, length_of="pfxs", fmt="B"), PacketListField("pfxs", [], ISIS_Ipv6Prefix, length_from=lambda pkt: pkt.len)] # noqa: E501
class RadioTap(Packet): name = "RadioTap dummy" fields_desc = [ ByteField('version', 0), ByteField('pad', 0), LEShortField('len', None), FlagsField('present', None, -32, _rt_present), # noqa: E501 # Extended presence mask ConditionalField( PacketListField("Ext", [], next_cls_cb=_next_radiotap_extpm), lambda pkt: pkt.present and pkt.present.Ext), # noqa: E501 # RadioTap fields - each starts with a _RadiotapReversePadField # to handle padding # TSFT ConditionalField( _RadiotapReversePadField(LELongField("mac_timestamp", 0)), lambda pkt: pkt.present and pkt.present.TSFT), # Flags ConditionalField( _RadiotapReversePadField(FlagsField("Flags", None, -8, _rt_flags)), lambda pkt: pkt.present and pkt.present.Flags), # Rate ConditionalField(_RadiotapReversePadField(ByteField("Rate", 0)), lambda pkt: pkt.present and pkt.present.Rate), # Channel ConditionalField(_RadiotapReversePadField(LEShortField("Channel", 0)), lambda pkt: pkt.present and pkt.present.Channel), ConditionalField( FlagsField("ChannelFlags", None, -16, _rt_channelflags), lambda pkt: pkt.present and pkt.present.Channel), # dBm_AntSignal ConditionalField( _RadiotapReversePadField(_dbmField("dBm_AntSignal", -256)), lambda pkt: pkt.present and pkt.present.dBm_AntSignal), # dBm_AntNoise ConditionalField( _RadiotapReversePadField(_dbmField("dBm_AntNoise", -256)), lambda pkt: pkt.present and pkt.present.dBm_AntNoise), # Lock_Quality ConditionalField( _RadiotapReversePadField(LEShortField("Lock_Quality", 0), ), lambda pkt: pkt.present and pkt.present.Lock_Quality), # Antenna ConditionalField(_RadiotapReversePadField(ByteField("Antenna", 0)), lambda pkt: pkt.present and pkt.present.Antenna), # RX Flags ConditionalField( _RadiotapReversePadField( FlagsField("RXFlags", None, -16, _rt_rxflags)), lambda pkt: pkt.present and pkt.present.RXFlags), # TX Flags ConditionalField( _RadiotapReversePadField( FlagsField("TXFlags", None, -16, _rt_txflags)), lambda pkt: pkt.present and pkt.present.TXFlags), # ChannelPlus ConditionalField( _RadiotapReversePadField( FlagsField("ChannelFlags2", None, -32, _rt_channelflags2)), lambda pkt: pkt.present and pkt.present.ChannelPlus), ConditionalField(LEShortField("ChannelFrequency", 0), lambda pkt: pkt.present and pkt.present.ChannelPlus), ConditionalField(ByteField("ChannelNumber", 0), lambda pkt: pkt.present and pkt.present.ChannelPlus), # MCS ConditionalField( _RadiotapReversePadField( FlagsField("knownMCS", None, -8, _rt_knownmcs)), lambda pkt: pkt.present and pkt.present.MCS), ConditionalField(BitField("Ness_LSB", 0, 1), lambda pkt: pkt.present and pkt.present.MCS), ConditionalField(BitField("STBC_streams", 0, 2), lambda pkt: pkt.present and pkt.present.MCS), ConditionalField(BitEnumField("FEC_type", 0, 1, { 0: "BCC", 1: "LDPC" }), lambda pkt: pkt.present and pkt.present.MCS), ConditionalField( BitEnumField("HT_format", 0, 1, { 0: "mixed", 1: "greenfield" }), lambda pkt: pkt.present and pkt.present.MCS), ConditionalField( BitEnumField("guard_interval", 0, 1, { 0: "Long_GI", 1: "Short_GI" }), # noqa: E501 lambda pkt: pkt.present and pkt.present.MCS), ConditionalField(BitEnumField("MCS_bandwidth", 0, 2, _rt_bandwidth), lambda pkt: pkt.present and pkt.present.MCS), ConditionalField(ByteField("MCS_index", 0), lambda pkt: pkt.present and pkt.present.MCS), # A_MPDU ConditionalField(_RadiotapReversePadField(LEIntField("A_MPDU_ref", 0)), lambda pkt: pkt.present and pkt.present.A_MPDU), ConditionalField( FlagsField("A_MPDU_flags", None, -32, _rt_a_mpdu_flags), lambda pkt: pkt.present and pkt.present.A_MPDU), # VHT ConditionalField( _RadiotapReversePadField( FlagsField("KnownVHT", None, -16, _rt_knownvht)), lambda pkt: pkt.present and pkt.present.VHT), ConditionalField(FlagsField("PresentVHT", None, -8, _rt_presentvht), lambda pkt: pkt.present and pkt.present.VHT), ConditionalField(ByteEnumField("VHT_bandwidth", 0, _rt_vhtbandwidth), lambda pkt: pkt.present and pkt.present.VHT), ConditionalField(StrFixedLenField("mcs_nss", 0, length=5), lambda pkt: pkt.present and pkt.present.VHT), ConditionalField(ByteField("GroupID", 0), lambda pkt: pkt.present and pkt.present.VHT), ConditionalField(ShortField("PartialAID", 0), lambda pkt: pkt.present and pkt.present.VHT), # timestamp ConditionalField(_RadiotapReversePadField(LELongField("timestamp", 0)), lambda pkt: pkt.present and pkt.present.timestamp), ConditionalField(LEShortField("ts_accuracy", 0), lambda pkt: pkt.present and pkt.present.timestamp), ConditionalField(ByteField("ts_position", 0), lambda pkt: pkt.present and pkt.present.timestamp), ConditionalField(ByteField("ts_flags", 0), lambda pkt: pkt.present and pkt.present.timestamp), # HE - XXX not complete ConditionalField(_RadiotapReversePadField(ShortField("he_data1", 0)), lambda pkt: pkt.present and pkt.present.HE), ConditionalField(ShortField("he_data2", 0), lambda pkt: pkt.present and pkt.present.HE), ConditionalField(ShortField("he_data3", 0), lambda pkt: pkt.present and pkt.present.HE), ConditionalField(ShortField("he_data4", 0), lambda pkt: pkt.present and pkt.present.HE), ConditionalField(ShortField("he_data5", 0), lambda pkt: pkt.present and pkt.present.HE), ConditionalField(ShortField("he_data6", 0), lambda pkt: pkt.present and pkt.present.HE), # HE_MU ConditionalField( _RadiotapReversePadField(LEShortField("hemu_flags1", 0)), lambda pkt: pkt.present and pkt.present.HE_MU), ConditionalField(LEShortField("hemu_flags2", 0), lambda pkt: pkt.present and pkt.present.HE_MU), ConditionalField( FieldListField("RU_channel1", [], ByteField, count_from=lambda x: 4), lambda pkt: pkt.present and pkt.present.HE_MU), ConditionalField( FieldListField("RU_channel2", [], ByteField, count_from=lambda x: 4), lambda pkt: pkt.present and pkt.present.HE_MU), # HE_MU_other_user ConditionalField( _RadiotapReversePadField(LEShortField("hemuou_per_user_1", 0x7fff)), lambda pkt: pkt.present and pkt.present.HE_MU_other_user), ConditionalField( LEShortField("hemuou_per_user_2", 0x003f), lambda pkt: pkt.present and pkt.present.HE_MU_other_user), ConditionalField( ByteField("hemuou_per_user_position", 0), lambda pkt: pkt.present and pkt.present.HE_MU_other_user), ConditionalField( FlagsField("hemuou_per_user_known", 0, -16, _rt_hemuother_per_user_known), lambda pkt: pkt.present and pkt.present.HE_MU_other_user), # L_SIG ConditionalField( _RadiotapReversePadField( FlagsField("lsig_data1", 0, -16, ["rate", "length"])), lambda pkt: pkt.present and pkt.present.L_SIG), ConditionalField(BitField("lsig_length", 0, 12), lambda pkt: pkt.present and pkt.present.L_SIG), ConditionalField(BitField("lsig_rate", 0, 4), lambda pkt: pkt.present and pkt.present.L_SIG), # Remaining StrLenField( 'notdecoded', "", length_from=lambda pkt: max(pkt.len - pkt._tmp_dissect_pos, 0)) ] def guess_payload_class(self, payload): if self.present and self.present.Flags and self.Flags.FCS: return Dot11FCS return Dot11 def post_build(self, p, pay): if self.len is None: p = p[:2] + struct.pack("!H", len(p))[::-1] + p[4:] return p + pay
class CDPv2_HDR(_CDPChecksum, CDPMsgGeneric): name = "Cisco Discovery Protocol version 2" fields_desc = [ByteField("vers", 2), ByteField("ttl", 180), XShortField("cksum", None), PacketListField("msg", [], _CDPGuessPayloadClass)]
class SAPDiagMenuEntries(Packet): name = "SAP Diag Menu Entries" fields_desc = [PacketListField("entries", None, SAPDiagMenuEntry)]
class LoWPAN_NHC(Packet): name = "LOWPAN_NHC" fields_desc = [ PacketListField( "exts", [], pkt_cls=LoWPAN_NHC_Hdr, next_cls_cb=lambda *s: LoWPAN_NHC_Hdr.get_next_cls(s[3]) ) ] def post_dissect(self, data): if not self.underlayer or not hasattr(self.underlayer, "_ipv6"): return data if self.guess_payload_class(data) != IPv6: return data # Underlayer is LoWPAN_IPHC packet = self.underlayer._ipv6 try: ipv6_hdr = next( x for x in self.exts if isinstance(x, LoWPAN_NHC_IPv6Ext) ) except StopIteration: ipv6_hdr = None if ipv6_hdr: # XXX todo: implement: append the IPv6 extension # packet = packet / ipv6extension pass try: udp_hdr = next( x for x in self.exts if isinstance(x, LoWPAN_NHC_UDP) ) except StopIteration: udp_hdr = None if udp_hdr: packet.nh = 0x11 # UDP udp = UDP() # https://tools.ietf.org/html/rfc6282#section-4.3.3 if udp_hdr.C == 0: udp.chksum = udp_hdr.udpChecksum if udp_hdr.P == 0: udp.sport = udp_hdr.udpSourcePort udp.dport = udp_hdr.udpDestPort elif udp_hdr.P == 1: udp.sport = udp_hdr.udpSourcePort udp.dport = 0xF000 + udp_hdr.udpDestPort elif udp_hdr.P == 2: udp.sport = 0xF000 + udp_hdr.udpSourcePort udp.dport = udp_hdr.udpDestPort elif udp_hdr.P == 3: udp.sport = 0xF0B0 + udp_hdr.udpSourcePort udp.dport = 0xF0B0 + udp_hdr.udpDestPort packet.lastlayer().add_payload(udp / data) else: packet.lastlayer().add_payload(data) data = raw(packet) return Packet.post_dissect(self, data) def do_build(self): if not isinstance(self.payload, IPv6): return Packet.do_build(self) pay = self.payload.payload while pay and isinstance(pay.payload, _IPv6ExtHdr): # XXX todo: populate a LoWPAN_NHC_IPv6Ext pay = pay.payload if isinstance(pay, UDP): try: udp_hdr = next( x for x in self.exts if isinstance(x, LoWPAN_NHC_UDP) ) except StopIteration: udp_hdr = LoWPAN_NHC_UDP() # Guess best compression if pay.sport >> 4 == 0xf0b and pay.dport >> 4 == 0xf0b: udp_hdr.P = 3 elif pay.sport >> 8 == 0xf0: udp_hdr.P = 2 elif pay.dport >> 8 == 0xf0: udp_hdr.P = 1 self.exts.insert(0, udp_hdr) # https://tools.ietf.org/html/rfc6282#section-4.3.3 if udp_hdr.P == 0: udp_hdr.udpSourcePort = pay.sport udp_hdr.udpDestPort = pay.dport elif udp_hdr.P == 1: udp_hdr.udpSourcePort = pay.sport udp_hdr.udpDestPort = pay.dport & 255 elif udp_hdr.P == 2: udp_hdr.udpSourcePort = pay.sport & 255 udp_hdr.udpDestPort = pay.dport elif udp_hdr.P == 3: udp_hdr.udpSourcePort = pay.sport & 15 udp_hdr.udpDestPort = pay.dport & 15 if udp_hdr.C == 0: if pay.chksum: udp_hdr.udpChecksum = pay.chksum else: udp_hdr.udpChecksum = UDP(raw(pay)).chksum return Packet.do_build(self) def do_build_payload(self): # Elide IPv6 payload, extensions and UDP if isinstance(self.payload, IPv6): cur = self.payload while cur and isinstance(cur, (IPv6, UDP)): cur = cur.payload return raw(cur) return Packet.do_build_payload(self) def guess_payload_class(self, payload): if self.underlayer: u = self.underlayer.underlayer if isinstance(u, (LoWPANFragmentationFirst, LoWPANFragmentationSubsequent)): return Raw return IPv6
class SDESChunk(Packet): name = "SDES chunk" fields_desc = [ IntField('sourcesync', None), PacketListField('items', None, pkt_cls=SDESItem) ]
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 PNIORealTimeCyclicPDU(Packet): """ PROFINET cyclic real-time """ __slots__ = ["_len", "_layout"] name = "PROFINET Real-Time" fields_desc = [ # C_SDU ^ CSF_SDU -- IEC-61158-6-10/FDIS ED 3, Table 163 PacketListField("data", [], next_cls_cb=lambda pkt, lst, p, remain: pkt. next_cls_cb(lst, p, remain)), # RTCPadding -- IEC - 61158 - 6 - 10 / FDIS ED 3, Table 163 StrFixedLenField("padding", '', length_from=lambda p: p.get_padding_length()), # APDU_Status -- IEC-61158-6-10/FDIS ED 3, Table 164 ShortField("cycleCounter", 0), FlagsField("dataStatus", 0x35, 8, [ "primary", "redundancy", "validData", "reserved_1", "run", "no_problem", "reserved_2", "ignore", ]), ByteField("transferStatus", 0) ] def pre_dissect(self, s): # Constraint from IEC-61158-6-10/FDIS ED 3, line 690 self._len = min(1440, len(s)) return s def get_padding_length(self): if hasattr(self, "_len"): pad_len = ( self._len - sum(len(raw(pkt)) for pkt in self.getfieldval("data")) - 2 - # Cycle Counter size (ShortField) 1 - # DataStatus size (FlagsField over 8 bits) 1 # TransferStatus (ByteField) ) else: pad_len = len(self.getfieldval("padding")) # Constraints from IEC-61158-6-10/FDIS ED 3, Table 163 assert (0 <= pad_len <= 40) q = self while not isinstance(q, UDP) and hasattr(q, "underlayer"): q = q.underlayer if isinstance(q, UDP): assert (0 <= pad_len <= 12) return pad_len def next_cls_cb(self, _lst, _p, _remain): if hasattr(self, "_layout") and isinstance(self._layout, list): try: return self._layout.pop(0) except IndexError: self._layout = None return None ether_layer = None q = self while not isinstance(q, Ether) and hasattr(q, "underlayer"): q = q.underlayer if isinstance(q, Ether): ether_layer = q pnio_layer = None q = self while not isinstance(q, ProfinetIO) and hasattr(q, "underlayer"): q = q.underlayer if isinstance(q, ProfinetIO): pnio_layer = q self._layout = [PNIORealTimeCyclicDefaultRawData] if (not isinstance(ether_layer, type(None)) and not isinstance(pnio_layer, type(None))): # Get from config the layout for these hosts and frameid layout = type(self).get_layout_from_config(ether_layer.src, ether_layer.dst, pnio_layer.frameID) if not isinstance(layout, type(None)): self._layout = layout return self._layout.pop(0) @staticmethod def get_layout_from_config(ether_src, ether_dst, frame_id): try: return copy.deepcopy(conf.contribs["PNIO_RTC"][(ether_src, ether_dst, frame_id)]) except KeyError: return None @staticmethod def build_fixed_len_raw_type(length): return type( "FixedLenRawPacketLen{}".format(length), (conf.raw_layer, ), { "name": "FixedLenRawPacketLen{}".format(length), "fields_desc": [StrFixedLenField("data", '', length=length)], "get_data_length": lambda _: length, "guess_payload_class": lambda self, p: conf.padding_layer, })
class SAPRouter(Packet): """SAP Router packet This packet is used for general SAP Router packets. There are (at least) five types of SAP Router packets: 1. Route packets. For requesting the routing of a connection to a remote hosts. The packet contains some general information and a connection string with a list of routing hops (:class:`SAPRouterRouteHop`). 2. Administration packets. This packet is used for the SAP Router to send administrative commands. It's suppose to be used only from the hosts running the SAP Router or when an specific route is included in the routing table. Generally administration packets are not accepted from the external binding. 3. Error Information packets. Packets sent when an error occurred. 4. Control Message packets. Used to perform some control activities, like retrieving the current SAPRouter version or to perform the SNC handshake. They have the same structure that error information packets. 5. Route accepted packet. Used to acknowledge a route request ("NI_PONG"). Routed packets and some responses doesn't fill in these five packet types. For identifying those cases, you should check the type using the function :class:`router_is_known_type`. NI Versions found (unconfirmed): - 30: Release 40C - 36: Release <6.20 - 38: Release 7.00/7.10 - 39: Release 7.11 - 40: Release 7.20/7.21 """ # Default router version to use SAPROUTER_DEFAULT_VERSION = 40 # Constants for router types SAPROUTER_ROUTE = "NI_ROUTE" """ :cvar: Constant for route packets :type: C{string} """ SAPROUTER_ADMIN = "ROUTER_ADM" """ :cvar: Constant for administration packets :type: C{string} """ SAPROUTER_ERROR = "NI_RTERR" """ :cvar: Constant for error information packets :type: C{string} """ SAPROUTER_CONTROL = "NI_RTERR" """ :cvar: Constant for control messages packets :type: C{string} """ SAPROUTER_PONG = "NI_PONG" """ :cvar: Constant for route accepted packets :type: C{string} """ router_type_values = [ SAPROUTER_ADMIN, SAPROUTER_ERROR, SAPROUTER_CONTROL, SAPROUTER_ROUTE, SAPROUTER_PONG, ] """ :cvar: List of known packet types :type: ``list`` of C{string} """ name = "SAP Router" fields_desc = [ # General fields present in all SAP Router packets StrNullField("type", SAPROUTER_ROUTE), ConditionalField( ByteField("version", 2), lambda pkt: router_is_known_type(pkt) and not router_is_pong(pkt)), # Route packets ConditionalField( ByteField("route_ni_version", SAPROUTER_DEFAULT_VERSION), router_is_route), ConditionalField(ByteField("route_entries", 0), router_is_route), ConditionalField( ByteEnumKeysField("route_talk_mode", 0, router_ni_talk_mode_values), router_is_route), ConditionalField(ShortField("route_padd", 0), router_is_route), ConditionalField(ByteField("route_rest_nodes", 0), router_is_route), ConditionalField( FieldLenField("route_length", 0, length_of="route_string", fmt="I"), router_is_route), ConditionalField(IntField("route_offset", 0), router_is_route), ConditionalField( PacketListField("route_string", None, SAPRouterRouteHop, length_from=lambda pkt: pkt.route_length), router_is_route), # Admin packets ConditionalField( ByteEnumKeysField("adm_command", 0x02, router_adm_commands), router_is_admin), ConditionalField( ShortField("adm_unused", 0x00), lambda pkt: router_is_admin(pkt) and pkt.adm_command not in [10, 11, 12, 13]), # Info Request fields ConditionalField( StrNullFixedLenField("adm_password", "", 19), lambda pkt: router_is_admin(pkt) and pkt.adm_command in [2]), # Cancel Route fields ConditionalField( FieldLenField("adm_client_count", None, count_of="adm_client_ids", fmt="H"), lambda pkt: router_is_admin(pkt) and pkt.adm_command in [6]), # Trace Connection fields ConditionalField( FieldLenField("adm_client_count", None, count_of="adm_client_ids", fmt="I"), lambda pkt: router_is_admin(pkt) and pkt.adm_command in [12, 13]), # Cancel Route or Trace Connection fields ConditionalField( FieldListField("adm_client_ids", [0x00], IntField("", 0), count_from=lambda pkt: pkt.adm_client_count), lambda pkt: router_is_admin(pkt) and pkt.adm_command in [6, 12, 13]), # Set/Clear Peer Trace fields # TODO: Check whether this field should be a IPv6 address or another proper field ConditionalField( StrFixedLenField("adm_address_mask", "", 32), lambda pkt: router_is_admin(pkt) and pkt.adm_command in [10, 11]), # Error Information/Control Messages fields ConditionalField( ByteEnumKeysField("opcode", 0, router_control_opcodes), lambda pkt: router_is_error(pkt) or router_is_control(pkt)), ConditionalField( ByteField("opcode_padd", 0), lambda pkt: router_is_error(pkt) or router_is_control(pkt)), ConditionalField( SignedIntEnumField("return_code", 0, router_return_codes), lambda pkt: router_is_error(pkt) or router_is_control(pkt)), # Error Information fields ConditionalField( FieldLenField("err_text_length", None, length_of="err_text_value", fmt="!I"), lambda pkt: router_is_error(pkt) and pkt.opcode == 0), ConditionalField( PacketField("err_text_value", SAPRouterError(), SAPRouterError), lambda pkt: router_is_error(pkt) and pkt.opcode == 0 and pkt.err_text_length > 0), ConditionalField(IntField("err_text_unknown", 0), lambda pkt: router_is_error(pkt) and pkt.opcode == 0), # Control Message fields ConditionalField( IntField("control_text_length", 0), lambda pkt: router_is_control(pkt) and pkt.opcode != 0), ConditionalField( StrField("control_text_value", "*ERR"), lambda pkt: router_is_control(pkt) and pkt.opcode != 0), # SNC Frame fields ConditionalField( PacketField("snc_frame", None, SAPSNCFrame), lambda pkt: router_is_control(pkt) and pkt.opcode in [70, 71]) ]