368 lines
11 KiB
C#
368 lines
11 KiB
C#
/*
|
|
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 2010 Evan Plaice <evanplaice@gmail.com>
|
|
* Copyright 2010 Chris Morgan <chmorgan@gmail.com>
|
|
*/
|
|
using System;
|
|
using System.Net;
|
|
using System.Net.NetworkInformation;
|
|
using PacketDotNet.Utils;
|
|
|
|
namespace PacketDotNet.LLDP
|
|
{
|
|
/// <summary>
|
|
/// A Chassis ID TLV
|
|
/// </summary>
|
|
public class ChassisID : TLV
|
|
{
|
|
// NOTE: No need to warn about lack of use, the compiler won't
|
|
// put any calls to 'log' here but we need 'log' to exist to compile
|
|
#pragma warning disable 0169, 0649
|
|
private static readonly ILogInactive log;
|
|
#pragma warning restore 0169, 0649
|
|
|
|
/// <summary>
|
|
/// Length of the sub type field in bytes
|
|
/// </summary>
|
|
private const int SubTypeLength = 1;
|
|
|
|
#region Constructors
|
|
|
|
/// <summary>
|
|
/// Creates a Chassis ID TLV by parsing a byte[]
|
|
/// </summary>
|
|
/// <param name="bytes">
|
|
/// </param>
|
|
/// <param name="offset">
|
|
/// The Chassis ID TLV's offset from the
|
|
/// origin of the LLDP
|
|
/// </param>
|
|
public ChassisID(byte[] bytes, int offset) :
|
|
base(bytes, offset)
|
|
{
|
|
log.Debug("");
|
|
}
|
|
|
|
/// <summary>
|
|
/// Creates a Chassis ID TLV and sets it value
|
|
/// </summary>
|
|
/// <param name="subType">
|
|
/// The ChassisID subtype
|
|
/// </param>
|
|
/// <param name="subTypeValue">
|
|
/// The subtype's value
|
|
/// </param>
|
|
public ChassisID(ChassisSubTypes subType, object subTypeValue)
|
|
{
|
|
log.DebugFormat("subType {0}", subType);
|
|
|
|
EmptyTLVDataInit();
|
|
|
|
Type = TLVTypes.ChassisID;
|
|
|
|
SubType = subType;
|
|
|
|
// method will resize the tlv
|
|
SubTypeValue = subTypeValue;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Create a ChassisID given a mac address
|
|
/// </summary>
|
|
/// <param name="MACAddress">
|
|
/// A <see cref="PhysicalAddress"/>
|
|
/// </param>
|
|
public ChassisID(PhysicalAddress MACAddress)
|
|
{
|
|
log.DebugFormat("MACAddress {0}", MACAddress.ToString());
|
|
|
|
EmptyTLVDataInit();
|
|
|
|
Type = TLVTypes.ChassisID;
|
|
SubType = ChassisSubTypes.MACAddress;
|
|
|
|
SubTypeValue = MACAddress;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Create a ChassisID given an interface name
|
|
/// http://tools.ietf.org/search/rfc2863 page 38
|
|
/// </summary>
|
|
/// <param name="InterfaceName">
|
|
/// A <see cref="System.String"/>
|
|
/// </param>
|
|
public ChassisID(string InterfaceName)
|
|
{
|
|
log.DebugFormat("InterfaceName {0}", InterfaceName);
|
|
|
|
EmptyTLVDataInit();
|
|
|
|
Type = TLVTypes.ChassisID;
|
|
SubType = ChassisSubTypes.InterfaceName;
|
|
|
|
SetSubTypeValue(InterfaceName);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Properties
|
|
|
|
/// <value>
|
|
/// The type of the TLV subtype
|
|
/// </value>
|
|
public ChassisSubTypes SubType
|
|
{
|
|
get
|
|
{
|
|
return (ChassisSubTypes)tlvData.Bytes[ValueOffset];
|
|
}
|
|
|
|
set
|
|
{
|
|
// set the subtype
|
|
tlvData.Bytes[ValueOffset] = (byte)value;
|
|
}
|
|
}
|
|
|
|
/// <value>
|
|
/// The TLV subtype value
|
|
/// </value>
|
|
public object SubTypeValue
|
|
{
|
|
get { return GetSubTypeValue(); }
|
|
set { SetSubTypeValue(value); }
|
|
}
|
|
|
|
/// <summary>
|
|
/// If SubType is ChassisComponent
|
|
/// </summary>
|
|
public byte[] ChassisComponent
|
|
{
|
|
get { return (byte[])GetSubTypeValue(); }
|
|
set
|
|
{
|
|
SubType = ChassisSubTypes.ChassisComponent;
|
|
SetSubTypeValue(value);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// If SubType is InterfaceName the interface name
|
|
/// </summary>
|
|
public string InterfaceName
|
|
{
|
|
get { return (string)GetSubTypeValue(); }
|
|
set
|
|
{
|
|
SubType = ChassisSubTypes.InterfaceName;
|
|
SetSubTypeValue(value);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// If SubType is MACAddress the mac address
|
|
/// </summary>
|
|
public PhysicalAddress MACAddress
|
|
{
|
|
get { return (PhysicalAddress)GetSubTypeValue(); }
|
|
set
|
|
{
|
|
SubType = ChassisSubTypes.MACAddress;
|
|
SetSubTypeValue(value);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// If SubType is NetworkAddress the network address
|
|
/// </summary>
|
|
public LLDP.NetworkAddress NetworkAddress
|
|
{
|
|
get { return (LLDP.NetworkAddress)GetSubTypeValue(); }
|
|
set
|
|
{
|
|
SubType = ChassisSubTypes.NetworkAddress;
|
|
SetSubTypeValue(value);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// If SubType is PortComponent
|
|
/// </summary>
|
|
public byte[] PortComponent
|
|
{
|
|
get { return (byte[])GetSubTypeValue(); }
|
|
set
|
|
{
|
|
SubType = ChassisSubTypes.PortComponent;
|
|
SetSubTypeValue(value);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// If SubType is InterfaceAlias
|
|
/// </summary>
|
|
public byte[] InterfaceAlias
|
|
{
|
|
get { return (byte[])GetSubTypeValue(); }
|
|
set
|
|
{
|
|
SubType = ChassisSubTypes.InterfaceAlias;
|
|
SetSubTypeValue(value);
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Methods
|
|
|
|
/// <summary>
|
|
/// Helper method to reduce duplication in type specific constructors
|
|
/// </summary>
|
|
private void EmptyTLVDataInit()
|
|
{
|
|
var length = TLVTypeLength.TypeLengthLength + SubTypeLength;
|
|
var bytes = new byte[length];
|
|
int offset = 0;
|
|
tlvData = new ByteArraySegment(bytes, offset, length);
|
|
}
|
|
|
|
private object GetSubTypeValue()
|
|
{
|
|
byte[] val;
|
|
int dataOffset = ValueOffset + SubTypeLength;
|
|
int dataLength = Length - SubTypeLength;
|
|
|
|
switch (SubType)
|
|
{
|
|
case ChassisSubTypes.ChassisComponent:
|
|
case ChassisSubTypes.InterfaceAlias:
|
|
case ChassisSubTypes.LocallyAssigned:
|
|
case ChassisSubTypes.PortComponent:
|
|
val = new byte[dataLength];
|
|
Array.Copy(tlvData.Bytes, dataOffset,
|
|
val, 0,
|
|
dataLength);
|
|
return val;
|
|
case ChassisSubTypes.NetworkAddress:
|
|
return new NetworkAddress(tlvData.Bytes,
|
|
dataOffset,
|
|
dataLength);
|
|
case ChassisSubTypes.MACAddress:
|
|
val = new byte[dataLength];
|
|
Array.Copy(tlvData.Bytes, dataOffset,
|
|
val, 0,
|
|
dataLength);
|
|
return new PhysicalAddress(val);
|
|
case ChassisSubTypes.InterfaceName:
|
|
return System.Text.ASCIIEncoding.ASCII.GetString(tlvData.Bytes, dataOffset, dataLength);
|
|
default:
|
|
throw new ArgumentOutOfRangeException();
|
|
}
|
|
}
|
|
|
|
private void SetSubTypeValue(object val)
|
|
{
|
|
byte[] valBytes;
|
|
|
|
// make sure we have the correct type
|
|
switch (SubType)
|
|
{
|
|
case ChassisSubTypes.ChassisComponent:
|
|
case ChassisSubTypes.InterfaceAlias:
|
|
case ChassisSubTypes.LocallyAssigned:
|
|
case ChassisSubTypes.PortComponent:
|
|
if(!(val is byte[]))
|
|
{
|
|
throw new ArgumentOutOfRangeException("expected byte[] for type");
|
|
}
|
|
|
|
valBytes = (byte[])val;
|
|
|
|
SetSubTypeValue(valBytes);
|
|
break;
|
|
case ChassisSubTypes.NetworkAddress:
|
|
if(!(val is NetworkAddress))
|
|
{
|
|
throw new ArgumentOutOfRangeException("expected NetworkAddress instance for NetworkAddress");
|
|
}
|
|
|
|
valBytes = ((NetworkAddress)val).Bytes;
|
|
|
|
SetSubTypeValue(valBytes);
|
|
break;
|
|
case ChassisSubTypes.InterfaceName:
|
|
if(!(val is string))
|
|
{
|
|
throw new ArgumentOutOfRangeException("expected string for InterfaceName");
|
|
}
|
|
|
|
var interfaceName = (string)val;
|
|
|
|
valBytes = System.Text.ASCIIEncoding.ASCII.GetBytes(interfaceName);
|
|
|
|
SetSubTypeValue(valBytes);
|
|
break;
|
|
case ChassisSubTypes.MACAddress:
|
|
if(!(val is PhysicalAddress))
|
|
{
|
|
throw new ArgumentOutOfRangeException("expected PhysicalAddress for MACAddress");
|
|
}
|
|
|
|
var physicalAddress = (PhysicalAddress)val;
|
|
|
|
SetSubTypeValue(physicalAddress.GetAddressBytes());
|
|
break;
|
|
default:
|
|
throw new ArgumentOutOfRangeException();
|
|
}
|
|
}
|
|
|
|
private void SetSubTypeValue(byte[] subTypeValue)
|
|
{
|
|
// is the length different than the current length?
|
|
if(subTypeValue.Length != Length)
|
|
{
|
|
var headerLength = TLVTypeLength.TypeLengthLength + SubTypeLength;
|
|
var newTlvMemory = new byte[headerLength + subTypeValue.Length];
|
|
|
|
// copy the header data over
|
|
Array.Copy(tlvData.Bytes, tlvData.Offset, newTlvMemory, 0, headerLength);
|
|
|
|
// update the tlv memory pointer, offset and length
|
|
tlvData = new ByteArraySegment(newTlvMemory, 0, newTlvMemory.Length);
|
|
}
|
|
|
|
Array.Copy(subTypeValue, 0, tlvData.Bytes, ValueOffset + SubTypeLength,
|
|
subTypeValue.Length);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Convert this Chassis ID TLV to a string.
|
|
/// </summary>
|
|
/// <returns>
|
|
/// A human readable string
|
|
/// </returns>
|
|
public override string ToString ()
|
|
{
|
|
return string.Format("[ChassisID: SubType={0}, SubTypeValue={1}]", SubType, SubTypeValue);
|
|
}
|
|
|
|
#endregion
|
|
}
|
|
}
|