diff --git a/CMakeLists.txt b/CMakeLists.txt index 8b933c8..930f78b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -194,6 +194,11 @@ set(EHS_SOURCES src/io/socket/ehc/NetClientCh.cpp src/io/socket/ehc/NetServerCh.cpp src/io/socket/ehc/NetUtils.cpp + src/io/socket/BaseICMP.cpp + include/ehs/io/socket/ICMP_LNX.h + src/io/socket/ICMP_LNX.cpp + include/ehs/io/socket/ICMP.h + src/io/socket/ICMP_LNX.cpp ) if (IS_OS_WINDOWS) @@ -257,7 +262,8 @@ endif() #message("${CMAKE_CXX_FLAGS}") add_library(EHS_Stc STATIC ${EHS_SOURCES}) -add_library(EHS_Dyn SHARED ${EHS_SOURCES}) +add_library(EHS_Dyn SHARED ${EHS_SOURCES} + include/ehs/io/socket/BaseICMP.h) add_executable(StrToHash src/StrToHash.cpp) target_compile_definitions(EHS_Dyn PRIVATE EHS_LIB_EXPORT) diff --git a/include/ehs/Array.h b/include/ehs/Array.h index 9ebd3c8..404daac 100644 --- a/include/ehs/Array.h +++ b/include/ehs/Array.h @@ -12,7 +12,7 @@ namespace ehs /// @tparam T Array data type to use. /// @tparam N Number data type to use. template - class Array : public BaseObj + class Array { protected: T* data; @@ -20,7 +20,7 @@ namespace ehs public: /// Frees any data created on the heap. - ~Array() override + ~Array() { delete[] data; } @@ -29,7 +29,6 @@ namespace ehs Array() : data(nullptr), size(0) { - AddType("Array"); } /// Initializes an empty array with the given size. @@ -37,7 +36,6 @@ namespace ehs explicit Array(const N size) : data(new T[size]), size(size) { - AddType("Array"); } /// Initializes this array with an initializer list object. @@ -45,8 +43,6 @@ namespace ehs Array(std::initializer_list list) : data(new T[list.size()]), size(list.size()) { - AddType("Array"); - N i = 0; for (auto v = list.begin(); v != list.end(); ++v) data[i++] = std::move(*v); @@ -58,14 +54,12 @@ namespace ehs Array(const T* const data, const N size) : data(new T[size]), size(size) { - AddType("Array"); - for (N i = 0; i < size; ++i) this->data[i] = data[i]; } Array(Array&& array) noexcept - : BaseObj(array), data(array.data), size(array.size) + : data(array.data), size(array.size) { array.data = nullptr; array.size = 0; @@ -74,7 +68,7 @@ namespace ehs /// Copies all members from the given array object. /// @param [in] array The array object to copy from. Array(const Array& array) - : BaseObj((BaseObj&&)array), data(new T[array.size]), size(array.size) + : data(new T[array.size]), size(array.size) { for (N i = 0; i < size; ++i) data[i] = array.data[i]; @@ -85,8 +79,6 @@ namespace ehs if (this == &array) return *this; - BaseObj::operator=((BaseObj&&)array); - delete[] data; data = array.data; size = array.size; @@ -105,8 +97,6 @@ namespace ehs if (this == &array) return *this; - BaseObj::operator=(array); - delete[] data; data = new T[array.size]; for (N i = 0; i < array.size; ++i) diff --git a/include/ehs/Serializer.h b/include/ehs/Serializer.h index 859195d..d80dcee 100644 --- a/include/ehs/Serializer.h +++ b/include/ehs/Serializer.h @@ -21,7 +21,7 @@ namespace ehs { template - class Serializer : public BaseObj + class Serializer { private: Endianness endianness; @@ -30,7 +30,7 @@ namespace ehs N offset; public: - ~Serializer() override + ~Serializer() { delete[] data; } @@ -38,32 +38,27 @@ namespace ehs Serializer() : endianness(Endianness::BE), data(nullptr), size(0), offset(0) { - AddType("Serializer"); } Serializer(const Endianness endianness) : endianness(endianness), data(nullptr), size(0), offset(0) { - AddType("Serializer"); } Serializer(const Endianness endianness, const N size) : endianness(endianness), data(new Byte[size]), size(size), offset(0) { - AddType("Serializer"); } Serializer(const Endianness endianness, const Byte* const data, const N size, const N offset = 0) : endianness(endianness), data(new Byte[size]), size(size), offset(offset) { - AddType("Serializer"); - for (N i = 0; i < size; ++i) this->data[i] = data[i]; } Serializer(Serializer&& serializer) noexcept - : BaseObj((BaseObj&&)serializer), endianness(serializer.endianness), data(serializer.data), + : endianness(serializer.endianness), data(serializer.data), size(serializer.size), offset(serializer.offset) { serializer.data = nullptr; @@ -72,7 +67,7 @@ namespace ehs } Serializer(const Serializer& serializer) - : BaseObj(serializer), endianness(serializer.endianness), data(new Byte[serializer.size]), + : endianness(serializer.endianness), data(new Byte[serializer.size]), size(serializer.size), offset(serializer.offset) { for (N i = 0; i < serializer.size; ++i) @@ -84,8 +79,6 @@ namespace ehs if (this == &serializer) return *this; - BaseObj::operator=((Serializer&&)serializer); - endianness = serializer.endianness; delete[] data; data = serializer.data; @@ -104,8 +97,6 @@ namespace ehs if (this == &serializer) return *this; - BaseObj::operator=(serializer); - endianness = serializer.endianness; delete[] data; @@ -1228,7 +1219,7 @@ namespace ehs void Resize(const N newSize) { Byte* result = new Byte[newSize]; - Util::Copy(result, data, size); + Util::Copy(result, data, newSize >= size ? size : newSize); delete[] data; data = result; size = newSize; diff --git a/include/ehs/Str.h b/include/ehs/Str.h index 23b4a9e..e1dfb8a 100644 --- a/include/ehs/Str.h +++ b/include/ehs/Str.h @@ -25,7 +25,7 @@ namespace ehs /// @tparam T The character's data type to use. /// @tparam N The number data type to use. template - class Str : public BaseObj + class Str { private: N size; @@ -33,7 +33,7 @@ namespace ehs public: /// Frees any data created on the heap. - ~Str() override + ~Str() { delete[] data; } @@ -42,7 +42,6 @@ namespace ehs Str() : size(0), data(nullptr) { - AddType("Str"); } /// Initializes members with given C-style string. @@ -56,8 +55,6 @@ namespace ehs Util::Copy(data, str, Size(true)); data[this->size] = 0; - - AddType("Str"); } /// Initializes members with given C-style string. @@ -70,8 +67,6 @@ namespace ehs Util::Copy(data, str, Size(true)); data[size] = 0; - - AddType("Str"); } /// Initializes string with the given size. @@ -80,13 +75,11 @@ namespace ehs : size(size), data(new T[size + 1]) { data[size] = 0; - - AddType("Str"); } /// A move constructor. Str(Str&& str) noexcept - : BaseObj((BaseObj&&)str), size(str.size), data(str.data) + : size(str.size), data(str.data) { str.size = 0; str.data = nullptr; @@ -95,7 +88,7 @@ namespace ehs /// Copies all members from the given string object. /// @param [in] str The string object to copy from. Str(const Str& str) - : BaseObj(str), size(str.size), data(new T[size + 1]) + : size(str.size), data(new T[size + 1]) { Util::Copy(data, str.data, Size(true)); @@ -107,8 +100,6 @@ namespace ehs if (this == &str) return *this; - BaseObj::operator=((BaseObj&&)str); - size = str.size; delete[] data; data = str.data; @@ -127,8 +118,6 @@ namespace ehs if (&str == this) return *this; - BaseObj::operator=(str); - size = str.size; delete[] data; diff --git a/include/ehs/Vector.h b/include/ehs/Vector.h index 5b09473..7f66afb 100644 --- a/include/ehs/Vector.h +++ b/include/ehs/Vector.h @@ -14,7 +14,7 @@ namespace ehs /// @tparam N Number data type to use. /// @note If extra memory is set to five then each time that memory is filled it will add five extra. template - class Vector : public BaseObj + class Vector { protected: N rawSize; @@ -24,7 +24,7 @@ namespace ehs public: /// Frees any data created on the heap. - ~Vector() override + ~Vector() { delete[] data; } @@ -33,7 +33,6 @@ namespace ehs Vector() : rawSize(0), size(0), stride(5), data(nullptr) { - AddType("Vector"); } /// Initializes members for pre-allocated memory to write to later. @@ -42,7 +41,6 @@ namespace ehs Vector(const N size, const N stride) : rawSize(size + stride), size(size), stride(stride), data(new T[rawSize]) { - AddType("Vector"); } /// Initializes this vector with an initializer list object. @@ -51,8 +49,6 @@ namespace ehs Vector(std::initializer_list list, const N stride = 5) : rawSize(0), size(list.size()), stride(stride), data(nullptr) { - AddType("Vector"); - if (stride) { rawSize = list.size() / stride * stride; @@ -78,8 +74,6 @@ namespace ehs Vector(const T* data, const N size, const N stride) : rawSize(0), size(size), stride(stride), data(nullptr) { - AddType("Vector"); - if (stride) { rawSize = size / stride * stride; @@ -100,14 +94,14 @@ namespace ehs /// Copies all members from the given vector object. /// @param [in] vec The vector object to copy from. Vector(const Vector& vec) - : BaseObj(vec), rawSize(vec.rawSize), size(vec.size), stride(vec.stride), data(new T[rawSize]) + : rawSize(vec.rawSize), size(vec.size), stride(vec.stride), data(new T[rawSize]) { for (N i = 0; i < size; ++i) data[i] = vec.data[i]; } Vector(Vector&& vec) noexcept - : BaseObj((BaseObj&&)vec), rawSize(vec.rawSize), size(vec.size), stride(vec.stride), data(vec.data) + : rawSize(vec.rawSize), size(vec.size), stride(vec.stride), data(vec.data) { vec.rawSize = 0; vec.size = 0; @@ -123,8 +117,6 @@ namespace ehs if (this == &vec) return *this; - BaseObj::operator=(vec); - rawSize = vec.rawSize; size = vec.size; stride = vec.stride; @@ -143,8 +135,6 @@ namespace ehs if (this == &vec) return *this; - BaseObj::operator=((BaseObj&&)vec); - rawSize = vec.rawSize; size = vec.size; stride = vec.stride; diff --git a/include/ehs/io/socket/BaseICMP.h b/include/ehs/io/socket/BaseICMP.h new file mode 100644 index 0000000..ab5acdd --- /dev/null +++ b/include/ehs/io/socket/BaseICMP.h @@ -0,0 +1,53 @@ +#pragma once + +#include "ehs/Serializer.h" +#include "ehs/Types.h" +#include "ehs/io/socket/Socket.h" + +namespace ehs +{ + struct ICMP_Header + { + UInt_8 type; + UInt_8 code; + UInt_16 checksum; + }; + + struct ICMP_EchoRequest + { + UInt_16 id; + UInt_16 sequence; + }; + + class BaseICMP + { + private: + IP version; + + public: + BaseICMP(); + + BaseICMP(IP version); + + BaseICMP(BaseICMP &&icmp) noexcept; + + BaseICMP(const BaseICMP &icmp); + + BaseICMP &operator=(BaseICMP &&icmp) noexcept; + + BaseICMP &operator=(const BaseICMP &icmp); + + virtual UInt_64 Send(const Str_8 &address, ICMP_Header header, const Byte *data, UInt_64 size); + + virtual UInt_64 Receive(Str_8 &address, ICMP_Header header, Serializer &data); + + void SendEchoRequest(const Str_8 &address, ICMP_EchoRequest er, const Byte *data, UInt_64 size); + + virtual void SetReceiveTimeout(UInt_64 timeout); + + virtual bool IsValid() const; + + protected: + static UInt_16 ComputeChecksum(UInt_16 *buffer, Size length); + }; +} diff --git a/include/ehs/io/socket/ICMP.h b/include/ehs/io/socket/ICMP.h new file mode 100644 index 0000000..a6ed5cb --- /dev/null +++ b/include/ehs/io/socket/ICMP.h @@ -0,0 +1,7 @@ +#pragma once + +#ifdef EHS_OS_WINDOWS +#include "BaseICMP.h" +#else +#include "ICMP_LNX.h" +#endif \ No newline at end of file diff --git a/include/ehs/io/socket/ICMP_LNX.h b/include/ehs/io/socket/ICMP_LNX.h new file mode 100644 index 0000000..eb255fc --- /dev/null +++ b/include/ehs/io/socket/ICMP_LNX.h @@ -0,0 +1,33 @@ +#pragma once + +#include "BaseICMP.h" + +namespace ehs +{ + class ICMP : public BaseICMP + { + private: + Int_32 hdl; + + public: + ICMP(); + + ICMP(IP version); + + ICMP(ICMP &&icmp) noexcept; + + ICMP(const ICMP &icmp); + + ICMP &operator=(ICMP &&icmp) noexcept; + + ICMP &operator=(const ICMP &icmp); + + UInt_64 Send(const Str_8 &address, ICMP_Header header, const Byte *data, UInt_64 size) override; + + UInt_64 Receive(Str_8 &address, ICMP_Header header, Serializer &data) override; + + void SetReceiveTimeout(UInt_64 timeout) override; + + bool IsValid() const override; + }; +} \ No newline at end of file diff --git a/include/ehs/system/CPU.h b/include/ehs/system/CPU.h index 2d39d0d..e512fca 100644 --- a/include/ehs/system/CPU.h +++ b/include/ehs/system/CPU.h @@ -210,6 +210,8 @@ namespace ehs /// @param[out] input A 48 byte character array representing the brand. static void GetBrand(Char_8* input); + static UInt_8 GetCacheLineSize(); + //static Str_8 ToStr(); private: diff --git a/src/io/socket/BaseICMP.cpp b/src/io/socket/BaseICMP.cpp new file mode 100644 index 0000000..4559e99 --- /dev/null +++ b/src/io/socket/BaseICMP.cpp @@ -0,0 +1,112 @@ +#include "ehs/io/socket/BaseICMP.h" +#include "ehs/Serializer.h" + +#include + +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 &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 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; + } +} diff --git a/src/io/socket/ICMP_LNX.cpp b/src/io/socket/ICMP_LNX.cpp new file mode 100644 index 0000000..5e426fd --- /dev/null +++ b/src/io/socket/ICMP_LNX.cpp @@ -0,0 +1,176 @@ +#include "ehs/io/socket/ICMP_LNX.h" +#include "ehs/Serializer.h" +#include "ehs/Log.h" + +#include +#include +#include + +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 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 &data) + { + if (!IsValid()) + { + EHS_LOG_INT(LogType::WARN, 0, "Socket is not initialized."); + + return 0; + } + + Serializer 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(); + header = payload.Read(); + data = Serializer(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; + } +} diff --git a/src/system/CPU_GCC_AMD64.asm b/src/system/CPU_GCC_AMD64.asm index 8b2592a..52da639 100644 --- a/src/system/CPU_GCC_AMD64.asm +++ b/src/system/CPU_GCC_AMD64.asm @@ -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 \ No newline at end of file