Skip to content

Commit b45f2dd

Browse files
authored
Merge pull request #2771 from gpotter2/radiotap-alignment
Fix MCS alignment
2 parents 63407c5 + 551cc0b commit b45f2dd

2 files changed

Lines changed: 78 additions & 57 deletions

File tree

scapy/layers/dot11.py

Lines changed: 66 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@
2424
"""
2525

2626
from __future__ import print_function
27-
import math
2827
import re
2928
import struct
3029
from zlib import crc32
@@ -147,22 +146,8 @@ def answers(self, other):
147146

148147
# https://www.radiotap.org/
149148

150-
151-
class _RadiotapReversePadField(ReversePadField):
152-
def __init__(self, fld):
153-
# Quote from https://www.radiotap.org/:
154-
# ""Radiotap requires that all fields in the radiotap header are aligned to natural boundaries. # noqa: E501
155-
# 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
156-
if isinstance(fld, BitField):
157-
_align = int(math.ceil(fld.i2len(None, None)))
158-
else:
159-
_align = struct.calcsize(fld.fmt)
160-
ReversePadField.__init__(
161-
self,
162-
fld,
163-
_align,
164-
padwith=b"\x00"
165-
)
149+
# Note: Radiotap alignment is crazy. See the doc:
150+
# https://www.radiotap.org/#alignment-in-radiotap
166151

167152

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

293278
# TSFT
294279
ConditionalField(
295-
_RadiotapReversePadField(
296-
LELongField("mac_timestamp", 0)
280+
ReversePadField(
281+
LELongField("mac_timestamp", 0),
282+
8
297283
),
298284
lambda pkt: pkt.present and pkt.present.TSFT),
299285
# Flags
300286
ConditionalField(
301-
_RadiotapReversePadField(
302-
FlagsField("Flags", None, -8, _rt_flags)
303-
),
287+
FlagsField("Flags", None, -8, _rt_flags),
304288
lambda pkt: pkt.present and pkt.present.Flags),
305289
# Rate
306290
ConditionalField(
307-
_RadiotapReversePadField(
308-
ScalingField("Rate", 0, scaling=0.5,
309-
unit="Mbps", fmt="B")),
291+
ScalingField("Rate", 0, scaling=0.5,
292+
unit="Mbps", fmt="B"),
310293
lambda pkt: pkt.present and pkt.present.Rate),
311294
# Channel
312295
ConditionalField(
313-
_RadiotapReversePadField(LEShortField("ChannelFrequency", 0)),
296+
ReversePadField(
297+
LEShortField("ChannelFrequency", 0),
298+
2
299+
),
314300
lambda pkt: pkt.present and pkt.present.Channel),
315301
ConditionalField(
316302
FlagsField("ChannelFlags", None, -16, _rt_channelflags),
317303
lambda pkt: pkt.present and pkt.present.Channel),
318304
# dBm_AntSignal
319305
ConditionalField(
320-
_RadiotapReversePadField(
321-
ScalingField("dBm_AntSignal", 0, offset=-256,
322-
unit="dBm", fmt="B")),
306+
ScalingField("dBm_AntSignal", 0, offset=-256,
307+
unit="dBm", fmt="B"),
323308
lambda pkt: pkt.present and pkt.present.dBm_AntSignal),
324309
# dBm_AntNoise
325310
ConditionalField(
326-
_RadiotapReversePadField(
327-
ScalingField("dBm_AntNoise", 0, offset=-256,
328-
unit="dBm", fmt="B")),
311+
ScalingField("dBm_AntNoise", 0, offset=-256,
312+
unit="dBm", fmt="B"),
329313
lambda pkt: pkt.present and pkt.present.dBm_AntNoise),
330314
# Lock_Quality
331315
ConditionalField(
332-
_RadiotapReversePadField(LEShortField("Lock_Quality", 0)),
316+
ReversePadField(
317+
LEShortField("Lock_Quality", 0),
318+
2
319+
),
333320
lambda pkt: pkt.present and pkt.present.Lock_Quality),
334321
# Antenna
335322
ConditionalField(
336-
_RadiotapReversePadField(ByteField("Antenna", 0)),
323+
ByteField("Antenna", 0),
337324
lambda pkt: pkt.present and pkt.present.Antenna),
338325
# RX Flags
339326
ConditionalField(
340-
_RadiotapReversePadField(
341-
FlagsField("RXFlags", None, -16, _rt_rxflags)),
327+
ReversePadField(
328+
FlagsField("RXFlags", None, -16, _rt_rxflags),
329+
2
330+
),
342331
lambda pkt: pkt.present and pkt.present.RXFlags),
343332
# TX Flags
344333
ConditionalField(
345-
_RadiotapReversePadField(
346-
FlagsField("TXFlags", None, -16, _rt_txflags)),
334+
ReversePadField(
335+
FlagsField("TXFlags", None, -16, _rt_txflags),
336+
2
337+
),
347338
lambda pkt: pkt.present and pkt.present.TXFlags),
348339
# ChannelPlus
349340
ConditionalField(
350-
_RadiotapReversePadField(
351-
FlagsField("ChannelPlusFlags", None, -32, _rt_channelflags2)),
341+
ReversePadField(
342+
FlagsField("ChannelPlusFlags", None, -32, _rt_channelflags2),
343+
4
344+
),
352345
lambda pkt: pkt.present and pkt.present.ChannelPlus),
353346
ConditionalField(
354347
LEShortField("ChannelPlusFrequency", 0),
@@ -358,8 +351,10 @@ class RadioTap(Packet):
358351
lambda pkt: pkt.present and pkt.present.ChannelPlus),
359352
# MCS
360353
ConditionalField(
361-
_RadiotapReversePadField(
362-
FlagsField("knownMCS", None, -8, _rt_knownmcs)),
354+
ReversePadField(
355+
FlagsField("knownMCS", None, -8, _rt_knownmcs),
356+
4
357+
),
363358
lambda pkt: pkt.present and pkt.present.MCS),
364359
ConditionalField(
365360
BitField("Ness_LSB", 0, 1),
@@ -384,16 +379,20 @@ class RadioTap(Packet):
384379
lambda pkt: pkt.present and pkt.present.MCS),
385380
# A_MPDU
386381
ConditionalField(
387-
_RadiotapReversePadField(
388-
LEIntField("A_MPDU_ref", 0)),
382+
ReversePadField(
383+
LEIntField("A_MPDU_ref", 0),
384+
4
385+
),
389386
lambda pkt: pkt.present and pkt.present.A_MPDU),
390387
ConditionalField(
391388
FlagsField("A_MPDU_flags", None, -32, _rt_a_mpdu_flags),
392389
lambda pkt: pkt.present and pkt.present.A_MPDU),
393390
# VHT
394391
ConditionalField(
395-
_RadiotapReversePadField(
396-
FlagsField("KnownVHT", None, -16, _rt_knownvht)),
392+
ReversePadField(
393+
FlagsField("KnownVHT", None, -16, _rt_knownvht),
394+
2
395+
),
397396
lambda pkt: pkt.present and pkt.present.VHT),
398397
ConditionalField(
399398
FlagsField("PresentVHT", None, -8, _rt_presentvht),
@@ -412,8 +411,10 @@ class RadioTap(Packet):
412411
lambda pkt: pkt.present and pkt.present.VHT),
413412
# timestamp
414413
ConditionalField(
415-
_RadiotapReversePadField(
416-
LELongField("timestamp", 0)),
414+
ReversePadField(
415+
LELongField("timestamp", 0),
416+
8
417+
),
417418
lambda pkt: pkt.present and pkt.present.timestamp),
418419
ConditionalField(
419420
LEShortField("ts_accuracy", 0),
@@ -426,8 +427,10 @@ class RadioTap(Packet):
426427
lambda pkt: pkt.present and pkt.present.timestamp),
427428
# HE - XXX not complete
428429
ConditionalField(
429-
_RadiotapReversePadField(
430-
ShortField("he_data1", 0)),
430+
ReversePadField(
431+
ShortField("he_data1", 0),
432+
2
433+
),
431434
lambda pkt: pkt.present and pkt.present.HE),
432435
ConditionalField(
433436
ShortField("he_data2", 0),
@@ -446,8 +449,10 @@ class RadioTap(Packet):
446449
lambda pkt: pkt.present and pkt.present.HE),
447450
# HE_MU
448451
ConditionalField(
449-
_RadiotapReversePadField(
450-
LEShortField("hemu_flags1", 0)),
452+
ReversePadField(
453+
LEShortField("hemu_flags1", 0),
454+
2
455+
),
451456
lambda pkt: pkt.present and pkt.present.HE_MU),
452457
ConditionalField(
453458
LEShortField("hemu_flags2", 0),
@@ -462,8 +467,10 @@ class RadioTap(Packet):
462467
lambda pkt: pkt.present and pkt.present.HE_MU),
463468
# HE_MU_other_user
464469
ConditionalField(
465-
_RadiotapReversePadField(
466-
LEShortField("hemuou_per_user_1", 0x7fff)),
470+
ReversePadField(
471+
LEShortField("hemuou_per_user_1", 0x7fff),
472+
2
473+
),
467474
lambda pkt: pkt.present and pkt.present.HE_MU_other_user),
468475
ConditionalField(
469476
LEShortField("hemuou_per_user_2", 0x003f),
@@ -477,8 +484,10 @@ class RadioTap(Packet):
477484
lambda pkt: pkt.present and pkt.present.HE_MU_other_user),
478485
# L_SIG
479486
ConditionalField(
480-
_RadiotapReversePadField(
481-
FlagsField("lsig_data1", 0, -16, ["rate", "length"])),
487+
ReversePadField(
488+
FlagsField("lsig_data1", 0, -16, ["rate", "length"]),
489+
2
490+
),
482491
lambda pkt: pkt.present and pkt.present.L_SIG),
483492
ConditionalField(
484493
BitField("lsig_length", 0, 12),

test/regression.uts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12433,6 +12433,18 @@ assert f.ASEL.Explicit_CSI_Feedback_Based_Transmit_ASEL
1243312433
assert f.ASEL.Antenna_Selection
1243412434
assert f.ASEL == 63
1243512435

12436+
= RadioTap - MCS weird padding
12437+
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')
12438+
assert f.knownMCS == 31
12439+
assert f.Ness_LSB == 0
12440+
assert f.STBC_streams == 0
12441+
assert f.FEC_type == 0
12442+
assert f.HT_format == 1
12443+
assert f.guard_interval == 0
12444+
assert f.MCS_bandwidth == 0
12445+
assert f.MCS_index == 0xc
12446+
assert f.A_MPDU_ref == 1428
12447+
1243612448
= Reassociation request
1243712449
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')
1243812450
assert Dot11EltRSN in f

0 commit comments

Comments
 (0)