From 90f60d2f650a417a8ffd002d2cfa22605941069f Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Tue, 12 Mar 2019 00:56:33 +0100 Subject: [PATCH] Kernel: Cache MAC<->IP mappings (from ARP responses) seen on the wire. --- AK/StringImpl.cpp | 16 +++------------- AK/StringImpl.h | 15 +++++++++++++++ Kernel/IPv4Address.h | 10 ++++++++++ Kernel/MACAddress.h | 15 +++++++++++++++ Kernel/NetworkTask.cpp | 25 ++++++++++++++++++++++++- 5 files changed, 67 insertions(+), 14 deletions(-) diff --git a/AK/StringImpl.cpp b/AK/StringImpl.cpp index 3a11a1a74e3..eead6a3ea79 100644 --- a/AK/StringImpl.cpp +++ b/AK/StringImpl.cpp @@ -155,20 +155,10 @@ slow_path: void StringImpl::compute_hash() const { - if (!length()) { + if (!length()) m_hash = 0; - } else { - unsigned hash = 0; - for (ssize_t i = 0; i < m_length; ++i) { - hash += m_characters[i]; - hash += (hash << 10); - hash ^= (hash >> 6); - } - hash += hash << 3; - hash ^= hash >> 11; - hash += hash << 15; - m_hash = hash; - } + else + m_hash = string_hash(m_characters, m_length); m_hasHash = true; } diff --git a/AK/StringImpl.h b/AK/StringImpl.h index 9a4405cadcb..c7ecfd3c24c 100644 --- a/AK/StringImpl.h +++ b/AK/StringImpl.h @@ -47,7 +47,22 @@ private: char m_inline_buffer[0]; }; +inline dword string_hash(const char* characters, int length) +{ + dword hash = 0; + for (int i = 0; i < length; ++i) { + hash += (dword)characters[i]; + hash += (hash << 10); + hash ^= (hash >> 6); + } + hash += hash << 3; + hash ^= hash >> 11; + hash += hash << 15; + return hash; +} + } using AK::StringImpl; using AK::Chomp; +using AK::string_hash; diff --git a/Kernel/IPv4Address.h b/Kernel/IPv4Address.h index d1f82c01146..12774b9e004 100644 --- a/Kernel/IPv4Address.h +++ b/Kernel/IPv4Address.h @@ -42,3 +42,13 @@ private: }; static_assert(sizeof(IPv4Address) == 4); + +namespace AK { + +template<> +struct Traits { + static unsigned hash(const IPv4Address& address) { return string_hash((const char*)&address, sizeof(address)); } + static void dump(const IPv4Address& address) { kprintf("%s", address.to_string().characters()); } +}; + +} diff --git a/Kernel/MACAddress.h b/Kernel/MACAddress.h index d8619beaaf1..0c2de93b270 100644 --- a/Kernel/MACAddress.h +++ b/Kernel/MACAddress.h @@ -20,6 +20,11 @@ public: return m_data[i]; } + bool operator==(const MACAddress& other) const + { + return !memcmp(m_data, other.m_data, sizeof(m_data)); + } + String to_string() const { return String::format("%b:%b:%b:%b:%b:%b", m_data[0], m_data[1], m_data[2], m_data[3], m_data[4], m_data[5]); @@ -30,3 +35,13 @@ private: }; static_assert(sizeof(MACAddress) == 6); + +namespace AK { + +template<> +struct Traits { + static unsigned hash(const MACAddress& address) { return string_hash((const char*)&address, sizeof(address)); } + static void dump(const MACAddress& address) { kprintf("%s", address.to_string().characters()); } +}; + +} diff --git a/Kernel/NetworkTask.cpp b/Kernel/NetworkTask.cpp index 867266d855a..e8a5404bb4c 100644 --- a/Kernel/NetworkTask.cpp +++ b/Kernel/NetworkTask.cpp @@ -3,10 +3,19 @@ #include #include #include +#include static void handle_arp(const EthernetFrameHeader&, int frame_size); static void handle_ipv4(const EthernetFrameHeader&, int frame_size); +Lockable>& arp_table() +{ + static Lockable>* the; + if (!the) + the = new Lockable>; + return *the; +} + void NetworkTask_main() { auto* e1000_ptr = E1000NetworkAdapter::the(); @@ -59,7 +68,7 @@ void handle_arp(const EthernetFrameHeader& eth, int frame_size) kprintf("handle_arp: Frame too small (%d, need %d)\n", frame_size, minimum_arp_frame_size); return; } - const ARPPacket& packet = *static_cast(eth.payload()); + auto& packet = *static_cast(eth.payload()); if (packet.hardware_type() != 1 || packet.hardware_address_length() != sizeof(MACAddress)) { kprintf("handle_arp: Hardware type not ethernet (%w, len=%u)\n", packet.hardware_type(), @@ -104,6 +113,20 @@ void handle_arp(const EthernetFrameHeader& eth, int frame_size) e1000.send(packet.sender_hardware_address(), response); } + return; + } + + if (packet.operation() == 2) { + // Someone has this IPv4 address. I guess we can try to remember that. + // FIXME: Protect against ARP spamming. + // FIXME: Support static ARP table entries. + LOCKER(arp_table().lock()); + arp_table().resource().set(packet.sender_protocol_address(), packet.sender_hardware_address()); + + kprintf("ARP table (%d entries):\n", arp_table().resource().size()); + for (auto& it : arp_table().resource()) { + kprintf("%s :: %s\n", it.value.to_string().characters(), it.key.to_string().characters()); + } } }