#include #include #include #include #include #include #include #include #include #include #include #include namespace Kernel { static BAN::UniqPtr s_instance; BAN::ErrorOr NetworkManager::initialize() { ASSERT(!s_instance); auto manager = TRY(BAN::UniqPtr::create()); TRY(manager->add_interface(TRY(LoopbackInterface::create()))); manager->m_ipv4_layer = TRY(IPv4Layer::create()); s_instance = BAN::move(manager); return {}; } NetworkManager& NetworkManager::get() { ASSERT(s_instance); return *s_instance; } 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; } if (RTL8169::probe(pci_device)) { interface = TRY(RTL8169::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); return add_interface(interface); } BAN::ErrorOr NetworkManager::add_interface(BAN::RefPtr interface) { TRY(m_interfaces.push_back(interface)); DevFileSystem::get().add_device(interface); return {}; } BAN::ErrorOr> NetworkManager::create_socket(Socket::Domain domain, Socket::Type type, mode_t mode, uid_t uid, gid_t gid) { switch (domain) { case Socket::Domain::INET: switch (type) { case Socket::Type::DGRAM: case Socket::Type::STREAM: break; default: return BAN::Error::from_errno(EPROTOTYPE); } break; case Socket::Domain::UNIX: break; default: return BAN::Error::from_errno(EAFNOSUPPORT); } ASSERT((mode & Inode::Mode::TYPE_MASK) == 0); mode |= Inode::Mode::IFSOCK; auto socket_info = Socket::Info { .mode = mode, .uid = uid, .gid = gid }; BAN::RefPtr socket; switch (domain) { case Socket::Domain::INET: { switch (type) { case Socket::Type::DGRAM: socket = TRY(UDPSocket::create(*m_ipv4_layer, socket_info)); break; case Socket::Type::STREAM: socket = TRY(TCPSocket::create(*m_ipv4_layer, socket_info)); break; default: ASSERT_NOT_REACHED(); } break; } case Socket::Domain::UNIX: { socket = TRY(UnixDomainSocket::create(type, socket_info)); break; } default: ASSERT_NOT_REACHED(); } ASSERT(socket); return socket; } BAN::ErrorOr NetworkManager::connect_sockets(Socket::Domain domain, BAN::RefPtr socket1, BAN::RefPtr socket2) { switch (domain) { case Socket::Domain::UNIX: { auto* usocket1 = static_cast(socket1.ptr()); auto* usocket2 = static_cast(socket2.ptr()); TRY(usocket1->make_socket_pair(*usocket2)); break; } default: dwarnln("TODO: connect {} domain sockets", static_cast(domain)); return BAN::Error::from_errno(ENOTSUP); } return {}; } void NetworkManager::on_receive(NetworkInterface& interface, BAN::ConstByteSpan packet) { if (packet.size() < sizeof(EthernetHeader)) return; auto ethernet_header = packet.as(); switch (ethernet_header.ether_type) { case EtherType::ARP: { m_ipv4_layer->arp_table().add_arp_packet(interface, packet.slice(sizeof(EthernetHeader))); break; } case EtherType::IPv4: { m_ipv4_layer->add_ipv4_packet(interface, packet.slice(sizeof(EthernetHeader))); break; } default: dprintln_if(DEBUG_ETHERTYPE, "Unknown EtherType 0x{4H}", (uint16_t)ethernet_header.ether_type); break; } } }