aboutsummaryrefslogtreecommitdiffstats
path: root/p2p/dial.go
diff options
context:
space:
mode:
authorFelix Lange <fjl@twurst.com>2016-11-23 03:51:59 +0800
committerFelix Lange <fjl@twurst.com>2016-11-23 05:21:18 +0800
commita47341cf96498332e2f0f67c1a6456c67831a5d0 (patch)
tree92e3c89aa1060e210cc288a68dddaa24be161181 /p2p/dial.go
parente46bda50935cfad5bfc51130e4ea802f518917e7 (diff)
downloadgo-tangerine-a47341cf96498332e2f0f67c1a6456c67831a5d0.tar
go-tangerine-a47341cf96498332e2f0f67c1a6456c67831a5d0.tar.gz
go-tangerine-a47341cf96498332e2f0f67c1a6456c67831a5d0.tar.bz2
go-tangerine-a47341cf96498332e2f0f67c1a6456c67831a5d0.tar.lz
go-tangerine-a47341cf96498332e2f0f67c1a6456c67831a5d0.tar.xz
go-tangerine-a47341cf96498332e2f0f67c1a6456c67831a5d0.tar.zst
go-tangerine-a47341cf96498332e2f0f67c1a6456c67831a5d0.zip
p2p, p2p/discover, p2p/discv5: add IP network restriction feature
The p2p packages can now be configured to restrict all communication to a certain subset of IP networks. This feature is meant to be used for private networks.
Diffstat (limited to 'p2p/dial.go')
-rw-r--r--p2p/dial.go45
1 files changed, 38 insertions, 7 deletions
diff --git a/p2p/dial.go b/p2p/dial.go
index 691b8539e..57fba136a 100644
--- a/p2p/dial.go
+++ b/p2p/dial.go
@@ -19,6 +19,7 @@ package p2p
import (
"container/heap"
"crypto/rand"
+ "errors"
"fmt"
"net"
"time"
@@ -26,6 +27,7 @@ import (
"github.com/ethereum/go-ethereum/logger"
"github.com/ethereum/go-ethereum/logger/glog"
"github.com/ethereum/go-ethereum/p2p/discover"
+ "github.com/ethereum/go-ethereum/p2p/netutil"
)
const (
@@ -48,6 +50,7 @@ const (
type dialstate struct {
maxDynDials int
ntab discoverTable
+ netrestrict *netutil.Netlist
lookupRunning bool
dialing map[discover.NodeID]connFlag
@@ -100,10 +103,11 @@ type waitExpireTask struct {
time.Duration
}
-func newDialState(static []*discover.Node, ntab discoverTable, maxdyn int) *dialstate {
+func newDialState(static []*discover.Node, ntab discoverTable, maxdyn int, netrestrict *netutil.Netlist) *dialstate {
s := &dialstate{
maxDynDials: maxdyn,
ntab: ntab,
+ netrestrict: netrestrict,
static: make(map[discover.NodeID]*dialTask),
dialing: make(map[discover.NodeID]connFlag),
randomNodes: make([]*discover.Node, maxdyn/2),
@@ -128,12 +132,9 @@ func (s *dialstate) removeStatic(n *discover.Node) {
func (s *dialstate) newTasks(nRunning int, peers map[discover.NodeID]*Peer, now time.Time) []task {
var newtasks []task
- isDialing := func(id discover.NodeID) bool {
- _, found := s.dialing[id]
- return found || peers[id] != nil || s.hist.contains(id)
- }
addDial := func(flag connFlag, n *discover.Node) bool {
- if isDialing(n.ID) {
+ if err := s.checkDial(n, peers); err != nil {
+ glog.V(logger.Debug).Infof("skipping dial candidate %x@%v:%d: %v", n.ID[:8], n.IP, n.TCP, err)
return false
}
s.dialing[n.ID] = flag
@@ -159,7 +160,12 @@ func (s *dialstate) newTasks(nRunning int, peers map[discover.NodeID]*Peer, now
// Create dials for static nodes if they are not connected.
for id, t := range s.static {
- if !isDialing(id) {
+ err := s.checkDial(t.dest, peers)
+ switch err {
+ case errNotWhitelisted, errSelf:
+ glog.V(logger.Debug).Infof("removing static dial candidate %x@%v:%d: %v", t.dest.ID[:8], t.dest.IP, t.dest.TCP, err)
+ delete(s.static, t.dest.ID)
+ case nil:
s.dialing[id] = t.flags
newtasks = append(newtasks, t)
}
@@ -202,6 +208,31 @@ func (s *dialstate) newTasks(nRunning int, peers map[discover.NodeID]*Peer, now
return newtasks
}
+var (
+ errSelf = errors.New("is self")
+ errAlreadyDialing = errors.New("already dialing")
+ errAlreadyConnected = errors.New("already connected")
+ errRecentlyDialed = errors.New("recently dialed")
+ errNotWhitelisted = errors.New("not contained in netrestrict whitelist")
+)
+
+func (s *dialstate) checkDial(n *discover.Node, peers map[discover.NodeID]*Peer) error {
+ _, dialing := s.dialing[n.ID]
+ switch {
+ case dialing:
+ return errAlreadyDialing
+ case peers[n.ID] != nil:
+ return errAlreadyConnected
+ case s.ntab != nil && n.ID == s.ntab.Self().ID:
+ return errSelf
+ case s.netrestrict != nil && !s.netrestrict.Contains(n.IP):
+ return errNotWhitelisted
+ case s.hist.contains(n.ID):
+ return errRecentlyDialed
+ }
+ return nil
+}
+
func (s *dialstate) taskDone(t task, now time.Time) {
switch t := t.(type) {
case *dialTask: