mirror of
https://github.com/smoltcp-rs/smoltcp.git
synced 2025-09-30 14:20:52 +00:00
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.
This commit is contained in:
parent
8e3ea5c7f0
commit
c76f32fa6c
@ -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!(),
|
||||
}
|
||||
|
@ -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,
|
||||
),
|
||||
|
@ -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,
|
||||
),
|
||||
|
Loading…
x
Reference in New Issue
Block a user