瀏覽代碼

Use own src address for ARP and NDISC Solicits

When looking up the destination link-layer address for a given
destination address, we need to send an ARP or ICMPv6 Neighbor
Solicitation if the destination link-layer address is not in the cache.

When transmitting an ARP or ICMPv6 Neighbor Solicitation packet, use the
source address of the interface instead of the source address of the
packet that is tried to be sent.

By using the source address of the interface, we are sure that a
response will be received on the same interface.
Thibaut Vandervelden 6 月之前
父節點
當前提交
c76f32fa6c
共有 3 個文件被更改,包括 10 次插入24 次删除
  1. 10 20
      src/iface/interface/mod.rs
  2. 0 3
      src/iface/interface/tests/ipv4.rs
  3. 0 1
      src/iface/interface/tests/ipv6.rs

+ 10 - 20
src/iface/interface/mod.rs

@@ -898,7 +898,6 @@ impl InterfaceInner {
     fn lookup_hardware_addr<Tx>(
         &mut self,
         tx_token: Tx,
-        src_addr: &IpAddress,
         dst_addr: &IpAddress,
         fragmenter: &mut Fragmenter,
     ) -> Result<(HardwareAddress, Tx), DispatchError>
@@ -966,11 +965,9 @@ impl InterfaceInner {
             _ => (), // XXX
         }
 
-        match (src_addr, dst_addr) {
+        match dst_addr {
             #[cfg(all(feature = "medium-ethernet", feature = "proto-ipv4"))]
-            (&IpAddress::Ipv4(src_addr), IpAddress::Ipv4(dst_addr))
-                if matches!(self.caps.medium, Medium::Ethernet) =>
-            {
+            IpAddress::Ipv4(dst_addr) if matches!(self.caps.medium, Medium::Ethernet) => {
                 net_debug!(
                     "address {} not in neighbor cache, sending ARP request",
                     dst_addr
@@ -980,7 +977,9 @@ impl InterfaceInner {
                 let arp_repr = ArpRepr::EthernetIpv4 {
                     operation: ArpOperation::Request,
                     source_hardware_addr: src_hardware_addr,
-                    source_protocol_addr: src_addr,
+                    source_protocol_addr: self
+                        .get_source_address_ipv4(&dst_addr)
+                        .ok_or(DispatchError::NoRoute)?,
                     target_hardware_addr: EthernetAddress::BROADCAST,
                     target_protocol_addr: dst_addr,
                 };
@@ -999,7 +998,7 @@ impl InterfaceInner {
             }
 
             #[cfg(feature = "proto-ipv6")]
-            (&IpAddress::Ipv6(src_addr), IpAddress::Ipv6(dst_addr)) => {
+            IpAddress::Ipv6(dst_addr) => {
                 net_debug!(
                     "address {} not in neighbor cache, sending Neighbor Solicitation",
                     dst_addr
@@ -1012,7 +1011,7 @@ impl InterfaceInner {
 
                 let packet = Packet::new_ipv6(
                     Ipv6Repr {
-                        src_addr,
+                        src_addr: self.get_source_address_ipv6(&dst_addr),
                         dst_addr: dst_addr.solicited_node(),
                         next_header: IpProtocol::Icmpv6,
                         payload_len: solicit.buffer_len(),
@@ -1059,12 +1058,8 @@ impl InterfaceInner {
 
         #[cfg(feature = "medium-ieee802154")]
         if matches!(self.caps.medium, Medium::Ieee802154) {
-            let (addr, tx_token) = self.lookup_hardware_addr(
-                tx_token,
-                &ip_repr.src_addr(),
-                &ip_repr.dst_addr(),
-                frag,
-            )?;
+            let (addr, tx_token) =
+                self.lookup_hardware_addr(tx_token, &ip_repr.dst_addr(), frag)?;
             let addr = addr.ieee802154_or_panic();
 
             self.dispatch_ieee802154(addr, tx_token, meta, packet, frag);
@@ -1091,12 +1086,7 @@ impl InterfaceInner {
         #[cfg(feature = "medium-ethernet")]
         let (dst_hardware_addr, mut tx_token) = match self.caps.medium {
             Medium::Ethernet => {
-                match self.lookup_hardware_addr(
-                    tx_token,
-                    &ip_repr.src_addr(),
-                    &ip_repr.dst_addr(),
-                    frag,
-                )? {
+                match self.lookup_hardware_addr(tx_token, &ip_repr.dst_addr(), frag)? {
                     (HardwareAddress::Ethernet(addr), tx_token) => (addr, tx_token),
                     (_, _) => unreachable!(),
                 }

+ 0 - 3
src/iface/interface/tests/ipv4.rs

@@ -456,7 +456,6 @@ fn test_handle_valid_arp_request(#[case] medium: Medium) {
     assert_eq!(
         iface.inner.lookup_hardware_addr(
             MockTxToken,
-            &IpAddress::Ipv4(local_ip_addr),
             &IpAddress::Ipv4(remote_ip_addr),
             &mut iface.fragmenter,
         ),
@@ -505,7 +504,6 @@ fn test_handle_other_arp_request(#[case] medium: Medium) {
     assert_eq!(
         iface.inner.lookup_hardware_addr(
             MockTxToken,
-            &IpAddress::Ipv4(Ipv4Address([0x7f, 0x00, 0x00, 0x01])),
             &IpAddress::Ipv4(remote_ip_addr),
             &mut iface.fragmenter,
         ),
@@ -564,7 +562,6 @@ fn test_arp_flush_after_update_ip(#[case] medium: Medium) {
     assert_eq!(
         iface.inner.lookup_hardware_addr(
             MockTxToken,
-            &IpAddress::Ipv4(local_ip_addr),
             &IpAddress::Ipv4(remote_ip_addr),
             &mut iface.fragmenter,
         ),

+ 0 - 1
src/iface/interface/tests/ipv6.rs

@@ -834,7 +834,6 @@ fn test_handle_valid_ndisc_request(#[case] medium: Medium) {
     assert_eq!(
         iface.inner.lookup_hardware_addr(
             MockTxToken,
-            &IpAddress::Ipv6(local_ip_addr),
             &IpAddress::Ipv6(remote_ip_addr),
             &mut iface.fragmenter,
         ),