Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/scapy/layers/dot11.py: 73%

Shortcuts on this page

r m x   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

678 statements  

1# SPDX-License-Identifier: GPL-2.0-only 

2# This file is part of Scapy 

3# See https://scapy.net/ for more information 

4# Copyright (C) Philippe Biondi <phil@secdev.org> 

5 

6""" 

7Wireless LAN according to IEEE 802.11. 

8 

9This file contains bindings for 802.11 layers and some usual linklayers: 

10 - PRISM 

11 - RadioTap 

12""" 

13 

14import re 

15import struct 

16from zlib import crc32 

17 

18from scapy.config import conf, crypto_validator 

19from scapy.data import ETHER_ANY, DLT_IEEE802_11, DLT_PRISM_HEADER, \ 

20 DLT_IEEE802_11_RADIO 

21from scapy.compat import raw, plain_str, orb, chb 

22from scapy.packet import Packet, bind_layers, bind_top_down, NoPayload 

23from scapy.fields import ( 

24 BitEnumField, 

25 BitField, 

26 BitMultiEnumField, 

27 ByteEnumField, 

28 ByteField, 

29 ConditionalField, 

30 FCSField, 

31 FieldLenField, 

32 FieldListField, 

33 FlagsField, 

34 IntField, 

35 LEFieldLenField, 

36 LEIntField, 

37 LELongField, 

38 LEShortEnumField, 

39 LEShortField, 

40 LESignedIntField, 

41 MayEnd, 

42 MultipleTypeField, 

43 OUIField, 

44 PacketField, 

45 PacketListField, 

46 ReversePadField, 

47 ScalingField, 

48 ShortField, 

49 StrField, 

50 StrFixedLenField, 

51 StrLenField, 

52 XByteField, 

53 XStrFixedLenField, 

54) 

55from scapy.ansmachine import AnsweringMachine 

56from scapy.plist import PacketList 

57from scapy.layers.l2 import Ether, LLC, MACField 

58from scapy.layers.inet import IP, TCP 

59from scapy.error import warning, log_loading 

60from scapy.sendrecv import sniff, sendp 

61 

62 

63if conf.crypto_valid: 

64 from cryptography.hazmat.backends import default_backend 

65 from cryptography.hazmat.primitives.ciphers import Cipher, algorithms 

66 

67 try: 

68 # cryptography > 43.0 

69 from cryptography.hazmat.decrepit.ciphers import ( 

70 algorithms as decrepit_algorithms, 

71 ) 

72 except ImportError: 

73 decrepit_algorithms = algorithms 

74else: 

75 default_backend = Ciphers = algorithms = decrepit_algorithms = None 

76 log_loading.info("Can't import python-cryptography v2.0+. Disabled WEP decryption/encryption. (Dot11)") # noqa: E501 

77 

78 

79######### 

80# Prism # 

81######### 

82 

83# http://www.martin.cc/linux/prism 

84 

85class PrismHeader(Packet): 

86 """ iwpriv wlan0 monitor 3 """ 

87 name = "Prism header" 

88 fields_desc = [LEIntField("msgcode", 68), 

89 LEIntField("len", 144), 

90 StrFixedLenField("dev", "", 16), 

91 LEIntField("hosttime_did", 0), 

92 LEShortField("hosttime_status", 0), 

93 LEShortField("hosttime_len", 0), 

94 LEIntField("hosttime", 0), 

95 LEIntField("mactime_did", 0), 

96 LEShortField("mactime_status", 0), 

97 LEShortField("mactime_len", 0), 

98 LEIntField("mactime", 0), 

99 LEIntField("channel_did", 0), 

100 LEShortField("channel_status", 0), 

101 LEShortField("channel_len", 0), 

102 LEIntField("channel", 0), 

103 LEIntField("rssi_did", 0), 

104 LEShortField("rssi_status", 0), 

105 LEShortField("rssi_len", 0), 

106 LEIntField("rssi", 0), 

107 LEIntField("sq_did", 0), 

108 LEShortField("sq_status", 0), 

109 LEShortField("sq_len", 0), 

110 LEIntField("sq", 0), 

111 LEIntField("signal_did", 0), 

112 LEShortField("signal_status", 0), 

113 LEShortField("signal_len", 0), 

114 LESignedIntField("signal", 0), 

115 LEIntField("noise_did", 0), 

116 LEShortField("noise_status", 0), 

117 LEShortField("noise_len", 0), 

118 LEIntField("noise", 0), 

119 LEIntField("rate_did", 0), 

120 LEShortField("rate_status", 0), 

121 LEShortField("rate_len", 0), 

122 LEIntField("rate", 0), 

123 LEIntField("istx_did", 0), 

124 LEShortField("istx_status", 0), 

125 LEShortField("istx_len", 0), 

126 LEIntField("istx", 0), 

127 LEIntField("frmlen_did", 0), 

128 LEShortField("frmlen_status", 0), 

129 LEShortField("frmlen_len", 0), 

130 LEIntField("frmlen", 0), 

131 ] 

132 

133 def answers(self, other): 

134 if isinstance(other, PrismHeader): 

135 return self.payload.answers(other.payload) 

136 else: 

137 return self.payload.answers(other) 

138 

139############ 

140# RadioTap # 

141############ 

142 

143# https://www.radiotap.org/ 

144 

145# Note: Radiotap alignment is crazy. See the doc: 

146# https://www.radiotap.org/#alignment-in-radiotap 

147 

148# RadioTap constants 

149 

150 

151_rt_present = ['TSFT', 'Flags', 'Rate', 'Channel', 'FHSS', 'dBm_AntSignal', 

152 'dBm_AntNoise', 'Lock_Quality', 'TX_Attenuation', 

153 'dB_TX_Attenuation', 'dBm_TX_Power', 'Antenna', 

154 'dB_AntSignal', 'dB_AntNoise', 'RXFlags', 'TXFlags', 

155 'b17', 'b18', 'ChannelPlus', 'MCS', 'A_MPDU', 

156 'VHT', 'timestamp', 'HE', 'HE_MU', 'HE_MU_other_user', 

157 'zero_length_psdu', 'L_SIG', 'TLV', 

158 'RadiotapNS', 'VendorNS', 'Ext'] 

159 

160# Note: Inconsistencies with wireshark 

161# Wireshark ignores the suggested fields, whereas we implement some of them 

162# (some are well-used even though not accepted) 

163# However, flags that conflicts with Wireshark are not and MUST NOT be 

164# implemented -> b17, b18 

165 

166_rt_flags = ['CFP', 'ShortPreamble', 'wep', 'fragment', 'FCS', 'pad', 

167 'badFCS', 'ShortGI'] 

168 

169_rt_channelflags = ['res1', 'res2', 'res3', 'res4', 'Turbo', 'CCK', 

170 'OFDM', '2GHz', '5GHz', 'Passive', 'Dynamic_CCK_OFDM', 

171 'GFSK', 'GSM', 'StaticTurbo', '10MHz', '5MHz'] 

172 

173_rt_rxflags = ["res1", "BAD_PLCP", "res2"] 

174 

175_rt_txflags = ["TX_FAIL", "CTS", "RTS", "NOACK", "NOSEQ", "ORDER"] 

176 

177_rt_channelflags2 = ['res1', 'res2', 'res3', 'res4', 'Turbo', 'CCK', 

178 'OFDM', '2GHz', '5GHz', 'Passive', 'Dynamic_CCK_OFDM', 

179 'GFSK', 'GSM', 'StaticTurbo', '10MHz', '5MHz', 

180 '20MHz', '40MHz_ext_channel_above', 

181 '40MHz_ext_channel_below', 

182 'res5', 'res6', 'res7', 'res8', 'res9'] 

183 

184_rt_tsflags = ['32-bit_counter', 'Accuracy', 'res1', 'res2', 'res3', 

185 'res4', 'res5', 'res6'] 

186 

187_rt_knownmcs = ['MCS_bandwidth', 'MCS_index', 'guard_interval', 'HT_format', 

188 'FEC_type', 'STBC_streams', 'Ness', 'Ness_MSB'] 

189 

190_rt_bandwidth = {0: "20MHz", 1: "40MHz", 2: "ht40Mhz-", 3: "ht40MHz+"} 

191 

192_rt_a_mpdu_flags = ['Report0Subframe', 'Is0Subframe', 'KnownLastSubframe', 

193 'LastSubframe', 'CRCerror', 'EOFsubframe', 'KnownEOF', 

194 'res1', 'res2', 'res3', 'res4', 'res5', 'res6', 'res7', 

195 'res8'] 

196 

197_rt_vhtbandwidth = { 

198 0: "20MHz", 1: "40MHz", 2: "40MHz", 3: "40MHz", 4: "80MHz", 5: "80MHz", 

199 6: "80MHz", 7: "80MHz", 8: "80MHz", 9: "80MHz", 10: "80MHz", 11: "160MHz", 

200 12: "160MHz", 13: "160MHz", 14: "160MHz", 15: "160MHz", 16: "160MHz", 

201 17: "160MHz", 18: "160MHz", 19: "160MHz", 20: "160MHz", 21: "160MHz", 

202 22: "160MHz", 23: "160MHz", 24: "160MHz", 25: "160MHz" 

203} 

204 

205_rt_knownvht = ['STBC', 'TXOP_PS_NOT_ALLOWED', 'GuardInterval', 'SGINsysmDis', 

206 'LDPCextraOFDM', 'Beamformed', 'Bandwidth', 'GroupID', 

207 'PartialAID', 

208 'res1', 'res2', 'res3', 'res4', 'res5', 'res6', 'res7'] 

209 

210_rt_presentvht = ['STBC', 'TXOP_PS_NOT_ALLOWED', 'GuardInterval', 

211 'SGINsysmDis', 'LDPCextraOFDM', 'Beamformed', 

212 'res1', 'res2'] 

213 

214_rt_hemuother_per_user_known = [ 

215 'user field position', 

216 'STA-ID', 

217 'NSTS', 

218 'Tx Beamforming', 

219 'Spatial Configuration', 

220 'MCS', 

221 'DCM', 

222 'Coding', 

223] 

224 

225 

226# Radiotap utils 

227 

228# Note: extended presence masks are dissected pretty dumbly by 

229# Wireshark. 

230 

231def _next_radiotap_extpm(pkt, lst, cur, s): 

232 """Generates the next RadioTapExtendedPresenceMask""" 

233 if cur is None or (cur.present and cur.present.Ext): 

234 st = len(lst) + (cur is not None) 

235 return lambda *args: RadioTapExtendedPresenceMask(*args, index=st) 

236 return None 

237 

238 

239class RadioTapExtendedPresenceMask(Packet): 

240 """RadioTapExtendedPresenceMask should be instantiated by passing an 

241 `index=` kwarg, stating which place the item has in the list. 

242 

243 Passing index will update the b[x] fields accordingly to the index. 

244 e.g. 

245 >>> a = RadioTapExtendedPresenceMask(present="b0+b12+b29+Ext") 

246 >>> b = RadioTapExtendedPresenceMask(index=1, present="b33+b45+b59+b62") 

247 >>> pkt = RadioTap(present="Ext", Ext=[a, b]) 

248 """ 

249 name = "RadioTap Extended presence mask" 

250 fields_desc = [FlagsField('present', None, -32, 

251 ["b%s" % i for i in range(0, 31)] + ["Ext"])] 

252 

253 def __init__(self, _pkt=None, index=0, **kwargs): 

254 self._restart_indentation(index) 

255 Packet.__init__(self, _pkt, **kwargs) 

256 

257 def _restart_indentation(self, index): 

258 st = index * 32 

259 self.fields_desc[0].names = ["b%s" % (i + st) for i in range(0, 31)] + ["Ext"] # noqa: E501 

260 

261 def guess_payload_class(self, pay): 

262 return conf.padding_layer 

263 

264 

265# This is still unimplemented in Wireshark 

266# https://www.radiotap.org/fields/TLV.html 

267class RadioTapTLV(Packet): 

268 fields_desc = [ 

269 LEShortEnumField("type", 0, _rt_present), 

270 LEShortField("length", None), 

271 ConditionalField( 

272 OUIField("oui", 0), 

273 lambda pkt: pkt.type == 30 # VendorNS 

274 ), 

275 ConditionalField( 

276 ByteField("subtype", 0), 

277 lambda pkt: pkt.type == 30 

278 ), 

279 ConditionalField( 

280 LEShortField("presence_type", 0), 

281 lambda pkt: pkt.type == 30 

282 ), 

283 ConditionalField( 

284 LEShortField("reserved", 0), 

285 lambda pkt: pkt.type == 30 

286 ), 

287 StrLenField("data", b"", 

288 length_from=lambda pkt: pkt.length), 

289 StrLenField("pad", None, length_from=lambda pkt: -pkt.length % 4) 

290 ] 

291 

292 def post_build(self, pkt, pay): 

293 if self.length is None: 

294 pkt = pkt[:2] + struct.pack("<H", len(self.data)) + pkt[4:] 

295 if self.pad is None: 

296 pkt += b"\x00" * (-len(self.data) % 4) 

297 return pkt + pay 

298 

299 def extract_padding(self, s): 

300 return "", s 

301 

302 

303# RADIOTAP 

304 

305class RadioTap(Packet): 

306 name = "RadioTap" 

307 deprecated_fields = { 

308 "Channel": ("ChannelFrequency", "2.4.3"), 

309 "ChannelFlags2": ("ChannelPlusFlags", "2.4.3"), 

310 "ChannelNumber": ("ChannelPlusNumber", "2.4.3"), 

311 } 

312 fields_desc = [ 

313 ByteField('version', 0), 

314 ByteField('pad', 0), 

315 LEShortField('len', None), 

316 FlagsField('present', None, -32, _rt_present), # noqa: E501 

317 # Extended presence mask 

318 ConditionalField(PacketListField("Ext", [], next_cls_cb=_next_radiotap_extpm), lambda pkt: pkt.present and pkt.present.Ext), # noqa: E501 

319 # RadioTap fields - each starts with a ReversePadField 

320 # to handle padding 

321 

322 # TSFT 

323 ConditionalField( 

324 ReversePadField( 

325 LELongField("mac_timestamp", 0), 

326 8 

327 ), 

328 lambda pkt: pkt.present and pkt.present.TSFT), 

329 # Flags 

330 ConditionalField( 

331 FlagsField("Flags", None, -8, _rt_flags), 

332 lambda pkt: pkt.present and pkt.present.Flags), 

333 # Rate 

334 ConditionalField( 

335 ScalingField("Rate", 0, scaling=0.5, 

336 unit="Mbps", fmt="B"), 

337 lambda pkt: pkt.present and pkt.present.Rate), 

338 # Channel 

339 ConditionalField( 

340 ReversePadField( 

341 LEShortField("ChannelFrequency", 0), 

342 2 

343 ), 

344 lambda pkt: pkt.present and pkt.present.Channel), 

345 ConditionalField( 

346 FlagsField("ChannelFlags", None, -16, _rt_channelflags), 

347 lambda pkt: pkt.present and pkt.present.Channel), 

348 # dBm_AntSignal 

349 ConditionalField( 

350 ScalingField("dBm_AntSignal", 0, 

351 unit="dBm", fmt="b"), 

352 lambda pkt: pkt.present and pkt.present.dBm_AntSignal), 

353 # dBm_AntNoise 

354 ConditionalField( 

355 ScalingField("dBm_AntNoise", 0, 

356 unit="dBm", fmt="b"), 

357 lambda pkt: pkt.present and pkt.present.dBm_AntNoise), 

358 # Lock_Quality 

359 ConditionalField( 

360 ReversePadField( 

361 LEShortField("Lock_Quality", 0), 

362 2 

363 ), 

364 lambda pkt: pkt.present and pkt.present.Lock_Quality), 

365 # Antenna 

366 ConditionalField( 

367 ByteField("Antenna", 0), 

368 lambda pkt: pkt.present and pkt.present.Antenna), 

369 # RX Flags 

370 ConditionalField( 

371 ReversePadField( 

372 FlagsField("RXFlags", None, -16, _rt_rxflags), 

373 2 

374 ), 

375 lambda pkt: pkt.present and pkt.present.RXFlags), 

376 # TX Flags 

377 ConditionalField( 

378 ReversePadField( 

379 FlagsField("TXFlags", None, -16, _rt_txflags), 

380 2 

381 ), 

382 lambda pkt: pkt.present and pkt.present.TXFlags), 

383 # ChannelPlus 

384 ConditionalField( 

385 ReversePadField( 

386 FlagsField("ChannelPlusFlags", None, -32, _rt_channelflags2), 

387 4 

388 ), 

389 lambda pkt: pkt.present and pkt.present.ChannelPlus), 

390 ConditionalField( 

391 LEShortField("ChannelPlusFrequency", 0), 

392 lambda pkt: pkt.present and pkt.present.ChannelPlus), 

393 ConditionalField( 

394 ByteField("ChannelPlusNumber", 0), 

395 lambda pkt: pkt.present and pkt.present.ChannelPlus), 

396 # MCS 

397 ConditionalField( 

398 ReversePadField( 

399 FlagsField("knownMCS", None, -8, _rt_knownmcs), 

400 2 

401 ), 

402 lambda pkt: pkt.present and pkt.present.MCS), 

403 ConditionalField( 

404 BitField("Ness_LSB", 0, 1), 

405 lambda pkt: pkt.present and pkt.present.MCS), 

406 ConditionalField( 

407 BitField("STBC_streams", 0, 2), 

408 lambda pkt: pkt.present and pkt.present.MCS), 

409 ConditionalField( 

410 BitEnumField("FEC_type", 0, 1, {0: "BCC", 1: "LDPC"}), 

411 lambda pkt: pkt.present and pkt.present.MCS), 

412 ConditionalField( 

413 BitEnumField("HT_format", 0, 1, {0: "mixed", 1: "greenfield"}), 

414 lambda pkt: pkt.present and pkt.present.MCS), 

415 ConditionalField( 

416 BitEnumField("guard_interval", 0, 1, {0: "Long_GI", 1: "Short_GI"}), # noqa: E501 

417 lambda pkt: pkt.present and pkt.present.MCS), 

418 ConditionalField( 

419 BitEnumField("MCS_bandwidth", 0, 2, _rt_bandwidth), 

420 lambda pkt: pkt.present and pkt.present.MCS), 

421 ConditionalField( 

422 ByteField("MCS_index", 0), 

423 lambda pkt: pkt.present and pkt.present.MCS), 

424 # A_MPDU 

425 ConditionalField( 

426 ReversePadField( 

427 LEIntField("A_MPDU_ref", 0), 

428 4 

429 ), 

430 lambda pkt: pkt.present and pkt.present.A_MPDU), 

431 ConditionalField( 

432 FlagsField("A_MPDU_flags", None, -32, _rt_a_mpdu_flags), 

433 lambda pkt: pkt.present and pkt.present.A_MPDU), 

434 # VHT 

435 ConditionalField( 

436 ReversePadField( 

437 FlagsField("KnownVHT", None, -16, _rt_knownvht), 

438 2 

439 ), 

440 lambda pkt: pkt.present and pkt.present.VHT), 

441 ConditionalField( 

442 FlagsField("PresentVHT", None, -8, _rt_presentvht), 

443 lambda pkt: pkt.present and pkt.present.VHT), 

444 ConditionalField( 

445 ByteEnumField("VHT_bandwidth", 0, _rt_vhtbandwidth), 

446 lambda pkt: pkt.present and pkt.present.VHT), 

447 ConditionalField( 

448 StrFixedLenField("mcs_nss", 0, length=5), 

449 lambda pkt: pkt.present and pkt.present.VHT), 

450 ConditionalField( 

451 ByteField("GroupID", 0), 

452 lambda pkt: pkt.present and pkt.present.VHT), 

453 ConditionalField( 

454 ShortField("PartialAID", 0), 

455 lambda pkt: pkt.present and pkt.present.VHT), 

456 # timestamp 

457 ConditionalField( 

458 ReversePadField( 

459 LELongField("timestamp", 0), 

460 8 

461 ), 

462 lambda pkt: pkt.present and pkt.present.timestamp), 

463 ConditionalField( 

464 LEShortField("ts_accuracy", 0), 

465 lambda pkt: pkt.present and pkt.present.timestamp), 

466 ConditionalField( 

467 BitEnumField("ts_unit", 0, 4, { 

468 0: 'milliseconds', 

469 1: 'microseconds', 

470 2: 'nanoseconds'}), 

471 lambda pkt: pkt.present and pkt.present.timestamp), 

472 ConditionalField( 

473 BitField("ts_position", 0, 4), 

474 lambda pkt: pkt.present and pkt.present.timestamp), 

475 ConditionalField( 

476 FlagsField("ts_flags", None, 8, _rt_tsflags), 

477 lambda pkt: pkt.present and pkt.present.timestamp), 

478 # HE - XXX not complete 

479 ConditionalField( 

480 ReversePadField( 

481 LEShortField("he_data1", 0), 

482 2 

483 ), 

484 lambda pkt: pkt.present and pkt.present.HE), 

485 ConditionalField( 

486 LEShortField("he_data2", 0), 

487 lambda pkt: pkt.present and pkt.present.HE), 

488 ConditionalField( 

489 LEShortField("he_data3", 0), 

490 lambda pkt: pkt.present and pkt.present.HE), 

491 ConditionalField( 

492 LEShortField("he_data4", 0), 

493 lambda pkt: pkt.present and pkt.present.HE), 

494 ConditionalField( 

495 LEShortField("he_data5", 0), 

496 lambda pkt: pkt.present and pkt.present.HE), 

497 ConditionalField( 

498 LEShortField("he_data6", 0), 

499 lambda pkt: pkt.present and pkt.present.HE), 

500 # HE_MU 

501 ConditionalField( 

502 ReversePadField( 

503 LEShortField("hemu_flags1", 0), 

504 2 

505 ), 

506 lambda pkt: pkt.present and pkt.present.HE_MU), 

507 ConditionalField( 

508 LEShortField("hemu_flags2", 0), 

509 lambda pkt: pkt.present and pkt.present.HE_MU), 

510 ConditionalField( 

511 FieldListField("RU_channel1", [], ByteField('', 0), 

512 length_from=lambda x: 4), 

513 lambda pkt: pkt.present and pkt.present.HE_MU), 

514 ConditionalField( 

515 FieldListField("RU_channel2", [], ByteField('', 0), 

516 length_from=lambda x: 4), 

517 lambda pkt: pkt.present and pkt.present.HE_MU), 

518 # HE_MU_other_user 

519 ConditionalField( 

520 ReversePadField( 

521 LEShortField("hemuou_per_user_1", 0x7fff), 

522 2 

523 ), 

524 lambda pkt: pkt.present and pkt.present.HE_MU_other_user), 

525 ConditionalField( 

526 LEShortField("hemuou_per_user_2", 0x003f), 

527 lambda pkt: pkt.present and pkt.present.HE_MU_other_user), 

528 ConditionalField( 

529 ByteField("hemuou_per_user_position", 0), 

530 lambda pkt: pkt.present and pkt.present.HE_MU_other_user), 

531 ConditionalField( 

532 FlagsField("hemuou_per_user_known", 0, -16, 

533 _rt_hemuother_per_user_known), 

534 lambda pkt: pkt.present and pkt.present.HE_MU_other_user), 

535 # L_SIG 

536 ConditionalField( 

537 ReversePadField( 

538 FlagsField("lsig_data1", 0, -16, ["rate", "length"]), 

539 2 

540 ), 

541 lambda pkt: pkt.present and pkt.present.L_SIG), 

542 ConditionalField( 

543 BitField("lsig_length", 0, 12, tot_size=-2), 

544 lambda pkt: pkt.present and pkt.present.L_SIG), 

545 ConditionalField( 

546 BitField("lsig_rate", 0, 4, end_tot_size=-2), 

547 lambda pkt: pkt.present and pkt.present.L_SIG), 

548 # TLV fields 

549 ConditionalField( 

550 ReversePadField( 

551 PacketListField("tlvs", [], RadioTapTLV), 

552 4 

553 ), 

554 lambda pkt: pkt.present and pkt.present.TLV, 

555 ), 

556 # Remaining 

557 StrLenField('notdecoded', "", length_from=lambda pkt: 0) 

558 ] 

559 

560 def guess_payload_class(self, payload): 

561 if self.present and self.present.Flags and self.Flags.FCS: 

562 return Dot11FCS 

563 return Dot11 

564 

565 def post_dissect(self, s): 

566 length = max(self.len - len(self.original) + len(s), 0) 

567 self.notdecoded = s[:length] 

568 return s[length:] 

569 

570 def post_build(self, p, pay): 

571 if self.len is None: 

572 p = p[:2] + struct.pack("!H", len(p))[::-1] + p[4:] 

573 return p + pay 

574 

575 

576########## 

577# 802.11 # 

578########## 

579 

580# Note: 

581# 802.11-2016 includes the spec for 

582# 802.11abdghijekrywnpzvus,ae,aa,ad,ac,af 

583 

584# 802.11-2016 9.2 

585 

586# 802.11-2016 9.2.4.1.3 

587_dot11_subtypes = { 

588 0: { # Management 

589 0: "Association Request", 

590 1: "Association Response", 

591 2: "Reassociation Request", 

592 3: "Reassociation Response", 

593 4: "Probe Request", 

594 5: "Probe Response", 

595 6: "Timing Advertisement", 

596 8: "Beacon", 

597 9: "ATIM", 

598 10: "Disassociation", 

599 11: "Authentication", 

600 12: "Deauthentication", 

601 13: "Action", 

602 14: "Action No Ack", 

603 }, 

604 1: { # Control 

605 2: "Trigger", 

606 3: "TACK", 

607 4: "Beamforming Report Poll", 

608 5: "VHT/HE NDP Announcement", 

609 6: "Control Frame Extension", 

610 7: "Control Wrapper", 

611 8: "Block Ack Request", 

612 9: "Block Ack", 

613 10: "PS-Poll", 

614 11: "RTS", 

615 12: "CTS", 

616 13: "Ack", 

617 14: "CF-End", 

618 15: "CF-End+CF-Ack", 

619 }, 

620 2: { # Data 

621 0: "Data", 

622 1: "Data+CF-Ack", 

623 2: "Data+CF-Poll", 

624 3: "Data+CF-Ack+CF-Poll", 

625 4: "Null (no data)", 

626 5: "CF-Ack (no data)", 

627 6: "CF-Poll (no data)", 

628 7: "CF-Ack+CF-Poll (no data)", 

629 8: "QoS Data", 

630 9: "QoS Data+CF-Ack", 

631 10: "QoS Data+CF-Poll", 

632 11: "QoS Data+CF-Ack+CF-Poll", 

633 12: "QoS Null (no data)", 

634 14: "QoS CF-Poll (no data)", 

635 15: "QoS CF-Ack+CF-Poll (no data)" 

636 }, 

637 3: { # Extension 

638 0: "DMG Beacon", 

639 1: "S1G Beacon" 

640 } 

641} 

642 

643_dot11_cfe = { 

644 2: "Poll", 

645 3: "SPR", 

646 4: "Grant", 

647 5: "DMG CTS", 

648 6: "DMG DTS", 

649 7: "Grant Ack", 

650 8: "SSW", 

651 9: "SSW-Feedback", 

652 10: "SSW-Ack", 

653} 

654 

655 

656_dot11_addr_meaning = [ 

657 [ # Management: 802.11-2016 9.3.3.2 

658 "RA=DA", "TA=SA", "BSSID/STA", None, 

659 ], 

660 [ # Control 

661 "RA", "TA", None, None 

662 ], 

663 [ # Data: 802.11-2016 9.3.2.1: Table 9-26 

664 [["RA=DA", "RA=DA"], ["RA=BSSID", "RA"]], 

665 [["TA=SA", "TA=BSSID"], ["TA=SA", "TA"]], 

666 [["BSSID", "SA"], ["DA", "DA"]], 

667 [[None, None], ["SA", "BSSID"]], 

668 ], 

669 [ # Extension 

670 "BSSID", None, None, None 

671 ], 

672] 

673 

674 

675class _Dot11MacField(MACField): 

676 """ 

677 A MACField that displays the address type depending on the 

678 802.11 flags 

679 """ 

680 __slots__ = ["index"] 

681 

682 def __init__(self, name, default, index): 

683 self.index = index 

684 super(_Dot11MacField, self).__init__(name, default) 

685 

686 def i2repr(self, pkt, val): 

687 s = super(_Dot11MacField, self).i2repr(pkt, val) 

688 meaning = pkt.address_meaning(self.index) 

689 if meaning: 

690 return "%s (%s)" % (s, meaning) 

691 return s 

692 

693 

694# 802.11-2020 9.2.4.1.1 

695class Dot11(Packet): 

696 name = "802.11" 

697 fields_desc = [ 

698 BitMultiEnumField("subtype", 0, 4, _dot11_subtypes, 

699 lambda pkt: pkt.type), 

700 BitEnumField("type", 0, 2, ["Management", "Control", "Data", 

701 "Extension"]), 

702 BitField("proto", 0, 2), 

703 ConditionalField( 

704 BitEnumField("cfe", 0, 4, _dot11_cfe), 

705 lambda pkt: (pkt.type, pkt.subtype) == (1, 6) 

706 ), 

707 MultipleTypeField( 

708 [ 

709 ( 

710 FlagsField("FCfield", 0, 4, 

711 ["pw_mgt", "MD", "protected", "order"]), 

712 lambda pkt: (pkt.type, pkt.subtype) == (1, 6) 

713 ), 

714 ( 

715 FlagsField("FCfield", 0, 2, 

716 ["security", "AP_PM"]), 

717 lambda pkt: (pkt.type, pkt.subtype) == (3, 1) 

718 ) 

719 ], 

720 FlagsField("FCfield", 0, 8, 

721 ["to_DS", "from_DS", "MF", "retry", 

722 "pw_mgt", "MD", "protected", "order"]) 

723 ), 

724 ConditionalField( 

725 BitField("FCfield_bw", 0, 3), 

726 lambda pkt: (pkt.type, pkt.subtype) == (3, 1) 

727 ), 

728 ConditionalField( 

729 FlagsField("FCfield2", 0, 3, 

730 ["next_tbtt", "comp_ssid", "ano"]), 

731 lambda pkt: (pkt.type, pkt.subtype) == (3, 1) 

732 ), 

733 LEShortField("ID", 0), 

734 _Dot11MacField("addr1", ETHER_ANY, 1), 

735 ConditionalField( 

736 _Dot11MacField("addr2", ETHER_ANY, 2), 

737 lambda pkt: (pkt.type not in {1, 3} or 

738 pkt.subtype in [0x4, 0x5, 0x6, 0x8, 0x9, 0xa, 0xb, 0xe, 0xf]), 

739 ), 

740 ConditionalField( 

741 _Dot11MacField("addr3", ETHER_ANY, 3), 

742 lambda pkt: (pkt.type in [0, 2] or 

743 ((pkt.type, pkt.subtype) == (1, 6) and pkt.cfe == 6)), 

744 ), 

745 ConditionalField(LEShortField("SC", 0), lambda pkt: pkt.type not in {1, 3}), 

746 ConditionalField( 

747 _Dot11MacField("addr4", ETHER_ANY, 4), 

748 lambda pkt: (pkt.type == 2 and 

749 pkt.FCfield & 3 == 3), # from_DS+to_DS 

750 ) 

751 ] 

752 

753 def mysummary(self): 

754 # Supports both Dot11 and Dot11FCS 

755 return self.sprintf("802.11 %%%s.type%% %%%s.subtype%% %%%s.addr2%% > %%%s.addr1%%" % ((self.__class__.__name__,) * 4)) # noqa: E501 

756 

757 def guess_payload_class(self, payload): 

758 if self.type == 0x02 and ( 

759 0x08 <= self.subtype <= 0xF and self.subtype != 0xD): 

760 return Dot11QoS 

761 elif hasattr(self.FCfield, "protected") and self.FCfield.protected: 

762 # When a frame is handled by encryption, the Protected Frame bit 

763 # (previously called WEP bit) is set to 1, and the Frame Body 

764 # begins with the appropriate cryptographic header. 

765 return Dot11Encrypted 

766 else: 

767 return Packet.guess_payload_class(self, payload) 

768 

769 def answers(self, other): 

770 if isinstance(other, Dot11): 

771 if self.type == 0: # management 

772 if self.addr1.lower() != other.addr2.lower(): # check resp DA w/ req SA # noqa: E501 

773 return 0 

774 if (other.subtype, self.subtype) in [(0, 1), (2, 3), (4, 5)]: 

775 return 1 

776 if self.subtype == other.subtype == 11: # auth 

777 return self.payload.answers(other.payload) 

778 elif self.type == 1: # control 

779 return 0 

780 elif self.type == 2: # data 

781 return self.payload.answers(other.payload) 

782 elif self.type == 3: # reserved 

783 return 0 

784 return 0 

785 

786 def address_meaning(self, index): 

787 """ 

788 Return the meaning of the address[index] considering the context 

789 """ 

790 if index not in [1, 2, 3, 4]: 

791 raise ValueError("Wrong index: should be [1, 2, 3, 4]") 

792 index = index - 1 

793 if self.type == 0: # Management 

794 return _dot11_addr_meaning[0][index] 

795 elif self.type == 1: # Control 

796 if (self.type, self.subtype) == (1, 6) and self.cfe == 6: 

797 return ["RA", "NAV-SA", "NAV-DA"][index] 

798 return _dot11_addr_meaning[1][index] 

799 elif self.type == 2: # Data 

800 meaning = _dot11_addr_meaning[2][index][ 

801 self.FCfield.to_DS 

802 ][self.FCfield.from_DS] 

803 if meaning and index in [2, 3]: # Address 3-4 

804 if isinstance(self.payload, Dot11QoS): 

805 # MSDU and Short A-MSDU 

806 if self.payload.A_MSDU_Present: 

807 meaning = "BSSID" 

808 return meaning 

809 elif self.type == 3: # Extension 

810 return _dot11_addr_meaning[3][index] 

811 return None 

812 

813 def unwep(self, key=None, warn=1): 

814 if self.FCfield & 0x40 == 0: 

815 if warn: 

816 warning("No WEP to remove") 

817 return 

818 if isinstance(self.payload.payload, NoPayload): 

819 if key or conf.wepkey: 

820 self.payload.decrypt(key) 

821 if isinstance(self.payload.payload, NoPayload): 

822 if warn: 

823 warning("Dot11 can't be decrypted. Check conf.wepkey.") 

824 return 

825 self.FCfield &= ~0x40 

826 self.payload = self.payload.payload 

827 

828 

829class Dot11FCS(Dot11): 

830 name = "802.11-FCS" 

831 match_subclass = True 

832 fields_desc = Dot11.fields_desc + [FCSField("fcs", None, fmt="<I")] 

833 

834 def compute_fcs(self, s): 

835 return struct.pack("!I", crc32(s) & 0xffffffff)[::-1] 

836 

837 def post_build(self, p, pay): 

838 p += pay 

839 if self.fcs is None: 

840 p = p[:-4] + self.compute_fcs(p[:-4]) 

841 return p 

842 

843 

844class Dot11QoS(Packet): 

845 name = "802.11 QoS" 

846 fields_desc = [BitField("A_MSDU_Present", 0, 1), 

847 BitField("Ack_Policy", 0, 2), 

848 BitField("EOSP", 0, 1), 

849 BitField("TID", 0, 4), 

850 ByteField("TXOP", 0)] 

851 

852 def guess_payload_class(self, payload): 

853 if isinstance(self.underlayer, Dot11): 

854 if self.underlayer.FCfield.protected: 

855 return Dot11Encrypted 

856 return Packet.guess_payload_class(self, payload) 

857 

858 

859capability_list = ["res8", "res9", "short-slot", "res11", 

860 "res12", "DSSS-OFDM", "res14", "res15", 

861 "ESS", "IBSS", "CFP", "CFP-req", 

862 "privacy", "short-preamble", "PBCC", "agility"] 

863 

864reason_code = {0: "reserved", 1: "unspec", 2: "auth-expired", 

865 3: "deauth-ST-leaving", 

866 4: "inactivity", 5: "AP-full", 6: "class2-from-nonauth", 

867 7: "class3-from-nonass", 8: "disas-ST-leaving", 

868 9: "ST-not-auth"} 

869 

870status_code = {0: "success", 1: "failure", 10: "cannot-support-all-cap", 

871 11: "inexist-asso", 12: "asso-denied", 13: "algo-unsupported", 

872 14: "bad-seq-num", 15: "challenge-failure", 

873 16: "timeout", 17: "AP-full", 18: "rate-unsupported"} 

874 

875 

876class _Dot11EltUtils(Packet): 

877 """ 

878 Contains utils for classes that have Dot11Elt as payloads 

879 """ 

880 def network_stats(self): 

881 """Return a dictionary containing a summary of the Dot11 

882 elements fields 

883 """ 

884 summary = {} 

885 crypto = set() 

886 p = self.payload 

887 while isinstance(p, Dot11Elt): 

888 # Avoid overriding already-set SSID values because it is not part 

889 # of the standard and it protects from parsing bugs, 

890 # see https://github.com/secdev/scapy/issues/2683 

891 if p.ID == 0 and "ssid" not in summary: 

892 summary["ssid"] = plain_str(p.info) 

893 elif p.ID == 3: 

894 summary["channel"] = ord(p.info) 

895 elif isinstance(p, Dot11EltCountry): 

896 summary["country"] = plain_str(p.country_string[:2]) 

897 country_descriptor_types = { 

898 b"I": "Indoor", 

899 b"O": "Outdoor", 

900 b"X": "Non-country", 

901 b"\xff": "Ignored" 

902 } 

903 summary["country_desc_type"] = country_descriptor_types.get( 

904 p.country_string[-1:] 

905 ) 

906 elif isinstance(p, Dot11EltRates): 

907 rates = [(x & 0x7f) / 2. for x in p.rates] 

908 if "rates" in summary: 

909 summary["rates"].extend(rates) 

910 else: 

911 summary["rates"] = rates 

912 elif isinstance(p, Dot11EltRSN): 

913 wpa_version = "WPA2" 

914 # WPA3-only: 

915 # - AP shall at least enable AKM suite selector 00-0F-AC:8 

916 # - AP shall not enable AKM suite selector 00-0F-AC:2 and 

917 # 00-0F-AC:6 

918 # - AP shall set MFPC and MFPR to 1 

919 # - AP shall not enable WEP and TKIP 

920 # WPA3-transition: 

921 # - AP shall at least enable AKM suite selector 00-0F-AC:2 

922 # and 00-0F-AC:8 

923 # - AP shall set MFPC to 1 and MFPR to 0 

924 if any(x.suite == 8 for x in p.akm_suites) and \ 

925 all(x.suite not in [2, 6] for x in p.akm_suites) and \ 

926 p.mfp_capable and p.mfp_required and \ 

927 all(x.cipher not in [1, 2, 5] 

928 for x in p.pairwise_cipher_suites): 

929 # WPA3 only mode 

930 wpa_version = "WPA3" 

931 elif any(x.suite == 8 for x in p.akm_suites) and \ 

932 any(x.suite == 2 for x in p.akm_suites) and \ 

933 p.mfp_capable and not p.mfp_required: 

934 # WPA3 transition mode 

935 wpa_version = "WPA3-transition" 

936 # Append suite 

937 if p.akm_suites: 

938 auth = p.akm_suites[0].sprintf("%suite%") 

939 crypto.add(wpa_version + "/%s" % auth) 

940 else: 

941 crypto.add(wpa_version) 

942 elif p.ID == 221: 

943 if isinstance(p, Dot11EltMicrosoftWPA): 

944 if p.akm_suites: 

945 auth = p.akm_suites[0].sprintf("%suite%") 

946 crypto.add("WPA/%s" % auth) 

947 else: 

948 crypto.add("WPA") 

949 p = p.payload 

950 if not crypto and hasattr(self, "cap"): 

951 if self.cap.privacy: 

952 crypto.add("WEP") 

953 else: 

954 crypto.add("OPN") 

955 if crypto: 

956 summary["crypto"] = crypto 

957 return summary 

958 

959 

960############# 

961# 802.11 IE # 

962############# 

963 

964# 802.11-2016 - 9.4.2 

965 

966_dot11_info_elts_ids = { 

967 0: "SSID", 

968 1: "Supported Rates", 

969 2: "FHset", 

970 3: "DSSS Set", 

971 4: "CF Set", 

972 5: "TIM", 

973 6: "IBSS Set", 

974 7: "Country", 

975 10: "Request", 

976 11: "BSS Load", 

977 12: "EDCA Set", 

978 13: "TSPEC", 

979 14: "TCLAS", 

980 15: "Schedule", 

981 16: "Challenge text", 

982 32: "Power Constraint", 

983 33: "Power Capability", 

984 36: "Supported Channels", 

985 37: "Channel Switch Announcement", 

986 38: "Measurement Request", 

987 39: "Measurement Report", 

988 42: "ERP", 

989 45: "HT Capabilities", 

990 46: "QoS Capability", 

991 48: "RSN", 

992 50: "Extended Supported Rates", 

993 52: "Neighbor Report", 

994 61: "HT Operation", 

995 74: "Overlapping BSS Scan Parameters", 

996 107: "Interworking", 

997 127: "Extended Capabilities", 

998 191: "VHT Capabilities", 

999 192: "VHT Operation", 

1000 221: "Vendor Specific", 

1001 255: "Element ID Extension" 

1002} 

1003 

1004# Backward compatibility 

1005_dot11_elt_deprecated_names = { 

1006 "Rates": 1, 

1007 "DSset": 3, 

1008 "CFset": 4, 

1009 "IBSSset": 6, 

1010 "challenge": 16, 

1011 "PowerCapability": 33, 

1012 "Channels": 36, 

1013 "ERPinfo": 42, 

1014 "HTinfo": 45, 

1015 "RSNinfo": 48, 

1016 "ESRates": 50, 

1017 "ExtendendCapatibilities": 127, 

1018 "VHTCapabilities": 191, 

1019 "Vendor": 221, 

1020} 

1021 

1022_dot11_info_elts_ids_rev = {v: k for k, v in _dot11_info_elts_ids.items()} 

1023_dot11_info_elts_ids_rev.update(_dot11_elt_deprecated_names) 

1024_dot11_id_enum = ( 

1025 lambda x: _dot11_info_elts_ids.get(x, x), 

1026 lambda x: _dot11_info_elts_ids_rev.get(x, x) 

1027) 

1028 

1029 

1030# 802.11-2020 9.4.2.1 

1031 

1032class Dot11Elt(Packet): 

1033 """ 

1034 A Generic 802.11 Element 

1035 """ 

1036 __slots__ = ["info"] 

1037 name = "802.11 Information Element" 

1038 fields_desc = [ByteEnumField("ID", 0, _dot11_id_enum), 

1039 FieldLenField("len", None, "info", "B"), 

1040 StrLenField("info", "", length_from=lambda x: x.len, 

1041 max_length=255)] 

1042 show_indent = 0 

1043 

1044 def __setattr__(self, attr, val): 

1045 if attr == "info": 

1046 # Will be caught by __slots__: we need an extra call 

1047 try: 

1048 self.setfieldval(attr, val) 

1049 except AttributeError: 

1050 pass 

1051 super(Dot11Elt, self).__setattr__(attr, val) 

1052 

1053 def mysummary(self): 

1054 if self.ID == 0: 

1055 ssid = plain_str(self.info) 

1056 return "SSID='%s'" % ssid, [Dot11] 

1057 else: 

1058 return "" 

1059 

1060 registered_ies = {} 

1061 

1062 @classmethod 

1063 def register_variant(cls, id=None): 

1064 id = id or cls.ID.default 

1065 if id not in cls.registered_ies: 

1066 cls.registered_ies[id] = cls 

1067 

1068 @classmethod 

1069 def dispatch_hook(cls, _pkt=None, *args, **kargs): 

1070 if _pkt: 

1071 _id = ord(_pkt[:1]) 

1072 idcls = cls.registered_ies.get(_id, cls) 

1073 if idcls.dispatch_hook != cls.dispatch_hook: 

1074 # Vendor has its own dispatch_hook 

1075 return idcls.dispatch_hook(_pkt=_pkt, *args, **kargs) 

1076 cls = idcls 

1077 return cls 

1078 

1079 def pre_dissect(self, s): 

1080 # Backward compatibility: add info to all elements 

1081 # This allows to introduce new Dot11Elt classes without breaking 

1082 # previous code 

1083 if len(s) >= 3: 

1084 length = orb(s[1]) 

1085 if length > 0 and length <= 255: 

1086 self.info = s[2:2 + length] 

1087 return s 

1088 

1089 def post_build(self, p, pay): 

1090 if self.len is None: 

1091 p = p[:1] + chb(len(p) - 2) + p[2:] 

1092 return p + pay 

1093 

1094 

1095# 802.11-2020 9.4.2.4 

1096 

1097class Dot11EltDSSSet(Dot11Elt): 

1098 name = "802.11 DSSS Parameter Set" 

1099 match_subclass = True 

1100 fields_desc = [ 

1101 ByteEnumField("ID", 3, _dot11_id_enum), 

1102 ByteField("len", 1), 

1103 ByteField("channel", 0), 

1104 ] 

1105 

1106 

1107# 802.11-2020 9.4.2.11 

1108 

1109class Dot11EltERP(Dot11Elt): 

1110 name = "802.11 ERP" 

1111 match_subclass = True 

1112 fields_desc = [ 

1113 ByteEnumField("ID", 42, _dot11_id_enum), 

1114 ByteField("len", 1), 

1115 BitField("NonERP_Present", 0, 1), 

1116 BitField("Use_Protection", 0, 1), 

1117 BitField("Barker_Preamble_Mode", 0, 1), 

1118 BitField("res", 0, 5), 

1119 ] 

1120 

1121 

1122# 802.11-2020 9.4.2.24.2 

1123 

1124class RSNCipherSuite(Packet): 

1125 name = "Cipher suite" 

1126 fields_desc = [ 

1127 OUIField("oui", 0x000fac), 

1128 ByteEnumField("cipher", 0x04, { 

1129 0x00: "Use group cipher suite", 

1130 0x01: "WEP-40", 

1131 0x02: "TKIP", 

1132 0x03: "OCB", 

1133 0x04: "CCMP-128", 

1134 0x05: "WEP-104", 

1135 0x06: "BIP-CMAC-128", 

1136 0x07: "Group addressed traffic not allowed", 

1137 0x08: "GCMP-128", 

1138 0x09: "GCMP-256", 

1139 0x0A: "CCMP-256", 

1140 0x0B: "BIP-GMAC-128", 

1141 0x0C: "BIP-GMAC-256", 

1142 0x0D: "BIP-CMAC-256" 

1143 }) 

1144 ] 

1145 

1146 def extract_padding(self, s): 

1147 return "", s 

1148 

1149 

1150# 802.11-2020 9.4.2.24.3 

1151 

1152class AKMSuite(Packet): 

1153 name = "AKM suite" 

1154 fields_desc = [ 

1155 OUIField("oui", 0x000fac), 

1156 ByteEnumField("suite", 0x01, { 

1157 0x00: "Reserved", 

1158 0x01: "802.1X", 

1159 0x02: "PSK", 

1160 0x03: "FT-802.1X", 

1161 0x04: "FT-PSK", 

1162 0x05: "WPA-SHA256", 

1163 0x06: "PSK-SHA256", 

1164 0x07: "TDLS", 

1165 0x08: "SAE", 

1166 0x09: "FT-SAE", 

1167 0x0A: "AP-PEER-KEY", 

1168 0x0B: "WPA-SHA256-SUITE-B", 

1169 0x0C: "WPA-SHA384-SUITE-B", 

1170 0x0D: "FT-802.1X-SHA384", 

1171 0x0E: "FILS-SHA256", 

1172 0x0F: "FILS-SHA384", 

1173 0x10: "FT-FILS-SHA256", 

1174 0x11: "FT-FILS-SHA384", 

1175 0x12: "OWE" 

1176 }) 

1177 ] 

1178 

1179 def extract_padding(self, s): 

1180 return "", s 

1181 

1182 

1183# 802.11-2020 9.4.2.24.5 

1184 

1185class PMKIDListPacket(Packet): 

1186 name = "PMKIDs" 

1187 fields_desc = [ 

1188 LEFieldLenField("nb_pmkids", None, count_of="pmkid_list"), 

1189 FieldListField( 

1190 "pmkid_list", 

1191 None, 

1192 XStrFixedLenField("", "", length=16), 

1193 count_from=lambda pkt: pkt.nb_pmkids 

1194 ) 

1195 ] 

1196 

1197 def extract_padding(self, s): 

1198 return "", s 

1199 

1200 

1201# 802.11-2020 9.4.2.24.1 

1202 

1203class Dot11EltRSN(Dot11Elt): 

1204 name = "802.11 RSN information" 

1205 match_subclass = True 

1206 fields_desc = [ 

1207 ByteEnumField("ID", 48, _dot11_id_enum), 

1208 ByteField("len", None), 

1209 LEShortField("version", 1), 

1210 PacketField("group_cipher_suite", RSNCipherSuite(), RSNCipherSuite), 

1211 LEFieldLenField( 

1212 "nb_pairwise_cipher_suites", 

1213 None, 

1214 count_of="pairwise_cipher_suites" 

1215 ), 

1216 PacketListField( 

1217 "pairwise_cipher_suites", 

1218 [RSNCipherSuite()], 

1219 RSNCipherSuite, 

1220 count_from=lambda p: p.nb_pairwise_cipher_suites 

1221 ), 

1222 LEFieldLenField( 

1223 "nb_akm_suites", 

1224 None, 

1225 count_of="akm_suites" 

1226 ), 

1227 PacketListField( 

1228 "akm_suites", 

1229 [AKMSuite()], 

1230 AKMSuite, 

1231 count_from=lambda p: p.nb_akm_suites 

1232 ), 

1233 # RSN Capabilities 

1234 # 802.11-2020 9.4.2.24.4 

1235 BitField("mfp_capable", 1, 1), 

1236 BitField("mfp_required", 1, 1), 

1237 BitField("gtksa_replay_counter", 0, 2), 

1238 BitField("ptksa_replay_counter", 0, 2), 

1239 BitField("no_pairwise", 0, 1), 

1240 BitField("pre_auth", 0, 1), 

1241 BitField("reserved", 0, 1), 

1242 BitField("ocvc", 0, 1), 

1243 BitField("extended_key_id", 0, 1), 

1244 BitField("pbac", 0, 1), 

1245 BitField("spp_a_msdu_required", 0, 1), 

1246 BitField("spp_a_msdu_capable", 0, 1), 

1247 BitField("peer_key_enabled", 0, 1), 

1248 BitField("joint_multiband_rsna", 0, 1), 

1249 # Theoretically we could use mfp_capable/mfp_required to know if those 

1250 # fields are present, but some implementations poorly implement it. 

1251 # In practice, do as wireshark: guess using offset. 

1252 ConditionalField( 

1253 PacketField("pmkids", PMKIDListPacket(), PMKIDListPacket), 

1254 lambda pkt: ( 

1255 True if pkt.len is None else 

1256 pkt.len - ( 

1257 12 + 

1258 (pkt.nb_pairwise_cipher_suites or 0) * 4 + 

1259 (pkt.nb_akm_suites or 0) * 4 

1260 ) >= 2 

1261 ) 

1262 ), 

1263 ConditionalField( 

1264 PacketField("group_management_cipher_suite", 

1265 RSNCipherSuite(cipher=0x6), RSNCipherSuite), 

1266 lambda pkt: ( 

1267 True if pkt.len is None else 

1268 pkt.len - ( 

1269 12 + 

1270 (pkt.nb_pairwise_cipher_suites or 0) * 4 + 

1271 (pkt.nb_akm_suites or 0) * 4 + 

1272 (2 if pkt.pmkids else 0) + 

1273 (pkt.pmkids and pkt.pmkids.nb_pmkids or 0) * 16 

1274 ) >= 4 

1275 ) 

1276 ) 

1277 ] 

1278 

1279 

1280class Dot11EltCountryConstraintTriplet(Packet): 

1281 name = "802.11 Country Constraint Triplet" 

1282 fields_desc = [ 

1283 ByteField("first_channel_number", 1), 

1284 ByteField("num_channels", 24), 

1285 ByteField("mtp", 0) 

1286 ] 

1287 

1288 def extract_padding(self, s): 

1289 return b"", s 

1290 

1291 

1292class Dot11EltCountry(Dot11Elt): 

1293 name = "802.11 Country" 

1294 match_subclass = True 

1295 fields_desc = [ 

1296 ByteEnumField("ID", 7, _dot11_id_enum), 

1297 ByteField("len", None), 

1298 StrFixedLenField("country_string", b"\0\0\0", length=3), 

1299 MayEnd(PacketListField( 

1300 "descriptors", 

1301 [], 

1302 Dot11EltCountryConstraintTriplet, 

1303 length_from=lambda pkt: ( 

1304 pkt.len - 3 - (pkt.len % 3) 

1305 ) 

1306 )), 

1307 # When this extension is last, padding appears to be omitted 

1308 ConditionalField( 

1309 ByteField("pad", 0), 

1310 # The length should be 3 bytes per each triplet, and 3 bytes for the 

1311 # country_string field. The standard dictates that the element length 

1312 # must be even, so if the result is odd, add a padding byte. 

1313 # Some transmitters don't comply with the standard, so instead of assuming 

1314 # the length, we test whether there is a padding byte. 

1315 # Some edge cases are still not covered, for example, if the tag length 

1316 # (pkt.len) is an arbitrary number. 

1317 lambda pkt: ((len(pkt.descriptors) + 1) % 2) if pkt.len is None else (pkt.len % 3) # noqa: E501 

1318 ) 

1319 ] 

1320 

1321 

1322class _RateField(ByteField): 

1323 def i2repr(self, pkt, val): 

1324 if val is None: 

1325 return "" 

1326 s = str((val & 0x7f) / 2.) 

1327 if val & 0x80: 

1328 s += "(B)" 

1329 return s + " Mbps" 

1330 

1331 

1332class Dot11EltRates(Dot11Elt): 

1333 name = "802.11 Rates" 

1334 match_subclass = True 

1335 fields_desc = [ 

1336 ByteEnumField("ID", 1, _dot11_id_enum), 

1337 ByteField("len", None), 

1338 FieldListField( 

1339 "rates", 

1340 [0x82], 

1341 _RateField("", 0), 

1342 length_from=lambda p: p.len 

1343 ) 

1344 ] 

1345 

1346 

1347Dot11EltRates.register_variant(50) # Extended rates 

1348 

1349 

1350class Dot11EltHTCapabilities(Dot11Elt): 

1351 name = "802.11 HT Capabilities" 

1352 match_subclass = True 

1353 fields_desc = [ 

1354 ByteEnumField("ID", 45, _dot11_id_enum), 

1355 ByteField("len", None), 

1356 # HT Capabilities Info: 2B 

1357 BitField("L_SIG_TXOP_Protection", 0, 1, tot_size=-2), 

1358 BitField("Forty_Mhz_Intolerant", 0, 1), 

1359 BitField("PSMP", 0, 1), 

1360 BitField("DSSS_CCK", 0, 1), 

1361 BitEnumField("Max_A_MSDU", 0, 1, {0: "3839 o", 1: "7935 o"}), 

1362 BitField("Delayed_BlockAck", 0, 1), 

1363 BitField("Rx_STBC", 0, 2), 

1364 BitField("Tx_STBC", 0, 1), 

1365 BitField("Short_GI_40Mhz", 0, 1), 

1366 BitField("Short_GI_20Mhz", 0, 1), 

1367 BitField("Green_Field", 0, 1), 

1368 BitEnumField("SM_Power_Save", 0, 2, 

1369 {0: "static SM", 1: "dynamic SM", 3: "disabled"}), 

1370 BitEnumField("Supported_Channel_Width", 0, 1, 

1371 {0: "20Mhz", 1: "20Mhz+40Mhz"}), 

1372 BitField("LDPC_Coding_Capability", 0, 1, end_tot_size=-2), 

1373 # A-MPDU Parameters: 1B 

1374 BitField("res1", 0, 3, tot_size=-1), 

1375 BitField("Min_MPDCU_Start_Spacing", 8, 3), 

1376 BitField("Max_A_MPDU_Length_Exponent", 3, 2, end_tot_size=-1), 

1377 # Supported MCS set: 16B 

1378 BitField("res2", 0, 27, tot_size=-16), 

1379 BitField("TX_Unequal_Modulation", 0, 1), 

1380 BitField("TX_Max_Spatial_Streams", 0, 2), 

1381 BitField("TX_RX_MCS_Set_Not_Equal", 0, 1), 

1382 BitField("TX_MCS_Set_Defined", 0, 1), 

1383 BitField("res3", 0, 6), 

1384 BitField("RX_Highest_Supported_Data_Rate", 0, 10), 

1385 BitField("res4", 0, 3), 

1386 BitField("RX_MSC_Bitmask", 0, 77, end_tot_size=-16), 

1387 # HT Extended capabilities: 2B 

1388 BitField("res5", 0, 4, tot_size=-2), 

1389 BitField("RD_Responder", 0, 1), 

1390 BitField("HTC_HT_Support", 0, 1), 

1391 BitField("MCS_Feedback", 0, 2), 

1392 BitField("res6", 0, 5), 

1393 BitField("PCO_Transition_Time", 0, 2), 

1394 BitField("PCO", 0, 1, end_tot_size=-2), 

1395 # TX Beamforming Capabilities TxBF: 4B 

1396 BitField("res7", 0, 3, tot_size=-4), 

1397 BitField("Channel_Estimation_Capability", 0, 2), 

1398 BitField("CSI_max_n_Rows_Beamformer_Supported", 0, 2), 

1399 BitField("Compressed_Steering_n_Beamformer_Antennas_Supported", 0, 2), 

1400 BitField("Noncompressed_Steering_n_Beamformer_Antennas_Supported", 

1401 0, 2), 

1402 BitField("CSI_n_Beamformer_Antennas_Supported", 0, 2), 

1403 BitField("Minimal_Grouping", 0, 2), 

1404 BitField("Explicit_Compressed_Beamforming_Feedback", 0, 2), 

1405 BitField("Explicit_Noncompressed_Beamforming_Feedback", 0, 2), 

1406 BitField("Explicit_Transmit_Beamforming_CSI_Feedback", 0, 2), 

1407 BitField("Explicit_Compressed_Steering", 0, 1), 

1408 BitField("Explicit_Noncompressed_Steering", 0, 1), 

1409 BitField("Explicit_CSI_Transmit_Beamforming", 0, 1), 

1410 BitField("Calibration", 0, 2), 

1411 BitField("Implicit_Trasmit_Beamforming", 0, 1), 

1412 BitField("Transmit_NDP", 0, 1), 

1413 BitField("Receive_NDP", 0, 1), 

1414 BitField("Transmit_Staggered_Sounding", 0, 1), 

1415 BitField("Receive_Staggered_Sounding", 0, 1), 

1416 BitField("Implicit_Transmit_Beamforming_Receiving", 0, 1, 

1417 end_tot_size=-4), 

1418 # ASEL Capabilities: 1B 

1419 FlagsField("ASEL", 0, 8, [ 

1420 "res", 

1421 "Transmit_Sounding_PPDUs", 

1422 "Receive_ASEL", 

1423 "Antenna_Indices_Feedback", 

1424 "Explicit_CSI_Feedback", 

1425 "Explicit_CSI_Feedback_Based_Transmit_ASEL", 

1426 "Antenna_Selection", 

1427 ]) 

1428 ] 

1429 

1430 

1431class Dot11EltVendorSpecific(Dot11Elt): 

1432 name = "802.11 Vendor Specific" 

1433 match_subclass = True 

1434 fields_desc = [ 

1435 ByteEnumField("ID", 221, _dot11_id_enum), 

1436 ByteField("len", None), 

1437 OUIField("oui", 0x000000), 

1438 StrLenField("info", "", length_from=lambda x: x.len - 3) 

1439 ] 

1440 

1441 @classmethod 

1442 def dispatch_hook(cls, _pkt=None, *args, **kargs): 

1443 if _pkt: 

1444 oui = struct.unpack("!I", b"\x00" + _pkt[2:5])[0] 

1445 ouicls = cls.registered_ouis.get(oui, cls) 

1446 if ouicls.dispatch_hook != cls.dispatch_hook: 

1447 # Sub-classes can have their own dispatch_hook 

1448 return ouicls.dispatch_hook(_pkt=_pkt, *args, **kargs) 

1449 cls = ouicls 

1450 return cls 

1451 

1452 registered_ouis = {} 

1453 

1454 @classmethod 

1455 def register_variant(cls): 

1456 oui = cls.oui.default 

1457 if not oui: 

1458 # This is Dot11EltVendorSpecific, register it in the super-class. 

1459 super().register_variant() 

1460 elif oui not in cls.registered_ouis: 

1461 # Sub-Vendor (e.g. Dot11EltMicrosoftWPA) 

1462 cls.registered_ouis[oui] = cls 

1463 

1464 

1465class Dot11EltMicrosoftWPA(Dot11EltVendorSpecific): 

1466 name = "802.11 Microsoft WPA" 

1467 match_subclass = True 

1468 ID = 221 

1469 oui = 0x0050f2 

1470 # It appears many WPA implementations ignore the fact 

1471 # that this IE should only have a single cipher and auth suite 

1472 fields_desc = Dot11EltVendorSpecific.fields_desc[:3] + [ 

1473 XByteField("type", 0x01) 

1474 ] + Dot11EltRSN.fields_desc[2:8] 

1475 

1476 @classmethod 

1477 def dispatch_hook(cls, _pkt=None, *args, **kargs): 

1478 if _pkt: 

1479 type_ = orb(_pkt[5]) 

1480 if type_ == 0x01: 

1481 # MS WPA IE 

1482 return Dot11EltMicrosoftWPA 

1483 elif type_ == 0x02: 

1484 # MS WME IE TODO 

1485 # return Dot11EltMicrosoftWME 

1486 pass 

1487 elif type_ == 0x04: 

1488 # MS WPS IE TODO 

1489 # return Dot11EltWPS 

1490 pass 

1491 return Dot11EltVendorSpecific 

1492 return cls 

1493 

1494 

1495# 802.11-2016 9.4.2.19 

1496 

1497class Dot11EltCSA(Dot11Elt): 

1498 name = "802.11 CSA Element" 

1499 match_subclass = True 

1500 fields_desc = [ 

1501 ByteEnumField("ID", 37, _dot11_id_enum), 

1502 ByteField("len", 3), 

1503 ByteField("mode", 0), 

1504 ByteField("new_channel", 0), 

1505 ByteField("channel_switch_count", 0) 

1506 ] 

1507 

1508 

1509# 802.11-2016 9.4.2.59 

1510 

1511class Dot11EltOBSS(Dot11Elt): 

1512 name = "802.11 OBSS Scan Parameters Element" 

1513 match_subclass = True 

1514 fields_desc = [ 

1515 ByteEnumField("ID", 74, _dot11_id_enum), 

1516 ByteField("len", 14), 

1517 LEShortField("Passive_Dwell", 0), 

1518 LEShortField("Active_Dwell", 0), 

1519 LEShortField("Scan_Interval", 0), 

1520 LEShortField("Passive_Total_Per_Channel", 0), 

1521 LEShortField("Active_Total_Per_Channel", 0), 

1522 LEShortField("Delay", 0), 

1523 LEShortField("Activity_Threshold", 0), 

1524 ] 

1525 

1526 

1527# 802.11-2016 9.4.2.159 

1528 

1529class Dot11VHTOperationInfo(Packet): 

1530 name = "802.11 VHT Operation Information" 

1531 fields_desc = [ 

1532 ByteField("channel_width", 0), 

1533 ByteField("channel_center0", 36), 

1534 ByteField("channel_center1", 0), 

1535 ] 

1536 

1537 def extract_padding(self, s): 

1538 return "", s 

1539 

1540 

1541class Dot11EltVHTOperation(Dot11Elt): 

1542 name = "802.11 VHT Operation Element" 

1543 match_subclass = True 

1544 fields_desc = [ 

1545 ByteEnumField("ID", 192, _dot11_id_enum), 

1546 ByteField("len", 5), 

1547 PacketField( 

1548 "VHT_Operation_Info", 

1549 Dot11VHTOperationInfo(), 

1550 Dot11VHTOperationInfo 

1551 ), 

1552 FieldListField( 

1553 "mcs_set", 

1554 [0x00], 

1555 BitField('SS', 0x00, size=2), 

1556 count_from=lambda x: 8 

1557 ) 

1558 ] 

1559 

1560 

1561# 802.11ax-2021 9.4.2.1, Table 9-92 

1562 

1563class Dot11EltExtension(Dot11Elt): 

1564 # Element ID Extension is a registry for many IEs. Only HE Operation is 

1565 # specialized here; unknown and unsupported extension IDs stay generic. 

1566 name = "802.11 Element ID Extension" 

1567 match_subclass = True 

1568 ID = 255 

1569 fields_desc = [ 

1570 ByteEnumField("ID", 255, _dot11_id_enum), 

1571 ByteField("len", 0), 

1572 ConditionalField( 

1573 ByteField("ext_ID", 0), 

1574 lambda pkt: pkt.len > 0 

1575 ), 

1576 ] 

1577 

1578 @classmethod 

1579 def dispatch_hook(cls, _pkt=None, *args, **kargs): 

1580 if not _pkt or len(_pkt) < 3: 

1581 return cls 

1582 

1583 if _pkt: 

1584 ext_id = orb(_pkt[2]) 

1585 idcls = cls.registered_ext_ids.get(ext_id) 

1586 if idcls is not None: 

1587 return idcls 

1588 return Dot11EltExtensionGeneric 

1589 return cls 

1590 

1591 registered_ext_ids = {} 

1592 

1593 @classmethod 

1594 def register_variant(cls, ext_id=None): 

1595 ext_id = ext_id or cls.ext_ID.default 

1596 if not ext_id: 

1597 # This is Dot11EltExtension, register it in the super-class. 

1598 super().register_variant() 

1599 elif ext_id not in cls.registered_ext_ids: 

1600 # Register extension ID to class (e.g. Dot11EltHEOperation) 

1601 cls.registered_ext_ids[ext_id] = cls 

1602 

1603 

1604# 802.11ax-2021 9.4.2.1, Table 9-92 

1605 

1606class Dot11EltExtensionGeneric(Dot11EltExtension): 

1607 name = "802.11 Element ID Extension" 

1608 match_subclass = True 

1609 ID = 255 

1610 fields_desc = Dot11EltExtension.fields_desc + [ 

1611 StrLenField("info", b"", length_from=lambda pkt: max(pkt.len - 1, 0))] 

1612 

1613 

1614# 802.11ax-2021 9.4.2.249, Figure 9-788k 

1615 

1616class Dot11HE6GOperationInfo(Packet): 

1617 name = "802.11 HE 6 GHz Operation Information" 

1618 fields_desc = [ 

1619 ByteField("primary_channel", 0), 

1620 # Control: 1B 

1621 BitField("reserved", 0, 2, tot_size=-1), 

1622 BitField("regulatory_info", 0, 3), 

1623 BitField("duplicate_beacon", 0, 1), 

1624 BitField("channel_width", 0, 2, end_tot_size=-1), 

1625 

1626 ByteField("channel_center0", 0), 

1627 ByteField("channel_center1", 0), 

1628 ByteField("minimum_rate", 0), 

1629 ] 

1630 

1631 def extract_padding(self, s): 

1632 return "", s 

1633 

1634 

1635# 802.11ax-2021 9.4.2.249 

1636 

1637class Dot11EltHEOperation(Dot11EltExtension): 

1638 name = "802.11 HE Operation" 

1639 match_subclass = True 

1640 ID = 255 

1641 ext_ID = 36 

1642 fields_desc = Dot11EltExtension.fields_desc + [ 

1643 # HE Operation Parameters: 3B 

1644 BitField("reserved", 0, 6, tot_size=-3), 

1645 BitField("six_g_op_info_present", 0, 1), 

1646 BitField("er_su_disable", 0, 1), 

1647 BitField("co_hosted_bss", 0, 1), 

1648 BitField("vht_operation_info_present", 0, 1), 

1649 BitField("txop_duration_rts_threshold", 0, 10), 

1650 BitField("twt_required", 0, 1), 

1651 BitField("default_pe_duration", 0, 3, end_tot_size=-3), 

1652 

1653 # BSS Color Information: 1B 

1654 BitField("bss_color_disabled", 0, 1, tot_size=-1), 

1655 BitField("partial_bss_color", 0, 1), 

1656 BitField("bss_color", 0, 6, end_tot_size=-1), 

1657 # Basic HE-MCS and NSS Set: 2B 

1658 FieldListField( 

1659 "basic_he_mcs_and_nss_set", 

1660 [0x00], 

1661 BitField('SS', 0x00, size=2), 

1662 count_from=lambda x: 8 

1663 ), 

1664 

1665 ConditionalField( 

1666 PacketField( 

1667 "vht_operation_info", 

1668 Dot11VHTOperationInfo(), 

1669 Dot11VHTOperationInfo 

1670 ), 

1671 lambda p: p.vht_operation_info_present == 1), 

1672 

1673 ConditionalField( 

1674 ByteField("max_co_hosted_bssid", 0), 

1675 lambda p: p.co_hosted_bss == 1), 

1676 

1677 ConditionalField( 

1678 PacketField( 

1679 "he_6g_operation_info", 

1680 Dot11HE6GOperationInfo(), 

1681 Dot11HE6GOperationInfo 

1682 ), 

1683 lambda p: p.six_g_op_info_present == 1) 

1684 ] 

1685 

1686 

1687Dot11EltHEOperation.register_variant(36) 

1688 

1689 

1690# 802.11n-2009 7.3.2.57, Figure 7-95o24, Table 7-43p 

1691 

1692class Dot11EltHTOperation(Dot11Elt): 

1693 name = "802.11 HT Operation" 

1694 match_subclass = True 

1695 fields_desc = [ 

1696 ByteEnumField("ID", 61, _dot11_id_enum), 

1697 ByteField("len", 22), 

1698 ByteField("primary_channel", 0), 

1699 

1700 # HT Operation Information: 1B 

1701 BitField("reserved_1", 0, 4, tot_size=-1), 

1702 BitField("rifs_mode", 0, 1), 

1703 BitField("channel_width", 0, 1), 

1704 BitField("secondary_channel_offset", 0, 2, end_tot_size=-1), 

1705 

1706 # HT Operation Information: 2B 

1707 BitField("reserved_3", 0, 11, tot_size=-2), 

1708 BitField("obss_non_ht_stas_present", 0, 1), 

1709 BitField("reserved_2", 0, 1), 

1710 BitField("nongreenfield_ht_stas_present", 0, 1), 

1711 BitField("ht_protection", 0, 2, end_tot_size=-2), 

1712 

1713 # HT Operation Information: 2B 

1714 BitField("reserved_4", 0, 10, tot_size=-2), 

1715 BitField("pco_phase", 0, 1), 

1716 BitField("pco_active", 0, 1), 

1717 BitField("lsig_txop_protection_full_support", 0, 1), 

1718 BitField("stbc_beacon", 0, 1), 

1719 BitField("dual_cts_protection", 0, 1), 

1720 BitField("dual_beacon", 0, 1, end_tot_size=-2), 

1721 

1722 StrFixedLenField("basic_mcs_set", b"\x00" * 16, 16), 

1723 ] 

1724 

1725 

1726###################### 

1727# 802.11 Frame types # 

1728###################### 

1729 

1730# 802.11-2016 9.3 

1731 

1732class Dot11Beacon(_Dot11EltUtils): 

1733 name = "802.11 Beacon" 

1734 fields_desc = [LELongField("timestamp", 0), 

1735 LEShortField("beacon_interval", 0x0064), 

1736 FlagsField("cap", 0, 16, capability_list)] 

1737 

1738 

1739class Dot11ATIM(Packet): 

1740 name = "802.11 ATIM" 

1741 

1742 

1743class Dot11Disas(Packet): 

1744 name = "802.11 Disassociation" 

1745 fields_desc = [LEShortEnumField("reason", 1, reason_code)] 

1746 

1747 

1748class Dot11AssoReq(_Dot11EltUtils): 

1749 name = "802.11 Association Request" 

1750 fields_desc = [FlagsField("cap", 0, 16, capability_list), 

1751 LEShortField("listen_interval", 0x00c8)] 

1752 

1753 

1754class Dot11AssoResp(_Dot11EltUtils): 

1755 name = "802.11 Association Response" 

1756 fields_desc = [FlagsField("cap", 0, 16, capability_list), 

1757 LEShortField("status", 0), 

1758 LEShortField("AID", 0)] 

1759 

1760 

1761class Dot11ReassoReq(_Dot11EltUtils): 

1762 name = "802.11 Reassociation Request" 

1763 fields_desc = [FlagsField("cap", 0, 16, capability_list), 

1764 LEShortField("listen_interval", 0x00c8), 

1765 MACField("current_AP", ETHER_ANY)] 

1766 

1767 

1768class Dot11ReassoResp(Dot11AssoResp): 

1769 name = "802.11 Reassociation Response" 

1770 

1771 

1772class Dot11ProbeReq(_Dot11EltUtils): 

1773 name = "802.11 Probe Request" 

1774 

1775 

1776class Dot11ProbeResp(_Dot11EltUtils): 

1777 name = "802.11 Probe Response" 

1778 fields_desc = [LELongField("timestamp", 0), 

1779 LEShortField("beacon_interval", 0x0064), 

1780 FlagsField("cap", 0, 16, capability_list)] 

1781 

1782 

1783class Dot11Auth(_Dot11EltUtils): 

1784 name = "802.11 Authentication" 

1785 fields_desc = [LEShortEnumField("algo", 0, ["open", "sharedkey"]), 

1786 LEShortField("seqnum", 0), 

1787 LEShortEnumField("status", 0, status_code)] 

1788 

1789 def answers(self, other): 

1790 if self.algo != other.algo: 

1791 return 0 

1792 

1793 if ( 

1794 self.seqnum == other.seqnum + 1 or 

1795 (self.algo == 3 and self.seqnum == other.seqnum) 

1796 ): 

1797 return 1 

1798 return 0 

1799 

1800 

1801class Dot11Deauth(Packet): 

1802 name = "802.11 Deauthentication" 

1803 fields_desc = [LEShortEnumField("reason", 1, reason_code)] 

1804 

1805 

1806class Dot11Ack(Packet): 

1807 name = "802.11 Ack packet" 

1808 

1809 

1810# 802.11-2016 9.4.1.11 

1811 

1812class Dot11Action(Packet): 

1813 name = "802.11 Action" 

1814 fields_desc = [ 

1815 ByteEnumField("category", 0x00, { 

1816 0x00: "Spectrum Management", 

1817 0x01: "QoS", 

1818 0x02: "DLS", 

1819 0x03: "Block", 

1820 0x04: "Public", 

1821 0x05: "Radio Measurement", 

1822 0x06: "Fast BSS Transition", 

1823 0x07: "HT", 

1824 0x08: "SA Query", 

1825 0x09: "Protected Dual of Public Action", 

1826 0x0A: "WNM", 

1827 0x0B: "Unprotected WNM", 

1828 0x0C: "TDLS", 

1829 0x0D: "Mesh", 

1830 0x0E: "Multihop", 

1831 0x0F: "Self-protected", 

1832 0x10: "DMG", 

1833 0x11: "Reserved Wi-Fi Alliance", 

1834 0x12: "Fast Session Transfer", 

1835 0x13: "Robust AV Streaming", 

1836 0x14: "Unprotected DMG", 

1837 0x15: "VHT" 

1838 }) 

1839 ] 

1840 

1841 

1842# 802.11-2016 9.6.14.1 

1843 

1844class Dot11WNM(Packet): 

1845 name = "802.11 WNM Action" 

1846 fields_desc = [ 

1847 ByteEnumField("action", 0x00, { 

1848 0x00: "Event Request", 

1849 0x01: "Event Report", 

1850 0x02: "Diagnostic Request", 

1851 0x03: "Diagnostic Report", 

1852 0x04: "Location Configuration Request", 

1853 0x05: "Location Configuration Response", 

1854 0x06: "BSS Transition Management Query", 

1855 0x07: "BSS Transition Management Request", 

1856 0x08: "BSS Transition Management Response", 

1857 0x09: "FMS Request", 

1858 0x0A: "FMS Response", 

1859 0x0B: "Collocated Interference Request", 

1860 0x0C: "Collocated Interference Report", 

1861 0x0D: "TFS Request", 

1862 0x0E: "TFS Response", 

1863 0x0F: "TFS Notify", 

1864 0x10: "WNM Sleep Mode Request", 

1865 0x11: "WNM Sleep Mode Response", 

1866 0x12: "TIM Broadcast Request", 

1867 0x13: "TIM Broadcast Response", 

1868 0x14: "QoS Traffic Capability Update", 

1869 0x15: "Channel Usage Request", 

1870 0x16: "Channel Usage Response", 

1871 0x17: "DMS Request", 

1872 0x18: "DMS Response", 

1873 0x19: "Timing Measurement Request", 

1874 0x1A: "WNM Notification Request", 

1875 0x1B: "WNM Notification Response", 

1876 0x1C: "WNM-Notify Response" 

1877 }) 

1878 ] 

1879 

1880 

1881# 802.11-2016 9.4.2.37 

1882 

1883class SubelemTLV(Packet): 

1884 fields_desc = [ 

1885 ByteField("type", 0), 

1886 LEFieldLenField("len", None, fmt="B", length_of="value"), 

1887 FieldListField( 

1888 "value", 

1889 [], 

1890 ByteField('', 0), 

1891 length_from=lambda p: p.len 

1892 ) 

1893 ] 

1894 

1895 

1896class BSSTerminationDuration(Packet): 

1897 name = "BSS Termination Duration" 

1898 fields_desc = [ 

1899 ByteField("id", 4), 

1900 ByteField("len", 10), 

1901 LELongField("TSF", 0), 

1902 LEShortField("duration", 0) 

1903 ] 

1904 

1905 def extract_padding(self, s): 

1906 return "", s 

1907 

1908 

1909class NeighborReport(Packet): 

1910 name = "Neighbor Report" 

1911 fields_desc = [ 

1912 ByteField("type", 0), 

1913 ByteField("len", 13), 

1914 MACField("BSSID", ETHER_ANY), 

1915 # BSSID Information 

1916 BitField("AP_reach", 0, 2, tot_size=-4), 

1917 BitField("security", 0, 1), 

1918 BitField("key_scope", 0, 1), 

1919 BitField("capabilities", 0, 6), 

1920 BitField("mobility", 0, 1), 

1921 BitField("HT", 0, 1), 

1922 BitField("VHT", 0, 1), 

1923 BitField("FTM", 0, 1), 

1924 BitField("reserved", 0, 18, end_tot_size=-4), 

1925 # BSSID Information end 

1926 ByteField("op_class", 0), 

1927 ByteField("channel", 0), 

1928 ByteField("phy_type", 0), 

1929 ConditionalField( 

1930 PacketListField( 

1931 "subelems", 

1932 SubelemTLV(), 

1933 SubelemTLV, 

1934 length_from=lambda p: p.len - 13 

1935 ), 

1936 lambda p: p.len > 13 

1937 ) 

1938 ] 

1939 

1940 

1941# 802.11-2016 9.6.14.9 

1942 

1943btm_request_mode = [ 

1944 "Preferred_Candidate_List_Included", 

1945 "Abridged", 

1946 "Disassociation_Imminent", 

1947 "BSS_Termination_Included", 

1948 "ESS_Disassociation_Imminent" 

1949] 

1950 

1951 

1952class Dot11BSSTMRequest(Packet): 

1953 name = "BSS Transition Management Request" 

1954 fields_desc = [ 

1955 ByteField("token", 0), 

1956 FlagsField("mode", 0, 8, btm_request_mode), 

1957 LEShortField("disassociation_timer", 0), 

1958 ByteField("validity_interval", 0), 

1959 ConditionalField( 

1960 PacketField( 

1961 "termination_duration", 

1962 BSSTerminationDuration(), 

1963 BSSTerminationDuration 

1964 ), 

1965 lambda p: p.mode and p.mode.BSS_Termination_Included 

1966 ), 

1967 ConditionalField( 

1968 ByteField("url_len", 0), 

1969 lambda p: p.mode and p.mode.ESS_Disassociation_Imminent 

1970 ), 

1971 ConditionalField( 

1972 StrLenField("url", "", length_from=lambda p: p.url_len), 

1973 lambda p: p.mode and p.mode.ESS_Disassociation_Imminent != 0 

1974 ), 

1975 ConditionalField( 

1976 PacketListField( 

1977 "neighbor_report", 

1978 NeighborReport(), 

1979 NeighborReport 

1980 ), 

1981 lambda p: p.mode and p.mode.Preferred_Candidate_List_Included 

1982 ) 

1983 ] 

1984 

1985 

1986# 802.11-2016 9.6.14.10 

1987 

1988btm_status_code = [ 

1989 "Accept", 

1990 "Reject-Unspecified_reject_reason", 

1991 "Reject-Insufficient_Beacon_or_Probe_Response_frames", 

1992 "Reject-Insufficient_available_capacity_from_all_candidates", 

1993 "Reject-BSS_termination_undesired", 

1994 "Reject-BSS_termination_delay_requested", 

1995 "Reject-STA_BSS_Transition_Candidate_List_provided", 

1996 "Reject-No_suitable_BSS_transition_candidates", 

1997 "Reject-Leaving_ESS" 

1998] 

1999 

2000 

2001class Dot11BSSTMResponse(Packet): 

2002 name = "BSS Transition Management Response" 

2003 fields_desc = [ 

2004 ByteField("token", 0), 

2005 ByteEnumField("status", 0, btm_status_code), 

2006 ByteField("termination_delay", 0), 

2007 ConditionalField( 

2008 MACField("target", ETHER_ANY), 

2009 lambda p: p.status == 0 

2010 ), 

2011 ConditionalField( 

2012 PacketListField( 

2013 "neighbor_report", 

2014 NeighborReport(), 

2015 NeighborReport 

2016 ), 

2017 lambda p: p.status == 6 

2018 ) 

2019 ] 

2020 

2021 

2022# 802.11-2016 9.6.2.1 

2023 

2024class Dot11SpectrumManagement(Packet): 

2025 name = "802.11 Spectrum Management Action" 

2026 fields_desc = [ 

2027 ByteEnumField("action", 0x00, { 

2028 0x00: "Measurement Request", 

2029 0x01: "Measurement Report", 

2030 0x02: "TPC Request", 

2031 0x03: "TPC Report", 

2032 0x04: "Channel Switch Announcement", 

2033 }) 

2034 ] 

2035 

2036 

2037# 802.11-2016 9.6.2.6 

2038 

2039class Dot11CSA(Packet): 

2040 name = "Channel Switch Announcement Frame" 

2041 fields_desc = [ 

2042 PacketField("CSA", Dot11EltCSA(), Dot11EltCSA), 

2043 ] 

2044 

2045 

2046# 802.11-2020 9.4.2.20, 9.4.2.21 

2047_dot11_measurement_type = { 

2048 5: "Beacon", 

2049} 

2050 

2051 

2052# 802.11-2020 9.6.6.1 

2053 

2054class Dot11RadioMeasurement(Packet): 

2055 name = "802.11 Radio Measurement Action" 

2056 fields_desc = [ 

2057 ByteEnumField("action", 0x00, { 

2058 0x00: "Radio Measurement Request", 

2059 0x01: "Radio Measurement Report", 

2060 0x02: "Link Measurement Request", 

2061 0x03: "Link Measurement Report", 

2062 0x04: "Neighbor Report Request", 

2063 0x05: "Neighbor Report Response", 

2064 }) 

2065 ] 

2066 

2067 

2068# 802.11-2020 9.4.2.20.7 

2069 

2070class Dot11RadioMeasurementBeaconRequest(Packet): 

2071 name = "802.11 Radio Measurement Beacon Request" 

2072 fields_desc = [ 

2073 ByteField("op_class", 0), 

2074 ByteField("channel", 0), 

2075 LEShortField("randomization_interval", 0), 

2076 LEShortField("measurement_duration", 0), 

2077 ByteField("measurement_mode", 0), 

2078 MACField("BSSID", ETHER_ANY), 

2079 ] 

2080 

2081 def extract_padding(self, s): 

2082 return b"", s 

2083 

2084 

2085# 802.11-2020 9.6.6.2, 9.4.2.20 

2086 

2087class Dot11RadioMeasurementRequest(Packet): 

2088 name = "802.11 Radio Measurement Request" 

2089 fields_desc = [ 

2090 ByteField("token", 0), 

2091 LEShortField("repetitions", 0), 

2092 ByteEnumField("ID", 38, _dot11_id_enum), 

2093 ByteField("len", 16), 

2094 ByteField("measurement_token", 0), 

2095 # Measurement Request Mode 

2096 BitField("reserved", 0, 3), 

2097 BitField("duration_mandatory", 0, 1), 

2098 BitField("report", 0, 1), 

2099 BitField("request", 0, 1), 

2100 BitField("enable", 0, 1), 

2101 BitField("parallel", 0, 1), 

2102 ByteEnumField("measurement_request_type", 5, 

2103 _dot11_measurement_type), 

2104 # Only Beacon requests are specialized for now. Other measurement 

2105 # request types stay raw instead of being mis-dissected. 

2106 ConditionalField( 

2107 PacketField( 

2108 "measurement_request", 

2109 Dot11RadioMeasurementBeaconRequest(), 

2110 Dot11RadioMeasurementBeaconRequest 

2111 ), 

2112 lambda p: p.measurement_request_type == 5 

2113 ), 

2114 ConditionalField( 

2115 StrLenField( 

2116 "measurement_request_data", 

2117 b"", 

2118 length_from=lambda p: max(p.len - 3, 0) 

2119 ), 

2120 lambda p: p.measurement_request_type != 5 

2121 ), 

2122 ConditionalField( 

2123 PacketListField( 

2124 "subelems", 

2125 [], 

2126 SubelemTLV, 

2127 length_from=lambda p: max(p.len - 16, 0) 

2128 ), 

2129 lambda p: p.measurement_request_type == 5 and p.len > 16 

2130 ) 

2131 ] 

2132 

2133 

2134# 802.11-2020 9.4.2.21.7 

2135 

2136class Dot11RadioMeasurementBeaconReport(Packet): 

2137 name = "802.11 Radio Measurement Beacon Report" 

2138 fields_desc = [ 

2139 ByteField("op_class", 0), 

2140 ByteField("channel", 0), 

2141 LELongField("measurement_start_time", 0), 

2142 LEShortField("measurement_duration", 0), 

2143 # Reported Frame Information 

2144 BitField("reported_frame_type", 0, 1), 

2145 BitField("condensed_phy", 0, 7), 

2146 ByteField("RCPI", 0), 

2147 ByteField("RSNI", 0), 

2148 MACField("BSSID", ETHER_ANY), 

2149 ByteField("antenna_id", 0), 

2150 LEIntField("parent_tsf", 0), 

2151 ] 

2152 

2153 def extract_padding(self, s): 

2154 return b"", s 

2155 

2156 

2157# 802.11-2020 9.6.6.3, 9.4.2.21 

2158 

2159class Dot11RadioMeasurementReport(Packet): 

2160 name = "802.11 Radio Measurement Report" 

2161 fields_desc = [ 

2162 ByteField("token", 0), 

2163 ByteEnumField("ID", 39, _dot11_id_enum), 

2164 ByteField("len", 29), 

2165 ByteField("measurement_token", 0), 

2166 # Measurement Report Mode 

2167 BitField("reserved", 0, 5), 

2168 BitField("refused", 0, 1), 

2169 BitField("incapable", 0, 1), 

2170 BitField("late", 0, 1), 

2171 ByteEnumField("measurement_report_type", 5, 

2172 _dot11_measurement_type), 

2173 # Only successful Beacon reports are specialized for now. Other or 

2174 # unsuccessful measurement report bodies stay raw. 

2175 ConditionalField( 

2176 PacketField( 

2177 "measurement_report", 

2178 Dot11RadioMeasurementBeaconReport(), 

2179 Dot11RadioMeasurementBeaconReport 

2180 ), 

2181 lambda p: ( 

2182 p.measurement_report_type == 5 and 

2183 p.late == 0 and 

2184 p.incapable == 0 and 

2185 p.refused == 0 

2186 ) 

2187 ), 

2188 ConditionalField( 

2189 StrLenField( 

2190 "measurement_report_data", 

2191 b"", 

2192 length_from=lambda p: max(p.len - 3, 0) 

2193 ), 

2194 lambda p: ( 

2195 not ( 

2196 p.measurement_report_type == 5 and 

2197 p.late == 0 and 

2198 p.incapable == 0 and 

2199 p.refused == 0 

2200 ) 

2201 ) 

2202 ), 

2203 ConditionalField( 

2204 PacketListField( 

2205 "subelems", 

2206 [], 

2207 SubelemTLV, 

2208 length_from=lambda p: max(p.len - 29, 0) 

2209 ), 

2210 lambda p: ( 

2211 p.measurement_report_type == 5 and 

2212 p.late == 0 and 

2213 p.incapable == 0 and 

2214 p.refused == 0 and 

2215 p.len > 29 

2216 ) 

2217 ) 

2218 ] 

2219 

2220 

2221class Dot11S1GBeacon(_Dot11EltUtils): 

2222 name = "802.11 S1G Beacon" 

2223 fields_desc = [LEIntField("timestamp", 0), 

2224 ByteField("change_seq", 0)] 

2225 

2226 

2227################### 

2228# 802.11 Security # 

2229################### 

2230 

2231# 802.11-2016 12 

2232 

2233class Dot11Encrypted(Packet): 

2234 name = "802.11 Encrypted (unknown algorithm)" 

2235 fields_desc = [StrField("data", None)] 

2236 

2237 @classmethod 

2238 def dispatch_hook(cls, _pkt=None, *args, **kargs): 

2239 # Extracted from 

2240 # https://github.com/wireshark/wireshark/blob/master/epan/dissectors/packet-ieee80211.c # noqa: E501 

2241 KEY_EXTIV = 0x20 

2242 EXTIV_LEN = 8 

2243 if _pkt and len(_pkt) >= 3: 

2244 if (orb(_pkt[3]) & KEY_EXTIV) and (len(_pkt) >= EXTIV_LEN): 

2245 if orb(_pkt[1]) == ((orb(_pkt[0]) | 0x20) & 0x7f): # IS_TKIP 

2246 return Dot11TKIP 

2247 elif orb(_pkt[2]) == 0: # IS_CCMP 

2248 return Dot11CCMP 

2249 else: 

2250 # Unknown encryption algorithm 

2251 return Dot11Encrypted 

2252 else: 

2253 return Dot11WEP 

2254 return conf.raw_layer 

2255 

2256 

2257# 802.11-2016 12.3.2 

2258 

2259class Dot11WEP(Dot11Encrypted): 

2260 name = "802.11 WEP packet" 

2261 fields_desc = [StrFixedLenField("iv", b"\0\0\0", 3), 

2262 ByteField("keyid", 0), 

2263 StrField("wepdata", None, remain=4), 

2264 IntField("icv", None)] 

2265 

2266 def decrypt(self, key=None): 

2267 if key is None: 

2268 key = conf.wepkey 

2269 if key and conf.crypto_valid: 

2270 d = Cipher( 

2271 decrepit_algorithms.ARC4(self.iv + key.encode("utf8")), 

2272 None, 

2273 default_backend(), 

2274 ).decryptor() 

2275 self.add_payload(LLC(d.update(self.wepdata) + d.finalize())) 

2276 

2277 def post_dissect(self, s): 

2278 self.decrypt() 

2279 

2280 def build_payload(self): 

2281 if self.wepdata is None: 

2282 return Packet.build_payload(self) 

2283 return b"" 

2284 

2285 @crypto_validator 

2286 def encrypt(self, p, pay, key=None): 

2287 if key is None: 

2288 key = conf.wepkey 

2289 if key: 

2290 if self.icv is None: 

2291 pay += struct.pack("<I", crc32(pay) & 0xffffffff) 

2292 icv = b"" 

2293 else: 

2294 icv = p[4:8] 

2295 e = Cipher( 

2296 decrepit_algorithms.ARC4(self.iv + key.encode("utf8")), 

2297 None, 

2298 default_backend(), 

2299 ).encryptor() 

2300 return p[:4] + e.update(pay) + e.finalize() + icv 

2301 else: 

2302 warning("No WEP key set (conf.wepkey).. strange results expected..") # noqa: E501 

2303 return b"" 

2304 

2305 def post_build(self, p, pay): 

2306 if self.wepdata is None: 

2307 p = self.encrypt(p, raw(pay)) 

2308 return p 

2309 

2310# we can't dissect ICV / MIC here: they are encrypted 

2311 

2312# 802.11-2016 12.5.2.2 

2313 

2314 

2315class Dot11TKIP(Dot11Encrypted): 

2316 name = "802.11 TKIP packet" 

2317 fields_desc = [ 

2318 # iv - 4 bytes 

2319 ByteField("TSC1", 0), 

2320 ByteField("WEPSeed", 0), 

2321 ByteField("TSC0", 0), 

2322 BitField("key_id", 0, 2), # 

2323 BitField("ext_iv", 0, 1), # => LE = reversed order 

2324 BitField("res", 0, 5), # 

2325 # ext_iv - 4 bytes 

2326 ConditionalField(ByteField("TSC2", 0), lambda pkt: pkt.ext_iv), 

2327 ConditionalField(ByteField("TSC3", 0), lambda pkt: pkt.ext_iv), 

2328 ConditionalField(ByteField("TSC4", 0), lambda pkt: pkt.ext_iv), 

2329 ConditionalField(ByteField("TSC5", 0), lambda pkt: pkt.ext_iv), 

2330 # data 

2331 StrField("data", None), 

2332 ] 

2333 

2334# 802.11-2016 12.5.3.2 

2335 

2336 

2337class Dot11CCMP(Dot11Encrypted): 

2338 name = "802.11 CCMP packet" 

2339 fields_desc = [ 

2340 # iv - 8 bytes 

2341 ByteField("PN0", 0), 

2342 ByteField("PN1", 0), 

2343 ByteField("res0", 0), 

2344 BitField("key_id", 0, 2), # 

2345 BitField("ext_iv", 0, 1), # => LE = reversed order 

2346 BitField("res1", 0, 5), # 

2347 ByteField("PN2", 0), 

2348 ByteField("PN3", 0), 

2349 ByteField("PN4", 0), 

2350 ByteField("PN5", 0), 

2351 # data 

2352 StrField("data", None), 

2353 ] 

2354 

2355 

2356############ 

2357# Bindings # 

2358############ 

2359 

2360 

2361bind_top_down(RadioTap, Dot11FCS, present=2, Flags=16) 

2362bind_top_down(Dot11, Dot11QoS, type=2, subtype=0xc) 

2363 

2364bind_layers(PrismHeader, Dot11,) 

2365bind_layers(Dot11, LLC, type=2) 

2366bind_layers(Dot11QoS, LLC,) 

2367 

2368# 802.11-2016 9.2.4.1.3 Type and Subtype subfields 

2369bind_layers(Dot11, Dot11AssoReq, subtype=0, type=0) 

2370bind_layers(Dot11, Dot11AssoResp, subtype=1, type=0) 

2371bind_layers(Dot11, Dot11ReassoReq, subtype=2, type=0) 

2372bind_layers(Dot11, Dot11ReassoResp, subtype=3, type=0) 

2373bind_layers(Dot11, Dot11ProbeReq, subtype=4, type=0) 

2374bind_layers(Dot11, Dot11ProbeResp, subtype=5, type=0) 

2375bind_layers(Dot11, Dot11Beacon, subtype=8, type=0) 

2376bind_layers(Dot11, Dot11S1GBeacon, subtype=1, type=3) 

2377bind_layers(Dot11, Dot11ATIM, subtype=9, type=0) 

2378bind_layers(Dot11, Dot11Disas, subtype=10, type=0) 

2379bind_layers(Dot11, Dot11Auth, subtype=11, type=0) 

2380bind_layers(Dot11, Dot11Deauth, subtype=12, type=0) 

2381bind_layers(Dot11, Dot11Action, subtype=13, type=0) 

2382bind_layers(Dot11, Dot11Ack, subtype=13, type=1) 

2383bind_layers(Dot11Beacon, Dot11Elt,) 

2384bind_layers(Dot11S1GBeacon, Dot11Elt,) 

2385bind_layers(Dot11AssoReq, Dot11Elt,) 

2386bind_layers(Dot11AssoResp, Dot11Elt,) 

2387bind_layers(Dot11ReassoReq, Dot11Elt,) 

2388bind_layers(Dot11ReassoResp, Dot11Elt,) 

2389bind_layers(Dot11ProbeReq, Dot11Elt,) 

2390bind_layers(Dot11ProbeResp, Dot11Elt,) 

2391bind_layers(Dot11Auth, Dot11Elt,) 

2392bind_layers(Dot11Elt, Dot11Elt,) 

2393bind_layers(Dot11TKIP, conf.raw_layer) 

2394bind_layers(Dot11CCMP, conf.raw_layer) 

2395bind_layers(Dot11Action, Dot11SpectrumManagement, category=0x00) 

2396bind_layers(Dot11SpectrumManagement, Dot11CSA, action=4) 

2397bind_layers(Dot11Action, Dot11WNM, category=0x0A) 

2398bind_layers(Dot11WNM, Dot11BSSTMRequest, action=7) 

2399bind_layers(Dot11WNM, Dot11BSSTMResponse, action=8) 

2400bind_layers(Dot11Action, Dot11RadioMeasurement, category=0x05) 

2401bind_layers(Dot11RadioMeasurement, Dot11RadioMeasurementRequest, action=0) 

2402bind_layers(Dot11RadioMeasurement, Dot11RadioMeasurementReport, action=1) 

2403 

2404 

2405conf.l2types.register(DLT_IEEE802_11, Dot11) 

2406conf.l2types.register_num2layer(801, Dot11) 

2407conf.l2types.register(DLT_PRISM_HEADER, PrismHeader) 

2408conf.l2types.register_num2layer(802, PrismHeader) 

2409conf.l2types.register(DLT_IEEE802_11_RADIO, RadioTap) 

2410conf.l2types.register_num2layer(803, RadioTap) 

2411 

2412#################### 

2413# Other WiFi utils # 

2414#################### 

2415 

2416 

2417class WiFi_am(AnsweringMachine): 

2418 """Before using this, initialize "iffrom" and "ifto" interfaces: 

2419iwconfig iffrom mode monitor 

2420iwpriv orig_ifto hostapd 1 

2421ifconfig ifto up 

2422note: if ifto=wlan0ap then orig_ifto=wlan0 

2423note: ifto and iffrom must be set on the same channel 

2424ex: 

2425ifconfig eth1 up 

2426iwconfig eth1 mode monitor 

2427iwconfig eth1 channel 11 

2428iwpriv wlan0 hostapd 1 

2429ifconfig wlan0ap up 

2430iwconfig wlan0 channel 11 

2431iwconfig wlan0 essid dontexist 

2432iwconfig wlan0 mode managed 

2433""" 

2434 function_name = "airpwn" 

2435 filter = None 

2436 

2437 def parse_options(self, iffrom=conf.iface, ifto=conf.iface, replace="", 

2438 pattern="", ignorepattern=""): 

2439 self.iffrom = iffrom 

2440 self.ifto = ifto 

2441 self.ptrn = re.compile(pattern.encode()) 

2442 self.iptrn = re.compile(ignorepattern.encode()) 

2443 self.replace = replace 

2444 

2445 def is_request(self, pkt): 

2446 if not isinstance(pkt, Dot11): 

2447 return 0 

2448 if not pkt.FCfield & 1: 

2449 return 0 

2450 if not pkt.haslayer(TCP): 

2451 return 0 

2452 tcp = pkt.getlayer(TCP) 

2453 pay = raw(tcp.payload) 

2454 if not self.ptrn.match(pay): 

2455 return 0 

2456 if self.iptrn.match(pay) is True: 

2457 return 0 

2458 return True 

2459 

2460 def make_reply(self, p): 

2461 ip = p.getlayer(IP) 

2462 tcp = p.getlayer(TCP) 

2463 pay = raw(tcp.payload) 

2464 p[IP].underlayer.remove_payload() 

2465 p.FCfield = "from_DS" 

2466 p.addr1, p.addr2 = p.addr2, p.addr1 

2467 p /= IP(src=ip.dst, dst=ip.src) 

2468 p /= TCP(sport=tcp.dport, dport=tcp.sport, 

2469 seq=tcp.ack, ack=tcp.seq + len(pay), 

2470 flags="PA") 

2471 q = p.copy() 

2472 p /= self.replace 

2473 q.ID += 1 

2474 q.getlayer(TCP).flags = "RA" 

2475 q.getlayer(TCP).seq += len(self.replace) 

2476 return [p, q] 

2477 

2478 def print_reply(self, query, *reply): 

2479 p = reply[0][0] 

2480 print(p.sprintf("Sent %IP.src%:%IP.sport% > %IP.dst%:%TCP.dport%")) 

2481 

2482 def send_reply(self, reply): 

2483 sendp(reply, iface=self.ifto, **self.optsend) 

2484 

2485 def sniff(self): 

2486 sniff(iface=self.iffrom, **self.optsniff) 

2487 

2488 

2489conf.stats_dot11_protocols += [Dot11WEP, Dot11Beacon, ] 

2490 

2491 

2492class Dot11PacketList(PacketList): 

2493 def __init__(self, res=None, name="Dot11List", stats=None): 

2494 if stats is None: 

2495 stats = conf.stats_dot11_protocols 

2496 

2497 PacketList.__init__(self, res, name, stats) 

2498 

2499 def toEthernet(self): 

2500 data = [x[Dot11] for x in self.res if Dot11 in x and x.type == 2] 

2501 r2 = [] 

2502 for p in data: 

2503 q = p.copy() 

2504 q.unwep() 

2505 r2.append(Ether() / q.payload.payload.payload) # Dot11/LLC/SNAP/IP 

2506 return PacketList(r2, name="Ether from %s" % self.listname)