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 }