Skip to content

Commit 1346522

Browse files
authored
Add support for S1G beacon to the dot11 layer. (#2) (#4458)
* Add support for S1G beacon to the dot11 layer. (#2) - Includes unit test parsing and confirming an S1G beacon - Includes support for the new Frame Control format for type=3, subtype=1 (S1G beacon) - Includes changes to support addressing used in S1G beacon. All dot11 unit tests pass with this change. * More unit test changes to trigger workflows (#3) * Add support for S1G beacon to the dot11 layer. - Includes unit test parsing and confirming an S1G beacon - Includes support for the new Frame Control format for type=3, subtype=1 (S1G beacon) - Includes changes to support addressing used in S1G beacon. All dot11 unit tests pass with this change. * Update S1G beacon parsing based on code review. (#4) * Fix review comments from @p-l-: - Use set for 'type in' checks for extension frame type 3, subtype 1 (S1G beacon). * Update to FCfield to split into three parts for type 3, subtype 1 (S1G beacon frame control field). This allows use of BitField for the 'bw', and FlagsField for the remaining bits.
1 parent 706568b commit 1346522

File tree

2 files changed

+44
-4
lines changed

2 files changed

+44
-4
lines changed

scapy/layers/dot11.py

+26-4
Original file line numberDiff line numberDiff line change
@@ -691,7 +691,7 @@ def i2repr(self, pkt, val):
691691
return s
692692

693693

694-
# 802.11-2016 9.2.4.1.1
694+
# 802.11-2020 9.2.4.1.1
695695
class Dot11(Packet):
696696
name = "802.11"
697697
fields_desc = [
@@ -710,25 +710,39 @@ class Dot11(Packet):
710710
FlagsField("FCfield", 0, 4,
711711
["pw-mgt", "MD", "protected", "order"]),
712712
lambda pkt: (pkt.type, pkt.subtype) == (1, 6)
713+
),
714+
(
715+
FlagsField("FCfield", 0, 2,
716+
["security", "AP_PM"]),
717+
lambda pkt: (pkt.type, pkt.subtype) == (3, 1)
713718
)
714719
],
715720
FlagsField("FCfield", 0, 8,
716721
["to-DS", "from-DS", "MF", "retry",
717722
"pw-mgt", "MD", "protected", "order"])
718723
),
724+
ConditionalField(
725+
BitField("FCfield_bw", 0, 3),
726+
lambda pkt: (pkt.type, pkt.subtype) == (3, 1)
727+
),
728+
ConditionalField(
729+
FlagsField("FCfield2", 0, 3,
730+
["next_tbtt", "comp_ssid", "ano"]),
731+
lambda pkt: (pkt.type, pkt.subtype) == (3, 1)
732+
),
719733
ShortField("ID", 0),
720734
_Dot11MacField("addr1", ETHER_ANY, 1),
721735
ConditionalField(
722736
_Dot11MacField("addr2", ETHER_ANY, 2),
723-
lambda pkt: (pkt.type != 1 or
737+
lambda pkt: (pkt.type not in {1, 3} or
724738
pkt.subtype in [0x4, 0x5, 0x6, 0x8, 0x9, 0xa, 0xb, 0xe, 0xf]),
725739
),
726740
ConditionalField(
727741
_Dot11MacField("addr3", ETHER_ANY, 3),
728742
lambda pkt: (pkt.type in [0, 2] or
729743
((pkt.type, pkt.subtype) == (1, 6) and pkt.cfe == 6)),
730744
),
731-
ConditionalField(LEShortField("SC", 0), lambda pkt: pkt.type != 1),
745+
ConditionalField(LEShortField("SC", 0), lambda pkt: pkt.type not in {1, 3}),
732746
ConditionalField(
733747
_Dot11MacField("addr4", ETHER_ANY, 4),
734748
lambda pkt: (pkt.type == 2 and
@@ -744,7 +758,7 @@ def guess_payload_class(self, payload):
744758
if self.type == 0x02 and (
745759
0x08 <= self.subtype <= 0xF and self.subtype != 0xD):
746760
return Dot11QoS
747-
elif self.FCfield.protected:
761+
elif hasattr(self.FCfield, "protected") and self.FCfield.protected:
748762
# When a frame is handled by encryption, the Protected Frame bit
749763
# (previously called WEP bit) is set to 1, and the Frame Body
750764
# begins with the appropriate cryptographic header.
@@ -1840,6 +1854,12 @@ class Dot11CSA(Packet):
18401854
]
18411855

18421856

1857+
class Dot11S1GBeacon(_Dot11EltUtils):
1858+
name = "802.11 S1G Beacon"
1859+
fields_desc = [LEIntField("timestamp", 0),
1860+
ByteField("change_seq", 0)]
1861+
1862+
18431863
###################
18441864
# 802.11 Security #
18451865
###################
@@ -1989,13 +2009,15 @@ class Dot11CCMP(Dot11Encrypted):
19892009
bind_layers(Dot11, Dot11ProbeReq, subtype=4, type=0)
19902010
bind_layers(Dot11, Dot11ProbeResp, subtype=5, type=0)
19912011
bind_layers(Dot11, Dot11Beacon, subtype=8, type=0)
2012+
bind_layers(Dot11, Dot11S1GBeacon, subtype=1, type=3)
19922013
bind_layers(Dot11, Dot11ATIM, subtype=9, type=0)
19932014
bind_layers(Dot11, Dot11Disas, subtype=10, type=0)
19942015
bind_layers(Dot11, Dot11Auth, subtype=11, type=0)
19952016
bind_layers(Dot11, Dot11Deauth, subtype=12, type=0)
19962017
bind_layers(Dot11, Dot11Action, subtype=13, type=0)
19972018
bind_layers(Dot11, Dot11Ack, subtype=13, type=1)
19982019
bind_layers(Dot11Beacon, Dot11Elt,)
2020+
bind_layers(Dot11S1GBeacon, Dot11Elt,)
19992021
bind_layers(Dot11AssoReq, Dot11Elt,)
20002022
bind_layers(Dot11AssoResp, Dot11Elt,)
20012023
bind_layers(Dot11ReassoReq, Dot11Elt,)

test/scapy/layers/dot11.uts

+18
Original file line numberDiff line numberDiff line change
@@ -778,3 +778,21 @@ assert pkt[Dot11Elt::{"ID": 74}].len == 14
778778

779779
pkt = Dot11EltCSA(b'%\x03\x01\x0b\x05')
780780
assert pkt[Dot11Elt::{"ID": 37}].len == 3
781+
782+
= Dot11S1GBeacon
783+
784+
pkt=Dot11(b"\x1c\x18\x00\x00,/u\x1c\x103hq\xf8\x00\x00\xd5\x08\x01\x00d\x00\x00\x00\x00\x00\x05\x02\x00\x01\xd9\x0f\x9e\x00@\x18\x80\x0c\x00\x02@\x00\xfe\x00\xfc\x01\x00\xe8\x06\x06\x18&(\xc4\xcc\xd6\x02d\x00\x00\nWiFiDiving\xdd\x18\x00P\xf2\x02\x01\x01\x01\x00\x03\xa4\xd5\x01'\xa4\xd5\x01BC\xd5\x01b2\xd5\x01")
785+
assert pkt[Dot11].type == 3
786+
assert pkt[Dot11].subtype == 1
787+
assert pkt[Dot11].addr1 == '2c:2f:75:1c:10:33'
788+
assert pkt[Dot11S1GBeacon].timestamp == 16281960
789+
assert pkt[Dot11Elt::{"ID": 0}].info == b"WiFiDiving"
790+
assert pkt[Dot11Elt::{"ID": 214}].len == 2
791+
assert pkt[Dot11Elt::{"ID": 217}].len == 15
792+
assert pkt[Dot11Elt::{"ID": 232}].len == 6
793+
assert pkt[Dot11].FCfield_bw == 3
794+
assert pkt[Dot11].FCfield2.next_tbtt == False
795+
assert pkt[Dot11].FCfield2.comp_ssid == False
796+
assert pkt[Dot11].FCfield2.ano == False
797+
assert pkt[Dot11].FCfield.security == False
798+
assert pkt[Dot11].FCfield.AP_PM == False

0 commit comments

Comments
 (0)