فهرست منبع

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,
         ),