浏览代码

arp: Do not fill cache from random packets.

On paper this looks great, and in a sane network it should work.
However the world out there is full of horribly broken, screwed up
networks, which *of course* ruin this.

I've seen a customer's network where the router is IP 192.168.1.1,
MAC addr xx:03. However, every 1 minute the router broadcasts some
"mikrotik discovery" UDP garbage with source IP 192.168.1.1, source MAC
addr xx:02 (one less!). This accidentally poisons smoltcp's ARP cache,
which then sends all traffic for the default gateway to xx:02, which
unsurprisingly blackholes it.

And, of course, the broadcast is every 1min and the ARP cache lifetime
is 1min. This means the cache is almsot all the time poisoned, and the
smoltcp device barely works. Fantastic.

Screw you mikrotik.
Dario Nieuwenhuis 3 年之前
父节点
当前提交
6210612be0
共有 1 个文件被更改,包括 0 次插入31 次删除
  1. 0 31
      src/iface/interface.rs

+ 0 - 31
src/iface/interface.rs

@@ -952,43 +952,12 @@ impl<'a> InterfaceInner<'a> {
             #[cfg(feature = "proto-ipv4")]
             EthernetProtocol::Ipv4 => {
                 let ipv4_packet = Ipv4Packet::new_checked(eth_frame.payload())?;
-                if eth_frame.src_addr().is_unicast() && ipv4_packet.src_addr().is_unicast() {
-                    // Fill the neighbor cache from IP header of unicast frames.
-                    let ip_addr = IpAddress::Ipv4(ipv4_packet.src_addr());
-                    if self.in_same_network(&ip_addr) {
-                        self.neighbor_cache.as_mut().unwrap().fill(
-                            ip_addr,
-                            eth_frame.src_addr(),
-                            cx.now,
-                        );
-                    }
-                }
-
                 self.process_ipv4(cx, sockets, &ipv4_packet)
                     .map(|o| o.map(EthernetPacket::Ip))
             }
             #[cfg(feature = "proto-ipv6")]
             EthernetProtocol::Ipv6 => {
                 let ipv6_packet = Ipv6Packet::new_checked(eth_frame.payload())?;
-                if eth_frame.src_addr().is_unicast() && ipv6_packet.src_addr().is_unicast() {
-                    // Fill the neighbor cache from IP header of unicast frames.
-                    let ip_addr = IpAddress::Ipv6(ipv6_packet.src_addr());
-                    if self.in_same_network(&ip_addr)
-                        && self
-                            .neighbor_cache
-                            .as_mut()
-                            .unwrap()
-                            .lookup(&ip_addr, cx.now)
-                            .found()
-                    {
-                        self.neighbor_cache.as_mut().unwrap().fill(
-                            ip_addr,
-                            eth_frame.src_addr(),
-                            cx.now,
-                        );
-                    }
-                }
-
                 self.process_ipv6(cx, sockets, &ipv6_packet)
                     .map(|o| o.map(EthernetPacket::Ip))
             }