using System.Net; using System.Net.NetworkInformation; using System.Net.Sockets; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using Models.Model.Backend; namespace Models.Experimental; public class RawSocket { public static unsafe Socket GetRawSocket(SocketConfig socketConfig) { Socket rawSocket = new Socket(AddressFamily.InterNetwork, SocketType.Raw, (ProtocolType)socketConfig.ProtocolType); rawSocket.ReceiveTimeout = socketConfig.Timeout; rawSocket.SendTimeout = socketConfig.Timeout; rawSocket.Connect(socketConfig.EndPoint); int num = 1; rawSocket.SetRawSocketOption(0, 11, new ReadOnlySpan((void*) &num, 4)); return rawSocket; } public static bool TryGetPingReply(byte[] receiveBuffer, int bytesReceived, ref int ipHeaderLength, out IPStatus reply) { byte num = (byte) (receiveBuffer[0] & 15U); ipHeaderLength = 4 * num; int start = ipHeaderLength; int srcOffset = ipHeaderLength + 8; IcmpHeader icmpHeader = Unsafe.ReadUnaligned(ref MemoryMarshal.GetReference(receiveBuffer.AsSpan(start))); byte[] numArray = new byte[bytesReceived - srcOffset]; Buffer.BlockCopy(receiveBuffer, srcOffset, numArray, 0, numArray.Length); reply = MessageConstant.MapV4TypeToIpStatus(icmpHeader.Type, icmpHeader.Code); return true; } public static unsafe byte[] CreateSendMessageBuffer(IcmpHeader icmpHeader) { int length = sizeof (IcmpHeader); byte[] sendMessageBuffer = new byte[length]; new Span((void*) &icmpHeader, length).CopyTo(new Span(sendMessageBuffer, 0, length)); ushort bufferChecksum = ComputeBufferChecksum(sendMessageBuffer.AsSpan(0)); sendMessageBuffer[2] = (byte) ((uint) bufferChecksum >> 8); sendMessageBuffer[3] = (byte) (bufferChecksum & byte.MaxValue); return sendMessageBuffer; } private static ushort ComputeBufferChecksum(ReadOnlySpan buffer) { uint num1 = 0; for (int index = 0; index < buffer.Length; index += 2) { ushort num2 = (ushort) ((ushort) (buffer[index] << 8 & 65280) | (index + 1 < buffer.Length ? (ushort) (buffer[index + 1] & (uint) byte.MaxValue) : 0)); num1 += num2; } while (num1 >> 16 != 0U) num1 = (num1 & ushort.MaxValue) + (num1 >> 16); return (ushort) ~num1; } } public class SocketConfig { public EndPoint EndPoint; public readonly int Timeout; public readonly CustomProtocolType ProtocolType; public readonly byte[] SendBuffer; public SocketConfig( EndPoint endPoint, int timeout, CustomProtocolType protocolType, byte[] sendBuffer) { EndPoint = endPoint; Timeout = timeout; ProtocolType = protocolType; SendBuffer = sendBuffer; } } public struct IcmpHeader { public byte Type; public byte Code; public ushort HeaderChecksum; public ushort Identifier; public ushort SequenceNumber; }