Compare commits

...

5 Commits

Author SHA1 Message Date
David Crawshaw
cd3fd076cc VERSION.txt: this is v1.10.1
Signed-off-by: David Crawshaw <crawshaw@tailscale.com>
2021-07-02 14:47:07 -07:00
Josh Bleecher Snyder
abdc0aec75 internal/deephash: 8 bits of output is not enough
Running hex.Encode(b, b) is a bad idea.
The first byte of input will overwrite the first two bytes of output.
Subsequent bytes have no impact on the output.

Not related to today's IPv6 bug, but...wh::ps.

This caused us to spuriously ignore some wireguard config updates.

Signed-off-by: Josh Bleecher Snyder <josh@tailscale.com>
(cherry picked from commit 7f095617f2)
2021-07-02 13:55:02 -07:00
Brad Fitzpatrick
39015a43da wgengine/netstack: make SOCKS5 resolve names to IPv6 if self node when no IPv4
For instance, ephemeral nodes with only IPv6 addresses can now
SOCKS5-dial out to names like "foo" and resolve foo's IPv6 address
rather than foo's IPv4 address and get a "no route"
(*tcpip.ErrNoRoute) error from netstack's dialer.

Per https://github.com/tailscale/tailscale/issues/2268#issuecomment-870027626
which is only part of the isuse.

Updates #2268

Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
(cherry picked from commit 722859b476)
2021-07-02 13:51:10 -07:00
Josh Bleecher Snyder
506476059a ipn/ipnlocal: fix data race
We can't access b.netMap without holding b.mu.
We already grabbed it earlier in the function with the lock held.

Introduced in Nov 2020 in 7ea809897d.
Discovered during stress testing.
Apparently it's a pretty rare?

Signed-off-by: Josh Bleecher Snyder <josh@tailscale.com>
(cherry picked from commit f11a8928a6)
2021-07-01 12:40:16 -07:00
David Anderson
405ea978f8 VERSION.txt: this is 1.10.0
Signed-off-by: David Anderson <danderson@tailscale.com>
2021-06-24 15:32:15 -07:00
6 changed files with 146 additions and 7 deletions

View File

@@ -1 +1 @@
1.9.0
1.10.1

View File

@@ -24,8 +24,12 @@ func calcHash(v interface{}) string {
printTo(b, v, scratch)
b.Flush()
scratch = h.Sum(scratch[:0])
hex.Encode(scratch[:cap(scratch)], scratch[:sha256.Size])
return string(scratch[:sha256.Size*2])
// The first sha256.Size bytes contain the hash.
// Hex-encode that into the next sha256.Size*2 bytes.
src := scratch[:sha256.Size]
dst := scratch[sha256.Size:cap(scratch)]
n := hex.Encode(dst, src)
return string(dst[:n])
}
// UpdateHash sets last to the hash of v and reports whether its value changed.

View File

@@ -134,3 +134,14 @@ func BenchmarkHashMapAcyclic(b *testing.B) {
}
}
}
func TestExhaustive(t *testing.T) {
seen := make(map[string]bool)
for i := 0; i < 100000; i++ {
s := calcHash(i)
if seen[s] {
t.Fatalf("hash collision %v", i)
}
seen[s] = true
}
}

View File

@@ -2213,7 +2213,7 @@ func (b *LocalBackend) enterState(newState ipn.State) {
b.e.RequestStatus()
case ipn.Running:
var addrs []string
for _, addr := range b.netMap.Addresses {
for _, addr := range netMap.Addresses {
addrs = append(addrs, addr.IP().String())
}
systemd.Status("Connected; %s; %s", activeLogin, strings.Join(addrs, " "))

View File

@@ -177,21 +177,33 @@ type DNSMap map[string]netaddr.IP
func DNSMapFromNetworkMap(nm *netmap.NetworkMap) DNSMap {
ret := make(DNSMap)
suffix := nm.MagicDNSSuffix()
have4 := false
if nm.Name != "" && len(nm.Addresses) > 0 {
ip := nm.Addresses[0].IP()
ret[strings.TrimRight(nm.Name, ".")] = ip
if dnsname.HasSuffix(nm.Name, suffix) {
ret[dnsname.TrimSuffix(nm.Name, suffix)] = ip
}
for _, a := range nm.Addresses {
if a.IP().Is4() {
have4 = true
}
}
}
for _, p := range nm.Peers {
if p.Name != "" && len(p.Addresses) > 0 {
ip := p.Addresses[0].IP()
if p.Name == "" {
continue
}
for _, a := range p.Addresses {
ip := a.IP()
if ip.Is4() && !have4 {
continue
}
ret[strings.TrimRight(p.Name, ".")] = ip
if dnsname.HasSuffix(p.Name, suffix) {
ret[dnsname.TrimSuffix(p.Name, suffix)] = ip
}
break
}
}
return ret

View File

@@ -0,0 +1,112 @@
// Copyright (c) 2021 Tailscale Inc & AUTHORS All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package netstack
import (
"reflect"
"testing"
"inet.af/netaddr"
"tailscale.com/tailcfg"
"tailscale.com/types/netmap"
)
func TestDNSMapFromNetworkMap(t *testing.T) {
pfx := netaddr.MustParseIPPrefix
ip := netaddr.MustParseIP
tests := []struct {
name string
nm *netmap.NetworkMap
want DNSMap
}{
{
name: "self",
nm: &netmap.NetworkMap{
Name: "foo.tailnet",
Addresses: []netaddr.IPPrefix{
pfx("100.102.103.104/32"),
pfx("100::123/128"),
},
},
want: DNSMap{
"foo": ip("100.102.103.104"),
"foo.tailnet": ip("100.102.103.104"),
},
},
{
name: "self_and_peers",
nm: &netmap.NetworkMap{
Name: "foo.tailnet",
Addresses: []netaddr.IPPrefix{
pfx("100.102.103.104/32"),
pfx("100::123/128"),
},
Peers: []*tailcfg.Node{
{
Name: "a.tailnet",
Addresses: []netaddr.IPPrefix{
pfx("100.0.0.201/32"),
pfx("100::201/128"),
},
},
{
Name: "b.tailnet",
Addresses: []netaddr.IPPrefix{
pfx("100::202/128"),
},
},
},
},
want: DNSMap{
"foo": ip("100.102.103.104"),
"foo.tailnet": ip("100.102.103.104"),
"a": ip("100.0.0.201"),
"a.tailnet": ip("100.0.0.201"),
"b": ip("100::202"),
"b.tailnet": ip("100::202"),
},
},
{
name: "self_has_v6_only",
nm: &netmap.NetworkMap{
Name: "foo.tailnet",
Addresses: []netaddr.IPPrefix{
pfx("100::123/128"),
},
Peers: []*tailcfg.Node{
{
Name: "a.tailnet",
Addresses: []netaddr.IPPrefix{
pfx("100.0.0.201/32"),
pfx("100::201/128"),
},
},
{
Name: "b.tailnet",
Addresses: []netaddr.IPPrefix{
pfx("100::202/128"),
},
},
},
},
want: DNSMap{
"foo": ip("100::123"),
"foo.tailnet": ip("100::123"),
"a": ip("100::201"),
"a.tailnet": ip("100::201"),
"b": ip("100::202"),
"b.tailnet": ip("100::202"),
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := DNSMapFromNetworkMap(tt.nm)
if !reflect.DeepEqual(got, tt.want) {
t.Errorf("mismatch:\n got %v\nwant %v\n", got, tt.want)
}
})
}
}