示例#1
0
class ZigbeeNWK(Packet):
    name = "Zigbee Network Layer"
    fields_desc = [
                    BitField("discover_route", 0, 2),
                    BitField("proto_version", 2, 4),
                    BitEnumField("frametype", 0, 2, {0:'data', 1:'command'}),
                    FlagsField("flags", 0, 8, ['multicast', 'security', 'source_route', 'extended_dst', 'extended_src', 'reserved1', 'reserved2', 'reserved3']),
                    XLEShortField("destination", 0),
                    XLEShortField("source", 0),
                    ByteField("radius", 0),
                    ByteField("seqnum", 1),

                    ConditionalField(ByteField("relay_count", 1), lambda pkt:pkt.flags & 0x04),
                    ConditionalField(ByteField("relay_index", 0), lambda pkt:pkt.flags & 0x04),
                    ConditionalField(FieldListField("relays", [ ], XLEShortField("", 0x0000), count_from = lambda pkt:pkt.relay_count), lambda pkt:pkt.flags & 0x04),

                    #ConditionalField(XLongField("ext_dst", 0), lambda pkt:pkt.flags & 8),
                    ConditionalField(dot15d4AddressField("ext_dst", 0, adjust=lambda pkt,x: 8), lambda pkt:pkt.flags & 8),
                    #ConditionalField(XLongField("ext_src", 0), lambda pkt:pkt.flags & 16),
                    ConditionalField(dot15d4AddressField("ext_src", 0, adjust=lambda pkt,x: 8), lambda pkt:pkt.flags & 16),
                ]

    def guess_payload_class(self, payload):
        if self.flags & 0x02:
            return ZigbeeSecurityHeader
        elif self.frametype == 0:
            return ZigbeeAppDataPayload
        elif self.frametype == 1:
            return ZigbeeNWKCommandPayload
        else:
            return Packet.guess_payload_class(self, payload)
示例#2
0
文件: zigbee.py 项目: mingqian/scapy
class ZigbeeAppCommandPayload(Packet):
    name = "Zigbee Application Layer Command Payload"
    fields_desc = [
        ByteEnumField("cmd_identifier", 1, {
            1: "APS_CMD_SKKE_1",
            2: "APS_CMD_SKKE_2",
            3: "APS_CMD_SKKE_3",
            4: "APS_CMD_SKKE_4",
            5: "APS_CMD_TRANSPORT_KEY",
            6: "APS_CMD_UPDATE_DEVICE",
            7: "APS_CMD_REMOVE_DEVICE",
            8: "APS_CMD_REQUEST_KEY",
            9: "APS_CMD_SWITCH_KEY",
            10: "APS_CMD_EA_INIT_CHLNG",
            11: "APS_CMD_EA_RSP_CHLNG",
            12: "APS_CMD_EA_INIT_MAC_DATA",
            13: "APS_CMD_EA_RSP_MAC_DATA",
            14: "APS_CMD_TUNNEL"
        }),
        ConditionalField(StrFixedLenField("key", None, 16), lambda pkt: pkt.cmd_identifier == 1),  # noqa: E501
        ConditionalField(ByteField("key_seqnum", 0), lambda pkt: pkt.cmd_identifier == 1),  # noqa: E501
        ConditionalField(dot15d4AddressField("dest_addr", 0, adjust=lambda pkt, x: 8), lambda pkt: pkt.cmd_identifier == 1),  # noqa: E501
        ConditionalField(dot15d4AddressField("src_addr", 0, adjust=lambda pkt, x: 8), lambda pkt: pkt.cmd_identifier == 1),  # noqa: E501
        ConditionalField(StrField("data", ""), lambda pkt: pkt.cmd_identifier != 1)  # noqa: E501
    ]
示例#3
0
class ZigbeeNWK(Packet):
    name = "Zigbee Network Layer"
    fields_desc = [
        BitField("discover_route", 0, 2),
        BitField("proto_version", 2, 4),
        BitEnumField("frametype", 0, 2, {
            0: 'data',
            1: 'command',
            3: 'Inter-PAN'
        }),
        FlagsField("flags", 0, 8, [
            'multicast', 'security', 'source_route', 'extended_dst',
            'extended_src', 'reserved1', 'reserved2', 'reserved3'
        ]),  # noqa: E501
        XLEShortField("destination", 0),
        XLEShortField("source", 0),
        ByteField("radius", 0),
        ByteField("seqnum", 1),

        # ConditionalField(XLongField("ext_dst", 0), lambda pkt:pkt.flags & 8),
        ConditionalField(
            dot15d4AddressField("ext_dst", 0, adjust=lambda pkt, x: 8),
            lambda pkt: pkt.flags & 8),  # noqa: E501
        ConditionalField(
            dot15d4AddressField("ext_src", 0, adjust=lambda pkt, x: 8),
            lambda pkt: pkt.flags & 16),  # noqa: E501
        ConditionalField(ByteField("relay_count", 1),
                         lambda pkt: pkt.flags & 0x04),  # noqa: E501
        ConditionalField(ByteField("relay_index", 0),
                         lambda pkt: pkt.flags & 0x04),  # noqa: E501
        ConditionalField(
            FieldListField("relays", [],
                           XLEShortField("", 0x0000),
                           count_from=lambda pkt: pkt.relay_count),
            lambda pkt: pkt.flags & 0x04),  # noqa: E501
    ]

    @classmethod
    def dispatch_hook(cls, _pkt=None, *args, **kargs):
        if _pkt and len(_pkt) >= 2:
            frametype = ord(_pkt[:1]) & 3
            if frametype == 3:
                return ZigbeeNWKStub
        return cls

    def guess_payload_class(self, payload):
        if self.flags.security:
            return ZigbeeSecurityHeader
        elif self.frametype == 0:
            return ZigbeeAppDataPayload
        elif self.frametype == 1:
            return ZigbeeNWKCommandPayload
        else:
            return Packet.guess_payload_class(self, payload)
示例#4
0
class ZigBeeBeacon(Packet):
    name = "ZigBee Beacon Payload"
    fields_desc = [
        # Protocol ID (1 octet)
        ByteField("proto_id", 0),
        # nwkcProtocolVersion (4 bits)
        BitField("nwkc_protocol_version", 0, 4),
        # Stack profile (4 bits)
        BitField("stack_profile", 0, 4),
        # End device capacity (1 bit)
        BitField("end_device_capacity", 0, 1),
        # Device depth (4 bits)
        BitField("device_depth", 0, 4),
        # Router capacity (1 bit)
        BitField("router_capacity", 0, 1),
        # Reserved (2 bits)
        BitField("reserved", 0, 2),
        # Extended PAN ID (8 octets)
        dot15d4AddressField("extended_pan_id", 0, adjust=lambda pkt, x: 8),
        # Tx offset (3 bytes)
        # In ZigBee 2006 the Tx-Offset is optional, while in the 2007 and later versions, the Tx-Offset is a required value.
        BitField("tx_offset", 0, 24),
        # Update ID (1 octet)
        ByteField("update_id", 0),
    ]
示例#5
0
class ZigbeeSecurityHeader(Packet):
    name = "Zigbee Security Header"
    fields_desc = [
        # Security control (1 octet)
        HiddenField(FlagsField("reserved1", 0, 2, [ 'reserved1', 'reserved2' ]), True),
        BitField("extended_nonce", 1, 1), # set to 1 if the sender address field is present (source)
        # 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
        # Source address (0/8 octets)
        ConditionalField(dot15d4AddressField("source", 0, adjust=lambda pkt,x: 8), lambda pkt:pkt.extended_nonce),
        # Key sequence number (0/1 octet): only present when key identifier is 1 (network key)
        ConditionalField(ByteField("key_seqnum", 0), lambda pkt:pkt.getfieldval("key_type") == 1),
        # Payload
        # the length of the encrypted data is the payload length minus the MIC
        ZigbeePayloadField("data", "", length_from=lambda pkt, s:len(s)-ZigbeeSecurityHeader.util_mic_len(pkt) ),
        # Message Integrity Code (0/variable in size), length depends on nwk_seclevel
        StrLenField("mic", "", length_from=lambda pkt:ZigbeeSecurityHeader.util_mic_len(pkt) ),
    ]

    def util_mic_len(pkt):
        ''' Calculate the length of the attribute value field '''
        if ( pkt.nwk_seclevel == 0 ): # no encryption, no mic
            return 0
        elif ( pkt.nwk_seclevel == 1 ): # MIC-32
            return 4
        elif ( pkt.nwk_seclevel == 2 ): # MIC-64
            return 8
        elif ( pkt.nwk_seclevel == 3 ): # MIC-128
            return 16
        elif ( pkt.nwk_seclevel == 4 ): # ENC
            return 0
        elif ( pkt.nwk_seclevel == 5 ): # ENC-MIC-32
            return 4
        elif ( pkt.nwk_seclevel == 6 ): # ENC-MIC-64
            return 8
        elif ( pkt.nwk_seclevel == 7 ): # ENC-MIC-128
            return 16
        else:
            return 0
示例#6
0
class ZigbeeSecurityHeader2(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
        IntField("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
示例#7
0
class ZigbeeDeviceProfile(Packet):
    name = "Zigbee Device Profile (ZDP) frame"
    fields_desc = [
        # sequence number (8 bits)
        ByteField("sequence_number", 0),
        # Device short address
        dot15d4AddressField("extended_address", 0, adjust=lambda pkt, x: 8),
        # flags 1 octet
        FlagsField("frame_control", 0, 8, [
            'reserved1', 'reserved2', 'reserved3', 'reserved4',
            'remove_children', 'rejoin'
        ]),
    ]

    def guess_payload_class(self, payload):
        return Packet.guess_payload_class(self, payload)
示例#8
0
class ZigbeeNWKCommandPayload(Packet):
    name = "Zigbee Network Layer Command Payload"
    fields_desc = [
        ByteEnumField(
            "cmd_identifier",
            1,
            {
                1: "route request",
                2: "route reply",
                3: "network status",
                4: "leave",
                5: "route record",
                6: "rejoin request",
                7: "rejoin response",
                8: "link status",
                9: "network report",
                10: "network update"
                # 0x0b - 0xff reserved
            }),

        ### Route Request Command ###
        # Command options (1 octet)
        ConditionalField(BitField("reserved", 0, 1),
                         lambda pkt: pkt.cmd_identifier == 1),
        ConditionalField(BitField("multicast", 0, 1),
                         lambda pkt: pkt.cmd_identifier == 1),
        ConditionalField(BitField("dest_addr_bit", 0, 1),
                         lambda pkt: pkt.cmd_identifier == 1),
        ConditionalField(
            BitEnumField(
                "many_to_one", 0, 2, {
                    0: "not_m2one",
                    1: "m2one_support_rrt",
                    2: "m2one_no_support_rrt",
                    3: "reserved"
                }), lambda pkt: pkt.cmd_identifier == 1),
        ConditionalField(BitField("reserved", 0, 3),
                         lambda pkt: pkt.cmd_identifier == 1),
        # Route request identifier (1 octet)
        ConditionalField(ByteField("route_request_identifier", 0),
                         lambda pkt: pkt.cmd_identifier == 1),
        # Destination address (2 octets)
        ConditionalField(XLEShortField("destination_address", 0x0000),
                         lambda pkt: pkt.cmd_identifier == 1),
        # Path cost (1 octet)
        ConditionalField(ByteField("path_cost", 0),
                         lambda pkt: pkt.cmd_identifier == 1),
        # Destination IEEE Address (0/8 octets), only present when dest_addr_bit has a value of 1
        ConditionalField(
            dot15d4AddressField("ext_dst", 0, adjust=lambda pkt, x: 8),
            lambda pkt: (pkt.cmd_identifier == 1 and pkt.dest_addr_bit == 1)),

        ### Route Reply Command ###
        # Command options (1 octet)
        ConditionalField(BitField("reserved", 0, 1),
                         lambda pkt: pkt.cmd_identifier == 2),
        ConditionalField(BitField("multicast", 0, 1),
                         lambda pkt: pkt.cmd_identifier == 2),
        ConditionalField(BitField("responder_addr_bit", 0, 1),
                         lambda pkt: pkt.cmd_identifier == 2),
        ConditionalField(BitField("originator_addr_bit", 0, 1),
                         lambda pkt: pkt.cmd_identifier == 2),
        ConditionalField(BitField("reserved", 0, 4),
                         lambda pkt: pkt.cmd_identifier == 2),
        # Route request identifier (1 octet)
        ConditionalField(ByteField("route_request_identifier", 0),
                         lambda pkt: pkt.cmd_identifier == 2),
        # Originator address (2 octets)
        ConditionalField(XLEShortField("originator_address", 0x0000),
                         lambda pkt: pkt.cmd_identifier == 2),
        # Responder address (2 octets)
        ConditionalField(XLEShortField("responder_address", 0x0000),
                         lambda pkt: pkt.cmd_identifier == 2),
        # Path cost (1 octet)
        ConditionalField(ByteField("path_cost", 0),
                         lambda pkt: pkt.cmd_identifier == 2),
        # Originator IEEE address (0/8 octets)
        ConditionalField(
            dot15d4AddressField("originator_addr", 0,
                                adjust=lambda pkt, x: 8), lambda pkt:
            (pkt.cmd_identifier == 2 and pkt.originator_addr_bit == 1)),
        # Responder IEEE address (0/8 octets)
        ConditionalField(
            dot15d4AddressField("responder_addr", 0,
                                adjust=lambda pkt, x: 8), lambda pkt:
            (pkt.cmd_identifier == 2 and pkt.responder_addr_bit == 1)),

        ### Network Status Command ###
        # Status code (1 octet)
        ConditionalField(
            ByteEnumField(
                "status_code",
                0,
                {
                    0x00: "No route available",
                    0x01: "Tree link failure",
                    0x02: "Non-tree link failure",
                    0x03: "Low battery level",
                    0x04: "No routing capacity",
                    0x05: "No indirect capacity",
                    0x06: "Indirect transaction expiry",
                    0x07: "Target device unavailable",
                    0x08: "Target address unallocated",
                    0x09: "Parent link failure",
                    0x0a: "Validate route",
                    0x0b: "Source route failure",
                    0x0c: "Many-to-one route failure",
                    0x0d: "Address conflict",
                    0x0e: "Verify addresses",
                    0x0f: "PAN identifier update",
                    0x10: "Network address update",
                    0x11: "Bad frame counter",
                    0x12: "Bad key sequence number",
                    # 0x13 - 0xff Reserved
                }),
            lambda pkt: pkt.cmd_identifier == 3),
        # Destination address (2 octets)
        ConditionalField(XLEShortField("destination_address", 0x0000),
                         lambda pkt: pkt.cmd_identifier == 3),

        ### Leave Command ###
        # Command options (1 octet)
        # Bit 7: Remove children
        ConditionalField(BitField("remove_children", 0, 1),
                         lambda pkt: pkt.cmd_identifier == 4),
        # Bit 6: Request
        ConditionalField(BitField("request", 0, 1),
                         lambda pkt: pkt.cmd_identifier == 4),
        # Bit 5: Rejoin
        ConditionalField(BitField("rejoin", 0, 1),
                         lambda pkt: pkt.cmd_identifier == 4),
        # Bit 0 - 4: Reserved
        ConditionalField(BitField("reserved", 0, 5),
                         lambda pkt: pkt.cmd_identifier == 4),

        ### Route Record Command ###
        # Relay count (1 octet)
        ConditionalField(ByteField("rr_relay_count", 0),
                         lambda pkt: pkt.cmd_identifier == 5),
        # Relay list (variable in length)
        ConditionalField(
            FieldListField("rr_relay_list", [],
                           XLEShortField("", 0x0000),
                           count_from=lambda pkt: pkt.rr_relay_count),
            lambda pkt: pkt.cmd_identifier == 5),

        ### Rejoin Request Command ###
        # Capability Information (1 octet)
        ConditionalField(
            BitField("allocate_address", 0, 1),
            lambda pkt: pkt.cmd_identifier == 6),  # Allocate Address
        ConditionalField(
            BitField("security_capability", 0, 1),
            lambda pkt: pkt.cmd_identifier == 6),  # Security Capability
        ConditionalField(BitField(
            "reserved2", 0,
            1), lambda pkt: pkt.cmd_identifier == 6),  # bit 5 is reserved
        ConditionalField(BitField(
            "reserved1", 0,
            1), lambda pkt: pkt.cmd_identifier == 6),  # bit 4 is reserved
        ConditionalField(
            BitField("receiver_on_when_idle", 0, 1),
            lambda pkt: pkt.cmd_identifier == 6),  # Receiver On When Idle
        ConditionalField(BitField("power_source", 0, 1),
                         lambda pkt: pkt.cmd_identifier == 6),  # Power Source
        ConditionalField(BitField("device_type", 0, 1),
                         lambda pkt: pkt.cmd_identifier == 6),  # Device Type
        ConditionalField(
            BitField("alternate_pan_coordinator", 0, 1),
            lambda pkt: pkt.cmd_identifier == 6),  # Alternate PAN Coordinator

        ### Rejoin Response Command ###
        # Network address (2 octets)
        ConditionalField(XLEShortField("network_address", 0xFFFF),
                         lambda pkt: pkt.cmd_identifier == 7),
        # Rejoin status (1 octet)
        ConditionalField(ByteField("rejoin_status", 0),
                         lambda pkt: pkt.cmd_identifier == 7),

        ### Link Status Command ###
        # Command options (1 octet)
        ConditionalField(BitField("reserved", 0, 1),
                         lambda pkt: pkt.cmd_identifier == 8),  # Reserved
        ConditionalField(BitField("last_frame", 0, 1),
                         lambda pkt: pkt.cmd_identifier == 8),  # Last frame
        ConditionalField(BitField("first_frame", 0, 1),
                         lambda pkt: pkt.cmd_identifier == 8),  # First frame
        ConditionalField(BitField("entry_count", 0, 5),
                         lambda pkt: pkt.cmd_identifier == 8),  # Entry count
        # Link status list (variable size)
        ConditionalField(
            PacketListField("link_status_list", [],
                            LinkStatusEntry,
                            count_from=lambda pkt: pkt.entry_count),
            lambda pkt: pkt.cmd_identifier == 8),

        ### Network Report Command ###
        # Command options (1 octet)
        ConditionalField(
            BitEnumField(
                "report_command_identifier", 0, 3,
                {0: "PAN identifier conflict"}),  # 0x01 - 0x07 Reserved
            lambda pkt: pkt.cmd_identifier == 9),
        ConditionalField(BitField("report_information_count", 0, 5),
                         lambda pkt: pkt.cmd_identifier == 9),
        # EPID: Extended PAN ID (8 octets)
        ConditionalField(
            dot15d4AddressField("epid", 0, adjust=lambda pkt, x: 8),
            lambda pkt: pkt.cmd_identifier == 9),
        # Report information (variable length)
        # Only present if we have a PAN Identifier Conflict Report
        ConditionalField(
            FieldListField(
                "PAN_ID_conflict_report", [],
                XLEShortField("", 0x0000),
                count_from=lambda pkt: pkt.report_information_count),
            lambda pkt:
            (pkt.cmd_identifier == 9 and pkt.report_command_identifier == 0)),

        ### Network Update Command ###
        # Command options (1 octet)
        ConditionalField(
            BitEnumField("update_command_identifier", 0, 3,
                         {0: "PAN Identifier Update"}),  # 0x01 - 0x07 Reserved
            lambda pkt: pkt.cmd_identifier == 10),
        ConditionalField(BitField("update_information_count", 0, 5),
                         lambda pkt: pkt.cmd_identifier == 10),
        # EPID: Extended PAN ID (8 octets)
        ConditionalField(
            dot15d4AddressField("epid", 0, adjust=lambda pkt, x: 8),
            lambda pkt: pkt.cmd_identifier == 10),
        # Update Id (1 octet)
        ConditionalField(ByteField("update_id", 0),
                         lambda pkt: pkt.cmd_identifier == 10),
        # Update Information (Variable)
        # Only present if we have a PAN Identifier Update
        # New PAN ID (2 octets)
        ConditionalField(
            XLEShortField("new_PAN_ID", 0x0000), lambda pkt:
            (pkt.cmd_identifier == 10 and pkt.update_command_identifier == 0)),

        #ZigbeePayloadField("data", "", length_from=lambda pkt, s:len(s)),
    ]
示例#9
0
class ZigbeeAppCommandPayload(Packet):
    name = "Zigbee Application Layer Command Payload"
    fields_desc = [
        ByteEnumField(
            "cmd_identifier",
            1,
            {
                1: "APS_CMD_SKKE_1",
                2: "APS_CMD_SKKE_2",
                3: "APS_CMD_SKKE_3",
                4: "APS_CMD_SKKE_4",
                5: "APS_CMD_TRANSPORT_KEY",
                6: "APS_CMD_UPDATE_DEVICE",
                7: "APS_CMD_REMOVE_DEVICE",
                8: "APS_CMD_REQUEST_KEY",
                9: "APS_CMD_SWITCH_KEY",
                # TODO: implement 10 to 14
                10: "APS_CMD_EA_INIT_CHLNG",
                11: "APS_CMD_EA_RSP_CHLNG",
                12: "APS_CMD_EA_INIT_MAC_DATA",
                13: "APS_CMD_EA_RSP_MAC_DATA",
                14: "APS_CMD_TUNNEL"
            }),
        # SKKE Commands
        ConditionalField(
            dot15d4AddressField("initiator", 0, adjust=lambda pkt, x: 8),
            lambda pkt: pkt.cmd_identifier in [1, 2, 3, 4]),
        ConditionalField(
            dot15d4AddressField("responder", 0, adjust=lambda pkt, x: 8),
            lambda pkt: pkt.cmd_identifier in [1, 2, 3, 4]),
        ConditionalField(StrFixedLenField("data", 0, length=16),
                         lambda pkt: pkt.cmd_identifier in [1, 2, 3, 4]),
        # Transport-key Command
        ConditionalField(ByteEnumField("key_type", 0, _TransportKeyKeyTypes),
                         lambda pkt: pkt.cmd_identifier == 5),
        ConditionalField(StrFixedLenField("key", None, 16),
                         lambda pkt: pkt.cmd_identifier == 5),
        ConditionalField(
            ByteField("key_seqnum", 0), lambda pkt:
            (pkt.cmd_identifier == 5 and pkt.key_type in [0x01, 0x05])),
        ConditionalField(
            dot15d4AddressField("dest_addr", 0, adjust=lambda pkt, x: 8),
            lambda pkt: pkt.cmd_identifier == 5),
        ConditionalField(
            dot15d4AddressField("src_addr", 0, adjust=lambda pkt, x: 8),
            lambda pkt: pkt.cmd_identifier == 5),
        # Update-Device Command
        ConditionalField(
            dot15d4AddressField("address", 0, adjust=lambda pkt, x: 8),
            lambda pkt: pkt.cmd_identifier == 6),
        ConditionalField(XLEShortField("short_address", 0),
                         lambda pkt: pkt.cmd_identifier == 6),
        ConditionalField(ByteField("status", 0),
                         lambda pkt: pkt.cmd_identifier == 6),
        # Remove-Device Command
        ConditionalField(
            dot15d4AddressField("address", 0, adjust=lambda pkt, x: 8),
            lambda pkt: pkt.cmd_identifier == 7),
        # Request-Key Command
        ConditionalField(ByteEnumField("key_type", 0, _TransportKeyKeyTypes),
                         lambda pkt: pkt.cmd_identifier == 8),
        ConditionalField(StrFixedLenField("key", None, 16),
                         lambda pkt: pkt.cmd_identifier == 8),
        # Switch-Key Command
        ConditionalField(StrFixedLenField("seqnum", None, 8),
                         lambda pkt: pkt.cmd_identifier == 9),
        # Un-implemented: 10-14 (+?)
        ConditionalField(
            StrField("data", ""), lambda pkt:
            (pkt.cmd_identifier < 0 or pkt.cmd_identifier > 9))
    ]
示例#10
0
class ZigbeeAppCommandPayload(Packet):
    name = "Zigbee Application Layer Command Payload"
    fields_desc = [
        ByteEnumField("cmd_identifier", 1, {
            1: "APS_CMD_SKKE_1",
            2: "APS_CMD_SKKE_2",
            3: "APS_CMD_SKKE_3",
            4: "APS_CMD_SKKE_4",
            5: "APS_CMD_TRANSPORT_KEY",
            6: "APS_CMD_UPDATE_DEVICE",
            7: "APS_CMD_REMOVE_DEVICE",
            8: "APS_CMD_REQUEST_KEY",
            9: "APS_CMD_SWITCH_KEY",
            # TODO: implement 10 to 13
            10: "APS_CMD_EA_INIT_CHLNG",
            11: "APS_CMD_EA_RSP_CHLNG",
            12: "APS_CMD_EA_INIT_MAC_DATA",
            13: "APS_CMD_EA_RSP_MAC_DATA",
            14: "APS_CMD_TUNNEL",
            15: "APS_CMD_VERIFY_KEY",
            16: "APS_CMD_CONFIRM_KEY"
        }),
        # SKKE Commands
        ConditionalField(dot15d4AddressField("initiator", 0,
                                             adjust=lambda pkt, x: 8),
                         lambda pkt: pkt.cmd_identifier in [1, 2, 3, 4]),
        ConditionalField(dot15d4AddressField("responder", 0,
                                             adjust=lambda pkt, x: 8),
                         lambda pkt: pkt.cmd_identifier in [1, 2, 3, 4]),
        ConditionalField(StrFixedLenField("data", 0, length=16),
                         lambda pkt: pkt.cmd_identifier in [1, 2, 3, 4]),
        # Confirm-key command
        ConditionalField(
            ByteEnumField("status", 0, _ApsStatusValues),
            lambda pkt: pkt.cmd_identifier == 16),
        # Common fields
        ConditionalField(
            ByteEnumField("key_type", 0, _TransportKeyKeyTypes),
            lambda pkt: pkt.cmd_identifier in [5, 8, 15, 16]),
        ConditionalField(dot15d4AddressField("address", 0,
                                             adjust=lambda pkt, x: 8),
                         lambda pkt: pkt.cmd_identifier in [6, 7, 15, 16]),
        # Transport-key Command
        ConditionalField(
            StrFixedLenField("key", None, 16),
            lambda pkt: pkt.cmd_identifier == 5),
        ConditionalField(
            ByteField("key_seqnum", 0),
            lambda pkt: (pkt.cmd_identifier == 5 and
                         pkt.key_type in [0x01, 0x05])),
        ConditionalField(
            dot15d4AddressField("dest_addr", 0, adjust=lambda pkt, x: 8),
            lambda pkt: ((pkt.cmd_identifier == 5 and
                         pkt.key_type not in [0x02, 0x03]) or
                         pkt.cmd_identifier == 14)),
        ConditionalField(
            dot15d4AddressField("src_addr", 0, adjust=lambda pkt, x: 8),
            lambda pkt: (pkt.cmd_identifier == 5 and
                         pkt.key_type not in [0x02, 0x03])),
        ConditionalField(
            dot15d4AddressField("partner_addr", 0, adjust=lambda pkt, x: 8),
            lambda pkt: ((pkt.cmd_identifier == 5 and
                         pkt.key_type in [0x02, 0x03]) or
                         (pkt.cmd_identifier == 8 and pkt.key_type == 0x02))),
        ConditionalField(
            ByteField("initiator_flag", 0),
            lambda pkt: (pkt.cmd_identifier == 5 and
                         pkt.key_type in [0x02, 0x03])),
        # Update-Device Command
        ConditionalField(XLEShortField("short_address", 0),
                         lambda pkt: pkt.cmd_identifier == 6),
        ConditionalField(ByteField("update_status", 0),
                         lambda pkt: pkt.cmd_identifier == 6),
        # Switch-Key Command
        ConditionalField(StrFixedLenField("seqnum", None, 8),
                         lambda pkt: pkt.cmd_identifier == 9),
        # Un-implemented: 10-13 (+?)
        ConditionalField(StrField("unimplemented", ""),
                         lambda pkt: (pkt.cmd_identifier >= 10 and
                                      pkt.cmd_identifier <= 13)),
        # Tunnel Command
        ConditionalField(
            FlagsField("frame_control", 2, 4, [
                "ack_format",
                "security",
                "ack_req",
                "extended_hdr"
            ]),
            lambda pkt: pkt.cmd_identifier == 14),
        ConditionalField(
            BitEnumField("delivery_mode", 0, 2, {
                0: "unicast",
                1: "indirect",
                2: "broadcast",
                3: "group_addressing"
            }),
            lambda pkt: pkt.cmd_identifier == 14),
        ConditionalField(
            BitEnumField("aps_frametype", 1, 2, {
                0: "data",
                1: "command",
                2: "ack"
            }),
            lambda pkt: pkt.cmd_identifier == 14),
        ConditionalField(
            ByteField("counter", 0),
            lambda pkt: pkt.cmd_identifier == 14),
        # Verify-Key Command
        ConditionalField(
            StrFixedLenField("key_hash", None, 16),
            lambda pkt: pkt.cmd_identifier == 15),
    ]

    def guess_payload_class(self, payload):
        if self.cmd_identifier == 14:
            # Tunneled APS Auxiliary Header
            return ZigbeeSecurityHeader
        else:
            return Packet.guess_payload_class(self, payload)