class Dot11ReassoReq(Packet): name = "802.11 Reassociation Request" fields_desc = [ FlagsField("cap", 0, 16, capability_list), LEShortField("listen_interval", 0x00c8), MACField("current_AP", ETHER_ANY) ]
class YOARP(Packet): name = "YOARP" fields_desc = [ XShortField("hwtype", 0x0001), XShortEnumField("ptype", 0x9999, ETHER_TYPES), ByteField("hwlen", 6), ByteField("plen", 2), ShortEnumField("op", 1, {"who-has": 1, "is-at": 2, "RARP-req": 3, "RARP-rep": 4, "Dyn-RARP-req": 5, "Dyn-RAR-rep": 6, "Dyn-RARP-err": 7, "InARP-req": 8, "InARP-rep": 9}), ARPSourceMACField("hwsrc"), YOIPField("psrc", "0.0"), MACField("hwdst", ETHER_ANY), YOIPField("pdst", "0.0") ] who_has = 1 is_at = 2 def extract_padding(self, s): return "", s def answers(self, other): if isinstance(other, YOARP): if ((self.op == self.is_at) and (other.op == self.who_has) and (self.psrc == other.pdst)): return 1 return 0 @classmethod def dispatch_hook(cls, _pkt=None, *args, **kargs): if _pkt and len(_pkt) >= 4 and _pkt[2:4] == "\x08\x00": return ARP return cls
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