Skip to content

Commit

Permalink
Add a --protocol-min-version option to router
Browse files Browse the repository at this point in the history
To allow users to forgo compatibility with Weave Net 1.0 in order to
avoid weaveworks#912, by setting --protocol-min-version=2.
Defaults to --protocol-min-version=1, i.e. compatible but vulnerable.
  • Loading branch information
dpw committed Jul 8, 2015
1 parent d7fd3ea commit ce8dfb7
Show file tree
Hide file tree
Showing 5 changed files with 77 additions and 65 deletions.
43 changes: 25 additions & 18 deletions prog/weaver/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -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{"-min-protocol-version"}, weave.ProtocolMinVersion, "minimum weave 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)")
Expand Down Expand Up @@ -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("--min-protocol-version must be in range [%d,%d]", weave.ProtocolMinVersion, weave.ProtocolMaxVersion)
}
config.ProtocolMinVersion = byte(protocolMinVersion)

var err error

if ifaceName != "" {
Expand Down
10 changes: 6 additions & 4 deletions router/connection.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
46 changes: 22 additions & 24 deletions router/protocol.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@ import (
)

const (
Protocol = "weave"
ProtocolMinVersion byte = 1
ProtocolVersion byte = 2
Protocol = "weave"
ProtocolMinVersion = 1
ProtocolMaxVersion = 2
)

var (
Expand Down Expand Up @@ -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 {
Expand All @@ -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
}

Expand Down Expand Up @@ -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)
Expand All @@ -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
Expand Down
28 changes: 16 additions & 12 deletions router/protocol_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
}()
Expand All @@ -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
Expand Down
15 changes: 8 additions & 7 deletions router/router.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down

0 comments on commit ce8dfb7

Please sign in to comment.