1// Copyright 2014 Google, Inc. All rights reserved. 2// 3// Use of this source code is governed by a BSD-style license 4// that can be found in the LICENSE file in the root of the source 5// tree. 6 7package layers 8 9import ( 10 "bytes" 11 "encoding/binary" 12 "fmt" 13 "hash/crc32" 14 "strings" 15 16 "github.com/google/gopacket" 17) 18 19// align calculates the number of bytes needed to align with the width 20// on the offset, returning the number of bytes we need to skip to 21// align to the offset (width). 22func align(offset uint16, width uint16) uint16 { 23 return ((((offset) + ((width) - 1)) & (^((width) - 1))) - offset) 24} 25 26type RadioTapPresent uint32 27 28const ( 29 RadioTapPresentTSFT RadioTapPresent = 1 << iota 30 RadioTapPresentFlags 31 RadioTapPresentRate 32 RadioTapPresentChannel 33 RadioTapPresentFHSS 34 RadioTapPresentDBMAntennaSignal 35 RadioTapPresentDBMAntennaNoise 36 RadioTapPresentLockQuality 37 RadioTapPresentTxAttenuation 38 RadioTapPresentDBTxAttenuation 39 RadioTapPresentDBMTxPower 40 RadioTapPresentAntenna 41 RadioTapPresentDBAntennaSignal 42 RadioTapPresentDBAntennaNoise 43 RadioTapPresentRxFlags 44 RadioTapPresentTxFlags 45 RadioTapPresentRtsRetries 46 RadioTapPresentDataRetries 47 _ 48 RadioTapPresentMCS 49 RadioTapPresentAMPDUStatus 50 RadioTapPresentVHT 51 RadioTapPresentEXT RadioTapPresent = 1 << 31 52) 53 54func (r RadioTapPresent) TSFT() bool { 55 return r&RadioTapPresentTSFT != 0 56} 57func (r RadioTapPresent) Flags() bool { 58 return r&RadioTapPresentFlags != 0 59} 60func (r RadioTapPresent) Rate() bool { 61 return r&RadioTapPresentRate != 0 62} 63func (r RadioTapPresent) Channel() bool { 64 return r&RadioTapPresentChannel != 0 65} 66func (r RadioTapPresent) FHSS() bool { 67 return r&RadioTapPresentFHSS != 0 68} 69func (r RadioTapPresent) DBMAntennaSignal() bool { 70 return r&RadioTapPresentDBMAntennaSignal != 0 71} 72func (r RadioTapPresent) DBMAntennaNoise() bool { 73 return r&RadioTapPresentDBMAntennaNoise != 0 74} 75func (r RadioTapPresent) LockQuality() bool { 76 return r&RadioTapPresentLockQuality != 0 77} 78func (r RadioTapPresent) TxAttenuation() bool { 79 return r&RadioTapPresentTxAttenuation != 0 80} 81func (r RadioTapPresent) DBTxAttenuation() bool { 82 return r&RadioTapPresentDBTxAttenuation != 0 83} 84func (r RadioTapPresent) DBMTxPower() bool { 85 return r&RadioTapPresentDBMTxPower != 0 86} 87func (r RadioTapPresent) Antenna() bool { 88 return r&RadioTapPresentAntenna != 0 89} 90func (r RadioTapPresent) DBAntennaSignal() bool { 91 return r&RadioTapPresentDBAntennaSignal != 0 92} 93func (r RadioTapPresent) DBAntennaNoise() bool { 94 return r&RadioTapPresentDBAntennaNoise != 0 95} 96func (r RadioTapPresent) RxFlags() bool { 97 return r&RadioTapPresentRxFlags != 0 98} 99func (r RadioTapPresent) TxFlags() bool { 100 return r&RadioTapPresentTxFlags != 0 101} 102func (r RadioTapPresent) RtsRetries() bool { 103 return r&RadioTapPresentRtsRetries != 0 104} 105func (r RadioTapPresent) DataRetries() bool { 106 return r&RadioTapPresentDataRetries != 0 107} 108func (r RadioTapPresent) MCS() bool { 109 return r&RadioTapPresentMCS != 0 110} 111func (r RadioTapPresent) AMPDUStatus() bool { 112 return r&RadioTapPresentAMPDUStatus != 0 113} 114func (r RadioTapPresent) VHT() bool { 115 return r&RadioTapPresentVHT != 0 116} 117func (r RadioTapPresent) EXT() bool { 118 return r&RadioTapPresentEXT != 0 119} 120 121type RadioTapChannelFlags uint16 122 123const ( 124 RadioTapChannelFlagsTurbo RadioTapChannelFlags = 0x0010 // Turbo channel 125 RadioTapChannelFlagsCCK RadioTapChannelFlags = 0x0020 // CCK channel 126 RadioTapChannelFlagsOFDM RadioTapChannelFlags = 0x0040 // OFDM channel 127 RadioTapChannelFlagsGhz2 RadioTapChannelFlags = 0x0080 // 2 GHz spectrum channel. 128 RadioTapChannelFlagsGhz5 RadioTapChannelFlags = 0x0100 // 5 GHz spectrum channel 129 RadioTapChannelFlagsPassive RadioTapChannelFlags = 0x0200 // Only passive scan allowed 130 RadioTapChannelFlagsDynamic RadioTapChannelFlags = 0x0400 // Dynamic CCK-OFDM channel 131 RadioTapChannelFlagsGFSK RadioTapChannelFlags = 0x0800 // GFSK channel (FHSS PHY) 132) 133 134func (r RadioTapChannelFlags) Turbo() bool { 135 return r&RadioTapChannelFlagsTurbo != 0 136} 137func (r RadioTapChannelFlags) CCK() bool { 138 return r&RadioTapChannelFlagsCCK != 0 139} 140func (r RadioTapChannelFlags) OFDM() bool { 141 return r&RadioTapChannelFlagsOFDM != 0 142} 143func (r RadioTapChannelFlags) Ghz2() bool { 144 return r&RadioTapChannelFlagsGhz2 != 0 145} 146func (r RadioTapChannelFlags) Ghz5() bool { 147 return r&RadioTapChannelFlagsGhz5 != 0 148} 149func (r RadioTapChannelFlags) Passive() bool { 150 return r&RadioTapChannelFlagsPassive != 0 151} 152func (r RadioTapChannelFlags) Dynamic() bool { 153 return r&RadioTapChannelFlagsDynamic != 0 154} 155func (r RadioTapChannelFlags) GFSK() bool { 156 return r&RadioTapChannelFlagsGFSK != 0 157} 158 159// String provides a human readable string for RadioTapChannelFlags. 160// This string is possibly subject to change over time; if you're storing this 161// persistently, you should probably store the RadioTapChannelFlags value, not its string. 162func (a RadioTapChannelFlags) String() string { 163 var out bytes.Buffer 164 if a.Turbo() { 165 out.WriteString("Turbo,") 166 } 167 if a.CCK() { 168 out.WriteString("CCK,") 169 } 170 if a.OFDM() { 171 out.WriteString("OFDM,") 172 } 173 if a.Ghz2() { 174 out.WriteString("Ghz2,") 175 } 176 if a.Ghz5() { 177 out.WriteString("Ghz5,") 178 } 179 if a.Passive() { 180 out.WriteString("Passive,") 181 } 182 if a.Dynamic() { 183 out.WriteString("Dynamic,") 184 } 185 if a.GFSK() { 186 out.WriteString("GFSK,") 187 } 188 189 if length := out.Len(); length > 0 { 190 return string(out.Bytes()[:length-1]) // strip final comma 191 } 192 return "" 193} 194 195type RadioTapFlags uint8 196 197const ( 198 RadioTapFlagsCFP RadioTapFlags = 1 << iota // sent/received during CFP 199 RadioTapFlagsShortPreamble // sent/received * with short * preamble 200 RadioTapFlagsWEP // sent/received * with WEP encryption 201 RadioTapFlagsFrag // sent/received * with fragmentation 202 RadioTapFlagsFCS // frame includes FCS 203 RadioTapFlagsDatapad // frame has padding between * 802.11 header and payload * (to 32-bit boundary) 204 RadioTapFlagsBadFCS // does not pass FCS check 205 RadioTapFlagsShortGI // HT short GI 206) 207 208func (r RadioTapFlags) CFP() bool { 209 return r&RadioTapFlagsCFP != 0 210} 211func (r RadioTapFlags) ShortPreamble() bool { 212 return r&RadioTapFlagsShortPreamble != 0 213} 214func (r RadioTapFlags) WEP() bool { 215 return r&RadioTapFlagsWEP != 0 216} 217func (r RadioTapFlags) Frag() bool { 218 return r&RadioTapFlagsFrag != 0 219} 220func (r RadioTapFlags) FCS() bool { 221 return r&RadioTapFlagsFCS != 0 222} 223func (r RadioTapFlags) Datapad() bool { 224 return r&RadioTapFlagsDatapad != 0 225} 226func (r RadioTapFlags) BadFCS() bool { 227 return r&RadioTapFlagsBadFCS != 0 228} 229func (r RadioTapFlags) ShortGI() bool { 230 return r&RadioTapFlagsShortGI != 0 231} 232 233// String provides a human readable string for RadioTapFlags. 234// This string is possibly subject to change over time; if you're storing this 235// persistently, you should probably store the RadioTapFlags value, not its string. 236func (a RadioTapFlags) String() string { 237 var out bytes.Buffer 238 if a.CFP() { 239 out.WriteString("CFP,") 240 } 241 if a.ShortPreamble() { 242 out.WriteString("SHORT-PREAMBLE,") 243 } 244 if a.WEP() { 245 out.WriteString("WEP,") 246 } 247 if a.Frag() { 248 out.WriteString("FRAG,") 249 } 250 if a.FCS() { 251 out.WriteString("FCS,") 252 } 253 if a.Datapad() { 254 out.WriteString("DATAPAD,") 255 } 256 if a.ShortGI() { 257 out.WriteString("SHORT-GI,") 258 } 259 260 if length := out.Len(); length > 0 { 261 return string(out.Bytes()[:length-1]) // strip final comma 262 } 263 return "" 264} 265 266type RadioTapRate uint8 267 268func (a RadioTapRate) String() string { 269 return fmt.Sprintf("%v Mb/s", 0.5*float32(a)) 270} 271 272type RadioTapChannelFrequency uint16 273 274func (a RadioTapChannelFrequency) String() string { 275 return fmt.Sprintf("%d MHz", a) 276} 277 278type RadioTapRxFlags uint16 279 280const ( 281 RadioTapRxFlagsBadPlcp RadioTapRxFlags = 0x0002 282) 283 284func (self RadioTapRxFlags) BadPlcp() bool { 285 return self&RadioTapRxFlagsBadPlcp != 0 286} 287 288func (self RadioTapRxFlags) String() string { 289 if self.BadPlcp() { 290 return "BADPLCP" 291 } 292 return "" 293} 294 295type RadioTapTxFlags uint16 296 297const ( 298 RadioTapTxFlagsFail RadioTapTxFlags = 1 << iota 299 RadioTapTxFlagsCTS 300 RadioTapTxFlagsRTS 301 RadioTapTxFlagsNoACK 302) 303 304func (self RadioTapTxFlags) Fail() bool { return self&RadioTapTxFlagsFail != 0 } 305func (self RadioTapTxFlags) CTS() bool { return self&RadioTapTxFlagsCTS != 0 } 306func (self RadioTapTxFlags) RTS() bool { return self&RadioTapTxFlagsRTS != 0 } 307func (self RadioTapTxFlags) NoACK() bool { return self&RadioTapTxFlagsNoACK != 0 } 308 309func (self RadioTapTxFlags) String() string { 310 var tokens []string 311 if self.Fail() { 312 tokens = append(tokens, "Fail") 313 } 314 if self.CTS() { 315 tokens = append(tokens, "CTS") 316 } 317 if self.RTS() { 318 tokens = append(tokens, "RTS") 319 } 320 if self.NoACK() { 321 tokens = append(tokens, "NoACK") 322 } 323 return strings.Join(tokens, ",") 324} 325 326type RadioTapMCS struct { 327 Known RadioTapMCSKnown 328 Flags RadioTapMCSFlags 329 MCS uint8 330} 331 332func (self RadioTapMCS) String() string { 333 var tokens []string 334 if self.Known.Bandwidth() { 335 token := "?" 336 switch self.Flags.Bandwidth() { 337 case 0: 338 token = "20" 339 case 1: 340 token = "40" 341 case 2: 342 token = "40(20L)" 343 case 3: 344 token = "40(20U)" 345 } 346 tokens = append(tokens, token) 347 } 348 if self.Known.MCSIndex() { 349 tokens = append(tokens, fmt.Sprintf("MCSIndex#%d", self.MCS)) 350 } 351 if self.Known.GuardInterval() { 352 if self.Flags.ShortGI() { 353 tokens = append(tokens, fmt.Sprintf("shortGI")) 354 } else { 355 tokens = append(tokens, fmt.Sprintf("longGI")) 356 } 357 } 358 if self.Known.HTFormat() { 359 if self.Flags.Greenfield() { 360 tokens = append(tokens, fmt.Sprintf("HT-greenfield")) 361 } else { 362 tokens = append(tokens, fmt.Sprintf("HT-mixed")) 363 } 364 } 365 if self.Known.FECType() { 366 if self.Flags.FECLDPC() { 367 tokens = append(tokens, fmt.Sprintf("LDPC")) 368 } else { 369 tokens = append(tokens, fmt.Sprintf("BCC")) 370 } 371 } 372 if self.Known.STBC() { 373 tokens = append(tokens, fmt.Sprintf("STBC#%d", self.Flags.STBC())) 374 } 375 if self.Known.NESS() { 376 num := 0 377 if self.Known.NESS1() { 378 num |= 0x02 379 } 380 if self.Flags.NESS0() { 381 num |= 0x01 382 } 383 tokens = append(tokens, fmt.Sprintf("num-of-ESS#%d", num)) 384 } 385 return strings.Join(tokens, ",") 386} 387 388type RadioTapMCSKnown uint8 389 390const ( 391 RadioTapMCSKnownBandwidth RadioTapMCSKnown = 1 << iota 392 RadioTapMCSKnownMCSIndex 393 RadioTapMCSKnownGuardInterval 394 RadioTapMCSKnownHTFormat 395 RadioTapMCSKnownFECType 396 RadioTapMCSKnownSTBC 397 RadioTapMCSKnownNESS 398 RadioTapMCSKnownNESS1 399) 400 401func (self RadioTapMCSKnown) Bandwidth() bool { return self&RadioTapMCSKnownBandwidth != 0 } 402func (self RadioTapMCSKnown) MCSIndex() bool { return self&RadioTapMCSKnownMCSIndex != 0 } 403func (self RadioTapMCSKnown) GuardInterval() bool { return self&RadioTapMCSKnownGuardInterval != 0 } 404func (self RadioTapMCSKnown) HTFormat() bool { return self&RadioTapMCSKnownHTFormat != 0 } 405func (self RadioTapMCSKnown) FECType() bool { return self&RadioTapMCSKnownFECType != 0 } 406func (self RadioTapMCSKnown) STBC() bool { return self&RadioTapMCSKnownSTBC != 0 } 407func (self RadioTapMCSKnown) NESS() bool { return self&RadioTapMCSKnownNESS != 0 } 408func (self RadioTapMCSKnown) NESS1() bool { return self&RadioTapMCSKnownNESS1 != 0 } 409 410type RadioTapMCSFlags uint8 411 412const ( 413 RadioTapMCSFlagsBandwidthMask RadioTapMCSFlags = 0x03 414 RadioTapMCSFlagsShortGI = 0x04 415 RadioTapMCSFlagsGreenfield = 0x08 416 RadioTapMCSFlagsFECLDPC = 0x10 417 RadioTapMCSFlagsSTBCMask = 0x60 418 RadioTapMCSFlagsNESS0 = 0x80 419) 420 421func (self RadioTapMCSFlags) Bandwidth() int { 422 return int(self & RadioTapMCSFlagsBandwidthMask) 423} 424func (self RadioTapMCSFlags) ShortGI() bool { return self&RadioTapMCSFlagsShortGI != 0 } 425func (self RadioTapMCSFlags) Greenfield() bool { return self&RadioTapMCSFlagsGreenfield != 0 } 426func (self RadioTapMCSFlags) FECLDPC() bool { return self&RadioTapMCSFlagsFECLDPC != 0 } 427func (self RadioTapMCSFlags) STBC() int { 428 return int(self&RadioTapMCSFlagsSTBCMask) >> 5 429} 430func (self RadioTapMCSFlags) NESS0() bool { return self&RadioTapMCSFlagsNESS0 != 0 } 431 432type RadioTapAMPDUStatus struct { 433 Reference uint32 434 Flags RadioTapAMPDUStatusFlags 435 CRC uint8 436} 437 438func (self RadioTapAMPDUStatus) String() string { 439 tokens := []string{ 440 fmt.Sprintf("ref#%x", self.Reference), 441 } 442 if self.Flags.ReportZerolen() && self.Flags.IsZerolen() { 443 tokens = append(tokens, fmt.Sprintf("zero-length")) 444 } 445 if self.Flags.LastKnown() && self.Flags.IsLast() { 446 tokens = append(tokens, "last") 447 } 448 if self.Flags.DelimCRCErr() { 449 tokens = append(tokens, "delimiter CRC error") 450 } 451 if self.Flags.DelimCRCKnown() { 452 tokens = append(tokens, fmt.Sprintf("delimiter-CRC=%02x", self.CRC)) 453 } 454 return strings.Join(tokens, ",") 455} 456 457type RadioTapAMPDUStatusFlags uint16 458 459const ( 460 RadioTapAMPDUStatusFlagsReportZerolen RadioTapAMPDUStatusFlags = 1 << iota 461 RadioTapAMPDUIsZerolen 462 RadioTapAMPDULastKnown 463 RadioTapAMPDUIsLast 464 RadioTapAMPDUDelimCRCErr 465 RadioTapAMPDUDelimCRCKnown 466) 467 468func (self RadioTapAMPDUStatusFlags) ReportZerolen() bool { 469 return self&RadioTapAMPDUStatusFlagsReportZerolen != 0 470} 471func (self RadioTapAMPDUStatusFlags) IsZerolen() bool { return self&RadioTapAMPDUIsZerolen != 0 } 472func (self RadioTapAMPDUStatusFlags) LastKnown() bool { return self&RadioTapAMPDULastKnown != 0 } 473func (self RadioTapAMPDUStatusFlags) IsLast() bool { return self&RadioTapAMPDUIsLast != 0 } 474func (self RadioTapAMPDUStatusFlags) DelimCRCErr() bool { return self&RadioTapAMPDUDelimCRCErr != 0 } 475func (self RadioTapAMPDUStatusFlags) DelimCRCKnown() bool { return self&RadioTapAMPDUDelimCRCKnown != 0 } 476 477type RadioTapVHT struct { 478 Known RadioTapVHTKnown 479 Flags RadioTapVHTFlags 480 Bandwidth uint8 481 MCSNSS [4]RadioTapVHTMCSNSS 482 Coding uint8 483 GroupId uint8 484 PartialAID uint16 485} 486 487func (self RadioTapVHT) String() string { 488 var tokens []string 489 if self.Known.STBC() { 490 if self.Flags.STBC() { 491 tokens = append(tokens, "STBC") 492 } else { 493 tokens = append(tokens, "no STBC") 494 } 495 } 496 if self.Known.TXOPPSNotAllowed() { 497 if self.Flags.TXOPPSNotAllowed() { 498 tokens = append(tokens, "TXOP doze not allowed") 499 } else { 500 tokens = append(tokens, "TXOP doze allowed") 501 } 502 } 503 if self.Known.GI() { 504 if self.Flags.SGI() { 505 tokens = append(tokens, "short GI") 506 } else { 507 tokens = append(tokens, "long GI") 508 } 509 } 510 if self.Known.SGINSYMDisambiguation() { 511 if self.Flags.SGINSYMMod() { 512 tokens = append(tokens, "NSYM mod 10=9") 513 } else { 514 tokens = append(tokens, "NSYM mod 10!=9 or no short GI") 515 } 516 } 517 if self.Known.LDPCExtraOFDMSymbol() { 518 if self.Flags.LDPCExtraOFDMSymbol() { 519 tokens = append(tokens, "LDPC extra OFDM symbols") 520 } else { 521 tokens = append(tokens, "no LDPC extra OFDM symbols") 522 } 523 } 524 if self.Known.Beamformed() { 525 if self.Flags.Beamformed() { 526 tokens = append(tokens, "beamformed") 527 } else { 528 tokens = append(tokens, "no beamformed") 529 } 530 } 531 if self.Known.Bandwidth() { 532 token := "?" 533 switch self.Bandwidth & 0x1f { 534 case 0: 535 token = "20" 536 case 1: 537 token = "40" 538 case 2: 539 token = "40(20L)" 540 case 3: 541 token = "40(20U)" 542 case 4: 543 token = "80" 544 case 5: 545 token = "80(40L)" 546 case 6: 547 token = "80(40U)" 548 case 7: 549 token = "80(20LL)" 550 case 8: 551 token = "80(20LU)" 552 case 9: 553 token = "80(20UL)" 554 case 10: 555 token = "80(20UU)" 556 case 11: 557 token = "160" 558 case 12: 559 token = "160(80L)" 560 case 13: 561 token = "160(80U)" 562 case 14: 563 token = "160(40LL)" 564 case 15: 565 token = "160(40LU)" 566 case 16: 567 token = "160(40UL)" 568 case 17: 569 token = "160(40UU)" 570 case 18: 571 token = "160(20LLL)" 572 case 19: 573 token = "160(20LLU)" 574 case 20: 575 token = "160(20LUL)" 576 case 21: 577 token = "160(20LUU)" 578 case 22: 579 token = "160(20ULL)" 580 case 23: 581 token = "160(20ULU)" 582 case 24: 583 token = "160(20UUL)" 584 case 25: 585 token = "160(20UUU)" 586 } 587 tokens = append(tokens, token) 588 } 589 for i, MCSNSS := range self.MCSNSS { 590 if MCSNSS.Present() { 591 fec := "?" 592 switch self.Coding & (1 << uint8(i)) { 593 case 0: 594 fec = "BCC" 595 case 1: 596 fec = "LDPC" 597 } 598 tokens = append(tokens, fmt.Sprintf("user%d(%s,%s)", i, MCSNSS.String(), fec)) 599 } 600 } 601 if self.Known.GroupId() { 602 tokens = append(tokens, 603 fmt.Sprintf("group=%d", self.GroupId)) 604 } 605 if self.Known.PartialAID() { 606 tokens = append(tokens, 607 fmt.Sprintf("partial-AID=%d", self.PartialAID)) 608 } 609 return strings.Join(tokens, ",") 610} 611 612type RadioTapVHTKnown uint16 613 614const ( 615 RadioTapVHTKnownSTBC RadioTapVHTKnown = 1 << iota 616 RadioTapVHTKnownTXOPPSNotAllowed 617 RadioTapVHTKnownGI 618 RadioTapVHTKnownSGINSYMDisambiguation 619 RadioTapVHTKnownLDPCExtraOFDMSymbol 620 RadioTapVHTKnownBeamformed 621 RadioTapVHTKnownBandwidth 622 RadioTapVHTKnownGroupId 623 RadioTapVHTKnownPartialAID 624) 625 626func (self RadioTapVHTKnown) STBC() bool { return self&RadioTapVHTKnownSTBC != 0 } 627func (self RadioTapVHTKnown) TXOPPSNotAllowed() bool { 628 return self&RadioTapVHTKnownTXOPPSNotAllowed != 0 629} 630func (self RadioTapVHTKnown) GI() bool { return self&RadioTapVHTKnownGI != 0 } 631func (self RadioTapVHTKnown) SGINSYMDisambiguation() bool { 632 return self&RadioTapVHTKnownSGINSYMDisambiguation != 0 633} 634func (self RadioTapVHTKnown) LDPCExtraOFDMSymbol() bool { 635 return self&RadioTapVHTKnownLDPCExtraOFDMSymbol != 0 636} 637func (self RadioTapVHTKnown) Beamformed() bool { return self&RadioTapVHTKnownBeamformed != 0 } 638func (self RadioTapVHTKnown) Bandwidth() bool { return self&RadioTapVHTKnownBandwidth != 0 } 639func (self RadioTapVHTKnown) GroupId() bool { return self&RadioTapVHTKnownGroupId != 0 } 640func (self RadioTapVHTKnown) PartialAID() bool { return self&RadioTapVHTKnownPartialAID != 0 } 641 642type RadioTapVHTFlags uint8 643 644const ( 645 RadioTapVHTFlagsSTBC RadioTapVHTFlags = 1 << iota 646 RadioTapVHTFlagsTXOPPSNotAllowed 647 RadioTapVHTFlagsSGI 648 RadioTapVHTFlagsSGINSYMMod 649 RadioTapVHTFlagsLDPCExtraOFDMSymbol 650 RadioTapVHTFlagsBeamformed 651) 652 653func (self RadioTapVHTFlags) STBC() bool { return self&RadioTapVHTFlagsSTBC != 0 } 654func (self RadioTapVHTFlags) TXOPPSNotAllowed() bool { 655 return self&RadioTapVHTFlagsTXOPPSNotAllowed != 0 656} 657func (self RadioTapVHTFlags) SGI() bool { return self&RadioTapVHTFlagsSGI != 0 } 658func (self RadioTapVHTFlags) SGINSYMMod() bool { return self&RadioTapVHTFlagsSGINSYMMod != 0 } 659func (self RadioTapVHTFlags) LDPCExtraOFDMSymbol() bool { 660 return self&RadioTapVHTFlagsLDPCExtraOFDMSymbol != 0 661} 662func (self RadioTapVHTFlags) Beamformed() bool { return self&RadioTapVHTFlagsBeamformed != 0 } 663 664type RadioTapVHTMCSNSS uint8 665 666func (self RadioTapVHTMCSNSS) Present() bool { 667 return self&0x0F != 0 668} 669 670func (self RadioTapVHTMCSNSS) String() string { 671 return fmt.Sprintf("NSS#%dMCS#%d", uint32(self&0xf), uint32(self>>4)) 672} 673 674func decodeRadioTap(data []byte, p gopacket.PacketBuilder) error { 675 d := &RadioTap{} 676 // TODO: Should we set LinkLayer here? And implement LinkFlow 677 return decodingLayerDecoder(d, data, p) 678} 679 680type RadioTap struct { 681 BaseLayer 682 683 // Version 0. Only increases for drastic changes, introduction of compatible new fields does not count. 684 Version uint8 685 // Length of the whole header in bytes, including it_version, it_pad, it_len, and data fields. 686 Length uint16 687 // Present is a bitmap telling which fields are present. Set bit 31 (0x80000000) to extend the bitmap by another 32 bits. Additional extensions are made by setting bit 31. 688 Present RadioTapPresent 689 // TSFT: value in microseconds of the MAC's 64-bit 802.11 Time Synchronization Function timer when the first bit of the MPDU arrived at the MAC. For received frames, only. 690 TSFT uint64 691 Flags RadioTapFlags 692 // Rate Tx/Rx data rate 693 Rate RadioTapRate 694 // ChannelFrequency Tx/Rx frequency in MHz, followed by flags 695 ChannelFrequency RadioTapChannelFrequency 696 ChannelFlags RadioTapChannelFlags 697 // FHSS For frequency-hopping radios, the hop set (first byte) and pattern (second byte). 698 FHSS uint16 699 // DBMAntennaSignal RF signal power at the antenna, decibel difference from one milliwatt. 700 DBMAntennaSignal int8 701 // DBMAntennaNoise RF noise power at the antenna, decibel difference from one milliwatt. 702 DBMAntennaNoise int8 703 // LockQuality Quality of Barker code lock. Unitless. Monotonically nondecreasing with "better" lock strength. Called "Signal Quality" in datasheets. 704 LockQuality uint16 705 // TxAttenuation Transmit power expressed as unitless distance from max power set at factory calibration. 0 is max power. Monotonically nondecreasing with lower power levels. 706 TxAttenuation uint16 707 // DBTxAttenuation Transmit power expressed as decibel distance from max power set at factory calibration. 0 is max power. Monotonically nondecreasing with lower power levels. 708 DBTxAttenuation uint16 709 // DBMTxPower Transmit power expressed as dBm (decibels from a 1 milliwatt reference). This is the absolute power level measured at the antenna port. 710 DBMTxPower int8 711 // Antenna Unitless indication of the Rx/Tx antenna for this packet. The first antenna is antenna 0. 712 Antenna uint8 713 // DBAntennaSignal RF signal power at the antenna, decibel difference from an arbitrary, fixed reference. 714 DBAntennaSignal uint8 715 // DBAntennaNoise RF noise power at the antenna, decibel difference from an arbitrary, fixed reference point. 716 DBAntennaNoise uint8 717 // 718 RxFlags RadioTapRxFlags 719 TxFlags RadioTapTxFlags 720 RtsRetries uint8 721 DataRetries uint8 722 MCS RadioTapMCS 723 AMPDUStatus RadioTapAMPDUStatus 724 VHT RadioTapVHT 725} 726 727func (m *RadioTap) LayerType() gopacket.LayerType { return LayerTypeRadioTap } 728 729func (m *RadioTap) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error { 730 m.Version = uint8(data[0]) 731 m.Length = binary.LittleEndian.Uint16(data[2:4]) 732 m.Present = RadioTapPresent(binary.LittleEndian.Uint32(data[4:8])) 733 734 offset := uint16(4) 735 736 for (binary.LittleEndian.Uint32(data[offset:offset+4]) & 0x80000000) != 0 { 737 // This parser only handles standard radiotap namespace, 738 // and expects all fields are packed in the first it_present. 739 // Extended bitmap will be just ignored. 740 offset += 4 741 } 742 offset += 4 // skip the bitmap 743 744 if m.Present.TSFT() { 745 offset += align(offset, 8) 746 m.TSFT = binary.LittleEndian.Uint64(data[offset : offset+8]) 747 offset += 8 748 } 749 if m.Present.Flags() { 750 m.Flags = RadioTapFlags(data[offset]) 751 offset++ 752 } 753 if m.Present.Rate() { 754 m.Rate = RadioTapRate(data[offset]) 755 offset++ 756 } 757 if m.Present.Channel() { 758 offset += align(offset, 2) 759 m.ChannelFrequency = RadioTapChannelFrequency(binary.LittleEndian.Uint16(data[offset : offset+2])) 760 offset += 2 761 m.ChannelFlags = RadioTapChannelFlags(binary.LittleEndian.Uint16(data[offset : offset+2])) 762 offset += 2 763 } 764 if m.Present.FHSS() { 765 m.FHSS = binary.LittleEndian.Uint16(data[offset : offset+2]) 766 offset += 2 767 } 768 if m.Present.DBMAntennaSignal() { 769 m.DBMAntennaSignal = int8(data[offset]) 770 offset++ 771 } 772 if m.Present.DBMAntennaNoise() { 773 m.DBMAntennaNoise = int8(data[offset]) 774 offset++ 775 } 776 if m.Present.LockQuality() { 777 offset += align(offset, 2) 778 m.LockQuality = binary.LittleEndian.Uint16(data[offset : offset+2]) 779 offset += 2 780 } 781 if m.Present.TxAttenuation() { 782 offset += align(offset, 2) 783 m.TxAttenuation = binary.LittleEndian.Uint16(data[offset : offset+2]) 784 offset += 2 785 } 786 if m.Present.DBTxAttenuation() { 787 offset += align(offset, 2) 788 m.DBTxAttenuation = binary.LittleEndian.Uint16(data[offset : offset+2]) 789 offset += 2 790 } 791 if m.Present.DBMTxPower() { 792 m.DBMTxPower = int8(data[offset]) 793 offset++ 794 } 795 if m.Present.Antenna() { 796 m.Antenna = uint8(data[offset]) 797 offset++ 798 } 799 if m.Present.DBAntennaSignal() { 800 m.DBAntennaSignal = uint8(data[offset]) 801 offset++ 802 } 803 if m.Present.DBAntennaNoise() { 804 m.DBAntennaNoise = uint8(data[offset]) 805 offset++ 806 } 807 if m.Present.RxFlags() { 808 offset += align(offset, 2) 809 m.RxFlags = RadioTapRxFlags(binary.LittleEndian.Uint16(data[offset:])) 810 offset += 2 811 } 812 if m.Present.TxFlags() { 813 offset += align(offset, 2) 814 m.TxFlags = RadioTapTxFlags(binary.LittleEndian.Uint16(data[offset:])) 815 offset += 2 816 } 817 if m.Present.RtsRetries() { 818 m.RtsRetries = uint8(data[offset]) 819 offset++ 820 } 821 if m.Present.DataRetries() { 822 m.DataRetries = uint8(data[offset]) 823 offset++ 824 } 825 if m.Present.MCS() { 826 m.MCS = RadioTapMCS{ 827 RadioTapMCSKnown(data[offset]), 828 RadioTapMCSFlags(data[offset+1]), 829 uint8(data[offset+2]), 830 } 831 offset += 3 832 } 833 if m.Present.AMPDUStatus() { 834 offset += align(offset, 4) 835 m.AMPDUStatus = RadioTapAMPDUStatus{ 836 Reference: binary.LittleEndian.Uint32(data[offset:]), 837 Flags: RadioTapAMPDUStatusFlags(binary.LittleEndian.Uint16(data[offset+4:])), 838 CRC: uint8(data[offset+6]), 839 } 840 offset += 8 841 } 842 if m.Present.VHT() { 843 offset += align(offset, 2) 844 m.VHT = RadioTapVHT{ 845 Known: RadioTapVHTKnown(binary.LittleEndian.Uint16(data[offset:])), 846 Flags: RadioTapVHTFlags(data[offset+2]), 847 Bandwidth: uint8(data[offset+3]), 848 MCSNSS: [4]RadioTapVHTMCSNSS{ 849 RadioTapVHTMCSNSS(data[offset+4]), 850 RadioTapVHTMCSNSS(data[offset+5]), 851 RadioTapVHTMCSNSS(data[offset+6]), 852 RadioTapVHTMCSNSS(data[offset+7]), 853 }, 854 Coding: uint8(data[offset+8]), 855 GroupId: uint8(data[offset+9]), 856 PartialAID: binary.LittleEndian.Uint16(data[offset+10:]), 857 } 858 offset += 12 859 } 860 861 payload := data[m.Length:] 862 863 // Remove non standard padding used by some Wi-Fi drivers 864 if m.Flags.Datapad() && 865 payload[0]&0xC == 0x8 { //&& // Data frame 866 headlen := 24 867 if payload[0]&0x8C == 0x88 { // QoS 868 headlen += 2 869 } 870 if payload[1]&0x3 == 0x3 { // 4 addresses 871 headlen += 2 872 } 873 if headlen%4 == 2 { 874 payload = append(payload[:headlen], payload[headlen+2:len(payload)]...) 875 } 876 } 877 878 if !m.Flags.FCS() { 879 // Dot11.DecodeFromBytes() expects FCS present and performs a hard chop on the checksum 880 // If a user is handing in subslices or packets from a buffered stream, the capacity of the slice 881 // may extend beyond the len, rather than expecting callers to enforce cap==len on every packet 882 // we take the hit in this one case and do a reallocation. If the user DOES enforce cap==len 883 // then the reallocation will happen anyway on the append. This is requried because the append 884 // write to the memory directly after the payload if there is sufficient capacity, which callers 885 // may not expect. 886 reallocPayload := make([]byte, len(payload)+4) 887 copy(reallocPayload[0:len(payload)], payload) 888 h := crc32.NewIEEE() 889 h.Write(payload) 890 binary.LittleEndian.PutUint32(reallocPayload[len(payload):], h.Sum32()) 891 payload = reallocPayload 892 } 893 m.BaseLayer = BaseLayer{Contents: data[:m.Length], Payload: payload} 894 895 return nil 896} 897 898func (m RadioTap) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error { 899 buf := make([]byte, 1024) 900 901 buf[0] = m.Version 902 buf[1] = 0 903 904 binary.LittleEndian.PutUint32(buf[4:8], uint32(m.Present)) 905 906 offset := uint16(4) 907 908 for (binary.LittleEndian.Uint32(buf[offset:offset+4]) & 0x80000000) != 0 { 909 offset += 4 910 } 911 912 offset += 4 913 914 if m.Present.TSFT() { 915 offset += align(offset, 8) 916 binary.LittleEndian.PutUint64(buf[offset:offset+8], m.TSFT) 917 offset += 8 918 } 919 920 if m.Present.Flags() { 921 buf[offset] = uint8(m.Flags) 922 offset++ 923 } 924 925 if m.Present.Rate() { 926 buf[offset] = uint8(m.Rate) 927 offset++ 928 } 929 930 if m.Present.Channel() { 931 offset += align(offset, 2) 932 binary.LittleEndian.PutUint16(buf[offset:offset+2], uint16(m.ChannelFrequency)) 933 offset += 2 934 binary.LittleEndian.PutUint16(buf[offset:offset+2], uint16(m.ChannelFlags)) 935 offset += 2 936 } 937 938 if m.Present.FHSS() { 939 binary.LittleEndian.PutUint16(buf[offset:offset+2], m.FHSS) 940 offset += 2 941 } 942 943 if m.Present.DBMAntennaSignal() { 944 buf[offset] = byte(m.DBMAntennaSignal) 945 offset++ 946 } 947 948 if m.Present.DBMAntennaNoise() { 949 buf[offset] = byte(m.DBMAntennaNoise) 950 offset++ 951 } 952 953 if m.Present.LockQuality() { 954 offset += align(offset, 2) 955 binary.LittleEndian.PutUint16(buf[offset:offset+2], m.LockQuality) 956 offset += 2 957 } 958 959 if m.Present.TxAttenuation() { 960 offset += align(offset, 2) 961 binary.LittleEndian.PutUint16(buf[offset:offset+2], m.TxAttenuation) 962 offset += 2 963 } 964 965 if m.Present.DBTxAttenuation() { 966 offset += align(offset, 2) 967 binary.LittleEndian.PutUint16(buf[offset:offset+2], m.DBTxAttenuation) 968 offset += 2 969 } 970 971 if m.Present.DBMTxPower() { 972 buf[offset] = byte(m.DBMTxPower) 973 offset++ 974 } 975 976 if m.Present.Antenna() { 977 buf[offset] = uint8(m.Antenna) 978 offset++ 979 } 980 981 if m.Present.DBAntennaSignal() { 982 buf[offset] = uint8(m.DBAntennaSignal) 983 offset++ 984 } 985 986 if m.Present.DBAntennaNoise() { 987 buf[offset] = uint8(m.DBAntennaNoise) 988 offset++ 989 } 990 991 if m.Present.RxFlags() { 992 offset += align(offset, 2) 993 binary.LittleEndian.PutUint16(buf[offset:offset+2], uint16(m.RxFlags)) 994 offset += 2 995 } 996 997 if m.Present.TxFlags() { 998 offset += align(offset, 2) 999 binary.LittleEndian.PutUint16(buf[offset:offset+2], uint16(m.TxFlags)) 1000 offset += 2 1001 } 1002 1003 if m.Present.RtsRetries() { 1004 buf[offset] = m.RtsRetries 1005 offset++ 1006 } 1007 1008 if m.Present.DataRetries() { 1009 buf[offset] = m.DataRetries 1010 offset++ 1011 } 1012 1013 if m.Present.MCS() { 1014 buf[offset] = uint8(m.MCS.Known) 1015 buf[offset+1] = uint8(m.MCS.Flags) 1016 buf[offset+2] = uint8(m.MCS.MCS) 1017 1018 offset += 3 1019 } 1020 1021 if m.Present.AMPDUStatus() { 1022 offset += align(offset, 4) 1023 1024 binary.LittleEndian.PutUint32(buf[offset:offset+4], m.AMPDUStatus.Reference) 1025 binary.LittleEndian.PutUint16(buf[offset+4:offset+6], uint16(m.AMPDUStatus.Flags)) 1026 1027 buf[offset+6] = m.AMPDUStatus.CRC 1028 1029 offset += 8 1030 } 1031 1032 if m.Present.VHT() { 1033 offset += align(offset, 2) 1034 1035 binary.LittleEndian.PutUint16(buf[offset:], uint16(m.VHT.Known)) 1036 1037 buf[offset+2] = uint8(m.VHT.Flags) 1038 buf[offset+3] = uint8(m.VHT.Bandwidth) 1039 buf[offset+4] = uint8(m.VHT.MCSNSS[0]) 1040 buf[offset+5] = uint8(m.VHT.MCSNSS[1]) 1041 buf[offset+6] = uint8(m.VHT.MCSNSS[2]) 1042 buf[offset+7] = uint8(m.VHT.MCSNSS[3]) 1043 buf[offset+8] = uint8(m.VHT.Coding) 1044 buf[offset+9] = uint8(m.VHT.GroupId) 1045 1046 binary.LittleEndian.PutUint16(buf[offset+10:offset+12], m.VHT.PartialAID) 1047 1048 offset += 12 1049 } 1050 1051 packetBuf, err := b.PrependBytes(int(offset)) 1052 1053 if err != nil { 1054 return err 1055 } 1056 1057 if opts.FixLengths { 1058 m.Length = offset 1059 } 1060 1061 binary.LittleEndian.PutUint16(buf[2:4], m.Length) 1062 1063 copy(packetBuf, buf) 1064 1065 return nil 1066} 1067 1068func (m *RadioTap) CanDecode() gopacket.LayerClass { return LayerTypeRadioTap } 1069func (m *RadioTap) NextLayerType() gopacket.LayerType { return LayerTypeDot11 } 1070