Explorar el Código

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.
Nishant Das hace 4 años
padre
commit
34f3c9539b
Se han modificado 2 ficheros con 40 adiciones y 1 borrados
  1. 8 1
      p2p/discover/v5_udp.go
  2. 32 0
      p2p/discover/v5_udp_test.go

+ 8 - 1
p2p/discover/v5_udp.go

@@ -763,9 +763,16 @@ func (t *UDPv5) matchWithCall(fromID enode.ID, nonce v5wire.Nonce) (*callV5, err
 
 // handlePing sends a PONG response.
 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{
 		ReqID:  p.ReqID,
-		ToIP:   fromAddr.IP,
+		ToIP:   remoteIP,
 		ToPort: uint16(fromAddr.Port),
 		ENRSeq: t.localNode.Node().Seq(),
 	})

+ 32 - 0
p2p/discover/v5_udp_test.go

@@ -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.
 // It runs the UDPv5 transport on a virtual socket and allows testing outgoing packets.
 type udpV5Test struct {