First commit for ICMP capabilities, added CPU::GetCacheLineSize(), and removed BaseObj from containers.
This commit is contained in:
112
src/io/socket/BaseICMP.cpp
Normal file
112
src/io/socket/BaseICMP.cpp
Normal file
@@ -0,0 +1,112 @@
|
||||
#include "ehs/io/socket/BaseICMP.h"
|
||||
#include "ehs/Serializer.h"
|
||||
|
||||
#include <netinet/ip.h>
|
||||
|
||||
namespace ehs
|
||||
{
|
||||
|
||||
|
||||
BaseICMP::BaseICMP()
|
||||
: version(IP::V6)
|
||||
{
|
||||
}
|
||||
|
||||
BaseICMP::BaseICMP(const IP version)
|
||||
: version(version)
|
||||
{
|
||||
}
|
||||
|
||||
BaseICMP::BaseICMP(BaseICMP &&icmp) noexcept
|
||||
: version(icmp.version)
|
||||
{
|
||||
}
|
||||
|
||||
BaseICMP::BaseICMP(const BaseICMP &icmp)
|
||||
: version(icmp.version)
|
||||
{
|
||||
}
|
||||
|
||||
BaseICMP & BaseICMP::operator=(BaseICMP &&icmp) noexcept
|
||||
{
|
||||
if (this == &icmp)
|
||||
return *this;
|
||||
|
||||
version = icmp.version;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
BaseICMP & BaseICMP::operator=(const BaseICMP &icmp)
|
||||
{
|
||||
if (this == &icmp)
|
||||
return *this;
|
||||
|
||||
version = icmp.version;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
UInt_64 BaseICMP::Send(const Str_8 &address, ICMP_Header header, const Byte *data, UInt_64 size)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
UInt_64 BaseICMP::Receive(Str_8 &address, ICMP_Header header, Serializer<UInt_64> &data)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void BaseICMP::SendEchoRequest(const Str_8 &address, ICMP_EchoRequest er, const Byte *data, UInt_64 size)
|
||||
{
|
||||
if (!IsValid())
|
||||
{
|
||||
EHS_LOG_INT(LogType::WARN, 0, "Socket is not initialized.");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
ICMP_Header header = {
|
||||
8,
|
||||
0,
|
||||
0
|
||||
};
|
||||
|
||||
Serializer<UInt_64> payload(Endianness::LE);
|
||||
payload.Write(er);
|
||||
payload.Resize(payload.Size() + size);
|
||||
|
||||
Util::Copy(&payload[payload.GetOffset()], data, size);
|
||||
|
||||
payload.SetOffset(payload.GetOffset() + size);
|
||||
|
||||
Send(address, header, &payload[0], payload.Size());
|
||||
}
|
||||
|
||||
void BaseICMP::SetReceiveTimeout(UInt_64 timeout)
|
||||
{
|
||||
}
|
||||
|
||||
bool BaseICMP::IsValid() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
UInt_16 BaseICMP::ComputeChecksum(UInt_16 *buffer, Size length)
|
||||
{
|
||||
Size sum = 0;
|
||||
while (length > 1)
|
||||
{
|
||||
sum += *buffer++;
|
||||
length -= sizeof(UInt_16);
|
||||
}
|
||||
|
||||
if (length == 1)
|
||||
sum += *(UInt_8 *)buffer;
|
||||
|
||||
sum = (sum >> 16) + (sum & 0xffff);
|
||||
sum += (sum >> 16);
|
||||
|
||||
return (UInt_16)~sum;
|
||||
}
|
||||
}
|
176
src/io/socket/ICMP_LNX.cpp
Normal file
176
src/io/socket/ICMP_LNX.cpp
Normal file
@@ -0,0 +1,176 @@
|
||||
#include "ehs/io/socket/ICMP_LNX.h"
|
||||
#include "ehs/Serializer.h"
|
||||
#include "ehs/Log.h"
|
||||
|
||||
#include <arpa/inet.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/ip.h>
|
||||
|
||||
namespace ehs
|
||||
{
|
||||
ICMP::ICMP()
|
||||
: hdl(EHS_INVALID_SOCKET)
|
||||
{
|
||||
}
|
||||
|
||||
ICMP::ICMP(const IP version)
|
||||
: BaseICMP(version)
|
||||
{
|
||||
hdl = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
|
||||
if (hdl < 0)
|
||||
{
|
||||
EHS_LOG_INT(LogType::ERR, 0, "Failed to create ICMP socket with error #" + Str_8::FromNum(errno) + ".");
|
||||
return;
|
||||
}
|
||||
|
||||
EHS_LOG_SUCCESS();
|
||||
}
|
||||
|
||||
ICMP::ICMP(ICMP &&icmp) noexcept
|
||||
: BaseICMP((BaseICMP &&)icmp), hdl(icmp.hdl)
|
||||
{
|
||||
icmp.hdl = EHS_INVALID_SOCKET;
|
||||
}
|
||||
|
||||
ICMP::ICMP(const ICMP &icmp)
|
||||
: BaseICMP(icmp), hdl(icmp.hdl)
|
||||
{
|
||||
}
|
||||
|
||||
ICMP & ICMP::operator=(ICMP &&icmp) noexcept
|
||||
{
|
||||
if (this == &icmp)
|
||||
return *this;
|
||||
|
||||
BaseICMP::operator=((BaseICMP &&)icmp);
|
||||
|
||||
hdl = icmp.hdl;
|
||||
|
||||
icmp.hdl = EHS_INVALID_SOCKET;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
ICMP & ICMP::operator=(const ICMP &icmp)
|
||||
{
|
||||
if (this == &icmp)
|
||||
return *this;
|
||||
|
||||
BaseICMP::operator=(icmp);
|
||||
|
||||
hdl = icmp.hdl;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
UInt_64 ICMP::Send(const Str_8 &address, ICMP_Header header, const Byte *data, const UInt_64 size)
|
||||
{
|
||||
if (!IsValid())
|
||||
{
|
||||
EHS_LOG_INT(LogType::WARN, 0, "Socket is not initialized.");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
header.checksum = 0;
|
||||
|
||||
Serializer<UInt_64> payload(Endianness::LE);
|
||||
payload.Write(header);
|
||||
payload.Resize(payload.Size() + size);
|
||||
|
||||
Util::Copy(&payload[payload.GetOffset()], data, size);
|
||||
|
||||
payload.SetOffset(payload.GetOffset() + size);
|
||||
|
||||
header.checksum = ComputeChecksum((UInt_16 *)&payload[0], payload.Size());
|
||||
|
||||
payload.SetOffset(0);
|
||||
payload.Write(header);
|
||||
payload.SetOffset(payload.Size());
|
||||
|
||||
sockaddr_in dst_addr = {};
|
||||
dst_addr.sin_family = AF_INET;
|
||||
inet_pton(AF_INET, address, &(dst_addr.sin_addr));
|
||||
|
||||
SInt_64 sent = sendto(hdl, payload, payload.Size(), 0, (sockaddr *)&dst_addr, sizeof(dst_addr));
|
||||
if (sent < 0)
|
||||
{
|
||||
EHS_LOG_INT(LogType::ERR, 0, "Failed to send packet with error #" + Str_8::FromNum(errno) + ".");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
EHS_LOG_SUCCESS();
|
||||
|
||||
return sent;
|
||||
}
|
||||
|
||||
UInt_64 ICMP::Receive(Str_8 &address, ICMP_Header header, Serializer<UInt_64> &data)
|
||||
{
|
||||
if (!IsValid())
|
||||
{
|
||||
EHS_LOG_INT(LogType::WARN, 0, "Socket is not initialized.");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Serializer<UInt_64> payload(Endianness::LE);
|
||||
payload.Resize(1500);
|
||||
|
||||
sockaddr_in remote = {};
|
||||
socklen_t from_len = sizeof(remote);
|
||||
|
||||
SInt_64 recv = recvfrom(hdl, payload, 1500, 0, (sockaddr *)&remote, &from_len);
|
||||
if (recv < 0)
|
||||
{
|
||||
int code = errno;
|
||||
if (code == EAGAIN)
|
||||
EHS_LOG_SUCCESS();
|
||||
else
|
||||
EHS_LOG_INT(LogType::ERR, 0, "Failed to receive packet with error #" + Str_8::FromNum(code) + ".");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
payload.Resize(recv);
|
||||
|
||||
char tmpAddr[INET_ADDRSTRLEN];
|
||||
|
||||
if (!inet_ntop(remote.sin_family, &remote.sin_addr, tmpAddr, INET_ADDRSTRLEN))
|
||||
{
|
||||
EHS_LOG_INT(LogType::ERR, 1, "Failed to convert IPv4 address with error #" + Str_8::FromNum(errno) + ".");
|
||||
|
||||
return recv;
|
||||
}
|
||||
|
||||
address = tmpAddr;
|
||||
iphdr ipHeader = payload.Read<iphdr>();
|
||||
header = payload.Read<ICMP_Header>();
|
||||
data = Serializer<UInt_64>(payload.GetEndianness(), &payload[payload.GetOffset()], payload.Size() - payload.GetOffset());
|
||||
|
||||
EHS_LOG_SUCCESS();
|
||||
|
||||
return recv;
|
||||
}
|
||||
|
||||
void ICMP::SetReceiveTimeout(UInt_64 timeout)
|
||||
{
|
||||
timeval result = {};
|
||||
result.tv_sec = (long)timeout;
|
||||
result.tv_usec = 0;
|
||||
|
||||
if (setsockopt(hdl, SOL_SOCKET, SO_RCVTIMEO, &result, sizeof(result)) < 0)
|
||||
{
|
||||
EHS_LOG_INT(LogType::WARN, 0, "Failed to set receive timeout with error #" + Str_8::FromNum(errno) + ".");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
EHS_LOG_SUCCESS();
|
||||
}
|
||||
|
||||
bool ICMP::IsValid() const
|
||||
{
|
||||
return hdl != EHS_INVALID_SOCKET;
|
||||
}
|
||||
}
|
@@ -7,6 +7,7 @@ global _ZN3ehs3CPU19GetExtFeatureBits_1Ev
|
||||
global _ZN3ehs3CPU19GetExtFeatureBits_2Ev
|
||||
global _ZN3ehs3CPU19GetExtFeatureBits_3Ev
|
||||
global _ZN3ehs3CPU8GetBrandEPc
|
||||
global _ZN3ehs3CPU16GetCacheLineSizeEv
|
||||
|
||||
section .text
|
||||
_ZN3ehs3CPU6RDTSCPEPNS_3TSCE:
|
||||
@@ -129,4 +130,17 @@ section .text
|
||||
|
||||
POP RBX
|
||||
|
||||
RET
|
||||
|
||||
_ZN3ehs3CPU16GetCacheLineSizeEv:
|
||||
PUSH RBX
|
||||
|
||||
MOV EAX, 0x80000006
|
||||
CPUID
|
||||
|
||||
XOR EAX, EAX
|
||||
MOV AL, CL
|
||||
|
||||
POP RBX
|
||||
|
||||
RET
|
Reference in New Issue
Block a user