346 lines
12 KiB
C#
346 lines
12 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.Text;
|
|
using MiscUtil.Conversion;
|
|
using PacketDotNet.Utils;
|
|
|
|
namespace PacketDotNet.LLDP
|
|
{
|
|
/// <summary>
|
|
/// A Time to Live TLV
|
|
///
|
|
/// [TLV Type Length : 2][Mgmt Addr length : 1][Mgmt Addr Subtype : 1][Mgmt Addr : 1-31]
|
|
/// [Interface Subtype : 1][Interface number : 4][OID length : 1][OID : 0-128]
|
|
///
|
|
/// </summary>
|
|
public class ManagementAddress : 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>
|
|
/// Number of bytes in the AddressLength field
|
|
/// </summary>
|
|
private const int MgmtAddressLengthLength = 1;
|
|
|
|
/// <summary>
|
|
/// Number of bytes in the interface number subtype field
|
|
/// </summary>
|
|
private const int InterfaceNumberSubTypeLength = 1;
|
|
|
|
/// <summary>
|
|
/// Number of bytes in the interface number field
|
|
/// </summary>
|
|
private const int InterfaceNumberLength = 4;
|
|
|
|
/// <summary>
|
|
/// Number of bytes in the object identifier length field
|
|
/// </summary>
|
|
private const int ObjectIdentifierLengthLength = 1;
|
|
|
|
/// <summary>
|
|
/// Maximum number of bytes in the object identifier field
|
|
/// </summary>
|
|
private const int maxObjectIdentifierLength = 128;
|
|
|
|
#region Constructors
|
|
|
|
/// <summary>
|
|
/// Creates a Management Address TLV
|
|
/// </summary>
|
|
/// <param name="bytes">
|
|
/// The LLDP Data unit being modified
|
|
/// </param>
|
|
/// <param name="offset">
|
|
/// The Management Address TLV's offset from the
|
|
/// origin of the LLDP
|
|
/// </param>
|
|
public ManagementAddress(byte[] bytes, int offset) :
|
|
base(bytes, offset)
|
|
{
|
|
log.Debug("");
|
|
}
|
|
|
|
/// <summary>
|
|
/// Creates a Management Address TLV and sets it value
|
|
/// </summary>
|
|
/// <param name="managementAddress">
|
|
/// The Management Address
|
|
/// </param>
|
|
/// <param name="interfaceSubType">
|
|
/// The Interface Numbering Sub Type
|
|
/// </param>
|
|
/// <param name="ifNumber">
|
|
/// The Interface Number
|
|
/// </param>
|
|
/// <param name="oid">
|
|
/// The Object Identifier
|
|
/// </param>
|
|
public ManagementAddress(NetworkAddress managementAddress,
|
|
InterfaceNumbering interfaceSubType, uint ifNumber,
|
|
string oid)
|
|
{
|
|
log.Debug("");
|
|
|
|
// NOTE: We presume that the mgmt address length and the
|
|
// object identifier length are zero
|
|
var length = TLVTypeLength.TypeLengthLength + MgmtAddressLengthLength +
|
|
InterfaceNumberSubTypeLength + InterfaceNumberLength +
|
|
ObjectIdentifierLengthLength;
|
|
var bytes = new byte[length];
|
|
var offset = 0;
|
|
tlvData = new ByteArraySegment(bytes, offset, length);
|
|
|
|
// The lengths are both zero until the values are set
|
|
AddressLength = 0;
|
|
ObjIdLength = 0;
|
|
|
|
Type = TLVTypes.ManagementAddress;
|
|
|
|
MgmtAddress = managementAddress;
|
|
InterfaceSubType = interfaceSubType;
|
|
InterfaceNumber = ifNumber;
|
|
ObjectIdentifier = oid;
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Properties
|
|
|
|
/// <value>
|
|
/// The Management Address Length
|
|
/// </value>
|
|
public int AddressLength
|
|
{
|
|
get { return (int)tlvData.Bytes[ValueOffset]; }
|
|
internal set { tlvData.Bytes[ValueOffset] = (byte)value; }
|
|
}
|
|
|
|
/// <value>
|
|
/// The Management Address Subtype
|
|
///
|
|
/// Forward to the MgmtAddress instance
|
|
/// </value>
|
|
public AddressFamily AddressSubType
|
|
{
|
|
get { return MgmtAddress.AddressFamily; }
|
|
}
|
|
|
|
/// <value>
|
|
/// The Management Address
|
|
/// </value>
|
|
public NetworkAddress MgmtAddress
|
|
{
|
|
get
|
|
{
|
|
int offset = ValueOffset + MgmtAddressLengthLength;
|
|
|
|
return new NetworkAddress(tlvData.Bytes, offset, AddressLength);
|
|
}
|
|
|
|
set
|
|
{
|
|
var valueLength = value.Length;
|
|
var valueBytes = value.Bytes;
|
|
|
|
// is the new address the same size as the old address?
|
|
if(AddressLength != valueLength)
|
|
{
|
|
// need to resize the tlv and shift data fields down
|
|
var newLength = TLVTypeLength.TypeLengthLength + MgmtAddressLengthLength +
|
|
valueLength +
|
|
InterfaceNumberSubTypeLength +
|
|
InterfaceNumberLength +
|
|
ObjectIdentifierLengthLength +
|
|
ObjIdLength;
|
|
|
|
var newBytes = new byte[newLength];
|
|
|
|
int headerLength = TLVTypeLength.TypeLengthLength + MgmtAddressLengthLength;
|
|
int oldStartOfAfterData = ValueOffset + MgmtAddressLengthLength + AddressLength;
|
|
int newStartOfAfterData = TLVTypeLength.TypeLengthLength + MgmtAddressLengthLength + value.Length;
|
|
int afterDataLength = InterfaceNumberSubTypeLength + InterfaceNumberLength + ObjectIdentifierLengthLength + ObjIdLength;
|
|
|
|
// copy the data before the mgmt address
|
|
Array.Copy(tlvData.Bytes, tlvData.Offset,
|
|
newBytes, 0,
|
|
headerLength);
|
|
|
|
// copy the data over after the mgmt address over
|
|
Array.Copy(tlvData.Bytes, oldStartOfAfterData,
|
|
newBytes, newStartOfAfterData,
|
|
afterDataLength);
|
|
|
|
var offset = 0;
|
|
tlvData = new ByteArraySegment(newBytes, offset, newLength);
|
|
|
|
// update the address length field
|
|
AddressLength = valueLength;
|
|
}
|
|
|
|
// copy the new address into the appropriate position in the byte[]
|
|
Array.Copy(valueBytes, 0,
|
|
tlvData.Bytes, ValueOffset + MgmtAddressLengthLength,
|
|
valueLength);
|
|
}
|
|
}
|
|
|
|
/// <value>
|
|
/// Interface Number Sub Type
|
|
/// </value>
|
|
public InterfaceNumbering InterfaceSubType
|
|
{
|
|
get
|
|
{
|
|
return (InterfaceNumbering)tlvData.Bytes[ValueOffset + MgmtAddressLengthLength + MgmtAddress.Length];
|
|
}
|
|
|
|
set
|
|
{
|
|
tlvData.Bytes[ValueOffset + MgmtAddressLengthLength + MgmtAddress.Length] = (byte)value;
|
|
}
|
|
}
|
|
|
|
private int InterfaceNumberOffset
|
|
{
|
|
get
|
|
{
|
|
return ValueOffset + MgmtAddressLengthLength + AddressLength + InterfaceNumberSubTypeLength;
|
|
}
|
|
}
|
|
|
|
/// <value>
|
|
/// Interface Number
|
|
/// </value>
|
|
public uint InterfaceNumber
|
|
{
|
|
get
|
|
{
|
|
return EndianBitConverter.Big.ToUInt32(tlvData.Bytes,
|
|
InterfaceNumberOffset);
|
|
}
|
|
|
|
set
|
|
{
|
|
EndianBitConverter.Big.CopyBytes(value,
|
|
tlvData.Bytes,
|
|
InterfaceNumberOffset);
|
|
}
|
|
}
|
|
|
|
private int ObjIdLengthOffset
|
|
{
|
|
get
|
|
{
|
|
return InterfaceNumberOffset + InterfaceNumberLength;
|
|
}
|
|
}
|
|
|
|
/// <value>
|
|
/// Object ID Length
|
|
/// </value>
|
|
public byte ObjIdLength
|
|
{
|
|
get
|
|
{
|
|
return tlvData.Bytes[ObjIdLengthOffset];
|
|
}
|
|
|
|
internal set
|
|
{
|
|
tlvData.Bytes[ObjIdLengthOffset] = value;
|
|
}
|
|
}
|
|
|
|
private int ObjectIdentifierOffset
|
|
{
|
|
get { return ObjIdLengthOffset + ObjectIdentifierLengthLength; }
|
|
}
|
|
|
|
/// <value>
|
|
/// Object ID
|
|
/// </value>
|
|
public string ObjectIdentifier
|
|
{
|
|
get
|
|
{
|
|
return UTF8Encoding.UTF8.GetString(tlvData.Bytes, ObjectIdentifierOffset,
|
|
ObjIdLength);
|
|
}
|
|
|
|
set
|
|
{
|
|
byte[] oid = UTF8Encoding.UTF8.GetBytes(value);
|
|
|
|
// check for out-of-range sizes
|
|
if(oid.Length > maxObjectIdentifierLength)
|
|
{
|
|
throw new System.ArgumentOutOfRangeException("ObjectIdentifier", "length > maxObjectIdentifierLength of " + maxObjectIdentifierLength);
|
|
}
|
|
|
|
// does the object identifier length match the existing one?
|
|
if(ObjIdLength != oid.Length)
|
|
{
|
|
var oldLength = TLVTypeLength.TypeLengthLength + MgmtAddressLengthLength +
|
|
AddressLength +
|
|
InterfaceNumberSubTypeLength + InterfaceNumberLength +
|
|
ObjectIdentifierLengthLength;
|
|
var newLength = oldLength + oid.Length;
|
|
|
|
var newBytes = new byte[newLength];
|
|
|
|
// copy the original bytes over
|
|
Array.Copy(tlvData.Bytes, tlvData.Offset,
|
|
newBytes, 0,
|
|
oldLength);
|
|
|
|
var offset = 0;
|
|
tlvData = new ByteArraySegment(newBytes, offset, newLength);
|
|
|
|
// update the length
|
|
ObjIdLength = (byte)value.Length;
|
|
}
|
|
|
|
Array.Copy(oid, 0,
|
|
tlvData.Bytes, ObjectIdentifierOffset,
|
|
oid.Length);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Convert this Management Address TLV to a string.
|
|
/// </summary>
|
|
/// <returns>
|
|
/// A human readable string
|
|
/// </returns>
|
|
public override string ToString ()
|
|
{
|
|
return string.Format("[ManagementAddress: AddressLength={0}, AddressSubType={1}, MgmtAddress={2}, InterfaceSubType={3}, InterfaceNumber={4}, ObjIdLength={5}, ObjectIdentifier={6}]", AddressLength, AddressSubType, MgmtAddress, InterfaceSubType, InterfaceNumber, ObjIdLength, ObjectIdentifier);
|
|
}
|
|
|
|
#endregion
|
|
}
|
|
}
|