From 74eaf0c551901d1bb1b496e51ef24b9a3fb51a8c Mon Sep 17 00:00:00 2001 From: Ugur Dogru Date: Thu, 23 Jul 2026 11:53:06 +0300 Subject: [PATCH] Add 802.11 EHT Operation element support AI-Assisted: yes (Codex) --- scapy/layers/dot11.py | 62 +++++++++++++++++++++++++++++++++++++ test/scapy/layers/dot11.uts | 46 +++++++++++++++++++++++++++ 2 files changed, 108 insertions(+) diff --git a/scapy/layers/dot11.py b/scapy/layers/dot11.py index bef8452355d..f8dc5a7ea9e 100644 --- a/scapy/layers/dot11.py +++ b/scapy/layers/dot11.py @@ -1723,6 +1723,68 @@ class Dot11EltHTOperation(Dot11Elt): ] +# 802.11be D7.0 9.4.2.311 + +class Dot11EHTOperationInfo(Packet): + name = "802.11 EHT Operation Information" + fields_desc = [ + BitField("reserved", 0, 5, tot_size=-1), + BitField("channel_width", 0, 3, end_tot_size=-1), + ByteField("channel_center0", 0), + ByteField("channel_center1", 0), + ] + + def extract_padding(self, s): + return b"", s + + +# 802.11be D7.0 9.4.2.311 + +class Dot11EltEHTOperation(Dot11EltExtension): + name = "802.11 EHT Operation" + match_subclass = True + ID = 255 + ext_ID = 106 + fields_desc = Dot11EltExtension.fields_desc + [ + # EHT Operation Parameters: 1B + BitField("reserved", 0, 2, tot_size=-1), + BitField("group_addressed_bu_indication_exponent", 0, 2), + BitField("group_addressed_bu_indication_limit", 0, 1), + BitField("eht_default_pe_duration", 0, 1), + BitField("disabled_subchannel_bitmap_present", 0, 1), + BitField( + "eht_operation_information_present", + 0, + 1, + end_tot_size=-1 + ), + + LEIntField("basic_eht_mcs_and_nss_set", 0), + + ConditionalField( + PacketField( + "eht_operation_info", + Dot11EHTOperationInfo(), + Dot11EHTOperationInfo, + ), + lambda p: ( + p.eht_operation_information_present == 1 and + p.len >= 9 + )), + + ConditionalField( + LEShortField("disabled_subchannel_bitmap", 0), + lambda p: ( + p.eht_operation_information_present == 1 and + p.disabled_subchannel_bitmap_present == 1 and + p.len >= 11 + )), + ] + + +Dot11EltEHTOperation.register_variant(106) + + ###################### # 802.11 Frame types # ###################### diff --git a/test/scapy/layers/dot11.uts b/test/scapy/layers/dot11.uts index ac0573c3063..fbdc51ca299 100644 --- a/test/scapy/layers/dot11.uts +++ b/test/scapy/layers/dot11.uts @@ -964,6 +964,52 @@ assert pkt[Dot11HE6GOperationInfo].channel_center1 == 0 assert pkt[Dot11HE6GOperationInfo].minimum_rate == 12 assert raw(pkt) == data += Dot11EltEHTOperation without Operation Information in isolation + +data = b'\xff\x06j\x00\x04\x03\x02\x01' +pkt = Dot11Elt(data) +assert Dot11EltEHTOperation in pkt +assert pkt[Dot11EltEHTOperation].ID == 255 +assert pkt[Dot11EltEHTOperation].len == 6 +assert pkt[Dot11EltEHTOperation].ext_ID == 106 +assert pkt[Dot11EltEHTOperation].eht_operation_information_present == 0 +assert pkt[Dot11EltEHTOperation].disabled_subchannel_bitmap_present == 0 +assert pkt[Dot11EltEHTOperation].basic_eht_mcs_and_nss_set == 0x01020304 +assert "eht_operation_info" not in pkt[Dot11EltEHTOperation].fields +assert "disabled_subchannel_bitmap" not in pkt[Dot11EltEHTOperation].fields +assert raw(pkt) == data + += Dot11EltEHTOperation with Operation Information in isolation + +data = b'\xff\tj\x01\x04\x03\x02\x01\x04\x0f\x1f' +pkt = Dot11Elt(data) +assert Dot11EltEHTOperation in pkt +assert Dot11EHTOperationInfo in pkt +assert pkt[Dot11EltEHTOperation].eht_operation_information_present == 1 +assert pkt[Dot11EltEHTOperation].disabled_subchannel_bitmap_present == 0 +assert pkt[Dot11EltEHTOperation].basic_eht_mcs_and_nss_set == 0x01020304 +assert pkt[Dot11EHTOperationInfo].channel_width == 4 +assert pkt[Dot11EHTOperationInfo].channel_center0 == 15 +assert pkt[Dot11EHTOperationInfo].channel_center1 == 31 +assert "disabled_subchannel_bitmap" not in pkt[Dot11EltEHTOperation].fields +assert raw(pkt) == data + += Dot11EltEHTOperation with Disabled Subchannel Bitmap in isolation + +data = b'\xff\x0bj\x03\x04\x03\x02\x01\x04\x0f\x1f\x34\x12\x00\x04test' +pkt = Dot11Elt(data) +assert Dot11EltEHTOperation in pkt +assert Dot11EHTOperationInfo in pkt +assert pkt[Dot11EltEHTOperation].eht_operation_information_present == 1 +assert pkt[Dot11EltEHTOperation].disabled_subchannel_bitmap_present == 1 +assert pkt[Dot11EltEHTOperation].disabled_subchannel_bitmap == 0x1234 +assert pkt[Dot11EHTOperationInfo].channel_width == 4 +assert pkt[Dot11EHTOperationInfo].channel_center0 == 15 +assert pkt[Dot11EHTOperationInfo].channel_center1 == 31 +assert pkt[Dot11EltEHTOperation].payload.ID == 0 +assert pkt[Dot11EltEHTOperation].payload.info == b'test' +assert raw(pkt) == data + = Dot11EltOBSS in isolation pkt = Dot11EltOBSS(b'J\x0e\x14\x00\n\x00,\x01\xc8\x00\x14\x00\x05\x00\x19\x00')