Skip to content

Commit

Permalink
Implement Ieee 802.1Q vlan tag support and unit test
Browse files Browse the repository at this point in the history
  • Loading branch information
chmorgan committed Jan 14, 2013
1 parent f7405d6 commit 89f1e05
Show file tree
Hide file tree
Showing 8 changed files with 398 additions and 1 deletion.
3 changes: 3 additions & 0 deletions PacketDotNet/EthernetPacket.cs
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,9 @@ internal static PacketOrByteArraySegment ParseEncapsulatedBytes(ByteArraySegment
case EthernetPacketType.WakeOnLan:
payloadPacketOrData.ThePacket = new WakeOnLanPacket(payload);
break;
case EthernetPacketType.VLanTaggedFrame:
payloadPacketOrData.ThePacket = new Ieee8021QPacket(payload);
break;
default: // consider the sub-packet to be a byte array
payloadPacketOrData.TheByteArraySegment = payload;
break;
Expand Down
42 changes: 42 additions & 0 deletions PacketDotNet/Ieee8021QFields.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/*
This file is part of PacketDotNet
PacketDotNet is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
PacketDotNet is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with PacketDotNet. If not, see <http://www.gnu.org/licenses/>.
*/
/*
* Copyright 2013 Chris Morgan <[email protected]>
*/
namespace PacketDotNet
{
/// <summary> 802.1Q fields </summary>
public class Ieee8021QFields
{
/// <summary> Length of the ethertype value in bytes.</summary>
public readonly static int TypeLength = 2;
/// <summary> Length of the tag control information in bytes. </summary>
public readonly static int TagControlInformationLength = 2;
/// <summary> Position of the tag control information </summary>
public readonly static int TagControlInformationPosition = 0;
/// <summary> Position of the type field </summary>
public readonly static int TypePosition;
/// <summary> Length in bytes of a Ieee8021Q header.</summary>
public readonly static int HeaderLength; // 4

static Ieee8021QFields()
{
TypePosition = TagControlInformationPosition + TagControlInformationLength;
HeaderLength = TypePosition + TypeLength;
}
}
}
226 changes: 226 additions & 0 deletions PacketDotNet/Ieee8021QPacket.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,226 @@
/*
This file is part of PacketDotNet
PacketDotNet is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
PacketDotNet is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with PacketDotNet. If not, see <http://www.gnu.org/licenses/>.
*/
/*
* Copyright 2013 Chris Morgan <[email protected]>
*/
using System;
using System.Collections.Generic;
using System.Text;
using MiscUtil.Conversion;
using PacketDotNet.Utils;

namespace PacketDotNet
{
/// <summary>
/// 802.1Q vlan packet
/// http://en.wikipedia.org/wiki/IEEE_802.1Q
/// </summary>
[Serializable]
public class Ieee8021QPacket : InternetPacket
{
/// <value>
/// Type of packet that this vlan packet encapsulates
/// </value>
public virtual EthernetPacketType Type
{
get
{
return (EthernetPacketType)EndianBitConverter.Big.ToInt16(header.Bytes,
header.Offset + Ieee8021QFields.TypePosition);
}

set
{
Int16 val = (Int16)value;
EndianBitConverter.Big.CopyBytes(val,
header.Bytes,
header.Offset + Ieee8021QFields.TypePosition);
}
}

/// <summary>
/// Gets or sets the priority control point.
/// </summary>
/// <value>
/// The priority control point.
/// </value>
public IeeeP8021PPriorities PriorityControlPoint
{
get
{
var tci = TagControlInformation;
tci >>= (16 - 3); // priority is the upper 3 bits
return (IeeeP8021PPriorities)tci;
}

set
{
var tci = TagControlInformation;

// mask the existing Priority off and then back in from value
ushort val = (ushort)value;
tci = (ushort)((tci & 0x1FFF) | ((val & 0x7) << (16 - 3)));
TagControlInformation = tci;
}
}

/// <summary>
/// Gets or sets a value indicating whether this instance canonical format indicator.
/// </summary>
/// <value>
/// <c>true</c> if the mac address is in non-canonical format <c>false</c> if otherwise.
/// </value>
public bool CanonicalFormatIndicator
{
get
{
var tci = TagControlInformation;
tci >>= 12;
return ((tci & 0x1) == 1) ? true : false;
}

set
{
var tci = TagControlInformation;

// mask the existing CFI off and then back in from value
int val = ((value == true) ? 1 : 0);
tci = (ushort)((tci & 0xEFFF) | (val << 12));
TagControlInformation = tci;
}
}

/// <summary>
/// Gets or sets the VLAN identifier.
/// </summary>
/// <value>
/// The VLAN identifier.
/// </value>
public ushort VLANIdentifier
{
get
{
var tci = TagControlInformation;
return (ushort)(tci & 0xFFF);
}

set
{
var tci = TagControlInformation;

// mask the existing vlan id off
tci = (ushort)((tci & 0xF000) | (value & 0xFFF));
TagControlInformation = tci;
}
}

private ushort TagControlInformation
{
get
{
return (ushort)EndianBitConverter.Big.ToInt16(header.Bytes,
header.Offset + Ieee8021QFields.TagControlInformationPosition);
}

set
{
Int16 val = (Int16)value;
EndianBitConverter.Big.CopyBytes(val,
header.Bytes,
header.Offset + Ieee8021QFields.TagControlInformationPosition);
}
}

/// <summary> Fetch ascii escape sequence of the color associated with this packet type.</summary>
override public System.String Color
{
get
{
return AnsiEscapeSequences.LightCyan;
}
}

/// <summary>
/// Constructor
/// </summary>
/// <param name="bas">
/// A <see cref="ByteArraySegment"/>
/// </param>
public Ieee8021QPacket(ByteArraySegment bas)
{
// set the header field, header field values are retrieved from this byte array
header = new ByteArraySegment(bas);
header.Length = Ieee8021QFields.HeaderLength;

// parse the payload via an EthernetPacket method
payloadPacketOrData = EthernetPacket.ParseEncapsulatedBytes(header,
Type);
}

/// <summary cref="Packet.ToString(StringOutputType)" />
public override string ToString(StringOutputType outputFormat)
{
var buffer = new StringBuilder();
string color = "";
string colorEscape = "";

if(outputFormat == StringOutputType.Colored || outputFormat == StringOutputType.VerboseColored)
{
color = Color;
colorEscape = AnsiEscapeSequences.Reset;
}

if(outputFormat == StringOutputType.Normal || outputFormat == StringOutputType.Colored)
{
// build the output string
buffer.AppendFormat("{0}[Ieee8021QPacket: PriorityControlPoint={2}, CanonicalFormatIndicator={3}, Type={4}]{1}",
color,
colorEscape,
PriorityControlPoint,
CanonicalFormatIndicator,
Type);
}

if(outputFormat == StringOutputType.Verbose || outputFormat == StringOutputType.VerboseColored)
{
// collect the properties and their value
Dictionary<string,string> properties = new Dictionary<string,string>();
properties.Add("priority", PriorityControlPoint + " (0x" + PriorityControlPoint.ToString("x") + ")");
properties.Add("canonical format indicator", CanonicalFormatIndicator.ToString());
properties.Add("type", Type.ToString() + " (0x" + Type.ToString("x") + ")");
properties.Add ("VLANIdentifier", VLANIdentifier.ToString () + " (0x" + VLANIdentifier.ToString ("x") + ")");

// calculate the padding needed to right-justify the property names
int padLength = Utils.RandomUtils.LongestStringLength(new List<string>(properties.Keys));

// build the output string
buffer.AppendLine("Ieee802.1Q: ******* Ieee802.1Q - \"VLan tag\" - offset=? length=" + TotalPacketLength);
buffer.AppendLine("Ieee802.1Q:");
foreach (var property in properties)
{
buffer.AppendLine("Ieee802.1Q: " + property.Key.PadLeft(padLength) + " = " + property.Value);
}
buffer.AppendLine("Ieee802.1Q:");
}

// append the base string output
buffer.Append(base.ToString(outputFormat));

return buffer.ToString();
}
}
}
63 changes: 63 additions & 0 deletions PacketDotNet/IeeeP8021PPriorities.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/*
This file is part of PacketDotNet
PacketDotNet is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
PacketDotNet is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with PacketDotNet. If not, see <http://www.gnu.org/licenses/>.
*/
/*
* Copyright 2013 Chris Morgan <[email protected]>
*/
using System;

namespace PacketDotNet
{
/// <summary>
/// Ieee p8021 P priorities.
/// http://en.wikipedia.org/wiki/IEEE_802.1p
/// </summary>
public enum IeeeP8021PPriorities : byte
{
/// <summary>
/// Background
/// </summary>
Background_0 = 1,
/// <summary>
/// Best effort
/// </summary>
BestEffort_1 = 0,
/// <summary>
/// Excellent effort
/// </summary>
ExcellentEffort_2 = 2,
/// <summary>
/// Critical application
/// </summary>
CriticalApplications_3 = 3,
/// <summary>
/// Video, &lt; 100ms latency and jitter
/// </summary>
Video_4 = 4,
/// <summary>
/// Voice, &lt; 10ms latency and jitter
/// </summary>
Voice_5 = 5,
/// <summary>
/// Internetwork control
/// </summary>
InternetworkControl_6 = 6,
/// <summary>
/// Network control
/// </summary>
NetworkControl_7 = 7
}
}
5 changes: 4 additions & 1 deletion PacketDotNet/PacketDotNet.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -187,14 +187,17 @@
<Compile Include="Ieee80211\PpiPacket.cs" />
<Compile Include="Ieee80211\AckFrame.cs" />
<Compile Include="Ieee80211\CtsFrame.cs" />
<Compile Include="Ieee8021QPacket.cs" />
<Compile Include="Ieee8021QFields.cs" />
<Compile Include="IeeeP8021PPriorities.cs" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<ItemGroup />
<ProjectExtensions>
<MonoDevelop>
<Properties>
<Policies>
<TextStylePolicy FileWidth="120" RemoveTrailingWhitespace="True" inheritsSet="VisualStudio" inheritsScope="text/plain" />
<TextStylePolicy FileWidth="120" inheritsSet="VisualStudio" inheritsScope="text/plain" />
</Policies>
</Properties>
</MonoDevelop>
Expand Down
Binary file added Test/CaptureFiles/802.1q_vlan_ipv4_tcp.pcap
Binary file not shown.
Loading

0 comments on commit 89f1e05

Please sign in to comment.