/* This file is part of Fennix Kernel. Fennix Kernel is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fennix Kernel is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Fennix Kernel. If not, see . */ #include #include #include "../kernel.h" /* conversion from 'uint48_t' {aka 'long unsigned int'} to 'long unsigned int:48' may change value */ #pragma GCC diagnostic ignored "-Wconversion" namespace NetworkEthernet { struct EthernetEventHelperStruct { EthernetEvents *Ptr; uint16_t Type; }; std::vector RegisteredEvents; Ethernet::Ethernet(NetworkInterfaceManager::DeviceInterface *Interface) : NetworkInterfaceManager::Events(Interface) { debug("Ethernet interface %#lx created.", this); this->Interface = Interface; } Ethernet::~Ethernet() { debug("Ethernet interface %#lx destroyed.", this); } void Ethernet::Send(MediaAccessControl MAC, FrameType Type, uint8_t *Data, size_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); assert(!"Function not implemented"); kfree(Packet); } void Ethernet::Receive(uint8_t *Data, size_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)); 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 e in RegisteredEvents) if (e.Type == TYPE_IPV4) Reply = e.Ptr->OnEthernetPacketReceived((uint8_t *)Packet->Data, Length); break; case TYPE_ARP: 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 e in RegisteredEvents) if (e.Type == TYPE_RARP) Reply = e.Ptr->OnEthernetPacketReceived((uint8_t *)Packet->Data, Length); break; case TYPE_IPV6: foreach (auto e in RegisteredEvents) if (e.Type == TYPE_IPV6) Reply = e.Ptr->OnEthernetPacketReceived((uint8_t *)Packet->Data, Length); break; default: warn("Unknown packet type %#lx", Packet->Header.Type); break; } if (Reply) { /* 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("Packet not for us [%s]=>[%s]", this->Interface->MAC.ToString(), DestinationMAC.ToString()); } } void Ethernet::OnInterfaceReceived(NetworkInterfaceManager::DeviceInterface *Interface, uint8_t *Data, size_t Length) { if (Interface == this->Interface) this->Receive(Data, Length); } EthernetEvents::EthernetEvents(FrameType Type) { this->FType = Type; RegisteredEvents.push_back({.Ptr = this, .Type = (uint16_t)Type}); } EthernetEvents::~EthernetEvents() { forItr(itr, RegisteredEvents) { if (itr->Ptr == this) { RegisteredEvents.erase(itr); return; } } } }