diff --git a/prog/weaver/main.go b/prog/weaver/main.go index e35ac49cae..4994232fa4 100644 --- a/prog/weaver/main.go +++ b/prog/weaver/main.go @@ -32,28 +32,30 @@ func main() { runtime.GOMAXPROCS(procs) var ( - config weave.Config - justVersion bool - ifaceName string - routerName string - nickName string - password string - wait int - pktdebug bool - logLevel string - prof string - bufSzMB int - noDiscovery bool - httpAddr string - iprangeCIDR string - ipsubnetCIDR string - peerCount int - apiPath string - peers []string + config weave.Config + justVersion bool + protocolMinVersion int + ifaceName string + routerName string + nickName string + password string + wait int + pktdebug bool + logLevel string + prof string + bufSzMB int + noDiscovery bool + httpAddr string + iprangeCIDR string + ipsubnetCIDR string + peerCount int + apiPath string + peers []string ) mflag.BoolVar(&justVersion, []string{"#version", "-version"}, false, "print version and exit") mflag.IntVar(&config.Port, []string{"#port", "-port"}, weave.Port, "router port") + mflag.IntVar(&protocolMinVersion, []string{"#protocol-min-version", "-protocol-min-version"}, weave.ProtocolMinVersion, "minimum Weave Net protocol version") mflag.StringVar(&ifaceName, []string{"#iface", "-iface"}, "", "name of interface to capture/inject from (disabled if blank)") mflag.StringVar(&routerName, []string{"#name", "-name"}, "", "name of router (defaults to MAC of interface)") mflag.StringVar(&nickName, []string{"#nickname", "-nickname"}, "", "nickname of peer (defaults to hostname)") @@ -82,6 +84,11 @@ func main() { Log.Println("Command line options:", options()) Log.Println("Command line peers:", peers) + if protocolMinVersion < weave.ProtocolMinVersion || protocolMinVersion > weave.ProtocolMaxVersion { + Log.Fatalf("--protocol-min-version must be in range [%d,%d]", weave.ProtocolMinVersion, weave.ProtocolMaxVersion) + } + config.ProtocolMinVersion = byte(protocolMinVersion) + var err error if ifaceName != "" { diff --git a/router/connection.go b/router/connection.go index 65c1893550..17d05b77e8 100644 --- a/router/connection.go +++ b/router/connection.go @@ -285,10 +285,12 @@ func (conn *LocalConnection) run(actionChan <-chan ConnectionAction, finished ch conn.TCPConn.SetLinger(0) intro, err := ProtocolIntroParams{ - Features: conn.makeFeatures(), - Conn: conn.TCPConn, - Password: conn.Router.Password, - Outbound: conn.outbound, + MinVersion: conn.Router.ProtocolMinVersion, + MaxVersion: ProtocolMaxVersion, + Features: conn.makeFeatures(), + Conn: conn.TCPConn, + Password: conn.Router.Password, + Outbound: conn.outbound, }.DoIntro() if err != nil { return diff --git a/router/protocol.go b/router/protocol.go index 89629c6bf7..dc32f389ff 100644 --- a/router/protocol.go +++ b/router/protocol.go @@ -10,9 +10,9 @@ import ( ) const ( - Protocol = "weave" - ProtocolMinVersion byte = 1 - ProtocolVersion byte = 2 + Protocol = "weave" + ProtocolMinVersion = 1 + ProtocolMaxVersion = 2 ) var ( @@ -48,10 +48,12 @@ type ProtocolIntroConn interface { } type ProtocolIntroParams struct { - Features map[string]string - Conn ProtocolIntroConn - Password []byte - Outbound bool + MinVersion byte + MaxVersion byte + Features map[string]string + Conn ProtocolIntroConn + Password []byte + Outbound bool } type ProtocolIntroResults struct { @@ -63,15 +65,11 @@ type ProtocolIntroResults struct { } func (params ProtocolIntroParams) DoIntro() (res ProtocolIntroResults, err error) { - return params.doIntro(ProtocolVersion) -} - -func (params ProtocolIntroParams) doIntro(maxVersion byte) (res ProtocolIntroResults, err error) { if err = params.Conn.SetDeadline(time.Now().Add(HeaderTimeout)); err != nil { return } - if res.Version, err = params.exchangeProtocolHeader(maxVersion); err != nil { + if res.Version, err = params.exchangeProtocolHeader(); err != nil { return } @@ -101,10 +99,10 @@ func (params ProtocolIntroParams) doIntro(maxVersion byte) (res ProtocolIntroRes return } -func (params ProtocolIntroParams) exchangeProtocolHeader(maxVersion byte) (byte, error) { +func (params ProtocolIntroParams) exchangeProtocolHeader() (byte, error) { // Write in a separate goroutine to avoid the possibility of // deadlock - sendHeader := append(ProtocolBytes, ProtocolMinVersion, maxVersion) + sendHeader := append(ProtocolBytes, params.MinVersion, params.MaxVersion) writeDone := make(chan error, 1) go func() { _, err := params.Conn.Write(sendHeader) @@ -125,27 +123,27 @@ func (params ProtocolIntroParams) exchangeProtocolHeader(maxVersion byte) (byte, theirMinVersion := header[len(ProtocolBytes)] minVersion := theirMinVersion - if ProtocolMinVersion > minVersion { - minVersion = ProtocolMinVersion + if params.MinVersion > minVersion { + minVersion = params.MinVersion } - theirVersion := header[len(ProtocolBytes)+1] - version := theirVersion - if version > maxVersion { - version = maxVersion + theirMaxVersion := header[len(ProtocolBytes)+1] + maxVersion := theirMaxVersion + if maxVersion > params.MaxVersion { + maxVersion = params.MaxVersion } - if minVersion > version { + if minVersion > maxVersion { return 0, fmt.Errorf("remote version range [%d,%d] is incompatible with ours [%d,%d]", - theirMinVersion, theirVersion, - ProtocolMinVersion, maxVersion) + theirMinVersion, theirMaxVersion, + params.MinVersion, params.MaxVersion) } if err := <-writeDone; err != nil { return 0, err } - return version, nil + return maxVersion, nil } // The V1 procotol consists of the protocol identification/version diff --git a/router/protocol_test.go b/router/protocol_test.go index 6cd36939b0..1a56079a08 100644 --- a/router/protocol_test.go +++ b/router/protocol_test.go @@ -33,10 +33,10 @@ func connPair() (ProtocolIntroConn, ProtocolIntroConn) { return &a, &b } -func doIntro(t *testing.T, ver byte, params ProtocolIntroParams) <-chan ProtocolIntroResults { +func doIntro(t *testing.T, params ProtocolIntroParams) <-chan ProtocolIntroResults { ch := make(chan ProtocolIntroResults, 1) go func() { - res, err := params.doIntro(ver) + res, err := params.DoIntro() require.Nil(t, err) ch <- res }() @@ -45,17 +45,21 @@ func doIntro(t *testing.T, ver byte, params ProtocolIntroParams) <-chan Protocol func doProtocolIntro(t *testing.T, aver, bver byte, password []byte) byte { aconn, bconn := connPair() - aresch := doIntro(t, aver, ProtocolIntroParams{ - Features: map[string]string{"Name": "A"}, - Conn: aconn, - Outbound: true, - Password: password, + aresch := doIntro(t, ProtocolIntroParams{ + MinVersion: ProtocolMinVersion, + MaxVersion: aver, + Features: map[string]string{"Name": "A"}, + Conn: aconn, + Outbound: true, + Password: password, }) - bresch := doIntro(t, bver, ProtocolIntroParams{ - Features: map[string]string{"Name": "B"}, - Conn: bconn, - Outbound: false, - Password: password, + bresch := doIntro(t, ProtocolIntroParams{ + MinVersion: ProtocolMinVersion, + MaxVersion: bver, + Features: map[string]string{"Name": "B"}, + Conn: bconn, + Outbound: false, + Password: password, }) ares := <-aresch bres := <-bresch diff --git a/router/router.go b/router/router.go index f4a254fc8f..9d9df0a9db 100644 --- a/router/router.go +++ b/router/router.go @@ -28,13 +28,14 @@ const ( type LogFrameFunc func(string, []byte, *EthernetDecoder) type Config struct { - Port int - Iface *net.Interface - Password []byte - ConnLimit int - PeerDiscovery bool - BufSz int - LogFrame LogFrameFunc + Port int + ProtocolMinVersion byte + Iface *net.Interface + Password []byte + ConnLimit int + PeerDiscovery bool + BufSz int + LogFrame LogFrameFunc } type Router struct {