aboutsummaryrefslogtreecommitdiffstats
path: root/p2p/discover
diff options
context:
space:
mode:
Diffstat (limited to 'p2p/discover')
-rw-r--r--p2p/discover/table_test.go1
-rw-r--r--p2p/discover/udp.go50
-rw-r--r--p2p/discover/udp_notwindows.go26
-rw-r--r--p2p/discover/udp_test.go59
-rw-r--r--p2p/discover/udp_windows.go40
5 files changed, 36 insertions, 140 deletions
diff --git a/p2p/discover/table_test.go b/p2p/discover/table_test.go
index 1a2405740..102c7c2d1 100644
--- a/p2p/discover/table_test.go
+++ b/p2p/discover/table_test.go
@@ -146,6 +146,7 @@ func fillBucket(tab *Table, ld int) (last *Node) {
func nodeAtDistance(base common.Hash, ld int) (n *Node) {
n = new(Node)
n.sha = hashAtDistance(base, ld)
+ n.IP = net.IP{10, 0, 2, byte(ld)}
copy(n.ID[:], n.sha[:]) // ensure the node still has a unique ID
return n
}
diff --git a/p2p/discover/udp.go b/p2p/discover/udp.go
index 74758b6fd..e09c63ffb 100644
--- a/p2p/discover/udp.go
+++ b/p2p/discover/udp.go
@@ -29,6 +29,7 @@ import (
"github.com/ethereum/go-ethereum/logger"
"github.com/ethereum/go-ethereum/logger/glog"
"github.com/ethereum/go-ethereum/p2p/nat"
+ "github.com/ethereum/go-ethereum/p2p/netutil"
"github.com/ethereum/go-ethereum/rlp"
)
@@ -126,8 +127,16 @@ func makeEndpoint(addr *net.UDPAddr, tcpPort uint16) rpcEndpoint {
return rpcEndpoint{IP: ip, UDP: uint16(addr.Port), TCP: tcpPort}
}
-func nodeFromRPC(rn rpcNode) (*Node, error) {
- // TODO: don't accept localhost, LAN addresses from internet hosts
+func (t *udp) nodeFromRPC(sender *net.UDPAddr, rn rpcNode) (*Node, error) {
+ if rn.UDP <= 1024 {
+ return nil, errors.New("low port")
+ }
+ if err := netutil.CheckRelayIP(sender.IP, rn.IP); err != nil {
+ return nil, err
+ }
+ if t.netrestrict != nil && !t.netrestrict.Contains(rn.IP) {
+ return nil, errors.New("not contained in netrestrict whitelist")
+ }
n := NewNode(rn.ID, rn.IP, rn.UDP, rn.TCP)
err := n.validateComplete()
return n, err
@@ -151,6 +160,7 @@ type conn interface {
// udp implements the RPC protocol.
type udp struct {
conn conn
+ netrestrict *netutil.Netlist
priv *ecdsa.PrivateKey
ourEndpoint rpcEndpoint
@@ -201,7 +211,7 @@ type reply struct {
}
// ListenUDP returns a new table that listens for UDP packets on laddr.
-func ListenUDP(priv *ecdsa.PrivateKey, laddr string, natm nat.Interface, nodeDBPath string) (*Table, error) {
+func ListenUDP(priv *ecdsa.PrivateKey, laddr string, natm nat.Interface, nodeDBPath string, netrestrict *netutil.Netlist) (*Table, error) {
addr, err := net.ResolveUDPAddr("udp", laddr)
if err != nil {
return nil, err
@@ -210,7 +220,7 @@ func ListenUDP(priv *ecdsa.PrivateKey, laddr string, natm nat.Interface, nodeDBP
if err != nil {
return nil, err
}
- tab, _, err := newUDP(priv, conn, natm, nodeDBPath)
+ tab, _, err := newUDP(priv, conn, natm, nodeDBPath, netrestrict)
if err != nil {
return nil, err
}
@@ -218,13 +228,14 @@ func ListenUDP(priv *ecdsa.PrivateKey, laddr string, natm nat.Interface, nodeDBP
return tab, nil
}
-func newUDP(priv *ecdsa.PrivateKey, c conn, natm nat.Interface, nodeDBPath string) (*Table, *udp, error) {
+func newUDP(priv *ecdsa.PrivateKey, c conn, natm nat.Interface, nodeDBPath string, netrestrict *netutil.Netlist) (*Table, *udp, error) {
udp := &udp{
- conn: c,
- priv: priv,
- closing: make(chan struct{}),
- gotreply: make(chan reply),
- addpending: make(chan *pending),
+ conn: c,
+ priv: priv,
+ netrestrict: netrestrict,
+ closing: make(chan struct{}),
+ gotreply: make(chan reply),
+ addpending: make(chan *pending),
}
realaddr := c.LocalAddr().(*net.UDPAddr)
if natm != nil {
@@ -281,9 +292,12 @@ func (t *udp) findnode(toid NodeID, toaddr *net.UDPAddr, target NodeID) ([]*Node
reply := r.(*neighbors)
for _, rn := range reply.Nodes {
nreceived++
- if n, err := nodeFromRPC(rn); err == nil {
- nodes = append(nodes, n)
+ n, err := t.nodeFromRPC(toaddr, rn)
+ if err != nil {
+ glog.V(logger.Detail).Infof("invalid neighbor node (%v) from %v: %v", rn.IP, toaddr, err)
+ continue
}
+ nodes = append(nodes, n)
}
return nreceived >= bucketSize
})
@@ -479,13 +493,6 @@ func encodePacket(priv *ecdsa.PrivateKey, ptype byte, req interface{}) ([]byte,
return packet, nil
}
-func isTemporaryError(err error) bool {
- tempErr, ok := err.(interface {
- Temporary() bool
- })
- return ok && tempErr.Temporary() || isPacketTooBig(err)
-}
-
// readLoop runs in its own goroutine. it handles incoming UDP packets.
func (t *udp) readLoop() {
defer t.conn.Close()
@@ -495,7 +502,7 @@ func (t *udp) readLoop() {
buf := make([]byte, 1280)
for {
nbytes, from, err := t.conn.ReadFromUDP(buf)
- if isTemporaryError(err) {
+ if netutil.IsTemporaryError(err) {
// Ignore temporary read errors.
glog.V(logger.Debug).Infof("Temporary read error: %v", err)
continue
@@ -602,6 +609,9 @@ func (req *findnode) handle(t *udp, from *net.UDPAddr, fromID NodeID, mac []byte
// Send neighbors in chunks with at most maxNeighbors per packet
// to stay below the 1280 byte limit.
for i, n := range closest {
+ if netutil.CheckRelayIP(from.IP, n.IP) != nil {
+ continue
+ }
p.Nodes = append(p.Nodes, nodeToRPC(n))
if len(p.Nodes) == maxNeighbors || i == len(closest)-1 {
t.send(from, neighborsPacket, p)
diff --git a/p2p/discover/udp_notwindows.go b/p2p/discover/udp_notwindows.go
deleted file mode 100644
index e9de83aa9..000000000
--- a/p2p/discover/udp_notwindows.go
+++ /dev/null
@@ -1,26 +0,0 @@
-// Copyright 2016 The go-ethereum Authors
-// This file is part of the go-ethereum library.
-//
-// The go-ethereum library is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Lesser General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// The go-ethereum library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public License
-// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
-
-//+build !windows
-
-package discover
-
-// reports whether err indicates that a UDP packet didn't
-// fit the receive buffer. There is no such error on
-// non-Windows platforms.
-func isPacketTooBig(err error) bool {
- return false
-}
diff --git a/p2p/discover/udp_test.go b/p2p/discover/udp_test.go
index f43bf3726..53cfac6f9 100644
--- a/p2p/discover/udp_test.go
+++ b/p2p/discover/udp_test.go
@@ -43,56 +43,6 @@ func init() {
spew.Config.DisableMethods = true
}
-// This test checks that isPacketTooBig correctly identifies
-// errors that result from receiving a UDP packet larger
-// than the supplied receive buffer.
-func TestIsPacketTooBig(t *testing.T) {
- listener, err := net.ListenPacket("udp", "127.0.0.1:0")
- if err != nil {
- t.Fatal(err)
- }
- defer listener.Close()
- sender, err := net.Dial("udp", listener.LocalAddr().String())
- if err != nil {
- t.Fatal(err)
- }
- defer sender.Close()
-
- sendN := 1800
- recvN := 300
- for i := 0; i < 20; i++ {
- go func() {
- buf := make([]byte, sendN)
- for i := range buf {
- buf[i] = byte(i)
- }
- sender.Write(buf)
- }()
-
- buf := make([]byte, recvN)
- listener.SetDeadline(time.Now().Add(1 * time.Second))
- n, _, err := listener.ReadFrom(buf)
- if err != nil {
- if nerr, ok := err.(net.Error); ok && nerr.Timeout() {
- continue
- }
- if !isPacketTooBig(err) {
- t.Fatal("unexpected read error:", spew.Sdump(err))
- }
- continue
- }
- if n != recvN {
- t.Fatalf("short read: %d, want %d", n, recvN)
- }
- for i := range buf {
- if buf[i] != byte(i) {
- t.Fatalf("error in pattern")
- break
- }
- }
- }
-}
-
// shared test variables
var (
futureExp = uint64(time.Now().Add(10 * time.Hour).Unix())
@@ -118,9 +68,9 @@ func newUDPTest(t *testing.T) *udpTest {
pipe: newpipe(),
localkey: newkey(),
remotekey: newkey(),
- remoteaddr: &net.UDPAddr{IP: net.IP{1, 2, 3, 4}, Port: 30303},
+ remoteaddr: &net.UDPAddr{IP: net.IP{10, 0, 1, 99}, Port: 30303},
}
- test.table, test.udp, _ = newUDP(test.localkey, test.pipe, nil, "")
+ test.table, test.udp, _ = newUDP(test.localkey, test.pipe, nil, "", nil)
return test
}
@@ -362,8 +312,9 @@ func TestUDP_findnodeMultiReply(t *testing.T) {
// check that the sent neighbors are all returned by findnode
select {
case result := <-resultc:
- if !reflect.DeepEqual(result, list) {
- t.Errorf("neighbors mismatch:\n got: %v\n want: %v", result, list)
+ want := append(list[:2], list[3:]...)
+ if !reflect.DeepEqual(result, want) {
+ t.Errorf("neighbors mismatch:\n got: %v\n want: %v", result, want)
}
case err := <-errc:
t.Errorf("findnode error: %v", err)
diff --git a/p2p/discover/udp_windows.go b/p2p/discover/udp_windows.go
deleted file mode 100644
index 66bbf9597..000000000
--- a/p2p/discover/udp_windows.go
+++ /dev/null
@@ -1,40 +0,0 @@
-// Copyright 2016 The go-ethereum Authors
-// This file is part of the go-ethereum library.
-//
-// The go-ethereum library is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Lesser General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// The go-ethereum library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public License
-// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
-
-//+build windows
-
-package discover
-
-import (
- "net"
- "os"
- "syscall"
-)
-
-const _WSAEMSGSIZE = syscall.Errno(10040)
-
-// reports whether err indicates that a UDP packet didn't
-// fit the receive buffer. On Windows, WSARecvFrom returns
-// code WSAEMSGSIZE and no data if this happens.
-func isPacketTooBig(err error) bool {
- if opErr, ok := err.(*net.OpError); ok {
- if scErr, ok := opErr.Err.(*os.SyscallError); ok {
- return scErr.Err == _WSAEMSGSIZE
- }
- return opErr.Err == _WSAEMSGSIZE
- }
- return false
-}