Fix tests and linters
This commit is contained in:
@@ -55,7 +55,7 @@ var (
|
||||
myNetworks []*net.IPNet
|
||||
myNetworksLock sync.Mutex
|
||||
myNetworksNetworkChangedFlag = GetNetworkChangedFlag()
|
||||
myNetworksRefreshError error
|
||||
myNetworksRefreshError error //nolint:errname // Not what the linter thinks this is for.
|
||||
myNetworksRefreshFailingUntil time.Time
|
||||
)
|
||||
|
||||
@@ -63,7 +63,7 @@ var (
|
||||
// Broadcast or multicast addresses will never match, even if valid in in use.
|
||||
func IsMyIP(ip net.IP) (yes bool, err error) {
|
||||
// Check for IPs that don't need extra checks.
|
||||
switch netutils.GetIPScope(ip) {
|
||||
switch netutils.GetIPScope(ip) { //nolint:exhaustive // Only looking for specific values.
|
||||
case netutils.HostLocal:
|
||||
return true, nil
|
||||
case netutils.LocalMulticast, netutils.GlobalMulticast:
|
||||
@@ -90,7 +90,7 @@ func IsMyIP(ip net.IP) (yes bool, err error) {
|
||||
|
||||
// Check if there was a recent error on the previous refresh.
|
||||
if myNetworksRefreshError != nil && time.Now().Before(myNetworksRefreshFailingUntil) {
|
||||
return false, fmt.Errorf("failed to previously refresh interface addresses: %s", myNetworksRefreshError)
|
||||
return false, fmt.Errorf("failed to previously refresh interface addresses: %w", myNetworksRefreshError)
|
||||
}
|
||||
|
||||
// Refresh assigned networks.
|
||||
@@ -101,7 +101,7 @@ func IsMyIP(ip net.IP) (yes bool, err error) {
|
||||
// literally over thousand goroutines wanting to try this again.
|
||||
myNetworksRefreshError = err
|
||||
myNetworksRefreshFailingUntil = time.Now().Add(1 * time.Second)
|
||||
return false, fmt.Errorf("failed to refresh interface addresses: %s", err)
|
||||
return false, fmt.Errorf("failed to refresh interface addresses: %w", err)
|
||||
}
|
||||
myNetworks = make([]*net.IPNet, 0, len(interfaceNetworks))
|
||||
for _, ifNet := range interfaceNetworks {
|
||||
|
||||
@@ -5,6 +5,8 @@ import (
|
||||
)
|
||||
|
||||
func TestGetAssignedAddresses(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
ipv4, ipv6, err := GetAssignedAddresses()
|
||||
t.Logf("all v4: %v", ipv4)
|
||||
t.Logf("all v6: %v", ipv6)
|
||||
@@ -17,6 +19,8 @@ func TestGetAssignedAddresses(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestGetAssignedGlobalAddresses(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
ipv4, ipv6, err := GetAssignedGlobalAddresses()
|
||||
t.Logf("all global v4: %v", ipv4)
|
||||
t.Logf("all global v6: %v", ipv6)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// +build !server
|
||||
// go:build !server
|
||||
|
||||
package netenv
|
||||
|
||||
@@ -8,9 +8,9 @@ import (
|
||||
"net"
|
||||
"sync"
|
||||
|
||||
"github.com/safing/portbase/log"
|
||||
|
||||
"github.com/godbus/dbus/v5"
|
||||
|
||||
"github.com/safing/portbase/log"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -36,7 +36,7 @@ func getNameserversFromDbus() ([]Nameserver, error) { //nolint:gocognit // TODO
|
||||
|
||||
primaryConnectionVariant, err := getNetworkManagerProperty(dbusConn, dbus.ObjectPath("/org/freedesktop/NetworkManager"), "org.freedesktop.NetworkManager.PrimaryConnection")
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("dbus: failed to access NetworkManager.PrimaryConnection: %s", err)
|
||||
return nil, fmt.Errorf("dbus: failed to access NetworkManager.PrimaryConnection: %w", err)
|
||||
}
|
||||
primaryConnection, ok := primaryConnectionVariant.Value().(dbus.ObjectPath)
|
||||
if !ok {
|
||||
@@ -45,7 +45,7 @@ func getNameserversFromDbus() ([]Nameserver, error) { //nolint:gocognit // TODO
|
||||
|
||||
activeConnectionsVariant, err := getNetworkManagerProperty(dbusConn, dbus.ObjectPath("/org/freedesktop/NetworkManager"), "org.freedesktop.NetworkManager.ActiveConnections")
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("dbus: failed to access NetworkManager.ActiveConnections: %s", err)
|
||||
return nil, fmt.Errorf("dbus: failed to access NetworkManager.ActiveConnections: %w", err)
|
||||
}
|
||||
activeConnections, ok := activeConnectionsVariant.Value().([]dbus.ObjectPath)
|
||||
if !ok {
|
||||
@@ -60,18 +60,18 @@ func getNameserversFromDbus() ([]Nameserver, error) { //nolint:gocognit // TODO
|
||||
}
|
||||
|
||||
for _, activeConnection := range sortedConnections {
|
||||
new, err := dbusGetInterfaceNameservers(dbusConn, activeConnection, 4)
|
||||
newNameservers, err := dbusGetInterfaceNameservers(dbusConn, activeConnection, 4)
|
||||
if err != nil {
|
||||
log.Warningf("failed to get nameserver: %s", err)
|
||||
} else {
|
||||
ns = append(ns, new...)
|
||||
ns = append(ns, newNameservers...)
|
||||
}
|
||||
|
||||
new, err = dbusGetInterfaceNameservers(dbusConn, activeConnection, 6)
|
||||
newNameservers, err = dbusGetInterfaceNameservers(dbusConn, activeConnection, 6)
|
||||
if err != nil {
|
||||
log.Warningf("failed to get nameserver: %s", err)
|
||||
} else {
|
||||
ns = append(ns, new...)
|
||||
ns = append(ns, newNameservers...)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -87,7 +87,7 @@ func dbusGetInterfaceNameservers(dbusConn *dbus.Conn, interfaceObject dbus.Objec
|
||||
// Get Interface Configuration.
|
||||
ipConfigVariant, err := getNetworkManagerProperty(dbusConn, interfaceObject, ipConfigPropertyKey)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to access %s:%s: %s", interfaceObject, ipConfigPropertyKey, err)
|
||||
return nil, fmt.Errorf("failed to access %s:%s: %w", interfaceObject, ipConfigPropertyKey, err)
|
||||
}
|
||||
ipConfig, ok := ipConfigVariant.Value().(dbus.ObjectPath)
|
||||
if !ok {
|
||||
@@ -102,7 +102,7 @@ func dbusGetInterfaceNameservers(dbusConn *dbus.Conn, interfaceObject dbus.Objec
|
||||
// Get Nameserver IPs
|
||||
nameserverIPsVariant, err := getNetworkManagerProperty(dbusConn, ipConfig, nameserversIPsPropertyKey)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to access %s:%s: %s", ipConfig, nameserversIPsPropertyKey, err)
|
||||
return nil, fmt.Errorf("failed to access %s:%s: %w", ipConfig, nameserversIPsPropertyKey, err)
|
||||
}
|
||||
var nameserverIPs []net.IP
|
||||
switch ipVersion {
|
||||
@@ -134,7 +134,7 @@ func dbusGetInterfaceNameservers(dbusConn *dbus.Conn, interfaceObject dbus.Objec
|
||||
// Get Nameserver Domains
|
||||
nameserverDomainsVariant, err := getNetworkManagerProperty(dbusConn, ipConfig, nameserversDomainsPropertyKey)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to access %s:%s: %s", ipConfig, nameserversDomainsPropertyKey, err)
|
||||
return nil, fmt.Errorf("failed to access %s:%s: %w", ipConfig, nameserversDomainsPropertyKey, err)
|
||||
}
|
||||
nameserverDomains, ok := nameserverDomainsVariant.Value().([]string)
|
||||
if !ok {
|
||||
@@ -144,7 +144,7 @@ func dbusGetInterfaceNameservers(dbusConn *dbus.Conn, interfaceObject dbus.Objec
|
||||
// Get Nameserver Searches
|
||||
nameserverSearchesVariant, err := getNetworkManagerProperty(dbusConn, ipConfig, nameserversSearchesPropertyKey)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to access %s:%s: %s", ipConfig, nameserversSearchesPropertyKey, err)
|
||||
return nil, fmt.Errorf("failed to access %s:%s: %w", ipConfig, nameserversSearchesPropertyKey, err)
|
||||
}
|
||||
nameserverSearches, ok := nameserverSearchesVariant.Value().([]string)
|
||||
if !ok {
|
||||
@@ -152,7 +152,7 @@ func dbusGetInterfaceNameservers(dbusConn *dbus.Conn, interfaceObject dbus.Objec
|
||||
}
|
||||
|
||||
ns := make([]Nameserver, 0, len(nameserverIPs))
|
||||
searchDomains := append(nameserverDomains, nameserverSearches...)
|
||||
searchDomains := append(nameserverDomains, nameserverSearches...) //nolint:gocritic
|
||||
for _, nameserverIP := range nameserverIPs {
|
||||
ns = append(ns, Nameserver{
|
||||
IP: nameserverIP,
|
||||
|
||||
@@ -6,6 +6,8 @@ import (
|
||||
)
|
||||
|
||||
func TestDbus(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
if testing.Short() {
|
||||
t.Skip("skipping test in short mode because it fails in the CI")
|
||||
}
|
||||
|
||||
@@ -2,9 +2,7 @@ package netenv
|
||||
|
||||
import "net"
|
||||
|
||||
var (
|
||||
localAddrFactory func(network string) net.Addr
|
||||
)
|
||||
var localAddrFactory func(network string) net.Addr
|
||||
|
||||
// SetLocalAddrFactory supplies the environment package with a function to get permitted local addresses for connections.
|
||||
func SetLocalAddrFactory(laf func(network string) net.Addr) {
|
||||
|
||||
@@ -43,7 +43,9 @@ func Gateways() []net.IP {
|
||||
log.Warningf("environment: could not read /proc/net/route: %s", err)
|
||||
return gateways
|
||||
}
|
||||
defer route.Close()
|
||||
defer func() {
|
||||
_ = route.Close()
|
||||
}()
|
||||
|
||||
// file scanner
|
||||
scanner := bufio.NewScanner(route)
|
||||
@@ -76,7 +78,9 @@ func Gateways() []net.IP {
|
||||
log.Warningf("environment: could not read /proc/net/ipv6_route: %s", err)
|
||||
return gateways
|
||||
}
|
||||
defer v6route.Close()
|
||||
defer func() {
|
||||
_ = v6route.Close()
|
||||
}()
|
||||
|
||||
// file scanner
|
||||
scanner = bufio.NewScanner(v6route)
|
||||
@@ -149,7 +153,9 @@ func getNameserversFromResolvconf() ([]Nameserver, error) {
|
||||
log.Warningf("environment: could not read /etc/resolv.conf: %s", err)
|
||||
return nil, err
|
||||
}
|
||||
defer resolvconf.Close()
|
||||
defer func() {
|
||||
_ = resolvconf.Close()
|
||||
}()
|
||||
|
||||
// file scanner
|
||||
scanner := bufio.NewScanner(resolvconf)
|
||||
@@ -186,7 +192,6 @@ func getNameserversFromResolvconf() ([]Nameserver, error) {
|
||||
})
|
||||
}
|
||||
return nameservers, nil
|
||||
|
||||
}
|
||||
|
||||
func addNameservers(nameservers, newNameservers []Nameserver) []Nameserver {
|
||||
|
||||
@@ -3,6 +3,8 @@ package netenv
|
||||
import "testing"
|
||||
|
||||
func TestLinuxEnvironment(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
nameserversTest, err := getNameserversFromResolvconf()
|
||||
if err != nil {
|
||||
t.Errorf("failed to get namerservers from resolvconf: %s", err)
|
||||
|
||||
@@ -3,6 +3,8 @@ package netenv
|
||||
import "testing"
|
||||
|
||||
func TestEnvironment(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
nameserversTest := Nameservers()
|
||||
t.Logf("nameservers: %+v", nameserversTest)
|
||||
|
||||
|
||||
@@ -9,10 +9,10 @@ import (
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"github.com/google/gopacket/layers"
|
||||
"golang.org/x/net/icmp"
|
||||
"golang.org/x/net/ipv4"
|
||||
|
||||
"github.com/google/gopacket/layers"
|
||||
"github.com/safing/portbase/log"
|
||||
"github.com/safing/portbase/rng"
|
||||
"github.com/safing/portmaster/intel/geoip"
|
||||
@@ -41,10 +41,12 @@ func prepLocation() (err error) {
|
||||
return err
|
||||
}
|
||||
|
||||
// DeviceLocations holds multiple device locations.
|
||||
type DeviceLocations struct {
|
||||
All []*DeviceLocation
|
||||
}
|
||||
|
||||
// Best returns the best (most accurate) device location.
|
||||
func (dl *DeviceLocations) Best() *DeviceLocation {
|
||||
if len(dl.All) > 0 {
|
||||
return dl.All[0]
|
||||
@@ -52,6 +54,7 @@ func (dl *DeviceLocations) Best() *DeviceLocation {
|
||||
return nil
|
||||
}
|
||||
|
||||
// BestV4 returns the best (most accurate) IPv4 device location.
|
||||
func (dl *DeviceLocations) BestV4() *DeviceLocation {
|
||||
for _, loc := range dl.All {
|
||||
if loc.IPVersion == packet.IPv4 {
|
||||
@@ -61,6 +64,7 @@ func (dl *DeviceLocations) BestV4() *DeviceLocation {
|
||||
return nil
|
||||
}
|
||||
|
||||
// BestV6 returns the best (most accurate) IPv6 device location.
|
||||
func (dl *DeviceLocations) BestV6() *DeviceLocation {
|
||||
for _, loc := range dl.All {
|
||||
if loc.IPVersion == packet.IPv6 {
|
||||
@@ -129,6 +133,7 @@ func (dl *DeviceLocation) IsMoreAccurateThan(other *DeviceLocation) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// LocationOrNil or returns the geoip location, or nil if not present.
|
||||
func (dl *DeviceLocation) LocationOrNil() *geoip.Location {
|
||||
if dl == nil {
|
||||
return nil
|
||||
@@ -147,8 +152,10 @@ func (dl *DeviceLocation) String() string {
|
||||
}
|
||||
}
|
||||
|
||||
// DeviceLocationSource is a location source.
|
||||
type DeviceLocationSource string
|
||||
|
||||
// Location Sources.
|
||||
const (
|
||||
SourceInterface DeviceLocationSource = "interface"
|
||||
SourcePeer DeviceLocationSource = "peer"
|
||||
@@ -158,6 +165,7 @@ const (
|
||||
SourceOther DeviceLocationSource = "other"
|
||||
)
|
||||
|
||||
// Accuracy returns the location accuracy of the source.
|
||||
func (dls DeviceLocationSource) Accuracy() int {
|
||||
switch dls {
|
||||
case SourceInterface:
|
||||
@@ -183,6 +191,7 @@ func (a sortLocationsByAccuracy) Len() int { return len(a) }
|
||||
func (a sortLocationsByAccuracy) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
|
||||
func (a sortLocationsByAccuracy) Less(i, j int) bool { return !a[j].IsMoreAccurateThan(a[i]) }
|
||||
|
||||
// SetInternetLocation provides the location management system with a possible Internet location.
|
||||
func SetInternetLocation(ip net.IP, source DeviceLocationSource) (dl *DeviceLocation, ok bool) {
|
||||
// Check if IP is global.
|
||||
if netutils.GetIPScope(ip) != netutils.Global {
|
||||
@@ -206,9 +215,8 @@ func SetInternetLocation(ip net.IP, source DeviceLocationSource) (dl *DeviceLoca
|
||||
if err != nil {
|
||||
log.Warningf("netenv: failed to get geolocation data of %s (from %s): %s", ip, source, err)
|
||||
return nil, false
|
||||
} else {
|
||||
loc.Location = geoLoc
|
||||
}
|
||||
loc.Location = geoLoc
|
||||
|
||||
addLocation(loc)
|
||||
return loc, true
|
||||
@@ -242,7 +250,8 @@ func addLocation(dl *DeviceLocation) {
|
||||
sort.Sort(sortLocationsByAccuracy(locations.All))
|
||||
}
|
||||
|
||||
// DEPRECATED: Please use GetInternetLocation instead.
|
||||
// GetApproximateInternetLocation returns the approximate Internet location.
|
||||
// Deprecated: Please use GetInternetLocation instead.
|
||||
func GetApproximateInternetLocation() (net.IP, error) {
|
||||
loc, ok := GetInternetLocation()
|
||||
if !ok || loc.Best() == nil {
|
||||
@@ -251,6 +260,7 @@ func GetApproximateInternetLocation() (net.IP, error) {
|
||||
return loc.Best().IP, nil
|
||||
}
|
||||
|
||||
// GetInternetLocation returns the possible device locations.
|
||||
func GetInternetLocation() (deviceLocations *DeviceLocations, ok bool) {
|
||||
gettingLocationsLock.Lock()
|
||||
defer gettingLocationsLock.Unlock()
|
||||
@@ -323,7 +333,7 @@ func getLocationFromInterfaces() (v4ok, v6ok bool) {
|
||||
func getLocationFromUPnP() (ok bool) {
|
||||
// Endoint: urn:schemas-upnp-org:service:WANIPConnection:1#GetExternalIPAddress
|
||||
// A first test showed that a router did offer that endpoint, but did not
|
||||
// return an IP addres.
|
||||
// return an IP address.
|
||||
return false
|
||||
}
|
||||
*/
|
||||
@@ -332,14 +342,14 @@ func getLocationFromTraceroute() (dl *DeviceLocation, err error) {
|
||||
// Create connection.
|
||||
conn, err := net.ListenPacket("ip4:icmp", "")
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to open icmp conn: %s", err)
|
||||
return nil, fmt.Errorf("failed to open icmp conn: %w", err)
|
||||
}
|
||||
v4Conn := ipv4.NewPacketConn(conn)
|
||||
|
||||
// Generate a random ID for the ICMP packets.
|
||||
generatedID, err := rng.Number(0xFFFF) // uint16
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to generate icmp msg ID: %s", err)
|
||||
return nil, fmt.Errorf("failed to generate icmp msg ID: %w", err)
|
||||
}
|
||||
msgID := int(generatedID)
|
||||
var msgSeq int
|
||||
@@ -368,28 +378,27 @@ nextHop:
|
||||
for j := 1; j <= 2; j++ { // Try every hop twice.
|
||||
// Increase sequence number.
|
||||
msgSeq++
|
||||
pingMessage.Body.(*icmp.Echo).Seq = msgSeq
|
||||
pingMessage.Body.(*icmp.Echo).Seq = msgSeq //nolint:forcetypeassert // Can only be *icmp.Echo.
|
||||
|
||||
// Make packet data.
|
||||
pingPacket, err := pingMessage.Marshal(nil)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to build icmp packet: %s", err)
|
||||
return nil, fmt.Errorf("failed to build icmp packet: %w", err)
|
||||
}
|
||||
|
||||
// Set TTL on IP packet.
|
||||
err = v4Conn.SetTTL(i)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to set icmp packet TTL: %s", err)
|
||||
return nil, fmt.Errorf("failed to set icmp packet TTL: %w", err)
|
||||
}
|
||||
|
||||
// Send ICMP packet.
|
||||
if _, err := conn.WriteTo(pingPacket, locationTestingIPv4Addr); err != nil {
|
||||
if neterr, ok := err.(*net.OpError); ok {
|
||||
if neterr.Err == syscall.ENOBUFS {
|
||||
continue
|
||||
}
|
||||
var opErr *net.OpError
|
||||
if errors.As(err, &opErr) && errors.Is(opErr.Err, syscall.ENOBUFS) {
|
||||
continue
|
||||
}
|
||||
return nil, fmt.Errorf("failed to send icmp packet: %s", err)
|
||||
return nil, fmt.Errorf("failed to send icmp packet: %w", err)
|
||||
}
|
||||
|
||||
// Listen for replies of the ICMP packet.
|
||||
@@ -433,7 +442,7 @@ nextHop:
|
||||
continue listen
|
||||
}
|
||||
// Check if the ID and sequence match.
|
||||
if originalEcho.ID != int(msgID) {
|
||||
if originalEcho.ID != msgID {
|
||||
continue listen
|
||||
}
|
||||
if originalEcho.Seq < minSeq {
|
||||
@@ -469,8 +478,8 @@ nextHop:
|
||||
}
|
||||
|
||||
func recvICMP(currentHop int, icmpPacketsViaFirewall chan packet.Packet) (
|
||||
remoteIP net.IP, imcpPacket *layers.ICMPv4, ok bool) {
|
||||
|
||||
remoteIP net.IP, imcpPacket *layers.ICMPv4, ok bool,
|
||||
) {
|
||||
for {
|
||||
select {
|
||||
case pkt := <-icmpPacketsViaFirewall:
|
||||
@@ -496,7 +505,7 @@ func recvICMP(currentHop int, icmpPacketsViaFirewall chan packet.Packet) (
|
||||
}
|
||||
}
|
||||
|
||||
func getLocationFromTimezone(ipVersion packet.IPVersion) (ok bool) {
|
||||
func getLocationFromTimezone(ipVersion packet.IPVersion) (ok bool) { //nolint:unparam // This is documentation.
|
||||
// Create base struct.
|
||||
tzLoc := &DeviceLocation{
|
||||
IPVersion: ipVersion,
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
//+build !windows
|
||||
// go:build !windows
|
||||
|
||||
package netenv
|
||||
|
||||
import "net"
|
||||
|
||||
func newICMPListener(_ string) (net.PacketConn, error) {
|
||||
func newICMPListener(_ string) (net.PacketConn, error) { //nolint:unused,deadcode // TODO: clean with Windows code later.
|
||||
return net.ListenPacket("ip4:icmp", "0.0.0.0")
|
||||
}
|
||||
|
||||
@@ -5,15 +5,15 @@ import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
var (
|
||||
privileged bool
|
||||
)
|
||||
var privileged bool
|
||||
|
||||
func init() {
|
||||
flag.BoolVar(&privileged, "privileged", false, "run tests that require root/admin privileges")
|
||||
}
|
||||
|
||||
func TestGetInternetLocation(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
if testing.Short() {
|
||||
t.Skip()
|
||||
}
|
||||
|
||||
@@ -4,16 +4,14 @@ import (
|
||||
"github.com/safing/portbase/modules"
|
||||
)
|
||||
|
||||
// Event Names
|
||||
// Event Names.
|
||||
const (
|
||||
ModuleName = "netenv"
|
||||
NetworkChangedEvent = "network changed"
|
||||
OnlineStatusChangedEvent = "online status changed"
|
||||
)
|
||||
|
||||
var (
|
||||
module *modules.Module
|
||||
)
|
||||
var module *modules.Module
|
||||
|
||||
func init() {
|
||||
module = modules.Register(ModuleName, prep, start, nil)
|
||||
|
||||
@@ -3,7 +3,7 @@ package netenv
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"crypto/sha1" //nolint:gosec // not used for security
|
||||
"crypto/sha1"
|
||||
"io"
|
||||
"net"
|
||||
"time"
|
||||
@@ -17,6 +17,7 @@ var (
|
||||
networkChangedBroadcastFlag = utils.NewBroadcastFlag()
|
||||
)
|
||||
|
||||
// GetNetworkChangedFlag returns a flag to be notified about a network change.
|
||||
func GetNetworkChangedFlag() *utils.Flag {
|
||||
return networkChangedBroadcastFlag.NewFlag()
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package netenv
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/http"
|
||||
@@ -21,7 +22,7 @@ import (
|
||||
// OnlineStatus represent a state of connectivity to the Internet.
|
||||
type OnlineStatus uint8
|
||||
|
||||
// Online Status Values
|
||||
// Online Status Values.
|
||||
const (
|
||||
StatusUnknown OnlineStatus = 0
|
||||
StatusOffline OnlineStatus = 1
|
||||
@@ -31,7 +32,7 @@ const (
|
||||
StatusOnline OnlineStatus = 5
|
||||
)
|
||||
|
||||
// Online Status and Resolver
|
||||
// Online Status and Resolver.
|
||||
var (
|
||||
PortalTestIP = net.IPv4(192, 0, 2, 1)
|
||||
PortalTestURL = fmt.Sprintf("http://%s/", PortalTestIP)
|
||||
@@ -124,8 +125,6 @@ func IsConnectivityDomain(domain string) bool {
|
||||
|
||||
func (os OnlineStatus) String() string {
|
||||
switch os {
|
||||
default:
|
||||
return "Unknown"
|
||||
case StatusOffline:
|
||||
return "Offline"
|
||||
case StatusLimited:
|
||||
@@ -136,6 +135,10 @@ func (os OnlineStatus) String() string {
|
||||
return "SemiOnline"
|
||||
case StatusOnline:
|
||||
return "Online"
|
||||
case StatusUnknown:
|
||||
fallthrough
|
||||
default:
|
||||
return "Unknown"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -175,7 +178,7 @@ func GetOnlineStatus() OnlineStatus {
|
||||
return OnlineStatus(atomic.LoadInt32(onlineStatus))
|
||||
}
|
||||
|
||||
// CheckAndGetOnlineStatus triggers a new online status check and returns the result
|
||||
// CheckAndGetOnlineStatus triggers a new online status check and returns the result.
|
||||
func CheckAndGetOnlineStatus() OnlineStatus {
|
||||
// trigger new investigation
|
||||
triggerOnlineStatusInvestigation()
|
||||
@@ -225,7 +228,7 @@ func notifyOnlineStatus(status OnlineStatus) {
|
||||
var eventID, title, message string
|
||||
|
||||
// Check if status is worth notifying.
|
||||
switch status {
|
||||
switch status { //nolint:exhaustive // Checking for selection only.
|
||||
case StatusOffline:
|
||||
eventID = "netenv:online-status:offline"
|
||||
title = "Device is Offline"
|
||||
@@ -419,7 +422,7 @@ func checkOnlineStatus(ctx context.Context) {
|
||||
} else {
|
||||
var lan bool
|
||||
for _, ip := range ipv4 {
|
||||
switch netutils.GetIPScope(ip) {
|
||||
switch netutils.GetIPScope(ip) { //nolint:exhaustive // Checking to specific values only.
|
||||
case netutils.SiteLocal:
|
||||
lan = true
|
||||
case netutils.Global:
|
||||
@@ -429,7 +432,7 @@ func checkOnlineStatus(ctx context.Context) {
|
||||
}
|
||||
}
|
||||
for _, ip := range ipv6 {
|
||||
switch netutils.GetIPScope(ip) {
|
||||
switch netutils.GetIPScope(ip) { //nolint:exhaustive // Checking to specific values only.
|
||||
case netutils.SiteLocal, netutils.Global:
|
||||
// IPv6 global addresses are also used in local networks
|
||||
lan = true
|
||||
@@ -470,14 +473,16 @@ func checkOnlineStatus(ctx context.Context) {
|
||||
|
||||
response, err := client.Do(request)
|
||||
if err != nil {
|
||||
nErr, ok := err.(net.Error)
|
||||
if !ok || !nErr.Timeout() {
|
||||
var netErr net.Error
|
||||
if !errors.As(err, &netErr) || !netErr.Timeout() {
|
||||
// Timeout is the expected error when there is no portal
|
||||
log.Debugf("netenv: http portal test failed: %s", err)
|
||||
// TODO: discern between errors to detect StatusLimited
|
||||
}
|
||||
} else {
|
||||
defer response.Body.Close()
|
||||
defer func() {
|
||||
_ = response.Body.Close()
|
||||
}()
|
||||
// Got a response, something is messing with the request
|
||||
|
||||
// check location
|
||||
|
||||
@@ -6,6 +6,8 @@ import (
|
||||
)
|
||||
|
||||
func TestCheckOnlineStatus(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
checkOnlineStatus(context.Background())
|
||||
t.Logf("online status: %s", GetOnlineStatus())
|
||||
t.Logf("captive portal: %+v", GetCaptivePortal())
|
||||
|
||||
Reference in New Issue
Block a user