forked from cerc-io/plugeth
p2p/discover: improve discv5 handling of IPv4-in-IPv6 addresses (#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.
This commit is contained in:
parent
cac1b21d39
commit
34f3c9539b
@ -763,9 +763,16 @@ func (t *UDPv5) matchWithCall(fromID enode.ID, nonce v5wire.Nonce) (*callV5, err
|
|||||||
|
|
||||||
// handlePing sends a PONG response.
|
// handlePing sends a PONG response.
|
||||||
func (t *UDPv5) handlePing(p *v5wire.Ping, fromID enode.ID, fromAddr *net.UDPAddr) {
|
func (t *UDPv5) handlePing(p *v5wire.Ping, fromID enode.ID, fromAddr *net.UDPAddr) {
|
||||||
|
remoteIP := fromAddr.IP
|
||||||
|
// Handle IPv4 mapped IPv6 addresses in the
|
||||||
|
// event the local node is binded to an
|
||||||
|
// ipv6 interface.
|
||||||
|
if remoteIP.To4() != nil {
|
||||||
|
remoteIP = remoteIP.To4()
|
||||||
|
}
|
||||||
t.sendResponse(fromID, fromAddr, &v5wire.Pong{
|
t.sendResponse(fromID, fromAddr, &v5wire.Pong{
|
||||||
ReqID: p.ReqID,
|
ReqID: p.ReqID,
|
||||||
ToIP: fromAddr.IP,
|
ToIP: remoteIP,
|
||||||
ToPort: uint16(fromAddr.Port),
|
ToPort: uint16(fromAddr.Port),
|
||||||
ENRSeq: t.localNode.Node().Seq(),
|
ENRSeq: t.localNode.Node().Seq(),
|
||||||
})
|
})
|
||||||
|
@ -597,6 +597,38 @@ func TestUDPv5_LocalNode(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestUDPv5_PingWithIPV4MappedAddress(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
test := newUDPV5Test(t)
|
||||||
|
defer test.close()
|
||||||
|
|
||||||
|
rawIP := net.IPv4(0xFF, 0x12, 0x33, 0xE5)
|
||||||
|
test.remoteaddr = &net.UDPAddr{
|
||||||
|
IP: rawIP.To16(),
|
||||||
|
Port: 0,
|
||||||
|
}
|
||||||
|
remote := test.getNode(test.remotekey, test.remoteaddr).Node()
|
||||||
|
done := make(chan struct{}, 1)
|
||||||
|
|
||||||
|
// This handler will truncate the ipv4-mapped in ipv6 address.
|
||||||
|
go func() {
|
||||||
|
test.udp.handlePing(&v5wire.Ping{ENRSeq: 1}, remote.ID(), test.remoteaddr)
|
||||||
|
done <- struct{}{}
|
||||||
|
}()
|
||||||
|
test.waitPacketOut(func(p *v5wire.Pong, addr *net.UDPAddr, _ v5wire.Nonce) {
|
||||||
|
if len(p.ToIP) == net.IPv6len {
|
||||||
|
t.Error("Received untruncated ip address")
|
||||||
|
}
|
||||||
|
if len(p.ToIP) != net.IPv4len {
|
||||||
|
t.Errorf("Received ip address with incorrect length: %d", len(p.ToIP))
|
||||||
|
}
|
||||||
|
if !p.ToIP.Equal(rawIP) {
|
||||||
|
t.Errorf("Received incorrect ip address: wanted %s but received %s", rawIP.String(), p.ToIP.String())
|
||||||
|
}
|
||||||
|
})
|
||||||
|
<-done
|
||||||
|
}
|
||||||
|
|
||||||
// udpV5Test is the framework for all tests above.
|
// udpV5Test is the framework for all tests above.
|
||||||
// It runs the UDPv5 transport on a virtual socket and allows testing outgoing packets.
|
// It runs the UDPv5 transport on a virtual socket and allows testing outgoing packets.
|
||||||
type udpV5Test struct {
|
type udpV5Test struct {
|
||||||
|
Loading…
Reference in New Issue
Block a user