Skip to content

Commit 4e5aede

Browse files
nisdasatif-konasl
authored andcommitted
p2p/discover: improve discv5 handling of IPv4-in-IPv6 addresses (ethereum#22703)
When receiving PING from an IPv4 address over IPv6, the implementation sent back a IPv4-in-IPv6 address. This change makes it reflect the IPv4 address.
1 parent 7d3bd37 commit 4e5aede

File tree

2 files changed

+40
-1
lines changed

2 files changed

+40
-1
lines changed

p2p/discover/v5_udp.go

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -763,9 +763,16 @@ func (t *UDPv5) matchWithCall(fromID enode.ID, nonce v5wire.Nonce) (*callV5, err
763763

764764
// handlePing sends a PONG response.
765765
func (t *UDPv5) handlePing(p *v5wire.Ping, fromID enode.ID, fromAddr *net.UDPAddr) {
766+
remoteIP := fromAddr.IP
767+
// Handle IPv4 mapped IPv6 addresses in the
768+
// event the local node is binded to an
769+
// ipv6 interface.
770+
if remoteIP.To4() != nil {
771+
remoteIP = remoteIP.To4()
772+
}
766773
t.sendResponse(fromID, fromAddr, &v5wire.Pong{
767774
ReqID: p.ReqID,
768-
ToIP: fromAddr.IP,
775+
ToIP: remoteIP,
769776
ToPort: uint16(fromAddr.Port),
770777
ENRSeq: t.localNode.Node().Seq(),
771778
})

p2p/discover/v5_udp_test.go

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -597,6 +597,38 @@ func TestUDPv5_LocalNode(t *testing.T) {
597597
}
598598
}
599599

600+
func TestUDPv5_PingWithIPV4MappedAddress(t *testing.T) {
601+
t.Parallel()
602+
test := newUDPV5Test(t)
603+
defer test.close()
604+
605+
rawIP := net.IPv4(0xFF, 0x12, 0x33, 0xE5)
606+
test.remoteaddr = &net.UDPAddr{
607+
IP: rawIP.To16(),
608+
Port: 0,
609+
}
610+
remote := test.getNode(test.remotekey, test.remoteaddr).Node()
611+
done := make(chan struct{}, 1)
612+
613+
// This handler will truncate the ipv4-mapped in ipv6 address.
614+
go func() {
615+
test.udp.handlePing(&v5wire.Ping{ENRSeq: 1}, remote.ID(), test.remoteaddr)
616+
done <- struct{}{}
617+
}()
618+
test.waitPacketOut(func(p *v5wire.Pong, addr *net.UDPAddr, _ v5wire.Nonce) {
619+
if len(p.ToIP) == net.IPv6len {
620+
t.Error("Received untruncated ip address")
621+
}
622+
if len(p.ToIP) != net.IPv4len {
623+
t.Errorf("Received ip address with incorrect length: %d", len(p.ToIP))
624+
}
625+
if !p.ToIP.Equal(rawIP) {
626+
t.Errorf("Received incorrect ip address: wanted %s but received %s", rawIP.String(), p.ToIP.String())
627+
}
628+
})
629+
<-done
630+
}
631+
600632
// udpV5Test is the framework for all tests above.
601633
// It runs the UDPv5 transport on a virtual socket and allows testing outgoing packets.
602634
type udpV5Test struct {

0 commit comments

Comments
 (0)