mirror of
https://github.com/esiur/esiur-dotnet.git
synced 2025-05-06 11:32:59 +00:00
368 lines
13 KiB
C#
368 lines
13 KiB
C#
|
|
/********************************************************************************\
|
|
* Uruky Project *
|
|
* *
|
|
* Copyright (C) 2006 Ahmed Zamil - ahmed@dijlh.com *
|
|
* http://www.dijlh.com *
|
|
* *
|
|
* Permission is hereby granted, free of charge, to any person obtaining a copy *
|
|
* of this software and associated documentation files (the "Software"), to deal *
|
|
* in the Software without restriction, including without limitation the rights *
|
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell *
|
|
* copies of the Software, and to permit persons to whom the Software is *
|
|
* furnished to do so, subject to the following conditions: *
|
|
* *
|
|
* The above copyright notice and this permission notice shall be included in all *
|
|
* copies or substantial portions of the Software. *
|
|
* *
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE *
|
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER *
|
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, *
|
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE *
|
|
* SOFTWARE. *
|
|
* *
|
|
* File: Packet.cs *
|
|
* Description: Ethernet/ARP/IPv4/TCP/UDP Packet Decoding & Encoding Class *
|
|
* Compatibility: .Net Framework 2.0 / Mono 1.1.8 *
|
|
* *
|
|
\********************************************************************************/
|
|
|
|
|
|
|
|
using System;
|
|
using System.Text;
|
|
using Esiur.Misc;
|
|
using Esiur.Net.DataLink;
|
|
using System.Net.NetworkInformation;
|
|
using Esiur.Data;
|
|
|
|
namespace Esiur.Net.Packets;
|
|
internal static class Functions
|
|
{
|
|
public static void AddData(ref byte[] dest, byte[] src)
|
|
{
|
|
int I = 0;
|
|
if (src == null)
|
|
{
|
|
return;
|
|
}
|
|
if (dest != null)
|
|
{
|
|
I = dest.Length;
|
|
Array.Resize(ref dest, dest.Length + src.Length);
|
|
//dest = (byte[])Resize(dest, dest.Length + src.Length);
|
|
}
|
|
else
|
|
{
|
|
dest = new byte[src.Length];
|
|
}
|
|
Array.Copy(src, 0, dest, I, src.Length);
|
|
}
|
|
|
|
/*
|
|
public static Array Resize(Array array, int newSize)
|
|
{
|
|
Type myType = Type.GetType(array.GetType().FullName.TrimEnd('[', ']'));
|
|
Array nA = Array.CreateInstance(myType, newSize);
|
|
Array.Copy(array, nA, (newSize > array.Length ? array.Length : newSize));
|
|
return nA;
|
|
} */
|
|
|
|
//Computes the checksum used in IP, ARP..., ie the
|
|
// "The 16 bit one's complement of the one 's complement sum
|
|
//of all 16 bit words" as seen in RFCs
|
|
// Returns a 4 characters hex string
|
|
// data's lenght must be multiple of 4, else zero padding
|
|
public static ushort IP_CRC16(byte[] data)
|
|
{
|
|
ulong Sum = 0;
|
|
bool Padding = false;
|
|
/// * Padding if needed
|
|
if (data.Length % 2 != 0)
|
|
{
|
|
Array.Resize(ref data, data.Length + 1);
|
|
//data = (byte[])Resize(data, data.Length + 1);
|
|
Padding = true;
|
|
}
|
|
int count = data.Length;
|
|
///* add 16-bit words */
|
|
while (count > 0) //1)
|
|
{
|
|
///* this is the inner loop */
|
|
Sum += GetInteger(data[count - 2], data[count - 1]);
|
|
///* Fold 32-bit sum to 16-bit */
|
|
while (Sum >> 16 != 0)
|
|
{
|
|
Sum = (Sum & 0XFFFF) + (Sum >> 16);
|
|
}
|
|
count -= 2;
|
|
}
|
|
/// * reverse padding
|
|
if (Padding)
|
|
{
|
|
Array.Resize(ref data, data.Length - 1);
|
|
//data = (byte[])Resize(data, data.Length - 1);
|
|
}
|
|
///* Return one's compliment of final sum.
|
|
//return (ushort)(ushort.MaxValue - (ushort)Sum);
|
|
return (ushort)(~Sum);
|
|
}
|
|
|
|
public static ushort GetInteger(byte B1, byte B2)
|
|
{
|
|
return BitConverter.ToUInt16(new byte[] { B2, B1 }, 0);
|
|
//return System.Convert.ToUInt16("&h" + GetHex(B1) + GetHex(B2));
|
|
}
|
|
|
|
public static uint GetLong(byte B1, byte B2, byte B3, byte B4)
|
|
{
|
|
return BitConverter.ToUInt32(new byte[] { B4, B3, B2, B1 }, 0);
|
|
//return System.Convert.ToUInt32("&h" + GetHex(B1) + GetHex(B2) + GetHex(B3) + GetHex(B4));
|
|
}
|
|
|
|
public static string GetHex(byte B)
|
|
{
|
|
return (((B < 15) ? 0 + System.Convert.ToString(B, 16).ToUpper() : System.Convert.ToString(B, 16).ToUpper()));
|
|
}
|
|
|
|
public static bool GetBit(uint B, byte Pos)
|
|
{
|
|
//return BitConverter.ToBoolean(BitConverter.GetBytes(B), Pos + 1);
|
|
return (B & (uint)(Math.Pow(2, (Pos - 1)))) == (Math.Pow(2, (Pos - 1)));
|
|
}
|
|
|
|
public static ushort RemoveBit(ushort I, byte Pos)
|
|
{
|
|
return (ushort)RemoveBit((uint)I, Pos);
|
|
}
|
|
|
|
public static uint RemoveBit(uint I, byte Pos)
|
|
{
|
|
if (GetBit(I, Pos))
|
|
{
|
|
return I - (uint)(Math.Pow(2, (Pos - 1)));
|
|
}
|
|
else
|
|
{
|
|
return I;
|
|
}
|
|
}
|
|
|
|
public static void SplitInteger(ushort I, ref byte BLeft, ref byte BRight)
|
|
{
|
|
byte[] b = BitConverter.GetBytes(I);
|
|
BLeft = b[1];
|
|
BRight = b[0];
|
|
//BLeft = I >> 8;
|
|
//BRight = (I << 8) >> 8;
|
|
}
|
|
|
|
public static void SplitLong(uint I, ref byte BLeft, ref byte BLeftMiddle, ref byte BRightMiddle, ref byte BRight)
|
|
{
|
|
byte[] b = BitConverter.GetBytes(I);
|
|
BLeft = b[3];
|
|
BLeftMiddle = b[2];
|
|
BRightMiddle = b[1];
|
|
BRight = b[0];
|
|
//BLeft = I >> 24;
|
|
//BLeftMiddle = (I << 8) >> 24;
|
|
//BRightMiddle = (I << 16) >> 24;
|
|
//BRight = (I << 24) >> 24;
|
|
}
|
|
|
|
}
|
|
|
|
public class PosixTime
|
|
{
|
|
ulong seconds;
|
|
ulong microseconds;
|
|
|
|
PosixTime(ulong Seconds, ulong Microseconds)
|
|
{
|
|
seconds = Seconds;
|
|
microseconds = Microseconds;
|
|
}
|
|
|
|
public override string ToString()
|
|
{
|
|
return seconds + "." + microseconds;
|
|
}
|
|
}
|
|
|
|
public class Packet
|
|
{
|
|
//public EtherServer2.EthernetSource Source;
|
|
|
|
public PacketSource Source;
|
|
|
|
public DateTime Timestamp;
|
|
|
|
public enum PPPType : ushort
|
|
{
|
|
IP = 0x0021, // Internet Protocol version 4 [RFC1332]
|
|
SDTP = 0x0049, // Serial Data Transport Protocol (PPP-SDTP) [RFC1963]
|
|
IPv6HeaderCompression = 0x004f, // IPv6 Header Compression
|
|
IPv6 = 0x0057, // Internet Protocol version 6 [RFC5072]
|
|
W8021dHelloPacket = 0x0201, // 802.1d Hello Packets [RFC3518]
|
|
IPv6ControlProtocol = 0x8057, // IPv6 Control Protocol [RFC5072]
|
|
}
|
|
|
|
public enum ProtocolType : ushort
|
|
{
|
|
IP = 0x800, // IPv4
|
|
ARP = 0x806, // Address Resolution Protocol
|
|
IPv6 = 0x86DD, // IPv6
|
|
FrameRelayARP = 0x0808, // Frame Relay ARP [RFC1701]
|
|
VINESLoopback = 0x0BAE, // VINES Loopback [RFC1701]
|
|
VINESEcho = 0x0BAF, // VINES ECHO [RFC1701]
|
|
TransEtherBridging = 0x6558, // TransEther Bridging [RFC1701]
|
|
RawFrameRelay = 0x6559, // Raw Frame Relay [RFC1701]
|
|
IEE8021QVLAN = 0x8100, // IEEE 802.1Q VLAN-tagged frames (initially Wellfleet)
|
|
SNMP = 0x814C, // SNMP [JKR1]
|
|
TCPIP_Compression = 0x876B, // TCP/IP Compression [RFC1144]
|
|
IPAutonomousSystems = 0x876C, // IP Autonomous Systems [RFC1701]
|
|
SecureData = 0x876D, // Secure Data [RFC1701]
|
|
PPP = 0x880B, // PPP [IANA]
|
|
MPLS = 0x8847, // MPLS [RFC5332]
|
|
MPLS_UpstreamAssignedLabel = 0x8848, // MPLS with upstream-assigned label [RFC5332]
|
|
PPPoEDiscoveryStage = 0x8863, // PPPoE Discovery Stage [RFC2516]
|
|
PPPoESessionStage = 0x8864, // PPPoE Session Stage [RFC2516]
|
|
}
|
|
|
|
|
|
/*
|
|
public static void GetPacketMACAddresses(Packet packet, out byte[] srcMAC, out byte[] dstMAC)
|
|
{
|
|
|
|
// get the node address
|
|
Packet root = packet.RootPacket;
|
|
if (root is TZSPPacket)
|
|
{
|
|
|
|
TZSPPacket tp = (TZSPPacket)root;
|
|
if (tp.Protocol == TZSPPacket.TZSPEncapsulatedProtocol.Ethernet)
|
|
{
|
|
EthernetPacket ep = (EthernetPacket)tp.SubPacket;
|
|
srcMAC = ep.SourceMAC;
|
|
dstMAC = ep.DestinationMAC;
|
|
}
|
|
else if (tp.Protocol == TZSPPacket.TZSPEncapsulatedProtocol.IEEE802_11)
|
|
{
|
|
W802_11Packet wp = (W802_11Packet)tp.SubPacket;
|
|
srcMAC = wp.SA;
|
|
dstMAC = wp.DA;
|
|
}
|
|
else
|
|
{
|
|
srcMAC = null;
|
|
dstMAC = null;
|
|
}
|
|
}
|
|
else if (root is EthernetPacket)
|
|
{
|
|
EthernetPacket ep = (EthernetPacket)root;
|
|
srcMAC = ep.SourceMAC;
|
|
dstMAC = ep.DestinationMAC;
|
|
}
|
|
else if (root is W802_11Packet)
|
|
{
|
|
W802_11Packet wp = (W802_11Packet)root;
|
|
srcMAC = wp.SA;
|
|
dstMAC = wp.DA;
|
|
}
|
|
else
|
|
{
|
|
srcMAC = null;
|
|
dstMAC = null;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
public static void GetPacketAddresses(Packet packet, ref string srcMAC, ref string dstMAC, ref string srcIP, ref string dstIP)
|
|
{
|
|
|
|
if (packet is TCPv4Packet)
|
|
{
|
|
if (packet.ParentPacket is IPv4Packet)
|
|
{
|
|
IPv4Packet ip = (IPv4Packet)packet.ParentPacket;
|
|
srcIP = ip.SourceIP.ToString();
|
|
dstIP = ip.DestinationIP.ToString();
|
|
}
|
|
}
|
|
|
|
// get the node address
|
|
Packet root = packet.RootPacket;
|
|
if (root is TZSPPacket)
|
|
{
|
|
|
|
TZSPPacket tp = (TZSPPacket)root;
|
|
if (tp.Protocol == TZSPPacket.TZSPEncapsulatedProtocol.Ethernet)
|
|
{
|
|
EthernetPacket ep = (EthernetPacket)tp.SubPacket;
|
|
srcMAC = DC.GetPhysicalAddress(ep.SourceMAC, 0).ToString();
|
|
dstMAC = DC.GetPhysicalAddress(ep.DestinationMAC, 0).ToString();
|
|
}
|
|
else if (tp.Protocol == TZSPPacket.TZSPEncapsulatedProtocol.IEEE802_11)
|
|
{
|
|
W802_11Packet wp = (W802_11Packet)tp.SubPacket;
|
|
srcMAC = DC.GetPhysicalAddress(wp.SA, 0).ToString();
|
|
dstMAC = DC.GetPhysicalAddress(wp.DA, 0).ToString();
|
|
}
|
|
}
|
|
else if (root is EthernetPacket)
|
|
{
|
|
EthernetPacket ep = (EthernetPacket)root;
|
|
srcMAC = DC.GetPhysicalAddress(ep.SourceMAC, 0).ToString();
|
|
dstMAC = DC.GetPhysicalAddress(ep.DestinationMAC, 0).ToString();
|
|
}
|
|
else if (root is W802_11Packet)
|
|
{
|
|
W802_11Packet wp = (W802_11Packet)root;
|
|
srcMAC = DC.GetPhysicalAddress(wp.SA, 0).ToString();
|
|
dstMAC = DC.GetPhysicalAddress(wp.DA, 0).ToString();
|
|
}
|
|
}
|
|
*/
|
|
|
|
//PosixTime Timeval;
|
|
public byte[] Header;
|
|
public byte[] Preamble;
|
|
//public byte[] Payload;
|
|
public byte[] Data;
|
|
|
|
public Packet SubPacket;
|
|
public Packet ParentPacket;
|
|
public virtual long Parse(byte[] data, uint offset, uint ends) { return 0; }
|
|
public virtual bool Compose() { return false; }
|
|
|
|
public Packet RootPacket
|
|
{
|
|
get
|
|
{
|
|
Packet root = this;
|
|
while (root.ParentPacket != null)
|
|
root = root.ParentPacket;
|
|
return root;
|
|
}
|
|
}
|
|
|
|
public Packet LeafPacket
|
|
{
|
|
get
|
|
{
|
|
Packet leaf = this;
|
|
while (leaf.SubPacket != null)
|
|
leaf = leaf.SubPacket;
|
|
return leaf;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/************************************ EOF *************************************/
|
|
|