From 330175889ed92ef3410c5f19ae1c6b8393e9a878 Mon Sep 17 00:00:00 2001 From: Arceliar Date: Thu, 14 Jun 2018 07:08:48 -0500 Subject: [PATCH 01/22] switch address range from fd00::/8 to the deprecated 0200::/7 range --- src/yggdrasil/address.go | 31 +++++++++++++++---------------- src/yggdrasil/admin.go | 2 +- 2 files changed, 16 insertions(+), 17 deletions(-) diff --git a/src/yggdrasil/address.go b/src/yggdrasil/address.go index e0baf9ca..a499edfa 100644 --- a/src/yggdrasil/address.go +++ b/src/yggdrasil/address.go @@ -7,9 +7,10 @@ type address [16]byte type subnet [8]byte // address_prefix is the prefix used for all addresses and subnets in the network. -// The current implementation requires this to be a multiple of 8 bits. +// The current implementation requires this to be a muliple of 8 bits + 7 bits. +// The 8th bit of the last byte is used to signal nodes (0) or /64 prefixes (1). // Nodes that configure this differently will be unable to communicate with eachother, though routing and the DHT machinery *should* still work. -var address_prefix = [...]byte{0xfd} +var address_prefix = [...]byte{0x02} // isValid returns true if an address falls within the range used by nodes in the network. func (a *address) isValid() bool { @@ -18,7 +19,7 @@ func (a *address) isValid() bool { return false } } - return (*a)[len(address_prefix)]&0x80 == 0 + return (*a)[len(address_prefix)-1]&0x80 == 0 } // isValid returns true if a prefix falls within the range usable by the network. @@ -28,14 +29,13 @@ func (s *subnet) isValid() bool { return false } } - return (*s)[len(address_prefix)]&0x80 != 0 + return (*s)[len(address_prefix)-1]&0x80 != 0 } // address_addrForNodeID takes a *NodeID as an argument and returns an *address. -// This address begins with the address prefix. -// The next bit is 0 for an address, and 1 for a subnet. -// The following 7 bits are set to the number of leading 1 bits in the NodeID. -// The NodeID, excluding the leading 1 bits and the first leading 1 bit, is truncated to the appropriate length and makes up the remainder of the address. +// This subnet begins with the address prefix, with the last bit set to 0 to indicate an address. +// The following 8 bits are set to the number of leading 1 bits in the NodeID. +// The NodeID, excluding the leading 1 bits and the first leading 0 bit, is truncated to the appropriate length and makes up the remainder of the address. func address_addrForNodeID(nid *NodeID) *address { // 128 bit address // Begins with prefix @@ -67,16 +67,15 @@ func address_addrForNodeID(nid *NodeID) *address { } } copy(addr[:], address_prefix[:]) - addr[len(address_prefix)] = ones & 0x7f + addr[len(address_prefix)] = ones copy(addr[len(address_prefix)+1:], temp) return &addr } // address_subnetForNodeID takes a *NodeID as an argument and returns a *subnet. -// This subnet begins with the address prefix. -// The next bit is 0 for an address, and 1 for a subnet. -// The following 7 bits are set to the number of leading 1 bits in the NodeID. -// The NodeID, excluding the leading 1 bits and the first leading 1 bit, is truncated to the appropriate length and makes up the remainder of the subnet. +// This subnet begins with the address prefix, with the last bit set to 1 to indicate a prefix. +// The following 8 bits are set to the number of leading 1 bits in the NodeID. +// The NodeID, excluding the leading 1 bits and the first leading 0 bit, is truncated to the appropriate length and makes up the remainder of the subnet. func address_subnetForNodeID(nid *NodeID) *subnet { // Exactly as the address version, with two exceptions: // 1) The first bit after the fixed prefix is a 1 instead of a 0 @@ -84,7 +83,7 @@ func address_subnetForNodeID(nid *NodeID) *subnet { addr := *address_addrForNodeID(nid) var snet subnet copy(snet[:], addr[:]) - snet[len(address_prefix)] |= 0x80 + snet[len(address_prefix)-1] |= 0x80 return &snet } @@ -97,7 +96,7 @@ func (a *address) getNodeIDandMask() (*NodeID, *NodeID) { // This means truncated leading 1s, first leading 0, and visible part of addr var nid NodeID var mask NodeID - ones := int(a[len(address_prefix)] & 0x7f) + ones := int(a[len(address_prefix)]) for idx := 0; idx < ones; idx++ { nid[idx/8] |= 0x80 >> byte(idx%8) } @@ -125,7 +124,7 @@ func (s *subnet) getNodeIDandMask() (*NodeID, *NodeID) { // As with the address version, but visible parts of the subnet prefix instead var nid NodeID var mask NodeID - ones := int(s[len(address_prefix)] & 0x7f) + ones := int(s[len(address_prefix)]) for idx := 0; idx < ones; idx++ { nid[idx/8] |= 0x80 >> byte(idx%8) } diff --git a/src/yggdrasil/admin.go b/src/yggdrasil/admin.go index f09835f6..0a9194ef 100644 --- a/src/yggdrasil/admin.go +++ b/src/yggdrasil/admin.go @@ -406,7 +406,7 @@ func (a *admin) startTunWithMTU(ifname string, iftapmode bool, ifmtu int) error _ = a.core.tun.close() // Then reconfigure and start it addr := a.core.router.addr - straddr := fmt.Sprintf("%s/%v", net.IP(addr[:]).String(), 8*len(address_prefix)) + straddr := fmt.Sprintf("%s/%v", net.IP(addr[:]).String(), 8*len(address_prefix)-1) if ifname != "none" { err := a.core.tun.setup(ifname, iftapmode, straddr, ifmtu) if err != nil { From 474fdda8cae0620658036fc4c91db384e0b7567a Mon Sep 17 00:00:00 2001 From: Neil Alexander Date: Thu, 14 Jun 2018 13:24:37 +0100 Subject: [PATCH 02/22] Fix launchd script path and amend debian control file --- contrib/deb/generate.sh | 7 ++++--- contrib/macos/yggdrasil.plist | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/contrib/deb/generate.sh b/contrib/deb/generate.sh index bcc4750f..e383ddcd 100644 --- a/contrib/deb/generate.sh +++ b/contrib/deb/generate.sh @@ -34,7 +34,7 @@ mkdir -p /tmp/$PKGNAME/usr/bin/ mkdir -p /tmp/$PKGNAME/etc/systemd/system/ cat > /tmp/$PKGNAME/debian/changelog << EOF -Please see https://github.com/Arceliar/yggdrasil-go/ +Please see https://github.com/yggdrasil-network/yggdrasil-go/ EOF echo 9 > /tmp/$PKGNAME/debian/compat cat > /tmp/$PKGNAME/debian/control << EOF @@ -43,15 +43,16 @@ Version: $PKGVERSION Section: contrib/net Priority: extra Architecture: $PKGARCH +Replaces: yggdrasil yggdrasil-develop Maintainer: Neil Alexander Description: Debian yggdrasil package Binary yggdrasil package for Debian and Ubuntu EOF cat > /tmp/$PKGNAME/debian/copyright << EOF -Please see https://github.com/Arceliar/yggdrasil-go/ +Please see https://github.com/yggdrasil-network/yggdrasil-go/ EOF cat > /tmp/$PKGNAME/debian/docs << EOF -Please see https://github.com/Arceliar/yggdrasil-go/ +Please see https://github.com/yggdrasil-network/yggdrasil-go/ EOF cat > /tmp/$PKGNAME/debian/install << EOF usr/bin/yggdrasil usr/bin diff --git a/contrib/macos/yggdrasil.plist b/contrib/macos/yggdrasil.plist index f6afbc90..e5d30240 100644 --- a/contrib/macos/yggdrasil.plist +++ b/contrib/macos/yggdrasil.plist @@ -8,7 +8,7 @@ sh -c - /usr/bin/yggdrasil -useconf < /etc/yggdrasil.conf + /usr/local/bin/yggdrasil -useconf < /etc/yggdrasil.conf KeepAlive From e7fca666554cddb3f7104d920c59c98cdb79ca7f Mon Sep 17 00:00:00 2001 From: Arceliar Date: Thu, 14 Jun 2018 07:58:07 -0500 Subject: [PATCH 03/22] fix address/prefix code, platform specific parts still need testing --- src/yggdrasil/address.go | 9 +++++---- src/yggdrasil/core.go | 2 +- src/yggdrasil/icmpv6.go | 2 +- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/yggdrasil/address.go b/src/yggdrasil/address.go index a499edfa..dd2c410a 100644 --- a/src/yggdrasil/address.go +++ b/src/yggdrasil/address.go @@ -19,17 +19,18 @@ func (a *address) isValid() bool { return false } } - return (*a)[len(address_prefix)-1]&0x80 == 0 + return true } // isValid returns true if a prefix falls within the range usable by the network. func (s *subnet) isValid() bool { - for idx := range address_prefix { + l := len(address_prefix) + for idx := range address_prefix[:l-1] { if (*s)[idx] != address_prefix[idx] { return false } } - return (*s)[len(address_prefix)-1]&0x80 != 0 + return (*s)[l-1] == address_prefix[l-1]|0x01 } // address_addrForNodeID takes a *NodeID as an argument and returns an *address. @@ -83,7 +84,7 @@ func address_subnetForNodeID(nid *NodeID) *subnet { addr := *address_addrForNodeID(nid) var snet subnet copy(snet[:], addr[:]) - snet[len(address_prefix)-1] |= 0x80 + snet[len(address_prefix)-1] |= 0x01 return &snet } diff --git a/src/yggdrasil/core.go b/src/yggdrasil/core.go index e1da6fee..bd7fecec 100644 --- a/src/yggdrasil/core.go +++ b/src/yggdrasil/core.go @@ -117,7 +117,7 @@ func (c *Core) Start(nc *config.NodeConfig, log *log.Logger) error { } ip := net.IP(c.router.addr[:]).String() - if err := c.tun.start(nc.IfName, nc.IfTAPMode, fmt.Sprintf("%s/8", ip), nc.IfMTU); err != nil { + if err := c.tun.start(nc.IfName, nc.IfTAPMode, fmt.Sprintf("%s/%d", ip, 8*len(address_prefix)-1), nc.IfMTU); err != nil { c.log.Println("Failed to start TUN/TAP") return err } diff --git a/src/yggdrasil/icmpv6.go b/src/yggdrasil/icmpv6.go index 1eb1c67c..0491f880 100644 --- a/src/yggdrasil/icmpv6.go +++ b/src/yggdrasil/icmpv6.go @@ -252,7 +252,7 @@ func (i *icmpv6) handle_ndp(in []byte) ([]byte, error) { case source.isValid(): case snet.isValid(): default: - return nil, errors.New("Not an NDP for fd00::/8") + return nil, errors.New("Not an NDP for 0200::/7") } // Create our NDP message body response From 93ffc0b876562b35053b5668c69b94d8a4f152c7 Mon Sep 17 00:00:00 2001 From: Arceliar Date: Thu, 14 Jun 2018 08:00:57 -0500 Subject: [PATCH 04/22] macos --- src/yggdrasil/tun_darwin.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/yggdrasil/tun_darwin.go b/src/yggdrasil/tun_darwin.go index bdfda387..ff85aa40 100644 --- a/src/yggdrasil/tun_darwin.go +++ b/src/yggdrasil/tun_darwin.go @@ -87,7 +87,7 @@ func (tun *tunDevice) setupAddress(addr string) error { ar.ifra_prefixmask.sin6_len = uint8(unsafe.Sizeof(ar.ifra_prefixmask)) b := make([]byte, 16) - binary.LittleEndian.PutUint16(b, uint16(0xFF00)) + binary.LittleEndian.PutUint16(b, uint16(0xFE00)) ar.ifra_prefixmask.sin6_addr[0] = uint16(binary.BigEndian.Uint16(b)) ar.ifra_addr.sin6_len = uint8(unsafe.Sizeof(ar.ifra_addr)) From f7a7f601a0938ecd5d0bf8316120865bebd69932 Mon Sep 17 00:00:00 2001 From: Arceliar Date: Thu, 14 Jun 2018 08:38:43 -0500 Subject: [PATCH 05/22] cleanup old ugly session MTU code that only mattered with lossy UDP fragments --- src/yggdrasil/session.go | 27 --------------------------- 1 file changed, 27 deletions(-) diff --git a/src/yggdrasil/session.go b/src/yggdrasil/session.go index 2580f45d..b36349ac 100644 --- a/src/yggdrasil/session.go +++ b/src/yggdrasil/session.go @@ -437,41 +437,14 @@ func (sinfo *sessionInfo) doSend(bs []byte) { // TODO? remove the MTU updating part? That should never happen with TCP peers, and the old UDP code that caused it was removed (and if replaced, should be replaced with something that can reliably send messages with an arbitrary size). func (sinfo *sessionInfo) doRecv(p *wire_trafficPacket) { defer util_putBytes(p.Payload) - payloadSize := uint16(len(p.Payload)) if !sinfo.nonceIsOK(&p.Nonce) { return } bs, isOK := boxOpen(&sinfo.sharedSesKey, p.Payload, &p.Nonce) if !isOK { - // We're going to guess that the session MTU is too large - // Set myMTU to the largest value we think we can receive - fixSessionMTU := func() { - // This clamps down to 1280 almost immediately over ipv4 - // Over link-local ipv6, it seems to approach link MTU - // So maybe it's doing the right thing?... - //sinfo.core.log.Println("DEBUG got bad packet:", payloadSize) - newMTU := payloadSize - boxOverhead - if newMTU < 1280 { - newMTU = 1280 - } - if newMTU < sinfo.myMTU { - sinfo.myMTU = newMTU - sinfo.core.sessions.sendPingPong(sinfo, false) - sinfo.mtuTime = time.Now() - sinfo.wasMTUFixed = true - } - } - go func() { sinfo.core.router.admin <- fixSessionMTU }() util_putBytes(bs) return } - fixSessionMTU := func() { - if time.Since(sinfo.mtuTime) > time.Minute { - sinfo.myMTU = uint16(sinfo.core.tun.mtu) - sinfo.mtuTime = time.Now() - } - } - go func() { sinfo.core.router.admin <- fixSessionMTU }() sinfo.updateNonce(&p.Nonce) sinfo.time = time.Now() sinfo.bytesRecvd += uint64(len(bs)) From 2ab5a1f1c2e76342b8326ec78beb661e50010b4d Mon Sep 17 00:00:00 2001 From: Neil Alexander Date: Thu, 14 Jun 2018 14:47:55 +0100 Subject: [PATCH 06/22] Fix debian control file --- contrib/deb/generate.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contrib/deb/generate.sh b/contrib/deb/generate.sh index e383ddcd..23024592 100644 --- a/contrib/deb/generate.sh +++ b/contrib/deb/generate.sh @@ -43,7 +43,7 @@ Version: $PKGVERSION Section: contrib/net Priority: extra Architecture: $PKGARCH -Replaces: yggdrasil yggdrasil-develop +Replaces: yggdrasil | yggdrasil-develop Maintainer: Neil Alexander Description: Debian yggdrasil package Binary yggdrasil package for Debian and Ubuntu From 7cc067e3a5018bd9bafb1291301feaed4f74fa95 Mon Sep 17 00:00:00 2001 From: Neil Alexander Date: Thu, 14 Jun 2018 15:07:39 +0100 Subject: [PATCH 07/22] Let's try this again --- contrib/deb/generate.sh | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/contrib/deb/generate.sh b/contrib/deb/generate.sh index 23024592..21840bc1 100644 --- a/contrib/deb/generate.sh +++ b/contrib/deb/generate.sh @@ -15,6 +15,11 @@ PKGNAME=$(sh contrib/semver/name.sh) PKGVERSION=$(sh contrib/semver/version.sh | cut -c 2-) PKGARCH=${PKGARCH-amd64} PKGFILE=$PKGNAME-$PKGVERSION-$PKGARCH.deb +PKGREPLACES=yggdrasil + +if [ $PKGBRANCH = "master" ]; then + PKGREPLACES=yggdrasil-develop +fi if [ $PKGARCH = "amd64" ]; then GOARCH=amd64 GOOS=linux ./build elif [ $PKGARCH = "i386" ]; then GOARCH=386 GOOS=linux ./build @@ -43,7 +48,7 @@ Version: $PKGVERSION Section: contrib/net Priority: extra Architecture: $PKGARCH -Replaces: yggdrasil | yggdrasil-develop +Replaces: $PKGREPLACES Maintainer: Neil Alexander Description: Debian yggdrasil package Binary yggdrasil package for Debian and Ubuntu From 57837057b7874741f9e6ff829fb197b27fd6541b Mon Sep 17 00:00:00 2001 From: Arceliar Date: Thu, 14 Jun 2018 09:11:34 -0500 Subject: [PATCH 08/22] tcp/socks cleanup --- src/yggdrasil/tcp.go | 66 +++++++++++++++++--------------------------- 1 file changed, 26 insertions(+), 40 deletions(-) diff --git a/src/yggdrasil/tcp.go b/src/yggdrasil/tcp.go index 9590f221..a768ec70 100644 --- a/src/yggdrasil/tcp.go +++ b/src/yggdrasil/tcp.go @@ -60,28 +60,17 @@ func (iface *tcpInterface) getAddr() *net.TCPAddr { // Attempts to initiate a connection to the provided address. func (iface *tcpInterface) connect(addr string) { - iface.call(addr) + iface.call(addr, nil) } // Attempst to initiate a connection to the provided address, viathe provided socks proxy address. func (iface *tcpInterface) connectSOCKS(socksaddr, peeraddr string) { - // TODO make sure this doesn't keep attempting/killing connections when one is already active. - // I think some of the interaction between this and callWithConn needs work, so the dial isn't even attempted if there's already an outgoing call to peeraddr. - // Or maybe only if there's already an outgoing call to peeraddr via this socksaddr? go func() { dialer, err := proxy.SOCKS5("tcp", socksaddr, nil, proxy.Direct) - if err == nil { - conn, err := dialer.Dial("tcp", peeraddr) - if err == nil { - iface.callWithConn(&wrappedConn{ - c: conn, - raddr: &wrappedAddr{ - network: "tcp", - addr: peeraddr, - }, - }) - } + if err != nil { + return } + iface.call(peeraddr, dialer) }() } @@ -112,33 +101,12 @@ func (iface *tcpInterface) listener() { } } -// Called by connectSOCKS, it's like call but with the connection already established. -func (iface *tcpInterface) callWithConn(conn net.Conn) { - go func() { - raddr := conn.RemoteAddr().String() - iface.mutex.Lock() - _, isIn := iface.calls[raddr] - iface.mutex.Unlock() - if !isIn { - iface.mutex.Lock() - iface.calls[raddr] = struct{}{} - iface.mutex.Unlock() - defer func() { - iface.mutex.Lock() - delete(iface.calls, raddr) - iface.mutex.Unlock() - }() - iface.handler(conn, false) - } - }() -} - // Checks if a connection already exists. // If not, it adds it to the list of active outgoing calls (to block future attempts) and dials the address. // If the dial is successful, it launches the handler. // When finished, it removes the outgoing call, so reconnection attempts can be made later. // This all happens in a separate goroutine that it spawns. -func (iface *tcpInterface) call(saddr string) { +func (iface *tcpInterface) call(saddr string, dialer proxy.Dialer) { go func() { quit := false iface.mutex.Lock() @@ -153,13 +121,31 @@ func (iface *tcpInterface) call(saddr string) { }() } iface.mutex.Unlock() - if !quit { - conn, err := net.Dial("tcp", saddr) + if quit { + return + } + var conn net.Conn + var err error + if dialer != nil { + conn, err = dialer.Dial("tcp", saddr) + if err != nil { + return + } + // + conn = &wrappedConn{ + c: conn, + raddr: &wrappedAddr{ + network: "tcp", + addr: saddr, + }, + } + } else { + conn, err = net.Dial("tcp", saddr) if err != nil { return } - iface.handler(conn, false) } + iface.handler(conn, false) }() } From e8eaabf0c8d2aa80d012f870ff0c592947236c3f Mon Sep 17 00:00:00 2001 From: Arceliar Date: Thu, 14 Jun 2018 09:12:58 -0500 Subject: [PATCH 09/22] comment --- src/yggdrasil/tcp.go | 1 - 1 file changed, 1 deletion(-) diff --git a/src/yggdrasil/tcp.go b/src/yggdrasil/tcp.go index a768ec70..e70507f2 100644 --- a/src/yggdrasil/tcp.go +++ b/src/yggdrasil/tcp.go @@ -131,7 +131,6 @@ func (iface *tcpInterface) call(saddr string, dialer proxy.Dialer) { if err != nil { return } - // conn = &wrappedConn{ c: conn, raddr: &wrappedAddr{ From d9c97876110c7a62f70add6172a51ff88b1e4da4 Mon Sep 17 00:00:00 2001 From: Arceliar Date: Thu, 14 Jun 2018 09:21:35 -0500 Subject: [PATCH 10/22] avoid the proxy.SOCK5 connection attempt unless we're actually going to use the dialer --- src/yggdrasil/tcp.go | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/src/yggdrasil/tcp.go b/src/yggdrasil/tcp.go index e70507f2..48695419 100644 --- a/src/yggdrasil/tcp.go +++ b/src/yggdrasil/tcp.go @@ -65,13 +65,7 @@ func (iface *tcpInterface) connect(addr string) { // Attempst to initiate a connection to the provided address, viathe provided socks proxy address. func (iface *tcpInterface) connectSOCKS(socksaddr, peeraddr string) { - go func() { - dialer, err := proxy.SOCKS5("tcp", socksaddr, nil, proxy.Direct) - if err != nil { - return - } - iface.call(peeraddr, dialer) - }() + iface.call(peeraddr, &socksaddr) } // Initializes the struct. @@ -106,7 +100,7 @@ func (iface *tcpInterface) listener() { // If the dial is successful, it launches the handler. // When finished, it removes the outgoing call, so reconnection attempts can be made later. // This all happens in a separate goroutine that it spawns. -func (iface *tcpInterface) call(saddr string, dialer proxy.Dialer) { +func (iface *tcpInterface) call(saddr string, socksaddr *string) { go func() { quit := false iface.mutex.Lock() @@ -126,7 +120,12 @@ func (iface *tcpInterface) call(saddr string, dialer proxy.Dialer) { } var conn net.Conn var err error - if dialer != nil { + if socksaddr != nil { + var dialer proxy.Dialer + dialer, err = proxy.SOCKS5("tcp", *socksaddr, nil, proxy.Direct) + if err != nil { + return + } conn, err = dialer.Dial("tcp", saddr) if err != nil { return From 415748d38157691e44bac4af05511ea4814e34b8 Mon Sep 17 00:00:00 2001 From: Neil Alexander Date: Thu, 14 Jun 2018 15:22:13 +0100 Subject: [PATCH 11/22] Update generate.sh --- contrib/deb/generate.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/contrib/deb/generate.sh b/contrib/deb/generate.sh index 21840bc1..beee3d51 100644 --- a/contrib/deb/generate.sh +++ b/contrib/deb/generate.sh @@ -49,6 +49,7 @@ Section: contrib/net Priority: extra Architecture: $PKGARCH Replaces: $PKGREPLACES +Conflicts: $PKGREPLACES Maintainer: Neil Alexander Description: Debian yggdrasil package Binary yggdrasil package for Debian and Ubuntu From 7fe038f87e9a8f0a18d02810bf4fe33e48b50f38 Mon Sep 17 00:00:00 2001 From: Arceliar Date: Thu, 14 Jun 2018 12:32:18 -0500 Subject: [PATCH 12/22] prevent parent nodes from forcing coord oscillation, have dht.handleRes clean up the old request info immediately --- src/yggdrasil/debug.go | 6 ++++-- src/yggdrasil/dht.go | 7 +++++-- src/yggdrasil/switch.go | 13 +++++++++++-- 3 files changed, 20 insertions(+), 6 deletions(-) diff --git a/src/yggdrasil/debug.go b/src/yggdrasil/debug.go index 61b4c2f1..2cf90401 100644 --- a/src/yggdrasil/debug.go +++ b/src/yggdrasil/debug.go @@ -10,7 +10,7 @@ package yggdrasil import _ "golang.org/x/net/ipv6" // TODO put this somewhere better -import "golang.org/x/net/proxy" +//import "golang.org/x/net/proxy" import "fmt" import "net" @@ -353,6 +353,7 @@ func (c *Core) DEBUG_addPeer(addr string) { } } +/* func (c *Core) DEBUG_addSOCKSConn(socksaddr, peeraddr string) { go func() { dialer, err := proxy.SOCKS5("tcp", socksaddr, nil, proxy.Direct) @@ -370,6 +371,7 @@ func (c *Core) DEBUG_addSOCKSConn(socksaddr, peeraddr string) { } }() } +*/ //* func (c *Core) DEBUG_setupAndStartGlobalTCPInterface(addrport string) { @@ -384,7 +386,7 @@ func (c *Core) DEBUG_getGlobalTCPAddr() *net.TCPAddr { } func (c *Core) DEBUG_addTCPConn(saddr string) { - c.tcp.call(saddr) + c.tcp.call(saddr, nil) } //*/ diff --git a/src/yggdrasil/dht.go b/src/yggdrasil/dht.go index 4e53be31..955ef839 100644 --- a/src/yggdrasil/dht.go +++ b/src/yggdrasil/dht.go @@ -126,8 +126,10 @@ func (t *dht) handleReq(req *dhtReq) { key: req.Key, coords: req.Coords, } - t.insertIfNew(&info, false) // This seems DoSable (we just trust their coords...) - //if req.dest != t.nodeID { t.ping(&info, info.getNodeID()) } // Or spam... + // For bootstrapping to work, we need to add these nodes to the table + // Using insertIfNew, they can lie about coords, but searches will route around them + // Using the mill would mean trying to block off the mill becomes an attack vector + t.insertIfNew(&info, false) } // Reads a lookup response, checks that we had sent a matching request, and processes the response info. @@ -142,6 +144,7 @@ func (t *dht) handleRes(res *dhtRes) { if !isIn { return } + delete(reqs, res.Dest) now := time.Now() rinfo := dhtInfo{ key: res.Key, diff --git a/src/yggdrasil/switch.go b/src/yggdrasil/switch.go index 9c0e3f17..d3b28710 100644 --- a/src/yggdrasil/switch.go +++ b/src/yggdrasil/switch.go @@ -364,7 +364,7 @@ func (t *switchTable) unlockedHandleMsg(msg *switchMsg, fromPort switchPort) { doUpdate := false if !equiv(&sender.locator, &oldSender.locator) { doUpdate = true - //sender.firstSeen = now // TODO? uncomment to prevent flapping? + sender.firstSeen = now } t.data.peers[fromPort] = sender updateRoot := false @@ -402,7 +402,16 @@ func (t *switchTable) unlockedHandleMsg(msg *switchMsg, fromPort switchPort) { updateRoot = true case sender.port != t.parent: // do nothing case !equiv(&sender.locator, &t.data.locator): - updateRoot = true + // Special case + // If coords changed, then this may now be a worse parent than before + // Re-parent the node (de-parent and reprocess the message) + // Then reprocess *all* messages to look for a better parent + // This is so we don't keep using this node as our parent if there's something better + t.parent = 0 + t.unlockedHandleMsg(msg, fromPort) + for _, info := range t.data.peers { + t.unlockedHandleMsg(&info.msg, info.port) + } case now.Sub(t.time) < switch_throttle: // do nothing case sender.locator.tstamp > t.data.locator.tstamp: updateRoot = true From 8025e5129991c388f3fa6d61db16bbba7fda6980 Mon Sep 17 00:00:00 2001 From: Arceliar Date: Thu, 14 Jun 2018 13:26:46 -0500 Subject: [PATCH 13/22] address range changes --- README.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 122fd224..d3ec2216 100644 --- a/README.md +++ b/README.md @@ -85,7 +85,7 @@ journalctl -u yggdrasil - Tested and working on Windows 7 and Windows 10, and should work on any recent versions of Windows, but it depends on the [OpenVPN TAP driver](https://openvpn.net/index.php/open-source/downloads.html) being installed first. - Has been proven to work with both the [NDIS 5](https://swupdate.openvpn.org/community/releases/tap-windows-9.9.2_3.exe) (`tap-windows-9.9.2_3`) driver and the [NDIS 6](https://swupdate.openvpn.org/community/releases/tap-windows-9.21.2.exe) (`tap-windows-9.21.2`) driver, however there are substantial performance issues with the NDIS 6 driver therefore it is recommended to use the NDIS 5 driver instead. -- Be aware that connectivity issues can occur on Windows if multiple IPv6 addresses from the `fd00::/8` prefix are assigned to the TAP interface. If this happens, then you may need to manually remove the old/unused addresses from the interface (though the code has a workaround in place to do this automatically in some cases). +- Be aware that connectivity issues can occur on Windows if multiple IPv6 addresses from the `0200::/7` prefix are assigned to the TAP interface. If this happens, then you may need to manually remove the old/unused addresses from the interface (though the code has a workaround in place to do this automatically in some cases). - TUN mode is not supported on Windows. - Yggdrasil can be installed as a Windows service so that it runs automatically in the background. From an Administrator Command Prompt: ``` @@ -105,26 +105,26 @@ sc create yggdrasil binpath= "\"C:\path\to\yggdrasil.exe\" -autoconf" ## Optional: advertise a prefix locally -Suppose a node has generated the address: `fd00:1111:2222:3333:4444:5555:6666:7777` +Suppose a node has generated the address: `200:1111:2222:3333:4444:5555:6666:7777` -Then the node may also use addresses from the prefix: `fd80:1111:2222:3333::/64` (note the `fd00` changed to `fd80`, a separate `/9` is used for prefixes, but the rest of the first 64 bits are the same). +Then the node may also use addresses from the prefix: `300:1111:2222:3333::/64` (note the `0200` changed to `0300`, a separate `/8` is used for prefixes, but the rest of the first 64 bits are the same). -To advertise this prefix and a route to `fd00::/8`, the following seems to work on the developers' networks: +To advertise this prefix and a route to `0200::/7`, the following seems to work on the developers' networks: 1. Enable IPv6 forwarding (e.g. `sysctl -w net.ipv6.conf.all.forwarding=1` or add it to sysctl.conf). -2. `ip addr add fd80:1111:2222:3333::1/64 dev eth0` or similar, to assign an address for the router to use in that prefix, where the LAN is reachable through `eth0`. +2. `ip addr add 300:1111:2222:3333::1/64 dev eth0` or similar, to assign an address for the router to use in that prefix, where the LAN is reachable through `eth0`. 3. Install/run `radvd` with something like the following in `/etc/radvd.conf`: ``` interface eth0 { AdvSendAdvert on; - prefix fd80:1111:2222:3333::/64 { + prefix 300:1111:2222:3333::/64 { AdvOnLink on; AdvAutonomous on; }; - route fd00::/8 {}; + route 200::/7 {}; }; ``` From 0c74c748794142085c054b6ce1f0c1370390f7de Mon Sep 17 00:00:00 2001 From: Arceliar Date: Thu, 14 Jun 2018 13:33:36 -0500 Subject: [PATCH 14/22] Update README.md Consistently remove leading zeros from addresses in the readme. --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index d3ec2216..15731952 100644 --- a/README.md +++ b/README.md @@ -85,7 +85,7 @@ journalctl -u yggdrasil - Tested and working on Windows 7 and Windows 10, and should work on any recent versions of Windows, but it depends on the [OpenVPN TAP driver](https://openvpn.net/index.php/open-source/downloads.html) being installed first. - Has been proven to work with both the [NDIS 5](https://swupdate.openvpn.org/community/releases/tap-windows-9.9.2_3.exe) (`tap-windows-9.9.2_3`) driver and the [NDIS 6](https://swupdate.openvpn.org/community/releases/tap-windows-9.21.2.exe) (`tap-windows-9.21.2`) driver, however there are substantial performance issues with the NDIS 6 driver therefore it is recommended to use the NDIS 5 driver instead. -- Be aware that connectivity issues can occur on Windows if multiple IPv6 addresses from the `0200::/7` prefix are assigned to the TAP interface. If this happens, then you may need to manually remove the old/unused addresses from the interface (though the code has a workaround in place to do this automatically in some cases). +- Be aware that connectivity issues can occur on Windows if multiple IPv6 addresses from the `200::/7` prefix are assigned to the TAP interface. If this happens, then you may need to manually remove the old/unused addresses from the interface (though the code has a workaround in place to do this automatically in some cases). - TUN mode is not supported on Windows. - Yggdrasil can be installed as a Windows service so that it runs automatically in the background. From an Administrator Command Prompt: ``` @@ -107,9 +107,9 @@ sc create yggdrasil binpath= "\"C:\path\to\yggdrasil.exe\" -autoconf" Suppose a node has generated the address: `200:1111:2222:3333:4444:5555:6666:7777` -Then the node may also use addresses from the prefix: `300:1111:2222:3333::/64` (note the `0200` changed to `0300`, a separate `/8` is used for prefixes, but the rest of the first 64 bits are the same). +Then the node may also use addresses from the prefix: `300:1111:2222:3333::/64` (note the `200` changed to `300`, a separate `/8` is used for prefixes, but the rest of the first 64 bits are the same). -To advertise this prefix and a route to `0200::/7`, the following seems to work on the developers' networks: +To advertise this prefix and a route to `200::/7`, the following seems to work on the developers' networks: 1. Enable IPv6 forwarding (e.g. `sysctl -w net.ipv6.conf.all.forwarding=1` or add it to sysctl.conf). From 0aea4bd39535961ea195e1f479104c575a888fe9 Mon Sep 17 00:00:00 2001 From: Neil Alexander Date: Fri, 15 Jun 2018 09:20:41 +0100 Subject: [PATCH 15/22] Update yggdrasil.go --- yggdrasil.go | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/yggdrasil.go b/yggdrasil.go index 5dc5f14a..7e35732f 100644 --- a/yggdrasil.go +++ b/yggdrasil.go @@ -1,7 +1,8 @@ package main -import "encoding/json" +import "bytes" import "encoding/hex" +import "encoding/json" import "flag" import "fmt" import "io/ioutil" @@ -13,6 +14,8 @@ import "regexp" import "math/rand" import "log" +import "golang.org/x/text/encoding/unicode" + import "yggdrasil" import "yggdrasil/config" @@ -107,6 +110,19 @@ func main() { if err != nil { panic(err) } + // If there's a byte order mark - which Windows 10 is now incredibly fond of + // throwing everywhere when it's converting things into UTF-16 for the hell + // of it - remove it and decode back down into UTF-8. This is necessary + // because hjson doesn't know what to do with UTF-16 and will panic + if bytes.Compare(config[0:2], []byte{0xFF, 0xFE}) == 0 || + bytes.Compare(config[0:2], []byte{0xFF, 0xFF}) == 0 { + utf := unicode.UTF16(unicode.BigEndian, unicode.UseBOM) + decoder := utf.NewDecoder() + config, err = decoder.Bytes(config) + if err != nil { + panic(err) + } + } // Generate a new configuration - this gives us a set of sane defaults - // then parse the configuration we loaded above on top of it. The effect // of this is that any configuration item that is missing from the provided From 20fc551a6790ca695e9784c5a10d4051f5c59878 Mon Sep 17 00:00:00 2001 From: Neil Alexander Date: Fri, 15 Jun 2018 09:54:29 +0100 Subject: [PATCH 16/22] Collect yggdrasilctl during CI build --- .circleci/config.yml | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 5773c6b1..dc52b208 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -21,42 +21,42 @@ jobs: - run: name: Build for Linux (including Debian packages) command: | - PKGARCH=amd64 sh contrib/deb/generate.sh && mv yggdrasil /tmp/upload/$CINAME-$CIVERSION-linux-amd64; - PKGARCH=i386 sh contrib/deb/generate.sh && mv yggdrasil /tmp/upload/$CINAME-$CIVERSION-linux-i386; - PKGARCH=mipsel sh contrib/deb/generate.sh && mv yggdrasil /tmp/upload/$CINAME-$CIVERSION-linux-mipsel; - PKGARCH=mips sh contrib/deb/generate.sh && mv yggdrasil /tmp/upload/$CINAME-$CIVERSION-linux-mips; - PKGARCH=armhf sh contrib/deb/generate.sh && mv yggdrasil /tmp/upload/$CINAME-$CIVERSION-linux-armhf; + PKGARCH=amd64 sh contrib/deb/generate.sh && mv yggdrasil /tmp/upload/$CINAME-$CIVERSION-linux-amd64 && mv yggdrasilctl /tmp/upload $CINAME-$CIVERSION-yggdrasilctl-linux-amd64; + PKGARCH=i386 sh contrib/deb/generate.sh && mv yggdrasil /tmp/upload/$CINAME-$CIVERSION-linux-i386 && mv yggdrasilctl /tmp/upload $CINAME-$CIVERSION-yggdrasilctl-linux-i386; + PKGARCH=mipsel sh contrib/deb/generate.sh && mv yggdrasil /tmp/upload/$CINAME-$CIVERSION-linux-mipsel && mv yggdrasilctl /tmp/upload $CINAME-$CIVERSION-yggdrasilctl-linux-mipsel; + PKGARCH=mips sh contrib/deb/generate.sh && mv yggdrasil /tmp/upload/$CINAME-$CIVERSION-linux-mips && mv yggdrasilctl /tmp/upload $CINAME-$CIVERSION-yggdrasilctl-linux-mips; + PKGARCH=armhf sh contrib/deb/generate.sh && mv yggdrasil /tmp/upload/$CINAME-$CIVERSION-linux-armh && mv yggdrasilctl /tmp/upload $CINAME-$CIVERSION-yggdrasilctl-linux-armhf; mv *.deb /tmp/upload/ - run: name: Build for macOS command: | - GOOS=darwin GOARCH=amd64 ./build && mv yggdrasil /tmp/upload/$CINAME-$CIVERSION-darwin-amd64; - GOOS=darwin GOARCH=386 ./build && mv yggdrasil /tmp/upload/$CINAME-$CIVERSION-darwin-i386; + GOOS=darwin GOARCH=amd64 ./build && mv yggdrasil /tmp/upload/$CINAME-$CIVERSION-darwin-amd64 && mv yggdrasilctl /tmp/upload $CINAME-$CIVERSION-yggdrasilctl-darwin-amd64; + GOOS=darwin GOARCH=386 ./build && mv yggdrasil /tmp/upload/$CINAME-$CIVERSION-darwin-i386 && mv yggdrasilctl /tmp/upload $CINAME-$CIVERSION-yggdrasilctl-darwin-i386; - run: name: Build for OpenBSD command: | - GOOS=openbsd GOARCH=amd64 ./build && mv yggdrasil /tmp/upload/$CINAME-$CIVERSION-openbsd-amd64; - GOOS=openbsd GOARCH=386 ./build && mv yggdrasil /tmp/upload/$CINAME-$CIVERSION-openbsd-i386; + GOOS=openbsd GOARCH=amd64 ./build && mv yggdrasil /tmp/upload/$CINAME-$CIVERSION-openbsd-amd64 && mv yggdrasilctl /tmp/upload $CINAME-$CIVERSION-yggdrasilctl-openbsd-amd64; + GOOS=openbsd GOARCH=386 ./build && mv yggdrasil /tmp/upload/$CINAME-$CIVERSION-openbsd-i386 && mv yggdrasilctl /tmp/upload $CINAME-$CIVERSION-yggdrasilctl-openbsd-i386; - run: name: Build for FreeBSD command: | - GOOS=freebsd GOARCH=amd64 ./build && mv yggdrasil /tmp/upload/$CINAME-$CIVERSION-freebsd-amd64; - GOOS=freebsd GOARCH=386 ./build && mv yggdrasil /tmp/upload/$CINAME-$CIVERSION-freebsd-i386; + GOOS=freebsd GOARCH=amd64 ./build && mv yggdrasil /tmp/upload/$CINAME-$CIVERSION-freebsd-amd64 && mv yggdrasilctl /tmp/upload $CINAME-$CIVERSION-yggdrasilctl-freebsd-amd64; + GOOS=freebsd GOARCH=386 ./build && mv yggdrasil /tmp/upload/$CINAME-$CIVERSION-freebsd-i386 && mv yggdrasilctl /tmp/upload $CINAME-$CIVERSION-yggdrasilctl-freebsd-i386; - run: name: Build for NetBSD command: | - GOOS=netbsd GOARCH=amd64 ./build && mv yggdrasil /tmp/upload/$CINAME-$CIVERSION-netbsd-amd64; - GOOS=netbsd GOARCH=386 ./build && mv yggdrasil /tmp/upload/$CINAME-$CIVERSION-netbsd-i386; + GOOS=netbsd GOARCH=amd64 ./build && mv yggdrasil /tmp/upload/$CINAME-$CIVERSION-netbsd-amd64 && mv yggdrasilctl /tmp/upload $CINAME-$CIVERSION-yggdrasilctl-netbsd-amd64; + GOOS=netbsd GOARCH=386 ./build && mv yggdrasil /tmp/upload/$CINAME-$CIVERSION-netbsd-i386 && mv yggdrasilctl /tmp/upload $CINAME-$CIVERSION-yggdrasilctl-netbsd-i386; - run: name: Build for Windows command: | - GOOS=windows GOARCH=amd64 ./build && mv yggdrasil.exe /tmp/upload/$CINAME-$CIVERSION-windows-amd64.exe; - GOOS=windows GOARCH=386 ./build && mv yggdrasil.exe /tmp/upload/$CINAME-$CIVERSION-windows-i386.exe; + GOOS=windows GOARCH=amd64 ./build && mv yggdrasil.exe /tmp/upload/$CINAME-$CIVERSION-windows-amd64.exe && mv yggdrasilctl /tmp/upload $CINAME-$CIVERSION-yggdrasilctl-windows-amd64.exe; + GOOS=windows GOARCH=386 ./build && mv yggdrasil.exe /tmp/upload/$CINAME-$CIVERSION-windows-i386.exe && mv yggdrasilctl /tmp/upload $CINAME-$CIVERSION-yggdrasilctl-windows-i386.exe; - run: name: Build for EdgeRouter From 3be8d97cc35eac0e850a9e627d89c04338d2680b Mon Sep 17 00:00:00 2001 From: Neil Alexander Date: Fri, 15 Jun 2018 09:58:02 +0100 Subject: [PATCH 17/22] Fix CircleCI after fat-fingered copypasta --- .circleci/config.yml | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index dc52b208..51b549e4 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -21,42 +21,42 @@ jobs: - run: name: Build for Linux (including Debian packages) command: | - PKGARCH=amd64 sh contrib/deb/generate.sh && mv yggdrasil /tmp/upload/$CINAME-$CIVERSION-linux-amd64 && mv yggdrasilctl /tmp/upload $CINAME-$CIVERSION-yggdrasilctl-linux-amd64; - PKGARCH=i386 sh contrib/deb/generate.sh && mv yggdrasil /tmp/upload/$CINAME-$CIVERSION-linux-i386 && mv yggdrasilctl /tmp/upload $CINAME-$CIVERSION-yggdrasilctl-linux-i386; - PKGARCH=mipsel sh contrib/deb/generate.sh && mv yggdrasil /tmp/upload/$CINAME-$CIVERSION-linux-mipsel && mv yggdrasilctl /tmp/upload $CINAME-$CIVERSION-yggdrasilctl-linux-mipsel; - PKGARCH=mips sh contrib/deb/generate.sh && mv yggdrasil /tmp/upload/$CINAME-$CIVERSION-linux-mips && mv yggdrasilctl /tmp/upload $CINAME-$CIVERSION-yggdrasilctl-linux-mips; - PKGARCH=armhf sh contrib/deb/generate.sh && mv yggdrasil /tmp/upload/$CINAME-$CIVERSION-linux-armh && mv yggdrasilctl /tmp/upload $CINAME-$CIVERSION-yggdrasilctl-linux-armhf; + PKGARCH=amd64 sh contrib/deb/generate.sh && mv yggdrasil /tmp/upload/$CINAME-$CIVERSION-linux-amd64 && mv yggdrasilctl /tmp/upload/$CINAME-$CIVERSION-yggdrasilctl-linux-amd64; + PKGARCH=i386 sh contrib/deb/generate.sh && mv yggdrasil /tmp/upload/$CINAME-$CIVERSION-linux-i386 && mv yggdrasilctl /tmp/upload/$CINAME-$CIVERSION-yggdrasilctl-linux-i386; + PKGARCH=mipsel sh contrib/deb/generate.sh && mv yggdrasil /tmp/upload/$CINAME-$CIVERSION-linux-mipsel && mv yggdrasilctl /tmp/upload/$CINAME-$CIVERSION-yggdrasilctl-linux-mipsel; + PKGARCH=mips sh contrib/deb/generate.sh && mv yggdrasil /tmp/upload/$CINAME-$CIVERSION-linux-mips && mv yggdrasilctl /tmp/upload/$CINAME-$CIVERSION-yggdrasilctl-linux-mips; + PKGARCH=armhf sh contrib/deb/generate.sh && mv yggdrasil /tmp/upload/$CINAME-$CIVERSION-linux-armh && mv yggdrasilctl /tmp/upload/$CINAME-$CIVERSION-yggdrasilctl-linux-armhf; mv *.deb /tmp/upload/ - run: name: Build for macOS command: | - GOOS=darwin GOARCH=amd64 ./build && mv yggdrasil /tmp/upload/$CINAME-$CIVERSION-darwin-amd64 && mv yggdrasilctl /tmp/upload $CINAME-$CIVERSION-yggdrasilctl-darwin-amd64; - GOOS=darwin GOARCH=386 ./build && mv yggdrasil /tmp/upload/$CINAME-$CIVERSION-darwin-i386 && mv yggdrasilctl /tmp/upload $CINAME-$CIVERSION-yggdrasilctl-darwin-i386; + GOOS=darwin GOARCH=amd64 ./build && mv yggdrasil /tmp/upload/$CINAME-$CIVERSION-darwin-amd64 && mv yggdrasilctl /tmp/upload/$CINAME-$CIVERSION-yggdrasilctl-darwin-amd64; + GOOS=darwin GOARCH=386 ./build && mv yggdrasil /tmp/upload/$CINAME-$CIVERSION-darwin-i386 && mv yggdrasilctl /tmp/upload/$CINAME-$CIVERSION-yggdrasilctl-darwin-i386; - run: name: Build for OpenBSD command: | - GOOS=openbsd GOARCH=amd64 ./build && mv yggdrasil /tmp/upload/$CINAME-$CIVERSION-openbsd-amd64 && mv yggdrasilctl /tmp/upload $CINAME-$CIVERSION-yggdrasilctl-openbsd-amd64; - GOOS=openbsd GOARCH=386 ./build && mv yggdrasil /tmp/upload/$CINAME-$CIVERSION-openbsd-i386 && mv yggdrasilctl /tmp/upload $CINAME-$CIVERSION-yggdrasilctl-openbsd-i386; + GOOS=openbsd GOARCH=amd64 ./build && mv yggdrasil /tmp/upload/$CINAME-$CIVERSION-openbsd-amd64 && mv yggdrasilctl /tmp/upload/$CINAME-$CIVERSION-yggdrasilctl-openbsd-amd64; + GOOS=openbsd GOARCH=386 ./build && mv yggdrasil /tmp/upload/$CINAME-$CIVERSION-openbsd-i386 && mv yggdrasilctl /tmp/upload/$CINAME-$CIVERSION-yggdrasilctl-openbsd-i386; - run: name: Build for FreeBSD command: | - GOOS=freebsd GOARCH=amd64 ./build && mv yggdrasil /tmp/upload/$CINAME-$CIVERSION-freebsd-amd64 && mv yggdrasilctl /tmp/upload $CINAME-$CIVERSION-yggdrasilctl-freebsd-amd64; - GOOS=freebsd GOARCH=386 ./build && mv yggdrasil /tmp/upload/$CINAME-$CIVERSION-freebsd-i386 && mv yggdrasilctl /tmp/upload $CINAME-$CIVERSION-yggdrasilctl-freebsd-i386; + GOOS=freebsd GOARCH=amd64 ./build && mv yggdrasil /tmp/upload/$CINAME-$CIVERSION-freebsd-amd64 && mv yggdrasilctl /tmp/upload/$CINAME-$CIVERSION-yggdrasilctl-freebsd-amd64; + GOOS=freebsd GOARCH=386 ./build && mv yggdrasil /tmp/upload/$CINAME-$CIVERSION-freebsd-i386 && mv yggdrasilctl /tmp/upload/$CINAME-$CIVERSION-yggdrasilctl-freebsd-i386; - run: name: Build for NetBSD command: | - GOOS=netbsd GOARCH=amd64 ./build && mv yggdrasil /tmp/upload/$CINAME-$CIVERSION-netbsd-amd64 && mv yggdrasilctl /tmp/upload $CINAME-$CIVERSION-yggdrasilctl-netbsd-amd64; - GOOS=netbsd GOARCH=386 ./build && mv yggdrasil /tmp/upload/$CINAME-$CIVERSION-netbsd-i386 && mv yggdrasilctl /tmp/upload $CINAME-$CIVERSION-yggdrasilctl-netbsd-i386; + GOOS=netbsd GOARCH=amd64 ./build && mv yggdrasil /tmp/upload/$CINAME-$CIVERSION-netbsd-amd64 && mv yggdrasilctl /tmp/upload/$CINAME-$CIVERSION-yggdrasilctl-netbsd-amd64; + GOOS=netbsd GOARCH=386 ./build && mv yggdrasil /tmp/upload/$CINAME-$CIVERSION-netbsd-i386 && mv yggdrasilctl /tmp/upload/$CINAME-$CIVERSION-yggdrasilctl-netbsd-i386; - run: name: Build for Windows command: | - GOOS=windows GOARCH=amd64 ./build && mv yggdrasil.exe /tmp/upload/$CINAME-$CIVERSION-windows-amd64.exe && mv yggdrasilctl /tmp/upload $CINAME-$CIVERSION-yggdrasilctl-windows-amd64.exe; - GOOS=windows GOARCH=386 ./build && mv yggdrasil.exe /tmp/upload/$CINAME-$CIVERSION-windows-i386.exe && mv yggdrasilctl /tmp/upload $CINAME-$CIVERSION-yggdrasilctl-windows-i386.exe; + GOOS=windows GOARCH=amd64 ./build && mv yggdrasil.exe /tmp/upload/$CINAME-$CIVERSION-windows-amd64.exe && mv yggdrasilctl /tmp/upload/$CINAME-$CIVERSION-yggdrasilctl-windows-amd64.exe; + GOOS=windows GOARCH=386 ./build && mv yggdrasil.exe /tmp/upload/$CINAME-$CIVERSION-windows-i386.exe && mv yggdrasilctl /tmp/upload/$CINAME-$CIVERSION-yggdrasilctl-windows-i386.exe; - run: name: Build for EdgeRouter From 17146ee5bb1094407fee365e9e712632efe1cd66 Mon Sep 17 00:00:00 2001 From: Neil Alexander Date: Fri, 15 Jun 2018 10:00:58 +0100 Subject: [PATCH 18/22] Fix for Windows --- .circleci/config.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 51b549e4..1f774364 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -55,8 +55,8 @@ jobs: - run: name: Build for Windows command: | - GOOS=windows GOARCH=amd64 ./build && mv yggdrasil.exe /tmp/upload/$CINAME-$CIVERSION-windows-amd64.exe && mv yggdrasilctl /tmp/upload/$CINAME-$CIVERSION-yggdrasilctl-windows-amd64.exe; - GOOS=windows GOARCH=386 ./build && mv yggdrasil.exe /tmp/upload/$CINAME-$CIVERSION-windows-i386.exe && mv yggdrasilctl /tmp/upload/$CINAME-$CIVERSION-yggdrasilctl-windows-i386.exe; + GOOS=windows GOARCH=amd64 ./build && mv yggdrasil.exe /tmp/upload/$CINAME-$CIVERSION-windows-amd64.exe && mv yggdrasilctl.exe /tmp/upload/$CINAME-$CIVERSION-yggdrasilctl-windows-amd64.exe; + GOOS=windows GOARCH=386 ./build && mv yggdrasil.exe /tmp/upload/$CINAME-$CIVERSION-windows-i386.exe && mv yggdrasilctl.exe /tmp/upload/$CINAME-$CIVERSION-yggdrasilctl-windows-i386.exe; - run: name: Build for EdgeRouter From e65a66b181549f8cac05005d0c1e61765068b78d Mon Sep 17 00:00:00 2001 From: Arceliar Date: Fri, 15 Jun 2018 04:30:09 -0500 Subject: [PATCH 19/22] clean up main yggdrasil.go imports and run gofmt --- yggdrasil.go | 42 ++++++++++++++++++++++-------------------- 1 file changed, 22 insertions(+), 20 deletions(-) diff --git a/yggdrasil.go b/yggdrasil.go index 7e35732f..233ad9bd 100644 --- a/yggdrasil.go +++ b/yggdrasil.go @@ -1,27 +1,29 @@ package main -import "bytes" -import "encoding/hex" -import "encoding/json" -import "flag" -import "fmt" -import "io/ioutil" -import "os" -import "os/signal" -import "syscall" -import "time" -import "regexp" -import "math/rand" -import "log" +import ( + "bytes" + "encoding/hex" + "encoding/json" + "flag" + "fmt" + "io/ioutil" + "log" + "math/rand" + "os" + "os/signal" + "regexp" + "syscall" + "time" -import "golang.org/x/text/encoding/unicode" + "golang.org/x/text/encoding/unicode" -import "yggdrasil" -import "yggdrasil/config" + "github.com/kardianos/minwinsvc" + "github.com/mitchellh/mapstructure" + "github.com/neilalexander/hjson-go" -import "github.com/kardianos/minwinsvc" -import "github.com/neilalexander/hjson-go" -import "github.com/mitchellh/mapstructure" + "yggdrasil" + "yggdrasil/config" +) type nodeConfig = config.NodeConfig type Core = yggdrasil.Core @@ -115,7 +117,7 @@ func main() { // of it - remove it and decode back down into UTF-8. This is necessary // because hjson doesn't know what to do with UTF-16 and will panic if bytes.Compare(config[0:2], []byte{0xFF, 0xFE}) == 0 || - bytes.Compare(config[0:2], []byte{0xFF, 0xFF}) == 0 { + bytes.Compare(config[0:2], []byte{0xFF, 0xFF}) == 0 { utf := unicode.UTF16(unicode.BigEndian, unicode.UseBOM) decoder := utf.NewDecoder() config, err = decoder.Bytes(config) From 9ac7d4e0dfcb1f3e88e6a5744a35f8482c92c425 Mon Sep 17 00:00:00 2001 From: Neil Alexander Date: Sat, 16 Jun 2018 17:01:47 +0100 Subject: [PATCH 20/22] Fix typo for big-endian BOM --- yggdrasil.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yggdrasil.go b/yggdrasil.go index 233ad9bd..d29c65b7 100644 --- a/yggdrasil.go +++ b/yggdrasil.go @@ -117,7 +117,7 @@ func main() { // of it - remove it and decode back down into UTF-8. This is necessary // because hjson doesn't know what to do with UTF-16 and will panic if bytes.Compare(config[0:2], []byte{0xFF, 0xFE}) == 0 || - bytes.Compare(config[0:2], []byte{0xFF, 0xFF}) == 0 { + bytes.Compare(config[0:2], []byte{0xFE, 0xFF}) == 0 { utf := unicode.UTF16(unicode.BigEndian, unicode.UseBOM) decoder := utf.NewDecoder() config, err = decoder.Bytes(config) From 496dc94f02a58a210e38cf6b3c97a148719606a4 Mon Sep 17 00:00:00 2001 From: Arceliar Date: Sat, 16 Jun 2018 15:31:25 -0500 Subject: [PATCH 21/22] possibly mitigate livelock bug where lossy links lead to constant connect/disconnect cycles due to disagreement about which of the two duplicate autoconnection attempts to use --- src/yggdrasil/tcp.go | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/yggdrasil/tcp.go b/src/yggdrasil/tcp.go index 48695419..5408b6bf 100644 --- a/src/yggdrasil/tcp.go +++ b/src/yggdrasil/tcp.go @@ -26,6 +26,7 @@ import ( ) const tcp_msgSize = 2048 + 65535 // TODO figure out what makes sense +const tcp_timeout = 6 * time.Second // Wrapper function for non tcp/ip connections. func setNoDelay(c net.Conn, delay bool) { @@ -109,6 +110,8 @@ func (iface *tcpInterface) call(saddr string, socksaddr *string) { } else { iface.calls[saddr] = struct{}{} defer func() { + // Block new calls for a little while, to mitigate livelock scenarios + time.Sleep(tcp_timeout) iface.mutex.Lock() delete(iface.calls, saddr) iface.mutex.Unlock() @@ -162,7 +165,7 @@ func (iface *tcpInterface) handler(sock net.Conn, incoming bool) { if err != nil { return } - timeout := time.Now().Add(6 * time.Second) + timeout := time.Now().Add(tcp_timeout) sock.SetReadDeadline(timeout) _, err = sock.Read(metaBytes) if err != nil { @@ -257,7 +260,7 @@ func (iface *tcpInterface) handler(sock net.Conn, incoming bool) { atomic.AddUint64(&p.bytesSent, uint64(len(tcp_msg)+len(msgLen)+len(msg))) util_putBytes(msg) } - timerInterval := 4 * time.Second + timerInterval := tcp_timeout * 2 / 3 timer := time.NewTimer(timerInterval) defer timer.Stop() for { @@ -334,7 +337,7 @@ func (iface *tcpInterface) reader(sock net.Conn, in func([]byte)) { bs := make([]byte, 2*tcp_msgSize) frag := bs[:0] for { - timeout := time.Now().Add(6 * time.Second) + timeout := time.Now().Add(tcp_timeout) sock.SetReadDeadline(timeout) n, err := sock.Read(bs[len(frag):]) if err != nil || n == 0 { From 10a66a4edcedb9e126e1d95f19170564b1ed1c6d Mon Sep 17 00:00:00 2001 From: Neil Alexander Date: Sun, 17 Jun 2018 18:17:21 +0100 Subject: [PATCH 22/22] Update semver to hopefully avoid squash merges --- contrib/semver/version.sh | 32 ++++++++++++++++++++++++++------ 1 file changed, 26 insertions(+), 6 deletions(-) diff --git a/contrib/semver/version.sh b/contrib/semver/version.sh index 1839a67b..bd009a9a 100644 --- a/contrib/semver/version.sh +++ b/contrib/semver/version.sh @@ -1,26 +1,46 @@ #!/bin/sh +# Merge commits from this branch are counted +DEVELOPBRANCH="yggdrasil-network/develop" + # Get the last tag TAG=$(git describe --abbrev=0 --tags --match="v[0-9]*\.[0-9]*" 2>/dev/null) -# Get the number of commits from the last tag -COUNT=$(git rev-list $TAG..HEAD --count 2>/dev/null) +# Get last merge to master +MERGE=$(git rev-list $TAG..master --grep "from $DEVELOPBRANCH" 2>/dev/null | head -n 1) + +# Get the number of merges since the last merge to master +PATCH=$(git rev-list $TAG..master --count --merges --grep="from $DEVELOPBRANCH" 2>/dev/null) # If it fails then there's no last tag - go from the first commit if [ $? != 0 ]; then - COUNT=$(git rev-list HEAD --count 2>/dev/null) + PATCH=$(git rev-list HEAD --count 2>/dev/null) - printf 'v0.0.%d' "$COUNT" + printf 'v0.0.%d' "$PATCH" exit -1 fi +# Get the number of merges on the current branch since the last tag +BUILD=$(git rev-list $TAG..HEAD --count --merges) + # Split out into major, minor and patch numbers MAJOR=$(echo $TAG | cut -c 2- | cut -d "." -f 1) MINOR=$(echo $TAG | cut -c 2- | cut -d "." -f 2) +# Get the current checked out branch +BRANCH=$(git rev-parse --abbrev-ref HEAD) + # Output in the desired format -if [ $COUNT = 0 ]; then +if [ $PATCH = 0 ]; then printf 'v%d.%d' "$MAJOR" "$MINOR" else - printf 'v%d.%d.%d' "$MAJOR" "$MINOR" "$COUNT" + printf 'v%d.%d.%d' "$MAJOR" "$MINOR" "$PATCH" fi + +# Add the build tag on non-master branches +if [ $BRANCH != "master" ]; then + if [ $BUILD != 0 ]; then + printf -- "-%04d" "$BUILD" + fi +fi +