Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
123 changes: 66 additions & 57 deletions scapy/layers/dot11.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@
"""

from __future__ import print_function
import math
import re
import struct
from zlib import crc32
Expand Down Expand Up @@ -147,22 +146,8 @@ def answers(self, other):

# https://www.radiotap.org/


class _RadiotapReversePadField(ReversePadField):
def __init__(self, fld):
# Quote from https://www.radiotap.org/:
# ""Radiotap requires that all fields in the radiotap header are aligned to natural boundaries. # noqa: E501
# For radiotap, that means all 8-, 16-, 32-, and 64-bit fields must begin on 8-, 16-, 32-, and 64-bit boundaries, respectively."" # noqa: E501
if isinstance(fld, BitField):
_align = int(math.ceil(fld.i2len(None, None)))
else:
_align = struct.calcsize(fld.fmt)
ReversePadField.__init__(
self,
fld,
_align,
padwith=b"\x00"
)
# Note: Radiotap alignment is crazy. See the doc:
# https://www.radiotap.org/#alignment-in-radiotap


def _next_radiotap_extpm(pkt, lst, cur, s):
Expand Down Expand Up @@ -287,68 +272,76 @@ class RadioTap(Packet):
FlagsField('present', None, -32, _rt_present), # noqa: E501
# Extended presence mask
ConditionalField(PacketListField("Ext", [], next_cls_cb=_next_radiotap_extpm), lambda pkt: pkt.present and pkt.present.Ext), # noqa: E501
# RadioTap fields - each starts with a _RadiotapReversePadField
# RadioTap fields - each starts with a ReversePadField
# to handle padding

# TSFT
ConditionalField(
_RadiotapReversePadField(
LELongField("mac_timestamp", 0)
ReversePadField(
LELongField("mac_timestamp", 0),
8
),
lambda pkt: pkt.present and pkt.present.TSFT),
# Flags
ConditionalField(
_RadiotapReversePadField(
FlagsField("Flags", None, -8, _rt_flags)
),
FlagsField("Flags", None, -8, _rt_flags),
lambda pkt: pkt.present and pkt.present.Flags),
# Rate
ConditionalField(
_RadiotapReversePadField(
ScalingField("Rate", 0, scaling=0.5,
unit="Mbps", fmt="B")),
ScalingField("Rate", 0, scaling=0.5,
unit="Mbps", fmt="B"),
lambda pkt: pkt.present and pkt.present.Rate),
# Channel
ConditionalField(
_RadiotapReversePadField(LEShortField("ChannelFrequency", 0)),
ReversePadField(
LEShortField("ChannelFrequency", 0),
2
),
lambda pkt: pkt.present and pkt.present.Channel),
ConditionalField(
FlagsField("ChannelFlags", None, -16, _rt_channelflags),
lambda pkt: pkt.present and pkt.present.Channel),
# dBm_AntSignal
ConditionalField(
_RadiotapReversePadField(
ScalingField("dBm_AntSignal", 0, offset=-256,
unit="dBm", fmt="B")),
ScalingField("dBm_AntSignal", 0, offset=-256,
unit="dBm", fmt="B"),
lambda pkt: pkt.present and pkt.present.dBm_AntSignal),
# dBm_AntNoise
ConditionalField(
_RadiotapReversePadField(
ScalingField("dBm_AntNoise", 0, offset=-256,
unit="dBm", fmt="B")),
ScalingField("dBm_AntNoise", 0, offset=-256,
unit="dBm", fmt="B"),
lambda pkt: pkt.present and pkt.present.dBm_AntNoise),
# Lock_Quality
ConditionalField(
_RadiotapReversePadField(LEShortField("Lock_Quality", 0)),
ReversePadField(
LEShortField("Lock_Quality", 0),
2
),
lambda pkt: pkt.present and pkt.present.Lock_Quality),
# Antenna
ConditionalField(
_RadiotapReversePadField(ByteField("Antenna", 0)),
ByteField("Antenna", 0),
lambda pkt: pkt.present and pkt.present.Antenna),
# RX Flags
ConditionalField(
_RadiotapReversePadField(
FlagsField("RXFlags", None, -16, _rt_rxflags)),
ReversePadField(
FlagsField("RXFlags", None, -16, _rt_rxflags),
2
),
lambda pkt: pkt.present and pkt.present.RXFlags),
# TX Flags
ConditionalField(
_RadiotapReversePadField(
FlagsField("TXFlags", None, -16, _rt_txflags)),
ReversePadField(
FlagsField("TXFlags", None, -16, _rt_txflags),
2
),
lambda pkt: pkt.present and pkt.present.TXFlags),
# ChannelPlus
ConditionalField(
_RadiotapReversePadField(
FlagsField("ChannelPlusFlags", None, -32, _rt_channelflags2)),
ReversePadField(
FlagsField("ChannelPlusFlags", None, -32, _rt_channelflags2),
4
),
lambda pkt: pkt.present and pkt.present.ChannelPlus),
ConditionalField(
LEShortField("ChannelPlusFrequency", 0),
Expand All @@ -358,8 +351,10 @@ class RadioTap(Packet):
lambda pkt: pkt.present and pkt.present.ChannelPlus),
# MCS
ConditionalField(
_RadiotapReversePadField(
FlagsField("knownMCS", None, -8, _rt_knownmcs)),
ReversePadField(
FlagsField("knownMCS", None, -8, _rt_knownmcs),
4
),
lambda pkt: pkt.present and pkt.present.MCS),
ConditionalField(
BitField("Ness_LSB", 0, 1),
Expand All @@ -384,16 +379,20 @@ class RadioTap(Packet):
lambda pkt: pkt.present and pkt.present.MCS),
# A_MPDU
ConditionalField(
_RadiotapReversePadField(
LEIntField("A_MPDU_ref", 0)),
ReversePadField(
LEIntField("A_MPDU_ref", 0),
4
),
lambda pkt: pkt.present and pkt.present.A_MPDU),
ConditionalField(
FlagsField("A_MPDU_flags", None, -32, _rt_a_mpdu_flags),
lambda pkt: pkt.present and pkt.present.A_MPDU),
# VHT
ConditionalField(
_RadiotapReversePadField(
FlagsField("KnownVHT", None, -16, _rt_knownvht)),
ReversePadField(
FlagsField("KnownVHT", None, -16, _rt_knownvht),
2
),
lambda pkt: pkt.present and pkt.present.VHT),
ConditionalField(
FlagsField("PresentVHT", None, -8, _rt_presentvht),
Expand All @@ -412,8 +411,10 @@ class RadioTap(Packet):
lambda pkt: pkt.present and pkt.present.VHT),
# timestamp
ConditionalField(
_RadiotapReversePadField(
LELongField("timestamp", 0)),
ReversePadField(
LELongField("timestamp", 0),
8
),
lambda pkt: pkt.present and pkt.present.timestamp),
ConditionalField(
LEShortField("ts_accuracy", 0),
Expand All @@ -426,8 +427,10 @@ class RadioTap(Packet):
lambda pkt: pkt.present and pkt.present.timestamp),
# HE - XXX not complete
ConditionalField(
_RadiotapReversePadField(
ShortField("he_data1", 0)),
ReversePadField(
ShortField("he_data1", 0),
2
),
lambda pkt: pkt.present and pkt.present.HE),
ConditionalField(
ShortField("he_data2", 0),
Expand All @@ -446,8 +449,10 @@ class RadioTap(Packet):
lambda pkt: pkt.present and pkt.present.HE),
# HE_MU
ConditionalField(
_RadiotapReversePadField(
LEShortField("hemu_flags1", 0)),
ReversePadField(
LEShortField("hemu_flags1", 0),
2
),
lambda pkt: pkt.present and pkt.present.HE_MU),
ConditionalField(
LEShortField("hemu_flags2", 0),
Expand All @@ -462,8 +467,10 @@ class RadioTap(Packet):
lambda pkt: pkt.present and pkt.present.HE_MU),
# HE_MU_other_user
ConditionalField(
_RadiotapReversePadField(
LEShortField("hemuou_per_user_1", 0x7fff)),
ReversePadField(
LEShortField("hemuou_per_user_1", 0x7fff),
2
),
lambda pkt: pkt.present and pkt.present.HE_MU_other_user),
ConditionalField(
LEShortField("hemuou_per_user_2", 0x003f),
Expand All @@ -477,8 +484,10 @@ class RadioTap(Packet):
lambda pkt: pkt.present and pkt.present.HE_MU_other_user),
# L_SIG
ConditionalField(
_RadiotapReversePadField(
FlagsField("lsig_data1", 0, -16, ["rate", "length"])),
ReversePadField(
FlagsField("lsig_data1", 0, -16, ["rate", "length"]),
2
),
lambda pkt: pkt.present and pkt.present.L_SIG),
ConditionalField(
BitField("lsig_length", 0, 12),
Expand Down
12 changes: 12 additions & 0 deletions test/regression.uts
Original file line number Diff line number Diff line change
Expand Up @@ -12433,6 +12433,18 @@ assert f.ASEL.Explicit_CSI_Feedback_Based_Transmit_ASEL
assert f.ASEL.Antenna_Selection
assert f.ASEL == 63

= RadioTap - MCS weird padding
f = RadioTap(b'\x00\x00,\x00K\x08\x1c\x00"b\x96\x03\x00\x00\x00\x00\x10\x00l\t\x80\x04\xb0\x00\x80\x04\x01\x00l\t\x01\x00\x1f\x08\x0c\x00\x94\x05\x00\x00\x04\x00\x00\x00\x88\x020\x00.\xdf\xc4J\xb0\xdc\xa0c\x91sf\xech\x05\xca?\xf4h@Y\x00\x00\xaa\xaa\x03\x00\x00\x00\x08\x00E\x00\x05\xdc \xcf@\x00\x80\x06P\xf0\xc0\xa8\x01\n\xc0\xa8\x01\x02\xdb\x8f\x13\x89\xfbv\xa3\xde\xf6\xd8L\xe8P\x10\xff\xfft\xdd\x00\x0023456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901O\xdc\x01x')
assert f.knownMCS == 31
assert f.Ness_LSB == 0
assert f.STBC_streams == 0
assert f.FEC_type == 0
assert f.HT_format == 1
assert f.guard_interval == 0
assert f.MCS_bandwidth == 0
assert f.MCS_index == 0xc
assert f.A_MPDU_ref == 1428

= Reassociation request
f = Dot11(b' \x00:\x01@\xe3\xd6\x7f*\x00\x00\x10\x18\xa9l.@\xe3\xd6\x7f*\x00 \t1\x04\n\x00@\xe3\xd6\x7f*\x00\x00\x064.2.12\x01\x08\x82\x84\x0b\x16$0Hl!\x02\x08\x1a$\x02\x01\x0b0&\x01\x00\x00\x0f\xac\x04\x01\x00\x00\x0f\xac\x04\x01\x00\x00\x0f\xac\x01\x00\x00\x01\x00LD\xfe\xf2l\xdcV\xce\x0b7\xab\xc62\x02O\x112\x04\x0c\x12\x18`\x7f\x08\x01\x00\x00\x00\x00\x00\x00@\xdd\t\x00\x10\x18\x02\x00\x00\x10\x00\x00')
assert Dot11EltRSN in f
Expand Down