mirror of
https://github.com/tailscale/tailscale.git
synced 2024-11-29 04:55:31 +00:00
net/netcheck: test for OS IPv6 support as well as connectivity.
This lets us distinguish "no IPv6 because the device's ISP doesn't offer IPv6" from "IPv6 is unavailable/disabled in the OS". Signed-off-by: David Anderson <danderson@tailscale.com>
This commit is contained in:
parent
4c0feba38e
commit
c1cb3efbba
@ -126,8 +126,10 @@ func printReport(dm *tailcfg.DERPMap, report *netcheck.Report) error {
|
|||||||
printf("\t* IPv6: yes, %v\n", report.GlobalV6)
|
printf("\t* IPv6: yes, %v\n", report.GlobalV6)
|
||||||
} else if report.IPv6 {
|
} else if report.IPv6 {
|
||||||
printf("\t* IPv6: (no addr found)\n")
|
printf("\t* IPv6: (no addr found)\n")
|
||||||
|
} else if report.OSHasIPv6 {
|
||||||
|
printf("\t* IPv6: no, but OS has support\n")
|
||||||
} else {
|
} else {
|
||||||
printf("\t* IPv6: no\n")
|
printf("\t* IPv6: no, unavailable in OS\n")
|
||||||
}
|
}
|
||||||
printf("\t* MappingVariesByDestIP: %v\n", report.MappingVariesByDestIP)
|
printf("\t* MappingVariesByDestIP: %v\n", report.MappingVariesByDestIP)
|
||||||
printf("\t* HairPinning: %v\n", report.HairPinning)
|
printf("\t* HairPinning: %v\n", report.HairPinning)
|
||||||
|
@ -76,6 +76,7 @@ type Report struct {
|
|||||||
IPv4 bool // an IPv4 STUN round trip completed
|
IPv4 bool // an IPv4 STUN round trip completed
|
||||||
IPv6CanSend bool // an IPv6 packet was able to be sent
|
IPv6CanSend bool // an IPv6 packet was able to be sent
|
||||||
IPv4CanSend bool // an IPv4 packet was able to be sent
|
IPv4CanSend bool // an IPv4 packet was able to be sent
|
||||||
|
OSHasIPv6 bool // could bind a socket to ::1
|
||||||
|
|
||||||
// MappingVariesByDestIP is whether STUN results depend which
|
// MappingVariesByDestIP is whether STUN results depend which
|
||||||
// STUN server you're talking to (on IPv4).
|
// STUN server you're talking to (on IPv4).
|
||||||
@ -806,6 +807,14 @@ func (c *Client) GetReport(ctx context.Context, dm *tailcfg.DERPMap) (_ *Report,
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// See if IPv6 works at all, or if it's been hard disabled at the
|
||||||
|
// OS level.
|
||||||
|
v6udp, err := netns.Listener(c.logf).ListenPacket(ctx, "udp6", "[::1]:0")
|
||||||
|
if err == nil {
|
||||||
|
rs.report.OSHasIPv6 = true
|
||||||
|
v6udp.Close()
|
||||||
|
}
|
||||||
|
|
||||||
// Create a UDP4 socket used for sending to our discovered IPv4 address.
|
// Create a UDP4 socket used for sending to our discovered IPv4 address.
|
||||||
rs.pc4Hair, err = netns.Listener(c.logf).ListenPacket(ctx, "udp4", ":0")
|
rs.pc4Hair, err = netns.Listener(c.logf).ListenPacket(ctx, "udp4", ":0")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -111,6 +111,9 @@ func TestWorksWhenUDPBlocked(t *testing.T) {
|
|||||||
// That's not relevant to this test, so just accept what we're
|
// That's not relevant to this test, so just accept what we're
|
||||||
// given.
|
// given.
|
||||||
want.IPv4CanSend = r.IPv4CanSend
|
want.IPv4CanSend = r.IPv4CanSend
|
||||||
|
// OS IPv6 test is irrelevant here, accept whatever the current
|
||||||
|
// machine has.
|
||||||
|
want.OSHasIPv6 = r.OSHasIPv6
|
||||||
|
|
||||||
if !reflect.DeepEqual(r, want) {
|
if !reflect.DeepEqual(r, want) {
|
||||||
t.Errorf("mismatch\n got: %+v\nwant: %+v\n", r, want)
|
t.Errorf("mismatch\n got: %+v\nwant: %+v\n", r, want)
|
||||||
|
@ -496,10 +496,14 @@ type NetInfo struct {
|
|||||||
// It reports true even if there's no NAT involved.
|
// It reports true even if there's no NAT involved.
|
||||||
HairPinning opt.Bool
|
HairPinning opt.Bool
|
||||||
|
|
||||||
// WorkingIPv6 is whether IPv6 works.
|
// WorkingIPv6 is whether the host has IPv6 internet connectivity.
|
||||||
WorkingIPv6 opt.Bool
|
WorkingIPv6 opt.Bool
|
||||||
|
|
||||||
// WorkingUDP is whether UDP works.
|
// OSHasIPv6 is whether the OS supports IPv6 at all, regardless of
|
||||||
|
// whether IPv6 internet connectivity is available.
|
||||||
|
OSHasIPv6 opt.Bool
|
||||||
|
|
||||||
|
// WorkingUDP is whether the host has UDP internet connectivity.
|
||||||
WorkingUDP opt.Bool
|
WorkingUDP opt.Bool
|
||||||
|
|
||||||
// HavePortMap is whether we have an existing portmap open
|
// HavePortMap is whether we have an existing portmap open
|
||||||
@ -590,6 +594,7 @@ func (ni *NetInfo) BasicallyEqual(ni2 *NetInfo) bool {
|
|||||||
return ni.MappingVariesByDestIP == ni2.MappingVariesByDestIP &&
|
return ni.MappingVariesByDestIP == ni2.MappingVariesByDestIP &&
|
||||||
ni.HairPinning == ni2.HairPinning &&
|
ni.HairPinning == ni2.HairPinning &&
|
||||||
ni.WorkingIPv6 == ni2.WorkingIPv6 &&
|
ni.WorkingIPv6 == ni2.WorkingIPv6 &&
|
||||||
|
ni.OSHasIPv6 == ni2.OSHasIPv6 &&
|
||||||
ni.WorkingUDP == ni2.WorkingUDP &&
|
ni.WorkingUDP == ni2.WorkingUDP &&
|
||||||
ni.HavePortMap == ni2.HavePortMap &&
|
ni.HavePortMap == ni2.HavePortMap &&
|
||||||
ni.UPnP == ni2.UPnP &&
|
ni.UPnP == ni2.UPnP &&
|
||||||
|
@ -154,6 +154,7 @@ func (src *NetInfo) Clone() *NetInfo {
|
|||||||
MappingVariesByDestIP opt.Bool
|
MappingVariesByDestIP opt.Bool
|
||||||
HairPinning opt.Bool
|
HairPinning opt.Bool
|
||||||
WorkingIPv6 opt.Bool
|
WorkingIPv6 opt.Bool
|
||||||
|
OSHasIPv6 opt.Bool
|
||||||
WorkingUDP opt.Bool
|
WorkingUDP opt.Bool
|
||||||
HavePortMap bool
|
HavePortMap bool
|
||||||
UPnP opt.Bool
|
UPnP opt.Bool
|
||||||
|
@ -500,6 +500,7 @@ func TestNetInfoFields(t *testing.T) {
|
|||||||
"MappingVariesByDestIP",
|
"MappingVariesByDestIP",
|
||||||
"HairPinning",
|
"HairPinning",
|
||||||
"WorkingIPv6",
|
"WorkingIPv6",
|
||||||
|
"OSHasIPv6",
|
||||||
"WorkingUDP",
|
"WorkingUDP",
|
||||||
"HavePortMap",
|
"HavePortMap",
|
||||||
"UPnP",
|
"UPnP",
|
||||||
|
@ -338,6 +338,7 @@ func (v *NetInfoView) UnmarshalJSON(b []byte) error {
|
|||||||
func (v NetInfoView) MappingVariesByDestIP() opt.Bool { return v.ж.MappingVariesByDestIP }
|
func (v NetInfoView) MappingVariesByDestIP() opt.Bool { return v.ж.MappingVariesByDestIP }
|
||||||
func (v NetInfoView) HairPinning() opt.Bool { return v.ж.HairPinning }
|
func (v NetInfoView) HairPinning() opt.Bool { return v.ж.HairPinning }
|
||||||
func (v NetInfoView) WorkingIPv6() opt.Bool { return v.ж.WorkingIPv6 }
|
func (v NetInfoView) WorkingIPv6() opt.Bool { return v.ж.WorkingIPv6 }
|
||||||
|
func (v NetInfoView) OSHasIPv6() opt.Bool { return v.ж.OSHasIPv6 }
|
||||||
func (v NetInfoView) WorkingUDP() opt.Bool { return v.ж.WorkingUDP }
|
func (v NetInfoView) WorkingUDP() opt.Bool { return v.ж.WorkingUDP }
|
||||||
func (v NetInfoView) HavePortMap() bool { return v.ж.HavePortMap }
|
func (v NetInfoView) HavePortMap() bool { return v.ж.HavePortMap }
|
||||||
func (v NetInfoView) UPnP() opt.Bool { return v.ж.UPnP }
|
func (v NetInfoView) UPnP() opt.Bool { return v.ж.UPnP }
|
||||||
@ -354,6 +355,7 @@ func (v NetInfoView) String() string { return v.ж.Stri
|
|||||||
MappingVariesByDestIP opt.Bool
|
MappingVariesByDestIP opt.Bool
|
||||||
HairPinning opt.Bool
|
HairPinning opt.Bool
|
||||||
WorkingIPv6 opt.Bool
|
WorkingIPv6 opt.Bool
|
||||||
|
OSHasIPv6 opt.Bool
|
||||||
WorkingUDP opt.Bool
|
WorkingUDP opt.Bool
|
||||||
HavePortMap bool
|
HavePortMap bool
|
||||||
UPnP opt.Bool
|
UPnP opt.Bool
|
||||||
|
Loading…
Reference in New Issue
Block a user