Пример #1
0
class UDS_IOCBIPR(Packet):
    name = 'InputOutputControlByIdentifierPositiveResponse'
    fields_desc = [
        XShortField('dataIdentifier', 0),
        StrField('controlStatusRecord', 0, fmt="B")
    ]

    def answers(self, other):
        return other.__class__ == UDS_IOCBI \
            and other.dataIdentifier == self.dataIdentifier

    @staticmethod
    def get_log(pkt):
        return pkt.sprintf("%UDS.service%"), pkt.dataIdentifier
Пример #2
0
class UDS_RDBPI(Packet):
    transmissionModes = {
        0: 'ISOSAEReserved',
        1: 'sendAtSlowRate',
        2: 'sendAtMediumRate',
        3: 'sendAtFastRate',
        4: 'stopSending'
    }
    name = 'ReadDataByPeriodicIdentifier'
    fields_desc = [
        ByteEnumField('transmissionMode', 0, transmissionModes),
        ByteField('periodicDataIdentifier', 0),
        StrField('furtherPeriodicDataIdentifier', 0, fmt="B")
    ]
Пример #3
0
class UDS_RUPR(Packet):
    name = 'RequestUploadPositiveResponse'
    fields_desc = [
        BitField('memorySizeLen', 0, 4),
        BitField('reserved', 0, 4),
        StrField('maxNumberOfBlockLength', 0, fmt="B"),
    ]

    def answers(self, other):
        return other.__class__ == UDS_RU

    @staticmethod
    def get_log(pkt):
        return pkt.sprintf("%UDS.service%"), pkt.memorySizeLen
Пример #4
0
class UDS_TDPR(Packet):
    name = 'TransferDataPositiveResponse'
    fields_desc = [
        ByteField('blockSequenceCounter', 0),
        StrField('transferResponseParameterRecord', 0, fmt="B")
    ]

    def answers(self, other):
        return other.__class__ == UDS_TD \
            and other.blockSequenceCounter == self.blockSequenceCounter

    @staticmethod
    def get_log(pkt):
        return pkt.sprintf("%UDS.service%"), pkt.blockSequenceCounter
Пример #5
0
 def __init__(self, tblfld):
     assert isinstance(tblfld, PacketField)
     assert hasattr(
         tblfld.cls,
         'index'), 'No index() method defined for OmciTableField row object'
     assert hasattr(
         tblfld.cls, 'is_delete'
     ), 'No delete() method defined for OmciTableField row object'
     super(OmciTableField,
           self).__init__([(IntField('table_length', 0),
                            (self.cond_pkt, self.cond_pkt_val)),
                           (PadField(StrField('me_type_table', None),
                                     OmciTableField.PDU_SIZE),
                            (self.cond_pkt2, self.cond_pkt_val2))], tblfld)
Пример #6
0
class UDS_RDTCIPR(Packet):
    name = 'ReadDTCInformationPositiveResponse'
    fields_desc = [
        ByteEnumField('reportType', 0, UDS_RDTCI.reportTypes),
        ConditionalField(XByteField('DTCStatusAvailabilityMask', 0),
                         lambda pkt: pkt.reportType in [0x01, 0x07, 0x11,
                                                        0x12, 0x02, 0x0A,
                                                        0x0B, 0x0C, 0x0D,
                                                        0x0E, 0x0F, 0x13,
                                                        0x15]),
        ConditionalField(ByteEnumField('DTCFormatIdentifier', 0,
                                       {0: 'ISO15031-6DTCFormat',
                                        1: 'UDS-1DTCFormat',
                                        2: 'SAEJ1939-73DTCFormat',
                                        3: 'ISO11992-4DTCFormat'}),
                         lambda pkt: pkt.reportType in [0x01, 0x07,
                                                        0x11, 0x12]),
        ConditionalField(ShortField('DTCCount', 0),
                         lambda pkt: pkt.reportType in [0x01, 0x07,
                                                        0x11, 0x12]),
        ConditionalField(StrField('DTCAndStatusRecord', 0),
                         lambda pkt: pkt.reportType in [0x02, 0x0A, 0x0B,
                                                        0x0C, 0x0D, 0x0E,
                                                        0x0F, 0x13, 0x15]),
        ConditionalField(StrField('dataRecord', 0),
                         lambda pkt: pkt.reportType in [0x03, 0x04, 0x05,
                                                        0x06, 0x08, 0x09,
                                                        0x10, 0x14])
    ]

    def answers(self, other):
        return other.__class__ == UDS_RDTCI \
            and other.reportType == self.reportType

    @staticmethod
    def get_log(pkt):
        return pkt.sprintf("%UDS.service%"), repr(pkt)
Пример #7
0
class ThriftMessage(Packet):
    fields_desc = [
        Field("type", None),
        Field("method", None),
        Field("seqid", None),
        Field('header', None),
        Field('args', None),
        StrField("load", ""),
    ]

    def __init__(self,
                 pkt=b"",
                 mtype=None,
                 method=None,
                 seqid=None,
                 args=None,
                 header=None):
        Packet.__init__(self, pkt)
        self.setfieldval('type', mtype)
        self.setfieldval('method', method)
        self.setfieldval('seqid', seqid)
        self.setfieldval('header', header)
        self.setfieldval('args', args)
        self.setfieldval('load', pkt)
        if args and not isinstance(args, ThriftStruct):
            raise ValueError('args must be a ThriftStruct instance')
        if header and not isinstance(header, ThriftStruct):
            raise ValueError('header must be a ThriftStruct instance')

    def hashret(self):
        # The only field both Call and Reply have in common
        return self.method

    def __str__(self):
        header = ', header=%s' % self.header if self.header else ''
        field = ', fields=%s' % self.args if self.args else ''
        return 'type=%s, method=%s, seqid=%s%s%s' % (self.type, self.method,
                                                     self.seqid, header, field)

    @property
    def as_dict(self):
        return {
            'type': self.type,
            'method': self.method,
            'seqid': self.seqid,
            'header': self.header.as_dict if self.header else None,
            'args': self.args.as_dict if self.args else None,
            'length': len(self.load),
        }
Пример #8
0
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
        },
    }
Пример #9
0
class UDS_ATP(Packet):
    timingParameterAccessTypes = {
        0: 'ISOSAEReserved',
        1: 'readExtendedTimingParameterSet',
        2: 'setTimingParametersToDefaultValues',
        3: 'readCurrentlyActiveTimingParameters',
        4: 'setTimingParametersToGivenValues'
    }
    name = 'AccessTimingParameter'
    fields_desc = [
        ByteEnumField('timingParameterAccessType', 0,
                      timingParameterAccessTypes),
        ConditionalField(StrField('timingParameterRequestRecord', B""),
                         lambda pkt: pkt.timingParameterAccessType == 0x4)
    ]
Пример #10
0
class DNSRRDNSKEY(_DNSRRdummy):
    name = "DNS DNSKEY Resource Record"
    fields_desc = [
        DNSStrField("rrname", ""),
        ShortEnumField("type", 48, dnstypes),
        ShortEnumField("rclass", 1, dnsclasses),
        IntField("ttl", 0),
        ShortField("rdlen", None),
        FlagsField("flags", 256, 16, "S???????Z???????"),
        # S: Secure Entry Point
        # Z: Zone Key
        ByteField("protocol", 3),
        ByteEnumField("algorithm", 5, dnssecalgotypes),
        StrField("publickey", "")
    ]
Пример #11
0
class GMLAN_RDBPKTI(Packet):
    name = 'ReadDataByPacketIdentifier'
    subfunctions = {
        0x00: "stopSending",
        0x01: "sendOneResponse",
        0x02: "scheduleAtSlowRate",
        0x03: "scheduleAtMediumRate",
        0x04: "scheduleAtFastRate"
    }

    fields_desc = [
        XByteEnumField('subfunction', 0, subfunctions),
        ConditionalField(StrField('request_DPIDs', b''),
                         lambda pkt: pkt.subfunction > 0x0)
    ]
Пример #12
0
class SignalPacket(Packet):
    name = "signal_packet"
    fields_desc = [
        IntEnumField("signal", 1, commands),
        IEEEDoubleField("send_timestamp", 0),
        IntField("wait_seconds", DEFAULT_WAIT_SECONDS),
        FieldLenField("music_file_name_len", None,
                      length_of="music_file_name"),
        StrField("music_file_name", "")
    ]

    def __eq__(self, other):
        return self.signal == other.signal \
               and self.send_timestamp == other.send_timestamp \
               and self.wait_seconds == other.wait_seconds \
               and self.music_file_name == other.music_file_name
Пример #13
0
class PortIngressRuleResultOLTQueue(Packet):
    """ Variable Descriptor: Port Ingress Rule Result OLT Queue """
    name = "Variable Descriptor: Port Ingress Rule Result OLT Queue"
    fields_desc = [
        XByteField("branch", 0xD7),
        XShortField("leaf", 0x0501),
        ByteField("length", 15),
        XByteField("result", 3),
        XByteField("oltqueuerule", 0x13),
        XShortField("objecttype", 0x0001),
        XByteField("instance", 0),
        XByteField("pon", 0),
        StrField("unicastvssn", "TBIT"),
        XIntField("unicastlink", 0xe2222900),
        XByteField("pad", 0),
    ]
Пример #14
0
class UDS_CDTCS(Packet):
    DTCSettingTypes = {
        0: 'ISOSAEReserved',
        1: 'on',
        2: 'off'
    }
    name = 'ControlDTCSetting'
    fields_desc = [
        ByteEnumField('DTCSettingType', 0, DTCSettingTypes),
        StrField('DTCSettingControlOptionRecord', B"")
    ]

    @staticmethod
    def get_log(pkt):
        return pkt.sprintf("%UDS.service%"), \
            pkt.sprintf("%UDS_CDTCS.DTCSettingType%")
Пример #15
0
class GMLAN_RMBAPR(Packet):
    name = 'ReadMemoryByAddressPositiveResponse'
    fields_desc = [
        MultipleTypeField([
            (XShortField('memoryAddress',
                         0), lambda pkt: GMLAN.determine_len(2)),
            (X3BytesField('memoryAddress',
                          0), lambda pkt: GMLAN.determine_len(3)),
            (XIntField('memoryAddress', 0), lambda pkt: GMLAN.determine_len(4))
        ], XIntField('memoryAddress', 0)),
        StrField('dataRecord', b"", fmt="B")
    ]

    def answers(self, other):
        return isinstance(other, GMLAN_RMBA) and \
            other.memoryAddress == self.memoryAddress
Пример #16
0
class SDOption_Config(_SDOption):
    LEN_OFFSET = 0x01

    name = "Config Option"
    _defaults = {'type': _SDOption.CFG_TYPE}
    fields_desc = [
        _SDOption_Header,
        StrField("cfg_str", "")
    ]

    def post_build(self, pkt, pay):
        length = self.len
        if length is None:
            length = len(self.cfg_str) + self.LEN_OFFSET
            pkt = struct.pack("!H", length) + pkt[2:]
        return pkt + pay
Пример #17
0
class SAPCredv2_Cred_Cipher(Packet):
    """SAP Cred cipher packet. This is the header of an encrypted
    credential format 1. It contains all the required data to decrypt the stored
    credential.

    """
    name = "SAP Cred Cipher Header"

    fields_desc = [
        ByteField("version", 2),
        ByteEnumField("algorithm", 0, cipher_algorithms),
        ShortField("unknown", 0),
        StrFixedLenField("salt", None, 16),
        StrFixedLenField("iv", None, 16),
        StrField("cipher_text", None),
    ]
Пример #18
0
class GMLAN_TD(Packet):
    subfunctions = {
        0x00: "download",
        0x80: "downloadAndExecuteOrExecute"
    }
    name = 'TransferData'
    fields_desc = [
        ByteEnumField('subfunction', 0, subfunctions),
        ConditionalField(XShortField('startingAddress', 0),
                         lambda pkt: GMLAN.determine_len(2)),
        ConditionalField(X3BytesField('startingAddress', 0),
                         lambda pkt: GMLAN.determine_len(3)),
        ConditionalField(XIntField('startingAddress', 0),
                         lambda pkt: GMLAN.determine_len(4)),
        StrField("dataRecord", None)
    ]
Пример #19
0
class KWP_IOCBLI(Packet):
    name = 'InputOutputControlByLocalIdentifier'
    inputOutputControlParameters = {
        0x00: "Return Control to ECU",
        0x01: "Report Current State",
        0x04: "Reset to Default",
        0x05: "Freeze Current State",
        0x07: "Short Term Adjustment",
        0x08: "Long Term Adjustment"
    }
    fields_desc = [
        XByteField('localIdentifier', 0),
        XByteEnumField('inputOutputControlParameter', 0,
                       inputOutputControlParameters),
        StrField('controlState', b"", fmt="B")
    ]
class Dot11CCMP(Dot11Encrypted):
    name = "802.11 TKIP packet"
    fields_desc = [
        # iv - 8 bytes
        ByteField("PN0", 0),
        ByteField("PN1", 0),
        ByteField("res0", 0),
        BitField("key_id", 0, 2),  #
        BitField("ext_iv", 0, 1),  # => LE = reversed order
        BitField("res1", 0, 5),  #
        ByteField("PN2", 0),
        ByteField("PN3", 0),
        ByteField("PN4", 0),
        ByteField("PN5", 0),
        # data
        StrField("data", None),
    ]
Пример #21
0
class SAPCARCompressedBlobFormat(PacketNoPadded):
    """SAP CAR compressed blob

    This is used for decompressing blobs inside the compressed block.
    """
    name = "SAP CAR Archive Compressed blob"

    fields_desc = [
        LEIntField("compressed_length", None),
        LEIntField("uncompress_length", None),
        ByteEnumField("algorithm", 0x12, {0x12: "LZH", 0x10: "LZC"}),
        StrFixedLenField("magic_bytes", "\x1f\x9d", 2),
        ByteField("special", 2),
        ConditionalField(StrField("blob", None, remain=4), lambda x: x.compressed_length <= 8),
        ConditionalField(StrFixedLenField("blob", None, length_from=lambda x: x.compressed_length - 8),
                         lambda x: x.compressed_length > 8),
    ]
Пример #22
0
class Raw(Packet):
    name = "Raw"
    fields_desc = [ StrField("load", "") ]
    def answers(self, other):
        return 1
#        s = str(other)
#        t = self.load
#        l = min(len(s), len(t))
#        return  s[:l] == t[:l]
    def mysummary(self):
        cs = conf.raw_summary
        if cs:
            if callable(cs):
                return "Raw %s" % cs(self.load)
            else:
                return "Raw %r" % self.load
        return Packet.mysummary(self)
Пример #23
0
class DNSRRRSIG(_DNSRRdummy):
    name = "DNS RRSIG Resource Record"
    fields_desc = [DNSStrField("rrname", ""),
                   ShortEnumField("type", 46, dnstypes),
                   ShortEnumField("rclass", 1, dnsclasses),
                   IntField("ttl", 0),
                   ShortField("rdlen", None),
                   ShortEnumField("typecovered", 1, dnstypes),
                   ByteEnumField("algorithm", 5, dnssecalgotypes),
                   ByteField("labels", 0),
                   IntField("originalttl", 0),
                   UTCTimeField("expiration", 0),
                   UTCTimeField("inception", 0),
                   ShortField("keytag", 0),
                   DNSStrField("signersname", ""),
                   StrField("signature", "")
                   ]
Пример #24
0
class BOOTP(Packet):
    name = "BOOTP"
    fields_desc = [
        ByteEnumField("op", 1, {
            1: "BOOTREQUEST",
            2: "BOOTREPLY"
        }),
        ByteField("htype", 1),
        ByteField("hlen", 6),
        ByteField("hops", 0),
        IntField("xid", 0),
        ShortField("secs", 0),
        FlagsField("flags", 0, 16, "???????????????B"),
        IPField("ciaddr", "0.0.0.0"),
        IPField("yiaddr", "0.0.0.0"),
        IPField("siaddr", "0.0.0.0"),
        IPField("giaddr", "0.0.0.0"),
        Field("chaddr", b"", "16s"),
        Field("sname", b"", "64s"),
        Field("file", b"", "128s"),
        StrField("options", b"")
    ]

    def guess_payload_class(self, payload):
        if self.options[:len(dhcpmagic)] == dhcpmagic:
            return DHCP
        else:
            return Packet.guess_payload_class(self, payload)

    def extract_padding(self, s):
        if self.options[:len(dhcpmagic)] == dhcpmagic:
            # set BOOTP options to DHCP magic cookie and make rest a payload of DHCP options  # noqa: E501
            payload = self.options[len(dhcpmagic):]
            self.options = self.options[:len(dhcpmagic)]
            return payload, None
        else:
            return b"", None

    def hashret(self):
        return struct.pack("!I", self.xid)

    def answers(self, other):
        if not isinstance(other, BOOTP):
            return 0
        return self.xid == other.xid
class Dot11TKIP(Dot11Encrypted):
    name = "802.11 TKIP packet"
    fields_desc = [
        # iv - 4 bytes
        ByteField("TSC1", 0),
        ByteField("WEPSeed", 0),
        ByteField("TSC0", 0),
        BitField("key_id", 0, 2),  #
        BitField("ext_iv", 0, 1),  # => LE = reversed order
        BitField("res", 0, 5),  #
        # ext_iv - 4 bytes
        ConditionalField(ByteField("TSC2", 0), lambda pkt: pkt.ext_iv),
        ConditionalField(ByteField("TSC3", 0), lambda pkt: pkt.ext_iv),
        ConditionalField(ByteField("TSC4", 0), lambda pkt: pkt.ext_iv),
        ConditionalField(ByteField("TSC5", 0), lambda pkt: pkt.ext_iv),
        # data
        StrField("data", None),
    ]
Пример #26
0
class UDS_RCPR(Packet):
    name = 'RoutineControlPositiveResponse'
    fields_desc = [
        ByteEnumField('routineControlType', 0, UDS_RC.routineControlTypes),
        XShortField('routineIdentifier', 0),
        StrField('routineStatusRecord', 0, fmt="B"),
    ]

    def answers(self, other):
        return other.__class__ == UDS_RC \
            and other.routineControlType == self.routineControlType

    @staticmethod
    def get_log(pkt):
        return pkt.sprintf("%UDS.service%"),\
            (pkt.routineControlType,
             pkt.routineIdentifier,
             pkt.routineStatusRecord)
Пример #27
0
class ZigbeeSecurityHeader(Packet):
    name = "Zigbee Security Header"
    fields_desc = [
        # Security control (1 octet)
        FlagsField("reserved1", 0, 2, ['reserved1', 'reserved2']),
        BitField("extended_nonce", 1, 1),  # set to 1 if the sender address field is present (source)  # noqa: E501
        # Key identifier
        BitEnumField("key_type", 1, 2, {
            0: 'data_key',
            1: 'network_key',
            2: 'key_transport_key',
            3: 'key_load_key'
        }),
        # Security level (3 bits)
        BitEnumField("nwk_seclevel", 0, 3, {
            0: "None",
            1: "MIC-32",
            2: "MIC-64",
            3: "MIC-128",
            4: "ENC",
            5: "ENC-MIC-32",
            6: "ENC-MIC-64",
            7: "ENC-MIC-128"
        }),
        # Frame counter (4 octets)
        XLEIntField("fc", 0),  # provide frame freshness and prevent duplicate frames  # noqa: E501
        # Source address (0/8 octets)
        ConditionalField(dot15d4AddressField("source", 0, adjust=lambda pkt, x: 8), lambda pkt: pkt.extended_nonce),  # noqa: E501
        # Key sequence number (0/1 octet): only present when key identifier is 1 (network key)  # noqa: E501
        ConditionalField(ByteField("key_seqnum", 0), lambda pkt: pkt.getfieldval("key_type") == 1),  # noqa: E501
        # Payload
        # the length of the encrypted data is the payload length minus the MIC
        StrField("data", ""),  # noqa: E501
        # Message Integrity Code (0/variable in size), length depends on nwk_seclevel  # noqa: E501
        XStrField("mic", ""),
    ]

    def post_dissect(self, s):
        # Get the mic dissected correctly
        mic_length = util_mic_len(self)
        if mic_length > 0:  # Slice "data" into "data + mic"
            _data, _mic = self.data[:-mic_length], self.data[-mic_length:]
            self.data, self.mic = _data, _mic
        return s
Пример #28
0
class VRRPv3(Packet):
    fields_desc = [
        BitField("version", 3, 4),
        BitField("type", 1, 4),
        ByteField("vrid", 1),
        ByteField("priority", 100),
        FieldLenField("ipcount", None, count_of="addrlist", fmt="B"),
        BitField("res", 0, 4),
        BitField("adv", 100, 12),
        XShortField("chksum", None),
        MultipleTypeField([
            (FieldListField("addrlist", [],
                            IPField("", "0.0.0.0"),
                            count_from=lambda pkt: pkt.ipcount),
             lambda p: isinstance(p.underlayer, IP)),
            (FieldListField("addrlist", [],
                            IP6Field("", "::"),
                            count_from=lambda pkt: pkt.ipcount),
             lambda p: isinstance(p.underlayer, IPv6)),
        ], StrField("addrlist", ""))
    ]

    def post_build(self, p, pay):
        if self.chksum is None:
            if isinstance(self.underlayer, IP):
                ck = in4_chksum(112, self.underlayer, p)
            elif isinstance(self.underlayer, IPv6):
                ck = in6_chksum(112, self.underlayer, p)
            else:
                warning(
                    "No IP(v6) layer to compute checksum on VRRP. Leaving null"
                )  # noqa: E501
                ck = 0
            p = p[:6] + chb(ck >> 8) + chb(ck & 0xff) + p[8:]
        return p

    @classmethod
    def dispatch_hook(cls, _pkt=None, *args, **kargs):
        if _pkt and len(_pkt) >= 16:
            ver_n_type = orb(_pkt[0])
            if ver_n_type < 48 or ver_n_type > 57:  # Version != 3
                return VRRP
        return VRRPv3
Пример #29
0
class GMLAN_TD(Packet):
    subfunctions = {0x00: "download", 0x80: "downloadAndExecuteOrExecute"}
    name = 'TransferData'
    fields_desc = [
        ByteEnumField('subfunction', 0, subfunctions),
        ConditionalField(XShortField('startingAddress', 0),
                         lambda pkt: GMLAN.determine_len(2)),
        ConditionalField(X3BytesField('startingAddress', 0),
                         lambda pkt: GMLAN.determine_len(3)),
        ConditionalField(XIntField('startingAddress', 0),
                         lambda pkt: GMLAN.determine_len(4)),
        StrField("dataRecord", None)
    ]

    @staticmethod
    def get_log(pkt):
        return pkt.sprintf("%GMLAN.service%"), \
            (pkt.sprintf("%GMLAN_TD.subfunction%"), pkt.startingAddress,
             pkt.dataRecord)
Пример #30
0
class USBPcap(Packet):
    ''' Packet used in pcap files '''

    name = 'USBPcap'
    fields_desc = [
        LELongField('urb_id', 0),
        CharEnumField('urb_type', SUBMIT, pcap_urb_type),
        ByteEnumField('urb_transfert', PCAP_CTRL, pcap_urb_transfert),
        BitEnumField('endpoint_direction', USBDefs.EP.Direction.IN, 1,
                     USBDefs.EP.Direction.desc),
        BitField('endpoint_number', 0, 7),
        ByteField('device', 1),
        LEShortField('bus_id', 1),
        ByteEnumField('device_setup_request', 0, pcap_setup_request),
        ByteEnumField('data_present', 0, pcap_data_present),
        LELongField('urb_sec', 0),
        LEIntField('urb_usec', 0),
        LESignedIntEnumField('urb_status', 0, pcap_urb_status),
        LEIntField('urb_length', 0),
        LEIntField('data_length', 0),
        ConditionalField(
            PacketField('urb_setup', GetDescriptor(), URB),
            lambda p: p.urb_transfert == 2 and p.urb_type == 'S',
        ),
        BytesFixedLenField(
            'garbage',
            pcap_garbage,
            length_from=lambda p: 24
            if p.urb_setup is None else 24 - len(p.urb_setup),
        ),
        ConditionalField(
            PacketField('descriptor', DeviceDescriptor(), Descriptor),
            lambda p: p.urb_transfert == 2 and p.urb_type == 'C' and p.
            data_length > 0,
        ),
        StrField('data', ''),
    ]

    def is_ctrl_request(self):
        return self.urb_type == SUBMIT and self.urb_transfert == PCAP_CTRL

    def is_ctrl_response(self):
        return self.urb_type == COMPLETE and self.urb_transfert == PCAP_CTRL