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