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 }