diff --git a/kernel/CMakeLists.txt b/kernel/CMakeLists.txt index f66bd685..8ba07f0a 100644 --- a/kernel/CMakeLists.txt +++ b/kernel/CMakeLists.txt @@ -52,6 +52,9 @@ set(KERNEL_SOURCES kernel/Networking/E1000/E1000.cpp kernel/Networking/E1000/E1000E.cpp kernel/Networking/NetworkInterface.cpp + kernel/Networking/NetworkManager.cpp + kernel/Networking/NetworkSocket.cpp + kernel/Networking/UDPSocket.cpp kernel/OpenFileDescriptorSet.cpp kernel/Panic.cpp kernel/PCI.cpp diff --git a/kernel/include/kernel/Networking/NetworkManager.h b/kernel/include/kernel/Networking/NetworkManager.h new file mode 100644 index 00000000..112474bd --- /dev/null +++ b/kernel/include/kernel/Networking/NetworkManager.h @@ -0,0 +1,39 @@ +#pragma once + +#include +#include +#include +#include +#include + +namespace Kernel +{ + + class NetworkManager : public TmpFileSystem + { + public: + enum class SocketType + { + STREAM, + DGRAM, + SEQPACKET, + }; + + public: + static BAN::ErrorOr initialize(); + static NetworkManager& get(); + + BAN::ErrorOr add_interface(PCI::Device& pci_device); + BAN::ErrorOr bind_socket(int port, BAN::RefPtr); + + BAN::ErrorOr> create_socket(SocketType, mode_t, uid_t, gid_t); + + private: + NetworkManager(); + + private: + 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 new file mode 100644 index 00000000..b03072d0 --- /dev/null +++ b/kernel/include/kernel/Networking/NetworkSocket.h @@ -0,0 +1,21 @@ +#pragma once + +#include +#include + +namespace Kernel +{ + + class NetworkSocket : public TmpInode + { + public: + void bind_interface(NetworkInterface*); + + protected: + NetworkSocket(mode_t mode, uid_t uid, gid_t gid); + + protected: + NetworkInterface* m_interface = nullptr; + }; + +} diff --git a/kernel/include/kernel/Networking/UDPSocket.h b/kernel/include/kernel/Networking/UDPSocket.h new file mode 100644 index 00000000..aea04613 --- /dev/null +++ b/kernel/include/kernel/Networking/UDPSocket.h @@ -0,0 +1,29 @@ +#pragma once + +#include +#include + +namespace Kernel +{ + + class UDPSocket final : public NetworkSocket + { + public: + static BAN::ErrorOr> create(mode_t, uid_t, gid_t); + + void bind_interface(NetworkInterface*); + + protected: + virtual BAN::ErrorOr read_impl(off_t, BAN::ByteSpan) override; + virtual BAN::ErrorOr write_impl(off_t, BAN::ConstByteSpan) override; + + private: + UDPSocket(mode_t, uid_t, gid_t); + + private: + NetworkInterface* m_interface = nullptr; + + friend class BAN::RefPtr; + }; + +} diff --git a/kernel/kernel/Networking/E1000/E1000.cpp b/kernel/kernel/Networking/E1000/E1000.cpp index 56239948..a79af51b 100644 --- a/kernel/kernel/Networking/E1000/E1000.cpp +++ b/kernel/kernel/Networking/E1000/E1000.cpp @@ -1,4 +1,3 @@ -#include #include #include #include @@ -97,8 +96,6 @@ namespace Kernel } #endif - DevFileSystem::get().add_device(this); - return {}; } diff --git a/kernel/kernel/Networking/NetworkManager.cpp b/kernel/kernel/Networking/NetworkManager.cpp new file mode 100644 index 00000000..f0ce65c8 --- /dev/null +++ b/kernel/kernel/Networking/NetworkManager.cpp @@ -0,0 +1,78 @@ +#include +#include +#include +#include +#include +#include + +namespace Kernel +{ + + static BAN::UniqPtr s_instance; + + BAN::ErrorOr NetworkManager::initialize() + { + ASSERT(!s_instance); + NetworkManager* manager_ptr = new NetworkManager(); + if (manager_ptr == nullptr) + return BAN::Error::from_errno(ENOMEM); + auto manager = BAN::UniqPtr::adopt(manager_ptr); + TRY(manager->TmpFileSystem::initialize(0777, 0, 0)); + s_instance = BAN::move(manager); + return {}; + } + + NetworkManager& NetworkManager::get() + { + ASSERT(s_instance); + return *s_instance; + } + + NetworkManager::NetworkManager() + : TmpFileSystem(128) + { } + + BAN::ErrorOr NetworkManager::add_interface(PCI::Device& pci_device) + { + BAN::RefPtr interface; + + switch (pci_device.subclass()) + { + case 0x00: + if (E1000::probe(pci_device)) + { + interface = TRY(E1000::create(pci_device)); + break; + } + if (E1000E::probe(pci_device)) + { + interface = TRY(E1000E::create(pci_device)); + break; + } + // fall through + default: + dprintln("unsupported network controller (pci {2H}.{2H}.{2H})", pci_device.class_code(), pci_device.subclass(), pci_device.prog_if()); + dprintln(" vendor id: {4H}", pci_device.vendor_id()); + dprintln(" device id: {4H}", pci_device.device_id()); + return BAN::Error::from_errno(ENOTSUP); + } + + ASSERT(interface); + + TRY(m_interfaces.push_back(interface)); + DevFileSystem::get().add_device(interface); + + return {}; + } + + + BAN::ErrorOr> NetworkManager::create_socket(SocketType type, mode_t mode, uid_t uid, gid_t gid) + { + if (type != SocketType::DGRAM) + return BAN::Error::from_errno(EPROTOTYPE); + + auto udp_socket = TRY(UDPSocket::create(mode, uid, gid)); + return BAN::RefPtr(udp_socket); + } + +} diff --git a/kernel/kernel/Networking/NetworkSocket.cpp b/kernel/kernel/Networking/NetworkSocket.cpp new file mode 100644 index 00000000..fd8b3f3c --- /dev/null +++ b/kernel/kernel/Networking/NetworkSocket.cpp @@ -0,0 +1,23 @@ +#include +#include + +namespace Kernel +{ + + NetworkSocket::NetworkSocket(mode_t mode, uid_t uid, gid_t gid) + // FIXME: what the fuck is this + : TmpInode( + NetworkManager::get(), + MUST(NetworkManager::get().allocate_inode(create_inode_info(mode, uid, gid))), + create_inode_info(mode, uid, gid) + ) + { } + + void NetworkSocket::bind_interface(NetworkInterface* interface) + { + ASSERT(!m_interface); + ASSERT(interface); + m_interface = interface; + } + +} diff --git a/kernel/kernel/Networking/UDPSocket.cpp b/kernel/kernel/Networking/UDPSocket.cpp new file mode 100644 index 00000000..967d1228 --- /dev/null +++ b/kernel/kernel/Networking/UDPSocket.cpp @@ -0,0 +1,25 @@ +#include + +namespace Kernel +{ + + BAN::ErrorOr> UDPSocket::create(mode_t mode, uid_t uid, gid_t gid) + { + return TRY(BAN::RefPtr::create(mode, uid, gid)); + } + + UDPSocket::UDPSocket(mode_t mode, uid_t uid, gid_t gid) + : NetworkSocket(mode, uid, gid) + { } + + BAN::ErrorOr UDPSocket::read_impl(off_t, BAN::ByteSpan) + { + return BAN::Error::from_errno(ENOTSUP); + } + + BAN::ErrorOr UDPSocket::write_impl(off_t, BAN::ConstByteSpan) + { + return BAN::Error::from_errno(ENOTSUP); + } + +} diff --git a/kernel/kernel/PCI.cpp b/kernel/kernel/PCI.cpp index f80a3ef1..09d23860 100644 --- a/kernel/kernel/PCI.cpp +++ b/kernel/kernel/PCI.cpp @@ -2,8 +2,7 @@ #include #include #include -#include -#include +#include #include #include #include @@ -184,28 +183,8 @@ namespace Kernel::PCI } case 0x02: { - switch (pci_device.subclass()) - { - case 0x00: - if (E1000::probe(pci_device)) - { - if (auto res = E1000::create(pci_device); res.is_error()) - dprintln("E1000: {}", res.error()); - break; - } - if (E1000E::probe(pci_device)) - { - if (auto res = E1000E::create(pci_device); res.is_error()) - dprintln("E1000E: {}", res.error()); - break; - } - // fall through - default: - dprintln("unsupported network controller (pci {2H}.{2H}.{2H})", pci_device.class_code(), pci_device.subclass(), pci_device.prog_if()); - dprintln(" vendor id: {4H}", pci_device.vendor_id()); - dprintln(" device id: {4H}", pci_device.device_id()); - break; - } + if (auto res = NetworkManager::get().add_interface(pci_device); res.is_error()) + dprintln("{}", res.error()); break; } default: diff --git a/kernel/kernel/kernel.cpp b/kernel/kernel/kernel.cpp index c4db1e19..e350a606 100644 --- a/kernel/kernel/kernel.cpp +++ b/kernel/kernel/kernel.cpp @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -187,6 +188,8 @@ static void init2(void*) if (auto res = PS2Controller::initialize(); res.is_error()) dprintln("{}", res.error()); + MUST(NetworkManager::initialize()); + // NOTE: PCI devices are the last ones to be initialized // so other devices can reserve predefined interrupts PCI::PCIManager::initialize();