예제 #1
0
	class ReassocReq(pypacker.Packet):
		__hdr__ = (
			("dst", "6s", b"\x00" * 6),
			("bssid", "6s", b"\x00" * 6),
			("src", "6s", b"\x00" * 6),
			("seq_frag", "H", 0),
			("capa", "H", 0),
			("interval", "H", 0),
			("current_ap", "6s", b"\x00" * 6)
		)

		dst_s = pypacker.get_property_mac("dst")
		bssid_s = pypacker.get_property_mac("bssid")
		src_s = pypacker.get_property_mac("src")

		def _get_seq(self):
			return (self.seq_frag & 0xFF) << 4 | (self.seq_frag >> 12)

		def _set_seq(self, val):
			self.seq_frag = (val & 0xF) << 12 | (val & 0xFF0) >> 4 | (self.seq_frag & 0x0F00)

		seq = property(_get_seq, _set_seq)

		def reverse_address(self):
			self.dst, self.src = self.src, self.dst
예제 #2
0
    class Deauth(pypacker.Packet):
        __hdr__ = (
            ("dst", "6s", b"\xFF" * 6),
            ("src", "6s", b"\x00" * 6),
            ("bssid", "6s", b"\xFF" * 6),
            ("seq_frag", "H", 0),
            ("reason", "H", 0x0700
             )  # class 3 frame received from non associated client
        )

        dst_s = pypacker.get_property_mac("dst")
        bssid_s = pypacker.get_property_mac("bssid")
        src_s = pypacker.get_property_mac("src")

        def _get_seq(self):
            return (self.seq_frag & 0xFF) << 4 | (self.seq_frag >> 12)

        def _set_seq(self, val):
            self.seq_frag = (val & 0xF) << 12 | (val & 0xFF0) >> 4 | (
                self.seq_frag & 0x0F00)

        seq = property(_get_seq, _set_seq)

        def reverse_address(self):
            self.dst, self.src = self.src, self.dst
예제 #3
0
	class AssocResp(pypacker.Packet):
		__hdr__ = (
			("dst", "6s", b"\x00" * 6),
			("bssid", "6s", b"\x00" * 6),
			("src", "6s", b"\x00" * 6),
			("seq_frag", "H", 0),
			("capa", "H", 0),
			("status", "H", 0),
			("aid", "H", 0),
			("params", None, triggerlist.TriggerList)
		)

		dst_s = pypacker.get_property_mac("dst")
		bssid_s = pypacker.get_property_mac("bssid")
		src_s = pypacker.get_property_mac("src")

		def _get_seq(self):
			return (self.seq_frag & 0xFF) << 4 | (self.seq_frag >> 12)

		def _set_seq(self, val):
			self.seq_frag = (val & 0xF) << 12 | (val & 0xFF0) >> 4 | (self.seq_frag & 0x0F00)

		seq = property(_get_seq, _set_seq)

		def _dissect(self, buf):
			self._init_triggerlist("params", buf[26:], IEEE80211._unpack_ies)
			return len(buf)

		def reverse_address(self):
			self.dst, self.src = self.src, self.dst
예제 #4
0
	class Auth(pypacker.Packet):
		"""Authentication request."""
		__hdr__ = (
			("dst", "6s", b"\x00" * 6),
			("src", "6s", b"\x00" * 6),
			("bssid", "6s", b"\x00" * 6),
			("seq_frag", "H", 0),
			("algo", "H", 0),
			("authseq", "H", 0x0100),
			("status", "H", 0)
		)

		dst_s = pypacker.get_property_mac("dst")
		bssid_s = pypacker.get_property_mac("bssid")
		src_s = pypacker.get_property_mac("src")

		def _get_seq(self):
			return (self.seq_frag & 0xFF) << 4 | (self.seq_frag >> 12)

		def _set_seq(self, val):
			self.seq_frag = (val & 0xF) << 12 | (val & 0xFF0) >> 4 | (self.seq_frag & 0x0F00)

		seq = property(_get_seq, _set_seq)

		def reverse_address(self):
			self.dst, self.src = self.src, self.dst
예제 #5
0
    class RTS(pypacker.Packet):
        __hdr__ = (("dst", "6s", b"\x00" * 6), ("src", "6s", b"\x00" * 6))

        dst_s = pypacker.get_property_mac("dst")
        src_s = pypacker.get_property_mac("src")

        def reverse_address(self):
            self.dst, self.src = self.src, self.dst
예제 #6
0
    class BlockAck(pypacker.Packet):
        __hdr__ = (("dst", "6s", b"\x00" * 6), ("src", "6s", b"\x00" * 6),
                   ("reqctrl", "H", 0), ("seq", "H", 0), ("bitmap", "Q", 0))

        dst_s = pypacker.get_property_mac("dst")
        src_s = pypacker.get_property_mac("src")

        def reverse_address(self):
            self.dst, self.src = self.src, self.dst
예제 #7
0
	class Action(pypacker.Packet):
		__hdr__ = (
			("dst", "6s", b"\x00" * 6),
			("src", "6s", b"\x00" * 6),
			("bssid", "6s", b"\x00" * 6),
			("seq_frag", "H", 0),
			("category", "B", 0),
			("code", "B", 0)
		)

		def _get_seq(self):
			return (self.seq_frag & 0xFF) << 4 | (self.seq_frag >> 12)

		def _set_seq(self, val):
			self.seq_frag = (val & 0xF) << 12 | (val & 0xFF0) >> 4 | (self.seq_frag & 0x0F00)

		seq = property(_get_seq, _set_seq)

		class BlockAckRequest(pypacker.Packet):
			__hdr__ = (
				("dialog", "B", 0),
				("parameters", "H", 0),
				("timeout", "H", 0),
				("starting_seq", "H", 0),
			)

		class BlockAckResponse(pypacker.Packet):
			__hdr__ = (
				("dialog", "B", 0),
				("status_code", "H", 0),
				("parameters", "H", 0),
				("timeout", "H", 0),
			)

		CATEGORY_BLOCK_ACK	= 3
		CODE_BLOCK_ACK_REQUEST	= 0
		CODE_BLOCK_ACK_RESPONSE	= 1

		dst_s = pypacker.get_property_mac("dst")
		src_s = pypacker.get_property_mac("src")
		bssid_s = pypacker.get_property_mac("bssid")

		def _dissect(self, buf):
			# logger.debug(">>>>>>>> ACTION!!!")
			# category: block ack, code: request or response
			self._init_handler(buf[20] * 4 + buf[21], buf[22:])
			return 22

		def reverse_address(self):
			self.dst, self.src = self.src, self.dst
예제 #8
0
class CMSlacParmCnf(Packet):
    __hdr__ = (
        ("msoundtarget", "6s", b"\x00" * 6),
        ("numsounds", "B", 0),
        ("timeout", "B", 0),
        ("resptype", "B", 0),
        ("forwardingsta", "6s", b"\x00" * 6),
        ("apptype", "B", 0),
        ("sectype", "B", 0),
        ("runid", "Q", 0),
        # Only present if security type is 1
        ("ciphersuite", "H", None))

    msoundtarget_s = pypacker.get_property_mac("msoundtarget")
    forwardingsta_s = pypacker.get_property_mac("forwardingsta")
예제 #9
0
class CMSlacMatchReq(Packet):
    __hdr__ = (("apptype", "B", 0), ("sectype", "B", 0), ("mvflen", "H", 0),
               ("pevid", "17s", b"\x00" * 17), ("pevmac", "6s", b"\x00" * 6),
               ("evseid", "17s", b"\x00" * 17), ("evsemac", "6s", b"\x00" * 6),
               ("runid", "Q", 0), ("rsvd", "8s", b"\x00" * 8))

    def _get_mvflen_be(self):
        return unpack_H(pack_H_le(self.mvflen))[0]

    def _set_mvflen_be(self, val):
        self.mvflen = unpack_H(pack_H_le(val))[0]

    mvflen_be = property(_get_mvflen_be, _set_mvflen_be)

    pevmac_s = pypacker.get_property_mac("pevmac")
    evsemac_s = pypacker.get_property_mac("evsemac")
예제 #10
0
class CMAttenCharRsp(Packet):
    __hdr__ = (("apptype", "B", 0), ("sectype", "B", 0), ("sourceaddr", "6s",
                                                          b"\x00" * 6),
               ("runid", "Q", 0), ("sourceid", "17s", b"\x00" * 17),
               ("respid", "17s", b"\x00" * 17), ("result", "B", 0))

    sourceaddr_s = pypacker.get_property_mac("sourceaddr")
예제 #11
0
class CMPKCSCertRsp(Packet):
    __hdr__ = (
        ("targetmac", "6s", b"\x00" * 6),
        ("status", "B", 0),
        ("ciphersuitesize", "B", 0),  # optional
        ("cipersuite", None, TriggerList))

    targetmac_s = pypacker.get_property_mac("targetmac")
예제 #12
0
파일: arp.py 프로젝트: wilixx/pypacker
class ARP(pypacker.Packet):
    __hdr__ = (
        ("hrd", "H", ARP_HRD_ETH),
        ("pro", "H", ARP_PRO_IP),
        ("hln", "B", 6),  # hardware address length
        ("pln", "B", 4),  # protocol address length
        ("op", "H", ARP_OP_REQUEST),
        ("sha", "6s", b"\x00" * 6),  # sender mac
        ("spa", "4s", b"\x00" * 4),  # sender ip
        ("tha", "6s", b"\x00" * 6),  # target mac
        ("tpa", "4s", b"\x00" * 4)  # target ip
    )

    # convenient access
    sha_s = pypacker.get_property_mac("sha")
    spa_s = pypacker.get_property_ip4("spa")
    tha_s = pypacker.get_property_mac("tha")
    tpa_s = pypacker.get_property_ip4("tpa")
예제 #13
0
class CMSlacMatchCnf(Packet):
    __hdr__ = (
        ("apptype", "B", 0),
        ("sectype", "B", 0),
        ("mvflen", "H", 0),
        ("pevid", "17s", b"\x00" * 17),
        ("pevmac", "6s", b"\x00" * 6),
        ("evseid", "17s", b"\x00" * 17),
        ("evsemac", "6s", b"\x00" * 6),
        ("runid", "Q", 0),
        ("rsvd1", "8s", b"\x00" * 8),
        ("nid", "7s", b"\x00" * 7),
        ("rsvd2", "B", 0),
        ("nmk", "16s", b"\x00" * 16),
    )

    pevmac_s = pypacker.get_property_mac("pevmac")
    evsemac_s = pypacker.get_property_mac("evsemac")
예제 #14
0
class CMStartAttenCharInd(Packet):
    __hdr__ = (
        ("apptype", "B", 0),
        ("sectype", "B", 0),
        ("numsounds", "B", 0),
        ("timeout", "B", 0),
        ("resptype", "B", 0),
        ("forwardingsta", "6s", b"\x00" * 6),
        ("runid", "Q", 0),
    )

    forwardingsta_s = pypacker.get_property_mac("forwardingsta")
예제 #15
0
	class Beacon(pypacker.Packet):
		__hdr__ = (
			("dst", "6s", b"\x00" * 6),
			("src", "6s", b"\x00" * 6),
			("bssid", "6s", b"\x00" * 6),
			# 12 Bits: 0->4095 | 4 Bits
			# SF SS (LE)
			("seq_frag", "H", 0),
			# _ts (integer) is saved as LE
			("_ts", "Q", 0),
			("interval", "H", 0x6400),
			("capa", "H", 0x0100),
			("params", None, triggerlist.TriggerList)
		)

		def _get_seq(self):
			return (self.seq_frag & 0xFF) << 4 | (self.seq_frag >> 12)

		def _set_seq(self, val):
			self.seq_frag = (val & 0xF) << 12 | (val & 0xFF0) >> 4 | (self.seq_frag & 0x0F00)

		def _get_ts(self):
			# LE->BE: dirty but simple
			return unpack_Q_le(pack_Q(self._ts))[0]

		def _set_ts(self, val):
			self._ts = unpack_Q_le(pack_Q(val))[0]

		seq = property(_get_seq, _set_seq)
		ts = property(_get_ts, _set_ts)
		dst_s = pypacker.get_property_mac("dst")
		bssid_s = pypacker.get_property_mac("bssid")
		src_s = pypacker.get_property_mac("src")

		def _dissect(self, buf):
			self._init_triggerlist("params", buf[32:], IEEE80211._unpack_ies)
			return len(buf)

		def reverse_address(self):
			self.dst, self.src = self.src, self.dst
예제 #16
0
class CMPKCSCertInd(Packet):
    """
	When the CM_SLAC_PARM.CNF indicates that Secure SLAC is required, the PEV-HLE
	shall send a CM_PKCS_CERT.IND message. The Target MAC address for this message
	shall be set to MAC address of the PEV Green PHY station. To ensure reliable
	reception of this message at all EVSEs, it is recommended that this message be
	transmitted at least three times by the PEV-HLE. If the CM_PKCS_CERT.IND message is
	larger than 502 Octets, the message shall be fragmented by the HLE (refer to
	Section 11.1.7).
	"""
    __hdr__ = (("targetmac", "6s", b"\x00" * 6), ("cipersuite", "H", 0),
               ("certlen", "H", 0), ("certpackage", None, TriggerList))

    targetmac_s = pypacker.get_property_mac("targetmac")
예제 #17
0
class LACPActorInfoTlv(pypacker.Packet):
    __hdr__ = (
        ("type", "B", ACTOR_TYPE),
        ("len", "B", LACP_ACTOR_LEN),
        ("sysprio", "H", DEFAULT_PRIORITY),
        ("sys", "6s", b"\x00" * 6),
        ("key", "H", 0),
        ("portprio", "H", DEFAULT_PRIORITY),
        ("port", "H", 1),
        ("state", "B", 0),
        ("reserved", "3s", b"\x00" * 3),
    )

    sys_s = pypacker.get_property_mac("sys")
    expired = get_property_of_state_field("expired")
    defaulted = get_property_of_state_field("defaulted")
    distribute = get_property_of_state_field("distribute")
    collect = get_property_of_state_field("collect")
    synch = get_property_of_state_field("synch")
    aggregate = get_property_of_state_field("aggregate")
    timeout = get_property_of_state_field("timeout")
    activity = get_property_of_state_field("activity")
예제 #18
0
class Ethernet(pypacker.Packet):
    __hdr__ = (
        ("dst", "6s", b"\xff" * 6),
        ("src", "6s", b"\xff" * 6),
        ("vlan", None, triggerlist.TriggerList),
        # ("len", "H", None),
        ("type", "H", ETH_TYPE_IP)  # type = Ethernet II, len = 802.3
    )

    dst_s = pypacker.get_property_mac("dst")
    src_s = pypacker.get_property_mac("src")

    def _dissect(self, buf):
        hlen = 14
        # we need to check for VLAN TPID here (0x8100) to get correct header-length
        type_len = unpack_H(buf[12:14])[0]

        # based on the type field, following bytes can be intrepreted differently than standard Ethernet II
        # Examples: 802.3/802.2 LLC or 802.3/802.2 SNAP

        if type_len in bridge_types_set:
            #logger.debug(">>> got vlan tag")
            # support up to 2 tags (double tagging aka QinQ)
            # triggerlist can't be initiated using _init_triggerlist() as amount of needed bytes is not known
            # -> full parsing of Dot1Q-part needed
            for _ in range(2):
                vlan_tag = Dot1Q(buf[hlen - 2:hlen + 2])

                if vlan_tag.type not in bridge_types_set:
                    break
                # logger.debug("re-extracting field: %s" % self.vlan)
                self.vlan.append(vlan_tag)
                hlen += 4
                self.type = vlan_tag.type

        # avoid calling unpack more than once
        eth_type = unpack_H(buf[hlen - 2:hlen])[0]
        # logger.debug("hlen is: %d" % eth_type)

        # handle ethernet-padding: remove it but save for later use
        # don't use headers for this because this is a rare situation
        dlen = len(buf) - hlen  # data length [+ padding?]

        try:
            # this will only work on complete headers: Ethernet + IP + ...
            # handle padding using IPv4, IPv6
            # TODO: check for other protocols
            # logger.debug(">>> checking for padding")
            if eth_type == ETH_TYPE_IP:
                dlen_ip = unpack_H(buf[hlen + 2:hlen +
                                       4])[0]  # real data length

                if dlen_ip < dlen:
                    # padding found
                    # logger.debug("got padding for IPv4")
                    self._padding = buf[hlen + dlen_ip:]
                    dlen = dlen_ip
            # handle padding using IPv6
            # IPv6 is a piece of sh$§! payloadlength = exclusive standard header, INCLUSIVE options!
            elif eth_type == ETH_TYPE_IP6:
                dlen_ip = unpack_H(buf[hlen + 4:hlen +
                                       6])[0]  # real data length

                if 40 + dlen_ip < dlen:
                    # padding found
                    # logger.debug("got padding for IPv6")
                    self._padding = buf[hlen + dlen_ip:]
                    dlen = dlen_ip
        except struct.error:
            # logger.debug("could not extract padding info, assuming incomplete ethernet frame")
            pass
        except:
            logger.exception("could not extract padding info")

        self._init_handler(eth_type, buf[hlen:hlen + dlen])
        return hlen

    def bin(self, update_auto_fields=True):
        """Custom bin(): handle padding for Ethernet."""
        return pypacker.Packet.bin(
            self, update_auto_fields=update_auto_fields) + self.padding

    def __len__(self):
        return super().__len__() + len(self.padding)

    def direction(self, other):
        # logger.debug("checking direction: %s<->%s" % (self, other))
        if self.dst == other.dst and self.src == other.src:
            # consider packet to itself: can be DIR_REV
            return pypacker.Packet.DIR_SAME | pypacker.Packet.DIR_REV
        elif (self.dst == other.src and self.src == other.dst) or\
         (self.dst == b"\xff\xff\xff\xff\xff\xff" and other.dst == self.src):  # broadcast
            return pypacker.Packet.DIR_REV
        else:
            return pypacker.Packet.DIR_UNKNOWN

    # handle padding attribute
    def __get_padding(self):
        try:
            return self._padding
        except AttributeError:
            return b""

    def __set_padding(self, padding):
        self._padding = padding

    padding = property(__get_padding, __set_padding)

    def reverse_address(self):
        self.dst, self.src = self.src, self.dst
예제 #19
0
class CMLinkStatsReq(Packet):
    __hdr__ = (("reqtype", "B", 0), ("reqid", "B", 0),
               ("nid", "7s", b"\x00" * 7), ("lid", "B", 0), ("tlflag", "B", 0),
               ("mgmtflag", "B", 0), ("dasa", "6s", b"\x00" * 6))

    dasa_s = pypacker.get_property_mac("dasa")
예제 #20
0
class CMPKCSCertCnf(Packet):
    __hdr__ = (("targetmac", "6s", b"\x00" * 6), ("status", "B", 0),
               ("cipersuite", "H", 0), ("certlen", "H",
                                        0), ("certpackage", None, TriggerList))

    targetmac_s = pypacker.get_property_mac("targetmac")
예제 #21
0
	class ACK(pypacker.Packet):
		__hdr__ = (
			("dst", "6s", b"\x00" * 6),
		)

		dst_s = pypacker.get_property_mac("dst")
예제 #22
0
class Ethernet(pypacker.Packet):
    __hdr__ = (
        ("dst", "6s", b"\xff" * 6),
        ("src", "6s", b"\xff" * 6),
        ("vlan", None, triggerlist.TriggerList),
        # ("len", "H", None),
        # type = Ethernet II, len = 802.3
        ("type", "H", ETH_TYPE_IP,
         FIELD_FLAG_AUTOUPDATE | FIELD_FLAG_IS_TYPEFIELD))

    dst_s = pypacker.get_property_mac("dst")
    src_s = pypacker.get_property_mac("src")

    __handler__ = {
        ETH_TYPE_IP: ip.IP,
        ETH_TYPE_ARP: arp.ARP,
        ETH_TYPE_DTP: dtp.DTP,
        ETH_TYPE_IPX: ipx.IPX,
        ETH_TYPE_IP6: ip6.IP6,
        ETH_TYPE_PPOE_DISC: pppoe.PPPoE,
        ETH_TYPE_PPOE_SESS: pppoe.PPPoE,
        ETH_TYPE_LLC: llc.LLC,
        ETH_TYPE_PTPv2: ptpv2.PTPv2,
        ETH_TYPE_EFC: flow_control.FlowControl,
        ETH_TYPE_LLDP: lldp.LLDP,
        ETH_TYPE_SP: lacp.LACP,
    }

    def _dissect(self, buf):
        hlen = ETH_HDR_LEN
        # we need to check for VLAN TPID here (0x8100) to get correct header-length
        type_len = unpack_H(buf[hlen - 2:hlen])[0]

        # based on the type field, following bytes can be intrepreted differently
        # than standard Ethernet II
        # Examples: 802.3/802.2 LLC or 802.3/802.2 SNAP

        if type_len in bridge_types_set:
            # logger.debug(">>> got vlan tag")
            # support up to 2 tags (double tagging aka QinQ)
            # triggerlist can't be initiated using _init_triggerlist() as amount of needed bytes is not known
            # -> full parsing of Dot1Q-part needed
            for _ in range(2):
                vlan_tag = Dot1Q(buf[hlen - 2:hlen + 2])

                if vlan_tag.type not in bridge_types_set:
                    break
                # logger.debug("re-extracting field: %s" % self.vlan)
                self.vlan.append(vlan_tag)
                hlen += 4
                self.type = vlan_tag.type

        # avoid calling unpack more than once
        if hlen == ETH_HDR_LEN:
            eth_type = type_len
        else:
            eth_type = unpack_H(buf[hlen - 2:hlen])[0]
        # logger.debug("eth type is: %d" % eth_type)

        # handle ethernet-padding: remove it but save for later use
        # don't use headers for this because this is a rare situation
        dlen = len(buf) - hlen  # data length [+ padding?]

        try:
            # this will only work on complete headers: Ethernet + IP + ...
            # handle padding using IPv4, IPv6 etc (min size "eth + ..." = 60 bytes)
            # logger.debug(">>> checking for padding")
            if eth_type == ETH_TYPE_IP:
                dlen_ip = unpack_H(buf[hlen + 2:hlen +
                                       4])[0]  # real data length

                if dlen_ip < dlen:
                    # padding found
                    self._padding = buf[hlen + dlen_ip:]
                    # logger.debug("got padding for IPv4: %r" % self._padding)
                    dlen = dlen_ip
            # handle padding using IPv6
            # IPv6 is a piece of sh$§! payloadlength (in header) = exclusive standard header
            # but INCLUSIVE options!
            elif eth_type == ETH_TYPE_IP6:
                dlen_ip = unpack_H(buf[hlen + 4:hlen +
                                       6])[0]  # real data length
                # logger.debug("eth.hlen=%d, data length based on header: %d" % (hlen, dlen_ip))

                if 40 + dlen_ip < dlen:
                    # padding found
                    self._padding = buf[hlen + 40 + dlen_ip:]
                    # logger.debug("got padding for IPv6: %r" % self._padding)
                    dlen = 40 + dlen_ip
            elif eth_type == ETH_TYPE_LLDP:
                # this is a bit redundant as we re-parse TLV when accessing the LLDP layer
                dlen_lldp, _ = lldp.count_and_dissect_tlvs(buf[hlen:])
                self._padding = buf[hlen + dlen_lldp:]
                dlen = dlen_lldp
            elif eth_type == ETH_TYPE_SP:
                lacppdu_len = 110
                self._padding = buf[hlen + lacppdu_len:]
                dlen = lacppdu_len
        except Exception as ex:
            logger.exception(
                "could not extract padding info, assuming incomplete ethernet frame: %r",
                ex)
        # logger.debug("len(buf)=%d, len(upper)=%d" % (len(buf), dlen))
        self._init_handler(eth_type, buf[hlen:hlen + dlen])
        return hlen

    def bin(self, update_auto_fields=True):
        if update_auto_fields:
            self._update_bodyhandler_id()
        return pypacker.Packet.bin(
            self, update_auto_fields=update_auto_fields) + self.padding

    def __len__(self):
        return super().__len__() + len(self.padding)

    def direction(self, other):
        # logger.debug("checking direction: %s<->%s" % (self, other))
        if self.dst == other.dst and self.src == other.src:
            # consider packet to itself: can be DIR_REV
            return pypacker.Packet.DIR_SAME | pypacker.Packet.DIR_REV
        if (self.dst == other.src and self.src == other.dst) or\
         (self.dst == b"\xff\xff\xff\xff\xff\xff" and other.dst == self.src):  # broadcast
            return pypacker.Packet.DIR_REV
        return pypacker.Packet.DIR_UNKNOWN

    # handle padding attribute
    def __get_padding(self):
        try:
            return self._padding
        except AttributeError:
            return b""

    def __set_padding(self, padding):
        self._padding = padding

    padding = property(__get_padding, __set_padding)

    def reverse_address(self):
        self.dst, self.src = self.src, self.dst
예제 #23
0
class Ethernet(pypacker.Packet):
    __hdr__ = (("dst", "6s", b"\xff" * 6), ("src", "6s", b"\xff" * 6),
               ("vlan", None, triggerlist.TriggerList),
               ("type", "H", ETH_TYPE_IP,
                FIELD_FLAG_AUTOUPDATE | FIELD_FLAG_IS_TYPEFIELD))

    dst_s = pypacker.get_property_mac("dst")
    src_s = pypacker.get_property_mac("src")

    __handler__ = {
        ETH_TYPE_IP: ip.IP,
        ETH_TYPE_ARP: arp.ARP,
        ETH_TYPE_DTP: dtp.DTP,
        ETH_TYPE_IPX: ipx.IPX,
        ETH_TYPE_IP6: ip6.IP6,
        ETH_TYPE_PPOE_DISC: pppoe.PPPoE,
        ETH_TYPE_PPOE_SESS: pppoe.PPPoE,
        ETH_TYPE_PTPv2: ptpv2.PTPv2,
        ETH_TYPE_EFC: flow_control.FlowControl,
        ETH_TYPE_LLDP: lldp.LLDP,
        ETH_TYPE_SP: lacp.LACP,
    }

    def _dissect(self, buf):
        hlen = 14
        # Ethernet formats:
        # RFC 894 (Ethernet II) -> type = -> value >1500
        # 802.[2,3] (LLC format) -> type = length field -> value <=1500, not supported
        eth_type = unpack_H(buf[hlen - 2:hlen])[0]

        # any VLAN tag present? in this case: type field is actually a vlan tag
        if eth_type in VLAN_TAG_START:
            # TODO: use _init_triggerlist()
            if eth_type == ETH_TYPE_8021Q:
                # logger.debug(">>> got vlan tag")
                vlan_tag = Dot1Q(buf[12:16])
                self.vlan.append(vlan_tag)
                hlen += 4
                # get real upper layer type
                eth_type = unpack_H(buf[16:18])[0]
            # 802.1ad: support up to 2 tags (double tagging aka QinQ)
            else:
                # logger.debug(">>> got vlan tag")
                vlan_tag1 = Dot1Q(buf[12:16])
                vlan_tag2 = Dot1Q(buf[16:20])
                self.vlan.extend([vlan_tag1, vlan_tag2])
                hlen += 8
                # get real upper layer type
                eth_type = unpack_H(buf[20:22])[0]

        # logger.debug("eth type is: %d" % eth_type)

        # handle ethernet-padding: remove it but save for later use
        # don't use headers for this because this is a rare situation
        dlen = len(buf) - hlen  # data length [+ padding?]

        # assume padding only present if len(upper_layer.bin()) <= 46
        if dlen <= 46:
            try:
                # this will only work on complete headers: Ethernet + IP + ...
                # handle padding using IPv4, IPv6 etc (min size "eth + ..." = 60 bytes)
                # logger.debug(">>> checking for padding")
                if eth_type == ETH_TYPE_IP:
                    dlen_ip = unpack_H(buf[hlen + 2:hlen +
                                           4])[0]  # real data length

                    if dlen_ip < dlen:
                        # padding found
                        self._padding = buf[hlen + dlen_ip:]
                        # logger.debug("got padding for IPv4: %r" % self._padding)
                        dlen = dlen_ip
                # handle padding using IPv6
                # IPv6 is a piece of sh$§! payloadlength (in header) = exclusive standard header
                # but INCLUSIVE options!
                elif eth_type == ETH_TYPE_IP6:
                    dlen_ip = unpack_H(buf[hlen + 4:hlen +
                                           6])[0]  # real data length
                    # logger.debug("eth.hlen=%d, data length based on header: %d" % (hlen, dlen_ip))

                    if 40 + dlen_ip < dlen:
                        # padding found
                        self._padding = buf[hlen + 40 + dlen_ip:]
                        # logger.debug("got padding for IPv6: %r" % self._padding)
                        dlen = 40 + dlen_ip
                elif eth_type == ETH_TYPE_LLDP:
                    # this is a bit redundant as we re-parse TLV when accessing the LLDP layer
                    dlen_lldp, _ = lldp.count_and_dissect_tlvs(buf[hlen:])
                    self._padding = buf[hlen + dlen_lldp:]
                    dlen = dlen_lldp
                elif eth_type == ETH_TYPE_SP:
                    lacppdu_len = 110
                    self._padding = buf[hlen + lacppdu_len:]
                    dlen = lacppdu_len
            except Exception as ex:
                logger.exception(
                    "could not extract padding info, assuming incomplete ethernet frame: %r",
                    ex)
        # logger.debug("len(buf)=%d, len(upper)=%d" % (len(buf), dlen))
        self._init_handler(eth_type, buf[hlen:hlen + dlen])
        return hlen

    def _update_fields(self):
        self._update_upperlayer_id()

    def bin(self, update_auto_fields=True):
        # padding needs to be placed at the very end
        return pypacker.Packet.bin(
            self, update_auto_fields=update_auto_fields) + self.padding

    def __len__(self):
        return super().__len__() + len(self.padding)

    def direction(self, other):
        # logger.debug("checking direction: %s<->%s" % (self, other))
        if self.dst == other.dst and self.src == other.src:
            # consider packet to itself: can be DIR_REV
            return pypacker.Packet.DIR_SAME | pypacker.Packet.DIR_REV
        if (self.dst == other.src and self.src == other.dst) or\
         (self.dst == b"\xff\xff\xff\xff\xff\xff" and other.dst == self.src):  # broadcast
            return pypacker.Packet.DIR_REV
        return pypacker.Packet.DIR_UNKNOWN

    padding = pypacker.get_ondemand_property("padding", lambda: b"")

    def reverse_address(self):
        self.dst, self.src = self.src, self.dst
예제 #24
0
	class Dataframe(pypacker.Packet):
		"""
		DataFrames need special care: there are too many types of field combinations
		to create classes for every one. Solution: initiate giving lower type "subType"
		via constructor. In order to use "src/dst/bssid" instead of addrX set from_to_ds
		of "subType" to one of the following values:

		[Bit 0: from DS][Bit 1: to DS] = [order of fields]

		00 = 0 = dst, src, bssid
		01 = 1 = bssid, src, dst
		10 = 2 = dst, bssid, src
		11 = 3 = RA, TA, DA, SA
		"""
		def __init__(self, *arg, **kwargs):
			if len(arg) > 1:
				# logger.debug("extracting lower layer type: %r" % arg[1])
				self.dtype = arg[1]
			else:
				self.dtype = self
				self._from_to_ds_value = 0
			#logger.debug("dstype: %r" % self.dtype.from_to_ds)
			super().__init__(*arg, **kwargs)

		__hdr__ = (
			("addr1", "6s", b"\x00" * 6),
			("addr2", "6s", b"\x00" * 6),
			("addr3", "6s", b"\x00" * 6),
			("seq_frag", "H", 0),
			("addr4", "6s", None),		# to/from-DS = 1
			("qos_ctrl", "H", 0),		# QoS
			("sec_param", "Q", 0)		# protected
		)

		def _get_seq(self):
			return (self.seq_frag & 0xFF) << 4 | (self.seq_frag >> 12)

		def _set_seq(self, val):
			self.seq_frag = (val & 0xF) << 12 | (val & 0xFF0) >> 4 | (self.seq_frag & 0x0F00)

		seq = property(_get_seq, _set_seq)

		def reverse_address(self):
			if self.dtype.from_to_ds == 0:
				self.addr1, self.addr2 = self.addr2, self.addr1
			elif self.dtype.from_to_ds == 1:
				self.addr2, self.addr3 = self.addr3, self.addr2
			elif self.dtype.from_to_ds == 2:
				self.addr1, self.addr3 = self.addr3, self.addr1

		def _get_from_to_ds(self):
			return self._from_to_ds_value
		# same property structure as in IEEE80211 class
		from_to_ds = property(_get_from_to_ds)

		# FromDs, ToDS
		# 00 = dst, src, bssid
		# 01 = bssid, src, dst
		# 10 = dst, bssid, src
		# 11 = RA, TA, DA, SA

		def __get_src(self):
			return self.addr2 if self.dtype.from_to_ds in [0, 1] else self.addr3

		def __set_src(self, src):
			if self.dtype.from_to_ds in [0, 1]:
				self.addr2 = src
			else:
				self.addr3 = src

		def __get_dst(self):
			return self.addr1 if self.dtype.from_to_ds in [0, 2] else self.addr3

		def __set_dst(self, dst):
			if self.dtype.from_to_ds in [0, 2]:
				self.addr1 = dst
			else:
				self.addr3 = dst

		def __get_bssid(self):
			dstype = self.dtype.from_to_ds

			if dstype == 0:
				return self.addr3
			elif dstype == 1:
				return self.addr1
			elif dstype == 2:
				return self.addr2

		def __set_bssid(self, bssid):
			dstype = self.dtype.from_to_ds
			if dstype == 0:
				self.addr3 = bssid
			elif dstype == 1:
				self.addr1 = bssid
			elif dstype == 2:
				self.addr2 = bssid

		src = property(__get_src, __set_src)
		src_s = pypacker.get_property_mac("src")
		dst = property(__get_dst, __set_dst)
		dst_s = pypacker.get_property_mac("dst")
		bssid = property(__get_bssid, __set_bssid)
		bssid_s = pypacker.get_property_mac("bssid")

		__QOS_SUBTYPES = {8, 9, 10, 11, 12, 14, 15}

		def _dissect(self, buf):
			# logger.debug("starting dissecting, buflen: %r" % str(buf))
			header_len = 30

			try:
				is_qos = True if self.dtype.subtype in IEEE80211.Dataframe.__QOS_SUBTYPES else False
				is_protected = self.dtype.protected == 1
				is_bridge = True if self.dtype.from_ds == 1 and self.dtype.to_ds == 1 else False
			except Exception:
				# logger.debug(e)
				# default is fromds
				is_qos = False
				is_protected = False
				is_bridge = False

			# logger.debug("switching fields1")
			if not is_qos:
				self.qos_ctrl = None
				header_len -= 2
			# logger.debug("switching fields2")
			if not is_protected:
				self.sec_param = None
				header_len -= 8
			# logger.debug("switching fields3")
			if is_bridge:
				self.addr4 = b"\x00" * 6
				header_len += 6
			# logger.debug("format/length/len(bin): %s/%d/%d" % (self._hdr_fmtstr, self.hdr_len, len(self.bin())))
			# logger.debug("%r" % self)
			return header_len
예제 #25
0
class Ethernet(pypacker.Packet):
    __hdr__ = (
        ("dst", "6s", b"\xff" * 6),
        ("src", "6s", b"\xff" * 6),
        ("vlan", "4s", None),
        # ("len", "H", None),
        ("type", "H", ETH_TYPE_IP)  # type = Ethernet II, len = 802.3
    )

    dst_s = pypacker.get_property_mac("dst")
    src_s = pypacker.get_property_mac("src")

    def _dissect(self, buf):
        hlen = 14
        # we need to check for VLAN TPID here (0x8100) to get correct header-length
        if buf[12:14] == b"\x81\x00":
            # logger.debug(">>> got vlan tag")
            self.vlan = buf[12:16]
            # logger.debug("re-extracting field: %s" % self.vlan)
            hlen = 18

        # check for DSAP via length
        type_len = unpack(">H", buf[12:14])[0]
        if type_len < 1536:
            # assume DSAP is following (802.2 DSAP)
            # self.len = type_len
            # deactivate eth_type field
            # logger.debug(">>> deactivating type")
            self.type = None
            self._init_handler(ETH_TYPE_LLC, buf[12:14])
            return

        # avoid calling unpack more than once
        eth_type = unpack(">H", buf[hlen - 2:hlen])[0]
        # logger.debug("hlen is: %d" % eth_type)

        # handle ethernet-padding: remove it but save for later use
        # don't use headers for this because this is a rare situation
        dlen = len(buf) - hlen  # data length [+ padding?]

        try:
            # this will only work on complete headers: Ethernet + IP + ...
            # handle padding using IPv4, IPv6
            # TODO: check for other protocols
            # logger.debug(">>> checking for padding")
            if eth_type == ETH_TYPE_IP:

                dlen_ip = unpack(">H",
                                 buf[hlen + 2:hlen + 4])[0]  # real data length

                if dlen_ip < dlen:
                    # padding found
                    # logger.debug("got padding for IPv4")
                    self._padding = buf[hlen + dlen_ip:]
                    dlen = dlen_ip
            # handle padding using IPv6
            # IPv6 is a piece of sh$§! payloadlength = exclusive standard header, INCLUSIVE options!
            elif eth_type == ETH_TYPE_IP6:
                dlen_ip = unpack(">H",
                                 buf[hlen + 4:hlen + 6])[0]  # real data length
                if 40 + dlen_ip < dlen:
                    # padding found
                    # logger.debug("got padding for IPv6")
                    self._padding = buf[hlen + dlen_ip:]
                    dlen = dlen_ip
        except struct.error:
            # logger.debug("could not extract padding info, assuming incomplete ethernet frame")
            pass
        except:
            logger.exception("could not extract padding info")

        self._init_handler(eth_type, buf[hlen:hlen + dlen])
        return hlen

    def bin(self, update_auto_fields=True):
        """Custom bin(): handle padding for Ethernet."""
        return pypacker.Packet.bin(
            self, update_auto_fields=update_auto_fields) + self.padding

    def __len__(self):
        return super().__len__() + len(self.padding)

    def direction(self, other):
        # logger.debug("checking direction: %s<->%s" % (self, other))
        if self.dst == other.dst and self.src == other.src:
            # consider packet to itself: can be DIR_REV
            return pypacker.Packet.DIR_SAME | pypacker.Packet.DIR_REV
        elif (self.dst == other.src and self.src == other.dst) or\
         (self.dst == b"\xff\xff\xff\xff\xff\xff" and other.dst == self.src):  # broadcast
            return pypacker.Packet.DIR_REV
        else:
            return pypacker.Packet.DIR_UNKNOWN

    # handle padding attribute
    def __get_padding(self):
        try:
            return self._padding
        except AttributeError:
            return b""

    def __set_padding(self, padding):
        self._padding = padding

    padding = property(__get_padding, __set_padding)

    def reverse_address(self):
        self.dst, self.src = self.src, self.dst