From 4f6c7e8a0d0783b511d7ca090664b282c92a904b Mon Sep 17 00:00:00 2001 From: Alex Date: Mon, 9 Jan 2023 03:32:17 +0200 Subject: [PATCH] Updated network related code so now it should work as expected --- Kernel.cpp | 2 + Network/AddressResolutionProtocol.cpp | 126 +++++++++------- Network/DomainNameSystem.cpp | 16 ++ Network/DynamicHostConfigurationProtocol.cpp | 50 +++++-- Network/Ethernet.cpp | 101 +++++++------ Network/InternetControlMessageProtocol.cpp | 4 +- Network/InternetProtocol.cpp | 57 ++++--- Network/NetworkController.cpp | 52 +++++-- Network/NetworkDebugger.cpp | 11 +- Network/NetworkTimeProtocol.cpp | 41 +++++- Network/UserDatagramProtocol.cpp | 37 ++--- include/net/arp.hpp | 12 +- include/net/dhcp.hpp | 13 +- include/net/dns.hpp | 20 +++ include/net/eth.hpp | 9 +- include/net/ipv4.hpp | 11 +- include/net/nc.hpp | 2 +- include/net/net.hpp | 147 ++++++++++++++----- include/net/ntp.hpp | 130 ++++++++++++++-- include/net/udp.hpp | 8 +- 20 files changed, 603 insertions(+), 246 deletions(-) create mode 100644 Network/DomainNameSystem.cpp create mode 100644 include/net/dns.hpp diff --git a/Kernel.cpp b/Kernel.cpp index 3580b3b..bdb5329 100644 --- a/Kernel.cpp +++ b/Kernel.cpp @@ -27,6 +27,8 @@ * * TODO: * - [ ] Optimize SMP. + * - [ ] Support IPv6. + * - [ ] Endianess of the network stack (currently: [HOST](LSB)<=>[NETWORK](MSB)). Not sure if this is a standard or not. * * BUGS: * - [ ] Kernel crashes when receiving interrupts for drivers only if the system has one core and the tasking is running. diff --git a/Network/AddressResolutionProtocol.cpp b/Network/AddressResolutionProtocol.cpp index 8f98d64..0621458 100644 --- a/Network/AddressResolutionProtocol.cpp +++ b/Network/AddressResolutionProtocol.cpp @@ -6,9 +6,8 @@ namespace NetworkARP { - DiscoveredAddress *ARP::ManageDA(DAType Type, InternetProtocol4 IP, MediaAccessControl MAC) + DiscoveredAddress *ARP::ManageDiscoveredAddresses(DAType Type, InternetProtocol IP, MediaAccessControl MAC) { - // TODO: Compare IPv6 too. switch (Type) { case DA_ADD: @@ -17,35 +16,46 @@ namespace NetworkARP tmp->IP = IP; tmp->MAC = MAC; DiscoveredAddresses.push_back(tmp); + netdbg("Added %s to discovered addresses", IP.v4.ToStringLittleEndian()); return tmp; } case DA_DEL: { for (size_t i = 0; i < DiscoveredAddresses.size(); i++) - if (DiscoveredAddresses[i]->IP == IP) + { + if (DiscoveredAddresses[i]->IP.v4 == IP.v4) { DiscoveredAddress *tmp = DiscoveredAddresses[i]; + netdbg("Removed %s from discovered addresses", IP.v4.ToStringLittleEndian()); delete tmp; DiscoveredAddresses.remove(i); } + } return nullptr; } case DA_SEARCH: { for (size_t i = 0; i < DiscoveredAddresses.size(); i++) - if (DiscoveredAddresses[i]->IP == IP) + { + if (DiscoveredAddresses[i]->IP.v4 == IP.v4) + { + netdbg("Found %s in discovered addresses", IP.v4.ToStringLittleEndian()); return DiscoveredAddresses[i]; - + } + } return nullptr; } case DA_UPDATE: { for (size_t i = 0; i < DiscoveredAddresses.size(); i++) - if (DiscoveredAddresses[i]->IP == IP) + { + if (DiscoveredAddresses[i]->IP.v4 == IP.v4) { DiscoveredAddresses[i]->MAC = MAC; + netdbg("Updated %s in discovered addresses", IP.v4.ToStringLittleEndian()); return DiscoveredAddresses[i]; } + } return nullptr; } } @@ -54,7 +64,6 @@ namespace NetworkARP ARP::ARP(NetworkEthernet::Ethernet *Ethernet) : NetworkEthernet::EthernetEvents(NetworkEthernet::TYPE_ARP) { - netdbg("Initializing."); this->Ethernet = Ethernet; } @@ -62,55 +71,62 @@ namespace NetworkARP { } - MediaAccessControl InvalidMAC = {.Address = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}}; - InternetProtocol4 InvalidIP = {.Address = {0xFF, 0xFF, 0xFF, 0xFF}}; + MediaAccessControl InvalidMAC; + InternetProtocol InvalidIP; DiscoveredAddress InvalidRet = {.MAC = InvalidMAC, .IP = InvalidIP}; - DiscoveredAddress *ARP::Search(InternetProtocol4 TargetIP) + DiscoveredAddress *ARP::Search(InternetProtocol TargetIP) { - DiscoveredAddress *ret = ManageDA(DA_SEARCH, TargetIP, MediaAccessControl()); + DiscoveredAddress *ret = ManageDiscoveredAddresses(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]); + warn("No address found for %s", TargetIP.v4.ToStringLittleEndian()); return &InvalidRet; } - DiscoveredAddress *ARP::Update(InternetProtocol4 TargetIP, MediaAccessControl TargetMAC) + DiscoveredAddress *ARP::Update(InternetProtocol TargetIP, MediaAccessControl TargetMAC) { - DiscoveredAddress *ret = ManageDA(DA_UPDATE, TargetIP, TargetMAC); + DiscoveredAddress *ret = ManageDiscoveredAddresses(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]); + warn("No address found for %s", TargetIP.v4.ToStringLittleEndian()); return &InvalidRet; } - uint48_t ARP::Resolve(InternetProtocol4 IP) + uint48_t ARP::Resolve(InternetProtocol IP) { - netdbg("Resolving %d.%d.%d.%d", IP.Address[3], IP.Address[2], IP.Address[1], IP.Address[0]); - if (IP == 0xFFFFFFFF) + netdbg("Resolving %s", IP.v4.ToStringLittleEndian()); + if (IP.v4 == 0xFFFFFFFF) return 0xFFFFFFFFFFFF; + /* If we can't find the MAC, return the default value which is 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); + netdbg("Resolved %s to %lx", IP.v4.ToStringLittleEndian(), ret); if (ret == 0xFFFFFFFFFFFF) { + netdbg("Sending request"); + /* If we can't find the MAC, send a request. + Because we are going to send this over the network, we need to byteswap first. + This is actually very confusing for me. */ 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(); + Header->HardwareType = b16(ARPHardwareType::HTYPE_ETHERNET); + Header->ProtocolType = b16(NetworkEthernet::FrameType::TYPE_IPV4); + Header->HardwareSize = b8(6); + Header->ProtocolSize = b8(4); + Header->Operation = b16(ARPOperation::REQUEST); + Header->SenderMAC = b48(Ethernet->GetInterface()->MAC.ToHex()); + Header->SenderIP = b32(Ethernet->GetInterface()->IP.v4.ToHex()); + Header->TargetMAC = b48(0xFFFFFFFFFFFF); + Header->TargetIP = b32(IP.v4.ToHex()); + netdbg("SIP: %s; TIP: %s", InternetProtocol().v4.FromHex(Header->SenderIP).ToStringLittleEndian(), + InternetProtocol().v4.FromHex(Header->TargetIP).ToStringLittleEndian()); + /* Send the request to the broadcast MAC address. */ 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; + int RequestTimeout = 20; debug("Waiting for response"); while (ret == 0xFFFFFFFFFFFF) { @@ -120,16 +136,17 @@ namespace NetworkARP warn("Request timeout."); return 0; } - TaskManager->Sleep(5000); + netdbg("Still waiting..."); + TaskManager->Sleep(1000); } return ret; } - void ARP::Broadcast(InternetProtocol4 IP) + void ARP::Broadcast(InternetProtocol IP) { netdbg("Sending broadcast"); - uint64_t ResolvedMAC = this->Resolve(IP); + uint48_t ResolvedMAC = this->Resolve(IP); ARPHeader *Header = new ARPHeader; Header->HardwareType = b16(ARPHardwareType::HTYPE_ETHERNET); Header->ProtocolType = b16(NetworkEthernet::FrameType::TYPE_IPV4); @@ -137,9 +154,9 @@ namespace NetworkARP 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(); + Header->SenderIP = b32(Ethernet->GetInterface()->IP.v4.ToHex()); + Header->TargetMAC = b48(ResolvedMAC); + Header->TargetIP = b32(IP.v4.ToHex()); Ethernet->Send(MediaAccessControl().FromHex(ResolvedMAC), NetworkEthernet::FrameType::TYPE_ARP, (uint8_t *)Header, sizeof(ARPHeader)); delete Header; } @@ -149,43 +166,50 @@ namespace NetworkARP netdbg("Received packet"); ARPHeader *Header = (ARPHeader *)Data; - InternetProtocol4 SenderIPv4; - SenderIPv4.FromHex(b32(Header->SenderIP)); + InternetProtocol SenderIPv4; + SenderIPv4.v4 = SenderIPv4.v4.FromHex(b32(Header->SenderIP)); + /* We only support Ethernet and IPv4. */ 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); + warn("Invalid hardware/protocol type (%d/%d)", b16(Header->HardwareType), b16(Header->ProtocolType)); return false; } - if (ManageDA(DA_SEARCH, InternetProtocol4().FromHex(Header->SenderIP), MediaAccessControl().FromHex(Header->SenderMAC)) == nullptr) + InternetProtocol TmpIPStruct; + InternetProtocol().v4.FromHex(b32(Header->SenderIP)); + + if (ManageDiscoveredAddresses(DA_SEARCH, TmpIPStruct, MediaAccessControl().FromHex(b48(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)); + netdbg("Discovered new address %s", SenderIPv4.v4.ToStringLittleEndian()); + TmpIPStruct.v4.FromHex(b32(Header->SenderIP)); + ManageDiscoveredAddresses(DA_ADD, TmpIPStruct, MediaAccessControl().FromHex(b48(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)); + netdbg("Updated address %s", SenderIPv4.v4.ToStringLittleEndian()); + TmpIPStruct.v4.FromHex(b32(Header->SenderIP)); + ManageDiscoveredAddresses(DA_UPDATE, TmpIPStruct, MediaAccessControl().FromHex(b48(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; + netdbg("Received request from %s", SenderIPv4.v4.ToStringLittleEndian()); + /* We need to byteswap before we send it back. */ + Header->TargetMAC = b48(Header->SenderMAC); + Header->TargetIP = b32(Header->SenderIP); Header->SenderMAC = b48(Ethernet->GetInterface()->MAC.ToHex()); - Header->SenderIP = b32(Ethernet->GetInterface()->IP.ToHex()); + Header->SenderIP = b32(Ethernet->GetInterface()->IP.v4.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]); + netdbg("Sent request for %s", SenderIPv4.v4.ToStringLittleEndian()); break; case ARPOperation::REPLY: - fixme("Received reply from %d.%d.%d.%d", SenderIPv4.Address[0], SenderIPv4.Address[1], SenderIPv4.Address[2], SenderIPv4.Address[3]); + fixme("Received reply from %s", SenderIPv4.v4.ToStringLittleEndian()); break; default: - warn("Invalid operation (%d)", Header->Operation); + warn("Invalid operation (%d)", b16(Header->Operation)); break; } return false; diff --git a/Network/DomainNameSystem.cpp b/Network/DomainNameSystem.cpp new file mode 100644 index 0000000..994883b --- /dev/null +++ b/Network/DomainNameSystem.cpp @@ -0,0 +1,16 @@ +#include +#include + +#include "../kernel.h" + +namespace NetworkDNS +{ + DNS::DNS(NetworkUDP::Socket *Socket) : NetworkUDP::UDPEvents() + { + this->UDPSocket = Socket; + } + + DNS::~DNS() + { + } +} diff --git a/Network/DynamicHostConfigurationProtocol.cpp b/Network/DynamicHostConfigurationProtocol.cpp index 200b8ac..94ded41 100644 --- a/Network/DynamicHostConfigurationProtocol.cpp +++ b/Network/DynamicHostConfigurationProtocol.cpp @@ -7,10 +7,24 @@ namespace NetworkDHCP { DHCP::DHCP(NetworkUDP::Socket *Socket, NetworkInterfaceManager::DeviceInterface *Interface) { - netdbg("Initializing."); this->UDPSocket = Socket; this->Interface = Interface; Socket->LocalPort = b16(68); + + InternetProtocol::Version4 DefaultIPv4 = {.Address = {0x0, 0x0, 0x0, 0x0}}; + InternetProtocol::Version6 DefaultIPv6 = {.Address = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}; + + this->IP.v4 = DefaultIPv4; + this->IP.v6 = DefaultIPv6; + + this->Gateway.v4 = DefaultIPv4; + this->Gateway.v6 = DefaultIPv6; + + this->SubNetworkMask.v4 = DefaultIPv4; + this->SubNetworkMask.v6 = DefaultIPv6; + + this->DomainNameSystem.v4 = DefaultIPv4; + this->DomainNameSystem.v6 = DefaultIPv6; } DHCP::~DHCP() @@ -29,7 +43,7 @@ namespace NetworkDHCP memcpy(Packet->ClientHardwareAddress, &InterfaceMAC, sizeof(InterfaceMAC)); uint8_t *Ptr = Packet->Options; - *((uint32_t *)(Ptr)) = b32(0x63825363); // magic cookie + *((uint32_t *)(Ptr)) = b32(0x63825363); // Magic Cookie Ptr += 4; *(Ptr++) = DHCP_OPTION_MESSAGE_TYPE; @@ -80,7 +94,7 @@ namespace NetworkDHCP this->UDPSocket->SocketUDP->Send(this->UDPSocket, (uint8_t *)&packet, sizeof(DHCPHeader)); debug("Waiting for response..."); - int RequestTimeout = 10; + int RequestTimeout = 20; while (!Received) { if (--RequestTimeout == 0) @@ -88,17 +102,19 @@ namespace NetworkDHCP warn("Request timeout."); break; } - TaskManager->Sleep(5000); + netdbg("Still waiting..."); + TaskManager->Sleep(1000); } } - void DHCP::Request(InternetProtocol4 IP) + void DHCP::Request(InternetProtocol IP) { - netdbg("Requesting IP address %d.%d.%d.%d", IP.Address[0], IP.Address[1], IP.Address[2], IP.Address[3]); + netdbg("Requesting IP address %s", IP.v4.ToStringLittleEndian()); DHCPHeader packet; memset(&packet, 0, sizeof(DHCPHeader)); - CreatePacket(&packet, DHCP_MESSAGE_TYPE_REQUEST, IP.ToHex()); + /* CreatePacket() accepts IP as MSB */ + CreatePacket(&packet, DHCP_MESSAGE_TYPE_REQUEST, b32(IP.v4.ToHex())); UDPSocket->SocketUDP->Send(UDPSocket, (uint8_t *)&packet, sizeof(DHCPHeader)); } @@ -106,7 +122,7 @@ namespace NetworkDHCP { uint8_t *Option = Packet->Options + 4; uint8_t Current = *Option; - while (Current != 0xff) + while (Current != 0xFF) { uint8_t OptionLength = *(Option + 1); if (Current == Type) @@ -126,17 +142,23 @@ namespace NetworkDHCP switch (*MessageType) { case DHCP_OPTION_TIME_OFFSET: - this->Request(InternetProtocol4().FromHex(Packet->YourIP)); + { + InternetProtocol ReqIP; + ReqIP.v4.FromHex(b32(Packet->YourIP)); + netdbg("Received DHCP offer for IP %s", ReqIP.v4.ToStringLittleEndian()); + this->Request(ReqIP); 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->IP.v4.FromHex(b32(Packet->YourIP)); + this->Gateway.v4.FromHex(b32((uint32_t)(*(uintptr_t *)GetOption(Packet, DHCP_OPTION_ROUTER)))); + this->DomainNameSystem.v4.FromHex(b32((uint32_t)(*(uintptr_t *)GetOption(Packet, DHCP_OPTION_DOMAIN_NAME_SERVER)))); + this->SubNetworkMask.v4.FromHex(b32((uint32_t)(*(uintptr_t *)GetOption(Packet, DHCP_OPTION_SUBNETMASK)))); this->Received = true; + netdbg("Received DHCP ACK for IP %s", this->IP.v4.ToStringLittleEndian()); break; default: - netdbg("Received unknown message type %#x", *MessageType); + warn("Received unknown message type %#x", *MessageType); break; } } diff --git a/Network/Ethernet.cpp b/Network/Ethernet.cpp index 95ddcbe..92ef04e 100644 --- a/Network/Ethernet.cpp +++ b/Network/Ethernet.cpp @@ -5,26 +5,6 @@ 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; @@ -33,62 +13,87 @@ namespace NetworkEthernet Vector RegisteredEvents; + 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("Sending frame type %#x to %s", Type, MAC.ToString()); + size_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); + /* Network Interface Manager takes care of physical allocation. + So basically, we allocate here and then it allocates again but 1:1 mapped. */ + NIManager->Send(Interface, (uint8_t *)Packet, PacketLength); + kfree(Packet); + } + void Ethernet::Receive(uint8_t *Data, uint64_t Length) { EthernetPacket *Packet = (EthernetPacket *)Data; + size_t PacketLength = Length - sizeof(EthernetHeader); + /* TODO: I have to do checks here to be sure that PacketLength is right */ + UNUSED(PacketLength); + 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)); + netdbg("Received frame type %#x from %s to %s", b16(Packet->Header.Type), SourceMAC.ToString(), DestinationMAC.ToString()); + /* Byte-swapped little-endian */ + if (b48(Packet->Header.DestinationMAC) == 0xFFFFFFFFFFFF || + /* Byte-swapped Driver interface has little-endian order */ + b48(Packet->Header.DestinationMAC) == this->Interface->MAC.ToHex()) + /* This is true only if the packet is for us (Interface MAC or broadcast) */ + { + netdbg("Received data from %s [Type %#x]", SourceMAC.ToString(), 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); + foreach (auto e in RegisteredEvents) + if (e.Type == TYPE_IPV4) + Reply = e.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); + foreach (auto e in RegisteredEvents) + if (e.Type == TYPE_ARP) + Reply = e.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); + foreach (auto e in RegisteredEvents) + if (e.Type == TYPE_RARP) + Reply = e.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); + foreach (auto e in RegisteredEvents) + if (e.Type == TYPE_IPV6) + Reply = e.Ptr->OnEthernetPacketReceived((uint8_t *)Packet->Data, Length); break; default: - warn("ETH: Unknown packet type %#lx", Packet->Header.Type); + warn("Unknown packet type %#lx", Packet->Header.Type); break; } if (Reply) { - Packet->Header.DestinationMAC = Packet->Header.SourceMAC; - Packet->Header.SourceMAC = b48(this->Interface->MAC.ToHex()); + /* FIXME: I should reply, right? I have to do more research here... */ + // Packet->Header.DestinationMAC = Packet->Header.SourceMAC; + // Packet->Header.SourceMAC = b48(this->Interface->MAC.ToHex()); + fixme("Replying to %s [%s]=>[%s]", SourceMAC.ToString(), + this->Interface->MAC.ToString(), DestinationMAC.ToString()); } } 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]); + netdbg("Packet not for us [%s]=>[%s]", this->Interface->MAC.ToString(), DestinationMAC.ToString()); } } @@ -100,13 +105,13 @@ namespace NetworkEthernet EthernetEvents::EthernetEvents(FrameType Type) { - FType = Type; + this->FType = Type; RegisteredEvents.push_back({.Ptr = this, .Type = (uint16_t)Type}); } EthernetEvents::~EthernetEvents() { - for (uint64_t i = 0; i < RegisteredEvents.size(); i++) + for (size_t i = 0; i < RegisteredEvents.size(); i++) if (RegisteredEvents[i].Ptr == this) { RegisteredEvents.remove(i); diff --git a/Network/InternetControlMessageProtocol.cpp b/Network/InternetControlMessageProtocol.cpp index 7315c3a..214fc34 100644 --- a/Network/InternetControlMessageProtocol.cpp +++ b/Network/InternetControlMessageProtocol.cpp @@ -19,7 +19,7 @@ namespace NetworkICMPv4 if (Packet->Header.Type == ICMPv4Type::TYPE_ECHO) { // TODO: This probably doesn't work - netdbg("ICMPv4: Echo Request"); + netdbg("Echo Request"); Packet->Header.Type = ICMPv4Type::TYPE_ECHO_REPLY; Packet->Header.Code = 0x0; Packet->Header.Checksum = CalculateChecksum((uint16_t *)Packet, sizeof(ICMPHeader)); @@ -27,7 +27,7 @@ namespace NetworkICMPv4 } else { - netdbg("ICMPv4: Unknown type %d", Packet->Header.Type); + netdbg("Unknown type %d", Packet->Header.Type); } } } diff --git a/Network/InternetProtocol.cpp b/Network/InternetProtocol.cpp index 29b37aa..2ff10eb 100644 --- a/Network/InternetProtocol.cpp +++ b/Network/InternetProtocol.cpp @@ -7,7 +7,6 @@ namespace NetworkIPv4 { IPv4::IPv4(NetworkARP::ARP *ARP, NetworkEthernet::Ethernet *Ethernet) : NetworkEthernet::EthernetEvents(NetworkEthernet::TYPE_IPV4) { - netdbg("IPv4: Initializing."); this->ARP = ARP; this->Ethernet = Ethernet; } @@ -16,30 +15,32 @@ namespace NetworkIPv4 { } - void IPv4::Send(uint8_t *Data, uint64_t Length, uint8_t Protocol, InternetProtocol4 DestinationIP) + void IPv4::Send(uint8_t *Data, uint64_t Length, uint8_t Protocol, InternetProtocol DestinationIP) { - netdbg("IPv4: Sending %ld bytes to %d.%d.%d.%d", Length, DestinationIP.Address[0], DestinationIP.Address[1], DestinationIP.Address[2], DestinationIP.Address[3]); + netdbg("Sending %ld bytes to %s", Length, DestinationIP.v4.ToStringLittleEndian()); IPv4Packet *Packet = (IPv4Packet *)kmalloc(Length + sizeof(IPv4Header)); - Packet->Header.Version = 4; - Packet->Header.IHL = sizeof(IPv4Header) / 4; - Packet->Header.TypeOfService = 0; + /* This part is the most confusing one for me. */ + Packet->Header.Version = b8(4); + Packet->Header.IHL = b8(sizeof(IPv4Header) / 4); + Packet->Header.TypeOfService = b8(0); + /* We don't byteswap. */ 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.Identification = b16(0x0000); + Packet->Header.Flags = b8(0x0); + Packet->Header.FragmentOffset = b8(0x0); + Packet->Header.TimeToLive = b8(64); + Packet->Header.Protocol = b8(Protocol); + Packet->Header.DestinationIP = b32(DestinationIP.v4.ToHex()); + Packet->Header.SourceIP = b32(Ethernet->GetInterface()->IP.v4.ToHex()); + Packet->Header.HeaderChecksum = b16(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())) + InternetProtocol DestinationRoute = DestinationIP; + if ((DestinationIP.v4.ToHex() & SubNetworkMaskIP.v4.ToHex()) != (b32(Packet->Header.SourceIP) & SubNetworkMaskIP.v4.ToHex())) DestinationRoute = SubNetworkMaskIP; Ethernet->Send(MediaAccessControl().FromHex(ARP->Resolve(DestinationRoute)), this->GetFrameType(), (uint8_t *)Packet, Length + sizeof(IPv4Header)); @@ -51,16 +52,16 @@ namespace NetworkIPv4 bool IPv4::OnEthernetPacketReceived(uint8_t *Data, uint64_t Length) { IPv4Packet *Packet = (IPv4Packet *)Data; - netdbg("IPv4: Received %d bytes [Protocol %ld]", Length, Packet->Header.Protocol); + netdbg("Received %d bytes [Protocol %ld]", Length, Packet->Header.Protocol); if (Length < sizeof(IPv4Header)) { - warn("IPv4: Packet too short"); + warn("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) + if (b32(Packet->Header.DestinationIP) == Ethernet->GetInterface()->IP.v4.ToHex() || b32(Packet->Header.DestinationIP) == 0xFFFFFFFF || Ethernet->GetInterface()->IP.v4.ToHex() == 0) { uint64_t TotalLength = Packet->Header.TotalLength; if (TotalLength > Length) @@ -68,8 +69,22 @@ namespace NetworkIPv4 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)) + { + InternetProtocol SourceIP; + InternetProtocol DestinationIP; + + SourceIP.v4 = SourceIP.v4.FromHex(b32(Packet->Header.SourceIP)); + DestinationIP.v4 = DestinationIP.v4.FromHex(b32(Packet->Header.DestinationIP)); + + if (Event->OnIPv4PacketReceived(SourceIP, DestinationIP, (uint8_t *)((uint64_t)Data + 4 * Packet->Header.IHL), TotalLength - 4 * Packet->Header.IHL)) Reply = true; + } + } + else + { + netdbg("Not for us. We are %s but this is for %s", + Ethernet->GetInterface()->IP.v4.ToHex(), + Packet->Header.DestinationIP); } if (Reply) diff --git a/Network/NetworkController.cpp b/Network/NetworkController.cpp index ab837ea..a8bd052 100644 --- a/Network/NetworkController.cpp +++ b/Network/NetworkController.cpp @@ -1,13 +1,15 @@ #include + +#include +#include #include #include -#include +#include +#include #include -#include #include #include "../kernel.h" - #include "../DAPI.hpp" #include "../Fex.hpp" @@ -37,7 +39,7 @@ namespace NetworkInterfaceManager // Unregister all events for (size_t i = 0; i < RegisteredEvents.size(); i++) - RegisteredEvents.remove(i); + RegisteredEvents.remove(i); // Delete all interfaces and their callbacks and free the memory delete mem; @@ -64,6 +66,12 @@ namespace NetworkInterfaceManager debug("Network Card: %s; MAC: %#lx", Iface->Name, Iface->MAC.ToHex()); } +#ifdef DEBUG_NETWORK +#define DbgWriteScreen(x, ...) KPrint(x, ##__VA_ARGS__) +#else +#define DbgWriteScreen(x, ...) debug(x, ##__VA_ARGS__) +#endif + void NetworkInterface::StartNetworkStack() { TaskManager->GetCurrentThread()->SetPriority(100); @@ -79,22 +87,46 @@ namespace NetworkInterfaceManager error("No network device found!"); else { + DbgWriteScreen("Using %s (%s) as the default network device", DefaultDevice->Name, DefaultDevice->MAC.ToString()); 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); + NetworkUDP::Socket *DHCP_Socket = udp->Connect(InternetProtocol() /* Default value is 255.255.255.255 */, 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())); + + DefaultDevice->IP.v4.FromHex(dhcp->IP.v4.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]); + TaskManager->Sleep(200); + DbgWriteScreen("IP: %s", dhcp->IP.v4.ToStringLittleEndian()); + DbgWriteScreen("SubNetwork Mask: %s", dhcp->SubNetworkMask.v4.ToStringLittleEndian()); + DbgWriteScreen("Gateway: %s", dhcp->Gateway.v4.ToStringLittleEndian()); + DbgWriteScreen("DNS: %s", dhcp->DomainNameSystem.v4.ToStringLittleEndian()); + TaskManager->Sleep(200); + + /* + I HAVE TO REWRITE THE ENTIRE NETWORK STACK BECAUSE IT'S A MESS. I HATE BYTE SWAPPING!!!!! + + Rules to follow: + - The functions MUST have little endian parameters and return values. + */ + + /* TODO: This is a quick workaround we need DNS resolver asap. IP is time-a-g.nist.gov; https://tf.nist.gov/tf-cgi/servers.cgi */ + InternetProtocol ip = {.v4 = {.Address = {129, 6, 15, 28}}, + .v6 = {.Address = {}}}; + NetworkUDP::Socket *NTP_Socket = udp->Connect(ip, 123); + NetworkNTP::NTP *ntp = new NetworkNTP::NTP(NTP_Socket); + udp->Bind(NTP_Socket, ntp); + int UnixTimestamp = ntp->ReadTime(); + Time::Clock time = Time::ConvertFromUnix(UnixTimestamp); + DbgWriteScreen("NTP: %d - %d.%d.%d %d:%d:%d", UnixTimestamp, + time.Day, time.Month, time.Year, + time.Hour, time.Minute, time.Second); + TaskManager->Sleep(200); /* TODO: Store everything in an vector and initialize all network cards */ } diff --git a/Network/NetworkDebugger.cpp b/Network/NetworkDebugger.cpp index 991fe80..719e444 100644 --- a/Network/NetworkDebugger.cpp +++ b/Network/NetworkDebugger.cpp @@ -6,16 +6,20 @@ TODO: This code is a mess. It needs to be cleaned up. #ifdef DEBUG_NETWORK -#include +#include #include -#include "../drivers/serial.h" +#include + +using namespace UniversalAsynchronousReceiverTransmitter; + +NewLock(netdbg_lock); namespace NetDbg { class NETWORK_DEBUG : public NetworkInterfaceManager::Events { public: - static inline void print_wrapper(char c, void *unused) { write_serial(COM1, c); } + static inline void print_wrapper(char c, void *unused) { UART(COM1).Write(c); } int vprintf(const char *format, va_list list) { return vfctprintf(print_wrapper, NULL, format, list); } void WriteRaw(const char *format, ...) { @@ -27,6 +31,7 @@ namespace NetDbg void DumpData(const char *Description, void *Address, unsigned long Length) { + SmartLock(netdbg_lock); WriteRaw("-------------------------------------------------------------------------\n"); unsigned char *AddressChar = (unsigned char *)Address; unsigned char Buffer[17]; diff --git a/Network/NetworkTimeProtocol.cpp b/Network/NetworkTimeProtocol.cpp index 384bb3a..a4d55af 100644 --- a/Network/NetworkTimeProtocol.cpp +++ b/Network/NetworkTimeProtocol.cpp @@ -5,17 +5,44 @@ namespace NetworkNTP { - NTP::NTP(NetworkUDP::Socket *Socket) : NetworkUDP::UDPEvents() + void NTP::OnUDPPacketReceived(NetworkUDP::Socket *Socket, uint8_t *Data, uint64_t Length) { - this->Socket = Socket; + this->NTPPacket = *(NTPHeader *)Data; + this->TimeReceived = true; + netdbg("Received UDP packet for NTP."); } - NTP::~NTP() - { - } + NTP::NTP(NetworkUDP::Socket *Socket) : NetworkUDP::UDPEvents() { this->UDPSocket = Socket; } + NTP::~NTP() {} - void ReadTime() + int NTP::ReadTime() { - fixme("ReadTime()"); + netdbg("Requesting time"); + this->TimeReceived = false; + + NTPHeader ReqPacket; // This may require phyiscal memory allocation but Ethernet already has this job. + memset(&ReqPacket, 0, sizeof(NTPHeader)); // Zero out the packet + *((char *)&ReqPacket) = 0x1b; // byteswap nightmare, this is the code below but in little endian + // ReqPacket.LeapIndicator = 0; + // ReqPacket.VersionNumber = 3; + // ReqPacket.Mode = 3; + UDPSocket->SocketUDP->Send(UDPSocket, (uint8_t *)&ReqPacket, sizeof(NTPHeader)); + + debug("Waiting for response..."); + int RequestTimeout = 20; + while (!this->TimeReceived) + { + if (--RequestTimeout == 0) + { + warn("Request timeout."); + return 0; + } + netdbg("Still waiting..."); + TaskManager->Sleep(1000); + } + + int UnixTimestamp = b32(this->NTPPacket.TransmitTimestamp[0]) - 2208988800; + debug("Unix time: %d", UnixTimestamp); + return UnixTimestamp; } } diff --git a/Network/UserDatagramProtocol.cpp b/Network/UserDatagramProtocol.cpp index 1827dbb..f1e55e5 100644 --- a/Network/UserDatagramProtocol.cpp +++ b/Network/UserDatagramProtocol.cpp @@ -20,7 +20,6 @@ namespace NetworkUDP UDP::UDP(NetworkIPv4::IPv4 *ipv4, NetworkInterfaceManager::DeviceInterface *Interface) : NetworkIPv4::IPv4Events(NetworkIPv4::PROTOCOL_UDP) { - netdbg("UDP: Initializing."); this->ipv4 = ipv4; this->Interface = Interface; } @@ -29,16 +28,16 @@ namespace NetworkUDP uint16_t UsablePort = 0x200; - Socket *UDP::Connect(InternetProtocol4 IP, uint16_t Port) + Socket *UDP::Connect(InternetProtocol 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); + netdbg("Connecting to %s", IP.v4.ToStringLittleEndian(), 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); + socket->LocalPort = b16(socket->LocalPort); + socket->RemotePort = b16(socket->RemotePort); RegisteredEvents.push_back({.UDPSocket = socket, .Port = socket->LocalPort}); return socket; } @@ -56,7 +55,7 @@ namespace NetworkUDP 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); + netdbg("Sending %d bytes to %s", Length, Socket->RemoteIP.v4.ToStringLittleEndian(), Socket->RemotePort); uint16_t TotalLength = Length + sizeof(UDPHeader); UDPPacket *packet = (UDPPacket *)kmalloc(TotalLength); packet->Header.SourcePort = Socket->LocalPort; @@ -69,36 +68,40 @@ namespace NetworkUDP 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) + void UDP::Bind(Socket *Socket, UDPEvents *EventHandler) { - netdbg("UDP: Received %d bytes from %d.%d.%d.%d", Length, SourceIP.Address[0], SourceIP.Address[1], SourceIP.Address[2], SourceIP.Address[3]); + netdbg("Binding socket to %s", Socket->LocalIP.v4.ToStringLittleEndian(), Socket->LocalPort); + Socket->EventHandler = EventHandler; + } + + bool UDP::OnIPv4PacketReceived(InternetProtocol SourceIP, InternetProtocol DestinationIP, uint8_t *Data, uint64_t Length) + { + netdbg("Received %d bytes from %s", Length, SourceIP.v4.ToStringLittleEndian()); 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)); + netdbg("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", + netdbg("UDP->SKT[]: LP:%d | LIP:%s | RP:%d | RIP:%s | 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], + var.UDPSocket->LocalIP.v4.ToStringLittleEndian(), b16(var.UDPSocket->RemotePort), - var.UDPSocket->RemoteIP.Address[0], var.UDPSocket->RemoteIP.Address[1], var.UDPSocket->RemoteIP.Address[2], var.UDPSocket->RemoteIP.Address[3], + var.UDPSocket->RemoteIP.v4.ToStringLittleEndian(), b16(var.UDPSocket->Listening)); if (var.UDPSocket->LocalPort == udp->DestinationPort && - var.UDPSocket->LocalIP == DestinationIP && + var.UDPSocket->LocalIP.v4 == DestinationIP.v4 && var.UDPSocket->Listening == true) { var.UDPSocket->Listening = false; var.UDPSocket->RemotePort = b16(udp->SourcePort); var.UDPSocket->RemoteIP = SourceIP; - netdbg("UDP: E1"); + netdbg("E1"); return true; } @@ -107,7 +110,7 @@ namespace NetworkUDP if (GoodSocket) GoodSocket->EventHandler->OnUDPPacketReceived(GoodSocket, ((UDPPacket *)Data)->Data, Length); - netdbg("UDP: E0 (Success)"); + netdbg("E0 (Success)"); return false; } diff --git a/include/net/arp.hpp b/include/net/arp.hpp index 24a2c85..2206406 100644 --- a/include/net/arp.hpp +++ b/include/net/arp.hpp @@ -43,7 +43,7 @@ namespace NetworkARP struct DiscoveredAddress { MediaAccessControl MAC; - InternetProtocol4 IP; + InternetProtocol IP; }; class ARP : public NetworkEthernet::EthernetEvents @@ -60,9 +60,9 @@ namespace NetworkARP }; Vector DiscoveredAddresses; - DiscoveredAddress *ManageDA(DAType Type, InternetProtocol4 IP, MediaAccessControl MAC); - DiscoveredAddress *Search(InternetProtocol4 TargetIP); - DiscoveredAddress *Update(InternetProtocol4 TargetIP, MediaAccessControl TargetMAC); + DiscoveredAddress *ManageDiscoveredAddresses(DAType Type, InternetProtocol IP, MediaAccessControl MAC); + DiscoveredAddress *Search(InternetProtocol TargetIP); + DiscoveredAddress *Update(InternetProtocol TargetIP, MediaAccessControl TargetMAC); bool OnEthernetPacketReceived(uint8_t *Data, uint64_t Length); public: @@ -75,14 +75,14 @@ namespace NetworkARP * @param IP The IP address to resolve. (Little-endian) * @return uint48_t The MAC address of the IP address. */ - uint48_t Resolve(InternetProtocol4 IP); + uint48_t Resolve(InternetProtocol IP); /** * @brief Broadcast an ARP packet. * * @param IP The IP address to broadcast. */ - void Broadcast(InternetProtocol4 IP); + void Broadcast(InternetProtocol IP); }; } diff --git a/include/net/dhcp.hpp b/include/net/dhcp.hpp index 74c18c3..1770f91 100644 --- a/include/net/dhcp.hpp +++ b/include/net/dhcp.hpp @@ -143,23 +143,22 @@ namespace NetworkDHCP void CreatePacket(DHCPHeader *Packet, uint8_t MessageType, uint32_t RequestIP); void *GetOption(DHCPHeader *Packet, uint8_t Type); + void OnUDPPacketReceived(NetworkUDP::Socket *Socket, uint8_t *Data, uint64_t Length); public: /** @brief IP address (Little-endian) */ - InternetProtocol4 IP = {.Address = {0x0, 0x0, 0x0, 0x0}}; + InternetProtocol IP = {}; /** @brief Gateway address (Little-endian) */ - InternetProtocol4 Gateway = {.Address = {0x0, 0x0, 0x0, 0x0}}; + InternetProtocol Gateway = {}; /** @brief Subnet mask (Little-endian) */ - InternetProtocol4 SubNetworkMask = {.Address = {0x0, 0x0, 0x0, 0x0}}; + InternetProtocol SubNetworkMask = {}; /** @brief DNS server address (Little-endian) */ - InternetProtocol4 DomainNameSystem = {.Address = {0x0, 0x0, 0x0, 0x0}}; + InternetProtocol DomainNameSystem = {}; 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); + void Request(InternetProtocol IP); }; } diff --git a/include/net/dns.hpp b/include/net/dns.hpp new file mode 100644 index 0000000..7465896 --- /dev/null +++ b/include/net/dns.hpp @@ -0,0 +1,20 @@ +#ifndef __FENNIX_KERNEL_DNS_H__ +#define __FENNIX_KERNEL_DNS_H__ + +#include +#include + +namespace NetworkDNS +{ + class DNS : public NetworkUDP::UDPEvents + { + private: + NetworkUDP::Socket *UDPSocket; + + public: + DNS(NetworkUDP::Socket *Socket); + ~DNS(); + }; +} + +#endif // !__FENNIX_KERNEL_DNS_H__ diff --git a/include/net/eth.hpp b/include/net/eth.hpp index 01fc41d..99f05bb 100644 --- a/include/net/eth.hpp +++ b/include/net/eth.hpp @@ -57,7 +57,14 @@ namespace NetworkEthernet /** @brief Get driver interface * @return Driver interface */ - NetworkInterfaceManager::DeviceInterface *GetInterface() { return this->Interface; } + NetworkInterfaceManager::DeviceInterface *GetInterface() + { + netdbg("Interface: %#lx (MAC: %s; IPv4: %s; IPv6: %s)", this->Interface, + this->Interface->MAC.ToString(), + this->Interface->IP.v4.ToStringLittleEndian(), + this->Interface->IP.v6.ToStringLittleEndian()); + return this->Interface; + } Ethernet(NetworkInterfaceManager::DeviceInterface *Interface); ~Ethernet(); diff --git a/include/net/ipv4.hpp b/include/net/ipv4.hpp index 2a97f34..a704fce 100644 --- a/include/net/ipv4.hpp +++ b/include/net/ipv4.hpp @@ -15,7 +15,8 @@ namespace NetworkIPv4 uint8_t TypeOfService; uint16_t TotalLength; uint16_t Identification; - uint16_t FlagsAndFragmentOffset; + uint8_t Flags; + uint8_t FragmentOffset; uint8_t TimeToLive; uint8_t Protocol; uint16_t HeaderChecksum; @@ -76,8 +77,8 @@ namespace NetworkIPv4 virtual bool OnEthernetPacketReceived(uint8_t *Data, uint64_t Length); public: - InternetProtocol4 GatewayIP = {.Address = {0xFF, 0xFF, 0xFF, 0xFF}}; - InternetProtocol4 SubNetworkMaskIP = {.Address = {0xFF, 0xFF, 0xFF, 0xFF}}; + InternetProtocol GatewayIP; + InternetProtocol SubNetworkMaskIP; IPv4(NetworkARP::ARP *ARP, NetworkEthernet::Ethernet *Ethernet); ~IPv4(); @@ -89,7 +90,7 @@ namespace NetworkIPv4 * @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); + void Send(uint8_t *Data, uint64_t Length, uint8_t Protocol, InternetProtocol DestinationIP); }; class IPv4Events @@ -104,7 +105,7 @@ namespace NetworkIPv4 public: uint8_t GetProtocol() { return Protocol; } - virtual bool OnIPv4PacketReceived(InternetProtocol4 SourceIP, InternetProtocol4 DestinationIP, uint8_t *Data, uint64_t Length) + virtual bool OnIPv4PacketReceived(InternetProtocol SourceIP, InternetProtocol DestinationIP, uint8_t *Data, uint64_t Length) { warn("Not implemented."); return false; diff --git a/include/net/nc.hpp b/include/net/nc.hpp index 34420f6..0fb8703 100644 --- a/include/net/nc.hpp +++ b/include/net/nc.hpp @@ -22,7 +22,7 @@ namespace NetworkInterfaceManager MediaAccessControl MAC; /** @brief Device interface IP address (Big-endian) */ - InternetProtocol4 IP; + InternetProtocol IP; /** @brief Reserved */ void *DriverCallBackAddress; diff --git a/include/net/net.hpp b/include/net/net.hpp index e6ab64e..05f837f 100644 --- a/include/net/net.hpp +++ b/include/net/net.hpp @@ -2,8 +2,9 @@ #define __FENNIX_KERNEL_NETWORK_H__ #include +#include -// #define DEBUG_NETWORK 1 +#define DEBUG_NETWORK 1 #ifdef DEBUG_NETWORK #define netdbg(m, ...) debug(m, ##__VA_ARGS__) @@ -25,9 +26,16 @@ typedef __UINT64_TYPE__ uint48_t; #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) +enum Endianness +{ + LITTLE_ENDIAN, + BIG_ENDIAN +}; + struct MediaAccessControl { - uint8_t Address[6]; + uint8_t Address[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; + Endianness Endianess = LITTLE_ENDIAN; inline bool operator==(const MediaAccessControl &lhs) const { @@ -96,53 +104,114 @@ struct MediaAccessControl this->Address[4] != 0xFF || this->Address[5] != 0xFF); } + + char *ToString() + { + static char Buffer[18]; + sprintf(Buffer, "%02X:%02X:%02X:%02X:%02X:%02X", this->Address[0], this->Address[1], this->Address[2], this->Address[3], this->Address[4], this->Address[5]); + return Buffer; + } }; -struct InternetProtocol4 +/* There's a confusion between LSB and MSB. Not sure if "ToStringLittleEndian" and "ToStringBigEndian" are implemented correctly. + Because x86 is a LSB architecture, I'm assuming that the "ToStringLittleEndian" is correct? */ +struct InternetProtocol { - uint8_t Address[4]; - - inline bool operator==(const InternetProtocol4 &lhs) const + struct Version4 { - 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]; - } + uint8_t Address[4] = {255, 255, 255, 255}; + Endianness Endianess = LITTLE_ENDIAN; - inline bool operator==(const uint32_t &lhs) const + inline bool operator==(const InternetProtocol::Version4 &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 + { + InternetProtocol::Version4 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 InternetProtocol::Version4 &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 InternetProtocol::Version4 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; + } + + char *ToStringLittleEndian() + { + static char Buffer[16]; + sprintf(Buffer, "%d.%d.%d.%d", this->Address[0], this->Address[1], this->Address[2], this->Address[3]); + return Buffer; + } + + char *ToStringBigEndian() + { + static char Buffer[16]; + sprintf(Buffer, "%d.%d.%d.%d", this->Address[3], this->Address[2], this->Address[1], this->Address[0]); + return Buffer; + } + } v4; + + struct Version6 { - 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); + uint16_t Address[8] = {0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF}; + Endianness Endianess = LITTLE_ENDIAN; - 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 InternetProtocol::Version6 &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] && + lhs.Address[6] == this->Address[6] && + lhs.Address[7] == this->Address[7]; + } - inline bool operator!=(const InternetProtocol4 &lhs) const { return !(*this == lhs); } - inline bool operator!=(const uint32_t &lhs) const { return !(*this == lhs); } + inline bool operator!=(const InternetProtocol::Version6 &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]); - } + char *ToStringLittleEndian() + { + static char Buffer[40]; + sprintf(Buffer, "%04X:%04X:%04X:%04X:%04X:%04X:%04X:%04X", this->Address[0], this->Address[1], this->Address[2], this->Address[3], this->Address[4], this->Address[5], this->Address[6], this->Address[7]); + return Buffer; + } - 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; - } + char *ToStringBigEndian() + { + static char Buffer[40]; + sprintf(Buffer, "%04X:%04X:%04X:%04X:%04X:%04X:%04X:%04X", this->Address[7], this->Address[6], this->Address[5], this->Address[4], this->Address[3], this->Address[2], this->Address[1], this->Address[0]); + return Buffer; + } + } v6; }; uint16_t CalculateChecksum(uint16_t *Data, uint64_t Length); diff --git a/include/net/ntp.hpp b/include/net/ntp.hpp index b8878de..425dfc2 100644 --- a/include/net/ntp.hpp +++ b/include/net/ntp.hpp @@ -8,31 +8,141 @@ namespace NetworkNTP { struct NTPHeader { - uint8_t LIv; - uint8_t VN; - uint8_t Mode; + /** @brief Leap indicator + * 00 - no warning + * 01 - last minute has 61 seconds + * 10 - last minute has 59 seconds + * 11 - alarm condition (clock not synchronized) + */ + uint8_t LeapIndicator : 2; + /** @brief Version number of the protocol + * 3 - IPv4 only + * 4 - IPv4, IPv6 and OSI + * 5 - IPv4, IPv6 and OSI + * 6 - IPv4, IPv6 and OSI + * 7 - IPv4, IPv6 and OSI + */ + uint8_t VersionNumber : 3; + /** @brief Mode + * 0 - reserved + * 1 - symmetric active + * 2 - symmetric passive + * 3 - client + * 4 - server + * 5 - broadcast + * 6 - reserved for NTP control message + * 7 - reserved for private use + */ + uint8_t Mode : 3; + /** @brief Stratum + * 0 - unspecified or unavailable + * 1 - primary reference (e.g. radio clock) + * 2-15 - secondary reference (via NTP or SNTP) + * 16 - unsynchronized + * 17-255 - reserved + */ uint8_t Stratum; + /** @brief Polling interval + * 4 - 16 seconds + * 5 - 32 seconds + * 6 - 64 seconds + * 7 - 128 seconds + * 8 - 256 seconds + * 9 - 512 seconds + * 10 - 1024 seconds + * 11 - 2048 seconds + * 12 - 4096 seconds + * 13 - 8192 seconds + * 14 - 16384 seconds + * 15 - 32768 seconds + */ uint8_t Poll; + /** @brief Precision + * -6 - 0.015625 seconds + * -5 - 0.03125 seconds + * -4 - 0.0625 seconds + * -3 - 0.125 seconds + * -2 - 0.25 seconds + * -1 - 0.5 seconds + * 0 - 1 second + * 1 - 2 seconds + * 2 - 4 seconds + * 3 - 8 seconds + * 4 - 16 seconds + * 5 - 32 seconds + * 6 - 64 seconds + * 7 - 128 seconds + */ uint8_t Precision; + /** @brief Root delay + * Total round trip delay to the primary reference source + */ uint32_t RootDelay; + /** @brief Root dispersion + * Nominal error relative to the primary reference source + */ uint32_t RootDispersion; - uint32_t ReferenceID; - uint32_t ReferenceTimestamp; - uint32_t OriginateTimestamp; - uint32_t ReceiveTimestamp; - uint32_t TransmitTimestamp; + /** @brief Reference identifier + * 0x00000000 - unspecified + * 0x00000001 - radio clock + * 0x00000002 - atomic clock + * 0x00000003 - GPS receiver + * 0x00000004 - local oscillator + * 0x00000005 - LORAN-C receiver + * 0x00000006 - microprocessor + * 0x00000007 - internet + * 0x00000008 - FLL + * 0x00000009 - other + * 0x0000000A - WWV + * 0x0000000B - WWVB + * 0x0000000C - WWVH + * 0x0000000D - NIST dialup + * 0x0000000E - telephone + * 0x0000000F - reserved + */ + uint32_t ReferenceIdentifier; + /** @brief Reference timestamp + * The time at which the clock was last set or corrected + */ + uint32_t ReferenceTimestamp[2]; + /** @brief Originate timestamp + * The time at which the request departed the client for the server + */ + uint32_t OriginateTimestamp[2]; + /** @brief Receive timestamp + * The time at which the request arrived at the server + */ + uint32_t ReceiveTimestamp[2]; + /** @brief Transmit timestamp + * The time at which the reply departed the server for the client + */ + uint32_t TransmitTimestamp[2]; + /** @brief Message authentication code + * Key identifier + * @note Only when the NTP authentication scheme is used + */ + // uint32_t MessageAuthenticationCode; } __attribute__((packed)); class NTP : public NetworkUDP::UDPEvents { private: - NetworkUDP::Socket *Socket; + NetworkUDP::Socket *UDPSocket; + bool TimeReceived = false; + NTPHeader NTPPacket; + + virtual void OnUDPPacketReceived(NetworkUDP::Socket *Socket, uint8_t *Data, uint64_t Length); public: NTP(NetworkUDP::Socket *Socket); ~NTP(); - void ReadTime(); + /** + * @brief Get the time from the NTP server + * + * @return Unix Timestamp + */ + int ReadTime(); }; } diff --git a/include/net/udp.hpp b/include/net/udp.hpp index 32415b3..b758d55 100644 --- a/include/net/udp.hpp +++ b/include/net/udp.hpp @@ -49,21 +49,21 @@ namespace NetworkUDP UDP(NetworkIPv4::IPv4 *ipv4, NetworkInterfaceManager::DeviceInterface *Interface); ~UDP(); - virtual Socket *Connect(InternetProtocol4 IP, uint16_t Port); + virtual Socket *Connect(InternetProtocol 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); + virtual bool OnIPv4PacketReceived(InternetProtocol SourceIP, InternetProtocol DestinationIP, uint8_t *Data, uint64_t Length); }; class Socket { public: - InternetProtocol4 LocalIP = {.Address = {0xFF, 0xFF, 0xFF, 0xFF}}; + InternetProtocol LocalIP; uint16_t LocalPort = 0; - InternetProtocol4 RemoteIP = {.Address = {0xFF, 0xFF, 0xFF, 0xFF}}; + InternetProtocol RemoteIP; uint16_t RemotePort = 0; bool Listening = false; UDPEvents *EventHandler = nullptr;