From 82bb5d99152b1fac5e2ed1542b38b172beddd1da Mon Sep 17 00:00:00 2001 From: Sepalani Date: Tue, 29 Aug 2017 22:14:01 +0100 Subject: NetworkCaptureLogger: PCAP support added Log TCP/UDP read/write with fake packet. --- Source/Core/Common/Network.cpp | 115 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 115 insertions(+) (limited to 'Source/Core/Common/Network.cpp') diff --git a/Source/Core/Common/Network.cpp b/Source/Core/Common/Network.cpp index a928e8e831..c84cf5fd88 100644 --- a/Source/Core/Common/Network.cpp +++ b/Source/Core/Common/Network.cpp @@ -6,6 +6,15 @@ #include #include +#include + +#ifndef _WIN32 +#include +#include +#include +#else +#include +#endif #include @@ -72,4 +81,110 @@ std::optional StringToMacAddress(std::string_view mac_string) return std::make_optional(mac); } + +EthernetHeader::EthernetHeader() = default; + +EthernetHeader::EthernetHeader(u16 ether_type) +{ + ethertype = htons(ether_type); +} + +u16 EthernetHeader::Size() const +{ + return static_cast(SIZE); +} + +IPv4Header::IPv4Header() = default; + +IPv4Header::IPv4Header(u16 data_size, u8 ip_proto, const sockaddr_in& from, const sockaddr_in& to) +{ + version_ihl = 0x45; + total_len = htons(Size() + data_size); + flags_fragment_offset = htons(0x4000); + ttl = 0x40; + protocol = ip_proto; + std::memcpy(&source_addr, &from.sin_addr, IPV4_ADDR_LEN); + std::memcpy(&destination_addr, &to.sin_addr, IPV4_ADDR_LEN); + + header_checksum = htons(ComputeNetworkChecksum(this, Size())); +} + +u16 IPv4Header::Size() const +{ + return static_cast(SIZE); +} + +TCPHeader::TCPHeader() = default; + +TCPHeader::TCPHeader(const sockaddr_in& from, const sockaddr_in& to, u32 seq, const u8* data, + u16 length) +{ + std::memcpy(&source_port, &from.sin_port, 2); + std::memcpy(&destination_port, &to.sin_port, 2); + sequence_number = htonl(seq); + + // TODO: Write flags + // Write data offset + std::memset(&properties, 0x50, 1); + + window_size = 0xFFFF; + + // Compute the TCP checksum with its pseudo header + const u32 source_addr = ntohl(from.sin_addr.s_addr); + const u32 destination_addr = ntohl(to.sin_addr.s_addr); + const u32 initial_value = (source_addr >> 16) + (source_addr & 0xFFFF) + + (destination_addr >> 16) + (destination_addr & 0xFFFF) + IPProto() + + Size() + length; + u32 tcp_checksum = ComputeNetworkChecksum(this, Size(), initial_value); + tcp_checksum += ComputeNetworkChecksum(data, length); + while (tcp_checksum > 0xFFFF) + tcp_checksum = (tcp_checksum >> 16) + (tcp_checksum & 0xFFFF); + checksum = htons(static_cast(tcp_checksum)); +} + +u16 TCPHeader::Size() const +{ + return static_cast(SIZE); +} + +u8 TCPHeader::IPProto() const +{ + return static_cast(IPPROTO_TCP); +} + +UDPHeader::UDPHeader() = default; + +UDPHeader::UDPHeader(const sockaddr_in& from, const sockaddr_in& to, u16 data_length) +{ + std::memcpy(&source_port, &from.sin_port, 2); + std::memcpy(&destination_port, &to.sin_port, 2); + length = htons(Size() + data_length); +} + +u16 UDPHeader::Size() const +{ + return static_cast(SIZE); +} + +u8 UDPHeader::IPProto() const +{ + return static_cast(IPPROTO_UDP); +} + +// Compute the network checksum with a 32-bit accumulator using the +// "Normal" order, see RFC 1071 for more details. +u16 ComputeNetworkChecksum(const void* data, u16 length, u32 initial_value) +{ + u32 checksum = initial_value; + std::size_t index = 0; + const std::string_view data_view{reinterpret_cast(data), length}; + for (u8 b : data_view) + { + const bool is_hi = index++ % 2 == 0; + checksum += is_hi ? b << 8 : b; + } + while (checksum > 0xFFFF) + checksum = (checksum >> 16) + (checksum & 0xFFFF); + return ~static_cast(checksum); +} } // namespace Common -- cgit v1.2.3