1 // Copyright 2014 Google, Inc. All rights reserved.
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
16 "github.com/google/gopacket"
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).
22 func align(offset uint16, width uint16) uint16 {
23 return ((((offset) + ((width) - 1)) & (^((width) - 1))) - offset)
26 type RadioTapPresent uint32
29 RadioTapPresentTSFT RadioTapPresent = 1 << iota
32 RadioTapPresentChannel
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
49 RadioTapPresentAMPDUStatus
51 RadioTapPresentEXT RadioTapPresent = 1 << 31
54 func (r RadioTapPresent) TSFT() bool {
55 return r&RadioTapPresentTSFT != 0
57 func (r RadioTapPresent) Flags() bool {
58 return r&RadioTapPresentFlags != 0
60 func (r RadioTapPresent) Rate() bool {
61 return r&RadioTapPresentRate != 0
63 func (r RadioTapPresent) Channel() bool {
64 return r&RadioTapPresentChannel != 0
66 func (r RadioTapPresent) FHSS() bool {
67 return r&RadioTapPresentFHSS != 0
69 func (r RadioTapPresent) DBMAntennaSignal() bool {
70 return r&RadioTapPresentDBMAntennaSignal != 0
72 func (r RadioTapPresent) DBMAntennaNoise() bool {
73 return r&RadioTapPresentDBMAntennaNoise != 0
75 func (r RadioTapPresent) LockQuality() bool {
76 return r&RadioTapPresentLockQuality != 0
78 func (r RadioTapPresent) TxAttenuation() bool {
79 return r&RadioTapPresentTxAttenuation != 0
81 func (r RadioTapPresent) DBTxAttenuation() bool {
82 return r&RadioTapPresentDBTxAttenuation != 0
84 func (r RadioTapPresent) DBMTxPower() bool {
85 return r&RadioTapPresentDBMTxPower != 0
87 func (r RadioTapPresent) Antenna() bool {
88 return r&RadioTapPresentAntenna != 0
90 func (r RadioTapPresent) DBAntennaSignal() bool {
91 return r&RadioTapPresentDBAntennaSignal != 0
93 func (r RadioTapPresent) DBAntennaNoise() bool {
94 return r&RadioTapPresentDBAntennaNoise != 0
96 func (r RadioTapPresent) RxFlags() bool {
97 return r&RadioTapPresentRxFlags != 0
99 func (r RadioTapPresent) TxFlags() bool {
100 return r&RadioTapPresentTxFlags != 0
102 func (r RadioTapPresent) RtsRetries() bool {
103 return r&RadioTapPresentRtsRetries != 0
105 func (r RadioTapPresent) DataRetries() bool {
106 return r&RadioTapPresentDataRetries != 0
108 func (r RadioTapPresent) MCS() bool {
109 return r&RadioTapPresentMCS != 0
111 func (r RadioTapPresent) AMPDUStatus() bool {
112 return r&RadioTapPresentAMPDUStatus != 0
114 func (r RadioTapPresent) VHT() bool {
115 return r&RadioTapPresentVHT != 0
117 func (r RadioTapPresent) EXT() bool {
118 return r&RadioTapPresentEXT != 0
121 type RadioTapChannelFlags uint16
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)
134 func (r RadioTapChannelFlags) Turbo() bool {
135 return r&RadioTapChannelFlagsTurbo != 0
137 func (r RadioTapChannelFlags) CCK() bool {
138 return r&RadioTapChannelFlagsCCK != 0
140 func (r RadioTapChannelFlags) OFDM() bool {
141 return r&RadioTapChannelFlagsOFDM != 0
143 func (r RadioTapChannelFlags) Ghz2() bool {
144 return r&RadioTapChannelFlagsGhz2 != 0
146 func (r RadioTapChannelFlags) Ghz5() bool {
147 return r&RadioTapChannelFlagsGhz5 != 0
149 func (r RadioTapChannelFlags) Passive() bool {
150 return r&RadioTapChannelFlagsPassive != 0
152 func (r RadioTapChannelFlags) Dynamic() bool {
153 return r&RadioTapChannelFlagsDynamic != 0
155 func (r RadioTapChannelFlags) GFSK() bool {
156 return r&RadioTapChannelFlagsGFSK != 0
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.
162 func (a RadioTapChannelFlags) String() string {
165 out.WriteString("Turbo,")
168 out.WriteString("CCK,")
171 out.WriteString("OFDM,")
174 out.WriteString("Ghz2,")
177 out.WriteString("Ghz5,")
180 out.WriteString("Passive,")
183 out.WriteString("Dynamic,")
186 out.WriteString("GFSK,")
189 if length := out.Len(); length > 0 {
190 return string(out.Bytes()[:length-1]) // strip final comma
195 type RadioTapFlags uint8
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
208 func (r RadioTapFlags) CFP() bool {
209 return r&RadioTapFlagsCFP != 0
211 func (r RadioTapFlags) ShortPreamble() bool {
212 return r&RadioTapFlagsShortPreamble != 0
214 func (r RadioTapFlags) WEP() bool {
215 return r&RadioTapFlagsWEP != 0
217 func (r RadioTapFlags) Frag() bool {
218 return r&RadioTapFlagsFrag != 0
220 func (r RadioTapFlags) FCS() bool {
221 return r&RadioTapFlagsFCS != 0
223 func (r RadioTapFlags) Datapad() bool {
224 return r&RadioTapFlagsDatapad != 0
226 func (r RadioTapFlags) BadFCS() bool {
227 return r&RadioTapFlagsBadFCS != 0
229 func (r RadioTapFlags) ShortGI() bool {
230 return r&RadioTapFlagsShortGI != 0
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.
236 func (a RadioTapFlags) String() string {
239 out.WriteString("CFP,")
241 if a.ShortPreamble() {
242 out.WriteString("SHORT-PREAMBLE,")
245 out.WriteString("WEP,")
248 out.WriteString("FRAG,")
251 out.WriteString("FCS,")
254 out.WriteString("DATAPAD,")
257 out.WriteString("SHORT-GI,")
260 if length := out.Len(); length > 0 {
261 return string(out.Bytes()[:length-1]) // strip final comma
266 type RadioTapRate uint8
268 func (a RadioTapRate) String() string {
269 return fmt.Sprintf("%v Mb/s", 0.5*float32(a))
272 type RadioTapChannelFrequency uint16
274 func (a RadioTapChannelFrequency) String() string {
275 return fmt.Sprintf("%d MHz", a)
278 type RadioTapRxFlags uint16
281 RadioTapRxFlagsBadPlcp RadioTapRxFlags = 0x0002
284 func (self RadioTapRxFlags) BadPlcp() bool {
285 return self&RadioTapRxFlagsBadPlcp != 0
288 func (self RadioTapRxFlags) String() string {
295 type RadioTapTxFlags uint16
298 RadioTapTxFlagsFail RadioTapTxFlags = 1 << iota
304 func (self RadioTapTxFlags) Fail() bool { return self&RadioTapTxFlagsFail != 0 }
305 func (self RadioTapTxFlags) CTS() bool { return self&RadioTapTxFlagsCTS != 0 }
306 func (self RadioTapTxFlags) RTS() bool { return self&RadioTapTxFlagsRTS != 0 }
307 func (self RadioTapTxFlags) NoACK() bool { return self&RadioTapTxFlagsNoACK != 0 }
309 func (self RadioTapTxFlags) String() string {
312 tokens = append(tokens, "Fail")
315 tokens = append(tokens, "CTS")
318 tokens = append(tokens, "RTS")
321 tokens = append(tokens, "NoACK")
323 return strings.Join(tokens, ",")
326 type RadioTapMCS struct {
327 Known RadioTapMCSKnown
328 Flags RadioTapMCSFlags
332 func (self RadioTapMCS) String() string {
334 if self.Known.Bandwidth() {
336 switch self.Flags.Bandwidth() {
346 tokens = append(tokens, token)
348 if self.Known.MCSIndex() {
349 tokens = append(tokens, fmt.Sprintf("MCSIndex#%d", self.MCS))
351 if self.Known.GuardInterval() {
352 if self.Flags.ShortGI() {
353 tokens = append(tokens, fmt.Sprintf("shortGI"))
355 tokens = append(tokens, fmt.Sprintf("longGI"))
358 if self.Known.HTFormat() {
359 if self.Flags.Greenfield() {
360 tokens = append(tokens, fmt.Sprintf("HT-greenfield"))
362 tokens = append(tokens, fmt.Sprintf("HT-mixed"))
365 if self.Known.FECType() {
366 if self.Flags.FECLDPC() {
367 tokens = append(tokens, fmt.Sprintf("LDPC"))
369 tokens = append(tokens, fmt.Sprintf("BCC"))
372 if self.Known.STBC() {
373 tokens = append(tokens, fmt.Sprintf("STBC#%d", self.Flags.STBC()))
375 if self.Known.NESS() {
377 if self.Known.NESS1() {
380 if self.Flags.NESS0() {
383 tokens = append(tokens, fmt.Sprintf("num-of-ESS#%d", num))
385 return strings.Join(tokens, ",")
388 type RadioTapMCSKnown uint8
391 RadioTapMCSKnownBandwidth RadioTapMCSKnown = 1 << iota
392 RadioTapMCSKnownMCSIndex
393 RadioTapMCSKnownGuardInterval
394 RadioTapMCSKnownHTFormat
395 RadioTapMCSKnownFECType
398 RadioTapMCSKnownNESS1
401 func (self RadioTapMCSKnown) Bandwidth() bool { return self&RadioTapMCSKnownBandwidth != 0 }
402 func (self RadioTapMCSKnown) MCSIndex() bool { return self&RadioTapMCSKnownMCSIndex != 0 }
403 func (self RadioTapMCSKnown) GuardInterval() bool { return self&RadioTapMCSKnownGuardInterval != 0 }
404 func (self RadioTapMCSKnown) HTFormat() bool { return self&RadioTapMCSKnownHTFormat != 0 }
405 func (self RadioTapMCSKnown) FECType() bool { return self&RadioTapMCSKnownFECType != 0 }
406 func (self RadioTapMCSKnown) STBC() bool { return self&RadioTapMCSKnownSTBC != 0 }
407 func (self RadioTapMCSKnown) NESS() bool { return self&RadioTapMCSKnownNESS != 0 }
408 func (self RadioTapMCSKnown) NESS1() bool { return self&RadioTapMCSKnownNESS1 != 0 }
410 type RadioTapMCSFlags uint8
413 RadioTapMCSFlagsBandwidthMask RadioTapMCSFlags = 0x03
414 RadioTapMCSFlagsShortGI = 0x04
415 RadioTapMCSFlagsGreenfield = 0x08
416 RadioTapMCSFlagsFECLDPC = 0x10
417 RadioTapMCSFlagsSTBCMask = 0x60
418 RadioTapMCSFlagsNESS0 = 0x80
421 func (self RadioTapMCSFlags) Bandwidth() int {
422 return int(self & RadioTapMCSFlagsBandwidthMask)
424 func (self RadioTapMCSFlags) ShortGI() bool { return self&RadioTapMCSFlagsShortGI != 0 }
425 func (self RadioTapMCSFlags) Greenfield() bool { return self&RadioTapMCSFlagsGreenfield != 0 }
426 func (self RadioTapMCSFlags) FECLDPC() bool { return self&RadioTapMCSFlagsFECLDPC != 0 }
427 func (self RadioTapMCSFlags) STBC() int {
428 return int(self&RadioTapMCSFlagsSTBCMask) >> 5
430 func (self RadioTapMCSFlags) NESS0() bool { return self&RadioTapMCSFlagsNESS0 != 0 }
432 type RadioTapAMPDUStatus struct {
434 Flags RadioTapAMPDUStatusFlags
438 func (self RadioTapAMPDUStatus) String() string {
440 fmt.Sprintf("ref#%x", self.Reference),
442 if self.Flags.ReportZerolen() && self.Flags.IsZerolen() {
443 tokens = append(tokens, fmt.Sprintf("zero-length"))
445 if self.Flags.LastKnown() && self.Flags.IsLast() {
446 tokens = append(tokens, "last")
448 if self.Flags.DelimCRCErr() {
449 tokens = append(tokens, "delimiter CRC error")
451 if self.Flags.DelimCRCKnown() {
452 tokens = append(tokens, fmt.Sprintf("delimiter-CRC=%02x", self.CRC))
454 return strings.Join(tokens, ",")
457 type RadioTapAMPDUStatusFlags uint16
460 RadioTapAMPDUStatusFlagsReportZerolen RadioTapAMPDUStatusFlags = 1 << iota
461 RadioTapAMPDUIsZerolen
462 RadioTapAMPDULastKnown
464 RadioTapAMPDUDelimCRCErr
465 RadioTapAMPDUDelimCRCKnown
468 func (self RadioTapAMPDUStatusFlags) ReportZerolen() bool {
469 return self&RadioTapAMPDUStatusFlagsReportZerolen != 0
471 func (self RadioTapAMPDUStatusFlags) IsZerolen() bool { return self&RadioTapAMPDUIsZerolen != 0 }
472 func (self RadioTapAMPDUStatusFlags) LastKnown() bool { return self&RadioTapAMPDULastKnown != 0 }
473 func (self RadioTapAMPDUStatusFlags) IsLast() bool { return self&RadioTapAMPDUIsLast != 0 }
474 func (self RadioTapAMPDUStatusFlags) DelimCRCErr() bool { return self&RadioTapAMPDUDelimCRCErr != 0 }
475 func (self RadioTapAMPDUStatusFlags) DelimCRCKnown() bool { return self&RadioTapAMPDUDelimCRCKnown != 0 }
477 type RadioTapVHT struct {
478 Known RadioTapVHTKnown
479 Flags RadioTapVHTFlags
481 MCSNSS [4]RadioTapVHTMCSNSS
487 func (self RadioTapVHT) String() string {
489 if self.Known.STBC() {
490 if self.Flags.STBC() {
491 tokens = append(tokens, "STBC")
493 tokens = append(tokens, "no STBC")
496 if self.Known.TXOPPSNotAllowed() {
497 if self.Flags.TXOPPSNotAllowed() {
498 tokens = append(tokens, "TXOP doze not allowed")
500 tokens = append(tokens, "TXOP doze allowed")
504 if self.Flags.SGI() {
505 tokens = append(tokens, "short GI")
507 tokens = append(tokens, "long GI")
510 if self.Known.SGINSYMDisambiguation() {
511 if self.Flags.SGINSYMMod() {
512 tokens = append(tokens, "NSYM mod 10=9")
514 tokens = append(tokens, "NSYM mod 10!=9 or no short GI")
517 if self.Known.LDPCExtraOFDMSymbol() {
518 if self.Flags.LDPCExtraOFDMSymbol() {
519 tokens = append(tokens, "LDPC extra OFDM symbols")
521 tokens = append(tokens, "no LDPC extra OFDM symbols")
524 if self.Known.Beamformed() {
525 if self.Flags.Beamformed() {
526 tokens = append(tokens, "beamformed")
528 tokens = append(tokens, "no beamformed")
531 if self.Known.Bandwidth() {
533 switch self.Bandwidth & 0x1f {
587 tokens = append(tokens, token)
589 for i, MCSNSS := range self.MCSNSS {
590 if MCSNSS.Present() {
592 switch self.Coding & (1 << uint8(i)) {
598 tokens = append(tokens, fmt.Sprintf("user%d(%s,%s)", i, MCSNSS.String(), fec))
601 if self.Known.GroupId() {
602 tokens = append(tokens,
603 fmt.Sprintf("group=%d", self.GroupId))
605 if self.Known.PartialAID() {
606 tokens = append(tokens,
607 fmt.Sprintf("partial-AID=%d", self.PartialAID))
609 return strings.Join(tokens, ",")
612 type RadioTapVHTKnown uint16
615 RadioTapVHTKnownSTBC RadioTapVHTKnown = 1 << iota
616 RadioTapVHTKnownTXOPPSNotAllowed
618 RadioTapVHTKnownSGINSYMDisambiguation
619 RadioTapVHTKnownLDPCExtraOFDMSymbol
620 RadioTapVHTKnownBeamformed
621 RadioTapVHTKnownBandwidth
622 RadioTapVHTKnownGroupId
623 RadioTapVHTKnownPartialAID
626 func (self RadioTapVHTKnown) STBC() bool { return self&RadioTapVHTKnownSTBC != 0 }
627 func (self RadioTapVHTKnown) TXOPPSNotAllowed() bool {
628 return self&RadioTapVHTKnownTXOPPSNotAllowed != 0
630 func (self RadioTapVHTKnown) GI() bool { return self&RadioTapVHTKnownGI != 0 }
631 func (self RadioTapVHTKnown) SGINSYMDisambiguation() bool {
632 return self&RadioTapVHTKnownSGINSYMDisambiguation != 0
634 func (self RadioTapVHTKnown) LDPCExtraOFDMSymbol() bool {
635 return self&RadioTapVHTKnownLDPCExtraOFDMSymbol != 0
637 func (self RadioTapVHTKnown) Beamformed() bool { return self&RadioTapVHTKnownBeamformed != 0 }
638 func (self RadioTapVHTKnown) Bandwidth() bool { return self&RadioTapVHTKnownBandwidth != 0 }
639 func (self RadioTapVHTKnown) GroupId() bool { return self&RadioTapVHTKnownGroupId != 0 }
640 func (self RadioTapVHTKnown) PartialAID() bool { return self&RadioTapVHTKnownPartialAID != 0 }
642 type RadioTapVHTFlags uint8
645 RadioTapVHTFlagsSTBC RadioTapVHTFlags = 1 << iota
646 RadioTapVHTFlagsTXOPPSNotAllowed
648 RadioTapVHTFlagsSGINSYMMod
649 RadioTapVHTFlagsLDPCExtraOFDMSymbol
650 RadioTapVHTFlagsBeamformed
653 func (self RadioTapVHTFlags) STBC() bool { return self&RadioTapVHTFlagsSTBC != 0 }
654 func (self RadioTapVHTFlags) TXOPPSNotAllowed() bool {
655 return self&RadioTapVHTFlagsTXOPPSNotAllowed != 0
657 func (self RadioTapVHTFlags) SGI() bool { return self&RadioTapVHTFlagsSGI != 0 }
658 func (self RadioTapVHTFlags) SGINSYMMod() bool { return self&RadioTapVHTFlagsSGINSYMMod != 0 }
659 func (self RadioTapVHTFlags) LDPCExtraOFDMSymbol() bool {
660 return self&RadioTapVHTFlagsLDPCExtraOFDMSymbol != 0
662 func (self RadioTapVHTFlags) Beamformed() bool { return self&RadioTapVHTFlagsBeamformed != 0 }
664 type RadioTapVHTMCSNSS uint8
666 func (self RadioTapVHTMCSNSS) Present() bool {
667 return self&0x0F != 0
670 func (self RadioTapVHTMCSNSS) String() string {
671 return fmt.Sprintf("NSS#%dMCS#%d", uint32(self&0xf), uint32(self>>4))
674 func decodeRadioTap(data []byte, p gopacket.PacketBuilder) error {
676 // TODO: Should we set LinkLayer here? And implement LinkFlow
677 return decodingLayerDecoder(d, data, p)
680 type RadioTap struct {
683 // Version 0. Only increases for drastic changes, introduction of compatible new fields does not count.
685 // Length of the whole header in bytes, including it_version, it_pad, it_len, and data fields.
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.
692 // Rate Tx/Rx data rate
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).
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.
703 // LockQuality Quality of Barker code lock. Unitless. Monotonically nondecreasing with "better" lock strength. Called "Signal Quality" in datasheets.
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.
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.
711 // Antenna Unitless indication of the Rx/Tx antenna for this packet. The first antenna is antenna 0.
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.
718 RxFlags RadioTapRxFlags
719 TxFlags RadioTapTxFlags
723 AMPDUStatus RadioTapAMPDUStatus
727 func (m *RadioTap) LayerType() gopacket.LayerType { return LayerTypeRadioTap }
729 func (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]))
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.
742 offset += 4 // skip the bitmap
744 if m.Present.TSFT() {
745 offset += align(offset, 8)
746 m.TSFT = binary.LittleEndian.Uint64(data[offset : offset+8])
749 if m.Present.Flags() {
750 m.Flags = RadioTapFlags(data[offset])
753 if m.Present.Rate() {
754 m.Rate = RadioTapRate(data[offset])
757 if m.Present.Channel() {
758 offset += align(offset, 2)
759 m.ChannelFrequency = RadioTapChannelFrequency(binary.LittleEndian.Uint16(data[offset : offset+2]))
761 m.ChannelFlags = RadioTapChannelFlags(binary.LittleEndian.Uint16(data[offset : offset+2]))
764 if m.Present.FHSS() {
765 m.FHSS = binary.LittleEndian.Uint16(data[offset : offset+2])
768 if m.Present.DBMAntennaSignal() {
769 m.DBMAntennaSignal = int8(data[offset])
772 if m.Present.DBMAntennaNoise() {
773 m.DBMAntennaNoise = int8(data[offset])
776 if m.Present.LockQuality() {
777 offset += align(offset, 2)
778 m.LockQuality = binary.LittleEndian.Uint16(data[offset : offset+2])
781 if m.Present.TxAttenuation() {
782 offset += align(offset, 2)
783 m.TxAttenuation = binary.LittleEndian.Uint16(data[offset : offset+2])
786 if m.Present.DBTxAttenuation() {
787 offset += align(offset, 2)
788 m.DBTxAttenuation = binary.LittleEndian.Uint16(data[offset : offset+2])
791 if m.Present.DBMTxPower() {
792 m.DBMTxPower = int8(data[offset])
795 if m.Present.Antenna() {
796 m.Antenna = uint8(data[offset])
799 if m.Present.DBAntennaSignal() {
800 m.DBAntennaSignal = uint8(data[offset])
803 if m.Present.DBAntennaNoise() {
804 m.DBAntennaNoise = uint8(data[offset])
807 if m.Present.RxFlags() {
808 offset += align(offset, 2)
809 m.RxFlags = RadioTapRxFlags(binary.LittleEndian.Uint16(data[offset:]))
812 if m.Present.TxFlags() {
813 offset += align(offset, 2)
814 m.TxFlags = RadioTapTxFlags(binary.LittleEndian.Uint16(data[offset:]))
817 if m.Present.RtsRetries() {
818 m.RtsRetries = uint8(data[offset])
821 if m.Present.DataRetries() {
822 m.DataRetries = uint8(data[offset])
827 RadioTapMCSKnown(data[offset]),
828 RadioTapMCSFlags(data[offset+1]),
829 uint8(data[offset+2]),
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]),
843 offset += align(offset, 2)
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]),
854 Coding: uint8(data[offset+8]),
855 GroupId: uint8(data[offset+9]),
856 PartialAID: binary.LittleEndian.Uint16(data[offset+10:]),
861 payload := data[m.Length:]
862 if !m.Flags.FCS() { // Dot11.DecodeFromBytes() expects FCS present
863 fcs := make([]byte, 4)
866 binary.LittleEndian.PutUint32(fcs, h.Sum32())
867 payload = append(payload, fcs...)
869 m.BaseLayer = BaseLayer{Contents: data[:m.Length], Payload: payload}
874 func (m RadioTap) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
875 buf := make([]byte, 1024)
880 binary.LittleEndian.PutUint32(buf[4:8], uint32(m.Present))
884 for (binary.LittleEndian.Uint32(buf[offset:offset+4]) & 0x80000000) != 0 {
890 if m.Present.TSFT() {
891 offset += align(offset, 8)
892 binary.LittleEndian.PutUint64(buf[offset:offset+8], m.TSFT)
896 if m.Present.Flags() {
897 buf[offset] = uint8(m.Flags)
901 if m.Present.Rate() {
902 buf[offset] = uint8(m.Rate)
906 if m.Present.Channel() {
907 offset += align(offset, 2)
908 binary.LittleEndian.PutUint16(buf[offset:offset+2], uint16(m.ChannelFrequency))
910 binary.LittleEndian.PutUint16(buf[offset:offset+2], uint16(m.ChannelFlags))
914 if m.Present.FHSS() {
915 binary.LittleEndian.PutUint16(buf[offset:offset+2], m.FHSS)
919 if m.Present.DBMAntennaSignal() {
920 buf[offset] = byte(m.DBMAntennaSignal)
924 if m.Present.DBMAntennaNoise() {
925 buf[offset] = byte(m.DBMAntennaNoise)
929 if m.Present.LockQuality() {
930 offset += align(offset, 2)
931 binary.LittleEndian.PutUint16(buf[offset:offset+2], m.LockQuality)
935 if m.Present.TxAttenuation() {
936 offset += align(offset, 2)
937 binary.LittleEndian.PutUint16(buf[offset:offset+2], m.TxAttenuation)
941 if m.Present.DBTxAttenuation() {
942 offset += align(offset, 2)
943 binary.LittleEndian.PutUint16(buf[offset:offset+2], m.DBTxAttenuation)
947 if m.Present.DBMTxPower() {
948 buf[offset] = byte(m.DBMTxPower)
952 if m.Present.Antenna() {
953 buf[offset] = uint8(m.Antenna)
957 if m.Present.DBAntennaSignal() {
958 buf[offset] = uint8(m.DBAntennaSignal)
962 if m.Present.DBAntennaNoise() {
963 buf[offset] = uint8(m.DBAntennaNoise)
967 if m.Present.RxFlags() {
968 offset += align(offset, 2)
969 binary.LittleEndian.PutUint16(buf[offset:offset+2], uint16(m.RxFlags))
973 if m.Present.TxFlags() {
974 offset += align(offset, 2)
975 binary.LittleEndian.PutUint16(buf[offset:offset+2], uint16(m.TxFlags))
979 if m.Present.RtsRetries() {
980 buf[offset] = m.RtsRetries
984 if m.Present.DataRetries() {
985 buf[offset] = m.DataRetries
990 buf[offset] = uint8(m.MCS.Known)
991 buf[offset+1] = uint8(m.MCS.Flags)
992 buf[offset+2] = uint8(m.MCS.MCS)
997 if m.Present.AMPDUStatus() {
998 offset += align(offset, 4)
1000 binary.LittleEndian.PutUint32(buf[offset:offset+4], m.AMPDUStatus.Reference)
1001 binary.LittleEndian.PutUint16(buf[offset+4:offset+6], uint16(m.AMPDUStatus.Flags))
1003 buf[offset+6] = m.AMPDUStatus.CRC
1008 if m.Present.VHT() {
1009 offset += align(offset, 2)
1011 binary.LittleEndian.PutUint16(buf[offset:], uint16(m.VHT.Known))
1013 buf[offset+2] = uint8(m.VHT.Flags)
1014 buf[offset+3] = uint8(m.VHT.Bandwidth)
1015 buf[offset+4] = uint8(m.VHT.MCSNSS[0])
1016 buf[offset+5] = uint8(m.VHT.MCSNSS[1])
1017 buf[offset+6] = uint8(m.VHT.MCSNSS[2])
1018 buf[offset+7] = uint8(m.VHT.MCSNSS[3])
1019 buf[offset+8] = uint8(m.VHT.Coding)
1020 buf[offset+9] = uint8(m.VHT.GroupId)
1022 binary.LittleEndian.PutUint16(buf[offset+10:offset+12], m.VHT.PartialAID)
1027 packetBuf, err := b.PrependBytes(int(offset))
1033 if opts.FixLengths {
1037 binary.LittleEndian.PutUint16(buf[2:4], m.Length)
1039 copy(packetBuf, buf)
1044 func (m *RadioTap) CanDecode() gopacket.LayerClass { return LayerTypeRadioTap }
1045 func (m *RadioTap) NextLayerType() gopacket.LayerType { return LayerTypeDot11 }