class IEC104_IE_RCO(IEC104_IE_QOC):
    """
    RCO - regulating step command

    EN 60870-5-101:2003, sec. 7.2.6.17 (p. 50)
    """
    RCO_FLAG_STATE_INVALID_0 = 0
    RCO_FLAG_STATE_STEP_DOWN = 1
    RCO_FLAG_STATE_STEP_UP = 2
    RCO_FLAG_STATE_INVALID_3 = 3
    RCO_FLAGS = {
        RCO_FLAG_STATE_INVALID_0: 'invalid (0)',
        RCO_FLAG_STATE_STEP_DOWN: 'step down',
        RCO_FLAG_STATE_STEP_UP: 'step up',
        RCO_FLAG_STATE_INVALID_3: 'invalid (3)',
    }

    informantion_element_fields = IEC104_IE_QOC.informantion_element_fields + [
        BitEnumField('rcs', 0, 2, RCO_FLAGS)
    ]
class IEC104_IE_DCO(IEC104_IE_QOC):
    """
    DCO - double command

    EN 60870-5-101:2003, sec. 7.2.6.16 (p. 50)
    """
    DCS_FLAG_STATE_INVALID_0 = 0
    DCS_FLAG_STATE_OFF = 1
    DCS_FLAG_STATE_ON = 2
    DCS_FLAG_STATE_INVALID_3 = 3
    DCS_FLAGS = {
        DCS_FLAG_STATE_INVALID_0: 'invalid (0)',
        DCS_FLAG_STATE_OFF: 'off',
        DCS_FLAG_STATE_ON: 'on',
        DCS_FLAG_STATE_INVALID_3: 'invalid (3)',
    }

    informantion_element_fields = IEC104_IE_QOC.informantion_element_fields + [
        BitEnumField('dcs', 0, 2, DCS_FLAGS)
    ]
示例#3
0
class BTLE_DATA(Packet):
    name = "BTLE data header"
    fields_desc = [
        BitField("RFU", 0, 3),  # Unused
        BitField("MD", 0, 1),
        BitField("SN", 0, 1),
        BitField("NESN", 0, 1),
        BitEnumField("LLID", 0, 2, {
            1: "continue",
            2: "start",
            3: "control"
        }),
        ByteField(
            "len",
            None),  # BLE 4.2 and upwards can use 1 entire byte for length
    ]

    def post_build(self, p, pay):
        if self.len is None:
            p = p[:-1] + chb(len(pay))
        return p + pay

    def do_dissect_payload(self, s):
        if s is not None:
            cls = self.guess_payload_class(s)
            try:
                p = cls(s, _internal=1, _underlayer=self)
            except KeyboardInterrupt:
                raise
            except Exception:
                if conf.debug_dissector:
                    if issubtype(cls, Packet):
                        log_runtime.error("%s dissector failed" % cls.__name__)
                    else:
                        log_runtime.error(
                            "%s.guess_payload_class() returned [%s]" %
                            (self.__class__.__name__, repr(cls)))  # noqa: E501
                    if cls is not None:
                        raise
                p = conf.raw_layer(s, _internal=1, _underlayer=self)
            self.add_payload(p)
示例#4
0
class RPLDAGMCNSA(DAGMCObj):
    """
    DAG Metric: Node State and Attributes
    """
    name = "Node State and Attributes"
    fields_desc = [
        ByteEnumField("otype", 1, DAGMC_OBJTYPE),
        BitField("resflags", 0, 5),
        BitField("P", 0, 1),
        BitField("C", 0, 1),
        BitField("O", 0, 1),
        BitField("R", 0, 1),
        BitEnumField("A", 0, 3, AGG_RTMETRIC),
        BitField("prec", 0, 4),
        ByteField("len", None),
        # NSA Object Body Format
        ByteField("res", 0),
        BitField("flags", 0, 6),
        BitField("A2", 0, 1),
        BitField("O2", 0, 1)
    ]
示例#5
0
文件: aoe.py 项目: Saad-20/Arp-Spoof
class QueryConfigInformation(Packet):
    name = "Query Config Information"
    fields_desc = [
        ShortField("buffer_count", 0),
        ShortField("firmware", 0),
        ByteField("sector_count", 0),
        BitField("aoe", 0, 4),
        BitEnumField(
            "ccmd", 0, 4, {
                0: "Read config string",
                1: "Test config string",
                2: "Test config string prefix",
                3: "Set config string",
                4: "Force set config string"
            }),
        FieldLenField("config_length", None, length_of="config"),
        StrLenField("config", None, length_from=lambda x: x.config_length)
    ]

    def extract_padding(self, s):
        return "", s
示例#6
0
class ZigbeeAppDataPayloadStub(Packet):
    name = "Zigbee Application Layer Data Payload for Inter-PAN Transmission"
    fields_desc = [
        FlagsField("frame_control", 0, 4, ['reserved1', 'security', 'ack_req', 'extended_hdr']),  # noqa: E501
        BitEnumField("delivery_mode", 0, 2, {0: 'unicast', 2: 'broadcast', 3: 'group'}),  # noqa: E501
        BitField("frametype", 3, 2),  # value 0b11 (3) is a reserved frame type
        # Group Address present only when delivery mode field has a value of 0b11 (group delivery mode)  # noqa: E501
        ConditionalField(
            XLEShortField("group_addr", 0x0),  # 16-bit identifier of the group
            lambda pkt: pkt.getfieldval("delivery_mode") == 0b11
        ),
        # Cluster identifier
        EnumField("cluster", 0, _zcl_cluster_identifier, fmt="<H"),  # unsigned short (little-endian)  # noqa: E501
        # Profile identifier
        EnumField("profile", 0, _zcl_profile_identifier, fmt="<H"),
        # ZigBee Payload
        ConditionalField(
            StrField("data", ""),
            lambda pkt: pkt.frametype == 3
        ),
    ]
示例#7
0
class L2TP(Packet):
    name = "L2TP"
    fields_desc = [
        FlagsField(
            "hdr",
            0,
            12,
            [
                'res00',
                'res01',
                'res02',
                'res03',
                'priority',
                'offset',  # noqa: E501
                'res06',
                'sequence',
                'res08',
                'res09',
                'length',
                'control'
            ]),  # noqa: E501
        BitEnumField("version", 2, 4, {2: 'L2TPv2'}),
        ConditionalField(ShortField("len", None),
                         lambda pkt: pkt.hdr & 'control+length'),
        ShortField("tunnel_id", 0),
        ShortField("session_id", 0),
        ConditionalField(ShortField("ns", 0),
                         lambda pkt: pkt.hdr & 'sequence+control'),
        ConditionalField(ShortField("nr", 0),
                         lambda pkt: pkt.hdr & 'sequence+control'),
        ConditionalField(
            PadField(ShortField("offset", 0), 4, b"\x00"),
            lambda pkt: not (pkt.hdr & 'control') and pkt.hdr & 'offset')
    ]

    def post_build(self, pkt, pay):
        if self.len is None and self.hdr & 'control+length':
            tmp_len = len(pkt) + len(pay)
            pkt = pkt[:2] + struct.pack("!H", tmp_len) + pkt[4:]
        return pkt + pay
示例#8
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)
示例#9
0
文件: knx.py 项目: polybassa/scapy-1
class LcEMI(Packet):
    name = "L_cEMI"
    fields_desc = [
        FieldLenField("additional_information_length", 0, fmt="B",
                      length_of="additional_information"),
        StrLenField("additional_information", None,
                    length_from=lambda pkt: pkt.additional_information_length),
        # Controlfield 1 (1 byte made of 8*1 bits)
        BitEnumField("frame_type", 1, 1, {
            1: "standard"
        }),
        BitField("reserved_1", 0, 1),
        BitField("repeat_on_error", 1, 1),
        BitEnumField("broadcast_type", 1, 1, {
            1: "domain"
        }),
        BitEnumField("priority", 3, 2, {
            3: "low"
        }),
        BitField("ack_request", 0, 1),
        BitField("confirmation_error", 0, 1),
        # Controlfield 2 (1 byte made of 1+3+4 bits)
        BitEnumField("address_type", 1, 1, {
            1: "group"
        }),
        BitField("hop_count", 6, 3),
        BitField("extended_frame_format", 0, 4),
        KNXAddressField("source_address", None),
        KNXGroupField("destination_address", "1/2/3"),
        FieldLenField("npdu_length", 0x01, fmt="B", length_of="data"),
        # TPCI and APCI (2 byte made of 1+1+4+4+6 bits)
        BitEnumField("packet_type", 0, 1, {
            0: "data"
        }),
        BitEnumField("sequence_type", 0, 1, {
            0: "unnumbered"
        }),
        BitField("reserved_2", 0, 4),
        BitEnumField("acpi", 2, 4, KNX_ACPI_CODES),
        BitField("data", 0, 6)

    ]
示例#10
0
class DNSRRNSEC3(_DNSRRdummy):
    name = "DNS NSEC3 Resource Record"
    fields_desc = [
        DNSStrField("rrname", ""),
        ShortEnumField("type", 50, dnstypes),
        ShortEnumField("rclass", 1, dnsclasses),
        IntField("ttl", 0),
        ShortField("rdlen", None),
        ByteField("hashalg", 0),
        BitEnumField("flags", 0, 8, {1: "Opt-Out"}),
        ShortField("iterations", 0),
        FieldLenField("saltlength", 0, fmt="!B", length_of="salt"),
        StrLenField("salt", "", length_from=lambda x: x.saltlength),
        FieldLenField("hashlength",
                      0,
                      fmt="!B",
                      length_of="nexthashedownername"),  # noqa: E501
        StrLenField("nexthashedownername",
                    "",
                    length_from=lambda x: x.hashlength),  # noqa: E501
        RRlistField("typebitmaps", "")
    ]
示例#11
0
class RPLDAGMCNodeEnergy(DAGMCObj):
    """
    DAG Metric: Node Energy
    """
    name = "Node Energy"
    fields_desc = [
        ByteEnumField("otype", 2, DAGMC_OBJTYPE),
        BitField("resflags", 0, 5),
        BitField("P", 0, 1),
        BitField("C", 0, 1),
        BitField("O", 0, 1),
        BitField("R", 0, 1),
        BitEnumField("A", 0, 3, AGG_RTMETRIC),
        BitField("prec", 0, 4),
        ByteField("len", None),
        # NE Sub-Object Format
        BitField("flags", 0, 4),
        BitField("I", 0, 1),
        BitField("T", 0, 2),
        BitField("E", 0, 1),
        ByteField("E_E", 0)
    ]
示例#12
0
class USB(Packet):
    """
    Represents a USB packet saved by USBPcap.
    
    Based on packet format specified at http://desowin.org/usbpcap/captureformat.html.
    """
    name = "USBPcap"
    fields_desc = [
        LEShortField("headerLen", None),
        LELongField("irpId", None),
        LEIntField("status", None),

        LEShortField("function", None),
        ByteField("info", None),

        LEShortField("bus", 0),
        LEShortField("device", 0),

        BitEnumField("direction", 0, 1, {
            0: "OUT",
            1: "IN"
        }),
        BitField("endpoint", 0, 7),

        ByteEnumField("transfer", 0, {
            0: "isochronous",
            1: "interrupt",
            2: "control",
            3: "bulk"
        }),
        LEIntField("bodyLength", 0)
    ]

    def detail(self):
        if hasattr(self.payload, "detail"):
            return self.sprintf("USB ep=%USB.endpoint% %-3s,USB.direction%") + " | " + self.payload.detail()
        else:
            pass
示例#13
0
文件: zigbee.py 项目: mingqian/scapy
class ZigbeeClusterLibrary(Packet):
    name = "Zigbee Cluster Library (ZCL) Frame"
    fields_desc = [
        # Frame control (8 bits)
        BitField("reserved", 0, 3),
        BitField("disable_default_response", 0, 1),  # 0 default response command will be returned  # noqa: E501
        BitField("direction", 0, 1),  # 0 command sent from client to server; 1 command sent from server to client  # noqa: E501
        BitField("manufacturer_specific", 0, 1),  # 0 manufacturer code shall not be included in the ZCL frame  # noqa: E501
        # Frame Type
        # 0b00 command acts across the entire profile
        # 0b01 command is specific to a cluster
        # 0b10 - 0b11 reserved
        BitEnumField("zcl_frametype", 0, 2, {0: 'profile-wide', 1: 'cluster-specific', 2: 'reserved2', 3: 'reserved3'}),  # noqa: E501
        # Manufacturer code (0/16 bits) only present then manufacturer_specific field is set to 1  # noqa: E501
        ConditionalField(XLEShortField("manufacturer_code", 0x0),
                         lambda pkt: pkt.getfieldval("manufacturer_specific") == 1  # noqa: E501
                         ),
        # Transaction sequence number (8 bits)
        ByteField("transaction_sequence", 0),
        # Command identifier (8 bits): the cluster command
        ByteEnumField("command_identifier", 0, _zcl_command_frames),
    ]

    def guess_payload_class(self, payload):
        # Profile-wide commands
        if self.zcl_frametype == 0x00 and self.command_identifier == 0x00:
            return ZCLGeneralReadAttributes
        elif self.zcl_frametype == 0x00 and self.command_identifier == 0x01:
            return ZCLGeneralReadAttributesResponse
        # Cluster-specific commands
        elif self.zcl_frametype == 0x01 and self.command_identifier == 0x00 and self.direction == 0 and self.underlayer.cluster == 0x0700:  # "price"  # noqa: E501
            return ZCLPriceGetCurrentPrice
        elif self.zcl_frametype == 0x01 and self.command_identifier == 0x01 and self.direction == 0 and self.underlayer.cluster == 0x0700:  # "price"  # noqa: E501
            return ZCLPriceGetScheduledPrices
        elif self.zcl_frametype == 0x01 and self.command_identifier == 0x00 and self.direction == 1 and self.underlayer.cluster == 0x0700:  # "price"  # noqa: E501
            return ZCLPricePublishPrice
        else:
            return Packet.guess_payload_class(self, payload)
示例#14
0
文件: lldp.py 项目: yvyshneva/scapy
class LLDPDUGenericOrganisationSpecific(LLDPDU):

    ORG_UNIQUE_CODE_PNO = 0x000ecf
    ORG_UNIQUE_CODE_IEEE_802_1 = 0x0080c2
    ORG_UNIQUE_CODE_IEEE_802_3 = 0x00120f
    ORG_UNIQUE_CODE_TIA_TR_41_MED = 0x0012bb
    ORG_UNIQUE_CODE_HYTEC = 0x30b216

    ORG_UNIQUE_CODES = {
        ORG_UNIQUE_CODE_PNO: "PROFIBUS International (PNO)",
        ORG_UNIQUE_CODE_IEEE_802_1: "IEEE 802.1",
        ORG_UNIQUE_CODE_IEEE_802_3: "IEEE 802.3",
        ORG_UNIQUE_CODE_TIA_TR_41_MED: "TIA TR-41 Committee . Media Endpoint Discovery",  # noqa: E501
        ORG_UNIQUE_CODE_HYTEC: "Hytec Geraetebau GmbH"
    }

    fields_desc = [
        BitEnumField('_type', 127, 7, LLDPDU.TYPES),
        BitFieldLenField('_length', None, 9, length_of='data', adjust=lambda pkt, x: len(pkt.data) + 4),  # noqa: E501
        ThreeBytesEnumField('org_code', 0, ORG_UNIQUE_CODES),
        ByteField('subtype', 0x00),
        XStrLenField('data', '', length_from=lambda pkt: pkt._length - 4)
    ]
示例#15
0
class ExpectedSubmodule(Packet):
    """Description of a submodule in an API of an expected submodule"""
    name = "Submodule"
    fields_desc = [
        XShortField("SubslotNumber", 0),
        XIntField("SubmoduleIdentNumber", 0),
        # Submodule Properties
        XByteField("SubmoduleProperties_reserved_2", 0),
        BitField("SubmoduleProperties_reserved_1", 0, 2),
        BitField("SubmoduleProperties_DiscardIOXS", 0, 1),
        BitField("SubmoduleProperties_ReduceOutputSubmoduleDataLength", 0, 1),
        BitField("SubmoduleProperties_ReduceInputSubmoduleDataLength", 0, 1),
        BitField("SubmoduleProperties_SharedInput", 0, 1),
        BitEnumField("SubmoduleProperties_Type", 0, 2,
                     ["NO_IO", "INPUT", "OUTPUT", "INPUT_OUTPUT"]),
        PacketListField(
            "DataDescription", [], ExpectedSubmoduleDataDescription,
            count_from=lambda p: 2 if p.SubmoduleProperties_Type == 3 else 1
        ),
    ]

    def extract_padding(self, s):
        return None, s  # No extra payload
示例#16
0
class AlarmCRBlockReq(Block):
    """Alarm CR block request"""
    fields_desc = [
        BlockHeader,
        XShortEnumField("AlarmCRType", 1, ALARM_CR_TYPE),
        ShortField("LT", 0x8892),
        BitField("AlarmCRProperties_Priority", 0, 1),
        BitEnumField("AlarmCRProperties_Transport", 0, 1, ALARM_CR_TRANSPORT),
        BitField("AlarmCRProperties_Reserved1", 0, 22),
        BitField("AlarmCRProperties_Reserved2", 0, 8),
        ShortField("RTATimeoutFactor", 0x0001),
        ShortField("RTARetries", 0x0003),
        ShortField("LocalAlarmReference", 0x0003),
        ShortField("MaxAlarmDataLength", 0x00C8),
        ShortField("AlarmCRTagHeaderHigh", 0xC000),
        ShortField("AlarmCRTagHeaderLow", 0xA000),
    ]
    # default block_type value
    block_type = 0x0103

    def post_build(self, p, pay):
        # Set the LT based on transport
        if self.AlarmCRProperties_Transport == 0x1:
            p = p[:8] + struct.pack("!H", 0x0800) + p[10:]

        return Block.post_build(self, p, pay)

    def get_response(self):
        """Generate the response block of this request.
        Careful: it only sets the fields which can be set from the request
        """
        res = AlarmCRBlockRes()
        for field in ["AlarmCRType", "LocalAlarmReference"]:
            res.setfieldval(field, self.getfieldval(field))

        res.block_type = self.block_type + 0x8000
        return res
示例#17
0
文件: pim.py 项目: chenbaolou/scapy
class PIMv2Hdr(Packet):
    name = "Protocol Independent Multicast Version 2 Header"
    fields_desc = [
        BitField("version", 2, 4),
        BitEnumField("type", 0, 4, PIM_TYPE),
        ByteField("reserved", 0),
        XShortField("chksum", None)
    ]

    def post_build(self, p, pay):
        """
        Called implicitly before a packet is sent to compute and
         place PIM checksum.

        Parameters:
          self    The instantiation of an PIMv2Hdr class
          p       The PIMv2Hdr message in hex in network byte order
          pay     Additional payload for the PIMv2Hdr message
        """
        p += pay
        if self.chksum is None:
            ck = checksum(p)
            p = p[:2] + struct.pack("!H", ck) + p[4:]
        return p
class IEC104_IE_AFQ:
    """
    AFQ - acknowledge file or section qualifier

    EN 60870-5-101:2003, sec. 7.2.6.32 (p. 55)
    """
    ACK_FILE_OR_SEC_FLAG_UNUSED = 0
    ACK_FILE_OR_SEC_FLAG_POSITIVE_ACK_FILE_TRANSFER = 1
    ACK_FILE_OR_SEC_FLAG_NEGATIVE_ACK_FILE_TRANSFER = 2
    ACK_FILE_OR_SEC_FLAG_POSITIVE_ACK_SECTION_TRANSFER = 3
    ACK_FILE_OR_SEC_FLAG_NEGATIVE_ACK_SECTION_TRANSFER = 4

    ACK_FILE_OR_SEC_FLAGS = {
        ACK_FILE_OR_SEC_FLAG_UNUSED:
        'unused',
        ACK_FILE_OR_SEC_FLAG_POSITIVE_ACK_FILE_TRANSFER:
        'positive acknowledge'
        ' file transfer',
        ACK_FILE_OR_SEC_FLAG_NEGATIVE_ACK_FILE_TRANSFER:
        'negative acknowledge'
        ' file transfer',
        ACK_FILE_OR_SEC_FLAG_POSITIVE_ACK_SECTION_TRANSFER:
        'positive '
        'acknowledge '
        'section transfer',
        ACK_FILE_OR_SEC_FLAG_NEGATIVE_ACK_SECTION_TRANSFER:
        'negative '
        'acknowledge '
        'section transfer'
    }

    ACK_FILE_OR_SEC_ERR_FLAG_UNUSED = 0
    ACK_FILE_OR_SEC_ERR_FLAG_REQ_MEM_AREA_NO_AVAIL = 1
    ACK_FILE_OR_SEC_ERR_FLAG_INVALID_CHECKSUM = 2
    ACK_FILE_OR_SEC_ERR_FLAG_UNEXPECTED_COMMUNICATION_SERVICE = 3
    ACK_FILE_OR_SEC_ERR_FLAG_UNEXPECTED_FILENAME = 4
    ACK_FILE_OR_SEC_ERR_FLAG_UNEXPECTED_SECTION_NAME = 5

    ACK_FILE_OR_SEC_ERR_FLAGS = {
        ACK_FILE_OR_SEC_ERR_FLAG_UNUSED:
        'unused',
        ACK_FILE_OR_SEC_ERR_FLAG_REQ_MEM_AREA_NO_AVAIL:
        'requested memory '
        'area not available',
        ACK_FILE_OR_SEC_ERR_FLAG_INVALID_CHECKSUM:
        'invalid checksum',
        ACK_FILE_OR_SEC_ERR_FLAG_UNEXPECTED_COMMUNICATION_SERVICE:
        'unexpected'
        ' communica'
        'tion '
        'service',
        ACK_FILE_OR_SEC_ERR_FLAG_UNEXPECTED_FILENAME:
        'unexpected file name',
        ACK_FILE_OR_SEC_ERR_FLAG_UNEXPECTED_SECTION_NAME:
        'unexpected '
        'section name'
    }

    GENERATED_ATTRIBUTES = [
        ('ACK_FILE_OR_SEC_FLAG_COMPATIBLE_RESERVED', 'compatible reserved',
         ACK_FILE_OR_SEC_FLAGS, 5, 10),
        ('ACK_FILE_OR_SEC_FLAG_PRIVATE_RESERVED', 'private reserved',
         ACK_FILE_OR_SEC_FLAGS, 11, 15),
        ('ACK_FILE_OR_SEC_ERR_FLAG_COMPATIBLE_RESERVED', 'compatible reserved',
         ACK_FILE_OR_SEC_ERR_FLAGS, 6, 10),
        ('ACK_FILE_OR_SEC_ERR_FLAG_PRIVATE_RESERVED', 'private reserved',
         ACK_FILE_OR_SEC_ERR_FLAGS, 11, 15)
    ]

    informantion_element_fields = [
        BitEnumField('errors', 0, 4, ACK_FILE_OR_SEC_ERR_FLAGS),
        BitEnumField('ack_file_or_sec', 0, 4, ACK_FILE_OR_SEC_FLAGS)
    ]
class IEC104_IE_SCQ:
    """
    SCQ - select and call qualifier

    EN 60870-5-101:2003, sec. 7.2.6.30 (p. 55)
    """
    SEL_CALL_FLAG_UNUSED = 0
    SEL_CALL_FLAG_FILE_SELECT = 1
    SEL_CALL_FLAG_FILE_REQUEST = 2
    SEL_CALL_FLAG_FILE_ABORT = 3
    SEL_CALL_FLAG_FILE_DELETE = 4
    SEL_CALL_FLAG_SECTION_SELECTION = 5
    SEL_CALL_FLAG_SECTION_REQUEST = 6
    SEL_CALL_FLAG_SECTION_ABORT = 7

    SEL_CALL_FLAGS = {
        SEL_CALL_FLAG_UNUSED: 'unused',
        SEL_CALL_FLAG_FILE_SELECT: 'file select',
        SEL_CALL_FLAG_FILE_REQUEST: 'file request',
        SEL_CALL_FLAG_FILE_ABORT: 'file abort',
        SEL_CALL_FLAG_FILE_DELETE: 'file delete',
        SEL_CALL_FLAG_SECTION_SELECTION: 'section selection',
        SEL_CALL_FLAG_SECTION_REQUEST: 'section request',
        SEL_CALL_FLAG_SECTION_ABORT: 'section abort'
    }

    SEL_CALL_ERR_FLAG_UNUSED = 0
    SEL_CALL_ERR_FLAG_REQ_MEM_AREA_NO_AVAIL = 1
    SEL_CALL_ERR_FLAG_INVALID_CHECKSUM = 2
    SEL_CALL_ERR_FLAG_UNEXPECTED_COMMUNICATION_SERVICE = 3
    SEL_CALL_ERR_FLAG_UNEXPECTED_FILENAME = 4
    SEL_CALL_ERR_FLAG_UNEXPECTED_SECTION_NAME = 5
    SEL_CALL_ERR_FLAG_COMPATIBLE_RESERVED_6 = 6
    SEL_CALL_ERR_FLAG_COMPATIBLE_RESERVED_7 = 7
    SEL_CALL_ERR_FLAG_COMPATIBLE_RESERVED_8 = 8
    SEL_CALL_ERR_FLAG_COMPATIBLE_RESERVED_9 = 9
    SEL_CALL_ERR_FLAG_COMPATIBLE_RESERVED_10 = 10
    SEL_CALL_ERR_FLAG_PRIVATE_RESERVED_11 = 11
    SEL_CALL_ERR_FLAG_PRIVATE_RESERVED_12 = 12
    SEL_CALL_ERR_FLAG_PRIVATE_RESERVED_13 = 13
    SEL_CALL_ERR_FLAG_PRIVATE_RESERVED_14 = 14
    SEL_CALL_ERR_FLAG_PRIVATE_RESERVED_15 = 15

    SEL_CALL_ERR_FLAGS = {
        SEL_CALL_ERR_FLAG_UNUSED:
        'unused',
        SEL_CALL_ERR_FLAG_REQ_MEM_AREA_NO_AVAIL:
        'requested memory area '
        'not available',
        SEL_CALL_ERR_FLAG_INVALID_CHECKSUM:
        'invalid checksum',
        SEL_CALL_ERR_FLAG_UNEXPECTED_COMMUNICATION_SERVICE:
        'unexpected '
        'communication '
        'service',
        SEL_CALL_ERR_FLAG_UNEXPECTED_FILENAME:
        'unexpected file name',
        SEL_CALL_ERR_FLAG_UNEXPECTED_SECTION_NAME:
        'unexpected section name'
    }

    GENERATED_ATTRIBUTES = [('SEL_CALL_FLAG_COMPATIBLE_RESERVED',
                             'compatible reserved', SEL_CALL_FLAGS, 8, 10),
                            ('SEL_CALL_FLAG_PRIVATE_RESERVED',
                             'private reserved', SEL_CALL_FLAGS, 11, 15),
                            ('SEL_CALL_ERR_FLAG_COMPATIBLE_RESERVED',
                             'compatible reserved', SEL_CALL_ERR_FLAGS, 6, 10),
                            ('SEL_CALL_ERR_FLAG_PRIVATE_RESERVED',
                             'private reserved', SEL_CALL_ERR_FLAGS, 11, 15)]

    informantion_element_fields = [
        BitEnumField('errors', 0, 4, SEL_CALL_ERR_FLAGS),
        BitEnumField('select_call', 0, 4, SEL_CALL_FLAGS)
    ]
class Dot11(Packet):
    name = "802.11"
    fields_desc = [
        BitField("subtype", 0, 4),
        BitEnumField("type", 0, 2,
                     ["Management", "Control", "Data", "Reserved"]),
        BitField("proto", 0, 2),
        FlagsField("FCfield", 0, 8, [
            "to-DS", "from-DS", "MF", "retry", "pw-mgt", "MD", "protected",
            "order"
        ]),
        ShortField("ID", 0),
        MACField("addr1", ETHER_ANY),
        ConditionalField(
            MACField("addr2", ETHER_ANY),
            lambda pkt:
            (pkt.type != 1 or pkt.subtype in [0x8, 0x9, 0xa, 0xb, 0xe, 0xf]),
        ),
        ConditionalField(
            MACField("addr3", ETHER_ANY),
            lambda pkt: pkt.type in [0, 2],
        ),
        ConditionalField(LEShortField("SC", 0), lambda pkt: pkt.type != 1),
        ConditionalField(
            MACField("addr4", ETHER_ANY),
            lambda pkt:
            (pkt.type == 2 and pkt.FCfield & 3 == 3),  # from-DS+to-DS
        )
    ]

    def mysummary(self):
        # Supports both Dot11 and Dot11FCS
        # return self.sprintf("802.11 %%%s.type%% %%%s.subtype%% %%%s.addr2%% > %%%s.addr1%%" % ((self.__class__.__name__,) * 4))  # noqa: E501
        return self.sprintf("802.11 %%%s.type%% %%%s.subtype%%" %
                            ((self.__class__.__name__, ) * 2))  # noqa: E501

    def guess_payload_class(self, payload):
        if self.type == 0x02 and (0x08 <= self.subtype <= 0xF
                                  and self.subtype != 0xD):  # noqa: E501
            return Dot11QoS
        elif self.FCfield.protected:
            # When a frame is handled by encryption, the Protected Frame bit
            # (previously called WEP bit) is set to 1, and the Frame Body
            # begins with the appropriate cryptographic header.
            return Dot11Encrypted
        else:
            return Packet.guess_payload_class(self, payload)

    def answers(self, other):
        if isinstance(other, Dot11):
            if self.type == 0:  # management
                if self.addr1.lower() != other.addr2.lower(
                ):  # check resp DA w/ req SA  # noqa: E501
                    return 0
                if (other.subtype, self.subtype) in [(0, 1), (2, 3), (4, 5)]:
                    return 1
                if self.subtype == other.subtype == 11:  # auth
                    return self.payload.answers(other.payload)
            elif self.type == 1:  # control
                return 0
            elif self.type == 2:  # data
                return self.payload.answers(other.payload)
            elif self.type == 3:  # reserved
                return 0
        return 0

    def unwep(self, key=None, warn=1):
        if self.FCfield & 0x40 == 0:
            if warn:
                warning("No WEP to remove")
            return
        if isinstance(self.payload.payload, NoPayload):
            if key or conf.wepkey:
                self.payload.decrypt(key)
            if isinstance(self.payload.payload, NoPayload):
                if warn:
                    warning("Dot11 can't be decrypted. Check conf.wepkey.")
                return
        self.FCfield &= ~0x40
        self.payload = self.payload.payload
示例#21
0
class DNS(Packet):
    name = "DNS"
    fields_desc = [
        ConditionalField(ShortField("length", None),
                         lambda p: isinstance(p.underlayer, TCP)),
        ShortField("id", 0),
        BitField("qr", 0, 1),
        BitEnumField("opcode", 0, 4, {
            0: "QUERY",
            1: "IQUERY",
            2: "STATUS"
        }),
        BitField("aa", 0, 1),
        BitField("tc", 0, 1),
        BitField("rd", 1, 1),
        BitField("ra", 0, 1),
        BitField("z", 0, 1),
        # AD and CD bits are defined in RFC 2535
        BitField("ad", 0, 1),  # Authentic Data
        BitField("cd", 0, 1),  # Checking Disabled
        BitEnumField(
            "rcode", 0, 4, {
                0: "ok",
                1: "format-error",
                2: "server-failure",
                3: "name-error",
                4: "not-implemented",
                5: "refused"
            }),
        DNSRRCountField("qdcount", None, "qd"),
        DNSRRCountField("ancount", None, "an"),
        DNSRRCountField("nscount", None, "ns"),
        DNSRRCountField("arcount", None, "ar"),
        DNSQRField("qd", "qdcount", DNSQR()),
        DNSRRField("an", "ancount", None),
        DNSRRField("ns", "nscount", None),
        DNSRRField("ar", "arcount", None, 0),
    ]

    def answers(self, other):
        return (isinstance(other, DNS) and self.id == other.id and self.qr == 1
                and other.qr == 0)

    def mysummary(self):
        name = ""
        if self.qr:
            type = "Ans"
            if self.ancount > 0 and isinstance(self.an, DNSRR):
                name = ' "%s"' % self.an.rdata
        else:
            type = "Qry"
            if self.qdcount > 0 and isinstance(self.qd, DNSQR):
                name = ' "%s"' % self.qd.qname
        return 'DNS %s%s ' % (type, name)

    def post_build(self, pkt, pay):
        if isinstance(self.underlayer, TCP) and self.length is None:
            pkt = struct.pack("!H", len(pkt) - 2) + pkt[2:]
        return pkt + pay

    def compress(self):
        """Return the compressed DNS packet (using `dns_compress()`"""
        return dns_compress(self)

    def pre_dissect(self, s):
        """
        Check that a valid DNS over TCP message can be decoded
        """
        if isinstance(self.underlayer, TCP):

            # Compute the length of the DNS packet
            if len(s) >= 2:
                dns_len = struct.unpack("!H", s[:2])[0]
            else:
                message = "Malformed DNS message: too small!"
                log_runtime.info(message)
                raise Scapy_Exception(message)

            # Check if the length is valid
            if dns_len < 14 or len(s) < dns_len:
                message = "Malformed DNS message: invalid length!"
                log_runtime.info(message)
                raise Scapy_Exception(message)

        return s
示例#22
0
class LoWPAN_IPHC(Packet):
    """6LoWPAN IPv6 header compressed packets

    It follows the implementation of draft-ietf-6lowpan-hc-15.
    """
    # the LOWPAN_IPHC encoding utilizes 13 bits, 5 dispatch type
    name = "LoWPAN IP Header Compression Packet"
    _address_modes = ["Unspecified", "1", "16-bits inline", "Compressed"]
    _state_mode = ["Stateless", "Stateful"]
    fields_desc = [
        # dispatch
        BitField("_reserved", 0x03, 3),
        BitField("tf", 0x0, 2),
        BitEnumField("nh", 0x0, 1, ["Inline", "Compressed"]),
        BitField("hlim", 0x0, 2),
        BitEnumField("cid", 0x0, 1, [False, True]),
        BitEnumField("sac", 0x0, 1, _state_mode),
        BitEnumField("sam", 0x0, 2, _address_modes),
        BitEnumField("m", 0x0, 1, [False, True]),
        BitEnumField("dac", 0x0, 1, _state_mode),
        BitEnumField("dam", 0x0, 2, _address_modes),
        ConditionalField(ByteField("_contextIdentifierExtension", 0x0),
                         lambda pkt: pkt.cid == 0x1),
        # TODO: THIS IS WRONG!!!!!
        BitVarSizeField("tc_ecn",
                        0,
                        calculate_length=lambda pkt: tf_last_attempt(pkt)[0]
                        ),  # noqa: E501
        BitVarSizeField("tc_dscp",
                        0,
                        calculate_length=lambda pkt: tf_last_attempt(pkt)[1]
                        ),  # noqa: E501
        BitVarSizeField("_padd",
                        0,
                        calculate_length=lambda pkt: tf_last_attempt(pkt)[2]
                        ),  # noqa: E501
        BitVarSizeField("flowlabel",
                        0,
                        calculate_length=lambda pkt: tf_last_attempt(pkt)[3]
                        ),  # noqa: E501

        # NH
        ConditionalField(ByteField("_nhField", 0x0), lambda pkt: not pkt.nh),
        # HLIM: Hop Limit: if it's 0
        ConditionalField(ByteField("_hopLimit", 0x0),
                         lambda pkt: pkt.hlim == 0x0),
        IP6FieldLenField("sourceAddr", "::", 0, length_of=source_addr_mode2),
        IP6FieldLenField(
            "destinyAddr", "::", 0,
            length_of=destiny_addr_mode),  # problem when it's 0  # noqa: E501

        # LoWPAN_UDP Header Compression ########################################  # noqa: E501
        # TODO: IMPROVE!!!!!
        ConditionalField(
            FlagsField(
                "header_compression", 0, 8,
                ["A", "B", "C", "D", "E", "C", "PS", "PD"]),  # noqa: E501
            lambda pkt: pkt.nh),
        ConditionalField(
            BitFieldLenField(
                "udpSourcePort",
                0x0,
                16,
                length_of=lambda pkt: nhc_port(pkt)[0]),  # noqa: E501
            # ShortField("udpSourcePort", 0x0),
            lambda pkt: pkt.nh and pkt.header_compression & 0x2 == 0x0),
        ConditionalField(
            BitFieldLenField(
                "udpDestinyPort",
                0x0,
                16,
                length_of=lambda pkt: nhc_port(pkt)[1]),  # noqa: E501
            lambda pkt: pkt.nh and pkt.header_compression & 0x1 == 0x0),
        ConditionalField(
            XShortField("udpChecksum", 0x0),
            lambda pkt: pkt.nh and pkt.header_compression & 0x4 == 0x0),
    ]

    def post_dissect(self, data):
        """dissect the IPv6 package compressed into this IPHC packet.

        The packet payload needs to be decompressed and depending on the
        arguments, several conversions should be done.
        """

        # uncompress payload
        packet = IPv6()
        packet.version = IPHC_DEFAULT_VERSION
        packet.tc, packet.fl = self._getTrafficClassAndFlowLabel()
        if not self.nh:
            packet.nh = self._nhField
        # HLIM: Hop Limit
        if self.hlim == 0:
            packet.hlim = self._hopLimit
        elif self.hlim == 0x1:
            packet.hlim = 1
        elif self.hlim == 0x2:
            packet.hlim = 64
        else:
            packet.hlim = 255
        # TODO: Payload length can be inferred from lower layers from either the  # noqa: E501
        # 6LoWPAN Fragmentation header or the IEEE802.15.4 header

        packet.src = self.decompressSourceAddr(packet)
        packet.dst = self.decompressDestinyAddr(packet)

        if self.nh == 1:
            # The Next Header field is compressed and the next header is
            # encoded using LOWPAN_NHC

            udp = UDP()
            if self.header_compression and \
               self.header_compression & 0x4 == 0x0:
                udp.chksum = self.udpChecksum

            s, d = nhc_port(self)
            if s == 16:
                udp.sport = self.udpSourcePort
            elif s == 8:
                udp.sport = 0xF000 + s
            elif s == 4:
                udp.sport = 0xF0B0 + s
            if d == 16:
                udp.dport = self.udpDestinyPort
            elif d == 8:
                udp.dport = 0xF000 + d
            elif d == 4:
                udp.dport = 0xF0B0 + d

            packet.payload = udp / data
            data = raw(packet)
        # else self.nh == 0 not necessary
        elif self._nhField & 0xE0 == 0xE0:  # IPv6 Extension Header Decompression  # noqa: E501
            warning('Unimplemented: IPv6 Extension Header decompression'
                    )  # noqa: E501
            packet.payload = conf.raw_layer(data)
            data = raw(packet)
        else:
            packet.payload = conf.raw_layer(data)
            data = raw(packet)

        return Packet.post_dissect(self, data)

    def decompressDestinyAddr(self, packet):
        try:
            tmp_ip = inet_pton(socket.AF_INET6, self.destinyAddr)
        except socket.error:
            tmp_ip = b"\x00" * 16

        if self.m == 0 and self.dac == 0:
            if self.dam == 0:
                pass
            elif self.dam == 1:
                tmp_ip = LINK_LOCAL_PREFIX[0:8] + tmp_ip[-8:]
            elif self.dam == 2:
                tmp_ip = LINK_LOCAL_PREFIX[
                    0:8] + b"\x00\x00\x00\xff\xfe\x00" + tmp_ip[
                        -2:]  # noqa: E501
            """else: #self.dam == 3
                raise Exception('Unimplemented')"""

        elif self.m == 0 and self.dac == 1:
            if self.dam == 0:
                raise Exception('Reserved')
            elif self.dam == 0x3:
                underlayer = self.underlayer
                while underlayer is not None and not isinstance(
                        underlayer, Dot15d4Data):  # noqa: E501
                    underlayer = underlayer.underlayer
                if type(underlayer) == Dot15d4Data:
                    if underlayer.underlayer.fcf_destaddrmode == 3:
                        tmp_ip = LINK_LOCAL_PREFIX[0:8] + struct.pack(
                            ">Q", underlayer.dest_addr)  # noqa: E501
                        # Turn off the bit 7.
                        tmp_ip = tmp_ip[0:8] + struct.pack(
                            "B", (orb(tmp_ip[8])
                                  ^ 0x2)) + tmp_ip[9:16]  # noqa: E501
                    elif underlayer.underlayer.fcf_destaddrmode == 2:
                        tmp_ip = LINK_LOCAL_PREFIX[0:8] + \
                            b"\x00\x00\x00\xff\xfe\x00" + \
                            struct.pack(">Q", underlayer.dest_addr)[6:]
                else:
                    # Most of the times, it's necessary the IEEE 802.15.4 data to extract this address  # noqa: E501
                    raise Exception(
                        'Unimplemented: IP Header is contained into IEEE 802.15.4 frame, in this case it\'s not available.'
                    )  # noqa: E501
            elif self.dam not in [0x1, 0x2]:
                warning("Unknown destiny address compression mode !")
        elif self.m == 1 and self.dac == 0:
            if self.dam == 0:
                raise Exception("unimplemented")
            elif self.dam == 1:
                tmp = b"\xff" + chb(tmp_ip[16 - destiny_addr_mode(self)])
                tmp_ip = tmp + b"\x00" * 9 + tmp_ip[-5:]
            elif self.dam == 2:
                tmp = b"\xff" + chb(tmp_ip[16 - destiny_addr_mode(self)])
                tmp_ip = tmp + b"\x00" * 11 + tmp_ip[-3:]
            else:  # self.dam == 3:
                tmp_ip = b"\xff\x02" + b"\x00" * 13 + tmp_ip[-1:]
        elif self.m == 1 and self.dac == 1:
            if self.dam == 0x0:
                raise Exception(
                    "Unimplemented: I didn't understand the 6lowpan specification"
                )  # noqa: E501
            else:  # all the others values
                raise Exception("Reserved value by specification.")

        self.destinyAddr = inet_ntop(socket.AF_INET6, tmp_ip)
        return self.destinyAddr

    def compressSourceAddr(self, ipv6):
        tmp_ip = inet_pton(socket.AF_INET6, ipv6.src)

        if self.sac == 0:
            if self.sam == 0x0:
                tmp_ip = tmp_ip
            elif self.sam == 0x1:
                tmp_ip = tmp_ip[8:16]
            elif self.sam == 0x2:
                tmp_ip = tmp_ip[14:16]
            else:  # self.sam == 0x3:
                pass
        else:  # self.sac == 1
            if self.sam == 0x0:
                tmp_ip = b"\x00" * 16
            elif self.sam == 0x1:
                tmp_ip = tmp_ip[8:16]
            elif self.sam == 0x2:
                tmp_ip = tmp_ip[14:16]

        self.sourceAddr = inet_ntop(socket.AF_INET6, b"\x00" *
                                    (16 - len(tmp_ip)) + tmp_ip)  # noqa: E501
        return self.sourceAddr

    def compressDestinyAddr(self, ipv6):
        tmp_ip = inet_pton(socket.AF_INET6, ipv6.dst)

        if self.m == 0 and self.dac == 0:
            if self.dam == 0x0:
                tmp_ip = tmp_ip
            elif self.dam == 0x1:
                tmp_ip = b"\x00" * 8 + tmp_ip[8:16]
            elif self.dam == 0x2:
                tmp_ip = b"\x00" * 14 + tmp_ip[14:16]
        elif self.m == 0 and self.dac == 1:
            if self.dam == 0x1:
                tmp_ip = b"\x00" * 8 + tmp_ip[8:16]
            elif self.dam == 0x2:
                tmp_ip = b"\x00" * 14 + tmp_ip[14:16]
        elif self.m == 1 and self.dac == 0:
            if self.dam == 0x1:
                tmp_ip = b"\x00" * 10 + tmp_ip[1:2] + tmp_ip[11:16]
            elif self.dam == 0x2:
                tmp_ip = b"\x00" * 12 + tmp_ip[1:2] + tmp_ip[13:16]
            elif self.dam == 0x3:
                tmp_ip = b"\x00" * 15 + tmp_ip[15:16]
        elif self.m == 1 and self.dac == 1:
            raise Exception('Unimplemented')

        self.destinyAddr = inet_ntop(socket.AF_INET6, tmp_ip)

    def decompressSourceAddr(self, packet):
        try:
            tmp_ip = inet_pton(socket.AF_INET6, self.sourceAddr)
        except socket.error:
            tmp_ip = b"\x00" * 16

        if self.sac == 0:
            if self.sam == 0x0:
                pass
            elif self.sam == 0x1:
                tmp_ip = LINK_LOCAL_PREFIX[0:8] + tmp_ip[
                    16 - source_addr_mode2(self):16]  # noqa: E501
            elif self.sam == 0x2:
                tmp = LINK_LOCAL_PREFIX[0:8] + b"\x00\x00\x00\xff\xfe\x00"
                tmp_ip = tmp + tmp_ip[16 - source_addr_mode2(self):16]
            elif self.sam == 0x3:  # EXTRACT ADDRESS FROM Dot15d4
                underlayer = self.underlayer
                if underlayer is not None:
                    while underlayer is not None and not isinstance(
                            underlayer, Dot15d4Data):  # noqa: E501
                        underlayer = underlayer.underlayer
                    assert type(underlayer) == Dot15d4Data
                    if underlayer.underlayer.fcf_srcaddrmode == 3:
                        tmp_ip = LINK_LOCAL_PREFIX[0:8] + struct.pack(
                            ">Q", underlayer.src_addr)  # noqa: E501
                        # Turn off the bit 7.
                        tmp_ip = tmp_ip[0:8] + struct.pack(
                            "B", (orb(tmp_ip[8])
                                  ^ 0x2)) + tmp_ip[9:16]  # noqa: E501
                    elif underlayer.underlayer.fcf_srcaddrmode == 2:
                        tmp_ip = LINK_LOCAL_PREFIX[0:8] + \
                            b"\x00\x00\x00\xff\xfe\x00" + \
                            struct.pack(">Q", underlayer.src_addr)[6:]
                else:
                    # Most of the times, it's necessary the IEEE 802.15.4 data to extract this address  # noqa: E501
                    raise Exception(
                        'Unimplemented: IP Header is contained into IEEE 802.15.4 frame, in this case it\'s not available.'
                    )  # noqa: E501
            else:
                warning("Unknown source address compression mode !")
        else:  # self.sac == 1:
            if self.sam == 0x0:
                pass
            elif self.sam == 0x2:
                # TODO: take context IID
                tmp = LINK_LOCAL_PREFIX[0:8] + b"\x00\x00\x00\xff\xfe\x00"
                tmp_ip = tmp + tmp_ip[16 - source_addr_mode2(self):16]
            elif self.sam == 0x3:
                tmp_ip = LINK_LOCAL_PREFIX[
                    0:8] + b"\x00" * 8  # TODO: CONTEXT ID  # noqa: E501
            else:
                raise Exception('Unimplemented')
        self.sourceAddr = inet_ntop(socket.AF_INET6, tmp_ip)
        return self.sourceAddr

    def guess_payload_class(self, payload):
        if self.underlayer and isinstance(
                self.underlayer,
            (LoWPANFragmentationFirst,
             LoWPANFragmentationSubsequent)):  # noqa: E501
            return Raw
        return IPv6

    def do_build(self):
        if not isinstance(self.payload, IPv6):
            return Packet.do_build(self)
        ipv6 = self.payload

        self._reserved = 0x03

        # NEW COMPRESSION TECHNIQUE!
        # a ) Compression Techniques

        # 1. Set Traffic Class
        if self.tf == 0x0:
            self.tc_ecn = ipv6.tc >> 6
            self.tc_dscp = ipv6.tc & 0x3F
            self.flowlabel = ipv6.fl
        elif self.tf == 0x1:
            self.tc_ecn = ipv6.tc >> 6
            self.flowlabel = ipv6.fl
        elif self.tf == 0x2:
            self.tc_ecn = ipv6.tc >> 6
            self.tc_dscp = ipv6.tc & 0x3F
        else:  # self.tf == 0x3:
            pass  # no field is set

        # 2. Next Header
        if self.nh == 0x0:
            self.nh = 0  # ipv6.nh
        elif self.nh == 0x1:
            self.nh = 0  # disable compression
            # The Next Header field is compressed and the next header is encoded using LOWPAN_NHC, which is discussed in Section 4.1.  # noqa: E501
            warning(
                'Next header compression is not implemented yet ! Will be ignored'
            )  # noqa: E501

        # 3. HLim
        if self.hlim == 0x0:
            self._hopLimit = ipv6.hlim
        else:  # if hlim is 1, 2 or 3, there are nothing to do!
            pass

        # 4. Context (which context to use...)
        if self.cid == 0x0:
            pass
        else:
            # TODO: Context Unimplemented yet in my class
            self._contextIdentifierExtension = 0

        # 5. Compress Source Addr
        self.compressSourceAddr(ipv6)
        self.compressDestinyAddr(ipv6)

        return Packet.do_build(self)

    def do_build_payload(self):
        if self.header_compression and\
           self.header_compression & 240 == 240:  # TODO: UDP header IMPROVE
            return raw(self.payload)[40 + 16:]
        else:
            return raw(self.payload)[40:]

    def _getTrafficClassAndFlowLabel(self):
        """Page 6, draft feb 2011 """
        if self.tf == 0x0:
            return (self.tc_ecn << 6) + self.tc_dscp, self.flowlabel
        elif self.tf == 0x1:
            return (self.tc_ecn << 6), self.flowlabel
        elif self.tf == 0x2:
            return (self.tc_ecn << 6) + self.tc_dscp, 0
        else:
            return 0, 0
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
示例#24
0
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),
    ]
示例#25
0
class LLDPDUManagementAddress(LLDPDU):
    """
    ieee 802.1ab-2016 - sec. 8.5.9 / p. 32

    currently only 0x00..0x1e are used by standards, no way to
    use anything > 0xff as management address subtype is only
    one octet wide

    see https://www.iana.org/assignments/address-family-numbers/address-family-numbers.xhtml  # noqa: E501
    """
    IANA_ADDRESS_FAMILY_NUMBERS = {
        0x00: 'other',
        0x01: 'IPv4',
        0x02: 'IPv6',
        0x03: 'NSAP',
        0x04: 'HDLC',
        0x05: 'BBN',
        0x06: '802',
        0x07: 'E.163',
        0x08: 'E.164',
        0x09: 'F.69',
        0x0a: 'X.121',
        0x0b: 'IPX',
        0x0c: 'Appletalk',
        0x0d: 'Decnet IV',
        0x0e: 'Banyan Vines',
        0x0f: 'E.164 with NSAP',
        0x10: 'DNS',
        0x11: 'Distinguished Name',
        0x12: 'AS Number',
        0x13: 'XTP over IPv4',
        0x14: 'XTP over IPv6',
        0x15: 'XTP native mode XTP',
        0x16: 'Fiber Channel World-Wide Port Name',
        0x17: 'Fiber Channel World-Wide Node Name',
        0x18: 'GWID',
        0x19: 'AFI for L2VPN',
        0x1a: 'MPLS-TP Section Endpoint ID',
        0x1b: 'MPLS-TP LSP Endpoint ID',
        0x1c: 'MPLS-TP Pseudowire Endpoint ID',
        0x1d: 'MT IP Multi-Topology IPv4',
        0x1e: 'MT IP Multi-Topology IPv6'
    }

    SUBTYPE_MANAGEMENT_ADDRESS_OTHER = 0x00
    SUBTYPE_MANAGEMENT_ADDRESS_IPV4 = 0x01
    SUBTYPE_MANAGEMENT_ADDRESS_IPV6 = 0x02
    SUBTYPE_MANAGEMENT_ADDRESS_NSAP = 0x03
    SUBTYPE_MANAGEMENT_ADDRESS_HDLC = 0x04
    SUBTYPE_MANAGEMENT_ADDRESS_BBN = 0x05
    SUBTYPE_MANAGEMENT_ADDRESS_802 = 0x06
    SUBTYPE_MANAGEMENT_ADDRESS_E_163 = 0x07
    SUBTYPE_MANAGEMENT_ADDRESS_E_164 = 0x08
    SUBTYPE_MANAGEMENT_ADDRESS_F_69 = 0x09
    SUBTYPE_MANAGEMENT_ADDRESS_X_121 = 0x0A
    SUBTYPE_MANAGEMENT_ADDRESS_IPX = 0x0B
    SUBTYPE_MANAGEMENT_ADDRESS_APPLETALK = 0x0C
    SUBTYPE_MANAGEMENT_ADDRESS_DECNET_IV = 0x0D
    SUBTYPE_MANAGEMENT_ADDRESS_BANYAN_VINES = 0x0E
    SUBTYPE_MANAGEMENT_ADDRESS_E_164_WITH_NSAP = 0x0F
    SUBTYPE_MANAGEMENT_ADDRESS_DNS = 0x10
    SUBTYPE_MANAGEMENT_ADDRESS_DISTINGUISHED_NAME = 0x11
    SUBTYPE_MANAGEMENT_ADDRESS_AS_NUMBER = 0x12
    SUBTYPE_MANAGEMENT_ADDRESS_XTP_OVER_IPV4 = 0x13
    SUBTYPE_MANAGEMENT_ADDRESS_XTP_OVER_IPV6 = 0x14
    SUBTYPE_MANAGEMENT_ADDRESS_XTP_NATIVE_MODE_XTP = 0x15
    SUBTYPE_MANAGEMENT_ADDRESS_FIBER_CHANNEL_WORLD_WIDE_PORT_NAME = 0x16
    SUBTYPE_MANAGEMENT_ADDRESS_FIBER_CHANNEL_WORLD_WIDE_NODE_NAME = 0x17
    SUBTYPE_MANAGEMENT_ADDRESS_GWID = 0x18
    SUBTYPE_MANAGEMENT_ADDRESS_AFI_FOR_L2VPN = 0x19
    SUBTYPE_MANAGEMENT_ADDRESS_MPLS_TP_SECTION_ENDPOINT_ID = 0x1A
    SUBTYPE_MANAGEMENT_ADDRESS_MPLS_TP_LSP_ENDPOINT_ID = 0x1B
    SUBTYPE_MANAGEMENT_ADDRESS_MPLS_TP_PSEUDOWIRE_ENDPOINT_ID = 0x1C
    SUBTYPE_MANAGEMENT_ADDRESS_MT_IP_MULTI_TOPOLOGY_IPV4 = 0x1D
    SUBTYPE_MANAGEMENT_ADDRESS_MT_IP_MULTI_TOPOLOGY_IPV6 = 0x1E

    INTERFACE_NUMBERING_SUBTYPES = {
        0x01: 'unknown',
        0x02: 'ifIndex',
        0x03: 'system port number'
    }

    SUBTYPE_INTERFACE_NUMBER_UNKNOWN = 0x01
    SUBTYPE_INTERFACE_NUMBER_IF_INDEX = 0x02
    SUBTYPE_INTERFACE_NUMBER_SYSTEM_PORT_NUMBER = 0x03
    '''
    Note - calculation of _length field::

        _length = 1@_management_address_string_length +
                  1@management_address_subtype +
                  management_address.len +
                  1@interface_numbering_subtype +
                  4@interface_number +
                  1@_oid_string_length +
                  object_id.len
    '''

    fields_desc = [
        BitEnumField('_type', 0x08, 7, LLDPDU.TYPES),
        BitFieldLenField('_length',
                         None,
                         9,
                         length_of='management_address',
                         adjust=lambda pkt, x: 8 + len(pkt.management_address)
                         + len(pkt.object_id)),
        BitFieldLenField('_management_address_string_length',
                         None,
                         8,
                         length_of='management_address',
                         adjust=lambda pkt, x: len(pkt.management_address) + 1
                         ),  # noqa: E501
        ByteEnumField('management_address_subtype', 0x00,
                      IANA_ADDRESS_FAMILY_NUMBERS),
        XStrLenField('management_address',
                     '',
                     length_from=lambda pkt: 0
                     if pkt._management_address_string_length is None else pkt.
                     _management_address_string_length - 1),
        ByteEnumField('interface_numbering_subtype',
                      SUBTYPE_INTERFACE_NUMBER_UNKNOWN,
                      INTERFACE_NUMBERING_SUBTYPES),
        BitField('interface_number', 0, 32),
        BitFieldLenField('_oid_string_length', None, 8, length_of='object_id'),
        XStrLenField('object_id',
                     '',
                     length_from=lambda pkt: pkt._oid_string_length),
    ]

    def _check(self):
        """
        run layer specific checks
        """
        if conf.contribs['LLDP'].strict_mode():
            management_address_len = len(self.management_address)
            if management_address_len == 0 or management_address_len > 31:
                raise LLDPInvalidLengthField(
                    'management address must be  1..31 characters long - '
                    'got string of size {}'.format(management_address_len))
示例#26
0
class IE_SelectionMode(IE_Base):
    # Indicates the origin of the APN in the message
    name = "Selection Mode"
    fields_desc = [ByteEnumField("ietype", 15, IEType),
                   BitEnumField("SelectionMode", "MS or APN",
                                8, Selection_Mode)]
class IEC104_IE_SCD:
    """
    SCD - status and status change detection

    EN 60870-5-101:2003, sec. 7.2.6.40 (p. 57)
    """
    ST_FLAG_STATE_OFF = 0
    ST_FLAG_STATE_ON = 1
    ST_FLAGS = {ST_FLAG_STATE_OFF: 'off', ST_FLAG_STATE_ON: 'on'}

    CD_FLAG_STATE_NOT_CHANGED = 0
    CD_FLAG_STATE_CHANGED = 1
    CD_FLAGS = {
        CD_FLAG_STATE_NOT_CHANGED: 'state not changed',
        CD_FLAG_STATE_CHANGED: 'state changed'
    }

    informantion_element_fields = [
        BitEnumField('cd_16', 0, 1, CD_FLAGS),
        BitEnumField('cd_15', 0, 1, CD_FLAGS),
        BitEnumField('cd_14', 0, 1, CD_FLAGS),
        BitEnumField('cd_13', 0, 1, CD_FLAGS),
        BitEnumField('cd_12', 0, 1, CD_FLAGS),
        BitEnumField('cd_11', 0, 1, CD_FLAGS),
        BitEnumField('cd_10', 0, 1, CD_FLAGS),
        BitEnumField('cd_9', 0, 1, CD_FLAGS),
        BitEnumField('cd_8', 0, 1, CD_FLAGS),
        BitEnumField('cd_7', 0, 1, CD_FLAGS),
        BitEnumField('cd_6', 0, 1, CD_FLAGS),
        BitEnumField('cd_5', 0, 1, CD_FLAGS),
        BitEnumField('cd_4', 0, 1, CD_FLAGS),
        BitEnumField('cd_3', 0, 1, CD_FLAGS),
        BitEnumField('cd_2', 0, 1, CD_FLAGS),
        BitEnumField('cd_1', 0, 1, CD_FLAGS),
        BitEnumField('st_16', 0, 1, ST_FLAGS),
        BitEnumField('st_15', 0, 1, ST_FLAGS),
        BitEnumField('st_14', 0, 1, ST_FLAGS),
        BitEnumField('st_13', 0, 1, ST_FLAGS),
        BitEnumField('st_12', 0, 1, ST_FLAGS),
        BitEnumField('st_11', 0, 1, ST_FLAGS),
        BitEnumField('st_10', 0, 1, ST_FLAGS),
        BitEnumField('st_9', 0, 1, ST_FLAGS),
        BitEnumField('st_8', 0, 1, ST_FLAGS),
        BitEnumField('st_7', 0, 1, ST_FLAGS),
        BitEnumField('st_6', 0, 1, ST_FLAGS),
        BitEnumField('st_5', 0, 1, ST_FLAGS),
        BitEnumField('st_4', 0, 1, ST_FLAGS),
        BitEnumField('st_3', 0, 1, ST_FLAGS),
        BitEnumField('st_2', 0, 1, ST_FLAGS),
        BitEnumField('st_1', 0, 1, ST_FLAGS),
    ]
示例#28
0
class LoWPAN_IPHC(Packet):
    """6LoWPAN IPv6 header compressed packets

    It follows the implementation of RFC6282
    """
    __slots__ = ["_ipv6"]
    # the LOWPAN_IPHC encoding utilizes 13 bits, 5 dispatch type
    name = "LoWPAN IP Header Compression Packet"
    _address_modes = ["Unspecified (0)", "1", "16-bits inline (3)",
                      "Compressed (3)"]
    _state_mode = ["Stateless (0)", "Stateful (1)"]
    deprecated_fields = {
        "_nhField": ("nhField", "2.4.4"),
        "_hopLimit": ("hopLimit", "2.4.4"),
        "sourceAddr": ("src", "2.4.4"),
        "destinyAddr": ("dst", "2.4.4"),
        "udpDestinyPort": ("udpDestPort", "2.4.4"),
    }
    fields_desc = [
        # Base Format https://tools.ietf.org/html/rfc6282#section-3.1.2
        BitField("_reserved", 0x03, 3),
        BitField("tf", 0x0, 2),
        BitEnumField("nh", 0x0, 1, ["Inline", "Compressed"]),
        BitEnumField("hlim", 0x0, 2, {0: "Inline",
                                      1: "Compressed/HL1",
                                      2: "Compressed/HL64",
                                      3: "Compressed/HL255"}),
        BitEnumField("cid", 0x0, 1, {1: "Present (1)"}),
        BitEnumField("sac", 0x0, 1, _state_mode),
        BitEnumField("sam", 0x0, 2, _address_modes),
        BitEnumField("m", 0x0, 1, {1: "multicast (1)"}),
        BitEnumField("dac", 0x0, 1, _state_mode),
        BitEnumField("dam", 0x0, 2, _address_modes),
        # https://tools.ietf.org/html/rfc6282#section-3.1.2
        # Context Identifier Extension
        ConditionalField(
            BitField("sci", 0, 4),
            lambda pkt: pkt.cid == 0x1
        ),
        ConditionalField(
            BitField("dci", 0, 4),
            lambda pkt: pkt.cid == 0x1
        ),
        # https://tools.ietf.org/html/rfc6282#section-3.2.1
        ConditionalField(
            BitField("tc_ecn", 0, 2),
            lambda pkt: pkt.tf in [0, 1, 2]
        ),
        ConditionalField(
            BitField("tc_dscp", 0, 6),
            lambda pkt: pkt.tf in [0, 2],
        ),
        ConditionalField(
            MultipleTypeField(
                [(BitField("rsv", 0, 4), lambda pkt: pkt.tf == 0)],
                BitField("rsv", 0, 2),
            ),
            lambda pkt: pkt.tf in [0, 1]
        ),
        ConditionalField(
            BitField("flowlabel", 0, 20),
            lambda pkt: pkt.tf in [0, 1]
        ),
        # Inline fields https://tools.ietf.org/html/rfc6282#section-3.1.1
        ConditionalField(
            ByteEnumField("nhField", 0x0, ipv6nh),
            lambda pkt: pkt.nh == 0x0
        ),
        ConditionalField(
            ByteField("hopLimit", 0x0),
            lambda pkt: pkt.hlim == 0x0
        ),
        # The src and dst fields are filled up or removed in the
        # pre_dissect and post_build, depending on the other options.
        IP6FieldLenField("src", "::", length_of=source_addr_size),
        IP6FieldLenField("dst", "::", length_of=dest_addr_size),  # problem when it's 0  # noqa: E501
    ]

    def post_dissect(self, data):
        """dissect the IPv6 package compressed into this IPHC packet.

        The packet payload needs to be decompressed and depending on the
        arguments, several conversions should be done.
        """

        # uncompress payload
        packet = IPv6()
        packet.tc, packet.fl = self._getTrafficClassAndFlowLabel()
        if not self.nh:
            packet.nh = self.nhField
        # HLIM: Hop Limit
        if self.hlim == 0:
            packet.hlim = self.hopLimit
        elif self.hlim == 0x1:
            packet.hlim = 1
        elif self.hlim == 0x2:
            packet.hlim = 64
        else:
            packet.hlim = 255

        packet.src = self.decompressSourceAddr(packet)
        packet.dst = self.decompressDestAddr(packet)

        pay_cls = self.guess_payload_class(data)
        if pay_cls == IPv6:
            packet.add_payload(data)
            data = raw(packet)
        elif pay_cls == LoWPAN_NHC:
            self._ipv6 = packet
        return Packet.post_dissect(self, data)

    def decompressDestAddr(self, packet):
        # https://tools.ietf.org/html/rfc6282#section-3.1.1
        try:
            tmp_ip = inet_pton(socket.AF_INET6, self.dst)
        except socket.error:
            tmp_ip = b"\x00" * 16

        if self.m == 0 and self.dac == 0:
            if self.dam == 0:
                # Address fully carried
                pass
            elif self.dam == 1:
                tmp_ip = LINK_LOCAL_PREFIX[0:8] + tmp_ip[-8:]
            elif self.dam == 2:
                tmp_ip = LINK_LOCAL_PREFIX[0:8] + b"\x00\x00\x00\xff\xfe\x00" + tmp_ip[-2:]  # noqa: E501
            elif self.dam == 3:
                tmp_ip = _extract_upperaddress(self, source=False)

        elif self.m == 0 and self.dac == 1:
            if self.dam == 0:
                # reserved
                pass
            elif self.dam == 0x3:
                # should use context IID + encapsulating header
                tmp_ip = _extract_upperaddress(self, source=False)
            elif self.dam not in [0x1, 0x2]:
                # https://tools.ietf.org/html/rfc6282#page-9
                # Should use context information: unimplemented
                pass
        elif self.m == 1 and self.dac == 0:
            if self.dam == 0:
                # Address fully carried
                pass
            elif self.dam == 1:
                tmp = b"\xff" + chb(tmp_ip[16 - dest_addr_size(self)])
                tmp_ip = tmp + b"\x00" * 9 + tmp_ip[-5:]
            elif self.dam == 2:
                tmp = b"\xff" + chb(tmp_ip[16 - dest_addr_size(self)])
                tmp_ip = tmp + b"\x00" * 11 + tmp_ip[-3:]
            else:  # self.dam == 3:
                tmp_ip = b"\xff\x02" + b"\x00" * 13 + tmp_ip[-1:]
        elif self.m == 1 and self.dac == 1:
            if self.dam == 0x0:
                # https://tools.ietf.org/html/rfc6282#page-10
                # https://github.com/wireshark/wireshark/blob/f54611d1104d85a425e52c7318c522ed249916b6/epan/dissectors/packet-6lowpan.c#L2149-L2166
                # Format: ffXX:XXLL:PPPP:PPPP:PPPP:PPPP:XXXX:XXXX
                # P and L should be retrieved from context
                P = b"\x00" * 16
                L = b"\x00"
                X = tmp_ip[-6:]
                tmp_ip = b"\xff" + X[:2] + L + P[:8] + X[2:6]
            else:  # all the others values: reserved
                pass

        self.dst = inet_ntop(socket.AF_INET6, tmp_ip)
        return self.dst

    def compressSourceAddr(self, ipv6):
        # https://tools.ietf.org/html/rfc6282#section-3.1.1
        tmp_ip = inet_pton(socket.AF_INET6, ipv6.src)

        if self.sac == 0:
            if self.sam == 0x0:
                pass
            elif self.sam == 0x1:
                tmp_ip = tmp_ip[8:16]
            elif self.sam == 0x2:
                tmp_ip = tmp_ip[14:16]
            else:  # self.sam == 0x3:
                pass
        else:  # self.sac == 1
            if self.sam == 0x0:
                tmp_ip = b"\x00" * 16
            elif self.sam == 0x1:
                tmp_ip = tmp_ip[8:16]
            elif self.sam == 0x2:
                tmp_ip = tmp_ip[14:16]

        self.src = inet_ntop(socket.AF_INET6, b"\x00" * (16 - len(tmp_ip)) + tmp_ip)  # noqa: E501
        return self.src

    def compressDestAddr(self, ipv6):
        # https://tools.ietf.org/html/rfc6282#section-3.1.1
        tmp_ip = inet_pton(socket.AF_INET6, ipv6.dst)

        if self.m == 0 and self.dac == 0:
            if self.dam == 0x0:
                pass
            elif self.dam == 0x1:
                tmp_ip = b"\x00" * 8 + tmp_ip[8:16]
            elif self.dam == 0x2:
                tmp_ip = b"\x00" * 14 + tmp_ip[14:16]
        elif self.m == 0 and self.dac == 1:
            if self.dam == 0x1:
                tmp_ip = b"\x00" * 8 + tmp_ip[8:16]
            elif self.dam == 0x2:
                tmp_ip = b"\x00" * 14 + tmp_ip[14:16]
        elif self.m == 1 and self.dac == 0:
            if self.dam == 0x0:
                pass
            if self.dam == 0x1:
                tmp_ip = b"\x00" * 10 + tmp_ip[1:2] + tmp_ip[11:16]
            elif self.dam == 0x2:
                tmp_ip = b"\x00" * 12 + tmp_ip[1:2] + tmp_ip[13:16]
            elif self.dam == 0x3:
                tmp_ip = b"\x00" * 15 + tmp_ip[15:16]
        elif self.m == 1 and self.dac == 1:
            if self.dam == 0:
                tmp_ip = b"\x00" * 10 + tmp_ip[1:3] + tmp_ip[12:16]

        self.dst = inet_ntop(socket.AF_INET6, tmp_ip)

    def decompressSourceAddr(self, packet):
        # https://tools.ietf.org/html/rfc6282#section-3.1.1
        try:
            tmp_ip = inet_pton(socket.AF_INET6, self.src)
        except socket.error:
            tmp_ip = b"\x00" * 16

        if self.sac == 0:
            if self.sam == 0x0:
                # Full address is carried in-line
                pass
            elif self.sam == 0x1:
                tmp_ip = LINK_LOCAL_PREFIX[0:8] + tmp_ip[16 - source_addr_size(self):16]  # noqa: E501
            elif self.sam == 0x2:
                tmp = LINK_LOCAL_PREFIX[0:8] + b"\x00\x00\x00\xff\xfe\x00"
                tmp_ip = tmp + tmp_ip[16 - source_addr_size(self):16]
            elif self.sam == 0x3:
                # Taken from encapsulating header
                tmp_ip = _extract_upperaddress(self, source=True)
        else:  # self.sac == 1:
            if self.sam == 0x0:
                # Unspecified address ::
                pass
            elif self.sam == 0x1:
                # should use context IID
                pass
            elif self.sam == 0x2:
                # should use context IID
                tmp = LINK_LOCAL_PREFIX[0:8] + b"\x00\x00\x00\xff\xfe\x00"
                tmp_ip = tmp + tmp_ip[16 - source_addr_size(self):16]
            elif self.sam == 0x3:
                # should use context IID
                tmp_ip = LINK_LOCAL_PREFIX[0:8] + b"\x00" * 8
        self.src = inet_ntop(socket.AF_INET6, tmp_ip)
        return self.src

    def guess_payload_class(self, payload):
        if self.nh:
            return LoWPAN_NHC
        u = self.underlayer
        if u and isinstance(u, (LoWPANFragmentationFirst,
                                LoWPANFragmentationSubsequent)):
            return Raw
        return IPv6

    def do_build(self):
        _cur = self
        if isinstance(_cur.payload, LoWPAN_NHC):
            _cur = _cur.payload
        if not isinstance(_cur.payload, IPv6):
            return Packet.do_build(self)
        ipv6 = _cur.payload

        self._reserved = 0x03

        # NEW COMPRESSION TECHNIQUE!
        # a ) Compression Techniques

        # 1. Set Traffic Class
        if self.tf == 0x0:
            self.tc_ecn = ipv6.tc >> 6
            self.tc_dscp = ipv6.tc & 0x3F
            self.flowlabel = ipv6.fl
        elif self.tf == 0x1:
            self.tc_ecn = ipv6.tc >> 6
            self.flowlabel = ipv6.fl
        elif self.tf == 0x2:
            self.tc_ecn = ipv6.tc >> 6
            self.tc_dscp = ipv6.tc & 0x3F
        else:  # self.tf == 0x3:
            pass  # no field is set

        # 2. Next Header
        if self.nh == 0x0:
            self.nhField = ipv6.nh
        elif self.nh == 1:
            # This will be handled in LoWPAN_NHC
            pass

        # 3. HLim
        if self.hlim == 0x0:
            self.hopLimit = ipv6.hlim
        else:  # if hlim is 1, 2 or 3, there are nothing to do!
            pass

        # 4. Context (which context to use...)
        if self.cid == 0x0:
            pass
        else:
            # TODO: Context Unimplemented yet
            pass

        # 5. Compress Source Addr
        self.compressSourceAddr(ipv6)
        self.compressDestAddr(ipv6)

        return Packet.do_build(self)

    def do_build_payload(self):
        # Elide the IPv6 payload
        if isinstance(self.payload, IPv6):
            return raw(self.payload.payload)
        return Packet.do_build_payload(self)

    def _getTrafficClassAndFlowLabel(self):
        """Page 6, draft feb 2011 """
        if self.tf == 0x0:
            return (self.tc_ecn << 6) + self.tc_dscp, self.flowlabel
        elif self.tf == 0x1:
            return (self.tc_ecn << 6), self.flowlabel
        elif self.tf == 0x2:
            return (self.tc_ecn << 6) + self.tc_dscp, 0
        else:
            return 0, 0
class IEC104_IE_CP56TIME2A(IEC104_IE_CommonQualityFlags):
    """
    CP56Time2a - dual time, 7 octets
                 (milliseconds, valid flag, minutes, hours,
                  summer-time-indicator, day of month, weekday, years)

    well, someone should have talked to them about the idea of the
    unix timestamp...

    EN 60870-5-101:2003, sec. 7.2.6.18 (p. 50)

    time representation format according IEC 60870-5-4:1993, sec. 6.8, p. 23
    """
    WEEK_DAY_FLAG_UNUSED = 0
    WEEK_DAY_FLAG_MONDAY = 1
    WEEK_DAY_FLAG_TUESDAY = 2
    WEEK_DAY_FLAG_WEDNESDAY = 3
    WEEK_DAY_FLAG_THURSDAY = 4
    WEEK_DAY_FLAG_FRIDAY = 5
    WEEK_DAY_FLAG_SATURDAY = 6
    WEEK_DAY_FLAG_SUNDAY = 7
    WEEK_DAY_FLAGS = {
        WEEK_DAY_FLAG_UNUSED: 'unused',
        WEEK_DAY_FLAG_MONDAY: 'Monday',
        WEEK_DAY_FLAG_TUESDAY: 'Tuesday',
        WEEK_DAY_FLAG_WEDNESDAY: 'Wednesday',
        WEEK_DAY_FLAG_THURSDAY: 'Thursday',
        WEEK_DAY_FLAG_FRIDAY: 'Friday',
        WEEK_DAY_FLAG_SATURDAY: 'Saturday',
        WEEK_DAY_FLAG_SUNDAY: 'Sunday'
    }

    GEN_FLAG_REALTIME = 0
    GEN_FLAG_SUBSTITUTED_TIME = 1
    GEN_FLAGS = {
        GEN_FLAG_REALTIME: 'real time',
        GEN_FLAG_SUBSTITUTED_TIME: 'substituted time'
    }

    SU_FLAG_NORMAL_TIME = 0
    SU_FLAG_SUMMER_TIME = 1
    SU_FLAGS = {
        SU_FLAG_NORMAL_TIME: 'normal time',
        SU_FLAG_SUMMER_TIME: 'summer time'
    }

    informantion_element_fields = [
        LEShortField('sec_milli', 0),
        BitEnumField('iv_time', 0, 1, IEC104_IE_CommonQualityFlags.IV_FLAGS),
        BitEnumField('gen', 0, 1, GEN_FLAGS),
        # only valid in monitor direction ToDo: special treatment needed?
        BitField('minutes', 0, 6),
        BitEnumField('su', 0, 1, SU_FLAGS),
        BitField('reserved_2', 0, 2),
        BitField('hours', 0, 5),
        BitEnumField('weekday', 0, 3, WEEK_DAY_FLAGS),
        BitField('day-of-month', 0, 5),
        BitField('reserved_3', 0, 4),
        BitField('month', 0, 4),
        BitField('reserved_4', 0, 1),
        BitField('year', 0, 7),
    ]
示例#30
0
class LoWPAN_HC1(Packet):
    name = "LoWPAN_HC1 Compressed IPv6"
    fields_desc = [
        # https://tools.ietf.org/html/rfc4944#section-10.1
        ByteField("reserved", 0x42),
        BitEnumField("sp", 0, 1, ["In-line", "Compressed"]),
        BitEnumField("si", 0, 1, ["In-line", "Elided"]),
        BitEnumField("dp", 0, 1, ["In-line", "Compressed"]),
        BitEnumField("di", 0, 1, ["In-line", "Elided"]),
        BitEnumField("tc_fl", 0, 1, ["Not compressed", "zero"]),
        BitEnumField("nh", 0, 2, {0: "not compressed",
                                  1: "UDP",
                                  2: "ICMP",
                                  3: "TCP"}),
        BitEnumField("hc2", 0, 1, ["No more header compression bits",
                                   "HC2 Present"]),
        # https://tools.ietf.org/html/rfc4944#section-10.2
        ConditionalField(
            MultipleTypeField(
                [
                    (PacketField("hc2Field", LoWPAN_HC2_UDP(),
                                 LoWPAN_HC2_UDP),
                        lambda pkt: pkt.nh == 1),
                    # TODO: ICMP & TCP not implemented yet for HC1
                    # (PacketField("hc2Field", LoWPAN_HC2_ICMP(),
                    #              LoWPAN_HC2_ICMP),
                    #     lambda pkt: pkt.nh == 2),
                    # (PacketField("hc2Field", LoWPAN_HC2_TCP(),
                    #              LoWPAN_HC2_TCP),
                    #     lambda pkt: pkt.nh == 3),
                ],
                StrFixedLenField("hc2Field", b"", 0),
            ),
            lambda pkt: pkt.hc2
        ),
        # IPv6 header fields
        # https://tools.ietf.org/html/rfc4944#section-10.3.1
        ByteField("hopLimit", 0x0),
        IP6FieldLenField("src", "::",
                         lambda pkt: (0 if pkt.sp else 8) +
                                     (0 if pkt.si else 8)),
        IP6FieldLenField("dst", "::",
                         lambda pkt: (0 if pkt.dp else 8) +
                                     (0 if pkt.di else 8)),
        ConditionalField(
            ByteField("traffic_class", 0),
            lambda pkt: not pkt.tc_fl
        ),
        ConditionalField(
            BitField("flow_label", 0, 20),
            lambda pkt: not pkt.tc_fl
        ),
        # Other fields
        # https://tools.ietf.org/html/rfc4944#section-10.3.2
        ConditionalField(
            MultipleTypeField(
                [(BitScalingField("udpSourcePort", 0, 4, offset=0xF0B0),
                    lambda pkt: getattr(pkt.hc2Field, "sc", 0))],
                BitField("udpSourcePort", 0, 16)
            ),
            lambda pkt: pkt.nh == 1 and pkt.hc2
        ),
        ConditionalField(
            MultipleTypeField(
                [(BitScalingField("udpDestPort", 0, 4, offset=0xF0B0),
                    lambda pkt: getattr(pkt.hc2Field, "dc", 0))],
                BitField("udpDestPort", 0, 16)
            ),
            lambda pkt: pkt.nh == 1 and pkt.hc2
        ),
        ConditionalField(
            BitField("udpLength", 0, 16),
            lambda pkt: pkt.nh == 1 and pkt.hc2 and not pkt.hc2Field.lc
        ),
        ConditionalField(
            XBitField("udpChecksum", 0, 16),
            lambda pkt: pkt.nh == 1 and pkt.hc2
        ),
        # Out of spec
        BitFixedLenField("pad", 0, _get_hc1_pad)
    ]

    def post_dissect(self, data):
        # uncompress payload
        packet = IPv6()
        packet.version = IPHC_DEFAULT_VERSION
        packet.tc = self.traffic_class
        packet.fl = self.flow_label
        nh_match = {
            1: socket.IPPROTO_UDP,
            2: socket.IPPROTO_ICMP,
            3: socket.IPPROTO_TCP
        }
        if self.nh:
            packet.nh = nh_match.get(self.nh)
        packet.hlim = self.hopLimit

        packet.src = self.decompressSourceAddr()
        packet.dst = self.decompressDestAddr()

        if self.hc2 and self.nh == 1:  # UDP
            udp = UDP()
            udp.sport = self.udpSourcePort
            udp.dport = self.udpDestPort
            udp.len = self.udpLength or None
            udp.chksum = self.udpChecksum
            udp.add_payload(data)
            packet.add_payload(udp)
        else:
            packet.add_payload(data)
        data = raw(packet)
        return Packet.post_dissect(self, data)

    def decompressSourceAddr(self):
        if not self.sp and not self.si:
            # Prefix & Interface
            return self.src
        elif not self.si:
            # Only interface
            addr = inet_pton(socket.AF_INET6, self.src)[-8:]
            addr = LINK_LOCAL_PREFIX[:8] + addr
        else:
            # Interface not provided
            addr = _extract_upperaddress(self, source=True)
        self.src = inet_ntop(socket.AF_INET6, addr)
        return self.src

    def decompressDestAddr(self):
        if not self.dp and not self.di:
            # Prefix & Interface
            return self.dst
        elif not self.di:
            # Only interface
            addr = inet_pton(socket.AF_INET6, self.dst)[-8:]
            addr = LINK_LOCAL_PREFIX[:8] + addr
        else:
            # Interface not provided
            addr = _extract_upperaddress(self, source=False)
        self.dst = inet_ntop(socket.AF_INET6, addr)
        return self.dst

    def do_build(self):
        if not isinstance(self.payload, IPv6):
            return Packet.do_build(self)
        # IPv6
        ipv6 = self.payload
        self.src = ipv6.src
        self.dst = ipv6.dst
        self.flow_label = ipv6.fl
        self.traffic_class = ipv6.tc
        self.hopLimit = ipv6.hlim
        if isinstance(ipv6.payload, UDP):
            self.nh = 1
            self.hc2 = 1
            udp = ipv6.payload
            self.udpSourcePort = udp.sport
            self.udpDestPort = udp.dport
            if not udp.len or not udp.chksum:
                udp = UDP(raw(udp))
            self.udpLength = udp.len
            self.udpChecksum = udp.chksum
        return Packet.do_build(self)

    def do_build_payload(self):
        # Elide the IPv6 and UDP payload
        if isinstance(self.payload, IPv6):
            if isinstance(self.payload.payload, UDP):
                return raw(self.payload.payload.payload)
            return raw(self.payload.payload)
        return Packet.do_build_payload(self)