Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for Wi-Fi/802.11 related radiotap fields: MCS, HE, VHT #207

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
312 changes: 312 additions & 0 deletions PacketDotNet/Ieee80211/RadioTapFields.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,306 @@ This Source Code Form is subject to the terms of the Mozilla Public

namespace PacketDotNet.Ieee80211;


/// <summary>
/// The presence of this field indicates that the frame was received or transmitted using the VHT PHY (Wi-Fi 5 / ieee802.11ac).
/// </summary>
public class VeryHighThroughputRadioTapField : RadioTapField
{
public RadioTapVhtKnown Known { get; set; }
public RadioTapVhtFlags Flags { get; set; }
public RadioTapVhtBandwidth Bandwidth { get; set; }
public RadioTapVhtMcsNss McsNss1 { get; set; }
public RadioTapVhtMcsNss McsNss2 { get; set; }
public RadioTapVhtMcsNss McsNss3 { get; set; }
public RadioTapVhtMcsNss McsNss4 { get; set; }

/// <summary>
/// The coding for a user is only valid if the NSS (in the mcs_nss field) for that user is nonzero.
/// </summary>
public RadioTapVhtCoding Coding { get; set; }
public byte GroupId { get; set; }
public ushort PartialAid { get; set; }

/// <summary>
/// Constructor
/// </summary>
/// <param name="br">
/// A <see cref="BinaryReader" />
/// </param>
public VeryHighThroughputRadioTapField(BinaryReader br)
{
Known = (RadioTapVhtKnown)br.ReadUInt16();
Flags = (RadioTapVhtFlags)br.ReadByte();
Bandwidth = (RadioTapVhtBandwidth)br.ReadByte();
McsNss1 = (RadioTapVhtMcsNss)br.ReadByte();
McsNss2 = (RadioTapVhtMcsNss)br.ReadByte();
McsNss3 = (RadioTapVhtMcsNss)br.ReadByte();
McsNss4 = (RadioTapVhtMcsNss)br.ReadByte();
Coding = (RadioTapVhtCoding)br.ReadByte();
GroupId = br.ReadByte();
PartialAid = br.ReadUInt16();
}


Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Formatting

/// <summary>
/// Initializes a new instance of the <see cref="VeryHighThroughputRadioTapField" /> class.
/// </summary>
public VeryHighThroughputRadioTapField()
{ }

/// <summary>
/// Initializes a new instance of the <see cref="VeryHighThroughputRadioTapField" /> class.
/// </summary>
public VeryHighThroughputRadioTapField(
RadioTapVhtKnown known,
RadioTapVhtFlags flags,
RadioTapVhtBandwidth bandwidth,
RadioTapVhtMcsNss mcsNss1,
RadioTapVhtMcsNss mcsNss2,
RadioTapVhtMcsNss mcsNss3,
RadioTapVhtMcsNss mcsNss4,
RadioTapVhtCoding coding,
byte groupId,
ushort partialAid)
{
Known = known;
Flags = flags;
Bandwidth = bandwidth;
McsNss1 = mcsNss1;
McsNss2 = mcsNss2;
McsNss3 = mcsNss3;
McsNss4 = mcsNss4;
Coding = coding;
GroupId = groupId;
PartialAid = partialAid;
}

/// <summary>Type of the field</summary>
public override RadioTapType FieldType => RadioTapType.VeryHighThroughput;

/// <summary>
/// Gets the length of the field data.
/// </summary>
/// <value>
/// The length.
/// </value>
public override ushort Length => 12;

/// <summary>
///
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fix comments throughout file please.

/// </summary>
/// <value>The alignment.</value>
public override ushort Alignment => 2;


/// <summary>
/// Copies the field data to the destination buffer at the specified offset.
/// </summary>
public override void CopyTo(byte[] dest, int offset)
{
EndianBitConverter.Little.CopyBytes((ushort)Known, dest, offset);
EndianBitConverter.Little.CopyBytes((byte)Flags, dest, offset + 2);
EndianBitConverter.Little.CopyBytes((byte)Bandwidth, dest, offset + 3);
EndianBitConverter.Little.CopyBytes((byte)McsNss1, dest, offset + 4);
EndianBitConverter.Little.CopyBytes((byte)McsNss2, dest, offset + 5);
EndianBitConverter.Little.CopyBytes((byte)McsNss3, dest, offset + 6);
EndianBitConverter.Little.CopyBytes((byte)McsNss4, dest, offset + 7);
EndianBitConverter.Little.CopyBytes((byte)Coding, dest, offset + 8);
EndianBitConverter.Little.CopyBytes(GroupId, dest, offset + 9);
EndianBitConverter.Little.CopyBytes(PartialAid, dest, offset + 10);
}

/// <summary>
/// ToString() override
/// </summary>
/// <returns>
/// A <see cref="string" />
/// </returns>
public override string ToString()
{
return $"Known {Known}, Flags {Flags}, Bandwidth {Bandwidth}, McsNss1 {McsNss1}, McsNss2 {McsNss2}, McsNss3 {McsNss3}, McsNss4 {McsNss4}, Coding {Coding}, GroupId {GroupId}, PartialAid {PartialAid}";
}
}

/// <summary>
/// The presence of this field indicates that the frame was received or transmitted using the HE PHY (Wi-Fi 6 / ieee802.11ax).
/// </summary>
public class HighEfficiencyRadioTapField : RadioTapField
{
public RadioTapHighEfficiencyData1 Data1 { get; set; }
public RadioTapHighEfficiencyData2 Data2 { get; set; }
public ushort Data3 { get; set; }
public ushort Data4 { get; set; }
public ushort Data5 { get; set; }
public ushort Data6 { get; set; }

/// <summary>
/// Constructor
/// </summary>
/// <param name="br">
/// A <see cref="BinaryReader" />
/// </param>
public HighEfficiencyRadioTapField(BinaryReader br)
{
Data1 = (RadioTapHighEfficiencyData1)br.ReadUInt16();
Data2 = (RadioTapHighEfficiencyData2)br.ReadUInt16();
Data3 = br.ReadUInt16();
Data4 = br.ReadUInt16();
Data5 = br.ReadUInt16();
Data6 = br.ReadUInt16();
}


/// <summary>
/// Initializes a new instance of the <see cref="HighEfficiencyRadioTapField" /> class.
/// </summary>
public HighEfficiencyRadioTapField()
{ }

/// <summary>
/// Initializes a new instance of the <see cref="HighEfficiencyRadioTapField" /> class.
/// </summary>
public HighEfficiencyRadioTapField(RadioTapHighEfficiencyData1 data1, RadioTapHighEfficiencyData2 data2, ushort data3, ushort data4, ushort data5, ushort data6)
{
Data1 = data1;
Data2 = data2;
Data3 = data3;
Data4 = data4;
Data5 = data5;
Data6 = data6;
}

/// <summary>Type of the field</summary>
public override RadioTapType FieldType => RadioTapType.HighEfficiency;

/// <summary>
/// Gets the length of the field data.
/// </summary>
/// <value>
/// The length.
/// </value>
public override ushort Length => 12;

/// <summary>
///
/// </summary>
/// <value>The alignment.</value>
public override ushort Alignment => 2;


/// <summary>
/// Copies the field data to the destination buffer at the specified offset.
/// </summary>
public override void CopyTo(byte[] dest, int offset)
{
EndianBitConverter.Little.CopyBytes((ushort)Data1, dest, offset);
EndianBitConverter.Little.CopyBytes((ushort)Data2, dest, offset + 2);
EndianBitConverter.Little.CopyBytes(Data3, dest, offset + 4);
EndianBitConverter.Little.CopyBytes(Data4, dest, offset + 6);
EndianBitConverter.Little.CopyBytes(Data5, dest, offset + 8);
EndianBitConverter.Little.CopyBytes(Data6, dest, offset + 10);
}

/// <summary>
/// ToString() override
/// </summary>
/// <returns>
/// A <see cref="string" />
/// </returns>
public override string ToString()
{
return $"Data1 {Data1}, Data2 {Data2}, Data3 {Data3}, Data4 {Data4}, Data5 {Data5}, Data6 {Data6}";
}
}

public class McsRadioTapField : RadioTapField
{
/// <summary>
/// Indicates which information is known
/// </summary>
public RadioTapMcsKnown Known { get; set; }

/// <summary>
/// Indicates which information is known
/// </summary>
public RadioTapMcsFlags Flags { get; set; }

public byte Mcs { get; set; }
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment?


/// <summary>
/// Constructor
/// </summary>
/// <param name="br">
/// A <see cref="BinaryReader" />
/// </param>
public McsRadioTapField(BinaryReader br)
{
Known = (RadioTapMcsKnown)br.ReadByte();
Flags = (RadioTapMcsFlags)br.ReadByte();
Mcs = br.ReadByte();
}


/// <summary>
/// Initializes a new instance of the <see cref="McsRadioTapField" /> class.
/// </summary>
public McsRadioTapField()
{ }

/// <summary>
/// Initializes a new instance of the <see cref="McsRadioTapField" /> class.
/// <param name="known">Known information</param>
/// <param name="flags">MCS Flags</param>
/// <param name="mcs">Known information</param>
/// </summary>
public McsRadioTapField(RadioTapMcsKnown known, RadioTapMcsFlags flags, byte mcs)
{
Known = known;
Flags = flags;
Mcs = mcs;
}

/// <summary>Type of the field</summary>
public override RadioTapType FieldType => RadioTapType.Mcs;

/// <summary>
/// Gets the length of the field data.
/// </summary>
/// <value>
/// The length.
/// </value>
public override ushort Length => 3;

/// <summary>
///
/// </summary>
/// <value>The alignment.</value>
public override ushort Alignment => 1;


Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Formatting, best reformat this entire file.

/// <summary>
/// Copies the field data to the destination buffer at the specified offset.
/// </summary>
public override void CopyTo(byte[] dest, int offset)
{
EndianBitConverter.Little.CopyBytes((byte)Known, dest, offset);
EndianBitConverter.Little.CopyBytes((byte)Flags, dest, offset + 1);
EndianBitConverter.Little.CopyBytes((byte)Mcs, dest, offset + 2);
}

/// <summary>
/// ToString() override
/// </summary>
/// <returns>
/// A <see cref="string" />
/// </returns>
public override string ToString()
{
return $"Known {Known}, Flags {Flags}, Mcs {Mcs}";
}
}

/// <summary>
/// Channel field
/// </summary>
Expand Down Expand Up @@ -1528,6 +1828,18 @@ public static RadioTapField Parse(int bitIndex, BinaryReader br)
{
return new RxFlagsRadioTapField(br);
}
case RadioTapType.Mcs:
{
return new McsRadioTapField(br);
}
case RadioTapType.HighEfficiency:
{
return new HighEfficiencyRadioTapField(br);
}
case RadioTapType.VeryHighThroughput:
{
return new VeryHighThroughputRadioTapField(br);
}
default:
{
//the RadioTap fields are extendable so there may be some we dont know about
Expand Down
34 changes: 34 additions & 0 deletions PacketDotNet/Ieee80211/RadioTapHighEfficiencyData1.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/*
This file is part of PacketDotNet.

This Source Code Form is subject to the terms of the Mozilla Public
License, v. 2.0. If a copy of the MPL was not distributed with this
file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
/*
* Copyright 2010 Chris Morgan <[email protected]>
*/
jerkerolofsson marked this conversation as resolved.
Show resolved Hide resolved

using System;

namespace PacketDotNet.Ieee80211;

[Flags]
public enum RadioTapHighEfficiencyData1 : ushort
{
HePpduFormat = 0x0003,
BssColorKnown = 0x0004,
BeamChangeKnown = 0x0008,
UlDlDown = 0x0010,
DataMcsKnown = 0x0020,
DataDcmKnown = 0x0040,
CodingKnown = 0x0080,
LdpcExtraSymbolSegmentKnown = 0x0100,
StbcKnown = 0x0200,
SpatialReuseKnownKnown = 0x0400,
SpatialReuse2KnownKnown = 0x0800,
SpatialReuse3KnownKnown = 0x1000,
SpatialReuse4KnownKnown = 0x2000,
DataBwRuAllocationKnown = 0x4000,
DopplerKnown = 0x8000,
}
34 changes: 34 additions & 0 deletions PacketDotNet/Ieee80211/RadioTapHighEfficiencyData2.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/*
This file is part of PacketDotNet.

This Source Code Form is subject to the terms of the Mozilla Public
License, v. 2.0. If a copy of the MPL was not distributed with this
file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
/*
* Copyright 2010 Chris Morgan <[email protected]>
*/

using System;

namespace PacketDotNet.Ieee80211;

[Flags]
public enum RadioTapHighEfficiencyData2 : ushort
{
PriSec80MHzKnown = 0x0001,
GiKnown = 0x0002,
NumberOfLtfSymbolsKnown = 0x0004,
PreFecPaddingFactorKnown = 0x0008,
TxbfKnown = 0x0010,
PeDisambiguityKnown = 0x0020,
TxopKnown = 0x0040,
MidamblePeriodicityKnown = 0x0080,
RuAllocationOffset = 0x3f00,
RuAllocationOffsetKnown = 0x4000,

/// <summary>
/// 0 = primary, 1 = secondary
/// </summary>
PriSec80MHz = 0x8000,
}
Loading
Loading