Skip to content

Commit 63407c5

Browse files
committed
Backward compatibility of 802.11 elements
1 parent bf2304b commit 63407c5

File tree

2 files changed

+51
-22
lines changed

2 files changed

+51
-22
lines changed

scapy/layers/dot11.py

Lines changed: 44 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,6 @@
3838
BitEnumField,
3939
BitField,
4040
BitMultiEnumField,
41-
BitScalingField,
4241
ByteEnumField,
4342
ByteField,
4443
ConditionalField,
@@ -752,7 +751,7 @@ def network_stats(self):
752751
p.country_string[-1:]
753752
)
754753
elif isinstance(p, Dot11EltRates):
755-
rates = [x.label for x in p.rates]
754+
rates = [(x & 0x7f) / 2. for x in p.rates]
756755
if "rates" in summary:
757756
summary["rates"].extend(rates)
758757
else:
@@ -843,14 +842,39 @@ def network_stats(self):
843842
221: "Vendor Specific"
844843
}
845844

845+
# Backward compatibility
846+
_dot11_elt_deprecated_names = {
847+
"Rates": 1,
848+
"DSset": 3,
849+
"CFset": 4,
850+
"IBSSset": 6,
851+
"challenge": 16,
852+
"PowerCapability": 33,
853+
"Channels": 36,
854+
"ERPinfo": 42,
855+
"HTinfo": 45,
856+
"RSNinfo": 48,
857+
"ESRates": 50,
858+
"ExtendendCapatibilities": 127,
859+
"VHTCapabilities": 191,
860+
"Vendor": 221,
861+
}
862+
863+
_dot11_info_elts_ids_rev = {v: k for k, v in _dot11_info_elts_ids.items()}
864+
_dot11_info_elts_ids_rev.update(_dot11_elt_deprecated_names)
865+
_dot11_id_enum = (
866+
lambda x: _dot11_info_elts_ids.get(x, x),
867+
lambda x: _dot11_info_elts_ids_rev.get(x, x)
868+
)
869+
846870

847871
class Dot11Elt(Packet):
848872
"""
849873
A Generic 802.11 Element
850874
"""
851875
__slots__ = ["info"]
852876
name = "802.11 Information Element"
853-
fields_desc = [ByteEnumField("ID", 0, _dot11_info_elts_ids),
877+
fields_desc = [ByteEnumField("ID", 0, _dot11_id_enum),
854878
FieldLenField("len", None, "info", "B"),
855879
StrLenField("info", "", length_from=lambda x: x.len,
856880
max_length=255)]
@@ -977,7 +1001,7 @@ class Dot11EltRSN(Dot11Elt):
9771001
name = "802.11 RSN information"
9781002
match_subclass = True
9791003
fields_desc = [
980-
ByteEnumField("ID", 48, _dot11_info_elts_ids),
1004+
ByteEnumField("ID", 48, _dot11_id_enum),
9811005
ByteField("len", None),
9821006
LEShortField("version", 1),
9831007
PacketField("group_cipher_suite", RSNCipherSuite(), RSNCipherSuite),
@@ -1045,7 +1069,7 @@ class Dot11EltCountry(Dot11Elt):
10451069
name = "802.11 Country"
10461070
match_subclass = True
10471071
fields_desc = [
1048-
ByteEnumField("ID", 7, _dot11_info_elts_ids),
1072+
ByteEnumField("ID", 7, _dot11_id_enum),
10491073
ByteField("len", None),
10501074
StrFixedLenField("country_string", b"\0\0\0", length=3),
10511075
PacketListField(
@@ -1063,28 +1087,27 @@ class Dot11EltCountry(Dot11Elt):
10631087
]
10641088

10651089

1066-
class RateElement(Packet):
1067-
name = "Rate element"
1068-
fields_desc = [
1069-
BitField("mandatory", 0, 1),
1070-
BitScalingField("label", 0, 7, scaling=0.5, unit="Mbps"),
1071-
]
1072-
1073-
def extract_padding(self, s):
1074-
return b'', s
1090+
class _RateField(ByteField):
1091+
def i2repr(self, pkt, val):
1092+
if val is None:
1093+
return ""
1094+
s = str((val & 0x7f) / 2.)
1095+
if val & 0x80:
1096+
s += "(B)"
1097+
return s + " Mbps"
10751098

10761099

10771100
class Dot11EltRates(Dot11Elt):
10781101
name = "802.11 Rates"
10791102
match_subclass = True
10801103
fields_desc = [
1081-
ByteEnumField("ID", 1, _dot11_info_elts_ids),
1104+
ByteEnumField("ID", 1, _dot11_id_enum),
10821105
ByteField("len", None),
1083-
PacketListField(
1106+
FieldListField(
10841107
"rates",
1085-
[],
1086-
RateElement,
1087-
count_from=lambda p: p.len
1108+
[0x82],
1109+
_RateField("", 0),
1110+
length_from=lambda p: p.len
10881111
)
10891112
]
10901113

@@ -1096,7 +1119,7 @@ class Dot11EltHTCapabilities(Dot11Elt):
10961119
name = "HT Capabilities"
10971120
match_subclass = True
10981121
fields_desc = [
1099-
ByteEnumField("ID", 45, _dot11_info_elts_ids),
1122+
ByteEnumField("ID", 45, _dot11_id_enum),
11001123
ByteField("len", None),
11011124
# HT Capabilities Info: 2B
11021125
BitField("L_SIG_TXOP_Protection", 0, 1, tot_size=-2),
@@ -1177,7 +1200,7 @@ class Dot11EltVendorSpecific(Dot11Elt):
11771200
name = "802.11 Vendor Specific"
11781201
match_subclass = True
11791202
fields_desc = [
1180-
ByteEnumField("ID", 221, _dot11_info_elts_ids),
1203+
ByteEnumField("ID", 221, _dot11_id_enum),
11811204
ByteField("len", None),
11821205
X3BytesField("oui", 0x000000),
11831206
StrLenField("info", "", length_from=lambda x: x.len - 3)

test/regression.uts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1311,7 +1311,7 @@ assert Dot11FCS in radiotap
13111311
assert radiotap.fcs == 0xdbc04908
13121312

13131313
assert Dot11EltRates in radiotap
1314-
assert [x.label for x in radiotap[Dot11EltRates].rates] == [1.0, 2.0, 5.5, 11.0, 18.0, 24.0, 36.0, 54.0]
1314+
assert radiotap[Dot11EltRates].rates == [130, 132, 139, 150, 36, 48, 72, 108]
13151315

13161316
= RadioTap - Build with Extended presence mask
13171317

@@ -12440,6 +12440,12 @@ assert f[Dot11EltRSN].pmkids.nb_pmkids == 1
1244012440
assert len(f[Dot11EltRSN].pmkids.pmkid_list) == 1
1244112441
assert f[Dot11EltRSN].pmkids.pmkid_list[0] == b'LD\xfe\xf2l\xdcV\xce\x0b7\xab\xc62\x02O\x11'
1244212442

12443+
= Backward compatibility of Dot11Elt
12444+
12445+
# Old naming scheme
12446+
assert Dot11Elt(ID="DSset").sprintf("%ID%") == 'DSSS Set'
12447+
assert Dot11Elt(ID="RSNinfo").sprintf("%ID%") == 'RSN'
12448+
1244312449

1244412450
######################################
1244512451
# More PPI tests in contrib/ppi_cace #

0 commit comments

Comments
 (0)