mirror of
https://github.com/Fennix-Project/Kernel.git
synced 2025-05-28 15:34:33 +00:00
Updated network related code so now it should work as expected
This commit is contained in:
parent
ad16d361dc
commit
4f6c7e8a0d
@ -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.
|
||||
|
@ -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;
|
||||
|
16
Network/DomainNameSystem.cpp
Normal file
16
Network/DomainNameSystem.cpp
Normal 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()
|
||||
{
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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"
|
||||
|
||||
@ -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 */
|
||||
}
|
||||
|
@ -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];
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -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
20
include/net/dns.hpp
Normal 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__
|
@ -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();
|
||||
|
@ -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;
|
||||
|
@ -22,7 +22,7 @@ namespace NetworkInterfaceManager
|
||||
MediaAccessControl MAC;
|
||||
|
||||
/** @brief Device interface IP address (Big-endian) */
|
||||
InternetProtocol4 IP;
|
||||
InternetProtocol IP;
|
||||
|
||||
/** @brief Reserved */
|
||||
void *DriverCallBackAddress;
|
||||
|
@ -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,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);
|
||||
|
@ -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();
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user