From 9e0f7acfe5d7529cf65d86cfd229780aca8c3694 Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Sun, 16 Jun 2019 07:06:49 +0200 Subject: [PATCH] Kernel+Userland: Expose list of network adapters through /proc/netadapters. Added a simple /bin/ifconfig program that just pretty-prints that file. :^) --- Kernel/FileSystem/ProcFS.cpp | 16 ++++++++++++++++ Kernel/Net/E1000NetworkAdapter.cpp | 3 +++ Kernel/Net/LoopbackAdapter.cpp | 1 + Kernel/Net/NetworkAdapter.cpp | 13 +++++++++++++ Kernel/Net/NetworkAdapter.h | 6 ++++++ Userland/ifconfig.cpp | 30 ++++++++++++++++++++++++++++++ 6 files changed, 69 insertions(+) create mode 100644 Userland/ifconfig.cpp diff --git a/Kernel/FileSystem/ProcFS.cpp b/Kernel/FileSystem/ProcFS.cpp index f1cc2c74aa..c042b5abb7 100644 --- a/Kernel/FileSystem/ProcFS.cpp +++ b/Kernel/FileSystem/ProcFS.cpp @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -40,6 +41,7 @@ enum ProcFileType { FI_Root_dmesg, FI_Root_pci, FI_Root_uptime, + FI_Root_netadapters, FI_Root_self, // symlink FI_Root_sys, // directory __FI_Root_End, @@ -251,6 +253,19 @@ ByteBuffer procfs$uptime(InodeIdentifier) return builder.to_byte_buffer(); } +ByteBuffer procfs$netadapters(InodeIdentifier) +{ + StringBuilder builder; + NetworkAdapter::for_each([&builder](auto& adapter) { + builder.appendf("%s,%s,%s,%s\n", + adapter.name().characters(), + adapter.class_name(), + adapter.mac_address().to_string().characters(), + adapter.ipv4_address().to_string().characters()); + }); + return builder.to_byte_buffer(); +} + ByteBuffer procfs$pid_vmo(InodeIdentifier identifier) { auto handle = ProcessInspectionHandle::from_pid(to_pid(identifier)); @@ -1098,6 +1113,7 @@ ProcFS::ProcFS() m_entries[FI_Root_self] = { "self", FI_Root_self, procfs$self }; m_entries[FI_Root_pci] = { "pci", FI_Root_pci, procfs$pci }; m_entries[FI_Root_uptime] = { "uptime", FI_Root_uptime, procfs$uptime }; + m_entries[FI_Root_netadapters] = { "netadapters", FI_Root_netadapters, procfs$netadapters }; m_entries[FI_Root_sys] = { "sys", FI_Root_sys }; m_entries[FI_PID_vm] = { "vm", FI_PID_vm, procfs$pid_vm }; diff --git a/Kernel/Net/E1000NetworkAdapter.cpp b/Kernel/Net/E1000NetworkAdapter.cpp index fcfaa48e6b..356b1c5f50 100644 --- a/Kernel/Net/E1000NetworkAdapter.cpp +++ b/Kernel/Net/E1000NetworkAdapter.cpp @@ -107,6 +107,9 @@ E1000NetworkAdapter::E1000NetworkAdapter(PCI::Address pci_address, byte irq) , m_pci_address(pci_address) { s_the = this; + + set_interface_name("e1k"); + kprintf("E1000: Found at PCI address %b:%b:%b\n", pci_address.bus(), pci_address.slot(), pci_address.function()); enable_bus_mastering(m_pci_address); diff --git a/Kernel/Net/LoopbackAdapter.cpp b/Kernel/Net/LoopbackAdapter.cpp index 1593f3b3cf..2f90602e6b 100644 --- a/Kernel/Net/LoopbackAdapter.cpp +++ b/Kernel/Net/LoopbackAdapter.cpp @@ -10,6 +10,7 @@ LoopbackAdapter& LoopbackAdapter::the() LoopbackAdapter::LoopbackAdapter() { + set_interface_name("loop"); set_ipv4_address({ 127, 0, 0, 1 }); } diff --git a/Kernel/Net/NetworkAdapter.cpp b/Kernel/Net/NetworkAdapter.cpp index 139c5d0ba8..7537e1e224 100644 --- a/Kernel/Net/NetworkAdapter.cpp +++ b/Kernel/Net/NetworkAdapter.cpp @@ -14,6 +14,13 @@ static Lockable>& all_adapters() return *table; } +void NetworkAdapter::for_each(Function callback) +{ + LOCKER(all_adapters().lock()); + for (auto& it : all_adapters().resource()) + callback(*it); +} + NetworkAdapter* NetworkAdapter::from_ipv4_address(const IPv4Address& address) { LOCKER(all_adapters().lock()); @@ -90,6 +97,12 @@ void NetworkAdapter::set_ipv4_address(const IPv4Address& address) m_ipv4_address = address; } +void NetworkAdapter::set_interface_name(const StringView& basename) +{ + // FIXME: Find a unique name for this interface, starting with $basename. + m_name = String::format("%s0", basename.characters()); +} + bool PacketQueueAlarm::is_ringing() const { return m_adapter.has_queued_packets(); diff --git a/Kernel/Net/NetworkAdapter.h b/Kernel/Net/NetworkAdapter.h index fd24d7ca41..39c2374e0d 100644 --- a/Kernel/Net/NetworkAdapter.h +++ b/Kernel/Net/NetworkAdapter.h @@ -1,6 +1,7 @@ #pragma once #include +#include #include #include #include @@ -26,10 +27,13 @@ private: class NetworkAdapter { public: + static void for_each(Function); static NetworkAdapter* from_ipv4_address(const IPv4Address&); virtual ~NetworkAdapter(); virtual const char* class_name() const = 0; + + const String& name() const { return m_name; } MACAddress mac_address() { return m_mac_address; } IPv4Address ipv4_address() const { return m_ipv4_address; } @@ -46,6 +50,7 @@ public: protected: NetworkAdapter(); + void set_interface_name(const StringView& basename); void set_mac_address(const MACAddress& mac_address) { m_mac_address = mac_address; } virtual void send_raw(const byte*, int) = 0; void did_receive(const byte*, int); @@ -55,4 +60,5 @@ private: IPv4Address m_ipv4_address; PacketQueueAlarm m_packet_queue_alarm; SinglyLinkedList m_packet_queue; + String m_name; }; diff --git a/Userland/ifconfig.cpp b/Userland/ifconfig.cpp new file mode 100644 index 0000000000..fbde9341a5 --- /dev/null +++ b/Userland/ifconfig.cpp @@ -0,0 +1,30 @@ +#include +#include + +int main(int argc, char** argv) +{ + UNUSED_PARAM(argc); + UNUSED_PARAM(argv); + + CFile file("/proc/netadapters"); + if (!file.open(CIODevice::ReadOnly)) { + fprintf(stderr, "Error: %s\n", file.error_string()); + return 1; + } + + for (;;) { + auto line = file.read_line(1024); + if (line.is_null()) + break; + auto parts = String::copy(line, Chomp).split(','); + if (parts.size() < 4) + continue; + printf("%s:\n", parts[0].characters()); + printf(" mac: %s\n", parts[2].characters()); + printf(" ipv4: %s\n", parts[3].characters()); + printf(" class: %s\n", parts[1].characters()); + printf("\n"); + } + + return 0; +}