diff --git a/kernel/CMakeLists.txt b/kernel/CMakeLists.txt index 2107df31..1b733373 100644 --- a/kernel/CMakeLists.txt +++ b/kernel/CMakeLists.txt @@ -49,6 +49,7 @@ set(KERNEL_SOURCES kernel/Memory/MemoryRegion.cpp kernel/Memory/PhysicalRange.cpp kernel/Memory/VirtualRange.cpp + kernel/Networking/ARPTable.cpp kernel/Networking/E1000/E1000.cpp kernel/Networking/E1000/E1000E.cpp kernel/Networking/IPv4.cpp diff --git a/kernel/include/kernel/Networking/ARPTable.h b/kernel/include/kernel/Networking/ARPTable.h new file mode 100644 index 00000000..0bb7c209 --- /dev/null +++ b/kernel/include/kernel/Networking/ARPTable.h @@ -0,0 +1,30 @@ +#pragma once + +#include +#include +#include +#include + +namespace Kernel +{ + + class ARPTable + { + BAN_NON_COPYABLE(ARPTable); + BAN_NON_MOVABLE(ARPTable); + + public: + static BAN::ErrorOr> create(); + + BAN::ErrorOr get_mac_from_ipv4(BAN::IPv4Address); + + private: + ARPTable(); + + private: + BAN::HashMap m_arp_table; + + friend class BAN::UniqPtr; + }; + +} diff --git a/kernel/include/kernel/Networking/NetworkManager.h b/kernel/include/kernel/Networking/NetworkManager.h index 047f0089..6d05f717 100644 --- a/kernel/include/kernel/Networking/NetworkManager.h +++ b/kernel/include/kernel/Networking/NetworkManager.h @@ -2,6 +2,7 @@ #include #include +#include #include #include #include @@ -13,6 +14,9 @@ namespace Kernel class NetworkManager : public TmpFileSystem { + BAN_NON_COPYABLE(NetworkManager); + BAN_NON_MOVABLE(NetworkManager); + public: enum class SocketType { @@ -25,6 +29,8 @@ namespace Kernel static BAN::ErrorOr initialize(); static NetworkManager& get(); + ARPTable& arp_table() { return *m_arp_table; } + BAN::ErrorOr add_interface(PCI::Device& pci_device); void unbind_socket(uint16_t port, BAN::RefPtr); @@ -38,6 +44,7 @@ namespace Kernel NetworkManager(); private: + BAN::UniqPtr m_arp_table; BAN::Vector> m_interfaces; BAN::HashMap> m_bound_sockets; }; diff --git a/kernel/include/kernel/Networking/NetworkSocket.h b/kernel/include/kernel/Networking/NetworkSocket.h index 587d4a46..2c89e9f4 100644 --- a/kernel/include/kernel/Networking/NetworkSocket.h +++ b/kernel/include/kernel/Networking/NetworkSocket.h @@ -11,6 +11,9 @@ namespace Kernel class NetworkSocket : public TmpInode, public BAN::Weakable { + BAN_NON_COPYABLE(NetworkSocket); + BAN_NON_MOVABLE(NetworkSocket); + public: static constexpr uint16_t PORT_NONE = 0; diff --git a/kernel/kernel/Networking/ARPTable.cpp b/kernel/kernel/Networking/ARPTable.cpp new file mode 100644 index 00000000..d7efdb1b --- /dev/null +++ b/kernel/kernel/Networking/ARPTable.cpp @@ -0,0 +1,27 @@ +#include + +namespace Kernel +{ + + static constexpr BAN::IPv4Address s_broadcast_ipv4 { 0xFFFFFFFF }; + static constexpr BAN::MACAddress s_broadcast_mac {{ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }}; + + BAN::ErrorOr> ARPTable::create() + { + return TRY(BAN::UniqPtr::create()); + } + + ARPTable::ARPTable() + { + + } + + BAN::ErrorOr ARPTable::get_mac_from_ipv4(BAN::IPv4Address ipv4_address) + { + if (ipv4_address == s_broadcast_ipv4) + return s_broadcast_mac; + dprintln("No MAC for IPv4 {}", ipv4_address); + return BAN::Error::from_errno(ENOTSUP); + } + +} diff --git a/kernel/kernel/Networking/NetworkManager.cpp b/kernel/kernel/Networking/NetworkManager.cpp index 33534982..d58d0ea7 100644 --- a/kernel/kernel/Networking/NetworkManager.cpp +++ b/kernel/kernel/Networking/NetworkManager.cpp @@ -19,6 +19,7 @@ namespace Kernel if (manager_ptr == nullptr) return BAN::Error::from_errno(ENOMEM); auto manager = BAN::UniqPtr::adopt(manager_ptr); + manager->m_arp_table = TRY(ARPTable::create()); TRY(manager->TmpFileSystem::initialize(0777, 0, 0)); s_instance = BAN::move(manager); return {}; diff --git a/kernel/kernel/Networking/NetworkSocket.cpp b/kernel/kernel/Networking/NetworkSocket.cpp index b37b612d..63e41195 100644 --- a/kernel/kernel/Networking/NetworkSocket.cpp +++ b/kernel/kernel/Networking/NetworkSocket.cpp @@ -58,16 +58,12 @@ namespace Kernel auto* destination = reinterpret_cast(arguments->dest_addr); auto message = BAN::ConstByteSpan((const uint8_t*)arguments->message, arguments->length); - if (destination->sin_port == PORT_NONE) + uint16_t dst_port = destination->sin_port; + if (dst_port == PORT_NONE) return BAN::Error::from_errno(EINVAL); - if (destination->sin_addr.s_addr != 0xFFFFFFFF) - { - dprintln("Only broadcast ip supported"); - return BAN::Error::from_errno(EINVAL); - } - - static BAN::MACAddress dest_mac {{ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }}; + auto dst_addr = BAN::IPv4Address(destination->sin_addr.s_addr); + auto dst_mac = TRY(NetworkManager::get().arp_table().get_mac_from_ipv4(dst_addr)); const size_t interface_header_offset = 0; const size_t interface_header_size = m_interface->interface_header_size(); @@ -87,9 +83,9 @@ namespace Kernel BAN::ByteSpan packet_bytespan { full_packet.span() }; memcpy(full_packet.data() + payload_offset, message.data(), payload_size); - add_protocol_header(packet_bytespan.slice(protocol_header_offset), m_port, destination->sin_port); - add_ipv4_header(packet_bytespan.slice(ipv4_header_offset), m_interface->get_ipv4_address(), destination->sin_addr.s_addr, protocol()); - m_interface->add_interface_header(packet_bytespan.slice(interface_header_offset), dest_mac); + add_protocol_header(packet_bytespan.slice(protocol_header_offset), m_port, dst_port); + add_ipv4_header(packet_bytespan.slice(ipv4_header_offset), m_interface->get_ipv4_address(), dst_addr, protocol()); + m_interface->add_interface_header(packet_bytespan.slice(interface_header_offset), dst_mac); TRY(m_interface->send_raw_bytes(packet_bytespan)); return arguments->length;