From 551cc0b5fce94694084440cb8e14d2ccc8ec2859 Mon Sep 17 00:00:00 2001 From: gpotter2 Date: Mon, 17 Aug 2020 17:33:08 +0200 Subject: [PATCH] Fix MCS alignment --- scapy/layers/dot11.py | 123 ++++++++++++++++++++++-------------------- test/regression.uts | 12 +++++ 2 files changed, 78 insertions(+), 57 deletions(-) diff --git a/scapy/layers/dot11.py b/scapy/layers/dot11.py index b1b70855a92..38cc568073e 100644 --- a/scapy/layers/dot11.py +++ b/scapy/layers/dot11.py @@ -24,7 +24,6 @@ """ from __future__ import print_function -import math import re import struct from zlib import crc32 @@ -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): @@ -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), @@ -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), @@ -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), @@ -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), @@ -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), @@ -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), @@ -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), @@ -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), diff --git a/test/regression.uts b/test/regression.uts index d4ff053367d..c3e7a77caad 100644 --- a/test/regression.uts +++ b/test/regression.uts @@ -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