mirror of
				https://github.com/esiur/esiur-dotnet.git
				synced 2025-10-31 07:51:36 +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 *************************************/
 | |
| 
 |