123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272 |
- // Copyright 2014 Dolphin Emulator Project
- // SPDX-License-Identifier: GPL-2.0-or-later
- #pragma once
- #include <array>
- #include <optional>
- #include <string>
- #include <string_view>
- #include <type_traits>
- #include <vector>
- #include "Common/CommonTypes.h"
- struct sockaddr_in;
- namespace Common
- {
- enum class MACConsumer
- {
- BBA,
- IOS
- };
- enum
- {
- BBA_HARDWARE_TYPE = 1,
- MAC_ADDRESS_SIZE = 6,
- IPV4_HEADER_TYPE = 8
- };
- enum DHCPConst
- {
- MESSAGE_QUERY = 1,
- MESSAGE_REPLY = 2
- };
- using MACAddress = std::array<u8, MAC_ADDRESS_SIZE>;
- constexpr std::size_t IPV4_ADDR_LEN = 4;
- using IPAddress = std::array<u8, IPV4_ADDR_LEN>;
- constexpr IPAddress IP_ADDR_ANY = {0, 0, 0, 0};
- constexpr IPAddress IP_ADDR_BROADCAST = {255, 255, 255, 255};
- constexpr IPAddress IP_ADDR_SSDP = {239, 255, 255, 250};
- constexpr u16 SSDP_PORT = 1900;
- constexpr u16 IPV4_ETHERTYPE = 0x800;
- constexpr u16 ARP_ETHERTYPE = 0x806;
- struct EthernetHeader
- {
- EthernetHeader();
- explicit EthernetHeader(u16 ether_type);
- EthernetHeader(const MACAddress& dest, const MACAddress& src, u16 ether_type);
- u16 Size() const;
- static constexpr std::size_t SIZE = 14;
- MACAddress destination = {};
- MACAddress source = {};
- u16 ethertype = 0;
- };
- static_assert(sizeof(EthernetHeader) == EthernetHeader::SIZE);
- static_assert(std::is_standard_layout_v<EthernetHeader>);
- struct IPv4Header
- {
- IPv4Header();
- IPv4Header(u16 data_size, u8 ip_proto, const sockaddr_in& from, const sockaddr_in& to);
- u16 Size() const;
- u8 DefinedSize() const;
- static constexpr std::size_t SIZE = 20;
- u8 version_ihl = 0;
- u8 dscp_esn = 0;
- u16 total_len = 0;
- u16 identification = 0;
- u16 flags_fragment_offset = 0;
- u8 ttl = 0;
- u8 protocol = 0;
- u16 header_checksum = 0;
- IPAddress source_addr{};
- IPAddress destination_addr{};
- };
- static_assert(sizeof(IPv4Header) == IPv4Header::SIZE);
- static_assert(std::is_standard_layout_v<IPv4Header>);
- struct TCPHeader
- {
- TCPHeader();
- TCPHeader(const sockaddr_in& from, const sockaddr_in& to, u32 seq, const u8* data, u16 length);
- TCPHeader(const sockaddr_in& from, const sockaddr_in& to, u32 seq, u32 ack, u16 flags);
- u8 GetHeaderSize() const;
- u16 Size() const;
- u8 IPProto() const;
- static constexpr std::size_t SIZE = 20;
- u16 source_port = 0;
- u16 destination_port = 0;
- u32 sequence_number = 0;
- u32 acknowledgement_number = 0;
- u16 properties = 0;
- u16 window_size = 0;
- u16 checksum = 0;
- u16 urgent_pointer = 0;
- };
- static_assert(sizeof(TCPHeader) == TCPHeader::SIZE);
- static_assert(std::is_standard_layout_v<TCPHeader>);
- struct UDPHeader
- {
- UDPHeader();
- UDPHeader(const sockaddr_in& from, const sockaddr_in& to, u16 data_length);
- u16 Size() const;
- u8 IPProto() const;
- static constexpr std::size_t SIZE = 8;
- u16 source_port = 0;
- u16 destination_port = 0;
- u16 length = 0;
- u16 checksum = 0;
- };
- static_assert(sizeof(UDPHeader) == UDPHeader::SIZE);
- static_assert(std::is_standard_layout_v<UDPHeader>);
- #pragma pack(push, 1)
- struct ARPHeader
- {
- ARPHeader();
- ARPHeader(u32 from_ip, const MACAddress& from_mac, u32 to_ip, const MACAddress& to_mac);
- u16 Size() const;
- static constexpr std::size_t SIZE = 28;
- u16 hardware_type = 0;
- u16 protocol_type = 0;
- u8 hardware_size = 0;
- u8 protocol_size = 0;
- u16 opcode = 0;
- MACAddress sender_address{};
- u32 sender_ip = 0;
- MACAddress targer_address{};
- u32 target_ip = 0;
- };
- static_assert(sizeof(ARPHeader) == ARPHeader::SIZE);
- #pragma pack(pop)
- struct DHCPBody
- {
- DHCPBody();
- DHCPBody(u32 transaction, const MACAddress& client_address, u32 new_ip, u32 serv_ip);
- static constexpr std::size_t SIZE = 240;
- u8 message_type = 0;
- u8 hardware_type = 0;
- u8 hardware_addr = 0;
- u8 hops = 0;
- u32 transaction_id = 0;
- u16 seconds = 0;
- u16 boot_flag = 0;
- u32 client_ip = 0;
- u32 your_ip = 0;
- u32 server_ip = 0;
- u32 relay_ip = 0;
- MACAddress client_mac{};
- unsigned char padding[10]{};
- unsigned char hostname[0x40]{};
- unsigned char boot_file[0x80]{};
- u8 magic_cookie[4] = {0x63, 0x82, 0x53, 0x63};
- };
- static_assert(sizeof(DHCPBody) == DHCPBody::SIZE);
- struct DHCPPacket
- {
- DHCPPacket();
- DHCPPacket(const std::vector<u8>& data);
- void AddOption(u8 fnc, const std::vector<u8>& params);
- std::vector<u8> Build() const;
- DHCPBody body;
- std::vector<std::vector<u8>> options;
- };
- // The compiler might add 2 bytes after EthernetHeader to enforce 16-bytes alignment
- #pragma pack(push, 1)
- struct ARPPacket
- {
- ARPPacket();
- ARPPacket(const MACAddress& destination, const MACAddress& source);
- std::vector<u8> Build() const;
- u16 Size() const;
- EthernetHeader eth_header;
- ARPHeader arp_header;
- static constexpr std::size_t SIZE = EthernetHeader::SIZE + ARPHeader::SIZE;
- };
- static_assert(sizeof(ARPPacket) == ARPPacket::SIZE);
- #pragma pack(pop)
- struct TCPPacket
- {
- TCPPacket();
- TCPPacket(const MACAddress& destination, const MACAddress& source, const sockaddr_in& from,
- const sockaddr_in& to, u32 seq, u32 ack, u16 flags);
- std::vector<u8> Build() const;
- u16 Size() const;
- EthernetHeader eth_header;
- IPv4Header ip_header;
- TCPHeader tcp_header;
- std::vector<u8> ipv4_options;
- std::vector<u8> tcp_options;
- std::vector<u8> data;
- static constexpr std::size_t MIN_SIZE = EthernetHeader::SIZE + IPv4Header::SIZE + TCPHeader::SIZE;
- };
- struct UDPPacket
- {
- UDPPacket();
- UDPPacket(const MACAddress& destination, const MACAddress& source, const sockaddr_in& from,
- const sockaddr_in& to, const std::vector<u8>& payload);
- std::vector<u8> Build() const;
- u16 Size() const;
- EthernetHeader eth_header;
- IPv4Header ip_header;
- UDPHeader udp_header;
- std::vector<u8> ipv4_options;
- std::vector<u8> data;
- static constexpr std::size_t MIN_SIZE = EthernetHeader::SIZE + IPv4Header::SIZE + UDPHeader::SIZE;
- };
- class PacketView
- {
- public:
- PacketView(const u8* ptr, std::size_t size);
- std::optional<u16> GetEtherType() const;
- std::optional<ARPPacket> GetARPPacket() const;
- std::optional<u8> GetIPProto() const;
- std::optional<TCPPacket> GetTCPPacket() const;
- std::optional<UDPPacket> GetUDPPacket() const;
- private:
- const u8* m_ptr;
- std::size_t m_size;
- };
- struct NetworkErrorState
- {
- int error;
- #ifdef _WIN32
- int wsa_error;
- #endif
- };
- MACAddress GenerateMacAddress(MACConsumer type);
- std::string MacAddressToString(const MACAddress& mac);
- std::optional<MACAddress> StringToMacAddress(std::string_view mac_string);
- u16 ComputeNetworkChecksum(const void* data, u16 length, u32 initial_value = 0);
- u16 ComputeTCPNetworkChecksum(const IPAddress& from, const IPAddress& to, const void* data,
- u16 length, u8 protocol);
- NetworkErrorState SaveNetworkErrorState();
- void RestoreNetworkErrorState(const NetworkErrorState& state);
- const char* DecodeNetworkError(s32 error_code);
- const char* StrNetworkError();
- } // namespace Common
|