IEEE 802.11 - Wireless LAN MAC Header

pcapkit.protocols.link.ieee802_11 contains IEEE802_11 only, which implements the extractor for the IEEE 802.11 MAC header [*] of a protocol version 0 frame, as a LINKTYPE_IEEE802_11 capture carries it or Radiotap hands it on. Its fields, in the order they appear, numeric ones little-endian:

Name

Octets

Present

frame_control

2

always (§9.2.4.1)

duration_id

2

always (§9.2.4.2)

addr1

6

always (§9.2.4.3)

addr2

6

Management, Data, and Control frames that carry a TA (§9.2.4.3, §9.3.1)

addr3

6

Management and Data frames (§9.2.4.3)

seq_ctrl

2

Management and Data frames (§9.2.4.4)

addr4

6

Data frames with To DS and From DS set (§9.2.4.3)

qos_control

2

QoS Data subtypes (§9.2.4.5)

ht_control

4

QoS Data subtypes and Management frames with +HTC/Order set (§9.2.4.6)

layout() gives the rule per frame type. A Control frame of a subtype whose layout this class does not model, and an Extension frame, are read as the minimal frame format of §9.2.3: the first three fields only. A Control Frame Extension frame and an S1G Beacon lay out B8-B15 of Frame Control differently; see FrameControl.

Scope

  • The frame body (§9.2.4.7) is kept as Raw, protected or not.

  • The FCS (§9.2.4.8), where one was captured, stays at the end of the body: this class does not decide whether a capture carries one, which behind radiotap is a Flags bit Radiotap decodes but does not pass on.

  • Pad octets that radiotap’s data-pad flag says follow the header stay at the start of the body, for the same reason.

  • A protocol version other than 0 is refused: version 1 is the PV1 frame format of §9.8, whose Frame Control field is laid out differently, and versions 2 and 3 are reserved.

class pcapkit.protocols.link.ieee802_11.IEEE802_11(file=None, length=None, **kwargs)[source]

Bases: Link[IEEE802_11, IEEE802_11]

This class implements the IEEE 802.11 MAC header.

The frame body is kept as Raw; see the module docstring.

property name: Literal['IEEE 802.11 Wireless LAN']

Name of current protocol.

property alias: Literal['802.11']

Acronym of corresponding protocol.

property length: int

Header length of current protocol, from the fields its Frame Control declares.

classmethod id()[source]

Index ID of the protocol.

Return type:

tuple[Literal['IEEE802_11']]

read(length=None, **kwargs)[source]

Read IEEE 802.11 MAC header.

Structure of the MAC header with every field present (IEEE Std 802.11-2020 §9.2.3, General frame format), in octets:

+-------+--------+------+------+------+------+------+-----+-----+------+-----+
| Frame | Dura-  | Addr | Addr | Addr | Seq  | Addr | QoS | HT  | Body | FCS |
| Ctrl  | tion/ID|  1   |  2   |  3   | Ctrl |  4   | Ctl | Ctl |      |     |
+-------+--------+------+------+------+------+------+-----+-----+------+-----+
    2       2       6      6      6      2      6      2     4    var.    4
Parameters:
  • length (int | None) – Length of packet data.

  • **kwargs (Any) – Arbitrary keyword arguments.

Return type:

IEEE802_11

Returns:

Parsed packet data.

Raises:

ProtocolError – If the protocol version is not 0.

make(type=Type.Data, subtype=0, version=0, to_ds=None, from_ds=None, more_fragments=None, retry=None, control_frame_extension=None, power_management=None, more_data=None, protected=None, order=None, s1g_beacon_flags=None, duration_id=0, addr1='00:00:00:00:00:00', addr2=None, addr3=None, seq_ctrl=None, addr4=None, qos_control=None, ht_control=None, payload=b'', **kwargs)[source]

Make (construct) packet data.

The Frame Control subfields decide which fields the header carries, as layout() reads them. A field the header carries and the caller leaves out is written as zeros; a field the header does not carry must be left out.

Parameters:
Return type:

IEEE802_11

Returns:

Constructed packet data.

Raises:

ProtocolError – If a value does not fit its field, if type or subtype is a name or a member or code its field cannot carry, if version is not 0, or if a field is given that the header does not carry.

__length_hint__()[source]

Return an estimated length for the object.

The longest form – every optional field present, 36 octets – per the reason L2TPv2.__length_hint__ gives for a variable-length header.

Return type:

Literal[36]

classmethod __index__()[source]

Numeral registry index of the protocol.

Return type:

LinkType

Returns:

Numeral registry index of the protocol in tcpdump link-layer header types, which Radiotap.__proto__ is keyed by too.

classmethod _make_data(data)[source]

Create key-value pairs from data for protocol construction.

Parameters:

data (IEEE802_11) – protocol data

Return type:

dict[str, Any]

Returns:

Key-value pairs for protocol construction.

_read_frame_control(value)[source]

Read the Frame Control field (IEEE Std 802.11-2020 §9.2.4.1).

In a Control Frame Extension frame, B8-B11 are the Control Frame Extension subfield rather than To DS, From DS, More Fragments and Retry (§9.2.4.1.1). In an S1G Beacon, B8-B15 are the subfields Wireshark’s packet-ieee80211.c reads as wlan.fc.s1g.*, so none of the eight flags is read there.

Parameters:

value (int) – Frame Control field, as a little-endian integer.

Return type:

FrameControl

Returns:

Parsed Frame Control field.

_make_frame_control(*, version, type, subtype, to_ds, from_ds, more_fragments, retry, control_frame_extension, power_management, more_data, protected, order, s1g_beacon_flags)[source]

Make the Frame Control field (IEEE Std 802.11-2020 §9.2.4.1).

Parameters:
  • version (int) – Protocol Version.

  • type (int) – Type.

  • subtype (int) – Subtype.

  • to_ds (bool | None) – To DS.

  • from_ds (bool | None) – From DS.

  • more_fragments (bool | None) – More Fragments.

  • retry (bool | None) – Retry.

  • control_frame_extension (int | None) – Control Frame Extension.

  • power_management (bool | None) – Power Management.

  • more_data (bool | None) – More Data.

  • protected (bool | None) – Protected Frame.

  • order (bool | None) – +HTC/Order.

  • s1g_beacon_flags (int | None) – B8-B15 of an S1G Beacon.

Return type:

int

Returns:

Frame Control field, as a little-endian integer.

Raises:

ProtocolError – If version is not 0; if a Control Frame Extension frame sets any of to_ds, from_ds, more_fragments and retry, or an S1G Beacon sets any flag; if control_frame_extension or s1g_beacon_flags is given for a frame that does not carry it; or if a subfield does not fit.

_read_seq_ctrl(value)[source]

Read the Sequence Control field (IEEE Std 802.11-2020 §9.2.4.4).

Parameters:

value (int) – Sequence Control field, as a little-endian integer.

Return type:

SequenceControl

Returns:

Parsed Sequence Control field.

_make_seq_ctrl(seq_ctrl)[source]

Make the Sequence Control field (IEEE Std 802.11-2020 §9.2.4.4).

Parameters:

seq_ctrl (SequenceControl | Mapping[str, int] | None) – Sequence Control field; None makes zeros.

Return type:

int

Returns:

Sequence Control field, as a little-endian integer.

Raises:

ProtocolError – If a subfield does not fit.

_read_qos_control(value)[source]

Read the QoS Control field (IEEE Std 802.11-2020 §9.2.4.5).

Parameters:

value (int) – QoS Control field, as a little-endian integer.

Return type:

QoSControl

Returns:

Parsed QoS Control field.

_make_qos_control(qos_control)[source]

Make the QoS Control field (IEEE Std 802.11-2020 §9.2.4.5).

Parameters:

qos_control (QoSControl | Mapping[str, Any] | None) – QoS Control field; None makes zeros.

Return type:

int

Returns:

QoS Control field, as a little-endian integer.

Raises:

ProtocolError – If a subfield does not fit.

_read_ht_control(value)[source]

Read the HT Control field (IEEE Std 802.11-2020 §9.2.4.6).

Parameters:

value (int) – HT Control field, as a little-endian integer.

Return type:

HTControl

Returns:

Parsed HT Control field.

_make_ht_control(value)[source]

Make the HT Control field (IEEE Std 802.11-2020 §9.2.4.6).

Parameters:

value (int | None) – HT Control field, as an integer; None makes zeros.

Return type:

int

Returns:

HT Control field, as a little-endian integer.

Raises:

ProtocolError – If value does not fit in 32 bits.

_make_mac_addr(addr, *, size=6, name='MAC address', alias=None)[source]

Make MAC address.

Parameters:
Return type:

bytes

Returns:

MAC address packed as size octets, 6 by default.

Raises:

ProtocolError – If addr is not a :- or --separated hex encoded MAC address.

pcapkit.protocols.link.ieee802_11.SUBTYPE: dict[int, Type[ManagementSubtype | ControlSubtype | DataSubtype | ExtensionSubtype]]

Subtype registry of each frame type (IEEE Std 802.11-2020, Table 9-1).

Header Schemas

class pcapkit.protocols.schema.link.ieee802_11.IEEE802_11(frame_control=NO_VALUE, duration_id=NO_VALUE, addr1=NO_VALUE, addr2=NO_VALUE, addr3=NO_VALUE, seq_ctrl=NO_VALUE, addr4=NO_VALUE, qos_control=NO_VALUE, ht_control=NO_VALUE, payload=NO_VALUE, *, __packet__=None, **kwargs)[source]

Bases: Schema

Header schema for an IEEE 802.11 MAC header (IEEE Std 802.11-2020 §9.2).

frame_control: int = <UInt16Field frame_control>

Frame Control.

duration_id: int = <UInt16Field duration_id>

Duration/ID.

addr1: bytes = <BytesField addr1>

Address 1.

addr2: bytes | None = <ConditionalField addr2>

Address 2, where layout() says so.

addr3: bytes | None = <ConditionalField addr3>

Address 3, where layout() says so.

seq_ctrl: int | None = <ConditionalField seq_ctrl>

Sequence Control, where layout() says so.

addr4: bytes | None = <ConditionalField addr4>

Address 4, where layout() says so.

qos_control: int | None = <ConditionalField qos_control>

QoS Control, where layout() says so.

ht_control: int | None = <ConditionalField ht_control>

HT Control, where layout() says so.

payload: bytes = <PayloadField payload>

Frame body, and the FCS where one was captured.

pcapkit.protocols.schema.link.ieee802_11.layout(frame_control)[source]

Decide which fields a protocol version 0 MAC header carries.

  • A Management frame carries Address 2, Address 3 and Sequence Control whatever its subtype, and HT Control when +HTC/Order is set (IEEE Std 802.11-2020 §9.3.3, Management frames; §9.2.4.1.10, +HTC/Order subfield).

  • A Data frame carries the same three, Address 4 when To DS and From DS are both set, QoS Control when the QoS bit (B7) of its subtype is set, and HT Control when that bit and +HTC/Order are both set (§9.3.2, Data frames).

  • A Control frame carries Address 2 for the subtypes in CONTROL_WITH_ADDR2, and Address 1 alone for CTS and Ack (§9.3.1, Control frames).

  • Every other frame – a reserved Control subtype, a Control Wrapper, whose octets after Address 1 are Carried Frame Control and HT Control, and every Extension frame – is read as the minimal frame format that §9.2.3, General frame format, makes present in every frame, reserved types and subtypes included: Frame Control, Duration/ID and Address 1. What follows stays in the frame body.

This departs from the Linux kernel’s ieee80211_hdrlen() deliberately: a Control Wrapper and the reserved Control subtypes 0 and 1 read 10 octets where it gives 16, and an Extension frame reads 10 where it gives 4.

Parameters:

frame_control (int) – Frame Control field, as the little-endian integer read off the wire.

Return type:

Layout

Returns:

The fields present after Address 1.

class pcapkit.protocols.schema.link.ieee802_11.Layout(addr2, addr3, seq_ctrl, addr4, qos_control, ht_control)[source]

Bases: NamedTuple

Fields a MAC header carries after Frame Control, Duration/ID and Address 1.

addr2: bool

Address 2.

addr3: bool

Address 3.

seq_ctrl: bool

Sequence Control.

addr4: bool

Address 4.

qos_control: bool

QoS Control.

ht_control: bool

HT Control.

pcapkit.protocols.schema.link.ieee802_11.CONTROL_WITH_ADDR2

Control frame subtypes whose MAC header carries a TA (or BSSID) as Address 2 after the RA; IEEE Std 802.11-2020 §9.3.1, Control frames, and IEEE Std 802.11ax-2021 for Trigger. CTS and Ack carry the RA alone. A Control Frame Extension frame takes the six octets after the RA as Address 2, as the Linux kernel’s ieee80211_hdrlen() reads it; in a DMG DTS (extension 6) they are NAV-SA rather than a TA, and NAV-DA stays in the body.

Data Models

class pcapkit.protocols.data.link.ieee802_11.IEEE802_11(frame_control, duration_id, addr1, addr2, addr3, seq_ctrl, addr4, qos_control, ht_control)[source]

Bases: Protocol

Data model for an IEEE 802.11 MAC header (IEEE Std 802.11-2020 §9.2).

A field the header does not carry is None; see layout().

frame_control: FrameControl

Frame Control.

duration_id: int

Duration/ID; the AID in a PS-Poll frame.

addr1: str

Address 1.

addr2: str | None

Address 2.

addr3: str | None

Address 3.

seq_ctrl: SequenceControl | None

Sequence Control.

addr4: str | None

Address 4.

qos_control: QoSControl | None

QoS Control.

ht_control: HTControl | None

HT Control.

class pcapkit.protocols.data.link.ieee802_11.FrameControl(version, type, subtype, to_ds, from_ds, more_fragments, retry, control_frame_extension, power_management, more_data, protected, order, s1g_beacon_flags)[source]

Bases: Data

Data model for the Frame Control field (IEEE Std 802.11-2020 §9.2.4.1).

Two frames lay out B8-B15 differently, and the flags they replace are None there: a Control Frame Extension frame carries control_frame_extension in B8-B11, and an S1G Beacon carries s1g_beacon_flags in all of B8-B15.

version: int

Protocol Version.

type: Type

Type.

subtype: ManagementSubtype | ControlSubtype | DataSubtype | ExtensionSubtype

Subtype, from the registry type selects.

to_ds: bool | None

To DS.

from_ds: bool | None

From DS.

more_fragments: bool | None

More Fragments.

retry: bool | None

Retry.

control_frame_extension: int | None

Control Frame Extension (B8-B11) of a Control Frame Extension frame; None in any other frame.

power_management: bool | None

Power Management.

more_data: bool | None

More Data.

protected: bool | None

Protected Frame.

order: bool | None

+HTC/Order.

s1g_beacon_flags: int | None

B8-B15 of an S1G Beacon, kept whole – Next TBTT Present, Compressed SSID Present, ANO Present, BSS BW, Security and AP PM, as Wireshark’s packet-ieee80211.c names them; None in any other frame.

class pcapkit.protocols.data.link.ieee802_11.SequenceControl(fragment_number, sequence_number)[source]

Bases: Data

Data model for the Sequence Control field (IEEE Std 802.11-2020 §9.2.4.4).

fragment_number: int

Fragment Number.

sequence_number: int

Sequence Number.

class pcapkit.protocols.data.link.ieee802_11.QoSControl(tid, eosp, ack_policy, amsdu_present, bits_8_15)[source]

Bases: Data

Data model for the QoS Control field (IEEE Std 802.11-2020 §9.2.4.5).

Only the subfields every QoS Data subtype places alike are decoded. What bits 8-15 carry depends on the subtype and on the kind of station that sent the frame, which the MAC header does not say, so they are kept whole as bits_8_15.

tid: int

TID (bits 0-3).

eosp: bool

EOSP (bit 4). In a frame a non-AP station sends, the same bit says whether bits_8_15 is TXOP Duration Requested or Queue Size.

ack_policy: int

Ack Policy Indicator (bits 5-6).

amsdu_present: bool

A-MSDU Present (bit 7); reserved in the subtypes that carry no data.

bits_8_15: int

Bits 8-15, which are TXOP Limit, TXOP Duration Requested, Queue Size, AP PS Buffer State, or the mesh subfields, by subtype and sender.

class pcapkit.protocols.data.link.ieee802_11.HTControl(variant, value)[source]

Bases: Data

Data model for the HT Control field (IEEE Std 802.11-2020 §9.2.4.6).

Its first bits name the variant the rest of the field takes; the variants’ own subfields are not decoded.

variant: Literal['HT', 'VHT', 'HE']

The variant, 'HT' when bit 0 is clear, 'VHT' when bit 0 is set and bit 1 clear, and 'HE' when both are set (IEEE Std 802.11ax-2021).

value: int

The whole field, as the little-endian integer read off the wire.

Footnotes