91 lines
3.1 KiB
C#
91 lines
3.1 KiB
C#
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<byte>((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<IcmpHeader>(ref MemoryMarshal.GetReference<byte>(receiveBuffer.AsSpan<byte>(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<byte>((void*) &icmpHeader, length).CopyTo(new Span<byte>(sendMessageBuffer, 0, length));
|
|
ushort bufferChecksum = ComputeBufferChecksum(sendMessageBuffer.AsSpan<byte>(0));
|
|
sendMessageBuffer[2] = (byte) ((uint) bufferChecksum >> 8);
|
|
sendMessageBuffer[3] = (byte) (bufferChecksum & byte.MaxValue);
|
|
return sendMessageBuffer;
|
|
}
|
|
|
|
private static ushort ComputeBufferChecksum(ReadOnlySpan<byte> 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;
|
|
} |