From ba425e59caab7832b12522f4fc8233d063935544 Mon Sep 17 00:00:00 2001 From: Alex Date: Sat, 24 Dec 2022 06:24:10 +0200 Subject: [PATCH] =?UTF-8?q?=F0=9F=8E=89Implemented=20networking?= =?UTF-8?q?=F0=9F=8E=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- KThread.cpp | 8 + Network/AddressResolutionProtocol.cpp | 193 +++++++++++++++++++ Network/Checksum.cpp | 14 ++ Network/DynamicHostConfigurationProtocol.cpp | 143 ++++++++++++++ Network/Ethernet.cpp | 116 +++++++++++ Network/InternetControlMessageProtocol.cpp | 42 ++++ Network/InternetProtocol.cpp | 108 +++++++++++ Network/NetworkController.cpp | 182 +++++++++++++++++ Network/NetworkDebugger.cpp | 78 ++++++++ Network/NetworkTimeProtocol.cpp | 21 ++ Network/TransmissionControlProtocol.cpp | 8 + Network/UserDatagramProtocol.cpp | 119 ++++++++++++ include/net/arp.hpp | 89 +++++++++ include/net/dhcp.hpp | 166 ++++++++++++++++ include/net/eth.hpp | 77 ++++++++ include/net/icmpv4.hpp | 54 ++++++ include/net/icmpv6.hpp | 39 ++++ include/net/ipv4.hpp | 115 +++++++++++ include/net/ipv6.hpp | 27 +++ include/net/nc.hpp | 75 +++++++ include/net/net.hpp | 150 ++++++++++++++ include/net/ntp.hpp | 39 ++++ include/net/tcp.hpp | 10 + include/net/udp.hpp | 77 ++++++++ kernel.h | 2 + 25 files changed, 1952 insertions(+) create mode 100644 Network/AddressResolutionProtocol.cpp create mode 100644 Network/Checksum.cpp create mode 100644 Network/DynamicHostConfigurationProtocol.cpp create mode 100644 Network/Ethernet.cpp create mode 100644 Network/InternetControlMessageProtocol.cpp create mode 100644 Network/InternetProtocol.cpp create mode 100644 Network/NetworkController.cpp create mode 100644 Network/NetworkDebugger.cpp create mode 100644 Network/NetworkTimeProtocol.cpp create mode 100644 Network/TransmissionControlProtocol.cpp create mode 100644 Network/UserDatagramProtocol.cpp create mode 100644 include/net/arp.hpp create mode 100644 include/net/dhcp.hpp create mode 100644 include/net/eth.hpp create mode 100644 include/net/icmpv4.hpp create mode 100644 include/net/icmpv6.hpp create mode 100644 include/net/ipv4.hpp create mode 100644 include/net/ipv6.hpp create mode 100644 include/net/nc.hpp create mode 100644 include/net/net.hpp create mode 100644 include/net/ntp.hpp create mode 100644 include/net/tcp.hpp create mode 100644 include/net/udp.hpp diff --git a/KThread.cpp b/KThread.cpp index 1626693..c94b523 100644 --- a/KThread.cpp +++ b/KThread.cpp @@ -13,6 +13,7 @@ Driver::Driver *DriverManager = nullptr; Disk::Manager *DiskManager = nullptr; +NetworkInterfaceManager::NetworkInterface *NIManager = nullptr; void KernelMainThread() { @@ -42,6 +43,11 @@ void KernelMainThread() else KPrint("\eE85230No disk drivers found! Cannot fetch disks!"); + KPrint("Initializing Network Interface Manager..."); + NIManager = new NetworkInterfaceManager::NetworkInterface; + KPrint("Starting Network Interface Manager..."); + NIManager->StartService(); + KPrint("Setting up userspace..."); const char *envp[9] = { @@ -82,6 +88,8 @@ Exit: void KernelShutdownThread(bool Reboot) { + delete NIManager; + if (DriverManager) DriverManager->UnloadAllDrivers(); diff --git a/Network/AddressResolutionProtocol.cpp b/Network/AddressResolutionProtocol.cpp new file mode 100644 index 0000000..8f98d64 --- /dev/null +++ b/Network/AddressResolutionProtocol.cpp @@ -0,0 +1,193 @@ +#include +#include +#include + +#include "../kernel.h" + +namespace NetworkARP +{ + DiscoveredAddress *ARP::ManageDA(DAType Type, InternetProtocol4 IP, MediaAccessControl MAC) + { + // TODO: Compare IPv6 too. + switch (Type) + { + case DA_ADD: + { + DiscoveredAddress *tmp = new DiscoveredAddress; + tmp->IP = IP; + tmp->MAC = MAC; + DiscoveredAddresses.push_back(tmp); + return tmp; + } + case DA_DEL: + { + for (size_t i = 0; i < DiscoveredAddresses.size(); i++) + if (DiscoveredAddresses[i]->IP == IP) + { + DiscoveredAddress *tmp = DiscoveredAddresses[i]; + delete tmp; + DiscoveredAddresses.remove(i); + } + return nullptr; + } + case DA_SEARCH: + { + for (size_t i = 0; i < DiscoveredAddresses.size(); i++) + if (DiscoveredAddresses[i]->IP == IP) + return DiscoveredAddresses[i]; + + return nullptr; + } + case DA_UPDATE: + { + for (size_t i = 0; i < DiscoveredAddresses.size(); i++) + if (DiscoveredAddresses[i]->IP == IP) + { + DiscoveredAddresses[i]->MAC = MAC; + return DiscoveredAddresses[i]; + } + return nullptr; + } + } + return nullptr; + } + + ARP::ARP(NetworkEthernet::Ethernet *Ethernet) : NetworkEthernet::EthernetEvents(NetworkEthernet::TYPE_ARP) + { + netdbg("Initializing."); + this->Ethernet = Ethernet; + } + + ARP::~ARP() + { + } + + MediaAccessControl InvalidMAC = {.Address = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}}; + InternetProtocol4 InvalidIP = {.Address = {0xFF, 0xFF, 0xFF, 0xFF}}; + DiscoveredAddress InvalidRet = {.MAC = InvalidMAC, .IP = InvalidIP}; + + DiscoveredAddress *ARP::Search(InternetProtocol4 TargetIP) + { + DiscoveredAddress *ret = ManageDA(DA_SEARCH, TargetIP, MediaAccessControl()); + if (ret) + return ret; + netdbg("[DA] No address found for %d.%d.%d.%d", TargetIP.Address[0], TargetIP.Address[1], TargetIP.Address[2], TargetIP.Address[3]); + return &InvalidRet; + } + + DiscoveredAddress *ARP::Update(InternetProtocol4 TargetIP, MediaAccessControl TargetMAC) + { + DiscoveredAddress *ret = ManageDA(DA_UPDATE, TargetIP, TargetMAC); + if (ret) + return ret; + warn("[DA] No address found for %d.%d.%d.%d", TargetIP.Address[0], TargetIP.Address[1], TargetIP.Address[2], TargetIP.Address[3]); + return &InvalidRet; + } + + uint48_t ARP::Resolve(InternetProtocol4 IP) + { + netdbg("Resolving %d.%d.%d.%d", IP.Address[3], IP.Address[2], IP.Address[1], IP.Address[0]); + if (IP == 0xFFFFFFFF) + return 0xFFFFFFFFFFFF; + + uint48_t ret = this->Search(IP)->MAC.ToHex(); + netdbg("Resolved %d.%d.%d.%d to %x", IP.Address[3], IP.Address[2], IP.Address[1], IP.Address[0], ret); + + if (ret == 0xFFFFFFFFFFFF) + { + ARPHeader *Header = new ARPHeader; + Header->HardwareType = ARPHardwareType::HTYPE_ETHERNET; + Header->ProtocolType = NetworkEthernet::FrameType::TYPE_IPV4; + Header->HardwareSize = 6; + Header->ProtocolSize = 4; + Header->Operation = ARPOperation::REQUEST; + Header->SenderMAC = Ethernet->GetInterface()->MAC.ToHex(); + Header->SenderIP = Ethernet->GetInterface()->IP.ToHex(); + Header->TargetMAC = 0xFFFFFFFFFFFF; + Header->TargetIP = IP.ToHex(); + Ethernet->Send({.Address = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}}, NetworkEthernet::FrameType::TYPE_ARP, (uint8_t *)Header, sizeof(ARPHeader)); + delete Header; + netdbg("Sent request"); + } + + int RequestTimeout = 10; + debug("Waiting for response"); + while (ret == 0xFFFFFFFFFFFF) + { + ret = this->Search(IP)->MAC.ToHex(); + if (--RequestTimeout == 0) + { + warn("Request timeout."); + return 0; + } + TaskManager->Sleep(5000); + } + + return ret; + } + + void ARP::Broadcast(InternetProtocol4 IP) + { + netdbg("Sending broadcast"); + uint64_t ResolvedMAC = this->Resolve(IP); + ARPHeader *Header = new ARPHeader; + Header->HardwareType = b16(ARPHardwareType::HTYPE_ETHERNET); + Header->ProtocolType = b16(NetworkEthernet::FrameType::TYPE_IPV4); + Header->HardwareSize = b8(0x6); + Header->ProtocolSize = b8(0x4); + Header->Operation = b16(ARPOperation::REQUEST); + Header->SenderMAC = b48(Ethernet->GetInterface()->MAC.ToHex()); + Header->SenderIP = b32(Ethernet->GetInterface()->IP.ToHex()); + Header->TargetMAC = ResolvedMAC; + Header->TargetIP = IP.ToHex(); + Ethernet->Send(MediaAccessControl().FromHex(ResolvedMAC), NetworkEthernet::FrameType::TYPE_ARP, (uint8_t *)Header, sizeof(ARPHeader)); + delete Header; + } + + bool ARP::OnEthernetPacketReceived(uint8_t *Data, uint64_t Length) + { + netdbg("Received packet"); + ARPHeader *Header = (ARPHeader *)Data; + + InternetProtocol4 SenderIPv4; + SenderIPv4.FromHex(b32(Header->SenderIP)); + + if (b16(Header->HardwareType) != ARPHardwareType::HTYPE_ETHERNET || b16(Header->ProtocolType) != NetworkEthernet::FrameType::TYPE_IPV4) + { + warn("[DA] Invalid hardware/protocol type (%d/%d)", Header->HardwareType, Header->ProtocolType); + return false; + } + + if (ManageDA(DA_SEARCH, InternetProtocol4().FromHex(Header->SenderIP), MediaAccessControl().FromHex(Header->SenderMAC)) == nullptr) + { + netdbg("[DA] Discovered new address %d.%d.%d.%d", SenderIPv4.Address[3], SenderIPv4.Address[2], SenderIPv4.Address[1], SenderIPv4.Address[0]); + ManageDA(DA_ADD, InternetProtocol4().FromHex(Header->SenderIP), MediaAccessControl().FromHex(Header->SenderMAC)); + } + else + { + netdbg("[DA] Updated address %d.%d.%d.%d", SenderIPv4.Address[3], SenderIPv4.Address[2], SenderIPv4.Address[1], SenderIPv4.Address[0]); + ManageDA(DA_UPDATE, InternetProtocol4().FromHex(Header->SenderIP), MediaAccessControl().FromHex(Header->SenderMAC)); + } + + switch (b16(Header->Operation)) + { + case ARPOperation::REQUEST: + netdbg("Received request from %d.%d.%d.%d", SenderIPv4.Address[3], SenderIPv4.Address[2], SenderIPv4.Address[1], SenderIPv4.Address[0]); + Header->TargetMAC = Header->SenderMAC; + Header->TargetIP = Header->SenderIP; + Header->SenderMAC = b48(Ethernet->GetInterface()->MAC.ToHex()); + Header->SenderIP = b32(Ethernet->GetInterface()->IP.ToHex()); + Header->Operation = b16(ARPOperation::REPLY); + Ethernet->Send(MediaAccessControl().FromHex(Header->TargetMAC), NetworkEthernet::FrameType::TYPE_ARP, (uint8_t *)Header, sizeof(ARPHeader)); + netdbg("Sent request for %d.%d.%d.%d", SenderIPv4.Address[0], SenderIPv4.Address[1], SenderIPv4.Address[2], SenderIPv4.Address[3]); + break; + case ARPOperation::REPLY: + fixme("Received reply from %d.%d.%d.%d", SenderIPv4.Address[0], SenderIPv4.Address[1], SenderIPv4.Address[2], SenderIPv4.Address[3]); + break; + default: + warn("Invalid operation (%d)", Header->Operation); + break; + } + return false; + } +} diff --git a/Network/Checksum.cpp b/Network/Checksum.cpp new file mode 100644 index 0000000..17321cd --- /dev/null +++ b/Network/Checksum.cpp @@ -0,0 +1,14 @@ +#include + +uint16_t CalculateChecksum(uint16_t *Data, uint64_t Length) +{ + uint16_t *Data16 = (uint16_t *)Data; + uint64_t Checksum = 0; + for (uint64_t i = 0; i < Length / 2; i++) + Checksum += ((Data16[i] & 0xFF00) >> 8) | ((Data16[i] & 0x00FF) << 8); + if (Length % 2) + Checksum += ((uint16_t)((char *)Data16)[Length - 1]) << 8; + while (Checksum & 0xFFFF0000) + Checksum = (Checksum & 0xFFFF) + (Checksum >> 16); + return (uint16_t)(((~Checksum & 0xFF00) >> 8) | ((~Checksum & 0x00FF) << 8)); +} diff --git a/Network/DynamicHostConfigurationProtocol.cpp b/Network/DynamicHostConfigurationProtocol.cpp new file mode 100644 index 0000000..200b8ac --- /dev/null +++ b/Network/DynamicHostConfigurationProtocol.cpp @@ -0,0 +1,143 @@ +#include +#include + +#include "../kernel.h" + +namespace NetworkDHCP +{ + DHCP::DHCP(NetworkUDP::Socket *Socket, NetworkInterfaceManager::DeviceInterface *Interface) + { + netdbg("Initializing."); + this->UDPSocket = Socket; + this->Interface = Interface; + Socket->LocalPort = b16(68); + } + + DHCP::~DHCP() + { + } + + void DHCP::CreatePacket(DHCPHeader *Packet, uint8_t MessageType, uint32_t RequestIP) + { + Packet->Opcode = b8(DHCP_OP_BOOTREQUEST); + Packet->HardwareType = b8(1); + Packet->HardwareAddressLength = b8(6); + Packet->Hops = b8(0); + Packet->TransactionID = b32(DHCP_TRANSACTION_ID); + Packet->Flags = b16(0x40); + uint48_t InterfaceMAC = b48(Interface->MAC.ToHex()); + memcpy(Packet->ClientHardwareAddress, &InterfaceMAC, sizeof(InterfaceMAC)); + + uint8_t *Ptr = Packet->Options; + *((uint32_t *)(Ptr)) = b32(0x63825363); // magic cookie + Ptr += 4; + + *(Ptr++) = DHCP_OPTION_MESSAGE_TYPE; + *(Ptr++) = DHCP_MESSAGE_TYPE_DISCOVER; + *(Ptr++) = MessageType; + + *(Ptr++) = DHCP_OPTION_CLIENT_IDENTIFIER; + *(Ptr++) = 0x07; + *(Ptr++) = 0x01; + memcpy(Ptr, &InterfaceMAC, sizeof(InterfaceMAC)); + Ptr += 6; + + *(Ptr++) = DHCP_OPTION_REQUESTED_IP; + *(Ptr++) = 0x04; + *((uint32_t *)(Ptr)) = b32(0x0a00020e); + memcpy((uint32_t *)(Ptr), &RequestIP, 4); + Ptr += 4; + + *(Ptr++) = DHCP_OPTION_HOST_NAME; + char *HostName = (char *)KERNEL_NAME; + *(Ptr++) = 1 + strlen(HostName); + memcpy(Ptr, HostName, strlen(HostName)); + Ptr += strlen(HostName); + + *(Ptr++) = DHCP_OPTION_PAD; + + *(Ptr++) = DHCP_OPTION_PARAMETER_REQUEST_LIST; + *(Ptr++) = DHCP_OPTION_COOKIE_SERVER; + *(Ptr++) = DHCP_OPTION_SUBNETMASK; + *(Ptr++) = DHCP_OPTION_ROUTER; + *(Ptr++) = DHCP_OPTION_DOMAIN_NAME_SERVER; + *(Ptr++) = DHCP_OPTION_DOMAIN_NAME; + *(Ptr++) = DHCP_OPTION_NETBIOS_NAME_SERVERS; + *(Ptr++) = DHCP_OPTION_NETBIOS_NODE_TYPE; + *(Ptr++) = DHCP_OPTION_NETBIOS_SCOPE; + *(Ptr++) = DHCP_OPTION_MAX_MESSAGE_SIZE; + + *(Ptr++) = DHCP_OPTION_END; + } + + void DHCP::Request() + { + netdbg("Requesting IP address"); + DHCPHeader packet; + memset(&packet, 0, sizeof(DHCPHeader)); + + CreatePacket(&packet, DHCP_MESSAGE_TYPE_DISCOVER, 0x00000000); + this->UDPSocket->SocketUDP->Send(this->UDPSocket, (uint8_t *)&packet, sizeof(DHCPHeader)); + + debug("Waiting for response..."); + int RequestTimeout = 10; + while (!Received) + { + if (--RequestTimeout == 0) + { + warn("Request timeout."); + break; + } + TaskManager->Sleep(5000); + } + } + + void DHCP::Request(InternetProtocol4 IP) + { + netdbg("Requesting IP address %d.%d.%d.%d", IP.Address[0], IP.Address[1], IP.Address[2], IP.Address[3]); + DHCPHeader packet; + memset(&packet, 0, sizeof(DHCPHeader)); + + CreatePacket(&packet, DHCP_MESSAGE_TYPE_REQUEST, IP.ToHex()); + UDPSocket->SocketUDP->Send(UDPSocket, (uint8_t *)&packet, sizeof(DHCPHeader)); + } + + void *DHCP::GetOption(DHCPHeader *Packet, uint8_t Type) + { + uint8_t *Option = Packet->Options + 4; + uint8_t Current = *Option; + while (Current != 0xff) + { + uint8_t OptionLength = *(Option + 1); + if (Current == Type) + return Option + 2; + Option += (2 + OptionLength); + Current = *Option; + } + warn("Option %#x not found", Type); + return nullptr; + } + + void DHCP::OnUDPPacketReceived(NetworkUDP::Socket *Socket, uint8_t *Data, uint64_t Length) + { + DHCPHeader *Packet = (DHCPHeader *)Data; + uint8_t *MessageType = (uint8_t *)GetOption(Packet, DHCP_OPTION_MESSAGE_TYPE); + + switch (*MessageType) + { + case DHCP_OPTION_TIME_OFFSET: + this->Request(InternetProtocol4().FromHex(Packet->YourIP)); + break; + case DHCP_OPTION_NAME_SERVER: + this->IP.FromHex(Packet->YourIP); + this->Gateway.FromHex(*(uint32_t *)GetOption(Packet, DHCP_OPTION_ROUTER)); + this->DomainNameSystem.FromHex(*(uint32_t *)GetOption(Packet, DHCP_OPTION_DOMAIN_NAME_SERVER)); + this->SubNetworkMask.FromHex((*(uint32_t *)GetOption(Packet, DHCP_OPTION_SUBNETMASK))); + this->Received = true; + break; + default: + netdbg("Received unknown message type %#x", *MessageType); + break; + } + } +} diff --git a/Network/Ethernet.cpp b/Network/Ethernet.cpp new file mode 100644 index 0000000..95ddcbe --- /dev/null +++ b/Network/Ethernet.cpp @@ -0,0 +1,116 @@ +#include +#include + +#include "../kernel.h" + +namespace NetworkEthernet +{ + Ethernet::Ethernet(NetworkInterfaceManager::DeviceInterface *Interface) : NetworkInterfaceManager::Events(Interface) { this->Interface = Interface; } + Ethernet::~Ethernet() {} + + void Ethernet::Send(MediaAccessControl MAC, FrameType Type, uint8_t *Data, uint64_t Length) + { + netdbg("ETH: Sending frame type %#x to %02x:%02x:%02x:%02x:%02x:%02x", Type, + MAC.Address[0], MAC.Address[1], MAC.Address[2], + MAC.Address[3], MAC.Address[4], MAC.Address[5]); + uint64_t PacketLength = sizeof(EthernetHeader) + Length; + EthernetPacket *Packet = (EthernetPacket *)kmalloc(PacketLength); + + Packet->Header.DestinationMAC = b48(MAC.ToHex()); + Packet->Header.SourceMAC = b48(this->Interface->MAC.ToHex()); + Packet->Header.Type = b16(Type); + + memcpy(Packet->Data, Data, Length); + NIManager->Send(Interface, (uint8_t *)Packet, PacketLength); + kfree(Packet); + } + + struct EthernetEventHelperStruct + { + EthernetEvents *Ptr; + uint16_t Type; + }; + + Vector RegisteredEvents; + + void Ethernet::Receive(uint8_t *Data, uint64_t Length) + { + EthernetPacket *Packet = (EthernetPacket *)Data; + MediaAccessControl SourceMAC; + SourceMAC.FromHex(b48(Packet->Header.SourceMAC)); + MediaAccessControl DestinationMAC; + DestinationMAC.FromHex(b48(Packet->Header.DestinationMAC)); + + if (b48(Packet->Header.DestinationMAC) == 0xFFFFFFFFFFFF || + b48(Packet->Header.DestinationMAC) == this->Interface->MAC.ToHex()) + { + netdbg("ETH: Received data from %02x:%02x:%02x:%02x:%02x:%02x [Type %#x]", + SourceMAC.Address[0], SourceMAC.Address[1], SourceMAC.Address[2], + SourceMAC.Address[3], SourceMAC.Address[4], SourceMAC.Address[5], b16(Packet->Header.Type)); + + bool Reply = false; + + switch (b16(Packet->Header.Type)) + { + case TYPE_IPV4: + foreach (auto var in RegisteredEvents) + if (var.Type == TYPE_IPV4) + Reply = var.Ptr->OnEthernetPacketReceived((uint8_t *)Packet->Data, Length); + break; + case TYPE_ARP: + foreach (auto var in RegisteredEvents) + if (var.Type == TYPE_ARP) + Reply = var.Ptr->OnEthernetPacketReceived((uint8_t *)Packet->Data, Length); + break; + case TYPE_RARP: + foreach (auto var in RegisteredEvents) + if (var.Type == TYPE_RARP) + Reply = var.Ptr->OnEthernetPacketReceived((uint8_t *)Packet->Data, Length); + break; + case TYPE_IPV6: + foreach (auto var in RegisteredEvents) + if (var.Type == TYPE_IPV6) + Reply = var.Ptr->OnEthernetPacketReceived((uint8_t *)Packet->Data, Length); + break; + default: + warn("ETH: Unknown packet type %#lx", Packet->Header.Type); + break; + } + if (Reply) + { + Packet->Header.DestinationMAC = Packet->Header.SourceMAC; + Packet->Header.SourceMAC = b48(this->Interface->MAC.ToHex()); + } + } + else + { + netdbg("ETH: Type: [%#x] [%02x:%02x:%02x:%02x:%02x:%02x]=>[%02x:%02x:%02x:%02x:%02x:%02x]", b16(Packet->Header.Type), + SourceMAC.Address[0], SourceMAC.Address[1], SourceMAC.Address[2], + SourceMAC.Address[3], SourceMAC.Address[4], SourceMAC.Address[5], + DestinationMAC.Address[0], DestinationMAC.Address[1], DestinationMAC.Address[2], + DestinationMAC.Address[3], DestinationMAC.Address[4], DestinationMAC.Address[5]); + } + } + + void Ethernet::OnInterfaceReceived(NetworkInterfaceManager::DeviceInterface *Interface, uint8_t *Data, uint64_t Length) + { + if (Interface == this->Interface) + this->Receive(Data, Length); + } + + EthernetEvents::EthernetEvents(FrameType Type) + { + FType = Type; + RegisteredEvents.push_back({.Ptr = this, .Type = (uint16_t)Type}); + } + + EthernetEvents::~EthernetEvents() + { + for (uint64_t i = 0; i < RegisteredEvents.size(); i++) + if (RegisteredEvents[i].Ptr == this) + { + RegisteredEvents.remove(i); + return; + } + } +} diff --git a/Network/InternetControlMessageProtocol.cpp b/Network/InternetControlMessageProtocol.cpp new file mode 100644 index 0000000..7315c3a --- /dev/null +++ b/Network/InternetControlMessageProtocol.cpp @@ -0,0 +1,42 @@ +#include +#include +#include + +#include "../kernel.h" + +namespace NetworkICMPv4 +{ + ICMPv4::ICMPv4(NetworkInterfaceManager::DeviceInterface *Interface) { this->Interface = Interface; } + ICMPv4::~ICMPv4() {} + + void ICMPv4::Send(/* ???? */) + { + fixme("Unimplemented"); + } + + void ICMPv4::Receive(ICMPPacket *Packet) + { + if (Packet->Header.Type == ICMPv4Type::TYPE_ECHO) + { + // TODO: This probably doesn't work + netdbg("ICMPv4: Echo Request"); + Packet->Header.Type = ICMPv4Type::TYPE_ECHO_REPLY; + Packet->Header.Code = 0x0; + Packet->Header.Checksum = CalculateChecksum((uint16_t *)Packet, sizeof(ICMPHeader)); + NIManager->Send(this->Interface, (uint8_t *)Packet, sizeof(ICMPHeader) + 0); + } + else + { + netdbg("ICMPv4: Unknown type %d", Packet->Header.Type); + } + } +} + +namespace NetworkICMPv6 +{ + ICMPv6::ICMPv6(NetworkInterfaceManager::DeviceInterface *Interface) { this->Interface = Interface; } + ICMPv6::~ICMPv6() {} + + void ICMPv6::Send(uint8_t *Data, uint64_t Length) { fixme("Unimplemented"); } + void ICMPv6::Receive(uint8_t *Data) { fixme("Unimplemented"); } +} diff --git a/Network/InternetProtocol.cpp b/Network/InternetProtocol.cpp new file mode 100644 index 0000000..29b37aa --- /dev/null +++ b/Network/InternetProtocol.cpp @@ -0,0 +1,108 @@ +#include +#include + +#include "../kernel.h" + +namespace NetworkIPv4 +{ + IPv4::IPv4(NetworkARP::ARP *ARP, NetworkEthernet::Ethernet *Ethernet) : NetworkEthernet::EthernetEvents(NetworkEthernet::TYPE_IPV4) + { + netdbg("IPv4: Initializing."); + this->ARP = ARP; + this->Ethernet = Ethernet; + } + + IPv4::~IPv4() + { + } + + void IPv4::Send(uint8_t *Data, uint64_t Length, uint8_t Protocol, InternetProtocol4 DestinationIP) + { + netdbg("IPv4: Sending %ld bytes to %d.%d.%d.%d", Length, DestinationIP.Address[0], DestinationIP.Address[1], DestinationIP.Address[2], DestinationIP.Address[3]); + IPv4Packet *Packet = (IPv4Packet *)kmalloc(Length + sizeof(IPv4Header)); + + Packet->Header.Version = 4; + Packet->Header.IHL = sizeof(IPv4Header) / 4; + Packet->Header.TypeOfService = 0; + Packet->Header.TotalLength = Length + sizeof(IPv4Header); + Packet->Header.TotalLength = ((Packet->Header.TotalLength & 0xFF00) >> 8) | ((Packet->Header.TotalLength & 0x00FF) << 8); + Packet->Header.Identification = 0; + // Packet->Header.Flags = 0x0; + // Packet->Header.FragmentOffset = 0x0; + Packet->Header.FlagsAndFragmentOffset = 0x0; + Packet->Header.TimeToLive = 64; + Packet->Header.Protocol = Protocol; + Packet->Header.DestinationIP = b32(DestinationIP.ToHex()); + Packet->Header.SourceIP = b32(Ethernet->GetInterface()->IP.ToHex()); + Packet->Header.HeaderChecksum = 0x0; + Packet->Header.HeaderChecksum = CalculateChecksum((uint16_t *)Packet, sizeof(IPv4Header)); + + memcpy(Packet->Data, Data, Length); + InternetProtocol4 DestinationRoute = DestinationIP; + if ((b32(DestinationIP.ToHex()) & SubNetworkMaskIP.ToHex()) != (Packet->Header.SourceIP & SubNetworkMaskIP.ToHex())) + DestinationRoute = SubNetworkMaskIP; + + Ethernet->Send(MediaAccessControl().FromHex(ARP->Resolve(DestinationRoute)), this->GetFrameType(), (uint8_t *)Packet, Length + sizeof(IPv4Header)); + kfree(Packet); + } + + Vector RegisteredEvents; + + bool IPv4::OnEthernetPacketReceived(uint8_t *Data, uint64_t Length) + { + IPv4Packet *Packet = (IPv4Packet *)Data; + netdbg("IPv4: Received %d bytes [Protocol %ld]", Length, Packet->Header.Protocol); + if (Length < sizeof(IPv4Header)) + { + warn("IPv4: Packet too short"); + return false; + } + + bool Reply = false; + + if (Packet->Header.DestinationIP == Ethernet->GetInterface()->IP.ToHex() || Packet->Header.DestinationIP == 0xFFFFFFFF || Ethernet->GetInterface()->IP.ToHex() == 0) + { + uint64_t TotalLength = Packet->Header.TotalLength; + if (TotalLength > Length) + TotalLength = Length; + + foreach (auto Event in RegisteredEvents) + if (Packet->Header.Protocol == Event->GetProtocol()) + if (Event->OnIPv4PacketReceived(InternetProtocol4().FromHex(b32(Packet->Header.SourceIP)), InternetProtocol4().FromHex(b32(Packet->Header.DestinationIP)), (uint8_t *)((uint64_t)Data + 4 * Packet->Header.IHL), TotalLength - 4 * Packet->Header.IHL)) + Reply = true; + } + + if (Reply) + { + uint32_t SwapIP = Packet->Header.DestinationIP; + Packet->Header.DestinationIP = Packet->Header.SourceIP; + Packet->Header.SourceIP = SwapIP; + Packet->Header.TimeToLive = 0x40; + Packet->Header.HeaderChecksum = 0x0; + Packet->Header.HeaderChecksum = CalculateChecksum((uint16_t *)Data, 4 * Packet->Header.TotalLength); + NIManager->Send(Ethernet->GetInterface(), (uint8_t *)Data, Length); + } + return Reply; + } + + IPv4Events::IPv4Events(IPv4Protocols Protocol) + { + this->Protocol = (uint8_t)Protocol; + RegisteredEvents.push_back(this); + } + + IPv4Events::~IPv4Events() + { + for (uint64_t i = 0; i < RegisteredEvents.size(); i++) + if (RegisteredEvents[i] == this) + { + RegisteredEvents.remove(i); + break; + } + } +} + +namespace NetworkIPv6 +{ + +} diff --git a/Network/NetworkController.cpp b/Network/NetworkController.cpp new file mode 100644 index 0000000..c495df2 --- /dev/null +++ b/Network/NetworkController.cpp @@ -0,0 +1,182 @@ +#include +#include +#include +#include +#include +#include +#include + +#include "../kernel.h" + +#include "../DAPI.hpp" +#include "../Fex.hpp" + +namespace NetworkInterfaceManager +{ + Vector RegisteredEvents; + + NetworkInterface::NetworkInterface() + { + mem = new Memory::MemMgr; + if (DriverManager->GetDrivers().size() > 0) + { + foreach (auto Driver in DriverManager->GetDrivers()) + if (((FexExtended *)((uintptr_t)Driver->Address + EXTENDED_SECTION_ADDRESS))->Driver.Type == FexDriverType::FexDriverType_Network) + this->FetchNetworkCards(Driver->DriverUID); + } + else + KPrint("\eE85230No network drivers found! Cannot fetch network cards!"); + + DbgNetwork(); + } + + NetworkInterface::~NetworkInterface() + { + // Stop the network stack + this->StopNetworkStack(); + + // Unregister all events + for (size_t i = 0; i < RegisteredEvents.size(); i++) + RegisteredEvents.remove(i); + + // Delete all interfaces and their callbacks and free the memory + delete mem; + } + + void NetworkInterface::FetchNetworkCards(unsigned long DriverUID) + { + KernelCallback *cb = (KernelCallback *)mem->RequestPages(TO_PAGES(sizeof(KernelCallback))); + memset(cb, 0, sizeof(KernelCallback)); + cb->Reason = FetchReason; + DriverManager->IOCB(DriverUID, (void *)cb); + + DeviceInterface *Iface = (DeviceInterface *)mem->RequestPages(TO_PAGES(sizeof(DeviceInterface))); + strcpy(Iface->Name, cb->NetworkCallback.Fetch.Name); + Iface->ID = this->CardIDs++; + Iface->MAC.FromHex(cb->NetworkCallback.Fetch.MAC); + Iface->DriverCallBackAddress = cb; + Iface->DriverID = DriverUID; + Interfaces.push_back(Iface); + + foreach (auto var in RegisteredEvents) + var->OnInterfaceAdded(Iface); + + debug("Network Card: %s; MAC: %#lx", Iface->Name, Iface->MAC.ToHex()); + } + + void NetworkInterface::StartNetworkStack() + { + TaskManager->GetCurrentThread()->SetPriority(100); + DeviceInterface *DefaultDevice = nullptr; + foreach (auto var in Interfaces) + if (var && var->DriverCallBackAddress) + { + DefaultDevice = var; + break; + } + + if (!DefaultDevice) + error("No network device found!"); + else + { + NetworkEthernet::Ethernet *eth = new NetworkEthernet::Ethernet(DefaultDevice); // Use the first device found as the ethernet device + NetworkARP::ARP *arp = new NetworkARP::ARP(eth); + NetworkIPv4::IPv4 *ipv4 = new NetworkIPv4::IPv4(arp, eth); + NetworkUDP::UDP *udp = new NetworkUDP::UDP(ipv4, DefaultDevice); + NetworkUDP::Socket *DHCP_Socket = udp->Connect({.Address = {0xFF, 0xFF, 0xFF, 0xFF}}, 67); + NetworkDHCP::DHCP *dhcp = new NetworkDHCP::DHCP(DHCP_Socket, DefaultDevice); + udp->Bind(DHCP_Socket, dhcp); + dhcp->Request(); + DefaultDevice->IP = InternetProtocol4().FromHex(b32(dhcp->IP.ToHex())); + ipv4->SubNetworkMaskIP = dhcp->SubNetworkMask; + ipv4->GatewayIP = dhcp->Gateway; + arp->Broadcast(dhcp->Gateway); + trace("IP: %d.%d.%d.%d", dhcp->IP.Address[3], dhcp->IP.Address[2], dhcp->IP.Address[1], dhcp->IP.Address[0]); + trace("SubNetwork Mask: %d.%d.%d.%d", dhcp->SubNetworkMask.Address[3], dhcp->SubNetworkMask.Address[2], dhcp->SubNetworkMask.Address[1], dhcp->SubNetworkMask.Address[0]); + trace("Gateway: %d.%d.%d.%d", dhcp->Gateway.Address[3], dhcp->Gateway.Address[2], dhcp->Gateway.Address[1], dhcp->Gateway.Address[0]); + trace("DNS: %d.%d.%d.%d", dhcp->DomainNameSystem.Address[3], dhcp->DomainNameSystem.Address[2], dhcp->DomainNameSystem.Address[1], dhcp->DomainNameSystem.Address[0]); + + /* TODO: Store everything in an vector and initialize all network cards */ + } + + TaskManager->GetCurrentThread()->SetPriority(1); + CPU::Pause(true); + } + + void NetworkInterface::StopNetworkStack() + { + fixme("Stop network stack"); + } + + ReadFSFunction(NetRead) + { + fixme("Not implemented."); + return Size; + } + + WriteFSFunction(NetWrite) + { + fixme("Not implemented."); + return Size; + } + + void CallStartNetworkStackWrapper() { NIManager->StartNetworkStack(); } + + void NetworkInterface::StartService() + { + this->NetSvcProcess = TaskManager->CreateProcess(nullptr, "Network Service", Tasking::TaskTrustLevel::System); + Vector auxv; + auxv.push_back({.archaux = {.a_type = AT_NULL, .a_un = {.a_val = 0}}}); + this->NetSvcThread = TaskManager->CreateThread(this->NetSvcProcess, (Tasking::IP)CallStartNetworkStackWrapper, nullptr, nullptr, auxv); + } + + void NetworkInterface::DrvSend(unsigned int DriverID, unsigned char *Data, unsigned short Size) + { + foreach (auto var in this->Interfaces) + if (var->DriverID == DriverID) + NIManager->Send(var, Data, Size); + } + + void NetworkInterface::DrvReceive(unsigned int DriverID, unsigned char *Data, unsigned short Size) + { + foreach (auto var in this->Interfaces) + if (var->DriverID == DriverID) + NIManager->Receive(var, Data, Size); + } + + void NetworkInterface::Send(DeviceInterface *Interface, uint8_t *Data, uint64_t Length) + { + void *DataToBeSent = mem->RequestPages(TO_PAGES(Length)); + memcpy(DataToBeSent, Data, Length); + + KernelCallback *cb = (KernelCallback *)Interface->DriverCallBackAddress; + + memset(cb, 0, sizeof(KernelCallback)); + cb->Reason = SendReason; + cb->NetworkCallback.Send.Data = (uint8_t *)DataToBeSent; + cb->NetworkCallback.Send.Length = Length; + DriverManager->IOCB(Interface->DriverID, (void *)cb); + + mem->FreePages(DataToBeSent, TO_PAGES(Length)); + foreach (auto var in RegisteredEvents) + var->OnInterfaceSent(Interface, Data, Length); + } + + void NetworkInterface::Receive(DeviceInterface *Interface, uint8_t *Data, uint64_t Length) + { + foreach (auto var in RegisteredEvents) + var->OnInterfaceReceived(Interface, Data, Length); + } + + Events::Events(DeviceInterface *Interface) { RegisteredEvents.push_back(this); } + + Events::~Events() + { + for (size_t i = 0; i < RegisteredEvents.size(); i++) + if (RegisteredEvents[i] == this) + { + RegisteredEvents.remove(i); + return; + } + } +} diff --git a/Network/NetworkDebugger.cpp b/Network/NetworkDebugger.cpp new file mode 100644 index 0000000..991fe80 --- /dev/null +++ b/Network/NetworkDebugger.cpp @@ -0,0 +1,78 @@ +#include + +/* +TODO: This code is a mess. It needs to be cleaned up. +*/ + +#ifdef DEBUG_NETWORK + +#include +#include +#include "../drivers/serial.h" + +namespace NetDbg +{ + class NETWORK_DEBUG : public NetworkInterfaceManager::Events + { + public: + static inline void print_wrapper(char c, void *unused) { write_serial(COM1, c); } + int vprintf(const char *format, va_list list) { return vfctprintf(print_wrapper, NULL, format, list); } + void WriteRaw(const char *format, ...) + { + va_list args; + va_start(args, format); + vprintf(format, args); + va_end(args); + } + + void DumpData(const char *Description, void *Address, unsigned long Length) + { + WriteRaw("-------------------------------------------------------------------------\n"); + unsigned char *AddressChar = (unsigned char *)Address; + unsigned char Buffer[17]; + unsigned long Iterate; + + if (Description != nullptr) + WriteRaw("%s:\n", Description); + + for (Iterate = 0; Iterate < Length; Iterate++) + { + if ((Iterate % 16) == 0) + { + if (Iterate != 0) + WriteRaw(" %s\n", Buffer); + WriteRaw(" %04x ", Iterate); + } + + WriteRaw(" %02x", AddressChar[Iterate]); + + if ((AddressChar[Iterate] < 0x20) || (AddressChar[Iterate] > 0x7e)) + Buffer[Iterate % 16] = '.'; + else + Buffer[Iterate % 16] = AddressChar[Iterate]; + + Buffer[(Iterate % 16) + 1] = '\0'; + } + + while ((Iterate % 16) != 0) + { + WriteRaw(" "); + Iterate++; + } + + WriteRaw(" %s\n", Buffer); + WriteRaw("-------------------------------------------------------------------------\n"); + } + + NETWORK_DEBUG() : NetworkInterfaceManager::Events(nullptr) { netdbg("NetworkDebugger initialized."); } + ~NETWORK_DEBUG() { netdbg("NetworkDebugger destroyed."); } + void OnInterfaceReceived(NetworkInterfaceManager::DeviceInterface *Interface, uint8_t *Data, uint64_t Length) { DumpData("Received", Data, Length); } + void OnInterfaceSent(NetworkInterfaceManager::DeviceInterface *Interface, uint8_t *Data, uint64_t Length) { DumpData("Sent", Data, Length); } + }; +} + +NetDbg::NETWORK_DEBUG *N; +void DbgNetwork() { N = new NetDbg::NETWORK_DEBUG; } +void DbgDumpData(const char *Description, void *Address, unsigned long Length) { N->DumpData(Description, Address, Length); } + +#endif diff --git a/Network/NetworkTimeProtocol.cpp b/Network/NetworkTimeProtocol.cpp new file mode 100644 index 0000000..384bb3a --- /dev/null +++ b/Network/NetworkTimeProtocol.cpp @@ -0,0 +1,21 @@ +#include +#include + +#include "../kernel.h" + +namespace NetworkNTP +{ + NTP::NTP(NetworkUDP::Socket *Socket) : NetworkUDP::UDPEvents() + { + this->Socket = Socket; + } + + NTP::~NTP() + { + } + + void ReadTime() + { + fixme("ReadTime()"); + } +} diff --git a/Network/TransmissionControlProtocol.cpp b/Network/TransmissionControlProtocol.cpp new file mode 100644 index 0000000..7a023d1 --- /dev/null +++ b/Network/TransmissionControlProtocol.cpp @@ -0,0 +1,8 @@ +#include +#include + +#include "../kernel.h" + +namespace NetworkTCP +{ +} diff --git a/Network/UserDatagramProtocol.cpp b/Network/UserDatagramProtocol.cpp new file mode 100644 index 0000000..1827dbb --- /dev/null +++ b/Network/UserDatagramProtocol.cpp @@ -0,0 +1,119 @@ +#include +#include + +#include "../kernel.h" + +namespace NetworkUDP +{ + struct EventInfo + { + Socket *UDPSocket; + uint16_t Port; + }; + Vector RegisteredEvents; + + UDPEvents::UDPEvents() {} + + UDPEvents::~UDPEvents() {} + + /* -------------------------------------------------------------------------------------------------------------------------------- */ + + UDP::UDP(NetworkIPv4::IPv4 *ipv4, NetworkInterfaceManager::DeviceInterface *Interface) : NetworkIPv4::IPv4Events(NetworkIPv4::PROTOCOL_UDP) + { + netdbg("UDP: Initializing."); + this->ipv4 = ipv4; + this->Interface = Interface; + } + + UDP::~UDP() {} + + uint16_t UsablePort = 0x200; + + Socket *UDP::Connect(InternetProtocol4 IP, uint16_t Port) + { + netdbg("UDP: Connecting to %d.%d.%d.%d:%d", IP.Address[0], IP.Address[1], IP.Address[2], IP.Address[3], Port); + Socket *socket = new Socket(this); + socket->RemoteIP = IP; + socket->RemotePort = Port; + socket->LocalPort = UsablePort++; // TODO: track ports + socket->LocalIP = Interface->IP; + socket->LocalPort = __builtin_bswap16(socket->LocalPort); + socket->RemotePort = __builtin_bswap16(socket->RemotePort); + RegisteredEvents.push_back({.UDPSocket = socket, .Port = socket->LocalPort}); + return socket; + } + + Socket *UDP::Listen(uint16_t Port) + { + fixme("Not implemented."); + return nullptr; + } + + void UDP::Disconnect(Socket *Socket) + { + fixme("Not implemented."); + } + + void UDP::Send(Socket *Socket, uint8_t *Data, uint64_t Length) + { + netdbg("UDP: Sending %d bytes to %d.%d.%d.%d:%d", Length, Socket->RemoteIP.Address[0], Socket->RemoteIP.Address[1], Socket->RemoteIP.Address[2], Socket->RemoteIP.Address[3], Socket->RemotePort); + uint16_t TotalLength = Length + sizeof(UDPHeader); + UDPPacket *packet = (UDPPacket *)kmalloc(TotalLength); + packet->Header.SourcePort = Socket->LocalPort; + packet->Header.DestinationPort = Socket->RemotePort; + packet->Header.Length = b16(TotalLength); + memcpy(packet->Data, Data, Length); + packet->Header.Checksum = 0; // I totally should do this. Some devices may require it. + // packet->Header.Checksum = CalculateChecksum((uint16_t *)packet, TotalLength); + this->ipv4->Send((uint8_t *)packet, TotalLength, 0x11, Socket->RemoteIP); + kfree(packet); + } + + void UDP::Bind(Socket *Socket, UDPEvents *EventHandler) { Socket->EventHandler = EventHandler; } + + bool UDP::OnIPv4PacketReceived(InternetProtocol4 SourceIP, InternetProtocol4 DestinationIP, uint8_t *Data, uint64_t Length) + { + netdbg("UDP: Received %d bytes from %d.%d.%d.%d", Length, SourceIP.Address[0], SourceIP.Address[1], SourceIP.Address[2], SourceIP.Address[3]); + if (Length < sizeof(UDPHeader)) + return false; + + UDPHeader *udp = (UDPHeader *)Data; + + netdbg("UDP: SP:%d | DP:%d | L:%d | CHK:%#x", b16(udp->SourcePort), b16(udp->DestinationPort), b16(udp->Length), b16(udp->Checksum)); + + Socket *GoodSocket = nullptr; + + foreach (auto var in RegisteredEvents) + { + netdbg("UDP->SKT[]: LP:%d | LIP:%d.%d.%d.%d | RP:%d | RIP:%d.%d.%d.%d | LST:%d", + b16(var.UDPSocket->LocalPort), + var.UDPSocket->LocalIP.Address[0], var.UDPSocket->LocalIP.Address[1], var.UDPSocket->LocalIP.Address[2], var.UDPSocket->LocalIP.Address[3], + b16(var.UDPSocket->RemotePort), + var.UDPSocket->RemoteIP.Address[0], var.UDPSocket->RemoteIP.Address[1], var.UDPSocket->RemoteIP.Address[2], var.UDPSocket->RemoteIP.Address[3], + b16(var.UDPSocket->Listening)); + if (var.UDPSocket->LocalPort == udp->DestinationPort && + var.UDPSocket->LocalIP == DestinationIP && + var.UDPSocket->Listening == true) + { + var.UDPSocket->Listening = false; + var.UDPSocket->RemotePort = b16(udp->SourcePort); + var.UDPSocket->RemoteIP = SourceIP; + netdbg("UDP: E1"); + return true; + } + + GoodSocket = var.UDPSocket; + } + if (GoodSocket) + GoodSocket->EventHandler->OnUDPPacketReceived(GoodSocket, ((UDPPacket *)Data)->Data, Length); + + netdbg("UDP: E0 (Success)"); + return false; + } + + /* -------------------------------------------------------------------------------------------------------------------------------- */ + + Socket::Socket(UDP *_UDP) { this->SocketUDP = _UDP; } + + Socket::~Socket() {} +} diff --git a/include/net/arp.hpp b/include/net/arp.hpp new file mode 100644 index 0000000..24a2c85 --- /dev/null +++ b/include/net/arp.hpp @@ -0,0 +1,89 @@ +#ifndef __FENNIX_KERNEL_NETWORK_ARP_H__ +#define __FENNIX_KERNEL_NETWORK_ARP_H__ + +#include +#include +#include +#include + +namespace NetworkARP +{ + enum ARPOperation + { + REQUEST = 0x1, + REPLY = 0x2 + }; + + enum ARPHardwareType + { + HTYPE_ETHERNET = 1, + HTYPE_802_3 = 6, + HTYPE_ARCNET = 7, + HTYPE_FRAME_RELAY = 15, + HTYPE_ATM = 16, + HTYPE_HDLC = 17, + HTYPE_FIBRE_CHANNEL = 18, + HTYPE_ATM_2 = 19, + HTYPE_SERIAL_LINE = 20 + }; + + struct ARPHeader + { + uint16_t HardwareType; + uint16_t ProtocolType; + uint8_t HardwareSize; + uint8_t ProtocolSize; + uint16_t Operation; + uint48_t SenderMAC : 48; + uint32_t SenderIP; + uint48_t TargetMAC : 48; + uint32_t TargetIP; + } __attribute__((packed)); + + struct DiscoveredAddress + { + MediaAccessControl MAC; + InternetProtocol4 IP; + }; + + class ARP : public NetworkEthernet::EthernetEvents + { + private: + NetworkEthernet::Ethernet *Ethernet; + + enum DAType + { + DA_ADD = 1, + DA_DEL = 2, + DA_SEARCH = 3, + DA_UPDATE = 4 + }; + + Vector DiscoveredAddresses; + DiscoveredAddress *ManageDA(DAType Type, InternetProtocol4 IP, MediaAccessControl MAC); + DiscoveredAddress *Search(InternetProtocol4 TargetIP); + DiscoveredAddress *Update(InternetProtocol4 TargetIP, MediaAccessControl TargetMAC); + bool OnEthernetPacketReceived(uint8_t *Data, uint64_t Length); + + public: + ARP(NetworkEthernet::Ethernet *Ethernet); + ~ARP(); + + /** + * @brief Resolve an IP address to a MAC address. + * + * @param IP The IP address to resolve. (Little-endian) + * @return uint48_t The MAC address of the IP address. + */ + uint48_t Resolve(InternetProtocol4 IP); + + /** + * @brief Broadcast an ARP packet. + * + * @param IP The IP address to broadcast. + */ + void Broadcast(InternetProtocol4 IP); + }; +} + +#endif // !__FENNIX_KERNEL_NETWORK_ARP_H__ diff --git a/include/net/dhcp.hpp b/include/net/dhcp.hpp new file mode 100644 index 0000000..74c18c3 --- /dev/null +++ b/include/net/dhcp.hpp @@ -0,0 +1,166 @@ +#ifndef __FENNIX_KERNEL_DHCP_H__ +#define __FENNIX_KERNEL_DHCP_H__ + +#include +#include +#include +#include + +namespace NetworkDHCP +{ + struct DHCPHeader + { + uint8_t Opcode; + uint8_t HardwareType; + uint8_t HardwareAddressLength; + uint8_t Hops; + uint32_t TransactionID; + uint16_t Seconds; + uint16_t Flags; + uint32_t ClientIP; + uint32_t YourIP; + uint32_t ServerIP; + uint32_t GatewayIP; + uint8_t ClientHardwareAddress[16]; + uint8_t ServerHostName[64]; + uint8_t BootFileName[128]; + uint8_t Options[64]; + } __attribute__((packed)); + + enum DHCPOperation + { + DHCP_OP_BOOTREQUEST = 1, + DHCP_OP_BOOTREPLY = 2 + }; + + /* TODO: Complete list from https://en.wikipedia.org/wiki/Dynamic_Host_Configuration_Protocol#Options */ + enum DHCPOption + { + DHCP_OPTION_PAD = 0, + DHCP_OPTION_SUBNETMASK = 1, + DHCP_OPTION_TIME_OFFSET = 2, + DHCP_OPTION_ROUTER = 3, + DHCP_OPTION_TIME_SERVER = 4, + DHCP_OPTION_NAME_SERVER = 5, + DHCP_OPTION_DOMAIN_NAME_SERVER = 6, + DHCP_OPTION_LOG_SERVER = 7, + DHCP_OPTION_COOKIE_SERVER = 8, + DHCP_OPTION_LPR_SERVER = 9, + DHCP_OPTION_IMPRESS_SERVER = 10, + DHCP_OPTION_RESOURCE_LOCATION_SERVER = 11, + DHCP_OPTION_HOST_NAME = 12, + DHCP_OPTION_BOOT_FILE_SIZE = 13, + DHCP_OPTION_MERIT_DUMP_FILE = 14, + DHCP_OPTION_DOMAIN_NAME = 15, + DHCP_OPTION_SWAP_SERVER = 16, + DHCP_OPTION_ROOT_PATH = 17, + DHCP_OPTION_EXTENSION_PATH = 18, + + DHCP_OPTION_IP_FORWARDING = 19, + DHCP_OPTION_NON_LOCAL_SOURCE_ROUTING = 20, + DHCP_OPTION_POLICY_FILTER = 21, + DHCP_OPTION_MAX_DATAGRAM_REASSEMBLY_SIZE = 22, + DHCP_OPTION_DEFAULT_IP_TTL = 23, + DHCP_OPTION_PATH_MTU_AGING_TIMEOUT = 24, + DHCP_OPTION_PATH_MTU_PLATEAU_TABLE = 25, + + DHCP_OPTION_INTERFACE_MTU = 26, + DHCP_OPTION_ALL_SUBNETS_ARE_LOCAL = 27, + DHCP_OPTION_BROADCAST_ADDRESS = 28, + DHCP_OPTION_PERFORM_MASK_DISCOVERY = 29, + DHCP_OPTION_MASK_SUPPLIER = 30, + DHCP_OPTION_ROUTER_DISCOVERY = 31, + DHCP_OPTION_ROUTER_SOLICITATION_ADDRESS = 32, + DHCP_OPTION_STATIC_ROUTE = 33, + + DHCP_OPTION_TRAILER_ENCAPSULATION = 34, + DHCP_OPTION_ARP_CACHE_TIMEOUT = 35, + DHCP_OPTION_ETHERNET_ENCAPSULATION = 36, + + DHCP_OPTION_DEFAULT_TCP_TTL = 37, + DHCP_OPTION_TCP_KEEPALIVE_INTERVAL = 38, + DHCP_OPTION_TCP_KEEPALIVE_GARBAGE = 39, + + DHCP_OPTION_NIS_DOMAIN = 40, + DHCP_OPTION_NIS_SERVERS = 41, + DHCP_OPTION_NTP_SERVERS = 42, + DHCP_OPTION_VENDOR_SPECIFIC = 43, + DHCP_OPTION_NETBIOS_NAME_SERVERS = 44, + DHCP_OPTION_NETBIOS_DD_SERVER = 45, + DHCP_OPTION_NETBIOS_NODE_TYPE = 46, + DHCP_OPTION_NETBIOS_SCOPE = 47, + DHCP_OPTION_X_FONT_SERVERS = 48, + DHCP_OPTION_X_DISPLAY_MANAGER = 49, + + DHCP_OPTION_REQUESTED_IP = 50, + DHCP_OPTION_IP_LEASE_TIME = 51, + DHCP_OPTION_OPTION_OVERLOAD = 52, + DHCP_OPTION_MESSAGE_TYPE = 53, + DHCP_OPTION_SERVER_IDENTIFIER = 54, + DHCP_OPTION_PARAMETER_REQUEST_LIST = 55, + DHCP_OPTION_MESSAGE = 56, + DHCP_OPTION_MAX_MESSAGE_SIZE = 57, + DHCP_OPTION_T1_TIMEOUT = 58, + DHCP_OPTION_T2_TIMEOUT = 59, + DHCP_OPTION_VENDOR_CLASS_IDENTIFIER = 60, + DHCP_OPTION_CLIENT_IDENTIFIER = 61, + + DHCP_OPTION_NETWORK_TIME_SERVER = 62, + + DHCP_OPTION_END = 255 + }; + + enum DHCPMessageType + { + DHCP_MESSAGE_TYPE_DISCOVER = 1, + DHCP_MESSAGE_TYPE_OFFER = 2, + DHCP_MESSAGE_TYPE_REQUEST = 3, + DHCP_MESSAGE_TYPE_DECLINE = 4, + DHCP_MESSAGE_TYPE_ACK = 5, + DHCP_MESSAGE_TYPE_NAK = 6, + DHCP_MESSAGE_TYPE_RELEASE = 7, + DHCP_MESSAGE_TYPE_INFORM = 8, + DHCP_MESSAGE_TYPE_FORCERENEW = 9, + DHCP_MESSAGE_TYPE_LEASEQUERY = 10, + DHCP_MESSAGE_TYPE_LEASEUNASSIGNED = 11, + DHCP_MESSAGE_TYPE_LEASEUNKNOWN = 12, + DHCP_MESSAGE_TYPE_LEASEACTIVE = 13, + DHCP_MESSAGE_TYPE_BULKLEASEQUERY = 14, + DHCP_MESSAGE_TYPE_LEASEQUERYDONE = 15, + DHCP_MESSAGE_TYPE_ACTIVELEASEQUERY = 16, + DHCP_MESSAGE_TYPE_LEASEQUERYSTATUS = 17, + DHCP_MESSAGE_TYPE_DHCPTLS = 18 + }; + +#define DHCP_TRANSACTION_ID 0xFE2EC005 + + class DHCP : public NetworkUDP::UDPEvents + { + private: + NetworkUDP::Socket *UDPSocket; + NetworkInterfaceManager::DeviceInterface *Interface; + bool Received = false; + + void CreatePacket(DHCPHeader *Packet, uint8_t MessageType, uint32_t RequestIP); + void *GetOption(DHCPHeader *Packet, uint8_t Type); + + public: + /** @brief IP address (Little-endian) */ + InternetProtocol4 IP = {.Address = {0x0, 0x0, 0x0, 0x0}}; + /** @brief Gateway address (Little-endian) */ + InternetProtocol4 Gateway = {.Address = {0x0, 0x0, 0x0, 0x0}}; + /** @brief Subnet mask (Little-endian) */ + InternetProtocol4 SubNetworkMask = {.Address = {0x0, 0x0, 0x0, 0x0}}; + /** @brief DNS server address (Little-endian) */ + InternetProtocol4 DomainNameSystem = {.Address = {0x0, 0x0, 0x0, 0x0}}; + + DHCP(NetworkUDP::Socket *Socket, NetworkInterfaceManager::DeviceInterface *Interface); + ~DHCP(); + void Request(); + void Request(InternetProtocol4 IP); + + virtual void OnUDPPacketReceived(NetworkUDP::Socket *Socket, uint8_t *Data, uint64_t Length); + }; +} + +#endif // !__FENNIX_KERNEL_DHCP_H__ diff --git a/include/net/eth.hpp b/include/net/eth.hpp new file mode 100644 index 0000000..01fc41d --- /dev/null +++ b/include/net/eth.hpp @@ -0,0 +1,77 @@ +#ifndef __FENNIX_KERNEL_NETWORK_ETHERNET_H__ +#define __FENNIX_KERNEL_NETWORK_ETHERNET_H__ + +#include +#include + +namespace NetworkEthernet +{ + enum FrameType + { + TYPE_IPV4 = 0x0800, + TYPE_ARP = 0x0806, + TYPE_RARP = 0x8035, + TYPE_IPV6 = 0x86DD + }; + + struct EthernetHeader + { + uint48_t DestinationMAC : 48; + uint48_t SourceMAC : 48; + uint16_t Type; + } __attribute__((packed)); + + struct EthernetPacket + { + EthernetHeader Header; + uint8_t Data[]; + }; + + class EthernetEvents + { + private: + FrameType FType; + + protected: + EthernetEvents(FrameType Type); + ~EthernetEvents(); + + public: + FrameType GetFrameType() { return FType; } + virtual void OnEthernetPacketSent(EthernetPacket *Packet) { netdbg("Event not handled. [%p]", Packet); } + virtual bool OnEthernetPacketReceived(uint8_t *Data, uint64_t Length) + { + netdbg("Event not handled. [%p, %d]", Data, Length); + return false; + } + }; + + class Ethernet : public NetworkInterfaceManager::Events + { + private: + NetworkInterfaceManager::DeviceInterface *Interface; + void Receive(uint8_t *Data, uint64_t Length); + void OnInterfaceReceived(NetworkInterfaceManager::DeviceInterface *Interface, uint8_t *Data, uint64_t Length); + + public: + /** @brief Get driver interface + * @return Driver interface + */ + NetworkInterfaceManager::DeviceInterface *GetInterface() { return this->Interface; } + + Ethernet(NetworkInterfaceManager::DeviceInterface *Interface); + ~Ethernet(); + + /** + * @brief Send an Ethernet packet. + * + * @param MAC The MAC address of the destination. (Big-endian) + * @param Type The type of the packet. + * @param Data The data to send. + * @param Length The length of the data. + */ + void Send(MediaAccessControl MAC, FrameType Type, uint8_t *Data, uint64_t Length); + }; +} + +#endif // !__FENNIX_KERNEL_NETWORK_ETHERNET_H__ diff --git a/include/net/icmpv4.hpp b/include/net/icmpv4.hpp new file mode 100644 index 0000000..00b710c --- /dev/null +++ b/include/net/icmpv4.hpp @@ -0,0 +1,54 @@ +#ifndef __FENNIX_KERNEL_ICMPv4_H__ +#define __FENNIX_KERNEL_ICMPv4_H__ + +#include +#include + +namespace NetworkICMPv4 +{ + enum ICMPv4Type + { + TYPE_ECHO_REPLY = 0, + TYPE_DESTINATION_UNREACHABLE = 3, + TYPE_SOURCE_QUENCH = 4, + TYPE_REDIRECT = 5, + TYPE_ECHO = 8, + TYPE_ROUTER_ADVERTISEMENT = 9, + TYPE_ROUTER_SELECTION = 10, + TYPE_TIME_EXCEEDED = 11, + TYPE_PARAMETER_PROBLEM = 12, + TYPE_TIMESTAMP = 13, + TYPE_TIMESTAMP_REPLY = 14 + }; + + struct ICMPHeader + { + uint8_t Type; + uint8_t Code; + uint16_t Checksum; + uint16_t Identifier; + uint16_t SequenceNumber; + }; + + struct ICMPPacket + { + ICMPHeader Header; + uint8_t Data[]; + }; + + class ICMPv4 + { + private: + NetworkInterfaceManager::DeviceInterface *Interface; + + public: + NetworkInterfaceManager::DeviceInterface *GetInterface() { return this->Interface; } + + ICMPv4(NetworkInterfaceManager::DeviceInterface *Interface); + ~ICMPv4(); + void Send(/* ???? */); + void Receive(ICMPPacket *Packet); + }; +} + +#endif // !__FENNIX_KERNEL_ICMPv4_H__ diff --git a/include/net/icmpv6.hpp b/include/net/icmpv6.hpp new file mode 100644 index 0000000..c367053 --- /dev/null +++ b/include/net/icmpv6.hpp @@ -0,0 +1,39 @@ +#ifndef __FENNIX_KERNEL_ICMPv6_H__ +#define __FENNIX_KERNEL_ICMPv6_H__ + +#include +#include + +namespace NetworkICMPv6 +{ + struct ICMPHeader + { + uint8_t Type; + uint8_t Code; + uint16_t Checksum; + uint16_t Identifier; + uint16_t SequenceNumber; + }; + + struct ICMPPacket + { + ICMPHeader Header; + uint8_t Data[]; + }; + + class ICMPv6 + { + private: + NetworkInterfaceManager::DeviceInterface *Interface; + + public: + NetworkInterfaceManager::DeviceInterface *GetInterface() { return this->Interface; } + + ICMPv6(NetworkInterfaceManager::DeviceInterface *Interface); + ~ICMPv6(); + void Send(uint8_t *Data, uint64_t Length); + void Receive(uint8_t *Data); + }; +} + +#endif // !__FENNIX_KERNEL_ICMPv6_H__ diff --git a/include/net/ipv4.hpp b/include/net/ipv4.hpp new file mode 100644 index 0000000..2a97f34 --- /dev/null +++ b/include/net/ipv4.hpp @@ -0,0 +1,115 @@ +#ifndef __FENNIX_KERNEL_IPv4_H__ +#define __FENNIX_KERNEL_IPv4_H__ + +#include +#include +#include +#include + +namespace NetworkIPv4 +{ + struct IPv4Header + { + uint8_t IHL : 4; + uint8_t Version : 4; + uint8_t TypeOfService; + uint16_t TotalLength; + uint16_t Identification; + uint16_t FlagsAndFragmentOffset; + uint8_t TimeToLive; + uint8_t Protocol; + uint16_t HeaderChecksum; + uint32_t SourceIP; + uint32_t DestinationIP; + + /* On wikipedia page we have this: https://en.wikipedia.org/wiki/File:IPv4_Packet-en.svg + but only the code above works... */ + // uint8_t Version : 4; + // uint8_t IHL : 4; + // uint16_t TypeOfService : 8; + // uint16_t TotalLength : 12; + // uint16_t Identification : 16; + // uint16_t Flags : 3; + // uint16_t FragmentOffset : 13; + // uint8_t TimeToLive : 8; + // uint8_t Protocol : 8; + // uint16_t HeaderChecksum; + // uint32_t SourceIP; + // uint32_t DestinationIP; + }; + + struct IPv4Packet + { + IPv4Header Header; + uint8_t Data[]; + }; + + enum IPv4Protocols + { + PROTOCOL_ICMP = 1, + PROTOCOL_IGMP = 2, + PROTOCOL_TCP = 6, + PROTOCOL_UDP = 17, + PROTOCOL_IPV6 = 41, + PROTOCOL_ROUTING = 43, + PROTOCOL_FRAGMENT = 44, + PROTOCOL_ESP = 50, + PROTOCOL_AH = 51, + PROTOCOL_ICMPV6 = 58, + PROTOCOL_NONE = 59, + PROTOCOL_DSTOPTS = 60, + PROTOCOL_ND = 77, + PROTOCOL_ICLFXBM = 78, + PROTOCOL_PIM = 103, + PROTOCOL_COMP = 108, + PROTOCOL_SCTP = 132, + PROTOCOL_UDPLITE = 136, + PROTOCOL_RAW = 255 + }; + + class IPv4 : public NetworkEthernet::EthernetEvents + { + private: + NetworkARP::ARP *ARP; + NetworkEthernet::Ethernet *Ethernet; + + virtual bool OnEthernetPacketReceived(uint8_t *Data, uint64_t Length); + + public: + InternetProtocol4 GatewayIP = {.Address = {0xFF, 0xFF, 0xFF, 0xFF}}; + InternetProtocol4 SubNetworkMaskIP = {.Address = {0xFF, 0xFF, 0xFF, 0xFF}}; + IPv4(NetworkARP::ARP *ARP, NetworkEthernet::Ethernet *Ethernet); + ~IPv4(); + + /** + * @brief Send an IPv4 packet. + * + * @param Data The data to send. + * @param Length The length of the data. + * @param Protocol The protocol of the packet. + * @param DestinationIP The IP address of the destination. (Big-endian) + */ + void Send(uint8_t *Data, uint64_t Length, uint8_t Protocol, InternetProtocol4 DestinationIP); + }; + + class IPv4Events + { + private: + uint8_t Protocol; + + protected: + IPv4Events(IPv4Protocols Protocol); + ~IPv4Events(); + + public: + uint8_t GetProtocol() { return Protocol; } + + virtual bool OnIPv4PacketReceived(InternetProtocol4 SourceIP, InternetProtocol4 DestinationIP, uint8_t *Data, uint64_t Length) + { + warn("Not implemented."); + return false; + } + }; +} + +#endif // !__FENNIX_KERNEL_IPv4_H__ diff --git a/include/net/ipv6.hpp b/include/net/ipv6.hpp new file mode 100644 index 0000000..0a940ca --- /dev/null +++ b/include/net/ipv6.hpp @@ -0,0 +1,27 @@ +#ifndef __FENNIX_KERNEL_IPv6_H__ +#define __FENNIX_KERNEL_IPv6_H__ + +#include + +namespace NetworkIPv6 +{ + struct IPv6Header + { + uint32_t Version; + uint8_t TrafficClass; + uint16_t FlowLabel; + uint16_t PayloadLength; + uint8_t NextHeader; + uint8_t HopLimit; + uint32_t SourceIP; + uint32_t DestinationIP; + }; + + struct IPv6Packet + { + IPv6Header Header; + uint8_t Data[]; + }; +} + +#endif // !__FENNIX_KERNEL_IPv6_H__ diff --git a/include/net/nc.hpp b/include/net/nc.hpp new file mode 100644 index 0000000..34420f6 --- /dev/null +++ b/include/net/nc.hpp @@ -0,0 +1,75 @@ +#ifndef __FENNIX_KERNEL_NETWORK_CONTROLLER_H__ +#define __FENNIX_KERNEL_NETWORK_CONTROLLER_H__ + +#include +#include +#include +#include +#include +#include + +namespace NetworkInterfaceManager +{ + struct DeviceInterface + { + /** @brief Device interface name */ + char Name[128]; + + /** @brief Device interface index */ + uint64_t ID; + + /** @brief Device interface MAC address (Big-endian) */ + MediaAccessControl MAC; + + /** @brief Device interface IP address (Big-endian) */ + InternetProtocol4 IP; + + /** @brief Reserved */ + void *DriverCallBackAddress; + + /** @brief Reserved */ + unsigned int DriverID; + }; + + class Events + { + protected: + Events(DeviceInterface *Interface); + ~Events(); + + public: + virtual void OnInterfaceAdded(DeviceInterface *Interface) { netdbg("Event for %s not handled.", Interface->Name); } + virtual void OnInterfaceRemoved(DeviceInterface *Interface) { netdbg("Event for %s not handled.", Interface->Name); } + virtual void OnInterfaceChanged(DeviceInterface *Interface) { netdbg("Event for %s not handled.", Interface->Name); } + virtual void OnInterfaceReceived(DeviceInterface *Interface, uint8_t *Data, uint64_t Length) { netdbg("Event for %s not handled.", Interface->Name); } + virtual void OnInterfaceSent(DeviceInterface *Interface, uint8_t *Data, uint64_t Length) { netdbg("Event for %s not handled.", Interface->Name); } + }; + + class NetworkInterface + { + private: + Memory::MemMgr *mem; + int CardIDs = 0; + Vector Interfaces; + + Tasking::PCB *NetSvcProcess; + Tasking::TCB *NetSvcThread; + void StopNetworkStack(); + void FetchNetworkCards(unsigned long DriverUID); + + public: + NetworkInterface(); + ~NetworkInterface(); + + void StartService(); + + void Send(DeviceInterface *Interface, uint8_t *Data, uint64_t Length); + void Receive(DeviceInterface *Interface, uint8_t *Data, uint64_t Length); + + void DrvSend(unsigned int DriverID, unsigned char *Data, unsigned short Size); + void DrvReceive(unsigned int DriverID, unsigned char *Data, unsigned short Size); + void StartNetworkStack(); + }; +} + +#endif // !__FENNIX_KERNEL_NETWORK_CONTROLLER_H__ diff --git a/include/net/net.hpp b/include/net/net.hpp new file mode 100644 index 0000000..e6ab64e --- /dev/null +++ b/include/net/net.hpp @@ -0,0 +1,150 @@ +#ifndef __FENNIX_KERNEL_NETWORK_H__ +#define __FENNIX_KERNEL_NETWORK_H__ + +#include + +// #define DEBUG_NETWORK 1 + +#ifdef DEBUG_NETWORK +#define netdbg(m, ...) debug(m, ##__VA_ARGS__) +void DbgNetwork(); +void DbgDumpData(const char *Description, void *Address, unsigned long Length); +#else +#define netdbg(m, ...) +static inline void DbgNetwork() { return; } +static inline void DbgDumpData(const char *Description, void *Address, unsigned long Length) { return; } +#endif + +// TODO: How i would do this? +typedef __UINT64_TYPE__ uint48_t; + +#define b4(x) ((x & 0x0F) << 4 | (x & 0xF0) >> 4) +#define b8(x) ((x)&0xFF) +#define b16(x) __builtin_bswap16(x) +#define b32(x) __builtin_bswap32(x) +#define b48(x) (((((x)&0x0000000000ff) << 40) | (((x)&0x00000000ff00) << 24) | (((x)&0x000000ff0000) << 8) | (((x)&0x0000ff000000) >> 8) | (((x)&0x00ff00000000) >> 24) | (((x)&0xff0000000000) >> 40))) +#define b64(x) __builtin_bswap64(x) + +struct MediaAccessControl +{ + uint8_t Address[6]; + + inline bool operator==(const MediaAccessControl &lhs) const + { + return lhs.Address[0] == this->Address[0] && + lhs.Address[1] == this->Address[1] && + lhs.Address[2] == this->Address[2] && + lhs.Address[3] == this->Address[3] && + lhs.Address[4] == this->Address[4] && + lhs.Address[5] == this->Address[5]; + } + + inline bool operator==(const uint48_t &lhs) const + { + MediaAccessControl MAC; + MAC.Address[0] = (uint8_t)((lhs >> 40) & 0xFF); + MAC.Address[1] = (uint8_t)((lhs >> 32) & 0xFF); + MAC.Address[2] = (uint8_t)((lhs >> 24) & 0xFF); + MAC.Address[3] = (uint8_t)((lhs >> 16) & 0xFF); + MAC.Address[4] = (uint8_t)((lhs >> 8) & 0xFF); + MAC.Address[5] = (uint8_t)(lhs & 0xFF); + return MAC.Address[0] == this->Address[0] && + MAC.Address[1] == this->Address[1] && + MAC.Address[2] == this->Address[2] && + MAC.Address[3] == this->Address[3] && + MAC.Address[4] == this->Address[4] && + MAC.Address[5] == this->Address[5]; + } + + inline bool operator!=(const MediaAccessControl &lhs) const { return !(*this == lhs); } + inline bool operator!=(const uint48_t &lhs) const { return !(*this == lhs); } + + inline uint48_t ToHex() + { + return ((uint48_t)this->Address[0] << 40) | + ((uint48_t)this->Address[1] << 32) | + ((uint48_t)this->Address[2] << 24) | + ((uint48_t)this->Address[3] << 16) | + ((uint48_t)this->Address[4] << 8) | + ((uint48_t)this->Address[5]); + } + + inline MediaAccessControl FromHex(uint48_t Hex) + { + this->Address[0] = (uint8_t)((Hex >> 40) & 0xFF); + this->Address[1] = (uint8_t)((Hex >> 32) & 0xFF); + this->Address[2] = (uint8_t)((Hex >> 24) & 0xFF); + this->Address[3] = (uint8_t)((Hex >> 16) & 0xFF); + this->Address[4] = (uint8_t)((Hex >> 8) & 0xFF); + this->Address[5] = (uint8_t)(Hex & 0xFF); + return *this; + } + + inline bool Valid() + { + // TODO: More complex MAC validation + return (this->Address[0] != 0 || + this->Address[1] != 0 || + this->Address[2] != 0 || + this->Address[3] != 0 || + this->Address[4] != 0 || + this->Address[5] != 0) && + (this->Address[0] != 0xFF || + this->Address[1] != 0xFF || + this->Address[2] != 0xFF || + this->Address[3] != 0xFF || + this->Address[4] != 0xFF || + this->Address[5] != 0xFF); + } +}; + +struct InternetProtocol4 +{ + uint8_t Address[4]; + + inline bool operator==(const InternetProtocol4 &lhs) const + { + return lhs.Address[0] == this->Address[0] && + lhs.Address[1] == this->Address[1] && + lhs.Address[2] == this->Address[2] && + lhs.Address[3] == this->Address[3]; + } + + inline bool operator==(const uint32_t &lhs) const + { + InternetProtocol4 IP; + IP.Address[0] = (uint8_t)((lhs >> 24) & 0xFF); + IP.Address[1] = (uint8_t)((lhs >> 16) & 0xFF); + IP.Address[2] = (uint8_t)((lhs >> 8) & 0xFF); + IP.Address[3] = (uint8_t)(lhs & 0xFF); + + return IP.Address[0] == this->Address[0] && + IP.Address[1] == this->Address[1] && + IP.Address[2] == this->Address[2] && + IP.Address[3] == this->Address[3]; + } + + inline bool operator!=(const InternetProtocol4 &lhs) const { return !(*this == lhs); } + inline bool operator!=(const uint32_t &lhs) const { return !(*this == lhs); } + + inline uint32_t ToHex() + { + return ((uint64_t)this->Address[0] << 24) | + ((uint64_t)this->Address[1] << 16) | + ((uint64_t)this->Address[2] << 8) | + ((uint64_t)this->Address[3]); + } + + inline InternetProtocol4 FromHex(uint32_t Hex) + { + this->Address[0] = (uint8_t)((Hex >> 24) & 0xFF); + this->Address[1] = (uint8_t)((Hex >> 16) & 0xFF); + this->Address[2] = (uint8_t)((Hex >> 8) & 0xFF); + this->Address[3] = (uint8_t)(Hex & 0xFF); + return *this; + } +}; + +uint16_t CalculateChecksum(uint16_t *Data, uint64_t Length); + +#endif // !__FENNIX_KERNEL_NETWORK_H__ diff --git a/include/net/ntp.hpp b/include/net/ntp.hpp new file mode 100644 index 0000000..b8878de --- /dev/null +++ b/include/net/ntp.hpp @@ -0,0 +1,39 @@ +#ifndef __FENNIX_KERNEL_NTP_H__ +#define __FENNIX_KERNEL_NTP_H__ + +#include +#include + +namespace NetworkNTP +{ + struct NTPHeader + { + uint8_t LIv; + uint8_t VN; + uint8_t Mode; + uint8_t Stratum; + uint8_t Poll; + uint8_t Precision; + uint32_t RootDelay; + uint32_t RootDispersion; + uint32_t ReferenceID; + uint32_t ReferenceTimestamp; + uint32_t OriginateTimestamp; + uint32_t ReceiveTimestamp; + uint32_t TransmitTimestamp; + } __attribute__((packed)); + + class NTP : public NetworkUDP::UDPEvents + { + private: + NetworkUDP::Socket *Socket; + + public: + NTP(NetworkUDP::Socket *Socket); + ~NTP(); + + void ReadTime(); + }; +} + +#endif // !__FENNIX_KERNEL_NTP_H__ diff --git a/include/net/tcp.hpp b/include/net/tcp.hpp new file mode 100644 index 0000000..282226e --- /dev/null +++ b/include/net/tcp.hpp @@ -0,0 +1,10 @@ +#ifndef __FENNIX_KERNEL_TCP_H__ +#define __FENNIX_KERNEL_TCP_H__ + +#include + +namespace NetworkTCP +{ +} + +#endif // !__FENNIX_KERNEL_TCP_H__ diff --git a/include/net/udp.hpp b/include/net/udp.hpp new file mode 100644 index 0000000..32415b3 --- /dev/null +++ b/include/net/udp.hpp @@ -0,0 +1,77 @@ +#ifndef __FENNIX_KERNEL_UDP_H__ +#define __FENNIX_KERNEL_UDP_H__ + +#include +#include +#include +#include + +namespace NetworkUDP +{ + struct UDPHeader + { + uint16_t SourcePort; + uint16_t DestinationPort; + uint16_t Length; + uint16_t Checksum; + } __attribute__((packed)); + + struct UDPPacket + { + UDPHeader Header; + uint8_t Data[]; + }; + + class Socket; + + class UDPEvents + { + protected: + UDPEvents(); + ~UDPEvents(); + + public: + virtual void OnUDPPacketReceived(Socket *Socket, uint8_t *Data, uint64_t Length) + { + warn("Not implemented."); + } + }; + + class UDP : public NetworkIPv4::IPv4Events + { + private: + NetworkIPv4::IPv4 *ipv4; + NetworkInterfaceManager::DeviceInterface *Interface; + + public: + NetworkInterfaceManager::DeviceInterface *GetInterface() { return this->Interface; } + + UDP(NetworkIPv4::IPv4 *ipv4, NetworkInterfaceManager::DeviceInterface *Interface); + ~UDP(); + + virtual Socket *Connect(InternetProtocol4 IP, uint16_t Port); + virtual Socket *Listen(uint16_t Port); + virtual void Disconnect(Socket *Socket); + virtual void Send(Socket *Socket, uint8_t *Data, uint64_t Length); + virtual void Bind(Socket *Socket, UDPEvents *EventHandler); + + virtual bool OnIPv4PacketReceived(InternetProtocol4 SourceIP, InternetProtocol4 DestinationIP, uint8_t *Data, uint64_t Length); + }; + + class Socket + { + public: + InternetProtocol4 LocalIP = {.Address = {0xFF, 0xFF, 0xFF, 0xFF}}; + uint16_t LocalPort = 0; + InternetProtocol4 RemoteIP = {.Address = {0xFF, 0xFF, 0xFF, 0xFF}}; + uint16_t RemotePort = 0; + bool Listening = false; + UDPEvents *EventHandler = nullptr; + UDP *SocketUDP = nullptr; + + Socket(UDP *_UDP); + ~Socket(); + }; +} + +#endif // !__FENNIX_KERNEL_UDP_H__ diff --git a/kernel.h b/kernel.h index 55d8a9b..adad586 100644 --- a/kernel.h +++ b/kernel.h @@ -5,6 +5,7 @@ #include #ifdef __cplusplus +#include #include #include #include @@ -29,6 +30,7 @@ extern Time::time *TimeManager; extern FileSystem::Virtual *vfs; extern Driver::Driver *DriverManager; extern Disk::Manager *DiskManager; +extern NetworkInterfaceManager::NetworkInterface *NIManager; #define PEXIT(Code) TaskManager->GetCurrentProcess()->ExitCode = Code #define TEXIT(Code) TaskManager->GetCurrentThread()->ExitCode = Code