Updated network related code so now it should work as expected

This commit is contained in:
Alex 2023-01-09 03:32:17 +02:00
parent ad16d361dc
commit 4f6c7e8a0d
Signed by untrusted user who does not match committer: enderice2
GPG Key ID: EACC3AD603BAB4DD
20 changed files with 603 additions and 246 deletions

View File

@ -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.

View File

@ -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;

View File

@ -0,0 +1,16 @@
#include <net/dns.hpp>
#include <debug.h>
#include "../kernel.h"
namespace NetworkDNS
{
DNS::DNS(NetworkUDP::Socket *Socket) : NetworkUDP::UDPEvents()
{
this->UDPSocket = Socket;
}
DNS::~DNS()
{
}
}

View File

@ -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;
}
}

View File

@ -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<EthernetEventHelperStruct> 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);

View File

@ -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);
}
}
}

View File

@ -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,9 +69,23 @@ 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)
{

View File

@ -1,13 +1,15 @@
#include <net/nc.hpp>
#include <net/ipv4.hpp>
#include <net/dhcp.hpp>
#include <net/eth.hpp>
#include <net/arp.hpp>
#include <net/ipv4.hpp>
#include <net/ntp.hpp>
#include <net/dns.hpp>
#include <net/udp.hpp>
#include <net/dhcp.hpp>
#include <debug.h>
#include "../kernel.h"
#include "../DAPI.hpp"
#include "../Fex.hpp"
@ -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 */
}

View File

@ -6,16 +6,20 @@ TODO: This code is a mess. It needs to be cleaned up.
#ifdef DEBUG_NETWORK
#include <stdarg.h>
#include <uart.hpp>
#include <printf.h>
#include "../drivers/serial.h"
#include <lock.hpp>
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];

View File

@ -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() {}
int NTP::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);
}
void ReadTime()
{
fixme("ReadTime()");
int UnixTimestamp = b32(this->NTPPacket.TransmitTimestamp[0]) - 2208988800;
debug("Unix time: %d", UnixTimestamp);
return UnixTimestamp;
}
}

View File

@ -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;
}

View File

@ -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<NetworkARP::DiscoveredAddress *> 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);
};
}

View File

@ -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);
};
}

20
include/net/dns.hpp Normal file
View File

@ -0,0 +1,20 @@
#ifndef __FENNIX_KERNEL_DNS_H__
#define __FENNIX_KERNEL_DNS_H__
#include <net/udp.hpp>
#include <types.h>
namespace NetworkDNS
{
class DNS : public NetworkUDP::UDPEvents
{
private:
NetworkUDP::Socket *UDPSocket;
public:
DNS(NetworkUDP::Socket *Socket);
~DNS();
};
}
#endif // !__FENNIX_KERNEL_DNS_H__

View File

@ -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();

View File

@ -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;

View File

@ -22,7 +22,7 @@ namespace NetworkInterfaceManager
MediaAccessControl MAC;
/** @brief Device interface IP address (Big-endian) */
InternetProtocol4 IP;
InternetProtocol IP;
/** @brief Reserved */
void *DriverCallBackAddress;

View File

@ -2,8 +2,9 @@
#define __FENNIX_KERNEL_NETWORK_H__
#include <types.h>
#include <printf.h>
// #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,13 +104,25 @@ 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];
struct Version4
{
uint8_t Address[4] = {255, 255, 255, 255};
Endianness Endianess = LITTLE_ENDIAN;
inline bool operator==(const InternetProtocol4 &lhs) const
inline bool operator==(const InternetProtocol::Version4 &lhs) const
{
return lhs.Address[0] == this->Address[0] &&
lhs.Address[1] == this->Address[1] &&
@ -112,7 +132,7 @@ struct InternetProtocol4
inline bool operator==(const uint32_t &lhs) const
{
InternetProtocol4 IP;
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);
@ -124,7 +144,7 @@ struct InternetProtocol4
IP.Address[3] == this->Address[3];
}
inline bool operator!=(const InternetProtocol4 &lhs) const { return !(*this == lhs); }
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()
@ -135,7 +155,7 @@ struct InternetProtocol4
((uint64_t)this->Address[3]);
}
inline InternetProtocol4 FromHex(uint32_t Hex)
inline InternetProtocol::Version4 FromHex(uint32_t Hex)
{
this->Address[0] = (uint8_t)((Hex >> 24) & 0xFF);
this->Address[1] = (uint8_t)((Hex >> 16) & 0xFF);
@ -143,6 +163,55 @@ struct InternetProtocol4
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
{
uint16_t Address[8] = {0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF};
Endianness Endianess = LITTLE_ENDIAN;
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 InternetProtocol::Version6 &lhs) const { return !(*this == lhs); }
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;
}
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);

View File

@ -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();
};
}

View File

@ -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;