Fix unit tests
[govpp.git] / vendor / github.com / google / gopacket / layers / radiotap.go
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         "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).
22 func align(offset uint16, width uint16) uint16 {
23         return ((((offset) + ((width) - 1)) & (^((width) - 1))) - offset)
24 }
25
26 type RadioTapPresent uint32
27
28 const (
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
54 func (r RadioTapPresent) TSFT() bool {
55         return r&RadioTapPresentTSFT != 0
56 }
57 func (r RadioTapPresent) Flags() bool {
58         return r&RadioTapPresentFlags != 0
59 }
60 func (r RadioTapPresent) Rate() bool {
61         return r&RadioTapPresentRate != 0
62 }
63 func (r RadioTapPresent) Channel() bool {
64         return r&RadioTapPresentChannel != 0
65 }
66 func (r RadioTapPresent) FHSS() bool {
67         return r&RadioTapPresentFHSS != 0
68 }
69 func (r RadioTapPresent) DBMAntennaSignal() bool {
70         return r&RadioTapPresentDBMAntennaSignal != 0
71 }
72 func (r RadioTapPresent) DBMAntennaNoise() bool {
73         return r&RadioTapPresentDBMAntennaNoise != 0
74 }
75 func (r RadioTapPresent) LockQuality() bool {
76         return r&RadioTapPresentLockQuality != 0
77 }
78 func (r RadioTapPresent) TxAttenuation() bool {
79         return r&RadioTapPresentTxAttenuation != 0
80 }
81 func (r RadioTapPresent) DBTxAttenuation() bool {
82         return r&RadioTapPresentDBTxAttenuation != 0
83 }
84 func (r RadioTapPresent) DBMTxPower() bool {
85         return r&RadioTapPresentDBMTxPower != 0
86 }
87 func (r RadioTapPresent) Antenna() bool {
88         return r&RadioTapPresentAntenna != 0
89 }
90 func (r RadioTapPresent) DBAntennaSignal() bool {
91         return r&RadioTapPresentDBAntennaSignal != 0
92 }
93 func (r RadioTapPresent) DBAntennaNoise() bool {
94         return r&RadioTapPresentDBAntennaNoise != 0
95 }
96 func (r RadioTapPresent) RxFlags() bool {
97         return r&RadioTapPresentRxFlags != 0
98 }
99 func (r RadioTapPresent) TxFlags() bool {
100         return r&RadioTapPresentTxFlags != 0
101 }
102 func (r RadioTapPresent) RtsRetries() bool {
103         return r&RadioTapPresentRtsRetries != 0
104 }
105 func (r RadioTapPresent) DataRetries() bool {
106         return r&RadioTapPresentDataRetries != 0
107 }
108 func (r RadioTapPresent) MCS() bool {
109         return r&RadioTapPresentMCS != 0
110 }
111 func (r RadioTapPresent) AMPDUStatus() bool {
112         return r&RadioTapPresentAMPDUStatus != 0
113 }
114 func (r RadioTapPresent) VHT() bool {
115         return r&RadioTapPresentVHT != 0
116 }
117 func (r RadioTapPresent) EXT() bool {
118         return r&RadioTapPresentEXT != 0
119 }
120
121 type RadioTapChannelFlags uint16
122
123 const (
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
134 func (r RadioTapChannelFlags) Turbo() bool {
135         return r&RadioTapChannelFlagsTurbo != 0
136 }
137 func (r RadioTapChannelFlags) CCK() bool {
138         return r&RadioTapChannelFlagsCCK != 0
139 }
140 func (r RadioTapChannelFlags) OFDM() bool {
141         return r&RadioTapChannelFlagsOFDM != 0
142 }
143 func (r RadioTapChannelFlags) Ghz2() bool {
144         return r&RadioTapChannelFlagsGhz2 != 0
145 }
146 func (r RadioTapChannelFlags) Ghz5() bool {
147         return r&RadioTapChannelFlagsGhz5 != 0
148 }
149 func (r RadioTapChannelFlags) Passive() bool {
150         return r&RadioTapChannelFlagsPassive != 0
151 }
152 func (r RadioTapChannelFlags) Dynamic() bool {
153         return r&RadioTapChannelFlagsDynamic != 0
154 }
155 func (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.
162 func (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
195 type RadioTapFlags uint8
196
197 const (
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
208 func (r RadioTapFlags) CFP() bool {
209         return r&RadioTapFlagsCFP != 0
210 }
211 func (r RadioTapFlags) ShortPreamble() bool {
212         return r&RadioTapFlagsShortPreamble != 0
213 }
214 func (r RadioTapFlags) WEP() bool {
215         return r&RadioTapFlagsWEP != 0
216 }
217 func (r RadioTapFlags) Frag() bool {
218         return r&RadioTapFlagsFrag != 0
219 }
220 func (r RadioTapFlags) FCS() bool {
221         return r&RadioTapFlagsFCS != 0
222 }
223 func (r RadioTapFlags) Datapad() bool {
224         return r&RadioTapFlagsDatapad != 0
225 }
226 func (r RadioTapFlags) BadFCS() bool {
227         return r&RadioTapFlagsBadFCS != 0
228 }
229 func (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.
236 func (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
266 type RadioTapRate uint8
267
268 func (a RadioTapRate) String() string {
269         return fmt.Sprintf("%v Mb/s", 0.5*float32(a))
270 }
271
272 type RadioTapChannelFrequency uint16
273
274 func (a RadioTapChannelFrequency) String() string {
275         return fmt.Sprintf("%d MHz", a)
276 }
277
278 type RadioTapRxFlags uint16
279
280 const (
281         RadioTapRxFlagsBadPlcp RadioTapRxFlags = 0x0002
282 )
283
284 func (self RadioTapRxFlags) BadPlcp() bool {
285         return self&RadioTapRxFlagsBadPlcp != 0
286 }
287
288 func (self RadioTapRxFlags) String() string {
289         if self.BadPlcp() {
290                 return "BADPLCP"
291         }
292         return ""
293 }
294
295 type RadioTapTxFlags uint16
296
297 const (
298         RadioTapTxFlagsFail RadioTapTxFlags = 1 << iota
299         RadioTapTxFlagsCTS
300         RadioTapTxFlagsRTS
301         RadioTapTxFlagsNoACK
302 )
303
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 }
308
309 func (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
326 type RadioTapMCS struct {
327         Known RadioTapMCSKnown
328         Flags RadioTapMCSFlags
329         MCS   uint8
330 }
331
332 func (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
388 type RadioTapMCSKnown uint8
389
390 const (
391         RadioTapMCSKnownBandwidth RadioTapMCSKnown = 1 << iota
392         RadioTapMCSKnownMCSIndex
393         RadioTapMCSKnownGuardInterval
394         RadioTapMCSKnownHTFormat
395         RadioTapMCSKnownFECType
396         RadioTapMCSKnownSTBC
397         RadioTapMCSKnownNESS
398         RadioTapMCSKnownNESS1
399 )
400
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 }
409
410 type RadioTapMCSFlags uint8
411
412 const (
413         RadioTapMCSFlagsBandwidthMask RadioTapMCSFlags = 0x03
414         RadioTapMCSFlagsShortGI                        = 0x04
415         RadioTapMCSFlagsGreenfield                     = 0x08
416         RadioTapMCSFlagsFECLDPC                        = 0x10
417         RadioTapMCSFlagsSTBCMask                       = 0x60
418         RadioTapMCSFlagsNESS0                          = 0x80
419 )
420
421 func (self RadioTapMCSFlags) Bandwidth() int {
422         return int(self & RadioTapMCSFlagsBandwidthMask)
423 }
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
429 }
430 func (self RadioTapMCSFlags) NESS0() bool { return self&RadioTapMCSFlagsNESS0 != 0 }
431
432 type RadioTapAMPDUStatus struct {
433         Reference uint32
434         Flags     RadioTapAMPDUStatusFlags
435         CRC       uint8
436 }
437
438 func (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
457 type RadioTapAMPDUStatusFlags uint16
458
459 const (
460         RadioTapAMPDUStatusFlagsReportZerolen RadioTapAMPDUStatusFlags = 1 << iota
461         RadioTapAMPDUIsZerolen
462         RadioTapAMPDULastKnown
463         RadioTapAMPDUIsLast
464         RadioTapAMPDUDelimCRCErr
465         RadioTapAMPDUDelimCRCKnown
466 )
467
468 func (self RadioTapAMPDUStatusFlags) ReportZerolen() bool {
469         return self&RadioTapAMPDUStatusFlagsReportZerolen != 0
470 }
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 }
476
477 type 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
487 func (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
612 type RadioTapVHTKnown uint16
613
614 const (
615         RadioTapVHTKnownSTBC RadioTapVHTKnown = 1 << iota
616         RadioTapVHTKnownTXOPPSNotAllowed
617         RadioTapVHTKnownGI
618         RadioTapVHTKnownSGINSYMDisambiguation
619         RadioTapVHTKnownLDPCExtraOFDMSymbol
620         RadioTapVHTKnownBeamformed
621         RadioTapVHTKnownBandwidth
622         RadioTapVHTKnownGroupId
623         RadioTapVHTKnownPartialAID
624 )
625
626 func (self RadioTapVHTKnown) STBC() bool { return self&RadioTapVHTKnownSTBC != 0 }
627 func (self RadioTapVHTKnown) TXOPPSNotAllowed() bool {
628         return self&RadioTapVHTKnownTXOPPSNotAllowed != 0
629 }
630 func (self RadioTapVHTKnown) GI() bool { return self&RadioTapVHTKnownGI != 0 }
631 func (self RadioTapVHTKnown) SGINSYMDisambiguation() bool {
632         return self&RadioTapVHTKnownSGINSYMDisambiguation != 0
633 }
634 func (self RadioTapVHTKnown) LDPCExtraOFDMSymbol() bool {
635         return self&RadioTapVHTKnownLDPCExtraOFDMSymbol != 0
636 }
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 }
641
642 type RadioTapVHTFlags uint8
643
644 const (
645         RadioTapVHTFlagsSTBC RadioTapVHTFlags = 1 << iota
646         RadioTapVHTFlagsTXOPPSNotAllowed
647         RadioTapVHTFlagsSGI
648         RadioTapVHTFlagsSGINSYMMod
649         RadioTapVHTFlagsLDPCExtraOFDMSymbol
650         RadioTapVHTFlagsBeamformed
651 )
652
653 func (self RadioTapVHTFlags) STBC() bool { return self&RadioTapVHTFlagsSTBC != 0 }
654 func (self RadioTapVHTFlags) TXOPPSNotAllowed() bool {
655         return self&RadioTapVHTFlagsTXOPPSNotAllowed != 0
656 }
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
661 }
662 func (self RadioTapVHTFlags) Beamformed() bool { return self&RadioTapVHTFlagsBeamformed != 0 }
663
664 type RadioTapVHTMCSNSS uint8
665
666 func (self RadioTapVHTMCSNSS) Present() bool {
667         return self&0x0F != 0
668 }
669
670 func (self RadioTapVHTMCSNSS) String() string {
671         return fmt.Sprintf("NSS#%dMCS#%d", uint32(self&0xf), uint32(self>>4))
672 }
673
674 func 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
680 type 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
727 func (m *RadioTap) LayerType() gopacket.LayerType { return LayerTypeRadioTap }
728
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]))
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         if !m.Flags.FCS() { // Dot11.DecodeFromBytes() expects FCS present
863                 fcs := make([]byte, 4)
864                 h := crc32.NewIEEE()
865                 h.Write(payload)
866                 binary.LittleEndian.PutUint32(fcs, h.Sum32())
867                 payload = append(payload, fcs...)
868         }
869         m.BaseLayer = BaseLayer{Contents: data[:m.Length], Payload: payload}
870
871         return nil
872 }
873
874 func (m RadioTap) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
875         buf := make([]byte, 1024)
876
877         buf[0] = m.Version
878         buf[1] = 0
879
880         binary.LittleEndian.PutUint32(buf[4:8], uint32(m.Present))
881
882         offset := uint16(4)
883
884         for (binary.LittleEndian.Uint32(buf[offset:offset+4]) & 0x80000000) != 0 {
885                 offset += 4
886         }
887
888         offset += 4
889
890         if m.Present.TSFT() {
891                 offset += align(offset, 8)
892                 binary.LittleEndian.PutUint64(buf[offset:offset+8], m.TSFT)
893                 offset += 8
894         }
895
896         if m.Present.Flags() {
897                 buf[offset] = uint8(m.Flags)
898                 offset++
899         }
900
901         if m.Present.Rate() {
902                 buf[offset] = uint8(m.Rate)
903                 offset++
904         }
905
906         if m.Present.Channel() {
907                 offset += align(offset, 2)
908                 binary.LittleEndian.PutUint16(buf[offset:offset+2], uint16(m.ChannelFrequency))
909                 offset += 2
910                 binary.LittleEndian.PutUint16(buf[offset:offset+2], uint16(m.ChannelFlags))
911                 offset += 2
912         }
913
914         if m.Present.FHSS() {
915                 binary.LittleEndian.PutUint16(buf[offset:offset+2], m.FHSS)
916                 offset += 2
917         }
918
919         if m.Present.DBMAntennaSignal() {
920                 buf[offset] = byte(m.DBMAntennaSignal)
921                 offset++
922         }
923
924         if m.Present.DBMAntennaNoise() {
925                 buf[offset] = byte(m.DBMAntennaNoise)
926                 offset++
927         }
928
929         if m.Present.LockQuality() {
930                 offset += align(offset, 2)
931                 binary.LittleEndian.PutUint16(buf[offset:offset+2], m.LockQuality)
932                 offset += 2
933         }
934
935         if m.Present.TxAttenuation() {
936                 offset += align(offset, 2)
937                 binary.LittleEndian.PutUint16(buf[offset:offset+2], m.TxAttenuation)
938                 offset += 2
939         }
940
941         if m.Present.DBTxAttenuation() {
942                 offset += align(offset, 2)
943                 binary.LittleEndian.PutUint16(buf[offset:offset+2], m.DBTxAttenuation)
944                 offset += 2
945         }
946
947         if m.Present.DBMTxPower() {
948                 buf[offset] = byte(m.DBMTxPower)
949                 offset++
950         }
951
952         if m.Present.Antenna() {
953                 buf[offset] = uint8(m.Antenna)
954                 offset++
955         }
956
957         if m.Present.DBAntennaSignal() {
958                 buf[offset] = uint8(m.DBAntennaSignal)
959                 offset++
960         }
961
962         if m.Present.DBAntennaNoise() {
963                 buf[offset] = uint8(m.DBAntennaNoise)
964                 offset++
965         }
966
967         if m.Present.RxFlags() {
968                 offset += align(offset, 2)
969                 binary.LittleEndian.PutUint16(buf[offset:offset+2], uint16(m.RxFlags))
970                 offset += 2
971         }
972
973         if m.Present.TxFlags() {
974                 offset += align(offset, 2)
975                 binary.LittleEndian.PutUint16(buf[offset:offset+2], uint16(m.TxFlags))
976                 offset += 2
977         }
978
979         if m.Present.RtsRetries() {
980                 buf[offset] = m.RtsRetries
981                 offset++
982         }
983
984         if m.Present.DataRetries() {
985                 buf[offset] = m.DataRetries
986                 offset++
987         }
988
989         if m.Present.MCS() {
990                 buf[offset] = uint8(m.MCS.Known)
991                 buf[offset+1] = uint8(m.MCS.Flags)
992                 buf[offset+2] = uint8(m.MCS.MCS)
993
994                 offset += 3
995         }
996
997         if m.Present.AMPDUStatus() {
998                 offset += align(offset, 4)
999
1000                 binary.LittleEndian.PutUint32(buf[offset:offset+4], m.AMPDUStatus.Reference)
1001                 binary.LittleEndian.PutUint16(buf[offset+4:offset+6], uint16(m.AMPDUStatus.Flags))
1002
1003                 buf[offset+6] = m.AMPDUStatus.CRC
1004
1005                 offset += 8
1006         }
1007
1008         if m.Present.VHT() {
1009                 offset += align(offset, 2)
1010
1011                 binary.LittleEndian.PutUint16(buf[offset:], uint16(m.VHT.Known))
1012
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)
1021
1022                 binary.LittleEndian.PutUint16(buf[offset+10:offset+12], m.VHT.PartialAID)
1023
1024                 offset += 12
1025         }
1026
1027         packetBuf, err := b.PrependBytes(int(offset))
1028
1029         if err != nil {
1030                 return err
1031         }
1032
1033         if opts.FixLengths {
1034                 m.Length = offset
1035         }
1036
1037         binary.LittleEndian.PutUint16(buf[2:4], m.Length)
1038
1039         copy(packetBuf, buf)
1040
1041         return nil
1042 }
1043
1044 func (m *RadioTap) CanDecode() gopacket.LayerClass    { return LayerTypeRadioTap }
1045 func (m *RadioTap) NextLayerType() gopacket.LayerType { return LayerTypeDot11 }