diff --git a/internal/home/ipdetector.go b/internal/aghnet/ipdetector.go similarity index 77% rename from internal/home/ipdetector.go rename to internal/aghnet/ipdetector.go index 01d7ca99..7fa9414c 100644 --- a/internal/home/ipdetector.go +++ b/internal/aghnet/ipdetector.go @@ -1,14 +1,14 @@ -package home +package aghnet import "net" -// ipDetector describes IP address properties. -type ipDetector struct { +// IPDetector describes IP address properties. +type IPDetector struct { nets []*net.IPNet } -// newIPDetector returns a new IP detector. -func newIPDetector() (ipd *ipDetector, err error) { +// NewIPDetector returns a new IP detector. +func NewIPDetector() (ipd *IPDetector, err error) { specialNetworks := []string{ "0.0.0.0/8", "10.0.0.0/8", @@ -43,7 +43,7 @@ func newIPDetector() (ipd *ipDetector, err error) { "fe80::/10", } - ipd = &ipDetector{ + ipd = &IPDetector{ nets: make([]*net.IPNet, len(specialNetworks)), } for i, ipnetStr := range specialNetworks { @@ -59,10 +59,10 @@ func newIPDetector() (ipd *ipDetector, err error) { return ipd, nil } -// detectSpecialNetwork returns true if IP address is contained by any of +// DetectSpecialNetwork returns true if IP address is contained by any of // special-purpose IP address registries according to RFC-6890 // (https://tools.ietf.org/html/rfc6890). -func (ipd *ipDetector) detectSpecialNetwork(ip net.IP) bool { +func (ipd *IPDetector) DetectSpecialNetwork(ip net.IP) bool { for _, ipnet := range ipd.nets { if ipnet.Contains(ip) { return true diff --git a/internal/home/ipdetector_test.go b/internal/aghnet/ipdetector_test.go similarity index 95% rename from internal/home/ipdetector_test.go rename to internal/aghnet/ipdetector_test.go index 6609ba08..833ef53a 100644 --- a/internal/home/ipdetector_test.go +++ b/internal/aghnet/ipdetector_test.go @@ -1,4 +1,4 @@ -package home +package aghnet import ( "net" @@ -9,10 +9,10 @@ import ( ) func TestIPDetector_detectSpecialNetwork(t *testing.T) { - var ipd *ipDetector + var ipd *IPDetector var err error - ipd, err = newIPDetector() + ipd, err = NewIPDetector() require.Nil(t, err) testCases := []struct { @@ -139,7 +139,7 @@ func TestIPDetector_detectSpecialNetwork(t *testing.T) { for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { - assert.Equal(t, tc.want, ipd.detectSpecialNetwork(tc.ip)) + assert.Equal(t, tc.want, ipd.DetectSpecialNetwork(tc.ip)) }) } } diff --git a/internal/util/network.go b/internal/aghnet/net.go similarity index 73% rename from internal/util/network.go rename to internal/aghnet/net.go index ad2f253b..9bce75fd 100644 --- a/internal/util/network.go +++ b/internal/aghnet/net.go @@ -1,4 +1,5 @@ -package util +// Package aghnet contains some utilities for networking. +package aghnet import ( "encoding/json" @@ -6,14 +7,70 @@ import ( "fmt" "net" "os" + "os/exec" "runtime" "strconv" + "strings" "syscall" "time" + "github.com/AdguardTeam/AdGuardHome/internal/agherr" "github.com/AdguardTeam/golibs/log" ) +// ErrNoStaticIPInfo is returned by IfaceHasStaticIP when no information about +// the IP being static is available. +const ErrNoStaticIPInfo agherr.Error = "no information about static ip" + +// IfaceHasStaticIP checks if interface is configured to have static IP address. +// If it can't give a definitive answer, it returns false and an error for which +// errors.Is(err, ErrNoStaticIPInfo) is true. +func IfaceHasStaticIP(ifaceName string) (has bool, err error) { + return ifaceHasStaticIP(ifaceName) +} + +// IfaceSetStaticIP sets static IP address for network interface. +func IfaceSetStaticIP(ifaceName string) (err error) { + return ifaceSetStaticIP(ifaceName) +} + +// GatewayIP returns IP address of interface's gateway. +func GatewayIP(ifaceName string) net.IP { + cmd := exec.Command("ip", "route", "show", "dev", ifaceName) + log.Tracef("executing %s %v", cmd.Path, cmd.Args) + d, err := cmd.Output() + if err != nil || cmd.ProcessState.ExitCode() != 0 { + return nil + } + + fields := strings.Fields(string(d)) + // The meaningful "ip route" command output should contain the word + // "default" at first field and default gateway IP address at third + // field. + if len(fields) < 3 || fields[0] != "default" { + return nil + } + + return net.ParseIP(fields[2]) +} + +// CanBindPort checks if we can bind to the given port. +func CanBindPort(port int) (can bool, err error) { + var addr *net.TCPAddr + addr, err = net.ResolveTCPAddr("tcp", fmt.Sprintf("127.0.0.1:%d", port)) + if err != nil { + return false, err + } + + var listener *net.TCPListener + listener, err = net.ListenTCP("tcp", addr) + if err != nil { + return false, err + } + _ = listener.Close() + return true, nil +} + // NetInterface represents an entry of network interfaces map. type NetInterface struct { MTU int `json:"mtu"` diff --git a/internal/sysutil/net_darwin.go b/internal/aghnet/net_darwin.go similarity index 99% rename from internal/sysutil/net_darwin.go rename to internal/aghnet/net_darwin.go index 1bc1ac61..56fa51e1 100644 --- a/internal/sysutil/net_darwin.go +++ b/internal/aghnet/net_darwin.go @@ -1,6 +1,6 @@ // +build darwin -package sysutil +package aghnet import ( "errors" diff --git a/internal/sysutil/net_linux.go b/internal/aghnet/net_linux.go similarity index 97% rename from internal/sysutil/net_linux.go rename to internal/aghnet/net_linux.go index 1964f9dd..47614067 100644 --- a/internal/sysutil/net_linux.go +++ b/internal/aghnet/net_linux.go @@ -1,6 +1,6 @@ // +build linux -package sysutil +package aghnet import ( "bufio" @@ -13,7 +13,6 @@ import ( "strings" "github.com/AdguardTeam/AdGuardHome/internal/aghio" - "github.com/AdguardTeam/AdGuardHome/internal/util" "github.com/AdguardTeam/golibs/file" ) @@ -132,7 +131,7 @@ func ifacesStaticConfig(r io.Reader, ifaceName string) (has bool, err error) { } func ifaceSetStaticIP(ifaceName string) (err error) { - ipNet := util.GetSubnet(ifaceName) + ipNet := GetSubnet(ifaceName) if ipNet.IP == nil { return errors.New("can't get IP address") } diff --git a/internal/sysutil/net_linux_test.go b/internal/aghnet/net_linux_test.go similarity index 99% rename from internal/sysutil/net_linux_test.go rename to internal/aghnet/net_linux_test.go index 3fbfc547..81ebb8b0 100644 --- a/internal/sysutil/net_linux_test.go +++ b/internal/aghnet/net_linux_test.go @@ -1,6 +1,6 @@ // +build linux -package sysutil +package aghnet import ( "bytes" diff --git a/internal/sysutil/net_others.go b/internal/aghnet/net_others.go similarity index 94% rename from internal/sysutil/net_others.go rename to internal/aghnet/net_others.go index fd28c1a1..3b8e9da8 100644 --- a/internal/sysutil/net_others.go +++ b/internal/aghnet/net_others.go @@ -1,6 +1,6 @@ // +build !linux,!darwin -package sysutil +package aghnet import ( "fmt" diff --git a/internal/util/network_test.go b/internal/aghnet/net_test.go similarity index 96% rename from internal/util/network_test.go rename to internal/aghnet/net_test.go index bcc1da4c..45960e5a 100644 --- a/internal/util/network_test.go +++ b/internal/aghnet/net_test.go @@ -1,4 +1,4 @@ -package util +package aghnet import ( "testing" diff --git a/internal/sysutil/os.go b/internal/aghos/os.go similarity index 87% rename from internal/sysutil/os.go rename to internal/aghos/os.go index 63d2bf7e..f573d7a7 100644 --- a/internal/sysutil/os.go +++ b/internal/aghos/os.go @@ -1,5 +1,5 @@ -// Package sysutil contains utilities for functions requiring system calls. -package sysutil +// Package aghos contains utilities for functions requiring system calls. +package aghos import "syscall" diff --git a/internal/sysutil/os_freebsd.go b/internal/aghos/os_freebsd.go similarity index 97% rename from internal/sysutil/os_freebsd.go rename to internal/aghos/os_freebsd.go index 12321aa7..40965e3a 100644 --- a/internal/sysutil/os_freebsd.go +++ b/internal/aghos/os_freebsd.go @@ -1,6 +1,6 @@ // +build freebsd -package sysutil +package aghos import ( "os" diff --git a/internal/sysutil/os_linux.go b/internal/aghos/os_linux.go similarity index 98% rename from internal/sysutil/os_linux.go rename to internal/aghos/os_linux.go index 2bab01d4..7c74bbd0 100644 --- a/internal/sysutil/os_linux.go +++ b/internal/aghos/os_linux.go @@ -1,6 +1,6 @@ // +build linux -package sysutil +package aghos import ( "os" diff --git a/internal/sysutil/os_unix.go b/internal/aghos/os_unix.go similarity index 97% rename from internal/sysutil/os_unix.go rename to internal/aghos/os_unix.go index a77e9da1..5e0ffef6 100644 --- a/internal/sysutil/os_unix.go +++ b/internal/aghos/os_unix.go @@ -1,6 +1,6 @@ // +build aix darwin dragonfly netbsd openbsd solaris -package sysutil +package aghos import ( "os" diff --git a/internal/sysutil/os_windows.go b/internal/aghos/os_windows.go similarity index 97% rename from internal/sysutil/os_windows.go rename to internal/aghos/os_windows.go index 3d6745c7..738889b4 100644 --- a/internal/sysutil/os_windows.go +++ b/internal/aghos/os_windows.go @@ -1,6 +1,6 @@ // +build windows -package sysutil +package aghos import ( "fmt" diff --git a/internal/sysutil/syslog.go b/internal/aghos/syslog.go similarity index 90% rename from internal/sysutil/syslog.go rename to internal/aghos/syslog.go index 7bd505fc..a67a5635 100644 --- a/internal/sysutil/syslog.go +++ b/internal/aghos/syslog.go @@ -1,4 +1,4 @@ -package sysutil +package aghos // ConfigureSyslog reroutes standard logger output to syslog. func ConfigureSyslog(serviceName string) error { diff --git a/internal/sysutil/syslog_others.go b/internal/aghos/syslog_others.go similarity index 94% rename from internal/sysutil/syslog_others.go rename to internal/aghos/syslog_others.go index 91fe27cf..e202b573 100644 --- a/internal/sysutil/syslog_others.go +++ b/internal/aghos/syslog_others.go @@ -1,6 +1,6 @@ // +build !windows,!plan9 -package sysutil +package aghos import ( "log/syslog" diff --git a/internal/sysutil/syslog_windows.go b/internal/aghos/syslog_windows.go similarity index 98% rename from internal/sysutil/syslog_windows.go rename to internal/aghos/syslog_windows.go index 1d5cd03f..c1ec0323 100644 --- a/internal/sysutil/syslog_windows.go +++ b/internal/aghos/syslog_windows.go @@ -1,6 +1,6 @@ // +build windows plan9 -package sysutil +package aghos import ( "strings" diff --git a/internal/sysutil/sysutil_test.go b/internal/aghos/sysutil_test.go similarity index 89% rename from internal/sysutil/sysutil_test.go rename to internal/aghos/sysutil_test.go index 8ca0ff66..e68c26b7 100644 --- a/internal/sysutil/sysutil_test.go +++ b/internal/aghos/sysutil_test.go @@ -1,4 +1,4 @@ -package sysutil +package aghos import ( "testing" diff --git a/internal/dhcpd/http.go b/internal/dhcpd/http.go index 9fea7bf6..24a73b77 100644 --- a/internal/dhcpd/http.go +++ b/internal/dhcpd/http.go @@ -10,8 +10,7 @@ import ( "os" "strings" - "github.com/AdguardTeam/AdGuardHome/internal/sysutil" - "github.com/AdguardTeam/AdGuardHome/internal/util" + "github.com/AdguardTeam/AdGuardHome/internal/aghnet" "github.com/AdguardTeam/golibs/log" ) @@ -93,7 +92,7 @@ func (s *Server) handleDHCPStatus(w http.ResponseWriter, r *http.Request) { func (s *Server) enableDHCP(ifaceName string) (code int, err error) { var hasStaticIP bool - hasStaticIP, err = sysutil.IfaceHasStaticIP(ifaceName) + hasStaticIP, err = aghnet.IfaceHasStaticIP(ifaceName) if err != nil { if errors.Is(err, os.ErrPermission) { // ErrPermission may happen here on Linux systems where @@ -110,7 +109,7 @@ func (s *Server) enableDHCP(ifaceName string) (code int, err error) { log.Info("error while checking static ip: %s; "+ "assuming machine has static ip and going on", err) hasStaticIP = true - } else if errors.Is(err, sysutil.ErrNoStaticIPInfo) { + } else if errors.Is(err, aghnet.ErrNoStaticIPInfo) { // Couldn't obtain a definitive answer. Assume static // IP an go on. log.Info("can't check for static ip; " + @@ -124,7 +123,7 @@ func (s *Server) enableDHCP(ifaceName string) (code int, err error) { } if !hasStaticIP { - err = sysutil.IfaceSetStaticIP(ifaceName) + err = aghnet.IfaceSetStaticIP(ifaceName) if err != nil { err = fmt.Errorf("setting static ip: %w", err) @@ -267,7 +266,7 @@ type netInterfaceJSON struct { func (s *Server) handleDHCPInterfaces(w http.ResponseWriter, r *http.Request) { response := map[string]netInterfaceJSON{} - ifaces, err := util.GetValidNetInterfaces() + ifaces, err := aghnet.GetValidNetInterfaces() if err != nil { httpError(r, w, http.StatusInternalServerError, "Couldn't get interfaces: %s", err) return @@ -317,7 +316,7 @@ func (s *Server) handleDHCPInterfaces(w http.ResponseWriter, r *http.Request) { } } if len(jsonIface.Addrs4)+len(jsonIface.Addrs6) != 0 { - jsonIface.GatewayIP = sysutil.GatewayIP(iface.Name) + jsonIface.GatewayIP = aghnet.GatewayIP(iface.Name) response[iface.Name] = jsonIface } } @@ -397,13 +396,13 @@ func (s *Server) handleDHCPFindActiveServer(w http.ResponseWriter, r *http.Reque found4, err4 := CheckIfOtherDHCPServersPresentV4(interfaceName) - isStaticIP, err := sysutil.IfaceHasStaticIP(interfaceName) + isStaticIP, err := aghnet.IfaceHasStaticIP(interfaceName) if err != nil { result.V4.StaticIP.Static = "error" result.V4.StaticIP.Error = err.Error() } else if !isStaticIP { result.V4.StaticIP.Static = "no" - result.V4.StaticIP.IP = util.GetSubnet(interfaceName).String() + result.V4.StaticIP.IP = aghnet.GetSubnet(interfaceName).String() } if found4 { diff --git a/internal/home/controlinstall.go b/internal/home/controlinstall.go index 3577a000..6c80e1d9 100644 --- a/internal/home/controlinstall.go +++ b/internal/home/controlinstall.go @@ -15,18 +15,16 @@ import ( "strings" "time" - "github.com/AdguardTeam/AdGuardHome/internal/util" - - "github.com/AdguardTeam/AdGuardHome/internal/sysutil" + "github.com/AdguardTeam/AdGuardHome/internal/aghnet" "github.com/AdguardTeam/golibs/log" ) // getAddrsResponse is the response for /install/get_addresses endpoint. type getAddrsResponse struct { - WebPort int `json:"web_port"` - DNSPort int `json:"dns_port"` - Interfaces map[string]*util.NetInterface `json:"interfaces"` + WebPort int `json:"web_port"` + DNSPort int `json:"dns_port"` + Interfaces map[string]*aghnet.NetInterface `json:"interfaces"` } // handleInstallGetAddresses is the handler for /install/get_addresses endpoint. @@ -35,13 +33,13 @@ func (web *Web) handleInstallGetAddresses(w http.ResponseWriter, r *http.Request data.WebPort = 80 data.DNSPort = 53 - ifaces, err := util.GetValidNetInterfacesForWeb() + ifaces, err := aghnet.GetValidNetInterfacesForWeb() if err != nil { httpError(w, http.StatusInternalServerError, "Couldn't get interfaces: %s", err) return } - data.Interfaces = make(map[string]*util.NetInterface) + data.Interfaces = make(map[string]*aghnet.NetInterface) for _, iface := range ifaces { data.Interfaces[iface.Name] = iface } @@ -94,16 +92,16 @@ func (web *Web) handleInstallCheckConfig(w http.ResponseWriter, r *http.Request) } if reqData.Web.Port != 0 && reqData.Web.Port != config.BindPort && reqData.Web.Port != config.BetaBindPort { - err = util.CheckPortAvailable(reqData.Web.IP, reqData.Web.Port) + err = aghnet.CheckPortAvailable(reqData.Web.IP, reqData.Web.Port) if err != nil { respData.Web.Status = err.Error() } } if reqData.DNS.Port != 0 { - err = util.CheckPacketPortAvailable(reqData.DNS.IP, reqData.DNS.Port) + err = aghnet.CheckPacketPortAvailable(reqData.DNS.IP, reqData.DNS.Port) - if util.ErrorIsAddrInUse(err) { + if aghnet.ErrorIsAddrInUse(err) { canAutofix := checkDNSStubListener() if canAutofix && reqData.DNS.Autofix { @@ -112,7 +110,7 @@ func (web *Web) handleInstallCheckConfig(w http.ResponseWriter, r *http.Request) log.Error("Couldn't disable DNSStubListener: %s", err) } - err = util.CheckPacketPortAvailable(reqData.DNS.IP, reqData.DNS.Port) + err = aghnet.CheckPacketPortAvailable(reqData.DNS.IP, reqData.DNS.Port) canAutofix = false } @@ -120,7 +118,7 @@ func (web *Web) handleInstallCheckConfig(w http.ResponseWriter, r *http.Request) } if err == nil { - err = util.CheckPortAvailable(reqData.DNS.IP, reqData.DNS.Port) + err = aghnet.CheckPortAvailable(reqData.DNS.IP, reqData.DNS.Port) } if err != nil { @@ -144,7 +142,7 @@ func (web *Web) handleInstallCheckConfig(w http.ResponseWriter, r *http.Request) func handleStaticIP(ip net.IP, set bool) staticIPJSON { resp := staticIPJSON{} - interfaceName := util.GetInterfaceByIP(ip) + interfaceName := aghnet.GetInterfaceByIP(ip) resp.Static = "no" if len(interfaceName) == 0 { @@ -155,7 +153,7 @@ func handleStaticIP(ip net.IP, set bool) staticIPJSON { if set { // Try to set static IP for the specified interface - err := sysutil.IfaceSetStaticIP(interfaceName) + err := aghnet.IfaceSetStaticIP(interfaceName) if err != nil { resp.Static = "error" resp.Error = err.Error() @@ -165,7 +163,7 @@ func handleStaticIP(ip net.IP, set bool) staticIPJSON { // Fallthrough here even if we set static IP // Check if we have a static IP and return the details - isStaticIP, err := sysutil.IfaceHasStaticIP(interfaceName) + isStaticIP, err := aghnet.IfaceHasStaticIP(interfaceName) if err != nil { resp.Static = "error" resp.Error = err.Error() @@ -173,7 +171,7 @@ func handleStaticIP(ip net.IP, set bool) staticIPJSON { if isStaticIP { resp.Static = "yes" } - resp.IP = util.GetSubnet(interfaceName).String() + resp.IP = aghnet.GetSubnet(interfaceName).String() } return resp } @@ -315,7 +313,7 @@ func (web *Web) handleInstallConfigure(w http.ResponseWriter, r *http.Request) { // validate that hosts and ports are bindable if restartHTTP { - err = util.CheckPortAvailable(newSettings.Web.IP, newSettings.Web.Port) + err = aghnet.CheckPortAvailable(newSettings.Web.IP, newSettings.Web.Port) if err != nil { httpError(w, http.StatusBadRequest, "Impossible to listen on IP:port %s due to %s", net.JoinHostPort(newSettings.Web.IP.String(), strconv.Itoa(newSettings.Web.Port)), err) @@ -324,13 +322,13 @@ func (web *Web) handleInstallConfigure(w http.ResponseWriter, r *http.Request) { } - err = util.CheckPacketPortAvailable(newSettings.DNS.IP, newSettings.DNS.Port) + err = aghnet.CheckPacketPortAvailable(newSettings.DNS.IP, newSettings.DNS.Port) if err != nil { httpError(w, http.StatusBadRequest, "%s", err) return } - err = util.CheckPortAvailable(newSettings.DNS.IP, newSettings.DNS.Port) + err = aghnet.CheckPortAvailable(newSettings.DNS.IP, newSettings.DNS.Port) if err != nil { httpError(w, http.StatusBadRequest, "%s", err) return @@ -537,9 +535,9 @@ func (web *Web) handleInstallConfigureBeta(w http.ResponseWriter, r *http.Reques // TODO(e.burkov): This should removed with the API v1 when the appropriate // functionality will appear in default firstRunData. type getAddrsResponseBeta struct { - WebPort int `json:"web_port"` - DNSPort int `json:"dns_port"` - Interfaces []*util.NetInterface `json:"interfaces"` + WebPort int `json:"web_port"` + DNSPort int `json:"dns_port"` + Interfaces []*aghnet.NetInterface `json:"interfaces"` } // handleInstallConfigureBeta is a substitution of /install/get_addresses @@ -552,7 +550,7 @@ func (web *Web) handleInstallGetAddressesBeta(w http.ResponseWriter, r *http.Req data.WebPort = 80 data.DNSPort = 53 - ifaces, err := util.GetValidNetInterfacesForWeb() + ifaces, err := aghnet.GetValidNetInterfacesForWeb() if err != nil { httpError(w, http.StatusInternalServerError, "Couldn't get interfaces: %s", err) return diff --git a/internal/home/controlupdate.go b/internal/home/controlupdate.go index 8b3f1bf5..1aafa2f7 100644 --- a/internal/home/controlupdate.go +++ b/internal/home/controlupdate.go @@ -12,7 +12,7 @@ import ( "syscall" "time" - "github.com/AdguardTeam/AdGuardHome/internal/sysutil" + "github.com/AdguardTeam/AdGuardHome/internal/aghos" "github.com/AdguardTeam/AdGuardHome/internal/updater" "github.com/AdguardTeam/golibs/log" ) @@ -141,7 +141,7 @@ func (vr *versionResponse) confirmAutoUpdate() { tlsConf.PortDNSOverQUIC < 1024)) || config.BindPort < 1024 || config.DNS.Port < 1024) { - canUpdate, _ = sysutil.CanBindPrivilegedPorts() + canUpdate, _ = aghos.CanBindPrivilegedPorts() } vr.CanAutoUpdate = &canUpdate } diff --git a/internal/home/dns.go b/internal/home/dns.go index 889fe702..0020c77c 100644 --- a/internal/home/dns.go +++ b/internal/home/dns.go @@ -9,11 +9,11 @@ import ( "strconv" "github.com/AdguardTeam/AdGuardHome/internal/agherr" + "github.com/AdguardTeam/AdGuardHome/internal/aghnet" "github.com/AdguardTeam/AdGuardHome/internal/dnsfilter" "github.com/AdguardTeam/AdGuardHome/internal/dnsforward" "github.com/AdguardTeam/AdGuardHome/internal/querylog" "github.com/AdguardTeam/AdGuardHome/internal/stats" - "github.com/AdguardTeam/AdGuardHome/internal/util" "github.com/AdguardTeam/dnsproxy/proxy" "github.com/AdguardTeam/golibs/log" "github.com/ameshkov/dnscrypt/v2" @@ -109,7 +109,7 @@ func onDNSRequest(d *proxy.DNSContext) { if !ip.IsLoopback() { Context.rdns.Begin(ip) } - if !Context.ipDetector.detectSpecialNetwork(ip) { + if !Context.ipDetector.DetectSpecialNetwork(ip) { Context.whois.Begin(ip) } } @@ -253,7 +253,7 @@ func getDNSAddresses() []string { dnsAddresses := []string{} if config.DNS.BindHost.IsUnspecified() { - ifaces, e := util.GetValidNetInterfacesForWeb() + ifaces, e := aghnet.GetValidNetInterfacesForWeb() if e != nil { log.Error("Couldn't get network interfaces: %v", e) return []string{} @@ -344,7 +344,7 @@ func startDNSServer() error { if !ip.IsLoopback() { Context.rdns.Begin(ip) } - if !Context.ipDetector.detectSpecialNetwork(ip) { + if !Context.ipDetector.DetectSpecialNetwork(ip) { Context.whois.Begin(ip) } } diff --git a/internal/home/home.go b/internal/home/home.go index 21307c05..5c2b2d3f 100644 --- a/internal/home/home.go +++ b/internal/home/home.go @@ -22,12 +22,13 @@ import ( "time" "github.com/AdguardTeam/AdGuardHome/internal/agherr" + "github.com/AdguardTeam/AdGuardHome/internal/aghnet" + "github.com/AdguardTeam/AdGuardHome/internal/aghos" "github.com/AdguardTeam/AdGuardHome/internal/dhcpd" "github.com/AdguardTeam/AdGuardHome/internal/dnsfilter" "github.com/AdguardTeam/AdGuardHome/internal/dnsforward" "github.com/AdguardTeam/AdGuardHome/internal/querylog" "github.com/AdguardTeam/AdGuardHome/internal/stats" - "github.com/AdguardTeam/AdGuardHome/internal/sysutil" "github.com/AdguardTeam/AdGuardHome/internal/updater" "github.com/AdguardTeam/AdGuardHome/internal/util" "github.com/AdguardTeam/AdGuardHome/internal/version" @@ -60,7 +61,7 @@ type homeContext struct { autoHosts util.AutoHosts // IP-hostname pairs taken from system configuration (e.g. /etc/hosts) files updater *updater.Updater - ipDetector *ipDetector + ipDetector *aghnet.IPDetector // mux is our custom http.ServeMux. mux *http.ServeMux @@ -204,7 +205,7 @@ func setupConfig(args options) { if (runtime.GOOS == "linux" || runtime.GOOS == "darwin") && config.RlimitNoFile != 0 { - sysutil.SetRlimit(config.RlimitNoFile) + aghos.SetRlimit(config.RlimitNoFile) } // override bind host/port from the console @@ -304,7 +305,7 @@ func run(args options) { log.Fatalf("Can't initialize Web module") } - Context.ipDetector, err = newIPDetector() + Context.ipDetector, err = aghnet.NewIPDetector() if err != nil { log.Fatal(err) } @@ -361,7 +362,7 @@ func checkPermissions() { if runtime.GOOS == "windows" { // On Windows we need to have admin rights to run properly - admin, _ := sysutil.HaveAdminRights() + admin, _ := aghos.HaveAdminRights() if admin { return } @@ -370,7 +371,7 @@ func checkPermissions() { } // We should check if AdGuard Home is able to bind to port 53 - ok, err := util.CanBindPort(53) + ok, err := aghnet.CanBindPort(53) if ok { log.Info("AdGuard Home can bind to port 53") @@ -481,7 +482,7 @@ func configureLogger(args options) { if ls.LogFile == configSyslog { // Use syslog where it is possible and eventlog on Windows - err := sysutil.ConfigureSyslog(serviceName) + err := aghos.ConfigureSyslog(serviceName) if err != nil { log.Fatalf("cannot initialize syslog: %s", err) } @@ -592,7 +593,7 @@ func printHTTPAddresses(proto string) { } } else if config.BindHost.IsUnspecified() { log.Println("AdGuard Home is available on the following addresses:") - ifaces, err := util.GetValidNetInterfacesForWeb() + ifaces, err := aghnet.GetValidNetInterfacesForWeb() if err != nil { // That's weird, but we'll ignore it hostStr = config.BindHost.String() diff --git a/internal/home/service.go b/internal/home/service.go index caebb582..2ebd4f2f 100644 --- a/internal/home/service.go +++ b/internal/home/service.go @@ -9,7 +9,7 @@ import ( "strings" "syscall" - "github.com/AdguardTeam/AdGuardHome/internal/sysutil" + "github.com/AdguardTeam/AdGuardHome/internal/aghos" "github.com/AdguardTeam/AdGuardHome/internal/util" "github.com/AdguardTeam/golibs/log" "github.com/kardianos/service" @@ -121,7 +121,7 @@ func sendSigReload() { log.Error("Can't read PID file %s: %s", pidfile, err) return } - err = sysutil.SendProcessSignal(pid, syscall.SIGHUP) + err = aghos.SendProcessSignal(pid, syscall.SIGHUP) if err != nil { log.Error("Can't send signal to PID %d: %s", pid, err) return diff --git a/internal/home/web.go b/internal/home/web.go index 6b650576..73987dcb 100644 --- a/internal/home/web.go +++ b/internal/home/web.go @@ -9,7 +9,7 @@ import ( "sync" "time" - "github.com/AdguardTeam/AdGuardHome/internal/util" + "github.com/AdguardTeam/AdGuardHome/internal/aghnet" "github.com/AdguardTeam/golibs/log" "github.com/NYTimes/gziphandler" "github.com/gobuffalo/packr" @@ -117,7 +117,7 @@ func WebCheckPortAvailable(port int) bool { alreadyRunning = true } if !alreadyRunning { - err := util.CheckPortAvailable(config.BindHost, port) + err := aghnet.CheckPortAvailable(config.BindHost, port) if err != nil { return false } diff --git a/internal/sysutil/net.go b/internal/sysutil/net.go deleted file mode 100644 index 9ba41704..00000000 --- a/internal/sysutil/net.go +++ /dev/null @@ -1,46 +0,0 @@ -package sysutil - -import ( - "net" - "os/exec" - "strings" - - "github.com/AdguardTeam/AdGuardHome/internal/agherr" - "github.com/AdguardTeam/golibs/log" -) - -// ErrNoStaticIPInfo is returned by IfaceHasStaticIP when no information about -// the IP being static is available. -const ErrNoStaticIPInfo agherr.Error = "no information about static ip" - -// IfaceHasStaticIP checks if interface is configured to have static IP address. -// If it can't give a definitive answer, it returns false and an error for which -// errors.Is(err, ErrNoStaticIPInfo) is true. -func IfaceHasStaticIP(ifaceName string) (has bool, err error) { - return ifaceHasStaticIP(ifaceName) -} - -// IfaceSetStaticIP sets static IP address for network interface. -func IfaceSetStaticIP(ifaceName string) (err error) { - return ifaceSetStaticIP(ifaceName) -} - -// GatewayIP returns IP address of interface's gateway. -func GatewayIP(ifaceName string) net.IP { - cmd := exec.Command("ip", "route", "show", "dev", ifaceName) - log.Tracef("executing %s %v", cmd.Path, cmd.Args) - d, err := cmd.Output() - if err != nil || cmd.ProcessState.ExitCode() != 0 { - return nil - } - - fields := strings.Fields(string(d)) - // The meaningful "ip route" command output should contain the word - // "default" at first field and default gateway IP address at third - // field. - if len(fields) < 3 || fields[0] != "default" { - return nil - } - - return net.ParseIP(fields[2]) -} diff --git a/internal/util/net.go b/internal/util/net.go deleted file mode 100644 index e6d4d58e..00000000 --- a/internal/util/net.go +++ /dev/null @@ -1,21 +0,0 @@ -package util - -import ( - "fmt" - "net" -) - -// CanBindPort - checks if we can bind to this port or not -func CanBindPort(port int) (bool, error) { - addr, err := net.ResolveTCPAddr("tcp", fmt.Sprintf("127.0.0.1:%d", port)) - if err != nil { - return false, err - } - - l, err := net.ListenTCP("tcp", addr) - if err != nil { - return false, err - } - _ = l.Close() - return true, nil -}