802.11 PROTOCOL INTELLIGENCE

Frame Sequences - 802.11 Exchanges

Every 802.11 connection is a sequence of management frame exchanges. Knowing the exact order, Frame Control values, and what each frame contains lets you diagnose failures at the precise step where they occur - not at the symptom layer.

IEEE 802.11-2020 CWAP Domain

If you know which frame in the association sequence did not arrive, you know exactly what to fix. The controller log tells you the outcome. The PCAP tells you the cause.

// quick wireshark filters - frame exchanges
wlan.fc.type_subtype == 0x0bAuthentication frames - check status code in frame 2. Non-zero = rejection.
wlan.fc.type_subtype == 0x00 || wlan.fc.type_subtype == 0x01Association request + response. RSN IE in req shows what client actually supports.
eapol4-Way Handshake. Exactly 4 frames = success. Missing M2 = PMKID rejected. Missing M3 = AP-side issue.
wlan.fc.type_subtype == 0x02 || wlan.fc.type_subtype == 0x03Reassociation (roaming). Delta between req and resp = roam latency. >50ms = problem.
wlan.fc.type_subtype == 0x0cDeauthentication. Check reason code. Burst from non-AP BSSID = deauth attack.
wlan.fc.type_subtype == 0x0b && wlan.fixed.auth.alg == 3SAE commit/confirm (WPA3). Algorithm=3.
Full filter reference → /wireshark-filters
802.11 THREE-STATE MACHINE - IEEE 802.11-2020 §11.3.3
State 1
Unauthenticated Unassociated
Class 1 only: Probe, Auth, Deauth, Beacon
→ Auth →
State 2
Authenticated Unassociated
Class 1+2: Assoc, Reassoc, Disassoc
→ Assoc →
State 3
Authenticated Associated
Class 1+2+3: Data, QoS Data, Action

Passive Discovery - Beacon Listening

Before: Unauthenticated / Unassociated (State 1) After: State 1 - STA has found candidate APs
2 frames
# Frame From → To FC Key contents / notes
1 Beacon AP → (broadcast) 0x0080 Sent every 102.4 ms (TU = 1024 µs). Contains: SSID, BSSID, supported rates, capabilities IEs, RSN IE, HT/VHT/HE capabilities, TIM. STA passively listens on each channel for MinChannelTime (10 ms default).
2 (STA records AP) STA — STA stores candidate APs from Beacon frames. No transmission from STA in passive mode. 2.4 GHz: dwell ~10-50 ms per channel. 5 GHz/6 GHz: typically active scan (fewer channels).
NOTES

Passive scan: STA does not transmit. Best for power save. Slower - must wait for a Beacon on each channel. 6 GHz mandates RNR (Reduced Neighbor Report) in 2.4/5 GHz Beacons to announce 6 GHz APs.

Active Discovery - Probe Request/Response

Before: Unauthenticated / Unassociated (State 1) After: State 1 - STA has list of APs
3 frames
# Frame From → To FC Key contents / notes
1 Probe Request STA → (broadcast FF:FF:FF:FF:FF:FF) 0x0040 FC Type=0 Subtype=4. Contains: SSID (wildcard "" for all SSIDs, or specific SSID), Supported Rates, HT/VHT/HE capabilities. Sent at lowest mandatory rate: 1 Mbps (2.4 GHz) or 6 Mbps (5/6 GHz) to reach maximum number of APs.
2 Probe Response AP ← STA (unicast) 0x0050 AP responds only if: (1) SSID matches or wildcard, AND (2) at least one common supported rate. Contains same IEs as Beacon. Timestamp, Beacon Interval, Capability Info. Unicast - ACK expected.
3 ACK STA → AP 0x00D4 Acknowledges Probe Response. STA collects responses across channels. ProbeTimer expires → STA moves to next channel.
NOTES

Hidden SSIDs require a directed Probe Request with the specific SSID. An SSID with "broadcast suppressed" (SSID IE length=0 in Beacon) still responds to a directed probe. Active scan is faster than passive but increases power consumption and airtime.

Open System Authentication

Before: State 1 - Unauthenticated / Unassociated After: State 2 - Authenticated / Unassociated
2 frames
# Frame From → To FC Key contents / notes
1 Authentication Request STA → AP 0x00B0 Auth Algorithm=0 (Open System). Auth Seq=1. Status=0 (success). Body: just 6 bytes (Algorithm + Seq + Status). This is NOT WPA2 authentication - it is a legacy 802.11 formality that still runs before WPA3 SAE.
2 Authentication Response AP ← STA 0x00B0 Auth Algorithm=0. Auth Seq=2. Status=0 (success). AP accepts any STA at this stage. Real authentication happens later in EAPOL/SAE exchange. STA transitions to State 2.
NOTES

Open System Auth is a vestigial 2-frame handshake from 1997. In WPA2/WPA3 networks, this exchange is trivial - every STA is "authenticated" at this step. The real credential check happens in the EAPOL 4-Way Handshake (WPA2-PSK), SAE commit/confirm (WPA3), or 802.1X EAP exchange. WPA3-SAE replaces this step with the SAE commit/confirm exchange.

WPA3-SAE Authentication (SAE Commit/Confirm)

Before: State 1 - Unauthenticated / Unassociated After: State 2 - Authenticated (PMK derived) / Unassociated
4 frames
# Frame From → To FC Key contents / notes
1 SAE Commit (Auth frame) STA → AP 0x00B0 Auth Algorithm=3 (SAE). Auth Seq=1. Body contains: Finite Cyclic Group ID (19 = P-256), Scalar (random+password-derived), Element (point on elliptic curve). Anti-clogging token if AP previously sent one.
2 SAE Commit (Auth frame) AP ← STA 0x00B0 AP sends its own Scalar+Element pair. Both sides compute PMK = KDF(commit scalar, commit element, peer scalar, peer element, password). Each attempt requires live interaction - no offline dictionary attack possible.
3 SAE Confirm (Auth frame) STA → AP 0x00B0 Auth Seq=2. Send-Confirm = HMAC(KCK, "SAE Confirm"||send-confirm-counter||AP scalar||AP element||STA scalar||STA element). Proves both sides derived same KCK.
4 SAE Confirm (Auth frame) AP ← STA 0x00B0 Auth Seq=2. AP sends its Confirm. If both confirms match → PMK established. STA transitions to State 2. 4-Way Handshake follows to derive PTK/GTK from PMK.
NOTES

SAE (Dragonfly Key Exchange) provides forward secrecy - even if the password is compromised later, past sessions cannot be decrypted. Each exchange uses ephemeral scalars/elements. Anti-clogging token prevents CPU exhaustion DoS on AP during commit phase.

Association Request / Response

Before: State 2 - Authenticated / Unassociated After: State 3 - Authenticated / Associated (data can flow)
3 frames
# Frame From → To FC Key contents / notes
1 Association Request STA → AP 0x0000 Contains: Capability Info, Listen Interval, SSID, Supported Rates, RSN IE (cipher suites + AKM + MFPC/MFPR + PMKID), HT/VHT/HE Capabilities, Extended Capabilities, Power Capability. RSN IE tells AP which cipher the STA supports. PMKID present if PMKSA cached (from previous auth).
2 Association Response AP ← STA 0x0010 Capability Info, Status Code (0=success, else error), AID (Association ID, 1–2007), Supported Rates, RSN IE (AP confirms cipher selection), HT/VHT/HE Operation, EDCA Parameter Set (WMM/QoS). AID is used in TIM to indicate buffered frames for sleeping STAs.
3 ACK STA → AP 0x00D4 Association complete. STA port transitions to State 3. 4-Way Handshake begins immediately (WPA2/WPA3).
NOTES

Association Request carries the STA RSN IE - this is where cipher suite negotiation occurs. If the STA requests CCMP-128 but the AP requires GCMP-256 (WPA3-Enterprise 192-bit), the AP rejects with Status Code 24 (Cipher Suite Rejected). The PMKID in the RSN IE enables PMKSA fast-reconnect - skips full re-authentication.

4-Way Handshake (EAPOL Key Exchange)

Before: Associated - PMK established (PSK or EAP). No data encryption yet. After: PTK/GTK installed. CCMP/GCMP cipher active. Controlled port AUTHORIZED.
4 frames
# Frame From → To FC Key contents / notes
1 EAPOL-Key M1 (ANonce) AP → STA EAPOL EtherType 0x888E Key Info: Pairwise=1, ACK=1. Key Data: ANonce (256-bit random). No MIC. STA can now derive PTK = PRF-512(PMK, "Pairwise key expansion", min(AA,SPA)||max(AA,SPA)||min(ANonce,SNonce)||max(ANonce,SNonce)).
2 EAPOL-Key M2 (SNonce+MIC) STA ← AP EAPOL 0x888E Key Info: Pairwise=1, MIC=1. SNonce. RSN IE (same as Association Request - AP verifies no IE substitution attack). MIC computed over entire EAPOL frame using KCK (Key Confirmation Key = PTK[0:16]). AP verifies MIC → confirms STA holds correct PMK.
3 EAPOL-Key M3 (GTK+MIC) AP → STA EAPOL 0x888E Key Info: Pairwise=1, Install=1, ACK=1, MIC=1, Encrypted=1. GTK encrypted with KEK (Key Encryption Key = PTK[16:32]). RSN IE. If PMF required: IGTK also included. STA installs PTK and GTK. CCMP/GCMP cipher activated.
4 EAPOL-Key M4 (ACK) STA ← AP EAPOL 0x888E Key Info: Pairwise=1, MIC=1. MIC confirms GTK received. AP installs PTK. 802.1X Controlled Port transitions to AUTHORIZED. First encrypted data frames can now flow.
NOTES

The 4-Way Handshake is identical whether PMK comes from PSK (PBKDF2 of passphrase) or 802.1X EAP (MSK[0:32]). KRACK (CVE-2017-13077) exploited nonce reuse via M3 retransmission - patched in OS updates. WPA3-SAE prevents PMKID-based offline attacks (no PMKID in SAE mode).

Deauthentication Sequence

Before: State 2 or 3 - Authenticated After: State 1 - Unauthenticated / Unassociated
2 frames
# Frame From → To FC Key contents / notes
1 Deauthentication AP → STA (unicast) 0x00C0 Reason Code (2B): Common codes: 1=Unspecified, 2=Previous auth invalid, 3=Leaving BSS, 4=Inactivity timeout, 6=Class 2 frame from non-auth STA, 8=STA leaving (assoc). Without PMF: plaintext - any device can spoof this. With PMF: encrypted under PTK.
2 Deauthentication STA → AP (unicast) 0x00C0 STA can also initiate deauth when roaming, shutting down, or receiving a BTM Request with Disassociation Imminent bit. Same frame format. AP removes STA from its association table.
NOTES

Reason Code 3 = "Deauthenticated because sending STA is leaving (or has left) IBSS or ESS" - the standard clean disconnect. Reason Code 6 = "Class 2 frame received from nonauthenticated STA" - AP received a data frame from a client that never completed authentication (common rogue AP indicator). Reason Code 8 = "Disassociated because sending STA is leaving (or has left) BSS" - normal STA-initiated disconnect.

Roaming - 802.11k/v/r Fast Transition

Before: Associated to AP-1. RSSI declining. After: Associated to AP-2. Sub-50 ms transition.
7 frames
# Frame From → To FC Key contents / notes
1 Radio Measurement Request (Neighbor Report) STA → AP-1 Action Cat=5 802.11k: STA asks AP-1 for list of neighbor APs (BSSID, Operating Class, Channel, PHY type, BSSID Info). Eliminates full band scan (~200 ms saved). STA can now probe target APs directly.
2 Neighbor Report Response AP-1 ← STA Action Cat=5 AP-1 returns Neighbor Report IE with candidate APs ranked by preference. STA uses this to probe only relevant channels.
3 BSS Transition Mgmt Request (802.11v) AP-1 ← STA Action Cat=10 Optional: AP-1 proactively steers STA to AP-2. Preferred Candidate List. Disassociation Imminent Timer. STA replies with BTM Response (Accept/Reject). Fixes "sticky client" problem.
4 FT Auth Request (802.11r) STA → AP-2 0x00B0 Auth Algorithm=2 (FT). SNonce + RSNE (with PMKR0Name) + MDIE (Mobility Domain IE) + FTIE. PMK-R1 pre-distributed to AP-2 by R0KH (controller/RADIUS). AP-2 verifies PMK-R1Name matches.
5 FT Auth Response AP-2 ← STA 0x00B0 ANonce + FTIE (with MIC over all IEs). STA derives PTK-R1 directly. No full 4-Way Handshake required - keys already established via FT hierarchy.
6 Reassociation Request STA → AP-2 0x0020 Contains MDIE, FTIE, RSN IE. AP-2 validates FTIE MIC → confirms STA holds correct PMK-R1. AID assigned.
7 Reassociation Response AP-2 ← STA 0x0030 Status=0. GTK (encrypted in FTIE). PTK installed. Data flows immediately. Total time from BTM Accept → first data frame on AP-2: <50 ms (802.11r) vs 300–500 ms (legacy).
NOTES

802.11k + 802.11v + 802.11r = "WFA Voice-Enterprise" roaming suite. Without 802.11r, a full 802.1X re-auth takes 200–500 ms - voice calls drop. With FT over-DS variant, STA can pre-authenticate to AP-2 WHILE still sending data to AP-1 via AP-1 → DS → AP-2 path. MDIE (Mobility Domain IE) identifies the FT domain - all APs in the same mobility domain share R0KH identity.

Wireshark Filters - Capture These Sequences

Full association sequence
wlan.fc.type_subtype == 4 || wlan.fc.type_subtype == 5 || wlan.fc.type_subtype == 11 || wlan.fc.type_subtype == 0 || wlan.fc.type_subtype == 1
Probe Request only
wlan.fc.type_subtype == 4
Authentication frames
wlan.fc.type_subtype == 11
Association Request/Response
wlan.fc.type_subtype == 0 || wlan.fc.type_subtype == 1
EAPOL 4-Way Handshake
eapol
Deauth frames
wlan.fc.type_subtype == 12
Disassociation frames
wlan.fc.type_subtype == 10
Reason Code = 6 (class 2 from non-auth STA)
wlan.fixed.reason_code == 6
SAE commit/confirm (WPA3)
wlan.fc.type_subtype == 11 && wlan.fixed.auth.alg == 3
FT Auth (802.11r)
wlan.fc.type_subtype == 11 && wlan.fixed.auth.alg == 2
BTM Request (802.11v)
wlan.fixed.action_code == 7 && wlan.fixed.category_code == 10
Neighbor Report Request (802.11k)
wlan.fixed.action_code == 4 && wlan.fixed.category_code == 5
// related reference
State Machine Visualizer →4-Way Handshake Visualizer →802.1X / EAP →Roaming (k/v/r) →Frame Types →PMF (802.11w) →