From 868dfbce4fd59f03145e2bc5ac0b585917c371fa Mon Sep 17 00:00:00 2001 From: Amaindex Date: Tue, 1 Apr 2025 17:16:43 +0800 Subject: [PATCH] netstack: allow defaultHandler respond ICMPv4Echo in promiscuous mode In promiscuous mode, ICMPv4Echo packets are replied to directly by the network stack, even if custom transport defaultHandler processes them. This change adds a LocalAddressTemporary field to NetworkPacketInfo to identify packets received with temporary addresses due to promiscuous mode, and skips the direct ICMP reply for these. This allows custom handlers to independently process such packets. - Added LocalAddressTemporary field to NetworkPacketInfo. - Set Temporary property when adding temporary address. - Set LocalAddressTemporary in addressEndpoint check. - Skip direct ICMPv4Echo reply for packets with temporary addresses. For #8657 --- pkg/tcpip/network/ipv4/icmp.go | 10 +++++++++- pkg/tcpip/network/ipv4/ipv4.go | 1 + pkg/tcpip/stack/addressable_endpoint_state.go | 2 +- pkg/tcpip/stack/registration.go | 4 ++++ 4 files changed, 15 insertions(+), 2 deletions(-) diff --git a/pkg/tcpip/network/ipv4/icmp.go b/pkg/tcpip/network/ipv4/icmp.go index 8e96ca8031..e3d79c3ee9 100644 --- a/pkg/tcpip/network/ipv4/icmp.go +++ b/pkg/tcpip/network/ipv4/icmp.go @@ -356,12 +356,20 @@ func (e *endpoint) handleICMP(pkt *stack.PacketBuffer) { replyData := stack.PayloadSince(pkt.TransportHeader()) defer replyData.Release() ipHdr := header.IPv4(pkt.NetworkHeader().Slice()) + localAddressTemporary := pkt.NetworkPacketInfo.LocalAddressTemporary localAddressBroadcast := pkt.NetworkPacketInfo.LocalAddressBroadcast - // It's possible that a raw socket expects to receive this. + // It's possible that a raw socket or custom defaultHandler expects to + // receive this packet. e.dispatcher.DeliverTransportPacket(header.ICMPv4ProtocolNumber, pkt) pkt = nil + // Skip direct ICMP echo reply if the packet was received with a temporary + // address, allowing custom handlers to take over. + if localAddressTemporary { + return + } + sent := e.stats.icmp.packetsSent if !e.protocol.allowICMPReply(header.ICMPv4EchoReply, header.ICMPv4UnusedCode) { sent.rateLimited.Increment() diff --git a/pkg/tcpip/network/ipv4/ipv4.go b/pkg/tcpip/network/ipv4/ipv4.go index bb4bcb6ed3..4a3878c761 100644 --- a/pkg/tcpip/network/ipv4/ipv4.go +++ b/pkg/tcpip/network/ipv4/ipv4.go @@ -1169,6 +1169,7 @@ func (e *endpoint) handleValidatedPacket(h header.IPv4, pkt *stack.PacketBuffer, // If the packet is destined for this device, then it should be delivered // locally. Otherwise, if forwarding is enabled, it should be forwarded. if addressEndpoint := e.AcquireAssignedAddress(dstAddr, e.nic.Promiscuous(), stack.CanBePrimaryEndpoint, true /* readOnly */); addressEndpoint != nil { + pkt.NetworkPacketInfo.LocalAddressTemporary = addressEndpoint.Temporary() subnet := addressEndpoint.AddressWithPrefix().Subnet() pkt.NetworkPacketInfo.LocalAddressBroadcast = subnet.IsBroadcast(dstAddr) || dstAddr == header.IPv4Broadcast e.deliverPacketLocally(h, pkt, inNICName) diff --git a/pkg/tcpip/stack/addressable_endpoint_state.go b/pkg/tcpip/stack/addressable_endpoint_state.go index e08909c816..cf37edb50c 100644 --- a/pkg/tcpip/stack/addressable_endpoint_state.go +++ b/pkg/tcpip/stack/addressable_endpoint_state.go @@ -602,7 +602,7 @@ func (a *AddressableEndpointState) AcquireAssignedAddressOrMatching(localAddr tc // Proceed to add a new temporary endpoint. addr := localAddr.WithPrefix() - ep, err := a.addAndAcquireAddressLocked(addr, AddressProperties{PEB: tempPEB}, Temporary) + ep, err := a.addAndAcquireAddressLocked(addr, AddressProperties{PEB: tempPEB, Temporary: true}, Temporary) if err != nil { // addAndAcquireAddressLocked only returns an error if the address is // already assigned but we just checked above if the address exists so we diff --git a/pkg/tcpip/stack/registration.go b/pkg/tcpip/stack/registration.go index fd6f501a60..23fb19af18 100644 --- a/pkg/tcpip/stack/registration.go +++ b/pkg/tcpip/stack/registration.go @@ -58,6 +58,10 @@ type NetworkPacketInfo struct { // address. LocalAddressBroadcast bool + // LocalAddressTemporary is true if the packet's local address is a temporary + // address. + LocalAddressTemporary bool + // IsForwardedPacket is true if the packet is being forwarded. IsForwardedPacket bool }