diff --git a/scapy/layers/dot11.py b/scapy/layers/dot11.py index 96cf6619847..862ed6686de 100644 --- a/scapy/layers/dot11.py +++ b/scapy/layers/dot11.py @@ -1439,22 +1439,25 @@ class Dot11EltVendorSpecific(Dot11Elt): def dispatch_hook(cls, _pkt=None, *args, **kargs): if _pkt: oui = struct.unpack("!I", b"\x00" + _pkt[2:5])[0] - if oui == 0x0050f2: # Microsoft - type_ = orb(_pkt[5]) - if type_ == 0x01: - # MS WPA IE - return Dot11EltMicrosoftWPA - elif type_ == 0x02: - # MS WME IE TODO - # return Dot11EltMicrosoftWME - pass - elif type_ == 0x04: - # MS WPS IE TODO - # return Dot11EltWPS - pass - return Dot11EltVendorSpecific + ouicls = cls.registered_ouis.get(oui, cls) + if ouicls.dispatch_hook != cls.dispatch_hook: + # Sub-classes can have their own dispatch_hook + return ouicls.dispatch_hook(_pkt=_pkt, *args, **kargs) + cls = ouicls return cls + registered_ouis = {} + + @classmethod + def register_variant(cls): + oui = cls.oui.default + if not oui: + # This is Dot11EltVendorSpecific, register it in the super-class. + super().register_variant() + elif oui not in cls.registered_ouis: + # Sub-Vendor (e.g. Dot11EltMicrosoftWPA) + cls.registered_ouis[oui] = cls + class Dot11EltMicrosoftWPA(Dot11EltVendorSpecific): name = "802.11 Microsoft WPA" @@ -1467,6 +1470,24 @@ class Dot11EltMicrosoftWPA(Dot11EltVendorSpecific): XByteField("type", 0x01) ] + Dot11EltRSN.fields_desc[2:8] + @classmethod + def dispatch_hook(cls, _pkt=None, *args, **kargs): + if _pkt: + type_ = orb(_pkt[5]) + if type_ == 0x01: + # MS WPA IE + return Dot11EltMicrosoftWPA + elif type_ == 0x02: + # MS WME IE TODO + # return Dot11EltMicrosoftWME + pass + elif type_ == 0x04: + # MS WPS IE TODO + # return Dot11EltWPS + pass + return Dot11EltVendorSpecific + return cls + # 802.11-2016 9.4.2.19