From 4c7b569c8b7e3e83dae31118f1f33e9c80ae14ea Mon Sep 17 00:00:00 2001 From: Pierre LALET <pierre.lalet@cea.fr> Date: Wed, 5 Apr 2017 10:50:29 +0200 Subject: [PATCH] Dot11: use ConditionalField() to replace .is_applicable() methods Some fields in Dot11 protocols were using specific .is_applicable() methods to implement similar features than ConditionalField() (which probably didn't exist by the time Dot11 dissectors have been written). This commit uses ConditionalField and removes specific field classes to use generic (MACField and LEShortField) fields. This should make the code easier to understand. This will also prevent some fields from being displayed when they should not: >>> Dot11().show() ###[ 802.11 ]### subtype= 0 type= Management proto= 0 FCfield= ID= 0 addr1= 00:00:00:00:00:00 addr2= 00:00:00:00:00:00 addr3= 00:00:00:00:00:00 SC= 0 >>> Dot11(type=2, FCfield=3).show() ###[ 802.11 ]### subtype= 0 type= Data proto= 0 FCfield= to-DS+from-DS ID= 0 addr1= 00:00:00:00:00:00 addr2= 00:00:00:00:00:00 addr3= 00:00:00:00:00:00 SC= 0 addr4= 00:00:00:00:00:00 >>> Dot11(type=1).show() ###[ 802.11 ]### subtype= 0 type= Control proto= 0 FCfield= ID= 0 addr1= 00:00:00:00:00:00 --- scapy/layers/dot11.py | 86 ++++++++++++------------------------------- 1 file changed, 24 insertions(+), 62 deletions(-) diff --git a/scapy/layers/dot11.py b/scapy/layers/dot11.py index 1bdbe33e..1d4a1b12 100644 --- a/scapy/layers/dot11.py +++ b/scapy/layers/dot11.py @@ -29,42 +29,6 @@ else: log_loading.info("Can't import python-cryptography v1.7+. Disabled WEP decryption/encryption.") -### Fields - -class Dot11AddrMACField(MACField): - def is_applicable(self, pkt): - return 1 - def addfield(self, pkt, s, val): - if self.is_applicable(pkt): - return MACField.addfield(self, pkt, s, val) - else: - return s - def getfield(self, pkt, s): - if self.is_applicable(pkt): - return MACField.getfield(self, pkt, s) - else: - return s,None - -class Dot11Addr2MACField(Dot11AddrMACField): - # Block-Ack, RTS, PS-Poll, CF-End, CF-End+CF-Ack - subtypes = {0x9, 0xb, 0xa, 0xe, 0xf} - def is_applicable(self, pkt): - return pkt.type != 1 or pkt.subtype in self.subtypes - -class Dot11Addr3MACField(Dot11AddrMACField): - def is_applicable(self, pkt): - if pkt.type in [0,2]: - return 1 - return 0 - -class Dot11Addr4MACField(Dot11AddrMACField): - def is_applicable(self, pkt): - if pkt.type == 2: - if pkt.FCfield & 0x3 == 0x3: # To-DS and From-DS are set - return 1 - return 0 - - ### Layers @@ -143,35 +107,33 @@ class PPI(Packet): ] - -class Dot11SCField(LEShortField): - def is_applicable(self, pkt): - return pkt.type != 1 # control frame - def addfield(self, pkt, s, val): - if self.is_applicable(pkt): - return LEShortField.addfield(self, pkt, s, val) - else: - return s - def getfield(self, pkt, s): - if self.is_applicable(pkt): - return LEShortField.getfield(self, pkt, s) - else: - return s,None - 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", "wep", "order"]), - ShortField("ID",0), - MACField("addr1", ETHER_ANY), - Dot11Addr2MACField("addr2", ETHER_ANY), - Dot11Addr3MACField("addr3", ETHER_ANY), - Dot11SCField("SC", 0), - Dot11Addr4MACField("addr4", ETHER_ANY) - ] + 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", "wep", "order"]), + ShortField("ID",0), + MACField("addr1", ETHER_ANY), + ConditionalField( + MACField("addr2", ETHER_ANY), + lambda pkt: (pkt.type != 1 or + pkt.subtype in [0x9, 0xb, 0xa, 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): return self.sprintf("802.11 %Dot11.type% %Dot11.subtype% %Dot11.addr2% > %Dot11.addr1%") def guess_payload_class(self, payload): -- GitLab