class Deauth(packetracer.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 = packetracer.get_property_mac("dst") bssid_s = packetracer.get_property_mac("bssid") src_s = packetracer.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
class AssocResp(packetracer.Packet): __hdr__ = (("dst", "6s", b"\x00" * 6), ("src", "6s", b"\x00" * 6), ("bssid", "6s", b"\x00" * 6), ("seq_frag", "H", 0), ("capa", "H", 0), ("status", "H", 0), ("aid", "H", 0), ("params", None, triggerlist.TriggerList)) dst_s = packetracer.get_property_mac("dst") bssid_s = packetracer.get_property_mac("bssid") src_s = packetracer.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
class RTS(packetracer.Packet): __hdr__ = (("dst", "6s", b"\x00" * 6), ("src", "6s", b"\x00" * 6)) dst_s = packetracer.get_property_mac("dst") src_s = packetracer.get_property_mac("src") def reverse_address(self): self.dst, self.src = self.src, self.dst
class BlockAck(packetracer.Packet): __hdr__ = (("dst", "6s", b"\x00" * 6), ("src", "6s", b"\x00" * 6), ("reqctrl", "H", 0), ("seq", "H", 0), ("bitmap", "Q", 0)) dst_s = packetracer.get_property_mac("dst") src_s = packetracer.get_property_mac("src") def reverse_address(self): self.dst, self.src = self.src, self.dst
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 = packetracer.get_property_mac("msoundtarget") forwardingsta_s = packetracer.get_property_mac("forwardingsta")
class Action(packetracer.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(packetracer.Packet): __hdr__ = ( ("dialog", "B", 0), ("parameters", "H", 0), ("timeout", "H", 0), ("starting_seq", "H", 0), ) class BlockAckResponse(packetracer.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 = packetracer.get_property_mac("dst") src_s = packetracer.get_property_mac("src") bssid_s = packetracer.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
class CMPKCSCertReq(Packet): __hdr__ = ( ("targetmac", "6s", b"\x00" * 6), ("ciphersuitesize", "B", 0), ("cipersuite", None, TriggerList) ) targetmac_s = packetracer.get_property_mac("targetmac")
class ARP(packetracer.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 = packetracer.get_property_mac("sha") spa_s = packetracer.get_property_ip4("spa") tha_s = packetracer.get_property_mac("tha") tpa_s = packetracer.get_property_ip4("tpa")
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 = packetracer.get_property_mac("pevmac") evsemac_s = packetracer.get_property_mac("evsemac")
class CMPKCSCertCnf(Packet): __hdr__ = ( ("targetmac", "6s", b"\x00" * 6), ("status", "B", 0), ("cipersuite", "H", 0), ("certlen", "H", 0), ("certpackage", None, TriggerList) ) targetmac_s = packetracer.get_property_mac("targetmac")
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 = packetracer.get_property_mac("dasa")
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 = packetracer.get_property_mac("forwardingsta")
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 = packetracer.get_property_mac("sourceaddr")
class ReassocReq(packetracer.Packet): __hdr__ = (("dst", "6s", b"\x00" * 6), ("src", "6s", b"\x00" * 6), ("bssid", "6s", b"\x00" * 6), ("seq_frag", "H", 0), ("capa", "H", 0), ("interval", "H", 0), ("current_ap", "6s", b"\x00" * 6)) dst_s = packetracer.get_property_mac("dst") bssid_s = packetracer.get_property_mac("bssid") src_s = packetracer.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
class Beacon(packetracer.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 = packetracer.get_property_mac("dst") bssid_s = packetracer.get_property_mac("bssid") src_s = packetracer.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
class Auth(packetracer.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 = packetracer.get_property_mac("dst") bssid_s = packetracer.get_property_mac("bssid") src_s = packetracer.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
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 = packetracer.get_property_mac("pevmac") evsemac_s = packetracer.get_property_mac("evsemac")
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 = packetracer.get_property_mac("targetmac")
class LACPActorInfoTlv(packetracer.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 = packetracer.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")
class Ethernet(packetracer.Packet): __hdr__ = [("dst", "6s", b"\xff" * 6), ("src", "6s", b"\xff" * 6), ("vlan", None, triggerlist.TriggerList), ("type", "H", ETH_TYPE_IP, FIELD_FLAG_IS_TYPEFIELD)] dst_s = packetracer.get_property_mac("dst") src_s = packetracer.get_property_mac("src") type_t = packetracer.get_property_translator("type", "ETH_TYPE_") __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, ETH_TYPE_SLAC: slac.Slac } 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 higher 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 higher 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(higher_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: # Could not extract padding info, assuming incomplete ethernet frame. # Init of handler will take place after all. pass # logger.debug("len(buf)=%d, len(higher)=%d" % (len(buf), dlen)) self._init_handler(eth_type, buf[hlen:hlen + dlen]) return hlen def _update_fields(self): self._update_higherlayer_id() def bin(self, update_auto_fields=True): # padding needs to be placed at the very end return packetracer.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 packetracer.Packet.DIR_SAME | packetracer.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 packetracer.Packet.DIR_REV return packetracer.Packet.DIR_UNKNOWN padding = packetracer.get_ondemand_property("padding", lambda: b"") def reverse_address(self): self.dst, self.src = self.src, self.dst
class ACK(packetracer.Packet): __hdr__ = (("dst", "6s", b"\x00" * 6), ) dst_s = packetracer.get_property_mac("dst")
class Dataframe(packetracer.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 = packetracer.get_property_mac("src") dst = property(__get_dst, __set_dst) dst_s = packetracer.get_property_mac("dst") bssid = property(__get_bssid, __set_bssid) bssid_s = packetracer.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