mirror of
https://github.com/genodelabs/genode.git
synced 2025-06-11 20:01:48 +00:00
nic_router: fix use of outdated ARP-cache entries
When a NIC session is destructed at the router, we have to remove all ARP cache entries that match the MAC address of that session. Otherwise the outdated entries might be re-applied later, leading to wrong destination MAC addresses in routed packets. Fixes #2637
This commit is contained in:
committed by
Norman Feske
parent
0423eb4499
commit
6575df84c5
@ -13,6 +13,8 @@
|
|||||||
|
|
||||||
/* local includes */
|
/* local includes */
|
||||||
#include <arp_cache.h>
|
#include <arp_cache.h>
|
||||||
|
#include <domain.h>
|
||||||
|
#include <configuration.h>
|
||||||
|
|
||||||
using namespace Net;
|
using namespace Net;
|
||||||
using namespace Genode;
|
using namespace Genode;
|
||||||
@ -48,6 +50,11 @@ Arp_cache_entry::find_by_ip(Ipv4_address const &ip) const
|
|||||||
return entry->find_by_ip(ip);
|
return entry->find_by_ip(ip);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Arp_cache_entry::print(Output &output) const
|
||||||
|
{
|
||||||
|
Genode::print(output, _ip, " > ", _mac);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/***************
|
/***************
|
||||||
** Arp_cache **
|
** Arp_cache **
|
||||||
@ -55,9 +62,15 @@ Arp_cache_entry::find_by_ip(Ipv4_address const &ip) const
|
|||||||
|
|
||||||
void Arp_cache::new_entry(Ipv4_address const &ip, Mac_address const &mac)
|
void Arp_cache::new_entry(Ipv4_address const &ip, Mac_address const &mac)
|
||||||
{
|
{
|
||||||
if (_entries[_curr].constructed()) { remove(&(*_entries[_curr])); }
|
if (_entries[_curr].constructed()) {
|
||||||
|
remove(&(*_entries[_curr]));
|
||||||
|
}
|
||||||
_entries[_curr].construct(ip, mac);
|
_entries[_curr].construct(ip, mac);
|
||||||
insert(&(*_entries[_curr]));
|
Arp_cache_entry &entry = *_entries[_curr];
|
||||||
|
insert(&entry);
|
||||||
|
if (_domain.config().verbose()) {
|
||||||
|
log("[", _domain, "] new ARP entry ", entry);
|
||||||
|
}
|
||||||
if (_curr < NR_OF_ENTRIES - 1) {
|
if (_curr < NR_OF_ENTRIES - 1) {
|
||||||
_curr++;
|
_curr++;
|
||||||
} else {
|
} else {
|
||||||
@ -73,3 +86,22 @@ Arp_cache_entry const &Arp_cache::find_by_ip(Ipv4_address const &ip) const
|
|||||||
|
|
||||||
return first()->find_by_ip(ip);
|
return first()->find_by_ip(ip);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Arp_cache::destroy_entries_with_mac(Mac_address const &mac)
|
||||||
|
{
|
||||||
|
for (unsigned curr = 0; curr < NR_OF_ENTRIES; curr++) {
|
||||||
|
try {
|
||||||
|
Arp_cache_entry &entry = *_entries[curr];
|
||||||
|
if (entry.mac() != mac) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (_domain.config().verbose()) {
|
||||||
|
log("[", _domain, "] destroy ARP entry ", entry);
|
||||||
|
}
|
||||||
|
remove(&entry);
|
||||||
|
_entries[curr].destruct();
|
||||||
|
|
||||||
|
} catch (Arp_cache_entry_slot::Deref_unconstructed_object) { }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
|
|
||||||
namespace Net {
|
namespace Net {
|
||||||
|
|
||||||
|
class Domain;
|
||||||
class Arp_cache;
|
class Arp_cache;
|
||||||
class Arp_cache_entry;
|
class Arp_cache_entry;
|
||||||
using Arp_cache_entry_slot = Genode::Constructible<Arp_cache_entry>;
|
using Arp_cache_entry_slot = Genode::Constructible<Arp_cache_entry>;
|
||||||
@ -56,6 +57,14 @@ class Net::Arp_cache_entry : public Genode::Avl_node<Arp_cache_entry>
|
|||||||
***************/
|
***************/
|
||||||
|
|
||||||
Mac_address const &mac() const { return _mac; }
|
Mac_address const &mac() const { return _mac; }
|
||||||
|
Ipv4_address const &ip() const { return _ip; }
|
||||||
|
|
||||||
|
|
||||||
|
/*********
|
||||||
|
** log **
|
||||||
|
*********/
|
||||||
|
|
||||||
|
void print(Genode::Output &output) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -68,6 +77,7 @@ class Net::Arp_cache : public Genode::Avl_tree<Arp_cache_entry>
|
|||||||
NR_OF_ENTRIES = ENTRIES_SIZE / sizeof(Arp_cache_entry),
|
NR_OF_ENTRIES = ENTRIES_SIZE / sizeof(Arp_cache_entry),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Domain const &_domain;
|
||||||
Arp_cache_entry_slot _entries[NR_OF_ENTRIES];
|
Arp_cache_entry_slot _entries[NR_OF_ENTRIES];
|
||||||
bool _init = true;
|
bool _init = true;
|
||||||
unsigned _curr = 0;
|
unsigned _curr = 0;
|
||||||
@ -76,8 +86,12 @@ class Net::Arp_cache : public Genode::Avl_tree<Arp_cache_entry>
|
|||||||
|
|
||||||
struct No_match : Genode::Exception { };
|
struct No_match : Genode::Exception { };
|
||||||
|
|
||||||
|
Arp_cache(Domain const &domain) : _domain(domain) { }
|
||||||
|
|
||||||
void new_entry(Ipv4_address const &ip, Mac_address const &mac);
|
void new_entry(Ipv4_address const &ip, Mac_address const &mac);
|
||||||
|
|
||||||
|
void destroy_entries_with_mac(Mac_address const &mac);
|
||||||
|
|
||||||
Arp_cache_entry const &find_by_ip(Ipv4_address const &ip) const;
|
Arp_cache_entry const &find_by_ip(Ipv4_address const &ip) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -98,7 +98,7 @@ class Net::Domain : public Domain_base
|
|||||||
unsigned long _interface_cnt { 0 };
|
unsigned long _interface_cnt { 0 };
|
||||||
Pointer<Dhcp_server> _dhcp_server { };
|
Pointer<Dhcp_server> _dhcp_server { };
|
||||||
Genode::Reconstructible<Ipv4_config> _ip_config;
|
Genode::Reconstructible<Ipv4_config> _ip_config;
|
||||||
Arp_cache _arp_cache { };
|
Arp_cache _arp_cache { *this };
|
||||||
Arp_waiter_list _foreign_arp_waiters { };
|
Arp_waiter_list _foreign_arp_waiters { };
|
||||||
Link_side_tree _tcp_links { };
|
Link_side_tree _tcp_links { };
|
||||||
Link_side_tree _udp_links { };
|
Link_side_tree _udp_links { };
|
||||||
|
@ -1022,6 +1022,8 @@ Interface::~Interface()
|
|||||||
_dhcp_allocations.remove(allocation);
|
_dhcp_allocations.remove(allocation);
|
||||||
_destroy_dhcp_allocation(*allocation);
|
_destroy_dhcp_allocation(*allocation);
|
||||||
}
|
}
|
||||||
|
/* dissolve ARP cache entries with the MAC address of this interface */
|
||||||
|
_domain.arp_cache().destroy_entries_with_mac(_mac);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user