Don't put non-unicast (IP or Ethernet) addresses into ARP cache.

Thanks @little-dude for pointing this out--it's probably a DoS bug.
This commit is contained in:
whitequark 2017-03-07 06:32:09 +00:00
parent b305797cb4
commit 393ebbe682
3 changed files with 21 additions and 3 deletions

View File

@ -95,6 +95,9 @@ impl<'a> SliceCache<'a> {
impl<'a> Cache for SliceCache<'a> {
fn fill(&mut self, protocol_addr: &IpAddress, hardware_addr: &EthernetAddress) {
debug_assert!(protocol_addr.is_unicast());
debug_assert!(hardware_addr.is_unicast());
if let None = self.find(protocol_addr) {
let lru_index = self.lru();

View File

@ -137,7 +137,10 @@ impl<'a, 'b, 'c, DeviceT: Device + 'a> Interface<'a, 'b, 'c, DeviceT> {
source_hardware_addr, source_protocol_addr,
target_protocol_addr, ..
} => {
self.arp_cache.fill(&source_protocol_addr.into(), &source_hardware_addr);
if source_protocol_addr.is_unicast() && source_hardware_addr.is_unicast() {
self.arp_cache.fill(&source_protocol_addr.into(),
&source_hardware_addr);
}
if self.has_protocol_addr(target_protocol_addr) {
response = Response::Arp(ArpRepr::EthernetIpv4 {
@ -155,7 +158,10 @@ impl<'a, 'b, 'c, DeviceT: Device + 'a> Interface<'a, 'b, 'c, DeviceT> {
operation: ArpOperation::Reply,
source_hardware_addr, source_protocol_addr, ..
} => {
self.arp_cache.fill(&source_protocol_addr.into(), &source_hardware_addr)
if source_protocol_addr.is_unicast() && source_hardware_addr.is_unicast() {
self.arp_cache.fill(&source_protocol_addr.into(),
&source_hardware_addr);
}
},
_ => return Err(Error::Unrecognized)
@ -168,7 +174,10 @@ impl<'a, 'b, 'c, DeviceT: Device + 'a> Interface<'a, 'b, 'c, DeviceT> {
let ipv4_repr = try!(Ipv4Repr::parse(&ipv4_packet));
// Fill the ARP cache from IP header.
self.arp_cache.fill(&IpAddress::Ipv4(ipv4_repr.src_addr), &eth_frame.src_addr());
if ipv4_repr.src_addr.is_unicast() && eth_frame.src_addr().is_unicast() {
self.arp_cache.fill(&IpAddress::Ipv4(ipv4_repr.src_addr),
&eth_frame.src_addr());
}
match ipv4_repr {
// Ignore IP packets not directed at us.

View File

@ -45,6 +45,12 @@ impl Address {
&self.0
}
/// Query whether the address is an unicast address.
pub fn is_unicast(&self) -> bool {
!(self.is_broadcast() ||
self.is_multicast())
}
/// Query whether this address is the broadcast address.
pub fn is_broadcast(&self) -> bool {
self.0 == [0xff; 6]